mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-17 03:08:26 +00:00
[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:
+239
-233
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user