aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/updates/world/2011_09_26_00_world_spell_script_names.sql4
-rwxr-xr-xsrc/server/game/AI/CoreAI/PetAI.cpp40
-rwxr-xr-xsrc/server/game/Entities/Unit/Unit.cpp239
-rwxr-xr-xsrc/server/game/Server/Protocol/Handlers/BattleGroundHandler.cpp7
-rwxr-xr-xsrc/server/game/Spells/SpellEffects.cpp8
-rw-r--r--src/server/scripts/Northrend/Nexus/Nexus/boss_keristrasza.cpp9
-rw-r--r--src/server/scripts/Northrend/Ulduar/ulduar/boss_flame_leviathan.cpp181
-rw-r--r--src/server/scripts/Northrend/Ulduar/ulduar/ulduar.h2
-rw-r--r--src/server/scripts/Spells/spell_dk.cpp8
-rw-r--r--src/server/scripts/Spells/spell_generic.cpp2
-rw-r--r--src/server/scripts/Spells/spell_quest.cpp2
-rwxr-xr-xsrc/server/shared/Logging/Log.cpp12
-rwxr-xr-xsrc/server/shared/Logging/Log.h1
13 files changed, 212 insertions, 303 deletions
diff --git a/sql/updates/world/2011_09_26_00_world_spell_script_names.sql b/sql/updates/world/2011_09_26_00_world_spell_script_names.sql
new file mode 100644
index 00000000000..4896990bb5b
--- /dev/null
+++ b/sql/updates/world/2011_09_26_00_world_spell_script_names.sql
@@ -0,0 +1,4 @@
+DELETE FROM `spell_script_names` WHERE `spell_id` IN (62374,62475);
+INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES
+(62374,'spell_pursue'),
+(62475,'spell_systems_shutdown');
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( );