aboutsummaryrefslogtreecommitdiff
path: root/src/server/game
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/game')
-rwxr-xr-xsrc/server/game/AI/CoreAI/PetAI.cpp5
-rw-r--r--src/server/game/AI/SmartScripts/SmartAI.cpp4
-rw-r--r--src/server/game/AI/SmartScripts/SmartScript.cpp293
-rw-r--r--src/server/game/AI/SmartScripts/SmartScript.h3
-rwxr-xr-xsrc/server/game/Battlegrounds/Battleground.cpp1
-rwxr-xr-xsrc/server/game/Entities/Creature/Creature.cpp12
-rwxr-xr-xsrc/server/game/Entities/Creature/Creature.h3
-rwxr-xr-xsrc/server/game/Entities/GameObject/GameObject.cpp23
-rwxr-xr-xsrc/server/game/Entities/Player/Player.cpp16
-rwxr-xr-xsrc/server/game/Entities/Player/Player.h4
-rwxr-xr-xsrc/server/game/Entities/Unit/Unit.cpp22
-rwxr-xr-xsrc/server/game/Entities/Unit/Unit.h28
-rwxr-xr-xsrc/server/game/Globals/ObjectMgr.cpp4
-rwxr-xr-xsrc/server/game/Groups/Group.cpp14
-rwxr-xr-xsrc/server/game/Groups/Group.h2
-rwxr-xr-xsrc/server/game/Server/Protocol/Handlers/PetHandler.cpp7
-rwxr-xr-xsrc/server/game/Spells/Spell.cpp72
-rwxr-xr-xsrc/server/game/Spells/Spell.h3
-rwxr-xr-xsrc/server/game/Spells/SpellEffects.cpp6
19 files changed, 413 insertions, 109 deletions
diff --git a/src/server/game/AI/CoreAI/PetAI.cpp b/src/server/game/AI/CoreAI/PetAI.cpp
index ac142db923d..115f65311b9 100755
--- a/src/server/game/AI/CoreAI/PetAI.cpp
+++ b/src/server/game/AI/CoreAI/PetAI.cpp
@@ -122,7 +122,7 @@ void PetAI::UpdateAI(const uint32 diff)
return;
// Autocast (casted only in combat or persistent spells in any state)
- if (me->GetGlobalCooldown() == 0 && !me->HasUnitState(UNIT_STAT_CASTING))
+ if (!me->HasUnitState(UNIT_STAT_CASTING))
{
typedef std::vector<std::pair<Unit*, Spell*> > TargetSpellList;
TargetSpellList targetSpellStore;
@@ -137,6 +137,9 @@ void PetAI::UpdateAI(const uint32 diff)
if (!spellInfo)
continue;
+ if (me->GetCharmInfo() && me->GetCharmInfo()->GetGlobalCooldownMgr().HasGlobalCooldown(spellInfo))
+ continue;
+
// ignore some combinations of combat state and combat/noncombat spells
if (!me->getVictim())
{
diff --git a/src/server/game/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp
index 422096b3798..cc8bdc00d12 100644
--- a/src/server/game/AI/SmartScripts/SmartAI.cpp
+++ b/src/server/game/AI/SmartScripts/SmartAI.cpp
@@ -793,7 +793,7 @@ void SmartAI::SetFollow(Unit* target, float dist, float angle, uint32 credit, ui
void SmartAI::SetScript9(SmartScriptHolder &e, uint32 entry, Unit* invoker)
{
if (invoker)
- GetScript()->mLastInvoker = invoker;
+ GetScript()->mLastInvoker = invoker->GetGUID();
GetScript()->SetScript9(e, entry);
}
/*
@@ -894,7 +894,7 @@ void SmartGameObjectAI::SetData(uint32 id, uint32 value)
void SmartGameObjectAI::SetScript9(SmartScriptHolder &e, uint32 entry, Unit* invoker)
{
if (invoker)
- GetScript()->mLastInvoker = invoker;
+ GetScript()->mLastInvoker = invoker->GetGUID();
GetScript()->SetScript9(e, entry);
}
diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp
index f9371979a77..4abf17049b2 100644
--- a/src/server/game/AI/SmartScripts/SmartScript.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScript.cpp
@@ -109,7 +109,7 @@ void SmartScript::ProcessAction(SmartScriptHolder &e, Unit* unit, uint32 var0, u
e.runOnce = true;//used for repeat check
if (unit)
- mLastInvoker = unit;
+ mLastInvoker = unit->GetGUID();
if (e.link && e.link != e.event_id)
{
@@ -120,6 +120,9 @@ void SmartScript::ProcessAction(SmartScriptHolder &e, Unit* unit, uint32 var0, u
sLog->outErrorDb("SmartScript::ProcessAction: Entry %d SourceType %u, Event %u, Link Event %u not found or invalid, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.link);
}
+ if (Unit* tempInvoker = GetLastInvoker())
+ sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction: Invoker: %s (guidlow: %u)", tempInvoker->GetName(), tempInvoker->GetGUIDLow());
+
switch (e.GetActionType())
{
case SMART_ACTION_TALK:
@@ -139,9 +142,13 @@ void SmartScript::ProcessAction(SmartScriptHolder &e, Unit* unit, uint32 var0, u
}
mLastTextID = e.action.talk.textGroupID;
mTextTimer = e.action.talk.duration;
- mTextGUID = IsPlayer(mLastInvoker)? mLastInvoker->GetGUID() : NULL;//invoker, used for $vars in texts
+ mTextGUID = IsPlayer(GetLastInvoker())? GetLastInvoker()->GetGUID() : NULL;//invoker, used for $vars in texts
mUseTextTimer = true;
sCreatureTextMgr->SendChat(talker, uint8(e.action.talk.textGroupID), mTextGUID);
+
+ sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction: SMART_ACTION_TALK: talker: %s (GuidLow: %u), textGuid: %u",
+ talker->GetName(), talker->GetGUIDLow(), mTextGUID);
+
break;
}
case SMART_ACTION_SIMPLE_TALK:
@@ -152,12 +159,14 @@ void SmartScript::ProcessAction(SmartScriptHolder &e, Unit* unit, uint32 var0, u
for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); itr++)
{
if (IsCreature((*itr)))
+ sCreatureTextMgr->SendChat((*itr)->ToCreature(), uint8(e.action.talk.textGroupID), IsPlayer(GetLastInvoker())? GetLastInvoker()->GetGUID() : NULL);
+ else if (IsPlayer((*itr)))
{
- sCreatureTextMgr->SendChat((*itr)->ToCreature(), uint8(e.action.talk.textGroupID), IsPlayer(mLastInvoker)? mLastInvoker->GetGUID() : NULL);
- } else if (IsPlayer((*itr)))
- {
- sCreatureTextMgr->SendChat(me, uint8(e.action.talk.textGroupID),IsPlayer(mLastInvoker)? mLastInvoker->GetGUID() : NULL,CHAT_TYPE_END,LANG_ADDON,TEXT_RANGE_NORMAL,NULL,TEAM_OTHER,false, (*itr)->ToPlayer());
+ Unit* templastInvoker = GetLastInvoker();
+ sCreatureTextMgr->SendChat(me, uint8(e.action.talk.textGroupID),IsPlayer(templastInvoker)? templastInvoker->GetGUID() : NULL,CHAT_TYPE_END,LANG_ADDON,TEXT_RANGE_NORMAL,NULL,TEAM_OTHER,false, (*itr)->ToPlayer());
}
+ sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction:: SMART_ACTION_SIMPLE_TALK: talker: %s (GuidLow: %u), textGroupId: %u",
+ (*itr)->GetName(), (*itr)->GetGUIDLow(), uint8(e.action.talk.textGroupID));
}
}
break;
@@ -168,7 +177,11 @@ void SmartScript::ProcessAction(SmartScriptHolder &e, Unit* unit, uint32 var0, u
if (targets)
for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); itr++)
if (IsUnit((*itr)))
+ {
(*itr)->ToUnit()->HandleEmoteCommand(e.action.emote.emote);
+ sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction:: SMART_ACTION_PLAY_EMOTE: target: %s (GuidLow: %u), emote: %u",
+ (*itr)->GetName(), (*itr)->GetGUIDLow(), e.action.emote.emote);
+ }
break;
}
case SMART_ACTION_SOUND:
@@ -177,7 +190,11 @@ void SmartScript::ProcessAction(SmartScriptHolder &e, Unit* unit, uint32 var0, u
if (targets)
for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); itr++)
if (IsCreature((*itr)))
+ {
sCreatureTextMgr->SendSound((*itr)->ToCreature(), e.action.sound.sound, CHAT_TYPE_SAY, 0, TextRange(e.action.sound.range), Team(NULL), false);
+ sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction:: SMART_ACTION_SOUND: source: %s (GuidLow: %u), sound: %u, range: %u",
+ (*itr)->GetName(), (*itr)->GetGUIDLow(), e.action.sound.sound, e.action.sound.range);
+ }
break;
}
case SMART_ACTION_SET_FACTION:
@@ -190,13 +207,21 @@ void SmartScript::ProcessAction(SmartScriptHolder &e, Unit* unit, uint32 var0, u
if (IsCreature((*itr)))
{
if (e.action.faction.factionID)
+ {
(*itr)->ToCreature()->setFaction(e.action.faction.factionID);
+ sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction:: SMART_ACTION_SET_FACTION: Creature entry %u, GuidLow %u set faction to %u",
+ (*itr)->GetEntry(), (*itr)->GetGUIDLow(), e.action.faction.factionID);
+ }
else
{
if (CreatureInfo const* ci = GetCreatureTemplateStore((*itr)->ToCreature()->GetEntry()))
{
if ((*itr)->ToCreature()->getFaction() != ci->faction_A)
+ {
(*itr)->ToCreature()->setFaction(ci->faction_A);
+ sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction:: SMART_ACTION_SET_FACTION: Creature entry %u, GuidLow %u set faction to %u",
+ (*itr)->GetEntry(), (*itr)->GetGUIDLow(), ci->faction_A);
+ }
}
}
}
@@ -222,14 +247,24 @@ void SmartScript::ProcessAction(SmartScriptHolder &e, Unit* unit, uint32 var0, u
{
uint32 display_id = sObjectMgr->ChooseDisplayId(0, ci);
(*itr)->ToCreature()->SetDisplayId(display_id);
+ sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction:: SMART_ACTION_MORPH_TO_ENTRY_OR_MODEL: Creature entry %u, GuidLow %u set displayid to %u",
+ (*itr)->GetEntry(), (*itr)->GetGUIDLow(), display_id);
}
}
//if no param1, then use value from param2 (modelId)
else
+ {
(*itr)->ToCreature()->SetDisplayId(e.action.morphOrMount.model);
+ sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction:: SMART_ACTION_MORPH_TO_ENTRY_OR_MODEL: Creature entry %u, GuidLow %u set displayid to %u",
+ (*itr)->GetEntry(), (*itr)->GetGUIDLow(), e.action.morphOrMount.model);
+ }
}
else
+ {
(*itr)->ToCreature()->DeMorph();
+ sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction:: SMART_ACTION_MORPH_TO_ENTRY_OR_MODEL: Creature entry %u, GuidLow %u demorphs.",
+ (*itr)->GetEntry(), (*itr)->GetGUIDLow());
+ }
}
break;
}
@@ -240,7 +275,11 @@ void SmartScript::ProcessAction(SmartScriptHolder &e, Unit* unit, uint32 var0, u
for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); itr++)
{
if (IsPlayer((*itr)))
+ {
(*itr)->ToPlayer()->FailQuest(e.action.quest.quest);
+ sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction:: SMART_ACTION_FAIL_QUEST: Player guidLow %u fails quest %u",
+ (*itr)->GetGUIDLow(), e.action.quest.quest);
+ }
}
break;
}
@@ -252,14 +291,23 @@ void SmartScript::ProcessAction(SmartScriptHolder &e, Unit* unit, uint32 var0, u
{
if (IsPlayer((*itr)))
if (const Quest* q = sObjectMgr->GetQuestTemplate(e.action.quest.quest))
+ {
(*itr)->ToPlayer()->AddQuest(q, NULL);
+ sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction:: SMART_ACTION_ADD_QUEST: Player guidLow %u add quest %u",
+ (*itr)->GetGUIDLow(), e.action.quest.quest);
+ }
}
break;
}
case SMART_ACTION_SET_REACT_STATE:
{
- if (!me) return;
+ if (!me)
+ return;
+
me->SetReactState(ReactStates(e.action.react.state));
+
+ sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction:: SMART_ACTION_SET_REACT_STATE: Creature guidLow %u set reactstate %u",
+ me->GetGUIDLow(), e.action.react.state);
break;
}
case SMART_ACTION_RANDOM_EMOTE:
@@ -285,26 +333,43 @@ void SmartScript::ProcessAction(SmartScriptHolder &e, Unit* unit, uint32 var0, u
}
for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); itr++)
if (IsUnit((*itr)))
- (*itr)->ToUnit()->HandleEmoteCommand(temp[urand(0, count)]);
+ {
+ uint32 emote = temp[urand(0, count)];
+ (*itr)->ToUnit()->HandleEmoteCommand(emote);
+ sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction:: SMART_ACTION_RANDOM_EMOTE: Creature guidLow %u handle random emote %u",
+ (*itr)->GetGUIDLow(), emote);
+ }
break;
}
case SMART_ACTION_THREAT_ALL_PCT:
{
- if (!me) return;
+ if (!me)
+ return;
+
std::list<HostileReference*>& threatList = me->getThreatManager().getThreatList();
for (std::list<HostileReference*>::iterator i = threatList.begin(); i != threatList.end(); ++i)
if (Unit* Temp = Unit::GetUnit(*me,(*i)->getUnitGuid()))
+ {
me->getThreatManager().modifyThreatPercent(Temp, e.action.threatPCT.threatINC ? (int32)e.action.threatPCT.threatINC : -(int32)e.action.threatPCT.threatDEC);
+ sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction:: SMART_ACTION_THREAT_ALL_PCT: Creature guidLow %u modify threat for unit %u, value %i",
+ me->GetGUIDLow(), Temp->GetGUIDLow(), e.action.threatPCT.threatINC ? (int32)e.action.threatPCT.threatINC : -(int32)e.action.threatPCT.threatDEC);
+ }
break;
}
case SMART_ACTION_THREAT_SINGLE_PCT:
{
- if (!me) return;
+ if (!me)
+ return;
+
ObjectList* targets = GetTargets(e, unit);
if (!targets) return;
for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); itr++)
if (IsUnit((*itr)))
+ {
me->getThreatManager().modifyThreatPercent((*itr)->ToUnit(), e.action.threatPCT.threatINC ? (int32)e.action.threatPCT.threatINC : -(int32)e.action.threatPCT.threatDEC);
+ sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction:: SMART_ACTION_THREAT_SINGLE_PCT: Creature guidLow %u modify threat for unit %u, value %i",
+ me->GetGUIDLow(), (*itr)->GetGUIDLow(), e.action.threatPCT.threatINC ? (int32)e.action.threatPCT.threatINC : -(int32)e.action.threatPCT.threatDEC);
+ }
break;
}
case SMART_ACTION_CALL_AREAEXPLOREDOREVENTHAPPENS:
@@ -314,7 +379,11 @@ void SmartScript::ProcessAction(SmartScriptHolder &e, Unit* unit, uint32 var0, u
if (!targets) return;
for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); itr++)
if (IsPlayer((*itr)))
+ {
(*itr)->ToPlayer()->AreaExploredOrEventHappens(e.action.quest.quest);
+ sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction:: SMART_ACTION_CALL_AREAEXPLOREDOREVENTHAPPENS: Player guidLow %u credited quest %u",
+ (*itr)->GetGUIDLow(), e.action.quest.quest);
+ }
break;
}
case SMART_ACTION_SEND_CASTCREATUREORGO:
@@ -324,12 +393,18 @@ void SmartScript::ProcessAction(SmartScriptHolder &e, Unit* unit, uint32 var0, u
if (!targets) return;
for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); itr++)
if (IsPlayer((*itr)))
+ {
(*itr)->ToPlayer()->CastedCreatureOrGO(e.action.castedCreatureOrGO.creature, GetBaseObject()->GetGUID(), e.action.castedCreatureOrGO.spell);
+ sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction:: SMART_ACTION_SEND_CASTCREATUREORGO: Player guidLow %u.org Creature: %u, BaseObject GUID: "UI64FMTD" , Spell: %u",
+ e.action.castedCreatureOrGO.creature, GetBaseObject()->GetGUID(), e.action.castedCreatureOrGO.spell);
+ }
break;
}
case SMART_ACTION_CAST:
{
- if (!me) return;
+ if (!me)
+ return;
+
ObjectList* targets = GetTargets(e, unit);
if (!targets) return;
for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); itr++)
@@ -337,45 +412,61 @@ void SmartScript::ProcessAction(SmartScriptHolder &e, Unit* unit, uint32 var0, u
{
if (e.action.cast.flags & SMARTCAST_INTERRUPT_PREVIOUS)
me->InterruptNonMeleeSpells(false);
+
me->CastSpell((*itr)->ToUnit(), e.action.cast.spell,(e.action.cast.flags & SMARTCAST_TRIGGERED) ? true : false);
+ sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction:: SMART_ACTION_CAST:: Creature %u casts spell % on target %u with castflags %u",
+ me->GetGUIDLow(), (*itr)->GetGUIDLow(), e.action.cast.spell, e.action.cast.flags);
}
break;
}
case SMART_ACTION_INVOKER_CAST:
{
- if (!mLastInvoker) return;
+ Unit* tempLastInvoker = GetLastInvoker();
+ if (!tempLastInvoker)
+ return;
ObjectList* targets = GetTargets(e, unit);
if (!targets) return;
for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); itr++)
if (IsUnit((*itr)))
{
if (e.action.cast.flags & SMARTCAST_INTERRUPT_PREVIOUS)
- mLastInvoker->InterruptNonMeleeSpells(false);
- mLastInvoker->CastSpell((*itr)->ToUnit(), e.action.cast.spell,(e.action.cast.flags & SMARTCAST_TRIGGERED) ? true : false);
+ tempLastInvoker->InterruptNonMeleeSpells(false);
+
+ tempLastInvoker->CastSpell((*itr)->ToUnit(), e.action.cast.spell,(e.action.cast.flags & SMARTCAST_TRIGGERED) ? true : false);
+ sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction:: SMART_ACTION_INVOKER_CAST: Invoker %u casts spell % on target %u with castflags %u",
+ tempLastInvoker->GetGUIDLow(), (*itr)->GetGUIDLow(), e.action.cast.spell, e.action.cast.flags);
}
break;
}
case SMART_ACTION_ADD_AURA:
{
ObjectList* targets = GetTargets(e, unit);
- if (!targets) return;
+ if (!targets)
+ return;
+
for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); itr++)
if (IsUnit((*itr)))
{
(*itr)->ToUnit()->AddAura(e.action.cast.spell, (*itr)->ToUnit());
+ sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction:: SMART_ACTION_ADD_AURA: Adding aura %u to unit %u",
+ e.action.cast.spell, (*itr)->GetGUIDLow());
}
break;
}
case SMART_ACTION_ACTIVATE_GOBJECT:
{
ObjectList* targets = GetTargets(e, unit);
- if (!targets) return;
+ if (!targets)
+ return;
+
for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); itr++)
if (IsGameObject((*itr)))
{
// Activate
(*itr)->ToGameObject()->SetLootState(GO_READY);
(*itr)->ToGameObject()->UseDoorOrButton();
+ sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction:: SMART_ACTION_ACTIVATE_GOBJECT. Gameobject %u (entry: %u) activated",
+ (*itr)->GetGUIDLow(), (*itr)->GetEntry());
}
break;
}
@@ -385,7 +476,11 @@ void SmartScript::ProcessAction(SmartScriptHolder &e, Unit* unit, uint32 var0, u
if (!targets) return;
for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); itr++)
if (IsGameObject((*itr)))
+ {
(*itr)->ToGameObject()->ResetDoorOrButton();
+ sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction:: SMART_ACTION_RESET_GOBJECT. Gameobject %u (entry: %u) reset",
+ (*itr)->GetGUIDLow(), (*itr)->GetEntry());
+ }
break;
}
case SMART_ACTION_SET_EMOTE_STATE:
@@ -394,7 +489,11 @@ void SmartScript::ProcessAction(SmartScriptHolder &e, Unit* unit, uint32 var0, u
if (!targets) return;
for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); itr++)
if (IsUnit((*itr)))
+ {
(*itr)->ToUnit()->SetUInt32Value(UNIT_NPC_EMOTESTATE, e.action.emote.emote);
+ sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction:: SMART_ACTION_SET_EMOTE_STATE. Unit %u set emotestate to %u",
+ (*itr)->GetGUIDLow(), e.action.emote.emote);
+ }
break;
}
case SMART_ACTION_SET_UNIT_FLAG:
@@ -403,7 +502,11 @@ void SmartScript::ProcessAction(SmartScriptHolder &e, Unit* unit, uint32 var0, u
if (!targets) return;
for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); itr++)
if (IsUnit((*itr)))
+ {
(*itr)->ToUnit()->SetFlag(UNIT_FIELD_FLAGS, e.action.unitFlag.flag);
+ sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction:: SMART_ACTION_SET_UNIT_FLAG. Unit %u added flag %u to UNIT_FIELD_FLAGS",
+ (*itr)->GetGUIDLow(), e.action.unitFlag.flag);
+ }
break;
}
case SMART_ACTION_REMOVE_UNIT_FLAG:
@@ -412,82 +515,131 @@ void SmartScript::ProcessAction(SmartScriptHolder &e, Unit* unit, uint32 var0, u
if (!targets) return;
for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); itr++)
if (IsUnit((*itr)))
+ {
(*itr)->ToUnit()->RemoveFlag(UNIT_FIELD_FLAGS, e.action.unitFlag.flag);
+ sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction:: SMART_ACTION_REMOVE_UNIT_FLAG. Unit %u removed flag %u to UNIT_FIELD_FLAGS",
+ (*itr)->GetGUIDLow(), e.action.unitFlag.flag);
+ }
break;
}
case SMART_ACTION_AUTO_ATTACK:
{
- if (!IsSmart()) return;
+ if (!IsSmart())
+ return;
+
CAST_AI(SmartAI, me->AI())->SetAutoAttack(e.action.autoAttack.attack ? true : false);
+ sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction:: SMART_ACTION_AUTO_ATTACK: Creature: %u bool on = %u",
+ me->GetGUIDLow(), e.action.autoAttack.attack);
break;
}
case SMART_ACTION_ALLOW_COMBAT_MOVEMENT:
{
- if (!IsSmart()) return;
+ if (!IsSmart())
+ return;
+
bool move = e.action.combatMove.move ? true : false;
CAST_AI(SmartAI, me->AI())->SetCombatMove(move);
+ sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction:: SMART_ACTION_ALLOW_COMBAT_MOVEMENT: Creature %u bool on = %u",
+ me->GetGUIDLow(), e.action.combatMove.move);
break;
}
case SMART_ACTION_SET_EVENT_PHASE:
{
SetPhase(e.action.setEventPhase.phase);
+ sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction:: SMART_ACTION_SET_EVENT_PHASE: Creature %u set event phase %u",
+ me->GetGUIDLow(), e.action.setEventPhase.phase);
break;
}
case SMART_ACTION_INC_EVENT_PHASE:
{
IncPhase(e.action.incEventPhase.inc);
DecPhase(e.action.incEventPhase.dec);
+
+ sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction:: SMART_ACTION_INC_EVENT_PHASE: Creature %u inc event phase by %u, "
+ "decrease by %u", me->GetGUIDLow(), e.action.incEventPhase.inc, e.action.incEventPhase.dec);
break;
}
case SMART_ACTION_EVADE:
{
- if (me) me->AI()->EnterEvadeMode();
+ if (!me)
+ return;
+
+ me->AI()->EnterEvadeMode();
+ sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction:: SMART_ACTION_EVADE: Creature %u EnterEvadeMode", me->GetGUIDLow());
return;
}
case SMART_ACTION_FLEE_FOR_ASSIST:
{
- if (me) me->DoFleeToGetAssistance();
+ if (!me)
+ return;
+
+ me->DoFleeToGetAssistance();
+ sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction:: SMART_ACTION_FLEE_FOR_ASSIST: Creature %u DoFleeToGetAssistance", me->GetGUIDLow());
break;
}
case SMART_ACTION_CALL_GROUPEVENTHAPPENS:
{
if (IsPlayer(unit) && GetBaseObject())
+ {
unit->ToPlayer()->GroupEventHappens(e.action.quest.quest, GetBaseObject());
+ sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction: SMART_ACTION_CALL_GROUPEVENTHAPPENS: Player %u, group credit for quest %u",
+ unit->GetGUIDLow(), e.action.quest.quest);
+ }
break;
}
case SMART_ACTION_CALL_CASTEDCREATUREORGO:
{
- if (!GetBaseObject()) return;
+ if (!GetBaseObject())
+ return;
+
ObjectList* targets = GetTargets(e, unit);
- if (!targets) return;
+ if (!targets)
+ return;
+
for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); itr++)
{
if (IsPlayer((*itr)))
+ {
(*itr)->ToPlayer()->CastedCreatureOrGO(e.action.castedCreatureOrGO.creature, GetBaseObject()->GetGUID(), e.action.castedCreatureOrGO.spell);
+ sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction: SMART_ACTION_CALL_CASTEDCREATUREORGO: Player %u, target %u, spell %u",
+ (*itr)->GetGUIDLow(), e.action.castedCreatureOrGO.creature, e.action.castedCreatureOrGO.spell);
+ }
}
break;
}
case SMART_ACTION_REMOVEAURASFROMSPELL:
{
ObjectList* targets = GetTargets(e, unit);
- if (!targets) return;
+ if (!targets)
+ return;
+
for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); itr++)
{
- if(!IsUnit((*itr))) continue;
+ if (!IsUnit((*itr)))
+ continue;
+
(*itr)->ToUnit()->RemoveAurasDueToSpell(e.action.removeAura.spell);
+ sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction: SMART_ACTION_REMOVEAURASFROMSPELL: Unit %u, spell %u",
+ (*itr)->GetGUIDLow(), e.action.removeAura.spell);
}
break;
}
case SMART_ACTION_FOLLOW:
{
- if (!IsSmart()) return;
+ if (!IsSmart())
+ return;
+
ObjectList* targets = GetTargets(e, unit);
- if (!targets) return;
+ if (!targets)
+ return;
+
for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); itr++)
{
if (IsUnit((*itr)))
{
CAST_AI(SmartAI, me->AI())->SetFollow((*itr)->ToUnit(), (float)e.action.follow.dist, (float)e.action.follow.angle, e.action.follow.credit, e.action.follow.entry, e.action.follow.creditType);
+ sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction: SMART_ACTION_FOLLOW: Creature %u following target %u",
+ me->GetGUIDLow(), (*itr)->GetGUIDLow());
return;
}
}
@@ -496,12 +648,12 @@ void SmartScript::ProcessAction(SmartScriptHolder &e, Unit* unit, uint32 var0, u
case SMART_ACTION_RANDOM_PHASE:
{
uint32 phases[SMART_ACTION_PARAM_COUNT];
- phases[0] = e.action.randomEmote.emote1;
- phases[1] = e.action.randomEmote.emote2;
- phases[2] = e.action.randomEmote.emote3;
- phases[3] = e.action.randomEmote.emote4;
- phases[4] = e.action.randomEmote.emote5;
- phases[5] = e.action.randomEmote.emote6;
+ phases[0] = e.action.randomPhase.phase1;
+ phases[1] = e.action.randomPhase.phase2;
+ phases[2] = e.action.randomPhase.phase3;
+ phases[3] = e.action.randomPhase.phase4;
+ phases[4] = e.action.randomPhase.phase5;
+ phases[5] = e.action.randomPhase.phase6;
uint32 temp[SMART_ACTION_PARAM_COUNT];
uint32 count = 0;
for (uint8 i = 0; i < SMART_ACTION_PARAM_COUNT; i++)
@@ -512,12 +664,19 @@ void SmartScript::ProcessAction(SmartScriptHolder &e, Unit* unit, uint32 var0, u
count++;
}
}
- SetPhase(temp[urand(0, count)]);
+
+ uint32 phase = temp[urand(0, count)];
+ SetPhase(phase);
+ sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction: SMART_ACTION_RANDOM_PHASE: Creature %u sets event phase to %u",
+ me->GetGUIDLow(), phase);
break;
}
case SMART_ACTION_RANDOM_PHASE_RANGE:
{
- SetPhase(urand(e.action.randomPhaseRange.phaseMin, e.action.randomPhaseRange.phaseMax));
+ uint32 phase = urand(e.action.randomPhaseRange.phaseMin, e.action.randomPhaseRange.phaseMax);
+ SetPhase(phase);
+ sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction: SMART_ACTION_RANDOM_PHASE_RANGE: Creature %u sets event phase to %u",
+ me->GetGUIDLow(), phase);
break;
}
case SMART_ACTION_CALL_KILLEDMONSTER:
@@ -525,20 +684,31 @@ void SmartScript::ProcessAction(SmartScriptHolder &e, Unit* unit, uint32 var0, u
Player* pPlayer = NULL;
if (me)
pPlayer = me->GetLootRecipient();
+
if (me && pPlayer)
pPlayer->RewardPlayerAndGroupAtEvent(e.action.killedMonster.creature, pPlayer);
+
else if (GetBaseObject())
{
ObjectList* targets = GetTargets(e, unit);
- if (!targets) return;
+ if (!targets)
+ return;
+
for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); itr++)
{
- if(!IsPlayer((*itr))) continue;
+ if (!IsPlayer((*itr)))
+ continue;
+
(*itr)->ToPlayer()->RewardPlayerAndGroupAtEvent(e.action.killedMonster.creature, (*itr)->ToPlayer());
+ sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction: SMART_ACTION_CALL_KILLEDMONSTER: Player %u, Killcredit: %u",
+ (*itr)->GetGUIDLow(), e.action.killedMonster.creature);
}
- }else if (trigger && IsPlayer(unit))
+ }
+ else if (trigger && IsPlayer(unit))
{
unit->ToPlayer()->RewardPlayerAndGroupAtEvent(e.action.killedMonster.creature, unit);
+ sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction: SMART_ACTION_CALL_KILLEDMONSTER: (trigger == true) Player %u, Killcredit: %u",
+ unit->GetGUIDLow(), e.action.killedMonster.creature);
}
break;
}
@@ -547,15 +717,20 @@ void SmartScript::ProcessAction(SmartScriptHolder &e, Unit* unit, uint32 var0, u
WorldObject* obj = GetBaseObject();
if (!obj)
obj = unit;
+
if (!obj)
return;
+
InstanceScript* pInst = (InstanceScript*)obj->GetInstanceScript();
if (!pInst)
{
sLog->outErrorDb("SmartScript: Event %u attempt to set instance data without instance script. EntryOrGuid %d", e.GetEventType(), e.entryOrGuid);
return;
}
+
pInst->SetData(e.action.setInstanceData.field, e.action.setInstanceData.data);
+ sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction: SMART_ACTION_SET_INST_DATA: Field: %u, data: %u",
+ e.action.setInstanceData.field, e.action.setInstanceData.data);
break;
}
case SMART_ACTION_SET_INST_DATA64:
@@ -563,19 +738,26 @@ void SmartScript::ProcessAction(SmartScriptHolder &e, Unit* unit, uint32 var0, u
WorldObject* obj = GetBaseObject();
if (!obj)
obj = unit;
+
if (!obj)
return;
+
InstanceScript* pInst = (InstanceScript*)obj->GetInstanceScript();
if (!pInst)
{
sLog->outErrorDb("SmartScript: Event %u attempt to set instance data without instance script. EntryOrGuid %d", e.GetEventType(), e.entryOrGuid);
return;
}
+
ObjectList* targets = GetTargets(e, unit);
- if (!targets) return;
+ if (!targets)
+ return;
+
for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); itr++)
{
pInst->SetData64(e.action.setInstanceData64.field, (*itr)->GetGUID());
+ sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction: SMART_ACTION_SET_INST_DATA64: Field: %u, data: "UI64FMTD,
+ e.action.setInstanceData64.field, (*itr)->GetGUID());
return;
}
@@ -585,31 +767,47 @@ void SmartScript::ProcessAction(SmartScriptHolder &e, Unit* unit, uint32 var0, u
{
if (!me || me->GetEntry() == e.action.updateTemplate.creature)
return;
+
me->UpdateEntry(e.action.updateTemplate.creature, e.action.updateTemplate.team ? HORDE : ALLIANCE);
+ sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction: SMART_ACTION_UPDATE_TEMPLATE: Creature %u, Template: %u, Team: %u",
+ me->GetGUIDLow(), e.action.updateTemplate.team ? HORDE : ALLIANCE);
break;
}
case SMART_ACTION_DIE:
{
if (me && !me->isDead())
+ {
me->Kill(me);
+ sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction: SMART_ACTION_DIE: Creature %u", me->GetGUIDLow());
+ }
break;
}
case SMART_ACTION_SET_IN_COMBAT_WITH_ZONE:
{
if (me)
+ {
me->SetInCombatWithZone();
+ sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction: SMART_ACTION_SET_IN_COMBAT_WITH_ZONE: Creature %u", me->GetGUIDLow());
+ }
break;
}
case SMART_ACTION_CALL_FOR_HELP:
{
if (me)
+ {
me->CallForHelp((float)e.action.callHelp.range);
+ sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction: SMART_ACTION_CALL_FOR_HELP: Creature %u", me->GetGUIDLow());
+ }
break;
}
case SMART_ACTION_SET_SHEATH:
{
if (me)
+ {
me->SetSheath(SheathState(e.action.setSheath.sheath));
+ sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction: SMART_ACTION_SET_SHEATH: Creature %u, State: %u",
+ me->GetGUIDLow(), e.action.setSheath.sheath);
+ }
break;
}
case SMART_ACTION_FORCE_DESPAWN:
@@ -1073,11 +1271,11 @@ void SmartScript::ProcessAction(SmartScriptHolder &e, Unit* unit, uint32 var0, u
if (Creature* target = (*itr)->ToCreature())
{
if (IsSmart(target))
- CAST_AI(SmartAI, target->AI())->SetScript9(e, e.action.timedActionList.id, mLastInvoker);
+ CAST_AI(SmartAI, target->AI())->SetScript9(e, e.action.timedActionList.id, GetLastInvoker());
} else if (GameObject* target = (*itr)->ToGameObject())
{
if (IsSmartGO(target))
- CAST_AI(SmartGameObjectAI, target->AI())->SetScript9(e, e.action.timedActionList.id, mLastInvoker);
+ CAST_AI(SmartGameObjectAI, target->AI())->SetScript9(e, e.action.timedActionList.id, GetLastInvoker());
}
}
}
@@ -1166,11 +1364,11 @@ void SmartScript::ProcessAction(SmartScriptHolder &e, Unit* unit, uint32 var0, u
if (Creature* target = (*itr)->ToCreature())
{
if (IsSmart(target))
- CAST_AI(SmartAI, target->AI())->SetScript9(e, id, mLastInvoker);
+ CAST_AI(SmartAI, target->AI())->SetScript9(e, id, GetLastInvoker());
} else if (GameObject* target = (*itr)->ToGameObject())
{
if (IsSmartGO(target))
- CAST_AI(SmartGameObjectAI, target->AI())->SetScript9(e, id, mLastInvoker);
+ CAST_AI(SmartGameObjectAI, target->AI())->SetScript9(e, id, GetLastInvoker());
}
}
}
@@ -1192,11 +1390,11 @@ void SmartScript::ProcessAction(SmartScriptHolder &e, Unit* unit, uint32 var0, u
if (Creature* target = (*itr)->ToCreature())
{
if (IsSmart(target))
- CAST_AI(SmartAI, target->AI())->SetScript9(e, id, mLastInvoker);
+ CAST_AI(SmartAI, target->AI())->SetScript9(e, id, GetLastInvoker());
} else if (GameObject* target = (*itr)->ToGameObject())
{
if (IsSmartGO(target))
- CAST_AI(SmartGameObjectAI, target->AI())->SetScript9(e, id, mLastInvoker);
+ CAST_AI(SmartGameObjectAI, target->AI())->SetScript9(e, id, GetLastInvoker());
}
}
}
@@ -1374,8 +1572,8 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder e, Unit* invoker)
Unit* trigger = NULL;
if (invoker)
trigger = invoker;
- else if (mLastInvoker)
- trigger = mLastInvoker;
+ else if (Unit* tempLastInvoker = GetLastInvoker())
+ trigger = tempLastInvoker;
ObjectList* l = new ObjectList();
switch (e.GetTargetType())
{
@@ -2376,4 +2574,7 @@ void SmartScript::SetScript9(SmartScriptHolder &e, uint32 entry)
mResumeActionList = e.action.timedActionList.dontResume ? false : true;
InitTimer((*i));
}
+}Unit* SmartScript::GetLastInvoker()
+{
+ return ObjectAccessor::FindUnit(mLastInvoker);
}
diff --git a/src/server/game/AI/SmartScripts/SmartScript.h b/src/server/game/AI/SmartScripts/SmartScript.h
index 08ee5570a89..a5331672803 100644
--- a/src/server/game/AI/SmartScripts/SmartScript.h
+++ b/src/server/game/AI/SmartScripts/SmartScript.h
@@ -191,7 +191,8 @@ class SmartScript
//TIMED_ACTIONLIST (script type 9 aka script9)
void SetScript9(SmartScriptHolder &e, uint32 entry);
- Unit* mLastInvoker;
+ Unit* GetLastInvoker();
+ uint64 mLastInvoker;
private:
void IncPhase(int32 p = 1) {
diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp
index 658846c881c..e0844cdcccd 100755
--- a/src/server/game/Battlegrounds/Battleground.cpp
+++ b/src/server/game/Battlegrounds/Battleground.cpp
@@ -1034,7 +1034,6 @@ void Battleground::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac
if (!group->RemoveMember(guid)) // group was disbanded
{
SetBgRaid(team, NULL);
- delete group;
}
}
DecreaseInvitedCount(team);
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index 0fd48f47ae6..53370170c9e 100755
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -154,7 +154,6 @@ m_formation(NULL)
m_CreatureSpellCooldowns.clear();
m_CreatureCategoryCooldowns.clear();
- m_GlobalCooldown = 0;
DisableReputationGain = false;
//m_unit_movement_flags = MONSTER_MOVE_WALK;
@@ -430,11 +429,6 @@ bool Creature::UpdateEntry(uint32 Entry, uint32 team, const CreatureData *data)
void Creature::Update(uint32 diff)
{
- if (m_GlobalCooldown <= diff)
- m_GlobalCooldown = 0;
- else
- m_GlobalCooldown -= diff;
-
if (IsAIEnabled && TriggerJustRespawned)
{
TriggerJustRespawned = false;
@@ -2185,8 +2179,6 @@ void Creature::AddCreatureSpellCooldown(uint32 spellid)
if (spellInfo->Category)
_AddCreatureCategoryCooldown(spellInfo->Category, time(NULL));
-
- m_GlobalCooldown = spellInfo->StartRecoveryTime;
}
bool Creature::HasCategoryCooldown(uint32 spell_id) const
@@ -2195,10 +2187,6 @@ bool Creature::HasCategoryCooldown(uint32 spell_id) const
if (!spellInfo)
return false;
- // check global cooldown if spell affected by it
- if (spellInfo->StartRecoveryCategory > 0 && m_GlobalCooldown > 0)
- return true;
-
CreatureSpellCooldowns::const_iterator itr = m_CreatureCategoryCooldowns.find(spellInfo->Category);
return(itr != m_CreatureCategoryCooldowns.end() && time_t(itr->second + (spellInfo->CategoryRecoveryTime / IN_MILLISECONDS)) > time(NULL));
}
diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h
index 43ff73df08c..4933428bf4e 100755
--- a/src/server/game/Entities/Creature/Creature.h
+++ b/src/server/game/Entities/Creature/Creature.h
@@ -577,7 +577,6 @@ class Creature : public Unit, public GridObject<Creature>
uint32 m_spells[CREATURE_MAX_SPELLS];
CreatureSpellCooldowns m_CreatureSpellCooldowns;
CreatureSpellCooldowns m_CreatureCategoryCooldowns;
- uint32 m_GlobalCooldown;
bool canStartAttack(Unit const* u, bool force) const;
float GetAttackDistance(Unit const* pl) const;
@@ -646,8 +645,6 @@ class Creature : public Unit, public GridObject<Creature>
void GetHomePosition(float &x, float &y, float &z, float &ori) { m_homePosition.GetPosition(x, y, z, ori); }
Position GetHomePosition() { return m_homePosition; }
- uint32 GetGlobalCooldown() const { return m_GlobalCooldown; }
-
uint32 GetWaypointPath(){return m_path_id;}
void LoadPath(uint32 pathid) { m_path_id = pathid; }
diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp
index 88ae3306371..6bbb1784ee1 100755
--- a/src/server/game/Entities/GameObject/GameObject.cpp
+++ b/src/server/game/Entities/GameObject/GameObject.cpp
@@ -1064,7 +1064,7 @@ void GameObject::Use(Unit* user)
if (user->GetTypeId() != TYPEID_PLAYER)
return;
- Player* player = (Player*)user;
+ Player* player = user->ToPlayer();
player->PrepareGossipMenu(this, GetGOInfo()->questgiver.gossipID);
player->SendPreparedGossip(this);
@@ -1089,7 +1089,7 @@ void GameObject::Use(Unit* user)
ChairListSlots[0] = 0; // error in DB, make one default slot
}
- Player* player = (Player*)user;
+ Player* player = user->ToPlayer();
// a chair may have n slots. we have to calculate their positions and teleport the player to the nearest one
@@ -1167,7 +1167,7 @@ void GameObject::Use(Unit* user)
if (user->GetTypeId() == TYPEID_PLAYER)
{
- Player* player = (Player*)user;
+ Player* player = user->ToPlayer();
if (info->goober.pageId) // show page...
{
@@ -1233,7 +1233,7 @@ void GameObject::Use(Unit* user)
if (user->GetTypeId() != TYPEID_PLAYER)
return;
- Player* player = (Player*)user;
+ Player* player = user->ToPlayer();
if (info->camera.cinematicId)
player->SendCinematicStart(info->camera.cinematicId);
@@ -1437,7 +1437,7 @@ void GameObject::Use(Unit* user)
if (user->GetTypeId() != TYPEID_PLAYER)
return;
- Player* player = (Player*)user;
+ Player* player = user->ToPlayer();
Player* targetPlayer = ObjectAccessor::FindPlayer(player->GetSelection());
@@ -1466,7 +1466,7 @@ void GameObject::Use(Unit* user)
if (user->GetTypeId() != TYPEID_PLAYER)
return;
- Player* player = (Player*)user;
+ Player* player = user->ToPlayer();
if (player->CanUseBattlegroundObject())
{
@@ -1494,7 +1494,7 @@ void GameObject::Use(Unit* user)
if (user->GetTypeId() != TYPEID_PLAYER)
return;
- Player* player = (Player*)user;
+ Player* player = user->ToPlayer();
player->SendLoot(GetGUID(), LOOT_FISHINGHOLE);
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT, GetGOInfo()->id);
@@ -1506,7 +1506,7 @@ void GameObject::Use(Unit* user)
if (user->GetTypeId() != TYPEID_PLAYER)
return;
- Player* player = (Player*)user;
+ Player* player = user->ToPlayer();
if (player->CanUseBattlegroundObject())
{
@@ -1557,7 +1557,7 @@ void GameObject::Use(Unit* user)
if (user->GetTypeId() != TYPEID_PLAYER)
return;
- Player* player = (Player*)user;
+ Player* player = user->ToPlayer();
// fallback, will always work
player->TeleportTo(GetMapId(), GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation(),TELE_TO_NOT_LEAVE_TRANSPORT | TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET);
@@ -1569,7 +1569,8 @@ void GameObject::Use(Unit* user)
return;
}
default:
- sLog->outError("Unknown Object Type %u", GetGoType());
+ sLog->outError("GameObject::Use(): unit (type: %u, guid: %u) tries to use object (guid: %u) of unknown type (%u)",
+ user->GetTypeId(), user->GetGUIDLow(), GetGUIDLow(), GetGoType());
break;
}
@@ -1579,7 +1580,7 @@ void GameObject::Use(Unit* user)
SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId);
if (!spellInfo)
{
- if (user->GetTypeId() != TYPEID_PLAYER || !sOutdoorPvPMgr->HandleCustomSpell((Player*)user,spellId,this))
+ if (user->GetTypeId() != TYPEID_PLAYER || !sOutdoorPvPMgr->HandleCustomSpell(user->ToPlayer(), spellId, this))
sLog->outError("WORLD: unknown spell id %u at use action for gameobject (Entry: %u GoType: %u)", spellId,GetEntry(),GetGoType());
else
sLog->outDebug(LOG_FILTER_OUTDOORPVP, "WORLD: %u non-dbc spell was handled by OutdoorPvP", spellId);
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index d3d38ffa4aa..1179eef26e6 100755
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -2647,12 +2647,12 @@ void Player::UninviteFromGroup()
if (group->IsCreated())
{
group->Disband(true);
- sObjectMgr->RemoveGroup(group);
}
else
+ {
group->RemoveAllInvites();
-
- delete group;
+ delete group;
+ }
}
}
@@ -2660,14 +2660,8 @@ void Player::RemoveFromGroup(Group* group, uint64 guid, RemoveMethod method /* =
{
if (group)
{
- if (group->RemoveMember(guid, method, kicker, reason) <= 1)
- {
- // group->Disband(); already disbanded in RemoveMember
- sObjectMgr->RemoveGroup(group);
- delete group;
- group = NULL;
- // removemember sets the player's group pointer to NULL
- }
+ group->RemoveMember(guid, method, kicker, reason);
+ group = NULL;
}
}
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index d14082cc864..8ee626d18bb 100755
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -1640,6 +1640,8 @@ class Player : public Unit, public GridObject<Player>
void RemoveSpellCategoryCooldown(uint32 cat, bool update = false);
void SendClearCooldown(uint32 spell_id, Unit* target);
+ GlobalCooldownMgr& GetGlobalCooldownMgr() { return m_GlobalCooldownMgr; }
+
void RemoveCategoryCooldown(uint32 cat);
void RemoveArenaSpellCooldowns(bool removeActivePetCooldowns = false);
void RemoveAllSpellCooldown();
@@ -2545,6 +2547,8 @@ class Player : public Unit, public GridObject<Player>
PlayerTalentMap *m_talents[MAX_TALENT_SPECS];
uint32 m_lastPotionId; // last used health/mana potion in combat, that block next potion use
+ GlobalCooldownMgr m_GlobalCooldownMgr;
+
uint8 m_activeSpec;
uint8 m_specsCount;
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 1ad52613687..81f048771c9 100755
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -192,6 +192,26 @@ m_vehicleKit(NULL), m_unitTypeMask(UNIT_MASK_NONE), m_HostileRefManager(this)
m_serverSideVisibility.SetValue(SERVERSIDE_VISIBILITY_GHOST, GHOST_VISIBILITY_ALIVE);
}
+////////////////////////////////////////////////////////////
+// Methods of class GlobalCooldownMgr
+bool GlobalCooldownMgr::HasGlobalCooldown(SpellEntry const* spellInfo) const
+{
+ GlobalCooldownList::const_iterator itr = m_GlobalCooldowns.find(spellInfo->StartRecoveryCategory);
+ return itr != m_GlobalCooldowns.end() && itr->second.duration && getMSTimeDiff(itr->second.cast_time, getMSTime()) < itr->second.duration;
+}
+
+void GlobalCooldownMgr::AddGlobalCooldown(SpellEntry const* spellInfo, uint32 gcd)
+{
+ m_GlobalCooldowns[spellInfo->StartRecoveryCategory] = GlobalCooldown(gcd, getMSTime());
+}
+
+void GlobalCooldownMgr::CancelGlobalCooldown(SpellEntry const* spellInfo)
+{
+ m_GlobalCooldowns[spellInfo->StartRecoveryCategory].duration = 0;
+}
+
+////////////////////////////////////////////////////////////
+// Methods of class Unit
Unit::~Unit()
{
// set current spells as deletable
@@ -515,7 +535,7 @@ bool Unit::HasAuraTypeWithFamilyFlags(AuraType auraType, uint32 familyName, uint
void Unit::DealDamageMods(Unit *pVictim, uint32 &damage, uint32* absorb)
{
- if (!pVictim->isAlive() || pVictim->HasUnitState(UNIT_STAT_IN_FLIGHT) || (pVictim->HasUnitState(UNIT_STAT_ONVEHICLE) && pVictim->GetVehicleBase() != this) || (pVictim->GetTypeId() == TYPEID_UNIT && pVictim->ToCreature()->IsInEvadeMode()))
+ if (!pVictim->isAlive() || pVictim->HasUnitState(UNIT_STAT_IN_FLIGHT) || (pVictim->GetTypeId() == TYPEID_UNIT && pVictim->ToCreature()->IsInEvadeMode()))
{
if (absorb)
*absorb += damage;
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index e546af981a3..73d5cae78f0 100755
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -937,6 +937,30 @@ enum CurrentSpellTypes
#define CURRENT_FIRST_NON_MELEE_SPELL 1
#define CURRENT_MAX_SPELL 4
+struct GlobalCooldown
+{
+ explicit GlobalCooldown(uint32 _dur = 0, uint32 _time = 0) : duration(_dur), cast_time(_time) {}
+
+ uint32 duration;
+ uint32 cast_time;
+};
+
+typedef UNORDERED_MAP<uint32 /*category*/, GlobalCooldown> GlobalCooldownList;
+
+class GlobalCooldownMgr // Shared by Player and CharmInfo
+{
+public:
+ GlobalCooldownMgr() {}
+
+public:
+ bool HasGlobalCooldown(SpellEntry const* spellInfo) const;
+ void AddGlobalCooldown(SpellEntry const* spellInfo, uint32 gcd);
+ void CancelGlobalCooldown(SpellEntry const* spellInfo);
+
+private:
+ GlobalCooldownList m_GlobalCooldowns;
+};
+
enum ActiveStates
{
ACT_PASSIVE = 0x01, // 0x01 - passive
@@ -1057,6 +1081,8 @@ struct CharmInfo
CharmSpellEntry* GetCharmSpell(uint8 index) { return &(m_charmspells[index]); }
+ GlobalCooldownMgr& GetGlobalCooldownMgr() { return m_GlobalCooldownMgr; }
+
void SetIsCommandAttack(bool val);
bool IsCommandAttack();
void SetIsAtStay(bool val);
@@ -1088,6 +1114,8 @@ struct CharmInfo
float m_stayX;
float m_stayY;
float m_stayZ;
+
+ GlobalCooldownMgr m_GlobalCooldownMgr;
};
// for clearing special attacks
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index 41564b49a2e..ea648172a2a 100755
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -3970,9 +3970,9 @@ void ObjectMgr::LoadGroups()
uint32 oldMSTime = getMSTime();
// Delete all groups whose leader does not exist
- CharacterDatabase.Execute(CharacterDatabase.GetPreparedStatement(CHAR_DEL_LEADERLESS_GROUPS));
+ CharacterDatabase.DirectExecute(CharacterDatabase.GetPreparedStatement(CHAR_DEL_LEADERLESS_GROUPS));
// Delete all groups with less than 2 members
- CharacterDatabase.Execute(CharacterDatabase.GetPreparedStatement(CHAR_DEL_TINY_GROUPS));
+ CharacterDatabase.DirectExecute(CharacterDatabase.GetPreparedStatement(CHAR_DEL_TINY_GROUPS));
// 0 1 2 3 4 5 6 7 8 9
QueryResult result = CharacterDatabase.PQuery("SELECT leaderGuid, lootMethod, looterGuid, lootThreshold, icon1, icon2, icon3, icon4, icon5, icon6"
diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp
index bef3904bddb..2f7ae3c4d5f 100755
--- a/src/server/game/Groups/Group.cpp
+++ b/src/server/game/Groups/Group.cpp
@@ -405,7 +405,7 @@ bool Group::AddMember(Player *player)
return true;
}
-uint32 Group::RemoveMember(const uint64 &guid, const RemoveMethod &method /* = GROUP_REMOVEMETHOD_DEFAULT */, uint64 kicker /* = 0 */, const char* reason /* = NULL */)
+bool Group::RemoveMember(const uint64 &guid, const RemoveMethod &method /*= GROUP_REMOVEMETHOD_DEFAULT*/, uint64 kicker /*= 0*/, const char* reason /*= NULL*/)
{
BroadcastGroupUpdate();
@@ -505,12 +505,15 @@ uint32 Group::RemoveMember(const uint64 &guid, const RemoveMethod &method /* = G
}
SendUpdate();
+
+ return true;
}
// If group size before player removal <= 2 then disband it
else
+ {
Disband();
-
- return m_memberSlots.size();
+ return false;
+ }
}
void Group::ChangeLeader(const uint64 &guid)
@@ -634,9 +637,8 @@ void Group::Disband(bool hideDestroy /* = false */)
ResetInstances(INSTANCE_RESET_GROUP_DISBAND, true, NULL);
}
- m_guid = 0;
- m_leaderGuid = 0;
- m_leaderName = "";
+ sObjectMgr->RemoveGroup(this);
+ delete this;
}
/*********************************************************/
diff --git a/src/server/game/Groups/Group.h b/src/server/game/Groups/Group.h
index e4c4066572a..3928b6ee54a 100755
--- a/src/server/game/Groups/Group.h
+++ b/src/server/game/Groups/Group.h
@@ -190,7 +190,7 @@ class Group
void RemoveAllInvites();
bool AddLeaderInvite(Player *player);
bool AddMember(Player *player);
- uint32 RemoveMember(const uint64 &guid, const RemoveMethod &method = GROUP_REMOVEMETHOD_DEFAULT, uint64 kicker = 0, const char* reason = NULL);
+ bool RemoveMember(const uint64 &guid, const RemoveMethod &method = GROUP_REMOVEMETHOD_DEFAULT, uint64 kicker = 0, const char* reason = NULL);
void ChangeLeader(const uint64 &guid);
void SetLootMethod(LootMethod method);
void SetLooterGuid(const uint64 &guid);
diff --git a/src/server/game/Server/Protocol/Handlers/PetHandler.cpp b/src/server/game/Server/Protocol/Handlers/PetHandler.cpp
index 9dd53dd14dc..83d3c1db28c 100755
--- a/src/server/game/Server/Protocol/Handlers/PetHandler.cpp
+++ b/src/server/game/Server/Protocol/Handlers/PetHandler.cpp
@@ -141,7 +141,8 @@ void WorldSession::HandlePetActionHelper(Unit *pet, uint64 guid1, uint16 spellid
CharmInfo *charmInfo = pet->GetCharmInfo();
if (!charmInfo)
{
- sLog->outError("WorldSession::HandlePetAction: object (GUID: %u TypeId: %u) is considered pet-like but doesn't have a charminfo!", pet->GetGUIDLow(), pet->GetTypeId());
+ sLog->outError("WorldSession::HandlePetAction(petGuid: " UI64FMTD ", tagGuid: " UI64FMTD ", spellId: %u, flag: %u): object (entry: %u TypeId: %u) is considered pet-like but doesn't have a charminfo!",
+ guid1, guid2, spellid, flag, pet->GetGUIDLow(), pet->GetTypeId());
return;
}
@@ -295,7 +296,7 @@ void WorldSession::HandlePetActionHelper(Unit *pet, uint64 guid1, uint16 spellid
}
if (spellInfo->StartRecoveryCategory > 0)
- if (pet->ToCreature()->GetGlobalCooldown() > 0)
+ if (pet->GetCharmInfo() && pet->GetCharmInfo()->GetGlobalCooldownMgr().HasGlobalCooldown(spellInfo))
return;
for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i)
@@ -753,7 +754,7 @@ void WorldSession::HandlePetCastSpellOpcode(WorldPacket& recvPacket)
}
if (spellInfo->StartRecoveryCategory > 0) // Check if spell is affected by GCD
- if (caster->GetTypeId() == TYPEID_UNIT && caster->ToCreature()->GetGlobalCooldown() > 0)
+ if (caster->GetTypeId() == TYPEID_UNIT && caster->GetCharmInfo() && caster->GetCharmInfo()->GetGlobalCooldownMgr().HasGlobalCooldown(spellInfo))
{
caster->SendPetCastFail(spellId, SPELL_FAILED_NOT_READY);
return;
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index 95769040dde..4d6459bc66d 100755
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -3001,8 +3001,7 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect const * triggere
m_caster->SetCurrentCastedSpell(this);
SendSpellStart();
- if (m_caster->GetTypeId() == TYPEID_PLAYER)
- m_caster->ToPlayer()->AddGlobalCooldown(m_spellInfo,this);
+ TriggerGlobalCooldown();
if (!m_casttime && !m_spellInfo->StartRecoveryTime
&& !m_castItemGUID //item: first cast may destroy item and second cast causes crash
@@ -3027,6 +3026,7 @@ void Spell::cancel()
switch (oldState)
{
case SPELL_STATE_PREPARING:
+ CancelGlobalCooldown();
case SPELL_STATE_DELAYED:
SendInterrupted(0);
SendCastResult(SPELL_FAILED_INTERRUPTED);
@@ -4680,6 +4680,10 @@ SpellCastResult Spell::CheckCast(bool strict)
}
}
+ // Check global cooldown
+ if (strict && !m_IsTriggeredSpell && HasGlobalCooldown())
+ return SPELL_FAILED_NOT_READY;
+
// only allow triggered spells if at an ended battleground
if (!m_IsTriggeredSpell && m_caster->GetTypeId() == TYPEID_PLAYER)
if (Battleground * bg = m_caster->ToPlayer()->GetBattleground())
@@ -7285,3 +7289,67 @@ void Spell::CallScriptAfterUnitTargetSelectHandlers(std::list<Unit*>& unitTarget
(*scritr)->_FinishScriptCall();
}
}
+
+// Global cooldowns management
+enum GCDLimits
+{
+ MIN_GCD = 1000,
+ MAX_GCD = 1500
+};
+
+bool Spell::HasGlobalCooldown()
+{
+ // Only player or controlled units have global cooldown
+ if (m_caster->GetCharmInfo())
+ return m_caster->GetCharmInfo()->GetGlobalCooldownMgr().HasGlobalCooldown(m_spellInfo);
+ else if (m_caster->GetTypeId() == TYPEID_PLAYER)
+ return m_caster->ToPlayer()->GetGlobalCooldownMgr().HasGlobalCooldown(m_spellInfo);
+ else
+ return false;
+}
+
+void Spell::TriggerGlobalCooldown()
+{
+ int32 gcd = m_spellInfo->StartRecoveryTime;
+ if (!gcd)
+ return;
+
+ // Global cooldown can't leave range 1..1.5 secs
+ // There are some spells (mostly not casted directly by player) that have < 1 sec and > 1.5 sec global cooldowns
+ // but as tests show are not affected by any spell mods.
+ if (m_spellInfo->StartRecoveryTime >= MIN_GCD && m_spellInfo->StartRecoveryTime <= MAX_GCD)
+ {
+ // gcd modifier auras are applied only to own spells and only players have such mods
+ if (m_caster->GetTypeId() == TYPEID_PLAYER)
+ m_caster->ToPlayer()->ApplySpellMod(m_spellInfo->Id, SPELLMOD_GLOBAL_COOLDOWN, gcd, this);
+
+ // Apply haste rating
+ gcd = int32(float(gcd) * m_caster->GetFloatValue(UNIT_MOD_CAST_SPEED));
+ if (gcd < MIN_GCD)
+ gcd = MIN_GCD;
+ else if (gcd > MAX_GCD)
+ gcd = MAX_GCD;
+ }
+
+ // Only players or controlled units have global cooldown
+ if (m_caster->GetCharmInfo())
+ m_caster->GetCharmInfo()->GetGlobalCooldownMgr().AddGlobalCooldown(m_spellInfo, gcd);
+ else if (m_caster->GetTypeId() == TYPEID_PLAYER)
+ m_caster->ToPlayer()->GetGlobalCooldownMgr().AddGlobalCooldown(m_spellInfo, gcd);
+}
+
+void Spell::CancelGlobalCooldown()
+{
+ if (!m_spellInfo->StartRecoveryTime)
+ return;
+
+ // Cancel global cooldown when interrupting current cast
+ if (m_caster->GetCurrentSpell(CURRENT_GENERIC_SPELL) != this)
+ return;
+
+ // Only players or controlled units have global cooldown
+ if (m_caster->GetCharmInfo())
+ m_caster->GetCharmInfo()->GetGlobalCooldownMgr().CancelGlobalCooldown(m_spellInfo);
+ else if (m_caster->GetTypeId() == TYPEID_PLAYER)
+ m_caster->ToPlayer()->GetGlobalCooldownMgr().CancelGlobalCooldown(m_spellInfo);
+}
diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h
index 34ddf5c1028..d83107f1db3 100755
--- a/src/server/game/Spells/Spell.h
+++ b/src/server/game/Spells/Spell.h
@@ -543,6 +543,9 @@ class Spell
void SetSpellValue(SpellValueMod mod, int32 value);
protected:
+ bool HasGlobalCooldown();
+ void TriggerGlobalCooldown();
+ void CancelGlobalCooldown();
void SendLoot(uint64 guid, LootType loottype);
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index 9136cf2c9cb..4c0fec17774 100755
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -5149,12 +5149,6 @@ void Spell::EffectScriptEffect(SpellEffIndex effIndex)
}
return;
}
- case 65594: // Cancel Stone Grip
- {
- uint32 spellToRemove = unitTarget->GetMap()->GetDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL ? 62166 : 63981;
- unitTarget->RemoveAurasDueToSpell(spellToRemove);
- return;
- }
case 60123: // Lightwell
{
if (m_caster->GetTypeId() != TYPEID_UNIT || !m_caster->ToCreature()->isSummon())