[Feature] GuildBank Updates (#4674)

* First pass of a re-write of Guild Bank to enable RoF2 features

* Testing - Corrected a few bugs with merging, splitting and withdrawing

* Testing - Corrected a few bugs with depositing of bags

* Added player event logging for deposit, withdrawal and movement between deposit to main area.

* Fix the guilddelete routine

Fix the guilddelete routine as a result of the new guild_bank table structure

* Fix an issue with items not being withdrawn correctly.

* Final Testing Phase 1 - A few failures to be resolved yet.

* Final Testing Phase 2 - Looks good

* Final Testing Phase 3 - Repair a visual bug with withdrawal of items with charges

* Cleanup

* Formatting feedback updates

* Rebase and fix version.h

* Fix manifest issue after changes
This commit is contained in:
Mitch Freeman
2025-02-15 19:48:50 -04:00
committed by GitHub
parent 8201175c2c
commit c09fad5a75
20 changed files with 1419 additions and 1227 deletions
+239 -233
View File
@@ -7585,292 +7585,298 @@ void Client::Handle_OP_GroupUpdate(const EQApplicationPacket *app)
void Client::Handle_OP_GuildBank(const EQApplicationPacket *app)
{
if (!GuildBanks)
if (!GuildBanks) {
GuildBankAck();
return;
}
if (zone->GetZoneID() != Zones::GUILDHALL)
{
if (zone->GetZoneID() != Zones::GUILDHALL) {
Message(Chat::Red, "The Guild Bank is not available in this zone.");
GuildBankAck();
return;
}
if (app->size < sizeof(uint32)) {
LogError("Wrong size: OP_GuildBank, size=[{}], expected [{}]", app->size, sizeof(uint32));
DumpPacket(app);
GuildBankAck();
return;
}
char *Buffer = (char *)app->pBuffer;
uint32 Action = VARSTRUCT_DECODE_TYPE(uint32, Buffer);
char *Buffer = (char *) app->pBuffer;
uint32 Action = VARSTRUCT_DECODE_TYPE(uint32, Buffer);
uint32 sentAction = Action;
if (!IsInAGuild())
{
if (!IsInAGuild()) {
Message(Chat::Red, "You must be in a Guild to use the Guild Bank.");
if (Action == GuildBankDeposit)
if (Action == GuildBankDeposit) {
GuildBankDepositAck(true, sentAction);
else
}
else {
GuildBankAck();
}
return;
}
if (!IsGuildBanker())
{
if ((Action != GuildBankDeposit) && (Action != GuildBankViewItem) && (Action != GuildBankWithdraw))
if (Action != GuildBankDeposit && Action != GuildBankViewItem && Action != GuildBankWithdraw)
{
LogError("Suspected hacking attempt on guild bank from [{}]", GetName());
GuildBankAck();
return;
}
}
switch (Action)
{
case GuildBankPromote:
{
if (GuildBanks->IsAreaFull(GuildID(), GuildBankMainArea))
{
MessageString(Chat::Red, GUILD_BANK_FULL);
GuildBankDepositAck(true, sentAction);
return;
}
GuildBankPromote_Struct *gbps = (GuildBankPromote_Struct*)app->pBuffer;
int Slot = GuildBanks->Promote(GuildID(), gbps->Slot);
if (Slot >= 0)
{
EQ::ItemInstance* inst = GuildBanks->GetItem(GuildID(), GuildBankMainArea, Slot, 1);
if (inst)
{
MessageString(Chat::LightGray, GUILD_BANK_TRANSFERRED, inst->GetItem()->Name);
safe_delete(inst);
}
}
else
Message(Chat::Red, "Unexpected error while moving item into Guild Bank.");
GuildBankAck();
break;
}
case GuildBankViewItem:
{
GuildBankViewItem_Struct *gbvis = (GuildBankViewItem_Struct*)app->pBuffer;
EQ::ItemInstance* inst = GuildBanks->GetItem(GuildID(), gbvis->Area, gbvis->SlotID, 1);
if (!inst)
break;
SendItemPacket(0, inst, ItemPacketViewLink);
safe_delete(inst);
break;
}
case GuildBankDeposit: // Deposit Item
{
EQ::ItemInstance *CursorItemInst = GetInv().GetItem(EQ::invslot::slotCursor);
bool Allowed = true;
if (!CursorItemInst)
{
Message(Chat::Red, "No Item on the cursor.");
GuildBankDepositAck(true, sentAction);
return;
}
const EQ::ItemData* CursorItem = CursorItemInst->GetItem();
if (GuildBanks->IsAreaFull(GuildID(), GuildBankDepositArea))
{
MessageString(Chat::Red, GUILD_BANK_FULL);
GuildBankDepositAck(true, sentAction);
if (ClientVersion() >= EQ::versions::ClientVersion::RoF) {
GetInv().PopItem(EQ::invslot::slotCursor);
PushItemOnCursor(CursorItem, true);
switch (Action) {
case GuildBankPromote: {
if (GuildBanks->IsAreaFull(GuildID(), GuildBankMainArea)) {
MessageString(Chat::Red, GUILD_BANK_FULL);
GuildBankAck();
return;
}
return;
}
auto gbps = (GuildBankPromote_Struct *) app->pBuffer;
int slot_id = GuildBanks->Promote(GuildID(), gbps->Slot, this);
if (!CursorItem->NoDrop || CursorItemInst->IsAttuned())
{
Allowed = false;
}
else if (CursorItemInst->IsNoneEmptyContainer())
{
Allowed = false;
}
else if (CursorItemInst->IsAugmented())
{
Allowed = false;
}
else if (CursorItem->NoRent == 0)
{
Allowed = false;
}
else if (CursorItem->LoreFlag && GuildBanks->HasItem(GuildID(), CursorItem->ID))
{
Allowed = false;
}
if (slot_id >= 0) {
auto inst = GuildBanks->GetItem(GuildID(), GuildBankMainArea, slot_id, 1);
if (inst) {
if (player_event_logs.IsEventEnabled(PlayerEvent::GUILD_BANK_MOVE_TO_BANK_AREA)) {
PlayerEvent::GuildBankTransaction log{};
log.char_id = CharacterID();
log.guild_id = GuildID();
log.item_id = inst->GetID();
log.quantity = inst->GetCharges();
if (inst->IsAugmented()) {
auto augs = inst->GetAugmentIDs();
log.aug_slot_one = augs.at(0);
log.aug_slot_two = augs.at(1);
log.aug_slot_three = augs.at(2);
log.aug_slot_four = augs.at(3);
log.aug_slot_five = augs.at(4);
log.aug_slot_six = augs.at(5);
}
if (!Allowed)
{
MessageString(Chat::Red, GUILD_BANK_CANNOT_DEPOSIT);
GuildBankDepositAck(true, sentAction);
RecordPlayerEventLog(PlayerEvent::GUILD_BANK_MOVE_TO_BANK_AREA, log);
}
if (ClientVersion() >= EQ::versions::ClientVersion::RoF) {
GetInv().PopItem(EQ::invslot::slotCursor);
PushItemOnCursor(CursorItem, true);
MessageString(Chat::LightGray, GUILD_BANK_TRANSFERRED, inst->GetItem()->Name);
}
}
else {
Message(Chat::Red, "Unexpected error while moving item into Guild Bank.");
}
return;
}
if (GuildBanks->AddItem(GuildID(), GuildBankDepositArea, CursorItem->ID, CursorItemInst->GetCharges(), GetName(), GuildBankBankerOnly, ""))
{
GuildBankDepositAck(false, sentAction);
DeleteItemInInventory(EQ::invslot::slotCursor, 0, false);
}
break;
}
case GuildBankPermissions:
{
GuildBankPermissions_Struct *gbps = (GuildBankPermissions_Struct*)app->pBuffer;
if (gbps->Permissions == 1)
GuildBanks->SetPermissions(GuildID(), gbps->SlotID, gbps->Permissions, gbps->MemberName);
else
GuildBanks->SetPermissions(GuildID(), gbps->SlotID, gbps->Permissions, "");
GuildBankAck();
break;
}
case GuildBankWithdraw:
{
if (GetInv()[EQ::invslot::slotCursor])
{
MessageString(Chat::Red, GUILD_BANK_EMPTY_HANDS);
GuildBankAck();
break;
}
case GuildBankViewItem: {
auto gbvis = (GuildBankViewItem_Struct *) app->pBuffer;
auto inst = GuildBanks->GetItem(GuildID(), gbvis->Area, gbvis->SlotID, 1);
if (!inst) {
break;
}
SendItemPacket(0, inst.get(), ItemPacketViewLink);
break;
}
case GuildBankDeposit: // Deposit Item
{
const auto cursor_item_inst = GetInv().GetItem(EQ::invslot::slotCursor);
bool allowed = true;
if (!cursor_item_inst) {
Message(Chat::Red, "No Item on the cursor.");
GuildBankDepositAck(true, sentAction);
return;
}
const auto cursor_item = cursor_item_inst->GetItem();
if (GuildBanks->IsAreaFull(GuildID(), GuildBankDepositArea)) {
MessageString(Chat::Red, GUILD_BANK_FULL);
GuildBankDepositAck(true, sentAction);
if (ClientVersion() >= EQ::versions::ClientVersion::RoF) {
GetInv().PopItem(EQ::invslot::slotCursor);
PushItemOnCursor(*cursor_item_inst, true);
}
return;
}
if (!cursor_item->NoDrop ||
cursor_item_inst->IsAttuned() ||
cursor_item_inst->IsNoneEmptyContainer() ||
cursor_item->NoRent == 0 ||
(cursor_item->LoreFlag && GuildBanks->HasItem(GuildID(), cursor_item->ID))
) {
allowed = false;
}
if (!allowed) {
MessageString(Chat::Red, GUILD_BANK_CANNOT_DEPOSIT);
GuildBankDepositAck(true, sentAction);
if (ClientVersion() >= EQ::versions::ClientVersion::RoF) {
GetInv().PopItem(EQ::invslot::slotCursor);
PushItemOnCursor(*cursor_item_inst, true);
}
return;
}
auto item = GuildBankRepository::NewEntity();
item.guild_id = GuildID();
item.area = GuildBankDepositArea;
item.item_id = cursor_item->ID;
item.quantity = cursor_item_inst->GetCharges();
item.donator = GetCleanName();
item.permissions = GuildBankBankerOnly;
if (cursor_item_inst->IsAugmented()) {
auto const augs = cursor_item_inst->GetAugmentIDs();
item.augment_one_id = augs.at(0);
item.augment_two_id = augs.at(1);
item.augment_three_id = augs.at(2);
item.augment_four_id = augs.at(3);
item.augment_five_id = augs.at(4);
item.augment_six_id = augs.at(5);
}
if (GuildBanks->AddItem(item, this)) {
GuildBankDepositAck(false, sentAction);
DeleteItemInInventory(EQ::invslot::slotCursor, 0, false);
if (player_event_logs.IsEventEnabled(PlayerEvent::GUILD_BANK_DEPOSIT)) {
PlayerEvent::GuildBankTransaction log{};
log.char_id = CharacterID();
log.guild_id = GuildID();
log.item_id = item.item_id;
log.quantity = item.quantity;
log.aug_slot_one = item.augment_one_id;
log.aug_slot_two = item.augment_two_id;
log.aug_slot_three = item.augment_three_id;
log.aug_slot_four = item.augment_four_id;
log.aug_slot_five = item.augment_five_id;
log.aug_slot_six = item.augment_six_id;
RecordPlayerEventLog(PlayerEvent::GUILD_BANK_DEPOSIT, log);
}
}
break;
}
GuildBankWithdrawItem_Struct *gbwis = (GuildBankWithdrawItem_Struct*)app->pBuffer;
case GuildBankPermissions: {
auto gbps = (GuildBankPermissions_Struct *) app->pBuffer;
EQ::ItemInstance* inst = GuildBanks->GetItem(GuildID(), gbwis->Area, gbwis->SlotID, gbwis->Quantity);
if (gbps->Permissions == 1) {
GuildBanks->SetPermissions(GuildID(), gbps->SlotID, gbps->Permissions, gbps->MemberName, this);
}
else {
GuildBanks->SetPermissions(GuildID(), gbps->SlotID, gbps->Permissions, "", this);
}
if (!inst)
{
GuildBankAck();
break;
}
if (!guild_mgr.CheckPermission(GuildID(), GuildRank(), GUILD_ACTION_BANK_WITHDRAW_ITEMS))
{
Message(Chat::Red, "You do not have permission to withdraw.");
case GuildBankWithdraw: {
if (GetInv()[EQ::invslot::slotCursor]) {
MessageString(Chat::Red, GUILD_BANK_EMPTY_HANDS);
GuildBankAck();
break;
}
auto gbwis = (GuildBankWithdrawItem_Struct *) app->pBuffer;
auto inst = GuildBanks->GetItem(GuildID(), gbwis->Area, gbwis->SlotID, gbwis->Quantity);
if (!inst) {
GuildBankAck();
break;
}
if (!guild_mgr.CheckPermission(GuildID(), GuildRank(), GUILD_ACTION_BANK_WITHDRAW_ITEMS)) {
Message(Chat::Red, "You do not have permission to withdraw.");
GuildBankAck();
break;
}
if (!IsGuildBanker()) {
LogError("Suspected attempted hack on the guild bank from [{}]", GetName());
GuildBankAck();
break;
}
if (CheckLoreConflict(inst->GetItem())) {
MessageString(Chat::Red, DUP_LORE);
GuildBankAck();
break;
}
if (inst->GetCharges() > 0) {
gbwis->Quantity = inst->GetCharges();
}
if (inst->GetCharges() < 0) {
gbwis->Quantity = 1;
}
PushItemOnCursor(*inst.get());
SendItemPacket(EQ::invslot::slotCursor, inst.get(), ItemPacketLimbo);
GuildBanks->DeleteItem(GuildID(), gbwis->Area, gbwis->SlotID, gbwis->Quantity, this);
if (player_event_logs.IsEventEnabled(PlayerEvent::GUILD_BANK_WITHDRAWAL)) {
PlayerEvent::GuildBankTransaction log{};
log.char_id = CharacterID();
log.guild_id = GuildID();
log.item_id = inst->GetID();
log.quantity = gbwis->Quantity;
if (inst->IsAugmented()) {
auto augs = inst->GetAugmentIDs();
log.aug_slot_one = augs.at(0);
log.aug_slot_two = augs.at(1);
log.aug_slot_three = augs.at(2);
log.aug_slot_four = augs.at(3);
log.aug_slot_five = augs.at(4);
log.aug_slot_six = augs.at(5);
}
RecordPlayerEventLog(PlayerEvent::GUILD_BANK_WITHDRAWAL, log);
}
else {
Message(Chat::Red, "Unable to withdraw 0 quantity of %s", inst->GetItem()->Name);
}
GuildBankAck();
break;
}
case GuildBankSplitStacks: {
if (GuildBanks->IsAreaFull(GuildID(), GuildBankMainArea)) {
MessageString(Chat::Red, GUILD_BANK_FULL);
}
else {
auto gbwis = (GuildBankWithdrawItem_Struct *) app->pBuffer;
GuildBanks->SplitStack(GuildID(), gbwis->SlotID, gbwis->Quantity, this);
}
GuildBankAck();
break;
}
case GuildBankMergeStacks: {
auto gbwis = (GuildBankWithdrawItem_Struct *) app->pBuffer;
GuildBanks->MergeStacks(GuildID(), gbwis->SlotID, this);
GuildBankAck();
safe_delete(inst);
break;
}
if (!IsGuildBanker() && !GuildBanks->AllowedToWithdraw(GuildID(), gbwis->Area, gbwis->SlotID, GetName()))
{
LogError("Suspected attempted hack on the guild bank from [{}]", GetName());
GuildBankAck();
safe_delete(inst);
break;
default: {
Message(Chat::Red, "Unexpected GuildBank action.");
LogError("Received unexpected guild bank action code [{}] from [{}]", Action, GetName());
}
if (CheckLoreConflict(inst->GetItem()))
{
MessageString(Chat::Red, DUP_LORE);
GuildBankAck();
safe_delete(inst);
break;
}
if (gbwis->Quantity > 0)
{
PushItemOnCursor(*inst);
SendItemPacket(EQ::invslot::slotCursor, inst, ItemPacketLimbo);
GuildBanks->DeleteItem(GuildID(), gbwis->Area, gbwis->SlotID, gbwis->Quantity);
}
else
{
Message(Chat::Red, "Unable to withdraw 0 quantity of %s", inst->GetItem()->Name);
}
safe_delete(inst);
GuildBankAck();
break;
}
case GuildBankSplitStacks:
{
if (GuildBanks->IsAreaFull(GuildID(), GuildBankMainArea))
MessageString(Chat::Red, GUILD_BANK_FULL);
else
{
GuildBankWithdrawItem_Struct *gbwis = (GuildBankWithdrawItem_Struct*)app->pBuffer;
GuildBanks->SplitStack(GuildID(), gbwis->SlotID, gbwis->Quantity);
}
GuildBankAck();
break;
}
case GuildBankMergeStacks:
{
GuildBankWithdrawItem_Struct *gbwis = (GuildBankWithdrawItem_Struct*)app->pBuffer;
GuildBanks->MergeStacks(GuildID(), gbwis->SlotID);
GuildBankAck();
break;
}
default:
{
Message(Chat::Red, "Unexpected GuildBank action.");
LogError("Received unexpected guild bank action code [{}] from [{}]", Action, GetName());
}
}
}
+7 -19
View File
@@ -2332,30 +2332,18 @@ void EntityList::QueueClientsGuild(const EQApplicationPacket *app, uint32 guild_
}
}
void EntityList::QueueClientsGuildBankItemUpdate(const GuildBankItemUpdate_Struct *gbius, uint32 GuildID)
void EntityList::QueueClientsGuildBankItemUpdate(GuildBankItemUpdate_Struct *gbius, uint32 guild_id)
{
auto outapp = new EQApplicationPacket(OP_GuildBank, sizeof(GuildBankItemUpdate_Struct));
auto outapp = std::make_unique<EQApplicationPacket>(OP_GuildBank, sizeof(GuildBankItemUpdate_Struct));
auto data = reinterpret_cast<GuildBankItemUpdate_Struct *>(outapp->pBuffer);
GuildBankItemUpdate_Struct *outgbius = (GuildBankItemUpdate_Struct*)outapp->pBuffer;
memcpy(data, gbius, sizeof(GuildBankItemUpdate_Struct));
memcpy(outgbius, gbius, sizeof(GuildBankItemUpdate_Struct));
const EQ::ItemData *Item = database.GetItem(gbius->ItemID);
auto it = client_list.begin();
while (it != client_list.end()) {
Client *client = it->second;
if (client->IsInGuild(GuildID)) {
if (Item && (gbius->Permissions == GuildBankPublicIfUsable))
outgbius->Useable = Item->IsEquipable(client->GetBaseRace(), client->GetBaseClass());
client->QueuePacket(outapp);
for (auto const &[key, client]: client_list) {
if (client->IsInGuild(guild_id)) {
client->QueuePacket(outapp.get());
}
++it;
}
safe_delete(outapp);
}
void EntityList::MessageStatus(uint32 to_guild_id, int to_minstatus, uint32 type, const char *message, ...)
+1 -1
View File
@@ -429,7 +429,7 @@ public:
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(const EQApplicationPacket* app, uint32 guildeqid = 0);
void QueueClientsGuildBankItemUpdate(const GuildBankItemUpdate_Struct *gbius, uint32 GuildID);
void QueueClientsGuildBankItemUpdate(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);
void QueueClientsByXTarget(Mob* sender, const EQApplicationPacket* app, bool iSendToSender = true, EQ::versions::ClientVersionBitmask client_version_bits = EQ::versions::ClientVersionBitmask::maskAllClients);
+67 -29
View File
@@ -603,35 +603,73 @@ void command_guild(Client* c, const Seperator* sep)
auto guild_id = Strings::ToUnsignedInt(sep->arg[2]);
auto guild = guild_mgr.GetGuildByGuildID(guild_id);
PlayerEvent::LootItemEvent e{};
e.charges = -1;
e.corpse_name = "Test Corpse Name";
e.item_id = 123456789;
e.item_name = "Test Item Name";
e.npc_id = 987654321;
e.augment_1_id = 11;
e.augment_2_id = 0;
e.augment_3_id = 0;
e.augment_4_id = 44;
e.augment_5_id = 55;
e.augment_6_id = 66;
RecordPlayerEventLogWithClient(c, PlayerEvent::LOOT_ITEM, e);
PlayerEvent::DestroyItemEvent e2{};
e2.charges = -1;
e2.attuned = true;
e.augment_1_id = 11;
e.augment_2_id = 0;
e.augment_3_id = 0;
e.augment_4_id = 44;
e.augment_5_id = 55;
e.augment_6_id = 66;
e2.item_id = 123456789;
e2.item_name = "Test Item Destroy Name";
e2.reason = "Test Item Destroy Reason";
RecordPlayerEventLogWithClient(c, PlayerEvent::ITEM_DESTROY, e2);
// PlayerEvent::LootItemEvent e{};
// e.charges = -1;
// e.corpse_name = "Test Corpse Name";
// e.item_id = 123456789;
// e.item_name = "Test Item Name";
// e.npc_id = 987654321;
// e.augment_1_id = 11;
// e.augment_2_id = 0;
// e.augment_3_id = 0;
// e.augment_4_id = 44;
// e.augment_5_id = 55;
// e.augment_6_id = 66;
//
// RecordPlayerEventLogWithClient(c, PlayerEvent::LOOT_ITEM, e);
//
// PlayerEvent::DestroyItemEvent e2{};
// e2.charges = -1;
// e2.attuned = true;
// e.augment_1_id = 11;
// e.augment_2_id = 0;
// e.augment_3_id = 0;
// e.augment_4_id = 44;
// e.augment_5_id = 55;
// e.augment_6_id = 66;
// e2.item_id = 123456789;
// e2.item_name = "Test Item Destroy Name";
// e2.reason = "Test Item Destroy Reason";
//
// RecordPlayerEventLogWithClient(c, PlayerEvent::ITEM_DESTROY, e2);
// auto id = Strings::ToUnsignedInt(sep->arg[3]);
// //auto guild = guild_mgr.GetGuildByGuildID(guild_id);
// // c->SendGuildMembersList();
// auto bank = GuildBanks->GetGuildBank(guild_id);
// if (id == 1) {
// for (auto &[key, item]: bank->items.main_area) {
// auto i = ItemsRepository::FindOne(content_db, item.item_id);
// c->Message(Chat::Yellow, fmt::format("key:{:02} item:{:05} Name:{:40} Qty:{:40} Slot:{}",
// key, item.item_id, i.Name, item.quantity, item.slot).c_str());
// }
// return;
// }
// if (id == 2) {
// for (auto &[key, item]: bank->items.deposit_area) {
// auto i = ItemsRepository::FindOne(content_db, item.item_id);
// c->Message(Chat::Yellow, fmt::format("key:{:02} item:{:05} Name:{} Qty:{:40} Slot:{}",
// key, item.item_id, i.Name, item.quantity, item.slot).c_str());
// }
// return;
// }
// if (id == 3) {
// for (auto &[key, item]: bank->items.main_area) {
// if (item.item_id == 30416) {
// auto i = ItemsRepository::FindOne(content_db, item.item_id);
// c->Message(Chat::Yellow, fmt::format("key:{:02} item:{:05} Name:{:40} Qty:{:40} Slot:{}",
// key, item.item_id, i.Name, item.quantity, item.slot).c_str());
// }
// }
// return;
// }
// if (id == 4) {
// c->Message(Chat::Yellow, "Guild Test 4");
// auto inst = database.CreateItem(30416, 30);
// database.UpdateInventorySlot(c->CharacterID(), inst, -1);
// safe_delete(inst);
//
// return;
// }
}
}
}
+585 -654
View File
File diff suppressed because it is too large Load Diff
+52 -38
View File
@@ -1,10 +1,12 @@
#ifndef GUILD_MGR_H_
#define GUILD_MGR_H_
#include "../common/types.h"
#include "../common/guild_base.h"
#include <map>
#include <list>
#include <map>
#include "../common/guild_base.h"
#include "../common/types.h"
#include "../common/repositories/guild_bank_repository.h"
#include "../zone/petitions.h"
extern PetitionList petition_list;
@@ -14,38 +16,50 @@ extern PetitionList petition_list;
#define PBUFFER 50
#define MBUFFER 50
#define GUILD_BANK_MAIN_AREA_SIZE 200
#define GUILD_BANK_DEPOSIT_AREA_SIZE 20
class Client;
class ServerPacket;
struct GuildBankItem
{
uint32 ItemID;
uint32 Quantity;
char Donator[64];
uint8 Permissions;
char WhoFor[64];
};
struct GuildBankItems
{
GuildBankItem MainArea[GUILD_BANK_MAIN_AREA_SIZE];
GuildBankItem DepositArea[GUILD_BANK_DEPOSIT_AREA_SIZE];
std::map<int32, GuildBankRepository::GuildBank> main_area{};
std::map<int32, GuildBankRepository::GuildBank> deposit_area{};
};
struct GuildBank
{
uint32 GuildID;
GuildBankItems Items;
uint32 guild_id;
GuildBankItems items{};
GuildBank()
{
guild_id = 0;
}
};
enum { GuildBankBulkItems = 0, GuildBankItemUpdate = 1, GuildBankPromote = 3, GuildBankViewItem = 4, GuildBankDeposit = 5,
GuildBankPermissions = 6, GuildBankWithdraw = 7, GuildBankSplitStacks = 8, GuildBankMergeStacks = 9, GuildBankAcknowledge = 10 };
enum {
GuildBankBulkItems = 0,
GuildBankItemUpdate = 1,
GuildBankPromote = 3,
GuildBankViewItem = 4,
GuildBankDeposit = 5,
GuildBankPermissions = 6,
GuildBankWithdraw = 7,
GuildBankSplitStacks = 8,
GuildBankMergeStacks = 9,
GuildBankAcknowledge = 10
};
enum { GuildBankDepositArea = 0, GuildBankMainArea = 1 };
enum {
GuildBankDepositArea = 0,
GuildBankMainArea = 1
};
enum { GuildBankBankerOnly = 0, GuildBankSingleMember = 1, GuildBankPublicIfUsable = 2, GuildBankPublic = 3 };
enum {
GuildBankBankerOnly = 0,
GuildBankSingleMember = 1,
GuildBankPublicIfUsable = 2,
GuildBankPublic = 3
};
class ZoneGuildManager : public BaseGuildManager {
public:
@@ -82,7 +96,7 @@ public:
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);
GuildInfo* GetGuildByGuildID(uint32 guild_id);
virtual void SendGuildRefresh(uint32 guild_id, bool name, bool motd, bool rank, bool relation);
protected:
@@ -103,30 +117,30 @@ class GuildBankManager
public:
~GuildBankManager();
void SendGuildBank(Client *c);
bool AddItem(uint32 GuildID, uint8 Area, uint32 ItemID, int32 QtyOrCharges, const char *Donator, uint8 Permissions, const char *WhoFor);
int Promote(uint32 GuildID, int SlotID);
void SetPermissions(uint32 GuildID, uint16 SlotID, uint32 Permissions, const char *MemberName);
EQ::ItemInstance* GetItem(uint32 GuildID, uint16 Area, uint16 SlotID, uint32 Quantity);
bool DeleteItem(uint32 GuildID, uint16 Area, uint16 SlotID, uint32 Quantity);
bool HasItem(uint32 GuildID, uint32 ItemID);
bool IsAreaFull(uint32 GuildID, uint16 Area);
bool MergeStacks(uint32 GuildID, uint16 SlotID);
bool SplitStack(uint32 GuildID, uint16 SlotID, uint32 Quantity);
bool AllowedToWithdraw(uint32 GuildID, uint16 Area, uint16 SlotID, const char *Name);
bool AddItem(GuildBankRepository::GuildBank &guild_bank_item, Client* client);
int Promote(uint32 GuildID, int SlotID, Client* c);
void SetPermissions(uint32 GuildID, uint16 SlotID, uint32 Permissions, const char *MemberName, Client* c);
std::unique_ptr<EQ::ItemInstance> GetItem(uint32 guild_id, uint16 area, uint16 slot_id, uint32 quantity);
bool DeleteItem(uint32 GuildID, uint16 Area, uint16 SlotID, uint32 Quantity, Client* c);
bool HasItem(uint32 guild_id, uint32 item_id);
bool IsAreaFull(uint32 guild_id, uint16 area);
int32 NextFreeBankSlot(uint32 guild_id, uint32 area);
bool MergeStacks(uint32 GuildID, uint16 SlotID, Client* c);
bool SplitStack(uint32 GuildID, uint16 SlotID, uint32 Quantity, Client* c);
//bool AllowedToWithdraw(uint32 GuildID, uint16 Area, uint16 SlotID, const char *Name);
void SendGuildBankItemUpdate(uint32 guild_id, int32 slot_id, uint32 area, bool display, Client* c);
std::shared_ptr<GuildBank> GetGuildBank(uint32 guild_id);
private:
bool IsLoaded(uint32 GuildID);
bool Load(uint32 GuildID);
std::list<GuildBank*>::iterator GetGuildBank(uint32 GuildID);
void Load(uint32 GuildID);
void UpdateItemQuantity(uint32 GuildID, uint16 Area, uint16 SlotID, uint32 Quantity);
std::list<GuildBank*> Banks;
std::list<std::shared_ptr<GuildBank>> banks{};
};
extern ZoneGuildManager guild_mgr;
extern GuildBankManager *GuildBanks;
#endif /*GUILD_MGR_H_*/