aboutsummaryrefslogtreecommitdiff
path: root/src/server/game
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2020-06-15 00:26:08 +0200
committerGitHub <noreply@github.com>2020-06-15 00:26:08 +0200
commitc715e635cf3feb50ac61d30659e614aaa2cc0c63 (patch)
tree5af30c80f8b1df3f60852adde4680951f6f55442 /src/server/game
parentabff505a6eaf3e649be506c802b80eed3dd35f3a (diff)
parentcf88f0a9735f9ba010a4ae46e848c8f1a86e17fa (diff)
Merge pull request #24554 from funjoker/cherry-picks
Diffstat (limited to 'src/server/game')
-rw-r--r--src/server/game/AI/CoreAI/CombatAI.cpp12
-rw-r--r--src/server/game/AI/CoreAI/CombatAI.h10
-rw-r--r--src/server/game/AI/CoreAI/GameObjectAI.cpp7
-rw-r--r--src/server/game/AI/CoreAI/GameObjectAI.h4
-rw-r--r--src/server/game/AI/CoreAI/GuardAI.cpp4
-rw-r--r--src/server/game/AI/CoreAI/GuardAI.h2
-rw-r--r--src/server/game/AI/CoreAI/PassiveAI.cpp27
-rw-r--r--src/server/game/AI/CoreAI/PassiveAI.h10
-rw-r--r--src/server/game/AI/CoreAI/PetAI.cpp10
-rw-r--r--src/server/game/AI/CoreAI/PetAI.h2
-rw-r--r--src/server/game/AI/CoreAI/ReactorAI.cpp2
-rw-r--r--src/server/game/AI/CoreAI/ReactorAI.h2
-rw-r--r--src/server/game/AI/CoreAI/TotemAI.cpp2
-rw-r--r--src/server/game/AI/CoreAI/TotemAI.h2
-rw-r--r--src/server/game/AI/CreatureAI.h2
-rw-r--r--src/server/game/AI/CreatureAIFactory.h60
-rw-r--r--src/server/game/AI/CreatureAIRegistry.cpp9
-rw-r--r--src/server/game/AI/CreatureAISelector.cpp160
-rw-r--r--src/server/game/AI/CreatureAISelector.h7
-rw-r--r--src/server/game/AI/GameObjectAIFactory.h54
-rw-r--r--src/server/game/AI/ScriptedAI/ScriptedCreature.cpp2
-rw-r--r--src/server/game/AI/ScriptedAI/ScriptedGossip.cpp1
-rw-r--r--src/server/game/AI/ScriptedAI/ScriptedGossip.h1
-rw-r--r--src/server/game/AI/SmartScripts/SmartAI.cpp29
-rw-r--r--src/server/game/AI/SmartScripts/SmartAI.h16
-rw-r--r--src/server/game/AI/SmartScripts/SmartScript.cpp8
-rw-r--r--src/server/game/Accounts/RBAC.h23
-rw-r--r--src/server/game/Battlefield/Zones/BattlefieldWG.cpp2
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp2
-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/Entities/Creature/Creature.cpp53
-rw-r--r--src/server/game/Entities/Creature/Creature.h5
-rw-r--r--src/server/game/Entities/GameObject/GameObject.cpp9
-rw-r--r--src/server/game/Entities/GameObject/GameObject.h2
-rw-r--r--src/server/game/Entities/Player/Player.cpp68
-rw-r--r--src/server/game/Entities/Transport/Transport.cpp2
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp59
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp19
-rw-r--r--src/server/game/Groups/GroupMgr.cpp13
-rw-r--r--src/server/game/Miscellaneous/SharedDefines.h45
-rw-r--r--src/server/game/Movement/MotionMaster.cpp19
-rw-r--r--src/server/game/Movement/MovementGenerator.cpp7
-rwxr-xr-xsrc/server/game/Movement/MovementGenerator.h24
-rw-r--r--src/server/game/Movement/MovementGeneratorImpl.h29
-rw-r--r--src/server/game/Movement/MovementGenerators/IdleMovementGenerator.cpp2
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/IdleMovementGenerator.h2
-rw-r--r--src/server/game/Scripting/ScriptMgr.cpp5
-rw-r--r--src/server/game/Scripting/ScriptSystem.h24
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp12
-rw-r--r--src/server/game/Spells/Spell.cpp15
-rw-r--r--src/server/game/Spells/SpellEffects.cpp13
-rw-r--r--src/server/game/Spells/SpellInfo.cpp29
-rw-r--r--src/server/game/Spells/SpellInfo.h1
-rw-r--r--src/server/game/Spells/SpellMgr.cpp8
-rw-r--r--src/server/game/World/World.cpp6
56 files changed, 496 insertions, 451 deletions
diff --git a/src/server/game/AI/CoreAI/CombatAI.cpp b/src/server/game/AI/CoreAI/CombatAI.cpp
index 2f2461b5ab0..160b58a9742 100644
--- a/src/server/game/AI/CoreAI/CombatAI.cpp
+++ b/src/server/game/AI/CoreAI/CombatAI.cpp
@@ -32,11 +32,11 @@
// AggressorAI
/////////////////
-int AggressorAI::Permissible(const Creature* creature)
+int32 AggressorAI::Permissible(Creature const* creature)
{
// have some hostile factions, it will be selected by IsHostileTo check at MoveInLineOfSight
if (!creature->IsCivilian() && !creature->IsNeutralToAll())
- return PERMIT_BASE_PROACTIVE;
+ return PERMIT_BASE_REACTIVE;
return PERMIT_BASE_NO;
}
@@ -344,3 +344,11 @@ void VehicleAI::CheckConditions(uint32 diff)
else
m_ConditionsTimer -= diff;
}
+
+int32 VehicleAI::Permissible(Creature const* creature)
+{
+ if (creature->IsVehicle())
+ return PERMIT_BASE_SPECIAL;
+
+ return PERMIT_BASE_NO;
+}
diff --git a/src/server/game/AI/CoreAI/CombatAI.h b/src/server/game/AI/CoreAI/CombatAI.h
index 9e4e05d9544..9082ad515e8 100644
--- a/src/server/game/AI/CoreAI/CombatAI.h
+++ b/src/server/game/AI/CoreAI/CombatAI.h
@@ -28,7 +28,7 @@ class TC_GAME_API AggressorAI : public CreatureAI
explicit AggressorAI(Creature* c) : CreatureAI(c) { }
void UpdateAI(uint32) override;
- static int Permissible(const Creature*);
+ static int32 Permissible(Creature const* creature);
};
typedef std::vector<uint32> SpellVct;
@@ -45,7 +45,7 @@ class TC_GAME_API CombatAI : public CreatureAI
void UpdateAI(uint32 diff) override;
void SpellInterrupted(uint32 spellId, uint32 unTimeMs) override;
- static int Permissible(Creature const* /*creature*/) { return PERMIT_BASE_NO; }
+ static int32 Permissible(Creature const* /*creature*/) { return PERMIT_BASE_NO; }
protected:
EventMap events;
@@ -71,7 +71,7 @@ struct TC_GAME_API ArcherAI : public CreatureAI
void AttackStart(Unit* who) override;
void UpdateAI(uint32 diff) override;
- static int Permissible(Creature const* /*creature*/) { return PERMIT_BASE_NO; }
+ static int32 Permissible(Creature const* /*creature*/) { return PERMIT_BASE_NO; }
protected:
float m_minRange;
@@ -85,7 +85,7 @@ struct TC_GAME_API TurretAI : public CreatureAI
void AttackStart(Unit* who) override;
void UpdateAI(uint32 diff) override;
- static int Permissible(Creature const* /*creature*/) { return PERMIT_BASE_NO; }
+ static int32 Permissible(Creature const* /*creature*/) { return PERMIT_BASE_NO; }
protected:
float m_minRange;
@@ -104,7 +104,7 @@ struct TC_GAME_API VehicleAI : public CreatureAI
void AttackStart(Unit*) override { }
void OnCharmed(bool apply) override;
- static int Permissible(Creature const* /*creature*/) { return PERMIT_BASE_NO; }
+ static int32 Permissible(Creature const* creature);
private:
void LoadConditions();
diff --git a/src/server/game/AI/CoreAI/GameObjectAI.cpp b/src/server/game/AI/CoreAI/GameObjectAI.cpp
index 48caa63dbce..94fe71f449d 100644
--- a/src/server/game/AI/CoreAI/GameObjectAI.cpp
+++ b/src/server/game/AI/CoreAI/GameObjectAI.cpp
@@ -20,11 +20,8 @@
#include "GameObject.h"
#include "QuestDef.h"
-//GameObjectAI::GameObjectAI(GameObject* g) : go(g) { }
-int GameObjectAI::Permissible(const GameObject* go)
+int32 GameObjectAI::Permissible(GameObject const* /*go*/)
{
- if (go->GetAIName() == "GameObjectAI")
- return PERMIT_BASE_SPECIAL;
return PERMIT_BASE_NO;
}
@@ -35,7 +32,7 @@ uint32 GameObjectAI::GetDialogStatus(Player* /*player*/)
NullGameObjectAI::NullGameObjectAI(GameObject* g) : GameObjectAI(g) { }
-int NullGameObjectAI::Permissible(GameObject const* /*go*/)
+int32 NullGameObjectAI::Permissible(GameObject const* /*go*/)
{
return PERMIT_BASE_IDLE;
}
diff --git a/src/server/game/AI/CoreAI/GameObjectAI.h b/src/server/game/AI/CoreAI/GameObjectAI.h
index 655035d505b..4bfc6c7a2f3 100644
--- a/src/server/game/AI/CoreAI/GameObjectAI.h
+++ b/src/server/game/AI/CoreAI/GameObjectAI.h
@@ -46,7 +46,7 @@ class TC_GAME_API GameObjectAI
virtual void SetGUID(uint64 /*guid*/, int32 /*id = 0 */) { }
virtual uint64 GetGUID(int32 /*id = 0 */) const { return 0; }
- static int Permissible(GameObject const* go);
+ static int32 Permissible(GameObject const* /*go*/);
// Called when a player opens a gossip dialog with the gameobject.
virtual bool GossipHello(Player* /*player*/, bool /*reportUse*/) { return false; }
@@ -88,6 +88,6 @@ class TC_GAME_API NullGameObjectAI : public GameObjectAI
void UpdateAI(uint32 /*diff*/) override { }
- static int Permissible(GameObject const* /*go*/);
+ static int32 Permissible(GameObject const* /*go*/);
};
#endif
diff --git a/src/server/game/AI/CoreAI/GuardAI.cpp b/src/server/game/AI/CoreAI/GuardAI.cpp
index f9d3b96cadb..2b358945bd9 100644
--- a/src/server/game/AI/CoreAI/GuardAI.cpp
+++ b/src/server/game/AI/CoreAI/GuardAI.cpp
@@ -26,10 +26,10 @@ GuardAI::GuardAI(Creature* creature) : ScriptedAI(creature)
{
}
-int GuardAI::Permissible(Creature const* creature)
+int32 GuardAI::Permissible(Creature const* creature)
{
if (creature->IsGuard())
- return PERMIT_BASE_SPECIAL;
+ return PERMIT_BASE_PROACTIVE;
return PERMIT_BASE_NO;
}
diff --git a/src/server/game/AI/CoreAI/GuardAI.h b/src/server/game/AI/CoreAI/GuardAI.h
index a731e160e90..037094cff4b 100644
--- a/src/server/game/AI/CoreAI/GuardAI.h
+++ b/src/server/game/AI/CoreAI/GuardAI.h
@@ -27,7 +27,7 @@ class TC_GAME_API GuardAI : public ScriptedAI
public:
explicit GuardAI(Creature* creature);
- static int Permissible(Creature const* creature);
+ static int32 Permissible(Creature const* creature);
void UpdateAI(uint32 diff) override;
bool CanSeeAlways(WorldObject const* obj) override;
diff --git a/src/server/game/AI/CoreAI/PassiveAI.cpp b/src/server/game/AI/CoreAI/PassiveAI.cpp
index 417a3c9bf04..5c3e8026600 100644
--- a/src/server/game/AI/CoreAI/PassiveAI.cpp
+++ b/src/server/game/AI/CoreAI/PassiveAI.cpp
@@ -22,6 +22,17 @@ PassiveAI::PassiveAI(Creature* c) : CreatureAI(c) { me->SetReactState(REACT_PASS
PossessedAI::PossessedAI(Creature* c) : CreatureAI(c) { me->SetReactState(REACT_PASSIVE); }
NullCreatureAI::NullCreatureAI(Creature* c) : CreatureAI(c) { me->SetReactState(REACT_PASSIVE); }
+int32 NullCreatureAI::Permissible(Creature const* creature)
+{
+ if (creature->HasNpcFlag(UNIT_NPC_FLAG_SPELLCLICK))
+ return PERMIT_BASE_PROACTIVE + 50;
+
+ if (creature->IsTrigger())
+ return PERMIT_BASE_REACTIVE;
+
+ return PERMIT_BASE_IDLE;
+}
+
void PassiveAI::UpdateAI(uint32)
{
if (me->IsInCombat() && me->getAttackers().empty())
@@ -76,8 +87,24 @@ void CritterAI::EnterEvadeMode(EvadeReason why)
CreatureAI::EnterEvadeMode(why);
}
+int32 CritterAI::Permissible(Creature const* creature)
+{
+ if (creature->IsCritter() && !creature->HasUnitTypeMask(UNIT_MASK_GUARDIAN))
+ return PERMIT_BASE_PROACTIVE;
+
+ return PERMIT_BASE_NO;
+}
+
void TriggerAI::IsSummonedBy(Unit* summoner)
{
if (me->m_spells[0])
me->CastSpell(me, me->m_spells[0], false, nullptr, nullptr, summoner->GetGUID());
}
+
+int32 TriggerAI::Permissible(Creature const* creature)
+{
+ if (creature->IsTrigger() && creature->m_spells[0])
+ return PERMIT_BASE_PROACTIVE;
+
+ return PERMIT_BASE_NO;
+}
diff --git a/src/server/game/AI/CoreAI/PassiveAI.h b/src/server/game/AI/CoreAI/PassiveAI.h
index 43ad670e0df..41d4c2bfb12 100644
--- a/src/server/game/AI/CoreAI/PassiveAI.h
+++ b/src/server/game/AI/CoreAI/PassiveAI.h
@@ -29,7 +29,7 @@ class TC_GAME_API PassiveAI : public CreatureAI
void AttackStart(Unit*) override { }
void UpdateAI(uint32) override;
- static int Permissible(const Creature*) { return PERMIT_BASE_IDLE; }
+ static int32 Permissible(Creature const* /*creature*/) { return PERMIT_BASE_NO; }
};
class TC_GAME_API PossessedAI : public CreatureAI
@@ -47,7 +47,7 @@ class TC_GAME_API PossessedAI : public CreatureAI
void OnCharmed(bool /*apply*/) override;
- static int Permissible(const Creature*) { return PERMIT_BASE_IDLE; }
+ static int32 Permissible(Creature const* /*creature*/) { return PERMIT_BASE_NO; }
};
class TC_GAME_API NullCreatureAI : public CreatureAI
@@ -61,7 +61,7 @@ class TC_GAME_API NullCreatureAI : public CreatureAI
void EnterEvadeMode(EvadeReason /*why*/) override { }
void OnCharmed(bool /*apply*/) override { }
- static int Permissible(const Creature*) { return PERMIT_BASE_IDLE; }
+ static int32 Permissible(Creature const* creature);
};
class TC_GAME_API CritterAI : public PassiveAI
@@ -71,6 +71,8 @@ class TC_GAME_API CritterAI : public PassiveAI
void DamageTaken(Unit* done_by, uint32& /*damage*/) override;
void EnterEvadeMode(EvadeReason why) override;
+
+ static int32 Permissible(Creature const* creature);
};
class TC_GAME_API TriggerAI : public NullCreatureAI
@@ -78,6 +80,8 @@ class TC_GAME_API TriggerAI : public NullCreatureAI
public:
explicit TriggerAI(Creature* c) : NullCreatureAI(c) { }
void IsSummonedBy(Unit* summoner) override;
+
+ static int32 Permissible(Creature const* creature);
};
#endif
diff --git a/src/server/game/AI/CoreAI/PetAI.cpp b/src/server/game/AI/CoreAI/PetAI.cpp
index a39e4a8dfc0..c16e1f945eb 100644
--- a/src/server/game/AI/CoreAI/PetAI.cpp
+++ b/src/server/game/AI/CoreAI/PetAI.cpp
@@ -31,10 +31,14 @@
#include "SpellMgr.h"
#include "Util.h"
-int PetAI::Permissible(const Creature* creature)
+int32 PetAI::Permissible(Creature const* creature)
{
- if (creature->IsPet())
- return PERMIT_BASE_SPECIAL;
+ if (creature->HasUnitTypeMask(UNIT_MASK_CONTROLABLE_GUARDIAN))
+ {
+ if (reinterpret_cast<Guardian const*>(creature)->GetOwner()->GetTypeId() == TYPEID_PLAYER)
+ return PERMIT_BASE_PROACTIVE;
+ return PERMIT_BASE_REACTIVE;
+ }
return PERMIT_BASE_NO;
}
diff --git a/src/server/game/AI/CoreAI/PetAI.h b/src/server/game/AI/CoreAI/PetAI.h
index c712d42651d..4455c1cd494 100644
--- a/src/server/game/AI/CoreAI/PetAI.h
+++ b/src/server/game/AI/CoreAI/PetAI.h
@@ -33,7 +33,7 @@ class TC_GAME_API PetAI : public CreatureAI
explicit PetAI(Creature* c);
void UpdateAI(uint32) override;
- static int Permissible(const Creature*);
+ static int32 Permissible(Creature const* creature);
void KilledUnit(Unit* /*victim*/) override;
void AttackStart(Unit* target) override;
diff --git a/src/server/game/AI/CoreAI/ReactorAI.cpp b/src/server/game/AI/CoreAI/ReactorAI.cpp
index 836cc1e0358..8b15bed1908 100644
--- a/src/server/game/AI/CoreAI/ReactorAI.cpp
+++ b/src/server/game/AI/CoreAI/ReactorAI.cpp
@@ -18,7 +18,7 @@
#include "ReactorAI.h"
#include "Creature.h"
-int ReactorAI::Permissible(const Creature* creature)
+int32 ReactorAI::Permissible(Creature const* creature)
{
if (creature->IsCivilian() || creature->IsNeutralToAll())
return PERMIT_BASE_REACTIVE;
diff --git a/src/server/game/AI/CoreAI/ReactorAI.h b/src/server/game/AI/CoreAI/ReactorAI.h
index fa0bd2d8ee1..be76f855781 100644
--- a/src/server/game/AI/CoreAI/ReactorAI.h
+++ b/src/server/game/AI/CoreAI/ReactorAI.h
@@ -29,6 +29,6 @@ class TC_GAME_API ReactorAI : public CreatureAI
void MoveInLineOfSight(Unit*) override { }
void UpdateAI(uint32 diff) override;
- static int Permissible(const Creature*);
+ static int32 Permissible(Creature const* creature);
};
#endif
diff --git a/src/server/game/AI/CoreAI/TotemAI.cpp b/src/server/game/AI/CoreAI/TotemAI.cpp
index 4d2bda5faa0..c727ea45003 100644
--- a/src/server/game/AI/CoreAI/TotemAI.cpp
+++ b/src/server/game/AI/CoreAI/TotemAI.cpp
@@ -24,7 +24,7 @@
#include "GridNotifiersImpl.h"
#include "CellImpl.h"
-int TotemAI::Permissible(Creature const* creature)
+int32 TotemAI::Permissible(Creature const* creature)
{
if (creature->IsTotem())
return PERMIT_BASE_PROACTIVE;
diff --git a/src/server/game/AI/CoreAI/TotemAI.h b/src/server/game/AI/CoreAI/TotemAI.h
index 2938190c771..fd25ca86df6 100644
--- a/src/server/game/AI/CoreAI/TotemAI.h
+++ b/src/server/game/AI/CoreAI/TotemAI.h
@@ -35,7 +35,7 @@ class TC_GAME_API TotemAI : public CreatureAI
void EnterEvadeMode(EvadeReason /*why*/) override;
void UpdateAI(uint32 diff) override;
- static int Permissible(Creature const* creature);
+ static int32 Permissible(Creature const* creature);
private:
ObjectGuid i_victimGuid;
diff --git a/src/server/game/AI/CreatureAI.h b/src/server/game/AI/CreatureAI.h
index b274a4794d1..41e6ab2501d 100644
--- a/src/server/game/AI/CreatureAI.h
+++ b/src/server/game/AI/CreatureAI.h
@@ -204,7 +204,7 @@ class TC_GAME_API CreatureAI : public UnitAI
bool m_MoveInLineOfSight_locked;
};
-enum Permitions
+enum Permitions : int32
{
PERMIT_BASE_NO = -1,
PERMIT_BASE_IDLE = 1,
diff --git a/src/server/game/AI/CreatureAIFactory.h b/src/server/game/AI/CreatureAIFactory.h
index 656435ad632..92e757d835d 100644
--- a/src/server/game/AI/CreatureAIFactory.h
+++ b/src/server/game/AI/CreatureAIFactory.h
@@ -18,66 +18,34 @@
#ifndef TRINITY_CREATUREAIFACTORY_H
#define TRINITY_CREATUREAIFACTORY_H
-//#include "Policies/Singleton.h"
#include "ObjectRegistry.h"
#include "FactoryHolder.h"
-#include "GameObjectAI.h"
-struct SelectableAI : public FactoryHolder<CreatureAI>, public Permissible<Creature>
+typedef FactoryHolder<CreatureAI, Creature> CreatureAICreator;
+
+struct SelectableAI : public CreatureAICreator, public Permissible<Creature>
{
- SelectableAI(const char* id) : FactoryHolder<CreatureAI>(id) { }
+ SelectableAI(std::string const& name) : CreatureAICreator(name), Permissible<Creature>() { }
};
template<class REAL_AI>
struct CreatureAIFactory : public SelectableAI
{
- CreatureAIFactory(const char* name) : SelectableAI(name) { }
+ CreatureAIFactory(std::string const& name) : SelectableAI(name) { }
- CreatureAI* Create(void*) const override;
+ inline CreatureAI* Create(Creature* c) const override
+ {
+ return new REAL_AI(c);
+ }
- int Permit(const Creature* c) const override { return REAL_AI::Permissible(c); }
+ int32 Permit(Creature const* c) const override
+ {
+ return REAL_AI::Permissible(c);
+ }
};
-template<class REAL_AI>
-inline CreatureAI*
-CreatureAIFactory<REAL_AI>::Create(void* data) const
-{
- Creature* creature = reinterpret_cast<Creature*>(data);
- return (new REAL_AI(creature));
-}
-
-typedef FactoryHolder<CreatureAI> CreatureAICreator;
-typedef FactoryHolder<CreatureAI>::FactoryHolderRegistry CreatureAIRegistry;
+typedef CreatureAICreator::FactoryHolderRegistry CreatureAIRegistry;
#define sCreatureAIRegistry CreatureAIRegistry::instance()
-//GO
-struct SelectableGameObjectAI : public FactoryHolder<GameObjectAI>, public Permissible<GameObject>
-{
- SelectableGameObjectAI(const char* id) : FactoryHolder<GameObjectAI>(id) { }
-};
-
-template<class REAL_GO_AI>
-struct GameObjectAIFactory : public SelectableGameObjectAI
-{
- GameObjectAIFactory(const char* name) : SelectableGameObjectAI(name) { }
-
- GameObjectAI* Create(void*) const override;
-
- int Permit(const GameObject* g) const override { return REAL_GO_AI::Permissible(g); }
-};
-
-template<class REAL_GO_AI>
-inline GameObjectAI*
-GameObjectAIFactory<REAL_GO_AI>::Create(void* data) const
-{
- GameObject* go = reinterpret_cast<GameObject*>(data);
- return (new REAL_GO_AI(go));
-}
-
-typedef FactoryHolder<GameObjectAI> GameObjectAICreator;
-typedef FactoryHolder<GameObjectAI>::FactoryHolderRegistry GameObjectAIRegistry;
-
-#define sGameObjectAIRegistry GameObjectAIRegistry::instance()
-
#endif
diff --git a/src/server/game/AI/CreatureAIRegistry.cpp b/src/server/game/AI/CreatureAIRegistry.cpp
index 9aab7376ab2..34cc64af22b 100644
--- a/src/server/game/AI/CreatureAIRegistry.cpp
+++ b/src/server/game/AI/CreatureAIRegistry.cpp
@@ -22,10 +22,11 @@
#include "PetAI.h"
#include "TotemAI.h"
#include "RandomMovementGenerator.h"
-#include "MovementGeneratorImpl.h"
+#include "MovementGenerator.h"
#include "CreatureAIRegistry.h"
#include "WaypointMovementGenerator.h"
#include "CreatureAIFactory.h"
+#include "GameObjectAIFactory.h"
#include "SmartAI.h"
namespace AIRegistry
@@ -47,10 +48,12 @@ namespace AIRegistry
(new CreatureAIFactory<VehicleAI>("VehicleAI"))->RegisterSelf();
(new CreatureAIFactory<SmartAI>("SmartAI"))->RegisterSelf();
+ (new GameObjectAIFactory<NullGameObjectAI>("NullGameObjectAI"))->RegisterSelf();
(new GameObjectAIFactory<GameObjectAI>("GameObjectAI"))->RegisterSelf();
(new GameObjectAIFactory<SmartGameObjectAI>("SmartGameObjectAI"))->RegisterSelf();
- (new MovementGeneratorFactory<RandomMovementGenerator<Creature> >(RANDOM_MOTION_TYPE))->RegisterSelf();
- (new MovementGeneratorFactory<WaypointMovementGenerator<Creature> >(WAYPOINT_MOTION_TYPE))->RegisterSelf();
+ (new IdleMovementFactory())->RegisterSelf();
+ (new MovementGeneratorFactory<RandomMovementGenerator<Creature>>(RANDOM_MOTION_TYPE))->RegisterSelf();
+ (new MovementGeneratorFactory<WaypointMovementGenerator<Creature>>(WAYPOINT_MOTION_TYPE))->RegisterSelf();
}
}
diff --git a/src/server/game/AI/CreatureAISelector.cpp b/src/server/game/AI/CreatureAISelector.cpp
index 487511eff3e..b7181a35f76 100644
--- a/src/server/game/AI/CreatureAISelector.cpp
+++ b/src/server/game/AI/CreatureAISelector.cpp
@@ -17,130 +17,94 @@
#include "Creature.h"
#include "CreatureAISelector.h"
-#include "GameObject.h"
-#include "PassiveAI.h"
+#include "CreatureAIFactory.h"
#include "Log.h"
#include "MovementGenerator.h"
-#include "TemporarySummon.h"
-#include "CreatureAIFactory.h"
+
+#include "GameObject.h"
+#include "GameObjectAIFactory.h"
+
#include "ScriptMgr.h"
namespace FactorySelector
{
- CreatureAI* selectAI(Creature* creature)
+ template <class T, class Value>
+ inline int32 GetPermitFor(T const* obj, Value const& value)
{
- const CreatureAICreator* ai_factory = NULL;
-
- if (creature->IsPet())
- ai_factory = sCreatureAIRegistry->GetRegistryItem("PetAI");
-
- //scriptname in db
- if (!ai_factory)
- if (CreatureAI* scriptedAI = sScriptMgr->GetCreatureAI(creature))
- return scriptedAI;
+ Permissible<T> const* const p = ASSERT_NOTNULL(dynamic_cast<Permissible<T> const*>(value.second.get()));
+ return p->Permit(obj);
+ }
- // AIname in db
- std::string ainame=creature->GetAIName();
- if (!ai_factory && !ainame.empty())
- ai_factory = sCreatureAIRegistry->GetRegistryItem(ainame);
+ template <class T>
+ struct PermissibleOrderPred
+ {
+ public:
+ PermissibleOrderPred(T const* obj) : _obj(obj) { }
- // select by NPC flags
- if (!ai_factory)
+ template <class Value>
+ bool operator()(Value const& left, Value const& right) const
{
- if (creature->IsVehicle())
- ai_factory = sCreatureAIRegistry->GetRegistryItem("VehicleAI");
- else if (creature->HasUnitTypeMask(UNIT_MASK_CONTROLABLE_GUARDIAN) && ((Guardian*)creature)->GetOwner()->GetTypeId() == TYPEID_PLAYER)
- ai_factory = sCreatureAIRegistry->GetRegistryItem("PetAI");
- else if (creature->HasNpcFlag(UNIT_NPC_FLAG_SPELLCLICK))
- ai_factory = sCreatureAIRegistry->GetRegistryItem("NullCreatureAI");
- else if (creature->IsGuard())
- ai_factory = sCreatureAIRegistry->GetRegistryItem("GuardAI");
- else if (creature->HasUnitTypeMask(UNIT_MASK_CONTROLABLE_GUARDIAN))
- ai_factory = sCreatureAIRegistry->GetRegistryItem("PetAI");
- else if (creature->IsTotem())
- ai_factory = sCreatureAIRegistry->GetRegistryItem("TotemAI");
- else if (creature->IsTrigger())
- {
- if (creature->m_spells[0])
- ai_factory = sCreatureAIRegistry->GetRegistryItem("TriggerAI");
- else
- ai_factory = sCreatureAIRegistry->GetRegistryItem("NullCreatureAI");
- }
- else if (creature->IsCritter() && !creature->HasUnitTypeMask(UNIT_MASK_GUARDIAN))
- ai_factory = sCreatureAIRegistry->GetRegistryItem("CritterAI");
+ return GetPermitFor(_obj, left) < GetPermitFor(_obj, right);
}
- // select by permit check
- if (!ai_factory)
- {
- int best_val = -1;
- typedef CreatureAIRegistry::RegistryMapType RMT;
- RMT const& l = sCreatureAIRegistry->GetRegisteredItems();
- for (RMT::const_iterator iter = l.begin(); iter != l.end(); ++iter)
- {
- const CreatureAICreator* factory = iter->second;
- const SelectableAI* p = dynamic_cast<const SelectableAI*>(factory);
- ASSERT(p);
- int val = p->Permit(creature);
- if (val > best_val)
- {
- best_val = val;
- ai_factory = p;
- }
- }
- }
+ private:
+ T const* const _obj;
+ };
- // select NullCreatureAI if not another cases
- ainame = (ai_factory == NULL) ? "NullCreatureAI" : ai_factory->key();
+ template <class AI, class T>
+ inline FactoryHolder<AI, T> const* SelectFactory(T* obj)
+ {
+ static_assert(std::is_same<AI, CreatureAI>::value || std::is_same<AI, GameObjectAI>::value, "Invalid template parameter");
+ static_assert(std::is_same<AI, CreatureAI>::value == std::is_same<T, Creature>::value, "Incompatible AI for type");
+ static_assert(std::is_same<AI, GameObjectAI>::value == std::is_same<T, GameObject>::value, "Incompatible AI for type");
- TC_LOG_DEBUG("scripts", "Creature %s (%s DB GUID: " UI64FMTD ") is using AI type: %s.", creature->GetName().c_str(), creature->GetGUID().ToString().c_str(), creature->GetSpawnId(), ainame.c_str());
- return (ai_factory == NULL ? new NullCreatureAI(creature) : ai_factory->Create(creature));
- }
+ using AIRegistry = typename FactoryHolder<AI, T>::FactoryHolderRegistry;
- MovementGenerator* selectMovementGenerator(Creature* creature)
- {
- MovementGeneratorRegistry& mv_registry(*MovementGeneratorRegistry::instance());
- ASSERT(creature->GetCreatureTemplate());
- const MovementGeneratorCreator* mv_factory = mv_registry.GetRegistryItem(creature->GetDefaultMovementType());
+ // AIName in db
+ std::string const& aiName = obj->GetAIName();
+ if (!aiName.empty())
+ return AIRegistry::instance()->GetRegistryItem(aiName);
- /* if (mv_factory == NULL)
- {
- int best_val = -1;
- StringVector l;
- mv_registry.GetRegisteredItems(l);
- for (StringVector::iterator iter = l.begin(); iter != l.end(); ++iter)
- {
- const MovementGeneratorCreator *factory = mv_registry.GetRegistryItem((*iter).c_str());
- const SelectableMovement *p = dynamic_cast<const SelectableMovement *>(factory);
- ASSERT(p != NULL);
- int val = p->Permit(creature);
- if (val > best_val)
- {
- best_val = val;
- mv_factory = p;
- }
- }
- }*/
-
- return (mv_factory == NULL ? NULL : mv_factory->Create(creature));
+ // select by permit check
+ typename AIRegistry::RegistryMapType const& items = AIRegistry::instance()->GetRegisteredItems();
+ auto itr = std::max_element(items.begin(), items.end(), PermissibleOrderPred<T>(obj));
+ if (itr != items.end() && GetPermitFor(obj, *itr) >= 0)
+ return itr->second.get();
+
+ // should _never_ happen, Null AI types defined as PERMIT_BASE_IDLE, it must've been found
+ ABORT();
+ return nullptr;
}
- GameObjectAI* SelectGameObjectAI(GameObject* go)
+ CreatureAI* SelectAI(Creature* creature)
{
- GameObjectAICreator const* ai_factory = NULL;
+ // special pet case, if a tamed creature uses AIName (example SmartAI) we need to override it
+ if (creature->IsPet())
+ return ASSERT_NOTNULL(sCreatureAIRegistry->GetRegistryItem("PetAI"))->Create(creature);
// scriptname in db
- if (GameObjectAI* scriptedAI = sScriptMgr->GetGameObjectAI(go))
+ if (CreatureAI* scriptedAI = sScriptMgr->GetCreatureAI(creature))
return scriptedAI;
- ai_factory = sGameObjectAIRegistry->GetRegistryItem(go->GetAIName());
+ return SelectFactory<CreatureAI>(creature)->Create(creature);
+ }
- //future goAI types go here
+ MovementGenerator* SelectMovementGenerator(Unit* unit)
+ {
+ MovementGeneratorType type = IDLE_MOTION_TYPE;
+ if (unit->GetTypeId() == TYPEID_UNIT)
+ type = unit->ToCreature()->GetDefaultMovementType();
- std::string ainame = (ai_factory == NULL || go->GetScriptId()) ? "NullGameObjectAI" : ai_factory->key();
+ MovementGeneratorCreator const* mv_factory = sMovementGeneratorRegistry->GetRegistryItem(type);
+ return ASSERT_NOTNULL(mv_factory)->Create(unit);
+ }
- TC_LOG_DEBUG("scripts", "%s used AI is %s.", go->GetGUID().ToString().c_str(), ainame.c_str());
+ GameObjectAI* SelectGameObjectAI(GameObject* go)
+ {
+ // scriptname in db
+ if (GameObjectAI* scriptedAI = sScriptMgr->GetGameObjectAI(go))
+ return scriptedAI;
- return (ai_factory == NULL ? new NullGameObjectAI(go) : ai_factory->Create(go));
+ return SelectFactory<GameObjectAI>(go)->Create(go);
}
}
diff --git a/src/server/game/AI/CreatureAISelector.h b/src/server/game/AI/CreatureAISelector.h
index d22bf0bb1e7..b4046a5e982 100644
--- a/src/server/game/AI/CreatureAISelector.h
+++ b/src/server/game/AI/CreatureAISelector.h
@@ -21,13 +21,14 @@
class CreatureAI;
class Creature;
class MovementGenerator;
+class Unit;
class GameObjectAI;
class GameObject;
namespace FactorySelector
{
- TC_GAME_API CreatureAI* selectAI(Creature*);
- TC_GAME_API MovementGenerator* selectMovementGenerator(Creature*);
- TC_GAME_API GameObjectAI* SelectGameObjectAI(GameObject*);
+ TC_GAME_API CreatureAI* SelectAI(Creature* creature);
+ TC_GAME_API MovementGenerator* SelectMovementGenerator(Unit* unit);
+ TC_GAME_API GameObjectAI* SelectGameObjectAI(GameObject* go);
}
#endif
diff --git a/src/server/game/AI/GameObjectAIFactory.h b/src/server/game/AI/GameObjectAIFactory.h
new file mode 100644
index 00000000000..88dcb5cbb81
--- /dev/null
+++ b/src/server/game/AI/GameObjectAIFactory.h
@@ -0,0 +1,54 @@
+/*
+ * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TRINITY_GAMEOBJECTAIFACTORY_H
+#define TRINITY_GAMEOBJECTAIFACTORY_H
+
+#include "ObjectRegistry.h"
+#include "FactoryHolder.h"
+
+class GameObject;
+class GameObjectAI;
+
+typedef FactoryHolder<GameObjectAI, GameObject> GameObjectAICreator;
+
+struct SelectableGameObjectAI : public GameObjectAICreator, public Permissible<GameObject>
+{
+ SelectableGameObjectAI(std::string const& name) : GameObjectAICreator(name), Permissible<GameObject>() { }
+};
+
+template<class REAL_GO_AI>
+struct GameObjectAIFactory : public SelectableGameObjectAI
+{
+ GameObjectAIFactory(std::string const& name) : SelectableGameObjectAI(name) { }
+
+ GameObjectAI* Create(GameObject* go) const override
+ {
+ return new REAL_GO_AI(go);
+ }
+
+ int32 Permit(GameObject const* go) const override
+ {
+ return REAL_GO_AI::Permissible(go);
+ }
+};
+
+typedef GameObjectAICreator::FactoryHolderRegistry GameObjectAIRegistry;
+
+#define sGameObjectAIRegistry GameObjectAIRegistry::instance()
+
+#endif
diff --git a/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp b/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp
index 71125e716a6..bde3a192642 100644
--- a/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp
+++ b/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp
@@ -537,7 +537,7 @@ bool BossAI::CanAIAttack(Unit const* target) const
return CheckBoundary(target);
}
-void BossAI::_DespawnAtEvade(uint32 delayToRespawn, Creature* who)
+void BossAI::_DespawnAtEvade(uint32 delayToRespawn /*= 30*/, Creature* who /*= nullptr*/)
{
if (delayToRespawn < 2)
{
diff --git a/src/server/game/AI/ScriptedAI/ScriptedGossip.cpp b/src/server/game/AI/ScriptedAI/ScriptedGossip.cpp
index 0e0ad589518..33e69bf850c 100644
--- a/src/server/game/AI/ScriptedAI/ScriptedGossip.cpp
+++ b/src/server/game/AI/ScriptedAI/ScriptedGossip.cpp
@@ -19,6 +19,7 @@
#include "Creature.h"
#include "Player.h"
+uint32 GetGossipActionFor(Player* player, uint32 gossipListId) { return player->PlayerTalkClass->GetGossipOptionAction(gossipListId); }
void ClearGossipMenuFor(Player* player) { player->PlayerTalkClass->ClearMenus(); }
// Using provided text, not from DB
void AddGossipItemFor(Player* player, uint32 icon, std::string const& text, uint32 sender, uint32 action) { player->PlayerTalkClass->GetGossipMenu().AddMenuItem(-1, icon, text, sender, action, "", 0); }
diff --git a/src/server/game/AI/ScriptedAI/ScriptedGossip.h b/src/server/game/AI/ScriptedAI/ScriptedGossip.h
index 3032059d81b..6963155c94a 100644
--- a/src/server/game/AI/ScriptedAI/ScriptedGossip.h
+++ b/src/server/game/AI/ScriptedAI/ScriptedGossip.h
@@ -86,6 +86,7 @@ enum eTradeskill
GOSSIP_SENDER_SEC_STABLEMASTER = 10
};
+uint32 TC_GAME_API GetGossipActionFor(Player* player, uint32 gossipListId);
void TC_GAME_API ClearGossipMenuFor(Player* player);
// Using provided text, not from DB
void TC_GAME_API AddGossipItemFor(Player* player, uint32 icon, std::string const& text, uint32 sender, uint32 action);
diff --git a/src/server/game/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp
index 2dd122de1ee..065ca31bee0 100644
--- a/src/server/game/AI/SmartScripts/SmartAI.cpp
+++ b/src/server/game/AI/SmartScripts/SmartAI.cpp
@@ -74,6 +74,8 @@ SmartAI::SmartAI(Creature* c) : CreatureAI(c)
mJustReset = false;
mConditionsTimer = 0;
mHasConditions = sConditionMgr->HasConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_CREATURE_TEMPLATE_VEHICLE, c->GetEntry());
+
+ _gossipReturn = false;
}
bool SmartAI::IsAIControlled() const
@@ -594,13 +596,6 @@ void SmartAI::JustRespawned()
mFollowCreditType = 0;
}
-int SmartAI::Permissible(const Creature* creature)
-{
- if (creature->GetAIName() == "SmartAI")
- return PERMIT_BASE_SPECIAL;
- return PERMIT_BASE_NO;
-}
-
void SmartAI::JustReachedHome()
{
GetScript()->OnReset();
@@ -810,14 +805,16 @@ void SmartAI::SetEvadeDisabled(bool disable)
bool SmartAI::GossipHello(Player* player)
{
+ _gossipReturn = false;
GetScript()->ProcessEventsFor(SMART_EVENT_GOSSIP_HELLO, player);
- return false;
+ return _gossipReturn;
}
bool SmartAI::GossipSelect(Player* player, uint32 menuId, uint32 gossipListId)
{
+ _gossipReturn = false;
GetScript()->ProcessEventsFor(SMART_EVENT_GOSSIP_SELECT, player, menuId, gossipListId);
- return false;
+ return _gossipReturn;
}
bool SmartAI::GossipSelectCode(Player* /*player*/, uint32 /*menuId*/, uint32 /*gossipListId*/, const char* /*code*/)
@@ -962,13 +959,6 @@ void SmartAI::CheckConditions(uint32 diff)
mConditionsTimer -= diff;
}
-int SmartGameObjectAI::Permissible(const GameObject* g)
-{
- if (g->GetAIName() == "SmartGameObjectAI")
- return PERMIT_BASE_SPECIAL;
- return PERMIT_BASE_NO;
-}
-
void SmartGameObjectAI::UpdateAI(uint32 diff)
{
GetScript()->OnUpdate(diff);
@@ -995,16 +985,17 @@ void SmartGameObjectAI::Reset()
// Called when a player opens a gossip dialog with the gameobject.
bool SmartGameObjectAI::GossipHello(Player* player, bool reportUse)
{
- TC_LOG_DEBUG("scripts.ai", "SmartGameObjectAI::GossipHello");
+ _gossipReturn = false;
GetScript()->ProcessEventsFor(SMART_EVENT_GOSSIP_HELLO, player, uint32(reportUse), 0, false, nullptr, me);
- return false;
+ return _gossipReturn;
}
// Called when a player selects a gossip item in the gameobject's gossip menu.
bool SmartGameObjectAI::GossipSelect(Player* player, uint32 sender, uint32 action)
{
+ _gossipReturn = false;
GetScript()->ProcessEventsFor(SMART_EVENT_GOSSIP_SELECT, player, sender, action, false, nullptr, me);
- return false;
+ return _gossipReturn;
}
// Called when a player selects a gossip with a code in the gameobject's gossip menu.
diff --git a/src/server/game/AI/SmartScripts/SmartAI.h b/src/server/game/AI/SmartScripts/SmartAI.h
index 1c65c9633b9..070165efa40 100644
--- a/src/server/game/AI/SmartScripts/SmartAI.h
+++ b/src/server/game/AI/SmartScripts/SmartAI.h
@@ -158,7 +158,7 @@ class TC_GAME_API SmartAI : public CreatureAI
ObjectGuid GetGUID(int32 id = 0) const override;
//core related
- static int Permissible(const Creature*);
+ static int32 Permissible(Creature const* /*creature*/) { return PERMIT_BASE_NO; }
// Called at movepoint reached
void MovepointReached(uint32 id);
@@ -198,6 +198,8 @@ class TC_GAME_API SmartAI : public CreatureAI
void SetWPPauseTimer(uint32 time) { mWPPauseTimer = time; }
+ void SetGossipReturn(bool val) { _gossipReturn = val; }
+
private:
bool mIsCharmed;
uint32 mFollowCreditType;
@@ -241,19 +243,22 @@ class TC_GAME_API SmartAI : public CreatureAI
void CheckConditions(uint32 diff);
bool mHasConditions;
uint32 mConditionsTimer;
+
+ // Gossip
+ bool _gossipReturn;
};
class TC_GAME_API SmartGameObjectAI : public GameObjectAI
{
public:
- SmartGameObjectAI(GameObject* g) : GameObjectAI(g) { }
+ SmartGameObjectAI(GameObject* g) : GameObjectAI(g), _gossipReturn(false) { }
~SmartGameObjectAI() { }
void UpdateAI(uint32 diff) override;
void InitializeAI() override;
void Reset() override;
SmartScript* GetScript() { return &mScript; }
- static int Permissible(const GameObject* g);
+ static int32 Permissible(GameObject const* /*go*/) { return PERMIT_BASE_NO; }
bool GossipHello(Player* player, bool reportUse) override;
bool GossipSelect(Player* player, uint32 menuId, uint32 gossipListId) override;
@@ -268,8 +273,13 @@ class TC_GAME_API SmartGameObjectAI : public GameObjectAI
void EventInform(uint32 eventId) override;
void SpellHit(Unit* unit, const SpellInfo* spellInfo) override;
+ void SetGossipReturn(bool val) { _gossipReturn = val; }
+
private:
SmartScript mScript;
+
+ // Gossip
+ bool _gossipReturn;
};
/// Registers scripts required by the SAI scripting system
diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp
index ebf884133a4..a1c6d3af9b6 100644
--- a/src/server/game/AI/SmartScripts/SmartScript.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScript.cpp
@@ -2411,7 +2411,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
}
case SMART_ACTION_SEND_GOSSIP_MENU:
{
- if (!GetBaseObject())
+ if (!GetBaseObject() || !IsSmart())
break;
TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_SEND_GOSSIP_MENU: gossipMenuId %d, gossipNpcTextId %d",
@@ -2421,6 +2421,12 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
if (!targets)
break;
+ // override default gossip
+ if (me)
+ ENSURE_AI(SmartAI, me->AI())->SetGossipReturn(true);
+ else if (go)
+ ENSURE_AI(SmartGameObjectAI, go->AI())->SetGossipReturn(true);
+
for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
{
if (Player* player = (*itr)->ToPlayer())
diff --git a/src/server/game/Accounts/RBAC.h b/src/server/game/Accounts/RBAC.h
index 05931ce840e..68b3d673a15 100644
--- a/src/server/game/Accounts/RBAC.h
+++ b/src/server/game/Accounts/RBAC.h
@@ -562,17 +562,17 @@ enum RBACPermissions
RBAC_PERM_COMMAND_RELOAD_ITEM_LOOT_TEMPLATE = 654,
RBAC_PERM_COMMAND_RELOAD_ITEM_SET_NAMES = 655,
RBAC_PERM_COMMAND_RELOAD_LFG_DUNGEON_REWARDS = 656,
- RBAC_PERM_COMMAND_RELOAD_LOCALES_ACHIEVEMENT_REWARD = 657,
- RBAC_PERM_COMMAND_RELOAD_LOCALES_CRETURE = 658,
- RBAC_PERM_COMMAND_RELOAD_LOCALES_CRETURE_TEXT = 659,
- RBAC_PERM_COMMAND_RELOAD_LOCALES_GAMEOBJECT = 660,
- RBAC_PERM_COMMAND_RELOAD_LOCALES_GOSSIP_MENU_OPTION = 661,
- RBAC_PERM_COMMAND_RELOAD_LOCALES_ITEM = 662, // deprecated since Draenor DON'T reuse
- RBAC_PERM_COMMAND_RELOAD_LOCALES_ITEM_SET_NAME = 663,
- RBAC_PERM_COMMAND_RELOAD_LOCALES_NPC_TEXT = 664, // deprecated since Draenor DON'T reuse
- RBAC_PERM_COMMAND_RELOAD_LOCALES_PAGE_TEXT = 665,
- RBAC_PERM_COMMAND_RELOAD_LOCALES_POINTS_OF_INTEREST = 666,
- RBAC_PERM_COMMAND_RELOAD_QUEST_LOCALE = 667,
+ RBAC_PERM_COMMAND_RELOAD_ACHIEVEMENT_REWARD_LOCALE = 657,
+ RBAC_PERM_COMMAND_RELOAD_CRETURE_TEMPLATE_LOCALE = 658,
+ RBAC_PERM_COMMAND_RELOAD_CRETURE_TEXT_LOCALE = 659,
+ RBAC_PERM_COMMAND_RELOAD_GAMEOBJECT_TEMPLATE_LOCALE = 660,
+ RBAC_PERM_COMMAND_RELOAD_GOSSIP_MENU_OPTION_LOCALE = 661,
+ RBAC_PERM_COMMAND_RELOAD_ITEM_TEMPLATE_LOCALE = 662, // deprecated since Draenor DON'T reus
+ RBAC_PERM_COMMAND_RELOAD_ITEM_SET_NAME_LOCALE = 663,
+ RBAC_PERM_COMMAND_RELOAD_NPC_TEXT_LOCALE = 664, // deprecated since Draenor DON'T reuse
+ RBAC_PERM_COMMAND_RELOAD_PAGE_TEXT_LOCALE = 665,
+ RBAC_PERM_COMMAND_RELOAD_POINTS_OF_INTEREST_LOCALE = 666,
+ RBAC_PERM_COMMAND_RELOAD_QUEST_TEMPLATE_LOCALE = 667,
RBAC_PERM_COMMAND_RELOAD_MAIL_LEVEL_REWARD = 668,
RBAC_PERM_COMMAND_RELOAD_MAIL_LOOT_TEMPLATE = 669,
RBAC_PERM_COMMAND_RELOAD_MILLING_LOOT_TEMPLATE = 670,
@@ -760,6 +760,7 @@ enum RBACPermissions
RBAC_PERM_COMMAND_GO_OFFSET = 852,
RBAC_PERM_COMMAND_RELOAD_CONVERSATION_TEMPLATE = 853,
RBAC_PERM_COMMAND_DEBUG_CONVERSATION = 854,
+ RBAC_PERM_COMMAND_DEBUG_PLAY_MUSIC = 855,
RBAC_PERM_COMMAND_NPC_SPAWNGROUP = 856, // reserved for dynamic_spawning
RBAC_PERM_COMMAND_NPC_DESPAWNGROUP = 857, // reserved for dynamic_spawning
RBAC_PERM_COMMAND_GOBJECT_SPAWNGROUP = 858, // reserved for dynamic_spawning
diff --git a/src/server/game/Battlefield/Zones/BattlefieldWG.cpp b/src/server/game/Battlefield/Zones/BattlefieldWG.cpp
index 6e1bba5f1a9..62e37f5d76b 100644
--- a/src/server/game/Battlefield/Zones/BattlefieldWG.cpp
+++ b/src/server/game/Battlefield/Zones/BattlefieldWG.cpp
@@ -57,7 +57,7 @@ BfWGCoordGY const WGGraveYard[BATTLEFIELD_WG_GRAVEYARD_MAX] =
};
uint32 const ClockWorldState[] = { 3781, 4354 };
-uint32 const WintergraspFaction[] = { 1732, 1735, 35 };
+uint32 const WintergraspFaction[] = { FACTION_ALLIANCE_GENERIC_WG, FACTION_HORDE_GENERIC_WG, FACTION_FRIENDLY };
Position const WintergraspStalkerPos = { 4948.985f, 2937.789f, 550.5172f, 1.815142f };
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp
index edd6d3e67ed..31345c14048 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp
@@ -384,7 +384,7 @@ void BattlegroundAB::_NodeOccupied(uint8 node, Team team)
//aura should only apply to players who have accupied the node, set correct faction for trigger
if (trigger)
{
- trigger->SetFaction(team == ALLIANCE ? 84 : 83);
+ trigger->SetFaction(team == ALLIANCE ? FACTION_ALLIANCE_GENERIC : FACTION_HORDE_GENERIC);
trigger->CastSpell(trigger, SPELL_HONORABLE_DEFENDER_25Y, false);
}
}
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp
index 3fc2cd2ad8d..ff37ce06346 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp
@@ -757,7 +757,7 @@ void BattlegroundAV::PopulateNode(BG_AV_Nodes node)
DelCreature(node + 302);
return;
}
- trigger->SetFaction(owner == ALLIANCE ? 84 : 83);
+ trigger->SetFaction(owner == ALLIANCE ? FACTION_ALLIANCE_GENERIC : FACTION_HORDE_GENERIC);
trigger->CastSpell(trigger, SPELL_HONORABLE_DEFENDER_25Y, false);
}
}
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp
index c83e1ff48b1..8c4143e0ce3 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp
@@ -810,7 +810,7 @@ void BattlegroundEY::EventTeamCapturedPoint(Player* player, uint32 Point)
//aura should only apply to players who have accupied the node, set correct faction for trigger
if (trigger)
{
- trigger->SetFaction(Team == ALLIANCE ? 84 : 83);
+ trigger->SetFaction(Team == ALLIANCE ? FACTION_ALLIANCE_GENERIC : FACTION_HORDE_GENERIC);
trigger->CastSpell(trigger, SPELL_HONORABLE_DEFENDER_25Y, false);
}
}
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index 2d66f88a745..ba761b95ed0 100644
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -978,7 +978,7 @@ bool Creature::AIM_Create(CreatureAI* ai /*= nullptr*/)
Motion_Initialize();
- i_AI = ai ? ai : FactorySelector::selectAI(this);
+ i_AI = ai ? ai : FactorySelector::SelectAI(this);
return true;
}
@@ -2048,27 +2048,34 @@ void Creature::ForcedDespawn(uint32 timeMSToDespawn, Seconds const& forceRespawn
{
if (timeMSToDespawn)
{
- ForcedDespawnDelayEvent* pEvent = new ForcedDespawnDelayEvent(*this, forceRespawnTimer);
-
- m_Events.AddEvent(pEvent, m_Events.CalculateTime(timeMSToDespawn));
+ m_Events.AddEvent(new ForcedDespawnDelayEvent(*this, forceRespawnTimer), m_Events.CalculateTime(timeMSToDespawn));
return;
}
+ uint32 corpseDelay = GetCorpseDelay();
+ uint32 respawnDelay = GetRespawnDelay();
+
// do it before killing creature
DestroyForNearbyPlayers();
+ bool overrideRespawnTime = false;
if (IsAlive())
- setDeathState(JUST_DIED);
-
- bool overrideRespawnTime = true;
- if (forceRespawnTimer > Seconds::zero())
{
- SetRespawnTime(forceRespawnTimer.count());
- overrideRespawnTime = false;
+ if (forceRespawnTimer > Seconds::zero())
+ {
+ SetCorpseDelay(0);
+ SetRespawnDelay(forceRespawnTimer.count());
+ overrideRespawnTime = false;
+ }
+
+ setDeathState(JUST_DIED);
}
// Skip corpse decay time
RemoveCorpse(overrideRespawnTime, false);
+
+ SetCorpseDelay(corpseDelay);
+ SetRespawnDelay(respawnDelay);
}
void Creature::DespawnOrUnsummon(uint32 msTimeToDespawn /*= 0*/, Seconds const& forceRespawnTimer /*= 0*/)
@@ -2418,14 +2425,9 @@ bool Creature::_IsTargetAcceptable(Unit const* target) const
Unit const* targetVictim = target->getAttackerForHelper();
// if I'm already fighting target, or I'm hostile towards the target, the target is acceptable
- if (GetVictim() == target || IsHostileTo(target))
+ if (IsInCombatWith(target) || IsHostileTo(target))
return true;
- // a player is targeting me, but I'm not hostile towards it, and not currently attacking it, the target is not acceptable
- // (players may set their victim from a distance, and doesn't mean we should attack)
- if (target->GetTypeId() == TYPEID_PLAYER && targetVictim == this)
- return false;
-
// if the target's victim is friendly, and the target is neutral, the target is acceptable
if (targetVictim && IsFriendlyTo(targetVictim))
return true;
@@ -2808,7 +2810,7 @@ uint8 Creature::GetLevelForTarget(WorldObject const* target) const
return Unit::GetLevelForTarget(target);
}
-std::string Creature::GetAIName() const
+std::string const& Creature::GetAIName() const
{
return sObjectMgr->GetCreatureTemplate(GetEntry())->AIName;
}
@@ -2943,20 +2945,6 @@ float Creature::GetPetChaseDistance() const
return range;
}
-void Creature::SetPosition(float x, float y, float z, float o)
-{
- // prevent crash when a bad coord is sent by the client
- if (!Trinity::IsValidMapCoord(x, y, z, o))
- {
- TC_LOG_DEBUG("entities.unit", "Creature::SetPosition(%f, %f, %f) .. bad coordinates!", x, y, z);
- return;
- }
-
- GetMap()->CreatureRelocation(this, x, y, z, o);
- if (IsVehicle())
- GetVehicleKit()->RelocatePassengers();
-}
-
float Creature::GetAggroRange(Unit const* target) const
{
// Determines the aggro range for creatures (usually pets), used mainly for aggressive pet target selection.
@@ -3217,8 +3205,7 @@ bool Creature::IsMovementPreventedByCasting() const
{
if (spell->getState() != SPELL_STATE_FINISHED && spell->IsChannelActive())
if (spell->GetSpellInfo()->IsMoveAllowedChannel())
- if (HasUnitState(UNIT_STATE_CASTING))
- return true;
+ return false;
}
if (const_cast<Creature*>(this)->IsFocusing(nullptr, true))
diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h
index cc5608bfc3d..beb9ed4d64f 100644
--- a/src/server/game/Entities/Creature/Creature.h
+++ b/src/server/game/Entities/Creature/Creature.h
@@ -172,7 +172,7 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma
CreatureData const* GetCreatureData() const { return m_creatureData; }
CreatureAddon const* GetCreatureAddon() const;
- std::string GetAIName() const;
+ std::string const& GetAIName() const;
std::string GetScriptName() const;
uint32 GetScriptId() const;
@@ -282,9 +282,6 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma
void SetCannotReachTarget(bool cannotReach) { if (cannotReach == m_cannotReachTarget) return; m_cannotReachTarget = cannotReach; m_cannotReachTimer = 0; }
bool CanNotReachTarget() const { return m_cannotReachTarget; }
- void SetPosition(float x, float y, float z, float o);
- void SetPosition(const Position &pos) { SetPosition(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation()); }
-
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); }
diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp
index 4059e6e72d6..cd3ebd306ea 100644
--- a/src/server/game/Entities/GameObject/GameObject.cpp
+++ b/src/server/game/Entities/GameObject/GameObject.cpp
@@ -166,12 +166,9 @@ bool GameObject::AIM_Initialize()
return true;
}
-std::string GameObject::GetAIName() const
+std::string const& GameObject::GetAIName() const
{
- if (GameObjectTemplate const* got = sObjectMgr->GetGameObjectTemplate(GetEntry()))
- return got->AIName;
-
- return "";
+ return sObjectMgr->GetGameObjectTemplate(GetEntry())->AIName;
}
void GameObject::CleanupsBeforeDelete(bool finalCleanup)
@@ -2121,7 +2118,7 @@ void GameObject::CastSpell(Unit* target, uint32 spellId, TriggerCastFlags trigge
}
else
{
- trigger->SetFaction(spellInfo->IsPositive() ? 35 : 14);
+ trigger->SetFaction(spellInfo->IsPositive() ? FACTION_FRIENDLY : FACTION_MONSTER);
// Set owner guid for target if no owner available - needed by trigger auras
// - trigger gets despawned and there's no caster avalible (see AuraEffect::TriggerSpell())
trigger->CastSpell(target ? target : trigger, spellInfo, triggered, nullptr, nullptr, target ? target->GetGUID() : ObjectGuid::Empty);
diff --git a/src/server/game/Entities/GameObject/GameObject.h b/src/server/game/Entities/GameObject/GameObject.h
index da06d1842f8..7bbf09a26ad 100644
--- a/src/server/game/Entities/GameObject/GameObject.h
+++ b/src/server/game/Entities/GameObject/GameObject.h
@@ -283,7 +283,7 @@ class TC_GAME_API GameObject : public WorldObject, public GridObject<GameObject>
uint32 GetScriptId() const;
GameObjectAI* AI() const { return m_AI; }
- std::string GetAIName() const;
+ std::string const& GetAIName() const;
void SetDisplayId(uint32 displayid);
uint32 GetDisplayId() const { return m_gameObjectData->DisplayID; }
uint8 GetNameSetId() const;
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 32f2be86bd9..939d7e750d1 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -2105,8 +2105,8 @@ Creature* Player::GetNPCIfCanInteractWith(ObjectGuid const& guid, NPCFlags npcFl
if (creature->GetReactionTo(this) <= REP_UNFRIENDLY)
return nullptr;
- // not too far
- if (!creature->IsWithinDistInMap(this, INTERACTION_DISTANCE))
+ // not too far, taken from CGGameUI::SetInteractTarget
+ if (!creature->IsWithinDistInMap(this, creature->GetCombatReach() + 4.0f))
return nullptr;
return creature;
@@ -2114,33 +2114,36 @@ Creature* Player::GetNPCIfCanInteractWith(ObjectGuid const& guid, NPCFlags npcFl
GameObject* Player::GetGameObjectIfCanInteractWith(ObjectGuid const& guid) const
{
- if (GameObject* go = GetMap()->GetGameObject(guid))
- {
- if (go->IsWithinDistInMap(this, go->GetInteractionDistance()))
- return go;
+ if (!guid)
+ return nullptr;
- TC_LOG_DEBUG("maps", "Player::GetGameObjectIfCanInteractWith: GameObject '%s' (%s) is too far away from player '%s' (%s) to be used by him (Distance: %f, maximal %f is allowed)",
- go->GetGOInfo()->name.c_str(), go->GetGUID().ToString().c_str(), GetName().c_str(), GetGUID().ToString().c_str(), go->GetDistance(this), go->GetInteractionDistance());
- }
+ if (!IsInWorld())
+ return nullptr;
- return nullptr;
+ if (IsInFlight())
+ return nullptr;
+
+ // exist
+ GameObject* go = ObjectAccessor::GetGameObject(*this, guid);
+ if (!go)
+ return nullptr;
+
+ if (!go->IsWithinDistInMap(this, go->GetInteractionDistance()))
+ return nullptr;
+
+ return go;
}
GameObject* Player::GetGameObjectIfCanInteractWith(ObjectGuid const& guid, GameobjectTypes type) const
{
- if (GameObject* go = GetMap()->GetGameObject(guid))
- {
- if (go->GetGoType() == type)
- {
- if (go->IsWithinDistInMap(this, go->GetInteractionDistance()))
- return go;
+ GameObject* go = GetGameObjectIfCanInteractWith(guid);
+ if (!go)
+ return nullptr;
- TC_LOG_DEBUG("maps", "Player::GetGameObjectIfCanInteractWith: GameObject '%s' (%s) is too far away from player '%s' (%s) to be used by him (Distance: %f, maximal %f is allowed)",
- go->GetGOInfo()->name.c_str(), go->GetGUID().ToString().c_str(), GetName().c_str(), GetGUID().ToString().c_str(), go->GetDistance(this), go->GetInteractionDistance());
- }
- }
+ if (go->GetGoType() != type)
+ return nullptr;
- return nullptr;
+ return go;
}
bool Player::IsUnderWater() const
@@ -2201,13 +2204,13 @@ void Player::SetGameMaster(bool on)
if (on)
{
m_ExtraFlags |= PLAYER_EXTRA_GM_ON;
- SetFaction(35);
+ SetFaction(FACTION_FRIENDLY);
AddPlayerFlag(PLAYER_FLAGS_GM);
AddUnitFlag2(UNIT_FLAG2_ALLOW_CHEAT_SPELLS);
if (Pet* pet = GetPet())
{
- pet->SetFaction(35);
+ pet->SetFaction(FACTION_FRIENDLY);
pet->getHostileRefManager().setOnlineOfflineState(false);
}
@@ -16604,7 +16607,6 @@ QuestGiverStatus Player::GetQuestDialogStatus(Object* questgiver)
QuestRelationBounds qr;
QuestRelationBounds qir;
- PlayerTalkClass->ClearMenus();
switch (questgiver->GetTypeId())
{
case TYPEID_GAMEOBJECT:
@@ -16832,9 +16834,7 @@ void Player::AreaExploredOrEventHappens(uint32 questId)
q_status.Explored = true;
m_QuestStatusSave[questId] = QUEST_DEFAULT_SAVE_TYPE;
- // if we cannot complete quest send exploration succeded (to mark exploration on client)
- if (!CanCompleteQuest(questId))
- SendQuestComplete(questId);
+ SendQuestComplete(questId);
}**/
}
if (CanCompleteQuest(questId))
@@ -25390,18 +25390,24 @@ void Player::ResurrectUsingRequestData()
void Player::ResurrectUsingRequestDataImpl()
{
+ // save health and mana before resurrecting, _resurrectionData can be erased
+ uint32 resurrectHealth = _resurrectionData->Health;
+ uint32 resurrectMana = _resurrectionData->Mana;
+ uint32 resurrectAura = _resurrectionData->Aura;
+ ObjectGuid resurrectGUID = _resurrectionData->GUID;
+
ResurrectPlayer(0.0f, false);
- SetHealth(_resurrectionData->Health);
- SetPower(POWER_MANA, _resurrectionData->Mana);
+ SetHealth(resurrectHealth);
+ SetPower(POWER_MANA, resurrectMana);
SetPower(POWER_RAGE, 0);
SetFullPower(POWER_ENERGY);
SetFullPower(POWER_FOCUS);
SetPower(POWER_LUNAR_POWER, 0);
- if (uint32 aura = _resurrectionData->Aura)
- CastSpell(this, aura, true, nullptr, nullptr, _resurrectionData->GUID);
+ if (uint32 aura = resurrectAura)
+ CastSpell(this, aura, true, nullptr, nullptr, resurrectGUID);
SpawnCorpseBones();
}
diff --git a/src/server/game/Entities/Transport/Transport.cpp b/src/server/game/Entities/Transport/Transport.cpp
index c4c7d2a971d..c261fdef73b 100644
--- a/src/server/game/Entities/Transport/Transport.cpp
+++ b/src/server/game/Entities/Transport/Transport.cpp
@@ -154,8 +154,8 @@ void Transport::Update(uint32 diff)
if (timer < _currentFrame->DepartureTime)
{
+ justStopped = IsMoving();
SetMoving(false);
- justStopped = true;
if (_pendingStop && GetGoState() != GO_STATE_READY)
{
SetGoState(GO_STATE_READY);
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 29f2d6433ce..6d5b164f594 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -3391,7 +3391,14 @@ void Unit::_ApplyAura(AuraApplication * aurApp, uint32 effMask)
// Update target aura state flag
if (AuraStateType aState = aura->GetSpellInfo()->GetAuraState())
- ModifyAuraState(aState, true);
+ {
+ uint32 aStateMask = (1 << (aState - 1));
+ // force update so the new caster registers it
+ if ((aStateMask & PER_CASTER_AURA_STATE_MASK) && *m_unitData->AuraState & aStateMask)
+ ForceUpdateFieldChange(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::AuraState));
+ else
+ ModifyAuraState(aState, true);
+ }
if (aurApp->GetRemoveMode())
return;
@@ -3484,9 +3491,19 @@ void Unit::_UnapplyAura(AuraApplicationMap::iterator &i, AuraRemoveMode removeMo
ToTotem()->setDeathState(JUST_DIED);
}
- // Remove aurastates only if were not found
- if (!auraStateFound)
- ModifyAuraState(auraState, false);
+ // Remove aurastates only if needed and were not found
+ if (auraState)
+ {
+ if (!auraStateFound)
+ ModifyAuraState(auraState, false);
+ else
+ {
+ // update for casters, some shouldn't 'see' the aura state
+ uint32 aStateMask = (1 << (auraState - 1));
+ if ((aStateMask & PER_CASTER_AURA_STATE_MASK) != 0)
+ ForceUpdateFieldChange(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::AuraState));
+ }
+ }
aura->HandleAuraSpecificMods(aurApp, caster, false, false);
@@ -5618,13 +5635,22 @@ void Unit::_removeAttacker(Unit* pAttacker)
Unit* Unit::getAttackerForHelper() const // If someone wants to help, who to give them
{
- if (GetVictim() != NULL)
- return GetVictim();
+ if (Unit* victim = GetVictim())
+ if (!IsControlledByPlayer() || IsInCombatWith(victim) || victim->IsInCombatWith(this))
+ return victim;
if (!m_attackers.empty())
return *(m_attackers.begin());
- return NULL;
+ if (Player* owner = GetCharmerOrOwnerPlayerOrPlayerItself())
+ {
+ HostileRefManager& refs = owner->getHostileRefManager();
+ for (Reference<Unit, ThreatManager> const& ref : refs)
+ if (Unit* hostile = ref.GetSource()->GetOwner())
+ return hostile;
+ }
+
+ return nullptr;
}
bool Unit::Attack(Unit* victim, bool meleeAttack)
@@ -5640,6 +5666,11 @@ bool Unit::Attack(Unit* victim, bool meleeAttack)
if (GetTypeId() == TYPEID_PLAYER && IsMounted())
return false;
+ Creature* creature = ToCreature();
+ // creatures cannot attack while evading
+ if (creature && creature->IsInEvadeMode())
+ return false;
+
if (HasUnitFlag(UNIT_FLAG_PACIFIED))
return false;
@@ -5704,7 +5735,7 @@ bool Unit::Attack(Unit* victim, bool meleeAttack)
//if (GetTypeId() == TYPEID_UNIT)
// ToCreature()->SetCombatStartPosition(GetPositionX(), GetPositionY(), GetPositionZ());
- if (GetTypeId() == TYPEID_UNIT && !IsPet())
+ if (creature && !IsPet())
{
// should not let player enter combat by right clicking target - doesn't helps
AddThreat(victim, 0.0f);
@@ -5712,8 +5743,8 @@ bool Unit::Attack(Unit* victim, bool meleeAttack)
if (victim->GetTypeId() == TYPEID_PLAYER)
victim->SetInCombatWith(this);
- ToCreature()->SendAIReaction(AI_REACTION_HOSTILE);
- ToCreature()->CallAssistance();
+ creature->SendAIReaction(AI_REACTION_HOSTILE);
+ creature->CallAssistance();
// Remove emote state - will be restored on creature reset
SetEmoteState(EMOTE_ONESHOT_NONE);
@@ -5728,7 +5759,7 @@ bool Unit::Attack(Unit* victim, bool meleeAttack)
// Let the pet know we've started attacking someting. Handles melee attacks only
// Spells such as auto-shot and others handled in WorldSession::HandleCastSpellOpcode
- if (this->GetTypeId() == TYPEID_PLAYER)
+ if (GetTypeId() == TYPEID_PLAYER)
{
Pet* playerPet = this->ToPlayer()->GetPet();
@@ -8726,8 +8757,6 @@ void Unit::setDeathState(DeathState s)
if (s == JUST_DIED)
{
- ModifyAuraState(AURA_STATE_HEALTHLESS_20_PERCENT, false);
- ModifyAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, false);
// remove aurastates allowing special moves
ClearAllReactives();
ClearDiminishings();
@@ -10616,13 +10645,13 @@ Player* Unit::GetSpellModOwner() const
if (Player* player = const_cast<Unit*>(this)->ToPlayer())
return player;
- if (IsPet() || IsTotem())
+ if (HasUnitTypeMask(UNIT_MASK_PET | UNIT_MASK_TOTEM | UNIT_MASK_GUARDIAN))
{
if (Unit* owner = GetOwner())
if (Player* player = owner->ToPlayer())
return player;
}
- return NULL;
+ return nullptr;
}
///----------Pet responses methods-----------------
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index e38539429ae..c616ee11270 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -21,10 +21,12 @@
#include "AzeriteItem.h"
#include "Chat.h"
#include "Containers.h"
+#include "CreatureAIFactory.h"
#include "DatabaseEnv.h"
#include "DB2Stores.h"
#include "DisableMgr.h"
#include "GameObject.h"
+#include "GameObjectAIFactory.h"
#include "GameTables.h"
#include "GridDefines.h"
#include "GossipDef.h"
@@ -935,6 +937,12 @@ void ObjectMgr::CheckCreatureTemplate(CreatureTemplate const* cInfo)
ok = true;
}
+ if (!cInfo->AIName.empty() && !sCreatureAIRegistry->HasItem(cInfo->AIName))
+ {
+ TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) has non-registered `AIName` '%s' set, removing", cInfo->Entry, cInfo->AIName.c_str());
+ const_cast<CreatureTemplate*>(cInfo)->AIName.clear();
+ }
+
FactionTemplateEntry const* factionTemplate = sFactionTemplateStore.LookupEntry(cInfo->faction);
if (!factionTemplate)
{
@@ -2048,6 +2056,12 @@ void ObjectMgr::LoadCreatures()
TC_LOG_ERROR("sql.sql", "Table `creature` has creature (GUID: " UI64FMTD " Entry: %u) with `creature_template`.`flags_extra` including CREATURE_FLAG_EXTRA_INSTANCE_BIND but creature is not in instance.", guid, data.id);
}
+ if (data.movementType >= MAX_DB_MOTION_TYPE)
+ {
+ TC_LOG_ERROR("sql.sql", "Table `creature` has creature (GUID: " UI64FMTD " Entry: %u) with wrong movement generator type (%u), ignored and set to IDLE.", guid, data.id, data.movementType);
+ data.movementType = IDLE_MOTION_TYPE;
+ }
+
if (data.spawndist < 0.0f)
{
TC_LOG_ERROR("sql.sql", "Table `creature` has creature (GUID: " UI64FMTD " Entry: %u) with `spawndist`< 0, set to 0.", guid, data.id);
@@ -7061,6 +7075,11 @@ void ObjectMgr::LoadGameObjectTemplate()
got.ScriptId = GetScriptId(fields[44].GetString());
// Checks
+ if (!got.AIName.empty() && !sGameObjectAIRegistry->HasItem(got.AIName))
+ {
+ TC_LOG_ERROR("sql.sql", "GameObject (Entry: %u) has non-registered `AIName` '%s' set, removing", got.entry, got.AIName.c_str());
+ got.AIName.clear();
+ }
switch (got.type)
{
diff --git a/src/server/game/Groups/GroupMgr.cpp b/src/server/game/Groups/GroupMgr.cpp
index 314c74c1766..53d8fb5a877 100644
--- a/src/server/game/Groups/GroupMgr.cpp
+++ b/src/server/game/Groups/GroupMgr.cpp
@@ -203,10 +203,13 @@ void GroupMgr::LoadGroups()
TC_LOG_INFO("server.loading", "Loading Group instance saves...");
{
uint32 oldMSTime = getMSTime();
- // 0 1 2 3 4 5 6 7
- QueryResult result = CharacterDatabase.Query("SELECT gi.guid, i.map, gi.instance, gi.permanent, i.difficulty, i.resettime, i.entranceId, COUNT(g.guid) "
- "FROM group_instance gi INNER JOIN instance i ON gi.instance = i.id "
- "LEFT JOIN character_instance ci LEFT JOIN `groups` g ON g.leaderGuid = ci.guid ON ci.instance = gi.instance AND ci.permanent = 1 GROUP BY gi.instance ORDER BY gi.guid");
+
+ // 0 1 2 3 4 5 6
+ QueryResult result = CharacterDatabase.Query("SELECT gi.guid, i.map, gi.instance, gi.permanent, i.difficulty, i.resettime, i.entranceId, "
+ // 7
+ "(SELECT COUNT(1) FROM character_instance ci LEFT JOIN groups g ON ci.guid = g.leaderGuid WHERE ci.instance = gi.instance AND ci.permanent = 1 LIMIT 1) "
+ "FROM group_instance gi LEFT JOIN instance i ON gi.instance = i.id ORDER BY guid");
+
if (!result)
{
TC_LOG_INFO("server.loading", ">> Loaded 0 group-instance saves. DB table `group_instance` is empty!");
@@ -232,7 +235,7 @@ void GroupMgr::LoadGroups()
if (!difficultyEntry || difficultyEntry->InstanceType != mapEntry->InstanceType)
continue;
- InstanceSave* save = sInstanceSaveMgr->AddInstanceSave(mapEntry->ID, fields[2].GetUInt32(), Difficulty(diff), time_t(fields[5].GetUInt32()), fields[6].GetUInt32(), fields[7].GetUInt64() != 0, true);
+ InstanceSave* save = sInstanceSaveMgr->AddInstanceSave(mapEntry->ID, fields[2].GetUInt32(), Difficulty(diff), time_t(fields[5].GetUInt32()), fields[6].GetUInt32(), fields[7].GetUInt64() == 0, true);
group->BindToInstance(save, fields[3].GetBool(), true);
++count;
}
diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h
index 2e7d7e81ddb..03b0f954ccd 100644
--- a/src/server/game/Miscellaneous/SharedDefines.h
+++ b/src/server/game/Miscellaneous/SharedDefines.h
@@ -189,6 +189,51 @@ enum ReputationRank
REP_EXALTED = 7
};
+enum FactionTemplates
+{
+ FACTION_NONE = 0,
+ FACTION_CREATURE = 7,
+ FACTION_ESCORTEE_A_NEUTRAL_PASSIVE = 10,
+ FACTION_MONSTER = 14,
+ FACTION_MONSTER_2 = 16,
+ FACTION_TROLL_BLOODSCALP = 28,
+ FACTION_PREY = 31,
+ FACTION_ESCORTEE_H_NEUTRAL_PASSIVE = 33,
+ FACTION_FRIENDLY = 35,
+ FACTION_OGRE = 45,
+ FACTION_ORC_DRAGONMAW = 62,
+ FACTION_HORDE_GENERIC = 83,
+ FACTION_ALLIANCE_GENERIC = 84,
+ FACTION_DEMON = 90,
+ FACTION_ELEMENTAL = 91,
+ FACTION_DRAGONFLIGHT_BLACK = 103,
+ FACTION_ESCORTEE_N_NEUTRAL_PASSIVE = 113,
+ FACTION_ENEMY = 168,
+ FACTION_ESCORTEE_A_NEUTRAL_ACTIVE = 231,
+ FACTION_ESCORTEE_H_NEUTRAL_ACTIVE = 232,
+ FACTION_ESCORTEE_N_NEUTRAL_ACTIVE = 250,
+ FACTION_ESCORTEE_N_FRIEND_PASSIVE = 290,
+ FACTION_TITAN = 415,
+ FACTION_ESCORTEE_N_FRIEND_ACTIVE = 495,
+ FACTION_GOBLIN_DARK_IRON_BAR_PATRON = 736,
+ FACTION_DARK_IRON_DWARVES = 754,
+ FACTION_ESCORTEE_A_PASSIVE = 774,
+ FACTION_ESCORTEE_H_PASSIVE = 775,
+ FACTION_UNDEAD_SCOURGE = 974,
+ FACTION_EARTHEN_RING = 1726,
+ FACTION_ALLIANCE_GENERIC_WG = 1732,
+ FACTION_HORDE_GENERIC_WG = 1735,
+ FACTION_ARAKKOA = 1738,
+ FACTION_ASHTONGUE_DEATHSWORN = 1820,
+ FACTION_FLAYER_HUNTER = 1840,
+ FACTION_MONSTER_SPAR_BUDDY = 1868,
+ FACTION_ESCORTEE_N_ACTIVE = 1986,
+ FACTION_ESCORTEE_H_ACTIVE = 2046,
+ FACTION_UNDEAD_SCOURGE_2 = 2068,
+ FACTION_UNDEAD_SCOURGE_3 = 2084,
+ FACTION_SCARLET_CRUSADE = 2089
+};
+
#define MIN_REPUTATION_RANK (REP_HATED)
#define MAX_REPUTATION_RANK 8
diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp
index 3b446733bbb..295c70039e6 100644
--- a/src/server/game/Movement/MotionMaster.cpp
+++ b/src/server/game/Movement/MotionMaster.cpp
@@ -35,9 +35,14 @@
#include "MoveSplineInit.h"
#include "PathGenerator.h"
+inline MovementGenerator* GetIdleMovementGenerator()
+{
+ return sMovementGeneratorRegistry->GetRegistryItem(IDLE_MOTION_TYPE)->Create();
+}
+
inline bool IsStatic(MovementGenerator* movement)
{
- return (movement == &si_idleMovement);
+ return (movement == GetIdleMovementGenerator());
}
MotionMaster::~MotionMaster()
@@ -75,15 +80,7 @@ void MotionMaster::Initialize()
// set new default movement generator
void MotionMaster::InitDefault()
{
- if (_owner->GetTypeId() == TYPEID_UNIT)
- {
- MovementGenerator* movement = FactorySelector::selectMovementGenerator(_owner->ToCreature());
- Mutate(movement == nullptr ? &si_idleMovement : movement, MOTION_SLOT_IDLE);
- }
- else
- {
- Mutate(&si_idleMovement, MOTION_SLOT_IDLE);
- }
+ Mutate(FactorySelector::SelectMovementGenerator(_owner), MOTION_SLOT_IDLE);
}
void MotionMaster::UpdateMotion(uint32 diff)
@@ -198,7 +195,7 @@ void MotionMaster::MoveIdle()
{
//! Should be preceded by MovementExpired or Clear if there's an overlying movementgenerator active
if (empty() || !IsStatic(top()))
- Mutate(&si_idleMovement, MOTION_SLOT_IDLE);
+ Mutate(GetIdleMovementGenerator(), MOTION_SLOT_IDLE);
}
void MotionMaster::MoveTargetedHome()
diff --git a/src/server/game/Movement/MovementGenerator.cpp b/src/server/game/Movement/MovementGenerator.cpp
index 5ce585b483d..661267401d2 100644
--- a/src/server/game/Movement/MovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerator.cpp
@@ -16,5 +16,12 @@
*/
#include "MovementGenerator.h"
+#include "IdleMovementGenerator.h"
MovementGenerator::~MovementGenerator() { }
+
+MovementGenerator* IdleMovementFactory::Create(Unit* /*object*/) const
+{
+ static IdleMovementGenerator instance;
+ return &instance;
+}
diff --git a/src/server/game/Movement/MovementGenerator.h b/src/server/game/Movement/MovementGenerator.h
index fdf5506dd15..4af0709aa06 100755
--- a/src/server/game/Movement/MovementGenerator.h
+++ b/src/server/game/Movement/MovementGenerator.h
@@ -69,20 +69,28 @@ class MovementGeneratorMedium : public MovementGenerator
}
};
-struct SelectableMovement : public FactoryHolder<MovementGenerator, MovementGeneratorType>
+typedef FactoryHolder<MovementGenerator, Unit, MovementGeneratorType> MovementGeneratorCreator;
+
+template<class Movement>
+struct MovementGeneratorFactory : public MovementGeneratorCreator
{
- SelectableMovement(MovementGeneratorType movementGeneratorType) : FactoryHolder<MovementGenerator, MovementGeneratorType>(movementGeneratorType) { }
+ MovementGeneratorFactory(MovementGeneratorType movementGeneratorType) : MovementGeneratorCreator(movementGeneratorType) { }
+
+ MovementGenerator* Create(Unit* /*object*/) const override
+ {
+ return new Movement();
+ }
};
-template<class Movement>
-struct MovementGeneratorFactory : public SelectableMovement
+struct IdleMovementFactory : public MovementGeneratorCreator
{
- MovementGeneratorFactory(MovementGeneratorType movementGeneratorType) : SelectableMovement(movementGeneratorType) { }
+ IdleMovementFactory() : MovementGeneratorCreator(IDLE_MOTION_TYPE) { }
- MovementGenerator* Create(void *) const override;
+ MovementGenerator* Create(Unit* object) const override;
};
-typedef FactoryHolder<MovementGenerator, MovementGeneratorType> MovementGeneratorCreator;
-typedef FactoryHolder<MovementGenerator, MovementGeneratorType>::FactoryHolderRegistry MovementGeneratorRegistry;
+typedef MovementGeneratorCreator::FactoryHolderRegistry MovementGeneratorRegistry;
+
+#define sMovementGeneratorRegistry MovementGeneratorRegistry::instance()
#endif
diff --git a/src/server/game/Movement/MovementGeneratorImpl.h b/src/server/game/Movement/MovementGeneratorImpl.h
deleted file mode 100644
index 0b5474b22b3..00000000000
--- a/src/server/game/Movement/MovementGeneratorImpl.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef TRINITY_MOVEMENTGENERATOR_IMPL_H
-#define TRINITY_MOVEMENTGENERATOR_IMPL_H
-
-#include "MovementGenerator.h"
-
-template<class Movement>
-inline MovementGenerator* MovementGeneratorFactory<Movement>::Create(void * /*data*/) const
-{
- return (new Movement());
-}
-
-#endif
diff --git a/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.cpp
index 76b1aca3cc2..43638197578 100644
--- a/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.cpp
@@ -20,8 +20,6 @@
#include "Creature.h"
#include <G3D/g3dmath.h>
-IdleMovementGenerator si_idleMovement;
-
// StopMoving is needed to make unit stop if its last movement generator expires
// But it should not be sent otherwise there are many redundent packets
void IdleMovementGenerator::Initialize(Unit* owner)
diff --git a/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.h b/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.h
index 9bb58419433..773d4dc03b7 100755
--- a/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.h
+++ b/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.h
@@ -31,8 +31,6 @@ class IdleMovementGenerator : public MovementGenerator
MovementGeneratorType GetMovementGeneratorType() const override { return IDLE_MOTION_TYPE; }
};
-TC_GAME_API extern IdleMovementGenerator si_idleMovement;
-
class RotateMovementGenerator : public MovementGenerator
{
public:
diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp
index b912f51cf9d..72354f47b21 100644
--- a/src/server/game/Scripting/ScriptMgr.cpp
+++ b/src/server/game/Scripting/ScriptMgr.cpp
@@ -1607,7 +1607,10 @@ bool ScriptMgr::CanSpawn(ObjectGuid::LowType spawnId, uint32 entry, CreatureTemp
CreatureTemplate const* baseTemplate = sObjectMgr->GetCreatureTemplate(entry);
if (!baseTemplate)
baseTemplate = actTemplate;
- GET_SCRIPT_RET(CreatureScript, (cData ? cData->ScriptId : baseTemplate->ScriptID), tmpscript, true);
+ uint32 scriptId = baseTemplate->ScriptID;
+ if (cData && cData->ScriptId)
+ scriptId = cData->ScriptId;
+ GET_SCRIPT_RET(CreatureScript, scriptId, tmpscript, true);
return tmpscript->CanSpawn(spawnId, entry, baseTemplate, actTemplate, cData, map);
}
diff --git a/src/server/game/Scripting/ScriptSystem.h b/src/server/game/Scripting/ScriptSystem.h
index 9f5a0ef78ce..f058bf886ee 100644
--- a/src/server/game/Scripting/ScriptSystem.h
+++ b/src/server/game/Scripting/ScriptSystem.h
@@ -28,30 +28,6 @@ struct SplineChainLink;
#define TEXT_SOURCE_RANGE -1000000 //the amount of entries each text source has available
-/// @todo find better namings and definitions.
-//N=Neutral, A=Alliance, H=Horde.
-//NEUTRAL or FRIEND = Hostility to player surroundings (not a good definition)
-//ACTIVE or PASSIVE = Hostility to environment surroundings.
-enum eEscortFaction
-{
- FACTION_ESCORT_A_NEUTRAL_PASSIVE = 10,
- FACTION_ESCORT_H_NEUTRAL_PASSIVE = 33,
- FACTION_ESCORT_N_NEUTRAL_PASSIVE = 113,
-
- FACTION_ESCORT_A_NEUTRAL_ACTIVE = 231,
- FACTION_ESCORT_H_NEUTRAL_ACTIVE = 232,
- FACTION_ESCORT_N_NEUTRAL_ACTIVE = 250,
-
- FACTION_ESCORT_N_FRIEND_PASSIVE = 290,
- FACTION_ESCORT_N_FRIEND_ACTIVE = 495,
-
- FACTION_ESCORT_A_PASSIVE = 774,
- FACTION_ESCORT_H_PASSIVE = 775,
-
- FACTION_ESCORT_N_ACTIVE = 1986,
- FACTION_ESCORT_H_ACTIVE = 2046
-};
-
struct ScriptPointMove
{
uint32 uiCreatureEntry;
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index aef183d8b97..2db4d4f8b3c 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -5896,18 +5896,6 @@ void AuraEffect::HandlePeriodicHealAurasTick(Unit* target, Unit* caster) const
}
else
{
- // Wild Growth = amount + (6 - 2*doneTicks) * ticks* amount / 100
- if (m_spellInfo->SpellFamilyName == SPELLFAMILY_DRUID && m_spellInfo->SpellFamilyFlags & flag128(0, 0x04000000, 0, 0))
- {
- int32 addition = int32(float(damage * GetTotalTicks()) * ((6-float(2*(GetTickNumber()-1)))/100));
-
- // Item - Druid T10 Restoration 2P Bonus
- if (AuraEffect* aurEff = caster->GetAuraEffect(70658, 0))
- // divided by 50 instead of 100 because calculated as for every 2 tick
- addition += abs(int32((addition * aurEff->GetAmount()) / 50));
-
- damage += addition;
- }
if (isAreaAura)
damage = caster->SpellHealingBonusDone(target, GetSpellInfo(), damage, DOT, GetSpellEffectInfo(), GetBase()->GetStackAmount()) * caster->SpellHealingPctDone(target, m_spellInfo);
damage = target->SpellHealingBonusTaken(caster, GetSpellInfo(), damage, DOT, GetSpellEffectInfo(), GetBase()->GetStackAmount());
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index f9c6b64e7f3..ca79aa1ac0e 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -778,6 +778,14 @@ void Spell::SelectSpellTargets()
if (m_spellInfo->IsChanneled())
{
+ // maybe do this for all spells?
+ if (m_UniqueTargetInfo.empty() && m_UniqueGOTargetInfo.empty() && m_UniqueItemInfo.empty() && !m_targets.HasDst())
+ {
+ SendCastResult(SPELL_FAILED_BAD_IMPLICIT_TARGETS);
+ finish(false);
+ return;
+ }
+
uint32 mask = (1 << effect->EffectIndex);
for (std::vector<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
{
@@ -1241,10 +1249,6 @@ void Spell::SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTarge
return;
float radius = effect->CalcRadius(m_caster) * m_spellValue->RadiusMod;
- // if this is a proximity based aoe (Frost Nova, Psychic Scream, ...), include the caster's own combat reach
- if (targetType.IsProximityBasedAoe())
- radius += GetCaster()->GetCombatReach();
-
SearchAreaTargets(targets, radius, center, referer, targetType.GetObjectType(), targetType.GetCheckType(), effect->ImplicitTargetConditions);
CallScriptObjectAreaTargetSelectHandlers(targets, effIndex, targetType);
@@ -2342,7 +2346,8 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
{
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
{
- if (!(target->effectMask & (1 << i)))
+ // in case of immunity, check all effects to choose correct procFlags, as none has technically hit
+ if (target->effectMask && !(target->effectMask & (1 << i)))
continue;
if (!m_spellInfo->IsPositiveEffect(i))
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index a9fa7bfee03..b02c080fe9b 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -879,15 +879,12 @@ void Spell::EffectJump(SpellEffIndex /*effIndex*/)
if (!unitTarget)
return;
- float x, y, z;
- unitTarget->GetContactPoint(m_caster, x, y, z, CONTACT_DISTANCE);
-
float speedXY, speedZ;
- CalculateJumpSpeeds(effectInfo, m_caster->GetExactDist2d(x, y), speedXY, speedZ);
+ CalculateJumpSpeeds(effectInfo, m_caster->GetExactDist2d(unitTarget), speedXY, speedZ);
JumpArrivalCastArgs arrivalCast;
arrivalCast.SpellId = effectInfo->TriggerSpell;
arrivalCast.Target = unitTarget->GetGUID();
- m_caster->GetMotionMaster()->MoveJump(x, y, z, 0.0f, speedXY, speedZ, EVENT_JUMP, false, &arrivalCast);
+ m_caster->GetMotionMaster()->MoveJump(*unitTarget, speedXY, speedZ, EVENT_JUMP, false, &arrivalCast);
}
void Spell::EffectJumpDest(SpellEffIndex /*effIndex*/)
@@ -2725,13 +2722,9 @@ void Spell::EffectTaunt(SpellEffIndex /*effIndex*/)
if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
return;
- if (!unitTarget)
- return;
-
// this effect use before aura Taunt apply for prevent taunt already attacking target
// for spell as marked "non effective at already attacking target"
- if (!unitTarget || !unitTarget->CanHaveThreatList()
- || unitTarget->GetVictim() == m_caster)
+ if (!unitTarget || !unitTarget->CanHaveThreatList() || unitTarget->GetVictim() == m_caster)
{
SendCastResult(SPELL_FAILED_DONT_REPORT);
return;
diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp
index 8dc5af047ec..084695559bd 100644
--- a/src/server/game/Spells/SpellInfo.cpp
+++ b/src/server/game/Spells/SpellInfo.cpp
@@ -75,35 +75,6 @@ bool SpellImplicitTargetInfo::IsArea() const
return GetSelectionCategory() == TARGET_SELECT_CATEGORY_AREA || GetSelectionCategory() == TARGET_SELECT_CATEGORY_CONE;
}
-bool SpellImplicitTargetInfo::IsProximityBasedAoe() const
-{
- switch (_target)
- {
- case TARGET_UNIT_SRC_AREA_ENTRY:
- case TARGET_UNIT_SRC_AREA_ENEMY:
- case TARGET_UNIT_CASTER_AREA_PARTY:
- case TARGET_UNIT_SRC_AREA_ALLY:
- case TARGET_UNIT_SRC_AREA_PARTY:
- case TARGET_UNIT_LASTTARGET_AREA_PARTY:
- case TARGET_GAMEOBJECT_SRC_AREA:
- case TARGET_UNIT_CASTER_AREA_RAID:
- case TARGET_CORPSE_SRC_AREA_ENEMY:
- return true;
-
- case TARGET_UNIT_DEST_AREA_ENTRY:
- case TARGET_UNIT_DEST_AREA_ENEMY:
- case TARGET_UNIT_DEST_AREA_ALLY:
- case TARGET_UNIT_DEST_AREA_PARTY:
- case TARGET_GAMEOBJECT_DEST_AREA:
- case TARGET_UNIT_TARGET_AREA_RAID_CLASS:
- return false;
-
- default:
- TC_LOG_WARN("spells", "SpellImplicitTargetInfo::IsProximityBasedAoe called a non-aoe spell");
- return false;
- }
-}
-
SpellTargetSelectionCategories SpellImplicitTargetInfo::GetSelectionCategory() const
{
return _data[_target].SelectionCategory;
diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h
index 4af84e40376..5a5afeff4ee 100644
--- a/src/server/game/Spells/SpellInfo.h
+++ b/src/server/game/Spells/SpellInfo.h
@@ -286,7 +286,6 @@ public:
SpellImplicitTargetInfo(uint32 target);
bool IsArea() const;
- bool IsProximityBasedAoe() const;
SpellTargetSelectionCategories GetSelectionCategory() const;
SpellTargetReferenceTypes GetReferenceType() const;
SpellTargetObjectTypes GetObjectType() const;
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index 1e2bc42c17d..f2afcdbc474 100644
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -3363,6 +3363,14 @@ void SpellMgr::LoadSpellInfoCorrections()
spellInfo->AttributesEx |= SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY;
});
+ // Blizzard (Thorim)
+ ApplySpellFix({ 62576, 62602 }, [](SpellInfo* spellInfo)
+ {
+ // DBC data is wrong for EFFECT_0, it's a different dynobject target than EFFECT_1
+ // Both effects should be shared by the same DynObject
+ const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->TargetA = SpellImplicitTargetInfo(TARGET_DEST_CASTER_LEFT);
+ });
+
// Spinning Up (Mimiron)
ApplySpellFix({ 63414 }, [](SpellInfo* spellInfo)
{
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index fc45fa83113..7a64662c730 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -1613,6 +1613,9 @@ void World::SetInitialWorldSettings()
MMAP::MMapManager* mmmgr = MMAP::MMapFactory::createOrGetMMapManager();
mmmgr->InitializeThreadUnsafe(mapData);
+ ///- Initialize static helper structures
+ AIRegistry::Initialize();
+
TC_LOG_INFO("server.loading", "Loading SpellInfo store...");
sSpellMgr->LoadSpellInfoStore();
@@ -2140,9 +2143,6 @@ void World::SetInitialWorldSettings()
mail_timer_expires = ((DAY * IN_MILLISECONDS) / (m_timers[WUPDATE_AUCTIONS].GetInterval()));
TC_LOG_INFO("server.loading", "Mail timer set to: " UI64FMTD ", mail return is called every " UI64FMTD " minutes", uint64(mail_timer), uint64(mail_timer_expires));
- ///- Initilize static helper structures
- AIRegistry::Initialize();
-
///- Initialize MapManager
TC_LOG_INFO("server.loading", "Starting Map System");
sMapMgr->Initialize();