Skip to content

Bundle of updates 2#4207

Merged
Henrybk merged 4 commits intomasterfrom
bundle2
Apr 12, 2026
Merged

Bundle of updates 2#4207
Henrybk merged 4 commits intomasterfrom
bundle2

Conversation

@Henrybk
Copy link
Copy Markdown
Contributor

@Henrybk Henrybk commented Apr 12, 2026

[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 eventMacro capabilities, simplify duplicated quest-condition logic, improve portal/NPC recovery, and clean up several noisy logs and edge cases.

Main goals

  • Rework movement prediction and “has movement finished?” checks so more subsystems use shared actor-aware helpers instead of manually comparing time_move and time_move_calc.
  • Expand eventMacro with cycle-stage-aware execution, queue-blocking controls, new conditions, and a quest-condition base class to remove duplicated logic.
  • Improve routing, NPC talk flow, and dynamic portal behavior so route recovery and teleport/NPC interactions are more resilient.
  • Improve monster-related data handling by extending monsters_table.txt parsing to support names, exposing monster priority lookup by name or ID, and wiring that into existing logic.
  • Consolidate Kafra position-fixing and Kafra portal-refresh behavior into a single plugin that can repair stale portal data and restart live route flows with refreshed NPC/portal steps.
  • Clean up several plugins, defaults, and logs so behavior is more consistent with runtime state and less noisy in normal operation.

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_solution
  • actorFinishedMovement
  • a more complete calcPosFromPathfinding
  • subcell-aware timing helpers
  • safer guards in calcStepsWalkedFromTimeAndSolution and calcTimeFromSolution
  • start-subcell decoding through makeCoordsFromTo

The 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 in character_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 repeated movetoattack correction logic into resolve_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 calling calcPosFromPathfinding(..., 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.pm receives the same style of prediction update and the same warning-to-debug reduction for wait-to-attack messages. src/AI/Slave.pm and parts of src/AI/CoreLogic.pm also replace older calcPosition uses with calcPosFromPathfinding, so target selection, item gathering, slave auto-attack, and teleport-away checks operate on more realistic positions.

3. New AI cycle-stage hooks and eventMacro stage-aware execution

A major eventMacro enhancement in this PR is support for multiple AI cycle stages instead of only AI_start. Core AI now emits AI_pre, AI_middle, and AI_post with the current AI state, and eventMacro is updated to understand and use these stages.

eventMacro::Core now 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 at AI_start.

Related changes:

  • CheckOnCycleStage becomes a valid automacro parameter.
  • overrideNotWhenInQueue becomes a valid automacro parameter.
  • a new config key eventMacro_notWhenInQueue is introduced.
  • pre-call checks are centralized through run_before_call_checks.
  • automacros can now be skipped automatically when configured blocked AI queue states are active, unless explicitly overridden.

This gives much finer control over when automacros are allowed to fire and helps prevent unwanted macro execution during sensitive AI states.

4. eventMacro quest-condition refactor

This PR adds a new shared base class, eventMacro::Condition::Base::Quest, and migrates multiple quest-related conditions to inherit from it:

  • QuestActive
  • QuestComplete
  • QuestIncomplete
  • QuestNotComplete
  • QuestNotIncomplete
  • QuestInactive
  • QuestOnTime
  • QuestTimeOverdue
  • QuestHuntCompleted
  • QuestHuntOngoing

Before 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 .LastID and .LastListIndex, while each child condition only implements its quest-specific check logic or result accessor.

A new utility helper, updateQuestConditionStandbyState, is added in eventMacro::Utilities to 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 eventMacro conditions

This PR also adds three new conditions:

  • isAlive
  • isCloseToCoordinate
  • isNotCloseToCoordinate

isAlive allows macro conditions based on whether the character is dead or alive, using in_game, self_died, self_resurrected, and packet_mapChange hooks. 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. eventMacro runtime behavior tweaks

There are also smaller runtime changes:

  • parse_log in Runner.pm now advances with timeout(0) instead of macro_delay.
  • .pos in eventMacro::Core now uses calcPosFromPathfinding($field, $char) instead of calcPosition.
  • attack-related conditions now use block-distance/pathfinding-based positions instead of older calcPosition + distance combinations.

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.pm contains a broad set of route-quality and edge-case improvements:

  • adds a route loop counter for debugging
  • supports early completion when already within distFromGoal / pyDistFromGoal
  • improves occupied-destination handling by passing the moving actor into isCellOccupied
  • improves debug/error messages with actor context
  • handles anyDistFromGoal more explicitly while selecting movement steps
  • resets/blocks aggressive trim behavior after actual movement
  • wraps unexpected movement reset into _resetRouteForMoveSelection instead of inline logic

On the helper side, Misc::isCellOccupied now accepts an ignore_actor argument 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.pm now uses actorFinishedMovement before 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_error
  • improved handling for npc_teleport_missing
  • renamed local arg hashes for clarity
  • plugin-driven route reset/recalculation behavior after teleport/NPC failures

src/Task/TalkNPC.pm adds a new TalkNPC_reset hook so plugins can request a forced NPC conversation reset while the task is in the talking stage. It also waits for movement completion using actorFinishedMovement before opening dialogue.

9. Dynamic portals and Eden exit synchronization

Dynamic portal behavior is improved in several places.

functions.pl now refreshes dynamic portal states through onLoaded for portals.txt, instead of manually calling refreshDynamicPortalStates after the full data-load block. Misc.pm removes a duplicate manual refresh from parseReload, and applyDynamicPortalStates now emits debug information when dynamic destinations are enabled or disabled.

edenPortalExitSync is also tightened up. It introduces EDEN_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.pm extends parseMonstersTableFile so monsters_table.txt can now contain an optional Name column in addition to Ai. It supports both tab-separated and whitespace-separated formats, preserves names with spaces, and defaults Ai to 06 when omitted.

The generator script tables/tools/mobdb_yml_to_monsters_table_txt.pl is updated to emit the Name column as well. This improves fidelity between YAML source data and OpenKore’s text table output.

In Misc.pm, a new monsterPriority($name, $nameID) helper centralizes priority lookup. It prefers explicit monster ID entries, then name-based entries, then all. getBestTarget now uses this helper instead of only checking lowercase name keys. This means priority.txt can 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. xConf is also updated to prefer monstersTable->{Name} when writing mon_control.txt entries, instead of relying only on LUT lookups.

11. checkAggressive plugin overhaul

The checkAggressive plugin is significantly expanded. It now:

  • imports pathfinding-based position helpers and facing/vector helpers
  • adds detection for monsters already engaged with us
  • adds direction/facing checks
  • builds a set of attackable actors (players, slaves, elementals)
  • checks for another attackable actor between us and the monster
  • wraps the decision in is_aggressive_towards_actor for both character and slave cases

This 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. avoidAssisters plugin simplification

The avoidAssisters plugin is reworked so it no longer parses config blocks directly from the config file. Instead, it now reads from flattened %config keys and supports numbered variants such as:

  • maxAssistersBellowDistAllowed
  • maxAssistersBellowDistAllowed_0
  • maxAssistersBellowDistAllowed_1

This removes direct file parsing, removes the Settings dependency 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 fixKafraPortals and fixKafraPosition plugins and replaces them with a new combined plugin: fixKafraPositionAndPortals.

The new plugin merges both responsibilities into one flow:

  • keeps the old “guess the real Kafra position” recovery behavior for storage and teleport flows
  • updates stale Kafra/Zonda portal entries in portals.txt
  • tracks the difference between the stale portal source and the live NPC position that was actually found in game
  • reloads and recompiles portal data after repairing entries
  • uses TalkNPC_reset to restart NPC dialogue after live portal data changes
  • uses npc_teleport_error to tell MapRoute to recalculate using refreshed data instead of retrying stale NPC steps
  • preserves a short-lived refresh/guess state so route recovery can continue coherently after a live repair

It 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/:

  • adds default eventMacro config entries to control/config.txt
  • documents and enables eventMacro_notWhenInQueue by default for common queue states such as storageAuto, buyAuto, and sellAuto
  • changes avoidObstacles_enable_move default from 0 to 1
  • removes one sample avoidObstaclesMonster block from control/config.txt
  • updates control/priority.txt comments to document the meaning of all and clarify that entries listed below all become lower priority than unlisted monsters

These changes make the new eventMacro queue 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:

  • bulkConfigModify now calls configModify after applying local updates and returns early if nothing changed.
  • objectIsMovingTowards and objectIsMovingTowardsPlayer now use actorFinishedMovement.
  • CalcMapRoute downgrades warp-item cooldown warnings to debug.
  • Network::DirectConnection adds a newline to the disconnect message.
  • functions.pl Poseidon handling is guarded so replies are only sent while in-game, with a new PoseidonReply hook and reset behavior when no longer in game.
  • tables/portals_spawns.txt adds another Payon savepoint entry.

Notes

This PR is intentionally a bundled update because several of these changes depend on each other:

  • movement prediction changes are consumed by attack/routing/NPC logic
  • new route/NPC reset hooks are used by the new Kafra recovery plugin
  • dynamic portal refresh behavior is tied to route/NPC correctness
  • monster-table parsing changes support the new priority/xConf behavior
  • eventMacro stage and standby changes rely on the new AI hook flow

@Henrybk Henrybk merged commit 1c49aed into master Apr 12, 2026
9 checks passed
@Henrybk Henrybk deleted the bundle2 branch April 12, 2026 22:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants