Conversation
alisonrag
approved these changes
Apr 12, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
[AI] ## Summary
This PR bundles a broad set of updates across core AI, routing, movement prediction, NPC interaction, dynamic portals, monster data parsing,
eventMacro, and multiple plugins. It now updates 53 files across 4 commits, with 4,547 additions and 4,278 deletions.The overall goal is to improve movement/state accuracy, make routing and NPC interactions more robust, expand
eventMacrocapabilities, simplify duplicated quest-condition logic, improve portal/NPC recovery, and clean up several noisy logs and edge cases.Main goals
time_moveandtime_move_calc.eventMacrowith cycle-stage-aware execution, queue-blocking controls, new conditions, and a quest-condition base class to remove duplicated logic.monsters_table.txtparsing to support names, exposing monster priority lookup by name or ID, and wiring that into existing logic.Detailed changes
1. Shared movement prediction and movement-finished logic
A large part of this PR is centered in
src/Utils.pm, where movement prediction is expanded and normalized. This adds:set_actor_solutionactorFinishedMovementcalcPosFromPathfindingcalcStepsWalkedFromTimeAndSolutionandcalcTimeFromSolutionmakeCoordsFromToThe new flow avoids having many callers reason directly about
time_move_calc. Instead, callers can now ask whether an actor has actually finished movement, optionally with wait/lookahead semantics, while letting Utils lazily build and cache the path solution. This makes movement-dependent decisions more consistent across attack, route, map route, NPC talk, aggro detection, and teleport logic.On the receive side, actor movement packets now preserve
move_start_sx/move_start_sy, reset cached timing/solution fields on fresh movement, and rely on the new cache behavior rather than precomputing an incomplete movement model incharacter_moves. The self-death/self-resurrection hook timing is also adjusted so character state is already updated before the hook runs.2. AI attack and slave-attack accuracy improvements
In
src/AI/Attack.pm, this PR extracts repeatedmovetoattackcorrection logic intoresolve_movetoattack_pos, and both the character and target now use the same helper. It also switches attack position prediction to the more precise pathfinding mode by callingcalcPosFromPathfinding(..., 1)for both actor and target. A noisy warning about temporary inability to attack while waiting for target movement is downgraded to debug.src/AI/SlaveAttack.pmreceives the same style of prediction update and the same warning-to-debug reduction for wait-to-attack messages.src/AI/Slave.pmand parts ofsrc/AI/CoreLogic.pmalso replace oldercalcPositionuses withcalcPosFromPathfinding, so target selection, item gathering, slave auto-attack, and teleport-away checks operate on more realistic positions.3. New AI cycle-stage hooks and
eventMacrostage-aware executionA major
eventMacroenhancement in this PR is support for multiple AI cycle stages instead of onlyAI_start. Core AI now emitsAI_pre,AI_middle, andAI_postwith the current AI state, andeventMacrois updated to understand and use these stages.eventMacro::Corenow defines cycle stages (AI_start,AI_pre,AI_middle,AI_post), stores triggered automacros per stage, installs/removes per-stage hooks dynamically, and hands off pending automacros according to the stage that was active when a macro queue finished. This means automacros can be scheduled more precisely inside the AI loop rather than competing only atAI_start.Related changes:
CheckOnCycleStagebecomes a valid automacro parameter.overrideNotWhenInQueuebecomes a valid automacro parameter.eventMacro_notWhenInQueueis introduced.run_before_call_checks.This gives much finer control over when automacros are allowed to fire and helps prevent unwanted macro execution during sensitive AI states.
4.
eventMacroquest-condition refactorThis PR adds a new shared base class,
eventMacro::Condition::Base::Quest, and migrates multiple quest-related conditions to inherit from it:QuestActiveQuestCompleteQuestIncompleteQuestNotCompleteQuestNotIncompleteQuestInactiveQuestOnTimeQuestTimeOverdueQuestHuntCompletedQuestHuntOngoingBefore this PR, these modules duplicated large amounts of parsing, variable update, standby, and result-reporting logic. Now the shared base handles list parsing, variable substitution, standby behavior, hook registration, and common output variables such as
.LastIDand.LastListIndex, while each child condition only implements its quest-specific check logic or result accessor.A new utility helper,
updateQuestConditionStandbyState, is added ineventMacro::Utilitiesto manage delayed quest readiness after map change / in-game transitions, including dynamic standby hooks. This reduces premature quest-condition evaluation right after zone/load transitions.5. New
eventMacroconditionsThis PR also adds three new conditions:
isAliveisCloseToCoordinateisNotCloseToCoordinateisAliveallows macro conditions based on whether the character is dead or alive, usingin_game,self_died,self_resurrected, andpacket_mapChangehooks. The coordinate conditions allow proximity-based checks against a given(x, y, dist)tuple and expose map/X/Y/dist in their generated variables.6.
eventMacroruntime behavior tweaksThere are also smaller runtime changes:
parse_loginRunner.pmnow advances withtimeout(0)instead ofmacro_delay..posineventMacro::Corenow usescalcPosFromPathfinding($field, $char)instead ofcalcPosition.calcPosition + distancecombinations.These changes help align macro-visible state with the same positional logic the AI is already moving toward.
7. Routing robustness improvements
src/Task/Route.pmcontains a broad set of route-quality and edge-case improvements:distFromGoal/pyDistFromGoalisCellOccupiedanyDistFromGoalmore explicitly while selecting movement steps_resetRouteForMoveSelectioninstead of inline logicOn the helper side,
Misc::isCellOccupiednow accepts anignore_actorargument so the current actor does not treat itself as an obstacle. This matters for route finishing and destination replacement.8. MapRoute / TalkNPC / teleport-NPC recovery improvements
src/Task/MapRoute.pmnow usesactorFinishedMovementbefore trying to interact with portal/NPC route steps. This is cleaner than open-coding time comparisons and reduces race conditions where route logic tries to talk or warp too early.This PR also introduces more plugin recovery points for NPC teleport failures:
npc_teleport_errornpc_teleport_missingsrc/Task/TalkNPC.pmadds a newTalkNPC_resethook so plugins can request a forced NPC conversation reset while the task is in the talking stage. It also waits for movement completion usingactorFinishedMovementbefore opening dialogue.9. Dynamic portals and Eden exit synchronization
Dynamic portal behavior is improved in several places.
functions.plnow refreshes dynamic portal states throughonLoadedforportals.txt, instead of manually callingrefreshDynamicPortalStatesafter the full data-load block.Misc.pmremoves a duplicate manual refresh fromparseReload, andapplyDynamicPortalStatesnow emits debug information when dynamic destinations are enabled or disabled.edenPortalExitSyncis also tightened up. It introducesEDEN_EXIT_POS_TOLERANCE, filters candidate destinations to entries with valid coordinates, sorts by proximity, and only accepts an inferred exit destination if the landing point is within tolerance of the known portal exit. This prevents incorrect rewrites when the character leaves Eden in a way that is not actually tied to the expected portal landing.The test suite is updated accordingly, including coverage for dynamic portal state restoration after portal reload and Eden exit updates with nearby landing offsets.
10. Monster-table parsing and monster priority improvements
src/FileParsers.pmextendsparseMonstersTableFilesomonsters_table.txtcan now contain an optionalNamecolumn in addition toAi. It supports both tab-separated and whitespace-separated formats, preserves names with spaces, and defaultsAito06when omitted.The generator script
tables/tools/mobdb_yml_to_monsters_table_txt.plis updated to emit theNamecolumn as well. This improves fidelity between YAML source data and OpenKore’s text table output.In
Misc.pm, a newmonsterPriority($name, $nameID)helper centralizes priority lookup. It prefers explicit monster ID entries, then name-based entries, thenall.getBestTargetnow uses this helper instead of only checking lowercase name keys. This meanspriority.txtcan influence targeting by monster ID as well as by name.The tests add coverage for both the extended monster-table format and the new mixed priority behavior.
xConfis also updated to prefermonstersTable->{Name}when writingmon_control.txtentries, instead of relying only on LUT lookups.11.
checkAggressiveplugin overhaulThe
checkAggressiveplugin is significantly expanded. It now:is_aggressive_towards_actorfor both character and slave casesThis makes the plugin much less simplistic than the old “aggressive + clean + moving toward us” check and should reduce false positives when a monster is actually oriented toward or blocked by another actor.
12.
avoidAssistersplugin simplificationThe
avoidAssistersplugin is reworked so it no longer parses config blocks directly from the config file. Instead, it now reads from flattened%configkeys and supports numbered variants such as:maxAssistersBellowDistAllowedmaxAssistersBellowDistAllowed_0maxAssistersBellowDistAllowed_1This removes direct file parsing, removes the
Settingsdependency in that path, and keeps behavior aligned with OpenKore’s runtime config state. It also downgrades some target-drop/release warnings to debug, reducing routine log noise.13. Kafra position and Kafra portal repair plugin consolidation
This PR removes the old
fixKafraPortalsandfixKafraPositionplugins and replaces them with a new combined plugin:fixKafraPositionAndPortals.The new plugin merges both responsibilities into one flow:
portals.txtTalkNPC_resetto restart NPC dialogue after live portal data changesnpc_teleport_errorto tellMapRouteto recalculate using refreshed data instead of retrying stale NPC stepsIt also improves destination normalization and alias matching for Kafra menu destinations, including some text variants that were previously more fragile.
This makes Kafra warp recovery much more robust when portal data is stale because it can now repair the table, reset the current NPC interaction, and force route recalculation around the updated live data instead of only retrying the same broken path.
14. Default config and documentation updates
This PR also updates user-facing defaults and docs in
control/:eventMacroconfig entries tocontrol/config.txteventMacro_notWhenInQueueby default for common queue states such asstorageAuto,buyAuto, andsellAutoavoidObstacles_enable_movedefault from0to1avoidObstaclesMonsterblock fromcontrol/config.txtcontrol/priority.txtcomments to document the meaning ofalland clarify that entries listed belowallbecome lower priority than unlisted monstersThese changes make the new
eventMacroqueue controls and priority behavior discoverable from the default control files instead of only existing in code/tests.15. Miscellaneous fixes and cleanup
Other smaller changes included in the bundle:
bulkConfigModifynow callsconfigModifyafter applying local updates and returns early if nothing changed.objectIsMovingTowardsandobjectIsMovingTowardsPlayernow useactorFinishedMovement.CalcMapRoutedowngrades warp-item cooldown warnings to debug.Network::DirectConnectionadds a newline to the disconnect message.functions.plPoseidon handling is guarded so replies are only sent while in-game, with a newPoseidonReplyhook and reset behavior when no longer in game.tables/portals_spawns.txtadds another Payon savepoint entry.Notes
This PR is intentionally a bundled update because several of these changes depend on each other:
eventMacrostage and standby changes rely on the new AI hook flow