mirror of
https://github.com/EQEmu/Server.git
synced 2026-09-04 06:16:38 +00:00
[Feature] Add RoF2 Guild features (#3699)
* [Feature] Add additional Guild Features This adds the following guild features and design pattern - the existing guild system was used - guild features are based on RoF2 within source with translaters used to converted between client differences - backward compatible with Ti and UF, and allows for mixed client servers - Guild Back for Ti and UF is based on RoF2 Permissions for banking if Guild Leader does not use Ti/UF - Guild Ranks and Permissions are enabled. - Guild Tributes are enabled. - Event logging via rules for donating tribute items and plat - Rules to limit Guild Tributes based on max level of server - Rewrote guild communications to client using specific opcodes -- Server no longer sends a guild member list on each zone -- Guild window is updated when a member levels, rank changes, zone changes, banker/alt status using individual opcodes -- When a member is removed or added to a guild, a single opcode is sent to each guild member -- This reduces network traffic considerably Known issues: - Visual bug only. Guild Tributes window will display a 0 for level if tribute is above max level rule setting. - Visual bug only. Guild Mgmt Window will not display an online member if the player has 'show offline' unchecked and a guild member zones within the Notes/Tribute tab. This is resolved by selecting and de-selecting the 'Show Offline' checkbox. * Updated RoF2 Guild Comms Updated RoF2 Guild Comms Update RoF2 Opcodes Rewrote RoF2 Guild Communications using specific opcodes. Added database changes - they are irreversible * Formatting * Update base_guild_members_repository.h * Format GuildInfo * Format GuildAction enum * Formatting in clientlist * quantity vs quantity * desc vs description * Format structs * Inline struct values * Formatting * Formatting * Formatting fixes * Formatting items * Formatting * Formatting * struct formatting updates * Updated formatting * Updated - std:string items - naming conventions - magic numbers * Repo refactors Other formatting updates * Remove test guild commands * Updated #guild info command * Add new repo methods for Neckolla ReplaceOne and ReplaceMany * Fix guild_tributes repo * Update database_update_manifest.cpp * Phase 1 of final testing with RoF2 -> RoF2. Next phase will be inter compatibility review * Remove #guild testing commands * Fix uf translator error Rewrite LoadGuilds * Use extended repository * FIx guild window on member add * LoadGuild Changes * Update guild_base.cpp * Few small fixes for display issue with UF * Update guild_base.cpp * Update guild_members_repository.h * Update zoneserver.cpp * Update guild.cpp * Update entity.h * Switch formatting * Formatting * Update worldserver.cpp * Switch formatting * Formatting switch statement * Update guild.cpp * Formatting in guild_base * We don't need to validate m_db everywhere * More formatting / spacing issues * Switch format * Update guild_base.cpp * Fix an UF issue displaying incorrect guildtag as <> * Updated several constants, fixed a few issues with Ti/UF and guild tributes not being removed or sent when a member is removed/disbands from a guild. * Formatting and logging updates * Fix for Loadguilds and permissions after repo updates. * Cleanup unnecessary m_db checks * Updated logging to use player_event_logs * Updated to use the single opcodes for guild traffic for Ti/UF/RoF2. Several enhancements for guild functionality for more reusable code and readability. * Update to fix Demote Self and guild invites declining when option set to not accept guild invites * Potential fix for guild notes/tribute display issues when client has 'Show Offline' unchecked. * Updates to fox recent master changes Updates to fix recent master changes * Updates in response to comments * Further Updates in response to comments * Comment updates and refactor for SendAppearance functions * Comment updates * Update client spawn process for show guild name Add show guild tag to default spawn process * Update to use zone spawn packets for RoF2 Removed several unused functions as a result Updated MemberRankUpdate to properly update guild_show on rank change. Updated OP_GuildURLAndChannel opcode for UF/RoF2 * Cleanup of world changes Created function for repetitive zonelist sendpackets to only booted zones Re-Inserted accidental delete of scanclosemobs * Fixes * Further world cleanup * Fix a few test guild bank cases for backward compat Removed a duplicate db call Fixed a fallthrough issue * Update guild_mgr.cpp * Cleanup --------- Co-authored-by: Akkadius <akkadius1@gmail.com>
This commit is contained in:
@@ -193,6 +193,17 @@ void Mob::CalcItemBonuses(StatBonuses* b) {
|
||||
}
|
||||
}
|
||||
|
||||
if (IsOfClientBot()) {
|
||||
for (i = EQ::invslot::GUILD_TRIBUTE_BEGIN; i <= EQ::invslot::GUILD_TRIBUTE_END; i++) {
|
||||
const auto* inst = GetInv().GetItem(i);
|
||||
if (!inst) {
|
||||
continue;
|
||||
}
|
||||
|
||||
AddItemBonuses(inst, b, false, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
RuleI(Spells, AdditiveBonusWornType) &&
|
||||
RuleI(Spells, AdditiveBonusWornType) != EQ::item::ItemEffectWorn
|
||||
|
||||
+17
-8
@@ -209,6 +209,7 @@ Client::Client(EQStreamInterface *ieqs) : Mob(
|
||||
lsaccountid = 0;
|
||||
guild_id = GUILD_NONE;
|
||||
guildrank = 0;
|
||||
guild_tribute_opt_in = 0;
|
||||
GuildBanker = false;
|
||||
memset(lskey, 0, sizeof(lskey));
|
||||
strcpy(account_name, "");
|
||||
@@ -378,6 +379,7 @@ Client::Client(EQStreamInterface *ieqs) : Mob(
|
||||
SetBotPrecombat(false);
|
||||
|
||||
AI_Init();
|
||||
|
||||
}
|
||||
|
||||
Client::~Client() {
|
||||
@@ -535,7 +537,8 @@ void Client::SendZoneInPackets()
|
||||
safe_delete(outapp);
|
||||
|
||||
if (IsInAGuild()) {
|
||||
SendGuildMembers();
|
||||
guild_mgr.UpdateDbMemberOnline(CharacterID(), true);
|
||||
//SendGuildMembers();
|
||||
SendGuildURL();
|
||||
SendGuildChannel();
|
||||
SendGuildLFGuildStatus();
|
||||
@@ -744,7 +747,7 @@ bool Client::Save(uint8 iCommitNow) {
|
||||
SetNextInvSnapshot(RuleI(Character, InvSnapshotMinRetryM));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
database.SaveCharacterData(this, &m_pp, &m_epp); /* Save Character Data */
|
||||
|
||||
database.SaveCharacterEXPModifier(this);
|
||||
@@ -951,12 +954,13 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s
|
||||
switch(chan_num)
|
||||
{
|
||||
case ChatChannel_Guild: { /* Guild Chat */
|
||||
if (!IsInAGuild())
|
||||
if (!IsInAGuild()) {
|
||||
MessageString(Chat::DefaultText, GUILD_NOT_MEMBER2); //You are not a member of any guild.
|
||||
else if (!guild_mgr.CheckPermission(GuildID(), GuildRank(), GUILD_SPEAK))
|
||||
Message(0, "Error: You dont have permission to speak to the guild.");
|
||||
else if (!worldserver.SendChannelMessage(this, targetname, chan_num, GuildID(), language, lang_skill, message))
|
||||
Message(0, "Error: World server disconnected");
|
||||
} else if (!guild_mgr.CheckPermission(GuildID(), GuildRank(), GUILD_ACTION_GUILD_CHAT_SPEAK_IN)) {
|
||||
MessageString(Chat::EchoGuild, NO_PROPER_ACCESS);
|
||||
} else if (!worldserver.SendChannelMessage(this, targetname, chan_num, GuildID(), language, lang_skill, message)) {
|
||||
Message(Chat::White, "Error: World server disconnected");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ChatChannel_Group: { /* Group Chat */
|
||||
@@ -1776,6 +1780,8 @@ void Client::UpdateWho(uint8 remove)
|
||||
s->ClientVersion = static_cast<unsigned int>(ClientVersion());
|
||||
s->tellsoff = tellsoff;
|
||||
s->guild_id = guild_id;
|
||||
s->guild_rank = guildrank;
|
||||
s->guild_tribute_opt_in = guild_tribute_opt_in;
|
||||
s->LFG = LFG;
|
||||
if (LFG) {
|
||||
s->LFGFromLevel = LFGFromLevel;
|
||||
@@ -2160,7 +2166,8 @@ void Client::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho)
|
||||
if (!IsInAGuild()) {
|
||||
ns->spawn.guildrank = 0xFF;
|
||||
} else {
|
||||
ns->spawn.guildrank = guild_mgr.GetDisplayedRank(GuildID(), GuildRank(), AccountID());
|
||||
ns->spawn.guildrank = guild_mgr.GetDisplayedRank(GuildID(), GuildRank(), CharacterID());
|
||||
ns->spawn.guild_show = guild_mgr.CheckPermission(GuildID(), GuildRank(), GUILD_ACTION_DISPLAY_GUILD_NAME);
|
||||
}
|
||||
ns->spawn.size = 0; // Changing size works, but then movement stops! (wth?)
|
||||
ns->spawn.runspeed = (gmspeed == 0) ? runspeed : 3.125f;
|
||||
@@ -10178,6 +10185,7 @@ int Client::CountItem(uint32 item_id)
|
||||
{ EQ::invbag::GENERAL_BAGS_BEGIN, EQ::invbag::GENERAL_BAGS_END },
|
||||
{ EQ::invbag::CURSOR_BAG_BEGIN, EQ::invbag::CURSOR_BAG_END},
|
||||
{ EQ::invslot::BANK_BEGIN, EQ::invslot::BANK_END },
|
||||
{ EQ::invslot::GUILD_TRIBUTE_BEGIN, EQ::invslot::GUILD_TRIBUTE_END },
|
||||
{ EQ::invbag::BANK_BAGS_BEGIN, EQ::invbag::BANK_BAGS_END },
|
||||
{ EQ::invslot::SHARED_BANK_BEGIN, EQ::invslot::SHARED_BANK_END },
|
||||
{ EQ::invbag::SHARED_BANK_BAGS_BEGIN, EQ::invbag::SHARED_BANK_BAGS_END },
|
||||
@@ -10330,6 +10338,7 @@ void Client::RemoveItem(uint32 item_id, uint32 quantity)
|
||||
{ EQ::invbag::GENERAL_BAGS_BEGIN, EQ::invbag::GENERAL_BAGS_END },
|
||||
{ EQ::invbag::CURSOR_BAG_BEGIN, EQ::invbag::CURSOR_BAG_END},
|
||||
{ EQ::invslot::BANK_BEGIN, EQ::invslot::BANK_END },
|
||||
{ EQ::invslot::GUILD_TRIBUTE_BEGIN, EQ::invslot::GUILD_TRIBUTE_END },
|
||||
{ EQ::invbag::BANK_BAGS_BEGIN, EQ::invbag::BANK_BAGS_END },
|
||||
{ EQ::invslot::SHARED_BANK_BEGIN, EQ::invslot::SHARED_BANK_END },
|
||||
{ EQ::invbag::SHARED_BANK_BAGS_BEGIN, EQ::invbag::SHARED_BANK_BAGS_END },
|
||||
|
||||
+30
-1
@@ -718,8 +718,16 @@ public:
|
||||
|
||||
inline bool IsInAGuild() const { return(guild_id != GUILD_NONE && guild_id != 0); }
|
||||
inline bool IsInGuild(uint32 in_gid) const { return(in_gid == guild_id && IsInAGuild()); }
|
||||
inline bool GetGuildListDirty() { return guild_dirty; }
|
||||
inline void SetGuildListDirty(bool state) { guild_dirty = state; }
|
||||
inline uint32 GuildID() const { return guild_id; }
|
||||
inline uint8 GuildRank() const { return guildrank; }
|
||||
inline bool GuildTributeOptIn() const { return guild_tribute_opt_in; }
|
||||
void SetGuildTributeOptIn(bool state);
|
||||
void SendGuildTributeDonateItemReply(GuildTributeDonateItemRequest_Struct* in, uint32 favor);
|
||||
void SendGuildTributeDonatePlatReply(GuildTributeDonatePlatRequest_Struct* in, uint32 favor);
|
||||
void SetGuildRank(uint32 rank);
|
||||
void SetGuildID(uint32 guild_id);
|
||||
void SendGuildMOTD(bool GetGuildMOTDReply = false);
|
||||
void SendGuildURL();
|
||||
void SendGuildChannel();
|
||||
@@ -729,6 +737,24 @@ public:
|
||||
void SendGuildList();
|
||||
void SendGuildJoin(GuildJoin_Struct* gj);
|
||||
void RefreshGuildInfo();
|
||||
void SendGuildRankNames();
|
||||
void SendGuildTributeDetails(uint32 tribute_id, uint32 tier);
|
||||
void DoGuildTributeUpdate();
|
||||
void SendGuildActiveTributes(uint32 guild_id);
|
||||
void SendGuildFavorAndTimer(uint32 guild_id);
|
||||
void SendGuildTributeOptInToggle(const GuildTributeMemberToggle* in);
|
||||
void RequestGuildActiveTributes(uint32 guild_id);
|
||||
void RequestGuildFavorAndTimer(uint32 guild_id);
|
||||
void SendGuildMembersList();
|
||||
void SendGuildMemberAdd(uint32 guild_id, uint32 level, uint32 _class, uint32 rank, uint32 guild_show, uint32 zone_id, std::string player_name);
|
||||
void SendGuildMemberRename(uint32 guild_id, std::string player_name, std::string new_player_name);
|
||||
void SendGuildMemberDelete(uint32 guild_id, std::string player_name);
|
||||
void SendGuildMemberLevel(uint32 guild_id, uint32 level, std::string player_name);
|
||||
void SendGuildMemberRankAltBanker(uint32 guild_id, uint32 rank, std::string player_name, bool alt, bool banker);
|
||||
void SendGuildMemberPublicNote(uint32 guild_id, std::string player_name, std::string public_note);
|
||||
void SendGuildMemberDetails(uint32 guild_id, uint32 zone_id, uint32 offline_mode, std::string player_name);
|
||||
void SendGuildRenameGuild(uint32 guild_id, std::string new_guild_name);
|
||||
void SendGuildDeletePacket(uint32 guild_id);
|
||||
|
||||
uint8 GetClientMaxLevel() const { return client_max_level; }
|
||||
void SetClientMaxLevel(uint8 max_level) { client_max_level = max_level; }
|
||||
@@ -1481,6 +1507,7 @@ public:
|
||||
void GuildBankAck();
|
||||
void GuildBankDepositAck(bool Fail, int8 action);
|
||||
inline bool IsGuildBanker() { return GuildBanker; }
|
||||
inline void SetGuildBanker(bool banker) { GuildBanker = banker; }
|
||||
void ClearGuildBank();
|
||||
void SendGroupCreatePacket();
|
||||
void SendGroupLeaderChangePacket(const char *LeaderName);
|
||||
@@ -1782,7 +1809,9 @@ private:
|
||||
char lskey[30];
|
||||
int16 admin;
|
||||
uint32 guild_id;
|
||||
uint8 guildrank; // player's rank in the guild, 0-GUILD_MAX_RANK
|
||||
uint8 guildrank; // player's rank in the guild, 1- Leader 8 Recruit
|
||||
bool guild_tribute_opt_in;
|
||||
bool guild_dirty{ true }; //used to control add/delete opcodes due to client bug in Ti thru RoF2
|
||||
bool GuildBanker;
|
||||
uint16 duel_target;
|
||||
bool duelaccepted;
|
||||
|
||||
+879
-432
File diff suppressed because it is too large
Load Diff
@@ -166,7 +166,14 @@
|
||||
void Handle_OP_GuildPublicNote(const EQApplicationPacket *app);
|
||||
void Handle_OP_GuildRemove(const EQApplicationPacket *app);
|
||||
void Handle_OP_GuildStatus(const EQApplicationPacket *app);
|
||||
void Handle_OP_GuildUpdateURLAndChannel(const EQApplicationPacket *app);
|
||||
void Handle_OP_GuildTributeModifyBenefits(const EQApplicationPacket* app);
|
||||
void Handle_OP_GuildTributeOptInOut(const EQApplicationPacket* app);
|
||||
void Handle_OP_GuildTributeSaveActiveTributes(const EQApplicationPacket* app);
|
||||
void Handle_OP_GuildTributeSelect(const EQApplicationPacket* app);
|
||||
void Handle_OP_GuildTributeToggle(const EQApplicationPacket* app);
|
||||
void Handle_OP_GuildUpdate(const EQApplicationPacket *app);
|
||||
void Handle_OP_GuildTributeDonateItem(const EQApplicationPacket* app);
|
||||
void Handle_OP_GuildTributeDonatePlat(const EQApplicationPacket* app);
|
||||
void Handle_OP_GuildWar(const EQApplicationPacket *app);
|
||||
void Handle_OP_Heartbeat(const EQApplicationPacket *app);
|
||||
void Handle_OP_Hide(const EQApplicationPacket *app);
|
||||
|
||||
@@ -177,6 +177,10 @@ bool Client::Process() {
|
||||
if (myraid) {
|
||||
myraid->MemberZoned(this);
|
||||
}
|
||||
if (IsInAGuild()) {
|
||||
guild_mgr.UpdateDbMemberOnline(CharacterID(), false);
|
||||
guild_mgr.SendToWorldSendGuildMembersList(GuildID());
|
||||
}
|
||||
|
||||
SetDynamicZoneMemberStatus(DynamicZoneMemberStatus::Offline);
|
||||
|
||||
@@ -196,6 +200,11 @@ bool Client::Process() {
|
||||
}
|
||||
LeaveGroup();
|
||||
Save();
|
||||
if (IsInAGuild()) {
|
||||
guild_mgr.UpdateDbMemberOnline(CharacterID(), false);
|
||||
guild_mgr.SendToWorldSendGuildMembersList(GuildID());
|
||||
}
|
||||
|
||||
if (GetMerc())
|
||||
{
|
||||
GetMerc()->Save();
|
||||
@@ -561,6 +570,10 @@ bool Client::Process() {
|
||||
GetMerc()->Save();
|
||||
GetMerc()->Depop();
|
||||
}
|
||||
if (IsInAGuild()) {
|
||||
guild_mgr.UpdateDbMemberOnline(CharacterID(), false);
|
||||
guild_mgr.SendToWorldSendGuildMembersList(GuildID());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else if (!linkdead_timer.Enabled()) {
|
||||
|
||||
+6
-5
@@ -2307,8 +2307,10 @@ void EntityList::ChannelMessageFromWorld(const char *from, const char *to,
|
||||
if (chan_num == ChatChannel_Guild) {
|
||||
if (!client->IsInGuild(guild_id))
|
||||
continue;
|
||||
if (!guild_mgr.CheckPermission(guild_id, client->GuildRank(), GUILD_HEAR))
|
||||
continue;
|
||||
if (client->ClientVersion() >= EQ::versions::ClientVersion::RoF) {
|
||||
if (!guild_mgr.CheckPermission(guild_id, client->GuildRank(), GUILD_ACTION_GUILD_CHAT_SEE))
|
||||
continue;
|
||||
}
|
||||
if (client->GetFilter(FilterGuildChat) == FilterHide)
|
||||
continue;
|
||||
} else if (chan_num == ChatChannel_OOC) {
|
||||
@@ -2337,14 +2339,13 @@ void EntityList::Message(uint32 to_guilddbid, uint32 type, const char *message,
|
||||
}
|
||||
}
|
||||
|
||||
void EntityList::QueueClientsGuild(Mob *sender, const EQApplicationPacket *app,
|
||||
bool ignore_sender, uint32 guild_id)
|
||||
void EntityList::QueueClientsGuild(const EQApplicationPacket *app, uint32 guild_id)
|
||||
{
|
||||
auto it = client_list.begin();
|
||||
while (it != client_list.end()) {
|
||||
Client *client = it->second;
|
||||
if (client->IsInGuild(guild_id))
|
||||
client->QueuePacket(app);
|
||||
client->QueuePacket(app, true);
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
+18
-4
@@ -240,11 +240,24 @@ public:
|
||||
bool IsMobInZone(Mob *who);
|
||||
void ClearClientPetitionQueue();
|
||||
bool CanAddHateForMob(Mob *p);
|
||||
void SendGuildMOTD(uint32 guild_id);
|
||||
void SendGuildSpawnAppearance(uint32 guild_id);
|
||||
void SendGuildMembers(uint32 guild_id);
|
||||
void SendGuildMOTD(uint32 guild_id);
|
||||
void SendGuildChannel(uint32 guild_id);
|
||||
void SendGuildURL(uint32 guild_id);
|
||||
void SendGuildSpawnAppearance(uint32 guild_id);
|
||||
void SendGuildMembers(uint32 guild_id);
|
||||
void SendGuildMembersList(uint32 guild_id);
|
||||
void SendGuildMemberAdd(uint32 guild_id, uint32 level, uint32 _class, uint32 rank, uint32 spirit, uint32 zone_id, std::string player_name);
|
||||
void SendGuildMemberRename(uint32 guild_id, std::string player_name, std::string new_player_name);
|
||||
void SendGuildMemberRemove(uint32 guild_id, std::string player_name);
|
||||
void SendGuildMemberLevel(uint32 guild_id, uint32 level, std::string player_name);
|
||||
void SendGuildMemberRankAltBanker(uint32 guild_id, uint32 rank, std::string player_name, bool alt, bool banker);
|
||||
void SendGuildMemberPublicNote(uint32 guild_id, std::string player_name, std::string public_note);
|
||||
void SendGuildMemberDetails(uint32 guild_id, uint32 zone_id, uint32 offline_mode, std::string player_name);
|
||||
void SendGuildRenameGuild(uint32 guild_id, std::string new_guild_name);
|
||||
|
||||
void RefreshAllGuildInfo(uint32 guild_id);
|
||||
void SendGuildList();
|
||||
void GuildSetPreRoFBankerFlag(uint32 guild_id, uint32 guild_rank, bool banker_status);
|
||||
void CheckGroupList (const char *fname, const int fline);
|
||||
void GroupProcess();
|
||||
void RaidProcess();
|
||||
@@ -402,6 +415,7 @@ public:
|
||||
void QuestJournalledSayClose(Mob *sender, float dist, const char* mobname, const char* message, Journal::Options &opts);
|
||||
void GroupMessage(uint32 gid, const char *from, const char *message);
|
||||
void ExpeditionWarning(uint32 minutes_left);
|
||||
void UpdateGuildTributes(uint32 guild_id);
|
||||
|
||||
void RemoveFromTargets(Mob* mob, bool RemoveFromXTargets = false);
|
||||
void RemoveFromTargetsFadingMemories(Mob* spell_target, bool RemoveFromXTargets = false, uint32 max_level = 0);
|
||||
@@ -411,7 +425,7 @@ public:
|
||||
void QueueCloseClients(Mob* sender, const EQApplicationPacket* app, bool ignore_sender=false, float distance=200, Mob* skipped_mob = 0, bool is_ack_required = true, eqFilterType filter=FilterNone);
|
||||
void QueueClients(Mob* sender, const EQApplicationPacket* app, bool ignore_sender=false, bool ackreq = true);
|
||||
void QueueClientsStatus(Mob* sender, const EQApplicationPacket* app, bool ignore_sender = false, uint8 minstatus = AccountStatus::Player, uint8 maxstatus = AccountStatus::Player);
|
||||
void QueueClientsGuild(Mob* sender, const EQApplicationPacket* app, bool ignore_sender = false, uint32 guildeqid = 0);
|
||||
void QueueClientsGuild(const EQApplicationPacket* app, uint32 guildeqid = 0);
|
||||
void QueueClientsGuildBankItemUpdate(const GuildBankItemUpdate_Struct *gbius, uint32 GuildID);
|
||||
void QueueClientsByTarget(Mob* sender, const EQApplicationPacket* app, bool iSendToSender = true, Mob* SkipThisMob = 0, bool ackreq = true, bool HoTT = true, uint32 ClientVersionBits = 0xFFFFFFFF, bool inspect_buffs = false, bool clear_target_window = false);
|
||||
|
||||
|
||||
@@ -969,6 +969,11 @@ void Client::SetLevel(uint8 set_level, bool command)
|
||||
SetPVP(true);
|
||||
}
|
||||
|
||||
if (IsInAGuild()) {
|
||||
guild_mgr.SendToWorldMemberLevelUpdate(GuildID(), GetLevel(), std::string(GetCleanName()));
|
||||
DoGuildTributeUpdate();
|
||||
}
|
||||
|
||||
DoTributeUpdate();
|
||||
SendHPUpdate();
|
||||
SetMana(CalcMaxMana());
|
||||
|
||||
+167
-39
@@ -6,7 +6,7 @@ extern WorldServer worldserver;
|
||||
#include "../guild_mgr.h"
|
||||
#include "../doors.h"
|
||||
|
||||
void command_guild(Client *c, const Seperator *sep)
|
||||
void command_guild(Client* c, const Seperator* sep)
|
||||
{
|
||||
const auto arguments = sep->argnum;
|
||||
if (!arguments) {
|
||||
@@ -30,6 +30,8 @@ void command_guild(Client *c, const Seperator *sep)
|
||||
bool is_set_leader = !strcasecmp(sep->arg[1], "setleader");
|
||||
bool is_set_rank = !strcasecmp(sep->arg[1], "setrank");
|
||||
bool is_status = !strcasecmp(sep->arg[1], "status");
|
||||
bool is_details = !strcasecmp(sep->arg[1], "details");
|
||||
bool is_test = !strcasecmp(sep->arg[1], "test");
|
||||
if (
|
||||
!is_create &&
|
||||
!is_delete &&
|
||||
@@ -41,8 +43,10 @@ void command_guild(Client *c, const Seperator *sep)
|
||||
!is_set &&
|
||||
!is_set_leader &&
|
||||
!is_set_rank &&
|
||||
!is_status
|
||||
) {
|
||||
!is_status &&
|
||||
!is_details &&
|
||||
!is_test
|
||||
) {
|
||||
SendGuildSubCommands(c);
|
||||
return;
|
||||
}
|
||||
@@ -50,12 +54,13 @@ void command_guild(Client *c, const Seperator *sep)
|
||||
if (is_create) {
|
||||
if (arguments < 3) {
|
||||
c->Message(Chat::White, "Usage: #guild create [Character ID|Character Name] [Guild Name]");
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
auto leader_id = (
|
||||
sep->IsNumber(2) ?
|
||||
Strings::ToUnsignedInt(sep->arg[2]) :
|
||||
database.GetCharacterID(sep->arg[2])
|
||||
);
|
||||
);
|
||||
auto leader_name = database.GetCharNameByID(leader_id);
|
||||
if (!leader_id || leader_name.empty()) {
|
||||
c->Message(
|
||||
@@ -80,7 +85,8 @@ void command_guild(Client *c, const Seperator *sep)
|
||||
guild_id
|
||||
).c_str()
|
||||
);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
auto guild_name = sep->argplus[3];
|
||||
auto guild_id = guild_mgr.CreateGuild(sep->argplus[3], leader_id);
|
||||
|
||||
@@ -94,7 +100,8 @@ void command_guild(Client *c, const Seperator *sep)
|
||||
|
||||
if (guild_id == GUILD_NONE) {
|
||||
c->Message(Chat::White, "Guild creation failed.");
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
@@ -123,10 +130,12 @@ void command_guild(Client *c, const Seperator *sep)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (is_delete) {
|
||||
}
|
||||
else if (is_delete) {
|
||||
if (!sep->IsNumber(2)) {
|
||||
c->Message(Chat::White, "Usage: #guild delete [Guild ID]");
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
auto guild_id = Strings::ToUnsignedInt(sep->arg[2]);
|
||||
if (!guild_mgr.GuildExists(guild_id)) {
|
||||
c->Message(
|
||||
@@ -156,12 +165,15 @@ void command_guild(Client *c, const Seperator *sep)
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
} else if (is_help) {
|
||||
}
|
||||
else if (is_help) {
|
||||
SendGuildSubCommands(c);
|
||||
} else if (is_info) {
|
||||
}
|
||||
else if (is_info) {
|
||||
if (arguments != 2 && c->IsInAGuild()) {
|
||||
c->Message(Chat::White, "#guild info [Guild ID]");
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
auto guild_id = GUILD_NONE;
|
||||
if (sep->IsNumber(2)) {
|
||||
guild_id = Strings::ToUnsignedInt(sep->arg[2]);
|
||||
@@ -171,12 +183,15 @@ void command_guild(Client *c, const Seperator *sep)
|
||||
guild_mgr.DescribeGuild(c, guild_id);
|
||||
}
|
||||
}
|
||||
} else if (is_list) {
|
||||
}
|
||||
else if (is_list) {
|
||||
guild_mgr.ListGuilds(c, std::string());
|
||||
} else if (is_rename) {
|
||||
}
|
||||
else if (is_rename) {
|
||||
if (!sep->IsNumber(2)) {
|
||||
c->Message(Chat::White, "Usage: #guild rename [Guild ID] [New Guild Name]");
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
auto guild_id = Strings::ToUnsignedInt(sep->arg[2]);
|
||||
if (!guild_mgr.GuildExists(guild_id)) {
|
||||
c->Message(
|
||||
@@ -208,28 +223,33 @@ void command_guild(Client *c, const Seperator *sep)
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
} else if (is_search) {
|
||||
}
|
||||
else if (is_search) {
|
||||
if (Strings::IsNumber(sep->arg[2])) {
|
||||
const auto guild_id = Strings::ToUnsignedInt(sep->arg[2]);
|
||||
|
||||
guild_mgr.ListGuilds(c, guild_id);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
const std::string search_criteria = sep->argplus[2];
|
||||
|
||||
guild_mgr.ListGuilds(c, search_criteria);
|
||||
}
|
||||
} else if (is_set) {
|
||||
}
|
||||
else if (is_set) {
|
||||
if (
|
||||
arguments != 3 ||
|
||||
!sep->IsNumber(3)
|
||||
) {
|
||||
) {
|
||||
c->Message(Chat::White, "#guild set [Character ID|Character Name] [Guild ID] (Guild ID 0 is Guildless)");
|
||||
return;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
auto guild_id = Strings::ToUnsignedInt(sep->arg[3]);
|
||||
if (!guild_id) {
|
||||
guild_id = GUILD_NONE;
|
||||
} else if (!guild_mgr.GuildExists(guild_id)) {
|
||||
}
|
||||
else if (!guild_mgr.GuildExists(guild_id)) {
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
@@ -244,7 +264,7 @@ void command_guild(Client *c, const Seperator *sep)
|
||||
sep->IsNumber(2) ?
|
||||
Strings::ToUnsignedInt(sep->arg[2]) :
|
||||
database.GetCharacterID(sep->arg[2])
|
||||
);
|
||||
);
|
||||
auto character_name = database.GetCharNameByID(character_id);
|
||||
if (!character_id || character_name.empty()) {
|
||||
c->Message(
|
||||
@@ -264,7 +284,8 @@ void command_guild(Client *c, const Seperator *sep)
|
||||
character_name,
|
||||
character_id
|
||||
);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
LogGuilds(
|
||||
"[{}]: Putting [{}] ([{}]) into guild [{}] ([{}]) with GM command",
|
||||
c->GetName(),
|
||||
@@ -287,7 +308,8 @@ void command_guild(Client *c, const Seperator *sep)
|
||||
guild_id
|
||||
).c_str()
|
||||
);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
guild_mgr.SetGuild(character_id, GUILD_NONE, 0);
|
||||
c->Message(
|
||||
Chat::White,
|
||||
@@ -299,18 +321,20 @@ void command_guild(Client *c, const Seperator *sep)
|
||||
);
|
||||
}
|
||||
}
|
||||
} else if (is_set_leader) {
|
||||
}
|
||||
else if (is_set_leader) {
|
||||
if (
|
||||
arguments != 3 ||
|
||||
!sep->IsNumber(2)
|
||||
) {
|
||||
) {
|
||||
c->Message(Chat::White, "Usage: #guild setleader [Guild ID] [Character ID|Character Name]");
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
auto leader_id = (
|
||||
sep->IsNumber(2) ?
|
||||
Strings::ToUnsignedInt(sep->arg[2]) :
|
||||
database.GetCharacterID(sep->arg[2])
|
||||
);
|
||||
);
|
||||
auto leader_name = database.GetCharNameByID(leader_id);
|
||||
if (!leader_id || leader_name.empty()) {
|
||||
c->Message(
|
||||
@@ -368,11 +392,13 @@ void command_guild(Client *c, const Seperator *sep)
|
||||
);
|
||||
}
|
||||
}
|
||||
} else if (is_set_rank) {
|
||||
}
|
||||
else if (is_set_rank) {
|
||||
auto rank = static_cast<uint8>(Strings::ToUnsignedInt(sep->arg[3]));
|
||||
if (!sep->IsNumber(3)) {
|
||||
c->Message(Chat::White, "#guild setrank [Character ID|Character Name] [Rank]");
|
||||
} else if (rank < 0 || rank > GUILD_MAX_RANK) {
|
||||
}
|
||||
else if (rank < 0 || rank > GUILD_MAX_RANK) {
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
@@ -380,12 +406,13 @@ void command_guild(Client *c, const Seperator *sep)
|
||||
GUILD_MAX_RANK
|
||||
).c_str()
|
||||
);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
auto character_id = (
|
||||
sep->IsNumber(2) ?
|
||||
Strings::ToUnsignedInt(sep->arg[2]) :
|
||||
database.GetCharacterID(sep->arg[2])
|
||||
);
|
||||
);
|
||||
auto character_name = database.GetCharNameByID(character_id);
|
||||
if (!character_id || character_name.empty()) {
|
||||
c->Message(
|
||||
@@ -430,7 +457,8 @@ void command_guild(Client *c, const Seperator *sep)
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
} else if (is_status) {
|
||||
}
|
||||
else if (is_status) {
|
||||
auto client = (
|
||||
t ?
|
||||
t :
|
||||
@@ -438,11 +466,12 @@ void command_guild(Client *c, const Seperator *sep)
|
||||
arguments == 2 ?
|
||||
entity_list.GetClientByName(sep->arg[2]) :
|
||||
c
|
||||
)
|
||||
);
|
||||
)
|
||||
);
|
||||
if (!client) {
|
||||
c->Message(Chat::White, "You must target someone or specify a character name.");
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if (!client->IsInAGuild()) {
|
||||
c->Message(
|
||||
Chat::White,
|
||||
@@ -452,7 +481,8 @@ void command_guild(Client *c, const Seperator *sep)
|
||||
c == t ? "are" : "is"
|
||||
).c_str()
|
||||
);
|
||||
} else if (guild_mgr.IsGuildLeader(client->GuildID(), client->CharacterID())) {
|
||||
}
|
||||
else if (guild_mgr.IsGuildLeader(client->GuildID(), client->CharacterID())) {
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
@@ -462,7 +492,8 @@ void command_guild(Client *c, const Seperator *sep)
|
||||
guild_mgr.GetGuildNameByID(client->GuildID())
|
||||
).c_str()
|
||||
);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
@@ -476,12 +507,109 @@ void command_guild(Client *c, const Seperator *sep)
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (is_details) {
|
||||
if (!sep->IsNumber(2)) {
|
||||
c->Message(Chat::White, "Usage: #guild details [Guild ID]");
|
||||
}
|
||||
else {
|
||||
auto guild_id = Strings::ToUnsignedInt(sep->arg[2]);
|
||||
if (!guild_mgr.GuildExists(guild_id)) {
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Guild ID {} could not be found.",
|
||||
guild_id
|
||||
).c_str()
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
auto guild = guild_mgr.GetGuildByGuildID(guild_id);
|
||||
if (!guild) {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Guild {} not found. #guild list can be used to get guild ids.",
|
||||
guild_id
|
||||
).c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
if (guild) {
|
||||
c->Message(Chat::Yellow, fmt::format("Guild ID: {}.", sep->arg[2]).c_str());
|
||||
c->Message(Chat::Yellow, fmt::format("Guild Name: {}.", guild->name.c_str()).c_str());
|
||||
c->Message(Chat::Yellow, fmt::format("Guild Leader ID: {}.", guild->leader).c_str());
|
||||
c->Message(Chat::Yellow, fmt::format("Guild MinStatus: {}.", guild->minstatus).c_str());
|
||||
c->Message(Chat::Yellow, fmt::format("Guild MOTD: {}.", guild->motd.c_str()).c_str());
|
||||
c->Message(Chat::Yellow, fmt::format("Guild MOTD Setter:{}.", guild->motd_setter.c_str()).c_str());
|
||||
c->Message(Chat::Yellow, fmt::format("Guild Channel: {}.", guild->channel.c_str()).c_str());
|
||||
c->Message(Chat::Yellow, fmt::format("Guild URL: {}.", guild->url.c_str()).c_str());
|
||||
|
||||
for (int i = 1; i <= GUILD_MAX_RANK; i++) {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format("Guild Rank: {} - {}.", i, guild->rank_names[i].c_str()).c_str());
|
||||
}
|
||||
|
||||
c->Message(Chat::Yellow, "Guild Functions: {db_id} - {guild_id} - {perm_id} - {perm_value}.");
|
||||
for (int i = 1; i <= GUILD_MAX_FUNCTIONS; i++) {
|
||||
c->Message(
|
||||
Chat::Yellow, fmt::format(
|
||||
"Guild Function: {} - {} - {} - {}.",
|
||||
guild->functions[i].id,
|
||||
guild->functions[i].guild_id,
|
||||
guild->functions[i].perm_id,
|
||||
guild->functions[i].perm_value
|
||||
).c_str());
|
||||
}
|
||||
c->Message(Chat::Yellow, fmt::format("Guild Tribute: Favor {}", guild->tribute.favor).c_str());
|
||||
c->Message(
|
||||
Chat::Yellow, fmt::format(
|
||||
"Guild Tribute: Tribute 1 {}/{} - Tribute 2 {}/{}",
|
||||
guild->tribute.id_1,
|
||||
guild->tribute.id_1_tier,
|
||||
guild->tribute.id_2,
|
||||
guild->tribute.id_2_tier
|
||||
).c_str());
|
||||
c->Message(
|
||||
Chat::Yellow, fmt::format(
|
||||
"Guild Tribute: Time Remaining {} - Enabled {}",
|
||||
guild->tribute.time_remaining,
|
||||
guild->tribute.enabled
|
||||
).c_str());
|
||||
}
|
||||
for (auto &c1: entity_list.GetClientList()) {
|
||||
if (c1.second->GuildID() == guild_id) {
|
||||
c->Message(
|
||||
Chat::Yellow, fmt::format(
|
||||
"PlayerName: {} ID: {} Rank: {} OptIn: {} DirtyList: {}.",
|
||||
c1.second->GetCleanName(),
|
||||
c1.second->GuildID(),
|
||||
c1.second->GuildRank(),
|
||||
c1.second->GuildTributeOptIn(),
|
||||
c1.second->GetGuildListDirty()
|
||||
).c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (is_test) {
|
||||
if (!sep->IsNumber(2)) {
|
||||
c->Message(Chat::White, "Usage: #guild test [Guild ID]");
|
||||
}
|
||||
else {
|
||||
auto guild_id = Strings::ToUnsignedInt(sep->arg[2]);
|
||||
auto guild = guild_mgr.GetGuildByGuildID(guild_id);
|
||||
c->SendGuildMembersList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SendGuildSubCommands(Client *c)
|
||||
void SendGuildSubCommands(Client* c)
|
||||
{
|
||||
c->Message(Chat::White, "#guild create [Character ID|Character Name] [Guild Name]");
|
||||
c->Message(Chat::White, "#guild delete [Guild ID]");
|
||||
c->Message(Chat::White, "#guild details [Guild ID]");
|
||||
c->Message(Chat::White, "#guild help");
|
||||
c->Message(Chat::White, "#guild info [Guild ID]");
|
||||
c->Message(Chat::White, "#guild list");
|
||||
|
||||
+523
-68
@@ -69,13 +69,13 @@ void Client::SendGuildURL()
|
||||
if(IsInAGuild())
|
||||
{
|
||||
auto outapp =
|
||||
new EQApplicationPacket(OP_GuildUpdateURLAndChannel, sizeof(GuildUpdateURLAndChannel_Struct));
|
||||
new EQApplicationPacket(OP_GuildUpdate, sizeof(GuildUpdateURLAndChannel_Struct));
|
||||
|
||||
GuildUpdateURLAndChannel_Struct *guuacs = (GuildUpdateURLAndChannel_Struct*) outapp->pBuffer;
|
||||
|
||||
if(guild_mgr.GetGuildURL(GuildID(), guuacs->Text))
|
||||
{
|
||||
guuacs->Action = 0;
|
||||
guuacs->Action = GuildUpdateURL;
|
||||
FastQueuePacket(&outapp);
|
||||
}
|
||||
else
|
||||
@@ -91,13 +91,13 @@ void Client::SendGuildChannel()
|
||||
if(IsInAGuild())
|
||||
{
|
||||
auto outapp =
|
||||
new EQApplicationPacket(OP_GuildUpdateURLAndChannel, sizeof(GuildUpdateURLAndChannel_Struct));
|
||||
new EQApplicationPacket(OP_GuildUpdate, sizeof(GuildUpdateURLAndChannel_Struct));
|
||||
|
||||
GuildUpdateURLAndChannel_Struct *guuacs = (GuildUpdateURLAndChannel_Struct*) outapp->pBuffer;
|
||||
|
||||
if(guild_mgr.GetGuildChannel(GuildID(), guuacs->Text))
|
||||
{
|
||||
guuacs->Action = 1;
|
||||
guuacs->Action = GuildUpdateChannel;
|
||||
|
||||
FastQueuePacket(&outapp);
|
||||
}
|
||||
@@ -111,8 +111,8 @@ void Client::SendGuildRanks()
|
||||
if (ClientVersion() < EQ::versions::ClientVersion::RoF)
|
||||
return;
|
||||
|
||||
int permissions = 30 + 1; //Static number of permissions in all EQ clients as of May 2014
|
||||
int ranks = 8 + 1; // Static number of RoF+ ranks as of May 2014
|
||||
int permissions = GUILD_MAX_FUNCTIONS + 1; //Static number of permissions in all EQ clients as of May 2014
|
||||
int ranks = GUILD_RECRUIT + 1; // Static number of RoF+ ranks as of May 2014
|
||||
int j = 1;
|
||||
int i = 1;
|
||||
if(IsInAGuild())
|
||||
@@ -121,21 +121,20 @@ void Client::SendGuildRanks()
|
||||
{
|
||||
while(i < permissions)
|
||||
{
|
||||
auto outapp = new EQApplicationPacket(OP_GuildUpdateURLAndChannel,
|
||||
sizeof(GuildUpdateRanks_Struct));
|
||||
GuildUpdateRanks_Struct *guuacs = (GuildUpdateRanks_Struct*) outapp->pBuffer;
|
||||
//guuacs->Unknown0008 = GuildID();
|
||||
strncpy(guuacs->Unknown0012, GetCleanName(), 64);
|
||||
guuacs->Action = 5;
|
||||
guuacs->RankID = j;
|
||||
guuacs->GuildID = GuildID();
|
||||
guuacs->PermissionID = i;
|
||||
guuacs->PermissionVal = 1;
|
||||
guuacs->Unknown0089[0] = 0x2c;
|
||||
guuacs->Unknown0089[1] = 0x01;
|
||||
guuacs->Unknown0089[2] = 0x00;
|
||||
FastQueuePacket(&outapp);
|
||||
i++;
|
||||
auto outapp = new EQApplicationPacket(OP_GuildUpdate,
|
||||
sizeof(GuildUpdateRanks_Struct));
|
||||
GuildUpdateRanks_Struct* guuacs = (GuildUpdateRanks_Struct*)outapp->pBuffer;
|
||||
strncpy(guuacs->Unknown0012, GetCleanName(), 64);
|
||||
guuacs->Action = GuildUpdatePermissions;
|
||||
guuacs->RankID = j;
|
||||
guuacs->GuildID = GuildID();
|
||||
guuacs->PermissionID = i;
|
||||
guuacs->PermissionVal = guild_mgr.CheckPermission(GuildID(), j, (GuildAction)i);
|
||||
guuacs->Unknown0089[0] = 0x2c;
|
||||
guuacs->Unknown0089[1] = 0x01;
|
||||
guuacs->Unknown0089[2] = 0x00;
|
||||
FastQueuePacket(&outapp);
|
||||
i++;
|
||||
}
|
||||
j++;
|
||||
i = 1;
|
||||
@@ -143,25 +142,42 @@ void Client::SendGuildRanks()
|
||||
}
|
||||
}
|
||||
|
||||
void Client::SendGuildRankNames()
|
||||
{
|
||||
if (IsInAGuild() && (ClientVersion() >= EQ::versions::ClientVersion::RoF)) {
|
||||
auto guild = guild_mgr.GetGuildByGuildID(GuildID());
|
||||
|
||||
for (int i = 1; i <= GUILD_MAX_RANK; i++) {
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_GuildUpdate, sizeof(GuildUpdateUCPStruct));
|
||||
GuildUpdateUCPStruct *gucp = (GuildUpdateUCPStruct *) outapp->pBuffer;
|
||||
|
||||
gucp->payload.rank_name.rank = i;
|
||||
strn0cpy(
|
||||
gucp->payload.rank_name.rank_name,
|
||||
guild->rank_names[i].c_str(),
|
||||
sizeof(gucp->payload.rank_name.rank_name)
|
||||
);
|
||||
gucp->action = GuildUpdateRanks;
|
||||
|
||||
QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Client::SendGuildSpawnAppearance() {
|
||||
if (!IsInAGuild()) {
|
||||
// clear guildtag
|
||||
SendAppearancePacket(AppearanceType::GuildID, GUILD_NONE);
|
||||
LogGuilds("Sending spawn appearance for no guild tag");
|
||||
} else {
|
||||
uint8 rank = guild_mgr.GetDisplayedRank(GuildID(), GuildRank(), CharacterID());
|
||||
uint8 rank = guild_mgr.GetDisplayedRank(GuildID(), GuildRank(), CharacterID());
|
||||
uint32 display = guild_mgr.CheckPermission(GuildID(), GuildRank(), GUILD_ACTION_DISPLAY_GUILD_NAME) ? 1 : 0;
|
||||
LogGuilds("Sending spawn appearance for guild [{}] at rank [{}]", GuildID(), rank);
|
||||
SendAppearancePacket(AppearanceType::GuildID, GuildID());
|
||||
if (ClientVersion() >= EQ::versions::ClientVersion::RoF)
|
||||
{
|
||||
switch (rank) {
|
||||
case 0: { rank = 5; break; } // GUILD_MEMBER 0
|
||||
case 1: { rank = 3; break; } // GUILD_OFFICER 1
|
||||
case 2: { rank = 1; break; } // GUILD_LEADER 2
|
||||
default: { break; } // GUILD_NONE
|
||||
}
|
||||
}
|
||||
SendAppearancePacket(AppearanceType::GuildRank, rank);
|
||||
SendAppearancePacket(AppearanceType::GuildID, GuildID(), true);
|
||||
SendAppearancePacket(AppearanceType::GuildRank, rank, true);
|
||||
SendAppearancePacket(AppearanceType::GuildShow, display, true);
|
||||
}
|
||||
UpdateWho();
|
||||
}
|
||||
@@ -234,7 +250,10 @@ void Client::RefreshGuildInfo()
|
||||
|
||||
guildrank = info.rank;
|
||||
guild_id = info.guild_id;
|
||||
GuildBanker = info.banker || guild_mgr.IsGuildLeader(GuildID(), CharacterID());
|
||||
GuildBanker = info.banker ||
|
||||
guild_mgr.IsGuildLeader(GuildID(), CharacterID()) ||
|
||||
guild_mgr.GetBankerFlag(CharacterID()) ||
|
||||
ClientVersion() >= EQ::versions::ClientVersion::RoF ? true : false;
|
||||
|
||||
if(zone->GetZoneID() == Zones::GUILDHALL)
|
||||
{
|
||||
@@ -244,9 +263,9 @@ void Client::RefreshGuildInfo()
|
||||
|
||||
GuildSetRank_Struct *gsrs = (GuildSetRank_Struct*)outapp->pBuffer;
|
||||
|
||||
gsrs->Rank = guildrank;
|
||||
strn0cpy(gsrs->MemberName, GetName(), sizeof(gsrs->MemberName));
|
||||
gsrs->Banker = GuildBanker;
|
||||
gsrs->rank = guildrank;
|
||||
strn0cpy(gsrs->member_name, GetName(), sizeof(gsrs->member_name));
|
||||
gsrs->banker = GuildBanker;
|
||||
|
||||
FastQueuePacket(&outapp);
|
||||
}
|
||||
@@ -257,7 +276,7 @@ void Client::RefreshGuildInfo()
|
||||
if (ClientVersion() < EQ::versions::ClientVersion::RoF)
|
||||
ClearGuildBank();
|
||||
|
||||
if(guild_id != GUILD_NONE)
|
||||
if (guild_id != GUILD_NONE)
|
||||
GuildBanks->SendGuildBank(this);
|
||||
}
|
||||
}
|
||||
@@ -265,24 +284,50 @@ void Client::RefreshGuildInfo()
|
||||
SendGuildSpawnAppearance();
|
||||
}
|
||||
|
||||
void EntityList::SendGuildMOTD(uint32 guild_id) {
|
||||
if(guild_id == GUILD_NONE)
|
||||
void EntityList::SendGuildMOTD(uint32 guild_id)
|
||||
{
|
||||
if (guild_id == GUILD_NONE) {
|
||||
return;
|
||||
auto it = client_list.begin();
|
||||
while (it != client_list.end()) {
|
||||
Client *client = it->second;
|
||||
if (client->GuildID() == guild_id) {
|
||||
client->SendGuildMOTD();
|
||||
client->SendGuildURL();
|
||||
client->SendGuildChannel();
|
||||
}
|
||||
|
||||
for (auto const &c: client_list) {
|
||||
if (c.second->GuildID() == guild_id) {
|
||||
c.second->SendGuildMOTD();
|
||||
}
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
void EntityList::SendGuildSpawnAppearance(uint32 guild_id) {
|
||||
if(guild_id == GUILD_NONE)
|
||||
void EntityList::SendGuildChannel(uint32 guild_id)
|
||||
{
|
||||
if (guild_id == GUILD_NONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto const &c: client_list) {
|
||||
if (c.second->GuildID() == guild_id) {
|
||||
c.second->SendGuildChannel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EntityList::SendGuildURL(uint32 guild_id)
|
||||
{
|
||||
if (guild_id == GUILD_NONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto const &c: client_list) {
|
||||
if (c.second->GuildID() == guild_id) {
|
||||
c.second->SendGuildURL();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EntityList::SendGuildSpawnAppearance(uint32 guild_id)
|
||||
{
|
||||
if (guild_id == GUILD_NONE) {
|
||||
return;
|
||||
}
|
||||
auto it = client_list.begin();
|
||||
while (it != client_list.end()) {
|
||||
Client *client = it->second;
|
||||
@@ -293,9 +338,11 @@ void EntityList::SendGuildSpawnAppearance(uint32 guild_id) {
|
||||
}
|
||||
}
|
||||
|
||||
void EntityList::RefreshAllGuildInfo(uint32 guild_id) {
|
||||
if(guild_id == GUILD_NONE)
|
||||
void EntityList::RefreshAllGuildInfo(uint32 guild_id)
|
||||
{
|
||||
if (guild_id == GUILD_NONE) {
|
||||
return;
|
||||
}
|
||||
auto it = client_list.begin();
|
||||
while (it != client_list.end()) {
|
||||
Client *client = it->second;
|
||||
@@ -306,9 +353,11 @@ void EntityList::RefreshAllGuildInfo(uint32 guild_id) {
|
||||
}
|
||||
}
|
||||
|
||||
void EntityList::SendGuildMembers(uint32 guild_id) {
|
||||
if(guild_id == GUILD_NONE)
|
||||
void EntityList::SendGuildMembers(uint32 guild_id)
|
||||
{
|
||||
if (guild_id == GUILD_NONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
//this could be optimized a bit to only build the member's packet once
|
||||
//and then keep swapping out the name in the packet on each send.
|
||||
@@ -317,36 +366,92 @@ void EntityList::SendGuildMembers(uint32 guild_id) {
|
||||
while (it != client_list.end()) {
|
||||
Client *client = it->second;
|
||||
if (client->GuildID() == guild_id) {
|
||||
client->SendGuildMembers();
|
||||
//client->SendGuildMembers();
|
||||
}
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
void EntityList::SendGuildList() {
|
||||
auto it = client_list.begin();
|
||||
while (it != client_list.end()) {
|
||||
Client *client = it->second;
|
||||
client->SendGuildList();
|
||||
++it;
|
||||
void EntityList::SendGuildList()
|
||||
{
|
||||
for (auto const& c : client_list) {
|
||||
c.second->SendGuildList();
|
||||
}
|
||||
}
|
||||
|
||||
void Client::SendGuildJoin(GuildJoin_Struct* gj){
|
||||
void Client::SendGuildJoin(GuildJoin_Struct *gj)
|
||||
{
|
||||
auto outapp = new EQApplicationPacket(OP_GuildManageAdd, sizeof(GuildJoin_Struct));
|
||||
GuildJoin_Struct* outgj=(GuildJoin_Struct*)outapp->pBuffer;
|
||||
outgj->class_ = gj->class_;
|
||||
auto outgj = (GuildJoin_Struct *) outapp->pBuffer;
|
||||
outgj->class_ = gj->class_;
|
||||
outgj->guild_id = gj->guild_id;
|
||||
outgj->level = gj->level;
|
||||
outgj->level = gj->level;
|
||||
outgj->rank = gj->rank;
|
||||
outgj->zoneid = gj->zoneid;
|
||||
strcpy(outgj->name, gj->name);
|
||||
outgj->rank = gj->rank;
|
||||
outgj->zoneid = gj->zoneid;
|
||||
|
||||
LogGuilds("Sending OP_GuildManageAdd for join of length [{}]", outapp->size);
|
||||
|
||||
FastQueuePacket(&outapp);
|
||||
}
|
||||
|
||||
// SendGuildMembers(gj->guild_id, true);
|
||||
void EntityList::GuildSetPreRoFBankerFlag(uint32 guild_id, uint32 guild_rank, bool bank_status)
|
||||
{
|
||||
auto guild_members = [&]() -> std::vector<Client *> {
|
||||
std::vector<Client *> members = {};
|
||||
for (auto const &c: entity_list.GetClientList()) {
|
||||
if (c.second->GuildID() == guild_id && c.second->GuildRank() == guild_rank) {
|
||||
members.push_back(c.second);
|
||||
}
|
||||
}
|
||||
return members;
|
||||
};
|
||||
|
||||
for (auto const &c: guild_members()) {
|
||||
auto outapp = new ServerPacket(
|
||||
ServerOP_GuildRankUpdate,
|
||||
sizeof(ServerGuildRankUpdate_Struct)
|
||||
);
|
||||
|
||||
guild_mgr.UpdateDbBankerFlag(c->CharacterID(), bank_status);
|
||||
c->SetGuildBanker(bank_status);
|
||||
CharGuildInfo cgi;
|
||||
guild_mgr.GetCharInfo(c->CharacterID(), cgi);
|
||||
|
||||
auto *sgrus = (ServerGuildRankUpdate_Struct *) outapp->pBuffer;
|
||||
sgrus->guild_id = guild_id;
|
||||
sgrus->rank = guild_rank;
|
||||
sgrus->banker = (bank_status ? 1 : 0) + (cgi.alt ? 2 : 0);
|
||||
sgrus->no_update = true;
|
||||
strn0cpy(sgrus->member_name, c->GetCleanName(), sizeof(sgrus->member_name));
|
||||
|
||||
worldserver.SendPacket(outapp);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
}
|
||||
|
||||
void Client::SetGuildRank(uint32 rank)
|
||||
{
|
||||
guildrank = rank;
|
||||
}
|
||||
|
||||
void Client::SetGuildTributeOptIn(bool state)
|
||||
{
|
||||
guild_tribute_opt_in = state;
|
||||
}
|
||||
|
||||
void Client::SetGuildID(uint32 g_id)
|
||||
{
|
||||
guild_id = g_id;
|
||||
}
|
||||
|
||||
void EntityList::UpdateGuildTributes(uint32 guild_id)
|
||||
{
|
||||
for (auto const &c: entity_list.GetClientList()) {
|
||||
if (c.second->GuildID() == guild_id) {
|
||||
c.second->DoGuildTributeUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -409,3 +514,353 @@ void Client::GuildChangeRank(const char* name, uint32 guild_id, uint32 oldrank,
|
||||
SendGuildMembers(guild_id, true);
|
||||
}*/
|
||||
|
||||
void Client::SendGuildMembersList()
|
||||
{
|
||||
auto guild_name = guild_mgr.GetGuildName(GuildID());
|
||||
uint32 len;
|
||||
uint8 *data = guild_mgr.MakeGuildMembers(GuildID(), guild_name, len);
|
||||
if (data == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_GuildMemberList);
|
||||
outapp->size = len;
|
||||
outapp->pBuffer = data;
|
||||
data = nullptr;
|
||||
|
||||
LogGuilds("Sending OP_GuildMemberList of length [{}]", outapp->size);
|
||||
|
||||
FastQueuePacket(&outapp);
|
||||
|
||||
SendGuildMOTD();
|
||||
SendGuildChannel();
|
||||
SendGuildURL();
|
||||
|
||||
SetGuildListDirty(false);
|
||||
}
|
||||
|
||||
void Client::SendGuildMemberAdd(
|
||||
uint32 guild_id,
|
||||
uint32 level,
|
||||
uint32 class_,
|
||||
uint32 rank_,
|
||||
uint32 guild_show,
|
||||
uint32 zone_id,
|
||||
std::string player_name
|
||||
)
|
||||
{
|
||||
if (GetGuildListDirty()) {
|
||||
SendGuildMembersList();
|
||||
return;
|
||||
}
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_GuildMemberAdd, sizeof(GuildMemberAdd_Struct));
|
||||
auto out = (GuildMemberAdd_Struct *) outapp->pBuffer;
|
||||
|
||||
out->guild_id = guild_id;
|
||||
out->last_on = time(nullptr);
|
||||
out->level = level;
|
||||
out->zone_id = zone_id;
|
||||
out->rank_ = rank_;
|
||||
out->guild_show = guild_show;
|
||||
out->class_ = class_;
|
||||
strn0cpy(out->player_name, player_name.c_str(), sizeof(out->player_name));
|
||||
|
||||
QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
|
||||
void Client::SendGuildMemberRename(uint32 guild_id, std::string player_name, std::string new_player_name)
|
||||
{
|
||||
auto outapp = new EQApplicationPacket(OP_GuildMemberRename, sizeof(GuildRenameMember_Struct));
|
||||
auto *out = (GuildRenameMember_Struct *) outapp->pBuffer;
|
||||
|
||||
out->guild_id = guild_id;
|
||||
strn0cpy(out->player_name, player_name.c_str(), sizeof(out->player_name));
|
||||
strn0cpy(out->new_player_name, new_player_name.c_str(), sizeof(out->new_player_name));
|
||||
|
||||
QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
|
||||
}
|
||||
|
||||
void Client::SendGuildMemberDelete(uint32 guild_id, std::string player_name)
|
||||
{
|
||||
auto outapp = new EQApplicationPacket(OP_GuildMemberDelete, sizeof(GuildMemberDelete_Struct));
|
||||
auto out = (GuildMemberDelete_Struct *) outapp->pBuffer;
|
||||
|
||||
out->guild_id = guild_id;
|
||||
strn0cpy(out->player_name, player_name.c_str(), sizeof(out->player_name));
|
||||
|
||||
QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
|
||||
SetGuildListDirty(true);
|
||||
|
||||
}
|
||||
|
||||
void Client::SendGuildMemberLevel(uint32 guild_id, uint32 level, std::string player_name)
|
||||
{
|
||||
auto outapp = new EQApplicationPacket(OP_GuildMemberLevel, sizeof(GuildMemberLevel_Struct));
|
||||
auto out = (GuildMemberLevel_Struct *) outapp->pBuffer;
|
||||
|
||||
out->guild_id = guild_id;
|
||||
out->level = level;
|
||||
strn0cpy(out->player_name, player_name.c_str(), sizeof(out->player_name));
|
||||
|
||||
QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
|
||||
void Client::SendGuildMemberRankAltBanker(uint32 guild_id, uint32 rank, std::string player_name, bool alt, bool banker)
|
||||
{
|
||||
auto outapp = new EQApplicationPacket(OP_GuildMemberRankAltBanker, sizeof(GuildMemberRank_Struct));
|
||||
auto out = (GuildMemberRank_Struct *) outapp->pBuffer;
|
||||
|
||||
out->guild_id = guild_id;
|
||||
out->rank_ = rank;
|
||||
out->alt_banker = (alt << 1) | banker;
|
||||
strn0cpy(out->player_name, player_name.c_str(), sizeof(out->player_name));
|
||||
|
||||
QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
|
||||
void Client::SendGuildMemberPublicNote(uint32 guild_id, std::string player_name, std::string public_note)
|
||||
{
|
||||
auto outapp = new EQApplicationPacket(OP_GuildMemberPublicNote, sizeof(GuildMemberPublicNote_Struct));
|
||||
auto out = (GuildMemberPublicNote_Struct *) outapp->pBuffer;
|
||||
|
||||
out->guild_id = guild_id;
|
||||
strn0cpy(out->player_name, player_name.c_str(), sizeof(out->player_name));
|
||||
strn0cpy(out->public_note, public_note.c_str(), sizeof(out->public_note));
|
||||
|
||||
QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
|
||||
void Client::SendGuildMemberDetails(uint32 guild_id, uint32 zone_id, uint32 offline_mode, std::string player_name)
|
||||
{
|
||||
auto outapp = new EQApplicationPacket(OP_GuildMemberDetails, sizeof(GuildMemberDetails_Struct));
|
||||
auto out = (GuildMemberDetails_Struct *) outapp->pBuffer;
|
||||
|
||||
out->guild_id = guild_id;
|
||||
out->zone_id = zone_id;
|
||||
out->last_on = time(nullptr);
|
||||
out->offline_mode = offline_mode;
|
||||
strn0cpy(out->player_name, player_name.c_str(), sizeof(out->player_name));
|
||||
|
||||
QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
|
||||
void Client::SendGuildRenameGuild(uint32 guild_id, std::string new_guild_name)
|
||||
{
|
||||
auto outapp = new EQApplicationPacket(OP_GuildRenameGuild, sizeof(GuildRenameGuild_Struct));
|
||||
auto out = (GuildRenameGuild_Struct *) outapp->pBuffer;
|
||||
|
||||
out->guild_id = guild_id;
|
||||
strn0cpy(out->new_guild_name, new_guild_name.c_str(), sizeof(out->new_guild_name));
|
||||
|
||||
QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
|
||||
void EntityList::SendGuildMembersList(uint32 guild_id)
|
||||
{
|
||||
for (auto const& c : client_list) {
|
||||
if (c.second->GuildID() == guild_id) {
|
||||
c.second->SendGuildMembersList();
|
||||
c.second->SetGuildListDirty(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EntityList::SendGuildMemberAdd(
|
||||
uint32 guild_id,
|
||||
uint32 level,
|
||||
uint32 class_,
|
||||
uint32 rank_,
|
||||
uint32 spirit,
|
||||
uint32 zone_id,
|
||||
std::string player_name
|
||||
)
|
||||
{
|
||||
for (auto &c: client_list) {
|
||||
if (c.second->GuildID() == guild_id) {
|
||||
c.second->SendGuildMemberAdd(guild_id, level, class_, rank_, 0, zone_id, player_name);
|
||||
}
|
||||
|
||||
if (player_name.compare(c.second->GetCleanName()) == 0) {
|
||||
c.second->SetGuildID(guild_id);
|
||||
c.second->SetGuildRank(rank_);
|
||||
c.second->SendGuildList();
|
||||
c.second->SetGuildTributeOptIn(false);
|
||||
c.second->SendGuildMembersList();
|
||||
if (c.second->ClientVersion() >= EQ::versions::ClientVersion::RoF) {
|
||||
c.second->SendGuildRanks();
|
||||
c.second->SendGuildRankNames();
|
||||
}
|
||||
|
||||
if (zone->GetZoneID() == Zones::GUILDHALL && GuildBanks) {
|
||||
GuildBanks->SendGuildBank(c.second);
|
||||
}
|
||||
|
||||
c.second->SendGuildActiveTributes(guild_id);
|
||||
c.second->SendAppearancePacket(AppearanceType::GuildID, guild_id, true, false, c.second);
|
||||
c.second->SendAppearancePacket(AppearanceType::GuildRank, rank_, true, false, c.second);
|
||||
c.second->SendAppearancePacket(AppearanceType::GuildShow, guild_mgr.CheckPermission(guild_id, rank_, GUILD_ACTION_DISPLAY_GUILD_NAME) ? 1 : 0);
|
||||
c.second->DoGuildTributeUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EntityList::SendGuildMemberRename(uint32 guild_id, std::string player_name, std::string new_player_name)
|
||||
{
|
||||
for (auto const &c: client_list) {
|
||||
if (c.second->GuildID() == guild_id) {
|
||||
auto outapp = new EQApplicationPacket(OP_GuildMemberRename, sizeof(GuildRenameMember_Struct));
|
||||
auto out = (GuildRenameMember_Struct *) outapp->pBuffer;
|
||||
|
||||
out->guild_id = guild_id;
|
||||
strn0cpy(out->player_name, player_name.c_str(), sizeof(out->player_name));
|
||||
strn0cpy(out->new_player_name, new_player_name.c_str(), sizeof(out->new_player_name));
|
||||
|
||||
c.second->QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EntityList::SendGuildMemberRemove(uint32 guild_id, std::string player_name)
|
||||
{
|
||||
for (auto &c: client_list) {
|
||||
if (c.second->GuildID() == guild_id) {
|
||||
auto outapp = new EQApplicationPacket(OP_GuildMemberDelete, sizeof(GuildMemberDelete_Struct));
|
||||
auto out = (GuildMemberDelete_Struct *) outapp->pBuffer;
|
||||
|
||||
out->guild_id = guild_id;
|
||||
strn0cpy(out->player_name, player_name.c_str(), sizeof(out->player_name));
|
||||
|
||||
c.second->QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
|
||||
c.second->SetGuildListDirty(true);
|
||||
|
||||
if (player_name.compare(c.second->GetCleanName()) == 0) {
|
||||
c.second->SetGuildID(GUILD_NONE);
|
||||
c.second->SetGuildRank(GUILD_RANK_NONE);
|
||||
c.second->SetGuildTributeOptIn(false);
|
||||
c.second->SendGuildActiveTributes(0);
|
||||
c.second->SetGuildListDirty(false);
|
||||
c.second->SendGuildList();
|
||||
c.second->SendAppearancePacket(AppearanceType::GuildID, GUILD_NONE, true);
|
||||
c.second->SendAppearancePacket(AppearanceType::GuildRank, GUILD_RANK_NONE, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EntityList::SendGuildMemberLevel(uint32 guild_id, uint32 level, std::string player_name)
|
||||
{
|
||||
for (auto const &c: client_list) {
|
||||
if (c.second->GuildID() == guild_id) {
|
||||
auto outapp = new EQApplicationPacket(OP_GuildMemberLevel, sizeof(GuildMemberLevel_Struct));
|
||||
GuildMemberLevel_Struct *out = (GuildMemberLevel_Struct *) outapp->pBuffer;
|
||||
|
||||
out->guild_id = guild_id;
|
||||
out->level = level;
|
||||
strn0cpy(out->player_name, player_name.c_str(), sizeof(out->player_name));
|
||||
|
||||
c.second->QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EntityList::SendGuildMemberRankAltBanker(uint32 guild_id, uint32 rank_, std::string player_name, bool alt, bool banker)
|
||||
{
|
||||
for (auto const &c: client_list) {
|
||||
if (c.second->GuildID() == guild_id) {
|
||||
auto outapp = new EQApplicationPacket(OP_GuildMemberRankAltBanker, sizeof(GuildMemberRank_Struct));
|
||||
auto out = (GuildMemberRank_Struct *) outapp->pBuffer;
|
||||
|
||||
out->guild_id = guild_id;
|
||||
out->rank_ = rank_;
|
||||
out->alt_banker = (alt << 1) | banker;
|
||||
strn0cpy(out->player_name, player_name.c_str(), sizeof(out->player_name));
|
||||
|
||||
c.second->QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
|
||||
if (player_name.compare(c.second->GetName()) == 0) {
|
||||
c.second->SetGuildRank(rank_);
|
||||
c.second->SendAppearancePacket(AppearanceType::GuildRank, rank_, false);
|
||||
c.second->SendAppearancePacket(AppearanceType::GuildShow,
|
||||
guild_mgr.CheckPermission(c.second->GuildID(), c.second->GuildRank(), GUILD_ACTION_DISPLAY_GUILD_NAME) ? 1 : 0,
|
||||
true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EntityList::SendGuildMemberPublicNote(uint32 guild_id, std::string player_name, std::string public_note)
|
||||
{
|
||||
for (auto const &c: client_list) {
|
||||
if (c.second->GuildID() == guild_id) {
|
||||
auto outapp = new EQApplicationPacket(OP_GuildMemberPublicNote, sizeof(GuildMemberPublicNote_Struct));
|
||||
auto out = (GuildMemberPublicNote_Struct *) outapp->pBuffer;
|
||||
|
||||
out->guild_id = guild_id;
|
||||
strn0cpy(out->player_name, player_name.c_str(), sizeof(out->player_name));
|
||||
strn0cpy(out->public_note, public_note.c_str(), sizeof(out->public_note));
|
||||
|
||||
c.second->QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EntityList::SendGuildMemberDetails(uint32 guild_id, uint32 zone_id, uint32 offline_mode, std::string player_name)
|
||||
{
|
||||
for (auto const &c: client_list) {
|
||||
if (c.second->GuildID() == guild_id) {
|
||||
auto outapp = new EQApplicationPacket(OP_GuildMemberDetails, sizeof(GuildMemberDetails_Struct));
|
||||
auto out = (GuildMemberDetails_Struct *) outapp->pBuffer;
|
||||
|
||||
out->guild_id = guild_id;
|
||||
out->zone_id = zone_id;
|
||||
out->last_on = time(nullptr);
|
||||
out->offline_mode = offline_mode;
|
||||
strn0cpy(out->player_name, player_name.c_str(), sizeof(out->player_name));
|
||||
|
||||
c.second->QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EntityList::SendGuildRenameGuild(uint32 guild_id, std::string new_guild_name)
|
||||
{
|
||||
for (auto const &c: client_list) {
|
||||
if (c.second->GuildID() == guild_id) {
|
||||
auto outapp = new EQApplicationPacket(OP_GuildRenameGuild, sizeof(GuildRenameGuild_Struct));
|
||||
auto out = (GuildRenameGuild_Struct *) outapp->pBuffer;
|
||||
|
||||
out->guild_id = guild_id;
|
||||
strn0cpy(out->new_guild_name, new_guild_name.c_str(), sizeof(out->new_guild_name));
|
||||
|
||||
c.second->QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Client::SendGuildDeletePacket(uint32 guild_id)
|
||||
{
|
||||
auto outapp = new EQApplicationPacket(OP_GuildDeleteGuild, sizeof(GuildDelete_Struct));
|
||||
auto data = (GuildDelete_Struct*)outapp->pBuffer;
|
||||
|
||||
data->guild_id = guild_id;
|
||||
FastQueuePacket(&outapp);
|
||||
}
|
||||
|
||||
+750
-383
File diff suppressed because it is too large
Load Diff
+20
-4
@@ -57,16 +57,32 @@ public:
|
||||
void ListGuilds(Client *c, std::string search_criteria = std::string()) const;
|
||||
void ListGuilds(Client *c, uint32 guild_id = 0) const;
|
||||
void DescribeGuild(Client *c, uint32 guild_id) const;
|
||||
bool IsActionABankAction(GuildAction action);
|
||||
|
||||
|
||||
// bool DonateTribute(uint32 charid, uint32 guild_id, uint32 tribute_amount);
|
||||
|
||||
uint8 *MakeGuildMembers(uint32 guild_id, const char *prefix_name, uint32 &length); //make a guild member list packet, returns ownership of the buffer.
|
||||
uint8 *MakeGuildMembers(uint32 guild_id, const char* prefix_name, uint32& length);
|
||||
void SendToWorldMemberLevelUpdate(uint32 guild_id, uint32 level, std::string player_name);
|
||||
void SendToWorldMemberPublicNote(uint32 guild_id, std::string player_name, std::string public_note);
|
||||
void SendToWorldMemberRemove(uint32 guild_id, std::string player_name);
|
||||
void SendToWorldMemberAdd(uint32 guild_id, uint32 char_id, uint32 level, uint32 _class, uint32 rank, uint32 zone_id, std::string player_name);
|
||||
void SendToWorldGuildChannel(uint32 guild_id, std::string channel);
|
||||
void SendToWorldGuildURL(uint32 guild_id, std::string url);
|
||||
void SendToWorldSendGuildList();
|
||||
void SendToWorldMemberRankUpdate(uint32 guild_id, uint32 rank, uint32 banker, uint32 alt, bool no_update, const char *player_name);
|
||||
void SendToWorldSendGuildMembersList(uint32 guild_id);
|
||||
bool RemoveMember(uint32 guild_id, uint32 char_id, std::string player_name);
|
||||
void MemberAdd(uint32 guild_id, uint32 char_id, uint32 level, uint32 _class, uint32 rank, uint32 zone_id, std::string player_name);
|
||||
bool MemberRankUpdate(uint32 guild_id, uint32 rank, uint32 banker, uint32 alt, bool no_update, const char *player_name);
|
||||
|
||||
void RecordInvite(uint32 char_id, uint32 guild_id, uint8 rank);
|
||||
bool VerifyAndClearInvite(uint32 char_id, uint32 guild_id, uint8 rank);
|
||||
void SendGuildMemberUpdateToWorld(const char *MemberName, uint32 GuildID, uint16 ZoneID, uint32 LastSeen);
|
||||
void RequestOnlineGuildMembers(uint32 FromID, uint32 GuildID);
|
||||
void UpdateRankPermission(uint32 gid, uint32 charid, uint32 fid, uint32 rank, uint32 value);
|
||||
void SendPermissionUpdate(uint32 guild_id, uint32 rank, uint32 function_id, uint32 value);
|
||||
void UpdateRankName(uint32 gid, uint32 rank, std::string rank_name);
|
||||
void SendRankName(uint32 guild_id, uint32 rank, std::string rank_name);
|
||||
void SendAllRankNames(uint32 guild_id, uint32 char_id);
|
||||
BaseGuildManager::GuildInfo* GetGuildByGuildID(uint32 guild_id);
|
||||
|
||||
protected:
|
||||
virtual void SendGuildRefresh(uint32 guild_id, bool name, bool motd, bool rank, bool relation);
|
||||
|
||||
+8
-1
@@ -1105,7 +1105,7 @@ void Client::DeleteItemInInventory(int16 slot_id, int16 quantity, bool client_up
|
||||
if(update_db)
|
||||
database.SaveInventory(character_id, inst, slot_id);
|
||||
}
|
||||
|
||||
|
||||
if(client_update && IsValidSlot(slot_id)) {
|
||||
EQApplicationPacket* outapp = nullptr;
|
||||
if(inst) {
|
||||
@@ -1674,6 +1674,7 @@ bool Client::IsValidSlot(uint32 slot) {
|
||||
(slot == (uint32)EQ::invslot::slotCursor) ||
|
||||
(slot <= EQ::invbag::CURSOR_BAG_END && slot >= EQ::invbag::CURSOR_BAG_BEGIN) ||
|
||||
(slot <= EQ::invslot::TRIBUTE_END && slot >= EQ::invslot::TRIBUTE_BEGIN) ||
|
||||
(slot <= EQ::invslot::GUILD_TRIBUTE_END && slot >= EQ::invslot::GUILD_TRIBUTE_BEGIN) ||
|
||||
(slot <= EQ::invslot::SHARED_BANK_END && slot >= EQ::invslot::SHARED_BANK_BEGIN) ||
|
||||
(slot <= EQ::invbag::SHARED_BANK_BAGS_END && slot >= EQ::invbag::SHARED_BANK_BAGS_BEGIN) ||
|
||||
(slot <= EQ::invslot::TRADE_END && slot >= EQ::invslot::TRADE_BEGIN) ||
|
||||
@@ -3578,6 +3579,11 @@ bool Client::InterrogateInventory(Client* requester, bool log, bool silent, bool
|
||||
if (inst == nullptr) { continue; }
|
||||
instmap[index] = inst;
|
||||
}
|
||||
for (int16 index = EQ::invslot::GUILD_TRIBUTE_BEGIN; index <= EQ::invslot::GUILD_TRIBUTE_END; ++index) {
|
||||
auto inst = m_inv[index];
|
||||
if (inst == nullptr) { continue; }
|
||||
instmap[index] = inst;
|
||||
}
|
||||
for (int16 index = EQ::invslot::BANK_BEGIN; index <= EQ::invslot::BANK_END; ++index) {
|
||||
auto inst = m_inv[index];
|
||||
if (inst == nullptr) { continue; }
|
||||
@@ -3714,6 +3720,7 @@ bool Client::InterrogateInventory_error(int16 head, int16 index, const EQ::ItemI
|
||||
if (
|
||||
(head >= EQ::invslot::EQUIPMENT_BEGIN && head <= EQ::invslot::EQUIPMENT_END) ||
|
||||
(head >= EQ::invslot::TRIBUTE_BEGIN && head <= EQ::invslot::TRIBUTE_END) ||
|
||||
(head >= EQ::invslot::GUILD_TRIBUTE_BEGIN && head <= EQ::invslot::GUILD_TRIBUTE_END) ||
|
||||
(head >= EQ::invslot::WORLD_BEGIN && head <= EQ::invslot::WORLD_END) ||
|
||||
(head >= 8000 && head <= 8101)) {
|
||||
switch (depth)
|
||||
|
||||
+7
-1
@@ -83,6 +83,11 @@ int Lua_Packet::GetRawOpcode() {
|
||||
return static_cast<int>(self->GetOpcodeBypass());
|
||||
}
|
||||
|
||||
int Lua_Packet::GetProtocolOpcode() {
|
||||
Lua_Safe_Call_Int();
|
||||
return static_cast<int>(self->GetProtocolOpcode());
|
||||
}
|
||||
|
||||
void Lua_Packet::SetRawOpcode(int op) {
|
||||
Lua_Safe_Call_Void();
|
||||
self->SetOpcode(static_cast<EmuOpcode>(op));
|
||||
@@ -329,6 +334,7 @@ luabind::scope lua_register_packet() {
|
||||
.property("valid", &Lua_Packet::Valid)
|
||||
.def("GetOpcode", &Lua_Packet::GetOpcode)
|
||||
.def("GetRawOpcode", &Lua_Packet::GetRawOpcode)
|
||||
.def("GetProtocolOpcode", &Lua_Packet::GetProtocolOpcode)
|
||||
.def("GetSize", &Lua_Packet::GetSize)
|
||||
.def("GetWritePosition", &Lua_Packet::GetWritePosition)
|
||||
.def("ReadDouble", &Lua_Packet::ReadDouble)
|
||||
@@ -837,7 +843,7 @@ luabind::scope lua_register_packet_opcodes() {
|
||||
luabind::value("HideCorpse", static_cast<int>(OP_HideCorpse)),
|
||||
luabind::value("TargetBuffs", static_cast<int>(OP_TargetBuffs)),
|
||||
luabind::value("TradeBusy", static_cast<int>(OP_TradeBusy)),
|
||||
luabind::value("GuildUpdateURLAndChannel", static_cast<int>(OP_GuildUpdateURLAndChannel)),
|
||||
luabind::value("GuildUpdate", static_cast<int>(OP_GuildUpdate)),
|
||||
luabind::value("CameraEffect", static_cast<int>(OP_CameraEffect)),
|
||||
luabind::value("SpellEffect", static_cast<int>(OP_SpellEffect)),
|
||||
luabind::value("DzQuit", static_cast<int>(OP_DzQuit)),
|
||||
|
||||
@@ -30,6 +30,7 @@ public:
|
||||
int GetOpcode();
|
||||
void SetOpcode(int op);
|
||||
int GetRawOpcode();
|
||||
int GetProtocolOpcode();
|
||||
void SetRawOpcode(int op);
|
||||
int GetWritePosition();
|
||||
void SetWritePosition(int offset);
|
||||
|
||||
+2
-1
@@ -371,7 +371,7 @@ int main(int argc, char **argv)
|
||||
LogError("Loading items failed!");
|
||||
LogError("Failed. But ignoring error and going on..");
|
||||
}
|
||||
|
||||
|
||||
if (!content_db.LoadSkillCaps(std::string(hotfix_name))) {
|
||||
LogError("Loading skill caps failed!");
|
||||
return 1;
|
||||
@@ -381,6 +381,7 @@ int main(int argc, char **argv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
guild_mgr.LoadGuilds();
|
||||
content_db.LoadFactionData();
|
||||
title_manager.LoadTitles();
|
||||
|
||||
@@ -21,6 +21,8 @@ enum PlayerGenericLogEventTypes {
|
||||
Player_Log_Issued_Commands,
|
||||
Player_Log_Money_Transactions,
|
||||
Player_Log_Alternate_Currency_Transactions,
|
||||
Player_Log_Guild_Tribute_Item_Donation,
|
||||
Player_Log_Guild_Tribute_Plat_Donation
|
||||
};
|
||||
|
||||
|
||||
|
||||
+43
-1
@@ -6596,7 +6596,49 @@ int64 Mob::GetFocusEffect(focusType type, uint16 spell_id, Mob *caster, bool fro
|
||||
focus_max_real = focus_max;
|
||||
UsedItem = TempItem;
|
||||
UsedFocusID = TempItem->Focus.Effect;
|
||||
} else if (focus_max < 0 && focus_max < focus_max_real) {
|
||||
}
|
||||
else if (focus_max < 0 && focus_max < focus_max_real) {
|
||||
focus_max_real = focus_max;
|
||||
UsedItem = TempItem;
|
||||
UsedFocusID = TempItem->Focus.Effect;
|
||||
}
|
||||
}
|
||||
else {
|
||||
Total = CalcFocusEffect(type, TempItem->Focus.Effect, spell_id);
|
||||
if (Total > 0 && realTotal >= 0 && Total > realTotal) {
|
||||
realTotal = Total;
|
||||
UsedItem = TempItem;
|
||||
UsedFocusID = TempItem->Focus.Effect;
|
||||
}
|
||||
else if (Total < 0 && Total < realTotal) {
|
||||
realTotal = Total;
|
||||
UsedItem = TempItem;
|
||||
UsedFocusID = TempItem->Focus.Effect;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (IsClient()) {
|
||||
//Client Guild Tribute Focus
|
||||
for (int x = EQ::invslot::GUILD_TRIBUTE_BEGIN; x <= EQ::invslot::GUILD_TRIBUTE_END; ++x) {
|
||||
TempItem = nullptr;
|
||||
EQ::ItemInstance* ins = GetInv().GetItem(x);
|
||||
if (!ins) {
|
||||
continue;
|
||||
}
|
||||
|
||||
TempItem = ins->GetItem();
|
||||
if (TempItem && IsValidSpell(TempItem->Focus.Effect)) {
|
||||
if (rand_effectiveness) {
|
||||
focus_max = CalcFocusEffect(type, TempItem->Focus.Effect, spell_id, true);
|
||||
if (focus_max > 0 && focus_max_real >= 0 && focus_max > focus_max_real) {
|
||||
focus_max_real = focus_max;
|
||||
UsedItem = TempItem;
|
||||
UsedFocusID = TempItem->Focus.Effect;
|
||||
}
|
||||
else if (focus_max < 0 && focus_max < focus_max_real) {
|
||||
focus_max_real = focus_max;
|
||||
UsedItem = TempItem;
|
||||
UsedFocusID = TempItem->Focus.Effect;
|
||||
|
||||
@@ -278,6 +278,7 @@
|
||||
#define GROWS_DIM 1237 //Your %1 grows dim.
|
||||
#define BEGINS_TO_SHINE 1238 //Your %1 begins to shine.
|
||||
#define SURNAME_REJECTED 1374 //Your new surname was rejected. Please try a different name.
|
||||
#define GUILD_DISBANDED 1377 //Your guild has been disbanded! You are no longer a member of any guild.
|
||||
#define DUEL_DECLINE 1383 //%1 has declined your challenge to duel to the death.
|
||||
#define DUEL_ACCEPTED 1384 //%1 has already accepted a duel with someone else.
|
||||
#define DUEL_CONSIDERING 1385 //%1 is considering a duel with someone else.
|
||||
@@ -384,6 +385,7 @@
|
||||
#define DUNGEON_SEALED 5141 //The gateway to the dungeon is sealed off to you. Perhaps you would be able to enter if you needed to adventure there.
|
||||
#define ADVENTURE_COMPLETE 5147 //You received %1 points for successfully completing the adventure.
|
||||
#define SUCCOR_FAIL 5169 //The portal collapes before you can escape!
|
||||
#define NO_PROPER_ACCESS 5410 //You don't have the proper access rights.
|
||||
#define AUGMENT_RESTRICTED 5480 //The item does not satisfy the augment's restrictions.
|
||||
#define PET_ATTACKING 5501 //%1 tells you, 'Attacking %2 Master.'
|
||||
#define AVOID_STUNNING_BLOW 5753 //You avoid the stunning blow.
|
||||
@@ -408,6 +410,7 @@
|
||||
#define TRANSFORM_FAILED 6326 //This mold cannot be applied to your %1.
|
||||
#define TRANSFORM_COMPLETE 6327 //You have successfully transformed your %1.
|
||||
#define DETRANSFORM_FAILED 6341 //%1 has no transformation that can be removed.
|
||||
#define GUILD_PERMISSION_FAILED 6418 //You do not have permission to change access options.
|
||||
#define GENERIC_STRING 6688 //%1 (used to any basic message)
|
||||
#define SENTINEL_TRIG_YOU 6724 //You have triggered your sentinel.
|
||||
#define SENTINEL_TRIG_OTHER 6725 //%1 has triggered your sentinel.
|
||||
|
||||
+242
-57
@@ -19,6 +19,10 @@
|
||||
#include "../common/global_define.h"
|
||||
#include "../common/eq_packet_structs.h"
|
||||
#include "../common/features.h"
|
||||
#include "../common/repositories/guild_tributes_repository.h"
|
||||
#include "../common/guild_base.h"
|
||||
#include "guild_mgr.h"
|
||||
#include "worldserver.h"
|
||||
|
||||
#include "client.h"
|
||||
|
||||
@@ -43,19 +47,7 @@ The server periodicly sends tribute timer updates to the client on live,
|
||||
but I dont see a point to that right now, so I dont do it.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
class TributeData {
|
||||
public:
|
||||
//this level data stored in regular byte order and must be flipped before sending
|
||||
TributeLevel_Struct tiers[MAX_TRIBUTE_TIERS];
|
||||
uint8 tier_count;
|
||||
uint32 unknown;
|
||||
std::string name;
|
||||
std::string description;
|
||||
bool is_guild; //is a guild tribute item
|
||||
};
|
||||
|
||||
extern WorldServer worldserver;
|
||||
std::map<uint32, TributeData> tribute_list;
|
||||
|
||||
void Client::ToggleTribute(bool enabled) {
|
||||
@@ -229,8 +221,8 @@ void Client::SendTributeDetails(uint32 client_id, uint32 tribute_id) {
|
||||
|
||||
t->client_id = client_id;
|
||||
t->tribute_id = tribute_id;
|
||||
memcpy(t->desc, td.description.c_str(), len);
|
||||
t->desc[len] = '\0';
|
||||
memcpy(t->description, td.description.c_str(), len);
|
||||
t->description[len] = '\0';
|
||||
|
||||
QueuePacket(&outapp);
|
||||
}
|
||||
@@ -334,47 +326,6 @@ void Client::SendTributes() {
|
||||
}
|
||||
}
|
||||
|
||||
void Client::SendGuildTributes() {
|
||||
|
||||
std::map<uint32, TributeData>::iterator cur,end;
|
||||
cur = tribute_list.begin();
|
||||
end = tribute_list.end();
|
||||
|
||||
for(; cur != end; ++cur) {
|
||||
if(!cur->second.is_guild)
|
||||
continue; //skip guild tributes here
|
||||
int len = cur->second.name.length();
|
||||
|
||||
//guild tribute has an unknown uint32 at its begining, guild ID?
|
||||
EQApplicationPacket outapp(OP_TributeInfo, sizeof(TributeAbility_Struct) + len + 1 + 4);
|
||||
uint32 *unknown = (uint32 *) outapp.pBuffer;
|
||||
TributeAbility_Struct* tas = (TributeAbility_Struct*) (outapp.pBuffer+4);
|
||||
|
||||
//this is prolly wrong in general, prolly for one specific guild
|
||||
*unknown = 0x8A110000;
|
||||
|
||||
tas->tribute_id = htonl(cur->first);
|
||||
tas->tier_count = htonl(cur->second.unknown);
|
||||
|
||||
//gotta copy over the data from tiers, and flip all the
|
||||
//byte orders, no idea why its flipped here
|
||||
uint32 r, c;
|
||||
c = cur->second.tier_count;
|
||||
TributeLevel_Struct *dest = tas->tiers;
|
||||
TributeLevel_Struct *src = cur->second.tiers;
|
||||
for(r = 0; r < c; r++, dest++, src++) {
|
||||
dest->cost = htonl(src->cost);
|
||||
dest->level = htonl(src->level);
|
||||
dest->tribute_item_id = htonl(src->tribute_item_id);
|
||||
}
|
||||
|
||||
memcpy(tas->name, cur->second.name.c_str(), len);
|
||||
tas->name[len] = '\0';
|
||||
|
||||
QueuePacket(&outapp);
|
||||
}
|
||||
}
|
||||
|
||||
bool ZoneDatabase::LoadTributes() {
|
||||
|
||||
TributeData tributeData;
|
||||
@@ -435,9 +386,243 @@ bool ZoneDatabase::LoadTributes() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void Client::SendGuildTributes()
|
||||
{
|
||||
for (auto const& t : tribute_list) {
|
||||
if (!t.second.is_guild)
|
||||
continue; //skip non guild tributes here
|
||||
|
||||
//guild tribute has an unknown uint32 at its begining, guild ID?
|
||||
int len = t.second.name.length() + 1;
|
||||
|
||||
EQApplicationPacket* outapp = new EQApplicationPacket(OP_SendGuildTributes, sizeof(GuildTributeAbility_Struct) + len);
|
||||
GuildTributeAbility_Struct* gtas = (GuildTributeAbility_Struct*)outapp->pBuffer;
|
||||
|
||||
auto tier_count = t.second.tier_count;
|
||||
for (int ti = 0; ti < t.second.tier_count; ti++) {
|
||||
if (RuleB(Guild, UseCharacterMaxLevelForGuildTributes) && t.second.tiers[ti].level > RuleI(Character, MaxLevel)) {
|
||||
tier_count -= 1;
|
||||
continue;
|
||||
}
|
||||
gtas->guild_id = GuildID();
|
||||
gtas->ability.tier_count = htonl(tier_count);
|
||||
gtas->ability.tribute_id = htonl(t.first);
|
||||
gtas->ability.tiers[ti].cost = htonl(t.second.tiers[ti].cost);
|
||||
gtas->ability.tiers[ti].tribute_item_id = htonl(t.second.tiers[ti].tribute_item_id);
|
||||
gtas->ability.tiers[ti].level = htonl(t.second.tiers[ti].level);
|
||||
}
|
||||
strcpy(gtas->ability.name, t.second.name.data());
|
||||
FastQueuePacket(&outapp);
|
||||
}
|
||||
}
|
||||
|
||||
void Client::SendGuildTributeDetails(uint32 tribute_id, uint32 tier)
|
||||
{
|
||||
if (tribute_list.count(tribute_id) != 1) {
|
||||
LogGuilds("Details request for invalid tribute [{}]", tribute_id);
|
||||
return;
|
||||
}
|
||||
|
||||
TributeData& td = tribute_list[tribute_id];
|
||||
|
||||
int len = td.description.length();
|
||||
EQApplicationPacket* outapp = new EQApplicationPacket(OP_GuildSelectTribute, sizeof(GuildTributeSelectReply_Struct) + len + 1);
|
||||
GuildTributeSelectReply_Struct* t = (GuildTributeSelectReply_Struct*)outapp->pBuffer;
|
||||
|
||||
t->tribute_id = tribute_id;
|
||||
t->tier = tier;
|
||||
t->tribute_id2 = tribute_id;
|
||||
strncpy(&t->description, td.description.c_str(), len);
|
||||
|
||||
QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
|
||||
void Client::DoGuildTributeUpdate()
|
||||
{
|
||||
LogTribute("DoGuildTributeUpdate");
|
||||
auto guild = guild_mgr.GetGuildByGuildID(GuildID());
|
||||
|
||||
if (guild && guild->tribute.enabled && GuildTributeOptIn()) {
|
||||
TributeData& d1 = tribute_list[guild->tribute.id_1];
|
||||
uint32 item_id1 = d1.tiers[guild->tribute.id_1_tier].tribute_item_id;
|
||||
TributeData& d2 = tribute_list[guild->tribute.id_2];
|
||||
uint32 item_id2 = d2.tiers[guild->tribute.id_2_tier].tribute_item_id;
|
||||
|
||||
if (item_id1) {
|
||||
LogGuilds("Guild Tribute Item 1 is {}", item_id1);
|
||||
const EQ::ItemInstance* inst = database.CreateItem(item_id1, 1);
|
||||
if (!inst) {
|
||||
LogGuilds("Guild Tribute Item 1 was not found. {}", item_id1);
|
||||
return;
|
||||
}
|
||||
auto inst_level = d1.tiers[guild->tribute.id_1_tier].level;
|
||||
if (m_inv[EQ::invslot::GUILD_TRIBUTE_BEGIN]) {
|
||||
LogGuilds("Guild Tribute DELETE Item in Slot 450");
|
||||
DeleteItemInInventory(EQ::invslot::GUILD_TRIBUTE_BEGIN);
|
||||
}
|
||||
|
||||
if ((RuleB(Guild,UseCharacterMaxLevelForGuildTributes) && RuleI(Character, MaxLevel) >= inst_level && GetLevel() >= inst_level) ||
|
||||
!RuleB(Guild, UseCharacterMaxLevelForGuildTributes)) {
|
||||
PutItemInInventory(EQ::invslot::GUILD_TRIBUTE_BEGIN, *inst);
|
||||
SendItemPacket(EQ::invslot::GUILD_TRIBUTE_BEGIN, inst, ItemPacketGuildTribute);
|
||||
}
|
||||
|
||||
safe_delete(inst);
|
||||
}
|
||||
|
||||
if (item_id2) {
|
||||
LogInfo("Guild Tribute Item 2 is {}", item_id2);
|
||||
const EQ::ItemInstance* inst = database.CreateItem(item_id2, 1);
|
||||
if (!inst) {
|
||||
LogGuilds("Guild Tribute Item 1 was not found. {}", item_id2);
|
||||
return;
|
||||
}
|
||||
auto inst_level = d2.tiers[guild->tribute.id_2_tier].level;
|
||||
if (m_inv[EQ::invslot::GUILD_TRIBUTE_BEGIN + 1]) {
|
||||
DeleteItemInInventory(EQ::invslot::GUILD_TRIBUTE_BEGIN + 1);
|
||||
LogGuilds("Guild Tribute DELETE Item in Slot 451");
|
||||
}
|
||||
|
||||
if ((RuleB(Guild, UseCharacterMaxLevelForGuildTributes) && RuleI(Character, MaxLevel) >= inst_level && GetLevel() >= inst_level) ||
|
||||
!RuleB(Guild, UseCharacterMaxLevelForGuildTributes)) {
|
||||
PutItemInInventory(EQ::invslot::GUILD_TRIBUTE_BEGIN + 1, *inst);
|
||||
SendItemPacket(EQ::invslot::GUILD_TRIBUTE_BEGIN + 1, inst, ItemPacketGuildTribute);
|
||||
}
|
||||
|
||||
safe_delete(inst);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (m_inv[EQ::invslot::GUILD_TRIBUTE_BEGIN]) {
|
||||
DeleteItemInInventory(EQ::invslot::GUILD_TRIBUTE_BEGIN);
|
||||
}
|
||||
if (m_inv[EQ::invslot::GUILD_TRIBUTE_BEGIN + 1]) {
|
||||
DeleteItemInInventory(EQ::invslot::GUILD_TRIBUTE_BEGIN + 1);
|
||||
}
|
||||
}
|
||||
CalcBonuses();
|
||||
}
|
||||
|
||||
void Client::SendGuildActiveTributes(uint32 guild_id)
|
||||
{
|
||||
auto guild = guild_mgr.GetGuildByGuildID(guild_id);
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_GuildSendActiveTributes, sizeof(GuildTributeSendActive_Struct));
|
||||
auto gtsa = (GuildTributeSendActive_Struct *) outapp->pBuffer;
|
||||
|
||||
if (guild) {
|
||||
gtsa->guild_favor = guild->tribute.favor;
|
||||
gtsa->tribute_timer = guild->tribute.time_remaining;
|
||||
gtsa->tribute_enabled = guild->tribute.enabled;
|
||||
gtsa->tribute_id_1 = guild->tribute.id_1;
|
||||
gtsa->tribute_id_1_tier = guild->tribute.id_1_tier;
|
||||
gtsa->tribute_id_2 = guild->tribute.id_2;
|
||||
gtsa->tribute_id_2_tier = guild->tribute.id_2_tier;
|
||||
}
|
||||
else {
|
||||
gtsa->guild_favor = 0;
|
||||
gtsa->tribute_timer = 0;
|
||||
gtsa->tribute_enabled = 0;
|
||||
gtsa->tribute_id_1 = 0xffffffff;
|
||||
gtsa->tribute_id_1_tier = 0;
|
||||
gtsa->tribute_id_2 = 0xffffffff;
|
||||
gtsa->tribute_id_2_tier = 0;
|
||||
}
|
||||
|
||||
QueuePacket(outapp);
|
||||
safe_delete(outapp)
|
||||
}
|
||||
|
||||
void Client::SendGuildFavorAndTimer(uint32 guild_id)
|
||||
{
|
||||
auto guild = guild_mgr.GetGuildByGuildID(guild_id);
|
||||
|
||||
if (guild) {
|
||||
auto outapp = new EQApplicationPacket(OP_GuildTributeFavorAndTimer, sizeof(GuildTributeFavorTimer_Struct));
|
||||
auto gtsa = (GuildTributeFavorTimer_Struct *) outapp->pBuffer;
|
||||
|
||||
gtsa->guild_favor = guild->tribute.favor;
|
||||
gtsa->tribute_timer = guild->tribute.time_remaining;
|
||||
gtsa->trophy_timer = 0; //not yet implemented
|
||||
|
||||
QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
}
|
||||
|
||||
void Client::SendGuildTributeOptInToggle(const GuildTributeMemberToggle* in)
|
||||
{
|
||||
EQApplicationPacket* outapp = new EQApplicationPacket(OP_GuildOptInOut, sizeof(GuildTributeOptInOutReply_Struct));
|
||||
GuildTributeOptInOutReply_Struct* data = (GuildTributeOptInOutReply_Struct*)outapp->pBuffer;
|
||||
|
||||
strncpy(data->player_name, in->player_name, 64);
|
||||
data->guild_id = in->guild_id;
|
||||
data->no_donations = in->no_donations;
|
||||
data->tribute_toggle = in->tribute_toggle;
|
||||
data->tribute_trophy_toggle = 0; //not yet implemented
|
||||
data->time = time(nullptr);
|
||||
data->command = in->command;
|
||||
|
||||
QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
|
||||
void Client::RequestGuildActiveTributes(uint32 guild_id)
|
||||
{
|
||||
auto sp = new ServerPacket(ServerOP_RequestGuildActiveTributes, sizeof(GuildTributeUpdate));
|
||||
auto data = (GuildTributeUpdate *) sp->pBuffer;
|
||||
|
||||
data->guild_id = GuildID();
|
||||
|
||||
worldserver.SendPacket(sp);
|
||||
safe_delete(sp);
|
||||
}
|
||||
|
||||
void Client::RequestGuildFavorAndTimer(uint32 guild_id)
|
||||
{
|
||||
auto sp = new ServerPacket(ServerOP_RequestGuildFavorAndTimer, sizeof(GuildTributeUpdate));
|
||||
auto data = (GuildTributeUpdate *) sp->pBuffer;
|
||||
|
||||
data->guild_id = GuildID();
|
||||
|
||||
worldserver.SendPacket(sp);
|
||||
safe_delete(sp);
|
||||
}
|
||||
|
||||
void Client::SendGuildTributeDonateItemReply(GuildTributeDonateItemRequest_Struct* in, uint32 favor) {
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_GuildTributeDonateItem, sizeof(GuildTributeDonateItemReply_Struct));
|
||||
auto out = (GuildTributeDonateItemReply_Struct*)outapp->pBuffer;
|
||||
|
||||
out->type = in->type;
|
||||
out->slot = in->slot;
|
||||
out->aug_index = in->aug_index;
|
||||
out->sub_index = in->sub_index;
|
||||
out->quantity = in->quantity;
|
||||
out->unknown10 = in->unknown10;
|
||||
out->unknown20 = in->unknown20;
|
||||
out->favor = favor;
|
||||
|
||||
QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
|
||||
}
|
||||
|
||||
void Client::SendGuildTributeDonatePlatReply(GuildTributeDonatePlatRequest_Struct* in, uint32 favor) {
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_GuildTributeDonatePlat, sizeof(GuildTributeDonatePlatReply_Struct));
|
||||
auto out = (GuildTributeDonatePlatReply_Struct*)outapp->pBuffer;
|
||||
|
||||
out->favor = favor;
|
||||
out->quantity = in->quantity;
|
||||
|
||||
QueuePacket(outapp);
|
||||
safe_delete(outapp)
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
64.37.149.6:1353 == server
|
||||
66.90.221.245:3173 == client
|
||||
|
||||
|
||||
@@ -57,6 +57,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#include "dialogue_window.h"
|
||||
#include "bot_command.h"
|
||||
#include "../common/events/player_event_logs.h"
|
||||
#include "../common/repositories/guild_tributes_repository.h"
|
||||
|
||||
extern EntityList entity_list;
|
||||
extern Zone* zone;
|
||||
@@ -781,8 +782,18 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
|
||||
case ServerOP_DeleteGuild:
|
||||
case ServerOP_GuildCharRefresh:
|
||||
case ServerOP_GuildMemberUpdate:
|
||||
case ServerOP_GuildPermissionUpdate:
|
||||
case ServerOP_GuildRankUpdate:
|
||||
case ServerOP_GuildRankNameChange:
|
||||
case ServerOP_LFGuildUpdate:
|
||||
case ServerOP_GuildMemberLevelUpdate:
|
||||
case ServerOP_GuildMemberPublicNote:
|
||||
case ServerOP_GuildChannel:
|
||||
case ServerOP_GuildURL:
|
||||
case ServerOP_GuildMemberRemove:
|
||||
case ServerOP_GuildMemberAdd:
|
||||
case ServerOP_GuildSendGuildList:
|
||||
case ServerOP_GuildMembersList:
|
||||
{
|
||||
guild_mgr.ProcessWorldPacket(pack);
|
||||
break;
|
||||
@@ -3613,6 +3624,225 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
|
||||
DataBucket::HandleWorldMessage(pack);
|
||||
break;
|
||||
}
|
||||
case ServerOP_GuildTributeUpdate: {
|
||||
GuildTributeUpdate* in = (GuildTributeUpdate*)pack->pBuffer;
|
||||
|
||||
auto guild = guild_mgr.GetGuildByGuildID(in->guild_id);
|
||||
if (guild) {
|
||||
guild->tribute.favor = in->favor;
|
||||
guild->tribute.id_1 = in->tribute_id_1;
|
||||
guild->tribute.id_2 = in->tribute_id_2;
|
||||
guild->tribute.id_1_tier = in->tribute_id_1_tier;
|
||||
guild->tribute.id_2_tier = in->tribute_id_2_tier;
|
||||
guild->tribute.time_remaining = in->time_remaining;
|
||||
guild->tribute.enabled = in->enabled;
|
||||
}
|
||||
EQApplicationPacket* outapp = new EQApplicationPacket(OP_GuildSendActiveTributes, sizeof(GuildTributeSendActive_Struct));
|
||||
GuildTributeSendActive_Struct* out = (GuildTributeSendActive_Struct*)outapp->pBuffer;
|
||||
|
||||
out->not_used = in->guild_id;
|
||||
out->guild_favor = in->favor;
|
||||
out->tribute_enabled = in->enabled;
|
||||
out->tribute_timer = in->time_remaining;
|
||||
out->tribute_id_1 = in->tribute_id_1;
|
||||
out->tribute_id_2 = in->tribute_id_2;
|
||||
out->tribute_id_1_tier = in->tribute_id_1_tier;
|
||||
out->tribute_id_2_tier = in->tribute_id_2_tier;
|
||||
|
||||
entity_list.QueueClientsGuild(outapp, in->guild_id);
|
||||
safe_delete(outapp);
|
||||
break;
|
||||
}
|
||||
case ServerOP_GuildTributeActivate: {
|
||||
GuildTributeUpdate* in = (GuildTributeUpdate*)pack->pBuffer;
|
||||
|
||||
auto guild = guild_mgr.GetGuildByGuildID(in->guild_id);
|
||||
if (guild) {
|
||||
guild->tribute.favor = in->favor;
|
||||
guild->tribute.id_1 = in->tribute_id_1;
|
||||
guild->tribute.id_2 = in->tribute_id_2;
|
||||
guild->tribute.id_1_tier = in->tribute_id_1_tier;
|
||||
guild->tribute.id_2_tier = in->tribute_id_2_tier;
|
||||
guild->tribute.time_remaining = in->time_remaining;
|
||||
guild->tribute.enabled = in->enabled;
|
||||
}
|
||||
|
||||
EQApplicationPacket* outapp = new EQApplicationPacket(OP_GuildTributeToggleReply, sizeof(GuildTributeSendActive_Struct));
|
||||
GuildTributeSendActive_Struct* out = (GuildTributeSendActive_Struct*)outapp->pBuffer;
|
||||
|
||||
out->not_used = in->guild_id;
|
||||
out->guild_favor = in->favor;
|
||||
out->tribute_enabled = in->enabled;
|
||||
out->tribute_timer = in->time_remaining;
|
||||
out->tribute_id_1 = in->tribute_id_1;
|
||||
out->tribute_id_2 = in->tribute_id_2;
|
||||
out->tribute_id_1_tier = in->tribute_id_1_tier;
|
||||
out->tribute_id_2_tier = in->tribute_id_2_tier;
|
||||
|
||||
entity_list.QueueClientsGuild(outapp, in->guild_id);
|
||||
safe_delete(outapp);
|
||||
|
||||
for (auto& c : entity_list.GetClientList()) {
|
||||
if (c.second->IsInGuild(in->guild_id)) {
|
||||
c.second->DoGuildTributeUpdate();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ServerOP_GuildTributeUpdateDonations:
|
||||
{
|
||||
GuildTributeUpdate* in = (GuildTributeUpdate*)pack->pBuffer;
|
||||
|
||||
EQApplicationPacket* outapp = new EQApplicationPacket(OP_GuildOptInOut, sizeof(GuildTributeOptInOutReply_Struct));
|
||||
GuildTributeOptInOutReply_Struct* data = (GuildTributeOptInOutReply_Struct*)outapp->pBuffer;
|
||||
|
||||
data->guild_id = in->guild_id;
|
||||
strn0cpy(data->player_name, in->player_name, sizeof(data->player_name));
|
||||
data->no_donations = in->member_favor;
|
||||
data->tribute_toggle = in->member_enabled ? true : false;
|
||||
data->tribute_trophy_toggle = 0; //not yet implemented
|
||||
data->time = in->member_time;
|
||||
data->command = 1;
|
||||
|
||||
entity_list.QueueClientsGuild(outapp, in->guild_id);
|
||||
safe_delete(outapp);
|
||||
|
||||
//my new items
|
||||
outapp = new EQApplicationPacket(OP_GuildTributeToggleReply, sizeof(GuildTributeSendActive_Struct));
|
||||
GuildTributeSendActive_Struct *out = (GuildTributeSendActive_Struct *) outapp->pBuffer;
|
||||
|
||||
auto guild = guild_mgr.GetGuildByGuildID(in->guild_id);
|
||||
out->not_used = in->guild_id;
|
||||
out->guild_favor = guild->tribute.favor;
|
||||
out->tribute_enabled = guild->tribute.enabled;
|
||||
out->tribute_timer = guild->tribute.time_remaining;
|
||||
out->tribute_id_1 = guild->tribute.id_1;
|
||||
out->tribute_id_2 = guild->tribute.id_2;
|
||||
out->tribute_id_1_tier = guild->tribute.id_1_tier;
|
||||
out->tribute_id_2_tier = guild->tribute.id_2_tier;
|
||||
|
||||
entity_list.QueueClientsGuild(outapp, in->guild_id);
|
||||
safe_delete(outapp)
|
||||
|
||||
break;
|
||||
}
|
||||
case ServerOP_GuildTributeOptInToggle:
|
||||
{
|
||||
GuildTributeMemberToggle* in = (GuildTributeMemberToggle*)pack->pBuffer;
|
||||
|
||||
EQApplicationPacket* outapp = new EQApplicationPacket(OP_GuildOptInOut, sizeof(GuildTributeOptInOutReply_Struct));
|
||||
GuildTributeOptInOutReply_Struct* data = (GuildTributeOptInOutReply_Struct*)outapp->pBuffer;
|
||||
|
||||
data->guild_id = in->guild_id;
|
||||
strn0cpy(data->player_name, in->player_name, sizeof(data->player_name));
|
||||
data->no_donations = in->no_donations;
|
||||
data->tribute_toggle = in->tribute_toggle ? true : false;
|
||||
data->tribute_trophy_toggle = 0; //not yet implemented
|
||||
data->time = in->member_last_donated;
|
||||
data->command = in->command;
|
||||
|
||||
entity_list.QueueClientsGuild(outapp, in->guild_id);
|
||||
safe_delete(outapp);
|
||||
|
||||
auto guild = guild_mgr.GetGuildByGuildID(in->guild_id);
|
||||
auto client = entity_list.GetClientByCharID(in->char_id);
|
||||
if (guild && client) {
|
||||
client->SetGuildTributeOptIn(in->tribute_toggle ? true : false);
|
||||
|
||||
EQApplicationPacket* outapp = new EQApplicationPacket(OP_GuildTributeToggleReply, sizeof(GuildTributeSendActive_Struct));
|
||||
GuildTributeSendActive_Struct* out = (GuildTributeSendActive_Struct*)outapp->pBuffer;
|
||||
|
||||
out->not_used = in->guild_id;
|
||||
out->guild_favor = guild->tribute.favor;
|
||||
out->tribute_enabled = guild->tribute.enabled;
|
||||
out->tribute_timer = guild->tribute.time_remaining;
|
||||
out->tribute_id_1 = guild->tribute.id_1;
|
||||
out->tribute_id_2 = guild->tribute.id_2;
|
||||
out->tribute_id_1_tier = guild->tribute.id_1_tier;
|
||||
out->tribute_id_2_tier = guild->tribute.id_2_tier;
|
||||
client->QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
//send deactivate and then activate
|
||||
|
||||
client->DoGuildTributeUpdate();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case ServerOP_GuildTributeFavAndTimer:
|
||||
{
|
||||
GuildTributeFavorTimer_Struct* in = (GuildTributeFavorTimer_Struct*)pack->pBuffer;
|
||||
|
||||
auto guild = guild_mgr.GetGuildByGuildID(in->guild_id);
|
||||
if (guild) {
|
||||
guild->tribute.favor = in->guild_favor;
|
||||
guild->tribute.time_remaining = in->tribute_timer;
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_GuildTributeFavorAndTimer, sizeof(GuildTributeFavorTimer_Struct));
|
||||
GuildTributeFavorTimer_Struct* gtsa = (GuildTributeFavorTimer_Struct*)outapp->pBuffer;
|
||||
|
||||
gtsa->guild_id = in->guild_id;
|
||||
gtsa->guild_favor = guild->tribute.favor;
|
||||
gtsa->tribute_timer = guild->tribute.time_remaining;
|
||||
gtsa->trophy_timer = 0; //not yet implemented
|
||||
|
||||
entity_list.QueueClientsGuild(outapp, in->guild_id);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ServerOP_RequestGuildActiveTributes:
|
||||
{
|
||||
GuildTributeUpdate* in = (GuildTributeUpdate*)pack->pBuffer;
|
||||
auto guild = guild_mgr.GetGuildByGuildID(in->guild_id);
|
||||
|
||||
if (guild) {
|
||||
auto outapp = new EQApplicationPacket(OP_GuildSendActiveTributes, sizeof(GuildTributeSendActive_Struct));
|
||||
GuildTributeSendActive_Struct* gtsa = (GuildTributeSendActive_Struct*)outapp->pBuffer;
|
||||
|
||||
guild->tribute.enabled = in->enabled;
|
||||
guild->tribute.favor = in->favor;
|
||||
guild->tribute.id_1 = in->tribute_id_1;
|
||||
guild->tribute.id_2 = in->tribute_id_2;
|
||||
guild->tribute.id_1_tier = in->tribute_id_1_tier;
|
||||
guild->tribute.id_2_tier = in->tribute_id_2_tier;
|
||||
guild->tribute.time_remaining = in->time_remaining;
|
||||
|
||||
gtsa->guild_favor = guild->tribute.favor;
|
||||
gtsa->tribute_timer = guild->tribute.time_remaining;
|
||||
gtsa->tribute_enabled = guild->tribute.enabled;
|
||||
gtsa->tribute_id_1 = guild->tribute.id_1;
|
||||
gtsa->tribute_id_1_tier = guild->tribute.id_1_tier;
|
||||
gtsa->tribute_id_2 = guild->tribute.id_2;
|
||||
gtsa->tribute_id_2_tier = guild->tribute.id_2_tier;
|
||||
|
||||
entity_list.QueueClientsGuild(outapp, in->guild_id);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ServerOP_RequestGuildFavorAndTimer:
|
||||
{
|
||||
GuildTributeFavorTimer_Struct* in = (GuildTributeFavorTimer_Struct*)pack->pBuffer;
|
||||
|
||||
auto guild = guild_mgr.GetGuildByGuildID(in->guild_id);
|
||||
if (guild) {
|
||||
guild->tribute.favor = in->guild_favor;
|
||||
guild->tribute.time_remaining = in->tribute_timer;
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_GuildTributeFavorAndTimer, sizeof(GuildTributeFavorTimer_Struct));
|
||||
GuildTributeFavorTimer_Struct* gtsa = (GuildTributeFavorTimer_Struct*)outapp->pBuffer;
|
||||
|
||||
gtsa->guild_id = in->guild_id;
|
||||
gtsa->guild_favor = guild->tribute.favor;
|
||||
gtsa->tribute_timer = guild->tribute.time_remaining;
|
||||
gtsa->trophy_timer = 0; //not yet implemented
|
||||
|
||||
entity_list.QueueClientsGuild(outapp, in->guild_id);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LogInfo("Unknown ZS Opcode [{}] size [{}]", (int)pack->opcode, pack->size);
|
||||
break;
|
||||
|
||||
@@ -1203,6 +1203,8 @@ bool Zone::Init(bool is_static) {
|
||||
DynamicZone::CacheAllFromDatabase();
|
||||
Expedition::CacheAllFromDatabase();
|
||||
|
||||
guild_mgr.LoadGuilds();
|
||||
|
||||
LogInfo("Loading timezone data");
|
||||
zone_time.setEQTimeZone(content_db.GetZoneTimezone(zoneid, GetInstanceVersion()));
|
||||
|
||||
|
||||
Executable → Regular
Reference in New Issue
Block a user