diff --git a/zone/command.cpp b/zone/command.cpp index 858e6c5b8..5742da04f 100755 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -266,7 +266,7 @@ int command_init(void) command_add("npctype_cache", "[id] or all - Clears the npc type cache for either the id or all npcs.", AccountStatus::GMImpossible, command_npctype_cache) || command_add("npctypespawn", "[npctypeid] [factionid] - Spawn an NPC from the db", AccountStatus::Steward, command_npctypespawn) || command_add("nudge", "- Nudge your target's current position by specific values", AccountStatus::QuestTroupe, command_nudge) || - command_add("nukebuffs", "- Strip all buffs on you or your target", AccountStatus::Guide, command_nukebuffs) || + command_add("nukebuffs", "[Beneficial|Detrimental|Help] - Strip all buffs by type on you or your target (no argument to remove all buffs)", AccountStatus::Guide, command_nukebuffs) || command_add("nukeitem", "[Item ID] - Removes the specified Item ID from you or your player target's inventory", AccountStatus::GMLeadAdmin, command_nukeitem) || command_add("object", "List|Add|Edit|Move|Rotate|Copy|Save|Undo|Delete - Manipulate static and tradeskill objects within the zone", AccountStatus::GMAdmin, command_object) || command_add("oocmute", "[1/0] - Mutes OOC chat", AccountStatus::GMMgmt, command_oocmute) || diff --git a/zone/gm_commands/nukebuffs.cpp b/zone/gm_commands/nukebuffs.cpp index 8d1267b3c..bb6542ea0 100755 --- a/zone/gm_commands/nukebuffs.cpp +++ b/zone/gm_commands/nukebuffs.cpp @@ -1,12 +1,47 @@ #include "../client.h" void command_nukebuffs(Client *c, const Seperator *sep) -{ - if (c->GetTarget() == 0) { - c->BuffFadeAll(); +{ + Mob* target = c; + if (c->GetTarget()) { + target = c->GetTarget(); } - else { - c->GetTarget()->BuffFadeAll(); + + std::string buff_identifier = str_tolower(sep->arg[1]); + std::string buff_type; + bool is_beneficial = buff_identifier.find("beneficial") != std::string::npos; + bool is_detrimental = buff_identifier.find("detrimental") != std::string::npos; + bool is_help = buff_identifier.find("help") != std::string::npos; + if (is_beneficial) { + target->BuffFadeBeneficial(); + buff_type = " beneficial"; + } else if (is_detrimental) { + target->BuffFadeDetrimental(); + buff_type = " detrimental"; + } else if (is_help) { + c->Message(Chat::White, "Usage: #nukebuffs"); + c->Message(Chat::White, "Usage: #nukebuffs beneficial"); + c->Message(Chat::White, "Usage: #nukebuffs detrimental"); + return; + } else { + target->BuffFadeAll(); } + + c->Message( + Chat::White, + fmt::format( + "Faded all{} buffs for {}.", + buff_type, + ( + c == target ? + "yourself" : + fmt::format( + "{} ({})", + target->GetCleanName(), + target->GetID() + ) + ) + ).c_str() + ); } diff --git a/zone/mob.h b/zone/mob.h index 1500f41af..a59cbe400 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -361,8 +361,9 @@ public: virtual void DoBuffTic(const Buffs_Struct &buff, int slot, Mob* caster = nullptr); void BuffFadeBySpellID(uint16 spell_id); void BuffFadeBySpellIDAndCaster(uint16 spell_id, uint16 caster_id); - void BuffFadeByEffect(int effect_id, int skipslot = -1); + void BuffFadeByEffect(int effect_id, int slot_to_skip = -1); void BuffFadeAll(); + void BuffFadeBeneficial(); void BuffFadeNonPersistDeath(); void BuffFadeDetrimental(); void BuffFadeBySlot(int slot, bool iRecalcBonuses = true); @@ -393,7 +394,7 @@ public: void DoGravityEffect(); void DamageShield(Mob* other, bool spell_ds = false); int32 RuneAbsorb(int32 damage, uint16 type); - bool FindBuff(uint16 spellid); + bool FindBuff(uint16 spell_id); uint16 FindBuffBySlot(int slot); uint32 BuffCount(); bool FindType(uint16 type, bool bOffensive = false, uint16 threshold = 100); @@ -421,7 +422,7 @@ public: inline float GetTargetRingZ() const { return m_TargetRing.z; } inline bool HasEndurUpkeep() const { return endur_upkeep; } inline void SetEndurUpkeep(bool val) { endur_upkeep = val; } - bool HasBuffWithSpellGroup(int spellgroup); + bool HasBuffWithSpellGroup(int spell_group); //Basic Stats/Inventory virtual void SetLevel(uint8 in_level, bool command = false) { level = in_level; } diff --git a/zone/spells.cpp b/zone/spells.cpp index e01df8a33..344d69781 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -4255,21 +4255,27 @@ void Corpse::CastRezz(uint16 spellid, Mob* Caster) safe_delete(outapp); } -bool Mob::FindBuff(uint16 spellid) +bool Mob::FindBuff(uint16 spell_id) { - int i; - uint32 buff_count = GetMaxTotalSlots(); - for(i = 0; i < buff_count; i++) - if(buffs[i].spellid == spellid) + for (int buff_slot = 0; buff_slot < buff_count; buff_slot++) { + auto current_spell_id = buffs[buff_slot].spellid; + if ( + IsValidSpell(current_spell_id) && + current_spell_id == spell_id + ) { return true; + } + } return false; } uint16 Mob::FindBuffBySlot(int slot) { - if (buffs[slot].spellid != SPELL_UNKNOWN) - return buffs[slot].spellid; + auto current_spell_id = buffs[slot].spellid; + if (IsValidSpell(current_spell_id)) { + return current_spell_id; + } return 0; } @@ -4277,167 +4283,221 @@ uint16 Mob::FindBuffBySlot(int slot) { uint32 Mob::BuffCount() { uint32 active_buff_count = 0; int buff_count = GetMaxTotalSlots(); - for (int i = 0; i < buff_count; i++) - if (buffs[i].spellid != SPELL_UNKNOWN) + for (int buff_slot = 0; buff_slot < buff_count; buff_slot++) { + if (IsValidSpell(buffs[buff_slot].spellid)) { active_buff_count++; + } + } return active_buff_count; } -bool Mob::HasBuffWithSpellGroup(int spellgroup) +bool Mob::HasBuffWithSpellGroup(int spell_group) { - for (int i = 0; i < GetMaxTotalSlots(); i++) { - if (IsValidSpell(buffs[i].spellid) && spells[buffs[i].spellid].spell_group == spellgroup) { + for (int buff_slot = 0; buff_slot < GetMaxTotalSlots(); buff_slot++) { + auto current_spell_id = buffs[buff_slot].spellid; + if ( + IsValidSpell(current_spell_id) && + spells[current_spell_id].spell_group == spell_group + ) { return true; } } + return false; } -// removes all buffs void Mob::BuffFadeAll() { + bool recalc_bonus = false; int buff_count = GetMaxTotalSlots(); - for (int j = 0; j < buff_count; j++) { - if(buffs[j].spellid != SPELL_UNKNOWN) - BuffFadeBySlot(j, false); - } - //we tell BuffFadeBySlot not to recalc, so we can do it only once when were done - CalcBonuses(); -} - -void Mob::BuffFadeNonPersistDeath() -{ - int buff_count = GetMaxTotalSlots(); - for (int j = 0; j < buff_count; j++) { - if (buffs[j].spellid != SPELL_UNKNOWN && !IsPersistDeathSpell(buffs[j].spellid)) - BuffFadeBySlot(j, false); - } - //we tell BuffFadeBySlot not to recalc, so we can do it only once when were done - CalcBonuses(); -} - -void Mob::BuffFadeDetrimental() { - int buff_count = GetMaxTotalSlots(); - for (int j = 0; j < buff_count; j++) { - if(buffs[j].spellid != SPELL_UNKNOWN) { - if(IsDetrimentalSpell(buffs[j].spellid)) - BuffFadeBySlot(j, false); - } - } - //we tell BuffFadeBySlot not to recalc, so we can do it only once when were done - CalcBonuses(); -} - -void Mob::BuffFadeDetrimentalByCaster(Mob *caster) -{ - if(!caster) - return; - - int buff_count = GetMaxTotalSlots(); - for (int j = 0; j < buff_count; j++) { - if(buffs[j].spellid != SPELL_UNKNOWN) { - if(IsDetrimentalSpell(buffs[j].spellid)) - { - //this is a pretty terrible way to do this but - //there really isn't another way till I rewrite the basics - Mob * c = entity_list.GetMob(buffs[j].casterid); - if(c && c == caster) - BuffFadeBySlot(j, false); - } - } - } - //we tell BuffFadeBySlot not to recalc, so we can do it only once when were done - CalcBonuses(); -} - -void Mob::BuffFadeBySitModifier() -{ - bool r_bonus = false; - uint32 buff_count = GetMaxTotalSlots(); - for(uint32 j = 0; j < buff_count; ++j) - { - if(buffs[j].spellid != SPELL_UNKNOWN) - { - if(spells[buffs[j].spellid].disallow_sit) - { - BuffFadeBySlot(j, false); - r_bonus = true; - } + for (int buff_slot = 0; buff_slot < buff_count; buff_slot++) { + if (IsValidSpell(buffs[buff_slot].spellid)) { + BuffFadeBySlot(buff_slot, false); + recalc_bonus = true; } } - if(r_bonus) - { + if (recalc_bonus) { CalcBonuses(); } } -// removes the buff matching spell_id -void Mob::BuffFadeBySpellID(uint16 spell_id) +void Mob::BuffFadeNonPersistDeath() { + bool recalc_bonus = false; int buff_count = GetMaxTotalSlots(); - for (int j = 0; j < buff_count; j++) - { - if (buffs[j].spellid == spell_id) - BuffFadeBySlot(j, false); + for (int buff_slot = 0; buff_slot < buff_count; buff_slot++) { + auto current_spell_id = buffs[buff_slot].spellid; + if ( + IsValidSpell(current_spell_id) && + !IsPersistDeathSpell(current_spell_id) + ) { + BuffFadeBySlot(buff_slot, false); + recalc_bonus = true; + } } - //we tell BuffFadeBySlot not to recalc, so we can do it only once when were done - CalcBonuses(); + if (recalc_bonus) { + CalcBonuses(); + } +} + +void Mob::BuffFadeBeneficial() { + bool recalc_bonus = false; + int buff_count = GetMaxTotalSlots(); + for (int buff_slot = 0; buff_slot < buff_count; buff_slot++) { + auto current_spell_id = buffs[buff_slot].spellid; + if ( + IsValidSpell(current_spell_id) && + IsBeneficialSpell(current_spell_id) + ) { + BuffFadeBySlot(buff_slot, false); + recalc_bonus = true; + } + } + + if (recalc_bonus) { + CalcBonuses(); + } +} + +void Mob::BuffFadeDetrimental() { + bool recalc_bonus = false; + int buff_count = GetMaxTotalSlots(); + for (int buff_slot = 0; buff_slot < buff_count; buff_slot++) { + auto current_spell_id = buffs[buff_slot].spellid; + if ( + IsValidSpell(current_spell_id) && + IsDetrimentalSpell(current_spell_id) + ) { + BuffFadeBySlot(buff_slot, false); + recalc_bonus = true; + } + } + + if (recalc_bonus) { + CalcBonuses(); + } +} + +void Mob::BuffFadeDetrimentalByCaster(Mob *caster) +{ + if(!caster) { + return; + } + + bool recalc_bonus = false; + int buff_count = GetMaxTotalSlots(); + for (int buff_slot = 0; buff_slot < buff_count; buff_slot++) { + auto current_spell_id = buffs[buff_slot].spellid; + if ( + IsValidSpell(current_spell_id) && + IsDetrimentalSpell(current_spell_id) && + caster->GetID() == buffs[buff_slot].casterid + ) { + BuffFadeBySlot(buff_slot, false); + recalc_bonus = true; + } + } + + if (recalc_bonus) { + CalcBonuses(); + } +} + +void Mob::BuffFadeBySitModifier() +{ + bool recalc_bonus = false; + int buff_count = GetMaxTotalSlots(); + for (int buff_slot = 0; buff_slot < buff_count; buff_slot++) { + auto current_spell_id = buffs[buff_slot].spellid; + if ( + IsValidSpell(current_spell_id) && + spells[current_spell_id].disallow_sit + ) { + BuffFadeBySlot(buff_slot, false); + recalc_bonus = true; + } + } + + if (recalc_bonus) { + CalcBonuses(); + } +} + +void Mob::BuffFadeBySpellID(uint16 spell_id) +{ + bool recalc_bonus = false; + int buff_count = GetMaxTotalSlots(); + for (int buff_slot = 0; buff_slot < buff_count; buff_slot++) { + if (buffs[buff_slot].spellid == spell_id) { + BuffFadeBySlot(buff_slot, false); + recalc_bonus = true; + } + } + + if (recalc_bonus) { + CalcBonuses(); + } } void Mob::BuffFadeBySpellIDAndCaster(uint16 spell_id, uint16 caster_id) { bool recalc_bonus = false; auto buff_count = GetMaxTotalSlots(); - for (int i = 0; i < buff_count; ++i) { - if (buffs[i].spellid == spell_id && buffs[i].casterid == caster_id) { - BuffFadeBySlot(i, false); + for (int buff_slot = 0; buff_slot < buff_count; buff_slot++) { + if ( + buffs[buff_slot].spellid == spell_id && + buffs[buff_slot].casterid == caster_id + ) { + BuffFadeBySlot(buff_slot, false); recalc_bonus = true; } } - if (recalc_bonus) + if (recalc_bonus) { CalcBonuses(); + } } -// removes buffs containing effectid, skipping skipslot -void Mob::BuffFadeByEffect(int effect_id, int skipslot) +void Mob::BuffFadeByEffect(int effect_id, int slot_to_skip) { - int i; - + bool recalc_bonus = false; int buff_count = GetMaxTotalSlots(); - for(i = 0; i < buff_count; i++) - { - if(buffs[i].spellid == SPELL_UNKNOWN) - continue; - if(IsEffectInSpell(buffs[i].spellid, effect_id) && i != skipslot) - BuffFadeBySlot(i, false); + for(int buff_slot = 0; buff_slot < buff_count; buff_slot++) { + auto current_spell_id = buffs[buff_slot].spellid; + if ( + IsValidSpell(current_spell_id) && + IsEffectInSpell(current_spell_id, effect_id) && + buff_slot != slot_to_skip + ) { + BuffFadeBySlot(buff_slot, false); + recalc_bonus = true; + } } - //we tell BuffFadeBySlot not to recalc, so we can do it only once when were done - CalcBonuses(); + if (recalc_bonus) { + CalcBonuses(); + } } bool Mob::IsAffectedByBuff(uint16 spell_id) { - int buff_count = GetMaxTotalSlots(); - for (int i = 0; i < buff_count; ++i) - if (buffs[i].spellid == spell_id) - return true; - - return false; + return FindBuff(spell_id); } bool Mob::IsAffectedByBuffByGlobalGroup(GlobalGroup group) { int buff_count = GetMaxTotalSlots(); - for (int i = 0; i < buff_count; ++i) { - if (buffs[i].spellid == SPELL_UNKNOWN) - continue; - if (spells[buffs[i].spellid].spell_category == static_cast(group)) + for (int buff_slot = 0; buff_slot < buff_count; buff_slot++) { + auto current_spell_id = buffs[buff_slot].spellid; + if ( + IsValidSpell(current_spell_id) && + spells[current_spell_id].spell_category == static_cast(group) + ) { return true; + } } return false;