[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
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
80 changed files with 8152 additions and 2463 deletions

View File

@ -222,6 +222,9 @@ SET(repositories
repositories/base/base_group_leaders_repository.h
repositories/base/base_guilds_repository.h
repositories/base/base_guild_ranks_repository.h
repositories/base/base_guild_permissions_repository.h
repositories/base/base_guild_members_repository.h
repositories/base/base_guild_bank_repository.h
repositories/base/base_guild_relations_repository.h
repositories/base/base_horses_repository.h
repositories/base/base_instance_list_repository.h
@ -399,6 +402,9 @@ SET(repositories
repositories/group_leaders_repository.h
repositories/guilds_repository.h
repositories/guild_ranks_repository.h
repositories/guild_permissions_repository.h
repositories/guild_members_repository.h
repositories/guild_bank_repository.h
repositories/guild_relations_repository.h
repositories/horses_repository.h
repositories/instance_list_repository.h

View File

@ -4844,7 +4844,7 @@ UPDATE data_buckets SET bot_id = SUBSTRING_INDEX(SUBSTRING_INDEX( `key`, '-', 2
ADD COLUMN `marked_npc_3_zone_id` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `marked_npc_3_entity_id`,
ADD COLUMN `marked_npc_3_instance_id` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `marked_npc_3_zone_id`;
)"
},
},
ManifestEntry{
.version = 9235,
.description = "2023_07_31_character_stats_record.sql",
@ -5284,7 +5284,68 @@ ADD COLUMN `gm_exp` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `rez_time`,
ADD COLUMN `killed_by` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `gm_exp`,
ADD COLUMN `rezzable` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 AFTER `killed_by`;
)"
}
},
ManifestEntry{
.version = 9260,
.description = "2023_11_11_guild_features.sql",
.check = "SHOW TABLES LIKE 'guild_permissions'",
.condition = "empty",
.match = "",
.sql = R"(
CREATE TABLE `guild_permissions` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`perm_id` INT(11) NOT NULL DEFAULT '0',
`guild_id` INT(11) NOT NULL DEFAULT '0',
`permission` INT(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `perm_id_guild_id` (`perm_id`, `guild_id`) USING BTREE
)
ENGINE=InnoDB
AUTO_INCREMENT=1;
UPDATE guild_ranks SET title = 'Leader' WHERE `rank` = '1';
UPDATE guild_ranks SET title = 'Senior Officer' WHERE `rank` = '2';
UPDATE guild_ranks SET title = 'Officer' WHERE `rank` = '3';
UPDATE guild_ranks SET title = 'Senior Member' WHERE `rank` = '4';
UPDATE guild_ranks SET title = 'Member' WHERE `rank` = '5';
UPDATE guild_ranks SET title = 'Junior Member' WHERE `rank` = '6';
UPDATE guild_ranks SET title = 'Initiate' WHERE `rank` = '7';
UPDATE guild_ranks SET title = 'Recruit' WHERE `rank` = '8';
DELETE FROM guild_ranks WHERE `rank` = 0;
ALTER TABLE `guild_ranks`
DROP COLUMN `can_hear`,
DROP COLUMN `can_speak`,
DROP COLUMN `can_invite`,
DROP COLUMN `can_remove`,
DROP COLUMN `can_promote`,
DROP COLUMN `can_demote`,
DROP COLUMN `can_motd`,
DROP COLUMN `can_warpeace`;
UPDATE guild_members SET `rank` = '5' WHERE `rank` = '0';
UPDATE guild_members SET `rank` = '3' WHERE `rank` = '1';
UPDATE guild_members SET `rank` = '1' WHERE `rank` = '2';
ALTER TABLE `guild_members`
ADD COLUMN `online` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0' AFTER `alt`;
ALTER TABLE `guilds`
ADD COLUMN `favor` INT(10) UNSIGNED NOT NULL DEFAULT '0' AFTER `url`;
CREATE TABLE guild_tributes (
guild_id int(11) unsigned NOT NULL DEFAULT 0,
tribute_id_1 int(11) unsigned NOT NULL DEFAULT 0,
tribute_id_1_tier int(11) unsigned NOT NULL DEFAULT 0,
tribute_id_2 int(11) unsigned NOT NULL DEFAULT 0,
tribute_id_2_tier int(11) unsigned NOT NULL DEFAULT 0,
time_remaining int(11) unsigned NOT NULL DEFAULT 0,
enabled int(11) unsigned NOT NULL DEFAULT 0,
PRIMARY KEY (guild_id) USING BTREE
) ENGINE=InnoDB;
)"
},
// -- template; copy/paste this when you need to create a new entry
// ManifestEntry{
// .version = 9228,

View File

@ -148,6 +148,7 @@ namespace DatabaseSchema {
"guild_members",
"guild_ranks",
"guild_relations",
"guild_tributes",
"guilds",
"instance_list_player",
"inventory",

View File

@ -228,6 +228,7 @@ N(OP_GuildBank),
N(OP_GuildBankItemList),
N(OP_GuildCreate),
N(OP_GuildDelete),
N(OP_GuildDeleteGuild),
N(OP_GuildDemote),
N(OP_GuildInvite),
N(OP_GuildInviteAccept),
@ -239,15 +240,33 @@ N(OP_GuildManageStatus),
N(OP_GuildMemberLevelUpdate),
N(OP_GuildMemberList),
N(OP_GuildMemberUpdate),
N(OP_GuildMemberLevel),
N(OP_GuildMemberRankAltBanker),
N(OP_GuildMemberPublicNote),
N(OP_GuildMemberAdd),
N(OP_GuildMemberRename),
N(OP_GuildMemberDelete),
N(OP_GuildMemberDetails),
N(OP_GuildRenameGuild),
N(OP_GuildMOTD),
N(OP_GuildPeace),
N(OP_GuildPromote),
N(OP_GuildPublicNote),
N(OP_GuildRemove),
N(OP_GuildSelectTribute),
N(OP_GuildModifyBenefits),
N(OP_GuildTributeToggleReq),
N(OP_GuildTributeToggleReply),
N(OP_GuildOptInOut),
N(OP_GuildSaveActiveTributes),
N(OP_GuildSendActiveTributes),
N(OP_GuildTributeFavorAndTimer),
N(OP_GuildsList),
N(OP_GuildStatus),
N(OP_GuildTributeInfo),
N(OP_GuildUpdateURLAndChannel),
N(OP_GuildUpdate),
N(OP_GuildTributeDonateItem),
N(OP_GuildTributeDonatePlat),
N(OP_GuildWar),
N(OP_Heartbeat),
N(OP_Hide),
@ -425,6 +444,7 @@ N(OP_ReqClientSpawn),
N(OP_ReqNewZone),
N(OP_RequestClientZoneChange),
N(OP_RequestDuel),
N(OP_RequestGuildTributes),
N(OP_RequestKnowledgeBase),
N(OP_RequestTitles),
N(OP_RespawnWindow),

View File

@ -314,6 +314,7 @@ union
uint32 DestructibleUnk9;
bool targetable_with_hotkey;
bool show_name;
bool guild_show;
};
struct PlayerState_Struct {
@ -1677,6 +1678,68 @@ struct GuildUpdate_Struct {
GuildsListEntry_Struct entry;
};
struct GuildMemberAdd_Struct {
/*000*/ uint32 guild_id;
/*004*/ uint32 unknown04;
/*008*/ uint32 unknown08;
/*012*/ uint32 unknown12;
/*016*/ uint32 level;
/*020*/ uint32 class_;
/*024*/ uint32 rank_;
/*028*/ uint32 guild_show;
/*032*/ uint32 zone_id;
/*036*/ uint32 last_on;
/*040*/ char player_name[64];
};
struct GuildMemberLevel_Struct {
/*000*/ uint32 guild_id;
/*004*/ char player_name[64];
/*068*/ uint32 level;
};
struct GuildMemberRank_Struct {
/*000*/ uint32 guild_id;
/*004*/ uint32 rank_;
/*008*/ char player_name[64];
/*072*/ uint32 alt_banker; //Banker/Alt bit 00 - none 10 - Alt 11 - Alt and Banker 01 - Banker. Banker not functional for RoF2+
/*076*/ uint32 offline;
};
struct GuildMemberPublicNote_Struct {
/*000*/ uint32 guild_id;
/*004*/ char player_name[64];
/*068*/ char public_note[256]; //RoF2 256
};
struct GuildDelete_Struct {
/*000*/ uint32 guild_id;
};
struct GuildRenameGuild_Struct {
/*000*/ uint32 guild_id;
/*004*/ char new_guild_name[64];
};
struct GuildRenameMember_Struct {
/*000*/ uint32 guild_id;
/*004*/ char player_name[64];
/*068*/ char new_player_name[64];
};
struct GuildMemberDetails_Struct {
/*000*/ uint32 guild_id;
/*004*/ char player_name[64];
/*068*/ uint32 zone_id;
/*072*/ uint32 last_on;
/*076*/ uint32 offline_mode; //1 Offline
};
struct GuildMemberDelete_Struct {
/*000*/ uint32 guild_id;
/*004*/ char player_name[64];
};
/*
** Money Loot
** Length: 22 Bytes
@ -1725,10 +1788,10 @@ struct GuildJoin_Struct{
/*092*/
};
struct GuildInviteAccept_Struct {
char inviter[64];
char newmember[64];
char inviter[64];
char new_member[64];
uint32 response;
uint32 guildeqid;
uint32 guild_id;
};
struct GuildManageRemove_Struct {
uint32 guildeqid;
@ -1760,6 +1823,14 @@ struct PopupResponse_Struct {
/*0004*/ uint32 popupid;
};
enum GuildInformationActions
{
GuildUpdateURL = 0,
GuildUpdateChannel = 1,
GuildUpdateRanks = 4,
GuildUpdatePermissions = 5
};
struct GuildManageBanker_Struct {
uint32 unknown0;
char myname[64];
@ -1773,9 +1844,9 @@ struct GuildSetRank_Struct
{
/*00*/ uint32 Unknown00;
/*04*/ uint32 Unknown04;
/*08*/ uint32 Rank;
/*12*/ char MemberName[64];
/*76*/ uint32 Banker;
/*08*/ uint32 rank;
/*12*/ char member_name[64];
/*76*/ uint32 banker;
/*80*/
};
@ -3333,6 +3404,7 @@ struct Internal_GuildMemberEntry_Struct {
// char public_note[1]; //variable length.
uint16 zoneinstance; //network byte order
uint16 zone_id; //network byte order
uint32 online;
};
struct Internal_GuildMembers_Struct { //just for display purposes, this is not actually used in the message encoding.
@ -3359,7 +3431,42 @@ struct GuildUpdate_PublicNote{
uint32 unknown0;
char name[64];
char target[64];
char note[1]; //variable length.
char note[256];
};
struct GuildUpdateURLAndChannelStruct {
char text[512];
};
struct GuildUpdatePermissionsStruct {
uint32 rank; // the rank that is being changed
uint32 function_id; // the id of the guild function
uint32 value; // 1 is on, 0 is off
};
struct GuildUpdateRankNamesStruct {
uint32 rank; // the rank that is being updated
char rank_name[76]; // the rank name
};
struct GuildUpdateUCPStruct {
uint32 action; // 0 and 1 use url and channel payload. 5 uses permissions payload
char unknown[76];
union {
GuildUpdateURLAndChannelStruct url_channel;
GuildUpdatePermissionsStruct permissions;
GuildUpdateRankNamesStruct rank_name;
}payload;
};
struct GuildPermission_Struct
{
uint32 Action; // 5 = Update function permission
char Unknown0004[76]; // not used
uint32 rank; // the rank that is being changed
uint32 function_id; // the id of the guild function
uint32 value; // 1 is on, 0 is off
};
struct GuildUpdateURLAndChannel_Struct
@ -3378,7 +3485,7 @@ struct GuildUpdateURLAndChannel_Struct
//The client sends this struct on changing a guild rank. The server sends each rank in 32 or less packets upon zonein if you are in a guild.
struct GuildUpdateRanks_Struct
{
/*0000*/ uint32 Action; // 0 = Update URL, 1 = Update Channel, 5 = RoF Ranks
/*0000*/ uint32 Action; // 0 = Update URL, 1 = Update Channel, 4 = Ranks 5 = Permissions
/*0004*/ uint32 Unknown0004; //Seen 00 00 00 00
/*0008*/ uint32 Unknown0008; //Seen 96 29 00 00
/*0008*/ char Unknown0012[64]; //Seen "CharacterName"
@ -3400,6 +3507,7 @@ struct GuildStatus_Struct
struct GuildDemoteStruct{
char name[64];
char target[64];
uint32 rank;
};
struct GuildRemoveStruct{
@ -3409,9 +3517,9 @@ struct GuildRemoveStruct{
uint32 leaderstatus; //?
};
struct GuildMakeLeader{
char name[64];
char target[64];
struct GuildMakeLeader_Struct{
char requestor[64];
char new_leader[64];
};
struct BugReport_Struct {
@ -3505,66 +3613,193 @@ struct ZoneInSendName_Struct2 {
static const uint32 MAX_TRIBUTE_TIERS = 10;
struct StartTribute_Struct {
uint32 client_id;
uint32 tribute_master_id;
uint32 response;
uint32 client_id;
uint32 tribute_master_id;
uint32 response;
};
struct TributeLevel_Struct {
uint32 level; //backwards byte order!
uint32 tribute_item_id; //backwards byte order!
uint32 cost; //backwards byte order!
uint32 level; //backwards byte order!
uint32 tribute_item_id; //backwards byte order!
uint32 cost; //backwards byte order!
};
struct TributeAbility_Struct {
uint32 tribute_id; //backwards byte order!
uint32 tier_count; //backwards byte order!
uint32 tribute_id; //backwards byte order!
uint32 tier_count; //backwards byte order!
TributeLevel_Struct tiers[MAX_TRIBUTE_TIERS];
char name[0];
};
struct GuildTributeAbility_Struct {
uint32 guild_id;
TributeAbility_Struct ability;
char name[0];
};
struct SelectTributeReq_Struct {
uint32 client_id; //? maybe action ID?
uint32 tribute_id;
uint32 unknown8; //seen E3 00 00 00
uint32 client_id; //? maybe action ID?
uint32 tribute_id;
uint32 unknown8; //seen E3 00 00 00
};
struct GuildTributeAbilityDetail_Struct {
uint32 tribute_id; //backwards byte order!
uint32 tier_count; //backwards byte order!
TributeLevel_Struct tiers[MAX_TRIBUTE_TIERS];
uint32 unknown132;
char name[0];
};
struct GuildTributeAbility_Struct {
uint32 guild_id;
GuildTributeAbilityDetail_Struct ability;
};
struct GuildTributeSelectReq_Struct {
uint32 tribute_id;
uint32 tier;
uint32 tribute_id2;
uint32 unknown12; //seen A7 01 00 00
};
struct GuildTributeSelectReply_Struct {
uint32 tribute_id;
uint32 tier;
uint32 tribute_id2;
char description;
};
struct GuildTributeModifyBenefits_Struct {
/*000*/uint32 command;
/*004*/uint32 data;
/*008*/char unknown8[12];
/*020*/uint32 tribute_master_id;
/*024*/uint32 tribute_id_1;
/*028*/uint32 tribute_id_2;
/*032*/uint32 tribute_id_1_tier;
/*036*/uint32 tribute_id_2_tier;
/*040*/char unknown[40];
};
struct GuildTributeOptInOutReq_Struct {
/*000*/uint32 guild_id;
/*004*/uint32 tribute_toggle;
/*008*/char player[64];
/*072*/uint32 command;
/*076*/uint32 tribute_master_id;
};
struct GuildTributeOptInOutReply_Struct {
/*000*/uint32 guild_id;
/*004*/char player_name[64];
/*068*/uint32 tribute_toggle;// 0 off 1 on
/*072*/uint32 tribute_trophy_toggle;// 0 off 1 on not yet implemented
/*076*/uint32 no_donations;
/*080*/uint32 time;
/*084*/uint32 command;
};
struct GuildTributeSaveActive_Struct {
/*000*/ uint32 command;
/*004*/ char unknown04[16];
/*020*/ uint32 master_tribute_id;
/*024*/ uint32 tribute_id_1;
/*028*/ uint32 tribute_id_2;
/*032*/ uint32 tribute_1_tier;
/*036*/ uint32 tribute_2_tier;
/*040*/ char unknown40[8];
};
struct GuildTributeFavorTimer_Struct {
/*000*/ uint32 guild_id;
/*004*/ uint32 guild_favor;
/*008*/ uint32 tribute_timer;
/*012*/ uint32 trophy_timer;
};
struct GuildTributeSendActive_Struct {
/*000*/ uint32 not_used;
/*004*/ uint32 guild_favor;
/*008*/ uint32 tribute_timer;
/*012*/ uint32 tribute_enabled;
/*016*/ char unknown16[8];
/*024*/ uint32 tribute_id_1;
/*028*/ uint32 tribute_id_2;
/*032*/ uint32 tribute_id_1_tier;
/*036*/ uint32 tribute_id_2_tier;
};
struct GuildTributeToggleReq_Struct {
/*000*/ uint32 command;
/*004*/ uint32 unknown4;
/*008*/ uint32 unknown8;
};
struct GuildTributeDonateItemRequest_Struct {
/*000*/ uint32 type;
/*004*/ uint16 slot;
/*006*/ uint16 sub_index;
/*008*/ uint16 aug_index;
/*010*/ uint16 unknown10;
/*012*/ uint32 quantity;
/*016*/ uint32 tribute_master_id;
/*020*/ uint32 unknown20;
/*024*/ uint32 guild_id;
/*028*/ uint32 unknown28;
/*032*/ uint32 unknown32;
};
struct GuildTributeDonateItemReply_Struct {
/*000*/ uint32 type;
/*004*/ uint16 slot;
/*006*/ uint16 sub_index;
/*008*/ uint16 aug_index;
/*010*/ uint16 unknown10;
/*012*/ uint32 quantity;
/*016*/ uint32 unknown20;
/*020*/ uint32 favor;
};
struct GuildTributeDonatePlatRequest_Struct {
/*000*/ uint32 quantity;
/*004*/ uint32 tribute_master_id;
/*008*/ uint32 unknown08;
/*012*/ uint32 guild_id;
/*016*/ uint32 unknown16;
};
struct GuildTributeDonatePlatReply_Struct {
/*000*/ uint32 quantity;
/*004*/ uint32 unknown4;
/*008*/ uint32 favor;
};
struct SelectTributeReply_Struct {
uint32 client_id; //echoed from request.
uint32 tribute_id;
char desc[0];
uint32 client_id; //echoed from request.
uint32 tribute_id;
char description[0];
};
struct TributeInfo_Struct {
uint32 active; //0 == inactive, 1 == active
uint32 tributes[EQ::invtype::TRIBUTE_SIZE]; //-1 == NONE
uint32 tiers[EQ::invtype::TRIBUTE_SIZE]; //all 00's
uint32 tribute_master_id;
uint32 active; //0 == inactive, 1 == active
uint32 tributes[EQ::invtype::TRIBUTE_SIZE]; //-1 == NONE
uint32 tiers[EQ::invtype::TRIBUTE_SIZE]; //all 00's
uint32 tribute_master_id;
};
struct TributeItem_Struct {
uint32 slot;
uint32 quantity;
uint32 tribute_master_id;
int32 tribute_points;
uint32 slot;
uint32 quantity;
uint32 tribute_master_id;
int32 tribute_points;
};
struct TributePoint_Struct {
int32 tribute_points;
uint32 unknown04;
int32 career_tribute_points;
uint32 unknown12;
int32 tribute_points;
uint32 unknown04;
int32 career_tribute_points;
uint32 unknown12;
};
struct TributeMoney_Struct {
uint32 platinum;
uint32 tribute_master_id;
int32 tribute_points;
uint32 platinum;
uint32 tribute_master_id;
int32 tribute_points;
};

View File

@ -697,6 +697,8 @@ void PlayerEventLogs::SetSettingsDefaults()
m_settings[PlayerEvent::KILLED_NAMED_NPC].event_enabled = 1;
m_settings[PlayerEvent::KILLED_RAID_NPC].event_enabled = 1;
m_settings[PlayerEvent::ITEM_CREATION].event_enabled = 1;
m_settings[PlayerEvent::GUILD_TRIBUTE_DONATE_ITEM].event_enabled = 1;
m_settings[PlayerEvent::GUILD_TRIBUTE_DONATE_PLAT].event_enabled = 1;
for (int i = PlayerEvent::GM_COMMAND; i != PlayerEvent::MAX; i++) {
m_settings[i].retention_days = RETENTION_DAYS_DEFAULT;

View File

@ -56,6 +56,8 @@ namespace PlayerEvent {
KILLED_NAMED_NPC,
KILLED_RAID_NPC,
ITEM_CREATION,
GUILD_TRIBUTE_DONATE_ITEM,
GUILD_TRIBUTE_DONATE_PLAT,
MAX // dont remove
};
@ -112,7 +114,9 @@ namespace PlayerEvent {
"Killed NPC",
"Killed Named NPC",
"Killed Raid NPC",
"Item Creation"
"Item Creation",
"Guild Tribute Donate Item",
"Guild Tribute Donate Platinum"
};
// Generic struct used by all events
@ -942,6 +946,36 @@ namespace PlayerEvent {
);
}
};
struct GuildTributeDonateItem {
uint32 item_id;
uint32 guild_favor;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(item_id),
CEREAL_NVP(guild_favor)
);
}
};
struct GuildTributeDonatePlat {
uint32 plat;
uint32 guild_favor;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(plat),
CEREAL_NVP(guild_favor)
);
}
};
}
#endif //EQEMU_PLAYER_EVENTS_H

File diff suppressed because it is too large Load Diff

View File

@ -5,6 +5,42 @@
#include <map>
#include <string>
#include <vector>
#include "timer.h"
#include "../common/repositories/guild_members_repository.h"
#include "../common/repositories/guilds_repository.h"
struct DefaultPermissionStruct {
GuildAction id;
uint32 value;
};
struct DefaultRankNamesStruct {
uint32 id;
std::string name;
};
struct GuildTributeStruct {
Timer timer;
uint32 id_1;
uint32 id_2;
uint32 id_1_tier;
uint32 id_2_tier;
uint32 favor;
uint32 time_remaining;
uint32 enabled;
bool send_timer;
};
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
};
class Database;
@ -12,22 +48,23 @@ class CharGuildInfo
{
public:
//fields from `characer_`
uint32 char_id;
uint32 char_id;
std::string char_name;
uint8 class_;
uint16 level;
uint32 time_last_on;
uint32 zone_id;
uint8 class_;
uint16 level;
uint32 time_last_on;
uint32 zone_id;
//fields from `guild_members`
uint32 guild_id;
uint8 rank;
bool tribute_enable;
uint32 total_tribute;
uint32 last_tribute; //timestamp
bool banker;
bool alt;
uint32 guild_id;
uint8 rank;
bool tribute_enable;
uint32 total_tribute;
uint32 last_tribute; //timestamp
bool banker;
bool alt;
std::string public_note;
bool online;
};
//this object holds guild functionality shared between world and zone.
@ -44,15 +81,16 @@ class BaseGuildManager
}
bool LoadGuilds();
bool RefreshGuild(uint32 guild_id);
virtual bool RefreshGuild(uint32 guild_id);
//guild edit actions.
uint32 CreateGuild(const char* name, uint32 leader_char_id);
uint32 CreateGuild(std::string name, uint32 leader_char_id);
bool StoreGuildDB(uint32 guild_id);
bool DeleteGuild(uint32 guild_id);
bool RenameGuild(uint32 guild_id, const char* name);
bool SetGuildMOTD(uint32 guild_id, const char* motd, const char *setter);
bool SetGuildURL(uint32 GuildID, const char* URL);
bool SetGuildChannel(uint32 GuildID, const char* Channel);
bool RenameGuild(uint32 guild_id, std::string name);
bool SetGuildMOTD(uint32 guild_id, std::string motd, std::string setter);
bool SetGuildURL(uint32 guild_id, std::string URL);
bool SetGuildChannel(uint32 guild_id, std::string Channel);
//character edit actions
bool SetGuildLeader(uint32 guild_id, uint32 leader_char_id);
@ -62,9 +100,16 @@ class BaseGuildManager
bool ForceRankUpdate(uint32 charid);
bool GetAltFlag(uint32 CharID);
bool SetAltFlag(uint32 charid, bool is_alt);
bool GetBankerFlag(uint32 CharID);
bool GetBankerFlag(uint32 CharID, bool compat_mode = false);
bool GetGuildBankerStatus(uint32 guild_id, uint32 guild_rank);
bool SetTributeFlag(uint32 charid, bool enabled);
bool SetPublicNote(uint32 charid, const char *note);
bool SetPublicNote(uint32 charid, std::string public_note);
uint32 UpdateDbGuildFavor(uint32 guild_id, uint32 enabled);
bool UpdateDbGuildTributeEnabled(uint32 guild_id, uint32 enabled);
bool UpdateDbMemberTributeEnabled(uint32 guild_id, uint32 char_id, uint32 enabled);
bool UpdateDbTributeTimeRemaining(uint32 guild_id, uint32 enabled);
uint32 UpdateDbMemberFavor(uint32 guild_id, uint32 char_id, uint32 favor);
bool UpdateDbMemberOnline(uint32 char_id, bool status);
//queries
bool GetCharInfo(const char *char_name, CharGuildInfo &into);
@ -74,29 +119,24 @@ class BaseGuildManager
bool GetGuildMOTD(uint32 guild_id, char *motd_buffer, char *setter_buffer) const;
bool GetGuildURL(uint32 GuildID, char *URLBuffer) const;
bool GetGuildChannel(uint32 GuildID, char *ChannelBuffer) const;
const char *GetRankName(uint32 guild_id, uint8 rank) const;
const char *GetGuildName(uint32 guild_id) const;
std::string GetGuildNameByID(uint32 guild_id) const;
std::string GetGuildRankName(uint32 guild_id, uint8 rank) const;
bool IsCharacterInGuild(uint32 character_id, uint32 guild_id = 0);
bool GetGuildNameByID(uint32 guild_id, std::string &into) const;
uint32 GetGuildIDByName(const char *GuildName);
uint32 GetGuildIDByCharacterID(uint32 character_id);
bool IsGuildLeader(uint32 guild_id, uint32 char_id) const;
uint8 GetDisplayedRank(uint32 guild_id, uint8 rank, uint32 char_id) const;
bool CheckGMStatus(uint32 guild_id, uint8 status) const;
bool CheckPermission(uint32 guild_id, uint8 rank, GuildAction act) const;
// uint32 Getguild_id(uint32 eqid);
uint32 FindGuildByLeader(uint32 leader) const;
// void GetGuildMembers(uint32 guild_id,GuildMember_Struct* gms);
uint32 NumberInGuild(uint32 guild_id);
// bool GetGuildRanks(uint32 guildeqid, GuildRanks_Struct* gr);
// bool EditGuild(uint32 guild_id, uint8 ranknum, GuildRankLevel_Struct* grl);
uint8 *MakeGuildList(const char *head_name, uint32 &length) const; //make a guild list packet, returns ownership of the buffer.
static const char *const GuildActionNames[_MaxGuildAction];
uint32 DoesAccountContainAGuildLeader(uint32 AccountID);
bool IsCharacterInGuild(uint32 character_id, uint32 guild_id = 0);
bool GetGuildNameByID(uint32 guild_id, std::string& into) const;
bool IsGuildLeader(uint32 guild_id, uint32 char_id) const;
bool CheckGMStatus(uint32 guild_id, uint8 status) const;
bool CheckPermission(uint32 guild_id, uint8 rank, GuildAction act) const;
bool UpdateDbBankerFlag(uint32 charid, bool is_banker);
uint8* MakeGuildList(const char* head_name, uint32& length) const; //make a guild list packet, returns ownership of the buffer.
uint8 GetDisplayedRank(uint32 guild_id, uint8 rank, uint32 char_id) const;
uint32 GetGuildIDByName(const char *GuildName);
uint32 GetGuildIDByCharacterID(uint32 character_id);
uint32 FindGuildByLeader(uint32 leader) const;
uint32 NumberInGuild(uint32 guild_id);
uint32 DoesAccountContainAGuildLeader(uint32 AccountID);
const char* GetRankName(uint32 guild_id, uint8 rank) const;
const char* GetGuildName(uint32 guild_id) const;
std::string GetGuildNameByID(uint32 guild_id) const;
std::string GetGuildRankName(uint32 guild_id, uint8 rank) const;
std::vector<GuildMembersRepository::GuildMembers> GetGuildMembers(uint32 guild_id);
protected:
//the methods which must be defined by base classes.
@ -105,58 +145,62 @@ class BaseGuildManager
virtual void SendRankUpdate(uint32 CharID) = 0;
virtual void SendGuildDelete(uint32 guild_id) = 0;
uint32 DBCreateGuild(const char* name, uint32 leader_char_id);
bool DBDeleteGuild(uint32 guild_id);
bool DBRenameGuild(uint32 guild_id, const char* name);
bool DBSetGuildLeader(uint32 guild_id, uint32 leader_char_id);
bool DBSetGuildMOTD(uint32 guild_id, const char* motd, const char *setter);
bool DBSetGuildURL(uint32 GuildID, const char* URL);
bool DBSetGuildChannel(uint32 GuildID, const char* Channel);
bool DBSetGuild(uint32 charid, uint32 guild_id, uint8 rank);
bool DBSetGuildRank(uint32 charid, uint8 rank);
bool DBSetBankerFlag(uint32 charid, bool is_banker);
bool DBSetAltFlag(uint32 charid, bool is_alt);
bool DBSetTributeFlag(uint32 charid, bool enabled);
bool DBSetPublicNote(uint32 charid, const char *note);
uint32 UpdateDbCreateGuild(std::string name, uint32 leader_char_id);
bool UpdateDbDeleteGuild(uint32 guild_id, bool local_delete = true, bool db_delete = true);
bool UpdateDbRenameGuild(uint32 guild_id, std::string name);
bool UpdateDbGuildLeader(uint32 guild_id, uint32 leader_char_id);
bool UpdateDbGuildMOTD(uint32 guild_id, std::string motd, std::string setter);
bool UpdateDbGuildURL(uint32 GuildID, std::string URL);
bool UpdateDbGuildChannel(uint32 GuildID, std::string Channel);
bool UpdateDbGuild(uint32 charid, uint32 guild_id, uint8 rank);
bool UpdateDbGuildRank(uint32 charid, uint8 rank);
bool UpdateDbAltFlag(uint32 charid, bool is_alt);
bool UpdateDbTributeFlag(uint32 charid, bool enabled);
bool UpdateDbPublicNote(uint32 charid, std::string public_note);
bool QueryWithLogging(std::string query, const char *errmsg);
// void DBSetPublicNote(uint32 guild_id,char* charname, char* note);
bool LocalDeleteGuild(uint32 guild_id);
class RankInfo
struct RankInfo
{
public:
RankInfo();
std::string name;
bool permissions[_MaxGuildAction];
RankInfo();
std::string rank_name;
};
class GuildInfo
struct Functions
{
public:
GuildInfo();
std::string name;
std::string motd;
std::string motd_setter;
std::string url;
std::string channel;
uint32 leader_char_id;
uint8 minstatus;
//tribute is not in here on purpose, since it is only valid in world!
RankInfo ranks[GUILD_MAX_RANK + 1];
uint32 id;
uint32 perm_id;
uint32 guild_id;
uint32 perm_value;
};
public:
class GuildInfo {
public:
GuildInfo();
std::string name;
std::string motd;
std::string motd_setter;
std::string url;
std::string channel;
uint32 leader;
uint8 minstatus;
std::string rank_names[GUILD_MAX_RANK + 1];
Functions functions[GUILD_MAX_FUNCTIONS + 1];
GuildTributeStruct tribute;
};
virtual BaseGuildManager::GuildInfo* GetGuildByGuildID(uint32 guild_id);
uint32 GetGuildTributeTimeRemaining(uint32 guild_id);
protected:
std::map<uint32, GuildInfo *> m_guilds; //we own the pointers in this map
void ClearGuilds(); //clears internal structure
Database *m_db; //we do not own this
bool _StoreGuildDB(uint32 guild_id);
GuildInfo *_CreateGuild(uint32 guild_id, const char *guild_name, uint32 account_id, uint8 minstatus, const char *guild_motd, const char *motd_setter, const char *Channel, const char *URL);
GuildInfo* _CreateGuild(uint32 guild_id, std::string guild_name, uint32 leader_char_id, uint8 minstatus, std::string guild_motd, std::string motd_setter, std::string Channel, std::string URL, uint32 favour);
uint32 _GetFreeGuildID();
GuildsRepository::Guilds CreateGuildRepoFromGuildInfo(uint32 guild_id, BaseGuildManager::GuildInfo& in);
};
#endif /*GUILD_BASE_H_*/

