aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/game/AI/CoreAI/GameObjectAI.h1
-rwxr-xr-xsrc/server/game/AI/CoreAI/UnitAI.h1
-rwxr-xr-xsrc/server/game/AI/EventAI/CreatureEventAI.cpp2
-rwxr-xr-xsrc/server/game/AI/EventAI/CreatureEventAI.h2
-rw-r--r--src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp1
-rw-r--r--src/server/game/AI/SmartScripts/SmartAI.cpp13
-rw-r--r--src/server/game/AI/SmartScripts/SmartAI.h2
-rw-r--r--src/server/game/AI/SmartScripts/SmartScript.cpp20
-rw-r--r--src/server/game/AI/SmartScripts/SmartScriptMgr.cpp10
-rw-r--r--src/server/game/AI/SmartScripts/SmartScriptMgr.h15
-rwxr-xr-xsrc/server/game/Achievements/AchievementMgr.cpp50
-rwxr-xr-xsrc/server/game/Achievements/AchievementMgr.h2
-rwxr-xr-xsrc/server/game/Chat/Channels/Channel.cpp12
-rwxr-xr-xsrc/server/game/Chat/Chat.cpp36
-rwxr-xr-xsrc/server/game/Chat/Commands/Level0.cpp13
-rwxr-xr-xsrc/server/game/Chat/Commands/TicketCommands.cpp61
-rwxr-xr-xsrc/server/game/Conditions/ConditionMgr.cpp5
-rwxr-xr-xsrc/server/game/DataStores/DBCEnums.h23
-rwxr-xr-xsrc/server/game/DataStores/DBCStructure.h5
-rwxr-xr-xsrc/server/game/DungeonFinding/LFGMgr.cpp2
-rwxr-xr-xsrc/server/game/Entities/Corpse/Corpse.cpp16
-rwxr-xr-xsrc/server/game/Entities/Corpse/Corpse.h2
-rwxr-xr-xsrc/server/game/Entities/Creature/Creature.cpp3
-rwxr-xr-xsrc/server/game/Entities/Creature/Creature.h5
-rwxr-xr-xsrc/server/game/Entities/Creature/TemporarySummon.cpp10
-rwxr-xr-xsrc/server/game/Entities/Creature/TemporarySummon.h6
-rwxr-xr-xsrc/server/game/Entities/DynamicObject/DynamicObject.cpp7
-rwxr-xr-xsrc/server/game/Entities/DynamicObject/DynamicObject.h4
-rwxr-xr-xsrc/server/game/Entities/GameObject/GameObject.cpp2
-rwxr-xr-xsrc/server/game/Entities/Object/Object.cpp34
-rwxr-xr-xsrc/server/game/Entities/Object/Object.h7
-rwxr-xr-xsrc/server/game/Entities/Pet/Pet.cpp5
-rwxr-xr-xsrc/server/game/Entities/Player/Player.cpp68
-rwxr-xr-xsrc/server/game/Entities/Player/Player.h7
-rwxr-xr-xsrc/server/game/Entities/Totem/Totem.cpp2
-rwxr-xr-xsrc/server/game/Entities/Transport/Transport.cpp4
-rwxr-xr-xsrc/server/game/Entities/Unit/Unit.cpp400
-rwxr-xr-xsrc/server/game/Entities/Unit/Unit.h6
-rwxr-xr-xsrc/server/game/Entities/Vehicle/Vehicle.cpp2
-rwxr-xr-xsrc/server/game/Events/GameEventMgr.cpp27
-rwxr-xr-xsrc/server/game/Events/GameEventMgr.h1
-rwxr-xr-xsrc/server/game/Globals/ObjectAccessor.h20
-rwxr-xr-xsrc/server/game/Globals/ObjectMgr.cpp19
-rwxr-xr-xsrc/server/game/Grids/Grid.h7
-rwxr-xr-xsrc/server/game/Grids/GridStates.cpp2
-rwxr-xr-xsrc/server/game/Grids/NGrid.h22
-rwxr-xr-xsrc/server/game/Grids/Notifiers/GridNotifiers.cpp6
-rwxr-xr-xsrc/server/game/Groups/Group.cpp1
-rwxr-xr-xsrc/server/game/Guilds/Guild.cpp1
-rwxr-xr-xsrc/server/game/Mails/Mail.cpp8
-rwxr-xr-xsrc/server/game/Maps/Map.cpp126
-rwxr-xr-xsrc/server/game/Maps/Map.h4
-rwxr-xr-xsrc/server/game/Miscellaneous/Language.h7
-rwxr-xr-xsrc/server/game/Miscellaneous/SharedDefines.h72
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp3
-rwxr-xr-xsrc/server/game/Server/Protocol/Handlers/AuctionHouseHandler.cpp15
-rwxr-xr-xsrc/server/game/Server/Protocol/Handlers/CharacterHandler.cpp157
-rwxr-xr-xsrc/server/game/Server/Protocol/Handlers/CombatHandler.cpp23
-rwxr-xr-xsrc/server/game/Server/Protocol/Handlers/ItemHandler.cpp2
-rwxr-xr-xsrc/server/game/Server/Protocol/Handlers/MiscHandler.cpp45
-rwxr-xr-xsrc/server/game/Server/Protocol/Handlers/MovementHandler.cpp2
-rwxr-xr-xsrc/server/game/Server/Protocol/Handlers/NPCHandler.cpp29
-rwxr-xr-xsrc/server/game/Server/Protocol/Handlers/PetitionsHandler.cpp12
-rwxr-xr-xsrc/server/game/Server/Protocol/Handlers/QueryHandler.cpp3
-rwxr-xr-xsrc/server/game/Server/WorldSession.cpp57
-rwxr-xr-xsrc/server/game/Server/WorldSession.h28
-rwxr-xr-xsrc/server/game/Spells/Auras/SpellAuraEffects.cpp31
-rwxr-xr-xsrc/server/game/Spells/Auras/SpellAuras.cpp1
-rwxr-xr-xsrc/server/game/Spells/Spell.cpp58
-rwxr-xr-xsrc/server/game/Spells/Spell.h2
-rwxr-xr-xsrc/server/game/Spells/SpellEffects.cpp177
-rw-r--r--src/server/game/Spells/SpellInfo.cpp13
-rwxr-xr-xsrc/server/game/Spells/SpellMgr.cpp4
-rwxr-xr-xsrc/server/game/World/World.h3
-rw-r--r--src/server/scripts/Commands/cs_modify.cpp7
-rw-r--r--src/server/scripts/Commands/cs_npc.cpp10
-rw-r--r--src/server/scripts/EasternKingdoms/ScarletEnclave/chapter2.cpp4
-rw-r--r--src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp6
-rw-r--r--src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp2
-rw-r--r--src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_mal_ganis.cpp8
-rw-r--r--src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.cpp2
-rw-r--r--src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/old_hillsbrad.cpp2
-rw-r--r--src/server/scripts/Kalimdor/durotar.cpp4
-rw-r--r--src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_anubarak.cpp208
-rw-r--r--src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_black_knight.cpp8
-rw-r--r--src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_grand_champions.cpp5
-rw-r--r--src/server/scripts/Northrend/DraktharonKeep/boss_tharon_ja.cpp3
-rw-r--r--src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp1
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp2
-rw-r--r--src/server/scripts/Northrend/Nexus/Oculus/boss_urom.cpp1
-rw-r--r--src/server/scripts/Northrend/Nexus/Oculus/boss_varos.cpp2
-rw-r--r--src/server/scripts/Northrend/Nexus/Oculus/oculus.cpp37
-rw-r--r--src/server/scripts/Northrend/Nexus/Oculus/oculus.h3
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp4
-rw-r--r--src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_ingvar_the_plunderer.cpp4
-rw-r--r--src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp4
-rw-r--r--src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp4
-rw-r--r--src/server/scripts/Outland/nagrand.cpp2
-rw-r--r--src/server/scripts/Spells/spell_generic.cpp53
-rw-r--r--src/server/scripts/World/go_scripts.cpp82
-rw-r--r--src/server/scripts/World/npcs_special.cpp179
-rwxr-xr-xsrc/server/shared/Database/DatabaseWorkerPool.h7
-rwxr-xr-xsrc/server/shared/Database/Implementation/CharacterDatabase.cpp9
-rwxr-xr-xsrc/server/shared/Database/Implementation/CharacterDatabase.h7
-rwxr-xr-xsrc/server/shared/Database/MySQLConnection.cpp7
-rwxr-xr-xsrc/server/shared/Database/MySQLConnection.h1
-rwxr-xr-xsrc/server/shared/Debugging/Errors.h3
-rwxr-xr-xsrc/server/shared/Threading/Callback.h121
-rwxr-xr-xsrc/server/shared/Threading/LockedQueue.h7
-rwxr-xr-xsrc/server/worldserver/CommandLine/CliRunnable.cpp2
-rwxr-xr-xsrc/server/worldserver/RemoteAccess/RASocket.cpp2
-rw-r--r--src/server/worldserver/worldserver.conf.dist3
112 files changed, 1627 insertions, 1043 deletions
diff --git a/src/server/game/AI/CoreAI/GameObjectAI.h b/src/server/game/AI/CoreAI/GameObjectAI.h
index 8d0e0508113..93cd3a6d237 100644
--- a/src/server/game/AI/CoreAI/GameObjectAI.h
+++ b/src/server/game/AI/CoreAI/GameObjectAI.h
@@ -49,6 +49,7 @@ class GameObjectAI
virtual uint32 GetDialogStatus(Player* /*player*/) {return 100;}
virtual void Destroyed(Player* /*player*/, uint32 /*eventId*/) {}
virtual void SetData(uint32 /*id*/, uint32 /*value*/) {}
+ virtual void OnGameEvent(bool /*start*/, uint16 /*eventId*/) {}
};
class NullGameObjectAI : public GameObjectAI
diff --git a/src/server/game/AI/CoreAI/UnitAI.h b/src/server/game/AI/CoreAI/UnitAI.h
index 3c16fe493b4..444dce0339e 100755
--- a/src/server/game/AI/CoreAI/UnitAI.h
+++ b/src/server/game/AI/CoreAI/UnitAI.h
@@ -267,6 +267,7 @@ class UnitAI
virtual void sQuestComplete(Player* /*player*/, Quest const* /*quest*/) {}
virtual void sQuestReward(Player* /*player*/, Quest const* /*quest*/, uint32 /*opt*/) {}
virtual bool sOnDummyEffect(Unit* /*caster*/, uint32 /*spellId*/, SpellEffIndex /*effIndex*/) { return false; }
+ virtual void sOnGameEvent(bool /*start*/, uint16 /*eventId*/) {}
};
class PlayerAI : public UnitAI
diff --git a/src/server/game/AI/EventAI/CreatureEventAI.cpp b/src/server/game/AI/EventAI/CreatureEventAI.cpp
index be0dd8c3679..1db6bbd550e 100755
--- a/src/server/game/AI/EventAI/CreatureEventAI.cpp
+++ b/src/server/game/AI/EventAI/CreatureEventAI.cpp
@@ -840,7 +840,7 @@ void CreatureEventAI::ProcessAction(CreatureEventAI_Action const& action, uint32
me->Mount(action.mount.modelId);
}
else
- me->Unmount();
+ me->Dismount();
break;
}
diff --git a/src/server/game/AI/EventAI/CreatureEventAI.h b/src/server/game/AI/EventAI/CreatureEventAI.h
index 2fc26bcbd3e..9cc8c8f9c4a 100755
--- a/src/server/game/AI/EventAI/CreatureEventAI.h
+++ b/src/server/game/AI/EventAI/CreatureEventAI.h
@@ -108,7 +108,7 @@ enum EventAI_ActionType
ACTION_T_SET_SHEATH = 40, // Sheath (0-passive, 1-melee, 2-ranged)
ACTION_T_FORCE_DESPAWN = 41, // No Params
ACTION_T_SET_INVINCIBILITY_HP_LEVEL = 42, // MinHpValue, format(0-flat, 1-percent from max health)
- ACTION_T_MOUNT_TO_ENTRY_OR_MODEL = 43, // Creature_template entry(param1) OR ModelId (param2) (or 0 for both to unmount)
+ ACTION_T_MOUNT_TO_ENTRY_OR_MODEL = 43, // Creature_template entry(param1) OR ModelId (param2) (or 0 for both to dismount)
ACTION_T_SET_PHASE_MASK = 97,
ACTION_T_SET_STAND_STATE = 98,
diff --git a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp
index 06c1570ccd9..c5f04d4ff5f 100644
--- a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp
+++ b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp
@@ -543,7 +543,6 @@ bool npc_escortAI::GetWaypointPosition(uint32 pointId, float& x, float& y, float
if (waypoints.empty())
return false;
- ScriptPointVector::const_iterator itrEnd = waypoints.end();
for (ScriptPointVector::const_iterator itr = waypoints.begin(); itr != waypoints.end(); ++itr)
{
if (itr->uiPointId == pointId)
diff --git a/src/server/game/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp
index afa7e9c2932..7dd793a302b 100644
--- a/src/server/game/AI/SmartScripts/SmartAI.cpp
+++ b/src/server/game/AI/SmartScripts/SmartAI.cpp
@@ -707,7 +707,7 @@ void SmartAI::SetRun(bool run)
me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
else
me->AddUnitMovementFlag(MOVEMENTFLAG_WALKING);
- me->SendMovementFlagUpdate();
+
mRun = run;
}
@@ -811,6 +811,12 @@ void SmartAI::SetScript9(SmartScriptHolder& e, uint32 entry, Unit* invoker)
GetScript()->mLastInvoker = invoker->GetGUID();
GetScript()->SetScript9(e, entry);
}
+
+void SmartAI::sOnGameEvent(bool start, uint16 eventId)
+{
+ GetScript()->ProcessEventsFor(start ? SMART_EVENT_GAME_EVENT_START : SMART_EVENT_GAME_EVENT_END, NULL, eventId);
+}
+
/*
SMART_EVENT_UPDATE_OOC
SMART_EVENT_SPELLHIT
@@ -913,6 +919,11 @@ void SmartGameObjectAI::SetScript9(SmartScriptHolder& e, uint32 entry, Unit* inv
GetScript()->SetScript9(e, entry);
}
+void SmartGameObjectAI::OnGameEvent(bool start, uint16 eventId)
+{
+ GetScript()->ProcessEventsFor(start ? SMART_EVENT_GAME_EVENT_START : SMART_EVENT_GAME_EVENT_END, NULL, eventId);
+}
+
class SmartTrigger : public AreaTriggerScript
{
public:
diff --git a/src/server/game/AI/SmartScripts/SmartAI.h b/src/server/game/AI/SmartScripts/SmartAI.h
index 8bb3bda8dd6..dc1f901d477 100644
--- a/src/server/game/AI/SmartScripts/SmartAI.h
+++ b/src/server/game/AI/SmartScripts/SmartAI.h
@@ -183,6 +183,7 @@ class SmartAI : public CreatureAI
//void sQuestComplete(Player* player, Quest const* quest);
void sQuestReward(Player* player, Quest const* quest, uint32 opt);
bool sOnDummyEffect(Unit* caster, uint32 spellId, SpellEffIndex effIndex);
+ void sOnGameEvent(bool start, uint16 eventId);
uint32 mEscortQuestID;
@@ -249,6 +250,7 @@ public:
void Destroyed(Player* player, uint32 eventId);
void SetData(uint32 id, uint32 value);
void SetScript9(SmartScriptHolder& e, uint32 entry, Unit* invoker);
+ void OnGameEvent(bool start, uint16 eventId);
protected:
GameObject* const go;
diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp
index c845f6110d6..34d465a5e7e 100644
--- a/src/server/game/AI/SmartScripts/SmartScript.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScript.cpp
@@ -994,7 +994,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
(*itr)->ToUnit()->Mount(e.action.morphOrMount.model);
}
else
- (*itr)->ToUnit()->Unmount();
+ (*itr)->ToUnit()->Dismount();
}
delete targets;
@@ -1493,7 +1493,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
else if (GameObject* goTarget = (*itr)->ToGameObject())
{
if (IsSmartGO(goTarget))
- CAST_AI(SmartGameObjectAI, target->AI())->SetScript9(e, e.action.timedActionList.id, GetLastInvoker());
+ CAST_AI(SmartGameObjectAI, goTarget->AI())->SetScript9(e, e.action.timedActionList.id, GetLastInvoker());
}
}
@@ -1610,7 +1610,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
else if (GameObject* goTarget = (*itr)->ToGameObject())
{
if (IsSmartGO(goTarget))
- CAST_AI(SmartGameObjectAI, target->AI())->SetScript9(e, id, GetLastInvoker());
+ CAST_AI(SmartGameObjectAI, goTarget->AI())->SetScript9(e, id, GetLastInvoker());
}
}
@@ -1640,7 +1640,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
else if (GameObject* goTarget = (*itr)->ToGameObject())
{
if (IsSmartGO(goTarget))
- CAST_AI(SmartGameObjectAI, target->AI())->SetScript9(e, id, GetLastInvoker());
+ CAST_AI(SmartGameObjectAI, goTarget->AI())->SetScript9(e, id, GetLastInvoker());
}
}
@@ -2595,6 +2595,14 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui
ProcessAction(e, unit, var0, var1);
break;
}
+ case SMART_EVENT_GAME_EVENT_START:
+ case SMART_EVENT_GAME_EVENT_END:
+ {
+ if (e.event.gameEvent.gameEventId != var0)
+ return;
+ ProcessAction(e, NULL, var0);
+ break;
+ }
default:
sLog->outErrorDb("SmartScript::ProcessEvent: Unhandled Event type %u", e.GetEventType());
break;
@@ -2996,7 +3004,9 @@ void SmartScript::SetScript9(SmartScriptHolder& e, uint32 entry)
mResumeActionList = e.action.timedActionList.dontResume ? false : true;
InitTimer((*i));
}
-}Unit* SmartScript::GetLastInvoker()
+}
+
+Unit* SmartScript::GetLastInvoker()
{
return ObjectAccessor::FindUnit(mLastInvoker);
}
diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
index 011ed75205d..1df5849ca75 100644
--- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
@@ -26,6 +26,7 @@
#include "CellImpl.h"
#include "InstanceScript.h"
#include "ScriptedCreature.h"
+#include "GameEventMgr.h"
#include "SmartScriptMgr.h"
@@ -466,6 +467,14 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
if (!IsMinMaxValid(e, e.event.behindTarget.cooldownMin, e.event.behindTarget.cooldownMax))
return false;
break;
+ case SMART_EVENT_GAME_EVENT_START:
+ case SMART_EVENT_GAME_EVENT_END:
+ {
+ GameEventMgr::GameEventDataMap const& events = sGameEventMgr->GetEventMap();
+ if (e.event.gameEvent.gameEventId >= events.size() || !events[e.event.gameEvent.gameEventId].isValid())
+ return false;
+ break;
+ }
case SMART_EVENT_TIMED_EVENT_TRIGGERED:
case SMART_EVENT_INSTANCE_PLAYER_ENTER:
case SMART_EVENT_TRANSPORT_RELOCATE:
@@ -492,7 +501,6 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
case SMART_EVENT_WAYPOINT_RESUMED:
case SMART_EVENT_WAYPOINT_STOPPED:
case SMART_EVENT_WAYPOINT_ENDED:
- case SMART_ACTION_PLAYMOVIE:
case SMART_EVENT_GOSSIP_SELECT:
case SMART_EVENT_GOSSIP_HELLO:
case SMART_EVENT_JUST_CREATED:
diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h
index e80da52ccd3..e8ec80672fc 100644
--- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h
+++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h
@@ -152,8 +152,10 @@ enum SMART_EVENT
SMART_EVENT_FOLLOW_COMPLETED = 65, //1 // none
SMART_EVENT_DUMMY_EFFECT = 66, //1 // spellId, effectIndex
SMART_EVENT_IS_BEHIND_TARGET = 67, //1 // cooldownMin, CooldownMax
+ SMART_EVENT_GAME_EVENT_START = 68, //1 // game_event.Entry
+ SMART_EVENT_GAME_EVENT_END = 69, //1 // game_event.Entry
- SMART_EVENT_END = 68,
+ SMART_EVENT_END = 70,
};
struct SmartEvent
@@ -338,6 +340,11 @@ struct SmartEvent
uint32 cooldownMax;
} behindTarget;
+ struct
+ {
+ uint32 gameEventId;
+ } gameEvent;
+
struct
{
uint32 param1;
@@ -401,7 +408,7 @@ enum SMART_ACTION
SMART_ACTION_SET_SHEATH = 40, // Sheath (0-unarmed, 1-melee, 2-ranged)
SMART_ACTION_FORCE_DESPAWN = 41, // timer
SMART_ACTION_SET_INVINCIBILITY_HP_LEVEL = 42, // MinHpValue(+pct, -flat)
- SMART_ACTION_MOUNT_TO_ENTRY_OR_MODEL = 43, // Creature_template entry(param1) OR ModelId (param2) (or 0 for both to unmount)
+ SMART_ACTION_MOUNT_TO_ENTRY_OR_MODEL = 43, // Creature_template entry(param1) OR ModelId (param2) (or 0 for both to dismount)
SMART_ACTION_SET_INGAME_PHASE_MASK = 44, // mask
SMART_ACTION_SET_DATA = 45, // Field, Data (only creature TODO)
@@ -1128,7 +1135,9 @@ const uint32 SmartAIEventMask[SMART_EVENT_END][2] =
{SMART_EVENT_GOSSIP_HELLO, SMART_SCRIPT_TYPE_MASK_CREATURE + SMART_SCRIPT_TYPE_MASK_GAMEOBJECT },
{SMART_EVENT_FOLLOW_COMPLETED, SMART_SCRIPT_TYPE_MASK_CREATURE },
{SMART_EVENT_DUMMY_EFFECT, SMART_SCRIPT_TYPE_MASK_SPELL },
- {SMART_EVENT_IS_BEHIND_TARGET, SMART_SCRIPT_TYPE_MASK_CREATURE }
+ {SMART_EVENT_IS_BEHIND_TARGET, SMART_SCRIPT_TYPE_MASK_CREATURE },
+ {SMART_EVENT_GAME_EVENT_START, SMART_SCRIPT_TYPE_MASK_CREATURE + SMART_SCRIPT_TYPE_MASK_GAMEOBJECT },
+ {SMART_EVENT_GAME_EVENT_END, SMART_SCRIPT_TYPE_MASK_CREATURE + SMART_SCRIPT_TYPE_MASK_GAMEOBJECT },
};
diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp
index 8967446f199..d22f4b94caa 100755
--- a/src/server/game/Achievements/AchievementMgr.cpp
+++ b/src/server/game/Achievements/AchievementMgr.cpp
@@ -102,6 +102,7 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria)
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST: // only Children's Week achievements
case ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM: // only Children's Week achievements
case ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS:
+ case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL:
break;
default:
if (dataType != ACHIEVEMENT_CRITERIA_DATA_TYPE_SCRIPT)
@@ -135,13 +136,13 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria)
}
if (classRace.class_id && ((1 << (classRace.class_id-1)) & CLASSMASK_ALL_PLAYABLE) == 0)
{
- sLog->outErrorDb("Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_CREATURE (%u) has non-existing class in value1 (%u), ignored.",
+ sLog->outErrorDb("Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_PLAYER_CLASS_RACE (%u) has non-existing class in value1 (%u), ignored.",
criteria->ID, criteria->requiredType, dataType, classRace.class_id);
return false;
}
if (classRace.race_id && ((1 << (classRace.race_id-1)) & RACEMASK_ALL_PLAYABLE) == 0)
{
- sLog->outErrorDb("Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_CREATURE (%u) has non-existing race in value2 (%u), ignored.",
+ sLog->outErrorDb("Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_PLAYER_CLASS_RACE (%u) has non-existing race in value2 (%u), ignored.",
criteria->ID, criteria->requiredType, dataType, classRace.race_id);
return false;
}
@@ -450,7 +451,7 @@ void AchievementMgr::ResetAchievementCriteria(AchievementCriteriaTypes type, uin
continue;
// don't update already completed criteria if not forced or achievement already complete
- if ((IsCompletedCriteria(achievementCriteria, achievement) && !evenIfCriteriaComplete) || HasAchieved(achievement))
+ if ((IsCompletedCriteria(achievementCriteria, achievement) && !evenIfCriteriaComplete) || HasAchieved(achievement->ID))
continue;
for (uint8 j = 0; j < MAX_CRITERIA_REQUIREMENTS; ++j)
@@ -846,6 +847,9 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
break;
}
case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL:
+ if (AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria))
+ if (!data->Meets(GetPlayer(), unit))
+ continue;
SetCriteriaProgress(achievementCriteria, GetPlayer()->getLevel());
break;
case ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL:
@@ -1065,14 +1069,9 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
continue;
}
- if (achievement->ID == 1282)
- {
- // those requirements couldn't be found in the dbc
- AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria);
- if (!data || !data->Meets(GetPlayer(), unit))
+ if (AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria))
+ if (!data->Meets(GetPlayer(), unit))
continue;
- break;
- }
SetCriteriaProgress(achievementCriteria, 1);
break;
@@ -1597,9 +1596,6 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
}
}
-static const uint32 achievIdByClass[MAX_CLASSES] = { 0, 459, 465, 462, 458, 464, 461, 467, 460, 463, 0, 466 };
-static const uint32 achievIdByRace[MAX_RACES] = { 0, 1408, 1410, 1407, 1409, 1413, 1411, 1404, 1412, 0, 1405, 1406 };
-
bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achievementCriteria, AchievementEntry const* achievement)
{
// counter can never complete
@@ -1624,20 +1620,7 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve
case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE:
return progress->counter >= achievementCriteria->kill_creature.creatureCount;
case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL:
- {
- // skip wrong class achievements
- for (int i = 1; i < MAX_CLASSES; ++i)
- if (achievIdByClass[i] == achievement->ID && i != GetPlayer()->getClass())
- return false;
-
- // skip wrong race achievements
- for (int i = 1; i < MAX_RACES; ++i)
- if (achievIdByRace[i] == achievement->ID && i != GetPlayer()->getRace())
- return false;
-
- // appropriate class/race or not class/race specific
return progress->counter >= achievementCriteria->reach_level.level;
- }
case ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL:
return progress->counter >= achievementCriteria->reach_skill_level.skillLevel;
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT:
@@ -1778,7 +1761,7 @@ void AchievementMgr::CompletedCriteriaFor(AchievementEntry const* achievement)
return;
// already completed and stored
- if (HasAchieved(achievement))
+ if (HasAchieved(achievement->ID))
return;
if (IsCompletedAchievement(achievement))
@@ -2012,7 +1995,7 @@ void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement)
if (m_player->isGameMaster())
return;
- if (achievement->flags & ACHIEVEMENT_FLAG_COUNTER || HasAchieved(achievement))
+ if (achievement->flags & ACHIEVEMENT_FLAG_COUNTER || HasAchieved(achievement->ID))
return;
SendAchievementEarned(achievement);
@@ -2127,9 +2110,9 @@ void AchievementMgr::BuildAllDataPacket(WorldPacket* data) const
*data << int32(-1);
}
-bool AchievementMgr::HasAchieved(AchievementEntry const* achievement) const
+bool AchievementMgr::HasAchieved(uint32 achievementId) const
{
- return m_completedAchievements.find(achievement->ID) != m_completedAchievements.end();
+ return m_completedAchievements.find(achievementId) != m_completedAchievements.end();
}
bool AchievementMgr::CanUpdateCriteria(AchievementCriteriaEntry const* criteria, AchievementEntry const* achievement)
@@ -2393,15 +2376,16 @@ void AchievementGlobalMgr::LoadCompletedAchievements()
Field* fields = result->Fetch();
uint32 achievement_id = fields[0].GetUInt32();
- if (!sAchievementStore.LookupEntry(achievement_id))
+ const AchievementEntry* achievement = sAchievementStore.LookupEntry(achievement_id);
+ if (!achievement)
{
// we will remove not existed achievement for all characters
sLog->outError("Non-existing 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);
+ else if (achievement->flags & (ACHIEVEMENT_FLAG_REALM_FIRST_REACH | ACHIEVEMENT_FLAG_REALM_FIRST_KILL))
+ m_allCompletedAchievements.insert(achievement_id);
} while (result->NextRow());
sLog->outString(">> Loaded %lu completed achievements in %u ms", (unsigned long)m_allCompletedAchievements.size(), GetMSTimeDiffToNow(oldMSTime));
diff --git a/src/server/game/Achievements/AchievementMgr.h b/src/server/game/Achievements/AchievementMgr.h
index 7f66565622f..f88be974c9d 100755
--- a/src/server/game/Achievements/AchievementMgr.h
+++ b/src/server/game/Achievements/AchievementMgr.h
@@ -257,7 +257,7 @@ class AchievementMgr
void CheckAllAchievementCriteria();
void SendAllAchievementData() const;
void SendRespondInspectAchievements(Player* player) const;
- bool HasAchieved(AchievementEntry const* achievement) const;
+ bool HasAchieved(uint32 achievementId) const;
Player* GetPlayer() const { return m_player; }
void UpdateTimedAchievements(uint32 timeDiff);
void StartTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry, uint32 timeLost = 0);
diff --git a/src/server/game/Chat/Channels/Channel.cpp b/src/server/game/Chat/Channels/Channel.cpp
index 1968de70f46..244c05ec0ad 100755
--- a/src/server/game/Chat/Channels/Channel.cpp
+++ b/src/server/game/Chat/Channels/Channel.cpp
@@ -310,18 +310,22 @@ void Channel::KickOrBan(uint64 good, const char *badname, bool ban)
bool changeowner = (m_ownerGUID == bad->GetGUID());
WorldPacket data;
+ bool notify = !(AccountMgr::IsGMAccount(sec) && sWorld->getBoolConfig(CONFIG_SILENTLY_GM_JOIN_TO_CHANNEL));
if (ban && !IsBanned(bad->GetGUID()))
{
banned.insert(bad->GetGUID());
- MakePlayerBanned(&data, bad->GetGUID(), good);
-
UpdateChannelInDB();
+
+ if (notify)
+ MakePlayerBanned(&data, bad->GetGUID(), good);
}
- else
+ else if (notify)
MakePlayerKicked(&data, bad->GetGUID(), good);
- SendToAll(&data);
+ if (notify)
+ SendToAll(&data);
+
players.erase(bad->GetGUID());
bad->LeftChannel(this);
diff --git a/src/server/game/Chat/Chat.cpp b/src/server/game/Chat/Chat.cpp
index be43862eaea..185ac487481 100755
--- a/src/server/game/Chat/Chat.cpp
+++ b/src/server/game/Chat/Chat.cpp
@@ -303,29 +303,29 @@ ChatCommand* ChatHandler::getCommandTable()
static ChatCommand ticketResponseCommandTable[] =
{
- { "append", SEC_MODERATOR, false, OldHandler<&ChatHandler::HandleGMTicketResponseAppendCommand>, "", NULL },
- { "appendln", SEC_MODERATOR, false, OldHandler<&ChatHandler::HandleGMTicketResponseAppendLnCommand>, "", NULL },
+ { "append", SEC_MODERATOR, true, OldHandler<&ChatHandler::HandleGMTicketResponseAppendCommand>, "", NULL },
+ { "appendln", SEC_MODERATOR, true, OldHandler<&ChatHandler::HandleGMTicketResponseAppendLnCommand>, "", NULL },
{ NULL, 0, false, NULL, "", NULL }
};
static ChatCommand ticketCommandTable[] =
{
- { "list", SEC_MODERATOR, false, OldHandler<&ChatHandler::HandleGMTicketListCommand>, "", NULL },
- { "onlinelist", SEC_MODERATOR, false, OldHandler<&ChatHandler::HandleGMTicketListOnlineCommand>, "", NULL },
- { "viewname", SEC_MODERATOR, false, OldHandler<&ChatHandler::HandleGMTicketGetByNameCommand>, "", NULL },
- { "viewid", SEC_MODERATOR, false, OldHandler<&ChatHandler::HandleGMTicketGetByIdCommand>, "", NULL },
- { "close", SEC_MODERATOR, false, OldHandler<&ChatHandler::HandleGMTicketCloseByIdCommand>, "", NULL },
- { "closedlist", SEC_MODERATOR, false, OldHandler<&ChatHandler::HandleGMTicketListClosedCommand>, "", NULL },
- { "escalatedlist", SEC_GAMEMASTER, false, OldHandler<&ChatHandler::HandleGMTicketListEscalatedCommand>, "", NULL },
- { "delete", SEC_ADMINISTRATOR, false, OldHandler<&ChatHandler::HandleGMTicketDeleteByIdCommand>, "", NULL },
- { "reset", SEC_ADMINISTRATOR, false, OldHandler<&ChatHandler::HandleGMTicketResetCommand>, "", NULL },
- { "assign", SEC_GAMEMASTER, false, OldHandler<&ChatHandler::HandleGMTicketAssignToCommand>, "", NULL },
- { "unassign", SEC_GAMEMASTER, false, OldHandler<&ChatHandler::HandleGMTicketUnAssignCommand>, "", NULL },
- { "comment", SEC_MODERATOR, false, OldHandler<&ChatHandler::HandleGMTicketCommentCommand>, "", NULL },
- { "togglesystem", SEC_ADMINISTRATOR, false, OldHandler<&ChatHandler::HandleToggleGMTicketSystem>, "", NULL },
- { "escalate", SEC_MODERATOR, false, OldHandler<&ChatHandler::HandleGMTicketEscalateCommand>, "", NULL },
- { "response", SEC_MODERATOR, false, NULL, "", ticketResponseCommandTable },
- { "complete", SEC_MODERATOR, false, OldHandler<&ChatHandler::HandleGMTicketCompleteCommand>, "", NULL },
+ { "list", SEC_MODERATOR, true, OldHandler<&ChatHandler::HandleGMTicketListCommand>, "", NULL },
+ { "onlinelist", SEC_MODERATOR, true, OldHandler<&ChatHandler::HandleGMTicketListOnlineCommand>, "", NULL },
+ { "viewname", SEC_MODERATOR, true, OldHandler<&ChatHandler::HandleGMTicketGetByNameCommand>, "", NULL },
+ { "viewid", SEC_MODERATOR, true, OldHandler<&ChatHandler::HandleGMTicketGetByIdCommand>, "", NULL },
+ { "close", SEC_MODERATOR, true, OldHandler<&ChatHandler::HandleGMTicketCloseByIdCommand>, "", NULL },
+ { "closedlist", SEC_MODERATOR, true, OldHandler<&ChatHandler::HandleGMTicketListClosedCommand>, "", NULL },
+ { "escalatedlist", SEC_GAMEMASTER, true, OldHandler<&ChatHandler::HandleGMTicketListEscalatedCommand>, "", NULL },
+ { "delete", SEC_ADMINISTRATOR, true, OldHandler<&ChatHandler::HandleGMTicketDeleteByIdCommand>, "", NULL },
+ { "reset", SEC_ADMINISTRATOR, true, OldHandler<&ChatHandler::HandleGMTicketResetCommand>, "", NULL },
+ { "assign", SEC_GAMEMASTER, true, OldHandler<&ChatHandler::HandleGMTicketAssignToCommand>, "", NULL },
+ { "unassign", SEC_GAMEMASTER, true, OldHandler<&ChatHandler::HandleGMTicketUnAssignCommand>, "", NULL },
+ { "comment", SEC_MODERATOR, true, OldHandler<&ChatHandler::HandleGMTicketCommentCommand>, "", NULL },
+ { "togglesystem", SEC_ADMINISTRATOR, true, OldHandler<&ChatHandler::HandleToggleGMTicketSystem>, "", NULL },
+ { "escalate", SEC_MODERATOR, true, OldHandler<&ChatHandler::HandleGMTicketEscalateCommand>, "", NULL },
+ { "response", SEC_MODERATOR, true, NULL, "", ticketResponseCommandTable },
+ { "complete", SEC_MODERATOR, true, OldHandler<&ChatHandler::HandleGMTicketCompleteCommand>, "", NULL },
{ NULL, 0, false, NULL, "", NULL }
};
diff --git a/src/server/game/Chat/Commands/Level0.cpp b/src/server/game/Chat/Commands/Level0.cpp
index 338ad49463e..7ff7a82bf58 100755
--- a/src/server/game/Chat/Commands/Level0.cpp
+++ b/src/server/game/Chat/Commands/Level0.cpp
@@ -84,8 +84,8 @@ bool ChatHandler::HandleStartCommand(const char* /*args*/)
bool ChatHandler::HandleServerInfoCommand(const char* /*args*/)
{
- uint32 PlayersNum = sWorld->GetPlayerCount();
- uint32 MaxPlayersNum = sWorld->GetMaxPlayerCount();
+ uint32 playersNum = sWorld->GetPlayerCount();
+ uint32 maxPlayersNum = sWorld->GetMaxPlayerCount();
uint32 activeClientsNum = sWorld->GetActiveSessionCount();
uint32 queuedClientsNum = sWorld->GetQueuedSessionCount();
uint32 maxActiveClientsNum = sWorld->GetMaxActiveSessionCount();
@@ -94,10 +94,13 @@ bool ChatHandler::HandleServerInfoCommand(const char* /*args*/)
uint32 updateTime = sWorld->GetUpdateTime();
SendSysMessage(_FULLVERSION);
- PSendSysMessage(LANG_CONNECTED_PLAYERS, PlayersNum, MaxPlayersNum);
+ PSendSysMessage(LANG_CONNECTED_PLAYERS, playersNum, maxPlayersNum);
PSendSysMessage(LANG_CONNECTED_USERS, activeClientsNum, maxActiveClientsNum, queuedClientsNum, maxQueuedClientsNum);
PSendSysMessage(LANG_UPTIME, uptime.c_str());
- PSendSysMessage("Update time diff: %u.", updateTime);
+ PSendSysMessage(LANG_UPDATE_DIFF, updateTime);
+ //! Can't use sWorld->ShutdownMsg here in case of console command
+ if (sWorld->IsShuttingDown())
+ PSendSysMessage(LANG_SHUTDOWN_TIMELEFT, secsToTimeString(sWorld->GetShutDownTimeLeft()).c_str());
return true;
}
@@ -119,7 +122,7 @@ bool ChatHandler::HandleDismountCommand(const char* /*args*/)
return false;
}
- m_session->GetPlayer()->Unmount();
+ m_session->GetPlayer()->Dismount();
m_session->GetPlayer()->RemoveAurasByType(SPELL_AURA_MOUNTED);
return true;
}
diff --git a/src/server/game/Chat/Commands/TicketCommands.cpp b/src/server/game/Chat/Commands/TicketCommands.cpp
index 7caf63aac2b..d38da9eb97c 100755
--- a/src/server/game/Chat/Commands/TicketCommands.cpp
+++ b/src/server/game/Chat/Commands/TicketCommands.cpp
@@ -85,12 +85,14 @@ bool ChatHandler::HandleGMTicketGetByNameCommand(const char* args)
guid = player->GetGUID();
else
guid = sObjectMgr->GetPlayerGUIDByName(name);
+
// Target must exist
if (!guid)
{
SendSysMessage(LANG_NO_PLAYERS_FOUND);
return true;
}
+
// Ticket must exist
GmTicket *ticket = sTicketMgr->GetTicketByPlayer(guid);
if (!ticket)
@@ -119,27 +121,32 @@ bool ChatHandler::HandleGMTicketCloseByIdCommand(const char* args)
SendSysMessage(LANG_COMMAND_TICKETNOTEXIST);
return true;
}
- // Ticket must be assigned to player, who tries to close it.
- uint64 guid = m_session->GetPlayer()->GetGUID();
- if (ticket->IsAssignedNotTo(guid))
+
+ // Ticket should be assigned to the player who tries to close it.
+ // Console can override though
+ Player* player = m_session ? m_session->GetPlayer() : NULL;
+ if (player && ticket->IsAssignedNotTo(player->GetGUID()))
{
PSendSysMessage(LANG_COMMAND_TICKETCANNOTCLOSE, ticket->GetId());
return true;
}
- sTicketMgr->CloseTicket(ticket->GetId(), guid);
+
+ sTicketMgr->CloseTicket(ticket->GetId(), player ? player->GetGUID() : -1);
sTicketMgr->UpdateLastChange();
- std::string msg = ticket->FormatMessageString(*this, m_session->GetPlayer()->GetName(), NULL, NULL, NULL);
+ std::string msg = ticket->FormatMessageString(*this, player ? player->GetName() : "Console", NULL, NULL, NULL);
SendGlobalGMSysMessage(msg.c_str());
// Inform player, who submitted this ticket, that it is closed
- if (Player* player = ticket->GetPlayer())
- if (player->IsInWorld())
+ if (Player* submitter = ticket->GetPlayer())
+ {
+ if (submitter->IsInWorld())
{
WorldPacket data(SMSG_GMTICKET_DELETETICKET, 4);
data << uint32(GMTICKET_RESPONSE_TICKET_DELETED);
- player->GetSession()->SendPacket(&data);
+ submitter->GetSession()->SendPacket(&data);
}
+ }
return true;
}
@@ -170,25 +177,30 @@ bool ChatHandler::HandleGMTicketAssignToCommand(const char* args)
uint64 targetGuid = sObjectMgr->GetPlayerGUIDByName(target.c_str());
uint64 targetAccId = sObjectMgr->GetPlayerAccountIdByGUID(targetGuid);
uint32 targetGmLevel = AccountMgr::GetSecurity(targetAccId, realmID);
+
// Target must exist and have administrative rights
if (!targetGuid || AccountMgr::IsPlayerAccount(targetGmLevel))
{
SendSysMessage(LANG_COMMAND_TICKETASSIGNERROR_A);
return true;
}
+
// If already assigned, leave
if (ticket->IsAssignedTo(targetGuid))
{
PSendSysMessage(LANG_COMMAND_TICKETASSIGNERROR_B, ticket->GetId());
return true;
}
+
// If assigned to different player other than current, leave
- Player* player = m_session->GetPlayer();
- if (ticket->IsAssignedNotTo(player->GetGUID()))
+ //! Console can override though
+ Player* player = m_session ? m_session->GetPlayer() : NULL;
+ if (player && ticket->IsAssignedNotTo(player->GetGUID()))
{
PSendSysMessage(LANG_COMMAND_TICKETALREADYASSIGNED, ticket->GetId(), target.c_str());
return true;
}
+
// Assign ticket
SQLTransaction trans = SQLTransaction(NULL);
ticket->SetAssignedTo(targetGuid, AccountMgr::IsAdminAccount(targetGmLevel));
@@ -218,6 +230,7 @@ bool ChatHandler::HandleGMTicketUnAssignCommand(const char* args)
PSendSysMessage(LANG_COMMAND_TICKETNOTASSIGNED, ticket->GetId());
return true;
}
+
// Get security level of player, whom this ticket is assigned to
uint32 security = SEC_PLAYER;
Player* assignedPlayer = ticket->GetAssignedPlayer();
@@ -229,9 +242,11 @@ bool ChatHandler::HandleGMTicketUnAssignCommand(const char* args)
uint32 accountId = sObjectMgr->GetPlayerAccountIdByGUID(guid);
security = AccountMgr::GetSecurity(accountId, realmID);
}
+
// Check security
- Player* player = m_session->GetPlayer();
- if (security > uint32(player->GetSession()->GetSecurity()))
+ //! If no m_session present it means we're issuing this command from the console
+ uint32 mySecurity = m_session ? m_session->GetSecurity() : SEC_CONSOLE;
+ if (security > mySecurity)
{
SendSysMessage(LANG_COMMAND_TICKETUNASSIGNSECURITY);
return true;
@@ -242,7 +257,8 @@ bool ChatHandler::HandleGMTicketUnAssignCommand(const char* args)
ticket->SaveToDB(trans);
sTicketMgr->UpdateLastChange();
- std::string msg = ticket->FormatMessageString(*this, NULL, ticket->GetAssignedToName().c_str(), player->GetName(), NULL);
+ std::string msg = ticket->FormatMessageString(*this, NULL, ticket->GetAssignedToName().c_str(),
+ m_session ? m_session->GetPlayer()->GetName() : "Console", NULL);
SendGlobalGMSysMessage(msg.c_str());
return true;
}
@@ -265,9 +281,11 @@ bool ChatHandler::HandleGMTicketCommentCommand(const char* args)
PSendSysMessage(LANG_COMMAND_TICKETNOTEXIST);
return true;
}
+
// Cannot comment ticket assigned to someone else
- Player* player = m_session->GetPlayer();
- if (ticket->IsAssignedNotTo(player->GetGUID()))
+ //! Console excluded
+ Player* player = m_session ? m_session->GetPlayer() : NULL;
+ if (player && ticket->IsAssignedNotTo(player->GetGUID()))
{
PSendSysMessage(LANG_COMMAND_TICKETALREADYASSIGNED, ticket->GetId());
return true;
@@ -279,7 +297,7 @@ bool ChatHandler::HandleGMTicketCommentCommand(const char* args)
sTicketMgr->UpdateLastChange();
std::string msg = ticket->FormatMessageString(*this, NULL, ticket->GetAssignedToName().c_str(), NULL, NULL);
- msg += PGetParseString(LANG_COMMAND_TICKETLISTADDCOMMENT, player->GetName(), comment);
+ msg += PGetParseString(LANG_COMMAND_TICKETLISTADDCOMMENT, player ? player->GetName() : "Console", comment);
SendGlobalGMSysMessage(msg.c_str());
return true;
@@ -297,19 +315,21 @@ bool ChatHandler::HandleGMTicketDeleteByIdCommand(const char* args)
SendSysMessage(LANG_COMMAND_TICKETNOTEXIST);
return true;
}
+
if (!ticket->IsClosed())
{
SendSysMessage(LANG_COMMAND_TICKETCLOSEFIRST);
return true;
}
- std::string msg = ticket->FormatMessageString(*this, NULL, NULL, NULL, m_session->GetPlayer()->GetName());
+ std::string msg = ticket->FormatMessageString(*this, NULL, NULL, NULL, m_session ? m_session->GetPlayer()->GetName() : "Console");
SendGlobalGMSysMessage(msg.c_str());
sTicketMgr->RemoveTicket(ticket->GetId());
sTicketMgr->UpdateLastChange();
if (Player* player = ticket->GetPlayer())
+ {
if (player->IsInWorld())
{
// Force abandon ticket
@@ -317,6 +337,7 @@ bool ChatHandler::HandleGMTicketDeleteByIdCommand(const char* args)
data << uint32(GMTICKET_RESPONSE_TICKET_DELETED);
player->GetSession()->SendPacket(&data);
}
+ }
return true;
}
@@ -406,9 +427,11 @@ inline bool ChatHandler::_HandleGMTicketResponseAppendCommand(const char* args,
PSendSysMessage(LANG_COMMAND_TICKETNOTEXIST);
return true;
}
+
// Cannot add response to ticket, assigned to someone else
- Player* player = m_session->GetPlayer();
- if (ticket->IsAssignedNotTo(player->GetGUID()))
+ //! Console excluded
+ Player* player = m_session ? m_session->GetPlayer() : NULL;
+ if (player && ticket->IsAssignedNotTo(player->GetGUID()))
{
PSendSysMessage(LANG_COMMAND_TICKETALREADYASSIGNED, ticket->GetId());
return true;
diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp
index bfefb3e4e76..cf349044042 100755
--- a/src/server/game/Conditions/ConditionMgr.cpp
+++ b/src/server/game/Conditions/ConditionMgr.cpp
@@ -67,11 +67,8 @@ bool Condition::Meets(Player* player, Unit* invoker)
break;
}
case CONDITION_ACHIEVEMENT:
- {
- AchievementEntry const* achievement = GetAchievementStore()->LookupEntry(mConditionValue1);
- condMeets = player->GetAchievementMgr().HasAchieved(achievement);
+ condMeets = player->GetAchievementMgr().HasAchieved(mConditionValue1);
break;
- }
case CONDITION_TEAM:
condMeets = player->GetTeam() == mConditionValue1;
break;
diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h
index dcdc2b2ea0a..78324f8fae2 100755
--- a/src/server/game/DataStores/DBCEnums.h
+++ b/src/server/game/DataStores/DBCEnums.h
@@ -74,14 +74,14 @@ enum AchievementFlags
enum AchievementCriteriaCondition
{
- ACHIEVEMENT_CRITERIA_CONDITION_NONE = 0,
- ACHIEVEMENT_CRITERIA_CONDITION_NO_DEATH = 1, // reset progress on death
- ACHIEVEMENT_CRITERIA_CONDITION_UNK1 = 2, // only used in "Complete a daily quest every day for five consecutive days"
- ACHIEVEMENT_CRITERIA_CONDITION_BG_MAP = 3, // requires you to be on specific map, reset at change
- ACHIEVEMENT_CRITERIA_CONDITION_NO_LOSE = 4, // only used in "Win 10 arenas without losing"
- ACHIEVEMENT_CRITERIA_CONDITION_UNK2 = 9, // unk
- ACHIEVEMENT_CRITERIA_CONDITION_NOT_IN_GROUP = 10, // requires the player not to be in group
- ACHIEVEMENT_CRITERIA_CONDITION_UNK3 = 13, // unk
+ ACHIEVEMENT_CRITERIA_CONDITION_NONE = 0,
+ ACHIEVEMENT_CRITERIA_CONDITION_NO_DEATH = 1, // reset progress on death
+ ACHIEVEMENT_CRITERIA_CONDITION_UNK1 = 2, // only used in "Complete a daily quest every day for five consecutive days"
+ ACHIEVEMENT_CRITERIA_CONDITION_BG_MAP = 3, // requires you to be on specific map, reset at change
+ ACHIEVEMENT_CRITERIA_CONDITION_NO_LOSE = 4, // only used in "Win 10 arenas without losing"
+ ACHIEVEMENT_CRITERIA_CONDITION_NO_SPELL_HIT = 9, // requires the player not to be hit by specific spell
+ ACHIEVEMENT_CRITERIA_CONDITION_NOT_IN_GROUP = 10, // requires the player not to be in group
+ ACHIEVEMENT_CRITERIA_CONDITION_UNK3 = 13, // unk
};
enum AchievementCriteriaFlags
@@ -97,7 +97,7 @@ enum AchievementCriteriaFlags
enum AchievementCriteriaTimedTypes
{
ACHIEVEMENT_TIMED_TYPE_EVENT = 1, // Timer is started by internal event with id in timerStartEvent
- ACHIEVEMENT_TIMED_TYPE_QUEST = 2, // Timer is started by acceting quest with entry in timerStartEvent
+ ACHIEVEMENT_TIMED_TYPE_QUEST = 2, // Timer is started by accepting quest with entry in timerStartEvent
ACHIEVEMENT_TIMED_TYPE_SPELL_CASTER = 5, // Timer is started by casting a spell with entry in timerStartEvent
ACHIEVEMENT_TIMED_TYPE_SPELL_TARGET = 6, // Timer is started by being target of spell with entry in timerStartEvent
ACHIEVEMENT_TIMED_TYPE_CREATURE = 7, // Timer is started by killing creature with entry in timerStartEvent
@@ -417,7 +417,7 @@ enum SummonPropFlags
enum VehicleSeatFlags
{
VEHICLE_SEAT_FLAG_HIDE_PASSENGER = 0x00000200, // Passenger is hidden
- VEHICLE_SEAT_FLAG_UNK11 = 0x00000400, // needed for CGCamera__SyncFreeLookFacing
+ VEHICLE_SEAT_FLAG_UNK1 = 0x00000400, // needed for CGCamera__SyncFreeLookFacing
VEHICLE_SEAT_FLAG_CAN_CONTROL = 0x00000800, // Lua_UnitInVehicleControlSeat
VEHICLE_SEAT_FLAG_CAN_CAST_MOUNT_SPELL = 0x00001000, // Can cast spells with SPELL_AURA_MOUNTED from seat (possibly 4.x only, 0 seats on 3.3.5a)
VEHICLE_SEAT_FLAG_UNCONTROLLED = 0x00002000, // can override !& VEHICLE_SEAT_FLAG_CAN_ENTER_OR_EXIT
@@ -425,6 +425,7 @@ enum VehicleSeatFlags
VEHICLE_SEAT_FLAG_CAN_ENTER_OR_EXIT = 0x02000000, // Lua_CanExitVehicle - can enter and exit at free will
VEHICLE_SEAT_FLAG_CAN_SWITCH = 0x04000000, // Lua_CanSwitchVehicleSeats
VEHICLE_SEAT_FLAG_CAN_CAST = 0x20000000, // Lua_UnitHasVehicleUI
+ VEHICLE_SEAT_FLAG_UNK2 = 0x40000000, // checked in conjunction with 0x800 in CastSpell2
};
enum VehicleSeatFlagsB
@@ -435,7 +436,7 @@ enum VehicleSeatFlagsB
VEHICLE_SEAT_FLAG_B_EJECTABLE = 0x00000020, // ejectable
VEHICLE_SEAT_FLAG_B_USABLE_FORCED_2 = 0x00000040,
VEHICLE_SEAT_FLAG_B_USABLE_FORCED_3 = 0x00000100,
- VEHICLE_SEAT_FLAG_B_CANSWITCH = 0x04000000, // can switch seats
+ VEHICLE_SEAT_FLAG_B_USABLE_FORCED_4 = 0x02000000,
VEHICLE_SEAT_FLAG_B_VEHICLE_PLAYERFRAME_UI = 0x80000000, // Lua_UnitHasVehiclePlayerFrameUI - actually checked for flagsb &~ 0x80000000
};
diff --git a/src/server/game/DataStores/DBCStructure.h b/src/server/game/DataStores/DBCStructure.h
index ba7be495c77..5a4dea3a020 100755
--- a/src/server/game/DataStores/DBCStructure.h
+++ b/src/server/game/DataStores/DBCStructure.h
@@ -1939,9 +1939,10 @@ struct VehicleSeatEntry
// 46-57 added in 3.1, floats mostly
bool CanEnterOrExit() const { return m_flags & VEHICLE_SEAT_FLAG_CAN_ENTER_OR_EXIT; }
- bool CanSwitchFromSeat() const { return m_flags & VEHICLE_SEAT_FLAG_B_CANSWITCH; }
+ bool CanSwitchFromSeat() const { return m_flags & VEHICLE_SEAT_FLAG_CAN_SWITCH; }
bool IsUsableByOverride() const { return (m_flags & VEHICLE_SEAT_FLAG_UNCONTROLLED)
- || (m_flagsB & (VEHICLE_SEAT_FLAG_B_USABLE_FORCED | VEHICLE_SEAT_FLAG_B_USABLE_FORCED_2 | VEHICLE_SEAT_FLAG_B_USABLE_FORCED_3)); }
+ || (m_flagsB & (VEHICLE_SEAT_FLAG_B_USABLE_FORCED | VEHICLE_SEAT_FLAG_B_USABLE_FORCED_2 |
+ VEHICLE_SEAT_FLAG_B_USABLE_FORCED_3 | VEHICLE_SEAT_FLAG_B_USABLE_FORCED_4)); }
bool IsEjectable() const { return m_flagsB & VEHICLE_SEAT_FLAG_B_EJECTABLE; }
};
diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp
index 55f798204db..21ff3c6e4e8 100755
--- a/src/server/game/DungeonFinding/LFGMgr.cpp
+++ b/src/server/game/DungeonFinding/LFGMgr.cpp
@@ -389,7 +389,7 @@ void LFGMgr::InitializeLockedDungeons(Player* player)
locktype = LFG_LOCKSTATUS_TOO_HIGH_LEVEL;
else if (locktype == LFG_LOCKSTATUS_OK && ar)
{
- if (ar->achievement && !player->GetAchievementMgr().HasAchieved(sAchievementStore.LookupEntry(ar->achievement)))
+ if (ar->achievement && !player->GetAchievementMgr().HasAchieved(ar->achievement))
locktype = LFG_LOCKSTATUS_RAID_LOCKED; // FIXME: Check the correct lock value
else if (player->GetTeam() == ALLIANCE && ar->quest_A && !player->GetQuestRewardStatus(ar->quest_A))
locktype = LFG_LOCKSTATUS_QUEST_NOT_COMPLETED;
diff --git a/src/server/game/Entities/Corpse/Corpse.cpp b/src/server/game/Entities/Corpse/Corpse.cpp
index 31cc21659c9..cd05cba7475 100755
--- a/src/server/game/Entities/Corpse/Corpse.cpp
+++ b/src/server/game/Entities/Corpse/Corpse.cpp
@@ -26,7 +26,7 @@
#include "GossipDef.h"
#include "World.h"
-Corpse::Corpse(CorpseType type) : WorldObject()
+Corpse::Corpse(CorpseType type) : WorldObject(type != CORPSE_BONES)
, m_type(type)
{
m_objectType |= TYPEMASK_CORPSE;
@@ -39,9 +39,6 @@ Corpse::Corpse(CorpseType type) : WorldObject()
m_time = time(NULL);
lootForBody = false;
-
- if (type != CORPSE_BONES)
- m_isWorldObject = true;
}
Corpse::~Corpse()
@@ -162,20 +159,11 @@ void Corpse::DeleteFromDB(SQLTransaction& trans)
trans->Append(stmt);
}
-bool Corpse::LoadFromDB(uint32 guid, Field* fields)
+bool Corpse::LoadCorpseFromDB(uint32 guid, Field* fields)
{
uint32 ownerGuid = fields[17].GetUInt32();
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
// SELECT posX, posY, posZ, orientation, mapId, displayId, itemCache, bytes1, bytes2, guildId, flags, dynFlags, time, corpseType, instanceId, phaseMask, corpseGuid, guid FROM corpse WHERE corpseType <> 0
- m_type = CorpseType(fields[13].GetUInt8());
- if (m_type >= MAX_CORPSE_TYPE)
- {
- sLog->outError("Corpse (guid: %u, owner: %u) have wrong corpse type (%u), not loading.", guid, ownerGuid, m_type);
- return false;
- }
- if (m_type != CORPSE_BONES)
- m_isWorldObject = true;
-
float posX = fields[0].GetFloat();
float posY = fields[1].GetFloat();
float posZ = fields[2].GetFloat();
diff --git a/src/server/game/Entities/Corpse/Corpse.h b/src/server/game/Entities/Corpse/Corpse.h
index 2e45606b88f..a704e2243eb 100755
--- a/src/server/game/Entities/Corpse/Corpse.h
+++ b/src/server/game/Entities/Corpse/Corpse.h
@@ -59,7 +59,7 @@ class Corpse : public WorldObject, public GridObject<Corpse>
bool Create(uint32 guidlow, Player* owner);
void SaveToDB();
- bool LoadFromDB(uint32 guid, Field* fields);
+ bool LoadCorpseFromDB(uint32 guid, Field* fields);
void DeleteBonesFromWorld();
void DeleteFromDB(SQLTransaction& trans);
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index 3238d9873a9..f97d01a42a4 100755
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -137,7 +137,7 @@ bool ForcedDespawnDelayEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
return true;
}
-Creature::Creature(): Unit(), MapCreature(),
+Creature::Creature(bool isWorldObject): Unit(isWorldObject), MapCreature(),
lootForPickPocketed(false), lootForBody(false), m_groupLootTimer(0), lootingGroupLowGUID(0),
m_PlayerDamageReq(0), m_lootMoney(0), m_lootRecipient(0), m_lootRecipientGroup(0), m_corpseRemoveTime(0), m_respawnTime(0),
m_respawnDelay(300), m_corpseDelay(60), m_respawnradius(0.0f), m_reactState(REACT_AGGRESSIVE),
@@ -160,6 +160,7 @@ m_creatureInfo(NULL), m_creatureData(NULL), m_formation(NULL)
ResetLootMode(); // restore default loot mode
TriggerJustRespawned = false;
+ m_isTempWorldObject = false;
}
Creature::~Creature()
diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h
index 6ae9fa97462..d84221f0e63 100755
--- a/src/server/game/Entities/Creature/Creature.h
+++ b/src/server/game/Entities/Creature/Creature.h
@@ -440,7 +440,7 @@ class Creature : public Unit, public GridObject<Creature>, public MapCreature
{
public:
- explicit Creature();
+ explicit Creature(bool isWorldObject = false);
virtual ~Creature();
void AddToWorld();
@@ -707,6 +707,9 @@ class Creature : public Unit, public GridObject<Creature>, public MapCreature
uint32 GetGUIDTransport() { return guid_transport; }
void FarTeleportTo(Map* map, float X, float Y, float Z, float O);
+
+ bool m_isTempWorldObject; //true when possessed
+
protected:
bool CreateFromProto(uint32 guidlow, uint32 Entry, uint32 vehId, uint32 team, const CreatureData* data = NULL);
bool InitEntry(uint32 entry, uint32 team=ALLIANCE, const CreatureData* data=NULL);
diff --git a/src/server/game/Entities/Creature/TemporarySummon.cpp b/src/server/game/Entities/Creature/TemporarySummon.cpp
index b17606b83cc..1b06f0f0b6a 100755
--- a/src/server/game/Entities/Creature/TemporarySummon.cpp
+++ b/src/server/game/Entities/Creature/TemporarySummon.cpp
@@ -22,8 +22,8 @@
#include "ObjectMgr.h"
#include "TemporarySummon.h"
-TempSummon::TempSummon(SummonPropertiesEntry const* properties, Unit* owner) :
-Creature(), m_Properties(properties), m_type(TEMPSUMMON_MANUAL_DESPAWN),
+TempSummon::TempSummon(SummonPropertiesEntry const* properties, Unit* owner, bool isWorldObject) :
+Creature(isWorldObject), m_Properties(properties), m_type(TEMPSUMMON_MANUAL_DESPAWN),
m_timer(0), m_lifetime(0)
{
m_summonerGUID = owner ? owner->GetGUID() : 0;
@@ -272,7 +272,7 @@ void TempSummon::RemoveFromWorld()
Creature::RemoveFromWorld();
}
-Minion::Minion(SummonPropertiesEntry const* properties, Unit* owner) : TempSummon(properties, owner)
+Minion::Minion(SummonPropertiesEntry const* properties, Unit* owner, bool isWorldObject) : TempSummon(properties, owner, isWorldObject)
, m_owner(owner)
{
ASSERT(m_owner);
@@ -306,7 +306,7 @@ bool Minion::IsGuardianPet() const
return isPet() || (m_Properties && m_Properties->Category == SUMMON_CATEGORY_PET);
}
-Guardian::Guardian(SummonPropertiesEntry const* properties, Unit* owner) : Minion(properties, owner)
+Guardian::Guardian(SummonPropertiesEntry const* properties, Unit* owner, bool isWorldObject) : Minion(properties, owner, isWorldObject)
, m_bonusSpellDamage(0)
{
memset(m_statFromOwner, 0, sizeof(float)*MAX_STATS);
@@ -340,7 +340,7 @@ void Guardian::InitSummon()
m_owner->ToPlayer()->CharmSpellInitialize();
}
-Puppet::Puppet(SummonPropertiesEntry const* properties, Unit* owner) : Minion(properties, owner)
+Puppet::Puppet(SummonPropertiesEntry const* properties, Unit* owner) : Minion(properties, owner, false) //maybe true?
{
ASSERT(owner->GetTypeId() == TYPEID_PLAYER);
m_owner = (Player*)owner;
diff --git a/src/server/game/Entities/Creature/TemporarySummon.h b/src/server/game/Entities/Creature/TemporarySummon.h
index 1982dec4bb8..69ae8349155 100755
--- a/src/server/game/Entities/Creature/TemporarySummon.h
+++ b/src/server/game/Entities/Creature/TemporarySummon.h
@@ -24,7 +24,7 @@
class TempSummon : public Creature
{
public:
- explicit TempSummon(SummonPropertiesEntry const* properties, Unit* owner);
+ explicit TempSummon(SummonPropertiesEntry const* properties, Unit* owner, bool isWorldObject);
virtual ~TempSummon() {}
void Update(uint32 time);
virtual void InitStats(uint32 lifetime);
@@ -48,7 +48,7 @@ class TempSummon : public Creature
class Minion : public TempSummon
{
public:
- Minion(SummonPropertiesEntry const* properties, Unit* owner);
+ Minion(SummonPropertiesEntry const* properties, Unit* owner, bool isWorldObject);
void InitStats(uint32 duration);
void RemoveFromWorld();
Unit* GetOwner() { return m_owner; }
@@ -64,7 +64,7 @@ class Minion : public TempSummon
class Guardian : public Minion
{
public:
- Guardian(SummonPropertiesEntry const* properties, Unit* owner);
+ Guardian(SummonPropertiesEntry const* properties, Unit* owner, bool isWorldObject);
void InitStats(uint32 duration);
bool InitStatsForLevel(uint8 level);
void InitSummon();
diff --git a/src/server/game/Entities/DynamicObject/DynamicObject.cpp b/src/server/game/Entities/DynamicObject/DynamicObject.cpp
index 30afd43cf14..4e0d2d7d0b9 100755
--- a/src/server/game/Entities/DynamicObject/DynamicObject.cpp
+++ b/src/server/game/Entities/DynamicObject/DynamicObject.cpp
@@ -27,7 +27,7 @@
#include "GridNotifiersImpl.h"
#include "ScriptMgr.h"
-DynamicObject::DynamicObject() : WorldObject(),
+DynamicObject::DynamicObject(bool isWorldObject) : WorldObject(isWorldObject),
_aura(NULL), _removedAura(NULL), _caster(NULL), _duration(0), _isViewpoint(false)
{
m_objectType |= TYPEMASK_DYNAMICOBJECT;
@@ -79,7 +79,7 @@ void DynamicObject::RemoveFromWorld()
}
}
-bool DynamicObject::CreateDynamicObject(uint32 guidlow, Unit* caster, uint32 spellId, Position const& pos, float radius, bool active, DynamicObjectType type)
+bool DynamicObject::CreateDynamicObject(uint32 guidlow, Unit* caster, uint32 spellId, Position const& pos, float radius, DynamicObjectType type)
{
SetMap(caster->GetMap());
Relocate(pos);
@@ -105,8 +105,7 @@ bool DynamicObject::CreateDynamicObject(uint32 guidlow, Unit* caster, uint32 spe
SetFloatValue(DYNAMICOBJECT_RADIUS, radius);
SetUInt32Value(DYNAMICOBJECT_CASTTIME, getMSTime());
- m_isWorldObject = active;
- if (active)
+ if (IsWorldObject())
setActive(true); //must before add to map to be put in world container
if (!GetMap()->AddToMap(this))
diff --git a/src/server/game/Entities/DynamicObject/DynamicObject.h b/src/server/game/Entities/DynamicObject/DynamicObject.h
index c178fe98d14..bd8c15cdba4 100755
--- a/src/server/game/Entities/DynamicObject/DynamicObject.h
+++ b/src/server/game/Entities/DynamicObject/DynamicObject.h
@@ -35,13 +35,13 @@ enum DynamicObjectType
class DynamicObject : public WorldObject, public GridObject<DynamicObject>
{
public:
- DynamicObject();
+ DynamicObject(bool isWorldObject);
~DynamicObject();
void AddToWorld();
void RemoveFromWorld();
- bool CreateDynamicObject(uint32 guidlow, Unit* caster, uint32 spellId, Position const& pos, float radius, bool active, DynamicObjectType type);
+ bool CreateDynamicObject(uint32 guidlow, Unit* caster, uint32 spellId, Position const& pos, float radius, DynamicObjectType type);
void Update(uint32 p_time);
void Remove();
void SetDuration(int32 newDuration);
diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp
index de1b0f84871..036664a2760 100755
--- a/src/server/game/Entities/GameObject/GameObject.cpp
+++ b/src/server/game/Entities/GameObject/GameObject.cpp
@@ -30,7 +30,7 @@
#include "CreatureAISelector.h"
#include "Group.h"
-GameObject::GameObject() : WorldObject(), m_goValue(new GameObjectValue), m_AI(NULL)
+GameObject::GameObject() : WorldObject(false), m_goValue(new GameObjectValue), m_AI(NULL)
{
m_objectType |= TYPEMASK_GAMEOBJECT;
m_objectTypeId = TYPEID_GAMEOBJECT;
diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp
index 978d9accb64..d4679928d82 100755
--- a/src/server/game/Entities/Object/Object.cpp
+++ b/src/server/game/Entities/Object/Object.cpp
@@ -82,7 +82,7 @@ Object::Object() : m_PackGUID(sizeof(uint64)+1)
WorldObject::~WorldObject()
{
// this may happen because there are many !create/delete
- if (m_isWorldObject && m_currMap)
+ if (IsWorldObject() && m_currMap)
{
if (GetTypeId() == TYPEID_CORPSE)
{
@@ -1221,8 +1221,8 @@ void MovementInfo::OutDebug()
sLog->outString("splineElevation: %f", splineElevation);
}
-WorldObject::WorldObject(): WorldLocation(),
-m_isWorldObject(false), m_name(""), m_isActive(false), m_zoneScript(NULL),
+WorldObject::WorldObject(bool isWorldObject): WorldLocation(),
+m_isWorldObject(isWorldObject), m_name(""), m_isActive(false), m_zoneScript(NULL),
m_transport(NULL), m_currMap(NULL), m_InstanceId(0),
m_phaseMask(PHASEMASK_NORMAL), m_notifyflags(0), m_executed_notifies(0)
{
@@ -1238,6 +1238,17 @@ void WorldObject::SetWorldObject(bool on)
GetMap()->AddObjectToSwitchList(this, on);
}
+bool WorldObject::IsWorldObject() const
+{
+ if (m_isWorldObject)
+ return true;
+
+ if (ToCreature() && ToCreature()->m_isTempWorldObject)
+ return true;
+
+ return false;
+}
+
void WorldObject::setActive(bool on)
{
if (m_isActive == on)
@@ -1642,7 +1653,7 @@ bool WorldObject::canSeeOrDetect(WorldObject const* obj, bool ignoreStealth, boo
bool corpseVisibility = false;
if (distanceCheck)
{
- if (const Player* thisPlayer = ToPlayer())
+ if (Player const* thisPlayer = ToPlayer())
{
if (thisPlayer->isDead() && thisPlayer->GetHealth() > 0 && // Cheap way to check for ghost state
!(obj->m_serverSideVisibility.GetValue(SERVERSIDE_VISIBILITY_GHOST) & m_serverSideVisibility.GetValue(SERVERSIDE_VISIBILITY_GHOST) & GHOST_VISIBILITY_GHOST))
@@ -1675,9 +1686,9 @@ bool WorldObject::canSeeOrDetect(WorldObject const* obj, bool ignoreStealth, boo
if (!corpseVisibility && !(obj->m_serverSideVisibility.GetValue(SERVERSIDE_VISIBILITY_GHOST) & m_serverSideVisibilityDetect.GetValue(SERVERSIDE_VISIBILITY_GHOST)))
{
// Alive players can see dead players in some cases, but other objects can't do that
- if (const Player* thisPlayer = ToPlayer())
+ if (Player const* thisPlayer = ToPlayer())
{
- if (const Player* objPlayer = obj->ToPlayer())
+ if (Player const* objPlayer = obj->ToPlayer())
{
if (thisPlayer->GetTeam() != objPlayer->GetTeam() || !thisPlayer->IsGroupVisibleFor(objPlayer))
return false;
@@ -2018,7 +2029,6 @@ void WorldObject::SendMessageToSet(WorldPacket* data, bool self)
SendMessageToSetInRange(data, GetVisibilityRange(), self);
}
-
void WorldObject::SendMessageToSetInRange(WorldPacket* data, float dist, bool /*self*/)
{
Trinity::MessageDistDeliverer notifier(this, data, dist);
@@ -2052,7 +2062,7 @@ void WorldObject::SetMap(Map* map)
m_currMap = map;
m_mapId = map->GetId();
m_InstanceId = map->GetInstanceId();
- if (m_isWorldObject)
+ if (IsWorldObject())
m_currMap->AddWorldObject(this);
}
@@ -2060,7 +2070,7 @@ void WorldObject::ResetMap()
{
ASSERT(m_currMap);
ASSERT(!IsInWorld());
- if (m_isWorldObject)
+ if (IsWorldObject())
m_currMap->RemoveWorldObject(this);
m_currMap = NULL;
//maybe not for corpse
@@ -2150,10 +2160,10 @@ TempSummon* Map::SummonCreature(uint32 entry, Position const& pos, SummonPropert
switch (mask)
{
case UNIT_MASK_SUMMON:
- summon = new TempSummon(properties, summoner);
+ summon = new TempSummon(properties, summoner, false);
break;
case UNIT_MASK_GUARDIAN:
- summon = new Guardian(properties, summoner);
+ summon = new Guardian(properties, summoner, false);
break;
case UNIT_MASK_PUPPET:
summon = new Puppet(properties, summoner);
@@ -2162,7 +2172,7 @@ TempSummon* Map::SummonCreature(uint32 entry, Position const& pos, SummonPropert
summon = new Totem(properties, summoner);
break;
case UNIT_MASK_MINION:
- summon = new Minion(properties, summoner);
+ summon = new Minion(properties, summoner, false);
break;
default:
return NULL;
diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h
index eab4dbeba99..786b23f6340 100755
--- a/src/server/game/Entities/Object/Object.h
+++ b/src/server/game/Entities/Object/Object.h
@@ -561,7 +561,7 @@ class FlaggedValuesArray32
class WorldObject : public Object, public WorldLocation
{
protected:
- explicit WorldObject();
+ explicit WorldObject(bool isWorldObject); //note: here it means if it is in grid object list or world object list
public:
virtual ~WorldObject();
@@ -800,6 +800,9 @@ class WorldObject : public Object, public WorldLocation
bool isActiveObject() const { return m_isActive; }
void setActive(bool isActiveObject);
void SetWorldObject(bool apply);
+ bool IsPermanentWorldObject() const { return m_isWorldObject; }
+ bool IsWorldObject() const;
+
template<class NOTIFIER> void VisitNearbyObject(float const& radius, NOTIFIER& notifier) const { if (IsInWorld()) GetMap()->VisitAll(GetPositionX(), GetPositionY(), radius, notifier); }
template<class NOTIFIER> void VisitNearbyGridObject(float const& radius, NOTIFIER& notifier) const { if (IsInWorld()) GetMap()->VisitGrid(GetPositionX(), GetPositionY(), radius, notifier); }
template<class NOTIFIER> void VisitNearbyWorldObject(float const& radius, NOTIFIER& notifier) const { if (IsInWorld()) GetMap()->VisitWorld(GetPositionX(), GetPositionY(), radius, notifier); }
@@ -812,7 +815,6 @@ class WorldObject : public Object, public WorldLocation
double rand_chance() const { return GetMap()->mtRand.randExc(100.0);}
#endif
- bool m_isWorldObject;
uint32 LastUsedScriptID;
// Transports
@@ -830,6 +832,7 @@ class WorldObject : public Object, public WorldLocation
protected:
std::string m_name;
bool m_isActive;
+ const bool m_isWorldObject;
ZoneScript* m_zoneScript;
// transports
diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp
index 404fe24d467..4e33142f5ce 100755
--- a/src/server/game/Entities/Pet/Pet.cpp
+++ b/src/server/game/Entities/Pet/Pet.cpp
@@ -33,7 +33,7 @@
#define PET_XP_FACTOR 0.05f
-Pet::Pet(Player* owner, PetType type) : Guardian(NULL, owner),
+Pet::Pet(Player* owner, PetType type) : Guardian(NULL, owner, true),
m_usedTalentCount(0), m_removed(false), m_owner(owner),
m_happinessTimer(7500), m_petType(type), m_duration(0),
m_auraRaidUpdateMask(0), m_loading(false), m_declinedname(NULL)
@@ -50,8 +50,6 @@ m_auraRaidUpdateMask(0), m_loading(false), m_declinedname(NULL)
m_name = "Pet";
m_regenTimer = PET_FOCUS_REGEN_INTERVAL;
-
- m_isWorldObject = true;
}
Pet::~Pet()
@@ -908,6 +906,7 @@ bool Guardian::InitStatsForLevel(uint8 petlevel)
SetCreateHealth(40*petlevel);
SetCreateMana(28 + 10*petlevel);
}
+ SetBonusDamage(m_owner->SpellBaseDamageBonus(SPELL_SCHOOL_MASK_FIRE) * 0.5f);
SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel * 4 - petlevel));
SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel * 4 + petlevel));
break;
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 0e98eb27596..510813a4e56 100755
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -629,7 +629,7 @@ UpdateMask Player::updateVisualBits;
#ifdef _MSC_VER
#pragma warning(disable:4355)
#endif
-Player::Player (WorldSession* session): Unit(), m_achievementMgr(this), m_reputationMgr(this)
+Player::Player(WorldSession* session): Unit(true), m_achievementMgr(this), m_reputationMgr(this)
{
#ifdef _MSC_VER
#pragma warning(default:4355)
@@ -839,7 +839,6 @@ Player::Player (WorldSession* session): Unit(), m_achievementMgr(this), m_reputa
m_grantableLevels = 0;
m_ControlledByPlayer = true;
- m_isWorldObject = true;
sWorld->IncreasePlayerCount();
@@ -1850,7 +1849,7 @@ void Player::setDeathState(DeathState s)
SetUInt32Value(PLAYER_SELF_RES_SPELL, 0);
}
-bool Player::BuildEnumData(QueryResult result, WorldPacket* data)
+bool Player::BuildEnumData(PreparedQueryResult result, WorldPacket* data)
{
// 0 1 2 3 4 5 6 7
// "SELECT characters.guid, characters.name, characters.race, characters.class, characters.gender, characters.playerBytes, characters.playerBytes2, characters.level, "
@@ -1894,8 +1893,8 @@ bool Player::BuildEnumData(QueryResult result, WorldPacket* data)
*data << uint8(playerBytes2 & 0xFF); // facial hair
*data << uint8(fields[7].GetUInt8()); // level
- *data << uint32(fields[8].GetUInt32()); // zone
- *data << uint32(fields[9].GetUInt32()); // map
+ *data << uint32(fields[8].GetUInt16()); // zone
+ *data << uint32(fields[9].GetUInt16()); // map
*data << fields[10].GetFloat(); // x
*data << fields[11].GetFloat(); // y
@@ -2052,28 +2051,6 @@ void Player::SendTeleportAckPacket()
GetSession()->SendPacket(&data);
}
-// this is not used anywhere
-void Player::TeleportOutOfMap(Map* oldMap)
-{
- while (IsBeingTeleportedFar())
- GetSession()->HandleMoveWorldportAckOpcode();
-
- if (GetMap() != oldMap)
- return;
-
- TeleportTo(m_homebindMapId, m_homebindX, m_homebindY, m_homebindZ, GetOrientation());
-
- while (IsBeingTeleportedFar())
- GetSession()->HandleMoveWorldportAckOpcode();
-
- if (GetMap() == oldMap)
- {
- sLog->outCrash("Cannot teleport player out of map!");
- ResetMap();
- ASSERT(false);
- }
-}
-
bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options)
{
if (!MapManager::IsValidMapCoord(mapid, x, y, z, orientation))
@@ -12885,6 +12862,8 @@ void Player::SwapItem(uint16 src, uint16 dst)
RemoveItem(srcbag, srcslot, true);
StoreItem(dest, pSrcItem, true);
+ if (IsBankPos(src))
+ ItemAddedQuestCheck(pSrcItem->GetEntry(), pSrcItem->GetCount());
}
else if (IsBankPos (dst))
{
@@ -12898,6 +12877,7 @@ void Player::SwapItem(uint16 src, uint16 dst)
RemoveItem(srcbag, srcslot, true);
BankItem(dest, pSrcItem, true);
+ ItemRemovedQuestCheck(pSrcItem->GetEntry(), pSrcItem->GetCount());
}
else if (IsEquipmentPos (dst))
{
@@ -13322,11 +13302,7 @@ void Player::UpdateSoulboundTradeItems()
// also checks for garbage data
for (ItemDurationList::iterator itr = m_itemSoulboundTradeable.begin(); itr != m_itemSoulboundTradeable.end();)
{
- if (!*itr)
- {
- m_itemSoulboundTradeable.erase(itr++);
- continue;
- }
+ ASSERT(*itr);
if ((*itr)->GetOwnerGUID() != GetGUID())
{
m_itemSoulboundTradeable.erase(itr++);
@@ -13341,16 +13317,10 @@ void Player::UpdateSoulboundTradeItems()
}
}
+//TODO: should never allow an item to be added to m_itemSoulboundTradeable twice
void Player::RemoveTradeableItem(Item* item)
{
- for (ItemDurationList::iterator itr = m_itemSoulboundTradeable.begin(); itr != m_itemSoulboundTradeable.end(); ++itr)
- {
- if ((*itr) == item)
- {
- m_itemSoulboundTradeable.erase(itr);
- break;
- }
- }
+ m_itemSoulboundTradeable.remove(item);
}
void Player::UpdateItemDuration(uint32 time, bool realtimeonly)
@@ -15052,11 +15022,11 @@ void Player::FailQuest(uint32 questId)
// Destroy quest items on quest failure.
for (uint8 i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
if (quest->RequiredItemId[i] > 0 && quest->RequiredItemCount[i] > 0)
- // Destroy items recieved on starting the quest.
+ // Destroy items received on starting the quest.
DestroyItemCount(quest->RequiredItemId[i], quest->RequiredItemCount[i], true, true);
for (uint8 i = 0; i < QUEST_SOURCE_ITEM_IDS_COUNT; ++i)
if (quest->RequiredSourceItemId[i] > 0 && quest->RequiredSourceItemCount[i] > 0)
- // Destroy items recieved during the quest.
+ // Destroy items received during the quest.
DestroyItemCount(quest->RequiredSourceItemId[i], quest->RequiredSourceItemCount[i], true, true);
}
}
@@ -18143,8 +18113,14 @@ bool Player::Satisfy(AccessRequirement const* ar, uint32 target_map, bool report
missingQuest = ar->quest_H;
uint32 missingAchievement = 0;
- if (ar->achievement && !GetAchievementMgr().HasAchieved(sAchievementStore.LookupEntry(ar->achievement)))
- missingAchievement = ar->achievement;
+ Player* leader = this;
+ uint64 leaderGuid = GetGroup() ? GetGroup()->GetLeaderGUID() : GetGUID();
+ if (leaderGuid != GetGUID())
+ leader = ObjectAccessor::FindPlayer(leaderGuid);
+
+ if (ar->achievement)
+ if (!leader || !leader->GetAchievementMgr().HasAchieved(ar->achievement))
+ missingAchievement = ar->achievement;
Difficulty target_difficulty = GetDifficulty(mapEntry->IsRaid());
MapDifficulty const* mapDiff = GetDownscaledMapDifficultyData(target_map, target_difficulty);
@@ -18919,7 +18895,7 @@ void Player::_SaveSkills(SQLTransaction& trans)
void Player::_SaveSpells(SQLTransaction& trans)
{
- for (PlayerSpellMap::iterator itr = m_spells.begin(), next = m_spells.begin(); itr != m_spells.end();)
+ for (PlayerSpellMap::iterator itr = m_spells.begin(); itr != m_spells.end();)
{
if (itr->second->state == PLAYERSPELL_REMOVED || itr->second->state == PLAYERSPELL_CHANGED)
trans->PAppend("DELETE FROM character_spell WHERE guid = '%u' and spell = '%u'", GetGUIDLow(), itr->first);
@@ -20221,7 +20197,7 @@ bool Player::ActivateTaxiPathTo(uint32 taxi_path_id, uint32 spellid /*= 0*/)
void Player::CleanupAfterTaxiFlight()
{
m_taxi.ClearTaxiDestinations(); // not destinations, clear source node
- Unmount();
+ Dismount();
RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_TAXI_FLIGHT);
getHostileRefManager().setOnlineOfflineState(true);
}
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 651b99e7cb4..8ee7d1a417f 100755
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -1091,13 +1091,10 @@ class Player : public Unit, public GridObject<Player>
void RemoveFromWorld();
bool TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options = 0);
- void TeleportOutOfMap(Map* oldMap);
-
bool TeleportTo(WorldLocation const &loc, uint32 options = 0)
{
return TeleportTo(loc.GetMapId(), loc.GetPositionX(), loc.GetPositionY(), loc.GetPositionZ(), loc.GetOrientation(), options);
}
-
bool TeleportToBGEntryPoint();
void SetSummonPoint(uint32 mapid, float x, float y, float z)
@@ -1114,7 +1111,7 @@ class Player : public Unit, public GridObject<Player>
void Update(uint32 time);
- static bool BuildEnumData(QueryResult result, WorldPacket* data);
+ static bool BuildEnumData(PreparedQueryResult result, WorldPacket* data);
void SetInWater(bool apply);
@@ -2503,7 +2500,7 @@ class Player : public Unit, public GridObject<Player>
CreatureDisplayInfoEntry const* mountDisplayInfo = sCreatureDisplayInfoStore.LookupEntry(GetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID));
if (!mountDisplayInfo)
return GetCollisionHeight(false);
-
+
CreatureModelDataEntry const* mountModelData = sCreatureModelDataStore.LookupEntry(mountDisplayInfo->ModelId);
if (!mountModelData)
return GetCollisionHeight(false);
diff --git a/src/server/game/Entities/Totem/Totem.cpp b/src/server/game/Entities/Totem/Totem.cpp
index 97629e802d4..fc368b1f109 100755
--- a/src/server/game/Entities/Totem/Totem.cpp
+++ b/src/server/game/Entities/Totem/Totem.cpp
@@ -25,7 +25,7 @@
#include "SpellMgr.h"
#include "SpellInfo.h"
-Totem::Totem(SummonPropertiesEntry const* properties, Unit* owner) : Minion(properties, owner)
+Totem::Totem(SummonPropertiesEntry const* properties, Unit* owner) : Minion(properties, owner, false)
{
m_unitTypeMask |= UNIT_MASK_TOTEM;
m_duration = 0;
diff --git a/src/server/game/Entities/Transport/Transport.cpp b/src/server/game/Entities/Transport/Transport.cpp
index 008f752306d..d533f6fe5b9 100755
--- a/src/server/game/Entities/Transport/Transport.cpp
+++ b/src/server/game/Entities/Transport/Transport.cpp
@@ -633,7 +633,8 @@ void Transport::BuildStopMovePacket(Map const* targetMap)
uint32 Transport::AddNPCPassenger(uint32 tguid, uint32 entry, float x, float y, float z, float o, uint32 anim)
{
Map* map = GetMap();
- Creature* creature = new Creature;
+ //make it world object so it will not be unloaded with grid
+ Creature* creature = new Creature(true);
if (!creature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, GetPhaseMask(), entry, 0, GetGOInfo()->faction, 0, 0, 0, 0))
{
@@ -666,7 +667,6 @@ uint32 Transport::AddNPCPassenger(uint32 tguid, uint32 entry, float x, float y,
map->AddToMap(creature);
m_NPCPassengerSet.insert(creature);
- creature->SetWorldObject(true); //so it will not be unloaded with grid
if (tguid == 0)
{
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 298f9c60af8..fec9a13192c 100755
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -144,7 +144,7 @@ _hitMask(hitMask), _spell(spell), _damageInfo(damageInfo), _healInfo(healInfo)
#ifdef _MSC_VER
#pragma warning(disable:4355)
#endif
-Unit::Unit(): WorldObject(),
+Unit::Unit(bool isWorldObject): WorldObject(isWorldObject),
m_movedPlayer(NULL), m_lastSanctuaryTime(0), IsAIEnabled(false), NeedChangeAI(false),
m_ControlledByPlayer(false), i_AI(NULL), i_disabledAI(NULL), m_procDeep(0),
m_removedAurasCount(0), i_motionMaster(this), m_ThreatManager(this), m_vehicle(NULL),
@@ -1478,9 +1478,13 @@ bool Unit::IsDamageReducedByArmor(SpellSchoolMask schoolMask, SpellInfo const* s
return false;
// bleeding effects are not reduced by armor
- if (effIndex != MAX_SPELL_EFFECTS && spellInfo->Effects[effIndex].ApplyAuraName == SPELL_AURA_PERIODIC_DAMAGE)
- if (spellInfo->GetEffectMechanicMask(effIndex) & (1<<MECHANIC_BLEED))
- return false;
+ if (effIndex != MAX_SPELL_EFFECTS)
+ {
+ if (spellInfo->Effects[effIndex].ApplyAuraName == SPELL_AURA_PERIODIC_DAMAGE ||
+ spellInfo->Effects[effIndex].Effect == SPELL_EFFECT_SCHOOL_DAMAGE)
+ if (spellInfo->GetEffectMechanicMask(effIndex) & (1<<MECHANIC_BLEED))
+ return false;
+ }
}
return true;
}
@@ -1922,12 +1926,7 @@ void Unit::AttackerStateUpdate (Unit* victim, WeaponAttackType attType, bool ext
CombatStart(victim);
RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_MELEE_ATTACK);
- uint32 hitInfo;
- if (attType == BASE_ATTACK)
- hitInfo = HITINFO_NORMALSWING2;
- else if (attType == OFF_ATTACK)
- hitInfo = HITINFO_LEFTSWING;
- else
+ if (attType != BASE_ATTACK && attType != OFF_ATTACK)
return; // ignore ranged case
// melee attack spell casted at main hand attack only - no normal melee dmg dealt
@@ -5470,7 +5469,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
case CLASS_DRUID:
RandomSpells.push_back(71484);
RandomSpells.push_back(71485);
- RandomSpells.push_back(71486);
+ RandomSpells.push_back(71492);
break;
case CLASS_HUNTER:
RandomSpells.push_back(71486);
@@ -5516,7 +5515,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
case CLASS_DRUID:
RandomSpells.push_back(71561);
RandomSpells.push_back(71556);
- RandomSpells.push_back(71558);
+ RandomSpells.push_back(71560);
break;
case CLASS_HUNTER:
RandomSpells.push_back(71558);
@@ -6498,7 +6497,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
RemoveAura(57934);
if (!redirectTarget)
break;
- redirectTarget->CastSpell(this,59628,true);
+ CastSpell(this,59628,true);
CastSpell(redirectTarget,57933,true);
break;
}
@@ -8920,6 +8919,20 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
}
break;
}
+ case 46916: // Slam! (Bloodsurge proc)
+ case 52437: // Sudden Death
+ {
+ // Item - Warrior T10 Melee 4P Bonus
+ if (AuraEffect const* aurEff = GetAuraEffect(70847, 0))
+ {
+ if (!roll_chance_i(aurEff->GetAmount()))
+ break;
+ CastSpell(this, 70849, true, castItem, triggeredByAura); // Extra Charge!
+ CastSpell(this, 71072, true, castItem, triggeredByAura); // Slam GCD Reduced
+ CastSpell(this, 71069, true, castItem, triggeredByAura); // Execute GCD Reduced
+ }
+ break;
+ }
// Sword and Board
case 50227:
{
@@ -11929,7 +11942,7 @@ void Unit::Mount(uint32 mount, uint32 VehicleId, uint32 creatureEntry)
RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_MOUNT);
}
-void Unit::Unmount()
+void Unit::Dismount()
{
if (!IsMounted())
return;
@@ -11950,7 +11963,7 @@ void Unit::Unmount()
data.appendPackGUID(GetGUID());
SendMessageToSet(&data, true);
- // unmount as a vehicle
+ // dismount as a vehicle
if (GetTypeId() == TYPEID_PLAYER && GetVehicleKit())
{
// Send other players that we are no longer a vehicle
@@ -12072,7 +12085,7 @@ void Unit::SetInCombatState(bool PvP, Unit* enemy)
}
if (!(creature->GetCreatureInfo()->type_flags & CREATURE_TYPEFLAGS_MOUNTED_COMBAT))
- Unmount();
+ Dismount();
}
for (Unit::ControlList::iterator itr = m_Controlled.begin(); itr != m_Controlled.end(); ++itr)
@@ -14300,6 +14313,7 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u
if (procTriggered.empty())
return;
+ // Note: must SetCantProc(false) before return
if (procExtra & (PROC_EX_INTERNAL_TRIGGERED | PROC_EX_INTERNAL_CANT_PROC))
SetCantProc(true);
@@ -14324,6 +14338,7 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u
if (GetTypeId() == TYPEID_PLAYER && i->spellProcEvent && i->spellProcEvent->cooldown)
cooldown = i->spellProcEvent->cooldown;
+ // Note: must SetCantProc(false) before return
if (spellInfo->AttributesEx3 & SPELL_ATTR3_DISABLE_PROC)
SetCantProc(true);
@@ -14336,176 +14351,179 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u
}
if (!handled)
- for (uint8 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex)
{
- if (!(i->effMask & (1<<effIndex)))
- continue;
-
- AuraEffect* triggeredByAura = i->aura->GetEffect(effIndex);
- ASSERT(triggeredByAura);
-
- switch (triggeredByAura->GetAuraType())
+ for (uint8 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex)
{
- case SPELL_AURA_PROC_TRIGGER_SPELL:
- {
- sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "ProcDamageAndSpell: casting spell %u (triggered by %s aura of spell %u)", spellInfo->Id, (isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());
- // Don`t drop charge or add cooldown for not started trigger
- if (HandleProcTriggerSpell(target, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown))
- takeCharges = true;
- break;
- }
- case SPELL_AURA_PROC_TRIGGER_DAMAGE:
- {
- // target has to be valid
- if (!target)
- return;
-
- sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "ProcDamageAndSpell: doing %u damage from spell id %u (triggered by %s aura of spell %u)", triggeredByAura->GetAmount(), spellInfo->Id, (isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());
- SpellNonMeleeDamage damageInfo(this, target, spellInfo->Id, spellInfo->SchoolMask);
- uint32 newDamage = SpellDamageBonus(target, spellInfo, triggeredByAura->GetAmount(), SPELL_DIRECT_DAMAGE);
- CalculateSpellDamageTaken(&damageInfo, newDamage, spellInfo);
- DealDamageMods(damageInfo.target, damageInfo.damage, &damageInfo.absorb);
- SendSpellNonMeleeDamageLog(&damageInfo);
- DealSpellDamage(&damageInfo, true);
- takeCharges = true;
- break;
- }
- case SPELL_AURA_MANA_SHIELD:
- case SPELL_AURA_DUMMY:
- {
- sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "ProcDamageAndSpell: casting spell id %u (triggered by %s dummy aura of spell %u)", spellInfo->Id, (isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());
- if (HandleDummyAuraProc(target, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown))
- takeCharges = true;
- break;
- }
- case SPELL_AURA_OBS_MOD_POWER:
- sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "ProcDamageAndSpell: casting spell id %u (triggered by %s aura of spell %u)", spellInfo->Id, (isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());
- if (HandleObsModEnergyAuraProc(target, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown))
- takeCharges = true;
- break;
- case SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN:
- sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "ProcDamageAndSpell: casting spell id %u (triggered by %s aura of spell %u)", spellInfo->Id, (isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());
- if (HandleModDamagePctTakenAuraProc(target, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown))
- takeCharges = true;
- break;
- case SPELL_AURA_MOD_MELEE_HASTE:
- {
- sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "ProcDamageAndSpell: casting spell id %u (triggered by %s haste aura of spell %u)", spellInfo->Id, (isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());
- if (HandleHasteAuraProc(target, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown))
- takeCharges = true;
- break;
- }
- case SPELL_AURA_OVERRIDE_CLASS_SCRIPTS:
- {
- sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "ProcDamageAndSpell: casting spell id %u (triggered by %s aura of spell %u)", spellInfo->Id, (isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());
- if (HandleOverrideClassScriptAuraProc(target, damage, triggeredByAura, procSpell, cooldown))
- takeCharges = true;
- break;
- }
- case SPELL_AURA_RAID_PROC_FROM_CHARGE_WITH_VALUE:
- {
- sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "ProcDamageAndSpell: casting mending (triggered by %s dummy aura of spell %u)",
- (isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());
+ if (!(i->effMask & (1<<effIndex)))
+ continue;
- HandleAuraRaidProcFromChargeWithValue(triggeredByAura);
- takeCharges = true;
- break;
- }
- case SPELL_AURA_RAID_PROC_FROM_CHARGE:
- {
- sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "ProcDamageAndSpell: casting mending (triggered by %s dummy aura of spell %u)",
- (isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());
+ AuraEffect* triggeredByAura = i->aura->GetEffect(effIndex);
+ ASSERT(triggeredByAura);
- HandleAuraRaidProcFromCharge(triggeredByAura);
- takeCharges = true;
- break;
- }
- case SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE:
+ switch (triggeredByAura->GetAuraType())
{
- sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "ProcDamageAndSpell: casting spell %u (triggered with value by %s aura of spell %u)", spellInfo->Id, (isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());
+ case SPELL_AURA_PROC_TRIGGER_SPELL:
+ {
+ sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "ProcDamageAndSpell: casting spell %u (triggered by %s aura of spell %u)", spellInfo->Id, (isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());
+ // Don`t drop charge or add cooldown for not started trigger
+ if (HandleProcTriggerSpell(target, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown))
+ takeCharges = true;
+ break;
+ }
+ case SPELL_AURA_PROC_TRIGGER_DAMAGE:
+ {
+ // target has to be valid
+ if (!target)
+ break;
- if (HandleProcTriggerSpell(target, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown))
- takeCharges = true;
- break;
- }
- case SPELL_AURA_MOD_CASTING_SPEED_NOT_STACK:
- // Skip melee hits or instant cast spells
- if (procSpell && procSpell->CalcCastTime() != 0)
- takeCharges = true;
- break;
- case SPELL_AURA_REFLECT_SPELLS_SCHOOL:
- // Skip Melee hits and spells ws wrong school
- if (procSpell && (triggeredByAura->GetMiscValue() & procSpell->SchoolMask)) // School check
- takeCharges = true;
- break;
- case SPELL_AURA_MOD_POWER_COST_SCHOOL_PCT:
- case SPELL_AURA_MOD_POWER_COST_SCHOOL:
- // Skip melee hits and spells ws wrong school or zero cost
- if (procSpell &&
- (procSpell->ManaCost != 0 || procSpell->ManaCostPercentage != 0) && // Cost check
- (triggeredByAura->GetMiscValue() & procSpell->SchoolMask)) // School check
- takeCharges = true;
- break;
- case SPELL_AURA_MECHANIC_IMMUNITY:
- // Compare mechanic
- if (procSpell && procSpell->Mechanic == uint32(triggeredByAura->GetMiscValue()))
- takeCharges = true;
- break;
- case SPELL_AURA_MOD_MECHANIC_RESISTANCE:
- // Compare mechanic
- if (procSpell && procSpell->Mechanic == uint32(triggeredByAura->GetMiscValue()))
+ sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "ProcDamageAndSpell: doing %u damage from spell id %u (triggered by %s aura of spell %u)", triggeredByAura->GetAmount(), spellInfo->Id, (isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());
+ SpellNonMeleeDamage damageInfo(this, target, spellInfo->Id, spellInfo->SchoolMask);
+ uint32 newDamage = SpellDamageBonus(target, spellInfo, triggeredByAura->GetAmount(), SPELL_DIRECT_DAMAGE);
+ CalculateSpellDamageTaken(&damageInfo, newDamage, spellInfo);
+ DealDamageMods(damageInfo.target, damageInfo.damage, &damageInfo.absorb);
+ SendSpellNonMeleeDamageLog(&damageInfo);
+ DealSpellDamage(&damageInfo, true);
takeCharges = true;
- break;
- case SPELL_AURA_MOD_DAMAGE_FROM_CASTER:
- // Compare casters
- if (triggeredByAura->GetCasterGUID() == target->GetGUID())
- takeCharges = true;
- break;
- case SPELL_AURA_MOD_SPELL_CRIT_CHANCE:
- sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "ProcDamageAndSpell: casting spell id %u (triggered by %s spell crit chance aura of spell %u)", spellInfo->Id, (isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());
- if (procSpell && HandleSpellCritChanceAuraProc(target, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown))
+ break;
+ }
+ case SPELL_AURA_MANA_SHIELD:
+ case SPELL_AURA_DUMMY:
+ {
+ sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "ProcDamageAndSpell: casting spell id %u (triggered by %s dummy aura of spell %u)", spellInfo->Id, (isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());
+ if (HandleDummyAuraProc(target, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown))
+ takeCharges = true;
+ break;
+ }
+ case SPELL_AURA_OBS_MOD_POWER:
+ sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "ProcDamageAndSpell: casting spell id %u (triggered by %s aura of spell %u)", spellInfo->Id, (isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());
+ if (HandleObsModEnergyAuraProc(target, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown))
+ takeCharges = true;
+ break;
+ case SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN:
+ sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "ProcDamageAndSpell: casting spell id %u (triggered by %s aura of spell %u)", spellInfo->Id, (isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());
+ if (HandleModDamagePctTakenAuraProc(target, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown))
+ takeCharges = true;
+ break;
+ case SPELL_AURA_MOD_MELEE_HASTE:
+ {
+ sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "ProcDamageAndSpell: casting spell id %u (triggered by %s haste aura of spell %u)", spellInfo->Id, (isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());
+ if (HandleHasteAuraProc(target, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown))
+ takeCharges = true;
+ break;
+ }
+ case SPELL_AURA_OVERRIDE_CLASS_SCRIPTS:
+ {
+ sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "ProcDamageAndSpell: casting spell id %u (triggered by %s aura of spell %u)", spellInfo->Id, (isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());
+ if (HandleOverrideClassScriptAuraProc(target, damage, triggeredByAura, procSpell, cooldown))
+ takeCharges = true;
+ break;
+ }
+ case SPELL_AURA_RAID_PROC_FROM_CHARGE_WITH_VALUE:
+ {
+ sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "ProcDamageAndSpell: casting mending (triggered by %s dummy aura of spell %u)",
+ (isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());
+
+ HandleAuraRaidProcFromChargeWithValue(triggeredByAura);
takeCharges = true;
- break;
- // CC Auras which use their amount amount to drop
- // Are there any more auras which need this?
- case SPELL_AURA_MOD_CONFUSE:
- case SPELL_AURA_MOD_FEAR:
- case SPELL_AURA_MOD_STUN:
- case SPELL_AURA_MOD_ROOT:
- case SPELL_AURA_TRANSFORM:
- {
- // chargeable mods are breaking on hit
- if (useCharges)
+ break;
+ }
+ case SPELL_AURA_RAID_PROC_FROM_CHARGE:
+ {
+ sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "ProcDamageAndSpell: casting mending (triggered by %s dummy aura of spell %u)",
+ (isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());
+
+ HandleAuraRaidProcFromCharge(triggeredByAura);
takeCharges = true;
- else
+ break;
+ }
+ case SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE:
{
- // Spell own direct damage at apply wont break the CC
- if (procSpell && (procSpell->Id == triggeredByAura->GetId()))
+ sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "ProcDamageAndSpell: casting spell %u (triggered with value by %s aura of spell %u)", spellInfo->Id, (isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());
+
+ if (HandleProcTriggerSpell(target, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown))
+ takeCharges = true;
+ break;
+ }
+ case SPELL_AURA_MOD_CASTING_SPEED_NOT_STACK:
+ // Skip melee hits or instant cast spells
+ if (procSpell && procSpell->CalcCastTime() != 0)
+ takeCharges = true;
+ break;
+ case SPELL_AURA_REFLECT_SPELLS_SCHOOL:
+ // Skip Melee hits and spells ws wrong school
+ if (procSpell && (triggeredByAura->GetMiscValue() & procSpell->SchoolMask)) // School check
+ takeCharges = true;
+ break;
+ case SPELL_AURA_MOD_POWER_COST_SCHOOL_PCT:
+ case SPELL_AURA_MOD_POWER_COST_SCHOOL:
+ // Skip melee hits and spells ws wrong school or zero cost
+ if (procSpell &&
+ (procSpell->ManaCost != 0 || procSpell->ManaCostPercentage != 0) && // Cost check
+ (triggeredByAura->GetMiscValue() & procSpell->SchoolMask)) // School check
+ takeCharges = true;
+ break;
+ case SPELL_AURA_MECHANIC_IMMUNITY:
+ // Compare mechanic
+ if (procSpell && procSpell->Mechanic == uint32(triggeredByAura->GetMiscValue()))
+ takeCharges = true;
+ break;
+ case SPELL_AURA_MOD_MECHANIC_RESISTANCE:
+ // Compare mechanic
+ if (procSpell && procSpell->Mechanic == uint32(triggeredByAura->GetMiscValue()))
+ takeCharges = true;
+ break;
+ case SPELL_AURA_MOD_DAMAGE_FROM_CASTER:
+ // Compare casters
+ if (triggeredByAura->GetCasterGUID() == target->GetGUID())
+ takeCharges = true;
+ break;
+ case SPELL_AURA_MOD_SPELL_CRIT_CHANCE:
+ sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "ProcDamageAndSpell: casting spell id %u (triggered by %s spell crit chance aura of spell %u)", spellInfo->Id, (isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());
+ if (procSpell && HandleSpellCritChanceAuraProc(target, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown))
+ takeCharges = true;
+ break;
+ // CC Auras which use their amount amount to drop
+ // Are there any more auras which need this?
+ case SPELL_AURA_MOD_CONFUSE:
+ case SPELL_AURA_MOD_FEAR:
+ case SPELL_AURA_MOD_STUN:
+ case SPELL_AURA_MOD_ROOT:
+ case SPELL_AURA_TRANSFORM:
+ {
+ // chargeable mods are breaking on hit
+ if (useCharges)
+ takeCharges = true;
+ else
{
- Aura* aura = triggeredByAura->GetBase();
- // called from spellcast, should not have ticked yet
- if (aura->GetDuration() == aura->GetMaxDuration())
- break;
+ // Spell own direct damage at apply wont break the CC
+ if (procSpell && (procSpell->Id == triggeredByAura->GetId()))
+ {
+ Aura* aura = triggeredByAura->GetBase();
+ // called from spellcast, should not have ticked yet
+ if (aura->GetDuration() == aura->GetMaxDuration())
+ break;
+ }
+ int32 damageLeft = triggeredByAura->GetAmount();
+ // No damage left
+ if (damageLeft < int32(damage))
+ i->aura->Remove();
+ else
+ triggeredByAura->SetAmount(damageLeft - damage);
}
- int32 damageLeft = triggeredByAura->GetAmount();
- // No damage left
- if (damageLeft < int32(damage))
- i->aura->Remove();
- else
- triggeredByAura->SetAmount(damageLeft - damage);
+ break;
}
- break;
- }
- //case SPELL_AURA_ADD_FLAT_MODIFIER:
- //case SPELL_AURA_ADD_PCT_MODIFIER:
- // HandleSpellModAuraProc
- //break;
- default:
- // nothing do, just charges counter
- takeCharges = true;
- break;
- }
- }
+ //case SPELL_AURA_ADD_FLAT_MODIFIER:
+ //case SPELL_AURA_ADD_PCT_MODIFIER:
+ // HandleSpellModAuraProc
+ //break;
+ default:
+ // nothing do, just charges counter
+ takeCharges = true;
+ break;
+ } // switch (triggeredByAura->GetAuraType())
+ } // for (uint8 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex)
+ } // if (!handled)
+
// Remove charge (aura can be removed by triggers)
if (useCharges && takeCharges)
i->aura->DropCharge(AURA_REMOVE_BY_EXPIRE);
@@ -15593,29 +15611,17 @@ void Unit::Kill(Unit* victim, bool durabilityLoss)
}
// Hook for OnPVPKill Event
- if (GetTypeId() == TYPEID_PLAYER)
+ if (Player* killerPlr = ToPlayer())
{
- if (victim->GetTypeId() == TYPEID_PLAYER)
- {
- Player* killer = ToPlayer();
- Player* killed = victim->ToPlayer();
- sScriptMgr->OnPVPKill(killer, killed);
- }
- else if (victim->GetTypeId() == TYPEID_UNIT)
- {
- Player* killer = ToPlayer();
- Creature* killed = victim->ToCreature();
- sScriptMgr->OnCreatureKill(killer, killed);
- }
+ if (Player* killedPlr = victim->ToPlayer())
+ sScriptMgr->OnPVPKill(killerPlr, killedPlr);
+ else if (Creature* killedCre = victim->ToCreature())
+ sScriptMgr->OnCreatureKill(killerPlr, killedCre);
}
- else if (GetTypeId() == TYPEID_UNIT)
+ else if (Creature* killerCre = ToCreature())
{
- if (victim->GetTypeId() == TYPEID_PLAYER)
- {
- Creature* killer = ToCreature();
- Player* killed = victim->ToPlayer();
- sScriptMgr->OnPlayerKilledByCreature(killer, killed);
- }
+ if (Player* killed = victim->ToPlayer())
+ sScriptMgr->OnPlayerKilledByCreature(killerCre, killed);
}
if (victim->GetVehicle())
@@ -15851,9 +15857,9 @@ bool Unit::SetCharmedBy(Unit* charmer, CharmType type, AuraApplication const* au
if (!charmer)
return false;
- // unmount players when charmed
+ // dismount players when charmed
if (GetTypeId() == TYPEID_PLAYER)
- Unmount();
+ Dismount();
ASSERT(type != CHARM_TYPE_POSSESS || charmer->GetTypeId() == TYPEID_PLAYER);
ASSERT((type == CHARM_TYPE_VEHICLE) == IsVehicle());
@@ -16999,7 +17005,7 @@ void Unit::_EnterVehicle(Vehicle* vehicle, int8 seatId, AuraApplication const* a
InterruptNonMeleeSpells(false);
player->StopCastingCharm();
player->StopCastingBindSight();
- Unmount();
+ Dismount();
RemoveAurasByType(SPELL_AURA_MOUNTED);
// drop flag at invisible in bg
@@ -17099,7 +17105,7 @@ void Unit::_ExitVehicle(Position const* exitPosition)
// Vehicle just died, we die too
if (vehicle->GetBase()->getDeathState() == JUST_DIED)
setDeathState(JUST_DIED);
- // If for other reason we as minion are exiting the vehicle (ejected, master unmounted) - unsummon
+ // If for other reason we as minion are exiting the vehicle (ejected, master dismounted) - unsummon
else
ToTempSummon()->UnSummon(2000); // Approximation
}
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index 5906a7f3a2b..b18223ae3ce 100755
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -65,7 +65,7 @@ enum SpellAuraInterruptFlags
AURA_INTERRUPT_FLAG_MOVE = 0x00000008, // 3 removed by any movement
AURA_INTERRUPT_FLAG_TURNING = 0x00000010, // 4 removed by any turning
AURA_INTERRUPT_FLAG_JUMP = 0x00000020, // 5 removed by entering combat
- AURA_INTERRUPT_FLAG_NOT_MOUNTED = 0x00000040, // 6 removed by unmounting
+ AURA_INTERRUPT_FLAG_NOT_MOUNTED = 0x00000040, // 6 removed by dismounting
AURA_INTERRUPT_FLAG_NOT_ABOVEWATER = 0x00000080, // 7 removed by entering water
AURA_INTERRUPT_FLAG_NOT_UNDERWATER = 0x00000100, // 8 removed by leaving water
AURA_INTERRUPT_FLAG_NOT_SHEATHED = 0x00000200, // 9 removed by unsheathing
@@ -1441,7 +1441,7 @@ class Unit : public WorldObject
bool IsMounted() const { return HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_MOUNT); }
uint32 GetMountID() const { return GetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID); }
void Mount(uint32 mount, uint32 vehicleId = 0, uint32 creatureEntry = 0);
- void Unmount();
+ void Dismount();
uint16 GetMaxSkillValueForLevel(Unit const* target = NULL) const { return (target ? getLevelForTarget(target) : getLevel()) * 5; }
void DealDamageMods(Unit* pVictim, uint32 &damage, uint32* absorb);
@@ -2233,7 +2233,7 @@ class Unit : public WorldObject
}
protected:
- explicit Unit ();
+ explicit Unit (bool isWorldObject);
UnitAI* i_AI, *i_disabledAI;
diff --git a/src/server/game/Entities/Vehicle/Vehicle.cpp b/src/server/game/Entities/Vehicle/Vehicle.cpp
index fe018ec78ce..d3c3268e9ce 100755
--- a/src/server/game/Entities/Vehicle/Vehicle.cpp
+++ b/src/server/game/Entities/Vehicle/Vehicle.cpp
@@ -341,7 +341,7 @@ bool Vehicle::AddPassenger(Unit* unit, int8 seatId)
}
}
- if (seat->second.SeatInfo->m_flags && !(seat->second.SeatInfo->m_flags & VEHICLE_SEAT_FLAG_UNK11))
+ if (seat->second.SeatInfo->m_flags && !(seat->second.SeatInfo->m_flags & VEHICLE_SEAT_FLAG_UNK1))
unit->AddUnitState(UNIT_STAT_ONVEHICLE);
unit->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT);
diff --git a/src/server/game/Events/GameEventMgr.cpp b/src/server/game/Events/GameEventMgr.cpp
index d3cc27c9e6c..5cb130b93e4 100755
--- a/src/server/game/Events/GameEventMgr.cpp
+++ b/src/server/game/Events/GameEventMgr.cpp
@@ -27,6 +27,8 @@
#include "GossipDef.h"
#include "Player.h"
#include "BattlegroundMgr.h"
+#include "UnitAI.h"
+#include "GameObjectAI.h"
bool GameEventMgr::CheckOneGameEvent(uint16 entry) const
{
@@ -1059,6 +1061,8 @@ uint32 GameEventMgr::Update() // return the next e
void GameEventMgr::UnApplyEvent(uint16 event_id)
{
sLog->outDetail("GameEvent %u \"%s\" removed.", event_id, mGameEvent[event_id].description.c_str());
+ //! Run SAI scripts with SMART_EVENT_GAME_EVENT_END
+ RunSmartAIScripts(event_id, false);
// un-spawn positive event tagged objects
GameEventUnspawn(event_id);
// spawn negative event tagget objects
@@ -1090,6 +1094,9 @@ void GameEventMgr::ApplyNewEvent(uint16 event_id)
sLog->outDetail("GameEvent %u \"%s\" started.", event_id, mGameEvent[event_id].description.c_str());
+ //! Run SAI scripts with SMART_EVENT_GAME_EVENT_END
+ RunSmartAIScripts(event_id, true);
+
// spawn positive event tagget objects
GameEventSpawn(event_id);
// un-spawn negative event tagged objects
@@ -1601,6 +1608,26 @@ void GameEventMgr::SendWorldStateUpdate(Player* player, uint16 event_id)
}
}
+void GameEventMgr::RunSmartAIScripts(uint16 event_id, bool activate)
+{
+ //! Iterate over every supported source type (creature and gameobject)
+ //! Not entirely sure how this will affect units in non-loaded grids.
+ {
+ TRINITY_READ_GUARD(HashMapHolder<Creature>::LockType, *HashMapHolder<Creature>::GetLock());
+ HashMapHolder<Creature>::MapType const& m = ObjectAccessor::GetCreatures();
+ for (HashMapHolder<Creature>::MapType::const_iterator iter = m.begin(); iter != m.end(); ++iter)
+ if (iter->second->IsInWorld())
+ iter->second->AI()->sOnGameEvent(activate, event_id);
+ }
+ {
+ TRINITY_READ_GUARD(HashMapHolder<GameObject>::LockType, *HashMapHolder<GameObject>::GetLock());
+ HashMapHolder<GameObject>::MapType const& m = ObjectAccessor::GetGameObjects();
+ for (HashMapHolder<GameObject>::MapType::const_iterator iter = m.begin(); iter != m.end(); ++iter)
+ if (iter->second->IsInWorld())
+ iter->second->AI()->OnGameEvent(activate, event_id);
+ }
+}
+
bool IsHolidayActive(HolidayIds id)
{
if (id == HOLIDAY_NONE)
diff --git a/src/server/game/Events/GameEventMgr.h b/src/server/game/Events/GameEventMgr.h
index a2a35a85098..bba92b4d24c 100755
--- a/src/server/game/Events/GameEventMgr.h
+++ b/src/server/game/Events/GameEventMgr.h
@@ -132,6 +132,7 @@ class GameEventMgr
void UpdateEventNPCFlags(uint16 event_id);
void UpdateEventNPCVendor(uint16 event_id, bool activate);
void UpdateBattlegroundSettings();
+ void RunSmartAIScripts(uint16 event_id, bool activate); //! Runs SMART_EVENT_GAME_EVENT_START/_END SAI
bool CheckOneGameEventConditions(uint16 event_id);
void SaveWorldEventStateToDB(uint16 event_id);
bool hasCreatureQuestActiveEventExcept(uint32 quest_id, uint16 event_id);
diff --git a/src/server/game/Globals/ObjectAccessor.h b/src/server/game/Globals/ObjectAccessor.h
index 25fa20dce70..92c947eb86f 100755
--- a/src/server/game/Globals/ObjectAccessor.h
+++ b/src/server/game/Globals/ObjectAccessor.h
@@ -201,16 +201,16 @@ class ObjectAccessor
}
// when using this, you must use the hashmapholder's lock
- //HashMapHolder<Creature>::MapType& GetCreatures()
- //{
- // return HashMapHolder<Creature>::GetContainer();
- //}
-
- //// when using this, you must use the hashmapholder's lock
- //HashMapHolder<GameObject>::MapType& GetGameObjects()
- //{
- // return HashMapHolder<GameObject>::GetContainer();
- //}
+ static HashMapHolder<Creature>::MapType const& GetCreatures()
+ {
+ return HashMapHolder<Creature>::GetContainer();
+ }
+
+ // when using this, you must use the hashmapholder's lock
+ static HashMapHolder<GameObject>::MapType const& GetGameObjects()
+ {
+ return HashMapHolder<GameObject>::GetContainer();
+ }
template<class T> static void AddObject(T* object)
{
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index 75573367241..5353e048066 100755
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -3818,11 +3818,11 @@ void ObjectMgr::LoadQuests()
// no changes, quest not dependent from this value but can have problems at client (note some may be 0, we must allow this so no check)
}
//check for proper RequiredSkillId value (skill case)
- if (int32 skill_id = SkillByQuestSort(-int32(qinfo->ZoneOrSort)))
+ if (uint32 skill_id = SkillByQuestSort(-int32(qinfo->ZoneOrSort)))
{
if (qinfo->RequiredSkillId != skill_id)
{
- sLog->outErrorDb("Quest %u has `ZoneOrSort` = %i but `RequiredSkillId` does not have a corresponding value (%i).",
+ sLog->outErrorDb("Quest %u has `ZoneOrSort` = %i but `RequiredSkillId` does not have a corresponding value (%d).",
qinfo->GetQuestId(), qinfo->ZoneOrSort, skill_id);
//override, and force proper value here?
}
@@ -6721,9 +6721,15 @@ void ObjectMgr::LoadCorpses()
{
Field* fields = result->Fetch();
uint32 guid = fields[16].GetUInt32();
+ CorpseType type = CorpseType(fields[13].GetUInt8());
+ if (type >= MAX_CORPSE_TYPE)
+ {
+ sLog->outError("Corpse (guid: %u) have wrong corpse type (%u), not loading.", guid, type);
+ continue;
+ }
- Corpse* corpse = new Corpse();
- if (!corpse->LoadFromDB(guid, fields))
+ Corpse* corpse = new Corpse(type);
+ if (!corpse->LoadCorpseFromDB(guid, fields))
{
delete corpse;
continue;
@@ -8040,8 +8046,11 @@ bool ObjectMgr::AddGameTele(GameTele& tele)
m_GameTeleMap[new_id] = tele;
+ std::string safeName(tele.name);
+ WorldDatabase.EscapeString(safeName);
+
WorldDatabase.PExecute("INSERT INTO game_tele (id, position_x, position_y, position_z, orientation, map, name) VALUES (%u, %f, %f, %f, %f, %d, '%s')",
- new_id, tele.position_x, tele.position_y, tele.position_z, tele.orientation, tele.mapId, tele.name.c_str());
+ new_id, tele.position_x, tele.position_y, tele.position_z, tele.orientation, tele.mapId, safeName.c_str());
return true;
}
diff --git a/src/server/game/Grids/Grid.h b/src/server/game/Grids/Grid.h
index 448c4cb35fd..7e66cf1080a 100755
--- a/src/server/game/Grids/Grid.h
+++ b/src/server/game/Grids/Grid.h
@@ -100,7 +100,12 @@ class Grid
/** Returns the number of object within the grid.
*/
- unsigned int ActiveObjectsInGrid(void) const { return /*m_activeGridObjects.size()+*/i_objects.template Count<ACTIVE_OBJECT>(); }
+ //unsigned int ActiveObjectsInGrid(void) const { return i_objects.template Count<ACTIVE_OBJECT>(); }
+ template<class T>
+ uint32 GetWorldObjectCountInGrid() const
+ {
+ return i_objects.template Count<T>();
+ }
/** Inserts a container type object into the grid.
*/
diff --git a/src/server/game/Grids/GridStates.cpp b/src/server/game/Grids/GridStates.cpp
index 5f88516c9ac..4e63388c356 100755
--- a/src/server/game/Grids/GridStates.cpp
+++ b/src/server/game/Grids/GridStates.cpp
@@ -31,7 +31,7 @@ void ActiveState::Update(Map &m, NGridType &grid, GridInfo & info, const uint32
info.UpdateTimeTracker(t_diff);
if (info.getTimeTracker().Passed())
{
- if (grid.ActiveObjectsInGrid() == 0 && !m.ActiveObjectsNearGrid(grid))
+ if (!grid.GetWorldObjectCountInNGrid<Player>() && !m.ActiveObjectsNearGrid(grid))
{
ObjectGridStoper worker;
TypeContainerVisitor<ObjectGridStoper, GridTypeMapContainer> visitor(worker);
diff --git a/src/server/game/Grids/NGrid.h b/src/server/game/Grids/NGrid.h
index 97a47f7d272..c87fd7e6129 100755
--- a/src/server/game/Grids/NGrid.h
+++ b/src/server/game/Grids/NGrid.h
@@ -158,14 +158,28 @@ class NGrid
GetGridType(x, y).Visit(visitor);
}
- unsigned int ActiveObjectsInGrid(void) const
+ //This gets the player count in grid
+ //I disable this to avoid confusion (active object usually means something else)
+ /*
+ uint32 GetActiveObjectCountInGrid() const
{
- unsigned int count=0;
- for (unsigned int x=0; x < N; ++x)
- for (unsigned int y=0; y < N; ++y)
+ uint32 count = 0;
+ for (uint32 x = 0; x < N; ++x)
+ for (uint32 y = 0; y < N; ++y)
count += i_cells[x][y].ActiveObjectsInGrid();
return count;
}
+ */
+
+ template<class T>
+ uint32 GetWorldObjectCountInNGrid() const
+ {
+ uint32 count = 0;
+ for (uint32 x = 0; x < N; ++x)
+ for (uint32 y = 0; y < N; ++y)
+ count += i_cells[x][y].template GetWorldObjectCountInGrid<T>();
+ return count;
+ }
private:
uint32 i_gridId;
diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.cpp b/src/server/game/Grids/Notifiers/GridNotifiers.cpp
index ca61a82e840..99d402b4add 100755
--- a/src/server/game/Grids/Notifiers/GridNotifiers.cpp
+++ b/src/server/game/Grids/Notifiers/GridNotifiers.cpp
@@ -344,7 +344,7 @@ bool AnyDeadUnitObjectInRangeCheck::operator()(Creature* u)
bool AnyDeadUnitSpellTargetInRangeCheck::operator()(Player* u)
{
return AnyDeadUnitObjectInRangeCheck::operator()(u)
- && i_spellInfo->CheckTarget(i_searchObj, u, true)
+ && (i_spellInfo->CheckTarget(i_searchObj, u, true) == SPELL_CAST_OK)
&& i_searchObj->IsTargetMatchingCheck(u, i_check);
}
@@ -352,14 +352,14 @@ bool AnyDeadUnitSpellTargetInRangeCheck::operator()(Corpse* u)
{
Player* owner = ObjectAccessor::FindPlayer(u->GetOwnerGUID());
return owner && AnyDeadUnitObjectInRangeCheck::operator()(u)
- && i_spellInfo->CheckTarget(i_searchObj, owner, true)
+ && (i_spellInfo->CheckTarget(i_searchObj, owner, true) == SPELL_CAST_OK)
&& i_searchObj->IsTargetMatchingCheck(owner, i_check);
}
bool AnyDeadUnitSpellTargetInRangeCheck::operator()(Creature* u)
{
return AnyDeadUnitObjectInRangeCheck::operator()(u)
- && i_spellInfo->CheckTarget(i_searchObj, u, true)
+ && (i_spellInfo->CheckTarget(i_searchObj, u, true) == SPELL_CAST_OK)
&& i_searchObj->IsTargetMatchingCheck(u, i_check);
}
diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp
index 6311066f597..11175b13114 100755
--- a/src/server/game/Groups/Group.cpp
+++ b/src/server/game/Groups/Group.cpp
@@ -1121,6 +1121,7 @@ void Group::CountTheRoll(Rolls::iterator rollI, uint32 NumberOfPlayers)
roll->getLoot()->unlootedCount--;
ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(roll->itemid);
player->AutoStoreLoot(pProto->DisenchantID, LootTemplates_Disenchant, true);
+ player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL, 13262); // Disenchant
}
}
}
diff --git a/src/server/game/Guilds/Guild.cpp b/src/server/game/Guilds/Guild.cpp
index 59c107bd40f..94fcbbdda25 100755
--- a/src/server/game/Guilds/Guild.cpp
+++ b/src/server/game/Guilds/Guild.cpp
@@ -1993,6 +1993,7 @@ bool Guild::Validate()
}
}
}
+
if (broken_ranks)
{
m_ranks.clear();
diff --git a/src/server/game/Mails/Mail.cpp b/src/server/game/Mails/Mail.cpp
index 6d54aacb311..e5de3e35956 100755
--- a/src/server/game/Mails/Mail.cpp
+++ b/src/server/game/Mails/Mail.cpp
@@ -171,6 +171,7 @@ void MailDraft::SendReturnToSender(uint32 sender_acc, uint32 sender_guid, uint32
void MailDraft::SendMailTo(SQLTransaction& trans, MailReceiver const& receiver, MailSender const& sender, MailCheckMask checked, uint32 deliver_delay)
{
Player* pReceiver = receiver.GetPlayer(); // can be NULL
+ Player* pSender = sObjectMgr->GetPlayerByLowGUID(sender.GetSenderId());
if (pReceiver)
prepareItems(pReceiver, trans); // generate mail template items
@@ -188,9 +189,12 @@ void MailDraft::SendMailTo(SQLTransaction& trans, MailReceiver const& receiver,
// mail from battlemaster (rewardmarks) should last only one day
else if (sender.GetMailMessageType() == MAIL_CREATURE && sBattlegroundMgr->GetBattleMasterBG(sender.GetSenderId()) != BATTLEGROUND_TYPE_NONE)
expire_delay = DAY;
- // default case: expire time if COD 3 days, if no COD 30 days
+ // default case: expire time if COD 3 days, if no COD 30 days (or 90 days if sender is a game master)
else
- expire_delay = (m_COD > 0) ? 3 * DAY : 30 * DAY;
+ if (m_COD)
+ expire_delay = 3 * DAY;
+ else
+ expire_delay = pSender && pSender->isGameMaster() ? 90 * DAY : 30 * DAY;
time_t expire_time = deliver_time + expire_delay;
diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp
index 13a47633b53..34a7b60bcbd 100755
--- a/src/server/game/Maps/Map.cpp
+++ b/src/server/game/Maps/Map.cpp
@@ -30,6 +30,7 @@
#include "MapManager.h"
#include "ObjectMgr.h"
#include "Group.h"
+#include "LFGMgr.h"
union u_map_magic
{
@@ -58,7 +59,7 @@ Map::~Map()
while (!i_worldObjects.empty())
{
WorldObject* obj = *i_worldObjects.begin();
- ASSERT(obj->m_isWorldObject);
+ ASSERT(obj->IsWorldObject());
//ASSERT(obj->GetTypeId() == TYPEID_CORPSE);
obj->RemoveFromWorld();
obj->ResetMap();
@@ -237,7 +238,7 @@ template<class T>
void Map::AddToGrid(T* obj, Cell const& cell)
{
NGridType* grid = getNGrid(cell.GridX(), cell.GridY());
- if (obj->m_isWorldObject)
+ if (obj->IsWorldObject())
grid->GetGridType(cell.CellX(), cell.CellY()).template AddWorldObject<T>(obj);
else
grid->GetGridType(cell.CellX(), cell.CellY()).template AddGridObject<T>(obj);
@@ -247,7 +248,7 @@ template<>
void Map::AddToGrid(Creature* obj, Cell const& cell)
{
NGridType* grid = getNGrid(cell.GridX(), cell.GridY());
- if (obj->m_isWorldObject)
+ if (obj->IsWorldObject())
grid->GetGridType(cell.CellX(), cell.CellY()).AddWorldObject(obj);
else
grid->GetGridType(cell.CellX(), cell.CellY()).AddGridObject(obj);
@@ -255,9 +256,9 @@ void Map::AddToGrid(Creature* obj, Cell const& cell)
obj->SetCurrentCell(cell);
}
-template<class T>
-void Map::SwitchGridContainers(T* obj, bool on)
+void Map::SwitchGridContainers(Creature* obj, bool on)
{
+ ASSERT(!obj->IsPermanentWorldObject());
CellCoord p = Trinity::ComputeCellCoord(obj->GetPositionX(), obj->GetPositionY());
if (!p.IsCoordValid())
{
@@ -277,15 +278,18 @@ void Map::SwitchGridContainers(T* obj, bool on)
obj->RemoveFromGrid(); //This step is not really necessary but we want to do ASSERT in remove/add
if (on)
- grid.AddWorldObject<T>(obj);
+ {
+ grid.AddWorldObject(obj);
+ AddWorldObject(obj);
+ }
else
- grid.AddGridObject<T>(obj);
- obj->m_isWorldObject = on;
+ {
+ grid.AddGridObject(obj);
+ RemoveWorldObject(obj);
+ }
+ obj->m_isTempWorldObject = on;
}
-template void Map::SwitchGridContainers(Creature*, bool);
-//template void Map::SwitchGridContainers(DynamicObject*, bool);
-
template<class T>
void Map::DeleteFromWorld(T* obj)
{
@@ -685,8 +689,7 @@ void Map::RemoveFromMap(T *obj, bool remove)
}
}
-void
-Map::PlayerRelocation(Player* player, float x, float y, float z, float orientation)
+void Map::PlayerRelocation(Player* player, float x, float y, float z, float orientation)
{
ASSERT(player);
@@ -710,8 +713,7 @@ Map::PlayerRelocation(Player* player, float x, float y, float z, float orientati
player->UpdateObjectVisibility(false);
}
-void
-Map::CreatureRelocation(Creature* creature, float x, float y, float z, float ang, bool respawnRelocationOnFail)
+void Map::CreatureRelocation(Creature* creature, float x, float y, float z, float ang, bool respawnRelocationOnFail)
{
ASSERT(CheckGridIntegrity(creature, false));
@@ -910,8 +912,15 @@ bool Map::UnloadGrid(NGridType& ngrid, bool unloadAll)
const uint32 y = ngrid.getY();
{
- if (!unloadAll && ActiveObjectsNearGrid(ngrid))
- return false;
+ if (!unloadAll)
+ {
+ //pets, possessed creatures (must be active), transport passengers
+ if (ngrid.GetWorldObjectCountInNGrid<Creature>())
+ return false;
+
+ if (ActiveObjectsNearGrid(ngrid))
+ return false;
+ }
sLog->outDebug(LOG_FILTER_MAPS, "Unloading grid[%u, %u] for map %u", x, y, GetId());
@@ -1161,7 +1170,7 @@ bool GridMap::loadHeihgtData(FILE* in, uint32 offset, uint32 /*size*/)
return true;
}
-bool GridMap::loadLiquidData(FILE* in, uint32 offset, uint32 /*size*/)
+bool GridMap::loadLiquidData(FILE* in, uint32 offset, uint32 /*size*/)
{
map_liquidHeader header;
fseek(in, offset, SEEK_SET);
@@ -1203,12 +1212,12 @@ uint16 GridMap::getArea(float x, float y)
return m_area_map[lx*16 + ly];
}
-float GridMap::getHeightFromFlat(float /*x*/, float /*y*/) const
+float GridMap::getHeightFromFlat(float /*x*/, float /*y*/) const
{
return m_gridHeight;
}
-float GridMap::getHeightFromFloat(float x, float y) const
+float GridMap::getHeightFromFloat(float x, float y) const
{
if (!m_V8 || !m_V9)
return m_gridHeight;
@@ -1290,7 +1299,7 @@ float GridMap::getHeightFromFloat(float x, float y) const
return a * x + b * y + c;
}
-float GridMap::getHeightFromUint8(float x, float y) const
+float GridMap::getHeightFromUint8(float x, float y) const
{
if (!m_uint8_V8 || !m_uint8_V9)
return m_gridHeight;
@@ -1357,7 +1366,7 @@ float GridMap::getHeightFromUint8(float x, float y) const
return (float)((a * x) + (b * y) + c)*m_gridIntHeightMultiplier + m_gridHeight;
}
-float GridMap::getHeightFromUint16(float x, float y) const
+float GridMap::getHeightFromUint16(float x, float y) const
{
if (!m_uint16_V8 || !m_uint16_V9)
return m_gridHeight;
@@ -1424,7 +1433,7 @@ float GridMap::getHeightFromUint16(float x, float y) const
return (float)((a * x) + (b * y) + c)*m_gridIntHeightMultiplier + m_gridHeight;
}
-float GridMap::getLiquidLevel(float x, float y)
+float GridMap::getLiquidLevel(float x, float y)
{
if (!m_liquid_map)
return m_liquidLevel;
@@ -1443,7 +1452,7 @@ float GridMap::getLiquidLevel(float x, float y)
return m_liquid_map[cx_int*m_liquid_width + cy_int];
}
-uint8 GridMap::getTerrainType(float x, float y)
+uint8 GridMap::getTerrainType(float x, float y)
{
if (!m_liquid_type)
return 0;
@@ -1530,41 +1539,28 @@ inline GridMap* Map::GetGrid(float x, float y)
return GridMaps[gx][gy];
}
-float Map::GetHeight(float x, float y, float z, bool pUseVmaps, float maxSearchDist) const
+float Map::GetHeight(float x, float y, float z, bool checkVMap /*= true*/, float maxSearchDist /*= DEFAULT_HEIGHT_SEARCH*/) const
{
// find raw .map surface under Z coordinates
- float mapHeight;
+ float mapHeight = VMAP_INVALID_HEIGHT_VALUE;
if (GridMap* gmap = const_cast<Map*>(this)->GetGrid(x, y))
{
- float _mapheight = gmap->getHeight(x, y);
-
+ float gridHeight = gmap->getHeight(x, y);
// look from a bit higher pos to find the floor, ignore under surface case
- if (z + 2.0f > _mapheight)
- mapHeight = _mapheight;
- else
- mapHeight = VMAP_INVALID_HEIGHT_VALUE;
+ if (z + 2.0f > gridHeight)
+ mapHeight = gridHeight;
}
- else
- mapHeight = VMAP_INVALID_HEIGHT_VALUE;
- float vmapHeight;
- if (pUseVmaps)
+ float vmapHeight = VMAP_INVALID_HEIGHT_VALUE;
+ if (checkVMap)
{
VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager();
if (vmgr->isHeightCalcEnabled())
- {
- // look from a bit higher pos to find the floor
- vmapHeight = vmgr->getHeight(GetId(), x, y, z + 2.0f, maxSearchDist);
- }
- else
- vmapHeight = VMAP_INVALID_HEIGHT_VALUE;
+ vmapHeight = vmgr->getHeight(GetId(), x, y, z + 2.0f, maxSearchDist); // look from a bit higher pos to find the floor
}
- else
- vmapHeight = VMAP_INVALID_HEIGHT_VALUE;
// mapHeight set for any above raw ground Z or <= INVALID_HEIGHT
// vmapheight set for any under Z value or <= INVALID_HEIGHT
-
if (vmapHeight > INVALID_HEIGHT)
{
if (mapHeight > INVALID_HEIGHT)
@@ -1581,15 +1577,8 @@ float Map::GetHeight(float x, float y, float z, bool pUseVmaps, float maxSearchD
else
return vmapHeight; // we have only vmapHeight (if have)
}
- else
- {
- if (!pUseVmaps)
- return mapHeight; // explicitly use map data (if have)
- else if (mapHeight > INVALID_HEIGHT && (z < mapHeight + 2 || z == MAX_HEIGHT))
- return mapHeight; // explicitly use map data if original z < mapHeight but map found (z+2 > mapHeight)
- else
- return VMAP_INVALID_HEIGHT_VALUE; // we not have any height
- }
+
+ return mapHeight; // explicitly use map data
}
inline bool IsOutdoorWMO(uint32 mogpFlags, int32 /*adtId*/, int32 /*rootId*/, int32 /*groupId*/, WMOAreaTableEntry const* wmoEntry, AreaTableEntry const* atEntry)
@@ -1826,7 +1815,7 @@ bool Map::CheckGridIntegrity(Creature* c, bool moved) const
return true;
}
-const char* Map::GetMapName() const
+char const* Map::GetMapName() const
{
return i_mapEntry ? i_mapEntry->name[sWorld->GetDefaultDbcLocale()] : "UNNAMEDMAP\x0";
}
@@ -1996,15 +1985,8 @@ void Map::RemoveAllObjectsInRemoveList()
bool on = itr->second;
i_objectsToSwitch.erase(itr);
- switch (obj->GetTypeId())
- {
- case TYPEID_UNIT:
- if (!obj->ToCreature()->isPet())
- SwitchGridContainers(obj->ToCreature(), on);
- break;
- default:
- break;
- }
+ if (obj->GetTypeId() == TYPEID_UNIT && !obj->IsPermanentWorldObject())
+ SwitchGridContainers(obj->ToCreature(), on);
}
//sLog->outDebug(LOG_FILTER_MAPS, "Object remover 1 check.");
@@ -2340,6 +2322,13 @@ bool InstanceMap::AddPlayerToMap(Player* player)
ASSERT(playerBind->save == mapSave);
}
}
+
+ if (group && group->isLFGGroup())
+ if (uint32 dungeonId = sLFGMgr->GetDungeon(group->GetGUID(), true))
+ if (LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(dungeonId))
+ if (LFGDungeonEntry const* randomDungeon = sLFGDungeonStore.LookupEntry(*(sLFGMgr->GetSelectedDungeons(player->GetGUID()).begin())))
+ if (dungeon->map == GetId() && dungeon->difficulty == GetDifficulty() && randomDungeon->type == LFG_TYPE_RANDOM)
+ player->CastSpell(player, LFG_SPELL_LUCK_OF_THE_DRAW, true);
}
// for normal instances cancel the reset schedule when the
@@ -2623,20 +2612,17 @@ void BattlegroundMap::RemoveAllPlayers()
player->TeleportTo(player->GetBattlegroundEntryPoint());
}
-Creature*
-Map::GetCreature(uint64 guid)
+Creature* Map::GetCreature(uint64 guid)
{
return ObjectAccessor::GetObjectInMap(guid, this, (Creature*)NULL);
}
-GameObject*
-Map::GetGameObject(uint64 guid)
+GameObject* Map::GetGameObject(uint64 guid)
{
return ObjectAccessor::GetObjectInMap(guid, this, (GameObject*)NULL);
}
-DynamicObject*
-Map::GetDynamicObject(uint64 guid)
+DynamicObject* Map::GetDynamicObject(uint64 guid)
{
return ObjectAccessor::GetObjectInMap(guid, this, (DynamicObject*)NULL);
}
diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h
index 5b652a2524a..542d9119830 100755
--- a/src/server/game/Maps/Map.h
+++ b/src/server/game/Maps/Map.h
@@ -296,7 +296,7 @@ class Map : public GridRefManager<NGridType>
// some calls like isInWater should not use vmaps due to processor power
// can return INVALID_HEIGHT if under z+2 z coord not found height
- float GetHeight(float x, float y, float z, bool pCheckVMap=true, float maxSearchDist=DEFAULT_HEIGHT_SEARCH) const;
+ float GetHeight(float x, float y, float z, bool checkVMap = true, float maxSearchDist = DEFAULT_HEIGHT_SEARCH) const;
ZLiquidStatus getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData* data = 0) const;
@@ -405,7 +405,7 @@ class Map : public GridRefManager<NGridType>
void RemoveFromActive(Creature* obj);
- template<class T> void SwitchGridContainers(T* obj, bool active);
+ void SwitchGridContainers(Creature* creature, bool toWorldContainer);
template<class NOTIFIER> void VisitAll(const float &x, const float &y, float radius, NOTIFIER &notifier);
template<class NOTIFIER> void VisitFirstFound(const float &x, const float &y, float radius, NOTIFIER &notifier);
template<class NOTIFIER> void VisitWorld(const float &x, const float &y, float radius, NOTIFIER &notifier);
diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h
index ffdf0131143..a5935e1de9f 100755
--- a/src/server/game/Miscellaneous/Language.h
+++ b/src/server/game/Miscellaneous/Language.h
@@ -42,8 +42,8 @@ enum TrinityStrings
LANG_GMS_ON_SRV = 16,
LANG_GMS_NOT_LOGGED = 17,
LANG_YOU_IN_FLIGHT = 18,
- //LANG_YOU_IN_BATTLEGROUND = 19, not used
- //LANG_TARGET_IN_FLIGHT = 20, not used
+ LANG_UPDATE_DIFF = 19,
+ LANG_SHUTDOWN_TIMELEFT = 20,
LANG_CHAR_IN_FLIGHT = 21,
LANG_CHAR_NON_MOUNTED = 22,
LANG_YOU_IN_COMBAT = 23,
@@ -946,8 +946,9 @@ enum TrinityStrings
LANG_GOINFO_NAME = 5027,
LANG_GOINFO_LOOTID = 5028,
LANG_COMMAND_LOOKUP_MAX_RESULTS = 5029,
- // Room for more Trinity strings 5030-9999
LANG_FLEE = 5030,
+ LANG_NPCINFO_AIINFO = 5031,
+ // Room for more Trinity strings 5032-9999
// Level requirement notifications
LANG_SAY_REQ = 6604,
diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h
index a99d0f37c02..952df731c19 100755
--- a/src/server/game/Miscellaneous/SharedDefines.h
+++ b/src/server/game/Miscellaneous/SharedDefines.h
@@ -312,13 +312,13 @@ enum SpellAttr1
SPELL_ATTR1_MELEE_COMBAT_START = 0x00000200, // 9 player starts melee combat after this spell is cast
SPELL_ATTR1_NO_THREAT = 0x00000400, // 10 no generates threat on cast 100% (old NO_INITIAL_AGGRO)
SPELL_ATTR1_UNK11 = 0x00000800, // 11 aura
- SPELL_ATTR1_UNK12 = 0x00001000, // 12
+ SPELL_ATTR1_UNK12 = 0x00001000, // 12 pickpoket
SPELL_ATTR1_FARSIGHT = 0x00002000, // 13 Client removes farsight on aura loss
SPELL_ATTR1_CHANNEL_TRACK_TARGET = 0x00004000, // 14 Client automatically forces player to face target when channeling
SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY = 0x00008000, // 15 remove auras on immunity
SPELL_ATTR1_UNAFFECTED_BY_SCHOOL_IMMUNE = 0x00010000, // 16 on immuniy
SPELL_ATTR1_UNAUTOCASTABLE_BY_PET = 0x00020000, // 17
- SPELL_ATTR1_UNK18 = 0x00040000, // 18
+ SPELL_ATTR1_UNK18 = 0x00040000, // 18 stun, polymorph, daze, hex
SPELL_ATTR1_CANT_TARGET_SELF = 0x00080000, // 19
SPELL_ATTR1_REQ_COMBO_POINTS1 = 0x00100000, // 20 Req combo points on target
SPELL_ATTR1_UNK21 = 0x00200000, // 21
@@ -327,17 +327,17 @@ enum SpellAttr1
SPELL_ATTR1_UNK24 = 0x01000000, // 24 only fishing spells
SPELL_ATTR1_UNK25 = 0x02000000, // 25
SPELL_ATTR1_UNK26 = 0x04000000, // 26 works correctly with [target=focus] and [target=mouseover] macros?
- SPELL_ATTR1_UNK27 = 0x08000000, // 27
+ SPELL_ATTR1_UNK27 = 0x08000000, // 27 melee spell?
SPELL_ATTR1_DONT_DISPLAY_IN_AURA_BAR = 0x10000000, // 28 client doesn't display these spells in aura bar
SPELL_ATTR1_CHANNEL_DISPLAY_SPELL_NAME = 0x20000000, // 29 spell name is displayed in cast bar instead of 'channeling' text
- SPELL_ATTR1_ENABLE_AT_DODGE = 0x40000000, // 30 Overpower, Wolverine Bite
+ SPELL_ATTR1_ENABLE_AT_DODGE = 0x40000000, // 30 Overpower
SPELL_ATTR1_UNK31 = 0x80000000 // 31
};
enum SpellAttr2
{
SPELL_ATTR2_CAN_TARGET_DEAD = 0x00000001, // 0 can target dead unit or corpse
- SPELL_ATTR2_UNK1 = 0x00000002, // 1 ? many triggered spells have this flag
+ SPELL_ATTR2_UNK1 = 0x00000002, // 1 vanish, shadowform, Ghost Wolf and other
SPELL_ATTR2_CAN_TARGET_NOT_IN_LOS = 0x00000004, // 2 26368 4.0.1 dbc change
SPELL_ATTR2_UNK3 = 0x00000008, // 3
SPELL_ATTR2_DISPLAY_IN_STANCE_BAR = 0x00000010, // 4 client displays icon in stance bar when learned, even if not shapeshift
@@ -346,9 +346,9 @@ enum SpellAttr2
SPELL_ATTR2_UNK7 = 0x00000080, // 7
SPELL_ATTR2_UNK8 = 0x00000100, // 8 not set in 3.0.3
SPELL_ATTR2_UNK9 = 0x00000200, // 9
- SPELL_ATTR2_UNK10 = 0x00000400, // 10
+ SPELL_ATTR2_UNK10 = 0x00000400, // 10 related to tame
SPELL_ATTR2_HEALTH_FUNNEL = 0x00000800, // 11
- SPELL_ATTR2_UNK12 = 0x00001000, // 12
+ SPELL_ATTR2_UNK12 = 0x00001000, // 12 Cleave, Heart Strike, Maul, Sunder Armor, Swipe
SPELL_ATTR2_UNK13 = 0x00002000, // 13 Items enchanted by spells with this flag preserve the enchant to arenas
SPELL_ATTR2_UNK14 = 0x00004000, // 14
SPELL_ATTR2_UNK15 = 0x00008000, // 15 not set in 3.0.3
@@ -358,13 +358,13 @@ enum SpellAttr2
SPELL_ATTR2_NOT_NEED_SHAPESHIFT = 0x00080000, // 19 does not necessarly need shapeshift
SPELL_ATTR2_UNK20 = 0x00100000, // 20
SPELL_ATTR2_DAMAGE_REDUCED_SHIELD = 0x00200000, // 21 for ice blocks, pala immunity buffs, priest absorb shields, but used also for other spells -> not sure!
- SPELL_ATTR2_UNK22 = 0x00400000, // 22
+ SPELL_ATTR2_UNK22 = 0x00400000, // 22 Ambush, Backstab, Cheap Shot, Death Grip, Garrote, Judgements, Mutilate, Pounce, Ravage, Shiv, Shred
SPELL_ATTR2_UNK23 = 0x00800000, // 23 Only mage Arcane Concentration have this flag
SPELL_ATTR2_UNK24 = 0x01000000, // 24
SPELL_ATTR2_UNK25 = 0x02000000, // 25
SPELL_ATTR2_UNK26 = 0x04000000, // 26 unaffected by school immunity
SPELL_ATTR2_UNK27 = 0x08000000, // 27
- SPELL_ATTR2_UNK28 = 0x10000000, // 28 no breaks stealth if it fails??
+ SPELL_ATTR2_UNK28 = 0x10000000, // 28
SPELL_ATTR2_CANT_CRIT = 0x20000000, // 29 Spell can't crit
SPELL_ATTR2_TRIGGERED_CAN_TRIGGER_PROC = 0x40000000, // 30 spell can trigger even if triggered
SPELL_ATTR2_FOOD_BUFF = 0x80000000 // 31 Food or Drink Buff (like Well Fed)
@@ -393,7 +393,7 @@ enum SpellAttr3
SPELL_ATTR3_IGNORE_HIT_RESULT = 0x00040000, // 18 Spell should always hit its target
SPELL_ATTR3_DISABLE_PROC = 0x00080000, // 19 during aura proc no spells can trigger (20178, 20375)
SPELL_ATTR3_DEATH_PERSISTENT = 0x00100000, // 20 Death persistent spells
- SPELL_ATTR3_UNK21 = 0x00200000, // 21
+ SPELL_ATTR3_UNK21 = 0x00200000, // 21 unused
SPELL_ATTR3_REQ_WAND = 0x00400000, // 22 Req wand
SPELL_ATTR3_UNK23 = 0x00800000, // 23
SPELL_ATTR3_REQ_OFFHAND = 0x01000000, // 24 Req offhand weapon
@@ -417,7 +417,7 @@ enum SpellAttr4
SPELL_ATTR4_NOT_STEALABLE = 0x00000040, // 6 although such auras might be dispellable, they cannot be stolen
SPELL_ATTR4_TRIGGERED = 0x00000080, // 7 spells forced to be triggered
SPELL_ATTR4_UNK8 = 0x00000100, // 8 ignores taken percent damage mods?
- SPELL_ATTR4_UNK9 = 0x00000200, // 9
+ SPELL_ATTR4_TRIGGER_ACTIVATE = 0x00000200, // 9 initially disabled / trigger activate from event (Execute, Riposte, Deep Freeze end other)
SPELL_ATTR4_SPELL_VS_EXTEND_COST = 0x00000400, // 10 Rogue Shiv have this flag
SPELL_ATTR4_UNK11 = 0x00000800, // 11
SPELL_ATTR4_UNK12 = 0x00001000, // 12
@@ -427,16 +427,16 @@ enum SpellAttr4
SPELL_ATTR4_NOT_USABLE_IN_ARENA = 0x00010000, // 16
SPELL_ATTR4_USABLE_IN_ARENA = 0x00020000, // 17
SPELL_ATTR4_AREA_TARGET_CHAIN = 0x00040000, // 18 (NYI)hits area targets one after another instead of all at once
- SPELL_ATTR4_UNK19 = 0x00080000, // 19
+ SPELL_ATTR4_UNK19 = 0x00080000, // 19 proc dalayed, after damage or don't proc on absorb?
SPELL_ATTR4_NOT_CHECK_SELFCAST_POWER = 0x00100000, // 20 supersedes message "More powerful spell applied" for self casts.
- SPELL_ATTR4_UNK21 = 0x00200000, // 21
+ SPELL_ATTR4_UNK21 = 0x00200000, // 21 Pally aura, dk presence, dudu form, warrior stance, shadowform, hunter track
SPELL_ATTR4_UNK22 = 0x00400000, // 22
SPELL_ATTR4_UNK23 = 0x00800000, // 23
- SPELL_ATTR4_UNK24 = 0x01000000, // 24
+ SPELL_ATTR4_UNK24 = 0x01000000, // 24 some shoot spell
SPELL_ATTR4_UNK25 = 0x02000000, // 25 pet scaling auras
SPELL_ATTR4_CAST_ONLY_IN_OUTLAND = 0x04000000, // 26 Can only be used in Outland.
SPELL_ATTR4_UNK27 = 0x08000000, // 27
- SPELL_ATTR4_UNK28 = 0x10000000, // 28
+ SPELL_ATTR4_UNK28 = 0x10000000, // 28 Aimed Shot
SPELL_ATTR4_UNK29 = 0x20000000, // 29
SPELL_ATTR4_UNK30 = 0x40000000, // 30
SPELL_ATTR4_UNK31 = 0x80000000 // 31
@@ -456,7 +456,7 @@ enum SpellAttr5
SPELL_ATTR5_START_PERIODIC_AT_APPLY = 0x00000200, // 9 begin periodic tick at aura apply
SPELL_ATTR5_HIDE_DURATION = 0x00000400, // 10 do not send duration to client
SPELL_ATTR5_ALLOW_TARGET_OF_TARGET_AS_TARGET = 0x00000800, // 11 (NYI) uses target's target as target if original target not valid (intervene for example)
- SPELL_ATTR5_UNK12 = 0x00001000, // 12
+ SPELL_ATTR5_UNK12 = 0x00001000, // 12 Cleave related?
SPELL_ATTR5_HASTE_AFFECT_DURATION = 0x00002000, // 13 haste effects decrease duration of this
SPELL_ATTR5_UNK14 = 0x00004000, // 14
SPELL_ATTR5_UNK15 = 0x00008000, // 15
@@ -470,7 +470,7 @@ enum SpellAttr5
SPELL_ATTR5_UNK23 = 0x00800000, // 23
SPELL_ATTR5_UNK24 = 0x01000000, // 24
SPELL_ATTR5_UNK25 = 0x02000000, // 25
- SPELL_ATTR5_UNK26 = 0x04000000, // 26
+ SPELL_ATTR5_UNK26 = 0x04000000, // 26 aoe related - Boulder, Cannon, Corpse Explosion, Fire Nova, Flames, Frost Bomb, Living Bomb, Seed of Corruption, Starfall, Thunder Clap, Volley
SPELL_ATTR5_UNK27 = 0x08000000, // 27
SPELL_ATTR5_UNK28 = 0x10000000, // 28
SPELL_ATTR5_UNK29 = 0x20000000, // 29
@@ -495,23 +495,23 @@ enum SpellAttr6
SPELL_ATTR6_CASTABLE_WHILE_ON_VEHICLE = 0x00001000, // 12 castable while caster is on vehicle
SPELL_ATTR6_CAN_TARGET_INVISIBLE = 0x00002000, // 13 ignore visibility requirement for spell target (phases, invisibility, etc.)
SPELL_ATTR6_UNK14 = 0x00004000, // 14
- SPELL_ATTR6_UNK15 = 0x00008000, // 15 not set in 3.0.3
+ SPELL_ATTR6_UNK15 = 0x00008000, // 15 only 54368, 67892
SPELL_ATTR6_UNK16 = 0x00010000, // 16
- SPELL_ATTR6_UNK17 = 0x00020000, // 17
+ SPELL_ATTR6_UNK17 = 0x00020000, // 17 Mount spell
SPELL_ATTR6_CAST_BY_CHARMER = 0x00040000, // 18 client won't allow to cast these spells when unit is not possessed && charmer of caster will be original caster
- SPELL_ATTR6_UNK19 = 0x00080000, // 19
- SPELL_ATTR6_UNK20 = 0x00100000, // 20
+ SPELL_ATTR6_UNK19 = 0x00080000, // 19 only 47488, 50782
+ SPELL_ATTR6_UNK20 = 0x00100000, // 20 only 58371, 62218
SPELL_ATTR6_CLIENT_UI_TARGET_EFFECTS = 0x00200000, // 21 it's only client-side attribute
- SPELL_ATTR6_UNK22 = 0x00400000, // 22
+ SPELL_ATTR6_UNK22 = 0x00400000, // 22 only 72054
SPELL_ATTR6_UNK23 = 0x00800000, // 23
SPELL_ATTR6_CAN_TARGET_UNTARGETABLE = 0x01000000, // 24
- SPELL_ATTR6_UNK25 = 0x02000000, // 25
- SPELL_ATTR6_UNK26 = 0x04000000, // 26
+ SPELL_ATTR6_UNK25 = 0x02000000, // 25 Exorcism, Flash of Light
+ SPELL_ATTR6_UNK26 = 0x04000000, // 26 related to player castable positive buff
SPELL_ATTR6_UNK27 = 0x08000000, // 27
- SPELL_ATTR6_UNK28 = 0x10000000, // 28
+ SPELL_ATTR6_UNK28 = 0x10000000, // 28 Death Grip
SPELL_ATTR6_NO_DONE_PCT_DAMAGE_MODS = 0x20000000, // 29 ignores done percent damage mods?
SPELL_ATTR6_UNK30 = 0x40000000, // 30
- SPELL_ATTR6_UNK31 = 0x80000000 // 31 some special cooldown calc?
+ SPELL_ATTR6_UNK31 = 0x80000000 // 31 some special cooldown calc? only 2894
};
enum SpellAttr7
@@ -520,7 +520,7 @@ enum SpellAttr7
SPELL_ATTR7_UNK1 = 0x00000002, // 1 Not set in 3.2.2a.
SPELL_ATTR7_REACTIVATE_AT_RESURRECT = 0x00000004, // 2 Paladin's auras and 65607 only.
SPELL_ATTR7_IS_CHEAT_SPELL = 0x00000008, // 3 Cannot cast if caster doesn't have UnitFlag2 & UNIT_FLAG2_ALLOW_CHEAT_SPELLS
- SPELL_ATTR7_UNK4 = 0x00000010, // 4 Only 66109 test spell.
+ SPELL_ATTR7_UNK4 = 0x00000010, // 4 Only 47883 (Soulstone Resurrection) and test spell.
SPELL_ATTR7_SUMMON_PLAYER_TOTEM = 0x00000020, // 5 Only Shaman player totems.
SPELL_ATTR7_UNK6 = 0x00000040, // 6 Dark Surge, Surge of Light, Burning Breath triggers (boss spells).
SPELL_ATTR7_UNK7 = 0x00000080, // 7 66218 (Launch) spell.
@@ -536,18 +536,18 @@ enum SpellAttr7
SPELL_ATTR7_UNK17 = 0x00020000, // 17 Only 27965 (Suicide) spell.
SPELL_ATTR7_HAS_CHARGE_EFFECT = 0x00040000, // 18 Only spells that have Charge among effects.
SPELL_ATTR7_ZONE_TELEPORT = 0x00080000, // 19 Teleports to specific zones.
- SPELL_ATTR7_UNK20 = 0x00100000, // 20
- SPELL_ATTR7_UNK21 = 0x00200000, // 21
+ SPELL_ATTR7_UNK20 = 0x00100000, // 20 Blink, Divine Shield, Ice Block
+ SPELL_ATTR7_UNK21 = 0x00200000, // 21 Not set
SPELL_ATTR7_UNK22 = 0x00400000, // 22
- SPELL_ATTR7_UNK23 = 0x00800000, // 23
- SPELL_ATTR7_UNK24 = 0x01000000, // 24
+ SPELL_ATTR7_UNK23 = 0x00800000, // 23 Motivate, Mutilate, Shattering Throw
+ SPELL_ATTR7_UNK24 = 0x01000000, // 24 Motivate, Mutilate, Perform Speech, Shattering Throw
SPELL_ATTR7_UNK25 = 0x02000000, // 25
SPELL_ATTR7_UNK26 = 0x04000000, // 26
- SPELL_ATTR7_UNK27 = 0x08000000, // 27
- SPELL_ATTR7_UNK28 = 0x10000000, // 28
- SPELL_ATTR7_UNK29 = 0x20000000, // 29
- SPELL_ATTR7_UNK30 = 0x40000000, // 30
- SPELL_ATTR7_UNK31 = 0x80000000 // 31
+ SPELL_ATTR7_UNK27 = 0x08000000, // 27 Not set
+ SPELL_ATTR7_UNK28 = 0x10000000, // 28 related to player positive buff
+ SPELL_ATTR7_UNK29 = 0x20000000, // 29 only 69028, 71237
+ SPELL_ATTR7_UNK30 = 0x40000000, // 30 Burning Determination, Divine Sacrifice, Earth Shield, Prayer of Mending
+ SPELL_ATTR7_UNK31 = 0x80000000 // 31 only 70769
};
#define MIN_TALENT_SPEC 0
diff --git a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp
index 5bd0a23207e..09af2303397 100755
--- a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp
@@ -47,11 +47,10 @@ template<>
void
RandomMovementGenerator<Creature>::_setRandomLocation(Creature &creature)
{
- float X, Y, Z, z, nx, ny, nz, ori, dist;
+ float X, Y, Z, nx, ny, nz, ori, dist;
creature.GetHomePosition(X, Y, Z, ori);
- z = creature.GetPositionZ();
Map const* map = creature.GetBaseMap();
// For 2D/3D system selection
diff --git a/src/server/game/Server/Protocol/Handlers/AuctionHouseHandler.cpp b/src/server/game/Server/Protocol/Handlers/AuctionHouseHandler.cpp
index 2f8a27740be..1710a387307 100755
--- a/src/server/game/Server/Protocol/Handlers/AuctionHouseHandler.cpp
+++ b/src/server/game/Server/Protocol/Handlers/AuctionHouseHandler.cpp
@@ -115,6 +115,8 @@ void WorldSession::SendAuctionOwnerNotification(AuctionEntry* auction)
//this void creates new auction and adds auction to some auctionhouse
void WorldSession::HandleAuctionSellItem(WorldPacket & recv_data)
{
+ sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_AUCTION_SELL_ITEM");
+
uint64 auctioneer, item;
uint32 etime, bid, buyout, count;
recv_data >> auctioneer;
@@ -253,6 +255,8 @@ void WorldSession::HandleAuctionSellItem(WorldPacket & recv_data)
//this function is called when client bids or buys out auction
void WorldSession::HandleAuctionPlaceBid(WorldPacket & recv_data)
{
+ sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_AUCTION_PLACE_BID");
+
uint64 auctioneer;
uint32 auctionId;
uint32 price;
@@ -374,6 +378,8 @@ void WorldSession::HandleAuctionPlaceBid(WorldPacket & recv_data)
//this void is called when auction_owner cancels his auction
void WorldSession::HandleAuctionRemoveItem(WorldPacket & recv_data)
{
+ sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_AUCTION_REMOVE_ITEM");
+
uint64 auctioneer;
uint32 auctionId;
recv_data >> auctioneer;
@@ -452,6 +458,8 @@ void WorldSession::HandleAuctionRemoveItem(WorldPacket & recv_data)
//called when player lists his bids
void WorldSession::HandleAuctionListBidderItems(WorldPacket & recv_data)
{
+ sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_AUCTION_LIST_BIDDER_ITEMS");
+
uint64 guid; //NPC guid
uint32 listfrom; //page of auctions
uint32 outbiddedCount; //count of outbidded auctions
@@ -469,6 +477,7 @@ void WorldSession::HandleAuctionListBidderItems(WorldPacket & recv_data)
if (!creature)
{
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleAuctionListBidderItems - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)));
+ recv_data.rfinish();
return;
}
@@ -506,6 +515,8 @@ void WorldSession::HandleAuctionListBidderItems(WorldPacket & recv_data)
//this void sends player info about his auctions
void WorldSession::HandleAuctionListOwnerItems(WorldPacket & recv_data)
{
+ sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_AUCTION_LIST_OWNER_ITEMS");
+
uint32 listfrom;
uint64 guid;
@@ -541,6 +552,8 @@ void WorldSession::HandleAuctionListOwnerItems(WorldPacket & recv_data)
//this void is called when player clicks on search button
void WorldSession::HandleAuctionListItems(WorldPacket & recv_data)
{
+ sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_AUCTION_LIST_ITEMS");
+
std::string searchedname;
uint8 levelmin, levelmax, usable;
uint32 listfrom, auctionSlotID, auctionMainCategory, auctionSubCategory, quality;
@@ -606,7 +619,7 @@ void WorldSession::HandleAuctionListItems(WorldPacket & recv_data)
void WorldSession::HandleAuctionListPendingSales(WorldPacket & recv_data)
{
- sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_AUCTION_LIST_PENDING_SALES");
+ sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_AUCTION_LIST_PENDING_SALES");
recv_data.read_skip<uint64>();
diff --git a/src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp b/src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp
index 83b9ab048ad..2a4e1c50ac5 100755
--- a/src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp
+++ b/src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp
@@ -196,7 +196,7 @@ bool LoginQueryHolder::Initialize()
return res;
}
-void WorldSession::HandleCharEnum(QueryResult result)
+void WorldSession::HandleCharEnum(PreparedQueryResult result)
{
WorldPacket data(SMSG_CHAR_ENUM, 100); // we guess size
@@ -232,35 +232,16 @@ void WorldSession::HandleCharEnumOpcode(WorldPacket & /*recv_data*/)
CharacterDatabase.Execute(stmt);
/// get all the data necessary for loading all characters (along with their pets) on the account
- _charEnumCallback =
- CharacterDatabase.AsyncPQuery(
- !sWorld->getBoolConfig(CONFIG_DECLINED_NAMES_USED) ?
- // ------- Query Without Declined Names --------
- // 0 1 2 3 4 5 6 7
- "SELECT characters.guid, characters.name, characters.race, characters.class, characters.gender, characters.playerBytes, characters.playerBytes2, characters.level, "
- // 8 9 10 11 12 13 14
- "characters.zone, characters.map, characters.position_x, characters.position_y, characters.position_z, guild_member.guildid, characters.playerFlags, "
- // 15 16 17 18 19 20
- "characters.at_login, character_pet.entry, character_pet.modelid, character_pet.level, characters.equipmentCache, character_banned.guid "
- "FROM characters LEFT JOIN character_pet ON characters.guid=character_pet.owner AND character_pet.slot='%u' "
- "LEFT JOIN guild_member ON characters.guid = guild_member.guid "
- "LEFT JOIN character_banned ON characters.guid = character_banned.guid AND character_banned.active = 1 "
- "WHERE characters.account = '%u' ORDER BY characters.guid"
- :
- // --------- Query With Declined Names ---------
- // 0 1 2 3 4 5 6 7
- "SELECT characters.guid, characters.name, characters.race, characters.class, characters.gender, characters.playerBytes, characters.playerBytes2, characters.level, "
- // 8 9 10 11 12 13 14
- "characters.zone, characters.map, characters.position_x, characters.position_y, characters.position_z, guild_member.guildid, characters.playerFlags, "
- // 15 16 17 18 19 20 21
- "characters.at_login, character_pet.entry, character_pet.modelid, character_pet.level, characters.equipmentCache, character_banned.guid, 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 "
- "LEFT JOIN character_banned ON characters.guid = character_banned.guid AND character_banned.active = 1 "
- "WHERE characters.account = '%u' ORDER BY characters.guid",
- PET_SAVE_AS_CURRENT, GetAccountId()
- );
+
+ if (sWorld->getBoolConfig(CONFIG_DECLINED_NAMES_USED))
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_GET_ENUM_DECLINED_NAME);
+ else
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_GET_ENUM);
+
+ stmt->setUInt8(0, PET_SAVE_AS_CURRENT);
+ stmt->setUInt32(1, GetAccountId());
+
+ _charEnumCallback = CharacterDatabase.AsyncQuery(stmt);
}
void WorldSession::HandleCharCreateOpcode(WorldPacket & recv_data)
@@ -413,7 +394,7 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, Characte
This is much more efficient than synchronous requests on packet handler, and much less DoS prone.
It also prevents data syncrhonisation errors.
*/
- switch (createInfo->Stage)
+ switch (_charCreateCallback.GetStage())
{
case 0:
{
@@ -423,8 +404,7 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, Characte
data << uint8(CHAR_CREATE_NAME_IN_USE);
SendPacket(&data);
delete createInfo;
- _charCreateCallback.SetParam(NULL);
- _charCreateCallback.FreeResult();
+ _charCreateCallback.Reset();
return;
}
@@ -435,8 +415,7 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, Characte
_charCreateCallback.FreeResult();
_charCreateCallback.SetFutureResult(LoginDatabase.AsyncQuery(stmt));
-
- createInfo->Stage++;
+ _charCreateCallback.NextStage();
}
break;
case 1:
@@ -457,8 +436,7 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, Characte
data << uint8(CHAR_CREATE_ACCOUNT_LIMIT);
SendPacket(&data);
delete createInfo;
- _charCreateCallback.SetParam(NULL);
- _charCreateCallback.FreeResult();
+ _charCreateCallback.Reset();
return;
}
@@ -470,8 +448,7 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, Characte
_charCreateCallback.FreeResult();
_charCreateCallback.SetFutureResult(CharacterDatabase.AsyncQuery(stmt));
-
- createInfo->Stage++;
+ _charCreateCallback.NextStage();
}
break;
case 2:
@@ -487,8 +464,7 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, Characte
data << uint8(CHAR_CREATE_SERVER_LIMIT);
SendPacket(&data);
delete createInfo;
- _charCreateCallback.SetParam(NULL);
- _charCreateCallback.FreeResult();
+ _charCreateCallback.Reset();
return;
}
}
@@ -504,11 +480,11 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, Characte
stmt->setUInt32(0, GetAccountId());
stmt->setUInt32(1, (skipCinematics == 1 || createInfo->Class == CLASS_DEATH_KNIGHT) ? 10 : 1);
_charCreateCallback.SetFutureResult(CharacterDatabase.AsyncQuery(stmt));
- createInfo->Stage++;
+ _charCreateCallback.NextStage();
return;
}
- createInfo->Stage++;
+ _charCreateCallback.NextStage();
HandleCharCreateCallback(PreparedQueryResult(NULL), createInfo); // Will jump to case 3
}
break;
@@ -542,8 +518,7 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, Characte
data << uint8(CHAR_CREATE_UNIQUE_CLASS_LIMIT);
SendPacket(&data);
delete createInfo;
- _charCreateCallback.SetParam(NULL);
- _charCreateCallback.FreeResult();
+ _charCreateCallback.Reset();
return;
}
}
@@ -570,8 +545,7 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, Characte
data << uint8(CHAR_CREATE_PVP_TEAMS_VIOLATION);
SendPacket(&data);
delete createInfo;
- _charCreateCallback.SetParam(NULL);
- _charCreateCallback.FreeResult();
+ _charCreateCallback.Reset();
return;
}
}
@@ -603,8 +577,7 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, Characte
data << uint8(CHAR_CREATE_UNIQUE_CLASS_LIMIT);
SendPacket(&data);
delete createInfo;
- _charCreateCallback.SetParam(NULL);
- _charCreateCallback.FreeResult();
+ _charCreateCallback.Reset();
return;
}
}
@@ -625,8 +598,7 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, Characte
data << uint8(CHAR_CREATE_LEVEL_REQUIREMENT);
SendPacket(&data);
delete createInfo;
- _charCreateCallback.SetParam(NULL);
- _charCreateCallback.FreeResult();
+ _charCreateCallback.Reset();
return;
}
@@ -647,8 +619,7 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, Characte
data << uint8(CHAR_CREATE_ERROR);
SendPacket(&data);
delete createInfo;
- _charCreateCallback.SetParam(NULL);
- _charCreateCallback.FreeResult();
+ _charCreateCallback.Reset();
return;
}
@@ -689,8 +660,7 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, Characte
sWorld->AddCharacterNameData(newChar.GetGUIDLow(), std::string(newChar.GetName()), newChar.getGender(), newChar.getRace(), newChar.getClass());
delete createInfo;
- _charCreateCallback.SetParam(NULL);
- _charCreateCallback.FreeResult();
+ _charCreateCallback.Reset();
}
break;
}
@@ -791,7 +761,7 @@ void WorldSession::HandlePlayerLoginOpcode(WorldPacket & recv_data)
_charLoginCallback = CharacterDatabase.DelayQueryHolder((SQLQueryHolder*)holder);
}
-void WorldSession::HandlePlayerLogin(LoginQueryHolder * holder)
+void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder)
{
uint64 playerGuid = holder->GetGuid();
@@ -997,7 +967,7 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder * holder)
pCurrChar->RemoveAtLoginFlag(AT_LOGIN_FIRST);
// show time before shutdown if shutdown planned.
- if (sWorld->IsShutdowning())
+ if (sWorld->IsShuttingDown())
sWorld->ShutdownMsg(true, pCurrChar);
if (sWorld->getBoolConfig(CONFIG_ALL_TAXI_PATHS))
@@ -1085,28 +1055,30 @@ void WorldSession::HandleSetFactionInactiveOpcode(WorldPacket & recv_data)
_player->GetReputationMgr().SetInactive(replistid, inactive);
}
-void WorldSession::HandleShowingHelmOpcode(WorldPacket & /*recv_data*/)
+void WorldSession::HandleShowingHelmOpcode(WorldPacket& recv_data)
{
sLog->outStaticDebug("CMSG_SHOWING_HELM for %s", _player->GetName());
+ recv_data.read_skip<uint8>(); // unknown, bool?
_player->ToggleFlag(PLAYER_FLAGS, PLAYER_FLAGS_HIDE_HELM);
}
-void WorldSession::HandleShowingCloakOpcode(WorldPacket & /*recv_data*/)
+void WorldSession::HandleShowingCloakOpcode(WorldPacket& recv_data)
{
sLog->outStaticDebug("CMSG_SHOWING_CLOAK for %s", _player->GetName());
+ recv_data.read_skip<uint8>(); // unknown, bool?
_player->ToggleFlag(PLAYER_FLAGS, PLAYER_FLAGS_HIDE_CLOAK);
}
void WorldSession::HandleCharRenameOpcode(WorldPacket& recv_data)
{
uint64 guid;
- std::string newname;
+ std::string newName;
recv_data >> guid;
- recv_data >> newname;
+ recv_data >> newName;
// prevent character rename to invalid name
- if (!normalizePlayerName(newname))
+ if (!normalizePlayerName(newName))
{
WorldPacket data(SMSG_CHAR_RENAME, 1);
data << uint8(CHAR_NAME_NO_NAME);
@@ -1114,7 +1086,7 @@ void WorldSession::HandleCharRenameOpcode(WorldPacket& recv_data)
return;
}
- uint8 res = ObjectMgr::CheckPlayerName(newname, true);
+ uint8 res = ObjectMgr::CheckPlayerName(newName, true);
if (res != CHAR_NAME_SUCCESS)
{
WorldPacket data(SMSG_CHAR_RENAME, 1);
@@ -1124,7 +1096,7 @@ void WorldSession::HandleCharRenameOpcode(WorldPacket& recv_data)
}
// check name limitations
- if (AccountMgr::IsPlayerAccount(GetSecurity()) && sObjectMgr->IsReservedName(newname))
+ if (AccountMgr::IsPlayerAccount(GetSecurity()) && sObjectMgr->IsReservedName(newName))
{
WorldPacket data(SMSG_CHAR_RENAME, 1);
data << uint8(CHAR_NAME_RESERVED);
@@ -1132,21 +1104,22 @@ void WorldSession::HandleCharRenameOpcode(WorldPacket& recv_data)
return;
}
- std::string escaped_newname = newname;
- CharacterDatabase.EscapeString(escaped_newname);
-
- // make sure that the character belongs to the current account, that rename at login is enabled
+ // Ensure that the character belongs to the current account, that rename at login is enabled
// and that there is no character with the desired new name
- _charRenameCallback.SetParam(newname);
- _charRenameCallback.SetFutureResult(
- CharacterDatabase.AsyncPQuery(
- "SELECT guid, name FROM characters WHERE guid = %d AND account = %d AND (at_login & %d) = %d AND NOT EXISTS (SELECT NULL FROM characters WHERE name = '%s')",
- GUID_LOPART(guid), GetAccountId(), AT_LOGIN_RENAME, AT_LOGIN_RENAME, escaped_newname.c_str()
- )
- );
+ _charRenameCallback.SetParam(newName);
+
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_GET_FREE_NAME);
+
+ stmt->setUInt32(0, GUID_LOPART(guid));
+ stmt->setUInt32(1, GetAccountId());
+ stmt->setUInt16(2, AT_LOGIN_RENAME);
+ stmt->setUInt16(3, AT_LOGIN_RENAME);
+ stmt->setString(4, newName);
+
+ _charRenameCallback.SetFutureResult(CharacterDatabase.AsyncQuery(stmt));
}
-void WorldSession::HandleChangePlayerNameOpcodeCallBack(QueryResult result, std::string newname)
+void WorldSession::HandleChangePlayerNameOpcodeCallBack(PreparedQueryResult result, std::string newName)
{
if (!result)
{
@@ -1156,22 +1129,38 @@ void WorldSession::HandleChangePlayerNameOpcodeCallBack(QueryResult result, std:
return;
}
- uint32 guidLow = result->Fetch()[0].GetUInt32();
+ Field* fields = result->Fetch();
+
+ uint32 guidLow = fields[0].GetUInt32();
+ std::string oldName = fields[1].GetString();
+
uint64 guid = MAKE_NEW_GUID(guidLow, 0, HIGHGUID_PLAYER);
- std::string oldname = result->Fetch()[1].GetString();
- CharacterDatabase.PExecute("UPDATE characters set name = '%s', at_login = at_login & ~ %u WHERE guid ='%u'", newname.c_str(), uint32(AT_LOGIN_RENAME), guidLow);
- CharacterDatabase.PExecute("DELETE FROM character_declinedname WHERE guid ='%u'", guidLow);
+ // Update name and at_login flag in the db
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPDATE_NAME);
+
+ stmt->setString(0, newName);
+ stmt->setUInt16(1, AT_LOGIN_RENAME);
+ stmt->setUInt32(2, guidLow);
- sLog->outChar("Account: %d (IP: %s) Character:[%s] (guid:%u) Changed name to: %s", GetAccountId(), GetRemoteAddress().c_str(), oldname.c_str(), guidLow, newname.c_str());
+ CharacterDatabase.Execute(stmt);
+
+ // Removed declined name from db
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_DECLINED_NAME);
- WorldPacket data(SMSG_CHAR_RENAME, 1+8+(newname.size()+1));
+ stmt->setUInt32(0, guidLow);
+
+ CharacterDatabase.Execute(stmt);
+
+ sLog->outChar("Account: %d (IP: %s) Character:[%s] (guid:%u) Changed name to: %s", GetAccountId(), GetRemoteAddress().c_str(), oldName.c_str(), guidLow, newName.c_str());
+
+ WorldPacket data(SMSG_CHAR_RENAME, 1+8+(newName.size()+1));
data << uint8(RESPONSE_SUCCESS);
data << uint64(guid);
- data << newname;
+ data << newName;
SendPacket(&data);
- sWorld->UpdateCharacterNameData(guidLow, newname);
+ sWorld->UpdateCharacterNameData(guidLow, newName);
}
void WorldSession::HandleSetPlayerDeclinedNames(WorldPacket& recv_data)
diff --git a/src/server/game/Server/Protocol/Handlers/CombatHandler.cpp b/src/server/game/Server/Protocol/Handlers/CombatHandler.cpp
index 31a09e830ff..e6c4499baab 100755
--- a/src/server/game/Server/Protocol/Handlers/CombatHandler.cpp
+++ b/src/server/game/Server/Protocol/Handlers/CombatHandler.cpp
@@ -23,13 +23,15 @@
#include "ObjectAccessor.h"
#include "CreatureAI.h"
#include "ObjectDefines.h"
+#include "Vehicle.h"
+#include "VehicleDefines.h"
-void WorldSession::HandleAttackSwingOpcode(WorldPacket & recv_data)
+void WorldSession::HandleAttackSwingOpcode(WorldPacket& recv_data)
{
uint64 guid;
recv_data >> guid;
- sLog->outStaticDebug("WORLD: Recvd CMSG_ATTACKSWING Message guidlow:%u guidhigh:%u", GUID_LOPART(guid), GUID_HIPART(guid));
+ sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_ATTACKSWING Message guidlow:%u guidhigh:%u", GUID_LOPART(guid), GUID_HIPART(guid));
Unit* pEnemy = ObjectAccessor::GetUnit(*_player, guid);
@@ -47,6 +49,20 @@ void WorldSession::HandleAttackSwingOpcode(WorldPacket & recv_data)
return;
}
+ //! Client explicitly checks the following before sending CMSG_ATTACKSWING packet,
+ //! so we'll place the same check here. Note that it might be possible to reuse this snippet
+ //! in other places as well.
+ if (Vehicle* vehicle = _player->GetVehicle())
+ {
+ VehicleSeatEntry const* seat = vehicle->GetSeatForPassenger(_player);
+ ASSERT(seat);
+ if (!(seat->m_flags & VEHICLE_SEAT_FLAG_CAN_ATTACK))
+ {
+ SendAttackStop(pEnemy);
+ return;
+ }
+ }
+
_player->Attack(pEnemy, true);
}
@@ -55,7 +71,7 @@ void WorldSession::HandleAttackStopOpcode(WorldPacket & /*recv_data*/)
GetPlayer()->AttackStop();
}
-void WorldSession::HandleSetSheathedOpcode(WorldPacket & recv_data)
+void WorldSession::HandleSetSheathedOpcode(WorldPacket& recv_data)
{
uint32 sheathed;
recv_data >> sheathed;
@@ -79,4 +95,3 @@ void WorldSession::SendAttackStop(Unit const* enemy)
data << uint32(0); // unk, can be 1 also
SendPacket(&data);
}
-
diff --git a/src/server/game/Server/Protocol/Handlers/ItemHandler.cpp b/src/server/game/Server/Protocol/Handlers/ItemHandler.cpp
index f4e3af72892..4d323996de7 100755
--- a/src/server/game/Server/Protocol/Handlers/ItemHandler.cpp
+++ b/src/server/game/Server/Protocol/Handlers/ItemHandler.cpp
@@ -938,6 +938,7 @@ void WorldSession::HandleAutoBankItemOpcode(WorldPacket& recvPacket)
}
_player->RemoveItem(srcbag, srcslot, true);
+ _player->ItemRemovedQuestCheck(pItem->GetEntry(), pItem->GetCount());
_player->BankItem(dest, pItem, true);
}
@@ -965,6 +966,7 @@ void WorldSession::HandleAutoStoreBankItemOpcode(WorldPacket& recvPacket)
_player->RemoveItem(srcbag, srcslot, true);
_player->StoreItem(dest, pItem, true);
+ _player->ItemAddedQuestCheck(pItem->GetEntry(), pItem->GetCount());
}
else // moving from inventory to bank
{
diff --git a/src/server/game/Server/Protocol/Handlers/MiscHandler.cpp b/src/server/game/Server/Protocol/Handlers/MiscHandler.cpp
index 7327cdbba65..aef3bf03bd9 100755
--- a/src/server/game/Server/Protocol/Handlers/MiscHandler.cpp
+++ b/src/server/game/Server/Protocol/Handlers/MiscHandler.cpp
@@ -531,24 +531,23 @@ void WorldSession::HandleAddFriendOpcode(WorldPacket & recv_data)
if (!normalizePlayerName(friendName))
return;
- CharacterDatabase.EscapeString(friendName); // prevent SQL injection - normal name must not be changed by this call
+ sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: %s asked to add friend : '%s'", GetPlayer()->GetName(), friendName.c_str());
- sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: %s asked to add friend : '%s'",
- GetPlayer()->GetName(), friendName.c_str());
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_GET_GUID_RACE_ACC_BY_NAME);
+
+ stmt->setString(0, friendName);
_addFriendCallback.SetParam(friendNote);
- _addFriendCallback.SetFutureResult(
- CharacterDatabase.AsyncPQuery("SELECT guid, race, account FROM characters WHERE name = '%s'", friendName.c_str())
- );
+ _addFriendCallback.SetFutureResult(CharacterDatabase.AsyncQuery(stmt));
}
-void WorldSession::HandleAddFriendOpcodeCallBack(QueryResult result, std::string friendNote)
+void WorldSession::HandleAddFriendOpcodeCallBack(PreparedQueryResult result, std::string friendNote)
{
if (!GetPlayer())
return;
uint64 friendGuid;
- uint32 friendAcctid;
+ uint32 friendAccountId;
uint32 team;
FriendsResult friendResult;
@@ -557,11 +556,13 @@ void WorldSession::HandleAddFriendOpcodeCallBack(QueryResult result, std::string
if (result)
{
- friendGuid = MAKE_NEW_GUID((*result)[0].GetUInt32(), 0, HIGHGUID_PLAYER);
- team = Player::TeamForRace((*result)[1].GetUInt8());
- friendAcctid = (*result)[2].GetUInt32();
+ Field* fields = result->Fetch();
+
+ friendGuid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER);
+ team = Player::TeamForRace(fields[1].GetUInt8());
+ friendAccountId = fields[2].GetUInt32();
- if (!AccountMgr::IsPlayerAccount(GetSecurity()) || sWorld->getBoolConfig(CONFIG_ALLOW_GM_FRIEND) || AccountMgr::IsPlayerAccount(AccountMgr::GetSecurity(friendAcctid, realmID)))
+ if (!AccountMgr::IsPlayerAccount(GetSecurity()) || sWorld->getBoolConfig(CONFIG_ALLOW_GM_FRIEND) || AccountMgr::IsPlayerAccount(AccountMgr::GetSecurity(friendAccountId, realmID)))
{
if (friendGuid)
{
@@ -613,22 +614,24 @@ void WorldSession::HandleAddIgnoreOpcode(WorldPacket & recv_data)
{
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_ADD_IGNORE");
- std::string IgnoreName = GetTrinityString(LANG_FRIEND_IGNORE_UNKNOWN);
+ std::string ignoreName = GetTrinityString(LANG_FRIEND_IGNORE_UNKNOWN);
- recv_data >> IgnoreName;
+ recv_data >> ignoreName;
- if (!normalizePlayerName(IgnoreName))
+ if (!normalizePlayerName(ignoreName))
return;
- CharacterDatabase.EscapeString(IgnoreName); // prevent SQL injection - normal name must not be changed by this call
-
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: %s asked to Ignore: '%s'",
- GetPlayer()->GetName(), IgnoreName.c_str());
+ GetPlayer()->GetName(), ignoreName.c_str());
+
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_GET_GUID_BY_NAME);
+
+ stmt->setString(0, ignoreName);
- _addIgnoreCallback = CharacterDatabase.AsyncPQuery("SELECT guid FROM characters WHERE name = '%s'", IgnoreName.c_str());
+ _addIgnoreCallback = CharacterDatabase.AsyncQuery(stmt);
}
-void WorldSession::HandleAddIgnoreOpcodeCallBack(QueryResult result)
+void WorldSession::HandleAddIgnoreOpcodeCallBack(PreparedQueryResult result)
{
if (!GetPlayer())
return;
@@ -1607,7 +1610,7 @@ void WorldSession::HandleCancelMountAuraOpcode(WorldPacket & /*recv_data*/)
return;
}
- _player->Unmount();
+ _player->Dismount();
_player->RemoveAurasByType(SPELL_AURA_MOUNTED);
}
diff --git a/src/server/game/Server/Protocol/Handlers/MovementHandler.cpp b/src/server/game/Server/Protocol/Handlers/MovementHandler.cpp
index 4e45eb2d6c6..ae2612e4ced 100755
--- a/src/server/game/Server/Protocol/Handlers/MovementHandler.cpp
+++ b/src/server/game/Server/Protocol/Handlers/MovementHandler.cpp
@@ -299,7 +299,7 @@ void WorldSession::HandleMovementOpcodes(WorldPacket & recv_data)
// if we boarded a transport, add us to it
if (plMover && !plMover->GetTransport())
{
- // elevators also cause the client to send MOVEMENTFLAG_ONTRANSPORT - just unmount if the guid can be found in the transport list
+ // elevators also cause the client to send MOVEMENTFLAG_ONTRANSPORT - just dismount if the guid can be found in the transport list
for (MapManager::TransportSet::const_iterator iter = sMapMgr->m_Transports.begin(); iter != sMapMgr->m_Transports.end(); ++iter)
{
if ((*iter)->GetGUID() == movementInfo.t_guid)
diff --git a/src/server/game/Server/Protocol/Handlers/NPCHandler.cpp b/src/server/game/Server/Protocol/Handlers/NPCHandler.cpp
index a675214930a..92f4a0380f9 100755
--- a/src/server/game/Server/Protocol/Handlers/NPCHandler.cpp
+++ b/src/server/game/Server/Protocol/Handlers/NPCHandler.cpp
@@ -618,39 +618,43 @@ void WorldSession::HandleStablePet(WorldPacket & recv_data)
return;
}
- _stablePetCallback = CharacterDatabase.AsyncPQuery("SELECT owner, slot, id FROM character_pet WHERE owner = '%u' AND slot >= '%u' AND slot <= '%u' ORDER BY slot ",
- _player->GetGUIDLow(), PET_SAVE_FIRST_STABLE_SLOT, PET_SAVE_LAST_STABLE_SLOT);
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_GET_PET_SLOTS);
+ stmt->setUInt32(0, _player->GetGUIDLow());
+ stmt->setUInt8(1, PET_SAVE_FIRST_STABLE_SLOT);
+ stmt->setUInt8(2, PET_SAVE_LAST_STABLE_SLOT);
+
+ _stablePetCallback = CharacterDatabase.AsyncQuery(stmt);
}
-void WorldSession::HandleStablePetCallback(QueryResult result)
+void WorldSession::HandleStablePetCallback(PreparedQueryResult result)
{
if (!GetPlayer())
return;
- uint32 free_slot = 1;
+ uint8 freeSlot = 1;
if (result)
{
do
{
Field* fields = result->Fetch();
- uint32 slot = fields[1].GetUInt32();
+ uint8 slot = fields[1].GetUInt8();
// slots ordered in query, and if not equal then free
- if (slot != free_slot)
+ if (slot != freeSlot)
break;
// this slot not free, skip
- ++free_slot;
+ ++freeSlot;
}
while (result->NextRow());
}
WorldPacket data(SMSG_STABLE_RESULT, 1);
- if (free_slot > 0 && free_slot <= GetPlayer()->m_stableSlots)
+ if (freeSlot > 0 && freeSlot <= GetPlayer()->m_stableSlots)
{
- _player->RemovePet(_player->GetPet(), PetSaveMode(free_slot));
+ _player->RemovePet(_player->GetPet(), PetSaveMode(freeSlot));
SendStableResult(STABLE_SUCCESS_STABLE);
}
else
@@ -801,7 +805,7 @@ void WorldSession::HandleStableSwapPet(WorldPacket & recv_data)
// find swapped pet slot in stable
_stableSwapCallback.SetParam(pet_number);
_stableSwapCallback.SetFutureResult(
- CharacterDatabase.PQuery("SELECT slot, entry FROM character_pet WHERE owner = '%u' AND id = '%u'",
+ CharacterDatabase.AsyncPQuery("SELECT slot, entry FROM character_pet WHERE owner = '%u' AND id = '%u'",
_player->GetGUIDLow(), pet_number)
);
}
@@ -878,19 +882,18 @@ void WorldSession::HandleRepairItemOpcode(WorldPacket & recv_data)
// reputation discount
float discountMod = _player->GetReputationPriceDiscount(unit);
- uint32 TotalCost = 0;
if (itemGUID)
{
sLog->outDebug(LOG_FILTER_NETWORKIO, "ITEM: Repair item, itemGUID = %u, npcGUID = %u", GUID_LOPART(itemGUID), GUID_LOPART(npcGUID));
Item* item = _player->GetItemByGuid(itemGUID);
if (item)
- TotalCost = _player->DurabilityRepair(item->GetPos(), true, discountMod, guildBank);
+ _player->DurabilityRepair(item->GetPos(), true, discountMod, guildBank);
}
else
{
sLog->outDebug(LOG_FILTER_NETWORKIO, "ITEM: Repair all items, npcGUID = %u", GUID_LOPART(npcGUID));
- TotalCost = _player->DurabilityRepairAll(true, discountMod, guildBank);
+ _player->DurabilityRepairAll(true, discountMod, guildBank);
}
}
diff --git a/src/server/game/Server/Protocol/Handlers/PetitionsHandler.cpp b/src/server/game/Server/Protocol/Handlers/PetitionsHandler.cpp
index a931d8a5b3d..2e9b88bd3f0 100755
--- a/src/server/game/Server/Protocol/Handlers/PetitionsHandler.cpp
+++ b/src/server/game/Server/Protocol/Handlers/PetitionsHandler.cpp
@@ -311,21 +311,17 @@ void WorldSession::SendPetitionQueryOpcode(uint64 petitionguid)
uint64 ownerguid = 0;
uint32 type;
std::string name = "NO_NAME_FOR_GUID";
- uint8 signs = 0;
- QueryResult result = CharacterDatabase.PQuery(
- "SELECT ownerguid, name, "
- " (SELECT COUNT(playerguid) FROM petition_sign WHERE petition_sign.petitionguid = '%u') AS signs, "
- " type "
- "FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid), GUID_LOPART(petitionguid));
+ // TODO: Use CHAR_LOAD_PETITION PS
+ QueryResult result = CharacterDatabase.PQuery("SELECT ownerguid, name, type "
+ "FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
if (result)
{
Field* fields = result->Fetch();
ownerguid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER);
name = fields[1].GetString();
- signs = fields[2].GetUInt8();
- type = fields[3].GetUInt32();
+ type = fields[2].GetUInt32();
}
else
{
diff --git a/src/server/game/Server/Protocol/Handlers/QueryHandler.cpp b/src/server/game/Server/Protocol/Handlers/QueryHandler.cpp
index bf951619e63..042b1242a95 100755
--- a/src/server/game/Server/Protocol/Handlers/QueryHandler.cpp
+++ b/src/server/game/Server/Protocol/Handlers/QueryHandler.cpp
@@ -413,7 +413,10 @@ void WorldSession::HandleQuestPOIQuery(WorldPacket& recv_data)
recv_data >> count; // quest count, max=25
if (count >= MAX_QUEST_LOG_SIZE)
+ {
+ recv_data.rfinish();
return;
+ }
WorldPacket data(SMSG_QUEST_POI_QUERY_RESPONSE, 4+(4+4)*count);
data << uint32(count); // count
diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp
index 14c86286718..54d477abf69 100755
--- a/src/server/game/Server/WorldSession.cpp
+++ b/src/server/game/Server/WorldSession.cpp
@@ -222,7 +222,18 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
///- Retrieve packets from the receive queue and call the appropriate handlers
/// not process packets if socket already closed
WorldPacket* packet = NULL;
- while (m_Socket && !m_Socket->IsClosed() && _recvQueue.next(packet, updater))
+ //! Delete packet after processing by default
+ bool deletePacket = true;
+ //! To prevent infinite loop
+ WorldPacket* firstDelayedPacket = NULL;
+ //! If _recvQueue.peek() == firstDelayedPacket it means that in this Update call, we've processed all
+ //! *properly timed* packets, and we're now at the part of the queue where we find
+ //! delayed packets that were re-enqueued due to improper timing. To prevent an infinite
+ //! loop caused by re-enqueueing the same packets over and over again, we stop updating this session
+ //! and continue updating others. The re-enqueued packets will be handled in the next Update call for this session.
+ while (m_Socket && !m_Socket->IsClosed() &&
+ !_recvQueue.empty() && _recvQueue.peek(true) != firstDelayedPacket &&
+ _recvQueue.next(packet, updater))
{
if (packet->GetOpcode() >= NUM_MSG_TYPES)
{
@@ -240,8 +251,21 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
if (!_player)
{
// skip STATUS_LOGGEDIN opcode unexpected errors if player logout sometime ago - this can be network lag delayed packets
+ //! If player didn't log out a while ago, it means packets are being sent while the server does not recognize
+ //! the client to be in world yet. We will re-add the packets to the bottom of the queue and process them later.
if (!m_playerRecentlyLogout)
- LogUnexpectedOpcode(packet, "STATUS_LOGGEDIN", "the player has not logged in yet");
+ {
+ //! Prevent infinite loop
+ if (!firstDelayedPacket)
+ firstDelayedPacket = packet;
+ //! Because checking a bool is faster than reallocating memory
+ deletePacket = false;
+ QueuePacket(packet);
+ //! Log
+ sLog->outDebug(LOG_FILTER_NETWORKIO, "Re-enqueueing packet with opcode %s (0x%.4X) with with status STATUS_LOGGEDIN. "
+ "Player is currently not in world yet.", opHandle.name, packet->GetOpcode());
+ }
+
}
else if (_player->IsInWorld())
{
@@ -258,7 +282,7 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
"the player has not logged in yet and not recently logout");
else
{
- // not expected _player or must checked in packet hanlder
+ // not expected _player or must checked in packet handler
sScriptMgr->OnPacketReceive(m_Socket, WorldPacket(*packet));
(this->*opHandle.handler)(*packet);
if (sLog->IsOutDebug() && packet->rpos() < packet->wpos())
@@ -308,7 +332,7 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
break;
}
}
- catch(ByteBufferException &)
+ catch (ByteBufferException &)
{
sLog->outError("WorldSession::Update ByteBufferException occured while parsing a packet (opcode: %u) from client %s, accountid=%i. Skipped packet.",
packet->GetOpcode(), GetRemoteAddress().c_str(), GetAccountId());
@@ -320,7 +344,8 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
}
}
- delete packet;
+ if (deletePacket)
+ delete packet;
}
ProcessQueryCallbacks();
@@ -344,6 +369,7 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
if (!m_Socket)
return false; //Will remove this session from the world session map
}
+
return true;
}
@@ -983,12 +1009,13 @@ void WorldSession::InitializeQueryCallbackParameters()
void WorldSession::ProcessQueryCallbacks()
{
QueryResult result;
+ PreparedQueryResult result2;
//! HandleCharEnumOpcode
if (_charEnumCallback.ready())
{
- _charEnumCallback.get(result);
- HandleCharEnum(result);
+ _charEnumCallback.get(result2);
+ HandleCharEnum(result2);
_charEnumCallback.cancel();
}
@@ -1013,8 +1040,8 @@ void WorldSession::ProcessQueryCallbacks()
if (_addFriendCallback.IsReady())
{
std::string param = _addFriendCallback.GetParam();
- _addFriendCallback.GetResult(result);
- HandleAddFriendOpcodeCallBack(result, param);
+ _addFriendCallback.GetResult(result2);
+ HandleAddFriendOpcodeCallBack(result2, param);
_addFriendCallback.FreeResult();
}
@@ -1022,16 +1049,16 @@ void WorldSession::ProcessQueryCallbacks()
if (_charRenameCallback.IsReady())
{
std::string param = _charRenameCallback.GetParam();
- _charRenameCallback.GetResult(result);
- HandleChangePlayerNameOpcodeCallBack(result, param);
+ _charRenameCallback.GetResult(result2);
+ HandleChangePlayerNameOpcodeCallBack(result2, param);
_charRenameCallback.FreeResult();
}
//- HandleCharAddIgnoreOpcode
if (_addIgnoreCallback.ready())
{
- _addIgnoreCallback.get(result);
- HandleAddIgnoreOpcodeCallBack(result);
+ _addIgnoreCallback.get(result2);
+ HandleAddIgnoreOpcodeCallBack(result2);
_addIgnoreCallback.cancel();
}
@@ -1047,8 +1074,8 @@ void WorldSession::ProcessQueryCallbacks()
//- HandleStablePet
if (_stablePetCallback.ready())
{
- _stablePetCallback.get(result);
- HandleStablePetCallback(result);
+ _stablePetCallback.get(result2);
+ HandleStablePetCallback(result2);
_stablePetCallback.cancel();
}
diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h
index 4a83c2d4092..d1f607704b9 100755
--- a/src/server/game/Server/WorldSession.h
+++ b/src/server/game/Server/WorldSession.h
@@ -184,7 +184,7 @@ class CharacterCreateInfo
protected:
CharacterCreateInfo(std::string name, uint8 race, uint8 cclass, uint8 gender, uint8 skin, uint8 face, uint8 hairStyle, uint8 hairColor, uint8 facialHair, uint8 outfitId,
WorldPacket& data) : Name(name), Race(race), Class(cclass), Gender(gender), Skin(skin), Face(face), HairStyle(hairStyle), HairColor(hairColor), FacialHair(facialHair),
- OutfitId(outfitId), Data(data), CharCount(0), Stage(0)
+ OutfitId(outfitId), Data(data), CharCount(0)
{}
/// User specified variables
@@ -203,9 +203,6 @@ class CharacterCreateInfo
/// Server side data
uint8 CharCount;
- /// Internal
- uint8 Stage; // Stage of the callback chain
-
private:
virtual ~CharacterCreateInfo(){};
};
@@ -400,7 +397,7 @@ class WorldSession
void HandleCharCreateOpcode(WorldPacket& recvPacket);
void HandleCharCreateCallback(PreparedQueryResult result, CharacterCreateInfo* createInfo);
void HandlePlayerLoginOpcode(WorldPacket& recvPacket);
- void HandleCharEnum(QueryResult result);
+ void HandleCharEnum(PreparedQueryResult result);
void HandlePlayerLogin(LoginQueryHolder * holder);
void HandleCharFactionOrRaceChange(WorldPacket& recv_data);
@@ -469,10 +466,10 @@ class WorldSession
void HandleEmoteOpcode(WorldPacket& recvPacket);
void HandleContactListOpcode(WorldPacket& recvPacket);
void HandleAddFriendOpcode(WorldPacket& recvPacket);
- void HandleAddFriendOpcodeCallBack(QueryResult result, std::string friendNote);
+ void HandleAddFriendOpcodeCallBack(PreparedQueryResult result, std::string friendNote);
void HandleDelFriendOpcode(WorldPacket& recvPacket);
void HandleAddIgnoreOpcode(WorldPacket& recvPacket);
- void HandleAddIgnoreOpcodeCallBack(QueryResult result);
+ void HandleAddIgnoreOpcodeCallBack(PreparedQueryResult result);
void HandleDelIgnoreOpcode(WorldPacket& recvPacket);
void HandleSetContactNotesOpcode(WorldPacket& recvPacket);
void HandleBugOpcode(WorldPacket& recvPacket);
@@ -588,7 +585,7 @@ class WorldSession
void HandleBinderActivateOpcode(WorldPacket& recvPacket);
void HandleListStabledPetsOpcode(WorldPacket& recvPacket);
void HandleStablePet(WorldPacket& recvPacket);
- void HandleStablePetCallback(QueryResult result);
+ void HandleStablePetCallback(PreparedQueryResult result);
void HandleUnstablePet(WorldPacket& recvPacket);
void HandleUnstablePetCallback(QueryResult result, uint32 petnumber);
void HandleBuyStableSlot(WorldPacket& recvPacket);
@@ -747,7 +744,7 @@ class WorldSession
void HandleSetActionBarToggles(WorldPacket& recv_data);
void HandleCharRenameOpcode(WorldPacket& recv_data);
- void HandleChangePlayerNameOpcodeCallBack(QueryResult result, std::string newname);
+ void HandleChangePlayerNameOpcodeCallBack(PreparedQueryResult result, std::string newName);
void HandleSetPlayerDeclinedNames(WorldPacket& recv_data);
void HandleTotemDestroyed(WorldPacket& recv_data);
@@ -896,16 +893,15 @@ class WorldSession
void InitializeQueryCallbackParameters();
void ProcessQueryCallbacks();
- ACE_Future_Set<QueryResult> _nameQueryCallbacks;
- QueryResultFuture _charEnumCallback;
- QueryResultFuture _addIgnoreCallback;
- QueryResultFuture _stablePetCallback;
- QueryCallback<QueryResult, std::string> _charRenameCallback;
- QueryCallback<QueryResult, std::string> _addFriendCallback;
+ PreparedQueryResultFuture _charEnumCallback;
+ PreparedQueryResultFuture _addIgnoreCallback;
+ PreparedQueryResultFuture _stablePetCallback;
+ QueryCallback<PreparedQueryResult, std::string> _charRenameCallback;
+ QueryCallback<PreparedQueryResult, std::string> _addFriendCallback;
QueryCallback<QueryResult, uint32> _unstablePetCallback;
QueryCallback<QueryResult, uint32> _stableSwapCallback;
QueryCallback<QueryResult, uint64> _sendStabledPetCallback;
- QueryCallback<PreparedQueryResult, CharacterCreateInfo*> _charCreateCallback;
+ QueryCallback<PreparedQueryResult, CharacterCreateInfo*, true> _charCreateCallback;
QueryResultHolderFuture _charLoginCallback;
private:
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index b690a811fbb..12c40c15db4 100755
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -1518,7 +1518,7 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const
spellId3 = 47180;
break;
}
- target->CastSpell(target, spellId, true, NULL, this);
+ target->CastSpell(target, spellId3, true, NULL, this);
}
// Master Shapeshifter - Cat
if (AuraEffect const* aurEff = target->GetDummyAuraEffect(SPELLFAMILY_GENERIC, 2851, 0))
@@ -2821,7 +2821,7 @@ void AuraEffect::HandleAuraMounted(AuraApplication const* aurApp, uint8 mode, bo
}
else
{
- target->Unmount();
+ target->Dismount();
//some mounts like Headless Horseman's Mount or broom stick are skill based spell
// need to remove ALL arura related to mounts, this will stop client crash with broom stick
// and never endless flying after using Headless Horseman's Mount
@@ -4794,18 +4794,22 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool
break;
case 63322: // Saronite Vapors
{
- int32 mana = int32(GetAmount() * pow(2.0f, GetBase()->GetStackAmount())); // mana restore - bp * 2^stackamount
- int32 damage = mana * 2; // damage
- caster->CastCustomSpell(target, 63337, &mana, NULL, NULL, true);
- caster->CastCustomSpell(target, 63338, &damage, NULL, NULL, true);
+ if (caster)
+ {
+ int32 mana = int32(GetAmount() * pow(2.0f, GetBase()->GetStackAmount())); // mana restore - bp * 2^stackamount
+ int32 damage = mana * 2; // damage
+ caster->CastCustomSpell(target, 63337, &mana, NULL, NULL, true);
+ caster->CastCustomSpell(target, 63338, &damage, NULL, NULL, true);
+ }
break;
}
case 71563:
if (Aura* newAura = target->AddAura(71564, target))
newAura->SetStackAmount(newAura->GetSpellInfo()->StackAmount);
break;
- case 59628: // Tricks of the Trade
- target->SetReducedThreatPercent(100,caster->GetGUID());
+ case 59628: // Tricks of the Trade
+ if (caster && caster->GetMisdirectionTarget())
+ target->SetReducedThreatPercent(100, caster->GetMisdirectionTarget()->GetGUID());
break;
}
}
@@ -4958,9 +4962,14 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool
// Tricks of the trade
switch(GetId())
{
- case 59628:
- case 57934:
+ case 59628: //Tricks of the trade buff on rogue (6sec duration)
target->SetReducedThreatPercent(0,0);
+ break;
+ case 57934: //Tricks of the trade buff on rogue (30sec duration)
+ if (aurApp->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE || !caster->GetMisdirectionTarget())
+ target->SetReducedThreatPercent(0,0);
+ else
+ target->SetReducedThreatPercent(0,caster->GetMisdirectionTarget()->GetGUID());
break;
}
default:
@@ -5201,7 +5210,7 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool
if (!(mode & AURA_EFFECT_HANDLE_REAL))
break;
// Sentry Totem
- if (GetId() == 6495 && caster->GetTypeId() == TYPEID_PLAYER)
+ if (GetId() == 6495 && caster && caster->GetTypeId() == TYPEID_PLAYER)
{
if (apply)
{
diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp
index 525084a70ed..91ecc328fd8 100755
--- a/src/server/game/Spells/Auras/SpellAuras.cpp
+++ b/src/server/game/Spells/Auras/SpellAuras.cpp
@@ -1332,6 +1332,7 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b
if (removeMode != AURA_REMOVE_BY_EXPIRE)
break;
target->CastSpell(target, 32612, true, NULL, GetEffect(1));
+ target->CombatStop();
break;
case 74396: // Fingers of Frost
// Remove the IGNORE_AURASTATE aura
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index 8a4c0a768d8..fbb1a1965d8 100755
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -3254,6 +3254,12 @@ void Spell::handle_immediate()
m_caster->AddInterruptMask(m_spellInfo->ChannelInterruptFlags);
SendChannelStart(duration);
}
+ else if (duration == -1)
+ {
+ m_spellState = SPELL_STATE_CASTING;
+ m_caster->AddInterruptMask(m_spellInfo->ChannelInterruptFlags);
+ SendChannelStart(duration);
+ }
}
PrepareTargetProcessing();
@@ -3279,7 +3285,6 @@ void Spell::handle_immediate()
if (m_spellInfo->IsRangedWeaponSpell() && m_spellInfo->IsChanneled())
TakeAmmo();
-
if (m_spellState != SPELL_STATE_CASTING)
finish(true); // successfully finish spell cast (not last in case autorepeat or channel spell)
}
@@ -3478,9 +3483,9 @@ void Spell::update(uint32 difftime)
{
case SPELL_STATE_PREPARING:
{
- if (m_timer)
+ if (m_timer > 0)
{
- if (difftime >= m_timer)
+ if (difftime >= (uint32)m_timer)
m_timer = 0;
else
m_timer -= difftime;
@@ -3489,10 +3494,11 @@ void Spell::update(uint32 difftime)
if (m_timer == 0 && !IsNextMeleeSwingSpell() && !IsAutoRepeat())
// don't CheckCast for instant spells - done in spell::prepare, skip duplicate checks, needed for range checks for example
cast(!m_casttime);
- } break;
+ break;
+ }
case SPELL_STATE_CASTING:
{
- if (m_timer > 0)
+ if (m_timer)
{
// check if there are alive targets left
if (!UpdateChanneledTargetList())
@@ -3502,10 +3508,13 @@ void Spell::update(uint32 difftime)
finish();
}
- if (difftime >= m_timer)
- m_timer = 0;
- else
- m_timer -= difftime;
+ if (m_timer > 0)
+ {
+ if (difftime >= (uint32)m_timer)
+ m_timer = 0;
+ else
+ m_timer -= difftime;
+ }
}
if (m_timer == 0)
@@ -3547,10 +3556,10 @@ void Spell::update(uint32 difftime)
finish();
}
- } break;
+ break;
+ }
default:
- {
- }break;
+ break;
}
}
@@ -3666,9 +3675,9 @@ void Spell::SendCastResult(Player* caster, SpellInfo const* spellInfo, uint8 cas
switch (result)
{
case SPELL_FAILED_REQUIRES_SPELL_FOCUS:
- data << uint32(spellInfo->RequiresSpellFocus);
+ data << uint32(spellInfo->RequiresSpellFocus); // SpellFocusObject.dbc id
break;
- case SPELL_FAILED_REQUIRES_AREA:
+ case SPELL_FAILED_REQUIRES_AREA: // AreaTable.dbc id
// hardcode areas limitation case
switch (spellInfo->Id)
{
@@ -3701,14 +3710,15 @@ void Spell::SendCastResult(Player* caster, SpellInfo const* spellInfo, uint8 cas
data << uint32(spellInfo->TotemCategory[1]);
break;
case SPELL_FAILED_EQUIPPED_ITEM_CLASS:
+ case SPELL_FAILED_EQUIPPED_ITEM_CLASS_MAINHAND:
+ case SPELL_FAILED_EQUIPPED_ITEM_CLASS_OFFHAND:
data << uint32(spellInfo->EquippedItemClass);
data << uint32(spellInfo->EquippedItemSubClassMask);
- //data << uint32(spellInfo->EquippedItemInventoryTypeMask);
break;
case SPELL_FAILED_TOO_MANY_OF_ITEM:
{
uint32 item = 0;
- for (int8 x = 0;x < 3; x++)
+ for (int8 x = 0; x < 3; x++)
if (spellInfo->Effects[x].ItemType)
item = spellInfo->Effects[x].ItemType;
ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(item);
@@ -3757,7 +3767,7 @@ void Spell::SendSpellStart()
data << uint8(m_cast_count); // pending spell cast?
data << uint32(m_spellInfo->Id); // spellId
data << uint32(castFlags); // cast flags
- data << uint32(m_timer); // delay?
+ data << int32(m_timer); // delay?
m_targets.Write(data);
@@ -3856,7 +3866,7 @@ void Spell::SendSpellGo()
}
}
- if (castFlags & CAST_FLAG_UNKNOWN_18) // unknown wotlk
+ if (castFlags & CAST_FLAG_UNKNOWN_18)
{
data << float(0);
data << uint32(0);
@@ -3865,7 +3875,7 @@ void Spell::SendSpellGo()
if (castFlags & CAST_FLAG_AMMO)
WriteAmmoToPacket(&data);
- if (castFlags & CAST_FLAG_UNKNOWN_20) // unknown wotlk
+ if (castFlags & CAST_FLAG_UNKNOWN_20)
{
data << uint32(0);
data << uint32(0);
@@ -4126,9 +4136,6 @@ void Spell::SendChannelUpdate(uint32 time)
m_caster->SetUInt32Value(UNIT_CHANNEL_SPELL, 0);
}
- if (m_caster->GetTypeId() != TYPEID_PLAYER)
- return;
-
WorldPacket data(MSG_CHANNEL_UPDATE, 8+4);
data.append(m_caster->GetPackGUID());
data << uint32(time);
@@ -5646,7 +5653,8 @@ SpellCastResult Spell::CheckRange(bool strict)
if (m_spellInfo->RangeEntry)
{
- // self cast is used for triggered spells, no range checking needed
+ // check needed by 68766 51693 - both spells are cast on enemies and have 0 max range
+ // these are triggered by other spells - possibly we should omit range check in that case?
if (m_spellInfo->RangeEntry->ID == 1)
return SPELL_CAST_OK;
@@ -6263,7 +6271,7 @@ void Spell::Delayed() // only called in DealDamage()
AddPctN(delaytime, -delayReduce);
- if (int32(m_timer) + delaytime > m_casttime)
+ if (m_timer + delaytime > m_casttime)
{
delaytime = m_casttime - m_timer;
m_timer = m_casttime;
@@ -6298,7 +6306,7 @@ void Spell::DelayedChannel()
AddPctN(delaytime, -delayReduce);
- if (int32(m_timer) <= delaytime)
+ if (m_timer <= delaytime)
{
delaytime = m_timer;
m_timer = 0;
diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h
index 624c3b9b9b3..f57b3114a70 100755
--- a/src/server/game/Spells/Spell.h
+++ b/src/server/game/Spells/Spell.h
@@ -647,7 +647,7 @@ class Spell
// -------------------------------------------
uint32 m_spellState;
- uint32 m_timer;
+ int32 m_timer;
TriggerCastFlags _triggeredCastFlags;
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index e42294f59ae..95917070b5d 100755
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -606,57 +606,67 @@ void Spell::EffectSchoolDMG(SpellEffIndex effIndex)
case SPELLFAMILY_ROGUE:
{
// Envenom
- if (m_caster->GetTypeId() == TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags[1] & 0x8))
+ if (m_spellInfo->SpellFamilyFlags[1] & 0x00000008)
{
- // consume from stack dozes not more that have combo-points
- if (uint32 combo = m_caster->ToPlayer()->GetComboPoints())
+ if (Player* player = m_caster->ToPlayer())
{
- // Lookup for Deadly poison (only attacker applied)
- if (AuraEffect const* aurEff = unitTarget->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_ROGUE, 0x10000, 0, 0, m_caster->GetGUID()))
+ // consume from stack dozes not more that have combo-points
+ if (uint32 combo = player->GetComboPoints())
{
- // count consumed deadly poison doses at target
- bool needConsume = true;
- uint32 spellId = aurEff->GetId();
- uint32 doses = aurEff->GetBase()->GetStackAmount();
- if (doses > combo)
- doses = combo;
- // Master Poisoner
- Unit::AuraEffectList const& auraList = m_caster->ToPlayer()->GetAuraEffectsByType(SPELL_AURA_MOD_AURA_DURATION_BY_DISPEL_NOT_STACK);
- for (Unit::AuraEffectList::const_iterator iter = auraList.begin(); iter != auraList.end(); ++iter)
+ // Lookup for Deadly poison (only attacker applied)
+ if (AuraEffect const* aurEff = unitTarget->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_ROGUE, 0x00010000, 0, 0, m_caster->GetGUID()))
{
- if ((*iter)->GetSpellInfo()->SpellFamilyName == SPELLFAMILY_ROGUE && (*iter)->GetSpellInfo()->SpellIconID == 1960)
+ // count consumed deadly poison doses at target
+ bool needConsume = true;
+ uint32 spellId = aurEff->GetId();
+
+ uint32 doses = aurEff->GetBase()->GetStackAmount();
+ if (doses > combo)
+ doses = combo;
+
+ // Master Poisoner
+ Unit::AuraEffectList const& auraList = player->GetAuraEffectsByType(SPELL_AURA_MOD_AURA_DURATION_BY_DISPEL_NOT_STACK);
+ for (Unit::AuraEffectList::const_iterator iter = auraList.begin(); iter != auraList.end(); ++iter)
{
- uint32 chance = (*iter)->GetSpellInfo()->Effects[EFFECT_2].CalcValue(m_caster);
+ if ((*iter)->GetSpellInfo()->SpellFamilyName == SPELLFAMILY_ROGUE && (*iter)->GetSpellInfo()->SpellIconID == 1960)
+ {
+ uint32 chance = (*iter)->GetSpellInfo()->Effects[EFFECT_2].CalcValue(m_caster);
- if (chance && roll_chance_i(chance))
- needConsume = false;
+ if (chance && roll_chance_i(chance))
+ needConsume = false;
- break;
+ break;
+ }
}
+
+ if (needConsume)
+ for (uint32 i = 0; i < doses; ++i)
+ unitTarget->RemoveAuraFromStack(spellId);
+
+ damage *= doses;
+ damage += int32(player->GetTotalAttackPowerValue(BASE_ATTACK) * 0.09f * combo);
}
- if (needConsume)
- for (uint32 i = 0; i < doses; ++i)
- unitTarget->RemoveAuraFromStack(spellId);
- damage *= doses;
- damage += int32(((Player*)m_caster)->GetTotalAttackPowerValue(BASE_ATTACK) * 0.09f * doses);
+ // Eviscerate and Envenom Bonus Damage (item set effect)
+ if (m_caster->HasAura(37169))
+ damage += combo * 40;
}
- // Eviscerate and Envenom Bonus Damage (item set effect)
- if (m_caster->HasAura(37169))
- damage += ((Player*)m_caster)->GetComboPoints()*40;
}
}
// Eviscerate
- else if ((m_spellInfo->SpellFamilyFlags[0] & 0x00020000) && m_caster->GetTypeId() == TYPEID_PLAYER)
+ else if (m_spellInfo->SpellFamilyFlags[0] & 0x00020000)
{
- if (uint32 combo = ((Player*)m_caster)->GetComboPoints())
+ if (m_caster->GetTypeId() == TYPEID_PLAYER)
{
- float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
- damage += irand(int32(ap * combo * 0.03f), int32(ap * combo * 0.07f));
+ if (uint32 combo = ((Player*)m_caster)->GetComboPoints())
+ {
+ float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
+ damage += irand(int32(ap * combo * 0.03f), int32(ap * combo * 0.07f));
- // Eviscerate and Envenom Bonus Damage (item set effect)
- if (m_caster->HasAura(37169))
- damage += combo*40;
+ // Eviscerate and Envenom Bonus Damage (item set effect)
+ if (m_caster->HasAura(37169))
+ damage += combo*40;
+ }
}
}
break;
@@ -1421,11 +1431,19 @@ void Spell::EffectDummy(SpellEffIndex effIndex)
{
if (!unitTarget)
return;
- // Restorative Totems
if (Unit* owner = m_caster->GetOwner())
+ {
+ if (m_triggeredByAuraSpell)
+ damage = int32(owner->SpellHealingBonus(unitTarget, m_triggeredByAuraSpell, damage, HEAL));
+
+ // Restorative Totems
if (AuraEffect* dummy = owner->GetAuraEffect(SPELL_AURA_DUMMY, SPELLFAMILY_SHAMAN, 338, 1))
AddPctN(damage, dummy->GetAmount());
+ // Glyph of Healing Stream Totem
+ if (AuraEffect const* aurEff = owner->GetAuraEffect(55456, EFFECT_0))
+ AddPctN(damage, aurEff->GetAmount());
+ }
m_caster->CastCustomSpell(unitTarget, 52042, &damage, 0, 0, true, 0, 0, m_originalCasterGUID);
return;
}
@@ -2093,12 +2111,12 @@ void Spell::EffectUnlearnSpecialization(SpellEffIndex effIndex)
if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
return;
- Player* _player = unitTarget->ToPlayer();
+ Player* player = unitTarget->ToPlayer();
uint32 spellToUnlearn = m_spellInfo->Effects[effIndex].TriggerSpell;
- _player->removeSpell(spellToUnlearn);
+ player->removeSpell(spellToUnlearn);
- sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Spell: Player %u has unlearned spell %u from NpcGUID: %u", _player->GetGUIDLow(), spellToUnlearn, m_caster->GetGUIDLow());
+ sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Spell: Player %u has unlearned spell %u from NpcGUID: %u", player->GetGUIDLow(), spellToUnlearn, m_caster->GetGUIDLow());
}
void Spell::EffectPowerDrain(SpellEffIndex effIndex)
@@ -2145,19 +2163,9 @@ void Spell::EffectSendEvent(SpellEffIndex effIndex)
&& effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
return;
- //! it's possible for spells with this spell effect to either have a target or no target
- //! in case of a target, we will execute this handler on SPELL_EFFECT_HANDLE_HIT_TARGET
- //! with all relevant variables, and we will skip SPELL_EFFECT_HANDLE_HIT
- if (effectHandleMode == SPELL_EFFECT_HANDLE_HIT)
- {
- if (GetSpellInfo()->Effects[effIndex].TargetA.GetTarget() != 0 ||
- GetSpellInfo()->Effects[effIndex].TargetB.GetTarget() != 0)
- return;
- }
-
WorldObject* target = NULL;
- // call events for target if present
+ // call events for object target if present
if (effectHandleMode == SPELL_EFFECT_HANDLE_HIT_TARGET)
{
if (unitTarget)
@@ -2165,9 +2173,15 @@ void Spell::EffectSendEvent(SpellEffIndex effIndex)
else if (gameObjTarget)
target = gameObjTarget;
}
- // call event with no target or focus target when no targets could be found due to no dbc entry
- else if (!m_spellInfo->Effects[effIndex].GetProvidedTargetMask())
+ else // if (effectHandleMode == SPELL_EFFECT_HANDLE_HIT)
{
+ // let's prevent executing effect handler twice in case when spell effect is capable of targeting an object
+ // this check was requested by scripters, but it has some downsides:
+ // now it's impossible to script (using sEventScripts) a cast which misses all targets
+ // or to have an ability to script the moment spell hits dest (in a case when there are object targets present)
+ if (m_spellInfo->Effects[effIndex].GetProvidedTargetMask() & (TARGET_FLAG_UNIT_MASK | TARGET_FLAG_GAMEOBJECT_MASK))
+ return;
+ // some spells have no target entries in dbc and they use focus target
if (focusObject)
target = focusObject;
// TODO: there should be a possibility to pass dest target to event script
@@ -2588,8 +2602,8 @@ void Spell::EffectPersistentAA(SpellEffIndex effIndex)
// Caster not in world, might be spell triggered from aura removal
if (!caster->IsInWorld())
return;
- DynamicObject* dynObj = new DynamicObject();
- if (!dynObj->CreateDynamicObject(sObjectMgr->GenerateLowGuid(HIGHGUID_DYNAMICOBJECT), caster, m_spellInfo->Id, *m_targets.GetDst(), radius, false, DYNAMIC_OBJECT_AREA_SPELL))
+ DynamicObject* dynObj = new DynamicObject(false);
+ if (!dynObj->CreateDynamicObject(sObjectMgr->GenerateLowGuid(HIGHGUID_DYNAMICOBJECT), caster, m_spellInfo->Id, *m_targets.GetDst(), radius, DYNAMIC_OBJECT_AREA_SPELL))
{
delete dynObj;
return;
@@ -3437,8 +3451,8 @@ void Spell::EffectAddFarsight(SpellEffIndex effIndex)
if (!m_caster->IsInWorld())
return;
- DynamicObject* dynObj = new DynamicObject();
- if (!dynObj->CreateDynamicObject(sObjectMgr->GenerateLowGuid(HIGHGUID_DYNAMICOBJECT), m_caster, m_spellInfo->Id, *m_targets.GetDst(), radius, true, DYNAMIC_OBJECT_FARSIGHT_FOCUS))
+ DynamicObject* dynObj = new DynamicObject(true);
+ if (!dynObj->CreateDynamicObject(sObjectMgr->GenerateLowGuid(HIGHGUID_DYNAMICOBJECT), m_caster, m_spellInfo->Id, *m_targets.GetDst(), radius, DYNAMIC_OBJECT_FARSIGHT_FOCUS))
{
delete dynObj;
return;
@@ -5875,16 +5889,15 @@ void Spell::EffectFeedPet(SpellEffIndex effIndex)
if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
return;
- if (m_caster->GetTypeId() != TYPEID_PLAYER)
+ Player* player = m_caster->ToPlayer();
+ if (!player)
return;
- Player* _player = m_caster->ToPlayer();
-
Item* foodItem = itemTarget;
if (!foodItem)
return;
- Pet* pet = _player->GetPet();
+ Pet* pet = player->GetPet();
if (!pet)
return;
@@ -5898,7 +5911,7 @@ void Spell::EffectFeedPet(SpellEffIndex effIndex)
ExecuteLogEffectDestroyItem(effIndex, foodItem->GetEntry());
uint32 count = 1;
- _player->DestroyItemCount(foodItem, count, true);
+ player->DestroyItemCount(foodItem, count, true);
// TODO: fix crash when a spell has two effects, both pointed at the same item target
m_caster->CastCustomSpell(pet, m_spellInfo->Effects[effIndex].TriggerSpell, &benefit, NULL, NULL, true);
@@ -6097,7 +6110,7 @@ void Spell::EffectReputation(SpellEffIndex effIndex)
if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
return;
- Player* _player = unitTarget->ToPlayer();
+ Player* player = unitTarget->ToPlayer();
int32 rep_change = damage;
@@ -6114,10 +6127,10 @@ void Spell::EffectReputation(SpellEffIndex effIndex)
}
// Bonus from spells that increase reputation gain
- float bonus = rep_change * _player->GetTotalAuraModifier(SPELL_AURA_MOD_REPUTATION_GAIN) / 100.0f; // 10%
+ float bonus = rep_change * player->GetTotalAuraModifier(SPELL_AURA_MOD_REPUTATION_GAIN) / 100.0f; // 10%
rep_change += (int32)bonus;
- _player->GetReputationMgr().ModifyReputation(factionEntry, rep_change);
+ player->GetReputationMgr().ModifyReputation(factionEntry, rep_change);
}
void Spell::EffectQuestComplete(SpellEffIndex effIndex)
@@ -6227,9 +6240,13 @@ void Spell::EffectCharge(SpellEffIndex /*effIndex*/)
if (!unitTarget)
return;
- float x, y, z;
- unitTarget->GetContactPoint(m_caster, x, y, z);
- m_caster->GetMotionMaster()->MoveCharge(x, y, z);
+ float angle = unitTarget->GetRelativeAngle(m_caster);
+ Position pos;
+
+ unitTarget->GetContactPoint(m_caster, pos.m_positionX, pos.m_positionY, pos.m_positionZ);
+ unitTarget->GetFirstCollisionPosition(pos, unitTarget->GetObjectSize(), angle);
+
+ m_caster->GetMotionMaster()->MoveCharge(pos.m_positionX, pos.m_positionY, pos.m_positionZ + unitTarget->GetObjectSize());
}
if (effectHandleMode == SPELL_EFFECT_HANDLE_HIT_TARGET)
@@ -6250,9 +6267,13 @@ void Spell::EffectChargeDest(SpellEffIndex /*effIndex*/)
if (m_targets.HasDst())
{
- float x, y, z;
- m_targets.GetDst()->GetPosition(x, y, z);
- m_caster->GetMotionMaster()->MoveCharge(x, y, z);
+ Position pos;
+ m_targets.GetDst()->GetPosition(&pos);
+ float angle = m_caster->GetRelativeAngle(pos.GetPositionX(), pos.GetPositionY());
+ float dist = m_caster->GetDistance(pos);
+ m_caster->GetFirstCollisionPosition(pos, dist, angle);
+
+ m_caster->GetMotionMaster()->MoveCharge(pos.m_positionX, pos.m_positionY, pos.m_positionZ);
}
}
@@ -6432,20 +6453,20 @@ void Spell::EffectSummonDeadPet(SpellEffIndex /*effIndex*/)
if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
return;
- if (m_caster->GetTypeId() != TYPEID_PLAYER)
- return;
- Player* _player = m_caster->ToPlayer();
- Pet* pet = _player->GetPet();
- if (!pet)
+ Player* player = m_caster->ToPlayer();
+ if (!player)
return;
- if (pet->isAlive())
+
+ Pet* pet = player->GetPet();
+ if (!pet || pet->isAlive())
return;
+
if (damage < 0)
return;
float x, y, z;
- _player->GetPosition(x, y, z);
- _player->GetMap()->CreatureRelocation(pet, x, y, z, _player->GetOrientation());
+ player->GetPosition(x, y, z);
+ player->GetMap()->CreatureRelocation(pet, x, y, z, player->GetOrientation());
pet->SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_NONE);
pet->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
@@ -6454,7 +6475,7 @@ void Spell::EffectSummonDeadPet(SpellEffIndex /*effIndex*/)
pet->SetHealth(pet->CountPctFromMaxHealth(damage));
//pet->AIM_Initialize();
- //_player->PetSpellInitialize();
+ //player->PetSpellInitialize();
pet->SavePetToDB(PET_SAVE_AS_CURRENT);
}
diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp
index 972276c7d26..463b46972fa 100644
--- a/src/server/game/Spells/SpellInfo.cpp
+++ b/src/server/game/Spells/SpellInfo.cpp
@@ -2304,6 +2304,19 @@ bool SpellInfo::_IsPositiveEffect(uint8 effIndex, bool deep) const
if (Id == 30708)
return false;
break;
+ case SPELLFAMILY_ROGUE:
+ switch (Id)
+ {
+ // Envenom must be considered as a positive effect even though it deals damage
+ case 32645: // Envenom (Rank 1)
+ case 32684: // Envenom (Rank 2)
+ case 57992: // Envenom (Rank 3)
+ case 57993: // Envenom (Rank 4)
+ return true;
+ default:
+ break;
+ }
+ break;
default:
break;
}
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index 6cfbb04e179..8976f90690c 100755
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -3230,6 +3230,10 @@ void SpellMgr::LoadDbcDataCorrections()
// this needs research on modifier applying rules, does not seem to be in Attributes fields
spellInfo->EffectSpellClassMask[0] = flag96(0x00000040, 0x00000000, 0x00000000);
break;
+ case 63163: // Apply Enchanted Bridle (Argent Tournament)
+ spellInfo->EffectDieSides[0] = 0; // was 1, that should probably mean seat 0, but instead it's treated as spell 1
+ spellInfo->EffectBasePoints[0] = 52391; // Ride Vehicle (forces seat 0)
+ break;
case 19970: // Entangling Roots (Rank 6) -- Nature's Grasp Proc
case 19971: // Entangling Roots (Rank 5) -- Nature's Grasp Proc
case 19972: // Entangling Roots (Rank 4) -- Nature's Grasp Proc
diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h
index f643ae60287..9354c14f51c 100755
--- a/src/server/game/World/World.h
+++ b/src/server/game/World/World.h
@@ -634,7 +634,8 @@ class World
void SendServerMessage(ServerMessageType type, const char *text = "", Player* player = NULL);
/// Are we in the middle of a shutdown?
- bool IsShutdowning() const { return m_ShutdownTimer > 0; }
+ bool IsShuttingDown() const { return m_ShutdownTimer > 0; }
+ uint32 GetShutDownTimeLeft() const { return m_ShutdownTimer; }
void ShutdownServ(uint32 time, uint32 options, uint8 exitcode);
void ShutdownCancel();
void ShutdownMsg(bool show = false, Player* player = NULL);
diff --git a/src/server/scripts/Commands/cs_modify.cpp b/src/server/scripts/Commands/cs_modify.cpp
index 28bc17a7450..c32abb9537b 100644
--- a/src/server/scripts/Commands/cs_modify.cpp
+++ b/src/server/scripts/Commands/cs_modify.cpp
@@ -1129,7 +1129,12 @@ public:
uint16 drunkMod = drunklevel * 0xFFFF / 100;
- handler->GetSession()->GetPlayer()->SetDrunkValue(drunkMod);
+ Player* target = handler->getSelectedPlayer();
+ if (!target)
+ target = handler->GetSession()->GetPlayer();
+
+ if (target)
+ target->SetDrunkValue(drunkMod);
return true;
}
diff --git a/src/server/scripts/Commands/cs_npc.cpp b/src/server/scripts/Commands/cs_npc.cpp
index b9ac21cc040..a5aa2a516f3 100644
--- a/src/server/scripts/Commands/cs_npc.cpp
+++ b/src/server/scripts/Commands/cs_npc.cpp
@@ -552,15 +552,13 @@ public:
handler->PSendSysMessage(LANG_NPCINFO_PHASEMASK, target->GetPhaseMask());
handler->PSendSysMessage(LANG_NPCINFO_ARMOR, target->GetArmor());
handler->PSendSysMessage(LANG_NPCINFO_POSITION, float(target->GetPositionX()), float(target->GetPositionY()), float(target->GetPositionZ()));
+ handler->PSendSysMessage(LANG_NPCINFO_AIINFO, target->GetAIName().c_str(), target->GetScriptName().c_str());
- if ((npcflags & UNIT_NPC_FLAG_VENDOR))
- {
+ if (npcflags & UNIT_NPC_FLAG_VENDOR)
handler->SendSysMessage(LANG_NPCINFO_VENDOR);
- }
- if ((npcflags & UNIT_NPC_FLAG_TRAINER))
- {
+
+ if (npcflags & UNIT_NPC_FLAG_TRAINER)
handler->SendSysMessage(LANG_NPCINFO_TRAINER);
- }
return true;
}
diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter2.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter2.cpp
index ebd30aa2f5d..8179c9fccaa 100644
--- a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter2.cpp
+++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter2.cpp
@@ -248,7 +248,7 @@ public:
me->Mount(MODEL_DEATH_KNIGHT_MOUNT);
break;
case 10:
- me->Unmount();
+ me->Dismount();
break;
}
}
@@ -378,7 +378,7 @@ public:
void EnterCombat(Unit* /*who*/)
{
DoScriptText(SAY_TREE2, me);
- me->Unmount();
+ me->Dismount();
uiStage = 0;
}
diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp
index 18316d67cd4..3ee71ce3609 100644
--- a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp
+++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp
@@ -526,13 +526,13 @@ public:
NPCChangeTarget(uiOrbazGUID);
NPCChangeTarget(uiThassarianGUID);
- me->Unmount();
+ me->Dismount();
me->CastSpell(me, SPELL_THE_MIGHT_OF_MOGRAINE, true); // need to fix, on player only
if (Creature* temp = Unit::GetCreature(*me, uiKoltiraGUID))
- temp->Unmount();
+ temp->Dismount();
if (Creature* temp = Unit::GetCreature(*me, uiThassarianGUID))
- temp->Unmount();
+ temp->Dismount();
bIsBattle = true;
break;
diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp
index f45c943b0f1..7dc357f692a 100644
--- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp
+++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp
@@ -149,7 +149,7 @@ class boss_mandokir : public CreatureScript
if (!CombatStart)
{
//At combat Start Mandokir is mounted so we must unmount it first
- me->Unmount();
+ me->Dismount();
//And summon his raptor
me->SummonCreature(14988, me->getVictim()->GetPositionX(), me->getVictim()->GetPositionY(), me->getVictim()->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 35000);
diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_mal_ganis.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_mal_ganis.cpp
index 1a43472365a..798ea3925dc 100644
--- a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_mal_ganis.cpp
+++ b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_mal_ganis.cpp
@@ -34,7 +34,8 @@ enum Spells
H_SPELL_MIND_BLAST = 58850,
SPELL_SLEEP = 52721, //Puts an enemy to sleep for up to 10 sec. Any damage caused will awaken the target.
H_SPELL_SLEEP = 58849,
- SPELL_VAMPIRIC_TOUCH = 52723 //Heals the caster for half the damage dealt by a melee attack.
+ SPELL_VAMPIRIC_TOUCH = 52723, //Heals the caster for half the damage dealt by a melee attack.
+ SPELL_KILL_CREDIT = 58630 // Non-existing spell as encounter credit, created in spell_dbc
};
enum Yells
@@ -237,9 +238,8 @@ public:
{
instance->SetData(DATA_MAL_GANIS_EVENT, DONE);
- // give achievement credit to players. criteria use spell 58630 which doesn't exist.
- if (instance)
- instance->DoUpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, 58630);
+ // give achievement credit and LFG rewards to players. criteria use spell 58630 which doesn't exist, but it was created in spell_dbc
+ DoCast(me, SPELL_KILL_CREDIT);
}
}
diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.cpp
index 82f16dd7784..7cbb1b91755 100644
--- a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.cpp
+++ b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.cpp
@@ -582,7 +582,7 @@ public:
{
Unit* pJaina = GetClosestCreatureWithEntry(me, NPC_JAINA, 50.0f);
if (!pJaina)
- pJaina = pJaina = me->SummonCreature(NPC_JAINA, 1895.48f, 1292.66f, 143.706f, 0.023475f, TEMPSUMMON_DEAD_DESPAWN, 180000);
+ pJaina = me->SummonCreature(NPC_JAINA, 1895.48f, 1292.66f, 143.706f, 0.023475f, TEMPSUMMON_DEAD_DESPAWN, 180000);
if (pJaina)
uiJainaGUID = pJaina->GetGUID();
bStepping = false;
diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/old_hillsbrad.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/old_hillsbrad.cpp
index 1f0342b3804..65ae3287381 100644
--- a/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/old_hillsbrad.cpp
+++ b/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/old_hillsbrad.cpp
@@ -498,7 +498,7 @@ public:
}
void DoUnmount()
{
- me->Unmount();
+ me->Dismount();
me->SetSpeed(MOVE_RUN, SPEED_RUN);
}
void EnterCombat(Unit* /*who*/)
diff --git a/src/server/scripts/Kalimdor/durotar.cpp b/src/server/scripts/Kalimdor/durotar.cpp
index 1f64353901c..d6d2d633890 100644
--- a/src/server/scripts/Kalimdor/durotar.cpp
+++ b/src/server/scripts/Kalimdor/durotar.cpp
@@ -400,7 +400,7 @@ class npc_troll_volunteer : public CreatureScript
DoCast(me, SPELL_TURNIN);
DoCast(me, SPELL_QUEST_CREDIT);
me->RemoveAurasDueToSpell(SPELL_MOUNTING_CHECK);
- me->Unmount();
+ me->Dismount();
Talk(SAY_VOLUNTEER_END);
me->GetMotionMaster()->MovePoint(POINT_URUZIN, caster->GetPositionX(), caster->GetPositionY(), caster->GetPositionZ());
}
@@ -447,7 +447,7 @@ class spell_mount_check : public SpellScriptLoader
target->Mount(mountid);
}
else if (!owner->IsMounted() && target->IsMounted())
- target->Unmount();
+ target->Dismount();
target->SetSpeed(MOVE_RUN, owner->GetSpeedRate(MOVE_RUN));
target->SetSpeed(MOVE_WALK, owner->GetSpeedRate(MOVE_WALK));
diff --git a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_anubarak.cpp b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_anubarak.cpp
index 545dc79453d..e0892ffb009 100644
--- a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_anubarak.cpp
+++ b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_anubarak.cpp
@@ -91,49 +91,50 @@ public:
struct boss_anub_arakAI : public ScriptedAI
{
- boss_anub_arakAI(Creature* c) : ScriptedAI(c), lSummons(me)
+ boss_anub_arakAI(Creature* creature) : ScriptedAI(creature), Summons(me)
{
- instance = c->GetInstanceScript();
+ instance = creature->GetInstanceScript();
}
InstanceScript* instance;
- bool bChanneling;
- bool bGuardianSummoned;
- bool bVenomancerSummoned;
- bool bDatterSummoned;
- uint8 uiPhase;
- uint32 uiUndergroundPhase;
- uint32 uiCarrionBeetlesTimer;
- uint32 uiLeechingSwarmTimer;
- uint32 uiPoundTimer;
- uint32 uiSubmergeTimer;
- uint32 uiUndergroundTimer;
- uint32 uiVenomancerTimer;
- uint32 uiDatterTimer;
-
- uint32 uiImpaleTimer;
- uint32 uiImpalePhase;
- uint64 uiImpaleTarget;
-
- SummonList lSummons;
+ bool Channeling;
+ bool GuardianSummoned;
+ bool VenomancerSummoned;
+ bool DatterSummoned;
+ uint8 Phase;
+ uint32 UndergroundPhase;
+ uint32 CarrionBeetlesTimer;
+ uint32 LeechingSwarmTimer;
+ uint32 PoundTimer;
+ uint32 SubmergeTimer;
+ uint32 UndergroundTimer;
+ uint32 VenomancerTimer;
+ uint32 DatterTimer;
+ uint32 DelayTimer;
+
+ uint32 ImpaleTimer;
+ uint32 ImpalePhase;
+ uint64 ImpaleTarget;
+
+ SummonList Summons;
void Reset()
{
- uiCarrionBeetlesTimer = 8*IN_MILLISECONDS;
- uiLeechingSwarmTimer = 20*IN_MILLISECONDS;
- uiImpaleTimer = 9*IN_MILLISECONDS;
- uiPoundTimer = 15*IN_MILLISECONDS;
+ CarrionBeetlesTimer = 8*IN_MILLISECONDS;
+ LeechingSwarmTimer = 20*IN_MILLISECONDS;
+ ImpaleTimer = 9*IN_MILLISECONDS;
+ PoundTimer = 15*IN_MILLISECONDS;
- uiPhase = PHASE_MELEE;
- uiUndergroundPhase = 0;
- bChanneling = false;
- uiImpalePhase = IMPALE_PHASE_TARGET;
+ Phase = PHASE_MELEE;
+ UndergroundPhase = 0;
+ Channeling = false;
+ ImpalePhase = IMPALE_PHASE_TARGET;
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE);
me->RemoveAura(SPELL_SUBMERGE);
- lSummons.DespawnAll();
+ Summons.DespawnAll();
if (instance)
{
@@ -147,13 +148,13 @@ public:
Position targetPos;
target->GetPosition(&targetPos);
- if (TempSummon* pImpaleTarget = me->SummonCreature(CREATURE_IMPALE_TARGET, targetPos, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 6*IN_MILLISECONDS))
+ if (TempSummon* impaleTarget = me->SummonCreature(CREATURE_IMPALE_TARGET, targetPos, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 6*IN_MILLISECONDS))
{
- uiImpaleTarget = pImpaleTarget->GetGUID();
- pImpaleTarget->SetReactState(REACT_PASSIVE);
- pImpaleTarget->SetDisplayId(DISPLAY_INVISIBLE);
- pImpaleTarget->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE|UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE);
- return pImpaleTarget;
+ ImpaleTarget = impaleTarget->GetGUID();
+ impaleTarget->SetReactState(REACT_PASSIVE);
+ impaleTarget->SetDisplayId(DISPLAY_INVISIBLE);
+ impaleTarget->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE|UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE);
+ return impaleTarget;
}
return NULL;
@@ -162,11 +163,15 @@ public:
void EnterCombat(Unit* /*who*/)
{
DoScriptText(SAY_AGGRO, me);
+ DelayTimer = 0;
if (instance)
- {
- instance->SetData(DATA_ANUBARAK_EVENT, IN_PROGRESS);
instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
- }
+ }
+
+ void DelayEventStart()
+ {
+ if (instance)
+ instance->SetData(DATA_ANUBARAK_EVENT, IN_PROGRESS);
}
void UpdateAI(const uint32 diff)
@@ -174,41 +179,45 @@ public:
if (!UpdateVictim())
return;
- switch (uiPhase)
+ if (DelayTimer && DelayTimer > 5000)
+ DelayEventStart();
+ else DelayTimer+=diff;
+
+ switch (Phase)
{
case PHASE_UNDERGROUND:
- if (uiImpaleTimer <= diff)
+ if (ImpaleTimer <= diff)
{
- switch (uiImpalePhase)
+ switch (ImpalePhase)
{
case IMPALE_PHASE_TARGET:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
{
- if (Creature* pImpaleTarget = DoSummonImpaleTarget(target))
- pImpaleTarget->CastSpell(pImpaleTarget, SPELL_IMPALE_SHAKEGROUND, true);
- uiImpaleTimer = 3*IN_MILLISECONDS;
- uiImpalePhase = IMPALE_PHASE_ATTACK;
+ if (Creature* impaleTarget = DoSummonImpaleTarget(target))
+ impaleTarget->CastSpell(impaleTarget, SPELL_IMPALE_SHAKEGROUND, true);
+ ImpaleTimer = 3*IN_MILLISECONDS;
+ ImpalePhase = IMPALE_PHASE_ATTACK;
}
break;
case IMPALE_PHASE_ATTACK:
- if (Creature* pImpaleTarget = Unit::GetCreature(*me, uiImpaleTarget))
+ if (Creature* impaleTarget = Unit::GetCreature(*me, ImpaleTarget))
{
- pImpaleTarget->CastSpell(pImpaleTarget, SPELL_IMPALE_SPIKE, false);
- pImpaleTarget->RemoveAurasDueToSpell(SPELL_IMPALE_SHAKEGROUND);
+ impaleTarget->CastSpell(impaleTarget, SPELL_IMPALE_SPIKE, false);
+ impaleTarget->RemoveAurasDueToSpell(SPELL_IMPALE_SHAKEGROUND);
}
- uiImpalePhase = IMPALE_PHASE_DMG;
- uiImpaleTimer = 1*IN_MILLISECONDS;
+ ImpalePhase = IMPALE_PHASE_DMG;
+ ImpaleTimer = 1*IN_MILLISECONDS;
break;
case IMPALE_PHASE_DMG:
- if (Creature* pImpaleTarget = Unit::GetCreature(*me, uiImpaleTarget))
- me->CastSpell(pImpaleTarget, DUNGEON_MODE(SPELL_IMPALE_DMG, SPELL_IMPALE_DMG_H), true);
- uiImpalePhase = IMPALE_PHASE_TARGET;
- uiImpaleTimer = 9*IN_MILLISECONDS;
+ if (Creature* impaleTarget = Unit::GetCreature(*me, ImpaleTarget))
+ me->CastSpell(impaleTarget, DUNGEON_MODE(SPELL_IMPALE_DMG, SPELL_IMPALE_DMG_H), true);
+ ImpalePhase = IMPALE_PHASE_TARGET;
+ ImpaleTimer = 9*IN_MILLISECONDS;
break;
}
- } else uiImpaleTimer -= diff;
+ } else ImpaleTimer -= diff;
- if (!bGuardianSummoned)
+ if (!GuardianSummoned)
{
for (uint8 i = 0; i < 2; ++i)
{
@@ -218,14 +227,14 @@ public:
DoZoneInCombat(Guardian);
}
}
- bGuardianSummoned = true;
+ GuardianSummoned = true;
}
- if (!bVenomancerSummoned)
+ if (!VenomancerSummoned)
{
- if (uiVenomancerTimer <= diff)
+ if (VenomancerTimer <= diff)
{
- if (uiUndergroundPhase > 1)
+ if (UndergroundPhase > 1)
{
for (uint8 i = 0; i < 2; ++i)
{
@@ -235,16 +244,16 @@ public:
DoZoneInCombat(Venomancer);
}
}
- bVenomancerSummoned = true;
+ VenomancerSummoned = true;
}
- } else uiVenomancerTimer -= diff;
+ } else VenomancerTimer -= diff;
}
- if (!bDatterSummoned)
+ if (!DatterSummoned)
{
- if (uiDatterTimer <= diff)
+ if (DatterTimer <= diff)
{
- if (uiUndergroundPhase > 2)
+ if (UndergroundPhase > 2)
{
for (uint8 i = 0; i < 2; ++i)
{
@@ -254,71 +263,74 @@ public:
DoZoneInCombat(Datter);
}
}
- bDatterSummoned = true;
+ DatterSummoned = true;
}
- } else uiDatterTimer -= diff;
+ } else DatterTimer -= diff;
+
+ if(me->HasAura(SPELL_LEECHING_SWARM))
+ me->RemoveAurasDueToSpell(SPELL_LEECHING_SWARM);
}
- if (uiUndergroundTimer <= diff)
+ if (UndergroundTimer <= diff)
{
me->RemoveAura(SPELL_SUBMERGE);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE);
- uiPhase = PHASE_MELEE;
- } else uiUndergroundTimer -= diff;
+ Phase = PHASE_MELEE;
+ } else UndergroundTimer -= diff;
break;
case PHASE_MELEE:
- if (((uiUndergroundPhase == 0 && HealthBelowPct(75))
- || (uiUndergroundPhase == 1 && HealthBelowPct(50))
- || (uiUndergroundPhase == 2 && HealthBelowPct(25)))
+ if (((UndergroundPhase == 0 && HealthBelowPct(75))
+ || (UndergroundPhase == 1 && HealthBelowPct(50))
+ || (UndergroundPhase == 2 && HealthBelowPct(25)))
&& !me->HasUnitState(UNIT_STAT_CASTING))
{
- bGuardianSummoned = false;
- bVenomancerSummoned = false;
- bDatterSummoned = false;
+ GuardianSummoned = false;
+ VenomancerSummoned = false;
+ DatterSummoned = false;
- uiUndergroundTimer = 40*IN_MILLISECONDS;
- uiVenomancerTimer = 25*IN_MILLISECONDS;
- uiDatterTimer = 32*IN_MILLISECONDS;
+ UndergroundTimer = 40*IN_MILLISECONDS;
+ VenomancerTimer = 25*IN_MILLISECONDS;
+ DatterTimer = 32*IN_MILLISECONDS;
- uiImpalePhase = 0;
- uiImpaleTimer = 9*IN_MILLISECONDS;
+ ImpalePhase = 0;
+ ImpaleTimer = 9*IN_MILLISECONDS;
DoCast(me, SPELL_SUBMERGE, false);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE);
- uiPhase = PHASE_UNDERGROUND;
- ++uiUndergroundPhase;
+ Phase = PHASE_UNDERGROUND;
+ ++UndergroundPhase;
}
- if (bChanneling == true)
+ if (Channeling == true)
{
for (uint8 i = 0; i < 8; ++i)
DoCast(me->getVictim(), SPELL_SUMMON_CARRION_BEETLES, true);
- bChanneling = false;
+ Channeling = false;
}
- else if (uiCarrionBeetlesTimer <= diff)
+ else if (CarrionBeetlesTimer <= diff)
{
- bChanneling = true;
+ Channeling = true;
DoCastVictim(SPELL_CARRION_BEETLES);
- uiCarrionBeetlesTimer = 25*IN_MILLISECONDS;
- } else uiCarrionBeetlesTimer -= diff;
+ CarrionBeetlesTimer = 25*IN_MILLISECONDS;
+ } else CarrionBeetlesTimer -= diff;
- if (uiLeechingSwarmTimer <= diff)
+ if (LeechingSwarmTimer <= diff)
{
DoCast(me, SPELL_LEECHING_SWARM, true);
- uiLeechingSwarmTimer = 19*IN_MILLISECONDS;
- } else uiLeechingSwarmTimer -= diff;
+ LeechingSwarmTimer = 19*IN_MILLISECONDS;
+ } else LeechingSwarmTimer -= diff;
- if (uiPoundTimer <= diff)
+ if (PoundTimer <= diff)
{
if (Unit* target = me->getVictim())
{
if (Creature* pImpaleTarget = DoSummonImpaleTarget(target))
me->CastSpell(pImpaleTarget, DUNGEON_MODE(SPELL_POUND, SPELL_POUND_H), false);
}
- uiPoundTimer = 16500;
- } else uiPoundTimer -= diff;
+ PoundTimer = 16500;
+ } else PoundTimer -= diff;
DoMeleeAttackIfReady();
break;
@@ -328,7 +340,7 @@ public:
void JustDied(Unit* /*killer*/)
{
DoScriptText(SAY_DEATH, me);
- lSummons.DespawnAll();
+ Summons.DespawnAll();
if (instance)
instance->SetData(DATA_ANUBARAK_EVENT, DONE);
}
@@ -342,7 +354,7 @@ public:
void JustSummoned(Creature* summon)
{
- lSummons.Summon(summon);
+ Summons.Summon(summon);
}
};
diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_black_knight.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_black_knight.cpp
index fd84c1eec8a..f73e9779248 100644
--- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_black_knight.cpp
+++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_black_knight.cpp
@@ -54,8 +54,10 @@ enum eSpells
SPELL_BLACK_KNIGHT_RES = 67693,
- SPELL_LEAP = 67749,
- SPELL_LEAP_H = 67880
+ SPELL_LEAP = 67749,
+ SPELL_LEAP_H = 67880,
+
+ SPELL_KILL_CREDIT = 68663
};
enum eModels
@@ -288,6 +290,8 @@ public:
void JustDied(Unit* /*killer*/)
{
+ DoCast(me, SPELL_KILL_CREDIT);
+
if (instance)
instance->SetData(BOSS_BLACK_KNIGHT, DONE);
}
diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_grand_champions.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_grand_champions.cpp
index 2fbe381fed5..2f6a01e73d7 100644
--- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_grand_champions.cpp
+++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_grand_champions.cpp
@@ -839,7 +839,8 @@ public:
if (target && me->IsInRange(target, 5.0f, 30.0f, false))
{
DoCast(target, SPELL_MULTI_SHOT);
- } else
+ }
+ else
{
Map::PlayerList const& players = me->GetMap()->GetPlayers();
if (me->GetMap()->IsDungeon() && !players.isEmpty())
@@ -849,7 +850,7 @@ public:
Player* player = itr->getSource();
if (player && !player->isGameMaster() && me->IsInRange(player, 5.0f, 30.0f, false))
{
- DoCast(target, SPELL_MULTI_SHOT);
+ DoCast(player, SPELL_MULTI_SHOT);
break;
}
}
diff --git a/src/server/scripts/Northrend/DraktharonKeep/boss_tharon_ja.cpp b/src/server/scripts/Northrend/DraktharonKeep/boss_tharon_ja.cpp
index e552341fd1e..d877bbd0842 100644
--- a/src/server/scripts/Northrend/DraktharonKeep/boss_tharon_ja.cpp
+++ b/src/server/scripts/Northrend/DraktharonKeep/boss_tharon_ja.cpp
@@ -237,7 +237,8 @@ public:
for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
if (Player* player = i->getSource())
player->DeMorph();
- instance->DoUpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2, SPELL_ACHIEVEMENT_CHECK);
+
+ DoCast(me, SPELL_ACHIEVEMENT_CHECK);
instance->SetData(DATA_THARON_JA_EVENT, DONE);
}
diff --git a/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp b/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp
index eacb800f15a..1e29ec55dc8 100644
--- a/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp
+++ b/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp
@@ -215,7 +215,6 @@ class mob_corrupted_soul_fragment : public CreatureScript
if (Creature* bronjahm = ObjectAccessor::GetCreature(*me, BronjahmGUID))
me->CastSpell(bronjahm, SPELL_CONSUME_SOUL, true);
- summ->GetMotionMaster()->MoveIdle();
summ->UnSummon();
}
}
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp
index 29c3276467b..25610341a2f 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp
@@ -341,7 +341,7 @@ class boss_sindragosa : public CreatureScript
{
if (uint32 spellId = sSpellMgr->GetSpellIdForDifficulty(_isThirdPhase ? SPELL_FROST_BREATH_P2 : SPELL_FROST_BREATH_P1, me))
{
- if (player->GetQuestStatus(QUEST_FROST_INFUSION) != QUEST_STATUS_REWARDED && spellId == spell->Id)
+ if (player->GetQuestStatus(QUEST_FROST_INFUSION) == QUEST_STATUS_INCOMPLETE && spellId == spell->Id)
{
if (Item* shadowsEdge = player->GetWeaponForAttack(BASE_ATTACK, true))
{
diff --git a/src/server/scripts/Northrend/Nexus/Oculus/boss_urom.cpp b/src/server/scripts/Northrend/Nexus/Oculus/boss_urom.cpp
index 16c258af756..e63d50b0133 100644
--- a/src/server/scripts/Northrend/Nexus/Oculus/boss_urom.cpp
+++ b/src/server/scripts/Northrend/Nexus/Oculus/boss_urom.cpp
@@ -289,6 +289,7 @@ public:
void JustDied(Unit* /*killer*/)
{
_JustDied();
+ DoCast(me, SPELL_DEATH_SPELL, true); // we cast the spell as triggered or the summon effect does not occur
}
void LeaveCombat()
diff --git a/src/server/scripts/Northrend/Nexus/Oculus/boss_varos.cpp b/src/server/scripts/Northrend/Nexus/Oculus/boss_varos.cpp
index f3384b7ec15..4dcd2618895 100644
--- a/src/server/scripts/Northrend/Nexus/Oculus/boss_varos.cpp
+++ b/src/server/scripts/Northrend/Nexus/Oculus/boss_varos.cpp
@@ -144,8 +144,8 @@ public:
void JustDied(Unit* /*killer*/)
{
_JustDied();
-
Talk(SAY_DEATH);
+ DoCast(me, SPELL_DEATH_SPELL, true); // we cast the spell as triggered or the summon effect does not occur
}
private:
bool firstCoreEnergize;
diff --git a/src/server/scripts/Northrend/Nexus/Oculus/oculus.cpp b/src/server/scripts/Northrend/Nexus/Oculus/oculus.cpp
index f8839aa0028..b9799103214 100644
--- a/src/server/scripts/Northrend/Nexus/Oculus/oculus.cpp
+++ b/src/server/scripts/Northrend/Nexus/Oculus/oculus.cpp
@@ -50,6 +50,12 @@ enum Drakes
NPC_ETERNOS = 27659
};
+enum Says
+{
+ SAY_VAROS = 0,
+ SAY_UROM = 1
+};
+
class npc_oculus_drake : public CreatureScript
{
public:
@@ -174,7 +180,38 @@ public:
};
+class npc_image_belgaristrasz : public CreatureScript
+{
+public:
+ npc_image_belgaristrasz() : CreatureScript("npc_image_belgaristrasz") { }
+
+ struct npc_image_belgaristraszAI : public ScriptedAI
+ {
+ npc_image_belgaristraszAI(Creature* creature) : ScriptedAI(creature) {}
+
+ void IsSummonedBy(Unit* summoner)
+ {
+ if (summoner->GetEntry() == NPC_VAROS)
+ {
+ Talk(SAY_VAROS);
+ me->DespawnOrUnsummon(60000);
+ }
+ if (summoner->GetEntry() == NPC_UROM)
+ {
+ Talk(SAY_UROM);
+ me->DespawnOrUnsummon(60000);
+ }
+ }
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return new npc_image_belgaristraszAI(creature);
+ }
+};
+
void AddSC_oculus()
{
new npc_oculus_drake();
+ new npc_image_belgaristrasz();
}
diff --git a/src/server/scripts/Northrend/Nexus/Oculus/oculus.h b/src/server/scripts/Northrend/Nexus/Oculus/oculus.h
index e04f2c8aab9..dab2821b5e5 100644
--- a/src/server/scripts/Northrend/Nexus/Oculus/oculus.h
+++ b/src/server/scripts/Northrend/Nexus/Oculus/oculus.h
@@ -71,6 +71,7 @@ enum OculusWorldStates
enum OculusSpells
{
- SPELL_CENTRIFUGE_SHIELD = 50053
+ SPELL_CENTRIFUGE_SHIELD = 50053,
+ SPELL_DEATH_SPELL = 50415
};
#endif
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp
index e7d8b070e53..13c174a9607 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp
@@ -526,7 +526,7 @@ class boss_freya : public CreatureScript
{
uint8 n = 0;
- // Handling recieved data
+ // Handling received data
for (uint8 i = 0; i < 5; ++i) // We have created "instances" for keeping informations about last 6 death lashers - needed because of respawning
{
deforestation[i][0] = deforestation[(i + 1)][0]; // Time
@@ -590,7 +590,7 @@ class boss_freya : public CreatureScript
waveCount++;
}
- void JustDied(Unit* who)
+ void JustDied(Unit* /*who*/)
{
//! Freya's chest is dynamically spawned on death by different spells.
const uint32 summonSpell[2][4] =
diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_ingvar_the_plunderer.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_ingvar_the_plunderer.cpp
index dc2d34326a7..3712bd748a5 100644
--- a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_ingvar_the_plunderer.cpp
+++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_ingvar_the_plunderer.cpp
@@ -173,7 +173,11 @@ public:
DoScriptText(YELL_DEAD_2, me);
if (instance)
+ {
+ // Ingvar has MOB_INGVAR_UNDEAD id in this moment, so we have to update encounter state for his original id
+ instance->UpdateEncounterState(ENCOUNTER_CREDIT_KILL_CREATURE, MOB_INGVAR_HUMAN, me);
instance->SetData(DATA_INGVAR_EVENT, DONE);
+ }
}
void KilledUnit(Unit* /*victim*/)
diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp
index 7b459e7410d..f31271b825e 100644
--- a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp
+++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp
@@ -218,7 +218,7 @@ public:
void JustReachedHome()
{
me->SetFlying(false);
- me->Unmount();
+ me->Dismount();
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE);
if (Unit::GetCreature((*me), m_uiGraufGUID) == NULL)
me->SummonCreature(CREATURE_GRAUF, Location[0].GetPositionX(), Location[0].GetPositionY(), Location[0].GetPositionZ(), 3.0f);
@@ -285,7 +285,7 @@ public:
{
Phase = SKADI;
me->SetFlying(false);
- me->Unmount();
+ me->Dismount();
if (Creature* pGrauf = me->SummonCreature(CREATURE_GRAUF, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 3*IN_MILLISECONDS))
{
pGrauf->GetMotionMaster()->MoveFall(0);
diff --git a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp
index 4f837870612..5965c352975 100644
--- a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp
+++ b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp
@@ -303,9 +303,7 @@ class boss_warchief_kargath_bladefist : public CreatureScript
if (resetcheck_timer <= diff)
{
- uint32 tempx, tempy;
- tempx = uint32(me->GetPositionX());
- tempy = uint32(me->GetPositionY());
+ uint32 tempx = uint32(me->GetPositionX());
if (tempx > 255 || tempx < 205)
{
EnterEvadeMode();
diff --git a/src/server/scripts/Outland/nagrand.cpp b/src/server/scripts/Outland/nagrand.cpp
index c556253ecf1..bae3aa65b98 100644
--- a/src/server/scripts/Outland/nagrand.cpp
+++ b/src/server/scripts/Outland/nagrand.cpp
@@ -573,7 +573,7 @@ public:
{
Talk(SAY_KUR_MORE);
- if (Creature* temp = me->SummonCreature(NPC_KUR_MURK_PUTRIFIER, kurenaiAmbushB[0], kurenaiAmbushB[1], kurenaiAmbushB[2], 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000))
+ if (me->SummonCreature(NPC_KUR_MURK_PUTRIFIER, kurenaiAmbushB[0], kurenaiAmbushB[1], kurenaiAmbushB[2], 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000))
Talk(SAY_KUR_MORE_TWO);
me->SummonCreature(NPC_KUR_MURK_PUTRIFIER, kurenaiAmbushB[0]-2.5f, kurenaiAmbushB[1]-2.5f, kurenaiAmbushB[2], 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000);
diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp
index 260b0c57563..298e9b6410e 100644
--- a/src/server/scripts/Spells/spell_generic.cpp
+++ b/src/server/scripts/Spells/spell_generic.cpp
@@ -26,6 +26,8 @@
#include "SpellAuraEffects.h"
#include "SkillDiscovery.h"
#include "GridNotifiers.h"
+#include "Group.h"
+#include "LFGMgr.h"
class spell_gen_absorb0_hitlimit1 : public SpellScriptLoader
{
@@ -564,6 +566,9 @@ class spell_creature_permanent_feign_death : public SpellScriptLoader
Unit* target = GetTarget();
target->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD);
target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH);
+
+ if (target->GetTypeId() == TYPEID_UNIT)
+ target->ToCreature()->SetReactState(REACT_PASSIVE);
}
void Register()
@@ -1419,6 +1424,53 @@ public:
}
};
+class spell_gen_luck_of_the_draw : public SpellScriptLoader
+{
+ public:
+ spell_gen_luck_of_the_draw() : SpellScriptLoader("spell_gen_luck_of_the_draw") { }
+
+ class spell_gen_luck_of_the_draw_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_gen_luck_of_the_draw_AuraScript);
+
+ // cheap hax to make it have update calls
+ void CalcPeriodic(AuraEffect const* /*effect*/, bool& isPeriodic, int32& amplitude)
+ {
+ isPeriodic = true;
+ amplitude = 5 * IN_MILLISECONDS;
+ }
+
+ void Update(AuraEffect* /*effect*/)
+ {
+ if (GetUnitOwner()->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ LFGDungeonEntry const* randomDungeon = sLFGDungeonStore.LookupEntry(*(sLFGMgr->GetSelectedDungeons(GetUnitOwner()->GetGUID()).begin()));
+ Group* group = GetUnitOwner()->ToPlayer()->GetGroup();
+ Map const* map = GetUnitOwner()->GetMap();
+ if (group && group->isLFGGroup())
+ if (uint32 dungeonId = sLFGMgr->GetDungeon(group->GetGUID(), true))
+ if (LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(dungeonId))
+ if (dungeon->map == map->GetId() && dungeon->difficulty == map->GetDifficulty())
+ if (randomDungeon && randomDungeon->type == LFG_TYPE_RANDOM)
+ return; // in correct dungeon
+
+ Remove(AURA_REMOVE_BY_DEFAULT);
+ }
+
+ void Register()
+ {
+ DoEffectCalcPeriodic += AuraEffectCalcPeriodicFn(spell_gen_luck_of_the_draw_AuraScript::CalcPeriodic, EFFECT_0, SPELL_AURA_MOD_DAMAGE_PERCENT_DONE);
+ OnEffectUpdatePeriodic += AuraEffectUpdatePeriodicFn(spell_gen_luck_of_the_draw_AuraScript::Update, EFFECT_0, SPELL_AURA_MOD_DAMAGE_PERCENT_DONE);
+ }
+ };
+
+ AuraScript* GetAuraScript() const
+ {
+ return new spell_gen_luck_of_the_draw_AuraScript();
+ }
+};
+
void AddSC_generic_spell_scripts()
{
new spell_gen_absorb0_hitlimit1();
@@ -1451,4 +1503,5 @@ void AddSC_generic_spell_scripts()
new spell_gen_vehicle_scaling();
new spell_gen_oracle_wolvar_reputation();
new spell_gen_damage_reduction_aura();
+ new spell_gen_luck_of_the_draw();
}
diff --git a/src/server/scripts/World/go_scripts.cpp b/src/server/scripts/World/go_scripts.cpp
index 3bb969977b6..4799b893286 100644
--- a/src/server/scripts/World/go_scripts.cpp
+++ b/src/server/scripts/World/go_scripts.cpp
@@ -16,13 +16,6 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/* ScriptData
-SDName: GO_Scripts
-SD%Complete: 100
-SDComment: Quest support: 4285, 4287, 4288(crystal pylons), 4296, 6481, 10990, 10991, 10992, Field_Repair_Bot->Teaches spell 22704. Barov_journal->Teaches spell 26089, 12843, 12982, 2936. Soulwell
-SDCategory: Game Objects
-EndScriptData */
-
/* ContentData
go_cat_figurine (the "trap" version of GO, two different exist)
go_northern_crystal_pylon
@@ -47,6 +40,16 @@ go_jotunheim_cage
go_table_theka
go_soulwell
go_bashir_crystalforge
+go_ethereal_teleport_pad
+go_soulwell
+go_dragonflayer_cage
+go_tadpole_cage
+go_black_cage
+go_amberpine_outhouse
+go_hive_pod
+go_gjalerbron_cage
+go_large_gjalerbron_cage
+go_veil_skith_cage
EndContentData */
#include "ScriptPCH.h"
@@ -922,6 +925,32 @@ public:
};
/*######
+## go_ethereal_teleport_pad
+######*/
+
+enum eEtherealTeleportPad
+{
+ NPC_IMAGE_WIND_TRADER = 20518,
+ ITEM_TELEPORTER_POWER_PACK = 28969,
+};
+
+class go_ethereal_teleport_pad : public GameObjectScript
+{
+public:
+ go_ethereal_teleport_pad() : GameObjectScript("go_ethereal_teleport_pad") { }
+
+ bool OnGossipHello(Player* player, GameObject* pGO)
+ {
+ if (!player->HasItemCount(ITEM_TELEPORTER_POWER_PACK, 1))
+ return false;
+
+ pGO->SummonCreature(NPC_IMAGE_WIND_TRADER, pGO->GetPositionX(), pGO->GetPositionY(), pGO->GetPositionZ(), pGO->GetAngle(player), TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 60000);
+
+ return true;
+ }
+};
+
+/*######
## go_soulwell
######*/
@@ -1152,6 +1181,7 @@ public:
/*######
## Quest 1126: Hive in the Tower
+## go_hive_pod
######*/
enum eHives
@@ -1251,6 +1281,42 @@ class go_large_gjalerbron_cage : public GameObjectScript
}
};
+/*########
+#### go_veil_skith_cage
+#####*/
+
+enum MissingFriends
+{
+ QUEST_MISSING_FRIENDS = 10852,
+ NPC_CAPTIVE_CHILD = 22314,
+ SAY_FREE = 0,
+};
+
+class go_veil_skith_cage : public GameObjectScript
+{
+ public:
+ go_veil_skith_cage() : GameObjectScript("go_veil_skith_cage") { }
+
+ bool OnGossipHello(Player* player, GameObject* go)
+ {
+ if (player->GetQuestStatus(QUEST_MISSING_FRIENDS) == QUEST_STATUS_INCOMPLETE)
+ {
+ std::list<Creature*> ChildrenList;
+ GetCreatureListWithEntryInGrid(ChildrenList, go, NPC_CAPTIVE_CHILD, INTERACTION_DISTANCE);
+ for (std::list<Creature*>::const_iterator itr = ChildrenList.begin(); itr != ChildrenList.end(); ++itr)
+ {
+ go->UseDoorOrButton();
+ player->KilledMonsterCredit(NPC_CAPTIVE_CHILD, (*itr)->GetGUID());
+ (*itr)->ForcedDespawn(5000);
+ (*itr)->GetMotionMaster()->MovePoint(1, go->GetPositionX()+5, go->GetPositionY(), go->GetPositionZ());
+ (*itr)->AI()->Talk(SAY_FREE);
+ (*itr)->GetMotionMaster()->Clear();
+ }
+ }
+ return false;
+ }
+};
+
void AddSC_go_scripts()
{
new go_cat_figurine;
@@ -1282,6 +1348,7 @@ void AddSC_go_scripts()
new go_jotunheim_cage;
new go_table_theka;
new go_inconspicuous_landmark;
+ new go_ethereal_teleport_pad;
new go_soulwell;
new go_tadpole_cage;
new go_dragonflayer_cage;
@@ -1291,4 +1358,5 @@ void AddSC_go_scripts()
new go_massive_seaforium_charge;
new go_gjalerbron_cage;
new go_large_gjalerbron_cage;
+ new go_veil_skith_cage;
}
diff --git a/src/server/scripts/World/npcs_special.cpp b/src/server/scripts/World/npcs_special.cpp
index a5e5b467fc7..38a56f7b64a 100644
--- a/src/server/scripts/World/npcs_special.cpp
+++ b/src/server/scripts/World/npcs_special.cpp
@@ -1623,46 +1623,44 @@ public:
## npc_winter_reveler
####*/
+enum WinterReveler
+{
+ SPELL_MISTLETOE_DEBUFF = 26218,
+ SPELL_CREATE_MISTLETOE = 26206,
+ SPELL_CREATE_HOLLY = 26207,
+ SPELL_CREATE_SNOWFLAKES = 45036,
+};
+
class npc_winter_reveler : public CreatureScript
{
-public:
- npc_winter_reveler() : CreatureScript("npc_winter_reveler") { }
+ public:
+ npc_winter_reveler() : CreatureScript("npc_winter_reveler") { }
- struct npc_winter_revelerAI : public ScriptedAI
- {
- npc_winter_revelerAI(Creature* c) : ScriptedAI(c) {}
- void ReceiveEmote(Player* player, uint32 emote)
+ struct npc_winter_revelerAI : public ScriptedAI
{
- if (!IsHolidayActive(HOLIDAY_FEAST_OF_WINTER_VEIL))
- return;
- //TODO: check auralist.
- if (player->HasAura(26218))
- return;
+ npc_winter_revelerAI(Creature* c) : ScriptedAI(c) {}
- if (emote == TEXT_EMOTE_KISS)
+ void ReceiveEmote(Player* player, uint32 emote)
{
- me->CastSpell(me, 26218, false);
- player->CastSpell(player, 26218, false);
- switch (urand(0, 2))
+ if (player->HasAura(SPELL_MISTLETOE_DEBUFF))
+ return;
+
+ if (!IsHolidayActive(HOLIDAY_FEAST_OF_WINTER_VEIL))
+ return;
+
+ if (emote == TEXT_EMOTE_KISS)
{
- case 0:
- me->CastSpell(player, 26207, false);
- break;
- case 1:
- me->CastSpell(player, 26206, false);
- break;
- case 2:
- me->CastSpell(player, 45036, false);
- break;
+ uint32 spellId = RAND<uint32>(SPELL_CREATE_MISTLETOE, SPELL_CREATE_HOLLY, SPELL_CREATE_SNOWFLAKES);
+ me->CastSpell(player, spellId, false);
+ me->CastSpell(player, SPELL_MISTLETOE_DEBUFF, false);
}
}
- }
- };
+ };
- CreatureAI* GetAI(Creature* creature) const
- {
- return new npc_winter_revelerAI(creature);
- }
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return new npc_winter_revelerAI(creature);
+ }
};
/*####
@@ -1678,8 +1676,6 @@ public:
#define C_VIPER 19921
-#define RAND 5
-
class npc_snake_trap : public CreatureScript
{
public:
@@ -1726,7 +1722,7 @@ public:
float attackRadius = me->GetAttackDistance(who);
if (me->IsWithinDistInMap(who, attackRadius) && me->IsWithinLOSInMap(who))
{
- if (!(rand() % RAND))
+ if (!(rand() % 5))
{
me->setAttackTimer(BASE_ATTACK, (rand() % 10) * 100);
SpellTimer = (rand() % 10) * 100;
@@ -2164,6 +2160,121 @@ public:
};
/*######
+# npc_fire_elemental
+######*/
+#define SPELL_FIRENOVA 12470
+#define SPELL_FIRESHIELD 13376
+#define SPELL_FIREBLAST 57984
+
+class npc_fire_elemental : public CreatureScript
+{
+public:
+ npc_fire_elemental() : CreatureScript("npc_fire_elemental") { }
+
+ struct npc_fire_elementalAI : public ScriptedAI
+ {
+ npc_fire_elementalAI(Creature* creature) : ScriptedAI(creature) {}
+
+ uint32 FireNova_Timer;
+ uint32 FireShield_Timer;
+ uint32 FireBlast_Timer;
+
+ void Reset()
+ {
+ FireNova_Timer = 5000 + rand() % 15000; // 5-20 sec cd
+ FireBlast_Timer = 5000 + rand() % 15000; // 5-20 sec cd
+ FireShield_Timer = 0;
+ me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, true);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!UpdateVictim())
+ return;
+
+ if (me->HasUnitState(UNIT_STAT_CASTING))
+ return;
+
+ if (FireShield_Timer <= diff)
+ {
+ DoCast(me->getVictim(), SPELL_FIRESHIELD);
+ FireShield_Timer = 2 * IN_MILLISECONDS;
+ }
+ else
+ FireShield_Timer -= diff;
+
+ if (FireBlast_Timer <= diff)
+ {
+ DoCast(me->getVictim(), SPELL_FIREBLAST);
+ FireBlast_Timer = 5000 + rand() % 15000; // 5-20 sec cd
+ }
+ else
+ FireBlast_Timer -= diff;
+
+ if (FireNova_Timer <= diff)
+ {
+ DoCast(me->getVictim(), SPELL_FIRENOVA);
+ FireNova_Timer = 5000 + rand() % 15000; // 5-20 sec cd
+ }
+ else
+ FireNova_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+ };
+
+ CreatureAI *GetAI(Creature* creature) const
+ {
+ return new npc_fire_elementalAI(creature);
+ }
+};
+
+/*######
+# npc_earth_elemental
+######*/
+#define SPELL_ANGEREDEARTH 36213
+
+class npc_earth_elemental : public CreatureScript
+{
+public:
+ npc_earth_elemental() : CreatureScript("npc_earth_elemental") { }
+
+ struct npc_earth_elementalAI : public ScriptedAI
+ {
+ npc_earth_elementalAI(Creature* creature) : ScriptedAI(creature) {}
+
+ uint32 AngeredEarth_Timer;
+
+ void Reset()
+ {
+ AngeredEarth_Timer = 0;
+ me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, true);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!UpdateVictim())
+ return;
+
+ if (AngeredEarth_Timer <= diff)
+ {
+ DoCast(me->getVictim(), SPELL_ANGEREDEARTH);
+ AngeredEarth_Timer = 5000 + rand() % 15000; // 5-20 sec cd
+ }
+ else
+ AngeredEarth_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+ };
+
+ CreatureAI *GetAI(Creature* creature) const
+ {
+ return new npc_earth_elementalAI(creature);
+ }
+};
+
+/*######
# npc_wormhole
######*/
@@ -2673,5 +2784,7 @@ void AddSC_npcs_special()
new npc_locksmith;
new npc_tabard_vendor;
new npc_experience;
+ new npc_fire_elemental;
+ new npc_earth_elemental;
}
diff --git a/src/server/shared/Database/DatabaseWorkerPool.h b/src/server/shared/Database/DatabaseWorkerPool.h
index adf5902a591..f1d01661210 100755
--- a/src/server/shared/Database/DatabaseWorkerPool.h
+++ b/src/server/shared/Database/DatabaseWorkerPool.h
@@ -158,6 +158,7 @@ class DatabaseWorkerPool
}
//! Enqueues a one-way SQL operation in prepared statement format that will be executed asynchronously.
+ //! Statement must be prepared with CONNECTION_ASYNC flag.
void Execute(PreparedStatement* stmt)
{
PreparedStatementTask* task = new PreparedStatementTask(stmt);
@@ -195,6 +196,7 @@ class DatabaseWorkerPool
}
//! Directly executes a one-way SQL operation in prepared statement format, that will block the calling thread until finished.
+ //! Statement must be prepared with the CONNECTION_SYNCH flag.
void DirectExecute(PreparedStatement* stmt)
{
T* t = GetFreeConnection();
@@ -203,7 +205,7 @@ class DatabaseWorkerPool
}
/**
- Syncrhonous query (with resultset) methods.
+ Synchronous query (with resultset) methods.
*/
//! Directly executes an SQL query in string format that will block the calling thread until finished.
@@ -256,6 +258,7 @@ class DatabaseWorkerPool
//! Directly executes an SQL query in prepared format that will block the calling thread until finished.
//! Returns reference counted auto pointer, no need for manual memory management in upper level code.
+ //! Statement must be prepared with CONNECTION_SYNCH flag.
PreparedQueryResult Query(PreparedStatement* stmt)
{
T* t = GetFreeConnection();
@@ -297,6 +300,7 @@ class DatabaseWorkerPool
//! Enqueues a query in prepared format that will set the value of the PreparedQueryResultFuture return object as soon as the query is executed.
//! The return value is then processed in ProcessQueryCallback methods.
+ //! Statement must be prepared with CONNECTION_ASYNC flag.
PreparedQueryResultFuture AsyncQuery(PreparedStatement* stmt)
{
PreparedQueryResultFuture res;
@@ -308,6 +312,7 @@ class DatabaseWorkerPool
//! Enqueues a vector of SQL operations (can be both adhoc and prepared) that will set the value of the QueryResultHolderFuture
//! return object as soon as the query is executed.
//! The return value is then processed in ProcessQueryCallback methods.
+ //! Any prepared statements added to this holder need to be prepared with the CONNECTION_ASYNC flag.
QueryResultHolderFuture DelayQueryHolder(SQLQueryHolder* holder)
{
QueryResultHolderFuture res;
diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.cpp b/src/server/shared/Database/Implementation/CharacterDatabase.cpp
index f93c4a70d7c..0cbf4f8f4b4 100755
--- a/src/server/shared/Database/Implementation/CharacterDatabase.cpp
+++ b/src/server/shared/Database/Implementation/CharacterDatabase.cpp
@@ -26,7 +26,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PREPARE_STATEMENT(CHAR_ADD_QUEST_POOL_SAVE, "INSERT INTO pool_quest_save (pool_id, quest_id) VALUES (?, ?)", CONNECTION_ASYNC)
PREPARE_STATEMENT(CHAR_DEL_NONEXISTENT_GUILD_BANK_ITEM, "DELETE FROM guild_bank_item WHERE guildid = ? AND TabId = ? AND SlotId = ?", CONNECTION_ASYNC)
PREPARE_STATEMENT(CHAR_DEL_EXPIRED_BANS, "UPDATE character_banned SET active = 0 WHERE unbandate <= UNIX_TIMESTAMP() AND unbandate <> bandate", CONNECTION_ASYNC)
- PREPARE_STATEMENT(CHAR_GET_GUID_BY_NAME, "SELECT guid FROM characters WHERE name = ?", CONNECTION_SYNCH);
+ PREPARE_STATEMENT(CHAR_GET_GUID_BY_NAME, "SELECT guid FROM characters WHERE name = ?", CONNECTION_BOTH);
PREPARE_STATEMENT(CHAR_GET_CHECK_NAME, "SELECT 1 FROM characters WHERE name = ?", CONNECTION_ASYNC);
PREPARE_STATEMENT(CHAR_GET_SUM_CHARS, "SELECT COUNT(guid) FROM characters WHERE account = ?", CONNECTION_ASYNC);
PREPARE_STATEMENT(CHAR_GET_CHAR_CREATE_INFO, "SELECT level, race, class FROM characters WHERE account = ? LIMIT 0, ?", CONNECTION_ASYNC);
@@ -36,6 +36,11 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PREPARE_STATEMENT(CHAR_GET_GUID_BY_NAME_FILTER, "SELECT guid, name FROM characters WHERE name LIKE CONCAT('%', ?, '%')", CONNECTION_SYNCH)
PREPARE_STATEMENT(CHAR_GET_BANINFO_LIST, "SELECT bandate, unbandate, bannedby, banreason FROM character_banned WHERE guid = ? ORDER BY unbandate", CONNECTION_SYNCH)
PREPARE_STATEMENT(CHAR_GET_BANNED_NAME, "SELECT characters.name FROM characters, character_banned WHERE character_banned.guid = ? AND character_banned.guid = characters.guid", CONNECTION_SYNCH)
+ PREPARE_STATEMENT(CHAR_GET_ENUM, "SELECT c.guid, c.name, c.race, c.class, c.gender, c.playerBytes, c.playerBytes2, c.level, c.zone, c.map, c.position_x, c.position_y, c.position_z, gm.guildid, c.playerFlags, c.at_login, cp.entry, cp.modelid, cp.level, c.equipmentCache, cb.guid FROM characters AS c LEFT JOIN character_pet AS cp ON c.guid = cp.owner AND cp.slot = ? LEFT JOIN guild_member AS gm ON c.guid = gm.guid LEFT JOIN character_banned AS cb ON c.guid = cb.guid AND cb.active = 1 WHERE c.account = ? ORDER BY c.guid", CONNECTION_ASYNC);
+ PREPARE_STATEMENT(CHAR_GET_ENUM_DECLINED_NAME, "SELECT c.guid, c.name, c.race, c.class, c.gender, c.playerBytes, c.playerBytes2, c.level, c.zone, c.map, c.position_x, c.position_y, c.position_z, gm.guildid, c.playerFlags, c.at_login, cp.entry, cp.modelid, cp.level, c.equipmentCache, cb.guid, cd.genitive FROM characters AS c LEFT JOIN character_pet AS cp ON c.guid = cp.owner AND cp.slot = ? LEFT JOIN character_declinedname AS cd ON c.guid = cd.guid LEFT JOIN guild_member AS gm ON c.guid = gm.guid LEFT JOIN character_banned AS cb ON c.guid = cb.guid AND cb.active = 1 WHERE c.account = ? ORDER BY c.guid", CONNECTION_ASYNC);
+ PREPARE_STATEMENT(CHAR_GET_PET_SLOTS, "SELECT owner, slot FROM character_pet WHERE owner = ? AND slot >= ? AND slot <= ? ORDER BY slot", CONNECTION_ASYNC);
+ PREPARE_STATEMENT(CHAR_GET_FREE_NAME, "SELECT guid, name FROM characters WHERE guid = ? AND account = ? AND (at_login & ?) = ? AND NOT EXISTS (SELECT NULL FROM characters WHERE name = ?)", CONNECTION_ASYNC);
+ PREPARE_STATEMENT(CHAR_GET_GUID_RACE_ACC_BY_NAME, "SELECT guid, race, account FROM characters WHERE name = ?", CONNECTION_ASYNC);
// Start LoginQueryHolder content
PREPARE_STATEMENT(CHAR_LOAD_PLAYER, "SELECT guid, account, name, race, class, gender, level, xp, money, playerBytes, playerBytes2, playerFlags, "
@@ -111,6 +116,8 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PREPARE_STATEMENT(CHAR_LOAD_PLAYER_NAME_CLASS, "SELECT name, class FROM characters WHERE guid = ?", CONNECTION_SYNCH);
PREPARE_STATEMENT(CHAR_LOAD_MATCH_MAKER_RATING, "SELECT matchMakerRating FROM character_arena_stats WHERE guid = ? AND slot = ?", CONNECTION_SYNCH);
PREPARE_STATEMENT(CHAR_GET_CHARACTER_COUNT, "SELECT account, COUNT(guid) FROM characters WHERE account = ? GROUP BY account", CONNECTION_ASYNC);
+ PREPARE_STATEMENT(CHAR_UPDATE_NAME, "UPDATE characters set name = ?, at_login = at_login & ~ ? WHERE guid = ?", CONNECTION_ASYNC);
+ PREPARE_STATEMENT(CHAR_DEL_DECLINED_NAME, "DELETE FROM character_declinedname WHERE guid = ?", CONNECTION_ASYNC);
// Guild handling
// 0: uint32, 1: string, 2: uint32, 3: string, 4: string, 5: uint64, 6-10: uint32, 11: uint64
diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.h b/src/server/shared/Database/Implementation/CharacterDatabase.h
index f06a17aa924..a9464aed34f 100755
--- a/src/server/shared/Database/Implementation/CharacterDatabase.h
+++ b/src/server/shared/Database/Implementation/CharacterDatabase.h
@@ -56,6 +56,11 @@ enum CharacterDatabaseStatements
CHAR_GET_GUID_BY_NAME_FILTER,
CHAR_GET_BANINFO_LIST,
CHAR_GET_BANNED_NAME,
+ CHAR_GET_ENUM,
+ CHAR_GET_ENUM_DECLINED_NAME,
+ CHAR_GET_PET_SLOTS,
+ CHAR_GET_FREE_NAME,
+ CHAR_GET_GUID_RACE_ACC_BY_NAME,
CHAR_LOAD_PLAYER,
CHAR_LOAD_PLAYER_GROUP,
CHAR_LOAD_PLAYER_BOUNDINSTANCES,
@@ -120,6 +125,8 @@ enum CharacterDatabaseStatements
CHAR_LOAD_PLAYER_NAME_CLASS,
CHAR_LOAD_MATCH_MAKER_RATING,
CHAR_GET_CHARACTER_COUNT,
+ CHAR_UPDATE_NAME,
+ CHAR_DEL_DECLINED_NAME,
CHAR_ADD_GUILD,
CHAR_DEL_GUILD,
diff --git a/src/server/shared/Database/MySQLConnection.cpp b/src/server/shared/Database/MySQLConnection.cpp
index 70a8beb3d70..9ce924127ba 100755
--- a/src/server/shared/Database/MySQLConnection.cpp
+++ b/src/server/shared/Database/MySQLConnection.cpp
@@ -527,7 +527,12 @@ bool MySQLConnection::_HandleMySQLErrno(uint32 errNo)
// Query related errors - skip query
case 1058: // "Column count doesn't match value count"
case 1062: // "Duplicate entry '%s' for key '%d'"
- case 1054: // "Unknown column '%s' in 'order clause'"
+ return false;
+
+ // Outdated table or database structure - terminate core
+ case 1054: // "Unknown column '%s' in '%s'"
+ case 1146: // "Table '%s' doesn't exist"
+ WPFatal(!errNo, "Your database structure is not up to date. Please make sure you've executed all queries in the sql/updates folders.");
return false;
default:
diff --git a/src/server/shared/Database/MySQLConnection.h b/src/server/shared/Database/MySQLConnection.h
index 03846c47ecd..2e134cfa814 100755
--- a/src/server/shared/Database/MySQLConnection.h
+++ b/src/server/shared/Database/MySQLConnection.h
@@ -33,6 +33,7 @@ enum ConnectionFlags
{
CONNECTION_ASYNC = 0x1,
CONNECTION_SYNCH = 0x2,
+ CONNECTION_BOTH = CONNECTION_ASYNC | CONNECTION_SYNCH,
};
struct MySQLConnectionInfo
diff --git a/src/server/shared/Debugging/Errors.h b/src/server/shared/Debugging/Errors.h
index cfa1452864f..921363d6dc5 100755
--- a/src/server/shared/Debugging/Errors.h
+++ b/src/server/shared/Debugging/Errors.h
@@ -22,11 +22,12 @@
#include "Common.h"
#include "Log.h"
#include <ace/Stack_Trace.h>
+#include <ace/OS_NS_unistd.h>
#define WPAssert( assertion ) { if (!(assertion)) { ACE_Stack_Trace st; sLog->outError( "\n%s:%i in %s ASSERTION FAILED:\n %s\n%s\n", __FILE__, __LINE__, __FUNCTION__, #assertion, st.c_str()); assert( #assertion &&0 ); ((void(*)())NULL)();} }
#define WPError( assertion, errmsg ) if ( ! (assertion) ) { sLog->outError( "%\n%s:%i in %s ERROR:\n %s\n", __FILE__, __LINE__, __FUNCTION__, (char *)errmsg ); assert( false ); }
#define WPWarning( assertion, errmsg ) if ( ! (assertion) ) { sLog->outError( "\n%s:%i in %s WARNING:\n %s\n", __FILE__, __LINE__, __FUNCTION__, (char *)errmsg ); }
-#define WPFatal( assertion, errmsg ) if ( ! (assertion) ) { sLog->outError( "\n%s:%i in %s FATAL ERROR:\n %s\n", __FILE__, __LINE__, __FUNCTION__, (char *)errmsg ); assert( #assertion &&0 ); abort(); }
+#define WPFatal( assertion, errmsg ) if ( ! (assertion) ) { sLog->outError( "\n%s:%i in %s FATAL ERROR:\n %s\n", __FILE__, __LINE__, __FUNCTION__, (char *)errmsg ); ACE_OS::sleep(10); assert( #assertion &&0 ); abort(); }
#define ASSERT WPAssert
#endif
diff --git a/src/server/shared/Threading/Callback.h b/src/server/shared/Threading/Callback.h
index b179b215253..6ec2f49c8ff 100755
--- a/src/server/shared/Threading/Callback.h
+++ b/src/server/shared/Threading/Callback.h
@@ -29,107 +29,178 @@ typedef ACE_Future<PreparedQueryResult> PreparedQueryResultFuture;
issued the request. <ParamType> is variable type of parameter that is used as parameter
for the callback function.
*/
-template <typename Result, typename ParamType>
+#define CALLBACK_STAGE_INVALID uint8(-1)
+
+template <typename Result, typename ParamType, bool chain = false>
class QueryCallback
{
public:
- QueryCallback() {}
+ QueryCallback() : _stage(chain ? 0 : CALLBACK_STAGE_INVALID) {}
+ //! The parameter of this function should be a resultset returned from either .AsyncQuery or .AsyncPQuery
void SetFutureResult(ACE_Future<Result> value)
{
- result = value;
+ _result = value;
}
ACE_Future<Result> GetFutureResult()
{
- return result;
+ return _result;
}
int IsReady()
{
- return result.ready();
+ return _result.ready();
}
void GetResult(Result& res)
{
- result.get(res);
+ _result.get(res);
}
void FreeResult()
{
- result.cancel();
+ _result.cancel();
}
void SetParam(ParamType value)
{
- param = value;
+ _param = value;
}
ParamType GetParam()
{
- return param;
+ return _param;
+ }
+
+ //! Resets the stage of the callback chain
+ void ResetStage()
+ {
+ if (!chain)
+ return;
+
+ _stage = 0;
+ }
+
+ //! Advances the callback chain to the next stage, so upper level code can act on its results accordingly
+ void NextStage()
+ {
+ if (!chain)
+ return;
+
+ ++_stage;
+ }
+
+ //! Returns the callback stage (or CALLBACK_STAGE_INVALID if invalid)
+ uint8 GetStage()
+ {
+ return _stage;
+ }
+
+ //! Resets all underlying variables (param, result and stage)
+ void Reset()
+ {
+ SetParam(NULL);
+ FreeResult();
+ ResetStage();
}
private:
- ACE_Future<Result> result;
- ParamType param;
+ ACE_Future<Result> _result;
+ ParamType _param;
+ uint8 _stage;
};
-template <typename Result, typename ParamType1, typename ParamType2>
+template <typename Result, typename ParamType1, typename ParamType2, bool chain = false>
class QueryCallback_2
{
public:
- QueryCallback_2() {}
+ QueryCallback_2() : _stage(chain ? 0 : CALLBACK_STAGE_INVALID) {}
+ //! The parameter of this function should be a resultset returned from either .AsyncQuery or .AsyncPQuery
void SetFutureResult(ACE_Future<Result> value)
{
- result = value;
+ _result = value;
}
ACE_Future<Result> GetFutureResult()
{
- return result;
+ return _result;
}
int IsReady()
{
- return result.ready();
+ return _result.ready();
}
void GetResult(Result& res)
{
- result.get(res);
+ _result.get(res);
}
void FreeResult()
{
- result.cancel();
+ _result.cancel();
}
void SetFirstParam(ParamType1 value)
{
- param_1 = value;
+ _param_1 = value;
}
void SetSecondParam(ParamType2 value)
{
- param_2 = value;
+ _param_2 = value;
}
ParamType1 GetFirstParam()
{
- return param_1;
+ return _param_1;
}
ParamType2 GetSecondParam()
{
- return param_2;
+ return _param_2;
+ }
+
+ //! Resets the stage of the callback chain
+ void ResetStage()
+ {
+ if (!chain)
+ return;
+
+ _stage = 0;
+ }
+
+ //! Advances the callback chain to the next stage, so upper level code can act on its results accordingly
+ void NextStage()
+ {
+ if (!chain)
+ return;
+
+ ++_stage;
+ }
+
+ //! Returns the callback stage (or CALLBACK_STAGE_INVALID if invalid)
+ uint8 GetStage()
+ {
+ return _stage;
+ }
+
+ //! Resets all underlying variables (param, result and stage)
+ void Reset()
+ {
+ SetFirstParam(NULL);
+ SetSecondParam(NULL);
+ FreeResult();
+ ResetStage();
}
private:
- ACE_Future<Result> result;
- ParamType1 param_1;
- ParamType2 param_2;
+ ACE_Future<Result> _result;
+ ParamType1 _param_1;
+ ParamType2 _param_2;
+ uint8 _stage;
};
#endif \ No newline at end of file
diff --git a/src/server/shared/Threading/LockedQueue.h b/src/server/shared/Threading/LockedQueue.h
index 92eab440684..4d2ddd33f5f 100755
--- a/src/server/shared/Threading/LockedQueue.h
+++ b/src/server/shared/Threading/LockedQueue.h
@@ -98,13 +98,16 @@ namespace ACE_Based
return true;
}
- //! Peeks at the top of the queue. Remember to unlock after use.
- T& peek()
+ //! Peeks at the top of the queue. Check if the queue is empty before calling! Remember to unlock after use if autoUnlock == false.
+ T& peek(bool autoUnlock = false)
{
lock();
T& result = _queue.front();
+ if (autoUnlock)
+ unlock();
+
return result;
}
diff --git a/src/server/worldserver/CommandLine/CliRunnable.cpp b/src/server/worldserver/CommandLine/CliRunnable.cpp
index 564f6028eca..61352521d9f 100755
--- a/src/server/worldserver/CommandLine/CliRunnable.cpp
+++ b/src/server/worldserver/CommandLine/CliRunnable.cpp
@@ -104,7 +104,7 @@ void utf8print(void* /*arg*/, const char* str)
printf(temp_buf);
#else
{
- printf(str);
+ printf("%s", str);
fflush(stdout);
}
#endif
diff --git a/src/server/worldserver/RemoteAccess/RASocket.cpp b/src/server/worldserver/RemoteAccess/RASocket.cpp
index 71d4d1df035..82238ee54bc 100755
--- a/src/server/worldserver/RemoteAccess/RASocket.cpp
+++ b/src/server/worldserver/RemoteAccess/RASocket.cpp
@@ -286,7 +286,7 @@ int RASocket::subnegotiate()
if (n >= 1024)
{
- sLog->outRemote("RASocket::subnegotiate: allocated buffer 1024 bytes was too small for negotiation packet, size: %u", n);
+ sLog->outRemote("RASocket::subnegotiate: allocated buffer 1024 bytes was too small for negotiation packet, size: %u", uint32(n));
return -1;
}
diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist
index a8c0d91b2e6..1e37f50aa63 100644
--- a/src/server/worldserver/worldserver.conf.dist
+++ b/src/server/worldserver/worldserver.conf.dist
@@ -1744,7 +1744,8 @@ Channel.RestrictedLfg = 1
#
# Channel.SilentlyGMJoin
-# Description: Silently join GM characters to channels
+# Description: Silently join GM characters to channels. If set to 1, channel kick and ban
+# commands issued by a GM will not be broadcasted.
# Default: 0 - (Disabled, Join with announcement)
# 1 - (Enabled, Join without announcement)