From 9ff4bbd0858850e9ba2a98800fb434802fd25228 Mon Sep 17 00:00:00 2001 From: Ovahlord Date: Wed, 21 Apr 2021 18:51:34 +0200 Subject: [PATCH] Core/Spells: ported implementations of SPELL_AURA_DISABLE_CASTING_EXCEPT_ABILITIES and SPELL_AURA_DISABLE_ATTACKING_EXCEPT_ABILITIES from master branch closes #93 --- src/server/game/Entities/Player/Player.cpp | 2 +- src/server/game/Entities/Player/Player.h | 64 +++++++++---------- src/server/game/Entities/Unit/Unit.cpp | 3 + .../game/Spells/Auras/SpellAuraDefines.h | 4 +- .../game/Spells/Auras/SpellAuraEffects.cpp | 38 +++++++++-- .../game/Spells/Auras/SpellAuraEffects.h | 3 +- src/server/game/Spells/Spell.cpp | 28 +++++++- 7 files changed, 97 insertions(+), 45 deletions(-) diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index f61abe85d5..79f76177d3 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -2587,7 +2587,7 @@ void Player::InitStatsForLevel(bool reapplyMods) SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_REGENERATE_POWER);// must be set // cleanup player flags (will be re-applied if need at aura load), to avoid have ghost flag without ghost aura, for example. - RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_AFK | PLAYER_FLAGS_DND | PLAYER_FLAGS_GM | PLAYER_FLAGS_GHOST | PLAYER_ALLOW_ONLY_ABILITY); + RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_AFK | PLAYER_FLAGS_DND | PLAYER_FLAGS_GM | PLAYER_FLAGS_GHOST | PLAYER_FLAGS_DISABLE_CASTING_EXCEPT_ABILITIES | PLAYER_FLAGS_DISABLE_ATTACKING_EXCEPT_ABILITIES); RemoveStandFlags(UNIT_STAND_FLAGS_ALL); // one form stealth modified bytes RemoveByteFlag(UNIT_FIELD_BYTES_2, UNIT_BYTES_2_OFFSET_PVP_FLAG, UNIT_BYTE2_FLAG_FFA_PVP | UNIT_BYTE2_FLAG_SANCTUARY); diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 25800a5680..368128a1a6 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -382,38 +382,38 @@ enum DrunkenState enum PlayerFlags { - PLAYER_FLAGS_GROUP_LEADER = 0x00000001, - PLAYER_FLAGS_AFK = 0x00000002, - PLAYER_FLAGS_DND = 0x00000004, - PLAYER_FLAGS_GM = 0x00000008, - PLAYER_FLAGS_GHOST = 0x00000010, - PLAYER_FLAGS_RESTING = 0x00000020, - PLAYER_FLAGS_UNK6 = 0x00000040, - PLAYER_FLAGS_UNK7 = 0x00000080, // pre-3.0.3 PLAYER_FLAGS_FFA_PVP flag for FFA PVP state - PLAYER_FLAGS_CONTESTED_PVP = 0x00000100, // Player has been involved in a PvP combat and will be attacked by contested guards - PLAYER_FLAGS_IN_PVP = 0x00000200, - PLAYER_FLAGS_HIDE_HELM = 0x00000400, - PLAYER_FLAGS_HIDE_CLOAK = 0x00000800, - PLAYER_FLAGS_PLAYED_LONG_TIME = 0x00001000, // played long time - PLAYER_FLAGS_PLAYED_TOO_LONG = 0x00002000, // played too long time - PLAYER_FLAGS_IS_OUT_OF_BOUNDS = 0x00004000, - PLAYER_FLAGS_DEVELOPER = 0x00008000, // prefix for something? - PLAYER_FLAGS_UNK16 = 0x00010000, // pre-3.0.3 PLAYER_FLAGS_SANCTUARY flag for player entered sanctuary - PLAYER_FLAGS_TAXI_BENCHMARK = 0x00020000, // taxi benchmark mode (on/off) (2.0.1) - PLAYER_FLAGS_PVP_TIMER = 0x00040000, // 3.0.2, pvp timer active (after you disable pvp manually) - PLAYER_FLAGS_UBER = 0x00080000, - PLAYER_FLAGS_UNK20 = 0x00100000, - PLAYER_FLAGS_UNK21 = 0x00200000, - PLAYER_FLAGS_COMMENTATOR2 = 0x00400000, - PLAYER_ALLOW_ONLY_ABILITY = 0x00800000, // used by bladestorm and killing spree, allowed only spells with SPELL_ATTR0_REQ_AMMO, SPELL_EFFECT_ATTACK, checked only for active player - PLAYER_FLAGS_UNK24 = 0x01000000, // disabled all melee ability on tab include autoattack - PLAYER_FLAGS_NO_XP_GAIN = 0x02000000, - PLAYER_FLAGS_UNK26 = 0x04000000, - PLAYER_FLAGS_AUTO_DECLINE_GUILD = 0x08000000, // Automatically declines guild invites - PLAYER_FLAGS_GUILD_LEVEL_ENABLED = 0x10000000, // Lua_GetGuildLevelEnabled() - enables guild leveling related UI - PLAYER_FLAGS_VOID_UNLOCKED = 0x20000000, // void storage - PLAYER_FLAGS_UNK30 = 0x40000000, - PLAYER_FLAGS_UNK31 = 0x80000000 + PLAYER_FLAGS_GROUP_LEADER = 0x00000001, + PLAYER_FLAGS_AFK = 0x00000002, + PLAYER_FLAGS_DND = 0x00000004, + PLAYER_FLAGS_GM = 0x00000008, + PLAYER_FLAGS_GHOST = 0x00000010, + PLAYER_FLAGS_RESTING = 0x00000020, + PLAYER_FLAGS_UNK6 = 0x00000040, + PLAYER_FLAGS_UNK7 = 0x00000080, // pre-3.0.3 PLAYER_FLAGS_FFA_PVP flag for FFA PVP state + PLAYER_FLAGS_CONTESTED_PVP = 0x00000100, // Player has been involved in a PvP combat and will be attacked by contested guards + PLAYER_FLAGS_IN_PVP = 0x00000200, + PLAYER_FLAGS_HIDE_HELM = 0x00000400, + PLAYER_FLAGS_HIDE_CLOAK = 0x00000800, + PLAYER_FLAGS_PLAYED_LONG_TIME = 0x00001000, // played long time + PLAYER_FLAGS_PLAYED_TOO_LONG = 0x00002000, // played too long time + PLAYER_FLAGS_IS_OUT_OF_BOUNDS = 0x00004000, + PLAYER_FLAGS_DEVELOPER = 0x00008000, // prefix for something? + PLAYER_FLAGS_UNK16 = 0x00010000, // pre-3.0.3 PLAYER_FLAGS_SANCTUARY flag for player entered sanctuary + PLAYER_FLAGS_TAXI_BENCHMARK = 0x00020000, // taxi benchmark mode (on/off) (2.0.1) + PLAYER_FLAGS_PVP_TIMER = 0x00040000, // 3.0.2, pvp timer active (after you disable pvp manually) + PLAYER_FLAGS_UBER = 0x00080000, + PLAYER_FLAGS_UNK20 = 0x00100000, + PLAYER_FLAGS_UNK21 = 0x00200000, + PLAYER_FLAGS_COMMENTATOR2 = 0x00400000, + PLAYER_FLAGS_DISABLE_CASTING_EXCEPT_ABILITIES = 0x00800000, // disables casting any ability except for the ones specified in the aura effect's SpellClassMask + PLAYER_FLAGS_DISABLE_ATTACKING_EXCEPT_ABILITIES = 0x01000000, // disables all attacks including ability casts except for the ones specified in the aura effect's SpellClassMask + PLAYER_FLAGS_NO_XP_GAIN = 0x02000000, + PLAYER_FLAGS_UNK26 = 0x04000000, + PLAYER_FLAGS_AUTO_DECLINE_GUILD = 0x08000000, // Automatically declines guild invites + PLAYER_FLAGS_GUILD_LEVEL_ENABLED = 0x10000000, // Lua_GetGuildLevelEnabled() - enables guild leveling related UI + PLAYER_FLAGS_VOID_UNLOCKED = 0x20000000, // void storage + PLAYER_FLAGS_UNK30 = 0x40000000, + PLAYER_FLAGS_UNK31 = 0x80000000 }; enum PlayerBytesOffsets diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index fd04c7289c..36cc5dfec1 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -5588,6 +5588,9 @@ bool Unit::Attack(Unit* victim, bool meleeAttack) if (creature && creature->IsInEvadeMode()) return false; + if (HasAuraType(SPELL_AURA_DISABLE_ATTACKING_EXCEPT_ABILITIES)) + return false; + // nobody can attack GM in GM-mode if (victim->GetTypeId() == TYPEID_PLAYER) { diff --git a/src/server/game/Spells/Auras/SpellAuraDefines.h b/src/server/game/Spells/Auras/SpellAuraDefines.h index cc945e4bad..2a41c16e9b 100644 --- a/src/server/game/Spells/Auras/SpellAuraDefines.h +++ b/src/server/game/Spells/Auras/SpellAuraDefines.h @@ -338,8 +338,8 @@ enum AuraType : uint32 SPELL_AURA_SCREEN_EFFECT = 260, SPELL_AURA_PHASE = 261, SPELL_AURA_ABILITY_IGNORE_AURASTATE = 262, - SPELL_AURA_ALLOW_ONLY_ABILITY = 263, - SPELL_AURA_264 = 264, + SPELL_AURA_DISABLE_CASTING_EXCEPT_ABILITIES = 263, + SPELL_AURA_DISABLE_ATTACKING_EXCEPT_ABILITIES = 264, SPELL_AURA_265 = 265, SPELL_AURA_266 = 266, SPELL_AURA_MOD_IMMUNE_AURA_APPLY_SCHOOL = 267, diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 084a058f96..acac221b8b 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -328,8 +328,8 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]= &AuraEffect::HandleNoImmediateEffect, //260 SPELL_AURA_SCREEN_EFFECT (miscvalue = id in ScreenEffect.dbc) not required any code &AuraEffect::HandlePhase, //261 SPELL_AURA_PHASE &AuraEffect::HandleNoImmediateEffect, //262 SPELL_AURA_ABILITY_IGNORE_AURASTATE implemented in Spell::CheckCast - &AuraEffect::HandleAuraAllowOnlyAbility, //263 SPELL_AURA_ALLOW_ONLY_ABILITY player can use only abilities set in SpellClassMask - &AuraEffect::HandleUnused, //264 unused (3.2.0) + &AuraEffect::HandleAuraDisableCastingExceptAbilities, //263 SPELL_AURA_DISABLE_CASTING_EXCEPT_ABILITIES implemented in Spell::CheckCast + &AuraEffect::HandleAuraDisableAttackingExceptAbilities, //264 SPELL_AURA_DISABLE_ATTACKING_EXCEPT_ABILITIES implemented in Spell::CheckCast, Unit::Attack &AuraEffect::HandleUnused, //265 unused (4.3.4) &AuraEffect::HandleUnused, //266 unused (4.3.4) &AuraEffect::HandleNoImmediateEffect, //267 SPELL_AURA_MOD_IMMUNE_AURA_APPLY_SCHOOL implemented in Unit::IsImmunedToSpellEffect @@ -2490,23 +2490,47 @@ void AuraEffect::HandleAuraModPacifyAndSilence(AuraApplication const* aurApp, ui HandleAuraModSilence(aurApp, mode, apply); } -void AuraEffect::HandleAuraAllowOnlyAbility(AuraApplication const* aurApp, uint8 mode, bool apply) const +void AuraEffect::HandleAuraDisableCastingExceptAbilities(AuraApplication const* aurApp, uint8 mode, bool apply) const { if (!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK)) return; Unit* target = aurApp->GetTarget(); - if (target->GetTypeId() == TYPEID_PLAYER) + if (target->IsPlayer()) { if (apply) - target->SetFlag(PLAYER_FLAGS, PLAYER_ALLOW_ONLY_ABILITY); + target->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_DISABLE_CASTING_EXCEPT_ABILITIES); else { // do not remove unit flag if there are more than this auraEffect of that kind on unit on unit - if (target->HasAuraType(SPELL_AURA_ALLOW_ONLY_ABILITY)) + if (target->HasAuraType(SPELL_AURA_DISABLE_CASTING_EXCEPT_ABILITIES)) return; - target->RemoveFlag(PLAYER_FLAGS, PLAYER_ALLOW_ONLY_ABILITY); + target->RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_DISABLE_CASTING_EXCEPT_ABILITIES); + } + } +} + +void AuraEffect::HandleAuraDisableAttackingExceptAbilities(AuraApplication const* aurApp, uint8 mode, bool apply) const +{ + if (!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK)) + return; + + Unit* target = aurApp->GetTarget(); + + if (target->IsPlayer()) + { + if (apply) + { + target->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_DISABLE_ATTACKING_EXCEPT_ABILITIES); + target->AttackStop(); + } + else + { + // do not remove unit flag if there are more than this auraEffect of that kind on unit on unit + if (target->HasAuraType(SPELL_AURA_DISABLE_ATTACKING_EXCEPT_ABILITIES)) + return; + target->RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_DISABLE_ATTACKING_EXCEPT_ABILITIES); } } } diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.h b/src/server/game/Spells/Auras/SpellAuraEffects.h index ea1dbdf6a8..bb69993484 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.h +++ b/src/server/game/Spells/Auras/SpellAuraEffects.h @@ -159,7 +159,8 @@ class TC_GAME_API AuraEffect void HandleAuraModSilence(AuraApplication const* aurApp, uint8 mode, bool apply) const; void HandleAuraModPacify(AuraApplication const* aurApp, uint8 mode, bool apply) const; void HandleAuraModPacifyAndSilence(AuraApplication const* aurApp, uint8 mode, bool apply) const; - void HandleAuraAllowOnlyAbility(AuraApplication const* aurApp, uint8 mode, bool apply) const; + void HandleAuraDisableCastingExceptAbilities(AuraApplication const* aurApp, uint8 mode, bool apply) const; + void HandleAuraDisableAttackingExceptAbilities(AuraApplication const* aurApp, uint8 mode, bool apply) const; void HandleAuraModNoActions(AuraApplication const* aurApp, uint8 mode, bool apply) const; // tracking void HandleAuraTrackResources(AuraApplication const* aurApp, uint8 mode, bool apply) const; diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 35dd1dd33f..a874cd10ce 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -5459,8 +5459,32 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint if (m_caster->GetTypeId() == TYPEID_PLAYER) { //can cast triggered (by aura only?) spells while have this flag - if (!(_triggeredCastFlags & TRIGGERED_IGNORE_CASTER_AURASTATE) && m_caster->ToPlayer()->HasFlag(PLAYER_FLAGS, PLAYER_ALLOW_ONLY_ABILITY)) - return SPELL_FAILED_SPELL_IN_PROGRESS; + if (!(_triggeredCastFlags & TRIGGERED_IGNORE_CASTER_AURASTATE)) + { + // These two auras check SpellFamilyName defined by dbc class data instead of current spell SpellFamilyName + if (m_caster->HasAuraType(SPELL_AURA_DISABLE_CASTING_EXCEPT_ABILITIES) + && !m_spellInfo->HasAttribute(SPELL_ATTR0_REQ_AMMO) + && !m_spellInfo->HasEffect(SPELL_EFFECT_ATTACK) + && !m_caster->HasAuraTypeWithFamilyFlags(SPELL_AURA_DISABLE_CASTING_EXCEPT_ABILITIES, sChrClassesStore.AssertEntry(m_caster->getClass())->SpellClassSet, m_spellInfo->SpellFamilyFlags)) + return SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW; + + if (m_caster->HasAuraType(SPELL_AURA_DISABLE_ATTACKING_EXCEPT_ABILITIES)) + { + if (!m_caster->HasAuraTypeWithFamilyFlags(SPELL_AURA_DISABLE_ATTACKING_EXCEPT_ABILITIES, sChrClassesStore.AssertEntry(m_caster->getClass())->SpellClassSet, m_spellInfo->SpellFamilyFlags)) + { + if (m_spellInfo->HasAttribute(SPELL_ATTR0_REQ_AMMO) + || m_spellInfo->IsNextMeleeSwingSpell() + || m_spellInfo->HasAttribute(SPELL_ATTR1_MELEE_COMBAT_START) + || m_spellInfo->HasAttribute(SPELL_ATTR2_UNK20) + || m_spellInfo->HasEffect(SPELL_EFFECT_ATTACK) + || m_spellInfo->HasEffect(SPELL_EFFECT_NORMALIZED_WEAPON_DMG) + || m_spellInfo->HasEffect(SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL) + || m_spellInfo->HasEffect(SPELL_EFFECT_WEAPON_PERCENT_DAMAGE) + || m_spellInfo->HasEffect(SPELL_EFFECT_WEAPON_DAMAGE)) + return SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW; + } + } + } // check if we are using a potion in combat for the 2nd+ time. Cooldown is added only after caster gets out of combat if (!IsIgnoringCooldowns() && m_caster->ToPlayer()->GetLastPotionId() && m_CastItem && (m_CastItem->IsPotion() || m_spellInfo->IsCooldownStartedOnEvent()))