Merge branch 'master' of github.com:TrinityCore/TrinityCore
This commit is contained in:
@@ -1535,8 +1535,6 @@ UPDATE `creature_template` SET `ScriptName`='mob_lightning_elemental' WHERE `ent
|
||||
UPDATE `creature_template` SET `ScriptName`='mob_rune_of_summoning' WHERE `entry`=33051;
|
||||
UPDATE `creature_template` SET `ScriptName`= 'mob_rune_of_power' WHERE entry = 33705;
|
||||
UPDATE `creature_template` SET `ScriptName`='boss_kologarn' WHERE `entry`=32930;
|
||||
UPDATE `creature_template` SET `ScriptName`='npc_right_arm' WHERE `entry`=32934;
|
||||
UPDATE `creature_template` SET `ScriptName`='npc_left_arm' WHERE `entry`=32933;
|
||||
UPDATE `creature_template` SET `ScriptName`='boss_general_vezax' WHERE `entry`=33271;
|
||||
UPDATE `creature_template` SET `ScriptName`='npc_saronite_vapors' WHERE `entry`=33488;
|
||||
UPDATE `creature_template` SET `ScriptName`='npc_saronite_animus' WHERE `entry`=33524;
|
||||
@@ -2064,6 +2062,12 @@ INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES
|
||||
( 62521, 'spell_attuned_to_nature_dose_reduction'),
|
||||
( 62524, 'spell_attuned_to_nature_dose_reduction'),
|
||||
( 62525, 'spell_attuned_to_nature_dose_reduction'),
|
||||
( 63633, 'spell_ulduar_rubble_summon'),
|
||||
( 65594, 'spell_ulduar_cancel_stone_grip'),
|
||||
( 62056, 'spell_ulduar_stone_grip'),
|
||||
( 63985, 'spell_ulduar_stone_grip'),
|
||||
( 64224, 'spell_ulduar_stone_grip_absorb'),
|
||||
( 64225, 'spell_ulduar_stone_grip_absorb'),
|
||||
-- quest
|
||||
( 8913, 'spell_q55_sacred_cleansing'),
|
||||
( 17271, 'spell_q5206_test_fetid_skull'),
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
UPDATE `creature_template` SET `ScriptName`='' WHERE `entry` IN(32933,32934);
|
||||
@@ -0,0 +1,8 @@
|
||||
DELETE FROM `spell_script_names` WHERE `spell_id` IN(63633,65594,62056,63985,64224,64225);
|
||||
INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES
|
||||
(63633,'spell_ulduar_rubble_summon'),
|
||||
(65594,'spell_ulduar_cancel_stone_grip'),
|
||||
(62056,'spell_ulduar_stone_grip'),
|
||||
(63985,'spell_ulduar_stone_grip'),
|
||||
(64224,'spell_ulduar_stone_grip_absorb'),
|
||||
(64225,'spell_ulduar_stone_grip_absorb');
|
||||
@@ -0,0 +1,3 @@
|
||||
DELETE FROM `conditions` WHERE `SourceEntry`=65594 AND `ConditionTypeOrReference`=18;
|
||||
INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`ConditionTypeOrReference`,`ConditionValue1`,`ConditionValue2`,`Comment`) VALUES
|
||||
(13,0,65594,18,1,0,'Cancel Stone Grip Target');
|
||||
@@ -0,0 +1 @@
|
||||
UPDATE `creature_template` SET `flags_extra`= `flags_extra`&~1 WHERE `entry` IN(32933,32934);
|
||||
@@ -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())
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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; }
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/*********************************************************/
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -26,19 +26,35 @@
|
||||
#define SPELL_PETRIFY_BREATH RAID_MODE(62030,63980)
|
||||
|
||||
#define SPELL_STONE_GRIP RAID_MODE(62166,63981)
|
||||
|
||||
#define NPC_RUBBLE_STALKER RAID_MODE(33809,33942)
|
||||
#define SPELL_SUMMON_RUBBLE 63633
|
||||
#define SPELL_FALLING_RUBBLE 63821
|
||||
|
||||
#define SPELL_STONE_GRIP_CANCEL 65594
|
||||
|
||||
#define SPELL_ARM_SWEEP RAID_MODE(63766,63983)
|
||||
|
||||
#define SPELL_ARM_ENTER_VEHICLE 65343
|
||||
#define SPELL_ARM_VISUAL 64753
|
||||
|
||||
#define SPELL_BERSERK 47008 // guess
|
||||
|
||||
#define NPC_LEFT_ARM RAID_MODE(32933,33910)
|
||||
#define NPC_RIGHT_ARM RAID_MODE(32934,33911)
|
||||
|
||||
enum Events
|
||||
{
|
||||
EVENT_NONE = 0,
|
||||
EVENT_INSTALL_ACCESSORIES,
|
||||
EVENT_MELEE_CHECK,
|
||||
EVENT_SMASH,
|
||||
EVENT_SWEEP,
|
||||
EVENT_STONE_SHOUT,
|
||||
EVENT_RESPAWN_ARM,
|
||||
EVENT_STONE_GRIP,
|
||||
EVENT_RIGHT_ARM_DEAD,
|
||||
EVENT_RESPAWN_LEFT_ARM,
|
||||
EVENT_RESPAWN_RIGHT_ARM,
|
||||
EVENT_ENRAGE,
|
||||
};
|
||||
|
||||
@@ -60,22 +76,6 @@ enum
|
||||
ACHIEV_DISARMED_START_EVENT = 21687,
|
||||
};
|
||||
|
||||
void EncounterInCombat(Creature* me, InstanceScript* pInstance)
|
||||
{
|
||||
Creature* c;
|
||||
c = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(TYPE_KOLOGARN) : 0);
|
||||
if (c && c != me && c->isAlive())
|
||||
c->SetInCombatWithZone();
|
||||
|
||||
c = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_RIGHT_ARM) : 0);
|
||||
if (c && c != me && c->isAlive())
|
||||
c->SetInCombatWithZone();
|
||||
|
||||
c = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_LEFT_ARM) : 0);
|
||||
if (c && c != me && c->isAlive())
|
||||
c->SetInCombatWithZone();
|
||||
}
|
||||
|
||||
class boss_kologarn : public CreatureScript
|
||||
{
|
||||
public:
|
||||
@@ -89,7 +89,7 @@ public:
|
||||
struct boss_kologarnAI : public BossAI
|
||||
{
|
||||
boss_kologarnAI(Creature *pCreature) : BossAI(pCreature, TYPE_KOLOGARN), vehicle(pCreature->GetVehicleKit()),
|
||||
uiArmCount(0)
|
||||
left(false), right(false)
|
||||
{
|
||||
ASSERT(vehicle);
|
||||
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
||||
@@ -99,21 +99,31 @@ public:
|
||||
}
|
||||
|
||||
Vehicle *vehicle;
|
||||
uint8 uiArmCount;
|
||||
bool left, right;
|
||||
|
||||
void EnterCombat(Unit * who)
|
||||
{
|
||||
DoScriptText(SAY_AGGRO, me);
|
||||
|
||||
events.ScheduleEvent(EVENT_MELEE_CHECK, 6000);
|
||||
events.ScheduleEvent(EVENT_SMASH, 5000);
|
||||
events.ScheduleEvent(EVENT_STONE_GRIP, 25000);
|
||||
events.ScheduleEvent(EVENT_ENRAGE, 600000);
|
||||
|
||||
Unit* arm = NULL;
|
||||
if (arm = vehicle->GetPassenger(0))
|
||||
arm->Attack(who, true);
|
||||
if (arm = vehicle->GetPassenger(1))
|
||||
arm->Attack(who, true);
|
||||
|
||||
_EnterCombat();
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
_Reset();
|
||||
}
|
||||
|
||||
void EnterCombat(Unit * /*who*/)
|
||||
{
|
||||
DoScriptText(SAY_AGGRO, me);
|
||||
_EnterCombat();
|
||||
events.ScheduleEvent(EVENT_MELEE_CHECK, 6000);
|
||||
events.ScheduleEvent(EVENT_SMASH, 5000);
|
||||
events.ScheduleEvent(EVENT_ENRAGE, 600000);
|
||||
EncounterInCombat(me, instance);
|
||||
events.ScheduleEvent(EVENT_INSTALL_ACCESSORIES, 1000);
|
||||
|
||||
}
|
||||
|
||||
void JustDied(Unit * /*victim*/)
|
||||
@@ -124,28 +134,53 @@ public:
|
||||
|
||||
void KilledUnit(Unit* /*who*/)
|
||||
{
|
||||
DoScriptText(RAND(SAY_SLAY_2,SAY_SLAY_2), me);
|
||||
DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me);
|
||||
}
|
||||
|
||||
void PassengerBoarded(Unit *who, int8 /*seatId*/, bool apply)
|
||||
{
|
||||
if (who->GetTypeId() == TYPEID_UNIT)
|
||||
if (who->GetEntry() == NPC_LEFT_ARM)
|
||||
{
|
||||
if (apply)
|
||||
{
|
||||
++uiArmCount;
|
||||
events.CancelEvent(EVENT_STONE_SHOUT);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (--uiArmCount == 0)
|
||||
events.ScheduleEvent(EVENT_STONE_SHOUT, 5000);
|
||||
|
||||
events.ScheduleEvent(EVENT_RESPAWN_ARM, 40000);
|
||||
if (instance)
|
||||
instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_DISARMED_START_EVENT);
|
||||
}
|
||||
left = apply;
|
||||
if (!apply)
|
||||
DoScriptText(SAY_LEFT_ARM_GONE, me);
|
||||
}
|
||||
|
||||
else if (who->GetEntry() == NPC_RIGHT_ARM)
|
||||
{
|
||||
right = apply;
|
||||
if (!apply)
|
||||
DoScriptText(SAY_RIGHT_ARM_GONE, me);
|
||||
}
|
||||
|
||||
if (!apply)
|
||||
{
|
||||
who->CastSpell(me, SPELL_ARM_DEAD_DAMAGE, true);
|
||||
DoScriptText(SAY_RIGHT_ARM_GONE, me);
|
||||
|
||||
if (Creature* rubbleStalker = me->FindNearestCreature(NPC_RUBBLE_STALKER, 20.0f))
|
||||
{
|
||||
if (rubbleStalker)
|
||||
{
|
||||
rubbleStalker->CastSpell(rubbleStalker, SPELL_FALLING_RUBBLE, true);
|
||||
rubbleStalker->CastSpell(rubbleStalker, SPELL_SUMMON_RUBBLE, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (!right && !left)
|
||||
events.ScheduleEvent(EVENT_STONE_SHOUT, 5000);
|
||||
|
||||
if (who->GetEntry() == NPC_LEFT_ARM)
|
||||
events.ScheduleEvent(EVENT_RESPAWN_LEFT_ARM, 40000);
|
||||
else if (who->GetEntry() == NPC_RIGHT_ARM)
|
||||
events.ScheduleEvent(EVENT_RESPAWN_RIGHT_ARM, 40000);
|
||||
|
||||
if (instance)
|
||||
instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_DISARMED_START_EVENT);
|
||||
}
|
||||
|
||||
if (apply)
|
||||
events.CancelEvent(EVENT_STONE_SHOUT);
|
||||
}
|
||||
|
||||
void UpdateAI(const uint32 diff)
|
||||
@@ -160,15 +195,23 @@ public:
|
||||
|
||||
switch (events.GetEvent())
|
||||
{
|
||||
case EVENT_INSTALL_ACCESSORIES: // Delayed install, this is needed for IsInWorldCheck in Vehicle code to trigger PassengerBoarded
|
||||
vehicle->InstallAllAccessories(me->GetEntry());
|
||||
events.CancelEvent(EVENT_INSTALL_ACCESSORIES);
|
||||
break;
|
||||
case EVENT_MELEE_CHECK:
|
||||
if (!me->IsWithinMeleeRange(me->getVictim()))
|
||||
DoCast(SPELL_PETRIFY_BREATH);
|
||||
events.RepeatEvent(1000);
|
||||
break;
|
||||
case EVENT_SWEEP:
|
||||
DoCast(SPELL_ARM_SWEEP);
|
||||
events.RepeatEvent(15000);
|
||||
break;
|
||||
case EVENT_SMASH:
|
||||
if (uiArmCount == 2)
|
||||
if (left && right)
|
||||
DoCastVictim(SPELL_TWO_ARM_SMASH);
|
||||
else if (uiArmCount == 1)
|
||||
else if (left || right)
|
||||
DoCastVictim(SPELL_ONE_ARM_SMASH);
|
||||
events.RepeatEvent(15000);
|
||||
break;
|
||||
@@ -180,203 +223,195 @@ public:
|
||||
DoCast(SPELL_BERSERK);
|
||||
DoScriptText(SAY_BERSERK, me);
|
||||
break;
|
||||
case EVENT_RESPAWN_ARM:
|
||||
case EVENT_RESPAWN_LEFT_ARM:
|
||||
{
|
||||
Creature* curArm = Unit::GetCreature(*me, instance ? instance->GetData64(DATA_RIGHT_ARM) : 0);
|
||||
if (!(curArm && curArm->isAlive()))
|
||||
curArm = Unit::GetCreature(*me, instance ? instance->GetData64(DATA_LEFT_ARM) : 0);
|
||||
if (!(curArm && curArm->isAlive()))
|
||||
break;
|
||||
|
||||
curArm->Respawn();
|
||||
curArm->SetInCombatWithZone();
|
||||
curArm->EnterVehicle(me);
|
||||
if (Unit* arm = me->FindNearestCreature(NPC_LEFT_ARM, 20.0f, false))
|
||||
RespawnArm(arm);
|
||||
events.CancelEvent(EVENT_RESPAWN_LEFT_ARM);
|
||||
break;
|
||||
}
|
||||
case EVENT_RESPAWN_RIGHT_ARM:
|
||||
{
|
||||
if (Unit* arm = me->FindNearestCreature(NPC_RIGHT_ARM, 20.0f, false))
|
||||
RespawnArm(arm);
|
||||
events.CancelEvent(EVENT_RESPAWN_RIGHT_ARM);
|
||||
break;
|
||||
}
|
||||
case EVENT_STONE_GRIP:
|
||||
{
|
||||
if (right)
|
||||
{
|
||||
std::list<Unit*> targetList;
|
||||
std::list<Unit*>::const_iterator itr;
|
||||
SelectTargetList(targetList, RAID_MODE(1, 3), SELECT_TARGET_RANDOM, 0.0f, true);
|
||||
for (itr = targetList.begin(); itr != targetList.end(); ++itr)
|
||||
{
|
||||
DoCast((*itr), SPELL_STONE_GRIP, true);
|
||||
/* 10 man: */
|
||||
// Cast 62056 -> HandleAuraLinked (64224) -> Apply 64224 -> Absorb damage
|
||||
// -> Apply Stun with basepoints 64290
|
||||
// Cast 64290 -> Trigger spell (64708) Squeezed Lifeless
|
||||
// -> Periodic damage
|
||||
// Cast 63962 -> Visual
|
||||
}
|
||||
DoScriptText(SAY_GRAB_PLAYER, me);
|
||||
}
|
||||
events.RepeatEvent(25000);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
void RespawnArm(Unit* arm)
|
||||
{
|
||||
arm->ToCreature()->Respawn();
|
||||
arm->ToCreature()->SetInCombatWithZone();
|
||||
|
||||
arm->CastSpell(me, SPELL_ARM_ENTER_VEHICLE, true);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
class npc_right_arm : public CreatureScript
|
||||
class spell_ulduar_rubble_summon : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
npc_right_arm() : CreatureScript("npc_right_arm") { }
|
||||
spell_ulduar_rubble_summon() : SpellScriptLoader("spell_ulduar_rubble_summon") { }
|
||||
|
||||
CreatureAI* GetAI(Creature* pCreature) const
|
||||
class spell_ulduar_rubble_summonSpellScript : public SpellScript
|
||||
{
|
||||
return new npc_right_armAI(pCreature);
|
||||
}
|
||||
PrepareSpellScript(spell_ulduar_rubble_summonSpellScript);
|
||||
|
||||
struct npc_right_armAI : public ScriptedAI
|
||||
{
|
||||
npc_right_armAI(Creature* pCreature) : ScriptedAI(pCreature)
|
||||
void HandleScript(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
pInstance = me->GetInstanceScript();
|
||||
SetCombatMovement(false);
|
||||
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE);
|
||||
Reset();
|
||||
}
|
||||
|
||||
uint32 uiStoneGripTimer;
|
||||
uint64 uiGrippedTargets[3];
|
||||
uint32 uiPermittedDamage;
|
||||
InstanceScript * pInstance;
|
||||
|
||||
void EnterCombat(Unit* /*who*/)
|
||||
{
|
||||
EncounterInCombat(me, pInstance);
|
||||
uiStoneGripTimer = 30000;
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
memset(&uiGrippedTargets, 0, sizeof(uiGrippedTargets));
|
||||
uiPermittedDamage = RAID_MODE(100000, 480000);
|
||||
uiStoneGripTimer = 0;
|
||||
DoCast(SPELL_ARM_VISUAL);
|
||||
}
|
||||
|
||||
void DamageTaken(Unit* /*who*/, uint32& damage)
|
||||
{
|
||||
if (uiGrippedTargets[0] == 0)
|
||||
Unit* caster = GetCaster();
|
||||
if (!caster)
|
||||
return;
|
||||
|
||||
if (damage > uiPermittedDamage)
|
||||
uiPermittedDamage = 0;
|
||||
else
|
||||
uiPermittedDamage -= damage;
|
||||
|
||||
if (!uiPermittedDamage)
|
||||
ReleaseGrabbedPlayers();
|
||||
uint32 spellId = GetEffectValue();
|
||||
for (uint8 i = 0; i < 5; ++i)
|
||||
caster->CastSpell(caster, spellId, true);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*who*/)
|
||||
void Register()
|
||||
{
|
||||
ReleaseGrabbedPlayers();
|
||||
|
||||
if (Creature* Kologarn = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(TYPE_KOLOGARN) : 0))
|
||||
{
|
||||
if (Kologarn->isAlive())
|
||||
{
|
||||
Kologarn->CastSpell(Kologarn, SPELL_ARM_DEAD_DAMAGE, true);
|
||||
DoScriptText(SAY_RIGHT_ARM_GONE, Kologarn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(const uint32 diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (uiStoneGripTimer <= diff)
|
||||
{
|
||||
GrabPlayers();
|
||||
if (Creature* Kologarn = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(TYPE_KOLOGARN) : 0))
|
||||
DoScriptText(SAY_GRAB_PLAYER, Kologarn);
|
||||
|
||||
uiStoneGripTimer = urand(30000, 35000);
|
||||
uiPermittedDamage = RAID_MODE(100000, 480000);
|
||||
}
|
||||
else
|
||||
uiStoneGripTimer -= diff;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
void ReleaseGrabbedPlayers()
|
||||
{
|
||||
for (uint8 i = 0; i < RAID_MODE(1, 3); ++i)
|
||||
if (Unit* grabbed = Unit::GetUnit(*me, uiGrippedTargets[i]))
|
||||
me->CastSpell(grabbed, SPELL_STONE_GRIP_CANCEL, false);
|
||||
}
|
||||
|
||||
void GrabPlayers()
|
||||
{
|
||||
for (uint8 i = 0; i < RAID_MODE(1, 3); ++i)
|
||||
{
|
||||
if (Unit* grabbed = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
|
||||
{
|
||||
DoCast(grabbed, SPELL_STONE_GRIP);
|
||||
uiGrippedTargets[i] = grabbed->GetGUID();
|
||||
}
|
||||
}
|
||||
OnEffect += SpellEffectFn(spell_ulduar_rubble_summonSpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
|
||||
}
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const
|
||||
{
|
||||
return new spell_ulduar_rubble_summonSpellScript();
|
||||
}
|
||||
};
|
||||
|
||||
class npc_left_arm : public CreatureScript
|
||||
class spell_ulduar_cancel_stone_grip : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
npc_left_arm() : CreatureScript("npc_left_arm") { }
|
||||
spell_ulduar_cancel_stone_grip() : SpellScriptLoader("spell_ulduar_cancel_stone_grip") { }
|
||||
|
||||
CreatureAI* GetAI(Creature* pCreature) const
|
||||
class spell_ulduar_cancel_stone_gripSpellScript : public SpellScript
|
||||
{
|
||||
return new npc_left_armAI(pCreature);
|
||||
}
|
||||
PrepareSpellScript(spell_ulduar_cancel_stone_gripSpellScript);
|
||||
|
||||
struct npc_left_armAI : public ScriptedAI
|
||||
{
|
||||
npc_left_armAI(Creature* pCreature) : ScriptedAI(pCreature)
|
||||
void HandleScript(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
pInstance = me->GetInstanceScript();
|
||||
SetCombatMovement(false);
|
||||
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE);
|
||||
Reset();
|
||||
}
|
||||
|
||||
uint32 uiSweepTimer;
|
||||
InstanceScript * pInstance;
|
||||
|
||||
void EnterCombat(Unit* /*who*/)
|
||||
{
|
||||
EncounterInCombat(me, pInstance);
|
||||
uiSweepTimer = 15000;
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
DoCast(SPELL_ARM_VISUAL);
|
||||
EncounterInCombat(me, pInstance);
|
||||
uiSweepTimer = 0;
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*who*/)
|
||||
{
|
||||
if (Creature* Kologarn = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(TYPE_KOLOGARN) : 0))
|
||||
{
|
||||
if (Kologarn->isAlive())
|
||||
{
|
||||
Kologarn->CastSpell(Kologarn, SPELL_ARM_DEAD_DAMAGE, true);
|
||||
DoScriptText(SAY_LEFT_ARM_GONE, Kologarn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(const uint32 diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
Unit* target = this->GetHitPlayer();
|
||||
if (!target)
|
||||
return;
|
||||
|
||||
if (uiSweepTimer <= diff)
|
||||
switch (target->GetMap()->GetDifficulty())
|
||||
{
|
||||
DoCast(SPELL_ARM_SWEEP);
|
||||
uiSweepTimer = urand(15000, 25000);
|
||||
case RAID_DIFFICULTY_10MAN_NORMAL:
|
||||
target->RemoveAura(SpellMgr::CalculateSpellEffectAmount(GetSpellInfo(), EFFECT_0));
|
||||
break;
|
||||
case RAID_DIFFICULTY_25MAN_NORMAL:
|
||||
target->RemoveAura(SpellMgr::CalculateSpellEffectAmount(GetSpellInfo(), EFFECT_1));
|
||||
break;
|
||||
}
|
||||
else
|
||||
uiSweepTimer -= diff;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
void Register()
|
||||
{
|
||||
OnEffect += SpellEffectFn(spell_ulduar_cancel_stone_gripSpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
|
||||
}
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const
|
||||
{
|
||||
return new spell_ulduar_cancel_stone_gripSpellScript();
|
||||
}
|
||||
};
|
||||
|
||||
class spell_ulduar_stone_grip_absorb : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
spell_ulduar_stone_grip_absorb() : SpellScriptLoader("spell_ulduar_stone_grip_absorb") { }
|
||||
|
||||
class spell_ulduar_stone_grip_absorb_AuraScript : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_ulduar_stone_grip_absorb_AuraScript);
|
||||
|
||||
//! This will be called when Right Arm (vehicle) has sustained a specific amount of damage depending on instance mode
|
||||
//! What we do here is remove all harmful aura's related and teleport to safe spot.
|
||||
void OnRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
if (!GetOwner()->ToCreature())
|
||||
return;
|
||||
|
||||
uint32 rubbleStalkerEntry = (GetOwner()->GetMap()->GetDifficulty() == DUNGEON_DIFFICULTY_NORMAL ? 33809 : 33942);
|
||||
Creature* rubbleStalker = GetOwner()->FindNearestCreature(rubbleStalkerEntry, 200.0f, true);
|
||||
if (rubbleStalker)
|
||||
rubbleStalker->CastSpell(rubbleStalker, SPELL_STONE_GRIP_CANCEL, true);
|
||||
}
|
||||
|
||||
void Register()
|
||||
{
|
||||
OnEffectRemove += AuraEffectRemoveFn(spell_ulduar_stone_grip_absorb_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_SCHOOL_ABSORB, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
AuraScript* GetAuraScript() const
|
||||
{
|
||||
return new spell_ulduar_stone_grip_absorb_AuraScript();
|
||||
}
|
||||
};
|
||||
|
||||
class spell_ulduar_stone_grip : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
spell_ulduar_stone_grip() : SpellScriptLoader("spell_ulduar_stone_grip") { }
|
||||
|
||||
class spell_ulduar_stone_grip_AuraScript : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_ulduar_stone_grip_AuraScript);
|
||||
|
||||
void OnRemoveStun(AuraEffect const* aurEff, AuraEffectHandleModes mode)
|
||||
{
|
||||
GetOwner()->ToUnit()->RemoveAurasDueToSpell(SpellMgr::CalculateSpellEffectAmount(GetSpellProto(), EFFECT_2));
|
||||
// Spellsystem doesn't recognize EFFECT_0 as actionable effect on dispel for some reason, manually do it here
|
||||
GetOwner()->ToUnit()->ExitVehicle();
|
||||
GetOwner()->ToUnit()->NearTeleportTo(1756.25f + irand(-3, 3), -8.3f + irand(-3, 3), 448.8f, 3.62f);
|
||||
}
|
||||
|
||||
void Register()
|
||||
{
|
||||
OnEffectRemove += AuraEffectRemoveFn(spell_ulduar_stone_grip_AuraScript::OnRemoveStun, EFFECT_2, SPELL_AURA_MOD_STUN, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
AuraScript* GetAuraScript() const
|
||||
{
|
||||
return new spell_ulduar_stone_grip_AuraScript();
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_kologarn()
|
||||
{
|
||||
new boss_kologarn();
|
||||
new npc_right_arm();
|
||||
new npc_left_arm();
|
||||
new spell_ulduar_rubble_summon();
|
||||
new spell_ulduar_cancel_stone_grip();
|
||||
new spell_ulduar_stone_grip_absorb();
|
||||
new spell_ulduar_stone_grip();
|
||||
}
|
||||
|
||||
@@ -32,8 +32,8 @@ bool CharacterDatabaseConnection::Open()
|
||||
PREPARE_STATEMENT(CHAR_DEL_OLD_GUILD_BANK_EVENT_LOGS, "DELETE FROM guild_bank_eventlog WHERE LogGuid > ?", 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_NONEXISTENT_CHARACTER_GROUP_MEMBERS, "DELETE FROM group_member WHERE NOT EXISTS (SELECT guid FROM characters WHERE guid=memberGuid)", CONNECTION_ASYNC)
|
||||
PREPARE_STATEMENT(CHAR_DEL_LEADERLESS_GROUPS, "DELETE FROM groups WHERE NOT EXISTS (SELECT guid FROM characters WHERE guid=leaderGuid)", CONNECTION_ASYNC)
|
||||
PREPARE_STATEMENT(CHAR_DEL_TINY_GROUPS, "DELETE FROM groups WHERE guid NOT IN (SELECT guid FROM group_member GROUP BY guid HAVING COUNT(guid) > 1)", CONNECTION_ASYNC)
|
||||
PREPARE_STATEMENT(CHAR_DEL_LEADERLESS_GROUPS, "DELETE FROM groups WHERE NOT EXISTS (SELECT guid FROM characters WHERE guid=leaderGuid)", CONNECTION_SYNCH)
|
||||
PREPARE_STATEMENT(CHAR_DEL_TINY_GROUPS, "DELETE FROM groups WHERE guid NOT IN (SELECT guid FROM group_member GROUP BY guid HAVING COUNT(guid) > 1)", CONNECTION_SYNCH)
|
||||
PREPARE_STATEMENT(CHAR_DEL_NONEXISTENT_GROUP_MEMBERS, "DELETE FROM group_member WHERE guid NOT IN (SELECT guid FROM groups)", CONNECTION_ASYNC)
|
||||
PREPARE_STATEMENT(CHAR_DEL_NONEXISTENT_GROUP_INSTANCES, "DELETE FROM group_instance WHERE guid NOT IN (SELECT guid FROM groups)", CONNECTION_ASYNC)
|
||||
PREPARE_STATEMENT(CHAR_DEL_EXPIRED_BANS, "UPDATE character_banned SET active = 0 WHERE unbandate <= UNIX_TIMESTAMP() AND unbandate <> bandate", CONNECTION_ASYNC)
|
||||
|
||||
Reference in New Issue
Block a user