View File

@ -16,31 +16,70 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef GUILD_H
#define GUILD_H
#ifndef GUILDS_H
#define GUILDS_H
#include "types.h"
#define GUILD_NONE 0xFFFFFFFF // user has no guild
#define GUILD_MAX_RANK 8 // 0-2 - some places in the code assume a single digit, dont go above 9
#define GUILD_MAX_RANK 8 // 0-2 - some places in the code assume a single digit, dont go above 9
#define GUILD_MAX_FUNCTIONS 30
#define GUILD_TRIBUTES_MODIFY 1
#define GUILD_TRIBUTES_SAVE 0
#define GUILD_TRIBUTES_OFF 0
#define GUILD_TRIBUTES_ON 1
#define GUILD_INVITE_DECLINE 9
//defines for standard ranks
#define GUILD_MEMBER 0
#define GUILD_OFFICER 1
#define GUILD_LEADER 2
#define GUILD_MEMBER_TI 0
#define GUILD_OFFICER_TI 1
#define GUILD_LEADER_TI 2
#define GUILD_RANK_NONE (GUILD_MAX_RANK+1)
//defines for standard ranks base on RoF2 definitions
#define GUILD_RANK_NONE 0
#define GUILD_LEADER 1
#define GUILD_SENIOR_OFFICER 2
#define GUILD_OFFICER 3
#define GUILD_SENIOR_MEMBER 4
#define GUILD_MEMBER 5
#define GUILD_JUNIOR_MEMBER 6
#define GUILD_INITIATE 7
#define GUILD_RECRUIT 8
typedef enum {
GUILD_HEAR = 0,
GUILD_SPEAK = 1,
GUILD_INVITE = 2,
GUILD_REMOVE = 3,
GUILD_PROMOTE = 4,
GUILD_DEMOTE = 5,
GUILD_MOTD = 6,
GUILD_WARPEACE = 7,
_MaxGuildAction
GUILD_ACTION_BANNER_CHANGE = 1,
GUILD_ACTION_BANNER_PLANT = 2,
GUILD_ACTION_BANNER_REMOVE = 3,
GUILD_ACTION_DISPLAY_GUILD_NAME = 4,
GUILD_ACTION_RANKS_CHANGE_PERMISSIONS = 5,
GUILD_ACTION_RANKS_CHANGE_RANK_NAMES = 6,
GUILD_ACTION_MEMBERS_INVITE = 7,
GUILD_ACTION_MEMBERS_PROMOTE = 8,
GUILD_ACTION_MEMBERS_DEMOTE = 9,
GUILD_ACTION_MEMBERS_REMOVE = 10,
GUILD_ACTION_EDIT_RECRUITING_SETTINGS = 11,
GUILD_ACTION_EDIT_PUBLIC_NOTES = 12,
GUILD_ACTION_BANK_DEPOSIT_ITEMS = 13,
GUILD_ACTION_BANK_WITHDRAW_ITEMS = 14,
GUILD_ACTION_BANK_VIEW_ITEMS = 15,
GUILD_ACTION_BANK_PROMOTE_ITEMS = 16,
GUILD_ACTION_BANK_CHANGE_ITEM_PERMISSIONS = 17,
GUILD_ACTION_CHANGE_THE_MOTD = 18,
GUILD_ACTION_GUILD_CHAT_SEE = 19,
GUILD_ACTION_GUILD_CHAT_SPEAK_IN = 20,
GUILD_ACTION_SEND_THE_WHOLE_GUILD_E_MAIL = 21,
GUILD_ACTION_TRIBUTE_CHANGE_FOR_OTHERS = 22,
GUILD_ACTION_TRIBUTE_CHANGE_ACTIVE_BENEFIT = 23,
GUILD_ACTION_TROPHY_TRIBUTE_CHANGE_FOR_OTHERS = 24,
GUILD_ACTION_TROPHY_TRIBUTE_CHANGE_ACTIVE_BENEFIT = 25,
GUILD_ACTION_MEMBERS_CHANGE_ALT_FLAG_FOR_OTHER = 26,
GUILD_ACTION_REAL_ESTATE_GUILD_PLOT_BUY = 27,
GUILD_ACTION_REAL_ESTATE_GUILD_PLOT_SELL = 28,
GUILD_ACTION_REAL_ESTATE_MODIFY_TROPHIES = 29,
GUILD_ACTION_MEMBERS_DEMOTE_SELF = 30,
} GuildAction;
#endif

View File

@ -173,7 +173,8 @@ EQ::ItemInstance* EQ::InventoryProfile::GetItem(int16 slot_id) const
result = _GetItem(m_inv, slot_id);
}
else if ((slot_id >= invslot::EQUIPMENT_BEGIN && slot_id <= invslot::EQUIPMENT_END) ||
(slot_id >= invslot::TRIBUTE_BEGIN && slot_id <= invslot::TRIBUTE_END)) {
(slot_id >= invslot::TRIBUTE_BEGIN && slot_id <= invslot::TRIBUTE_END) ||
(slot_id >= invslot::GUILD_TRIBUTE_BEGIN && slot_id <= invslot::GUILD_TRIBUTE_END)) {
// Equippable slots (on body)
result = _GetItem(m_worn, slot_id);
}
@ -465,6 +466,10 @@ EQ::ItemInstance* EQ::InventoryProfile::PopItem(int16 slot_id)
p = m_worn[slot_id];
m_worn.erase(slot_id);
}
else if (slot_id >= invslot::GUILD_TRIBUTE_BEGIN && slot_id <= invslot::GUILD_TRIBUTE_END) {
p = m_worn[slot_id];
m_worn.erase(slot_id);
}
else if (slot_id >= invslot::BANK_BEGIN && slot_id <= invslot::BANK_END) {
p = m_bank[slot_id];
m_bank.erase(slot_id);
@ -1419,6 +1424,10 @@ int16 EQ::InventoryProfile::_PutItem(int16 slot_id, ItemInstance* inst)
m_worn[slot_id] = inst;
result = slot_id;
}
else if (slot_id >= invslot::GUILD_TRIBUTE_BEGIN && slot_id <= invslot::GUILD_TRIBUTE_END) {
m_worn[slot_id] = inst;
result = slot_id;
}
else if (slot_id >= invslot::BANK_BEGIN && slot_id <= invslot::BANK_END) {
if (slot_id - EQ::invslot::BANK_BEGIN < m_lookup->InventoryTypeSize.Bank) {
m_bank[slot_id] = inst;

View File

@ -1791,6 +1791,16 @@ int EQ::ItemInstance::RemoveTaskDeliveredItems()
return count;
}
uint32 EQ::ItemInstance::GetItemGuildFavor() const
{
uint32 total = 0;
const auto item = GetItem();
if (item) {
return total = item->GuildFavor;
}
return 0;
}
//
// class EvolveInfo
//

View File

@ -299,6 +299,7 @@ namespace EQ
int GetItemHeroicDR(bool augments = false) const;
int GetItemHeroicCorrup(bool augments = false) const;
int GetItemHaste(bool augments = false) const;
uint32 GetItemGuildFavor() const;
protected:
//////////////////////////

View File

@ -1308,13 +1308,13 @@ namespace RoF
PutFieldN(class_);
/* Translate older ranks to new values */
switch (emu_e->rank) {
case 0: { e->rank = htonl(5); break; } // GUILD_MEMBER 0
case 1: { e->rank = htonl(3); break; } // GUILD_OFFICER 1
case 2: { e->rank = htonl(1); break; } // GUILD_LEADER 2
default: { e->rank = htonl(emu_e->rank); break; } // GUILD_NONE
}
//switch (emu_e->rank) {
//case 0: { e->rank = htonl(5); break; } // GUILD_MEMBER 0
//case 1: { e->rank = htonl(3); break; } // GUILD_OFFICER 1
//case 2: { e->rank = htonl(1); break; } // GUILD_LEADER 2
//default: { e->rank = htonl(emu_e->rank); break; } // GUILD_NONE
//}
PutFieldN(rank);
PutFieldN(time_last_on);
PutFieldN(tribute_enable);
e->unknown01 = 0;
@ -3051,19 +3051,12 @@ namespace RoF
ENCODE_LENGTH_EXACT(GuildSetRank_Struct);
SETUP_DIRECT_ENCODE(GuildSetRank_Struct, structs::GuildSetRank_Struct);
eq->GuildID = emu->Unknown00;
eq->guild_id = emu->Unknown00;
eq->rank = emu->rank;
/* Translate older ranks to new values */
switch (emu->Rank) {
case 0: { eq->Rank = 5; break; } // GUILD_MEMBER 0
case 1: { eq->Rank = 3; break; } // GUILD_OFFICER 1
case 2: { eq->Rank = 1; break; } // GUILD_LEADER 2
default: { eq->Rank = emu->Rank; break; }
}
memcpy(eq->MemberName, emu->MemberName, sizeof(eq->MemberName));
OUT(Banker);
eq->Unknown76 = 1;
memcpy(eq->member_name, emu->member_name, sizeof(eq->member_name));
OUT(banker);
eq->unknown76 = 1;
FINISH_ENCODE();
}
@ -3973,10 +3966,22 @@ namespace RoF
/* Translate older ranks to new values */
switch (emu->guildrank) {
case 0: { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 5); break; } // GUILD_MEMBER 0
case 1: { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 3); break; } // GUILD_OFFICER 1
case 2: { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 1); break; } // GUILD_LEADER 2
default: { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->guildrank); break; } //
case 0: {
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 5);
break;
} // GUILD_MEMBER 0
case 1: {
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 3);
break;
} // GUILD_OFFICER 1
case 2: {
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 1);
break;
} // GUILD_LEADER 2
default: {
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->guildrank);
break;
} //
}
}

View File

