aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/game/AI/CoreAI/GameObjectAI.h23
-rwxr-xr-xsrc/server/game/AI/CoreAI/PetAI.cpp61
-rwxr-xr-xsrc/server/game/AI/CoreAI/PetAI.h2
-rwxr-xr-xsrc/server/game/AI/CoreAI/TotemAI.cpp14
-rwxr-xr-xsrc/server/game/AI/CoreAI/TotemAI.h8
-rwxr-xr-xsrc/server/game/AI/CoreAI/UnitAI.h2
-rwxr-xr-xsrc/server/game/AI/CreatureAI.h6
-rwxr-xr-xsrc/server/game/AI/CreatureAIImpl.h5
-rwxr-xr-xsrc/server/game/AI/CreatureAISelector.cpp7
-rwxr-xr-xsrc/server/game/AI/EventAI/CreatureEventAI.cpp2
-rw-r--r--src/server/game/AI/ScriptedAI/ScriptedCreature.cpp37
-rw-r--r--src/server/game/AI/ScriptedAI/ScriptedCreature.h29
-rw-r--r--src/server/game/AI/SmartScripts/SmartAI.cpp2
-rw-r--r--src/server/game/AI/SmartScripts/SmartAI.h2
-rw-r--r--src/server/game/AI/SmartScripts/SmartScript.cpp31
-rw-r--r--src/server/game/AI/SmartScripts/SmartScriptMgr.h17
-rwxr-xr-xsrc/server/game/Battlegrounds/Battleground.cpp47
-rwxr-xr-xsrc/server/game/Battlegrounds/Battleground.h4
-rwxr-xr-xsrc/server/game/Battlegrounds/BattlegroundMgr.cpp28
-rwxr-xr-xsrc/server/game/Battlegrounds/BattlegroundMgr.h1
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundDS.cpp5
-rwxr-xr-xsrc/server/game/Battlegrounds/Zones/BattlegroundDS.h8
-rwxr-xr-xsrc/server/game/Battlegrounds/Zones/BattlegroundIC.cpp1
-rwxr-xr-xsrc/server/game/Battlegrounds/Zones/BattlegroundSA.cpp10
-rwxr-xr-xsrc/server/game/Battlegrounds/Zones/BattlegroundSA.h89
-rwxr-xr-xsrc/server/game/Battlegrounds/Zones/BattlegroundWS.cpp16
-rw-r--r--src/server/game/CMakeLists.txt1
-rwxr-xr-xsrc/server/game/Chat/Channels/Channel.cpp1
-rwxr-xr-xsrc/server/game/Chat/Chat.cpp5
-rwxr-xr-xsrc/server/game/Chat/Chat.h1
-rwxr-xr-xsrc/server/game/Chat/Commands/Level3.cpp64
-rwxr-xr-xsrc/server/game/Combat/ThreatManager.cpp3
-rwxr-xr-xsrc/server/game/Conditions/ConditionMgr.cpp22
-rwxr-xr-xsrc/server/game/Conditions/ConditionMgr.h2
-rwxr-xr-xsrc/server/game/DataStores/DBCStructure.h1
-rwxr-xr-xsrc/server/game/DungeonFinding/LFGMgr.cpp2
-rwxr-xr-xsrc/server/game/Entities/Creature/Creature.cpp11
-rwxr-xr-xsrc/server/game/Entities/Creature/Creature.h3
-rwxr-xr-xsrc/server/game/Entities/Creature/GossipDef.cpp3
-rwxr-xr-xsrc/server/game/Entities/GameObject/GameObject.cpp9
-rwxr-xr-xsrc/server/game/Entities/Item/Item.cpp6
-rwxr-xr-xsrc/server/game/Entities/Object/Object.cpp10
-rwxr-xr-xsrc/server/game/Entities/Object/Object.h18
-rwxr-xr-xsrc/server/game/Entities/Pet/Pet.cpp9
-rwxr-xr-xsrc/server/game/Entities/Player/Player.cpp104
-rwxr-xr-xsrc/server/game/Entities/Player/Player.h4
-rwxr-xr-xsrc/server/game/Entities/Unit/StatSystem.cpp2
-rwxr-xr-xsrc/server/game/Entities/Unit/Unit.cpp184
-rwxr-xr-xsrc/server/game/Entities/Unit/Unit.h7
-rwxr-xr-xsrc/server/game/Entities/Vehicle/Vehicle.cpp7
-rwxr-xr-xsrc/server/game/Globals/ObjectMgr.h9
-rwxr-xr-xsrc/server/game/Grids/GridStates.h1
-rwxr-xr-xsrc/server/game/Grids/Notifiers/GridNotifiers.h4
-rwxr-xr-xsrc/server/game/Grids/Notifiers/GridNotifiersImpl.h25
-rwxr-xr-xsrc/server/game/Groups/Group.cpp2
-rwxr-xr-xsrc/server/game/Handlers/ItemHandler.cpp6
-rwxr-xr-xsrc/server/game/Handlers/LFGHandler.cpp4
-rwxr-xr-xsrc/server/game/Handlers/PetHandler.cpp2
-rwxr-xr-xsrc/server/game/Handlers/TicketHandler.cpp2
-rwxr-xr-xsrc/server/game/Instances/InstanceSaveMgr.cpp6
-rwxr-xr-xsrc/server/game/Loot/LootMgr.cpp2
-rwxr-xr-xsrc/server/game/Maps/Map.cpp8
-rwxr-xr-xsrc/server/game/Maps/Map.h2
-rwxr-xr-xsrc/server/game/Maps/MapManager.cpp16
-rwxr-xr-xsrc/server/game/Miscellaneous/Language.h6
-rwxr-xr-xsrc/server/game/Miscellaneous/SharedDefines.h56
-rwxr-xr-xsrc/server/game/Movement/MotionMaster.cpp9
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp60
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.h5
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp25
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/FleeingMovementGenerator.h6
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/HomeMovementGenerator.h3
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp2
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/PointMovementGenerator.h6
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp6
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/RandomMovementGenerator.h3
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp4
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h3
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h10
-rw-r--r--src/server/game/Movement/Spline/MoveSpline.cpp2
-rw-r--r--src/server/game/Movement/Spline/MovementPacketBuilder.cpp4
-rwxr-xr-xsrc/server/game/Pools/PoolMgr.cpp4
-rwxr-xr-xsrc/server/game/Reputation/ReputationMgr.h4
-rwxr-xr-xsrc/server/game/Scripting/ScriptLoader.cpp2
-rwxr-xr-xsrc/server/game/Scripting/ScriptMgr.cpp24
-rwxr-xr-xsrc/server/game/Scripting/ScriptMgr.h5
-rwxr-xr-xsrc/server/game/Server/Protocol/Opcodes.h2
-rwxr-xr-xsrc/server/game/Server/WorldSession.cpp4
-rwxr-xr-xsrc/server/game/Spells/Auras/SpellAuraEffects.cpp94
-rwxr-xr-xsrc/server/game/Spells/Auras/SpellAuras.cpp3
-rwxr-xr-xsrc/server/game/Spells/Spell.cpp103
-rwxr-xr-xsrc/server/game/Spells/Spell.h16
-rwxr-xr-xsrc/server/game/Spells/SpellEffects.cpp59
-rw-r--r--src/server/game/Spells/SpellInfo.cpp4
-rwxr-xr-xsrc/server/game/Spells/SpellMgr.cpp35
-rwxr-xr-xsrc/server/game/Spells/SpellScript.cpp4
-rwxr-xr-xsrc/server/game/Spells/SpellScript.h2
-rwxr-xr-xsrc/server/game/Tickets/TicketMgr.cpp5
-rw-r--r--src/server/game/Tools/PlayerDump.cpp22
-rw-r--r--src/server/game/Warden/Warden.cpp4
-rw-r--r--src/server/game/Warden/Warden.h2
-rw-r--r--src/server/game/Warden/WardenCheckMgr.cpp11
-rw-r--r--src/server/game/Warden/WardenCheckMgr.h2
-rw-r--r--src/server/game/Warden/WardenMac.cpp2
-rwxr-xr-xsrc/server/game/World/World.cpp2
-rw-r--r--src/server/scripts/CMakeLists.txt2
-rw-r--r--src/server/scripts/Commands/cs_modify.cpp2
-rw-r--r--src/server/scripts/Commands/cs_reload.cpp164
-rw-r--r--src/server/scripts/Commands/cs_tele.cpp4
-rw-r--r--src/server/scripts/EasternKingdoms/Karazhan/boss_midnight.cpp4
-rw-r--r--src/server/scripts/EasternKingdoms/MoltenCore/boss_sulfuron_harbinger.cpp2
-rw-r--r--src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp13
-rw-r--r--src/server/scripts/EasternKingdoms/ScarletMonastery/boss_high_inquisitor_fairbanks.cpp8
-rw-r--r--src/server/scripts/EasternKingdoms/eversong_woods.cpp4
-rw-r--r--src/server/scripts/EasternKingdoms/isle_of_queldanas.cpp4
-rw-r--r--src/server/scripts/EasternKingdoms/undercity.cpp95
-rw-r--r--src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal.cpp1
-rw-r--r--src/server/scripts/Kalimdor/CavernsOfTime/DarkPortal/instance_dark_portal.cpp4
-rw-r--r--src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_moam.cpp2
-rw-r--r--src/server/scripts/Kalimdor/silithus.cpp97
-rw-r--r--src/server/scripts/Northrend/CMakeLists.txt2
-rw-r--r--src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_saviana_ragefire.cpp2
-rwxr-xr-xsrc/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp6
-rwxr-xr-xsrc/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp31
-rwxr-xr-xsrc/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp2
-rw-r--r--src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_scourgelord_tyrannus.cpp6
-rw-r--r--src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.cpp5
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp65
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp8
-rwxr-xr-xsrc/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp2
-rwxr-xr-xsrc/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp2
-rwxr-xr-xsrc/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp192
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp2
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp156
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp12
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp4
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp20
-rw-r--r--src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp6
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon.cpp376
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp1374
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp4
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp2
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp8
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp271
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h226
-rw-r--r--src/server/scripts/Northrend/VaultOfArchavon/boss_emalon.cpp2
-rw-r--r--src/server/scripts/Outland/BlackTemple/boss_supremus.cpp3
-rw-r--r--src/server/scripts/Outland/boss_doomlord_kazzak.cpp37
-rw-r--r--src/server/scripts/Outland/netherstorm.cpp2
-rw-r--r--src/server/scripts/Spells/spell_druid.cpp2
-rw-r--r--src/server/scripts/Spells/spell_generic.cpp42
-rw-r--r--src/server/scripts/Spells/spell_item.cpp32
-rw-r--r--src/server/scripts/Spells/spell_mage.cpp6
-rw-r--r--src/server/scripts/Spells/spell_paladin.cpp11
-rw-r--r--src/server/scripts/Spells/spell_quest.cpp4
-rw-r--r--src/server/scripts/Spells/spell_shaman.cpp125
-rw-r--r--src/server/scripts/Spells/spell_warlock.cpp14
-rw-r--r--src/server/scripts/Spells/spell_warrior.cpp48
-rw-r--r--src/server/scripts/World/npcs_special.cpp203
-rw-r--r--src/server/shared/CMakeLists.txt1
-rw-r--r--src/server/shared/Containers.h71
-rwxr-xr-xsrc/server/shared/Database/DatabaseWorkerPool.h6
-rw-r--r--src/server/shared/Database/Implementation/CharacterDatabase.cpp6
-rw-r--r--src/server/shared/Debugging/WheatyExceptionReport.cpp18
-rwxr-xr-xsrc/server/shared/Dynamic/TypeContainerFunctionsPtr.h168
-rwxr-xr-xsrc/server/shared/Utilities/Util.h12
-rw-r--r--src/server/worldserver/CMakeLists.txt1
-rw-r--r--src/tools/map_extractor/System.cpp4
168 files changed, 3774 insertions, 1884 deletions
diff --git a/src/server/game/AI/CoreAI/GameObjectAI.h b/src/server/game/AI/CoreAI/GameObjectAI.h
index b9d385ba675..f4555649210 100644
--- a/src/server/game/AI/CoreAI/GameObjectAI.h
+++ b/src/server/game/AI/CoreAI/GameObjectAI.h
@@ -33,21 +33,24 @@ class GameObjectAI
explicit GameObjectAI(GameObject* g) : go(g) {}
virtual ~GameObjectAI() {}
- virtual void UpdateAI(const uint32 /*diff*/) {}
+ virtual void UpdateAI(uint32 /*diff*/) {}
virtual void InitializeAI() { Reset(); }
virtual void Reset() {};
- static int Permissible(const GameObject* go);
+ static int Permissible(GameObject const* go);
- virtual bool GossipHello(Player* /*player*/) {return false;}
- virtual bool GossipSelect(Player* /*player*/, uint32 /*sender*/, uint32 /*action*/) {return false;}
- virtual bool GossipSelectCode(Player* /*player*/, uint32 /*sender*/, uint32 /*action*/, const char* /*code*/) {return false;}
- virtual bool QuestAccept(Player* /*player*/, Quest const* /*quest*/) {return false;}
- virtual bool QuestReward(Player* /*player*/, Quest const* /*quest*/, uint32 /*opt*/) {return false;}
- virtual uint32 GetDialogStatus(Player* /*player*/) {return 100;}
+ virtual bool GossipHello(Player* /*player*/) { return false; }
+ virtual bool GossipSelect(Player* /*player*/, uint32 /*sender*/, uint32 /*action*/) { return false; }
+ virtual bool GossipSelectCode(Player* /*player*/, uint32 /*sender*/, uint32 /*action*/, char const* /*code*/) { return false; }
+ virtual bool QuestAccept(Player* /*player*/, Quest const* /*quest*/) { return false; }
+ virtual bool QuestReward(Player* /*player*/, Quest const* /*quest*/, uint32 /*opt*/) { return false; }
+ virtual uint32 GetDialogStatus(Player* /*player*/) { return 100; }
virtual void Destroyed(Player* /*player*/, uint32 /*eventId*/) {}
+ virtual uint32 GetData(uint32 /*id*/) { return 0; }
+ virtual void SetData64(uint32 /*id*/, uint64 /*value*/) {}
+ virtual uint64 GetData64(uint32 /*id*/) { return 0; }
virtual void SetData(uint32 /*id*/, uint32 /*value*/) {}
virtual void OnGameEvent(bool /*start*/, uint16 /*eventId*/) {}
virtual void OnStateChanged(uint32 /*state*/, Unit* /*unit*/) { }
@@ -58,8 +61,8 @@ class NullGameObjectAI : public GameObjectAI
public:
explicit NullGameObjectAI(GameObject* g);
- void UpdateAI(const uint32 /*diff*/) {}
+ void UpdateAI(uint32 /*diff*/) {}
- static int Permissible(const GameObject* /*go*/) { return PERMIT_BASE_IDLE; }
+ static int Permissible(GameObject const* /*go*/) { return PERMIT_BASE_IDLE; }
};
#endif
diff --git a/src/server/game/AI/CoreAI/PetAI.cpp b/src/server/game/AI/CoreAI/PetAI.cpp
index 295768f9d3e..bcec8d273b9 100755
--- a/src/server/game/AI/CoreAI/PetAI.cpp
+++ b/src/server/game/AI/CoreAI/PetAI.cpp
@@ -109,17 +109,25 @@ void PetAI::UpdateAI(const uint32 diff)
}
else if (owner && me->GetCharmInfo()) //no victim
{
- Unit* nextTarget = SelectNextTarget();
+ // Only aggressive pets do target search every update.
+ // Defensive pets do target search only in these cases:
+ // * Owner attacks something - handled by OwnerAttacked()
+ // * Owner receives damage - handled by OwnerDamagedBy()
+ // * Pet is in combat and current target dies - handled by KilledUnit()
+ if (me->HasReactState(REACT_AGGRESSIVE))
+ {
+ Unit* nextTarget = SelectNextTarget();
- if (me->HasReactState(REACT_PASSIVE))
- _stopAttack();
- else if (nextTarget)
- AttackStart(nextTarget);
+ if (nextTarget)
+ AttackStart(nextTarget);
+ else
+ HandleReturnMovement();
+ }
else
HandleReturnMovement();
}
else if (owner && !me->HasUnitState(UNIT_STATE_FOLLOW)) // no charm info and no victim
- me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, me->GetFollowAngle());
+ HandleReturnMovement();
if (!me->GetCharmInfo())
return;
@@ -302,6 +310,47 @@ void PetAI::AttackStart(Unit* target)
DoAttack(target, true);
}
+void PetAI::OwnerDamagedBy(Unit* attacker)
+{
+ // Called when owner takes damage. Allows defensive pets to know
+ // that their owner might need help
+
+ if (!attacker)
+ return;
+
+ // Passive pets don't do anything
+ if (me->HasReactState(REACT_PASSIVE))
+ return;
+
+ // Prevent pet from disengaging from current target
+ if (me->getVictim() && me->getVictim()->isAlive())
+ return;
+
+ // Continue to evaluate and attack if necessary
+ AttackStart(attacker);
+}
+
+void PetAI::OwnerAttacked(Unit* target)
+{
+ // Called when owner attacks something. Allows defensive pets to know
+ // that they need to assist
+
+ // Target might be NULL if called from spell with invalid cast targets
+ if (!target)
+ return;
+
+ // Passive pets don't do anything
+ if (me->HasReactState(REACT_PASSIVE))
+ return;
+
+ // Prevent pet from disengaging from current target
+ if (me->getVictim() && me->getVictim()->isAlive())
+ return;
+
+ // Continue to evaluate and attack if necessary
+ AttackStart(target);
+}
+
Unit* PetAI::SelectNextTarget()
{
// Provides next target selection after current target death
diff --git a/src/server/game/AI/CoreAI/PetAI.h b/src/server/game/AI/CoreAI/PetAI.h
index 730ab12a3ca..ed3e2305556 100755
--- a/src/server/game/AI/CoreAI/PetAI.h
+++ b/src/server/game/AI/CoreAI/PetAI.h
@@ -40,6 +40,8 @@ class PetAI : public CreatureAI
void KilledUnit(Unit* /*victim*/);
void AttackStart(Unit* target);
void MovementInform(uint32 moveType, uint32 data);
+ void OwnerDamagedBy(Unit* attacker);
+ void OwnerAttacked(Unit* target);
private:
bool _isVisible(Unit*) const;
diff --git a/src/server/game/AI/CoreAI/TotemAI.cpp b/src/server/game/AI/CoreAI/TotemAI.cpp
index 0739b62b605..d12d3c098e8 100755
--- a/src/server/game/AI/CoreAI/TotemAI.cpp
+++ b/src/server/game/AI/CoreAI/TotemAI.cpp
@@ -27,8 +27,7 @@
#include "GridNotifiersImpl.h"
#include "CellImpl.h"
-int
-TotemAI::Permissible(const Creature* creature)
+int TotemAI::Permissible(Creature const* creature)
{
if (creature->isTotem())
return PERMIT_BASE_PROACTIVE;
@@ -41,8 +40,7 @@ TotemAI::TotemAI(Creature* c) : CreatureAI(c), i_victimGuid(0)
ASSERT(c->isTotem());
}
-void
-TotemAI::MoveInLineOfSight(Unit*)
+void TotemAI::MoveInLineOfSight(Unit* /*who*/)
{
}
@@ -51,10 +49,9 @@ void TotemAI::EnterEvadeMode()
me->CombatStop(true);
}
-void
-TotemAI::UpdateAI(const uint32 /*diff*/)
+void TotemAI::UpdateAI(uint32 const /*diff*/)
{
- if (me->ToTotem()->GetTotemType() != TOTEM_ACTIVE)
+ if (me->ToTotem()->GetTotemType() != TOTEM_ACTIVE)
return;
if (!me->isAlive() || me->IsNonMeleeSpellCasted(false))
@@ -98,8 +95,7 @@ TotemAI::UpdateAI(const uint32 /*diff*/)
i_victimGuid = 0;
}
-void
-TotemAI::AttackStart(Unit*)
+void TotemAI::AttackStart(Unit* /*victim*/)
{
// Sentry totem sends ping on attack
if (me->GetEntry() == SENTRY_TOTEM_ENTRY && me->GetOwner()->GetTypeId() == TYPEID_PLAYER)
diff --git a/src/server/game/AI/CoreAI/TotemAI.h b/src/server/game/AI/CoreAI/TotemAI.h
index 0fa2920888f..f0d705345ef 100755
--- a/src/server/game/AI/CoreAI/TotemAI.h
+++ b/src/server/game/AI/CoreAI/TotemAI.h
@@ -31,12 +31,12 @@ class TotemAI : public CreatureAI
explicit TotemAI(Creature* c);
- void MoveInLineOfSight(Unit*);
- void AttackStart(Unit*);
+ void MoveInLineOfSight(Unit* who);
+ void AttackStart(Unit* victim);
void EnterEvadeMode();
- void UpdateAI(const uint32);
- static int Permissible(const Creature*);
+ void UpdateAI(uint32 const diff);
+ static int Permissible(Creature const* creature);
private:
uint64 i_victimGuid;
diff --git a/src/server/game/AI/CoreAI/UnitAI.h b/src/server/game/AI/CoreAI/UnitAI.h
index b871a25835b..593f0d15e18 100755
--- a/src/server/game/AI/CoreAI/UnitAI.h
+++ b/src/server/game/AI/CoreAI/UnitAI.h
@@ -223,7 +223,7 @@ class UnitAI
targetList.reverse();
if (targetType == SELECT_TARGET_RANDOM)
- Trinity::RandomResizeList(targetList, maxTargets);
+ Trinity::Containers::RandomResizeList(targetList, maxTargets);
else
targetList.resize(maxTargets);
}
diff --git a/src/server/game/AI/CreatureAI.h b/src/server/game/AI/CreatureAI.h
index 423b00291e7..94ac452b9f3 100755
--- a/src/server/game/AI/CreatureAI.h
+++ b/src/server/game/AI/CreatureAI.h
@@ -138,6 +138,12 @@ class CreatureAI : public UnitAI
// Called at text emote receive from player
virtual void ReceiveEmote(Player* /*player*/, uint32 /*emoteId*/) {}
+ // Called when owner takes damage
+ virtual void OwnerDamagedBy(Unit* /*attacker*/) {}
+
+ // Called when owner attacks something
+ virtual void OwnerAttacked(Unit* /*target*/) {}
+
/// == Triggered Actions Requested ==================
// Called when creature attack expected (if creature can and no have current victim)
diff --git a/src/server/game/AI/CreatureAIImpl.h b/src/server/game/AI/CreatureAIImpl.h
index f568da80b49..d097adf38ec 100755
--- a/src/server/game/AI/CreatureAIImpl.h
+++ b/src/server/game/AI/CreatureAIImpl.h
@@ -326,11 +326,15 @@ class EventMap : private std::map<uint32, uint32>
uint32 GetPhaseMask() const { return (_phase >> 24) & 0xFF; }
+ bool Empty() const { return empty(); }
+
// Sets event phase, must be in range 1 - 8
void SetPhase(uint32 phase)
{
if (phase && phase < 8)
_phase = (1 << (phase + 24));
+ else if (!phase)
+ _phase = 0;
}
// Creates new event entry in map with given id, time, group if given (1 - 8) and phase if given (1 - 8)
@@ -604,6 +608,7 @@ inline void UnitAI::DoCast(Unit* victim, uint32 spellId, bool triggered)
inline void UnitAI::DoCastVictim(uint32 spellId, bool triggered)
{
+ // Why don't we check for casting unit_state and existing target as we do in DoCast(.. ?
me->CastSpell(me->getVictim(), spellId, triggered);
}
diff --git a/src/server/game/AI/CreatureAISelector.cpp b/src/server/game/AI/CreatureAISelector.cpp
index f64bb320542..1a0c6652e74 100755
--- a/src/server/game/AI/CreatureAISelector.cpp
+++ b/src/server/game/AI/CreatureAISelector.cpp
@@ -82,7 +82,7 @@ namespace FactorySelector
{
const CreatureAICreator* factory = iter->second;
const SelectableAI* p = dynamic_cast<const SelectableAI*>(factory);
- ASSERT(p != NULL);
+ ASSERT(p);
int val = p->Permit(creature);
if (val > best_val)
{
@@ -102,7 +102,7 @@ namespace FactorySelector
MovementGenerator* selectMovementGenerator(Creature* creature)
{
MovementGeneratorRegistry& mv_registry(*MovementGeneratorRepository::instance());
- ASSERT(creature->GetCreatureTemplate() != NULL);
+ ASSERT(creature->GetCreatureTemplate());
const MovementGeneratorCreator* mv_factory = mv_registry.GetRegistryItem(creature->GetDefaultMovementType());
/* if (mv_factory == NULL)
@@ -133,6 +133,9 @@ namespace FactorySelector
const GameObjectAICreator* ai_factory = NULL;
GameObjectAIRegistry& ai_registry(*GameObjectAIRepository::instance());
+ if (GameObjectAI* scriptedAI = sScriptMgr->GetGameObjectAI(go))
+ return scriptedAI;
+
ai_factory = ai_registry.GetRegistryItem(go->GetAIName());
//future goAI types go here
diff --git a/src/server/game/AI/EventAI/CreatureEventAI.cpp b/src/server/game/AI/EventAI/CreatureEventAI.cpp
index 7a2b83273c9..835705a0d7c 100755
--- a/src/server/game/AI/EventAI/CreatureEventAI.cpp
+++ b/src/server/game/AI/EventAI/CreatureEventAI.cpp
@@ -1107,7 +1107,7 @@ void CreatureEventAI::UpdateAI(const uint32 diff)
break;
case EVENT_T_RANGE:
if (me->getVictim())
- if (me->IsInMap(me->getVictim()))
+ if (me->IsInMap(me->getVictim()) && me->InSamePhase(me->getVictim()))
if (me->IsInRange(me->getVictim(), (float)(*i).Event.range.minDist, (float)(*i).Event.range.maxDist))
ProcessEvent(*i);
break;
diff --git a/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp b/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp
index d80c71bfb35..6d27d251579 100644
--- a/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp
+++ b/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp
@@ -30,18 +30,6 @@ void SummonList::DoZoneInCombat(uint32 entry)
}
}
-void SummonList::DoAction(uint32 entry, int32 info)
-{
- for (iterator i = begin(); i != end();)
- {
- Creature* summon = Unit::GetCreature(*me, *i);
- ++i;
- if (summon && summon->IsAIEnabled
- && (!entry || summon->GetEntry() == entry))
- summon->AI()->DoAction(info);
- }
-}
-
void SummonList::DespawnEntry(uint32 entry)
{
for (iterator i = begin(); i != end();)
@@ -126,15 +114,7 @@ void ScriptedAI::UpdateAI(uint32 const /*diff*/)
if (!UpdateVictim())
return;
- if (me->isAttackReady())
- {
- //If we are within range melee the target
- if (me->IsWithinMeleeRange(me->getVictim()))
- {
- me->AttackerStateUpdate(me->getVictim());
- me->resetAttackTimer();
- }
- }
+ DoMeleeAttackIfReady();
}
void ScriptedAI::DoStartMovement(Unit* victim, float distance, float angle)
@@ -189,11 +169,11 @@ SpellInfo const* ScriptedAI::SelectSpell(Unit* target, uint32 school, uint32 mec
{
//No target so we can't cast
if (!target)
- return false;
+ return NULL;
//Silenced so we can't cast
if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED))
- return false;
+ return NULL;
//Using the extended script system we first create a list of viable spells
SpellInfo const* apSpell[CREATURE_MAX_SPELLS];
@@ -309,14 +289,13 @@ void ScriptedAI::DoTeleportTo(const float position[4])
void ScriptedAI::DoTeleportPlayer(Unit* unit, float x, float y, float z, float o)
{
- if (!unit || unit->GetTypeId() != TYPEID_PLAYER)
- {
- if (unit)
- sLog->outError("TSCR: Creature " UI64FMTD " (Entry: %u) Tried to teleport non-player unit (Type: %u GUID: " UI64FMTD ") to x: %f y:%f z: %f o: %f. Aborted.", me->GetGUID(), me->GetEntry(), unit->GetTypeId(), unit->GetGUID(), x, y, z, o);
+ if (!unit)
return;
- }
- CAST_PLR(unit)->TeleportTo(unit->GetMapId(), x, y, z, o, TELE_TO_NOT_LEAVE_COMBAT);
+ if (Player* player = unit->ToPlayer())
+ player->TeleportTo(unit->GetMapId(), x, y, z, o, TELE_TO_NOT_LEAVE_COMBAT);
+ else
+ sLog->outError("TSCR: Creature " UI64FMTD " (Entry: %u) Tried to teleport non-player unit (Type: %u GUID: " UI64FMTD ") to x: %f y:%f z: %f o: %f. Aborted.", me->GetGUID(), me->GetEntry(), unit->GetTypeId(), unit->GetGUID(), x, y, z, o);
}
void ScriptedAI::DoTeleportAll(float x, float y, float z, float o)
diff --git a/src/server/game/AI/ScriptedAI/ScriptedCreature.h b/src/server/game/AI/ScriptedAI/ScriptedCreature.h
index a01c993cab6..4fac8b3cba5 100644
--- a/src/server/game/AI/ScriptedAI/ScriptedCreature.h
+++ b/src/server/game/AI/ScriptedAI/ScriptedCreature.h
@@ -38,7 +38,18 @@ class SummonList : public std::list<uint64>
void Despawn(Creature* summon) { remove(summon->GetGUID()); }
void DespawnEntry(uint32 entry);
void DespawnAll();
- void DoAction(uint32 entry, int32 info);
+
+ template <class Predicate> void DoAction(int32 info, Predicate& predicate, uint16 max = 0)
+ {
+ Trinity::Containers::RandomResizeList<uint64, Predicate>(*this, predicate, max);
+ for (iterator i = begin(); i != end(); )
+ {
+ Creature* summon = Unit::GetCreature(*me, *i++);
+ if (summon && summon->IsAIEnabled)
+ summon->AI()->DoAction(info);
+ }
+ }
+
void DoZoneInCombat(uint32 entry = 0);
void RemoveNotExisting();
bool HasEntry(uint32 entry);
@@ -46,6 +57,22 @@ class SummonList : public std::list<uint64>
Creature* me;
};
+class EntryCheckPredicate
+{
+ public:
+ EntryCheckPredicate(uint32 entry) : _entry(entry) {}
+ bool operator()(uint64 guid) { return GUID_ENPART(guid) == _entry; }
+
+ private:
+ uint32 _entry;
+};
+
+class DummyEntryCheckPredicate
+{
+ public:
+ bool operator()(uint64) { return true; }
+};
+
struct ScriptedAI : public CreatureAI
{
explicit ScriptedAI(Creature* creature);
diff --git a/src/server/game/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp
index 4eb7f8a7f50..2a412bffb22 100644
--- a/src/server/game/AI/SmartScripts/SmartAI.cpp
+++ b/src/server/game/AI/SmartScripts/SmartAI.cpp
@@ -854,7 +854,7 @@ int SmartGameObjectAI::Permissible(const GameObject* g)
return PERMIT_BASE_NO;
}
-void SmartGameObjectAI::UpdateAI(const uint32 diff)
+void SmartGameObjectAI::UpdateAI(uint32 diff)
{
GetScript()->OnUpdate(diff);
}
diff --git a/src/server/game/AI/SmartScripts/SmartAI.h b/src/server/game/AI/SmartScripts/SmartAI.h
index 94e5e65cf8b..bfd1c7b9d41 100644
--- a/src/server/game/AI/SmartScripts/SmartAI.h
+++ b/src/server/game/AI/SmartScripts/SmartAI.h
@@ -239,7 +239,7 @@ public:
SmartGameObjectAI(GameObject* g) : GameObjectAI(g), go(g) {}
~SmartGameObjectAI() {}
- void UpdateAI(const uint32 diff);
+ void UpdateAI(uint32 diff);
void InitializeAI();
void Reset();
SmartScript* GetScript() { return &mScript; }
diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp
index b2c4fd29868..893c8f4580e 100644
--- a/src/server/game/AI/SmartScripts/SmartScript.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScript.cpp
@@ -108,8 +108,11 @@ void SmartScript::OnReset()
ResetBaseObject();
for (SmartAIEventList::iterator i = mEvents.begin(); i != mEvents.end(); ++i)
{
- InitTimer((*i));
- (*i).runOnce = false;
+ if (!((*i).event.event_flags & SMART_EVENT_FLAG_DONT_RESET))
+ {
+ InitTimer((*i));
+ (*i).runOnce = false;
+ }
}
ProcessEventsFor(SMART_EVENT_RESET);
mLastInvoker = 0;
@@ -1116,12 +1119,13 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
{
for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
{
- if (!IsUnit(*itr))
- continue;
-
(*itr)->GetPosition(x, y, z, o);
+ x += e.target.x;
+ y += e.target.y;
+ z += e.target.z;
+ o += e.target.o;
if (Creature* summon = GetBaseObject()->SummonCreature(e.action.summonCreature.creature, x, y, z, o, (TempSummonType)e.action.summonCreature.type, e.action.summonCreature.duration))
- if (unit && e.action.summonCreature.attackInvoker)
+ if (e.action.summonCreature.attackInvoker)
summon->AI()->AttackStart((*itr)->ToUnit());
}
@@ -1151,6 +1155,10 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
continue;
(*itr)->GetPosition(x, y, z, o);
+ x += e.target.x;
+ y += e.target.y;
+ z += e.target.z;
+ o += e.target.o;
GetBaseObject()->SummonGameObject(e.action.summonGO.entry, x, y, z, o, 0, 0, 0, 0, e.action.summonGO.despawnTime);
}
@@ -1862,19 +1870,26 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
if (!targets)
break;
+ ObjectList* storedTargets = GetTargetList(e.action.sendTargetToTarget.id);
+ if (!storedTargets)
+ {
+ delete targets;
+ return;
+ }
+
for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
{
if (IsCreature(*itr))
{
if (SmartAI* ai = CAST_AI(SmartAI, (*itr)->ToCreature()->AI()))
- ai->GetScript()->StoreTargetList(GetTargetList(e.action.sendTargetToTarget.id), e.action.sendTargetToTarget.id);
+ ai->GetScript()->StoreTargetList(new ObjectList(*storedTargets), e.action.sendTargetToTarget.id); // store a copy of target list
else
sLog->outErrorDb("SmartScript: Action target for SMART_ACTION_SEND_TARGET_TO_TARGET is not using SmartAI, skipping");
}
else if (IsGameObject(*itr))
{
if (SmartGameObjectAI* ai = CAST_AI(SmartGameObjectAI, (*itr)->ToGameObject()->AI()))
- ai->GetScript()->StoreTargetList(GetTargetList(e.action.sendTargetToTarget.id), e.action.sendTargetToTarget.id);
+ ai->GetScript()->StoreTargetList(new ObjectList(*storedTargets), e.action.sendTargetToTarget.id); // store a copy of target list
else
sLog->outErrorDb("SmartScript: Action target for SMART_ACTION_SEND_TARGET_TO_TARGET is not using SmartGameObjectAI, skipping");
}
diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h
index e2cd75ee62c..8d3686a265d 100644
--- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h
+++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h
@@ -1165,14 +1165,15 @@ const uint32 SmartAIEventMask[SMART_EVENT_END][2] =
enum SmartEventFlags
{
- SMART_EVENT_FLAG_NOT_REPEATABLE = 0x01, //Event can not repeat
- SMART_EVENT_FLAG_DIFFICULTY_0 = 0x02, //Event only occurs in instance difficulty 0
- SMART_EVENT_FLAG_DIFFICULTY_1 = 0x04, //Event only occurs in instance difficulty 1
- SMART_EVENT_FLAG_DIFFICULTY_2 = 0x08, //Event only occurs in instance difficulty 2
- SMART_EVENT_FLAG_DIFFICULTY_3 = 0x10, //Event only occurs in instance difficulty 3
- SMART_EVENT_FLAG_RESERVED_5 = 0x20,
- SMART_EVENT_FLAG_RESERVED_6 = 0x40,
- SMART_EVENT_FLAG_DEBUG_ONLY = 0x80, //Event only occurs in debug build
+ SMART_EVENT_FLAG_NOT_REPEATABLE = 0x001, //Event can not repeat
+ SMART_EVENT_FLAG_DIFFICULTY_0 = 0x002, //Event only occurs in instance difficulty 0
+ SMART_EVENT_FLAG_DIFFICULTY_1 = 0x004, //Event only occurs in instance difficulty 1
+ SMART_EVENT_FLAG_DIFFICULTY_2 = 0x008, //Event only occurs in instance difficulty 2
+ SMART_EVENT_FLAG_DIFFICULTY_3 = 0x010, //Event only occurs in instance difficulty 3
+ SMART_EVENT_FLAG_RESERVED_5 = 0x020,
+ SMART_EVENT_FLAG_RESERVED_6 = 0x040,
+ SMART_EVENT_FLAG_DEBUG_ONLY = 0x080, //Event only occurs in debug build
+ SMART_EVENT_FLAG_DONT_RESET = 0x100, //Event will not reset in SmartScript::OnReset()
SMART_EVENT_FLAG_DIFFICULTY_ALL = (SMART_EVENT_FLAG_DIFFICULTY_0|SMART_EVENT_FLAG_DIFFICULTY_1|SMART_EVENT_FLAG_DIFFICULTY_2|SMART_EVENT_FLAG_DIFFICULTY_3)
};
diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp
index f3c393eaa36..44192a74123 100755
--- a/src/server/game/Battlegrounds/Battleground.cpp
+++ b/src/server/game/Battlegrounds/Battleground.cpp
@@ -144,6 +144,7 @@ Battleground::Battleground()
m_Winner = 2;
m_StartTime = 0;
m_ResetStatTimer = 0;
+ m_ValidStartPositionTimer = 0;
m_Events = 0;
m_IsRated = false;
m_BuffChange = false;
@@ -177,6 +178,8 @@ Battleground::Battleground()
m_ArenaTeamIds[BG_TEAM_ALLIANCE] = 0;
m_ArenaTeamIds[BG_TEAM_HORDE] = 0;
+ m_StartMaxDist = 0.0f;
+
m_ArenaTeamRatingChanges[BG_TEAM_ALLIANCE] = 0;
m_ArenaTeamRatingChanges[BG_TEAM_HORDE] = 0;
@@ -291,6 +294,7 @@ void Battleground::Update(uint32 diff)
// Update start time and reset stats timer
m_StartTime += diff;
m_ResetStatTimer += diff;
+ m_ValidStartPositionTimer += diff;
PostUpdateImpl(diff);
}
@@ -422,7 +426,7 @@ inline void Battleground::_ProcessJoin(uint32 diff)
// *********************************************************
ModifyStartDelayTime(diff);
- if (m_ResetStatTimer <= 5000)
+ if (m_ResetStatTimer > 5000)
{
m_ResetStatTimer = 0;
for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
@@ -453,19 +457,19 @@ inline void Battleground::_ProcessJoin(uint32 diff)
// First start warning - 2 or 1 minute
SendMessageToAll(StartMessageIds[BG_STARTING_EVENT_FIRST], CHAT_MSG_BG_SYSTEM_NEUTRAL);
}
- // After 1 minute or 30 seconds, warning is signalled
+ // After 1 minute or 30 seconds, warning is signaled
else if (GetStartDelayTime() <= StartDelayTimes[BG_STARTING_EVENT_SECOND] && !(m_Events & BG_STARTING_EVENT_2))
{
m_Events |= BG_STARTING_EVENT_2;
SendMessageToAll(StartMessageIds[BG_STARTING_EVENT_SECOND], CHAT_MSG_BG_SYSTEM_NEUTRAL);
}
- // After 30 or 15 seconds, warning is signalled
+ // After 30 or 15 seconds, warning is signaled
else if (GetStartDelayTime() <= StartDelayTimes[BG_STARTING_EVENT_THIRD] && !(m_Events & BG_STARTING_EVENT_3))
{
m_Events |= BG_STARTING_EVENT_3;
SendMessageToAll(StartMessageIds[BG_STARTING_EVENT_THIRD], CHAT_MSG_BG_SYSTEM_NEUTRAL);
}
- // Delay expired (atfer 2 or 1 minute)
+ // Delay expired (after 2 or 1 minute)
else if (GetStartDelayTime() <= 0 && !(m_Events & BG_STARTING_EVENT_4))
{
m_Events |= BG_STARTING_EVENT_4;
@@ -526,6 +530,33 @@ inline void Battleground::_ProcessJoin(uint32 diff)
sWorld->SendWorldText(LANG_BG_STARTED_ANNOUNCE_WORLD, GetName(), GetMinLevel(), GetMaxLevel());
}
}
+
+ // Find if the player left our start zone; if so, teleport it back
+ if (m_ValidStartPositionTimer > 1000)
+ {
+ m_ValidStartPositionTimer = 0;
+ float maxDist = GetStartMaxDist();
+ if (maxDist > 0.0f)
+ {
+ for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
+ {
+ if (Player *plr = ObjectAccessor::FindPlayer(itr->first))
+ {
+ float x, y, z, o;
+ uint32 team = plr->GetBGTeam();
+ GetTeamStartLoc(team, x, y, z, o);
+
+ float dist = plr->GetDistance(x, y, z);
+
+ if (dist >= maxDist)
+ {
+ sLog->outError("BATTLEGROUND: Sending %s back to start location (possible exploit)", plr->GetName());
+ plr->TeleportTo(GetMapId(), x, y, z, o);
+ }
+ }
+ }
+ }
+ }
}
inline void Battleground::_ProcessLeave(uint32 diff)
@@ -1459,9 +1490,8 @@ void Battleground::DoorClose(uint32 type)
// If doors are open, close it
if (obj->getLootState() == GO_ACTIVATED && obj->GetGoState() != GO_STATE_READY)
{
- // Change state to allow door to be closed
obj->SetLootState(GO_READY);
- obj->UseDoorOrButton(RESPAWN_ONE_DAY);
+ obj->SetGoState(GO_STATE_READY);
}
}
else
@@ -1473,9 +1503,8 @@ void Battleground::DoorOpen(uint32 type)
{
if (GameObject* obj = GetBgMap()->GetGameObject(BgObjects[type]))
{
- // Change state to be sure they will be opened
- obj->SetLootState(GO_READY);
- obj->UseDoorOrButton(RESPAWN_ONE_DAY);
+ obj->SetLootState(GO_ACTIVATED);
+ obj->SetGoState(GO_STATE_ACTIVE);
}
else
sLog->outError("Battleground::DoorOpen: door gameobject (type: %u, GUID: %u) not found for BG (map: %u, instance id: %u)!",
diff --git a/src/server/game/Battlegrounds/Battleground.h b/src/server/game/Battlegrounds/Battleground.h
index 32f6ebc92de..01dfbb23033 100755
--- a/src/server/game/Battlegrounds/Battleground.h
+++ b/src/server/game/Battlegrounds/Battleground.h
@@ -443,6 +443,8 @@ class Battleground
Z = m_TeamStartLocZ[idx];
O = m_TeamStartLocO[idx];
}
+ void SetStartMaxDist(float startMaxDist) { m_StartMaxDist = startMaxDist; }
+ float GetStartMaxDist() const { return m_StartMaxDist; }
// Packet Transfer
// method that should fill worldpacket with actual world states (not yet implemented for all battlegrounds!)
@@ -617,6 +619,7 @@ class Battleground
uint32 m_ClientInstanceID; // the instance-id which is sent to the client and without any other internal use
uint32 m_StartTime;
uint32 m_ResetStatTimer;
+ uint32 m_ValidStartPositionTimer;
int32 m_EndTime; // it is set to 120000 when bg is ending and it decreases itself
uint32 m_LastResurrectTime;
BattlegroundBracketId m_BracketId;
@@ -698,6 +701,7 @@ class Battleground
float m_TeamStartLocY[BG_TEAMS_COUNT];
float m_TeamStartLocZ[BG_TEAMS_COUNT];
float m_TeamStartLocO[BG_TEAMS_COUNT];
+ float m_StartMaxDist;
uint32 ScriptId;
};
#endif
diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.cpp b/src/server/game/Battlegrounds/BattlegroundMgr.cpp
index e1b99cbdcb9..a106f11ae82 100755
--- a/src/server/game/Battlegrounds/BattlegroundMgr.cpp
+++ b/src/server/game/Battlegrounds/BattlegroundMgr.cpp
@@ -660,6 +660,7 @@ uint32 BattlegroundMgr::CreateBattleground(CreateBattlegroundData& data)
bg->SetName(data.BattlegroundName);
bg->SetTeamStartLoc(ALLIANCE, data.Team1StartLocX, data.Team1StartLocY, data.Team1StartLocZ, data.Team1StartLocO);
bg->SetTeamStartLoc(HORDE, data.Team2StartLocX, data.Team2StartLocY, data.Team2StartLocZ, data.Team2StartLocO);
+ bg->SetStartMaxDist(data.StartMaxDist);
bg->SetLevelRange(data.LevelMin, data.LevelMax);
bg->SetScriptId(data.scriptId);
@@ -677,8 +678,8 @@ void BattlegroundMgr::CreateInitialBattlegrounds()
uint8 selectionWeight;
BattlemasterListEntry const* bl;
- // 0 1 2 3 4 5 6 7 8 9 10
- QueryResult result = WorldDatabase.Query("SELECT id, MinPlayersPerTeam, MaxPlayersPerTeam, MinLvl, MaxLvl, AllianceStartLoc, AllianceStartO, HordeStartLoc, HordeStartO, Weight, ScriptName FROM battleground_template");
+ // 0 1 2 3 4 5 6 7 8 9 10 11
+ QueryResult result = WorldDatabase.Query("SELECT id, MinPlayersPerTeam, MaxPlayersPerTeam, MinLvl, MaxLvl, AllianceStartLoc, AllianceStartO, HordeStartLoc, HordeStartO, StartMaxDist, Weight, ScriptName FROM battleground_template");
if (!result)
{
@@ -712,17 +713,20 @@ void BattlegroundMgr::CreateInitialBattlegrounds()
data.MaxPlayersPerTeam = fields[2].GetUInt16();
data.LevelMin = fields[3].GetUInt8();
data.LevelMax = fields[4].GetUInt8();
- //check values from DB
- if (data.MaxPlayersPerTeam == 0 || data.MinPlayersPerTeam == 0 || data.MinPlayersPerTeam > data.MaxPlayersPerTeam)
+
+ // check values from DB
+ if (data.MaxPlayersPerTeam == 0 || data.MinPlayersPerTeam > data.MaxPlayersPerTeam)
{
- data.MinPlayersPerTeam = 0; // by default now expected strong full bg requirement
- data.MaxPlayersPerTeam = 40;
+ sLog->outErrorDb("Table `battleground_template` for id %u has bad values for MinPlayersPerTeam (%u) and MaxPlayersPerTeam(%u)",
+ data.bgTypeId, data.MinPlayersPerTeam, data.MaxPlayersPerTeam);
+ continue;
}
+
if (data.LevelMin == 0 || data.LevelMax == 0 || data.LevelMin > data.LevelMax)
{
- //TO-DO: FIX ME
- data.LevelMin = 0;//bl->minlvl;
- data.LevelMax = 80;//bl->maxlvl;
+ sLog->outErrorDb("Table `battleground_template` for id %u has bad values for LevelMin (%u) and LevelMax(%u)",
+ data.bgTypeId, data.LevelMin, data.LevelMax);
+ continue;
}
startId = fields[5].GetUInt32();
@@ -767,8 +771,10 @@ void BattlegroundMgr::CreateInitialBattlegrounds()
continue;
}
- selectionWeight = fields[9].GetUInt8();
- data.scriptId = sObjectMgr->GetScriptId(fields[10].GetCString());
+ data.StartMaxDist = fields[9].GetFloat();
+
+ selectionWeight = fields[10].GetUInt8();
+ data.scriptId = sObjectMgr->GetScriptId(fields[11].GetCString());
data.BattlegroundName = bl->name[sWorld->GetDefaultDbcLocale()];
data.MapID = bl->mapid[0];
diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.h b/src/server/game/Battlegrounds/BattlegroundMgr.h
index 88559d07993..7afb83da0a6 100755
--- a/src/server/game/Battlegrounds/BattlegroundMgr.h
+++ b/src/server/game/Battlegrounds/BattlegroundMgr.h
@@ -50,6 +50,7 @@ struct CreateBattlegroundData
float Team2StartLocY;
float Team2StartLocZ;
float Team2StartLocO;
+ float StartMaxDist;
uint32 scriptId;
};
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundDS.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundDS.cpp
index 8a11edf85e6..ccc6a2305b4 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundDS.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundDS.cpp
@@ -86,11 +86,8 @@ void BattlegroundDS::PostUpdateImpl(uint32 diff)
setWaterFallTimer(BG_DS_WATERFALL_WARNING_DURATION);
setWaterFallStatus(BG_DS_WATERFALL_STATUS_WARNING);
}
- else if (getWaterFallStatus() == BG_DS_WATERFALL_STATUS_WARNING) // Active collision and perform knockback
+ else if (getWaterFallStatus() == BG_DS_WATERFALL_STATUS_WARNING) // Active collision and start knockback timer
{
- if (Creature* waterSpout = GetBgMap()->GetCreature(BgCreatures[BG_DS_NPC_WATERFALL_KNOCKBACK]))
- waterSpout->CastSpell(waterSpout, BG_DS_SPELL_WATER_SPOUT, true);
-
if (GameObject* gob = GetBgMap()->GetGameObject(BgObjects[BG_DS_OBJECT_WATER_1]))
gob->SetGoState(GO_STATE_READY);
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundDS.h b/src/server/game/Battlegrounds/Zones/BattlegroundDS.h
index 12ed91fc922..aaf08ba1313 100755
--- a/src/server/game/Battlegrounds/Zones/BattlegroundDS.h
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundDS.h
@@ -66,9 +66,9 @@ enum BattlegroundDSData
{ // These values are NOT blizzlike... need the correct data!
BG_DS_WATERFALL_TIMER_MIN = 30000,
BG_DS_WATERFALL_TIMER_MAX = 60000,
- BG_DS_WATERFALL_WARNING_DURATION = 7000,
- BG_DS_WATERFALL_DURATION = 10000,
- BG_DS_WATERFALL_KNOCKBACK_TIMER = 500,
+ BG_DS_WATERFALL_WARNING_DURATION = 5000,
+ BG_DS_WATERFALL_DURATION = 30000,
+ BG_DS_WATERFALL_KNOCKBACK_TIMER = 1500,
BG_DS_PIPE_KNOCKBACK_FIRST_DELAY = 5000,
BG_DS_PIPE_KNOCKBACK_DELAY = 3000,
@@ -118,7 +118,7 @@ class BattlegroundDS : public Battleground
void setWaterFallStatus(uint8 status) { _waterfallStatus = status; };
uint32 getWaterFallTimer() { return _waterfallTimer; };
void setWaterFallTimer(uint32 timer) { _waterfallTimer = timer; };
- uint32 getWaterFallKnockbackTimer() { return _waterfallTimer; };
+ uint32 getWaterFallKnockbackTimer() { return _waterfallKnockbackTimer; };
void setWaterFallKnockbackTimer(uint32 timer) { _waterfallKnockbackTimer = timer; };
uint8 getPipeKnockBackCount() { return _pipeKnockBackCount; };
void setPipeKnockBackCount(uint8 count) { _pipeKnockBackCount = count; };
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp
index f3d0f5520f0..45335ae7b8b 100755
--- a/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp
@@ -837,6 +837,7 @@ void BattlegroundIC::DestroyGate(Player* player, GameObject* go)
{
case GO_HORDE_GATE_1:
lang_entry = LANG_BG_IC_NORTH_GATE_DESTROYED;
+ break;
case GO_HORDE_GATE_2:
case GO_ALLIANCE_GATE_1:
lang_entry = LANG_BG_IC_WEST_GATE_DESTROYED;
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp
index 6d784488aad..977897b8d48 100755
--- a/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp
@@ -534,16 +534,16 @@ void BattlegroundSA::EventPlayerDamagedGO(Player* /*player*/, GameObject* go, ui
if (eventType == go->GetGOInfo()->building.damagedEvent)
{
- uint32 i = GetGateIDFromDestroyEventID(eventType);
+ uint32 i = getGateIdFromDamagedOrDestroyEventId(eventType);
GateStatus[i] = BG_SA_GATE_DAMAGED;
- uint32 uws = GetWorldStateFromGateID(i);
+ uint32 uws = getWorldStateFromGateId(i);
if (uws)
UpdateWorldState(uws, GateStatus[i]);
}
if (eventType == go->GetGOInfo()->building.destroyedEvent)
{
- if (go->GetGOInfo()->building.destroyedEvent == 19837)
+ if (go->GetGOInfo()->building.destroyedEvent == BG_SA_EVENT_ANCIENT_GATE_DESTROYED)
SendWarningToAll(LANG_BG_SA_CHAMBER_BREACHED);
else
SendWarningToAll(LANG_BG_SA_WAS_DESTROYED, go->GetGOInfo()->name.c_str());
@@ -603,7 +603,7 @@ void BattlegroundSA::DemolisherStartState(bool start)
void BattlegroundSA::DestroyGate(Player* player, GameObject* go)
{
- uint32 i = GetGateIDFromDestroyEventID(go->GetGOInfo()->building.destroyedEvent);
+ uint32 i = getGateIdFromDamagedOrDestroyEventId(go->GetGOInfo()->building.destroyedEvent);
if (!GateStatus[i])
return;
@@ -612,7 +612,7 @@ void BattlegroundSA::DestroyGate(Player* player, GameObject* go)
if (g->GetGOValue()->Building.Health == 0)
{
GateStatus[i] = BG_SA_GATE_DESTROYED;
- uint32 uws = GetWorldStateFromGateID(i);
+ uint32 uws = getWorldStateFromGateId(i);
if (uws)
UpdateWorldState(uws, GateStatus[i]);
bool rewardHonor = true;
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundSA.h b/src/server/game/Battlegrounds/Zones/BattlegroundSA.h
index 76a772ff978..2ade101ce54 100755
--- a/src/server/game/Battlegrounds/Zones/BattlegroundSA.h
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundSA.h
@@ -45,9 +45,30 @@ enum BG_SA_Status
enum BG_SA_GateState
{
- BG_SA_GATE_OK = 1,
- BG_SA_GATE_DAMAGED = 2,
- BG_SA_GATE_DESTROYED = 3
+ BG_SA_GATE_OK = 1,
+ BG_SA_GATE_DAMAGED = 2,
+ BG_SA_GATE_DESTROYED = 3
+};
+
+enum BG_SA_EventIdGate
+{
+ BG_SA_EVENT_GREEN_GATE_DAMAGED = 19041,
+ BG_SA_EVENT_GREEN_GATE_DESTROYED = 19046,
+
+ BG_SA_EVENT_BLUE_GATE_DAMAGED = 19040,
+ BG_SA_EVENT_BLUE_GATE_DESTROYED = 19045,
+
+ BG_SA_EVENT_RED_GATE_DAMAGED = 19042,
+ BG_SA_EVENT_RED_GATE_DESTROYED = 19047,
+
+ BG_SA_EVENT_PURPLE_GATE_DAMAGED = 19048,
+ BG_SA_EVENT_PURPLE_GATE_DESTROYED = 19043,
+
+ BG_SA_EVENT_YELLOW_GATE_DAMAGED = 19049,
+ BG_SA_EVENT_YELLOW_GATE_DESTROYED = 19044,
+
+ BG_SA_EVENT_ANCIENT_GATE_DAMAGED = 19836,
+ BG_SA_EVENT_ANCIENT_GATE_DESTROYED = 19837
};
enum BG_SA_Timers
@@ -443,34 +464,60 @@ class BattlegroundSA : public Battleground
/// Called when a player use a gamobject (relic)
virtual void EventPlayerUsedGO(Player* Source, GameObject* object);
/// Return gate id, relative to bg data, according to gameobject id
- uint32 GetGateIDFromDestroyEventID(uint32 id)
+ uint32 getGateIdFromDamagedOrDestroyEventId(uint32 id)
{
- uint32 i = 0;
switch (id)
{
- case 19046: i = BG_SA_GREEN_GATE; break; //Green gate destroyed
- case 19045: i = BG_SA_BLUE_GATE; break; //blue gate
- case 19047: i = BG_SA_RED_GATE; break; //red gate
- case 19048: i = BG_SA_PURPLE_GATE; break; //purple gate
- case 19049: i = BG_SA_YELLOW_GATE; break; //yellow gate
- case 19837: i = BG_SA_ANCIENT_GATE; break; //ancient gate
+ // Green gate
+ case BG_SA_EVENT_GREEN_GATE_DAMAGED:
+ case BG_SA_EVENT_GREEN_GATE_DESTROYED:
+ return BG_SA_GREEN_GATE;
+ // Blue gate
+ case BG_SA_EVENT_BLUE_GATE_DAMAGED:
+ case BG_SA_EVENT_BLUE_GATE_DESTROYED:
+ return BG_SA_BLUE_GATE;
+ // Red gate
+ case BG_SA_EVENT_RED_GATE_DAMAGED:
+ case BG_SA_EVENT_RED_GATE_DESTROYED:
+ return BG_SA_RED_GATE;
+ // Purple gate
+ case BG_SA_EVENT_PURPLE_GATE_DAMAGED:
+ case BG_SA_EVENT_PURPLE_GATE_DESTROYED:
+ return BG_SA_PURPLE_GATE;
+ // Yellow gate
+ case BG_SA_EVENT_YELLOW_GATE_DAMAGED:
+ case BG_SA_EVENT_YELLOW_GATE_DESTROYED:
+ return BG_SA_YELLOW_GATE;
+ // Ancient gate
+ case BG_SA_EVENT_ANCIENT_GATE_DAMAGED:
+ case BG_SA_EVENT_ANCIENT_GATE_DESTROYED:
+ return BG_SA_ANCIENT_GATE;
+ default:
+ break;
}
- return i;
+ return 0;
}
/// Return worldstate id, according to door id
- uint32 GetWorldStateFromGateID(uint32 id)
+ uint32 getWorldStateFromGateId(uint32 id)
{
- uint32 uws = 0;
switch (id)
{
- case BG_SA_GREEN_GATE: uws = BG_SA_GREEN_GATEWS; break;
- case BG_SA_YELLOW_GATE: uws = BG_SA_YELLOW_GATEWS; break;
- case BG_SA_BLUE_GATE: uws = BG_SA_BLUE_GATEWS; break;
- case BG_SA_RED_GATE: uws = BG_SA_RED_GATEWS; break;
- case BG_SA_PURPLE_GATE: uws = BG_SA_PURPLE_GATEWS; break;
- case BG_SA_ANCIENT_GATE: uws = BG_SA_ANCIENT_GATEWS; break;
+ case BG_SA_GREEN_GATE:
+ return BG_SA_GREEN_GATEWS;
+ case BG_SA_YELLOW_GATE:
+ return BG_SA_YELLOW_GATEWS;
+ case BG_SA_BLUE_GATE:
+ return BG_SA_BLUE_GATEWS;
+ case BG_SA_RED_GATE:
+ return BG_SA_RED_GATEWS;
+ case BG_SA_PURPLE_GATE:
+ return BG_SA_PURPLE_GATEWS;
+ case BG_SA_ANCIENT_GATE:
+ return BG_SA_ANCIENT_GATEWS;
+ default:
+ break;
}
- return uws;
+ return 0;
}
/// Called on battleground ending
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp
index 86ad749b8b7..d100dc645a2 100755
--- a/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp
@@ -179,20 +179,20 @@ void BattlegroundWS::StartingEventCloseDoors()
void BattlegroundWS::StartingEventOpenDoors()
{
- for (uint32 i = BG_WS_OBJECT_DOOR_A_1; i <= BG_WS_OBJECT_DOOR_A_4; ++i)
+ for (uint32 i = BG_WS_OBJECT_DOOR_A_1; i <= BG_WS_OBJECT_DOOR_A_6; ++i)
DoorOpen(i);
- for (uint32 i = BG_WS_OBJECT_DOOR_H_1; i <= BG_WS_OBJECT_DOOR_H_2; ++i)
+ for (uint32 i = BG_WS_OBJECT_DOOR_H_1; i <= BG_WS_OBJECT_DOOR_H_4; ++i)
DoorOpen(i);
+ for (uint32 i = BG_WS_OBJECT_A_FLAG; i <= BG_WS_OBJECT_BERSERKBUFF_2; ++i)
+ SpawnBGObject(i, RESPAWN_IMMEDIATELY);
+
SpawnBGObject(BG_WS_OBJECT_DOOR_A_5, RESPAWN_ONE_DAY);
SpawnBGObject(BG_WS_OBJECT_DOOR_A_6, RESPAWN_ONE_DAY);
SpawnBGObject(BG_WS_OBJECT_DOOR_H_3, RESPAWN_ONE_DAY);
SpawnBGObject(BG_WS_OBJECT_DOOR_H_4, RESPAWN_ONE_DAY);
- for (uint32 i = BG_WS_OBJECT_A_FLAG; i <= BG_WS_OBJECT_BERSERKBUFF_2; ++i)
- SpawnBGObject(i, RESPAWN_IMMEDIATELY);
-
- // players joining later are not egible
+ // players joining later are not eligibles
StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, WS_EVENT_START_BATTLE);
}
@@ -476,7 +476,7 @@ void BattlegroundWS::EventPlayerClickedOnFlag(Player* Source, GameObject* target
}
//Alliance flag on ground(not in base) (returned or picked up again from ground!)
- if (GetFlagState(ALLIANCE) == BG_WS_FLAG_STATE_ON_GROUND && Source->IsWithinDistInMap(target_obj, 10) && BgObjects[BG_WS_OBJECT_A_FLAG] == target_obj->GetGUID())
+ if (GetFlagState(ALLIANCE) == BG_WS_FLAG_STATE_ON_GROUND && Source->IsWithinDistInMap(target_obj, 10) && target_obj->GetGOInfo()->entry == BG_OBJECT_A_FLAG_GROUND_WS_ENTRY)
{
if (Source->GetTeam() == ALLIANCE)
{
@@ -510,7 +510,7 @@ void BattlegroundWS::EventPlayerClickedOnFlag(Player* Source, GameObject* target
}
//Horde flag on ground(not in base) (returned or picked up again)
- if (GetFlagState(HORDE) == BG_WS_FLAG_STATE_ON_GROUND && Source->IsWithinDistInMap(target_obj, 10) && BgObjects[BG_WS_OBJECT_H_FLAG] == target_obj->GetGUID())
+ if (GetFlagState(HORDE) == BG_WS_FLAG_STATE_ON_GROUND && Source->IsWithinDistInMap(target_obj, 10) && target_obj->GetGOInfo()->entry == BG_OBJECT_H_FLAG_GROUND_WS_ENTRY)
{
if (Source->GetTeam() == HORDE)
{
diff --git a/src/server/game/CMakeLists.txt b/src/server/game/CMakeLists.txt
index 1f680f6e9b0..8b81a48c33b 100644
--- a/src/server/game/CMakeLists.txt
+++ b/src/server/game/CMakeLists.txt
@@ -107,7 +107,6 @@ set(game_STAT_SRCS
include_directories(
${CMAKE_BINARY_DIR}
${CMAKE_SOURCE_DIR}/dep/g3dlite/include
- ${CMAKE_SOURCE_DIR}/dep/mersennetwister
${CMAKE_SOURCE_DIR}/dep/SFMT
${CMAKE_SOURCE_DIR}/dep/zlib
${CMAKE_SOURCE_DIR}/src/server/collision
diff --git a/src/server/game/Chat/Channels/Channel.cpp b/src/server/game/Chat/Channels/Channel.cpp
index 92cf4d750a8..0e89601e987 100755
--- a/src/server/game/Chat/Channels/Channel.cpp
+++ b/src/server/game/Chat/Channels/Channel.cpp
@@ -49,7 +49,6 @@ Channel::Channel(const std::string& name, uint32 channel_id, uint32 Team)
}
else // it's custom channel
{
- channel_id = 0;
m_flags |= CHANNEL_FLAG_CUSTOM;
// If storing custom channels in the db is enabled either load or save the channel
diff --git a/src/server/game/Chat/Chat.cpp b/src/server/game/Chat/Chat.cpp
index 48bb4c27ef8..cc64a8e22dd 100755
--- a/src/server/game/Chat/Chat.cpp
+++ b/src/server/game/Chat/Chat.cpp
@@ -381,7 +381,6 @@ ChatCommand* ChatHandler::getCommandTable()
{ "linkgrave", SEC_ADMINISTRATOR, false, OldHandler<&ChatHandler::HandleLinkGraveCommand>, "", NULL },
{ "neargrave", SEC_ADMINISTRATOR, false, OldHandler<&ChatHandler::HandleNearGraveCommand>, "", NULL },
{ "explorecheat", SEC_ADMINISTRATOR, false, OldHandler<&ChatHandler::HandleExploreCheatCommand>, "", NULL },
- { "hover", SEC_ADMINISTRATOR, false, OldHandler<&ChatHandler::HandleHoverCommand>, "", NULL },
{ "levelup", SEC_ADMINISTRATOR, false, OldHandler<&ChatHandler::HandleLevelUpCommand>, "", NULL },
{ "showarea", SEC_ADMINISTRATOR, false, OldHandler<&ChatHandler::HandleShowAreaCommand>, "", NULL },
{ "hidearea", SEC_ADMINISTRATOR, false, OldHandler<&ChatHandler::HandleHideAreaCommand>, "", NULL },
@@ -1334,7 +1333,7 @@ GameTele const* ChatHandler::extractGameTeleFromLink(char* text)
// id, or string, or [name] Shift-click form |color|Htele:id|h[name]|h|r
char* cId = extractKeyFromLink(text, "Htele");
if (!cId)
- return false;
+ return NULL;
// id case (explicit or from shift link)
if (cId[0] >= '0' || cId[0] >= '9')
@@ -1506,7 +1505,7 @@ char* ChatHandler::extractQuotedArg(char* args)
{
char* space = strtok(args, "\"");
if (!space)
- return false;
+ return NULL;
return strtok(NULL, "\"");
}
}
diff --git a/src/server/game/Chat/Chat.h b/src/server/game/Chat/Chat.h
index 0a39eb43ddb..e88914a2daf 100755
--- a/src/server/game/Chat/Chat.h
+++ b/src/server/game/Chat/Chat.h
@@ -286,7 +286,6 @@ class ChatHandler
bool HandleActivateObjectCommand(const char* args);
bool HandleSpawnTransportCommand(const char* args);
bool HandleExploreCheatCommand(const char* args);
- bool HandleHoverCommand(const char* args);
bool HandleWaterwalkCommand(const char* args);
bool HandleLevelUpCommand(const char* args);
bool HandleShowAreaCommand(const char* args);
diff --git a/src/server/game/Chat/Commands/Level3.cpp b/src/server/game/Chat/Commands/Level3.cpp
index d3417705867..30562bb9662 100755
--- a/src/server/game/Chat/Commands/Level3.cpp
+++ b/src/server/game/Chat/Commands/Level3.cpp
@@ -441,7 +441,7 @@ bool ChatHandler::HandleListItemCommand(const char *args)
Field* fields = result->Fetch();
uint32 item_guid = fields[0].GetUInt32();
uint32 item_bag = fields[1].GetUInt32();
- uint32 item_slot = fields[2].GetUInt32();
+ uint8 item_slot = fields[2].GetUInt8();
uint32 owner_guid = fields[3].GetUInt32();
uint32 owner_acc = fields[4].GetUInt32();
std::string owner_name = fields[5].GetString();
@@ -638,7 +638,7 @@ bool ChatHandler::HandleListObjectCommand(const char *args)
uint32 obj_count = 0;
result = WorldDatabase.PQuery("SELECT COUNT(guid) FROM gameobject WHERE id='%u'", go_id);
if (result)
- obj_count = (*result)[0].GetUInt32();
+ obj_count = (*result)[0].GetUInt64();
if (m_session)
{
@@ -710,7 +710,7 @@ bool ChatHandler::HandleListCreatureCommand(const char *args)
uint32 cr_count = 0;
result = WorldDatabase.PQuery("SELECT COUNT(guid) FROM creature WHERE id='%u'", cr_id);
if (result)
- cr_count = (*result)[0].GetUInt32();
+ cr_count = (*result)[0].GetUInt64();
if (m_session)
{
@@ -2158,25 +2158,6 @@ bool ChatHandler::HandleExploreCheatCommand(const char *args)
return true;
}
-bool ChatHandler::HandleHoverCommand(const char *args)
-{
- char* px = strtok((char*)args, " ");
- uint32 flag;
- if (!px)
- flag = 1;
- else
- flag = atoi(px);
-
- m_session->GetPlayer()->SetHover(flag);
-
- if (flag)
- SendSysMessage(LANG_HOVER_ENABLED);
- else
- SendSysMessage(LANG_HOVER_DISABLED);
-
- return true;
-}
-
void ChatHandler::HandleCharacterLevel(Player* player, uint64 playerGuid, uint32 oldLevel, uint32 newLevel)
{
if (player)
@@ -4593,40 +4574,38 @@ bool ChatHandler::HandleUnFreezeCommand(const char *args)
{
std::string name;
Player* player;
- char *TargetName = strtok((char*)args, " "); //get entered name
- if (!TargetName) //if no name entered use target
- {
- player = getSelectedPlayer();
- if (player) //prevent crash with creature as target
- name = player->GetName();
- }
+ char* targetName = strtok((char*)args, " "); // Get entered name
- else // if name entered
+ if (targetName)
{
- name = TargetName;
+ name = targetName;
normalizePlayerName(name);
player = sObjectAccessor->FindPlayerByName(name.c_str());
}
+ else // If no name was entered - use target
+ {
+ player = getSelectedPlayer();
+ if (player)
+ name = player->GetName();
+ }
- //effect
if (player)
{
PSendSysMessage(LANG_COMMAND_UNFREEZE, name.c_str());
- //Reset player faction + allow combat + allow duels
+ // Reset player faction + allow combat + allow duels
player->setFactionForRace(player->getRace());
player->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
- //allow movement and spells
+ // Remove Freeze spell (allowing movement and spells)
player->RemoveAurasDueToSpell(9454);
- //save player
+ // Save player
player->SaveToDB();
}
-
- if (!player)
+ else
{
- if (TargetName)
+ if (targetName)
{
// Check for offline players
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_GUID_BY_NAME);
@@ -4638,12 +4617,13 @@ bool ChatHandler::HandleUnFreezeCommand(const char *args)
SendSysMessage(LANG_COMMAND_FREEZE_WRONG);
return true;
}
- //if player found: delete his freeze aura
- Field* fields=result->Fetch();
- uint64 pguid = fields[0].GetUInt64();
+
+ // If player found: delete his freeze aura
+ Field* fields = result->Fetch();
+ uint32 lowGuid = fields[0].GetUInt32();
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_AURA_FROZEN);
- stmt->setUInt32(0, pguid);
+ stmt->setUInt32(0, lowGuid);
CharacterDatabase.Execute(stmt);
PSendSysMessage(LANG_COMMAND_UNFREEZE, name.c_str());
diff --git a/src/server/game/Combat/ThreatManager.cpp b/src/server/game/Combat/ThreatManager.cpp
index d82e43ba83b..e604eaf9024 100755
--- a/src/server/game/Combat/ThreatManager.cpp
+++ b/src/server/game/Combat/ThreatManager.cpp
@@ -75,7 +75,7 @@ bool ThreatCalcHelper::isValidProcess(Unit* hatedUnit, Unit* hatingUnit, SpellIn
return false;
// not in same map or phase
- if (!hatedUnit->IsInMap(hatingUnit))
+ if (!hatedUnit->IsInMap(hatingUnit) || !hatedUnit->InSamePhase(hatingUnit))
return false;
// spell not causing threat
@@ -182,6 +182,7 @@ void HostileReference::updateOnlineStatus()
&& (getTarget()->GetTypeId() != TYPEID_PLAYER || !getTarget()->ToPlayer()->isGameMaster())
&& !getTarget()->HasUnitState(UNIT_STATE_IN_FLIGHT)
&& getTarget()->IsInMap(getSourceUnit())
+ && getTarget()->InSamePhase(getSourceUnit())
)
{
Creature* creature = getSourceUnit()->ToCreature();
diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp
index 3fcabea4c74..96f454fd3e2 100755
--- a/src/server/game/Conditions/ConditionMgr.cpp
+++ b/src/server/game/Conditions/ConditionMgr.cpp
@@ -274,6 +274,12 @@ bool Condition::Meets(ConditionSourceInfo& sourceInfo)
condMeets = object->GetPhaseMask() & ConditionValue1;
break;
}
+ case CONDITION_TITLE:
+ {
+ if (Player* player = object->ToPlayer())
+ condMeets = player->HasTitle(ConditionValue1);
+ break;
+ }
default:
condMeets = false;
break;
@@ -422,6 +428,9 @@ uint32 Condition::GetSearcherTypeMaskForCondition()
case CONDITION_PHASEMASK:
mask |= GRID_MAP_TYPE_MASK_ALL;
break;
+ case CONDITION_TITLE:
+ mask |= GRID_MAP_TYPE_MASK_PLAYER;
+ break;
default:
ASSERT(false && "Condition::GetSearcherTypeMaskForCondition - missing condition handling!");
break;
@@ -1826,9 +1835,16 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond)
sLog->outErrorDb("Phasemask condition has useless data in value3 (%u)!", cond->ConditionValue3);
break;
}
- case CONDITION_UNUSED_18:
- sLog->outErrorDb("Found ConditionTypeOrReference = CONDITION_UNUSED_18 in `conditions` table - ignoring");
- return false;
+ case CONDITION_TITLE:
+ {
+ CharTitlesEntry const* titleEntry = sCharTitlesStore.LookupEntry(cond->ConditionValue1);
+ if (!titleEntry)
+ {
+ sLog->outErrorDb("Title condition has non existing title in value1 (%u), skipped", cond->ConditionValue1);
+ return false;
+ }
+ break;
+ }
case CONDITION_UNUSED_19:
sLog->outErrorDb("Found ConditionTypeOrReference = CONDITION_UNUSED_19 in `conditions` table - ignoring");
return false;
diff --git a/src/server/game/Conditions/ConditionMgr.h b/src/server/game/Conditions/ConditionMgr.h
index 2df79eab088..130a23a0cb0 100755
--- a/src/server/game/Conditions/ConditionMgr.h
+++ b/src/server/game/Conditions/ConditionMgr.h
@@ -48,7 +48,7 @@ enum ConditionTypes
CONDITION_CLASS = 15, // class 0 0 true if player's class is equal to class
CONDITION_RACE = 16, // race 0 0 true if player's race is equal to race
CONDITION_ACHIEVEMENT = 17, // achievement_id 0 0 true if achievement is complete
- CONDITION_UNUSED_18 = 18, //
+ CONDITION_TITLE = 18, // title id 0 0 true if player has title
CONDITION_UNUSED_19 = 19, //
CONDITION_UNUSED_20 = 20, //
CONDITION_UNUSED_21 = 21, //
diff --git a/src/server/game/DataStores/DBCStructure.h b/src/server/game/DataStores/DBCStructure.h
index 38e8c957681..15792fd57da 100755
--- a/src/server/game/DataStores/DBCStructure.h
+++ b/src/server/game/DataStores/DBCStructure.h
@@ -1292,6 +1292,7 @@ struct MapEntry
bool IsBattleground() const { return map_type == MAP_BATTLEGROUND; }
bool IsBattleArena() const { return map_type == MAP_ARENA; }
bool IsBattlegroundOrArena() const { return map_type == MAP_BATTLEGROUND || map_type == MAP_ARENA; }
+ bool IsWorldMap() const { return map_type == MAP_COMMON; }
bool GetEntrancePos(int32 &mapid, float &x, float &y) const
{
diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp
index b936d32e13f..47c298d7467 100755
--- a/src/server/game/DungeonFinding/LFGMgr.cpp
+++ b/src/server/game/DungeonFinding/LFGMgr.cpp
@@ -1023,7 +1023,7 @@ bool LFGMgr::CheckCompatibility(LfgGuidList check, LfgProposal*& pProposal)
// Select a random dungeon from the compatible list
// TODO - Select the dungeon based on group item Level, not just random
// Create a new proposal
- pProposal = new LfgProposal(SelectRandomContainerElement(compatibleDungeons));
+ pProposal = new LfgProposal(Trinity::Containers::SelectRandomContainerElement(compatibleDungeons));
pProposal->cancelTime = time_t(time(NULL)) + LFG_TIME_PROPOSAL;
pProposal->state = LFG_PROPOSAL_INITIATING;
pProposal->queues = check;
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index 6a8ae07291a..ed89041ff66 100755
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -357,8 +357,9 @@ bool Creature::UpdateEntry(uint32 Entry, uint32 team, const CreatureData* data)
m_regenHealth = cInfo->RegenHealth;
- // creatures always have melee weapon ready if any
- SetSheath(SHEATH_STATE_MELEE);
+ // creatures always have melee weapon ready if any unless specified otherwise
+ if (!GetCreatureAddon())
+ SetSheath(SHEATH_STATE_MELEE);
SelectLevel(GetCreatureTemplate());
if (team == HORDE)
@@ -795,10 +796,12 @@ bool Creature::Create(uint32 guidlow, Map* map, uint32 phaseMask, uint32 Entry,
//! Need to be called after LoadCreaturesAddon - MOVEMENTFLAG_HOVER is set there
if (HasUnitMovementFlag(MOVEMENTFLAG_HOVER))
+ {
z += GetFloatValue(UNIT_FIELD_HOVERHEIGHT);
- //! Relocate again with updated Z coord
- Relocate(x, y, z, ang);
+ //! Relocate again with updated Z coord
+ Relocate(x, y, z, ang);
+ }
uint32 displayID = GetNativeDisplayId();
CreatureModelInfo const* minfo = sObjectMgr->GetCreatureModelRandomGender(&displayID);
diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h
index f100d391698..f6d03ca38b2 100755
--- a/src/server/game/Entities/Creature/Creature.h
+++ b/src/server/game/Entities/Creature/Creature.h
@@ -266,7 +266,6 @@ struct CreatureData
// `creature_addon` table
struct CreatureAddon
{
- uint32 guidOrEntry;
uint32 path_id;
uint32 mount;
uint32 bytes1;
@@ -508,7 +507,7 @@ class Creature : public Unit, public GridObject<Creature>, public MapCreature
if (isPet())
return false;
- return GetCreatureTemplate()->rank == CREATURE_ELITE_WORLDBOSS;
+ return GetCreatureTemplate()->type_flags & CREATURE_TYPEFLAGS_BOSS;
}
bool IsDungeonBoss() const;
diff --git a/src/server/game/Entities/Creature/GossipDef.cpp b/src/server/game/Entities/Creature/GossipDef.cpp
index a39bd8eddf7..836fbe8c7bf 100755
--- a/src/server/game/Entities/Creature/GossipDef.cpp
+++ b/src/server/game/Entities/Creature/GossipDef.cpp
@@ -47,10 +47,7 @@ void GossipMenu::AddMenuItem(int32 menuItemId, uint8 icon, std::string const& me
for (GossipMenuItemContainer::const_iterator itr = _menuItems.begin(); itr != _menuItems.end(); ++itr)
{
if (int32(itr->first) > menuItemId)
- {
- menuItemId = menuItemId;
break;
- }
menuItemId = itr->first + 1;
}
diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp
index 1fe83023976..f58dd6b2e4d 100755
--- a/src/server/game/Entities/GameObject/GameObject.cpp
+++ b/src/server/game/Entities/GameObject/GameObject.cpp
@@ -135,10 +135,10 @@ void GameObject::AddToWorld()
sObjectAccessor->AddObject(this);
bool startOpen = (GetGoType() == GAMEOBJECT_TYPE_DOOR || GetGoType() == GAMEOBJECT_TYPE_BUTTON ? GetGOInfo()->door.startOpen : false);
// The state can be changed after GameObject::Create but before GameObject::AddToWorld
- bool toggledState = GetGoState() == GO_STATE_READY;
+ bool toggledState = GetGOData() ? GetGOData()->go_state == GO_STATE_READY : false;
if (m_model)
GetMap()->Insert(*m_model);
- if ((startOpen && !toggledState) || (!startOpen && toggledState))
+ if (startOpen ^ toggledState)
EnableCollision(false);
WorldObject::AddToWorld();
@@ -1432,7 +1432,7 @@ void GameObject::Use(Unit* user)
if (info->summoningRitual.casterTargetSpell && info->summoningRitual.casterTargetSpell != 1) // No idea why this field is a bool in some cases
for (uint32 i = 0; i < info->summoningRitual.casterTargetSpellTargets; i++)
// m_unique_users can contain only player GUIDs
- if (Player* target = ObjectAccessor::GetPlayer(*this, SelectRandomContainerElement(m_unique_users)))
+ if (Player* target = ObjectAccessor::GetPlayer(*this, Trinity::Containers::SelectRandomContainerElement(m_unique_users)))
spellCaster->CastSpell(target, info->summoningRitual.casterTargetSpell, true);
// finish owners spell
@@ -1825,6 +1825,7 @@ void GameObject::SetDestructibleState(GameObjectDestructibleState state, Player*
m_goValue->Building.Health = m_goValue->Building.MaxHealth;
SetGoAnimProgress(255);
}
+ EnableCollision(true);
break;
case GO_DESTRUCTIBLE_DAMAGED:
{
@@ -1881,6 +1882,7 @@ void GameObject::SetDestructibleState(GameObjectDestructibleState state, Player*
m_goValue->Building.Health = 0;
SetGoAnimProgress(0);
}
+ EnableCollision(false);
break;
}
case GO_DESTRUCTIBLE_REBUILDING:
@@ -1900,6 +1902,7 @@ void GameObject::SetDestructibleState(GameObjectDestructibleState state, Player*
m_goValue->Building.Health = m_goValue->Building.MaxHealth;
SetGoAnimProgress(255);
}
+ EnableCollision(true);
break;
}
}
diff --git a/src/server/game/Entities/Item/Item.cpp b/src/server/game/Entities/Item/Item.cpp
index bc90e6f4484..f2b893896dc 100755
--- a/src/server/game/Entities/Item/Item.cpp
+++ b/src/server/game/Entities/Item/Item.cpp
@@ -1089,9 +1089,9 @@ void Item::SaveRefundDataToDB()
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_ITEM_REFUND_INSTANCE);
stmt->setUInt32(0, GetGUIDLow());
- stmt->setUInt32(0, GetRefundRecipient());
- stmt->setUInt32(0, GetPaidMoney());
- stmt->setUInt16(0, uint16(GetPaidExtendedCost()));
+ stmt->setUInt32(1, GetRefundRecipient());
+ stmt->setUInt32(2, GetPaidMoney());
+ stmt->setUInt16(3, uint16(GetPaidExtendedCost()));
trans->Append(stmt);
CharacterDatabase.CommitTransaction(trans);
diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp
index 69effaa016e..70b680c6ae0 100755
--- a/src/server/game/Entities/Object/Object.cpp
+++ b/src/server/game/Entities/Object/Object.cpp
@@ -1630,7 +1630,7 @@ void WorldObject::UpdateAllowedPositionZ(float x, float y, float &z) const
default:
{
float ground_z = GetBaseMap()->GetHeight(GetPhaseMask(), x, y, z, true);
- if(ground_z > INVALID_HEIGHT)
+ if (ground_z > INVALID_HEIGHT)
z = ground_z;
break;
}
@@ -2741,6 +2741,14 @@ void WorldObject::MovePositionToFirstCollision(Position &pos, float dist, float
pos.m_positionZ += 2.0f;
destx = pos.m_positionX + dist * cos(angle);
desty = pos.m_positionY + dist * sin(angle);
+
+ // Prevent invalid coordinates here, position is unchanged
+ if (!Trinity::IsValidMapCoord(destx, desty))
+ {
+ sLog->outCrash("WorldObject::MovePositionToFirstCollision invalid coordinates X: %f and Y: %f were passed!", destx, desty);
+ return;
+ }
+
ground = GetMap()->GetHeight(GetPhaseMask(), destx, desty, MAX_HEIGHT, true);
floor = GetMap()->GetHeight(GetPhaseMask(), destx, desty, pos.m_positionZ, true);
destz = fabs(ground - pos.m_positionZ) <= fabs(floor - pos.m_positionZ) ? ground : floor;
diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h
index 6c77bf69a68..3693f683b24 100755
--- a/src/server/game/Entities/Object/Object.h
+++ b/src/server/game/Entities/Object/Object.h
@@ -685,7 +685,7 @@ class WorldObject : public Object, public WorldLocation
bool IsInMap(const WorldObject* obj) const
{
if (obj)
- return IsInWorld() && obj->IsInWorld() && (GetMap() == obj->GetMap()) && InSamePhase(obj);
+ return IsInWorld() && obj->IsInWorld() && (GetMap() == obj->GetMap());
return false;
}
bool IsWithinDist3d(float x, float y, float z, float dist) const
@@ -703,7 +703,7 @@ class WorldObject : public Object, public WorldLocation
}
bool IsWithinDistInMap(WorldObject const* obj, float dist2compare, bool is3D = true) const
{
- return obj && IsInMap(obj) && _IsWithinDist(obj, dist2compare, is3D);
+ return obj && IsInMap(obj) && InSamePhase(obj) && _IsWithinDist(obj, dist2compare, is3D);
}
bool IsWithinLOS(float x, float y, float z) const;
bool IsWithinLOSInMap(const WorldObject* obj) const;
@@ -878,20 +878,6 @@ class WorldObject : public Object, public WorldLocation
namespace Trinity
{
- template<class T>
- void RandomResizeList(std::list<T> &_list, uint32 _size)
- {
- size_t list_size = _list.size();
-
- while (list_size > _size)
- {
- typename std::list<T>::iterator itr = _list.begin();
- std::advance(itr, urand(0, list_size - 1));
- _list.erase(itr);
- --list_size;
- }
- }
-
// Binary predicate to sort WorldObjects based on the distance to a reference WorldObject
class ObjectDistanceOrderPred
{
diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp
index 0ee8381d54f..586f09bd79c 100755
--- a/src/server/game/Entities/Pet/Pet.cpp
+++ b/src/server/game/Entities/Pet/Pet.cpp
@@ -1041,6 +1041,13 @@ bool Guardian::InitStatsForLevel(uint8 petlevel)
SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel + (petlevel / 4)));
break;
}
+ case 28017: // Bloodworms
+ {
+ SetCreateHealth(4 * petlevel);
+ SetBonusDamage(int32(m_owner->GetTotalAttackPowerValue(BASE_ATTACK) * 0.006f));
+ SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel - 30 - (petlevel / 4)));
+ SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel - 30 + (petlevel / 4)));
+ }
}
break;
}
@@ -1745,7 +1752,7 @@ void Pet::resetTalentsForAllPetsOf(Player* owner, Pet* online_pet /*= NULL*/)
stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PET_SPELL_LIST);
stmt->setUInt32(0, owner->GetGUIDLow());
- stmt->setUInt32(0, except_petnumber);
+ stmt->setUInt32(1, except_petnumber);
PreparedQueryResult result = CharacterDatabase.Query(stmt);
if (!result)
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 0a4363df323..7c70fe9358e 100755
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -724,7 +724,6 @@ Player::Player(WorldSession* session): Unit(true), m_achievementMgr(this), m_rep
for (uint8 i=0; i<MAX_TIMERS; i++)
m_MirrorTimer[i] = DISABLED_MIRROR_TIMER;
- _lastLiquid = NULL;
m_MirrorTimerFlags = UNDERWATER_NONE;
m_MirrorTimerFlagsLast = UNDERWATER_NONE;
m_isInWater = false;
@@ -932,7 +931,8 @@ bool Player::Create(uint32 guidlow, CharacterCreateInfo* createInfo)
PlayerInfo const* info = sObjectMgr->GetPlayerInfo(createInfo->Race, createInfo->Class);
if (!info)
{
- sLog->outError("Player (Name %s) has incorrect race/class pair. Can't be loaded.", m_name.c_str());
+ sLog->outError("Player::Create: Possible hacking-attempt: Account %u tried creating a character named '%s' with an invalid race/class pair (%u/%u) - refusing to do so.",
+ GetSession()->GetAccountId(), m_name.c_str(), createInfo->Race, createInfo->Class);
return false;
}
@@ -944,7 +944,8 @@ bool Player::Create(uint32 guidlow, CharacterCreateInfo* createInfo)
ChrClassesEntry const* cEntry = sChrClassesStore.LookupEntry(createInfo->Class);
if (!cEntry)
{
- sLog->outError("Class %u not found in DBC (Wrong DBC files?)", createInfo->Class);
+ sLog->outError("Player::Create: Possible hacking-attempt: Account %u tried creating a character named '%s' with an invalid character class (%u) - refusing to do so (wrong DBC-files?)",
+ GetSession()->GetAccountId(), m_name.c_str(), createInfo->Class);
return false;
}
@@ -959,7 +960,8 @@ bool Player::Create(uint32 guidlow, CharacterCreateInfo* createInfo)
if (!IsValidGender(createInfo->Gender))
{
- sLog->outError("Player has invalid gender (%hu), can't be loaded.", createInfo->Gender);
+ sLog->outError("Player::Create: Possible hacking-attempt: Account %u tried creating a character named '%s' with an invalid gender (%hu) - refusing to do so",
+ GetSession()->GetAccountId(), m_name.c_str(), createInfo->Gender);
return false;
}
@@ -2134,7 +2136,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
if (duel && GetMapId() != mapid && GetMap()->GetGameObject(GetUInt64Value(PLAYER_DUEL_ARBITER)))
DuelComplete(DUEL_FLED);
- if ((GetMapId() == mapid && !m_transport) || (GetTransport() && GetMapId() == 628))
+ if (GetMapId() == mapid)
{
//lets reset far teleport flag if it wasn't reset during chained teleports
SetSemaphoreTeleportFar(false);
@@ -2936,7 +2938,7 @@ void Player::GiveXP(uint32 xp, Unit* victim, float group_rate)
if (xp < 1)
return;
- if (!isAlive())
+ if (!isAlive() && !GetBattlegroundId())
return;
if (HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_NO_XP_GAIN))
@@ -4819,16 +4821,16 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC
{
do
{
- Field* fields = resultMail->Fetch();
+ Field* mailFields = resultMail->Fetch();
- uint32 mail_id = fields[0].GetUInt32();
- uint8 mailType = fields[1].GetUInt8();
- uint16 mailTemplateId= fields[2].GetUInt16();
- uint32 sender = fields[3].GetUInt32();
- std::string subject = fields[4].GetString();
- std::string body = fields[5].GetString();
- uint32 money = fields[6].GetUInt32();
- bool has_items = fields[7].GetBool();
+ uint32 mail_id = mailFields[0].GetUInt32();
+ uint8 mailType = mailFields[1].GetUInt8();
+ uint16 mailTemplateId= mailFields[2].GetUInt16();
+ uint32 sender = mailFields[3].GetUInt32();
+ std::string subject = mailFields[4].GetString();
+ std::string body = mailFields[5].GetString();
+ uint32 money = mailFields[6].GetUInt32();
+ bool has_items = mailFields[7].GetBool();
// We can return mail now
// So firstly delete the old one
@@ -4862,9 +4864,9 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC
{
do
{
- Field* fields2 = resultItems->Fetch();
- uint32 item_guidlow = fields2[11].GetUInt32();
- uint32 item_template = fields2[12].GetUInt32();
+ Field* itemFields = resultItems->Fetch();
+ uint32 item_guidlow = itemFields[11].GetUInt32();
+ uint32 item_template = itemFields[12].GetUInt32();
ItemTemplate const* itemProto = sObjectMgr->GetItemTemplate(item_template);
if (!itemProto)
@@ -4876,7 +4878,7 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC
}
Item* pItem = NewItemOrBag(itemProto);
- if (!pItem->LoadFromDB(item_guidlow, MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER), fields, item_template))
+ if (!pItem->LoadFromDB(item_guidlow, MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER), itemFields, item_template))
{
pItem->FSetState(ITEM_REMOVED);
pItem->SaveToDB(trans); // it also deletes item object!
@@ -6827,11 +6829,6 @@ bool Player::UpdatePosition(float x, float y, float z, float orientation, bool t
if (GetGroup())
SetGroupUpdateFlag(GROUP_UPDATE_FLAG_POSITION);
- // code block for underwater state update
- // Unit::UpdatePosition() checks for validity and updates our coordinates
- // so we re-fetch them instead of using "raw" coordinates from function params
- UpdateUnderwaterState(GetMap(), GetPositionX(), GetPositionY(), GetPositionZ());
-
if (GetTrader() && !IsWithinDistInMap(GetTrader(), INTERACTION_DISTANCE))
GetSession()->SendCancelTrade();
@@ -8196,6 +8193,10 @@ void Player::_ApplyWeaponDependentAuraMods(Item* item, WeaponAttackType attackTy
void Player::_ApplyWeaponDependentAuraCritMod(Item* item, WeaponAttackType attackType, AuraEffect const* aura, bool apply)
{
+ // don't apply mod if item is broken or cannot be used
+ if (item->IsBroken() || !CanUseAttackType(attackType))
+ return;
+
// generic not weapon specific case processes in aura code
if (aura->GetSpellInfo()->EquippedItemClass == -1)
return;
@@ -8209,13 +8210,13 @@ void Player::_ApplyWeaponDependentAuraCritMod(Item* item, WeaponAttackType attac
default: return;
}
- if (!item->IsBroken()&&item->IsFitToSpellRequirements(aura->GetSpellInfo()))
+ if (item->IsFitToSpellRequirements(aura->GetSpellInfo()))
HandleBaseModValue(mod, FLAT_MOD, float (aura->GetAmount()), apply);
}
void Player::_ApplyWeaponDependentAuraDamageMod(Item* item, WeaponAttackType attackType, AuraEffect const* aura, bool apply)
{
- //don't apply mod if item is broken
+ // don't apply mod if item is broken or cannot be used
if (item->IsBroken() || !CanUseAttackType(attackType))
return;
@@ -9216,6 +9217,9 @@ void Player::SendInitWorldStates(uint32 zoneid, uint32 areaid)
case 4100: // The Culling of Stratholme
NumberOfFields = 13;
break;
+ case 4273: // Ulduar
+ NumberOfFields = 10;
+ break;
default:
NumberOfFields = 12;
break;
@@ -9760,6 +9764,16 @@ void Player::SendInitWorldStates(uint32 zoneid, uint32 areaid)
data << uint32(3932) << uint32(0); // 13 WORLDSTATE_TIME_GUARDIAN_SHOW
}
break;
+ // Ulduar
+ case 4273:
+ if (instance && mapid == 603)
+ instance->FillInitialWorldStates(data);
+ else
+ {
+ data << uint32(4132) << uint32(0); // 9 WORLDSTATE_SHOW_CRATES
+ data << uint32(4131) << uint32(0); // 10 WORLDSTATE_CRATES_REVEALED
+ }
+ break;
default:
data << uint32(0x914) << uint32(0x0); // 7
data << uint32(0x913) << uint32(0x0); // 8
@@ -17650,7 +17664,7 @@ void Player::_LoadInventory(PreparedQueryResult result, uint32 timeDiff)
ItemPosCountVec dest;
err = CanStoreItem(itr->second->GetSlot(), slot, dest, item);
if (err == EQUIP_ERR_OK)
- itr->second->StoreItem(slot, item, true);
+ item = StoreItem(dest, item, true);
}
}
@@ -18311,10 +18325,10 @@ void Player::UnbindInstance(BoundInstancesMap::iterator &itr, Difficulty difficu
CharacterDatabase.Execute(stmt);
}
- itr->second.save->RemovePlayer(this); // save can become invalid
if (itr->second.perm)
GetSession()->SendCalendarRaidLockout(itr->second.save, false);
+ itr->second.save->RemovePlayer(this); // save can become invalid
m_boundInstances[difficulty].erase(itr++);
}
}
@@ -19776,7 +19790,11 @@ void Player::SendResetInstanceSuccess(uint32 MapId)
void Player::SendResetInstanceFailed(uint32 reason, uint32 MapId)
{
- // TODO: find what other fail reasons there are besides players in the instance
+ /*reasons for instance reset failure:
+ // 0: There are players inside the instance.
+ // 1: There are players offline in your party.
+ // 2>: There are players in your party attempting to zone into an instance.
+ */
WorldPacket data(SMSG_INSTANCE_RESET_FAILED, 4);
data << uint32(reason);
data << uint32(MapId);
@@ -21144,10 +21162,10 @@ bool Player::BuyItemFromVendorSlot(uint64 vendorguid, uint32 vendorslot, uint32
}
uint32 price = 0;
- if(crItem->IsGoldRequired(pProto) && pProto->BuyPrice > 0) //Assume price cannot be negative (do not know why it is int32)
+ if (crItem->IsGoldRequired(pProto) && pProto->BuyPrice > 0) //Assume price cannot be negative (do not know why it is int32)
{
uint32 maxCount = MAX_MONEY_AMOUNT / pProto->BuyPrice;
- if((uint32)count > maxCount)
+ if ((uint32)count > maxCount)
{
sLog->outError("Player %s tried to buy %u item id %u, causing overflow", GetName(), (uint32)count, pProto->ItemId);
count = (uint8)maxCount;
@@ -25546,3 +25564,27 @@ void Player::SendMovementSetCanTransitionBetweenSwimAndFly(bool apply)
data << uint32(0); //! movement counter
SendDirectMessage(&data);
}
+
+void Player::SendMovementSetHover(bool apply)
+{
+ WorldPacket data(apply ? SMSG_MOVE_SET_HOVER : SMSG_MOVE_UNSET_HOVER, 12);
+ data.append(GetPackGUID());
+ data << uint32(0); //! movement counter
+ SendDirectMessage(&data);
+}
+
+void Player::SendMovementSetWaterWalking(bool apply)
+{
+ WorldPacket data(apply ? SMSG_MOVE_WATER_WALK : SMSG_MOVE_LAND_WALK, 12);
+ data.append(GetPackGUID());
+ data << uint32(0); //! movement counter
+ SendDirectMessage(&data);
+}
+
+void Player::SendMovementSetFeatherFall(bool apply)
+{
+ WorldPacket data(apply ? SMSG_MOVE_FEATHER_FALL : SMSG_MOVE_NORMAL_FALL, 12);
+ data.append(GetPackGUID());
+ data << uint32(0); //! movement counter
+ SendDirectMessage(&data);
+}
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 53b848a89b0..ed887994bca 100755
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -2486,6 +2486,9 @@ class Player : public Unit, public GridObject<Player>
*/
void SendMovementSetCanFly(bool apply);
void SendMovementSetCanTransitionBetweenSwimAndFly(bool apply);
+ void SendMovementSetHover(bool apply);
+ void SendMovementSetWaterWalking(bool apply);
+ void SendMovementSetFeatherFall(bool apply);
bool CanFly() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_CAN_FLY); }
@@ -2822,7 +2825,6 @@ class Player : public Unit, public GridObject<Player>
uint32 m_lastFallTime;
float m_lastFallZ;
- LiquidTypeEntry const* _lastLiquid;
int32 m_MirrorTimer[MAX_TIMERS];
uint8 m_MirrorTimerFlags;
uint8 m_MirrorTimerFlagsLast;
diff --git a/src/server/game/Entities/Unit/StatSystem.cpp b/src/server/game/Entities/Unit/StatSystem.cpp
index 69771129ac9..2da1c1b88cb 100755
--- a/src/server/game/Entities/Unit/StatSystem.cpp
+++ b/src/server/game/Entities/Unit/StatSystem.cpp
@@ -1068,6 +1068,7 @@ void Creature::UpdateDamagePhysical(WeaponAttackType attType)
#define ENTRY_TREANT 1964
#define ENTRY_FIRE_ELEMENTAL 15438
#define ENTRY_GHOUL 26125
+#define ENTRY_BLOODWORM 28017
bool Guardian::UpdateStats(Stats stat)
{
@@ -1229,6 +1230,7 @@ void Guardian::UpdateMaxHealth()
case ENTRY_SUCCUBUS: multiplicator = 9.1f; break;
case ENTRY_FELHUNTER: multiplicator = 9.5f; break;
case ENTRY_FELGUARD: multiplicator = 11.0f; break;
+ case ENTRY_BLOODWORM: multiplicator = 1.0f; break;
default: multiplicator = 10.0f; break;
}
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index d71f8e8dfc3..fb91c3fc9f1 100755
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -252,6 +252,7 @@ m_HostileRefManager(this)
_focusSpell = NULL;
_targetLocked = false;
+ _lastLiquid = NULL;
}
////////////////////////////////////////////////////////////
@@ -459,7 +460,7 @@ void Unit::resetAttackTimer(WeaponAttackType type)
bool Unit::IsWithinCombatRange(const Unit* obj, float dist2compare) const
{
- if (!obj || !IsInMap(obj))
+ if (!obj || !IsInMap(obj) || !InSamePhase(obj))
return false;
float dx = GetPositionX() - obj->GetPositionX();
@@ -475,7 +476,7 @@ bool Unit::IsWithinCombatRange(const Unit* obj, float dist2compare) const
bool Unit::IsWithinMeleeRange(const Unit* obj, float dist) const
{
- if (!obj || !IsInMap(obj))
+ if (!obj || !IsInMap(obj) || !InSamePhase(obj))
return false;
float dx = GetPositionX() - obj->GetPositionX();
@@ -572,6 +573,15 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam
if (IsAIEnabled)
GetAI()->DamageDealt(victim, damage, damagetype);
+ // Signal to pets that their owner was attacked
+ if (victim->GetTypeId() == TYPEID_PLAYER)
+ {
+ Pet* pet = victim->ToPlayer()->GetPet();
+
+ if (pet && pet->isAlive())
+ pet->AI()->OwnerDamagedBy(this);
+ }
+
if (damagetype != NODAMAGE)
{
// interrupting auras with AURA_INTERRUPT_FLAG_DAMAGE before checking !damage (absorbed damage breaks that type of auras)
@@ -1485,7 +1495,7 @@ uint32 Unit::CalcArmorReducedDamage(Unit* victim, const uint32 damage, SpellInfo
}
else
{
- if (ToPlayer() && ToPlayer()->HasItemFitToSpellRequirements((*itr)->GetSpellInfo()))
+ if (ToPlayer()->HasItemFitToSpellRequirements((*itr)->GetSpellInfo()))
bonusPct += (*itr)->GetAmount();
}
}
@@ -1495,6 +1505,7 @@ uint32 Unit::CalcArmorReducedDamage(Unit* victim, const uint32 damage, SpellInfo
maxArmorPen = float(400 + 85 * victim->getLevel());
else
maxArmorPen = 400 + 85 * victim->getLevel() + 4.5f * 85 * (victim->getLevel() - 59);
+
// Cap armor penetration to this number
maxArmorPen = std::min((armor + maxArmorPen) / 3, armor);
// Figure out how much armor do we ignore
@@ -1531,7 +1542,8 @@ void Unit::CalcAbsorbResist(Unit* victim, SpellSchoolMask schoolMask, DamageEffe
DamageInfo dmgInfo = DamageInfo(this, victim, damage, spellInfo, schoolMask, damagetype);
// Magic damage, check for resists
- if ((schoolMask & SPELL_SCHOOL_MASK_NORMAL) == 0)
+ // Ignore spells that cant be resisted
+ if ((schoolMask & SPELL_SCHOOL_MASK_NORMAL) == 0 && (!spellInfo || (spellInfo->AttributesEx4 & SPELL_ATTR4_IGNORE_RESISTANCES) == 0))
{
float victimResistance = float(victim->GetResistance(schoolMask));
victimResistance += float(GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_TARGET_RESISTANCE, schoolMask));
@@ -3078,6 +3090,48 @@ bool Unit::IsUnderWater() const
return GetBaseMap()->IsUnderWater(GetPositionX(), GetPositionY(), GetPositionZ());
}
+void Unit::UpdateUnderwaterState(Map* m, float x, float y, float z)
+{
+ if (!isPet() && !IsVehicle())
+ return;
+
+ LiquidData liquid_status;
+ ZLiquidStatus res = m->getLiquidStatus(x, y, z, MAP_ALL_LIQUIDS, &liquid_status);
+ if (!res)
+ {
+ if (_lastLiquid && _lastLiquid->SpellId)
+ RemoveAurasDueToSpell(_lastLiquid->SpellId);
+
+ RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_NOT_UNDERWATER);
+ _lastLiquid = NULL;
+ return;
+ }
+
+ if (uint32 liqEntry = liquid_status.entry)
+ {
+ LiquidTypeEntry const* liquid = sLiquidTypeStore.LookupEntry(liqEntry);
+ if (_lastLiquid && _lastLiquid->SpellId && _lastLiquid->Id != liqEntry)
+ RemoveAurasDueToSpell(_lastLiquid->SpellId);
+
+ if (liquid && liquid->SpellId)
+ {
+ if (res & (LIQUID_MAP_UNDER_WATER | LIQUID_MAP_IN_WATER))
+ CastSpell(this, liquid->SpellId, true);
+ else
+ RemoveAurasDueToSpell(liquid->SpellId);
+ }
+
+ RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_NOT_ABOVEWATER);
+ _lastLiquid = liquid;
+ }
+ else if (_lastLiquid && _lastLiquid->SpellId)
+ {
+ RemoveAurasDueToSpell(_lastLiquid->SpellId);
+ RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_NOT_UNDERWATER);
+ _lastLiquid = NULL;
+ }
+}
+
void Unit::DeMorph()
{
SetDisplayId(GetNativeDisplayId());
@@ -3597,8 +3651,9 @@ void Unit::RemoveAurasDueToSpellByDispel(uint32 spellId, uint32 dispellerSpellId
{
// final heal
int32 healAmount = aurEff->GetAmount();
- int32 stack = dispelInfo.GetRemovedCharges();
- CastCustomSpell(this, 33778, &healAmount, &stack, NULL, true, NULL, NULL, aura->GetCasterGUID());
+ if (Unit* caster = aura->GetCaster())
+ healAmount = caster->SpellHealingBonus(this, aura->GetSpellInfo(), healAmount, HEAL, dispelInfo.GetRemovedCharges());
+ CastCustomSpell(this, 33778, &healAmount, NULL, NULL, true, NULL, NULL, aura->GetCasterGUID());
// mana
if (Unit* caster = aura->GetCaster())
@@ -4488,7 +4543,7 @@ float Unit::GetTotalAuraMultiplierByMiscValue(AuraType auratype, int32 misc_valu
if (!sSpellMgr->AddSameEffectStackRuleSpellGroups((*i)->GetSpellInfo(), (*i)->GetAmount(), SameEffectSpellGroup))
AddPctN(multiplier, (*i)->GetAmount());
}
-
+
for (std::map<SpellGroup, int32>::const_iterator itr = SameEffectSpellGroup.begin(); itr != SameEffectSpellGroup.end(); ++itr)
AddPctN(multiplier, itr->second);
@@ -4535,7 +4590,7 @@ int32 Unit::GetTotalAuraModifierByAffectMask(AuraType auratype, SpellInfo const*
if (!sSpellMgr->AddSameEffectStackRuleSpellGroups((*i)->GetSpellInfo(), (*i)->GetAmount(), SameEffectSpellGroup))
modifier += (*i)->GetAmount();
}
-
+
for (std::map<SpellGroup, int32>::const_iterator itr = SameEffectSpellGroup.begin(); itr != SameEffectSpellGroup.end(); ++itr)
modifier += itr->second;
@@ -5741,7 +5796,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
// Glyph of Polymorph
case 56375:
{
- if(!target)
+ if (!target)
return false;
target->RemoveAurasByType(SPELL_AURA_PERIODIC_DAMAGE, 0, target->GetAura(32409)); // SW:D shall not be removed.
target->RemoveAurasByType(SPELL_AURA_PERIODIC_DAMAGE_PERCENT);
@@ -5800,7 +5855,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
// Blessing of Ancient Kings (Val'anyr, Hammer of Ancient Kings)
case 64411:
{
- if(!victim)
+ if (!victim)
return false;
basepoints0 = int32(CalculatePctN(damage, 15));
if (AuraEffect* aurEff = victim->GetAuraEffect(64413, 0, GetGUID()))
@@ -5988,6 +6043,8 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
// Siphon Life
case 63108:
{
+ if (!damage)
+ break;
// Glyph of Siphon Life
if (HasAura(56216))
triggerAmount += triggerAmount / 4;
@@ -6111,7 +6168,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
// Divine Aegis
if (dummySpell->SpellIconID == 2820)
{
- if(!target)
+ if (!target)
return false;
// Multiple effects stack, so let's try to find this aura.
@@ -6281,7 +6338,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
// Glyph of Shred
case 54815:
{
- if(!target)
+ if (!target)
return false;
// try to find spell Rip on the target
@@ -6587,7 +6644,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
// Explosive Shot
if (procSpell->SpellFamilyFlags[2] & 0x200)
{
- if(!victim)
+ if (!victim)
return false;
if (AuraEffect const* pEff = victim->GetAuraEffect(SPELL_AURA_PERIODIC_DUMMY, SPELLFAMILY_HUNTER, 0x0, 0x80000000, 0x0, GetGUID()))
basepoints0 = pEff->GetSpellInfo()->CalcPowerCost(this, SpellSchoolMask(pEff->GetSpellInfo()->SchoolMask)) * 4/10/3;
@@ -7342,20 +7399,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
triggered_spell_id = 63685;
break;
}
- // Storm, Earth and Fire
- if (dummySpell->SpellIconID == 3063)
- {
- // Earthbind Totem summon only
- if (procSpell->Id != 2484)
- return false;
-
- float chance = (float)triggerAmount;
- if (!roll_chance_f(chance))
- return false;
-
- triggered_spell_id = 64695;
- break;
- }
// Ancestral Awakening
if (dummySpell->SpellIconID == 3065)
{
@@ -7384,8 +7427,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
if (GetTypeId() != TYPEID_PLAYER || !victim || !victim->isAlive() || !castItem || !castItem->IsEquipped())
return false;
- Player* player = ToPlayer();
- WeaponAttackType attType = WeaponAttackType(player->GetAttackBySlot(castItem->GetSlot()));
+ WeaponAttackType attType = WeaponAttackType(Player::GetAttackBySlot(castItem->GetSlot()));
if ((attType != BASE_ATTACK && attType != OFF_ATTACK)
|| (attType == BASE_ATTACK && procFlag & PROC_FLAG_DONE_OFFHAND_ATTACK)
|| (attType == OFF_ATTACK && procFlag & PROC_FLAG_DONE_MAINHAND_ATTACK))
@@ -7973,11 +8015,7 @@ bool Unit::HandleAuraProc(Unit* victim, uint32 damage, Aura* triggeredByAura, Sp
for (uint8 i = 1; i < stack; ++i)
dmg += mod * stack;
if (Unit* caster = triggeredByAura->GetCaster())
- {
caster->CastCustomSpell(70701, SPELLVALUE_BASE_POINT0, dmg);
- if (Creature* creature = caster->ToCreature())
- creature->DespawnOrUnsummon(1);
- }
break;
}
// Ball of Flames Proc
@@ -8188,6 +8226,16 @@ bool Unit::HandleAuraProc(Unit* victim, uint32 damage, Aura* triggeredByAura, Sp
CastCustomSpell(this, 70845, &basepoints0, NULL, NULL, true);
break;
}
+ // Recklessness
+ case 1719:
+ {
+ //! Possible hack alert
+ //! Don't drop charges on proc, they will be dropped on SpellMod removal
+ //! Before this change, it was dropping two charges per attack, one in ProcDamageAndSpellFor, and one in RemoveSpellMods.
+ //! The reason of this behaviour is Recklessness having three auras, 2 of them can not proc (isTriggeredAura array) but the other one can, making the whole spell proc.
+ *handled = true;
+ break;
+ }
default:
break;
}
@@ -8311,6 +8359,12 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
RemoveAuraFromStack(auraSpellInfo->Id);
return false;
}
+ if (auraSpellInfo->Id == 50720)
+ {
+ target = triggeredByAura->GetCaster();
+ if (!target)
+ return false;
+ }
break;
case SPELLFAMILY_WARLOCK:
{
@@ -8663,6 +8717,26 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
}
break;
}
+ case SPELLFAMILY_ROGUE:
+ {
+ switch (auraSpellInfo->Id)
+ {
+ // Rogue T10 2P bonus, should only proc on caster
+ case 70805:
+ {
+ if (victim != this)
+ return false;
+ break;
+ }
+ // Rogue T10 4P bonus, should proc on victim
+ case 70803:
+ {
+ target = victim;
+ break;
+ }
+ }
+ break;
+ }
default:
break;
}
@@ -8827,7 +8901,7 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
}
// Blade Barrier
- if (auraSpellInfo->SpellFamilyName == SPELLFAMILY_DEATHKNIGHT && auraSpellInfo->SpellIconID == 85)
+ if (auraSpellInfo->SpellFamilyName == SPELLFAMILY_DEATHKNIGHT && auraSpellInfo->SpellIconID == 85 && procSpell)
{
Player* player = ToPlayer();
if (!player || player->getClass() != CLASS_DEATH_KNIGHT)
@@ -9515,6 +9589,16 @@ bool Unit::Attack(Unit* victim, bool meleeAttack)
if (meleeAttack)
SendMeleeAttackStart(victim);
+ // Let the pet know we've started attacking someting. Handles melee attacks only
+ // Spells such as auto-shot and others handled in WorldSession::HandleCastSpellOpcode
+ if (this->GetTypeId() == TYPEID_PLAYER)
+ {
+ Pet* playerPet = this->ToPlayer()->GetPet();
+
+ if (playerPet && playerPet->isAlive())
+ playerPet->AI()->OwnerAttacked(victim);
+ }
+
return true;
}
@@ -12487,6 +12571,12 @@ bool Unit::IsAlwaysVisibleFor(WorldObject const* seer) const
if (seer->GetGUID() == guid)
return true;
+ if (Player const* seerPlayer = seer->ToPlayer())
+ if (Unit* owner = GetOwner())
+ if (Player* ownerPlayer = owner->ToPlayer())
+ if (ownerPlayer->IsGroupVisibleFor(seerPlayer))
+ return true;
+
return false;
}
@@ -14911,7 +15001,7 @@ Unit* Unit::SelectNearbyTarget(Unit* exclude, float dist) const
return NULL;
// select random
- return SelectRandomContainerElement(targets);
+ return Trinity::Containers::SelectRandomContainerElement(targets);
}
void Unit::ApplyAttackTimePercentMod(WeaponAttackType att, float val, bool apply)
@@ -17208,6 +17298,9 @@ bool Unit::UpdatePosition(float x, float y, float z, float orientation, bool tel
else if (turn)
UpdateOrientation(orientation);
+ // code block for underwater state update
+ UpdateUnderwaterState(GetMap(), x, y, z);
+
return (relocated || turn);
}
@@ -17512,7 +17605,7 @@ bool Unit::SetWalk(bool enable)
return true;
}
-bool Unit::SetDisableGravity(bool disable)
+bool Unit::SetDisableGravity(bool disable, bool /*packetOnly = false*/)
{
if (disable == IsLevitating())
return false;
@@ -17553,26 +17646,35 @@ bool Unit::SetHover(bool enable)
void Unit::SendMovementHover()
{
+ if (GetTypeId() == TYPEID_PLAYER)
+ ToPlayer()->SendMovementSetHover(HasUnitMovementFlag(MOVEMENTFLAG_HOVER));
+
WorldPacket data(MSG_MOVE_HOVER, 64);
data.append(GetPackGUID());
BuildMovementPacket(&data);
- SendMessageToSet(&data, true);
+ SendMessageToSet(&data, false);
}
void Unit::SendMovementWaterWalking()
{
+ if (GetTypeId() == TYPEID_PLAYER)
+ ToPlayer()->SendMovementSetWaterWalking(HasUnitMovementFlag(MOVEMENTFLAG_WATERWALKING));
+
WorldPacket data(MSG_MOVE_WATER_WALK, 64);
data.append(GetPackGUID());
BuildMovementPacket(&data);
- SendMessageToSet(&data, true);
+ SendMessageToSet(&data, false);
}
void Unit::SendMovementFeatherFall()
{
+ if (GetTypeId() == TYPEID_PLAYER)
+ ToPlayer()->SendMovementSetFeatherFall(HasUnitMovementFlag(MOVEMENTFLAG_FALLING_SLOW));
+
WorldPacket data(MSG_MOVE_FEATHER_FALL, 64);
data.append(GetPackGUID());
BuildMovementPacket(&data);
- SendMessageToSet(&data, true);
+ SendMessageToSet(&data, false);
}
void Unit::SendMovementGravityChange()
@@ -17580,7 +17682,7 @@ void Unit::SendMovementGravityChange()
WorldPacket data(MSG_MOVE_GRAVITY_CHNG, 64);
data.append(GetPackGUID());
BuildMovementPacket(&data);
- SendMessageToSet(&data, true);
+ SendMessageToSet(&data, false);
}
void Unit::SendMovementCanFlyChange()
@@ -17605,5 +17707,5 @@ void Unit::SendMovementCanFlyChange()
WorldPacket data(MSG_MOVE_UPDATE_CAN_FLY, 64);
data.append(GetPackGUID());
BuildMovementPacket(&data);
- SendMessageToSet(&data, true);
+ SendMessageToSet(&data, false);
}
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index fcbe1afa389..5a6276d3b0c 100755
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -707,6 +707,9 @@ enum MovementFlags
MOVEMENTFLAG_MASK_TURNING =
MOVEMENTFLAG_LEFT | MOVEMENTFLAG_RIGHT,
+ MOVEMENTFLAG_MASK_MOVING_FLY =
+ MOVEMENTFLAG_FLYING | MOVEMENTFLAG_ASCENDING | MOVEMENTFLAG_DESCENDING,
+
//! TODO if needed: add more flags to this masks that are exclusive to players
MOVEMENTFLAG_MASK_PLAYER_ONLY =
MOVEMENTFLAG_FLYING,
@@ -1577,6 +1580,7 @@ class Unit : public WorldObject
virtual bool IsInWater() const;
virtual bool IsUnderWater() const;
+ virtual void UpdateUnderwaterState(Map* m, float x, float y, float z);
bool isInAccessiblePlaceFor(Creature const* c) const;
void SendHealSpellLog(Unit* victim, uint32 SpellID, uint32 Damage, uint32 OverHeal, uint32 Absorb, bool critical = false);
@@ -1644,7 +1648,7 @@ class Unit : public WorldObject
bool IsLevitating() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY);}
bool IsWalking() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_WALKING);}
virtual bool SetWalk(bool enable);
- virtual bool SetDisableGravity(bool disable);
+ virtual bool SetDisableGravity(bool disable, bool packetOnly = false);
bool SetHover(bool enable);
void SetInFront(Unit const* target);
@@ -2316,6 +2320,7 @@ class Unit : public WorldObject
Vehicle* m_vehicleKit;
uint32 m_unitTypeMask;
+ LiquidTypeEntry const* _lastLiquid;
bool IsAlwaysVisibleFor(WorldObject const* seer) const;
bool IsAlwaysDetectableFor(WorldObject const* seer) const;
diff --git a/src/server/game/Entities/Vehicle/Vehicle.cpp b/src/server/game/Entities/Vehicle/Vehicle.cpp
index f3d6e8abc79..4ce05ff40d3 100755
--- a/src/server/game/Entities/Vehicle/Vehicle.cpp
+++ b/src/server/game/Entities/Vehicle/Vehicle.cpp
@@ -453,11 +453,12 @@ void Vehicle::RelocatePassengers(float x, float y, float z, float ang)
void Vehicle::Dismiss()
{
+ if (GetBase()->GetTypeId() != TYPEID_UNIT)
+ return;
+
sLog->outDebug(LOG_FILTER_VEHICLES, "Vehicle::Dismiss Entry: %u, GuidLow %u", _creatureEntry, _me->GetGUIDLow());
Uninstall();
- _me->DestroyForNearbyPlayers();
- _me->CombatStop();
- _me->AddObjectToRemoveList();
+ GetBase()->ToCreature()->DespawnOrUnsummon();
}
void Vehicle::InitMovementInfoForBase()
diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h
index 0f2b2382007..f81e7f1f074 100755
--- a/src/server/game/Globals/ObjectMgr.h
+++ b/src/server/game/Globals/ObjectMgr.h
@@ -1025,15 +1025,6 @@ class ObjectMgr
return &itr->second;
}
- bool IsGoOfSpecificEntrySpawned(uint32 entry) const
- {
- for (GameObjectDataContainer::const_iterator it = _gameObjectDataStore.begin(); it != _gameObjectDataStore.end(); ++it)
- if (it->second.id == entry)
- return true;
-
- return false;
- }
-
GameObjectData const* GetGOData(uint32 guid) const
{
GameObjectDataContainer::const_iterator itr = _gameObjectDataStore.find(guid);
diff --git a/src/server/game/Grids/GridStates.h b/src/server/game/Grids/GridStates.h
index 08b66f6bb35..cf649f8d896 100755
--- a/src/server/game/Grids/GridStates.h
+++ b/src/server/game/Grids/GridStates.h
@@ -40,6 +40,7 @@ class GridState
void setMagic() { i_Magic = MAGIC_TESTVAL; }
unsigned int i_Magic;
#endif
+ virtual ~GridState() {};
virtual void Update(Map &, NGridType&, GridInfo &, const uint32 t_diff) const = 0;
};
diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.h b/src/server/game/Grids/Notifiers/GridNotifiers.h
index bb2a9c5130b..e81822e72be 100755
--- a/src/server/game/Grids/Notifiers/GridNotifiers.h
+++ b/src/server/game/Grids/Notifiers/GridNotifiers.h
@@ -797,7 +797,7 @@ namespace Trinity
if (u->GetTypeId() == TYPEID_UNIT && ((Creature*)u)->isTotem())
return false;
- if(!u->isTargetableForAttack(false))
+ if (!u->isTargetableForAttack(false))
return false;
return i_obj->IsWithinDistInMap(u, i_range) && !i_funit->IsFriendlyTo(u);
@@ -1287,7 +1287,7 @@ namespace Trinity
AllWorldObjectsInRange(const WorldObject* object, float maxRange) : m_pObject(object), m_fRange(maxRange) {}
bool operator() (WorldObject* go)
{
- return m_pObject->IsWithinDist(go, m_fRange, false);
+ return m_pObject->IsWithinDist(go, m_fRange, false) && m_pObject->InSamePhase(go);
}
private:
const WorldObject* m_pObject;
diff --git a/src/server/game/Grids/Notifiers/GridNotifiersImpl.h b/src/server/game/Grids/Notifiers/GridNotifiersImpl.h
index 40b3863679b..e3cda4dd76d 100755
--- a/src/server/game/Grids/Notifiers/GridNotifiersImpl.h
+++ b/src/server/game/Grids/Notifiers/GridNotifiersImpl.h
@@ -251,9 +251,8 @@ void Trinity::WorldObjectListSearcher<Check>::Visit(PlayerMapType &m)
return;
for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
- if (itr->getSource()->InSamePhase(i_phaseMask))
- if (i_check(itr->getSource()))
- i_objects.push_back(itr->getSource());
+ if (i_check(itr->getSource()))
+ i_objects.push_back(itr->getSource());
}
template<class Check>
@@ -263,9 +262,8 @@ void Trinity::WorldObjectListSearcher<Check>::Visit(CreatureMapType &m)
return;
for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
- if (itr->getSource()->InSamePhase(i_phaseMask))
- if (i_check(itr->getSource()))
- i_objects.push_back(itr->getSource());
+ if (i_check(itr->getSource()))
+ i_objects.push_back(itr->getSource());
}
template<class Check>
@@ -275,9 +273,8 @@ void Trinity::WorldObjectListSearcher<Check>::Visit(CorpseMapType &m)
return;
for (CorpseMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
- if (itr->getSource()->InSamePhase(i_phaseMask))
- if (i_check(itr->getSource()))
- i_objects.push_back(itr->getSource());
+ if (i_check(itr->getSource()))
+ i_objects.push_back(itr->getSource());
}
template<class Check>
@@ -287,9 +284,8 @@ void Trinity::WorldObjectListSearcher<Check>::Visit(GameObjectMapType &m)
return;
for (GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
- if (itr->getSource()->InSamePhase(i_phaseMask))
- if (i_check(itr->getSource()))
- i_objects.push_back(itr->getSource());
+ if (i_check(itr->getSource()))
+ i_objects.push_back(itr->getSource());
}
template<class Check>
@@ -299,9 +295,8 @@ void Trinity::WorldObjectListSearcher<Check>::Visit(DynamicObjectMapType &m)
return;
for (DynamicObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
- if (itr->getSource()->InSamePhase(i_phaseMask))
- if (i_check(itr->getSource()))
- i_objects.push_back(itr->getSource());
+ if (i_check(itr->getSource()))
+ i_objects.push_back(itr->getSource());
}
// Gameobject searchers
diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp
index 768531b0aea..c7648bf1ccc 100755
--- a/src/server/game/Groups/Group.cpp
+++ b/src/server/game/Groups/Group.cpp
@@ -2136,7 +2136,7 @@ void Group::SetGroupMemberFlag(uint64 guid, bool apply, GroupMemberFlags flag)
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GROUP_MEMBER_FLAG);
stmt->setUInt8(0, slot->flags);
- stmt->setUInt32(0, GUID_LOPART(guid));
+ stmt->setUInt32(1, GUID_LOPART(guid));
CharacterDatabase.Execute(stmt);
diff --git a/src/server/game/Handlers/ItemHandler.cpp b/src/server/game/Handlers/ItemHandler.cpp
index 85694dba630..d537fc5b4aa 100755
--- a/src/server/game/Handlers/ItemHandler.cpp
+++ b/src/server/game/Handlers/ItemHandler.cpp
@@ -1127,9 +1127,9 @@ void WorldSession::HandleWrapItemOpcode(WorldPacket& recv_data)
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_GIFT);
stmt->setUInt32(0, GUID_LOPART(item->GetOwnerGUID()));
- stmt->setUInt32(0, item->GetGUIDLow());
- stmt->setUInt32(0, item->GetEntry());
- stmt->setUInt32(0, item->GetUInt32Value(ITEM_FIELD_FLAGS));
+ stmt->setUInt32(1, item->GetGUIDLow());
+ stmt->setUInt32(2, item->GetEntry());
+ stmt->setUInt32(3, item->GetUInt32Value(ITEM_FIELD_FLAGS));
trans->Append(stmt);
item->SetEntry(gift->GetEntry());
diff --git a/src/server/game/Handlers/LFGHandler.cpp b/src/server/game/Handlers/LFGHandler.cpp
index aea7499aaa9..aa6d208ad3a 100755
--- a/src/server/game/Handlers/LFGHandler.cpp
+++ b/src/server/game/Handlers/LFGHandler.cpp
@@ -525,9 +525,9 @@ void WorldSession::SendLfgBootPlayer(const LfgPlayerBoot* pBoot)
++agreeNum;
}
}
- sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_LFG_BOOT_PLAYER [" UI64FMTD "] inProgress: %u - didVote: %u - agree: %u - victim: [" UI64FMTD "] votes: %u - agrees: %u - left: %u - needed: %u - reason %s",
+ sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_LFG_BOOT_PROPOSAL_UPDATE [" UI64FMTD "] inProgress: %u - didVote: %u - agree: %u - victim: [" UI64FMTD "] votes: %u - agrees: %u - left: %u - needed: %u - reason %s",
guid, uint8(pBoot->inProgress), uint8(playerVote != LFG_ANSWER_PENDING), uint8(playerVote == LFG_ANSWER_AGREE), pBoot->victim, votesNum, agreeNum, secsleft, pBoot->votedNeeded, pBoot->reason.c_str());
- WorldPacket data(SMSG_LFG_BOOT_PLAYER, 1 + 1 + 1 + 8 + 4 + 4 + 4 + 4 + pBoot->reason.length());
+ WorldPacket data(SMSG_LFG_BOOT_PROPOSAL_UPDATE, 1 + 1 + 1 + 8 + 4 + 4 + 4 + 4 + pBoot->reason.length());
data << uint8(pBoot->inProgress); // Vote in progress
data << uint8(playerVote != LFG_ANSWER_PENDING); // Did Vote
data << uint8(playerVote == LFG_ANSWER_AGREE); // Agree
diff --git a/src/server/game/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp
index 1fa6d9fc0ed..e54bee96b8b 100755
--- a/src/server/game/Handlers/PetHandler.cpp
+++ b/src/server/game/Handlers/PetHandler.cpp
@@ -153,8 +153,6 @@ void WorldSession::HandlePetActionHelper(Unit* pet, uint64 guid1, uint16 spellid
switch (spellid)
{
case COMMAND_STAY: //flat=1792 //STAY
- pet->AttackStop();
- pet->InterruptNonMeleeSpells(false);
pet->StopMoving();
pet->GetMotionMaster()->Clear(false);
pet->GetMotionMaster()->MoveIdle();
diff --git a/src/server/game/Handlers/TicketHandler.cpp b/src/server/game/Handlers/TicketHandler.cpp
index 9c4eba67426..d6675188f6e 100755
--- a/src/server/game/Handlers/TicketHandler.cpp
+++ b/src/server/game/Handlers/TicketHandler.cpp
@@ -176,6 +176,8 @@ void WorldSession::HandleReportLag(WorldPacket& recv_data)
stmt->setFloat (3, x);
stmt->setFloat (4, y);
stmt->setFloat (5, z);
+ stmt->setUInt32(6, GetLatency());
+ stmt->setUInt32(7, time(NULL));
CharacterDatabase.Execute(stmt);
}
diff --git a/src/server/game/Instances/InstanceSaveMgr.cpp b/src/server/game/Instances/InstanceSaveMgr.cpp
index c17c7edbf0d..8078a91d082 100755
--- a/src/server/game/Instances/InstanceSaveMgr.cpp
+++ b/src/server/game/Instances/InstanceSaveMgr.cpp
@@ -581,17 +581,17 @@ void InstanceSaveManager::_ResetOrWarnAll(uint32 mapid, Difficulty difficulty, b
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_INSTANCE_BY_MAP_DIFF);
stmt->setUInt16(0, uint16(mapid));
- stmt->setUInt8(0, uint8(difficulty));
+ stmt->setUInt8(1, uint8(difficulty));
trans->Append(stmt);
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GROUP_INSTANCE_BY_MAP_DIFF);
stmt->setUInt16(0, uint16(mapid));
- stmt->setUInt8(0, uint8(difficulty));
+ stmt->setUInt8(1, uint8(difficulty));
trans->Append(stmt);
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_INSTANCE_BY_MAP_DIFF);
stmt->setUInt16(0, uint16(mapid));
- stmt->setUInt8(0, uint8(difficulty));
+ stmt->setUInt8(1, uint8(difficulty));
trans->Append(stmt);
CharacterDatabase.CommitTransaction(trans);
diff --git a/src/server/game/Loot/LootMgr.cpp b/src/server/game/Loot/LootMgr.cpp
index 1b349b11156..75065158ef6 100755
--- a/src/server/game/Loot/LootMgr.cpp
+++ b/src/server/game/Loot/LootMgr.cpp
@@ -1526,7 +1526,7 @@ void LoadLootTemplates_Gameobject()
{
if (uint32 lootid = itr->second.GetLootId())
{
- if (sObjectMgr->IsGoOfSpecificEntrySpawned(itr->second.entry) && lootIdSet.find(lootid) == lootIdSet.end())
+ if (lootIdSet.find(lootid) == lootIdSet.end())
LootTemplates_Gameobject.ReportNotExistedId(lootid);
else
lootIdSetUsed.insert(lootid);
diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp
index f60a8f20c1c..a1b3d913c99 100755
--- a/src/server/game/Maps/Map.cpp
+++ b/src/server/game/Maps/Map.cpp
@@ -787,20 +787,20 @@ void Map::RemoveCreatureFromMoveList(Creature* c)
void Map::MoveAllCreaturesInMoveList()
{
_creatureToMoveLock = true;
- for(std::vector<Creature*>::iterator itr = _creaturesToMove.begin(); itr != _creaturesToMove.end(); ++itr)
+ for (std::vector<Creature*>::iterator itr = _creaturesToMove.begin(); itr != _creaturesToMove.end(); ++itr)
{
Creature* c = *itr;
- if(c->FindMap() != this) //pet is teleported to another map
+ if (c->FindMap() != this) //pet is teleported to another map
continue;
- if(c->_moveState != CREATURE_CELL_MOVE_ACTIVE)
+ if (c->_moveState != CREATURE_CELL_MOVE_ACTIVE)
{
c->_moveState = CREATURE_CELL_MOVE_NONE;
continue;
}
c->_moveState = CREATURE_CELL_MOVE_NONE;
- if(!c->IsInWorld())
+ if (!c->IsInWorld())
continue;
// do move or do move to respawn or remove creature if previous all fail
diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h
index 766e3d23f93..6ba08646f25 100755
--- a/src/server/game/Maps/Map.h
+++ b/src/server/game/Maps/Map.h
@@ -228,7 +228,7 @@ enum LevelRequirementVsMode
#define MAX_HEIGHT 100000.0f // can be use for find ground height at surface
#define INVALID_HEIGHT -100000.0f // for check, must be equal to VMAP_INVALID_HEIGHT, real value for unknown height is VMAP_INVALID_HEIGHT_VALUE
#define MAX_FALL_DISTANCE 250000.0f // "unlimited fall" to find VMap ground if it is available, just larger than MAX_HEIGHT - INVALID_HEIGHT
-#define DEFAULT_HEIGHT_SEARCH 10.0f // default search distance to find height at nearby locations
+#define DEFAULT_HEIGHT_SEARCH 50.0f // default search distance to find height at nearby locations
#define MIN_UNLOAD_DELAY 1 // immediate unload
typedef std::map<uint32/*leaderDBGUID*/, CreatureGroup*> CreatureGroupHolderType;
diff --git a/src/server/game/Maps/MapManager.cpp b/src/server/game/Maps/MapManager.cpp
index 0fb28008c1e..eb09538721d 100755
--- a/src/server/game/Maps/MapManager.cpp
+++ b/src/server/game/Maps/MapManager.cpp
@@ -96,32 +96,32 @@ void MapManager::checkAndCorrectGridStatesArray()
Map* MapManager::CreateBaseMap(uint32 id)
{
- Map* m = FindBaseMap(id);
+ Map* map = FindBaseMap(id);
- if (m == NULL)
+ if (map == NULL)
{
TRINITY_GUARD(ACE_Thread_Mutex, Lock);
const MapEntry* entry = sMapStore.LookupEntry(id);
if (entry && entry->Instanceable())
{
- m = new MapInstanced(id, i_gridCleanUpDelay);
+ map = new MapInstanced(id, i_gridCleanUpDelay);
}
else
{
- m = new Map(id, i_gridCleanUpDelay, 0, REGULAR_DIFFICULTY);
+ map = new Map(id, i_gridCleanUpDelay, 0, REGULAR_DIFFICULTY);
}
- i_maps[id] = m;
+ i_maps[id] = map;
}
- ASSERT(m != NULL);
- return m;
+ ASSERT(map);
+ return map;
}
Map* MapManager::FindBaseNonInstanceMap(uint32 mapId) const
{
Map* map = FindBaseMap(mapId);
- if(map && map->Instanceable())
+ if (map && map->Instanceable())
return NULL;
return map;
}
diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h
index 547f1679b61..4b07d19bd7a 100755
--- a/src/server/game/Miscellaneous/Language.h
+++ b/src/server/game/Miscellaneous/Language.h
@@ -522,8 +522,10 @@ enum TrinityStrings
LANG_YOURS_EXPLORE_SET_ALL = 553,
LANG_YOURS_EXPLORE_SET_NOTHING = 554,
- LANG_HOVER_ENABLED = 555,
- LANG_HOVER_DISABLED = 556,
+ //! Old ones now free:
+ // LANG_HOVER_ENABLED = 555,
+ // LANG_HOVER_DISABLED = 556,
+
LANG_YOURS_LEVEL_UP = 557,
LANG_YOURS_LEVEL_DOWN = 558,
LANG_YOURS_LEVEL_PROGRESS_RESET = 559,
diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h
index bca896df38f..06aca10879d 100755
--- a/src/server/game/Miscellaneous/SharedDefines.h
+++ b/src/server/game/Miscellaneous/SharedDefines.h
@@ -269,7 +269,7 @@ enum SpellAttr0
SPELL_ATTR0_UNK0 = 0x00000001, // 0
SPELL_ATTR0_REQ_AMMO = 0x00000002, // 1 on next ranged
SPELL_ATTR0_ON_NEXT_SWING = 0x00000004, // 2
- SPELL_ATTR0_UNK3 = 0x00000008, // 3 not set in 3.0.3
+ SPELL_ATTR0_IS_REPLENISHMENT = 0x00000008, // 3 not set in 3.0.3
SPELL_ATTR0_ABILITY = 0x00000010, // 4 client puts 'ability' instead of 'spell' in game strings for these spells
SPELL_ATTR0_TRADESPELL = 0x00000020, // 5 trade spells (recipes), will be added by client to a sublist of profession spell
SPELL_ATTR0_PASSIVE = 0x00000040, // 6 Passive spell
@@ -314,7 +314,7 @@ enum SpellAttr1
SPELL_ATTR1_MELEE_COMBAT_START = 0x00000200, // 9 player starts melee combat after this spell is cast
SPELL_ATTR1_NO_THREAT = 0x00000400, // 10 no generates threat on cast 100% (old NO_INITIAL_AGGRO)
SPELL_ATTR1_UNK11 = 0x00000800, // 11 aura
- SPELL_ATTR1_UNK12 = 0x00001000, // 12 pickpoket
+ SPELL_ATTR1_IS_PICKPOCKET = 0x00001000, // 12 Pickpocket
SPELL_ATTR1_FARSIGHT = 0x00002000, // 13 Client removes farsight on aura loss
SPELL_ATTR1_CHANNEL_TRACK_TARGET = 0x00004000, // 14 Client automatically forces player to face target when channeling
SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY = 0x00008000, // 15 remove auras on immunity
@@ -326,7 +326,7 @@ enum SpellAttr1
SPELL_ATTR1_UNK21 = 0x00200000, // 21
SPELL_ATTR1_REQ_COMBO_POINTS2 = 0x00400000, // 22 Req combo points on target
SPELL_ATTR1_UNK23 = 0x00800000, // 23
- SPELL_ATTR1_UNK24 = 0x01000000, // 24 only fishing spells
+ SPELL_ATTR1_IS_FISHING = 0x01000000, // 24 only fishing spells
SPELL_ATTR1_UNK25 = 0x02000000, // 25
SPELL_ATTR1_UNK26 = 0x04000000, // 26 works correctly with [target=focus] and [target=mouseover] macros?
SPELL_ATTR1_UNK27 = 0x08000000, // 27 melee spell?
@@ -351,17 +351,17 @@ enum SpellAttr2
SPELL_ATTR2_UNK10 = 0x00000400, // 10 related to tame
SPELL_ATTR2_HEALTH_FUNNEL = 0x00000800, // 11
SPELL_ATTR2_UNK12 = 0x00001000, // 12 Cleave, Heart Strike, Maul, Sunder Armor, Swipe
- SPELL_ATTR2_UNK13 = 0x00002000, // 13 Items enchanted by spells with this flag preserve the enchant to arenas
+ SPELL_ATTR2_PRESERVE_ENCHANT_IN_ARENA = 0x00002000, // 13 Items enchanted by spells with this flag preserve the enchant to arenas
SPELL_ATTR2_UNK14 = 0x00004000, // 14
SPELL_ATTR2_UNK15 = 0x00008000, // 15 not set in 3.0.3
SPELL_ATTR2_TAME_BEAST = 0x00010000, // 16
SPELL_ATTR2_NOT_RESET_AUTO_ACTIONS = 0x00020000, // 17 don't reset timers for melee autoattacks (swings) or ranged autoattacks (autoshoots)
- SPELL_ATTR2_UNK18 = 0x00040000, // 18 Only Revive pet - possible req dead pet
+ SPELL_ATTR2_REQ_DEAD_PET = 0x00040000, // 18 Only Revive pet and Heart of the Pheonix
SPELL_ATTR2_NOT_NEED_SHAPESHIFT = 0x00080000, // 19 does not necessarly need shapeshift
SPELL_ATTR2_UNK20 = 0x00100000, // 20
SPELL_ATTR2_DAMAGE_REDUCED_SHIELD = 0x00200000, // 21 for ice blocks, pala immunity buffs, priest absorb shields, but used also for other spells -> not sure!
SPELL_ATTR2_UNK22 = 0x00400000, // 22 Ambush, Backstab, Cheap Shot, Death Grip, Garrote, Judgements, Mutilate, Pounce, Ravage, Shiv, Shred
- SPELL_ATTR2_UNK23 = 0x00800000, // 23 Only mage Arcane Concentration have this flag
+ SPELL_ATTR2_IS_ARCANE_CONCENTRATION = 0x00800000, // 23 Only mage Arcane Concentration have this flag
SPELL_ATTR2_UNK24 = 0x01000000, // 24
SPELL_ATTR2_UNK25 = 0x02000000, // 25
SPELL_ATTR2_UNK26 = 0x04000000, // 26 unaffected by school immunity
@@ -388,7 +388,7 @@ enum SpellAttr3
SPELL_ATTR3_BATTLEGROUND = 0x00000800, // 11 Can casted only on battleground
SPELL_ATTR3_ONLY_TARGET_GHOSTS = 0x00001000, // 12
SPELL_ATTR3_UNK13 = 0x00002000, // 13
- SPELL_ATTR3_UNK14 = 0x00004000, // 14 "Honorless Target" only this spells have this flag
+ SPELL_ATTR3_IS_HONORLESS_TARGET = 0x00004000, // 14 "Honorless Target" only this spells have this flag
SPELL_ATTR3_UNK15 = 0x00008000, // 15 Auto Shoot, Shoot, Throw, - this is autoshot flag
SPELL_ATTR3_CANT_TRIGGER_PROC = 0x00010000, // 16 confirmed with many patchnotes
SPELL_ATTR3_NO_INITIAL_AGGRO = 0x00020000, // 17 Soothe Animal, 39758, Mind Soothe
@@ -410,8 +410,8 @@ enum SpellAttr3
enum SpellAttr4
{
- SPELL_ATTR4_UNK0 = 0x00000001, // 0
- SPELL_ATTR4_PROC_ONLY_ON_DUMMY = 0x00000002, // 1 proc only on SPELL_EFFECT_DUMMY?
+ SPELL_ATTR4_IGNORE_RESISTANCES = 0x00000001, // 0 spells with this attribute will completely ignore the target's resistance (these spells can't be resisted)
+ SPELL_ATTR4_PROC_ONLY_ON_CASTER = 0x00000002, // 1 proc only on effects with TARGET_UNIT_CASTER?
SPELL_ATTR4_UNK2 = 0x00000004, // 2
SPELL_ATTR4_UNK3 = 0x00000008, // 3
SPELL_ATTR4_UNK4 = 0x00000010, // 4 This will no longer cause guards to attack on use??
@@ -432,16 +432,16 @@ enum SpellAttr4
SPELL_ATTR4_UNK19 = 0x00080000, // 19 proc dalayed, after damage or don't proc on absorb?
SPELL_ATTR4_NOT_CHECK_SELFCAST_POWER = 0x00100000, // 20 supersedes message "More powerful spell applied" for self casts.
SPELL_ATTR4_UNK21 = 0x00200000, // 21 Pally aura, dk presence, dudu form, warrior stance, shadowform, hunter track
- SPELL_ATTR4_UNK22 = 0x00400000, // 22
+ SPELL_ATTR4_UNK22 = 0x00400000, // 22 Seal of Command (42058,57770) and Gymer's Smash 55426
SPELL_ATTR4_UNK23 = 0x00800000, // 23
SPELL_ATTR4_UNK24 = 0x01000000, // 24 some shoot spell
- SPELL_ATTR4_UNK25 = 0x02000000, // 25 pet scaling auras
+ SPELL_ATTR4_IS_PET_SCALING = 0x02000000, // 25 pet scaling auras
SPELL_ATTR4_CAST_ONLY_IN_OUTLAND = 0x04000000, // 26 Can only be used in Outland.
SPELL_ATTR4_UNK27 = 0x08000000, // 27
SPELL_ATTR4_UNK28 = 0x10000000, // 28 Aimed Shot
SPELL_ATTR4_UNK29 = 0x20000000, // 29
SPELL_ATTR4_UNK30 = 0x40000000, // 30
- SPELL_ATTR4_UNK31 = 0x80000000 // 31
+ SPELL_ATTR4_UNK31 = 0x80000000 // 31 Polymorph (chicken) 228 and Sonic Boom (38052,38488)
};
enum SpellAttr5
@@ -461,7 +461,7 @@ enum SpellAttr5
SPELL_ATTR5_UNK12 = 0x00001000, // 12 Cleave related?
SPELL_ATTR5_HASTE_AFFECT_DURATION = 0x00002000, // 13 haste effects decrease duration of this
SPELL_ATTR5_UNK14 = 0x00004000, // 14
- SPELL_ATTR5_UNK15 = 0x00008000, // 15
+ SPELL_ATTR5_UNK15 = 0x00008000, // 15 Inflits on multiple targets?
SPELL_ATTR5_SPECIAL_ITEM_CLASS_CHECK = 0x00010000, // 16 this allows spells with EquippedItemClass to affect spells from other items if the required item is equipped
SPELL_ATTR5_USABLE_WHILE_FEARED = 0x00020000, // 17 usable while feared
SPELL_ATTR5_USABLE_WHILE_CONFUSED = 0x00040000, // 18 usable while confused
@@ -2566,7 +2566,7 @@ enum CreatureTypeFlags
{
CREATURE_TYPEFLAGS_TAMEABLE = 0x00000001, // Tameable by any hunter
CREATURE_TYPEFLAGS_GHOST = 0x00000002, // Creature are also visible for not alive player. Allow gossip interaction if npcflag allow?
- CREATURE_TYPEFLAGS_UNK2 = 0x00000004,
+ CREATURE_TYPEFLAGS_BOSS = 0x00000004,
CREATURE_TYPEFLAGS_UNK3 = 0x00000008,
CREATURE_TYPEFLAGS_UNK4 = 0x00000010,
CREATURE_TYPEFLAGS_UNK5 = 0x00000020,
@@ -3294,20 +3294,20 @@ enum BanReturn
// indexes of BattlemasterList.dbc
enum BattlegroundTypeId
{
- BATTLEGROUND_TYPE_NONE = 0,
- BATTLEGROUND_AV = 1,
- BATTLEGROUND_WS = 2,
- BATTLEGROUND_AB = 3,
- BATTLEGROUND_NA = 4,
- BATTLEGROUND_BE = 5,
- BATTLEGROUND_AA = 6,
- BATTLEGROUND_EY = 7,
- BATTLEGROUND_RL = 8,
- BATTLEGROUND_SA = 9,
- BATTLEGROUND_DS = 10,
- BATTLEGROUND_RV = 11,
- BATTLEGROUND_IC = 30,
- BATTLEGROUND_RB = 32
+ BATTLEGROUND_TYPE_NONE = 0, // None
+ BATTLEGROUND_AV = 1, // Alterac Valley
+ BATTLEGROUND_WS = 2, // Warsong Gulch
+ BATTLEGROUND_AB = 3, // Arathi Basin
+ BATTLEGROUND_NA = 4, // Nagrand Arena
+ BATTLEGROUND_BE = 5, // Blade's Edge Arena
+ BATTLEGROUND_AA = 6, // All Arenas
+ BATTLEGROUND_EY = 7, // Eye of the Storm
+ BATTLEGROUND_RL = 8, // Ruins of Lordaernon
+ BATTLEGROUND_SA = 9, // Strand of the Ancients
+ BATTLEGROUND_DS = 10, // Dalaran Sewers
+ BATTLEGROUND_RV = 11, // Ring of Valor
+ BATTLEGROUND_IC = 30, // Isle of Conquest
+ BATTLEGROUND_RB = 32 // Random Battleground
};
#define MAX_BATTLEGROUND_TYPE_ID 33
diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp
index b8a7ee848ed..c0e1eb842ae 100755
--- a/src/server/game/Movement/MotionMaster.cpp
+++ b/src/server/game/Movement/MotionMaster.cpp
@@ -114,6 +114,9 @@ void MotionMaster::UpdateMotion(uint32 diff)
_cleanFlag &= ~MMCF_RESET;
}
+
+ // probably not the best place to pu this but im not really sure where else to put it.
+ _owner->UpdateUnderwaterState(_owner->GetMap(), _owner->GetPositionX(), _owner->GetPositionY(), _owner->GetPositionZ());
}
void MotionMaster::DirectClean(bool reset)
@@ -383,6 +386,12 @@ void MotionMaster::MoveFall(uint32 id/*=0*/)
if (fabs(_owner->GetPositionZ() - tz) < 0.1f)
return;
+ if (_owner->GetTypeId() == TYPEID_PLAYER)
+ {
+ _owner->AddUnitMovementFlag(MOVEMENTFLAG_FALLING);
+ _owner->m_movementInfo.SetFallTime(0);
+ }
+
Movement::MoveSplineInit init(*_owner);
init.MoveTo(_owner->GetPositionX(), _owner->GetPositionY(), tz);
init.SetFall();
diff --git a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp
index da830a9a49b..54a68f92c66 100755
--- a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp
@@ -32,11 +32,10 @@
template<class T>
void ConfusedMovementGenerator<T>::Initialize(T &unit)
{
- const float wander_distance=4;
- float x,y,z;
- x = unit.GetPositionX();
- y = unit.GetPositionY();
- z = unit.GetPositionZ();
+ float const wander_distance = 4;
+ float x = unit.GetPositionX();
+ float y = unit.GetPositionY();
+ float z = unit.GetPositionZ();
Map const* map = unit.GetBaseMap();
@@ -47,31 +46,42 @@ void ConfusedMovementGenerator<T>::Initialize(T &unit)
for (uint8 idx = 0; idx < MAX_CONF_WAYPOINTS + 1; ++idx)
{
- const float wanderX=wander_distance*(float)rand_norm() - wander_distance/2;
- const float wanderY=wander_distance*(float)rand_norm() - wander_distance/2;
-
- i_waypoints[idx][0] = x + wanderX;
- i_waypoints[idx][1] = y + wanderY;
+ float wanderX = x + (wander_distance * (float)rand_norm() - wander_distance/2);
+ float wanderY = y + (wander_distance * (float)rand_norm() - wander_distance/2);
// prevent invalid coordinates generation
- Trinity::NormalizeMapCoord(i_waypoints[idx][0]);
- Trinity::NormalizeMapCoord(i_waypoints[idx][1]);
+ Trinity::NormalizeMapCoord(wanderX);
+ Trinity::NormalizeMapCoord(wanderY);
- bool is_water = map->IsInWater(i_waypoints[idx][0],i_waypoints[idx][1],z);
- // if generated wrong path just ignore
- if ((is_water && !is_water_ok) || (!is_water && !is_land_ok))
+ if (unit.IsWithinLOS(wanderX, wanderY, z))
+ {
+ bool is_water = map->IsInWater(wanderX, wanderY, z);
+
+ if ((is_water && !is_water_ok) || (!is_water && !is_land_ok))
+ {
+ //! Cannot use coordinates outside our InhabitType. Use the current or previous position.
+ wanderX = idx > 0 ? i_waypoints[idx-1][0] : x;
+ wanderY = idx > 0 ? i_waypoints[idx-1][1] : y;
+ }
+ }
+ else
{
- i_waypoints[idx][0] = idx > 0 ? i_waypoints[idx-1][0] : x;
- i_waypoints[idx][1] = idx > 0 ? i_waypoints[idx-1][1] : y;
+ //! Trying to access path outside line of sight. Skip this by using the current or previous position.
+ wanderX = idx > 0 ? i_waypoints[idx-1][0] : x;
+ wanderY = idx > 0 ? i_waypoints[idx-1][1] : y;
}
- unit.UpdateAllowedPositionZ(i_waypoints[idx][0], i_waypoints[idx][1], z);
+ unit.UpdateAllowedPositionZ(wanderX, wanderY, z);
+
+ //! Positions are fine - apply them to this waypoint
+ i_waypoints[idx][0] = wanderX;
+ i_waypoints[idx][1] = wanderY;
i_waypoints[idx][2] = z;
}
unit.StopMoving();
unit.SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CONFUSED);
- unit.AddUnitState(UNIT_STATE_CONFUSED|UNIT_STATE_CONFUSED_MOVE);
+ unit.AddUnitState(UNIT_STATE_CONFUSED | UNIT_STATE_CONFUSED_MOVE);
}
template<>
@@ -94,7 +104,7 @@ void ConfusedMovementGenerator<T>::Reset(T &unit)
i_nextMove = 1;
i_nextMoveTime.Reset(0);
unit.StopMoving();
- unit.AddUnitState(UNIT_STATE_CONFUSED|UNIT_STATE_CONFUSED_MOVE);
+ unit.AddUnitState(UNIT_STATE_CONFUSED | UNIT_STATE_CONFUSED_MOVE);
}
template<class T>
@@ -110,8 +120,8 @@ bool ConfusedMovementGenerator<T>::Update(T &unit, const uint32 &diff)
if (unit.movespline->Finalized())
{
- i_nextMove = urand(1,MAX_CONF_WAYPOINTS);
- i_nextMoveTime.Reset(urand(0, 1500-1)); // TODO: check the minimum reset time, should be probably higher
+ i_nextMove = urand(1, MAX_CONF_WAYPOINTS);
+ i_nextMoveTime.Reset(urand(500, 1200)); // Guessed
}
}
else
@@ -123,7 +133,7 @@ bool ConfusedMovementGenerator<T>::Update(T &unit, const uint32 &diff)
// start moving
unit.AddUnitState(UNIT_STATE_CONFUSED_MOVE);
- ASSERT( i_nextMove <= MAX_CONF_WAYPOINTS );
+ ASSERT(i_nextMove <= MAX_CONF_WAYPOINTS);
float x = i_waypoints[i_nextMove][0];
float y = i_waypoints[i_nextMove][1];
float z = i_waypoints[i_nextMove][2];
@@ -141,14 +151,14 @@ template<>
void ConfusedMovementGenerator<Player>::Finalize(Player &unit)
{
unit.RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CONFUSED);
- unit.ClearUnitState(UNIT_STATE_CONFUSED|UNIT_STATE_CONFUSED_MOVE);
+ unit.ClearUnitState(UNIT_STATE_CONFUSED | UNIT_STATE_CONFUSED_MOVE);
}
template<>
void ConfusedMovementGenerator<Creature>::Finalize(Creature &unit)
{
unit.RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CONFUSED);
- unit.ClearUnitState(UNIT_STATE_CONFUSED|UNIT_STATE_CONFUSED_MOVE);
+ unit.ClearUnitState(UNIT_STATE_CONFUSED | UNIT_STATE_CONFUSED_MOVE);
if (unit.getVictim())
unit.SetTarget(unit.getVictim()->GetGUID());
}
diff --git a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.h b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.h
index b9f96bb785d..7f2226ea069 100755
--- a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.h
+++ b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.h
@@ -22,11 +22,10 @@
#include "MovementGenerator.h"
#include "Timer.h"
-#define MAX_CONF_WAYPOINTS 24
+#define MAX_CONF_WAYPOINTS 24 //! Allows a twelve second confusion if i_nextMove always is the absolute minimum timer.
template<class T>
-class ConfusedMovementGenerator
-: public MovementGeneratorMedium< T, ConfusedMovementGenerator<T> >
+class ConfusedMovementGenerator : public MovementGeneratorMedium< T, ConfusedMovementGenerator<T> >
{
public:
explicit ConfusedMovementGenerator() : i_nextMoveTime(0) {}
diff --git a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp
index 7de5f1095c4..08e27abf050 100755
--- a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp
@@ -28,8 +28,7 @@
#define MAX_QUIET_DISTANCE 43.0f
template<class T>
-void
-FleeingMovementGenerator<T>::_setTargetLocation(T &owner)
+void FleeingMovementGenerator<T>::_setTargetLocation(T &owner)
{
if (!&owner)
return;
@@ -53,8 +52,7 @@ FleeingMovementGenerator<T>::_setTargetLocation(T &owner)
}
template<class T>
-bool
-FleeingMovementGenerator<T>::_getPoint(T &owner, float &x, float &y, float &z)
+bool FleeingMovementGenerator<T>::_getPoint(T &owner, float &x, float &y, float &z)
{
if (!&owner)
return false;
@@ -65,8 +63,8 @@ FleeingMovementGenerator<T>::_getPoint(T &owner, float &x, float &y, float &z)
float temp_x, temp_y, angle;
const Map* _map = owner.GetBaseMap();
- //primitive path-finding
- for(uint8 i = 0; i < 18; ++i)
+ // primitive path-finding
+ for (uint8 i = 0; i < 18; ++i)
{
if (i_only_forward && i > 2)
break;
@@ -187,8 +185,7 @@ FleeingMovementGenerator<T>::_getPoint(T &owner, float &x, float &y, float &z)
}
template<class T>
-bool
-FleeingMovementGenerator<T>::_setMoveData(T &owner)
+bool FleeingMovementGenerator<T>::_setMoveData(T &owner)
{
float cur_dist_xyz = owner.GetDistance(i_caster_x, i_caster_y, i_caster_z);
@@ -280,8 +277,7 @@ FleeingMovementGenerator<T>::_setMoveData(T &owner)
}
template<class T>
-void
-FleeingMovementGenerator<T>::Initialize(T &owner)
+void FleeingMovementGenerator<T>::Initialize(T &owner)
{
if (!&owner)
return;
@@ -312,8 +308,7 @@ FleeingMovementGenerator<T>::Initialize(T &owner)
}
template<>
-void
-FleeingMovementGenerator<Creature>::_Init(Creature &owner)
+void FleeingMovementGenerator<Creature>::_Init(Creature &owner)
{
if (!&owner)
return;
@@ -324,8 +319,7 @@ FleeingMovementGenerator<Creature>::_Init(Creature &owner)
}
template<>
-void
-FleeingMovementGenerator<Player>::_Init(Player &)
+void FleeingMovementGenerator<Player>::_Init(Player &)
{
is_water_ok = true;
is_land_ok = true;
@@ -354,8 +348,7 @@ void FleeingMovementGenerator<T>::Reset(T &owner)
}
template<class T>
-bool
-FleeingMovementGenerator<T>::Update(T &owner, const uint32 &time_diff)
+bool FleeingMovementGenerator<T>::Update(T &owner, const uint32 &time_diff)
{
if (!&owner || !owner.isAlive())
return false;
diff --git a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.h b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.h
index f795a002821..aec93ad3375 100755
--- a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.h
+++ b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.h
@@ -22,8 +22,7 @@
#include "MovementGenerator.h"
template<class T>
-class FleeingMovementGenerator
-: public MovementGeneratorMedium< T, FleeingMovementGenerator<T> >
+class FleeingMovementGenerator : public MovementGeneratorMedium< T, FleeingMovementGenerator<T> >
{
public:
FleeingMovementGenerator(uint64 fright) : i_frightGUID(fright), i_nextCheckTime(0) {}
@@ -55,8 +54,7 @@ class FleeingMovementGenerator
TimeTracker i_nextCheckTime;
};
-class TimedFleeingMovementGenerator
-: public FleeingMovementGenerator<Creature>
+class TimedFleeingMovementGenerator : public FleeingMovementGenerator<Creature>
{
public:
TimedFleeingMovementGenerator(uint64 fright, uint32 time) :
diff --git a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.h b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.h
index c724edc91ff..95eb05f281c 100755
--- a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.h
+++ b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.h
@@ -27,8 +27,7 @@ template < class T >
class HomeMovementGenerator;
template <>
-class HomeMovementGenerator<Creature>
-: public MovementGeneratorMedium< Creature, HomeMovementGenerator<Creature> >
+class HomeMovementGenerator<Creature> : public MovementGeneratorMedium< Creature, HomeMovementGenerator<Creature> >
{
public:
diff --git a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp
index 91b50344ccb..a922c937b5f 100755
--- a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp
@@ -46,7 +46,7 @@ bool PointMovementGenerator<T>::Update(T &unit, const uint32 & /*diff*/)
if (!&unit)
return false;
- if(unit.HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED))
+ if (unit.HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED))
{
unit.ClearUnitState(UNIT_STATE_ROAMING_MOVE);
return true;
diff --git a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.h b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.h
index 82578da5f9b..13be9fee77b 100755
--- a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.h
+++ b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.h
@@ -23,8 +23,7 @@
#include "FollowerReference.h"
template<class T>
-class PointMovementGenerator
-: public MovementGeneratorMedium< T, PointMovementGenerator<T> >
+class PointMovementGenerator : public MovementGeneratorMedium< T, PointMovementGenerator<T> >
{
public:
PointMovementGenerator(uint32 _id, float _x, float _y, float _z, float _speed = 0.0f) : id(_id),
@@ -46,8 +45,7 @@ class PointMovementGenerator
float speed;
};
-class AssistanceMovementGenerator
-: public PointMovementGenerator<Creature>
+class AssistanceMovementGenerator : public PointMovementGenerator<Creature>
{
public:
AssistanceMovementGenerator(float _x, float _y, float _z) :
diff --git a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp
index e520253eb46..84cd9e88295 100755
--- a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp
@@ -127,8 +127,7 @@ void RandomMovementGenerator<Creature>::Initialize(Creature &creature)
}
template<>
-void
-RandomMovementGenerator<Creature>::Reset(Creature &creature)
+void RandomMovementGenerator<Creature>::Reset(Creature &creature)
{
Initialize(creature);
}
@@ -141,8 +140,7 @@ void RandomMovementGenerator<Creature>::Finalize(Creature &creature)
}
template<>
-bool
-RandomMovementGenerator<Creature>::Update(Creature &creature, const uint32 diff)
+bool RandomMovementGenerator<Creature>::Update(Creature &creature, const uint32 diff)
{
if (creature.HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED | UNIT_STATE_DISTRACTED))
{
diff --git a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.h b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.h
index 67161b6fc29..07ec3647052 100755
--- a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.h
+++ b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.h
@@ -22,8 +22,7 @@
#include "MovementGenerator.h"
template<class T>
-class RandomMovementGenerator
-: public MovementGeneratorMedium< T, RandomMovementGenerator<T> >
+class RandomMovementGenerator : public MovementGeneratorMedium< T, RandomMovementGenerator<T> >
{
public:
RandomMovementGenerator(float spawn_dist = 0.0f) : i_nextMoveTime(0), wander_distance(spawn_dist) {}
diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp
index 6d507a3b694..fdff5a92564 100755
--- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp
@@ -78,7 +78,7 @@ void TargetedMovementGeneratorMedium<T,D>::_setTargetLocation(T &owner)
//We don't update Mob Movement, if the difference between New destination and last destination is < BothObjectSize
float bothObjectSize = i_target->GetObjectBoundingRadius() + owner.GetObjectBoundingRadius() + CONTACT_DISTANCE;
- if( i_destinationHolder.HasDestination() && i_destinationHolder.GetDestinationDiff(x,y,z) < bothObjectSize )
+ if ( i_destinationHolder.HasDestination() && i_destinationHolder.GetDestinationDiff(x,y,z) < bothObjectSize )
return;
*/
@@ -135,7 +135,7 @@ bool TargetedMovementGeneratorMedium<T,D>::Update(T &owner, const uint32 & time_
}
// prevent movement while casting spells with cast time or channel time
- if (owner.IsNonMeleeSpellCasted(false, false, true))
+ if (owner.HasUnitState(UNIT_STATE_CASTING))
{
if (!owner.IsStopped())
owner.StopMoving();
diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h
index b851dbc0e05..29fd73624e1 100755
--- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h
+++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h
@@ -34,8 +34,7 @@ class TargetedMovementGeneratorBase
};
template<class T, typename D>
-class TargetedMovementGeneratorMedium
-: public MovementGeneratorMedium< T, D >, public TargetedMovementGeneratorBase
+class TargetedMovementGeneratorMedium : public MovementGeneratorMedium< T, D >, public TargetedMovementGeneratorBase
{
protected:
TargetedMovementGeneratorMedium(Unit &target, float offset, float angle) :
diff --git a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h
index b5b43fcae64..0d8f047c83a 100755
--- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h
+++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h
@@ -58,9 +58,8 @@ template<class T>
class WaypointMovementGenerator;
template<>
-class WaypointMovementGenerator<Creature>
-: public MovementGeneratorMedium< Creature, WaypointMovementGenerator<Creature> >,
-public PathMovementBase<Creature, WaypointPath const*>
+class WaypointMovementGenerator<Creature> : public MovementGeneratorMedium< Creature, WaypointMovementGenerator<Creature> >,
+ public PathMovementBase<Creature, WaypointPath const*>
{
public:
WaypointMovementGenerator(uint32 _path_id = 0, bool _repeating = true)
@@ -110,9 +109,8 @@ public PathMovementBase<Creature, WaypointPath const*>
/** FlightPathMovementGenerator generates movement of the player for the paths
* and hence generates ground and activities for the player.
*/
-class FlightPathMovementGenerator
-: public MovementGeneratorMedium< Player, FlightPathMovementGenerator >,
-public PathMovementBase<Player, TaxiPathNodeList const*>
+class FlightPathMovementGenerator : public MovementGeneratorMedium< Player, FlightPathMovementGenerator >,
+ public PathMovementBase<Player, TaxiPathNodeList const*>
{
public:
explicit FlightPathMovementGenerator(TaxiPathNodeList const& pathnodes, uint32 startNode = 0)
diff --git a/src/server/game/Movement/Spline/MoveSpline.cpp b/src/server/game/Movement/Spline/MoveSpline.cpp
index 5d0344f9769..91b4ff08250 100644
--- a/src/server/game/Movement/Spline/MoveSpline.cpp
+++ b/src/server/game/Movement/Spline/MoveSpline.cpp
@@ -288,7 +288,7 @@ std::string MoveSpline::ToString() const
str << "facing angle: " << facing.angle;
else if (splineflags.final_target)
str << "facing target: " << facing.target;
- else if(splineflags.final_point)
+ else if (splineflags.final_point)
str << "facing point: " << facing.f.x << " " << facing.f.y << " " << facing.f.z;
str << std::endl;
str << "time passed: " << time_passed << std::endl;
diff --git a/src/server/game/Movement/Spline/MovementPacketBuilder.cpp b/src/server/game/Movement/Spline/MovementPacketBuilder.cpp
index e9031f95486..0260767dbe2 100644
--- a/src/server/game/Movement/Spline/MovementPacketBuilder.cpp
+++ b/src/server/game/Movement/Spline/MovementPacketBuilder.cpp
@@ -111,7 +111,7 @@ namespace Movement
Vector3 middle = (real_path[0] + real_path[last_idx]) / 2.f;
Vector3 offset;
// first and last points already appended
- for(uint32 i = 1; i < last_idx; ++i)
+ for (uint32 i = 1; i < last_idx; ++i)
{
offset = middle - real_path[i];
data.appendPackXYZ(offset.x, offset.y, offset.z);
@@ -169,7 +169,7 @@ namespace Movement
{
data << move_spline.facing.target;
}
- else if(splineFlags.final_point)
+ else if (splineFlags.final_point)
{
data << move_spline.facing.f.x << move_spline.facing.f.y << move_spline.facing.f.z;
}
diff --git a/src/server/game/Pools/PoolMgr.cpp b/src/server/game/Pools/PoolMgr.cpp
index 5ebf78e484c..d8548b552d3 100755
--- a/src/server/game/Pools/PoolMgr.cpp
+++ b/src/server/game/Pools/PoolMgr.cpp
@@ -479,7 +479,7 @@ void PoolGroup<Quest>::SpawnObject(ActivePoolData& spawns, uint32 limit, uint32
{
do
{
- uint32 questId = SelectRandomContainerElement(currentQuests);
+ uint32 questId = Trinity::Containers::SelectRandomContainerElement(currentQuests);
newQuests.insert(questId);
currentQuests.erase(questId);
} while (newQuests.size() < limit && !currentQuests.empty()); // failsafe
@@ -491,7 +491,7 @@ void PoolGroup<Quest>::SpawnObject(ActivePoolData& spawns, uint32 limit, uint32
// activate <limit> random quests
do
{
- uint32 questId = SelectRandomContainerElement(newQuests);
+ uint32 questId = Trinity::Containers::SelectRandomContainerElement(newQuests);
spawns.ActivateObject<Quest>(questId, poolId);
PoolObject tempObj(questId, 0.0f);
Spawn1Object(&tempObj);
diff --git a/src/server/game/Reputation/ReputationMgr.h b/src/server/game/Reputation/ReputationMgr.h
index 401503783b9..a073845ea73 100755
--- a/src/server/game/Reputation/ReputationMgr.h
+++ b/src/server/game/Reputation/ReputationMgr.h
@@ -132,6 +132,9 @@ class ReputationMgr
void ApplyForceReaction(uint32 faction_id, ReputationRank rank, bool apply);
+ //! Public for chat command needs
+ bool SetOneFactionReputation(FactionEntry const* factionEntry, int32 standing, bool incremental);
+
public: // senders
void SendInitialReputations();
void SendForceReactions();
@@ -142,7 +145,6 @@ class ReputationMgr
void Initialize();
uint32 GetDefaultStateFlags(FactionEntry const* factionEntry) const;
bool SetReputation(FactionEntry const* factionEntry, int32 standing, bool incremental);
- bool SetOneFactionReputation(FactionEntry const* factionEntry, int32 standing, bool incremental);
void SetVisible(FactionState* faction);
void SetAtWar(FactionState* faction, bool atWar) const;
void SetInactive(FactionState* faction, bool inactive) const;
diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp
index 8e95f1a05cd..f64d0953e86 100755
--- a/src/server/game/Scripting/ScriptLoader.cpp
+++ b/src/server/game/Scripting/ScriptLoader.cpp
@@ -424,6 +424,7 @@ void AddSC_ulduar_teleporter();
void AddSC_boss_mimiron();
void AddSC_boss_hodir();
void AddSC_boss_freya();
+void AddSC_boss_algalon_the_observer();
void AddSC_instance_ulduar();
void AddSC_boss_keleseth(); //Utgarde Keep
void AddSC_boss_skarvald_dalronn();
@@ -1127,6 +1128,7 @@ void AddNorthrendScripts()
AddSC_boss_mimiron();
AddSC_boss_hodir();
AddSC_boss_freya();
+ AddSC_boss_algalon_the_observer();
AddSC_instance_ulduar();
AddSC_boss_keleseth(); //Utgarde Keep
AddSC_boss_skarvald_dalronn();
diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp
index 012910210a5..01d56cf8060 100755
--- a/src/server/game/Scripting/ScriptMgr.cpp
+++ b/src/server/game/Scripting/ScriptMgr.cpp
@@ -582,7 +582,7 @@ void ScriptMgr::OnCreateMap(Map* map)
{
ASSERT(map);
- SCR_MAP_BGN(WorldMapScript, map, itr, end, entry, IsContinent);
+ SCR_MAP_BGN(WorldMapScript, map, itr, end, entry, IsWorldMap);
itr->second->OnCreate(map);
SCR_MAP_END;
@@ -599,7 +599,7 @@ void ScriptMgr::OnDestroyMap(Map* map)
{
ASSERT(map);
- SCR_MAP_BGN(WorldMapScript, map, itr, end, entry, IsContinent);
+ SCR_MAP_BGN(WorldMapScript, map, itr, end, entry, IsWorldMap);
itr->second->OnDestroy(map);
SCR_MAP_END;
@@ -617,7 +617,7 @@ void ScriptMgr::OnLoadGridMap(Map* map, GridMap* gmap, uint32 gx, uint32 gy)
ASSERT(map);
ASSERT(gmap);
- SCR_MAP_BGN(WorldMapScript, map, itr, end, entry, IsContinent);
+ SCR_MAP_BGN(WorldMapScript, map, itr, end, entry, IsWorldMap);
itr->second->OnLoadGridMap(map, gmap, gx, gy);
SCR_MAP_END;
@@ -635,7 +635,7 @@ void ScriptMgr::OnUnloadGridMap(Map* map, GridMap* gmap, uint32 gx, uint32 gy)
ASSERT(map);
ASSERT(gmap);
- SCR_MAP_BGN(WorldMapScript, map, itr, end, entry, IsContinent);
+ SCR_MAP_BGN(WorldMapScript, map, itr, end, entry, IsWorldMap);
itr->second->OnUnloadGridMap(map, gmap, gx, gy);
SCR_MAP_END;
@@ -653,7 +653,7 @@ void ScriptMgr::OnPlayerEnterMap(Map* map, Player* player)
ASSERT(map);
ASSERT(player);
- SCR_MAP_BGN(WorldMapScript, map, itr, end, entry, IsContinent);
+ SCR_MAP_BGN(WorldMapScript, map, itr, end, entry, IsWorldMap);
itr->second->OnPlayerEnter(map, player);
SCR_MAP_END;
@@ -671,7 +671,7 @@ void ScriptMgr::OnPlayerLeaveMap(Map* map, Player* player)
ASSERT(map);
ASSERT(player);
- SCR_MAP_BGN(WorldMapScript, map, itr, end, entry, IsContinent);
+ SCR_MAP_BGN(WorldMapScript, map, itr, end, entry, IsWorldMap);
itr->second->OnPlayerLeave(map, player);
SCR_MAP_END;
@@ -688,7 +688,7 @@ void ScriptMgr::OnMapUpdate(Map* map, uint32 diff)
{
ASSERT(map);
- SCR_MAP_BGN(WorldMapScript, map, itr, end, entry, IsContinent);
+ SCR_MAP_BGN(WorldMapScript, map, itr, end, entry, IsWorldMap);
itr->second->OnUpdate(map, diff);
SCR_MAP_END;
@@ -954,6 +954,14 @@ bool ScriptMgr::OnDummyEffect(Unit* caster, uint32 spellId, SpellEffIndex effInd
return tmpscript->OnDummyEffect(caster, spellId, effIndex, target);
}
+GameObjectAI* ScriptMgr::GetGameObjectAI(GameObject* go)
+{
+ ASSERT(go);
+
+ GET_SCRIPT_RET(GameObjectScript, go->GetScriptId(), tmpscript, NULL);
+ return tmpscript->GetAI(go);
+}
+
bool ScriptMgr::OnAreaTrigger(Player* player, AreaTriggerEntry const* trigger)
{
ASSERT(player);
@@ -1415,7 +1423,7 @@ FormulaScript::FormulaScript(const char* name)
WorldMapScript::WorldMapScript(const char* name, uint32 mapId)
: ScriptObject(name), MapScript<Map>(mapId)
{
- if (GetEntry() && !GetEntry()->IsContinent())
+ if (GetEntry() && !GetEntry()->IsWorldMap())
sLog->outError("WorldMapScript for map %u is invalid.", mapId);
ScriptRegistry<WorldMapScript>::AddScript(this);
diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h
index 3b65a5cf256..6fe058d336a 100755
--- a/src/server/game/Scripting/ScriptMgr.h
+++ b/src/server/game/Scripting/ScriptMgr.h
@@ -39,6 +39,7 @@ class Creature;
class CreatureAI;
class DynamicObject;
class GameObject;
+class GameObjectAI;
class Guild;
class GridMap;
class Group;
@@ -471,6 +472,9 @@ class GameObjectScript : public ScriptObject, public UpdatableScript<GameObject>
// Called when the game object is damaged (destructible buildings only).
virtual void OnDamaged(GameObject* /*go*/, Player* /*player*/) { }
+
+ // Called when a GameObjectAI object is needed for the gameobject.
+ virtual GameObjectAI* GetAI(GameObject* /*go*/) const { return NULL; }
};
class AreaTriggerScript : public ScriptObject
@@ -911,6 +915,7 @@ class ScriptMgr
void OnGameObjectDestroyed(GameObject* go, Player* player);
void OnGameObjectDamaged(GameObject* go, Player* player);
void OnGameObjectUpdate(GameObject* go, uint32 diff);
+ GameObjectAI* GetGameObjectAI(GameObject* go);
public: /* AreaTriggerScript */
diff --git a/src/server/game/Server/Protocol/Opcodes.h b/src/server/game/Server/Protocol/Opcodes.h
index ab6ba7e7796..3c77ced6741 100755
--- a/src/server/game/Server/Protocol/Opcodes.h
+++ b/src/server/game/Server/Protocol/Opcodes.h
@@ -911,7 +911,7 @@ enum Opcodes
CMSG_LFG_SET_ROLES = 0x36A,
CMSG_LFG_SET_NEEDS = 0x36B,
CMSG_LFG_SET_BOOT_VOTE = 0x36C,
- SMSG_LFG_BOOT_PLAYER = 0x36D, // uint8, uint8, uint8, uint64, uint32, uint32, uint32, uint32
+ SMSG_LFG_BOOT_PROPOSAL_UPDATE = 0x36D, // uint8, uint8, uint8, uint64, uint32, uint32, uint32, uint32
CMSG_LFD_PLAYER_LOCK_INFO_REQUEST = 0x36E,
SMSG_LFG_PLAYER_INFO = 0x36F, // uint8, for (uint8) { uint32, uint8, uint32, uint32, uint32, uint32, uint8, for (uint8) {uint32, uint32, uint32}}, uint32, for (uint32) {uint32, uint32}
CMSG_LFG_TELEPORT = 0x370,
diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp
index be6561c2633..88248b7bc55 100755
--- a/src/server/game/Server/WorldSession.cpp
+++ b/src/server/game/Server/WorldSession.cpp
@@ -831,8 +831,8 @@ void WorldSession::ReadMovementInfo(WorldPacket &data, MovementInfo* mi)
in conjunction with any of the moving movement flags such as MOVEMENTFLAG_FORWARD.
It will freeze clients that receive this player's movement info.
*/
- REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_ROOT) && mi->HasMovementFlag(MOVEMENTFLAG_MASK_MOVING),
- MOVEMENTFLAG_MASK_MOVING);
+ REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_ROOT),
+ MOVEMENTFLAG_ROOT);
//! Cannot hover without SPELL_AURA_HOVER
REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_HOVER) && !GetPlayer()->HasAuraType(SPELL_AURA_HOVER),
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index 6383c7ff3ef..dbbd89c7533 100755
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -1231,12 +1231,11 @@ bool AuraEffect::IsPeriodicTickCrit(Unit* target, Unit const* caster) const
if ((*itr)->IsAffectedOnSpell(m_spellInfo) && caster->isSpellCrit(target, m_spellInfo, m_spellInfo->GetSchoolMask()))
return true;
}
+
// Rupture - since 3.3.3 can crit
- if (target->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_ROGUE, 0x100000, 0x0, 0x0, caster->GetGUID()))
- {
- if (caster->isSpellCrit(target, m_spellInfo, m_spellInfo->GetSchoolMask()))
- return true;
- }
+ if (m_spellInfo->SpellIconID == 500 && m_spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE)
+ return caster->isSpellCrit(target, m_spellInfo, m_spellInfo->GetSchoolMask());
+
return false;
}
@@ -1475,6 +1474,23 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const
if (spellInfo->Stances & (1<<(GetMiscValue()-1)))
target->CastSpell(target, itr->first, true, NULL, this);
}
+
+ // Also do it for Glyphs
+ for (uint32 i = 0; i < MAX_GLYPH_SLOT_INDEX; ++i)
+ {
+ if (uint32 glyphId = target->ToPlayer()->GetGlyph(i))
+ {
+ if (GlyphPropertiesEntry const* glyph = sGlyphPropertiesStore.LookupEntry(glyphId))
+ {
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(glyph->SpellId);
+ if (!spellInfo || !(spellInfo->Attributes & (SPELL_ATTR0_PASSIVE | SPELL_ATTR0_HIDDEN_CLIENTSIDE)))
+ continue;
+ if (spellInfo->Stances & (1<<(GetMiscValue()-1)))
+ target->CastSpell(target, glyph->SpellId, true, NULL, this);
+ }
+ }
+ }
+
// Leader of the Pack
if (target->ToPlayer()->HasSpell(17007))
{
@@ -1584,10 +1600,25 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const
}
}
+ const Unit::AuraEffectList& shapeshifts = target->GetAuraEffectsByType(SPELL_AURA_MOD_SHAPESHIFT);
+ AuraEffect* newAura = NULL;
+ // Iterate through all the shapeshift auras that the target has, if there is another aura with SPELL_AURA_MOD_SHAPESHIFT, then this aura is being removed due to that one being applied
+ for (Unit::AuraEffectList::const_iterator itr = shapeshifts.begin(); itr != shapeshifts.end(); ++itr)
+ {
+ if ((*itr) != this)
+ {
+ newAura = *itr;
+ break;
+ }
+ }
Unit::AuraApplicationMap& tAuras = target->GetAppliedAuras();
for (Unit::AuraApplicationMap::iterator itr = tAuras.begin(); itr != tAuras.end();)
{
- if (itr->second->GetBase()->IsRemovedOnShapeLost(target))
+ // Use the new aura to see on what stance the target will be
+ uint32 newStance = (1<<((newAura ? newAura->GetMiscValue() : 0)-1));
+
+ // If the stances are not compatible with the spell, remove it
+ if (itr->second->GetBase()->IsRemovedOnShapeLost(target) && !(itr->second->GetBase()->GetSpellInfo()->Stances & newStance))
target->RemoveAura(itr);
else
++itr;
@@ -2856,9 +2887,8 @@ void AuraEffect::HandleAuraAllowFlight(AuraApplication const* aurApp, uint8 mode
target->SetCanFly(apply);
if (!apply)
{
- target->RemoveUnitMovementFlag(MOVEMENTFLAG_FLYING);
- target->AddUnitMovementFlag(MOVEMENTFLAG_FALLING);
- target->m_movementInfo.SetFallTime(0);
+ target->RemoveUnitMovementFlag(MOVEMENTFLAG_MASK_MOVING_FLY);
+ target->GetMotionMaster()->MoveFall();
}
Player* player = target->ToPlayer();
@@ -2889,10 +2919,7 @@ void AuraEffect::HandleAuraWaterWalk(AuraApplication const* aurApp, uint8 mode,
if (apply)
target->AddUnitMovementFlag(MOVEMENTFLAG_WATERWALKING);
else
- {
target->RemoveUnitMovementFlag(MOVEMENTFLAG_WATERWALKING);
- target->AddUnitMovementFlag(MOVEMENTFLAG_FALLING);
- }
target->SendMovementWaterWalking();
}
@@ -4768,11 +4795,6 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool
if (target->GetTypeId() == TYPEID_PLAYER)
target->ToPlayer()->RemoveAmmo(); // not use ammo and not allow use
break;
- case 49028:
- if (caster)
- if (AuraEffect* aurEff = caster->GetAuraEffect(63330, 0)) // glyph of Dancing Rune Weapon
- GetBase()->SetDuration(GetBase()->GetDuration() + aurEff->GetAmount());
- break;
case 52916: // Honor Among Thieves
if (target->GetTypeId() == TYPEID_PLAYER)
if (Unit* spellTarget = ObjectAccessor::GetUnit(*target, target->ToPlayer()->GetComboTarget()))
@@ -4938,7 +4960,10 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool
// final heal
int32 stack = GetBase()->GetStackAmount();
- target->CastCustomSpell(target, 33778, &m_amount, &stack, NULL, true, NULL, this, GetCasterGUID());
+ int32 heal = m_amount;
+ if (caster)
+ heal = caster->SpellHealingBonus(target, GetSpellInfo(), heal, HEAL, stack);
+ target->CastCustomSpell(target, 33778, &heal, &stack, NULL, true, NULL, this, GetCasterGUID());
// restore mana
if (caster)
@@ -5623,21 +5648,6 @@ void AuraEffect::HandlePeriodicDummyAuraTick(Unit* target, Unit* caster) const
caster->CastCustomSpell(66153, SPELLVALUE_MAX_TARGETS, urand(1, 6), target, true);
break;
}
- case 54798: // FLAMING Arrow Triggered Effect
- {
- if (!caster || !target || !target->ToCreature() || !caster->GetVehicle() || target->HasAura(54683))
- break;
-
- target->CastSpell(target, 54683, true);
-
- // Credit Frostworgs
- if (target->GetEntry() == 29358)
- caster->CastSpell(caster, 54896, true);
- // Credit Frost Giants
- else if (target->GetEntry() == 29351)
- caster->CastSpell(caster, 54893, true);
- break;
- }
case 62292: // Blaze (Pool of Tar)
// should we use custom damage?
target->CastSpell((Unit*)NULL, m_spellInfo->Effects[m_effIndex].TriggerSpell, true);
@@ -5726,7 +5736,7 @@ void AuraEffect::HandlePeriodicDummyAuraTick(Unit* target, Unit* caster) const
if (targets.empty())
return;
- Unit* spellTarget = SelectRandomContainerElement(targets);
+ Unit* spellTarget = Trinity::Containers::SelectRandomContainerElement(targets);
target->CastSpell(spellTarget, 57840, true);
target->CastSpell(spellTarget, 57841, true);
@@ -6272,7 +6282,7 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const
void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) const
{
- if (!caster || !caster->isAlive() || !target->isAlive())
+ if (!caster || !target->isAlive())
return;
if (target->HasUnitState(UNIT_STATE_ISOLATED) || target->IsImmunedToDamage(GetSpellInfo()))
@@ -6325,15 +6335,19 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c
damage = (damage <= absorb+resist) ? 0 : (damage-absorb-resist);
if (damage)
procVictim |= PROC_FLAG_TAKEN_DAMAGE;
- caster->ProcDamageAndSpell(target, procAttacker, procVictim, procEx, damage, BASE_ATTACK, GetSpellInfo());
+ if (caster->isAlive())
+ caster->ProcDamageAndSpell(target, procAttacker, procVictim, procEx, damage, BASE_ATTACK, GetSpellInfo());
int32 new_damage = caster->DealDamage(target, damage, &cleanDamage, DOT, GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), false);
- float gainMultiplier = GetSpellInfo()->Effects[GetEffIndex()].CalcValueMultiplier(caster);
+ if (caster->isAlive())
+ {
+ float gainMultiplier = GetSpellInfo()->Effects[GetEffIndex()].CalcValueMultiplier(caster);
- uint32 heal = uint32(caster->SpellHealingBonus(caster, GetSpellInfo(), uint32(new_damage * gainMultiplier), DOT, GetBase()->GetStackAmount()));
+ uint32 heal = uint32(caster->SpellHealingBonus(caster, GetSpellInfo(), uint32(new_damage * gainMultiplier), DOT, GetBase()->GetStackAmount()));
- int32 gain = caster->HealBySpell(caster, GetSpellInfo(), heal);
- caster->getHostileRefManager().threatAssist(caster, gain * 0.5f, GetSpellInfo());
+ int32 gain = caster->HealBySpell(caster, GetSpellInfo(), heal);
+ caster->getHostileRefManager().threatAssist(caster, gain * 0.5f, GetSpellInfo());
+ }
}
void AuraEffect::HandlePeriodicHealthFunnelAuraTick(Unit* target, Unit* caster) const
diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp
index b6cdc006d2d..0bf91b1b6c5 100755
--- a/src/server/game/Spells/Auras/SpellAuras.cpp
+++ b/src/server/game/Spells/Auras/SpellAuras.cpp
@@ -2243,7 +2243,7 @@ void Aura::CallScriptEffectCalcSpellModHandlers(AuraEffect const* aurEff, SpellM
}
}
-void Aura::CallScriptEffectAbsorbHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo & dmgInfo, uint32 & absorbAmount, bool & /*defaultPrevented*/)
+void Aura::CallScriptEffectAbsorbHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo & dmgInfo, uint32 & absorbAmount, bool& defaultPrevented)
{
for (std::list<AuraScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
@@ -2254,6 +2254,7 @@ void Aura::CallScriptEffectAbsorbHandlers(AuraEffect* aurEff, AuraApplication co
if ((*effItr).IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
(*effItr).Call(*scritr, aurEff, dmgInfo, absorbAmount);
}
+ defaultPrevented = (*scritr)->_IsDefaultActionPrevented();
(*scritr)->_FinishScriptCall();
}
}
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index 942f9dc7e86..f055d669925 100755
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -1008,7 +1008,7 @@ void Spell::SelectImplicitNearbyTargets(SpellEffIndex effIndex, SpellImplicitTar
{
case TARGET_OBJECT_TYPE_UNIT:
if (Unit* unitTarget = target->ToUnit())
- AddUnitTarget(unitTarget, effMask, false);
+ AddUnitTarget(unitTarget, effMask, true, false);
break;
case TARGET_OBJECT_TYPE_GOBJ:
if (GameObject* gobjTarget = target->ToGameObject())
@@ -1055,7 +1055,7 @@ void Spell::SelectImplicitConeTargets(SpellEffIndex effIndex, SpellImplicitTarge
if ((*j)->IsAffectedOnSpell(m_spellInfo))
maxTargets += (*j)->GetAmount();
- Trinity::RandomResizeList(targets, maxTargets);
+ Trinity::Containers::RandomResizeList(targets, maxTargets);
}
// for compability with older code - add only unit and go targets
@@ -1350,7 +1350,7 @@ void Spell::SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTarge
if (m_spellInfo->Id == 5246) //Intimidating Shout
unitTargets.remove(m_targets.GetUnitTarget());
- Trinity::RandomResizeList(unitTargets, maxTargets);
+ Trinity::Containers::RandomResizeList(unitTargets, maxTargets);
}
CallScriptAfterUnitTargetSelectHandlers(unitTargets, effIndex);
@@ -1368,7 +1368,7 @@ void Spell::SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTarge
if ((*j)->IsAffectedOnSpell(m_spellInfo))
maxTargets += (*j)->GetAmount();
- Trinity::RandomResizeList(gObjTargets, maxTargets);
+ Trinity::Containers::RandomResizeList(gObjTargets, maxTargets);
}
for (std::list<GameObject*>::iterator itr = gObjTargets.begin(); itr != gObjTargets.end(); ++itr)
AddGOTarget(*itr, effMask);
@@ -1544,7 +1544,7 @@ void Spell::SelectImplicitTargetObjectTargets(SpellEffIndex effIndex, SpellImpli
{
ASSERT((m_targets.GetObjectTarget() || m_targets.GetItemTarget()) && "Spell::SelectImplicitTargetObjectTargets - no explicit object or item target available!");
if (Unit* unit = m_targets.GetUnitTarget())
- AddUnitTarget(unit, 1 << effIndex);
+ AddUnitTarget(unit, 1 << effIndex, true, false);
else if (GameObject* gobj = m_targets.GetGOTarget())
AddGOTarget(gobj, 1 << effIndex);
else
@@ -2077,7 +2077,7 @@ void Spell::CleanupTargetList()
m_delayMoment = 0;
}
-void Spell::AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid /*= true*/)
+void Spell::AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid /*= true*/, bool implicit /*= true*/)
{
for (uint32 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex)
if (!m_spellInfo->Effects[effIndex].IsEffect() || !CheckEffectTarget(target, effIndex))
@@ -2088,7 +2088,7 @@ void Spell::AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid /*=
return;
if (checkIfValid)
- if (m_spellInfo->CheckTarget(m_caster, target, true) != SPELL_CAST_OK)
+ if (m_spellInfo->CheckTarget(m_caster, target, implicit) != SPELL_CAST_OK)
return;
// Check for effect immune skip if immuned
@@ -2442,13 +2442,13 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
else
procEx |= PROC_EX_NORMAL_HIT;
- // Do triggers for unit (reflect triggers passed on hit phase for correct drop charge)
- if (canEffectTrigger && missInfo != SPELL_MISS_REFLECT)
- caster->ProcDamageAndSpell(unitTarget, procAttacker, procVictim, procEx, addhealth, m_attackType, m_spellInfo, m_triggeredByAuraSpell);
-
int32 gain = caster->HealBySpell(unitTarget, m_spellInfo, addhealth, crit);
unitTarget->getHostileRefManager().threatAssist(caster, float(gain) * 0.5f, m_spellInfo);
m_healing = gain;
+
+ // Do triggers for unit (reflect triggers passed on hit phase for correct drop charge)
+ if (canEffectTrigger && missInfo != SPELL_MISS_REFLECT)
+ caster->ProcDamageAndSpell(unitTarget, procAttacker, procVictim, procEx, addhealth, m_attackType, m_spellInfo, m_triggeredByAuraSpell);
}
// Do damage and triggers
else if (m_damage > 0)
@@ -2745,18 +2745,18 @@ void Spell::DoTriggersOnSpellHit(Unit* unit, uint8 effMask)
if (!m_hitTriggerSpells.empty())
{
int _duration = 0;
- for (HitTriggerSpells::const_iterator i = m_hitTriggerSpells.begin(); i != m_hitTriggerSpells.end(); ++i)
+ for (HitTriggerSpellList::const_iterator i = m_hitTriggerSpells.begin(); i != m_hitTriggerSpells.end(); ++i)
{
- if (CanExecuteTriggersOnHit(effMask, i->first) && roll_chance_i(i->second))
+ if (CanExecuteTriggersOnHit(effMask, i->triggeredByAura) && roll_chance_i(i->chance))
{
- m_caster->CastSpell(unit, i->first, true);
- sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Spell %d triggered spell %d by SPELL_AURA_ADD_TARGET_TRIGGER aura", m_spellInfo->Id, i->first->Id);
+ m_caster->CastSpell(unit, i->triggeredSpell, true);
+ sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Spell %d triggered spell %d by SPELL_AURA_ADD_TARGET_TRIGGER aura", m_spellInfo->Id, i->triggeredSpell->Id);
// SPELL_AURA_ADD_TARGET_TRIGGER auras shouldn't trigger auras without duration
// set duration of current aura to the triggered spell
- if (i->first->GetDuration() == -1)
+ if (i->triggeredSpell->GetDuration() == -1)
{
- if (Aura* triggeredAur = unit->GetAura(i->first->Id, m_caster->GetGUID()))
+ if (Aura* triggeredAur = unit->GetAura(i->triggeredSpell->Id, m_caster->GetGUID()))
{
// get duration from aura-only once
if (!_duration)
@@ -3101,11 +3101,20 @@ void Spell::cast(bool skipCheck)
return;
}
- // now that we've done the basic check, now run the scripts
- // should be done before the spell is actually executed
if (Player* playerCaster = m_caster->ToPlayer())
+ {
+ // now that we've done the basic check, now run the scripts
+ // should be done before the spell is actually executed
sScriptMgr->OnPlayerSpellCast(playerCaster, this, skipCheck);
+ // As of 3.0.2 pets begin attacking their owner's target immediately
+ // Let any pets know we've attacked something. Check DmgClass for harmful spells only
+ // This prevents spells such as Hunter's Mark from triggering pet attack
+ if (this->GetSpellInfo()->DmgClass != SPELL_DAMAGE_CLASS_NONE)
+ if (Pet* playerPet = playerCaster->GetPet())
+ if (playerPet->isAlive() && playerPet->isControlled() && (m_targets.GetTargetMask() & TARGET_FLAG_UNIT))
+ playerPet->AI()->OwnerAttacked(m_targets.GetObjectTarget()->ToUnit());
+ }
SetExecutedCurrently(true);
if (m_caster->GetTypeId() != TYPEID_PLAYER && m_targets.GetUnitTarget() && m_targets.GetUnitTarget() != m_caster)
@@ -3418,36 +3427,6 @@ void Spell::_handle_immediate_phase()
// process items
for (std::list<ItemTargetInfo>::iterator ihit= m_UniqueItemInfo.begin(); ihit != m_UniqueItemInfo.end(); ++ihit)
DoAllEffectOnTarget(&(*ihit));
-
- if (!m_originalCaster)
- return;
- // Handle procs on cast
- // TODO: finish new proc system:P
- if (m_UniqueTargetInfo.empty())
- {
- uint32 procAttacker = m_procAttacker;
- if (!procAttacker)
- {
- bool positive = m_spellInfo->IsPositive();
- switch (m_spellInfo->DmgClass)
- {
- case SPELL_DAMAGE_CLASS_MAGIC:
- if (positive)
- procAttacker |= PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_POS;
- else
- procAttacker |= PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_NEG;
- break;
- case SPELL_DAMAGE_CLASS_NONE:
- if (positive)
- procAttacker |= PROC_FLAG_DONE_SPELL_NONE_DMG_CLASS_POS;
- else
- procAttacker |= PROC_FLAG_DONE_SPELL_NONE_DMG_CLASS_NEG;
- break;
- }
- }
- // Proc damage for spells which have only dest targets (2484 should proc 51486 for example)
- m_originalCaster->ProcDamageAndSpell(NULL, procAttacker, 0, m_procEx | PROC_EX_NORMAL_HIT, 0, BASE_ATTACK, m_spellInfo, m_triggeredByAuraSpell);
- }
}
void Spell::_handle_finish_phase()
@@ -4331,10 +4310,9 @@ void Spell::TakePower()
for (std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
if (ihit->targetGUID == targetGUID)
{
- if (ihit->missCondition != SPELL_MISS_NONE && ihit->missCondition != SPELL_MISS_MISS/* && ihit->targetGUID != m_caster->GetGUID()*/)
- hit = false;
if (ihit->missCondition != SPELL_MISS_NONE)
{
+ hit = false;
//lower spell cost on fail (by talent aura)
if (Player* modOwner = m_caster->ToPlayer()->GetSpellModOwner())
modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_SPELL_COST_REFUND_ON_FAIL, m_powerCost);
@@ -5230,10 +5208,8 @@ SpellCastResult Spell::CheckCast(bool strict)
case SPELL_EFFECT_SUMMON_DEAD_PET:
{
Creature* pet = m_caster->GetGuardianPet();
- if (!pet)
- return SPELL_FAILED_NO_PET;
- if (pet->isAlive())
+ if (pet && pet->isAlive())
return SPELL_FAILED_ALREADY_HAVE_SUMMON;
break;
@@ -5283,7 +5259,6 @@ SpellCastResult Spell::CheckCast(bool strict)
if (m_caster->GetCharmGUID())
return SPELL_FAILED_ALREADY_HAVE_CHARM;
-
break;
}
case SPELL_EFFECT_SUMMON_PLAYER:
@@ -7171,14 +7146,13 @@ void Spell::CallScriptAfterUnitTargetSelectHandlers(std::list<Unit*>& unitTarget
}
}
-bool Spell::CanExecuteTriggersOnHit(uint8 effMask, SpellInfo const* spellInfo) const
+bool Spell::CanExecuteTriggersOnHit(uint8 effMask, SpellInfo const* triggeredByAura) const
{
- bool only_on_dummy = (spellInfo && (spellInfo->AttributesEx4 & SPELL_ATTR4_PROC_ONLY_ON_DUMMY));
- // If triggered spell has SPELL_ATTR4_PROC_ONLY_ON_DUMMY then it can only proc on a casted spell with SPELL_EFFECT_DUMMY
- // If triggered spell doesn't have SPELL_ATTR4_PROC_ONLY_ON_DUMMY then it can NOT proc on SPELL_EFFECT_DUMMY (needs confirmation)
+ bool only_on_caster = (triggeredByAura && (triggeredByAura->AttributesEx4 & SPELL_ATTR4_PROC_ONLY_ON_CASTER));
+ // If triggeredByAura has SPELL_ATTR4_PROC_ONLY_ON_CASTER then it can only proc on a casted spell with TARGET_UNIT_CASTER
for (uint8 i = 0;i < MAX_SPELL_EFFECTS; ++i)
{
- if ((effMask & (1 << i)) && (only_on_dummy == (m_spellInfo->Effects[i].Effect == SPELL_EFFECT_DUMMY)))
+ if ((effMask & (1 << i)) && (!only_on_caster || (m_spellInfo->Effects[i].TargetA.GetTarget() == TARGET_UNIT_CASTER)))
return true;
}
return false;
@@ -7230,9 +7204,14 @@ void Spell::PrepareTriggersExecutedOnHit()
// calculate the chance using spell base amount, because aura amount is not updated on combo-points change
// this possibly needs fixing
int32 auraBaseAmount = (*i)->GetBaseAmount();
- int32 chance = m_caster->CalculateSpellDamage(NULL, auraSpellInfo, auraSpellIdx, &auraBaseAmount);
// proc chance is stored in effect amount
- m_hitTriggerSpells.push_back(std::make_pair(spellInfo, chance * (*i)->GetBase()->GetStackAmount()));
+ int32 chance = m_caster->CalculateSpellDamage(NULL, auraSpellInfo, auraSpellIdx, &auraBaseAmount);
+ // build trigger and add to the list
+ HitTriggerSpell spellTriggerInfo;
+ spellTriggerInfo.triggeredSpell = spellInfo;
+ spellTriggerInfo.triggeredByAura = auraSpellInfo;
+ spellTriggerInfo.chance = chance * (*i)->GetBase()->GetStackAmount();
+ m_hitTriggerSpells.push_back(spellTriggerInfo);
}
}
}
diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h
index 37842433eb3..8f43b9b2290 100755
--- a/src/server/game/Spells/Spell.h
+++ b/src/server/game/Spells/Spell.h
@@ -596,7 +596,7 @@ class Spell
SpellDestination m_destTargets[MAX_SPELL_EFFECTS];
- void AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid = true);
+ void AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid = true, bool implicit = true);
void AddGOTarget(GameObject* target, uint32 effectMask);
void AddItemTarget(Item* item, uint32 effectMask);
void AddDestTarget(SpellDestination const& dest, uint32 effIndex);
@@ -633,10 +633,18 @@ class Spell
void CallScriptAfterUnitTargetSelectHandlers(std::list<Unit*>& unitTargets, SpellEffIndex effIndex);
std::list<SpellScript*> m_loadedScripts;
- bool CanExecuteTriggersOnHit(uint8 effMask, SpellInfo const* spellInfo = NULL) const;
+ struct HitTriggerSpell
+ {
+ SpellInfo const* triggeredSpell;
+ SpellInfo const* triggeredByAura;
+ // uint8 triggeredByEffIdx This might be needed at a later stage - No need known for now
+ int32 chance;
+ };
+
+ bool CanExecuteTriggersOnHit(uint8 effMask, SpellInfo const* triggeredByAura = NULL) const;
void PrepareTriggersExecutedOnHit();
- typedef std::list< std::pair<SpellInfo const*, int32> > HitTriggerSpells;
- HitTriggerSpells m_hitTriggerSpells;
+ typedef std::list<HitTriggerSpell> HitTriggerSpellList;
+ HitTriggerSpellList m_hitTriggerSpells;
// effect helpers
void SummonGuardian(uint32 i, uint32 entry, SummonPropertiesEntry const* properties, uint32 numSummons);
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index ce64c2e9560..c72ccbacc3d 100755
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -390,23 +390,6 @@ void Spell::EffectSchoolDMG(SpellEffIndex effIndex)
if (!unitTarget->HasAura(27825))
return;
break;
- // Cataclysmic Bolt
- case 38441:
- {
- damage = unitTarget->CountPctFromMaxHealth(50);
- break;
- }
- case 20625: // Ritual of Doom Sacrifice
- case 29142: // Eyesore Blaster
- case 35139: // Throw Boom's Doom
- case 42393: // Brewfest - Attack Keg
- case 55269: // Deathly Stare
- case 56578: // Rapid-Fire Harpoon
- case 62775: // Tympanic Tantrum
- {
- damage = unitTarget->CountPctFromMaxHealth(damage);
- break;
- }
// Gargoyle Strike
case 51963:
{
@@ -666,19 +649,19 @@ void Spell::EffectSchoolDMG(SpellEffIndex effIndex)
if (found)
damage += m_spellInfo->Effects[EFFECT_1].CalcValue();
- if (m_caster->GetTypeId() == TYPEID_PLAYER)
+ if (Player* caster = m_caster->ToPlayer())
{
// Add Ammo and Weapon damage plus RAP * 0.1
- Item* item = m_caster->ToPlayer()->GetWeaponForAttack(RANGED_ATTACK);
- if (item)
+ if (Item* item = caster->GetWeaponForAttack(RANGED_ATTACK))
{
- float dmg_min = item->GetTemplate()->Damage->DamageMin;
- float dmg_max = item->GetTemplate()->Damage->DamageMax;
+ ItemTemplate const* weaponTemplate = item->GetTemplate();
+ float dmg_min = weaponTemplate->Damage[0].DamageMin;
+ float dmg_max = weaponTemplate->Damage[0].DamageMax;
if (dmg_max == 0.0f && dmg_min > dmg_max)
damage += int32(dmg_min);
else
damage += irand(int32(dmg_min), int32(dmg_max));
- damage += int32(m_caster->ToPlayer()->GetAmmoDPS()*item->GetTemplate()->Delay*0.001f);
+ damage += int32(caster->GetAmmoDPS() * weaponTemplate->Delay * 0.001f);
}
}
}
@@ -774,7 +757,7 @@ void Spell::EffectDummy(SpellEffIndex effIndex)
uint32 maxTargets = std::min<uint32>(3, attackers.size());
for (uint32 i = 0; i < maxTargets; ++i)
{
- Unit* attacker = SelectRandomContainerElement(attackers);
+ Unit* attacker = Trinity::Containers::SelectRandomContainerElement(attackers);
AddUnitTarget(attacker, 1 << 1);
attackers.erase(attacker);
}
@@ -1611,20 +1594,6 @@ void Spell::EffectHeal(SpellEffIndex /*effIndex*/)
}
}
}
- // Lifebloom - final heal coef multiplied by original DoT stack
- else if (m_spellInfo->Id == 33778)
- addhealth = caster->SpellHealingBonus(unitTarget, m_spellInfo, addhealth, HEAL, m_spellValue->EffectBasePoints[1]);
- // Riptide - increase healing done by Chain Heal
- else if (m_spellInfo->SpellFamilyName == SPELLFAMILY_SHAMAN && m_spellInfo->SpellFamilyFlags[0] & 0x100)
- {
- addhealth = caster->SpellHealingBonus(unitTarget, m_spellInfo, addhealth, HEAL);
- if (AuraEffect* aurEff = unitTarget->GetAuraEffect(SPELL_AURA_PERIODIC_HEAL, SPELLFAMILY_SHAMAN, 0, 0, 0x10, m_originalCasterGUID))
- {
- addhealth = int32(addhealth * 1.25f);
- // consume aura
- unitTarget->RemoveAura(aurEff->GetBase());
- }
- }
// Death Pact - return pct of max health to caster
else if (m_spellInfo->SpellFamilyName == SPELLFAMILY_DEATHKNIGHT && m_spellInfo->SpellFamilyFlags[0] & 0x00080000)
addhealth = caster->SpellHealingBonus(unitTarget, m_spellInfo, int32(caster->CountPctFromMaxHealth(damage)), HEAL);
@@ -2008,7 +1977,7 @@ void Spell::EffectEnergize(SpellEffIndex effIndex)
if (!avalibleElixirs.empty())
{
// cast random elixir on target
- m_caster->CastSpell(unitTarget, SelectRandomContainerElement(avalibleElixirs), true, m_CastItem);
+ m_caster->CastSpell(unitTarget, Trinity::Containers::SelectRandomContainerElement(avalibleElixirs), true, m_CastItem);
}
}
}
@@ -5726,7 +5695,7 @@ void Spell::EffectSummonDeadPet(SpellEffIndex /*effIndex*/)
return;
Pet* pet = player->GetPet();
- if (!pet || pet->isAlive())
+ if (pet && pet->isAlive())
return;
if (damage < 0)
@@ -5734,8 +5703,16 @@ void Spell::EffectSummonDeadPet(SpellEffIndex /*effIndex*/)
float x, y, z;
player->GetPosition(x, y, z);
+ if (!pet)
+ {
+ player->SummonPet(0, x, y, z, player->GetOrientation(), SUMMON_PET, 0);
+ pet = player->GetPet();
+ }
+ if (!pet)
+ return;
+
player->GetMap()->CreatureRelocation(pet, x, y, z, player->GetOrientation());
-
+
pet->SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_NONE);
pet->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
pet->setDeathState(ALIVE);
diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp
index b95ee766f38..07ab71207f1 100644
--- a/src/server/game/Spells/SpellInfo.cpp
+++ b/src/server/game/Spells/SpellInfo.cpp
@@ -2177,12 +2177,12 @@ bool SpellInfo::_IsPositiveEffect(uint8 effIndex, bool deep) const
switch (Id)
{
case 34700: // Allergic Reaction
- case 61716: // Rabbit Costume
- case 61734: // Noblegarden Bunny
case 61987: // Avenging Wrath Marker
case 61988: // Divine Shield exclude aura
case 62532: // Conservator's Grip
return false;
+ case 61716: // Rabbit Costume
+ case 61734: // Noblegarden Bunny
case 30877: // Tag Murloc
case 62344: // Fists of Stone
return true;
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index 895dc9ab4b7..3de87790be9 100755
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -2094,7 +2094,7 @@ void SpellMgr::LoadEnchantCustomAttr()
continue;
// TODO: find a better check
- if (!(spellInfo->AttributesEx2 & SPELL_ATTR2_UNK13) || !(spellInfo->Attributes & SPELL_ATTR0_NOT_SHAPESHIFT))
+ if (!(spellInfo->AttributesEx2 & SPELL_ATTR2_PRESERVE_ENCHANT_IN_ARENA) || !(spellInfo->Attributes & SPELL_ATTR0_NOT_SHAPESHIFT))
continue;
for (uint32 j = 0; j < MAX_SPELL_EFFECTS; ++j)
@@ -3238,6 +3238,10 @@ void SpellMgr::LoadDbcDataCorrections()
spellInfo->EffectDieSides[0] = 0; // was 1, that should probably mean seat 0, but instead it's treated as spell 1
spellInfo->EffectBasePoints[0] = 52391; // Ride Vehicle (forces seat 0)
break;
+ case 64745: // Item - Death Knight T8 Tank 4P Bonus
+ case 64936: // Item - Warrior T8 Protection 4P Bonus
+ spellInfo->EffectBasePoints[0] = 100; // 100% chance of procc'ing, not -10% (chance calculated in PrepareTriggersExecutedOnHit)
+ break;
case 19970: // Entangling Roots (Rank 6) -- Nature's Grasp Proc
case 19971: // Entangling Roots (Rank 5) -- Nature's Grasp Proc
case 19972: // Entangling Roots (Rank 4) -- Nature's Grasp Proc
@@ -3294,6 +3298,19 @@ void SpellMgr::LoadDbcDataCorrections()
spellInfo->EffectImplicitTargetB[1] = TARGET_UNIT_NEARBY_ENTRY;
spellInfo->EffectImplicitTargetB[2] = TARGET_UNIT_NEARBY_ENTRY;
break;
+ case 62301: // Cosmic Smash (Algalon the Observer)
+ spellInfo->MaxAffectedTargets = 1;
+ break;
+ case 64598: // Cosmic Smash (Algalon the Observer)
+ spellInfo->MaxAffectedTargets = 3;
+ break;
+ case 62293: // Cosmic Smash (Algalon the Observer)
+ spellInfo->EffectImplicitTargetB[0] = TARGET_DEST_CASTER;
+ break;
+ case 62311: // Cosmic Smash (Algalon the Observer)
+ case 64596: // Cosmic Smash (Algalon the Observer)
+ spellInfo->rangeIndex = 6; // 100yd
+ break;
// ENDOF ULDUAR SPELLS
//
// TRIAL OF THE CRUSADER SPELLS
@@ -3343,9 +3360,9 @@ void SpellMgr::LoadDbcDataCorrections()
case 70460: // Coldflame Jets (Traps after Saurfang)
spellInfo->DurationIndex = 1; // 10 seconds
break;
- case 71413: // Green Ooze Summon (Professor Putricide)
- case 71414: // Orange Ooze Summon (Professor Putricide)
- spellInfo->EffectImplicitTargetA[0] = TARGET_DEST_DEST;
+ case 71412: // Green Ooze Summon (Professor Putricide)
+ case 71415: // Orange Ooze Summon (Professor Putricide)
+ spellInfo->EffectImplicitTargetA[0] = TARGET_UNIT_TARGET_ANY;
break;
case 71159: // Awaken Plagued Zombies
spellInfo->DurationIndex = 21;
@@ -3406,10 +3423,7 @@ void SpellMgr::LoadDbcDataCorrections()
spellInfo->EffectImplicitTargetA[0] = TARGET_DEST_CASTER;
break;
case 69846: // Frost Bomb
- spellInfo->speed = 10;
- spellInfo->EffectImplicitTargetA[0] = TARGET_DEST_TARGET_ANY;
- spellInfo->EffectImplicitTargetB[0] = TARGET_UNIT_TARGET_ANY;
- spellInfo->Effect[1] = 0;
+ spellInfo->speed = 0.0f; // This spell's summon happens instantly
break;
case 71614: // Ice Lock
spellInfo->Mechanic = MECHANIC_STUN;
@@ -3505,6 +3519,11 @@ void SpellMgr::LoadDbcDataCorrections()
case 40166: // Introspection
case 40167: // Introspection
spellInfo->Attributes |= SPELL_ATTR0_NEGATIVE_1;
+ break;
+ case 2378: // Minor Fortitude
+ spellInfo->manaCost = 0;
+ spellInfo->manaPerSecond = 0;
+ break;
default:
break;
}
diff --git a/src/server/game/Spells/SpellScript.cpp b/src/server/game/Spells/SpellScript.cpp
index 81f8bbd78c5..44a2dd4dedb 100755
--- a/src/server/game/Spells/SpellScript.cpp
+++ b/src/server/game/Spells/SpellScript.cpp
@@ -403,7 +403,7 @@ GameObject* SpellScript::GetHitGObj()
return m_spell->gameObjTarget;
}
-WorldLocation const* SpellScript::GetHitDest()
+WorldLocation* SpellScript::GetHitDest()
{
if (!IsInEffectHook())
{
@@ -773,6 +773,7 @@ bool AuraScript::_IsDefaultActionPrevented()
case AURA_SCRIPT_HOOK_EFFECT_APPLY:
case AURA_SCRIPT_HOOK_EFFECT_REMOVE:
case AURA_SCRIPT_HOOK_EFFECT_PERIODIC:
+ case AURA_SCRIPT_HOOK_EFFECT_ABSORB:
return m_defaultActionPrevented;
default:
ASSERT(false && "AuraScript::_IsDefaultActionPrevented is called in a wrong place");
@@ -787,6 +788,7 @@ void AuraScript::PreventDefaultAction()
case AURA_SCRIPT_HOOK_EFFECT_APPLY:
case AURA_SCRIPT_HOOK_EFFECT_REMOVE:
case AURA_SCRIPT_HOOK_EFFECT_PERIODIC:
+ case AURA_SCRIPT_HOOK_EFFECT_ABSORB:
m_defaultActionPrevented = true;
break;
default:
diff --git a/src/server/game/Spells/SpellScript.h b/src/server/game/Spells/SpellScript.h
index e84a56c8dbb..26393040a1e 100755
--- a/src/server/game/Spells/SpellScript.h
+++ b/src/server/game/Spells/SpellScript.h
@@ -325,7 +325,7 @@ class SpellScript : public _SpellScript
// returns: target of current effect if it was GameObject otherwise NULL
GameObject* GetHitGObj();
// returns: destination of current effect
- WorldLocation const* GetHitDest();
+ WorldLocation* GetHitDest();
// setter/getter for for damage done by spell to target of spell hit
// returns damage calculated before hit, and real dmg done after hit
int32 GetHitDamage();
diff --git a/src/server/game/Tickets/TicketMgr.cpp b/src/server/game/Tickets/TicketMgr.cpp
index 68e28014319..f82c01adf31 100755
--- a/src/server/game/Tickets/TicketMgr.cpp
+++ b/src/server/game/Tickets/TicketMgr.cpp
@@ -37,7 +37,10 @@ GmTicket::GmTicket(Player* player, WorldPacket& recv_data) : _createTime(time(NU
_playerName = player->GetName();
_playerGuid = player->GetGUID();
- recv_data >> _mapId;
+ uint32 mapId;
+ recv_data >> mapId; // Map is sent as UInt32!
+ _mapId = mapId;
+
recv_data >> _posX;
recv_data >> _posY;
recv_data >> _posZ;
diff --git a/src/server/game/Tools/PlayerDump.cpp b/src/server/game/Tools/PlayerDump.cpp
index 8d5d16d22b9..476a19b6885 100644
--- a/src/server/game/Tools/PlayerDump.cpp
+++ b/src/server/game/Tools/PlayerDump.cpp
@@ -306,22 +306,28 @@ bool PlayerDumpWriter::DumpTable(std::string& dump, uint32 guid, char const*tabl
switch (type)
{
case DTT_INVENTORY:
- StoreGUID(result, 3, items); break; // item guid collection (character_inventory.item)
+ StoreGUID(result, 3, items); // item guid collection (character_inventory.item)
+ break;
case DTT_PET:
- StoreGUID(result, 0, pets); break; // pet petnumber collection (character_pet.id)
+ StoreGUID(result, 0, pets); // pet petnumber collection (character_pet.id)
+ break;
case DTT_MAIL:
- StoreGUID(result, 0, mails); // mail id collection (mail.id)
+ StoreGUID(result, 0, mails); // mail id collection (mail.id)
+ break;
case DTT_MAIL_ITEM:
- StoreGUID(result, 1, items); break; // item guid collection (mail_items.item_guid)
+ StoreGUID(result, 1, items); // item guid collection (mail_items.item_guid)
+ break;
case DTT_CHARACTER:
{
- if (result->GetFieldCount() <= 67) // avoid crashes on next check
- return true;
- if (result->Fetch()[67].GetUInt32()) // characters.deleteInfos_Account - if filled error
+ if (result->GetFieldCount() <= 68) // avoid crashes on next check
+ sLog->outCrash("PlayerDumpWriter::DumpTable - Trying to access non-existing or wrong positioned field (`deleteInfos_Account`) in `characters` table.");
+
+ if (result->Fetch()[68].GetUInt32()) // characters.deleteInfos_Account - if filled error
return false;
break;
}
- default: break;
+ default:
+ break;
}
dump += CreateDumpString(tableTo, result);
diff --git a/src/server/game/Warden/Warden.cpp b/src/server/game/Warden/Warden.cpp
index fa30adde72a..0734e0a0f63 100644
--- a/src/server/game/Warden/Warden.cpp
+++ b/src/server/game/Warden/Warden.cpp
@@ -187,7 +187,9 @@ std::string Warden::Penalty(WardenCheck* check /*= NULL*/)
duration << sWorld->getIntConfig(CONFIG_WARDEN_CLIENT_BAN_DURATION) << "s";
std::string accountName;
AccountMgr::GetName(_session->GetAccountId(), accountName);
- sWorld->BanAccount(BAN_ACCOUNT, accountName, duration.str(), "Warden Anticheat violation","Server");
+ std::stringstream banReason;
+ banReason << "Warden Anticheat Violation: " << check->Comment << " (CheckId: " << check->CheckId << ")";
+ sWorld->BanAccount(BAN_ACCOUNT, accountName, duration.str(), banReason.str(),"Server");
return "Ban";
break;
diff --git a/src/server/game/Warden/Warden.h b/src/server/game/Warden/Warden.h
index e06ea7dca25..d16890b31b9 100644
--- a/src/server/game/Warden/Warden.h
+++ b/src/server/game/Warden/Warden.h
@@ -107,7 +107,7 @@ class Warden
public:
Warden();
- ~Warden();
+ virtual ~Warden();
virtual void Init(WorldSession* session, BigNumber* k) = 0;
virtual ClientWardenModule* GetModuleForClient() = 0;
diff --git a/src/server/game/Warden/WardenCheckMgr.cpp b/src/server/game/Warden/WardenCheckMgr.cpp
index 90d1cfc0140..f4c7a5069cf 100644
--- a/src/server/game/Warden/WardenCheckMgr.cpp
+++ b/src/server/game/Warden/WardenCheckMgr.cpp
@@ -63,8 +63,8 @@ void WardenCheckMgr::LoadWardenChecks()
CheckStore.resize(maxCheckId + 1);
- // 0 1 2 3 4 5 6
- result = WorldDatabase.Query("SELECT id, type, data, result, address, length, str FROM warden_checks ORDER BY id ASC");
+ // 0 1 2 3 4 5 6 7
+ result = WorldDatabase.Query("SELECT id, type, data, result, address, length, str, comment FROM warden_checks ORDER BY id ASC");
uint32 count = 0;
do
@@ -78,9 +78,11 @@ void WardenCheckMgr::LoadWardenChecks()
uint32 address = fields[4].GetUInt32();
uint8 length = fields[5].GetUInt8();
std::string str = fields[6].GetString();
+ std::string comment = fields[7].GetString();
WardenCheck* wardenCheck = new WardenCheck();
wardenCheck->Type = checkType;
+ wardenCheck->CheckId = id;
// Initialize action with default action from config
wardenCheck->Action = WardenActions(sWorld->getIntConfig(CONFIG_WARDEN_CLIENT_FAIL_ACTION));
@@ -134,6 +136,11 @@ void WardenCheckMgr::LoadWardenChecks()
CheckResultStore[id] = wr;
}
+ if (comment.empty())
+ wardenCheck->Comment = "Undocumented Check";
+ else
+ wardenCheck->Comment = comment;
+
++count;
}
while (result->NextRow());
diff --git a/src/server/game/Warden/WardenCheckMgr.h b/src/server/game/Warden/WardenCheckMgr.h
index 45de18081c2..7a83d8f0c6d 100644
--- a/src/server/game/Warden/WardenCheckMgr.h
+++ b/src/server/game/Warden/WardenCheckMgr.h
@@ -36,6 +36,8 @@ struct WardenCheck
uint32 Address; // PROC_CHECK, MEM_CHECK, PAGE_CHECK
uint8 Length; // PROC_CHECK, MEM_CHECK, PAGE_CHECK
std::string Str; // LUA, MPQ, DRIVER
+ std::string Comment;
+ uint16 CheckId;
enum WardenActions Action;
};
diff --git a/src/server/game/Warden/WardenMac.cpp b/src/server/game/Warden/WardenMac.cpp
index f62aa11a339..a60ae765013 100644
--- a/src/server/game/Warden/WardenMac.cpp
+++ b/src/server/game/Warden/WardenMac.cpp
@@ -122,7 +122,7 @@ void WardenMac::HandleHashResult(ByteBuffer &buff)
uint8 mod_seed[16] = { 0x4D, 0x80, 0x8D, 0x2C, 0x77, 0xD9, 0x05, 0xC4, 0x1A, 0x63, 0x80, 0xEC, 0x08, 0x58, 0x6A, 0xFE };
- for(int i = 0; i < 4; ++i)
+ for (int i = 0; i < 4; ++i)
{
keyIn[i] = *(int*)(&mod_seed[0] + i * 4);
}
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index ccc8bb2c3e7..6e32d33a7bb 100755
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -2602,7 +2602,7 @@ void World::SendAutoBroadcast()
std::string msg;
- msg = SelectRandomContainerElement(m_Autobroadcasts);
+ msg = Trinity::Containers::SelectRandomContainerElement(m_Autobroadcasts);
uint32 abcenter = sWorld->getIntConfig(CONFIG_AUTOBROADCAST_CENTER);
diff --git a/src/server/scripts/CMakeLists.txt b/src/server/scripts/CMakeLists.txt
index 728d95a0851..792fdeb3e7b 100644
--- a/src/server/scripts/CMakeLists.txt
+++ b/src/server/scripts/CMakeLists.txt
@@ -53,7 +53,6 @@ include_directories(
${CMAKE_BINARY_DIR}
${CMAKE_SOURCE_DIR}/dep/g3dlite/include
${CMAKE_SOURCE_DIR}/dep/SFMT
- ${CMAKE_SOURCE_DIR}/dep/mersennetwister
${CMAKE_SOURCE_DIR}/dep/zlib
${CMAKE_SOURCE_DIR}/src/server/shared
${CMAKE_SOURCE_DIR}/src/server/shared/Configuration
@@ -120,6 +119,7 @@ include_directories(
${CMAKE_SOURCE_DIR}/src/server/game/Maps
${CMAKE_SOURCE_DIR}/src/server/game/Movement
${CMAKE_SOURCE_DIR}/src/server/game/Movement/MovementGenerators
+ ${CMAKE_SOURCE_DIR}/src/server/game/Movement/Spline
${CMAKE_SOURCE_DIR}/src/server/game/Movement/Waypoints
${CMAKE_SOURCE_DIR}/src/server/game/Opcodes
${CMAKE_SOURCE_DIR}/src/server/game/OutdoorPvP
diff --git a/src/server/scripts/Commands/cs_modify.cpp b/src/server/scripts/Commands/cs_modify.cpp
index f62c434e2e5..b6feccc10c6 100644
--- a/src/server/scripts/Commands/cs_modify.cpp
+++ b/src/server/scripts/Commands/cs_modify.cpp
@@ -1241,7 +1241,7 @@ public:
return false;
}
- target->GetReputationMgr().SetReputation(factionEntry, amount);
+ target->GetReputationMgr().SetOneFactionReputation(factionEntry, amount, false);
handler->PSendSysMessage(LANG_COMMAND_MODIFY_REP, factionEntry->name[handler->GetSessionDbcLocale()], factionId,
handler->GetNameLink(target).c_str(), target->GetReputationMgr().GetReputation(factionEntry));
return true;
diff --git a/src/server/scripts/Commands/cs_reload.cpp b/src/server/scripts/Commands/cs_reload.cpp
index 5f192ffceee..1c119fdef4c 100644
--- a/src/server/scripts/Commands/cs_reload.cpp
+++ b/src/server/scripts/Commands/cs_reload.cpp
@@ -424,7 +424,7 @@ public:
continue;
}
- CreatureTemplate const* cInfo = sObjectMgr->GetCreatureTemplate(entry);
+ CreatureTemplate* cInfo = const_cast<CreatureTemplate*>(sObjectMgr->GetCreatureTemplate(entry));
if (!cInfo)
{
handler->PSendSysMessage(LANG_COMMAND_CREATURESTORAGE_NOTFOUND, entry);
@@ -435,90 +435,88 @@ public:
Field* fields = result->Fetch();
- const_cast<CreatureTemplate*>(cInfo)->DifficultyEntry[0] = fields[0].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->DifficultyEntry[1] = fields[1].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->DifficultyEntry[2] = fields[2].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->KillCredit[0] = fields[3].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->KillCredit[1] = fields[4].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->Modelid1 = fields[5].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->Modelid2 = fields[6].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->Modelid3 = fields[7].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->Modelid4 = fields[8].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->Name = fields[9].GetString();
- const_cast<CreatureTemplate*>(cInfo)->SubName = fields[10].GetString();
- const_cast<CreatureTemplate*>(cInfo)->IconName = fields[11].GetString();
- const_cast<CreatureTemplate*>(cInfo)->GossipMenuId = fields[12].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->minlevel = fields[13].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->maxlevel = fields[14].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->expansion = fields[15].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->faction_A = fields[16].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->faction_H = fields[17].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->npcflag = fields[18].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->speed_walk = fields[19].GetFloat();
- const_cast<CreatureTemplate*>(cInfo)->speed_run = fields[20].GetFloat();
- const_cast<CreatureTemplate*>(cInfo)->scale = fields[21].GetFloat();
- const_cast<CreatureTemplate*>(cInfo)->rank = fields[22].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->mindmg = fields[23].GetFloat();
- const_cast<CreatureTemplate*>(cInfo)->maxdmg = fields[24].GetFloat();
- const_cast<CreatureTemplate*>(cInfo)->dmgschool = fields[25].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->attackpower = fields[26].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->dmg_multiplier = fields[27].GetFloat();
- const_cast<CreatureTemplate*>(cInfo)->baseattacktime = fields[28].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->rangeattacktime = fields[29].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->unit_class = fields[30].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->unit_flags = fields[31].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->dynamicflags = fields[32].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->family = fields[33].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->trainer_type = fields[34].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->trainer_spell = fields[35].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->trainer_class = fields[36].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->trainer_race = fields[37].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->minrangedmg = fields[38].GetFloat();
- const_cast<CreatureTemplate*>(cInfo)->maxrangedmg = fields[39].GetFloat();
- const_cast<CreatureTemplate*>(cInfo)->rangedattackpower = fields[40].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->type = fields[41].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->type_flags = fields[42].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->lootid = fields[43].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->pickpocketLootId = fields[44].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->SkinLootId = fields[45].GetUInt32();
+ cInfo->DifficultyEntry[0] = fields[0].GetUInt32();
+ cInfo->DifficultyEntry[1] = fields[1].GetUInt32();
+ cInfo->DifficultyEntry[2] = fields[2].GetUInt32();
+ cInfo->KillCredit[0] = fields[3].GetUInt32();
+ cInfo->KillCredit[1] = fields[4].GetUInt32();
+ cInfo->Modelid1 = fields[5].GetUInt32();
+ cInfo->Modelid2 = fields[6].GetUInt32();
+ cInfo->Modelid3 = fields[7].GetUInt32();
+ cInfo->Modelid4 = fields[8].GetUInt32();
+ cInfo->Name = fields[9].GetString();
+ cInfo->SubName = fields[10].GetString();
+ cInfo->IconName = fields[11].GetString();
+ cInfo->GossipMenuId = fields[12].GetUInt32();
+ cInfo->minlevel = fields[13].GetUInt8();
+ cInfo->maxlevel = fields[14].GetUInt8();
+ cInfo->expansion = fields[15].GetUInt16();
+ cInfo->faction_A = fields[16].GetUInt16();
+ cInfo->faction_H = fields[17].GetUInt16();
+ cInfo->npcflag = fields[18].GetUInt32();
+ cInfo->speed_walk = fields[19].GetFloat();
+ cInfo->speed_run = fields[20].GetFloat();
+ cInfo->scale = fields[21].GetFloat();
+ cInfo->rank = fields[22].GetUInt8();
+ cInfo->mindmg = fields[23].GetFloat();
+ cInfo->maxdmg = fields[24].GetFloat();
+ cInfo->dmgschool = fields[25].GetUInt8();
+ cInfo->attackpower = fields[26].GetUInt32();
+ cInfo->dmg_multiplier = fields[27].GetFloat();
+ cInfo->baseattacktime = fields[28].GetUInt32();
+ cInfo->rangeattacktime = fields[29].GetUInt32();
+ cInfo->unit_class = fields[30].GetUInt8();
+ cInfo->unit_flags = fields[31].GetUInt32();
+ cInfo->dynamicflags = fields[32].GetUInt32();
+ cInfo->family = fields[33].GetUInt8();
+ cInfo->trainer_type = fields[34].GetUInt8();
+ cInfo->trainer_spell = fields[35].GetUInt32();
+ cInfo->trainer_class = fields[36].GetUInt8();
+ cInfo->trainer_race = fields[37].GetUInt8();
+ cInfo->minrangedmg = fields[38].GetFloat();
+ cInfo->maxrangedmg = fields[39].GetFloat();
+ cInfo->rangedattackpower = fields[40].GetUInt16();
+ cInfo->type = fields[41].GetUInt8();
+ cInfo->type_flags = fields[42].GetUInt32();
+ cInfo->lootid = fields[43].GetUInt32();
+ cInfo->pickpocketLootId = fields[44].GetUInt32();
+ cInfo->SkinLootId = fields[45].GetUInt32();
for (uint8 i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i)
- {
- const_cast<CreatureTemplate*>(cInfo)->resistance[i] = fields[46 + i -1].GetUInt32();
- }
-
- const_cast<CreatureTemplate*>(cInfo)->spells[0] = fields[52].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->spells[1] = fields[53].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->spells[2] = fields[54].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->spells[3] = fields[55].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->spells[4] = fields[56].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->spells[5] = fields[57].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->spells[6] = fields[58].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->spells[7] = fields[59].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->PetSpellDataId = fields[60].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->VehicleId = fields[61].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->mingold = fields[62].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->maxgold = fields[63].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->AIName = fields[64].GetString();
- const_cast<CreatureTemplate*>(cInfo)->MovementType = fields[65].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->InhabitType = fields[66].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->HoverHeight = fields[67].GetFloat();
- const_cast<CreatureTemplate*>(cInfo)->ModHealth = fields[68].GetFloat();
- const_cast<CreatureTemplate*>(cInfo)->ModMana = fields[69].GetFloat();
- const_cast<CreatureTemplate*>(cInfo)->ModArmor = fields[70].GetFloat();
- const_cast<CreatureTemplate*>(cInfo)->RacialLeader = fields[71].GetBool();
- const_cast<CreatureTemplate*>(cInfo)->questItems[0] = fields[72].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->questItems[1] = fields[73].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->questItems[2] = fields[74].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->questItems[3] = fields[75].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->questItems[4] = fields[76].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->questItems[5] = fields[77].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->movementId = fields[78].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->RegenHealth = fields[79].GetBool();
- const_cast<CreatureTemplate*>(cInfo)->equipmentId = fields[80].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->MechanicImmuneMask = fields[81].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->flags_extra = fields[82].GetUInt32();
- const_cast<CreatureTemplate*>(cInfo)->ScriptID = sObjectMgr->GetScriptId(fields[83].GetCString());
+ cInfo->resistance[i] = fields[46 + i -1].GetUInt16();
+
+ cInfo->spells[0] = fields[52].GetUInt32();
+ cInfo->spells[1] = fields[53].GetUInt32();
+ cInfo->spells[2] = fields[54].GetUInt32();
+ cInfo->spells[3] = fields[55].GetUInt32();
+ cInfo->spells[4] = fields[56].GetUInt32();
+ cInfo->spells[5] = fields[57].GetUInt32();
+ cInfo->spells[6] = fields[58].GetUInt32();
+ cInfo->spells[7] = fields[59].GetUInt32();
+ cInfo->PetSpellDataId = fields[60].GetUInt32();
+ cInfo->VehicleId = fields[61].GetUInt32();
+ cInfo->mingold = fields[62].GetUInt32();
+ cInfo->maxgold = fields[63].GetUInt32();
+ cInfo->AIName = fields[64].GetString();
+ cInfo->MovementType = fields[65].GetUInt8();
+ cInfo->InhabitType = fields[66].GetUInt8();
+ cInfo->HoverHeight = fields[67].GetFloat();
+ cInfo->ModHealth = fields[68].GetFloat();
+ cInfo->ModMana = fields[69].GetFloat();
+ cInfo->ModArmor = fields[70].GetFloat();
+ cInfo->RacialLeader = fields[71].GetBool();
+ cInfo->questItems[0] = fields[72].GetUInt32();
+ cInfo->questItems[1] = fields[73].GetUInt32();
+ cInfo->questItems[2] = fields[74].GetUInt32();
+ cInfo->questItems[3] = fields[75].GetUInt32();
+ cInfo->questItems[4] = fields[76].GetUInt32();
+ cInfo->questItems[5] = fields[77].GetUInt32();
+ cInfo->movementId = fields[78].GetUInt32();
+ cInfo->RegenHealth = fields[79].GetBool();
+ cInfo->equipmentId = fields[80].GetUInt32();
+ cInfo->MechanicImmuneMask = fields[81].GetUInt32();
+ cInfo->flags_extra = fields[82].GetUInt32();
+ cInfo->ScriptID = sObjectMgr->GetScriptId(fields[83].GetCString());
sObjectMgr->CheckCreatureTemplate(cInfo);
}
diff --git a/src/server/scripts/Commands/cs_tele.cpp b/src/server/scripts/Commands/cs_tele.cpp
index 89646c23ea0..ca7c3af7fde 100644
--- a/src/server/scripts/Commands/cs_tele.cpp
+++ b/src/server/scripts/Commands/cs_tele.cpp
@@ -138,8 +138,8 @@ public:
if (resultDB)
{
Field* fieldsDB = resultDB->Fetch();
- uint32 mapId = fieldsDB[0].GetUInt32();
- uint32 zoneId = fieldsDB[1].GetUInt32();
+ uint32 mapId = fieldsDB[0].GetUInt16();
+ uint32 zoneId = fieldsDB[1].GetUInt16();
float posX = fieldsDB[2].GetFloat();
float posY = fieldsDB[3].GetFloat();
float posZ = fieldsDB[4].GetFloat();
diff --git a/src/server/scripts/EasternKingdoms/Karazhan/boss_midnight.cpp b/src/server/scripts/EasternKingdoms/Karazhan/boss_midnight.cpp
index bbf87ac3e73..783ac6baad1 100644
--- a/src/server/scripts/EasternKingdoms/Karazhan/boss_midnight.cpp
+++ b/src/server/scripts/EasternKingdoms/Karazhan/boss_midnight.cpp
@@ -244,8 +244,8 @@ void boss_attumen::boss_attumenAI::UpdateAI(const uint32 diff)
Midnight = 0;
me->SetVisible(false);
me->Kill(me);
- }
- } else ResetTimer -= diff;
+ } else ResetTimer -= diff;
+ }
//Return since we have no target
if (!UpdateVictim())
diff --git a/src/server/scripts/EasternKingdoms/MoltenCore/boss_sulfuron_harbinger.cpp b/src/server/scripts/EasternKingdoms/MoltenCore/boss_sulfuron_harbinger.cpp
index 9f511c1394a..343298d29fe 100644
--- a/src/server/scripts/EasternKingdoms/MoltenCore/boss_sulfuron_harbinger.cpp
+++ b/src/server/scripts/EasternKingdoms/MoltenCore/boss_sulfuron_harbinger.cpp
@@ -103,7 +103,7 @@ class boss_sulfuron : public CreatureScript
{
std::list<Creature*> healers = DoFindFriendlyMissingBuff(45.0f, SPELL_INSPIRE);
if (!healers.empty())
- DoCast(SelectRandomContainerElement(healers), SPELL_INSPIRE);
+ DoCast(Trinity::Containers::SelectRandomContainerElement(healers), SPELL_INSPIRE);
DoCast(me, SPELL_INSPIRE);
events.ScheduleEvent(EVENT_INSPIRE, urand(20000, 26000));
diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp
index ceab845f0a2..37808e2b924 100644
--- a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp
+++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp
@@ -809,11 +809,11 @@ public:
{
for (std::list<Creature*>::const_iterator itr = MinionList.begin(); itr != MinionList.end(); ++itr)
{
- if (CAST_CRE(*itr)->GetOwner()->GetGUID() == me->GetOwner()->GetGUID())
+ if ((*itr)->GetOwner()->GetGUID() == me->GetOwner()->GetGUID())
{
- if (CAST_CRE(*itr)->isInCombat() && CAST_CRE(*itr)->getAttackerForHelper())
+ if ((*itr)->isInCombat() && (*itr)->getAttackerForHelper())
{
- AttackStart(CAST_CRE(*itr)->getAttackerForHelper());
+ AttackStart((*itr)->getAttackerForHelper());
}
}
}
@@ -826,10 +826,11 @@ public:
{
if (Unit* owner = me->GetOwner())
{
- if (owner->GetTypeId() == TYPEID_PLAYER && CAST_PLR(owner)->isInCombat())
+ Player* plrOwner = owner->ToPlayer();
+ if (plrOwner && plrOwner->isInCombat())
{
- if (CAST_PLR(owner)->getAttackerForHelper() && CAST_PLR(owner)->getAttackerForHelper()->GetEntry() == GHOSTS)
- AttackStart(CAST_PLR(owner)->getAttackerForHelper());
+ if (plrOwner->getAttackerForHelper() && plrOwner->getAttackerForHelper()->GetEntry() == GHOSTS)
+ AttackStart(plrOwner->getAttackerForHelper());
else
FindMinions(owner);
}
diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_high_inquisitor_fairbanks.cpp b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_high_inquisitor_fairbanks.cpp
index a64636a4223..1989c318c84 100644
--- a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_high_inquisitor_fairbanks.cpp
+++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_high_inquisitor_fairbanks.cpp
@@ -66,9 +66,15 @@ public:
Sleep_Timer = 30000;
Dispel_Timer = 20000;
PowerWordShield = false;
+ me->SetStandState(UNIT_STAND_STATE_DEAD);
+ me->SetUInt32Value(UNIT_FIELD_BYTES_1, 7);
}
- void EnterCombat(Unit* /*who*/) {}
+ void EnterCombat(Unit* /*who*/)
+ {
+ me->SetStandState(UNIT_STAND_STATE_STAND);
+ me->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
+ }
void UpdateAI(const uint32 diff)
{
diff --git a/src/server/scripts/EasternKingdoms/eversong_woods.cpp b/src/server/scripts/EasternKingdoms/eversong_woods.cpp
index 016dd60b39c..8ae72e142c8 100644
--- a/src/server/scripts/EasternKingdoms/eversong_woods.cpp
+++ b/src/server/scripts/EasternKingdoms/eversong_woods.cpp
@@ -490,14 +490,14 @@ public:
{
if (PlayerGUID)
if (Player* player = Unit::GetPlayer(*me, PlayerGUID))
- CAST_PLR(player)->FailQuest(QUEST_UNEXPECTED_RESULT);
+ player->FailQuest(QUEST_UNEXPECTED_RESULT);
}
void UpdateAI(const uint32 /*diff*/)
{
if (KillCount >= 3 && PlayerGUID)
if (Player* player = Unit::GetPlayer(*me, PlayerGUID))
- CAST_PLR(player)->CompleteQuest(QUEST_UNEXPECTED_RESULT);
+ player->CompleteQuest(QUEST_UNEXPECTED_RESULT);
if (Summon)
{
diff --git a/src/server/scripts/EasternKingdoms/isle_of_queldanas.cpp b/src/server/scripts/EasternKingdoms/isle_of_queldanas.cpp
index b0b09c0ec76..27d8ea3e51c 100644
--- a/src/server/scripts/EasternKingdoms/isle_of_queldanas.cpp
+++ b/src/server/scripts/EasternKingdoms/isle_of_queldanas.cpp
@@ -129,8 +129,8 @@ public:
PlayerGUID = caster->GetGUID();
if (PlayerGUID)
{
- Unit* player = Unit::GetUnit(*me, PlayerGUID);
- if (player && CAST_PLR(player)->GetQuestStatus(QUESTG) == QUEST_STATUS_INCOMPLETE)
+ Player* player = Unit::GetPlayer(*me, PlayerGUID);
+ if (player && player->GetQuestStatus(QUESTG) == QUEST_STATUS_INCOMPLETE)
DoCast(player, 45110, true);
}
DoCast(me, ENRAGE);
diff --git a/src/server/scripts/EasternKingdoms/undercity.cpp b/src/server/scripts/EasternKingdoms/undercity.cpp
index 0522e214012..d5896812007 100644
--- a/src/server/scripts/EasternKingdoms/undercity.cpp
+++ b/src/server/scripts/EasternKingdoms/undercity.cpp
@@ -47,7 +47,15 @@ enum Sylvanas
SPELL_HIGHBORNE_AURA = 37090,
SPELL_SYLVANAS_CAST = 36568,
- SPELL_RIBBON_OF_SOULS = 34432, //the real one to use might be 37099
+ SPELL_RIBBON_OF_SOULS = 34432, // the real one to use might be 37099
+
+ // Combat spells
+ SPELL_BLACK_ARROW = 59712,
+ SPELL_FADE = 20672,
+ SPELL_FADE_BLINK = 29211,
+ SPELL_MULTI_SHOT = 59713,
+ SPELL_SHOT = 59710,
+ SPELL_SUMMON_SKELETON = 59711
};
float HighborneLoc[4][3]=
@@ -90,15 +98,27 @@ public:
{
npc_lady_sylvanas_windrunnerAI(Creature* creature) : ScriptedAI(creature) {}
- uint32 LamentEvent_Timer;
+ uint32 LamentEventTimer;
bool LamentEvent;
uint64 targetGUID;
+ uint32 FadeTimer;
+ uint32 SummonSkeletonTimer;
+ uint32 BlackArrowTimer;
+ uint32 ShotTimer;
+ uint32 MultiShotTimer;
+
void Reset()
{
- LamentEvent_Timer = 5000;
+ LamentEventTimer = 5000;
LamentEvent = false;
targetGUID = 0;
+
+ FadeTimer = 30000;
+ SummonSkeletonTimer = 20000;
+ BlackArrowTimer = 15000;
+ ShotTimer = 8000;
+ MultiShotTimer = 10000;
}
void EnterCombat(Unit* /*who*/) {}
@@ -123,23 +143,70 @@ public:
{
if (LamentEvent)
{
- if (LamentEvent_Timer <= diff)
+ if (LamentEventTimer <= diff)
{
DoSummon(ENTRY_HIGHBORNE_BUNNY, me, 10.0f, 3000, TEMPSUMMON_TIMED_DESPAWN);
- LamentEvent_Timer = 2000;
+ LamentEventTimer = 2000;
if (!me->HasAura(SPELL_SYLVANAS_CAST))
{
DoScriptText(SAY_LAMENT_END, me);
DoScriptText(EMOTE_LAMENT_END, me);
LamentEvent = false;
}
- } else LamentEvent_Timer -= diff;
+ } else LamentEventTimer -= diff;
}
if (!UpdateVictim())
return;
+ // Combat spells
+
+ if (FadeTimer <= diff)
+ {
+ DoCast(me, SPELL_FADE);
+ // add a blink to simulate a stealthed movement and reappearing elsewhere
+ DoCast(me, SPELL_FADE_BLINK);
+ FadeTimer = 30000 + rand()%5000;
+ // if the victim is out of melee range she cast multi shot
+ if (Unit* victim = me->getVictim())
+ if (me->GetDistance(victim) > 10.0f)
+ DoCast(victim, SPELL_MULTI_SHOT);
+ } else FadeTimer -= diff;
+
+ if (SummonSkeletonTimer <= diff)
+ {
+ DoCast(me, SPELL_SUMMON_SKELETON);
+ SummonSkeletonTimer = 20000 + rand()%10000;
+ } else SummonSkeletonTimer -= diff;
+
+ if (BlackArrowTimer <= diff)
+ {
+ if (Unit* victim = me->getVictim())
+ {
+ DoCast(me->getVictim(), SPELL_BLACK_ARROW);
+ BlackArrowTimer = 15000 + rand()%5000;
+ }
+ } else BlackArrowTimer -= diff;
+
+ if (ShotTimer <= diff)
+ {
+ if (Unit* victim = me->getVictim())
+ {
+ DoCast(me->getVictim(), SPELL_SHOT);
+ ShotTimer = 8000 + rand()%2000;
+ }
+ } else ShotTimer -= diff;
+
+ if (MultiShotTimer <= diff)
+ {
+ if (Unit* victim = me->getVictim())
+ {
+ DoCast(me->getVictim(), SPELL_MULTI_SHOT);
+ MultiShotTimer = 10000 + rand()%3000;
+ }
+ } else MultiShotTimer -= diff;
+
DoMeleeAttackIfReady();
}
};
@@ -163,15 +230,15 @@ public:
{
npc_highborne_lamenterAI(Creature* creature) : ScriptedAI(creature) {}
- uint32 EventMove_Timer;
- uint32 EventCast_Timer;
+ uint32 EventMoveTimer;
+ uint32 EventCastTimer;
bool EventMove;
bool EventCast;
void Reset()
{
- EventMove_Timer = 10000;
- EventCast_Timer = 17500;
+ EventMoveTimer = 10000;
+ EventCastTimer = 17500;
EventMove = true;
EventCast = true;
}
@@ -182,21 +249,21 @@ public:
{
if (EventMove)
{
- if (EventMove_Timer <= diff)
+ if (EventMoveTimer <= diff)
{
me->SetDisableGravity(true);
me->MonsterMoveWithSpeed(me->GetPositionX(), me->GetPositionY(), HIGHBORNE_LOC_Y_NEW, me->GetDistance(me->GetPositionX(), me->GetPositionY(), HIGHBORNE_LOC_Y_NEW) / (5000 * 0.001f));
me->SetPosition(me->GetPositionX(), me->GetPositionY(), HIGHBORNE_LOC_Y_NEW, me->GetOrientation());
EventMove = false;
- } else EventMove_Timer -= diff;
+ } else EventMoveTimer -= diff;
}
if (EventCast)
{
- if (EventCast_Timer <= diff)
+ if (EventCastTimer <= diff)
{
DoCast(me, SPELL_HIGHBORNE_AURA);
EventCast = false;
- } else EventCast_Timer -= diff;
+ } else EventCastTimer -= diff;
}
}
};
diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal.cpp
index 28457b3b461..22307468f14 100644
--- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal.cpp
+++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal.cpp
@@ -226,7 +226,6 @@ public:
player->SendNewItem(item, 1, true, false, true);
}
player->SEND_GOSSIP_MENU(907, creature->GetGUID());
- CAST_AI(hyjalAI, creature->AI());
}
return true;
}
diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/DarkPortal/instance_dark_portal.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/DarkPortal/instance_dark_portal.cpp
index dabf3db13cb..2c8cd096644 100644
--- a/src/server/scripts/Kalimdor/CavernsOfTime/DarkPortal/instance_dark_portal.cpp
+++ b/src/server/scripts/Kalimdor/CavernsOfTime/DarkPortal/instance_dark_portal.cpp
@@ -116,9 +116,9 @@ public:
DoUpdateWorldState(WORLD_STATE_BM_RIFT, 0);
}
- bool IsEncounterInProgress()
+ bool IsEncounterInProgress() const
{
- if (GetData(TYPE_MEDIVH) == IN_PROGRESS)
+ if (const_cast<instance_dark_portal_InstanceMapScript*>(this)->GetData(TYPE_MEDIVH) == IN_PROGRESS)
return true;
return false;
diff --git a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_moam.cpp b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_moam.cpp
index a290b07e60f..18a77519ba2 100644
--- a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_moam.cpp
+++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_moam.cpp
@@ -147,7 +147,7 @@ class boss_moam : public CreatureScript
targetList.push_back((*itr)->getTarget());
}
- Trinity::RandomResizeList(targetList, 5);
+ Trinity::Containers::RandomResizeList(targetList, 5);
for (std::list<Unit*>::iterator itr = targetList.begin(); itr != targetList.end(); ++itr)
DoCast(*itr, SPELL_DRAIN_MANA);
diff --git a/src/server/scripts/Kalimdor/silithus.cpp b/src/server/scripts/Kalimdor/silithus.cpp
index 66986ebd5ae..2d91f32fe9d 100644
--- a/src/server/scripts/Kalimdor/silithus.cpp
+++ b/src/server/scripts/Kalimdor/silithus.cpp
@@ -373,8 +373,13 @@ static QuestCinematic EventAnim[]=
{0, 0, 0}
};
+struct Location
+{
+ float x, y, z, o;
+};
+
//Cordinates for Spawns
-static const Position SpawnLocation[]=
+static Location SpawnLocation[]=
{
{-8085.0f, 1528.0f, 2.61f, 3.141592f}, //Kaldorei Infantry
{-8080.0f, 1526.0f, 2.61f, 3.141592f}, //Kaldorei Infantry
@@ -485,9 +490,9 @@ class npc_anachronos_the_ancient : public CreatureScript
public:
npc_anachronos_the_ancient() : CreatureScript("npc_anachronos_the_ancient") { }
- CreatureAI* GetAI(Creature* c) const
+ CreatureAI* GetAI(Creature* creature) const
{
- return new npc_anachronos_the_ancientAI(c);
+ return new npc_anachronos_the_ancientAI(creature);
}
struct npc_anachronos_the_ancientAI : public ScriptedAI
@@ -813,9 +818,9 @@ class mob_qiraj_war_spawn : public CreatureScript
public:
mob_qiraj_war_spawn() : CreatureScript("mob_qiraj_war_spawn") { }
- CreatureAI* GetAI(Creature* c) const
+ CreatureAI* GetAI(Creature* creature) const
{
- return new mob_qiraj_war_spawnAI(c);
+ return new mob_qiraj_war_spawnAI(creature);
}
struct mob_qiraj_war_spawnAI : public ScriptedAI
@@ -928,9 +933,9 @@ class npc_anachronos_quest_trigger : public CreatureScript
public:
npc_anachronos_quest_trigger() : CreatureScript("npc_anachronos_quest_trigger") { }
- CreatureAI* GetAI(Creature* c) const
+ CreatureAI* GetAI(Creature* creature) const
{
- return new npc_anachronos_quest_triggerAI(c);
+ return new npc_anachronos_quest_triggerAI(creature);
}
struct npc_anachronos_quest_triggerAI : public ScriptedAI
@@ -967,16 +972,19 @@ public:
void SummonNextWave()
{
- //uint8 count = WavesInfo[WaveCount].SpawnCount;
uint8 locIndex = WavesInfo[WaveCount].UsedSpawnPoint;
- //uint8 KaldoreiSoldierCount = 0;
- //uint8 AnubisathConquerorCount = 0;
- //uint8 QirajiWaspCount = 0;
- for (uint8 i = 0; i < 67; ++i)
+ uint8 count = locIndex + WavesInfo[WaveCount].SpawnCount;
+
+ for (uint8 i = locIndex; i <= count; ++i)
{
- if (Creature* spawn = me->SummonCreature(WavesInfo[WaveCount].CreatureId, SpawnLocation[locIndex + i], TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, WavesInfo[WaveCount].DespTimer))
+ float x = SpawnLocation[i].x;
+ float y = SpawnLocation[i].y;
+ float z = SpawnLocation[i].z;
+ float o = SpawnLocation[i].o;
+ uint32 desptimer = WavesInfo[WaveCount].DespTimer;
+
+ if (Creature* spawn = me->SummonCreature(WavesInfo[WaveCount].CreatureId, x, y, z, o, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, desptimer))
{
- spawn->LoadCreaturesAddon();
if (spawn->GetEntry() == 15423)
spawn->SetUInt32Value(UNIT_FIELD_DISPLAYID, 15427+rand()%4);
if (i >= 30) WaveCount = 1;
@@ -986,12 +994,15 @@ public:
if (WaveCount < 5) //1-4 Wave
{
- mob_qiraj_war_spawn::mob_qiraj_war_spawnAI* spawnAI = CAST_AI(mob_qiraj_war_spawn::mob_qiraj_war_spawnAI, spawn->AI());
- spawnAI->MobGUID = me->GetGUID();
- spawnAI->PlayerGUID = PlayerGUID;
+ if (mob_qiraj_war_spawn::mob_qiraj_war_spawnAI* spawnAI = CAST_AI(mob_qiraj_war_spawn::mob_qiraj_war_spawnAI, spawn->AI()))
+ {
+ spawnAI->MobGUID = me->GetGUID();
+ spawnAI->PlayerGUID = PlayerGUID;
+ }
}
}
}
+
WaveTimer = WavesInfo[WaveCount].SpawnTimer;
AnnounceTimer = WavesInfo[WaveCount].YellTimer;
}
@@ -1005,27 +1016,27 @@ public:
if (Group* EventGroup = player->GetGroup())
{
- Player* GroupMember;
+ Player* groupMember;
uint8 GroupMemberCount = 0;
uint8 DeadMemberCount = 0;
uint8 FailedMemberCount = 0;
- const Group::MemberSlotList members = EventGroup->GetMemberSlots();
+ Group::MemberSlotList const members = EventGroup->GetMemberSlots();
for (Group::member_citerator itr = members.begin(); itr!= members.end(); ++itr)
{
- GroupMember = (Unit::GetPlayer(*me, itr->guid));
- if (!GroupMember)
+ groupMember = (Unit::GetPlayer(*me, itr->guid));
+ if (!groupMember)
continue;
- if (!GroupMember->IsWithinDistInMap(me, EVENT_AREA_RADIUS) && GroupMember->GetQuestStatus(QUEST_A_PAWN_ON_THE_ETERNAL_BOARD) == QUEST_STATUS_INCOMPLETE)
+ if (!groupMember->IsWithinDistInMap(me, EVENT_AREA_RADIUS) && groupMember->GetQuestStatus(QUEST_A_PAWN_ON_THE_ETERNAL_BOARD) == QUEST_STATUS_INCOMPLETE)
{
- GroupMember->FailQuest(QUEST_A_PAWN_ON_THE_ETERNAL_BOARD);
+ groupMember->FailQuest(QUEST_A_PAWN_ON_THE_ETERNAL_BOARD);
++FailedMemberCount;
}
++GroupMemberCount;
- if (GroupMember->isDead())
+ if (groupMember->isDead())
++DeadMemberCount;
}
@@ -1069,8 +1080,13 @@ public:
void mob_qiraj_war_spawn::mob_qiraj_war_spawnAI::JustDied(Unit* /*slayer*/)
{
me->RemoveCorpse();
- if (Creature* Mob = (Unit::GetCreature(*me, MobGUID)))
- CAST_AI(npc_anachronos_quest_trigger::npc_anachronos_quest_triggerAI, Mob->AI())->LiveCounter();
+
+ if (!MobGUID)
+ return;
+
+ if (Creature* mob = Unit::GetCreature(*me, MobGUID))
+ if (npc_anachronos_quest_trigger::npc_anachronos_quest_triggerAI* triggerAI = CAST_AI(npc_anachronos_quest_trigger::npc_anachronos_quest_triggerAI, mob->AI()))
+ triggerAI->LiveCounter();
};
@@ -1087,15 +1103,13 @@ public:
{
if (quest->GetQuestId() == QUEST_A_PAWN_ON_THE_ETERNAL_BOARD)
{
-
- if (Unit* Anachronos_Quest_Trigger = go->FindNearestCreature(15454, 100, player))
+ if (Creature* trigger = go->FindNearestCreature(15454, 100, player))
{
-
- Unit* Merithra = Anachronos_Quest_Trigger->SummonCreature(15378, -8034.535f, 1535.14f, 2.61f, 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 220000);
- Unit* Caelestrasz = Anachronos_Quest_Trigger->SummonCreature(15379, -8032.767f, 1533.148f, 2.61f, 1.5f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 220000);
- Unit* Arygos = Anachronos_Quest_Trigger->SummonCreature(15380, -8034.52f, 1537.843f, 2.61f, 5.7f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 220000);
- /* Unit* Fandral = */ Anachronos_Quest_Trigger->SummonCreature(15382, -8028.462f, 1535.843f, 2.61f, 3.141592f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 220000);
- Creature* Anachronos = Anachronos_Quest_Trigger->SummonCreature(15381, -8028.75f, 1538.795f, 2.61f, 4, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 220000);
+ Unit* Merithra = trigger->SummonCreature(15378, -8034.535f, 1535.14f, 2.61f, 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 220000);
+ Unit* Caelestrasz = trigger->SummonCreature(15379, -8032.767f, 1533.148f, 2.61f, 1.5f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 220000);
+ Unit* Arygos = trigger->SummonCreature(15380, -8034.52f, 1537.843f, 2.61f, 5.7f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 220000);
+ /* Unit* Fandral = */ trigger->SummonCreature(15382, -8028.462f, 1535.843f, 2.61f, 3.141592f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 220000);
+ Creature* Anachronos = trigger->SummonCreature(15381, -8028.75f, 1538.795f, 2.61f, 4, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 220000);
if (Merithra)
{
@@ -1123,11 +1137,16 @@ public:
if (Anachronos)
{
- CAST_AI(npc_anachronos_the_ancient::npc_anachronos_the_ancientAI, Anachronos->AI())->PlayerGUID = player->GetGUID();
- CAST_AI(npc_anachronos_quest_trigger::npc_anachronos_quest_triggerAI, CAST_CRE(Anachronos_Quest_Trigger)->AI())->Failed=false;
- CAST_AI(npc_anachronos_quest_trigger::npc_anachronos_quest_triggerAI, CAST_CRE(Anachronos_Quest_Trigger)->AI())->PlayerGUID = player->GetGUID();
- CAST_AI(npc_anachronos_quest_trigger::npc_anachronos_quest_triggerAI, CAST_CRE(Anachronos_Quest_Trigger)->AI())->EventStarted=true;
- CAST_AI(npc_anachronos_quest_trigger::npc_anachronos_quest_triggerAI, CAST_CRE(Anachronos_Quest_Trigger)->AI())->Announced=true;
+ if (npc_anachronos_the_ancient::npc_anachronos_the_ancientAI* anachronosAI = CAST_AI(npc_anachronos_the_ancient::npc_anachronos_the_ancientAI, Anachronos->AI()))
+ anachronosAI->PlayerGUID = player->GetGUID();
+
+ if (npc_anachronos_quest_trigger::npc_anachronos_quest_triggerAI* triggerAI = CAST_AI(npc_anachronos_quest_trigger::npc_anachronos_quest_triggerAI, trigger->AI()))
+ {
+ triggerAI->Failed = false;
+ triggerAI->PlayerGUID = player->GetGUID();
+ triggerAI->EventStarted = true;
+ triggerAI->Announced = true;
+ }
}
}
}
diff --git a/src/server/scripts/Northrend/CMakeLists.txt b/src/server/scripts/Northrend/CMakeLists.txt
index 31aa924365d..3502e7fb104 100644
--- a/src/server/scripts/Northrend/CMakeLists.txt
+++ b/src/server/scripts/Northrend/CMakeLists.txt
@@ -22,7 +22,7 @@ set(scripts_STAT_SRCS
Northrend/Ulduar/Ulduar/ulduar_teleporter.cpp
Northrend/Ulduar/Ulduar/boss_thorim.cpp
Northrend/Ulduar/Ulduar/boss_ignis.cpp
- Northrend/Ulduar/Ulduar/boss_algalon.cpp
+ Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp
Northrend/Ulduar/Ulduar/instance_ulduar.cpp
Northrend/Ulduar/Ulduar/boss_auriaya.cpp
Northrend/Ulduar/Ulduar/boss_yoggsaron.cpp
diff --git a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_saviana_ragefire.cpp b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_saviana_ragefire.cpp
index 3407b42b2a7..4e5e01cc745 100644
--- a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_saviana_ragefire.cpp
+++ b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_saviana_ragefire.cpp
@@ -206,7 +206,7 @@ class spell_saviana_conflagration_init : public SpellScriptLoader
unitList.remove_if (ConflagrationTargetSelector());
uint8 maxSize = uint8(GetCaster()->GetMap()->GetSpawnMode() & 1 ? 6 : 3);
if (unitList.size() > maxSize)
- Trinity::RandomResizeList(unitList, maxSize);
+ Trinity::Containers::RandomResizeList(unitList, maxSize);
}
void HandleDummy(SpellEffIndex effIndex)
diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp
index 37516e5e0df..c718c0cee5f 100755
--- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp
+++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp
@@ -263,7 +263,8 @@ public:
if (instance)
instance->SetData(TYPE_ANUBARAK, IN_PROGRESS);
//Despawn Scarab Swarms neutral
- Summons.DoAction(NPC_SCARAB, ACTION_SCARAB_SUBMERGE);
+ EntryCheckPredicate pred(NPC_SCARAB);
+ Summons.DoAction(ACTION_SCARAB_SUBMERGE, pred);
//Spawn Burrow
for (int i=0; i < 4; i++)
me->SummonCreature(NPC_BURROW, AnubarakLoc[i+2]);
@@ -304,7 +305,8 @@ public:
if (IsHeroic() && m_uiNerubianShadowStrikeTimer <= uiDiff)
{
- Summons.DoAction(NPC_BURROWER, ACTION_SHADOW_STRIKE);
+ EntryCheckPredicate pred(NPC_BURROWER);
+ Summons.DoAction(ACTION_SHADOW_STRIKE, pred);
m_uiNerubianShadowStrikeTimer = 30*IN_MILLISECONDS;
} else m_uiNerubianShadowStrikeTimer -= uiDiff;
diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp
index 6f817a6d0eb..a7328b43826 100755
--- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp
+++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp
@@ -515,36 +515,6 @@ public:
};
-class spell_spinning_pain_spike : public SpellScriptLoader
-{
- public:
- spell_spinning_pain_spike() : SpellScriptLoader("spell_spinning_pain_spike") {}
-
- class spell_spinning_pain_spike_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_spinning_pain_spike_SpellScript);
-
- void HandleScript(SpellEffIndex /*eff*/)
- {
- Unit* target = GetHitUnit();
- if (!target)
- return;
-
- if (target->isAlive())
- SetHitDamage(target->CountPctFromMaxHealth(50));
- }
- void Register()
- {
- OnEffectHitTarget += SpellEffectFn(spell_spinning_pain_spike_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE);
- }
- };
-
- SpellScript* GetSpellScript() const
- {
- return new spell_spinning_pain_spike_SpellScript();
- }
-};
-
void AddSC_boss_jaraxxus()
{
new boss_jaraxxus();
@@ -553,5 +523,4 @@ void AddSC_boss_jaraxxus()
new mob_fel_infernal();
new mob_nether_portal();
new mob_mistress_of_pain();
- new spell_spinning_pain_spike();
}
diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp
index 74b9c038482..241d6239f82 100755
--- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp
+++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp
@@ -759,7 +759,7 @@ class spell_powering_up : public SpellScriptLoader
uint32 spellId;
- bool Validate(SpellEntry const* /*spellEntry*/)
+ bool Load()
{
spellId = sSpellMgr->GetSpellIdForDifficulty(SPELL_SURGE_OF_SPEED, GetCaster());
if (!sSpellMgr->GetSpellInfo(spellId))
diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_scourgelord_tyrannus.cpp b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_scourgelord_tyrannus.cpp
index 88e9bedcd07..8d015adf4a4 100644
--- a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_scourgelord_tyrannus.cpp
+++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_scourgelord_tyrannus.cpp
@@ -387,8 +387,7 @@ class player_overlord_brandAI : public PlayerAI
void SetGUID(uint64 guid, int32 /*type*/)
{
tyrannus = ObjectAccessor::GetCreature(*me, guid);
- if (!tyrannus)
- me->IsAIEnabled = false;
+ me->IsAIEnabled = tyrannus != NULL;
}
void DamageDealt(Unit* /*victim*/, uint32& damage, DamageEffectType /*damageType*/)
@@ -423,10 +422,9 @@ class spell_tyrannus_overlord_brand : public SpellScriptLoader
return;
oldAI = GetTarget()->GetAI();
+ oldAIState = GetTarget()->IsAIEnabled;
GetTarget()->SetAI(new player_overlord_brandAI(GetTarget()->ToPlayer()));
GetTarget()->GetAI()->SetGUID(GetCasterGUID());
- oldAIState = GetTarget()->IsAIEnabled;
- GetTarget()->IsAIEnabled = true;
}
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.cpp b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.cpp
index a91951ca25e..70d72e52e67 100644
--- a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.cpp
+++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.cpp
@@ -240,12 +240,13 @@ class mob_geist_ambusher : public CreatureScript
_leapingFaceMaulCooldown = 9000;
}
- void MoveInLineOfSight(Unit* who)
+ void EnterCombat(Unit* who)
{
if (who->GetTypeId() != TYPEID_PLAYER)
return;
- if (me->IsWithinDistInMap(who, 30.0f))
+ // the max range is determined by aggro range
+ if (me->GetDistance(who) > 5.0f)
DoCast(who, SPELL_LEAPING_FACE_MAUL);
}
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp
index de104a78e43..8090fc98101 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp
@@ -103,6 +103,7 @@ enum Spells
SPELL_UNSTABLE = 72059,
SPELL_KINETIC_BOMB_VISUAL = 72054,
SPELL_KINETIC_BOMB_EXPLOSION = 72052,
+ SPELL_KINETIC_BOMB_KNOCKBACK = 72087,
// Shock Vortex
SPELL_SHOCK_VORTEX_PERIODIC = 71945,
@@ -443,20 +444,12 @@ class boss_prince_keleseth_icc : public CreatureScript
{
summons.Summon(summon);
Position pos;
- pos.Relocate(summon);
+ me->GetPosition(&pos);
float maxRange = me->GetDistance2d(summon);
float angle = me->GetAngle(summon);
- // prevent spawning outside of room
- while (!me->IsWithinLOS(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()))
- {
- maxRange -= 5.0f;
- if (maxRange < 5.0f)
- break;
-
- summon->MovePosition(pos, float(rand_norm() * maxRange), angle);
- }
-
+ me->MovePositionToFirstCollision(pos, maxRange, angle);
summon->NearTeleportTo(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation());
+ summon->ToTempSummon()->SetTempSummonType(TEMPSUMMON_CORPSE_DESPAWN);
}
void DamageDealt(Unit* /*target*/, uint32& damage, DamageEffectType damageType)
@@ -894,6 +887,7 @@ class boss_prince_valanar_icc : public CreatureScript
summon->GetPosition(x, y, z);
float ground_Z = summon->GetMap()->GetHeight(summon->GetPhaseMask(), x, y, z, true, 500.0f);
summon->GetMotionMaster()->MovePoint(POINT_KINETIC_BOMB_IMPACT, x, y, ground_Z);
+ summon->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
break;
}
case NPC_SHOCK_VORTEX:
@@ -1073,7 +1067,7 @@ class npc_blood_queen_lana_thel : public CreatureScript
if (_introDone)
return;
- if (!me->IsWithinDistInMap(who, 35.0f))
+ if (!me->IsWithinDistInMap(who, 35.0f, false))
return;
_introDone = true;
@@ -1232,12 +1226,12 @@ class npc_kinetic_bomb : public CreatureScript
void Reset()
{
_events.Reset();
- me->SetDisplayId(DISPLAY_KINETIC_BOMB);
+ me->SetWalk(true);
me->CastSpell(me, SPELL_UNSTABLE, true);
me->CastSpell(me, SPELL_KINETIC_BOMB_VISUAL, true);
me->SetReactState(REACT_PASSIVE);
- me->SetSpeed(MOVE_FLIGHT, IsHeroic() ? 0.3f : 0.15f, true);
me->GetPosition(_x, _y, _groundZ);
+ me->DespawnOrUnsummon(60000);
_groundZ = me->GetMap()->GetHeight(me->GetPhaseMask(), _x, _y, _groundZ, true, 500.0f);
}
@@ -1247,9 +1241,9 @@ class npc_kinetic_bomb : public CreatureScript
_events.ScheduleEvent(EVENT_BOMB_DESPAWN, 1000);
else if (action == ACTION_KINETIC_BOMB_JUMP)
{
- me->GetMotionMaster()->Clear();
- me->GetMotionMaster()->MoveJump(_x, _y, me->GetPositionZ() + 7.0f, 1.0f, 7.0f);
- _events.ScheduleEvent(EVENT_CONTINUE_FALLING, 700);
+ if (!me->HasAura(SPELL_KINETIC_BOMB_KNOCKBACK))
+ me->GetMotionMaster()->MoveCharge(_x, _y, me->GetPositionZ() + 100.0f, me->GetSpeed(MOVE_RUN), 0);
+ _events.RescheduleEvent(EVENT_CONTINUE_FALLING, 3000);
}
}
@@ -1263,10 +1257,10 @@ class npc_kinetic_bomb : public CreatureScript
{
case EVENT_BOMB_DESPAWN:
me->SetVisible(false);
+ me->DespawnOrUnsummon(5000);
break;
case EVENT_CONTINUE_FALLING:
- me->GetMotionMaster()->Clear();
- me->GetMotionMaster()->MovePoint(POINT_KINETIC_BOMB_IMPACT, _x, _y, _groundZ);
+ me->GetMotionMaster()->MoveCharge(_x, _y, _groundZ, me->GetSpeed(MOVE_WALK), POINT_KINETIC_BOMB_IMPACT);
break;
default:
break;
@@ -1329,17 +1323,16 @@ class npc_dark_nucleus : public CreatureScript
void DamageTaken(Unit* attacker, uint32& /*damage*/)
{
- if (attacker == me)
+ if (attacker == me || attacker == me->getVictim())
return;
- if (!_lockedTarget)
- if (me->getVictim() == attacker)
- _lockedTarget = true;
+ me->DeleteThreatList();
+ me->AddThreat(attacker, 500000000.0f);
}
- void UpdateAI(const uint32 diff)
+ void UpdateAI(uint32 const diff)
{
- if (!me->isInCombat())
+ if (!UpdateVictim())
return;
if (_targetAuraCheck <= diff)
@@ -1355,23 +1348,6 @@ class npc_dark_nucleus : public CreatureScript
}
else
_targetAuraCheck -= diff;
-
- if (!_lockedTarget)
- {
- if (Unit* victim = me->SelectVictim())
- {
- if (me->getVictim() && me->getVictim() != victim)
- {
- me->getVictim()->RemoveAurasDueToSpell(SPELL_SHADOW_RESONANCE_RESIST, me->GetGUID());
- _lockedTarget = true;
- }
-
- _lockedTarget = true;
- AttackStart(victim);
- DoCast(victim, SPELL_SHADOW_RESONANCE_RESIST);
- me->ClearUnitState(UNIT_STATE_CASTING);
- }
- }
}
private:
@@ -1525,6 +1501,7 @@ class spell_valanar_kinetic_bomb : public SpellScriptLoader
Position offset = {0.0f, 0.0f, 20.0f, 0.0f};
summonPos.RelocateOffset(offset);
SetTargetDest(summonPos);
+ GetHitDest()->RelocateOffset(offset);
}
void Register()
@@ -1586,7 +1563,7 @@ class spell_valanar_kinetic_bomb_knockback : public SpellScriptLoader
void Register()
{
- AfterHit += SpellHitFn(spell_valanar_kinetic_bomb_knockback_SpellScript::KnockIntoAir);
+ BeforeHit += SpellHitFn(spell_valanar_kinetic_bomb_knockback_SpellScript::KnockIntoAir);
}
};
@@ -1663,7 +1640,7 @@ class spell_blood_council_shadow_prison_damage : public SpellScriptLoader
void AddExtraDamage()
{
if (Aura* aur = GetHitUnit()->GetAura(GetSpellInfo()->Id))
- if (AuraEffect const* eff = aur->GetEffect(1))
+ if (AuraEffect const* eff = aur->GetEffect(EFFECT_1))
SetHitDamage(GetHitDamage() + eff->GetAmount());
}
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp
index 784cda8f595..b6544fd9a2a 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp
@@ -386,7 +386,7 @@ class boss_blood_queen_lana_thel : public CreatureScript
++targetCount;
if (Is25ManRaid())
++targetCount;
- Trinity::RandomResizeList<Player*>(targets, targetCount);
+ Trinity::Containers::RandomResizeList<Player*>(targets, targetCount);
if (targets.size() > 1)
{
Talk(SAY_PACT_OF_THE_DARKFALLEN);
@@ -409,7 +409,7 @@ class boss_blood_queen_lana_thel : public CreatureScript
{
std::list<Player*> targets;
SelectRandomTarget(false, &targets);
- Trinity::RandomResizeList<Player*>(targets, uint32(Is25ManRaid() ? 4 : 2));
+ Trinity::Containers::RandomResizeList<Player*>(targets, uint32(Is25ManRaid() ? 4 : 2));
for (std::list<Player*>::iterator itr = targets.begin(); itr != targets.end(); ++itr)
DoCast(*itr, SPELL_TWILIGHT_BLOODBOLT);
DoCast(me, SPELL_TWILIGHT_BLOODBOLT_TARGET);
@@ -481,7 +481,7 @@ class boss_blood_queen_lana_thel : public CreatureScript
return tempTargets.front();
}
- return SelectRandomContainerElement(tempTargets);
+ return Trinity::Containers::SelectRandomContainerElement(tempTargets);
}
std::set<uint64> _vampires;
@@ -658,7 +658,7 @@ class spell_blood_queen_bloodbolt : public SpellScriptLoader
{
uint32 targetCount = (targets.size() + 2) / 3;
targets.remove_if (BloodboltHitCheck(static_cast<LanaThelAI*>(GetCaster()->GetAI())));
- Trinity::RandomResizeList(targets, targetCount);
+ Trinity::Containers::RandomResizeList(targets, targetCount);
// mark targets now, effect hook has missile travel time delay (might cast next in that time)
for (std::list<Unit*>::const_iterator itr = targets.begin(); itr != targets.end(); ++itr)
GetCaster()->GetAI()->SetGUID((*itr)->GetGUID(), GUID_BLOODBOLT);
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp
index 3ce62d939d3..249eed01643 100755
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp
@@ -1272,7 +1272,7 @@ class spell_deathbringer_boiling_blood : public SpellScriptLoader
if (unitList.empty())
return;
- Unit* target = SelectRandomContainerElement(unitList);
+ Unit* target = Trinity::Containers::SelectRandomContainerElement(unitList);
unitList.clear();
unitList.push_back(target);
}
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp
index ea2f73e788f..e2f9faf6a97 100755
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp
@@ -605,7 +605,7 @@ class boss_lady_deathwhisper : public CreatureScript
return;
// select random cultist
- Creature* cultist = SelectRandomContainerElement(temp);
+ Creature* cultist = Trinity::Containers::SelectRandomContainerElement(temp);
DoCast(cultist, cultist->GetEntry() == NPC_CULT_FANATIC ? SPELL_DARK_TRANSFORMATION_T : SPELL_DARK_EMPOWERMENT_T, true);
Talk(uint8(cultist->GetEntry() == NPC_CULT_FANATIC ? SAY_DARK_TRANSFORMATION : SAY_DARK_EMPOWERMENT));
}
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp
index 44bc40d08bd..c043cb27c7c 100755
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp
@@ -64,6 +64,9 @@ enum Spells
SPELL_MALLEABLE_GOO = 70852,
SPELL_UNSTABLE_EXPERIMENT = 70351,
SPELL_TEAR_GAS = 71617, // phase transition
+ SPELL_TEAR_GAS_CREATURE = 71618,
+ SPELL_TEAR_GAS_CANCEL = 71620,
+ SPELL_TEAR_GAS_PERIODIC_TRIGGER = 73170,
SPELL_CREATE_CONCOCTION = 71621,
SPELL_GUZZLE_POTIONS = 71893,
SPELL_OOZE_TANK_PROTECTION = 71770, // protects the tank
@@ -86,6 +89,7 @@ enum Spells
SPELL_GASEOUS_BLOAT_PROC = 70215,
SPELL_GASEOUS_BLOAT = 70672,
SPELL_GASEOUS_BLOAT_PROTECTION = 70812,
+ SPELL_EXPUNGED_GAS = 70701,
// Volatile Ooze
SPELL_OOZE_ERUPTION = 70492,
@@ -167,6 +171,33 @@ enum PutricideData
#define EXPERIMENT_STATE_OOZE false
#define EXPERIMENT_STATE_GAS true
+class AbominationDespawner
+{
+ public:
+ explicit AbominationDespawner(Unit* owner) : _owner(owner) { }
+
+ bool operator()(uint64 guid)
+ {
+ if (Unit* summon = ObjectAccessor::GetUnit(*_owner, guid))
+ {
+ if (summon->GetEntry() == NPC_MUTATED_ABOMINATION_10 || summon->GetEntry() == NPC_MUTATED_ABOMINATION_25)
+ {
+ if (Vehicle* veh = summon->GetVehicleKit())
+ veh->RemoveAllPassengers(); // also despawns the vehicle
+
+ return true;
+ }
+
+ return false;
+ }
+
+ return true;
+ }
+
+ private:
+ Unit* _owner;
+};
+
class boss_professor_putricide : public CreatureScript
{
public:
@@ -477,8 +508,7 @@ class boss_professor_putricide : public CreatureScript
SetPhase(PHASE_COMBAT_3);
events.ScheduleEvent(EVENT_MUTATED_PLAGUE, 25000);
events.CancelEvent(EVENT_UNSTABLE_EXPERIMENT);
- summons.DespawnEntry(NPC_MUTATED_ABOMINATION_10);
- summons.DespawnEntry(NPC_MUTATED_ABOMINATION_25);
+ summons.remove_if(AbominationDespawner(me));
break;
default:
break;
@@ -514,7 +544,7 @@ class boss_professor_putricide : public CreatureScript
void UpdateAI(uint32 const diff)
{
- if ((!UpdateVictim() && !(events.GetPhaseMask() & PHASE_MASK_NOT_SELF)) || !CheckInRoom())
+ if ((!(events.GetPhaseMask() & PHASE_MASK_NOT_SELF) && !UpdateVictim()) || !CheckInRoom())
return;
events.Update(diff);
@@ -569,13 +599,15 @@ class boss_professor_putricide : public CreatureScript
break;
case EVENT_TEAR_GAS:
me->GetMotionMaster()->MovePoint(POINT_TABLE, tablePos);
+ DoCast(me, SPELL_TEAR_GAS_PERIODIC_TRIGGER, true);
break;
case EVENT_RESUME_ATTACK:
me->SetReactState(REACT_DEFENSIVE);
AttackStart(me->getVictim());
// remove Tear Gas
+ me->RemoveAurasDueToSpell(SPELL_TEAR_GAS_PERIODIC_TRIGGER);
instance->DoRemoveAurasDueToSpellOnPlayers(71615);
- instance->DoRemoveAurasDueToSpellOnPlayers(71618);
+ DoCastAOE(SPELL_TEAR_GAS_CANCEL);
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_GAS_VARIABLE);
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_OOZE_VARIABLE);
break;
@@ -673,27 +705,36 @@ class npc_volatile_ooze : public CreatureScript
public:
npc_volatile_ooze() : CreatureScript("npc_volatile_ooze") { }
- struct npc_volatile_oozeAI : public ScriptedAI
+ struct npc_putricide_oozeAI : public ScriptedAI
{
- npc_volatile_oozeAI(Creature* creature) : ScriptedAI(creature)
+ npc_putricide_oozeAI(Creature* creature) : ScriptedAI(creature)
{
_newTargetSelectTimer = 0;
}
void SpellHitTarget(Unit* /*target*/, SpellInfo const* spell)
{
- if (!_newTargetSelectTimer && sSpellMgr->GetSpellDifficultyId(spell->Id) == sSpellMgr->GetSpellDifficultyId(SPELL_OOZE_ERUPTION))
+ if (!_newTargetSelectTimer && spell->Id == sSpellMgr->GetSpellIdForDifficulty(SPELL_OOZE_ERUPTION, me))
+ _newTargetSelectTimer = 1000;
+ }
+
+ void SpellHit(Unit* /*caster*/, SpellInfo const* spell)
+ {
+ if (spell->Id == SPELL_TEAR_GAS_CREATURE)
_newTargetSelectTimer = 1000;
}
void UpdateAI(uint32 const diff)
{
- if (!UpdateVictim())
+ if (!UpdateVictim() && !_newTargetSelectTimer)
return;
if (!_newTargetSelectTimer)
return;
+ if (me->HasAura(SPELL_TEAR_GAS_CREATURE))
+ return;
+
if (_newTargetSelectTimer <= diff)
{
_newTargetSelectTimer = 0;
@@ -704,13 +745,68 @@ class npc_volatile_ooze : public CreatureScript
}
private:
- // no need to use EventMap for just one event
uint32 _newTargetSelectTimer;
};
CreatureAI* GetAI(Creature* creature) const
{
- return GetIcecrownCitadelAI<npc_volatile_oozeAI>(creature);
+ return GetIcecrownCitadelAI<npc_putricide_oozeAI>(creature);
+ }
+};
+
+class npc_gas_cloud : public CreatureScript
+{
+ public:
+ npc_gas_cloud() : CreatureScript("npc_gas_cloud") { }
+
+ struct npc_gas_cloudAI : public ScriptedAI
+ {
+ npc_gas_cloudAI(Creature* creature) : ScriptedAI(creature)
+ {
+ _newTargetSelectTimer = 0;
+ }
+
+ void SpellHitTarget(Unit* /*target*/, SpellInfo const* spell)
+ {
+ if (!_newTargetSelectTimer && spell->Id == sSpellMgr->GetSpellIdForDifficulty(SPELL_EXPUNGED_GAS, me))
+ _newTargetSelectTimer = 1000;
+ }
+
+ void SpellHit(Unit* /*caster*/, SpellInfo const* spell)
+ {
+ if (spell->Id == SPELL_TEAR_GAS_CREATURE)
+ _newTargetSelectTimer = 1000;
+ }
+
+ void UpdateAI(uint32 const diff)
+ {
+ if (!UpdateVictim() && !_newTargetSelectTimer)
+ return;
+
+ DoMeleeAttackIfReady();
+
+ if (!_newTargetSelectTimer)
+ return;
+
+ if (me->HasAura(SPELL_TEAR_GAS_CREATURE))
+ return;
+
+ if (_newTargetSelectTimer <= diff)
+ {
+ _newTargetSelectTimer = 0;
+ me->CastCustomSpell(SPELL_GASEOUS_BLOAT, SPELLVALUE_AURA_STACK, 10, me, false);
+ }
+ else
+ _newTargetSelectTimer -= diff;
+ }
+
+ private:
+ uint32 _newTargetSelectTimer;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return GetIcecrownCitadelAI<npc_gas_cloudAI>(creature);
}
};
@@ -729,8 +825,8 @@ class spell_putricide_gaseous_bloat : public SpellScriptLoader
if (Unit* caster = GetCaster())
{
target->RemoveAuraFromStack(GetSpellInfo()->Id, GetCasterGUID());
- if (!target->HasAura(GetId())&& caster->GetTypeId() == TYPEID_UNIT)
- caster->ToCreature()->DespawnOrUnsummon();
+ if (!target->HasAura(GetId()))
+ caster->CastCustomSpell(SPELL_GASEOUS_BLOAT, SPELLVALUE_AURA_STACK, 10, caster, false);
}
}
@@ -781,7 +877,7 @@ class spell_putricide_ooze_channel : public SpellScriptLoader
return;
}
- Unit* target = SelectRandomContainerElement(targetList);
+ Unit* target = Trinity::Containers::SelectRandomContainerElement(targetList);
targetList.clear();
targetList.push_back(target);
_target = target;
@@ -797,7 +893,19 @@ class spell_putricide_ooze_channel : public SpellScriptLoader
void StartAttack()
{
GetCaster()->ClearUnitState(UNIT_STATE_CASTING);
+ GetCaster()->DeleteThreatList();
GetCaster()->ToCreature()->AI()->AttackStart(GetHitUnit());
+ GetCaster()->AddThreat(GetHitUnit(), 500000000.0f); // value seen in sniff
+ }
+
+ // temporary, until SelectTarget are not called on empty lists
+ void CheckTarget()
+ {
+ if (_target)
+ return;
+
+ FinishCast(SPELL_FAILED_NO_VALID_TARGETS);
+ GetCaster()->ToCreature()->DespawnOrUnsummon(1); // despawn next update
}
void Register()
@@ -806,6 +914,7 @@ class spell_putricide_ooze_channel : public SpellScriptLoader
OnUnitTargetSelect += SpellUnitTargetFn(spell_putricide_ooze_channel_SpellScript::SetTarget, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY);
OnUnitTargetSelect += SpellUnitTargetFn(spell_putricide_ooze_channel_SpellScript::SetTarget, EFFECT_2, TARGET_UNIT_SRC_AREA_ENEMY);
AfterHit += SpellHitFn(spell_putricide_ooze_channel_SpellScript::StartAttack);
+ OnCast += SpellCastFn(spell_putricide_ooze_channel_SpellScript::CheckTarget);
}
Unit* _target;
@@ -905,13 +1014,13 @@ class spell_putricide_unstable_experiment : public SpellScriptLoader
uint32 stage = GetCaster()->ToCreature()->AI()->GetData(DATA_EXPERIMENT_STAGE);
Creature* target = NULL;
std::list<Creature*> creList;
- GetCreatureListWithEntryInGrid(creList, GetCaster(), NPC_ABOMINATION_WING_MAD_SCIENTIST_STALKER, 100.0f);
+ GetCreatureListWithEntryInGrid(creList, GetCaster(), NPC_ABOMINATION_WING_MAD_SCIENTIST_STALKER, 200.0f);
// 2 of them are spawned at green place - weird trick blizz
for (std::list<Creature*>::iterator itr = creList.begin(); itr != creList.end(); ++itr)
{
target = *itr;
std::list<Creature*> tmp;
- GetCreatureListWithEntryInGrid(tmp, target, NPC_ABOMINATION_WING_MAD_SCIENTIST_STALKER, 1.0f);
+ GetCreatureListWithEntryInGrid(tmp, target, NPC_ABOMINATION_WING_MAD_SCIENTIST_STALKER, 10.0f);
if ((!stage && tmp.size() > 1) || (stage && tmp.size() == 1))
break;
}
@@ -931,42 +1040,6 @@ class spell_putricide_unstable_experiment : public SpellScriptLoader
}
};
-class spell_putricide_ooze_summon : public SpellScriptLoader
-{
- public:
- spell_putricide_ooze_summon() : SpellScriptLoader("spell_putricide_ooze_summon") { }
-
- class spell_putricide_ooze_summon_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_putricide_ooze_summon_AuraScript);
-
- void HandleTriggerSpell(AuraEffect const* aurEff)
- {
- PreventDefaultAction();
- if (Unit* caster = GetCaster())
- {
- uint32 triggerSpellId = GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell;
- float x, y, z;
- GetTarget()->GetPosition(x, y, z);
- z = GetTarget()->GetMap()->GetHeight(GetTarget()->GetPhaseMask(), x, y, z, true, 25.0f);
- x += 10.0f * cosf(caster->GetOrientation());
- y += 10.0f * sinf(caster->GetOrientation());
- caster->CastSpell(x, y, z, triggerSpellId, true, NULL, NULL, GetCasterGUID());
- }
- }
-
- void Register()
- {
- OnEffectPeriodic += AuraEffectPeriodicFn(spell_putricide_ooze_summon_AuraScript::HandleTriggerSpell, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
- }
- };
-
- AuraScript* GetAuraScript() const
- {
- return new spell_putricide_ooze_summon_AuraScript();
- }
-};
-
class spell_putricide_ooze_eruption_searcher : public SpellScriptLoader
{
public:
@@ -1429,14 +1502,15 @@ class spell_putricide_regurgitated_ooze : public SpellScriptLoader
}
};
-class spell_putricide_clear_mutated_plague : public SpellScriptLoader
+// Removes aura with id stored in effect value
+class spell_putricide_clear_aura_effect_value : public SpellScriptLoader
{
public:
- spell_putricide_clear_mutated_plague() : SpellScriptLoader("spell_putricide_clear_mutated_plague") { }
+ spell_putricide_clear_aura_effect_value() : SpellScriptLoader("spell_putricide_clear_aura_effect_value") { }
- class spell_putricide_clear_mutated_plague_SpellScript : public SpellScript
+ class spell_putricide_clear_aura_effect_value_SpellScript : public SpellScript
{
- PrepareSpellScript(spell_putricide_clear_mutated_plague_SpellScript);
+ PrepareSpellScript(spell_putricide_clear_aura_effect_value_SpellScript);
void HandleScript(SpellEffIndex effIndex)
{
@@ -1447,13 +1521,13 @@ class spell_putricide_clear_mutated_plague : public SpellScriptLoader
void Register()
{
- OnEffectHitTarget += SpellEffectFn(spell_putricide_clear_mutated_plague_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ OnEffectHitTarget += SpellEffectFn(spell_putricide_clear_aura_effect_value_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
SpellScript* GetSpellScript() const
{
- return new spell_putricide_clear_mutated_plague_SpellScript();
+ return new spell_putricide_clear_aura_effect_value_SpellScript();
}
};
@@ -1492,12 +1566,12 @@ void AddSC_boss_professor_putricide()
{
new boss_professor_putricide();
new npc_volatile_ooze();
+ new npc_gas_cloud();
new spell_putricide_gaseous_bloat();
new spell_putricide_ooze_channel();
new spell_putricide_slime_puddle();
new spell_putricide_slime_puddle_aura();
new spell_putricide_unstable_experiment();
- new spell_putricide_ooze_summon();
new spell_putricide_ooze_eruption_searcher();
new spell_putricide_choking_gas_bomb();
new spell_putricide_unbound_plague();
@@ -1508,6 +1582,6 @@ void AddSC_boss_professor_putricide()
new spell_putricide_mutated_transformation();
new spell_putricide_mutated_transformation_dmg();
new spell_putricide_regurgitated_ooze();
- new spell_putricide_clear_mutated_plague();
+ new spell_putricide_clear_aura_effect_value();
new spell_stinky_precious_decimate();
}
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp
index 09707b2d9ab..85de6789784 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp
@@ -498,7 +498,7 @@ class spell_rotface_mutated_infection : public SpellScriptLoader
if (targets.empty())
return;
- Unit* target = SelectRandomContainerElement(targets);
+ Unit* target = Trinity::Containers::SelectRandomContainerElement(targets);
targets.clear();
targets.push_back(target);
_target = target;
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp
index c88b3aa8b37..ebf9ae02a95 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp
@@ -61,6 +61,7 @@ enum Spells
SPELL_ASPHYXIATION = 71665,
SPELL_FROST_BOMB_TRIGGER = 69846,
SPELL_FROST_BOMB_VISUAL = 70022,
+ SPELL_BIRTH_NO_VISUAL = 40031,
SPELL_FROST_BOMB = 69845,
SPELL_MYSTIC_BUFFET = 70128,
@@ -98,6 +99,8 @@ enum Events
EVENT_LAND = 12,
EVENT_AIR_MOVEMENT = 21,
EVENT_THIRD_PHASE_CHECK = 22,
+ EVENT_AIR_MOVEMENT_FAR = 23,
+ EVENT_LAND_GROUND = 24,
// Spinestalker
EVENT_BELLOWING_ROAR = 13,
@@ -133,6 +136,8 @@ enum MovementPoints
POINT_AIR_PHASE = 3,
POINT_TAKEOFF = 4,
POINT_LAND = 5,
+ POINT_AIR_PHASE_FAR = 6,
+ POINT_LAND_GROUND = 7,
};
enum Shadowmourne
@@ -152,6 +157,8 @@ Position const SindragosaSpawnPos = {4818.700f, 2483.710f, 287.0650f, 3.089233f
Position const SindragosaFlyPos = {4475.190f, 2484.570f, 234.8510f, 3.141593f};
Position const SindragosaLandPos = {4419.190f, 2484.570f, 203.3848f, 3.141593f};
Position const SindragosaAirPos = {4475.990f, 2484.430f, 247.9340f, 3.141593f};
+Position const SindragosaAirPosFar = {4525.600f, 2485.150f, 245.0820f, 3.141593f};
+Position const SindragosaFlyInPos = {4419.190f, 2484.360f, 232.5150f, 3.141593f};
class FrostwyrmLandEvent : public BasicEvent
{
@@ -169,6 +176,23 @@ class FrostwyrmLandEvent : public BasicEvent
Position const& _dest;
};
+class FrostBombExplosion : public BasicEvent
+{
+ public:
+ FrostBombExplosion(Creature* owner, uint64 sindragosaGUID) : _owner(owner), _sindragosaGUID(sindragosaGUID) { }
+
+ bool Execute(uint64 /*eventTime*/, uint32 /*updateTime*/)
+ {
+ _owner->CastSpell((Unit*)NULL, SPELL_FROST_BOMB, true, NULL, NULL, _sindragosaGUID);
+ _owner->RemoveAurasDueToSpell(SPELL_FROST_BOMB_VISUAL);
+ return true;
+ }
+
+ private:
+ Creature* _owner;
+ uint64 _sindragosaGUID;
+};
+
class boss_sindragosa : public CreatureScript
{
public:
@@ -293,20 +317,31 @@ class boss_sindragosa : public CreatureScript
break;
case POINT_AIR_PHASE:
me->CastCustomSpell(SPELL_ICE_TOMB_TARGET, SPELLVALUE_MAX_TARGETS, RAID_MODE<int32>(2, 5, 2, 6), NULL);
- events.ScheduleEvent(EVENT_FROST_BOMB, 8000);
+ me->SetFacingTo(float(M_PI));
+ events.ScheduleEvent(EVENT_AIR_MOVEMENT_FAR, 1);
+ events.ScheduleEvent(EVENT_FROST_BOMB, 9000);
+ break;
+ case POINT_AIR_PHASE_FAR:
+ me->SetFacingTo(float(M_PI));
+ events.ScheduleEvent(EVENT_LAND, 30000);
break;
case POINT_LAND:
+ events.ScheduleEvent(EVENT_LAND_GROUND, 1);
+ break;
+ case POINT_LAND_GROUND:
+ {
me->SetCanFly(false);
me->SetDisableGravity(false);
me->RemoveByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER);
me->SetReactState(REACT_DEFENSIVE);
if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == POINT_MOTION_TYPE)
me->GetMotionMaster()->MovementExpired();
- DoStartMovement(me->getVictim());
_isInAirPhase = false;
// trigger Asphyxiation
- summons.DoAction(NPC_ICE_TOMB, ACTION_TRIGGER_ASPHYXIATION);
+ EntryCheckPredicate pred(NPC_ICE_TOMB);
+ summons.DoAction(ACTION_TRIGGER_ASPHYXIATION, pred);
break;
+ }
default:
break;
}
@@ -325,6 +360,12 @@ class boss_sindragosa : public CreatureScript
void JustSummoned(Creature* summon)
{
summons.Summon(summon);
+ if (summon->GetEntry() == NPC_FROST_BOMB)
+ {
+ summon->CastSpell(summon, SPELL_FROST_BOMB_VISUAL, true);
+ summon->CastSpell(summon, SPELL_BIRTH_NO_VISUAL, true);
+ summon->m_Events.AddEvent(new FrostBombExplosion(summon, me->GetGUID()), summon->m_Events.CalculateTime(5500));
+ }
}
void SummonedCreatureDespawn(Creature* summon)
@@ -337,18 +378,25 @@ class boss_sindragosa : public CreatureScript
void SpellHitTarget(Unit* target, SpellInfo const* spell)
{
if (uint32 spellId = sSpellMgr->GetSpellIdForDifficulty(70127, me))
+ {
if (spellId == spell->Id)
+ {
if (Aura const* mysticBuffet = target->GetAura(spell->Id))
_mysticBuffetStack = std::max<uint8>(_mysticBuffetStack, mysticBuffet->GetStackAmount());
+ return;
+ }
+ }
+
// Frost Infusion
if (Player* player = target->ToPlayer())
{
if (uint32 spellId = sSpellMgr->GetSpellIdForDifficulty(_isThirdPhase ? SPELL_FROST_BREATH_P2 : SPELL_FROST_BREATH_P1, me))
{
- if (player->GetQuestStatus(QUEST_FROST_INFUSION) == QUEST_STATUS_INCOMPLETE && spellId == spell->Id)
+ if (spellId == spell->Id)
{
- if (Item* shadowsEdge = player->GetWeaponForAttack(BASE_ATTACK, true))
+ Item* shadowsEdge = player->GetWeaponForAttack(BASE_ATTACK, true);
+ if (player->GetQuestStatus(QUEST_FROST_INFUSION) == QUEST_STATUS_INCOMPLETE && shadowsEdge)
{
if (!player->HasAura(SPELL_FROST_IMBUED_BLADE) && shadowsEdge->GetEntry() == ITEM_SHADOW_S_EDGE)
{
@@ -366,15 +414,11 @@ class boss_sindragosa : public CreatureScript
player->CastSpell(player, SPELL_FROST_INFUSION, true);
}
}
+
+ return;
}
}
}
-
- if (spell->Id == SPELL_FROST_BOMB_TRIGGER)
- {
- target->CastSpell(target, SPELL_FROST_BOMB, true);
- target->RemoveAurasDueToSpell(SPELL_FROST_BOMB_VISUAL);
- }
}
void UpdateAI(uint32 const diff)
@@ -415,7 +459,6 @@ class boss_sindragosa : public CreatureScript
break;
case EVENT_ICY_GRIP:
DoCast(me, SPELL_ICY_GRIP);
- events.ScheduleEvent(EVENT_ICY_GRIP, urand(70000, 75000), EVENT_GROUP_LAND_PHASE);
events.ScheduleEvent(EVENT_BLISTERING_COLD, 1000, EVENT_GROUP_LAND_PHASE);
break;
case EVENT_BLISTERING_COLD:
@@ -434,19 +477,21 @@ class boss_sindragosa : public CreatureScript
me->SetDisableGravity(true);
me->SetByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER);
me->SetReactState(REACT_PASSIVE);
+ me->AttackStop();
Position pos;
pos.Relocate(me);
pos.m_positionZ += 17.0f;
me->GetMotionMaster()->MoveTakeoff(POINT_TAKEOFF, pos, 8.30078125f);
- events.DelayEvents(45000, EVENT_GROUP_LAND_PHASE);
+ events.CancelEventGroup(EVENT_GROUP_LAND_PHASE);
events.ScheduleEvent(EVENT_AIR_PHASE, 110000);
- events.RescheduleEvent(EVENT_UNCHAINED_MAGIC, urand(55000, 60000), EVENT_GROUP_LAND_PHASE);
- events.ScheduleEvent(EVENT_LAND, 45000);
break;
}
case EVENT_AIR_MOVEMENT:
me->GetMotionMaster()->MovePoint(POINT_AIR_PHASE, SindragosaAirPos);
break;
+ case EVENT_AIR_MOVEMENT_FAR:
+ me->GetMotionMaster()->MovePoint(POINT_AIR_PHASE_FAR, SindragosaAirPosFar);
+ break;
case EVENT_ICE_TOMB:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true, -SPELL_ICE_TOMB_UNTARGETABLE))
{
@@ -458,30 +503,28 @@ class boss_sindragosa : public CreatureScript
case EVENT_FROST_BOMB:
{
float destX, destY, destZ;
- destX = float(rand_norm()) * 117.25f + 4339.25f;
- if (destX > 4371.5f && destX < 4432.0f)
- destY = float(rand_norm()) * 111.0f + 2429.0f;
- else
- destY = float(rand_norm()) * 31.23f + 2454.64f;
+ destX = float(rand_norm()) * 75.0f + 4350.0f;
+ destY = float(rand_norm()) * 75.0f + 2450.0f;
destZ = 205.0f; // random number close to ground, get exact in next call
me->UpdateGroundPositionZ(destX, destY, destZ);
- Position pos;
- pos.Relocate(destX, destY, destZ, 0.0f);
- if (TempSummon* summ = me->SummonCreature(NPC_FROST_BOMB, pos, TEMPSUMMON_TIMED_DESPAWN, 40000))
- {
- summ->CastSpell(summ, SPELL_FROST_BOMB_VISUAL, true);
- DoCast(summ, SPELL_FROST_BOMB_TRIGGER);
- //me->CastSpell(destX, destY, destZ, SPELL_FROST_BOMB_TRIGGER, false);
- }
- events.ScheduleEvent(EVENT_FROST_BOMB, urand(5000, 10000));
+ me->CastSpell(destX, destY, destZ, SPELL_FROST_BOMB_TRIGGER, false);
+ events.ScheduleEvent(EVENT_FROST_BOMB, urand(6000, 8000));
break;
}
case EVENT_LAND:
{
events.CancelEvent(EVENT_FROST_BOMB);
- me->GetMotionMaster()->MovePoint(POINT_LAND, SindragosaLandPos);
+ me->GetMotionMaster()->MovePoint(POINT_LAND, SindragosaFlyInPos);
break;
}
+ case EVENT_LAND_GROUND:
+ events.ScheduleEvent(EVENT_CLEAVE, urand(13000, 15000), EVENT_GROUP_LAND_PHASE);
+ events.ScheduleEvent(EVENT_TAIL_SMASH, urand(19000, 23000), EVENT_GROUP_LAND_PHASE);
+ events.ScheduleEvent(EVENT_FROST_BREATH, urand(10000, 15000), EVENT_GROUP_LAND_PHASE);
+ events.ScheduleEvent(EVENT_UNCHAINED_MAGIC, urand(12000, 17000), EVENT_GROUP_LAND_PHASE);
+ events.ScheduleEvent(EVENT_ICY_GRIP, urand(35000, 40000), EVENT_GROUP_LAND_PHASE);
+ me->GetMotionMaster()->MoveLand(POINT_LAND_GROUND, SindragosaLandPos, 0.0f);
+ break;
case EVENT_THIRD_PHASE_CHECK:
{
if (!_isInAirPhase)
@@ -670,6 +713,7 @@ class npc_spinestalker : public CreatureScript
me->SetDisableGravity(false);
me->RemoveByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER);
me->SetHomePosition(SpinestalkerLandPos);
+ me->SetFacingTo(SpinestalkerLandPos.GetOrientation());
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
}
@@ -796,6 +840,7 @@ class npc_rimefang : public CreatureScript
me->SetDisableGravity(false);
me->RemoveByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER);
me->SetHomePosition(RimefangLandPos);
+ me->SetFacingTo(RimefangLandPos.GetOrientation());
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
}
@@ -1054,10 +1099,10 @@ class spell_sindragosa_unchained_magic : public SpellScriptLoader
void FilterTargets(std::list<Unit*>& unitList)
{
- unitList.remove_if (UnchainedMagicTargetSelector());
- uint32 maxSize = uint32(GetCaster()->GetMap()->GetSpawnMode() & 1 ? 5 : 2);
+ unitList.remove_if(UnchainedMagicTargetSelector());
+ uint32 maxSize = uint32(GetCaster()->GetMap()->GetSpawnMode() & 1 ? 6 : 2);
if (unitList.size() > maxSize)
- Trinity::RandomResizeList(unitList, maxSize);
+ Trinity::Containers::RandomResizeList(unitList, maxSize);
}
void Register()
@@ -1240,6 +1285,46 @@ class spell_sindragosa_icy_grip : public SpellScriptLoader
}
};
+class MysticBuffetTargetFilter
+{
+ public:
+ explicit MysticBuffetTargetFilter(Unit* caster) : _caster(caster) { }
+
+ bool operator()(Unit* unit)
+ {
+ return !unit->IsWithinLOSInMap(_caster);
+ }
+
+ private:
+ Unit* _caster;
+};
+
+class spell_sindragosa_mystic_buffet : public SpellScriptLoader
+{
+ public:
+ spell_sindragosa_mystic_buffet() : SpellScriptLoader("spell_sindragosa_mystic_buffet") { }
+
+ class spell_sindragosa_mystic_buffet_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_sindragosa_mystic_buffet_SpellScript);
+
+ void FilterTargets(std::list<Unit*>& unitList)
+ {
+ unitList.remove_if(MysticBuffetTargetFilter(GetCaster()));
+ }
+
+ void Register()
+ {
+ OnUnitTargetSelect += SpellUnitTargetFn(spell_sindragosa_mystic_buffet_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_sindragosa_mystic_buffet_SpellScript();
+ }
+};
+
class spell_rimefang_icy_blast : public SpellScriptLoader
{
public:
@@ -1321,7 +1406,7 @@ class spell_frostwarden_handler_order_whelp : public SpellScriptLoader
if (unitList.empty())
return;
- Unit* target = SelectRandomContainerElement(unitList);
+ Unit* target = Trinity::Containers::SelectRandomContainerElement(unitList);
unitList.clear();
unitList.push_back(target);
}
@@ -1338,7 +1423,7 @@ class spell_frostwarden_handler_order_whelp : public SpellScriptLoader
if (unitList.empty())
return;
- SelectRandomContainerElement(unitList)->CastSpell(GetHitUnit(), uint32(GetEffectValue()), true);
+ Trinity::Containers::SelectRandomContainerElement(unitList)->CastSpell(GetHitUnit(), uint32(GetEffectValue()), true);
}
void Register()
@@ -1465,6 +1550,7 @@ void AddSC_boss_sindragosa()
new spell_sindragosa_frost_beacon();
new spell_sindragosa_ice_tomb();
new spell_sindragosa_icy_grip();
+ new spell_sindragosa_mystic_buffet();
new spell_rimefang_icy_blast();
new spell_frostwarden_handler_order_whelp();
new spell_frostwarden_handler_focus_fire();
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp
index 90ee6e1af71..2eb894a5153 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp
@@ -554,7 +554,8 @@ class boss_the_lich_king : public CreatureScript
if (Creature* tirion = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_HIGHLORD_TIRION_FORDRING)))
tirion->AI()->EnterEvadeMode();
DoCastAOE(SPELL_KILL_FROSTMOURNE_PLAYERS);
- summons.DoAction(NPC_STRANGULATE_VEHICLE, ACTION_TELEPORT_BACK);
+ EntryCheckPredicate pred(NPC_STRANGULATE_VEHICLE);
+ summons.DoAction(ACTION_TELEPORT_BACK, pred);
}
void KilledUnit(Unit* victim)
@@ -595,12 +596,15 @@ class boss_the_lich_king : public CreatureScript
events.ScheduleEvent(EVENT_OUTRO_TALK_8, 17000, 0, PHASE_OUTRO);
break;
case ACTION_TELEPORT_BACK:
- summons.DoAction(NPC_STRANGULATE_VEHICLE, ACTION_TELEPORT_BACK);
+ {
+ EntryCheckPredicate pred(NPC_STRANGULATE_VEHICLE);
+ summons.DoAction(ACTION_TELEPORT_BACK, pred);
if (!IsHeroic())
Talk(SAY_LK_FROSTMOURNE_ESCAPE);
else
DoCastAOE(SPELL_TRIGGER_VILE_SPIRIT_HEROIC);
break;
+ }
default:
break;
}
@@ -2550,7 +2554,7 @@ class spell_the_lich_king_valkyr_target_search : public SpellScriptLoader
if (unitList.empty())
return;
- _target = SelectRandomContainerElement(unitList);
+ _target = Trinity::Containers::SelectRandomContainerElement(unitList);
unitList.clear();
unitList.push_back(_target);
GetCaster()->GetAI()->SetGUID(_target->GetGUID());
@@ -2758,7 +2762,7 @@ class spell_the_lich_king_vile_spirit_move_target_search : public SpellScriptLoa
if (targets.empty())
return;
- _target = SelectRandomContainerElement(targets);
+ _target = Trinity::Containers::SelectRandomContainerElement(targets);
}
void HandleScript(SpellEffIndex effIndex)
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp
index af2eb57b7c3..ed1ca4d20fb 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp
@@ -1196,7 +1196,7 @@ class spell_dreamwalker_summoner : public SpellScriptLoader
if (targets.empty())
return;
- Unit* target = SelectRandomContainerElement(targets);
+ Unit* target = Trinity::Containers::SelectRandomContainerElement(targets);
targets.clear();
targets.push_back(target);
}
@@ -1242,7 +1242,7 @@ class spell_dreamwalker_summon_suppresser : public SpellScriptLoader
std::list<Creature*> summoners;
GetCreatureListWithEntryInGrid(summoners, caster, NPC_WORLD_TRIGGER, 100.0f);
summoners.remove_if (Trinity::UnitAuraCheck(true, SPELL_RECENTLY_SPAWNED));
- Trinity::RandomResizeList(summoners, 2);
+ Trinity::Containers::RandomResizeList(summoners, 2);
if (summoners.empty())
return;
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp
index 5720ce0e423..8d562a23f67 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp
@@ -796,7 +796,8 @@ class boss_sister_svalna : public CreatureScript
{
_JustReachedHome();
me->SetReactState(REACT_PASSIVE);
- me->SetCanFly(false);
+ me->SetDisableGravity(false);
+ me->SetHover(false);
}
void DoAction(int32 const action)
@@ -838,13 +839,14 @@ class boss_sister_svalna : public CreatureScript
void MovementInform(uint32 type, uint32 id)
{
- if (type != POINT_MOTION_TYPE || id != POINT_LAND)
+ if (type != EFFECT_MOTION_TYPE || id != POINT_LAND)
return;
_isEventInProgress = false;
me->setActive(false);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC);
- me->SetCanFly(false);
+ me->SetDisableGravity(false);
+ me->SetHover(false);
}
void SpellHitTarget(Unit* target, SpellInfo const* spell)
@@ -1368,7 +1370,7 @@ class npc_captain_arnath : public CreatureScript
case EVENT_ARNATH_PW_SHIELD:
{
std::list<Creature*> targets = DoFindFriendlyMissingBuff(40.0f, SPELL_POWER_WORD_SHIELD);
- DoCast(SelectRandomContainerElement(targets), SPELL_POWER_WORD_SHIELD);
+ DoCast(Trinity::Containers::SelectRandomContainerElement(targets), SPELL_POWER_WORD_SHIELD);
Events.ScheduleEvent(EVENT_ARNATH_PW_SHIELD, urand(15000, 20000));
break;
}
@@ -1822,7 +1824,7 @@ class spell_frost_giant_death_plague : public SpellScriptLoader
unitList.remove_if (DeathPlagueTargetSelector(GetCaster()));
if (!unitList.empty())
{
- Unit* target = SelectRandomContainerElement(unitList);
+ Unit* target = Trinity::Containers::SelectRandomContainerElement(unitList);
unitList.clear();
unitList.push_back(target);
}
@@ -1909,7 +1911,7 @@ class spell_svalna_revive_champion : public SpellScriptLoader
void RemoveAliveTarget(std::list<Unit*>& unitList)
{
unitList.remove_if(AliveCheck());
- Trinity::RandomResizeList(unitList, 2);
+ Trinity::Containers::RandomResizeList(unitList, 2);
}
void Land(SpellEffIndex /*effIndex*/)
@@ -1921,10 +1923,10 @@ class spell_svalna_revive_champion : public SpellScriptLoader
Position pos;
caster->GetPosition(&pos);
caster->GetNearPosition(pos, 5.0f, 0.0f);
- pos.m_positionZ = caster->GetBaseMap()->GetHeight(caster->GetPhaseMask(), pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), true, 20.0f);
- pos.m_positionZ += 0.05f;
+ //pos.m_positionZ = caster->GetBaseMap()->GetHeight(caster->GetPhaseMask(), pos.GetPositionX(), pos.GetPositionY(), caster->GetPositionZ(), true, 50.0f);
+ //pos.m_positionZ += 0.05f;
caster->SetHomePosition(pos);
- caster->GetMotionMaster()->MovePoint(POINT_LAND, pos);
+ caster->GetMotionMaster()->MoveLand(POINT_LAND, pos, caster->GetSpeed(MOVE_FLIGHT));
}
void Register()
diff --git a/src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp b/src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp
index 132ecdafa5a..8d23de5427c 100644
--- a/src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp
+++ b/src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp
@@ -424,7 +424,8 @@ class boss_gothik : public CreatureScript
{
if (instance)
instance->SetData(DATA_GOTHIK_GATE, GO_STATE_ACTIVE);
- summons.DoAction(0, 0);
+ DummyEntryCheckPredicate pred;
+ summons.DoAction(0, pred); //! Magic numbers fail
summons.DoZoneInCombat();
mergedSides = true;
}
@@ -447,7 +448,8 @@ class boss_gothik : public CreatureScript
DoScriptText(SAY_TELEPORT, me);
DoTeleportTo(PosGroundLiveSide);
me->SetReactState(REACT_AGGRESSIVE);
- summons.DoAction(0, 0);
+ DummyEntryCheckPredicate pred;
+ summons.DoAction(0, pred); //! Magic numbers fail
summons.DoZoneInCombat();
events.ScheduleEvent(EVENT_BOLT, 1000);
events.ScheduleEvent(EVENT_HARVEST, urand(3000, 15000));
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon.cpp
deleted file mode 100644
index 2dd13e7ce07..00000000000
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon.cpp
+++ /dev/null
@@ -1,376 +0,0 @@
-/*
- * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "ScriptMgr.h"
-#include "ScriptedCreature.h"
-#include "ulduar.h"
-
-#define GAMEOBJECT_GIVE_OF_THE_OBSERVER 194821
-
-enum Spells
-{
- SPELL_ASCEND = 64487,
- SPELL_BERSERK = 47008,
- SPELL_BIG_BANG = 64443,
- H_SPELL_BIG_BANG = 64584,
- SPELL_COSMIC_SMASH = 62301,
- H_SPELL_COSMIC_SMASH = 64598,
- SPELL_PHASE_PUNCH = 64412,
- SPELL_QUANTUM_STRIKE = 64395,
- H_SPELL_QUANTUM_STRIKE = 64592,
- SPELL_BLACK_HOLE_EXPLOSION = 64122,
- SPELL_ARCANE_BARAGE = 64599,
- H_SPELL_ARCANE_BARAGE = 64607
-};
-
-enum Creatures
-{
- CREATURE_COLLAPSING_STAR = 32955,
- CREATURE_BLACK_HOLE = 32953,
- CREATURE_LIVING_CONSTELLATION = 33052,
- CREATURE_DARK_MATTER = 33089
-};
-
-enum Yells
-{
- SAY_AGGRO = -1603000,
- SAY_SLAY_1 = -1603001,
- SAY_SLAY_2 = -1603002,
- SAY_ENGADED_FOR_FIRTS_TIME = -1603003,
- SAY_PHASE_2 = -1603004,
- SAY_SUMMON_COLLAPSING_STAR = -1603005,
- SAY_DEATH_1 = -1603006,
- SAY_DEATH_2 = -1603007,
- SAY_DEATH_3 = -1603008,
- SAY_DEATH_4 = -1603009,
- SAY_DEATH_5 = -1603010,
- SAY_BERSERK = -1603011,
- SAY_BIG_BANG_1 = -1603012,
- SAY_BIG_BANG_2 = -1603013,
- SAY_TIMER_1 = -1603014,
- SAY_TIMER_2 = -1603015,
- SAY_TIMER_3 = -1603016,
- SAY_SUMMON_1 = -1603017,
- SAY_SUMMON_2 = -1603018,
- SAY_SUMMON_3 = -1603019,
-};
-
-class boss_algalon : public CreatureScript
-{
-public:
- boss_algalon() : CreatureScript("boss_algalon") { }
-
- CreatureAI* GetAI(Creature* creature) const
- {
- return GetUlduarAI<boss_algalonAI>(creature);
- }
-
- struct boss_algalonAI : public ScriptedAI
- {
- boss_algalonAI(Creature* creature) : ScriptedAI(creature)
- {
- instance = creature->GetInstanceScript();
- Summon = false; // not in reset. intro speech done only once.
- }
-
- InstanceScript* instance;
-
- std::list<uint64> m_lCollapsingStarGUIDList;
-
- uint32 Phase;
- uint32 Ascend_Timer;
- uint32 Berserk_Timer;
- uint32 BigBang_Timer;
- uint32 CosmicSmash_Timer;
- uint32 PhasePunch_Timer;
- uint32 QuantumStrike_Timer;
- uint32 CollapsingStar_Timer;
- uint32 uiPhase_timer;
- uint32 uiStep;
-
- uint64 BlackHoleGUID;
-
- bool Enrage;
- bool Summon;
-
- void EnterCombat(Unit* who)
- {
- if (Summon)
- {
- DoScriptText(SAY_AGGRO, me);
- me->InterruptSpell(CURRENT_CHANNELED_SPELL);
- DoZoneInCombat(who->ToCreature());
- }
- else
- {
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
- me->SetReactState(REACT_PASSIVE);
- uiStep = 1;
- }
-
- if (instance)
- instance->SetData(BOSS_ALGALON, IN_PROGRESS);
- }
-
- void KilledUnit(Unit* /*victim*/)
- {
- DoScriptText(RAND(SAY_SLAY_1, SAY_SLAY_2), me);
- }
-
- void Reset()
- {
- Phase = 1;
-
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
- if (instance)
- instance->SetData(BOSS_ALGALON, NOT_STARTED);
-
- BlackHoleGUID = 0;
-
- uiPhase_timer = 0;
- Ascend_Timer = 480000; //8 minutes
- QuantumStrike_Timer = urand(4000, 14000);
- Berserk_Timer = 360000; //6 minutes
- CollapsingStar_Timer = urand(15000, 20000); //Spawns between 15 to 20 seconds
- BigBang_Timer = 90000;
- PhasePunch_Timer = 8000;
- CosmicSmash_Timer = urand(30000, 60000);
- Enrage = false;
- }
-
- void JumpToNextStep(uint32 uiTimer)
- {
- uiPhase_timer = uiTimer;
- ++uiStep;
- }
-
- void DespawnCollapsingStar()
- {
- if (m_lCollapsingStarGUIDList.empty())
- return;
-
- for (std::list<uint64>::const_iterator itr = m_lCollapsingStarGUIDList.begin(); itr != m_lCollapsingStarGUIDList.end(); ++itr)
- {
- if (Creature* temp = Unit::GetCreature(*me, *itr))
- {
- if (temp->isAlive())
- temp->DespawnOrUnsummon();
- }
- }
- m_lCollapsingStarGUIDList.clear();
- }
-
- void JustSummoned(Creature* summoned)
- {
- if (summoned->GetEntry() == CREATURE_COLLAPSING_STAR)
- {
- Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0);
- if (me->getVictim())
- summoned->AI()->AttackStart(target ? target : me->getVictim());
- m_lCollapsingStarGUIDList.push_back(summoned->GetGUID());
- }
- }
-
- void SummonCollapsingStar(Unit* target)
- {
- DoScriptText(SAY_SUMMON_COLLAPSING_STAR, me);
- me->SummonCreature(CREATURE_COLLAPSING_STAR, target->GetPositionX()+15.0f, target->GetPositionY()+15.0f, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 100000);
- me->SummonCreature(CREATURE_BLACK_HOLE, target->GetPositionX()+15.0f, target->GetPositionY()+15.0f, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 27000);
- }
-
- void UpdateAI(const uint32 diff)
- {
- //Return since we have no target
- if (!UpdateVictim())
- return;
-
- if (Phase == 1 && HealthBelowPct(20))
- {
- Phase = 2;
- DoScriptText(SAY_PHASE_2, me);
- }
-
- if (HealthBelowPct(2))
- {
- me->SummonGameObject(GAMEOBJECT_GIVE_OF_THE_OBSERVER, 1634.258667f, -295.101166f, 417.321381f, 0, 0, 0, 0, 0, 0);
-
- // All of them. or random?
- DoScriptText(SAY_DEATH_1, me);
- DoScriptText(SAY_DEATH_2, me);
- DoScriptText(SAY_DEATH_3, me);
- DoScriptText(SAY_DEATH_4, me);
- DoScriptText(SAY_DEATH_5, me);
-
- me->DisappearAndDie();
-
- if (instance)
- instance->SetData(BOSS_ALGALON, DONE);
-
- return;
- }
-
- if (Phase == 1)
- {
- if (!Summon)
- {
- if (uiPhase_timer <= diff)
- {
- switch (uiStep)
- {
- case 1:
- DoScriptText(SAY_SUMMON_1, me);
- JumpToNextStep(3000);
- break;
- case 2:
- DoScriptText(SAY_SUMMON_2, me);
- JumpToNextStep(3000);
- break;
- case 3:
- DoScriptText(SAY_SUMMON_3, me);
- JumpToNextStep(3000);
- break;
- case 4:
- DoScriptText(SAY_ENGADED_FOR_FIRTS_TIME, me);
- JumpToNextStep(3000);
- break;
- case 5:
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
- me->SetReactState(REACT_AGGRESSIVE);
- Summon = true;
- break;
- }
- } else uiPhase_timer -= diff;
-
- return;
- }
-
- if (QuantumStrike_Timer <= diff)
- {
- DoCast(me->getVictim(), RAID_MODE(SPELL_QUANTUM_STRIKE, H_SPELL_QUANTUM_STRIKE), true);
-
- QuantumStrike_Timer = urand(4000, 14000);
- } else QuantumStrike_Timer -= diff;
-
- if (BigBang_Timer <= diff)
- {
- DoScriptText(RAND(SAY_BIG_BANG_1, SAY_BIG_BANG_2), me);
- DoCast(me->getVictim(), RAID_MODE(SPELL_BIG_BANG, H_SPELL_BIG_BANG), true);
-
- BigBang_Timer = 90000;
- } else BigBang_Timer -= diff;
-
- if (Ascend_Timer <= diff)
- {
- DoCast(me->getVictim(), SPELL_ASCEND, true);
-
- Ascend_Timer = 480000;
- } else Ascend_Timer -= diff;
-
- if (PhasePunch_Timer <= diff)
- {
- DoCast(me->getVictim(), SPELL_PHASE_PUNCH, true);
-
- PhasePunch_Timer = 8000;
- } else PhasePunch_Timer -= diff;
-
- if (CosmicSmash_Timer <= diff)
- {
- DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0), RAID_MODE(SPELL_COSMIC_SMASH, H_SPELL_COSMIC_SMASH), true);
-
- CosmicSmash_Timer = urand(30000, 60000);
- } else CosmicSmash_Timer -= diff;
-
- if (Berserk_Timer <= diff)
- {
- DoScriptText(SAY_BERSERK, me);
- DoCast(me->getVictim(), SPELL_BERSERK, true);
-
- Berserk_Timer = 360000;
- } else Berserk_Timer -= diff;
-
- DoMeleeAttackIfReady();
-
- EnterEvadeIfOutOfCombatArea(diff);
- }
-
- if (Phase == 2)
- {
- if (Enrage)
- {
- if (Ascend_Timer <= diff)
- {
- DoCast(me, SPELL_ASCEND);
- DoScriptText(SAY_BERSERK, me);
- Ascend_Timer = urand(360000, 365000);
- Enrage = false;
- } else Ascend_Timer -= diff;
- }
- }
-
- DoMeleeAttackIfReady();
- }
- };
-
-};
-
-//Collapsing Star
-class mob_collapsing_star : public CreatureScript
-{
-public:
- mob_collapsing_star() : CreatureScript("mob_collapsing_star") { }
-
- CreatureAI* GetAI(Creature* creature) const
- {
- return new mob_collapsing_starAI(creature);
- }
-
- struct mob_collapsing_starAI : public ScriptedAI
- {
- mob_collapsing_starAI(Creature* creature) : ScriptedAI(creature)
- {
- instance = creature->GetInstanceScript();
- }
-
- InstanceScript* instance;
-
- uint32 BlackHoleExplosion_Timer;
-
- void Reset()
- {
- BlackHoleExplosion_Timer = 0;
- }
-
- void UpdateAI(const uint32 diff)
- {
- if (!UpdateVictim())
- return;
-
- if (BlackHoleExplosion_Timer <= diff)
- {
- me->CastSpell(me, SPELL_BLACK_HOLE_EXPLOSION, false);
- BlackHoleExplosion_Timer = 0;
- } else BlackHoleExplosion_Timer -= diff;
- }
- };
-
-};
-
-void AddSC_boss_Algalon()
-{
- new boss_algalon();
- new mob_collapsing_star();
-}
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp
new file mode 100644
index 00000000000..6f87d7fcd2a
--- /dev/null
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp
@@ -0,0 +1,1374 @@
+/*
+ * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ObjectMgr.h"
+#include "ScriptMgr.h"
+#include "ScriptedCreature.h"
+#include "SpellScript.h"
+#include "PassiveAI.h"
+#include "GameObjectAI.h"
+#include "MapManager.h"
+#include "MoveSplineInit.h"
+#include "ulduar.h"
+
+enum Texts
+{
+ SAY_BRANN_ALGALON_INTRO_1 = 0,
+ SAY_BRANN_ALGALON_INTRO_2 = 1,
+ SAY_BRANN_ALGALON_OUTRO = 2,
+
+ SAY_ALGALON_INTRO_1 = 0,
+ SAY_ALGALON_INTRO_2 = 1,
+ SAY_ALGALON_INTRO_3 = 2,
+ SAY_ALGALON_START_TIMER = 3,
+ SAY_ALGALON_AGGRO = 4,
+ SAY_ALGALON_COLLAPSING_STAR = 5,
+ EMOTE_ALGALON_COLLAPSING_STAR = 6,
+ SAY_ALGALON_BIG_BANG = 7,
+ EMOTE_ALGALON_BIG_BANG = 8,
+ SAY_ALGALON_ASCEND = 9,
+ EMOTE_ALGALON_COSMIC_SMASH = 10,
+ SAY_ALGALON_PHASE_TWO = 11,
+ SAY_ALGALON_OUTRO_1 = 12,
+ SAY_ALGALON_OUTRO_2 = 13,
+ SAY_ALGALON_OUTRO_3 = 14,
+ SAY_ALGALON_OUTRO_4 = 15,
+ SAY_ALGALON_OUTRO_5 = 16,
+ SAY_ALGALON_DESPAWN_1 = 17,
+ SAY_ALGALON_DESPAWN_2 = 18,
+ SAY_ALGALON_DESPAWN_3 = 19,
+ SAY_ALGALON_KILL = 20,
+};
+
+enum Spells
+{
+ // Algalon the Observer
+ SPELL_ARRIVAL = 64997,
+ SPELL_RIDE_THE_LIGHTNING = 64986,
+ SPELL_SUMMON_AZEROTH = 64994,
+ SPELL_REORIGINATION = 64996,
+ SPELL_SUPERMASSIVE_FAIL = 65311,
+ SPELL_QUANTUM_STRIKE = 64395,
+ SPELL_PHASE_PUNCH = 64412,
+ SPELL_BIG_BANG = 64443,
+ SPELL_ASCEND_TO_THE_HEAVENS = 64487,
+ SPELL_COSMIC_SMASH = 62301,
+ SPELL_COSMIC_SMASH_TRIGGERED = 62304,
+ SPELL_COSMIC_SMASH_VISUAL_STATE = 62300,
+ SPELL_SELF_STUN = 65256,
+ SPELL_KILL_CREDIT = 65184,
+ SPELL_TELEPORT = 62940,
+
+ // Algalon Stalker
+ SPELL_TRIGGER_3_ADDS = 62266, // Triggers Living Constellation
+
+ // Living Constellation
+ SPELL_ARCANE_BARRAGE = 64599,
+
+ // Collapsing Star
+ SPELL_COLLAPSE = 62018,
+ SPELL_BLACK_HOLE_SPAWN_VISUAL = 62003,
+ SPELL_SUMMON_BLACK_HOLE = 62189,
+
+ // Black Hole
+ SPELL_BLACK_HOLE_TRIGGER = 62185,
+ SPELL_CONSTELLATION_PHASE_TRIGGER = 65508,
+ SPELL_CONSTELLATION_PHASE_EFFECT = 65509,
+ SPELL_BLACK_HOLE_EXPLOSION = 64122,
+ SPELL_SUMMON_VOID_ZONE_VISUAL = 64470,
+ SPELL_VOID_ZONE_VISUAL = 64469,
+ SPELL_BLACK_HOLE_CREDIT = 65312,
+
+ // Worm Hole
+ SPELL_WORM_HOLE_TRIGGER = 65251,
+ SPELL_SUMMON_UNLEASHED_DARK_MATTER = 64450,
+};
+
+uint32 const PhasePunchAlphaId[5] = {64435, 64434, 64428, 64421, 64417};
+
+enum Events
+{
+ // Celestial Planetarium Access
+ EVENT_DESPAWN_CONSOLE = 1,
+
+ // Brann Bronzebeard
+ EVENT_BRANN_MOVE_INTRO = 2,
+ EVENT_SUMMON_ALGALON = 3,
+ EVENT_BRANN_OUTRO_1 = 4,
+ EVENT_BRANN_OUTRO_2 = 5,
+
+ // Algalon the Observer
+ EVENT_INTRO_1 = 6,
+ EVENT_INTRO_2 = 7,
+ EVENT_INTRO_3 = 8,
+ EVENT_INTRO_FINISH = 9,
+ EVENT_START_COMBAT = 10,
+ EVENT_INTRO_TIMER_DONE = 11,
+ EVENT_QUANTUM_STRIKE = 12,
+ EVENT_PHASE_PUNCH = 13,
+ EVENT_SUMMON_COLLAPSING_STAR = 14,
+ EVENT_BIG_BANG = 15,
+ EVENT_RESUME_UPDATING = 16,
+ EVENT_ASCEND_TO_THE_HEAVENS = 17,
+ EVENT_EVADE = 18,
+ EVENT_COSMIC_SMASH = 19,
+ EVENT_UNLOCK_YELL = 20,
+ EVENT_OUTRO_START = 21,
+ EVENT_OUTRO_1 = 22,
+ EVENT_OUTRO_2 = 23,
+ EVENT_OUTRO_3 = 24,
+ EVENT_OUTRO_4 = 25,
+ EVENT_OUTRO_5 = 26,
+ EVENT_OUTRO_6 = 27,
+ EVENT_OUTRO_7 = 28,
+ EVENT_OUTRO_8 = 29,
+ EVENT_OUTRO_9 = 30,
+ EVENT_OUTRO_10 = 31,
+ EVENT_OUTRO_11 = 32,
+ EVENT_OUTRO_12 = 33,
+ EVENT_OUTRO_13 = 34,
+ EVENT_OUTRO_14 = 35,
+ EVENT_DESPAWN_ALGALON_1 = 36,
+ EVENT_DESPAWN_ALGALON_2 = 37,
+ EVENT_DESPAWN_ALGALON_3 = 38,
+
+ // Living Constellation
+ EVENT_ARCANE_BARRAGE = 39,
+};
+
+enum Actions
+{
+ ACTION_START_INTRO = 0,
+ ACTION_FINISH_INTRO = 1,
+ ACTION_ACTIVATE_STAR = 2,
+ ACTION_BIG_BANG = 3,
+ ACTION_ASCEND = 4,
+ ACTION_OUTRO = 5,
+};
+
+enum Points
+{
+ POINT_BRANN_INTRO = 0,
+ MAX_BRANN_WAYPOINTS_INTRO = 10,
+ POINT_BRANN_OUTRO = 10,
+ POINT_BRANN_OUTRO_END = 11,
+
+ POINT_ALGALON_LAND = 1,
+ POINT_ALGALON_OUTRO = 2,
+};
+
+enum EncounterPhases
+{
+ PHASE_NORMAL = 0,
+ PHASE_ROLE_PLAY = 1,
+ PHASE_BIG_BANG = 2,
+
+ PHASE_MASK_NO_UPDATE = (1 << PHASE_ROLE_PLAY) | (1 << PHASE_BIG_BANG),
+ PHASE_MASK_NO_CAST_CHECK = 1 << PHASE_ROLE_PLAY,
+};
+
+enum AchievmentInfo
+{
+ EVENT_ID_SUPERMASSIVE_START = 21697,
+ DATA_HAS_FED_ON_TEARS = 30043005,
+};
+
+
+Position const BrannIntroSpawnPos = {1676.277f, -162.5308f, 427.3326f, 3.235537f};
+Position const BrannIntroWaypoint[MAX_BRANN_WAYPOINTS_INTRO] =
+{
+ {1642.482f, -164.0812f, 427.2602f, 0.0f},
+ {1635.000f, -169.5145f, 427.2523f, 0.0f},
+ {1632.814f, -173.9334f, 427.2621f, 0.0f},
+ {1632.676f, -190.5927f, 425.8831f, 0.0f},
+ {1631.497f, -214.2221f, 418.1152f, 0.0f},
+ {1624.717f, -224.6876f, 418.1152f, 0.0f},
+ {1631.497f, -214.2221f, 418.1152f, 0.0f},
+ {1632.676f, -190.5927f, 425.8831f, 0.0f},
+ {1632.814f, -173.9334f, 427.2621f, 0.0f},
+ {1635.000f, -169.5145f, 427.2523f, 0.0f},
+};
+Position const AlgalonSummonPos = {1632.531f, -304.8516f, 450.1123f, 1.530165f};
+Position const AlgalonLandPos = {1632.668f, -302.7656f, 417.3211f, 1.530165f};
+
+#define LIVING_CONSTELLATION_COUNT 11
+Position const ConstellationPos[LIVING_CONSTELLATION_COUNT] =
+{
+ {1625.208f, -267.2771f, 446.4296f, 5.044002f},
+ {1658.279f, -262.5490f, 441.9073f, 4.188790f},
+ {1678.677f, -276.3280f, 427.7531f, 3.979351f},
+ {1593.389f, -299.4325f, 432.4636f, 6.073746f},
+ {1685.613f, -300.1219f, 443.2366f, 3.385939f},
+ {1591.706f, -263.8201f, 441.4153f, 5.253441f},
+ {1668.317f, -324.7676f, 457.9394f, 3.211406f},
+ {1592.242f, -325.5323f, 446.9508f, 0.226893f},
+ {1635.821f, -363.3442f, 424.3459f, 1.466077f},
+ {1672.188f, -357.2484f, 436.7337f, 2.338741f},
+ {1615.800f, -348.0065f, 442.9586f, 1.134464f},
+};
+
+#define COLLAPSING_STAR_COUNT 4
+Position const CollapsingStarPos[COLLAPSING_STAR_COUNT] =
+{
+ {1649.438f, -319.8127f, 418.3941f, 1.082104f},
+ {1647.005f, -288.6790f, 417.3955f, 3.490659f},
+ {1622.451f, -321.1563f, 417.6188f, 4.677482f},
+ {1615.060f, -291.6816f, 417.7796f, 3.490659f},
+};
+Position const AlgalonOutroPos = {1633.64f, -317.78f, 417.3211f, 0.0f};
+Position const BrannOutroPos[3] =
+{
+ {1632.023f, -243.7434f, 417.9118f, 0.0f},
+ {1631.986f, -297.7831f, 417.3210f, 0.0f},
+ {1633.832f, -216.2948f, 417.0463f, 0.0f},
+};
+
+class ActivateLivingConstellation : public BasicEvent
+{
+ public:
+ ActivateLivingConstellation(Unit* owner) : _owner(owner), _instance(owner->GetInstanceScript())
+ {
+ }
+
+ bool Execute(uint64 execTime, uint32 /*diff*/)
+ {
+ if (!_instance || _instance->GetBossState(BOSS_ALGALON) != IN_PROGRESS)
+ return true; // delete event
+
+ _owner->CastSpell((Unit*)NULL, SPELL_TRIGGER_3_ADDS, TRIGGERED_FULL_MASK);
+ _owner->m_Events.AddEvent(this, execTime + urand(45000, 50000));
+ return false;
+ }
+
+ private:
+ Unit* _owner;
+ InstanceScript* _instance;
+};
+
+class CosmicSmashDamageEvent : public BasicEvent
+{
+ public:
+ CosmicSmashDamageEvent(Unit* caster) : _caster(caster)
+ {
+ }
+
+ bool Execute(uint64 /*execTime*/, uint32 /*diff*/)
+ {
+ _caster->CastSpell((Unit*)NULL, SPELL_COSMIC_SMASH_TRIGGERED, TRIGGERED_FULL_MASK);
+ return true;
+ }
+
+ private:
+ Unit* _caster;
+};
+
+class SummonUnleashedDarkMatter : public BasicEvent
+{
+ public:
+ SummonUnleashedDarkMatter(Unit* caster) : _caster(caster)
+ {
+ }
+
+ bool Execute(uint64 execTime, uint32 /*diff*/)
+ {
+ _caster->CastSpell((Unit*)NULL, SPELL_SUMMON_UNLEASHED_DARK_MATTER, TRIGGERED_FULL_MASK);
+ _caster->m_Events.AddEvent(this, execTime + 30000);
+ return false;
+ }
+
+ private:
+ Unit* _caster;
+};
+
+class boss_algalon_the_observer : public CreatureScript
+{
+ public:
+ boss_algalon_the_observer() : CreatureScript("boss_algalon_the_observer") {}
+
+ struct boss_algalon_the_observerAI : public BossAI
+ {
+ boss_algalon_the_observerAI(Creature* creature) : BossAI(creature, BOSS_ALGALON)
+ {
+ _firstPull = true;
+ _fedOnTears = false;
+ }
+
+ void Reset()
+ {
+ _Reset();
+ me->SetReactState(REACT_PASSIVE);
+ _phaseTwo = false;
+ _fightWon = false;
+ _hasYelled = false;
+ }
+
+ void KilledUnit(Unit* victim)
+ {
+ if (victim->GetTypeId() == TYPEID_UNIT)
+ {
+ _fedOnTears = true;
+ if (!_hasYelled)
+ {
+ _hasYelled = true;
+ events.ScheduleEvent(EVENT_UNLOCK_YELL, 1000);
+ Talk(SAY_ALGALON_KILL);
+ }
+ }
+ }
+
+ void DoAction(int32 const action)
+ {
+ switch (action)
+ {
+ case ACTION_START_INTRO:
+ {
+ me->SetFlag(UNIT_FIELD_FLAGS_2, 0x20);
+ me->SetDisableGravity(true);
+ DoCast(me, SPELL_ARRIVAL, true);
+ DoCast(me, SPELL_RIDE_THE_LIGHTNING, true);
+ me->GetMotionMaster()->MovePoint(POINT_ALGALON_LAND, AlgalonLandPos);
+ me->SetHomePosition(AlgalonLandPos);
+ Movement::MoveSplineInit init(*me);
+ init.MoveTo(AlgalonLandPos.GetPositionX(), AlgalonLandPos.GetPositionY(), AlgalonLandPos.GetPositionZ());
+ init.SetOrientationFixed(true);
+ init.Launch();
+ events.Reset();
+ events.SetPhase(PHASE_ROLE_PLAY);
+ events.ScheduleEvent(EVENT_INTRO_1, 5000, 0, PHASE_ROLE_PLAY);
+ events.ScheduleEvent(EVENT_INTRO_2, 15000, 0, PHASE_ROLE_PLAY);
+ events.ScheduleEvent(EVENT_INTRO_3, 23000, 0, PHASE_ROLE_PLAY);
+ events.ScheduleEvent(EVENT_INTRO_FINISH, 36000, 0, PHASE_ROLE_PLAY);
+ break;
+ }
+ case ACTION_ASCEND:
+ events.SetPhase(PHASE_BIG_BANG);
+ events.CancelEvent(EVENT_RESUME_UPDATING);
+ events.ScheduleEvent(EVENT_ASCEND_TO_THE_HEAVENS, 1500);
+ break;
+ case EVENT_DESPAWN_ALGALON:
+ events.Reset();
+ events.SetPhase(PHASE_ROLE_PLAY);
+ if (me->isInCombat())
+ events.ScheduleEvent(EVENT_ASCEND_TO_THE_HEAVENS, 1);
+ events.ScheduleEvent(EVENT_DESPAWN_ALGALON_1, 5000);
+ events.ScheduleEvent(EVENT_DESPAWN_ALGALON_2, 17000);
+ events.ScheduleEvent(EVENT_DESPAWN_ALGALON_3, 26000);
+ me->DespawnOrUnsummon(34000);
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_IMMUNE_TO_NPC);
+ break;
+ case ACTION_INIT_ALGALON:
+ _firstPull = false;
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
+ break;;
+ }
+ }
+
+ uint32 GetData(uint32 type)
+ {
+ return type == DATA_HAS_FED_ON_TEARS ? _fedOnTears : 1;
+ }
+
+ void EnterCombat(Unit* /*target*/)
+ {
+ uint32 introDelay = 0;
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_IMMUNE_TO_NPC);
+ events.Reset();
+ events.SetPhase(PHASE_ROLE_PLAY);
+
+ if (!_firstPull)
+ {
+ Talk(SAY_ALGALON_AGGRO);
+ _EnterCombat();
+ introDelay = 8000;
+ }
+ else
+ {
+ _firstPull = false;
+ Talk(SAY_ALGALON_START_TIMER);
+ if (Creature* brann = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_BRANN_BRONZEBEARD_ALG)))
+ brann->AI()->DoAction(ACTION_FINISH_INTRO);
+
+ me->setActive(true);
+ DoZoneInCombat();
+ introDelay = 26000;
+ summons.DespawnEntry(NPC_AZEROTH);
+ instance->SetData(EVENT_DESPAWN_ALGALON, 0);
+ events.ScheduleEvent(EVENT_START_COMBAT, 18000);
+ }
+
+ events.ScheduleEvent(EVENT_INTRO_TIMER_DONE, introDelay);
+ events.ScheduleEvent(EVENT_QUANTUM_STRIKE, 3500 + introDelay);
+ events.ScheduleEvent(EVENT_PHASE_PUNCH, 15500 + introDelay);
+ events.ScheduleEvent(EVENT_SUMMON_COLLAPSING_STAR, 18000 + introDelay);
+ events.ScheduleEvent(EVENT_BIG_BANG, 90000 + introDelay);
+ events.ScheduleEvent(EVENT_ASCEND_TO_THE_HEAVENS, 360000 + introDelay);
+ events.ScheduleEvent(EVENT_COSMIC_SMASH, 25000 + introDelay);
+
+ std::list<Creature*> stalkers;
+ me->GetCreatureListWithEntryInGrid(stalkers, NPC_ALGALON_STALKER, 200.0f);
+ for (std::list<Creature*>::iterator itr = stalkers.begin(); itr != stalkers.end(); ++itr)
+ (*itr)->m_Events.KillAllEvents(true);
+ }
+
+ void MovementInform(uint32 movementType, uint32 pointId)
+ {
+ if (movementType != POINT_MOTION_TYPE)
+ return;
+
+ if (pointId == POINT_ALGALON_LAND)
+ me->SetDisableGravity(false);
+ else if (pointId == POINT_ALGALON_OUTRO)
+ {
+ me->SetFacingTo(1.605703f);
+ events.ScheduleEvent(EVENT_OUTRO_3, 1200);
+ events.ScheduleEvent(EVENT_OUTRO_4, 2400);
+ events.ScheduleEvent(EVENT_OUTRO_5, 8500);
+ events.ScheduleEvent(EVENT_OUTRO_6, 15500);
+ events.ScheduleEvent(EVENT_OUTRO_7, 55500);
+ events.ScheduleEvent(EVENT_OUTRO_8, 73500);
+ events.ScheduleEvent(EVENT_OUTRO_9, 85500);
+ events.ScheduleEvent(EVENT_OUTRO_10, 108500);
+ events.ScheduleEvent(EVENT_OUTRO_11, 123500);
+ }
+ }
+
+ void JustSummoned(Creature* summon)
+ {
+ summons.Summon(summon);
+ switch (summon->GetEntry())
+ {
+ case NPC_AZEROTH:
+ DoCastAOE(SPELL_REORIGINATION, true);
+ break;
+ case NPC_COLLAPSING_STAR:
+ summon->SetReactState(REACT_PASSIVE);
+ summon->GetMotionMaster()->MoveRandom(20.0f);
+ summon->CastSpell(summon, SPELL_COLLAPSE, TRIGGERED_FULL_MASK);
+ break;
+ case NPC_BLACK_HOLE:
+ summon->SetReactState(REACT_PASSIVE);
+ summon->CastSpell((Unit*)NULL, SPELL_BLACK_HOLE_TRIGGER, TRIGGERED_FULL_MASK);
+ summon->CastSpell(summon, SPELL_CONSTELLATION_PHASE_TRIGGER, TRIGGERED_FULL_MASK);
+ summon->CastSpell((Unit*)NULL, SPELL_BLACK_HOLE_EXPLOSION);
+ summon->CastSpell(summon, SPELL_SUMMON_VOID_ZONE_VISUAL, TRIGGERED_FULL_MASK);
+ break;
+ case NPC_ALGALON_VOID_ZONE_VISUAL_STALKER:
+ summon->CastSpell(summon, SPELL_VOID_ZONE_VISUAL, TRIGGERED_FULL_MASK);
+ break;
+ case NPC_ALGALON_STALKER_ASTEROID_TARGET_01:
+ summon->CastSpell(summon, SPELL_COSMIC_SMASH_VISUAL_STATE, TRIGGERED_FULL_MASK);
+ break;
+ case NPC_ALGALON_STALKER_ASTEROID_TARGET_02:
+ summon->m_Events.AddEvent(new CosmicSmashDamageEvent(summon), summon->m_Events.CalculateTime(3250));
+ break;
+ case NPC_WORM_HOLE:
+ summon->SetReactState(REACT_PASSIVE);
+ summon->CastSpell(summon, SPELL_WORM_HOLE_TRIGGER, TRIGGERED_FULL_MASK);
+ summon->CastSpell(summon, SPELL_SUMMON_VOID_ZONE_VISUAL, TRIGGERED_FULL_MASK);
+ break;
+ case NPC_UNLEASHED_DARK_MATTER:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, NonTankTargetSelector(me)))
+ if (summon->Attack(target, true))
+ summon->GetMotionMaster()->MoveChase(target);
+ break;
+ }
+ }
+
+ void EnterEvadeMode()
+ {
+ instance->SetBossState(BOSS_ALGALON, FAIL);
+ BossAI::EnterEvadeMode();
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
+ me->SetSheath(SHEATH_STATE_UNARMED);
+ }
+
+ void DamageTaken(Unit* /*attacker*/, uint32& damage)
+ {
+ if (_fightWon)
+ {
+ damage = 0;
+ return;
+ }
+
+ if (!_phaseTwo && me->HealthBelowPctDamaged(20, damage))
+ {
+ _phaseTwo = true;
+ Talk(SAY_ALGALON_PHASE_TWO);
+ summons.DespawnEntry(NPC_LIVING_CONSTELLATION);
+ summons.DespawnEntry(NPC_COLLAPSING_STAR);
+ summons.DespawnEntry(NPC_BLACK_HOLE);
+ summons.DespawnEntry(NPC_ALGALON_VOID_ZONE_VISUAL_STALKER);
+ events.CancelEvent(EVENT_SUMMON_COLLAPSING_STAR);
+ std::list<Creature*> stalkers;
+ me->GetCreatureListWithEntryInGrid(stalkers, NPC_ALGALON_STALKER, 200.0f);
+ for (std::list<Creature*>::iterator itr = stalkers.begin(); itr != stalkers.end(); ++itr)
+ (*itr)->m_Events.KillAllEvents(true);
+ for (uint32 i = 0; i < COLLAPSING_STAR_COUNT; ++i)
+ if (Creature* wormHole = DoSummon(NPC_WORM_HOLE, CollapsingStarPos[i], TEMPSUMMON_MANUAL_DESPAWN))
+ wormHole->m_Events.AddEvent(new SummonUnleashedDarkMatter(wormHole), wormHole->m_Events.CalculateTime(i >= 2 ? 8000 : 6000));
+ }
+ else if ((int32(me->GetHealth()) - int32(damage)) < CalculatePctF<int32>(int32(me->GetMaxHealth()), 2.5f) && !_fightWon)
+ {
+ _fightWon = true;
+ damage = 0;
+ me->SetReactState(REACT_PASSIVE);
+ me->AttackStop();
+ me->setFaction(35);
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ DoCast(me, SPELL_SELF_STUN);
+ events.Reset();
+ summons.DespawnAll();
+ events.SetPhase(PHASE_ROLE_PLAY);
+ events.ScheduleEvent(EVENT_OUTRO_START, 1500);
+ events.ScheduleEvent(EVENT_OUTRO_1, 7200);
+ events.ScheduleEvent(EVENT_OUTRO_2, 8700);
+ }
+ }
+
+ void UpdateAI(uint32 const diff)
+ {
+ if ((!(events.GetPhaseMask() & PHASE_MASK_NO_UPDATE) && !UpdateVictim()) || !CheckInRoom())
+ return;
+
+ events.Update(diff);
+
+ if (!(events.GetPhaseMask() & PHASE_MASK_NO_CAST_CHECK))
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_INTRO_1:
+ me->RemoveAurasDueToSpell(SPELL_RIDE_THE_LIGHTNING);
+ Talk(SAY_ALGALON_INTRO_1);
+ break;
+ case EVENT_INTRO_2:
+ DoCastAOE(SPELL_SUMMON_AZEROTH, true);
+ Talk(SAY_ALGALON_INTRO_2);
+ break;
+ case EVENT_INTRO_3:
+ Talk(SAY_ALGALON_INTRO_3);
+ break;
+ case EVENT_INTRO_FINISH:
+ events.Reset();
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
+ break;
+ case EVENT_START_COMBAT:
+ instance->SetBossState(BOSS_ALGALON, IN_PROGRESS);
+ break;
+ case EVENT_INTRO_TIMER_DONE:
+ {
+ events.SetPhase(PHASE_NORMAL);
+ me->SetSheath(SHEATH_STATE_MELEE);
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_IMMUNE_TO_NPC);
+ me->SetReactState(REACT_DEFENSIVE);
+ DoCastAOE(SPELL_SUPERMASSIVE_FAIL, true);
+ //! Workaround for Creature::_IsTargetAcceptable returning false
+ //! for creatures that start combat in REACT_PASSIVE and UNIT_FLAG_NOT_SELECTABLE
+ //! causing them to immediately evade
+ if (!me->getThreatManager().isThreatListEmpty())
+ AttackStart(me->getThreatManager().getHostilTarget());
+ for (uint32 i = 0; i < LIVING_CONSTELLATION_COUNT; ++i)
+ if (Creature* summon = DoSummon(NPC_LIVING_CONSTELLATION, ConstellationPos[i], 0, TEMPSUMMON_DEAD_DESPAWN))
+ summon->SetReactState(REACT_PASSIVE);
+
+ std::list<Creature*> stalkers;
+ me->GetCreatureListWithEntryInGrid(stalkers, NPC_ALGALON_STALKER, 200.0f);
+ if (!stalkers.empty())
+ {
+ Unit* stalker = Trinity::Containers::SelectRandomContainerElement(stalkers);
+ stalker->m_Events.AddEvent(new ActivateLivingConstellation(stalker), stalker->m_Events.CalculateTime(urand(45000, 50000)));
+ }
+ break;
+ }
+ case EVENT_QUANTUM_STRIKE:
+ DoCastVictim(SPELL_QUANTUM_STRIKE);
+ events.ScheduleEvent(EVENT_QUANTUM_STRIKE, urand(3000, 5000));
+ break;
+ case EVENT_PHASE_PUNCH:
+ DoCastVictim(SPELL_PHASE_PUNCH);
+ events.ScheduleEvent(EVENT_PHASE_PUNCH, 15500);
+ break;
+ case EVENT_SUMMON_COLLAPSING_STAR:
+ Talk(SAY_ALGALON_COLLAPSING_STAR);
+ Talk(EMOTE_ALGALON_COLLAPSING_STAR);
+ for (uint32 i = 0; i < COLLAPSING_STAR_COUNT; ++i)
+ me->SummonCreature(NPC_COLLAPSING_STAR, CollapsingStarPos[i], TEMPSUMMON_CORPSE_DESPAWN);
+ events.ScheduleEvent(EVENT_SUMMON_COLLAPSING_STAR, 60000);
+ break;
+ case EVENT_BIG_BANG:
+ {
+ Talk(SAY_ALGALON_BIG_BANG);
+ Talk(EMOTE_ALGALON_BIG_BANG);
+ events.SetPhase(PHASE_BIG_BANG);
+ std::list<Creature*> constellations;
+ me->GetCreatureListWithEntryInGrid(constellations, NPC_LIVING_CONSTELLATION, 200.0f);
+ for (std::list<Creature*>::iterator itr = constellations.begin(); itr != constellations.end(); ++itr)
+ (*itr)->AI()->DoAction(ACTION_BIG_BANG);
+ DoCastAOE(SPELL_BIG_BANG);
+ events.ScheduleEvent(EVENT_BIG_BANG, 90500);
+ events.ScheduleEvent(EVENT_RESUME_UPDATING, 9500);
+ break;
+ }
+ case EVENT_RESUME_UPDATING:
+ events.SetPhase(0);
+ break;
+ case EVENT_ASCEND_TO_THE_HEAVENS:
+ Talk(SAY_ALGALON_ASCEND);
+ DoCastAOE(SPELL_ASCEND_TO_THE_HEAVENS);
+ events.ScheduleEvent(EVENT_EVADE, 2500);
+ break;
+ case EVENT_EVADE:
+ EnterEvadeMode();
+ break;
+ case EVENT_COSMIC_SMASH:
+ Talk(EMOTE_ALGALON_COSMIC_SMASH);
+ DoCastAOE(SPELL_COSMIC_SMASH);
+ events.ScheduleEvent(EVENT_COSMIC_SMASH, 25500);
+ break;
+ case EVENT_UNLOCK_YELL:
+ _hasYelled = false;
+ break;
+ case EVENT_OUTRO_START:
+ instance->SetBossState(BOSS_ALGALON, DONE);
+ break;
+ case EVENT_OUTRO_1:
+ me->RemoveAllAuras();
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_RENAME);
+ break;
+ case EVENT_OUTRO_2:
+ _EnterEvadeMode();
+ me->AddUnitState(UNIT_STATE_EVADE);
+ me->GetMotionMaster()->MovePoint(POINT_ALGALON_OUTRO, AlgalonOutroPos);
+ break;
+ case EVENT_OUTRO_3:
+ DoCastAOE(SPELL_KILL_CREDIT);
+ break;
+ case EVENT_OUTRO_4:
+ DoCastAOE(SPELL_SUPERMASSIVE_FAIL);
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ break;
+ case EVENT_OUTRO_5:
+ if (Creature* brann = DoSummon(NPC_BRANN_BRONZBEARD_ALG, BrannOutroPos[0], 131500, TEMPSUMMON_TIMED_DESPAWN))
+ brann->AI()->DoAction(ACTION_OUTRO);
+ break;
+ case EVENT_OUTRO_6:
+ Talk(SAY_ALGALON_OUTRO_1);
+ me->SetStandState(UNIT_STAND_STATE_KNEEL);
+ break;
+ case EVENT_OUTRO_7:
+ Talk(SAY_ALGALON_OUTRO_2);
+ break;
+ case EVENT_OUTRO_8:
+ Talk(SAY_ALGALON_OUTRO_3);
+ break;
+ case EVENT_OUTRO_9:
+ Talk(SAY_ALGALON_OUTRO_4);
+ break;
+ case EVENT_OUTRO_10:
+ Talk(SAY_ALGALON_OUTRO_5);
+ break;
+ case EVENT_OUTRO_11:
+ me->SetStandState(UNIT_STAND_STATE_STAND);
+ DoCast(me, SPELL_TELEPORT);
+ me->DespawnOrUnsummon(1500);
+ break;
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ }
+
+ private:
+ bool _firstPull;
+ bool _fedOnTears;
+ bool _phaseTwo;
+ bool _fightWon;
+ bool _hasYelled;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return GetUlduarAI<boss_algalon_the_observerAI>(creature);
+ }
+};
+
+class npc_living_constellation : public CreatureScript
+{
+ public:
+ npc_living_constellation() : CreatureScript("npc_living_constellation") { }
+
+ struct npc_living_constellationAI : public CreatureAI
+ {
+ npc_living_constellationAI(Creature* creature) : CreatureAI(creature)
+ {
+ }
+
+ void Reset()
+ {
+ _events.Reset();
+ _events.ScheduleEvent(EVENT_ARCANE_BARRAGE, 2500);
+ _isActive = false;
+ }
+
+ uint32 GetData(uint32 /*type*/)
+ {
+ return _isActive ? 1 : 0;
+ }
+
+ void DoAction(int32 const action)
+ {
+ switch (action)
+ {
+ case ACTION_ACTIVATE_STAR:
+ if (Creature* algalon = me->FindNearestCreature(NPC_ALGALON, 200.0f))
+ {
+ if (Unit* target = algalon->AI()->SelectTarget(SELECT_TARGET_RANDOM, 0, NonTankTargetSelector(algalon)))
+ {
+ me->SetReactState(REACT_AGGRESSIVE);
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ AttackStart(target);
+ DoZoneInCombat();
+ _isActive = true;
+ }
+ }
+ break;
+ case ACTION_BIG_BANG:
+ _events.SetPhase(PHASE_BIG_BANG);
+ _events.DelayEvents(9500);
+ _events.ScheduleEvent(EVENT_RESUME_UPDATING, 9500);
+ break;
+ }
+ }
+
+ void SpellHit(Unit* caster, SpellInfo const* spell)
+ {
+ if (spell->Id != SPELL_CONSTELLATION_PHASE_EFFECT || caster->GetTypeId() != TYPEID_UNIT)
+ return;
+
+ me->DespawnOrUnsummon(1);
+ if (InstanceScript* instance = me->GetInstanceScript())
+ instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, EVENT_ID_SUPERMASSIVE_START);
+ caster->CastSpell((Unit*)NULL, SPELL_BLACK_HOLE_CREDIT, TRIGGERED_FULL_MASK);
+ caster->ToCreature()->DespawnOrUnsummon(1);
+ }
+
+ void UpdateAI(uint32 const diff)
+ {
+ if (!(_events.GetPhaseMask() & PHASE_MASK_NO_UPDATE) && !UpdateVictim())
+ return;
+
+ _events.Update(diff);
+
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_ARCANE_BARRAGE:
+ DoCastAOE(SPELL_ARCANE_BARRAGE);
+ _events.ScheduleEvent(EVENT_ARCANE_BARRAGE, 2500);
+ break;
+ case EVENT_RESUME_UPDATING:
+ _events.SetPhase(0);
+ break;
+ }
+ }
+ }
+
+ private:
+ EventMap _events;
+ bool _isActive;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return GetUlduarAI<npc_living_constellationAI>(creature);
+ }
+};
+
+class npc_collapsing_star : public CreatureScript
+{
+ public:
+ npc_collapsing_star() : CreatureScript("npc_collapsing_star") { }
+
+ struct npc_collapsing_starAI : public PassiveAI
+ {
+ npc_collapsing_starAI(Creature* creature) : PassiveAI(creature)
+ {
+ _dying = false;
+ }
+
+ void JustSummoned(Creature* summon)
+ {
+ if (summon->GetEntry() != NPC_BLACK_HOLE)
+ return;
+
+ if (TempSummon* summ = me->ToTempSummon())
+ if (Creature* algalon = ObjectAccessor::GetCreature(*me, summ->GetSummonerGUID()))
+ algalon->AI()->JustSummoned(summon);
+
+ me->DespawnOrUnsummon(1);
+ }
+
+ void DamageTaken(Unit* /*attacker*/, uint32& damage)
+ {
+ if (_dying)
+ {
+ damage = 0;
+ return;
+ }
+
+ if (damage >= me->GetHealth())
+ {
+ _dying = true;
+ damage = 0;
+ DoCast(me, SPELL_BLACK_HOLE_SPAWN_VISUAL, true);
+ DoCast(me, SPELL_SUMMON_BLACK_HOLE, true);
+ }
+ }
+
+ bool _dying;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return GetUlduarAI<npc_collapsing_starAI>(creature);
+ }
+};
+
+class npc_brann_bronzebeard_algalon : public CreatureScript
+{
+ public:
+ npc_brann_bronzebeard_algalon() : CreatureScript("npc_brann_bronzebeard_algalon") { }
+
+ struct npc_brann_bronzebeard_algalonAI : public CreatureAI
+ {
+ npc_brann_bronzebeard_algalonAI(Creature* creature) : CreatureAI(creature)
+ {
+ }
+
+ void DoAction(int32 const action)
+ {
+ switch (action)
+ {
+ case ACTION_START_INTRO:
+ _currentPoint = 0;
+ _events.Reset();
+ me->SetWalk(false);
+ _events.ScheduleEvent(EVENT_BRANN_MOVE_INTRO, 1);
+ break;
+ case ACTION_FINISH_INTRO:
+ Talk(SAY_BRANN_ALGALON_INTRO_2);
+ _events.ScheduleEvent(EVENT_BRANN_MOVE_INTRO, 1);
+ break;
+ case ACTION_OUTRO:
+ me->GetMotionMaster()->MovePoint(POINT_BRANN_OUTRO, BrannOutroPos[1]);
+ _events.ScheduleEvent(EVENT_BRANN_OUTRO_1, 89500);
+ _events.ScheduleEvent(EVENT_BRANN_OUTRO_2, 116500);
+ break;
+ }
+ }
+
+ void MovementInform(uint32 movementType, uint32 pointId)
+ {
+ if (movementType != POINT_MOTION_TYPE)
+ return;
+
+ uint32 delay = 1;
+ _currentPoint = pointId + 1;
+ switch (pointId)
+ {
+ case 2:
+ delay = 8000;
+ me->SetWalk(true);
+ break;
+ case 5:
+ me->SetWalk(false);
+ Talk(SAY_BRANN_ALGALON_INTRO_1);
+ _events.ScheduleEvent(EVENT_SUMMON_ALGALON, 7500);
+ return;
+ case 9:
+ me->DespawnOrUnsummon(1);
+ return;
+ case POINT_BRANN_OUTRO:
+ case POINT_BRANN_OUTRO_END:
+ return;
+ }
+
+ _events.ScheduleEvent(EVENT_BRANN_MOVE_INTRO, delay);
+ }
+
+ void UpdateAI(uint32 const diff)
+ {
+ UpdateVictim();
+
+ if (_events.Empty())
+ return;
+
+ _events.Update(diff);
+
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_BRANN_MOVE_INTRO:
+ if (_currentPoint < MAX_BRANN_WAYPOINTS_INTRO)
+ me->GetMotionMaster()->MovePoint(_currentPoint, BrannIntroWaypoint[_currentPoint]);
+ break;
+ case EVENT_SUMMON_ALGALON:
+ if (Creature* algalon = me->GetMap()->SummonCreature(NPC_ALGALON, AlgalonSummonPos))
+ algalon->AI()->DoAction(ACTION_START_INTRO);
+ break;
+ case EVENT_BRANN_OUTRO_1:
+ Talk(SAY_BRANN_ALGALON_OUTRO);
+ break;
+ case EVENT_BRANN_OUTRO_2:
+ me->GetMotionMaster()->MovePoint(POINT_BRANN_OUTRO_END, BrannOutroPos[2]);
+ break;
+ }
+ }
+ }
+
+ private:
+ EventMap _events;
+ uint32 _currentPoint;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return GetUlduarAI<npc_brann_bronzebeard_algalonAI>(creature);
+ }
+};
+
+class go_celestial_planetarium_access : public GameObjectScript
+{
+ public:
+ go_celestial_planetarium_access() : GameObjectScript("go_celestial_planetarium_access") {}
+
+ struct go_celestial_planetarium_accessAI : public GameObjectAI
+ {
+ go_celestial_planetarium_accessAI(GameObject* go) : GameObjectAI(go)
+ {
+ }
+
+ bool GossipHello(Player* player)
+ {
+ bool hasKey = true;
+ if (LockEntry const* lock = sLockStore.LookupEntry(go->GetGOInfo()->goober.lockId))
+ {
+ hasKey = false;
+ for (uint32 i = 0; i < MAX_LOCK_CASE; ++i)
+ {
+ if (!lock->Index[i])
+ continue;
+
+ if (player->HasItemCount(lock->Index[i], 1))
+ {
+ hasKey = true;
+ break;
+ }
+ }
+ }
+
+ if (!hasKey)
+ return false;
+
+ // Start Algalon event
+ go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_IN_USE);
+ _events.ScheduleEvent(EVENT_DESPAWN_CONSOLE, 5000);
+ if (Creature* brann = go->SummonCreature(NPC_BRANN_BRONZBEARD_ALG, BrannIntroSpawnPos))
+ brann->AI()->DoAction(ACTION_START_INTRO);
+
+ if (InstanceScript* instance = go->GetInstanceScript())
+ {
+ instance->SetData(DATA_ALGALON_SUMMON_STATE, 1);
+ if (GameObject* sigil = ObjectAccessor::GetGameObject(*go, instance->GetData64(DATA_SIGILDOOR_01)))
+ sigil->SetGoState(GO_STATE_ACTIVE);
+
+ if (GameObject* sigil = ObjectAccessor::GetGameObject(*go, instance->GetData64(DATA_SIGILDOOR_02)))
+ sigil->SetGoState(GO_STATE_ACTIVE);
+ }
+
+ return false;
+ }
+
+ void UpdateAI(uint32 diff)
+ {
+ if (_events.Empty())
+ return;
+
+ _events.Update(diff);
+
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_DESPAWN_CONSOLE:
+ go->Delete();
+ break;
+ }
+ }
+ }
+
+ EventMap _events;
+ };
+
+ GameObjectAI* GetAI(GameObject* go) const
+ {
+ return GetUlduarAI<go_celestial_planetarium_accessAI>(go);
+ }
+};
+
+class spell_algalon_phase_punch : public SpellScriptLoader
+{
+ public:
+ spell_algalon_phase_punch() : SpellScriptLoader("spell_algalon_phase_punch") { }
+
+ class spell_algalon_phase_punch_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_algalon_phase_punch_AuraScript);
+
+ void HandlePeriodic(AuraEffect const* aurEff)
+ {
+ PreventDefaultAction();
+ if (GetStackAmount() != 1)
+ GetTarget()->RemoveAurasDueToSpell(PhasePunchAlphaId[GetStackAmount() - 2]);
+ GetTarget()->CastSpell(GetTarget(), PhasePunchAlphaId[GetStackAmount() - 1], TRIGGERED_FULL_MASK);
+ if (GetStackAmount() == 5)
+ Remove(AURA_REMOVE_BY_DEFAULT);
+ }
+
+ void OnRemove(AuraEffect const*, AuraEffectHandleModes)
+ {
+ if (GetStackAmount() != 5)
+ GetTarget()->RemoveAurasDueToSpell(PhasePunchAlphaId[GetStackAmount() - 1]);
+ }
+
+ void Register()
+ {
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_algalon_phase_punch_AuraScript::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
+ OnEffectRemove += AuraEffectRemoveFn(spell_algalon_phase_punch_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL);
+ }
+ };
+
+ AuraScript* GetAuraScript() const
+ {
+ return new spell_algalon_phase_punch_AuraScript();
+ }
+};
+
+class NotVictimFilter
+{
+ public:
+ NotVictimFilter(Unit* caster) : _victim(caster->getVictim())
+ {
+ }
+
+ bool operator()(Unit* target)
+ {
+ return target != _victim;
+ }
+
+ private:
+ Unit* _victim;
+};
+
+class spell_algalon_arcane_barrage : public SpellScriptLoader
+{
+ public:
+ spell_algalon_arcane_barrage() : SpellScriptLoader("spell_algalon_arcane_barrage") { }
+
+ class spell_algalon_arcane_barrage_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_algalon_arcane_barrage_SpellScript);
+
+ void SelectTarget(std::list<Unit*>& targets)
+ {
+ targets.remove_if(NotVictimFilter(GetCaster()));
+ }
+
+ void Register()
+ {
+ OnUnitTargetSelect += SpellUnitTargetFn(spell_algalon_arcane_barrage_SpellScript::SelectTarget, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_algalon_arcane_barrage_SpellScript();
+ }
+};
+
+class ActiveConstellationFilter
+{
+ public:
+ bool operator()(Unit* target) const
+ {
+ return target->GetAI()->GetData(0);
+ }
+};
+
+class spell_algalon_trigger_3_adds : public SpellScriptLoader
+{
+ public:
+ spell_algalon_trigger_3_adds() : SpellScriptLoader("spell_algalon_trigger_3_adds") { }
+
+ class spell_algalon_trigger_3_adds_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_algalon_trigger_3_adds_SpellScript);
+
+ void SelectTarget(std::list<Unit*>& targets)
+ {
+ targets.remove_if(ActiveConstellationFilter());
+ }
+
+ void HandleDummy(SpellEffIndex effIndex)
+ {
+ PreventHitDefaultEffect(effIndex);
+ Creature* target = GetHitCreature();
+ if (!target)
+ return;
+
+ target->AI()->DoAction(ACTION_ACTIVATE_STAR);
+ }
+
+ void Register()
+ {
+ OnUnitTargetSelect += SpellUnitTargetFn(spell_algalon_trigger_3_adds_SpellScript::SelectTarget, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_algalon_trigger_3_adds_SpellScript();
+ }
+};
+
+class spell_algalon_collapse : public SpellScriptLoader
+{
+ public:
+ spell_algalon_collapse() : SpellScriptLoader("spell_algalon_collapse") { }
+
+ class spell_algalon_collapse_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_algalon_collapse_AuraScript);
+
+ void HandlePeriodic(AuraEffect const* /*aurEff*/)
+ {
+ PreventDefaultAction();
+ GetTarget()->DealDamage(GetTarget(), GetTarget()->CountPctFromMaxHealth(1), NULL, NODAMAGE);
+ }
+
+ void Register()
+ {
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_algalon_collapse_AuraScript::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
+ }
+ };
+
+ AuraScript* GetAuraScript() const
+ {
+ return new spell_algalon_collapse_AuraScript();
+ }
+};
+
+class spell_algalon_big_bang : public SpellScriptLoader
+{
+ public:
+ spell_algalon_big_bang() : SpellScriptLoader("spell_algalon_big_bang") { }
+
+ class spell_algalon_big_bang_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_algalon_big_bang_SpellScript);
+
+ bool Load()
+ {
+ _targetCount = 0;
+ return true;
+ }
+
+ void CountTargets(std::list<Unit*>& targets)
+ {
+ _targetCount = targets.size();
+ }
+
+ void CheckTargets()
+ {
+ if (!_targetCount)
+ GetCaster()->GetAI()->DoAction(ACTION_ASCEND);
+ }
+
+ void Register()
+ {
+ OnUnitTargetSelect += SpellUnitTargetFn(spell_algalon_big_bang_SpellScript::CountTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
+ AfterCast += SpellCastFn(spell_algalon_big_bang_SpellScript::CheckTargets);
+ }
+
+ uint32 _targetCount;
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_algalon_big_bang_SpellScript();
+ }
+};
+
+class spell_algalon_remove_phase : public SpellScriptLoader
+{
+ public:
+ spell_algalon_remove_phase() : SpellScriptLoader("spell_algalon_remove_phase") { }
+
+ class spell_algalon_remove_phase_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_algalon_remove_phase_AuraScript);
+
+ void HandlePeriodic(AuraEffect const* /*aurEff*/)
+ {
+ PreventDefaultAction();
+ GetTarget()->RemoveAurasByType(SPELL_AURA_PHASE);
+ }
+
+ void Register()
+ {
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_algalon_remove_phase_AuraScript::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
+ }
+ };
+
+ AuraScript* GetAuraScript() const
+ {
+ return new spell_algalon_remove_phase_AuraScript();
+ }
+};
+
+class spell_algalon_cosmic_smash : public SpellScriptLoader
+{
+ public:
+ spell_algalon_cosmic_smash() : SpellScriptLoader("spell_algalon_cosmic_smash") { }
+
+ class spell_algalon_cosmic_smash_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_algalon_cosmic_smash_SpellScript);
+
+ void ModDestHeight(SpellEffIndex /*effIndex*/)
+ {
+ Position offset = {0.0f, 0.0f, 65.0f, 0.0f};
+ const_cast<WorldLocation*>(GetTargetDest())->RelocateOffset(offset);
+ GetHitDest()->RelocateOffset(offset);
+ }
+
+ void Register()
+ {
+ OnEffectLaunch += SpellEffectFn(spell_algalon_cosmic_smash_SpellScript::ModDestHeight, EFFECT_0, SPELL_EFFECT_SUMMON);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_algalon_cosmic_smash_SpellScript();
+ }
+};
+
+class spell_algalon_cosmic_smash_damage : public SpellScriptLoader
+{
+ public:
+ spell_algalon_cosmic_smash_damage() : SpellScriptLoader("spell_algalon_cosmic_smash_damage") { }
+
+ class spell_algalon_cosmic_smash_damage_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_algalon_cosmic_smash_damage_SpellScript);
+
+ void RecalculateDamage()
+ {
+ if (!GetTargetDest() || !GetHitUnit())
+ return;
+
+ float distance = GetHitUnit()->GetDistance2d(GetTargetDest()->GetPositionX(), GetTargetDest()->GetPositionY());
+ if (distance > 6.0f)
+ SetHitDamage(int32(float(GetHitDamage()) / distance) * 2);
+ }
+
+ void Register()
+ {
+ OnHit += SpellHitFn(spell_algalon_cosmic_smash_damage_SpellScript::RecalculateDamage);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_algalon_cosmic_smash_damage_SpellScript();
+ }
+};
+
+class spell_algalon_supermassive_fail : public SpellScriptLoader
+{
+ public:
+ spell_algalon_supermassive_fail() : SpellScriptLoader("spell_algalon_supermassive_fail") { }
+
+ class spell_algalon_supermassive_fail_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_algalon_supermassive_fail_SpellScript);
+
+ void RecalculateDamage()
+ {
+ if (!GetHitPlayer())
+ return;
+
+ GetHitPlayer()->GetAchievementMgr().ResetAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, ACHIEVEMENT_CRITERIA_CONDITION_NO_SPELL_HIT, GetSpellInfo()->Id, true);
+ }
+
+ void Register()
+ {
+ OnHit += SpellHitFn(spell_algalon_supermassive_fail_SpellScript::RecalculateDamage);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_algalon_supermassive_fail_SpellScript();
+ }
+};
+
+class achievement_he_feeds_on_your_tears : public AchievementCriteriaScript
+{
+ public:
+ achievement_he_feeds_on_your_tears() : AchievementCriteriaScript("achievement_he_feeds_on_your_tears") { }
+
+ bool OnCheck(Player* /*source*/, Unit* target)
+ {
+ return !target->GetAI()->GetData(DATA_HAS_FED_ON_TEARS);
+ }
+};
+
+void AddSC_boss_algalon_the_observer()
+{
+ new boss_algalon_the_observer();
+ new npc_living_constellation();
+ new npc_collapsing_star();
+ new npc_brann_bronzebeard_algalon();
+ new go_celestial_planetarium_access();
+ new spell_algalon_phase_punch();
+ new spell_algalon_arcane_barrage();
+ new spell_algalon_trigger_3_adds();
+ new spell_algalon_collapse();
+ new spell_algalon_big_bang();
+ new spell_algalon_remove_phase();
+ new spell_algalon_cosmic_smash();
+ new spell_algalon_cosmic_smash_damage();
+ new spell_algalon_supermassive_fail();
+ new achievement_he_feeds_on_your_tears();
+}
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 5d68da4e75a..462c767f599 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp
@@ -1273,7 +1273,7 @@ class go_ulduar_tower : public GameObjectScript
public:
go_ulduar_tower() : GameObjectScript("go_ulduar_tower") { }
- void OnDestroyed(GameObject* go, Player* /*player*/, uint32 /*value*/)
+ void OnDestroyed(GameObject* go, Player* /*player*/)
{
InstanceScript* instance = go->GetInstanceScript();
if (!instance)
@@ -1678,7 +1678,7 @@ class spell_pursue : public SpellScriptLoader
else
{
//! In the end, only one target should be selected
- _target = SelectRandomContainerElement(targets);
+ _target = Trinity::Containers::SelectRandomContainerElement(targets);
FilterTargetsSubsequently(targets);
}
}
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp
index 61f82d898b9..3556bf188de 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp
@@ -290,7 +290,7 @@ class boss_general_vezax : public CreatureScript
if (size < playersMin)
return NULL;
- return SelectRandomContainerElement(PlayerList);
+ return Trinity::Containers::SelectRandomContainerElement(PlayerList);
}
return NULL;
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp
index 727f40aef81..c7091b42c5a 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp
@@ -947,13 +947,19 @@ class spell_xt002_tympanic_tantrum : public SpellScriptLoader
void FilterTargets(std::list<Unit*>& unitList)
{
- unitList.remove_if (PlayerOrPetCheck());
+ unitList.remove_if(PlayerOrPetCheck());
+ }
+
+ void RecalculateDamage()
+ {
+ SetHitDamage(GetHitUnit()->CountPctFromMaxHealth(GetHitDamage()));
}
void Register()
{
OnUnitTargetSelect += SpellUnitTargetFn(spell_xt002_tympanic_tantrum_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
OnUnitTargetSelect += SpellUnitTargetFn(spell_xt002_tympanic_tantrum_SpellScript::FilterTargets, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY);
+ OnHit += SpellHitFn(spell_xt002_tympanic_tantrum_SpellScript::RecalculateDamage);
}
};
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp
index e12393f047f..654d763ddbc 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp
@@ -22,9 +22,14 @@
static DoorData const doorData[] =
{
- { GO_LEVIATHAN_DOOR, BOSS_LEVIATHAN, DOOR_TYPE_ROOM, BOUNDARY_S },
- { GO_XT_002_DOOR, BOSS_XT002, DOOR_TYPE_ROOM, BOUNDARY_S },
- { 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE },
+ {GO_LEVIATHAN_DOOR, BOSS_LEVIATHAN, DOOR_TYPE_ROOM, BOUNDARY_S },
+ {GO_XT_002_DOOR, BOSS_XT002, DOOR_TYPE_ROOM, BOUNDARY_S },
+ {GO_DOODAD_UL_SIGILDOOR_03, BOSS_ALGALON, DOOR_TYPE_ROOM, BOUNDARY_W },
+ {GO_DOODAD_UL_UNIVERSEFLOOR_01, BOSS_ALGALON, DOOR_TYPE_ROOM, BOUNDARY_NONE },
+ {GO_DOODAD_UL_UNIVERSEFLOOR_02, BOSS_ALGALON, DOOR_TYPE_SPAWN_HOLE, BOUNDARY_NONE },
+ {GO_DOODAD_UL_UNIVERSEGLOBE01, BOSS_ALGALON, DOOR_TYPE_SPAWN_HOLE, BOUNDARY_NONE },
+ {GO_DOODAD_UL_ULDUAR_TRAPDOOR_03, BOSS_ALGALON, DOOR_TYPE_SPAWN_HOLE, BOUNDARY_NONE },
+ {0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE },
};
class instance_ulduar : public InstanceMapScript
@@ -36,7 +41,6 @@ class instance_ulduar : public InstanceMapScript
{
instance_ulduar_InstanceMapScript(InstanceMap* map) : InstanceScript(map) { }
- uint32 Encounter[MAX_ENCOUNTER];
std::string m_strInstData;
// Creatures
@@ -72,6 +76,12 @@ class instance_ulduar : public InstanceMapScript
uint64 HodirDoorGUID;
uint64 HodirIceDoorGUID;
uint64 ArchivumDoorGUID;
+ uint64 AlgalonSigilDoorGUID[3];
+ uint64 AlgalonFloorGUID[2];
+ uint64 AlgalonUniverseGUID;
+ uint64 AlgalonTrapdoorGUID;
+ uint64 BrannBronzebeardAlgGUID;
+ uint64 GiftOfTheObserverGUID;
// Miscellaneous
uint32 TeamInInstance;
@@ -111,35 +121,49 @@ class instance_ulduar : public InstanceMapScript
HodirDoorGUID = 0;
HodirIceDoorGUID = 0;
ArchivumDoorGUID = 0;
+ AlgalonUniverseGUID = 0;
+ AlgalonTrapdoorGUID = 0;
+ BrannBronzebeardAlgGUID = 0;
+ GiftOfTheObserverGUID = 0;
+ _algalonTimer = 61;
+ _maxArmorItemLevel = 0;
+ _maxWeaponItemLevel = 0;
TeamInInstance = 0;
HodirRareCacheData = 0;
ColossusData = 0;
elderCount = 0;
conSpeedAtory = false;
Unbroken = true;
+ _summonAlgalon = false;
- memset(Encounter, 0, sizeof(Encounter));
+ memset(AlgalonSigilDoorGUID, 0, sizeof(AlgalonSigilDoorGUID));
+ memset(AlgalonFloorGUID, 0, sizeof(AlgalonFloorGUID));
memset(XTToyPileGUIDs, 0, sizeof(XTToyPileGUIDs));
memset(AssemblyGUIDs, 0, sizeof(AssemblyGUIDs));
memset(RazorHarpoonGUIDs, 0, sizeof(RazorHarpoonGUIDs));
memset(KeeperGUIDs, 0, sizeof(KeeperGUIDs));
}
- bool IsEncounterInProgress() const
+ void FillInitialWorldStates(WorldPacket& packet)
{
- for (uint8 i = 0; i < MAX_ENCOUNTER; ++i)
- {
- if (Encounter[i] == IN_PROGRESS)
- return true;
- }
-
- return false;
+ packet << uint32(WORLD_STATE_ALGALON_TIMER_ENABLED) << uint32(_algalonTimer && _algalonTimer <= 60);
+ packet << uint32(WORLD_STATE_ALGALON_DESPAWN_TIMER) << uint32(std::min<uint32>(_algalonTimer, 60));
}
void OnPlayerEnter(Player* player)
{
if (!TeamInInstance)
TeamInInstance = player->GetTeam();
+
+ if (_summonAlgalon)
+ {
+ _summonAlgalon = false;
+ TempSummon* algalon = instance->SummonCreature(NPC_ALGALON, AlgalonLandPos);
+ if (_algalonTimer && _algalonTimer <= 60)
+ algalon->AI()->DoAction(ACTION_INIT_ALGALON);
+ else
+ algalon->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
+ }
}
void OnCreatureCreate(Creature* creature)
@@ -234,7 +258,6 @@ class instance_ulduar : public InstanceMapScript
case NPC_ALGALON:
AlgalonGUID = creature->GetGUID();
break;
-
// Hodir's Helper NPCs
case NPC_EIVI_NIGHTFEATHER:
if (TeamInInstance == HORDE)
@@ -268,9 +291,32 @@ class instance_ulduar : public InstanceMapScript
if (TeamInInstance == HORDE)
creature->UpdateEntry(NPC_BATTLE_PRIEST_GINA, HORDE);
break;
+ case NPC_BRANN_BRONZBEARD_ALG:
+ BrannBronzebeardAlgGUID = creature->GetGUID();
+ break;
+ //! These creatures are summoned by something else than Algalon
+ //! but need to be controlled/despawned by him - so they need to be
+ //! registered in his summon list
+ case NPC_ALGALON_VOID_ZONE_VISUAL_STALKER:
+ case NPC_ALGALON_STALKER_ASTEROID_TARGET_01:
+ case NPC_ALGALON_STALKER_ASTEROID_TARGET_02:
+ case NPC_UNLEASHED_DARK_MATTER:
+ if (Creature* algalon = instance->GetCreature(AlgalonGUID))
+ algalon->AI()->JustSummoned(creature);
+ break;
}
+ }
- }
+ void OnCreatureRemove(Creature* creature)
+ {
+ switch (creature->GetEntry())
+ {
+ case NPC_BRANN_BRONZBEARD_ALG:
+ if (BrannBronzebeardAlgGUID == creature->GetGUID())
+ BrannBronzebeardAlgGUID = 0;
+ break;
+ }
+ }
void OnGameObjectCreate(GameObject* gameObject)
{
@@ -341,6 +387,45 @@ class instance_ulduar : public InstanceMapScript
if (GetBossState(BOSS_ASSEMBLY_OF_IRON) != DONE)
HandleGameObject(ArchivumDoorGUID, false);
break;
+ case GO_CELESTIAL_PLANETARIUM_ACCESS_10:
+ case GO_CELESTIAL_PLANETARIUM_ACCESS_25:
+ if (_algalonSummoned)
+ gameObject->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_IN_USE);
+ break;
+ case GO_DOODAD_UL_SIGILDOOR_01:
+ AlgalonSigilDoorGUID[0] = gameObject->GetGUID();
+ if (_algalonSummoned)
+ gameObject->SetGoState(GO_STATE_ACTIVE);
+ break;
+ case GO_DOODAD_UL_SIGILDOOR_02:
+ AlgalonSigilDoorGUID[1] = gameObject->GetGUID();
+ if (_algalonSummoned)
+ gameObject->SetGoState(GO_STATE_ACTIVE);
+ break;
+ case GO_DOODAD_UL_SIGILDOOR_03:
+ AlgalonSigilDoorGUID[2] = gameObject->GetGUID();
+ AddDoor(gameObject, true);
+ break;
+ case GO_DOODAD_UL_UNIVERSEFLOOR_01:
+ AlgalonFloorGUID[0] = gameObject->GetGUID();
+ AddDoor(gameObject, true);
+ break;
+ case GO_DOODAD_UL_UNIVERSEFLOOR_02:
+ AlgalonFloorGUID[1] = gameObject->GetGUID();
+ AddDoor(gameObject, true);
+ break;
+ case GO_DOODAD_UL_UNIVERSEGLOBE01:
+ AlgalonUniverseGUID = gameObject->GetGUID();
+ AddDoor(gameObject, true);
+ break;
+ case GO_DOODAD_UL_ULDUAR_TRAPDOOR_03:
+ AlgalonTrapdoorGUID = gameObject->GetGUID();
+ AddDoor(gameObject, true);
+ break;
+ case GO_GIFT_OF_THE_OBSERVER_10:
+ case GO_GIFT_OF_THE_OBSERVER_25:
+ GiftOfTheObserverGUID = gameObject->GetGUID();
+ break;
}
}
@@ -349,10 +434,14 @@ class instance_ulduar : public InstanceMapScript
switch (gameObject->GetEntry())
{
case GO_LEVIATHAN_DOOR:
- AddDoor(gameObject, false);
- break;
case GO_XT_002_DOOR:
+ case GO_DOODAD_UL_SIGILDOOR_03:
+ case GO_DOODAD_UL_UNIVERSEFLOOR_01:
+ case GO_DOODAD_UL_UNIVERSEFLOOR_02:
+ case GO_DOODAD_UL_UNIVERSEGLOBE01:
+ case GO_DOODAD_UL_ULDUAR_TRAPDOOR_03:
AddDoor(gameObject, false);
+ break;
default:
break;
}
@@ -390,6 +479,7 @@ class instance_ulduar : public InstanceMapScript
// Flame Leviathan's Tower Event triggers
Creature* FlameLeviathan = instance->GetCreature(LeviathanGUID);
if (FlameLeviathan && FlameLeviathan->isAlive()) // No leviathan, no event triggering ;)
+ {
switch (eventId)
{
case EVENT_TOWER_OF_STORM_DESTROYED:
@@ -405,6 +495,7 @@ class instance_ulduar : public InstanceMapScript
FlameLeviathan->AI()->DoAction(ACTION_TOWER_OF_LIFE_DESTROYED);
break;
}
+ }
}
@@ -465,6 +556,52 @@ class instance_ulduar : public InstanceMapScript
if (GameObject* gameObject = instance->GetGameObject(ThorimChestGUID))
gameObject->SetRespawnTime(gameObject->GetRespawnDelay());
break;
+ case BOSS_ALGALON:
+ if (state == DONE)
+ {
+ _events.CancelEvent(EVENT_UPDATE_ALGALON_TIMER);
+ _events.CancelEvent(EVENT_DESPAWN_ALGALON);
+ DoUpdateWorldState(WORLD_STATE_ALGALON_TIMER_ENABLED, 0);
+ _algalonTimer = 61;
+ if (GameObject* gameObject = instance->GetGameObject(GiftOfTheObserverGUID))
+ gameObject->SetRespawnTime(gameObject->GetRespawnDelay());
+ // get item level (recheck weapons)
+ Map::PlayerList const& players = instance->GetPlayers();
+ for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
+ if (Player* player = itr->getSource())
+ for (uint8 slot = EQUIPMENT_SLOT_MAINHAND; slot <= EQUIPMENT_SLOT_RANGED; ++slot)
+ if (Item* item = player->GetItemByPos(INVENTORY_SLOT_BAG_0, slot))
+ if (item->GetTemplate()->ItemLevel > _maxWeaponItemLevel)
+ _maxWeaponItemLevel = item->GetTemplate()->ItemLevel;
+ }
+ else if (state == IN_PROGRESS)
+ {
+ // get item level (armor cannot be swapped in combat)
+ Map::PlayerList const& players = instance->GetPlayers();
+ for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
+ {
+ if (Player* player = itr->getSource())
+ {
+ for (uint8 slot = EQUIPMENT_SLOT_START; slot < EQUIPMENT_SLOT_END; ++slot)
+ {
+ if (slot == EQUIPMENT_SLOT_TABARD || slot == EQUIPMENT_SLOT_BODY)
+ continue;
+
+ if (Item* item = player->GetItemByPos(INVENTORY_SLOT_BAG_0, slot))
+ {
+ if (slot >= EQUIPMENT_SLOT_MAINHAND && slot <= EQUIPMENT_SLOT_RANGED)
+ {
+ if (item->GetTemplate()->ItemLevel > _maxWeaponItemLevel)
+ _maxWeaponItemLevel = item->GetTemplate()->ItemLevel;
+ }
+ else if (item->GetTemplate()->ItemLevel > _maxArmorItemLevel)
+ _maxArmorItemLevel = item->GetTemplate()->ItemLevel;
+ }
+ }
+ }
+ }
+ }
+ break;
}
return true;
@@ -497,6 +634,16 @@ class instance_ulduar : public InstanceMapScript
case DATA_UNBROKEN:
Unbroken = bool(data);
break;
+ case EVENT_DESPAWN_ALGALON:
+ DoUpdateWorldState(WORLD_STATE_ALGALON_TIMER_ENABLED, 1);
+ DoUpdateWorldState(WORLD_STATE_ALGALON_DESPAWN_TIMER, 60);
+ _algalonTimer = 60;
+ _events.ScheduleEvent(EVENT_DESPAWN_ALGALON, 3600000);
+ _events.ScheduleEvent(EVENT_UPDATE_ALGALON_TIMER, 60000);
+ break;
+ case DATA_ALGALON_SUMMON_STATE:
+ _algalonSummoned = true;
+ break;
default:
break;
}
@@ -571,6 +718,22 @@ class instance_ulduar : public InstanceMapScript
return KeeperGUIDs[1];
case BOSS_STONEBARK:
return KeeperGUIDs[2];
+ case DATA_SIGILDOOR_01:
+ return AlgalonSigilDoorGUID[0];
+ case DATA_SIGILDOOR_02:
+ return AlgalonSigilDoorGUID[1];
+ case DATA_SIGILDOOR_03:
+ return AlgalonSigilDoorGUID[2];
+ case DATA_UNIVERSE_FLOOR_01:
+ return AlgalonFloorGUID[0];
+ case DATA_UNIVERSE_FLOOR_02:
+ return AlgalonFloorGUID[1];
+ case DATA_UNIVERSE_GLOBE:
+ return AlgalonUniverseGUID;
+ case DATA_ALGALON_TRAPDOOR:
+ return AlgalonTrapdoorGUID;
+ case DATA_BRANN_BRONZEBEARD_ALG:
+ return BrannBronzebeardAlgGUID;
}
return 0;
@@ -593,12 +756,23 @@ class instance_ulduar : public InstanceMapScript
return 0;
}
+ bool CheckAchievementCriteriaMeet(uint32 criteriaId, Player const* , Unit const* /* = NULL */, uint32 /* = 0 */)
+ {
+ switch (criteriaId)
+ {
+ case CRITERIA_HERALD_OF_TITANS:
+ return _maxArmorItemLevel <= MAX_HERALD_ARMOR_ITEMLEVEL && _maxWeaponItemLevel <= MAX_HERALD_WEAPON_ITEMLEVEL;
+ }
+
+ return false;
+ }
+
std::string GetSaveData()
{
OUT_SAVE_INST_DATA;
std::ostringstream saveStream;
- saveStream << "U U " << GetBossSaveData() << GetData(DATA_COLOSSUS);
+ saveStream << "U U " << GetBossSaveData() << GetData(DATA_COLOSSUS) << ' ' << _algalonTimer << ' ' << (_algalonSummoned ? 1 : 0);
OUT_SAVE_INST_DATA_COMPLETE;
return saveStream.str();
@@ -628,15 +802,68 @@ class instance_ulduar : public InstanceMapScript
if (tmpState == IN_PROGRESS || tmpState > SPECIAL)
tmpState = NOT_STARTED;
- if (i == DATA_COLOSSUS)
- SetData(i, tmpState);
- else
- SetBossState(i, EncounterState(tmpState));
+ SetBossState(i, EncounterState(tmpState));
+ }
+
+ uint32 tempState;
+ loadStream >> tempState;
+ if (tempState == IN_PROGRESS || tempState > SPECIAL)
+ tempState = NOT_STARTED;
+ SetData(DATA_COLOSSUS, tempState);
+
+ loadStream >> _algalonTimer;
+ loadStream >> tempState;
+ _algalonSummoned = tempState != 0;
+ if (_algalonSummoned && GetBossState(BOSS_ALGALON) != DONE)
+ {
+ _summonAlgalon = true;
+ if (_algalonTimer && _algalonTimer <= 60)
+ {
+ _events.ScheduleEvent(EVENT_UPDATE_ALGALON_TIMER, 60000);
+ DoUpdateWorldState(WORLD_STATE_ALGALON_TIMER_ENABLED, 1);
+ DoUpdateWorldState(WORLD_STATE_ALGALON_DESPAWN_TIMER, _algalonTimer);
+ }
}
}
OUT_LOAD_INST_DATA_COMPLETE;
}
+
+ void Update(uint32 diff)
+ {
+ if (_events.Empty())
+ return;
+
+ _events.Update(diff);
+
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_UPDATE_ALGALON_TIMER:
+ SaveToDB();
+ DoUpdateWorldState(WORLD_STATE_ALGALON_DESPAWN_TIMER, --_algalonTimer);
+ if (_algalonTimer)
+ _events.ScheduleEvent(EVENT_UPDATE_ALGALON_TIMER, 60000);
+ else
+ {
+ DoUpdateWorldState(WORLD_STATE_ALGALON_TIMER_ENABLED, 0);
+ _events.CancelEvent(EVENT_UPDATE_ALGALON_TIMER);
+ if (Creature* algalon = instance->GetCreature(AlgalonGUID))
+ algalon->AI()->DoAction(EVENT_DESPAWN_ALGALON);
+ }
+ break;
+ }
+ }
+ }
+
+ private:
+ EventMap _events;
+ uint32 _algalonTimer;
+ bool _summonAlgalon;
+ bool _algalonSummoned;
+ uint32 _maxArmorItemLevel;
+ uint32 _maxWeaponItemLevel;
};
InstanceScript* GetInstanceScript(InstanceMap* map) const
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h b/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h
index a31954b8a16..d35f0559080 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h
@@ -21,6 +21,8 @@
#include "ObjectMgr.h"
#define UlduarScriptName "instance_ulduar"
+extern Position const AlgalonLandPos;
+
enum UlduarBosses
{
MAX_ENCOUNTER = 20,
@@ -50,98 +52,124 @@ enum UlduarBosses
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,
- NPC_STEELFORGED_DEFFENDER = 33236,
- NPC_EXPEDITION_COMMANDER = 33210,
- NPC_XT002 = 33293,
- NPC_XT_TOY_PILE = 33337,
- NPC_STEELBREAKER = 32867,
- NPC_MOLGEIM = 32927,
- NPC_BRUNDIR = 32857,
- NPC_KOLOGARN = 32930,
- NPC_FOCUSED_EYEBEAM = 33632,
- NPC_FOCUSED_EYEBEAM_RIGHT = 33802,
- NPC_LEFT_ARM = 32933,
- NPC_RIGHT_ARM = 32934,
- NPC_RUBBLE = 33768,
- NPC_AURIAYA = 33515,
- NPC_MIMIRON = 33350,
- NPC_HODIR = 32845,
- NPC_THORIM = 32865,
- NPC_FREYA = 32906,
- NPC_VEZAX = 33271,
- NPC_YOGGSARON = 33288,
- NPC_ALGALON = 32871,
+ NPC_LEVIATHAN = 33113,
+ NPC_SALVAGED_DEMOLISHER = 33109,
+ NPC_SALVAGED_SIEGE_ENGINE = 33060,
+ NPC_IGNIS = 33118,
+ NPC_RAZORSCALE = 33186,
+ NPC_RAZORSCALE_CONTROLLER = 33233,
+ NPC_STEELFORGED_DEFFENDER = 33236,
+ NPC_EXPEDITION_COMMANDER = 33210,
+ NPC_XT002 = 33293,
+ NPC_XT_TOY_PILE = 33337,
+ NPC_STEELBREAKER = 32867,
+ NPC_MOLGEIM = 32927,
+ NPC_BRUNDIR = 32857,
+ NPC_KOLOGARN = 32930,
+ NPC_FOCUSED_EYEBEAM = 33632,
+ NPC_FOCUSED_EYEBEAM_RIGHT = 33802,
+ NPC_LEFT_ARM = 32933,
+ NPC_RIGHT_ARM = 32934,
+ NPC_RUBBLE = 33768,
+ NPC_AURIAYA = 33515,
+ NPC_MIMIRON = 33350,
+ NPC_HODIR = 32845,
+ NPC_THORIM = 32865,
+ NPC_FREYA = 32906,
+ NPC_VEZAX = 33271,
+ NPC_YOGGSARON = 33288,
+ NPC_ALGALON = 32871,
// Mimiron
- NPC_LEVIATHAN_MKII = 33432,
- NPC_VX_001 = 33651,
- NPC_AERIAL_COMMAND_UNIT = 33670,
+ NPC_LEVIATHAN_MKII = 33432,
+ NPC_VX_001 = 33651,
+ NPC_AERIAL_COMMAND_UNIT = 33670,
// Freya's Keepers
- NPC_IRONBRANCH = 32913,
- NPC_BRIGHTLEAF = 32915,
- NPC_STONEBARK = 32914,
+ NPC_IRONBRANCH = 32913,
+ NPC_BRIGHTLEAF = 32915,
+ NPC_STONEBARK = 32914,
// Hodir's Helper NPCs
- NPC_TOR_GREYCLOUD = 32941,
- NPC_KAR_GREYCLOUD = 33333,
- NPC_EIVI_NIGHTFEATHER = 33325,
- NPC_ELLIE_NIGHTFEATHER = 32901,
- NPC_SPIRITWALKER_TARA = 33332,
- NPC_SPIRITWALKER_YONA = 32950,
- NPC_ELEMENTALIST_MAHFUUN = 33328,
- NPC_ELEMENTALIST_AVUUN = 32900,
- NPC_AMIRA_BLAZEWEAVER = 33331,
- NPC_VEESHA_BLAZEWEAVER = 32946,
- NPC_MISSY_FLAMECUFFS = 32893,
- NPC_SISSY_FLAMECUFFS = 33327,
- NPC_BATTLE_PRIEST_ELIZA = 32948,
- NPC_BATTLE_PRIEST_GINA = 33330,
- NPC_FIELD_MEDIC_PENNY = 32897,
- NPC_FIELD_MEDIC_JESSI = 33326,
+ NPC_TOR_GREYCLOUD = 32941,
+ NPC_KAR_GREYCLOUD = 33333,
+ NPC_EIVI_NIGHTFEATHER = 33325,
+ NPC_ELLIE_NIGHTFEATHER = 32901,
+ NPC_SPIRITWALKER_TARA = 33332,
+ NPC_SPIRITWALKER_YONA = 32950,
+ NPC_ELEMENTALIST_MAHFUUN = 33328,
+ NPC_ELEMENTALIST_AVUUN = 32900,
+ NPC_AMIRA_BLAZEWEAVER = 33331,
+ NPC_VEESHA_BLAZEWEAVER = 32946,
+ NPC_MISSY_FLAMECUFFS = 32893,
+ NPC_SISSY_FLAMECUFFS = 33327,
+ NPC_BATTLE_PRIEST_ELIZA = 32948,
+ NPC_BATTLE_PRIEST_GINA = 33330,
+ NPC_FIELD_MEDIC_PENNY = 32897,
+ NPC_FIELD_MEDIC_JESSI = 33326,
// Freya's trash NPCs
- NPC_CORRUPTED_SERVITOR = 33354,
- NPC_MISGUIDED_NYMPH = 33355,
- NPC_GUARDIAN_LASHER = 33430,
- NPC_FOREST_SWARMER = 33431,
- NPC_MANGROVE_ENT = 33525,
- NPC_IRONROOT_LASHER = 33526,
- NPC_NATURES_BLADE = 33527,
- NPC_GUARDIAN_OF_LIFE = 33528,
+ NPC_CORRUPTED_SERVITOR = 33354,
+ NPC_MISGUIDED_NYMPH = 33355,
+ NPC_GUARDIAN_LASHER = 33430,
+ NPC_FOREST_SWARMER = 33431,
+ NPC_MANGROVE_ENT = 33525,
+ NPC_IRONROOT_LASHER = 33526,
+ NPC_NATURES_BLADE = 33527,
+ NPC_GUARDIAN_OF_LIFE = 33528,
+
+ // Algalon the Observer
+ NPC_BRANN_BRONZBEARD_ALG = 34064,
+ NPC_AZEROTH = 34246,
+ NPC_LIVING_CONSTELLATION = 33052,
+ NPC_ALGALON_STALKER = 33086,
+ NPC_COLLAPSING_STAR = 32955,
+ NPC_BLACK_HOLE = 32953,
+ NPC_WORM_HOLE = 34099,
+ NPC_ALGALON_VOID_ZONE_VISUAL_STALKER = 34100,
+ NPC_ALGALON_STALKER_ASTEROID_TARGET_01 = 33104,
+ NPC_ALGALON_STALKER_ASTEROID_TARGET_02 = 33105,
+ NPC_UNLEASHED_DARK_MATTER = 34097,
};
enum UlduarGameObjects
{
- GO_KOLOGARN_CHEST_HERO = 195047,
- GO_KOLOGARN_CHEST = 195046,
- GO_KOLOGARN_BRIDGE = 194232,
- GO_KOLOGARN_DOOR = 194553,
- GO_THORIM_CHEST_HERO = 194315,
- GO_THORIM_CHEST = 194314,
- GO_HODIR_RARE_CACHE_OF_WINTER = 194200,
- GO_HODIR_RARE_CACHE_OF_WINTER_HERO = 194201,
- GO_HODIR_CHEST_HERO = 194308,
- GO_HODIR_CHEST = 194307,
- GO_LEVIATHAN_DOOR = 194905,
- GO_LEVIATHAN_GATE = 194630,
- GO_XT_002_DOOR = 194631,
- GO_VEZAX_DOOR = 194750,
- GO_MOLE_MACHINE = 194316,
- GO_RAZOR_HARPOON_1 = 194542,
- GO_RAZOR_HARPOON_2 = 194541,
- GO_RAZOR_HARPOON_3 = 194543,
- GO_RAZOR_HARPOON_4 = 194519,
- GO_RAZOR_BROKEN_HARPOON = 194565,
- GO_HODIR_DOOR = 194634,
- GO_HODIR_ICE_DOOR = 194441,
- GO_ARCHIVUM_DOOR = 194556,
+ GO_KOLOGARN_CHEST_HERO = 195047,
+ GO_KOLOGARN_CHEST = 195046,
+ GO_KOLOGARN_BRIDGE = 194232,
+ GO_KOLOGARN_DOOR = 194553,
+ GO_THORIM_CHEST_HERO = 194315,
+ GO_THORIM_CHEST = 194314,
+ GO_HODIR_RARE_CACHE_OF_WINTER = 194200,
+ GO_HODIR_RARE_CACHE_OF_WINTER_HERO = 194201,
+ GO_HODIR_CHEST_HERO = 194308,
+ GO_HODIR_CHEST = 194307,
+ GO_LEVIATHAN_DOOR = 194905,
+ GO_LEVIATHAN_GATE = 194630,
+ GO_XT_002_DOOR = 194631,
+ GO_VEZAX_DOOR = 194750,
+ GO_MOLE_MACHINE = 194316,
+ GO_RAZOR_HARPOON_1 = 194542,
+ GO_RAZOR_HARPOON_2 = 194541,
+ GO_RAZOR_HARPOON_3 = 194543,
+ GO_RAZOR_HARPOON_4 = 194519,
+ GO_RAZOR_BROKEN_HARPOON = 194565,
+ GO_HODIR_DOOR = 194634,
+ GO_HODIR_ICE_DOOR = 194441,
+ GO_ARCHIVUM_DOOR = 194556,
+
+ // Algalon the Observer
+ GO_CELESTIAL_PLANETARIUM_ACCESS_10 = 194628,
+ GO_CELESTIAL_PLANETARIUM_ACCESS_25 = 194752,
+ GO_DOODAD_UL_SIGILDOOR_01 = 194767,
+ GO_DOODAD_UL_SIGILDOOR_02 = 194911,
+ GO_DOODAD_UL_SIGILDOOR_03 = 194910,
+ GO_DOODAD_UL_UNIVERSEFLOOR_01 = 194715,
+ GO_DOODAD_UL_UNIVERSEFLOOR_02 = 194716,
+ GO_DOODAD_UL_UNIVERSEGLOBE01 = 194148,
+ GO_DOODAD_UL_ULDUAR_TRAPDOOR_03 = 194253,
+ GO_GIFT_OF_THE_OBSERVER_10 = 194821,
+ GO_GIFT_OF_THE_OBSERVER_25 = 194822,
};
enum LeviathanData
@@ -161,6 +189,7 @@ enum UlduarAchievementCriteriaIds
{
CRITERIA_CON_SPEED_ATORY = 21597,
CRITERIA_DISARMED = 21687,
+ CRITERIA_HERALD_OF_TITANS = 10678,
};
enum UlduarData
@@ -180,12 +209,38 @@ enum UlduarData
// Hodir
DATA_HODIR_RARE_CACHE,
+
+ // Algalon the Observer
+ DATA_ALGALON_SUMMON_STATE,
+ DATA_SIGILDOOR_01,
+ DATA_SIGILDOOR_02,
+ DATA_SIGILDOOR_03,
+ DATA_UNIVERSE_FLOOR_01,
+ DATA_UNIVERSE_FLOOR_02,
+ DATA_UNIVERSE_GLOBE,
+ DATA_ALGALON_TRAPDOOR,
+ DATA_BRANN_BRONZEBEARD_ALG,
+};
+
+enum UlduarWorldStates
+{
+ WORLD_STATE_ALGALON_DESPAWN_TIMER = 4131,
+ WORLD_STATE_ALGALON_TIMER_ENABLED = 4132,
};
enum UlduarAchievementData
{
// FL Achievement boolean
DATA_UNBROKEN = 29052906, // 2905, 2906 are achievement IDs,
+ MAX_HERALD_ARMOR_ITEMLEVEL = 226,
+ MAX_HERALD_WEAPON_ITEMLEVEL = 232,
+};
+
+enum UlduarEvents
+{
+ EVENT_DESPAWN_ALGALON = 1,
+ EVENT_UPDATE_ALGALON_TIMER = 2,
+ ACTION_INIT_ALGALON = 6,
};
template<class AI>
@@ -199,6 +254,17 @@ CreatureAI* GetUlduarAI(Creature* creature)
return NULL;
}
+template<class AI>
+GameObjectAI* GetUlduarAI(GameObject* go)
+{
+ if (InstanceMap* instance = go->GetMap()->ToInstanceMap())
+ if (instance->GetInstanceScript())
+ if (instance->GetScriptId() == sObjectMgr->GetScriptId(UlduarScriptName))
+ return new AI(go);
+
+ return NULL;
+}
+
class PlayerOrPetCheck
{
public:
diff --git a/src/server/scripts/Northrend/VaultOfArchavon/boss_emalon.cpp b/src/server/scripts/Northrend/VaultOfArchavon/boss_emalon.cpp
index dc58e51a5a1..4980ed36ec3 100644
--- a/src/server/scripts/Northrend/VaultOfArchavon/boss_emalon.cpp
+++ b/src/server/scripts/Northrend/VaultOfArchavon/boss_emalon.cpp
@@ -139,7 +139,7 @@ class boss_emalon : public CreatureScript
case EVENT_OVERCHARGE:
if (!summons.empty())
{
- Creature* minion = Unit::GetCreature(*me, SelectRandomContainerElement(summons));
+ Creature* minion = Unit::GetCreature(*me, Trinity::Containers::SelectRandomContainerElement(summons));
if (minion && minion->isAlive())
{
minion->CastSpell(me, SPELL_OVERCHARGED, true);
diff --git a/src/server/scripts/Outland/BlackTemple/boss_supremus.cpp b/src/server/scripts/Outland/BlackTemple/boss_supremus.cpp
index 0dd1d37116c..ce1732433c8 100644
--- a/src/server/scripts/Outland/BlackTemple/boss_supremus.cpp
+++ b/src/server/scripts/Outland/BlackTemple/boss_supremus.cpp
@@ -134,7 +134,8 @@ public:
if (!phase || phase == PHASE_CHASE)
{
phase = PHASE_STRIKE;
- summons.DoAction(EVENT_VOLCANO, 0);
+ DummyEntryCheckPredicate pred;
+ summons.DoAction(EVENT_VOLCANO, pred);
events.ScheduleEvent(EVENT_HATEFUL_STRIKE, 5000, GCD_CAST, PHASE_STRIKE);
me->SetSpeed(MOVE_RUN, 1.2f);
me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, false);
diff --git a/src/server/scripts/Outland/boss_doomlord_kazzak.cpp b/src/server/scripts/Outland/boss_doomlord_kazzak.cpp
index 147d2d60359..a213713ae1a 100644
--- a/src/server/scripts/Outland/boss_doomlord_kazzak.cpp
+++ b/src/server/scripts/Outland/boss_doomlord_kazzak.cpp
@@ -31,15 +31,15 @@ enum Texts
enum Spells
{
- SPELL_SHADOWVOLLEY = 32963,
+ SPELL_SHADOW_VOLLEY = 32963,
SPELL_CLEAVE = 31779,
SPELL_THUNDERCLAP = 36706,
- SPELL_VOIDBOLT = 39329,
- SPELL_MARKOFKAZZAK = 32960,
- SPELL_MARKOFKAZZAK_DAMAGE = 32961,
+ SPELL_VOID_BOLT = 39329,
+ SPELL_MARK_OF_KAZZAK = 32960,
SPELL_ENRAGE = 32964,
- SPELL_CAPTURESOUL = 32966,
- SPELL_TWISTEDREFLECTION = 21063
+ SPELL_CAPTURE_SOUL = 32966,
+ SPELL_TWISTED_REFLECTION = 21063,
+ SPELL_BERSERK = 32965,
};
enum Events
@@ -47,10 +47,11 @@ enum Events
EVENT_SHADOW_VOLLEY = 1,
EVENT_CLEAVE = 2,
EVENT_THUNDERCLAP = 3,
- EVENT_VOIDBOLT = 4,
+ EVENT_VOID_BOLT = 4,
EVENT_MARK_OF_KAZZAK = 5,
EVENT_ENRAGE = 6,
- EVENT_TWISTED_REFLECTION = 7
+ EVENT_TWISTED_REFLECTION = 7,
+ EVENT_BERSERK = 8
};
class boss_doomlord_kazzak : public CreatureScript
@@ -70,10 +71,11 @@ class boss_doomlord_kazzak : public CreatureScript
_events.ScheduleEvent(EVENT_SHADOW_VOLLEY, urand(6000, 10000));
_events.ScheduleEvent(EVENT_CLEAVE, 7000);
_events.ScheduleEvent(EVENT_THUNDERCLAP, urand(14000, 18000));
- _events.ScheduleEvent(EVENT_VOIDBOLT, 30000);
+ _events.ScheduleEvent(EVENT_VOID_BOLT, 30000);
_events.ScheduleEvent(EVENT_MARK_OF_KAZZAK, 25000);
_events.ScheduleEvent(EVENT_ENRAGE, 60000);
_events.ScheduleEvent(EVENT_TWISTED_REFLECTION, 33000);
+ _events.ScheduleEvent(EVENT_BERSERK, 180000);
}
void JustRespawned()
@@ -92,7 +94,7 @@ class boss_doomlord_kazzak : public CreatureScript
if (victim->GetTypeId() != TYPEID_PLAYER)
return;
- DoCast(me, SPELL_CAPTURESOUL);
+ DoCast(me, SPELL_CAPTURE_SOUL);
Talk(SAY_KILL);
}
@@ -118,7 +120,7 @@ class boss_doomlord_kazzak : public CreatureScript
switch (eventId)
{
case EVENT_SHADOW_VOLLEY:
- DoCastVictim(SPELL_SHADOWVOLLEY);
+ DoCastVictim(SPELL_SHADOW_VOLLEY);
_events.ScheduleEvent(EVENT_SHADOW_VOLLEY, urand(4000, 6000));
break;
case EVENT_CLEAVE:
@@ -129,13 +131,13 @@ class boss_doomlord_kazzak : public CreatureScript
DoCastVictim(SPELL_THUNDERCLAP);
_events.ScheduleEvent(EVENT_THUNDERCLAP, urand(10000, 14000));
break;
- case EVENT_VOIDBOLT:
- DoCastVictim(SPELL_VOIDBOLT);
- _events.ScheduleEvent(EVENT_VOIDBOLT, urand(15000, 18000));
+ case EVENT_VOID_BOLT:
+ DoCastVictim(SPELL_VOID_BOLT);
+ _events.ScheduleEvent(EVENT_VOID_BOLT, urand(15000, 18000));
break;
case EVENT_MARK_OF_KAZZAK:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
- DoCast(target, SPELL_MARKOFKAZZAK);
+ DoCast(target, SPELL_MARK_OF_KAZZAK);
_events.ScheduleEvent(EVENT_MARK_OF_KAZZAK, 20000);
break;
case EVENT_ENRAGE:
@@ -145,9 +147,12 @@ class boss_doomlord_kazzak : public CreatureScript
break;
case EVENT_TWISTED_REFLECTION:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
- DoCast(target, SPELL_TWISTEDREFLECTION);
+ DoCast(target, SPELL_TWISTED_REFLECTION);
_events.ScheduleEvent(EVENT_TWISTED_REFLECTION, 15000);
break;
+ case EVENT_BERSERK:
+ DoCast(me, SPELL_BERSERK);
+ break;
default:
break;
}
diff --git a/src/server/scripts/Outland/netherstorm.cpp b/src/server/scripts/Outland/netherstorm.cpp
index 4fdaebeacae..388d18697b9 100644
--- a/src/server/scripts/Outland/netherstorm.cpp
+++ b/src/server/scripts/Outland/netherstorm.cpp
@@ -812,7 +812,7 @@ public:
}
if (!UnitsWithMana.empty())
{
- DoCast(SelectRandomContainerElement(UnitsWithMana), SPELL_MANA_BURN);
+ DoCast(Trinity::Containers::SelectRandomContainerElement(UnitsWithMana), SPELL_MANA_BURN);
ManaBurnTimer = 8000 + (rand() % 10 * 1000); // 8-18 sec cd
}
else
diff --git a/src/server/scripts/Spells/spell_druid.cpp b/src/server/scripts/Spells/spell_druid.cpp
index 4c440f18bd9..380cac4e5ee 100644
--- a/src/server/scripts/Spells/spell_druid.cpp
+++ b/src/server/scripts/Spells/spell_druid.cpp
@@ -250,7 +250,7 @@ class spell_dru_t10_restoration_4p_bonus : public SpellScriptLoader
return;
}
- Unit* target = SelectRandomContainerElement(tempTargets);
+ Unit* target = Trinity::Containers::SelectRandomContainerElement(tempTargets);
unitList.clear();
unitList.push_back(target);
}
diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp
index 41d1c24c517..2d431331691 100644
--- a/src/server/scripts/Spells/spell_generic.cpp
+++ b/src/server/scripts/Spells/spell_generic.cpp
@@ -2601,7 +2601,7 @@ class spell_gen_wg_water : public SpellScriptLoader
SpellCastResult CheckCast()
{
- if (!GetSpellInfo()->CheckTargetCreatureType(GetTargetUnit()))
+ if (!GetSpellInfo()->CheckTargetCreatureType(GetCaster()))
return SPELL_FAILED_DONT_REPORT;
return SPELL_CAST_OK;
}
@@ -2618,6 +2618,44 @@ class spell_gen_wg_water : public SpellScriptLoader
}
};
+class spell_gen_count_pct_from_max_hp : public SpellScriptLoader
+{
+ public:
+ spell_gen_count_pct_from_max_hp(char const* name, int32 damagePct = 0) : SpellScriptLoader(name), _damagePct(damagePct) { }
+
+ class spell_gen_count_pct_from_max_hp_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_gen_count_pct_from_max_hp_SpellScript)
+
+ public:
+ spell_gen_count_pct_from_max_hp_SpellScript(int32 damagePct) : SpellScript(), _damagePct(damagePct) { }
+
+ void RecalculateDamage()
+ {
+ if (!_damagePct)
+ _damagePct = GetHitDamage();
+
+ SetHitDamage(GetHitUnit()->CountPctFromMaxHealth(_damagePct));
+ }
+
+ void Register()
+ {
+ OnHit += SpellHitFn(spell_gen_count_pct_from_max_hp_SpellScript::RecalculateDamage);
+ }
+
+ private:
+ int32 _damagePct;
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_gen_count_pct_from_max_hp_SpellScript(_damagePct);
+ }
+
+ private:
+ int32 _damagePct;
+};
+
void AddSC_generic_spell_scripts()
{
new spell_gen_absorb0_hitlimit1();
@@ -2669,4 +2707,6 @@ void AddSC_generic_spell_scripts()
new spell_gen_chaos_blast();
new spell_gen_ds_flush_knockback();
new spell_gen_wg_water();
+ new spell_gen_count_pct_from_max_hp("spell_gen_default_count_pct_from_max_hp");
+ new spell_gen_count_pct_from_max_hp("spell_gen_50pct_count_pct_from_max_hp", 50);
}
diff --git a/src/server/scripts/Spells/spell_item.cpp b/src/server/scripts/Spells/spell_item.cpp
index 666477e68e7..3c5d6438275 100644
--- a/src/server/scripts/Spells/spell_item.cpp
+++ b/src/server/scripts/Spells/spell_item.cpp
@@ -1744,6 +1744,7 @@ class spell_item_rocket_boots : public SpellScriptLoader
if (Battleground* bg = caster->GetBattleground())
bg->EventPlayerDroppedFlag(caster);
+ caster->RemoveSpellCooldown(SPELL_ROCKET_BOOTS_PROC);
caster->CastSpell(caster, SPELL_ROCKET_BOOTS_PROC, true, NULL);
}
@@ -2020,6 +2021,37 @@ class spell_item_muisek_vessel : public SpellScriptLoader
}
};
+enum GreatmothersSoulcather
+{
+ SPELL_FORCE_CAST_SUMMON_GNOME_SOUL = 46486,
+};
+class spell_item_greatmothers_soulcatcher : public SpellScriptLoader
+{
+public:
+ spell_item_greatmothers_soulcatcher() : SpellScriptLoader("spell_item_greatmothers_soulcatcher") { }
+
+ class spell_item_greatmothers_soulcatcher_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_item_greatmothers_soulcatcher_SpellScript);
+
+ void HandleDummy(SpellEffIndex /*effIndex*/)
+ {
+ if (Unit* target = GetHitUnit())
+ GetCaster()->CastSpell(GetCaster(),SPELL_FORCE_CAST_SUMMON_GNOME_SOUL);
+ }
+
+ void Register()
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_item_greatmothers_soulcatcher_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_item_greatmothers_soulcatcher_SpellScript();
+ }
+};
+
void AddSC_item_spell_scripts()
{
// 23074 Arcanite Dragonling
diff --git a/src/server/scripts/Spells/spell_mage.cpp b/src/server/scripts/Spells/spell_mage.cpp
index b746c37a090..050741ffaba 100644
--- a/src/server/scripts/Spells/spell_mage.cpp
+++ b/src/server/scripts/Spells/spell_mage.cpp
@@ -250,9 +250,11 @@ class spell_mage_frost_warding_trigger : public SpellScriptLoader
if (roll_chance_i(chance))
{
- absorbAmount = dmgInfo.GetDamage();
- int32 bp = absorbAmount;
+ int32 bp = dmgInfo.GetDamage();
+ dmgInfo.AbsorbDamage(bp);
target->CastCustomSpell(target, SPELL_MAGE_FROST_WARDING_TRIGGERED, &bp, NULL, NULL, true, NULL, aurEff);
+ absorbAmount = 0;
+ PreventDefaultAction();
}
}
}
diff --git a/src/server/scripts/Spells/spell_paladin.cpp b/src/server/scripts/Spells/spell_paladin.cpp
index d823c629d4b..9f7f7d847e1 100644
--- a/src/server/scripts/Spells/spell_paladin.cpp
+++ b/src/server/scripts/Spells/spell_paladin.cpp
@@ -285,9 +285,20 @@ class spell_pal_holy_shock : public SpellScriptLoader
}
}
+ SpellCastResult CheckCast()
+ {
+ Player* caster = GetCaster()->ToPlayer();
+ if (GetTargetUnit())
+ if (Player* target = GetTargetUnit()->ToPlayer())
+ if (caster->GetTeam() != target->GetTeam() && !caster->IsValidAttackTarget(target))
+ return SPELL_FAILED_BAD_TARGETS;
+ return SPELL_CAST_OK;
+ }
+
void Register()
{
// add dummy effect spell handler to Holy Shock
+ OnCheckCast += SpellCheckCastFn(spell_pal_holy_shock_SpellScript::CheckCast);
OnEffectHitTarget += SpellEffectFn(spell_pal_holy_shock_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
diff --git a/src/server/scripts/Spells/spell_quest.cpp b/src/server/scripts/Spells/spell_quest.cpp
index 278abcc0c0b..48faf83cd2f 100644
--- a/src/server/scripts/Spells/spell_quest.cpp
+++ b/src/server/scripts/Spells/spell_quest.cpp
@@ -636,6 +636,10 @@ class spell_q12851_going_bearback : public SpellScriptLoader
if (Unit* caster = GetCaster())
{
Unit* target = GetTarget();
+ // Already in fire
+ if (target->HasAura(SPELL_ABLAZE))
+ return;
+
if (Player* player = caster->GetCharmerOrOwnerPlayerOrPlayerItself())
{
switch (target->GetEntry())
diff --git a/src/server/scripts/Spells/spell_shaman.cpp b/src/server/scripts/Spells/spell_shaman.cpp
index 96ee7a18429..f16f663ae2d 100644
--- a/src/server/scripts/Spells/spell_shaman.cpp
+++ b/src/server/scripts/Spells/spell_shaman.cpp
@@ -35,6 +35,9 @@ enum ShamanSpells
SHAMAN_SPELL_FIRE_NOVA_TRIGGERED_R1 = 8349,
SHAMAN_SPELL_SATED = 57724,
SHAMAN_SPELL_EXHAUSTION = 57723,
+
+ SHAMAN_SPELL_STORM_EARTH_AND_FIRE = 51483,
+ EARTHBIND_TOTEM_SPELL_EARTHGRAB = 64695,
// For Earthen Power
SHAMAN_TOTEM_SPELL_EARTHBIND_TOTEM = 6474,
@@ -212,18 +215,33 @@ class spell_sha_earthbind_totem : public SpellScriptLoader
void HandleEffectPeriodic(AuraEffect const* aurEff)
{
- if (Unit* target = GetTarget())
- if (Unit* caster = aurEff->GetBase()->GetCaster())
- if (TempSummon* summon = caster->ToTempSummon())
- if (Unit* owner = summon->GetOwner())
- if (AuraEffect* aur = owner->GetDummyAuraEffect(SPELLFAMILY_SHAMAN, 2289, 0))
- if (roll_chance_i(aur->GetBaseAmount()) && target->HasAuraWithMechanic(1 << MECHANIC_SNARE))
- caster->CastSpell(caster, SHAMAN_TOTEM_SPELL_EARTHEN_POWER, true, NULL, aurEff);
+ if (!GetCaster())
+ return;
+ if (Player* owner = GetCaster()->GetCharmerOrOwnerPlayerOrPlayerItself())
+ if (AuraEffect* aur = owner->GetDummyAuraEffect(SPELLFAMILY_SHAMAN, 2289, 0))
+ if (roll_chance_i(aur->GetBaseAmount()))
+ GetTarget()->CastSpell((Unit*)NULL, SHAMAN_TOTEM_SPELL_EARTHEN_POWER, true);
+ }
+
+ void Apply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ if (!GetCaster())
+ return;
+ Player* owner = GetCaster()->GetCharmerOrOwnerPlayerOrPlayerItself();
+ if (!owner)
+ return;
+ // Storm, Earth and Fire
+ if (AuraEffect* aurEff = owner->GetAuraEffectOfRankedSpell(SHAMAN_SPELL_STORM_EARTH_AND_FIRE, EFFECT_1))
+ {
+ if (roll_chance_i(aurEff->GetAmount()))
+ GetCaster()->CastSpell(GetCaster(), EARTHBIND_TOTEM_SPELL_EARTHGRAB, false);
+ }
}
void Register()
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_sha_earthbind_totem_AuraScript::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
+ OnEffectApply += AuraEffectApplyFn(spell_sha_earthbind_totem_AuraScript::Apply, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL);
}
};
@@ -233,6 +251,46 @@ class spell_sha_earthbind_totem : public SpellScriptLoader
}
};
+class EarthenPowerTargetSelector
+{
+ public:
+ EarthenPowerTargetSelector() { }
+
+ bool operator() (Unit* target)
+ {
+ if (!target->HasAuraWithMechanic(1 << MECHANIC_SNARE))
+ return true;
+
+ return false;
+ }
+};
+
+class spell_sha_earthen_power : public SpellScriptLoader
+{
+ public:
+ spell_sha_earthen_power() : SpellScriptLoader("spell_sha_earthen_power") { }
+
+ class spell_sha_earthen_power_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_sha_earthen_power_SpellScript);
+
+ void FilterTargets(std::list<Unit*>& unitList)
+ {
+ unitList.remove_if(EarthenPowerTargetSelector());
+ }
+
+ void Register()
+ {
+ OnUnitTargetSelect += SpellUnitTargetFn(spell_sha_earthen_power_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_sha_earthen_power_SpellScript();
+ }
+};
+
class spell_sha_bloodlust : public SpellScriptLoader
{
public:
@@ -251,7 +309,7 @@ class spell_sha_bloodlust : public SpellScriptLoader
void RemoveInvalidTargets(std::list<Unit*>& targets)
{
- targets.remove_if (Trinity::UnitAuraCheck(true, SHAMAN_SPELL_SATED));
+ targets.remove_if(Trinity::UnitAuraCheck(true, SHAMAN_SPELL_SATED));
}
void ApplyDebuff()
@@ -542,6 +600,55 @@ class spell_sha_lava_lash : public SpellScriptLoader
}
};
+// 1064 Chain Heal
+class spell_sha_chain_heal : public SpellScriptLoader
+{
+ public:
+ spell_sha_chain_heal() : SpellScriptLoader("spell_sha_chain_heal") { }
+
+ class spell_sha_chain_heal_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_sha_chain_heal_SpellScript);
+
+ bool Load()
+ {
+ firstHeal = true;
+ riptide = false;
+ return true;
+ }
+
+ void HandleHeal(SpellEffIndex /*effIndex*/)
+ {
+ if (firstHeal)
+ {
+ // Check if the target has Riptide
+ if (AuraEffect* aurEff = GetHitUnit()->GetAuraEffect(SPELL_AURA_PERIODIC_HEAL, SPELLFAMILY_SHAMAN, 0, 0, 0x10, GetCaster()->GetGUID()))
+ {
+ riptide = true;
+ // Consume it
+ GetHitUnit()->RemoveAura(aurEff->GetBase());
+ }
+ firstHeal = false;
+ }
+ // Riptide increases the Chain Heal effect by 25%
+ if (riptide)
+ SetHitHeal(GetHitHeal() * 1.25f);
+ }
+
+ void Register()
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_sha_chain_heal_SpellScript::HandleHeal, EFFECT_0, SPELL_EFFECT_HEAL);
+ }
+
+ bool firstHeal;
+ bool riptide;
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_sha_chain_heal_SpellScript();
+ }
+};
void AddSC_shaman_spell_scripts()
{
@@ -549,6 +656,7 @@ void AddSC_shaman_spell_scripts()
new spell_sha_fire_nova();
new spell_sha_mana_tide_totem();
new spell_sha_earthbind_totem();
+ new spell_sha_earthen_power();
new spell_sha_bloodlust();
new spell_sha_heroism();
new spell_sha_ancestral_awakening_proc();
@@ -556,4 +664,5 @@ void AddSC_shaman_spell_scripts()
new spell_sha_healing_stream_totem();
new spell_sha_mana_spring_totem();
new spell_sha_lava_lash();
+ new spell_sha_chain_heal();
}
diff --git a/src/server/scripts/Spells/spell_warlock.cpp b/src/server/scripts/Spells/spell_warlock.cpp
index 29a52406279..1f7e8171e46 100644
--- a/src/server/scripts/Spells/spell_warlock.cpp
+++ b/src/server/scripts/Spells/spell_warlock.cpp
@@ -172,6 +172,19 @@ class spell_warl_create_healthstone : public SpellScriptLoader
return true;
}
+ SpellCastResult CheckCast()
+ {
+ if (Player* caster = GetCaster()->ToPlayer())
+ {
+ uint8 spellRank = sSpellMgr->GetSpellRank(GetSpellInfo()->Id);
+ ItemPosCountVec dest;
+ InventoryResult msg = caster->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, iTypes[spellRank - 1][0], 1, NULL);
+ if (msg != EQUIP_ERR_OK)
+ return SPELL_FAILED_TOO_MANY_OF_ITEM;
+ }
+ return SPELL_CAST_OK;
+ }
+
void HandleScriptEffect(SpellEffIndex effIndex)
{
if (Unit* unitTarget = GetHitUnit())
@@ -198,6 +211,7 @@ class spell_warl_create_healthstone : public SpellScriptLoader
void Register()
{
OnEffectHitTarget += SpellEffectFn(spell_warl_create_healthstone_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ OnCheckCast += SpellCheckCastFn(spell_warl_create_healthstone_SpellScript::CheckCast);
}
};
diff --git a/src/server/scripts/Spells/spell_warrior.cpp b/src/server/scripts/Spells/spell_warrior.cpp
index 1084398c37d..3e4c043ae47 100644
--- a/src/server/scripts/Spells/spell_warrior.cpp
+++ b/src/server/scripts/Spells/spell_warrior.cpp
@@ -365,7 +365,7 @@ class spell_warr_concussion_blow : public SpellScriptLoader
void HandleDummy(SpellEffIndex /* effIndex */)
{
- SetHitDamage(GetHitDamage() + CalculatePctF(GetHitDamage(),GetCaster()->GetTotalAttackPowerValue(BASE_ATTACK)));
+ SetHitDamage(CalculatePctN(GetCaster()->GetTotalAttackPowerValue(BASE_ATTACK), GetEffectValue()));
}
void Register()
@@ -413,6 +413,51 @@ class spell_warr_bloodthirst : public SpellScriptLoader
}
};
+enum Overpower
+{
+ SPELL_UNRELENTING_ASSAULT_RANK_1 = 46859,
+ SPELL_UNRELENTING_ASSAULT_RANK_2 = 46860,
+ SPELL_UNRELENTING_ASSAULT_TRIGGER_1 = 64849,
+ SPELL_UNRELENTING_ASSAULT_TRIGGER_2 = 64850,
+};
+
+class spell_warr_overpower : public SpellScriptLoader
+{
+public:
+ spell_warr_overpower() : SpellScriptLoader("spell_warr_overpower") { }
+
+ class spell_warr_overpower_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_warr_overpower_SpellScript);
+
+ void HandleEffect(SpellEffIndex /* effIndex */)
+ {
+ uint32 spellId = 0;
+ if (GetCaster()->HasAura(SPELL_UNRELENTING_ASSAULT_RANK_1))
+ spellId = SPELL_UNRELENTING_ASSAULT_TRIGGER_1;
+ else if (GetCaster()->HasAura(SPELL_UNRELENTING_ASSAULT_RANK_2))
+ spellId = SPELL_UNRELENTING_ASSAULT_TRIGGER_2;
+
+ if (!spellId)
+ return;
+
+ if (Player* target = GetHitPlayer())
+ if (target->HasUnitState(UNIT_STATE_CASTING))
+ target->CastSpell(target, spellId, true);
+ }
+
+ void Register()
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_warr_overpower_SpellScript::HandleEffect, EFFECT_0, SPELL_EFFECT_ANY);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_warr_overpower_SpellScript();
+ }
+};
+
void AddSC_warrior_spell_scripts()
{
new spell_warr_last_stand();
@@ -424,4 +469,5 @@ void AddSC_warrior_spell_scripts()
new spell_warr_execute();
new spell_warr_concussion_blow();
new spell_warr_bloodthirst();
+ new spell_warr_overpower();
}
diff --git a/src/server/scripts/World/npcs_special.cpp b/src/server/scripts/World/npcs_special.cpp
index 6858827ed8e..e1cfd077444 100644
--- a/src/server/scripts/World/npcs_special.cpp
+++ b/src/server/scripts/World/npcs_special.cpp
@@ -2400,6 +2400,9 @@ enum eLockSmith
QUEST_HOTTER_THAN_HELL_H = 10764,
QUEST_RETURN_TO_KHAGDAR = 9837,
QUEST_CONTAINMENT = 13159,
+ QUEST_ETERNAL_VIGILANCE = 11011,
+ QUEST_KEY_TO_THE_FOCUSING_IRIS = 13372,
+ QUEST_HC_KEY_TO_THE_FOCUSING_IRIS = 13375,
ITEM_ARCATRAZ_KEY = 31084,
ITEM_SHADOWFORGE_KEY = 11000,
@@ -2407,21 +2410,28 @@ enum eLockSmith
ITEM_SHATTERED_HALLS_KEY = 28395,
ITEM_THE_MASTERS_KEY = 24490,
ITEM_VIOLET_HOLD_KEY = 42482,
+ ITEM_ESSENCE_INFUSED_MOONSTONE = 32449,
+ ITEM_KEY_TO_THE_FOCUSING_IRIS = 44582,
+ ITEM_HC_KEY_TO_THE_FOCUSING_IRIS = 44581,
SPELL_ARCATRAZ_KEY = 54881,
SPELL_SHADOWFORGE_KEY = 54882,
SPELL_SKELETON_KEY = 54883,
SPELL_SHATTERED_HALLS_KEY = 54884,
SPELL_THE_MASTERS_KEY = 54885,
- SPELL_VIOLET_HOLD_KEY = 67253
+ SPELL_VIOLET_HOLD_KEY = 67253,
+ SPELL_ESSENCE_INFUSED_MOONSTONE = 40173,
};
-#define GOSSIP_LOST_ARCATRAZ_KEY "I've lost my key to the Arcatraz."
-#define GOSSIP_LOST_SHADOWFORGE_KEY "I've lost my key to the Blackrock Depths."
-#define GOSSIP_LOST_SKELETON_KEY "I've lost my key to the Scholomance."
-#define GOSSIP_LOST_SHATTERED_HALLS_KEY "I've lost my key to the Shattered Halls."
-#define GOSSIP_LOST_THE_MASTERS_KEY "I've lost my key to the Karazhan."
-#define GOSSIP_LOST_VIOLET_HOLD_KEY "I've lost my key to the Violet Hold."
+#define GOSSIP_LOST_ARCATRAZ_KEY "I've lost my key to the Arcatraz."
+#define GOSSIP_LOST_SHADOWFORGE_KEY "I've lost my key to the Blackrock Depths."
+#define GOSSIP_LOST_SKELETON_KEY "I've lost my key to the Scholomance."
+#define GOSSIP_LOST_SHATTERED_HALLS_KEY "I've lost my key to the Shattered Halls."
+#define GOSSIP_LOST_THE_MASTERS_KEY "I've lost my key to the Karazhan."
+#define GOSSIP_LOST_VIOLET_HOLD_KEY "I've lost my key to the Violet Hold."
+#define GOSSIP_LOST_ESSENCE_INFUSED_MOONSTONE "I've lost my Essence-Infused Moonstone."
+#define GOSSIP_LOST_KEY_TO_THE_FOCUSING_IRIS "I've lost my Key to the Focusing Iris."
+#define GOSSIP_LOST_HC_KEY_TO_THE_FOCUSING_IRIS "I've lost my Heroic Key to the Focusing Iris."
class npc_locksmith : public CreatureScript
{
@@ -2456,6 +2466,18 @@ public:
if (player->GetQuestRewardStatus(QUEST_CONTAINMENT) && !player->HasItemCount(ITEM_VIOLET_HOLD_KEY, 1, true))
player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_VIOLET_HOLD_KEY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6);
+ // Essence-Infused Moonstone
+ if (player->GetQuestRewardStatus(QUEST_ETERNAL_VIGILANCE) && !player->HasItemCount(ITEM_ESSENCE_INFUSED_MOONSTONE, 1, true))
+ player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_ESSENCE_INFUSED_MOONSTONE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 7);
+
+ // Key to the Focusing Iris
+ if (player->GetQuestRewardStatus(QUEST_KEY_TO_THE_FOCUSING_IRIS) && !player->HasItemCount(ITEM_KEY_TO_THE_FOCUSING_IRIS, 1, true))
+ player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_KEY_TO_THE_FOCUSING_IRIS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 8);
+
+ // Heroic Key to the Focusing Iris
+ if (player->GetQuestRewardStatus(QUEST_HC_KEY_TO_THE_FOCUSING_IRIS) && !player->HasItemCount(ITEM_HC_KEY_TO_THE_FOCUSING_IRIS, 1, true))
+ player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_HC_KEY_TO_THE_FOCUSING_IRIS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 9);
+
player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID());
return true;
@@ -2490,171 +2512,17 @@ public:
player->CLOSE_GOSSIP_MENU();
player->CastSpell(player, SPELL_VIOLET_HOLD_KEY, false);
break;
- }
- return true;
- }
-};
-
-/*######
-## npc_tabard_vendor
-######*/
-
-enum
-{
- QUEST_TRUE_MASTERS_OF_LIGHT = 9737,
- QUEST_THE_UNWRITTEN_PROPHECY = 9762,
- QUEST_INTO_THE_BREACH = 10259,
- QUEST_BATTLE_OF_THE_CRIMSON_WATCH = 10781,
- QUEST_SHARDS_OF_AHUNE = 11972,
-
- ACHIEVEMENT_EXPLORE_NORTHREND = 45,
- ACHIEVEMENT_TWENTYFIVE_TABARDS = 1021,
- ACHIEVEMENT_THE_LOREMASTER_A = 1681,
- ACHIEVEMENT_THE_LOREMASTER_H = 1682,
-
- ITEM_TABARD_OF_THE_HAND = 24344,
- ITEM_TABARD_OF_THE_BLOOD_KNIGHT = 25549,
- ITEM_TABARD_OF_THE_PROTECTOR = 28788,
- ITEM_OFFERING_OF_THE_SHATAR = 31408,
- ITEM_GREEN_TROPHY_TABARD_OF_THE_ILLIDARI = 31404,
- ITEM_PURPLE_TROPHY_TABARD_OF_THE_ILLIDARI = 31405,
- ITEM_TABARD_OF_THE_SUMMER_SKIES = 35279,
- ITEM_TABARD_OF_THE_SUMMER_FLAMES = 35280,
- ITEM_TABARD_OF_THE_ACHIEVER = 40643,
- ITEM_LOREMASTERS_COLORS = 43300,
- ITEM_TABARD_OF_THE_EXPLORER = 43348,
-
- SPELL_TABARD_OF_THE_BLOOD_KNIGHT = 54974,
- SPELL_TABARD_OF_THE_HAND = 54976,
- SPELL_GREEN_TROPHY_TABARD_OF_THE_ILLIDARI = 54977,
- SPELL_PURPLE_TROPHY_TABARD_OF_THE_ILLIDARI = 54982,
- SPELL_TABARD_OF_THE_ACHIEVER = 55006,
- SPELL_TABARD_OF_THE_PROTECTOR = 55008,
- SPELL_LOREMASTERS_COLORS = 58194,
- SPELL_TABARD_OF_THE_EXPLORER = 58224,
- SPELL_TABARD_OF_SUMMER_SKIES = 62768,
- SPELL_TABARD_OF_SUMMER_FLAMES = 62769
-};
-
-#define GOSSIP_LOST_TABARD_OF_BLOOD_KNIGHT "I've lost my Tabard of Blood Knight."
-#define GOSSIP_LOST_TABARD_OF_THE_HAND "I've lost my Tabard of the Hand."
-#define GOSSIP_LOST_TABARD_OF_THE_PROTECTOR "I've lost my Tabard of the Protector."
-#define GOSSIP_LOST_GREEN_TROPHY_TABARD_OF_THE_ILLIDARI "I've lost my Green Trophy Tabard of the Illidari."
-#define GOSSIP_LOST_PURPLE_TROPHY_TABARD_OF_THE_ILLIDARI "I've lost my Purple Trophy Tabard of the Illidari."
-#define GOSSIP_LOST_TABARD_OF_SUMMER_SKIES "I've lost my Tabard of Summer Skies."
-#define GOSSIP_LOST_TABARD_OF_SUMMER_FLAMES "I've lost my Tabard of Summer Flames."
-#define GOSSIP_LOST_LOREMASTERS_COLORS "I've lost my Loremaster's Colors."
-#define GOSSIP_LOST_TABARD_OF_THE_EXPLORER "I've lost my Tabard of the Explorer."
-#define GOSSIP_LOST_TABARD_OF_THE_ACHIEVER "I've lost my Tabard of the Achiever."
-
-class npc_tabard_vendor : public CreatureScript
-{
-public:
- npc_tabard_vendor() : CreatureScript("npc_tabard_vendor") { }
-
- bool OnGossipHello(Player* player, Creature* creature)
- {
- bool lostBloodKnight = false;
- bool lostHand = false;
- bool lostProtector = false;
- bool lostIllidari = false;
- bool lostSummer = false;
-
- //Tabard of the Blood Knight
- if (player->GetQuestRewardStatus(QUEST_TRUE_MASTERS_OF_LIGHT) && !player->HasItemCount(ITEM_TABARD_OF_THE_BLOOD_KNIGHT, 1, true))
- lostBloodKnight = true;
-
- //Tabard of the Hand
- if (player->GetQuestRewardStatus(QUEST_THE_UNWRITTEN_PROPHECY) && !player->HasItemCount(ITEM_TABARD_OF_THE_HAND, 1, true))
- lostHand = true;
-
- //Tabard of the Protector
- if (player->GetQuestRewardStatus(QUEST_INTO_THE_BREACH) && !player->HasItemCount(ITEM_TABARD_OF_THE_PROTECTOR, 1, true))
- lostProtector = true;
-
- //Green Trophy Tabard of the Illidari
- //Purple Trophy Tabard of the Illidari
- if (player->GetQuestRewardStatus(QUEST_BATTLE_OF_THE_CRIMSON_WATCH) &&
- (!player->HasItemCount(ITEM_GREEN_TROPHY_TABARD_OF_THE_ILLIDARI, 1, true) &&
- !player->HasItemCount(ITEM_PURPLE_TROPHY_TABARD_OF_THE_ILLIDARI, 1, true) &&
- !player->HasItemCount(ITEM_OFFERING_OF_THE_SHATAR, 1, true)))
- lostIllidari = true;
-
- //Tabard of Summer Skies
- //Tabard of Summer Flames
- if (player->GetQuestRewardStatus(QUEST_SHARDS_OF_AHUNE) &&
- !player->HasItemCount(ITEM_TABARD_OF_THE_SUMMER_SKIES, 1, true) &&
- !player->HasItemCount(ITEM_TABARD_OF_THE_SUMMER_FLAMES, 1, true))
- lostSummer = true;
-
- if (lostBloodKnight || lostHand || lostProtector || lostIllidari || lostSummer)
- {
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE);
-
- if (lostBloodKnight)
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_TABARD_OF_BLOOD_KNIGHT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
-
- if (lostHand)
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_TABARD_OF_THE_HAND, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
-
- if (lostProtector)
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_TABARD_OF_THE_PROTECTOR, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
-
- if (lostIllidari)
- {
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_GREEN_TROPHY_TABARD_OF_THE_ILLIDARI, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4);
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_PURPLE_TROPHY_TABARD_OF_THE_ILLIDARI, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5);
- }
-
- if (lostSummer)
- {
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_TABARD_OF_SUMMER_SKIES, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6);
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_TABARD_OF_SUMMER_FLAMES, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 7);
- }
-
- player->SEND_GOSSIP_MENU(13583, creature->GetGUID());
- }
- else
- player->GetSession()->SendListInventory(creature->GetGUID());
-
- return true;
- }
-
- bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action)
- {
- player->PlayerTalkClass->ClearMenus();
- switch (action)
- {
- case GOSSIP_ACTION_TRADE:
- player->GetSession()->SendListInventory(creature->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF + 1:
- player->CLOSE_GOSSIP_MENU();
- player->CastSpell(player, SPELL_TABARD_OF_THE_BLOOD_KNIGHT, false);
- break;
- case GOSSIP_ACTION_INFO_DEF + 2:
- player->CLOSE_GOSSIP_MENU();
- player->CastSpell(player, SPELL_TABARD_OF_THE_HAND, false);
- break;
- case GOSSIP_ACTION_INFO_DEF + 3:
- player->CLOSE_GOSSIP_MENU();
- player->CastSpell(player, SPELL_TABARD_OF_THE_PROTECTOR, false);
- break;
- case GOSSIP_ACTION_INFO_DEF + 4:
- player->CLOSE_GOSSIP_MENU();
- player->CastSpell(player, SPELL_GREEN_TROPHY_TABARD_OF_THE_ILLIDARI, false);
- break;
- case GOSSIP_ACTION_INFO_DEF + 5:
+ case GOSSIP_ACTION_INFO_DEF + 7:
player->CLOSE_GOSSIP_MENU();
- player->CastSpell(player, SPELL_PURPLE_TROPHY_TABARD_OF_THE_ILLIDARI, false);
+ player->CastSpell(player, SPELL_ESSENCE_INFUSED_MOONSTONE, false);
break;
- case GOSSIP_ACTION_INFO_DEF + 6:
+ case GOSSIP_ACTION_INFO_DEF + 8:
player->CLOSE_GOSSIP_MENU();
- player->CastSpell(player, SPELL_TABARD_OF_SUMMER_SKIES, false);
+ player->AddItem(ITEM_KEY_TO_THE_FOCUSING_IRIS,1);
break;
- case GOSSIP_ACTION_INFO_DEF + 7:
+ case GOSSIP_ACTION_INFO_DEF + 9:
player->CLOSE_GOSSIP_MENU();
- player->CastSpell(player, SPELL_TABARD_OF_SUMMER_FLAMES, false);
+ player->AddItem(ITEM_HC_KEY_TO_THE_FOCUSING_IRIS,1);
break;
}
return true;
@@ -3124,7 +2992,6 @@ void AddSC_npcs_special()
new npc_wormhole();
new npc_pet_trainer();
new npc_locksmith();
- new npc_tabard_vendor();
new npc_experience();
new npc_fire_elemental();
new npc_earth_elemental();
diff --git a/src/server/shared/CMakeLists.txt b/src/server/shared/CMakeLists.txt
index 3ec35b5394a..de998442419 100644
--- a/src/server/shared/CMakeLists.txt
+++ b/src/server/shared/CMakeLists.txt
@@ -53,7 +53,6 @@ set(shared_STAT_SRCS
include_directories(
${CMAKE_BINARY_DIR}
${CMAKE_SOURCE_DIR}/dep/SFMT
- ${CMAKE_SOURCE_DIR}/dep/mersennetwister
${CMAKE_SOURCE_DIR}/dep/sockets/include
${CMAKE_SOURCE_DIR}/dep/utf8cpp
${CMAKE_SOURCE_DIR}/src/server
diff --git a/src/server/shared/Containers.h b/src/server/shared/Containers.h
new file mode 100644
index 00000000000..f0242cbff0e
--- /dev/null
+++ b/src/server/shared/Containers.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TRINITY_CONTAINERS_H
+#define TRINITY_CONTAINERS_H
+
+#include <list>
+
+//! Because circular includes are bad
+extern uint32 urand(uint32 min, uint32 max);
+
+namespace Trinity
+{
+ namespace Containers
+ {
+ template<class T>
+ void RandomResizeList(std::list<T> &list, uint32 size)
+ {
+ size_t list_size = list.size();
+
+ while (list_size > size)
+ {
+ typename std::list<T>::iterator itr = list.begin();
+ std::advance(itr, urand(0, list_size - 1));
+ list.erase(itr);
+ --list_size;
+ }
+ }
+
+ template<class T, class Predicate>
+ void RandomResizeList(std::list<T> &list, Predicate& predicate, uint32 size)
+ {
+ //! First use predicate filter
+ std::list<T> listCopy;
+ for (typename std::list<T>::iterator itr = list.begin(); itr != list.end(); ++itr)
+ if (predicate(*itr))
+ listCopy.push_back(*itr);
+
+ if (size)
+ RandomResizeList(listCopy, size);
+
+ list = listCopy;
+ }
+
+ /* Select a random element from a container. Note: make sure you explicitly empty check the container */
+ template <class C> typename C::value_type const& SelectRandomContainerElement(C const& container)
+ {
+ typename C::const_iterator it = container.begin();
+ std::advance(it, urand(0, container.size() - 1));
+ return *it;
+ }
+ };
+ //! namespace Containers
+};
+//! namespace Trinity
+
+#endif //! #ifdef TRINITY_CONTAINERS_H \ No newline at end of file
diff --git a/src/server/shared/Database/DatabaseWorkerPool.h b/src/server/shared/Database/DatabaseWorkerPool.h
index 5fe31006bb2..314d196cc06 100755
--- a/src/server/shared/Database/DatabaseWorkerPool.h
+++ b/src/server/shared/Database/DatabaseWorkerPool.h
@@ -102,7 +102,7 @@ class DatabaseWorkerPool
//! Shuts down delaythreads for this connection pool by underlying deactivate().
//! The next dequeue attempt in the worker thread tasks will result in an error,
- //! ultimately ending the worker thread task.
+ //! ultimately ending the worker thread task.
_queue->queue()->close();
for (uint8 i = 0; i < _connectionCount[IDX_ASYNC]; ++i)
@@ -114,7 +114,7 @@ class DatabaseWorkerPool
t->Close(); //! Closes the actualy MySQL connection.
}
- sLog->outSQLDriver("Asynchronous connections on DatabasePool '%s' terminated. Proceeding with synchronous connections.",
+ sLog->outSQLDriver("Asynchronous connections on DatabasePool '%s' terminated. Proceeding with synchronous connections.",
GetDatabaseName());
//! Shut down the synchronous connections
@@ -239,7 +239,7 @@ class DatabaseWorkerPool
va_list ap;
char szQuery[MAX_QUERY_LEN];
- va_start(ap, sql);
+ va_start(ap, conn);
vsnprintf(szQuery, MAX_QUERY_LEN, sql, ap);
va_end(ap);
diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.cpp b/src/server/shared/Database/Implementation/CharacterDatabase.cpp
index 97207410159..772a52b62cf 100644
--- a/src/server/shared/Database/Implementation/CharacterDatabase.cpp
+++ b/src/server/shared/Database/Implementation/CharacterDatabase.cpp
@@ -27,9 +27,9 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PREPARE_STATEMENT(CHAR_DEL_NONEXISTENT_GUILD_BANK_ITEM, "DELETE FROM guild_bank_item WHERE guildid = ? AND TabId = ? AND SlotId = ?", CONNECTION_ASYNC)
PREPARE_STATEMENT(CHAR_DEL_EXPIRED_BANS, "UPDATE character_banned SET active = 0 WHERE unbandate <= UNIX_TIMESTAMP() AND unbandate <> bandate", CONNECTION_ASYNC)
PREPARE_STATEMENT(CHAR_SEL_GUID_BY_NAME, "SELECT guid FROM characters WHERE name = ?", CONNECTION_BOTH);
- PREPARE_STATEMENT(CHAR_SEL_CHECK_NAME, "SELECT 1 FROM characters WHERE name = ?", CONNECTION_ASYNC);
+ PREPARE_STATEMENT(CHAR_SEL_CHECK_NAME, "SELECT 1 FROM characters WHERE name = ?", CONNECTION_BOTH);
PREPARE_STATEMENT(CHAR_SEL_CHECK_GUID, "SELECT 1 FROM characters WHERE guid = ?", CONNECTION_SYNCH);
- PREPARE_STATEMENT(CHAR_SEL_SUM_CHARS, "SELECT COUNT(guid) FROM characters WHERE account = ?", CONNECTION_ASYNC);
+ PREPARE_STATEMENT(CHAR_SEL_SUM_CHARS, "SELECT COUNT(guid) FROM characters WHERE account = ?", CONNECTION_BOTH);
PREPARE_STATEMENT(CHAR_SEL_CHAR_CREATE_INFO, "SELECT level, race, class FROM characters WHERE account = ? LIMIT 0, ?", CONNECTION_ASYNC);
PREPARE_STATEMENT(CHAR_INS_CHARACTER_BAN, "INSERT INTO character_banned VALUES (?, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()+?, ?, ?, 1)", CONNECTION_ASYNC)
PREPARE_STATEMENT(CHAR_UPD_CHARACTER_BAN, "UPDATE character_banned SET active = 0 WHERE guid = ? AND active != 0", CONNECTION_ASYNC)
@@ -335,7 +335,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
// GM Survey/subsurvey/lag report
PREPARE_STATEMENT(CHAR_INS_GM_SURVEY, "INSERT INTO gm_surveys (guid, surveyId, mainSurvey, overallComment, createTime) VALUES (?, ?, ?, ?, UNIX_TIMESTAMP(NOW()))", CONNECTION_ASYNC)
PREPARE_STATEMENT(CHAR_INS_GM_SUBSURVEY, "INSERT INTO gm_subsurveys (surveyId, subsurveyId, rank, comment) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC)
- PREPARE_STATEMENT(CHAR_INS_LAG_REPORT, "INSERT INTO lag_reports (guid, lagType, mapId, posX, posY, posZ) VALUES (?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC)
+ PREPARE_STATEMENT(CHAR_INS_LAG_REPORT, "INSERT INTO lag_reports (guid, lagType, mapId, posX, posY, posZ, latency, createTime) VALUES (?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC)
// For loading and deleting expired auctions at startup
PREPARE_STATEMENT(CHAR_SEL_EXPIRED_AUCTIONS, "SELECT id, auctioneerguid, itemguid, itemEntry, itemowner, buyoutprice, time, buyguid, lastbid, startbid, deposit FROM auctionhouse ah INNER JOIN item_instance ii ON ii.guid = ah.itemguid WHERE ah.time <= ?", CONNECTION_SYNCH)
diff --git a/src/server/shared/Debugging/WheatyExceptionReport.cpp b/src/server/shared/Debugging/WheatyExceptionReport.cpp
index 63648f66e29..febc5ef3573 100644
--- a/src/server/shared/Debugging/WheatyExceptionReport.cpp
+++ b/src/server/shared/Debugging/WheatyExceptionReport.cpp
@@ -195,7 +195,23 @@ BOOL WheatyExceptionReport::_GetWindowsVersion(TCHAR* szVersion, DWORD cntMax)
case VER_PLATFORM_WIN32_NT:
// Test for the specific product family.
if (osvi.dwMajorVersion == 6)
- _tcsncat(szVersion, _T("Windows Vista or Windows Server 2008 "), cntMax);
+ {
+ #if WINVER < 0x0500
+ if (osvi.wReserved[1] == VER_NT_WORKSTATION)
+ #else
+ if (osvi.wProductType == VER_NT_WORKSTATION)
+ #endif // WINVER < 0x0500
+ {
+ if (osvi.dwMinorVersion == 1)
+ _tcsncat(szVersion, _T("Windows 7 "), cntMax);
+ else
+ _tcsncat(szVersion, _T("Windows Vista "), cntMax);
+ }
+ else if (osvi.dwMinorVersion == 1)
+ _tcsncat(szVersion, _T("Windows Server 2008 R2 "), cntMax);
+ else
+ _tcsncat(szVersion, _T("Windows Server 2008 "), cntMax);
+ }
if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2)
_tcsncat(szVersion, _T("Microsoft Windows Server 2003 "), cntMax);
if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
diff --git a/src/server/shared/Dynamic/TypeContainerFunctionsPtr.h b/src/server/shared/Dynamic/TypeContainerFunctionsPtr.h
deleted file mode 100755
index 2c065d96d4a..00000000000
--- a/src/server/shared/Dynamic/TypeContainerFunctionsPtr.h
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
- * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef TYPECONTAINER_FUNCTIONS_PTR_H
-#define TYPECONTAINER_FUNCTIONS_PTR_H
-
-/*
- * Here you'll find a list of helper functions to make
- * the TypeContainer usefull. Without it, its hard
- * to access or mutate the container.
- */
-
-#include "Platform/Define.h"
-#include "Utilities/TypeList.h"
-#include <map>
-
-namespace Trinity
-{
- /* ContainerMapList Helpers */
- // count functions
- // template<class SPECIFIC_TYPE> size_t Count(const ContainerMapList<SPECIFIC_TYPE> &elements, CountedPtr<SPECIFIC_TYPE>* /*fake*/)
- // {
- // return elements._element.size();
- // };
- //
- // template<class SPECIFIC_TYPE> size_t Count(const ContainerMapList<TypeNull> &elements, CountedPtr<SPECIFIC_TYPE>* /*fake*/)
- // {
- // return 0;
- // }
- //
- // template<class SPECIFIC_TYPE, class T> size_t Count(const ContainerMapList<T> &elements, CountedPtr<SPECIFIC_TYPE>* /*fake*/)
- // {
- // return 0;
- // }
- //
- // template<class SPECIFIC_TYPE, class T> size_t Count(const ContainerMapList<TypeList<SPECIFIC_TYPE, T> >&elements, SPECIFIC_TYPE* fake)
- // {
- // return Count(elements._elements, fake);
- // }
- //
- // template<class SPECIFIC_TYPE, class H, class T> size_t Count(const ContainerMapList<TypeList<H, T> >&elements, SPECIFIC_TYPE* fake)
- // {
- // return Count(elements._TailElements, fake);
- // }
-
- // non-const find functions
- template<class SPECIFIC_TYPE> CountedPtr<SPECIFIC_TYPE>& Find(ContainerMapList<SPECIFIC_TYPE> &elements, OBJECT_HANDLE hdl, CountedPtr<SPECIFIC_TYPE>* /*fake*/)
- {
- typename std::map<OBJECT_HANDLE, CountedPtr<SPECIFIC_TYPE> >::iterator iter = elements._element.find(hdl);
- return (iter == elements._element.end() ? NullPtr<SPECIFIC_TYPE>((SPECIFIC_TYPE*)NULL) : iter->second);
- };
-
- template<class SPECIFIC_TYPE> CountedPtr<SPECIFIC_TYPE>& Find(ContainerMapList<TypeNull> &elements, OBJECT_HANDLE hdl, CountedPtr<SPECIFIC_TYPE>* /*fake*/)
- {
- return NullPtr<SPECIFIC_TYPE>((SPECIFIC_TYPE*)NULL);// terminate recursion
- }
-
- template<class SPECIFIC_TYPE, class T> CountedPtr<SPECIFIC_TYPE>& Find(ContainerMapList<T> &elements, OBJECT_HANDLE hdl, CountedPtr<SPECIFIC_TYPE>* /*fake*/)
- {
- return NullPtr<SPECIFIC_TYPE>((SPECIFIC_TYPE*)NULL);// this is a missed
- }
-
- template<class SPECIFIC_TYPE, class H, class T> CountedPtr<SPECIFIC_TYPE>& Find(ContainerMapList<TypeList<H, T> >&elements, OBJECT_HANDLE hdl, CountedPtr<SPECIFIC_TYPE>* fake)
- {
- CountedPtr<SPECIFIC_TYPE> &t = Find(elements._elements, hdl, fake);
- return (!t ? Find(elements._TailElements, hdl, fake) : t);
- }
-
- // const find functions
- template<class SPECIFIC_TYPE> const CountedPtr<SPECIFIC_TYPE>& Find(const ContainerMapList<SPECIFIC_TYPE> &elements, OBJECT_HANDLE hdl, CountedPtr<SPECIFIC_TYPE>* /*fake*/)
- {
- typename CountedPtr<SPECIFIC_TYPE>::iterator iter = elements._element.find(hdl);
- return (iter == elements._element.end() ? NullPtr<SPECIFIC_TYPE>((SPECIFIC_TYPE*)NULL) : iter->second);
- };
-
- template<class SPECIFIC_TYPE> const CountedPtr<SPECIFIC_TYPE>& Find(const ContainerMapList<TypeNull> &elements, OBJECT_HANDLE hdl, CountedPtr<SPECIFIC_TYPE>* /*fake*/)
- {
- return NullPtr<SPECIFIC_TYPE>((SPECIFIC_TYPE*)NULL);
- }
-
- template<class SPECIFIC_TYPE, class T> const CountedPtr<SPECIFIC_TYPE>& Find(const ContainerMapList<T> &elements, OBJECT_HANDLE hdl, CountedPtr<SPECIFIC_TYPE>* /*fake*/)
- {
- return NullPtr<SPECIFIC_TYPE>((SPECIFIC_TYPE*)NULL);
- }
-
- template<class SPECIFIC_TYPE, class H, class T> CountedPtr<SPECIFIC_TYPE>& Find(const ContainerMapList<TypeList<H, T> >&elements, OBJECT_HANDLE hdl, CountedPtr<SPECIFIC_TYPE>* fake)
- {
- CountedPtr<SPECIFIC_TYPE> &t = Find(elements._elements, hdl, fake);
- if (!t)
- t = Find(elements._TailElement, hdl, fake);
-
- return t;
- }
-
- // non-const insert functions
- template<class SPECIFIC_TYPE> CountedPtr<SPECIFIC_TYPE>& Insert(ContainerMapList<SPECIFIC_TYPE> &elements, CountedPtr<SPECIFIC_TYPE> &obj, OBJECT_HANDLE hdl)
- {
- elements._element[hdl] = obj;
- return obj;
- };
-
- template<class SPECIFIC_TYPE> CountedPtr<SPECIFIC_TYPE>& Insert(ContainerMapList<TypeNull> &elements, CountedPtr<SPECIFIC_TYPE> &obj, OBJECT_HANDLE hdl)
- {
- return NullPtr<SPECIFIC_TYPE>((SPECIFIC_TYPE*)NULL);
- }
-
- // this is a missed
- template<class SPECIFIC_TYPE, class T> CountedPtr<SPECIFIC_TYPE>& Insert(ContainerMapList<T> &elements, CountedPtr<SPECIFIC_TYPE> &obj, OBJECT_HANDLE hdl)
- {
- return NullPtr<SPECIFIC_TYPE>((SPECIFIC_TYPE*)NULL);// a missed
- }
-
- // Recursion
- template<class SPECIFIC_TYPE, class H, class T> CountedPtr<SPECIFIC_TYPE>& Insert(ContainerMapList<TypeList<H, T> >&elements, CountedPtr<SPECIFIC_TYPE> &obj, OBJECT_HANDLE hdl)
- {
- CountedPtr<SPECIFIC_TYPE> &t= Insert(elements._elements, obj, hdl);
- return (!t ? Insert(elements._TailElements, obj, hdl) : t);
- }
-
- // non-const remove method
- template<class SPECIFIC_TYPE> bool Remove(ContainerMapList<SPECIFIC_TYPE> &elements, CountedPtr<SPECIFIC_TYPE> &obj, OBJECT_HANDLE hdl)
- {
- typename std::map<OBJECT_HANDLE, CountedPtr<SPECIFIC_TYPE> >::iterator iter = elements._element.find(hdl);
- if ( iter != elements._element.end() )
- {
- elements._element.erase(iter);
- return true;
- }
-
- return false; // found... terminate the search
- }
-
- template<class SPECIFIC_TYPE> bool Remove(ContainerMapList<TypeNull> &elements, CountedPtr<SPECIFIC_TYPE> &obj, OBJECT_HANDLE hdl)
- {
- return false;
- }
-
- // this is a missed
- template<class SPECIFIC_TYPE, class T> bool Remove(ContainerMapList<T> &elements, CountedPtr<SPECIFIC_TYPE> &obj, OBJECT_HANDLE hdl)
- {
- return false;
- }
-
- template<class SPECIFIC_TYPE, class T, class H> bool Remove(ContainerMapList<TypeList<H, T> > &elements, CountedPtr<SPECIFIC_TYPE> &obj, OBJECT_HANDLE hdl)
- {
- // The head element is bad
- bool t = Remove(elements._elements, obj, hdl);
- return ( !t ? Remove(elements._TailElements, obj, hdl) : t );
- }
-
-}
-#endif
-
diff --git a/src/server/shared/Utilities/Util.h b/src/server/shared/Utilities/Util.h
index 4c2c1936993..196882dc2a0 100755
--- a/src/server/shared/Utilities/Util.h
+++ b/src/server/shared/Utilities/Util.h
@@ -20,7 +20,7 @@
#define _UTIL_H
#include "Common.h"
-
+#include "Containers.h"
#include <string>
#include <vector>
@@ -73,7 +73,7 @@ inline uint32 secsToTimeBitFields(time_t secs)
double rand_norm(void);
/* Return a random double from 0.0 to 99.9999999999999. Floats support only 7 valid decimal digits.
- * A double supports up to 15 valid decimal digits and is used internaly (RAND32_MAX has 10 digits).
+ * A double supports up to 15 valid decimal digits and is used internally (RAND32_MAX has 10 digits).
* With an FPU, there is usually no difference in performance between float and double. */
double rand_chance(void);
@@ -653,12 +653,4 @@ public:
};
};
-/* Select a random element from a container. Note: make sure you explicitly empty check the container */
-template <class C> typename C::value_type const& SelectRandomContainerElement(C const& container)
-{
- typename C::const_iterator it = container.begin();
- std::advance(it, urand(0, container.size() - 1));
- return *it;
-}
-
#endif
diff --git a/src/server/worldserver/CMakeLists.txt b/src/server/worldserver/CMakeLists.txt
index d1419cb0fcb..0d51f30449e 100644
--- a/src/server/worldserver/CMakeLists.txt
+++ b/src/server/worldserver/CMakeLists.txt
@@ -48,7 +48,6 @@ include_directories(
${CMAKE_SOURCE_DIR}/dep/gsoap
${CMAKE_SOURCE_DIR}/dep/sockets/include
${CMAKE_SOURCE_DIR}/dep/SFMT
- ${CMAKE_SOURCE_DIR}/dep/mersennetwister
${CMAKE_SOURCE_DIR}/src/server/collision
${CMAKE_SOURCE_DIR}/src/server/collision/Management
${CMAKE_SOURCE_DIR}/src/server/collision/Models
diff --git a/src/tools/map_extractor/System.cpp b/src/tools/map_extractor/System.cpp
index bbde9f4675e..cf2f2188a70 100644
--- a/src/tools/map_extractor/System.cpp
+++ b/src/tools/map_extractor/System.cpp
@@ -71,7 +71,7 @@ float CONF_flat_height_delta_limit = 0.005f; // If max - min less this value - s
float CONF_flat_liquid_delta_limit = 0.001f; // If max - min less this value - liquid surface is flat
// List MPQ for extract from
-char *CONF_mpq_list[]={
+const char *CONF_mpq_list[]={
"common.MPQ",
"common-2.MPQ",
"lichking.MPQ",
@@ -83,7 +83,7 @@ char *CONF_mpq_list[]={
"patch-5.MPQ",
};
-static char* const langs[] = {"enGB", "enUS", "deDE", "esES", "frFR", "koKR", "zhCN", "zhTW", "enCN", "enTW", "esMX", "ruRU" };
+static const char* const langs[] = {"enGB", "enUS", "deDE", "esES", "frFR", "koKR", "zhCN", "zhTW", "enCN", "enTW", "esMX", "ruRU" };
#define LANG_COUNT 12
void CreateDir( const std::string& Path )