mirror of
https://github.com/araxiaonline/TrinityCore.git
synced 2026-06-17 13:39:46 -04:00
Core/SmartAI: Various fixes and extensions for smart scripts: (#18673)
- Possible crashes fixed
- Memory leak fixed
- Implemented checking of vehicle conditions
- Extended eventphasemask to 12 bits (sql required to change DB field type)
- SMART_EVENT_GOSSIP_HELLO - added possibility to detect for gameobject reportUse call
- Renamed action SMART_ACTION_SET_FLY to SMART_ACTION_SET_DISABLE_GRAVITY (to reflect actual functionality)
- Added targetsLimit to action SMART_ACTION_CAST and SMART_ACTION_INVOKER_CAST to limit max amount of targets (selected randomly)
- Action SMART_ACTION_TALK corrected to always work as intended
- Properly call GroupEventHappens in action SMART_ACTION_CALL_GROUPEVENTHAPPENS if invoker was charmed or owned by the player
- Properly utilize followAngle in action SMART_ACTION_FOLLOW (db orientation should be in degrees), but keep backward compatibility
- Added action SMART_ACTION_SET_CAN_FLY (119) 0/1
- Added action SMART_ACTION_REMOVE_AURAS_BY_TYPE (120) AuraType, can be used to exit vehicle for example
- Added action SMART_ACTION_SET_SIGHT_DIST (121) sightDist
- Added action SMART_ACTION_FLEE (122) fleeTime
- Added action SMART_ACTION_ADD_THREAT (123) +threat, -threat
- Added action SMART_ACTION_LOAD_EQUIPMENT (124) equipmentId
- Added action SMART_ACTION_TRIGGER_RANDOM_TIMED_EVENT (125) minId, maxId
- Added action SMART_ACTION_REMOVE_ALL_GAMEOBJECTS (126), removes all owned gameobjects
- Added action SMART_ACTION_STOP_MOTION (127), stopMoving, movementExpired
- Extended target SMART_TARGET_HOSTILE_SECOND_AGGRO with following parameters maxdist, playerOnly, powerType + 1
- Extended target SMART_TARGET_HOSTILE_LAST_AGGRO with following parameters maxdist, playerOnly, powerType + 1
- Extended target SMART_TARGET_HOSTILE_RANDOM with following parameters maxdist, playerOnly, powerType + 1
- Extended target SMART_TARGET_HOSTILE_RANDOM_NOT_TOP with following parameters maxdist, playerOnly, powerType + 1
- Extended target SMART_TARGET_THREAT_LIST with maxdist
- Extended target SMART_TARGET_OWNER_OR_SUMMONER to be able to get charmer/owner of current owner
- Added new target SMART_TARGET_FARTHEST with maxDist, playerOnly, isInLos restrictions
- Added SpellHit hook to GameObjectAI and extended SmartGameObjectAI to call SMART_EVENT_SPELLHIT when gameobject is hit by spell
- Call GameObjectAI Reset hook on gameobject respawn (for ex. to reset one time events in smart scripts)
- Fixed some logic errors in code
- SmartAI Escorts properly despawn escortee if no players are in range
- Disable Evading while charming creature with SmartAI
- Don't call SMART_EVENT_RESPAWN for dead units before they actually respawn
- Don't call SMART_EVENT_RESPAWN for not spawned gameobjects
- Properly call SMART_EVENT_RESPAWN for gameobject respawn
- Allow action SMART_ACTION_SET_IN_COMBAT_WITH_ZONE to utilize targetlist
- Allow action SMART_ACTION_CALL_FOR_HELP to utilize targetList
- Allow action SMART_ACTION_SET_INVINCIBILITY_HP_LEVEL to utilize targetList
- Allow action SMART_ACTION_SET_VISIBILITY to utilize targetList
- Allow action SMART_ACTION_SET_ACTIVE to utilize targetList
- Allow action SMART_ACTION_ATTACK_START to select random attack target instead of first on the list
- Allow gameobjects to summon gameobjects with action SMART_ACTION_SUMMON_GO
- Properly store action invokers for action SMART_ACTION_WP_START, if no player invokers are found, distance despawn check won't be used
- Allow action SMART_ACTION_WP_RESUME to compensate for the state the unit actually is in (eg. combat)
- Allow action SMART_ACTION_MOVE_TO_POS to select random of the avaiable targets, not only the first one.
- Allow action SMART_ACTION_MOVE_TO_POS to utilize x, y, z parameters as an offset to calculated coordinates
- Action SMART_ACTION_RESPAWN_TARGET should never modify respawntime of already spawned gameobjects, use dedicated function
- Properly delete ontime events created by SMART_ACTION_CREATE_TIMED_EVENT
- If action could not be started because conditions were not satisfied, do not recalculate the waittime to action repeattime, use smaller value to recheck more frequently
- Allow target SMART_TARGET_CLOSEST_PLAYER to be used by gameobjects
- Allow target SMART_TARGET_OWNER_OR_SUMMONER to be used by gameobjects
- Fixed SMART_EVENT_COUNTER_SET to be only called for the id that was incremented
- Changed the way counters work
- Protect PhaseInc from surpassing maximum phase
- Added loading checks for missing NON_REPEATABLE flag if no repeatmin, repeatmax is set
- Added spell validation for SMART_ACTION_CROSS_CAST
(cherrypicked from b0ae5fadd1)
This commit is contained in:
@@ -235,7 +235,7 @@ void SmartAIMgr::LoadSmartAIFromDB()
|
||||
temp.event_id = fields[2].GetUInt16();
|
||||
temp.link = fields[3].GetUInt16();
|
||||
temp.event.type = (SMART_EVENT)fields[4].GetUInt8();
|
||||
temp.event.event_phase_mask = fields[5].GetUInt8();
|
||||
temp.event.event_phase_mask = fields[5].GetUInt16();
|
||||
temp.event.event_chance = fields[6].GetUInt8();
|
||||
temp.event.event_flags = fields[7].GetUInt16();
|
||||
|
||||
@@ -272,6 +272,50 @@ void SmartAIMgr::LoadSmartAIFromDB()
|
||||
if (!IsEventValid(temp))
|
||||
continue;
|
||||
|
||||
// specific check for timed events
|
||||
switch (temp.event.type)
|
||||
{
|
||||
case SMART_EVENT_UPDATE:
|
||||
case SMART_EVENT_UPDATE_OOC:
|
||||
case SMART_EVENT_UPDATE_IC:
|
||||
case SMART_EVENT_HEALT_PCT:
|
||||
case SMART_EVENT_TARGET_HEALTH_PCT:
|
||||
case SMART_EVENT_MANA_PCT:
|
||||
case SMART_EVENT_TARGET_MANA_PCT:
|
||||
case SMART_EVENT_RANGE:
|
||||
case SMART_EVENT_FRIENDLY_HEALTH:
|
||||
case SMART_EVENT_FRIENDLY_HEALTH_PCT:
|
||||
case SMART_EVENT_FRIENDLY_MISSING_BUFF:
|
||||
case SMART_EVENT_HAS_AURA:
|
||||
case SMART_EVENT_TARGET_BUFFED:
|
||||
if (temp.event.minMaxRepeat.repeatMin == 0 && temp.event.minMaxRepeat.repeatMax == 0 && !(temp.event.event_flags & SMART_EVENT_FLAG_NOT_REPEATABLE) && temp.source_type != SMART_SCRIPT_TYPE_TIMED_ACTIONLIST)
|
||||
{
|
||||
temp.event.event_flags |= SMART_EVENT_FLAG_NOT_REPEATABLE;
|
||||
TC_LOG_ERROR("sql.sql", "SmartAIMgr::LoadSmartAIFromDB: Entry " SI64FMTD " SourceType %u, Event %u, Missing Repeat flag.",
|
||||
temp.entryOrGuid, temp.GetScriptType(), temp.event_id);
|
||||
}
|
||||
break;
|
||||
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) && temp.source_type != SMART_SCRIPT_TYPE_TIMED_ACTIONLIST)
|
||||
{
|
||||
temp.event.event_flags |= SMART_EVENT_FLAG_NOT_REPEATABLE;
|
||||
TC_LOG_ERROR("sql.sql", "SmartAIMgr::LoadSmartAIFromDB: Entry " SI64FMTD " SourceType %u, Event %u, Missing Repeat flag.",
|
||||
temp.entryOrGuid, temp.GetScriptType(), temp.event_id);
|
||||
}
|
||||
break;
|
||||
case SMART_EVENT_FRIENDLY_IS_CC:
|
||||
if (temp.event.friendlyCC.repeatMin == 0 && temp.event.friendlyCC.repeatMax == 0 && !(temp.event.event_flags & SMART_EVENT_FLAG_NOT_REPEATABLE) && temp.source_type != SMART_SCRIPT_TYPE_TIMED_ACTIONLIST)
|
||||
{
|
||||
temp.event.event_flags |= SMART_EVENT_FLAG_NOT_REPEATABLE;
|
||||
TC_LOG_ERROR("sql.sql", "SmartAIMgr::LoadSmartAIFromDB: Entry " SI64FMTD " SourceType %u, Event %u, Missing Repeat flag.",
|
||||
temp.entryOrGuid, temp.GetScriptType(), temp.event_id);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// creature entry / guid not found in storage, create empty event list for it and increase counters
|
||||
if (mEventMap[source_type].find(temp.entryOrGuid) == mEventMap[source_type].end())
|
||||
{
|
||||
@@ -427,6 +471,7 @@ bool SmartAIMgr::IsTargetValid(SmartScriptHolder const& e)
|
||||
case SMART_TARGET_CLOSEST_FRIENDLY:
|
||||
case SMART_TARGET_STORED:
|
||||
case SMART_TARGET_LOOT_RECIPIENTS:
|
||||
case SMART_TARGET_FARTHEST:
|
||||
case SMART_TARGET_VEHICLE_ACCESSORY:
|
||||
break;
|
||||
default:
|
||||
@@ -1060,6 +1105,12 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SMART_ACTION_CROSS_CAST:
|
||||
{
|
||||
if (!IsSpellValid(e, e.action.crossCast.spell))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case SMART_ACTION_ADD_AURA:
|
||||
case SMART_ACTION_INVOKER_CAST:
|
||||
if (!IsSpellValid(e, e.action.cast.spell))
|
||||
@@ -1223,20 +1274,6 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
|
||||
TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u uses non-existent Map entry %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.teleport.mapID);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case SMART_ACTION_SET_COUNTER:
|
||||
if (e.action.setCounter.counterId == 0)
|
||||
{
|
||||
TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u uses wrong counterId %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.setCounter.counterId);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (e.action.setCounter.value == 0)
|
||||
{
|
||||
TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u uses wrong value %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.setCounter.value);
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
case SMART_ACTION_INSTALL_AI_TEMPLATE:
|
||||
if (e.action.installTtemplate.id >= SMARTAI_TEMPLATE_END)
|
||||
@@ -1413,6 +1450,15 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
|
||||
|
||||
break;
|
||||
}
|
||||
case SMART_ACTION_REMOVE_AURAS_BY_TYPE:
|
||||
{
|
||||
if (e.action.auraType.type >= TOTAL_AURAS)
|
||||
{
|
||||
TC_LOG_ERROR("sql.sql", "Entry " SI64FMTD " SourceType %u Event %u Action %u uses invalid data type %u (value range 0-TOTAL_AURAS), skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.auraType.type);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SMART_ACTION_START_CLOSEST_WAYPOINT:
|
||||
case SMART_ACTION_FOLLOW:
|
||||
case SMART_ACTION_SET_ORIENTATION:
|
||||
@@ -1437,7 +1483,8 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
|
||||
case SMART_ACTION_SET_DATA:
|
||||
case SMART_ACTION_SET_VISIBILITY:
|
||||
case SMART_ACTION_WP_PAUSE:
|
||||
case SMART_ACTION_SET_FLY:
|
||||
case SMART_ACTION_SET_DISABLE_GRAVITY:
|
||||
case SMART_ACTION_SET_CAN_FLY:
|
||||
case SMART_ACTION_SET_RUN:
|
||||
case SMART_ACTION_SET_SWIM:
|
||||
case SMART_ACTION_FORCE_DESPAWN:
|
||||
@@ -1458,7 +1505,6 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
|
||||
case SMART_ACTION_SET_NPC_FLAG:
|
||||
case SMART_ACTION_ADD_NPC_FLAG:
|
||||
case SMART_ACTION_REMOVE_NPC_FLAG:
|
||||
case SMART_ACTION_CROSS_CAST:
|
||||
case SMART_ACTION_CALL_RANDOM_TIMED_ACTIONLIST:
|
||||
case SMART_ACTION_RANDOM_MOVE:
|
||||
case SMART_ACTION_SET_UNIT_FIELD_BYTES_1:
|
||||
@@ -1483,6 +1529,13 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
|
||||
case SMART_ACTION_MOVE_OFFSET:
|
||||
case SMART_ACTION_SET_CORPSE_DELAY:
|
||||
case SMART_ACTION_DISABLE_EVADE:
|
||||
case SMART_ACTION_SET_SIGHT_DIST:
|
||||
case SMART_ACTION_FLEE:
|
||||
case SMART_ACTION_ADD_THREAT:
|
||||
case SMART_ACTION_LOAD_EQUIPMENT:
|
||||
case SMART_ACTION_TRIGGER_RANDOM_TIMED_EVENT:
|
||||
case SMART_ACTION_SET_COUNTER:
|
||||
case SMART_ACTION_REMOVE_ALL_GAMEOBJECTS:
|
||||
break;
|
||||
default:
|
||||
TC_LOG_ERROR("sql.sql", "SmartAIMgr: Not handled action_type(%u), event_type(%u), Entry " SI64FMTD " SourceType %u Event %u, skipped.", e.GetActionType(), e.GetEventType(), e.entryOrGuid, e.GetScriptType(), e.event_id);
|
||||
|
||||
Reference in New Issue
Block a user