@ -1319,6 +1319,7 @@ namespace RoF2
buffer++;
// Guild ID
//*((uint32*)buffer) = htonl(2);
buffer += sizeof(uint32);
//add member count.
@ -1357,15 +1358,7 @@ namespace RoF2
PutFieldN(level);
PutFieldN(banker);
PutFieldN(class_);
/* Translate older ranks to new values */
switch (emu_e->rank) {
case 0: { e->rank = htonl(5); break; } // GUILD_MEMBER 0
case 1: { e->rank = htonl(3); break; } // GUILD_OFFICER 1
case 2: { e->rank = htonl(1); break; } // GUILD_LEADER 2
default: { e->rank = htonl(emu_e->rank); break; } // GUILD_NONE
}
PutFieldN(rank);
PutFieldN(time_last_on);
PutFieldN(tribute_enable);
e->unknown01 = 0;
@ -1395,8 +1388,10 @@ namespace RoF2
OUT(GuildID);
memcpy(eq->MemberName, emu->MemberName, sizeof(eq->MemberName));
OUT(ZoneID);
OUT(InstanceID);
//OUT(ZoneID);
//OUT(InstanceID);
eq->InstanceID = emu->InstanceID;
eq->ZoneID = emu->ZoneID;
OUT(LastSeen);
eq->Unknown76 = 0;
@ -1422,7 +1417,7 @@ namespace RoF2
if (InBuffer[0])
{
PacketSize += (5 + strlen(InBuffer));
HighestGuildID = i - 1;
HighestGuildID += 1;
}
InBuffer += 64;
}
@ -1460,6 +1455,30 @@ namespace RoF2
dest->FastQueuePacket(&in, ack_req);
}
ENCODE(OP_GuildTributeDonateItem)
{
SETUP_DIRECT_ENCODE(GuildTributeDonateItemReply_Struct, structs::GuildTributeDonateItemReply_Struct);
Log(Logs::Detail, Logs::Netcode, "RoF2::ENCODE(OP_GuildTributeDonateItem)");
OUT(type);
OUT(sub_index);
OUT(aug_index);
OUT(quantity);
OUT(unknown10);
OUT(unknown20);
OUT(favor);
structs::InventorySlot_Struct iss;
iss = ServerToRoF2Slot(emu->slot);
eq->slot = iss.Slot;
eq->sub_index = iss.SubIndex;
FINISH_ENCODE();
}
ENCODE(OP_HPUpdate)
{
SETUP_DIRECT_ENCODE(SpawnHPUpdate_Struct, structs::SpawnHPUpdate_Struct);
@ -2466,6 +2485,8 @@ namespace RoF2
{
outapp->WriteUInt32(0xffffffff);
outapp->WriteUInt32(0);
// outapp->WriteUInt32(60);
// outapp->WriteUInt32(1);
}
outapp->WriteUInt32(0); // Unknown
@ -3104,19 +3125,12 @@ namespace RoF2
ENCODE_LENGTH_EXACT(GuildSetRank_Struct);
SETUP_DIRECT_ENCODE(GuildSetRank_Struct, structs::GuildSetRank_Struct);
eq->GuildID = emu->Unknown00;
eq->guild_id= emu->Unknown00;
eq->rank = emu->rank;
/* Translate older ranks to new values */
switch (emu->Rank) {
case 0: { eq->Rank = 5; break; } // GUILD_MEMBER 0
case 1: { eq->Rank = 3; break; } // GUILD_OFFICER 1
case 2: { eq->Rank = 1; break; } // GUILD_LEADER 2
default: { eq->Rank = emu->Rank; break; }
}
memcpy(eq->MemberName, emu->MemberName, sizeof(eq->MemberName));
OUT(Banker);
eq->Unknown76 = 1;
memcpy(eq->member_name, emu->member_name, sizeof(eq->member_name));
OUT(banker);
eq->unknown76 = 1;
FINISH_ENCODE();
}
@ -4178,12 +4192,13 @@ namespace RoF2
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->guildID);
/* Translate older ranks to new values */
switch (emu->guildrank) {
case 0: { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 5); break; } // GUILD_MEMBER 0
case 1: { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 3); break; } // GUILD_OFFICER 1
case 2: { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 1); break; } // GUILD_LEADER 2
default: { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->guildrank); break; } //
}
//switch (emu->guildrank) {
//case 0: { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 5); break; } // GUILD_MEMBER 0
//case 1: { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 3); break; } // GUILD_OFFICER 1
//case 2: { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 1); break; } // GUILD_LEADER 2
//default: { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->guildrank); break; } //
//}
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->guildrank);
}
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->class_);
@ -4199,7 +4214,7 @@ namespace RoF2
VARSTRUCT_ENCODE_STRING(Buffer, emu->lastName);
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // aatitle
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->NPC ? 0 : 1); // unknown - Must be 1 for guild name to be shown abover players head.
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->guild_show);
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // TempPet
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->petOwnerId);
@ -4955,7 +4970,7 @@ namespace RoF2
strn0cpy(emu->target, eq->target, sizeof(emu->target));
strn0cpy(emu->name, eq->name, sizeof(emu->name));
// IN(rank);
IN(rank);
FINISH_DIRECT_DECODE();
}
@ -4983,6 +4998,38 @@ namespace RoF2
FINISH_DIRECT_DECODE();
}
DECODE(OP_GuildTributeDonateItem)
{
DECODE_LENGTH_EXACT(structs::GuildTributeDonateItemRequest_Struct);
SETUP_DIRECT_DECODE(GuildTributeDonateItemRequest_Struct, structs::GuildTributeDonateItemRequest_Struct);
Log(Logs::Detail, Logs::Netcode, "RoF2::DECODE(OP_GuildTributeDonateItem)");
IN(type);
IN(slot);
IN(sub_index);
IN(aug_index);
IN(unknown10);
IN(quantity);
IN(tribute_master_id);
IN(unknown20);
IN(guild_id);
IN(unknown28);
IN(unknown32);
structs::InventorySlot_Struct iss;
iss.Slot = eq->slot;
iss.SubIndex = eq->sub_index;
iss.AugIndex = eq->aug_index;
iss.Type = eq->type;
iss.Unknown01 = 0;
iss.Unknown02 = 0;
emu->slot = RoF2ToServerSlot(iss);
FINISH_DIRECT_DECODE();
}
/*DECODE(OP_InspectAnswer)
{
DECODE_LENGTH_EXACT(structs::InspectResponse_Struct);

View File

@ -82,6 +82,7 @@ E(OP_GuildBank)
E(OP_GuildMemberList)
E(OP_GuildMemberUpdate)
E(OP_GuildsList)
E(OP_GuildTributeDonateItem)
E(OP_HPUpdate)
E(OP_Illusion)
E(OP_InspectBuffs)
@ -182,6 +183,7 @@ D(OP_GuildBank)
D(OP_GuildDemote)
D(OP_GuildRemove)
D(OP_GuildStatus)
D(OP_GuildTributeDonateItem)
D(OP_InspectRequest)
D(OP_ItemLinkClick)
D(OP_ItemVerifyRequest)

View File

@ -2011,6 +2011,31 @@ struct GuildBankClear_Struct
/*16*/ uint32 MainAreaCount;
};
struct GuildTributeDonateItemRequest_Struct {
/*000*/ uint32 type;
/*004*/ uint16 slot;
/*006*/ uint16 sub_index;
/*008*/ uint16 aug_index;
/*010*/ uint16 unknown10;
/*012*/ uint32 quantity;
/*016*/ uint32 tribute_master_id;
/*020*/ uint32 unknown20;
/*024*/ uint32 guild_id;
/*028*/ uint32 unknown28;
/*032*/ uint32 unknown32;
};
struct GuildTributeDonateItemReply_Struct {
/*000*/ uint32 type;
/*004*/ uint16 slot;
/*006*/ uint16 sub_index;
/*008*/ uint16 aug_index;
/*010*/ uint16 unknown10;
/*012*/ uint32 quantity;
/*016*/ uint32 unknown20;
/*020*/ uint32 favor;
};
/*
** Money Loot
** Length: 22 Bytes
@ -3600,11 +3625,11 @@ struct GuildMakeLeader {
// Update a guild members rank and banker status
struct GuildSetRank_Struct
{
/*00*/ uint32 GuildID; // Was Unknown00
/*04*/ uint32 Rank;
/*08*/ char MemberName[64];
/*72*/ uint32 Banker;
/*76*/ uint32 Unknown76; // Seen 1 - Maybe Banker?
/*00*/ uint32 guild_id; // Was Unknown00
/*04*/ uint32 rank;
/*08*/ char member_name[64];
/*72*/ uint32 banker;
/*76*/ uint32 unknown76; // Seen 1 - Maybe Banker?
/*80*/
};
@ -3722,15 +3747,15 @@ struct TributeItem_Struct
struct TributePoint_Struct {
int32 tribute_points;
uint32 unknown04;
uint32 unknown04;
int32 career_tribute_points;
uint32 unknown12;
uint32 unknown12;
};
struct TributeMoney_Struct {
uint32 platinum;
uint32 tribute_master_id;
int32 tribute_points;
int32 tribute_points;
};

View File

