Core/SmartAI: added script type 9 (TimedActionList)
- interrupt spells when entering combat - fixed reset of timers - added npc flag modify actions - added action to call a TimedActionList, default options are: process only OOC and resume after combat --HG-- branch : trunk
This commit is contained in:
@@ -571,6 +571,7 @@ void SmartAI::JustReachedHome()
|
|||||||
|
|
||||||
void SmartAI::EnterCombat(Unit* enemy)
|
void SmartAI::EnterCombat(Unit* enemy)
|
||||||
{
|
{
|
||||||
|
me->InterruptNonMeleeSpells(false);//msut be before ProcessEvents
|
||||||
GetScript()->ProcessEventsFor(SMART_EVENT_AGGRO, enemy);
|
GetScript()->ProcessEventsFor(SMART_EVENT_AGGRO, enemy);
|
||||||
me->GetPosition(&mLastOOCPos);
|
me->GetPosition(&mLastOOCPos);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ SmartScript::SmartScript()
|
|||||||
mTemplate = SMARTAI_TEMPLATE_BASIC;
|
mTemplate = SMARTAI_TEMPLATE_BASIC;
|
||||||
meOrigGUID = 0;
|
meOrigGUID = 0;
|
||||||
goOrigGUID = 0;
|
goOrigGUID = 0;
|
||||||
|
mResumeActionList = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SmartScript::OnReset()
|
void SmartScript::OnReset()
|
||||||
@@ -59,8 +60,7 @@ void SmartScript::OnReset()
|
|||||||
ResetBaseObject();
|
ResetBaseObject();
|
||||||
for (SmartAIEventList::iterator i = mEvents.begin(); i != mEvents.end(); ++i)
|
for (SmartAIEventList::iterator i = mEvents.begin(); i != mEvents.end(); ++i)
|
||||||
{
|
{
|
||||||
if ((*i).GetEventType() == SMART_EVENT_UPDATE_OOC || (*i).GetEventType() == SMART_EVENT_UPDATE)
|
InitTimer((*i));
|
||||||
RecalcTimer((*i), (*i).event.minMaxRepeat.min, (*i).event.minMaxRepeat.max);
|
|
||||||
(*i).runOnce = false;
|
(*i).runOnce = false;
|
||||||
}
|
}
|
||||||
ProcessEventsFor(SMART_EVENT_RESET);
|
ProcessEventsFor(SMART_EVENT_RESET);
|
||||||
@@ -68,10 +68,27 @@ void SmartScript::OnReset()
|
|||||||
|
|
||||||
void SmartScript::ProcessEventsFor(SMART_EVENT e, Unit* unit, uint32 var0, uint32 var1, bool bvar, const SpellEntry* spell, GameObject* gob)
|
void SmartScript::ProcessEventsFor(SMART_EVENT e, Unit* unit, uint32 var0, uint32 var1, bool bvar, const SpellEntry* spell, GameObject* gob)
|
||||||
{
|
{
|
||||||
|
if (e == SMART_EVENT_AGGRO)
|
||||||
|
{
|
||||||
|
if (!mResumeActionList)
|
||||||
|
mTimedActionList.clear();//clear action list if it is not resumable
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (SmartAIEventList::iterator itr = mTimedActionList.begin(); itr != mTimedActionList.end(); ++itr)
|
||||||
|
{
|
||||||
|
if (itr->enableTimed)
|
||||||
|
{
|
||||||
|
InitTimer((*itr));//re-init the currently enabled timer, so it restarts the timer when resumed
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
for (SmartAIEventList::iterator i = mEvents.begin(); i != mEvents.end(); ++i)
|
for (SmartAIEventList::iterator i = mEvents.begin(); i != mEvents.end(); ++i)
|
||||||
{
|
{
|
||||||
if ((*i).GetEventType() == SMART_EVENT_LINK)//special handling
|
if ((*i).GetEventType() == SMART_EVENT_LINK)//special handling
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if ((*i).GetEventType() == e/* && (!(*i).event.event_phase_mask || IsInPhase((*i).event.event_phase_mask)) && !((*i).event.event_flags & SMART_EVENT_FLAG_NOT_REPEATABLE && (*i).runOnce)*/)
|
if ((*i).GetEventType() == e/* && (!(*i).event.event_phase_mask || IsInPhase((*i).event.event_phase_mask)) && !((*i).event.event_flags & SMART_EVENT_FLAG_NOT_REPEATABLE && (*i).runOnce)*/)
|
||||||
ProcessEvent(*i, unit, var0, var1, bvar, spell, gob);
|
ProcessEvent(*i, unit, var0, var1, bvar, spell, gob);
|
||||||
}
|
}
|
||||||
@@ -989,6 +1006,57 @@ void SmartScript::ProcessAction(SmartScriptHolder &e, Unit* unit, uint32 var0, u
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case SMART_ACTION_CALL_TIMED_ACTIONLIST:
|
||||||
|
{
|
||||||
|
mTimedActionList.clear();
|
||||||
|
mTimedActionList = sSmartScriptMgr.GetScript(e.action.timedActionList.id, SMART_SCRIPT_TYPE_TIMED_ACTIONLIST);
|
||||||
|
if (mTimedActionList.empty())
|
||||||
|
return;
|
||||||
|
for (SmartAIEventList::iterator i = mTimedActionList.begin(); i != mTimedActionList.end(); ++i)
|
||||||
|
{
|
||||||
|
if (i == mTimedActionList.begin())
|
||||||
|
{
|
||||||
|
i->enableTimed = true;//enable processing only for the first action
|
||||||
|
}
|
||||||
|
else i->enableTimed = false;
|
||||||
|
|
||||||
|
//i->event.type = SMART_EVENT_UPDATE_IC;//default value
|
||||||
|
if (e.action.timedActionList.timerType == 1)
|
||||||
|
i->event.type = SMART_EVENT_UPDATE_IC;
|
||||||
|
else if (e.action.timedActionList.timerType > 1)
|
||||||
|
i->event.type = SMART_EVENT_UPDATE;
|
||||||
|
mResumeActionList = e.action.timedActionList.dontResume ? false : true;
|
||||||
|
InitTimer((*i));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SMART_ACTION_SET_NPC_FLAG:
|
||||||
|
{
|
||||||
|
ObjectList* targets = GetTargets(e, unit);
|
||||||
|
if (!targets) return;
|
||||||
|
for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); itr++)
|
||||||
|
if (IsUnit((*itr)))
|
||||||
|
(*itr)->ToUnit()->SetUInt32Value(UNIT_NPC_FLAGS, e.action.unitFlag.flag);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SMART_ACTION_ADD_NPC_FLAG:
|
||||||
|
{
|
||||||
|
ObjectList* targets = GetTargets(e, unit);
|
||||||
|
if (!targets) return;
|
||||||
|
for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); itr++)
|
||||||
|
if (IsUnit((*itr)))
|
||||||
|
(*itr)->ToUnit()->SetFlag(UNIT_NPC_FLAGS, e.action.unitFlag.flag);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SMART_ACTION_REMOVE_NPC_FLAG:
|
||||||
|
{
|
||||||
|
ObjectList* targets = GetTargets(e, unit);
|
||||||
|
if (!targets) return;
|
||||||
|
for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); itr++)
|
||||||
|
if (IsUnit((*itr)))
|
||||||
|
(*itr)->ToUnit()->RemoveFlag(UNIT_NPC_FLAGS, e.action.unitFlag.flag);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
sLog.outErrorDb("SmartScript::ProcessAction: Unhandled Action type %u", e.GetActionType());
|
sLog.outErrorDb("SmartScript::ProcessAction: Unhandled Action type %u", e.GetActionType());
|
||||||
break;
|
break;
|
||||||
@@ -1738,6 +1806,11 @@ void SmartScript::UpdateTimer(SmartScriptHolder &e, const uint32 diff)
|
|||||||
return;
|
return;
|
||||||
if (e.event.event_phase_mask && !IsInPhase(e.event.event_phase_mask))
|
if (e.event.event_phase_mask && !IsInPhase(e.event.event_phase_mask))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (e.GetEventType() == SMART_EVENT_UPDATE_IC && (!me || !me->isInCombat()))
|
||||||
|
return;
|
||||||
|
if (e.GetEventType() == SMART_EVENT_UPDATE_OOC && (me && me->isInCombat()))//can be used with me=NULL (go script)
|
||||||
|
return;
|
||||||
if (e.timer < diff)
|
if (e.timer < diff)
|
||||||
{
|
{
|
||||||
e.active = true;//activate events with cooldown
|
e.active = true;//activate events with cooldown
|
||||||
@@ -1757,8 +1830,23 @@ void SmartScript::UpdateTimer(SmartScriptHolder &e, const uint32 diff)
|
|||||||
case SMART_EVENT_FRIENDLY_MISSING_BUFF:
|
case SMART_EVENT_FRIENDLY_MISSING_BUFF:
|
||||||
case SMART_EVENT_HAS_AURA:
|
case SMART_EVENT_HAS_AURA:
|
||||||
case SMART_EVENT_TARGET_BUFFED:
|
case SMART_EVENT_TARGET_BUFFED:
|
||||||
|
{
|
||||||
ProcessEvent(e);
|
ProcessEvent(e);
|
||||||
|
if (e.GetScriptType() == SMART_SCRIPT_TYPE_TIMED_ACTIONLIST)
|
||||||
|
{
|
||||||
|
e.enableTimed = false;//disable event if it is in an ActionList and was processed once
|
||||||
|
for (SmartAIEventList::iterator i = mTimedActionList.begin(); i != mTimedActionList.end(); ++i)
|
||||||
|
{
|
||||||
|
//find the first event which is not the current one and enable it
|
||||||
|
if (i->event_id > e.event_id)
|
||||||
|
{
|
||||||
|
i->enableTimed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else e.timer -= diff;
|
} else e.timer -= diff;
|
||||||
}
|
}
|
||||||
@@ -1796,6 +1884,21 @@ void SmartScript::OnUpdate(const uint32 diff)
|
|||||||
UpdateTimer((*i), diff);
|
UpdateTimer((*i), diff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
bool needCleanup = true;
|
||||||
|
if (!mTimedActionList.empty())
|
||||||
|
{
|
||||||
|
for (SmartAIEventList::iterator i = mTimedActionList.begin(); i != mTimedActionList.end(); ++i)
|
||||||
|
{
|
||||||
|
if ((*i).enableTimed)
|
||||||
|
{
|
||||||
|
UpdateTimer((*i), diff);
|
||||||
|
needCleanup = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (needCleanup)
|
||||||
|
mTimedActionList.clear();
|
||||||
|
|
||||||
if (!mRemIDs.empty())
|
if (!mRemIDs.empty())
|
||||||
{
|
{
|
||||||
for (std::list<uint32>::iterator i = mRemIDs.begin(); i != mRemIDs.end(); ++i)
|
for (std::list<uint32>::iterator i = mRemIDs.begin(); i != mRemIDs.end(); ++i)
|
||||||
|
|||||||
@@ -193,6 +193,8 @@ class SmartScript
|
|||||||
|
|
||||||
SmartAIEventList mEvents;
|
SmartAIEventList mEvents;
|
||||||
SmartAIEventList mInstallEvents;
|
SmartAIEventList mInstallEvents;
|
||||||
|
SmartAIEventList mTimedActionList;
|
||||||
|
bool mResumeActionList;
|
||||||
Creature* me;
|
Creature* me;
|
||||||
uint64 meOrigGUID;
|
uint64 meOrigGUID;
|
||||||
GameObject* go;
|
GameObject* go;
|
||||||
|
|||||||
@@ -159,6 +159,8 @@ void SmartAIMgr::LoadSmartAIFromDB()
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case SMART_SCRIPT_TYPE_TIMED_ACTIONLIST:
|
||||||
|
break;//nothing to check, really
|
||||||
default:
|
default:
|
||||||
sLog.outErrorDb("SmartAIMgr::LoadSmartAIFromDB: not yet implemented source_type %u", (uint32)source_type);
|
sLog.outErrorDb("SmartAIMgr::LoadSmartAIFromDB: not yet implemented source_type %u", (uint32)source_type);
|
||||||
continue;
|
continue;
|
||||||
@@ -284,14 +286,15 @@ bool SmartAIMgr::IsTargetValid(SmartScriptHolder e)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SmartAIMgr::IsEventValid(SmartScriptHolder e)
|
bool SmartAIMgr::IsEventValid(SmartScriptHolder &e)
|
||||||
{
|
{
|
||||||
if (e.event.type >= SMART_EVENT_END)
|
if (e.event.type >= SMART_EVENT_END)
|
||||||
{
|
{
|
||||||
sLog.outErrorDb("SmartAIMgr: EntryOrGuid %d using event(%u) has invalid event type (%u), skipped.", e.entryOrGuid, e.event_id, e.GetEventType());
|
sLog.outErrorDb("SmartAIMgr: EntryOrGuid %d using event(%u) has invalid event type (%u), skipped.", e.entryOrGuid, e.event_id, e.GetEventType());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!(SmartAIEventMask[e.event.type][1] & SmartAITypeMask[e.GetScriptType()][1]))
|
// in SMART_SCRIPT_TYPE_TIMED_ACTIONLIST all event types are overriden by core
|
||||||
|
if (e.GetScriptType() != SMART_SCRIPT_TYPE_TIMED_ACTIONLIST && !(SmartAIEventMask[e.event.type][1] & SmartAITypeMask[e.GetScriptType()][1]))
|
||||||
{
|
{
|
||||||
sLog.outErrorDb("SmartAIMgr: EntryOrGuid %d, event type %u can not be used for Script type %u", e.entryOrGuid, e.GetEventType(), e.GetScriptType());
|
sLog.outErrorDb("SmartAIMgr: EntryOrGuid %d, event type %u can not be used for Script type %u", e.entryOrGuid, e.GetEventType(), e.GetScriptType());
|
||||||
return false;
|
return false;
|
||||||
@@ -306,173 +309,183 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder e)
|
|||||||
sLog.outErrorDb("SmartAIMgr: EntryOrGuid %d using event(%u) has invalid phase mask (%u), skipped.", e.entryOrGuid, e.event_id, e.event.event_phase_mask);
|
sLog.outErrorDb("SmartAIMgr: EntryOrGuid %d using event(%u) has invalid phase mask (%u), skipped.", e.entryOrGuid, e.event_id, e.event.event_phase_mask);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
switch (e.event.type)
|
if (e.GetScriptType() == SMART_SCRIPT_TYPE_TIMED_ACTIONLIST)
|
||||||
{
|
{
|
||||||
case SMART_EVENT_UPDATE:
|
e.event.type = SMART_EVENT_UPDATE_OOC;//force default OOC, can change when calling the script!
|
||||||
case SMART_EVENT_UPDATE_IC:
|
if (!IsMinMaxValid(e, e.event.minMaxRepeat.min, e.event.minMaxRepeat.max)) return false;
|
||||||
case SMART_EVENT_UPDATE_OOC:
|
if (!IsMinMaxValid(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax)) return false;
|
||||||
case SMART_EVENT_HEALT_PCT:
|
|
||||||
case SMART_EVENT_MANA_PCT:
|
|
||||||
case SMART_EVENT_TARGET_HEALTH_PCT:
|
|
||||||
case SMART_EVENT_TARGET_MANA_PCT:
|
|
||||||
case SMART_EVENT_RANGE:
|
|
||||||
case SMART_EVENT_DAMAGED:
|
|
||||||
case SMART_EVENT_DAMAGED_TARGET:
|
|
||||||
case SMART_EVENT_RECEIVE_HEAL:
|
|
||||||
if (!IsMinMaxValid(e, e.event.minMaxRepeat.min, e.event.minMaxRepeat.max)) return false;
|
|
||||||
if (!IsMinMaxValid(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax)) return false;
|
|
||||||
break;
|
|
||||||
case SMART_EVENT_SPELLHIT:
|
|
||||||
case SMART_EVENT_SPELLHIT_TARGET:
|
|
||||||
if (e.event.spellHit.spell)
|
|
||||||
{
|
|
||||||
SpellEntry const* pSpell = sSpellStore.LookupEntry(e.event.spellHit.spell);
|
|
||||||
if (!pSpell)
|
|
||||||
{
|
|
||||||
sLog.outErrorDb("SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses non-existent Spell entry %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.event.spellHit.spell);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (e.event.spellHit.school && (e.event.spellHit.school & pSpell->SchoolMask) != pSpell->SchoolMask)
|
|
||||||
{
|
|
||||||
sLog.outErrorDb("SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses Spell entry %u with invalid school mask, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.event.spellHit.spell);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!IsMinMaxValid(e, e.event.spellHit.cooldownMin, e.event.spellHit.cooldownMax)) return false;
|
|
||||||
break;
|
|
||||||
case SMART_EVENT_OOC_LOS:
|
|
||||||
case SMART_EVENT_IC_LOS:
|
|
||||||
if (!IsMinMaxValid(e, e.event.los.cooldownMin, e.event.los.cooldownMax)) return false;
|
|
||||||
break;
|
|
||||||
case SMART_EVENT_RESPAWN:
|
|
||||||
if (e.event.respawn.type == SMART_SCRIPT_RESPAWN_CONDITION_MAP && !sMapStore.LookupEntry(e.event.respawn.map))
|
|
||||||
{
|
|
||||||
sLog.outErrorDb("SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses non-existent Map entry %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.event.respawn.map);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (e.event.respawn.type == SMART_SCRIPT_RESPAWN_CONDITION_AREA && !GetAreaEntryByAreaID(e.event.respawn.area))
|
|
||||||
{
|
|
||||||
sLog.outErrorDb("SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses non-existent Area entry %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.event.respawn.area);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case SMART_EVENT_FRIENDLY_HEALTH:
|
|
||||||
if (!NotNULL(e, e.event.friendlyHealt.radius)) return false;
|
|
||||||
if (!IsMinMaxValid(e, e.event.friendlyHealt.repeatMin, e.event.friendlyHealt.repeatMax)) return false;
|
|
||||||
break;
|
|
||||||
case SMART_EVENT_FRIENDLY_IS_CC:
|
|
||||||
if (!IsMinMaxValid(e, e.event.friendlyCC.repeatMin, e.event.friendlyCC.repeatMax)) return false;
|
|
||||||
break;
|
|
||||||
case SMART_EVENT_FRIENDLY_MISSING_BUFF:
|
|
||||||
{
|
|
||||||
if (!IsSpellValid(e, e.event.missingBuff.spell)) return false;
|
|
||||||
if (!NotNULL(e, e.event.missingBuff.radius)) return false;
|
|
||||||
if (!IsMinMaxValid(e, e.event.missingBuff.repeatMin, e.event.missingBuff.repeatMax)) return false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SMART_EVENT_KILL:
|
|
||||||
if (!IsMinMaxValid(e, e.event.kill.cooldownMin, e.event.kill.cooldownMax)) return false;
|
|
||||||
if (e.event.kill.creature && !IsCreatureValid(e, e.event.kill.creature)) return false;
|
|
||||||
break;
|
|
||||||
case SMART_EVENT_TARGET_CASTING:
|
|
||||||
case SMART_EVENT_PASSENGER_BOARDED:
|
|
||||||
case SMART_EVENT_PASSENGER_REMOVED:
|
|
||||||
if (!IsMinMaxValid(e, e.event.minMax.repeatMin, e.event.minMax.repeatMax)) return false;
|
|
||||||
break;
|
|
||||||
case SMART_EVENT_SUMMON_DESPAWNED:
|
|
||||||
case SMART_EVENT_SUMMONED_UNIT:
|
|
||||||
if (e.event.summoned.creature && !IsCreatureValid(e, e.event.summoned.creature)) return false;
|
|
||||||
if (!IsMinMaxValid(e, e.event.summoned.cooldownMin, e.event.summoned.cooldownMax)) return false;
|
|
||||||
break;
|
|
||||||
case SMART_EVENT_ACCEPTED_QUEST:
|
|
||||||
case SMART_EVENT_REWARD_QUEST:
|
|
||||||
if (!IsQuestValid(e, e.event.quest.quest)) return false;
|
|
||||||
break;
|
|
||||||
case SMART_EVENT_RECEIVE_EMOTE:
|
|
||||||
{
|
|
||||||
if (e.event.emote.emote && !IsEmoteValid(e, e.event.emote.emote)) return false;
|
|
||||||
if (!IsMinMaxValid(e, e.event.emote.cooldownMin, e.event.emote.cooldownMax)) return false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SMART_EVENT_HAS_AURA:
|
|
||||||
case SMART_EVENT_TARGET_BUFFED:
|
|
||||||
{
|
|
||||||
if (!IsSpellValid(e, e.event.aura.spell)) return false;
|
|
||||||
if (!IsMinMaxValid(e, e.event.aura.repeatMin, e.event.aura.repeatMax)) return false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SMART_EVENT_TRANSPORT_ADDCREATURE:
|
|
||||||
{
|
|
||||||
if (e.event.transportAddCreature.creature && !IsCreatureValid(e, e.event.transportAddCreature.creature)) return false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SMART_EVENT_MOVEMENTINFORM:
|
|
||||||
{
|
|
||||||
if (e.event.movementInform.type > NULL_MOTION_TYPE)
|
|
||||||
{
|
|
||||||
sLog.outErrorDb("SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses invalid Motion type %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.event.movementInform.type);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SMART_EVENT_DATA_SET:
|
|
||||||
{
|
|
||||||
if (!IsMinMaxValid(e, e.event.dataSet.cooldownMin, e.event.dataSet.cooldownMax)) return false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SMART_EVENT_AREATRIGGER_ONTRIGGER:
|
|
||||||
{
|
|
||||||
if (e.event.areatrigger.id && !IsAreaTriggerValid(e, e.event.areatrigger.id)) return false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SMART_EVENT_TEXT_OVER:
|
|
||||||
//if (e.event.textOver.textGroupID && !IsTextValid(e, e.event.textOver.textGroupID)) return false;// 0 is a valid text group!
|
|
||||||
break;
|
|
||||||
case SMART_EVENT_LINK:
|
|
||||||
{
|
|
||||||
if (e.link && e.link == e.event_id)
|
|
||||||
{
|
|
||||||
sLog.outErrorDb("SmartAIMgr: Entry %d SourceType %u, Event %u, Link Event is linking self (infinite loop), skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SMART_EVENT_TIMED_EVENT_TRIGGERED:
|
|
||||||
case SMART_EVENT_INSTANCE_PLAYER_ENTER:
|
|
||||||
case SMART_EVENT_TRANSPORT_RELOCATE:
|
|
||||||
case SMART_EVENT_CHARMED:
|
|
||||||
case SMART_EVENT_CHARMED_TARGET:
|
|
||||||
case SMART_EVENT_CORPSE_REMOVED:
|
|
||||||
case SMART_EVENT_AI_INIT:
|
|
||||||
case SMART_EVENT_TRANSPORT_ADDPLAYER:
|
|
||||||
case SMART_EVENT_TRANSPORT_REMOVE_PLAYER:
|
|
||||||
case SMART_EVENT_AGGRO:
|
|
||||||
case SMART_EVENT_DEATH:
|
|
||||||
case SMART_EVENT_EVADE:
|
|
||||||
case SMART_EVENT_REACHED_HOME:
|
|
||||||
case SMART_EVENT_RESET:
|
|
||||||
case SMART_EVENT_QUEST_ACCEPTED:
|
|
||||||
case SMART_EVENT_QUEST_OBJ_COPLETETION:
|
|
||||||
case SMART_EVENT_QUEST_COMPLETION:
|
|
||||||
case SMART_EVENT_QUEST_REWARDED:
|
|
||||||
case SMART_EVENT_QUEST_FAIL:
|
|
||||||
case SMART_EVENT_JUST_SUMMONED:
|
|
||||||
case SMART_EVENT_WAYPOINT_START:
|
|
||||||
case SMART_EVENT_WAYPOINT_REACHED:
|
|
||||||
case SMART_EVENT_WAYPOINT_PAUSED:
|
|
||||||
case SMART_EVENT_WAYPOINT_RESUMED:
|
|
||||||
case SMART_EVENT_WAYPOINT_STOPPED:
|
|
||||||
case SMART_EVENT_WAYPOINT_ENDED:
|
|
||||||
case SMART_ACTION_PLAYMOVIE:
|
|
||||||
case SMART_EVENT_GOSSIP_SELECT:
|
|
||||||
case SMART_EVENT_GOSSIP_HELLO:
|
|
||||||
case SMART_EVENT_JUST_CREATED:
|
|
||||||
case SMART_EVENT_FOLLOW_COPMLETE:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
sLog.outErrorDb("SmartAIMgr: Not handled event_type(%u), Entry %d SourceType %u Event %u Action %u, skipped.", e.GetEventType(), e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType());
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (e.event.type)
|
||||||
|
{
|
||||||
|
case SMART_EVENT_UPDATE:
|
||||||
|
case SMART_EVENT_UPDATE_IC:
|
||||||
|
case SMART_EVENT_UPDATE_OOC:
|
||||||
|
case SMART_EVENT_HEALT_PCT:
|
||||||
|
case SMART_EVENT_MANA_PCT:
|
||||||
|
case SMART_EVENT_TARGET_HEALTH_PCT:
|
||||||
|
case SMART_EVENT_TARGET_MANA_PCT:
|
||||||
|
case SMART_EVENT_RANGE:
|
||||||
|
case SMART_EVENT_DAMAGED:
|
||||||
|
case SMART_EVENT_DAMAGED_TARGET:
|
||||||
|
case SMART_EVENT_RECEIVE_HEAL:
|
||||||
|
if (!IsMinMaxValid(e, e.event.minMaxRepeat.min, e.event.minMaxRepeat.max)) return false;
|
||||||
|
if (!IsMinMaxValid(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax)) return false;
|
||||||
|
break;
|
||||||
|
case SMART_EVENT_SPELLHIT:
|
||||||
|
case SMART_EVENT_SPELLHIT_TARGET:
|
||||||
|
if (e.event.spellHit.spell)
|
||||||
|
{
|
||||||
|
SpellEntry const* pSpell = sSpellStore.LookupEntry(e.event.spellHit.spell);
|
||||||
|
if (!pSpell)
|
||||||
|
{
|
||||||
|
sLog.outErrorDb("SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses non-existent Spell entry %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.event.spellHit.spell);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (e.event.spellHit.school && (e.event.spellHit.school & pSpell->SchoolMask) != pSpell->SchoolMask)
|
||||||
|
{
|
||||||
|
sLog.outErrorDb("SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses Spell entry %u with invalid school mask, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.event.spellHit.spell);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!IsMinMaxValid(e, e.event.spellHit.cooldownMin, e.event.spellHit.cooldownMax)) return false;
|
||||||
|
break;
|
||||||
|
case SMART_EVENT_OOC_LOS:
|
||||||
|
case SMART_EVENT_IC_LOS:
|
||||||
|
if (!IsMinMaxValid(e, e.event.los.cooldownMin, e.event.los.cooldownMax)) return false;
|
||||||
|
break;
|
||||||
|
case SMART_EVENT_RESPAWN:
|
||||||
|
if (e.event.respawn.type == SMART_SCRIPT_RESPAWN_CONDITION_MAP && !sMapStore.LookupEntry(e.event.respawn.map))
|
||||||
|
{
|
||||||
|
sLog.outErrorDb("SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses non-existent Map entry %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.event.respawn.map);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (e.event.respawn.type == SMART_SCRIPT_RESPAWN_CONDITION_AREA && !GetAreaEntryByAreaID(e.event.respawn.area))
|
||||||
|
{
|
||||||
|
sLog.outErrorDb("SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses non-existent Area entry %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.event.respawn.area);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SMART_EVENT_FRIENDLY_HEALTH:
|
||||||
|
if (!NotNULL(e, e.event.friendlyHealt.radius)) return false;
|
||||||
|
if (!IsMinMaxValid(e, e.event.friendlyHealt.repeatMin, e.event.friendlyHealt.repeatMax)) return false;
|
||||||
|
break;
|
||||||
|
case SMART_EVENT_FRIENDLY_IS_CC:
|
||||||
|
if (!IsMinMaxValid(e, e.event.friendlyCC.repeatMin, e.event.friendlyCC.repeatMax)) return false;
|
||||||
|
break;
|
||||||
|
case SMART_EVENT_FRIENDLY_MISSING_BUFF:
|
||||||
|
{
|
||||||
|
if (!IsSpellValid(e, e.event.missingBuff.spell)) return false;
|
||||||
|
if (!NotNULL(e, e.event.missingBuff.radius)) return false;
|
||||||
|
if (!IsMinMaxValid(e, e.event.missingBuff.repeatMin, e.event.missingBuff.repeatMax)) return false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SMART_EVENT_KILL:
|
||||||
|
if (!IsMinMaxValid(e, e.event.kill.cooldownMin, e.event.kill.cooldownMax)) return false;
|
||||||
|
if (e.event.kill.creature && !IsCreatureValid(e, e.event.kill.creature)) return false;
|
||||||
|
break;
|
||||||
|
case SMART_EVENT_TARGET_CASTING:
|
||||||
|
case SMART_EVENT_PASSENGER_BOARDED:
|
||||||
|
case SMART_EVENT_PASSENGER_REMOVED:
|
||||||
|
if (!IsMinMaxValid(e, e.event.minMax.repeatMin, e.event.minMax.repeatMax)) return false;
|
||||||
|
break;
|
||||||
|
case SMART_EVENT_SUMMON_DESPAWNED:
|
||||||
|
case SMART_EVENT_SUMMONED_UNIT:
|
||||||
|
if (e.event.summoned.creature && !IsCreatureValid(e, e.event.summoned.creature)) return false;
|
||||||
|
if (!IsMinMaxValid(e, e.event.summoned.cooldownMin, e.event.summoned.cooldownMax)) return false;
|
||||||
|
break;
|
||||||
|
case SMART_EVENT_ACCEPTED_QUEST:
|
||||||
|
case SMART_EVENT_REWARD_QUEST:
|
||||||
|
if (!IsQuestValid(e, e.event.quest.quest)) return false;
|
||||||
|
break;
|
||||||
|
case SMART_EVENT_RECEIVE_EMOTE:
|
||||||
|
{
|
||||||
|
if (e.event.emote.emote && !IsEmoteValid(e, e.event.emote.emote)) return false;
|
||||||
|
if (!IsMinMaxValid(e, e.event.emote.cooldownMin, e.event.emote.cooldownMax)) return false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SMART_EVENT_HAS_AURA:
|
||||||
|
case SMART_EVENT_TARGET_BUFFED:
|
||||||
|
{
|
||||||
|
if (!IsSpellValid(e, e.event.aura.spell)) return false;
|
||||||
|
if (!IsMinMaxValid(e, e.event.aura.repeatMin, e.event.aura.repeatMax)) return false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SMART_EVENT_TRANSPORT_ADDCREATURE:
|
||||||
|
{
|
||||||
|
if (e.event.transportAddCreature.creature && !IsCreatureValid(e, e.event.transportAddCreature.creature)) return false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SMART_EVENT_MOVEMENTINFORM:
|
||||||
|
{
|
||||||
|
if (e.event.movementInform.type > NULL_MOTION_TYPE)
|
||||||
|
{
|
||||||
|
sLog.outErrorDb("SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses invalid Motion type %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.event.movementInform.type);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SMART_EVENT_DATA_SET:
|
||||||
|
{
|
||||||
|
if (!IsMinMaxValid(e, e.event.dataSet.cooldownMin, e.event.dataSet.cooldownMax)) return false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SMART_EVENT_AREATRIGGER_ONTRIGGER:
|
||||||
|
{
|
||||||
|
if (e.event.areatrigger.id && !IsAreaTriggerValid(e, e.event.areatrigger.id)) return false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SMART_EVENT_TEXT_OVER:
|
||||||
|
//if (e.event.textOver.textGroupID && !IsTextValid(e, e.event.textOver.textGroupID)) return false;// 0 is a valid text group!
|
||||||
|
break;
|
||||||
|
case SMART_EVENT_LINK:
|
||||||
|
{
|
||||||
|
if (e.link && e.link == e.event_id)
|
||||||
|
{
|
||||||
|
sLog.outErrorDb("SmartAIMgr: Entry %d SourceType %u, Event %u, Link Event is linking self (infinite loop), skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SMART_EVENT_TIMED_EVENT_TRIGGERED:
|
||||||
|
case SMART_EVENT_INSTANCE_PLAYER_ENTER:
|
||||||
|
case SMART_EVENT_TRANSPORT_RELOCATE:
|
||||||
|
case SMART_EVENT_CHARMED:
|
||||||
|
case SMART_EVENT_CHARMED_TARGET:
|
||||||
|
case SMART_EVENT_CORPSE_REMOVED:
|
||||||
|
case SMART_EVENT_AI_INIT:
|
||||||
|
case SMART_EVENT_TRANSPORT_ADDPLAYER:
|
||||||
|
case SMART_EVENT_TRANSPORT_REMOVE_PLAYER:
|
||||||
|
case SMART_EVENT_AGGRO:
|
||||||
|
case SMART_EVENT_DEATH:
|
||||||
|
case SMART_EVENT_EVADE:
|
||||||
|
case SMART_EVENT_REACHED_HOME:
|
||||||
|
case SMART_EVENT_RESET:
|
||||||
|
case SMART_EVENT_QUEST_ACCEPTED:
|
||||||
|
case SMART_EVENT_QUEST_OBJ_COPLETETION:
|
||||||
|
case SMART_EVENT_QUEST_COMPLETION:
|
||||||
|
case SMART_EVENT_QUEST_REWARDED:
|
||||||
|
case SMART_EVENT_QUEST_FAIL:
|
||||||
|
case SMART_EVENT_JUST_SUMMONED:
|
||||||
|
case SMART_EVENT_WAYPOINT_START:
|
||||||
|
case SMART_EVENT_WAYPOINT_REACHED:
|
||||||
|
case SMART_EVENT_WAYPOINT_PAUSED:
|
||||||
|
case SMART_EVENT_WAYPOINT_RESUMED:
|
||||||
|
case SMART_EVENT_WAYPOINT_STOPPED:
|
||||||
|
case SMART_EVENT_WAYPOINT_ENDED:
|
||||||
|
case SMART_ACTION_PLAYMOVIE:
|
||||||
|
case SMART_EVENT_GOSSIP_SELECT:
|
||||||
|
case SMART_EVENT_GOSSIP_HELLO:
|
||||||
|
case SMART_EVENT_JUST_CREATED:
|
||||||
|
case SMART_EVENT_FOLLOW_COPMLETE:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sLog.outErrorDb("SmartAIMgr: Not handled event_type(%u), Entry %d SourceType %u Event %u Action %u, skipped.", e.GetEventType(), e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (e.GetActionType())
|
switch (e.GetActionType())
|
||||||
{
|
{
|
||||||
case SMART_ACTION_TALK:
|
case SMART_ACTION_TALK:
|
||||||
@@ -735,6 +748,10 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder e)
|
|||||||
case SMART_ACTION_CALL_SCRIPT_RESET:
|
case SMART_ACTION_CALL_SCRIPT_RESET:
|
||||||
case SMART_ACTION_ENTER_VEHICLE:
|
case SMART_ACTION_ENTER_VEHICLE:
|
||||||
case SMART_ACTION_NONE:
|
case SMART_ACTION_NONE:
|
||||||
|
case SMART_ACTION_CALL_TIMED_ACTIONLIST:
|
||||||
|
case SMART_ACTION_SET_NPC_FLAG:
|
||||||
|
case SMART_ACTION_ADD_NPC_FLAG:
|
||||||
|
case SMART_ACTION_REMOVE_NPC_FLAG:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sLog.outErrorDb("SmartAIMgr: Not handled action_type(%u), Entry %d SourceType %u Event %u, skipped.", e.GetActionType(), e.GetEventType(), e.entryOrGuid, e.GetScriptType(), e.event_id);
|
sLog.outErrorDb("SmartAIMgr: Not handled action_type(%u), Entry %d SourceType %u Event %u, skipped.", e.GetActionType(), e.GetEventType(), e.entryOrGuid, e.GetScriptType(), e.event_id);
|
||||||
|
|||||||
@@ -345,7 +345,7 @@ enum SMART_SCRIPT_RESPAWN_CONDITION
|
|||||||
enum SMART_ACTION
|
enum SMART_ACTION
|
||||||
{
|
{
|
||||||
SMART_ACTION_NONE = 0, // No action
|
SMART_ACTION_NONE = 0, // No action
|
||||||
SMART_ACTION_TALK = 1, // groupID from creature_text
|
SMART_ACTION_TALK = 1, // groupID from creature_text, duration to wait before TEXT_OVER event is triggered
|
||||||
SMART_ACTION_SET_FACTION = 2, // FactionId (or 0 for default)
|
SMART_ACTION_SET_FACTION = 2, // FactionId (or 0 for default)
|
||||||
SMART_ACTION_MORPH_TO_ENTRY_OR_MODEL = 3, // Creature_template entry(param1) OR ModelId (param2) (or 0 for both to demorph)
|
SMART_ACTION_MORPH_TO_ENTRY_OR_MODEL = 3, // Creature_template entry(param1) OR ModelId (param2) (or 0 for both to demorph)
|
||||||
SMART_ACTION_SOUND = 4, // SoundId, TextRange
|
SMART_ACTION_SOUND = 4, // SoundId, TextRange
|
||||||
@@ -426,7 +426,12 @@ enum SMART_ACTION
|
|||||||
SMART_ACTION_RESET_SCRIPT_BASE_OBJECT = 77, // none
|
SMART_ACTION_RESET_SCRIPT_BASE_OBJECT = 77, // none
|
||||||
SMART_ACTION_CALL_SCRIPT_RESET = 78, // none
|
SMART_ACTION_CALL_SCRIPT_RESET = 78, // none
|
||||||
SMART_ACTION_ENTER_VEHICLE = 79, // seatID
|
SMART_ACTION_ENTER_VEHICLE = 79, // seatID
|
||||||
SMART_ACTION_END = 80,
|
SMART_ACTION_CALL_TIMED_ACTIONLIST = 80, // ID (overwrites already running actionlist), stop after combat?(0/1), timer update type(0-OOC, 1-IC, 2-ALWAYS)
|
||||||
|
SMART_ACTION_SET_NPC_FLAG = 81, // Flags
|
||||||
|
SMART_ACTION_ADD_NPC_FLAG = 82, // Flags
|
||||||
|
SMART_ACTION_REMOVE_NPC_FLAG = 83, // Flags
|
||||||
|
|
||||||
|
SMART_ACTION_END = 84,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SmartAction
|
struct SmartAction
|
||||||
@@ -767,6 +772,13 @@ struct SmartAction
|
|||||||
uint32 seat;
|
uint32 seat;
|
||||||
} enterVehicle;
|
} enterVehicle;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint32 id;
|
||||||
|
uint32 dontResume;
|
||||||
|
uint32 timerType;
|
||||||
|
} timedActionList;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
uint32 param1;
|
uint32 param1;
|
||||||
@@ -927,7 +939,8 @@ enum SmartScriptType
|
|||||||
SMART_SCRIPT_TYPE_SPELL = 6,//
|
SMART_SCRIPT_TYPE_SPELL = 6,//
|
||||||
SMART_SCRIPT_TYPE_TRANSPORT = 7,//
|
SMART_SCRIPT_TYPE_TRANSPORT = 7,//
|
||||||
SMART_SCRIPT_TYPE_INSTANCE = 8,//
|
SMART_SCRIPT_TYPE_INSTANCE = 8,//
|
||||||
SMART_SCRIPT_TYPE_MAX = 9
|
SMART_SCRIPT_TYPE_TIMED_ACTIONLIST = 9,//
|
||||||
|
SMART_SCRIPT_TYPE_MAX = 10
|
||||||
};
|
};
|
||||||
|
|
||||||
enum SmartAITypeMaskId
|
enum SmartAITypeMaskId
|
||||||
@@ -941,24 +954,26 @@ enum SmartAITypeMaskId
|
|||||||
SMART_SCRIPT_TYPE_MASK_SPELL = 64,
|
SMART_SCRIPT_TYPE_MASK_SPELL = 64,
|
||||||
SMART_SCRIPT_TYPE_MASK_TRANSPORT = 128,
|
SMART_SCRIPT_TYPE_MASK_TRANSPORT = 128,
|
||||||
SMART_SCRIPT_TYPE_MASK_INSTANCE = 256,
|
SMART_SCRIPT_TYPE_MASK_INSTANCE = 256,
|
||||||
|
SMART_SCRIPT_TYPE_MASK_TIMED_ACTIONLIST = 512,
|
||||||
};
|
};
|
||||||
|
|
||||||
const uint32 SmartAITypeMask[SMART_SCRIPT_TYPE_MAX][2] =
|
const uint32 SmartAITypeMask[SMART_SCRIPT_TYPE_MAX][2] =
|
||||||
{
|
{
|
||||||
{SMART_SCRIPT_TYPE_CREATURE, SMART_SCRIPT_TYPE_MASK_CREATURE },
|
{SMART_SCRIPT_TYPE_CREATURE, SMART_SCRIPT_TYPE_MASK_CREATURE },
|
||||||
{SMART_SCRIPT_TYPE_GAMEOBJECT, SMART_SCRIPT_TYPE_MASK_GAMEOBJECT },
|
{SMART_SCRIPT_TYPE_GAMEOBJECT, SMART_SCRIPT_TYPE_MASK_GAMEOBJECT },
|
||||||
{SMART_SCRIPT_TYPE_AREATRIGGER, SMART_SCRIPT_TYPE_MASK_AREATRIGGER },
|
{SMART_SCRIPT_TYPE_AREATRIGGER, SMART_SCRIPT_TYPE_MASK_AREATRIGGER },
|
||||||
{SMART_SCRIPT_TYPE_EVENT, SMART_SCRIPT_TYPE_MASK_EVENT },
|
{SMART_SCRIPT_TYPE_EVENT, SMART_SCRIPT_TYPE_MASK_EVENT },
|
||||||
{SMART_SCRIPT_TYPE_GOSSIP, SMART_SCRIPT_TYPE_MASK_GOSSIP },
|
{SMART_SCRIPT_TYPE_GOSSIP, SMART_SCRIPT_TYPE_MASK_GOSSIP },
|
||||||
{SMART_SCRIPT_TYPE_QUEST, SMART_SCRIPT_TYPE_MASK_QUEST },
|
{SMART_SCRIPT_TYPE_QUEST, SMART_SCRIPT_TYPE_MASK_QUEST },
|
||||||
{SMART_SCRIPT_TYPE_SPELL, SMART_SCRIPT_TYPE_MASK_SPELL },
|
{SMART_SCRIPT_TYPE_SPELL, SMART_SCRIPT_TYPE_MASK_SPELL },
|
||||||
{SMART_SCRIPT_TYPE_TRANSPORT, SMART_SCRIPT_TYPE_MASK_TRANSPORT },
|
{SMART_SCRIPT_TYPE_TRANSPORT, SMART_SCRIPT_TYPE_MASK_TRANSPORT },
|
||||||
{SMART_SCRIPT_TYPE_INSTANCE, SMART_SCRIPT_TYPE_MASK_INSTANCE }
|
{SMART_SCRIPT_TYPE_INSTANCE, SMART_SCRIPT_TYPE_MASK_INSTANCE },
|
||||||
|
{SMART_SCRIPT_TYPE_TIMED_ACTIONLIST, SMART_SCRIPT_TYPE_MASK_TIMED_ACTIONLIST }
|
||||||
};
|
};
|
||||||
|
|
||||||
const uint32 SmartAIEventMask[SMART_EVENT_END][2] =
|
const uint32 SmartAIEventMask[SMART_EVENT_END][2] =
|
||||||
{
|
{
|
||||||
{SMART_EVENT_UPDATE_IC, SMART_SCRIPT_TYPE_MASK_CREATURE },
|
{SMART_EVENT_UPDATE_IC, SMART_SCRIPT_TYPE_MASK_CREATURE + SMART_SCRIPT_TYPE_MASK_TIMED_ACTIONLIST},
|
||||||
{SMART_EVENT_UPDATE_OOC, SMART_SCRIPT_TYPE_MASK_CREATURE + SMART_SCRIPT_TYPE_MASK_GAMEOBJECT + SMART_SCRIPT_TYPE_MASK_INSTANCE },
|
{SMART_EVENT_UPDATE_OOC, SMART_SCRIPT_TYPE_MASK_CREATURE + SMART_SCRIPT_TYPE_MASK_GAMEOBJECT + SMART_SCRIPT_TYPE_MASK_INSTANCE },
|
||||||
{SMART_EVENT_HEALT_PCT, SMART_SCRIPT_TYPE_MASK_CREATURE },
|
{SMART_EVENT_HEALT_PCT, SMART_SCRIPT_TYPE_MASK_CREATURE },
|
||||||
{SMART_EVENT_MANA_PCT, SMART_SCRIPT_TYPE_MASK_CREATURE },
|
{SMART_EVENT_MANA_PCT, SMART_SCRIPT_TYPE_MASK_CREATURE },
|
||||||
@@ -1062,6 +1077,7 @@ struct SmartScriptHolder
|
|||||||
entryOrGuid = 0;
|
entryOrGuid = 0;
|
||||||
link = 0;
|
link = 0;
|
||||||
event_id = 0;
|
event_id = 0;
|
||||||
|
enableTimed = false;
|
||||||
}
|
}
|
||||||
int32 entryOrGuid;
|
int32 entryOrGuid;
|
||||||
SmartScriptType source_type;
|
SmartScriptType source_type;
|
||||||
@@ -1081,7 +1097,7 @@ struct SmartScriptHolder
|
|||||||
uint32 timer;
|
uint32 timer;
|
||||||
bool active;
|
bool active;
|
||||||
bool runOnce;
|
bool runOnce;
|
||||||
|
bool enableTimed;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1133,7 +1149,7 @@ class SmartAIMgr
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(entry > 0)//first search is for guid (negative), do not drop error if not found
|
if(entry > 0)//first search is for guid (negative), do not drop error if not found
|
||||||
sLog.outError("SmartAIMgr::GetScript: Could not load Script for Entry %d AIType %u.", entry, uint32(type));
|
sLog.outError("SmartAIMgr::GetScript: Could not load Script for Entry %d ScriptType %u.", entry, uint32(type));
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1142,7 +1158,7 @@ class SmartAIMgr
|
|||||||
//event stores
|
//event stores
|
||||||
SmartAIEventMap mEventMap[SMART_SCRIPT_TYPE_MAX];
|
SmartAIEventMap mEventMap[SMART_SCRIPT_TYPE_MAX];
|
||||||
|
|
||||||
bool IsEventValid(SmartScriptHolder e);
|
bool IsEventValid(SmartScriptHolder &e);
|
||||||
bool IsTargetValid(SmartScriptHolder e);
|
bool IsTargetValid(SmartScriptHolder e);
|
||||||
/*inline bool IsTargetValid(SmartScriptHolder e, int32 target)
|
/*inline bool IsTargetValid(SmartScriptHolder e, int32 target)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user