feat(Core/SmartAI): Implement a few more stuff (#17090)

* init

* init2

* attempt to fix WP delays

* init3

* init4

* buildfix

* Create rev_1693093120417899200.sql

* workflow

* Underbat

* castflag power mana

* did not work

* Update SmartScriptMgr.cpp

* ugly

* port range to new system

* attempt

* simplify cast

simplify cast
add iteration for aura_not_present
recalc timer if already castig spell

* Update SmartScript.cpp

* attempt

* attempts

* HP PCT

* missing aura to targetselector

* Update rev_1693093120417899200.sql

* Update SmartScriptMgr.h

* Update SmartScriptMgr.h

* Update SmartScript.cpp

* remove not_attacking, fix behind_me

* revert is_behind_me

* Update SmartScriptMgr.h

* Update underbog.cpp

* Update underbog.cpp
This commit is contained in:
Gultask
2023-09-10 08:12:55 -03:00
committed by GitHub
parent 2faceea420
commit e422583132
5 changed files with 2012 additions and 185 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -601,7 +601,7 @@ void SmartAI::MovepointReached(uint32 id)
if (mLastWP) if (mLastWP)
{ {
me->SetPosition(mLastWP->x, mLastWP->y, mLastWP->z, me->GetOrientation()); me->SetPosition(mLastWP->x, mLastWP->y, mLastWP->z, me->GetOrientation());
me->SetHomePosition(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation()); me->SetHomePosition(me->GetPosition());
} }
if (HasEscortState(SMART_ESCORT_PAUSED)) if (HasEscortState(SMART_ESCORT_PAUSED))

View File

@@ -593,9 +593,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
{ {
// may be nullptr // may be nullptr
if (go) if (go)
{
go->CastSpell(target->ToUnit(), e.action.cast.spell); go->CastSpell(target->ToUnit(), e.action.cast.spell);
}
if (!IsUnit(target)) if (!IsUnit(target))
continue; continue;
@@ -604,29 +602,24 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
{ {
caster->CastSpell(target->ToUnit(), e.action.cast.spell, (e.action.cast.castFlags & SMARTCAST_TRIGGERED)); caster->CastSpell(target->ToUnit(), e.action.cast.spell, (e.action.cast.castFlags & SMARTCAST_TRIGGERED));
} }
else if (me && (!(e.action.cast.castFlags & SMARTCAST_AURA_NOT_PRESENT) || !target->ToUnit()->HasAura(e.action.cast.spell))) else if (me)
{ {
if (e.action.cast.castFlags & SMARTCAST_INTERRUPT_PREVIOUS) // If target has the aura, skip
{ if ((e.action.cast.castFlags & SMARTCAST_AURA_NOT_PRESENT) && target->ToUnit()->HasAura(e.action.cast.spell))
me->InterruptNonMeleeSpells(false); continue;
}
// If the threatlist is a singleton, cancel
if (e.action.cast.castFlags & SMARTCAST_THREATLIST_NOT_SINGLE) if (e.action.cast.castFlags & SMARTCAST_THREATLIST_NOT_SINGLE)
if (me->GetThreatMgr().GetThreatListSize() <= 1) if (me->GetThreatMgr().GetThreatListSize() <= 1)
break; break;
TriggerCastFlags triggerFlags = TRIGGERED_NONE; // If target does not use mana, skip
if (e.action.cast.castFlags & SMARTCAST_TRIGGERED) if ((e.action.cast.castFlags & SMARTCAST_TARGET_POWER_MANA) && !target->ToUnit()->GetPower(POWER_MANA))
{ continue;
if (e.action.cast.triggerFlags)
{ // Interrupts current spellcast
triggerFlags = TriggerCastFlags(e.action.cast.triggerFlags); if (e.action.cast.castFlags & SMARTCAST_INTERRUPT_PREVIOUS)
} me->InterruptNonMeleeSpells(false);
else
{
triggerFlags = TRIGGERED_FULL_MASK;
}
}
// Flag usable only if caster has max dist set. // Flag usable only if caster has max dist set.
if ((e.action.cast.castFlags & SMARTCAST_COMBAT_MOVE) && GetCasterMaxDist() > 0.0f && me->GetMaxPower(GetCasterPowerType()) > 0) if ((e.action.cast.castFlags & SMARTCAST_COMBAT_MOVE) && GetCasterMaxDist() > 0.0f && me->GetMaxPower(GetCasterPowerType()) > 0)
@@ -647,15 +640,19 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
} }
} }
TriggerCastFlags triggerFlags = TRIGGERED_NONE;
if (e.action.cast.castFlags & SMARTCAST_TRIGGERED)
{
if (e.action.cast.triggerFlags)
triggerFlags = TriggerCastFlags(e.action.cast.triggerFlags);
else
triggerFlags = TRIGGERED_FULL_MASK;
}
me->CastSpell(target->ToUnit(), e.action.cast.spell, triggerFlags); me->CastSpell(target->ToUnit(), e.action.cast.spell, triggerFlags);
LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_CAST: Unit {} casts spell {} on target {} with castflags {}", LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_CAST: Unit {} casts spell {} on target {} with castflags {}",
me->GetGUID().ToString(), e.action.cast.spell, target->GetGUID().ToString(), e.action.cast.castFlags); me->GetGUID().ToString(), e.action.cast.spell, target->GetGUID().ToString(), e.action.cast.castFlags);
} }
else
{
LOG_DEBUG("scripts.ai", "Spell {} not cast because it has flag SMARTCAST_AURA_NOT_PRESENT and the target {} already has the aura",
e.action.cast.spell, target->GetGUID().ToString());
}
} }
break; break;
} }
@@ -2991,6 +2988,47 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
break; break;
} }
case SMART_ACTION_SET_ORIENTATION_TARGET:
{
switch (e.action.orientationTarget.type)
{
case 0: // Reset
{
for (WorldObject* target : targets)
target->ToCreature()->SetFacingTo((target->ToCreature()->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && target->ToCreature()->GetTransGUID() ? target->ToCreature()->GetTransportHomePosition() : target->ToCreature()->GetHomePosition()).GetOrientation());
break;
}
case 1: // Target target.o
{
for (WorldObject* target : targets)
target->ToCreature()->SetFacingTo(e.target.o);
break;
}
case 2: // Target source
{
for (WorldObject* target : targets)
target->ToCreature()->SetFacingToObject(me);
break;
}
case 3: // Target parameters
{
ObjectVector facingTargets;
GetTargets(facingTargets, CreateSmartEvent(SMART_EVENT_UPDATE_IC, 0, 0, 0, 0, 0, 0, 0, SMART_ACTION_NONE, 0, 0, 0, 0, 0, 0, (SMARTAI_TARGETS)e.action.orientationTarget.targetType, e.action.orientationTarget.targetParam1, e.action.orientationTarget.targetParam2, e.action.orientationTarget.targetParam3, e.action.orientationTarget.targetParam4, 0), unit);
for (WorldObject* facingTarget : facingTargets)
for (WorldObject* target : targets)
target->ToCreature()->SetFacingToObject(facingTarget);
break;
}
default:
break;
}
break;
}
default: default:
LOG_ERROR("sql.sql", "SmartScript::ProcessAction: Entry {} SourceType {}, Event {}, Unhandled Action type {}", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType()); LOG_ERROR("sql.sql", "SmartScript::ProcessAction: Entry {} SourceType {}, Event {}, Unhandled Action type {}", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType());
break; break;
@@ -3162,7 +3200,7 @@ void SmartScript::GetTargets(ObjectVector& targets, SmartScriptHolder const& e,
if (Unit* u = me->AI()->SelectTarget(SelectTargetMethod::MaxThreat, 1, PowerUsersSelector(me, Powers(e.target.hostileRandom.powerType - 1), (float)e.target.hostileRandom.maxDist, e.target.hostileRandom.playerOnly))) if (Unit* u = me->AI()->SelectTarget(SelectTargetMethod::MaxThreat, 1, PowerUsersSelector(me, Powers(e.target.hostileRandom.powerType - 1), (float)e.target.hostileRandom.maxDist, e.target.hostileRandom.playerOnly)))
targets.push_back(u); targets.push_back(u);
} }
else if (Unit* u = me->AI()->SelectTarget(SelectTargetMethod::MaxThreat, 1, (float)e.target.hostileRandom.maxDist, e.target.hostileRandom.playerOnly)) else if (Unit* u = me->AI()->SelectTarget(SelectTargetMethod::MaxThreat, 1, (float)e.target.hostileRandom.maxDist, e.target.hostileRandom.playerOnly, true, -e.target.hostileRandom.aura))
targets.push_back(u); targets.push_back(u);
} }
break; break;
@@ -3174,7 +3212,7 @@ void SmartScript::GetTargets(ObjectVector& targets, SmartScriptHolder const& e,
if (Unit* u = me->AI()->SelectTarget(SelectTargetMethod::MinThreat, 0, PowerUsersSelector(me, Powers(e.target.hostileRandom.powerType - 1), (float)e.target.hostileRandom.maxDist, e.target.hostileRandom.playerOnly))) if (Unit* u = me->AI()->SelectTarget(SelectTargetMethod::MinThreat, 0, PowerUsersSelector(me, Powers(e.target.hostileRandom.powerType - 1), (float)e.target.hostileRandom.maxDist, e.target.hostileRandom.playerOnly)))
targets.push_back(u); targets.push_back(u);
} }
else if (Unit* u = me->AI()->SelectTarget(SelectTargetMethod::MinThreat, 0, (float)e.target.hostileRandom.maxDist, e.target.hostileRandom.playerOnly)) else if (Unit* u = me->AI()->SelectTarget(SelectTargetMethod::MinThreat, 0, (float)e.target.hostileRandom.maxDist, e.target.hostileRandom.playerOnly, true, -e.target.hostileRandom.aura))
targets.push_back(u); targets.push_back(u);
} }
break; break;
@@ -3186,7 +3224,7 @@ void SmartScript::GetTargets(ObjectVector& targets, SmartScriptHolder const& e,
if (Unit* u = me->AI()->SelectTarget(SelectTargetMethod::Random, 0, PowerUsersSelector(me, Powers(e.target.hostileRandom.powerType - 1), (float)e.target.hostileRandom.maxDist, e.target.hostileRandom.playerOnly))) if (Unit* u = me->AI()->SelectTarget(SelectTargetMethod::Random, 0, PowerUsersSelector(me, Powers(e.target.hostileRandom.powerType - 1), (float)e.target.hostileRandom.maxDist, e.target.hostileRandom.playerOnly)))
targets.push_back(u); targets.push_back(u);
} }
else if (Unit* u = me->AI()->SelectTarget(SelectTargetMethod::Random, 0, (float)e.target.hostileRandom.maxDist, e.target.hostileRandom.playerOnly)) else if (Unit* u = me->AI()->SelectTarget(SelectTargetMethod::Random, 0, (float)e.target.hostileRandom.maxDist, e.target.hostileRandom.playerOnly, true, -e.target.hostileRandom.aura))
targets.push_back(u); targets.push_back(u);
} }
break; break;
@@ -3198,7 +3236,7 @@ void SmartScript::GetTargets(ObjectVector& targets, SmartScriptHolder const& e,
if (Unit* u = me->AI()->SelectTarget(SelectTargetMethod::Random, 1, PowerUsersSelector(me, Powers(e.target.hostileRandom.powerType - 1), (float)e.target.hostileRandom.maxDist, e.target.hostileRandom.playerOnly))) if (Unit* u = me->AI()->SelectTarget(SelectTargetMethod::Random, 1, PowerUsersSelector(me, Powers(e.target.hostileRandom.powerType - 1), (float)e.target.hostileRandom.maxDist, e.target.hostileRandom.playerOnly)))
targets.push_back(u); targets.push_back(u);
} }
else if (Unit* u = me->AI()->SelectTarget(SelectTargetMethod::Random, 1, (float)e.target.hostileRandom.maxDist, e.target.hostileRandom.playerOnly)) else if (Unit* u = me->AI()->SelectTarget(SelectTargetMethod::Random, 1, (float)e.target.hostileRandom.maxDist, e.target.hostileRandom.playerOnly, true, -e.target.hostileRandom.aura))
targets.push_back(u); targets.push_back(u);
} }
break; break;
@@ -3785,16 +3823,8 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui
if (!me || !me->IsEngaged() || !me->GetVictim()) if (!me || !me->IsEngaged() || !me->GetVictim())
return; return;
if (me->IsInRange(me->GetVictim(), (float)e.event.rangeRepeat.minRange, (float)e.event.rangeRepeat.maxRange)) if (me->IsInRange(me->GetVictim(), (float)e.event.minMaxRepeat.rangeMin, (float)e.event.minMaxRepeat.rangeMax))
{ ProcessTimedAction(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax, me->GetVictim());
if (e.event.rangeRepeat.onlyFireOnRepeat == 2)
{
e.event.rangeRepeat.onlyFireOnRepeat = 1;
RecalcTimer(e, e.event.rangeRepeat.repeatMin, e.event.rangeRepeat.repeatMax);
}
else
ProcessTimedAction(e, e.event.rangeRepeat.repeatMin, e.event.rangeRepeat.repeatMax, me->GetVictim());
}
else else
RecalcTimer(e, 1200, 1200); // make it predictable RecalcTimer(e, 1200, 1200); // make it predictable
@@ -3947,9 +3977,11 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui
if (Unit* victim = me->GetVictim()) if (Unit* victim = me->GetVictim())
{ {
if (!victim->HasInArc(static_cast<float>(M_PI), me)) if (e.event.minMaxRepeat.rangeMax && (me->IsInRange(victim, (float)e.event.minMaxRepeat.rangeMin, (float)e.event.minMaxRepeat.rangeMax)))
ProcessTimedAction(e, e.event.behindTarget.cooldownMin, e.event.behindTarget.cooldownMax, victim); if (!victim->HasInArc(static_cast<float>(M_PI), me))
ProcessTimedAction(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax, victim);
} }
break; break;
} }
case SMART_EVENT_RECEIVE_EMOTE: case SMART_EVENT_RECEIVE_EMOTE:
@@ -4229,7 +4261,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui
if (IsUnit(target) && me->IsFriendlyTo(target->ToUnit()) && target->ToUnit()->IsAlive() && target->ToUnit()->IsInCombat()) if (IsUnit(target) && me->IsFriendlyTo(target->ToUnit()) && target->ToUnit()->IsAlive() && target->ToUnit()->IsInCombat())
{ {
uint32 healthPct = uint32(target->ToUnit()->GetHealthPct()); uint32 healthPct = uint32(target->ToUnit()->GetHealthPct());
if (healthPct > e.event.friendlyHealthPct.maxHpPct || healthPct < e.event.friendlyHealthPct.minHpPct) if (healthPct > e.event.friendlyHealthPct.hpPct)
{ {
continue; continue;
} }
@@ -4243,7 +4275,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui
} }
case SMART_TARGET_SELF: case SMART_TARGET_SELF:
case SMART_TARGET_ACTION_INVOKER: case SMART_TARGET_ACTION_INVOKER:
unitTarget = DoSelectLowestHpPercentFriendly((float)e.event.friendlyHealthPct.radius, e.event.friendlyHealthPct.minHpPct, e.event.friendlyHealthPct.maxHpPct); unitTarget = DoSelectLowestHpPercentFriendly((float)e.event.friendlyHealthPct.radius, 0, e.event.friendlyHealthPct.hpPct);
break; break;
default: default:
return; return;
@@ -4435,14 +4467,14 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui
{ {
if (Unit* target = ObjectAccessor::GetUnit(*me, (*i)->getUnitGuid())) if (Unit* target = ObjectAccessor::GetUnit(*me, (*i)->getUnitGuid()))
{ {
if (!target || target->IsPet() || target->IsTotem() || !target->IsNonMeleeSpellCast(false, false, true)) if (!target || !IsPlayer(target) || !target->IsNonMeleeSpellCast(false, false, true))
continue; continue;
if (e.event.areaCasting.rangeMin && !(me->IsInRange(target, (float)e.event.areaCasting.rangeMin, (float)e.event.areaCasting.rangeMax))) if (!(me->IsInRange(target, (float)e.event.minMaxRepeat.rangeMin, (float)e.event.minMaxRepeat.rangeMax)))
continue; continue;
ProcessAction(e, target); ProcessAction(e, target);
RecalcTimer(e, e.event.areaCasting.repeatMin, e.event.areaCasting.repeatMax); RecalcTimer(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax);
return; return;
} }
@@ -4463,11 +4495,11 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui
{ {
if (Unit* target = ObjectAccessor::GetUnit(*me, (*i)->getUnitGuid())) if (Unit* target = ObjectAccessor::GetUnit(*me, (*i)->getUnitGuid()))
{ {
if (!(me->IsInRange(target, (float)e.event.areaRange.rangeMin, (float)e.event.areaRange.rangeMax))) if (!(me->IsInRange(target, (float)e.event.minMaxRepeat.rangeMin, (float)e.event.minMaxRepeat.rangeMax)))
continue; continue;
ProcessAction(e, target); ProcessAction(e, target);
RecalcTimer(e, e.event.areaRange.repeatMin, e.event.areaRange.repeatMax); RecalcTimer(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax);
return; return;
} }
} }
@@ -4487,16 +4519,6 @@ void SmartScript::InitTimer(SmartScriptHolder& e)
switch (e.GetEventType()) switch (e.GetEventType())
{ {
//set only events which have initial timers //set only events which have initial timers
case SMART_EVENT_RANGE:
// If onlyFireOnRepeat is true set to 2 before entering combat. Will be set back to 1 after entering combat to ignore initial firing.
if (e.event.rangeRepeat.onlyFireOnRepeat == 1)
e.event.rangeRepeat.onlyFireOnRepeat = 2;
// make it predictable
RecalcTimer(e, 1200, 1200);
break;
case SMART_EVENT_AREA_RANGE:
RecalcTimer(e, e.event.areaRange.min, e.event.areaRange.max);
break;
case SMART_EVENT_NEAR_PLAYERS: case SMART_EVENT_NEAR_PLAYERS:
case SMART_EVENT_NEAR_PLAYERS_NEGATION: case SMART_EVENT_NEAR_PLAYERS_NEGATION:
RecalcTimer(e, e.event.nearPlayer.firstTimer, e.event.nearPlayer.firstTimer); RecalcTimer(e, e.event.nearPlayer.firstTimer, e.event.nearPlayer.firstTimer);
@@ -4504,13 +4526,13 @@ void SmartScript::InitTimer(SmartScriptHolder& e)
case SMART_EVENT_UPDATE: case SMART_EVENT_UPDATE:
case SMART_EVENT_UPDATE_IC: case SMART_EVENT_UPDATE_IC:
case SMART_EVENT_UPDATE_OOC: case SMART_EVENT_UPDATE_OOC:
case SMART_EVENT_RANGE:
case SMART_EVENT_AREA_RANGE:
case SMART_EVENT_AREA_CASTING:
case SMART_EVENT_IS_BEHIND_TARGET:
case SMART_EVENT_FRIENDLY_HEALTH_PCT:
RecalcTimer(e, e.event.minMaxRepeat.min, e.event.minMaxRepeat.max); RecalcTimer(e, e.event.minMaxRepeat.min, e.event.minMaxRepeat.max);
break; break;
case SMART_EVENT_OOC_LOS:
case SMART_EVENT_IC_LOS:
// Xinef: cooldown should be processed AFTER action is done, not before...
//RecalcTimer(e, e.event.los.cooldownMin, e.event.los.cooldownMax);
//break;
case SMART_EVENT_DISTANCE_CREATURE: case SMART_EVENT_DISTANCE_CREATURE:
case SMART_EVENT_DISTANCE_GAMEOBJECT: case SMART_EVENT_DISTANCE_GAMEOBJECT:
RecalcTimer(e, e.event.distance.repeat, e.event.distance.repeat); RecalcTimer(e, e.event.distance.repeat, e.event.distance.repeat);
@@ -4519,9 +4541,6 @@ void SmartScript::InitTimer(SmartScriptHolder& e)
case SMART_EVENT_NEAR_UNIT_NEGATION: case SMART_EVENT_NEAR_UNIT_NEGATION:
RecalcTimer(e, e.event.nearUnit.timer, e.event.nearUnit.timer); RecalcTimer(e, e.event.nearUnit.timer, e.event.nearUnit.timer);
break; break;
case SMART_EVENT_AREA_CASTING:
RecalcTimer(e, e.event.areaCasting.min, e.event.areaCasting.max);
break;
default: default:
e.active = true; e.active = true;
break; break;
@@ -4550,14 +4569,14 @@ void SmartScript::UpdateTimer(SmartScriptHolder& e, uint32 const diff)
if (e.timer < diff) if (e.timer < diff)
{ {
// delay spell cast event if another spell is being casted // delay spell cast for another AI tick if another spell is being cast
if (e.GetActionType() == SMART_ACTION_CAST) if (e.GetActionType() == SMART_ACTION_CAST)
{ {
if (!(e.action.cast.castFlags & SMARTCAST_INTERRUPT_PREVIOUS)) if (!(e.action.cast.castFlags & SMARTCAST_INTERRUPT_PREVIOUS))
{ {
if (me && me->HasUnitState(UNIT_STATE_CASTING)) if (me && me->HasUnitState(UNIT_STATE_CASTING))
{ {
e.timer = 1; e.timer = 1200;
return; return;
} }
} }
@@ -4566,9 +4585,9 @@ void SmartScript::UpdateTimer(SmartScriptHolder& e, uint32 const diff)
// Delay flee for assist event if casting // Delay flee for assist event if casting
if (e.GetActionType() == SMART_ACTION_FLEE_FOR_ASSIST && me && me->HasUnitState(UNIT_STATE_CASTING)) if (e.GetActionType() == SMART_ACTION_FLEE_FOR_ASSIST && me && me->HasUnitState(UNIT_STATE_CASTING))
{ {
e.timer = 1; e.timer = 1200;
return; return;
} } // @TODO: Can't these be handled by the action themselves instead? Less expensive
e.active = true;//activate events with cooldown e.active = true;//activate events with cooldown
switch (e.GetEventType())//process ONLY timed events switch (e.GetEventType())//process ONLY timed events
@@ -4809,10 +4828,10 @@ void SmartScript::OnInitialize(WorldObject* obj, AreaTrigger const* at)
InitTimer((*i));//calculate timers for first time use InitTimer((*i));//calculate timers for first time use
if (i->GetEventType() == SMART_EVENT_RANGE && i->GetActionType() == SMART_ACTION_ALLOW_COMBAT_MOVEMENT) if (i->GetEventType() == SMART_EVENT_RANGE && i->GetActionType() == SMART_ACTION_ALLOW_COMBAT_MOVEMENT)
{ {
if (i->action.combatMove.move == 1 && i->event.rangeRepeat.minRange > minEnableDist) if (i->action.combatMove.move == 1 && i->event.minMaxRepeat.rangeMin > minEnableDist)
minEnableDist = i->event.rangeRepeat.minRange; minEnableDist = i->event.minMaxRepeat.rangeMin;
else if (i->action.combatMove.move == 0 && (i->event.rangeRepeat.maxRange < maxDisableDist || maxDisableDist == 0)) else if (i->action.combatMove.move == 0 && (i->event.minMaxRepeat.rangeMax < maxDisableDist || maxDisableDist == 0))
maxDisableDist = i->event.rangeRepeat.maxRange; maxDisableDist = i->event.minMaxRepeat.rangeMax;
} }
// Xinef: if smartcast combat move flag is present // Xinef: if smartcast combat move flag is present

View File

@@ -264,29 +264,14 @@ void SmartAIMgr::LoadSmartAIFromDB()
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:
case SMART_EVENT_RANGE:
case SMART_EVENT_AREA_RANGE:
case SMART_EVENT_AREA_CASTING:
case SMART_EVENT_IS_BEHIND_TARGET:
if (temp.event.minMaxRepeat.repeatMin == 0 && temp.event.minMaxRepeat.repeatMax == 0) if (temp.event.minMaxRepeat.repeatMin == 0 && temp.event.minMaxRepeat.repeatMax == 0)
temp.event.event_flags |= SMART_EVENT_FLAG_NOT_REPEATABLE; temp.event.event_flags |= SMART_EVENT_FLAG_NOT_REPEATABLE;
break; break;
case SMART_EVENT_RANGE:
if (temp.event.rangeRepeat.repeatMin == 0 && temp.event.rangeRepeat.repeatMax == 0)
temp.event.event_flags |= SMART_EVENT_FLAG_NOT_REPEATABLE;
// Will only work properly if value is 0 or 1
if (temp.event.rangeRepeat.onlyFireOnRepeat > 1)
temp.event.rangeRepeat.onlyFireOnRepeat = 1;
break;
case SMART_EVENT_AREA_RANGE:
if (temp.event.areaRange.repeatMin == 0 && temp.event.areaRange.repeatMax == 0)
temp.event.event_flags |= SMART_EVENT_FLAG_NOT_REPEATABLE;
break;
case SMART_EVENT_VICTIM_CASTING: case SMART_EVENT_VICTIM_CASTING:
case SMART_EVENT_IS_BEHIND_TARGET:
if (temp.event.minMaxRepeat.min == 0 && temp.event.minMaxRepeat.max == 0)
temp.event.event_flags |= SMART_EVENT_FLAG_NOT_REPEATABLE;
break;
case SMART_EVENT_AREA_CASTING:
if (temp.event.areaCasting.repeatMin == 0 && temp.event.areaCasting.repeatMax == 0)
temp.event.event_flags |= SMART_EVENT_FLAG_NOT_REPEATABLE;
break;
case SMART_EVENT_FRIENDLY_IS_CC: case SMART_EVENT_FRIENDLY_IS_CC:
if (temp.event.friendlyCC.repeatMin == 0 && temp.event.friendlyCC.repeatMax == 0) if (temp.event.friendlyCC.repeatMin == 0 && temp.event.friendlyCC.repeatMax == 0)
temp.event.event_flags |= SMART_EVENT_FLAG_NOT_REPEATABLE; temp.event.event_flags |= SMART_EVENT_FLAG_NOT_REPEATABLE;
@@ -506,7 +491,7 @@ bool SmartAIMgr::CheckUnusedEventParams(SmartScriptHolder const& e)
case SMART_EVENT_DEATH: return NO_PARAMS; case SMART_EVENT_DEATH: return NO_PARAMS;
case SMART_EVENT_EVADE: return NO_PARAMS; case SMART_EVENT_EVADE: return NO_PARAMS;
case SMART_EVENT_SPELLHIT: return sizeof(SmartEvent::spellHit); case SMART_EVENT_SPELLHIT: return sizeof(SmartEvent::spellHit);
case SMART_EVENT_RANGE: return sizeof(SmartEvent::rangeRepeat); case SMART_EVENT_RANGE: return sizeof(SmartEvent::minMaxRepeat);
case SMART_EVENT_OOC_LOS: return sizeof(SmartEvent::los); case SMART_EVENT_OOC_LOS: return sizeof(SmartEvent::los);
case SMART_EVENT_RESPAWN: return sizeof(SmartEvent::respawn); case SMART_EVENT_RESPAWN: return sizeof(SmartEvent::respawn);
case SMART_EVENT_TARGET_HEALTH_PCT: return sizeof(SmartEvent::minMaxRepeat); case SMART_EVENT_TARGET_HEALTH_PCT: return sizeof(SmartEvent::minMaxRepeat);
@@ -564,7 +549,7 @@ bool SmartAIMgr::CheckUnusedEventParams(SmartScriptHolder const& e)
case SMART_EVENT_GOSSIP_HELLO: return sizeof(SmartEvent::gossipHello); case SMART_EVENT_GOSSIP_HELLO: return sizeof(SmartEvent::gossipHello);
case SMART_EVENT_FOLLOW_COMPLETED: return NO_PARAMS; case SMART_EVENT_FOLLOW_COMPLETED: return NO_PARAMS;
case SMART_EVENT_EVENT_PHASE_CHANGE: return sizeof(SmartEvent::eventPhaseChange); case SMART_EVENT_EVENT_PHASE_CHANGE: return sizeof(SmartEvent::eventPhaseChange);
case SMART_EVENT_IS_BEHIND_TARGET: return sizeof(SmartEvent::behindTarget); case SMART_EVENT_IS_BEHIND_TARGET: return sizeof(SmartEvent::minMaxRepeat);
case SMART_EVENT_GAME_EVENT_START: return sizeof(SmartEvent::gameEvent); case SMART_EVENT_GAME_EVENT_START: return sizeof(SmartEvent::gameEvent);
case SMART_EVENT_GAME_EVENT_END: return sizeof(SmartEvent::gameEvent); case SMART_EVENT_GAME_EVENT_END: return sizeof(SmartEvent::gameEvent);
case SMART_EVENT_GO_STATE_CHANGED: return sizeof(SmartEvent::goStateChanged); case SMART_EVENT_GO_STATE_CHANGED: return sizeof(SmartEvent::goStateChanged);
@@ -584,8 +569,8 @@ bool SmartAIMgr::CheckUnusedEventParams(SmartScriptHolder const& e)
case SMART_EVENT_NEAR_PLAYERS_NEGATION: return sizeof(SmartEvent::nearPlayerNegation); case SMART_EVENT_NEAR_PLAYERS_NEGATION: return sizeof(SmartEvent::nearPlayerNegation);
case SMART_EVENT_NEAR_UNIT: return sizeof(SmartEvent::nearUnit); case SMART_EVENT_NEAR_UNIT: return sizeof(SmartEvent::nearUnit);
case SMART_EVENT_NEAR_UNIT_NEGATION: return sizeof(SmartEvent::nearUnitNegation); case SMART_EVENT_NEAR_UNIT_NEGATION: return sizeof(SmartEvent::nearUnitNegation);
case SMART_EVENT_AREA_CASTING: return sizeof(SmartEvent::areaCasting); case SMART_EVENT_AREA_CASTING: return sizeof(SmartEvent::minMaxRepeat);
case SMART_EVENT_AREA_RANGE: return sizeof(SmartEvent::areaRange); case SMART_EVENT_AREA_RANGE: return sizeof(SmartEvent::minMaxRepeat);
default: default:
LOG_WARN("sql.sql", "SmartAIMgr: entryorguid {} source_type {} id {} action_type {} is using an event {} with no unused params specified in SmartAIMgr::CheckUnusedEventParams(), please report this.", LOG_WARN("sql.sql", "SmartAIMgr: entryorguid {} source_type {} id {} action_type {} is using an event {} with no unused params specified in SmartAIMgr::CheckUnusedEventParams(), please report this.",
e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.GetEventType()); e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.GetEventType());
@@ -781,6 +766,7 @@ bool SmartAIMgr::CheckUnusedActionParams(SmartScriptHolder const& e)
case SMART_ACTION_SUMMON_RADIAL: return sizeof(SmartAction::radialSummon); case SMART_ACTION_SUMMON_RADIAL: return sizeof(SmartAction::radialSummon);
case SMART_ACTION_PLAY_SPELL_VISUAL: return sizeof(SmartAction::spellVisual); case SMART_ACTION_PLAY_SPELL_VISUAL: return sizeof(SmartAction::spellVisual);
case SMART_ACTION_FOLLOW_GROUP: return sizeof(SmartAction::followGroup); case SMART_ACTION_FOLLOW_GROUP: return sizeof(SmartAction::followGroup);
case SMART_ACTION_SET_ORIENTATION_TARGET: return sizeof(SmartAction::orientationTarget);
default: default:
LOG_WARN("sql.sql", "SmartAIMgr: entryorguid {} source_type {} id {} action_type {} is using an action with no unused params specified in SmartAIMgr::CheckUnusedActionParams(), please report this.", LOG_WARN("sql.sql", "SmartAIMgr: entryorguid {} source_type {} id {} action_type {} is using an action with no unused params specified in SmartAIMgr::CheckUnusedActionParams(), please report this.",
e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType()); e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType());
@@ -963,21 +949,17 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
if (!IsMinMaxValid(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax)) if (!IsMinMaxValid(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax))
return false; return false;
break; break;
case SMART_EVENT_RANGE:
if (!IsMinMaxValid(e, e.event.rangeRepeat.minRange, e.event.rangeRepeat.maxRange))
return false;
if (!IsMinMaxValid(e, e.event.rangeRepeat.repeatMin, e.event.rangeRepeat.repeatMax))
return false;
break;
case SMART_EVENT_AREA_RANGE: case SMART_EVENT_AREA_RANGE:
if (!IsMinMaxValid(e, e.event.areaRange.min, e.event.areaRange.max)) case SMART_EVENT_AREA_CASTING:
case SMART_EVENT_IS_BEHIND_TARGET:
case SMART_EVENT_RANGE:
if (!IsMinMaxValid(e, e.event.minMaxRepeat.min, e.event.minMaxRepeat.max))
return false; return false;
if (!IsMinMaxValid(e, e.event.areaRange.repeatMin, e.event.areaRange.repeatMax)) if (!IsMinMaxValid(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax))
return false; return false;
if (!IsMinMaxValid(e, e.event.areaRange.rangeMin, e.event.areaRange.rangeMax)) if (!IsMinMaxValid(e, e.event.minMaxRepeat.rangeMin, e.event.minMaxRepeat.rangeMax))
return false; return false;
break; break;
@@ -1070,16 +1052,6 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
if (!IsMinMaxValid(e, e.event.targetCasting.repeatMin, e.event.targetCasting.repeatMax)) if (!IsMinMaxValid(e, e.event.targetCasting.repeatMin, e.event.targetCasting.repeatMax))
return false; return false;
break; break;
case SMART_EVENT_AREA_CASTING:
if (!IsMinMaxValid(e, e.event.areaCasting.min, e.event.areaCasting.max))
return false;
if (!IsMinMaxValid(e, e.event.areaCasting.repeatMin, e.event.areaCasting.repeatMax))
return false;
if (!IsMinMaxValid(e, e.event.areaCasting.rangeMin, e.event.areaCasting.rangeMax))
return false;
break;
case SMART_EVENT_PASSENGER_BOARDED: case SMART_EVENT_PASSENGER_BOARDED:
case SMART_EVENT_PASSENGER_REMOVED: case SMART_EVENT_PASSENGER_REMOVED:
if (!IsMinMaxValid(e, e.event.minMax.repeatMin, e.event.minMax.repeatMax)) if (!IsMinMaxValid(e, e.event.minMax.repeatMin, e.event.minMax.repeatMax))
@@ -1185,10 +1157,6 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
} }
break; break;
} }
case SMART_EVENT_IS_BEHIND_TARGET:
if (!IsMinMaxValid(e, e.event.behindTarget.cooldownMin, e.event.behindTarget.cooldownMax))
return false;
break;
case SMART_EVENT_GAME_EVENT_START: case SMART_EVENT_GAME_EVENT_START:
case SMART_EVENT_GAME_EVENT_END: case SMART_EVENT_GAME_EVENT_END:
{ {
@@ -1207,10 +1175,13 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
break; break;
} }
case SMART_EVENT_FRIENDLY_HEALTH_PCT: case SMART_EVENT_FRIENDLY_HEALTH_PCT:
if (!IsMinMaxValid(e, e.event.friendlyHealthPct.min, e.event.friendlyHealthPct.max))
return false;
if (!IsMinMaxValid(e, e.event.friendlyHealthPct.repeatMin, e.event.friendlyHealthPct.repeatMax)) if (!IsMinMaxValid(e, e.event.friendlyHealthPct.repeatMin, e.event.friendlyHealthPct.repeatMax))
return false; return false;
if (e.event.friendlyHealthPct.maxHpPct > 100 || e.event.friendlyHealthPct.minHpPct > 100) if (e.event.friendlyHealthPct.hpPct > 100)
{ {
LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} has pct value above 100, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType()); LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} has pct value above 100, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType());
return false; return false;
@@ -1971,6 +1942,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
case SMART_ACTION_SUMMON_RADIAL: case SMART_ACTION_SUMMON_RADIAL:
case SMART_ACTION_PLAY_SPELL_VISUAL: case SMART_ACTION_PLAY_SPELL_VISUAL:
case SMART_ACTION_FOLLOW_GROUP: case SMART_ACTION_FOLLOW_GROUP:
case SMART_ACTION_SET_ORIENTATION_TARGET:
break; break;
default: default:
LOG_ERROR("sql.sql", "SmartAIMgr: Not handled action_type({}), event_type({}), Entry {} SourceType {} Event {}, skipped.", e.GetActionType(), e.GetEventType(), e.entryOrGuid, e.GetScriptType(), e.event_id); LOG_ERROR("sql.sql", "SmartAIMgr: Not handled action_type({}), event_type({}), Entry {} SourceType {} Event {}, skipped.", e.GetActionType(), e.GetEventType(), e.entryOrGuid, e.GetScriptType(), e.event_id);

View File

@@ -124,7 +124,7 @@ enum SMART_EVENT
SMART_EVENT_DEATH = 6, // NONE SMART_EVENT_DEATH = 6, // NONE
SMART_EVENT_EVADE = 7, // NONE SMART_EVENT_EVADE = 7, // NONE
SMART_EVENT_SPELLHIT = 8, // SpellID, School, CooldownMin, CooldownMax SMART_EVENT_SPELLHIT = 8, // SpellID, School, CooldownMin, CooldownMax
SMART_EVENT_RANGE = 9, // minRange, maxRange, repeatMin, repeatMax, onlyFireOnRepeat SMART_EVENT_RANGE = 9, // min, max, repeatMin, repeatMax, rangeMin, rangeMax
SMART_EVENT_OOC_LOS = 10, // HostilityMode, MaxRnage, CooldownMin, CooldownMax, PlayerOnly SMART_EVENT_OOC_LOS = 10, // HostilityMode, MaxRnage, CooldownMin, CooldownMax, PlayerOnly
SMART_EVENT_RESPAWN = 11, // type, MapId, ZoneId SMART_EVENT_RESPAWN = 11, // type, MapId, ZoneId
SMART_EVENT_TARGET_HEALTH_PCT = 12, // HPMin%, HPMax%, RepeatMin, RepeatMax SMART_EVENT_TARGET_HEALTH_PCT = 12, // HPMin%, HPMax%, RepeatMin, RepeatMax
@@ -182,14 +182,14 @@ enum SMART_EVENT
SMART_EVENT_GOSSIP_HELLO = 64, // event_para_1 (only) 0 = no filter set, always execute action, 1 = GossipHello only filter set, skip action if reportUse, 2 = reportUse only filter set, skip action if GossipHello SMART_EVENT_GOSSIP_HELLO = 64, // event_para_1 (only) 0 = no filter set, always execute action, 1 = GossipHello only filter set, skip action if reportUse, 2 = reportUse only filter set, skip action if GossipHello
SMART_EVENT_FOLLOW_COMPLETED = 65, // none SMART_EVENT_FOLLOW_COMPLETED = 65, // none
SMART_EVENT_EVENT_PHASE_CHANGE = 66, // event phase mask (<= SMART_EVENT_PHASE_ALL) SMART_EVENT_EVENT_PHASE_CHANGE = 66, // event phase mask (<= SMART_EVENT_PHASE_ALL)
SMART_EVENT_IS_BEHIND_TARGET = 67, // cooldownMin, CooldownMax SMART_EVENT_IS_BEHIND_TARGET = 67, // min, max, repeatMin, repeatMax, rangeMin, rangeMax
SMART_EVENT_GAME_EVENT_START = 68, // game_event.Entry SMART_EVENT_GAME_EVENT_START = 68, // game_event.Entry
SMART_EVENT_GAME_EVENT_END = 69, // game_event.Entry SMART_EVENT_GAME_EVENT_END = 69, // game_event.Entry
SMART_EVENT_GO_STATE_CHANGED = 70, // go state SMART_EVENT_GO_STATE_CHANGED = 70, // go state
SMART_EVENT_GO_EVENT_INFORM = 71, // eventId SMART_EVENT_GO_EVENT_INFORM = 71, // eventId
SMART_EVENT_ACTION_DONE = 72, // eventId (SharedDefines.EventId) SMART_EVENT_ACTION_DONE = 72, // eventId (SharedDefines.EventId)
SMART_EVENT_ON_SPELLCLICK = 73, // clicker (unit) SMART_EVENT_ON_SPELLCLICK = 73, // clicker (unit)
SMART_EVENT_FRIENDLY_HEALTH_PCT = 74, // minHpPct, maxHpPct, repeatMin, repeatMax SMART_EVENT_FRIENDLY_HEALTH_PCT = 74, // min, max, repeatMin, repeatMax, hpPct, range
SMART_EVENT_DISTANCE_CREATURE = 75, // guid, entry, distance, repeat SMART_EVENT_DISTANCE_CREATURE = 75, // guid, entry, distance, repeat
SMART_EVENT_DISTANCE_GAMEOBJECT = 76, // guid, entry, distance, repeat SMART_EVENT_DISTANCE_GAMEOBJECT = 76, // guid, entry, distance, repeat
SMART_EVENT_COUNTER_SET = 77, // id, value, cooldownMin, cooldownMax SMART_EVENT_COUNTER_SET = 77, // id, value, cooldownMin, cooldownMax
@@ -210,8 +210,8 @@ enum SMART_EVENT
SMART_EVENT_NEAR_PLAYERS_NEGATION = 102, // max, radius, first timer, repeatMin, repeatMax SMART_EVENT_NEAR_PLAYERS_NEGATION = 102, // max, radius, first timer, repeatMin, repeatMax
SMART_EVENT_NEAR_UNIT = 103, // type (0: creature 1: gob), entry, count, range, timer SMART_EVENT_NEAR_UNIT = 103, // type (0: creature 1: gob), entry, count, range, timer
SMART_EVENT_NEAR_UNIT_NEGATION = 104, // type (0: creature 1: gob), entry, count, range, timer SMART_EVENT_NEAR_UNIT_NEGATION = 104, // type (0: creature 1: gob), entry, count, range, timer
SMART_EVENT_AREA_CASTING = 105, // min, max, repeatMin, repeatMax, range SMART_EVENT_AREA_CASTING = 105, // min, max, repeatMin, repeatMax, rangeMin, rangeMax
SMART_EVENT_AREA_RANGE = 106, // min, max, repeatMin, repeatMax, range SMART_EVENT_AREA_RANGE = 106, // min, max, repeatMin, repeatMax, rangeMin, rangeMax
SMART_EVENT_AC_END = 107 SMART_EVENT_AC_END = 107
}; };
@@ -230,17 +230,10 @@ struct SmartEvent
uint32 max; uint32 max;
uint32 repeatMin; uint32 repeatMin;
uint32 repeatMax; uint32 repeatMax;
uint32 rangeMin;
uint32 rangeMax;
} minMaxRepeat; } minMaxRepeat;
struct
{
uint32 minRange;
uint32 maxRange;
uint32 repeatMin;
uint32 repeatMax;
uint32 onlyFireOnRepeat;
} rangeRepeat;
struct struct
{ {
uint32 cooldownMin; uint32 cooldownMin;
@@ -430,12 +423,6 @@ struct SmartEvent
uint32 phasemask; uint32 phasemask;
} eventPhaseChange; } eventPhaseChange;
struct
{
uint32 cooldownMin;
uint32 cooldownMax;
} behindTarget;
struct struct
{ {
uint32 gameEventId; uint32 gameEventId;
@@ -458,10 +445,11 @@ struct SmartEvent
struct struct
{ {
uint32 minHpPct; uint32 min;
uint32 maxHpPct; uint32 max;
uint32 repeatMin; uint32 repeatMin;
uint32 repeatMax; uint32 repeatMax;
uint32 hpPct;
uint32 radius; uint32 radius;
} friendlyHealthPct; } friendlyHealthPct;
@@ -517,26 +505,6 @@ struct SmartEvent
uint32 timer; uint32 timer;
} nearUnitNegation; } nearUnitNegation;
struct
{
uint32 min;
uint32 max;
uint32 repeatMin;
uint32 repeatMax;
uint32 rangeMin;
uint32 rangeMax;
} areaCasting;
struct
{
uint32 min;
uint32 max;
uint32 repeatMin;
uint32 repeatMax;
uint32 rangeMin;
uint32 rangeMax;
} areaRange;
struct struct
{ {
uint32 param1; uint32 param1;
@@ -743,8 +711,9 @@ enum SMART_ACTION
SMART_ACTION_SUMMON_RADIAL = 228, // summonEntry, summonDuration, repetitions, startAngle, stepAngle, dist SMART_ACTION_SUMMON_RADIAL = 228, // summonEntry, summonDuration, repetitions, startAngle, stepAngle, dist
SMART_ACTION_PLAY_SPELL_VISUAL = 229, // visualId, visualIdImpact SMART_ACTION_PLAY_SPELL_VISUAL = 229, // visualId, visualIdImpact
SMART_ACTION_FOLLOW_GROUP = 230, // followState, followType, dist SMART_ACTION_FOLLOW_GROUP = 230, // followState, followType, dist
SMART_ACTION_SET_ORIENTATION_TARGET = 231, // type, target_type, target_param1, target_param2, target_param3, target_param4
SMART_ACTION_AC_END = 231, // placeholder SMART_ACTION_AC_END = 232, // placeholder
}; };
enum class SmartActionSummonCreatureFlags enum class SmartActionSummonCreatureFlags
@@ -1453,6 +1422,16 @@ struct SmartAction
uint32 followType; uint32 followType;
uint32 dist; uint32 dist;
} followGroup; } followGroup;
struct
{
uint32 type;
uint32 targetType;
uint32 targetParam1;
uint32 targetParam2;
uint32 targetParam3;
uint32 targetParam4;
} orientationTarget;
//! Note for any new future actions //! Note for any new future actions
//! All parameters must have type uint32 //! All parameters must have type uint32
@@ -1484,10 +1463,10 @@ enum SMARTAI_TARGETS
SMART_TARGET_NONE = 0, // NONE SMART_TARGET_NONE = 0, // NONE
SMART_TARGET_SELF = 1, // Self cast SMART_TARGET_SELF = 1, // Self cast
SMART_TARGET_VICTIM = 2, // Our current target (ie: highest aggro) SMART_TARGET_VICTIM = 2, // Our current target (ie: highest aggro)
SMART_TARGET_HOSTILE_SECOND_AGGRO = 3, // Second highest aggro, maxdist, playerOnly, powerType + 1 SMART_TARGET_HOSTILE_SECOND_AGGRO = 3, // Second highest aggro, maxdist, playerOnly, powerType + 1, missing aura
SMART_TARGET_HOSTILE_LAST_AGGRO = 4, // Dead last on aggro, maxdist, playerOnly, powerType + 1 SMART_TARGET_HOSTILE_LAST_AGGRO = 4, // Dead last on aggro, maxdist, playerOnly, powerType + 1, missing aura
SMART_TARGET_HOSTILE_RANDOM = 5, // Just any random target on our threat list, maxdist, playerOnly, powerType + 1 SMART_TARGET_HOSTILE_RANDOM = 5, // Just any random target on our threat list, maxdist, playerOnly, powerType + 1, missing aura
SMART_TARGET_HOSTILE_RANDOM_NOT_TOP = 6, // Any random target except top threat, maxdist, playerOnly, powerType + 1 SMART_TARGET_HOSTILE_RANDOM_NOT_TOP = 6, // Any random target except top threat, maxdist, playerOnly, powerType + 1, missing aura
SMART_TARGET_ACTION_INVOKER = 7, // Unit who caused this Event to occur SMART_TARGET_ACTION_INVOKER = 7, // Unit who caused this Event to occur
SMART_TARGET_POSITION = 8, // use xyz from event params SMART_TARGET_POSITION = 8, // use xyz from event params
SMART_TARGET_CREATURE_RANGE = 9, // CreatureEntry(0any), minDist, maxDist, alive(0 - both, 1 - alive, 2 - dead) SMART_TARGET_CREATURE_RANGE = 9, // CreatureEntry(0any), minDist, maxDist, alive(0 - both, 1 - alive, 2 - dead)
@@ -1551,6 +1530,7 @@ struct SmartTarget
uint32 maxDist; uint32 maxDist;
SAIBool playerOnly; SAIBool playerOnly;
uint32 powerType; uint32 powerType;
uint32 aura;
} hostileRandom; } hostileRandom;
struct struct
@@ -1864,16 +1844,16 @@ const uint32 SmartAIEventMask[SMART_EVENT_AC_END][2] =
enum SmartEventFlags enum SmartEventFlags
{ {
SMART_EVENT_FLAG_NOT_REPEATABLE = 0x001, //Event can not repeat SMART_EVENT_FLAG_NOT_REPEATABLE = 0x001, // Event can not repeat
SMART_EVENT_FLAG_DIFFICULTY_0 = 0x002, //Event only occurs in instance difficulty 0 SMART_EVENT_FLAG_DIFFICULTY_0 = 0x002, // Event only occurs in instance difficulty 0
SMART_EVENT_FLAG_DIFFICULTY_1 = 0x004, //Event only occurs in instance difficulty 1 SMART_EVENT_FLAG_DIFFICULTY_1 = 0x004, // Event only occurs in instance difficulty 1
SMART_EVENT_FLAG_DIFFICULTY_2 = 0x008, //Event only occurs in instance difficulty 2 SMART_EVENT_FLAG_DIFFICULTY_2 = 0x008, // Event only occurs in instance difficulty 2
SMART_EVENT_FLAG_DIFFICULTY_3 = 0x010, //Event only occurs in instance difficulty 3 SMART_EVENT_FLAG_DIFFICULTY_3 = 0x010, // Event only occurs in instance difficulty 3
SMART_EVENT_FLAG_RESERVED_5 = 0x020, SMART_EVENT_FLAG_RESERVED_5 = 0x020,
SMART_EVENT_FLAG_RESERVED_6 = 0x040, SMART_EVENT_FLAG_RESERVED_6 = 0x040,
SMART_EVENT_FLAG_DEBUG_ONLY = 0x080, //Event only occurs in debug build SMART_EVENT_FLAG_DEBUG_ONLY = 0x080, // Event only occurs in debug build
SMART_EVENT_FLAG_DONT_RESET = 0x100, //Event will not reset in SmartScript::OnReset() SMART_EVENT_FLAG_DONT_RESET = 0x100, // Event will not reset in SmartScript::OnReset()
SMART_EVENT_FLAG_WHILE_CHARMED = 0x200, //Event occurs even if AI owner is charmed SMART_EVENT_FLAG_WHILE_CHARMED = 0x200, // Event occurs even if AI owner is charmed
SMART_EVENT_FLAG_DIFFICULTY_ALL = (SMART_EVENT_FLAG_DIFFICULTY_0 | SMART_EVENT_FLAG_DIFFICULTY_1 | SMART_EVENT_FLAG_DIFFICULTY_2 | SMART_EVENT_FLAG_DIFFICULTY_3), SMART_EVENT_FLAG_DIFFICULTY_ALL = (SMART_EVENT_FLAG_DIFFICULTY_0 | SMART_EVENT_FLAG_DIFFICULTY_1 | SMART_EVENT_FLAG_DIFFICULTY_2 | SMART_EVENT_FLAG_DIFFICULTY_3),
SMART_EVENT_FLAGS_ALL = (SMART_EVENT_FLAG_NOT_REPEATABLE | SMART_EVENT_FLAG_DIFFICULTY_ALL | SMART_EVENT_FLAG_RESERVED_5 | SMART_EVENT_FLAG_RESERVED_6 | SMART_EVENT_FLAG_DEBUG_ONLY | SMART_EVENT_FLAG_DONT_RESET | SMART_EVENT_FLAG_WHILE_CHARMED) SMART_EVENT_FLAGS_ALL = (SMART_EVENT_FLAG_NOT_REPEATABLE | SMART_EVENT_FLAG_DIFFICULTY_ALL | SMART_EVENT_FLAG_RESERVED_5 | SMART_EVENT_FLAG_RESERVED_6 | SMART_EVENT_FLAG_DEBUG_ONLY | SMART_EVENT_FLAG_DONT_RESET | SMART_EVENT_FLAG_WHILE_CHARMED)
@@ -1881,14 +1861,15 @@ enum SmartEventFlags
enum SmartCastFlags enum SmartCastFlags
{ {
SMARTCAST_INTERRUPT_PREVIOUS = 0x01, //Interrupt any spell casting SMARTCAST_INTERRUPT_PREVIOUS = 0x001, // Interrupt any spell casting
SMARTCAST_TRIGGERED = 0x02, //Triggered (this makes spell cost zero mana and have no cast time) SMARTCAST_TRIGGERED = 0x002, // Triggered (this makes spell cost zero mana and have no cast time)
//CAST_FORCE_CAST = 0x04, //Forces cast even if creature is out of mana or out of range //CAST_FORCE_CAST = 0x004, // Forces cast even if creature is out of mana or out of range
//CAST_NO_MELEE_IF_OOM = 0x08, //Prevents creature from entering melee if out of mana or out of range //CAST_NO_MELEE_IF_OOM = 0x008, // Prevents creature from entering melee if out of mana or out of range
//CAST_FORCE_TARGET_SELF = 0x10, //Forces the target to cast this spell on itself //CAST_FORCE_TARGET_SELF = 0x010, // Forces the target to cast this spell on itself
SMARTCAST_AURA_NOT_PRESENT = 0x20, //Only casts the spell if the target does not have an aura from the spell SMARTCAST_AURA_NOT_PRESENT = 0x020, // Only casts the spell if the target does not have an aura from the spell
SMARTCAST_COMBAT_MOVE = 0x40, //Prevents combat movement if cast successful. Allows movement on range, OOM, LOS SMARTCAST_COMBAT_MOVE = 0x040, // Prevents combat movement if cast successful. Allows movement on range, OOM, LOS
SMARTCAST_THREATLIST_NOT_SINGLE = 0x80 //Only cast if the source's threatlist is higher than one. This includes pets (see Skeram's True Fulfillment) SMARTCAST_THREATLIST_NOT_SINGLE = 0x080, // Only cast if the source's threatlist is higher than one. This includes pets (see Skeram's True Fulfillment)
SMARTCAST_TARGET_POWER_MANA = 0x100 // Only cast if the target has power type mana (e.g. Mana Drain)
}; };
enum SmartFollowType enum SmartFollowType