@ -3537,11 +3537,11 @@ struct GuildMakeLeader {
// Update a guild members rank and banker status
struct GuildSetRank_Struct
{
/*00*/ uint32 GuildID; // Was Unknown00
/*04*/ uint32 Rank;
/*08*/ char MemberName[64];
/*72*/ uint32 Banker;
/*76*/ uint32 Unknown76; // Seen 1 - Maybe Banker?
/*00*/ uint32 guild_id; // Was Unknown00
/*04*/ uint32 rank;
/*08*/ char member_name[64];
/*72*/ uint32 banker;
/*76*/ uint32 unknown76; // Seen 1 - Maybe Banker?
/*80*/
};

View File

@ -34,6 +34,7 @@
#include "titanium_structs.h"
#include "../path_manager.h"
#include "../raid.h"
#include "../guilds.h"
#include <sstream>
@ -664,6 +665,151 @@ namespace Titanium
dest->FastQueuePacket(&in, ack_req);
}
ENCODE(OP_SetGuildRank)
{
ENCODE_LENGTH_EXACT(GuildSetRank_Struct);
SETUP_DIRECT_ENCODE(GuildSetRank_Struct, structs::GuildSetRank_Struct);
eq->unknown00 = 0;
eq->unknown04 = 0;
//Translate older ranks to new values* /
switch (emu->rank) {
case GUILD_SENIOR_MEMBER:
case GUILD_MEMBER:
case GUILD_JUNIOR_MEMBER:
case GUILD_INITIATE:
case GUILD_RECRUIT: {
eq->rank = GUILD_MEMBER_TI;
break;
}
case GUILD_OFFICER:
case GUILD_SENIOR_OFFICER: {
eq->rank = GUILD_OFFICER_TI;
break;
}
case GUILD_LEADER: {
eq->rank = GUILD_LEADER_TI;
break;
}
}
memcpy(eq->member_name, emu->member_name, sizeof(eq->member_name));
OUT(banker);
FINISH_ENCODE();
}
ENCODE(OP_SpawnAppearance)
{
ENCODE_LENGTH_EXACT(SpawnAppearance_Struct);
SETUP_DIRECT_ENCODE(SpawnAppearance_Struct, structs::SpawnAppearance_Struct);
OUT(spawn_id);
OUT(type);
OUT(parameter);
switch (emu->type) {
case AppearanceType::GuildRank: {
//Translate new ranks to old values* /
switch (emu->parameter) {
case GUILD_SENIOR_MEMBER:
case GUILD_MEMBER:
case GUILD_JUNIOR_MEMBER:
case GUILD_INITIATE:
case GUILD_RECRUIT: {
eq->parameter = GUILD_MEMBER_TI;
break;
}
case GUILD_OFFICER:
case GUILD_SENIOR_OFFICER: {
eq->parameter = GUILD_OFFICER_TI;
break;
}
case GUILD_LEADER: {
eq->parameter = GUILD_LEADER_TI;
break;
}
}
break;
}
case AppearanceType::GuildShow: {
FAIL_ENCODE();
return;
}
default: {
break;
}
}
FINISH_ENCODE();
}
ENCODE(OP_GuildMemberAdd)
{
ENCODE_LENGTH_EXACT(GuildMemberAdd_Struct)
SETUP_DIRECT_ENCODE(GuildMemberAdd_Struct, structs::GuildMemberAdd_Struct)
OUT(guild_id)
OUT(level)
OUT(class_)
switch (emu->rank_) {
case GUILD_SENIOR_MEMBER:
case GUILD_MEMBER:
case GUILD_JUNIOR_MEMBER:
case GUILD_INITIATE:
case GUILD_RECRUIT: {
eq->rank_ = GUILD_MEMBER_TI;
break;
}
case GUILD_OFFICER:
case GUILD_SENIOR_OFFICER: {
eq->rank_ = GUILD_OFFICER_TI;
break;
}
case GUILD_LEADER: {
eq->rank_ = GUILD_LEADER_TI;
break;
}
}
OUT(zone_id)
OUT(last_on)
OUT_str(player_name)
FINISH_ENCODE()
}
ENCODE(OP_GuildMemberRankAltBanker)
{
ENCODE_LENGTH_EXACT(GuildMemberRank_Struct)
SETUP_DIRECT_ENCODE(GuildMemberRank_Struct, structs::GuildMemberRank_Struct)
OUT(guild_id)
OUT(alt_banker)
OUT_str(player_name)
switch (emu->rank_) {
case GUILD_SENIOR_MEMBER:
case GUILD_MEMBER:
case GUILD_JUNIOR_MEMBER:
case GUILD_INITIATE:
case GUILD_RECRUIT: {
eq->rank_ = GUILD_MEMBER_TI;
break;
}
case GUILD_OFFICER:
case GUILD_SENIOR_OFFICER: {
eq->rank_ = GUILD_OFFICER_TI;
break;
}
case GUILD_LEADER: {
eq->rank_ = GUILD_LEADER_TI;
break;
}
}
FINISH_ENCODE()
}
ENCODE(OP_GuildMemberList)
{
//consume the packet
@ -727,12 +873,34 @@ namespace Titanium
str += sl + 1; \
}
#define PutFieldN(field) e->field = htonl(emu_e->field)
/* Translate new ranks to older values */
SlideStructString(name, emu_name);
PutFieldN(level);
PutFieldN(banker);
PutFieldN(class_);
PutFieldN(rank);
switch (emu_e->rank) {
case GUILD_SENIOR_MEMBER:
case GUILD_MEMBER:
case GUILD_JUNIOR_MEMBER:
case GUILD_INITIATE:
case GUILD_RECRUIT: {
e->rank = htonl(GUILD_MEMBER_TI);
break;
}
case GUILD_OFFICER:
case GUILD_SENIOR_OFFICER: {
e->rank = htonl(GUILD_OFFICER_TI);
break;
}
case GUILD_LEADER: {
e->rank = htonl(GUILD_LEADER_TI);
break;
}
default: {
e->rank = htonl(GUILD_MEMBER_TI);
break;
}
}
PutFieldN(time_last_on);
PutFieldN(tribute_enable);
PutFieldN(total_tribute);
@ -753,6 +921,38 @@ namespace Titanium
dest->FastQueuePacket(&in, ack_req);
}
ENCODE(OP_SendGuildTributes)
{
ENCODE_LENGTH_ATLEAST(structs::GuildTributeAbility_Struct);
SETUP_VAR_ENCODE(GuildTributeAbility_Struct);
ALLOC_VAR_ENCODE(structs::GuildTributeAbility_Struct, sizeof(GuildTributeAbility_Struct) + strlen(emu->ability.name));
eq->guild_id = emu->guild_id;;
strncpy(eq->ability.name, emu->ability.name, strlen(emu->ability.name));
eq->ability.tribute_id = emu->ability.tribute_id;
eq->ability.tier_count = emu->ability.tier_count;
for (int i = 0; i < ntohl(emu->ability.tier_count); i++) {
eq->ability.tiers[i].cost = emu->ability.tiers[i].cost;
eq->ability.tiers[i].level = emu->ability.tiers[i].level;
eq->ability.tiers[i].tribute_item_id = emu->ability.tiers[i].tribute_item_id;
}
FINISH_ENCODE();
}
ENCODE(OP_GuildTributeDonateItem)
{
SETUP_DIRECT_ENCODE(GuildTributeDonateItemReply_Struct, structs::GuildTributeDonateItemReply_Struct);
Log(Logs::Detail, Logs::Netcode, "UF::ENCODE(OP_GuildTributeDonateItem)");
OUT(quantity);
OUT(favor);
eq->unknown8 = 0;
eq->slot = ServerToTitaniumSlot(emu->slot);
FINISH_ENCODE();
}
ENCODE(OP_Illusion)
{
ENCODE_LENGTH_EXACT(Illusion_Struct);
@ -867,11 +1067,60 @@ namespace Titanium
ENCODE(OP_LFGuild)
{
struct bit_mask_conversion {
uint32 titanium_mask;
uint32 rof2_mask;
};
std::vector<bit_mask_conversion> bit_mask = {
{.titanium_mask = 2, .rof2_mask = 256},
{.titanium_mask = 4, .rof2_mask = 32768},
{.titanium_mask = 8, .rof2_mask = 65536},
{.titanium_mask = 16, .rof2_mask = 4},
{.titanium_mask = 32, .rof2_mask = 64},
{.titanium_mask = 64, .rof2_mask = 16384},
{.titanium_mask = 128, .rof2_mask = 8192},
{.titanium_mask = 256, .rof2_mask = 128},
{.titanium_mask = 512, .rof2_mask = 2048},
{.titanium_mask = 1024, .rof2_mask = 8},
{.titanium_mask = 2048, .rof2_mask = 16},
{.titanium_mask = 4096, .rof2_mask = 512},
{.titanium_mask = 8192, .rof2_mask = 32},
{.titanium_mask = 16384, .rof2_mask = 1024},
{.titanium_mask = 32768, .rof2_mask = 2},
{.titanium_mask = 65536, .rof2_mask = 4096},
};
EQApplicationPacket *in = *p;
*p = nullptr;
uint32 Command = in->ReadUInt32();
if (Command == 1) {
ENCODE_LENGTH_EXACT(LFGuild_GuildToggle_Struct);
SETUP_DIRECT_ENCODE(LFGuild_GuildToggle_Struct, structs::LFGuild_GuildToggle_Struct);
OUT(Command);
OUT_str(Comment);
OUT(FromLevel);
OUT(ToLevel);
OUT(AACount);
OUT(TimeZone);
OUT(Toggle);
OUT(TimePosted);
OUT_str(Name);
uint32 emu_bitmask = emu->Classes;
uint32 ti_bitmask = 0;
for (auto const& b : bit_mask) {
(emu_bitmask & b.rof2_mask) != 0 ? ti_bitmask |= b.titanium_mask : ti_bitmask &= ~b.titanium_mask;
}
eq->Classes = ti_bitmask;
FINISH_ENCODE();
return;
}
*p = nullptr;
if (Command != 0)
{
dest->FastQueuePacket(&in, ack_req);
@ -1149,7 +1398,28 @@ namespace Titanium
OUT(pvp);
OUT(anon);
OUT(gm);
OUT(guildrank);
switch (emu->guildrank) {
case GUILD_SENIOR_MEMBER:
case GUILD_MEMBER:
case GUILD_JUNIOR_MEMBER:
case GUILD_INITIATE:
case GUILD_RECRUIT: {
eq->guildrank = GUILD_MEMBER_TI;
break;
}
case GUILD_OFFICER:
case GUILD_SENIOR_OFFICER: {
eq->guildrank = GUILD_OFFICER_TI;
break;
}
case GUILD_LEADER: {
eq->guildrank = GUILD_LEADER_TI;
break;
}
default: {
break;
}
}
OUT(guildbanker);
// OUT(unknown13054[8]);
OUT(exp);
@ -1250,7 +1520,7 @@ namespace Titanium
{
ENCODE_LENGTH_EXACT(MarkNPC_Struct);
SETUP_DIRECT_ENCODE(MarkNPC_Struct, MarkNPC_Struct);
EQApplicationPacket* outapp = new EQApplicationPacket(OP_MarkNPC, sizeof(MarkNPC_Struct));
MarkNPC_Struct* mnpcs = (MarkNPC_Struct*)outapp->pBuffer;
mnpcs->TargetID = emu->TargetID;
@ -1267,10 +1537,10 @@ namespace Titanium
*p = nullptr;
unsigned char* __emu_buffer = inapp->pBuffer;
RaidGeneral_Struct* raid_gen = (RaidGeneral_Struct*)__emu_buffer;
switch (raid_gen->action)
{
case raidAdd:
case raidAdd:
{
RaidAddMember_Struct* emu = (RaidAddMember_Struct*)__emu_buffer;
@ -1340,7 +1610,7 @@ namespace Titanium
dest->QueuePacket(inapp);
break;
}
default:
default:
{
RaidGeneral_Struct* emu = (RaidGeneral_Struct*)__emu_buffer;
@ -1864,7 +2134,28 @@ namespace Titanium
eq->beard = emu->beard;
strcpy(eq->suffix, emu->suffix);
eq->petOwnerId = emu->petOwnerId;
eq->guildrank = emu->guildrank;
switch (emu->guildrank) {
case GUILD_SENIOR_MEMBER:
case GUILD_MEMBER:
case GUILD_JUNIOR_MEMBER:
case GUILD_INITIATE:
case GUILD_RECRUIT: {
eq->guildrank = GUILD_MEMBER_TI;
break;
}
case GUILD_OFFICER:
case GUILD_SENIOR_OFFICER: {
eq->guildrank = GUILD_OFFICER_TI;
break;
}
case GUILD_LEADER: {
eq->guildrank = GUILD_LEADER_TI;
break;
}
default: {
break;
}
}
// eq->unknown0194[3] = emu->unknown0194[3];
for (k = EQ::textures::textureBegin; k < EQ::textures::materialCount; k++) {
eq->equipment.Slot[k].Material = emu->equipment.Slot[k].Material;
@ -2205,6 +2496,34 @@ namespace Titanium
FINISH_DIRECT_DECODE();
}
DECODE(OP_GuildDemote)
{
DECODE_LENGTH_EXACT(structs::GuildDemoteStruct);
SETUP_DIRECT_DECODE(GuildDemoteStruct, structs::GuildDemoteStruct);
memcpy(emu->name, eq->name, sizeof(emu->name));
memcpy(emu->target, eq->target, sizeof(emu->target));
emu->rank = GUILD_MEMBER;
FINISH_DIRECT_DECODE();
}
DECODE(OP_GuildTributeDonateItem)
{
DECODE_LENGTH_EXACT(structs::GuildTributeDonateItemRequest_Struct);
SETUP_DIRECT_DECODE(GuildTributeDonateItemRequest_Struct, structs::GuildTributeDonateItemRequest_Struct);
Log(Logs::Detail, Logs::Netcode, "UF::DECODE(OP_GuildTributeDonateItem)");
IN(quantity);
IN(tribute_master_id);
IN(guild_id);
emu->slot = TitaniumToServerSlot(eq->slot);
FINISH_DIRECT_DECODE();
}
DECODE(OP_InspectAnswer)
{
DECODE_LENGTH_EXACT(structs::InspectResponse_Struct);
@ -2260,8 +2579,77 @@ namespace Titanium
DECODE(OP_LFGuild)
{
struct bit_mask_conversion {
uint32 titanium_mask;
uint32 rof2_mask;
};
std::vector<bit_mask_conversion> bit_mask = {
{.titanium_mask = 2, .rof2_mask = 256},
{.titanium_mask = 4, .rof2_mask = 32768},
{.titanium_mask = 8, .rof2_mask = 65536},
{.titanium_mask = 16, .rof2_mask = 4},
{.titanium_mask = 32, .rof2_mask = 64},
{.titanium_mask = 64, .rof2_mask = 16384},
{.titanium_mask = 128, .rof2_mask = 8192},
{.titanium_mask = 256, .rof2_mask = 128},
{.titanium_mask = 512, .rof2_mask = 2048},
{.titanium_mask = 1024, .rof2_mask = 8},
{.titanium_mask = 2048, .rof2_mask = 16},
{.titanium_mask = 4096, .rof2_mask = 512},
{.titanium_mask = 8192, .rof2_mask = 32},
{.titanium_mask = 16384, .rof2_mask = 1024},
{.titanium_mask = 32768, .rof2_mask = 2},
{.titanium_mask = 65536, .rof2_mask = 4096},
};
uint32 Command = __packet->ReadUInt32();
if (Command == 3) {
DECODE_LENGTH_EXACT(structs::LFGuild_SearchPlayer_Struct);
SETUP_DIRECT_DECODE(LFGuild_SearchPlayer_Struct, structs::LFGuild_SearchPlayer_Struct);
IN(Command);
IN(Unknown04);
IN(FromLevel);
IN(ToLevel);
IN(MinAA);
IN(TimeZone);
uint32 new_bitmask = 0;
uint32 ti_bitmask = eq->Classes;
for (auto const& b : bit_mask) {
(ti_bitmask & b.titanium_mask) != 0 ? new_bitmask |= b.rof2_mask : new_bitmask &= ~b.rof2_mask;
}
emu->Classes = new_bitmask;
FINISH_DIRECT_DECODE();
return;
}
if (Command == 1) {
DECODE_LENGTH_EXACT(structs::LFGuild_GuildToggle_Struct);
SETUP_DIRECT_DECODE(LFGuild_GuildToggle_Struct, structs::LFGuild_GuildToggle_Struct);
IN(Command);
IN_str(Comment);
IN(FromLevel);
IN(ToLevel);
IN(AACount);
IN(TimeZone);
IN(Toggle);
IN(TimePosted);
IN_str(Name);
uint32 new_bitmask = 0;
uint32 ti_bitmask = eq->Classes;
for (auto const& b : bit_mask) {
(ti_bitmask & b.titanium_mask) != 0 ? new_bitmask |= b.rof2_mask : new_bitmask &= ~b.rof2_mask;
}
emu->Classes = new_bitmask;
FINISH_DIRECT_DECODE();
return;
}
if (Command != 0)
return;
@ -2401,7 +2789,7 @@ namespace Titanium
IN(general.parameter);
IN_str(general.leader_name);
IN_str(general.player_name);
auto len = 0;
if (__packet->size < sizeof(structs::RaidMOTD_Struct)) {
len = __packet->size - sizeof(structs::RaidGeneral_Struct);
@ -2409,8 +2797,8 @@ namespace Titanium
else {
len = sizeof(eq->motd);
}
strn0cpy(emu->motd, eq->motd, len > 1024 ? 1024 : len);
strn0cpy(emu->motd, eq->motd, len > 1024 ? 1024 : len);
emu->motd[len - 1] = '\0';
FINISH_VAR_DECODE();
@ -2428,7 +2816,7 @@ namespace Titanium
FINISH_VAR_DECODE();
break;
}
}
default:
{
SETUP_DIRECT_DECODE(RaidGeneral_Struct, structs::RaidGeneral_Struct);

View File

@ -44,8 +44,13 @@ E(OP_DzSetLeaderName)
E(OP_Emote)
E(OP_FormattedMessage)
E(OP_GroundSpawn)
E(OP_SetGuildRank)
E(OP_GuildMemberLevelUpdate)
E(OP_GuildMemberList)
E(OP_GuildMemberAdd)
E(OP_GuildMemberRankAltBanker)
E(OP_SendGuildTributes)
E(OP_GuildTributeDonateItem)
E(OP_Illusion)
E(OP_InspectAnswer)
E(OP_InspectRequest)
@ -69,6 +74,7 @@ E(OP_SendCharInfo)
E(OP_SendAATable)
E(OP_SetFace)
E(OP_ShopPlayerSell)
E(OP_SpawnAppearance)
E(OP_SpecialMesg)
E(OP_TaskDescription)
E(OP_Track)
@ -100,9 +106,11 @@ D(OP_DzRemovePlayer)
D(OP_DzSwapPlayer)
D(OP_Emote)
D(OP_FaceChange)
D(OP_GuildDemote)
D(OP_InspectAnswer)
D(OP_InspectRequest)
D(OP_ItemLinkClick)
D(OP_GuildTributeDonateItem)
D(OP_LFGuild)
D(OP_LoadSpellSet)
D(OP_LootItem)

View File

@ -1423,6 +1423,23 @@ struct GuildUpdate_Struct {
GuildsListEntry_Struct entry;
};
struct GuildTributeDonateItemRequest_Struct {
/*000*/ uint32 slot;
/*004*/ uint32 quantity;
/*008*/ uint32 tribute_master_id;
/*012*/ uint32 unknown12;
/*016*/ uint32 guild_id;
/*020*/ uint32 unknown20;
/*024*/ uint32 unknown24;
};
struct GuildTributeDonateItemReply_Struct {
/*000*/ uint32 slot;
/*004*/ uint32 quantity;
/*008*/ uint32 unknown8;
/*012*/ uint32 favor;
};
/*
** Money Loot
** Length: 22 Bytes
@ -3508,7 +3525,7 @@ struct LFGuild_GuildToggle_Struct
/*540*/ uint32 TimeZone;
/*544*/ uint8 Toggle;
/*545*/ uint8 Unknown545[3];
/*548*/ uint32 Expires;
/*548*/ uint32 TimePosted;
/*552*/ char Name[64];
/*616*/
};
@ -3699,6 +3716,34 @@ struct SayLinkBodyFrame_Struct {
/*045*/
};
struct GuildSetRank_Struct
{
/*00*/ uint32 unknown00;
/*04*/ uint32 unknown04;
/*08*/ uint32 rank;
/*72*/ char member_name[64];
/*76*/ uint32 banker;
};
struct GuildMemberAdd_Struct {
/*000*/ uint32 guild_id;
/*004*/ uint32 unknown04;
/*008*/ uint32 level;
/*012*/ uint32 class_;
/*016*/ uint32 rank_;
/*020*/ uint32 zone_id;
/*024*/ uint32 last_on;
/*028*/ char player_name[64];
};
struct GuildMemberRank_Struct {
/*000*/ uint32 guild_id;
/*004*/ uint32 unknown_004;
/*008*/ uint32 rank_;
/*012*/ char player_name[64];
/*076*/ uint32 alt_banker; //Banker/Alt bit 00 - none 10 - Alt 11 - Alt and Banker 01 - Banker. Banker not functional for RoF2+
};
}; /*structs*/
}; /*Titanium*/

View File

@ -36,6 +36,7 @@
#include "../classes.h"
#include "../races.h"
#include "../raid.h"
#include "../guilds.h"
#include <iostream>
#include <sstream>
@ -1134,6 +1135,29 @@ namespace UF
PutFieldN(level);
PutFieldN(banker);
PutFieldN(class_);
//Translate older ranks to new values* /
switch (emu_e->rank) {
case GUILD_SENIOR_MEMBER:
case GUILD_MEMBER:
case GUILD_JUNIOR_MEMBER:
case GUILD_INITIATE:
case GUILD_RECRUIT: {
emu_e->rank = GUILD_MEMBER_TI;
break;
}
case GUILD_OFFICER:
case GUILD_SENIOR_OFFICER: {
emu_e->rank = GUILD_OFFICER_TI;
break;
}
case GUILD_LEADER: {
emu_e->rank = GUILD_LEADER_TI;
break;
}
default: {
break;
}
}
PutFieldN(rank);
PutFieldN(time_last_on);
PutFieldN(tribute_enable);
@ -1165,14 +1189,14 @@ namespace UF
unsigned char *__emu_buffer = in->pBuffer;
char *InBuffer = (char *)__emu_buffer;
uint32 HighestGuildID = 0;
uint32 actual_no_guilds = 0;
for (unsigned int i = 0; i < NumberOfGuilds; ++i)
{
if (InBuffer[0])
{
PacketSize += (5 + strlen(InBuffer));
HighestGuildID = i - 1;
actual_no_guilds++;
}
InBuffer += 64;
}
@ -1188,7 +1212,7 @@ namespace UF
memset(OutBuffer, 0, 64);
OutBuffer += 64;
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, HighestGuildID);
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, actual_no_guilds);
for (unsigned int i = 0; i < NumberOfGuilds; ++i)
{
@ -1206,6 +1230,103 @@ namespace UF
dest->FastQueuePacket(&in, ack_req);
}
ENCODE(OP_GuildMemberAdd)
{
ENCODE_LENGTH_EXACT(GuildMemberAdd_Struct)
SETUP_DIRECT_ENCODE(GuildMemberAdd_Struct, structs::GuildMemberAdd_Struct)
OUT(guild_id)
OUT(level)
OUT(class_)
switch (emu->rank_) {
case GUILD_SENIOR_MEMBER:
case GUILD_MEMBER:
case GUILD_JUNIOR_MEMBER:
case GUILD_INITIATE:
case GUILD_RECRUIT: {
eq->rank_ = GUILD_MEMBER_TI;
break;
}
case GUILD_OFFICER:
case GUILD_SENIOR_OFFICER: {
eq->rank_ = GUILD_OFFICER_TI;
break;
}
case GUILD_LEADER: {
eq->rank_ = GUILD_LEADER_TI;
break;
}
}
OUT(zone_id)
OUT(last_on)
OUT_str(player_name)
FINISH_ENCODE()
}
ENCODE(OP_GuildMemberRankAltBanker)
{
ENCODE_LENGTH_EXACT(GuildMemberRank_Struct)
SETUP_DIRECT_ENCODE(GuildMemberRank_Struct, structs::GuildMemberRank_Struct)
OUT(guild_id)
OUT(alt_banker)
OUT_str(player_name)
switch (emu->rank_) {
case GUILD_SENIOR_MEMBER:
case GUILD_MEMBER:
case GUILD_JUNIOR_MEMBER:
case GUILD_INITIATE:
case GUILD_RECRUIT: {
eq->rank_ = GUILD_MEMBER_TI;
break;
}
case GUILD_OFFICER:
case GUILD_SENIOR_OFFICER: {
eq->rank_ = GUILD_OFFICER_TI;
break;
}
case GUILD_LEADER: {
eq->rank_ = GUILD_LEADER_TI;
break;
}
}
FINISH_ENCODE()
}
ENCODE(OP_SendGuildTributes)
{
ENCODE_LENGTH_ATLEAST(structs::GuildTributeAbility_Struct)
SETUP_VAR_ENCODE(GuildTributeAbility_Struct)
ALLOC_VAR_ENCODE(structs::GuildTributeAbility_Struct, sizeof(GuildTributeAbility_Struct) + strlen(emu->ability.name))
eq->guild_id = emu->guild_id;
eq->ability.tribute_id = emu->ability.tribute_id;
eq->ability.tier_count = emu->ability.tier_count;
strncpy(eq->ability.name, emu->ability.name, strlen(emu->ability.name));
for (int i = 0; i < ntohl(emu->ability.tier_count); i++) {
eq->ability.tiers[i].cost = emu->ability.tiers[i].cost;
eq->ability.tiers[i].level = emu->ability.tiers[i].level;
eq->ability.tiers[i].tribute_item_id = emu->ability.tiers[i].tribute_item_id;
}
FINISH_ENCODE()
}
ENCODE(OP_GuildTributeDonateItem)
{
SETUP_DIRECT_ENCODE(GuildTributeDonateItemReply_Struct, structs::GuildTributeDonateItemReply_Struct);
Log(Logs::Detail, Logs::Netcode, "UF::ENCODE(OP_GuildTributeDonateItem)");
OUT(quantity)
OUT(favor)
eq->unknown8 = 0;
eq->slot = ServerToUFSlot(emu->slot);
FINISH_ENCODE()
}
ENCODE(OP_Illusion)
{
ENCODE_LENGTH_EXACT(Illusion_Struct);
@ -1829,6 +1950,29 @@ namespace UF
OUT(pvp);
OUT(anon);
OUT(gm);
//Translate older ranks to new values* /
switch (emu->guildrank) {
case GUILD_SENIOR_MEMBER:
case GUILD_MEMBER:
case GUILD_JUNIOR_MEMBER:
case GUILD_INITIATE:
case GUILD_RECRUIT: {
emu->guildrank = GUILD_MEMBER_TI;
break;
}
case GUILD_OFFICER:
case GUILD_SENIOR_OFFICER: {
emu->guildrank = GUILD_OFFICER_TI;
break;
}
case GUILD_LEADER: {
emu->guildrank = GUILD_LEADER_TI;
break;
}
default: {
break;
}
}
OUT(guildrank);
OUT(guildbanker);
// OUT(unknown13054[12]);
@ -2332,29 +2476,83 @@ namespace UF
ENCODE(OP_SpawnAppearance)
{
EQApplicationPacket *in = *p;
*p = nullptr;
ENCODE_LENGTH_EXACT(SpawnAppearance_Struct);
SETUP_DIRECT_ENCODE(SpawnAppearance_Struct, structs::SpawnAppearance_Struct);
unsigned char *emu_buffer = in->pBuffer;
SpawnAppearance_Struct *sas = (SpawnAppearance_Struct *)emu_buffer;
if (sas->type != AppearanceType::Size)
{
dest->FastQueuePacket(&in, ack_req);
return;
OUT(spawn_id);
OUT(type);
OUT(parameter);
switch (emu->type) {
case AppearanceType::GuildRank: {
//Translate new ranks to old values* /
switch (emu->parameter) {
case GUILD_SENIOR_MEMBER:
case GUILD_MEMBER:
case GUILD_JUNIOR_MEMBER:
case GUILD_INITIATE:
case GUILD_RECRUIT: {
eq->parameter = GUILD_MEMBER_TI;
break;
}
case GUILD_OFFICER:
case GUILD_SENIOR_OFFICER: {
eq->parameter = GUILD_OFFICER_TI;
break;
}
case GUILD_LEADER: {
eq->parameter = GUILD_LEADER_TI;
break;
}
}
break;
}
case AppearanceType::GuildShow: {
FAIL_ENCODE();
return;
}
default: {
break;
}
}
auto outapp = new EQApplicationPacket(OP_ChangeSize, sizeof(ChangeSize_Struct));
ChangeSize_Struct *css = (ChangeSize_Struct *)outapp->pBuffer;
FINISH_ENCODE();
}
css->EntityID = sas->spawn_id;
css->Size = (float)sas->parameter;
css->Unknown08 = 0;
css->Unknown12 = 1.0f;
ENCODE(OP_SetGuildRank)
{
ENCODE_LENGTH_EXACT(GuildSetRank_Struct);
SETUP_DIRECT_ENCODE(GuildSetRank_Struct, structs::GuildSetRank_Struct);
dest->FastQueuePacket(&outapp, ack_req);
delete in;
eq->unknown00 = 0;
eq->unknown04 = 0;
switch (emu->rank) {
case GUILD_SENIOR_MEMBER:
case GUILD_MEMBER:
case GUILD_JUNIOR_MEMBER:
case GUILD_INITIATE:
case GUILD_RECRUIT: {
emu->rank = GUILD_MEMBER_TI;
break;
}
case GUILD_OFFICER:
case GUILD_SENIOR_OFFICER: {
emu->rank = GUILD_OFFICER_TI;
break;
}
case GUILD_LEADER: {
emu->rank = GUILD_LEADER_TI;
break;
}
default: {
break;
}
}
memcpy(eq->member_name, emu->member_name, sizeof(eq->member_name));
OUT(banker);
FINISH_ENCODE();
}
ENCODE(OP_SpawnDoor)
@ -2945,6 +3143,29 @@ namespace UF
else
{
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->guildID);
//Translate older ranks to new values* /
switch (emu->guildrank) {
case GUILD_SENIOR_MEMBER:
case GUILD_MEMBER:
case GUILD_JUNIOR_MEMBER:
case GUILD_INITIATE:
case GUILD_RECRUIT: {
emu->guildrank = GUILD_MEMBER_TI;
break;
}
case GUILD_OFFICER:
case GUILD_SENIOR_OFFICER: {
emu->guildrank = GUILD_OFFICER_TI;
break;
}
case GUILD_LEADER: {
emu->guildrank = GUILD_LEADER_TI;
break;
}
default: {
break;
}
}
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->guildrank);
}
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->class_);
@ -3577,6 +3798,34 @@ namespace UF
DECODE_FORWARD(OP_GroupInvite);
}
DECODE(OP_GuildDemote)
{
DECODE_LENGTH_EXACT(structs::GuildDemoteStruct);
SETUP_DIRECT_DECODE(GuildDemoteStruct, structs::GuildDemoteStruct);
memcpy(emu->name, eq->name, sizeof(emu->name));
memcpy(emu->target, eq->target, sizeof(emu->target));
emu->rank = GUILD_MEMBER;
FINISH_DIRECT_DECODE();
}
DECODE(OP_GuildTributeDonateItem)
{
DECODE_LENGTH_EXACT(structs::GuildTributeDonateItemRequest_Struct);
SETUP_DIRECT_DECODE(GuildTributeDonateItemRequest_Struct, structs::GuildTributeDonateItemRequest_Struct);
Log(Logs::Detail, Logs::Netcode, "UF::DECODE(OP_GuildTributeDonateItem)");
IN(quantity);
IN(tribute_master_id);
IN(guild_id);
emu->slot = UFToServerSlot(eq->slot);
FINISH_DIRECT_DECODE();
}
DECODE(OP_InspectRequest)
{
DECODE_LENGTH_EXACT(structs::Inspect_Struct);

View File

@ -58,6 +58,10 @@ E(OP_GroupInvite)
E(OP_GroupUpdate)
E(OP_GuildMemberList)
E(OP_GuildsList)
E(OP_GuildMemberAdd)
E(OP_SendGuildTributes)
E(OP_GuildMemberRankAltBanker)
E(OP_GuildTributeDonateItem)
E(OP_Illusion)
E(OP_InspectBuffs)
E(OP_InspectRequest)
@ -82,6 +86,7 @@ E(OP_RespondAA)
E(OP_SendAATable)
E(OP_SendCharInfo)
E(OP_SendZonepoints)
E(OP_SetGuildRank)
E(OP_ShopPlayerBuy)
E(OP_ShopPlayerSell)
E(OP_SomeItemPacketMaybe)
@ -138,6 +143,8 @@ D(OP_GroupFollow)
D(OP_GroupFollow2)
D(OP_GroupInvite)
D(OP_GroupInvite2)
D(OP_GuildDemote)
D(OP_GuildTributeDonateItem)
D(OP_InspectRequest)
D(OP_ItemLinkClick)
D(OP_ItemVerifyRequest)

View File

@ -1670,6 +1670,15 @@ struct Surname_Struct
/*0100*/
};
struct GuildSetRank_Struct
{
/*00*/ uint32 unknown00;
/*04*/ uint32 unknown04;
/*08*/ uint32 rank;
/*72*/ char member_name[64];
/*76*/ uint32 banker;
};
struct GuildsListEntry_Struct {
char name[64];
};
@ -1685,6 +1694,27 @@ struct GuildUpdate_Struct {
GuildsListEntry_Struct entry;
};
struct GuildMemberAdd_Struct {
/*000*/ uint32 guild_id;
/*004*/ uint32 unknown04;
/*008*/ uint32 unknown08;
/*012*/ uint32 unknown12;
/*016*/ uint32 level;
/*020*/ uint32 class_;
/*024*/ uint32 rank_;
/*028*/ uint32 zone_id;
/*032*/ uint32 last_on;
/*036*/ char player_name[64];
};
struct GuildMemberRank_Struct {
/*000*/ uint32 guild_id;
/*004*/ uint32 unknown_004;
/*008*/ uint32 rank_;
/*012*/ char player_name[64];
/*076*/ uint32 alt_banker; //Banker/Alt bit 00 - none 10 - Alt 11 - Alt and Banker 01 - Banker. Banker not functional for RoF2+
};
/*
** Money Loot
** Length: 22 Bytes
@ -3067,6 +3097,23 @@ struct GuildMakeLeader{
char target[64];
};
struct GuildTributeDonateItemRequest_Struct {
/*000*/ uint32 slot;
/*004*/ uint32 quantity;
/*008*/ uint32 tribute_master_id;
/*012*/ uint32 unknown12;
/*016*/ uint32 guild_id;
/*020*/ uint32 unknown20;
/*024*/ uint32 unknown24;
};
struct GuildTributeDonateItemReply_Struct {
/*000*/ uint32 slot;
/*004*/ uint32 quantity;
/*008*/ uint32 unknown8;
/*012*/ uint32 favor;
};
struct Make_Pet_Struct { //Simple struct for getting pet info
uint8 level;
uint8 class_;

View File

@ -0,0 +1,404 @@
/**
* DO NOT MODIFY THIS FILE
*
* This repository was automatically generated and is NOT to be modified directly.
* Any repository modifications are meant to be made to the repository extending the base.
* Any modifications to base repositories are to be made by the generator only
*
* @generator ./utils/scripts/generators/repository-generator.pl
* @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories
*/
#ifndef EQEMU_BASE_GUILD_BANK_REPOSITORY_H
#define EQEMU_BASE_GUILD_BANK_REPOSITORY_H
#include "../../database.h"
#include "../../strings.h"
#include <ctime>
class BaseGuildBankRepository {
public:
struct GuildBank {
uint32_t id;
uint32_t guildid;
uint8_t area;
uint32_t slot;
uint32_t itemid;
uint32_t qty;
std::string donator;
uint8_t permissions;
std::string whofor;
};
static std::string PrimaryKey()
{
return std::string("id");
}
static std::vector<std::string> Columns()
{
return {
"id",
"guildid",
"area",
"slot",
"itemid",
"qty",
"donator",
"permissions",
"whofor",
};
}
static std::vector<std::string> SelectColumns()
{
return {
"id",
"guildid",
"area",
"slot",
"itemid",
"qty",
"donator",
"permissions",
"whofor",
};
}
static std::string ColumnsRaw()
{
return std::string(Strings::Implode(", ", Columns()));
}
static std::string SelectColumnsRaw()
{
return std::string(Strings::Implode(", ", SelectColumns()));
}
static std::string TableName()
{
return std::string("guild_bank");
}
static std::string BaseSelect()
{
return fmt::format(
"SELECT {} FROM {}",
SelectColumnsRaw(),
TableName()
);
}
static std::string BaseInsert()
{
return fmt::format(
"INSERT INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static GuildBank NewEntity()
{
GuildBank e{};
e.id = 0;
e.guildid = 0;
e.area = 0;
e.slot = 0;
e.itemid = 0;
e.qty = 0;
e.donator = "";
e.permissions = 0;
e.whofor = "";
return e;
}
static GuildBank GetGuildBank(
const std::vector<GuildBank> &guild_banks,
int guild_bank_id
)
{
for (auto &guild_bank : guild_banks) {
if (guild_bank.id == guild_bank_id) {
return guild_bank;
}
}
return NewEntity();
}
static GuildBank FindOne(
Database& db,
int guild_bank_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE {} = {} LIMIT 1",
BaseSelect(),
PrimaryKey(),
guild_bank_id
)
);
auto row = results.begin();
if (results.RowCount() == 1) {
GuildBank e{};
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.guildid = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.area = static_cast<uint8_t>(strtoul(row[2], nullptr, 10));
e.slot = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
e.itemid = static_cast<uint32_t>(strtoul(row[4], nullptr, 10));
e.qty = static_cast<uint32_t>(strtoul(row[5], nullptr, 10));
e.donator = row[6] ? row[6] : "";
e.permissions = static_cast<uint8_t>(strtoul(row[7], nullptr, 10));
e.whofor = row[8] ? row[8] : "";
return e;
}
return NewEntity();
}
static int DeleteOne(
Database& db,
int guild_bank_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {} = {}",
TableName(),
PrimaryKey(),
guild_bank_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int UpdateOne(
Database& db,
const GuildBank &e
)
{
std::vector<std::string> v;
auto columns = Columns();
v.push_back(columns[1] + " = " + std::to_string(e.guildid));
v.push_back(columns[2] + " = " + std::to_string(e.area));
v.push_back(columns[3] + " = " + std::to_string(e.slot));
v.push_back(columns[4] + " = " + std::to_string(e.itemid));
v.push_back(columns[5] + " = " + std::to_string(e.qty));
v.push_back(columns[6] + " = '" + Strings::Escape(e.donator) + "'");
v.push_back(columns[7] + " = " + std::to_string(e.permissions));
v.push_back(columns[8] + " = '" + Strings::Escape(e.whofor) + "'");
auto results = db.QueryDatabase(
fmt::format(
"UPDATE {} SET {} WHERE {} = {}",
TableName(),
Strings::Implode(", ", v),
PrimaryKey(),
e.id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static GuildBank InsertOne(
Database& db,
GuildBank e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.guildid));
v.push_back(std::to_string(e.area));
v.push_back(std::to_string(e.slot));
v.push_back(std::to_string(e.itemid));
v.push_back(std::to_string(e.qty));
v.push_back("'" + Strings::Escape(e.donator) + "'");
v.push_back(std::to_string(e.permissions));
v.push_back("'" + Strings::Escape(e.whofor) + "'");
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseInsert(),
Strings::Implode(",", v)
)
);
if (results.Success()) {
e.id = results.LastInsertedID();
return e;
}
e = NewEntity();
return e;
}
static int InsertMany(
Database& db,
const std::vector<GuildBank> &entries
)
{
std::vector<std::string> insert_chunks;
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.guildid));
v.push_back(std::to_string(e.area));
v.push_back(std::to_string(e.slot));
v.push_back(std::to_string(e.itemid));
v.push_back(std::to_string(e.qty));
v.push_back("'" + Strings::Escape(e.donator) + "'");
v.push_back(std::to_string(e.permissions));
v.push_back("'" + Strings::Escape(e.whofor) + "'");
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
std::vector<std::string> v;
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES {}",
BaseInsert(),
Strings::Implode(",", insert_chunks)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static std::vector<GuildBank> All(Database& db)
{
std::vector<GuildBank> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{}",
BaseSelect()
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
GuildBank e{};
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.guildid = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.area = static_cast<uint8_t>(strtoul(row[2], nullptr, 10));
e.slot = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
e.itemid = static_cast<uint32_t>(strtoul(row[4], nullptr, 10));
e.qty = static_cast<uint32_t>(strtoul(row[5], nullptr, 10));
e.donator = row[6] ? row[6] : "";
e.permissions = static_cast<uint8_t>(strtoul(row[7], nullptr, 10));
e.whofor = row[8] ? row[8] : "";
all_entries.push_back(e);
}
return all_entries;
}
static std::vector<GuildBank> GetWhere(Database& db, const std::string &where_filter)
{
std::vector<GuildBank> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE {}",
BaseSelect(),
where_filter
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
GuildBank e{};
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.guildid = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.area = static_cast<uint8_t>(strtoul(row[2], nullptr, 10));
e.slot = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
e.itemid = static_cast<uint32_t>(strtoul(row[4], nullptr, 10));
e.qty = static_cast<uint32_t>(strtoul(row[5], nullptr, 10));
e.donator = row[6] ? row[6] : "";
e.permissions = static_cast<uint8_t>(strtoul(row[7], nullptr, 10));
e.whofor = row[8] ? row[8] : "";
all_entries.push_back(e);
}
return all_entries;
}
static int DeleteWhere(Database& db, const std::string &where_filter)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {}",
TableName(),
where_filter
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int Truncate(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"TRUNCATE TABLE {}",
TableName()
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int64 GetMaxId(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COALESCE(MAX({}), 0) FROM {}",
PrimaryKey(),
TableName()
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
static int64 Count(Database& db, const std::string &where_filter = "")
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COUNT(*) FROM {} {}",
TableName(),
(where_filter.empty() ? "" : "WHERE " + where_filter)
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
};
#endif //EQEMU_BASE_GUILD_BANK_REPOSITORY_H

View File

@ -0,0 +1,416 @@
/**
* DO NOT MODIFY THIS FILE
*
* This repository was automatically generated and is NOT to be modified directly.
* Any repository modifications are meant to be made to the repository extending the base.
* Any modifications to base repositories are to be made by the generator only
*
* @generator ./utils/scripts/generators/repository-generator.pl
* @docs https://docs.eqemu.io/developer/repositories
*/
#ifndef EQEMU_BASE_GUILD_PERMISSIONS_REPOSITORY_H
#define EQEMU_BASE_GUILD_PERMISSIONS_REPOSITORY_H
#include "../../database.h"
#include "../../strings.h"
#include <ctime>
class BaseGuildPermissionsRepository {
public:
struct GuildPermissions {
int32_t id;
int32_t perm_id;
int32_t guild_id;
int32_t permission;
};
static std::string PrimaryKey()
{
return std::string("id");
}
static std::vector<std::string> Columns()
{
return {
"id",
"perm_id",
"guild_id",
"permission",
};
}
static std::vector<std::string> SelectColumns()
{
return {
"id",
"perm_id",
"guild_id",
"permission",
};
}
static std::string ColumnsRaw()
{
return std::string(Strings::Implode(", ", Columns()));
}
static std::string SelectColumnsRaw()
{
return std::string(Strings::Implode(", ", SelectColumns()));
}
static std::string TableName()
{
return std::string("guild_permissions");
}
static std::string BaseSelect()
{
return fmt::format(
"SELECT {} FROM {}",
SelectColumnsRaw(),
TableName()
);
}
static std::string BaseInsert()
{
return fmt::format(
"INSERT INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static GuildPermissions NewEntity()
{
GuildPermissions e{};
e.id = 0;
e.perm_id = 0;
e.guild_id = 0;
e.permission = 0;
return e;
}
static GuildPermissions GetGuildPermissions(
const std::vector<GuildPermissions> &guild_permissionss,
int guild_permissions_id
)
{
for (auto &guild_permissions : guild_permissionss) {
if (guild_permissions.id == guild_permissions_id) {
return guild_permissions;
}
}
return NewEntity();
}
static GuildPermissions FindOne(
Database& db,
int guild_permissions_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE {} = {} LIMIT 1",
BaseSelect(),
PrimaryKey(),
guild_permissions_id
)
);
auto row = results.begin();
if (results.RowCount() == 1) {
GuildPermissions e{};
e.id = static_cast<int32_t>(atoi(row[0]));
e.perm_id = static_cast<int32_t>(atoi(row[1]));
e.guild_id = static_cast<int32_t>(atoi(row[2]));
e.permission = static_cast<int32_t>(atoi(row[3]));
return e;
}
return NewEntity();
}
static int DeleteOne(
Database& db,
int guild_permissions_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {} = {}",
TableName(),
PrimaryKey(),
guild_permissions_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int UpdateOne(
Database& db,
const GuildPermissions &e
)
{
std::vector<std::string> v;
auto columns = Columns();
v.push_back(columns[1] + " = " + std::to_string(e.perm_id));
v.push_back(columns[2] + " = " + std::to_string(e.guild_id));
v.push_back(columns[3] + " = " + std::to_string(e.permission));
auto results = db.QueryDatabase(
fmt::format(
"UPDATE {} SET {} WHERE {} = {}",
TableName(),
Strings::Implode(", ", v),
PrimaryKey(),
e.id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static GuildPermissions InsertOne(
Database& db,
GuildPermissions e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.perm_id));
v.push_back(std::to_string(e.guild_id));
v.push_back(std::to_string(e.permission));
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseInsert(),
Strings::Implode(",", v)
)
);
if (results.Success()) {
e.id = results.LastInsertedID();
return e;
}
e = NewEntity();
return e;
}
static int InsertMany(
Database& db,
const std::vector<GuildPermissions> &entries
)
{
std::vector<std::string> insert_chunks;
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.perm_id));
v.push_back(std::to_string(e.guild_id));
v.push_back(std::to_string(e.permission));
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
std::vector<std::string> v;
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES {}",
BaseInsert(),
Strings::Implode(",", insert_chunks)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static std::vector<GuildPermissions> All(Database& db)
{
std::vector<GuildPermissions> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{}",
BaseSelect()
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
GuildPermissions e{};
e.id = static_cast<int32_t>(atoi(row[0]));
e.perm_id = static_cast<int32_t>(atoi(row[1]));
e.guild_id = static_cast<int32_t>(atoi(row[2]));
e.permission = static_cast<int32_t>(atoi(row[3]));
all_entries.push_back(e);
}
return all_entries;
}
static std::vector<GuildPermissions> GetWhere(Database& db, const std::string &where_filter)
{
std::vector<GuildPermissions> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE {}",
BaseSelect(),
where_filter
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
GuildPermissions e{};
e.id = static_cast<int32_t>(atoi(row[0]));
e.perm_id = static_cast<int32_t>(atoi(row[1]));
e.guild_id = static_cast<int32_t>(atoi(row[2]));
e.permission = static_cast<int32_t>(atoi(row[3]));
all_entries.push_back(e);
}
return all_entries;
}
static int DeleteWhere(Database& db, const std::string &where_filter)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {}",
TableName(),
where_filter
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int Truncate(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"TRUNCATE TABLE {}",
TableName()
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int64 GetMaxId(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COALESCE(MAX({}), 0) FROM {}",
PrimaryKey(),
TableName()
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
static int64 Count(Database& db, const std::string &where_filter = "")
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COUNT(*) FROM {} {}",
TableName(),
(where_filter.empty() ? "" : "WHERE " + where_filter)
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
static std::string BaseReplace()
{
return fmt::format(
"REPLACE INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static int ReplaceOne(
Database& db,
const GuildPermissions &e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.perm_id));
v.push_back(std::to_string(e.guild_id));
v.push_back(std::to_string(e.permission));
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseReplace(),
Strings::Implode(",", v)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int ReplaceMany(
Database& db,
const std::vector<GuildPermissions> &entries
)
{
std::vector<std::string> insert_chunks;
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.perm_id));
v.push_back(std::to_string(e.guild_id));
v.push_back(std::to_string(e.permission));
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
std::vector<std::string> v;
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES {}",
BaseReplace(),
Strings::Implode(",", insert_chunks)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
};
#endif //EQEMU_BASE_GUILD_PERMISSIONS_REPOSITORY_H

