[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:
Mitch Freeman
2024-02-10 05:27:58 -04:00
committed by GitHub
parent dacebca9dd
commit 91f5932c6d
80 changed files with 8152 additions and 2463 deletions
+11
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+8 -1
View File
@@ -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);
+13
View File
@@ -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
View File
@@ -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
View File
@@ -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);
+5
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+20 -4
View File
@@ -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
View File
@@ -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
View File
@@ -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)),
+1
View File
@@ -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
View File
@@ -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();
+2
View File
@@ -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
View File
@@ -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;
+3
View File
@@ -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
View File
@@ -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
+230
View File
@@ -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;
+2
View File
@@ -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
View File