aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bindings/scripts/ScriptMgr.cpp4
-rw-r--r--src/bindings/scripts/VC80/80ScriptDev2.vcproj16
-rw-r--r--src/bindings/scripts/VC90/90ScriptDev2.vcproj16
-rw-r--r--src/bindings/scripts/include/precompiled.h3
-rw-r--r--src/bindings/scripts/include/sc_creature.cpp285
-rw-r--r--src/bindings/scripts/include/sc_creature.h122
-rw-r--r--src/bindings/scripts/include/sc_instance.h13
-rw-r--r--src/bindings/scripts/scripts/creature/mob_generic_creature.cpp35
-rw-r--r--src/bindings/scripts/scripts/zone/aunchindoun/shadow_labyrinth/boss_grandmaster_vorpil.cpp2
-rw-r--r--src/bindings/scripts/scripts/zone/aunchindoun/shadow_labyrinth/boss_murmur.cpp4
-rw-r--r--src/bindings/scripts/scripts/zone/aunchindoun/shadow_labyrinth/instance_shadow_labyrinth.cpp2
-rw-r--r--src/bindings/scripts/scripts/zone/azjol_nerub/ahnkahet/instance_ahnkahet.cpp2
-rw-r--r--src/bindings/scripts/scripts/zone/azjol_nerub/azjol_nerub/instance_azjol_nerub.cpp2
-rw-r--r--src/bindings/scripts/scripts/zone/azuremyst_isle/azuremyst_isle.cpp3
-rw-r--r--src/bindings/scripts/scripts/zone/black_temple/boss_illidan.cpp12
-rw-r--r--src/bindings/scripts/scripts/zone/black_temple/boss_supremus.cpp8
-rw-r--r--src/bindings/scripts/scripts/zone/black_temple/boss_warlord_najentus.cpp2
-rw-r--r--src/bindings/scripts/scripts/zone/black_temple/instance_black_temple.cpp2
-rw-r--r--src/bindings/scripts/scripts/zone/blackrock_depths/instance_blackrock_depths.cpp2
-rw-r--r--src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/boss_anetheron.cpp6
-rw-r--r--src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/boss_azgalor.cpp6
-rw-r--r--src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/boss_rage_winterchill.cpp2
-rw-r--r--src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/hyjal_trash.cpp2
-rw-r--r--src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/instance_hyjal.cpp2
-rw-r--r--src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_lurker_below.cpp2
-rw-r--r--src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_morogrim_tidewalker.cpp4
-rw-r--r--src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/instance_serpent_shrine.cpp2
-rw-r--r--src/bindings/scripts/scripts/zone/coilfang_resevoir/steam_vault/instance_steam_vault.cpp2
-rw-r--r--src/bindings/scripts/scripts/zone/coilfang_resevoir/underbog/boss_the_black_stalker.cpp2
-rw-r--r--src/bindings/scripts/scripts/zone/gruuls_lair/instance_gruuls_lair.cpp2
-rw-r--r--src/bindings/scripts/scripts/zone/karazhan/boss_moroes.cpp168
-rw-r--r--src/bindings/scripts/scripts/zone/karazhan/instance_karazhan.cpp2
-rw-r--r--src/bindings/scripts/scripts/zone/naxxramas/boss_anubrekhan.cpp38
-rw-r--r--src/bindings/scripts/scripts/zone/naxxramas/boss_faerlina.cpp129
-rw-r--r--src/bindings/scripts/scripts/zone/naxxramas/boss_gothik.cpp374
-rw-r--r--src/bindings/scripts/scripts/zone/naxxramas/boss_grobbulus.cpp29
-rw-r--r--src/bindings/scripts/scripts/zone/naxxramas/boss_heigan.cpp29
-rw-r--r--src/bindings/scripts/scripts/zone/naxxramas/boss_noth.cpp142
-rw-r--r--src/bindings/scripts/scripts/zone/naxxramas/boss_patchwerk.cpp38
-rw-r--r--src/bindings/scripts/scripts/zone/naxxramas/boss_razuvious.cpp150
-rw-r--r--src/bindings/scripts/scripts/zone/naxxramas/boss_sapphiron.cpp401
-rw-r--r--src/bindings/scripts/scripts/zone/naxxramas/def_naxxramas.h19
-rw-r--r--src/bindings/scripts/scripts/zone/naxxramas/instance_naxxramas.cpp87
-rw-r--r--src/bindings/scripts/scripts/zone/shadowfang_keep/instance_shadowfang_keep.cpp2
-rw-r--r--src/bindings/scripts/scripts/zone/sunwell_plateau/boss_felmyst.cpp8
-rw-r--r--src/bindings/scripts/scripts/zone/sunwell_plateau/boss_kiljaeden.cpp8
-rw-r--r--src/bindings/scripts/scripts/zone/sunwell_plateau/boss_muru.cpp10
-rw-r--r--src/bindings/scripts/scripts/zone/sunwell_plateau/instance_sunwell_plateau.cpp2
-rw-r--r--src/bindings/scripts/scripts/zone/tempest_keep/the_eye/boss_alar.cpp5
-rw-r--r--src/bindings/scripts/scripts/zone/tempest_keep/the_eye/boss_astromancer.cpp4
-rw-r--r--src/bindings/scripts/scripts/zone/tempest_keep/the_eye/boss_kaelthas.cpp6
-rw-r--r--src/bindings/scripts/scripts/zone/tempest_keep/the_eye/instance_the_eye.cpp2
-rw-r--r--src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/boss_twinemperors.cpp6
-rw-r--r--src/bindings/scripts/scripts/zone/utgarde_keep/utgarde_keep/instance_utgarde_keep.cpp2
-rw-r--r--src/bindings/scripts/scripts/zone/utgarde_keep/utgarde_keep/utgarde_keep.cpp4
-rw-r--r--src/bindings/scripts/scripts/zone/zulaman/boss_akilzon.cpp2
-rw-r--r--src/bindings/scripts/scripts/zone/zulaman/boss_hexlord.cpp2
-rw-r--r--src/bindings/scripts/scripts/zone/zulaman/boss_nalorakk.cpp2
-rw-r--r--src/bindings/scripts/scripts/zone/zulaman/instance_zulaman.cpp2
-rw-r--r--src/framework/Platform/Define.h6
-rw-r--r--src/game/AchievementMgr.cpp31
-rw-r--r--src/game/AggressorAI.cpp125
-rw-r--r--src/game/AggressorAI.h34
-rw-r--r--src/game/BattleGround.cpp77
-rw-r--r--src/game/BattleGround.h4
-rw-r--r--src/game/CMakeLists.txt5
-rw-r--r--src/game/CharacterHandler.cpp7
-rw-r--r--src/game/Chat.cpp3
-rw-r--r--src/game/Chat.h2
-rw-r--r--src/game/Creature.cpp40
-rw-r--r--src/game/Creature.h25
-rw-r--r--src/game/CreatureAI.cpp293
-rw-r--r--src/game/CreatureAI.h146
-rw-r--r--src/game/CreatureAIFactory.h53
-rw-r--r--src/game/CreatureAIImpl.h154
-rw-r--r--src/game/CreatureAIRegistry.cpp6
-rw-r--r--src/game/CreatureAISelector.cpp14
-rw-r--r--src/game/CreatureEventAI.cpp21
-rw-r--r--src/game/DBCEnums.h2
-rw-r--r--src/game/DBCStructure.h57
-rw-r--r--src/game/DBCfmt.h2
-rw-r--r--src/game/GameObject.cpp4
-rw-r--r--src/game/GridNotifiers.h61
-rw-r--r--src/game/GridNotifiersImpl.h9
-rw-r--r--src/game/Group.cpp14
-rw-r--r--src/game/GroupHandler.cpp6
-rw-r--r--src/game/GuardAI.cpp2
-rw-r--r--src/game/InstanceData.cpp135
-rw-r--r--src/game/InstanceData.h62
-rw-r--r--src/game/InstanceSaveMgr.cpp10
-rw-r--r--src/game/InstanceSaveMgr.h4
-rw-r--r--src/game/ItemPrototype.h44
-rw-r--r--src/game/Language.h10
-rw-r--r--src/game/Level1.cpp60
-rw-r--r--src/game/Level2.cpp71
-rw-r--r--src/game/Level3.cpp90
-rw-r--r--src/game/LootHandler.cpp2
-rw-r--r--src/game/Map.cpp7
-rw-r--r--src/game/Map.h25
-rw-r--r--src/game/MapManager.cpp4
-rw-r--r--src/game/MapManager.h6
-rw-r--r--src/game/MiscHandler.cpp43
-rw-r--r--src/game/MotionMaster.cpp10
-rw-r--r--src/game/NullCreatureAI.h19
-rw-r--r--src/game/Object.cpp331
-rw-r--r--src/game/Object.h25
-rw-r--r--src/game/ObjectAccessor.cpp6
-rw-r--r--src/game/ObjectAccessor.h12
-rw-r--r--src/game/ObjectMgr.cpp9
-rw-r--r--src/game/ObjectMgr.h2
-rw-r--r--src/game/OutdoorPvPEP.cpp2
-rw-r--r--src/game/Pet.cpp30
-rw-r--r--src/game/Pet.h6
-rw-r--r--src/game/PetHandler.cpp9
-rw-r--r--src/game/Player.cpp322
-rw-r--r--src/game/Player.h12
-rw-r--r--src/game/PossessedAI.cpp20
-rw-r--r--src/game/PossessedAI.h25
-rw-r--r--src/game/RandomMovementGenerator.cpp22
-rw-r--r--src/game/SharedDefines.h11
-rw-r--r--src/game/Spell.cpp132
-rw-r--r--src/game/Spell.h12
-rw-r--r--src/game/SpellAuras.cpp100
-rw-r--r--src/game/SpellAuras.h1
-rw-r--r--src/game/SpellEffects.cpp163
-rw-r--r--src/game/SpellMgr.cpp37
-rw-r--r--src/game/TaxiHandler.cpp7
-rw-r--r--src/game/TemporarySummon.cpp8
-rw-r--r--src/game/TemporarySummon.h2
-rw-r--r--src/game/TradeHandler.cpp26
-rw-r--r--src/game/Unit.cpp208
-rw-r--r--src/game/Unit.h49
-rw-r--r--src/game/UnitAI.cpp89
-rw-r--r--src/game/UnitAI.h68
-rw-r--r--src/game/WaypointManager.cpp21
-rw-r--r--src/game/WaypointManager.h11
-rw-r--r--src/game/WaypointMovementGenerator.cpp8
-rw-r--r--src/game/WaypointMovementGenerator.h4
-rw-r--r--src/game/World.cpp4
-rw-r--r--src/game/World.h6
-rw-r--r--src/game/WorldLog.cpp4
-rw-r--r--src/game/WorldLog.h4
-rw-r--r--src/game/WorldSession.h3
-rw-r--r--src/shared/CMakeLists.txt5
-rw-r--r--src/shared/Common.h41
-rw-r--r--src/shared/Database/Database.cpp3
-rw-r--r--src/shared/Database/Database.h9
-rw-r--r--src/shared/Database/DatabaseImpl.h4
-rw-r--r--src/shared/Database/DatabaseMysql.cpp29
-rw-r--r--src/shared/Database/DatabaseMysql.h7
-rw-r--r--src/shared/Database/DatabasePostgre.cpp30
-rw-r--r--src/shared/Database/DatabasePostgre.h7
-rw-r--r--src/shared/Database/QueryResult.h2
-rw-r--r--src/shared/Database/SQLStorage.cpp4
-rw-r--r--src/shared/Database/SqlDelayThread.cpp2
-rw-r--r--src/shared/Database/SqlDelayThread.h15
-rw-r--r--src/shared/Database/SqlOperations.h7
-rw-r--r--src/shared/LockedQueue.h144
-rw-r--r--src/shared/Log.h2
-rw-r--r--src/shared/Makefile.am3
-rw-r--r--src/shared/MemoryLeaks.h6
-rw-r--r--src/shared/Threading.cpp205
-rw-r--r--src/shared/Threading.h99
-rw-r--r--src/shared/Util.cpp20
-rw-r--r--src/trinitycore/CliRunnable.cpp4
-rw-r--r--src/trinitycore/CliRunnable.h2
-rw-r--r--src/trinitycore/Makefile.am5
-rw-r--r--src/trinitycore/Master.cpp20
-rw-r--r--src/trinitycore/WorldRunnable.cpp2
-rw-r--r--src/trinitycore/WorldRunnable.h2
-rw-r--r--src/trinitycore/trinitycore.conf.dist12
-rw-r--r--src/trinityrealm/AuthSocket.cpp16
-rw-r--r--src/trinityrealm/AuthSocket.h3
-rw-r--r--src/trinityrealm/Makefile.am5
174 files changed, 4307 insertions, 2264 deletions
diff --git a/src/bindings/scripts/ScriptMgr.cpp b/src/bindings/scripts/ScriptMgr.cpp
index 18465bfacf7..849c4d64be5 100644
--- a/src/bindings/scripts/ScriptMgr.cpp
+++ b/src/bindings/scripts/ScriptMgr.cpp
@@ -389,6 +389,7 @@ extern void AddSC_boss_sapphiron();
extern void AddSC_boss_four_horsemen();
extern void AddSC_boss_faerlina();
extern void AddSC_boss_heigan();
+extern void AddSC_boss_gothik();
extern void AddSC_instance_naxxramas();
//Netherstorm
@@ -1327,6 +1328,7 @@ void ScriptsInit(char const* cfg_file = "trinitycore.conf")
AddSC_boss_sapphiron();
AddSC_boss_four_horsemen();
AddSC_boss_heigan();
+ AddSC_boss_gothik();
AddSC_instance_naxxramas();
//Netherstorm
@@ -1657,7 +1659,7 @@ void Script::RegisterSelf()
m_scripts[id] = this;
++num_sc_scripts;
}
- else
+ else if(Name.find("example") == std::string::npos)
{
error_db_log("CRASH ALERT! TrinityScript: RegisterSelf, but script named %s does not have ScriptName assigned in database.",(this)->Name.c_str());
delete this;
diff --git a/src/bindings/scripts/VC80/80ScriptDev2.vcproj b/src/bindings/scripts/VC80/80ScriptDev2.vcproj
index c442ae52a2d..28875c526ab 100644
--- a/src/bindings/scripts/VC80/80ScriptDev2.vcproj
+++ b/src/bindings/scripts/VC80/80ScriptDev2.vcproj
@@ -68,10 +68,10 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="TrinityCore.lib zthread.lib"
+ AdditionalDependencies="TrinityCore.lib aced.lib"
OutputFile="$(OutDir)/TrinityScript.dll"
LinkIncremental="2"
- AdditionalLibraryDirectories="..\..\..\..\win\VC80\zthread__$(PlatformName)_$(ConfigurationName);..\..\..\..\win\VC80\trinitycore__$(PlatformName)_$(ConfigurationName)"
+ AdditionalLibraryDirectories="..\..\..\..\win\VC80\trinitycore__$(PlatformName)_$(ConfigurationName);..\..\..\..\dep\lib\$(PlatformName)_$(ConfigurationName)"
GenerateDebugInformation="true"
ProgramDatabaseFile="$(OutDir)/TrinityScript.pdb"
SubSystem="2"
@@ -151,10 +151,10 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="TrinityCore.lib zthread.lib"
+ AdditionalDependencies="TrinityCore.lib ace.lib"
OutputFile="$(OutDir)/TrinityScript.dll"
LinkIncremental="1"
- AdditionalLibraryDirectories="..\..\..\..\win\VC80\zthread__$(PlatformName)_$(ConfigurationName);..\..\..\..\win\VC80\trinitycore__$(PlatformName)_$(ConfigurationName)"
+ AdditionalLibraryDirectories="..\..\..\..\win\VC80\trinitycore__$(PlatformName)_$(ConfigurationName);..\..\..\..\dep\lib\$(PlatformName)_$(ConfigurationName)"
GenerateDebugInformation="false"
SubSystem="2"
OptimizeReferences="2"
@@ -236,10 +236,10 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="TrinityCore.lib zthread.lib"
+ AdditionalDependencies="TrinityCore.lib aced.lib"
OutputFile="$(OutDir)/TrinityScript.dll"
LinkIncremental="2"
- AdditionalLibraryDirectories="..\..\..\..\win\VC80\zthread__$(PlatformName)_$(ConfigurationName);..\..\..\..\win\VC80\trinitycore__$(PlatformName)_$(ConfigurationName)"
+ AdditionalLibraryDirectories="..\..\..\..\win\VC80\trinitycore__$(PlatformName)_$(ConfigurationName);..\..\..\..\dep\lib\$(PlatformName)_$(ConfigurationName)"
GenerateDebugInformation="true"
ProgramDatabaseFile="$(OutDir)/TrinityScript.pdb"
SubSystem="2"
@@ -320,10 +320,10 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="TrinityCore.lib zthread.lib"
+ AdditionalDependencies="TrinityCore.lib ace.lib"
OutputFile="$(OutDir)/TrinityScript.dll"
LinkIncremental="1"
- AdditionalLibraryDirectories="..\..\..\..\win\VC80\zthread__$(PlatformName)_$(ConfigurationName);..\..\..\..\win\VC80\trinitycore__$(PlatformName)_$(ConfigurationName)"
+ AdditionalLibraryDirectories="..\..\..\..\win\VC80\trinitycore__$(PlatformName)_$(ConfigurationName);..\..\..\..\dep\lib\$(PlatformName)_$(ConfigurationName)"
GenerateDebugInformation="false"
SubSystem="2"
OptimizeReferences="2"
diff --git a/src/bindings/scripts/VC90/90ScriptDev2.vcproj b/src/bindings/scripts/VC90/90ScriptDev2.vcproj
index 398e54d6ec4..8f8330db453 100644
--- a/src/bindings/scripts/VC90/90ScriptDev2.vcproj
+++ b/src/bindings/scripts/VC90/90ScriptDev2.vcproj
@@ -68,10 +68,10 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="trinitycore.lib zthread.lib"
+ AdditionalDependencies="trinitycore.lib aced.lib"
OutputFile="$(OutDir)/TrinityScript.dll"
LinkIncremental="2"
- AdditionalLibraryDirectories="..\..\..\..\win\VC90\zthread__$(PlatformName)_$(ConfigurationName);..\..\..\..\win\VC90\trinitycore__$(PlatformName)_$(ConfigurationName)"
+ AdditionalLibraryDirectories="..\..\..\..\win\VC90\trinitycore__$(PlatformName)_$(ConfigurationName);..\..\..\..\dep\lib\$(PlatformName)_$(ConfigurationName)"
GenerateDebugInformation="true"
ProgramDatabaseFile="$(OutDir)/TrinityScript.pdb"
SubSystem="2"
@@ -152,10 +152,10 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="trinitycore.lib zthread.lib"
+ AdditionalDependencies="trinitycore.lib ace.lib"
OutputFile="$(OutDir)/TrinityScript.dll"
LinkIncremental="1"
- AdditionalLibraryDirectories="..\..\..\..\win\VC90\zthread__$(PlatformName)_$(ConfigurationName);..\..\..\..\win\VC90\trinitycore__$(PlatformName)_$(ConfigurationName)"
+ AdditionalLibraryDirectories="..\..\..\..\win\VC90\trinitycore__$(PlatformName)_$(ConfigurationName);..\..\..\..\dep\lib\$(PlatformName)_$(ConfigurationName)"
GenerateDebugInformation="false"
SubSystem="2"
OptimizeReferences="2"
@@ -237,10 +237,10 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="trinitycore.lib zthread.lib"
+ AdditionalDependencies="trinitycore.lib aced.lib"
OutputFile="$(OutDir)/TrinityScript.dll"
LinkIncremental="2"
- AdditionalLibraryDirectories="..\..\..\..\win\VC90\zthread__$(PlatformName)_$(ConfigurationName);..\..\..\..\win\VC90\trinitycore__$(PlatformName)_$(ConfigurationName)"
+ AdditionalLibraryDirectories="..\..\..\..\win\VC90\trinitycore__$(PlatformName)_$(ConfigurationName);..\..\..\..\dep\lib\$(PlatformName)_$(ConfigurationName)"
GenerateDebugInformation="true"
ProgramDatabaseFile="$(OutDir)/TrinityScript.pdb"
SubSystem="2"
@@ -320,10 +320,10 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="trinitycore.lib zthread.lib"
+ AdditionalDependencies="trinitycore.lib ace.lib"
OutputFile="$(OutDir)/TrinityScript.dll"
LinkIncremental="1"
- AdditionalLibraryDirectories="..\..\..\..\win\VC90\zthread__$(PlatformName)_$(ConfigurationName);..\..\..\..\win\VC90\trinitycore__$(PlatformName)_$(ConfigurationName)"
+ AdditionalLibraryDirectories="..\..\..\..\win\VC90\trinitycore__$(PlatformName)_$(ConfigurationName);..\..\..\..\dep\lib\$(PlatformName)_$(ConfigurationName)"
GenerateDebugInformation="false"
SubSystem="2"
OptimizeReferences="2"
diff --git a/src/bindings/scripts/include/precompiled.h b/src/bindings/scripts/include/precompiled.h
index 2c36cc924e0..fa676f460ef 100644
--- a/src/bindings/scripts/include/precompiled.h
+++ b/src/bindings/scripts/include/precompiled.h
@@ -12,10 +12,11 @@
#include "GridNotifiersImpl.h"
#include "Unit.h"
#include "GameObject.h"
-#include "TemporarySummon.h"
#include "sc_creature.h"
#include "sc_gossip.h"
#include "sc_instance.h"
+#include "AggressorAI.h"
+#include "NullCreatureAI.h"
#ifdef WIN32
#include <windows.h>
diff --git a/src/bindings/scripts/include/sc_creature.cpp b/src/bindings/scripts/include/sc_creature.cpp
index 258c7627dce..e575e40fac1 100644
--- a/src/bindings/scripts/include/sc_creature.cpp
+++ b/src/bindings/scripts/include/sc_creature.cpp
@@ -9,6 +9,7 @@
#include "Item.h"
#include "Spell.h"
#include "ObjectMgr.h"
+#include "TemporarySummon.h"
// Spell summary for ScriptedAI::SelectSpell
struct TSpellSummary {
@@ -16,13 +17,26 @@ struct TSpellSummary {
uint8 Effects; // set of enum SelectEffect
} *SpellSummary;
+void SummonList::DoZoneInCombat(uint32 entry)
+{
+ for(iterator i = begin(); i != end();)
+ {
+ Creature *summon = Unit::GetCreature(*m_creature, *i);
+ ++i;
+ if(summon && summon->IsAIEnabled
+ && (!entry || summon->GetEntry() == entry))
+ summon->AI()->DoZoneInCombat();
+ }
+}
+
void SummonList::DoAction(uint32 entry, uint32 info)
{
for(iterator i = begin(); i != end();)
{
Creature *summon = Unit::GetCreature(*m_creature, *i);
++i;
- if(summon && summon->IsAIEnabled)
+ if(summon && summon->IsAIEnabled
+ && (!entry || summon->GetEntry() == entry))
summon->AI()->DoAction(info);
}
}
@@ -55,7 +69,11 @@ void SummonList::DespawnAll()
else
{
erase(begin());
- summon->setDeathState(JUST_DIED);
+ summon->SetVisibility(VISIBILITY_OFF);
+ if(summon->HasSummonMask(SUMMON_MASK_SUMMON) && !summon->isPet())
+ ((TempSummon*)summon)->UnSummon();
+ else
+ summon->setDeathState(JUST_DIED);
summon->RemoveCorpse();
}
}
@@ -108,26 +126,6 @@ void ScriptedAI::UpdateAI(const uint32 diff)
}
}
-void ScriptedAI::EnterEvadeMode()
-{
- //m_creature->InterruptNonMeleeSpells(true);
- m_creature->RemoveAllAuras();
- m_creature->DeleteThreatList();
- m_creature->CombatStop();
- m_creature->LoadCreaturesAddon();
- m_creature->SetLootRecipient(NULL);
-
- if(m_creature->isAlive())
- m_creature->GetMotionMaster()->MoveTargetedHome();
-
- Reset();
-}
-
-void ScriptedAI::JustRespawned()
-{
- Reset();
-}
-
void ScriptedAI::DoStartMovement(Unit* victim, float distance, float angle)
{
if (!victim)
@@ -228,6 +226,19 @@ Creature* ScriptedAI::DoSpawnCreature(uint32 id, float x, float y, float z, floa
return m_creature->SummonCreature(id,m_creature->GetPositionX() + x,m_creature->GetPositionY() + y,m_creature->GetPositionZ() + z, angle, (TempSummonType)type, despawntime);
}
+Creature *ScriptedAI::DoSummon(uint32 entry, const float pos[4], uint32 despawntime, TempSummonType type)
+{
+ return me->SummonCreature(entry, pos[0], pos[1], pos[2], pos[3], type, despawntime);
+}
+
+Creature *ScriptedAI::DoSummon(uint32 entry, WorldObject *obj, float radius, uint32 despawntime, TempSummonType type)
+{
+ float x, y, z;
+ obj->GetGroundPointAroundUnit(x, y, z, radius * rand_norm(), rand_norm()*2*M_PI);
+ return me->SummonCreature(entry, x, y, z, me->GetOrientation(), type, despawntime);
+}
+
+
Unit* ScriptedAI::SelectUnit(SelectAggroTarget target, uint32 position)
{
//ThreatList m_threatlist;
@@ -259,147 +270,7 @@ Unit* ScriptedAI::SelectUnit(SelectAggroTarget target, uint32 position)
return NULL;
}
-struct TargetDistanceOrder : public std::binary_function<const Unit, const Unit, bool>
-{
- const Unit* me;
- TargetDistanceOrder(const Unit* Target) : me(Target) {};
- // functor for operator ">"
- bool operator()(const Unit* _Left, const Unit* _Right) const
- {
- return (me->GetDistance(_Left) < me->GetDistance(_Right));
- }
-};
-
-Unit* ScriptedAI::SelectUnit(SelectAggroTarget targetType, uint32 position, float dist, bool playerOnly)
-{
- if(targetType == SELECT_TARGET_NEAREST || targetType == SELECT_TARGET_FARTHEST)
- {
- std::list<HostilReference*> &m_threatlist = m_creature->getThreatManager().getThreatList();
- if(m_threatlist.empty()) return NULL;
- std::list<Unit*> targetList;
- std::list<HostilReference*>::iterator itr = m_threatlist.begin();
- for(; itr!= m_threatlist.end(); ++itr)
- {
- Unit *target = (*itr)->getTarget();
- if(!target
- || playerOnly && target->GetTypeId() != TYPEID_PLAYER
- || dist && !m_creature->IsWithinCombatRange(target, dist))
- {
- continue;
- }
- targetList.push_back(target);
- }
- if(position >= targetList.size())
- return NULL;
- targetList.sort(TargetDistanceOrder(m_creature));
- if(targetType == SELECT_TARGET_NEAREST)
- {
- std::list<Unit*>::iterator i = targetList.begin();
- advance(i, position);
- return *i;
- }
- else
- {
- std::list<Unit*>::reverse_iterator i = targetList.rbegin();
- advance(i, position);
- return *i;
- }
- }
- else
- {
- std::list<HostilReference*> m_threatlist = m_creature->getThreatManager().getThreatList();
- std::list<HostilReference*>::iterator i;
- Unit *target;
- while(position < m_threatlist.size())
- {
- if(targetType == SELECT_TARGET_BOTTOMAGGRO)
- {
- i = m_threatlist.end();
- advance(i, - (int32)position - 1);
- }
- else
- {
- i = m_threatlist.begin();
- if(targetType == SELECT_TARGET_TOPAGGRO)
- advance(i, position);
- else // random
- advance(i, position + rand()%(m_threatlist.size() - position));
- }
-
- target = (*i)->getTarget();
- if(!target
- || playerOnly && target->GetTypeId() != TYPEID_PLAYER
- || dist && !m_creature->IsWithinCombatRange(target, dist))
- {
- m_threatlist.erase(i);
- }
- else
- {
- return target;
- }
- }
- }
-
- return NULL;
-}
-
-void ScriptedAI::SelectUnitList(std::list<Unit*> &targetList, uint32 num, SelectAggroTarget targetType, float dist, bool playerOnly)
-{
- if(targetType == SELECT_TARGET_NEAREST || targetType == SELECT_TARGET_FARTHEST)
- {
- std::list<HostilReference*> &m_threatlist = m_creature->getThreatManager().getThreatList();
- if(m_threatlist.empty()) return;
- std::list<HostilReference*>::iterator itr = m_threatlist.begin();
- for(; itr!= m_threatlist.end(); ++itr)
- {
- Unit *target = (*itr)->getTarget();
- if(!target
- || playerOnly && target->GetTypeId() != TYPEID_PLAYER
- || dist && !m_creature->IsWithinCombatRange(target, dist))
- {
- continue;
- }
- targetList.push_back(target);
- }
- targetList.sort(TargetDistanceOrder(m_creature));
- targetList.resize(num);
- if(targetType == SELECT_TARGET_FARTHEST)
- targetList.reverse();
- }
- else
- {
- std::list<HostilReference*> m_threatlist = m_creature->getThreatManager().getThreatList();
- std::list<HostilReference*>::iterator i;
- Unit *target;
- while(m_threatlist.size() && num)
- {
- if(targetType == SELECT_TARGET_BOTTOMAGGRO)
- {
- i = m_threatlist.end();
- --i;
- }
- else
- {
- i = m_threatlist.begin();
- if(targetType == SELECT_TARGET_RANDOM)
- advance(i, rand()%m_threatlist.size());
- }
-
- target = (*i)->getTarget();
- m_threatlist.erase(i);
- if(!target
- || playerOnly && target->GetTypeId() != TYPEID_PLAYER
- || dist && !m_creature->IsWithinCombatRange(target, dist))
- {
- continue;
- }
- targetList.push_back(target);
- --num;
- }
- }
-}
-
-SpellEntry const* ScriptedAI::SelectSpell(Unit* Target, int32 School, int32 Mechanic, SelectTarget Targets, uint32 PowerCostMin, uint32 PowerCostMax, float RangeMin, float RangeMax, SelectEffect Effects)
+SpellEntry const* ScriptedAI::SelectSpell(Unit* Target, int32 School, int32 Mechanic, SelectTargetType Targets, uint32 PowerCostMin, uint32 PowerCostMax, float RangeMin, float RangeMax, SelectEffect Effects)
{
//No target so we can't cast
if (!Target)
@@ -515,7 +386,6 @@ bool ScriptedAI::CanCast(Unit* Target, SpellEntry const *Spell, bool Triggered)
return true;
}
-
float GetSpellMaxRangeForHostile(uint32 id)
{
SpellEntry const *spellInfo = GetSpellStore()->LookupEntry(id);
@@ -531,7 +401,7 @@ void FillSpellSummary()
SpellEntry const* TempSpell;
- for (int i=0; i < GetSpellStore()->GetNumRows(); i++ )
+ for(uint32 i = 0; i < GetSpellStore()->GetNumRows(); ++i)
{
SpellSummary[i].Effects = 0;
SpellSummary[i].Targets = 0;
@@ -541,7 +411,7 @@ void FillSpellSummary()
if (!TempSpell)
continue;
- for (int j=0; j<3; j++)
+ for(uint32 j = 0; j < 3; ++j)
{
//Spell targets self
if ( TempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_CASTER )
@@ -649,6 +519,11 @@ void ScriptedAI::DoTeleportTo(float x, float y, float z, uint32 time)
m_creature->SendMonsterMove(x, y, z, time);
}
+void ScriptedAI::DoTeleportTo(const float pos[4])
+{
+ me->NearTeleportTo(pos[0], pos[1], pos[2], pos[3]);
+}
+
void ScriptedAI::DoTeleportPlayer(Unit* pUnit, float x, float y, float z, float o)
{
if(!pUnit || pUnit->GetTypeId() != TYPEID_PLAYER)
@@ -775,23 +650,85 @@ void Scripted_NoMovementAI::AttackStart(Unit* who)
}
}
+void BossAI::_Reset()
+{
+ events.Reset();
+ summons.DespawnAll();
+ instance->SetBossState(bossId, NOT_STARTED);
+}
+
+void BossAI::_JustDied()
+{
+ events.Reset();
+ summons.DespawnAll();
+ instance->SetBossState(bossId, DONE);
+}
+
+void BossAI::_EnterCombat()
+{
+ DoZoneInCombat();
+ instance->SetBossState(bossId, IN_PROGRESS);
+}
+
+void BossAI::JustSummoned(Creature *summon)
+{
+ summons.Summon(summon);
+ if(me->isInCombat())
+ DoZoneInCombat(summon);
+}
+
+void BossAI::SummonedCreatureDespawn(Creature *summon)
+{
+ summons.Despawn(summon);
+}
+
+#define GOBJECT(x) (const_cast<GameObjectInfo*>(GetGameObjectInfo(x)))
+
void LoadOverridenSQLData()
{
GameObjectInfo *goInfo;
// Sunwell Plateau : Kalecgos : Spectral Rift
- goInfo = const_cast<GameObjectInfo*>(GetGameObjectInfo(187055));
- if(goInfo && goInfo->type == GAMEOBJECT_TYPE_GOOBER)
- goInfo->goober.lockId = 57; // need LOCKTYPE_QUICK_OPEN
+ if(goInfo = GOBJECT(187055))
+ if(goInfo->type == GAMEOBJECT_TYPE_GOOBER)
+ goInfo->goober.lockId = 57; // need LOCKTYPE_QUICK_OPEN
+
+ // Naxxramas : Sapphiron Birth
+ if(goInfo = GOBJECT(181356))
+ if(goInfo->type == GAMEOBJECT_TYPE_TRAP)
+ goInfo->trap.radius = 50;
}
void LoadOverridenDBCData()
{
SpellEntry *spellInfo;
+ for(uint32 i = 0; i < GetSpellStore()->GetNumRows(); ++i)
+ {
+ spellInfo = (SpellEntry*)GetSpellStore()->LookupEntry(i);
+ if(!spellInfo)
+ continue;
- // Black Temple : Illidan : Parasitic Shadowfiend Passive
- spellInfo = const_cast<SpellEntry*>(GetSpellStore()->LookupEntry(41913));
- if(spellInfo)
- spellInfo->EffectApplyAuraName[0] = 4; // proc debuff, and summon infinite fiends
+ switch(i)
+ {
+ // Black Temple : Illidan : Parasitic Shadowfiend Passive
+ case 41013:
+ spellInfo->EffectApplyAuraName[0] = 4; // proc debuff, and summon infinite fiends
+ break;
+ //temp, not needed in 310
+ case 28531:
+ case 55799:
+ spellInfo->DurationIndex = 21;
+ spellInfo->Effect[0] = SPELL_EFFECT_APPLY_AREA_AURA_ENEMY;
+ break;
+ // Naxxramas: Gothik : Inform Inf range
+ case 27892:
+ case 27928:
+ case 27935:
+ case 27915:
+ case 27931:
+ case 27937:
+ spellInfo->rangeIndex = 13;
+ break;
+ }
+ }
}
-
diff --git a/src/bindings/scripts/include/sc_creature.h b/src/bindings/scripts/include/sc_creature.h
index 638b6926a27..80016619e8b 100644
--- a/src/bindings/scripts/include/sc_creature.h
+++ b/src/bindings/scripts/include/sc_creature.h
@@ -8,75 +8,28 @@
#ifndef SC_CREATURE_H
#define SC_CREATURE_H
-#include "CreatureAI.h"
#include "Creature.h"
+#include "CreatureAI.h"
+#include "CreatureAIImpl.h"
-#define HEROIC(n,h) (HeroicMode ? h : n)
-
-template<class T>
-inline
-const T& RAND(const T& v1, const T& v2)
-{
- return rand()%2 ? v1 : v2;
-}
-
-template<class T>
-inline
-const T& RAND(const T& v1, const T& v2, const T& v3)
-{
- switch(rand()%3)
- {
- default:
- case 0: return v1;
- case 1: return v2;
- case 2: return v3;
- }
-}
-
-template<class T>
-inline
-const T& RAND(const T& v1, const T& v2, const T& v3, const T& v4)
-{
- switch(rand()%4)
- {
- default:
- case 0: return v1;
- case 1: return v2;
- case 2: return v3;
- case 3: return v4;
- }
-}
-
-template<class T>
-inline
-const T& RAND(const T& v1, const T& v2, const T& v3, const T& v4, const T& v5)
-{
- switch(rand()%4)
- {
- default:
- case 0: return v1;
- case 1: return v2;
- case 2: return v3;
- case 3: return v4;
- case 4: return v5;
- }
-}
-
-float GetSpellMaxRangeForHostile(uint32 id);
+class ScriptedInstance;
class SummonList : private std::list<uint64>
{
-public:
- explicit SummonList(Creature* creature) : m_creature(creature) {}
- void Summon(Creature *summon) { push_back(summon->GetGUID()); }
- void Despawn(Creature *summon) { remove(summon->GetGUID()); }
- void DespawnEntry(uint32 entry);
- void DespawnAll();
- void DoAction(uint32 entry, uint32 info);
-private:
- Creature *m_creature;
+ public:
+ explicit SummonList(Creature* creature) : m_creature(creature) {}
+ void Summon(Creature *summon) { push_back(summon->GetGUID()); }
+ void Despawn(Creature *summon) { remove(summon->GetGUID()); }
+ void DespawnEntry(uint32 entry);
+ void DespawnAll();
+ void DoAction(uint32 entry, uint32 info);
+ void DoZoneInCombat(uint32 entry = 0);
+ private:
+ Creature *m_creature;
};
+float GetSpellMaxRangeForHostile(uint32 id);
+
//Get a single creature of given entry
Unit* FindCreature(uint32 entry, float range, Unit* Finder);
@@ -106,9 +59,6 @@ struct TRINITY_DLL_DECL ScriptedAI : public CreatureAI
void AttackStart(Unit *);
void AttackStart(Unit *, bool melee);
- //Called at stoping attack by any attacker
- void EnterEvadeMode();
-
// Called at any Damage from any attacker (before damage apply)
void DamageTaken(Unit *done_by, uint32 &damage) {}
@@ -133,11 +83,8 @@ struct TRINITY_DLL_DECL ScriptedAI : public CreatureAI
// Called when spell hits a target
void SpellHitTarget(Unit* target, const SpellEntry*) {}
- // Called when creature is spawned or respawned (for reseting variables)
- void JustRespawned();
-
//Called at waypoint reached or PointMovement end
- void MovementInform(uint32, uint32){}
+ void MovementInform(uint32 type, uint32 id){}
// Called when AI is temporarily replaced or put back when possess is applied or removed
void OnPossess(bool apply) {}
@@ -206,6 +153,7 @@ struct TRINITY_DLL_DECL ScriptedAI : public CreatureAI
void DoModifyThreatPercent(Unit *pUnit, int32 pct);
void DoTeleportTo(float x, float y, float z, uint32 time = 0);
+ void DoTeleportTo(const float pos[4]);
void DoAction(const int32 param) {}
@@ -224,16 +172,16 @@ struct TRINITY_DLL_DECL ScriptedAI : public CreatureAI
//Spawns a creature relative to m_creature
Creature* DoSpawnCreature(uint32 id, float x, float y, float z, float angle, uint32 type, uint32 despawntime);
+ Creature *DoSummon(uint32 entry, const float pos[4], uint32 despawntime = 30000, TempSummonType type = TEMPSUMMON_CORPSE_TIMED_DESPAWN);
+ Creature *DoSummon(uint32 entry, WorldObject *obj, float radius = 5.0f, uint32 despawntime = 30000, TempSummonType type = TEMPSUMMON_CORPSE_TIMED_DESPAWN);
//Selects a unit from the creature's current aggro list
Unit* SelectUnit(SelectAggroTarget target, uint32 position);
- Unit* SelectUnit(SelectAggroTarget target, uint32 position, float dist, bool playerOnly);
- void SelectUnitList(std::list<Unit*> &targetList, uint32 num, SelectAggroTarget target, float dist, bool playerOnly);
bool HealthBelowPct(uint32 pct) const { return me->GetHealth() * 100 < m_creature->GetMaxHealth() * pct; }
//Returns spells that meet the specified criteria from the creatures spell list
- SpellEntry const* SelectSpell(Unit* Target, int32 School, int32 Mechanic, SelectTarget Targets, uint32 PowerCostMin, uint32 PowerCostMax, float RangeMin, float RangeMax, SelectEffect Effect);
+ SpellEntry const* SelectSpell(Unit* Target, int32 School, int32 Mechanic, SelectTargetType Targets, uint32 PowerCostMin, uint32 PowerCostMax, float RangeMin, float RangeMax, SelectEffect Effect);
//Checks if you can cast the specified spell
bool CanCast(Unit* Target, SpellEntry const *Spell, bool Triggered = false);
@@ -254,19 +202,29 @@ struct TRINITY_DLL_DECL Scripted_NoMovementAI : public ScriptedAI
void AttackStart(Unit *);
};
-struct TRINITY_DLL_DECL NullCreatureAI : public ScriptedAI
+struct TRINITY_DLL_DECL BossAI : public ScriptedAI
{
- NullCreatureAI(Creature* c) : ScriptedAI(c) {}
- ~NullCreatureAI() {}
+ BossAI(Creature *c, uint32 id) : ScriptedAI(c), bossId(id)
+ , summons(me), instance(c->GetInstanceData())
+ {}
- void Reset() {}
- void EnterCombat(Unit*) {}
- void MoveInLineOfSight(Unit *) {}
- void AttackStart(Unit *) {}
- void EnterEvadeMode() {}
- bool IsVisible(Unit *) const { return false; }
+ uint32 bossId;
+ EventMap events;
+ SummonList summons;
+ InstanceData *instance;
+
+ void JustSummoned(Creature *summon);
+ void SummonedCreatureDespawn(Creature *summon);
+
+ void UpdateAI(const uint32 diff) = 0;
+
+ void _Reset();
+ void _EnterCombat();
+ void _JustDied();
- void UpdateAI(const uint32) {}
+ void Reset() { _Reset(); }
+ void EnterCombat(Unit *who) { _EnterCombat(); }
+ void JustDied(Unit *killer) { _JustDied(); }
};
#endif
diff --git a/src/bindings/scripts/include/sc_instance.h b/src/bindings/scripts/include/sc_instance.h
index cdf0e03aa37..0620e89af07 100644
--- a/src/bindings/scripts/include/sc_instance.h
+++ b/src/bindings/scripts/include/sc_instance.h
@@ -17,20 +17,7 @@
class TRINITY_DLL_DECL ScriptedInstance : public InstanceData
{
public:
-
ScriptedInstance(Map *map) : InstanceData(map) {}
- ~ScriptedInstance() {}
-
- //All-purpose data storage 64 bit
- virtual uint64 GetData64(uint32 Data) { return 0; }
- virtual void SetData64(uint32 Data, uint64 Value) { }
-
- // Called every instance update
- virtual void Update(uint32) {}
-
- // Save and Load instance data to the database
- const char* Save() { return NULL; }
- void Load(const char* in) { }
};
#endif
diff --git a/src/bindings/scripts/scripts/creature/mob_generic_creature.cpp b/src/bindings/scripts/scripts/creature/mob_generic_creature.cpp
index 2f2d5349f2a..ec987e31c0e 100644
--- a/src/bindings/scripts/scripts/creature/mob_generic_creature.cpp
+++ b/src/bindings/scripts/scripts/creature/mob_generic_creature.cpp
@@ -156,11 +156,41 @@ struct TRINITY_DLL_DECL generic_creatureAI : public ScriptedAI
}
}
};
+
CreatureAI* GetAI_generic_creature(Creature *_Creature)
{
return new generic_creatureAI (_Creature);
}
+struct TRINITY_DLL_DECL trigger_periodicAI : public NullCreatureAI
+{
+ trigger_periodicAI(Creature* c) : NullCreatureAI(c)
+ {
+ spell = me->m_spells[0] ? GetSpellStore()->LookupEntry(me->m_spells[0]) : NULL;
+ interval = me->m_spells[1] ? me->m_spells[1] : 1000;
+ timer = interval;
+ }
+
+ uint32 timer, interval;
+ const SpellEntry * spell;
+
+ void UpdateAI(const uint32 diff)
+ {
+ if(timer < diff)
+ {
+ if(spell)
+ me->CastSpell(me, spell, true);
+ timer = interval;
+ }
+ else
+ timer -= diff;
+ }
+};
+
+CreatureAI* GetAI_trigger_periodic(Creature *_Creature)
+{
+ return new trigger_periodicAI (_Creature);
+}
void AddSC_generic_creature()
{
@@ -169,5 +199,10 @@ void AddSC_generic_creature()
newscript->Name="generic_creature";
newscript->GetAI = &GetAI_generic_creature;
newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name="trigger_periodic";
+ newscript->GetAI = &GetAI_trigger_periodic;
+ newscript->RegisterSelf();
}
diff --git a/src/bindings/scripts/scripts/zone/aunchindoun/shadow_labyrinth/boss_grandmaster_vorpil.cpp b/src/bindings/scripts/scripts/zone/aunchindoun/shadow_labyrinth/boss_grandmaster_vorpil.cpp
index 89fd75b9bc8..52e5a3e8915 100644
--- a/src/bindings/scripts/scripts/zone/aunchindoun/shadow_labyrinth/boss_grandmaster_vorpil.cpp
+++ b/src/bindings/scripts/scripts/zone/aunchindoun/shadow_labyrinth/boss_grandmaster_vorpil.cpp
@@ -262,7 +262,7 @@ struct TRINITY_DLL_DECL boss_grandmaster_vorpilAI : public ScriptedAI
if (HeroicMode && banish_Timer < diff)
{
- Unit *target = SelectUnit(SELECT_TARGET_RANDOM,0,30,false);
+ Unit *target = SelectTarget(SELECT_TARGET_RANDOM,0,30,false);
if (target)
{
DoCast(target,SPELL_BANISH);
diff --git a/src/bindings/scripts/scripts/zone/aunchindoun/shadow_labyrinth/boss_murmur.cpp b/src/bindings/scripts/scripts/zone/aunchindoun/shadow_labyrinth/boss_murmur.cpp
index 99bce54be62..599767b591f 100644
--- a/src/bindings/scripts/scripts/zone/aunchindoun/shadow_labyrinth/boss_murmur.cpp
+++ b/src/bindings/scripts/scripts/zone/aunchindoun/shadow_labyrinth/boss_murmur.cpp
@@ -118,7 +118,7 @@ struct TRINITY_DLL_DECL boss_murmurAI : public Scripted_NoMovementAI
// Murmur's Touch
if (MurmursTouch_Timer < diff)
{
- if(Unit* target = SelectUnit(SELECT_TARGET_RANDOM,0,80,true))
+ if(Unit* target = SelectTarget(SELECT_TARGET_RANDOM,0,80,true))
DoCast(target, SPELL_MURMURS_TOUCH);
MurmursTouch_Timer = 25000 + rand()%10000;
}else MurmursTouch_Timer -= diff;
@@ -162,7 +162,7 @@ struct TRINITY_DLL_DECL boss_murmurAI : public Scripted_NoMovementAI
// Sonic Shock
if(SonicShock_Timer < diff)
{
- if(Unit* target = SelectUnit(SELECT_TARGET_RANDOM,0,20,false))
+ if(Unit* target = SelectTarget(SELECT_TARGET_RANDOM,0,20,false))
if(target->isAlive())
DoCast(target, SPELL_SONIC_SHOCK);
SonicShock_Timer = 10000+rand()%10000;
diff --git a/src/bindings/scripts/scripts/zone/aunchindoun/shadow_labyrinth/instance_shadow_labyrinth.cpp b/src/bindings/scripts/scripts/zone/aunchindoun/shadow_labyrinth/instance_shadow_labyrinth.cpp
index 3cfb0af2fa1..37194a89b21 100644
--- a/src/bindings/scripts/scripts/zone/aunchindoun/shadow_labyrinth/instance_shadow_labyrinth.cpp
+++ b/src/bindings/scripts/scripts/zone/aunchindoun/shadow_labyrinth/instance_shadow_labyrinth.cpp
@@ -191,7 +191,7 @@ struct TRINITY_DLL_DECL instance_shadow_labyrinth : public ScriptedInstance
return 0;
}
- const char* Save()
+ std::string GetSaveData()
{
return str_data.c_str();
}
diff --git a/src/bindings/scripts/scripts/zone/azjol_nerub/ahnkahet/instance_ahnkahet.cpp b/src/bindings/scripts/scripts/zone/azjol_nerub/ahnkahet/instance_ahnkahet.cpp
index 41cb91f86b7..595a05a727f 100644
--- a/src/bindings/scripts/scripts/zone/azjol_nerub/ahnkahet/instance_ahnkahet.cpp
+++ b/src/bindings/scripts/scripts/zone/azjol_nerub/ahnkahet/instance_ahnkahet.cpp
@@ -129,7 +129,7 @@ struct TRINITY_DLL_DECL instance_ahnkahet : public ScriptedInstance
return 0;
}
- const char* Save()
+ std::string GetSaveData()
{
OUT_SAVE_INST_DATA;
diff --git a/src/bindings/scripts/scripts/zone/azjol_nerub/azjol_nerub/instance_azjol_nerub.cpp b/src/bindings/scripts/scripts/zone/azjol_nerub/azjol_nerub/instance_azjol_nerub.cpp
index bd3fccd98d9..7e0252f2009 100644
--- a/src/bindings/scripts/scripts/zone/azjol_nerub/azjol_nerub/instance_azjol_nerub.cpp
+++ b/src/bindings/scripts/scripts/zone/azjol_nerub/azjol_nerub/instance_azjol_nerub.cpp
@@ -117,7 +117,7 @@ struct TRINITY_DLL_DECL instance_azjol_nerub : public ScriptedInstance
return 0;
}
- const char* Save()
+ std::string GetSaveData()
{
OUT_SAVE_INST_DATA;
diff --git a/src/bindings/scripts/scripts/zone/azuremyst_isle/azuremyst_isle.cpp b/src/bindings/scripts/scripts/zone/azuremyst_isle/azuremyst_isle.cpp
index 1a3c40273af..104ef575de5 100644
--- a/src/bindings/scripts/scripts/zone/azuremyst_isle/azuremyst_isle.cpp
+++ b/src/bindings/scripts/scripts/zone/azuremyst_isle/azuremyst_isle.cpp
@@ -416,7 +416,8 @@ bool GossipSelect_npc_susurrus(Player *player, Creature *_Creature, uint32 sende
nodes.resize(2);
nodes[0] = 92; //from susurrus
nodes[1] = 91; //end at exodar
- player->ActivateTaxiPathTo(nodes,11686); //TaxiPath 506. Using invisible model, possible Trinity must allow 0(from dbc) for cases like this.
+// player->ActivateTaxiPathTo(nodes,11686); //TaxiPath 506. Using invisible model, possible Trinity must allow 0(from dbc) for cases like this.
+ player->ActivateTaxiPathTo(nodes);
}
return true;
}
diff --git a/src/bindings/scripts/scripts/zone/black_temple/boss_illidan.cpp b/src/bindings/scripts/scripts/zone/black_temple/boss_illidan.cpp
index 60c51f0be33..68431cb81ee 100644
--- a/src/bindings/scripts/scripts/zone/black_temple/boss_illidan.cpp
+++ b/src/bindings/scripts/scripts/zone/black_temple/boss_illidan.cpp
@@ -785,7 +785,7 @@ struct TRINITY_DLL_DECL boss_illidan_stormrageAI : public ScriptedAI
case EVENT_PARASITIC_SHADOWFIEND:
{
- if(Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 1, 200, true))
+ if(Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 200, true))
m_creature->CastSpell(target, SPELL_PARASITIC_SHADOWFIEND, true);
Timer[EVENT_PARASITIC_SHADOWFIEND] = 35000 + rand()%10000;
}break;
@@ -907,7 +907,7 @@ struct TRINITY_DLL_DECL flame_of_azzinothAI : public ScriptedAI
void ChargeCheck()
{
- Unit* target = SelectUnit(SELECT_TARGET_FARTHEST, 0, 200, false);
+ Unit* target = SelectTarget(SELECT_TARGET_FARTHEST, 0, 200, false);
if(target && (!m_creature->IsWithinCombatRange(target, FLAME_CHARGE_DISTANCE)))
{
m_creature->AddThreat(target, 5000000.0f);
@@ -1765,7 +1765,7 @@ struct TRINITY_DLL_DECL mob_parasitic_shadowfiendAI : public ScriptedAI
{
if(!m_creature->getVictim())
{
- if(Unit *target = SelectUnit(SELECT_TARGET_RANDOM, 0, 999, true))
+ if(Unit *target = SelectTarget(SELECT_TARGET_RANDOM, 0, 999, true))
AttackStart(target);
else
{
@@ -1862,15 +1862,15 @@ void boss_illidan_stormrageAI::JustSummoned(Creature* summon)
summon->setDeathState(JUST_DIED);
return;
}
- Unit *target = SelectUnit(SELECT_TARGET_TOPAGGRO, 0, 999, true);
+ Unit *target = SelectTarget(SELECT_TARGET_TOPAGGRO, 0, 999, true);
if(!target || target->HasAura(SPELL_PARASITIC_SHADOWFIEND)
|| target->HasAura(SPELL_PARASITIC_SHADOWFIEND2))
- target = SelectUnit(SELECT_TARGET_RANDOM, 0, 999, true);
+ target = SelectTarget(SELECT_TARGET_RANDOM, 0, 999, true);
if(target)
summon->AI()->AttackStart(target);
}break;
case SHADOW_DEMON:
- if(Unit *target = SelectUnit(SELECT_TARGET_RANDOM, 0, 999, true)) // only on players.
+ if(Unit *target = SelectTarget(SELECT_TARGET_RANDOM, 0, 999, true)) // only on players.
{
summon->AddThreat(target, 5000000.0f);
summon->AI()->AttackStart(target);
diff --git a/src/bindings/scripts/scripts/zone/black_temple/boss_supremus.cpp b/src/bindings/scripts/scripts/zone/black_temple/boss_supremus.cpp
index c01db75bd58..ff90f7e6a81 100644
--- a/src/bindings/scripts/scripts/zone/black_temple/boss_supremus.cpp
+++ b/src/bindings/scripts/scripts/zone/black_temple/boss_supremus.cpp
@@ -53,7 +53,9 @@ EndScriptData */
struct TRINITY_DLL_DECL molten_flameAI : public NullCreatureAI
{
- molten_flameAI(Creature *c) : NullCreatureAI(c)
+ molten_flameAI(Creature *c) : NullCreatureAI(c) {}
+
+ void InitializeAI()
{
float x, y, z;
me->GetNearPoint(me, x, y, z, 1, 50, M_PI*2*rand_norm());
@@ -198,7 +200,7 @@ struct TRINITY_DLL_DECL boss_supremusAI : public ScriptedAI
events.ScheduleEvent(EVENT_HATEFUL_STRIKE, 5000, GCD_CAST, PHASE_STRIKE);
break;
case EVENT_SWITCH_TARGET:
- if(Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 1, 100, true))
+ if(Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true))
{
DoResetThreat();
m_creature->AddThreat(target, 5000000.0f);
@@ -208,7 +210,7 @@ struct TRINITY_DLL_DECL boss_supremusAI : public ScriptedAI
break;
case EVENT_VOLCANO:
{
- Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0, 999, true);
+ Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 999, true);
if(!target) target = m_creature->getVictim();
if(target)
{
diff --git a/src/bindings/scripts/scripts/zone/black_temple/boss_warlord_najentus.cpp b/src/bindings/scripts/scripts/zone/black_temple/boss_warlord_najentus.cpp
index 7d6b7140a9d..032bccc57ed 100644
--- a/src/bindings/scripts/scripts/zone/black_temple/boss_warlord_najentus.cpp
+++ b/src/bindings/scripts/scripts/zone/black_temple/boss_warlord_najentus.cpp
@@ -171,7 +171,7 @@ struct TRINITY_DLL_DECL boss_najentusAI : public ScriptedAI
{
//m_creature->CastSpell(m_creature, SPELL_NEEDLE_SPINE, true);
std::list<Unit*> target;
- SelectUnitList(target, 3, SELECT_TARGET_RANDOM, 80, true);
+ SelectTargetList(target, 3, SELECT_TARGET_RANDOM, 80, true);
for(std::list<Unit*>::iterator i = target.begin(); i != target.end(); ++i)
m_creature->CastSpell(*i, 39835, true);
events.ScheduleEvent(EVENT_NEEDLE, 15000+rand()%10000, GCD_CAST);
diff --git a/src/bindings/scripts/scripts/zone/black_temple/instance_black_temple.cpp b/src/bindings/scripts/scripts/zone/black_temple/instance_black_temple.cpp
index 43646746505..bf5d62a7b86 100644
--- a/src/bindings/scripts/scripts/zone/black_temple/instance_black_temple.cpp
+++ b/src/bindings/scripts/scripts/zone/black_temple/instance_black_temple.cpp
@@ -303,7 +303,7 @@ struct TRINITY_DLL_DECL instance_black_temple : public ScriptedInstance
return 0;
}
- const char* Save()
+ std::string GetSaveData()
{
return str_data.c_str();
}
diff --git a/src/bindings/scripts/scripts/zone/blackrock_depths/instance_blackrock_depths.cpp b/src/bindings/scripts/scripts/zone/blackrock_depths/instance_blackrock_depths.cpp
index 6e26f3a0c03..d9f3ecd808a 100644
--- a/src/bindings/scripts/scripts/zone/blackrock_depths/instance_blackrock_depths.cpp
+++ b/src/bindings/scripts/scripts/zone/blackrock_depths/instance_blackrock_depths.cpp
@@ -265,7 +265,7 @@ struct TRINITY_DLL_DECL instance_blackrock_depths : public ScriptedInstance
return 0;
}
- const char* Save()
+ std::string GetSaveData()
{
return str_data.c_str();
}
diff --git a/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/boss_anetheron.cpp b/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/boss_anetheron.cpp
index 21b39fa378b..13b0c78ebc1 100644
--- a/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/boss_anetheron.cpp
+++ b/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/boss_anetheron.cpp
@@ -148,7 +148,7 @@ struct TRINITY_DLL_DECL boss_anetheronAI : public hyjal_trashAI
if(SwarmTimer < diff)
{
- Unit* target = SelectUnit(SELECT_TARGET_RANDOM,0,100,true);
+ Unit* target = SelectTarget(SELECT_TARGET_RANDOM,0,100,true);
if(target)
DoCast(target,SPELL_CARRION_SWARM);
@@ -170,7 +170,7 @@ struct TRINITY_DLL_DECL boss_anetheronAI : public hyjal_trashAI
{
for(uint8 i=0;i<3;++i)
{
- Unit* target = SelectUnit(SELECT_TARGET_RANDOM,0,100,true);
+ Unit* target = SelectTarget(SELECT_TARGET_RANDOM,0,100,true);
if(target)
target->CastSpell(target,SPELL_SLEEP,true);
}
@@ -194,7 +194,7 @@ struct TRINITY_DLL_DECL boss_anetheronAI : public hyjal_trashAI
}else AuraTimer -= diff;
if(InfernoTimer < diff)
{
- DoCast(SelectUnit(SELECT_TARGET_RANDOM,0,100,true), SPELL_INFERNO);
+ DoCast(SelectTarget(SELECT_TARGET_RANDOM,0,100,true), SPELL_INFERNO);
InfernoTimer = 45000;
switch(rand()%2)
{
diff --git a/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/boss_azgalor.cpp b/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/boss_azgalor.cpp
index 15085963b20..33e3d344da2 100644
--- a/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/boss_azgalor.cpp
+++ b/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/boss_azgalor.cpp
@@ -140,13 +140,13 @@ struct TRINITY_DLL_DECL boss_azgalorAI : public hyjal_trashAI
if(RainTimer < diff)
{
- DoCast(SelectUnit(SELECT_TARGET_RANDOM,0,30,true), SPELL_RAIN_OF_FIRE);
+ DoCast(SelectTarget(SELECT_TARGET_RANDOM,0,30,true), SPELL_RAIN_OF_FIRE);
RainTimer = 20000+rand()%15000;
}else RainTimer -= diff;
if(DoomTimer < diff)
{
- DoCast(SelectUnit(SELECT_TARGET_RANDOM,1,100,true), SPELL_DOOM);//never on tank
+ DoCast(SelectTarget(SELECT_TARGET_RANDOM,1,100,true), SPELL_DOOM);//never on tank
DoomTimer = 45000+rand()%5000;
}else DoomTimer -= diff;
@@ -260,7 +260,7 @@ struct TRINITY_DLL_DECL mob_lesser_doomguardAI : public hyjal_trashAI
if(CrippleTimer < diff)
{
- DoCast(SelectUnit(SELECT_TARGET_RANDOM,0,100,true), SPELL_CRIPPLE);
+ DoCast(SelectTarget(SELECT_TARGET_RANDOM,0,100,true), SPELL_CRIPPLE);
CrippleTimer = 25000+rand()%5000;
}else CrippleTimer -= diff;
diff --git a/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/boss_rage_winterchill.cpp b/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/boss_rage_winterchill.cpp
index addbddab5b8..3e6b2bc8e98 100644
--- a/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/boss_rage_winterchill.cpp
+++ b/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/boss_rage_winterchill.cpp
@@ -169,7 +169,7 @@ struct TRINITY_DLL_DECL boss_rage_winterchillAI : public hyjal_trashAI
}else NovaTimer -= diff;
if(IceboltTimer < diff)
{
- DoCast(SelectUnit(SELECT_TARGET_RANDOM,0,40,true), SPELL_ICEBOLT);
+ DoCast(SelectTarget(SELECT_TARGET_RANDOM,0,40,true), SPELL_ICEBOLT);
IceboltTimer = 11000+rand()%20000;
}else IceboltTimer -= diff;
diff --git a/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/hyjal_trash.cpp b/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/hyjal_trash.cpp
index 583c7831af5..30f0c14caaf 100644
--- a/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/hyjal_trash.cpp
+++ b/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/hyjal_trash.cpp
@@ -724,7 +724,7 @@ struct mob_necromancerAI : public hyjal_trashAI
void JustSummoned(Creature* summon)
{
- Unit* target = SelectUnit(SELECT_TARGET_RANDOM,0,30,true);
+ Unit* target = SelectTarget(SELECT_TARGET_RANDOM,0,30,true);
if(target && summon)
summon->Attack(target,false);
summons.Summon(summon);
diff --git a/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/instance_hyjal.cpp b/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/instance_hyjal.cpp
index 0dfa99198ac..cdcd6cb6b66 100644
--- a/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/instance_hyjal.cpp
+++ b/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/instance_hyjal.cpp
@@ -279,7 +279,7 @@ struct TRINITY_DLL_DECL instance_mount_hyjal : public ScriptedInstance
}else debug_log("TSCR: Instance Hyjal: UpdateWorldState, but PlayerList is empty!");
}
- const char* Save()
+ std::string GetSaveData()
{
return str_data.c_str();
}
diff --git a/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_lurker_below.cpp b/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_lurker_below.cpp
index eb35a3c74b4..254a4d1d899 100644
--- a/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_lurker_below.cpp
+++ b/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_lurker_below.cpp
@@ -322,7 +322,7 @@ struct TRINITY_DLL_DECL boss_the_lurker_belowAI : public Scripted_NoMovementAI
if(WaterboltTimer < diff)
{
- Unit* target = SelectUnit(SELECT_TARGET_NEAREST,0,14,true);
+ Unit* target = SelectTarget(SELECT_TARGET_NEAREST,0,14,true);
if(!target)
{
target = SelectUnit(SELECT_TARGET_RANDOM,0);
diff --git a/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_morogrim_tidewalker.cpp b/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_morogrim_tidewalker.cpp
index cea591182d5..f8d27df5bb0 100644
--- a/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_morogrim_tidewalker.cpp
+++ b/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_morogrim_tidewalker.cpp
@@ -235,7 +235,7 @@ struct TRINITY_DLL_DECL boss_morogrim_tidewalkerAI : public ScriptedAI
for(uint8 i = 0; i < 4; i++)
{
counter = 0;
- do{target = SelectUnit(SELECT_TARGET_RANDOM, 1, 50, true); //target players only
+ do{target = SelectTarget(SELECT_TARGET_RANDOM, 1, 50, true); //target players only
if(counter < Playercount)
break;
if(target) itr = list.find(target->GetGUID());
@@ -272,7 +272,7 @@ struct TRINITY_DLL_DECL boss_morogrim_tidewalkerAI : public ScriptedAI
for (int8 g = 0; g < 4; g++) //one unit cant cast more than one spell per update, so some players have to cast for us XD
{
counter = 0;
- do {globuletarget = SelectUnit(SELECT_TARGET_RANDOM, 0,50,true);
+ do {globuletarget = SelectTarget(SELECT_TARGET_RANDOM, 0,50,true);
if(globuletarget) itr = globulelist.find(globuletarget->GetGUID());
if (counter > Playercount)
break;
diff --git a/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/instance_serpent_shrine.cpp b/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/instance_serpent_shrine.cpp
index 6c4ae72aec1..8aa759a87c8 100644
--- a/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/instance_serpent_shrine.cpp
+++ b/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/instance_serpent_shrine.cpp
@@ -236,7 +236,7 @@ struct TRINITY_DLL_DECL instance_serpentshrine_cavern : public ScriptedInstance
}
return 0;
}
- const char* Save()
+ std::string GetSaveData()
{
OUT_SAVE_INST_DATA;
std::ostringstream stream;
diff --git a/src/bindings/scripts/scripts/zone/coilfang_resevoir/steam_vault/instance_steam_vault.cpp b/src/bindings/scripts/scripts/zone/coilfang_resevoir/steam_vault/instance_steam_vault.cpp
index 6d01da7f625..d375d073c35 100644
--- a/src/bindings/scripts/scripts/zone/coilfang_resevoir/steam_vault/instance_steam_vault.cpp
+++ b/src/bindings/scripts/scripts/zone/coilfang_resevoir/steam_vault/instance_steam_vault.cpp
@@ -209,7 +209,7 @@ struct TRINITY_DLL_DECL instance_steam_vault : public ScriptedInstance
return 0;
}
- const char* Save()
+ std::string GetSaveData()
{
OUT_SAVE_INST_DATA;
std::ostringstream stream;
diff --git a/src/bindings/scripts/scripts/zone/coilfang_resevoir/underbog/boss_the_black_stalker.cpp b/src/bindings/scripts/scripts/zone/coilfang_resevoir/underbog/boss_the_black_stalker.cpp
index 370b07c8adc..72c7992e109 100644
--- a/src/bindings/scripts/scripts/zone/coilfang_resevoir/underbog/boss_the_black_stalker.cpp
+++ b/src/bindings/scripts/scripts/zone/coilfang_resevoir/underbog/boss_the_black_stalker.cpp
@@ -165,7 +165,7 @@ struct TRINITY_DLL_DECL boss_the_black_stalkerAI : public ScriptedAI
// Static Charge
if(StaticCharge_Timer < diff)
{
- if(Unit *target = SelectUnit(SELECT_TARGET_RANDOM,0,30,true))
+ if(Unit *target = SelectTarget(SELECT_TARGET_RANDOM,0,30,true))
DoCast(target, SPELL_STATIC_CHARGE);
StaticCharge_Timer = 10000;
}else StaticCharge_Timer -= diff;
diff --git a/src/bindings/scripts/scripts/zone/gruuls_lair/instance_gruuls_lair.cpp b/src/bindings/scripts/scripts/zone/gruuls_lair/instance_gruuls_lair.cpp
index 34943449b1e..4c90fdf49a8 100644
--- a/src/bindings/scripts/scripts/zone/gruuls_lair/instance_gruuls_lair.cpp
+++ b/src/bindings/scripts/scripts/zone/gruuls_lair/instance_gruuls_lair.cpp
@@ -144,7 +144,7 @@ struct TRINITY_DLL_DECL instance_gruuls_lair : public ScriptedInstance
return 0;
}
- const char* Save()
+ std::string GetSaveData()
{
OUT_SAVE_INST_DATA;
std::ostringstream stream;
diff --git a/src/bindings/scripts/scripts/zone/karazhan/boss_moroes.cpp b/src/bindings/scripts/scripts/zone/karazhan/boss_moroes.cpp
index 115dfeab269..52e6f2e363c 100644
--- a/src/bindings/scripts/scripts/zone/karazhan/boss_moroes.cpp
+++ b/src/bindings/scripts/scripts/zone/karazhan/boss_moroes.cpp
@@ -1,4 +1,4 @@
-/* Copyright (C) 2006 - 2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
+/* Copyright (C) 2006 - 2008 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
* 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
@@ -62,7 +62,10 @@ struct TRINITY_DLL_DECL boss_moroesAI : public ScriptedAI
{
boss_moroesAI(Creature *c) : ScriptedAI(c)
{
- FirstTime = true;
+ for(int i = 0; i < 4; i++)
+ {
+ AddId[i] = 0;
+ }
pInstance = ((ScriptedInstance*)c->GetInstanceData());
}
@@ -77,7 +80,6 @@ struct TRINITY_DLL_DECL boss_moroesAI : public ScriptedAI
uint32 CheckAdds_Timer;
uint32 AddId[4];
- bool FirstTime;
bool InVanish;
bool Enrage;
@@ -91,12 +93,10 @@ struct TRINITY_DLL_DECL boss_moroesAI : public ScriptedAI
Enrage = false;
InVanish = false;
-
- SpawnAdds();
-
- m_creature->setFaction(16);
- m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ if(m_creature->GetHealth() > 0)
+ {
+ SpawnAdds();
+ }
if(pInstance)
pInstance->SetData(DATA_MOROES_EVENT, NOT_STARTED);
@@ -106,9 +106,11 @@ struct TRINITY_DLL_DECL boss_moroesAI : public ScriptedAI
{
if(pInstance)
pInstance->SetData(DATA_MOROES_EVENT, IN_PROGRESS);
+
+ DoZoneInCombat();
}
- void EnterCombat(Unit* who)
+ void Aggro(Unit* who)
{
StartEvent();
@@ -129,7 +131,7 @@ struct TRINITY_DLL_DECL boss_moroesAI : public ScriptedAI
void JustDied(Unit* victim)
{
- DoScriptText(SAY_DEATH, m_creature);
+ DoScriptText(SAY_DEATH, m_creature);
if (pInstance)
pInstance->SetData(DATA_MOROES_EVENT, DONE);
@@ -147,33 +149,21 @@ struct TRINITY_DLL_DECL boss_moroesAI : public ScriptedAI
for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
{
- if (i->getSource()->isAlive() && i->getSource()->HasAura(SPELL_GARROTE))
+ if (i->getSource()->isAlive() && i->getSource()->HasAura(SPELL_GARROTE,0))
i->getSource()->RemoveAurasDueToSpell(SPELL_GARROTE);
}
}
}
- uint8 CheckAdd(uint64 guid)
- {
- Unit* pUnit = Unit::GetUnit((*m_creature), guid);
- if (pUnit)
- {
- if (!pUnit->isAlive())
- return 1; // Exists but is dead
- else
- return 2; // Exists and is alive
- }
- return 0; // Does not exist
- }
-
void SpawnAdds()
{
- Creature *pCreature = NULL;
-
- if (FirstTime)
+ DeSpawnAdds();
+ if(isAddlistEmpty())
{
+ Creature *pCreature = NULL;
std::vector<uint32> AddList;
+
for(uint8 i = 0; i < 6; ++i)
AddList.push_back(Adds[i]);
@@ -193,48 +183,44 @@ struct TRINITY_DLL_DECL boss_moroesAI : public ScriptedAI
}
++i;
}
-
- FirstTime = false;
- }
- else
+ }else
{
- for(uint8 i = 0; i < 4; ++i)
+ for(int i = 0; i < 4; i++)
{
- switch(CheckAdd(AddGUID[i]))
+ Creature *pCreature = m_creature->SummonCreature(AddId[i], Locations[i][0], Locations[i][1], POS_Z, Locations[i][2], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000);
+ if (pCreature)
{
- case 0:
- pCreature = m_creature->SummonCreature(AddId[i], Locations[i][0], Locations[i][1], POS_Z, Locations[i][2], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000);
- if (pCreature)
- AddGUID[i] = pCreature->GetGUID();
- break;
- case 1:
- pCreature = (Unit::GetCreature((*m_creature), AddGUID[i]));
- if (pCreature)
- {
- pCreature->Respawn();
- pCreature->AI()->EnterEvadeMode();
- }
- break;
- case 2:
- pCreature = (Unit::GetCreature((*m_creature), AddGUID[i]));
- if (!pCreature->IsInEvadeMode())
- pCreature->AI()->EnterEvadeMode();
- break;
+ AddGUID[i] = pCreature->GetGUID();
}
}
}
}
+ bool isAddlistEmpty()
+ {
+ for(int i = 0; i < 4; i++)
+ {
+ if(AddId[i] == 0)
+ return true;
+ }
+ return false;
+ }
+
void DeSpawnAdds()
{
for(uint8 i = 0; i < 4 ; ++i)
{
- Unit* Temp = NULL;
+ Creature* Temp = NULL;
if (AddGUID[i])
{
- Temp = Unit::GetUnit((*m_creature),AddGUID[i]);
+ Temp = Creature::GetCreature((*m_creature),AddGUID[i]);
if (Temp && Temp->isAlive())
+ {
+ (*Temp).GetMotionMaster()->Clear(true);
Temp->DealDamage(Temp, Temp->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
+ Temp->RemoveCorpse();
+ }
+
}
}
}
@@ -246,7 +232,7 @@ struct TRINITY_DLL_DECL boss_moroesAI : public ScriptedAI
Creature* Temp = NULL;
if (AddGUID[i])
{
- Temp = Unit::GetCreature(*m_creature, AddGUID[i]);
+ Temp = Creature::GetCreature((*m_creature),AddGUID[i]);
if (Temp && Temp->isAlive())
{
Temp->AI()->AttackStart(m_creature->getVictim());
@@ -295,39 +281,12 @@ struct TRINITY_DLL_DECL boss_moroesAI : public ScriptedAI
//Cast Vanish, then Garrote random victim
if (Vanish_Timer < diff)
{
- m_creature->setFaction(35);
- m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
DoCast(m_creature, SPELL_VANISH);
InVanish = true;
Vanish_Timer = 30000;
Wait_Timer = 5000;
}else Vanish_Timer -= diff;
- if (InVanish)
- {
- if (Wait_Timer < diff)
- {
- switch(rand()%2)
- {
- case 0: DoScriptText(SAY_SPECIAL_1, m_creature); break;
- case 1: DoScriptText(SAY_SPECIAL_2, m_creature); break;
- }
-
- if (Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0))
- target->CastSpell(target, SPELL_GARROTE,true);
-
- m_creature->setFaction(16);
- m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
- m_creature->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true);
- m_creature->ApplySpellImmune(0, IMMUNITY_EFFECT,SPELL_EFFECT_ATTACK_ME, true);
- m_creature->AI()->AttackStart(m_creature->getVictim());
- InVanish = false;
- }else Wait_Timer -= diff;
- }
-
- //Gouge highest aggro, and attack second highest
if (Gouge_Timer < diff)
{
DoCast(m_creature->getVictim(), SPELL_GOUGE);
@@ -336,27 +295,32 @@ struct TRINITY_DLL_DECL boss_moroesAI : public ScriptedAI
if (Blind_Timer < diff)
{
- Unit* target = NULL;
- std::list<HostilReference*> t_list = m_creature->getThreatManager().getThreatList();
-
- if (t_list.empty())
- return;
+ Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0);
+ if (target && target->GetTypeId() == TYPEID_PLAYER && m_creature->IsWithinMeleeRange(target))
+ {
+ DoCast(target, SPELL_BLIND);
+ Blind_Timer = 40000;
+ }
+ else
+ Blind_Timer = 1000;
+ }else Blind_Timer -= diff;
+ }
- std::vector<Unit*> target_list;
- for (std::list<HostilReference*>::iterator itr = t_list.begin(); itr!= t_list.end(); ++itr)
+ if (InVanish)
+ {
+ if (Wait_Timer < diff)
+ {
+ switch(rand()%2)
{
- target = Unit::GetUnit(*m_creature, (*itr)->getUnitGuid());
- if (target && target->GetDistance2d(m_creature) < 5)
- target_list.push_back(target);
+ case 0: DoScriptText(SAY_SPECIAL_1, m_creature); break;
+ case 1: DoScriptText(SAY_SPECIAL_2, m_creature); break;
}
- if (target_list.size())
- target = *(target_list.begin()+rand()%target_list.size());
- if (target)
- DoCast(target, SPELL_BLIND);
+ if (Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0))
+ target->CastSpell(target, SPELL_GARROTE,true);
- Blind_Timer = 40000;
- }else Blind_Timer -= diff;
+ InVanish = false;
+ }else Wait_Timer -= diff;
}
if (!InVanish)
@@ -384,7 +348,7 @@ struct TRINITY_DLL_DECL boss_moroes_guestAI : public ScriptedAI
pInstance->SetData(DATA_MOROES_EVENT, NOT_STARTED);
}
- void EnterCombat(Unit* who) {}
+ void Aggro(Unit* who) {}
void AcquireGUID()
{
@@ -542,7 +506,7 @@ struct TRINITY_DLL_DECL boss_baron_rafe_dreugerAI : public boss_moroes_guestAI
struct TRINITY_DLL_DECL boss_lady_catriona_von_indiAI : public boss_moroes_guestAI
{
//Holy Priest
- boss_lady_catriona_von_indiAI(Creature *c) : boss_moroes_guestAI(c) {Reset();}
+ boss_lady_catriona_von_indiAI(Creature *c) : boss_moroes_guestAI(c) {}
uint32 DispelMagic_Timer;
uint32 GreaterHeal_Timer;
@@ -612,7 +576,7 @@ struct TRINITY_DLL_DECL boss_lady_catriona_von_indiAI : public boss_moroes_guest
struct TRINITY_DLL_DECL boss_lady_keira_berrybuckAI : public boss_moroes_guestAI
{
//Holy Pally
- boss_lady_keira_berrybuckAI(Creature *c) : boss_moroes_guestAI(c) {Reset();}
+ boss_lady_keira_berrybuckAI(Creature *c) : boss_moroes_guestAI(c) {}
uint32 Cleanse_Timer;
uint32 GreaterBless_Timer;
@@ -729,7 +693,7 @@ struct TRINITY_DLL_DECL boss_lord_robin_darisAI : public boss_moroes_guestAI
struct TRINITY_DLL_DECL boss_lord_crispin_ferenceAI : public boss_moroes_guestAI
{
//Arms Warr
- boss_lord_crispin_ferenceAI(Creature *c) : boss_moroes_guestAI(c) {Reset();}
+ boss_lord_crispin_ferenceAI(Creature *c) : boss_moroes_guestAI(c) {}
uint32 Disarm_Timer;
uint32 HeroicStrike_Timer;
diff --git a/src/bindings/scripts/scripts/zone/karazhan/instance_karazhan.cpp b/src/bindings/scripts/scripts/zone/karazhan/instance_karazhan.cpp
index e8dccdd62a4..62ad6fcf42c 100644
--- a/src/bindings/scripts/scripts/zone/karazhan/instance_karazhan.cpp
+++ b/src/bindings/scripts/scripts/zone/karazhan/instance_karazhan.cpp
@@ -247,7 +247,7 @@ struct TRINITY_DLL_DECL instance_karazhan : public ScriptedInstance
}
}
- const char* Save()
+ std::string GetSaveData()
{
return str_data.c_str();
}
diff --git a/src/bindings/scripts/scripts/zone/naxxramas/boss_anubrekhan.cpp b/src/bindings/scripts/scripts/zone/naxxramas/boss_anubrekhan.cpp
index 0a0fb17cce4..c675c8d7c27 100644
--- a/src/bindings/scripts/scripts/zone/naxxramas/boss_anubrekhan.cpp
+++ b/src/bindings/scripts/scripts/zone/naxxramas/boss_anubrekhan.cpp
@@ -1,4 +1,4 @@
-/* Copyright (C) 2006 - 2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
+/* Copyright (C) 2008 - 2009 Trinity <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
@@ -14,14 +14,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-/* ScriptData
-SDName: Boss_Anubrekhan
-SD%Complete: 100
-SDComment:
-SDCategory: Naxxramas
-EndScriptData */
-
#include "precompiled.h"
+#include "def_naxxramas.h"
#define SAY_GREET RAND(-1533000,-1533004,-1533005,-1533006,-1533007)
#define SAY_AGGRO RAND(-1533001,-1533002,-1533003)
@@ -31,46 +25,29 @@ EndScriptData */
#define SPELL_LOCUSTSWARM HEROIC(28785,54021)
#define SPELL_SELF_SPAWN_5 29105 //This spawns 5 corpse scarabs ontop of us (most likely the player casts this on death)
-#define SPELL_SELF_SPAWN_10 28864 //This is used by the crypt guards when they die
#define EVENT_IMPALE 1
#define EVENT_LOCUST 2
#define MOB_CRYPT_GUARD 16573
-struct TRINITY_DLL_DECL boss_anubrekhanAI : public ScriptedAI
+struct TRINITY_DLL_DECL boss_anubrekhanAI : public BossAI
{
- boss_anubrekhanAI(Creature *c) : ScriptedAI(c), summons(me) {}
+ boss_anubrekhanAI(Creature *c) : BossAI(c, BOSS_ANUBREKHAN) {}
bool HasTaunted;
- EventMap events;
- SummonList summons;
void Prepare()
{
HasTaunted = false;
- DoSpawnCreature(MOB_CRYPT_GUARD, 0, 10, 0, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 60000);
+ DoSpawnCreature(MOB_CRYPT_GUARD, 0, 10, 0, me->GetOrientation(), TEMPSUMMON_CORPSE_TIMED_DESPAWN, 60000);
if(HeroicMode)
- DoSpawnCreature(MOB_CRYPT_GUARD, 0, -10, 0, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 60000);
+ DoSpawnCreature(MOB_CRYPT_GUARD, 0, -10, 0, me->GetOrientation(), TEMPSUMMON_CORPSE_TIMED_DESPAWN, 60000);
}
void InitializeAI() { Prepare(); }
void JustReachedHome() { Prepare(); }
- void Reset()
- {
- events.Reset();
- summons.DespawnAll();
- }
-
- void JustSummoned(Creature *summon)
- {
- summons.Summon(summon);
- DoZoneInCombat(summon);
- }
-
- void SummonedCreatureDespawn(Creature *summon) {summons.Despawn(summon);}
-
void KilledUnit(Unit* victim)
{
//Force the player to spawn corpse scarabs via spell
@@ -82,9 +59,8 @@ struct TRINITY_DLL_DECL boss_anubrekhanAI : public ScriptedAI
void EnterCombat(Unit *who)
{
+ _EnterCombat();
DoScriptText(SAY_AGGRO, me);
- DoZoneInCombat();
-
events.ScheduleEvent(EVENT_IMPALE, 15000, 1);
events.ScheduleEvent(EVENT_LOCUST, 80000 + rand()%40000, 1);
}
diff --git a/src/bindings/scripts/scripts/zone/naxxramas/boss_faerlina.cpp b/src/bindings/scripts/scripts/zone/naxxramas/boss_faerlina.cpp
index 5ec67a8920b..9ee594b02b5 100644
--- a/src/bindings/scripts/scripts/zone/naxxramas/boss_faerlina.cpp
+++ b/src/bindings/scripts/scripts/zone/naxxramas/boss_faerlina.cpp
@@ -1,4 +1,6 @@
-/* Copyright (C) 2006 - 2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
+/*
+ * Copyright (C) 2008 - 2009 Trinity <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
@@ -14,83 +16,63 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-/* ScriptData
-SDName: Boss_Faerlina
-SD%Complete: 50
-SDComment:
-SDCategory: Naxxramas
-EndScriptData */
-
#include "precompiled.h"
+#include "def_naxxramas.h"
-#define SAY_GREET -1533009
-#define SAY_AGGRO1 -1533010
-#define SAY_AGGRO2 -1533011
-#define SAY_AGGRO3 -1533012
-#define SAY_AGGRO4 -1533013
-#define SAY_SLAY1 -1533014
-#define SAY_SLAY2 -1533015
-#define SAY_DEATH -1533016
+#define SAY_GREET -1533009
+#define SAY_AGGRO RAND(-1533010,-1533011,-1533012,-1533013)
+#define SAY_SLAY RAND(-1533014,-1533015)
+#define SAY_DEATH -1533016
//#define SOUND_RANDOM_AGGRO 8955 //soundId containing the 4 aggro sounds, we not using this
-#define SPELL_POSIONBOLT_VOLLEY 28796
-#define H_SPELL_POSIONBOLT_VOLLEY 54098
-#define SPELL_ENRAGE 28798
-#define H_SPELL_ENRAGE 54100
-#define SPELL_RAINOFFIRE 28794 //Not sure if targeted AoEs work if casted directly upon a player
+#define SPELL_POSION_BOLT_VOLLEY HEROIC(28796,54098)
+#define SPELL_RAIN_OF_FIRE HEROIC(28794,54099)
+#define SPELL_FRENZY HEROIC(28798,54100)
+#define SPELL_WIDOWS_EMBRACE HEROIC(28732,54097)
-struct TRINITY_DLL_DECL boss_faerlinaAI : public ScriptedAI
+enum Events
{
- boss_faerlinaAI(Creature *c) : ScriptedAI(c) {}
+ EVENT_POSION = 1,
+ EVENT_FIRE,
+ EVENT_FRENZY,
+};
- uint32 PoisonBoltVolley_Timer;
- uint32 RainOfFire_Timer;
- uint32 Enrage_Timer;
- bool HasTaunted;
+struct TRINITY_DLL_DECL boss_faerlinaAI : public BossAI
+{
+ boss_faerlinaAI(Creature *c) : BossAI(c, BOSS_FAERLINA), greet(false) {}
- void Reset()
- {
- PoisonBoltVolley_Timer = 8000;
- RainOfFire_Timer = 16000;
- Enrage_Timer = 60000;
- HasTaunted = false;
- }
+ bool greet;
void EnterCombat(Unit *who)
{
- switch (rand()%4)
- {
- case 0: DoScriptText(SAY_AGGRO1, m_creature); break;
- case 1: DoScriptText(SAY_AGGRO2, m_creature); break;
- case 2: DoScriptText(SAY_AGGRO3, m_creature); break;
- case 3: DoScriptText(SAY_AGGRO4, m_creature); break;
- }
+ _EnterCombat();
+ DoScriptText(SAY_AGGRO, me);
+ events.ScheduleEvent(EVENT_POSION, 10000 + rand()%15000);
+ events.ScheduleEvent(EVENT_FIRE, 5000 + rand()%15000);
+ events.ScheduleEvent(EVENT_FRENZY, 60000 + rand()%20000);
}
void MoveInLineOfSight(Unit *who)
{
- if (!HasTaunted && m_creature->IsWithinDistInMap(who, 60.0f))
- {
- DoScriptText(SAY_GREET, m_creature);
- HasTaunted = true;
-
+ if(!greet)
+ {
+ DoScriptText(SAY_GREET, me);
+ greet = true;
}
- ScriptedAI::MoveInLineOfSight(who);
+ BossAI::MoveInLineOfSight(who);
}
void KilledUnit(Unit* victim)
{
- switch (rand()%2)
- {
- case 0: DoScriptText(SAY_SLAY1, m_creature); break;
- case 1: DoScriptText(SAY_SLAY2, m_creature); break;
- }
+ if(!(rand()%3))
+ DoScriptText(SAY_SLAY, me);
}
void JustDied(Unit* Killer)
{
- DoScriptText(SAY_DEATH, m_creature);
+ _JustDied();
+ DoScriptText(SAY_DEATH, me);
}
void UpdateAI(const uint32 diff)
@@ -98,31 +80,33 @@ struct TRINITY_DLL_DECL boss_faerlinaAI : public ScriptedAI
if (!UpdateVictim())
return;
- //PoisonBoltVolley_Timer
- if (PoisonBoltVolley_Timer < diff)
- {
- DoCast(m_creature->getVictim(),SPELL_POSIONBOLT_VOLLEY);
- PoisonBoltVolley_Timer = 11000;
- }else PoisonBoltVolley_Timer -= diff;
+ events.Update(diff);
- //RainOfFire_Timer
- if (RainOfFire_Timer < diff)
+ while(uint32 eventId = events.ExecuteEvent())
{
- if (Unit* target = SelectUnit(SELECT_TARGET_RANDOM,0))
- DoCast(target,SPELL_RAINOFFIRE);
- RainOfFire_Timer = 16000;
- }else RainOfFire_Timer -= diff;
-
- //Enrage_Timer
- if (Enrage_Timer < diff)
- {
- DoCast(m_creature,SPELL_ENRAGE);
- Enrage_Timer = 61000;
- }else Enrage_Timer -= diff;
+ switch(eventId)
+ {
+ case EVENT_POSION:
+ if(!me->HasAura(SPELL_WIDOWS_EMBRACE))
+ DoCastAOE(SPELL_POSION_BOLT_VOLLEY);
+ events.ScheduleEvent(EVENT_POSION, 10000 + rand()%15000);
+ return;
+ case EVENT_FIRE:
+ if(Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0))
+ DoCast(target, SPELL_RAIN_OF_FIRE);
+ events.ScheduleEvent(EVENT_FIRE, 5000 + rand()%15000);
+ return;
+ case EVENT_FRENZY:
+ DoCast(me,SPELL_FRENZY);
+ events.ScheduleEvent(EVENT_FRENZY, 60000 + rand()%20000);
+ return;
+ }
+ }
DoMeleeAttackIfReady();
}
};
+
CreatureAI* GetAI_boss_faerlina(Creature *_Creature)
{
return new boss_faerlinaAI (_Creature);
@@ -136,4 +120,3 @@ void AddSC_boss_faerlina()
newscript->GetAI = &GetAI_boss_faerlina;
newscript->RegisterSelf();
}
-
diff --git a/src/bindings/scripts/scripts/zone/naxxramas/boss_gothik.cpp b/src/bindings/scripts/scripts/zone/naxxramas/boss_gothik.cpp
index 0becff399da..7def6c370f4 100644
--- a/src/bindings/scripts/scripts/zone/naxxramas/boss_gothik.cpp
+++ b/src/bindings/scripts/scripts/zone/naxxramas/boss_gothik.cpp
@@ -1,4 +1,4 @@
-/* Copyright (C) 2006 - 2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
+/* Copyright (C) 2008 - 2009 Trinity <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
@@ -14,14 +14,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-/* ScriptData
-SDName: Boss_Gothik
-SD%Complete: 0
-SDComment: Placeholder
-SDCategory: Naxxramas
-EndScriptData */
-
#include "precompiled.h"
+#include "def_naxxramas.h"
#define SAY_SPEECH -1533040
#define SAY_KILL -1533041
@@ -29,36 +23,336 @@ EndScriptData */
#define SAY_TELEPORT -1533043
//Gothik
-#define SPELL_HARVESTSOUL 28679
-#define SPELL_SHADOWBOLT 29317
-#define H_SPELL_SHADOWBOLT 56405
-//Unrelenting Trainee
-#define SPELL_EAGLECLAW 30285
-#define SPELL_KNOCKDOWN_PASSIVE 6961
-
-//Unrelenting Deathknight
-#define SPELL_CHARGE 22120
-#define SPELL_SHADOW_MARK 27825
-
-//Unrelenting Rider
-#define SPELL_UNHOLY_AURA 55606
-#define H_SPELL_UNHOLY_AURA 55608
-#define SPELL_SHADOWBOLT_VOLLEY 27831 //Search thru targets and find those who have the SHADOW_MARK to cast this on
-#define H_SPELL_SHADOWBOLT_VOLLEY 55638
-
-//Spectral Trainee
-#define SPELL_ARCANE_EXPLOSION 27989
-
-//Spectral Deathknight
-#define SPELL_WHIRLWIND 28334
-#define SPELL_SUNDER_ARMOR 25051 //cannot find sunder that reduces armor by 2950
-#define SPELL_CLEAVE 20677
-#define SPELL_MANA_BURN 17631
-
-//Spectral Rider
-#define SPELL_LIFEDRAIN 24300
-//USES SAME UNHOLY AURA AS UNRELENTING RIDER
-
-//Spectral Horse
-#define SPELL_STOMP 27993
+#define SPELL_HARVEST_SOUL 28679
+#define SPELL_SHADOW_BOLT HEROIC(29317,56405)
+
+#define SPELL_INFORM_LIVE_TRAINEE 27892
+#define SPELL_INFORM_LIVE_KNIGHT 27928
+#define SPELL_INFORM_LIVE_RIDER 27935
+#define SPELL_INFORM_DEAD_TRAINEE 27915
+#define SPELL_INFORM_DEAD_KNIGHT 27931
+#define SPELL_INFORM_DEAD_RIDER 27937
+
+#define MOB_LIVE_TRAINEE 16124
+#define MOB_LIVE_KNIGHT 16125
+#define MOB_LIVE_RIDER 16126
+#define MOB_DEAD_TRAINEE 16127
+#define MOB_DEAD_KNIGHT 16148
+#define MOB_DEAD_RIDER 16150
+#define MOB_DEAD_HORSE 16149
+
+const struct Waves { uint32 entry, number, time; }
+waves[] =
+{
+ {MOB_LIVE_TRAINEE, 2, 20000},
+ {MOB_LIVE_TRAINEE, 2, 20000},
+ {MOB_LIVE_TRAINEE, 2, 10000},
+ {MOB_LIVE_KNIGHT, 1, 10000},
+ {MOB_LIVE_TRAINEE, 2, 15000},
+ {MOB_LIVE_KNIGHT, 1, 10000},
+ {MOB_LIVE_TRAINEE, 2, 15000},
+ {MOB_LIVE_TRAINEE, 2, 0},
+ {MOB_LIVE_KNIGHT, 1, 10000},
+ {MOB_LIVE_RIDER, 1, 10000},
+ {MOB_LIVE_TRAINEE, 2, 5000},
+ {MOB_LIVE_KNIGHT, 1, 15000},
+ {MOB_LIVE_TRAINEE, 2, 0},
+ {MOB_LIVE_RIDER, 1, 10000},
+ {MOB_LIVE_KNIGHT, 2, 10000},
+ {MOB_LIVE_TRAINEE, 2, 10000},
+ {MOB_LIVE_RIDER, 1, 5000},
+ {MOB_LIVE_KNIGHT, 1, 5000},
+ {MOB_LIVE_TRAINEE, 2, 20000},
+ {MOB_LIVE_TRAINEE, 2, 0},
+ {MOB_LIVE_KNIGHT, 1, 0},
+ {MOB_LIVE_RIDER, 1, 15000},
+ {MOB_LIVE_TRAINEE, 2, 29000},
+ {0, 0, 0},
+};
+
+#define POS_Y_GATE -3360.78f
+
+enum Events
+{
+ EVENT_SUMMON = 1,
+ EVENT_HARVEST,
+ EVENT_BOLT,
+};
+
+#define POS_LIVE 3
+#define POS_DEAD 5
+
+const float PosSummonLive[POS_LIVE][4] =
+{
+ {2669.7, -3430.9, 268.56, 1.6},
+ {2692.0, -3430.9, 268.56, 1.6},
+ {2714.1, -3430.9, 268.56, 1.6},
+};
+
+const float PosSummonDead[POS_DEAD][4] =
+{
+ {2725.1, -3310.0, 268.85, 3.4},
+ {2699.3, -3322.8, 268.60, 3.3},
+ {2733.1, -3348.5, 268.84, 3.1},
+ {2682.8, -3304.2, 268.85, 3.9},
+ {2664.8, -3340.7, 268.23, 3.7},
+};
+
+const float PosGround[4] = {2691.2, -3362.7, 267.68, 1.7};
+const float PosPlatform[4] = {2640.5, -3360.6, 285.26, 0};
+
+struct TRINITY_DLL_DECL boss_gothikAI : public BossAI
+{
+ boss_gothikAI(Creature *c) : BossAI(c, BOSS_GOTHIK) {}
+
+ uint32 waveCount;
+ std::vector<Creature*> liveTrigger;
+ std::vector<Creature*> deadTrigger;
+
+ void Reset()
+ {
+ liveTrigger.clear();
+ deadTrigger.clear();
+ me->setActive(false);
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_ATTACKABLE_2);
+ me->SetReactState(REACT_PASSIVE);
+ _Reset();
+ }
+
+ void EnterCombat(Unit *who)
+ {
+ for(uint32 i = 0; i < POS_LIVE; ++i)
+ if(Creature *trigger = DoSummon(WORLD_TRIGGER, PosSummonLive[i]))
+ liveTrigger.push_back(trigger);
+ for(uint32 i = 0; i < POS_DEAD; ++i)
+ if(Creature *trigger = DoSummon(WORLD_TRIGGER, PosSummonDead[i]))
+ deadTrigger.push_back(trigger);
+
+ if(liveTrigger.size() < POS_LIVE || deadTrigger.size() < POS_DEAD)
+ {
+ error_log("Script Gothik: cannot summon triggers!");
+ EnterEvadeMode();
+ return;
+ }
+
+ _EnterCombat();
+ me->setActive(true);
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_ATTACKABLE_2);
+ waveCount = 0;
+ events.ScheduleEvent(EVENT_SUMMON, 30000);
+ DoTeleportTo(PosPlatform);
+ DoScriptText(SAY_SPEECH, me);
+ if(instance)
+ instance->SetData(DATA_GOTHIK_GATE, 1);
+ }
+
+ void JustSummoned(Creature *summon)
+ {
+ if(summon->GetEntry() == WORLD_TRIGGER)
+ summon->setActive(true);
+ else
+ {
+ summon->AI()->DoAction(me->HasReactState(REACT_PASSIVE) ? 1 : 0);
+ summon->AI()->EnterEvadeMode();
+ }
+ summons.Summon(summon);
+ }
+
+ void KilledUnit(Unit* victim)
+ {
+ if(!(rand()%5))
+ DoScriptText(SAY_KILL, me);
+ }
+
+ void JustDied(Unit* Killer)
+ {
+ _JustDied();
+ DoScriptText(SAY_DEATH, me);
+ }
+
+ void SpellHit(Unit *caster, const SpellEntry *spell)
+ {
+ uint32 spellId = 0;
+ switch(spell->Id)
+ {
+ case SPELL_INFORM_LIVE_TRAINEE: spellId = SPELL_INFORM_DEAD_TRAINEE; break;
+ case SPELL_INFORM_LIVE_KNIGHT: spellId = SPELL_INFORM_DEAD_KNIGHT; break;
+ case SPELL_INFORM_LIVE_RIDER: spellId = SPELL_INFORM_DEAD_RIDER; break;
+ }
+ if(spellId && me->isInCombat())
+ {
+ me->HandleEmoteCommand(EMOTE_ONESHOT_SPELLCAST);
+ me->CastSpell(deadTrigger[rand()%POS_DEAD], spellId, true);
+ }
+ }
+
+ void SpellHitTarget(Unit *target, const SpellEntry *spell)
+ {
+ if(!me->isInCombat())
+ return;
+
+ switch(spell->Id)
+ {
+ case SPELL_INFORM_DEAD_TRAINEE: DoSummon(MOB_DEAD_TRAINEE, target, 0); break;
+ case SPELL_INFORM_DEAD_KNIGHT: DoSummon(MOB_DEAD_KNIGHT, target, 0); break;
+ case SPELL_INFORM_DEAD_RIDER: DoSummon(MOB_DEAD_RIDER, target, 1.0f);
+ DoSummon(MOB_DEAD_HORSE, target, 1.0f); break;
+ }
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if(!me->isInCombat())
+ return;
+
+ if(me->getThreatManager().isThreatListEmpty())
+ {
+ EnterEvadeMode();
+ return;
+ }
+
+ if(me->HasReactState(REACT_AGGRESSIVE) && !UpdateVictim())
+ return;
+
+ events.Update(diff);
+
+ if(me->hasUnitState(UNIT_STAT_CASTING))
+ return;
+
+ while(uint32 eventId = events.ExecuteEvent())
+ {
+ switch(eventId)
+ {
+ case EVENT_SUMMON:
+ if(waves[waveCount].entry)
+ {
+ for(uint32 i = 0; i < waves[waveCount].number; ++i)
+ DoSummon(waves[waveCount].entry, liveTrigger[rand()%POS_LIVE], 1.0f);
+ events.ScheduleEvent(EVENT_SUMMON, waves[waveCount].time);
+ ++waveCount;
+ }
+ else
+ {
+ DoScriptText(SAY_TELEPORT, me);
+ DoTeleportTo(PosGround);
+ me->SetReactState(REACT_AGGRESSIVE);
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_ATTACKABLE_2);
+ if(instance)
+ instance->SetData(DATA_GOTHIK_GATE, 0);
+ summons.DoAction(0, 0);
+ summons.DoZoneInCombat();
+ events.ScheduleEvent(EVENT_BOLT, 1000);
+ events.ScheduleEvent(EVENT_HARVEST, 15000);
+ }
+ break;
+ case EVENT_BOLT:
+ DoCast(me->getVictim(), SPELL_SHADOW_BOLT);
+ events.ScheduleEvent(EVENT_BOLT, 1000);
+ return;
+ case EVENT_HARVEST:
+ DoCast(me->getVictim(), SPELL_HARVEST_SOUL);
+ events.ScheduleEvent(EVENT_HARVEST, 15000);
+ return;
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+struct TRINITY_DLL_DECL mob_gothik_minionAI : public SpellAI
+{
+ mob_gothik_minionAI(Creature *c) : SpellAI(c)
+ {
+ liveSide = me->GetPositionY() < POS_Y_GATE;
+ }
+
+ bool liveSide;
+ bool gateClose;
+
+#define SIDE_CHECK(who) (liveSide == (who->GetPositionY() < POS_Y_GATE))
+
+ void DoAction(const int32 param)
+ {
+ gateClose = param;
+ }
+
+ void DamageTaken(Unit *attacker, uint32 &damage)
+ {
+ if(gateClose && !SIDE_CHECK(attacker))
+ damage = 0;
+ }
+
+ void JustDied(Unit *killer)
+ {
+ if(me->isSummon())
+ {
+ if(Unit *owner = ((TempSummon*)me)->GetSummoner())
+ SpellAI::JustDied(owner);
+ }
+ }
+
+ void EnterEvadeMode()
+ {
+ if(!gateClose)
+ {
+ SpellAI::EnterEvadeMode();
+ return;
+ }
+
+ if(!_EnterEvadeMode())
+ return;
+
+ Map *map = me->GetMap();
+ if(map->IsDungeon())
+ {
+ Map::PlayerList const &PlayerList = map->GetPlayers();
+ for(Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
+ {
+ if(i->getSource()->isAlive() && SIDE_CHECK(i->getSource()))
+ {
+ AttackStart(i->getSource());
+ return;
+ }
+ }
+ }
+
+ me->GetMotionMaster()->MoveIdle();
+ Reset();
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if(gateClose && (!SIDE_CHECK(me) || me->getVictim() && !SIDE_CHECK(me->getVictim())))
+ {
+ EnterEvadeMode();
+ return;
+ }
+
+ SpellAI::UpdateAI(diff);
+ }
+};
+
+CreatureAI* GetAI_boss_gothik(Creature *_Creature)
+{
+ return new boss_gothikAI (_Creature);
+}
+
+CreatureAI* GetAI_mob_gothik_minion(Creature *_Creature)
+{
+ return new mob_gothik_minionAI (_Creature);
+}
+
+void AddSC_boss_gothik()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name="boss_gothik";
+ newscript->GetAI = &GetAI_boss_gothik;
+ newscript->RegisterSelf();
+ newscript = new Script;
+ newscript->Name="mob_gothik_minion";
+ newscript->GetAI = &GetAI_mob_gothik_minion;
+ newscript->RegisterSelf();
+}
diff --git a/src/bindings/scripts/scripts/zone/naxxramas/boss_grobbulus.cpp b/src/bindings/scripts/scripts/zone/naxxramas/boss_grobbulus.cpp
index f18cd81064a..45f54611ae3 100644
--- a/src/bindings/scripts/scripts/zone/naxxramas/boss_grobbulus.cpp
+++ b/src/bindings/scripts/scripts/zone/naxxramas/boss_grobbulus.cpp
@@ -1,4 +1,4 @@
-/* Copyright (C) 2006 - 2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
+/* Copyright (C) 2008 - 2009 Trinity <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
@@ -14,20 +14,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-/* ScriptData
-SDName: Boss_Grobbulus
-SD%Complete: 0
-SDComment: Place holder
-SDCategory: Naxxramas
-EndScriptData */
-
-/*Poison Cloud 26590
-Slime Spray 28157
-Fallout slime 28218
-Mutating Injection 28169
-Enrages 26527*/
-
#include "precompiled.h"
+#include "def_naxxramas.h"
#define SPELL_BOMBARD_SLIME 28280
@@ -43,20 +31,13 @@ Enrages 26527*/
#define MOB_FALLOUT_SLIME 16290
-struct TRINITY_DLL_DECL boss_grobbulusAI : public ScriptedAI
+struct TRINITY_DLL_DECL boss_grobbulusAI : public BossAI
{
- boss_grobbulusAI(Creature *c) : ScriptedAI(c) {}
-
- EventMap events;
-
- void Reset()
- {
- events.Reset();
- }
+ boss_grobbulusAI(Creature *c) : BossAI(c, BOSS_GROBBULUS) {}
void EnterCombat(Unit *who)
{
- DoZoneInCombat();
+ _EnterCombat();
events.ScheduleEvent(EVENT_CLOUD, 15000);
events.ScheduleEvent(EVENT_INJECT, 20000);
events.ScheduleEvent(EVENT_SPRAY, 15000+rand()%15000); //not sure
diff --git a/src/bindings/scripts/scripts/zone/naxxramas/boss_heigan.cpp b/src/bindings/scripts/scripts/zone/naxxramas/boss_heigan.cpp
index 9207b2c09a2..0302a93c488 100644
--- a/src/bindings/scripts/scripts/zone/naxxramas/boss_heigan.cpp
+++ b/src/bindings/scripts/scripts/zone/naxxramas/boss_heigan.cpp
@@ -1,4 +1,4 @@
-/* Copyright (C) 2006 - 2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
+/* Copyright (C) 2008 - 2009 Trinity <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
@@ -14,13 +14,6 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-/* ScriptData
-SDName: Boss_Heigan
-SD%Complete: 0
-SDComment: Place Holder
-SDCategory: Naxxramas
-EndScriptData */
-
#include "precompiled.h"
#include "def_naxxramas.h"
@@ -50,25 +43,14 @@ enum Phases
//Spell by eye stalks
#define SPELL_MIND_FLAY 26143
-struct TRINITY_DLL_DECL boss_heiganAI : public ScriptedAI
+struct TRINITY_DLL_DECL boss_heiganAI : public BossAI
{
- boss_heiganAI(Creature *c) : ScriptedAI(c)
- {
- instance = ((ScriptedInstance*)c->GetInstanceData());
- }
+ boss_heiganAI(Creature *c) : BossAI(c, BOSS_HEIGAN) {}
- EventMap events;
- ScriptedInstance *instance;
uint32 eruptSection;
bool eruptDirection;
Phases phase;
- void Reset()
- {
- events.Reset();
- instance->SetBossState(BOSS_HEIGAN, NOT_STARTED);
- }
-
void KilledUnit(Unit* Victim)
{
if(!(rand()%5))
@@ -77,16 +59,15 @@ struct TRINITY_DLL_DECL boss_heiganAI : public ScriptedAI
void JustDied(Unit* Killer)
{
+ _JustDied();
DoScriptText(SAY_DEATH, me);
- instance->SetBossState(BOSS_HEIGAN, DONE);
}
void EnterCombat(Unit *who)
{
+ _EnterCombat();
DoScriptText(SAY_AGGRO, me);
- DoZoneInCombat();
EnterPhase(PHASE_FIGHT);
- instance->SetBossState(BOSS_HEIGAN, IN_PROGRESS);
}
void EnterPhase(Phases newPhase)
diff --git a/src/bindings/scripts/scripts/zone/naxxramas/boss_noth.cpp b/src/bindings/scripts/scripts/zone/naxxramas/boss_noth.cpp
index 087bc8dc12c..1f7b1a55daa 100644
--- a/src/bindings/scripts/scripts/zone/naxxramas/boss_noth.cpp
+++ b/src/bindings/scripts/scripts/zone/naxxramas/boss_noth.cpp
@@ -1,4 +1,4 @@
-/* Copyright (C) 2006 - 2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
+/* Copyright (C) 2008 - 2009 Trinity <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
@@ -14,13 +14,6 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-/* ScriptData
-SDName: Boss_Noth
-SD%Complete: 40
-SDComment: Missing Balcony stage
-SDCategory: Naxxramas
-EndScriptData */
-
#include "precompiled.h"
#include "def_naxxramas.h"
@@ -34,6 +27,7 @@ EndScriptData */
#define SPELL_CURSE_PLAGUEBRINGER HEROIC(29213,54835)
#define SPELL_BLINK RAND(29208,29209,29210,29211)
#define SPELL_CRIPPLE HEROIC(29212,54814)
+#define SPELL_TELEPORT 29216
#define MOB_WARRIOR 16984
#define MOB_CHAMPION 16983
@@ -45,8 +39,16 @@ EndScriptData */
#define TELE_Z 274.040
#define TELE_O 6.277
-// IMPORTANT: BALCONY TELEPORT NOT ADDED YET! WILL BE ADDED SOON!
-// Dev note 26.12.2008: When is soon? :)
+#define MAX_SUMMON_POS 5
+
+const float SummonPos[MAX_SUMMON_POS][4] =
+{
+ {2728.12, -3544.43, 261.91, 6.04},
+ {2729.05, -3544.47, 261.91, 5.58},
+ {2728.24, -3465.08, 264.20, 3.56},
+ {2704.11, -3456.81, 265.53, 4.51},
+ {2663.56, -3464.43, 262.66, 5.20},
+};
enum Events
{
@@ -54,62 +56,91 @@ enum Events
EVENT_CURSE,
EVENT_BLINK,
EVENT_WARRIOR,
+ EVENT_BALCONY,
+ EVENT_WAVE,
+ EVENT_GROUND,
};
-struct TRINITY_DLL_DECL boss_nothAI : public ScriptedAI
+struct TRINITY_DLL_DECL boss_nothAI : public BossAI
{
- boss_nothAI(Creature *c) : ScriptedAI(c), summons(me)
- {
- instance = ((ScriptedInstance*)c->GetInstanceData());
- }
+ boss_nothAI(Creature *c) : BossAI(c, BOSS_NOTH) {}
- EventMap events;
- SummonList summons;
- ScriptedInstance *instance;
+ uint32 waveCount, balconyCount;
void Reset()
{
- events.Reset();
- summons.DespawnAll();
- instance->SetBossState(BOSS_NOTH, NOT_STARTED);
+ _Reset();
+ me->setActive(false);
}
void EnterCombat(Unit *who)
{
+ _EnterCombat();
DoScriptText(SAY_AGGRO, me);
- DoZoneInCombat();
-
- events.ScheduleEvent(EVENT_CURSE, 20000+rand()%10000);
- events.ScheduleEvent(EVENT_WARRIOR, 30000);
- if(HeroicMode)
- events.ScheduleEvent(EVENT_BLINK, 20000+rand()%10000);
+ me->setActive(true);
+ balconyCount = 0;
+ EnterPhaseGround();
+ }
- instance->SetBossState(BOSS_NOTH, IN_PROGRESS);
+ void EnterPhaseGround()
+ {
+ DoZoneInCombat();
+ if(me->getThreatManager().isThreatListEmpty())
+ EnterEvadeMode();
+ else
+ {
+ events.ScheduleEvent(EVENT_BALCONY, 110000);
+ events.ScheduleEvent(EVENT_CURSE, 20000+rand()%10000);
+ events.ScheduleEvent(EVENT_WARRIOR, 30000);
+ if(HeroicMode)
+ events.ScheduleEvent(EVENT_BLINK, 20000+rand()%10000);
+ }
}
void KilledUnit(Unit* victim)
{
- DoScriptText(SAY_SLAY, me);
+ if(!(rand()%5))
+ DoScriptText(SAY_SLAY, me);
}
void JustSummoned(Creature *summon)
{
summons.Summon(summon);
- DoZoneInCombat(summon);
+ summon->setActive(true);
+ summon->AI()->DoZoneInCombat();
}
- void SummonedCreatureDespawn(Creature *summon) { summons.Despawn(summon); }
-
void JustDied(Unit* Killer)
{
+ _JustDied();
DoScriptText(SAY_DEATH, me);
- instance->SetBossState(BOSS_NOTH, DONE);
+ }
+
+ void SummonUndead(uint32 entry, uint32 num)
+ {
+ for(uint32 i = 0; i < num; ++i)
+ {
+ uint32 pos = rand()%MAX_SUMMON_POS;
+ me->SummonCreature(entry, SummonPos[pos][0], SummonPos[pos][1], SummonPos[pos][2],
+ SummonPos[pos][3], TEMPSUMMON_CORPSE_DESPAWN, 60000);
+ }
}
void UpdateAI(const uint32 diff)
{
- if(!UpdateVictim())
- return;
+ if(me->HasReactState(REACT_AGGRESSIVE)) // ground
+ {
+ if(!UpdateVictim())
+ return;
+ }
+ else // balcony
+ {
+ if(me->getThreatManager().isThreatListEmpty()) // if no enemy, go back at once
+ {
+ events.Reset();
+ events.ScheduleEvent(EVENT_GROUND, 0);
+ }
+ }
events.Update(diff);
@@ -123,8 +154,7 @@ struct TRINITY_DLL_DECL boss_nothAI : public ScriptedAI
return;
case EVENT_WARRIOR:
DoScriptText(SAY_SUMMON, me);
- for(uint8 i = 0; i < 6; i++)
- m_creature->SummonCreature(MOB_WARRIOR,2684.804,-3502.517,261.313,0,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,80000);
+ SummonUndead(MOB_WARRIOR, HEROIC(2,3));
events.ScheduleEvent(EVENT_WARRIOR, 30000);
return;
case EVENT_BLINK:
@@ -133,10 +163,46 @@ struct TRINITY_DLL_DECL boss_nothAI : public ScriptedAI
DoResetThreat();
events.ScheduleEvent(EVENT_BLINK, 20000+rand()%10000);
return;
+ case EVENT_BALCONY:
+ me->SetReactState(REACT_PASSIVE);
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ me->AttackStop();
+ me->RemoveAllAuras();
+ me->NearTeleportTo(TELE_X, TELE_Y, TELE_Z, TELE_O);
+ events.Reset();
+ events.ScheduleEvent(EVENT_WAVE, 2000);
+ waveCount = 0;
+ return;
+ case EVENT_WAVE:
+ DoScriptText(SAY_SUMMON, me);
+ switch(balconyCount)
+ {
+ case 0: SummonUndead(MOB_CHAMPION, HEROIC(2,4)); break;
+ case 1: SummonUndead(MOB_CHAMPION, HEROIC(1,2));
+ SummonUndead(MOB_GUARDIAN, HEROIC(1,2)); break;
+ case 2: SummonUndead(MOB_GUARDIAN, HEROIC(2,4)); break;
+ default:SummonUndead(MOB_CHAMPION, HEROIC(5,10));
+ SummonUndead(MOB_GUARDIAN, HEROIC(5,10));break;
+ }
+ ++waveCount;
+ events.ScheduleEvent(waveCount < 2 ? EVENT_WAVE : EVENT_GROUND, 34000);
+ return;
+ case EVENT_GROUND:
+ {
+ ++balconyCount;
+ me->SetReactState(REACT_AGGRESSIVE);
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ float x, y, z, o;
+ me->GetHomePosition(x, y, z, o);
+ me->NearTeleportTo(x, y, z, o);
+ EnterPhaseGround();
+ return;
+ }
}
}
- DoMeleeAttackIfReady();
+ if(me->HasReactState(REACT_AGGRESSIVE))
+ DoMeleeAttackIfReady();
}
};
diff --git a/src/bindings/scripts/scripts/zone/naxxramas/boss_patchwerk.cpp b/src/bindings/scripts/scripts/zone/naxxramas/boss_patchwerk.cpp
index 3f51fc08ee4..7886fad94cc 100644
--- a/src/bindings/scripts/scripts/zone/naxxramas/boss_patchwerk.cpp
+++ b/src/bindings/scripts/scripts/zone/naxxramas/boss_patchwerk.cpp
@@ -1,4 +1,4 @@
-/* Copyright (C) 2006 - 2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
+/* Copyright (C) 2008 - 2009 Trinity <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
@@ -14,14 +14,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-/* ScriptData
-SDName: Boss_Patchwerk
-SD%Complete: 80
-SDComment: Some issues with hateful strike inturrupting the melee swing timer.
-SDCategory: Naxxramas
-EndScriptData */
-
#include "precompiled.h"
+#include "def_naxxramas.h"
#define SAY_AGGRO RAND(-1533017,-1533018)
#define SAY_SLAY -1533019
@@ -39,18 +33,11 @@ EndScriptData */
#define EVENT_HATEFUL 2
#define EVENT_SLIME 3
-struct TRINITY_DLL_DECL boss_patchwerkAI : public ScriptedAI
+struct TRINITY_DLL_DECL boss_patchwerkAI : public BossAI
{
- boss_patchwerkAI(Creature *c) : ScriptedAI(c) {}
+ boss_patchwerkAI(Creature *c) : BossAI(c, BOSS_PATCHWERK) {}
bool Enraged;
- EventMap events;
-
- void Reset()
- {
- events.Reset();
- Enraged = false;
- }
void KilledUnit(Unit* Victim)
{
@@ -60,13 +47,15 @@ struct TRINITY_DLL_DECL boss_patchwerkAI : public ScriptedAI
void JustDied(Unit* Killer)
{
+ _JustDied();
DoScriptText(SAY_DEATH, me);
}
void EnterCombat(Unit *who)
{
+ _EnterCombat();
+ Enraged = false;
DoScriptText(SAY_AGGRO, me);
- DoZoneInCombat();
events.ScheduleEvent(EVENT_HATEFUL, 1200);
events.ScheduleEvent(EVENT_BERSERK, 360000);
}
@@ -88,15 +77,14 @@ struct TRINITY_DLL_DECL boss_patchwerkAI : public ScriptedAI
//amount of HP within melee distance
uint32 MostHP = 0;
Unit* pMostHPTarget = NULL;
- std::list<HostilReference*>::iterator i = m_creature->getThreatManager().getThreatList().begin();
- for(; i != m_creature->getThreatManager().getThreatList().end();)
+ std::list<HostilReference*>::iterator i = me->getThreatManager().getThreatList().begin();
+ for(; i != me->getThreatManager().getThreatList().end(); ++i)
{
- Unit* pTemp = Unit::GetUnit(*m_creature, (*i)->getUnitGuid());
- ++i;
- if (pTemp && pTemp->isAlive() && pTemp->GetHealth() > MostHP && m_creature->IsWithinMeleeRange(pTemp))
+ Unit* target = (*i)->getTarget();
+ if (target->isAlive() && target->GetHealth() > MostHP && me->IsWithinMeleeRange(target))
{
- MostHP = pTemp->GetHealth();
- pMostHPTarget = pTemp;
+ MostHP = target->GetHealth();
+ pMostHPTarget = target;
}
}
diff --git a/src/bindings/scripts/scripts/zone/naxxramas/boss_razuvious.cpp b/src/bindings/scripts/scripts/zone/naxxramas/boss_razuvious.cpp
index 64147eaea8a..67fcaee7de3 100644
--- a/src/bindings/scripts/scripts/zone/naxxramas/boss_razuvious.cpp
+++ b/src/bindings/scripts/scripts/zone/naxxramas/boss_razuvious.cpp
@@ -1,4 +1,6 @@
-/* Copyright (C) 2006 - 2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
+/*
+ * Copyright (C) 2008 - 2009 Trinity <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
@@ -14,14 +16,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-/* ScriptData
-SDName: Boss_Razuvious
-SD%Complete: 50
-SDComment: Missing adds and event is impossible without Mind Control
-SDCategory: Naxxramas
-EndScriptData */
-
#include "precompiled.h"
+#include "def_naxxramas.h"
//Razuvious - NO TEXT sound only
//8852 aggro01 - Hah hah, I'm just getting warmed up!
@@ -37,121 +33,86 @@ EndScriptData */
//8860 death - An honorable... death...
//8947 - Aggro Mixed? - ?
-#define SOUND_AGGRO1 8852
-#define SOUND_AGGRO2 8853
-#define SOUND_AGGRO3 8854
-#define SOUND_SLAY1 8861
-#define SOUND_SLAY2 8863
-#define SOUND_COMMND1 8855
-#define SOUND_COMMND2 8856
-#define SOUND_COMMND3 8858
-#define SOUND_COMMND4 8859
-#define SOUND_COMMND5 8861
+#define SOUND_AGGRO RAND(8852,8853,8854)
+#define SOUND_SLAY RAND(8861,8863)
+#define SOUND_COMMND RAND(8855,8856,8858,8859,8861)
#define SOUND_DEATH 8860
#define SOUND_AGGROMIX 8847
-#define SPELL_UNBALANCINGSTRIKE 26613
-#define SPELL_DISRUPTINGSHOUT 29107
+#define SPELL_UNBALANCING_STRIKE 26613
+#define SPELL_DISRUPTING_SHOUT HEROIC(29107,55543)
+#define SPELL_JAGGED_KNIFE 55550
+#define SPELL_HOPELESS 29125
-struct TRINITY_DLL_DECL boss_razuviousAI : public ScriptedAI
+enum Events
{
- boss_razuviousAI(Creature *c) : ScriptedAI(c) {}
-
- uint32 UnbalancingStrike_Timer;
- uint32 DisruptingShout_Timer;
- uint32 CommandSound_Timer;
+ EVENT_STRIKE,
+ EVENT_SHOUT,
+ EVENT_KNIFE,
+ EVENT_COMMAND,
+};
- void Reset()
- {
- UnbalancingStrike_Timer = 30000; //30 seconds
- DisruptingShout_Timer = 25000; //25 seconds
- CommandSound_Timer = 40000; //40 seconds
- }
+struct TRINITY_DLL_DECL boss_razuviousAI : public BossAI
+{
+ boss_razuviousAI(Creature *c) : BossAI(c, BOSS_RAZUVIOUS) {}
- void KilledUnit(Unit* Victim)
+ void KilledUnit(Unit* victim)
{
- if (rand()%3)
- return;
-
- switch (rand()%2)
- {
- case 0:
- DoPlaySoundToSet(m_creature, SOUND_SLAY1);
- break;
- case 1:
- DoPlaySoundToSet(m_creature, SOUND_SLAY2);
- break;
- }
+ if(!(rand()%3))
+ DoPlaySoundToSet(me, SOUND_SLAY);
}
- void JustDied(Unit* Killer)
+ void JustDied(Unit* killer)
{
- DoPlaySoundToSet(m_creature, SOUND_DEATH);
+ _JustDied();
+ DoPlaySoundToSet(me, SOUND_DEATH);
+ me->CastSpell(me, SPELL_HOPELESS, true); // TODO: this may affect other creatures
}
void EnterCombat(Unit *who)
{
- switch (rand()%3)
- {
- case 0:
- DoPlaySoundToSet(m_creature, SOUND_AGGRO1);
- break;
- case 1:
- DoPlaySoundToSet(m_creature, SOUND_AGGRO2);
- break;
- case 2:
- DoPlaySoundToSet(m_creature, SOUND_AGGRO3);
- break;
- }
+ _EnterCombat();
+ DoPlaySoundToSet(m_creature, SOUND_AGGRO);
+ events.ScheduleEvent(EVENT_STRIKE, 30000);
+ events.ScheduleEvent(EVENT_SHOUT, 25000);
+ events.ScheduleEvent(EVENT_COMMAND, 40000);
}
void UpdateAI(const uint32 diff)
{
- if (!UpdateVictim())
+ if(!UpdateVictim())
return;
- //UnbalancingStrike_Timer
- if (UnbalancingStrike_Timer < diff)
- {
- DoCast(m_creature->getVictim(),SPELL_UNBALANCINGSTRIKE);
- UnbalancingStrike_Timer = 30000;
- }else UnbalancingStrike_Timer -= diff;
-
- //DisruptingShout_Timer
- if (DisruptingShout_Timer < diff)
- {
- DoCast(m_creature->getVictim(), SPELL_DISRUPTINGSHOUT);
- DisruptingShout_Timer = 25000;
- }else DisruptingShout_Timer -= diff;
+ events.Update(diff);
- //CommandSound_Timer
- if (CommandSound_Timer < diff)
+ while(uint32 eventId = events.ExecuteEvent())
{
- switch (rand()%5)
+ switch(eventId)
{
- case 0:
- DoPlaySoundToSet(m_creature, SOUND_COMMND1);
- break;
- case 1:
- DoPlaySoundToSet(m_creature, SOUND_COMMND2);
- break;
- case 2:
- DoPlaySoundToSet(m_creature, SOUND_COMMND3);
- break;
- case 3:
- DoPlaySoundToSet(m_creature, SOUND_COMMND4);
- break;
- case 4:
- DoPlaySoundToSet(m_creature, SOUND_COMMND5);
- break;
+ case EVENT_STRIKE:
+ DoCast(me->getVictim(), SPELL_UNBALANCING_STRIKE);
+ events.ScheduleEvent(EVENT_STRIKE, 30000);
+ return;
+ case EVENT_SHOUT:
+ DoCastAOE(SPELL_DISRUPTING_SHOUT);
+ events.ScheduleEvent(EVENT_SHOUT, 25000);
+ return;
+ case EVENT_KNIFE:
+ if(Unit *target = SelectTarget(SELECT_TARGET_RANDOM, 0, 45))
+ DoCast(target, SPELL_JAGGED_KNIFE);
+ events.ScheduleEvent(EVENT_KNIFE, 25000);
+ return;
+ case EVENT_COMMAND:
+ DoPlaySoundToSet(me, SOUND_COMMND);
+ events.ScheduleEvent(EVENT_COMMAND, 40000);
+ return;
}
-
- CommandSound_Timer = 40000;
- }else CommandSound_Timer -= diff;
+ }
DoMeleeAttackIfReady();
}
};
+
CreatureAI* GetAI_boss_razuvious(Creature *_Creature)
{
return new boss_razuviousAI (_Creature);
@@ -165,4 +126,3 @@ void AddSC_boss_razuvious()
newscript->GetAI = &GetAI_boss_razuvious;
newscript->RegisterSelf();
}
-
diff --git a/src/bindings/scripts/scripts/zone/naxxramas/boss_sapphiron.cpp b/src/bindings/scripts/scripts/zone/naxxramas/boss_sapphiron.cpp
index a0cfb77c06c..71259df7824 100644
--- a/src/bindings/scripts/scripts/zone/naxxramas/boss_sapphiron.cpp
+++ b/src/bindings/scripts/scripts/zone/naxxramas/boss_sapphiron.cpp
@@ -1,4 +1,6 @@
-/* Copyright (C) 2006 - 2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
+/*
+ * Copyright (C) 2008 - 2009 Trinity <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
@@ -14,171 +16,324 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-/* ScriptData
-SDName: Boss_Sapphiron
-SD%Complete: 0
-SDComment: Place Holder
-SDCategory: Naxxramas
-EndScriptData */
-
#include "precompiled.h"
+#include "def_naxxramas.h"
#define EMOTE_BREATH -1533082
#define EMOTE_ENRAGE -1533083
-#define SPELL_ICEBOLT 28522
-#define SPELL_FROST_BREATH 29318
#define SPELL_FROST_AURA HEROIC(28531,55799)
-#define SPELL_LIFE_DRAIN HEROIC(28542,55665)
-//#define SPELL_CHILL 28560
-#define SPELL_BLIZZARD 28547
-#define SPELL_BESERK 26662
#define SPELL_CLEAVE 19983
-#define SPELL_TAIL_SWEEP 55697
+#define SPELL_TAIL_SWEEP HEROIC(55697,55696)
+#define SPELL_SUMMON_BLIZZARD 28560
+#define SPELL_LIFE_DRAIN HEROIC(28542,55665)
+#define SPELL_ICEBOLT 28522
+#define SPELL_FROST_BREATH 29318
+#define SPELL_FROST_EXPLOSION 28524
+#define SPELL_FROST_MISSILE 30101
+#define SPELL_BERSERK 26662
+#define SPELL_DIES 29357
+#define SPELL_CHILL HEROIC(28547,55699)
-struct TRINITY_DLL_DECL boss_sapphironAI : public ScriptedAI
+#define MOB_BLIZZARD 16474
+#define GO_ICEBLOCK 181247
+
+enum Phases
{
- boss_sapphironAI(Creature* c) : ScriptedAI(c) {}
-
- uint32 Icebolt_Count;
- uint32 Icebolt_Timer;
- uint32 FrostBreath_Timer;
- uint32 FrostAura_Timer;
- uint32 LifeDrain_Timer;
- uint32 Blizzard_Timer;
- uint32 Tail_Sweep_Timer;
- uint32 Cleave_Timer;
- uint32 Fly_Timer;
- uint32 Fly2_Timer;
- uint32 Beserk_Timer;
- uint32 phase;
- bool IsInFly;
- uint32 land_Timer;
+ PHASE_NULL = 0,
+ PHASE_BIRTH,
+ PHASE_GROUND,
+ PHASE_FLIGHT,
+};
+
+enum Events
+{
+ EVENT_BERSERK = 1,
+ EVENT_CLEAVE,
+ EVENT_TAIL,
+ EVENT_DRAIN,
+ EVENT_BLIZZARD,
+ EVENT_FLIGHT,
+ EVENT_LIFTOFF,
+ EVENT_ICEBOLT,
+ EVENT_BREATH,
+ EVENT_EXPLOSION,
+ EVENT_LAND,
+ EVENT_GROUND,
+ EVENT_BIRTH,
+};
+
+typedef std::map<uint64, uint64> IceBlockMap;
+
+struct TRINITY_DLL_DECL boss_sapphironAI : public BossAI
+{
+ boss_sapphironAI(Creature* c) : BossAI(c, BOSS_SAPPHIRON)
+ , phase(PHASE_NULL)
+ {}
+
+ Phases phase;
+ uint32 iceboltCount;
+ IceBlockMap iceblocks;
+
+ void InitializeAI()
+ {
+ float x, y, z;
+ me->GetPosition(x, y, z);
+ me->SummonGameObject(GO_BIRTH, x, y, z, 0, 0, 0, 0, 0, 0);
+ me->SetVisibility(VISIBILITY_OFF);
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ me->SetReactState(REACT_PASSIVE);
+
+ Reset();
+ }
void Reset()
{
- FrostAura_Timer = 2000;
- LifeDrain_Timer = 24000;
- Blizzard_Timer = 20000;
- Tail_Sweep_Timer=(rand()%2+9)*1000;
- Cleave_Timer=10000;
- Fly_Timer = 45000;
- Icebolt_Timer = 4000;
- land_Timer = 0;
- Beserk_Timer = 15*60000;
- phase = 1;
- Icebolt_Count = 0;
- IsInFly = false;
-
- m_creature->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
+ _Reset();
+
+ if(phase = PHASE_FLIGHT)
+ ClearIceBlock();
+
+ phase = PHASE_NULL;
}
void EnterCombat(Unit *who)
{
- DoZoneInCombat();
+ _EnterCombat();
+
me->CastSpell(me, SPELL_FROST_AURA, true);
+
+ events.ScheduleEvent(EVENT_BERSERK, 15*60000);
+ EnterPhaseGround();
+ }
+
+ void SpellHitTarget(Unit *target, const SpellEntry *spell)
+ {
+ if(spell->Id == SPELL_ICEBOLT)
+ {
+ IceBlockMap::iterator itr = iceblocks.find(target->GetGUID());
+ if(itr != iceblocks.end() && !itr->second)
+ {
+ if(GameObject *iceblock = me->SummonGameObject(GO_ICEBLOCK, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, 0, 0, 0, 0, 25000))
+ itr->second = iceblock->GetGUID();
+ }
+ }
+ }
+
+ void JustDied(Unit*)
+ {
+ _JustDied();
+ me->CastSpell(me, SPELL_DIES, true);
+ }
+
+ void MovementInform(uint32, uint32 id)
+ {
+ if(id == 1)
+ events.ScheduleEvent(EVENT_LIFTOFF, 0);
+ }
+
+ void DoAction(const int32 param)
+ {
+ if(param == DATA_SAPPHIRON_BIRTH)
+ {
+ phase = PHASE_BIRTH;
+ events.ScheduleEvent(EVENT_BIRTH, 23000);
+ }
+ }
+
+ void EnterPhaseGround()
+ {
+ phase = PHASE_GROUND;
+ me->SetReactState(REACT_AGGRESSIVE);
+ events.SetPhase(PHASE_GROUND);
+ events.ScheduleEvent(EVENT_CLEAVE, 5000+rand()%10000, 0, PHASE_GROUND);
+ events.ScheduleEvent(EVENT_TAIL, 5000+rand()%10000, 0, PHASE_GROUND);
+ events.ScheduleEvent(EVENT_DRAIN, 24000, 0, PHASE_GROUND);
+ events.ScheduleEvent(EVENT_BLIZZARD, 5000+rand()%5000, 0, PHASE_GROUND);
+ events.ScheduleEvent(EVENT_FLIGHT, 45000);
+ }
+
+ void ClearIceBlock()
+ {
+ for(IceBlockMap::iterator itr = iceblocks.begin(); itr != iceblocks.end(); ++itr)
+ {
+ if(Player *player = Unit::GetPlayer(itr->first))
+ player->RemoveAura(SPELL_ICEBOLT);
+ if(GameObject *go = GameObject::GetGameObject(*me, itr->second))
+ go->Delete();
+ }
+ iceblocks.clear();
}
void UpdateAI(const uint32 diff)
{
- if (!UpdateVictim())
+ if(!phase)
return;
- if(phase == 1)
+ events.Update(diff);
+
+ if(phase == PHASE_GROUND)
{
- if(LifeDrain_Timer < diff)
- {
- DoCastAOE(SPELL_LIFE_DRAIN);
- LifeDrain_Timer = 24000;
- }else LifeDrain_Timer -= diff;
+ if(!UpdateVictim())
+ return;
- if(Blizzard_Timer < diff)
+ while(uint32 eventId = events.ExecuteEvent())
{
- if (Unit* target = SelectUnit(SELECT_TARGET_RANDOM,0))
+ switch(eventId)
{
- DoCast(target,SPELL_BLIZZARD);
- //It seems NO damage?
+ case EVENT_BERSERK:
+ DoScriptText(EMOTE_ENRAGE, m_creature);
+ DoCast(me, SPELL_BERSERK);
+ return;
+ case EVENT_CLEAVE:
+ DoCast(me->getVictim(), SPELL_CLEAVE);
+ events.ScheduleEvent(EVENT_CLEAVE, 5000+rand()%10000, 0, PHASE_GROUND);
+ return;
+ case EVENT_TAIL:
+ DoCastAOE(SPELL_TAIL_SWEEP);
+ events.ScheduleEvent(EVENT_TAIL, 5000+rand()%10000, 0, PHASE_GROUND);
+ return;
+ case EVENT_DRAIN:
+ DoCastAOE(SPELL_LIFE_DRAIN);
+ events.ScheduleEvent(EVENT_DRAIN, 24000, 0, PHASE_GROUND);
+ return;
+ case EVENT_BLIZZARD:
+ {
+ //DoCastAOE(SPELL_SUMMON_BLIZZARD);
+ float x, y, z;
+ me->GetGroundPointAroundUnit(x, y, z, rand_norm()*20, rand_norm()*2*M_PI);
+ if(Creature *summon = me->SummonCreature(MOB_BLIZZARD, x, y, z, 0, TEMPSUMMON_TIMED_DESPAWN, 25000+rand()%5000))
+ summon->GetMotionMaster()->MoveRandom(40);
+ events.ScheduleEvent(EVENT_BLIZZARD, HEROIC(20000,7000), 0, PHASE_GROUND);
+ break;
+ }
+ case EVENT_FLIGHT:
+ phase = PHASE_FLIGHT;
+ events.SetPhase(PHASE_FLIGHT);
+ me->SetReactState(REACT_PASSIVE);
+ me->AttackStop();
+ float x, y, z, o;
+ me->GetHomePosition(x, y, z, o);
+ me->GetMotionMaster()->MovePoint(1, x, y, z);
+ return;
}
- Blizzard_Timer = 20000;
- }else Blizzard_Timer -= diff;
+ }
- //SPELL_CLEAVE
- if(Cleave_Timer < diff)
+ DoMeleeAttackIfReady();
+ }
+ else
+ {
+ /*if(me->getThreatManager().isThreatListEmpty())
{
- DoCast(m_creature->getVictim(),SPELL_CLEAVE);
- Cleave_Timer = 10000;
- }else Cleave_Timer -= diff;
+ EnterEvadeMode();
+ return;
+ }*/
- //Tail Sweep_Timer,
- if(Tail_Sweep_Timer < diff)
+ if(uint32 eventId = events.ExecuteEvent())
{
- DoCast(m_creature,SPELL_TAIL_SWEEP);
- Tail_Sweep_Timer=(rand()%2+9)*1000;
- }else Tail_Sweep_Timer -= diff;
+ switch(eventId)
+ {
+ case EVENT_LIFTOFF:
+ me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF);
+ me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
+ me->SendMovementFlagUpdate();
+ events.ScheduleEvent(EVENT_ICEBOLT, 1500);
+ iceboltCount = HEROIC(2,3);
+ return;
+ case EVENT_ICEBOLT:
+ {
+ std::vector<Unit*> targets;
+ std::list<HostilReference*>::iterator i = me->getThreatManager().getThreatList().begin();
+ for(; i != me->getThreatManager().getThreatList().end(); ++i)
+ if((*i)->getTarget()->GetTypeId() == TYPEID_PLAYER && !(*i)->getTarget()->HasAura(SPELL_ICEBOLT))
+ targets.push_back((*i)->getTarget());
+
+ if(targets.empty())
+ iceboltCount = 0;
+ else
+ {
+ std::vector<Unit*>::iterator itr = targets.begin();
+ advance(itr, rand()%targets.size());
+ iceblocks.insert(std::make_pair((*itr)->GetGUID(), 0));
+ DoCast(*itr, SPELL_ICEBOLT);
+ --iceboltCount;
+ }
+
+ if(iceboltCount)
+ events.ScheduleEvent(EVENT_ICEBOLT, 1000);
+ else
+ events.ScheduleEvent(EVENT_BREATH, 1000);
+ return;
+ }
+ case EVENT_BREATH:
+ {
+ DoScriptText(EMOTE_BREATH, me);
+ DoCastAOE(SPELL_FROST_MISSILE);
+ events.ScheduleEvent(EVENT_EXPLOSION, 8000);
+ return;
+ }
+ case EVENT_EXPLOSION:
+ CastExplosion();
+ ClearIceBlock();
+ events.ScheduleEvent(EVENT_LAND, 3000);
+ return;
+ case EVENT_LAND:
+ me->HandleEmoteCommand(EMOTE_ONESHOT_LAND);
+ me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
+ me->SendMovementFlagUpdate();
+ events.ScheduleEvent(EVENT_GROUND, 1500);
+ return;
+ case EVENT_GROUND:
+ EnterPhaseGround();
+ return;
+ case EVENT_BIRTH:
+ me->SetVisibility(VISIBILITY_ON);
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ me->SetReactState(REACT_AGGRESSIVE);
+ return;
+ }
+ }//if(uint32 eventId = events.ExecuteEvent())
+ }//if(phase == PHASE_GROUND)
+ }
+
+ void CastExplosion()
+ {
+ DoZoneInCombat(); // make sure everyone is in threatlist
+ std::vector<Unit*> targets;
+ std::list<HostilReference*>::iterator i = me->getThreatManager().getThreatList().begin();
+ for(; i != me->getThreatManager().getThreatList().end(); ++i)
+ {
+ Unit *target = (*i)->getTarget();
+ if(target->GetTypeId() != TYPEID_PLAYER)
+ continue;
- if (m_creature->GetHealth()*100 / m_creature->GetMaxHealth() > 10)
+ if(target->HasAura(SPELL_ICEBOLT))
{
- if(Fly_Timer < diff)
- {
- phase = 2;
- m_creature->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF);
- m_creature->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
- m_creature->GetMotionMaster()->Clear(false);
- m_creature->GetMotionMaster()->MoveIdle();
- m_creature->SetHover(true);
- Icebolt_Timer = 4000;
- Icebolt_Count = 0;
- IsInFly = true;
- }else Fly_Timer -= diff;
+ target->ApplySpellImmune(0, IMMUNITY_ID, SPELL_FROST_EXPLOSION, true);
+ targets.push_back(target);
+ continue;
}
- }
- if (phase == 2)
- {
- if(Icebolt_Timer < diff && Icebolt_Count < 5)
+ for(IceBlockMap::iterator itr = iceblocks.begin(); itr != iceblocks.end(); ++itr)
{
- if (Unit* target = SelectUnit(SELECT_TARGET_RANDOM,0))
+ if(GameObject *go = GameObject::GetGameObject(*me, itr->second))
{
- DoCast(target,SPELL_ICEBOLT);
- ++Icebolt_Count;
- error_log("Count incremented");
+ if(go->IsInBetween(me, target, 2.0f)
+ && me->GetExactDistance2d(target->GetPositionX(), target->GetPositionY()) - me->GetExactDistance2d(go->GetPositionX(), go->GetPositionY()) < 5.0f)
+ {
+ target->ApplySpellImmune(0, IMMUNITY_ID, SPELL_FROST_EXPLOSION, true);
+ targets.push_back(target);
+ break;
+ }
}
- FrostBreath_Timer = 6000;
- Icebolt_Timer = 4000;
- }else Icebolt_Timer -= diff;
-
- if(Icebolt_Count == 5 && IsInFly && FrostBreath_Timer < diff )
- {
- DoScriptText(EMOTE_BREATH, m_creature);
- DoCast(m_creature->getVictim(),SPELL_FROST_BREATH);
- land_Timer = 2000;
- IsInFly = false;
- FrostBreath_Timer = 6000;
- }else FrostBreath_Timer -= diff;
-
- if(!IsInFly && land_Timer < diff)
- {
- phase = 1;
- m_creature->HandleEmoteCommand(EMOTE_ONESHOT_LAND);
- m_creature->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
- m_creature->GetMotionMaster()->Clear(false);
- m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim());
- m_creature->SetHover(true);
- land_Timer = 0;
- Fly_Timer = 67000;
- }else land_Timer -= diff;
+ }
}
- if (Beserk_Timer < diff)
- {
- DoScriptText(EMOTE_ENRAGE, m_creature);
- DoCast(m_creature,SPELL_BESERK);
- Beserk_Timer = 300000;
- }else Beserk_Timer -= diff;
+ me->CastSpell(me, SPELL_FROST_EXPLOSION, true);
- if (phase!=2)
- DoMeleeAttackIfReady();
+ for(std::vector<Unit*>::iterator itr = targets.begin(); itr != targets.end(); ++itr)
+ (*itr)->ApplySpellImmune(0, IMMUNITY_ID, SPELL_FROST_EXPLOSION, false);
}
};
diff --git a/src/bindings/scripts/scripts/zone/naxxramas/def_naxxramas.h b/src/bindings/scripts/scripts/zone/naxxramas/def_naxxramas.h
index b0931c556fe..383200d4600 100644
--- a/src/bindings/scripts/scripts/zone/naxxramas/def_naxxramas.h
+++ b/src/bindings/scripts/scripts/zone/naxxramas/def_naxxramas.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 Trinity <http://www.trinitycore.org/>
+ * Copyright (C) 2008 - 2009 Trinity <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
@@ -21,15 +21,32 @@
enum Encounter
{
+ BOSS_ANUBREKHAN,
+ BOSS_FAERLINA,
+ BOSS_MAEXXNA,
BOSS_NOTH,
BOSS_HEIGAN,
BOSS_LOATHEB,
+ BOSS_PATCHWERK,
+ BOSS_GROBBULUS,
+ BOSS_GLUTH,
+ BOSS_THADDIUS,
+ BOSS_RAZUVIOUS,
+ BOSS_GOTHIK,
+ BOSS_HORSEMEN,
+ BOSS_SAPPHIRON,
+ BOSS_KELTHUZAD,
+ MAX_BOSS_NUMBER
};
enum Data
{
DATA_HEIGAN_ERUPT,
+ DATA_GOTHIK_GATE,
+ DATA_SAPPHIRON_BIRTH,
};
+#define GO_BIRTH 181356
+
#endif
diff --git a/src/bindings/scripts/scripts/zone/naxxramas/instance_naxxramas.cpp b/src/bindings/scripts/scripts/zone/naxxramas/instance_naxxramas.cpp
index dfa085f39be..e5913660c3f 100644
--- a/src/bindings/scripts/scripts/zone/naxxramas/instance_naxxramas.cpp
+++ b/src/bindings/scripts/scripts/zone/naxxramas/instance_naxxramas.cpp
@@ -1,4 +1,4 @@
-/* Copyright (C) 2006 - 2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
+/* Copyright (C) 2008 - 2009 Trinity <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
@@ -14,16 +14,38 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-/* ScriptData
-SDName: Instance_Naxxramas
-SD%Complete: 0
-SDComment: Place holder
-SDCategory: Naxxramas
-EndScriptData */
-
#include "precompiled.h"
#include "def_naxxramas.h"
+const DoorData doorData[] =
+{
+ {181126, BOSS_ANUBREKHAN,DOOR_TYPE_ROOM},
+ {181195, BOSS_ANUBREKHAN,DOOR_TYPE_PASSAGE},
+ {194022, BOSS_FAERLINA, DOOR_TYPE_PASSAGE},
+ {181209, BOSS_FAERLINA, DOOR_TYPE_PASSAGE},
+ {181209, BOSS_MAEXXNA, DOOR_TYPE_ROOM},
+ {181200, BOSS_NOTH, DOOR_TYPE_ROOM},
+ {181201, BOSS_NOTH, DOOR_TYPE_PASSAGE},
+ {181202, BOSS_NOTH, DOOR_TYPE_PASSAGE},
+ {181202, BOSS_HEIGAN, DOOR_TYPE_ROOM},
+ {181203, BOSS_HEIGAN, DOOR_TYPE_PASSAGE},
+ {181241, BOSS_HEIGAN, DOOR_TYPE_PASSAGE},
+ {181241, BOSS_LOATHEB, DOOR_TYPE_ROOM},
+ {181123, BOSS_PATCHWERK, DOOR_TYPE_PASSAGE},
+ {181123, BOSS_GROBBULUS, DOOR_TYPE_ROOM},
+ {181120, BOSS_GLUTH, DOOR_TYPE_PASSAGE},
+ {181121, BOSS_GLUTH, DOOR_TYPE_PASSAGE},
+ {181121, BOSS_THADDIUS, DOOR_TYPE_ROOM},
+ {181124, BOSS_RAZUVIOUS, DOOR_TYPE_PASSAGE},
+ {181124, BOSS_GOTHIK, DOOR_TYPE_ROOM},
+ {181125, BOSS_GOTHIK, DOOR_TYPE_PASSAGE},
+ {181119, BOSS_GOTHIK, DOOR_TYPE_PASSAGE},
+ {181119, BOSS_HORSEMEN, DOOR_TYPE_ROOM},
+ {0, 0, DOOR_TYPE_ROOM}, // EOF
+};
+
+#define GO_GOTHIK_GATE 181170
+
#define SPELL_ERUPTION 29371
const float HeiganPos[2] = {2796, -3707};
@@ -55,14 +77,28 @@ inline uint32 GetEruptionSection(float x, float y)
return 3;
}
-struct TRINITY_DLL_DECL instance_naxxramas : public ScriptedInstance
+struct TRINITY_DLL_DECL instance_naxxramas : public InstanceData
{
- instance_naxxramas(Map *map) : ScriptedInstance(map)
+ instance_naxxramas(Map *map) : InstanceData(map)
+ , Sapphiron(NULL)
{
- SetBossNumber(15);
+ SetBossNumber(MAX_BOSS_NUMBER);
+ LoadDoorData(doorData);
}
+ std::set<Creature*> Worshipper;
std::set<GameObject*> HeiganEruption[4];
+ GameObject *GothikGate;
+ Creature *Sapphiron;
+
+ void OnCreatureCreate(Creature *creature, bool add)
+ {
+ switch(creature->GetEntry())
+ {
+ case 15989: Sapphiron = add ? creature : NULL; break;
+ case 16506: if(add) Worshipper.insert(creature); else Worshipper.erase(creature); break;
+ }
+ }
void OnObjectCreate(GameObject* go, bool add)
{
@@ -78,11 +114,24 @@ struct TRINITY_DLL_DECL instance_naxxramas : public ScriptedInstance
switch(go->GetEntry())
{
- case 181200: SetBossRoomDoor(BOSS_NOTH, go, add); break;
- case 181201: SetBossPassageDoor(BOSS_NOTH, go, add); break;
- case 181202: SetBossRoomDoor(BOSS_HEIGAN, go, add); break;
- case 181203: SetBossPassageDoor(BOSS_HEIGAN, go, add); break;
- case 181241: SetBossRoomDoor(BOSS_LOATHEB, go, add); break;
+ case GO_BIRTH: if(!add && Sapphiron) Sapphiron->AI()->DoAction(DATA_SAPPHIRON_BIRTH); return;
+ case GO_GOTHIK_GATE: GothikGate = add ? go : NULL; break;
+ }
+
+ AddDoor(go, add);
+ }
+
+ void SetBossState(uint32 id, EncounterState state)
+ {
+ InstanceData::SetBossState(id, state);
+ switch(id)
+ {
+ case BOSS_FAERLINA:
+ if(state == NOT_STARTED)
+ for(std::set<Creature*>::iterator itr = Worshipper.begin(); itr != Worshipper.end(); ++itr)
+ if(!(*itr)->isAlive())
+ (*itr)->Respawn();
+ break;
}
}
@@ -93,6 +142,10 @@ struct TRINITY_DLL_DECL instance_naxxramas : public ScriptedInstance
case DATA_HEIGAN_ERUPT:
HeiganErupt(value);
break;
+ case DATA_GOTHIK_GATE:
+ if(GothikGate)
+ GothikGate->SetGoState(GOState(value));
+ break;
}
}
@@ -122,6 +175,6 @@ void AddSC_instance_naxxramas()
Script *newscript;
newscript = new Script;
newscript->Name = "instance_naxxramas";
- newscript->GetInstanceData = GetInstanceData_instance_naxxramas;
+ newscript->GetInstanceData = &GetInstanceData_instance_naxxramas;
newscript->RegisterSelf();
}
diff --git a/src/bindings/scripts/scripts/zone/shadowfang_keep/instance_shadowfang_keep.cpp b/src/bindings/scripts/scripts/zone/shadowfang_keep/instance_shadowfang_keep.cpp
index caf18778abb..30f843badb0 100644
--- a/src/bindings/scripts/scripts/zone/shadowfang_keep/instance_shadowfang_keep.cpp
+++ b/src/bindings/scripts/scripts/zone/shadowfang_keep/instance_shadowfang_keep.cpp
@@ -185,7 +185,7 @@ struct TRINITY_DLL_DECL instance_shadowfang_keep : public ScriptedInstance
return 0;
}
- const char* Save()
+ std::string GetSaveData()
{
return str_data.c_str();
}
diff --git a/src/bindings/scripts/scripts/zone/sunwell_plateau/boss_felmyst.cpp b/src/bindings/scripts/scripts/zone/sunwell_plateau/boss_felmyst.cpp
index 8e42d074f88..e753d0b6047 100644
--- a/src/bindings/scripts/scripts/zone/sunwell_plateau/boss_felmyst.cpp
+++ b/src/bindings/scripts/scripts/zone/sunwell_plateau/boss_felmyst.cpp
@@ -306,7 +306,7 @@ struct TRINITY_DLL_DECL boss_felmystAI : public ScriptedAI
case 2:{
error_log("Summon Vapor case 2");
Unit* target;
- target = SelectUnit(SELECT_TARGET_RANDOM, 0, 150, true);
+ target = SelectTarget(SELECT_TARGET_RANDOM, 0, 150, true);
if(!target) target = Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_PLAYER_GUID));
if(target)
{
@@ -331,7 +331,7 @@ struct TRINITY_DLL_DECL boss_felmystAI : public ScriptedAI
error_log("Summon Vapor case3");
//m_creature->CastSpell(m_creature, SPELL_VAPOR_SELECT); need core support
Unit* target;
- target = SelectUnit(SELECT_TARGET_RANDOM, 0, 150, true);
+ target = SelectTarget(SELECT_TARGET_RANDOM, 0, 150, true);
if(!target) target = Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_PLAYER_GUID));
if(target)
{
@@ -358,7 +358,7 @@ struct TRINITY_DLL_DECL boss_felmystAI : public ScriptedAI
break;
case 5:{
Unit* target;
- target = SelectUnit(SELECT_TARGET_RANDOM, 0, 150, true);
+ target = SelectTarget(SELECT_TARGET_RANDOM, 0, 150, true);
if(!target) target = Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_PLAYER_GUID));
if(target)
{
@@ -471,7 +471,7 @@ struct TRINITY_DLL_DECL boss_felmystAI : public ScriptedAI
Timer[EVENT_GAS_NOVA] = 20000 + rand()%5 * 1000;
break;
case EVENT_ENCAPSULATE:
- if(Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0, 150, true))
+ if(Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 150, true))
{
m_creature->CastSpell(target, SPELL_ENCAPSULATE_CHANNEL, false);
target->CastSpell(target, SPELL_ENCAPSULATE_EFFECT, true);// linked aura, need core patch to remove this hack
diff --git a/src/bindings/scripts/scripts/zone/sunwell_plateau/boss_kiljaeden.cpp b/src/bindings/scripts/scripts/zone/sunwell_plateau/boss_kiljaeden.cpp
index 98cbfda7a7f..a0bd75cb156 100644
--- a/src/bindings/scripts/scripts/zone/sunwell_plateau/boss_kiljaeden.cpp
+++ b/src/bindings/scripts/scripts/zone/sunwell_plateau/boss_kiljaeden.cpp
@@ -540,7 +540,7 @@ struct TRINITY_DLL_DECL boss_kiljaedenAI : public Scripted_NoMovementAI
float x,y,z;
Unit* target;
for(uint8 z = 0; z < 6; ++z){
- target = SelectUnit(SELECT_TARGET_RANDOM, 0, 100, true);
+ target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true);
if (!target->HasAura(SPELL_VENGEANCE_OF_THE_BLUE_FLIGHT,0)) break;
}
target->GetPosition(x,y,z);
@@ -584,7 +584,7 @@ struct TRINITY_DLL_DECL boss_kiljaedenAI : public Scripted_NoMovementAI
if(!m_creature->IsNonMeleeSpellCasted(false)){
m_creature->RemoveAurasDueToSpell(SPELL_SOUL_FLAY);
for(uint8 z = 0; z < 6; ++z){
- randomPlayer = SelectUnit(SELECT_TARGET_RANDOM, 0, 100, true);
+ randomPlayer = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true);
if (!randomPlayer->HasAura(SPELL_VENGEANCE_OF_THE_BLUE_FLIGHT,0)) break;
}
if(randomPlayer)DoCast(randomPlayer, SPELL_LEGION_LIGHTNING, false);
@@ -658,7 +658,7 @@ struct TRINITY_DLL_DECL boss_kiljaedenAI : public Scripted_NoMovementAI
case TIMER_ARMAGEDDON: //Phase 4
Unit* target;
for(uint8 z = 0; z < 6; ++z){
- target = SelectUnit(SELECT_TARGET_RANDOM, 0, 100, true);
+ target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true);
if (!target->HasAura(SPELL_VENGEANCE_OF_THE_BLUE_FLIGHT,0)) break;
}
if(target){
@@ -1199,7 +1199,7 @@ struct TRINITY_DLL_DECL mob_sinster_reflectionAI : public ScriptedAI
Timer[1] = 4000;
}
if(Timer[2] < diff){
- DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0, 100, true), SPELL_SR_CURSE_OF_AGONY, true);
+ DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true), SPELL_SR_CURSE_OF_AGONY, true);
Timer[2] = 3000;
}
DoMeleeAttackIfReady();
diff --git a/src/bindings/scripts/scripts/zone/sunwell_plateau/boss_muru.cpp b/src/bindings/scripts/scripts/zone/sunwell_plateau/boss_muru.cpp
index 6000ee474e0..b38607e1a7f 100644
--- a/src/bindings/scripts/scripts/zone/sunwell_plateau/boss_muru.cpp
+++ b/src/bindings/scripts/scripts/zone/sunwell_plateau/boss_muru.cpp
@@ -155,7 +155,7 @@ struct TRINITY_DLL_DECL boss_entropiusAI : public ScriptedAI
m_creature->SummonCreature(CREATURE_DARK_FIENDS, x,y,z,o, TEMPSUMMON_CORPSE_DESPAWN, 0);
break;
}
- summoned->AI()->AttackStart(SelectUnit(SELECT_TARGET_RANDOM,0, 50, true));
+ summoned->AI()->AttackStart(SelectTarget(SELECT_TARGET_RANDOM,0, 50, true));
Summons.Summon(summoned);
}
@@ -180,10 +180,10 @@ struct TRINITY_DLL_DECL boss_entropiusAI : public ScriptedAI
}else EnrageTimer -= diff;
if(BlackHoleSummonTimer < diff){
- Unit* random = SelectUnit(SELECT_TARGET_RANDOM, 0, 100, true);
+ Unit* random = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true);
if(!random)return;
DoCast(random, SPELL_DARKNESS_E, false);
- random = SelectUnit(SELECT_TARGET_RANDOM, 0, 100, true);
+ random = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true);
if(!random)return;
random->CastSpell(random, SPELL_BLACKHOLE, false);
BlackHoleSummonTimer = 15000;
@@ -260,7 +260,7 @@ struct TRINITY_DLL_DECL boss_muruAI : public Scripted_NoMovementAI
summoned->CastSpell(summoned,SPELL_DARKFIEND_VISUAL,false);
break;
}
- summoned->AI()->AttackStart(SelectUnit(SELECT_TARGET_RANDOM,0, 50, true));
+ summoned->AI()->AttackStart(SelectTarget(SELECT_TARGET_RANDOM,0, 50, true));
Summons.Summon(summoned);
}
@@ -441,7 +441,7 @@ struct TRINITY_DLL_DECL npc_dark_fiendAI : public ScriptedAI
if(!InAction){
m_creature->clearUnitState(UNIT_STAT_STUNNED);
DoCastAOE(SPELL_DARKFIEND_SKIN, false);
- AttackStart(SelectUnit(SELECT_TARGET_RANDOM, 0, 100, true));
+ AttackStart(SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true));
InAction = true;
WaitTimer = 500;
}else{
diff --git a/src/bindings/scripts/scripts/zone/sunwell_plateau/instance_sunwell_plateau.cpp b/src/bindings/scripts/scripts/zone/sunwell_plateau/instance_sunwell_plateau.cpp
index f8bba5acf21..597103b62cf 100644
--- a/src/bindings/scripts/scripts/zone/sunwell_plateau/instance_sunwell_plateau.cpp
+++ b/src/bindings/scripts/scripts/zone/sunwell_plateau/instance_sunwell_plateau.cpp
@@ -236,7 +236,7 @@ struct TRINITY_DLL_DECL instance_sunwell_plateau : public ScriptedInstance
{
}
- const char* Save()
+ std::string GetSaveData()
{
OUT_SAVE_INST_DATA;
std::ostringstream stream;
diff --git a/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/boss_alar.cpp b/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/boss_alar.cpp
index 168f0f48e3a..dfeb7fea3e6 100644
--- a/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/boss_alar.cpp
+++ b/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/boss_alar.cpp
@@ -352,7 +352,7 @@ struct TRINITY_DLL_DECL boss_alarAI : public ScriptedAI
if(Charge_Timer < diff)
{
- Unit *target= SelectUnit(SELECT_TARGET_RANDOM, 1, GetSpellMaxRangeForHostile(SPELL_CHARGE), true);
+ Unit *target= SelectTarget(SELECT_TARGET_RANDOM, 1, GetSpellMaxRangeForHostile(SPELL_CHARGE), true);
if(target)
DoCast(target, SPELL_CHARGE);
Charge_Timer = 30000;
@@ -410,7 +410,8 @@ struct TRINITY_DLL_DECL boss_alarAI : public ScriptedAI
else
{
Unit *target = NULL;
- if(Phase1 && target && (target = m_creature->SelectNearestTarget(5)))
+ target = m_creature->SelectNearestTarget(5);
+ if(Phase1 && target)
m_creature->AI()->AttackStart(target);
else
{
diff --git a/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/boss_astromancer.cpp b/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/boss_astromancer.cpp
index 83cb789b189..6af14eceeed 100644
--- a/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/boss_astromancer.cpp
+++ b/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/boss_astromancer.cpp
@@ -230,7 +230,7 @@ struct TRINITY_DLL_DECL boss_high_astromancer_solarianAI : public ScriptedAI
if( Wrath_Timer < diff)
{
m_creature->InterruptNonMeleeSpells(false);
- DoCast(SelectUnit(SELECT_TARGET_RANDOM,1,100,true), SPELL_WRATH_OF_THE_ASTROMANCER, true);
+ DoCast(SelectTarget(SELECT_TARGET_RANDOM,1,100,true), SPELL_WRATH_OF_THE_ASTROMANCER, true);
Wrath_Timer = 20000+rand()%5000;
}else Wrath_Timer -= diff;
@@ -260,7 +260,7 @@ struct TRINITY_DLL_DECL boss_high_astromancer_solarianAI : public ScriptedAI
if (MarkOfTheAstromancer_Timer < diff) //A debuff that lasts for 5 seconds, cast several times each phase on a random raid member, but not the main tank
{
- Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 1, 100, true);
+ Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true);
if(target)
DoCast(target, SPELL_MARK_OF_THE_ASTROMANCER);
else DoCast(m_creature->getVictim(), SPELL_MARK_OF_THE_ASTROMANCER);
diff --git a/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/boss_kaelthas.cpp b/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/boss_kaelthas.cpp
index 6745c4fd9ec..7557e03f8e5 100644
--- a/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/boss_kaelthas.cpp
+++ b/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/boss_kaelthas.cpp
@@ -804,7 +804,7 @@ struct TRINITY_DLL_DECL boss_kaelthasAI : public ScriptedAI
if (FlameStrike_Timer < diff)
{
- if (Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 0, 70, true))
+ if (Unit* pUnit = SelectTarget(SELECT_TARGET_RANDOM, 0, 70, true))
DoCast(pUnit, SPELL_FLAME_STRIKE);
FlameStrike_Timer = 30000;
@@ -816,7 +816,7 @@ struct TRINITY_DLL_DECL boss_kaelthasAI : public ScriptedAI
for (uint32 i = 0; i < 3; i++)
{
- Unit* target =SelectUnit(SELECT_TARGET_RANDOM, 1, 70, true);
+ Unit* target =SelectTarget(SELECT_TARGET_RANDOM, 1, 70, true);
if(!target) target = m_creature->getVictim();
debug_log("TSCR: Kael'Thas mind control not supported.");
if(target)
@@ -1080,7 +1080,7 @@ struct TRINITY_DLL_DECL boss_thaladred_the_darkenerAI : public advisorbase_ai
//Gaze_Timer
if(Gaze_Timer < diff)
{
- if (Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0, 100, true))
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
{
DoResetThreat();
if(target)
diff --git a/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/instance_the_eye.cpp b/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/instance_the_eye.cpp
index 66e595ab729..55ef8c60bbd 100644
--- a/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/instance_the_eye.cpp
+++ b/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/instance_the_eye.cpp
@@ -129,7 +129,7 @@ struct TRINITY_DLL_DECL instance_the_eye : public ScriptedInstance
return 0;
}
- const char* Save()
+ std::string GetSaveData()
{
OUT_SAVE_INST_DATA;
std::ostringstream stream;
diff --git a/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/boss_twinemperors.cpp b/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/boss_twinemperors.cpp
index c3d4d0f35eb..d2fff0e569f 100644
--- a/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/boss_twinemperors.cpp
+++ b/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/boss_twinemperors.cpp
@@ -465,7 +465,7 @@ struct TRINITY_DLL_DECL boss_veknilashAI : public boss_twinemperorsAI
if (UpperCut_Timer < diff)
{
- Unit* randomMelee = SelectUnit(SELECT_TARGET_RANDOM, 0, NOMINAL_MELEE_RANGE, true);
+ Unit* randomMelee = SelectTarget(SELECT_TARGET_RANDOM, 0, NOMINAL_MELEE_RANGE, true);
if (randomMelee)
DoCast(randomMelee,SPELL_UPPERCUT);
UpperCut_Timer = 15000+rand()%15000;
@@ -560,7 +560,7 @@ struct TRINITY_DLL_DECL boss_veklorAI : public boss_twinemperorsAI
if (Blizzard_Timer < diff)
{
Unit* target = NULL;
- target = SelectUnit(SELECT_TARGET_RANDOM, 0, 45, true);
+ target = SelectTarget(SELECT_TARGET_RANDOM, 0, 45, true);
if (target)
DoCast(target,SPELL_BLIZZARD);
Blizzard_Timer = 15000+rand()%15000;
@@ -569,7 +569,7 @@ struct TRINITY_DLL_DECL boss_veklorAI : public boss_twinemperorsAI
if (ArcaneBurst_Timer < diff)
{
Unit *mvic;
- if ((mvic=SelectUnit(SELECT_TARGET_NEAREST, 0, NOMINAL_MELEE_RANGE, true))!=NULL)
+ if ((mvic=SelectTarget(SELECT_TARGET_NEAREST, 0, NOMINAL_MELEE_RANGE, true))!=NULL)
{
DoCast(mvic,SPELL_ARCANEBURST);
ArcaneBurst_Timer = 5000;
diff --git a/src/bindings/scripts/scripts/zone/utgarde_keep/utgarde_keep/instance_utgarde_keep.cpp b/src/bindings/scripts/scripts/zone/utgarde_keep/utgarde_keep/instance_utgarde_keep.cpp
index d6f5828d295..d483006642d 100644
--- a/src/bindings/scripts/scripts/zone/utgarde_keep/utgarde_keep/instance_utgarde_keep.cpp
+++ b/src/bindings/scripts/scripts/zone/utgarde_keep/utgarde_keep/instance_utgarde_keep.cpp
@@ -231,7 +231,7 @@ struct TRINITY_DLL_DECL instance_utgarde_keep : public ScriptedInstance
return 0;
}
- const char* Save()
+ std::string GetSaveData()
{
OUT_SAVE_INST_DATA;
diff --git a/src/bindings/scripts/scripts/zone/utgarde_keep/utgarde_keep/utgarde_keep.cpp b/src/bindings/scripts/scripts/zone/utgarde_keep/utgarde_keep/utgarde_keep.cpp
index 3c2b898653d..923328627e4 100644
--- a/src/bindings/scripts/scripts/zone/utgarde_keep/utgarde_keep/utgarde_keep.cpp
+++ b/src/bindings/scripts/scripts/zone/utgarde_keep/utgarde_keep/utgarde_keep.cpp
@@ -155,6 +155,6 @@ void AddSC_utgarde_keep()
newscript = new Script;
newscript->Name="npc_dragonflayer_forge_master";
- newscript->GetAI = GetAI_npc_dragonflayer_forge_master;
+ newscript->GetAI = &GetAI_npc_dragonflayer_forge_master;
newscript->RegisterSelf();
-} \ No newline at end of file
+}
diff --git a/src/bindings/scripts/scripts/zone/zulaman/boss_akilzon.cpp b/src/bindings/scripts/scripts/zone/zulaman/boss_akilzon.cpp
index f31f944a3d4..85ba26ef20d 100644
--- a/src/bindings/scripts/scripts/zone/zulaman/boss_akilzon.cpp
+++ b/src/bindings/scripts/scripts/zone/zulaman/boss_akilzon.cpp
@@ -297,7 +297,7 @@ struct TRINITY_DLL_DECL boss_akilzonAI : public ScriptedAI
}
if (ElectricalStorm_Timer < diff) {
- Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0, 50, true);
+ Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 50, true);
if(!target)
{
EnterEvadeMode();
diff --git a/src/bindings/scripts/scripts/zone/zulaman/boss_hexlord.cpp b/src/bindings/scripts/scripts/zone/zulaman/boss_hexlord.cpp
index 7fb8dc9b321..26229261905 100644
--- a/src/bindings/scripts/scripts/zone/zulaman/boss_hexlord.cpp
+++ b/src/bindings/scripts/scripts/zone/zulaman/boss_hexlord.cpp
@@ -383,7 +383,7 @@ struct TRINITY_DLL_DECL boss_hex_lord_malacrassAI : public ScriptedAI
if(SiphonSoul_Timer < diff)
{
- Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0, 70, true);
+ Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 70, true);
Unit *trigger = DoSpawnCreature(MOB_TEMP_TRIGGER, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN, 30000);
if(!target || !trigger)
{
diff --git a/src/bindings/scripts/scripts/zone/zulaman/boss_nalorakk.cpp b/src/bindings/scripts/scripts/zone/zulaman/boss_nalorakk.cpp
index 9fc50e621ac..68b92590025 100644
--- a/src/bindings/scripts/scripts/zone/zulaman/boss_nalorakk.cpp
+++ b/src/bindings/scripts/scripts/zone/zulaman/boss_nalorakk.cpp
@@ -406,7 +406,7 @@ struct TRINITY_DLL_DECL boss_nalorakkAI : public ScriptedAI
{
DoYell(YELL_SURGE, LANG_UNIVERSAL, NULL);
DoPlaySoundToSet(m_creature, SOUND_YELL_SURGE);
- Unit *target = SelectUnit(SELECT_TARGET_RANDOM, 1, GetSpellMaxRangeForHostile(SPELL_SURGE), true);
+ Unit *target = SelectTarget(SELECT_TARGET_RANDOM, 1, GetSpellMaxRangeForHostile(SPELL_SURGE), true);
if(target)
DoCast(target, SPELL_SURGE);
Surge_Timer = 15000 + rand()%5000;
diff --git a/src/bindings/scripts/scripts/zone/zulaman/instance_zulaman.cpp b/src/bindings/scripts/scripts/zone/zulaman/instance_zulaman.cpp
index 4ebf541515b..8ff01927908 100644
--- a/src/bindings/scripts/scripts/zone/zulaman/instance_zulaman.cpp
+++ b/src/bindings/scripts/scripts/zone/zulaman/instance_zulaman.cpp
@@ -179,7 +179,7 @@ struct TRINITY_DLL_DECL instance_zulaman : public ScriptedInstance
instance->SendToPlayers(&data);
}
- const char* Save()
+ std::string GetSaveData()
{
std::ostringstream ss;
ss << "S " << BossKilled << " " << ChestLooted << " " << QuestMinute;
diff --git a/src/framework/Platform/Define.h b/src/framework/Platform/Define.h
index 59c2418c745..35be370d65b 100644
--- a/src/framework/Platform/Define.h
+++ b/src/framework/Platform/Define.h
@@ -129,5 +129,11 @@ typedef uint32 DWORD;
typedef uint64 OBJECT_HANDLE;
+#define MaNGOS Trinity
+#define MANGOS_DLL_DECL TRINITY_DLL_DECL
+#define MANGOS_DLL_SPEC TRINITY_DLL_SPEC
+#define MANGOS_DEBUG TRINITY_DEBUG
+#define GetMangosString GetTrinityString
+
#endif //TRINITY_DEFINE_H
diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp
index 321922f821e..84ae9cb659e 100644
--- a/src/game/AchievementMgr.cpp
+++ b/src/game/AchievementMgr.cpp
@@ -407,7 +407,14 @@ void AchievementMgr::LoadFromDB(QueryResult *achievementResult, QueryResult *cri
do
{
Field *fields = achievementResult->Fetch();
- CompletedAchievementData& ca = m_completedAchievements[fields[0].GetUInt32()];
+
+ uint32 achievement_id = fields[0].GetUInt32();
+
+ // don't must happen: cleanup at server startup in achievementmgr.LoadCompletedAchievements()
+ if(!sAchievementStore.LookupEntry(achievement_id))
+ continue;
+
+ CompletedAchievementData& ca = m_completedAchievements[achievement_id];
ca.date = time_t(fields[1].GetUInt64());
ca.changed = false;
} while(achievementResult->NextRow());
@@ -425,7 +432,15 @@ void AchievementMgr::LoadFromDB(QueryResult *achievementResult, QueryResult *cri
time_t date = time_t(fields[2].GetUInt64());
AchievementCriteriaEntry const* criteria = sAchievementCriteriaStore.LookupEntry(id);
- if (!criteria || (criteria->timeLimit && time_t(date + criteria->timeLimit) < time(NULL)))
+ if (!criteria)
+ {
+ // we will remove not existed criteria for all characters
+ sLog.outError("Not existed achievement creataria %u data removed from table `character_achievement_progress`.",id);
+ CharacterDatabase.PExecute("DELETE FROM character_achievement_progress WHERE criteria = %u",id);
+ continue;
+ }
+
+ if (criteria->timeLimit && time_t(date + criteria->timeLimit) < time(NULL))
continue;
CriteriaProgress& progress = m_criteriaProgress[id];
@@ -1763,7 +1778,17 @@ void AchievementGlobalMgr::LoadCompletedAchievements()
{
bar.step();
Field *fields = result->Fetch();
- m_allCompletedAchievements.insert(fields[0].GetUInt32());
+
+ uint32 achievement_id = fields[0].GetUInt32();
+ if(!sAchievementStore.LookupEntry(achievement_id))
+ {
+ // we will remove not existed achievement for all characters
+ sLog.outError("Not existed achievement %u data removed from table `character_achievement`.",achievement_id);
+ CharacterDatabase.PExecute("DELETE FROM character_achievement WHERE achievement = %u",achievement_id);
+ continue;
+ }
+
+ m_allCompletedAchievements.insert(achievement_id);
} while(result->NextRow());
delete result;
diff --git a/src/game/AggressorAI.cpp b/src/game/AggressorAI.cpp
index a637e7e40f0..22ebe87cdc6 100644
--- a/src/game/AggressorAI.cpp
+++ b/src/game/AggressorAI.cpp
@@ -19,16 +19,9 @@
*/
#include "AggressorAI.h"
-#include "Errors.h"
-#include "Creature.h"
-#include "ObjectAccessor.h"
-#include "VMapFactory.h"
-#include "World.h"
+#include "SpellMgr.h"
-#include <list>
-
-int
-AggressorAI::Permissible(const Creature *creature)
+int AggressorAI::Permissible(const Creature *creature)
{
// have some hostile factions, it will be selected by IsHostileTo check at MoveInLineOfSight
if( !creature->isCivilian() && !creature->IsNeutralToAll() )
@@ -37,79 +30,83 @@ AggressorAI::Permissible(const Creature *creature)
return PERMIT_BASE_NO;
}
-AggressorAI::AggressorAI(Creature *c) : CreatureAI(c), i_victimGuid(0), i_state(STATE_NORMAL), i_tracker(TIME_INTERVAL_LOOK)
+void AggressorAI::UpdateAI(const uint32 /*diff*/)
{
+ if(!UpdateVictim())
+ return;
+
+ DoMeleeAttackIfReady();
}
-void AggressorAI::EnterEvadeMode()
+int SpellAI::Permissible(const Creature *creature)
{
- if( !m_creature->isAlive() )
- {
- DEBUG_LOG("Creature stopped attacking cuz his dead [guid=%u]", m_creature->GetGUIDLow());
- i_victimGuid = 0;
- m_creature->CombatStop(true);
- m_creature->DeleteThreatList();
- return;
- }
+ return PERMIT_BASE_NO;
+}
- Unit* victim = ObjectAccessor::GetUnit(*m_creature, i_victimGuid );
+void SpellAI::InitializeAI()
+{
+ for(uint32 i = 0; i < CREATURE_MAX_SPELLS; ++i)
+ if(me->m_spells[i] && GetSpellStore()->LookupEntry(me->m_spells[i]))
+ spells.push_back(me->m_spells[i]);
+}
- if( !victim )
- {
- DEBUG_LOG("Creature stopped attacking because victim is non exist [guid=%u]", m_creature->GetGUIDLow());
- }
- else if( !victim->isAlive() )
- {
- DEBUG_LOG("Creature stopped attacking cuz his victim is dead [guid=%u]", m_creature->GetGUIDLow());
- }
- else if( victim->HasStealthAura() )
- {
- DEBUG_LOG("Creature stopped attacking cuz his victim is stealth [guid=%u]", m_creature->GetGUIDLow());
- }
- else if( victim->isInFlight() )
- {
- DEBUG_LOG("Creature stopped attacking cuz his victim is fly away [guid=%u]", m_creature->GetGUIDLow());
- }
- else
- {
- DEBUG_LOG("Creature stopped attacking due to target out run him [guid=%u]", m_creature->GetGUIDLow());
- //i_state = STATE_LOOK_AT_VICTIM;
- //i_tracker.Reset(TIME_INTERVAL_LOOK);
- }
+void SpellAI::Reset()
+{
+ events.Reset();
+}
- if(!m_creature->GetCharmerOrOwner())
- {
- m_creature->RemoveAllAuras();
+void SpellAI::JustDied(Unit *killer)
+{
+ for(SpellVct::iterator i = spells.begin(); i != spells.end(); ++i)
+ if(AISpellInfo[*i].condition == AICOND_DIE)
+ me->CastSpell(killer, *i, true);
+}
- // Remove TargetedMovementGenerator from MotionMaster stack list, and add HomeMovementGenerator instead
- if( m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE )
- m_creature->GetMotionMaster()->MoveTargetedHome();
+void SpellAI::EnterCombat(Unit *who)
+{
+ for(SpellVct::iterator i = spells.begin(); i != spells.end(); ++i)
+ {
+ if(AISpellInfo[*i].condition == AICOND_AGGRO)
+ me->CastSpell(who, *i, true);
+ else if(AISpellInfo[*i].condition == AICOND_COMBAT)
+ events.ScheduleEvent(*i, AISpellInfo[*i].cooldown + rand()%AISpellInfo[*i].cooldown);
}
- else if (m_creature->GetOwner() && m_creature->GetOwner()->isAlive())
- m_creature->GetMotionMaster()->MoveFollow(m_creature->GetOwner(),PET_FOLLOW_DIST,PET_FOLLOW_ANGLE);
-
- m_creature->DeleteThreatList();
- i_victimGuid = 0;
- m_creature->CombatStop(true);
- m_creature->SetLootRecipient(NULL);
}
-void
-AggressorAI::UpdateAI(const uint32 /*diff*/)
+void SpellAI::UpdateAI(const uint32 diff)
{
- // update i_victimGuid if m_creature->getVictim() !=0 and changed
if(!UpdateVictim())
return;
- i_victimGuid = m_creature->getVictim()->GetGUID();
+ events.Update(diff);
- if( m_creature->isAttackReady() )
+ if(me->hasUnitState(UNIT_STAT_CASTING))
+ return;
+
+ if(uint32 spellId = events.ExecuteEvent())
{
- if( m_creature->IsWithinMeleeRange(m_creature->getVictim()))
+ Unit *target = NULL;
+ //sLog.outError("aggre %u %u", spellId, (uint32)AISpellInfo[spellId].target);
+ switch(AISpellInfo[spellId].target)
{
- m_creature->AttackerStateUpdate(m_creature->getVictim());
- m_creature->resetAttackTimer();
+ default:
+ case AITARGET_SELF: target = me; break;
+ case AITARGET_VICTIM: target = me->getVictim(); break;
+ case AITARGET_ENEMY: target = SelectTarget(SELECT_TARGET_RANDOM); break;
+ case AITARGET_ALLY: target = me; break;
+ case AITARGET_BUFF: target = me; break;
+ case AITARGET_DEBUFF:
+ {
+ const SpellEntry * spellInfo = GetSpellStore()->LookupEntry(spellId);
+ bool playerOnly = spellInfo->AttributesEx3 & SPELL_ATTR_EX3_PLAYERS_ONLY;
+ float range = GetSpellMaxRange(spellInfo, false);
+ target = SelectTarget(SELECT_TARGET_RANDOM, 0, range, playerOnly, -(int32)spellId);
+ break;
+ }
}
+ if(target) me->CastSpell(target, spellId, false);
+ events.ScheduleEvent(spellId, AISpellInfo[spellId].cooldown + rand()%AISpellInfo[spellId].cooldown);
}
+ else
+ DoMeleeAttackIfReady();
}
-
diff --git a/src/game/AggressorAI.h b/src/game/AggressorAI.h
index 983498716e6..2c43ccf82b7 100644
--- a/src/game/AggressorAI.h
+++ b/src/game/AggressorAI.h
@@ -22,31 +22,35 @@
#define TRINITY_AGGRESSORAI_H
#include "CreatureAI.h"
-#include "Timer.h"
+#include "CreatureAIImpl.h"
class Creature;
class TRINITY_DLL_DECL AggressorAI : public CreatureAI
{
- enum AggressorState
- {
- STATE_NORMAL = 1,
- STATE_LOOK_AT_VICTIM = 2
- };
-
public:
-
- explicit AggressorAI(Creature *c);
-
- void EnterEvadeMode();
+ explicit AggressorAI(Creature *c) : CreatureAI(c) {}
void UpdateAI(const uint32);
static int Permissible(const Creature *);
+};
+
+typedef std::vector<uint32> SpellVct;
+class TRINITY_DLL_SPEC SpellAI : public CreatureAI
+{
+ public:
+ explicit SpellAI(Creature *c) : CreatureAI(c) {}
+
+ void InitializeAI();
+ void Reset();
+ void EnterCombat(Unit* who);
+ void JustDied(Unit *killer);
+ void UpdateAI(const uint32 diff);
+ static int Permissible(const Creature *);
private:
- uint64 i_victimGuid;
- AggressorState i_state;
- TimeTracker i_tracker;
+ EventMap events;
+ SpellVct spells;
};
-#endif
+#endif
diff --git a/src/game/BattleGround.cpp b/src/game/BattleGround.cpp
index d179ec33691..b76e0c7835c 100644
--- a/src/game/BattleGround.cpp
+++ b/src/game/BattleGround.cpp
@@ -726,12 +726,10 @@ void BattleGround::EndBattleGround(uint32 winner)
if (team == winner)
{
RewardMark(plr,ITEM_WINNER_COUNT);
- RewardQuest(plr);
+ RewardQuestComplete(plr);
}
- else if(winner !=0)
- {
+ else if(winner)
RewardMark(plr,ITEM_LOSER_COUNT);
- }
plr->CombatStopWithPets(true);
@@ -785,13 +783,6 @@ uint32 BattleGround::GetBattlemasterEntry() const
void BattleGround::RewardMark(Player *plr,uint32 count)
{
- // 'Inactive' this aura prevents the player from gaining honor points and battleground tokens
- if (plr->GetDummyAura(SPELL_AURA_PLAYER_INACTIVE))
- return;
-
- if(!plr || !count)
- return;
-
BattleGroundMarks mark;
switch(GetTypeID())
{
@@ -811,21 +802,53 @@ void BattleGround::RewardMark(Player *plr,uint32 count)
return;
}
- if ( objmgr.GetItemPrototype( mark ) )
+ //if (IsSpell)
+ // RewardSpellCast(plr,mark);
+ //else
+ RewardItem(plr,mark,count);
+}
+
+void BattleGround::RewardSpellCast(Player *plr, uint32 spell_id)
+{
+ // 'Inactive' this aura prevents the player from gaining honor points and battleground tokens
+ if (plr->GetDummyAura(SPELL_AURA_PLAYER_INACTIVE))
+ return;
+
+ SpellEntry const *spellInfo = sSpellStore.LookupEntry(spell_id);
+ if(!spellInfo)
{
- ItemPosCountVec dest;
- uint32 no_space_count = 0;
- uint8 msg = plr->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, mark, count, &no_space_count );
- if( msg != EQUIP_ERR_OK ) // convert to possible store amount
- count -= no_space_count;
+ sLog.outError("Battleground reward casting spell %u not exist.",spell_id);
+ return;
+ }
- if(!dest.empty()) // can add some
- if(Item* item = plr->StoreNewItem( dest, mark, true, 0))
- plr->SendNewItem(item,count,false,true);
+ plr->CastSpell(plr, spellInfo, true);
+}
+
+void BattleGround::RewardItem(Player *plr, uint32 item_id, uint32 count)
+{
+ // 'Inactive' this aura prevents the player from gaining honor points and battleground tokens
+ if (plr->GetDummyAura(SPELL_AURA_PLAYER_INACTIVE))
+ return;
- if (no_space_count > 0)
- SendRewardMarkByMail(plr,mark,no_space_count);
+ ItemPosCountVec dest;
+ uint32 no_space_count = 0;
+ uint8 msg = plr->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, item_id, count, &no_space_count );
+
+ if( msg == EQUIP_ERR_ITEM_NOT_FOUND)
+ {
+ sLog.outErrorDb("Battleground reward item (Entry %u) not exist in `item_template`.",item_id);
+ return;
}
+
+ if( msg != EQUIP_ERR_OK ) // convert to possible store amount
+ count -= no_space_count;
+
+ if( count != 0 && !dest.empty()) // can add some
+ if (Item* item = plr->StoreNewItem( dest, item_id, true, 0))
+ plr->SendNewItem(item,count,false,true);
+
+ if (no_space_count > 0)
+ SendRewardMarkByMail(plr,item_id,no_space_count);
}
void BattleGround::SendRewardMarkByMail(Player *plr,uint32 mark, uint32 count)
@@ -865,12 +888,8 @@ void BattleGround::SendRewardMarkByMail(Player *plr,uint32 mark, uint32 count)
}
}
-void BattleGround::RewardQuest(Player *plr)
+void BattleGround::RewardQuestComplete(Player *plr)
{
- // 'Inactive' this aura prevents the player from gaining honor points and battleground tokens
- if (plr->GetDummyAura(SPELL_AURA_PLAYER_INACTIVE))
- return;
-
uint32 quest;
switch(GetTypeID())
{
@@ -890,7 +909,7 @@ void BattleGround::RewardQuest(Player *plr)
return;
}
- plr->CastSpell(plr, quest, true);
+ RewardSpellCast(plr, quest);
}
void BattleGround::BlockMovement(Player *plr)
@@ -1739,7 +1758,7 @@ uint32 BattleGround::GetAlivePlayersCountByTeam(uint32 Team) const
if (itr->second.Team == Team)
{
Player * pl = objmgr.GetPlayer(itr->first);
- if (pl && pl->isAlive())
+ if (pl && pl->isAlive() && !pl->HasByteFlag(UNIT_FIELD_BYTES_2, 3, FORM_SPIRITOFREDEMPTION))
++count;
}
}
diff --git a/src/game/BattleGround.h b/src/game/BattleGround.h
index 9788f264502..509ba6eb972 100644
--- a/src/game/BattleGround.h
+++ b/src/game/BattleGround.h
@@ -421,7 +421,9 @@ class BattleGround
void RewardReputationToTeam(uint32 faction_id, uint32 Reputation, uint32 TeamID);
void RewardMark(Player *plr,uint32 count);
void SendRewardMarkByMail(Player *plr,uint32 mark, uint32 count);
- void RewardQuest(Player *plr);
+ void RewardItem(Player *plr, uint32 item_id, uint32 count);
+ void RewardQuestComplete(Player *plr);
+ void RewardSpellCast(Player *plr, uint32 spell_id);
void UpdateWorldState(uint32 Field, uint32 Value);
void UpdateWorldStateForPlayer(uint32 Field, uint32 Value, Player *Source);
void EndBattleGround(uint32 winner);
diff --git a/src/game/CMakeLists.txt b/src/game/CMakeLists.txt
index 081d9669696..89a9e460968 100644
--- a/src/game/CMakeLists.txt
+++ b/src/game/CMakeLists.txt
@@ -68,6 +68,7 @@ SET(game_STAT_SRCS
Corpse.h
CreatureAI.cpp
CreatureAI.h
+ CreatureAIFactory.h
CreatureAIImpl.h
CreatureAIRegistry.cpp
CreatureAIRegistry.h
@@ -208,8 +209,6 @@ SET(game_STAT_SRCS
PointMovementGenerator.h
PoolHandler.cpp
PoolHandler.h
- PossessedAI.cpp
- PossessedAI.h
QueryHandler.cpp
QuestDef.cpp
QuestDef.h
@@ -262,6 +261,8 @@ SET(game_STAT_SRCS
Traveller.h
Unit.cpp
Unit.h
+ UnitAI.cpp
+ UnitAI.h
UnitEvents.h
UpdateData.cpp
UpdateData.h
diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp
index ca6a96c3b08..29a54da5d06 100644
--- a/src/game/CharacterHandler.cpp
+++ b/src/game/CharacterHandler.cpp
@@ -173,7 +173,7 @@ void WorldSession::HandleCharEnumOpcode( WorldPacket & /*recv_data*/ )
// 0 1 2 3 4 5 6 7 8
"SELECT characters.guid, characters.data, characters.name, characters.position_x, characters.position_y, characters.position_z, characters.map, characters.totaltime, characters.leveltime, "
// 9 10 11 12 13 14
- "characters.at_login, character_pet.entry, character_pet.modelid, character_pet.level, guild_member.guildid, genitive "
+ "characters.at_login, character_pet.entry, character_pet.modelid, character_pet.level, guild_member.guildid, character_declinedname.genitive "
"FROM characters LEFT JOIN character_pet ON characters.guid = character_pet.owner AND character_pet.slot='%u' "
"LEFT JOIN character_declinedname ON characters.guid = character_declinedname.guid "
"LEFT JOIN guild_member ON characters.guid = guild_member.guid "
@@ -571,7 +571,6 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder * holder)
uint64 playerGuid = holder->GetGuid();
Player* pCurrChar = new Player(this);
- pCurrChar->GetMotionMaster()->Initialize();
// for send server info and strings (config)
ChatHandler chH = ChatHandler(pCurrChar);
@@ -585,6 +584,8 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder * holder)
return;
}
+ pCurrChar->GetMotionMaster()->Initialize();
+
SetPlayer(pCurrChar);
pCurrChar->SendDungeonDifficulty(false);
@@ -769,7 +770,7 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder * holder)
{
sLog.outDebug( "WORLD: Restart character %u taxi flight", pCurrChar->GetGUIDLow() );
- uint32 MountId = objmgr.GetTaxiMount(sourceNode, pCurrChar->GetTeam());
+ uint32 MountId = objmgr.GetTaxiMount(sourceNode, pCurrChar->GetTeam(),true);
uint32 path = pCurrChar->m_taxi.GetCurrentTaxiPath();
// search appropriate start path node
diff --git a/src/game/Chat.cpp b/src/game/Chat.cpp
index 1bc6eb304e4..bf8ee9d3a77 100644
--- a/src/game/Chat.cpp
+++ b/src/game/Chat.cpp
@@ -49,6 +49,7 @@
// |color|Hskill:skill_id|h[name]|h|r
// |color|Hspell:spell_id|h[name]|h|r - client, spellbook spell icon shift-click
// |color|Htalent:talent_id,rank|h[name]|h|r - client, talent icon shift-click
+// |color|Htaxinode:id|h[name]|h|r
// |color|Htele:id|h[name]|h|r
// |color|Htrade:spell_id,cur_value,max_value,unk3int,unk3str|h[name]|h|r - client, spellbook profession icon shift-click
@@ -194,6 +195,7 @@ ChatCommand * ChatHandler::getCommandTable()
{ "graveyard", SEC_MODERATOR, false, &ChatHandler::HandleGoGraveyardCommand, "", NULL },
{ "grid", SEC_MODERATOR, false, &ChatHandler::HandleGoGridCommand, "", NULL },
{ "object", SEC_MODERATOR, false, &ChatHandler::HandleGoObjectCommand, "", NULL },
+ { "taxinode", SEC_MODERATOR, false, &ChatHandler::HandleGoTaxinodeCommand, "", NULL },
{ "trigger", SEC_MODERATOR, false, &ChatHandler::HandleGoTriggerCommand, "", NULL },
{ "zonexy", SEC_MODERATOR, false, &ChatHandler::HandleGoZoneXYCommand, "", NULL },
{ "xy", SEC_MODERATOR, false, &ChatHandler::HandleGoXYCommand, "", NULL },
@@ -301,6 +303,7 @@ ChatCommand * ChatHandler::getCommandTable()
{ "player", SEC_GAMEMASTER, true, NULL, "", lookupPlayerCommandTable },
{ "skill", SEC_ADMINISTRATOR, true, &ChatHandler::HandleLookupSkillCommand, "", NULL },
{ "spell", SEC_ADMINISTRATOR, true, &ChatHandler::HandleLookupSpellCommand, "", NULL },
+ { "taxinode", SEC_ADMINISTRATOR, true, &ChatHandler::HandleLookupTaxiNodeCommand, "", NULL },
{ "tele", SEC_MODERATOR, true, &ChatHandler::HandleLookupTeleCommand, "", NULL },
{ NULL, 0, false, NULL, "", NULL }
};
diff --git a/src/game/Chat.h b/src/game/Chat.h
index cc7de6731a6..97570d2f250 100644
--- a/src/game/Chat.h
+++ b/src/game/Chat.h
@@ -195,6 +195,7 @@ class ChatHandler
bool HandleGoGraveyardCommand(const char* args);
bool HandleGoGridCommand(const char* args);
bool HandleGoObjectCommand(const char* args);
+ bool HandleGoTaxinodeCommand(const char* args);
bool HandleGoTriggerCommand(const char* args);
bool HandleGoXYCommand(const char* args);
bool HandleGoXYZCommand(const char* args);
@@ -247,6 +248,7 @@ class ChatHandler
bool HandleLookupQuestCommand(const char* args);
bool HandleLookupSkillCommand(const char* args);
bool HandleLookupSpellCommand(const char* args);
+ bool HandleLookupTaxiNodeCommand(const char * args);
bool HandleLookupTeleCommand(const char * args);
bool HandleModifyKnownTitlesCommand(const char* args);
diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp
index 01f43ac8163..8d7b877d4f5 100644
--- a/src/game/Creature.cpp
+++ b/src/game/Creature.cpp
@@ -164,8 +164,8 @@ Creature::~Creature()
i_AI = NULL;
}
- if(m_uint32Values)
- sLog.outDetail("Deconstruct Creature Entry = %u", GetEntry());
+ //if(m_uint32Values)
+ // sLog.outDetail("Deconstruct Creature Entry = %u", GetEntry());
}
void Creature::AddToWorld()
@@ -175,7 +175,7 @@ void Creature::AddToWorld()
{
ObjectAccessor::Instance().AddObject(this);
Unit::AddToWorld();
- SearchFormation();
+ SearchFormationAndPath();
AIM_Initialize();
}
}
@@ -194,7 +194,7 @@ void Creature::RemoveFromWorld()
}
}
-void Creature::SearchFormation()
+void Creature::SearchFormationAndPath()
{
if(isSummon())
return;
@@ -203,9 +203,28 @@ void Creature::SearchFormation()
if(!lowguid)
return;
+ bool usePath = (GetDefaultMovementType() == WAYPOINT_MOTION_TYPE);
CreatureGroupInfoType::iterator frmdata = CreatureGroupMap.find(lowguid);
if(frmdata != CreatureGroupMap.end())
+ {
+ if(usePath && lowguid != frmdata->second->leaderGUID)
+ {
+ SetDefaultMovementType(IDLE_MOTION_TYPE);
+ usePath = false;
+ }
formation_mgr.AddCreatureToGroup(frmdata->second->leaderGUID, this);
+ }
+
+ if(usePath)
+ {
+ if(WaypointMgr.GetPath(lowguid * 10))
+ SetWaypointPathId(lowguid * 10);
+ else
+ {
+ sLog.outErrorDb("Creature DBGUID %u has waypoint motion type, but it does not have a waypoint path!", lowguid);
+ SetDefaultMovementType(IDLE_MOTION_TYPE);
+ }
+ }
}
void Creature::RemoveCorpse()
@@ -436,6 +455,9 @@ void Creature::Update(uint32 diff)
}
else
{
+ // for delayed spells
+ m_Events.Update( diff );
+
m_deathTimer -= diff;
if (m_groupLootTimer && lootingGroupLeaderGUID)
{
@@ -2036,12 +2058,12 @@ bool Creature::IsOutOfThreatArea(Unit* pVictim) const
if(sMapStore.LookupEntry(GetMapId())->IsDungeon())
return false;
- float length = pVictim->GetDistance(mHome_X, mHome_Y, mHome_Z);
float AttackDist = GetAttackDistance(pVictim);
uint32 ThreatRadius = sWorld.getConfig(CONFIG_THREAT_RADIUS);
//Use AttackDistance in distance check if threat radius is lower. This prevents creature bounce in and out of combat every update tick.
- return ( length > (ThreatRadius > AttackDist ? ThreatRadius : AttackDist));
+ return !pVictim->IsWithinDist3d(mHome_X,mHome_Y,mHome_Z,
+ ThreatRadius > AttackDist ? ThreatRadius : AttackDist);
}
CreatureDataAddon const* Creature::GetCreatureAddon() const
@@ -2081,10 +2103,6 @@ bool Creature::LoadCreaturesAddon(bool reload)
if (cainfo->move_flags != 0)
SetUnitMovementFlags(cainfo->move_flags);
- //Load Path
- if (cainfo->path_id != 0)
- m_path_id = cainfo->path_id;
-
if(cainfo->auras)
{
for (CreatureDataAddonAura const* cAura = cainfo->auras; cAura->spell_id; ++cAura)
@@ -2105,7 +2123,7 @@ bool Creature::LoadCreaturesAddon(bool reload)
continue;
}
- AddAuraEffect(AdditionalSpellInfo->Id, cAura->effect_idx, this);
+ AddAuraEffect(AdditionalSpellInfo, cAura->effect_idx, this);
sLog.outDebug("Spell: %u with Aura %u added to creature (GUIDLow: %u Entry: %u )", cAura->spell_id, AdditionalSpellInfo->EffectApplyAuraName[cAura->effect_idx],GetGUIDLow(),GetEntry());
}
}
diff --git a/src/game/Creature.h b/src/game/Creature.h
index 36cfee78c5f..f57f0592da5 100644
--- a/src/game/Creature.h
+++ b/src/game/Creature.h
@@ -108,6 +108,21 @@ enum Gossip_Guard_Skill
GOSSIP_GUARD_SKILL_ENGINERING = 91
};
+enum GossipOptionIcon
+{
+ GOSSIP_ICON_CHAT = 0, //white chat bubble
+ GOSSIP_ICON_VENDOR = 1, //brown bag
+ GOSSIP_ICON_TAXI = 2, //flight
+ GOSSIP_ICON_TRAINER = 3, //book
+ GOSSIP_ICON_INTERACT_1 = 4, //interaction wheel
+ GOSSIP_ICON_INTERACT_2 = 5, //interaction wheel
+ GOSSIP_ICON_MONEY_BAG = 6, //brown bag with yellow dot
+ GOSSIP_ICON_TALK = 7, //white chat bubble with black dots
+ GOSSIP_ICON_TABARD = 8, //tabard
+ GOSSIP_ICON_BATTLE = 9, //two swords
+ GOSSIP_ICON_DOT = 10 //yellow dot
+};
+
struct GossipOption
{
uint32 Id;
@@ -300,7 +315,6 @@ struct CreatureDataAddonAura
struct CreatureDataAddon
{
uint32 guidOrEntry;
- uint32 path_id;
uint32 mount;
uint32 bytes0;
uint32 bytes1;
@@ -635,6 +649,7 @@ class TRINITY_DLL_SPEC Creature : public Unit
bool IsVisibleInGridForPlayer(Player const* pl) const;
void RemoveCorpse();
+ bool isDeadByDefault() const { return m_isDeadByDefault; };
time_t const& GetRespawnTime() const { return m_respawnTime; }
time_t GetRespawnTimeEx() const;
@@ -676,13 +691,13 @@ class TRINITY_DLL_SPEC Creature : public Unit
uint32 GetGlobalCooldown() const { return m_GlobalCooldown; }
- uint32 GetWaypointPath(){return m_path_id;}
- void LoadPath(uint32 pathid) { m_path_id = pathid; }
+ uint32 GetWaypointPathId() const { return m_pathId; }
+ void SetWaypointPathId(uint32 pathid) { m_pathId = pathid; }
uint32 GetCurrentWaypointID(){return m_waypointID;}
void UpdateWaypointID(uint32 wpID){m_waypointID = wpID;}
- void SearchFormation();
+ void SearchFormationAndPath();
CreatureGroup *GetFormation() {return m_formation;}
void SetFormation(CreatureGroup *formation) {m_formation = formation;}
@@ -743,7 +758,7 @@ class TRINITY_DLL_SPEC Creature : public Unit
private:
//WaypointMovementGenerator vars
uint32 m_waypointID;
- uint32 m_path_id;
+ uint32 m_pathId;
//Formation var
CreatureGroup *m_formation;
diff --git a/src/game/CreatureAI.cpp b/src/game/CreatureAI.cpp
index 5fd35150b52..0864bc973ab 100644
--- a/src/game/CreatureAI.cpp
+++ b/src/game/CreatureAI.cpp
@@ -19,49 +19,10 @@
*/
#include "CreatureAI.h"
+#include "CreatureAIImpl.h"
#include "Creature.h"
-#include "Player.h"
-#include "Pet.h"
-#include "SpellAuras.h"
#include "World.h"
-
-void UnitAI::AttackStart(Unit *victim)
-{
- if(!victim)
- return;
-
- if(me->Attack(victim, true))
- {
- //DEBUG_LOG("Creature %s tagged a victim to kill [guid=%u]", me->GetName(), victim->GetGUIDLow());
- me->GetMotionMaster()->MoveChase(victim);
- }
-}
-
-void UnitAI::DoMeleeAttackIfReady()
-{
- //Make sure our attack is ready and we aren't currently casting before checking distance
- if (me->isAttackReady() && !me->hasUnitState(UNIT_STAT_CASTING))
- {
- //If we are within range melee the target
- if (me->IsWithinMeleeRange(me->getVictim()))
- {
- me->AttackerStateUpdate(me->getVictim());
- me->resetAttackTimer();
- }
- }
- if (me->haveOffhandWeapon() && me->isAttackReady(OFF_ATTACK) && !me->hasUnitState(UNIT_STAT_CASTING))
- {
- //If we are within range melee the target
- if (me->IsWithinMeleeRange(me->getVictim()))
- {
- me->AttackerStateUpdate(me->getVictim(), OFF_ATTACK);
- me->resetAttackTimer(OFF_ATTACK);
- }
- }
-}
-
-//Enable PlayerAI when charmed
-void PlayerAI::OnCharmed(bool apply) { me->IsAIEnabled = apply; }
+#include "SpellMgr.h"
//Disable CreatureAI when charmed
void CreatureAI::OnCharmed(bool apply)
@@ -71,11 +32,16 @@ void CreatureAI::OnCharmed(bool apply)
me->IsAIEnabled = false;
}
+AISpellInfoType * CreatureAI::AISpellInfo;
+
void CreatureAI::DoZoneInCombat(Creature* creature)
{
if (!creature)
creature = me;
+ if(!creature->CanHaveThreatList())
+ return;
+
Map *map = creature->GetMap();
if (!map->IsDungeon()) //use IsDungeon instead of Instanceable, in case battlegrounds will be instantiated
{
@@ -83,37 +49,38 @@ void CreatureAI::DoZoneInCombat(Creature* creature)
return;
}
- if(!creature->getVictim())
+ if(!creature->HasReactState(REACT_PASSIVE) && !creature->getVictim())
{
if(Unit *target = creature->SelectNearestTarget())
- AttackStart(target);
+ creature->AI()->AttackStart(target);
else if(creature->isSummon())
{
if(Unit *summoner = ((TempSummon*)creature)->GetSummoner())
{
- if(summoner->getVictim()
- && (creature->IsFriendlyTo(summoner) || creature->IsHostileTo(summoner->getVictim())))
- AttackStart(summoner->getVictim());
+ Unit *target = summoner->getAttackerForHelper();
+ if(!target && summoner->CanHaveThreatList() && !summoner->getThreatManager().isThreatListEmpty())
+ target = summoner->getThreatManager().getHostilTarget();
+ if(target && (creature->IsFriendlyTo(summoner) || creature->IsHostileTo(target)))
+ creature->AI()->AttackStart(target);
}
}
}
- if (!creature->CanHaveThreatList() || !creature->getVictim())
+ if(!creature->HasReactState(REACT_PASSIVE) && !creature->getVictim())
{
- sLog.outError("DoZoneInCombat called for creature that either cannot have threat list or has empty threat list (creature entry = %d)", creature->GetTypeId() == TYPEID_UNIT ? ((Creature*)creature)->GetEntry() : 0);
+ sLog.outError("DoZoneInCombat called for creature that has empty threat list (creature entry = %u)", creature->GetEntry());
return;
}
Map::PlayerList const &PlayerList = map->GetPlayers();
for(Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
{
- if (Player* i_pl = i->getSource())
- if (i_pl->isAlive())
- {
- creature->SetInCombatWith(i_pl);
- i_pl->SetInCombatWith(creature);
- creature->AddThreat(i_pl, 0.0f);
- }
+ if (i->getSource()->isAlive())
+ {
+ creature->SetInCombatWith(i->getSource());
+ i->getSource()->SetInCombatWith(creature);
+ creature->AddThreat(i->getSource(), 0.0f);
+ }
}
}
@@ -139,40 +106,222 @@ bool CreatureAI::UpdateVictim()
return me->getVictim();
}
-void CreatureAI::EnterEvadeMode()
+bool CreatureAI::_EnterEvadeMode()
{
+ if(me->IsInEvadeMode() || !me->isAlive())
+ return false;
+
me->RemoveAllAuras();
me->DeleteThreatList();
- me->CombatStop();
+ me->CombatStop(true);
me->LoadCreaturesAddon();
me->SetLootRecipient(NULL);
- if(me->isAlive())
+ return true;
+}
+
+void CreatureAI::EnterEvadeMode()
+{
+ if(!_EnterEvadeMode())
+ return;
+
+ if(Unit *owner = me->GetCharmerOrOwner())
+ me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE, MOTION_SLOT_IDLE);
+ else
me->GetMotionMaster()->MoveTargetedHome();
+
+ Reset();
+}
+
+inline bool SelectTargetHelper(const Unit * me, const Unit * target, const bool &playerOnly, const float &dist, const int32 &aura)
+{
+ if(playerOnly && target->GetTypeId() != TYPEID_PLAYER)
+ return false;
+
+ if(dist && !me->IsWithinCombatRange(target, dist))
+ return false;
+
+ if(aura)
+ {
+ if(aura > 0)
+ {
+ if(!target->HasAura(aura))
+ return false;
+ }
+ else
+ {
+ if(target->HasAura(aura))
+ return false;
+ }
+ }
+
+ return true;
+}
+
+struct TargetDistanceOrder : public std::binary_function<const Unit *, const Unit *, bool>
+{
+ const Unit * me;
+ TargetDistanceOrder(const Unit* Target) : me(Target) {};
+ // functor for operator ">"
+ bool operator()(const Unit * _Left, const Unit * _Right) const
+ {
+ return (me->GetDistanceSq(_Left) < me->GetDistanceSq(_Right));
+ }
+};
+
+Unit* CreatureAI::SelectTarget(SelectAggroTarget targetType, uint32 position, float dist, bool playerOnly, int32 aura)
+{
+ if(targetType == SELECT_TARGET_NEAREST || targetType == SELECT_TARGET_FARTHEST)
+ {
+ std::list<HostilReference*> &m_threatlist = me->getThreatManager().getThreatList();
+ if(position >= m_threatlist.size())
+ return NULL;
+
+ std::list<Unit*> targetList;
+ for(std::list<HostilReference*>::iterator itr = m_threatlist.begin(); itr!= m_threatlist.end(); ++itr)
+ if(SelectTargetHelper(me, (*itr)->getTarget(), playerOnly, dist, aura))
+ targetList.push_back((*itr)->getTarget());
+
+ if(position >= targetList.size())
+ return NULL;
+
+ targetList.sort(TargetDistanceOrder(m_creature));
+
+ if(targetType == SELECT_TARGET_NEAREST)
+ {
+ std::list<Unit*>::iterator i = targetList.begin();
+ advance(i, position);
+ return *i;
+ }
+ else
+ {
+ std::list<Unit*>::reverse_iterator i = targetList.rbegin();
+ advance(i, position);
+ return *i;
+ }
+ }
+ else
+ {
+ std::list<HostilReference*> m_threatlist = me->getThreatManager().getThreatList();
+ std::list<HostilReference*>::iterator i;
+ while(position < m_threatlist.size())
+ {
+ if(targetType == SELECT_TARGET_BOTTOMAGGRO)
+ {
+ i = m_threatlist.end();
+ advance(i, - (int32)position - 1);
+ }
+ else
+ {
+ i = m_threatlist.begin();
+ if(targetType == SELECT_TARGET_TOPAGGRO)
+ advance(i, position);
+ else // random
+ advance(i, position + rand()%(m_threatlist.size() - position));
+ }
+
+ if(SelectTargetHelper(me, (*i)->getTarget(), playerOnly, dist, aura))
+ return (*i)->getTarget();
+ else
+ m_threatlist.erase(i);
+ }
+ }
+
+ return NULL;
}
-void SimpleCharmedAI::UpdateAI(const uint32 /*diff*/)
+void CreatureAI::SelectTargetList(std::list<Unit*> &targetList, uint32 num, SelectAggroTarget targetType, float dist, bool playerOnly, int32 aura)
{
- Creature *charmer = (Creature*)me->GetCharmer();
+ if(targetType == SELECT_TARGET_NEAREST || targetType == SELECT_TARGET_FARTHEST)
+ {
+ std::list<HostilReference*> &m_threatlist = m_creature->getThreatManager().getThreatList();
+ if(m_threatlist.empty())
+ return;
+
+ for(std::list<HostilReference*>::iterator itr = m_threatlist.begin(); itr!= m_threatlist.end(); ++itr)
+ if(SelectTargetHelper(me, (*itr)->getTarget(), playerOnly, dist, aura))
+ targetList.push_back((*itr)->getTarget());
- //kill self if charm aura has infinite duration
- if(charmer->IsInEvadeMode())
+ targetList.sort(TargetDistanceOrder(me));
+ targetList.resize(num);
+ if(targetType == SELECT_TARGET_FARTHEST)
+ targetList.reverse();
+ }
+ else
{
- Unit::AuraEffectList const& auras = me->GetAurasByType(SPELL_AURA_MOD_CHARM);
- for(Unit::AuraEffectList::const_iterator iter = auras.begin(); iter != auras.end(); ++iter)
- if((*iter)->GetCasterGUID() == charmer->GetGUID() && (*iter)->GetParentAura()->IsPermanent())
+ std::list<HostilReference*> m_threatlist = me->getThreatManager().getThreatList();
+ std::list<HostilReference*>::iterator i;
+ while(!m_threatlist.empty() && num)
+ {
+ if(targetType == SELECT_TARGET_BOTTOMAGGRO)
{
- charmer->Kill(me);
- return;
+ i = m_threatlist.end();
+ --i;
}
+ else
+ {
+ i = m_threatlist.begin();
+ if(targetType == SELECT_TARGET_RANDOM)
+ advance(i, rand()%m_threatlist.size());
+ }
+
+ if(SelectTargetHelper(me, (*i)->getTarget(), playerOnly, dist, aura))
+ {
+ targetList.push_back((*i)->getTarget());
+ --num;
+ }
+ m_threatlist.erase(i);
+ }
}
+}
+
+void CreatureAI::FillAISpellInfo()
+{
+ AISpellInfo = new AISpellInfoType[GetSpellStore()->GetNumRows()];
- if(!charmer->isInCombat())
- me->GetMotionMaster()->MoveFollow(charmer, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
+ AISpellInfoType *AIInfo = AISpellInfo;
+ const SpellEntry * spellInfo;
- Unit *target = me->getVictim();
- if(!target || !charmer->canAttack(target))
- AttackStart(charmer->SelectNearestTarget());
+ for(uint32 i = 0; i < GetSpellStore()->GetNumRows(); ++i, ++AIInfo)
+ {
+ spellInfo = GetSpellStore()->LookupEntry(i);
+ if(!spellInfo)
+ continue;
+
+ if(spellInfo->Attributes & SPELL_ATTR_CASTABLE_WHILE_DEAD)
+ AIInfo->condition = AICOND_DIE;
+ else if(IsPassiveSpell(i) || GetSpellDuration(spellInfo) == -1)
+ AIInfo->condition = AICOND_AGGRO;
+ else
+ AIInfo->condition = AICOND_COMBAT;
+
+ if(AIInfo->cooldown < spellInfo->RecoveryTime)
+ AIInfo->cooldown = spellInfo->RecoveryTime;
+
+ for(uint32 j = 0; j < 3; ++j)
+ {
+ if(spellInfo->EffectImplicitTargetA[j] == TARGET_UNIT_TARGET_ENEMY
+ || spellInfo->EffectImplicitTargetA[j] == TARGET_DST_TARGET_ENEMY)
+ {
+ if(AIInfo->target < AITARGET_VICTIM)
+ AIInfo->target = AITARGET_VICTIM;
+ }
+
+ if(spellInfo->Effect[j] == SPELL_EFFECT_APPLY_AURA)
+ {
+ if(spellInfo->EffectImplicitTargetA[j] == TARGET_UNIT_TARGET_ENEMY)
+ {
+ if(AIInfo->target < AITARGET_DEBUFF)
+ AIInfo->target = AITARGET_DEBUFF;
+ }
+ else if(IsPositiveSpell(i))
+ {
+ if(AIInfo->target < AITARGET_BUFF)
+ AIInfo->target = AITARGET_BUFF;
+ }
+ }
+ }
+ }
}
/*void CreatureAI::AttackedBy( Unit* attacker )
diff --git a/src/game/CreatureAI.h b/src/game/CreatureAI.h
index e3a5a674e68..c46dd2a54f2 100644
--- a/src/game/CreatureAI.h
+++ b/src/game/CreatureAI.h
@@ -21,23 +21,21 @@
#ifndef TRINITY_CREATUREAI_H
#define TRINITY_CREATUREAI_H
+#include "UnitAI.h"
#include "Common.h"
-#include "Platform/Define.h"
-#include "Policies/Singleton.h"
-#include "Dynamic/ObjectRegistry.h"
-#include "Dynamic/FactoryHolder.h"
class WorldObject;
class Unit;
class Creature;
class Player;
struct SpellEntry;
+struct AISpellInfoType;
#define TIME_INTERVAL_LOOK 5000
#define VISIBILITY_RANGE 10000
//Spell targets used by SelectSpell
-enum SelectTarget
+enum SelectTargetType
{
SELECT_TARGET_DONTCARE = 0, //All target types allowed
@@ -77,120 +75,11 @@ enum SCEquip
EQUIP_UNEQUIP = 0
};
-class EventMap : private std::map<uint32, uint32>
-{
- private:
- uint32 m_time, m_phase;
- public:
- explicit EventMap() : m_phase(0), m_time(0) {}
-
- void Reset() { clear(); m_time = 0; m_phase = 0; }
-
- void Update(uint32 time) { m_time += time; }
-
- void SetPhase(uint32 phase)
- {
- if(phase && phase < 9)
- m_phase = (1 << (phase + 24));
- }
-
- void ScheduleEvent(uint32 eventId, uint32 time, uint32 gcd = 0, uint32 phase = 0)
- {
- time += m_time;
- if(gcd && gcd < 9)
- eventId |= (1 << (gcd + 16));
- if(phase && phase < 9)
- eventId |= (1 << (phase + 24));
- iterator itr = find(time);
- while(itr != end())
- {
- ++time;
- itr = find(time);
- }
- insert(std::make_pair(time, eventId));
- }
-
- uint32 ExecuteEvent()
- {
- while(!empty())
- {
- if(begin()->first > m_time)
- return 0;
- else if(m_phase && (begin()->second & 0xFF000000) && !(begin()->second & m_phase))
- erase(begin());
- else
- {
- uint32 eventId = (begin()->second & 0x0000FFFF);
- erase(begin());
- return eventId;
- }
- }
- return 0;
- }
-
- void DelayEvents(uint32 time, uint32 gcd)
- {
- time += m_time;
- gcd = (1 << (gcd + 16));
- for(iterator itr = begin(); itr != end();)
- {
- if(itr->first >= time)
- break;
- if(itr->second & gcd)
- {
- ScheduleEvent(time, itr->second);
- erase(itr++);
- }
- else
- ++itr;
- }
- }
-};
-
-class TRINITY_DLL_SPEC UnitAI
-{
- protected:
- Unit* const me;
- public:
- explicit UnitAI(Unit *u) : me(u) {}
- virtual void AttackStart(Unit *);
- virtual void UpdateAI(const uint32 diff) = 0;
-
- virtual void InitializeAI() { Reset(); }
-
- virtual void Reset() {};
-
- // Called when unit is charmed
- virtual void OnCharmed(bool apply) = 0;
-
- // Pass parameters between AI
- virtual void DoAction(const int32 param) {}
-
- //Do melee swing of current victim if in rnage and ready and not casting
- void DoMeleeAttackIfReady();
-};
-
-class TRINITY_DLL_SPEC PlayerAI : public UnitAI
-{
- protected:
- Player* const me;
- public:
- explicit PlayerAI(Player *p) : UnitAI((Unit*)p), me(p) {}
-
- void OnCharmed(bool apply);
-};
-
-class TRINITY_DLL_SPEC SimpleCharmedAI : public PlayerAI
-{
- public:
- void UpdateAI(const uint32 diff);
-};
-
class TRINITY_DLL_SPEC CreatureAI : public UnitAI
{
protected:
- Creature* const me;
- Creature* const m_creature;
+ Creature * const me;
+ Creature * const m_creature;
bool UpdateVictim();
public:
@@ -235,7 +124,7 @@ class TRINITY_DLL_SPEC CreatureAI : public UnitAI
//virtual void AttackedBy(Unit* attacker);
// Called when creature is spawned or respawned (for reseting variables)
- virtual void JustRespawned() {}
+ virtual void JustRespawned() { Reset(); }
// Called at waypoint reached or point movement finished
virtual void MovementInform(uint32 /*MovementType*/, uint32 /*Data*/) {}
@@ -273,22 +162,15 @@ class TRINITY_DLL_SPEC CreatureAI : public UnitAI
// Pointer to controlled by AI creature
//Creature* const m_creature;
-};
-
-struct SelectableAI : public FactoryHolder<CreatureAI>, public Permissible<Creature>
-{
-
- SelectableAI(const char *id) : FactoryHolder<CreatureAI>(id) {}
-};
-template<class REAL_AI>
-struct CreatureAIFactory : public SelectableAI
-{
- CreatureAIFactory(const char *name) : SelectableAI(name) {}
+ Unit* SelectTarget(SelectAggroTarget target, uint32 position = 0, float dist = 0, bool playerOnly = false, int32 aura = 0);
+ void SelectTargetList(std::list<Unit*> &targetList, uint32 num, SelectAggroTarget target, float dist = 0, bool playerOnly = false, int32 aura = 0);
- CreatureAI* Create(void *) const;
+ static AISpellInfoType *AISpellInfo;
+ static void FillAISpellInfo();
- int Permit(const Creature *c) const { return REAL_AI::Permissible(c); }
+ protected:
+ bool _EnterEvadeMode();
};
enum Permitions
@@ -301,8 +183,4 @@ enum Permitions
PERMIT_BASE_SPECIAL = 800
};
-typedef FactoryHolder<CreatureAI> CreatureAICreator;
-typedef FactoryHolder<CreatureAI>::FactoryHolderRegistry CreatureAIRegistry;
-typedef FactoryHolder<CreatureAI>::FactoryHolderRepository CreatureAIRepository;
#endif
-
diff --git a/src/game/CreatureAIFactory.h b/src/game/CreatureAIFactory.h
new file mode 100644
index 00000000000..d546c2b1720
--- /dev/null
+++ b/src/game/CreatureAIFactory.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * Copyright (C) 2008-2009 Trinity <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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef TRINITY_CREATUREAIFACTORY_H
+#define TRINITY_CREATUREAIFACTORY_H
+
+//#include "Policies/Singleton.h"
+#include "Dynamic/ObjectRegistry.h"
+#include "Dynamic/FactoryHolder.h"
+
+struct SelectableAI : public FactoryHolder<CreatureAI>, public Permissible<Creature>
+{
+ SelectableAI(const char *id) : FactoryHolder<CreatureAI>(id) {}
+};
+
+template<class REAL_AI>
+struct CreatureAIFactory : public SelectableAI
+{
+ CreatureAIFactory(const char *name) : SelectableAI(name) {}
+
+ CreatureAI* Create(void *) const;
+
+ int Permit(const Creature *c) const { 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 FactoryHolder<CreatureAI>::FactoryHolderRepository CreatureAIRepository;
+#endif
diff --git a/src/game/CreatureAIImpl.h b/src/game/CreatureAIImpl.h
index a8b8271c5ff..7edebb709fd 100644
--- a/src/game/CreatureAIImpl.h
+++ b/src/game/CreatureAIImpl.h
@@ -20,14 +20,156 @@
#ifndef CREATUREAIIMPL_H
#define CREATUREAIIMPL_H
-#include "CreatureAI.h"
+#include "Common.h"
+#include "Platform/Define.h"
-template<class REAL_AI>
-inline CreatureAI*
-CreatureAIFactory<REAL_AI>::Create(void *data) const
+#define HEROIC(n,h) (HeroicMode ? h : n)
+
+template<class T>
+inline
+const T& RAND(const T& v1, const T& v2)
+{
+ return rand()%2 ? v1 : v2;
+}
+
+template<class T>
+inline
+const T& RAND(const T& v1, const T& v2, const T& v3)
+{
+ switch(rand()%3)
+ {
+ default:
+ case 0: return v1;
+ case 1: return v2;
+ case 2: return v3;
+ }
+}
+
+template<class T>
+inline
+const T& RAND(const T& v1, const T& v2, const T& v3, const T& v4)
{
- Creature* creature = reinterpret_cast<Creature *>(data);
- return (new REAL_AI(creature));
+ switch(rand()%4)
+ {
+ default:
+ case 0: return v1;
+ case 1: return v2;
+ case 2: return v3;
+ case 3: return v4;
+ }
}
+
+template<class T>
+inline
+const T& RAND(const T& v1, const T& v2, const T& v3, const T& v4, const T& v5)
+{
+ switch(rand()%4)
+ {
+ default:
+ case 0: return v1;
+ case 1: return v2;
+ case 2: return v3;
+ case 3: return v4;
+ case 4: return v5;
+ }
+}
+
+class EventMap : private std::map<uint32, uint32>
+{
+ private:
+ uint32 m_time, m_phase;
+ public:
+ explicit EventMap() : m_phase(0), m_time(0) {}
+
+ void Reset() { clear(); m_time = 0; m_phase = 0; }
+
+ void Update(uint32 time) { m_time += time; }
+
+ void SetPhase(uint32 phase)
+ {
+ if(phase && phase < 9)
+ m_phase = (1 << (phase + 24));
+ }
+
+ void ScheduleEvent(uint32 eventId, uint32 time, uint32 gcd = 0, uint32 phase = 0)
+ {
+ time += m_time;
+ if(gcd && gcd < 9)
+ eventId |= (1 << (gcd + 16));
+ if(phase && phase < 9)
+ eventId |= (1 << (phase + 24));
+ iterator itr = find(time);
+ while(itr != end())
+ {
+ ++time;
+ itr = find(time);
+ }
+ insert(std::make_pair(time, eventId));
+ }
+
+ uint32 ExecuteEvent()
+ {
+ while(!empty())
+ {
+ if(begin()->first > m_time)
+ return 0;
+ else if(m_phase && (begin()->second & 0xFF000000) && !(begin()->second & m_phase))
+ erase(begin());
+ else
+ {
+ uint32 eventId = (begin()->second & 0x0000FFFF);
+ erase(begin());
+ return eventId;
+ }
+ }
+ return 0;
+ }
+
+ void DelayEvents(uint32 time, uint32 gcd)
+ {
+ time += m_time;
+ gcd = (1 << (gcd + 16));
+ for(iterator itr = begin(); itr != end();)
+ {
+ if(itr->first >= time)
+ break;
+ if(itr->second & gcd)
+ {
+ ScheduleEvent(time, itr->second);
+ erase(itr++);
+ }
+ else
+ ++itr;
+ }
+ }
+};
+
+enum AITarget
+{
+ AITARGET_SELF,
+ AITARGET_VICTIM,
+ AITARGET_ENEMY,
+ AITARGET_ALLY,
+ AITARGET_BUFF,
+ AITARGET_DEBUFF,
+};
+
+enum AICondition
+{
+ AICOND_AGGRO,
+ AICOND_COMBAT,
+ AICOND_DIE,
+};
+
+#define AI_DEFAULT_COOLDOWN 5000
+
+struct AISpellInfoType
+{
+ AISpellInfoType() : target(AITARGET_SELF), condition(AICOND_COMBAT), cooldown(AI_DEFAULT_COOLDOWN) {}
+ AITarget target;
+ AICondition condition;
+ uint32 cooldown;
+};
+
#endif
diff --git a/src/game/CreatureAIRegistry.cpp b/src/game/CreatureAIRegistry.cpp
index 6253c06b8bc..162ebd9b47c 100644
--- a/src/game/CreatureAIRegistry.cpp
+++ b/src/game/CreatureAIRegistry.cpp
@@ -23,16 +23,16 @@
#include "AggressorAI.h"
#include "GuardAI.h"
#include "PetAI.h"
-#include "PossessedAI.h"
#include "TotemAI.h"
#include "OutdoorPvPObjectiveAI.h"
#include "CreatureEventAI.h"
#include "RandomMovementGenerator.h"
-#include "CreatureAIImpl.h"
#include "MovementGeneratorImpl.h"
#include "CreatureAIRegistry.h"
#include "WaypointMovementGenerator.h"
+#include "CreatureAIFactory.h"
+#include "CreatureAIImpl.h"
namespace AIRegistry
{
void Initialize()
@@ -46,7 +46,7 @@ namespace AIRegistry
(new CreatureAIFactory<PetAI>("PetAI"))->RegisterSelf();
(new CreatureAIFactory<TotemAI>("TotemAI"))->RegisterSelf();
(new CreatureAIFactory<OutdoorPvPObjectiveAI>("OutdoorPvPObjectiveAI"))->RegisterSelf();
- (new CreatureAIFactory<PossessedAI>("PossessedAI"))->RegisterSelf();
+ (new CreatureAIFactory<SpellAI>("SpellAI"))->RegisterSelf();
(new CreatureAIFactory<CreatureEventAI>("EventAI"))->RegisterSelf();
(new MovementGeneratorFactory<RandomMovementGenerator<Creature> >(RANDOM_MOTION_TYPE))->RegisterSelf();
diff --git a/src/game/CreatureAISelector.cpp b/src/game/CreatureAISelector.cpp
index a698d094e18..bac4f3a4973 100644
--- a/src/game/CreatureAISelector.cpp
+++ b/src/game/CreatureAISelector.cpp
@@ -19,7 +19,6 @@
*/
#include "Creature.h"
-#include "CreatureAIImpl.h"
#include "CreatureAISelector.h"
#include "NullCreatureAI.h"
#include "Policies/SingletonImp.h"
@@ -27,6 +26,7 @@
#include "ScriptCalls.h"
#include "Pet.h"
#include "TemporarySummon.h"
+#include "CreatureAIFactory.h"
INSTANTIATE_SINGLETON_1(CreatureAIRegistry);
INSTANTIATE_SINGLETON_1(MovementGeneratorRegistry);
@@ -69,6 +69,18 @@ namespace FactorySelector
ai_factory = ai_registry.GetRegistryItem("CritterAI");
}
+ if(!ai_factory)
+ {
+ for(uint32 i = 0; i < CREATURE_MAX_SPELLS; ++i)
+ {
+ if(creature->m_spells[i])
+ {
+ ai_factory = ai_registry.GetRegistryItem("SpellAI");
+ break;
+ }
+ }
+ }
+
// select by permit check
if(!ai_factory)
{
diff --git a/src/game/CreatureEventAI.cpp b/src/game/CreatureEventAI.cpp
index fb7b7119860..5a84d43e80f 100644
--- a/src/game/CreatureEventAI.cpp
+++ b/src/game/CreatureEventAI.cpp
@@ -1054,14 +1054,7 @@ void CreatureEventAI::JustReachedHome()
void CreatureEventAI::EnterEvadeMode()
{
- m_creature->RemoveAllAuras();
- m_creature->DeleteThreatList();
- m_creature->CombatStop(true);
-
- if (m_creature->isAlive())
- m_creature->GetMotionMaster()->MoveTargetedHome();
-
- m_creature->SetLootRecipient(NULL);
+ CreatureAI::EnterEvadeMode();
if (bEmptyList)
return;
@@ -1295,13 +1288,10 @@ void CreatureEventAI::UpdateAI(const uint32 diff)
break;
case EVENT_T_RANGE:
if (Combat)
- {
- if (m_creature->IsWithinDistInMap(m_creature->getVictim(),(float)(*i).Event.event_param2))
- {
- if (m_creature->GetDistance(m_creature->getVictim()) >= (float)(*i).Event.event_param1)
+ if (m_creature->IsInMap(m_creature->getVictim()))
+ if (m_creature->IsInRange(m_creature->getVictim(),
+ (float)(*i).Event.event_param1,(float)(*i).Event.event_param2))
ProcessEvent(*i);
- }
- }
break;
}
}
@@ -1555,8 +1545,7 @@ bool CreatureEventAI::CanCast(Unit* Target, SpellEntry const *Spell, bool Trigge
return false;
//Unit is out of range of this spell
- if (me->GetDistance(Target) > me->GetSpellMaxRangeForTarget(Target, TempRange)
- || me->GetDistance(Target) < me->GetSpellMinRangeForTarget(Target, TempRange))
+ if (!m_creature->IsInRange(Target,TempRange->minRangeHostile,TempRange->maxRangeHostile))
return false;
return true;
diff --git a/src/game/DBCEnums.h b/src/game/DBCEnums.h
index 655c9967989..44ab34d7a11 100644
--- a/src/game/DBCEnums.h
+++ b/src/game/DBCEnums.h
@@ -48,7 +48,7 @@ enum AchievementFlags
ACHIEVEMENT_FLAG_SUMM = 0x00000008, // Use summ criteria value from all reqirements (and calculate max value)
ACHIEVEMENT_FLAG_MAX_USED = 0x00000010, // Show max criteria (and calculate max value ??)
ACHIEVEMENT_FLAG_REQ_COUNT = 0x00000020, // Use not zero req count (and calculate max value)
- ACHIEVEMENT_FLAG_AVERANGE = 0x00000040, // Show as averange value (value / time_in_days) depend from other flag (by def use last criteria value)
+ ACHIEVEMENT_FLAG_AVERAGE = 0x00000040, // Show as average value (value / time_in_days) depend from other flag (by def use last criteria value)
ACHIEVEMENT_FLAG_BAR = 0x00000080, // Show as progress bar (value / max vale) depend from other flag (by def use last criteria value)
ACHIEVEMENT_FLAG_REALM_FIRST_REACH = 0x00000100, //
ACHIEVEMENT_FLAG_REALM_FIRST_KILL = 0x00000200, //
diff --git a/src/game/DBCStructure.h b/src/game/DBCStructure.h
index 8c8195c018b..d5078e8b408 100644
--- a/src/game/DBCStructure.h
+++ b/src/game/DBCStructure.h
@@ -1143,7 +1143,7 @@ struct RandomPropertiesPointsEntry
struct ScalingStatDistributionEntry
{
uint32 Id;
- uint32 StatMod[10];
+ int32 StatMod[10];
uint32 Modifier[10];
uint32 MaxLevel;
};
@@ -1152,7 +1152,58 @@ struct ScalingStatValuesEntry
{
uint32 Id;
uint32 Level;
- uint32 Multiplier[17];
+ uint32 ssdMultiplier[5]; // Multiplier for ScalingStatDistribution
+ uint32 armorMod[4]; // Armor for level
+ uint32 dpsMod[6]; // DPS mod for level
+ uint32 spellBonus; // not sure.. TODO: need more info about
+ uint32 feralBonus; // Feral AP bonus
+
+ uint32 getssdMultiplier(uint32 mask) const
+ {
+ if (mask&0x001F)
+ {
+ if(mask & 0x00000001) return ssdMultiplier[0];
+ if(mask & 0x00000002) return ssdMultiplier[1];
+ if(mask & 0x00000004) return ssdMultiplier[2];
+ if(mask & 0x00000008) return ssdMultiplier[3];
+ if(mask & 0x00000010) return ssdMultiplier[4];
+ }
+ return 0;
+ }
+ uint32 getArmorMod(uint32 mask) const
+ {
+ if (mask&0x01E0)
+ {
+ if(mask & 0x00000020) return armorMod[0];
+ if(mask & 0x00000040) return armorMod[1];
+ if(mask & 0x00000080) return armorMod[2];
+ if(mask & 0x00000100) return armorMod[3];
+ }
+ return 0;
+ }
+ uint32 getDPSMod(uint32 mask) const
+ {
+ if (mask&0x7E00)
+ {
+ if(mask & 0x00000200) return dpsMod[0];
+ if(mask & 0x00000400) return dpsMod[1];
+ if(mask & 0x00000800) return dpsMod[2];
+ if(mask & 0x00001000) return dpsMod[3];
+ if(mask & 0x00002000) return dpsMod[4];
+ if(mask & 0x00004000) return dpsMod[5];
+ }
+ return 0;
+ }
+ uint32 getSpellBonus(uint32 mask) const
+ {
+ if (mask & 0x00008000) return spellBonus;
+ return 0;
+ }
+ uint32 getFeralBonus(uint32 mask) const
+ {
+ if (mask & 0x00010000) return feralBonus;
+ return 0;
+ }
};
//struct SkillLineCategoryEntry{
@@ -1517,7 +1568,7 @@ struct TaxiNodesEntry
float x; // 2 m_x
float y; // 3 m_y
float z; // 4 m_z
- //char* name[16]; // 5-21 m_Name_lang
+ char* name[16]; // 5-21 m_Name_lang
// 22 string flags
uint32 MountCreatureID[2]; // 23-24 m_MountCreatureID[2]
};
diff --git a/src/game/DBCfmt.h b/src/game/DBCfmt.h
index ea2198ef22c..170fd25dd9f 100644
--- a/src/game/DBCfmt.h
+++ b/src/game/DBCfmt.h
@@ -96,7 +96,7 @@ const char StableSlotPricesfmt[] = "ni";
const char SummonPropertiesfmt[] = "niiiii";
const char TalentEntryfmt[]="niiiiiiiixxxxixxixxxxxx";
const char TalentTabEntryfmt[]="nxxxxxxxxxxxxxxxxxxxiiix";
-const char TaxiNodesEntryfmt[]="nifffxxxxxxxxxxxxxxxxxii";
+const char TaxiNodesEntryfmt[]="nifffssssssssssssssssxii";
const char TaxiPathEntryfmt[]="niii";
const char TaxiPathNodeEntryfmt[]="diiifffiixx";
const char TotemCategoryEntryfmt[]="nxxxxxxxxxxxxxxxxxii";
diff --git a/src/game/GameObject.cpp b/src/game/GameObject.cpp
index 2f1014eb769..540ea1e0dd7 100644
--- a/src/game/GameObject.cpp
+++ b/src/game/GameObject.cpp
@@ -174,7 +174,7 @@ bool GameObject::Create(uint32 guidlow, uint32 name_id, Map *map, uint32 phaseMa
//Normally non-players do not teleport to other maps.
if(map->IsDungeon() && ((InstanceMap*)map)->GetInstanceData())
{
- ((InstanceMap*)map)->GetInstanceData()->OnObjectCreate(this);
+ ((InstanceMap*)map)->GetInstanceData()->OnObjectCreate(this, true);
}
return true;
@@ -198,7 +198,7 @@ void GameObject::Update(uint32 /*p_time*/)
{
// Arming Time for GAMEOBJECT_TYPE_TRAP (6)
Unit* owner = GetOwner();
- if (owner && ((Player*)owner)->isInCombat())
+ if (owner && owner->isInCombat())
m_cooldownTime = time(NULL) + GetGOInfo()->trap.startDelay;
m_lootState = GO_READY;
break;
diff --git a/src/game/GridNotifiers.h b/src/game/GridNotifiers.h
index 03d8ea11b16..a9925f67406 100644
--- a/src/game/GridNotifiers.h
+++ b/src/game/GridNotifiers.h
@@ -489,7 +489,7 @@ namespace Trinity
void Visit(PlayerMapType &m)
{
for(PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
- if(itr->getSource()->InSamePhase(i_searcher) && itr->getSource()->GetDistance(i_searcher) <= i_dist)
+ if (itr->getSource()->InSamePhase(i_searcher) && itr->getSource()->IsWithinDist(i_searcher,i_dist))
i_do(itr->getSource());
}
@@ -499,6 +499,53 @@ namespace Trinity
// CHECKS && DO classes
// WorldObject check classes
+ class RaiseDeadObjectCheck
+ {
+ public:
+ RaiseDeadObjectCheck(Unit* funit, float range) : i_funit(funit), i_range(range) {}
+ bool operator()(Creature* u)
+ {
+ if (i_funit->GetTypeId()!=TYPEID_PLAYER || !((Player*)i_funit)->isHonorOrXPTarget(u) ||
+ u->getDeathState() != CORPSE || u->isDeadByDefault() || u->isInFlight() ||
+ ( u->GetCreatureTypeMask() & (1 << (CREATURE_TYPE_HUMANOID-1)) )==0 ||
+ (u->GetDisplayId() != u->GetNativeDisplayId()))
+ return false;
+
+ return i_funit->IsWithinDistInMap(u, i_range);
+ }
+ template<class NOT_INTERESTED> bool operator()(NOT_INTERESTED*) { return false; }
+ private:
+ Unit* const i_funit;
+ float i_range;
+ };
+
+ class ExplodeCorpseObjectCheck
+ {
+ public:
+ ExplodeCorpseObjectCheck(Unit* funit, float range) : i_funit(funit), i_range(range) {}
+ bool operator()(Player* u)
+ {
+ if (u->getDeathState()!=CORPSE || u->isInFlight() ||
+ u->HasAuraType(SPELL_AURA_GHOST) || (u->GetDisplayId() != u->GetNativeDisplayId()))
+ return false;
+
+ return i_funit->IsWithinDistInMap(u, i_range);
+ }
+ bool operator()(Creature* u)
+ {
+ if (u->getDeathState()!=CORPSE || u->isInFlight() || u->isDeadByDefault() ||
+ (u->GetDisplayId() != u->GetNativeDisplayId()) ||
+ (u->GetCreatureTypeMask() & CREATURE_TYPEMASK_MECHANICAL_OR_ELEMENTAL)!=0)
+ return false;
+
+ return i_funit->IsWithinDistInMap(u, i_range);
+ }
+ template<class NOT_INTERESTED> bool operator()(NOT_INTERESTED*) { return false; }
+ private:
+ Unit* const i_funit;
+ float i_range;
+ };
+
class CannibalizeObjectCheck
{
public:
@@ -508,22 +555,16 @@ namespace Trinity
if( i_funit->IsFriendlyTo(u) || u->isAlive() || u->isInFlight() )
return false;
- if(i_funit->IsWithinDistInMap(u, i_range) )
- return true;
-
- return false;
+ return i_funit->IsWithinDistInMap(u, i_range);
}
bool operator()(Corpse* u);
bool operator()(Creature* u)
{
- if( i_funit->IsFriendlyTo(u) || u->isAlive() || u->isInFlight() ||
+ if (i_funit->IsFriendlyTo(u) || u->isAlive() || u->isInFlight() ||
(u->GetCreatureTypeMask() & CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD)==0)
return false;
- if(i_funit->IsWithinDistInMap(u, i_range) )
- return true;
-
- return false;
+ return i_funit->IsWithinDistInMap(u, i_range);
}
template<class NOT_INTERESTED> bool operator()(NOT_INTERESTED*) { return false; }
private:
diff --git a/src/game/GridNotifiersImpl.h b/src/game/GridNotifiersImpl.h
index 7726d5647bd..12f3706c4e2 100644
--- a/src/game/GridNotifiersImpl.h
+++ b/src/game/GridNotifiersImpl.h
@@ -178,8 +178,11 @@ inline void Trinity::DynamicObjectUpdater::VisitHelper(Unit* target)
if (i_dynobject.IsAffecting(target))
return;
- SpellEntry const *spellInfo = sSpellStore.LookupEntry(i_dynobject.GetSpellId());
uint32 eff_index = i_dynobject.GetEffIndex();
+ if(target->HasAuraEffect(i_dynobject.GetSpellId(), eff_index, i_check->GetGUID()))
+ return;
+
+ SpellEntry const *spellInfo = sSpellStore.LookupEntry(i_dynobject.GetSpellId());
if(spellInfo->EffectImplicitTargetB[eff_index] == TARGET_DEST_DYNOBJ_ALLY
|| spellInfo->EffectImplicitTargetB[eff_index] == TARGET_UNIT_AREA_ALLY_DST)
{
@@ -205,7 +208,9 @@ inline void Trinity::DynamicObjectUpdater::VisitHelper(Unit* target)
if (target->IsImmunedToSpell(spellInfo) || target->IsImmunedToSpellEffect(spellInfo, eff_index))
return;
// Apply PersistentAreaAura on target
- target->AddAuraEffect(spellInfo->Id, eff_index, i_dynobject.GetCaster());
+ if(Aura *aur = target->AddAuraEffect(spellInfo, eff_index, i_dynobject.GetCaster()))
+ aur->SetAuraDuration(i_dynobject.GetDuration());
+
i_dynobject.AddAffected(target);
}
diff --git a/src/game/Group.cpp b/src/game/Group.cpp
index 02fc72f2022..d2c17680e52 100644
--- a/src/game/Group.cpp
+++ b/src/game/Group.cpp
@@ -571,7 +571,7 @@ void Group::GroupLoot(const uint64& playerGUID, Loot *loot, Creature *creature)
continue;
if ( i->AllowedForPlayer(member) )
{
- if (member->GetDistance2d(creature) < sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE))
+ if (member->IsWithinDist(creature,sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE),false))
{
r->playerVote[member->GetGUID()] = NOT_EMITED_YET;
++r->totalPlayersRolling;
@@ -621,7 +621,7 @@ void Group::NeedBeforeGreed(const uint64& playerGUID, Loot *loot, Creature *crea
if (playerToRoll->CanUseItem(item) && i->AllowedForPlayer(playerToRoll) )
{
- if (playerToRoll->GetDistance2d(creature) < sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE))
+ if (playerToRoll->IsWithinDist(creature,sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE),false))
{
r->playerVote[playerToRoll->GetGUID()] = NOT_EMITED_YET;
++r->totalPlayersRolling;
@@ -669,7 +669,7 @@ void Group::MasterLoot(const uint64& playerGUID, Loot* /*loot*/, Creature *creat
if (!looter->IsInWorld())
continue;
- if (looter->GetDistance2d(creature) < sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE))
+ if (looter->IsWithinDist(creature,sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE),false))
{
data << looter->GetGUID();
++real_count;
@@ -681,7 +681,7 @@ void Group::MasterLoot(const uint64& playerGUID, Loot* /*loot*/, Creature *creat
for(GroupReference *itr = GetFirstMember(); itr != NULL; itr = itr->next())
{
Player *looter = itr->getSource();
- if (looter->GetDistance2d(creature) < sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE))
+ if (looter->IsWithinDist(creature,sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE),false))
looter->GetSession()->SendPacket(&data);
}
}
@@ -1338,7 +1338,7 @@ void Group::UpdateLooterGuid( Creature* creature, bool ifneed )
{
// not update if only update if need and ok
Player* looter = ObjectAccessor::FindPlayer(guid_itr->guid);
- if(looter && looter->GetDistance2d(creature) < sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE))
+ if(looter && looter->IsWithinDist(creature,sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE),false))
return;
}
++guid_itr;
@@ -1351,7 +1351,7 @@ void Group::UpdateLooterGuid( Creature* creature, bool ifneed )
{
if(Player* pl = ObjectAccessor::FindPlayer(itr->guid))
{
- if (pl->GetDistance2d(creature) < sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE))
+ if (pl->IsWithinDist(creature,sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE),false))
{
bool refresh = pl->GetLootGUID()==creature->GetGUID();
@@ -1372,7 +1372,7 @@ void Group::UpdateLooterGuid( Creature* creature, bool ifneed )
{
if(Player* pl = ObjectAccessor::FindPlayer(itr->guid))
{
- if (pl->GetDistance2d(creature) < sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE))
+ if (pl->IsWithinDist(creature,sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE),false))
{
bool refresh = pl->GetLootGUID()==creature->GetGUID();
diff --git a/src/game/GroupHandler.cpp b/src/game/GroupHandler.cpp
index b0094989e19..cd7004f5a07 100644
--- a/src/game/GroupHandler.cpp
+++ b/src/game/GroupHandler.cpp
@@ -78,6 +78,12 @@ void WorldSession::HandleGroupInviteOpcode( WorldPacket & recv_data )
return;
}
+ // restrict invite to GMs
+ if (!sWorld.getConfig(CONFIG_ALLOW_GM_GROUP) && !GetPlayer()->isGameMaster() && player->isGameMaster())
+ {
+ SendPartyResult(PARTY_OP_INVITE, membername, PARTY_RESULT_CANT_FIND_TARGET);
+ return;
+ }
// can't group with
if(!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP) && GetPlayer()->GetTeam() != player->GetTeam())
{
diff --git a/src/game/GuardAI.cpp b/src/game/GuardAI.cpp
index b716642ebd7..b7268758583 100644
--- a/src/game/GuardAI.cpp
+++ b/src/game/GuardAI.cpp
@@ -126,7 +126,7 @@ void GuardAI::UpdateAI(const uint32 /*diff*/)
bool GuardAI::IsVisible(Unit *pl) const
{
- return m_creature->GetDistance(pl) < sWorld.getConfig(CONFIG_SIGHT_GUARDER)
+ return m_creature->IsWithinDist(pl,sWorld.getConfig(CONFIG_SIGHT_GUARDER))
&& pl->isVisibleForOrDetect(m_creature,true);
}
diff --git a/src/game/InstanceData.cpp b/src/game/InstanceData.cpp
index 92e4b4afe3d..96c10f7b85c 100644
--- a/src/game/InstanceData.cpp
+++ b/src/game/InstanceData.cpp
@@ -26,8 +26,9 @@
void InstanceData::SaveToDB()
{
- if(!Save()) return;
- std::string data = Save();
+ std::string data = GetSaveData();
+ if(data.empty())
+ return;
CharacterDatabase.escape_string(data);
CharacterDatabase.PExecute("UPDATE instance SET data = '%s' WHERE id = '%d'", data.c_str(), instance->GetInstanceId());
}
@@ -57,42 +58,66 @@ void InstanceData::OnCreatureCreate(Creature *creature, bool add)
OnCreatureCreate(creature, creature->GetEntry());
}
-void InstanceData::SetBossRoomDoor(uint32 id, GameObject *door, bool add)
+void InstanceData::LoadDoorData(const DoorData *data)
{
- if(id < bosses.size())
+ while(data->entry)
{
- if(add)
+ if(data->bossId < bosses.size())
+ doors.insert(std::make_pair(data->entry, DoorInfo(&bosses[data->bossId], data->type)));
+
+ ++data;
+ }
+ sLog.outDebug("InstanceData::LoadDoorData: %u doors loaded.", doors.size());
+}
+
+void InstanceData::UpdateDoorState(GameObject *door)
+{
+ DoorInfoMap::iterator lower = doors.lower_bound(door->GetEntry());
+ DoorInfoMap::iterator upper = doors.upper_bound(door->GetEntry());
+ if(lower == upper)
+ return;
+
+ bool open = true;
+ for(DoorInfoMap::iterator itr = lower; itr != upper; ++itr)
+ {
+ if(itr->second.type == DOOR_TYPE_ROOM)
{
- BossInfo *bossInfo = &bosses[id];
- bossInfo->roomDoor.insert(door);
- // Room door is only closed when encounter is in progress
- if(bossInfo->state == IN_PROGRESS)
- door->SetGoState(GO_STATE_READY);
- else
- door->SetGoState(GO_STATE_ACTIVE);
+ if(itr->second.bossInfo->state == IN_PROGRESS)
+ {
+ open = false;
+ break;
+ }
+ }
+ else if(itr->second.type == DOOR_TYPE_PASSAGE)
+ {
+ if(itr->second.bossInfo->state != DONE)
+ {
+ open = false;
+ break;
+ }
}
- else
- bosses[id].roomDoor.erase(door);
}
+
+ door->SetGoState(open ? GO_STATE_ACTIVE : GO_STATE_READY);
}
-void InstanceData::SetBossPassageDoor(uint32 id, GameObject *door, bool add)
+void InstanceData::AddDoor(GameObject *door, bool add)
{
- if(id < bosses.size())
+ DoorInfoMap::iterator lower = doors.lower_bound(door->GetEntry());
+ DoorInfoMap::iterator upper = doors.upper_bound(door->GetEntry());
+ if(lower == upper)
+ return;
+
+ for(DoorInfoMap::iterator itr = lower; itr != upper; ++itr)
{
if(add)
- {
- BossInfo *bossInfo = &bosses[id];
- bossInfo->passageDoor.insert(door);
- // Passage door is only opened when boss is defeated
- if(bossInfo->state == DONE)
- door->SetGoState(GO_STATE_ACTIVE);
- else
- door->SetGoState(GO_STATE_READY);
- }
+ itr->second.bossInfo->door[itr->second.type].insert(door);
else
- bosses[id].passageDoor.erase(door);
+ itr->second.bossInfo->door[itr->second.type].erase(door);
}
+
+ if(add)
+ UpdateDoorState(door);
}
void InstanceData::SetBossState(uint32 id, EncounterState state)
@@ -100,33 +125,41 @@ void InstanceData::SetBossState(uint32 id, EncounterState state)
if(id < bosses.size())
{
BossInfo *bossInfo = &bosses[id];
- bossInfo->state = state;
- switch(state)
+ if(bossInfo->state == TO_BE_DECIDED) // loading
+ bossInfo->state = state;
+ else
{
- case NOT_STARTED:
- // Open all room doors, close all passage doors
- for(DoorSet::iterator i = bossInfo->roomDoor.begin(); i != bossInfo->roomDoor.end(); ++i)
- (*i)->SetGoState(GO_STATE_ACTIVE);
- for(DoorSet::iterator i = bossInfo->passageDoor.begin(); i != bossInfo->passageDoor.end(); ++i)
- (*i)->SetGoState(GO_STATE_READY);
- break;
- case IN_PROGRESS:
- // Close all doors
- for(DoorSet::iterator i = bossInfo->roomDoor.begin(); i != bossInfo->roomDoor.end(); ++i)
- (*i)->SetGoState(GO_STATE_READY);
- for(DoorSet::iterator i = bossInfo->passageDoor.begin(); i != bossInfo->passageDoor.end(); ++i)
- (*i)->SetGoState(GO_STATE_READY);
- break;
- case DONE:
- // Open all doors
- for(DoorSet::iterator i = bossInfo->roomDoor.begin(); i != bossInfo->roomDoor.end(); ++i)
- (*i)->SetGoState(GO_STATE_ACTIVE);
- for(DoorSet::iterator i = bossInfo->passageDoor.begin(); i != bossInfo->passageDoor.end(); ++i)
- (*i)->SetGoState(GO_STATE_ACTIVE);
- break;
- default:
- break;
+ if(bossInfo->state == state)
+ return;
+ bossInfo->state = state;
+ SaveToDB();
}
+
+ for(uint32 type = 0; type < MAX_DOOR_TYPES; ++type)
+ for(DoorSet::iterator i = bossInfo->door[type].begin(); i != bossInfo->door[type].end(); ++i)
+ UpdateDoorState(*i);
}
}
+std::string InstanceData::LoadBossState(const char * data)
+{
+ if(!data) return NULL;
+ std::istringstream loadStream(data);
+ uint32 buff;
+ uint32 bossId = 0;
+ for(std::vector<BossInfo>::iterator i = bosses.begin(); i != bosses.end(); ++i, ++bossId)
+ {
+ loadStream >> buff;
+ if(buff < TO_BE_DECIDED)
+ SetBossState(bossId, (EncounterState)buff);
+ }
+ return loadStream.str();
+}
+
+std::string InstanceData::GetBossSaveData()
+{
+ std::ostringstream saveStream;
+ for(std::vector<BossInfo>::iterator i = bosses.begin(); i != bosses.end(); ++i)
+ saveStream << (uint32)i->state << " ";
+ return saveStream.str();
+}
diff --git a/src/game/InstanceData.h b/src/game/InstanceData.h
index 2d7e5f84746..91f589384a0 100644
--- a/src/game/InstanceData.h
+++ b/src/game/InstanceData.h
@@ -37,16 +37,40 @@ enum EncounterState
IN_PROGRESS = 1,
FAIL = 2,
DONE = 3,
- SPECIAL = 4
+ SPECIAL = 4,
+ TO_BE_DECIDED = 5,
};
typedef std::set<GameObject*> DoorSet;
+enum DoorType
+{
+ DOOR_TYPE_ROOM = 0,
+ DOOR_TYPE_PASSAGE,
+ MAX_DOOR_TYPES,
+};
+
struct BossInfo
{
- BossInfo() : state(NOT_STARTED) {}
+ BossInfo() : state(TO_BE_DECIDED) {}
EncounterState state;
- DoorSet roomDoor, passageDoor;
+ DoorSet door[MAX_DOOR_TYPES];
+};
+
+struct DoorInfo
+{
+ explicit DoorInfo(BossInfo *_bossInfo, DoorType _type)
+ : bossInfo(_bossInfo), type(_type) {}
+ BossInfo *bossInfo;
+ DoorType type;
+};
+
+typedef std::multimap<uint32 /*entry*/, DoorInfo> DoorInfoMap;
+
+struct DoorData
+{
+ uint32 entry, bossId;
+ DoorType type;
};
class TRINITY_DLL_SPEC InstanceData
@@ -62,10 +86,10 @@ class TRINITY_DLL_SPEC InstanceData
virtual void Initialize() {}
//On load
- virtual void Load(const char* /*data*/) {}
+ virtual void Load(const char * data) { LoadBossState(data); }
//When save is needed, this function generates the data
- virtual const char* Save() { return ""; }
+ virtual std::string GetSaveData() { return GetBossSaveData(); }
void SaveToDB();
@@ -80,15 +104,10 @@ class TRINITY_DLL_SPEC InstanceData
virtual void OnPlayerEnter(Player *) {}
//Called when a gameobject is created
- virtual void OnObjectCreate(GameObject *go, bool add)
- {
- OnObjectCreate(go);
- }
- virtual void OnObjectCreate(GameObject *) {}
+ virtual void OnObjectCreate(GameObject *go, bool add) { OnObjectCreate(go); }
//called on creature creation
virtual void OnCreatureCreate(Creature *, bool add);
- virtual void OnCreatureCreate(Creature *, uint32 entry) {}
//All-purpose data storage 64 bit
virtual uint64 GetData64(uint32 /*Data*/) { return 0; }
@@ -103,23 +122,22 @@ class TRINITY_DLL_SPEC InstanceData
//use HandleGameObject(GUID,boolen,NULL); in any other script
void HandleGameObject(uint64 GUID, bool open, GameObject *go = NULL);
- void SetBossState(uint32 id, EncounterState state);
+ virtual void SetBossState(uint32 id, EncounterState state);
protected:
- void SetBossNumber(uint32 number) { bosses.resize(number); }
- void SetBossRoomDoor(uint32 id, GameObject *door, bool add);
- void SetBossPassageDoor(uint32 id, GameObject *door, bool add);
+ void LoadDoorData(const DoorData *data);
- std::string GetBossSave()
- {
- std::ostringstream saveStream;
- for(std::vector<BossInfo>::iterator i = bosses.begin(); i != bosses.end(); ++i)
- saveStream << (uint32)i->state << " ";
- return saveStream.str();
- }
+ void SetBossNumber(uint32 number) { bosses.resize(number); }
+ void AddDoor(GameObject *door, bool add);
+ void UpdateDoorState(GameObject *door);
+ std::string LoadBossState(const char * data);
+ std::string GetBossSaveData();
private:
std::vector<BossInfo> bosses;
+ DoorInfoMap doors;
+ virtual void OnObjectCreate(GameObject *) {}
+ virtual void OnCreatureCreate(Creature *, uint32 entry) {}
};
#endif
diff --git a/src/game/InstanceSaveMgr.cpp b/src/game/InstanceSaveMgr.cpp
index 9332f4b8f0a..7e2ad67c518 100644
--- a/src/game/InstanceSaveMgr.cpp
+++ b/src/game/InstanceSaveMgr.cpp
@@ -40,6 +40,8 @@
#include "Group.h"
#include "InstanceData.h"
#include "ProgressBar.h"
+#include "Policies/Singleton.h"
+#include "Policies/SingletonImp.h"
INSTANTIATE_SINGLETON_1( InstanceSaveManager );
@@ -163,11 +165,11 @@ void InstanceSave::SaveToDB()
if(map)
{
assert(map->IsDungeon());
- InstanceData *iData = ((InstanceMap *)map)->GetInstanceData();
- if(iData && iData->Save())
+ if(InstanceData *iData = ((InstanceMap*)map)->GetInstanceData())
{
- data = iData->Save();
- CharacterDatabase.escape_string(data);
+ data = iData->GetSaveData();
+ if(!data.empty())
+ CharacterDatabase.escape_string(data);
}
}
diff --git a/src/game/InstanceSaveMgr.h b/src/game/InstanceSaveMgr.h
index 2a913e5cedf..29972210f3d 100644
--- a/src/game/InstanceSaveMgr.h
+++ b/src/game/InstanceSaveMgr.h
@@ -24,7 +24,7 @@
#include "Platform/Define.h"
#include "Policies/Singleton.h"
-#include "zthread/Mutex.h"
+#include "ace/Thread_Mutex.h"
#include <list>
#include <map>
#include "Utilities/UnorderedMap.h"
@@ -113,7 +113,7 @@ class InstanceSave
bool m_canReset;
};
-class TRINITY_DLL_DECL InstanceSaveManager : public Trinity::Singleton<InstanceSaveManager, Trinity::ClassLevelLockable<InstanceSaveManager, ZThread::Mutex> >
+class MANGOS_DLL_DECL InstanceSaveManager : public MaNGOS::Singleton<InstanceSaveManager, MaNGOS::ClassLevelLockable<InstanceSaveManager, ACE_Thread_Mutex> >
{
friend class InstanceSave;
public:
diff --git a/src/game/ItemPrototype.h b/src/game/ItemPrototype.h
index f87e52b2e22..e7a37dc8e14 100644
--- a/src/game/ItemPrototype.h
+++ b/src/game/ItemPrototype.h
@@ -600,46 +600,6 @@ struct ItemPrototype
return false;
}
- uint32 GetScalingStatValuesColumn() const
- {
- if(ScalingStatValue & 0x00000001) // stat mod
- return 0;
- if(ScalingStatValue & 0x00000002) // stat mod
- return 1;
- if(ScalingStatValue & 0x00000004) // stat mod
- return 2;
- if(ScalingStatValue & 0x00000008) // stat mod
- return 3;
- if(ScalingStatValue & 0x00000010) // stat mod
- return 4;
- if(ScalingStatValue & 0x00000020) // armor mod
- return 5;
- if(ScalingStatValue & 0x00000040) // armor mod
- return 6;
- if(ScalingStatValue & 0x00000080) // armor mod
- return 7;
- if(ScalingStatValue & 0x00000100) // armor mod
- return 8;
- if(ScalingStatValue & 0x00000200) // damage mod
- return 9;
- if(ScalingStatValue & 0x00000400) // damage mod
- return 10;
- if(ScalingStatValue & 0x00000800) // damage mod
- return 11;
- if(ScalingStatValue & 0x00001000) // damage mod
- return 12;
- if(ScalingStatValue & 0x00002000) // damage mod
- return 13;
- if(ScalingStatValue & 0x00004000) // damage mod
- return 14;
- if(ScalingStatValue & 0x00008000) // spell power
- return 15;
- if(ScalingStatValue & 0x00020000) // feral AP
- return 16;
-
- return 0;
- }
-
uint32 GetMaxStackSize() const { return Stackable > 0 ? uint32(Stackable) : uint32(0x7FFFFFFF-1); }
float getDPS() const
@@ -652,12 +612,12 @@ struct ItemPrototype
return temp*500/Delay;
}
- int32 getFeralBonus() const
+ int32 getFeralBonus(int32 extraDPS = 0) const
{
// 0x02A5F3 - is mask for Melee weapon from ItemSubClassMask.dbc
if (Class == ITEM_CLASS_WEAPON && (1<<SubClass)&0x02A5F3)
{
- int32 bonus = int32(getDPS()*14.0f) - 767;
+ int32 bonus = int32((extraDPS + getDPS())*14.0f) - 767;
if (bonus < 0)
return 0;
return bonus;
diff --git a/src/game/Language.h b/src/game/Language.h
index 69bfbf00159..8bc01a7deea 100644
--- a/src/game/Language.h
+++ b/src/game/Language.h
@@ -328,7 +328,8 @@ enum TrinityStrings
LANG_YOU_ALREADY_HAVE_PET = 344,
LANG_CUSTOMIZE_PLAYER = 345,
LANG_CUSTOMIZE_PLAYER_GUID = 346,
- // Room for more level 2 345-399 not used
+ LANG_COMMAND_GOTAXINODENOTFOUND = 347,
+ // Room for more level 2 348-399 not used
// level 3 chat
LANG_SCRIPTS_RELOADED = 400,
@@ -403,8 +404,7 @@ enum TrinityStrings
LANG_COMMAND_TP_ADDED = 463,
LANG_COMMAND_TP_ADDEDERR = 464,
LANG_COMMAND_TP_DELETED = 465,
- // 466, // not used
-
+ LANG_COMMAND_NOTAXINODEFOUND = 466,
LANG_COMMAND_TARGET_LISTAURAS = 467,
LANG_COMMAND_TARGET_AURADETAIL = 468,
LANG_COMMAND_TARGET_LISTAURATYPE = 469,
@@ -765,7 +765,9 @@ enum TrinityStrings
LANG_COMMAND_LEARN_PET_TALENTS = 1125,
LANG_RESET_PET_TALENTS = 1126,
LANG_RESET_PET_TALENTS_ONLINE = 1127,
- // Room for more level 3 1128-1199 not used
+ LANG_TAXINODE_ENTRY_LIST_CHAT = 1128,
+ LANG_TAXINODE_ENTRY_LIST_CONSOLE = 1129,
+ // Room for more level 3 1130-1199 not used
// Debug commands
LANG_CINEMATIC_NOT_EXIST = 1200,
diff --git a/src/game/Level1.cpp b/src/game/Level1.cpp
index 963e79f8829..45137c5b214 100644
--- a/src/game/Level1.cpp
+++ b/src/game/Level1.cpp
@@ -2091,12 +2091,12 @@ bool ChatHandler::HandleModifyMoneyCommand(const char* args)
uint32 moneyuser = chr->GetMoney();
- if(addmoney < 0)
+ if (addmoney < 0)
{
- int32 newmoney = moneyuser + addmoney;
+ int32 newmoney = int32(moneyuser) + addmoney;
sLog.outDetail(GetTrinityString(LANG_CURRENT_MONEY), moneyuser, addmoney, newmoney);
- if(newmoney <= 0 )
+ if (newmoney <= 0 )
{
PSendSysMessage(LANG_YOU_TAKE_ALL_MONEY, GetNameLink(chr).c_str());
if (needReportToTarget(chr))
@@ -2106,6 +2106,9 @@ bool ChatHandler::HandleModifyMoneyCommand(const char* args)
}
else
{
+ if (newmoney > MAX_MONEY_AMOUNT)
+ newmoney = MAX_MONEY_AMOUNT;
+
PSendSysMessage(LANG_YOU_TAKE_MONEY, abs(addmoney), GetNameLink(chr).c_str());
if (needReportToTarget(chr))
ChatHandler(chr).PSendSysMessage(LANG_YOURS_MONEY_TAKEN, GetNameLink().c_str(), abs(addmoney));
@@ -2117,7 +2120,11 @@ bool ChatHandler::HandleModifyMoneyCommand(const char* args)
PSendSysMessage(LANG_YOU_GIVE_MONEY, addmoney, GetNameLink(chr).c_str());
if (needReportToTarget(chr))
ChatHandler(chr).PSendSysMessage(LANG_YOURS_MONEY_GIVEN, GetNameLink().c_str(), addmoney);
- chr->ModifyMoney( addmoney );
+
+ if (addmoney >=MAX_MONEY_AMOUNT)
+ chr->SetMoney(MAX_MONEY_AMOUNT);
+ else
+ chr->ModifyMoney( addmoney );
}
sLog.outDetail(GetTrinityString(LANG_NEW_MONEY), moneyuser, addmoney, chr->GetMoney() );
@@ -2753,6 +2760,51 @@ bool ChatHandler::HandleGroupgoCommand(const char* args)
return true;
}
+bool ChatHandler::HandleGoTaxinodeCommand(const char* args)
+{
+ Player* _player = m_session->GetPlayer();
+
+ if (!*args)
+ return false;
+
+ char* cNodeId = extractKeyFromLink((char*)args,"Htaxinode");
+ if (!cNodeId)
+ return false;
+
+ int32 i_nodeId = atoi(cNodeId);
+ if (!i_nodeId)
+ return false;
+
+ TaxiNodesEntry const* node = sTaxiNodesStore.LookupEntry(i_nodeId);
+ if (!node)
+ {
+ PSendSysMessage(LANG_COMMAND_GOTAXINODENOTFOUND,i_nodeId);
+ SetSentErrorMessage(true);
+ return false;
+ }
+
+ if (node->x == 0.0f && node->y == 0.0f && node->z == 0.0f ||
+ !MapManager::IsValidMapCoord(node->map_id,node->x,node->y,node->z))
+ {
+ PSendSysMessage(LANG_INVALID_TARGET_COORD,node->x,node->y,node->map_id);
+ SetSentErrorMessage(true);
+ return false;
+ }
+
+ // stop flight if need
+ if (_player->isInFlight())
+ {
+ _player->GetMotionMaster()->MovementExpired();
+ _player->m_taxi.ClearTaxiDestinations();
+ }
+ // save only in non-flight case
+ else
+ _player->SaveRecallPosition();
+
+ _player->TeleportTo(node->map_id, node->x, node->y, node->z, _player->GetOrientation());
+ return true;
+}
+
//teleport at coordinates
bool ChatHandler::HandleGoXYCommand(const char* args)
{
diff --git a/src/game/Level2.cpp b/src/game/Level2.cpp
index bc83aa7a352..782b0f9c44e 100644
--- a/src/game/Level2.cpp
+++ b/src/game/Level2.cpp
@@ -1288,7 +1288,7 @@ bool ChatHandler::HandleNpcAddMoveCommand(const char* args)
// update movement type
WorldDatabase.PExecuteLog("UPDATE creature SET MovementType = '%u' WHERE guid = '%u'", WAYPOINT_MOTION_TYPE,lowguid);
- if(pCreature && pCreature->GetWaypointPath())
+ if(pCreature && pCreature->GetWaypointPathId())
{
pCreature->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
pCreature->GetMotionMaster()->Initialize();
@@ -1609,7 +1609,7 @@ bool ChatHandler::HandleNpcSetMoveTypeCommand(const char* args)
{
// update movement type
if(doNotDelete == false)
- pCreature->LoadPath(0);
+ pCreature->SetWaypointPathId(0);
pCreature->SetDefaultMovementType(move_type);
pCreature->GetMotionMaster()->Initialize();
@@ -2639,7 +2639,7 @@ bool ChatHandler::HandleWpAddCommand(const char* args)
if (!path_number)
{
if(target)
- pathid = target->GetWaypointPath();
+ pathid = target->GetWaypointPathId();
else
{
QueryResult *result = WorldDatabase.PQuery( "SELECT MAX(id) FROM waypoint_data");
@@ -2694,7 +2694,6 @@ bool ChatHandler::HandleWpLoadPathCommand(const char *args)
if(*args)
path_number = strtok((char*)args, " ");
-
uint32 pathid = 0;
uint32 guidlow = 0;
Creature* target = getSelectedCreature();
@@ -2725,6 +2724,7 @@ bool ChatHandler::HandleWpLoadPathCommand(const char *args)
return true;
}
+ /*
guidlow = target->GetDBTableGUIDLow();
QueryResult *result = WorldDatabase.PQuery( "SELECT guid FROM creature_addon WHERE guid = '%u'",guidlow);
@@ -2735,10 +2735,11 @@ bool ChatHandler::HandleWpLoadPathCommand(const char *args)
}
else
WorldDatabase.PExecute("INSERT INTO creature_addon(guid,path_id) VALUES ('%u','%u')", guidlow, pathid);
+ */
WorldDatabase.PExecute("UPDATE creature SET MovementType = '%u' WHERE guid = '%u'", WAYPOINT_MOTION_TYPE, guidlow);
- target->LoadPath(pathid);
+ target->SetWaypointPathId(pathid);
target->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
target->GetMotionMaster()->Initialize();
target->MonsterSay("Path loaded.",0,0);
@@ -2746,20 +2747,19 @@ bool ChatHandler::HandleWpLoadPathCommand(const char *args)
return true;
}
-
bool ChatHandler::HandleReloadAllPaths(const char* args)
{
-if(!*args)
- return false;
+ if(!*args)
+ return false;
-uint32 id = atoi(args);
+ uint32 id = atoi(args);
-if(!id)
- return false;
+ if(!id)
+ return false;
PSendSysMessage("%s%s|r|cff00ffff%u|r", "|cff00ff00", "Loading Path: ", id);
WaypointMgr.UpdatePath(id);
- return true;
+ return true;
}
bool ChatHandler::HandleWpUnLoadPathCommand(const char *args)
@@ -2773,24 +2773,39 @@ bool ChatHandler::HandleWpUnLoadPathCommand(const char *args)
return true;
}
- if(target->GetCreatureAddon())
+ if(target->GetWaypointPathId())
{
- if(target->GetCreatureAddon()->path_id != 0)
+ uint32 pathId = target->GetDBTableGUIDLow() * 10;
+ if(target->GetWaypointPathId() == pathId)
{
- WorldDatabase.PExecute("DELETE FROM creature_addon WHERE guid = %u", target->GetGUIDLow());
- target->UpdateWaypointID(0);
- WorldDatabase.PExecute("UPDATE creature SET MovementType = '%u' WHERE guid = '%u'", IDLE_MOTION_TYPE, guidlow);
- target->LoadPath(0);
- target->SetDefaultMovementType(IDLE_MOTION_TYPE);
- target->GetMotionMaster()->MoveTargetedHome();
- target->GetMotionMaster()->Initialize();
- target->MonsterSay("Path unloaded.",0,0);
- return true;
+ for(uint32 i = 1; i < 11; ++i)
+ {
+ if(i == 10)
+ {
+ PSendSysMessage("%s%s|r", "|cffff33ff", "Target cannot have more than 9 script paths. Unloading failed.");
+ break;
+ }
+
+ if(WaypointMgr.GetPath(++pathId))
+ continue;
+
+ WorldDatabase.PExecute("UPDATE waypoint_data SET id = %u WHERE id = %u", pathId, target->GetDBTableGUIDLow() * 10);
+ WorldDatabase.PExecute("UPDATE creature SET MovementType = '%u' WHERE guid = '%u'", IDLE_MOTION_TYPE, guidlow);
+ target->SetWaypointPathId(0);
+ target->UpdateWaypointID(0);
+ target->SetDefaultMovementType(IDLE_MOTION_TYPE);
+ target->GetMotionMaster()->Initialize();
+ target->GetMotionMaster()->MoveTargetedHome();
+ PSendSysMessage("Path unloaded.");
+ break;
+ }
}
- PSendSysMessage("%s%s|r", "|cffff33ff", "Target have no loaded path.");
- return true;
+ else
+ PSendSysMessage("%s%s|r", "|cffff33ff", "Target has path but that path is not its default path. Unloading failed.");
}
- PSendSysMessage("%s%s|r", "|cffff33ff", "Target have no loaded path.");
+ else
+ PSendSysMessage("%s%s|r", "|cffff33ff", "Target has no loaded path.");
+
return true;
}
@@ -3264,7 +3279,7 @@ bool ChatHandler::HandleWpShowCommand(const char* args)
return false;
}
- pathid = target->GetWaypointPath();
+ pathid = target->GetWaypointPathId();
}
else
@@ -4629,7 +4644,7 @@ bool ChatHandler::HandleNpcAddFormationCommand(const char* args)
group_member->groupAI = 0;
CreatureGroupMap[lowguid] = group_member;
- pCreature->SearchFormation();
+ pCreature->SearchFormationAndPath();
WorldDatabase.PExecuteLog("INSERT INTO `creature_formations` (`leaderGUID`, `memberGUID`, `dist`, `angle`, `groupAI`) VALUES ('%u','%u','%f', '%f', '%u')",
leaderGUID, lowguid, group_member->follow_dist, group_member->follow_angle, group_member->groupAI);
diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp
index 474a79c5680..9d43c348831 100644
--- a/src/game/Level3.cpp
+++ b/src/game/Level3.cpp
@@ -1612,11 +1612,7 @@ bool ChatHandler::HandleCooldownCommand(const char* args)
return false;
}
- WorldPacket data( SMSG_CLEAR_COOLDOWN, (4+8) );
- data << uint32(spell_id);
- data << uint64(target->GetGUID());
- target->GetSession()->SendPacket(&data);
- target->RemoveSpellCooldown(spell_id);
+ target->RemoveSpellCooldown(spell_id,true);
PSendSysMessage(LANG_REMOVE_COOLDOWN, spell_id, target==m_session->GetPlayer() ? GetMangosString(LANG_YOU) : tNameLink.c_str());
}
return true;
@@ -3694,6 +3690,68 @@ bool ChatHandler::HandleLookupObjectCommand(const char* args)
return true;
}
+bool ChatHandler::HandleLookupTaxiNodeCommand(const char * args)
+{
+ if(!*args)
+ return false;
+
+ std::string namepart = args;
+ std::wstring wnamepart;
+
+ if(!Utf8toWStr(namepart,wnamepart))
+ return false;
+
+ // converting string that we try to find to lower case
+ wstrToLower( wnamepart );
+
+ uint32 counter = 0; // Counter for figure out that we found smth.
+
+ // Search in TaxiNodes.dbc
+ for (uint32 id = 0; id < sTaxiNodesStore.GetNumRows(); id++)
+ {
+ TaxiNodesEntry const *nodeEntry = sTaxiNodesStore.LookupEntry(id);
+ if(nodeEntry)
+ {
+ int loc = m_session ? m_session->GetSessionDbcLocale() : sWorld.GetDefaultDbcLocale();
+ std::string name = nodeEntry->name[loc];
+ if(name.empty())
+ continue;
+
+ if (!Utf8FitTo(name, wnamepart))
+ {
+ loc = 0;
+ for(; loc < MAX_LOCALE; ++loc)
+ {
+ if(m_session && loc==m_session->GetSessionDbcLocale())
+ continue;
+
+ name = nodeEntry->name[loc];
+ if(name.empty())
+ continue;
+
+ if (Utf8FitTo(name, wnamepart))
+ break;
+ }
+ }
+
+ if(loc < MAX_LOCALE)
+ {
+ // send taxinode in "id - [name] (Map:m X:x Y:y Z:z)" format
+ if (m_session)
+ PSendSysMessage (LANG_TAXINODE_ENTRY_LIST_CHAT, id, id, name.c_str(),localeNames[loc],
+ nodeEntry->map_id,nodeEntry->x,nodeEntry->y,nodeEntry->z);
+ else
+ PSendSysMessage (LANG_TAXINODE_ENTRY_LIST_CONSOLE, id, name.c_str(), localeNames[loc],
+ nodeEntry->map_id,nodeEntry->x,nodeEntry->y,nodeEntry->z);
+ ++counter;
+ }
+ }
+ }
+ if (counter == 0) // if counter == 0 then we found nth
+ SendSysMessage(LANG_COMMAND_NOSPELLFOUND);
+ return true;
+}
+
/** \brief GM command level 3 - Create a guild.
*
* This command allows a GM (level 3) to create a guild.
@@ -3966,31 +4024,34 @@ bool ChatHandler::HandleDamageCommand(const char * args)
Unit* target = getSelectedUnit();
- if(!target || !m_session->GetPlayer()->GetSelection())
+ if (!target || !m_session->GetPlayer()->GetSelection())
{
SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE);
SetSentErrorMessage(true);
return false;
}
- if( !target->isAlive() )
+ if (!target->isAlive())
return true;
char* damageStr = strtok((char*)args, " ");
- if(!damageStr)
+ if (!damageStr)
return false;
- int32 damage = atoi((char*)damageStr);
- if(damage <=0)
+ int32 damage_int = atoi((char*)damageStr);
+ if(damage_int <=0)
return true;
+ uint32 damage = damage_int;
+
char* schoolStr = strtok((char*)NULL, " ");
// flat melee damage without resistence/etc reduction
- if(!schoolStr)
+ if (!schoolStr)
{
m_session->GetPlayer()->DealDamage(target, damage, NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
- m_session->GetPlayer()->SendAttackStateUpdate (HITINFO_NORMALSWING2, target, 1, SPELL_SCHOOL_MASK_NORMAL, damage, 0, 0, VICTIMSTATE_NORMAL, 0);
+ if (target != m_session->GetPlayer())
+ m_session->GetPlayer()->SendAttackStateUpdate (HITINFO_NORMALSWING2, target, 1, SPELL_SCHOOL_MASK_NORMAL, damage, 0, 0, VICTIMSTATE_NORMAL, 0);
return true;
}
@@ -4006,7 +4067,7 @@ bool ChatHandler::HandleDamageCommand(const char * args)
char* spellStr = strtok((char*)NULL, " ");
// melee damage by specific school
- if(!spellStr)
+ if (!spellStr)
{
uint32 absorb = 0;
uint32 resist = 0;
@@ -4018,6 +4079,7 @@ bool ChatHandler::HandleDamageCommand(const char * args)
damage -= absorb + resist;
+ m_session->GetPlayer()->DealDamageMods(target,damage,&absorb);
m_session->GetPlayer()->DealDamage(target, damage, NULL, DIRECT_DAMAGE, schoolmask, NULL, false);
m_session->GetPlayer()->SendAttackStateUpdate (HITINFO_NORMALSWING2, target, 1, schoolmask, damage, absorb, resist, VICTIMSTATE_NORMAL, 0);
return true;
@@ -4027,7 +4089,7 @@ bool ChatHandler::HandleDamageCommand(const char * args)
// number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form
uint32 spellid = extractSpellIdFromLink((char*)args);
- if(!spellid || !sSpellStore.LookupEntry(spellid))
+ if (!spellid || !sSpellStore.LookupEntry(spellid))
return false;
m_session->GetPlayer()->SpellNonMeleeDamageLog(target, spellid, damage);
diff --git a/src/game/LootHandler.cpp b/src/game/LootHandler.cpp
index f8e2a6cde15..172a6ef46c2 100644
--- a/src/game/LootHandler.cpp
+++ b/src/game/LootHandler.cpp
@@ -224,7 +224,7 @@ void WorldSession::HandleLootMoneyOpcode( WorldPacket & /*recv_data*/ )
Player* playerGroup = itr->getSource();
if(!playerGroup)
continue;
- if (player->GetDistance2d(playerGroup) < sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE))
+ if (player->IsWithinDist(playerGroup,sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE),false))
playersNear.push_back(playerGroup);
}
diff --git a/src/game/Map.cpp b/src/game/Map.cpp
index 3884f39f5a4..140904bfb19 100644
--- a/src/game/Map.cpp
+++ b/src/game/Map.cpp
@@ -120,7 +120,7 @@ void Map::LoadVMap(int gx,int gy)
}
}
-void Map::LoadMap(int gx,int gy)
+void Map::LoadMap(int gx,int gy, bool reload)
{
if( i_InstanceId != 0 )
{
@@ -138,6 +138,9 @@ void Map::LoadMap(int gx,int gy)
return;
}
+ if(GridMaps[gx][gy] && !reload)
+ return;
+
//map already load, delete it before reloading (Is it necessary? Do we really need the ability the reload maps during runtime?)
if(GridMaps[gx][gy])
{
@@ -2503,7 +2506,7 @@ void InstanceMap::CreateInstanceData(bool load)
{
Field* fields = result->Fetch();
const char* data = fields[0].GetString();
- if(data)
+ if(data && data != "")
{
sLog.outDebug("Loading instance data for `%s` with id %u", objmgr.GetScriptName(i_script_id), i_InstanceId);
i_data->Load(data);
diff --git a/src/game/Map.h b/src/game/Map.h
index d85eb459171..c69fe5f7345 100644
--- a/src/game/Map.h
+++ b/src/game/Map.h
@@ -23,9 +23,9 @@
#include "Platform/Define.h"
#include "Policies/ThreadingModel.h"
-#include "zthread/Lockable.h"
-#include "zthread/Mutex.h"
-#include "zthread/FairReadWriteLock.h"
+#include "ace/RW_Thread_Mutex.h"
+#include "ace/Thread_Mutex.h"
+
#include "DBCStructure.h"
#include "GridDefines.h"
#include "Cell.h"
@@ -46,13 +46,8 @@ class WorldObject;
class TempSummon;
class CreatureGroup;
-namespace ZThread
-{
- class Lockable;
- class ReadWriteLock;
-}
-typedef ZThread::FairReadWriteLock GridRWLock;
+typedef ACE_RW_Thread_Mutex GridRWLock;
template<class MUTEX, class LOCK_TYPE>
struct RGuard
@@ -68,9 +63,9 @@ struct WGuard
Trinity::GeneralLock<LOCK_TYPE> i_lock;
};
-typedef RGuard<GridRWLock, ZThread::Lockable> GridReadGuard;
-typedef WGuard<GridRWLock, ZThread::Lockable> GridWriteGuard;
-typedef Trinity::SingleThreaded<GridRWLock>::Lock NullGuard;
+typedef RGuard<GridRWLock, ACE_Thread_Mutex> GridReadGuard;
+typedef WGuard<GridRWLock, ACE_Thread_Mutex> GridWriteGuard;
+typedef MaNGOS::SingleThreaded<GridRWLock>::Lock NullGuard;
//******************************************
// Map file format defines
@@ -251,7 +246,7 @@ typedef UNORDERED_MAP<Creature*, CreatureMover> CreatureMoveList;
typedef std::map<uint32/*leaderDBGUID*/, CreatureGroup*> CreatureGroupHolderType;
-class TRINITY_DLL_SPEC Map : public GridRefManager<NGridType>, public Trinity::ObjectLevelLockable<Map, ZThread::Mutex>
+class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::ObjectLevelLockable<Map, ACE_Thread_Mutex>
{
friend class MapReference;
public:
@@ -426,7 +421,7 @@ class TRINITY_DLL_SPEC Map : public GridRefManager<NGridType>, public Trinity::O
private:
void LoadMapAndVMap(int gx, int gy);
void LoadVMap(int gx, int gy);
- void LoadMap(int gx,int gy);
+ void LoadMap(int gx,int gy, bool reload = false);
GridMap *GetGrid(float x, float y);
void SetTimer(uint32 t) { i_gridExpiry = t < MIN_GRID_DELAY ? MIN_GRID_DELAY : t; }
@@ -466,7 +461,7 @@ class TRINITY_DLL_SPEC Map : public GridRefManager<NGridType>, public Trinity::O
protected:
void SetUnloadReferenceLock(const GridPair &p, bool on) { getNGrid(p.x_coord, p.y_coord)->setUnloadReferenceLock(on); }
- typedef Trinity::ObjectLevelLockable<Map, ZThread::Mutex>::Lock Guard;
+ typedef MaNGOS::ObjectLevelLockable<Map, ACE_Thread_Mutex>::Lock Guard;
MapEntry const* i_mapEntry;
uint8 i_spawnMode;
diff --git a/src/game/MapManager.cpp b/src/game/MapManager.cpp
index 061e0252a13..d75ba22b19a 100644
--- a/src/game/MapManager.cpp
+++ b/src/game/MapManager.cpp
@@ -34,9 +34,9 @@
#include "ObjectMgr.h"
#include "Language.h"
-#define CLASS_LOCK Trinity::ClassLevelLockable<MapManager, ZThread::Mutex>
+#define CLASS_LOCK MaNGOS::ClassLevelLockable<MapManager, ACE_Thread_Mutex>
INSTANTIATE_SINGLETON_2(MapManager, CLASS_LOCK);
-INSTANTIATE_CLASS_MUTEX(MapManager, ZThread::Mutex);
+INSTANTIATE_CLASS_MUTEX(MapManager, ACE_Thread_Mutex);
extern GridState* si_GridStates[]; // debugging code, should be deleted some day
diff --git a/src/game/MapManager.h b/src/game/MapManager.h
index 143248de162..b54c1cfbfa1 100644
--- a/src/game/MapManager.h
+++ b/src/game/MapManager.h
@@ -23,14 +23,14 @@
#include "Platform/Define.h"
#include "Policies/Singleton.h"
-#include "zthread/Mutex.h"
+#include "ace/Thread_Mutex.h"
#include "Common.h"
#include "Map.h"
#include "GridStates.h"
class Transport;
-class TRINITY_DLL_DECL MapManager : public Trinity::Singleton<MapManager, Trinity::ClassLevelLockable<MapManager, ZThread::Mutex> >
+class MANGOS_DLL_DECL MapManager : public MaNGOS::Singleton<MapManager, MaNGOS::ClassLevelLockable<MapManager, ACE_Thread_Mutex> >
{
friend class Trinity::OperatorNew<MapManager>;
@@ -149,7 +149,7 @@ class TRINITY_DLL_DECL MapManager : public Trinity::Singleton<MapManager, Trinit
return (iter == i_maps.end() ? NULL : iter->second);
}
- typedef Trinity::ClassLevelLockable<MapManager, ZThread::Mutex>::Lock Guard;
+ typedef MaNGOS::ClassLevelLockable<MapManager, ACE_Thread_Mutex>::Lock Guard;
uint32 i_gridCleanUpDelay;
MapMapType i_maps;
IntervalTimer i_timer;
diff --git a/src/game/MiscHandler.cpp b/src/game/MiscHandler.cpp
index a75141e2937..f7c53e536c4 100644
--- a/src/game/MiscHandler.cpp
+++ b/src/game/MiscHandler.cpp
@@ -44,6 +44,7 @@
#include "Pet.h"
#include "SocialMgr.h"
#include "CellImpl.h"
+#include "AccountMgr.h"
#include "Vehicle.h"
#include "CreatureAI.h"
@@ -561,12 +562,13 @@ void WorldSession::HandleAddFriendOpcode( WorldPacket & recv_data )
sLog.outDebug( "WORLD: %s asked to add friend : '%s'",
GetPlayer()->GetName(), friendName.c_str() );
- CharacterDatabase.AsyncPQuery(&WorldSession::HandleAddFriendOpcodeCallBack, GetAccountId(), friendNote, "SELECT guid, race FROM characters WHERE name = '%s'", friendName.c_str());
+ CharacterDatabase.AsyncPQuery(&WorldSession::HandleAddFriendOpcodeCallBack, GetAccountId(), friendNote, "SELECT guid, race, account FROM characters WHERE name = '%s'", friendName.c_str());
}
void WorldSession::HandleAddFriendOpcodeCallBack(QueryResult *result, uint32 accountId, std::string friendNote)
{
uint64 friendGuid;
+ uint64 friendAcctid;
uint32 team;
FriendsResult friendResult;
@@ -582,30 +584,33 @@ void WorldSession::HandleAddFriendOpcodeCallBack(QueryResult *result, uint32 acc
{
friendGuid = MAKE_NEW_GUID((*result)[0].GetUInt32(), 0, HIGHGUID_PLAYER);
team = Player::TeamForRace((*result)[1].GetUInt8());
+ friendAcctid = (*result)[2].GetUInt32();
delete result;
- if(friendGuid)
+ if ( session->GetSecurity() >= SEC_MODERATOR || sWorld.getConfig(CONFIG_ALLOW_GM_FRIEND) || accmgr.GetSecurity(friendAcctid) < SEC_MODERATOR)
{
- if(friendGuid==session->GetPlayer()->GetGUID())
- friendResult = FRIEND_SELF;
- else if(session->GetPlayer()->GetTeam() != team && !sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_ADD_FRIEND) && session->GetSecurity() < SEC_MODERATOR)
- friendResult = FRIEND_ENEMY;
- else if(session->GetPlayer()->GetSocial()->HasFriend(GUID_LOPART(friendGuid)))
- friendResult = FRIEND_ALREADY;
- else
+ if(friendGuid)
{
- Player* pFriend = ObjectAccessor::FindPlayer(friendGuid);
- if( pFriend && pFriend->IsInWorld() && pFriend->IsVisibleGloballyFor(session->GetPlayer()))
- friendResult = FRIEND_ADDED_ONLINE;
+ if(friendGuid==session->GetPlayer()->GetGUID())
+ friendResult = FRIEND_SELF;
+ else if(session->GetPlayer()->GetTeam() != team && !sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_ADD_FRIEND) && session->GetSecurity() < SEC_MODERATOR)
+ friendResult = FRIEND_ENEMY;
+ else if(session->GetPlayer()->GetSocial()->HasFriend(GUID_LOPART(friendGuid)))
+ friendResult = FRIEND_ALREADY;
else
- friendResult = FRIEND_ADDED_OFFLINE;
- if(!session->GetPlayer()->GetSocial()->AddToSocialList(GUID_LOPART(friendGuid), false))
{
- friendResult = FRIEND_LIST_FULL;
- sLog.outDebug( "WORLD: %s's friend list is full.", session->GetPlayer()->GetName());
+ Player* pFriend = ObjectAccessor::FindPlayer(friendGuid);
+ if( pFriend && pFriend->IsInWorld() && pFriend->IsVisibleGloballyFor(session->GetPlayer()))
+ friendResult = FRIEND_ADDED_ONLINE;
+ else
+ friendResult = FRIEND_ADDED_OFFLINE;
+ if(!session->GetPlayer()->GetSocial()->AddToSocialList(GUID_LOPART(friendGuid), false))
+ {
+ friendResult = FRIEND_LIST_FULL;
+ sLog.outDebug( "WORLD: %s's friend list is full.", session->GetPlayer()->GetName());
+ }
}
-
session->GetPlayer()->GetSocial()->SetFriendNote(GUID_LOPART(friendGuid), friendNote);
}
}
@@ -775,9 +780,7 @@ void WorldSession::HandleCorpseReclaimOpcode(WorldPacket &recv_data)
if(corpse->GetGhostTime() + GetPlayer()->GetCorpseReclaimDelay(corpse->GetType()==CORPSE_RESURRECTABLE_PVP) > time(NULL))
return;
- float dist = corpse->GetDistance2d(GetPlayer());
- sLog.outDebug("Corpse 2D Distance: \t%f",dist);
- if (dist > CORPSE_RECLAIM_RADIUS)
+ if (!corpse->IsWithinDist(GetPlayer(),CORPSE_RECLAIM_RADIUS,false))
return;
uint64 guid;
diff --git a/src/game/MotionMaster.cpp b/src/game/MotionMaster.cpp
index b31d3231a3b..52b9ba56e3e 100644
--- a/src/game/MotionMaster.cpp
+++ b/src/game/MotionMaster.cpp
@@ -203,14 +203,7 @@ MotionMaster::MoveTargetedHome()
Clear(false);
- if(Unit *target = i_owner->GetCharmerOrOwner())
- {
- DEBUG_LOG("Pet or controlled unit (Entry: %u GUID: %u) targeting home",
- i_owner->GetEntry(), i_owner->GetGUIDLow() );
-
- MoveFollow(target, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE, MOTION_SLOT_IDLE);
- }
- else if(i_owner->GetTypeId() == TYPEID_UNIT)
+ if(i_owner->GetTypeId() == TYPEID_UNIT)
{
DEBUG_LOG("Creature (Entry: %u GUID: %u) targeted home", i_owner->GetEntry(), i_owner->GetGUIDLow());
Mutate(new HomeMovementGenerator<Creature>(), MOTION_SLOT_ACTIVE);
@@ -218,7 +211,6 @@ MotionMaster::MoveTargetedHome()
else
{
sLog.outError("Player (GUID: %u) attempt targeted home", i_owner->GetGUIDLow() );
- return;
}
}
diff --git a/src/game/NullCreatureAI.h b/src/game/NullCreatureAI.h
index d5c12d8c9a0..347f52228b4 100644
--- a/src/game/NullCreatureAI.h
+++ b/src/game/NullCreatureAI.h
@@ -22,40 +22,47 @@
#define TRINITY_NULLCREATUREAI_H
#include "CreatureAI.h"
+#include "CreatureAIImpl.h"
class TRINITY_DLL_DECL PassiveAI : public CreatureAI
{
public:
explicit PassiveAI(Creature *c) : CreatureAI(c) {}
- ~PassiveAI() {}
void MoveInLineOfSight(Unit *) {}
void AttackStart(Unit *) {}
-
void UpdateAI(const uint32);
+
static int Permissible(const Creature *) { return PERMIT_BASE_IDLE; }
};
-class TRINITY_DLL_DECL PossessedAI : public PassiveAI
+class TRINITY_DLL_DECL PossessedAI : public CreatureAI
{
public:
- explicit PossessedAI(Creature *c) : PassiveAI(c) {}
+ explicit PossessedAI(Creature *c) : CreatureAI(c) {}
+ void MoveInLineOfSight(Unit *) {}
void AttackStart(Unit *target);
void UpdateAI(const uint32);
void EnterEvadeMode() {}
void JustDied(Unit*);
void KilledUnit(Unit* victim);
+
+ static int Permissible(const Creature *) { return PERMIT_BASE_IDLE; }
};
-class TRINITY_DLL_DECL NullCreatureAI : public PassiveAI
+class TRINITY_DLL_DECL NullCreatureAI : public CreatureAI
{
public:
- explicit NullCreatureAI(Creature *c) : PassiveAI(c) {}
+ explicit NullCreatureAI(Creature *c) : CreatureAI(c) {}
+ void MoveInLineOfSight(Unit *) {}
+ void AttackStart(Unit *) {}
void UpdateAI(const uint32) {}
void EnterEvadeMode() {}
+
+ static int Permissible(const Creature *) { return PERMIT_BASE_IDLE; }
};
class TRINITY_DLL_DECL CritterAI : public PassiveAI
diff --git a/src/game/Object.cpp b/src/game/Object.cpp
index f649164e21b..5c186921524 100644
--- a/src/game/Object.cpp
+++ b/src/game/Object.cpp
@@ -1148,7 +1148,6 @@ InstanceData* WorldObject::GetInstanceData()
Map *map = GetMap();
return map->IsDungeon() ? ((InstanceMap*)map)->GetInstanceData() : NULL;
}
-
//slow
float WorldObject::GetDistance(const WorldObject* obj) const
{
@@ -1176,7 +1175,7 @@ float WorldObject::GetExactDistance2d(const float x, const float y) const
return sqrt((dx*dx) + (dy*dy));
}
-float WorldObject::GetDistance(const float x, const float y, const float z) const
+float WorldObject::GetDistance(float x, float y, float z) const
{
float dx = GetPositionX() - x;
float dy = GetPositionY() - y;
@@ -1194,6 +1193,14 @@ float WorldObject::GetDistanceSq(const float &x, const float &y, const float &z)
return dx*dx + dy*dy + dz*dz;
}
+float WorldObject::GetDistanceSq(const WorldObject *obj) const
+{
+ float dx = GetPositionX() - obj->GetPositionX();
+ float dy = GetPositionY() - obj->GetPositionY();
+ float dz = GetPositionZ() - obj->GetPositionZ();
+ return dx*dx + dy*dy + dz*dz;
+}
+
float WorldObject::GetDistance2d(const WorldObject* obj) const
{
float dx = GetPositionX() - obj->GetPositionX();
@@ -1211,10 +1218,33 @@ float WorldObject::GetDistanceZ(const WorldObject* obj) const
return ( dist > 0 ? dist : 0);
}
-bool WorldObject::IsWithinDistInMap(const WorldObject* obj, const float dist2compare, const bool is3D) const
+bool WorldObject::IsWithinDist3d(float x, float y, float z, float dist2compare) const
{
- if (!obj || !IsInMap(obj)) return false;
+ float dx = GetPositionX() - x;
+ float dy = GetPositionY() - y;
+ float dz = GetPositionZ() - z;
+ float distsq = dx*dx + dy*dy + dz*dz;
+
+ float sizefactor = GetObjectSize();
+ float maxdist = dist2compare + sizefactor;
+
+ return distsq < maxdist * maxdist;
+}
+
+bool WorldObject::IsWithinDist2d(float x, float y, float dist2compare) const
+{
+ float dx = GetPositionX() - x;
+ float dy = GetPositionY() - y;
+ float distsq = dx*dx + dy*dy;
+
+ float sizefactor = GetObjectSize();
+ float maxdist = dist2compare + sizefactor;
+ return distsq < maxdist * maxdist;
+}
+
+bool WorldObject::_IsWithinDist(WorldObject const* obj, float dist2compare, bool is3D) const
+{
float dx = GetPositionX() - obj->GetPositionX();
float dy = GetPositionY() - obj->GetPositionY();
float distsq = dx*dx + dy*dy;
@@ -1237,7 +1267,7 @@ bool WorldObject::IsWithinLOSInMap(const WorldObject* obj) const
return(IsWithinLOS(ox, oy, oz ));
}
-bool WorldObject::IsWithinLOS(const float ox, const float oy, const float oz ) const
+bool WorldObject::IsWithinLOS(float ox, float oy, float oz) const
{
float x,y,z;
GetPosition(x,y,z);
@@ -1245,6 +1275,83 @@ bool WorldObject::IsWithinLOS(const float ox, const float oy, const float oz ) c
return vMapManager->isInLineOfSight(GetMapId(), x, y, z+2.0f, ox, oy, oz+2.0f);
}
+bool WorldObject::GetDistanceOrder(WorldObject const* obj1, WorldObject const* obj2, bool is3D /* = true */) const
+{
+ float dx1 = GetPositionX() - obj1->GetPositionX();
+ float dy1 = GetPositionY() - obj1->GetPositionY();
+ float distsq1 = dx1*dx1 + dy1*dy1;
+ if(is3D)
+ {
+ float dz1 = GetPositionZ() - obj1->GetPositionZ();
+ distsq1 += dz1*dz1;
+ }
+
+ float dx2 = GetPositionX() - obj2->GetPositionX();
+ float dy2 = GetPositionY() - obj2->GetPositionY();
+ float distsq2 = dx2*dx2 + dy2*dy2;
+ if(is3D)
+ {
+ float dz2 = GetPositionZ() - obj2->GetPositionZ();
+ distsq2 += dz2*dz2;
+ }
+
+ return distsq1 < distsq2;
+}
+
+bool WorldObject::IsInRange(WorldObject const* obj, float minRange, float maxRange, bool is3D /* = true */) const
+{
+ float dx = GetPositionX() - obj->GetPositionX();
+ float dy = GetPositionY() - obj->GetPositionY();
+ float distsq = dx*dx + dy*dy;
+ if(is3D)
+ {
+ float dz = GetPositionZ() - obj->GetPositionZ();
+ distsq += dz*dz;
+ }
+
+ float sizefactor = GetObjectSize() + obj->GetObjectSize();
+
+ float mindist = minRange + sizefactor;
+ if(distsq < mindist * mindist)
+ return false;
+
+ float maxdist = maxRange + sizefactor;
+ return distsq < maxdist * maxdist;
+}
+
+bool WorldObject::IsInRange2d(float x, float y, float minRange, float maxRange) const
+{
+ float dx = GetPositionX() - x;
+ float dy = GetPositionY() - y;
+ float distsq = dx*dx + dy*dy;
+
+ float sizefactor = GetObjectSize();
+
+ float mindist = minRange + sizefactor;
+ if(distsq < mindist * mindist)
+ return false;
+
+ float maxdist = maxRange + sizefactor;
+ return distsq < maxdist * maxdist;
+}
+
+bool WorldObject::IsInRange3d(float x, float y, float z, float minRange, float maxRange) const
+{
+ float dx = GetPositionX() - x;
+ float dy = GetPositionY() - y;
+ float dz = GetPositionZ() - z;
+ float distsq = dx*dx + dy*dy + dz*dz;
+
+ float sizefactor = GetObjectSize();
+
+ float mindist = minRange + sizefactor;
+ if(distsq < mindist * mindist)
+ return false;
+
+ float maxdist = maxRange + sizefactor;
+ return distsq < maxdist * maxdist;
+}
+
float WorldObject::GetAngle(const WorldObject* obj) const
{
if(!obj) return 0;
@@ -1309,6 +1416,21 @@ bool WorldObject::HasInArc(const float arcangle, const WorldObject* obj) const
return (( angle >= lborder ) && ( angle <= rborder ));
}
+bool WorldObject::IsInBetween(const WorldObject *obj1, const WorldObject *obj2, float size) const
+{
+ if(GetPositionX() > std::max(obj1->GetPositionX(), obj2->GetPositionX())
+ || GetPositionX() < std::min(obj1->GetPositionX(), obj2->GetPositionX())
+ || GetPositionY() > std::max(obj1->GetPositionY(), obj2->GetPositionY())
+ || GetPositionY() < std::min(obj1->GetPositionY(), obj2->GetPositionY()))
+ return false;
+
+ if(!size)
+ size = GetObjectSize() / 2;
+
+ float angle = obj1->GetAngle(this) - obj1->GetAngle(obj2);
+ return abs(sin(angle)) * GetExactDistance2d(obj1->GetPositionX(), obj1->GetPositionY()) < size;
+}
+
void WorldObject::GetRandomPoint( float x, float y, float z, float distance, float &rand_x, float &rand_y, float &rand_z) const
{
if(distance==0)
@@ -1658,6 +1780,8 @@ TempSummon *Map::SummonCreature(uint32 entry, float x, float y, float z, float a
return NULL;
}
+ summon->SetHomePosition(x, y, z, angle);
+
summon->InitStats(duration);
Add((Creature*)summon);
summon->InitSummon();
@@ -1680,7 +1804,6 @@ TempSummon* WorldObject::SummonCreature(uint32 entry, float x, float y, float z,
if(!pCreature)
return NULL;
- pCreature->SetHomePosition(x, y, z, ang);
pCreature->SetTempSummonType(spwtype);
return pCreature;
@@ -1890,6 +2013,81 @@ Creature* WorldObject::SummonTrigger(float x, float y, float z, float ang, uint3
return summon;
}
+/*
+namespace MaNGOS
+{
+ class NearUsedPosDo
+ {
+ public:
+ NearUsedPosDo(WorldObject const& obj, WorldObject const* searcher, float angle, ObjectPosSelector& selector)
+ : i_object(obj), i_searcher(searcher), i_angle(angle), i_selector(selector) {}
+
+ void operator()(Corpse*) const {}
+ void operator()(DynamicObject*) const {}
+
+ void operator()(Creature* c) const
+ {
+ // skip self or target
+ if(c==i_searcher || c==&i_object)
+ return;
+
+ float x,y,z;
+
+ if( !c->isAlive() || c->hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DISTRACTED) ||
+ !c->GetMotionMaster()->GetDestination(x,y,z) )
+ {
+ x = c->GetPositionX();
+ y = c->GetPositionY();
+ }
+
+ add(c,x,y);
+ }
+
+ template<class T>
+ void operator()(T* u) const
+ {
+ // skip self or target
+ if(u==i_searcher || u==&i_object)
+ return;
+
+ float x,y;
+
+ x = u->GetPositionX();
+ y = u->GetPositionY();
+
+ add(u,x,y);
+ }
+
+ // we must add used pos that can fill places around center
+ void add(WorldObject* u, float x, float y) const
+ {
+ // u is too nearest/far away to i_object
+ if(!i_object.IsInRange2d(x,y,i_selector.m_dist - i_selector.m_size,i_selector.m_dist + i_selector.m_size))
+ return;
+
+ float angle = i_object.GetAngle(u)-i_angle;
+
+ // move angle to range -pi ... +pi
+ while( angle > M_PI)
+ angle -= 2.0f * M_PI;
+ while(angle < -M_PI)
+ angle += 2.0f * M_PI;
+
+ // dist include size of u
+ float dist2d = i_object.GetDistance2d(x,y);
+ i_selector.AddUsedPos(u->GetObjectSize(),angle,dist2d + i_object.GetObjectSize());
+ }
+ private:
+ WorldObject const& i_object;
+ WorldObject const* i_searcher;
+ float i_angle;
+ ObjectPosSelector& i_selector;
+ };
+} // namespace MaNGOS
+*/
+
+//===================================================================================================
+
void WorldObject::GetNearPoint2D(float &x, float &y, float distance2d, float absAngle ) const
{
x = GetPositionX() + (GetObjectSize() + distance2d) * cos(absAngle);
@@ -1902,10 +2100,127 @@ void WorldObject::GetNearPoint2D(float &x, float &y, float distance2d, float abs
void WorldObject::GetNearPoint(WorldObject const* searcher, float &x, float &y, float &z, float searcher_size, float distance2d, float absAngle ) const
{
GetNearPoint2D(x,y,distance2d+searcher_size,absAngle);
-
z = GetPositionZ();
-
UpdateGroundPositionZ(x,y,z);
+
+ /*
+ // if detection disabled, return first point
+ if(!sWorld.getConfig(CONFIG_DETECT_POS_COLLISION))
+ {
+ UpdateGroundPositionZ(x,y,z); // update to LOS height if available
+ return;
+ }
+
+ // or remember first point
+ float first_x = x;
+ float first_y = y;
+ bool first_los_conflict = false; // first point LOS problems
+
+ // prepare selector for work
+ ObjectPosSelector selector(GetPositionX(),GetPositionY(),GetObjectSize(),distance2d+searcher_size);
+
+ // adding used positions around object
+ {
+ CellPair p(MaNGOS::ComputeCellPair(GetPositionX(), GetPositionY()));
+ Cell cell(p);
+ cell.data.Part.reserved = ALL_DISTRICT;
+ cell.SetNoCreate();
+
+ MaNGOS::NearUsedPosDo u_do(*this,searcher,absAngle,selector);
+ MaNGOS::WorldObjectWorker<MaNGOS::NearUsedPosDo> worker(this,u_do);
+
+ TypeContainerVisitor<MaNGOS::WorldObjectWorker<MaNGOS::NearUsedPosDo>, GridTypeMapContainer > grid_obj_worker(worker);
+ TypeContainerVisitor<MaNGOS::WorldObjectWorker<MaNGOS::NearUsedPosDo>, WorldTypeMapContainer > world_obj_worker(worker);
+
+ CellLock<GridReadGuard> cell_lock(cell, p);
+ cell_lock->Visit(cell_lock, grid_obj_worker, *GetMap());
+ cell_lock->Visit(cell_lock, world_obj_worker, *GetMap());
+ }
+
+ // maybe can just place in primary position
+ if( selector.CheckOriginal() )
+ {
+ UpdateGroundPositionZ(x,y,z); // update to LOS height if available
+
+ if(IsWithinLOS(x,y,z))
+ return;
+
+ first_los_conflict = true; // first point have LOS problems
+ }
+
+ float angle; // candidate of angle for free pos
+
+ // special case when one from list empty and then empty side preferred
+ if(selector.FirstAngle(angle))
+ {
+ GetNearPoint2D(x,y,distance2d,absAngle+angle);
+ z = GetPositionZ();
+ UpdateGroundPositionZ(x,y,z); // update to LOS height if available
+
+ if(IsWithinLOS(x,y,z))
+ return;
+ }
+
+ // set first used pos in lists
+ selector.InitializeAngle();
+
+ // select in positions after current nodes (selection one by one)
+ while(selector.NextAngle(angle)) // angle for free pos
+ {
+ GetNearPoint2D(x,y,distance2d,absAngle+angle);
+ z = GetPositionZ();
+ UpdateGroundPositionZ(x,y,z); // update to LOS height if available
+
+ if(IsWithinLOS(x,y,z))
+ return;
+ }
+
+ // BAD NEWS: not free pos (or used or have LOS problems)
+ // Attempt find _used_ pos without LOS problem
+
+ if(!first_los_conflict)
+ {
+ x = first_x;
+ y = first_y;
+
+ UpdateGroundPositionZ(x,y,z); // update to LOS height if available
+ return;
+ }
+
+ // special case when one from list empty and then empty side preferred
+ if( selector.IsNonBalanced() )
+ {
+ if(!selector.FirstAngle(angle)) // _used_ pos
+ {
+ GetNearPoint2D(x,y,distance2d,absAngle+angle);
+ z = GetPositionZ();
+ UpdateGroundPositionZ(x,y,z); // update to LOS height if available
+
+ if(IsWithinLOS(x,y,z))
+ return;
+ }
+ }
+
+ // set first used pos in lists
+ selector.InitializeAngle();
+
+ // select in positions after current nodes (selection one by one)
+ while(selector.NextUsedAngle(angle)) // angle for used pos but maybe without LOS problem
+ {
+ GetNearPoint2D(x,y,distance2d,absAngle+angle);
+ z = GetPositionZ();
+ UpdateGroundPositionZ(x,y,z); // update to LOS height if available
+
+ if(IsWithinLOS(x,y,z))
+ return;
+ }
+
+ // BAD BAD NEWS: all found pos (free and used) have LOS problem :(
+ x = first_x;
+ y = first_y;
+
+ UpdateGroundPositionZ(x,y,z); // update to LOS height if available
+ */
}
void WorldObject::GetGroundPoint(float &x, float &y, float &z, float dist, float angle)
diff --git a/src/game/Object.h b/src/game/Object.h
index 68438c4df85..326b09cfb73 100644
--- a/src/game/Object.h
+++ b/src/game/Object.h
@@ -461,10 +461,11 @@ class TRINITY_DLL_SPEC WorldObject : public Object
virtual const char* GetNameForLocaleIdx(int32 /*locale_idx*/) const { return GetName(); }
float GetDistance( const WorldObject* obj ) const;
- float GetDistance(const float x, const float y, const float z) const;
+ float GetDistance(float x, float y, float z) const;
float GetDistanceSq(const float &x, const float &y, const float &z) const;
+ float GetDistanceSq(const WorldObject *obj) const;
float GetDistance2d(const WorldObject* obj) const;
- float GetDistance2d(const float x, const float y) const;
+ float GetDistance2d(float x, float y) const;
float GetExactDistance2d(const float x, const float y) const;
float GetDistanceZ(const WorldObject* obj) const;
bool IsInMap(const WorldObject* obj) const
@@ -472,14 +473,30 @@ class TRINITY_DLL_SPEC WorldObject : public Object
return IsInWorld() && obj->IsInWorld() && GetMapId()==obj->GetMapId() &&
GetInstanceId()==obj->GetInstanceId() && InSamePhase(obj);
}
- bool IsWithinDistInMap(const WorldObject* obj, const float dist2compare, const bool is3D = true) const;
- bool IsWithinLOS(const float x, const float y, const float z ) const;
+ bool IsWithinDist3d(float x, float y, float z, float dist2compare) const;
+ bool IsWithinDist2d(float x, float y, float dist2compare) const;
+ bool _IsWithinDist(WorldObject const* obj, float dist2compare, bool is3D) const;
+ bool IsWithinDist(WorldObject const* obj, float dist2compare, bool is3D = true) const
+ // use only if you will sure about placing both object at same map
+ {
+ return obj && _IsWithinDist(obj,dist2compare,is3D);
+ }
+ bool IsWithinDistInMap(WorldObject const* obj, float dist2compare, bool is3D = true) const
+ {
+ return obj && IsInMap(obj) && _IsWithinDist(obj,dist2compare,is3D);
+ }
+ bool IsWithinLOS(float x, float y, float z) const;
bool IsWithinLOSInMap(const WorldObject* obj) const;
+ bool GetDistanceOrder(WorldObject const* obj1, WorldObject const* obj2, bool is3D = true) const;
+ bool IsInRange(WorldObject const* obj, float minRange, float maxRange, bool is3D = true) const;
+ bool IsInRange2d(float x, float y, float minRange, float maxRange) const;
+ bool IsInRange3d(float x, float y, float z, float minRange, float maxRange) const;
float GetAngle( const WorldObject* obj ) const;
float GetAngle( const float x, const float y ) const;
void GetSinCos(const float x, const float y, float &vsin, float &vcos);
bool HasInArc( const float arcangle, const WorldObject* obj ) const;
+ bool IsInBetween(const WorldObject *obj1, const WorldObject *obj2, float size = 0) const;
virtual void SendMessageToSet(WorldPacket *data, bool self, bool to_possessor = true);
virtual void SendMessageToSetInRange(WorldPacket *data, float dist, bool self, bool to_possessor = true);
diff --git a/src/game/ObjectAccessor.cpp b/src/game/ObjectAccessor.cpp
index 1fa0bd6d1ca..da6279e068a 100644
--- a/src/game/ObjectAccessor.cpp
+++ b/src/game/ObjectAccessor.cpp
@@ -41,9 +41,9 @@
#include <cmath>
-#define CLASS_LOCK Trinity::ClassLevelLockable<ObjectAccessor, ZThread::FastMutex>
+#define CLASS_LOCK MaNGOS::ClassLevelLockable<ObjectAccessor, ACE_Thread_Mutex>
INSTANTIATE_SINGLETON_2(ObjectAccessor, CLASS_LOCK);
-INSTANTIATE_CLASS_MUTEX(ObjectAccessor, ZThread::FastMutex);
+INSTANTIATE_CLASS_MUTEX(ObjectAccessor, ACE_Thread_Mutex);
ObjectAccessor::ObjectAccessor() {}
ObjectAccessor::~ObjectAccessor() {}
@@ -470,7 +470,7 @@ ObjectAccessor::UpdateObjectVisibility(WorldObject *obj)
/// Define the static member of HashMapHolder
template <class T> UNORDERED_MAP< uint64, T* > HashMapHolder<T>::m_objectMap;
-template <class T> ZThread::FastMutex HashMapHolder<T>::i_lock;
+template <class T> ACE_Thread_Mutex HashMapHolder<T>::i_lock;
/// Global definitions for the hashmap storage
diff --git a/src/game/ObjectAccessor.h b/src/game/ObjectAccessor.h
index dd8e02b81ab..f4452b81cab 100644
--- a/src/game/ObjectAccessor.h
+++ b/src/game/ObjectAccessor.h
@@ -23,7 +23,7 @@
#include "Platform/Define.h"
#include "Policies/Singleton.h"
-#include "zthread/FastMutex.h"
+#include <ace/Thread_Mutex.h>
#include "Utilities/UnorderedMap.h"
#include "Policies/ThreadingModel.h"
@@ -51,8 +51,8 @@ class HashMapHolder
public:
typedef UNORDERED_MAP< uint64, T* > MapType;
- typedef ZThread::FastMutex LockType;
- typedef Trinity::GeneralLock<LockType > Guard;
+ typedef ACE_Thread_Mutex LockType;
+ typedef MaNGOS::GeneralLock<LockType > Guard;
static void Insert(T* o) { m_objectMap[o->GetGUID()] = o; }
@@ -80,7 +80,7 @@ class HashMapHolder
static MapType m_objectMap;
};
-class TRINITY_DLL_DECL ObjectAccessor : public Trinity::Singleton<ObjectAccessor, Trinity::ClassLevelLockable<ObjectAccessor, ZThread::FastMutex> >
+class MANGOS_DLL_DECL ObjectAccessor : public MaNGOS::Singleton<ObjectAccessor, MaNGOS::ClassLevelLockable<ObjectAccessor, ACE_Thread_Mutex> >
{
friend class Trinity::OperatorNew<ObjectAccessor>;
@@ -228,8 +228,8 @@ class TRINITY_DLL_DECL ObjectAccessor : public Trinity::Singleton<ObjectAccessor
friend struct WorldObjectChangeAccumulator;
Player2CorpsesMapType i_player2corpse;
- typedef ZThread::FastMutex LockType;
- typedef Trinity::GeneralLock<LockType > Guard;
+ typedef ACE_Thread_Mutex LockType;
+ typedef MaNGOS::GeneralLock<LockType > Guard;
static void _buildChangeObjectForPlayer(WorldObject *, UpdateDataMapType &);
static void _buildPacket(Player *, Object *, UpdateDataMapType &);
diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp
index 12fb26f0ad8..a448a73f1dc 100644
--- a/src/game/ObjectMgr.cpp
+++ b/src/game/ObjectMgr.cpp
@@ -4837,7 +4837,7 @@ void ObjectMgr::GetTaxiPath( uint32 source, uint32 destination, uint32 &path, ui
path = dest_i->second.ID;
}
-uint16 ObjectMgr::GetTaxiMount( uint32 id, uint32 team )
+uint16 ObjectMgr::GetTaxiMount( uint32 id, uint32 team, bool allowed_alt_team /* = false */)
{
uint16 mount_entry = 0;
uint16 mount_id = 0;
@@ -4848,6 +4848,9 @@ uint16 ObjectMgr::GetTaxiMount( uint32 id, uint32 team )
if (team == ALLIANCE)
{
mount_entry = node->MountCreatureID[1];
+ if(!mount_entry && allowed_alt_team)
+ mount_entry = node->MountCreatureID[0];
+
CreatureInfo const *ci = GetCreatureTemplate(mount_entry);
if(ci)
mount_id = ci->Modelid_A1;
@@ -4855,6 +4858,10 @@ uint16 ObjectMgr::GetTaxiMount( uint32 id, uint32 team )
if (team == HORDE)
{
mount_entry = node->MountCreatureID[0];
+
+ if(!mount_entry && allowed_alt_team)
+ mount_entry = node->MountCreatureID[1];
+
CreatureInfo const *ci = GetCreatureTemplate(mount_entry);
if(ci)
mount_id = ci->Modelid_H1;
diff --git a/src/game/ObjectMgr.h b/src/game/ObjectMgr.h
index eff1f3812a1..3fe373f6a34 100644
--- a/src/game/ObjectMgr.h
+++ b/src/game/ObjectMgr.h
@@ -418,7 +418,7 @@ class ObjectMgr
uint32 GetNearestTaxiNode( float x, float y, float z, uint32 mapid, uint32 team );
void GetTaxiPath( uint32 source, uint32 destination, uint32 &path, uint32 &cost);
- uint16 GetTaxiMount( uint32 id, uint32 team );
+ uint16 GetTaxiMount( uint32 id, uint32 team, bool allowed_alt_team = false);
void GetTaxiPathNodes( uint32 path, Path &pathnodes, std::vector<uint32>& mapIds );
void GetTransportPathNodes( uint32 path, TransportPath &pathnodes );
diff --git a/src/game/OutdoorPvPEP.cpp b/src/game/OutdoorPvPEP.cpp
index f0ff85574c0..fc688314e0c 100644
--- a/src/game/OutdoorPvPEP.cpp
+++ b/src/game/OutdoorPvPEP.cpp
@@ -768,7 +768,7 @@ bool OutdoorPvPObjectiveEP_PWT::HandleGossipOption(Player *plr, uint64 guid, uin
nodes[1] = dst;
plr->PlayerTalkClass->CloseGossip();
- plr->ActivateTaxiPathTo(nodes, 0, cr);
+ plr->ActivateTaxiPathTo(nodes, cr);
// leave the opvp, seems like moveinlineofsight isn't called when entering a taxi
HandlePlayerLeave(plr);
}
diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp
index e846f7004c0..7edc9144bdc 100644
--- a/src/game/Pet.cpp
+++ b/src/game/Pet.cpp
@@ -190,10 +190,7 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool
return true;
}
- if (getPetType() == HUNTER_PET || (getPetType() == SUMMON_PET && cinfo->type == CREATURE_TYPE_DEMON && owner->getClass() == CLASS_WARLOCK))
- m_charmInfo->SetPetNumber(pet_number, true);
- else
- m_charmInfo->SetPetNumber(pet_number, false);
+ m_charmInfo->SetPetNumber(pet_number, IsPermanentPetFor(owner));
// set current pet as current
// 0=current
@@ -1685,6 +1682,27 @@ void Pet::ToggleAutocast(uint32 spellid, bool apply)
}
}
+bool Pet::IsPermanentPetFor(Player* owner)
+{
+ switch(getPetType())
+ {
+ case SUMMON_PET:
+ switch(owner->getClass())
+ {
+ case CLASS_WARLOCK:
+ return GetCreatureInfo()->type == CREATURE_TYPE_DEMON;
+ case CLASS_DEATH_KNIGHT:
+ return GetCreatureInfo()->type == CREATURE_TYPE_UNDEAD;
+ default:
+ return false;
+ }
+ case HUNTER_PET:
+ return true;
+ default:
+ return false;
+ }
+}
+
bool Pet::Create(uint32 guidlow, Map *map, uint32 phaseMask, uint32 Entry, uint32 pet_number)
{
SetMapId(map->GetId());
@@ -1735,10 +1753,10 @@ void Pet::LearnPetPassives()
void Pet::CastPetAuras(bool current)
{
Unit* owner = GetOwner();
- if(!owner)
+ if(!owner || owner->GetTypeId()!=TYPEID_PLAYER)
return;
- if(getPetType() != HUNTER_PET && (getPetType() != SUMMON_PET || owner->getClass() != CLASS_WARLOCK))
+ if(!IsPermanentPetFor((Player*)owner))
return;
for(PetAuraSet::const_iterator itr = owner->m_petAuras.begin(); itr != owner->m_petAuras.end();)
diff --git a/src/game/Pet.h b/src/game/Pet.h
index 90414a321de..b76b53ab554 100644
--- a/src/game/Pet.h
+++ b/src/game/Pet.h
@@ -121,11 +121,13 @@ typedef std::vector<uint32> AutoSpellList;
#define ACTIVE_SPELLS_MAX 4
-#define OWNER_MAX_DISTANCE 100
+#define OWNER_MAX_DISTANCE 100.0f
#define PET_FOLLOW_DIST 1
#define PET_FOLLOW_ANGLE (M_PI/2)
+class Player;
+
class Pet : public Guardian
{
public:
@@ -140,6 +142,8 @@ class Pet : public Guardian
bool isControlled() const { return getPetType()==SUMMON_PET || getPetType()==HUNTER_PET; }
bool isTemporarySummoned() const { return m_duration > 0; }
+ bool IsPermanentPetFor(Player* owner); // pet have tab in character windows and set UNIT_FIELD_PETNUMBER
+
bool Create (uint32 guidlow, Map *map, uint32 phaseMask, uint32 Entry, uint32 pet_number);
bool CreateBaseAtCreature(Creature* creature);
bool LoadPetFromDB( Player* owner,uint32 petentry = 0,uint32 petnumber = 0, bool current = false );
diff --git a/src/game/PetHandler.cpp b/src/game/PetHandler.cpp
index 42d0093510b..bfbe8ca7df4 100644
--- a/src/game/PetHandler.cpp
+++ b/src/game/PetHandler.cpp
@@ -89,10 +89,6 @@ void WorldSession::HandlePetActionHelper(Unit *pet, uint64 guid1, uint16 spellid
switch(flag)
{
case ACT_COMMAND: //0x0700
- // Possessed or shared vision pets are only able to attack
- if ((pet->isPossessed() || pet->HasAuraType(SPELL_AURA_BIND_SIGHT)) && spellid != COMMAND_ATTACK)
- return;
-
switch(spellid)
{
case COMMAND_STAY: //flat=1792 //STAY
@@ -162,10 +158,7 @@ void WorldSession::HandlePetActionHelper(Unit *pet, uint64 guid1, uint16 spellid
}
case COMMAND_ABANDON: // abandon (hunter pet) or dismiss (summoned pet)
if(pet->GetCharmerGUID() == GetPlayer()->GetGUID())
- {
- if(GetPlayer()->m_seer != pet)
- _player->StopCastingCharm();
- }
+ _player->StopCastingCharm();
else if(pet->GetOwnerGUID() == GetPlayer()->GetGUID())
{
assert(pet->GetTypeId() == TYPEID_UNIT);
diff --git a/src/game/Player.cpp b/src/game/Player.cpp
index 494334466f4..a68002445bc 100644
--- a/src/game/Player.cpp
+++ b/src/game/Player.cpp
@@ -230,7 +230,7 @@ bool PlayerTaxi::LoadTaxiDestinationsFromString( const std::string& values, uint
}
// can't load taxi path without mount set (quest taxi path?)
- if(!objmgr.GetTaxiMount(GetTaxiSource(),team))
+ if(!objmgr.GetTaxiMount(GetTaxiSource(),team,true))
return false;
return true;
@@ -897,6 +897,8 @@ void Player::EnvironmentalDamage(EnviromentalDamage type, uint32 damage)
damage-=absorb+resist;
+ DealDamageMods(this,damage,&absorb);
+
WorldPacket data(SMSG_ENVIRONMENTALDAMAGELOG, (21));
data << uint64(GetGUID());
data << uint8(type!=DAMAGE_FALL_TO_VOID ? type : DAMAGE_FALL);
@@ -1490,7 +1492,12 @@ void Player::BuildEnumData( QueryResult * result, WorldPacket * p_data )
char_flags |= CHARACTER_FLAG_GHOST;
if(HasAtLoginFlag(AT_LOGIN_RENAME))
char_flags |= CHARACTER_FLAG_RENAME;
- if(sWorld.getConfig(CONFIG_DECLINED_NAMES_USED) && (fields[14].GetCppString() != ""))
+ if(sWorld.getConfig(CONFIG_DECLINED_NAMES_USED))
+ {
+ if(!fields[14].GetCppString().empty())
+ char_flags |= CHARACTER_FLAG_DECLINED;
+ }
+ else
char_flags |= CHARACTER_FLAG_DECLINED;
*p_data << uint32(char_flags); // character flags
@@ -1505,7 +1512,7 @@ void Player::BuildEnumData( QueryResult * result, WorldPacket * p_data )
uint32 petFamily = 0;
// show pet at selection character in character list only for non-ghost character
- if(result && isAlive() && (pClass == CLASS_WARLOCK || pClass == CLASS_HUNTER))
+ if (result && isAlive() && (pClass == CLASS_WARLOCK || pClass == CLASS_HUNTER || pClass == CLASS_DEATH_KNIGHT))
{
uint32 entry = fields[10].GetUInt32();
CreatureInfo const* cInfo = sCreatureStorage.LookupEntry<CreatureInfo>(entry);
@@ -1666,7 +1673,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
if (!(options & TELE_TO_NOT_UNSUMMON_PET))
{
//same map, only remove pet if out of range for new position
- if(pet && pet->GetDistance(x,y,z) >= OWNER_MAX_DISTANCE)
+ if(pet && !pet->IsWithinDist3d(x,y,z, OWNER_MAX_DISTANCE))
UnsummonPetTemporaryIfAny();
}
@@ -1798,7 +1805,7 @@ void Player::AddToWorld()
///- The player should only be added when logging in
Unit::AddToWorld();
- for(int i = PLAYER_SLOT_START; i < PLAYER_SLOT_END; i++)
+ for(int i = PLAYER_SLOT_START; i < PLAYER_SLOT_END; ++i)
{
if(m_items[i])
m_items[i]->AddToWorld();
@@ -1815,7 +1822,7 @@ void Player::RemoveFromWorld()
StopCastingBindSight();
}
- for(int i = PLAYER_SLOT_START; i < PLAYER_SLOT_END; i++)
+ for(int i = PLAYER_SLOT_START; i < PLAYER_SLOT_END; ++i)
{
if(m_items[i])
m_items[i]->RemoveFromWorld();
@@ -3287,6 +3294,20 @@ void Player::removeSpell(uint32 spell_id, bool disabled, bool update_action_bar_
}
}
+
+void Player::RemoveSpellCooldown( uint32 spell_id, bool update /* = false */ )
+{
+ m_spellCooldowns.erase(spell_id);
+
+ if(update)
+ {
+ WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8));
+ data << uint32(spell_id);
+ data << uint64(GetGUID());
+ SendDirectMessage(&data);
+ }
+}
+
void Player::RemoveArenaSpellCooldowns()
{
// remove cooldowns on spells that has < 15 min CD
@@ -5729,23 +5750,26 @@ ReputationRank Player::GetReputationRank(uint32 faction) const
}
//Calculate total reputation percent player gain with quest/creature level
-int32 Player::CalculateReputationGain(uint32 creatureOrQuestLevel, int32 rep, bool for_quest)
+int32 Player::CalculateReputationGain(uint32 creatureOrQuestLevel, int32 rep, int32 faction, bool for_quest)
{
float percent = 100.0f;
float rate = for_quest ? sWorld.getRate(RATE_REPUTATION_LOWLEVEL_QUEST) : sWorld.getRate(RATE_REPUTATION_LOWLEVEL_KILL);
- if(rate != 1.0f && creatureOrQuestLevel <= MaNGOS::XP::GetGrayLevel(getLevel()))
+ if (rate != 1.0f && creatureOrQuestLevel <= MaNGOS::XP::GetGrayLevel(getLevel()))
percent *= rate;
- int32 repMod = GetTotalAuraModifier(SPELL_AURA_MOD_REPUTATION_GAIN);
+ float repMod = GetTotalAuraModifier(SPELL_AURA_MOD_REPUTATION_GAIN);
+
+ if (!for_quest)
+ repMod += GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_FACTION_REPUTATION_GAIN, faction);
percent += rep > 0 ? repMod : -repMod;
- if(percent <= 0.0f)
+ if (percent <= 0.0f)
return 0;
- return int32(sWorld.getRate(RATE_REPUTATION_GAIN)*rep*percent/100);
+ return int32(sWorld.getRate(RATE_REPUTATION_GAIN)*rep*percent/100.0f);
}
//Calculates how many reputation points player gains in victim's enemy factions
@@ -5764,7 +5788,7 @@ void Player::RewardReputation(Unit *pVictim, float rate)
if(Rep->repfaction1 && (!Rep->team_dependent || GetTeam()==ALLIANCE))
{
- int32 donerep1 = CalculateReputationGain(pVictim->getLevel(),Rep->repvalue1,false);
+ int32 donerep1 = CalculateReputationGain(pVictim->getLevel(), Rep->repvalue1, Rep->repfaction1, false);
donerep1 = int32(donerep1*rate);
FactionEntry const *factionEntry1 = sFactionStore.LookupEntry(Rep->repfaction1);
uint32 current_reputation_rank1 = GetReputationMgr().GetRank(factionEntry1);
@@ -5782,7 +5806,7 @@ void Player::RewardReputation(Unit *pVictim, float rate)
if(Rep->repfaction2 && (!Rep->team_dependent || GetTeam()==HORDE))
{
- int32 donerep2 = CalculateReputationGain(pVictim->getLevel(),Rep->repvalue2,false);
+ int32 donerep2 = CalculateReputationGain(pVictim->getLevel(), Rep->repvalue2, Rep->repfaction2, false);
donerep2 = int32(donerep2*rate);
FactionEntry const *factionEntry2 = sFactionStore.LookupEntry(Rep->repfaction2);
uint32 current_reputation_rank2 = GetReputationMgr().GetRank(factionEntry2);
@@ -5807,7 +5831,7 @@ void Player::RewardReputation(Quest const *pQuest)
{
if(pQuest->RewRepFaction[i] && pQuest->RewRepValue[i] )
{
- int32 rep = CalculateReputationGain(GetQuestLevel(pQuest),pQuest->RewRepValue[i],true);
+ int32 rep = CalculateReputationGain(GetQuestLevel(pQuest), pQuest->RewRepValue[i], pQuest->RewRepFaction[i], true);
FactionEntry const* factionEntry = sFactionStore.LookupEntry(pQuest->RewRepFaction[i]);
if(factionEntry)
GetReputationMgr().ModifyReputation(factionEntry, rep);
@@ -6425,8 +6449,8 @@ void Player::_ApplyItemMods(Item *item, uint8 slot,bool apply)
if(slot >= INVENTORY_SLOT_BAG_END || !item)
return;
- // not apply/remove mods for broken item
- if(item->IsBroken())
+ // not apply mods for broken item
+ if(item->IsBroken() && apply)
return;
ItemPrototype const *proto = item->GetProto();
@@ -6464,30 +6488,25 @@ void Player::_ApplyItemBonuses(ItemPrototype const *proto, uint8 slot, bool appl
if(slot >= INVENTORY_SLOT_BAG_END || !proto)
return;
+ ScalingStatDistributionEntry const *ssd = proto->ScalingStatDistribution ? sScalingStatDistributionStore.LookupEntry(proto->ScalingStatDistribution) : 0;
+ ScalingStatValuesEntry const *ssv = proto->ScalingStatValue ? sScalingStatValuesStore.LookupEntry(getLevel()) : 0;
+
for (int i = 0; i < MAX_ITEM_PROTO_STATS; ++i)
{
uint32 statType = 0;
- int32 val = 0;
-
- if(proto->ScalingStatDistribution)
+ int32 val = 0;
+ // If set ScalingStatDistribution need get stats and values from it
+ if (ssd && ssv)
{
- if(ScalingStatDistributionEntry const *ssd = sScalingStatDistributionStore.LookupEntry(proto->ScalingStatDistribution))
- {
- statType = ssd->StatMod[i];
-
- if(uint32 modifier = ssd->Modifier[i])
- {
- uint32 level = ((getLevel() > ssd->MaxLevel) ? ssd->MaxLevel : getLevel());
- if(ScalingStatValuesEntry const *ssv = sScalingStatValuesStore.LookupEntry(level))
- {
- uint32 multiplier = ssv->Multiplier[proto->GetScalingStatValuesColumn()];
- val = (multiplier * modifier) / 10000;
- }
- }
- }
+ if (ssd->StatMod[i] < 0)
+ continue;
+ statType = ssd->StatMod[i];
+ val = (ssv->getssdMultiplier(proto->ScalingStatValue) * ssd->Modifier[i]) / 10000;
}
else
{
+ if (i >= proto->StatsCount)
+ continue;
statType = proto->ItemStat[i].ItemStatType;
val = proto->ItemStat[i].ItemStatValue;
}
@@ -6642,8 +6661,18 @@ void Player::_ApplyItemBonuses(ItemPrototype const *proto, uint8 slot, bool appl
}
}
- if (proto->Armor)
- HandleStatModifier(UNIT_MOD_ARMOR, BASE_VALUE, float(proto->Armor), apply);
+ // If set ScalingStatValue armor get it or use item armor
+ uint32 armor = proto->Armor;
+ if (ssv)
+ {
+ if (uint32 ssvarmor = ssv->getArmorMod(proto->ScalingStatValue))
+ armor = ssvarmor;
+ }
+ // Add armor bonus from ArmorDamageModifier if > 0
+ if (proto->ArmorDamageModifier > 0)
+ armor+=proto->ArmorDamageModifier;
+ if (armor)
+ HandleStatModifier(UNIT_MOD_ARMOR, BASE_VALUE, float(armor), apply);
if (proto->Block)
HandleBaseModValue(SHIELD_BLOCK_VALUE, FLAT_MOD, float(proto->Block), apply);
@@ -6680,23 +6709,42 @@ void Player::_ApplyItemBonuses(ItemPrototype const *proto, uint8 slot, bool appl
attType = OFF_ATTACK;
}
- if (proto->Damage[0].DamageMin > 0 )
+ float minDamage = proto->Damage[0].DamageMin;
+ float maxDamage = proto->Damage[0].DamageMax;
+ int32 extraDPS = 0;
+ // If set dpsMod in ScalingStatValue use it for min (70% from average), max (130% from average) damage
+ if (ssv)
+ {
+ if (extraDPS = ssv->getDPSMod(proto->ScalingStatValue))
+ {
+ float average = extraDPS * proto->Delay / 1000.0f;
+ minDamage = 0.7f * average;
+ maxDamage = 1.3f * average;
+ }
+ }
+ if (minDamage > 0 )
{
- damage = apply ? proto->Damage[0].DamageMin : BASE_MINDAMAGE;
+ damage = apply ? minDamage : BASE_MINDAMAGE;
SetBaseWeaponDamage(attType, MINDAMAGE, damage);
//sLog.outError("applying mindam: assigning %f to weapon mindamage, now is: %f", damage, GetWeaponDamageRange(attType, MINDAMAGE));
}
- if (proto->Damage[0].DamageMax > 0 )
+ if (maxDamage > 0 )
{
- damage = apply ? proto->Damage[0].DamageMax : BASE_MAXDAMAGE;
+ damage = apply ? maxDamage : BASE_MAXDAMAGE;
SetBaseWeaponDamage(attType, MAXDAMAGE, damage);
}
- // Druids get feral AP bonus from weapon dps
+ // Apply feral bonus from ScalingStatValue if set
+ if (ssv)
+ {
+ if (int32 feral_bonus = ssv->getFeralBonus(proto->ScalingStatValue))
+ ApplyFeralAPBonus(feral_bonus, apply);
+ }
+ // Druids get feral AP bonus from weapon dps (lso use DPS from ScalingStatValue)
if(getClass() == CLASS_DRUID)
{
- int32 feral_bonus = proto->getFeralBonus();
+ int32 feral_bonus = proto->getFeralBonus(extraDPS);
if (feral_bonus > 0)
ApplyFeralAPBonus(feral_bonus, apply);
}
@@ -9825,18 +9873,22 @@ uint8 Player::CanEquipItem( uint8 slot, uint16 &dest, Item *pItem, bool swap, bo
return EQUIP_ERR_CANT_DO_RIGHT_NOW;
}
+ ScalingStatDistributionEntry const *ssd = pProto->ScalingStatDistribution ? sScalingStatDistributionStore.LookupEntry(pProto->ScalingStatDistribution) : 0;
+ if (ssd && ssd->MaxLevel < getLevel())
+ return EQUIP_ERR_ITEM_CANT_BE_EQUIPPED;
+
uint8 eslot = FindEquipSlot( pProto, slot, swap );
- if( eslot == NULL_SLOT )
+ if (eslot == NULL_SLOT)
return EQUIP_ERR_ITEM_CANT_BE_EQUIPPED;
- uint8 msg = CanUseItem( pItem , not_loading );
- if( msg != EQUIP_ERR_OK )
+ uint8 msg = CanUseItem(pItem , not_loading);
+ if (msg != EQUIP_ERR_OK)
return msg;
- if( !swap && GetItemByPos( INVENTORY_SLOT_BAG_0, eslot ) )
+ if (!swap && GetItemByPos(INVENTORY_SLOT_BAG_0, eslot))
return EQUIP_ERR_NO_EQUIPMENT_SLOT_AVAILABLE;
// if swap ignore item (equipped also)
- if(uint8 res2 = CanEquipUniqueItem(pItem, swap ? eslot : NULL_SLOT))
+ if (uint8 res2 = CanEquipUniqueItem(pItem, swap ? eslot : NULL_SLOT))
return res2;
// check unique-equipped special item classes
@@ -9844,16 +9896,16 @@ uint8 Player::CanEquipItem( uint8 slot, uint16 &dest, Item *pItem, bool swap, bo
{
for(int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i)
{
- if( Item* pBag = GetItemByPos( INVENTORY_SLOT_BAG_0, i ) )
+ if (Item* pBag = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
{
- if( ItemPrototype const* pBagProto = pBag->GetProto() )
+ if (pBag != pItem)
{
- if( pBagProto->Class==pProto->Class && (!swap || pBag->GetSlot() != eslot ) )
+ if (ItemPrototype const* pBagProto = pBag->GetProto())
{
- if(pBagProto->SubClass == ITEM_SUBCLASS_AMMO_POUCH)
- return EQUIP_ERR_CAN_EQUIP_ONLY1_AMMOPOUCH;
- else
- return EQUIP_ERR_CAN_EQUIP_ONLY1_QUIVER;
+ if (pBagProto->Class==pProto->Class && (!swap || pBag->GetSlot() != eslot))
+ return (pBagProto->SubClass == ITEM_SUBCLASS_AMMO_POUCH)
+ ? EQUIP_ERR_CAN_EQUIP_ONLY1_AMMOPOUCH
+ : EQUIP_ERR_CAN_EQUIP_ONLY1_QUIVER;
}
}
}
@@ -9862,25 +9914,25 @@ uint8 Player::CanEquipItem( uint8 slot, uint16 &dest, Item *pItem, bool swap, bo
uint32 type = pProto->InventoryType;
- if(eslot == EQUIPMENT_SLOT_OFFHAND)
+ if (eslot == EQUIPMENT_SLOT_OFFHAND)
{
if (type == INVTYPE_WEAPON || type == INVTYPE_WEAPONOFFHAND)
{
- if(!CanDualWield())
+ if (!CanDualWield())
return EQUIP_ERR_CANT_DUAL_WIELD;
}
else if (type == INVTYPE_2HWEAPON)
{
- if(!CanDualWield() || !CanTitanGrip())
+ if (!CanDualWield() || !CanTitanGrip())
return EQUIP_ERR_CANT_DUAL_WIELD;
}
- if(IsTwoHandUsed())
+ if (IsTwoHandUsed())
return EQUIP_ERR_CANT_EQUIP_WITH_TWOHANDED;
}
// equip two-hand weapon case (with possible unequip 2 items)
- if( type == INVTYPE_2HWEAPON )
+ if (type == INVTYPE_2HWEAPON)
{
if (eslot == EQUIPMENT_SLOT_OFFHAND)
{
@@ -9895,9 +9947,9 @@ uint8 Player::CanEquipItem( uint8 slot, uint16 &dest, Item *pItem, bool swap, bo
// offhand item must can be stored in inventory for offhand item and it also must be unequipped
Item *offItem = GetItemByPos( INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND );
ItemPosCountVec off_dest;
- if( offItem && (!not_loading ||
+ if (offItem && (!not_loading ||
CanUnequipItem(uint16(INVENTORY_SLOT_BAG_0) << 8 | EQUIPMENT_SLOT_OFFHAND,false) != EQUIP_ERR_OK ||
- CanStoreItem( NULL_BAG, NULL_SLOT, off_dest, offItem, false ) != EQUIP_ERR_OK ) )
+ CanStoreItem( NULL_BAG, NULL_SLOT, off_dest, offItem, false ) != EQUIP_ERR_OK ))
return swap ? EQUIP_ERR_ITEMS_CANT_BE_SWAPPED : EQUIP_ERR_INVENTORY_FULL;
}
}
@@ -9905,10 +9957,8 @@ uint8 Player::CanEquipItem( uint8 slot, uint16 &dest, Item *pItem, bool swap, bo
return EQUIP_ERR_OK;
}
}
- if( !swap )
- return EQUIP_ERR_ITEM_NOT_FOUND;
- else
- return EQUIP_ERR_ITEMS_CANT_BE_SWAPPED;
+
+ return !swap ? EQUIP_ERR_ITEM_NOT_FOUND : EQUIP_ERR_ITEMS_CANT_BE_SWAPPED;
}
uint8 Player::CanUnequipItem( uint16 pos, bool swap ) const
@@ -10127,38 +10177,49 @@ uint8 Player::CanBankItem( uint8 bag, uint8 slot, ItemPosCountVec &dest, Item *p
uint8 Player::CanUseItem( Item *pItem, bool not_loading ) const
{
- if( pItem )
+ if (pItem)
{
sLog.outDebug( "STORAGE: CanUseItem item = %u", pItem->GetEntry());
- if( !isAlive() && not_loading )
+
+ if (!isAlive() && not_loading)
return EQUIP_ERR_YOU_ARE_DEAD;
- //if( isStunned() )
+
+ //if (isStunned())
// return EQUIP_ERR_YOU_ARE_STUNNED;
+
ItemPrototype const *pProto = pItem->GetProto();
- if( pProto )
+ if (pProto)
{
- if( pItem->IsBindedNotWith(GetGUID()) )
+ if (pItem->IsBindedNotWith(GetGUID()))
return EQUIP_ERR_DONT_OWN_THAT_ITEM;
- if( (pProto->AllowableClass & getClassMask()) == 0 || (pProto->AllowableRace & getRaceMask()) == 0 )
+
+ if ((pProto->AllowableClass & getClassMask()) == 0 || (pProto->AllowableRace & getRaceMask()) == 0)
return EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM;
- if( pItem->GetSkill() != 0 )
+
+ if (pItem->GetSkill() != 0)
{
- if( GetSkillValue( pItem->GetSkill() ) == 0 )
+ if (GetSkillValue( pItem->GetSkill() ) == 0)
return EQUIP_ERR_NO_REQUIRED_PROFICIENCY;
}
- if( pProto->RequiredSkill != 0 )
+
+ if (pProto->RequiredSkill != 0)
{
- if( GetSkillValue( pProto->RequiredSkill ) == 0 )
+ if (GetSkillValue( pProto->RequiredSkill ) == 0)
return EQUIP_ERR_NO_REQUIRED_PROFICIENCY;
- else if( GetSkillValue( pProto->RequiredSkill ) < pProto->RequiredSkillRank )
+
+ if (GetSkillValue( pProto->RequiredSkill ) < pProto->RequiredSkillRank)
return EQUIP_ERR_ERR_CANT_EQUIP_SKILL;
}
- if( pProto->RequiredSpell != 0 && !HasSpell( pProto->RequiredSpell ) )
+
+ if (pProto->RequiredSpell != 0 && !HasSpell(pProto->RequiredSpell))
return EQUIP_ERR_NO_REQUIRED_PROFICIENCY;
- if( pProto->RequiredReputationFaction && uint32(GetReputationRank(pProto->RequiredReputationFaction)) < pProto->RequiredReputationRank )
+
+ if (pProto->RequiredReputationFaction && uint32(GetReputationRank(pProto->RequiredReputationFaction)) < pProto->RequiredReputationRank)
return EQUIP_ERR_CANT_EQUIP_REPUTATION;
- if( getLevel() < pProto->RequiredLevel )
+
+ if (getLevel() < pProto->RequiredLevel)
return EQUIP_ERR_CANT_EQUIP_LEVEL_I;
+
return EQUIP_ERR_OK;
}
}
@@ -16712,7 +16773,7 @@ void Player::PetSpellInitialize()
uint8 addlist = 0;
data << uint8(addlist); // placeholder
- if(pet->isControlled() && ((pet->getPetType() == HUNTER_PET) || ((pet->GetCreatureInfo()->type == CREATURE_TYPE_DEMON) && (getClass() == CLASS_WARLOCK))))
+ if (pet->IsPermanentPetFor(this))
{
// spells loop
for (PetSpellMap::iterator itr = pet->m_spells.begin(); itr != pet->m_spells.end(); ++itr)
@@ -17114,43 +17175,68 @@ void Player::HandleStealthedUnitsDetection()
}
}
-bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, uint32 mount_id, Creature* npc)
+bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, Creature* npc /*= NULL*/, uint32 spellid /*= 0*/)
{
if(nodes.size() < 2)
return false;
- // not let cheating with start flight mounted
- if(IsMounted())
+ // not let cheating with start flight in time of logout process || if casting not finished || while in combat || if not use Spell's with EffectSendTaxi
+ if(GetSession()->isLogingOut() || isInCombat())
{
WorldPacket data(SMSG_ACTIVATETAXIREPLY, 4);
- data << uint32(ERR_TAXIPLAYERALREADYMOUNTED);
+ data << uint32(ERR_TAXIPLAYERBUSY);
GetSession()->SendPacket(&data);
return false;
}
- if( m_ShapeShiftFormSpellId && m_form != FORM_BATTLESTANCE && m_form != FORM_BERSERKERSTANCE && m_form != FORM_DEFENSIVESTANCE && m_form != FORM_SHADOW )
- {
- WorldPacket data(SMSG_ACTIVATETAXIREPLY, 4);
- data << uint32(ERR_TAXIPLAYERSHAPESHIFTED);
- GetSession()->SendPacket(&data);
+ if(HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE))
return false;
- }
- // not let cheating with start flight in time of logout process || if casting not finished || while in combat || if not use Spell's with EffectSendTaxi
- if(GetSession()->isLogingOut() ||
- (!m_currentSpells[CURRENT_GENERIC_SPELL] ||
- m_currentSpells[CURRENT_GENERIC_SPELL]->m_spellInfo->Effect[0] != SPELL_EFFECT_SEND_TAXI)&&
- IsNonMeleeSpellCasted(false) ||
- isInCombat())
+ // taximaster case
+ if(npc)
{
- WorldPacket data(SMSG_ACTIVATETAXIREPLY, 4);
- data << uint32(ERR_TAXIPLAYERBUSY);
- GetSession()->SendPacket(&data);
- return false;
+ // not let cheating with start flight mounted
+ if(IsMounted())
+ {
+ WorldPacket data(SMSG_ACTIVATETAXIREPLY, 4);
+ data << uint32(ERR_TAXIPLAYERALREADYMOUNTED);
+ GetSession()->SendPacket(&data);
+ return false;
+ }
+
+ if( m_ShapeShiftFormSpellId && m_form != FORM_BATTLESTANCE && m_form != FORM_BERSERKERSTANCE && m_form != FORM_DEFENSIVESTANCE && m_form != FORM_SHADOW )
+ {
+ WorldPacket data(SMSG_ACTIVATETAXIREPLY, 4);
+ data << uint32(ERR_TAXIPLAYERSHAPESHIFTED);
+ GetSession()->SendPacket(&data);
+ return false;
+ }
+
+ // not let cheating with start flight in time of logout process || if casting not finished || while in combat || if not use Spell's with EffectSendTaxi
+ if(IsNonMeleeSpellCasted(false))
+ {
+ WorldPacket data(SMSG_ACTIVATETAXIREPLY, 4);
+ data << uint32(ERR_TAXIPLAYERBUSY);
+ GetSession()->SendPacket(&data);
+ return false;
+ }
}
+ // cast case or scripted call case
+ else
+ {
+ RemoveAurasByType(SPELL_AURA_MOUNTED);
- if(HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE))
- return false;
+ if( m_ShapeShiftFormSpellId && m_form != FORM_BATTLESTANCE && m_form != FORM_BERSERKERSTANCE && m_form != FORM_DEFENSIVESTANCE && m_form != FORM_SHADOW )
+ RemoveAurasDueToSpell(m_ShapeShiftFormSpellId);
+
+ if(m_currentSpells[CURRENT_GENERIC_SPELL] && m_currentSpells[CURRENT_GENERIC_SPELL]->m_spellInfo->Id != spellid)
+ InterruptSpell(CURRENT_GENERIC_SPELL,false);
+
+ InterruptSpell(CURRENT_AUTOREPEAT_SPELL,false);
+
+ if(m_currentSpells[CURRENT_CHANNELED_SPELL] && m_currentSpells[CURRENT_CHANNELED_SPELL]->m_spellInfo->Id != spellid)
+ InterruptSpell(CURRENT_CHANNELED_SPELL,true);
+ }
uint32 sourcenode = nodes[0];
@@ -17179,8 +17265,8 @@ bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, uint32 mount_i
return false;
}
}
- // node must have pos if not spell case (npc!=0)
- else if(npc)
+ // node must have pos if taxi master case (npc != NULL)
+ else if (npc)
{
WorldPacket data(SMSG_ACTIVATETAXIREPLY, 4);
data << uint32(ERR_TAXIUNSPECIFIEDSERVERERROR);
@@ -17232,10 +17318,11 @@ bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, uint32 mount_i
prevnode = lastnode;
}
- if(!mount_id) // if not provide then attempt use default.
- mount_id = objmgr.GetTaxiMount(sourcenode, GetTeam());
+ // get mount model (in case non taximaster (npc==NULL) allow more wide lookup)
+ uint16 mount_id = objmgr.GetTaxiMount(sourcenode, GetTeam(), npc == NULL);
- if (mount_id == 0 || sourcepath == 0)
+ // in spell case allow 0 model
+ if (mount_id == 0 && spellid == 0 || sourcepath == 0)
{
WorldPacket data(SMSG_ACTIVATETAXIREPLY, 4);
data << uint32(ERR_TAXIUNSPECIFIEDSERVERERROR);
@@ -17277,6 +17364,21 @@ bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, uint32 mount_i
return true;
}
+bool Player::ActivateTaxiPathTo( uint32 taxi_path_id, uint32 spellid /*= 0*/ )
+{
+ TaxiPathEntry const* entry = sTaxiPathStore.LookupEntry(taxi_path_id);
+ if(!entry)
+ return false;
+
+ std::vector<uint32> nodes;
+
+ nodes.resize(2);
+ nodes[0] = entry->from;
+ nodes[1] = entry->to;
+
+ return ActivateTaxiPathTo(nodes,NULL,spellid);
+}
+
void Player::ProhibitSpellScholl(SpellSchoolMask idSchoolMask, uint32 unTimeMs )
{
// last check 2.0.10
@@ -20509,12 +20611,14 @@ void Player::ResummonPetTemporaryUnSummonedIfAny()
bool Player::canSeeSpellClickOn(Creature const *c) const
{
- SpellClickInfoMap const& map = objmgr.mSpellClickInfoMap;
- if(map.empty())
+ SpellClickInfoMap::const_iterator lower = objmgr.mSpellClickInfoMap.lower_bound(c->GetEntry());
+ SpellClickInfoMap::const_iterator upper = objmgr.mSpellClickInfoMap.upper_bound(c->GetEntry());
+ if(lower == upper)
return true;
- for(SpellClickInfoMap::const_iterator itr = map.lower_bound(c->GetEntry()); itr != map.upper_bound(c->GetEntry()); ++itr)
+ for(SpellClickInfoMap::const_iterator itr = lower; itr != upper; ++itr)
{
+ sLog.outError("%u %u %u %u", (uint32)itr->second.castFlags, itr->second.questId, itr->second.spellId);
if(itr->second.questId == 0 || GetQuestStatus(itr->second.questId) == QUEST_STATUS_INCOMPLETE)
return true;
}
diff --git a/src/game/Player.h b/src/game/Player.h
index ecab25122bf..0223364cce0 100644
--- a/src/game/Player.h
+++ b/src/game/Player.h
@@ -867,7 +867,8 @@ class TRINITY_DLL_SPEC Player : public Unit
PlayerTaxi m_taxi;
void InitTaxiNodesForLevel() { m_taxi.InitTaxiNodesForLevel(getRace(), getClass(), getLevel()); }
- bool ActivateTaxiPathTo(std::vector<uint32> const& nodes, uint32 mount_id = 0 , Creature* npc = NULL);
+ bool ActivateTaxiPathTo(std::vector<uint32> const& nodes, Creature* npc = NULL, uint32 spellid = 0);
+ bool ActivateTaxiPathTo(uint32 taxi_path_id, uint32 spellid = 0);
// mount_id can be used in scripting calls
bool isAcceptWhispers() const { return m_ExtraFlags & PLAYER_EXTRA_ACCEPT_WHISPERS; }
void SetAcceptWhispers(bool on) { if(on) m_ExtraFlags |= PLAYER_EXTRA_ACCEPT_WHISPERS; else m_ExtraFlags &= ~PLAYER_EXTRA_ACCEPT_WHISPERS; }
@@ -1383,7 +1384,7 @@ class TRINITY_DLL_SPEC Player : public Unit
void AddSpellCooldown(uint32 spell_id, uint32 itemid, time_t end_time);
void SendCooldownEvent(SpellEntry const *spellInfo, uint32 itemId = 0, Spell* spell = NULL);
void ProhibitSpellScholl(SpellSchoolMask idSchoolMask, uint32 unTimeMs );
- void RemoveSpellCooldown(uint32 spell_id) { m_spellCooldowns.erase(spell_id); }
+ void RemoveSpellCooldown(uint32 spell_id, bool update = false);
void RemoveArenaSpellCooldowns();
void RemoveAllSpellCooldown();
void _LoadSpellCooldowns(QueryResult *result);
@@ -1668,6 +1669,8 @@ class TRINITY_DLL_SPEC Player : public Unit
//End of PvP System
+ inline SpellCooldowns GetSpellCooldowns() const { return m_spellCooldowns; }
+
void SetDrunkValue(uint16 newDrunkValue, uint32 itemid=0);
uint16 GetDrunkValue() const { return m_drunk; }
static DrunkenState GetDrunkenstateByValue(uint16 value);
@@ -2151,7 +2154,6 @@ class TRINITY_DLL_SPEC Player : public Unit
PlayerMails m_mail;
PlayerSpellMap m_spells;
- SpellCooldowns m_spellCooldowns;
uint32 m_lastPotionId; // last used health/mana potion in combat, that block next potion use
ActionButtonList m_actionButtons;
@@ -2256,7 +2258,7 @@ class TRINITY_DLL_SPEC Player : public Unit
Item* _StoreItem( uint16 pos, Item *pItem, uint32 count, bool clone, bool update );
void UpdateKnownCurrencies(uint32 itemId, bool apply);
- int32 CalculateReputationGain(uint32 creatureOrQuestLevel, int32 rep, bool for_quest);
+ int32 CalculateReputationGain(uint32 creatureOrQuestLevel, int32 rep, int32 faction, bool for_quest);
void AdjustQuestReqItemCount( Quest const* pQuest, QuestStatusData& questStatusData );
GridReference<Player> m_gridRef;
@@ -2284,6 +2286,8 @@ class TRINITY_DLL_SPEC Player : public Unit
AchievementMgr m_achievementMgr;
ReputationMgr m_reputationMgr;
+
+ SpellCooldowns m_spellCooldowns;
};
void AddItemsSetItem(Player*player,Item *item);
diff --git a/src/game/PossessedAI.cpp b/src/game/PossessedAI.cpp
deleted file mode 100644
index 8fd2e5ca014..00000000000
--- a/src/game/PossessedAI.cpp
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/>
- *
- * Thanks to the original authors: MaNGOS <http://getmangos.com/>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
diff --git a/src/game/PossessedAI.h b/src/game/PossessedAI.h
deleted file mode 100644
index bef7853246e..00000000000
--- a/src/game/PossessedAI.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/>
- *
- * Thanks to the original authors: MaNGOS <http://getmangos.com/>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef MANGOS_POSSESSEDAI_H
-#define MANGOS_POSSESSEDAI_H
-
-
-#endif
diff --git a/src/game/RandomMovementGenerator.cpp b/src/game/RandomMovementGenerator.cpp
index 6d147f15b8d..93e10ad6115 100644
--- a/src/game/RandomMovementGenerator.cpp
+++ b/src/game/RandomMovementGenerator.cpp
@@ -58,6 +58,9 @@ RandomMovementGenerator<Creature>::_setRandomLocation(Creature &creature)
bool is_water_ok = creature.canSwim();
bool is_air_ok = creature.canFly();
+ for(uint32 i = 0;; ++i)
+ {
+
const float angle = rand_norm()*(M_PI*2);
const float range = rand_norm()*wander_distance;
const float distanceX = range * cos(angle);
@@ -72,6 +75,12 @@ RandomMovementGenerator<Creature>::_setRandomLocation(Creature &creature)
dist = (nx - X)*(nx - X) + (ny - Y)*(ny - Y);
+ if(i == 5)
+ {
+ nz = Z;
+ break;
+ }
+
if (is_air_ok) // 3D system above ground and above water (flying mode)
{
const float distanceZ = rand_norm() * sqrtf(dist)/2; // Limit height change
@@ -79,12 +88,13 @@ RandomMovementGenerator<Creature>::_setRandomLocation(Creature &creature)
float tz = map->GetHeight(nx, ny, nz-2.0f, false); // Map check only, vmap needed here but need to alter vmaps checks for height.
float wz = map->GetWaterLevel(nx, ny);
if (tz >= nz || wz >= nz)
- return; // Problem here, we must fly above the ground and water, not under. Let's try on next tick
+ continue; // Problem here, we must fly above the ground and water, not under. Let's try on next tick
}
//else if (is_water_ok) // 3D system under water and above ground (swimming mode)
else // 2D only
{
dist = dist>=100.0f ? 10.0f : sqrtf(dist); // 10.0 is the max that vmap high can check (MAX_CAN_FALL_DISTANCE)
+
// The fastest way to get an accurate result 90% of the time.
// Better result can be obtained like 99% accuracy with a ray light, but the cost is too high and the code is too long.
nz = map->GetHeight(nx,ny,Z+dist-2.0f,false); // Map check
@@ -95,11 +105,14 @@ RandomMovementGenerator<Creature>::_setRandomLocation(Creature &creature)
{
nz = map->GetHeight(nx,ny,Z+dist-2.0f,true); // Vmap Higher
if (fabs(nz-Z)>dist)
- return; // let's forget this bad coords where a z cannot be find and retry at next tick
+ continue; // let's forget this bad coords where a z cannot be find and retry at next tick
}
}
}
+ break;
+ }
+
Traveller<Creature> traveller(creature);
creature.SetOrientation(creature.GetAngle(nx,ny));
i_destinationHolder.SetDestination(traveller, nx, ny, nz);
@@ -130,7 +143,8 @@ RandomMovementGenerator<Creature>::Initialize(Creature &creature)
if(!creature.isAlive())
return;
- wander_distance = creature.GetRespawnRadius();
+ if(!wander_distance)
+ wander_distance = creature.GetRespawnRadius();
if (creature.canFly())
creature.AddUnitMovementFlag(MOVEMENTFLAG_FLYING2);
@@ -181,7 +195,7 @@ RandomMovementGenerator<Creature>::Update(Creature &creature, const uint32 &diff
creature.SetUnitMovementFlags(irand(0,RUNNING_CHANCE_RANDOMMV) > 0 ? MOVEMENTFLAG_WALK_MODE : MOVEMENTFLAG_NONE);
_setRandomLocation(creature);
}
- else if(creature.isPet() && creature.GetOwner() && creature.GetDistance(creature.GetOwner()) > PET_FOLLOW_DIST+2.5f)
+ else if(creature.isPet() && creature.GetOwner() && !creature.IsWithinDist(creature.GetOwner(),PET_FOLLOW_DIST+2.5f))
{
creature.SetUnitMovementFlags(MOVEMENTFLAG_NONE);
_setRandomLocation(creature);
diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h
index cc8db7c30f8..a068815bb1c 100644
--- a/src/game/SharedDefines.h
+++ b/src/game/SharedDefines.h
@@ -24,9 +24,6 @@
#include "Platform/Define.h"
#include <cassert>
-#define MaNGOS Trinity
-#define GetMangosString GetTrinityString
-
enum Gender
{
GENDER_MALE = 0,
@@ -1109,9 +1106,10 @@ enum SpellHitType
{
SPELL_HIT_TYPE_UNK1 = 0x00001,
SPELL_HIT_TYPE_CRIT = 0x00002,
- SPELL_HIT_TYPE_UNK2 = 0x00004,
- SPELL_HIT_TYPE_UNK3 = 0x00008,
- SPELL_HIT_TYPE_UNK4 = 0x00020
+ SPELL_HIT_TYPE_UNK3 = 0x00004,
+ SPELL_HIT_TYPE_UNK4 = 0x00008,
+ SPELL_HIT_TYPE_UNK5 = 0x00010, // replace caster?
+ SPELL_HIT_TYPE_UNK6 = 0x00020
};
enum SpellDmgClass
@@ -1819,6 +1817,7 @@ enum CreatureType
};
uint32 const CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD = (1 << (CREATURE_TYPE_HUMANOID-1)) | (1 << (CREATURE_TYPE_UNDEAD-1));
+uint32 const CREATURE_TYPEMASK_MECHANICAL_OR_ELEMENTAL = (1 << (CREATURE_TYPE_MECHANICAL-1)) | (1 << (CREATURE_TYPE_ELEMENTAL-1));
// CreatureFamily.dbc
enum CreatureFamily
diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp
index 5934542f64f..2c778616d78 100644
--- a/src/game/Spell.cpp
+++ b/src/game/Spell.cpp
@@ -476,6 +476,35 @@ Spell::~Spell()
delete m_spellValue;
}
+template<typename T>
+WorldObject* Spell::FindCorpseUsing()
+{
+ // non-standard target selection
+ float max_range = GetSpellMaxRange(m_spellInfo, false);
+
+ CellPair p(MaNGOS::ComputeCellPair(m_caster->GetPositionX(), m_caster->GetPositionY()));
+ Cell cell(p);
+ cell.data.Part.reserved = ALL_DISTRICT;
+ cell.SetNoCreate();
+
+ WorldObject* result = NULL;
+
+ T u_check(m_caster, max_range);
+ MaNGOS::WorldObjectSearcher<T> searcher(m_caster, result, u_check);
+
+ TypeContainerVisitor<MaNGOS::WorldObjectSearcher<T>, GridTypeMapContainer > grid_searcher(searcher);
+ CellLock<GridReadGuard> cell_lock(cell, p);
+ cell_lock->Visit(cell_lock, grid_searcher, *m_caster->GetMap());
+
+ if (!result)
+ {
+ TypeContainerVisitor<MaNGOS::WorldObjectSearcher<T>, WorldTypeMapContainer > world_searcher(searcher);
+ cell_lock->Visit(cell_lock, world_searcher, *m_caster->GetMap());
+ }
+
+ return result;
+}
+
void Spell::FillTargetMap()
{
for(uint32 i = 0; i < 3; ++i)
@@ -535,17 +564,7 @@ void Spell::FillTargetMap()
{
case 20577: // Cannibalize
{
- // non-standard target selection
- SpellRangeEntry const* srange = sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex);
- float max_range = GetSpellMaxRangeForHostile(srange);
- WorldObject* result = NULL;
-
- Trinity::CannibalizeObjectCheck u_check(m_caster, max_range);
- Trinity::WorldObjectSearcher<Trinity::CannibalizeObjectCheck > searcher(m_caster, result, u_check);
- m_caster->VisitNearbyGridObject(max_range, searcher);
- if(!result)
- m_caster->VisitNearbyWorldObject(max_range, searcher);
-
+ WorldObject* result = FindCorpseUsing<MaNGOS::CannibalizeObjectCheck> ();
if(result)
{
@@ -566,15 +585,7 @@ void Spell::FillTargetMap()
{
// clear cooldown at fail
if(m_caster->GetTypeId()==TYPEID_PLAYER)
- {
- ((Player*)m_caster)->RemoveSpellCooldown(m_spellInfo->Id);
-
- WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8));
- data << uint32(m_spellInfo->Id);
- data << uint64(m_caster->GetGUID());
- ((Player*)m_caster)->GetSession()->SendPacket(&data);
- }
-
+ ((Player*)m_caster)->RemoveSpellCooldown(m_spellInfo->Id,true);
SendCastResult(SPELL_FAILED_NO_EDIBLE_CORPSES);
finish(false);
}
@@ -598,6 +609,7 @@ void Spell::FillTargetMap()
case SPELL_EFFECT_SELF_RESURRECT:
case SPELL_EFFECT_REPUTATION:
case SPELL_EFFECT_LEARN_SPELL:
+ case SPELL_EFFECT_SEND_TAXI:
if(m_targets.getUnitTarget())
AddUnitTarget(m_targets.getUnitTarget(), i);
// Triggered spells have additional spell targets - cast them even if no explicit unit target is given (required for spell 50516 for example)
@@ -1027,6 +1039,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target)
// Add bonuses and fill damageInfo struct
caster->CalculateSpellDamageTaken(&damageInfo, m_damage, m_spellInfo);
+ caster->DealDamageMods(damageInfo.target,damageInfo.damage,&damageInfo.absorb);
// Send log damage message to client
caster->SendSpellNonMeleeDamageLog(&damageInfo);
@@ -1186,8 +1199,8 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask)
if (aura_effmask)
{
- Unit * caster = m_originalCaster ? m_originalCaster : m_caster;
- Aura * Aur= new Aura(m_spellInfo, aura_effmask, &m_currentBasePoints[0], unit, caster , m_CastItem, m_caster);
+ Unit * caster = m_originalCaster ? m_originalCaster : m_caster;
+ Aura * Aur = new Aura(m_spellInfo, aura_effmask, m_currentBasePoints, unit, caster, m_CastItem, m_caster);
if (!Aur->IsAreaAura())
{
@@ -1412,7 +1425,7 @@ struct TargetDistanceOrder : public std::binary_function<const Unit, const Unit,
// functor for operator ">"
bool operator()(const Unit* _Left, const Unit* _Right) const
{
- return (MainTarget->GetDistance(_Left) < MainTarget->GetDistance(_Right));
+ return MainTarget->GetDistanceOrder(_Left,_Right);
}
};
@@ -1477,7 +1490,7 @@ void Spell::SearchChainTarget(std::list<Unit*> &TagUnitMap, float max_range, uin
if(cur->GetDistance(*next) > CHAIN_SPELL_JUMP_RADIUS)
break;
while(m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MELEE
- && !m_caster->isInFront(*next, max_range)
+ && !m_caster->isInFrontInMap(*next, max_range)
|| !m_caster->canSeeOrDetect(*next, false)
|| !cur->IsWithinLOSInMap(*next))
{
@@ -1595,6 +1608,8 @@ WorldObject* Spell::SearchNearbyTarget(float range, SpellTargets TargetType)
break;
}
case SPELL_TARGET_TYPE_CREATURE:
+ if(m_targets.getUnitTarget() && m_targets.getUnitTarget()->GetEntry() == i_spellST->second.targetEntry)
+ return m_targets.getUnitTarget();
case SPELL_TARGET_TYPE_DEAD:
default:
{
@@ -1752,15 +1767,15 @@ void Spell::SetTargetMap(uint32 i, uint32 cur)
if(!target)
return;
- else if(target->GetTypeId() == TYPEID_UNIT)
+ else if(target->GetTypeId() == TYPEID_GAMEOBJECT)
+ AddGOTarget((GameObject*)target, i);
+ else
{
pushType = PUSH_CHAIN;
- if(!m_targets.getUnitTarget())
+ if(m_targets.getUnitTarget() != target)
m_targets.setUnitTarget((Unit*)target);
}
- else if(target->GetTypeId() == TYPEID_GAMEOBJECT)
- AddGOTarget((GameObject*)target, i);
break;
}
@@ -1923,7 +1938,13 @@ void Spell::SetTargetMap(uint32 i, uint32 cur)
m_targets.setDestination(st->target_X, st->target_Y, st->target_Z);
}
else
- sLog.outError( "SPELL: unknown target coordinates for spell ID %u\n", m_spellInfo->Id );
+ {
+ sLog.outError( "SPELL: unknown target coordinates for spell ID %u", m_spellInfo->Id );
+ Unit *target = NULL;
+ if(uint64 guid = m_caster->GetUInt64Value(UNIT_FIELD_TARGET))
+ target = ObjectAccessor::GetUnit(*m_caster, guid);
+ m_targets.setDestination(target ? target : m_caster);
+ }
break;
case TARGET_DST_HOME:
if(m_caster->GetTypeId() == TYPEID_PLAYER)
@@ -2043,7 +2064,7 @@ void Spell::SetTargetMap(uint32 i, uint32 cur)
else if(pushType)
{
// Dummy, just for client
- if(spellmgr.EffectTargetType[m_spellInfo->Effect[i]] == SPELL_REQUIRE_DEST)
+ if(spellmgr.EffectTargetType[m_spellInfo->Effect[i]] != SPELL_REQUIRE_UNIT)
return;
float radius;
@@ -2225,9 +2246,20 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect* triggeredByAura
if(!m_targets.getUnitTargetGUID() && m_spellInfo->Targets & TARGET_FLAG_UNIT)
{
- if(Unit *target = ObjectAccessor::GetUnit(*m_caster, m_caster->GetUInt64Value(UNIT_FIELD_TARGET)))
- if(IsValidSingleTargetSpell(target))
- m_targets.setUnitTarget(target);
+ Unit *target = NULL;
+ if(m_caster->GetTypeId() == TYPEID_UNIT)
+ target = m_caster->getVictim();
+ else
+ target = ObjectAccessor::GetUnit(*m_caster, ((Player*)m_caster)->GetSelection());
+
+ if(target && IsValidSingleTargetSpell(target))
+ m_targets.setUnitTarget(target);
+ else
+ {
+ SendCastResult(SPELL_FAILED_BAD_TARGETS);
+ finish(false);
+ return;
+ }
}
m_spellState = SPELL_STATE_PREPARING;
@@ -2835,8 +2867,7 @@ void Spell::finish(bool ok)
m_caster->clearUnitState(UNIT_STAT_CASTING);
// Unsummon summon as possessed creatures on spell cancel
- if(IsChanneledSpell(m_spellInfo)
- && m_caster->GetTypeId() == TYPEID_PLAYER)
+ if(IsChanneledSpell(m_spellInfo) && m_caster->GetTypeId() == TYPEID_PLAYER)
{
if (Unit * charm = m_caster->GetCharm())
for(int i = 0; i < 3; ++i)
@@ -2854,7 +2885,12 @@ void Spell::finish(bool ok)
}
}
}
- else if (m_caster->GetTypeId()==TYPEID_UNIT && ((Creature*)m_caster)->isSummon())
+
+ // other code related only to successfully finished spells
+ if(!ok)
+ return;
+
+ if (m_caster->GetTypeId()==TYPEID_UNIT && ((Creature*)m_caster)->isSummon())
{
// Unsummon statue
uint32 spell = m_caster->GetUInt32Value(UNIT_CREATED_BY_SPELL);
@@ -2867,10 +2903,6 @@ void Spell::finish(bool ok)
}
}
- // other code related only to successfully finished spells
- if(!ok)
- return;
-
//remove spell mods
if (m_caster->GetTypeId() == TYPEID_PLAYER)
((Player*)m_caster)->RemoveSpellMods(this);
@@ -3969,13 +4001,16 @@ SpellCastResult Spell::CheckCast(bool strict)
return SPELL_FAILED_NOT_IN_ARENA;
// zone check
- uint32 zone, area;
- m_caster->GetZoneAndAreaId(zone,area);
+ if(m_caster->GetTypeId() == TYPEID_UNIT || !((Player*)m_caster)->isGameMaster())
+ {
+ uint32 zone, area;
+ m_caster->GetZoneAndAreaId(zone,area);
- SpellCastResult locRes= spellmgr.GetSpellAllowedInLocationError(m_spellInfo,m_caster->GetMapId(),zone,area,
- m_caster->GetTypeId()==TYPEID_PLAYER ? ((Player*)m_caster) : NULL);
- if(locRes != SPELL_CAST_OK)
- return locRes;
+ SpellCastResult locRes= spellmgr.GetSpellAllowedInLocationError(m_spellInfo,m_caster->GetMapId(),zone,area,
+ m_caster->GetTypeId()==TYPEID_PLAYER ? ((Player*)m_caster) : NULL);
+ if(locRes != SPELL_CAST_OK)
+ return locRes;
+ }
// not let players cast spells at mount (and let do it to creatures)
if( m_caster->IsMounted() && m_caster->GetTypeId()==TYPEID_PLAYER && !m_IsTriggeredSpell &&
@@ -4822,10 +4857,9 @@ SpellCastResult Spell::CheckRange(bool strict)
if(m_targets.m_targetMask == TARGET_FLAG_DEST_LOCATION && m_targets.m_destX != 0 && m_targets.m_destY != 0 && m_targets.m_destZ != 0)
{
- float dist = m_caster->GetDistance(m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ);
- if(dist > max_range)
+ if(!m_caster->IsWithinDist3d(m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ,max_range))
return SPELL_FAILED_OUT_OF_RANGE;
- if(dist < min_range)
+ if(m_caster->IsWithinDist3d(m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ,min_range))
return SPELL_FAILED_TOO_CLOSE;
}
diff --git a/src/game/Spell.h b/src/game/Spell.h
index 6dc8477dcdb..694bcf11277 100644
--- a/src/game/Spell.h
+++ b/src/game/Spell.h
@@ -412,6 +412,8 @@ class Spell
void SetTargetMap(uint32 i, uint32 cur);
+ template<typename T> WorldObject* FindCorpseUsing();
+
bool CheckTarget( Unit* target, uint32 eff );
bool CanAutoCast(Unit* target);
void CheckSrc() { if(!m_targets.HasSrc()) m_targets.setSrc(m_caster); }
@@ -607,7 +609,7 @@ class Spell
void SpellDamageWeaponDmg(uint32 i);
void SpellDamageHeal(uint32 i);
- void GetSummonPosition(float &x, float &y, float &z, float radius = 0.0f, uint32 count = 0);
+ void GetSummonPosition(uint32 i, float &x, float &y, float &z, float radius = 0.0f, uint32 count = 0);
void SummonGuardian (uint32 entry, SummonPropertiesEntry const *properties);
SpellCastResult CanOpenLock(uint32 effIndex, uint32 lockid, SkillType& skillid, int32& reqSkillValue, int32& skillValue);
@@ -666,6 +668,10 @@ namespace Trinity
{
Unit *target = (Unit*)itr->getSource();
+ // mostly phase check
+ if(!itr->getSource()->IsInMap(i_source))
+ continue;
+
switch (i_TargetType)
{
case SPELL_TARGETS_ENEMY:
@@ -706,11 +712,11 @@ namespace Trinity
i_data->push_back(target);
break;
case PUSH_IN_FRONT:
- if(i_source->isInFront(target, i_radius, M_PI/3))
+ if(i_source->isInFrontInMap(target, i_radius, M_PI/3))
i_data->push_back(target);
break;
case PUSH_IN_BACK:
- if(i_source->isInBack(target, i_radius, M_PI/3))
+ if(i_source->isInBackInMap(target, i_radius, M_PI/3))
i_data->push_back(target);
break;
case PUSH_IN_LINE:
diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp
index f7f13acc3f8..f7643747a21 100644
--- a/src/game/SpellAuras.cpp
+++ b/src/game/SpellAuras.cpp
@@ -196,7 +196,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]=
&AuraEffect::HandleRangedAmmoHaste, //141 SPELL_AURA_MOD_RANGED_AMMO_HASTE
&AuraEffect::HandleAuraModBaseResistancePCT, //142 SPELL_AURA_MOD_BASE_RESISTANCE_PCT
&AuraEffect::HandleAuraModResistanceExclusive, //143 SPELL_AURA_MOD_RESISTANCE_EXCLUSIVE
- &AuraEffect::HandleNoImmediateEffect, //144 SPELL_AURA_SAFE_FALL implemented in WorldSession::HandleMovementOpcodes
+ &AuraEffect::HandleAuraSafeFall, //144 SPELL_AURA_SAFE_FALL implemented in WorldSession::HandleMovementOpcodes
&AuraEffect::HandleAuraModPetTalentsPoints, //145 SPELL_AURA_MOD_PET_TALENT_POINTS
&AuraEffect::HandleNoImmediateEffect, //146 SPELL_AURA_ALLOW_TAME_PET_TYPE
&AuraEffect::HandleModStateImmunityMask, //147 SPELL_AURA_MECHANIC_IMMUNITY_MASK
@@ -242,7 +242,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]=
&AuraEffect::HandleNoImmediateEffect, //187 SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_CHANCE implemented in Unit::GetUnitCriticalChance
&AuraEffect::HandleNoImmediateEffect, //188 SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_CHANCE implemented in Unit::GetUnitCriticalChance
&AuraEffect::HandleModRating, //189 SPELL_AURA_MOD_RATING
- &AuraEffect::HandleNULL, //190 SPELL_AURA_MOD_FACTION_REPUTATION_GAIN
+ &AuraEffect::HandleNoImmediateEffect, //190 SPELL_AURA_MOD_FACTION_REPUTATION_GAIN implemented in Player::CalculateReputationGain
&AuraEffect::HandleAuraModUseNormalSpeed, //191 SPELL_AURA_USE_NORMAL_MOVEMENT_SPEED
&AuraEffect::HandleModMeleeRangedSpeedPct, //192 SPELL_AURA_HASTE_MELEE
&AuraEffect::HandleModCombatSpeedPct, //193 SPELL_AURA_MELEE_SLOW (in fact combat (any type attack) speed pct)
@@ -721,28 +721,28 @@ void AreaAuraEffect::Update(uint32 diff)
}
}
- for(std::list<Unit *>::iterator tIter = targets.begin(); tIter != targets.end(); tIter++)
+ for(std::list<Unit*>::iterator tIter = targets.begin(); tIter != targets.end(); tIter++)
{
- bool skip=false;
- for(Unit::AuraMap::iterator iter = (*tIter)->GetAuras().begin(); iter != (*tIter)->GetAuras().end();++iter)
+ if(Aura *aur = (*tIter)->GetAura(GetId(), m_formalCasterGUID))
{
- bool samecaster = iter->second->GetCasterGUID() == GetCasterGUID();
- if (samecaster && iter->first == GetId())
+ if(aur->HasEffect(GetEffIndex()))
+ continue;
+ }
+ else
+ {
+ bool skip = false;
+ for(Unit::AuraMap::iterator iter = (*tIter)->GetAuras().begin(); iter != (*tIter)->GetAuras().end();++iter)
{
- if (AuraEffect * aurEff = iter->second->GetPartAura(m_effIndex))
+ bool samecaster = iter->second->GetCasterGUID() == m_formalCasterGUID;
+ if(spellmgr.IsNoStackSpellDueToSpell(GetId(), iter->first, samecaster))
{
- skip=true;
+ skip = true;
+ break;
}
- break;
- }
- if (spellmgr.IsNoStackSpellDueToSpell(GetId(), iter->first,samecaster))
- {
- skip=true;
- break;
}
+ if(skip)
+ continue;
}
- if(skip)
- continue;
if(SpellEntry const *actualSpellInfo = spellmgr.SelectAuraRankForPlayerLevel(GetSpellProto(), (*tIter)->getLevel()))
{
@@ -750,7 +750,7 @@ void AreaAuraEffect::Update(uint32 diff)
// recalculate basepoints for lower rank (all AreaAura spell not use custom basepoints?)
//if(actualSpellInfo != GetSpellProto())
// actualBasePoints = actualSpellInfo->EffectBasePoints[m_effIndex];
- Aura * aur = (*tIter)->AddAuraEffect(actualSpellInfo->Id, GetEffIndex(), caster, &m_currentBasePoints);
+ (*tIter)->AddAuraEffect(actualSpellInfo, GetEffIndex(), caster, &m_currentBasePoints);
if(m_areaAuraType == AREA_AURA_ENEMY)
caster->CombatStart(*tIter);
@@ -1000,7 +1000,7 @@ void Aura::_AddAura()
for(std::vector<int32>::const_iterator itr = spell_triggered->begin(); itr != spell_triggered->end(); ++itr)
{
if(*itr < 0)
- m_target->ApplySpellImmune(id, IMMUNITY_ID, -(*itr), m_target);
+ m_target->ApplySpellImmune(id, IMMUNITY_ID, -(*itr), true);
else if(Unit* caster = GetCaster())
caster->AddAura(*itr, m_target);
}
@@ -2667,25 +2667,6 @@ void AuraEffect::HandleAuraDummy(bool apply, bool Real)
}
case SPELLFAMILY_HUNTER:
{
- // Improved Aspect of the Viper
- if( GetId()==38390 && m_target->GetTypeId()==TYPEID_PLAYER )
- {
- if(apply)
- {
- // + effect value for Aspect of the Viper
- SpellModifier *mod = new SpellModifier;
- mod->op = SPELLMOD_EFFECT1;
- mod->value = m_amount;
- mod->type = SPELLMOD_FLAT;
- mod->spellId = GetId();
- mod->mask[1] = 0x40000;
-
- m_spellmod = mod;
- }
-
- ((Player*)m_target)->AddSpellMod(m_spellmod, apply);
- return;
- }
// Glyph of Aspect of the Monkey
if(m_spellProto->Id==56833)
{
@@ -3880,25 +3861,11 @@ void AuraEffect::HandleAuraModSilence(bool apply, bool Real)
if (m_target->m_currentSpells[i] && m_target->m_currentSpells[i]->m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE)
m_target->InterruptSpell(i,false); // Stop spells on prepare or casting state
+ /*
switch (GetId())
{
- // Arcane Torrent (Energy)
- case 25046:
- {
- Unit * caster = GetCaster();
- if (!caster)
- return;
-
- // Search Mana Tap auras on caster
- AuraEffect * dummy = caster->GetDummyAura(28734);
- if (dummy)
- {
- int32 bp = dummy->GetParentAura()->GetStackAmount() * 10;
- caster->CastCustomSpell(caster, 25048, &bp, NULL, NULL, true);
- m_target->RemoveAurasDueToSpell(28734);
- }
- }
}
+ */
}
else
{
@@ -5698,6 +5665,7 @@ void AuraEffect::PeriodicTick()
if(!pCaster)
return;
+ // Consecrate ticks can miss and will not show up in the combat log
if( GetSpellProto()->Effect[GetEffIndex()]==SPELL_EFFECT_PERSISTENT_AREA_AURA &&
pCaster->SpellHitResult(m_target,GetSpellProto(),false)!=SPELL_MISS_NONE)
return;
@@ -5746,7 +5714,8 @@ void AuraEffect::PeriodicTick()
}
}
m_amount = 100 * m_tickNumber;
- }break;
+ break;
+ }
default:
break;
}
@@ -5800,6 +5769,8 @@ void AuraEffect::PeriodicTick()
sLog.outDetail("PeriodicTick: %u (TypeId: %u) attacked %u (TypeId: %u) for %u dmg inflicted by %u abs is %u",
GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId(),absorb);
+ pCaster->DealDamageMods(m_target,pdamage,&absorb);
+
WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size
data.append(m_target->GetPackGUID());
data.appendPackGUID(GetCasterGUID());
@@ -5983,10 +5954,13 @@ void AuraEffect::PeriodicTick()
}
else
{
- pCaster->SendSpellNonMeleeDamageLog(pCaster, GetId(), gain, GetSpellSchoolMask(GetSpellProto()), 0, 0, false, 0, false);
+ uint32 damage = gain;
+ uint32 absorb = 0;
+ pCaster->DealDamageMods(pCaster,damage,&absorb);
+ pCaster->SendSpellNonMeleeDamageLog(pCaster, GetId(), damage, GetSpellSchoolMask(GetSpellProto()), absorb, 0, false, 0, false);
CleanDamage cleanDamage = CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL );
- pCaster->DealDamage(pCaster, gain, &cleanDamage, NODAMAGE, GetSpellSchoolMask(GetSpellProto()), GetSpellProto(), true);
+ pCaster->DealDamage(pCaster, damage, &cleanDamage, NODAMAGE, GetSpellSchoolMask(GetSpellProto()), GetSpellProto(), true);
}
}
@@ -6202,6 +6176,9 @@ void AuraEffect::PeriodicTick()
SpellNonMeleeDamage damageInfo(pCaster, m_target, spellProto->Id, spellProto->SchoolMask);
//no SpellDamageBonus for burn mana
pCaster->CalculateSpellDamageTaken(&damageInfo, gain, spellProto);
+
+ pCaster->DealDamageMods(damageInfo.target,damageInfo.damage,&damageInfo.absorb);
+
pCaster->SendSpellNonMeleeDamageLog(&damageInfo);
// Set trigger flag
@@ -6973,3 +6950,12 @@ void Aura::UnregisterSingleCastAura()
m_isSingleTargetAura = false;
}
}
+
+void AuraEffect::HandleAuraSafeFall( bool Apply, bool Real )
+{
+ // implemented in WorldSession::HandleMovementOpcodes
+
+ // only special case
+ if(Apply && Real && GetId()==32474 && m_target->GetTypeId()==TYPEID_PLAYER)
+ ((Player*)m_target)->ActivateTaxiPathTo(506,GetId());
+}
diff --git a/src/game/SpellAuras.h b/src/game/SpellAuras.h
index f0120596ce9..973272a75d2 100644
--- a/src/game/SpellAuras.h
+++ b/src/game/SpellAuras.h
@@ -217,6 +217,7 @@ class TRINITY_DLL_SPEC AuraEffect
void HandlePeriodicTriggerSpellWithValue(bool apply, bool Real);
void HandlePeriodicEnergize(bool Apply, bool Real);
void HandleAuraModResistanceExclusive(bool Apply, bool Real);
+ void HandleAuraSafeFall(bool Apply, bool Real);
void HandleAuraModPetTalentsPoints(bool Apply, bool Real);
void HandleModStealth(bool Apply, bool Real);
void HandleInvisibility(bool Apply, bool Real);
diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp
index 14b012b6f73..330b0b9027b 100644
--- a/src/game/SpellEffects.cpp
+++ b/src/game/SpellEffects.cpp
@@ -286,8 +286,7 @@ void Spell::EffectInstaKill(uint32 /*i*/)
if(m_caster==unitTarget) // prevent interrupt message
finish();
- uint32 health = unitTarget->GetHealth();
- m_caster->DealDamage(unitTarget, health, NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
+ m_caster->DealDamage(unitTarget, unitTarget->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
}
void Spell::EffectEnvirinmentalDMG(uint32 i)
@@ -652,9 +651,9 @@ void Spell::SpellDamageSchoolDmg(uint32 effect_idx)
else if(m_spellInfo->SpellFamilyFlags[1]&0x00040000)
{
// Add main hand dps * effect[2] amount
- float averange = (m_caster->GetFloatValue(UNIT_FIELD_MINDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXDAMAGE)) / 2;
+ float average = (m_caster->GetFloatValue(UNIT_FIELD_MINDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXDAMAGE)) / 2;
int32 count = m_caster->CalculateSpellDamage(m_spellInfo, 2, m_spellInfo->EffectBasePoints[2], unitTarget);
- damage += count * int32(averange * IN_MILISECONDS) / m_caster->GetAttackTime(BASE_ATTACK);
+ damage += count * int32(average * IN_MILISECONDS) / m_caster->GetAttackTime(BASE_ATTACK);
}
// Shield of Righteousness
else if(m_spellInfo->SpellFamilyFlags[1]&0x00100000)
@@ -1012,17 +1011,6 @@ void Spell::EffectDummy(uint32 i)
m_caster->CastSpell(unitTarget,29294,true);
return;
}
- case 28730: // Arcane Torrent (Mana)
- {
- Aura * dummy = m_caster->GetAura(28734, m_caster->GetGUID());
- if (dummy)
- {
- int32 bp = damage * dummy->GetStackAmount();
- m_caster->CastCustomSpell(m_caster, 28733, &bp, NULL, NULL, true);
- m_caster->RemoveAurasDueToSpell(28734);
- }
- return;
- }
case 29200: // Purify Helboar Meat
{
if( m_caster->GetTypeId() != TYPEID_PLAYER )
@@ -1324,12 +1312,7 @@ void Spell::EffectDummy(uint32 i)
(GetSpellSchoolMask(spellInfo) & SPELL_SCHOOL_MASK_FROST) &&
spellInfo->Id != 11958 && GetSpellRecoveryTime(spellInfo) > 0 )
{
- ((Player*)m_caster)->RemoveSpellCooldown(classspell);
-
- WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8));
- data << uint32(classspell);
- data << uint64(m_caster->GetGUID());
- ((Player*)m_caster)->GetSession()->SendPacket(&data);
+ ((Player*)m_caster)->RemoveSpellCooldown(classspell,true);
}
}
return;
@@ -1367,24 +1350,29 @@ void Spell::EffectDummy(uint32 i)
if(!unitTarget)
return;
- uint32 rage = m_caster->GetPower(POWER_RAGE);
+ uint32 rage=0;
// Glyph of Execution bonus
if (AuraEffect *aura = m_caster->GetDummyAura(58367))
rage+=aura->GetAmount();
spell_id = 20647;
- bp = damage+int32(rage * m_spellInfo->DmgMultiplier[i] +
- m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f);
// Sudden death cost modifier
if (Aura * aur = m_caster->GetAura(52437))
{
+ rage += m_powerCost;
m_caster->ModifyPower(POWER_RAGE,- m_powerCost);
if (m_caster->GetPower(POWER_RAGE)<100)
m_caster->SetPower(POWER_RAGE,100);
m_caster->RemoveAura(aur);
}
else
+ {
+ rage += m_caster->GetPower(POWER_RAGE);
m_caster->SetPower(POWER_RAGE,0);
+ }
+
+ bp = damage+int32(rage * m_spellInfo->DmgMultiplier[i] +
+ m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f);
break;
}
// Slam
@@ -1580,14 +1568,7 @@ void Spell::EffectDummy(uint32 i)
SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell);
if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (spellInfo->SpellFamilyFlags[1] & 0x00000240 || spellInfo->SpellFamilyFlags[0] & 0x00000860))
- {
- ((Player*)m_caster)->RemoveSpellCooldown(classspell);
-
- WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8));
- data << uint32(classspell);
- data << uint64(m_caster->GetGUID());
- ((Player*)m_caster)->GetSession()->SendPacket(&data);
- }
+ ((Player*)m_caster)->RemoveSpellCooldown(classspell,true);
}
return;
}
@@ -1614,14 +1595,7 @@ void Spell::EffectDummy(uint32 i)
SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell);
if (spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER && spellInfo->Id != 23989 && GetSpellRecoveryTime(spellInfo) > 0 )
- {
- ((Player*)m_caster)->RemoveSpellCooldown(classspell);
-
- WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8));
- data << uint32(classspell);
- data << uint64(m_caster->GetGUID());
- ((Player*)m_caster)->GetSession()->SendPacket(&data);
- }
+ ((Player*)m_caster)->RemoveSpellCooldown(classspell,true);
}
return;
}
@@ -1716,17 +1690,8 @@ void Spell::EffectDummy(uint32 i)
// non-standard cast requirement check
if (!unitTarget || unitTarget->getAttackers().empty())
{
- // clear cooldown at fail
if(m_caster->GetTypeId()==TYPEID_PLAYER)
- {
- ((Player*)m_caster)->RemoveSpellCooldown(m_spellInfo->Id);
-
- WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8));
- data << uint32(m_spellInfo->Id);
- data << uint64(m_caster->GetGUID());
- ((Player*)m_caster)->GetSession()->SendPacket(&data);
- }
-
+ ((Player*)m_caster)->RemoveSpellCooldown(m_spellInfo->Id,true);
SendCastResult(SPELL_FAILED_TARGET_AFFECTING_COMBAT);
return;
}
@@ -3230,7 +3195,7 @@ void Spell::EffectSummonType(uint32 i)
modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_DURATION, duration);
float x, y, z;
- GetSummonPosition(x, y, z);
+ GetSummonPosition(i, x, y, z);
/*//totem must be at same Z in case swimming caster and etc.
if( fabs( z - m_caster->GetPositionZ() ) > 5 )
@@ -3315,7 +3280,7 @@ void Spell::EffectSummonType(uint32 i)
summon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
- summon->GetMotionMaster()->MoveTargetedHome();
+ summon->AI()->EnterEvadeMode();
std::string name = m_originalCaster->GetName();
name.append(petTypeSuffix[3]);
@@ -3331,7 +3296,7 @@ void Spell::EffectSummonType(uint32 i)
for(int32 count = 0; count < amount; ++count)
{
float px, py, pz;
- GetSummonPosition(px, py, pz, radius, count);
+ GetSummonPosition(i, px, py, pz, radius, count);
TempSummonType summonType = (duration == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_DESPAWN;
@@ -4776,17 +4741,17 @@ void Spell::EffectScriptEffect(uint32 effIndex)
unitTarget->CastSpell(unitTarget, 44870, true);
break;
}
- // spell of Brutallus - Stomp
- case 45185:
- {
- if(!unitTarget)
- return;
-
- if(unitTarget->HasAura(46394)) // spell of Brutallus - Burn
- unitTarget->RemoveAurasDueToSpell(46394);
+ // spell of Brutallus - Stomp
+ case 45185:
+ {
+ if(!unitTarget)
+ return;
- break;
- }
+ if(unitTarget->HasAura(46394)) // spell of Brutallus - Burn
+ unitTarget->RemoveAurasDueToSpell(46394);
+
+ break;
+ }
// Negative Energy
case 46289:
{
@@ -5891,47 +5856,7 @@ void Spell::EffectSendTaxi(uint32 i)
if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
return;
- TaxiPathEntry const* entry = sTaxiPathStore.LookupEntry(m_spellInfo->EffectMiscValue[i]);
- if(!entry)
- return;
-
- std::vector<uint32> nodes;
-
- nodes.resize(2);
- nodes[0] = entry->from;
- nodes[1] = entry->to;
-
- uint32 mountid = 0;
- switch(m_spellInfo->Id)
- {
- case 31606: //Stormcrow Amulet
- mountid = 17447;
- break;
- case 45071: //Quest - Sunwell Daily - Dead Scar Bombing Run
- case 45113: //Quest - Sunwell Daily - Ship Bombing Run
- case 45353: //Quest - Sunwell Daily - Ship Bombing Run Return
- mountid = 22840;
- break;
- case 34905: //Stealth Flight
- mountid = 6851;
- break;
- case 45883: //Amber Ledge to Beryl Point
- mountid = 23524;
- break;
- case 46064: //Amber Ledge to Coldarra
- mountid = 6371;
- break;
- case 53335: //Stormwind Harbor Flight - Peaceful
- mountid = 6852;
- break;
- case 41533: //Fly of the Netherwing
- case 41540: //Fly of the Netherwing
- mountid = 23468;
- break;
- }
-
- ((Player*)unitTarget)->ActivateTaxiPathTo(nodes,mountid);
-
+ ((Player*)unitTarget)->ActivateTaxiPathTo(m_spellInfo->EffectMiscValue[i],m_spellInfo->Id);
}
void Spell::EffectPlayerPull(uint32 i)
@@ -6292,7 +6217,7 @@ void Spell::EffectSummonDemon(uint32 i)
for(int32 count = 0; count < amount; ++count)
{
float px, py, pz;
- GetSummonPosition(px, py, pz, radius, count);
+ GetSummonPosition(i, px, py, pz, radius, count);
int32 duration = GetSpellDuration(m_spellInfo);
@@ -6492,7 +6417,7 @@ void Spell::SummonGuardian(uint32 entry, SummonPropertiesEntry const *properties
for(int32 count = 0; count < amount; ++count)
{
float px, py, pz;
- GetSummonPosition(px, py, pz, radius, count);
+ GetSummonPosition(0, px, py, pz, radius, count);
TempSummon *summon = map->SummonCreature(entry, px, py, pz, m_caster->GetOrientation(), properties, duration, caster);
if(!summon)
@@ -6503,11 +6428,11 @@ void Spell::SummonGuardian(uint32 entry, SummonPropertiesEntry const *properties
summon->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
- summon->GetMotionMaster()->MoveTargetedHome();
+ summon->AI()->EnterEvadeMode();
}
}
-void Spell::GetSummonPosition(float &x, float &y, float &z, float radius, uint32 count)
+void Spell::GetSummonPosition(uint32 i, float &x, float &y, float &z, float radius, uint32 count)
{
if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
{
@@ -6520,7 +6445,25 @@ void Spell::GetSummonPosition(float &x, float &y, float &z, float radius, uint32
}
// Summon in random point all other units if location present
else
- m_caster->GetRandomPoint(m_targets.m_destX,m_targets.m_destY,m_targets.m_destZ,radius,x,y,z);
+ {
+ //This is a workaround. Do not have time to write much about it
+ switch(m_spellInfo->EffectImplicitTargetA[i])
+ {
+ case TARGET_MINION:
+ case TARGET_DEST_CASTER_RANDOM:
+ m_caster->GetGroundPointAroundUnit(x, y, z, radius * rand_norm(), rand_norm()*2*M_PI);
+ break;
+ case TARGET_DEST_DEST_RANDOM:
+ case TARGET_DEST_TARGET_RANDOM:
+ m_caster->GetRandomPoint(m_targets.m_destX,m_targets.m_destY,m_targets.m_destZ,radius,x,y,z);
+ break;
+ default:
+ x = m_targets.m_destX;
+ y = m_targets.m_destY;
+ z = m_targets.m_destZ;
+ break;
+ }
+ }
}
// Summon if dest location not present near caster
else
@@ -6534,4 +6477,4 @@ void Spell::EffectRenamePet(uint32 /*eff_idx*/)
return;
unitTarget->SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_ALLOWED);
-}
+} \ No newline at end of file
diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp
index 945255f883a..4e5a4744e9a 100644
--- a/src/game/SpellMgr.cpp
+++ b/src/game/SpellMgr.cpp
@@ -27,6 +27,7 @@
#include "Chat.h"
#include "Spell.h"
#include "BattleGroundMgr.h"
+#include "CreatureAI.h"
bool IsAreaEffectTarget[TOTAL_SPELL_TARGETS];
@@ -1472,6 +1473,10 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2, bool
//if spells have exactly the same effect they cannot stack
for(uint32 i = 0; i < 3; ++i)
if(spellInfo_1->Effect[i] != spellInfo_2->Effect[i]
+ // Overkill and master of subtlety need this
+ || spellInfo_1->EffectApplyAuraName[i] == SPELL_AURA_DUMMY
+ || spellInfo_1->EffectApplyAuraName[i] == SPELL_AURA_PERIODIC_DUMMY
+
|| spellInfo_1->EffectApplyAuraName[i] != spellInfo_2->EffectApplyAuraName[i]
|| spellInfo_1->EffectMiscValue[i] != spellInfo_2->EffectMiscValue[i]) // paladin resist aura
return false; // need itemtype check? need an example to add that check
@@ -2426,31 +2431,32 @@ void SpellMgr::LoadSpellCustomAttr()
case 45976: // Muru Portal Channel
case 39365: // Thundering Storm
case 41071: // Raise Dead (HACK)
- case 28542: // Life Drain - Sapphiron
spellInfo->MaxAffectedTargets = 1;
break;
case 41376: // Spite
case 39992: // Needle Spine
- case 29576: //Multi-Shot
- case 40816: //Saber Lash
- case 37790: //Spread Shot
- case 46771: //Flame Sear
- case 45248: //Shadow Blades
+ case 29576: // Multi-Shot
+ case 40816: // Saber Lash
+ case 37790: // Spread Shot
+ case 46771: // Flame Sear
+ case 45248: // Shadow Blades
case 41303: // Soul Drain
case 54172: // Divine Storm (heal)
- case 29213: // Curse of the Plaguebringer
+ case 29213: // Curse of the Plaguebringer - Noth
+ case 28542: // Life Drain - Sapphiron
spellInfo->MaxAffectedTargets = 3;
break;
case 38310: //Multi-Shot
spellInfo->MaxAffectedTargets = 4;
break;
case 42005: // Bloodboil
- case 38296: //Spitfire Totem
- case 37676: //Insidious Whisper
- case 46009: //Negative Energy
- case 45641: //Fire Bloom
- case 54937: //Glyph of Holy Light
- case 55665: // Life Drain - Sapphiron
+ case 38296: // Spitfire Totem
+ case 37676: // Insidious Whisper
+ case 46009: // Negative Energy
+ case 45641: // Fire Bloom
+ case 54937: // Glyph of Holy Light
+ case 55665: // Life Drain - Sapphiron (H)
+ case 28796: // Poison Bolt Volly - Faerlina
spellInfo->MaxAffectedTargets = 5;
break;
case 40827: // Sinful Beam
@@ -2458,7 +2464,8 @@ void SpellMgr::LoadSpellCustomAttr()
case 40860: // Vile Beam
case 40861: // Wicked Beam
case 57669: // Replenishment
- case 54835: // Curse of the Plaguebringer
+ case 54835: // Curse of the Plaguebringer - Noth (H)
+ case 54098: // Poison Bolt Volly - Faerlina (H)
spellInfo->MaxAffectedTargets = 10;
break;
case 8122: case 8124: case 10888: case 10890: // Psychic Scream
@@ -2516,6 +2523,8 @@ void SpellMgr::LoadSpellCustomAttr()
SummonPropertiesEntry *properties = const_cast<SummonPropertiesEntry*>(sSummonPropertiesStore.LookupEntry(121));
properties->Type = SUMMON_TYPE_TOTEM;
+
+ CreatureAI::FillAISpellInfo();
}
void SpellMgr::LoadSpellLinked()
diff --git a/src/game/TaxiHandler.cpp b/src/game/TaxiHandler.cpp
index 24c6aca147a..5ba65c00660 100644
--- a/src/game/TaxiHandler.cpp
+++ b/src/game/TaxiHandler.cpp
@@ -128,7 +128,8 @@ void WorldSession::SendDoFlight( uint16 MountId, uint32 path, uint32 pathNode )
while(GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType()==FLIGHT_MOTION_TYPE)
GetPlayer()->GetMotionMaster()->MovementExpired(false);
- GetPlayer()->Mount( MountId );
+ if (MountId)
+ GetPlayer()->Mount( MountId );
GetPlayer()->GetMotionMaster()->MoveTaxiFlight(path,pathNode);
}
@@ -190,7 +191,7 @@ void WorldSession::HandleActivateTaxiFarOpcode ( WorldPacket & recv_data )
sLog.outDebug( "WORLD: Received CMSG_ACTIVATETAXIEXPRESS from %d to %d" ,nodes.front(),nodes.back());
- GetPlayer()->ActivateTaxiPathTo(nodes, 0, npc);
+ GetPlayer()->ActivateTaxiPathTo(nodes, npc);
}
void WorldSession::HandleTaxiNextDestinationOpcode(WorldPacket& /*recv_data*/)
@@ -275,6 +276,6 @@ void WorldSession::HandleActivateTaxiOpcode( WorldPacket & recv_data )
return;
}
- GetPlayer()->ActivateTaxiPathTo(nodes, 0, npc);
+ GetPlayer()->ActivateTaxiPathTo(nodes, npc);
}
diff --git a/src/game/TemporarySummon.cpp b/src/game/TemporarySummon.cpp
index 170e590fd9c..993ece988a0 100644
--- a/src/game/TemporarySummon.cpp
+++ b/src/game/TemporarySummon.cpp
@@ -208,10 +208,8 @@ void TempSummon::InitSummon()
if(GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_TRIGGER && m_spells[0])
{
setFaction(owner->getFaction());
- if(m_spells[1] && GetMap()->IsHeroic())
- CastSpell(this, m_spells[1], false, 0, 0, m_summonerGUID);
- else
- CastSpell(this, m_spells[0], false, 0, 0, m_summonerGUID);
+ SetLevel(owner->getLevel());
+ CastSpell(this, m_spells[0], false, 0, 0, m_summonerGUID);
}
}
}
@@ -309,6 +307,8 @@ void Guardian::InitStats(uint32 duration)
{
Minion::InitStats(duration);
+ InitStatsForLevel(m_owner->getLevel());
+
if(m_owner->GetTypeId() == TYPEID_PLAYER)
m_charmInfo->InitCharmCreateSpells();
diff --git a/src/game/TemporarySummon.h b/src/game/TemporarySummon.h
index 09e7f22afb0..e089c77c96e 100644
--- a/src/game/TemporarySummon.h
+++ b/src/game/TemporarySummon.h
@@ -23,7 +23,7 @@
#include "Creature.h"
-class TempSummon : public Creature
+class TRINITY_DLL_SPEC TempSummon : public Creature
{
public:
explicit TempSummon(SummonPropertiesEntry const *properties, Unit *owner);
diff --git a/src/game/TradeHandler.cpp b/src/game/TradeHandler.cpp
index 439626861fd..3cead4551c1 100644
--- a/src/game/TradeHandler.cpp
+++ b/src/game/TradeHandler.cpp
@@ -461,30 +461,30 @@ void WorldSession::HandleInitiateTradeOpcode(WorldPacket& recvPacket)
{
CHECK_PACKET_SIZE(recvPacket,8);
- if( GetPlayer()->pTrader )
+ if (GetPlayer()->pTrader)
return;
uint64 ID;
- if( !GetPlayer()->isAlive() )
+ if (!GetPlayer()->isAlive())
{
SendTradeStatus(TRADE_STATUS_YOU_DEAD);
return;
}
- if( GetPlayer()->hasUnitState(UNIT_STAT_STUNNED) )
+ if (GetPlayer()->hasUnitState(UNIT_STAT_STUNNED))
{
SendTradeStatus(TRADE_STATUS_YOU_STUNNED);
return;
}
- if( isLogingOut() )
+ if (isLogingOut())
{
SendTradeStatus(TRADE_STATUS_YOU_LOGOUT);
return;
}
- if( GetPlayer()->isInFlight() )
+ if (GetPlayer()->isInFlight())
{
SendTradeStatus(TRADE_STATUS_TARGET_TO_FAR);
return;
@@ -494,43 +494,43 @@ void WorldSession::HandleInitiateTradeOpcode(WorldPacket& recvPacket)
Player* pOther = ObjectAccessor::FindPlayer( ID );
- if( !pOther )
+ if (!pOther)
{
SendTradeStatus(TRADE_STATUS_NO_TARGET);
return;
}
- if( pOther == GetPlayer() || pOther->pTrader )
+ if (pOther == GetPlayer() || pOther->pTrader)
{
SendTradeStatus(TRADE_STATUS_BUSY);
return;
}
- if( !pOther->isAlive() )
+ if (!pOther->isAlive())
{
SendTradeStatus(TRADE_STATUS_TARGET_DEAD);
return;
}
- if( pOther->isInFlight() )
+ if (pOther->isInFlight())
{
SendTradeStatus(TRADE_STATUS_TARGET_TO_FAR);
return;
}
- if( pOther->hasUnitState(UNIT_STAT_STUNNED) )
+ if (pOther->hasUnitState(UNIT_STAT_STUNNED))
{
SendTradeStatus(TRADE_STATUS_TARGET_STUNNED);
return;
}
- if( pOther->GetSession()->isLogingOut() )
+ if (pOther->GetSession()->isLogingOut())
{
SendTradeStatus(TRADE_STATUS_TARGET_LOGOUT);
return;
}
- if( pOther->GetSocial()->HasIgnore(GetPlayer()->GetGUIDLow()) )
+ if (pOther->GetSocial()->HasIgnore(GetPlayer()->GetGUIDLow()))
{
SendTradeStatus(TRADE_STATUS_IGNORE_YOU);
return;
@@ -542,7 +542,7 @@ void WorldSession::HandleInitiateTradeOpcode(WorldPacket& recvPacket)
return;
}
- if( pOther->GetDistance2d( _player ) > 10.0f )
+ if (!pOther->IsWithinDistInMap(_player,10.0f,false))
{
SendTradeStatus(TRADE_STATUS_TARGET_TO_FAR);
return;
diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp
index bb2f8e98f4b..e36c25883d4 100644
--- a/src/game/Unit.cpp
+++ b/src/game/Unit.cpp
@@ -413,7 +413,7 @@ void Unit::resetAttackTimer(WeaponAttackType type)
m_attackTimer[type] = uint32(GetAttackTime(type) * m_modAttackSpeedPct[type]);
}
-bool Unit::IsWithinCombatRange(Unit *obj, float dist2compare) const
+bool Unit::IsWithinCombatRange(const Unit *obj, float dist2compare) const
{
if (!obj || !IsInMap(obj)) return false;
@@ -428,7 +428,7 @@ bool Unit::IsWithinCombatRange(Unit *obj, float dist2compare) const
return distsq < maxdist * maxdist;
}
-bool Unit::IsWithinMeleeRange(Unit *obj, float dist) const
+bool Unit::IsWithinMeleeRange(const Unit *obj, float dist) const
{
if (!obj || !IsInMap(obj)) return false;
@@ -535,10 +535,15 @@ void Unit::RemoveSpellbyDamageTaken(uint32 damage, uint32 spell)
}
}
-uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDamage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask, SpellEntry const *spellProto, bool durabilityLoss)
+void Unit::DealDamageMods(Unit *pVictim, uint32 &damage, uint32* absorb)
{
if (!pVictim->isAlive() || pVictim->hasUnitState(UNIT_STAT_UNATTACKABLE) || pVictim->GetTypeId() == TYPEID_UNIT && ((Creature*)pVictim)->IsInEvadeMode())
- return 0;
+ {
+ if(absorb)
+ absorb += damage;
+ damage = 0;
+ return;
+ }
//You don't lose health from damage taken from another player while in a sanctuary
//You still see it in the combat log though
@@ -546,14 +551,30 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa
{
const AreaTableEntry *area = GetAreaEntryByAreaID(pVictim->GetAreaId());
if(area && area->flags & AREA_FLAG_SANCTUARY) //sanctuary
- return 0;
+ {
+ if(absorb)
+ absorb += damage;
+ damage = 0;
+ }
}
+ uint32 originalDamage = damage;
+
+ //Script Event damage Deal
+ //if( GetTypeId()== TYPEID_UNIT && ((Creature *)this)->AI())
+ // ((Creature *)this)->AI()->DamageDeal(pVictim, damage);
//Script Event damage taken
if( pVictim->GetTypeId()== TYPEID_UNIT && ((Creature *)pVictim)->IsAIEnabled )
- {
((Creature *)pVictim)->AI()->DamageTaken(this, damage);
+ if(absorb && originalDamage > damage)
+ absorb += (originalDamage - damage);
+}
+
+uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDamage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask, SpellEntry const *spellProto, bool durabilityLoss)
+{
+ if( pVictim->GetTypeId()== TYPEID_UNIT)
+ {
// Set tagging
if(!pVictim->HasFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_OTHER_TAGGER) && !((Creature*)pVictim)->isPet())
{
@@ -1203,6 +1224,7 @@ uint32 Unit::SpellNonMeleeDamageLog(Unit *pVictim, uint32 spellID, uint32 damage
SpellNonMeleeDamage damageInfo(this, pVictim, spellInfo->Id, spellInfo->SchoolMask);
damage = SpellDamageBonus(pVictim, spellInfo, damage, SPELL_DIRECT_DAMAGE);
CalculateSpellDamageTaken(&damageInfo, damage, spellInfo);
+ DealDamageMods(damageInfo.target,damageInfo.damage,&damageInfo.absorb);
SendSpellNonMeleeDamageLog(&damageInfo);
DealSpellDamage(&damageInfo, true);
return damageInfo.damage;
@@ -1706,6 +1728,8 @@ void Unit::DealMeleeDamage(CalcDamageInfo *damageInfo, bool durabilityLoss)
//CalcAbsorbResist(pVictim, SpellSchools(spellProto->School), SPELL_DIRECT_DAMAGE, damage, &absorb, &resist);
//damage-=absorb + resist;
+ pVictim->DealDamageMods(this,damage,NULL);
+
WorldPacket data(SMSG_SPELLDAMAGESHIELD,(8+8+4+4+4+4));
data << uint64(pVictim->GetGUID());
data << uint64(GetGUID());
@@ -2085,8 +2109,12 @@ void Unit::CalcAbsorbResist(Unit *pVictim,SpellSchoolMask schoolMask, DamageEffe
int32 canabsorb = caster->GetHealth();
if (canabsorb < absorbed)
absorbed = canabsorb;
- DealDamage(caster, absorbed, NULL, damagetype, schoolMask, 0, false);
+
RemainingDamage -= absorbed;
+
+ uint32 ab_damage = absorbed;
+ DealDamageMods(caster,ab_damage,NULL);
+ DealDamage(caster, ab_damage, NULL, damagetype, schoolMask, 0, false);
continue;
}
break;
@@ -2195,10 +2223,15 @@ void Unit::CalcAbsorbResist(Unit *pVictim,SpellSchoolMask schoolMask, DamageEffe
RemainingDamage -= currentAbsorb;
- SendSpellNonMeleeDamageLog(caster, (*i)->GetSpellProto()->Id, currentAbsorb, schoolMask, 0, 0, false, 0, false);
- CleanDamage cleanDamage = CleanDamage(currentAbsorb, BASE_ATTACK, MELEE_HIT_NORMAL);
- DealDamage(caster, currentAbsorb, &cleanDamage, DIRECT_DAMAGE, schoolMask, (*i)->GetSpellProto(), false);
+ uint32 splitted = currentAbsorb;
+ uint32 splitted_absorb = 0;
+ DealDamageMods(caster,splitted,&splitted_absorb);
+
+ SendSpellNonMeleeDamageLog(caster, (*i)->GetSpellProto()->Id, splitted, schoolMask, splitted_absorb, 0, false, 0, false);
+
+ CleanDamage cleanDamage = CleanDamage(splitted, BASE_ATTACK, MELEE_HIT_NORMAL);
+ DealDamage(caster, splitted, &cleanDamage, DIRECT_DAMAGE, schoolMask, (*i)->GetSpellProto(), false);
}
AuraEffectList const& vSplitDamagePct = pVictim->GetAurasByType(SPELL_AURA_SPLIT_DAMAGE_PCT);
@@ -2215,11 +2248,14 @@ void Unit::CalcAbsorbResist(Unit *pVictim,SpellSchoolMask schoolMask, DamageEffe
if(!caster || caster == pVictim || !caster->IsInWorld() || !caster->isAlive())
continue;
- int32 splitted = int32(RemainingDamage * (*i)->GetAmount() / 100.0f);
+ uint32 splitted = uint32(RemainingDamage * (*i)->GetAmount() / 100.0f);
- RemainingDamage -= splitted;
+ RemainingDamage -= int32(splitted);
- SendSpellNonMeleeDamageLog(caster, (*i)->GetSpellProto()->Id, splitted, schoolMask, 0, 0, false, 0, false);
+ uint32 split_absorb = 0;
+ DealDamageMods(caster,splitted,&split_absorb);
+
+ SendSpellNonMeleeDamageLog(caster, (*i)->GetSpellProto()->Id, splitted, schoolMask, split_absorb, 0, false, 0, false);
CleanDamage cleanDamage = CleanDamage(splitted, BASE_ATTACK, MELEE_HIT_NORMAL);
DealDamage(caster, splitted, &cleanDamage, DIRECT_DAMAGE, schoolMask, (*i)->GetSpellProto(), false);
@@ -2354,6 +2390,7 @@ void Unit::AttackerStateUpdate (Unit *pVictim, WeaponAttackType attType, bool ex
CalcDamageInfo damageInfo;
CalculateMeleeDamage(pVictim, 0, &damageInfo, attType);
// Send log damage message to client
+ DealDamageMods(pVictim,damageInfo.damage,&damageInfo.absorb);
SendAttackStateUpdate(&damageInfo);
ProcDamageAndSpell(damageInfo.target, damageInfo.procAttacker, damageInfo.procVictim, damageInfo.procEx, damageInfo.damage, damageInfo.attackType);
DealMeleeDamage(&damageInfo,true);
@@ -2775,7 +2812,9 @@ SpellMissInfo Unit::MeleeSpellHitResult(Unit *pVictim, SpellEntry const *spell)
return SPELL_MISS_NONE;
// Ranged attack cannot be parry/dodge only deflect
- if (attType == RANGED_ATTACK)
+ // Check damage class instead of attack type to correctly handle judgements
+ // - they are meele, but can't be dodged/parried/deflected because of ranged dmg class
+ if (spell->DmgClass == SPELL_DAMAGE_CLASS_RANGED)
{
// only if in front
if (pVictim->HasInArc(M_PI,this))
@@ -3526,7 +3565,7 @@ Spell* Unit::FindCurrentSpellBySpellId(uint32 spell_id) const
return NULL;
}
-bool Unit::isInFront(Unit const* target, float distance, float arc) const
+bool Unit::isInFrontInMap(Unit const* target, float distance, float arc) const
{
return IsWithinDistInMap(target, distance) && HasInArc( arc, target );
}
@@ -3536,7 +3575,7 @@ void Unit::SetInFront(Unit const* target)
SetOrientation(GetAngle(target));
}
-bool Unit::isInBack(Unit const* target, float distance, float arc) const
+bool Unit::isInBackInMap(Unit const* target, float distance, float arc) const
{
return IsWithinDistInMap(target, distance) && !HasInArc( 2 * M_PI - arc, target );
}
@@ -4272,7 +4311,7 @@ bool Unit::HasAura(Aura * aur) const
bool Unit::HasAuraEffect(uint32 spellId, uint8 effIndex, uint64 caster) const
{
if (Aura * aur = GetAura(spellId, caster))
- return bool(aur->HasEffect(effIndex));
+ return aur->HasEffect(effIndex);
return false;
}
@@ -4486,38 +4525,32 @@ void Unit::SendSpellNonMeleeDamageLog(SpellNonMeleeDamage *log)
data.append(log->target->GetPackGUID());
data.append(log->attacker->GetPackGUID());
data << uint32(log->SpellID);
- data << uint32(log->damage); //damage amount
+ data << uint32(log->damage); // damage amount
data << uint32(int32 (log->target->GetHealth()-log->damage ) >0 ? 0 : log->damage - log->target->GetHealth());
- data << uint8 (log->schoolMask); //damage school
- data << uint32(log->absorb); //AbsorbedDamage
- data << uint32(log->resist); //resist
- data << uint8 (log->phusicalLog); // damsge type? flag
- data << uint8 (log->unused); //unused
- data << uint32(log->blocked); //blocked
+ //data << uint32(log->overkill); // overkill
+ data << uint8 (log->schoolMask); // damage school
+ data << uint32(log->absorb); // AbsorbedDamage
+ data << uint32(log->resist); // resist
+ data << uint8 (log->physicalLog); // if 1, then client show spell name (example: %s's ranged shot hit %s for %u school or %s suffers %u school damage from %s's spell_name
+ data << uint8 (log->unused); // unused
+ data << uint32(log->blocked); // blocked
data << uint32(log->HitInfo);
- data << uint8 (0); // flag to use extend data
+ data << uint8 (0); // flag to use extend data
SendMessageToSet( &data, true );
}
void Unit::SendSpellNonMeleeDamageLog(Unit *target,uint32 SpellID,uint32 Damage, SpellSchoolMask damageSchoolMask,uint32 AbsorbedDamage, uint32 Resist,bool PhysicalDamage, uint32 Blocked, bool CriticalHit)
{
- sLog.outDebug("Sending: SMSG_SPELLNONMELEEDAMAGELOG");
- WorldPacket data(SMSG_SPELLNONMELEEDAMAGELOG, (16+4+4+1+4+4+1+1+4+4+1)); // we guess size
- data.append(target->GetPackGUID());
- data.append(GetPackGUID());
- data << uint32(SpellID);
- int32 damageDone = Damage-AbsorbedDamage-Resist-Blocked;
- data << uint32(damageDone);
- data << uint32(int32 (target->GetHealth()-damageDone ) >0 ? 0 : damageDone - target->GetHealth());// wotlk
- data << uint8(damageSchoolMask); // spell school
- data << uint32(AbsorbedDamage); // AbsorbedDamage
- data << uint32(Resist); // resist
- data << uint8(PhysicalDamage); // if 1, then client show spell name (example: %s's ranged shot hit %s for %u school or %s suffers %u school damage from %s's spell_name
- data << uint8(0); // unk isFromAura
- data << uint32(Blocked); // blocked
- data << uint32(CriticalHit ? 0x27 : 0x25); // hitType, flags: 0x2 - SPELL_HIT_TYPE_CRIT, 0x10 - replace caster?
- data << uint8(0); // isDebug?
- SendMessageToSet( &data, true );
+ SpellNonMeleeDamage log(this,target,SpellID,damageSchoolMask);
+ log.damage = Damage-AbsorbedDamage-Resist-Blocked;
+ log.absorb = AbsorbedDamage;
+ log.resist = Resist;
+ log.physicalLog = PhysicalDamage;
+ log.blocked = Blocked;
+ log.HitInfo = SPELL_HIT_TYPE_UNK1 | SPELL_HIT_TYPE_UNK3 | SPELL_HIT_TYPE_UNK6;
+ if(CriticalHit)
+ log.HitInfo |= SPELL_HIT_TYPE_CRIT;
+ SendSpellNonMeleeDamageLog(&log);
}
void Unit::ProcDamageAndSpell(Unit *pVictim, uint32 procAttacker, uint32 procVictim, uint32 procExtra, uint32 amount, WeaponAttackType attType, SpellEntry const *procSpell)
@@ -5301,6 +5334,25 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
CastSpell(this, 28682, true, castItem, triggeredByAura);
return (procEx & PROC_EX_CRITICAL_HIT);// charge update only at crit hits, no hidden cooldowns
}
+ // Glyph of Ice Block
+ case 56372:
+ {
+ if(GetTypeId() != TYPEID_PLAYER)
+ return false;
+
+ SpellCooldowns SpellCDs = ((Player*)this)->GetSpellCooldowns();
+ // remove cooldowns on all ranks of Frost Nova
+ for(SpellCooldowns::const_iterator itr = SpellCDs.begin(); itr != SpellCDs.end(); itr++)
+ {
+ SpellEntry const* SpellCDs_entry = sSpellStore.LookupEntry(itr->first);
+ // Frost Nova
+ if(SpellCDs_entry && SpellCDs_entry->SpellFamilyName == SPELLFAMILY_MAGE && SpellCDs_entry->SpellFamilyFlags[0] & 0x00000040)
+ {
+ ((Player*)this)->RemoveSpellCooldown(SpellCDs_entry->Id, true);
+ }
+ }
+ break;
+ }
}
break;
}
@@ -5579,6 +5631,31 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
triggered_spell_id = 56160;
break;
}
+ // Glyph of Prayer of Healing
+ case 55680:
+ {
+ triggered_spell_id = 56161;
+
+ SpellEntry const* GoPoH = sSpellStore.LookupEntry(triggered_spell_id);
+ if(!GoPoH)
+ return false;
+
+ int EffIndex = 0;
+ for(int i = 0; i < MAX_SPELL_EFFECTS; i++)
+ {
+ if(GoPoH->Effect[i] == SPELL_EFFECT_APPLY_AURA)
+ {
+ EffIndex = i;
+ break;
+ }
+ }
+ int32 tickcount = GetSpellMaxDuration(GoPoH) / GoPoH->EffectAmplitude[EffIndex];
+ if(!tickcount)
+ return false;
+
+ basepoints0 = damage * triggerAmount / tickcount / 100;
+ break;
+ }
// Improved Shadowform
case 47570:
case 47569:
@@ -6750,6 +6827,9 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, AuraEffect* trig
// Set trigger spell id, target, custom basepoints
uint32 trigger_spell_id = auraSpellInfo->EffectTriggerSpell[triggeredByAura->GetEffIndex()];
+ if(procSpell && procSpell->Id == trigger_spell_id)
+ return false;
+
Unit* target = NULL;
int32 basepoints0 = 0;
@@ -9918,7 +9998,7 @@ void Unit::SetInCombatState(bool PvP, Unit* enemy)
((Creature*)this)->SetHomePosition(GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation());
if(enemy)
{
- if(!((Creature*)this)->HasReactState(REACT_PASSIVE) && ((Creature*)this)->IsAIEnabled)
+ if(((Creature*)this)->IsAIEnabled)
((Creature*)this)->AI()->EnterCombat(enemy);
if(((Creature*)this)->GetFormation())
((Creature*)this)->GetFormation()->MemberAttackStart((Creature*)this, enemy);
@@ -11579,11 +11659,14 @@ void CharmInfo::InitPossessCreateSpells()
{
for(uint32 i = 0; i < CREATURE_MAX_SPELLS; ++i)
{
- uint32 spellid = ((Creature*)m_unit)->m_spells[i];
- if(IsPassiveSpell(spellid))
- m_unit->CastSpell(m_unit, spellid, true);
+ uint32 spellId = ((Creature*)m_unit)->m_spells[i];
+ SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId);
+ if(spellInfo && spellInfo->Attributes & SPELL_ATTR_CASTABLE_WHILE_DEAD)
+ spellId = 0;
+ if(IsPassiveSpell(spellId))
+ m_unit->CastSpell(m_unit, spellId, true);
else
- AddSpellToAB(0, spellid, ACT_DISABLED);
+ AddSpellToAB(0, spellId, ACT_DISABLED);
}
}
}
@@ -11601,6 +11684,10 @@ void CharmInfo::InitCharmCreateSpells()
for(uint32 x = 0; x < MAX_SPELL_CHARM; ++x)
{
uint32 spellId = ((Creature*)m_unit)->m_spells[x];
+ SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId);
+ if(spellInfo && spellInfo->Attributes & SPELL_ATTR_CASTABLE_WHILE_DEAD)
+ spellId = 0;
+
m_charmspells[x].spellId = spellId;
if(!spellId)
@@ -11615,7 +11702,6 @@ void CharmInfo::InitCharmCreateSpells()
{
ActiveStates newstate;
bool onlyselfcast = true;
- SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId);
if(!spellInfo) onlyselfcast = false;
for(uint32 i = 0;i<3 && onlyselfcast;++i) //non existent spell will not make any problems as onlyselfcast would be false -> break right away
@@ -11925,6 +12011,7 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag
SpellNonMeleeDamage damageInfo(this, pTarget, spellInfo->Id, spellInfo->SchoolMask);
uint32 damage = SpellDamageBonus(pTarget, spellInfo, triggeredByAura->GetAmount(), SPELL_DIRECT_DAMAGE);
CalculateSpellDamageTaken(&damageInfo, damage, spellInfo);
+ DealDamageMods(damageInfo.target,damageInfo.damage,&damageInfo.absorb);
SendSpellNonMeleeDamageLog(&damageInfo);
DealSpellDamage(&damageInfo, true);
break;
@@ -12166,6 +12253,13 @@ void Unit::StopMoving()
SendMessageToSet(&data,false);
}
+void Unit::SendMovementFlagUpdate()
+{
+ WorldPacket data;
+ BuildHeartBeatMsg(&data);
+ SendMessageToSet(&data, false);
+}
+
/*
void Unit::SetFeared(bool apply, uint64 casterGUID, uint32 spellID)
{
@@ -13574,16 +13668,14 @@ void Unit::AddAura(uint32 spellId, Unit* target)
target->AddAura(Aur);
}
-Aura * Unit::AddAuraEffect(uint32 spellId, uint8 effIndex, Unit* caster, int32 * basePoints)
+Aura * Unit::AddAuraEffect(const SpellEntry * spellInfo, uint8 effIndex, Unit* caster, int32 * basePoints)
{
- SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId);
- if(!spellInfo || !caster)
- return NULL;
-
// can't do that for passive auras - they stack from same caster so there is no way to get exact aura which should get effect
//assert (!IsPassiveSpell(spellInfo));
- Aura * aur = GetAura(spellId, caster->GetGUID());
+ sLog.outDebug("AddAuraEffect: spell id: %u, effect index: %u", spellInfo->Id, (uint32)effIndex);
+
+ Aura *aur = GetAura(spellInfo->Id, caster->GetGUID());
if (aur)
{
@@ -13600,10 +13692,10 @@ Aura * Unit::AddAuraEffect(uint32 spellId, uint8 effIndex, Unit* caster, int32 *
aur = new Aura(spellInfo, 1<<effIndex, amount, this ,caster);
}
else
- {
aur = new Aura(spellInfo, 1<<effIndex, NULL, this ,caster);
- }
- AddAura(aur);
+
+ if(!AddAura(aur))
+ return NULL;
}
return aur;
}
@@ -13901,7 +13993,7 @@ void Unit::NearTeleportTo( float x, float y, float z, float orientation, bool ca
DestroyForNearbyPlayers();
GetMap()->CreatureRelocation((Creature*)this, x, y, z, orientation);
- ObjectAccessor::UpdateObjectVisibility(this);
+ //ObjectAccessor::UpdateObjectVisibility(this);
//WorldPacket data;
// Work strange for many spells: triggered active mover set for targeted player to creature
diff --git a/src/game/Unit.h b/src/game/Unit.h
index fcfc14b5394..bbd7471b1b8 100644
--- a/src/game/Unit.h
+++ b/src/game/Unit.h
@@ -745,24 +745,25 @@ struct CalcDamageInfo
// Spell damage info structure based on structure sending in SMSG_SPELLNONMELEEDAMAGELOG opcode
struct SpellNonMeleeDamage{
- SpellNonMeleeDamage(Unit *_attacker, Unit *_target, uint32 _SpellID, uint32 _schoolMask)
- : target(_target), attacker(_attacker), SpellID(_SpellID), damage(0), schoolMask(_schoolMask),
- absorb(0), resist(0), phusicalLog(false), unused(false), blocked(0), HitInfo(0), cleanDamage(0)
- {}
-
- Unit *target;
- Unit *attacker;
- uint32 SpellID;
- uint32 damage;
- uint32 schoolMask;
- uint32 absorb;
- uint32 resist;
- bool phusicalLog;
- bool unused;
- uint32 blocked;
- uint32 HitInfo;
- // Used for help
- uint32 cleanDamage;
+ SpellNonMeleeDamage(Unit *_attacker, Unit *_target, uint32 _SpellID, uint32 _schoolMask)
+ : target(_target), attacker(_attacker), SpellID(_SpellID), damage(0), overkill(0), schoolMask(_schoolMask),
+ absorb(0), resist(0), physicalLog(false), unused(false), blocked(0), HitInfo(0), cleanDamage(0)
+ {}
+
+ Unit *target;
+ Unit *attacker;
+ uint32 SpellID;
+ uint32 damage;
+ uint32 overkill;
+ uint32 schoolMask;
+ uint32 absorb;
+ uint32 resist;
+ bool physicalLog;
+ bool unused;
+ uint32 blocked;
+ uint32 HitInfo;
+ // Used for help
+ uint32 cleanDamage;
};
uint32 createProcExtendMask(SpellNonMeleeDamage *damageInfo, SpellMissInfo missCondition);
@@ -939,8 +940,8 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
void SetCanDualWield(bool value) { m_canDualWield = value; }
float GetCombatReach() const { return m_floatValues[UNIT_FIELD_COMBATREACH]; }
float GetMeleeReach() const { float reach = m_floatValues[UNIT_FIELD_COMBATREACH]; return reach > MIN_MELEE_REACH ? reach : MIN_MELEE_REACH; }
- bool IsWithinCombatRange(Unit *obj, float dist2compare) const;
- bool IsWithinMeleeRange(Unit *obj, float dist = MELEE_RANGE) const;
+ bool IsWithinCombatRange(const Unit *obj, float dist2compare) const;
+ bool IsWithinMeleeRange(const Unit *obj, float dist = MELEE_RANGE) const;
void GetRandomContactPoint( const Unit* target, float &x, float &y, float &z, float distance2dMin, float distance2dMax ) const;
uint32 m_extraAttacks;
bool m_canDualWield;
@@ -1072,6 +1073,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
uint16 GetMaxSkillValueForLevel(Unit const* target = NULL) const { return (target ? getLevelForTarget(target) : getLevel()) * 5; }
void RemoveSpellbyDamageTaken(uint32 damage, uint32 spell);
+ void DealDamageMods(Unit *pVictim, uint32 &damage, uint32* absorb);
uint32 DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDamage = NULL, DamageEffectType damagetype = DIRECT_DAMAGE, SpellSchoolMask damageSchoolMask = SPELL_SCHOOL_MASK_NORMAL, SpellEntry const *spellProto = NULL, bool durabilityLoss = true);
void Kill(Unit *pVictim, bool durabilityLoss = true);
int32 DealHeal(Unit *pVictim, uint32 addhealth, SpellEntry const *spellProto, bool critical = false);
@@ -1186,7 +1188,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
void CastSpell(GameObject *go, uint32 spellId, bool triggered, Item *castItem = NULL, AuraEffect* triggeredByAura = NULL, uint64 originalCaster = 0);
void AddAura(uint32 spellId, Unit *target);
void HandleAuraEffect(AuraEffect * aureff, bool apply);
- Aura *AddAuraEffect(uint32 spellId, uint8 effIndex, Unit* caster, int32 * basePoints=NULL);
+ Aura *AddAuraEffect(const SpellEntry * spellInfo, uint8 effIndex, Unit* caster, int32 * basePoints=NULL);
bool IsDamageToThreatSpell(SpellEntry const * spellInfo) const;
@@ -1212,6 +1214,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
void SendMonsterMoveByPath(Path const& path, uint32 start, uint32 end);
void SendMonsterMoveWithSpeed(float x, float y, float z, uint32 transitTime = 0, Player* player = NULL);
void SendMonsterMoveWithSpeedToCurrentDestination(Player* player = NULL);
+ void SendMovementFlagUpdate();
bool isAlive() const { return (m_deathState == ALIVE); };
bool isDead() const { return ( m_deathState == DEAD || m_deathState == CORPSE ); };
@@ -1400,9 +1403,9 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
float GetWeaponDamageRange(WeaponAttackType attType ,WeaponDamageRange type) const;
void SetBaseWeaponDamage(WeaponAttackType attType ,WeaponDamageRange damageRange, float value) { m_weaponDamage[attType][damageRange] = value; }
- bool isInFront(Unit const* target,float distance, float arc = M_PI) const;
+ bool isInFrontInMap(Unit const* target,float distance, float arc = M_PI) const;
void SetInFront(Unit const* target);
- bool isInBack(Unit const* target, float distance, float arc = M_PI) const;
+ bool isInBackInMap(Unit const* target, float distance, float arc = M_PI) const;
bool isInLine(Unit const* target, float distance) const;
// Visibility system
diff --git a/src/game/UnitAI.cpp b/src/game/UnitAI.cpp
new file mode 100644
index 00000000000..12dc20692c6
--- /dev/null
+++ b/src/game/UnitAI.cpp
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * Copyright (C) 2008-2009 Trinity <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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "UnitAI.h"
+#include "Player.h"
+#include "Creature.h"
+#include "SpellAuras.h"
+
+void UnitAI::AttackStart(Unit *victim)
+{
+ if(!victim)
+ return;
+
+ if(me->Attack(victim, true))
+ {
+ //DEBUG_LOG("Creature %s tagged a victim to kill [guid=%u]", me->GetName(), victim->GetGUIDLow());
+ me->GetMotionMaster()->MoveChase(victim);
+ }
+}
+
+void UnitAI::DoMeleeAttackIfReady()
+{
+ if(me->hasUnitState(UNIT_STAT_CASTING))
+ return;
+
+ //Make sure our attack is ready and we aren't currently casting before checking distance
+ if (me->isAttackReady())
+ {
+ //If we are within range melee the target
+ if (me->IsWithinMeleeRange(me->getVictim()))
+ {
+ me->AttackerStateUpdate(me->getVictim());
+ me->resetAttackTimer();
+ }
+ }
+ if (me->haveOffhandWeapon() && me->isAttackReady(OFF_ATTACK))
+ {
+ //If we are within range melee the target
+ if (me->IsWithinMeleeRange(me->getVictim()))
+ {
+ me->AttackerStateUpdate(me->getVictim(), OFF_ATTACK);
+ me->resetAttackTimer(OFF_ATTACK);
+ }
+ }
+}
+
+//Enable PlayerAI when charmed
+void PlayerAI::OnCharmed(bool apply) { me->IsAIEnabled = apply; }
+
+void SimpleCharmedAI::UpdateAI(const uint32 /*diff*/)
+{
+ Creature *charmer = (Creature*)me->GetCharmer();
+
+ //kill self if charm aura has infinite duration
+ if(charmer->IsInEvadeMode())
+ {
+ Unit::AuraEffectList const& auras = me->GetAurasByType(SPELL_AURA_MOD_CHARM);
+ for(Unit::AuraEffectList::const_iterator iter = auras.begin(); iter != auras.end(); ++iter)
+ if((*iter)->GetCasterGUID() == charmer->GetGUID() && (*iter)->GetParentAura()->IsPermanent())
+ {
+ charmer->Kill(me);
+ return;
+ }
+ }
+
+ if(!charmer->isInCombat())
+ me->GetMotionMaster()->MoveFollow(charmer, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
+
+ Unit *target = me->getVictim();
+ if(!target || !charmer->canAttack(target))
+ AttackStart(charmer->SelectNearestTarget());
+}
diff --git a/src/game/UnitAI.h b/src/game/UnitAI.h
new file mode 100644
index 00000000000..04de74f480e
--- /dev/null
+++ b/src/game/UnitAI.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * Copyright (C) 2008-2009 Trinity <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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef TRINITY_UNITAI_H
+#define TRINITY_UNITAI_H
+
+#include "Platform/Define.h"
+
+class Unit;
+class Player;
+
+class TRINITY_DLL_SPEC UnitAI
+{
+ protected:
+ Unit * const me;
+ public:
+ explicit UnitAI(Unit *u) : me(u) {}
+ virtual void AttackStart(Unit *);
+ virtual void UpdateAI(const uint32 diff) = 0;
+
+ virtual void InitializeAI() { Reset(); }
+
+ virtual void Reset() {};
+
+ // Called when unit is charmed
+ virtual void OnCharmed(bool apply) = 0;
+
+ // Pass parameters between AI
+ virtual void DoAction(const int32 param) {}
+
+ //Do melee swing of current victim if in rnage and ready and not casting
+ void DoMeleeAttackIfReady();
+};
+
+class TRINITY_DLL_SPEC PlayerAI : public UnitAI
+{
+ protected:
+ Player* const me;
+ public:
+ explicit PlayerAI(Player *p) : UnitAI((Unit*)p), me(p) {}
+
+ void OnCharmed(bool apply);
+};
+
+class TRINITY_DLL_SPEC SimpleCharmedAI : public PlayerAI
+{
+ public:
+ void UpdateAI(const uint32 diff);
+};
+
+#endif
diff --git a/src/game/WaypointManager.cpp b/src/game/WaypointManager.cpp
index a677fd5b6d2..26be14d89fa 100644
--- a/src/game/WaypointManager.cpp
+++ b/src/game/WaypointManager.cpp
@@ -24,12 +24,12 @@
#include "ProgressBar.h"
#include "MapManager.h"
-UNORDERED_MAP<uint32, WaypointPath*> waypoint_map;
+WaypointPathMap WaypointPathHolder;
WaypointStore WaypointMgr;
void WaypointStore::Free()
{
- waypoint_map.clear();
+ WaypointPathHolder.clear();
}
void WaypointStore::Load()
@@ -37,7 +37,7 @@ void WaypointStore::Load()
QueryResult *result = WorldDatabase.PQuery("SELECT MAX(`id`) FROM `waypoint_data`");
if(!result)
{
- sLog.outError(" an error occured while loading the table `waypoint_data` ( maybe it doesn't exist ?)\n");
+ sLog.outError("an error occured while loading the table `waypoint_data` (maybe it doesn't exist ?)");
exit(1); // Stop server at loading non exited table or not accessable table
}
@@ -47,7 +47,7 @@ void WaypointStore::Load()
result = WorldDatabase.PQuery("SELECT `id`,`point`,`position_x`,`position_y`,`position_z`,`move_flag`,`delay`,`action`,`action_chance` FROM `waypoint_data` ORDER BY `id`, `point`");
if(!result)
{
- sLog.outErrorDb("The table `creature_addon` is empty or corrupted");
+ sLog.outErrorDb("The table `waypoint_data` is empty or corrupted");
return;
}
@@ -87,22 +87,21 @@ void WaypointStore::Load()
path_data->push_back(wp);
- if(id != last_id)
- waypoint_map[id] = path_data;
+ if(id != last_id)
+ WaypointPathHolder[id] = path_data;
last_id = id;
} while(result->NextRow()) ;
-
delete result;
}
void WaypointStore::UpdatePath(uint32 id)
{
-
- if(waypoint_map.find(id)!= waypoint_map.end())
- waypoint_map[id]->clear();
+ // TODO: this will cause memory leak
+ if(WaypointPathHolder.find(id) != WaypointPathHolder.end())
+ WaypointPathHolder[id]->clear();
QueryResult *result;
@@ -145,7 +144,7 @@ void WaypointStore::UpdatePath(uint32 id)
}while (result->NextRow());
- waypoint_map[id] = path_data;
+ WaypointPathHolder[id] = path_data;
delete result;
}
diff --git a/src/game/WaypointManager.h b/src/game/WaypointManager.h
index 85f8b765d45..a8f2d5746e9 100644
--- a/src/game/WaypointManager.h
+++ b/src/game/WaypointManager.h
@@ -34,7 +34,9 @@ struct WaypointData
};
typedef std::vector<WaypointData*> WaypointPath;
-extern UNORDERED_MAP<uint32, WaypointPath*> waypoint_map;
+typedef UNORDERED_MAP<uint32, WaypointPath*> WaypointPathMap;
+
+extern WaypointPathMap WaypointPathHolder;
class WaypointStore
{
@@ -48,9 +50,10 @@ class WaypointStore
WaypointPath* GetPath(uint32 id)
{
- if(waypoint_map.find(id) != waypoint_map.end())
- return waypoint_map[id];
- else return 0;
+ WaypointPathMap::iterator itr = WaypointPathHolder.find(id);
+ if(itr != WaypointPathHolder.end())
+ return itr->second;
+ return NULL;
}
inline uint32 GetRecordsCount() { return records; }
diff --git a/src/game/WaypointMovementGenerator.cpp b/src/game/WaypointMovementGenerator.cpp
index 7cabd63acf1..effc78d8026 100644
--- a/src/game/WaypointMovementGenerator.cpp
+++ b/src/game/WaypointMovementGenerator.cpp
@@ -100,7 +100,7 @@ WaypointMovementGenerator<Creature>::Initialize(Creature &u)
//i_nextMoveTime.Reset(0);
StopedByPlayer = false;
if(!path_id)
- path_id = u.GetWaypointPath();
+ path_id = u.GetWaypointPathId();
waypoints = WaypointMgr.GetPath(path_id);
i_currentNode = 0;
if(waypoints && waypoints->size())
@@ -226,7 +226,7 @@ template bool WaypointMovementGenerator<Player>::Update(Player &, const uint32 &
template void WaypointMovementGenerator<Player>::MovementInform(Player &);
//----------------------------------------------------//
-void FlightPathMovementGenerator::LoadPath(Player &)
+void FlightPathMovementGenerator::SetWaypointPathId(Player &)
{
objmgr.GetTaxiPathNodes(i_pathId, i_path,i_mapIds);
}
@@ -251,7 +251,8 @@ void FlightPathMovementGenerator::Initialize(Player &player)
player.getHostilRefManager().setOnlineOfflineState(false);
player.addUnitState(UNIT_STAT_IN_FLIGHT);
player.SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_TAXI_FLIGHT);
- LoadPath(player);
+ player.AddUnitMovementFlag(MOVEMENTFLAG_FLYING2);
+ SetWaypointPathId(player);
Traveller<Player> traveller(player);
// do not send movement, it was sent already
i_destinationHolder.SetDestination(traveller, i_path[i_currentNode].x, i_path[i_currentNode].y, i_path[i_currentNode].z, false);
@@ -270,6 +271,7 @@ void FlightPathMovementGenerator::Finalize(Player & player)
player.Unmount();
player.RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_TAXI_FLIGHT);
+ player.RemoveUnitMovementFlag(MOVEMENTFLAG_FLYING2);
if(player.m_taxi.empty())
{
diff --git a/src/game/WaypointMovementGenerator.h b/src/game/WaypointMovementGenerator.h
index 9804c150d63..9c93486a675 100644
--- a/src/game/WaypointMovementGenerator.h
+++ b/src/game/WaypointMovementGenerator.h
@@ -50,7 +50,7 @@ class TRINITY_DLL_SPEC PathMovementBase
bool MovementInProgress(void) const { return i_currentNode < i_path.Size(); }
- void LoadPath(T &);
+ void SetWaypointPathId(T &);
void ReloadPath(T &);
uint32 GetCurrentNode() const { return i_currentNode; }
@@ -104,7 +104,7 @@ public PathMovementBase<Player>
bool Update(Player &, const uint32 &);
MovementGeneratorType GetMovementGeneratorType() { return FLIGHT_MOTION_TYPE; }
- void LoadPath(Player &);
+ void SetWaypointPathId(Player &);
void ReloadPath(Player &) { /* don't reload flight path */ }
Path& GetPath() { return i_path; }
diff --git a/src/game/World.cpp b/src/game/World.cpp
index fa44e527da5..665fb6d4bdc 100644
--- a/src/game/World.cpp
+++ b/src/game/World.cpp
@@ -792,7 +792,9 @@ void World::LoadConfigSettings(bool reload)
m_configs[CONFIG_GM_IN_GM_LIST] = sConfig.GetBoolDefault("GM.InGMList", false);
m_configs[CONFIG_GM_IN_WHO_LIST] = sConfig.GetBoolDefault("GM.InWhoList", false);
m_configs[CONFIG_GM_LOG_TRADE] = sConfig.GetBoolDefault("GM.LogTrade", false);
- m_configs[CONFIG_START_GM_LEVEL] = sConfig.GetIntDefault("GM.StartLevel", 1);
+ m_configs[CONFIG_START_GM_LEVEL] = sConfig.GetIntDefault("GM.StartLevel", 1);
+ m_configs[CONFIG_ALLOW_GM_GROUP] = sConfig.GetBoolDefault("GM.AllowInvite", false);
+ m_configs[CONFIG_ALLOW_GM_FRIEND] = sConfig.GetBoolDefault("GM.AllowFriend", false);
if(m_configs[CONFIG_START_GM_LEVEL] < m_configs[CONFIG_START_PLAYER_LEVEL])
{
sLog.outError("GM.StartLevel (%i) must be in range StartPlayerLevel(%u)..%u. Set to %u.",
diff --git a/src/game/World.h b/src/game/World.h
index 27075885368..62648ebce2c 100644
--- a/src/game/World.h
+++ b/src/game/World.h
@@ -141,6 +141,8 @@ enum WorldConfigs
CONFIG_GM_IN_GM_LIST,
CONFIG_GM_IN_WHO_LIST,
CONFIG_GM_LOG_TRADE,
+ CONFIG_ALLOW_GM_GROUP,
+ CONFIG_ALLOW_GM_FRIEND,
CONFIG_START_GM_LEVEL,
CONFIG_GM_LOWER_SECURITY,
CONFIG_GM_ALLOW_ACHIEVEMENT_GAINS,
@@ -626,7 +628,7 @@ class World
static float m_VisibleObjectGreyDistance;
// CLI command holder to be thread safe
- ZThread::LockedQueue<CliCommandHolder*, ZThread::FastMutex> cliCmdQueue;
+ ACE_Based::LockedQueue<CliCommandHolder*,ACE_Thread_Mutex> cliCmdQueue;
SqlResultQueue *m_resultQueue;
// next daily quests reset time
@@ -637,7 +639,7 @@ class World
//sessions that are added async
void AddSession_(WorldSession* s);
- ZThread::LockedQueue<WorldSession*, ZThread::FastMutex> addSessQueue;
+ ACE_Based::LockedQueue<WorldSession*, ACE_Thread_Mutex> addSessQueue;
//used versions
std::string m_DBVersion;
diff --git a/src/game/WorldLog.cpp b/src/game/WorldLog.cpp
index 52eb1e8b59c..978514ac7d7 100644
--- a/src/game/WorldLog.cpp
+++ b/src/game/WorldLog.cpp
@@ -27,9 +27,9 @@
#include "Config/ConfigEnv.h"
#include "Log.h"
-#define CLASS_LOCK Trinity::ClassLevelLockable<WorldLog, ZThread::FastMutex>
+#define CLASS_LOCK MaNGOS::ClassLevelLockable<WorldLog, ACE_Thread_Mutex>
INSTANTIATE_SINGLETON_2(WorldLog, CLASS_LOCK);
-INSTANTIATE_CLASS_MUTEX(WorldLog, ZThread::FastMutex);
+INSTANTIATE_CLASS_MUTEX(WorldLog, ACE_Thread_Mutex);
#define WORLD_LOG_FILE_STRING "world.log"
diff --git a/src/game/WorldLog.h b/src/game/WorldLog.h
index 01f34535dd9..e6b72e654f7 100644
--- a/src/game/WorldLog.h
+++ b/src/game/WorldLog.h
@@ -32,13 +32,13 @@
#include <stdarg.h>
/// %Log packets to a file
-class TRINITY_DLL_DECL WorldLog : public Trinity::Singleton<WorldLog, Trinity::ClassLevelLockable<WorldLog, ZThread::FastMutex> >
+class MANGOS_DLL_DECL WorldLog : public MaNGOS::Singleton<WorldLog, MaNGOS::ClassLevelLockable<WorldLog, ACE_Thread_Mutex> >
{
friend class Trinity::OperatorNew<WorldLog>;
WorldLog();
WorldLog(const WorldLog &);
WorldLog& operator=(const WorldLog &);
- typedef Trinity::ClassLevelLockable<WorldLog, ZThread::FastMutex>::Lock Guard;
+ typedef MaNGOS::ClassLevelLockable<WorldLog, ACE_Thread_Mutex>::Lock Guard;
/// Close the file in destructor
~WorldLog();
diff --git a/src/game/WorldSession.h b/src/game/WorldSession.h
index d514586957a..a8d6db72809 100644
--- a/src/game/WorldSession.h
+++ b/src/game/WorldSession.h
@@ -719,8 +719,7 @@ class TRINITY_DLL_SPEC WorldSession
uint32 m_latency;
AccountData m_accountData[NUM_ACCOUNT_DATA_TYPES];
AddonsList m_addonsList;
-
- ZThread::LockedQueue<WorldPacket*,ZThread::FastMutex> _recvQueue;
+ ACE_Based::LockedQueue<WorldPacket*, ACE_Thread_Mutex> _recvQueue;
};
#endif
/// @}
diff --git a/src/shared/CMakeLists.txt b/src/shared/CMakeLists.txt
index 8ecfccad34f..b271e2b9545 100644
--- a/src/shared/CMakeLists.txt
+++ b/src/shared/CMakeLists.txt
@@ -14,6 +14,7 @@ SET(shared_STAT_SRCS
Log.h
ProgressBar.cpp
ProgressBar.h
+ Threading.cpp
Timer.h
Util.cpp
Util.h
@@ -22,3 +23,7 @@ SET(shared_STAT_SRCS
)
add_library(shared STATIC ${shared_STAT_SRCS})
+target_link_libraries(
+shared
+${ACE_LIBRARY}
+)
diff --git a/src/shared/Common.h b/src/shared/Common.h
index abe804bb3a4..37ced4c8e11 100644
--- a/src/shared/Common.h
+++ b/src/shared/Common.h
@@ -62,26 +62,17 @@
#include "Platform/Define.h"
#if COMPILER == COMPILER_MICROSOFT
-
-#pragma warning(disable:4996)
-
+# pragma warning(disable:4996) // 'function': was declared deprecated
#ifndef __SHOW_STUPID_WARNINGS__
-
-#pragma warning(disable:4244)
-
-#pragma warning(disable:4267)
-
-#pragma warning(disable:4800)
-
-#pragma warning(disable:4018)
-
-#pragma warning(disable:4311)
-
-#pragma warning(disable:4305)
-
-#pragma warning(disable:4005)
-
-#pragma warning(disable:4522)//warning when class has 2 constructosr
+# pragma warning(disable:4005) // 'identifier' : macro redefinition
+# pragma warning(disable:4018) // 'expression' : signed/unsigned mismatch
+# pragma warning(disable:4244) // 'argument' : conversion from 'type1' to 'type2', possible loss of data
+# pragma warning(disable:4267) // 'var' : conversion from 'size_t' to 'type', possible loss of data
+# pragma warning(disable:4305) // 'identifier' : truncation from 'type1' to 'type2'
+# pragma warning(disable:4311) // 'variable' : pointer truncation from 'type' to 'type'
+# pragma warning(disable:4355) // 'this' : used in base member initializer list
+# pragma warning(disable:4800) // 'type' : forcing value to bool 'true' or 'false' (performance warning)
+# pragma warning(disable:4522) //warning when class has 2 constructosr
#endif // __SHOW_STUPID_WARNINGS__
#endif // __GNUC__
@@ -93,6 +84,7 @@
#include <math.h>
#include <errno.h>
#include <signal.h>
+#include <assert.h>
#if PLATFORM == PLATFORM_WINDOWS
#define STRCASECMP stricmp
@@ -108,10 +100,13 @@
#include <sstream>
#include <algorithm>
-#include <zthread/FastMutex.h>
-#include <zthread/LockedQueue.h>
-#include <zthread/Runnable.h>
-#include <zthread/Thread.h>
+#include "LockedQueue.h"
+#include "Threading.h"
+
+#include <ace/Guard_T.h>
+#include <ace/RW_Thread_Mutex.h>
+#include <ace/Thread_Mutex.h>
+
#if PLATFORM == PLATFORM_WINDOWS
# define FD_SETSIZE 4096
diff --git a/src/shared/Database/Database.cpp b/src/shared/Database/Database.cpp
index 07ece3b0cd9..d5ccc581232 100644
--- a/src/shared/Database/Database.cpp
+++ b/src/shared/Database/Database.cpp
@@ -110,7 +110,8 @@ bool Database::PExecuteLog(const char * format,...)
void Database::SetResultQueue(SqlResultQueue * queue)
{
- m_queryQueues[ZThread::ThreadImpl::current()] = queue;
+ m_queryQueues[ACE_Based::Thread::current()] = queue;
+
}
QueryResult* Database::PQuery(const char *format,...)
diff --git a/src/shared/Database/Database.h b/src/shared/Database/Database.h
index 92a1c991dcc..a9f7285c223 100644
--- a/src/shared/Database/Database.h
+++ b/src/shared/Database/Database.h
@@ -21,8 +21,7 @@
#ifndef DATABASE_H
#define DATABASE_H
-#include "zthread/Thread.h"
-#include "../src/zthread/ThreadImpl.h"
+#include "Threading.h"
#include "Utilities/UnorderedMap.h"
#include "Database/SqlDelayThread.h"
@@ -30,8 +29,8 @@ class SqlTransaction;
class SqlResultQueue;
class SqlQueryHolder;
-typedef UNORDERED_MAP<ZThread::ThreadImpl*, SqlTransaction*> TransactionQueues;
-typedef UNORDERED_MAP<ZThread::ThreadImpl*, SqlResultQueue*> QueryQueues;
+typedef UNORDERED_MAP<ACE_Based::Thread* , SqlTransaction*> TransactionQueues;
+typedef UNORDERED_MAP<ACE_Based::Thread* , SqlResultQueue*> QueryQueues;
#define MAX_QUERY_LEN 32*1024
@@ -43,7 +42,7 @@ class TRINITY_DLL_SPEC Database
TransactionQueues m_tranQueues; ///< Transaction queues from diff. threads
QueryQueues m_queryQueues; ///< Query queues from diff threads
SqlDelayThread* m_threadBody; ///< Pointer to delay sql executer
- ZThread::Thread* m_delayThread; ///< Pointer to executer thread
+ ACE_Based::Thread* m_delayThread; ///< Pointer to executer thread
public:
diff --git a/src/shared/Database/DatabaseImpl.h b/src/shared/Database/DatabaseImpl.h
index 3d3c53f0873..7cbd0ed8ba5 100644
--- a/src/shared/Database/DatabaseImpl.h
+++ b/src/shared/Database/DatabaseImpl.h
@@ -29,7 +29,7 @@
QueryQueues::iterator queue_itr; \
\
{ \
- ZThread::ThreadImpl * queryThread = ZThread::ThreadImpl::current(); \
+ ACE_Based::Thread * queryThread = ACE_Based::Thread::current(); \
queue_itr = m_queryQueues.find(queryThread); \
if (queue_itr == m_queryQueues.end()) return false; \
}
@@ -59,7 +59,7 @@
QueryQueues::iterator queue_itr; \
\
{ \
- ZThread::ThreadImpl * queryThread = ZThread::ThreadImpl::current(); \
+ ACE_Based::Thread * queryThread = ACE_Based::Thread::current(); \
queue_itr = m_queryQueues.find(queryThread); \
if (queue_itr == m_queryQueues.end()) return false; \
}
diff --git a/src/shared/Database/DatabaseMysql.cpp b/src/shared/Database/DatabaseMysql.cpp
index 5dc02c0a738..9574d3dc2ac 100644
--- a/src/shared/Database/DatabaseMysql.cpp
+++ b/src/shared/Database/DatabaseMysql.cpp
@@ -23,7 +23,7 @@
#include "Util.h"
#include "Policies/SingletonImp.h"
#include "Platform/Define.h"
-#include "../src/zthread/ThreadImpl.h"
+#include "Threading.h"
#include "DatabaseEnv.h"
#include "Database/MySQLDelayThread.h"
#include "Database/SqlOperations.h"
@@ -203,8 +203,8 @@ QueryResult* DatabaseMysql::Query(const char *sql)
{
// guarded block for thread-safe mySQL request
- ZThread::Guard<ZThread::FastMutex> query_connection_guard(mMutex);
- #ifdef TRINITY_DEBUG
+ ACE_Guard<ACE_Thread_Mutex> query_connection_guard(mMutex);
+ #ifdef MANGOS_DEBUG
uint32 _s = getMSTime();
#endif
if(mysql_query(mMysql, sql))
@@ -251,7 +251,7 @@ bool DatabaseMysql::Execute(const char *sql)
// don't use queued execution if it has not been initialized
if (!m_threadBody) return DirectExecute(sql);
- tranThread = ZThread::ThreadImpl::current(); // owner of this transaction
+ tranThread = ACE_Based::Thread::current(); // owner of this transaction
TransactionQueues::iterator i = m_tranQueues.find(tranThread);
if (i != m_tranQueues.end() && i->second != NULL)
{ // Statement for transaction
@@ -273,8 +273,9 @@ bool DatabaseMysql::DirectExecute(const char* sql)
{
// guarded block for thread-safe mySQL request
- ZThread::Guard<ZThread::FastMutex> query_connection_guard(mMutex);
- #ifdef TRINITY_DEBUG
+ ACE_Guard<ACE_Thread_Mutex> query_connection_guard(mMutex);
+
+ #ifdef MANGOS_DEBUG
uint32 _s = getMSTime();
#endif
if(mysql_query(mMysql, sql))
@@ -318,8 +319,9 @@ bool DatabaseMysql::BeginTransaction()
// don't use queued execution if it has not been initialized
if (!m_threadBody)
{
- if (tranThread==ZThread::ThreadImpl::current())
+ if (tranThread == ACE_Based::Thread::current())
return false; // huh? this thread already started transaction
+
mMutex.acquire();
if (!_TransactionCmd("START TRANSACTION"))
{
@@ -329,7 +331,7 @@ bool DatabaseMysql::BeginTransaction()
return true; // transaction started
}
- tranThread = ZThread::ThreadImpl::current(); // owner of this transaction
+ tranThread = ACE_Based::Thread::current(); // owner of this transaction
TransactionQueues::iterator i = m_tranQueues.find(tranThread);
if (i != m_tranQueues.end() && i->second != NULL)
// If for thread exists queue and also contains transaction
@@ -349,7 +351,7 @@ bool DatabaseMysql::CommitTransaction()
// don't use queued execution if it has not been initialized
if (!m_threadBody)
{
- if (tranThread!=ZThread::ThreadImpl::current())
+ if (tranThread != ACE_Based::Thread::current())
return false;
bool _res = _TransactionCmd("COMMIT");
tranThread = NULL;
@@ -357,7 +359,7 @@ bool DatabaseMysql::CommitTransaction()
return _res;
}
- tranThread = ZThread::ThreadImpl::current();
+ tranThread = ACE_Based::Thread::current();
TransactionQueues::iterator i = m_tranQueues.find(tranThread);
if (i != m_tranQueues.end() && i->second != NULL)
{
@@ -377,7 +379,7 @@ bool DatabaseMysql::RollbackTransaction()
// don't use queued execution if it has not been initialized
if (!m_threadBody)
{
- if (tranThread!=ZThread::ThreadImpl::current())
+ if (tranThread != ACE_Based::Thread::current())
return false;
bool _res = _TransactionCmd("ROLLBACK");
tranThread = NULL;
@@ -385,7 +387,7 @@ bool DatabaseMysql::RollbackTransaction()
return _res;
}
- tranThread = ZThread::ThreadImpl::current();
+ tranThread = ACE_Based::Thread::current();
TransactionQueues::iterator i = m_tranQueues.find(tranThread);
if (i != m_tranQueues.end() && i->second != NULL)
{
@@ -408,7 +410,8 @@ void DatabaseMysql::InitDelayThread()
assert(!m_delayThread);
//New delay thread for delay execute
- m_delayThread = new ZThread::Thread(m_threadBody = new MySQLDelayThread(this));
+ m_threadBody = new MySQLDelayThread(this);
+ m_delayThread = new ACE_Based::Thread(*m_threadBody);
}
void DatabaseMysql::HaltDelayThread()
diff --git a/src/shared/Database/DatabaseMysql.h b/src/shared/Database/DatabaseMysql.h
index 2fa157e75a5..7f5730f9579 100644
--- a/src/shared/Database/DatabaseMysql.h
+++ b/src/shared/Database/DatabaseMysql.h
@@ -25,7 +25,8 @@
#include "Database.h"
#include "Policies/Singleton.h"
-#include "zthread/FastMutex.h"
+#include "ace/Thread_Mutex.h"
+#include "ace/Guard_T.h"
#ifdef WIN32
#define FD_SETSIZE 1024
@@ -65,9 +66,9 @@ class TRINITY_DLL_SPEC DatabaseMysql : public Database
// must be call before finish thread run
void ThreadEnd();
private:
- ZThread::FastMutex mMutex;
+ ACE_Thread_Mutex mMutex;
- ZThread::ThreadImpl* tranThread;
+ ACE_Based::Thread * tranThread;
MYSQL *mMysql;
diff --git a/src/shared/Database/DatabasePostgre.cpp b/src/shared/Database/DatabasePostgre.cpp
index 79e1c87f5e3..12875b33200 100644
--- a/src/shared/Database/DatabasePostgre.cpp
+++ b/src/shared/Database/DatabasePostgre.cpp
@@ -23,7 +23,7 @@
#include "Util.h"
#include "Policies/SingletonImp.h"
#include "Platform/Define.h"
-#include "../src/zthread/ThreadImpl.h"
+#include "Threading.h"
#include "DatabaseEnv.h"
#include "Database/PGSQLDelayThread.h"
#include "Database/SqlOperations.h"
@@ -126,8 +126,8 @@ QueryResult* DatabasePostgre::Query(const char *sql)
uint32 fieldCount = 0;
// guarded block for thread-safe request
- ZThread::Guard<ZThread::FastMutex> query_connection_guard(mMutex);
- #ifdef TRINITY_DEBUG
+ ACE_Guard<ACE_Thread_Mutex> query_connection_guard(mMutex);
+ #ifdef MANGOS_DEBUG
uint32 _s = getMSTime();
#endif
// Send the query
@@ -174,9 +174,10 @@ bool DatabasePostgre::Execute(const char *sql)
return false;
// don't use queued execution if it has not been initialized
- if (!m_threadBody) return DirectExecute(sql);
+ if (!m_threadBody)
+ return DirectExecute(sql);
- tranThread = ZThread::ThreadImpl::current(); // owner of this transaction
+ tranThread = ACE_Based::Thread::current(); // owner of this transaction
TransactionQueues::iterator i = m_tranQueues.find(tranThread);
if (i != m_tranQueues.end() && i->second != NULL)
{ // Statement for transaction
@@ -197,8 +198,8 @@ bool DatabasePostgre::DirectExecute(const char* sql)
return false;
{
// guarded block for thread-safe request
- ZThread::Guard<ZThread::FastMutex> query_connection_guard(mMutex);
- #ifdef TRINITY_DEBUG
+ ACE_Guard<ACE_Thread_Mutex> query_connection_guard(mMutex);
+ #ifdef MANGOS_DEBUG
uint32 _s = getMSTime();
#endif
PGresult *res = PQexec(mPGconn, sql);
@@ -247,7 +248,7 @@ bool DatabasePostgre::BeginTransaction()
// don't use queued execution if it has not been initialized
if (!m_threadBody)
{
- if (tranThread==ZThread::ThreadImpl::current())
+ if (tranThread == ACE_Based::Thread::current())
return false; // huh? this thread already started transaction
mMutex.acquire();
if (!_TransactionCmd("START TRANSACTION"))
@@ -258,7 +259,7 @@ bool DatabasePostgre::BeginTransaction()
return true;
}
// transaction started
- tranThread = ZThread::ThreadImpl::current(); // owner of this transaction
+ tranThread = ACE_Based::Thread::current(); // owner of this transaction
TransactionQueues::iterator i = m_tranQueues.find(tranThread);
if (i != m_tranQueues.end() && i->second != NULL)
// If for thread exists queue and also contains transaction
@@ -278,14 +279,14 @@ bool DatabasePostgre::CommitTransaction()
// don't use queued execution if it has not been initialized
if (!m_threadBody)
{
- if (tranThread!=ZThread::ThreadImpl::current())
+ if (tranThread != ACE_Based::Thread::current())
return false;
bool _res = _TransactionCmd("COMMIT");
tranThread = NULL;
mMutex.release();
return _res;
}
- tranThread = ZThread::ThreadImpl::current();
+ tranThread = ACE_Based::Thread::current();
TransactionQueues::iterator i = m_tranQueues.find(tranThread);
if (i != m_tranQueues.end() && i->second != NULL)
{
@@ -304,14 +305,14 @@ bool DatabasePostgre::RollbackTransaction()
// don't use queued execution if it has not been initialized
if (!m_threadBody)
{
- if (tranThread!=ZThread::ThreadImpl::current())
+ if (tranThread != ACE_Based::Thread::current())
return false;
bool _res = _TransactionCmd("ROLLBACK");
tranThread = NULL;
mMutex.release();
return _res;
}
- tranThread = ZThread::ThreadImpl::current();
+ tranThread = ACE_Based::Thread::current();
TransactionQueues::iterator i = m_tranQueues.find(tranThread);
if (i != m_tranQueues.end() && i->second != NULL)
{
@@ -334,7 +335,8 @@ void DatabasePostgre::InitDelayThread()
assert(!m_delayThread);
//New delay thread for delay execute
- m_delayThread = new ZThread::Thread(m_threadBody = new PGSQLDelayThread(this));
+ m_threadBody = new PGSQLDelayThread(this);
+ m_delayThread = new ACE_Based::Thread(*m_threadBody);
}
void DatabasePostgre::HaltDelayThread()
diff --git a/src/shared/Database/DatabasePostgre.h b/src/shared/Database/DatabasePostgre.h
index c7242add572..53f0802f86c 100644
--- a/src/shared/Database/DatabasePostgre.h
+++ b/src/shared/Database/DatabasePostgre.h
@@ -22,7 +22,6 @@
#define _DatabasePostgre_H
#include "Policies/Singleton.h"
-#include "zthread/FastMutex.h"
#include <stdarg.h>
#ifdef WIN32
@@ -63,10 +62,8 @@ class DatabasePostgre : public Database
// must be call before finish thread run
void ThreadEnd();
private:
- ZThread::FastMutex mMutex;
- ZThread::FastMutex tranMutex;
-
- ZThread::ThreadImpl* tranThread;
+ ACE_Thread_Mutex mMutex;
+ ACE_Based::Thread * tranThread;
PGconn *mPGconn;
diff --git a/src/shared/Database/QueryResult.h b/src/shared/Database/QueryResult.h
index 01da45ed281..39228dd4ba9 100644
--- a/src/shared/Database/QueryResult.h
+++ b/src/shared/Database/QueryResult.h
@@ -40,7 +40,7 @@ class TRINITY_DLL_SPEC QueryResult
if(iter->second == name)
return iter->first;
}
- assert(false && "unknown field name");
+ ASSERT(false && "unknown field name");
return uint32(-1);
}
diff --git a/src/shared/Database/SQLStorage.cpp b/src/shared/Database/SQLStorage.cpp
index 8561afc4a33..67091174c77 100644
--- a/src/shared/Database/SQLStorage.cpp
+++ b/src/shared/Database/SQLStorage.cpp
@@ -29,9 +29,9 @@ extern DatabaseMysql WorldDatabase;
const char CreatureInfosrcfmt[]="iiiiiisssiiiiiiiiiiffiffiiiiiiiiiiiffiiiiiiiiiiiiiiiiiiiiiiiisiifflliiis";
const char CreatureInfodstfmt[]="iiiiiisssiiiiiiiiiiffiffiiiiiiiiiiiffiiiiiiiiiiiiiiiiiiiiiiiisiifflliiii";
-const char CreatureDataAddonInfofmt[]="iiiiiiiis";
+const char CreatureDataAddonInfofmt[]="iiiiiiis";
const char CreatureModelfmt[]="iffbi";
-const char CreatureInfoAddonInfofmt[]="iiiiiiiis";
+const char CreatureInfoAddonInfofmt[]="iiiiiiis";
const char EquipmentInfofmt[]="iiii";
const char GameObjectInfosrcfmt[]="iiisssiifiiiiiiiiiiiiiiiiiiiiiiiis";
const char GameObjectInfodstfmt[]="iiisssiifiiiiiiiiiiiiiiiiiiiiiiiii";
diff --git a/src/shared/Database/SqlDelayThread.cpp b/src/shared/Database/SqlDelayThread.cpp
index 27f58510a0a..9a92fd5dd63 100644
--- a/src/shared/Database/SqlDelayThread.cpp
+++ b/src/shared/Database/SqlDelayThread.cpp
@@ -37,7 +37,7 @@ void SqlDelayThread::run()
{
// if the running state gets turned off while sleeping
// empty the queue before exiting
- ZThread::Thread::sleep(10);
+ ACE_Based::Thread::Sleep(10);
while (!m_sqlQueue.empty())
{
s = m_sqlQueue.next();
diff --git a/src/shared/Database/SqlDelayThread.h b/src/shared/Database/SqlDelayThread.h
index cbae0c1e5eb..3c24d3525b7 100644
--- a/src/shared/Database/SqlDelayThread.h
+++ b/src/shared/Database/SqlDelayThread.h
@@ -21,21 +21,22 @@
#ifndef __SQLDELAYTHREAD_H
#define __SQLDELAYTHREAD_H
-#include "zthread/Thread.h"
-#include "zthread/Runnable.h"
-#include "zthread/FastMutex.h"
-#include "zthread/LockedQueue.h"
+#include "ace/Thread_Mutex.h"
+#include "LockedQueue.h"
+#include "Threading.h"
+
class Database;
class SqlOperation;
-class SqlDelayThread : public ZThread::Runnable
+class SqlDelayThread : public ACE_Based::Runnable
{
- typedef ZThread::LockedQueue<SqlOperation*, ZThread::FastMutex> SqlQueue;
+ typedef ACE_Based::LockedQueue<SqlOperation*, ACE_Thread_Mutex> SqlQueue;
+
private:
SqlQueue m_sqlQueue; ///< Queue of SQL statements
Database* m_dbEngine; ///< Pointer to used Database engine
- bool m_running;
+ volatile bool m_running;
SqlDelayThread();
public:
diff --git a/src/shared/Database/SqlOperations.h b/src/shared/Database/SqlOperations.h
index 61eef4bb7c4..e91d83b6611 100644
--- a/src/shared/Database/SqlOperations.h
+++ b/src/shared/Database/SqlOperations.h
@@ -23,9 +23,8 @@
#include "Common.h"
-#include "zthread/LockedQueue.h"
-#include "zthread/FastMutex.h"
-#include "zthread/Thread.h"
+#include "ace/Thread_Mutex.h"
+#include "LockedQueue.h"
#include <queue>
#include "Utilities/Callback.h"
@@ -72,7 +71,7 @@ class SqlResultQueue; /// queue for thread
class SqlQueryHolder; /// groups several async quries
class SqlQueryHolderEx; /// points to a holder, added to the delay thread
-class SqlResultQueue : public ZThread::LockedQueue<Trinity::IQueryCallback*, ZThread::FastMutex>
+class SqlResultQueue : public ACE_Based::LockedQueue<MaNGOS::IQueryCallback* , ACE_Thread_Mutex>
{
public:
SqlResultQueue() {}
diff --git a/src/shared/LockedQueue.h b/src/shared/LockedQueue.h
new file mode 100644
index 00000000000..b085dd09b83
--- /dev/null
+++ b/src/shared/LockedQueue.h
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2009 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef LOCKEDQUEUE_H
+#define LOCKEDQUEUE_H
+
+#include <ace/Guard_T.h>
+#include <ace/Thread_Mutex.h>
+#include <deque>
+#include <assert.h>
+#include "Errors.h"
+
+namespace ACE_Based
+{
+
+ template <class T, class LockType, typename StorageType=std::deque<T> >
+ class LockedQueue
+ {
+
+ //! Serialize access to the Queue
+ LockType _lock;
+
+ //! Storage backing the queue
+ StorageType _queue;
+
+ //! Cancellation flag
+ volatile bool _canceled;
+
+ public:
+
+ //! Create a LockedQueue
+ LockedQueue() : _canceled(false) {}
+
+ //! Destroy a LockedQueue
+ virtual ~LockedQueue() { }
+
+ /**
+ * @see Queue::add(const T& item)
+ */
+ void add(const T& item)
+ {
+
+ ACE_Guard<LockType> g(_lock);
+
+ ASSERT(!_canceled);
+ // throw Cancellation_Exception();
+
+ _queue.push_back(item);
+
+ }
+
+ /**
+ * @see Queue::next()
+ */
+ T next()
+ {
+
+ ACE_Guard<LockType> g(_lock);
+
+ ASSERT (!_queue.empty() || !_canceled);
+ // throw Cancellation_Exception();
+
+ T item = _queue.front();
+ _queue.pop_front();
+
+ return item;
+
+ }
+
+ T front()
+ {
+ ACE_Guard<LockType> g(_lock);
+
+ ASSERT (!_queue.empty());
+ // throw NoSuchElement_Exception();
+
+ return _queue.front();
+ }
+
+ /**
+ * @see Queue::cancel()
+ */
+ void cancel()
+ {
+
+ ACE_Guard<LockType> g(_lock);
+
+ _canceled = true;
+
+ }
+
+ /**
+ * @see Queue::isCanceled()
+ */
+ bool isCanceled()
+ {
+
+ // Faster check since the queue will not become un-canceled
+ if(_canceled)
+ return true;
+
+ ACE_Guard<LockType> g(_lock);
+
+ return _canceled;
+
+ }
+
+ /**
+ * @see Queue::size()
+ */
+ size_t size()
+ {
+
+ ACE_Guard<LockType> g(_lock);
+ return _queue.size();
+
+ }
+
+ bool empty()
+ {
+
+ ACE_Guard<LockType> g(_lock);
+ return _queue.empty();
+ }
+
+ };
+
+}
+#endif
diff --git a/src/shared/Log.h b/src/shared/Log.h
index 654f3c0f04c..23555995020 100644
--- a/src/shared/Log.h
+++ b/src/shared/Log.h
@@ -82,7 +82,7 @@ enum ColorTypes
const int Colors = int(WHITE)+1;
-class Log : public Trinity::Singleton<Log, Trinity::ClassLevelLockable<Log, ZThread::FastMutex> >
+class Log : public Trinity::Singleton<Log, Trinity::ClassLevelLockable<Log, ACE_Thread_Mutex> >
{
friend class Trinity::OperatorNew<Log>;
Log();
diff --git a/src/shared/Makefile.am b/src/shared/Makefile.am
index 6b99351cb26..60af5b8a4b5 100644
--- a/src/shared/Makefile.am
+++ b/src/shared/Makefile.am
@@ -38,6 +38,7 @@ libmangosshared_a_SOURCES = \
Common.cpp \
Common.h \
Errors.h \
+ LockedQueue.h \
Log.cpp \
Log.h \
MemoryLeaks.cpp \
@@ -45,6 +46,8 @@ libmangosshared_a_SOURCES = \
ProgressBar.cpp \
ProgressBar.h \
Timer.h \
+ Threading.cpp \
+ Threading.h \
Util.cpp \
Util.h \
WorldPacket.h \
diff --git a/src/shared/MemoryLeaks.h b/src/shared/MemoryLeaks.h
index fcea1f557b1..c8b8fb8e1b1 100644
--- a/src/shared/MemoryLeaks.h
+++ b/src/shared/MemoryLeaks.h
@@ -31,9 +31,9 @@
//# include <stdlib.h>
//# include <crtdbg.h>
#else
-# define _CRTDBG_MAP_ALLOC
-# include <stdlib.h>
-# include <crtdbg.h>
+//# define _CRTDBG_MAP_ALLOC
+//# include <stdlib.h>
+//# include <crtdbg.h>
#endif
#endif
diff --git a/src/shared/Threading.cpp b/src/shared/Threading.cpp
new file mode 100644
index 00000000000..496e86353ca
--- /dev/null
+++ b/src/shared/Threading.cpp
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2009 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "Threading.h"
+#include <ace/OS_NS_unistd.h>
+#include <ace/Sched_Params.h>
+#include <vector>
+
+using namespace ACE_Based;
+
+ThreadPriority::ThreadPriority()
+{
+ for (int i = Idle; i < MAXPRIORITYNUM; ++i)
+ m_priority[i] = ACE_THR_PRI_OTHER_DEF;
+
+ m_priority[Idle] = ACE_Sched_Params::priority_min(ACE_SCHED_OTHER);
+ m_priority[Realtime] = ACE_Sched_Params::priority_max(ACE_SCHED_OTHER);
+
+ std::vector<int> _tmp;
+
+ ACE_Sched_Params::Policy _policy = ACE_SCHED_OTHER;
+ ACE_Sched_Priority_Iterator pr_iter(_policy);
+
+ while (pr_iter.more())
+ {
+ _tmp.push_back(pr_iter.priority());
+ pr_iter.next();
+ }
+
+ ASSERT (!_tmp.empty());
+
+ if(_tmp.size() >= MAXPRIORITYNUM)
+ {
+ const size_t max_pos = _tmp.size();
+ size_t min_pos = 1;
+ size_t norm_pos = 0;
+ for (size_t i = 0; i < max_pos; ++i)
+ {
+ if(_tmp[i] == ACE_THR_PRI_OTHER_DEF)
+ {
+ norm_pos = i + 1;
+ break;
+ }
+ }
+
+ //since we have only 7(seven) values in enum Priority
+ //and 3 we know already (Idle, Normal, Realtime) so
+ //we need to split each list [Idle...Normal] and [Normal...Realtime]
+ //into ¹ piesces
+ const size_t _divider = 4;
+ size_t _div = (norm_pos - min_pos) / _divider;
+ if(_div == 0)
+ _div = 1;
+
+ min_pos = (norm_pos - 1);
+
+ m_priority[Low] = _tmp[min_pos -= _div];
+ m_priority[Lowest] = _tmp[min_pos -= _div ];
+
+ _div = (max_pos - norm_pos) / _divider;
+ if(_div == 0)
+ _div = 1;
+
+ min_pos = norm_pos - 1;
+
+ m_priority[High] = _tmp[min_pos += _div];
+ m_priority[Highest] = _tmp[min_pos += _div];
+ }
+}
+
+int ThreadPriority::getPriority(Priority p) const
+{
+ if(p < Idle)
+ p = Idle;
+
+ if(p > Realtime)
+ p = Realtime;
+
+ return m_priority[p];
+}
+
+#define THREADFLAG (THR_NEW_LWP | THR_SCHED_DEFAULT| THR_JOINABLE)
+
+Thread::Thread() : m_task(0), m_iThreadId(0), m_hThreadHandle(0)
+{
+
+}
+
+Thread::Thread(Runnable& instance) : m_task(&instance), m_iThreadId(0), m_hThreadHandle(0)
+{
+ bool _start = start();
+ ASSERT (_start);
+}
+
+Thread::~Thread()
+{
+ //Wait();
+}
+
+//initialize Thread's class static member
+Thread::ThreadStorage Thread::m_ThreadStorage;
+ThreadPriority Thread::m_TpEnum;
+
+bool Thread::start()
+{
+ if(m_task == 0 || m_iThreadId != 0)
+ return false;
+
+ return (ACE_Thread::spawn(&Thread::ThreadTask, (void*)m_task, THREADFLAG, &m_iThreadId, &m_hThreadHandle) == 0);
+}
+
+bool Thread::wait()
+{
+ if(!m_hThreadHandle || !m_task)
+ return false;
+
+ ACE_THR_FUNC_RETURN _value = ACE_THR_FUNC_RETURN(-1);
+ int _res = ACE_Thread::join(m_hThreadHandle, &_value);
+
+ m_iThreadId = 0;
+ m_hThreadHandle = 0;
+
+ return (_res == 0);
+}
+
+void Thread::destroy()
+{
+ ACE_Thread::kill(m_iThreadId, -1);
+}
+
+void Thread::suspend()
+{
+ ACE_Thread::suspend(m_hThreadHandle);
+}
+
+void Thread::resume()
+{
+ ACE_Thread::resume(m_hThreadHandle);
+}
+
+ACE_THR_FUNC_RETURN Thread::ThreadTask(void * param)
+{
+ Runnable * _task = (Runnable*)param;
+ _task->run();
+
+ return (ACE_THR_FUNC_RETURN)0;
+}
+
+ACE_thread_t Thread::currentId()
+{
+ return ACE_Thread::self();
+}
+
+ACE_hthread_t Thread::currentHandle()
+{
+ ACE_hthread_t _handle;
+ ACE_Thread::self(_handle);
+
+ return _handle;
+}
+
+Thread * Thread::current()
+{
+ Thread * _thread = m_ThreadStorage.ts_object();
+ if(!_thread)
+ {
+ _thread = new Thread();
+ _thread->m_iThreadId = Thread::currentId();
+ _thread->m_hThreadHandle = Thread::currentHandle();
+
+ Thread * _oldValue = m_ThreadStorage.ts_object(_thread);
+ if(_oldValue)
+ delete _oldValue;
+ }
+
+ return _thread;
+}
+
+void Thread::setPriority(Priority type)
+{
+ int _priority = m_TpEnum.getPriority(type);
+ int _ok = ACE_Thread::setprio(m_hThreadHandle, _priority);
+ //remove this ASSERT in case you don't want to know is thread priority change was successful or not
+ ASSERT (_ok == 0);
+}
+
+void Thread::Sleep(unsigned long msecs)
+{
+ ACE_OS::sleep(ACE_Time_Value(0, 1000 * msecs));
+}
diff --git a/src/shared/Threading.h b/src/shared/Threading.h
new file mode 100644
index 00000000000..eac3c0e8efb
--- /dev/null
+++ b/src/shared/Threading.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2009 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef THREADING_H
+#define THREADING_H
+
+#include <ace/Thread.h>
+#include <ace/TSS_T.h>
+#include <assert.h>
+#include "Errors.h"
+
+namespace ACE_Based
+{
+
+ class Runnable
+ {
+ public:
+ virtual ~Runnable() {}
+ virtual void run() = 0;
+ };
+
+ enum Priority
+ {
+ Idle,
+ Lowest,
+ Low,
+ Normal,
+ High,
+ Highest,
+ Realtime,
+ };
+
+#define MAXPRIORITYNUM (Realtime + 1)
+
+ class ThreadPriority
+ {
+ public:
+ ThreadPriority();
+ int getPriority(Priority p) const;
+
+ private:
+ int m_priority[MAXPRIORITYNUM];
+ };
+
+ class Thread
+ {
+ public:
+ Thread();
+ Thread(Runnable& instance);
+ ~Thread();
+
+ bool start();
+ bool wait();
+ void destroy();
+
+ void suspend();
+ void resume();
+
+ void setPriority(Priority type);
+
+ static void Sleep(unsigned long msecs);
+ static ACE_thread_t currentId();
+ static ACE_hthread_t currentHandle();
+ static Thread * current();
+
+ private:
+ Thread(const Thread&);
+ Thread& operator=(const Thread&);
+
+ static ACE_THR_FUNC_RETURN ThreadTask(void * param);
+
+ ACE_thread_t m_iThreadId;
+ ACE_hthread_t m_hThreadHandle;
+ Runnable * m_task;
+
+ typedef ACE_TSS<Thread> ThreadStorage;
+ //global object - container for Thread class representation of every thread
+ static ThreadStorage m_ThreadStorage;
+ //use this object to determine current OS thread priority values mapped to enum Priority{}
+ static ThreadPriority m_TpEnum;
+ };
+
+}
+#endif
diff --git a/src/shared/Util.cpp b/src/shared/Util.cpp
index 767b65e441c..ac57fc3c9e9 100644
--- a/src/shared/Util.cpp
+++ b/src/shared/Util.cpp
@@ -23,40 +23,34 @@
#include "sockets/socket_include.h"
#include "utf8cpp/utf8.h"
#include "mersennetwister/MersenneTwister.h"
-#include "zthread/ThreadLocal.h"
+#include <ace/TSS_T.h>
-typedef ZThread::ThreadLocal<MTRand> MTRandTSS;
-
-/* NOTE: Not sure if static initialization is ok for TSS objects ,
- * as I see zthread uses custom implementation of the TSS
- * ,and in the consturctor there is no code ,so I suppose its ok
- * If its not ok ,change it to use singleton.
- */
+typedef ACE_TSS<MTRand> MTRandTSS;
static MTRandTSS mtRand;
int32 irand (int32 min, int32 max)
{
- return int32 (mtRand.get ().randInt (max - min)) + min;
+ return int32 (mtRand->randInt (max - min)) + min;
}
uint32 urand (uint32 min, uint32 max)
{
- return mtRand.get ().randInt (max - min) + min;
+ return mtRand->randInt (max - min) + min;
}
int32 rand32 ()
{
- return mtRand.get ().randInt ();
+ return mtRand->randInt ();
}
double rand_norm(void)
{
- return mtRand.get ().randExc ();
+ return mtRand->randExc ();
}
double rand_chance (void)
{
- return mtRand.get ().randExc (100.0);
+ return mtRand->randExc (100.0);
}
Tokens StrSplit(const std::string &src, const std::string &sep)
diff --git a/src/trinitycore/CliRunnable.cpp b/src/trinitycore/CliRunnable.cpp
index 91f37cd1b48..d53ee8c24be 100644
--- a/src/trinitycore/CliRunnable.cpp
+++ b/src/trinitycore/CliRunnable.cpp
@@ -155,7 +155,7 @@ bool ChatHandler::HandleCharacterDeleteCommand(const char* args)
}
/// Exit the realm
-bool ChatHandler::HandleServerExitCommand(const char* args)
+bool ChatHandler::HandleServerExitCommand(const char* /*args*/)
{
SendSysMessage(LANG_COMMAND_EXIT);
World::StopNow(SHUTDOWN_EXIT_CODE);
@@ -163,7 +163,7 @@ bool ChatHandler::HandleServerExitCommand(const char* args)
}
/// Display info on users currently in the realm
-bool ChatHandler::HandleAccountOnlineListCommand(const char* args)
+bool ChatHandler::HandleAccountOnlineListCommand(const char* /*args*/)
{
///- Get the list of accounts ID logged to the realm
QueryResult *resultDB = CharacterDatabase.Query("SELECT name,account FROM characters WHERE online > 0");
diff --git a/src/trinitycore/CliRunnable.h b/src/trinitycore/CliRunnable.h
index 20ff58f27ba..cf745bbb195 100644
--- a/src/trinitycore/CliRunnable.h
+++ b/src/trinitycore/CliRunnable.h
@@ -26,7 +26,7 @@
#define __CLIRUNNABLE_H
/// Command Line Interface handling thread
-class CliRunnable : public ZThread::Runnable
+class CliRunnable : public ACE_Based::Runnable
{
public:
void run();
diff --git a/src/trinitycore/Makefile.am b/src/trinitycore/Makefile.am
index 7e1cd086d3c..f0ac432dab1 100644
--- a/src/trinitycore/Makefile.am
+++ b/src/trinitycore/Makefile.am
@@ -35,8 +35,13 @@ trinity_worldd_SOURCES = \
WorldRunnable.h
## Link world daemon against the shared library
+<<<<<<< HEAD:src/mangosd/Makefile.am
trinity_worldd_LDADD = ../bindings/scripts/libtrinityscript.la ../game/libmangosgame.a ../shared/Database/libmangosdatabase.a ../shared/Config/libmangosconfig.a ../shared/Auth/libmangosauth.a ../shared/libmangosshared.a ../shared/vmap/libmangosvmaps.a ../framework/libmangosframework.a ../../dep/src/sockets/libmangossockets.a ../../dep/src/zthread/libZThread.la ../../dep/src/g3dlite/libg3dlite.a
trinity_worldd_LDFLAGS = -L../../dep/src/sockets -L../../dep/src/zthread -L../../dep/src/g3dlite -L../bindings/scripts/ -L$(libdir) $(TRINI_LIBS) -export-dynamic
+=======
+mangos_worldd_LDADD = ../bindings/universal/libmangosscript.la ../game/libmangosgame.a ../shared/Database/libmangosdatabase.a ../shared/Config/libmangosconfig.a ../shared/Auth/libmangosauth.a ../shared/libmangosshared.a ../shared/vmap/libmangosvmaps.a ../framework/libmangosframework.a ../../dep/src/sockets/libmangossockets.a ../../dep/src/g3dlite/libg3dlite.a
+mangos_worldd_LDFLAGS = -L../../dep/src/sockets -L../../dep/src/g3dlite -L../bindings/universal/ -L$(libdir) $(MANGOS_LIBS) -export-dynamic
+>>>>>>> 00c7d15a78b1dcdbf888b768c55424183b2231e4:src/mangosd/Makefile.am
## Additional files to include when running 'make dist'
# Include world daemon configuration
diff --git a/src/trinitycore/Master.cpp b/src/trinitycore/Master.cpp
index 6a952b936d3..2e2d75d5c3c 100644
--- a/src/trinitycore/Master.cpp
+++ b/src/trinitycore/Master.cpp
@@ -60,7 +60,7 @@ INSTANTIATE_SINGLETON_1( Master );
volatile uint32 Master::m_masterLoopCounter = 0;
-class FreezeDetectorRunnable : public ZThread::Runnable
+class FreezeDetectorRunnable : public ACE_Based::Runnable
{
public:
FreezeDetectorRunnable() { _delaytime = 0; }
@@ -79,7 +79,7 @@ public:
w_lastchange = 0;
while(!World::IsStopped())
{
- ZThread::Thread::sleep(1000);
+ ACE_Based::Thread::Sleep(1000);
uint32 curtime = getMSTime();
//DEBUG_LOG("anti-freeze: time=%u, counters=[%u; %u]",curtime,Master::m_masterLoopCounter,World::m_worldLoopCounter);
@@ -115,7 +115,7 @@ public:
}
};
-class RARunnable : public ZThread::Runnable
+class RARunnable : public ACE_Based::Runnable
{
public:
uint32 numLoops, loopCounter;
@@ -181,7 +181,7 @@ public:
{
while (!World::IsStopped())
{
- ZThread::Thread::sleep (static_cast<unsigned long> (socketSelecttime / 1000));
+ ACE_Based::Thread::Sleep (static_cast<unsigned long> (socketSelecttime / 1000));
checkping ();
}
}
@@ -237,8 +237,8 @@ int Master::Run()
_HookSignals();
///- Launch WorldRunnable thread
- ZThread::Thread t(new WorldRunnable);
- t.setPriority ((ZThread::Priority )2);
+ ACE_Based::Thread t(*new WorldRunnable);
+ t.setPriority ((ACE_Based::Priority )2);
// set server online
LoginDatabase.PExecute("UPDATE realmlist SET color = 0, population = 0 WHERE id = '%d'",realmID);
@@ -250,10 +250,10 @@ int Master::Run()
#endif
{
///- Launch CliRunnable thread
- ZThread::Thread td1(new CliRunnable);
+ ACE_Based::Thread td1(*new CliRunnable);
}
- ZThread::Thread td2(new RARunnable);
+ ACE_Based::Thread td2(*new RARunnable);
///- Handle affinity for multiple processors and process priority on Windows
#ifdef WIN32
@@ -314,8 +314,8 @@ int Master::Run()
{
FreezeDetectorRunnable *fdr = new FreezeDetectorRunnable();
fdr->SetDelayTime(freeze_delay*1000);
- ZThread::Thread t(fdr);
- t.setPriority(ZThread::High);
+ ACE_Based::Thread t(*fdr);
+ t.setPriority(ACE_Based::High);
}
///- Launch the world listener socket
diff --git a/src/trinitycore/WorldRunnable.cpp b/src/trinitycore/WorldRunnable.cpp
index e49e4ad74b8..bd4d3170c52 100644
--- a/src/trinitycore/WorldRunnable.cpp
+++ b/src/trinitycore/WorldRunnable.cpp
@@ -76,7 +76,7 @@ void WorldRunnable::run()
if (diff <= WORLD_SLEEP_CONST+prevSleepTime)
{
prevSleepTime = WORLD_SLEEP_CONST+prevSleepTime-diff;
- ZThread::Thread::sleep(prevSleepTime);
+ ACE_Based::Thread::Sleep(prevSleepTime);
}
else
prevSleepTime = 0;
diff --git a/src/trinitycore/WorldRunnable.h b/src/trinitycore/WorldRunnable.h
index 8df3a6a0c89..07ce246b04f 100644
--- a/src/trinitycore/WorldRunnable.h
+++ b/src/trinitycore/WorldRunnable.h
@@ -26,7 +26,7 @@
#define __WORLDRUNNABLE_H
/// Heartbeat thread for the World
-class WorldRunnable : public ZThread::Runnable
+class WorldRunnable : public ACE_Based::Runnable
{
public:
void run();
diff --git a/src/trinitycore/trinitycore.conf.dist b/src/trinitycore/trinitycore.conf.dist
index 018ddf378b5..2748c92529a 100644
--- a/src/trinitycore/trinitycore.conf.dist
+++ b/src/trinitycore/trinitycore.conf.dist
@@ -1006,6 +1006,16 @@ Channel.SilentlyGMJoin = 0
# GM starting level (1-100)
# Default: 1
#
+# GM.AllowInvite
+# Is GM accepting invites from players by default or not
+# Default: 0 (false)
+# 1 (true)
+#
+# GM.AllowFriend
+# Are players allowed to add GMs to their friend list
+# Default: 0 (false)
+# 1 (true)
+#
# GM.LowerSecurity
# Disallow a lower security member to interact with a higher one using commands
# Default: 0 (disable)
@@ -1027,6 +1037,8 @@ GM.InGMList = 0
GM.InWhoList = 0
GM.LogTrade = 1
GM.StartLevel = 80
+GM.AllowInvite = 0
+GM.AllowFriend = 0
GM.LowerSecurity = 0
GM.AllowAchievementGain = 1
diff --git a/src/trinityrealm/AuthSocket.cpp b/src/trinityrealm/AuthSocket.cpp
index c5c81593737..8c9eab653ec 100644
--- a/src/trinityrealm/AuthSocket.cpp
+++ b/src/trinityrealm/AuthSocket.cpp
@@ -173,7 +173,7 @@ typedef struct AuthHandler
#endif
/// Launch a thread to transfer a patch to the client
-class PatcherRunnable: public ZThread::Runnable
+class PatcherRunnable: public ACE_Based::Runnable
{
public:
PatcherRunnable(class AuthSocket *);
@@ -236,7 +236,8 @@ AuthSocket::AuthSocket(ISocketHandler &h) : TcpSocket(h)
/// Close patch file descriptor before leaving
AuthSocket::~AuthSocket()
{
- ZThread::Guard<ZThread::Mutex> g(patcherLock);
+ ACE_Guard<ACE_Thread_Mutex> g(patcherLock);
+
if(pPatch)
fclose(pPatch);
}
@@ -912,7 +913,7 @@ bool AuthSocket::_HandleXferResume()
ibuf.Read((char*)&start,sizeof(start));
fseek(pPatch,start,0);
- ZThread::Thread u(new PatcherRunnable(this));
+ ACE_Based::Thread u(*new PatcherRunnable(this));
return true;
}
@@ -924,7 +925,6 @@ bool AuthSocket::_HandleXferCancel()
///- Close and delete the socket
ibuf.Remove(1); //clear input buffer
- //ZThread::Thread::sleep(15);
SetCloseAndDelete();
return true;
@@ -946,8 +946,7 @@ bool AuthSocket::_HandleXferAccept()
ibuf.Remove(1); //clear input buffer
fseek(pPatch,0,0);
- ZThread::Thread u(new PatcherRunnable(this));
-
+ ACE_Based::Thread u(*new PatcherRunnable(this));
return true;
}
@@ -965,7 +964,8 @@ PatcherRunnable::PatcherRunnable(class AuthSocket * as)
/// Send content of patch file to the client
void PatcherRunnable::run()
{
- ZThread::Guard<ZThread::Mutex> g(mySocket->patcherLock);
+ ACE_Guard<ACE_Thread_Mutex> g(mySocket->patcherLock);
+
XFER_DATA_STRUCT xfdata;
xfdata.opcode = XFER_DATA;
@@ -974,7 +974,7 @@ void PatcherRunnable::run()
///- Wait until output buffer is reasonably empty
while(mySocket->Ready() && mySocket->IsLag())
{
- ZThread::Thread::sleep(1);
+ ACE_Based::Thread::Sleep(1);
}
///- And send content of the patch file to the client
xfdata.data_size=fread(&xfdata.data,1,ChunkSize,mySocket->pPatch);
diff --git a/src/trinityrealm/AuthSocket.h b/src/trinityrealm/AuthSocket.h
index 3cae54c7789..43b880a1e74 100644
--- a/src/trinityrealm/AuthSocket.h
+++ b/src/trinityrealm/AuthSocket.h
@@ -33,7 +33,6 @@
#include "sockets/Utility.h"
#include "sockets/Parse.h"
#include "sockets/Socket.h"
-#include "zthread/Mutex.h"
/// Handle login commands
class AuthSocket: public TcpSocket
@@ -61,7 +60,7 @@ class AuthSocket: public TcpSocket
void _SetVSFields(const std::string& rI);
FILE *pPatch;
- ZThread::Mutex patcherLock;
+ ACE_Thread_Mutex patcherLock;
bool IsLag();
private:
diff --git a/src/trinityrealm/Makefile.am b/src/trinityrealm/Makefile.am
index a14b50c847a..197d6ebf8c4 100644
--- a/src/trinityrealm/Makefile.am
+++ b/src/trinityrealm/Makefile.am
@@ -32,8 +32,13 @@ trinity_realmd_SOURCES = \
RealmList.h
## Link realm list daemon against the shared library
+<<<<<<< HEAD:src/realmd/Makefile.am
trinity_realmd_LDADD = ../shared/Database/libmangosdatabase.a ../shared/Config/libmangosconfig.a ../shared/Auth/libmangosauth.a ../shared/libmangosshared.a ../framework/libmangosframework.a ../../dep/src/sockets/libmangossockets.a ../../dep/src/zthread/libZThread.la
trinity_realmd_LDFLAGS = -L../../dep/src/sockets -L../../dep/src/zthread -L$(libdir) $(TRINI_LIBS)
+=======
+mangos_realmd_LDADD = ../shared/Database/libmangosdatabase.a ../shared/Config/libmangosconfig.a ../shared/Auth/libmangosauth.a ../shared/libmangosshared.a ../framework/libmangosframework.a ../../dep/src/sockets/libmangossockets.a
+mangos_realmd_LDFLAGS = -L../../dep/src/sockets -L$(libdir) $(MANGOS_LIBS)
+>>>>>>> 00c7d15a78b1dcdbf888b768c55424183b2231e4:src/realmd/Makefile.am
## Additional files to include when running 'make dist'
# Include realm list daemon configuration