View File

@ -0,0 +1,453 @@
/**
* DO NOT MODIFY THIS FILE
*
* This repository was automatically generated and is NOT to be modified directly.
* Any repository modifications are meant to be made to the repository extending the base.
* Any modifications to base repositories are to be made by the generator only
*
* @generator ./utils/scripts/generators/repository-generator.pl
* @docs https://docs.eqemu.io/developer/repositories
*/
#ifndef EQEMU_BASE_GUILD_TRIBUTES_REPOSITORY_H
#define EQEMU_BASE_GUILD_TRIBUTES_REPOSITORY_H
#include "../../database.h"
#include "../../strings.h"
#include <ctime>
class BaseGuildTributesRepository {
public:
struct GuildTributes {
uint32_t guild_id;
uint32_t tribute_id_1;
uint32_t tribute_id_1_tier;
uint32_t tribute_id_2;
uint32_t tribute_id_2_tier;
uint32_t time_remaining;
uint32_t enabled;
};
static std::string PrimaryKey()
{
return std::string("guild_id");
}
static std::vector<std::string> Columns()
{
return {
"guild_id",
"tribute_id_1",
"tribute_id_1_tier",
"tribute_id_2",
"tribute_id_2_tier",
"time_remaining",
"enabled",
};
}
static std::vector<std::string> SelectColumns()
{
return {
"guild_id",
"tribute_id_1",
"tribute_id_1_tier",
"tribute_id_2",
"tribute_id_2_tier",
"time_remaining",
"enabled",
};
}
static std::string ColumnsRaw()
{
return std::string(Strings::Implode(", ", Columns()));
}
static std::string SelectColumnsRaw()
{
return std::string(Strings::Implode(", ", SelectColumns()));
}
static std::string TableName()
{
return std::string("guild_tributes");
}
static std::string BaseSelect()
{
return fmt::format(
"SELECT {} FROM {}",
SelectColumnsRaw(),
TableName()
);
}
static std::string BaseInsert()
{
return fmt::format(
"INSERT INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static GuildTributes NewEntity()
{
GuildTributes e{};
e.guild_id = 0;
e.tribute_id_1 = 0;
e.tribute_id_1_tier = 0;
e.tribute_id_2 = 0;
e.tribute_id_2_tier = 0;
e.time_remaining = 0;
e.enabled = 0;
return e;
}
static GuildTributes GetGuildTributes(
const std::vector<GuildTributes> &guild_tributess,
int guild_tributes_id
)
{
for (auto &guild_tributes : guild_tributess) {
if (guild_tributes.guild_id == guild_tributes_id) {
return guild_tributes;
}
}
return NewEntity();
}
static GuildTributes FindOne(
Database& db,
int guild_tributes_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE {} = {} LIMIT 1",
BaseSelect(),
PrimaryKey(),
guild_tributes_id
)
);
auto row = results.begin();
if (results.RowCount() == 1) {
GuildTributes e{};
e.guild_id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.tribute_id_1 = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.tribute_id_1_tier = static_cast<uint32_t>(strtoul(row[2], nullptr, 10));
e.tribute_id_2 = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
e.tribute_id_2_tier = static_cast<uint32_t>(strtoul(row[4], nullptr, 10));
e.time_remaining = static_cast<uint32_t>(strtoul(row[5], nullptr, 10));
e.enabled = static_cast<uint32_t>(strtoul(row[6], nullptr, 10));
return e;
}
return NewEntity();
}
static int DeleteOne(
Database& db,
int guild_tributes_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {} = {}",
TableName(),
PrimaryKey(),
guild_tributes_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int UpdateOne(
Database& db,
const GuildTributes &e
)
{
std::vector<std::string> v;
auto columns = Columns();
v.push_back(columns[0] + " = " + std::to_string(e.guild_id));
v.push_back(columns[1] + " = " + std::to_string(e.tribute_id_1));
v.push_back(columns[2] + " = " + std::to_string(e.tribute_id_1_tier));
v.push_back(columns[3] + " = " + std::to_string(e.tribute_id_2));
v.push_back(columns[4] + " = " + std::to_string(e.tribute_id_2_tier));
v.push_back(columns[5] + " = " + std::to_string(e.time_remaining));
v.push_back(columns[6] + " = " + std::to_string(e.enabled));
auto results = db.QueryDatabase(
fmt::format(
"UPDATE {} SET {} WHERE {} = {}",
TableName(),
Strings::Implode(", ", v),
PrimaryKey(),
e.guild_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static GuildTributes InsertOne(
Database& db,
GuildTributes e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.guild_id));
v.push_back(std::to_string(e.tribute_id_1));
v.push_back(std::to_string(e.tribute_id_1_tier));
v.push_back(std::to_string(e.tribute_id_2));
v.push_back(std::to_string(e.tribute_id_2_tier));
v.push_back(std::to_string(e.time_remaining));
v.push_back(std::to_string(e.enabled));
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseInsert(),
Strings::Implode(",", v)
)
);
if (results.Success()) {
e.guild_id = results.LastInsertedID();
return e;
}
e = NewEntity();
return e;
}
static int InsertMany(
Database& db,
const std::vector<GuildTributes> &entries
)
{
std::vector<std::string> insert_chunks;
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.guild_id));
v.push_back(std::to_string(e.tribute_id_1));
v.push_back(std::to_string(e.tribute_id_1_tier));
v.push_back(std::to_string(e.tribute_id_2));
v.push_back(std::to_string(e.tribute_id_2_tier));
v.push_back(std::to_string(e.time_remaining));
v.push_back(std::to_string(e.enabled));
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
std::vector<std::string> v;
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES {}",
BaseInsert(),
Strings::Implode(",", insert_chunks)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static std::vector<GuildTributes> All(Database& db)
{
std::vector<GuildTributes> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{}",
BaseSelect()
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
GuildTributes e{};
e.guild_id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.tribute_id_1 = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.tribute_id_1_tier = static_cast<uint32_t>(strtoul(row[2], nullptr, 10));
e.tribute_id_2 = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
e.tribute_id_2_tier = static_cast<uint32_t>(strtoul(row[4], nullptr, 10));
e.time_remaining = static_cast<uint32_t>(strtoul(row[5], nullptr, 10));
e.enabled = static_cast<uint32_t>(strtoul(row[6], nullptr, 10));
all_entries.push_back(e);
}
return all_entries;
}
static std::vector<GuildTributes> GetWhere(Database& db, const std::string &where_filter)
{
std::vector<GuildTributes> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE {}",
BaseSelect(),
where_filter
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
GuildTributes e{};
e.guild_id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.tribute_id_1 = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.tribute_id_1_tier = static_cast<uint32_t>(strtoul(row[2], nullptr, 10));
e.tribute_id_2 = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
e.tribute_id_2_tier = static_cast<uint32_t>(strtoul(row[4], nullptr, 10));
e.time_remaining = static_cast<uint32_t>(strtoul(row[5], nullptr, 10));
e.enabled = static_cast<uint32_t>(strtoul(row[6], nullptr, 10));
all_entries.push_back(e);
}
return all_entries;
}
static int DeleteWhere(Database& db, const std::string &where_filter)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {}",
TableName(),
where_filter
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int Truncate(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"TRUNCATE TABLE {}",
TableName()
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int64 GetMaxId(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COALESCE(MAX({}), 0) FROM {}",
PrimaryKey(),
TableName()
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
static int64 Count(Database& db, const std::string &where_filter = "")
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COUNT(*) FROM {} {}",
TableName(),
(where_filter.empty() ? "" : "WHERE " + where_filter)
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
static std::string BaseReplace()
{
return fmt::format(
"REPLACE INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static int ReplaceOne(
Database& db,
const GuildTributes &e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.guild_id));
v.push_back(std::to_string(e.tribute_id_1));
v.push_back(std::to_string(e.tribute_id_1_tier));
v.push_back(std::to_string(e.tribute_id_2));
v.push_back(std::to_string(e.tribute_id_2_tier));
v.push_back(std::to_string(e.time_remaining));
v.push_back(std::to_string(e.enabled));
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseReplace(),
Strings::Implode(",", v)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int ReplaceMany(
Database& db,
const std::vector<GuildTributes> &entries
)
{
std::vector<std::string> insert_chunks;
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.guild_id));
v.push_back(std::to_string(e.tribute_id_1));
v.push_back(std::to_string(e.tribute_id_1_tier));
v.push_back(std::to_string(e.tribute_id_2));
v.push_back(std::to_string(e.tribute_id_2_tier));
v.push_back(std::to_string(e.time_remaining));
v.push_back(std::to_string(e.enabled));
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
std::vector<std::string> v;
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES {}",
BaseReplace(),
Strings::Implode(",", insert_chunks)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
};
#endif //EQEMU_BASE_GUILD_TRIBUTES_REPOSITORY_H

View File

