diff options
Diffstat (limited to 'src')
-rwxr-xr-x | src/server/game/AI/CoreAI/PetAI.cpp | 40 | ||||
-rwxr-xr-x | src/server/game/Entities/Unit/Unit.cpp | 239 | ||||
-rwxr-xr-x | src/server/game/Server/Protocol/Handlers/BattleGroundHandler.cpp | 7 | ||||
-rwxr-xr-x | src/server/game/Spells/SpellEffects.cpp | 8 | ||||
-rw-r--r-- | src/server/scripts/Northrend/Nexus/Nexus/boss_keristrasza.cpp | 9 | ||||
-rw-r--r-- | src/server/scripts/Northrend/Ulduar/ulduar/boss_flame_leviathan.cpp | 181 | ||||
-rw-r--r-- | src/server/scripts/Northrend/Ulduar/ulduar/ulduar.h | 2 | ||||
-rw-r--r-- | src/server/scripts/Spells/spell_dk.cpp | 8 | ||||
-rw-r--r-- | src/server/scripts/Spells/spell_generic.cpp | 2 | ||||
-rw-r--r-- | src/server/scripts/Spells/spell_quest.cpp | 2 | ||||
-rwxr-xr-x | src/server/shared/Logging/Log.cpp | 12 | ||||
-rwxr-xr-x | src/server/shared/Logging/Log.h | 1 |
12 files changed, 208 insertions, 303 deletions
diff --git a/src/server/game/AI/CoreAI/PetAI.cpp b/src/server/game/AI/CoreAI/PetAI.cpp index 442da862b8a..5a0c199a4c0 100755 --- a/src/server/game/AI/CoreAI/PetAI.cpp +++ b/src/server/game/AI/CoreAI/PetAI.cpp @@ -141,13 +141,8 @@ void PetAI::UpdateAI(const uint32 diff) if (me->GetCharmInfo() && me->GetCharmInfo()->GetGlobalCooldownMgr().HasGlobalCooldown(spellInfo)) continue; - // ignore some combinations of combat state and combat/noncombat spells - if (!me->getVictim()) + if (spellInfo->IsPositive()) { - // ignore attacking spells, and allow only self/around spells - if (!spellInfo->IsPositive()) - continue; - // non combat spells allowed // only pet spells have IsNonCombatSpell and not fit this reqs: // Consume Shadows, Lesser Invisibility, so ignore checks for its @@ -163,36 +158,21 @@ void PetAI::UpdateAI(const uint32 diff) if (cooldown >= 0 && duration >= 0 && cooldown > duration) continue; } - } - else - { - // just ignore non-combat spells - if (!spellInfo->CanBeUsedInCombat()) - continue; - } - Spell* spell = new Spell(me, spellInfo, TRIGGERED_NONE, 0); + Spell* spell = new Spell(me, spellInfo, TRIGGERED_NONE, 0); - // Fix to allow pets on STAY to autocast - if (me->getVictim() && _CanAttack(me->getVictim()) && spell->CanAutoCast(me->getVictim())) - { - targetSpellStore.push_back(std::make_pair<Unit*, Spell*>(me->getVictim(), spell)); - continue; - } - else - { bool spellUsed = false; for (std::set<uint64>::const_iterator tar = m_AllySet.begin(); tar != m_AllySet.end(); ++tar) { - Unit* Target = ObjectAccessor::GetUnit(*me, *tar); + Unit* target = ObjectAccessor::GetUnit(*me, *tar); //only buff targets that are in combat, unless the spell can only be cast while out of combat - if (!Target) + if (!target) continue; - if (spell->CanAutoCast(Target)) + if (spell->CanAutoCast(target)) { - targetSpellStore.push_back(std::make_pair<Unit*, Spell*>(Target, spell)); + targetSpellStore.push_back(std::make_pair<Unit*, Spell*>(target, spell)); spellUsed = true; break; } @@ -200,6 +180,14 @@ void PetAI::UpdateAI(const uint32 diff) if (!spellUsed) delete spell; } + else if (me->getVictim() && _CanAttack(me->getVictim()) && spellInfo->CanBeUsedInCombat()) + { + Spell* spell = new Spell(me, spellInfo, TRIGGERED_NONE, 0); + if (spell->CanAutoCast(me->getVictim())) + targetSpellStore.push_back(std::make_pair<Unit*, Spell*>(me->getVictim(), spell)); + else + delete spell; + } } //found units to cast on to diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 26e3a79503d..a7b08d3872e 100755 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -9329,234 +9329,12 @@ ReputationRank Unit::GetFactionReactionTo(FactionTemplateEntry const* factionTem bool Unit::IsHostileTo(Unit const* unit) const { - if (!unit) - return false; - // always non-hostile to self - if (unit == this) - return false; - - // always non-hostile to GM in GM mode - if (unit->GetTypeId() == TYPEID_PLAYER && ((Player const*)unit)->isGameMaster()) - return false; - - // always hostile to enemy - if (getVictim() == unit || unit->getVictim() == this) - return true; - - // test pet/charm masters instead pers/charmeds - Unit const* testerOwner = GetCharmerOrOwner(); - Unit const* targetOwner = unit->GetCharmerOrOwner(); - - // always hostile to owner's enemy - if (testerOwner && (testerOwner->getVictim() == unit || unit->getVictim() == testerOwner)) - return true; - - // always hostile to enemy owner - if (targetOwner && (getVictim() == targetOwner || targetOwner->getVictim() == this)) - return true; - - // always hostile to owner of owner's enemy - if (testerOwner && targetOwner && (testerOwner->getVictim() == targetOwner || targetOwner->getVictim() == testerOwner)) - return true; - - Unit const* tester = testerOwner ? testerOwner : this; - Unit const* target = targetOwner ? targetOwner : unit; - - // always non-hostile to target with common owner, or to owner/pet - if (tester == target) - return false; - - // special cases (Duel, etc) - if (tester->GetTypeId() == TYPEID_PLAYER && target->GetTypeId() == TYPEID_PLAYER) - { - Player const* pTester = (Player const*)tester; - Player const* pTarget = (Player const*)target; - - // Duel - if (pTester->duel && pTester->duel->opponent == pTarget && pTester->duel->startTime != 0) - return true; - - // Group - if (pTester->GetGroup() && pTester->GetGroup() == pTarget->GetGroup()) - return false; - - // Sanctuary - if (pTarget->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY) && pTester->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY)) - return false; - - // PvP FFA state - if (pTester->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP) && pTarget->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP)) - return true; - - // = PvP states - // Green/Blue (can't attack) - if (!pTester->HasAuraType(SPELL_AURA_MOD_FACTION) && !pTarget->HasAuraType(SPELL_AURA_MOD_FACTION)) - { - if (pTester->GetTeam() == pTarget->GetTeam()) - return false; - - // Red (can attack) if true, Blue/Yellow (can't attack) in another case - return pTester->IsPvP() && pTarget->IsPvP(); - } - } - - // faction base cases - FactionTemplateEntry const*tester_faction = tester->getFactionTemplateEntry(); - FactionTemplateEntry const*target_faction = target->getFactionTemplateEntry(); - if (!tester_faction || !target_faction) - return false; - - if (target->isAttackingPlayer() && tester->IsContestedGuard()) - return true; - - // PvC forced reaction and reputation case - if (tester->GetTypeId() == TYPEID_PLAYER && !tester->HasAuraType(SPELL_AURA_MOD_FACTION)) - { - // forced reaction - if (target_faction->faction) - { - if (ReputationRank const* force = tester->ToPlayer()->GetReputationMgr().GetForcedRankIfAny(target_faction)) - return *force <= REP_HOSTILE; - - // if faction have reputation then hostile state for tester at 100% dependent from at_war state - if (FactionEntry const* raw_target_faction = sFactionStore.LookupEntry(target_faction->faction)) - if (FactionState const* factionState = tester->ToPlayer()->GetReputationMgr().GetState(raw_target_faction)) - return (factionState->Flags & FACTION_FLAG_AT_WAR); - } - } - // CvP forced reaction and reputation case - else if (target->GetTypeId() == TYPEID_PLAYER && !target->HasAuraType(SPELL_AURA_MOD_FACTION)) - { - // forced reaction - if (tester_faction->faction) - { - if (ReputationRank const* force = target->ToPlayer()->GetReputationMgr().GetForcedRankIfAny(tester_faction)) - return *force <= REP_HOSTILE; - - // apply reputation state - FactionEntry const* raw_tester_faction = sFactionStore.LookupEntry(tester_faction->faction); - if (raw_tester_faction && raw_tester_faction->reputationListID >= 0) - return ((Player const*)target)->GetReputationMgr().GetRank(raw_tester_faction) <= REP_HOSTILE; - } - } - - // common faction based case (CvC, PvC, CvP) - return tester_faction->IsHostileTo(*target_faction); + return GetReactionTo(unit) <= REP_HOSTILE; } bool Unit::IsFriendlyTo(Unit const* unit) const { - // always friendly to self - if (unit == this) - return true; - - // always friendly to GM in GM mode - if (unit->GetTypeId() == TYPEID_PLAYER && ((Player const*)unit)->isGameMaster()) - return true; - - // always non-friendly to enemy - if (getVictim() == unit || unit->getVictim() == this) - return false; - - // test pet/charm masters instead pers/charmeds - Unit const* testerOwner = GetCharmerOrOwner(); - Unit const* targetOwner = unit->GetCharmerOrOwner(); - - // always non-friendly to owner's enemy - if (testerOwner && (testerOwner->getVictim() == unit || unit->getVictim() == testerOwner)) - return false; - - // always non-friendly to enemy owner - if (targetOwner && (getVictim() == targetOwner || targetOwner->getVictim() == this)) - return false; - - // always non-friendly to owner of owner's enemy - if (testerOwner && targetOwner && (testerOwner->getVictim() == targetOwner || targetOwner->getVictim() == testerOwner)) - return false; - - Unit const* tester = testerOwner ? testerOwner : this; - Unit const* target = targetOwner ? targetOwner : unit; - - // always friendly to target with common owner, or to owner/pet - if (tester == target) - return true; - - // special cases (Duel) - if (tester->GetTypeId() == TYPEID_PLAYER && target->GetTypeId() == TYPEID_PLAYER) - { - Player const* pTester = (Player const*)tester; - Player const* pTarget = (Player const*)target; - - // Duel - if (pTester->duel && pTester->duel->opponent == target && pTester->duel->startTime != 0) - return false; - - // Group - if (pTester->GetGroup() && pTester->GetGroup() == pTarget->GetGroup()) - return true; - - // Sanctuary - if (pTarget->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY) && pTester->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY)) - return true; - - // PvP FFA state - if (pTester->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP) && pTarget->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP)) - return false; - - // = PvP states - // Green/Blue (non-attackable) - if (!pTester->HasAuraType(SPELL_AURA_MOD_FACTION) && !pTarget->HasAuraType(SPELL_AURA_MOD_FACTION)) - { - if (pTester->GetTeam() == pTarget->GetTeam()) - return true; - - // Blue (friendly/non-attackable) if not PVP, or Yellow/Red in another case (attackable) - return !pTarget->IsPvP(); - } - } - - // faction base cases - FactionTemplateEntry const* tester_faction = tester->getFactionTemplateEntry(); - FactionTemplateEntry const* target_faction = target->getFactionTemplateEntry(); - if (!tester_faction || !target_faction) - return false; - - if (target->isAttackingPlayer() && tester->IsContestedGuard()) - return false; - - // PvC forced reaction and reputation case - if (tester->GetTypeId() == TYPEID_PLAYER && !tester->HasAuraType(SPELL_AURA_MOD_FACTION)) - { - // forced reaction - if (target_faction->faction) - { - if (ReputationRank const* force = tester->ToPlayer()->GetReputationMgr().GetForcedRankIfAny(target_faction)) - return *force >= REP_FRIENDLY; - - // if faction have reputation then friendly state for tester at 100% dependent from at_war state - if (FactionEntry const* raw_target_faction = sFactionStore.LookupEntry(target_faction->faction)) - if (FactionState const* factionState = tester->ToPlayer()->GetReputationMgr().GetState(raw_target_faction)) - return !(factionState->Flags & FACTION_FLAG_AT_WAR); - } - } - // CvP forced reaction and reputation case - else if (target->GetTypeId() == TYPEID_PLAYER && !target->HasAuraType(SPELL_AURA_MOD_FACTION)) - { - // forced reaction - if (tester_faction->faction) - { - if (ReputationRank const* force = target->ToPlayer()->GetReputationMgr().GetForcedRankIfAny(tester_faction)) - return *force >= REP_FRIENDLY; - - // apply reputation state - if (FactionEntry const* raw_tester_faction = sFactionStore.LookupEntry(tester_faction->faction)) - if (raw_tester_faction->reputationListID >= 0) - return ((Player const*)target)->GetReputationMgr().GetRank(raw_tester_faction) >= REP_FRIENDLY; - } - } - - // common faction based case (CvC, PvC, CvP) - return tester_faction->IsFriendlyTo(*target_faction); + return GetReactionTo(unit) >= REP_FRIENDLY; } bool Unit::IsHostileToPlayers() const @@ -11127,6 +10905,13 @@ bool Unit::isSpellCrit(Unit* victim, SpellInfo const* spellProto, SpellSchoolMas // Custom crit by class switch (spellProto->SpellFamilyName) { + case SPELLFAMILY_MAGE: + // Glyph of Fire Blast + if (spellProto->SpellFamilyFlags[0] == 0x2 && spellProto->SpellIconID == 12) + if (victim->HasAuraWithMechanic((1<<MECHANIC_STUN) | (1<<MECHANIC_KNOCKOUT))) + if (AuraEffect const* aurEff = GetAuraEffect(56369, EFFECT_0)) + crit_chance += aurEff->GetAmount(); + break; case SPELLFAMILY_DRUID: // Improved Faerie Fire if (victim->HasAuraState(AURA_STATE_FAERIE_FIRE)) @@ -12359,8 +12144,8 @@ bool Unit::_IsValidAttackTarget(Unit const* target, SpellInfo const* bySpell) co if (IsOnVehicle(target) || m_vehicle->GetBase()->IsOnVehicle(target)) return false; - // can't attack invisible - if ((!bySpell || !(bySpell->AttributesEx6 & SPELL_ATTR6_CAN_TARGET_INVISIBLE)) && !canSeeOrDetect(target)) + // can't attack invisible (ignore stealth for aoe spells) + if ((!bySpell || !(bySpell->AttributesEx6 & SPELL_ATTR6_CAN_TARGET_INVISIBLE)) && !canSeeOrDetect(target, bySpell && bySpell->IsAOE())) return false; // can't attack dead @@ -12454,7 +12239,7 @@ bool Unit::_IsValidAssistTarget(Unit const* target, SpellInfo const* bySpell) co return false; // can't assist invisible - if ((!bySpell || !(bySpell->AttributesEx6 & SPELL_ATTR6_CAN_TARGET_INVISIBLE)) && !canSeeOrDetect(target)) + if ((!bySpell || !(bySpell->AttributesEx6 & SPELL_ATTR6_CAN_TARGET_INVISIBLE)) && !canSeeOrDetect(target, bySpell && bySpell->IsAOE())) return false; // can't assist dead diff --git a/src/server/game/Server/Protocol/Handlers/BattleGroundHandler.cpp b/src/server/game/Server/Protocol/Handlers/BattleGroundHandler.cpp index 69c1cc5edfe..1810016d22e 100755 --- a/src/server/game/Server/Protocol/Handlers/BattleGroundHandler.cpp +++ b/src/server/game/Server/Protocol/Handlers/BattleGroundHandler.cpp @@ -339,7 +339,7 @@ void WorldSession::HandleBattlefieldListOpcode(WorldPacket &recv_data) BattlemasterListEntry const* bl = sBattlemasterListStore.LookupEntry(bgTypeId); if (!bl) { - sLog->outError("Battleground: invalid bgtype received."); + sLog->outDebug(LOG_FILTER_BATTLEGROUND, "BattlegroundHandler: invalid bgtype (%u) with player (Name: %s, GUID: %u) received.", bgTypeId, _player->GetName(), _player->GetGUIDLow()); return; } @@ -362,12 +362,13 @@ void WorldSession::HandleBattleFieldPortOpcode(WorldPacket &recv_data) if (!sBattlemasterListStore.LookupEntry(bgTypeId_)) { - sLog->outError("BattlegroundHandler: invalid bgtype (%u) with player (Name: %s, GUID: %u) received.", bgTypeId_, _player->GetName(), _player->GetGUIDLow()); + sLog->outDebug(LOG_FILTER_BATTLEGROUND, "BattlegroundHandler: invalid bgtype (%u) with player (Name: %s, GUID: %u) received.", bgTypeId_, _player->GetName(), _player->GetGUIDLow()); return; } + if (!_player->InBattlegroundQueue()) { - sLog->outError("BattlegroundHandler: Invalid CMSG_BATTLEFIELD_PORT received from player (%u), he is not in bg_queue.", _player->GetGUIDLow()); + sLog->outDebug(LOG_FILTER_BATTLEGROUND, "BattlegroundHandler: Invalid CMSG_BATTLEFIELD_PORT received from player (Name: %s, GUID: %u), he is not in bg_queue.", _player->GetName(), _player->GetGUIDLow()); return; } diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 0637c25e3ab..43136555c7a 100755 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -1593,8 +1593,8 @@ void Spell::EffectTriggerSpell(SpellEffIndex effIndex) if (unitTarget->ToPlayer()->HasSpellCooldown(1784)) unitTarget->ToPlayer()->RemoveSpellCooldown(1784); - triggered_spell_id = 1784; - break; + unitTarget->CastSpell(unitTarget, 1784, true); + return; } // Demonic Empowerment -- succubus case 54437: @@ -1604,8 +1604,8 @@ void Spell::EffectTriggerSpell(SpellEffIndex effIndex) unitTarget->RemoveAurasByType(SPELL_AURA_MOD_STUN); // Cast Lesser Invisibility - triggered_spell_id = 7870; - break; + unitTarget->CastSpell(unitTarget, 7870, true); + return; } // just skip case 23770: // Sayge's Dark Fortune of * diff --git a/src/server/scripts/Northrend/Nexus/Nexus/boss_keristrasza.cpp b/src/server/scripts/Northrend/Nexus/Nexus/boss_keristrasza.cpp index 7d355b2f71a..1a153474416 100644 --- a/src/server/scripts/Northrend/Nexus/Nexus/boss_keristrasza.cpp +++ b/src/server/scripts/Northrend/Nexus/Nexus/boss_keristrasza.cpp @@ -237,12 +237,13 @@ class spell_intense_cold : public SpellScriptLoader void HandlePeriodicTick(AuraEffect const* aurEff) { + if (aurEff->GetBase()->GetStackAmount() < 2) + return; Unit* caster = GetCaster(); - if (!caster) + //TODO: the caster should be boss but not the player + if (!caster || !caster->GetAI()) return; - - if (aurEff->GetBase()->GetStackAmount() >= 2) - caster->GetAI()->SetGUID(GetTarget()->GetGUID(), DATA_INTENSE_COLD); + caster->GetAI()->SetGUID(GetTarget()->GetGUID(), DATA_INTENSE_COLD); } void Register() diff --git a/src/server/scripts/Northrend/Ulduar/ulduar/boss_flame_leviathan.cpp b/src/server/scripts/Northrend/Ulduar/ulduar/boss_flame_leviathan.cpp index 2aad0974e92..b72b84f18a9 100644 --- a/src/server/scripts/Northrend/Ulduar/ulduar/boss_flame_leviathan.cpp +++ b/src/server/scripts/Northrend/Ulduar/ulduar/boss_flame_leviathan.cpp @@ -32,6 +32,7 @@ #include "SpellInfo.h" #include "SpellScript.h" #include "Vehicle.h" +#include "VehicleDefines.h" #include "ulduar.h" enum Spells @@ -272,8 +273,8 @@ class boss_flame_leviathan : public CreatureScript void EnterCombat(Unit* /*who*/) { _EnterCombat(); - me->SetReactState(REACT_AGGRESSIVE); - events.ScheduleEvent(EVENT_PURSUE, 30*IN_MILLISECONDS); + me->SetReactState(REACT_PASSIVE); + events.ScheduleEvent(EVENT_PURSUE, 1); events.ScheduleEvent(EVENT_MISSILE, urand(1500, 4*IN_MILLISECONDS)); events.ScheduleEvent(EVENT_VENT, 20*IN_MILLISECONDS); events.ScheduleEvent(EVENT_SHUTDOWN, 150*IN_MILLISECONDS); @@ -319,14 +320,6 @@ class boss_flame_leviathan : public CreatureScript DoScriptText(SAY_AGGRO, me); } - //TODO: effect 0 and effect 1 may be on different target - //TODO: Move to spellscript - void SpellHitTarget(Unit* target, SpellInfo const* spell) - { - if (spell->Id == SPELL_PURSUED) - AttackStart(target); - } - void JustDied(Unit* /*victim*/) { _JustDied(); @@ -388,21 +381,6 @@ class boss_flame_leviathan : public CreatureScript return; } - if (me->HasAura(SPELL_SYSTEMS_SHUTDOWN)) - { - me->SetReactState(REACT_PASSIVE); - me->AddUnitState(UNIT_STAT_STUNNED | UNIT_STAT_ROOT); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); - if (Shutout) - Shutout = false; - return; - } - else - { - me->SetReactState(REACT_AGGRESSIVE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); - } - if (me->HasUnitState(UNIT_STAT_CASTING)) return; @@ -412,12 +390,8 @@ class boss_flame_leviathan : public CreatureScript { case EVENT_PURSUE: DoScriptText(RAND(SAY_TARGET_1, SAY_TARGET_2, SAY_TARGET_3), me); - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 75, true)) - { - me->CastSpell(target, SPELL_PURSUED, true); - me->MonsterTextEmote(EMOTE_PURSUE, target->GetGUID(), true); - } - events.ScheduleEvent(EVENT_PURSUE, 30*IN_MILLISECONDS); + DoCast(SPELL_PURSUED); // Will select target in spellscript + events.ScheduleEvent(EVENT_PURSUE, 35*IN_MILLISECONDS); break; case EVENT_MISSILE: DoCast(me, SPELL_MISSILE_BARRAGE, true); @@ -441,9 +415,10 @@ class boss_flame_leviathan : public CreatureScript DoScriptText(RAND(SAY_OVERLOAD_1, SAY_OVERLOAD_2, SAY_OVERLOAD_3), me); me->MonsterTextEmote(EMOTE_OVERLOAD, 0, true); me->CastSpell(me, SPELL_SYSTEMS_SHUTDOWN, true); - me->RemoveAurasDueToSpell(SPELL_GATHERING_SPEED); + if (Shutout) + Shutout = false; events.ScheduleEvent(EVENT_REPAIR, 4000); - events.CancelEvent(EVENT_SHUTDOWN); + events.DelayEvents(20 * IN_MILLISECONDS, 0); break; case EVENT_REPAIR: me->MonsterTextEmote(EMOTE_REPAIR, 0, true); @@ -488,7 +463,7 @@ class boss_flame_leviathan : public CreatureScript //TODO: Fix this spell, gets applied on players who are on leviathan should be excluded? /*if (me->IsWithinMeleeRange(me->getVictim())) //bugged spell casts on units that are boarded on leviathan DoSpellAttackIfReady(SPELL_BATTERING_RAM);*/ - DoMeleeAttackIfReady(); + //DoMeleeAttackIfReady(); } void DoAction(int32 const action) @@ -553,6 +528,8 @@ class boss_flame_leviathan : public CreatureScript break; } } + + //Unit* SelectTarget() }; CreatureAI* GetAI(Creature* creature) const @@ -1560,6 +1537,140 @@ class spell_auto_repair : public SpellScriptLoader } }; +class spell_systems_shutdown : public SpellScriptLoader +{ + public: + spell_systems_shutdown() : SpellScriptLoader("spell_systems_shutdown") { } + + class spell_systems_shutdown_AuraScript : public AuraScript + { + PrepareAuraScript(spell_systems_shutdown_AuraScript); + + void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + Creature* owner = GetOwner()->ToCreature(); + if (!owner) + return; + + //! This could probably in the SPELL_EFFECT_SEND_EVENT handler too: + owner->AddUnitState(UNIT_STAT_STUNNED | UNIT_STAT_ROOT); + owner->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); + owner->RemoveAurasDueToSpell(SPELL_GATHERING_SPEED); + } + + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + Creature* owner = GetOwner()->ToCreature(); + if (!owner) + return; + + owner->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); + } + + void Register() + { + OnEffectApply += AuraEffectApplyFn(spell_systems_shutdown_AuraScript::OnApply, EFFECT_0, SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, AURA_EFFECT_HANDLE_REAL); + OnEffectRemove += AuraEffectRemoveFn(spell_systems_shutdown_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_systems_shutdown_AuraScript(); + } +}; + +class FlameLeviathanPursuedTargetSelector +{ + enum Area + { + AREA_FORMATION_GROUNDS = 4652, + }; + + public: + explicit FlameLeviathanPursuedTargetSelector(Unit* unit) : _me(unit) {}; + + bool operator()(Unit* target) const + { + //! No players, only vehicles (todo: check if blizzlike) + Creature* creatureTarget = target->ToCreature(); + if (!creatureTarget) + return true; + + //! NPC entries must match + if (creatureTarget->GetEntry() != NPC_SALVAGED_DEMOLISHER && creatureTarget->GetEntry() != NPC_SALVAGED_SIEGE_ENGINE) + return true; + + //! NPC must be a valid vehicle installation + Vehicle* vehicle = creatureTarget->GetVehicleKit(); + if (!vehicle) + return true; + + //! Entity needs to be in appropriate area + if (target->GetAreaId() != AREA_FORMATION_GROUNDS) + return true; + + //! Vehicle must be in use by player + bool playerFound = false; + for (SeatMap::const_iterator itr = vehicle->Seats.begin(); itr != vehicle->Seats.end() && !playerFound; ++itr) + if (IS_PLAYER_GUID(itr->second.Passenger)) + playerFound = true; + + return !playerFound; + } + + private: + Unit const* _me; +}; + +class spell_pursue : public SpellScriptLoader +{ + public: + spell_pursue() : SpellScriptLoader("spell_pursue") {} + + class spell_pursue_SpellScript : public SpellScript + { + PrepareSpellScript(spell_pursue_SpellScript); + + void FilterTargets(std::list<Unit*>& targets) + { + targets.remove_if(FlameLeviathanPursuedTargetSelector(GetCaster())); + if (targets.empty()) + if (Creature* caster = GetCaster()->ToCreature()) + caster->AI()->EnterEvadeMode(); + } + + void HandleScript(SpellEffIndex eff) + { + Creature* caster = GetCaster()->ToCreature(); + if (!caster) + return; + + caster->AI()->AttackStart(GetHitUnit()); // Chase target + + for (SeatMap::const_iterator itr = caster->GetVehicleKit()->Seats.begin(); itr != caster->GetVehicleKit()->Seats.end(); ++itr) + { + if (IS_PLAYER_GUID(itr->second.Passenger)) + { + caster->MonsterTextEmote(EMOTE_PURSUE, itr->second.Passenger, true); + return; + } + } + } + + void Register() + { + OnUnitTargetSelect += SpellUnitTargetFn(spell_pursue_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnEffectHitTarget += SpellEffectFn(spell_pursue_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_APPLY_AURA); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_pursue_SpellScript(); + } +}; + void AddSC_boss_flame_leviathan() { new boss_flame_leviathan(); @@ -1592,4 +1703,6 @@ void AddSC_boss_flame_leviathan() new spell_load_into_catapult(); new spell_auto_repair(); + new spell_systems_shutdown(); + new spell_pursue(); } diff --git a/src/server/scripts/Northrend/Ulduar/ulduar/ulduar.h b/src/server/scripts/Northrend/Ulduar/ulduar/ulduar.h index 2caee4b600c..cff57563843 100644 --- a/src/server/scripts/Northrend/Ulduar/ulduar/ulduar.h +++ b/src/server/scripts/Northrend/Ulduar/ulduar/ulduar.h @@ -51,6 +51,8 @@ enum UlduarNPCs { // General NPC_LEVIATHAN = 33113, + NPC_SALVAGED_DEMOLISHER = 33109, + NPC_SALVAGED_SIEGE_ENGINE = 33060, NPC_IGNIS = 33118, NPC_RAZORSCALE = 33186, NPC_RAZORSCALE_CONTROLLER = 33233, diff --git a/src/server/scripts/Spells/spell_dk.cpp b/src/server/scripts/Spells/spell_dk.cpp index 19f9cea8ed1..b30841e19cc 100644 --- a/src/server/scripts/Spells/spell_dk.cpp +++ b/src/server/scripts/Spells/spell_dk.cpp @@ -167,9 +167,11 @@ class spell_dk_anti_magic_zone : public SpellScriptLoader { SpellInfo const* talentSpell = sSpellMgr->GetSpellInfo(DK_SPELL_ANTI_MAGIC_SHELL_TALENT); amount = talentSpell->Effects[EFFECT_0].CalcValue(GetCaster()); - // assume caster is a player here - if (Unit* caster = GetCaster()) - amount += int32(2 * caster->ToPlayer()->GetTotalAttackPowerValue(BASE_ATTACK)); + Unit* caster = GetCaster(); + if(!caster) + return; + if(Player* player = caster->ToPlayer()) + amount += int32(2 * player->GetTotalAttackPowerValue(BASE_ATTACK)); } void Absorb(AuraEffect* /*aurEff*/, DamageInfo & dmgInfo, uint32 & absorbAmount) diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp index 5159026d6f8..f90fe53a9e2 100644 --- a/src/server/scripts/Spells/spell_generic.cpp +++ b/src/server/scripts/Spells/spell_generic.cpp @@ -320,7 +320,7 @@ class spell_gen_pet_summoned : public SpellScriptLoader void Register() { - OnEffectHit += SpellEffectFn(spell_gen_pet_summoned_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + OnEffectHitTarget += SpellEffectFn(spell_gen_pet_summoned_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); } }; diff --git a/src/server/scripts/Spells/spell_quest.cpp b/src/server/scripts/Spells/spell_quest.cpp index fbdf9791364..6fbd33fe81b 100644 --- a/src/server/scripts/Spells/spell_quest.cpp +++ b/src/server/scripts/Spells/spell_quest.cpp @@ -56,7 +56,7 @@ public: void Register() { - OnEffectHit += SpellEffectFn(spell_generic_quest_update_entry_SpellScript::HandleDummy, _effIndex, _spellEffect); + OnEffectHitTarget += SpellEffectFn(spell_generic_quest_update_entry_SpellScript::HandleDummy, _effIndex, _spellEffect); } }; diff --git a/src/server/shared/Logging/Log.cpp b/src/server/shared/Logging/Log.cpp index d7222c8564f..55bfe76cb12 100755 --- a/src/server/shared/Logging/Log.cpp +++ b/src/server/shared/Logging/Log.cpp @@ -1039,3 +1039,15 @@ void Log::outChat(const char * str, ...) va_end(ap); } } + +void Log::outErrorST(const char * str, ...) +{ + va_list ap; + va_start(ap, str); + char nnew_str[MAX_QUERY_LEN]; + vsnprintf(nnew_str, MAX_QUERY_LEN, str, ap); + va_end(ap); + + ACE_Stack_Trace st; + outError("%s [Stacktrace: %s]", nnew_str, st.c_str()); +} diff --git a/src/server/shared/Logging/Log.h b/src/server/shared/Logging/Log.h index aba1708232f..5c23616ac5c 100755 --- a/src/server/shared/Logging/Log.h +++ b/src/server/shared/Logging/Log.h @@ -114,6 +114,7 @@ class Log void SetColor(bool stdout_stream, ColorTypes color); void ResetColor(bool stdout_stream); + void outErrorST( const char * err, ... ) ATTR_PRINTF(2, 3); void outDB( LogTypes type, const char * str ); void outString( const char * str, ... ) ATTR_PRINTF(2, 3); void outString( ); |