aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/authserver/Authentication/TOTP.h2
-rw-r--r--src/server/collision/Management/MMapManager.h1
-rw-r--r--src/server/collision/Models/GameObjectModel.cpp48
-rw-r--r--src/server/collision/Models/GameObjectModel.h6
-rw-r--r--src/server/game/AI/SmartScripts/SmartScript.cpp70
-rw-r--r--src/server/game/AI/SmartScripts/SmartScriptMgr.cpp50
-rw-r--r--src/server/game/AI/SmartScripts/SmartScriptMgr.h16
-rw-r--r--src/server/game/Battlegrounds/Battleground.cpp24
-rw-r--r--src/server/game/Battlegrounds/Battleground.h4
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp2
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp2
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp16
-rw-r--r--src/server/game/Conditions/ConditionMgr.cpp5
-rw-r--r--src/server/game/DataStores/DBCStores.cpp17
-rw-r--r--src/server/game/DataStores/DBCStores.h2
-rw-r--r--src/server/game/DataStores/DBCStructure.h18
-rw-r--r--src/server/game/DataStores/DBCfmt.h1
-rw-r--r--src/server/game/DungeonFinding/LFGMgr.cpp1
-rw-r--r--src/server/game/Entities/Creature/Creature.h8
-rw-r--r--src/server/game/Entities/Creature/GossipDef.cpp9
-rw-r--r--src/server/game/Entities/Creature/GossipDef.h9
-rw-r--r--src/server/game/Entities/DynamicObject/DynamicObject.cpp33
-rw-r--r--src/server/game/Entities/DynamicObject/DynamicObject.h4
-rw-r--r--src/server/game/Entities/GameObject/GameObject.cpp23
-rw-r--r--src/server/game/Entities/GameObject/GameObject.h2
-rw-r--r--src/server/game/Entities/Object/Object.cpp37
-rw-r--r--src/server/game/Entities/Pet/Pet.cpp3
-rw-r--r--src/server/game/Entities/Player/Player.cpp12
-rw-r--r--src/server/game/Entities/Transport/Transport.cpp152
-rw-r--r--src/server/game/Entities/Transport/Transport.h28
-rw-r--r--src/server/game/Entities/Unit/StatSystem.cpp4
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp15
-rw-r--r--src/server/game/Entities/Unit/Unit.h6
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp6
-rw-r--r--src/server/game/Handlers/AddonHandler.cpp2
-rw-r--r--src/server/game/Handlers/MiscHandler.cpp13
-rw-r--r--src/server/game/Maps/Map.cpp271
-rw-r--r--src/server/game/Maps/Map.h30
-rw-r--r--src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp4
-rw-r--r--src/server/game/Movement/Spline/MovementTypedefs.h6
-rw-r--r--src/server/game/Movement/Spline/Spline.h2
-rw-r--r--src/server/game/Scripting/ScriptLoader.cpp2
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp4
-rw-r--r--src/server/game/Spells/Spell.cpp62
-rw-r--r--src/server/game/Spells/Spell.h6
-rw-r--r--src/server/game/Spells/SpellEffects.cpp2
-rw-r--r--src/server/game/Spells/SpellMgr.cpp9
-rw-r--r--src/server/game/Spells/SpellMgr.h8
-rw-r--r--src/server/game/Spells/SpellScript.h1
-rw-r--r--src/server/game/Tickets/TicketMgr.cpp4
-rw-r--r--src/server/scripts/Commands/cs_misc.cpp4
-rw-r--r--src/server/scripts/EasternKingdoms/AlteracValley/boss_balinda.cpp7
-rw-r--r--src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_rend_blackhand.cpp7
-rw-r--r--src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/instance_blackwing_lair.cpp22
-rw-r--r--src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp11
-rw-r--r--src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp6
-rw-r--r--src/server/scripts/EasternKingdoms/Stratholme/instance_stratholme.cpp20
-rw-r--r--src/server/scripts/EasternKingdoms/ZulAman/boss_halazzi.cpp99
-rw-r--r--src/server/scripts/EasternKingdoms/ZulGurub/boss_jeklik.cpp2
-rw-r--r--src/server/scripts/EasternKingdoms/zone_blasted_lands.cpp33
-rw-r--r--src/server/scripts/EasternKingdoms/zone_westfall.cpp75
-rw-r--r--src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_anetheron.cpp2
-rw-r--r--src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_azgalor.cpp3
-rw-r--r--src/server/scripts/Kalimdor/RazorfenDowns/boss_glutton.cpp1
-rw-r--r--src/server/scripts/Kalimdor/RazorfenDowns/razorfen_downs.cpp2
-rw-r--r--src/server/scripts/Kalimdor/RazorfenKraul/razorfen_kraul.cpp6
-rw-r--r--src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_cthun.cpp14
-rw-r--r--src/server/scripts/Kalimdor/zone_mulgore.cpp37
-rw-r--r--src/server/scripts/Kalimdor/zone_silithus.cpp6
-rw-r--r--src/server/scripts/Kalimdor/zone_tanaris.cpp37
-rw-r--r--src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_prince_taldaram.cpp8
-rw-r--r--src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_krikthir_the_gatewatcher.cpp2
-rw-r--r--src/server/scripts/Northrend/CMakeLists.txt1
-rw-r--r--src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/obsidian_sanctum.cpp12
-rw-r--r--src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp2
-rw-r--r--src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp5
-rw-r--r--src/server/scripts/Northrend/Gundrak/boss_slad_ran.cpp15
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp2
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp24
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp2484
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp103
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h67
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel_teleport.cpp2
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp172
-rw-r--r--src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp33
-rw-r--r--src/server/scripts/Northrend/Nexus/Oculus/instance_oculus.cpp2
-rw-r--r--src/server/scripts/Northrend/zone_borean_tundra.cpp35
-rw-r--r--src/server/scripts/Northrend/zone_dragonblight.cpp1
-rw-r--r--src/server/scripts/Northrend/zone_storm_peaks.cpp36
-rw-r--r--src/server/scripts/Northrend/zone_zuldrak.cpp6
-rw-r--r--src/server/scripts/Outland/Auchindoun/AuchenaiCrypts/boss_exarch_maladaar.cpp6
-rw-r--r--src/server/scripts/Outland/BlackTemple/boss_reliquary_of_souls.cpp48
-rw-r--r--src/server/scripts/Outland/TempestKeep/Mechanar/boss_gatewatcher_ironhand.cpp6
-rw-r--r--src/server/scripts/Outland/TempestKeep/arcatraz/boss_dalliah_the_doomsayer.cpp7
-rw-r--r--src/server/scripts/Outland/TempestKeep/arcatraz/boss_wrath_scryer_soccothrates.cpp7
-rw-r--r--src/server/scripts/Outland/zone_blades_edge_mountains.cpp1
-rw-r--r--src/server/scripts/Outland/zone_netherstorm.cpp10
-rw-r--r--src/server/scripts/Spells/spell_dk.cpp4
-rw-r--r--src/server/scripts/Spells/spell_generic.cpp33
-rw-r--r--src/server/scripts/Spells/spell_mage.cpp4
-rw-r--r--src/server/scripts/Spells/spell_pet.cpp6
-rw-r--r--src/server/scripts/Spells/spell_priest.cpp2
-rw-r--r--src/server/scripts/Spells/spell_quest.cpp4
-rw-r--r--src/server/scripts/Spells/spell_rogue.cpp2
-rw-r--r--src/server/scripts/Spells/spell_warlock.cpp5
-rw-r--r--src/server/scripts/Spells/spell_warrior.cpp2
-rw-r--r--src/server/shared/Common.h10
-rw-r--r--src/server/shared/Database/AdhocStatement.cpp4
-rw-r--r--src/server/shared/Database/DatabaseWorkerPool.h3
-rw-r--r--src/server/shared/Database/QueryHolder.cpp3
-rw-r--r--src/server/shared/Dynamic/LinkedList.h15
-rw-r--r--src/server/shared/Dynamic/LinkedReference/Reference.h4
-rw-r--r--src/server/shared/Logging/AppenderFile.cpp2
-rw-r--r--src/tools/vmap4_extractor/mpq_libmpq04.h5
114 files changed, 4028 insertions, 633 deletions
diff --git a/src/server/authserver/Authentication/TOTP.h b/src/server/authserver/Authentication/TOTP.h
index 04b4a8c2110..7ced260758c 100644
--- a/src/server/authserver/Authentication/TOTP.h
+++ b/src/server/authserver/Authentication/TOTP.h
@@ -16,7 +16,7 @@
*/
#ifndef _TOTP_H
-#define _TOPT_H
+#define _TOTP_H
#include "openssl/hmac.h"
#include "openssl/evp.h"
diff --git a/src/server/collision/Management/MMapManager.h b/src/server/collision/Management/MMapManager.h
index 8b0d42b83cd..7840921e4e6 100644
--- a/src/server/collision/Management/MMapManager.h
+++ b/src/server/collision/Management/MMapManager.h
@@ -23,6 +23,7 @@
#include "DetourAlloc.h"
#include "DetourNavMesh.h"
#include "DetourNavMeshQuery.h"
+#include <string>
// move map related classes
namespace MMAP
diff --git a/src/server/collision/Models/GameObjectModel.cpp b/src/server/collision/Models/GameObjectModel.cpp
index d254a640279..42584693a13 100644
--- a/src/server/collision/Models/GameObjectModel.cpp
+++ b/src/server/collision/Models/GameObjectModel.cpp
@@ -130,17 +130,13 @@ bool GameObjectModel::initialize(const GameObject& go, const GameObjectDisplayIn
for (int i = 0; i < 8; ++i)
rotated_bounds.merge(iRotation * mdl_box.corner(i));
- this->iBound = rotated_bounds + iPos;
+ iBound = rotated_bounds + iPos;
#ifdef SPAWN_CORNERS
// test:
for (int i = 0; i < 8; ++i)
{
Vector3 pos(iBound.corner(i));
- if (Creature* c = const_cast<GameObject&>(go).SummonCreature(24440, pos.x, pos.y, pos.z, 0, TEMPSUMMON_MANUAL_DESPAWN))
- {
- c->setFaction(35);
- c->SetObjectScale(0.1f);
- }
+ go.SummonCreature(1, pos.x, pos.y, pos.z, 0, TEMPSUMMON_MANUAL_DESPAWN);
}
#endif
@@ -184,3 +180,43 @@ bool GameObjectModel::intersectRay(const G3D::Ray& ray, float& MaxDist, bool Sto
}
return hit;
}
+
+bool GameObjectModel::Relocate(const GameObject& go)
+{
+ if (!iModel)
+ return false;
+
+ ModelList::const_iterator it = model_list.find(go.GetDisplayId());
+ if (it == model_list.end())
+ return false;
+
+ G3D::AABox mdl_box(it->second.bound);
+ // ignore models with no bounds
+ if (mdl_box == G3D::AABox::zero())
+ {
+ VMAP_ERROR_LOG("misc", "GameObject model %s has zero bounds, loading skipped", it->second.name.c_str());
+ return false;
+ }
+
+ iPos = Vector3(go.GetPositionX(), go.GetPositionY(), go.GetPositionZ());
+
+ G3D::Matrix3 iRotation = G3D::Matrix3::fromEulerAnglesZYX(go.GetOrientation(), 0, 0);
+ iInvRot = iRotation.inverse();
+ // transform bounding box:
+ mdl_box = AABox(mdl_box.low() * iScale, mdl_box.high() * iScale);
+ AABox rotated_bounds;
+ for (int i = 0; i < 8; ++i)
+ rotated_bounds.merge(iRotation * mdl_box.corner(i));
+
+ iBound = rotated_bounds + iPos;
+#ifdef SPAWN_CORNERS
+ // test:
+ for (int i = 0; i < 8; ++i)
+ {
+ Vector3 pos(iBound.corner(i));
+ go.SummonCreature(1, pos.x, pos.y, pos.z, 0, TEMPSUMMON_MANUAL_DESPAWN);
+ }
+#endif
+
+ return true;
+}
diff --git a/src/server/collision/Models/GameObjectModel.h b/src/server/collision/Models/GameObjectModel.h
index 06a74cc6eb0..6088b924343 100644
--- a/src/server/collision/Models/GameObjectModel.h
+++ b/src/server/collision/Models/GameObjectModel.h
@@ -45,7 +45,7 @@ class GameObjectModel /*, public Intersectable*/
float iScale;
VMAP::WorldModel* iModel;
- GameObjectModel() : phasemask(0), iModel(NULL) { }
+ GameObjectModel() : phasemask(0), iInvScale(0), iScale(0), iModel(NULL) { }
bool initialize(const GameObject& go, const GameObjectDisplayInfoEntry& info);
public:
@@ -66,6 +66,8 @@ public:
bool intersectRay(const G3D::Ray& Ray, float& MaxDist, bool StopAtFirstHit, uint32 ph_mask) const;
static GameObjectModel* Create(const GameObject& go);
+
+ bool Relocate(GameObject const& go);
};
-#endif // _GAMEOBJECT_MODEL_H \ No newline at end of file
+#endif // _GAMEOBJECT_MODEL_H
diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp
index 49beb0ae86f..231f3808aa9 100644
--- a/src/server/game/AI/SmartScripts/SmartScript.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScript.cpp
@@ -512,7 +512,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
// unless target is outside spell range, out of mana, or LOS.
bool _allowMove = false;
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(e.action.cast.spell);
+ SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(e.action.cast.spell);
int32 mana = me->GetPower(POWER_MANA);
if (me->GetDistance(*itr) > spellInfo->GetMaxRange(true) ||
@@ -3118,6 +3118,68 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui
ProcessTimedAction(e, e.event.friendlyHealthPct.repeatMin, e.event.friendlyHealthPct.repeatMax, target);
break;
}
+ case SMART_EVENT_DISTANCE_CREATURE:
+ {
+ if (!me)
+ return;
+
+ WorldObject* creature = NULL;
+
+ if (e.event.distance.guid != 0)
+ {
+ creature = FindCreatureNear(me, e.event.distance.guid);
+
+ if (!creature)
+ return;
+
+ if (!me->IsInRange(creature, 0, (float)e.event.distance.dist))
+ return;
+ }
+ else if (e.event.distance.entry != 0)
+ {
+ std::list<Creature*> list;
+ me->GetCreatureListWithEntryInGrid(list, e.event.distance.entry, (float)e.event.distance.dist);
+
+ if (list.size() > 0)
+ creature = list.front();
+ }
+
+ if (creature)
+ ProcessTimedAction(e, e.event.distance.repeat, e.event.distance.repeat);
+
+ break;
+ }
+ case SMART_EVENT_DISTANCE_GAMEOBJECT:
+ {
+ if (!me)
+ return;
+
+ WorldObject* gameobject = NULL;
+
+ if (e.event.distance.guid != 0)
+ {
+ gameobject = FindGameObjectNear(me, e.event.distance.guid);
+
+ if (!gameobject)
+ return;
+
+ if (!me->IsInRange(gameobject, 0, (float)e.event.distance.dist))
+ return;
+ }
+ else if (e.event.distance.entry != 0)
+ {
+ std::list<GameObject*> list;
+ me->GetGameObjectListWithEntryInGrid(list, e.event.distance.entry, (float)e.event.distance.dist);
+
+ if (list.size() > 0)
+ gameobject = list.front();
+ }
+
+ if (gameobject)
+ ProcessTimedAction(e, e.event.distance.repeat, e.event.distance.repeat);
+
+ break;
+ }
default:
TC_LOG_ERROR("sql.sql", "SmartScript::ProcessEvent: Unhandled Event type %u", e.GetEventType());
break;
@@ -3138,6 +3200,10 @@ void SmartScript::InitTimer(SmartScriptHolder& e)
case SMART_EVENT_OOC_LOS:
RecalcTimer(e, e.event.los.cooldownMin, e.event.los.cooldownMax);
break;
+ case SMART_EVENT_DISTANCE_CREATURE:
+ case SMART_EVENT_DISTANCE_GAMEOBJECT:
+ RecalcTimer(e, e.event.distance.repeat, e.event.distance.repeat);
+ break;
default:
e.active = true;
break;
@@ -3198,6 +3264,8 @@ void SmartScript::UpdateTimer(SmartScriptHolder& e, uint32 const diff)
case SMART_EVENT_TARGET_BUFFED:
case SMART_EVENT_IS_BEHIND_TARGET:
case SMART_EVENT_FRIENDLY_HEALTH_PCT:
+ case SMART_EVENT_DISTANCE_CREATURE:
+ case SMART_EVENT_DISTANCE_GAMEOBJECT:
{
ProcessEvent(e);
if (e.GetScriptType() == SMART_SCRIPT_TYPE_TIMED_ACTIONLIST)
diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
index c6b73a468d2..93a9c6419b0 100644
--- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
@@ -583,6 +583,56 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
return false;
}
break;
+ case SMART_EVENT_DISTANCE_CREATURE:
+ if (e.event.distance.guid == 0 && e.event.distance.entry == 0)
+ {
+ TC_LOG_ERROR("sql.sql", "SmartAIMgr: Event SMART_EVENT_DISTANCE_CREATURE did not provide creature guid or entry, skipped.");
+ return false;
+ }
+
+ if (e.event.distance.guid != 0 && e.event.distance.entry != 0)
+ {
+ TC_LOG_ERROR("sql.sql", "SmartAIMgr: Event SMART_EVENT_DISTANCE_CREATURE provided both an entry and guid, skipped.");
+ return false;
+ }
+
+ if (e.event.distance.guid != 0 && !sObjectMgr->GetCreatureData(e.event.distance.guid))
+ {
+ TC_LOG_ERROR("sql.sql", "SmartAIMgr: Event SMART_EVENT_DISTANCE_CREATURE using invalid creature guid %u, skipped.", e.event.distance.guid);
+ return false;
+ }
+
+ if (e.event.distance.entry != 0 && !sObjectMgr->GetCreatureTemplate(e.event.distance.entry))
+ {
+ TC_LOG_ERROR("sql.sql", "SmartAIMgr: Event SMART_EVENT_DISTANCE_CREATURE using invalid creature entry %u, skipped.", e.event.distance.entry);
+ return false;
+ }
+ break;
+ case SMART_EVENT_DISTANCE_GAMEOBJECT:
+ if (e.event.distance.guid == 0 && e.event.distance.entry == 0)
+ {
+ TC_LOG_ERROR("sql.sql", "SmartAIMgr: Event SMART_EVENT_DISTANCE_GAMEOBJECT did not provide gameobject guid or entry, skipped.");
+ return false;
+ }
+
+ if (e.event.distance.guid != 0 && e.event.distance.entry != 0)
+ {
+ TC_LOG_ERROR("sql.sql", "SmartAIMgr: Event SMART_EVENT_DISTANCE_GAMEOBJECT provided both an entry and guid, skipped.");
+ return false;
+ }
+
+ if (e.event.distance.guid != 0 && !sObjectMgr->GetGOData(e.event.distance.guid))
+ {
+ TC_LOG_ERROR("sql.sql", "SmartAIMgr: Event SMART_EVENT_DISTANCE_GAMEOBJECT using invalid gameobject guid %u, skipped.", e.event.distance.guid);
+ return false;
+ }
+
+ if (e.event.distance.entry != 0 && !sObjectMgr->GetGameObjectTemplate(e.event.distance.entry))
+ {
+ TC_LOG_ERROR("sql.sql", "SmartAIMgr: Event SMART_EVENT_DISTANCE_GAMEOBJECT using invalid gameobject entry %u, skipped.", e.event.distance.entry);
+ return false;
+ }
+ break;
case SMART_EVENT_GO_STATE_CHANGED:
case SMART_EVENT_GO_EVENT_INFORM:
case SMART_EVENT_TIMED_EVENT_TRIGGERED:
diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h
index 265df8e2ac4..ac67fac0bfd 100644
--- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h
+++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h
@@ -165,8 +165,10 @@ enum SMART_EVENT
SMART_EVENT_ACTION_DONE = 72, // eventId (SharedDefines.EventId)
SMART_EVENT_ON_SPELLCLICK = 73, // clicker (unit)
SMART_EVENT_FRIENDLY_HEALTH_PCT = 74, // minHpPct, maxHpPct, repeatMin, repeatMax
+ SMART_EVENT_DISTANCE_CREATURE = 75, // guid, entry, distance, repeat
+ SMART_EVENT_DISTANCE_GAMEOBJECT = 76, // guid, entry, distance, repeat
- SMART_EVENT_END = 75
+ SMART_EVENT_END = 77
};
struct SmartEvent
@@ -388,6 +390,14 @@ struct SmartEvent
struct
{
+ uint32 guid;
+ uint32 entry;
+ uint32 dist;
+ uint32 repeat;
+ } distance;
+
+ struct
+ {
uint32 param1;
uint32 param2;
uint32 param3;
@@ -1220,7 +1230,7 @@ const uint32 SmartAIEventMask[SMART_EVENT_END][2] =
{SMART_EVENT_REACHED_HOME, SMART_SCRIPT_TYPE_MASK_CREATURE },
{SMART_EVENT_RECEIVE_EMOTE, SMART_SCRIPT_TYPE_MASK_CREATURE },
{SMART_EVENT_HAS_AURA, SMART_SCRIPT_TYPE_MASK_CREATURE },
- {SMART_EVENT_TARGET_BUFFED, SMART_SCRIPT_TYPE_MASK_CREATURE + SMART_SCRIPT_TYPE_MASK_GAMEOBJECT },
+ {SMART_EVENT_TARGET_BUFFED, SMART_SCRIPT_TYPE_MASK_CREATURE },
{SMART_EVENT_RESET, SMART_SCRIPT_TYPE_MASK_CREATURE },
{SMART_EVENT_IC_LOS, SMART_SCRIPT_TYPE_MASK_CREATURE },
{SMART_EVENT_PASSENGER_BOARDED, SMART_SCRIPT_TYPE_MASK_CREATURE },
@@ -1271,6 +1281,8 @@ const uint32 SmartAIEventMask[SMART_EVENT_END][2] =
{SMART_EVENT_ACTION_DONE, SMART_SCRIPT_TYPE_MASK_CREATURE },
{SMART_EVENT_ON_SPELLCLICK, SMART_SCRIPT_TYPE_MASK_CREATURE },
{SMART_EVENT_FRIENDLY_HEALTH_PCT, SMART_SCRIPT_TYPE_MASK_CREATURE },
+ {SMART_EVENT_DISTANCE_CREATURE, SMART_SCRIPT_TYPE_MASK_CREATURE },
+ {SMART_EVENT_DISTANCE_GAMEOBJECT, SMART_SCRIPT_TYPE_MASK_CREATURE },
};
enum SmartEventFlags
diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp
index 3fcfab81c73..c4aa3ef4481 100644
--- a/src/server/game/Battlegrounds/Battleground.cpp
+++ b/src/server/game/Battlegrounds/Battleground.cpp
@@ -1522,21 +1522,33 @@ void Battleground::DoorOpen(uint32 type)
type, GUID_LOPART(BgObjects[type]), m_MapId, m_InstanceID);
}
-GameObject* Battleground::GetBGObject(uint32 type)
+GameObject* Battleground::GetBGObject(uint32 type, bool logError)
{
GameObject* obj = GetBgMap()->GetGameObject(BgObjects[type]);
if (!obj)
- TC_LOG_ERROR("bg.battleground", "Battleground::GetBGObject: gameobject (type: %u, GUID: %u) not found for BG (map: %u, instance id: %u)!",
- type, GUID_LOPART(BgObjects[type]), m_MapId, m_InstanceID);
+ {
+ if (logError)
+ TC_LOG_ERROR("bg.battleground", "Battleground::GetBGObject: gameobject (type: %u, GUID: %u) not found for BG (map: %u, instance id: %u)!",
+ type, GUID_LOPART(BgObjects[type]), m_MapId, m_InstanceID);
+ else
+ TC_LOG_INFO("bg.battleground", "Battleground::GetBGObject: gameobject (type: %u, GUID: %u) not found for BG (map: %u, instance id: %u)!",
+ type, GUID_LOPART(BgObjects[type]), m_MapId, m_InstanceID);
+ }
return obj;
}
-Creature* Battleground::GetBGCreature(uint32 type)
+Creature* Battleground::GetBGCreature(uint32 type, bool logError)
{
Creature* creature = GetBgMap()->GetCreature(BgCreatures[type]);
if (!creature)
- TC_LOG_ERROR("bg.battleground", "Battleground::GetBGCreature: creature (type: %u, GUID: %u) not found for BG (map: %u, instance id: %u)!",
- type, GUID_LOPART(BgCreatures[type]), m_MapId, m_InstanceID);
+ {
+ if (logError)
+ TC_LOG_ERROR("bg.battleground", "Battleground::GetBGCreature: creature (type: %u, GUID: %u) not found for BG (map: %u, instance id: %u)!",
+ type, GUID_LOPART(BgCreatures[type]), m_MapId, m_InstanceID);
+ else
+ TC_LOG_INFO("bg.battleground", "Battleground::GetBGCreature: creature (type: %u, GUID: %u) not found for BG (map: %u, instance id: %u)!",
+ type, GUID_LOPART(BgCreatures[type]), m_MapId, m_InstanceID);
+ }
return creature;
}
diff --git a/src/server/game/Battlegrounds/Battleground.h b/src/server/game/Battlegrounds/Battleground.h
index a866f09639a..5e2aa4b2316 100644
--- a/src/server/game/Battlegrounds/Battleground.h
+++ b/src/server/game/Battlegrounds/Battleground.h
@@ -382,8 +382,8 @@ class Battleground
void StartBattleground();
- GameObject* GetBGObject(uint32 type);
- Creature* GetBGCreature(uint32 type);
+ GameObject* GetBGObject(uint32 type, bool logError = true);
+ Creature* GetBGCreature(uint32 type, bool logError = true);
// Location
void SetMapId(uint32 MapID) { m_MapId = MapID; }
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp
index 6256f53f07b..610e0bcecc7 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp
@@ -790,7 +790,7 @@ void BattlegroundAV::PopulateNode(BG_AV_Nodes node)
if (node >= BG_AV_NODES_MAX)//fail safe
return;
- Creature* trigger = GetBGCreature(node + 302);//0-302 other creatures
+ Creature* trigger = GetBGCreature(node + 302, false);//0-302 other creatures
if (!trigger)
{
trigger = AddCreature(WORLD_TRIGGER,
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp
index be2684631df..bc684aed176 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp
@@ -780,7 +780,7 @@ void BattlegroundEY::EventTeamCapturedPoint(Player* player, uint32 Point)
if (Point >= EY_POINTS_MAX)
return;
- Creature* trigger = GetBGCreature(Point + 6);//0-5 spirit guides
+ Creature* trigger = GetBGCreature(Point + 6, false);//0-5 spirit guides
if (!trigger)
trigger = AddCreature(WORLD_TRIGGER, Point+6, Team, BG_EY_TriggerPositions[Point][0], BG_EY_TriggerPositions[Point][1], BG_EY_TriggerPositions[Point][2], BG_EY_TriggerPositions[Point][3]);
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp
index 590a07541fe..fc3f839ae76 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp
@@ -658,7 +658,7 @@ void BattlegroundIC::HandleCapturedNodes(ICNodePoint* nodePoint, bool recapture)
// we must del opposing faction vehicles when the node is captured (unused ones)
for (uint8 i = (nodePoint->faction == TEAM_ALLIANCE ? BG_IC_NPC_GLAIVE_THROWER_1_H : BG_IC_NPC_GLAIVE_THROWER_1_A); i < (nodePoint->faction == TEAM_ALLIANCE ? BG_IC_NPC_GLAIVE_THROWER_2_H : BG_IC_NPC_GLAIVE_THROWER_2_A); ++i)
{
- if (Creature* glaiveThrower = GetBGCreature(i))
+ if (Creature* glaiveThrower = GetBGCreature(i, false))
{
if (Vehicle* vehicleGlaive = glaiveThrower->GetVehicleKit())
{
@@ -670,7 +670,7 @@ void BattlegroundIC::HandleCapturedNodes(ICNodePoint* nodePoint, bool recapture)
for (uint8 i = (nodePoint->faction == TEAM_ALLIANCE ? BG_IC_NPC_CATAPULT_1_H : BG_IC_NPC_CATAPULT_1_A); i < (nodePoint->faction == TEAM_ALLIANCE ? BG_IC_NPC_CATAPULT_4_H : BG_IC_NPC_CATAPULT_4_A); ++i)
{
- if (Creature* catapult = GetBGCreature(i))
+ if (Creature* catapult = GetBGCreature(i, false))
{
if (Vehicle* vehicleGlaive = catapult->GetVehicleKit())
{
@@ -685,7 +685,7 @@ void BattlegroundIC::HandleCapturedNodes(ICNodePoint* nodePoint, bool recapture)
{
uint8 type = (nodePoint->faction == TEAM_ALLIANCE ? BG_IC_NPC_GLAIVE_THROWER_1_A : BG_IC_NPC_GLAIVE_THROWER_1_H)+i;
- if (GetBGCreature(type) && GetBGCreature(type)->IsAlive())
+ if (GetBGCreature(type, false) && GetBGCreature(type)->IsAlive())
continue;
if (AddCreature(nodePoint->faction == TEAM_ALLIANCE ? NPC_GLAIVE_THROWER_A : NPC_GLAIVE_THROWER_H, type, nodePoint->faction,
@@ -700,7 +700,7 @@ void BattlegroundIC::HandleCapturedNodes(ICNodePoint* nodePoint, bool recapture)
{
uint8 type = (nodePoint->faction == TEAM_ALLIANCE ? BG_IC_NPC_CATAPULT_1_A : BG_IC_NPC_CATAPULT_1_H)+i;
- if (GetBGCreature(type) && GetBGCreature(type)->IsAlive())
+ if (GetBGCreature(type, false) && GetBGCreature(type)->IsAlive())
continue;
if (AddCreature(NPC_CATAPULT, type, nodePoint->faction,
@@ -720,7 +720,7 @@ void BattlegroundIC::HandleCapturedNodes(ICNodePoint* nodePoint, bool recapture)
// we must del opposing faction vehicles when the node is captured (unused ones)
for (uint8 i = (nodePoint->faction == TEAM_ALLIANCE ? BG_IC_NPC_DEMOLISHER_1_H : BG_IC_NPC_DEMOLISHER_1_A); i < (nodePoint->faction == TEAM_ALLIANCE ? BG_IC_NPC_DEMOLISHER_4_H : BG_IC_NPC_DEMOLISHER_4_A); ++i)
{
- if (Creature* demolisher = GetBGCreature(i))
+ if (Creature* demolisher = GetBGCreature(i, false))
{
if (Vehicle* vehicleDemolisher = demolisher->GetVehicleKit())
{
@@ -735,7 +735,7 @@ void BattlegroundIC::HandleCapturedNodes(ICNodePoint* nodePoint, bool recapture)
{
uint8 type = (nodePoint->faction == TEAM_ALLIANCE ? BG_IC_NPC_DEMOLISHER_1_A : BG_IC_NPC_DEMOLISHER_1_H)+i;
- if (GetBGCreature(type) && GetBGCreature(type)->IsAlive())
+ if (GetBGCreature(type, false) && GetBGCreature(type)->IsAlive())
continue;
if (AddCreature(NPC_DEMOLISHER, type, nodePoint->faction,
@@ -748,7 +748,7 @@ void BattlegroundIC::HandleCapturedNodes(ICNodePoint* nodePoint, bool recapture)
// we check if the opossing siege engine is in use
int8 enemySiege = (nodePoint->faction == TEAM_ALLIANCE ? BG_IC_NPC_SIEGE_ENGINE_H : BG_IC_NPC_SIEGE_ENGINE_A);
- if (Creature* siegeEngine = GetBGCreature(enemySiege))
+ if (Creature* siegeEngine = GetBGCreature(enemySiege, false))
{
if (Vehicle* vehicleSiege = siegeEngine->GetVehicleKit())
{
@@ -759,7 +759,7 @@ void BattlegroundIC::HandleCapturedNodes(ICNodePoint* nodePoint, bool recapture)
}
uint8 siegeType = (nodePoint->faction == TEAM_ALLIANCE ? BG_IC_NPC_SIEGE_ENGINE_A : BG_IC_NPC_SIEGE_ENGINE_H);
- if (!GetBGCreature(siegeType) || !GetBGCreature(siegeType)->IsAlive())
+ if (!GetBGCreature(siegeType, false) || !GetBGCreature(siegeType)->IsAlive())
{
AddCreature((nodePoint->faction == TEAM_ALLIANCE ? NPC_SIEGE_ENGINE_A : NPC_SIEGE_ENGINE_H), siegeType, nodePoint->faction,
BG_IC_WorkshopVehicles[4].GetPositionX(), BG_IC_WorkshopVehicles[4].GetPositionY(),
diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp
index e76ba18f1e2..bb1a722ec42 100644
--- a/src/server/game/Conditions/ConditionMgr.cpp
+++ b/src/server/game/Conditions/ConditionMgr.cpp
@@ -1078,8 +1078,7 @@ bool ConditionMgr::addToGossipMenuItems(Condition* cond)
bool ConditionMgr::addToSpellImplicitTargetConditions(Condition* cond)
{
uint32 conditionEffMask = cond->SourceGroup;
- SpellInfo* spellInfo = const_cast<SpellInfo*>(sSpellMgr->GetSpellInfo(cond->SourceEntry));
- ASSERT(spellInfo);
+ SpellInfo* spellInfo = const_cast<SpellInfo*>(sSpellMgr->EnsureSpellInfo(cond->SourceEntry));
std::list<uint32> sharedMasks;
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
{
@@ -1994,7 +1993,7 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond)
}
case CONDITION_UNIT_STATE:
{
- if (cond->ConditionValue1 > uint32(UNIT_STATE_ALL_STATE))
+ if (!(cond->ConditionValue1 & UNIT_STATE_ALL_STATE_SUPPORTED))
{
TC_LOG_ERROR("sql.sql", "UnitState condition has non existing UnitState in value1 (%u), skipped", cond->ConditionValue1);
return false;
diff --git a/src/server/game/DataStores/DBCStores.cpp b/src/server/game/DataStores/DBCStores.cpp
index a4b3ded80e5..37f4f4c1930 100644
--- a/src/server/game/DataStores/DBCStores.cpp
+++ b/src/server/game/DataStores/DBCStores.cpp
@@ -123,6 +123,7 @@ DBCStorage <ItemRandomSuffixEntry> sItemRandomSuffixStore(ItemRandomSuffixfmt);
DBCStorage <ItemSetEntry> sItemSetStore(ItemSetEntryfmt);
DBCStorage <LFGDungeonEntry> sLFGDungeonStore(LFGDungeonEntryfmt);
+DBCStorage <LightEntry> sLightStore(LightEntryfmt);
DBCStorage <LiquidTypeEntry> sLiquidTypeStore(LiquidTypefmt);
DBCStorage <LockEntry> sLockStore(LockEntryfmt);
@@ -371,6 +372,7 @@ void LoadDBCStores(const std::string& dataPath)
LoadDBC(availableDbcLocales, bad_dbc_files, sItemSetStore, dbcPath, "ItemSet.dbc");
LoadDBC(availableDbcLocales, bad_dbc_files, sLFGDungeonStore, dbcPath, "LFGDungeons.dbc");
+ LoadDBC(availableDbcLocales, bad_dbc_files, sLightStore, dbcPath, "Light.dbc");
LoadDBC(availableDbcLocales, bad_dbc_files, sLiquidTypeStore, dbcPath, "LiquidType.dbc");
LoadDBC(availableDbcLocales, bad_dbc_files, sLockStore, dbcPath, "Lock.dbc");
@@ -944,3 +946,18 @@ LFGDungeonEntry const* GetLFGDungeon(uint32 mapId, Difficulty difficulty)
return NULL;
}
+
+uint32 GetDefaultMapLight(uint32 mapId)
+{
+ for (int32 i = sLightStore.GetNumRows(); i >= 0; --i)
+ {
+ LightEntry const* light = sLightStore.LookupEntry(uint32(i));
+ if (!light)
+ continue;
+
+ if (light->MapId == mapId && light->X == 0.0f && light->Y == 0.0f && light->Z == 0.0f)
+ return light->Id;
+ }
+
+ return 0;
+}
diff --git a/src/server/game/DataStores/DBCStores.h b/src/server/game/DataStores/DBCStores.h
index fe8fb35220b..39747141322 100644
--- a/src/server/game/DataStores/DBCStores.h
+++ b/src/server/game/DataStores/DBCStores.h
@@ -72,6 +72,8 @@ CharStartOutfitEntry const* GetCharStartOutfitEntry(uint8 race, uint8 class_, ui
LFGDungeonEntry const* GetLFGDungeon(uint32 mapId, Difficulty difficulty);
+uint32 GetDefaultMapLight(uint32 mapId);
+
extern DBCStorage <AchievementEntry> sAchievementStore;
extern DBCStorage <AchievementCriteriaEntry> sAchievementCriteriaStore;
extern DBCStorage <AreaTableEntry> sAreaStore;// recommend access using functions
diff --git a/src/server/game/DataStores/DBCStructure.h b/src/server/game/DataStores/DBCStructure.h
index d1db4fb634d..8efc32cc9b2 100644
--- a/src/server/game/DataStores/DBCStructure.h
+++ b/src/server/game/DataStores/DBCStructure.h
@@ -1230,6 +1230,24 @@ struct LFGDungeonEntry
uint32 Entry() const { return ID + (type << 24); }
};
+struct LightEntry
+{
+ uint32 Id;
+ uint32 MapId;
+ float X;
+ float Y;
+ float Z;
+ //float FalloffStart;
+ //float FalloffEnd;
+ //uint32 SkyAndFog;
+ //uint32 WaterSettings;
+ //uint32 SunsetParams;
+ //uint32 OtherParams;
+ //uint32 DeathParams;
+ //uint32 Unknown;
+ //uint32 Unknown;
+ //uint32 Unknown;
+};
struct LiquidTypeEntry
{
diff --git a/src/server/game/DataStores/DBCfmt.h b/src/server/game/DataStores/DBCfmt.h
index be4369399d4..a1587dd6087 100644
--- a/src/server/game/DataStores/DBCfmt.h
+++ b/src/server/game/DataStores/DBCfmt.h
@@ -79,6 +79,7 @@ char const ItemRandomPropertiesfmt[] = "nxiiixxssssssssssssssssx";
char const ItemRandomSuffixfmt[] = "nssssssssssssssssxxiiixxiiixx";
char const ItemSetEntryfmt[] = "dssssssssssssssssxiiiiiiiiiixxxxxxxiiiiiiiiiiiiiiiiii";
char const LFGDungeonEntryfmt[] = "nssssssssssssssssxiiiiiiiiixxixixxxxxxxxxxxxxxxxx";
+char const LightEntryfmt[] = "nifffxxxxxxxxxx";
char const LiquidTypefmt[] = "nxxixixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
char const LockEntryfmt[] = "niiiiiiiiiiiiiiiiiiiiiiiixxxxxxxx";
char const MailTemplateEntryfmt[] = "nxxxxxxxxxxxxxxxxxssssssssssssssssx";
diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp
index d9df2057b54..98ca9222e67 100644
--- a/src/server/game/DungeonFinding/LFGMgr.cpp
+++ b/src/server/game/DungeonFinding/LFGMgr.cpp
@@ -968,6 +968,7 @@ void LFGMgr::MakeNewGroup(LfgProposal const& proposal)
player->CastSpell(player, LFG_SPELL_DUNGEON_COOLDOWN, false);
}
+ ASSERT(grp);
grp->SetDungeonDifficulty(Difficulty(dungeon->difficulty));
uint64 gguid = grp->GetGUID();
SetDungeon(gguid, dungeon->Entry());
diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h
index 737e3072091..69c3d169170 100644
--- a/src/server/game/Entities/Creature/Creature.h
+++ b/src/server/game/Entities/Creature/Creature.h
@@ -635,13 +635,13 @@ class Creature : public Unit, public GridObject<Creature>, public MapObject
void SetHomePosition(float x, float y, float z, float o) { m_homePosition.Relocate(x, y, z, o); }
void SetHomePosition(const Position &pos) { m_homePosition.Relocate(pos); }
- void GetHomePosition(float &x, float &y, float &z, float &ori) const { m_homePosition.GetPosition(x, y, z, ori); }
- Position GetHomePosition() const { return m_homePosition; }
+ void GetHomePosition(float& x, float& y, float& z, float& ori) const { m_homePosition.GetPosition(x, y, z, ori); }
+ Position const& GetHomePosition() const { return m_homePosition; }
void SetTransportHomePosition(float x, float y, float z, float o) { m_transportHomePosition.Relocate(x, y, z, o); }
void SetTransportHomePosition(const Position &pos) { m_transportHomePosition.Relocate(pos); }
- void GetTransportHomePosition(float &x, float &y, float &z, float &ori) { m_transportHomePosition.GetPosition(x, y, z, ori); }
- Position GetTransportHomePosition() { return m_transportHomePosition; }
+ void GetTransportHomePosition(float& x, float& y, float& z, float& ori) const { m_transportHomePosition.GetPosition(x, y, z, ori); }
+ Position const& GetTransportHomePosition() const { return m_transportHomePosition; }
uint32 GetWaypointPath() const { return m_path_id; }
void LoadPath(uint32 pathid) { m_path_id = pathid; }
diff --git a/src/server/game/Entities/Creature/GossipDef.cpp b/src/server/game/Entities/Creature/GossipDef.cpp
index ffb28849925..8671caf864d 100644
--- a/src/server/game/Entities/Creature/GossipDef.cpp
+++ b/src/server/game/Entities/Creature/GossipDef.cpp
@@ -28,6 +28,7 @@ GossipMenu::GossipMenu()
{
_menuId = 0;
_locale = DEFAULT_LOCALE;
+ _senderGUID = 0;
}
GossipMenu::~GossipMenu()
@@ -166,8 +167,10 @@ void PlayerMenu::ClearMenus()
_questMenu.ClearMenu();
}
-void PlayerMenu::SendGossipMenu(uint32 titleTextId, uint64 objectGUID) const
+void PlayerMenu::SendGossipMenu(uint32 titleTextId, uint64 objectGUID)
{
+ _gossipMenu.SetSenderGUID(objectGUID);
+
WorldPacket data(SMSG_GOSSIP_MESSAGE, 100); // guess size
data << uint64(objectGUID);
data << uint32(_gossipMenu.GetMenuId()); // new 2.4.0
@@ -222,8 +225,10 @@ void PlayerMenu::SendGossipMenu(uint32 titleTextId, uint64 objectGUID) const
_session->SendPacket(&data);
}
-void PlayerMenu::SendCloseGossip() const
+void PlayerMenu::SendCloseGossip()
{
+ _gossipMenu.SetSenderGUID(0);
+
WorldPacket data(SMSG_GOSSIP_COMPLETE, 0);
_session->SendPacket(&data);
}
diff --git a/src/server/game/Entities/Creature/GossipDef.h b/src/server/game/Entities/Creature/GossipDef.h
index 9a30fdeee2b..e8fac878409 100644
--- a/src/server/game/Entities/Creature/GossipDef.h
+++ b/src/server/game/Entities/Creature/GossipDef.h
@@ -25,7 +25,7 @@
class WorldSession;
-#define GOSSIP_MAX_MENU_ITEMS 64 // client supported items unknown, but provided number must be enough
+#define GOSSIP_MAX_MENU_ITEMS 32
#define DEFAULT_GOSSIP_MESSAGE 0xffffff
enum Gossip_Option
@@ -167,6 +167,8 @@ class GossipMenu
void SetMenuId(uint32 menu_id) { _menuId = menu_id; }
uint32 GetMenuId() const { return _menuId; }
+ void SetSenderGUID(uint64 guid) { _senderGUID = guid; }
+ uint64 GetSenderGUID() const { return _senderGUID; }
void SetLocale(LocaleConstant locale) { _locale = locale; }
LocaleConstant GetLocale() const { return _locale; }
@@ -215,6 +217,7 @@ class GossipMenu
GossipMenuItemContainer _menuItems;
GossipMenuItemDataContainer _menuItemData;
uint32 _menuId;
+ uint64 _senderGUID;
LocaleConstant _locale;
};
@@ -264,8 +267,8 @@ class PlayerMenu
uint32 GetGossipOptionAction(uint32 selection) const { return _gossipMenu.GetMenuItemAction(selection); }
bool IsGossipOptionCoded(uint32 selection) const { return _gossipMenu.IsMenuItemCoded(selection); }
- void SendGossipMenu(uint32 titleTextId, uint64 objectGUID) const;
- void SendCloseGossip() const;
+ void SendGossipMenu(uint32 titleTextId, uint64 objectGUID);
+ void SendCloseGossip();
void SendPointOfInterest(uint32 poiId) const;
/*********************************************************/
diff --git a/src/server/game/Entities/DynamicObject/DynamicObject.cpp b/src/server/game/Entities/DynamicObject/DynamicObject.cpp
index f4e956e8839..7cc94d992a1 100644
--- a/src/server/game/Entities/DynamicObject/DynamicObject.cpp
+++ b/src/server/game/Entities/DynamicObject/DynamicObject.cpp
@@ -26,6 +26,7 @@
#include "CellImpl.h"
#include "GridNotifiersImpl.h"
#include "ScriptMgr.h"
+#include "Transport.h"
DynamicObject::DynamicObject(bool isWorldObject) : WorldObject(isWorldObject),
_aura(NULL), _removedAura(NULL), _caster(NULL), _duration(0), _isViewpoint(false)
@@ -47,6 +48,18 @@ DynamicObject::~DynamicObject()
delete _removedAura;
}
+void DynamicObject::CleanupsBeforeDelete(bool finalCleanup /* = true */)
+{
+ WorldObject::CleanupsBeforeDelete(finalCleanup);
+
+ if (Transport* transport = GetTransport())
+ {
+ transport->RemovePassenger(this);
+ SetTransport(NULL);
+ m_movementInfo.transport.Reset();
+ }
+}
+
void DynamicObject::AddToWorld()
{
///- Register the dynamicObject for guid lookup and for caster
@@ -108,8 +121,28 @@ bool DynamicObject::CreateDynamicObject(uint32 guidlow, Unit* caster, uint32 spe
if (IsWorldObject())
setActive(true); //must before add to map to be put in world container
+ Transport* transport = caster->GetTransport();
+ if (transport)
+ {
+ m_movementInfo.transport.guid = GetGUID();
+
+ float x, y, z, o;
+ pos.GetPosition(x, y, z, o);
+ transport->CalculatePassengerOffset(x, y, z, &o);
+ m_movementInfo.transport.pos.Relocate(x, y, z, o);
+
+ SetTransport(transport);
+ // This object must be added to transport before adding to map for the client to properly display it
+ transport->AddPassenger(this);
+ }
+
if (!GetMap()->AddToMap(this))
+ {
+ // Returning false will cause the object to be deleted - remove from transport
+ if (transport)
+ transport->RemovePassenger(this);
return false;
+ }
return true;
}
diff --git a/src/server/game/Entities/DynamicObject/DynamicObject.h b/src/server/game/Entities/DynamicObject/DynamicObject.h
index 5b68bf377b9..cdba5982b3f 100644
--- a/src/server/game/Entities/DynamicObject/DynamicObject.h
+++ b/src/server/game/Entities/DynamicObject/DynamicObject.h
@@ -32,7 +32,7 @@ enum DynamicObjectType
DYNAMIC_OBJECT_FARSIGHT_FOCUS = 0x2
};
-class DynamicObject : public WorldObject, public GridObject<DynamicObject>
+class DynamicObject : public WorldObject, public GridObject<DynamicObject>, public MapObject
{
public:
DynamicObject(bool isWorldObject);
@@ -41,6 +41,8 @@ class DynamicObject : public WorldObject, public GridObject<DynamicObject>
void AddToWorld();
void RemoveFromWorld();
+ void CleanupsBeforeDelete(bool finalCleanup = true) OVERRIDE;
+
bool CreateDynamicObject(uint32 guidlow, Unit* caster, uint32 spellId, Position const& pos, float radius, DynamicObjectType type);
void Update(uint32 p_time);
void Remove();
diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp
index e3c8c9c8136..67f7b1a46b2 100644
--- a/src/server/game/Entities/GameObject/GameObject.cpp
+++ b/src/server/game/Entities/GameObject/GameObject.cpp
@@ -148,7 +148,7 @@ void GameObject::AddToWorld()
sObjectAccessor->AddObject(this);
// The state can be changed after GameObject::Create but before GameObject::AddToWorld
- bool toggledState = GetGoType() == GAMEOBJECT_TYPE_CHEST ? getLootState() == GO_READY : GetGoState() == GO_STATE_READY;
+ bool toggledState = GetGoType() == GAMEOBJECT_TYPE_CHEST ? getLootState() == GO_READY : (GetGoState() == GO_STATE_READY || IsTransport());
if (m_model)
GetMap()->InsertGameObjectModel(*m_model);
@@ -317,7 +317,6 @@ void GameObject::Update(uint32 diff)
m_lootState = GO_READY;
break;
}
- /* TODO: Fix movement in unloaded grid - currently GO will just disappear
case GAMEOBJECT_TYPE_TRANSPORT:
{
if (!m_goValue.Transport.AnimationInfo)
@@ -326,6 +325,7 @@ void GameObject::Update(uint32 diff)
if (GetGoState() == GO_STATE_READY)
{
m_goValue.Transport.PathProgress += diff;
+ /* TODO: Fix movement in unloaded grid - currently GO will just disappear
uint32 timer = m_goValue.Transport.PathProgress % m_goValue.Transport.AnimationInfo->TotalTime;
TransportAnimationEntry const* node = m_goValue.Transport.AnimationInfo->GetAnimNode(timer);
if (node && m_goValue.Transport.CurrentSeg != node->TimeSeg)
@@ -341,14 +341,14 @@ void GameObject::Update(uint32 diff)
G3D::Vector3 src(GetPositionX(), GetPositionY(), GetPositionZ());
- TC_LOG_INFO("misc", "Src: %s Dest: %s", src.toString().c_str(), pos.toString().c_str());
+ TC_LOG_DEBUG("misc", "Src: %s Dest: %s", src.toString().c_str(), pos.toString().c_str());
GetMap()->GameObjectRelocation(this, pos.x, pos.y, pos.z, GetOrientation());
}
+ */
}
break;
}
- */
case GAMEOBJECT_TYPE_FISHINGNODE:
{
// fishing code (bobber ready)
@@ -2019,7 +2019,7 @@ void GameObject::SetGoState(GOState state)
{
SetByteValue(GAMEOBJECT_BYTES_1, 0, state);
sScriptMgr->OnGameObjectStateChanged(this, state);
- if (m_model)
+ if (m_model && !IsTransport())
{
if (!IsInWorld())
return;
@@ -2238,3 +2238,16 @@ float GameObject::GetInteractionDistance()
return INTERACTION_DISTANCE;
}
}
+
+void GameObject::UpdateModelPosition()
+{
+ if (!m_model)
+ return;
+
+ if (GetMap()->ContainsGameObjectModel(*m_model))
+ {
+ GetMap()->RemoveGameObjectModel(*m_model);
+ m_model->Relocate(*this);
+ GetMap()->InsertGameObjectModel(*m_model);
+ }
+}
diff --git a/src/server/game/Entities/GameObject/GameObject.h b/src/server/game/Entities/GameObject/GameObject.h
index 84abc391bc6..48db64a3687 100644
--- a/src/server/game/Entities/GameObject/GameObject.h
+++ b/src/server/game/Entities/GameObject/GameObject.h
@@ -832,6 +832,8 @@ class GameObject : public WorldObject, public GridObject<GameObject>, public Map
float GetInteractionDistance();
+ void UpdateModelPosition();
+
protected:
bool AIM_Initialize();
void UpdateModel(); // updates model in case displayId were changed
diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp
index 8af48f277bd..12c8d0ba2ac 100644
--- a/src/server/game/Entities/Object/Object.cpp
+++ b/src/server/game/Entities/Object/Object.cpp
@@ -370,6 +370,7 @@ void Object::BuildMovementUpdate(ByteBuffer* data, uint16 flags) const
{
if (flags & UPDATEFLAG_POSITION)
{
+ ASSERT(object);
Transport* transport = object->GetTransport();
if (transport)
@@ -412,6 +413,7 @@ void Object::BuildMovementUpdate(ByteBuffer* data, uint16 flags) const
// 0x40
if (flags & UPDATEFLAG_STATIONARY_POSITION)
{
+ ASSERT(object);
*data << object->GetStationaryX();
*data << object->GetStationaryY();
*data << object->GetStationaryZ();
@@ -459,6 +461,7 @@ void Object::BuildMovementUpdate(ByteBuffer* data, uint16 flags) const
// 0x4
if (flags & UPDATEFLAG_HAS_TARGET)
{
+ ASSERT(unit);
if (Unit* victim = unit->GetVictim())
data->append(victim->GetPackGUID());
else
@@ -469,7 +472,12 @@ void Object::BuildMovementUpdate(ByteBuffer* data, uint16 flags) const
if (flags & UPDATEFLAG_TRANSPORT)
{
GameObject const* go = ToGameObject();
- if (go && go->IsTransport())
+ /** @TODO Use IsTransport() to also handle type 11 (TRANSPORT)
+ Currently grid objects are not updated if there are no nearby players,
+ this causes clients to receive different PathProgress
+ resulting in players seeing the object in a different position
+ */
+ if (go && go->ToTransport())
*data << uint32(go->GetGOValue()->Transport.PathProgress);
else
*data << uint32(getMSTime());
@@ -479,6 +487,9 @@ void Object::BuildMovementUpdate(ByteBuffer* data, uint16 flags) const
if (flags & UPDATEFLAG_VEHICLE)
{
/// @todo Allow players to aquire this updateflag.
+ ASSERT(unit);
+ ASSERT(unit->GetVehicleKit());
+ ASSERT(unit->GetVehicleKit()->GetVehicleInfo());
*data << uint32(unit->GetVehicleKit()->GetVehicleInfo()->m_ID);
if (unit->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT))
*data << float(unit->GetTransOffsetO());
@@ -739,7 +750,7 @@ void Object::SetByteValue(uint16 index, uint8 offset, uint8 value)
{
ASSERT(index < m_valuesCount || PrintIndexError(index, true));
- if (offset > 4)
+ if (offset > 3)
{
TC_LOG_ERROR("misc", "Object::SetByteValue: wrong offset %u", offset);
return;
@@ -763,7 +774,7 @@ void Object::SetUInt16Value(uint16 index, uint8 offset, uint16 value)
{
ASSERT(index < m_valuesCount || PrintIndexError(index, true));
- if (offset > 2)
+ if (offset > 1)
{
TC_LOG_ERROR("misc", "Object::SetUInt16Value: wrong offset %u", offset);
return;
@@ -903,7 +914,7 @@ void Object::SetByteFlag(uint16 index, uint8 offset, uint8 newFlag)
{
ASSERT(index < m_valuesCount || PrintIndexError(index, true));
- if (offset > 4)
+ if (offset > 3)
{
TC_LOG_ERROR("misc", "Object::SetByteFlag: wrong offset %u", offset);
return;
@@ -926,7 +937,7 @@ void Object::RemoveByteFlag(uint16 index, uint8 offset, uint8 oldFlag)
{
ASSERT(index < m_valuesCount || PrintIndexError(index, true));
- if (offset > 4)
+ if (offset > 3)
{
TC_LOG_ERROR("misc", "Object::RemoveByteFlag: wrong offset %u", offset);
return;
@@ -1552,9 +1563,9 @@ void WorldObject::GetRandomPoint(const Position &srcPos, float distance, Positio
void WorldObject::UpdateGroundPositionZ(float x, float y, float &z) const
{
- float new_z = GetBaseMap()->GetHeight(GetPhaseMask(), x, y, z, true);
+ float new_z = GetMap()->GetHeight(GetPhaseMask(), x, y, z + 2.0f, true);
if (new_z > INVALID_HEIGHT)
- z = new_z+ 0.05f; // just to be sure that we are not a few pixel under the surface
+ z = new_z + 0.05f; // just to be sure that we are not a few pixel under the surface
}
void WorldObject::UpdateAllowedPositionZ(float x, float y, float &z) const
@@ -1574,8 +1585,8 @@ void WorldObject::UpdateAllowedPositionZ(float x, float y, float &z) const
bool canSwim = ToCreature()->CanSwim();
float ground_z = z;
float max_z = canSwim
- ? GetBaseMap()->GetWaterOrGroundLevel(x, y, z, &ground_z, !ToUnit()->HasAuraType(SPELL_AURA_WATER_WALK))
- : ((ground_z = GetBaseMap()->GetHeight(GetPhaseMask(), x, y, z, true)));
+ ? GetMap()->GetWaterOrGroundLevel(x, y, z, &ground_z, !ToUnit()->HasAuraType(SPELL_AURA_WATER_WALK))
+ : ((ground_z = GetMap()->GetHeight(GetPhaseMask(), x, y, z, true)));
if (max_z > INVALID_HEIGHT)
{
if (z > max_z)
@@ -1586,7 +1597,7 @@ void WorldObject::UpdateAllowedPositionZ(float x, float y, float &z) const
}
else
{
- float ground_z = GetBaseMap()->GetHeight(GetPhaseMask(), x, y, z, true);
+ float ground_z = GetMap()->GetHeight(GetPhaseMask(), x, y, z, true);
if (z < ground_z)
z = ground_z;
}
@@ -1598,7 +1609,7 @@ void WorldObject::UpdateAllowedPositionZ(float x, float y, float &z) const
if (!ToPlayer()->CanFly())
{
float ground_z = z;
- float max_z = GetBaseMap()->GetWaterOrGroundLevel(x, y, z, &ground_z, !ToUnit()->HasAuraType(SPELL_AURA_WATER_WALK));
+ float max_z = GetMap()->GetWaterOrGroundLevel(x, y, z, &ground_z, !ToUnit()->HasAuraType(SPELL_AURA_WATER_WALK));
if (max_z > INVALID_HEIGHT)
{
if (z > max_z)
@@ -1609,7 +1620,7 @@ void WorldObject::UpdateAllowedPositionZ(float x, float y, float &z) const
}
else
{
- float ground_z = GetBaseMap()->GetHeight(GetPhaseMask(), x, y, z, true);
+ float ground_z = GetMap()->GetHeight(GetPhaseMask(), x, y, z, true);
if (z < ground_z)
z = ground_z;
}
@@ -1617,7 +1628,7 @@ void WorldObject::UpdateAllowedPositionZ(float x, float y, float &z) const
}
default:
{
- float ground_z = GetBaseMap()->GetHeight(GetPhaseMask(), x, y, z, true);
+ float ground_z = GetMap()->GetHeight(GetPhaseMask(), x, y, z, true);
if (ground_z > INVALID_HEIGHT)
z = ground_z;
break;
diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp
index 1d7db005a0b..19ac8dd57b5 100644
--- a/src/server/game/Entities/Pet/Pet.cpp
+++ b/src/server/game/Entities/Pet/Pet.cpp
@@ -2060,8 +2060,7 @@ void Pet::ProhibitSpellSchool(SpellSchoolMask idSchoolMask, uint32 unTimeMs)
continue;
uint32 unSpellId = itr->first;
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(unSpellId);
- ASSERT(spellInfo);
+ SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(unSpellId);
// Not send cooldown for this spells
if (spellInfo->IsCooldownStartedOnEvent())
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 2f7b37a2254..05c89a99ed2 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -4204,7 +4204,7 @@ bool Player::Has310Flyer(bool checkAllSpells, uint32 excludeSpellId)
if (_spell_idx->second->skillId != SKILL_MOUNTS)
break; // We can break because mount spells belong only to one skillline (at least 310 flyers do)
- spellInfo = sSpellMgr->GetSpellInfo(itr->first);
+ spellInfo = sSpellMgr->EnsureSpellInfo(itr->first);
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
if (spellInfo->Effects[i].ApplyAuraName == SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED &&
spellInfo->Effects[i].CalcValue() == 310)
@@ -15743,6 +15743,7 @@ bool Player::SatisfyQuestExclusiveGroup(Quest const* qInfo, bool msg)
// not allow have daily quest if daily quest from exclusive group already recently completed
Quest const* Nquest = sObjectMgr->GetQuestTemplate(exclude_Id);
+ ASSERT(Nquest);
if (!SatisfyQuestDay(Nquest, false) || !SatisfyQuestWeek(Nquest, false) || !SatisfyQuestSeasonal(Nquest, false))
{
if (msg)
@@ -15944,6 +15945,7 @@ bool Player::TakeQuestSourceItem(uint32 questId, bool msg)
return false;
}
+ ASSERT(item);
bool destroyItem = true;
for (uint8 n = 0; n < QUEST_ITEM_OBJECTIVES_COUNT; ++n)
if (item->StartQuest == questId && srcItemId == quest->RequiredItemId[n])
@@ -21334,6 +21336,7 @@ bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, Creature* npc
if (sWorld->getBoolConfig(CONFIG_INSTANT_TAXI))
{
TaxiNodesEntry const* lastPathNode = sTaxiNodesStore.LookupEntry(nodes[nodes.size()-1]);
+ ASSERT(lastPathNode);
m_taxi.ClearTaxiDestinations();
TeleportTo(lastPathNode->map_id, lastPathNode->x, lastPathNode->y, lastPathNode->z, GetOrientation());
return false;
@@ -21554,6 +21557,7 @@ inline bool Player::_StoreOrEquipNewItem(uint32 vendorslot, uint32 item, uint8 c
if (crItem->ExtendedCost) // case for new honor system
{
ItemExtendedCostEntry const* iece = sItemExtendedCostStore.LookupEntry(crItem->ExtendedCost);
+ ASSERT(iece);
if (iece->reqhonorpoints)
ModifyHonorPoints(- int32(iece->reqhonorpoints * count));
@@ -24745,6 +24749,12 @@ void Player::StoreLootItem(uint8 lootSlot, Loot* loot)
return;
}
+ if (!item->AllowedForPlayer(this))
+ {
+ SendLootRelease(GetLootGUID());
+ return;
+ }
+
// questitems use the blocked field for other purposes
if (!qitem && item->is_blocked)
{
diff --git a/src/server/game/Entities/Transport/Transport.cpp b/src/server/game/Entities/Transport/Transport.cpp
index f8c38d32390..cf7cadadbfd 100644
--- a/src/server/game/Entities/Transport/Transport.cpp
+++ b/src/server/game/Entities/Transport/Transport.cpp
@@ -31,6 +31,7 @@
#include "Player.h"
#include "Cell.h"
#include "CellImpl.h"
+#include "Totem.h"
Transport::Transport() : GameObject(),
_transportInfo(NULL), _isMoving(true), _pendingStop(false),
@@ -95,9 +96,26 @@ bool Transport::Create(uint32 guidlow, uint32 entry, uint32 mapid, float x, floa
SetGoAnimProgress(animprogress);
SetName(goinfo->name);
UpdateRotationFields(0.0f, 1.0f);
+
+ m_model = GameObjectModel::Create(*this);
return true;
}
+void Transport::CleanupsBeforeDelete(bool finalCleanup /*= true*/)
+{
+ UnloadStaticPassengers();
+ while (!_passengers.empty())
+ {
+ WorldObject* obj = *_passengers.begin();
+ obj->m_movementInfo.RemoveMovementFlag(MOVEMENTFLAG_ONTRANSPORT);
+ obj->m_movementInfo.transport.Reset();
+ obj->SetTransport(NULL);
+ RemovePassenger(obj);
+ }
+
+ GameObject::CleanupsBeforeDelete(finalCleanup);
+}
+
void Transport::Update(uint32 diff)
{
uint32 const positionUpdateDelay = 200;
@@ -202,6 +220,9 @@ void Transport::Update(uint32 diff)
void Transport::AddPassenger(WorldObject* passenger)
{
+ if (!IsInWorld())
+ return;
+
if (_passengers.insert(passenger).second)
{
TC_LOG_DEBUG("entities.transport", "Object %s boarded transport %s.", passenger->GetName().c_str(), GetName().c_str());
@@ -308,11 +329,135 @@ GameObject* Transport::CreateGOPassenger(uint32 guid, GameObjectData const* data
return go;
}
+TempSummon* Transport::SummonPassenger(uint32 entry, Position const& pos, TempSummonType summonType, SummonPropertiesEntry const* properties /*= NULL*/, uint32 duration /*= 0*/, Unit* summoner /*= NULL*/, uint32 spellId /*= 0*/, uint32 vehId /*= 0*/)
+{
+ Map* map = FindMap();
+ if (!map)
+ return NULL;
+
+ uint32 mask = UNIT_MASK_SUMMON;
+ if (properties)
+ {
+ switch (properties->Category)
+ {
+ case SUMMON_CATEGORY_PET:
+ mask = UNIT_MASK_GUARDIAN;
+ break;
+ case SUMMON_CATEGORY_PUPPET:
+ mask = UNIT_MASK_PUPPET;
+ break;
+ case SUMMON_CATEGORY_VEHICLE:
+ mask = UNIT_MASK_MINION;
+ break;
+ case SUMMON_CATEGORY_WILD:
+ case SUMMON_CATEGORY_ALLY:
+ case SUMMON_CATEGORY_UNK:
+ {
+ switch (properties->Type)
+ {
+ case SUMMON_TYPE_MINION:
+ case SUMMON_TYPE_GUARDIAN:
+ case SUMMON_TYPE_GUARDIAN2:
+ mask = UNIT_MASK_GUARDIAN;
+ break;
+ case SUMMON_TYPE_TOTEM:
+ case SUMMON_TYPE_LIGHTWELL:
+ mask = UNIT_MASK_TOTEM;
+ break;
+ case SUMMON_TYPE_VEHICLE:
+ case SUMMON_TYPE_VEHICLE2:
+ mask = UNIT_MASK_SUMMON;
+ break;
+ case SUMMON_TYPE_MINIPET:
+ mask = UNIT_MASK_MINION;
+ break;
+ default:
+ if (properties->Flags & 512) // Mirror Image, Summon Gargoyle
+ mask = UNIT_MASK_GUARDIAN;
+ break;
+ }
+ break;
+ }
+ default:
+ return NULL;
+ }
+ }
+
+ uint32 phase = PHASEMASK_NORMAL;
+ uint32 team = 0;
+ if (summoner)
+ {
+ phase = summoner->GetPhaseMask();
+ if (summoner->GetTypeId() == TYPEID_PLAYER)
+ team = summoner->ToPlayer()->GetTeam();
+ }
+
+ TempSummon* summon = NULL;
+ switch (mask)
+ {
+ case UNIT_MASK_SUMMON:
+ summon = new TempSummon(properties, summoner, false);
+ break;
+ case UNIT_MASK_GUARDIAN:
+ summon = new Guardian(properties, summoner, false);
+ break;
+ case UNIT_MASK_PUPPET:
+ summon = new Puppet(properties, summoner);
+ break;
+ case UNIT_MASK_TOTEM:
+ summon = new Totem(properties, summoner);
+ break;
+ case UNIT_MASK_MINION:
+ summon = new Minion(properties, summoner, false);
+ break;
+ }
+
+ float x, y, z, o;
+ pos.GetPosition(x, y, z, o);
+ CalculatePassengerPosition(x, y, z, &o);
+
+ if (!summon->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, phase, entry, vehId, team, x, y, z, o))
+ {
+ delete summon;
+ return NULL;
+ }
+
+ summon->SetUInt32Value(UNIT_CREATED_BY_SPELL, spellId);
+
+ summon->SetTransport(this);
+ summon->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT);
+ summon->m_movementInfo.transport.guid = GetGUID();
+ summon->m_movementInfo.transport.pos.Relocate(pos);
+ summon->Relocate(x, y, z, o);
+ summon->SetHomePosition(x, y, z, o);
+ summon->SetTransportHomePosition(pos);
+
+ /// @HACK - transport models are not added to map's dynamic LoS calculations
+ /// because the current GameObjectModel cannot be moved without recreating
+ summon->AddUnitState(UNIT_STATE_IGNORE_PATHFINDING);
+
+ summon->InitStats(duration);
+
+ if (!map->AddToMap<Creature>(summon))
+ {
+ delete summon;
+ return NULL;
+ }
+
+ _staticPassengers.insert(summon);
+
+ summon->InitSummon();
+ summon->SetTempSummonType(summonType);
+
+ return summon;
+}
+
void Transport::UpdatePosition(float x, float y, float z, float o)
{
bool newActive = GetMap()->IsGridLoaded(x, y);
Relocate(x, y, z, o);
+ UpdateModelPosition();
UpdatePassengerPositions(_passengers);
@@ -450,12 +595,16 @@ bool Transport::TeleportTransport(uint32 newMapid, float x, float y, float z, fl
if (!obj->ToPlayer()->TeleportTo(newMapid, destX, destY, destZ, destO, TELE_TO_NOT_LEAVE_TRANSPORT))
_passengers.erase(obj);
break;
+ case TYPEID_DYNAMICOBJECT:
+ obj->AddObjectToRemoveList();
+ break;
default:
break;
}
}
Relocate(x, y, z, o);
+ UpdateModelPosition();
GetMap()->AddToMap<Transport>(this);
return true;
}
@@ -518,6 +667,9 @@ void Transport::UpdatePassengerPositions(std::set<WorldObject*>& passengers)
case TYPEID_GAMEOBJECT:
GetMap()->GameObjectRelocation(passenger->ToGameObject(), x, y, z, o, false);
break;
+ case TYPEID_DYNAMICOBJECT:
+ GetMap()->DynamicObjectRelocation(passenger->ToDynObject(), x, y, z, o);
+ break;
default:
break;
}
diff --git a/src/server/game/Entities/Transport/Transport.h b/src/server/game/Entities/Transport/Transport.h
index 55f4daddecc..398356c4980 100644
--- a/src/server/game/Entities/Transport/Transport.h
+++ b/src/server/game/Entities/Transport/Transport.h
@@ -34,9 +34,11 @@ class Transport : public GameObject, public TransportBase
~Transport();
bool Create(uint32 guidlow, uint32 entry, uint32 mapid, float x, float y, float z, float ang, uint32 animprogress);
- void Update(uint32 diff);
+ void CleanupsBeforeDelete(bool finalCleanup = true) OVERRIDE;
- void BuildUpdate(UpdateDataMapType& data_map);
+ void Update(uint32 diff) OVERRIDE;
+
+ void BuildUpdate(UpdateDataMapType& data_map) OVERRIDE;
void AddPassenger(WorldObject* passenger);
void RemovePassenger(WorldObject* passenger);
@@ -45,14 +47,32 @@ class Transport : public GameObject, public TransportBase
Creature* CreateNPCPassenger(uint32 guid, CreatureData const* data);
GameObject* CreateGOPassenger(uint32 guid, GameObjectData const* data);
+ /**
+ * @fn bool Transport::SummonPassenger(uint64, Position const&, TempSummonType, SummonPropertiesEntry const*, uint32, Unit*, uint32, uint32)
+ *
+ * @brief Temporarily summons a creature as passenger on this transport.
+ *
+ * @param entry Id of the creature from creature_template table
+ * @param pos Initial position of the creature (transport offsets)
+ * @param summonType
+ * @param properties
+ * @param duration Determines how long the creauture will exist in world depending on @summonType (in milliseconds)
+ * @param summoner Summoner of the creature (for AI purposes)
+ * @param spellId
+ * @param vehId If set, this value overrides vehicle id from creature_template that the creature will use
+ *
+ * @return Summoned creature.
+ */
+ TempSummon* SummonPassenger(uint32 entry, Position const& pos, TempSummonType summonType, SummonPropertiesEntry const* properties = NULL, uint32 duration = 0, Unit* summoner = NULL, uint32 spellId = 0, uint32 vehId = 0);
+
/// This method transforms supplied transport offsets into global coordinates
- void CalculatePassengerPosition(float& x, float& y, float& z, float* o /*= NULL*/) const
+ void CalculatePassengerPosition(float& x, float& y, float& z, float* o = NULL) const OVERRIDE
{
TransportBase::CalculatePassengerPosition(x, y, z, o, GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation());
}
/// This method transforms supplied global coordinates into local offsets
- void CalculatePassengerOffset(float& x, float& y, float& z, float* o /*= NULL*/) const
+ void CalculatePassengerOffset(float& x, float& y, float& z, float* o = NULL) const OVERRIDE
{
TransportBase::CalculatePassengerOffset(x, y, z, o, GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation());
}
diff --git a/src/server/game/Entities/Unit/StatSystem.cpp b/src/server/game/Entities/Unit/StatSystem.cpp
index 3afa6b016d2..04136221d0d 100644
--- a/src/server/game/Entities/Unit/StatSystem.cpp
+++ b/src/server/game/Entities/Unit/StatSystem.cpp
@@ -1149,7 +1149,7 @@ bool Guardian::UpdateStats(Stats stat)
if (itr != ToPet()->m_spells.end()) // If pet has Wild Hunt
{
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itr->first); // Then get the SpellProto and add the dummy effect value
+ SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(itr->first); // Then get the SpellProto and add the dummy effect value
AddPct(mod, spellInfo->Effects[EFFECT_0].CalcValue());
}
}
@@ -1318,7 +1318,7 @@ void Guardian::UpdateAttackPowerAndDamage(bool ranged)
if (itr != ToPet()->m_spells.end()) // If pet has Wild Hunt
{
- SpellInfo const* sProto = sSpellMgr->GetSpellInfo(itr->first); // Then get the SpellProto and add the dummy effect value
+ SpellInfo const* sProto = sSpellMgr->EnsureSpellInfo(itr->first); // Then get the SpellProto and add the dummy effect value
mod += CalculatePct(1.0f, sProto->Effects[1].CalcValue());
}
}
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 52565a2eaa5..379cecc3db7 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -1286,10 +1286,8 @@ void Unit::CalculateMeleeDamage(Unit* victim, uint32 damage, CalcDamageInfo* dam
damageInfo->HitInfo |= HITINFO_AFFECTS_VICTIM;
int32 resilienceReduction = damageInfo->damage;
- if (attackType != RANGED_ATTACK)
- ApplyResilience(victim, NULL, &resilienceReduction, (damageInfo->hitOutCome == MELEE_HIT_CRIT), CR_CRIT_TAKEN_MELEE);
- else
- ApplyResilience(victim, NULL, &resilienceReduction, (damageInfo->hitOutCome == MELEE_HIT_CRIT), CR_CRIT_TAKEN_RANGED);
+ // attackType is checked already for BASE_ATTACK or OFF_ATTACK so it can't be RANGED_ATTACK here
+ ApplyResilience(victim, NULL, &resilienceReduction, (damageInfo->hitOutCome == MELEE_HIT_CRIT), CR_CRIT_TAKEN_MELEE);
resilienceReduction = damageInfo->damage - resilienceReduction;
damageInfo->damage -= resilienceReduction;
damageInfo->cleanDamage += resilienceReduction;
@@ -12990,6 +12988,8 @@ float Unit::GetSpellMaxRangeForTarget(Unit const* target, SpellInfo const* spell
return 0;
if (spellInfo->RangeEntry->maxRangeFriend == spellInfo->RangeEntry->maxRangeHostile)
return spellInfo->GetMaxRange();
+ if (target == NULL)
+ return spellInfo->GetMaxRange(true);
return spellInfo->GetMaxRange(!IsHostileTo(target));
}
@@ -17288,7 +17288,12 @@ bool CharmInfo::IsCommandFollow()
void CharmInfo::SaveStayPosition()
{
//! At this point a new spline destination is enabled because of Unit::StopMoving()
- G3D::Vector3 const stayPos = _unit->movespline->FinalDestination();
+ G3D::Vector3 stayPos = _unit->movespline->FinalDestination();
+
+ if (_unit->movespline->onTransport)
+ if (TransportBase* transport = _unit->GetDirectTransport())
+ transport->CalculatePassengerPosition(stayPos.x, stayPos.y, stayPos.z);
+
_stayX = stayPos.x;
_stayY = stayPos.y;
_stayZ = stayPos.z;
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index 751bfcb8126..6b6d844472a 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -513,6 +513,12 @@ enum UnitState
UNIT_STATE_CHASE_MOVE = 0x04000000,
UNIT_STATE_FOLLOW_MOVE = 0x08000000,
UNIT_STATE_IGNORE_PATHFINDING = 0x10000000, // do not use pathfinding in any MovementGenerator
+ UNIT_STATE_ALL_STATE_SUPPORTED = UNIT_STATE_DIED | UNIT_STATE_MELEE_ATTACKING | UNIT_STATE_STUNNED | UNIT_STATE_ROAMING | UNIT_STATE_CHASE
+ | UNIT_STATE_FLEEING | UNIT_STATE_IN_FLIGHT | UNIT_STATE_FOLLOW | UNIT_STATE_ROOT | UNIT_STATE_CONFUSED
+ | UNIT_STATE_DISTRACTED | UNIT_STATE_ISOLATED | UNIT_STATE_ATTACK_PLAYER | UNIT_STATE_CASTING
+ | UNIT_STATE_POSSESSED | UNIT_STATE_CHARGING | UNIT_STATE_JUMPING | UNIT_STATE_MOVE | UNIT_STATE_ROTATING
+ | UNIT_STATE_EVADE | UNIT_STATE_ROAMING_MOVE | UNIT_STATE_CONFUSED_MOVE | UNIT_STATE_FLEEING_MOVE
+ | UNIT_STATE_CHASE_MOVE | UNIT_STATE_FOLLOW_MOVE | UNIT_STATE_IGNORE_PATHFINDING,
UNIT_STATE_UNATTACKABLE = UNIT_STATE_IN_FLIGHT,
// for real move using movegen check and stop (except unstoppable flight)
UNIT_STATE_MOVING = UNIT_STATE_ROAMING_MOVE | UNIT_STATE_CONFUSED_MOVE | UNIT_STATE_FLEEING_MOVE | UNIT_STATE_CHASE_MOVE | UNIT_STATE_FOLLOW_MOVE,
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index 48e4411e035..8784e2ca4e7 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -1087,6 +1087,11 @@ void ObjectMgr::LoadEquipmentTemplates()
}
uint8 id = fields[1].GetUInt8();
+ if (!id)
+ {
+ TC_LOG_ERROR("sql.sql", "Creature equipment template with id 0 found for creature %u, skipped.", entry);
+ continue;
+ }
EquipmentInfo& equipmentInfo = _equipmentInfoStore[entry][id];
@@ -1437,6 +1442,7 @@ bool ObjectMgr::SetCreatureLinkedRespawn(uint32 guidLow, uint32 linkedGuidLow)
return false;
const CreatureData* master = GetCreatureData(guidLow);
+ ASSERT(master);
uint64 guid = MAKE_NEW_GUID(guidLow, master->id, HIGHGUID_UNIT);
if (!linkedGuidLow) // we're removing the linking
diff --git a/src/server/game/Handlers/AddonHandler.cpp b/src/server/game/Handlers/AddonHandler.cpp
index 3c9a66bedb5..806cbd1c7fc 100644
--- a/src/server/game/Handlers/AddonHandler.cpp
+++ b/src/server/game/Handlers/AddonHandler.cpp
@@ -49,7 +49,7 @@ bool AddonHandler::BuildAddonPacket(WorldPacket* source, WorldPacket* target)
AddOnPacked.resize(AddonRealSize); // resize target for zlib action
- if (!uncompress(AddOnPacked.contents(), &AddonRealSize, source->contents() + CurrentPosition, source->size() - CurrentPosition)!= Z_OK)
+ if (uncompress(AddOnPacked.contents(), &AddonRealSize, source->contents() + CurrentPosition, source->size() - CurrentPosition) == Z_OK)
{
target->Initialize(SMSG_ADDON_INFO);
diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp
index 60f4fb09c28..4fd1d516d31 100644
--- a/src/server/game/Handlers/MiscHandler.cpp
+++ b/src/server/game/Handlers/MiscHandler.cpp
@@ -97,9 +97,19 @@ void WorldSession::HandleGossipSelectOptionOpcode(WorldPacket& recvData)
recvData >> guid >> menuId >> gossipListId;
+ if (!_player->PlayerTalkClass->GetGossipMenu().GetItem(gossipListId))
+ {
+ recvData.rfinish();
+ return;
+ }
+
if (_player->PlayerTalkClass->IsGossipOptionCoded(gossipListId))
recvData >> code;
+ // Prevent cheating on C++ scripted menus
+ if (_player->PlayerTalkClass->GetGossipMenu().GetSenderGUID() != guid)
+ return;
+
Creature* unit = NULL;
GameObject* go = NULL;
if (IS_CRE_OR_VEH_GUID(guid))
@@ -151,7 +161,8 @@ void WorldSession::HandleGossipSelectOptionOpcode(WorldPacket& recvData)
else
{
go->AI()->GossipSelectCode(_player, menuId, gossipListId, code.c_str());
- sScriptMgr->OnGossipSelectCode(_player, go, _player->PlayerTalkClass->GetGossipOptionSender(gossipListId), _player->PlayerTalkClass->GetGossipOptionAction(gossipListId), code.c_str());
+ if (!sScriptMgr->OnGossipSelectCode(_player, go, _player->PlayerTalkClass->GetGossipOptionSender(gossipListId), _player->PlayerTalkClass->GetGossipOptionAction(gossipListId), code.c_str()))
+ _player->OnGossipSelect(go, gossipListId, menuId);
}
}
else
diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp
index 21e282cfcf4..8dc393c5f85 100644
--- a/src/server/game/Maps/Map.cpp
+++ b/src/server/game/Maps/Map.cpp
@@ -217,13 +217,13 @@ void Map::DeleteStateMachine()
}
Map::Map(uint32 id, time_t expiry, uint32 InstanceId, uint8 SpawnMode, Map* _parent):
-_creatureToMoveLock(false), _gameObjectsToMoveLock(false),
+_creatureToMoveLock(false), _gameObjectsToMoveLock(false), _dynamicObjectsToMoveLock(false),
i_mapEntry(sMapStore.LookupEntry(id)), i_spawnMode(SpawnMode), i_InstanceId(InstanceId),
m_unloadTimer(0), m_VisibleDistance(DEFAULT_VISIBILITY_DISTANCE),
m_VisibilityNotifyPeriod(DEFAULT_VISIBILITY_NOTIFY_PERIOD),
m_activeNonPlayersIter(m_activeNonPlayers.end()), _transportsUpdateIter(_transports.end()),
i_gridExpiry(expiry),
-i_scriptLock(false)
+i_scriptLock(false), _defaultLight(GetDefaultMapLight(id))
{
m_parentMap = (_parent ? _parent : this);
for (unsigned int idx=0; idx < MAX_NUMBER_OF_GRIDS; ++idx)
@@ -281,6 +281,15 @@ void Map::AddToGrid(GameObject* obj, Cell const& cell)
obj->SetCurrentCell(cell);
}
+template<>
+void Map::AddToGrid(DynamicObject* obj, Cell const& cell)
+{
+ NGridType* grid = getNGrid(cell.GridX(), cell.GridY());
+ grid->GetGridType(cell.CellX(), cell.CellY()).AddGridObject(obj);
+
+ obj->SetCurrentCell(cell);
+}
+
template<class T>
void Map::SwitchGridContainers(T* /*obj*/, bool /*on*/) { }
@@ -468,6 +477,7 @@ bool Map::AddPlayerToMap(Player* player)
SendInitSelf(player);
SendInitTransports(player);
+ SendZoneDynamicInfo(player);
player->m_clientGUIDs.clear();
player->UpdateObjectVisibility(false);
@@ -944,6 +954,7 @@ void Map::GameObjectRelocation(GameObject* go, float x, float y, float z, float
else
{
go->Relocate(x, y, z, orientation);
+ go->UpdateModelPosition();
go->UpdateObjectVisibility(false);
RemoveGameObjectFromMoveList(go);
}
@@ -953,6 +964,38 @@ void Map::GameObjectRelocation(GameObject* go, float x, float y, float z, float
ASSERT(integrity_check == old_cell);
}
+void Map::DynamicObjectRelocation(DynamicObject* dynObj, float x, float y, float z, float orientation)
+{
+ Cell integrity_check(dynObj->GetPositionX(), dynObj->GetPositionY());
+ Cell old_cell = dynObj->GetCurrentCell();
+
+ ASSERT(integrity_check == old_cell);
+ Cell new_cell(x, y);
+
+ if (!getNGrid(new_cell.GridX(), new_cell.GridY()))
+ return;
+
+ // delay creature move for grid/cell to grid/cell moves
+ if (old_cell.DiffCell(new_cell) || old_cell.DiffGrid(new_cell))
+ {
+#ifdef TRINITY_DEBUG
+ TC_LOG_DEBUG("maps", "GameObject (GUID: %u) added to moving list from grid[%u, %u]cell[%u, %u] to grid[%u, %u]cell[%u, %u].", dynObj->GetGUIDLow(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.GridX(), new_cell.GridY(), new_cell.CellX(), new_cell.CellY());
+#endif
+ AddDynamicObjectToMoveList(dynObj, x, y, z, orientation);
+ // in diffcell/diffgrid case notifiers called at finishing move dynObj in Map::MoveAllGameObjectsInMoveList
+ }
+ else
+ {
+ dynObj->Relocate(x, y, z, orientation);
+ dynObj->UpdateObjectVisibility(false);
+ RemoveDynamicObjectFromMoveList(dynObj);
+ }
+
+ old_cell = dynObj->GetCurrentCell();
+ integrity_check = Cell(dynObj->GetPositionX(), dynObj->GetPositionY());
+ ASSERT(integrity_check == old_cell);
+}
+
void Map::AddCreatureToMoveList(Creature* c, float x, float y, float z, float ang)
{
if (_creatureToMoveLock) //can this happen?
@@ -991,6 +1034,25 @@ void Map::RemoveGameObjectFromMoveList(GameObject* go)
go->_moveState = MAP_OBJECT_CELL_MOVE_INACTIVE;
}
+void Map::AddDynamicObjectToMoveList(DynamicObject* dynObj, float x, float y, float z, float ang)
+{
+ if (_dynamicObjectsToMoveLock) //can this happen?
+ return;
+
+ if (dynObj->_moveState == MAP_OBJECT_CELL_MOVE_NONE)
+ _dynamicObjectsToMove.push_back(dynObj);
+ dynObj->SetNewCellPosition(x, y, z, ang);
+}
+
+void Map::RemoveDynamicObjectFromMoveList(DynamicObject* dynObj)
+{
+ if (_dynamicObjectsToMoveLock) //can this happen?
+ return;
+
+ if (dynObj->_moveState == MAP_OBJECT_CELL_MOVE_ACTIVE)
+ dynObj->_moveState = MAP_OBJECT_CELL_MOVE_INACTIVE;
+}
+
void Map::MoveAllCreaturesInMoveList()
{
_creatureToMoveLock = true;
@@ -1071,6 +1133,7 @@ void Map::MoveAllGameObjectsInMoveList()
{
// update pos
go->Relocate(go->_newPosition);
+ go->UpdateModelPosition();
go->UpdateObjectVisibility(false);
}
else
@@ -1091,6 +1154,44 @@ void Map::MoveAllGameObjectsInMoveList()
_gameObjectsToMoveLock = false;
}
+void Map::MoveAllDynamicObjectsInMoveList()
+{
+ _dynamicObjectsToMoveLock = true;
+ for (std::vector<DynamicObject*>::iterator itr = _dynamicObjectsToMove.begin(); itr != _dynamicObjectsToMove.end(); ++itr)
+ {
+ DynamicObject* dynObj = *itr;
+ if (dynObj->FindMap() != this) //transport is teleported to another map
+ continue;
+
+ if (dynObj->_moveState != MAP_OBJECT_CELL_MOVE_ACTIVE)
+ {
+ dynObj->_moveState = MAP_OBJECT_CELL_MOVE_NONE;
+ continue;
+ }
+
+ dynObj->_moveState = MAP_OBJECT_CELL_MOVE_NONE;
+ if (!dynObj->IsInWorld())
+ continue;
+
+ // do move or do move to respawn or remove creature if previous all fail
+ if (DynamicObjectCellRelocation(dynObj, Cell(dynObj->_newPosition.m_positionX, dynObj->_newPosition.m_positionY)))
+ {
+ // update pos
+ dynObj->Relocate(dynObj->_newPosition);
+ dynObj->UpdateObjectVisibility(false);
+ }
+ else
+ {
+#ifdef TRINITY_DEBUG
+ TC_LOG_DEBUG("maps", "DynamicObject (GUID: %u) cannot be moved to unloaded grid.", dynObj->GetGUIDLow());
+#endif
+ }
+ }
+
+ _dynamicObjectsToMove.clear();
+ _dynamicObjectsToMoveLock = false;
+}
+
bool Map::CreatureCellRelocation(Creature* c, Cell new_cell)
{
Cell const& old_cell = c->GetCurrentCell();
@@ -1213,6 +1314,67 @@ bool Map::GameObjectCellRelocation(GameObject* go, Cell new_cell)
return false;
}
+bool Map::DynamicObjectCellRelocation(DynamicObject* go, Cell new_cell)
+{
+ Cell const& old_cell = go->GetCurrentCell();
+ if (!old_cell.DiffGrid(new_cell)) // in same grid
+ {
+ // if in same cell then none do
+ if (old_cell.DiffCell(new_cell))
+ {
+ #ifdef TRINITY_DEBUG
+ TC_LOG_DEBUG("maps", "DynamicObject (GUID: %u) moved in grid[%u, %u] from cell[%u, %u] to cell[%u, %u].", go->GetGUIDLow(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.CellX(), new_cell.CellY());
+ #endif
+
+ go->RemoveFromGrid();
+ AddToGrid(go, new_cell);
+ }
+ else
+ {
+ #ifdef TRINITY_DEBUG
+ TC_LOG_DEBUG("maps", "DynamicObject (GUID: %u) moved in same grid[%u, %u]cell[%u, %u].", go->GetGUIDLow(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY());
+ #endif
+ }
+
+ return true;
+ }
+
+ // in diff. grids but active GameObject
+ if (go->isActiveObject())
+ {
+ EnsureGridLoadedForActiveObject(new_cell, go);
+
+ #ifdef TRINITY_DEBUG
+ TC_LOG_DEBUG("maps", "Active DynamicObject (GUID: %u) moved from grid[%u, %u]cell[%u, %u] to grid[%u, %u]cell[%u, %u].", go->GetGUIDLow(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.GridX(), new_cell.GridY(), new_cell.CellX(), new_cell.CellY());
+ #endif
+
+ go->RemoveFromGrid();
+ AddToGrid(go, new_cell);
+
+ return true;
+ }
+
+ // in diff. loaded grid normal GameObject
+ if (IsGridLoaded(GridCoord(new_cell.GridX(), new_cell.GridY())))
+ {
+ #ifdef TRINITY_DEBUG
+ TC_LOG_DEBUG("maps", "DynamicObject (GUID: %u) moved from grid[%u, %u]cell[%u, %u] to grid[%u, %u]cell[%u, %u].", go->GetGUIDLow(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.GridX(), new_cell.GridY(), new_cell.CellX(), new_cell.CellY());
+ #endif
+
+ go->RemoveFromGrid();
+ EnsureGridCreated(GridCoord(new_cell.GridX(), new_cell.GridY()));
+ AddToGrid(go, new_cell);
+
+ return true;
+ }
+
+ // fail to move: normal GameObject attempt move to unloaded grid
+ #ifdef TRINITY_DEBUG
+ TC_LOG_DEBUG("maps", "DynamicObject (GUID: %u) attempted to move from grid[%u, %u]cell[%u, %u] to unloaded grid[%u, %u]cell[%u, %u].", go->GetGUIDLow(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.GridX(), new_cell.GridY(), new_cell.CellX(), new_cell.CellY());
+ #endif
+ return false;
+}
+
bool Map::CreatureRespawnRelocation(Creature* c, bool diffGridOnly)
{
float resp_x, resp_y, resp_z, resp_o;
@@ -2490,7 +2652,10 @@ void Map::RemoveAllObjectsInRemoveList()
RemoveFromMap((DynamicObject*)obj, true);
break;
case TYPEID_GAMEOBJECT:
- RemoveFromMap((GameObject*)obj, true);
+ if (Transport* transport = obj->ToGameObject()->ToTransport())
+ RemoveFromMap(transport, true);
+ else
+ RemoveFromMap(obj->ToGameObject(), true);
break;
case TYPEID_UNIT:
// in case triggered sequence some spell can continue casting after prev CleanupsBeforeDelete call
@@ -3274,3 +3439,103 @@ time_t Map::GetLinkedRespawnTime(uint64 guid) const
return time_t(0);
}
+void Map::SendZoneDynamicInfo(Player* player)
+{
+ uint32 zoneId = GetZoneId(player->GetPositionX(), player->GetPositionY(), player->GetPositionZ());
+ ZoneDynamicInfoMap::const_iterator itr = _zoneDynamicInfo.find(zoneId);
+ if (itr == _zoneDynamicInfo.end())
+ return;
+
+ if (uint32 music = itr->second.MusicId)
+ {
+ WorldPacket data(SMSG_PLAY_MUSIC, 4);
+ data << uint32(music);
+ player->SendDirectMessage(&data);
+ }
+
+ if (uint32 weather = itr->second.WeatherId)
+ {
+ WorldPacket data(SMSG_WEATHER, 4 + 4 + 1);
+ data << uint32(weather);
+ data << float(itr->second.WeatherGrade);
+ data << uint8(0);
+ player->SendDirectMessage(&data);
+ }
+
+ if (uint32 overrideLight = itr->second.OverrideLightId)
+ {
+ WorldPacket data(SMSG_OVERRIDE_LIGHT, 4 + 4 + 1);
+ data << uint32(_defaultLight);
+ data << uint32(overrideLight);
+ data << uint32(itr->second.LightFadeInTime);
+ player->SendDirectMessage(&data);
+ }
+}
+
+void Map::SetZoneMusic(uint32 zoneId, uint32 musicId)
+{
+ if (_zoneDynamicInfo.find(zoneId) == _zoneDynamicInfo.end())
+ _zoneDynamicInfo.insert(ZoneDynamicInfoMap::value_type(zoneId, ZoneDynamicInfo()));
+
+ _zoneDynamicInfo[zoneId].MusicId = musicId;
+
+ Map::PlayerList const& players = GetPlayers();
+ if (!players.isEmpty())
+ {
+ WorldPacket data(SMSG_PLAY_MUSIC, 4);
+ data << uint32(musicId);
+
+ for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
+ if (Player* player = itr->GetSource())
+ if (player->GetZoneId() == zoneId)
+ player->SendDirectMessage(&data);
+ }
+}
+
+void Map::SetZoneWeather(uint32 zoneId, uint32 weatherId, float weatherGrade)
+{
+ if (_zoneDynamicInfo.find(zoneId) == _zoneDynamicInfo.end())
+ _zoneDynamicInfo.insert(ZoneDynamicInfoMap::value_type(zoneId, ZoneDynamicInfo()));
+
+ ZoneDynamicInfo& info = _zoneDynamicInfo[zoneId];
+ info.WeatherId = weatherId;
+ info.WeatherGrade = weatherGrade;
+ Map::PlayerList const& players = GetPlayers();
+
+ if (!players.isEmpty())
+ {
+ WorldPacket data(SMSG_WEATHER, 4 + 4 + 1);
+ data << uint32(weatherId);
+ data << float(weatherGrade);
+ data << uint8(0);
+
+ for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
+ if (Player* player = itr->GetSource())
+ if (player->GetZoneId() == zoneId)
+ player->SendDirectMessage(&data);
+ }
+}
+
+void Map::SetZoneOverrideLight(uint32 zoneId, uint32 lightId, uint32 fadeInTime)
+{
+ if (_zoneDynamicInfo.find(zoneId) == _zoneDynamicInfo.end())
+ _zoneDynamicInfo.insert(ZoneDynamicInfoMap::value_type(zoneId, ZoneDynamicInfo()));
+
+ ZoneDynamicInfo& info = _zoneDynamicInfo[zoneId];
+ info.OverrideLightId = lightId;
+ info.LightFadeInTime = fadeInTime;
+ Map::PlayerList const& players = GetPlayers();
+
+ if (!players.isEmpty())
+ {
+ WorldPacket data(SMSG_OVERRIDE_LIGHT, 4 + 4 + 1);
+ data << uint32(_defaultLight);
+ data << uint32(lightId);
+ data << uint32(fadeInTime);
+
+ for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
+ if (Player* player = itr->GetSource())
+ if (player->GetZoneId() == zoneId)
+ player->SendDirectMessage(&data);
+ }
+}
diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h
index 8e7886dc5d2..4daeebe43d1 100644
--- a/src/server/game/Maps/Map.h
+++ b/src/server/game/Maps/Map.h
@@ -229,6 +229,18 @@ enum LevelRequirementVsMode
LEVELREQUIREMENT_HEROIC = 70
};
+struct ZoneDynamicInfo
+{
+ ZoneDynamicInfo() : MusicId(0), WeatherId(0), WeatherGrade(0.0f),
+ OverrideLightId(0), LightFadeInTime(0) { }
+
+ uint32 MusicId;
+ uint32 WeatherId;
+ float WeatherGrade;
+ uint32 OverrideLightId;
+ uint32 LightFadeInTime;
+};
+
#if defined(__GNUC__)
#pragma pack()
#else
@@ -243,6 +255,8 @@ enum LevelRequirementVsMode
typedef std::map<uint32/*leaderDBGUID*/, CreatureGroup*> CreatureGroupHolderType;
+typedef UNORDERED_MAP<uint32 /*zoneId*/, ZoneDynamicInfo> ZoneDynamicInfoMap;
+
class Map : public GridRefManager<NGridType>
{
friend class MapReference;
@@ -280,6 +294,7 @@ class Map : public GridRefManager<NGridType>
void PlayerRelocation(Player*, float x, float y, float z, float orientation);
void CreatureRelocation(Creature* creature, float x, float y, float z, float ang, bool respawnRelocationOnFail = true);
void GameObjectRelocation(GameObject* go, float x, float y, float z, float orientation, bool respawnRelocationOnFail = true);
+ void DynamicObjectRelocation(DynamicObject* go, float x, float y, float z, float orientation);
template<class T, class CONTAINER> void Visit(const Cell& cell, TypeContainerVisitor<T, CONTAINER> &visitor);
@@ -353,6 +368,7 @@ class Map : public GridRefManager<NGridType>
void MoveAllCreaturesInMoveList();
void MoveAllGameObjectsInMoveList();
+ void MoveAllDynamicObjectsInMoveList();
void RemoveAllObjectsInRemoveList();
virtual void RemoveAllPlayers();
@@ -488,6 +504,11 @@ class Map : public GridRefManager<NGridType>
void SendInitTransports(Player* player);
void SendRemoveTransports(Player* player);
+ void SendZoneDynamicInfo(Player* player);
+
+ void SetZoneMusic(uint32 zoneId, uint32 musicId);
+ void SetZoneWeather(uint32 zoneId, uint32 weatherId, float weatherGrade);
+ void SetZoneOverrideLight(uint32 zoneId, uint32 lightId, uint32 fadeInTime);
private:
void LoadMapAndVMap(int gx, int gy);
@@ -502,12 +523,15 @@ class Map : public GridRefManager<NGridType>
bool CreatureCellRelocation(Creature* creature, Cell new_cell);
bool GameObjectCellRelocation(GameObject* go, Cell new_cell);
+ bool DynamicObjectCellRelocation(DynamicObject* go, Cell new_cell);
template<class T> void InitializeObject(T* obj);
void AddCreatureToMoveList(Creature* c, float x, float y, float z, float ang);
void RemoveCreatureFromMoveList(Creature* c);
void AddGameObjectToMoveList(GameObject* go, float x, float y, float z, float ang);
void RemoveGameObjectFromMoveList(GameObject* go);
+ void AddDynamicObjectToMoveList(DynamicObject* go, float x, float y, float z, float ang);
+ void RemoveDynamicObjectFromMoveList(DynamicObject* go);
bool _creatureToMoveLock;
std::vector<Creature*> _creaturesToMove;
@@ -515,6 +539,9 @@ class Map : public GridRefManager<NGridType>
bool _gameObjectsToMoveLock;
std::vector<GameObject*> _gameObjectsToMove;
+ bool _dynamicObjectsToMoveLock;
+ std::vector<DynamicObject*> _dynamicObjectsToMove;
+
bool IsGridLoaded(const GridCoord &) const;
void EnsureGridCreated(const GridCoord &);
void EnsureGridCreated_i(const GridCoord &);
@@ -626,6 +653,9 @@ class Map : public GridRefManager<NGridType>
UNORDERED_MAP<uint32 /*dbGUID*/, time_t> _creatureRespawnTimes;
UNORDERED_MAP<uint32 /*dbGUID*/, time_t> _goRespawnTimes;
+
+ ZoneDynamicInfoMap _zoneDynamicInfo;
+ uint32 _defaultLight;
};
enum InstanceResetMethod
diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp
index f1656592000..28e58c87323 100644
--- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp
@@ -25,6 +25,7 @@
#include "MoveSplineInit.h"
#include "MoveSpline.h"
#include "Player.h"
+#include "VehicleDefines.h"
template<class T, typename D>
void TargetedMovementGeneratorMedium<T, D>::_setTargetLocation(T* owner, bool updateDestination)
@@ -154,6 +155,9 @@ bool TargetedMovementGeneratorMedium<T, D>::DoUpdate(T* owner, uint32 time_diff)
//More distance let have better performance, less distance let have more sensitive reaction at target move.
float allowed_dist = owner->GetCombatReach() + sWorld->getRate(RATE_TARGET_POS_RECALCULATION_RANGE);
G3D::Vector3 dest = owner->movespline->FinalDestination();
+ if (owner->movespline->onTransport)
+ if (TransportBase* transport = owner->GetDirectTransport())
+ transport->CalculatePassengerPosition(dest.x, dest.y, dest.z);
if (owner->GetTypeId() == TYPEID_UNIT && owner->ToCreature()->CanFly())
targetMoved = !i_target->IsWithinDist3d(dest.x, dest.y, dest.z, allowed_dist);
diff --git a/src/server/game/Movement/Spline/MovementTypedefs.h b/src/server/game/Movement/Spline/MovementTypedefs.h
index ffc19f10454..22850036b61 100644
--- a/src/server/game/Movement/Spline/MovementTypedefs.h
+++ b/src/server/game/Movement/Spline/MovementTypedefs.h
@@ -47,12 +47,6 @@ namespace Movement
float computeFallTime(float path_length, bool isSafeFall);
float computeFallElevation(float t_passed, bool isSafeFall, float start_velocity = 0.0f);
-#ifndef static_assert
- #define CONCAT(x, y) CONCAT1 (x, y)
- #define CONCAT1(x, y) x##y
- #define static_assert(expr, msg) typedef char CONCAT(static_assert_failed_at_line_, __LINE__) [(expr) ? 1 : -1]
-#endif
-
template<class T, T limit>
class counter
{
diff --git a/src/server/game/Movement/Spline/Spline.h b/src/server/game/Movement/Spline/Spline.h
index 1444b2872d1..6e8a5a0281d 100644
--- a/src/server/game/Movement/Spline/Spline.h
+++ b/src/server/game/Movement/Spline/Spline.h
@@ -56,7 +56,7 @@ protected:
// client's value is 20, blizzs use 2-3 steps to compute length
STEPS_PER_SEGMENT = 3
};
- static_assert(STEPS_PER_SEGMENT > 0, "shouldn't be lesser than 1");
+ static_assert(STEPS_PER_SEGMENT > 0, "STEPS_PER_SEGMENT shouldn't be lesser than 1");
protected:
void EvaluateLinear(index_type, float, Vector3&) const;
diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp
index 8da94ef2852..7365d592a62 100644
--- a/src/server/game/Scripting/ScriptLoader.cpp
+++ b/src/server/game/Scripting/ScriptLoader.cpp
@@ -522,6 +522,7 @@ void AddSC_boss_falric();
void AddSC_boss_marwyn();
void AddSC_boss_lord_marrowgar(); // Icecrown Citadel
void AddSC_boss_lady_deathwhisper();
+void AddSC_boss_icecrown_gunship_battle();
void AddSC_boss_deathbringer_saurfang();
void AddSC_boss_festergut();
void AddSC_boss_rotface();
@@ -1361,6 +1362,7 @@ void AddNorthrendScripts()
AddSC_boss_marwyn();
AddSC_boss_lord_marrowgar(); // Icecrown Citadel
AddSC_boss_lady_deathwhisper();
+ AddSC_boss_icecrown_gunship_battle();
AddSC_boss_deathbringer_saurfang();
AddSC_boss_festergut();
AddSC_boss_rotface();
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index b7aabcc7589..4ed742167a5 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -4772,7 +4772,7 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool
uint32 spellId = 24659;
if (apply && caster)
{
- SpellInfo const* spell = sSpellMgr->GetSpellInfo(spellId);
+ SpellInfo const* spell = sSpellMgr->EnsureSpellInfo(spellId);
for (uint32 i = 0; i < spell->StackAmount; ++i)
caster->CastSpell(target, spell->Id, true, NULL, NULL, GetCasterGUID());
@@ -4787,7 +4787,7 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool
uint32 spellId = 24662;
if (apply && caster)
{
- SpellInfo const* spell = sSpellMgr->GetSpellInfo(spellId);
+ SpellInfo const* spell = sSpellMgr->EnsureSpellInfo(spellId);
for (uint32 i = 0; i < spell->StackAmount; ++i)
caster->CastSpell(target, spell->Id, true, NULL, NULL, GetCasterGUID());
break;
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index 8b88ec9af92..124c1c21332 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -953,7 +953,7 @@ void Spell::SelectImplicitChannelTargets(SpellEffIndex effIndex, SpellImplicitTa
case TARGET_UNIT_CHANNEL_TARGET:
{
WorldObject* target = ObjectAccessor::GetUnit(*m_caster, m_originalCaster->GetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT));
- CallScriptObjectTargetSelectHandlers(target, effIndex);
+ CallScriptObjectTargetSelectHandlers(target, effIndex, targetType);
// unit target may be no longer avalible - teleported out of map for example
if (target && target->ToUnit())
AddUnitTarget(target->ToUnit(), 1 << effIndex);
@@ -966,7 +966,7 @@ void Spell::SelectImplicitChannelTargets(SpellEffIndex effIndex, SpellImplicitTa
m_targets.SetDst(channeledSpell->m_targets);
else if (WorldObject* target = ObjectAccessor::GetWorldObject(*m_caster, m_originalCaster->GetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT)))
{
- CallScriptObjectTargetSelectHandlers(target, effIndex);
+ CallScriptObjectTargetSelectHandlers(target, effIndex, targetType);
if (target)
m_targets.SetDst(*target);
}
@@ -1047,17 +1047,34 @@ void Spell::SelectImplicitNearbyTargets(SpellEffIndex effIndex, SpellImplicitTar
return;
}
- CallScriptObjectTargetSelectHandlers(target, effIndex);
+ CallScriptObjectTargetSelectHandlers(target, effIndex, targetType);
+ if (!target)
+ {
+ TC_LOG_DEBUG("spells", "Spell::SelectImplicitNearbyTargets: OnObjectTargetSelect script hook for spell Id %u set NULL target, effect %u", m_spellInfo->Id, effIndex);
+ return;
+ }
switch (targetType.GetObjectType())
{
case TARGET_OBJECT_TYPE_UNIT:
+ {
if (Unit* unitTarget = target->ToUnit())
AddUnitTarget(unitTarget, effMask, true, false);
+ else
+ {
+ TC_LOG_DEBUG("spells", "Spell::SelectImplicitNearbyTargets: OnObjectTargetSelect script hook for spell Id %u set object of wrong type, expected unit, got %s, effect %u", m_spellInfo->Id, GetLogNameForGuid(target->GetGUID()), effMask);
+ return;
+ }
break;
+ }
case TARGET_OBJECT_TYPE_GOBJ:
if (GameObject* gobjTarget = target->ToGameObject())
AddGOTarget(gobjTarget, effMask);
+ else
+ {
+ TC_LOG_DEBUG("spells", "Spell::SelectImplicitNearbyTargets: OnObjectTargetSelect script hook for spell Id %u set object of wrong type, expected gameobject, got %s, effect %u", m_spellInfo->Id, GetLogNameForGuid(target->GetGUID()), effMask);
+ return;
+ }
break;
case TARGET_OBJECT_TYPE_DEST:
m_targets.SetDst(*target);
@@ -1090,7 +1107,7 @@ void Spell::SelectImplicitConeTargets(SpellEffIndex effIndex, SpellImplicitTarge
Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellConeTargetCheck> searcher(m_caster, targets, check, containerTypeMask);
SearchTargets<Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellConeTargetCheck> >(searcher, containerTypeMask, m_caster, m_caster, radius);
- CallScriptObjectAreaTargetSelectHandlers(targets, effIndex);
+ CallScriptObjectAreaTargetSelectHandlers(targets, effIndex, targetType);
if (!targets.empty())
{
@@ -1171,7 +1188,7 @@ void Spell::SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTarge
float radius = m_spellInfo->Effects[effIndex].CalcRadius(m_caster) * m_spellValue->RadiusMod;
SearchAreaTargets(targets, radius, center, referer, targetType.GetObjectType(), targetType.GetCheckType(), m_spellInfo->Effects[effIndex].ImplicitTargetConditions);
- CallScriptObjectAreaTargetSelectHandlers(targets, effIndex);
+ CallScriptObjectAreaTargetSelectHandlers(targets, effIndex, targetType);
if (!targets.empty())
{
@@ -1280,7 +1297,7 @@ void Spell::SelectImplicitCasterDestTargets(SpellEffIndex effIndex, SpellImplici
}
}
- CallScriptDestinationTargetSelectHandlers(dest, effIndex);
+ CallScriptDestinationTargetSelectHandlers(dest, effIndex, targetType);
m_targets.SetDst(dest);
}
@@ -1313,7 +1330,7 @@ void Spell::SelectImplicitTargetDestTargets(SpellEffIndex effIndex, SpellImplici
}
}
- CallScriptDestinationTargetSelectHandlers(dest, effIndex);
+ CallScriptDestinationTargetSelectHandlers(dest, effIndex, targetType);
m_targets.SetDst(dest);
}
@@ -1352,7 +1369,7 @@ void Spell::SelectImplicitDestDestTargets(SpellEffIndex effIndex, SpellImplicitT
}
}
- CallScriptDestinationTargetSelectHandlers(dest, effIndex);
+ CallScriptDestinationTargetSelectHandlers(dest, effIndex, targetType);
m_targets.ModDst(dest);
}
@@ -1395,7 +1412,7 @@ void Spell::SelectImplicitCasterObjectTargets(SpellEffIndex effIndex, SpellImpli
break;
}
- CallScriptObjectTargetSelectHandlers(target, effIndex);
+ CallScriptObjectTargetSelectHandlers(target, effIndex, targetType);
if (target && target->ToUnit())
AddUnitTarget(target->ToUnit(), 1 << effIndex, checkIfValid);
@@ -1407,7 +1424,7 @@ void Spell::SelectImplicitTargetObjectTargets(SpellEffIndex effIndex, SpellImpli
WorldObject* target = m_targets.GetObjectTarget();
- CallScriptObjectTargetSelectHandlers(target, effIndex);
+ CallScriptObjectTargetSelectHandlers(target, effIndex, targetType);
if (target)
{
@@ -1442,7 +1459,7 @@ void Spell::SelectImplicitChainTargets(SpellEffIndex effIndex, SpellImplicitTarg
, m_spellInfo->Effects[effIndex].ImplicitTargetConditions, targetType.GetTarget() == TARGET_UNIT_TARGET_CHAINHEAL_ALLY);
// Chain primary target is added earlier
- CallScriptObjectAreaTargetSelectHandlers(targets, effIndex);
+ CallScriptObjectAreaTargetSelectHandlers(targets, effIndex, targetType);
for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr)
if (Unit* unitTarget = (*itr)->ToUnit())
@@ -1596,7 +1613,7 @@ void Spell::SelectImplicitTrajTargets(SpellEffIndex effIndex)
SpellDestination dest(*m_targets.GetDst());
dest.Relocate(trajDst);
- CallScriptDestinationTargetSelectHandlers(dest, effIndex);
+ CallScriptDestinationTargetSelectHandlers(dest, effIndex, SpellImplicitTargetInfo(TARGET_DEST_TRAJ));
m_targets.ModDst(dest);
}
}
@@ -1613,7 +1630,7 @@ void Spell::SelectEffectTypeImplicitTargets(uint8 effIndex)
{
WorldObject* target = ObjectAccessor::FindPlayer(m_caster->GetTarget());
- CallScriptObjectTargetSelectHandlers(target, SpellEffIndex(effIndex));
+ CallScriptObjectTargetSelectHandlers(target, SpellEffIndex(effIndex), SpellImplicitTargetInfo());
if (target && target->ToPlayer())
AddUnitTarget(target->ToUnit(), 1 << effIndex, false);
@@ -1673,7 +1690,7 @@ void Spell::SelectEffectTypeImplicitTargets(uint8 effIndex)
break;
}
- CallScriptObjectTargetSelectHandlers(target, SpellEffIndex(effIndex));
+ CallScriptObjectTargetSelectHandlers(target, SpellEffIndex(effIndex), SpellImplicitTargetInfo());
if (target)
{
@@ -5120,6 +5137,7 @@ SpellCastResult Spell::CheckCast(bool strict)
case SUMMON_CATEGORY_PET:
if (m_caster->GetPetGUID())
return SPELL_FAILED_ALREADY_HAVE_SUMMON;
+ // intentional missing break, check both GetPetGUID() and GetCharmGUID for SUMMON_CATEGORY_PET
case SUMMON_CATEGORY_PUPPET:
if (m_caster->GetCharmGUID())
return SPELL_FAILED_ALREADY_HAVE_CHARM;
@@ -6967,42 +6985,42 @@ void Spell::CallScriptAfterHitHandlers()
}
}
-void Spell::CallScriptObjectAreaTargetSelectHandlers(std::list<WorldObject*>& targets, SpellEffIndex effIndex)
+void Spell::CallScriptObjectAreaTargetSelectHandlers(std::list<WorldObject*>& targets, SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType)
{
for (std::list<SpellScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
(*scritr)->_PrepareScriptCall(SPELL_SCRIPT_HOOK_OBJECT_AREA_TARGET_SELECT);
std::list<SpellScript::ObjectAreaTargetSelectHandler>::iterator hookItrEnd = (*scritr)->OnObjectAreaTargetSelect.end(), hookItr = (*scritr)->OnObjectAreaTargetSelect.begin();
for (; hookItr != hookItrEnd; ++hookItr)
- if ((*hookItr).IsEffectAffected(m_spellInfo, effIndex))
- (*hookItr).Call(*scritr, targets);
+ if (hookItr->IsEffectAffected(m_spellInfo, effIndex) && targetType.GetTarget() == hookItr->GetTarget())
+ hookItr->Call(*scritr, targets);
(*scritr)->_FinishScriptCall();
}
}
-void Spell::CallScriptObjectTargetSelectHandlers(WorldObject*& target, SpellEffIndex effIndex)
+void Spell::CallScriptObjectTargetSelectHandlers(WorldObject*& target, SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType)
{
for (std::list<SpellScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
(*scritr)->_PrepareScriptCall(SPELL_SCRIPT_HOOK_OBJECT_TARGET_SELECT);
std::list<SpellScript::ObjectTargetSelectHandler>::iterator hookItrEnd = (*scritr)->OnObjectTargetSelect.end(), hookItr = (*scritr)->OnObjectTargetSelect.begin();
for (; hookItr != hookItrEnd; ++hookItr)
- if ((*hookItr).IsEffectAffected(m_spellInfo, effIndex))
- (*hookItr).Call(*scritr, target);
+ if (hookItr->IsEffectAffected(m_spellInfo, effIndex) && targetType.GetTarget() == hookItr->GetTarget())
+ hookItr->Call(*scritr, target);
(*scritr)->_FinishScriptCall();
}
}
-void Spell::CallScriptDestinationTargetSelectHandlers(SpellDestination& target, SpellEffIndex effIndex)
+void Spell::CallScriptDestinationTargetSelectHandlers(SpellDestination& target, SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType)
{
for (std::list<SpellScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
(*scritr)->_PrepareScriptCall(SPELL_SCRIPT_HOOK_DESTINATION_TARGET_SELECT);
std::list<SpellScript::DestinationTargetSelectHandler>::iterator hookItrEnd = (*scritr)->OnDestinationTargetSelect.end(), hookItr = (*scritr)->OnDestinationTargetSelect.begin();
for (; hookItr != hookItrEnd; ++hookItr)
- if (hookItr->IsEffectAffected(m_spellInfo, effIndex))
+ if (hookItr->IsEffectAffected(m_spellInfo, effIndex) && targetType.GetTarget() == hookItr->GetTarget())
hookItr->Call(*scritr, target);
(*scritr)->_FinishScriptCall();
diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h
index 031311f2749..e87e2c2085a 100644
--- a/src/server/game/Spells/Spell.h
+++ b/src/server/game/Spells/Spell.h
@@ -639,9 +639,9 @@ class Spell
void CallScriptBeforeHitHandlers();
void CallScriptOnHitHandlers();
void CallScriptAfterHitHandlers();
- void CallScriptObjectAreaTargetSelectHandlers(std::list<WorldObject*>& targets, SpellEffIndex effIndex);
- void CallScriptObjectTargetSelectHandlers(WorldObject*& target, SpellEffIndex effIndex);
- void CallScriptDestinationTargetSelectHandlers(SpellDestination& target, SpellEffIndex effIndex);
+ void CallScriptObjectAreaTargetSelectHandlers(std::list<WorldObject*>& targets, SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType);
+ void CallScriptObjectTargetSelectHandlers(WorldObject*& target, SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType);
+ void CallScriptDestinationTargetSelectHandlers(SpellDestination& target, SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType);
bool CheckScriptEffectImplicitTargets(uint32 effIndex, uint32 effIndexToCheck);
std::list<SpellScript*> m_loadedScripts;
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index 73d3c39148a..609c9ba05be 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -1829,7 +1829,7 @@ void Spell::EffectEnergize(SpellEffIndex effIndex)
sSpellMgr->GetSetOfSpellsInSpellGroup(SPELL_GROUP_ELIXIR_BATTLE, avalibleElixirs);
for (std::set<uint32>::iterator itr = avalibleElixirs.begin(); itr != avalibleElixirs.end();)
{
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(*itr);
+ SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(*itr);
if (spellInfo->SpellLevel < m_spellInfo->SpellLevel || spellInfo->SpellLevel > unitTarget->getLevel())
avalibleElixirs.erase(itr++);
else if (sSpellMgr->IsSpellMemberOfSpellGroup(*itr, SPELL_GROUP_ELIXIR_SHATTRATH))
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index 93f264d2d61..009b9861eb6 100644
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -3384,6 +3384,15 @@ void SpellMgr::LoadSpellInfoCorrections()
case 71169: // Shadow's Fate
spellInfo->AttributesEx3 |= SPELL_ATTR3_STACK_FOR_DIFF_CASTERS;
break;
+ case 72347: // Lock Players and Tap Chest
+ spellInfo->AttributesEx3 &= ~SPELL_ATTR3_NO_INITIAL_AGGRO;
+ break;
+ case 73843: // Award Reputation - Boss Kill
+ case 73844: // Award Reputation - Boss Kill
+ case 73845: // Award Reputation - Boss Kill
+ case 73846: // Award Reputation - Boss Kill
+ spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_50000_YARDS); // 50000yd
+ break;
case 72378: // Blood Nova (Deathbringer Saurfang)
case 73058: // Blood Nova (Deathbringer Saurfang)
spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS);
diff --git a/src/server/game/Spells/SpellMgr.h b/src/server/game/Spells/SpellMgr.h
index 01fe7708db2..76d59bd1e85 100644
--- a/src/server/game/Spells/SpellMgr.h
+++ b/src/server/game/Spells/SpellMgr.h
@@ -690,6 +690,14 @@ class SpellMgr
// SpellInfo object management
SpellInfo const* GetSpellInfo(uint32 spellId) const { return spellId < GetSpellInfoStoreSize() ? mSpellInfoMap[spellId] : NULL; }
+ // Use this only with 100% valid spellIds
+ SpellInfo const* EnsureSpellInfo(uint32 spellId) const
+ {
+ ASSERT(spellId < GetSpellInfoStoreSize());
+ SpellInfo const* spellInfo = mSpellInfoMap[spellId];
+ ASSERT(spellInfo);
+ return spellInfo;
+ }
uint32 GetSpellInfoStoreSize() const { return mSpellInfoMap.size(); }
private:
diff --git a/src/server/game/Spells/SpellScript.h b/src/server/game/Spells/SpellScript.h
index 6378a8bed9b..75a191a9801 100644
--- a/src/server/game/Spells/SpellScript.h
+++ b/src/server/game/Spells/SpellScript.h
@@ -208,6 +208,7 @@ class SpellScript : public _SpellScript
TargetHook(uint8 _effectIndex, uint16 _targetType, bool _area, bool _dest);
bool CheckEffect(SpellInfo const* spellInfo, uint8 effIndex);
std::string ToString();
+ uint16 GetTarget() const { return targetType; }
protected:
uint16 targetType;
bool area;
diff --git a/src/server/game/Tickets/TicketMgr.cpp b/src/server/game/Tickets/TicketMgr.cpp
index 43c9ba80e24..b9ecfffb8c3 100644
--- a/src/server/game/Tickets/TicketMgr.cpp
+++ b/src/server/game/Tickets/TicketMgr.cpp
@@ -36,7 +36,9 @@ GmTicket::GmTicket() : _id(0), _playerGuid(0), _posX(0), _posY(0), _posZ(0), _ma
_closedBy(0), _assignedTo(0), _completed(false), _escalatedStatus(TICKET_UNASSIGNED), _viewed(false),
_needResponse(false), _needMoreHelp(false) { }
-GmTicket::GmTicket(Player* player) : _createTime(time(NULL)), _lastModifiedTime(time(NULL)), _closedBy(0), _assignedTo(0), _completed(false), _escalatedStatus(TICKET_UNASSIGNED), _viewed(false), _needResponse(false), _needMoreHelp(false)
+GmTicket::GmTicket(Player* player) : _posX(0), _posY(0), _posZ(0), _mapId(0), _createTime(time(NULL)), _lastModifiedTime(time(NULL)),
+ _closedBy(0), _assignedTo(0), _completed(false), _escalatedStatus(TICKET_UNASSIGNED), _viewed(false),
+ _needResponse(false), _needMoreHelp(false)
{
_id = sTicketMgr->GenerateTicketId();
_playerName = player->GetName();
diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp
index d0c21168c80..cae2f5e511d 100644
--- a/src/server/scripts/Commands/cs_misc.cpp
+++ b/src/server/scripts/Commands/cs_misc.cpp
@@ -1018,7 +1018,6 @@ public:
int32 area = GetAreaFlagByAreaID(atoi((char*)args));
int32 offset = area / 32;
- uint32 val = uint32((1 << (area % 32)));
if (area<0 || offset >= PLAYER_EXPLORED_ZONES_SIZE)
{
@@ -1027,6 +1026,7 @@ public:
return false;
}
+ uint32 val = uint32((1 << (area % 32)));
uint32 currFields = playerTarget->GetUInt32Value(PLAYER_EXPLORED_ZONES_1 + offset);
playerTarget->SetUInt32Value(PLAYER_EXPLORED_ZONES_1 + offset, uint32((currFields | val)));
@@ -1049,7 +1049,6 @@ public:
int32 area = GetAreaFlagByAreaID(atoi((char*)args));
int32 offset = area / 32;
- uint32 val = uint32((1 << (area % 32)));
if (area < 0 || offset >= PLAYER_EXPLORED_ZONES_SIZE)
{
@@ -1058,6 +1057,7 @@ public:
return false;
}
+ uint32 val = uint32((1 << (area % 32)));
uint32 currFields = playerTarget->GetUInt32Value(PLAYER_EXPLORED_ZONES_1 + offset);
playerTarget->SetUInt32Value(PLAYER_EXPLORED_ZONES_1 + offset, uint32((currFields ^ val)));
diff --git a/src/server/scripts/EasternKingdoms/AlteracValley/boss_balinda.cpp b/src/server/scripts/EasternKingdoms/AlteracValley/boss_balinda.cpp
index ab135a2fd78..0b031f54ea0 100644
--- a/src/server/scripts/EasternKingdoms/AlteracValley/boss_balinda.cpp
+++ b/src/server/scripts/EasternKingdoms/AlteracValley/boss_balinda.cpp
@@ -50,7 +50,12 @@ public:
struct npc_water_elementalAI : public ScriptedAI
{
- npc_water_elementalAI(Creature* creature) : ScriptedAI(creature) { }
+ npc_water_elementalAI(Creature* creature) : ScriptedAI(creature)
+ {
+ waterBoltTimer = 3 * IN_MILLISECONDS;
+ resetTimer = 5 * IN_MILLISECONDS;
+ balindaGUID = 0;
+ }
uint32 waterBoltTimer;
uint64 balindaGUID;
diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_rend_blackhand.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_rend_blackhand.cpp
index 8989a8065dc..0cb96a519e7 100644
--- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_rend_blackhand.cpp
+++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_rend_blackhand.cpp
@@ -164,7 +164,12 @@ public:
struct boss_rend_blackhandAI : public BossAI
{
- boss_rend_blackhandAI(Creature* creature) : BossAI(creature, DATA_WARCHIEF_REND_BLACKHAND) { }
+ boss_rend_blackhandAI(Creature* creature) : BossAI(creature, DATA_WARCHIEF_REND_BLACKHAND)
+ {
+ gythEvent = false;
+ victorGUID = 0;
+ portcullisGUID = 0;
+ }
void Reset() OVERRIDE
{
diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/instance_blackwing_lair.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/instance_blackwing_lair.cpp
index 39d2a6d87d5..560f2e2e995 100644
--- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/instance_blackwing_lair.cpp
+++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/instance_blackwing_lair.cpp
@@ -56,6 +56,28 @@ public:
{
instance_blackwing_lair_InstanceMapScript(Map* map) : InstanceScript(map)
{
+ // Razorgore
+ EggCount = 0;
+ EggEvent = 0;
+ RazorgoreTheUntamedGUID = 0;
+ RazorgoreDoorGUID = 0;
+ // Vaelastrasz the Corrupt
+ VaelastraszTheCorruptGUID = 0;
+ VaelastraszDoorGUID = 0;
+ // Broodlord Lashlayer
+ BroodlordLashlayerGUID = 0;
+ BroodlordDoorGUID = 0;
+ // 3 Dragons
+ FiremawGUID = 0;
+ EbonrocGUID = 0;
+ FlamegorGUID = 0;
+ ChrommagusDoorGUID = 0;
+ // Chormaggus
+ ChromaggusGUID = 0;
+ NefarianDoorGUID = 0;
+ // Nefarian
+ LordVictorNefariusGUID = 0;
+ NefarianGUID = 0;
SetBossNumber(EncounterCount);
}
diff --git a/src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp b/src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp
index 241ac85faa2..b5c3bdd86d4 100644
--- a/src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp
+++ b/src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp
@@ -584,10 +584,13 @@ public:
arca->MonsterYell(SAY_DIALOG_ARCANAGOS_8, LANG_UNIVERSAL, NULL);
return 5000;
case 12:
- arca->GetMotionMaster()->MovePoint(0, -11010.82f, -1761.18f, 156.47f);
- arca->setActive(true);
- arca->InterruptNonMeleeSpells(true);
- arca->SetSpeed(MOVE_FLIGHT, 2.0f);
+ if (arca)
+ {
+ arca->GetMotionMaster()->MovePoint(0, -11010.82f, -1761.18f, 156.47f);
+ arca->setActive(true);
+ arca->InterruptNonMeleeSpells(true);
+ arca->SetSpeed(MOVE_FLIGHT, 2.0f);
+ }
return 10000;
case 13:
me->MonsterYell(SAY_DIALOG_MEDIVH_9, LANG_UNIVERSAL, NULL);
diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp
index 31219e18121..ad87b2d8d3d 100644
--- a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp
+++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp
@@ -787,7 +787,11 @@ public:
struct npc_pulsing_pumpkinAI : public ScriptedAI
{
- npc_pulsing_pumpkinAI(Creature* creature) : ScriptedAI(creature) { }
+ npc_pulsing_pumpkinAI(Creature* creature) : ScriptedAI(creature)
+ {
+ sprouted = false;
+ debuffGUID = 0;
+ }
bool sprouted;
uint64 debuffGUID;
diff --git a/src/server/scripts/EasternKingdoms/Stratholme/instance_stratholme.cpp b/src/server/scripts/EasternKingdoms/Stratholme/instance_stratholme.cpp
index d8518085b26..9ceaf8cb85b 100644
--- a/src/server/scripts/EasternKingdoms/Stratholme/instance_stratholme.cpp
+++ b/src/server/scripts/EasternKingdoms/Stratholme/instance_stratholme.cpp
@@ -310,6 +310,15 @@ class instance_stratholme : public InstanceMapScript
{
HandleGameObject(ziggurat4GUID, false);
HandleGameObject(ziggurat5GUID, false);
+ }
+ if (data == DONE || data == NOT_STARTED)
+ {
+ HandleGameObject(ziggurat4GUID, true);
+ HandleGameObject(ziggurat5GUID, true);
+ }
+ if (data == DONE)
+ {
+ HandleGameObject(portGauntletGUID, true);
if (GetData(TYPE_BARON_RUN) == IN_PROGRESS)
{
DoRemoveAurasDueToSpellOnPlayers(SPELL_BARON_ULTIMATUM);
@@ -318,18 +327,13 @@ class instance_stratholme : public InstanceMapScript
for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
if (Player* player = itr->GetSource())
if (player->GetQuestStatus(QUEST_DEAD_MAN_PLEA) == QUEST_STATUS_INCOMPLETE)
+ {
player->AreaExploredOrEventHappens(QUEST_DEAD_MAN_PLEA);
-
+ player->KilledMonsterCredit(NPC_YSIDA);
+ }
SetData(TYPE_BARON_RUN, DONE);
}
}
- if (data == DONE || data == NOT_STARTED)
- {
- HandleGameObject(ziggurat4GUID, true);
- HandleGameObject(ziggurat5GUID, true);
- }
- if (data == DONE)
- HandleGameObject(portGauntletGUID, true);
EncounterState[5] = data;
break;
case TYPE_SH_AELMAR:
diff --git a/src/server/scripts/EasternKingdoms/ZulAman/boss_halazzi.cpp b/src/server/scripts/EasternKingdoms/ZulAman/boss_halazzi.cpp
index 4e354b47be5..0c8eb663c9a 100644
--- a/src/server/scripts/EasternKingdoms/ZulAman/boss_halazzi.cpp
+++ b/src/server/scripts/EasternKingdoms/ZulAman/boss_halazzi.cpp
@@ -16,35 +16,11 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/* ScriptData
-SDName: boss_Halazzi
-SD%Complete: 80
-SDComment:
-SDCategory: Zul'Aman
-EndScriptData */
-
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "zulaman.h"
#include "SpellInfo.h"
-#define YELL_AGGRO "Get on your knees and bow to da fang and claw!"
-#define SOUND_AGGRO 12020
-#define YELL_SABER_ONE "You gonna leave in pieces!"
-#define YELL_SABER_TWO "Me gonna carve ya now!"
-#define YELL_SPLIT "Me gonna carve ya now!"
-#define SOUND_SPLIT 12021
-#define YELL_MERGE "Spirit, come back to me!"
-#define SOUND_MERGE 12022
-#define YELL_KILL_ONE "You cant fight the power!"
-#define SOUND_KILL_ONE 12026
-#define YELL_KILL_TWO "You gonna fail!"
-#define SOUND_KILL_TWO 12027
-#define YELL_DEATH "Chaga... choka'jinn."
-#define SOUND_DEATH 12028
-#define YELL_BERSERK "Whatch you be doing? Pissin' yourselves..."
-#define SOUND_BERSERK 12025
-
enum Spells
{
SPELL_DUAL_WIELD = 29651,
@@ -78,23 +54,32 @@ enum PhaseHalazzi
PHASE_ENRAGE = 5
};
+enum Yells
+{
+ SAY_AGGRO = 0,
+ SAY_SABER = 1,
+ SAY_SPLIT = 2,
+ SAY_MERGE = 3,
+ SAY_KILL = 4,
+ SAY_DEATH = 5,
+ SAY_BERSERK = 6
+};
+
class boss_halazzi : public CreatureScript
{
public:
-
- boss_halazzi()
- : CreatureScript("boss_halazzi")
- {
- }
+ boss_halazzi() : CreatureScript("boss_halazzi") { }
struct boss_halazziAI : public ScriptedAI
{
- boss_halazziAI(Creature* creature) : ScriptedAI(creature)
+ boss_halazziAI(Creature* creature) : ScriptedAI(creature), summons(me)
{
instance = creature->GetInstanceScript();
}
InstanceScript* instance;
+ SummonList summons;
+ PhaseHalazzi Phase;
uint32 FrenzyTimer;
uint32 SaberlashTimer;
@@ -102,16 +87,14 @@ class boss_halazzi : public CreatureScript
uint32 TotemTimer;
uint32 CheckTimer;
uint32 BerserkTimer;
-
uint32 TransformCount;
- PhaseHalazzi Phase;
-
uint64 LynxGUID;
void Reset() OVERRIDE
{
instance->SetData(DATA_HALAZZIEVENT, NOT_STARTED);
+ summons.DespawnAll();
LynxGUID = 0;
TransformCount = 0;
@@ -127,10 +110,7 @@ class boss_halazzi : public CreatureScript
void EnterCombat(Unit* /*who*/) OVERRIDE
{
instance->SetData(DATA_HALAZZIEVENT, IN_PROGRESS);
-
- me->MonsterYell(YELL_AGGRO, LANG_UNIVERSAL, NULL);
- DoPlaySoundToSet(me, SOUND_AGGRO);
-
+ Talk(SAY_AGGRO);
EnterPhase(PHASE_LYNX);
}
@@ -139,6 +119,7 @@ class boss_halazzi : public CreatureScript
summon->AI()->AttackStart(me->GetVictim());
if (summon->GetEntry() == NPC_SPIRIT_LYNX)
LynxGUID = summon->GetGUID();
+ summons.Summon(summon);
}
void DamageTaken(Unit* /*done_by*/, uint32 &damage) OVERRIDE
@@ -155,7 +136,8 @@ class boss_halazzi : public CreatureScript
void AttackStart(Unit* who) OVERRIDE
{
- if (Phase != PHASE_MERGE) ScriptedAI::AttackStart(who);
+ if (Phase != PHASE_MERGE)
+ ScriptedAI::AttackStart(who);
}
void EnterPhase(PhaseHalazzi NextPhase)
@@ -180,8 +162,7 @@ class boss_halazzi : public CreatureScript
TotemTimer = 12000;
break;
case PHASE_SPLIT:
- me->MonsterYell(YELL_SPLIT, LANG_UNIVERSAL, NULL);
- DoPlaySoundToSet(me, SOUND_SPLIT);
+ Talk(SAY_SPLIT);
DoCast(me, SPELL_TRANSFORM_SPLIT, true);
break;
case PHASE_HUMAN:
@@ -195,8 +176,7 @@ class boss_halazzi : public CreatureScript
case PHASE_MERGE:
if (Unit* pLynx = Unit::GetUnit(*me, LynxGUID))
{
- me->MonsterYell(YELL_MERGE, LANG_UNIVERSAL, NULL);
- DoPlaySoundToSet(me, SOUND_MERGE);
+ Talk(SAY_MERGE);
pLynx->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
pLynx->GetMotionMaster()->Clear();
pLynx->GetMotionMaster()->MoveFollow(me, 0, 0);
@@ -211,15 +191,14 @@ class boss_halazzi : public CreatureScript
Phase = NextPhase;
}
- void UpdateAI(uint32 diff) OVERRIDE
+ void UpdateAI(uint32 diff) OVERRIDE
{
if (!UpdateVictim())
return;
if (BerserkTimer <= diff)
{
- me->MonsterYell(YELL_BERSERK, LANG_UNIVERSAL, NULL);
- DoPlaySoundToSet(me, SOUND_BERSERK);
+ Talk(SAY_BERSERK);
DoCast(me, SPELL_BERSERK, true);
BerserkTimer = 60000;
} else BerserkTimer -= diff;
@@ -313,28 +292,18 @@ class boss_halazzi : public CreatureScript
DoMeleeAttackIfReady();
}
- void KilledUnit(Unit* /*victim*/) OVERRIDE
+ void KilledUnit(Unit* victim) OVERRIDE
{
- switch (urand(0, 1))
- {
- case 0:
- me->MonsterYell(YELL_KILL_ONE, LANG_UNIVERSAL, NULL);
- DoPlaySoundToSet(me, SOUND_KILL_ONE);
- break;
-
- case 1:
- me->MonsterYell(YELL_KILL_TWO, LANG_UNIVERSAL, NULL);
- DoPlaySoundToSet(me, SOUND_KILL_TWO);
- break;
- }
+ if (victim->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ Talk(SAY_KILL);
}
void JustDied(Unit* /*killer*/) OVERRIDE
{
instance->SetData(DATA_HALAZZIEVENT, DONE);
-
- me->MonsterYell(YELL_DEATH, LANG_UNIVERSAL, NULL);
- DoPlaySoundToSet(me, SOUND_DEATH);
+ Talk(SAY_DEATH);
}
};
@@ -348,11 +317,7 @@ class boss_halazzi : public CreatureScript
class npc_halazzi_lynx : public CreatureScript
{
public:
-
- npc_halazzi_lynx()
- : CreatureScript("npc_halazzi_lynx")
- {
- }
+ npc_halazzi_lynx() : CreatureScript("npc_halazzi_lynx") { }
struct npc_halazzi_lynxAI : public ScriptedAI
{
@@ -414,5 +379,3 @@ void AddSC_boss_halazzi()
new boss_halazzi();
new npc_halazzi_lynx();
}
-
-
diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_jeklik.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_jeklik.cpp
index 336599f2cc5..5d4bafb5f94 100644
--- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_jeklik.cpp
+++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_jeklik.cpp
@@ -152,9 +152,11 @@ class boss_jeklik : public CreatureScript
case EVENT_SONIC_BURST:
DoCastVictim(SPELL_SONICBURST);
events.ScheduleEvent(EVENT_SONIC_BURST, urand(8000, 13000), 0, PHASE_ONE);
+ break;
case EVENT_SCREECH:
DoCastVictim(SPELL_SCREECH);
events.ScheduleEvent(EVENT_SCREECH, urand(18000, 26000), 0, PHASE_ONE);
+ break;
case EVENT_SPAWN_BATS:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
for (uint8 i = 0; i < 6; ++i)
diff --git a/src/server/scripts/EasternKingdoms/zone_blasted_lands.cpp b/src/server/scripts/EasternKingdoms/zone_blasted_lands.cpp
index 3fcd3c093b7..bc09983fee1 100644
--- a/src/server/scripts/EasternKingdoms/zone_blasted_lands.cpp
+++ b/src/server/scripts/EasternKingdoms/zone_blasted_lands.cpp
@@ -17,11 +17,7 @@
/*
Blasted_Lands
-Quest support: 3628. Teleporter to Rise of the Defiler.
-*/
-
-/*
-npc_deathly_usher
+Quest support: 3628.
*/
#include "ScriptMgr.h"
@@ -31,10 +27,6 @@ npc_deathly_usher
#include "Player.h"
#include "Group.h"
-/*######
-## npc_deathly_usher
-######*/
-
enum DeathlyUsher
{
SPELL_TELEPORT_SINGLE = 12885,
@@ -42,28 +34,6 @@ enum DeathlyUsher
SPELL_TELEPORT_GROUP = 27686
};
-class npc_deathly_usher : public CreatureScript
-{
-public:
- npc_deathly_usher() : CreatureScript("npc_deathly_usher") { }
-
- struct npc_deathly_usherAI : public ScriptedAI
- {
- npc_deathly_usherAI(Creature* creature) : ScriptedAI(creature) { }
-
- void sGossipSelect(Player* player, uint32 /*sender*/, uint32 /*action*/) OVERRIDE
- {
- player->CLOSE_GOSSIP_MENU();
- me->CastSpell(player, SPELL_TELEPORT_GROUP, true);
- }
- };
-
- CreatureAI* GetAI(Creature* creature) const OVERRIDE
- {
- return new npc_deathly_usherAI(creature);
- }
-};
-
/*#####
# spell_razelikh_teleport_group
#####*/
@@ -113,6 +83,5 @@ class spell_razelikh_teleport_group : public SpellScriptLoader
void AddSC_blasted_lands()
{
- new npc_deathly_usher();
new spell_razelikh_teleport_group();
}
diff --git a/src/server/scripts/EasternKingdoms/zone_westfall.cpp b/src/server/scripts/EasternKingdoms/zone_westfall.cpp
index 350ceead706..d01806028c6 100644
--- a/src/server/scripts/EasternKingdoms/zone_westfall.cpp
+++ b/src/server/scripts/EasternKingdoms/zone_westfall.cpp
@@ -19,13 +19,12 @@
/* ScriptData
SDName: Westfall
SD%Complete: 90
-SDComment: Quest support: 155, 1651
+SDComment: Quest support: 1651
SDCategory: Westfall
EndScriptData */
/* ContentData
npc_daphne_stilwell
-npc_defias_traitor
EndContentData */
#include "ScriptMgr.h"
@@ -202,79 +201,7 @@ public:
};
};
-/*######
-## npc_defias_traitor
-######*/
-enum DefiasSays
-{
- SAY_START = 0,
- SAY_PROGRESS = 1,
- SAY_END = 2,
- SAY_AGGRO = 3
-};
-
-
-#define QUEST_DEFIAS_BROTHERHOOD 155
-
-class npc_defias_traitor : public CreatureScript
-{
-public:
- npc_defias_traitor() : CreatureScript("npc_defias_traitor") { }
-
- bool OnQuestAccept(Player* player, Creature* creature, Quest const* quest) OVERRIDE
- {
- if (quest->GetQuestId() == QUEST_DEFIAS_BROTHERHOOD)
- {
- if (npc_escortAI* pEscortAI = CAST_AI(npc_defias_traitor::npc_defias_traitorAI, creature->AI()))
- pEscortAI->Start(true, true, player->GetGUID());
-
- creature->AI()->Talk(SAY_START, player);
- }
-
- return true;
- }
-
- CreatureAI* GetAI(Creature* creature) const OVERRIDE
- {
- return new npc_defias_traitorAI(creature);
- }
-
- struct npc_defias_traitorAI : public npc_escortAI
- {
- npc_defias_traitorAI(Creature* creature) : npc_escortAI(creature) { Reset(); }
-
- void WaypointReached(uint32 waypointId) OVERRIDE
- {
- Player* player = GetPlayerForEscort();
- if (!player)
- return;
-
- switch (waypointId)
- {
- case 35:
- SetRun(false);
- break;
- case 36:
- Talk(SAY_PROGRESS, player);
- break;
- case 44:
- Talk(SAY_END, player);
- player->GroupEventHappens(QUEST_DEFIAS_BROTHERHOOD, me);
- break;
- }
- }
-
- void EnterCombat(Unit* who) OVERRIDE
- {
- Talk(SAY_AGGRO, who);
- }
-
- void Reset() OVERRIDE { }
- };
-};
-
void AddSC_westfall()
{
new npc_daphne_stilwell();
- new npc_defias_traitor();
}
diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_anetheron.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_anetheron.cpp
index c7803f23e1b..e5ddcd1c2ef 100644
--- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_anetheron.cpp
+++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_anetheron.cpp
@@ -185,6 +185,8 @@ public:
{
npc_towering_infernalAI(Creature* creature) : ScriptedAI(creature)
{
+ ImmolationTimer = 5000;
+ CheckTimer = 5000;
instance = creature->GetInstanceScript();
AnetheronGUID = instance->GetData64(DATA_ANETHERON);
}
diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_azgalor.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_azgalor.cpp
index 4decce7482f..16002b59f1a 100644
--- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_azgalor.cpp
+++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_azgalor.cpp
@@ -191,6 +191,9 @@ public:
{
npc_lesser_doomguardAI(Creature* creature) : hyjal_trashAI(creature)
{
+ CrippleTimer = 50000;
+ WarstompTimer = 10000;
+ CheckTimer = 5000;
instance = creature->GetInstanceScript();
AzgalorGUID = instance->GetData64(DATA_AZGALOR);
}
diff --git a/src/server/scripts/Kalimdor/RazorfenDowns/boss_glutton.cpp b/src/server/scripts/Kalimdor/RazorfenDowns/boss_glutton.cpp
index 830c3fed382..1e0d481249d 100644
--- a/src/server/scripts/Kalimdor/RazorfenDowns/boss_glutton.cpp
+++ b/src/server/scripts/Kalimdor/RazorfenDowns/boss_glutton.cpp
@@ -42,6 +42,7 @@ public:
{
boss_gluttonAI(Creature* creature) : BossAI(creature, DATA_GLUTTON)
{
+ hp50 = false;
hp15 = false;
}
diff --git a/src/server/scripts/Kalimdor/RazorfenDowns/razorfen_downs.cpp b/src/server/scripts/Kalimdor/RazorfenDowns/razorfen_downs.cpp
index b9605794074..f1d8e1b67e8 100644
--- a/src/server/scripts/Kalimdor/RazorfenDowns/razorfen_downs.cpp
+++ b/src/server/scripts/Kalimdor/RazorfenDowns/razorfen_downs.cpp
@@ -158,6 +158,8 @@ public:
{
instance = creature->GetInstanceScript();
eventInProgress = false;
+ channeling = false;
+ eventProgress = 0;
spawnerCount = 0;
}
diff --git a/src/server/scripts/Kalimdor/RazorfenKraul/razorfen_kraul.cpp b/src/server/scripts/Kalimdor/RazorfenKraul/razorfen_kraul.cpp
index f04b71d1da9..1dc37e063ba 100644
--- a/src/server/scripts/Kalimdor/RazorfenKraul/razorfen_kraul.cpp
+++ b/src/server/scripts/Kalimdor/RazorfenKraul/razorfen_kraul.cpp
@@ -171,7 +171,11 @@ public:
struct npc_snufflenose_gopherAI : public PetAI
{
- npc_snufflenose_gopherAI(Creature* creature) : PetAI(creature) { }
+ npc_snufflenose_gopherAI(Creature* creature) : PetAI(creature)
+ {
+ IsMovementActive = false;
+ TargetTubberGUID = 0;
+ }
void Reset() OVERRIDE
{
diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_cthun.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_cthun.cpp
index 9e3244cccdb..988436066b6 100644
--- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_cthun.cpp
+++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_cthun.cpp
@@ -898,6 +898,9 @@ public:
{
eye_tentacleAI(Creature* creature) : ScriptedAI(creature)
{
+ MindflayTimer = 500;
+ KillSelfTimer = 35000;
+
Portal = 0;
if (Creature* pPortal = me->SummonCreature(NPC_SMALL_PORTAL, *me, TEMPSUMMON_CORPSE_DESPAWN))
{
@@ -974,6 +977,10 @@ public:
{
claw_tentacleAI(Creature* creature) : ScriptedAI(creature)
{
+ GroundRuptureTimer = 500;
+ HamstringTimer = 2000;
+ EvadeTimer = 5000;
+
SetCombatMovement(false);
Portal = 0;
@@ -1085,6 +1092,11 @@ public:
{
giant_claw_tentacleAI(Creature* creature) : ScriptedAI(creature)
{
+ GroundRuptureTimer = 500;
+ HamstringTimer = 2000;
+ ThrashTimer = 5000;
+ EvadeTimer = 5000;
+
SetCombatMovement(false);
Portal = 0;
@@ -1205,6 +1217,8 @@ public:
{
giant_eye_tentacleAI(Creature* creature) : ScriptedAI(creature)
{
+ BeamTimer = 500;
+
SetCombatMovement(false);
Portal = 0;
diff --git a/src/server/scripts/Kalimdor/zone_mulgore.cpp b/src/server/scripts/Kalimdor/zone_mulgore.cpp
index f70460ec7b6..f8cc21da209 100644
--- a/src/server/scripts/Kalimdor/zone_mulgore.cpp
+++ b/src/server/scripts/Kalimdor/zone_mulgore.cpp
@@ -24,7 +24,6 @@ SDCategory: Mulgore
EndScriptData */
/* ContentData
-npc_skorn_whitecloud
npc_kyle_frenzied
npc_plains_vision
EndContentData */
@@ -35,41 +34,6 @@ EndContentData */
#include "Player.h"
#include "SpellInfo.h"
-/*######
-# npc_skorn_whitecloud
-######*/
-
-#define GOSSIP_SW "Tell me a story, Skorn."
-
-class npc_skorn_whitecloud : public CreatureScript
-{
-public:
- npc_skorn_whitecloud() : CreatureScript("npc_skorn_whitecloud") { }
-
- bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) OVERRIDE
- {
- player->PlayerTalkClass->ClearMenus();
- if (action == GOSSIP_ACTION_INFO_DEF)
- player->SEND_GOSSIP_MENU(523, creature->GetGUID());
-
- return true;
- }
-
- bool OnGossipHello(Player* player, Creature* creature) OVERRIDE
- {
- if (creature->IsQuestGiver())
- player->PrepareQuestMenu(creature->GetGUID());
-
- if (!player->GetQuestRewardStatus(770))
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SW, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
-
- player->SEND_GOSSIP_MENU(522, creature->GetGUID());
-
- return true;
- }
-
-};
-
/*#####
# npc_kyle_frenzied
######*/
@@ -321,7 +285,6 @@ public:
void AddSC_mulgore()
{
- new npc_skorn_whitecloud();
new npc_kyle_frenzied();
new npc_plains_vision();
}
diff --git a/src/server/scripts/Kalimdor/zone_silithus.cpp b/src/server/scripts/Kalimdor/zone_silithus.cpp
index b002bbe8a48..24d557222eb 100644
--- a/src/server/scripts/Kalimdor/zone_silithus.cpp
+++ b/src/server/scripts/Kalimdor/zone_silithus.cpp
@@ -649,11 +649,11 @@ public:
Unit* mob = NULL;
for (uint8 i = 0; i < 4; ++i)
{
- mob = player->FindNearestCreature(entries[i], 50, me);
+ mob = player->FindNearestCreature(entries[i], 50);
while (mob)
{
mob->RemoveFromWorld();
- mob = player->FindNearestCreature(15423, 50, me);
+ mob = player->FindNearestCreature(15423, 50);
}
}
break;
@@ -1021,7 +1021,7 @@ public:
{
if (quest->GetQuestId() == QUEST_A_PAWN_ON_THE_ETERNAL_BOARD)
{
- if (Creature* trigger = go->FindNearestCreature(15454, 100, player))
+ if (Creature* trigger = go->FindNearestCreature(15454, 100))
{
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);
diff --git a/src/server/scripts/Kalimdor/zone_tanaris.cpp b/src/server/scripts/Kalimdor/zone_tanaris.cpp
index 204a2960611..3ced3c7115d 100644
--- a/src/server/scripts/Kalimdor/zone_tanaris.cpp
+++ b/src/server/scripts/Kalimdor/zone_tanaris.cpp
@@ -19,14 +19,13 @@
/* ScriptData
SDName: Tanaris
SD%Complete: 80
-SDComment: Quest support: 648, 1560, 2954, 4005, 10277, 10279(Special flight path). Noggenfogger vendor
+SDComment: Quest support: 648, 1560, 2954, 4005, 10277, 10279(Special flight path).
SDCategory: Tanaris
EndScriptData */
/* ContentData
npc_aquementas
npc_custodian_of_time
-npc_marin_noggenfogger
npc_steward_of_time
npc_stone_watcher_of_norgannon
npc_OOX17
@@ -282,39 +281,6 @@ public:
};
/*######
-## npc_marin_noggenfogger
-######*/
-
-class npc_marin_noggenfogger : public CreatureScript
-{
-public:
- npc_marin_noggenfogger() : CreatureScript("npc_marin_noggenfogger") { }
-
- bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) OVERRIDE
- {
- player->PlayerTalkClass->ClearMenus();
- if (action == GOSSIP_ACTION_TRADE)
- player->GetSession()->SendListInventory(creature->GetGUID());
-
- return true;
- }
-
- bool OnGossipHello(Player* player, Creature* creature) OVERRIDE
- {
- if (creature->IsQuestGiver())
- player->PrepareQuestMenu(creature->GetGUID());
-
- if (creature->IsVendor() && player->GetQuestRewardStatus(2662))
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE);
-
- player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID());
-
- return true;
- }
-
-};
-
-/*######
## npc_steward_of_time
######*/
@@ -681,7 +647,6 @@ void AddSC_tanaris()
{
new npc_aquementas();
new npc_custodian_of_time();
- new npc_marin_noggenfogger();
new npc_steward_of_time();
new npc_stone_watcher_of_norgannon();
new npc_OOX17();
diff --git a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_prince_taldaram.cpp b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_prince_taldaram.cpp
index efe439de440..31c565e5be2 100644
--- a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_prince_taldaram.cpp
+++ b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_prince_taldaram.cpp
@@ -88,6 +88,9 @@ class boss_prince_taldaram : public CreatureScript
boss_prince_taldaramAI(Creature* creature) : BossAI(creature, DATA_PRINCE_TALDARAM)
{
me->SetDisableGravity(true);
+ _flameSphereTargetGUID = 0;
+ _embraceTargetGUID = 0;
+ _embraceTakenDamage = 0;
}
void Reset() OVERRIDE
@@ -283,7 +286,10 @@ class npc_prince_taldaram_flame_sphere : public CreatureScript
struct npc_prince_taldaram_flame_sphereAI : public ScriptedAI
{
- npc_prince_taldaram_flame_sphereAI(Creature* creature) : ScriptedAI(creature) { }
+ npc_prince_taldaram_flame_sphereAI(Creature* creature) : ScriptedAI(creature)
+ {
+ _flameSphereTargetGUID = 0;
+ }
void Reset() OVERRIDE
{
diff --git a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_krikthir_the_gatewatcher.cpp b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_krikthir_the_gatewatcher.cpp
index 19e6b55b5c5..1281d40fe5c 100644
--- a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_krikthir_the_gatewatcher.cpp
+++ b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_krikthir_the_gatewatcher.cpp
@@ -203,7 +203,7 @@ class npc_skittering_infector : public CreatureScript
enum TrashEvents
{
// Anubar Skrimisher
- EVENT_ANUBAR_CHARGE,
+ EVENT_ANUBAR_CHARGE = 1,
EVENT_BACKSTAB,
// Anubar Shadowcaster
diff --git a/src/server/scripts/Northrend/CMakeLists.txt b/src/server/scripts/Northrend/CMakeLists.txt
index 42a7ee15bb6..aff3c0a9528 100644
--- a/src/server/scripts/Northrend/CMakeLists.txt
+++ b/src/server/scripts/Northrend/CMakeLists.txt
@@ -168,6 +168,7 @@ set(scripts_STAT_SRCS
Northrend/IcecrownCitadel/icecrown_citadel_teleport.cpp
Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp
Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp
+ Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp
Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp
Northrend/IcecrownCitadel/boss_festergut.cpp
Northrend/IcecrownCitadel/boss_rotface.cpp
diff --git a/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/obsidian_sanctum.cpp b/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/obsidian_sanctum.cpp
index 9ae6f811e19..a24cd4db7c5 100644
--- a/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/obsidian_sanctum.cpp
+++ b/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/obsidian_sanctum.cpp
@@ -73,7 +73,7 @@ enum Enums
//Whelps
NPC_TWILIGHT_WHELP = 30890,
- NPC_SHARTHARION_TWILIGHT_WHELP = 31214,
+ NPC_SARTHARION_TWILIGHT_WHELP = 31214,
SPELL_FADE_ARMOR = 60708, // Reduces the armor of an enemy by 1500 for 15s
//flame tsunami
@@ -253,7 +253,7 @@ struct dummy_dragonAI : public ScriptedAI
{
case NPC_TENEBRON:
{
- if (!instance->GetBossState(DATA_SARTHARION) == IN_PROGRESS)
+ if (instance->GetBossState(DATA_SARTHARION) != IN_PROGRESS)
{
for (uint32 i = 0; i < 6; ++i)
me->SummonCreature(NPC_TWILIGHT_EGG, TwilightEggs[i], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20000);
@@ -267,7 +267,7 @@ struct dummy_dragonAI : public ScriptedAI
}
case NPC_SHADRON:
{
- if (!instance->GetBossState(DATA_SARTHARION) == IN_PROGRESS)
+ if (instance->GetBossState(DATA_SARTHARION) != IN_PROGRESS)
me->SummonCreature(NPC_ACOLYTE_OF_SHADRON, AcolyteofShadron, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 28000);
else
me->SummonCreature(NPC_ACOLYTE_OF_SHADRON, AcolyteofShadron2, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 28000);
@@ -276,7 +276,7 @@ struct dummy_dragonAI : public ScriptedAI
}
case NPC_VESPERON:
{
- if (!instance->GetBossState(DATA_SARTHARION) == IN_PROGRESS)
+ if (instance->GetBossState(DATA_SARTHARION) != IN_PROGRESS)
{
if (Creature* acolyte = me->SummonCreature(NPC_ACOLYTE_OF_VESPERON, AcolyteofVesperon, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20000))
{
@@ -816,10 +816,10 @@ public:
{
me->RemoveAllAuras();
- if (!instance->GetBossState(DATA_SARTHARION) == IN_PROGRESS)
+ if (instance->GetBossState(DATA_SARTHARION) != IN_PROGRESS)
me->SummonCreature(NPC_TWILIGHT_WHELP, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000);
else
- me->SummonCreature(NPC_SHARTHARION_TWILIGHT_WHELP, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000);
+ me->SummonCreature(NPC_SARTHARION_TWILIGHT_WHELP, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000);
me->DealDamage(me, me->GetHealth());
}
diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp
index ea166585bb3..4210ebfcad5 100644
--- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp
+++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp
@@ -294,6 +294,8 @@ class npc_snobold_vassal : public CreatureScript
{
npc_snobold_vassalAI(Creature* creature) : ScriptedAI(creature)
{
+ _targetGUID = 0;
+ _targetDied = false;
_instance = creature->GetInstanceScript();
_instance->SetData(DATA_SNOBOLD_COUNT, INCREASE);
}
diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp
index 1f4713415ac..de14b930220 100644
--- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp
+++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp
@@ -1180,7 +1180,10 @@ enum TrashEvents
struct npc_gauntlet_trash : public ScriptedAI
{
- npc_gauntlet_trash(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
+ npc_gauntlet_trash(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript())
+ {
+ InternalWaveId = 0;
+ }
void Reset() OVERRIDE
{
diff --git a/src/server/scripts/Northrend/Gundrak/boss_slad_ran.cpp b/src/server/scripts/Northrend/Gundrak/boss_slad_ran.cpp
index dd1d35e639e..0feec20d55f 100644
--- a/src/server/scripts/Northrend/Gundrak/boss_slad_ran.cpp
+++ b/src/server/scripts/Northrend/Gundrak/boss_slad_ran.cpp
@@ -219,7 +219,10 @@ public:
struct npc_slad_ran_constrictorAI : public ScriptedAI
{
- npc_slad_ran_constrictorAI(Creature* creature) : ScriptedAI(creature) { }
+ npc_slad_ran_constrictorAI(Creature* creature) : ScriptedAI(creature)
+ {
+ uiGripOfSladRanTimer = 1 * IN_MILLISECONDS;
+ }
uint32 uiGripOfSladRanTimer;
@@ -247,8 +250,9 @@ public:
target->CastSpell(target, SPELL_SNAKE_WRAP, true);
if (TempSummon* _me = me->ToTempSummon())
- if (Creature* sladran = _me->GetSummoner()->ToCreature())
- sladran->AI()->SetGUID(target->GetGUID(), DATA_SNAKES_WHYD_IT_HAVE_TO_BE_SNAKES);
+ if (Unit* summoner = _me->GetSummoner())
+ if (Creature* sladran = summoner->ToCreature())
+ sladran->AI()->SetGUID(target->GetGUID(), DATA_SNAKES_WHYD_IT_HAVE_TO_BE_SNAKES);
me->DespawnOrUnsummon();
}
@@ -270,7 +274,10 @@ public:
struct npc_slad_ran_viperAI : public ScriptedAI
{
- npc_slad_ran_viperAI(Creature* creature) : ScriptedAI(creature) { }
+ npc_slad_ran_viperAI(Creature* creature) : ScriptedAI(creature)
+ {
+ uiVenomousBiteTimer = 2 * IN_MILLISECONDS;
+ }
uint32 uiVenomousBiteTimer;
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 3d4ee279685..bbf3e8afc0f 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
@@ -800,7 +800,7 @@ class spell_blood_queen_pact_of_the_darkfallen_dmg : public SpellScriptLoader
// this is an additional effect to be executed
void PeriodicTick(AuraEffect const* aurEff)
{
- SpellInfo const* damageSpell = sSpellMgr->GetSpellInfo(SPELL_PACT_OF_THE_DARKFALLEN_DAMAGE);
+ SpellInfo const* damageSpell = sSpellMgr->EnsureSpellInfo(SPELL_PACT_OF_THE_DARKFALLEN_DAMAGE);
int32 damage = damageSpell->Effects[EFFECT_0].CalcValue();
float multiplier = 0.3375f + 0.1f * uint32(aurEff->GetTickNumber()/10); // do not convert to 0.01f - we need tick number/10 as INT (damage increases every 10 ticks)
damage = int32(damage * multiplier);
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp
index 7be766c0a0e..e8048404027 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp
@@ -333,6 +333,7 @@ class boss_deathbringer_saurfang : public CreatureScript
void JustReachedHome() OVERRIDE
{
_JustReachedHome();
+ Reset();
instance->SetBossState(DATA_DEATHBRINGER_SAURFANG, FAIL);
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_MARK_OF_THE_FALLEN_CHAMPION);
}
@@ -376,7 +377,16 @@ class boss_deathbringer_saurfang : public CreatureScript
void JustSummoned(Creature* summon) OVERRIDE
{
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true))
+ {
+ if (target->GetTransport())
+ {
+ summon->DespawnOrUnsummon(1);
+ EnterEvadeMode();
+ return;
+ }
+
summon->AI()->AttackStart(target);
+ }
summon->CastSpell(summon, SPELL_BLOOD_LINK_BEAST, true);
summon->CastSpell(summon, SPELL_RESISTANT_SKIN, true);
@@ -399,6 +409,12 @@ class boss_deathbringer_saurfang : public CreatureScript
void SpellHitTarget(Unit* target, SpellInfo const* spell) OVERRIDE
{
+ if (target->GetTransport())
+ {
+ EnterEvadeMode();
+ return;
+ }
+
switch (spell->Id)
{
case SPELL_MARK_OF_THE_FALLEN_CHAMPION:
@@ -571,6 +587,14 @@ class boss_deathbringer_saurfang : public CreatureScript
}
}
+ bool CanAIAttack(Unit const* target) const OVERRIDE
+ {
+ if (target->GetTransport())
+ return false;
+
+ return true;
+ }
+
static uint32 const FightWonValue;
private:
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp
new file mode 100644
index 00000000000..0a9e207db36
--- /dev/null
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp
@@ -0,0 +1,2484 @@
+/*
+ * Copyright (C) 2008-2014 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 "CellImpl.h"
+#include "CreatureTextMgr.h"
+#include "GridNotifiersImpl.h"
+#include "GossipDef.h"
+#include "MoveSpline.h"
+#include "MoveSplineInit.h"
+#include "PassiveAI.h"
+#include "ScriptMgr.h"
+#include "ScriptedCreature.h"
+#include "SpellAuraEffects.h"
+#include "SpellScript.h"
+#include "Transport.h"
+#include "TransportMgr.h"
+#include "Vehicle.h"
+#include "icecrown_citadel.h"
+
+enum Texts
+{
+ // High Overlord Saurfang
+ SAY_SAURFANG_INTRO_1 = 0,
+ SAY_SAURFANG_INTRO_2 = 1,
+ SAY_SAURFANG_INTRO_3 = 2,
+ SAY_SAURFANG_INTRO_4 = 3,
+ SAY_SAURFANG_INTRO_5 = 4,
+ SAY_SAURFANG_INTRO_6 = 5,
+ SAY_SAURFANG_INTRO_A = 6,
+ SAY_SAURFANG_BOARD = 7,
+ SAY_SAURFANG_ENTER_SKYBREAKER = 8,
+ SAY_SAURFANG_AXETHROWERS = 9,
+ SAY_SAURFANG_ROCKETEERS = 10,
+ SAY_SAURFANG_MAGES = 11,
+ SAY_SAURFANG_VICTORY = 12,
+ SAY_SAURFANG_WIPE = 13,
+
+ // Muradin Bronzebeard
+ SAY_MURADIN_INTRO_1 = 0,
+ SAY_MURADIN_INTRO_2 = 1,
+ SAY_MURADIN_INTRO_3 = 2,
+ SAY_MURADIN_INTRO_4 = 3,
+ SAY_MURADIN_INTRO_5 = 4,
+ SAY_MURADIN_INTRO_6 = 5,
+ SAY_MURADIN_INTRO_7 = 6,
+ SAY_MURADIN_INTRO_H = 7,
+ SAY_MURADIN_BOARD = 8,
+ SAY_MURADIN_ENTER_ORGRIMMS_HAMMER = 9,
+ SAY_MURADIN_RIFLEMAN = 10,
+ SAY_MURADIN_MORTAR = 11,
+ SAY_MURADIN_SORCERERS = 12,
+ SAY_MURADIN_VICTORY = 13,
+ SAY_MURADIN_WIPE = 14,
+
+ SAY_ZAFOD_ROCKET_PACK_ACTIVE = 0,
+ SAY_ZAFOD_ROCKET_PACK_DISABLED = 1,
+
+ SAY_OVERHEAT = 0
+};
+
+enum Events
+{
+ // High Overlord Saurfang
+ EVENT_INTRO_H_1 = 1,
+ EVENT_INTRO_H_2 = 2,
+ EVENT_INTRO_SUMMON_SKYBREAKER = 3,
+ EVENT_INTRO_H_3 = 4,
+ EVENT_INTRO_H_4 = 5,
+ EVENT_INTRO_H_5 = 6,
+ EVENT_INTRO_H_6 = 7,
+
+ // Muradin Bronzebeard
+ EVENT_INTRO_A_1 = 1,
+ EVENT_INTRO_A_2 = 2,
+ EVENT_INTRO_SUMMON_ORGRIMS_HAMMER = 3,
+ EVENT_INTRO_A_3 = 4,
+ EVENT_INTRO_A_4 = 5,
+ EVENT_INTRO_A_5 = 6,
+ EVENT_INTRO_A_6 = 7,
+ EVENT_INTRO_A_7 = 8,
+
+ EVENT_KEEP_PLAYER_IN_COMBAT = 9,
+ EVENT_SUMMON_MAGE = 10,
+ EVENT_ADDS = 11,
+ EVENT_ADDS_BOARD_YELL = 12,
+ EVENT_CHECK_RIFLEMAN = 13,
+ EVENT_CHECK_MORTAR = 14,
+ EVENT_CLEAVE = 15,
+
+ EVENT_BLADESTORM = 16,
+ EVENT_WOUNDING_STRIKE = 17
+};
+
+enum Spells
+{
+ // Applied on friendly transport NPCs
+ SPELL_FRIENDLY_BOSS_DAMAGE_MOD = 70339,
+ SPELL_CHECK_FOR_PLAYERS = 70332,
+ SPELL_GUNSHIP_FALL_TELEPORT = 67335,
+ SPELL_TELEPORT_PLAYERS_ON_RESET_A = 70446,
+ SPELL_TELEPORT_PLAYERS_ON_RESET_H = 71284,
+ SPELL_TELEPORT_PLAYERS_ON_VICTORY = 72340,
+ SPELL_ACHIEVEMENT = 72959,
+ SPELL_AWARD_REPUTATION_BOSS_KILL = 73843,
+
+ // Murading Bronzebeard
+ // High Overlord Saurfang
+ SPELL_BATTLE_FURY = 69637,
+ SPELL_RENDING_THROW = 70309,
+ SPELL_CLEAVE = 15284,
+ SPELL_TASTE_OF_BLOOD = 69634,
+
+ // Applied on enemy NPCs
+ SPELL_MELEE_TARGETING_ON_SKYBREAKER = 70219,
+ SPELL_MELEE_TARGETING_ON_ORGRIMS_HAMMER = 70294,
+
+ // Gunship Hull
+ SPELL_EXPLOSION_WIPE = 72134,
+ SPELL_EXPLOSION_VICTORY = 72137,
+
+ // Hostile NPCs
+ SPELL_TELEPORT_TO_ENEMY_SHIP = 70104,
+ SPELL_BATTLE_EXPERIENCE = 71201,
+ SPELL_EXPERIENCED = 71188,
+ SPELL_VETERAN = 71193,
+ SPELL_ELITE = 71195,
+ SPELL_ADDS_BERSERK = 72525,
+
+ // Skybreaker Sorcerer
+ // Kor'kron Battle-Mage
+ SPELL_SHADOW_CHANNELING = 43897,
+ SPELL_BELOW_ZERO = 69705,
+
+ // Skybreaker Rifleman
+ // Kor'kron Axethrower
+ SPELL_SHOOT = 70162,
+ SPELL_HURL_AXE = 70161,
+ SPELL_BURNING_PITCH_A = 70403,
+ SPELL_BURNING_PITCH_H = 70397,
+ SPELL_BURNING_PITCH = 69660,
+
+ // Skybreaker Mortar Soldier
+ // Kor'kron Rocketeer
+ SPELL_ROCKET_ARTILLERY_A = 70609,
+ SPELL_ROCKET_ARTILLERY_H = 69678,
+ SPELL_BURNING_PITCH_DAMAGE_A = 70383,
+ SPELL_BURNING_PITCH_DAMAGE_H = 70374,
+
+ // Skybreaker Marine
+ // Kor'kron Reaver
+ SPELL_DESPERATE_RESOLVE = 69647,
+
+ // Skybreaker Sergeant
+ // Kor'kron Sergeant
+ SPELL_BLADESTORM = 69652,
+ SPELL_WOUNDING_STRIKE = 69651,
+
+ //
+ SPELL_LOCK_PLAYERS_AND_TAP_CHEST = 72347,
+ SPELL_ON_SKYBREAKER_DECK = 70120,
+ SPELL_ON_ORGRIMS_HAMMER_DECK = 70121,
+
+ // Rocket Pack
+ SPELL_ROCKET_PACK_DAMAGE = 69193,
+ SPELL_ROCKET_BURST = 69192,
+ SPELL_ROCKET_PACK_USEABLE = 70348,
+
+ // Alliance Gunship Cannon
+ // Horde Gunship Cannon
+ SPELL_OVERHEAT = 69487,
+ SPELL_EJECT_ALL_PASSENGERS_BELOW_ZERO = 68576,
+ SPELL_EJECT_ALL_PASSENGERS_WIPE = 50630
+};
+
+enum MiscData
+{
+ ITEM_GOBLIN_ROCKET_PACK = 49278,
+
+ PHASE_COMBAT = 0,
+ PHASE_INTRO = 1,
+
+ MUSIC_ENCOUNTER = 17289
+};
+
+enum EncounterActions
+{
+ ACTION_SPAWN_MAGE = 1,
+ ACTION_SPAWN_ALL_ADDS = 2,
+ ACTION_CLEAR_SLOT = 3,
+ ACTION_SET_SLOT = 4,
+ ACTION_SHIP_VISITS = 5
+};
+
+Position const SkybreakerAddsSpawnPos = { 15.91131f, 0.0f, 20.4628f, M_PI };
+Position const OrgrimsHammerAddsSpawnPos = { 60.728395f, 0.0f, 38.93467f, M_PI };
+
+// Horde encounter
+Position const SkybreakerTeleportPortal = { 6.666975f, 0.013001f, 20.87888f, 0.0f };
+Position const OrgrimsHammerTeleportExit = { 7.461699f, 0.158853f, 35.72989f, 0.0f };
+
+// Alliance encounter
+Position const OrgrimsHammerTeleportPortal = { 47.550990f, -0.101778f, 37.61111f, 0.0f };
+Position const SkybreakerTeleportExit = { -17.55738f, -0.090421f, 21.18366f, 0.0f };
+
+uint32 const MuradinExitPathSize = 10;
+G3D::Vector3 const MuradinExitPath[MuradinExitPathSize] =
+{
+ { 8.130936f, -0.2699585f, 20.31728f },
+ { 6.380936f, -0.2699585f, 20.31728f },
+ { 3.507703f, 0.02986573f, 20.78463f },
+ { -2.767633f, 3.743143f, 20.37663f },
+ { -4.017633f, 4.493143f, 20.12663f },
+ { -7.242224f, 6.856013f, 20.03468f },
+ { -7.742224f, 8.606013f, 20.78468f },
+ { -7.992224f, 9.856013f, 21.28468f },
+ { -12.24222f, 23.10601f, 21.28468f },
+ { -14.88477f, 25.20844f, 21.59985f },
+};
+
+uint32 const SaurfangExitPathSize = 13;
+G3D::Vector3 const SaurfangExitPath[SaurfangExitPathSize] =
+{
+ { 30.43987f, 0.1475817f, 36.10674f },
+ { 21.36141f, -3.056458f, 35.42970f },
+ { 19.11141f, -3.806458f, 35.42970f },
+ { 19.01736f, -3.299440f, 35.39428f },
+ { 18.6747f, -5.862823f, 35.66611f },
+ { 18.6747f, -7.862823f, 35.66611f },
+ { 18.1747f, -17.36282f, 35.66611f },
+ { 18.1747f, -22.61282f, 35.66611f },
+ { 17.9247f, -24.36282f, 35.41611f },
+ { 17.9247f, -26.61282f, 35.66611f },
+ { 17.9247f, -27.86282f, 35.66611f },
+ { 17.9247f, -29.36282f, 35.66611f },
+ { 15.33203f, -30.42621f, 35.93796f }
+};
+
+enum PassengerSlots
+{
+ // Freezing the cannons
+ SLOT_FREEZE_MAGE = 0,
+
+ // Channeling the portal, refilled with adds that board player's ship
+ SLOT_MAGE_1 = 1,
+ SLOT_MAGE_2 = 2,
+
+ // Rifleman
+ SLOT_RIFLEMAN_1 = 3,
+ SLOT_RIFLEMAN_2 = 4,
+ SLOT_RIFLEMAN_3 = 5,
+ SLOT_RIFLEMAN_4 = 6,
+
+ // Additional Rifleman on 25 man
+ SLOT_RIFLEMAN_5 = 7,
+ SLOT_RIFLEMAN_6 = 8,
+ SLOT_RIFLEMAN_7 = 9,
+ SLOT_RIFLEMAN_8 = 10,
+
+ // Mortar
+ SLOT_MORTAR_1 = 11,
+ SLOT_MORTAR_2 = 12,
+
+ // Additional spawns on 25 man
+ SLOT_MORTAR_3 = 13,
+ SLOT_MORTAR_4 = 14,
+
+ // Marines
+ SLOT_MARINE_1 = 15,
+ SLOT_MARINE_2 = 16,
+
+ // Additional spawns on 25 man
+ SLOT_MARINE_3 = 17,
+ SLOT_MARINE_4 = 18,
+
+ // Sergeants
+ SLOT_SERGEANT_1 = 19,
+
+ // Additional spawns on 25 man
+ SLOT_SERGEANT_2 = 20,
+
+ MAX_SLOTS
+};
+
+struct SlotInfo
+{
+ uint32 Entry;
+ Position TargetPosition;
+ uint32 Cooldown;
+};
+
+SlotInfo const SkybreakerSlotInfo[MAX_SLOTS] =
+{
+ { NPC_SKYBREAKER_SORCERER, { -9.479858f, 0.05663967f, 20.77026f, 4.729842f }, 0 },
+
+ { NPC_SKYBREAKER_SORCERER, { 6.385986f, 4.978760f, 20.55417f, 4.694936f }, 0 },
+ { NPC_SKYBREAKER_SORCERER, { 6.579102f, -4.674561f, 20.55060f, 1.553343f }, 0 },
+
+ { NPC_SKYBREAKER_RIFLEMAN, { -29.563900f, -17.95801f, 20.73837f, 4.747295f }, 30 },
+ { NPC_SKYBREAKER_RIFLEMAN, { -18.017210f, -18.82056f, 20.79150f, 4.747295f }, 30 },
+ { NPC_SKYBREAKER_RIFLEMAN, { -9.1193850f, -18.79102f, 20.58887f, 4.712389f }, 30 },
+ { NPC_SKYBREAKER_RIFLEMAN, { -0.3364258f, -18.87183f, 20.56824f, 4.712389f }, 30 },
+
+ { NPC_SKYBREAKER_RIFLEMAN, { -34.705810f, -17.67261f, 20.51523f, 4.729842f }, 30 },
+ { NPC_SKYBREAKER_RIFLEMAN, { -23.562010f, -18.28564f, 20.67859f, 4.729842f }, 30 },
+ { NPC_SKYBREAKER_RIFLEMAN, { -13.602780f, -18.74268f, 20.59622f, 4.712389f }, 30 },
+ { NPC_SKYBREAKER_RIFLEMAN, { -4.3350220f, -18.84619f, 20.58234f, 4.712389f }, 30 },
+
+ { NPC_SKYBREAKER_MORTAR_SOLDIER, { -31.70142f, 18.02783f, 20.77197f, 4.712389f }, 30 },
+ { NPC_SKYBREAKER_MORTAR_SOLDIER, { -9.368652f, 18.75806f, 20.65335f, 4.712389f }, 30 },
+
+ { NPC_SKYBREAKER_MORTAR_SOLDIER, { -20.40851f, 18.40381f, 20.50647f, 4.694936f }, 30 },
+ { NPC_SKYBREAKER_MORTAR_SOLDIER, { 0.1585693f, 18.11523f, 20.41949f, 4.729842f }, 30 },
+
+ { NPC_SKYBREAKER_MARINE, SkybreakerTeleportPortal, 0 },
+ { NPC_SKYBREAKER_MARINE, SkybreakerTeleportPortal, 0 },
+
+ { NPC_SKYBREAKER_MARINE, SkybreakerTeleportPortal, 0 },
+ { NPC_SKYBREAKER_MARINE, SkybreakerTeleportPortal, 0 },
+
+ { NPC_SKYBREAKER_SERGEANT, SkybreakerTeleportPortal, 0 },
+
+ { NPC_SKYBREAKER_SERGEANT, SkybreakerTeleportPortal, 0 }
+};
+
+SlotInfo const OrgrimsHammerSlotInfo[MAX_SLOTS] =
+{
+ { NPC_KOR_KRON_BATTLE_MAGE, { 13.58548f, 0.3867192f, 34.99243f, 1.53589f }, 0 },
+
+ { NPC_KOR_KRON_BATTLE_MAGE, { 47.29290f, -4.308941f, 37.55550f, 1.570796f }, 0 },
+ { NPC_KOR_KRON_BATTLE_MAGE, { 47.34621f, 4.032004f, 37.70952f, 4.817109f }, 0 },
+
+ { NPC_KOR_KRON_AXETHROWER, { -12.09280f, 27.65942f, 33.58557f, 1.53589f }, 30 },
+ { NPC_KOR_KRON_AXETHROWER, { -3.170555f, 28.30652f, 34.21082f, 1.53589f }, 30 },
+ { NPC_KOR_KRON_AXETHROWER, { 14.928040f, 26.18018f, 35.47803f, 1.53589f }, 30 },
+ { NPC_KOR_KRON_AXETHROWER, { 24.703310f, 25.36584f, 35.97845f, 1.53589f }, 30 },
+
+ { NPC_KOR_KRON_AXETHROWER, { -16.65302f, 27.59668f, 33.18726f, 1.53589f }, 30 },
+ { NPC_KOR_KRON_AXETHROWER, { -8.084572f, 28.21448f, 33.93805f, 1.53589f }, 30 },
+ { NPC_KOR_KRON_AXETHROWER, { 7.594765f, 27.41968f, 35.00775f, 1.53589f }, 30 },
+ { NPC_KOR_KRON_AXETHROWER, { 20.763390f, 25.58215f, 35.75287f, 1.53589f }, 30 },
+
+ { NPC_KOR_KRON_ROCKETEER, { -11.44849f, -25.71838f, 33.64343f, 1.518436f }, 30 },
+ { NPC_KOR_KRON_ROCKETEER, { 12.30336f, -25.69653f, 35.32373f, 1.518436f }, 30 },
+
+ { NPC_KOR_KRON_ROCKETEER, { -0.05931854f, -25.46399f, 34.50592f, 1.518436f }, 30 },
+ { NPC_KOR_KRON_ROCKETEER, { 27.62149000f, -23.48108f, 36.12708f, 1.518436f }, 30 },
+
+ { NPC_KOR_KRON_REAVER, OrgrimsHammerTeleportPortal, 0 },
+ { NPC_KOR_KRON_REAVER, OrgrimsHammerTeleportPortal, 0 },
+
+ { NPC_KOR_KRON_REAVER, OrgrimsHammerTeleportPortal, 0 },
+ { NPC_KOR_KRON_REAVER, OrgrimsHammerTeleportPortal, 0 },
+
+ { NPC_KOR_KRON_SERGEANT, OrgrimsHammerTeleportPortal, 0 },
+
+ { NPC_KOR_KRON_SERGEANT, OrgrimsHammerTeleportPortal, 0 }
+};
+
+class PassengerController
+{
+public:
+ PassengerController()
+ {
+ ResetSlots(HORDE);
+ }
+
+ void SetTransport(Transport* transport) { _transport = transport; }
+
+ void ResetSlots(uint32 team)
+ {
+ _transport = NULL;
+ memset(_controlledSlots, 0, sizeof(uint64)* MAX_SLOTS);
+ memset(_respawnCooldowns, 0, sizeof(time_t)* MAX_SLOTS);
+ _spawnPoint = team == HORDE ? &OrgrimsHammerAddsSpawnPos : &SkybreakerAddsSpawnPos;
+ _slotInfo = team == HORDE ? OrgrimsHammerSlotInfo : SkybreakerSlotInfo;
+ }
+
+ bool SummonCreatures(PassengerSlots first, PassengerSlots last)
+ {
+ if (!_transport)
+ return false;
+
+ bool summoned = false;
+ time_t now = time(NULL);
+ for (int32 i = first; i <= last; ++i)
+ {
+ if (_respawnCooldowns[i] > now)
+ continue;
+
+ if (_controlledSlots[i])
+ {
+ Creature* current = ObjectAccessor::GetCreature(*_transport, _controlledSlots[i]);
+ if (current && current->IsAlive())
+ continue;
+ }
+
+ if (Creature* passenger = _transport->SummonPassenger(_slotInfo[i].Entry, SelectSpawnPoint(), TEMPSUMMON_CORPSE_TIMED_DESPAWN, NULL, 15000))
+ {
+ _controlledSlots[i] = passenger->GetGUID();
+ _respawnCooldowns[i] = time_t(0);
+ passenger->AI()->SetData(ACTION_SET_SLOT, i);
+ summoned = true;
+ }
+ }
+
+ return summoned;
+ }
+
+ void ClearSlot(PassengerSlots slot)
+ {
+ _controlledSlots[slot] = 0;
+ _respawnCooldowns[slot] = time(NULL) + _slotInfo[slot].Cooldown;
+ }
+
+ bool SlotsNeedRefill(PassengerSlots first, PassengerSlots last) const
+ {
+ for (int32 i = first; i <= last; ++i)
+ if (!_controlledSlots[i])
+ return true;
+
+ return false;
+ }
+
+private:
+ Position SelectSpawnPoint() const
+ {
+ Position newPos;
+ float angle = frand(-M_PI * 0.5f, M_PI * 0.5f);
+ newPos.m_positionX = _spawnPoint->GetPositionX() + 2.0f * std::cos(angle);
+ newPos.m_positionY = _spawnPoint->GetPositionY() + 2.0f * std::sin(angle);
+ newPos.m_positionZ = _spawnPoint->GetPositionZ();
+ newPos.SetOrientation(_spawnPoint->GetOrientation());
+ return newPos;
+ }
+
+ Transport* _transport;
+ uint64 _controlledSlots[MAX_SLOTS];
+ time_t _respawnCooldowns[MAX_SLOTS];
+ Position const* _spawnPoint;
+ SlotInfo const* _slotInfo;
+};
+
+class DelayedMovementEvent : public BasicEvent
+{
+public:
+ DelayedMovementEvent(Creature* owner, Position const& dest) : _owner(owner), _dest(dest) { }
+
+ bool Execute(uint64, uint32) OVERRIDE
+ {
+ if (!_owner->IsAlive())
+ return true;
+
+ _owner->GetMotionMaster()->MovePoint(EVENT_CHARGE_PREPATH, *_owner, false);
+
+ Movement::MoveSplineInit init(_owner);
+ init.DisableTransportPathTransformations();
+ init.MoveTo(_dest.GetPositionX(), _dest.GetPositionY(), _dest.GetPositionZ(), false);
+ init.Launch();
+
+ return true;
+ }
+
+private:
+ Creature* _owner;
+ Position const& _dest;
+};
+
+class ResetEncounterEvent : public BasicEvent
+{
+public:
+ ResetEncounterEvent(Unit* caster, uint32 spellId, uint64 otherTransport) : _caster(caster), _spellId(spellId), _otherTransport(otherTransport) { }
+
+ bool Execute(uint64, uint32) OVERRIDE
+ {
+ _caster->CastSpell(_caster, _spellId, true);
+ _caster->GetTransport()->AddObjectToRemoveList();
+
+ if (GameObject* go = HashMapHolder<GameObject>::Find(_otherTransport))
+ go->AddObjectToRemoveList();
+
+ return true;
+ }
+
+private:
+ Unit* _caster;
+ uint32 _spellId;
+ uint64 _otherTransport;
+};
+
+class BattleExperienceEvent : public BasicEvent
+{
+public:
+ static uint32 const ExperiencedSpells[5];
+ static uint32 const ExperiencedTimes[5];
+
+ BattleExperienceEvent(Creature* creature) : _creature(creature), _level(0) { }
+
+ bool Execute(uint64 timer, uint32 /*diff*/) OVERRIDE
+ {
+ if (!_creature->IsAlive())
+ return true;
+
+ _creature->RemoveAurasDueToSpell(ExperiencedSpells[_level]);
+ ++_level;
+
+ _creature->CastSpell(_creature, ExperiencedSpells[_level], TRIGGERED_FULL_MASK);
+ if (_level < (_creature->GetMap()->IsHeroic() ? 4 : 3))
+ {
+ _creature->m_Events.AddEvent(this, timer + ExperiencedTimes[_level]);
+ return false;
+ }
+
+ return true;
+ }
+
+private:
+ Creature* _creature;
+ int32 _level;
+};
+
+uint32 const BattleExperienceEvent::ExperiencedSpells[5] = { 0, SPELL_EXPERIENCED, SPELL_VETERAN, SPELL_ELITE, SPELL_ADDS_BERSERK };
+uint32 const BattleExperienceEvent::ExperiencedTimes[5] = { 100000, 70000, 60000, 90000, 0 };
+
+struct gunship_npc_AI : public ScriptedAI
+{
+ gunship_npc_AI(Creature* creature) : ScriptedAI(creature),
+ Instance(creature->GetInstanceScript()), Slot(NULL), Index(uint32(-1))
+ {
+ BurningPitchId = Instance->GetData(DATA_TEAM_IN_INSTANCE) == HORDE ? SPELL_BURNING_PITCH_A : SPELL_BURNING_PITCH_H;
+ me->setRegeneratingHealth(false);
+ }
+
+ void SetData(uint32 type, uint32 data) OVERRIDE
+ {
+ if (type == ACTION_SET_SLOT && data < MAX_SLOTS)
+ {
+ SetSlotInfo(data);
+
+ me->SetReactState(REACT_PASSIVE);
+
+ float x, y, z, o;
+ Slot->TargetPosition.GetPosition(x, y, z, o);
+
+ me->SetTransportHomePosition(Slot->TargetPosition);
+ float hx = x, hy = y, hz = z, ho = o;
+ me->GetTransport()->CalculatePassengerPosition(hx, hy, hz, &ho);
+ me->SetHomePosition(hx, hy, hz, ho);
+
+ me->GetMotionMaster()->MovePoint(EVENT_CHARGE_PREPATH, Slot->TargetPosition, false);
+
+ Movement::MoveSplineInit init(me);
+ init.DisableTransportPathTransformations();
+ init.MoveTo(x, y, z, false);
+ init.Launch();
+ }
+ }
+
+ void EnterEvadeMode() OVERRIDE
+ {
+ if (!me->IsAlive() || !me->IsInCombat())
+ return;
+
+ me->DeleteThreatList();
+ me->CombatStop(true);
+ me->GetMotionMaster()->MoveTargetedHome();
+ }
+
+ void JustDied(Unit* /*killer*/) OVERRIDE
+ {
+ if (Slot)
+ if (Creature* captain = me->FindNearestCreature(Instance->GetData(DATA_TEAM_IN_INSTANCE) == HORDE ? NPC_IGB_MURADIN_BRONZEBEARD : NPC_IGB_HIGH_OVERLORD_SAURFANG, 200.0f))
+ captain->AI()->SetData(ACTION_CLEAR_SLOT, Index);
+ }
+
+ void MovementInform(uint32 type, uint32 pointId) OVERRIDE
+ {
+ if (type != POINT_MOTION_TYPE)
+ return;
+
+ if (pointId == EVENT_CHARGE_PREPATH && Slot)
+ {
+ me->SetFacingTo(Slot->TargetPosition.GetOrientation());
+ me->m_Events.AddEvent(new BattleExperienceEvent(me), me->m_Events.CalculateTime(BattleExperienceEvent::ExperiencedTimes[0]));
+ DoCast(me, SPELL_BATTLE_EXPERIENCE, true);
+ me->SetReactState(REACT_AGGRESSIVE);
+ }
+ }
+
+ bool CanAIAttack(Unit const* target) const OVERRIDE
+ {
+ if (Instance->GetBossState(DATA_ICECROWN_GUNSHIP_BATTLE) != IN_PROGRESS)
+ return false;
+ return target->HasAura(Instance->GetData(DATA_TEAM_IN_INSTANCE) == HORDE ? SPELL_ON_ORGRIMS_HAMMER_DECK : SPELL_ON_SKYBREAKER_DECK);
+ }
+
+protected:
+ void SetSlotInfo(uint32 index)
+ {
+ Index = index;
+ Slot = &((Instance->GetData(DATA_TEAM_IN_INSTANCE) == HORDE ? SkybreakerSlotInfo : OrgrimsHammerSlotInfo)[Index]);
+ }
+
+ bool SelectVictim()
+ {
+ if (Instance->GetBossState(DATA_ICECROWN_GUNSHIP_BATTLE) != IN_PROGRESS)
+ {
+ EnterEvadeMode();
+ return false;
+ }
+
+ if (!me->HasReactState(REACT_PASSIVE))
+ {
+ if (Unit* victim = me->SelectVictim())
+ AttackStart(victim);
+ return me->GetVictim();
+ }
+ else if (me->getThreatManager().isThreatListEmpty())
+ {
+ EnterEvadeMode();
+ return false;
+ }
+
+ return true;
+ }
+
+ void TriggerBurningPitch()
+ {
+ if (Instance->GetBossState(DATA_ICECROWN_GUNSHIP_BATTLE) == IN_PROGRESS &&
+ !me->HasUnitState(UNIT_STATE_CASTING) && !me->HasReactState(REACT_PASSIVE) &&
+ !me->HasSpellCooldown(BurningPitchId))
+ {
+ DoCastAOE(BurningPitchId, true);
+ me->_AddCreatureSpellCooldown(BurningPitchId, time(NULL) + urand(3000, 4000) / IN_MILLISECONDS);
+ }
+ }
+
+ InstanceScript* Instance;
+ SlotInfo const* Slot;
+ uint32 Index;
+ uint32 BurningPitchId;
+};
+
+class npc_gunship : public CreatureScript
+{
+ public:
+ npc_gunship() : CreatureScript("npc_gunship") { }
+
+ struct npc_gunshipAI : public NullCreatureAI
+ {
+ npc_gunshipAI(Creature* creature) : NullCreatureAI(creature),
+ _teamInInstance(creature->GetInstanceScript()->GetData(DATA_TEAM_IN_INSTANCE)),
+ _summonedFirstMage(false), _died(false)
+ {
+ me->setRegeneratingHealth(false);
+ }
+
+ void DamageTaken(Unit* /*source*/, uint32& damage) OVERRIDE
+ {
+ if (damage >= me->GetHealth())
+ {
+ JustDied(NULL);
+ damage = me->GetHealth() - 1;
+ return;
+ }
+
+ if (_summonedFirstMage)
+ return;
+
+ if (me->GetTransport()->GetEntry() != uint32(_teamInInstance == HORDE ? GO_THE_SKYBREAKER_H : GO_ORGRIMS_HAMMER_A))
+ return;
+
+ if (!me->HealthBelowPctDamaged(90, damage))
+ return;
+
+ _summonedFirstMage = true;
+ if (Creature* captain = me->FindNearestCreature(_teamInInstance == HORDE ? NPC_IGB_MURADIN_BRONZEBEARD : NPC_IGB_HIGH_OVERLORD_SAURFANG, 100.0f))
+ captain->AI()->DoAction(ACTION_SPAWN_MAGE);
+ }
+
+ void JustDied(Unit* /*killer*/) OVERRIDE
+ {
+ if (_died)
+ return;
+
+ _died = true;
+
+ bool isVictory = me->GetTransport()->GetEntry() == GO_THE_SKYBREAKER_H || me->GetTransport()->GetEntry() == GO_ORGRIMS_HAMMER_A;
+ InstanceScript* instance = me->GetInstanceScript();
+ instance->SetBossState(DATA_ICECROWN_GUNSHIP_BATTLE, isVictory ? DONE : FAIL);
+ if (Creature* creature = me->FindNearestCreature(me->GetEntry() == NPC_ORGRIMS_HAMMER ? NPC_THE_SKYBREAKER : NPC_ORGRIMS_HAMMER, 200.0f))
+ {
+ instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, creature);
+ creature->RemoveAurasDueToSpell(SPELL_CHECK_FOR_PLAYERS);
+ }
+
+ instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
+ me->RemoveAurasDueToSpell(SPELL_CHECK_FOR_PLAYERS);
+
+ me->GetMap()->SetZoneMusic(AREA_ICECROWN_CITADEL, 0);
+ std::list<Creature*> creatures;
+ GetCreatureListWithEntryInGrid(creatures, me, NPC_MARTYR_STALKER_IGB_SAURFANG, SIZE_OF_GRIDS);
+ for (std::list<Creature*>::iterator itr = creatures.begin(); itr != creatures.end(); ++itr)
+ {
+ Creature* stalker = *itr;
+ stalker->RemoveAllAuras();
+ stalker->DeleteThreatList();
+ stalker->CombatStop(true);
+ }
+
+ uint32 explosionSpell = isVictory ? SPELL_EXPLOSION_VICTORY : SPELL_EXPLOSION_WIPE;
+ creatures.clear();
+ GetCreatureListWithEntryInGrid(creatures, me, NPC_GUNSHIP_HULL, 200.0f);
+ for (std::list<Creature*>::iterator itr = creatures.begin(); itr != creatures.end(); ++itr)
+ {
+ Creature* hull = *itr;
+ if (hull->GetTransport() != me->GetTransport())
+ continue;
+
+ hull->CastSpell(hull, explosionSpell, TRIGGERED_FULL_MASK);
+ }
+
+ creatures.clear();
+ GetCreatureListWithEntryInGrid(creatures, me, _teamInInstance == HORDE ? NPC_HORDE_GUNSHIP_CANNON : NPC_ALLIANCE_GUNSHIP_CANNON, 200.0f);
+ for (std::list<Creature*>::iterator itr = creatures.begin(); itr != creatures.end(); ++itr)
+ {
+ Creature* cannon = *itr;
+ if (isVictory)
+ {
+ cannon->CastSpell(cannon, SPELL_EJECT_ALL_PASSENGERS_BELOW_ZERO, TRIGGERED_FULL_MASK);
+
+ WorldPacket data(SMSG_PLAYER_VEHICLE_DATA, cannon->GetPackGUID().size() + 4);
+ data.append(cannon->GetPackGUID());
+ data << uint32(0);
+ cannon->SendMessageToSet(&data, true);
+
+ cannon->RemoveVehicleKit();
+ }
+ else
+ cannon->CastSpell(cannon, SPELL_EJECT_ALL_PASSENGERS_WIPE, TRIGGERED_FULL_MASK);
+ }
+
+ uint32 creatureEntry = NPC_IGB_MURADIN_BRONZEBEARD;
+ uint8 textId = isVictory ? SAY_MURADIN_VICTORY : SAY_MURADIN_WIPE;
+ if (_teamInInstance == HORDE)
+ {
+ creatureEntry = NPC_IGB_HIGH_OVERLORD_SAURFANG;
+ textId = isVictory ? SAY_SAURFANG_VICTORY : SAY_SAURFANG_WIPE;
+ }
+
+ if (Creature* creature = me->FindNearestCreature(creatureEntry, 100.0f))
+ creature->AI()->Talk(textId);
+
+ if (isVictory)
+ {
+ if (GameObject* go = HashMapHolder<GameObject>::Find(instance->GetData64(DATA_ICECROWN_GUNSHIP_BATTLE)))
+ if (Transport* otherTransport = go->ToTransport())
+ otherTransport->EnableMovement(true);
+
+ me->GetTransport()->EnableMovement(true);
+
+ if (Creature* ship = me->FindNearestCreature(_teamInInstance == HORDE ? NPC_ORGRIMS_HAMMER : NPC_THE_SKYBREAKER, 200.0f))
+ {
+ ship->CastSpell(ship, SPELL_TELEPORT_PLAYERS_ON_VICTORY, TRIGGERED_FULL_MASK);
+ ship->CastSpell(ship, SPELL_ACHIEVEMENT, TRIGGERED_FULL_MASK);
+ ship->CastSpell(ship, SPELL_AWARD_REPUTATION_BOSS_KILL, TRIGGERED_FULL_MASK);
+ }
+
+ creatures.clear();
+ GetCreatureListWithEntryInGrid(creatures, me, NPC_SKYBREAKER_MARINE, 200.0f);
+ GetCreatureListWithEntryInGrid(creatures, me, NPC_SKYBREAKER_SERGEANT, 200.0f);
+ GetCreatureListWithEntryInGrid(creatures, me, NPC_KOR_KRON_REAVER, 200.0f);
+ GetCreatureListWithEntryInGrid(creatures, me, NPC_KOR_KRON_SERGEANT, 200.0f);
+ for (std::list<Creature*>::iterator itr = creatures.begin(); itr != creatures.end(); ++itr)
+ (*itr)->DespawnOrUnsummon(1);
+ }
+ else
+ {
+ uint32 teleportSpellId = _teamInInstance == HORDE ? SPELL_TELEPORT_PLAYERS_ON_RESET_H : SPELL_TELEPORT_PLAYERS_ON_RESET_A;
+ me->m_Events.AddEvent(new ResetEncounterEvent(me, teleportSpellId, me->GetInstanceScript()->GetData64(DATA_ENEMY_GUNSHIP)),
+ me->m_Events.CalculateTime(8000));
+ }
+ }
+
+ void SetGUID(uint64 guid, int32 id/* = 0*/) OVERRIDE
+ {
+ if (id != ACTION_SHIP_VISITS)
+ return;
+
+ std::map<uint64, uint32>::iterator itr = _shipVisits.find(guid);
+ if (itr == _shipVisits.end())
+ _shipVisits[guid] = 1;
+ else
+ ++itr->second;
+ }
+
+ uint32 GetData(uint32 id) const OVERRIDE
+ {
+ if (id != ACTION_SHIP_VISITS)
+ return 0;
+
+ uint32 max = 0;
+ for (std::map<uint64, uint32>::const_iterator itr = _shipVisits.begin(); itr != _shipVisits.end(); ++itr)
+ max = std::max(max, itr->second);
+
+ return max;
+ }
+
+ private:
+ uint32 _teamInInstance;
+ std::map<uint64, uint32> _shipVisits;
+ bool _summonedFirstMage;
+ bool _died;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const OVERRIDE
+ {
+ if (!creature->GetTransport())
+ return NULL;
+
+ return GetIcecrownCitadelAI<npc_gunshipAI>(creature);
+ }
+};
+
+class npc_high_overlord_saurfang_igb : public CreatureScript
+{
+ public:
+ npc_high_overlord_saurfang_igb() : CreatureScript("npc_high_overlord_saurfang_igb") { }
+
+ struct npc_high_overlord_saurfang_igbAI : public ScriptedAI
+ {
+ npc_high_overlord_saurfang_igbAI(Creature* creature) : ScriptedAI(creature),
+ _instance(creature->GetInstanceScript())
+ {
+ _controller.ResetSlots(HORDE);
+ _controller.SetTransport(creature->GetTransport());
+ me->setRegeneratingHealth(false);
+ me->m_CombatDistance = 70.0f;
+ _firstMageCooldown = time(NULL) + 60;
+ _axethrowersYellCooldown = time_t(0);
+ _rocketeersYellCooldown = time_t(0);
+ }
+
+ void InitializeAI() OVERRIDE
+ {
+ ScriptedAI::InitializeAI();
+
+ _events.Reset();
+ _firstMageCooldown = time(NULL) + 60;
+ _axethrowersYellCooldown = time_t(0);
+ _rocketeersYellCooldown = time_t(0);
+ }
+
+ void EnterCombat(Unit* /*target*/) OVERRIDE
+ {
+ _events.SetPhase(PHASE_COMBAT);
+ DoCast(me, _instance->GetData(DATA_TEAM_IN_INSTANCE) == HORDE ? SPELL_FRIENDLY_BOSS_DAMAGE_MOD : SPELL_MELEE_TARGETING_ON_ORGRIMS_HAMMER, true);
+ DoCast(me, SPELL_BATTLE_FURY, true);
+ _events.ScheduleEvent(EVENT_CLEAVE, urand(2000, 10000));
+ }
+
+ void EnterEvadeMode() OVERRIDE
+ {
+ if (!me->IsAlive())
+ return;
+
+ me->DeleteThreatList();
+ me->CombatStop(true);
+ me->GetMotionMaster()->MoveTargetedHome();
+
+ Reset();
+ }
+
+ void DoAction(int32 action) OVERRIDE
+ {
+ if (action == ACTION_ENEMY_GUNSHIP_TALK)
+ {
+ if (Creature* muradin = me->FindNearestCreature(NPC_IGB_MURADIN_BRONZEBEARD, 100.0f))
+ muradin->AI()->DoAction(ACTION_SPAWN_ALL_ADDS);
+
+ Talk(SAY_SAURFANG_INTRO_5);
+ _events.ScheduleEvent(EVENT_INTRO_H_5, 4000);
+ _events.ScheduleEvent(EVENT_INTRO_H_6, 11000);
+ _events.ScheduleEvent(EVENT_KEEP_PLAYER_IN_COMBAT, 1);
+
+ _instance->SetBossState(DATA_ICECROWN_GUNSHIP_BATTLE, IN_PROGRESS);
+ // Combat starts now
+ if (Creature* skybreaker = me->FindNearestCreature(NPC_THE_SKYBREAKER, 100.0f))
+ _instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, skybreaker, 1);
+
+ if (Creature* orgrimsHammer = me->FindNearestCreature(NPC_ORGRIMS_HAMMER, 100.0f))
+ {
+ _instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, orgrimsHammer, 2);
+ orgrimsHammer->CastSpell(orgrimsHammer, SPELL_CHECK_FOR_PLAYERS, TRIGGERED_FULL_MASK);
+ }
+
+ me->GetMap()->SetZoneMusic(AREA_ICECROWN_CITADEL, MUSIC_ENCOUNTER);
+ }
+ else if (action == ACTION_SPAWN_MAGE)
+ {
+ time_t now = time(NULL);
+ if (_firstMageCooldown > now)
+ _events.ScheduleEvent(EVENT_SUMMON_MAGE, (_firstMageCooldown - now) * IN_MILLISECONDS);
+ else
+ _events.ScheduleEvent(EVENT_SUMMON_MAGE, 1);
+ }
+ else if (action == ACTION_SPAWN_ALL_ADDS)
+ {
+ _events.ScheduleEvent(EVENT_ADDS, 12000);
+ _events.ScheduleEvent(EVENT_CHECK_RIFLEMAN, 13000);
+ _events.ScheduleEvent(EVENT_CHECK_MORTAR, 13000);
+ if (Is25ManRaid())
+ _controller.SummonCreatures(SLOT_MAGE_1, SLOT_MORTAR_4);
+ else
+ {
+ _controller.SummonCreatures(SLOT_MAGE_1, SLOT_MAGE_2);
+ _controller.SummonCreatures(SLOT_MORTAR_1, SLOT_MORTAR_2);
+ _controller.SummonCreatures(SLOT_RIFLEMAN_1, SLOT_RIFLEMAN_4);
+ }
+ }
+ else if (action == ACTION_EXIT_SHIP)
+ {
+ Position pos;
+ pos.Relocate(SaurfangExitPath[SaurfangExitPathSize - 1].x, SaurfangExitPath[SaurfangExitPathSize - 1].y, SaurfangExitPath[SaurfangExitPathSize - 1].z);
+ me->GetMotionMaster()->MovePoint(EVENT_CHARGE_PREPATH, pos, false);
+
+ Movement::PointsArray path(SaurfangExitPath, SaurfangExitPath + SaurfangExitPathSize);
+
+ Movement::MoveSplineInit init(me);
+ init.DisableTransportPathTransformations();
+ init.MovebyPath(path, 0);
+ init.Launch();
+
+ me->DespawnOrUnsummon(18000);
+ }
+ }
+
+ void SetData(uint32 type, uint32 data) OVERRIDE
+ {
+ if (type == ACTION_CLEAR_SLOT)
+ {
+ _controller.ClearSlot(PassengerSlots(data));
+ if (data == SLOT_FREEZE_MAGE)
+ _events.ScheduleEvent(EVENT_SUMMON_MAGE, urand(30000, 33500));
+ }
+ }
+
+ void sGossipSelect(Player* /*player*/, uint32 /*sender*/, uint32 /*action*/) OVERRIDE
+ {
+ me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
+ me->GetTransport()->EnableMovement(true);
+ _events.SetPhase(PHASE_INTRO);
+ _events.ScheduleEvent(EVENT_INTRO_H_1, 5000, 0, PHASE_INTRO);
+ _events.ScheduleEvent(EVENT_INTRO_H_2, 16000, 0, PHASE_INTRO);
+ _events.ScheduleEvent(EVENT_INTRO_SUMMON_SKYBREAKER, 24600, 0, PHASE_INTRO);
+ _events.ScheduleEvent(EVENT_INTRO_H_3, 29600, 0, PHASE_INTRO);
+ _events.ScheduleEvent(EVENT_INTRO_H_4, 39200, 0, PHASE_INTRO);
+ }
+
+ void DamageTaken(Unit* , uint32& damage) OVERRIDE
+ {
+ if (me->HealthBelowPctDamaged(65, damage) && !me->HasAura(SPELL_TASTE_OF_BLOOD))
+ DoCast(me, SPELL_TASTE_OF_BLOOD, true);
+
+ if (damage >= me->GetHealth())
+ damage = me->GetHealth() - 1;
+ }
+
+ void UpdateAI(uint32 diff) OVERRIDE
+ {
+ if (!UpdateVictim() && !_events.IsInPhase(PHASE_INTRO) && _instance->GetBossState(DATA_ICECROWN_GUNSHIP_BATTLE) != IN_PROGRESS)
+ return;
+
+ _events.Update(diff);
+
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_INTRO_H_1:
+ Talk(SAY_SAURFANG_INTRO_1);
+ break;
+ case EVENT_INTRO_H_2:
+ Talk(SAY_SAURFANG_INTRO_2);
+ break;
+ case EVENT_INTRO_SUMMON_SKYBREAKER:
+ sTransportMgr->CreateTransport(GO_THE_SKYBREAKER_H, 0, me->GetMap());
+ break;
+ case EVENT_INTRO_H_3:
+ Talk(SAY_SAURFANG_INTRO_3);
+ break;
+ case EVENT_INTRO_H_4:
+ Talk(SAY_SAURFANG_INTRO_4);
+ break;
+ case EVENT_INTRO_H_5:
+ if (Creature* muradin = me->FindNearestCreature(NPC_IGB_MURADIN_BRONZEBEARD, 100.0f))
+ muradin->AI()->Talk(SAY_MURADIN_INTRO_H);
+ break;
+ case EVENT_INTRO_H_6:
+ Talk(SAY_SAURFANG_INTRO_6);
+ break;
+ case EVENT_KEEP_PLAYER_IN_COMBAT:
+ if (_instance->GetBossState(DATA_ICECROWN_GUNSHIP_BATTLE) == IN_PROGRESS)
+ {
+ _instance->DoCastSpellOnPlayers(SPELL_LOCK_PLAYERS_AND_TAP_CHEST);
+ _events.ScheduleEvent(EVENT_KEEP_PLAYER_IN_COMBAT, urand(5000, 8000));
+ }
+ break;
+ case EVENT_SUMMON_MAGE:
+ Talk(SAY_SAURFANG_MAGES);
+ _controller.SummonCreatures(SLOT_FREEZE_MAGE, SLOT_FREEZE_MAGE);
+ break;
+ case EVENT_ADDS:
+ Talk(SAY_SAURFANG_ENTER_SKYBREAKER);
+ _controller.SummonCreatures(SLOT_MAGE_1, SLOT_MAGE_2);
+ _controller.SummonCreatures(SLOT_MARINE_1, Is25ManRaid() ? SLOT_MARINE_4 : SLOT_MARINE_2);
+ _controller.SummonCreatures(SLOT_SERGEANT_1, Is25ManRaid() ? SLOT_SERGEANT_2 : SLOT_SERGEANT_1);
+ if (Transport* orgrimsHammer = me->GetTransport())
+ orgrimsHammer->SummonPassenger(NPC_TELEPORT_PORTAL, OrgrimsHammerTeleportPortal, TEMPSUMMON_TIMED_DESPAWN, NULL, 21000);
+
+ if (GameObject* go = HashMapHolder<GameObject>::Find(_instance->GetData64(DATA_ICECROWN_GUNSHIP_BATTLE)))
+ if (Transport* skybreaker = go->ToTransport())
+ skybreaker->SummonPassenger(NPC_TELEPORT_EXIT, SkybreakerTeleportExit, TEMPSUMMON_TIMED_DESPAWN, NULL, 23000);
+
+ _events.ScheduleEvent(EVENT_ADDS_BOARD_YELL, 6000);
+ _events.ScheduleEvent(EVENT_ADDS, 60000);
+ break;
+ case EVENT_ADDS_BOARD_YELL:
+ if (Creature* muradin = me->FindNearestCreature(NPC_IGB_MURADIN_BRONZEBEARD, 200.0f))
+ muradin->AI()->Talk(SAY_MURADIN_BOARD);
+ break;
+ case EVENT_CHECK_RIFLEMAN:
+ if (_controller.SummonCreatures(SLOT_RIFLEMAN_1, Is25ManRaid() ? SLOT_RIFLEMAN_8 : SLOT_RIFLEMAN_4))
+ {
+ if (_axethrowersYellCooldown < time(NULL))
+ {
+ Talk(SAY_SAURFANG_AXETHROWERS);
+ _axethrowersYellCooldown = time(NULL) + 5;
+ }
+ }
+ _events.ScheduleEvent(EVENT_CHECK_RIFLEMAN, 1000);
+ break;
+ case EVENT_CHECK_MORTAR:
+ if (_controller.SummonCreatures(SLOT_MORTAR_1, Is25ManRaid() ? SLOT_MORTAR_4 : SLOT_MORTAR_2))
+ {
+ if (_rocketeersYellCooldown < time(NULL))
+ {
+ Talk(SAY_SAURFANG_ROCKETEERS);
+ _rocketeersYellCooldown = time(NULL) + 5;
+ }
+ }
+ _events.ScheduleEvent(EVENT_CHECK_MORTAR, 1000);
+ break;
+ case EVENT_CLEAVE:
+ DoCastVictim(SPELL_CLEAVE);
+ _events.ScheduleEvent(EVENT_CLEAVE, urand(2000, 10000));
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (me->IsWithinMeleeRange(me->GetVictim()))
+ DoMeleeAttackIfReady();
+ else if (me->isAttackReady())
+ {
+ DoCastVictim(SPELL_RENDING_THROW);
+ me->resetAttackTimer();
+ }
+ }
+
+ bool CanAIAttack(Unit const* target) const OVERRIDE
+ {
+ if (_instance->GetBossState(DATA_ICECROWN_GUNSHIP_BATTLE) != IN_PROGRESS)
+ return false;
+ return target->HasAura(SPELL_ON_ORGRIMS_HAMMER_DECK) || target->GetEntry() == NPC_SKYBREAKER_MARINE || target->GetEntry() == NPC_SKYBREAKER_SERGEANT;
+ }
+
+ private:
+ EventMap _events;
+ PassengerController _controller;
+ InstanceScript* _instance;
+ time_t _firstMageCooldown;
+ time_t _axethrowersYellCooldown;
+ time_t _rocketeersYellCooldown;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const OVERRIDE
+ {
+ return GetIcecrownCitadelAI<npc_high_overlord_saurfang_igbAI>(creature);
+ }
+};
+
+class npc_muradin_bronzebeard_igb : public CreatureScript
+{
+ public:
+ npc_muradin_bronzebeard_igb() : CreatureScript("npc_muradin_bronzebeard_igb") { }
+
+ struct npc_muradin_bronzebeard_igbAI : public ScriptedAI
+ {
+ npc_muradin_bronzebeard_igbAI(Creature* creature) : ScriptedAI(creature),
+ _instance(creature->GetInstanceScript())
+ {
+ _controller.ResetSlots(ALLIANCE);
+ _controller.SetTransport(creature->GetTransport());
+ me->setRegeneratingHealth(false);
+ me->m_CombatDistance = 70.0f;
+ _firstMageCooldown = time(NULL) + 60;
+ _riflemanYellCooldown = time_t(0);
+ _mortarYellCooldown = time_t(0);
+ }
+
+ void InitializeAI() OVERRIDE
+ {
+ ScriptedAI::InitializeAI();
+
+ _events.Reset();
+ _firstMageCooldown = time(NULL) + 60;
+ _riflemanYellCooldown = time_t(0);
+ _mortarYellCooldown = time_t(0);
+ }
+
+ void EnterCombat(Unit* /*target*/) OVERRIDE
+ {
+ _events.SetPhase(PHASE_COMBAT);
+ DoCast(me, _instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE ? SPELL_FRIENDLY_BOSS_DAMAGE_MOD : SPELL_MELEE_TARGETING_ON_SKYBREAKER, true);
+ DoCast(me, SPELL_BATTLE_FURY, true);
+ _events.ScheduleEvent(EVENT_CLEAVE, urand(2000, 10000));
+ }
+
+ void EnterEvadeMode() OVERRIDE
+ {
+ if (!me->IsAlive())
+ return;
+
+ me->DeleteThreatList();
+ me->CombatStop(true);
+ me->GetMotionMaster()->MoveTargetedHome();
+
+ Reset();
+ }
+
+ void DoAction(int32 action) OVERRIDE
+ {
+ if (action == ACTION_ENEMY_GUNSHIP_TALK)
+ {
+ if (Creature* muradin = me->FindNearestCreature(NPC_IGB_HIGH_OVERLORD_SAURFANG, 100.0f))
+ muradin->AI()->DoAction(ACTION_SPAWN_ALL_ADDS);
+
+ Talk(SAY_MURADIN_INTRO_6);
+ _events.ScheduleEvent(EVENT_INTRO_A_6, 5000);
+ _events.ScheduleEvent(EVENT_INTRO_A_7, 11000);
+ _events.ScheduleEvent(EVENT_KEEP_PLAYER_IN_COMBAT, 1);
+
+ _instance->SetBossState(DATA_ICECROWN_GUNSHIP_BATTLE, IN_PROGRESS);
+ // Combat starts now
+ if (Creature* orgrimsHammer = me->FindNearestCreature(NPC_ORGRIMS_HAMMER, 100.0f))
+ _instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, orgrimsHammer, 1);
+
+ if (Creature* skybreaker = me->FindNearestCreature(NPC_THE_SKYBREAKER, 100.0f))
+ {
+ _instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, skybreaker, 2);
+ skybreaker->CastSpell(skybreaker, SPELL_CHECK_FOR_PLAYERS, TRIGGERED_FULL_MASK);
+ }
+
+ me->GetMap()->SetZoneMusic(AREA_ICECROWN_CITADEL, MUSIC_ENCOUNTER);
+ }
+ else if (action == ACTION_SPAWN_MAGE)
+ {
+ time_t now = time(NULL);
+ if (_firstMageCooldown > now)
+ _events.ScheduleEvent(EVENT_SUMMON_MAGE, (_firstMageCooldown - now) * IN_MILLISECONDS);
+ else
+ _events.ScheduleEvent(EVENT_SUMMON_MAGE, 1);
+ }
+ else if (action == ACTION_SPAWN_ALL_ADDS)
+ {
+ _events.ScheduleEvent(EVENT_ADDS, 12000);
+ _events.ScheduleEvent(EVENT_CHECK_RIFLEMAN, 13000);
+ _events.ScheduleEvent(EVENT_CHECK_MORTAR, 13000);
+ if (Is25ManRaid())
+ _controller.SummonCreatures(SLOT_MAGE_1, SLOT_MORTAR_4);
+ else
+ {
+ _controller.SummonCreatures(SLOT_MAGE_1, SLOT_MAGE_2);
+ _controller.SummonCreatures(SLOT_MORTAR_1, SLOT_MORTAR_2);
+ _controller.SummonCreatures(SLOT_RIFLEMAN_1, SLOT_RIFLEMAN_4);
+ }
+ }
+ else if (action == ACTION_EXIT_SHIP)
+ {
+ Position pos;
+ pos.Relocate(MuradinExitPath[MuradinExitPathSize - 1].x, MuradinExitPath[MuradinExitPathSize - 1].y, MuradinExitPath[MuradinExitPathSize - 1].z);
+ me->GetMotionMaster()->MovePoint(EVENT_CHARGE_PREPATH, pos, false);
+
+ Movement::PointsArray path(MuradinExitPath, MuradinExitPath + MuradinExitPathSize);
+
+ Movement::MoveSplineInit init(me);
+ init.DisableTransportPathTransformations();
+ init.MovebyPath(path, 0);
+ init.Launch();
+
+ me->DespawnOrUnsummon(18000);
+ }
+ }
+
+ void SetData(uint32 type, uint32 data) OVERRIDE
+ {
+ if (type == ACTION_CLEAR_SLOT)
+ {
+ _controller.ClearSlot(PassengerSlots(data));
+ if (data == SLOT_FREEZE_MAGE)
+ _events.ScheduleEvent(EVENT_SUMMON_MAGE, urand(30000, 33500));
+ }
+ }
+
+ void sGossipSelect(Player* /*player*/, uint32 /*sender*/, uint32 /*action*/) OVERRIDE
+ {
+ me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
+ me->GetTransport()->EnableMovement(true);
+ _events.SetPhase(PHASE_INTRO);
+ _events.ScheduleEvent(EVENT_INTRO_A_1, 5000);
+ _events.ScheduleEvent(EVENT_INTRO_A_2, 10000, 0, PHASE_INTRO);
+ _events.ScheduleEvent(EVENT_INTRO_SUMMON_ORGRIMS_HAMMER, 28000, 0, PHASE_INTRO);
+ _events.ScheduleEvent(EVENT_INTRO_A_3, 33000, 0, PHASE_INTRO);
+ _events.ScheduleEvent(EVENT_INTRO_A_4, 39000, 0, PHASE_INTRO);
+ _events.ScheduleEvent(EVENT_INTRO_A_5, 45000, 0, PHASE_INTRO);
+ }
+
+ void DamageTaken(Unit* , uint32& damage) OVERRIDE
+ {
+ if (me->HealthBelowPctDamaged(65, damage) && me->HasAura(SPELL_TASTE_OF_BLOOD))
+ DoCast(me, SPELL_TASTE_OF_BLOOD, true);
+
+ if (damage >= me->GetHealth())
+ damage = me->GetHealth() - 1;
+ }
+
+ void UpdateAI(uint32 diff) OVERRIDE
+ {
+ if (!UpdateVictim() && !_events.IsInPhase(PHASE_INTRO) && _instance->GetBossState(DATA_ICECROWN_GUNSHIP_BATTLE) != IN_PROGRESS)
+ return;
+
+ _events.Update(diff);
+
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_INTRO_A_1:
+ Talk(SAY_MURADIN_INTRO_1);
+ break;
+ case EVENT_INTRO_A_2:
+ Talk(SAY_MURADIN_INTRO_2);
+ break;
+ case EVENT_INTRO_SUMMON_ORGRIMS_HAMMER:
+ sTransportMgr->CreateTransport(GO_ORGRIMS_HAMMER_A, 0, me->GetMap());
+ break;
+ case EVENT_INTRO_A_3:
+ Talk(SAY_MURADIN_INTRO_3);
+ break;
+ case EVENT_INTRO_A_4:
+ Talk(SAY_MURADIN_INTRO_4);
+ break;
+ case EVENT_INTRO_A_5:
+ Talk(SAY_MURADIN_INTRO_5);
+ break;
+ case EVENT_INTRO_A_6:
+ if (Creature* saurfang = me->FindNearestCreature(NPC_IGB_HIGH_OVERLORD_SAURFANG, 100.0f))
+ saurfang->AI()->Talk(SAY_SAURFANG_INTRO_A);
+ break;
+ case EVENT_INTRO_A_7:
+ Talk(SAY_MURADIN_INTRO_7);
+ break;
+ case EVENT_KEEP_PLAYER_IN_COMBAT:
+ if (_instance->GetBossState(DATA_ICECROWN_GUNSHIP_BATTLE) == IN_PROGRESS)
+ {
+ _instance->DoCastSpellOnPlayers(SPELL_LOCK_PLAYERS_AND_TAP_CHEST);
+ _events.ScheduleEvent(EVENT_KEEP_PLAYER_IN_COMBAT, urand(5000, 8000));
+ }
+ break;
+ case EVENT_SUMMON_MAGE:
+ Talk(SAY_MURADIN_SORCERERS);
+ _controller.SummonCreatures(SLOT_FREEZE_MAGE, SLOT_FREEZE_MAGE);
+ break;
+ case EVENT_ADDS:
+ Talk(SAY_MURADIN_ENTER_ORGRIMMS_HAMMER);
+ _controller.SummonCreatures(SLOT_MAGE_1, SLOT_MAGE_2);
+ _controller.SummonCreatures(SLOT_MARINE_1, Is25ManRaid() ? SLOT_MARINE_4 : SLOT_MARINE_2);
+ _controller.SummonCreatures(SLOT_SERGEANT_1, Is25ManRaid() ? SLOT_SERGEANT_2 : SLOT_SERGEANT_1);
+ if (Transport* skybreaker = me->GetTransport())
+ skybreaker->SummonPassenger(NPC_TELEPORT_PORTAL, SkybreakerTeleportPortal, TEMPSUMMON_TIMED_DESPAWN, NULL, 21000);
+
+ if (GameObject* go = HashMapHolder<GameObject>::Find(_instance->GetData64(DATA_ICECROWN_GUNSHIP_BATTLE)))
+ if (Transport* orgrimsHammer = go->ToTransport())
+ orgrimsHammer->SummonPassenger(NPC_TELEPORT_EXIT, OrgrimsHammerTeleportExit, TEMPSUMMON_TIMED_DESPAWN, NULL, 23000);
+
+ _events.ScheduleEvent(EVENT_ADDS_BOARD_YELL, 6000);
+ _events.ScheduleEvent(EVENT_ADDS, 60000);
+ break;
+ case EVENT_ADDS_BOARD_YELL:
+ if (Creature* saurfang = me->FindNearestCreature(NPC_IGB_HIGH_OVERLORD_SAURFANG, 200.0f))
+ saurfang->AI()->Talk(SAY_SAURFANG_BOARD);
+ break;
+ case EVENT_CHECK_RIFLEMAN:
+ if (_controller.SummonCreatures(SLOT_RIFLEMAN_1, Is25ManRaid() ? SLOT_RIFLEMAN_8 : SLOT_RIFLEMAN_4))
+ {
+ if (_riflemanYellCooldown < time(NULL))
+ {
+ Talk(SAY_MURADIN_RIFLEMAN);
+ _riflemanYellCooldown = time(NULL) + 5;
+ }
+ }
+ _events.ScheduleEvent(EVENT_CHECK_RIFLEMAN, 1000);
+ break;
+ case EVENT_CHECK_MORTAR:
+ if (_controller.SummonCreatures(SLOT_MORTAR_1, Is25ManRaid() ? SLOT_MORTAR_4 : SLOT_MORTAR_2))
+ {
+ if (_mortarYellCooldown < time(NULL))
+ {
+ Talk(SAY_MURADIN_MORTAR);
+ _mortarYellCooldown = time(NULL) + 5;
+ }
+ }
+ _events.ScheduleEvent(EVENT_CHECK_MORTAR, 1000);
+ break;
+ case EVENT_CLEAVE:
+ DoCastVictim(SPELL_CLEAVE);
+ _events.ScheduleEvent(EVENT_CLEAVE, urand(2000, 10000));
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (me->IsWithinMeleeRange(me->GetVictim()))
+ DoMeleeAttackIfReady();
+ else if (me->isAttackReady())
+ {
+ DoCastVictim(SPELL_RENDING_THROW);
+ me->resetAttackTimer();
+ }
+ }
+
+ bool CanAIAttack(Unit const* target) const OVERRIDE
+ {
+ if (_instance->GetBossState(DATA_ICECROWN_GUNSHIP_BATTLE) != IN_PROGRESS)
+ return false;
+ return target->HasAura(SPELL_ON_SKYBREAKER_DECK) || target->GetEntry() == NPC_KOR_KRON_REAVER || target->GetEntry() == NPC_KOR_KRON_SERGEANT;
+ }
+
+ private:
+ EventMap _events;
+ PassengerController _controller;
+ InstanceScript* _instance;
+ time_t _firstMageCooldown;
+ time_t _riflemanYellCooldown;
+ time_t _mortarYellCooldown;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const OVERRIDE
+ {
+ return GetIcecrownCitadelAI<npc_muradin_bronzebeard_igbAI>(creature);
+ }
+};
+
+class npc_zafod_boombox : public CreatureScript
+{
+ public:
+ npc_zafod_boombox() : CreatureScript("npc_zafod_boombox") { }
+
+ struct npc_zafod_boomboxAI : public gunship_npc_AI
+ {
+ npc_zafod_boomboxAI(Creature* creature) : gunship_npc_AI(creature)
+ {
+ }
+
+ void Reset() OVERRIDE
+ {
+ me->SetReactState(REACT_PASSIVE);
+ }
+
+ void sGossipSelect(Player* player, uint32 /*sender*/, uint32 /*action*/) OVERRIDE
+ {
+ player->AddItem(ITEM_GOBLIN_ROCKET_PACK, 1);
+ player->PlayerTalkClass->SendCloseGossip();
+ }
+
+ void UpdateAI(uint32 /*diff*/) OVERRIDE
+ {
+ UpdateVictim();
+ }
+ };
+
+ CreatureAI* GetAI(Creature* creature) const OVERRIDE
+ {
+ return GetIcecrownCitadelAI<npc_zafod_boomboxAI>(creature);
+ }
+};
+
+struct npc_gunship_boarding_addAI : public gunship_npc_AI
+{
+ npc_gunship_boarding_addAI(Creature* creature) : gunship_npc_AI(creature)
+ {
+ me->m_CombatDistance = 80.0f;
+ _usedDesperateResolve = false;
+ }
+
+ void SetData(uint32 type, uint32 data) OVERRIDE
+ {
+ // detach from captain
+ if (type == ACTION_SET_SLOT)
+ {
+ SetSlotInfo(data);
+
+ me->SetReactState(REACT_PASSIVE);
+
+ me->m_Events.AddEvent(new DelayedMovementEvent(me, Slot->TargetPosition), me->m_Events.CalculateTime(3000 * (Index - SLOT_MARINE_1)));
+
+ if (Creature* captain = me->FindNearestCreature(Instance->GetData(DATA_TEAM_IN_INSTANCE) == HORDE ? NPC_IGB_MURADIN_BRONZEBEARD : NPC_IGB_HIGH_OVERLORD_SAURFANG, 200.0f))
+ captain->AI()->SetData(ACTION_CLEAR_SLOT, Index);
+ }
+ }
+
+ void MovementInform(uint32 type, uint32 pointId) OVERRIDE
+ {
+ if (type != POINT_MOTION_TYPE)
+ return;
+
+ if (pointId == EVENT_CHARGE_PREPATH && Slot)
+ {
+ Position const& otherTransportPos = Instance->GetData(DATA_TEAM_IN_INSTANCE) == HORDE ? OrgrimsHammerTeleportExit : SkybreakerTeleportExit;
+ float x, y, z, o;
+ otherTransportPos.GetPosition(x, y, z, o);
+
+ Transport* myTransport = me->GetTransport();
+ if (!myTransport)
+ return;
+
+ if (GameObject* go = HashMapHolder<GameObject>::Find(Instance->GetData64(DATA_ICECROWN_GUNSHIP_BATTLE)))
+ if (Transport* destTransport = go->ToTransport())
+ destTransport->CalculatePassengerPosition(x, y, z, &o);
+
+ float angle = frand(0, M_PI * 2.0f);
+ x += 2.0f * std::cos(angle);
+ y += 2.0f * std::sin(angle);
+
+ me->SetHomePosition(x, y, z, o);
+ myTransport->CalculatePassengerOffset(x, y, z, &o);
+ me->SetTransportHomePosition(x, y, z, o);
+
+ me->m_Events.AddEvent(new BattleExperienceEvent(me), me->m_Events.CalculateTime(BattleExperienceEvent::ExperiencedTimes[0]));
+ DoCast(me, SPELL_BATTLE_EXPERIENCE, true);
+ DoCast(me, SPELL_TELEPORT_TO_ENEMY_SHIP, true);
+ DoCast(me, Instance->GetData(DATA_TEAM_IN_INSTANCE) == HORDE ? SPELL_MELEE_TARGETING_ON_ORGRIMS_HAMMER : SPELL_MELEE_TARGETING_ON_SKYBREAKER, true);
+ me->_AddCreatureSpellCooldown(BurningPitchId, time(NULL) + 3);
+
+ std::list<Player*> players;
+ Trinity::UnitAuraCheck check(true, Instance->GetData(DATA_TEAM_IN_INSTANCE) == HORDE ? SPELL_ON_ORGRIMS_HAMMER_DECK : SPELL_ON_SKYBREAKER_DECK);
+ Trinity::PlayerListSearcher<Trinity::UnitAuraCheck> searcher(me, players, check);
+ me->VisitNearbyWorldObject(200.0f, searcher);
+
+ players.remove_if([this](Player* player)
+ {
+ return !me->_IsTargetAcceptable(player) || !me->CanStartAttack(player, true);
+ });
+
+ if (!players.empty())
+ {
+ players.sort(Trinity::ObjectDistanceOrderPred(me));
+ for (std::list<Player*>::iterator itr = players.begin(); itr != players.end(); ++itr)
+ me->AddThreat(*itr, 1.0f);
+
+ AttackStart(players.front());
+ }
+
+ me->SetReactState(REACT_AGGRESSIVE);
+ }
+ }
+
+ void DamageTaken(Unit* /*attacker*/, uint32& damage) OVERRIDE
+ {
+ if (_usedDesperateResolve)
+ return;
+
+ if (!me->HealthBelowPctDamaged(25, damage))
+ return;
+
+ _usedDesperateResolve = true;
+ DoCast(me, SPELL_DESPERATE_RESOLVE, true);
+ }
+
+ void UpdateAI(uint32 /*diff*/) OVERRIDE
+ {
+ if (!SelectVictim())
+ {
+ TriggerBurningPitch();
+ return;
+ }
+
+ if (!HasAttackablePlayerNearby())
+ TriggerBurningPitch();
+
+ DoMeleeAttackIfReady();
+ }
+
+ bool CanAIAttack(Unit const* target) const OVERRIDE
+ {
+ uint32 spellId = SPELL_ON_SKYBREAKER_DECK;
+ uint32 creatureEntry = NPC_IGB_MURADIN_BRONZEBEARD;
+ if (Instance->GetData(DATA_TEAM_IN_INSTANCE) == HORDE)
+ {
+ spellId = SPELL_ON_ORGRIMS_HAMMER_DECK;
+ creatureEntry = NPC_IGB_HIGH_OVERLORD_SAURFANG;
+ }
+
+ return target->HasAura(spellId) || target->GetEntry() == creatureEntry;
+ }
+
+ bool HasAttackablePlayerNearby()
+ {
+ std::list<Player*> players;
+ Trinity::UnitAuraCheck check(true, Instance->GetData(DATA_TEAM_IN_INSTANCE) == HORDE ? SPELL_ON_ORGRIMS_HAMMER_DECK : SPELL_ON_SKYBREAKER_DECK);
+ Trinity::PlayerListSearcher<Trinity::UnitAuraCheck> searcher(me, players, check);
+ me->VisitNearbyWorldObject(200.0f, searcher);
+
+ players.remove_if([this](Player* player)
+ {
+ return !me->_IsTargetAcceptable(player) || !me->CanStartAttack(player, true);
+ });
+
+ return !players.empty();
+ }
+
+private:
+ bool _usedDesperateResolve;
+};
+
+class npc_gunship_boarding_leader : public CreatureScript
+{
+ public:
+ npc_gunship_boarding_leader() : CreatureScript("npc_gunship_boarding_leader") { }
+
+ struct npc_gunship_boarding_leaderAI : public npc_gunship_boarding_addAI
+ {
+ npc_gunship_boarding_leaderAI(Creature* creature) : npc_gunship_boarding_addAI(creature)
+ {
+ }
+
+ void EnterCombat(Unit* target) OVERRIDE
+ {
+ npc_gunship_boarding_addAI::EnterCombat(target);
+ _events.ScheduleEvent(EVENT_BLADESTORM, urand(13000, 18000));
+ _events.ScheduleEvent(EVENT_WOUNDING_STRIKE, urand(8000, 10000));
+ }
+
+ void UpdateAI(uint32 diff) OVERRIDE
+ {
+ if (!SelectVictim())
+ {
+ TriggerBurningPitch();
+ return;
+ }
+
+ _events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING) || me->HasAura(SPELL_BLADESTORM))
+ return;
+
+ if (!HasAttackablePlayerNearby())
+ TriggerBurningPitch();
+
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_BLADESTORM:
+ DoCastAOE(SPELL_BLADESTORM);
+ _events.ScheduleEvent(EVENT_BLADESTORM, urand(25000, 30000));
+ break;
+ case EVENT_WOUNDING_STRIKE:
+ DoCastVictim(SPELL_WOUNDING_STRIKE);
+ _events.ScheduleEvent(EVENT_WOUNDING_STRIKE, urand(9000, 13000));
+ break;
+ default:
+ break;
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ }
+
+ private:
+ EventMap _events;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const OVERRIDE
+ {
+ return GetIcecrownCitadelAI<npc_gunship_boarding_leaderAI>(creature);
+ }
+};
+
+class npc_gunship_boarding_add : public CreatureScript
+{
+ public:
+ npc_gunship_boarding_add() : CreatureScript("npc_gunship_boarding_add") { }
+
+
+ CreatureAI* GetAI(Creature* creature) const OVERRIDE
+ {
+ return GetIcecrownCitadelAI<npc_gunship_boarding_addAI>(creature);
+ }
+};
+
+class npc_gunship_gunner : public CreatureScript
+{
+ public:
+ npc_gunship_gunner() : CreatureScript("npc_gunship_gunner") { }
+
+ struct npc_gunship_gunnerAI : public gunship_npc_AI
+ {
+ npc_gunship_gunnerAI(Creature* creature) : gunship_npc_AI(creature)
+ {
+ creature->m_CombatDistance = 200.0f;
+ }
+
+ void AttackStart(Unit* target) OVERRIDE
+ {
+ me->Attack(target, false);
+ }
+
+ void MovementInform(uint32 type, uint32 pointId) OVERRIDE
+ {
+ gunship_npc_AI::MovementInform(type, pointId);
+ if (type == POINT_MOTION_TYPE && pointId == EVENT_CHARGE_PREPATH)
+ me->SetControlled(true, UNIT_STATE_ROOT);
+ }
+
+ void UpdateAI(uint32 /*diff*/) OVERRIDE
+ {
+ if (!SelectVictim())
+ {
+ TriggerBurningPitch();
+ return;
+ }
+
+ DoSpellAttackIfReady(me->GetEntry() == NPC_SKYBREAKER_RIFLEMAN ? SPELL_SHOOT : SPELL_HURL_AXE);
+ }
+ };
+
+ CreatureAI* GetAI(Creature* creature) const OVERRIDE
+ {
+ return GetIcecrownCitadelAI<npc_gunship_gunnerAI>(creature);
+ }
+};
+
+class npc_gunship_rocketeer : public CreatureScript
+{
+ public:
+ npc_gunship_rocketeer() : CreatureScript("npc_gunship_rocketeer") { }
+
+ struct npc_gunship_rocketeerAI : public gunship_npc_AI
+ {
+ npc_gunship_rocketeerAI(Creature* creature) : gunship_npc_AI(creature)
+ {
+ creature->m_CombatDistance = 200.0f;
+ }
+
+ void MovementInform(uint32 type, uint32 pointId) OVERRIDE
+ {
+ gunship_npc_AI::MovementInform(type, pointId);
+ if (type == POINT_MOTION_TYPE && pointId == EVENT_CHARGE_PREPATH)
+ me->SetControlled(true, UNIT_STATE_ROOT);
+ }
+
+ void UpdateAI(uint32 /*diff*/) OVERRIDE
+ {
+ if (!SelectVictim())
+ return;
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ uint32 spellId = me->GetEntry() == NPC_SKYBREAKER_MORTAR_SOLDIER ? SPELL_ROCKET_ARTILLERY_A : SPELL_ROCKET_ARTILLERY_H;
+ if (me->HasSpellCooldown(spellId))
+ return;
+
+ DoCastAOE(spellId, true);
+ me->_AddCreatureSpellCooldown(spellId, time(NULL) + 9);
+ }
+ };
+
+ CreatureAI* GetAI(Creature* creature) const OVERRIDE
+ {
+ return GetIcecrownCitadelAI<npc_gunship_rocketeerAI>(creature);
+ }
+};
+
+class npc_gunship_mage : public CreatureScript
+{
+ public:
+ npc_gunship_mage() : CreatureScript("npc_gunship_mage") { }
+
+ struct npc_gunship_mageAI : public gunship_npc_AI
+ {
+ npc_gunship_mageAI(Creature* creature) : gunship_npc_AI(creature)
+ {
+ me->SetReactState(REACT_PASSIVE);
+ }
+
+ void EnterEvadeMode() OVERRIDE
+ {
+ ScriptedAI::EnterEvadeMode();
+ }
+
+ void MovementInform(uint32 type, uint32 pointId) OVERRIDE
+ {
+ if (type != POINT_MOTION_TYPE)
+ return;
+
+ if (pointId == EVENT_CHARGE_PREPATH && Slot)
+ {
+ SlotInfo const* slots = Instance->GetData(DATA_TEAM_IN_INSTANCE) == HORDE ? SkybreakerSlotInfo : OrgrimsHammerSlotInfo;
+ me->SetFacingTo(slots[Index].TargetPosition.GetOrientation());
+ switch (Index)
+ {
+ case SLOT_FREEZE_MAGE:
+ DoCastAOE(SPELL_BELOW_ZERO);
+ break;
+ case SLOT_MAGE_1:
+ case SLOT_MAGE_2:
+ DoCastAOE(SPELL_SHADOW_CHANNELING);
+ break;
+ default:
+ break;
+ }
+
+ me->SetControlled(true, UNIT_STATE_ROOT);
+ }
+ }
+
+ void UpdateAI(uint32 /*diff*/) OVERRIDE
+ {
+ UpdateVictim();
+ }
+
+ bool CanAIAttack(Unit const* /*target*/) const OVERRIDE
+ {
+ return true;
+ }
+ };
+
+ CreatureAI* GetAI(Creature* creature) const OVERRIDE
+ {
+ return GetIcecrownCitadelAI<npc_gunship_mageAI>(creature);
+ }
+};
+
+/** @HACK This AI only resets MOVEMENTFLAG_ROOT on the vehicle.
+ Currently the core always removes MOVEMENTFLAG_ROOT sent from client packets to prevent cheaters from freezing clients of other players
+ but it actually is a valid flag - needs more research to fix both freezes and keep the flag as is (see WorldSession::ReadMovementInfo)
+
+Example packet:
+ClientToServer: CMSG_FORCE_MOVE_ROOT_ACK (0x00E9) Length: 67 ConnectionIndex: 0 Time: 03/04/2010 03:57:55.000 Number: 471326
+Guid:
+Movement Counter: 80
+Movement Flags: OnTransport, Root (2560)
+Extra Movement Flags: None (0)
+Time: 52291611
+Position: X: -396.0302 Y: 2482.906 Z: 249.86
+Orientation: 1.468665
+Transport GUID: Full: 0x1FC0000000000460 Type: MOTransport Low: 1120
+Transport Position: X: -6.152398 Y: -23.49037 Z: 21.64464 O: 4.827727
+Transport Time: 9926
+Transport Seat: 255
+Fall Time: 824
+*/
+class npc_gunship_cannon : public CreatureScript
+{
+ public:
+ npc_gunship_cannon() : CreatureScript("npc_gunship_cannon") { }
+
+ struct npc_gunship_cannonAI : public PassiveAI
+ {
+ npc_gunship_cannonAI(Creature* creature) : PassiveAI(creature)
+ {
+ }
+
+ void OnCharmed(bool /*apply*/) OVERRIDE { }
+
+ void PassengerBoarded(Unit* /*passenger*/, int8 /*seat*/, bool apply) OVERRIDE
+ {
+ if (!apply)
+ {
+ me->SetControlled(false, UNIT_STATE_ROOT);
+ me->SetControlled(true, UNIT_STATE_ROOT);
+ }
+ }
+ };
+
+ CreatureAI* GetAI(Creature* creature) const OVERRIDE
+ {
+ return new npc_gunship_cannonAI(creature);
+ }
+};
+
+class spell_igb_rocket_pack : public SpellScriptLoader
+{
+ public:
+ spell_igb_rocket_pack() : SpellScriptLoader("spell_igb_rocket_pack") { }
+
+ class spell_igb_rocket_pack_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_igb_rocket_pack_AuraScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) OVERRIDE
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_ROCKET_PACK_DAMAGE) ||
+ !sSpellMgr->GetSpellInfo(SPELL_ROCKET_BURST))
+ return false;
+
+ return true;
+ }
+
+ void HandlePeriodic(AuraEffect const* /*aurEff*/)
+ {
+ if (GetTarget()->movespline->Finalized())
+ Remove(AURA_REMOVE_BY_EXPIRE);
+ }
+
+ void HandleRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
+ {
+ SpellInfo const* damageInfo = sSpellMgr->EnsureSpellInfo(SPELL_ROCKET_PACK_DAMAGE);
+ GetTarget()->CastCustomSpell(SPELL_ROCKET_PACK_DAMAGE, SPELLVALUE_BASE_POINT0, 2 * (damageInfo->Effects[EFFECT_0].CalcValue() + aurEff->GetTickNumber() * aurEff->GetAmplitude()), NULL, TRIGGERED_FULL_MASK);
+ GetTarget()->CastSpell(NULL, SPELL_ROCKET_BURST, TRIGGERED_FULL_MASK);
+ }
+
+ void Register() OVERRIDE
+ {
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_igb_rocket_pack_AuraScript::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
+ OnEffectRemove += AuraEffectRemoveFn(spell_igb_rocket_pack_AuraScript::HandleRemove, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL);
+ }
+ };
+
+ AuraScript* GetAuraScript() const OVERRIDE
+ {
+ return new spell_igb_rocket_pack_AuraScript();
+ }
+};
+
+class spell_igb_rocket_pack_useable : public SpellScriptLoader
+{
+ public:
+ spell_igb_rocket_pack_useable() : SpellScriptLoader("spell_igb_rocket_pack_useable") { }
+
+ class spell_igb_rocket_pack_useable_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_igb_rocket_pack_useable_AuraScript);
+
+ bool Load()
+ {
+ return GetOwner()->GetInstanceScript();
+ }
+
+ bool CheckAreaTarget(Unit* target)
+ {
+ return target->GetTypeId() == TYPEID_PLAYER && GetOwner()->GetInstanceScript()->GetBossState(DATA_ICECROWN_GUNSHIP_BATTLE) != DONE;
+ }
+
+ void HandleApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ if (Creature* owner = GetOwner()->ToCreature())
+ if (Player* target = GetTarget()->ToPlayer())
+ if (target->HasItemCount(ITEM_GOBLIN_ROCKET_PACK, 1))
+ sCreatureTextMgr->SendChat(owner, SAY_ZAFOD_ROCKET_PACK_ACTIVE, target, CHAT_MSG_ADDON, LANG_ADDON, TEXT_RANGE_NORMAL, 0, TEAM_OTHER, false, target);
+ }
+
+ void HandleRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ if (Creature* owner = GetOwner()->ToCreature())
+ if (Player* target = GetTarget()->ToPlayer())
+ if (target->HasItemCount(ITEM_GOBLIN_ROCKET_PACK, 1))
+ sCreatureTextMgr->SendChat(owner, SAY_ZAFOD_ROCKET_PACK_DISABLED, target, CHAT_MSG_ADDON, LANG_ADDON, TEXT_RANGE_NORMAL, 0, TEAM_OTHER, false, target);
+ }
+
+ void Register() OVERRIDE
+ {
+ DoCheckAreaTarget += AuraCheckAreaTargetFn(spell_igb_rocket_pack_useable_AuraScript::CheckAreaTarget);
+ AfterEffectApply += AuraEffectApplyFn(spell_igb_rocket_pack_useable_AuraScript::HandleApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
+ AfterEffectRemove += AuraEffectRemoveFn(spell_igb_rocket_pack_useable_AuraScript::HandleRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
+ }
+ };
+
+ AuraScript* GetAuraScript() const OVERRIDE
+ {
+ return new spell_igb_rocket_pack_useable_AuraScript();
+ }
+};
+
+class spell_igb_on_gunship_deck : public SpellScriptLoader
+{
+ public:
+ spell_igb_on_gunship_deck() : SpellScriptLoader("spell_igb_on_gunship_deck") { }
+
+ class spell_igb_on_gunship_deck_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_igb_on_gunship_deck_AuraScript);
+
+ bool Load() OVERRIDE
+ {
+ if (InstanceScript* instance = GetOwner()->GetInstanceScript())
+ _teamInInstance = instance->GetData(DATA_TEAM_IN_INSTANCE);
+ else
+ _teamInInstance = 0;
+ return true;
+ }
+
+ bool CheckAreaTarget(Unit* unit)
+ {
+ return unit->GetTypeId() == TYPEID_PLAYER;
+ }
+
+ void HandleApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ if (GetSpellInfo()->Id == uint32(_teamInInstance == HORDE ? SPELL_ON_SKYBREAKER_DECK : SPELL_ON_ORGRIMS_HAMMER_DECK))
+ if (Creature* gunship = GetOwner()->FindNearestCreature(_teamInInstance == HORDE ? NPC_ORGRIMS_HAMMER : NPC_THE_SKYBREAKER, 200.0f))
+ gunship->AI()->SetGUID(GetTarget()->GetGUID(), ACTION_SHIP_VISITS);
+ }
+
+ void Register() OVERRIDE
+ {
+ DoCheckAreaTarget += AuraCheckAreaTargetFn(spell_igb_on_gunship_deck_AuraScript::CheckAreaTarget);
+ AfterEffectApply += AuraEffectApplyFn(spell_igb_on_gunship_deck_AuraScript::HandleApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
+ }
+
+ uint32 _teamInInstance;
+ };
+
+ AuraScript* GetAuraScript() const OVERRIDE
+ {
+ return new spell_igb_on_gunship_deck_AuraScript();
+ }
+};
+
+class spell_igb_periodic_trigger_with_power_cost : public SpellScriptLoader
+{
+ public:
+ spell_igb_periodic_trigger_with_power_cost() : SpellScriptLoader("spell_igb_periodic_trigger_with_power_cost") { }
+
+ class spell_igb_periodic_trigger_with_power_cost_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_igb_periodic_trigger_with_power_cost_AuraScript);
+
+ void HandlePeriodicTick(AuraEffect const* /*aurEff*/)
+ {
+ PreventDefaultAction();
+ GetTarget()->CastSpell(GetTarget(), GetSpellInfo()->Effects[EFFECT_0].TriggerSpell, TriggerCastFlags(TRIGGERED_FULL_MASK & ~TRIGGERED_IGNORE_POWER_AND_REAGENT_COST));
+ }
+
+ void Register() OVERRIDE
+ {
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_igb_periodic_trigger_with_power_cost_AuraScript::HandlePeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
+ }
+ };
+
+ AuraScript* GetAuraScript() const OVERRIDE
+ {
+ return new spell_igb_periodic_trigger_with_power_cost_AuraScript();
+ }
+};
+
+class spell_igb_cannon_blast : public SpellScriptLoader
+{
+ public:
+ spell_igb_cannon_blast() : SpellScriptLoader("spell_igb_cannon_blast") { }
+
+ class spell_igb_cannon_blast_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_igb_cannon_blast_SpellScript);
+
+ bool Load()
+ {
+ return GetCaster()->GetTypeId() == TYPEID_UNIT;
+ }
+
+ void CheckEnergy()
+ {
+ if (GetCaster()->GetPower(POWER_ENERGY) >= 100)
+ {
+ GetCaster()->CastSpell(GetCaster(), SPELL_OVERHEAT, TRIGGERED_FULL_MASK);
+ if (Vehicle* vehicle = GetCaster()->GetVehicleKit())
+ if (Unit* passenger = vehicle->GetPassenger(0))
+ sCreatureTextMgr->SendChat(GetCaster()->ToCreature(), SAY_OVERHEAT, passenger);
+ }
+ }
+
+ void Register() OVERRIDE
+ {
+ AfterHit += SpellHitFn(spell_igb_cannon_blast_SpellScript::CheckEnergy);
+ }
+ };
+
+ SpellScript* GetSpellScript() const OVERRIDE
+ {
+ return new spell_igb_cannon_blast_SpellScript();
+ }
+};
+
+class spell_igb_incinerating_blast : public SpellScriptLoader
+{
+ public:
+ spell_igb_incinerating_blast() : SpellScriptLoader("spell_igb_incinerating_blast") { }
+
+ class spell_igb_incinerating_blast_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_igb_incinerating_blast_SpellScript);
+
+ void StoreEnergy()
+ {
+ _energyLeft = GetCaster()->GetPower(POWER_ENERGY) - 10;
+ }
+
+ void RemoveEnergy()
+ {
+ GetCaster()->SetPower(POWER_ENERGY, 0);
+ }
+
+ void CalculateDamage(SpellEffIndex /*effIndex*/)
+ {
+ SetEffectValue(GetEffectValue() + _energyLeft * _energyLeft * 8);
+ }
+
+ void Register() OVERRIDE
+ {
+ OnCast += SpellCastFn(spell_igb_incinerating_blast_SpellScript::StoreEnergy);
+ AfterCast += SpellCastFn(spell_igb_incinerating_blast_SpellScript::RemoveEnergy);
+ OnEffectLaunchTarget += SpellEffectFn(spell_igb_incinerating_blast_SpellScript::CalculateDamage, EFFECT_1, SPELL_EFFECT_SCHOOL_DAMAGE);
+ }
+
+ uint32 _energyLeft;
+ };
+
+ SpellScript* GetSpellScript() const OVERRIDE
+ {
+ return new spell_igb_incinerating_blast_SpellScript();
+ }
+};
+
+class spell_igb_overheat : public SpellScriptLoader
+{
+ public:
+ spell_igb_overheat() : SpellScriptLoader("spell_igb_overheat") { }
+
+ class spell_igb_overheat_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_igb_overheat_AuraScript);
+
+ bool Load() OVERRIDE
+ {
+ if (GetAura()->GetType() != UNIT_AURA_TYPE)
+ return false;
+ return GetUnitOwner()->IsVehicle();
+ }
+
+ void SendClientControl(uint8 value)
+ {
+ if (Vehicle* vehicle = GetUnitOwner()->GetVehicleKit())
+ {
+ if (Unit* passenger = vehicle->GetPassenger(0))
+ {
+ if (Player* player = passenger->ToPlayer())
+ {
+ WorldPacket data(SMSG_CLIENT_CONTROL_UPDATE, GetUnitOwner()->GetPackGUID().size() + 1);
+ data.append(GetUnitOwner()->GetPackGUID());
+ data << uint8(value);
+ player->GetSession()->SendPacket(&data);
+ }
+ }
+ }
+ }
+
+ void HandleApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ SendClientControl(0);
+ }
+
+ void HandleRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ SendClientControl(1);
+ }
+
+ void Register() OVERRIDE
+ {
+ AfterEffectApply += AuraEffectApplyFn(spell_igb_overheat_AuraScript::HandleApply, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL);
+ AfterEffectRemove += AuraEffectRemoveFn(spell_igb_overheat_AuraScript::HandleRemove, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL);
+ }
+ };
+
+ AuraScript* GetAuraScript() const OVERRIDE
+ {
+ return new spell_igb_overheat_AuraScript();
+ }
+};
+
+class spell_igb_below_zero : public SpellScriptLoader
+{
+ public:
+ spell_igb_below_zero() : SpellScriptLoader("spell_igb_below_zero") { }
+
+ class spell_igb_below_zero_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_igb_below_zero_SpellScript);
+
+ void RemovePassengers()
+ {
+ GetHitUnit()->CastSpell(GetHitUnit(), SPELL_EJECT_ALL_PASSENGERS_BELOW_ZERO, TRIGGERED_FULL_MASK);
+ }
+
+ void Register() OVERRIDE
+ {
+ BeforeHit += SpellHitFn(spell_igb_below_zero_SpellScript::RemovePassengers);
+ }
+ };
+
+ SpellScript* GetSpellScript() const OVERRIDE
+ {
+ return new spell_igb_below_zero_SpellScript();
+ }
+};
+
+class spell_igb_teleport_to_enemy_ship : public SpellScriptLoader
+{
+ public:
+ spell_igb_teleport_to_enemy_ship() : SpellScriptLoader("spell_igb_teleport_to_enemy_ship") { }
+
+ class spell_igb_teleport_to_enemy_ship_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_igb_teleport_to_enemy_ship_SpellScript);
+
+ void RelocateTransportOffset(SpellEffIndex /*effIndex*/)
+ {
+ WorldLocation const* dest = GetHitDest();
+ Unit* target = GetHitUnit();
+ if (!dest || !target || !target->GetTransport())
+ return;
+
+ float x, y, z, o;
+ dest->GetPosition(x, y, z, o);
+ target->GetTransport()->CalculatePassengerOffset(x, y, z, &o);
+ target->m_movementInfo.transport.pos.Relocate(x, y, z, o);
+ }
+
+ void Register() OVERRIDE
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_igb_teleport_to_enemy_ship_SpellScript::RelocateTransportOffset, EFFECT_0, SPELL_EFFECT_TELEPORT_UNITS);
+ }
+ };
+
+ SpellScript* GetSpellScript() const OVERRIDE
+ {
+ return new spell_igb_teleport_to_enemy_ship_SpellScript();
+ }
+};
+
+class spell_igb_burning_pitch_selector : public SpellScriptLoader
+{
+ public:
+ spell_igb_burning_pitch_selector() : SpellScriptLoader("spell_igb_burning_pitch_selector") { }
+
+ class spell_igb_burning_pitch_selector_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_igb_burning_pitch_selector_SpellScript);
+
+ void FilterTargets(std::list<WorldObject*>& targets)
+ {
+ uint32 team = HORDE;
+ if (InstanceScript* instance = GetCaster()->GetInstanceScript())
+ team = instance->GetData(DATA_TEAM_IN_INSTANCE);
+
+ targets.remove_if([team](WorldObject* target) -> bool
+ {
+ if (Transport* transport = target->GetTransport())
+ return transport->GetEntry() != uint32(team == HORDE ? GO_ORGRIMS_HAMMER_H : GO_THE_SKYBREAKER_A);
+ return true;
+ });
+
+ if (!targets.empty())
+ {
+ WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets);
+ targets.clear();
+ targets.push_back(target);
+ }
+ }
+
+ void HandleDummy(SpellEffIndex effIndex)
+ {
+ PreventHitDefaultEffect(effIndex);
+ GetCaster()->CastSpell(GetHitUnit(), uint32(GetEffectValue()), TRIGGERED_NONE);
+ }
+
+ void Register() OVERRIDE
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_igb_burning_pitch_selector_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY);
+ OnEffectHitTarget += SpellEffectFn(spell_igb_burning_pitch_selector_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
+ };
+
+ SpellScript* GetSpellScript() const OVERRIDE
+ {
+ return new spell_igb_burning_pitch_selector_SpellScript();
+ }
+};
+
+class spell_igb_burning_pitch : public SpellScriptLoader
+{
+ public:
+ spell_igb_burning_pitch() : SpellScriptLoader("spell_igb_burning_pitch") { }
+
+ class spell_igb_burning_pitch_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_igb_burning_pitch_SpellScript);
+
+ void HandleDummy(SpellEffIndex effIndex)
+ {
+ PreventHitDefaultEffect(effIndex);
+ GetCaster()->CastCustomSpell(uint32(GetEffectValue()), SPELLVALUE_BASE_POINT0, 8000, NULL, TRIGGERED_FULL_MASK);
+ GetHitUnit()->CastSpell(GetHitUnit(), SPELL_BURNING_PITCH, TRIGGERED_FULL_MASK);
+ }
+
+ void Register() OVERRIDE
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_igb_burning_pitch_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
+ };
+
+ SpellScript* GetSpellScript() const OVERRIDE
+ {
+ return new spell_igb_burning_pitch_SpellScript();
+ }
+};
+
+class spell_igb_rocket_artillery : public SpellScriptLoader
+{
+ public:
+ spell_igb_rocket_artillery() : SpellScriptLoader("spell_igb_rocket_artillery") { }
+
+ class spell_igb_rocket_artillery_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_igb_rocket_artillery_SpellScript);
+
+ void SelectRandomTarget(std::list<WorldObject*>& targets)
+ {
+ if (!targets.empty())
+ {
+ WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets);
+ targets.clear();
+ targets.push_back(target);
+ }
+ }
+
+ void HandleScript(SpellEffIndex effIndex)
+ {
+ PreventHitDefaultEffect(effIndex);
+ GetCaster()->CastSpell(GetHitUnit(), uint32(GetEffectValue()), TRIGGERED_NONE);
+ }
+
+ void Register() OVERRIDE
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_igb_rocket_artillery_SpellScript::SelectRandomTarget, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
+ OnEffectHitTarget += SpellEffectFn(spell_igb_rocket_artillery_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+ };
+
+ SpellScript* GetSpellScript() const OVERRIDE
+ {
+ return new spell_igb_rocket_artillery_SpellScript();
+ }
+};
+
+class spell_igb_rocket_artillery_explosion : public SpellScriptLoader
+{
+ public:
+ spell_igb_rocket_artillery_explosion() : SpellScriptLoader("spell_igb_rocket_artillery_explosion") { }
+
+ class spell_igb_rocket_artillery_explosion_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_igb_rocket_artillery_explosion_SpellScript);
+
+ void DamageGunship(SpellEffIndex /*effIndex*/)
+ {
+ if (InstanceScript* instance = GetCaster()->GetInstanceScript())
+ GetCaster()->CastCustomSpell(instance->GetData(DATA_TEAM_IN_INSTANCE) == HORDE ? SPELL_BURNING_PITCH_DAMAGE_A : SPELL_BURNING_PITCH_DAMAGE_H, SPELLVALUE_BASE_POINT0, 5000, NULL, TRIGGERED_FULL_MASK);
+ }
+
+ void Register() OVERRIDE
+ {
+ OnEffectHit += SpellEffectFn(spell_igb_rocket_artillery_explosion_SpellScript::DamageGunship, EFFECT_0, SPELL_EFFECT_TRIGGER_MISSILE);
+ }
+ };
+
+ SpellScript* GetSpellScript() const OVERRIDE
+ {
+ return new spell_igb_rocket_artillery_explosion_SpellScript();
+ }
+};
+
+class spell_igb_gunship_fall_teleport : public SpellScriptLoader
+{
+ public:
+ spell_igb_gunship_fall_teleport() : SpellScriptLoader("spell_igb_gunship_fall_teleport") { }
+
+ class spell_igb_gunship_fall_teleport_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_igb_gunship_fall_teleport_SpellScript);
+
+ bool Load()
+ {
+ return GetCaster()->GetInstanceScript();
+ }
+
+ void SelectTransport(WorldObject*& target)
+ {
+ if (InstanceScript* instance = target->GetInstanceScript())
+ target = HashMapHolder<GameObject>::Find(instance->GetData64(DATA_ICECROWN_GUNSHIP_BATTLE));
+ }
+
+ void RelocateDest(SpellEffIndex /*effIndex*/)
+ {
+ if (GetCaster()->GetInstanceScript()->GetData(DATA_TEAM_IN_INSTANCE) == HORDE)
+ GetHitDest()->RelocateOffset({ 0.0f, 0.0f, 36.0f, 0.0f });
+ else
+ GetHitDest()->RelocateOffset({ 0.0f, 0.0f, 21.0f, 0.0f });
+ }
+
+ void Register() OVERRIDE
+ {
+ OnObjectTargetSelect += SpellObjectTargetSelectFn(spell_igb_gunship_fall_teleport_SpellScript::SelectTransport, EFFECT_0, TARGET_DEST_NEARBY_ENTRY);
+ OnEffectLaunch += SpellEffectFn(spell_igb_gunship_fall_teleport_SpellScript::RelocateDest, EFFECT_0, SPELL_EFFECT_TELEPORT_UNITS);
+ }
+ };
+
+ SpellScript* GetSpellScript() const OVERRIDE
+ {
+ return new spell_igb_gunship_fall_teleport_SpellScript();
+ }
+};
+
+class spell_igb_check_for_players : public SpellScriptLoader
+{
+ public:
+ spell_igb_check_for_players() : SpellScriptLoader("spell_igb_check_for_players") { }
+
+ class spell_igb_check_for_players_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_igb_check_for_players_SpellScript);
+
+ bool Load() OVERRIDE
+ {
+ _playerCount = 0;
+ return GetCaster()->GetTypeId() == TYPEID_UNIT;
+ }
+
+ void CountTargets(std::list<WorldObject*>& targets)
+ {
+ _playerCount = targets.size();
+ }
+
+ void TriggerWipe()
+ {
+ if (!_playerCount)
+ GetCaster()->ToCreature()->AI()->JustDied(NULL);
+ }
+
+ void TeleportPlayer(SpellEffIndex /*effIndex*/)
+ {
+ if (GetHitUnit()->GetPositionZ() < GetCaster()->GetPositionZ() - 10.0f)
+ GetHitUnit()->CastSpell(GetHitUnit(), SPELL_GUNSHIP_FALL_TELEPORT, TRIGGERED_FULL_MASK);
+ }
+
+ void Register() OVERRIDE
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_igb_check_for_players_SpellScript::CountTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY);
+ AfterCast += SpellCastFn(spell_igb_check_for_players_SpellScript::TriggerWipe);
+ OnEffectHitTarget += SpellEffectFn(spell_igb_check_for_players_SpellScript::TeleportPlayer, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
+
+ uint32 _playerCount;
+ };
+
+ SpellScript* GetSpellScript() const OVERRIDE
+ {
+ return new spell_igb_check_for_players_SpellScript();
+ }
+};
+
+class spell_igb_teleport_players_on_victory : public SpellScriptLoader
+{
+ public:
+ spell_igb_teleport_players_on_victory() : SpellScriptLoader("spell_igb_teleport_players_on_victory") { }
+
+ class spell_igb_teleport_players_on_victory_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_igb_teleport_players_on_victory_SpellScript);
+
+ bool Load() OVERRIDE
+ {
+ return GetCaster()->GetInstanceScript();
+ }
+
+ void FilterTargets(std::list<WorldObject*>& targets)
+ {
+ InstanceScript* instance = GetCaster()->GetInstanceScript();
+ targets.remove_if([instance](WorldObject* target) -> bool
+ {
+ return target->GetTransGUID() != instance->GetData64(DATA_ENEMY_GUNSHIP);
+ });
+ }
+
+ void Register() OVERRIDE
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_igb_teleport_players_on_victory_SpellScript::FilterTargets, EFFECT_1, TARGET_UNIT_DEST_AREA_ENTRY);
+ }
+ };
+
+ SpellScript* GetSpellScript() const OVERRIDE
+ {
+ return new spell_igb_teleport_players_on_victory_SpellScript();
+ }
+};
+
+class achievement_im_on_a_boat : public AchievementCriteriaScript
+{
+ public:
+ achievement_im_on_a_boat() : AchievementCriteriaScript("achievement_im_on_a_boat") { }
+
+ bool OnCheck(Player* /*source*/, Unit* target) OVERRIDE
+ {
+ return target->GetAI() && target->GetAI()->GetData(ACTION_SHIP_VISITS) <= 2;
+ }
+};
+
+void AddSC_boss_icecrown_gunship_battle()
+{
+ new npc_gunship();
+ new npc_high_overlord_saurfang_igb();
+ new npc_muradin_bronzebeard_igb();
+ new npc_zafod_boombox();
+ new npc_gunship_boarding_leader();
+ new npc_gunship_boarding_add();
+ new npc_gunship_gunner();
+ new npc_gunship_rocketeer();
+ new npc_gunship_mage();
+ new npc_gunship_cannon();
+ new spell_igb_rocket_pack();
+ new spell_igb_rocket_pack_useable();
+ new spell_igb_on_gunship_deck();
+ new spell_igb_periodic_trigger_with_power_cost();
+ new spell_igb_cannon_blast();
+ new spell_igb_incinerating_blast();
+ new spell_igb_overheat();
+ new spell_igb_below_zero();
+ new spell_igb_teleport_to_enemy_ship();
+ new spell_igb_burning_pitch_selector();
+ new spell_igb_burning_pitch();
+ new spell_igb_rocket_artillery();
+ new spell_igb_rocket_artillery_explosion();
+ new spell_igb_gunship_fall_teleport();
+ new spell_igb_check_for_players();
+ new spell_igb_teleport_players_on_victory();
+ new achievement_im_on_a_boat();
+}
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 30d520ce7bf..0d262110b5f 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp
@@ -560,7 +560,7 @@ class boss_the_lich_king : public CreatureScript
me->VisitNearbyGridObject(333.0f, worker);
// Reset any light override
- SendLightOverride(0, 5000);
+ me->GetMap()->SetZoneOverrideLight(AREA_THE_FROZEN_THRONE, 0, 5000);
}
bool CanAIAttack(Unit const* target) const OVERRIDE
@@ -593,7 +593,7 @@ class boss_the_lich_king : public CreatureScript
case ACTION_START_ENCOUNTER:
instance->SetBossState(DATA_THE_LICH_KING, IN_PROGRESS);
Talk(SAY_LK_INTRO_1);
- SendMusicToPlayers(MUSIC_FROZEN_THRONE);
+ me->GetMap()->SetZoneMusic(AREA_THE_FROZEN_THRONE, MUSIC_FROZEN_THRONE);
// schedule talks
me->SetStandState(UNIT_STAND_STATE_STAND);
events.ScheduleEvent(EVENT_INTRO_MOVE_1, 4000);
@@ -602,10 +602,10 @@ class boss_the_lich_king : public CreatureScript
events.ScheduleEvent(EVENT_START_ATTACK, 5000);
break;
case ACTION_PLAY_MUSIC:
- SendMusicToPlayers(MUSIC_FINAL);
+ me->GetMap()->SetZoneMusic(AREA_THE_FROZEN_THRONE, MUSIC_FINAL);
break;
case ACTION_RESTORE_LIGHT:
- SendLightOverride(0, 5000);
+ me->GetMap()->SetZoneOverrideLight(AREA_THE_FROZEN_THRONE, 0, 5000);
break;
case ACTION_BREAK_FROSTMOURNE:
me->CastSpell((Unit*)NULL, SPELL_SUMMON_BROKEN_FROSTMOURNE, TRIGGERED_IGNORE_CAST_IN_PROGRESS);
@@ -687,7 +687,7 @@ class boss_the_lich_king : public CreatureScript
events.Reset();
events.SetPhase(PHASE_OUTRO);
summons.DespawnAll();
- SendMusicToPlayers(MUSIC_FURY_OF_FROSTMOURNE);
+ me->GetMap()->SetZoneMusic(AREA_THE_FROZEN_THRONE, MUSIC_FURY_OF_FROSTMOURNE);
me->InterruptNonMeleeSpells(true);
me->CastSpell((Unit*)NULL, SPELL_FURY_OF_FROSTMOURNE, TRIGGERED_NONE);
me->SetWalk(true);
@@ -739,8 +739,8 @@ class boss_the_lich_king : public CreatureScript
{
summon->CastSpell((Unit*)NULL, SPELL_BROKEN_FROSTMOURNE, true);
- SendLightOverride(LIGHT_SOULSTORM, 10000);
- SendWeather(WEATHER_STATE_BLACKSNOW);
+ me->GetMap()->SetZoneOverrideLight(AREA_THE_FROZEN_THRONE, LIGHT_SOULSTORM, 10000);
+ me->GetMap()->SetZoneWeather(AREA_THE_FROZEN_THRONE, WEATHER_STATE_BLACKSNOW, 0.5f);
events.ScheduleEvent(EVENT_OUTRO_SOUL_BARRAGE, 5000, 0, PHASE_OUTRO);
return;
@@ -792,8 +792,8 @@ class boss_the_lich_king : public CreatureScript
{
if (spell->Id == REMORSELESS_WINTER_1 || spell->Id == REMORSELESS_WINTER_2)
{
- SendLightOverride(LIGHT_SNOWSTORM, 5000);
- SendWeather(WEATHER_STATE_LIGHT_SNOW);
+ me->GetMap()->SetZoneOverrideLight(AREA_THE_FROZEN_THRONE, LIGHT_SNOWSTORM, 5000);
+ me->GetMap()->SetZoneWeather(AREA_THE_FROZEN_THRONE, WEATHER_STATE_LIGHT_SNOW, 0.5f);
}
}
@@ -819,7 +819,7 @@ class boss_the_lich_king : public CreatureScript
case POINT_CENTER_1:
me->SetFacingTo(0.0f);
Talk(SAY_LK_REMORSELESS_WINTER);
- SendMusicToPlayers(MUSIC_SPECIAL);
+ me->GetMap()->SetZoneMusic(AREA_THE_FROZEN_THRONE, MUSIC_SPECIAL);
DoCast(me, SPELL_REMORSELESS_WINTER_1);
events.DelayEvents(62500, EVENT_GROUP_BERSERK); // delay berserk timer, its not ticking during phase transitions
events.ScheduleEvent(EVENT_QUAKE, 62500, 0, PHASE_TRANSITION);
@@ -834,7 +834,7 @@ class boss_the_lich_king : public CreatureScript
case POINT_CENTER_2:
me->SetFacingTo(0.0f);
Talk(SAY_LK_REMORSELESS_WINTER);
- SendMusicToPlayers(MUSIC_SPECIAL);
+ me->GetMap()->SetZoneMusic(AREA_THE_FROZEN_THRONE, MUSIC_SPECIAL);
DoCast(me, SPELL_REMORSELESS_WINTER_2);
summons.DespawnEntry(NPC_VALKYR_SHADOWGUARD);
events.DelayEvents(62500, EVENT_GROUP_BERSERK); // delay berserk timer, its not ticking during phase transitions
@@ -920,7 +920,7 @@ class boss_the_lich_king : public CreatureScript
break;
case EVENT_SUMMON_SHAMBLING_HORROR:
DoCast(me, SPELL_SUMMON_SHAMBLING_HORROR);
- SendMusicToPlayers(MUSIC_SPECIAL);
+ me->GetMap()->SetZoneMusic(AREA_THE_FROZEN_THRONE, MUSIC_SPECIAL);
events.ScheduleEvent(EVENT_SUMMON_SHAMBLING_HORROR, 60000, 0, PHASE_ONE);
break;
case EVENT_SUMMON_DRUDGE_GHOUL:
@@ -980,18 +980,18 @@ class boss_the_lich_king : public CreatureScript
events.SetPhase(PHASE_TWO);
me->ClearUnitState(UNIT_STATE_CASTING); // clear state to ensure check in DoCastAOE passes
DoCastAOE(SPELL_QUAKE);
- SendMusicToPlayers(MUSIC_SPECIAL);
+ me->GetMap()->SetZoneMusic(AREA_THE_FROZEN_THRONE, MUSIC_SPECIAL);
Talk(SAY_LK_QUAKE);
break;
case EVENT_QUAKE_2:
events.SetPhase(PHASE_THREE);
me->ClearUnitState(UNIT_STATE_CASTING); // clear state to ensure check in DoCastAOE passes
DoCastAOE(SPELL_QUAKE);
- SendMusicToPlayers(MUSIC_SPECIAL);
+ me->GetMap()->SetZoneMusic(AREA_THE_FROZEN_THRONE, MUSIC_SPECIAL);
Talk(SAY_LK_QUAKE);
break;
case EVENT_SUMMON_VALKYR:
- SendMusicToPlayers(MUSIC_SPECIAL);
+ me->GetMap()->SetZoneMusic(AREA_THE_FROZEN_THRONE, MUSIC_SPECIAL);
Talk(SAY_LK_SUMMON_VALKYR);
DoCastAOE(SUMMON_VALKYR);
events.ScheduleEvent(EVENT_SUMMON_VALKYR, urand(45000, 50000), 0, PHASE_TWO);
@@ -1002,7 +1002,7 @@ class boss_the_lich_king : public CreatureScript
events.SetPhase(PHASE_THREE);
break;
case EVENT_VILE_SPIRITS:
- SendMusicToPlayers(MUSIC_SPECIAL);
+ me->GetMap()->SetZoneMusic(AREA_THE_FROZEN_THRONE, MUSIC_SPECIAL);
DoCastAOE(SPELL_VILE_SPIRITS);
events.ScheduleEvent(EVENT_VILE_SPIRITS, urand(35000, 40000), EVENT_GROUP_VILE_SPIRITS, PHASE_THREE);
break;
@@ -1073,7 +1073,7 @@ class boss_the_lich_king : public CreatureScript
case EVENT_OUTRO_RAISE_DEAD:
DoCastAOE(SPELL_RAISE_DEAD);
me->ClearUnitState(UNIT_STATE_CASTING);
- SendMusicToPlayers(MUSIC_FINAL);
+ me->GetMap()->SetZoneMusic(AREA_THE_FROZEN_THRONE, MUSIC_FINAL);
break;
case EVENT_OUTRO_TALK_5:
Talk(SAY_LK_OUTRO_5);
@@ -1114,42 +1114,6 @@ class boss_the_lich_king : public CreatureScript
}
private:
- void SendMusicToPlayers(uint32 musicId) const
- {
- WorldPacket data(SMSG_PLAY_MUSIC, 4);
- data << uint32(musicId);
- SendPacketToPlayers(&data);
- }
-
- void SendLightOverride(uint32 overrideId, uint32 fadeInTime) const
- {
- WorldPacket data(SMSG_OVERRIDE_LIGHT, 12);
- data << uint32(2488); // Light.dbc entry (map default)
- data << uint32(overrideId); // Light.dbc entry (override)
- data << uint32(fadeInTime);
- SendPacketToPlayers(&data);
- }
-
- void SendWeather(WeatherState weather) const
- {
- WorldPacket data(SMSG_WEATHER, 9);
- data << uint32(weather);
- data << float(0.5f);
- data << uint8(0);
- SendPacketToPlayers(&data);
- }
-
- // Send packet to all players in The Frozen Throne
- void SendPacketToPlayers(WorldPacket const* data) const
- {
- Map::PlayerList const& players = me->GetMap()->GetPlayers();
- if (!players.isEmpty())
- for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
- if (Player* player = itr->GetSource())
- if (player->GetAreaId() == AREA_THE_FROZEN_THRONE)
- player->GetSession()->SendPacket(data);
- }
-
uint32 _necroticPlagueStack;
uint32 _vileSpiritExplosions;
};
@@ -2606,38 +2570,6 @@ class spell_the_lich_king_valkyr_target_search : public SpellScriptLoader
}
};
-class spell_the_lich_king_eject_all_passengers : public SpellScriptLoader
-{
- public:
- spell_the_lich_king_eject_all_passengers() : SpellScriptLoader("spell_the_lich_king_eject_all_passengers") { }
-
- class spell_the_lich_king_eject_all_passengers_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_the_lich_king_eject_all_passengers_SpellScript);
-
- bool Load() OVERRIDE
- {
- return GetCaster()->IsVehicle();
- }
-
- void HandleDummy(SpellEffIndex effIndex)
- {
- PreventHitDefaultEffect(effIndex);
- GetCaster()->GetVehicleKit()->RemoveAllPassengers();
- }
-
- void Register() OVERRIDE
- {
- OnEffectHitTarget += SpellEffectFn(spell_the_lich_king_eject_all_passengers_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
- }
- };
-
- SpellScript* GetSpellScript() const OVERRIDE
- {
- return new spell_the_lich_king_eject_all_passengers_SpellScript();
- }
-};
-
class spell_the_lich_king_cast_back_to_caster : public SpellScriptLoader
{
public:
@@ -3270,7 +3202,6 @@ void AddSC_boss_the_lich_king()
new spell_the_lich_king_summon_into_air();
new spell_the_lich_king_soul_reaper();
new spell_the_lich_king_valkyr_target_search();
- new spell_the_lich_king_eject_all_passengers();
new spell_the_lich_king_cast_back_to_caster();
new spell_the_lich_king_life_siphon();
new spell_the_lich_king_vile_spirits();
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h
index 8e529ba0ee9..6aeab015b78 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h
+++ b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h
@@ -68,7 +68,7 @@ enum TeleporterSpells
DEATHBRINGER_S_RISE_TELEPORT = 70858,
UPPER_SPIRE_TELEPORT = 70859,
FROZEN_THRONE_TELEPORT = 70860,
- SINDRAGOSA_S_LAIR_TELEPORT = 70861,
+ SINDRAGOSA_S_LAIR_TELEPORT = 70861
};
enum DataTypes
@@ -76,7 +76,7 @@ enum DataTypes
// Encounter States/Boss GUIDs
DATA_LORD_MARROWGAR = 0,
DATA_LADY_DEATHWHISPER = 1,
- DATA_GUNSHIP_EVENT = 2,
+ DATA_ICECROWN_GUNSHIP_BATTLE = 2,
DATA_DEATHBRINGER_SAURFANG = 3,
DATA_FESTERGUT = 4,
DATA_ROTFACE = 5,
@@ -116,6 +116,7 @@ enum DataTypes
DATA_HIGHLORD_TIRION_FORDRING = 37,
DATA_ARTHAS_PLATFORM = 38,
DATA_TERENAS_MENETHIL = 39,
+ DATA_ENEMY_GUNSHIP = 40
};
enum CreaturesIds
@@ -169,6 +170,33 @@ enum CreaturesIds
NPC_REANIMATED_ADHERENT = 38010,
NPC_VENGEFUL_SHADE = 38222,
+ // Icecrown Gunship Battle
+ NPC_MARTYR_STALKER_IGB_SAURFANG = 38569,
+ NPC_ALLIANCE_GUNSHIP_CANNON = 36838,
+ NPC_HORDE_GUNSHIP_CANNON = 36839,
+ NPC_SKYBREAKER_DECKHAND = 36970,
+ NPC_ORGRIMS_HAMMER_CREW = 36971,
+ NPC_IGB_HIGH_OVERLORD_SAURFANG = 36939,
+ NPC_IGB_MURADIN_BRONZEBEARD = 36948,
+ NPC_THE_SKYBREAKER = 37540,
+ NPC_ORGRIMS_HAMMER = 37215,
+ NPC_GUNSHIP_HULL = 37547,
+ NPC_TELEPORT_PORTAL = 37227,
+ NPC_TELEPORT_EXIT = 37488,
+ NPC_SKYBREAKER_SORCERER = 37116,
+ NPC_SKYBREAKER_RIFLEMAN = 36969,
+ NPC_SKYBREAKER_MORTAR_SOLDIER = 36978,
+ NPC_SKYBREAKER_MARINE = 36950,
+ NPC_SKYBREAKER_SERGEANT = 36961,
+ NPC_KOR_KRON_BATTLE_MAGE = 37117,
+ NPC_KOR_KRON_AXETHROWER = 36968,
+ NPC_KOR_KRON_ROCKETEER = 36982,
+ NPC_KOR_KRON_REAVER = 36957,
+ NPC_KOR_KRON_SERGEANT = 36960,
+ NPC_ZAFOD_BOOMBOX = 37184,
+ NPC_HIGH_CAPTAIN_JUSTIN_BARTLETT = 37182,
+ NPC_SKY_REAVER_KORM_BLACKSCAR = 37833,
+
// Deathbringer Saurfang
NPC_DEATHBRINGER_SAURFANG = 37813,
NPC_BLOOD_BEAST = 38508,
@@ -285,7 +313,7 @@ enum CreaturesIds
NPC_FROSTMOURNE_TRIGGER = 38584,
// Generic
- NPC_INVISIBLE_STALKER = 30298,
+ NPC_INVISIBLE_STALKER = 30298
};
enum GameObjectsIds
@@ -305,6 +333,22 @@ enum GameObjectsIds
GO_ORATORY_OF_THE_DAMNED_ENTRANCE = 201563,
GO_LADY_DEATHWHISPER_ELEVATOR = 202220,
+ // Icecrown Gunship Battle - Horde raid
+ GO_ORGRIMS_HAMMER_H = 201812,
+ GO_THE_SKYBREAKER_H = 201811,
+ GO_GUNSHIP_ARMORY_H_10N = 202178,
+ GO_GUNSHIP_ARMORY_H_25N = 202180,
+ GO_GUNSHIP_ARMORY_H_10H = 202177,
+ GO_GUNSHIP_ARMORY_H_25H = 202179,
+
+ // Icecrown Gunship Battle - Alliance raid
+ GO_ORGRIMS_HAMMER_A = 201581,
+ GO_THE_SKYBREAKER_A = 201580,
+ GO_GUNSHIP_ARMORY_A_10N = 201873,
+ GO_GUNSHIP_ARMORY_A_25N = 201874,
+ GO_GUNSHIP_ARMORY_A_10H = 201872,
+ GO_GUNSHIP_ARMORY_A_25H = 201875,
+
// Deathbringer Saurfang
GO_SAURFANG_S_DOOR = 201825,
GO_DEATHBRINGER_S_CACHE_10N = 202239,
@@ -368,7 +412,7 @@ enum GameObjectsIds
GO_DOODAD_ICECROWN_SNOWEDGEWARNING01 = 202190,
GO_FROZEN_LAVAMAN = 202436,
GO_LAVAMAN_PILLARS_CHAINED = 202437,
- GO_LAVAMAN_PILLARS_UNCHAINED = 202438,
+ GO_LAVAMAN_PILLARS_UNCHAINED = 202438
};
enum AchievementCriteriaIds
@@ -403,11 +447,15 @@ enum AchievementCriteriaIds
CRITERIA_ONCE_BITTEN_TWICE_SHY_10N = 12780,
CRITERIA_ONCE_BITTEN_TWICE_SHY_25N = 13012,
CRITERIA_ONCE_BITTEN_TWICE_SHY_10V = 13011,
- CRITERIA_ONCE_BITTEN_TWICE_SHY_25V = 13013,
+ CRITERIA_ONCE_BITTEN_TWICE_SHY_25V = 13013
};
enum SharedActions
{
+ // Icecrown Gunship Battle
+ ACTION_ENEMY_GUNSHIP_TALK = -369390,
+ ACTION_EXIT_SHIP = -369391,
+
// Festergut
ACTION_FESTERGUT_COMBAT = -366260,
ACTION_FESTERGUT_GAS = -366261,
@@ -431,7 +479,7 @@ enum SharedActions
// The Lich King
ACTION_RESTORE_LIGHT = -72262,
- ACTION_FROSTMOURNE_INTRO = -36823,
+ ACTION_FROSTMOURNE_INTRO = -36823
};
enum WeekliesICC
@@ -445,7 +493,7 @@ enum WeekliesICC
QUEST_BLOOD_QUICKENING_10 = 24874,
QUEST_BLOOD_QUICKENING_25 = 24879,
QUEST_RESPITE_FOR_A_TORNMENTED_SOUL_10 = 24872,
- QUEST_RESPITE_FOR_A_TORNMENTED_SOUL_25 = 24880,
+ QUEST_RESPITE_FOR_A_TORNMENTED_SOUL_25 = 24880
};
enum WorldStatesICC
@@ -454,12 +502,13 @@ enum WorldStatesICC
WORLDSTATE_EXECUTION_TIME = 4904,
WORLDSTATE_SHOW_ATTEMPTS = 4940,
WORLDSTATE_ATTEMPTS_REMAINING = 4941,
- WORLDSTATE_ATTEMPTS_MAX = 4942,
+ WORLDSTATE_ATTEMPTS_MAX = 4942
};
enum AreaIds
{
- AREA_THE_FROZEN_THRONE = 4859,
+ AREA_ICECROWN_CITADEL = 4812,
+ AREA_THE_FROZEN_THRONE = 4859
};
class spell_trigger_spell_from_caster : public SpellScriptLoader
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel_teleport.cpp b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel_teleport.cpp
index ad06bc1c485..b56e0dd6360 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel_teleport.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel_teleport.cpp
@@ -38,7 +38,7 @@ class icecrown_citadel_teleport : public GameObjectScript
player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Teleport to the Oratory of the Damned.", GOSSIP_SENDER_ICC_PORT, ORATORY_OF_THE_DAMNED_TELEPORT);
if (instance->GetBossState(DATA_LADY_DEATHWHISPER) == DONE)
player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Teleport to the Rampart of Skulls.", GOSSIP_SENDER_ICC_PORT, RAMPART_OF_SKULLS_TELEPORT);
- if (instance->GetBossState(DATA_GUNSHIP_EVENT) == DONE)
+ if (instance->GetBossState(DATA_ICECROWN_GUNSHIP_BATTLE) == DONE)
player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Teleport to the Deathbringer's Rise.", GOSSIP_SENDER_ICC_PORT, DEATHBRINGER_S_RISE_TELEPORT);
if (instance->GetData(DATA_COLDFLAME_JETS) == DONE)
player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Teleport to the Upper Spire.", GOSSIP_SENDER_ICC_PORT, UPPER_SPIRE_TELEPORT);
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp
index edd80377d68..31daa92cbe8 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp
@@ -15,23 +15,30 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "ObjectMgr.h"
-#include "ScriptMgr.h"
+#include "AccountMgr.h"
#include "InstanceScript.h"
-#include "ScriptedCreature.h"
#include "Map.h"
-#include "PoolMgr.h"
-#include "AccountMgr.h"
-#include "icecrown_citadel.h"
+#include "ObjectMgr.h"
#include "Player.h"
+#include "PoolMgr.h"
+#include "ScriptMgr.h"
+#include "ScriptedCreature.h"
+#include "Transport.h"
+#include "TransportMgr.h"
#include "WorldPacket.h"
#include "WorldSession.h"
+#include "icecrown_citadel.h"
enum EventIds
{
+ EVENT_PLAYERS_GUNSHIP_SPAWN = 22663,
+ EVENT_PLAYERS_GUNSHIP_COMBAT = 22664,
+ EVENT_PLAYERS_GUNSHIP_SAURFANG = 22665,
+ EVENT_ENEMY_GUNSHIP_COMBAT = 22860,
+ EVENT_ENEMY_GUNSHIP_DESPAWN = 22861,
EVENT_QUAKE = 23437,
EVENT_SECOND_REMORSELESS_WINTER = 23507,
- EVENT_TELEPORT_TO_FROSMOURNE = 23617,
+ EVENT_TELEPORT_TO_FROSTMOURNE = 23617
};
enum TimedEvents
@@ -39,6 +46,7 @@ enum TimedEvents
EVENT_UPDATE_EXECUTION_TIME = 1,
EVENT_QUAKE_SHATTER = 2,
EVENT_REBUILD_PLATFORM = 3,
+ EVENT_RESPAWN_GUNSHIP = 4
};
DoorData const doorData[] =
@@ -68,7 +76,7 @@ DoorData const doorData[] =
{GO_SINDRAGOSA_SHORTCUT_EXIT_DOOR, DATA_SINDRAGOSA, DOOR_TYPE_PASSAGE, BOUNDARY_NONE},
{GO_ICE_WALL, DATA_SINDRAGOSA, DOOR_TYPE_ROOM, BOUNDARY_SE },
{GO_ICE_WALL, DATA_SINDRAGOSA, DOOR_TYPE_ROOM, BOUNDARY_SW },
- {0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE}, // END
+ {0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE} // END
};
// this doesnt have to only store questgivers, also can be used for related quest spawns
@@ -89,7 +97,7 @@ WeeklyQuest const WeeklyQuestData[WeeklyNPCs] =
{NPC_ALRIN_THE_AGILE, {QUEST_BLOOD_QUICKENING_10, QUEST_BLOOD_QUICKENING_25 }}, // Blood Quickening
{NPC_INFILTRATOR_MINCHAR_BQ, {QUEST_BLOOD_QUICKENING_10, QUEST_BLOOD_QUICKENING_25 }}, // Blood Quickening
{NPC_MINCHAR_BEAM_STALKER, {QUEST_BLOOD_QUICKENING_10, QUEST_BLOOD_QUICKENING_25 }}, // Blood Quickening
- {NPC_VALITHRIA_DREAMWALKER_QUEST, {QUEST_RESPITE_FOR_A_TORNMENTED_SOUL_10, QUEST_RESPITE_FOR_A_TORNMENTED_SOUL_25}}, // Respite for a Tormented Soul
+ {NPC_VALITHRIA_DREAMWALKER_QUEST, {QUEST_RESPITE_FOR_A_TORNMENTED_SOUL_10, QUEST_RESPITE_FOR_A_TORNMENTED_SOUL_25}} // Respite for a Tormented Soul
};
class instance_icecrown_citadel : public InstanceMapScript
@@ -106,6 +114,9 @@ class instance_icecrown_citadel : public InstanceMapScript
TeamInInstance = 0;
HeroicAttempts = MaxHeroicAttempts;
LadyDeathwisperElevatorGUID = 0;
+ GunshipGUID = 0;
+ EnemyGunshipGUID = 0;
+ GunshipArmoryGUID = 0;
DeathbringerSaurfangGUID = 0;
DeathbringerSaurfangDoorGUID = 0;
DeathbringerSaurfangEventGUID = 0;
@@ -164,6 +175,9 @@ class instance_icecrown_citadel : public InstanceMapScript
{
if (!TeamInInstance)
TeamInInstance = player->GetTeam();
+
+ if (GetBossState(DATA_LADY_DEATHWHISPER) == DONE && GetBossState(DATA_ICECROWN_GUNSHIP_BATTLE) != DONE)
+ SpawnGunship();
}
void OnCreatureCreate(Creature* creature) OVERRIDE
@@ -217,6 +231,10 @@ class instance_icecrown_citadel : public InstanceMapScript
case NPC_DEATHBRINGER_SAURFANG:
DeathbringerSaurfangGUID = creature->GetGUID();
break;
+ case NPC_ALLIANCE_GUNSHIP_CANNON:
+ case NPC_HORDE_GUNSHIP_CANNON:
+ creature->SetControlled(true, UNIT_STATE_ROOT);
+ break;
case NPC_SE_HIGH_OVERLORD_SAURFANG:
if (TeamInInstance == ALLIANCE)
creature->UpdateEntry(NPC_SE_MURADIN_BRONZEBEARD, ALLIANCE, creature->GetCreatureData());
@@ -335,12 +353,60 @@ class instance_icecrown_citadel : public InstanceMapScript
{
uint8 diffIndex = uint8(instance->GetSpawnMode() & 1);
if (!sPoolMgr->IsSpawnedObject<Quest>(WeeklyQuestData[questIndex].questId[diffIndex]))
- entry = 0;
+ return 0;
break;
}
}
break;
}
+ case NPC_HORDE_GUNSHIP_CANNON:
+ case NPC_ORGRIMS_HAMMER_CREW:
+ case NPC_SKY_REAVER_KORM_BLACKSCAR:
+ if (TeamInInstance == ALLIANCE)
+ return 0;
+ break;
+ case NPC_ALLIANCE_GUNSHIP_CANNON:
+ case NPC_SKYBREAKER_DECKHAND:
+ case NPC_HIGH_CAPTAIN_JUSTIN_BARTLETT:
+ if (TeamInInstance == HORDE)
+ return 0;
+ break;
+ case NPC_ZAFOD_BOOMBOX:
+ if (GameObjectTemplate const* go = sObjectMgr->GetGameObjectTemplate(GO_THE_SKYBREAKER_A))
+ if ((TeamInInstance == ALLIANCE && data->mapid == go->moTransport.mapID) ||
+ (TeamInInstance == HORDE && data->mapid != go->moTransport.mapID))
+ return entry;
+ return 0;
+ case NPC_IGB_MURADIN_BRONZEBEARD:
+ if ((TeamInInstance == ALLIANCE && data->posX > 10.0f) ||
+ (TeamInInstance == HORDE && data->posX < 10.0f))
+ return entry;
+ return 0;
+ default:
+ break;
+ }
+
+ return entry;
+ }
+
+ uint32 GetGameObjectEntry(uint32 /*guidLow*/, uint32 entry) OVERRIDE
+ {
+ switch (entry)
+ {
+ case GO_GUNSHIP_ARMORY_H_10N:
+ case GO_GUNSHIP_ARMORY_H_25N:
+ case GO_GUNSHIP_ARMORY_H_10H:
+ case GO_GUNSHIP_ARMORY_H_25H:
+ if (TeamInInstance == ALLIANCE)
+ return 0;
+ break;
+ case GO_GUNSHIP_ARMORY_A_10N:
+ case GO_GUNSHIP_ARMORY_A_25N:
+ case GO_GUNSHIP_ARMORY_A_10H:
+ case GO_GUNSHIP_ARMORY_A_25H:
+ if (TeamInInstance == HORDE)
+ return 0;
+ break;
default:
break;
}
@@ -446,6 +512,20 @@ class instance_icecrown_citadel : public InstanceMapScript
go->SetGoState(GO_STATE_READY);
}
break;
+ case GO_THE_SKYBREAKER_H:
+ case GO_ORGRIMS_HAMMER_A:
+ EnemyGunshipGUID = go->GetGUID();
+ break;
+ case GO_GUNSHIP_ARMORY_H_10N:
+ case GO_GUNSHIP_ARMORY_H_25N:
+ case GO_GUNSHIP_ARMORY_H_10H:
+ case GO_GUNSHIP_ARMORY_H_25H:
+ case GO_GUNSHIP_ARMORY_A_10N:
+ case GO_GUNSHIP_ARMORY_A_25N:
+ case GO_GUNSHIP_ARMORY_A_10H:
+ case GO_GUNSHIP_ARMORY_A_25H:
+ GunshipArmoryGUID = go->GetGUID();
+ break;
case GO_SAURFANG_S_DOOR:
DeathbringerSaurfangDoorGUID = go->GetGUID();
AddDoor(go, true);
@@ -587,6 +667,10 @@ class instance_icecrown_citadel : public InstanceMapScript
case GO_ICE_WALL:
AddDoor(go, false);
break;
+ case GO_THE_SKYBREAKER_A:
+ case GO_ORGRIMS_HAMMER_H:
+ GunshipGUID = 0;
+ break;
default:
break;
}
@@ -621,6 +705,10 @@ class instance_icecrown_citadel : public InstanceMapScript
{
switch (type)
{
+ case DATA_ICECROWN_GUNSHIP_BATTLE:
+ return GunshipGUID;
+ case DATA_ENEMY_GUNSHIP:
+ return EnemyGunshipGUID;
case DATA_DEATHBRINGER_SAURFANG:
return DeathbringerSaurfangGUID;
case DATA_SAURFANG_EVENT_NPC:
@@ -691,7 +779,7 @@ class instance_icecrown_citadel : public InstanceMapScript
switch (type)
{
case DATA_LADY_DEATHWHISPER:
- SetBossState(DATA_GUNSHIP_EVENT, state); // TEMP HACK UNTIL GUNSHIP SCRIPTED
+ {
if (state == DONE)
{
if (GameObject* elevator = instance->GetGameObject(LadyDeathwisperElevatorGUID))
@@ -699,7 +787,19 @@ class instance_icecrown_citadel : public InstanceMapScript
elevator->SetUInt32Value(GAMEOBJECT_LEVEL, 0);
elevator->SetGoState(GO_STATE_READY);
}
+
+ SpawnGunship();
+ }
+ break;
+ }
+ case DATA_ICECROWN_GUNSHIP_BATTLE:
+ if (state == DONE)
+ {
+ if (GameObject* loot = instance->GetGameObject(GunshipArmoryGUID))
+ loot->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED | GO_FLAG_NOT_SELECTABLE | GO_FLAG_NODESPAWN);
}
+ else if (state == FAIL)
+ Events.ScheduleEvent(EVENT_RESPAWN_GUNSHIP, 30000);
break;
case DATA_DEATHBRINGER_SAURFANG:
switch (state)
@@ -846,6 +946,17 @@ class instance_icecrown_citadel : public InstanceMapScript
return true;
}
+ void SpawnGunship()
+ {
+ if (!GunshipGUID)
+ {
+ SetBossState(DATA_ICECROWN_GUNSHIP_BATTLE, NOT_STARTED);
+ uint32 gunshipEntry = TeamInInstance == HORDE ? GO_ORGRIMS_HAMMER_H : GO_THE_SKYBREAKER_A;
+ if (Transport* gunship = sTransportMgr->CreateTransport(gunshipEntry, 0, instance))
+ GunshipGUID = gunship->GetGUID();
+ }
+ }
+
void SetData(uint32 type, uint32 data) OVERRIDE
{
switch (type)
@@ -1066,10 +1177,10 @@ class instance_icecrown_citadel : public InstanceMapScript
return false;
// no break
case DATA_DEATHBRINGER_SAURFANG:
- if (GetBossState(DATA_GUNSHIP_EVENT) != DONE)
+ if (GetBossState(DATA_ICECROWN_GUNSHIP_BATTLE) != DONE)
return false;
// no break
- case DATA_GUNSHIP_EVENT:
+ case DATA_ICECROWN_GUNSHIP_BATTLE:
if (GetBossState(DATA_LADY_DEATHWHISPER) != DONE)
return false;
// no break
@@ -1163,7 +1274,7 @@ class instance_icecrown_citadel : public InstanceMapScript
void Update(uint32 diff) OVERRIDE
{
- if (BloodQuickeningState != IN_PROGRESS && GetBossState(DATA_THE_LICH_KING) != IN_PROGRESS)
+ if (BloodQuickeningState != IN_PROGRESS && GetBossState(DATA_THE_LICH_KING) != IN_PROGRESS && GetBossState(DATA_ICECROWN_GUNSHIP_BATTLE) != FAIL)
return;
Events.Update(diff);
@@ -1213,16 +1324,42 @@ class instance_icecrown_citadel : public InstanceMapScript
if (GameObject* wind = instance->GetGameObject(FrozenThroneWindGUID))
wind->SetGoState(GO_STATE_ACTIVE);
break;
+ case EVENT_RESPAWN_GUNSHIP:
+ SpawnGunship();
+ break;
default:
break;
}
}
}
- void ProcessEvent(WorldObject* /*source*/, uint32 eventId) OVERRIDE
+ void ProcessEvent(WorldObject* source, uint32 eventId) OVERRIDE
{
switch (eventId)
{
+ case EVENT_ENEMY_GUNSHIP_DESPAWN:
+ if (GetBossState(DATA_ICECROWN_GUNSHIP_BATTLE) == DONE)
+ source->AddObjectToRemoveList();
+ break;
+ case EVENT_ENEMY_GUNSHIP_COMBAT:
+ if (Creature* captain = source->FindNearestCreature(TeamInInstance == HORDE ? NPC_IGB_HIGH_OVERLORD_SAURFANG : NPC_IGB_MURADIN_BRONZEBEARD, 100.0f))
+ captain->AI()->DoAction(ACTION_ENEMY_GUNSHIP_TALK);
+ // no break;
+ case EVENT_PLAYERS_GUNSHIP_SPAWN:
+ case EVENT_PLAYERS_GUNSHIP_COMBAT:
+ if (GameObject* go = source->ToGameObject())
+ if (Transport* transport = go->ToTransport())
+ transport->EnableMovement(false);
+ break;
+ case EVENT_PLAYERS_GUNSHIP_SAURFANG:
+ {
+ if (Creature* captain = source->FindNearestCreature(TeamInInstance == HORDE ? NPC_IGB_HIGH_OVERLORD_SAURFANG : NPC_IGB_MURADIN_BRONZEBEARD, 100.0f))
+ captain->AI()->DoAction(ACTION_EXIT_SHIP);
+ if (GameObject* go = source->ToGameObject())
+ if (Transport* transport = go->ToTransport())
+ transport->EnableMovement(false);
+ break;
+ }
case EVENT_QUAKE:
if (GameObject* warning = instance->GetGameObject(FrozenThroneWarningGUID))
warning->SetGoState(GO_STATE_ACTIVE);
@@ -1235,7 +1372,7 @@ class instance_icecrown_citadel : public InstanceMapScript
Events.ScheduleEvent(EVENT_REBUILD_PLATFORM, 1500);
}
break;
- case EVENT_TELEPORT_TO_FROSMOURNE: // Harvest Soul (normal mode)
+ case EVENT_TELEPORT_TO_FROSTMOURNE: // Harvest Soul (normal mode)
if (Creature* terenas = instance->SummonCreature(NPC_TERENAS_MENETHIL_FROSTMOURNE, TerenasSpawn, NULL, 63000))
{
terenas->AI()->DoAction(ACTION_FROSTMOURNE_INTRO);
@@ -1261,6 +1398,9 @@ class instance_icecrown_citadel : public InstanceMapScript
protected:
EventMap Events;
uint64 LadyDeathwisperElevatorGUID;
+ uint64 GunshipGUID;
+ uint64 EnemyGunshipGUID;
+ uint64 GunshipArmoryGUID;
uint64 DeathbringerSaurfangGUID;
uint64 DeathbringerSaurfangDoorGUID;
uint64 DeathbringerSaurfangEventGUID; // Muradin Bronzebeard or High Overlord Saurfang
diff --git a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp
index 7ae9ce3faa6..1df92618a3a 100644
--- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp
+++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp
@@ -584,7 +584,7 @@ public:
{
instance->SetBossState(DATA_MALYGOS_EVENT, FAIL);
- SendLightOverride(LIGHT_GET_DEFAULT_FOR_MAP, 1*IN_MILLISECONDS);
+ me->GetMap()->SetZoneOverrideLight(AREA_EYE_OF_ETERNITY, LIGHT_GET_DEFAULT_FOR_MAP, 1*IN_MILLISECONDS);
if (_phase == PHASE_THREE)
me->SetControlled(false, UNIT_STATE_ROOT);
@@ -725,8 +725,8 @@ public:
me->SetDisableGravity(true);
if (Creature* alexstraszaBunny = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_ALEXSTRASZA_BUNNY_GUID)))
me->SetFacingToObject(alexstraszaBunny);
- SendLightOverride(LIGHT_ARCANE_RUNES, 5*IN_MILLISECONDS);
- events.ScheduleEvent(EVENT_FLY_OUT_OF_PLATFORM, 18*IN_MILLISECONDS, 0, PHASE_TWO);
+ me->GetMap()->SetZoneOverrideLight(AREA_EYE_OF_ETERNITY, LIGHT_ARCANE_RUNES, 5 * IN_MILLISECONDS);
+ events.ScheduleEvent(EVENT_FLY_OUT_OF_PLATFORM, 18 * IN_MILLISECONDS, 0, PHASE_TWO);
break;
case POINT_SURGE_OF_POWER_P_TWO:
if (!_performingDestroyPlatform)
@@ -737,7 +737,7 @@ public:
}
break;
case POINT_DESTROY_PLATFORM_P_TWO:
- SendLightOverride(LIGHT_OBSCURE_SPACE, 1*IN_MILLISECONDS);
+ me->GetMap()->SetZoneOverrideLight(AREA_EYE_OF_ETERNITY, LIGHT_OBSCURE_SPACE, 1 * IN_MILLISECONDS);
DoCast(me, SPELL_DESTROY_PLATFORM_CHANNEL);
events.ScheduleEvent(EVENT_MOVE_TO_P_THREE_POINT, 11*IN_MILLISECONDS, 0, PHASE_TWO);
break;
@@ -929,7 +929,7 @@ public:
}
break;
case EVENT_LIGHT_DIMENSION_CHANGE:
- SendLightOverride(LIGHT_CHANGE_DIMENSIONS, 2*IN_MILLISECONDS);
+ me->GetMap()->SetZoneOverrideLight(AREA_EYE_OF_ETERNITY, LIGHT_CHANGE_DIMENSIONS, 2 * IN_MILLISECONDS);
break;
case EVENT_DELAY_MOVE_TO_DESTROY_P:
me->GetMotionMaster()->MovePoint(POINT_DESTROY_PLATFORM_P_TWO, MalygosPositions[0]);
@@ -939,7 +939,7 @@ public:
me->GetMotionMaster()->MovePoint(POINT_IDLE_P_THREE, MalygosPositions[4]);
break;
case EVENT_START_P_THREE:
- SendLightOverride(LIGHT_OBSCURE_ARCANE_RUNES, 1*IN_MILLISECONDS);
+ me->GetMap()->SetZoneOverrideLight(AREA_EYE_OF_ETERNITY, LIGHT_OBSCURE_ARCANE_RUNES, 1 * IN_MILLISECONDS);
DoCast(me, SPELL_CLEAR_ALL_DEBUFFS);
DoCast(me, SPELL_IMMUNE_CURSES);
_canAttack = true;
@@ -1026,27 +1026,6 @@ public:
}
}
- // Function that will change lights of map for all players on map.
- void SendLightOverride(uint32 overrideId, uint32 fadeInTime) const
- {
- WorldPacket data(SMSG_OVERRIDE_LIGHT, 12);
- data << uint32(1773); // Light.dbc entry (map default)
- data << uint32(overrideId); // Light.dbc entry (override)
- data << uint32(fadeInTime);
- SendPacketToPlayers(&data);
- }
-
- // Send packet to all players in Eye of Eternity
- void SendPacketToPlayers(WorldPacket const* data) const
- {
- Map::PlayerList const& players = me->GetMap()->GetPlayers();
- if (!players.isEmpty())
- for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
- if (Player* player = itr->GetSource())
- if (player->GetAreaId() == AREA_EYE_OF_ETERNITY)
- player->GetSession()->SendPacket(data);
- }
-
uint8 _phase; // Counter for phases used with a getter.
uint8 _summonDeaths; // Keeps count of arcane trash.
uint8 _preparingPulsesChecker; // In retail they use 2 preparing pulses with 7 sec CD, after they pass 2 seconds.
diff --git a/src/server/scripts/Northrend/Nexus/Oculus/instance_oculus.cpp b/src/server/scripts/Northrend/Nexus/Oculus/instance_oculus.cpp
index 2c809b17367..39dec9999cc 100644
--- a/src/server/scripts/Northrend/Nexus/Oculus/instance_oculus.cpp
+++ b/src/server/scripts/Northrend/Nexus/Oculus/instance_oculus.cpp
@@ -208,9 +208,11 @@ class instance_oculus : public InstanceMapScript
break;
case DATA_VAROS:
if (state == DONE)
+ {
DoUpdateWorldState(WORLD_STATE_CENTRIFUGE_CONSTRUCT_SHOW, 0);
if (Creature* urom = instance->GetCreature(UromGUID))
urom->SetPhaseMask(1, true);
+ }
break;
case DATA_UROM:
if (state == DONE)
diff --git a/src/server/scripts/Northrend/zone_borean_tundra.cpp b/src/server/scripts/Northrend/zone_borean_tundra.cpp
index f840c0562b3..f7f473297ef 100644
--- a/src/server/scripts/Northrend/zone_borean_tundra.cpp
+++ b/src/server/scripts/Northrend/zone_borean_tundra.cpp
@@ -44,6 +44,7 @@ EndContentData */
#include "Player.h"
#include "SpellInfo.h"
#include "WorldSession.h"
+#include "SpellScript.h"
/*######
## npc_sinkhole_kill_credit
@@ -2537,6 +2538,39 @@ public:
};
+enum WindsoulTotemAura
+{
+ SPELL_WINDSOUL_CREDT = 46378
+};
+
+class spell_windsoul_totem_aura : public SpellScriptLoader
+{
+public:
+ spell_windsoul_totem_aura() : SpellScriptLoader("spell_windsoul_totem_aura") { }
+
+ class spell_windsoul_totem_aura_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_windsoul_totem_aura_AuraScript);
+
+ void OnRemove(AuraEffect const*, AuraEffectHandleModes)
+ {
+ if (GetTarget()->isDead())
+ if (Unit* caster = GetCaster())
+ caster->CastSpell(NULL, SPELL_WINDSOUL_CREDT);
+ }
+
+ void Register() OVERRIDE
+ {
+ OnEffectRemove += AuraEffectRemoveFn(spell_windsoul_totem_aura_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
+ }
+ };
+
+ AuraScript* GetAuraScript() const OVERRIDE
+ {
+ return new spell_windsoul_totem_aura_AuraScript();
+ }
+};
+
void AddSC_borean_tundra()
{
new npc_sinkhole_kill_credit();
@@ -2565,4 +2599,5 @@ void AddSC_borean_tundra()
new npc_valiance_keep_cannoneer();
new npc_warmage_coldarra();
new npc_hidden_cultist();
+ new spell_windsoul_totem_aura();
}
diff --git a/src/server/scripts/Northrend/zone_dragonblight.cpp b/src/server/scripts/Northrend/zone_dragonblight.cpp
index 7487c3c8828..a9c46d19138 100644
--- a/src/server/scripts/Northrend/zone_dragonblight.cpp
+++ b/src/server/scripts/Northrend/zone_dragonblight.cpp
@@ -654,6 +654,7 @@ class npc_torturer_lecraft : public CreatureScript
{
npc_torturer_lecraftAI(Creature* creature) : ScriptedAI(creature)
{
+ _textCounter = 1;
_playerGUID = 0;
}
diff --git a/src/server/scripts/Northrend/zone_storm_peaks.cpp b/src/server/scripts/Northrend/zone_storm_peaks.cpp
index 1c6ec703f0c..bd80de627a8 100644
--- a/src/server/scripts/Northrend/zone_storm_peaks.cpp
+++ b/src/server/scripts/Northrend/zone_storm_peaks.cpp
@@ -454,6 +454,9 @@ public:
{
npc_brann_bronzebeard_keystoneAI(Creature* creature) : ScriptedAI(creature)
{
+ memset(&objectGUID, 0, sizeof(objectGUID));
+ playerGUID = 0;
+ voiceGUID = 0;
objectCounter = 0;
}
@@ -640,6 +643,7 @@ public:
{
npc_king_jokkum_vehicleAI(Creature* creature) : VehicleAI(creature)
{
+ playerGUID = 0;
pathEnd = false;
}
@@ -788,37 +792,6 @@ class spell_veranus_summon : public SpellScriptLoader
}
};
-/*#####
-# spell_jokkum_eject_all
-#####*/
-
-class spell_jokkum_eject_all : public SpellScriptLoader
-{
- public: spell_jokkum_eject_all() : SpellScriptLoader("spell_jokkum_eject_all") { }
-
- class spell_jokkum_eject_all_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_jokkum_eject_all_SpellScript);
-
- void HandleScriptEffect(SpellEffIndex /* effIndex */)
- {
- if (Unit* caster = GetCaster())
- if (caster->IsVehicle())
- caster->GetVehicleKit()->RemoveAllPassengers();
- }
-
- void Register() OVERRIDE
- {
- OnEffectHitTarget += SpellEffectFn(spell_jokkum_eject_all_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
- }
- };
-
- SpellScript* GetSpellScript() const OVERRIDE
- {
- return new spell_jokkum_eject_all_SpellScript();
- }
-};
-
enum CloseRift
{
SPELL_DESPAWN_RIFT = 61665
@@ -878,6 +851,5 @@ void AddSC_storm_peaks()
new npc_king_jokkum_vehicle();
new spell_jokkum_scriptcast();
new spell_veranus_summon();
- new spell_jokkum_eject_all();
new spell_close_rift();
}
diff --git a/src/server/scripts/Northrend/zone_zuldrak.cpp b/src/server/scripts/Northrend/zone_zuldrak.cpp
index 8f5ae0f65ff..0f542b3aca7 100644
--- a/src/server/scripts/Northrend/zone_zuldrak.cpp
+++ b/src/server/scripts/Northrend/zone_zuldrak.cpp
@@ -453,7 +453,11 @@ public:
struct npc_alchemist_finklesteinAI : public ScriptedAI
{
- npc_alchemist_finklesteinAI(Creature* creature) : ScriptedAI(creature) { }
+ npc_alchemist_finklesteinAI(Creature* creature) : ScriptedAI(creature)
+ {
+ _playerGUID = 0;
+ _getingredienttry = 0;
+ }
void Reset() OVERRIDE
{
diff --git a/src/server/scripts/Outland/Auchindoun/AuchenaiCrypts/boss_exarch_maladaar.cpp b/src/server/scripts/Outland/Auchindoun/AuchenaiCrypts/boss_exarch_maladaar.cpp
index 5266a7bd137..c9d452bfada 100644
--- a/src/server/scripts/Outland/Auchindoun/AuchenaiCrypts/boss_exarch_maladaar.cpp
+++ b/src/server/scripts/Outland/Auchindoun/AuchenaiCrypts/boss_exarch_maladaar.cpp
@@ -61,7 +61,11 @@ public:
struct npc_stolen_soulAI : public ScriptedAI
{
- npc_stolen_soulAI(Creature* creature) : ScriptedAI(creature) { }
+ npc_stolen_soulAI(Creature* creature) : ScriptedAI(creature)
+ {
+ myClass = CLASS_NONE;
+ Class_Timer = 1000;
+ }
uint8 myClass;
uint32 Class_Timer;
diff --git a/src/server/scripts/Outland/BlackTemple/boss_reliquary_of_souls.cpp b/src/server/scripts/Outland/BlackTemple/boss_reliquary_of_souls.cpp
index ca0ea947295..d92d8aaf5db 100644
--- a/src/server/scripts/Outland/BlackTemple/boss_reliquary_of_souls.cpp
+++ b/src/server/scripts/Outland/BlackTemple/boss_reliquary_of_souls.cpp
@@ -295,13 +295,13 @@ public:
Timer = 1000;
if (Phase == 3)
{
- if (!Essence->IsAlive())
+ if (Essence && !Essence->IsAlive())
DoCast(me, 7, true);
else return;
}
else
{
- if (Essence->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE))
+ if (Essence && Essence->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE))
{
MergeThreatList(Essence);
Essence->RemoveAllAuras();
@@ -312,31 +312,37 @@ public:
break;
case 4:
Timer = 1500;
- if (Essence->IsWithinDistInMap(me, 10))
+ if (Essence)
{
- Essence->SetUInt32Value(UNIT_NPC_EMOTESTATE, 374); //rotate and disappear
- Timer = 2000;
- me->RemoveAurasDueToSpell(SPELL_SUBMERGE);
- }
- else
- {
- MergeThreatList(Essence);
- Essence->RemoveAllAuras();
- Essence->DeleteThreatList();
- Essence->GetMotionMaster()->MoveFollow(me, 0, 0);
- return;
+ if (Essence->IsWithinDistInMap(me, 10))
+ {
+ Essence->SetUInt32Value(UNIT_NPC_EMOTESTATE, 374); //rotate and disappear
+ Timer = 2000;
+ me->RemoveAurasDueToSpell(SPELL_SUBMERGE);
+ }
+ else
+ {
+ MergeThreatList(Essence);
+ Essence->RemoveAllAuras();
+ Essence->DeleteThreatList();
+ Essence->GetMotionMaster()->MoveFollow(me, 0, 0);
+ return;
+ }
}
break;
case 5:
- if (Phase == 1)
+ if (Essence)
{
- Essence->AI()->Talk(SUFF_SAY_AFTER);
- }
- else
- {
- Essence->AI()->Talk(DESI_SAY_AFTER);
+ if (Phase == 1)
+ {
+ Essence->AI()->Talk(SUFF_SAY_AFTER);
+ }
+ else
+ {
+ Essence->AI()->Talk(DESI_SAY_AFTER);
+ }
+ Essence->DespawnOrUnsummon();
}
- Essence->DespawnOrUnsummon();
me->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
EssenceGUID = 0;
SoulCount = 0;
diff --git a/src/server/scripts/Outland/TempestKeep/Mechanar/boss_gatewatcher_ironhand.cpp b/src/server/scripts/Outland/TempestKeep/Mechanar/boss_gatewatcher_ironhand.cpp
index e34e4ebdb23..09eb261282f 100644
--- a/src/server/scripts/Outland/TempestKeep/Mechanar/boss_gatewatcher_ironhand.cpp
+++ b/src/server/scripts/Outland/TempestKeep/Mechanar/boss_gatewatcher_ironhand.cpp
@@ -48,9 +48,9 @@ enum Spells
enum Events
{
- EVENT_STREAM_OF_MACHINE_FLUID = 0,
- EVENT_JACKHAMMER = 1,
- EVENT_SHADOW_POWER = 2
+ EVENT_STREAM_OF_MACHINE_FLUID = 1,
+ EVENT_JACKHAMMER = 2,
+ EVENT_SHADOW_POWER = 3
};
class boss_gatewatcher_iron_hand : public CreatureScript
diff --git a/src/server/scripts/Outland/TempestKeep/arcatraz/boss_dalliah_the_doomsayer.cpp b/src/server/scripts/Outland/TempestKeep/arcatraz/boss_dalliah_the_doomsayer.cpp
index bfc304e6a99..18388341a36 100644
--- a/src/server/scripts/Outland/TempestKeep/arcatraz/boss_dalliah_the_doomsayer.cpp
+++ b/src/server/scripts/Outland/TempestKeep/arcatraz/boss_dalliah_the_doomsayer.cpp
@@ -59,11 +59,16 @@ class boss_dalliah_the_doomsayer : public CreatureScript
struct boss_dalliah_the_doomsayerAI : public BossAI
{
- boss_dalliah_the_doomsayerAI(Creature* creature) : BossAI(creature, DATA_DALLIAH) { }
+ boss_dalliah_the_doomsayerAI(Creature* creature) : BossAI(creature, DATA_DALLIAH)
+ {
+ soccothratesTaunt = false;
+ soccothratesDeath = false;
+ }
void Reset() OVERRIDE
{
_Reset();
+ soccothratesTaunt = false;
soccothratesDeath = false;
}
diff --git a/src/server/scripts/Outland/TempestKeep/arcatraz/boss_wrath_scryer_soccothrates.cpp b/src/server/scripts/Outland/TempestKeep/arcatraz/boss_wrath_scryer_soccothrates.cpp
index 044be4c1534..6c96708c69d 100644
--- a/src/server/scripts/Outland/TempestKeep/arcatraz/boss_wrath_scryer_soccothrates.cpp
+++ b/src/server/scripts/Outland/TempestKeep/arcatraz/boss_wrath_scryer_soccothrates.cpp
@@ -82,7 +82,12 @@ class boss_wrath_scryer_soccothrates : public CreatureScript
struct boss_wrath_scryer_soccothratesAI : public BossAI
{
- boss_wrath_scryer_soccothratesAI(Creature* creature) : BossAI(creature, DATA_SOCCOTHRATES) { }
+ boss_wrath_scryer_soccothratesAI(Creature* creature) : BossAI(creature, DATA_SOCCOTHRATES)
+ {
+ preFight = false;
+ dalliahTaunt = false;
+ dalliahDeath = false;
+ }
void Reset() OVERRIDE
{
diff --git a/src/server/scripts/Outland/zone_blades_edge_mountains.cpp b/src/server/scripts/Outland/zone_blades_edge_mountains.cpp
index 3f1579c42b1..fdeaa1c2520 100644
--- a/src/server/scripts/Outland/zone_blades_edge_mountains.cpp
+++ b/src/server/scripts/Outland/zone_blades_edge_mountains.cpp
@@ -115,6 +115,7 @@ public:
{
npc_bloodmaul_bruteAI(Creature* creature) : ScriptedAI(creature)
{
+ PlayerGUID = 0;
hp30 = false;
}
diff --git a/src/server/scripts/Outland/zone_netherstorm.cpp b/src/server/scripts/Outland/zone_netherstorm.cpp
index 72e7332381b..8542b32d631 100644
--- a/src/server/scripts/Outland/zone_netherstorm.cpp
+++ b/src/server/scripts/Outland/zone_netherstorm.cpp
@@ -728,7 +728,15 @@ public:
struct npc_phase_hunterAI : public ScriptedAI
{
- npc_phase_hunterAI(Creature* creature) : ScriptedAI(creature) { }
+ npc_phase_hunterAI(Creature* creature) : ScriptedAI(creature)
+ {
+ Weak = false;
+ Materialize = false;
+ Drained = false;
+ WeakPercent = 25;
+ PlayerGUID = 0;
+ ManaBurnTimer = 5000;
+ }
bool Weak;
bool Materialize;
diff --git a/src/server/scripts/Spells/spell_dk.cpp b/src/server/scripts/Spells/spell_dk.cpp
index e8108f03e7d..c100630a452 100644
--- a/src/server/scripts/Spells/spell_dk.cpp
+++ b/src/server/scripts/Spells/spell_dk.cpp
@@ -197,7 +197,7 @@ class spell_dk_anti_magic_zone : public SpellScriptLoader
void CalculateAmount(AuraEffect const* /*aurEff*/, int32 & amount, bool & /*canBeRecalculated*/)
{
- SpellInfo const* talentSpell = sSpellMgr->GetSpellInfo(SPELL_DK_ANTI_MAGIC_SHELL_TALENT);
+ SpellInfo const* talentSpell = sSpellMgr->EnsureSpellInfo(SPELL_DK_ANTI_MAGIC_SHELL_TALENT);
amount = talentSpell->Effects[EFFECT_0].CalcValue(GetCaster());
if (Player* player = GetCaster()->ToPlayer())
amount += int32(2 * player->GetTotalAttackPowerValue(BASE_ATTACK));
@@ -1424,7 +1424,7 @@ class spell_dk_will_of_the_necropolis : public SpellScriptLoader
{
// min pct of hp is stored in effect 0 of talent spell
uint8 rank = GetSpellInfo()->GetRank();
- SpellInfo const* talentProto = sSpellMgr->GetSpellInfo(sSpellMgr->GetSpellWithRank(SPELL_DK_WILL_OF_THE_NECROPOLIS_TALENT_R1, rank));
+ SpellInfo const* talentProto = sSpellMgr->EnsureSpellInfo(sSpellMgr->GetSpellWithRank(SPELL_DK_WILL_OF_THE_NECROPOLIS_TALENT_R1, rank));
int32 remainingHp = int32(GetTarget()->GetHealth() - dmgInfo.GetDamage());
int32 minHp = int32(GetTarget()->CountPctFromMaxHealth(talentProto->Effects[EFFECT_0].CalcValue(GetCaster())));
diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp
index 1e9a8713019..68c16a1b2d6 100644
--- a/src/server/scripts/Spells/spell_generic.cpp
+++ b/src/server/scripts/Spells/spell_generic.cpp
@@ -36,6 +36,7 @@
#include "SkillDiscovery.h"
#include "SpellScript.h"
#include "SpellAuraEffects.h"
+#include "Vehicle.h"
class spell_gen_absorb0_hitlimit1 : public SpellScriptLoader
{
@@ -1191,7 +1192,7 @@ class spell_gen_defend : public SpellScriptLoader
void Register() OVERRIDE
{
- SpellInfo const* spell = sSpellMgr->GetSpellInfo(m_scriptSpellId);
+ SpellInfo const* spell = sSpellMgr->EnsureSpellInfo(m_scriptSpellId);
// Defend spells cast by NPCs (add visuals)
if (spell->Effects[EFFECT_0].ApplyAuraName == SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN)
@@ -2177,7 +2178,7 @@ class spell_gen_mounted_charge: public SpellScriptLoader
void Register() OVERRIDE
{
- SpellInfo const* spell = sSpellMgr->GetSpellInfo(m_scriptSpellId);
+ SpellInfo const* spell = sSpellMgr->EnsureSpellInfo(m_scriptSpellId);
if (spell->HasEffect(SPELL_EFFECT_SCRIPT_EFFECT))
OnEffectHitTarget += SpellEffectFn(spell_gen_mounted_charge_SpellScript::HandleScriptEffect, EFFECT_FIRST_FOUND, SPELL_EFFECT_SCRIPT_EFFECT);
@@ -3673,6 +3674,33 @@ class spell_gen_whisper_gulch_yogg_saron_whisper : public SpellScriptLoader
}
};
+class spell_gen_eject_all_passengers : public SpellScriptLoader
+{
+ public:
+ spell_gen_eject_all_passengers() : SpellScriptLoader("spell_gen_eject_all_passengers") { }
+
+ class spell_gen_eject_all_passengers_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_gen_eject_all_passengers_SpellScript);
+
+ void RemoveVehicleAuras()
+ {
+ if (Vehicle* vehicle = GetHitUnit()->GetVehicleKit())
+ vehicle->RemoveAllPassengers();
+ }
+
+ void Register() OVERRIDE
+ {
+ AfterHit += SpellHitFn(spell_gen_eject_all_passengers_SpellScript::RemoveVehicleAuras);
+ }
+ };
+
+ SpellScript* GetSpellScript() const OVERRIDE
+ {
+ return new spell_gen_eject_all_passengers_SpellScript();
+ }
+};
+
void AddSC_generic_spell_scripts()
{
new spell_gen_absorb0_hitlimit1();
@@ -3754,4 +3782,5 @@ void AddSC_generic_spell_scripts()
new spell_gen_vendor_bark_trigger();
new spell_gen_wg_water();
new spell_gen_whisper_gulch_yogg_saron_whisper();
+ new spell_gen_eject_all_passengers();
}
diff --git a/src/server/scripts/Spells/spell_mage.cpp b/src/server/scripts/Spells/spell_mage.cpp
index ba59f701445..5f03c64eaf1 100644
--- a/src/server/scripts/Spells/spell_mage.cpp
+++ b/src/server/scripts/Spells/spell_mage.cpp
@@ -176,7 +176,7 @@ class spell_mage_cold_snap : public SpellScriptLoader
const SpellCooldowns& cm = caster->GetSpellCooldownMap();
for (SpellCooldowns::const_iterator itr = cm.begin(); itr != cm.end();)
{
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itr->first);
+ SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(itr->first);
if (spellInfo->SpellFamilyName == SPELLFAMILY_MAGE &&
(spellInfo->GetSchoolMask() & SPELL_SCHOOL_MASK_FROST) &&
@@ -388,7 +388,7 @@ class spell_mage_ignite : public SpellScriptLoader
{
PreventDefaultAction();
- SpellInfo const* igniteDot = sSpellMgr->GetSpellInfo(SPELL_MAGE_IGNITE);
+ SpellInfo const* igniteDot = sSpellMgr->EnsureSpellInfo(SPELL_MAGE_IGNITE);
int32 pct = 8 * GetSpellInfo()->GetRank();
int32 amount = int32(CalculatePct(eventInfo.GetDamageInfo()->GetDamage(), pct) / igniteDot->GetMaxTicks());
diff --git a/src/server/scripts/Spells/spell_pet.cpp b/src/server/scripts/Spells/spell_pet.cpp
index a7742630ccd..491bb7100b2 100644
--- a/src/server/scripts/Spells/spell_pet.cpp
+++ b/src/server/scripts/Spells/spell_pet.cpp
@@ -897,7 +897,7 @@ public:
if (itr != pet->ToPet()->m_spells.end()) // If pet has Wild Hunt
{
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itr->first); // Then get the SpellProto and add the dummy effect value
+ SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(itr->first); // Then get the SpellProto and add the dummy effect value
AddPct(mod, spellInfo->Effects[EFFECT_0].CalcValue());
}
@@ -940,7 +940,7 @@ public:
if (itr != pet->ToPet()->m_spells.end()) // If pet has Wild Hunt
{
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itr->first); // Then get the SpellProto and add the dummy effect value
+ SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(itr->first); // Then get the SpellProto and add the dummy effect value
mod += CalculatePct(1.0f, spellInfo->Effects[EFFECT_1].CalcValue());
}
@@ -970,7 +970,7 @@ public:
if (itr != pet->ToPet()->m_spells.end()) // If pet has Wild Hunt
{
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itr->first); // Then get the SpellProto and add the dummy effect value
+ SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(itr->first); // Then get the SpellProto and add the dummy effect value
mod += CalculatePct(1.0f, spellInfo->Effects[EFFECT_1].CalcValue());
}
diff --git a/src/server/scripts/Spells/spell_priest.cpp b/src/server/scripts/Spells/spell_priest.cpp
index 71e5dac28ec..f12a57aa2ec 100644
--- a/src/server/scripts/Spells/spell_priest.cpp
+++ b/src/server/scripts/Spells/spell_priest.cpp
@@ -236,7 +236,7 @@ class spell_pri_glyph_of_prayer_of_healing : public SpellScriptLoader
{
PreventDefaultAction();
- SpellInfo const* triggeredSpellInfo = sSpellMgr->GetSpellInfo(SPELL_PRIEST_GLYPH_OF_PRAYER_OF_HEALING_HEAL);
+ SpellInfo const* triggeredSpellInfo = sSpellMgr->EnsureSpellInfo(SPELL_PRIEST_GLYPH_OF_PRAYER_OF_HEALING_HEAL);
int32 heal = int32(CalculatePct(int32(eventInfo.GetHealInfo()->GetHeal()), aurEff->GetAmount()) / triggeredSpellInfo->GetMaxTicks());
GetTarget()->CastCustomSpell(SPELL_PRIEST_GLYPH_OF_PRAYER_OF_HEALING_HEAL, SPELLVALUE_BASE_POINT0, heal, eventInfo.GetProcTarget(), true, NULL, aurEff);
}
diff --git a/src/server/scripts/Spells/spell_quest.cpp b/src/server/scripts/Spells/spell_quest.cpp
index cdf32bd94d5..d1b32570795 100644
--- a/src/server/scripts/Spells/spell_quest.cpp
+++ b/src/server/scripts/Spells/spell_quest.cpp
@@ -903,7 +903,7 @@ class spell_q12659_ahunaes_knife : public SpellScriptLoader
enum StoppingTheSpread
{
NPC_VILLAGER_KILL_CREDIT = 18240,
- SPELL_FLAMES = 39199,
+ SPELL_FLAMES = 39199
};
class spell_q9874_liquid_fire : public SpellScriptLoader
@@ -926,7 +926,7 @@ class spell_q9874_liquid_fire : public SpellScriptLoader
{
Player* caster = GetCaster()->ToPlayer();
if (Creature* target = GetHitCreature())
- if (target && target->HasAura(SPELL_FLAMES))
+ if (target && !target->HasAura(SPELL_FLAMES))
{
caster->KilledMonsterCredit(NPC_VILLAGER_KILL_CREDIT, 0);
target->CastSpell(target, SPELL_FLAMES, true);
diff --git a/src/server/scripts/Spells/spell_rogue.cpp b/src/server/scripts/Spells/spell_rogue.cpp
index d1d43684f3e..4c1a4d096b9 100644
--- a/src/server/scripts/Spells/spell_rogue.cpp
+++ b/src/server/scripts/Spells/spell_rogue.cpp
@@ -428,7 +428,7 @@ class spell_rog_preparation : public SpellScriptLoader
const SpellCooldowns& cm = caster->GetSpellCooldownMap();
for (SpellCooldowns::const_iterator itr = cm.begin(); itr != cm.end();)
{
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itr->first);
+ SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(itr->first);
if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE)
{
diff --git a/src/server/scripts/Spells/spell_warlock.cpp b/src/server/scripts/Spells/spell_warlock.cpp
index 36e63b5a94e..0e3ada5d119 100644
--- a/src/server/scripts/Spells/spell_warlock.cpp
+++ b/src/server/scripts/Spells/spell_warlock.cpp
@@ -270,7 +270,7 @@ class spell_warl_demonic_circle_summon : public SpellScriptLoader
// WARLOCK_DEMONIC_CIRCLE_ALLOW_CAST; allowing him to cast the WARLOCK_DEMONIC_CIRCLE_TELEPORT.
// If not in range remove the WARLOCK_DEMONIC_CIRCLE_ALLOW_CAST.
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(SPELL_WARLOCK_DEMONIC_CIRCLE_TELEPORT);
+ SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(SPELL_WARLOCK_DEMONIC_CIRCLE_TELEPORT);
if (GetTarget()->IsWithinDist(circle, spellInfo->GetMaxRange(true)))
{
@@ -353,6 +353,7 @@ class spell_warl_demonic_empowerment : public SpellScriptLoader
if (targetCreature->IsPet())
{
CreatureTemplate const* ci = sObjectMgr->GetCreatureTemplate(targetCreature->GetEntry());
+ ASSERT(ci);
switch (ci->family)
{
case CREATURE_FAMILY_SUCCUBUS:
@@ -360,7 +361,7 @@ class spell_warl_demonic_empowerment : public SpellScriptLoader
break;
case CREATURE_FAMILY_VOIDWALKER:
{
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(SPELL_WARLOCK_DEMONIC_EMPOWERMENT_VOIDWALKER);
+ SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(SPELL_WARLOCK_DEMONIC_EMPOWERMENT_VOIDWALKER);
int32 hp = int32(targetCreature->CountPctFromMaxHealth(GetCaster()->CalculateSpellDamage(targetCreature, spellInfo, 0)));
targetCreature->CastCustomSpell(targetCreature, SPELL_WARLOCK_DEMONIC_EMPOWERMENT_VOIDWALKER, &hp, NULL, NULL, true);
//unitTarget->CastSpell(unitTarget, 54441, true);
diff --git a/src/server/scripts/Spells/spell_warrior.cpp b/src/server/scripts/Spells/spell_warrior.cpp
index 5a655a92996..d0ba39e8b09 100644
--- a/src/server/scripts/Spells/spell_warrior.cpp
+++ b/src/server/scripts/Spells/spell_warrior.cpp
@@ -273,7 +273,7 @@ class spell_warr_deep_wounds : public SpellScriptLoader
damage = target->SpellDamageBonusTaken(caster, GetSpellInfo(), damage, SPELL_DIRECT_DAMAGE);
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(SPELL_WARRIOR_DEEP_WOUNDS_RANK_PERIODIC);
+ SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(SPELL_WARRIOR_DEEP_WOUNDS_RANK_PERIODIC);
uint32 ticks = spellInfo->GetDuration() / spellInfo->Effects[EFFECT_0].Amplitude;
// Add remaining ticks to damage done
diff --git a/src/server/shared/Common.h b/src/server/shared/Common.h
index 5dea589da25..fb153f2ba3e 100644
--- a/src/server/shared/Common.h
+++ b/src/server/shared/Common.h
@@ -71,12 +71,6 @@
#include <signal.h>
#include <assert.h>
-#if PLATFORM == PLATFORM_WINDOWS
-#define STRCASECMP stricmp
-#else
-#define STRCASECMP strcasecmp
-#endif
-
#include <set>
#include <list>
#include <string>
@@ -114,8 +108,6 @@
#include <float.h>
-#define I32FMT "%08I32X"
-#define I64FMT "%016I64X"
#define snprintf _snprintf
#define atoll _atoi64
#define vsnprintf _vsnprintf
@@ -126,8 +118,6 @@
#define stricmp strcasecmp
#define strnicmp strncasecmp
-#define I32FMT "%08X"
-#define I64FMT "%016llX"
#endif
diff --git a/src/server/shared/Database/AdhocStatement.cpp b/src/server/shared/Database/AdhocStatement.cpp
index 15732f20849..896fefde5b7 100644
--- a/src/server/shared/Database/AdhocStatement.cpp
+++ b/src/server/shared/Database/AdhocStatement.cpp
@@ -42,13 +42,13 @@ bool BasicStatementTask::Execute()
if (m_has_result)
{
ResultSet* result = m_conn->Query(m_sql);
- if (!result || !result->GetRowCount())
+ if (!result || !result->GetRowCount() || !result->NextRow())
{
delete result;
m_result.set(QueryResult(NULL));
return false;
}
- result->NextRow();
+
m_result.set(QueryResult(result));
return true;
}
diff --git a/src/server/shared/Database/DatabaseWorkerPool.h b/src/server/shared/Database/DatabaseWorkerPool.h
index 6c2e961d2ad..e2ebda9e8ae 100644
--- a/src/server/shared/Database/DatabaseWorkerPool.h
+++ b/src/server/shared/Database/DatabaseWorkerPool.h
@@ -232,13 +232,12 @@ class DatabaseWorkerPool
ResultSet* result = conn->Query(sql);
conn->Unlock();
- if (!result || !result->GetRowCount())
+ if (!result || !result->GetRowCount() || !result->NextRow())
{
delete result;
return QueryResult(NULL);
}
- result->NextRow();
return QueryResult(result);
}
diff --git a/src/server/shared/Database/QueryHolder.cpp b/src/server/shared/Database/QueryHolder.cpp
index 0c80f70acd2..7b4105ee076 100644
--- a/src/server/shared/Database/QueryHolder.cpp
+++ b/src/server/shared/Database/QueryHolder.cpp
@@ -89,10 +89,9 @@ QueryResult SQLQueryHolder::GetResult(size_t index)
if (index < m_queries.size())
{
ResultSet* result = m_queries[index].second.qresult;
- if (!result || !result->GetRowCount())
+ if (!result || !result->GetRowCount() || !result->NextRow())
return QueryResult(NULL);
- result->NextRow();
return QueryResult(result);
}
else
diff --git a/src/server/shared/Dynamic/LinkedList.h b/src/server/shared/Dynamic/LinkedList.h
index 72d035c2cb6..402aaf3d40c 100644
--- a/src/server/shared/Dynamic/LinkedList.h
+++ b/src/server/shared/Dynamic/LinkedList.h
@@ -33,8 +33,8 @@ class LinkedListElement
LinkedListElement* iNext;
LinkedListElement* iPrev;
public:
- LinkedListElement(): iNext(NULL), iPrev(NULL) { }
- ~LinkedListElement() { delink(); }
+ LinkedListElement() : iNext(NULL), iPrev(NULL) { }
+ virtual ~LinkedListElement() { delink(); }
bool hasNext() const { return(iNext && iNext->iNext != NULL); }
bool hasPrev() const { return(iPrev && iPrev->iPrev != NULL); }
@@ -73,6 +73,10 @@ class LinkedListElement
iNext->iPrev = pElem;
iNext = pElem;
}
+
+ private:
+ LinkedListElement(LinkedListElement const&);
+ LinkedListElement& operator=(LinkedListElement const&);
};
//============================================
@@ -83,6 +87,7 @@ class LinkedListHead
LinkedListElement iFirst;
LinkedListElement iLast;
uint32 iSize;
+
public:
LinkedListHead(): iSize(0)
{
@@ -92,6 +97,8 @@ class LinkedListHead
iLast.iPrev = &iFirst;
}
+ virtual ~LinkedListHead() { }
+
bool isEmpty() const { return(!iFirst.iNext->isInList()); }
LinkedListElement * getFirst() { return(isEmpty() ? NULL : iFirst.iNext); }
@@ -239,6 +246,10 @@ class LinkedListHead
};
typedef Iterator<LinkedListElement> iterator;
+
+ private:
+ LinkedListHead(LinkedListHead const&);
+ LinkedListHead& operator=(LinkedListHead const&);
};
//============================================
diff --git a/src/server/shared/Dynamic/LinkedReference/Reference.h b/src/server/shared/Dynamic/LinkedReference/Reference.h
index 1ba41f1f454..83a1dd155b1 100644
--- a/src/server/shared/Dynamic/LinkedReference/Reference.h
+++ b/src/server/shared/Dynamic/LinkedReference/Reference.h
@@ -94,6 +94,10 @@ template <class TO, class FROM> class Reference : public LinkedListElement
TO* getTarget() const { return iRefTo; }
FROM* GetSource() const { return iRefFrom; }
+
+ private:
+ Reference(Reference const&);
+ Reference& operator=(Reference const&);
};
//=====================================================
diff --git a/src/server/shared/Logging/AppenderFile.cpp b/src/server/shared/Logging/AppenderFile.cpp
index a88188266e2..f2532ad8bb8 100644
--- a/src/server/shared/Logging/AppenderFile.cpp
+++ b/src/server/shared/Logging/AppenderFile.cpp
@@ -16,6 +16,7 @@
*/
#include "AppenderFile.h"
+#include "Common.h"
#if PLATFORM == PLATFORM_WINDOWS
# include <Windows.h>
@@ -80,6 +81,7 @@ FILE* AppenderFile::OpenFile(std::string const &filename, std::string const &mod
std::string newName(fullName);
newName.push_back('.');
newName.append(LogMessage::getTimeStr(time(NULL)));
+ std::replace(newName.begin(), newName.end(), ':', '-');
rename(fullName.c_str(), newName.c_str()); // no error handling... if we couldn't make a backup, just ignore
}
diff --git a/src/tools/vmap4_extractor/mpq_libmpq04.h b/src/tools/vmap4_extractor/mpq_libmpq04.h
index d045abe307a..46cb50fb003 100644
--- a/src/tools/vmap4_extractor/mpq_libmpq04.h
+++ b/src/tools/vmap4_extractor/mpq_libmpq04.h
@@ -36,7 +36,7 @@ public:
mpq_archive_s *mpq_a;
MPQArchive(const char* filename);
- void close();
+ ~MPQArchive() { close(); }
void GetFileListTo(vector<string>& filelist) {
uint32_t filenum;
@@ -65,6 +65,9 @@ public:
delete[] buffer;
}
+
+private:
+ void close();
};
typedef std::deque<MPQArchive*> ArchiveSet;