@ -16,6 +16,7 @@
#include "../../strings.h"
#include <ctime>
class BaseGuildsRepository {
public:
struct Guilds {

View File

@ -3,286 +3,47 @@
#include "../database.h"
#include "../strings.h"
#include "base/base_guild_bank_repository.h"
class GuildBankRepository {
class GuildBankRepository: public BaseGuildBankRepository {
public:
struct GuildBank {
int guildid;
int8 area;
int slot;
int itemid;
int qty;
std::string donator;
int8 permissions;
std::string whofor;
};
static std::string PrimaryKey()
{
return std::string("");
}
/**
* This file was auto generated and can be modified and extended upon
*
* Base repository methods are automatically
* generated in the "base" version of this repository. The base repository
* is immutable and to be left untouched, while methods in this class
* are used as extension methods for more specific persistence-layer
* accessors or mutators.
*
* Base Methods (Subject to be expanded upon in time)
*
* Note: Not all tables are designed appropriately to fit functionality with all base methods
*
* InsertOne
* UpdateOne
* DeleteOne
* FindOne
* GetWhere(std::string where_filter)
* DeleteWhere(std::string where_filter)
* InsertMany
* All
*
* Example custom methods in a repository
*
* GuildBankRepository::GetByZoneAndVersion(int zone_id, int zone_version)
* GuildBankRepository::GetWhereNeverExpires()
* GuildBankRepository::GetWhereXAndY()
* GuildBankRepository::DeleteWhereXAndY()
*
* Most of the above could be covered by base methods, but if you as a developer
* find yourself re-using logic for other parts of the code, its best to just make a
* method that can be re-used easily elsewhere especially if it can use a base repository
* method and encapsulate filters there
*/
static std::vector<std::string> Columns()
{
return {
"guildid",
"area",
"slot",
"itemid",
"qty",
"donator",
"permissions",
"whofor",
};
}
static std::string ColumnsRaw()
{
return std::string(Strings::Implode(", ", Columns()));
}
static std::string InsertColumnsRaw()
{
std::vector<std::string> insert_columns;
for (auto &column : Columns()) {
if (column == PrimaryKey()) {
continue;
}
insert_columns.push_back(column);
}
return std::string(Strings::Implode(", ", insert_columns));
}
static std::string TableName()
{
return std::string("guild_bank");
}
static std::string BaseSelect()
{
return fmt::format(
"SELECT {} FROM {}",
ColumnsRaw(),
TableName()
);
}
static std::string BaseInsert()
{
return fmt::format(
"INSERT INTO {} ({}) ",
TableName(),
InsertColumnsRaw()
);
}
static GuildBank NewEntity()
{
GuildBank entry{};
entry.guildid = 0;
entry.area = 0;
entry.slot = 0;
entry.itemid = 0;
entry.qty = 0;
entry.donator = 0;
entry.permissions = 0;
entry.whofor = 0;
return entry;
}
static GuildBank GetGuildBankEntry(
const std::vector<GuildBank> &guild_banks,
int guild_bank_id
)
{
for (auto &guild_bank : guild_banks) {
if (guild_bank. == guild_bank_id) {
return guild_bank;
}
}
return NewEntity();
}
static GuildBank FindOne(
int guild_bank_id
)
{
auto results = database.QueryDatabase(
fmt::format(
"{} WHERE id = {} LIMIT 1",
BaseSelect(),
guild_bank_id
)
);
auto row = results.begin();
if (results.RowCount() == 1) {
GuildBank entry{};
entry.guildid = atoi(row[0]);
entry.area = atoi(row[1]);
entry.slot = atoi(row[2]);
entry.itemid = atoi(row[3]);
entry.qty = atoi(row[4]);
entry.donator = row[5];
entry.permissions = atoi(row[6]);
entry.whofor = row[7];
return entry;
}
return NewEntity();
}
static int DeleteOne(
int guild_bank_id
)
{
auto results = database.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {} = {}",
TableName(),
PrimaryKey(),
guild_bank_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int UpdateOne(
GuildBank guild_bank_entry
)
{
std::vector<std::string> update_values;
auto columns = Columns();
update_values.push_back(columns[0] + " = " + std::to_string(guild_bank_entry.guildid));
update_values.push_back(columns[1] + " = " + std::to_string(guild_bank_entry.area));
update_values.push_back(columns[2] + " = " + std::to_string(guild_bank_entry.slot));
update_values.push_back(columns[3] + " = " + std::to_string(guild_bank_entry.itemid));
update_values.push_back(columns[4] + " = " + std::to_string(guild_bank_entry.qty));
update_values.push_back(columns[5] + " = '" + Strings::Escape(guild_bank_entry.donator) + "'");
update_values.push_back(columns[6] + " = " + std::to_string(guild_bank_entry.permissions));
update_values.push_back(columns[7] + " = '" + Strings::Escape(guild_bank_entry.whofor) + "'");
auto results = database.QueryDatabase(
fmt::format(
"UPDATE {} SET {} WHERE {} = {}",
TableName(),
Strings::Implode(", ", update_values),
PrimaryKey(),
guild_bank_entry.
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static GuildBank InsertOne(
GuildBank guild_bank_entry
)
{
std::vector<std::string> insert_values;
insert_values.push_back(std::to_string(guild_bank_entry.guildid));
insert_values.push_back(std::to_string(guild_bank_entry.area));
insert_values.push_back(std::to_string(guild_bank_entry.slot));
insert_values.push_back(std::to_string(guild_bank_entry.itemid));
insert_values.push_back(std::to_string(guild_bank_entry.qty));
insert_values.push_back("'" + Strings::Escape(guild_bank_entry.donator) + "'");
insert_values.push_back(std::to_string(guild_bank_entry.permissions));
insert_values.push_back("'" + Strings::Escape(guild_bank_entry.whofor) + "'");
auto results = database.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseInsert(),
Strings::Implode(",", insert_values)
)
);
if (results.Success()) {
guild_bank_entry.id = results.LastInsertedID();
return guild_bank_entry;
}
guild_bank_entry = InstanceListRepository::NewEntity();
return guild_bank_entry;
}
static int InsertMany(
std::vector<GuildBank> guild_bank_entries
)
{
std::vector<std::string> insert_chunks;
for (auto &guild_bank_entry: guild_bank_entries) {
std::vector<std::string> insert_values;
insert_values.push_back(std::to_string(guild_bank_entry.guildid));
insert_values.push_back(std::to_string(guild_bank_entry.area));
insert_values.push_back(std::to_string(guild_bank_entry.slot));
insert_values.push_back(std::to_string(guild_bank_entry.itemid));
insert_values.push_back(std::to_string(guild_bank_entry.qty));
insert_values.push_back("'" + Strings::Escape(guild_bank_entry.donator) + "'");
insert_values.push_back(std::to_string(guild_bank_entry.permissions));
insert_values.push_back("'" + Strings::Escape(guild_bank_entry.whofor) + "'");
insert_chunks.push_back("(" + Strings::Implode(",", insert_values) + ")");
}
std::vector<std::string> insert_values;
auto results = database.QueryDatabase(
fmt::format(
"{} VALUES {}",
BaseInsert(),
Strings::Implode(",", insert_chunks)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static std::vector<GuildBank> All()
{
std::vector<GuildBank> all_entries;
auto results = database.QueryDatabase(
fmt::format(
"{}",
BaseSelect()
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
GuildBank entry{};
entry.guildid = atoi(row[0]);
entry.area = atoi(row[1]);
entry.slot = atoi(row[2]);
entry.itemid = atoi(row[3]);
entry.qty = atoi(row[4]);
entry.donator = row[5];
entry.permissions = atoi(row[6]);
entry.whofor = row[7];
all_entries.push_back(entry);
}
return all_entries;
}
// Custom extended repository methods here
};

View File

@ -0,0 +1,194 @@
#ifndef EQEMU_GUILD_MEMBERS_REPOSITORY_H
#define EQEMU_GUILD_MEMBERS_REPOSITORY_H
#include "../database.h"
#include "../strings.h"
#include "base/base_guild_members_repository.h"
class GuildMembersRepository : public BaseGuildMembersRepository {
public:
struct GuildMembersWithTributeOnStruct {
int32_t char_id;
uint32_t guild_id;
uint8_t tribute_enable;
std::string char_name;
uint32_t char_level;
};
struct GuildMembershipStatsStruct {
uint32 leaders;
uint32 senior_officers;
uint32 officers;
uint32 senior_members;
uint32 members;
uint32 junior_members;
uint32 initates;
uint32 recruits;
uint32 tribute_enabled;
};
static int UpdateMemberRank(Database &db, uint32 char_id, uint32 rank_id)
{
const auto guild_members = GetWhere(db, fmt::format("char_id = '{}'", char_id));
if (guild_members.empty()) {
return 0;
}
auto m = guild_members[0];
m.rank_ = rank_id;
return UpdateOne(db, m);
}
static int UpdateEnabled(Database &db, uint32 guild_id, uint32 char_id, uint32 enabled)
{
const auto guild_members = GetWhere(db, fmt::format("char_id = '{}' AND guild_id = '{}'", char_id, guild_id));
if (guild_members.empty()) {
return 0;
}
auto m = guild_members[0];
m.tribute_enable = enabled ? 1 : 0;
return UpdateOne(db, m);
}
static std::vector<GuildMembersWithTributeOnStruct> GetMembersWithTributeOn(Database &db, uint32 guild_id)
{
std::vector<GuildMembersWithTributeOnStruct> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"SELECT gm.char_id, gm.guild_id, gm.tribute_enable, cd.`name`, cd.`level`, cd.deleted_at "
"FROM guild_members gm JOIN character_data cd ON cd.id = gm.char_id "
"WHERE ISNULL(cd.deleted_at) AND gm.tribute_enable = 1 AND gm.guild_id = '{}';",
guild_id
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
GuildMembersWithTributeOnStruct e{};
e.char_id = static_cast<int32_t>(atoi(row[0]));
e.guild_id = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.tribute_enable = static_cast<uint8_t>(strtoul(row[2], nullptr, 10));
e.char_name = row[3] ? row[3] : "";
e.char_level = static_cast<uint32_t>(strtoul(row[4], nullptr, 10));
all_entries.push_back(e);
}
return all_entries;
}
static int UpdateFavor(Database &db, uint32 guild_id, uint32 char_id, uint32 favor)
{
const auto guild_members = GetWhere(db, fmt::format("char_id = '{}' AND guild_id = '{}'", char_id, guild_id));
if (guild_members.empty()) {
return 0;
}
auto m = guild_members[0];
m.total_tribute = favor;
m.last_tribute = time(nullptr);
return UpdateOne(db, m);
}
static int UpdateOnline(Database &db, uint32 char_id, bool status)
{
const auto guild_members = GetWhere(db, fmt::format("char_id = '{}'", char_id));
if (guild_members.empty()) {
return 0;
}
auto m = guild_members[0];
m.online = status ? 1 : 0;
return UpdateOne(db, m);
}
static int UpdateNote(Database &db, uint32 char_id, std::string &public_note)
{
const auto guild_members = GetWhere(db, fmt::format("char_id = '{}'", char_id));
if (guild_members.empty()) {
return 0;
}
auto m = guild_members[0];
m.public_note = public_note;
return UpdateOne(db, m);
}
static GuildMembershipStatsStruct GetGuildMembershipStats(Database &db, uint32 guild_id)
{
std::string query = fmt::format(
"SELECT "
"SUM(CASE WHEN gm.`rank` = 1 THEN 1 ELSE 0 END) AS RANK1, "
"SUM(CASE WHEN gm.`rank` = 2 THEN 1 ELSE 0 END) AS RANK2, "
"SUM(CASE WHEN gm.`rank` = 3 THEN 1 ELSE 0 END) AS RANK3, "
"SUM(CASE WHEN gm.`rank` = 4 THEN 1 ELSE 0 END) AS RANK4, "
"SUM(CASE WHEN gm.`rank` = 5 THEN 1 ELSE 0 END) AS RANK5, "
"SUM(CASE WHEN gm.`rank` = 6 THEN 1 ELSE 0 END) AS RANK6, "
"SUM(CASE WHEN gm.`rank` = 7 THEN 1 ELSE 0 END) AS RANK7, "
"SUM(CASE WHEN gm.`rank` = 8 THEN 1 ELSE 0 END) AS RANK8, "
"SUM(CASE WHEN gm.tribute_enable = 1 THEN 1 ELSE 0 END) AS TRIBUTE "
"FROM guild_members gm "
"WHERE gm.guild_id = '{}';",
guild_id
);
GuildMembershipStatsStruct gmss{};
auto results = db.QueryDatabase(query);
if (!results.Success()) {
return gmss;
}
for (auto row = results.begin(); row != results.end(); ++row) {
gmss.leaders = static_cast<uint32_t>(Strings::ToUnsignedInt(row[0]));
gmss.senior_officers = static_cast<uint32_t>(Strings::ToUnsignedInt(row[1]));
gmss.officers = static_cast<uint32_t>(Strings::ToUnsignedInt(row[2]));
gmss.senior_members = static_cast<uint32_t>(Strings::ToUnsignedInt(row[3]));
gmss.members = static_cast<uint32_t>(Strings::ToUnsignedInt(row[4]));
gmss.junior_members = static_cast<uint32_t>(Strings::ToUnsignedInt(row[5]));
gmss.initates = static_cast<uint32_t>(Strings::ToUnsignedInt(row[6]));
gmss.recruits = static_cast<uint32_t>(Strings::ToUnsignedInt(row[7]));
gmss.tribute_enabled = static_cast<uint32_t>(Strings::ToUnsignedInt(row[8]));
}
return gmss;
}
static int UpdateBankerFlag(Database &db, uint32 char_id, bool status)
{
const auto guild_members = GetWhere(db, fmt::format("char_id = {}", char_id));
if (guild_members.empty()) {
return 0;
}
auto m = guild_members[0];
m.banker = status ? 1 : 0;
return UpdateOne(db, m);
}
static int UpdateAltFlag(Database &db, uint32 char_id, bool status)
{
const auto guild_members = GetWhere(db, fmt::format("char_id = {}", char_id));
if (guild_members.empty()) {
return 0;
}
auto m = guild_members[0];
m.alt = status ? 1 : 0;
return UpdateOne(db, m);
}
};
#endif //EQEMU_GUILD_MEMBERS_REPOSITORY_H

View File

@ -0,0 +1,50 @@
#ifndef EQEMU_GUILD_PERMISSIONS_REPOSITORY_H
#define EQEMU_GUILD_PERMISSIONS_REPOSITORY_H
#include "../database.h"
#include "../strings.h"
#include "base/base_guild_permissions_repository.h"
class GuildPermissionsRepository: public BaseGuildPermissionsRepository {
public:
/**
* This file was auto generated and can be modified and extended upon
*
* Base repository methods are automatically
* generated in the "base" version of this repository. The base repository
* is immutable and to be left untouched, while methods in this class
* are used as extension methods for more specific persistence-layer
* accessors or mutators.
*
* Base Methods (Subject to be expanded upon in time)
*
* Note: Not all tables are designed appropriately to fit functionality with all base methods
*
* InsertOne
* UpdateOne
* DeleteOne
* FindOne
* GetWhere(std::string where_filter)
* DeleteWhere(std::string where_filter)
* InsertMany
* All
*
* Example custom methods in a repository
*
* GuildPermissionsRepository::GetByZoneAndVersion(int zone_id, int zone_version)
* GuildPermissionsRepository::GetWhereNeverExpires()
* GuildPermissionsRepository::GetWhereXAndY()
* GuildPermissionsRepository::DeleteWhereXAndY()
*
* Most of the above could be covered by base methods, but if you as a developer
* find yourself re-using logic for other parts of the code, its best to just make a
* method that can be re-used easily elsewhere especially if it can use a base repository
* method and encapsulate filters there
*/
// Custom extended repository methods here
};
#endif //EQEMU_GUILD_PERMISSIONS_REPOSITORY_H

View File

@ -45,6 +45,21 @@ public:
// Custom extended repository methods here
static int UpdateTitle(Database &db, uint32 guild_id, uint32 rank, std::string title)
{
auto guild_rank = GetWhere(db, fmt::format("guild_id = '{}' AND rank = '{}'", guild_id, rank));
if (guild_rank.empty()) {
return 0;
}
auto r = guild_rank[0];
r.title = title;
DeleteWhere(db, fmt::format("guild_id = '{}' AND rank = '{}'", guild_id, rank));
InsertOne(db, r);
return 1;
}
};
#endif //EQEMU_GUILD_RANKS_REPOSITORY_H

View File

@ -0,0 +1,77 @@
#ifndef EQEMU_GUILD_TRIBUTES_REPOSITORY_H
#define EQEMU_GUILD_TRIBUTES_REPOSITORY_H
#include "../database.h"
#include "../strings.h"
#include "base/base_guild_tributes_repository.h"
class GuildTributesRepository: public BaseGuildTributesRepository {
public:
/**
* This file was auto generated and can be modified and extended upon
*
* Base repository methods are automatically
* generated in the "base" version of this repository. The base repository
* is immutable and to be left untouched, while methods in this class
* are used as extension methods for more specific persistence-layer
* accessors or mutators.
*
* Base Methods (Subject to be expanded upon in time)
*
* Note: Not all tables are designed appropriately to fit functionality with all base methods
*
* InsertOne
* UpdateOne
* DeleteOne
* FindOne
* GetWhere(std::string where_filter)
* DeleteWhere(std::string where_filter)
* InsertMany
* All
*
* Example custom methods in a repository
*
* GuildTributesRepository::GetByZoneAndVersion(int zone_id, int zone_version)
* GuildTributesRepository::GetWhereNeverExpires()
* GuildTributesRepository::GetWhereXAndY()
* GuildTributesRepository::DeleteWhereXAndY()
*
* Most of the above could be covered by base methods, but if you as a developer
* find yourself re-using logic for other parts of the code, its best to just make a
* method that can be re-used easily elsewhere especially if it can use a base repository
* method and encapsulate filters there
*/
// Custom extended repository methods here
static int UpdateEnabled(Database& db, uint32 guild_id, uint32 enabled)
{
auto results = db.QueryDatabase(
fmt::format(
"UPDATE {} SET `enabled` = '{}' WHERE `guild_id` = {}",
TableName(),
enabled,
guild_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int UpdateTimeRemaining(Database& db, uint32 guild_id, uint32 time_remaining)
{
auto results = db.QueryDatabase(
fmt::format(
"UPDATE {} SET `time_remaining` = '{}' WHERE `guild_id` = {}",
TableName(),
time_remaining,
guild_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
};
#endif //EQEMU_GUILD_TRIBUTES_REPOSITORY_H

View File

@ -5,46 +5,58 @@
#include "../strings.h"
#include "base/base_guilds_repository.h"
class GuildsRepository: public BaseGuildsRepository {
class GuildsRepository : public BaseGuildsRepository {
public:
/**
* This file was auto generated and can be modified and extended upon
*
* Base repository methods are automatically
* generated in the "base" version of this repository. The base repository
* is immutable and to be left untouched, while methods in this class
* are used as extension methods for more specific persistence-layer
* accessors or mutators.
*
* Base Methods (Subject to be expanded upon in time)
*
* Note: Not all tables are designed appropriately to fit functionality with all base methods
*
* InsertOne
* UpdateOne
* DeleteOne
* FindOne
* GetWhere(std::string where_filter)
* DeleteWhere(std::string where_filter)
* InsertMany
* All
*
* Example custom methods in a repository
*
* GuildsRepository::GetByZoneAndVersion(int zone_id, int zone_version)
* GuildsRepository::GetWhereNeverExpires()
* GuildsRepository::GetWhereXAndY()
* GuildsRepository::DeleteWhereXAndY()
*
* Most of the above could be covered by base methods, but if you as a developer
* find yourself re-using logic for other parts of the code, its best to just make a
* method that can be re-used easily elsewhere especially if it can use a base repository
* method and encapsulate filters there
*/
/**
* This file was auto generated and can be modified and extended upon
*
* Base repository methods are automatically
* generated in the "base" version of this repository. The base repository
* is immutable and to be left untouched, while methods in this class
* are used as extension methods for more specific persistence-layer
* accessors or mutators.
*
* Base Methods (Subject to be expanded upon in time)
*
* Note: Not all tables are designed appropriately to fit functionality with all base methods
*
* InsertOne
* UpdateOne
* DeleteOne
* FindOne
* GetWhere(std::string where_filter)
* DeleteWhere(std::string where_filter)
* InsertMany
* All
*
* Example custom methods in a repository
*
* GuildsRepository::GetByZoneAndVersion(int zone_id, int zone_version)
* GuildsRepository::GetWhereNeverExpires()
* GuildsRepository::GetWhereXAndY()
* GuildsRepository::DeleteWhereXAndY()
*
* Most of the above could be covered by base methods, but if you as a developer
* find yourself re-using logic for other parts of the code, its best to just make a
* method that can be re-used easily elsewhere especially if it can use a base repository
* method and encapsulate filters there
*/
// Custom extended repository methods here
// Custom extended repository methods here
static int UpdateFavor(Database &db, uint32 guild_id, uint32 favor)
{
auto const guild = GetWhere(db, fmt::format("id = '{}'", guild_id));
if (guild.empty()) {
return 0;
}
auto g = guild[0];
g.favor = favor;
return UpdateOne(db, g);
}
};
#endif //EQEMU_GUILDS_REPOSITORY_H

View File

@ -245,6 +245,10 @@ RULE_INT(Guild, PlayerCreationLimit, 1, "Only allow use of the UF+ window if the
RULE_INT(Guild, PlayerCreationRequiredStatus, 0, "Required status to create a guild")
RULE_INT(Guild, PlayerCreationRequiredLevel, 0, "Required level of the player attempting to create the guild")
RULE_INT(Guild, PlayerCreationRequiredTime, 0, "Time needed online on the account to create a guild (in minutes)")
RULE_INT(Guild, TributeTime, 600000, "Time in ms for guild tributes. Default is 10 mins.")
RULE_INT(Guild, TributeTimeRefreshInterval, 180000, "Time in ms to send all guild members a Tribute Time refresh. Default is 3 mins.")
RULE_INT(Guild, TributePlatConversionRate, 10, "The conversion rate of platinum donations. Default is 10 guild favor to 1 platinum.")
RULE_BOOL(Guild, UseCharacterMaxLevelForGuildTributes, true, "Guild Tributes will adhere to Character:MaxLevel. Default is true.")
RULE_CATEGORY_END()
RULE_CATEGORY(Skills)

View File

@ -5,6 +5,7 @@
#include "../common/packet_functions.h"
#include "../common/eq_packet_structs.h"
#include "../common/net/packet.h"
#include "../common/guilds.h"
#include <cereal/cereal.hpp>
#include <cereal/archives/binary.hpp>
#include <cereal/types/chrono.hpp>
@ -94,6 +95,23 @@
#define ServerOP_WebInterfaceEvent 0x0066
#define ServerOP_WebInterfaceSubscribe 0x0067
#define ServerOP_WebInterfaceUnsubscribe 0x0068
#define ServerOP_GuildPermissionUpdate 0x0069
#define ServerOP_GuildTributeUpdate 0x0070
#define ServerOP_GuildRankNameChange 0x0071
#define ServerOP_GuildTributeActivate 0x0072
#define ServerOP_GuildTributeOptInToggle 0x0073
#define ServerOP_GuildTributeFavAndTimer 0x0074
#define ServerOP_RequestGuildActiveTributes 0x0075
#define ServerOP_RequestGuildFavorAndTimer 0x0076
#define ServerOP_GuildTributeUpdateDonations 0x0077
#define ServerOP_GuildMemberLevelUpdate 0x0078
#define ServerOP_GuildMemberPublicNote 0x0079
#define ServerOP_GuildMemberRemove 0x007A
#define ServerOP_GuildMemberAdd 0x007B
#define ServerOP_GuildChannel 0x007C
#define ServerOP_GuildURL 0x007D
#define ServerOP_GuildSendGuildList 0x007E
#define ServerOP_GuildMembersList 0x007F
#define ServerOP_RaidAdd 0x0100 //in use
#define ServerOP_RaidRemove 0x0101 //in use
@ -567,6 +585,8 @@ struct ServerClientList_Struct {
uint8 anon;
bool tellsoff;
uint32 guild_id;
uint32 guild_rank;
bool guild_tribute_opt_in;
bool LFG;
uint8 gm;
uint8 ClientVersion;
@ -1006,19 +1026,34 @@ struct ServerGuildCharRefresh_Struct {
uint32 char_id;
};
struct ServerGuildRankUpdate_Struct
{
uint32 GuildID;
char MemberName[64];
uint32 Rank;
uint32 Banker;
struct ServerGuildRankUpdate_Struct {
uint32 guild_id;
char member_name[64];
uint32 rank;
uint32 banker;
uint32 alt;
bool no_update;
};
struct ServerGuildMemberUpdate_Struct {
uint32 GuildID;
char MemberName[64];
uint32 ZoneID;
uint32 LastSeen;
uint32 guild_id;
char member_name[64];
uint32 zone_id;
uint32 last_seen;
};
struct ServerGuildPermissionUpdate_Struct {
uint32 guild_id;
char member_name[64];
uint32 rank;
uint32 function_id;
uint32 function_value;
};
struct ServerGuildRankNameChange {
uint32 guild_id;
uint32 rank;
char rank_name[51]; //RoF2 has 51 max.
};
struct SpawnPlayerCorpse_Struct {
@ -1857,6 +1892,47 @@ struct ServerZoneStatus_Struct {
int16 admin;
};
struct GuildTributeUpdate {
uint32 guild_id;
uint32 tribute_id_1;
uint32 tribute_id_2;
uint32 tribute_id_1_tier;
uint32 tribute_id_2_tier;
uint32 enabled;
uint32 favor;
uint32 time_remaining;
uint32 member_favor;
uint32 member_time;
uint32 member_enabled;
char player_name[64];
};
struct GuildTributeMemberToggle {
uint32 guild_id;
uint32 char_id;
char player_name[64];
uint32 tribute_toggle;
uint32 command;
uint32 time_remaining;
uint32 no_donations;
uint32 member_last_donated;
};
struct ServerOP_GuildMessage_Struct {
uint32 guild_id{GUILD_NONE};
char player_name[64]{0};
uint32 player_level{0};
uint32 player_class{0};
uint32 player_rank{GUILD_RANK_NONE};
uint32 player_zone_id{0};
bool player_offline{false};
char player_new_name[64]{0};
char new_guild_name[64]{0};
char note[256]{0};
char channel[2048]{0};
char url[2048]{0};
};
#pragma pack()
#endif

View File

@ -42,8 +42,7 @@
* Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
*/
#define CURRENT_BINARY_DATABASE_VERSION 9259
#define CURRENT_BINARY_DATABASE_VERSION 9260
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9042
#endif

View File

@ -10,27 +10,27 @@
extern WorldServer *worldserver;
extern QSDatabase database;
PlayerLookingForGuild::PlayerLookingForGuild(char *Name, char *Comments, uint32 Level, uint32 Class, uint32 AACount, uint32 Timezone, uint32 TimePosted)
PlayerLookingForGuild::PlayerLookingForGuild(char *name, char *comments, uint32 level, uint32 classes, uint32 aa_count, uint32 time_zone, uint32 time_posted)
{
Name = Name;
Comments = Comments;
Level = Level;
Class = Class;
AACount = AACount;
TimeZone = Timezone;
TimePosted = TimePosted;
Name = std::string(name);
Comments = std::string(comments);
Level = level;
Class = classes;
AACount = aa_count;
TimeZone = time_zone;
TimePosted = time_posted;
}
GuildLookingForPlayers::GuildLookingForPlayers(char *Name, char *Comments, uint32 FromLevel, uint32 ToLevel, uint32 Classes, uint32 AACount, uint32 Timezone, uint32 TimePosted)
GuildLookingForPlayers::GuildLookingForPlayers(char * name, char * comments, uint32 from_level, uint32 to_level, uint32 classes, uint32 aa_count, uint32 time_zone, uint32 time_posted)
{
Name = Name;
Comments = Comments;
FromLevel = FromLevel;
ToLevel = ToLevel;
Classes = Classes;
AACount = AACount;
TimeZone = Timezone;
TimePosted = TimePosted;
Name = std::string(name);
Comments = std::string(comments);
FromLevel = from_level;
ToLevel = to_level;
Classes = classes;
AACount = aa_count;
TimeZone = time_zone;
TimePosted = time_posted;
}
bool LFGuildManager::LoadDatabase()

View File

@ -82,7 +82,7 @@ OP_ChangeSize=0x4707
OP_TributeUpdate=0x5961
OP_TributeTimer=0x073d
OP_SendTributes=0x729b
OP_SendGuildTributes=0x1877
OP_RequestGuildTributes=0x4d5e
OP_TributeInfo=0x4254
OP_Weather=0x661e
OP_ReqClientSpawn=0x35fa
@ -133,16 +133,20 @@ OP_GuildManageBanker=0x3f35
OP_GuildBank=0x5134
OP_GuildBankItemList=0x7850
OP_SetGuildRank=0x0b9c
OP_GuildUpdateURLAndChannel=0x2958
OP_GuildUpdate=0x2958
OP_GuildStatus=0x7326
OP_GuildCreate=0x76d9
OP_GuildMemberLevelUpdate=0x0000 # Unused?
OP_ZoneGuildList=0x0000 # Unused?
OP_GetGuildsList=0x0000 # Unused?
OP_LFGuild=0x0000
OP_GuildManageRemove=0x0000
OP_GuildManageAdd=0x0000
OP_GuildManageStatus=0x0000
OP_GuildOpenGuildWindow=0x0276
OP_GuildMemberLevel=0x1bd3
OP_GuildMemberRankAltBanker=0x0b9c
OP_GuildMemberPublicNote=0x01f9
OP_GuildMemberAdd=0x2925
OP_GuildMemberRename=0x3b26
OP_GuildMemberDelete=0x3141
OP_GuildMemberDetails=0x69b9
OP_GuildRenameGuild=0x61db
OP_LFGuild=0x3165
OP_GuildDeleteGuild=0x6dab
# GM/Guide Opcodes
OP_GMServers=0x08c1
@ -476,7 +480,6 @@ OP_RecipeAutoCombine=0x40d7
OP_TradeSkillCombine=0x579a
# Tribute Packets:
OP_OpenGuildTributeMaster=0x378d
OP_OpenTributeMaster=0x7666
OP_SelectTribute=0x79fc
OP_TributeItem=0x4f3e
@ -487,6 +490,18 @@ OP_TributeNPC=0x0000
OP_GuildTributeInfo=0x0000
OP_OpenTributeReply=0x0000
OP_GuildTributeStatus=0x0000
OP_GuildSaveActiveTributes=0x5f3f
OP_GuildSendActiveTributes=0x3771
OP_GuildTributeToggleReq=0x7745
OP_GuildTributeToggleReply=0x20ae
OP_GuildTributeFavorAndTimer=0x7fe0
OP_GuildTributeDonateItem=0x5bcb
OP_GuildTributeDonatePlat=0x43d2
OP_GuildSelectTribute=0x649f
OP_GuildModifyBenefits=0x34cd
OP_GuildOptInOut=0x0727
OP_SendGuildTributes=0x1877
OP_OpenGuildTributeMaster=0x49ea
# Adventure packets:
OP_LeaveAdventure=0x5d18

View File

@ -42,6 +42,7 @@ OP_WorldLoginFailed=0x8DA7 # world->client. reject.
OP_WorldLogout=0x7718 # client->world
OP_WorldLevelTooHigh=0x583b # world->client. Cancels zone in.
OP_CharInacessable=0x436A # world->client. Cancels zone in.
OP_RequestGuildTributes=0x5e3a # request packet, 4 bytes
#Zone in opcodes
OP_ZoneEntry=0x7213 # ShowEQ 10/27/05
@ -108,13 +109,20 @@ OP_GuildInvite=0x18b7
OP_GuildPublicNote=0x17a2 # ShowEQ 10/27/05
OP_GuildDelete=0x6cce
OP_GuildInviteAccept=0x61d0
#OP_GuildManageRemove=0x0000
#OP_GuildManageAdd=0x0000
#OP_GuildManageStatus=0x0000
OP_GuildMemberPublicNote=0x17a2
OP_GuildManageBanker=0x3d1e
OP_GuildBank=0xb4ab
OP_SetGuildRank=0x6966
OP_LFGuild=0x1858
OP_GuildMemberLevel=0x461a
OP_GuildMemberRankAltBanker=0x6966
OP_GuildMemberPublicNote=0x32cf
OP_GuildMemberAdd=0x754e
OP_GuildMemberRename=0x7c59
OP_GuildMemberDelete=0x712a
OP_GuildMemberDetails=0x0f4d
OP_GuildRenameGuild=0x4cc7
OP_GuildDeleteGuild=0x3230
#GM/guide opcodes
OP_GMServers=0x3387 #/servers
@ -370,7 +378,6 @@ OP_TrackTarget=0x7085
OP_TrackUnknown=0x6177 #size 0 right after OP_Track
#Tribute Packets:
OP_OpenGuildTributeMaster=0x0000
OP_OpenTributeMaster=0x512e #open tribute master window
OP_OpenTributeReply=0x27B3 #reply to open request
OP_SelectTribute=0x625d #clicking on a tribute, and text reply
@ -383,9 +390,20 @@ OP_TributePointUpdate=0x6463 #16 byte point packet
OP_TributeUpdate=0x5639 # ShowEQ 10/27/05
OP_GuildTributeInfo=0x5e3d # ShowEQ 10/27/05
OP_TributeInfo=0x152d
OP_SendGuildTributes=0x5e3a # request packet, 4 bytes
OP_SendTributes=0x067a # request packet, 4 bytes, migth be backwards
# 27b3 4665
OP_OpenGuildTributeMaster=0x60b6
OP_GuildSaveActiveTributes=0x12fb
OP_GuildSendActiveTributes=0x1a29
OP_GuildTributeToggleReq=0x4b98
OP_GuildTributeToggleReply=0x3312
OP_GuildTributeFavorAndTimer=0x67ea
OP_GuildTributeDonateItem=0x32c0
OP_GuildTributeDonatePlat=0x44c4
OP_GuildSelectTribute=0x704f
OP_GuildModifyBenefits=0x4eef
OP_GuildOptInOut=0x0cfc
OP_SendGuildTributes=0x5e3d
#Adventure packets:
OP_LeaveAdventure=0x0c0d

View File

@ -83,6 +83,7 @@ OP_SpawnAppearance=0x3e17 # V
OP_ChangeSize=0x6942 #
OP_TributeUpdate=0x684c # V
OP_TributeTimer=0x4895 # C
OP_RequestGuildTributes=0x6124 #
OP_TaskDescription=0x156c # C
OP_TaskActivity=0x31f3 # C
OP_CompletedTasks=0x687f # C
@ -104,7 +105,7 @@ OP_ClearBlockedBuffs=0x5570 # C
OP_SendExpZonein=0x47e7 # V
OP_SendTributes=0x6bfb # V
OP_TributeInfo=0x5a67 # V
OP_SendGuildTributes=0x4df0 # C 0x5a01
#OP_SendGuildTributes=0x4df0 # C 0x5a01
OP_AAExpUpdate=0x4aa2 # V
OP_ExpUpdate=0x0555 # V
OP_HPUpdate=0x6145 # V
@ -137,16 +138,22 @@ OP_GuildPublicNote=0x2dbd # C
OP_GuildManageBanker=0x1e4c # C
OP_GuildBank=0x0d8a # C
OP_SetGuildRank=0x4ffe # C
OP_GuildUpdateURLAndChannel=0x5232 # C
OP_GuildUpdate=0x5232 # C
OP_GuildMemberLevelUpdate=0x0000 #
OP_ZoneGuildList=0x0000 #
OP_GetGuildsList=0x0000 #
OP_GuildStatus=0x28c8 #
OP_GuildCreate=0x192d #
OP_LFGuild=0x7e23 #
# OP_GuildManageRemove=0x0000 #
# OP_GuildManageAdd=0x0000 #
# OP_GuildManageStatus=0x0000 #
OP_GuildMemberLevel=0x4d4e
OP_GuildMemberRankAltBanker=0x4ffe
OP_GuildMemberPublicNote=0x526d
OP_GuildMemberAdd=0x7337
OP_GuildMemberRename=0x5fc7
OP_GuildMemberDelete=0x190c
OP_GuildMemberDetails=0x0a53
OP_GuildRenameGuild=0x480e
OP_GuildDeleteGuild=0x736
# GM/guide opcodes
OP_GMServers=0x6989 # C
@ -480,6 +487,18 @@ OP_TributeNPC=0x0000 #
OP_GuildTributeInfo=0x0000 #
OP_OpenTributeReply=0x0000 #
# OP_GuildTributeStatus=0x0000 #
OP_OpenGuildTributeMaster=0x4933
OP_GuildSaveActiveTributes=0x322f
OP_GuildSendActiveTributes=0x5a01 #
OP_GuildTributeToggleReq=0x7880
OP_GuildTributeToggleReply=0x7d66 #
OP_GuildTributeFavorAndTimer=0x4df0
OP_GuildTributeDonateItem=0x3683
OP_GuildTributeDonatePlat=0x5e79
OP_GuildSelectTribute=0x3bef
OP_GuildModifyBenefits=0x3a1b
OP_GuildOptInOut=0x5a6f
OP_SendGuildTributes=0x45b3
# Adventure packets:
OP_LeaveAdventure=0x3ed4 # C

View File

@ -2387,3 +2387,45 @@ void Client::RecordPossibleHack(const std::string& message)
PlayerEventLogsRepository::InsertOne(database, e);
}
}
void Client::SendGuildTributeFavorAndTimer(uint32 favor, uint32 time_remaining)
{
auto cle = GetCLE();
if (!cle) {
return;
}
auto guild = guild_mgr.GetGuildByGuildID(GetCLE()->GuildID());
if (guild) {
guild->tribute.favor = favor;
guild->tribute.time_remaining = time_remaining;
auto outapp = new EQApplicationPacket(OP_GuildTributeFavorAndTimer, sizeof(GuildTributeFavorTimer_Struct));
auto gtsa = (GuildTributeFavorTimer_Struct *)outapp->pBuffer;
gtsa->guild_id = GetCLE()->GuildID();
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)
{
auto outapp = new EQApplicationPacket(OP_GuildOptInOut, sizeof(GuildTributeOptInOutReply_Struct));
auto data = (GuildTributeOptInOutReply_Struct *)outapp->pBuffer;
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;
strn0cpy(data->player_name, in->player_name, sizeof(data->player_name));
QueuePacket(outapp);
safe_delete(outapp);
}

View File

@ -51,6 +51,8 @@ public:
void SendLogServer();
void SendApproveWorld();
void SendPostEnterWorld();
void SendGuildTributeFavorAndTimer(uint32 favor, uint32 time_remaining);
void SendGuildTributeOptInToggle(const GuildTributeMemberToggle* in);
inline uint32 GetIP() { return ip; }
inline uint16 GetPort() { return port; }

View File

@ -223,6 +223,8 @@ void ClientListEntry::Update(ZoneServer *iZS, ServerClientList_Struct *scl, CLE_
panon = scl->anon;
ptellsoff = scl->tellsoff;
pguild_id = scl->guild_id;
pguild_rank = scl->guild_rank;
pguild_tribute_opt_in = scl->guild_tribute_opt_in;
pLFG = scl->LFG;
gm = scl->gm;
pClientVersion = scl->ClientVersion;
@ -280,6 +282,7 @@ void ClientListEntry::ClearVars(bool iAll)
panon = 0;
ptellsoff = 0;
pguild_id = GUILD_NONE;
pguild_rank = 0;
pLFG = 0;
gm = 0;
pClientVersion = 0;

View File

@ -95,29 +95,32 @@ public:
inline void SetAdmin(uint16 iAdmin) { padmin = iAdmin; }
// Character info
inline ZoneServer* Server() const { return pzoneserver; }
inline void ClearServer() { pzoneserver = 0; }
inline uint32 CharID() const { return pcharid; }
inline const char* name() const { return pname; }
inline uint32 zone() const { return pzone; }
inline uint16 instance() const { return pinstance; }
inline uint8 level() const { return plevel; }
inline uint8 class_() const { return pclass_; }
inline uint16 race() const { return prace; }
inline uint8 Anon() { return panon; }
inline uint8 TellsOff() const { return ptellsoff; }
inline uint32 GuildID() const { return pguild_id; }
inline void SetGuild(uint32 guild_id) { pguild_id = guild_id; }
inline bool LFG() const { return pLFG; }
inline uint8 GetGM() const { return gm; }
inline void SetGM(uint8 igm) { gm = igm; }
inline void SetZone(uint32 zone) { pzone = zone; }
inline bool IsLocalClient() const { return plocal; }
inline uint8 GetLFGFromLevel() const { return pLFGFromLevel; }
inline uint8 GetLFGToLevel() const { return pLFGToLevel; }
inline bool GetLFGMatchFilter() const { return pLFGMatchFilter; }
inline const char* GetLFGComments() const { return pLFGComments; }
inline uint8 GetClientVersion() { return pClientVersion; }
inline ZoneServer *Server() const { return pzoneserver; }
inline void ClearServer() { pzoneserver = 0; }
inline uint32 CharID() const { return pcharid; }
inline const char *name() const { return pname; }
inline uint32 zone() const { return pzone; }
inline uint16 instance() const { return pinstance; }
inline uint8 level() const { return plevel; }
inline uint8 class_() const { return pclass_; }
inline uint16 race() const { return prace; }
inline uint8 Anon() { return panon; }
inline uint8 TellsOff() const { return ptellsoff; }
inline uint32 GuildID() const { return pguild_id; }
inline uint32 GuildRank() const { return pguild_rank; }
inline bool GuildTributeOptIn() const { return pguild_tribute_opt_in; }
inline void SetGuild(uint32 guild_id) { pguild_id = guild_id; }
inline void SetGuildTributeOptIn(bool opt) { pguild_tribute_opt_in = opt; }
inline bool LFG() const { return pLFG; }
inline uint8 GetGM() const { return gm; }
inline void SetGM(uint8 igm) { gm = igm; }
inline void SetZone(uint32 zone) { pzone = zone; }
inline bool IsLocalClient() const { return plocal; }
inline uint8 GetLFGFromLevel() const { return pLFGFromLevel; }
inline uint8 GetLFGToLevel() const { return pLFGToLevel; }
inline bool GetLFGMatchFilter() const { return pLFGMatchFilter; }
inline const char *GetLFGComments() const { return pLFGComments; }
inline uint8 GetClientVersion() { return pClientVersion; }
inline bool TellQueueFull() const { return tell_queue.size() >= RuleI(World, TellQueueSize); }
inline bool TellQueueEmpty() const { return tell_queue.empty(); }
@ -160,6 +163,8 @@ private:
uint8 panon{};
uint8 ptellsoff{};
uint32 pguild_id{};
uint32 pguild_rank;
bool pguild_tribute_opt_in{};
bool pLFG{};
uint8 gm{};
uint8 pClientVersion{};

View File

@ -384,6 +384,8 @@ void ClientList::ClientUpdate(ZoneServer *zoneserver, ServerClientList_Struct *s
" anon [{}]"
" tellsoff [{}]"
" guild_id [{}]"
" guild_rank [{}]"
" guild_tribute_opt_in [{}]"
" LFG [{}]"
" gm [{}]"
" ClientVersion [{}]"
@ -409,6 +411,8 @@ void ClientList::ClientUpdate(ZoneServer *zoneserver, ServerClientList_Struct *s
scl->anon,
scl->tellsoff,
scl->guild_id,
scl->guild_rank,
scl->guild_tribute_opt_in,
scl->LFG,
scl->gm,
scl->ClientVersion,
@ -1577,6 +1581,8 @@ void ClientList::GetClientList(Json::Value &response)
row["client_version"] = cle->GetClientVersion();
row["gm"] = cle->GetGM();
row["guild_id"] = cle->GuildID();
row["guild_rank"] = cle->GuildRank();
row["guild_tribute_opt_in"] = cle->GuildTributeOptIn();
row["instance"] = cle->instance();
row["is_local_client"] = cle->IsLocalClient();
row["level"] = cle->level();
@ -1667,3 +1673,97 @@ void ClientList::SendCharacterMessageID(ClientListEntry* character,
character->Server()->SendPacket(pack.get());
}
void ClientList::GetGuildClientList(Json::Value& response, uint32 guild_id)
{
LinkedListIterator<ClientListEntry*> Iterator(clientlist);
Iterator.Reset();
while (Iterator.MoreElements()) {
ClientListEntry* cle = Iterator.GetData();
if (cle->GuildID() != guild_id) {
Iterator.Advance();
continue;
}
Json::Value row;
row["account_id"] = cle->AccountID();
row["account_name"] = cle->AccountName();
row["admin"] = cle->Admin();
row["id"] = cle->GetID();
row["ip"] = cle->GetIP();
row["loginserver_account_id"] = cle->LSAccountID();
row["loginserver_id"] = cle->LSID();
row["loginserver_name"] = cle->LSName();
row["online"] = cle->Online();
row["world_admin"] = cle->WorldAdmin();
auto server = cle->Server();
if (server) {
row["server"]["client_address"] = server->GetCAddress();
row["server"]["client_local_address"] = server->GetCLocalAddress();
row["server"]["client_port"] = server->GetCPort();
row["server"]["compile_time"] = server->GetCompileTime();
row["server"]["id"] = server->GetID();
row["server"]["instance_id"] = server->GetInstanceID();
row["server"]["ip"] = server->GetIP();
row["server"]["is_booting"] = server->IsBootingUp();
row["server"]["launch_name"] = server->GetLaunchName();
row["server"]["launched_name"] = server->GetLaunchedName();
row["server"]["number_players"] = server->NumPlayers();
row["server"]["port"] = server->GetPort();
row["server"]["previous_zone_id"] = server->GetPrevZoneID();
row["server"]["static_zone"] = server->IsStaticZone();
row["server"]["uui"] = server->GetUUID();
row["server"]["zone_id"] = server->GetZoneID();
row["server"]["zone_long_name"] = server->GetZoneLongName();
row["server"]["zone_name"] = server->GetZoneName();
row["server"]["zone_os_pid"] = server->GetZoneOSProcessID();
}
else {
row["server"] = Json::Value();
}
row["anon"] = cle->Anon();
row["character_id"] = cle->CharID();
row["class"] = cle->class_();
row["client_version"] = cle->GetClientVersion();
row["gm"] = cle->GetGM();
row["guild_id"] = cle->GuildID();
row["guild_rank"] = cle->GuildRank();
row["guild_tribute_opt_in"] = cle->GuildTributeOptIn();
row["instance"] = cle->instance();
row["is_local_client"] = cle->IsLocalClient();
row["level"] = cle->level();
row["lfg"] = cle->LFG();
row["lfg_comments"] = cle->GetLFGComments();
row["lfg_from_level"] = cle->GetLFGFromLevel();
row["lfg_match_filter"] = cle->GetLFGMatchFilter();
row["lfg_to_level"] = cle->GetLFGToLevel();
row["name"] = cle->name();
row["race"] = cle->race();
row["tells_off"] = cle->TellsOff();
row["zone"] = cle->zone();
response.append(row);
Iterator.Advance();
}
}
std::map<uint32, ClientListEntry *> ClientList::GetGuildClientsWithTributeOptIn(uint32 guild_id)
{
std::map<uint32, ClientListEntry *> guild_members;
LinkedListIterator<ClientListEntry *> Iterator(clientlist);
Iterator.Reset();
while (Iterator.MoreElements()) {
auto c = Iterator.GetData();
if (c->GuildID() == guild_id && c->GuildTributeOptIn()) {
guild_members.emplace(c->CharID(), c);
}
Iterator.Advance();
}
return guild_members;
}

View File

@ -33,7 +33,9 @@ public:
void ZoneBootup(ZoneServer* zs);
void RemoveCLEReferances(ClientListEntry* cle);
std::map<uint32, ClientListEntry*> GetGuildClientsWithTributeOptIn(uint32 guild_id);
std::map<uint32, ClientListEntry*> GetGuildClientList(uint32 guild_id);
//Client* GetClient(uint32 char_id);
//from ZSList
@ -65,6 +67,7 @@ public:
void GetClients(const char *zone_name, std::vector<ClientListEntry *> &into);
void GetClientList(Json::Value &response);
void GetGuildClientList(Json::Value& response, uint32 guild_id);
void SendCharacterMessage(uint32_t character_id, int chat_type, const std::string& message);
void SendCharacterMessage(const std::string& character_name, int chat_type, const std::string& message);

View File

@ -27,10 +27,12 @@
#include "../common/database_schema.h"
#include "../common/zone_store.h"
#include "worlddb.h"
#include "wguild_mgr.h"
#include "world_config.h"
extern ZSList zoneserver_list;
extern ClientList client_list;
extern ZSList zoneserver_list;
extern ClientList client_list;
extern WorldGuildManager guild_mgr;
void callGetZoneList(Json::Value &response)
{
@ -277,7 +279,63 @@ void EQEmuApiWorldDataService::get(Json::Value &r, const std::vector<std::string
if (m == "reload") {
reload(r, args);
}
if (m == "get_guild_details") {
callGetGuildDetails(r, args);
}
if (m == "lock_status") {
r["locked"] = WorldConfig::get()->Locked;
}
}
void EQEmuApiWorldDataService::callGetGuildDetails(Json::Value &response, const std::vector<std::string> &args)
{
std::string command = !args[1].empty() ? args[1] : "";
if (command.empty()) {
return;
}
Json::Value row;
auto guild_id = Strings::ToUnsignedInt(command);
if (!guild_id) {
row = "useage is: api get_guild_details ### where ### is a valid guild id.";
return;
}
auto guild = guild_mgr.GetGuildByGuildID(guild_id);
if (!guild) {
row = fmt::format("Could not find guild id {}", guild_id);
return;
}
row["guild_id"] = command;
row["guild_name"] = guild->name;
row["leader_id"] = guild->leader;
row["min_status"] = guild->minstatus;
row["motd"] = guild->motd;
row["motd_setter"] = guild->motd_setter;
row["url"] = guild->url;
row["channel"] = guild->channel;
for (int i = GUILD_LEADER; i <= GUILD_RECRUIT; i++) {
row["Ranks"][i] = guild->rank_names[i].c_str();
}
for (int i = 1; i <= GUILD_MAX_FUNCTIONS; i++) {
row["functions"][i]["db_id"] = guild->functions[i].id;
row["functions"][i]["perm_id"] = guild->functions[i].perm_id;
row["functions"][i]["guild_id"] = guild->functions[i].guild_id;
row["functions"][i]["perm_value"] = guild->functions[i].perm_value;
}
row["tribute"]["favor"] = guild->tribute.favor;
row["tribute"]["id1"] = guild->tribute.id_1;
row["tribute"]["id1_tier"] = guild->tribute.id_1_tier;
row["tribute"]["id2"] = guild->tribute.id_2;
row["tribute"]["id2_tier"] = guild->tribute.id_2_tier;
row["tribute"]["time_remaining"] = guild->tribute.time_remaining;
row["tribute"]["enabled"] = guild->tribute.enabled;
client_list.GetGuildClientList(response, guild_id);
response.append(row);
}

View File

@ -28,6 +28,7 @@ public:
static void get(Json::Value &r, const std::vector<std::string> &args);
static void reload(Json::Value &r, const std::vector<std::string> &args);
static void message(Json::Value &r, const std::string &message);
static void callGetGuildDetails(Json::Value &response, const std::vector<std::string> &args);
};

View File

@ -45,6 +45,7 @@
#include "../common/misc.h"
#include "client.h"
#include "worlddb.h"
#include "wguild_mgr.h"
#ifdef _WINDOWS
#include <process.h>
@ -409,6 +410,7 @@ int main(int argc, char **argv)
event_scheduler.Process(&zoneserver_list);
client_list.Process();
guild_mgr.Process();
if (player_event_process_timer.Check()) {
player_event_logs.Process();

View File

@ -22,17 +22,25 @@
#include "../common/servertalk.h"
#include "clientlist.h"
#include "zonelist.h"
#include "zoneserver.h"
#include "cliententry.h"
#include "client.h"
#include "../common/repositories/guilds_repository.h"
#include "../common/repositories/guild_ranks_repository.h"
#include "../common/repositories/guild_permissions_repository.h"
#include "../common/repositories/guild_members_repository.h"
#include "../common/repositories/guild_bank_repository.h"
#include "../common/repositories/guild_tributes_repository.h"
#include "../common/repositories/tributes_repository.h"
#include "../common/repositories/tribute_levels_repository.h"
extern ClientList client_list;
extern ZSList zoneserver_list;
std::map<uint32, TributeData> tribute_list;
WorldGuildManager guild_mgr;
void WorldGuildManager::SendGuildRefresh(uint32 guild_id, bool name, bool motd, bool rank, bool relation) {
LogGuilds("Broadcasting guild refresh for [{}], changes: name=[{}], motd=[{}], rank=d, relation=[{}]", guild_id, name, motd, rank, relation);
auto pack = new ServerPacket(ServerOP_RefreshGuild, sizeof(ServerGuildRefresh_Struct));
@ -89,14 +97,12 @@ void WorldGuildManager::ProcessZonePacket(ServerPacket *pack) {
break;
}
case ServerOP_GuildCharRefresh: {
if(pack->size != sizeof(ServerGuildCharRefresh_Struct)) {
LogGuilds("Received ServerOP_RefreshGuild of incorrect size [{}], expected [{}]", pack->size, sizeof(ServerGuildCharRefresh_Struct));
return;
}
case ServerOP_GuildCharRefresh:
{
ServerGuildCharRefresh_Struct *s = (ServerGuildCharRefresh_Struct *) pack->pBuffer;
LogGuilds("Received and broadcasting guild member refresh for char [{}] to all zones with members of guild [{}]", s->char_id, s->guild_id);
RefreshGuild(s->guild_id);
//preform the local update
client_list.UpdateClientGuild(s->char_id, s->guild_id);
@ -107,41 +113,325 @@ void WorldGuildManager::ProcessZonePacket(ServerPacket *pack) {
break;
}
case ServerOP_DeleteGuild: {
case ServerOP_DeleteGuild:
{
if(pack->size != sizeof(ServerGuildID_Struct)) {
LogGuilds("Received ServerOP_DeleteGuild of incorrect size [{}], expected [{}]", pack->size, sizeof(ServerGuildID_Struct));
return;
}
ServerGuildID_Struct *s = (ServerGuildID_Struct *) pack->pBuffer;
auto res = m_guilds.find(s->guild_id);
if (res != m_guilds.end()) {
delete res->second;
m_guilds.erase(res);
}
LogGuilds("Received and broadcasting guild delete for guild [{}]", s->guild_id);
//broadcast this packet to all zones.
zoneserver_list.SendPacket(pack);
//preform a local refresh.
if(!LocalDeleteGuild(s->guild_id)) {
LogGuilds("Unable to preform local delete on guild [{}]", s->guild_id);
//can we do anything?
}
break;
}
case ServerOP_GuildMemberUpdate: {
case ServerOP_GuildMemberUpdate:
{
if(pack->size != sizeof(ServerGuildMemberUpdate_Struct))
{
LogGuilds("Received ServerOP_GuildMemberUpdate of incorrect size [{}], expected [{}]", pack->size, sizeof(ServerGuildMemberUpdate_Struct));
return;
}
auto s = (ServerGuildID_Struct *)pack->pBuffer;
RefreshGuild(s->guild_id);
zoneserver_list.SendPacket(pack);
break;
}
case ServerOP_GuildPermissionUpdate:
{
if (pack->size != sizeof(ServerGuildPermissionUpdate_Struct))
{
LogGuilds("Received ServerOP_GuildPermissionUpdate of incorrect size [{}], expected [{}]", pack->size, sizeof(ServerGuildPermissionUpdate_Struct));
return;
}
auto sg = (ServerGuildPermissionUpdate_Struct *)pack->pBuffer;
auto guild = GetGuildByGuildID(sg->guild_id);
if (!guild) {
guild_mgr.LoadGuilds();
guild = GetGuildByGuildID(sg->guild_id);
}
if (guild) {
if (sg->function_value) {
guild->functions[sg->function_id].perm_value |= (1UL << (8 - sg->rank));
}
else {
guild->functions[sg->function_id].perm_value &= ~(1UL << (8 - sg->rank));
}
LogGuilds("World Received ServerOP_GuildPermissionUpdate for guild [{}] function id {} with value of {}",
sg->guild_id,
sg->function_id,
sg->function_value
);
zoneserver_list.SendPacketToBootedZones(pack);
}
else {
LogError("World Received ServerOP_GuildPermissionUpdate for guild [{}] function id {} with value of {} but guild could not be found.",
sg->guild_id,
sg->function_id,
sg->function_value
);
}
break;
}
case ServerOP_GuildRankNameChange:
{
if (pack->size != sizeof(ServerGuildRankNameChange))
{
LogGuilds("Received ServerOP_ServerGuildRankNameChange of incorrect size [{}], expected [{}]", pack->size, sizeof(ServerGuildPermissionUpdate_Struct));
return;
}
auto rnc = (ServerGuildRankNameChange*)pack->pBuffer;
auto guild = GetGuildByGuildID(rnc->guild_id);
if (!guild) {
guild_mgr.LoadGuilds();
guild = GetGuildByGuildID(rnc->guild_id);
}
if (guild) {
guild->rank_names[rnc->rank] = rnc->rank_name;
LogGuilds("World Received ServerOP_GuildRankNameChange from zone for guild [{}] rank id {} with new name of {}",
rnc->guild_id,
rnc->rank,
rnc->rank_name
);
zoneserver_list.SendPacketToBootedZones(pack);
}
else {
LogError("World Received ServerOP_GuildRankNameChange from zone for guild [{}] rank id {} with new name of {} but could not find guild.",
rnc->guild_id,
rnc->rank,
rnc->rank_name
);
}
break;
}
case ServerOP_GuildMemberLevelUpdate:
case ServerOP_GuildMemberPublicNote:
case ServerOP_GuildChannel:
case ServerOP_GuildURL:
case ServerOP_GuildMemberRemove:
case ServerOP_GuildMemberAdd:
case ServerOP_GuildSendGuildList:
case ServerOP_GuildMembersList:
{
zoneserver_list.SendPacketToBootedZones(pack);
break;
}
default:
LogGuilds("Unknown packet {:#04x} received from zone??", pack->opcode);
break;
}
}
void WorldGuildManager::Process()
{
for (auto &g: m_guilds) {
if (!g.second->tribute.enabled) {
continue;
}
else if (g.second->tribute.enabled && !g.second->tribute.timer.Enabled()) {
g.second->tribute.timer.Start(g.second->tribute.time_remaining);
LogGuilds(
"Found a Guild Tribute Timer for guild [{}]. that was not started. Started it with [{}] time remaining before restart.",
g.first,
g.second->tribute.time_remaining
);
}
else if (g.second->tribute.enabled && g.second->tribute.timer.Check()) {
g.second->tribute.favor -= GetGuildTributeCost(g.first);
g.second->tribute.time_remaining = RuleI(Guild, TributeTime);
g.second->tribute.timer.Start(RuleI(Guild, TributeTime));
guild_mgr.UpdateDbGuildFavor(g.first, g.second->tribute.favor);
guild_mgr.UpdateDbTributeTimeRemaining(g.first, RuleI(Guild, TributeTime));
SendGuildTributeFavorAndTimer(g.first, g.second->tribute.favor, g.second->tribute.timer.GetRemainingTime());
}
else if (g.second->tribute.send_timer &&
((g.second->tribute.timer.GetRemainingTime() / 1000) %
(RuleI(Guild, TributeTimeRefreshInterval) / 1000)) == 0 &&
!g.second->tribute.timer.Check()
) {
g.second->tribute.send_timer = false;
g.second->tribute.time_remaining = g.second->tribute.timer.GetRemainingTime();
SendGuildTributeFavorAndTimer(g.first, g.second->tribute.favor, g.second->tribute.time_remaining);
guild_mgr.UpdateDbTributeTimeRemaining(g.first, g.second->tribute.time_remaining);
LogGuilds(
"Timer Frequency [{}] ms hit sending time [{}] to guild clients",
RuleI(Guild, TributeTimeRefreshInterval),
g.second->tribute.time_remaining
);
}
else if (!g.second->tribute.send_timer &&
((g.second->tribute.timer.GetRemainingTime() / 1000) %
(RuleI(Guild, TributeTimeRefreshInterval) / 1000)) > 0 &&
!g.second->tribute.timer.Check()
) {
g.second->tribute.send_timer = true;
}
}
}
uint32 WorldGuildManager::GetGuildTributeCost(uint32 guild_id)
{
auto guild_members = client_list.GetGuildClientsWithTributeOptIn(guild_id);
auto total = guild_members.size();
auto total_cost = 0;
auto guild = guild_mgr.GetGuildByGuildID(guild_id);
if (guild)
{
TributeData &d1 = tribute_list[guild->tribute.id_1];
TributeData &d2 = tribute_list[guild->tribute.id_2];
uint32 cost_id1 = d1.tiers[guild->tribute.id_1_tier].cost;
uint32 cost_id2 = d2.tiers[guild->tribute.id_2_tier].cost;
uint32 level_id1 = d2.tiers[guild->tribute.id_1_tier].level;
uint32 level_id2 = d2.tiers[guild->tribute.id_2_tier].level;
for (auto const &m: guild_members) {
if (m.second->level() >= level_id1) {
total_cost += cost_id1;
}
if (m.second->level() >= level_id2) {
total_cost += cost_id2;
}
}
}
return total_cost;
}
bool WorldGuildManager::LoadTributes()
{
TributeData td{};
td.tier_count = 0;
tribute_list.clear();
auto tributes = TributesRepository::All(*m_db);
for (auto const& t : tributes) {
td.name = t.name;
td.description = t.descr;
td.unknown = t.unknown;
td.is_guild = t.isguild == 0 ? false : true;
tribute_list[t.id] = td;
}
LogInfo("Loaded [{}] tributes", Strings::Commify(tributes.size()));
auto tribute_levels = TributeLevelsRepository::GetWhere(*m_db, "TRUE ORDER BY tribute_id, level");
for (auto const& t : tribute_levels) {
uint32 id = t.tribute_id;
if (tribute_list.count(id) != 1) {
LogError("Error in LoadTributes: unknown tribute [{}] in tribute_levels", (unsigned long)id);
continue;
}
TributeData& cur = tribute_list[id];
if (cur.tier_count >= MAX_TRIBUTE_TIERS) {
LogError("Error in LoadTributes: on tribute [{}] more tiers defined than permitted", (unsigned long)id);
continue;
}
TributeLevel_Struct& s = cur.tiers[cur.tier_count];
s.level = t.level;
s.cost = t.cost;
s.tribute_item_id = t.item_id;
cur.tier_count++;
}
LogInfo("Loaded [{}] tribute levels", Strings::Commify(tribute_levels.size()));
return true;
}
bool WorldGuildManager::RefreshGuild(uint32 guild_id)
{
auto temp_guild = GetGuildByGuildID(guild_id);
BaseGuildManager::GuildInfo temp_guild_detail;
if (temp_guild) {
temp_guild_detail.tribute = temp_guild->tribute;
}
if (guild_id <= 0) {
LogError("Requested to refresh guild id [{}] but id must be greater than 0.", guild_id);
return false;
}
auto db_guild = GuildsRepository::FindOne(*m_db, guild_id);
if (!db_guild.id) {
LogGuilds("Guild ID [{}] not found in database.", db_guild.id);
return false;
}
LogGuilds("Found guild id [{}]. Loading details.....", db_guild.id);
_CreateGuild(db_guild.id, db_guild.name, db_guild.leader, db_guild.minstatus, db_guild.motd, db_guild.motd_setter, db_guild.channel, db_guild.url, db_guild.favor);
auto guild = GetGuildByGuildID(guild_id);
auto where_filter = fmt::format("guild_id = '{}'", guild_id);
auto guild_ranks = GuildRanksRepository::GetWhere(*m_db, where_filter);
for (auto const& r : guild_ranks) {
guild->rank_names[r.rank_] = r.title;
}
where_filter = fmt::format("guild_id = '{}'", guild_id);
auto guild_permissions = GuildPermissionsRepository::GetWhere(*m_db, where_filter);
for (auto const& p : guild_permissions) {
guild->functions[p.perm_id].id = p.id;
guild->functions[p.perm_id].guild_id = p.guild_id;
guild->functions[p.perm_id].perm_id = p.perm_id;
guild->functions[p.perm_id].perm_value = p.permission;
}
auto guild_tributes = GuildTributesRepository::FindOne(*m_db, guild_id);
if (guild_tributes.guild_id) {
guild->tribute.id_1 = guild_tributes.tribute_id_1;
guild->tribute.id_2 = guild_tributes.tribute_id_2;
guild->tribute.id_1_tier = guild_tributes.tribute_id_1_tier;
guild->tribute.id_2_tier = guild_tributes.tribute_id_2_tier;
guild->tribute.enabled = guild_tributes.enabled;
guild->tribute.time_remaining = guild_tributes.time_remaining;
}
if (temp_guild_detail.tribute.enabled == 1) {
guild->tribute = temp_guild_detail.tribute;
}
LogGuilds("Successfully refreshed guild id [{}] from the [WORLD] database", guild_id);
LogGuilds("Timer has [{}] time remaining from the [WORLD] refresh.", guild->tribute.time_remaining);
return true;
}
void WorldGuildManager::SendGuildTributeFavorAndTimer(uint32 guild_id, uint32 favor, uint32 time)
{
auto sp = new ServerPacket(ServerOP_GuildTributeFavAndTimer, sizeof(GuildTributeFavorTimer_Struct));
auto data = (GuildTributeFavorTimer_Struct *)sp->pBuffer;
data->guild_id = guild_id;
data->guild_favor = favor;
data->tribute_timer = time;
data->trophy_timer = 0;
zoneserver_list.SendPacketToBootedZones(sp);
safe_delete(sp)
}

View File

@ -1,5 +1,5 @@
#ifndef GUILD_MGR_H_
#define GUILD_MGR_H_
#ifndef WGUILD_MGR_H_
#define WGUILD_MGR_H_
#include "../common/types.h"
#include "../common/guild_base.h"
@ -12,6 +12,12 @@ public:
//called by zoneserver when it receives a guild message from zone.
void ProcessZonePacket(ServerPacket *pack);
void Process();
bool LoadTributes();
void SendGuildTributeFavorAndTimer(uint32 guild_id);
void SendGuildTributeFavorAndTimer(uint32 guild_id, uint32 favor, uint32 time);
uint32 GetGuildTributeCost(uint32 guild_id);
virtual bool RefreshGuild(uint32 guild_id);
protected:
virtual void SendGuildRefresh(uint32 guild_id, bool name, bool motd, bool rank, bool relation);
@ -19,11 +25,12 @@ protected:
virtual void SendRankUpdate(uint32 CharID) { return; }
virtual void SendGuildDelete(uint32 guild_id);
//map<uint32, uint32> m_tribute; //map from guild ID to current tribute ammount
};
extern WorldGuildManager guild_mgr;
#endif /*GUILD_MGR_H_*/
#endif /*WGUILD_MGR_H_*/

View File

@ -297,6 +297,7 @@ bool WorldBoot::DatabaseLoadRoutines(int argc, char **argv)
}
guild_mgr.LoadGuilds();
guild_mgr.LoadTributes();
//rules:
{

View File

@ -857,3 +857,15 @@ const std::list<std::unique_ptr<ZoneServer>> &ZSList::getZoneServerList() const
{
return zone_server_list;
}
bool ZSList::SendPacketToBootedZones(ServerPacket* pack)
{
for (auto const& z : zone_server_list) {
auto r = z.get();
if (r && r->GetZoneID() > 0) {
r->SendPacket(pack);
}
}
return true;
}

View File

@ -28,6 +28,7 @@ public:
bool SendPacket(ServerPacket *pack);
bool SendPacket(uint32 zoneid, ServerPacket *pack);
bool SendPacket(uint32 zoneid, uint16 instanceid, ServerPacket *pack);
bool SendPacketToBootedZones(ServerPacket* pack);
bool SetLockedZone(uint16 iZoneID, bool iLock);
EQTime worldclock;

View File

@ -1,3 +1,4 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2005 EQEMu Development Team (http://eqemulator.net)
@ -47,6 +48,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "../common/events/player_event_logs.h"
#include "../common/patches/patches.h"
#include "../zone/data_bucket.h"
#include "../common/repositories/guild_tributes_repository.h"
extern ClientList client_list;
extern GroupLFPList LFPGroupList;
@ -978,7 +980,18 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
case ServerOP_DeleteGuild:
case ServerOP_GuildCharRefresh:
case ServerOP_GuildMemberUpdate:
case ServerOP_RefreshGuild: {
case ServerOP_GuildPermissionUpdate:
case ServerOP_GuildRankNameChange:
case ServerOP_RefreshGuild:
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.ProcessZonePacket(pack);
break;
}
@ -1552,6 +1565,169 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
break;
}
case ServerOP_GuildTributeUpdate: {
auto data = (GuildTributeUpdate *)pack->pBuffer;
auto guild = guild_mgr.GetGuildByGuildID(data->guild_id);
if (guild) {
guild->tribute.enabled = 0;
guild->tribute.id_1 = data->tribute_id_1;
guild->tribute.id_2 = data->tribute_id_2;
guild->tribute.id_1_tier = data->tribute_id_1_tier;
guild->tribute.id_2_tier = data->tribute_id_2_tier;
guild->tribute.time_remaining = RuleI(Guild, TributeTime);
guild->tribute.timer.Disable();
zoneserver_list.SendPacketToBootedZones(pack);
}
break;
}
case ServerOP_GuildTributeActivate: {
auto data = (GuildTributeUpdate *)pack->pBuffer;
auto guild = guild_mgr.GetGuildByGuildID(data->guild_id);
if (guild) {
guild->tribute.enabled = data->enabled;
if (guild->tribute.enabled) {
data->enabled = 1;
if (guild->tribute.time_remaining == RuleI(Guild, TributeTime)) {
data->favor = (guild->tribute.favor -= guild_mgr.GetGuildTributeCost(data->guild_id));
}
data->time_remaining = guild->tribute.time_remaining;
data->tribute_id_1 = guild->tribute.id_1;
data->tribute_id_2 = guild->tribute.id_2;
data->tribute_id_1_tier = guild->tribute.id_1_tier;
data->tribute_id_2_tier = guild->tribute.id_2_tier;
guild->tribute.timer.Start(guild->tribute.time_remaining);
LogInfo("Guild Tribute Timer Started.");
}
else {
if (guild->tribute.timer.Enabled()) {
guild->tribute.time_remaining = guild->tribute.timer.GetRemainingTime();
}
data->enabled = 0;
data->favor = guild->tribute.favor;
data->time_remaining = guild->tribute.time_remaining;
data->tribute_id_1 = guild->tribute.id_1;
data->tribute_id_2 = guild->tribute.id_2;
data->tribute_id_1_tier = guild->tribute.id_1_tier;
data->tribute_id_2_tier = guild->tribute.id_2_tier;
LogInfo("Guild Tribute Timer Stopped with {} ms remaining.", data->time_remaining);
guild->tribute.timer.Disable();
}
guild_mgr.UpdateDbGuildTributeEnabled(data->guild_id, data->enabled);
guild_mgr.UpdateDbGuildFavor(data->guild_id, data->favor);
guild_mgr.UpdateDbTributeTimeRemaining(data->guild_id, data->time_remaining);
zoneserver_list.SendPacketToBootedZones(pack);
}
break;
}
case ServerOP_GuildTributeOptInToggle:
{
auto in = (GuildTributeMemberToggle *)pack->pBuffer;
auto guild = guild_mgr.GetGuildByGuildID(in->guild_id);
auto c = client_list.FindCharacter(in->player_name);
if (c) {
c->SetGuildTributeOptIn(in->tribute_toggle ? true : false);
}
auto cle = client_list.FindCLEByCharacterID(in->char_id);
if (cle) {
cle->SetGuildTributeOptIn(in->tribute_toggle ? true : false);
}
if (guild) {
CharGuildInfo gci;
guild_mgr.GetCharInfo(in->char_id, gci);
auto out = new ServerPacket(ServerOP_GuildTributeOptInToggle, sizeof(GuildTributeMemberToggle));
auto data = (GuildTributeMemberToggle *)out->pBuffer;
data->char_id = in->char_id;
data->command = in->command;
data->tribute_toggle = in->tribute_toggle;
data->no_donations = gci.total_tribute;
data->member_last_donated = gci.last_tribute;
data->guild_id = in->guild_id;
data->time_remaining = in->time_remaining;
strn0cpy(data->player_name, in->player_name, sizeof(data->player_name));
zoneserver_list.SendPacketToBootedZones(out);
safe_delete(out);
}
break;
}
case ServerOP_RequestGuildActiveTributes:
{
auto in = (GuildTributeUpdate *)pack->pBuffer;
auto guild = guild_mgr.GetGuildByGuildID(in->guild_id);
if (guild) {
auto sp = new ServerPacket(ServerOP_RequestGuildActiveTributes, sizeof(GuildTributeUpdate));
auto out = (GuildTributeUpdate *)sp->pBuffer;
out->guild_id = in->guild_id;
out->enabled = guild->tribute.enabled;
out->favor = guild->tribute.favor;
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;
out->time_remaining = guild_mgr.GetGuildTributeTimeRemaining(in->guild_id);
zoneserver_list.SendPacketToBootedZones(sp);
safe_delete(sp);
}
break;
}
case ServerOP_RequestGuildFavorAndTimer:
{
auto in = (GuildTributeUpdate *)pack->pBuffer;
auto guild = guild_mgr.GetGuildByGuildID(in->guild_id);
if (guild) {
auto sp = new ServerPacket(ServerOP_RequestGuildFavorAndTimer, sizeof(GuildTributeFavorTimer_Struct));
auto out = (GuildTributeFavorTimer_Struct *) sp->pBuffer;
out->guild_id = in->guild_id;
out->guild_favor = guild->tribute.favor;
out->tribute_timer = guild_mgr.GetGuildTributeTimeRemaining(in->guild_id);
out->trophy_timer = 0;
zoneserver_list.SendPacketToBootedZones(sp);
safe_delete(sp);
}
break;
}
case ServerOP_GuildTributeUpdateDonations:
{
auto in = (GuildTributeUpdate*)pack->pBuffer;
auto guild = guild_mgr.GetGuildByGuildID(in->guild_id);
if (guild) {
guild->tribute.favor = in->favor;
guild_mgr.SendGuildTributeFavorAndTimer(in->guild_id, guild->tribute.favor, guild_mgr.GetGuildTributeTimeRemaining(in->guild_id)/*guild->tribute.timer.GetRemainingTime()*/);
auto sp = new ServerPacket(ServerOP_GuildTributeUpdateDonations, sizeof(GuildTributeUpdate));
auto out = (GuildTributeUpdate *) sp->pBuffer;
out->guild_id = in->guild_id;
out->member_favor = in->member_favor;
out->member_enabled = in->member_enabled ? true : false;
out->member_time = in->member_time;
strn0cpy(out->player_name, in->player_name, sizeof(out->player_name));
zoneserver_list.SendPacketToBootedZones(sp);
safe_delete(sp)
}
break;
}
default: {
LogInfo("Unknown ServerOPcode from zone {:#04x}, size [{}]", pack->opcode, pack->size);
DumpPacket(pack->pBuffer, pack->size);

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

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 },

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;

File diff suppressed because it is too large Load Diff

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);

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()) {

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;
}
}

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);

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());

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");

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);
}

File diff suppressed because it is too large Load Diff

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);

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)

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)),

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);

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();

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
};

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;

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.

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

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;

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()));

0
zone/zonedb.cpp Executable file → Normal file
View File