From 3a46bf7383a6353e72485999f8ac3ed07528dead Mon Sep 17 00:00:00 2001 From: Vayle <76063792+Valorith@users.noreply.github.com> Date: Sun, 6 Aug 2023 15:32:25 -0400 Subject: [PATCH] [Rules] Add rule to toggle pets accepting quest items (#3533) * Add rule to disable handing quests items to pets * Logic tweak * Tweaks Updated formatting and minor logic change * Minor tweaks --- common/item_data.cpp | 4 ++++ common/item_data.h | 1 + common/ruletypes.h | 1 + zone/trading.cpp | 32 +++++++++++++++++++++++--------- 4 files changed, 29 insertions(+), 9 deletions(-) diff --git a/common/item_data.cpp b/common/item_data.cpp index 12e2f80a7..6dcb1f577 100644 --- a/common/item_data.cpp +++ b/common/item_data.cpp @@ -230,6 +230,10 @@ bool EQ::ItemData::IsTypeShield() const return (ItemType == item::ItemTypeShield); } +bool EQ::ItemData::IsQuestItem() const { + return QuestItemFlag; +} + bool EQ::ItemData::CheckLoreConflict(const ItemData* l_item, const ItemData* r_item) { if (!l_item || !r_item) diff --git a/common/item_data.h b/common/item_data.h index ff78ea11a..40add4239 100644 --- a/common/item_data.h +++ b/common/item_data.h @@ -546,6 +546,7 @@ namespace EQ bool IsType1HWeapon() const; bool IsType2HWeapon() const; bool IsTypeShield() const; + bool IsQuestItem() const; static bool CheckLoreConflict(const ItemData* l_item, const ItemData* r_item); bool CheckLoreConflict(const ItemData* item) const { return CheckLoreConflict(this, item); } diff --git a/common/ruletypes.h b/common/ruletypes.h index f1e66349a..bb6264359 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -256,6 +256,7 @@ RULE_REAL(Pets, AttackCommandRange, 150, "Range at which a pet will respond to a RULE_BOOL(Pets, UnTargetableSwarmPet, false, "Setting whether swarm pets should be targetable") RULE_REAL(Pets, PetPowerLevelCap, 10, "Maximum number of levels a player pet can go up with pet power") RULE_BOOL(Pets, CanTakeNoDrop, false, "Setting whether anyone can give no-drop items to pets") +RULE_BOOL(Pets, CanTakeQuestItems, true, "Setting whether anyone can give quest items to pets") RULE_BOOL(Pets, LivelikeBreakCharmOnInvis, true, "Default: true will break charm on any type of invis (hide/ivu/iva/etc) false will only break if the pet can not see you (ex. you have an undead pet and cast IVU") RULE_BOOL(Pets, ClientPetsUseOwnerNameInLastName, true, "Disable this to keep client pet's last names from being owner_name's pet") RULE_CATEGORY_END() diff --git a/zone/trading.cpp b/zone/trading.cpp index 19873c0bd..b0caf6b55 100644 --- a/zone/trading.cpp +++ b/zone/trading.cpp @@ -71,9 +71,10 @@ void Trade::Start(uint32 mob_id, bool initiate_with) // Autostart on other mob? if (initiate_with) { - Mob* with = With(); - if (with) + Mob *with = With(); + if (with) { with->trade->Start(owner->GetID(), false); + } } } @@ -774,20 +775,22 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st } const EQ::ItemData* item = inst->GetItem(); - - bool isPetAndCanHaveNoDrop = (RuleB(Pets, CanTakeNoDrop) && - _CLIENTPET(tradingWith) && - tradingWith->GetPetType()<=petOther); + const bool is_pet = _CLIENTPET(tradingWith) && tradingWith->GetPetType()<=petOther; + const bool pets_can_take_quest_items = RuleB(Pets, CanTakeQuestItems); + const bool is_pet_and_can_have_nodrop_items = (RuleB(Pets, CanTakeNoDrop) && is_pet); + const bool is_pet_and_can_have_quest_items = (pets_can_take_quest_items && is_pet); // if it was not a NO DROP or Attuned item (or if a GM is trading), let the NPC have it - if(GetGM() || (inst->IsAttuned() == false && - (item->NoDrop != 0 || isPetAndCanHaveNoDrop))) { + if (GetGM() || + (((item->NoDrop != 0 && !inst->IsAttuned()) || is_pet_and_can_have_nodrop_items) && + ((!item->IsQuestItem() || is_pet_and_can_have_quest_items || !is_pet)))) { // pets need to look inside bags and try to equip items found there if (item->IsClassBag() && item->BagSlots > 0) { for (int16 bslot = EQ::invbag::SLOT_BEGIN; bslot < item->BagSlots; bslot++) { const EQ::ItemInstance* baginst = inst->GetItem(bslot); if (baginst) { const EQ::ItemData* bagitem = baginst->GetItem(); - if (bagitem && (GetGM() || (bagitem->NoDrop != 0 && baginst->IsAttuned() == false))) { + if (bagitem && (GetGM() || ((bagitem->NoDrop != 0 && !baginst->IsAttuned()) || is_pet_and_can_have_nodrop_items) && + ((!bagitem->IsQuestItem()|| is_pet_and_can_have_quest_items || !is_pet)))) { auto loot_drop_entry = NPC::NewLootDropEntry(); loot_drop_entry.equip_item = 1; @@ -800,6 +803,11 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st true ); } + else if (is_pet && bagitem->IsQuestItem()) { + tradingWith->SayString(TRADE_BACK, GetCleanName()); + PushItemOnCursor(*baginst, true); + Message(Chat::Red, "You cannot trade quest items with your pet."); + } else if (RuleB(NPC, ReturnNonQuestNoDropItems)) { tradingWith->SayString(TRADE_BACK, GetCleanName()); PushItemOnCursor(*baginst, true); @@ -819,6 +827,12 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st true ); } + // Return quest items being traded to player pet when not allowed + else if (is_pet && item->IsQuestItem()) { + tradingWith->SayString(TRADE_BACK, GetCleanName()); + PushItemOnCursor(*inst, true); + Message(Chat::Red, "You cannot trade quest items with your pet."); + } // Return NO DROP and Attuned items being handed into a non-quest NPC if the rule is true else if (RuleB(NPC, ReturnNonQuestNoDropItems)) { tradingWith->SayString(TRADE_BACK, GetCleanName());