combat_ai.lua 1.5 KB

123456789101112131415161718192021222324252627282930
  1. -- Native objective costs select the group; the objective owns areas and task execution.
  2. local AI = {}
  3. function AI.assign(context, sensor, objective, group, reserved)
  4. context:slot(sensor):assign_combat_objective{
  5. objective = context:slot(objective), revision = 1, task_group = group, reserved = reserved or false,
  6. }
  7. end
  8. function AI.update(context, state, key, sensor, objective, group_count, event, ordinal, reserved)
  9. if event.objective_revision ~= 1 or not event.task_costs then return end
  10. -- Twelve five-bit group choices fit in one signed 64-bit durable Lua integer.
  11. -- Zero encodes unassigned; 1..24 encode native task groups 0..23.
  12. local shift = ((ordinal or 1) - 1) * 5
  13. assert(shift >= 0 and shift <= 55, "AI state lane is outside its packed word")
  14. local packed = state:variable(key) or 0
  15. local current = ((packed >> shift) & 31) - 1
  16. local best, cost = -1, 2040 -- native 4EB8E0's saturated/unreachable value
  17. for index = 1, group_count do
  18. local candidate = event.task_costs[index]
  19. if candidate and candidate >= 0 and candidate < cost then
  20. best, cost = index - 1, candidate
  21. end
  22. end
  23. -- Keep the current group on equal quantized costs to avoid needless relinking.
  24. if best >= 0 and current and current >= 0 and event.task_costs[current + 1] == cost then best = current end
  25. if current ~= best then
  26. AI.assign(context, sensor, objective, best, reserved)
  27. context:set_variable(key, (packed & ~(31 << shift)) | ((best + 1) << shift))
  28. end
  29. end
  30. return AI