Core/AI: enable SmartScripts on Scenes + add scene related actions/events

Closes #19194
This commit is contained in:
Traesh
2017-03-17 21:21:35 +01:00
committed by Shauren
parent 77d1080ff5
commit 01ded93a42
9 changed files with 229 additions and 46 deletions

View File

@@ -42,6 +42,7 @@ SmartScript::SmartScript()
go = nullptr;
me = nullptr;
trigger = nullptr;
sceneTemplate = nullptr;
mEventPhase = 0;
mPathId = 0;
mTargetStorage = new ObjectListMap();
@@ -80,7 +81,7 @@ void SmartScript::OnReset()
mCounterList.clear();
}
void SmartScript::ProcessEventsFor(SMART_EVENT e, Unit* unit, uint32 var0, uint32 var1, bool bvar, const SpellInfo* spell, GameObject* gob)
void SmartScript::ProcessEventsFor(SMART_EVENT e, Unit* unit, uint32 var0, uint32 var1, bool bvar, const SpellInfo* spell, GameObject* gob, std::string const& varString)
{
for (SmartAIEventList::iterator i = mEvents.begin(); i != mEvents.end(); ++i)
{
@@ -90,11 +91,11 @@ void SmartScript::ProcessEventsFor(SMART_EVENT e, Unit* unit, uint32 var0, uint3
if (eventType == e /*&& (!i->event.event_phase_mask || IsInPhase(i->event.event_phase_mask)) && !(i->event.event_flags & SMART_EVENT_FLAG_NOT_REPEATABLE && i->runOnce)*/)
if (sConditionMgr->IsObjectMeetingSmartEventConditions(i->entryOrGuid, i->event_id, i->source_type, unit, GetBaseObject()))
ProcessEvent(*i, unit, var0, var1, bvar, spell, gob);
ProcessEvent(*i, unit, var0, var1, bvar, spell, gob, varString);
}
}
void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, uint32 var1, bool bvar, const SpellInfo* spell, GameObject* gob)
void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, uint32 var1, bool bvar, const SpellInfo* spell, GameObject* gob, std::string const& varString)
{
//calc random
if (e.GetEventType() != SMART_EVENT_LINK && e.event.event_chance < 100 && e.event.event_chance)
@@ -1264,7 +1265,12 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
}
case SMART_ACTION_SUMMON_CREATURE:
{
WorldObject* summoner = GetBaseObjectOrUnit(unit);
if (!summoner)
break;
ObjectList* targets = GetTargets(e, unit);
if (targets)
{
float x, y, z, o;
@@ -1275,7 +1281,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
y += e.target.y;
z += e.target.z;
o += e.target.o;
if (Creature* summon = GetBaseObject()->SummonCreature(e.action.summonCreature.creature, x, y, z, o, (TempSummonType)e.action.summonCreature.type, e.action.summonCreature.duration))
if (Creature* summon = summoner->SummonCreature(e.action.summonCreature.creature, x, y, z, o, (TempSummonType)e.action.summonCreature.type, e.action.summonCreature.duration))
if (e.action.summonCreature.attackInvoker)
summon->AI()->AttackStart((*itr)->ToUnit());
}
@@ -1286,14 +1292,15 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
if (e.GetTargetType() != SMART_TARGET_POSITION)
break;
if (Creature* summon = GetBaseObject()->SummonCreature(e.action.summonCreature.creature, e.target.x, e.target.y, e.target.z, e.target.o, (TempSummonType)e.action.summonCreature.type, e.action.summonCreature.duration))
if (Creature* summon = summoner->SummonCreature(e.action.summonCreature.creature, e.target.x, e.target.y, e.target.z, e.target.o, (TempSummonType)e.action.summonCreature.type, e.action.summonCreature.duration))
if (unit && e.action.summonCreature.attackInvoker)
summon->AI()->AttackStart(unit);
break;
}
case SMART_ACTION_SUMMON_GO:
{
if (!GetBaseObject())
WorldObject* summoner = GetBaseObjectOrUnit(unit);
if (!summoner)
break;
ObjectList* targets = GetTargets(e, unit);
@@ -1306,7 +1313,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
Position pos = (*itr)->GetPositionWithOffset(Position(e.target.x, e.target.y, e.target.z, e.target.o));
G3D::Quat rot = G3D::Matrix3::fromEulerAnglesZYX(pos.GetOrientation(), 0.f, 0.f);
GetBaseObject()->SummonGameObject(e.action.summonGO.entry, pos, rot, e.action.summonGO.despawnTime);
summoner->SummonGameObject(e.action.summonGO.entry, pos, rot, e.action.summonGO.despawnTime);
}
delete targets;
@@ -1316,7 +1323,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
break;
G3D::Quat rot = G3D::Matrix3::fromEulerAnglesZYX(e.target.o, 0.f, 0.f);
GetBaseObject()->SummonGameObject(e.action.summonGO.entry, Position(e.target.x, e.target.y, e.target.z, e.target.o), rot, e.action.summonGO.despawnTime);
summoner->SummonGameObject(e.action.summonGO.entry, Position(e.target.x, e.target.y, e.target.z, e.target.o), rot, e.action.summonGO.despawnTime);
break;
}
case SMART_ACTION_KILL_UNIT:
@@ -2465,6 +2472,30 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
delete targets;
break;
}
case SMART_ACTION_SCENE_PLAY:
{
ObjectList* targets = GetTargets(e, unit);
if (!targets)
break;
for (WorldObject* target : *targets)
if (Player* playerTarget = target->ToPlayer())
playerTarget->GetSceneMgr().PlayScene(e.action.scene.sceneId);
break;
}
case SMART_ACTION_SCENE_CANCEL:
{
ObjectList* targets = GetTargets(e, unit);
if (!targets)
break;
for (WorldObject* target : *targets)
if (Player* playerTarget = target->ToPlayer())
playerTarget->GetSceneMgr().CancelSceneBySceneId(e.action.scene.sceneId);
break;
}
default:
TC_LOG_ERROR("sql.sql", "SmartScript::ProcessAction: Entry " SI64FMTD " SourceType %u, Event %u, Unhandled Action type %u", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType());
break;
@@ -2474,16 +2505,16 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
{
SmartScriptHolder& linked = SmartAIMgr::FindLinkedEvent(mEvents, e.link);
if (linked)
ProcessEvent(linked, unit, var0, var1, bvar, spell, gob);
ProcessEvent(linked, unit, var0, var1, bvar, spell, gob, varString);
else
TC_LOG_DEBUG("sql.sql", "SmartScript::ProcessAction: Entry " SI64FMTD " SourceType %u, Event %u, Link Event %u not found or invalid, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.link);
}
}
void SmartScript::ProcessTimedAction(SmartScriptHolder& e, uint32 const& min, uint32 const& max, Unit* unit, uint32 var0, uint32 var1, bool bvar, const SpellInfo* spell, GameObject* gob)
void SmartScript::ProcessTimedAction(SmartScriptHolder& e, uint32 const& min, uint32 const& max, Unit* unit, uint32 var0, uint32 var1, bool bvar, const SpellInfo* spell, GameObject* gob, std::string const& varString)
{
if (sConditionMgr->IsObjectMeetingSmartEventConditions(e.entryOrGuid, e.event_id, e.source_type, unit, GetBaseObject()))
ProcessAction(e, unit, var0, var1, bvar, spell, gob);
ProcessAction(e, unit, var0, var1, bvar, spell, gob, varString);
RecalcTimer(e, min, max);
}
@@ -2910,7 +2941,7 @@ ObjectList* SmartScript::GetWorldObjectsInDist(float dist)
return targets;
}
void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, uint32 var1, bool bvar, const SpellInfo* spell, GameObject* gob)
void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, uint32 var1, bool bvar, const SpellInfo* spell, GameObject* gob, std::string const& varString)
{
if (!e.active && e.GetEventType() != SMART_EVENT_LINK)
return;
@@ -3448,6 +3479,21 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui
if (GetCounterId(e.event.counter.id) != 0 && GetCounterValue(e.event.counter.id) == e.event.counter.value)
ProcessTimedAction(e, e.event.counter.cooldownMin, e.event.counter.cooldownMax);
break;
case SMART_EVENT_SCENE_START:
case SMART_EVENT_SCENE_CANCEL:
case SMART_EVENT_SCENE_COMPLETE:
{
ProcessAction(e, unit);
break;
}
case SMART_EVENT_SCENE_TRIGGER:
{
if (e.event.param_string != varString)
return;
ProcessAction(e, unit, var0, 0, false, nullptr, nullptr, varString);
break;
}
default:
TC_LOG_ERROR("sql.sql", "SmartScript::ProcessEvent: Unhandled Event type %u", e.GetEventType());
break;
@@ -3633,7 +3679,7 @@ void SmartScript::OnUpdate(uint32 const diff)
}
}
void SmartScript::FillScript(SmartAIEventList e, WorldObject* obj, AreaTriggerEntry const* at)
void SmartScript::FillScript(SmartAIEventList e, WorldObject* obj, AreaTriggerEntry const* at, SceneTemplate const* scene)
{
if (e.empty())
{
@@ -3641,6 +3687,8 @@ void SmartScript::FillScript(SmartAIEventList e, WorldObject* obj, AreaTriggerEn
TC_LOG_DEBUG("scripts.ai", "SmartScript: EventMap for Entry %u is empty but is using SmartScript.", obj->GetEntry());
if (at)
TC_LOG_DEBUG("scripts.ai", "SmartScript: EventMap for AreaTrigger %u is empty but is using SmartScript.", at->ID);
if (scene)
TC_LOG_DEBUG("scripts.ai", "SmartScript: EventMap for SceneId %u is empty but is using SmartScript.", scene->SceneId);
return;
}
for (SmartAIEventList::iterator i = e.begin(); i != e.end(); ++i)
@@ -3667,6 +3715,8 @@ void SmartScript::FillScript(SmartAIEventList e, WorldObject* obj, AreaTriggerEn
TC_LOG_ERROR("sql.sql", "SmartScript: Entry %u has events but no events added to list because of instance flags.", obj->GetEntry());
if (mEvents.empty() && at)
TC_LOG_ERROR("sql.sql", "SmartScript: AreaTrigger %u has events but no events added to list because of instance flags. NOTE: triggers can not handle any instance flags.", at->ID);
if (mEvents.empty() && scene)
TC_LOG_ERROR("sql.sql", "SmartScript: SceneId %u has events but no events added to list because of instance flags. NOTE: scenes can not handle any instance flags.", scene->SceneId);
}
void SmartScript::GetScript()
@@ -3677,23 +3727,28 @@ void SmartScript::GetScript()
e = sSmartScriptMgr->GetScript(-((int32)me->GetSpawnId()), mScriptType);
if (e.empty())
e = sSmartScriptMgr->GetScript((int32)me->GetEntry(), mScriptType);
FillScript(e, me, nullptr);
FillScript(e, me, nullptr, nullptr);
}
else if (go)
{
e = sSmartScriptMgr->GetScript(-((int32)go->GetSpawnId()), mScriptType);
if (e.empty())
e = sSmartScriptMgr->GetScript((int32)go->GetEntry(), mScriptType);
FillScript(e, go, nullptr);
FillScript(e, go, nullptr, nullptr);
}
else if (trigger)
{
e = sSmartScriptMgr->GetScript((int32)trigger->ID, mScriptType);
FillScript(e, nullptr, trigger);
FillScript(e, nullptr, trigger, nullptr);
}
else if (sceneTemplate)
{
e = sSmartScriptMgr->GetScript(sceneTemplate->SceneId, mScriptType);
FillScript(e, nullptr, nullptr, sceneTemplate);
}
}
void SmartScript::OnInitialize(WorldObject* obj, AreaTriggerEntry const* at)
void SmartScript::OnInitialize(WorldObject* obj, AreaTriggerEntry const* at, SceneTemplate const* scene)
{
if (obj)//handle object based scripts
{
@@ -3713,12 +3768,19 @@ void SmartScript::OnInitialize(WorldObject* obj, AreaTriggerEntry const* at)
TC_LOG_ERROR("misc", "SmartScript::OnInitialize: Unhandled TypeID !WARNING!");
return;
}
} else if (at)
}
else if (at)
{
mScriptType = SMART_SCRIPT_TYPE_AREATRIGGER;
trigger = at;
TC_LOG_DEBUG("scripts.ai", "SmartScript::OnInitialize: source is AreaTrigger %u", trigger->ID);
}
else if (scene)
{
mScriptType = SMART_SCRIPT_TYPE_SCENE;
sceneTemplate = scene;
TC_LOG_DEBUG("scripts.ai", "SmartScript::OnInitialize: source is Scene with id %u", scene->SceneId);
}
else
{
TC_LOG_ERROR("misc", "SmartScript::OnInitialize: !WARNING! Initialized objects are NULL.");