feat(Core/SmartAI): Add more smart events (#16642)

* init

* :)

* Update rev_1687966694240866600.sql

* >:)

change name from unit -> target
fix typo

Co-Authored-By: Angelo Venturini <nefertum.dev@protonmail.com>

* Update data/sql/updates/pending_db_world/rev_1687966694240866600.sql

Co-authored-by: Francesco Borzì <borzifrancesco@gmail.com>

* more_events

* Update SmartScriptMgr.cpp

---------

Co-authored-by: Angelo Venturini <nefertum.dev@protonmail.com>
Co-authored-by: Francesco Borzì <borzifrancesco@gmail.com>
This commit is contained in:
Gultask
2023-07-02 03:57:56 -03:00
committed by GitHub
parent d0fa5f04ef
commit 54f8386d99
4 changed files with 148 additions and 23 deletions
@@ -0,0 +1,3 @@
--
UPDATE `smart_scripts` SET `event_param5`=5000 WHERE `entryorguid` = 16420 AND `source_type` = 0 AND `id`=0;
UPDATE `smart_scripts` SET `event_param5`=1000 WHERE `entryorguid` = 30085 AND `source_type` = 0 AND `id` = 1;
+94 -15
View File
@@ -4208,34 +4208,105 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui
break; break;
case SMART_EVENT_NEAR_PLAYERS: case SMART_EVENT_NEAR_PLAYERS:
{ {
ObjectVector units; uint32 playerCount = 0;
GetWorldObjectsInDist(units, static_cast<float>(e.event.nearPlayer.radius)); ObjectVector targets;
GetWorldObjectsInDist(targets, static_cast<float>(e.event.nearPlayer.radius));
if (!units.empty()) if (!targets.empty())
{ {
if (!unit || unit->GetTypeId() != TYPEID_PLAYER) for (WorldObject* target : targets)
return; {
if (IsPlayer(target))
playerCount++;
if (units.size() >= e.event.nearPlayer.minCount) if (playerCount >= e.event.nearPlayer.minCount)
ProcessAction(e, unit); ProcessAction(e, target->ToUnit());
} }
RecalcTimer(e, e.event.nearPlayer.checkTimer, e.event.nearPlayer.checkTimer); }
RecalcTimer(e, e.event.nearPlayer.repeatMin, e.event.nearPlayer.repeatMax);
break; break;
} }
case SMART_EVENT_NEAR_PLAYERS_NEGATION: case SMART_EVENT_NEAR_PLAYERS_NEGATION:
{ {
ObjectVector units; uint32 playerCount = 0;
GetWorldObjectsInDist(units, static_cast<float>(e.event.nearPlayerNegation.radius)); ObjectVector targets;
GetWorldObjectsInDist(targets, static_cast<float>(e.event.nearPlayerNegation.radius));
if (!units.empty()) if (!targets.empty())
{ {
if (!unit || unit->GetTypeId() != TYPEID_PLAYER) for (WorldObject* target : targets)
return; {
if (IsPlayer(target))
playerCount++;
}
if (units.size() < e.event.nearPlayerNegation.minCount) if (playerCount <= e.event.nearPlayerNegation.maxCount)
ProcessAction(e, unit); ProcessAction(e, unit);
} }
RecalcTimer(e, e.event.nearPlayerNegation.checkTimer, e.event.nearPlayerNegation.checkTimer); RecalcTimer(e, e.event.nearPlayerNegation.repeatMin, e.event.nearPlayerNegation.repeatMax);
break;
}
case SMART_EVENT_NEAR_UNIT:
{
uint32 unitCount = 0;
ObjectVector targets;
GetWorldObjectsInDist(targets, static_cast<float>(e.event.nearUnit.range));
if (!targets.empty())
{
if (e.event.nearUnit.type)
{
for (WorldObject* target : targets)
{
if (IsGameObject(target) && target->GetEntry() == e.event.nearUnit.entry)
unitCount++;
}
}
else
{
for (WorldObject* target : targets)
{
if (IsCreature(target) && target->GetEntry() == e.event.nearUnit.entry)
unitCount++;
}
}
if (unitCount >= e.event.nearUnit.count)
ProcessAction(e, unit);
}
RecalcTimer(e, e.event.nearUnit.timer, e.event.nearUnit.timer);
break;
}
case SMART_EVENT_AREA_CASTING:
{
if (!me || !me->IsEngaged())
return;
float range = static_cast<float>(e.event.areaCasting.range);
ThreatContainer::StorageType threatList = me->GetThreatMgr().GetThreatList();
for (ThreatContainer::StorageType::const_iterator i = threatList.begin(); i != threatList.end(); ++i)
{
if (Unit* target = ObjectAccessor::GetUnit(*me, (*i)->getUnitGuid()))
{
if (e.event.areaCasting.range && !me->IsWithinDistInMap(target, range))
continue;
if (!target || !target->IsNonMeleeSpellCast(false, false, true))
continue;
if (e.event.areaCasting.spellId > 0)
if (Spell* currSpell = target->GetCurrentSpell(CURRENT_GENERIC_SPELL))
if (currSpell->m_spellInfo->Id != e.event.areaCasting.spellId)
continue;
ProcessAction(e, target);
RecalcTimer(e, e.event.areaCasting.repeatMin, e.event.areaCasting.repeatMin);
return;
}
}
// If no targets are found and it's off cooldown, check again
RecalcTimer(e, e.event.areaCasting.checkTimer, e.event.areaCasting.checkTimer);
break; break;
} }
default: default:
@@ -4274,6 +4345,12 @@ void SmartScript::InitTimer(SmartScriptHolder& e)
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);
break; break;
case SMART_EVENT_NEAR_UNIT:
RecalcTimer(e, e.event.nearUnit.timer, e.event.nearUnit.timer);
break;
case SMART_EVENT_AREA_CASTING:
RecalcTimer(e, e.event.areaCasting.repeatMin, e.event.areaCasting.repeatMax);
break;
default: default:
e.active = true; e.active = true;
break; break;
@@ -4327,6 +4404,7 @@ void SmartScript::UpdateTimer(SmartScriptHolder& e, uint32 const diff)
{ {
case SMART_EVENT_NEAR_PLAYERS: case SMART_EVENT_NEAR_PLAYERS:
case SMART_EVENT_NEAR_PLAYERS_NEGATION: case SMART_EVENT_NEAR_PLAYERS_NEGATION:
case SMART_EVENT_NEAR_UNIT:
case SMART_EVENT_UPDATE: case SMART_EVENT_UPDATE:
case SMART_EVENT_UPDATE_OOC: case SMART_EVENT_UPDATE_OOC:
case SMART_EVENT_UPDATE_IC: case SMART_EVENT_UPDATE_IC:
@@ -4336,6 +4414,7 @@ void SmartScript::UpdateTimer(SmartScriptHolder& e, uint32 const diff)
case SMART_EVENT_TARGET_MANA_PCT: case SMART_EVENT_TARGET_MANA_PCT:
case SMART_EVENT_RANGE: case SMART_EVENT_RANGE:
case SMART_EVENT_VICTIM_CASTING: case SMART_EVENT_VICTIM_CASTING:
case SMART_EVENT_AREA_CASTING:
case SMART_EVENT_FRIENDLY_HEALTH: case SMART_EVENT_FRIENDLY_HEALTH:
case SMART_EVENT_FRIENDLY_IS_CC: case SMART_EVENT_FRIENDLY_IS_CC:
case SMART_EVENT_FRIENDLY_MISSING_BUFF: case SMART_EVENT_FRIENDLY_MISSING_BUFF:
@@ -280,6 +280,10 @@ void SmartAIMgr::LoadSmartAIFromDB()
if (temp.event.minMaxRepeat.min == 0 && temp.event.minMaxRepeat.max == 0) if (temp.event.minMaxRepeat.min == 0 && temp.event.minMaxRepeat.max == 0)
temp.event.event_flags |= SMART_EVENT_FLAG_NOT_REPEATABLE; temp.event.event_flags |= SMART_EVENT_FLAG_NOT_REPEATABLE;
break; 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;
@@ -346,10 +350,12 @@ void SmartAIMgr::LoadSmartAIFromDB()
case SMART_EVENT_TARGET_MANA_PCT: case SMART_EVENT_TARGET_MANA_PCT:
case SMART_EVENT_RANGE: case SMART_EVENT_RANGE:
case SMART_EVENT_VICTIM_CASTING: case SMART_EVENT_VICTIM_CASTING:
case SMART_EVENT_AREA_CASTING:
case SMART_EVENT_TARGET_BUFFED: case SMART_EVENT_TARGET_BUFFED:
case SMART_EVENT_IS_BEHIND_TARGET: case SMART_EVENT_IS_BEHIND_TARGET:
case SMART_EVENT_INSTANCE_PLAYER_ENTER: case SMART_EVENT_INSTANCE_PLAYER_ENTER:
case SMART_EVENT_TRANSPORT_ADDCREATURE: case SMART_EVENT_TRANSPORT_ADDCREATURE:
case SMART_EVENT_NEAR_PLAYERS:
return true; return true;
default: default:
return false; return false;
@@ -572,6 +578,8 @@ bool SmartAIMgr::CheckUnusedEventParams(SmartScriptHolder const& e)
case SMART_EVENT_SUMMONED_UNIT_DIES: return sizeof(SmartEvent::summoned); case SMART_EVENT_SUMMONED_UNIT_DIES: return sizeof(SmartEvent::summoned);
case SMART_EVENT_NEAR_PLAYERS: return sizeof(SmartEvent::nearPlayer); case SMART_EVENT_NEAR_PLAYERS: return sizeof(SmartEvent::nearPlayer);
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_AREA_CASTING: return sizeof(SmartEvent::areaCasting);
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());
@@ -1043,6 +1051,16 @@ 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 (e.event.areaCasting.spellId > 0 && !sSpellMgr->GetSpellInfo(e.event.areaCasting.spellId))
{
LOG_ERROR("scripts.ai.sai", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses non-existent Spell entry {}, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.event.spellHit.spell);
return false;
}
if (!IsMinMaxValid(e, e.event.areaCasting.repeatMin, e.event.areaCasting.repeatMax))
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))
@@ -1272,6 +1290,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
case SMART_EVENT_GO_EVENT_INFORM: case SMART_EVENT_GO_EVENT_INFORM:
case SMART_EVENT_NEAR_PLAYERS: case SMART_EVENT_NEAR_PLAYERS:
case SMART_EVENT_NEAR_PLAYERS_NEGATION: case SMART_EVENT_NEAR_PLAYERS_NEGATION:
case SMART_EVENT_NEAR_UNIT:
case SMART_EVENT_TIMED_EVENT_TRIGGERED: case SMART_EVENT_TIMED_EVENT_TRIGGERED:
case SMART_EVENT_INSTANCE_PLAYER_ENTER: case SMART_EVENT_INSTANCE_PLAYER_ENTER:
case SMART_EVENT_TRANSPORT_RELOCATE: case SMART_EVENT_TRANSPORT_RELOCATE:
@@ -206,10 +206,12 @@ enum SMART_EVENT
/* AC Custom Events */ /* AC Custom Events */
SMART_EVENT_AC_START = 100, SMART_EVENT_AC_START = 100,
SMART_EVENT_NEAR_PLAYERS = 101, // min, radius, first timer, check timer SMART_EVENT_NEAR_PLAYERS = 101, // min, radius, first timer, repeatMin, repeatMax
SMART_EVENT_NEAR_PLAYERS_NEGATION = 102, // min, radius, first timer, check timer 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_AREA_CASTING = 104, // spellId (0: any), range (0: any), repeatMin, repeatMax, checkTimer
SMART_EVENT_AC_END = 103 SMART_EVENT_AC_END = 105
}; };
struct SmartEvent struct SmartEvent
@@ -482,17 +484,37 @@ struct SmartEvent
uint32 minCount; uint32 minCount;
uint32 radius; uint32 radius;
uint32 firstTimer; uint32 firstTimer;
uint32 checkTimer; uint32 repeatMin;
uint32 repeatMax;
} nearPlayer; } nearPlayer;
struct struct
{ {
uint32 minCount; uint32 maxCount;
uint32 radius; uint32 radius;
uint32 firstTimer; uint32 firstTimer;
uint32 checkTimer; uint32 repeatMin;
uint32 repeatMax;
} nearPlayerNegation; } nearPlayerNegation;
struct
{
uint32 type;
uint32 entry;
uint32 count;
uint32 range;
uint32 timer;
} nearUnit;
struct
{
uint32 spellId;
uint32 range;
uint32 repeatMin;
uint32 repeatMax;
uint32 checkTimer;
} areaCasting;
struct struct
{ {
uint32 param1; uint32 param1;
@@ -1795,8 +1817,10 @@ const uint32 SmartAIEventMask[SMART_EVENT_AC_END][2] =
{ 0, 0 }, // 98 { 0, 0 }, // 98
{ 0, 0 }, // 99 { 0, 0 }, // 99
{ 0, 0 }, // 100 { 0, 0 }, // 100
{SMART_EVENT_NEAR_PLAYERS, SMART_SCRIPT_TYPE_MASK_CREATURE }, {SMART_EVENT_NEAR_PLAYERS, SMART_SCRIPT_TYPE_MASK_CREATURE + SMART_SCRIPT_TYPE_MASK_GAMEOBJECT },
{SMART_EVENT_NEAR_PLAYERS_NEGATION, SMART_SCRIPT_TYPE_MASK_CREATURE } {SMART_EVENT_NEAR_PLAYERS_NEGATION, SMART_SCRIPT_TYPE_MASK_CREATURE + SMART_SCRIPT_TYPE_MASK_GAMEOBJECT },
{SMART_EVENT_NEAR_UNIT, SMART_SCRIPT_TYPE_MASK_CREATURE + SMART_SCRIPT_TYPE_MASK_GAMEOBJECT },
{SMART_EVENT_AREA_CASTING, SMART_SCRIPT_TYPE_MASK_CREATURE }
}; };
enum SmartEventFlags enum SmartEventFlags