@v12-engine/engine 0.1.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/abilities/amounts.d.ts +28 -0
- package/dist/abilities/amounts.js +74 -0
- package/dist/abilities/amounts.js.map +1 -0
- package/dist/abilities/buffs.d.ts +106 -6
- package/dist/abilities/buffs.js +443 -0
- package/dist/abilities/buffs.js.map +1 -0
- package/dist/abilities/castTold.d.ts +2 -0
- package/dist/abilities/castTold.js +66 -0
- package/dist/abilities/castTold.js.map +1 -0
- package/dist/abilities/chance.d.ts +38 -0
- package/dist/abilities/chance.js +77 -0
- package/dist/abilities/chance.js.map +1 -0
- package/dist/abilities/charges.d.ts +18 -0
- package/dist/abilities/charges.js +101 -0
- package/dist/abilities/charges.js.map +1 -0
- package/dist/abilities/control.d.ts +28 -0
- package/dist/abilities/control.js +113 -0
- package/dist/abilities/control.js.map +1 -0
- package/dist/abilities/dispel.js +51 -0
- package/dist/abilities/dispel.js.map +1 -0
- package/dist/abilities/effectFields.d.ts +1 -1
- package/dist/abilities/effectFields.js +676 -0
- package/dist/abilities/effectFields.js.map +1 -0
- package/dist/abilities/effectIndex.d.ts +27 -0
- package/dist/abilities/effectIndex.js +64 -0
- package/dist/abilities/effectIndex.js.map +1 -0
- package/dist/abilities/effects/buff.d.ts +9 -3
- package/dist/abilities/effects/buff.js +84 -0
- package/dist/abilities/effects/buff.js.map +1 -0
- package/dist/abilities/effects/conditions.d.ts +2 -0
- package/dist/abilities/effects/conditions.js +41 -0
- package/dist/abilities/effects/conditions.js.map +1 -0
- package/dist/abilities/effects/core.js +54 -0
- package/dist/abilities/effects/core.js.map +1 -0
- package/dist/abilities/effects/damage.d.ts +1 -1
- package/dist/abilities/effects/damage.js +43 -0
- package/dist/abilities/effects/damage.js.map +1 -0
- package/dist/abilities/effects/heal.d.ts +2 -2
- package/dist/abilities/effects/heal.js +51 -0
- package/dist/abilities/effects/heal.js.map +1 -0
- package/dist/abilities/effects/missile.d.ts +13 -1
- package/dist/abilities/effects/missile.js +104 -0
- package/dist/abilities/effects/missile.js.map +1 -0
- package/dist/abilities/effects/morph.d.ts +5 -0
- package/dist/abilities/effects/morph.js +43 -0
- package/dist/abilities/effects/morph.js.map +1 -0
- package/dist/abilities/effects/moves.d.ts +16 -4
- package/dist/abilities/effects/moves.js +212 -0
- package/dist/abilities/effects/moves.js.map +1 -0
- package/dist/abilities/effects/passives.d.ts +19 -9
- package/dist/abilities/effects/passives.js +131 -0
- package/dist/abilities/effects/passives.js.map +1 -0
- package/dist/abilities/effects/proxy.d.ts +5 -0
- package/dist/abilities/effects/proxy.js +60 -0
- package/dist/abilities/effects/proxy.js.map +1 -0
- package/dist/abilities/effects/sight.d.ts +2 -2
- package/dist/abilities/effects/sight.js +39 -0
- package/dist/abilities/effects/sight.js.map +1 -0
- package/dist/abilities/effects/spawn.d.ts +5 -2
- package/dist/abilities/effects/spawn.js +40 -0
- package/dist/abilities/effects/spawn.js.map +1 -0
- package/dist/abilities/effects/timed.d.ts +2 -2
- package/dist/abilities/effects/timed.js +96 -0
- package/dist/abilities/effects/timed.js.map +1 -0
- package/dist/abilities/effects/trade.d.ts +1 -1
- package/dist/abilities/effects/trade.js +25 -0
- package/dist/abilities/effects/trade.js.map +1 -0
- package/dist/abilities/effects.d.ts +97 -23
- package/dist/abilities/effects.js +860 -0
- package/dist/abilities/effects.js.map +1 -0
- package/dist/abilities/land.d.ts +38 -4
- package/dist/abilities/land.js +189 -0
- package/dist/abilities/land.js.map +1 -0
- package/dist/abilities/recast.d.ts +45 -0
- package/dist/abilities/recast.js +118 -0
- package/dist/abilities/recast.js.map +1 -0
- package/dist/abilities/scaled.js +40 -0
- package/dist/abilities/scaled.js.map +1 -0
- package/dist/abilities/screen.d.ts +6 -0
- package/dist/abilities/screen.js +83 -0
- package/dist/abilities/screen.js.map +1 -0
- package/dist/abilities/shapes.d.ts +66 -0
- package/dist/abilities/shapes.js +122 -0
- package/dist/abilities/shapes.js.map +1 -0
- package/dist/abilities/text.d.ts +14 -2
- package/dist/abilities/text.js +204 -0
- package/dist/abilities/text.js.map +1 -0
- package/dist/abilities/triggers.d.ts +98 -0
- package/dist/abilities/triggers.js +351 -0
- package/dist/abilities/triggers.js.map +1 -0
- package/dist/abilityChanges.d.ts +131 -0
- package/dist/abilityChanges.js +345 -0
- package/dist/abilityChanges.js.map +1 -0
- package/dist/ai/area.d.ts +4 -1
- package/dist/ai/brain.d.ts +4 -1
- package/dist/ai/brain.js +844 -0
- package/dist/ai/brain.js.map +1 -0
- package/dist/ai/budget.js +74 -0
- package/dist/ai/budget.js.map +1 -0
- package/dist/ai/checks.d.ts +9 -1
- package/dist/ai/checks.js +242 -0
- package/dist/ai/checks.js.map +1 -0
- package/dist/ai/computer.d.ts +11 -4
- package/dist/ai/computer.js +251 -0
- package/dist/ai/computer.js.map +1 -0
- package/dist/ai/defence.d.ts +4 -0
- package/dist/ai/defence.js +430 -0
- package/dist/ai/defence.js.map +1 -0
- package/dist/ai/define.d.ts +3 -2
- package/dist/ai/define.js +31 -0
- package/dist/ai/define.js.map +1 -0
- package/dist/ai/economy.d.ts +10 -7
- package/dist/ai/economy.js +780 -0
- package/dist/ai/economy.js.map +1 -0
- package/dist/ai/geometry.js +38 -0
- package/dist/ai/geometry.js.map +1 -0
- package/dist/ai/goals.d.ts +1 -0
- package/dist/ai/goals.js +560 -0
- package/dist/ai/goals.js.map +1 -0
- package/dist/ai/knowledge.d.ts +72 -7
- package/dist/ai/knowledge.js +804 -0
- package/dist/ai/knowledge.js.map +1 -0
- package/dist/ai/lanes.d.ts +10 -2
- package/dist/ai/lanes.js +715 -0
- package/dist/ai/lanes.js.map +1 -0
- package/dist/ai/melee/build.js +264 -0
- package/dist/ai/melee/build.js.map +1 -0
- package/dist/ai/melee/goals.d.ts +7 -0
- package/dist/ai/melee/goals.js +720 -0
- package/dist/ai/melee/goals.js.map +1 -0
- package/dist/ai/melee/heroes.js +68 -0
- package/dist/ai/melee/heroes.js.map +1 -0
- package/dist/ai/melee/index.d.ts +1 -1
- package/dist/ai/melee/index.js +51 -0
- package/dist/ai/melee/index.js.map +1 -0
- package/dist/ai/melee/production.js +29 -0
- package/dist/ai/melee/production.js.map +1 -0
- package/dist/ai/melee/surrender.js +64 -0
- package/dist/ai/melee/surrender.js.map +1 -0
- package/dist/ai/micro.d.ts +9 -0
- package/dist/ai/micro.js +1316 -0
- package/dist/ai/micro.js.map +1 -0
- package/dist/ai/mission.d.ts +9 -2
- package/dist/ai/mission.js +538 -0
- package/dist/ai/mission.js.map +1 -0
- package/dist/ai/missionRules.d.ts +1 -1
- package/dist/ai/missionRules.js +26 -0
- package/dist/ai/missionRules.js.map +1 -0
- package/dist/ai/module.d.ts +6 -2
- package/dist/ai/module.js +37 -0
- package/dist/ai/module.js.map +1 -0
- package/dist/ai/options.d.ts +3 -3
- package/dist/ai/plans/build.d.ts +20 -1
- package/dist/ai/plans/build.js +608 -0
- package/dist/ai/plans/build.js.map +1 -0
- package/dist/ai/plans/placement.d.ts +4 -1
- package/dist/ai/plans/placement.js +295 -0
- package/dist/ai/plans/placement.js.map +1 -0
- package/dist/ai/plans/plans.d.ts +9 -0
- package/dist/ai/plans/plans.js +110 -0
- package/dist/ai/plans/plans.js.map +1 -0
- package/dist/ai/plans/production.d.ts +14 -2
- package/dist/ai/plans/production.js +434 -0
- package/dist/ai/plans/production.js.map +1 -0
- package/dist/ai/plans/purse.d.ts +6 -3
- package/dist/ai/plans/purse.js +139 -0
- package/dist/ai/plans/purse.js.map +1 -0
- package/dist/ai/plans/tech.d.ts +6 -0
- package/dist/ai/plans/tech.js +122 -0
- package/dist/ai/plans/tech.js.map +1 -0
- package/dist/ai/profiles.d.ts +4 -4
- package/dist/{profiles-B3NS9jwk.js → ai/profiles.js} +3 -98
- package/dist/ai/profiles.js.map +1 -0
- package/dist/ai/reach.js +54 -0
- package/dist/ai/reach.js.map +1 -0
- package/dist/ai/report.d.ts +8 -0
- package/dist/ai/report.js +87 -0
- package/dist/ai/report.js.map +1 -0
- package/dist/ai/roles.d.ts +4 -0
- package/dist/ai/roles.js +207 -0
- package/dist/ai/roles.js.map +1 -0
- package/dist/ai/rules.d.ts +8 -2
- package/dist/ai/rules.js +416 -0
- package/dist/ai/rules.js.map +1 -0
- package/dist/ai/scouting.d.ts +6 -0
- package/dist/ai/scouting.js +324 -0
- package/dist/ai/scouting.js.map +1 -0
- package/dist/ai/settings.js +99 -0
- package/dist/ai/settings.js.map +1 -0
- package/dist/ai/squads.d.ts +21 -2
- package/dist/ai/squads.js +916 -0
- package/dist/ai/squads.js.map +1 -0
- package/dist/ai/strength.js +320 -0
- package/dist/ai/strength.js.map +1 -0
- package/dist/ai/task.d.ts +3 -1
- package/dist/ai/task.js +17 -0
- package/dist/ai/task.js.map +1 -0
- package/dist/ai/tasks/attack.js +24 -0
- package/dist/ai/tasks/attack.js.map +1 -0
- package/dist/ai/tasks/capture.d.ts +3 -3
- package/dist/ai/tasks/capture.js +37 -0
- package/dist/ai/tasks/capture.js.map +1 -0
- package/dist/ai/tasks/creep.js +29 -0
- package/dist/ai/tasks/creep.js.map +1 -0
- package/dist/ai/tasks/defend.js +61 -0
- package/dist/ai/tasks/defend.js.map +1 -0
- package/dist/ai/tasks/drop.js +81 -0
- package/dist/ai/tasks/drop.js.map +1 -0
- package/dist/ai/tasks/escort.js +59 -0
- package/dist/ai/tasks/escort.js.map +1 -0
- package/dist/ai/tasks/gather.js +48 -0
- package/dist/ai/tasks/gather.js.map +1 -0
- package/dist/ai/tasks/harass.js +39 -0
- package/dist/ai/tasks/harass.js.map +1 -0
- package/dist/ai/tasks/hold.js +32 -0
- package/dist/ai/tasks/hold.js.map +1 -0
- package/dist/ai/tasks/index.js +34 -0
- package/dist/ai/tasks/index.js.map +1 -0
- package/dist/ai/tasks/move.js +26 -0
- package/dist/ai/tasks/move.js.map +1 -0
- package/dist/ai/tasks/patrol.js +59 -0
- package/dist/ai/tasks/patrol.js.map +1 -0
- package/dist/ai/tasks/retreat.js +28 -0
- package/dist/ai/tasks/retreat.js.map +1 -0
- package/dist/ai/tasks/scout.js +73 -0
- package/dist/ai/tasks/scout.js.map +1 -0
- package/dist/ai/tasks/shared.d.ts +1 -1
- package/dist/ai/tasks/shared.js +137 -0
- package/dist/ai/tasks/shared.js.map +1 -0
- package/dist/ai/team.d.ts +18 -1
- package/dist/ai/team.js +492 -0
- package/dist/ai/team.js.map +1 -0
- package/dist/ai/threat.d.ts +6 -0
- package/dist/ai/threat.js +206 -0
- package/dist/ai/threat.js.map +1 -0
- package/dist/ai/view.d.ts +21 -7
- package/dist/ai/view.js +677 -0
- package/dist/ai/view.js.map +1 -0
- package/dist/ai/waves.d.ts +6 -0
- package/dist/ai/waves.js +410 -0
- package/dist/ai/waves.js.map +1 -0
- package/dist/ai.js +54 -6239
- package/dist/aiTesting.d.ts +6 -3
- package/dist/aiTesting.js +229 -0
- package/dist/aiTesting.js.map +1 -0
- package/dist/areas.d.ts +4 -1
- package/dist/areas.js +295 -0
- package/dist/areas.js.map +1 -0
- package/dist/attacks.d.ts +3 -3
- package/dist/attacks.js +127 -0
- package/dist/attacks.js.map +1 -0
- package/dist/burning.d.ts +267 -0
- package/dist/burning.js +795 -0
- package/dist/burning.js.map +1 -0
- package/dist/bytes.js +21 -0
- package/dist/bytes.js.map +1 -0
- package/dist/callings.d.ts +71 -0
- package/dist/callings.js +157 -0
- package/dist/callings.js.map +1 -0
- package/dist/cameraOrders.d.ts +78 -0
- package/dist/cameraOrders.js +114 -0
- package/dist/cameraOrders.js.map +1 -0
- package/dist/camps.d.ts +70 -4
- package/dist/camps.js +501 -0
- package/dist/camps.js.map +1 -0
- package/dist/capture.d.ts +15 -3
- package/dist/capture.js +304 -0
- package/dist/capture.js.map +1 -0
- package/dist/cellLayers.d.ts +78 -13
- package/dist/cellLayers.js +275 -0
- package/dist/cellLayers.js.map +1 -0
- package/dist/cellPatches.d.ts +24 -0
- package/dist/cellPatches.js +73 -0
- package/dist/cellPatches.js.map +1 -0
- package/dist/cinematics.d.ts +10 -5
- package/dist/cinematics.js +161 -0
- package/dist/cinematics.js.map +1 -0
- package/dist/clock.d.ts +2 -2
- package/dist/clock.js +78 -0
- package/dist/clock.js.map +1 -0
- package/dist/commands.d.ts +36 -4
- package/dist/commands.js +636 -0
- package/dist/commands.js.map +1 -0
- package/dist/components.d.ts +31 -10
- package/dist/components.js +74 -0
- package/dist/components.js.map +1 -0
- package/dist/computers.d.ts +4 -4
- package/dist/computers.js +194 -0
- package/dist/computers.js.map +1 -0
- package/dist/concealment.d.ts +25 -2
- package/dist/concealment.js +409 -0
- package/dist/concealment.js.map +1 -0
- package/dist/coreComponents.js +130 -0
- package/dist/coreComponents.js.map +1 -0
- package/dist/createGame.d.ts +306 -0
- package/dist/createGame.js +405 -0
- package/dist/createGame.js.map +1 -0
- package/dist/dashing.d.ts +18 -2
- package/dist/dashing.js +41 -0
- package/dist/dashing.js.map +1 -0
- package/dist/debug.d.ts +8 -0
- package/dist/debug.js +5 -3
- package/dist/debug2.js +76 -0
- package/dist/debug2.js.map +1 -0
- package/dist/debugCommands.d.ts +6 -6
- package/dist/debugCommands.js +537 -0
- package/dist/debugCommands.js.map +1 -0
- package/dist/debugging.d.ts +1 -0
- package/dist/defaultSets.d.ts +183 -0
- package/dist/defaultSets.js +216 -0
- package/dist/defaultSets.js.map +1 -0
- package/dist/definitions.d.ts +6 -0
- package/dist/definitions.js +78 -0
- package/dist/definitions.js.map +1 -0
- package/dist/defs.d.ts +1895 -165
- package/dist/defs.js +380 -0
- package/dist/defs.js.map +1 -0
- package/dist/denying.d.ts +4 -4
- package/dist/denying.js +106 -0
- package/dist/denying.js.map +1 -0
- package/dist/destructibles.d.ts +2 -2
- package/dist/destructibles.js +36 -0
- package/dist/destructibles.js.map +1 -0
- package/dist/determinism.d.ts +4 -4
- package/dist/determinism.js +247 -0
- package/dist/determinism.js.map +1 -0
- package/dist/dialog.d.ts +17 -2
- package/dist/dialog.js +108 -0
- package/dist/dialog.js.map +1 -0
- package/dist/effectRefs.js +28 -0
- package/dist/effectRefs.js.map +1 -0
- package/dist/effects.d.ts +27 -11
- package/dist/effects.js +110 -0
- package/dist/effects.js.map +1 -0
- package/dist/endings.d.ts +1 -1
- package/dist/endings.js +78 -0
- package/dist/endings.js.map +1 -0
- package/dist/engagement.d.ts +40 -6
- package/dist/engagement.js +530 -0
- package/dist/engagement.js.map +1 -0
- package/dist/engineEvents.d.ts +72 -9
- package/dist/engineEvents.js +520 -0
- package/dist/engineEvents.js.map +1 -0
- package/dist/entity.d.ts +275 -26
- package/dist/entity.js +441 -0
- package/dist/entity.js.map +1 -0
- package/dist/entityIndex.d.ts +10 -3
- package/dist/entityIndex.js +149 -0
- package/dist/entityIndex.js.map +1 -0
- package/dist/errors.d.ts +6 -2
- package/dist/errors.js +59 -0
- package/dist/errors.js.map +1 -0
- package/dist/events.d.ts +11 -5
- package/dist/events.js +158 -0
- package/dist/events.js.map +1 -0
- package/dist/exactMath.js +273 -0
- package/dist/exactMath.js.map +1 -0
- package/dist/features.d.ts +1 -1
- package/dist/features.js +127 -0
- package/dist/features.js.map +1 -0
- package/dist/fields.d.ts +25 -5
- package/dist/fields.js +140 -0
- package/dist/fields.js.map +1 -0
- package/dist/fixture.d.ts +3 -3
- package/dist/fixture.js +512 -0
- package/dist/fixture.js.map +1 -0
- package/dist/fog.d.ts +26 -3
- package/dist/fog.js +333 -0
- package/dist/fog.js.map +1 -0
- package/dist/foliage.d.ts +476 -0
- package/dist/foliage.js +1478 -0
- package/dist/foliage.js.map +1 -0
- package/dist/foliageDebug.d.ts +57 -0
- package/dist/foliageDebug.js +172 -0
- package/dist/foliageDebug.js.map +1 -0
- package/dist/foliageRegrowth.d.ts +20 -0
- package/dist/foliageRegrowth.js +332 -0
- package/dist/foliageRegrowth.js.map +1 -0
- package/dist/formState.d.ts +67 -0
- package/dist/formState.js +65 -0
- package/dist/formState.js.map +1 -0
- package/dist/formation.d.ts +46 -8
- package/dist/formation.js +297 -0
- package/dist/formation.js.map +1 -0
- package/dist/forms.d.ts +58 -0
- package/dist/forms.js +146 -0
- package/dist/forms.js.map +1 -0
- package/dist/friendlyFire.d.ts +2 -2
- package/dist/friendlyFire.js +37 -0
- package/dist/friendlyFire.js.map +1 -0
- package/dist/game.d.ts +141 -48
- package/dist/game.js +834 -0
- package/dist/game.js.map +1 -0
- package/dist/gameData.d.ts +96 -22
- package/dist/gameData.js +1690 -0
- package/dist/gameData.js.map +1 -0
- package/dist/gameFiles.d.ts +3 -3
- package/dist/gameFiles.js +14 -0
- package/dist/gameFiles.js.map +1 -0
- package/dist/gates.js +92 -0
- package/dist/gates.js.map +1 -0
- package/dist/generate.d.ts +28 -1
- package/dist/generate.js +1062 -0
- package/dist/generate.js.map +1 -0
- package/dist/generateWorker.d.ts +7 -3
- package/dist/generateWorker.js +86 -0
- package/dist/generateWorker.js.map +1 -0
- package/dist/grid.d.ts +9 -0
- package/dist/grid.js +102 -0
- package/dist/grid.js.map +1 -0
- package/dist/ground.d.ts +17 -1
- package/dist/ground.js +375 -0
- package/dist/ground.js.map +1 -0
- package/dist/groundObjects.d.ts +70 -0
- package/dist/groundObjects.js +371 -0
- package/dist/groundObjects.js.map +1 -0
- package/dist/groundSpeed.d.ts +20 -3
- package/dist/groundSpeed.js +117 -0
- package/dist/groundSpeed.js.map +1 -0
- package/dist/hero.d.ts +126 -10
- package/dist/hero.js +432 -0
- package/dist/hero.js.map +1 -0
- package/dist/holds.d.ts +94 -0
- package/dist/holds.js +305 -0
- package/dist/holds.js.map +1 -0
- package/dist/home.d.ts +1 -1
- package/dist/home.js +30 -0
- package/dist/home.js.map +1 -0
- package/dist/hooks.d.ts +339 -57
- package/dist/hooks.js +105 -0
- package/dist/hooks.js.map +1 -0
- package/dist/hotReload.d.ts +6 -5
- package/dist/hotReload.js +145 -0
- package/dist/hotReload.js.map +1 -0
- package/dist/ids.d.ts +3 -3
- package/dist/ids.js +30 -0
- package/dist/ids.js.map +1 -0
- package/dist/idsFile.d.ts +36 -0
- package/dist/idsFile.js +134 -0
- package/dist/idsFile.js.map +1 -0
- package/dist/index.d.ts +105 -68
- package/dist/index.js +194 -4701
- package/dist/inspect.d.ts +29 -2
- package/dist/{inspect-D9dWHmZ0.js → inspect.js} +21 -12
- package/dist/inspect.js.map +1 -0
- package/dist/inventory.d.ts +14 -1
- package/dist/inventory.js +84 -0
- package/dist/inventory.js.map +1 -0
- package/dist/items.d.ts +136 -8
- package/dist/items.js +585 -0
- package/dist/items.js.map +1 -0
- package/dist/lanes.d.ts +12 -3
- package/dist/lanes.js +496 -0
- package/dist/lanes.js.map +1 -0
- package/dist/life.d.ts +6 -2
- package/dist/life.js +287 -0
- package/dist/life.js.map +1 -0
- package/dist/log.d.ts +26 -3
- package/dist/log.js +192 -0
- package/dist/log.js.map +1 -0
- package/dist/manaBurn.d.ts +2 -2
- package/dist/manaBurn.js +75 -0
- package/dist/manaBurn.js.map +1 -0
- package/dist/map/file.d.ts +56 -3
- package/dist/map/file.js +264 -0
- package/dist/map/file.js.map +1 -0
- package/dist/map/images.js +61 -0
- package/dist/map/images.js.map +1 -0
- package/dist/map/look.d.ts +1 -1
- package/dist/map/look.js +30 -0
- package/dist/map/look.js.map +1 -0
- package/dist/map/pathProfile.js +183 -0
- package/dist/map/pathProfile.js.map +1 -0
- package/dist/map/resize.d.ts +4 -0
- package/dist/map/resize.js +136 -0
- package/dist/map/resize.js.map +1 -0
- package/dist/map/schema.js +257 -0
- package/dist/map/schema.js.map +1 -0
- package/dist/map/terrain.js +214 -0
- package/dist/map/terrain.js.map +1 -0
- package/dist/map/types.d.ts +92 -13
- package/dist/map/types.js +251 -0
- package/dist/map/types.js.map +1 -0
- package/dist/mapCheck/cells.js +94 -0
- package/dist/mapCheck/cells.js.map +1 -0
- package/dist/mapCheck/rules/foliage.d.ts +9 -0
- package/dist/mapCheck/rules/foliage.js +83 -0
- package/dist/mapCheck/rules/foliage.js.map +1 -0
- package/dist/mapCheck/rules/names.js +39 -0
- package/dist/mapCheck/rules/names.js.map +1 -0
- package/dist/mapCheck/rules/objects.d.ts +1 -1
- package/dist/mapCheck/rules/objects.js +56 -0
- package/dist/mapCheck/rules/objects.js.map +1 -0
- package/dist/mapCheck/rules/paths.js +32 -0
- package/dist/mapCheck/rules/paths.js.map +1 -0
- package/dist/mapCheck/rules/players.js +20 -0
- package/dist/mapCheck/rules/players.js.map +1 -0
- package/dist/mapCheck/rules/races.js +56 -0
- package/dist/mapCheck/rules/races.js.map +1 -0
- package/dist/mapCheck/rules/random.js +47 -0
- package/dist/mapCheck/rules/random.js.map +1 -0
- package/dist/mapCheck/rules/regions.js +30 -0
- package/dist/mapCheck/rules/regions.js.map +1 -0
- package/dist/mapCheck/rules/targets.js +31 -0
- package/dist/mapCheck/rules/targets.js.map +1 -0
- package/dist/mapCheck/rules/walking.js +45 -0
- package/dist/mapCheck/rules/walking.js.map +1 -0
- package/dist/mapCheck.d.ts +2 -2
- package/dist/mapCheck.js +63 -0
- package/dist/mapCheck.js.map +1 -0
- package/dist/mapFields.d.ts +25 -2
- package/dist/mapFields.js +134 -0
- package/dist/mapFields.js.map +1 -0
- package/dist/mapFile.js +176 -0
- package/dist/mapFile.js.map +1 -0
- package/dist/mapMeasure.d.ts +8 -0
- package/dist/mapMeasure.js +283 -0
- package/dist/mapMeasure.js.map +1 -0
- package/dist/mapMerge.d.ts +1 -0
- package/dist/mapMerge.js +172 -0
- package/dist/mapMerge.js.map +1 -0
- package/dist/mapObjectives.js +138 -0
- package/dist/mapObjectives.js.map +1 -0
- package/dist/mapObjects.js +80 -0
- package/dist/mapObjects.js.map +1 -0
- package/dist/math.d.ts +37 -7
- package/dist/math.js +155 -0
- package/dist/math.js.map +1 -0
- package/dist/messages.d.ts +71 -4
- package/dist/messages.js +29 -0
- package/dist/messages.js.map +1 -0
- package/dist/missionRules.d.ts +10 -2
- package/dist/{missionRules-C-bGxm0Q.js → missionRules.js} +30 -150
- package/dist/missionRules.js.map +1 -0
- package/dist/mods.d.ts +39 -20
- package/dist/mods.js +271 -0
- package/dist/mods.js.map +1 -0
- package/dist/moves.d.ts +87 -0
- package/dist/moves.js +539 -0
- package/dist/moves.js.map +1 -0
- package/dist/names.d.ts +7 -0
- package/dist/names.js +122 -0
- package/dist/names.js.map +1 -0
- package/dist/navigation/agentParams.js +14 -0
- package/dist/navigation/agentParams.js.map +1 -0
- package/dist/navigation/air.d.ts +7 -3
- package/dist/navigation/air.js +401 -0
- package/dist/navigation/air.js.map +1 -0
- package/dist/navigation/builds.d.ts +34 -2
- package/dist/navigation/builds.js +287 -0
- package/dist/navigation/builds.js.map +1 -0
- package/dist/navigation/groundAreas.d.ts +59 -1
- package/dist/navigation/groundAreas.js +407 -0
- package/dist/navigation/groundAreas.js.map +1 -0
- package/dist/navigation/navigation.d.ts +98 -9
- package/dist/navigation/recast.d.ts +194 -18
- package/dist/navigation/recast.js +1379 -0
- package/dist/navigation/recast.js.map +1 -0
- package/dist/navigation/sidePaths.d.ts +8 -3
- package/dist/navigation/sidePaths.js +241 -0
- package/dist/navigation/sidePaths.js.map +1 -0
- package/dist/navigation/sized.js +243 -0
- package/dist/navigation/sized.js.map +1 -0
- package/dist/nearest.js +32 -0
- package/dist/nearest.js.map +1 -0
- package/dist/noise.js +59 -0
- package/dist/noise.js.map +1 -0
- package/dist/objectives.d.ts +12 -3
- package/dist/objectives.js +144 -0
- package/dist/objectives.js.map +1 -0
- package/dist/orders/basic.d.ts +5 -5
- package/dist/orders/basic.js +417 -0
- package/dist/orders/basic.js.map +1 -0
- package/dist/orders/build.js +278 -0
- package/dist/orders/build.js.map +1 -0
- package/dist/orders/cast.d.ts +13 -3
- package/dist/orders/cast.js +558 -0
- package/dist/orders/cast.js.map +1 -0
- package/dist/orders/facts.js +16 -0
- package/dist/orders/facts.js.map +1 -0
- package/dist/orders/harvest.d.ts +21 -5
- package/dist/orders/harvest.js +540 -0
- package/dist/orders/harvest.js.map +1 -0
- package/dist/orders/idle.d.ts +3 -1
- package/dist/orders/idle.js +234 -0
- package/dist/orders/idle.js.map +1 -0
- package/dist/orders/items.js +92 -0
- package/dist/orders/items.js.map +1 -0
- package/dist/orders/queue.js +108 -0
- package/dist/orders/queue.js.map +1 -0
- package/dist/orders/waiting.d.ts +39 -0
- package/dist/orders/waiting.js +149 -0
- package/dist/orders/waiting.js.map +1 -0
- package/dist/pack.schema.js +13 -0
- package/dist/pack.schema.js.map +1 -0
- package/dist/pack.schema.json +7622 -841
- package/dist/packs/director/index.d.ts +13 -5
- package/dist/packs/director/index.js +204 -0
- package/dist/packs/director/index.js.map +1 -0
- package/dist/packs/heroes/campaign.d.ts +3 -2
- package/dist/packs/heroes/campaign.js +241 -0
- package/dist/packs/heroes/campaign.js.map +1 -0
- package/dist/packs/heroes/carry.d.ts +6 -0
- package/dist/packs/heroes/carry.js +112 -0
- package/dist/packs/heroes/carry.js.map +1 -0
- package/dist/packs/heroes/commands.js +115 -0
- package/dist/packs/heroes/commands.js.map +1 -0
- package/dist/packs/heroes/fallen.d.ts +43 -0
- package/dist/packs/heroes/fallen.js +61 -0
- package/dist/packs/heroes/fallen.js.map +1 -0
- package/dist/packs/heroes/hire.js +60 -0
- package/dist/packs/heroes/hire.js.map +1 -0
- package/dist/packs/heroes/index.d.ts +7 -6
- package/dist/packs/heroes/index.js +130 -0
- package/dist/packs/heroes/index.js.map +1 -0
- package/dist/packs/heroes/loop.d.ts +95 -0
- package/dist/packs/heroes/loop.js +250 -0
- package/dist/packs/heroes/loop.js.map +1 -0
- package/dist/packs/heroes/making.d.ts +6 -3
- package/dist/packs/heroes/making.js +55 -0
- package/dist/packs/heroes/making.js.map +1 -0
- package/dist/packs/heroes/respawn.d.ts +3 -3
- package/dist/packs/heroes/respawn.js +87 -0
- package/dist/packs/heroes/respawn.js.map +1 -0
- package/dist/packs/heroes/sets.d.ts +32 -0
- package/dist/packs/heroes/sets.js +51 -0
- package/dist/packs/heroes/sets.js.map +1 -0
- package/dist/packs/heroes/spells.d.ts +16 -0
- package/dist/packs/heroes/spells.js +269 -0
- package/dist/packs/heroes/spells.js.map +1 -0
- package/dist/packs/items/defaults.d.ts +43 -0
- package/dist/packs/items/defaults.js +1504 -0
- package/dist/packs/items/defaults.js.map +1 -0
- package/dist/packs/items/index.d.ts +27 -0
- package/dist/packs/items/index.js +214 -0
- package/dist/packs/items/index.js.map +1 -0
- package/dist/packs/moba/index.d.ts +3 -3
- package/dist/packs/moba/index.js +174 -0
- package/dist/packs/moba/index.js.map +1 -0
- package/dist/packs/pack.d.ts +15 -15
- package/dist/packs/pack.js +14 -0
- package/dist/packs/pack.js.map +1 -0
- package/dist/packs.d.ts +15 -7
- package/dist/packs.js +222 -0
- package/dist/packs.js.map +1 -0
- package/dist/paths.d.ts +2 -0
- package/dist/paths.js +109 -0
- package/dist/paths.js.map +1 -0
- package/dist/plain.js +57 -0
- package/dist/plain.js.map +1 -0
- package/dist/player.d.ts +33 -10
- package/dist/player.js +159 -0
- package/dist/player.js.map +1 -0
- package/dist/portals.d.ts +1 -1
- package/dist/portals.js +194 -0
- package/dist/portals.js.map +1 -0
- package/dist/prefabs.d.ts +25 -2
- package/dist/prefabs.js +239 -0
- package/dist/prefabs.js.map +1 -0
- package/dist/presetBuildings.js +58 -0
- package/dist/presetBuildings.js.map +1 -0
- package/dist/presetFoliage.d.ts +27 -0
- package/dist/presetFoliage.js +98 -0
- package/dist/presetFoliage.js.map +1 -0
- package/dist/presetGround.js +65 -0
- package/dist/presetGround.js.map +1 -0
- package/dist/proxies.d.ts +12 -0
- package/dist/proxies.js +79 -0
- package/dist/proxies.js.map +1 -0
- package/dist/query.d.ts +56 -0
- package/dist/query.js +88 -0
- package/dist/query.js.map +1 -0
- package/dist/races.d.ts +15 -14
- package/dist/races.js +172 -0
- package/dist/races.js.map +1 -0
- package/dist/randomGroups.js +91 -0
- package/dist/randomGroups.js.map +1 -0
- package/dist/registry.d.ts +117 -53
- package/dist/registry.js +323 -0
- package/dist/registry.js.map +1 -0
- package/dist/remains.d.ts +11 -9
- package/dist/remains.js +188 -0
- package/dist/remains.js.map +1 -0
- package/dist/replication.d.ts +12 -7
- package/dist/replication.js +100 -0
- package/dist/replication.js.map +1 -0
- package/dist/rng.d.ts +2 -0
- package/dist/rng.js +40 -0
- package/dist/rng.js.map +1 -0
- package/dist/rules.d.ts +186 -99
- package/dist/rules.js +179 -0
- package/dist/rules.js.map +1 -0
- package/dist/rulesCheck.d.ts +5 -4
- package/dist/rulesCheck.js +693 -0
- package/dist/rulesCheck.js.map +1 -0
- package/dist/runes.d.ts +2 -2
- package/dist/runes.js +80 -0
- package/dist/runes.js.map +1 -0
- package/dist/save.d.ts +37 -12
- package/dist/save.js +532 -0
- package/dist/save.js.map +1 -0
- package/dist/scenario.d.ts +2 -2
- package/dist/scenario.js +99 -0
- package/dist/scenario.js.map +1 -0
- package/dist/scheduler.d.ts +3 -0
- package/dist/scheduler.js +156 -0
- package/dist/scheduler.js.map +1 -0
- package/dist/score.d.ts +19 -19
- package/dist/score.js +709 -0
- package/dist/score.js.map +1 -0
- package/dist/sequences.d.ts +10 -6
- package/dist/sequences.js +206 -0
- package/dist/sequences.js.map +1 -0
- package/dist/server/doorman.js +154 -0
- package/dist/server/doorman.js.map +1 -0
- package/dist/server/gameServer.d.ts +16 -1
- package/dist/server/gameServer.js +643 -0
- package/dist/server/gameServer.js.map +1 -0
- package/dist/server/index.d.ts +1 -1
- package/dist/server/lobby.js +199 -0
- package/dist/server/lobby.js.map +1 -0
- package/dist/server/log.js +18 -0
- package/dist/server/log.js.map +1 -0
- package/dist/server/match.js +267 -0
- package/dist/server/match.js.map +1 -0
- package/dist/server/mode.d.ts +18 -9
- package/dist/server/mode.js +220 -0
- package/dist/server/mode.js.map +1 -0
- package/dist/{navigation-worker.js → server/navigation-worker.js} +1 -1
- package/dist/server/navigation-worker.js.map +1 -0
- package/dist/server/navigation.js +39 -0
- package/dist/server/navigation.js.map +1 -0
- package/dist/server/ops.d.ts +4 -0
- package/dist/server/ops.js +137 -0
- package/dist/server/ops.js.map +1 -0
- package/dist/server/packs.d.ts +3 -3
- package/dist/server/packs.js +32 -0
- package/dist/server/packs.js.map +1 -0
- package/dist/server/ratings.d.ts +5 -0
- package/dist/server/ratings.js +104 -0
- package/dist/server/ratings.js.map +1 -0
- package/dist/server/relay.d.ts +12 -2
- package/dist/server/relay.js +144 -0
- package/dist/server/relay.js.map +1 -0
- package/dist/server/rooms.d.ts +9 -2
- package/dist/server/rooms.js +442 -0
- package/dist/server/rooms.js.map +1 -0
- package/dist/server/seat.js +116 -0
- package/dist/server/seat.js.map +1 -0
- package/dist/server/seatSettings.d.ts +3 -3
- package/dist/server/seatSettings.js +63 -0
- package/dist/server/seatSettings.js.map +1 -0
- package/dist/server/secret.js +13 -0
- package/dist/server/secret.js.map +1 -0
- package/dist/server/start.d.ts +13 -6
- package/dist/server/start.js +76 -0
- package/dist/server/start.js.map +1 -0
- package/dist/server/websocket.d.ts +9 -1
- package/dist/server/websocket.js +306 -0
- package/dist/server/websocket.js.map +1 -0
- package/dist/server.js +15 -2861
- package/dist/session/can.js +26 -0
- package/dist/session/can.js.map +1 -0
- package/dist/session/commandReplay.d.ts +8 -2
- package/dist/session/commandReplay.js +293 -0
- package/dist/session/commandReplay.js.map +1 -0
- package/dist/session/debug.js +151 -0
- package/dist/session/debug.js.map +1 -0
- package/dist/session/delay.js +62 -0
- package/dist/session/delay.js.map +1 -0
- package/dist/session/delta.d.ts +14 -1
- package/dist/session/delta.js +407 -0
- package/dist/session/delta.js.map +1 -0
- package/dist/session/entityState.js +415 -0
- package/dist/session/entityState.js.map +1 -0
- package/dist/session/local.d.ts +47 -5
- package/dist/session/local.js +670 -0
- package/dist/session/local.js.map +1 -0
- package/dist/session/memory.d.ts +20 -2
- package/dist/session/memory.js +131 -0
- package/dist/session/memory.js.map +1 -0
- package/dist/session/protocol.d.ts +325 -31
- package/dist/session/protocol.js +55 -0
- package/dist/session/protocol.js.map +1 -0
- package/dist/session/remote.d.ts +74 -12
- package/dist/session/remote.js +1394 -0
- package/dist/session/remote.js.map +1 -0
- package/dist/session/replay.d.ts +11 -2
- package/dist/session/replay.js +160 -0
- package/dist/session/replay.js.map +1 -0
- package/dist/session/seed.js +12 -0
- package/dist/session/seed.js.map +1 -0
- package/dist/session/share.d.ts +5 -1
- package/dist/session/share.js +94 -0
- package/dist/session/share.js.map +1 -0
- package/dist/session/socket.d.ts +1 -1
- package/dist/session/socket.js +29 -0
- package/dist/session/socket.js.map +1 -0
- package/dist/session/wire.d.ts +5 -0
- package/dist/session/wire.js +84 -0
- package/dist/session/wire.js.map +1 -0
- package/dist/session/worker.d.ts +77 -12
- package/dist/session/worker.js +499 -0
- package/dist/session/worker.js.map +1 -0
- package/dist/shared.d.ts +31 -5
- package/dist/shared.js +166 -0
- package/dist/shared.js.map +1 -0
- package/dist/sides.d.ts +9 -3
- package/dist/sides.js +149 -0
- package/dist/sides.js.map +1 -0
- package/dist/sight.js +85 -0
- package/dist/sight.js.map +1 -0
- package/dist/simulate-worker.js +1 -1
- package/dist/simulate.d.ts +12 -8
- package/dist/{simulate-oXBiw1Ff.js → simulate.js} +10 -11
- package/dist/simulate.js.map +1 -0
- package/dist/smart.js +77 -0
- package/dist/smart.js.map +1 -0
- package/dist/spatial.d.ts +32 -16
- package/dist/spatial.js +234 -0
- package/dist/spatial.js.map +1 -0
- package/dist/spawning.d.ts +1 -0
- package/dist/spawning.js +224 -0
- package/dist/spawning.js.map +1 -0
- package/dist/stances.d.ts +6 -3
- package/dist/stances.js +169 -0
- package/dist/stances.js.map +1 -0
- package/dist/start.d.ts +10 -10
- package/dist/start.js +75 -0
- package/dist/start.js.map +1 -0
- package/dist/stats.d.ts +42 -16
- package/dist/stats.js +290 -0
- package/dist/stats.js.map +1 -0
- package/dist/summoned.d.ts +52 -0
- package/dist/summoned.js +38 -0
- package/dist/summoned.js.map +1 -0
- package/dist/summons.d.ts +10 -13
- package/dist/summons.js +271 -0
- package/dist/summons.js.map +1 -0
- package/dist/systems/abilities.js +224 -0
- package/dist/systems/abilities.js.map +1 -0
- package/dist/systems/combat.d.ts +35 -1
- package/dist/systems/combat.js +677 -0
- package/dist/systems/combat.js.map +1 -0
- package/dist/systems/combatTold.d.ts +3 -1
- package/dist/systems/combatTold.js +85 -0
- package/dist/systems/combatTold.js.map +1 -0
- package/dist/systems/construction.js +80 -0
- package/dist/systems/construction.js.map +1 -0
- package/dist/systems/economy.d.ts +0 -6
- package/dist/systems/economy.js +128 -0
- package/dist/systems/economy.js.map +1 -0
- package/dist/systems/fog.d.ts +1 -1
- package/dist/systems/fog.js +120 -0
- package/dist/systems/fog.js.map +1 -0
- package/dist/systems/life.js +32 -0
- package/dist/systems/life.js.map +1 -0
- package/dist/systems/movement.d.ts +24 -12
- package/dist/systems/movement.js +1247 -0
- package/dist/systems/movement.js.map +1 -0
- package/dist/systems/orders.js +64 -0
- package/dist/systems/orders.js.map +1 -0
- package/dist/systems/production.js +322 -0
- package/dist/systems/production.js.map +1 -0
- package/dist/systems/productionQueue.js +120 -0
- package/dist/systems/productionQueue.js.map +1 -0
- package/dist/systems/victory.d.ts +1 -1
- package/dist/systems/victory.js +56 -0
- package/dist/systems/victory.js.map +1 -0
- package/dist/talk.d.ts +6 -6
- package/dist/talk.js +153 -0
- package/dist/talk.js.map +1 -0
- package/dist/targeting.d.ts +142 -0
- package/dist/targeting.js +49 -0
- package/dist/targeting.js.map +1 -0
- package/dist/tech.d.ts +20 -3
- package/dist/tech.js +239 -0
- package/dist/tech.js.map +1 -0
- package/dist/techTree.d.ts +7 -0
- package/dist/techTree.js +90 -0
- package/dist/techTree.js.map +1 -0
- package/dist/terrain.d.ts +59 -7
- package/dist/terrain.js +389 -0
- package/dist/terrain.js.map +1 -0
- package/dist/terrainSave.d.ts +6 -0
- package/dist/terrainSave.js +74 -0
- package/dist/terrainSave.js.map +1 -0
- package/dist/testing.d.ts +8 -7
- package/dist/testing.js +13 -739
- package/dist/testing.js.map +1 -1
- package/dist/tiles.d.ts +1 -1
- package/dist/tiles.js +43 -0
- package/dist/tiles.js.map +1 -0
- package/dist/timers.d.ts +29 -4
- package/dist/timers.js +242 -0
- package/dist/timers.js.map +1 -0
- package/dist/tomes.d.ts +4 -4
- package/dist/tomes.js +94 -0
- package/dist/tomes.js.map +1 -0
- package/dist/trade.js +103 -0
- package/dist/trade.js.map +1 -0
- package/dist/transport.d.ts +6 -1
- package/dist/transport.js +281 -0
- package/dist/transport.js.map +1 -0
- package/dist/tunables.d.ts +10 -3
- package/dist/tunables.js +56 -0
- package/dist/tunables.js.map +1 -0
- package/dist/unitResources.d.ts +67 -0
- package/dist/unitResources.js +266 -0
- package/dist/unitResources.js.map +1 -0
- package/dist/upkeep.d.ts +6 -1
- package/dist/upkeep.js +26 -0
- package/dist/upkeep.js.map +1 -0
- package/dist/veterancy.d.ts +8 -3
- package/dist/veterancy.js +131 -0
- package/dist/veterancy.js.map +1 -0
- package/dist/vision.d.ts +36 -0
- package/dist/vision.js +133 -0
- package/dist/vision.js.map +1 -0
- package/dist/walls.d.ts +1 -1
- package/dist/walls.js +278 -0
- package/dist/walls.js.map +1 -0
- package/dist/world.d.ts +606 -88
- package/dist/world.js +1263 -0
- package/dist/world.js.map +1 -0
- package/package.json +2 -2
- package/dist/ai.js.map +0 -1
- package/dist/attributes.d.ts +0 -66
- package/dist/brain-BvVdUhX8.js +0 -7659
- package/dist/brain-BvVdUhX8.js.map +0 -1
- package/dist/builds-C6LfgvEU.js +0 -460
- package/dist/builds-C6LfgvEU.js.map +0 -1
- package/dist/coreComponents-syuh2fPG.js +0 -5149
- package/dist/coreComponents-syuh2fPG.js.map +0 -1
- package/dist/debugCommands-CzjrSm66.js +0 -14739
- package/dist/debugCommands-CzjrSm66.js.map +0 -1
- package/dist/determinism-BCymQwiE.js +0 -518
- package/dist/determinism-BCymQwiE.js.map +0 -1
- package/dist/game-DiJEN-Ks.js +0 -5800
- package/dist/game-DiJEN-Ks.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/inspect-D9dWHmZ0.js.map +0 -1
- package/dist/local-Dkovq42k.js +0 -1379
- package/dist/local-Dkovq42k.js.map +0 -1
- package/dist/missionRules-C-bGxm0Q.js.map +0 -1
- package/dist/navigation-worker.js.map +0 -1
- package/dist/packs-g5thvmGn.js +0 -3199
- package/dist/packs-g5thvmGn.js.map +0 -1
- package/dist/profiles-B3NS9jwk.js.map +0 -1
- package/dist/server.js.map +0 -1
- package/dist/simulate-oXBiw1Ff.js.map +0 -1
|
@@ -0,0 +1,1379 @@
|
|
|
1
|
+
import { walkedCell } from "../terrain.js";
|
|
2
|
+
import { addTileLayer, columnTileCache, groundMeshProcess, groundTileLayers, layerOf, setAreaCosts, tileGridOf, tileKey } from "./groundAreas.js";
|
|
3
|
+
import { buildNavigationData, buildNavigationNow, inTurn, initRecast, navigationData } from "./builds.js";
|
|
4
|
+
import { Crowd, DebugDrawerUtils, NavMeshQuery, Raw, TileCacheMeshProcess, importTileCache } from "@recast-navigation/core";
|
|
5
|
+
import { createDefaultTileCacheMeshProcess } from "@recast-navigation/generators";
|
|
6
|
+
//#region src/navigation/recast.ts
|
|
7
|
+
/**
|
|
8
|
+
* The engine's avoidance (`RecastNavigationOptions.avoidance`): Detour's own numbers, which `AVOIDANCE_LEVELS` change the sampling of
|
|
9
|
+
*
|
|
10
|
+
* @internal
|
|
11
|
+
*/
|
|
12
|
+
var DEFAULT_AVOIDANCE = Object.freeze({
|
|
13
|
+
velBias: .4,
|
|
14
|
+
weightDesVel: 2,
|
|
15
|
+
weightCurVel: .75,
|
|
16
|
+
weightSide: .75,
|
|
17
|
+
weightToi: 2.5,
|
|
18
|
+
horizTime: 2.5,
|
|
19
|
+
gridSize: 33,
|
|
20
|
+
adaptiveDivs: 7,
|
|
21
|
+
adaptiveRings: 2,
|
|
22
|
+
adaptiveDepth: 5
|
|
23
|
+
});
|
|
24
|
+
/**
|
|
25
|
+
* What `walls: 'soft'` changes of `DEFAULT_AVOIDANCE`, under the level and a game's own numbers: what is ahead counts
|
|
26
|
+
* within 1.5 s (Detour's 2.5) and weighs 1.5 (2.5), and going the speed it wants weighs 3 (2), so that a slower
|
|
27
|
+
* velocity that would touch a wall a little later no longer wins
|
|
28
|
+
*
|
|
29
|
+
* @beta
|
|
30
|
+
*/
|
|
31
|
+
var SOFT_WALLS = Object.freeze({
|
|
32
|
+
horizTime: 1.5,
|
|
33
|
+
weightToi: 1.5,
|
|
34
|
+
weightDesVel: 3
|
|
35
|
+
});
|
|
36
|
+
/**
|
|
37
|
+
* What each `AvoidanceLevel` changes of `DEFAULT_AVOIDANCE`: the sampling (`adaptiveDivs`, `adaptiveRings` and
|
|
38
|
+
* `adaptiveDepth`, which what an agent costs a tick goes by)
|
|
39
|
+
*
|
|
40
|
+
* @beta
|
|
41
|
+
*/
|
|
42
|
+
var AVOIDANCE_LEVELS = Object.freeze({
|
|
43
|
+
low: Object.freeze({
|
|
44
|
+
adaptiveDivs: 5,
|
|
45
|
+
adaptiveRings: 1,
|
|
46
|
+
adaptiveDepth: 3
|
|
47
|
+
}),
|
|
48
|
+
medium: Object.freeze({}),
|
|
49
|
+
high: Object.freeze({
|
|
50
|
+
adaptiveDivs: 7,
|
|
51
|
+
adaptiveRings: 3,
|
|
52
|
+
adaptiveDepth: 7
|
|
53
|
+
})
|
|
54
|
+
});
|
|
55
|
+
var DEFAULT_FLAGS = 31;
|
|
56
|
+
var GHOST_FLAGS = 25;
|
|
57
|
+
/**
|
|
58
|
+
* An agent with nowhere to go: no velocity sampled among its neighbours, which for one that wants to stand still comes to
|
|
59
|
+
* standing still all the same (a crowd of idle units: EN1, the same hashes). It is pushed as any agent is
|
|
60
|
+
*/
|
|
61
|
+
var RESTING_FLAGS = 29;
|
|
62
|
+
/** What an agent's target is while its path is still being looked for: requesting, waiting for the queue, waiting for the path */
|
|
63
|
+
var PLANNING = /* @__PURE__ */ new Set([
|
|
64
|
+
3,
|
|
65
|
+
4,
|
|
66
|
+
5
|
|
67
|
+
]);
|
|
68
|
+
/** How fast an agent with no speed left comes to a halt, in ground units per second squared */
|
|
69
|
+
var BRAKING = 60;
|
|
70
|
+
/**
|
|
71
|
+
* Detour's states of an agent. An invalid one is left out of every step of the crowd (no path checked, no neighbours
|
|
72
|
+
* looked for, no velocity sampled, not moved, not pushed) but stays in the grid the others look for neighbours in: it
|
|
73
|
+
* is what an anchored agent is, asleep where it stands, while everyone else still goes around it
|
|
74
|
+
*/
|
|
75
|
+
var INVALID = 0;
|
|
76
|
+
var WALKING = 1;
|
|
77
|
+
/**
|
|
78
|
+
* Where the mirror of an agent that phases is kept (`setMirrorPhasing`): far from anyone, so that it is nobody's
|
|
79
|
+
* neighbour, and still in its place among the crowd's agents
|
|
80
|
+
*/
|
|
81
|
+
var PARKED = -1e5;
|
|
82
|
+
/** Each cell's speed on the ground, as a build is told it: none where every cell is 1 (the ground cut as it always was) */
|
|
83
|
+
function speedsOf(terrain, speedAt) {
|
|
84
|
+
const { width, depth } = terrain;
|
|
85
|
+
const values = new Float32Array(width * depth);
|
|
86
|
+
let slow = false;
|
|
87
|
+
for (let z = 0; z < depth; z++) for (let x = 0; x < width; x++) {
|
|
88
|
+
const speed = speedAt(x + .5, z + .5);
|
|
89
|
+
values[z * width + x] = speed;
|
|
90
|
+
if (speed !== 1) slow = true;
|
|
91
|
+
}
|
|
92
|
+
return slow ? {
|
|
93
|
+
width,
|
|
94
|
+
depth,
|
|
95
|
+
values
|
|
96
|
+
} : void 0;
|
|
97
|
+
}
|
|
98
|
+
/** The least of one coordinate (0 x, 2 z) of the vertices a mesh's triangles use: where its tiles start, as Recast's bounds do */
|
|
99
|
+
function minOf(positions, indices, axis) {
|
|
100
|
+
let least = Infinity;
|
|
101
|
+
for (let i = 0; i < indices.length; i++) least = Math.min(least, positions[indices[i] * 3 + axis]);
|
|
102
|
+
return least;
|
|
103
|
+
}
|
|
104
|
+
/** A limit from the map's size, never less than it was before the map's size counted, never past what Detour counts to */
|
|
105
|
+
var limitFor = (wanted, least) => Math.min(Math.max(Math.ceil(wanted), least), 65535);
|
|
106
|
+
/** How many requests the tile cache queues, and how many tiles it makes again from one batch of them, at most (Detour's) */
|
|
107
|
+
var MAX_REQUESTS = 64;
|
|
108
|
+
/** Half of Detour's 64: a column of the tile grid may hold more than one layer, and each is a tile of its own */
|
|
109
|
+
var MAX_HELD_COLUMNS = 32;
|
|
110
|
+
/**
|
|
111
|
+
* The walkable ground about some tiles (their keys), as `Terrain.buildMesh(true)` and `speedsOf` give it whole: the
|
|
112
|
+
* triangles of the cells within a tile's border (and a cell more) of each, in the whole mesh's order, and the speed of
|
|
113
|
+
* the cell a point is in, so that each of those tiles is made from it as from the whole (`groundTileLayers` takes a
|
|
114
|
+
* tile's triangles by where they reach). As much as those tiles need, however big the map
|
|
115
|
+
*/
|
|
116
|
+
function groundPart(terrain, config, speedAt, keys, grid) {
|
|
117
|
+
const { width, depth, vertsX } = terrain;
|
|
118
|
+
const reach = grid.border + 1;
|
|
119
|
+
const near = [];
|
|
120
|
+
for (const key of keys) {
|
|
121
|
+
const tx = Math.floor(key / 65536);
|
|
122
|
+
const ty = key % 65536;
|
|
123
|
+
const x0 = Math.max(0, Math.floor(grid.bbMin[0] + tx * grid.tileSize - reach));
|
|
124
|
+
const x1 = Math.min(width - 1, Math.ceil(grid.bbMin[0] + (tx + 1) * grid.tileSize + reach));
|
|
125
|
+
const z0 = Math.max(0, Math.floor(grid.bbMin[2] + ty * grid.tileSize - reach));
|
|
126
|
+
const z1 = Math.min(depth - 1, Math.ceil(grid.bbMin[2] + (ty + 1) * grid.tileSize + reach));
|
|
127
|
+
for (let iz = z0; iz <= z1; iz++) for (let ix = x0; ix <= x1; ix++) near.push(iz * width + ix);
|
|
128
|
+
}
|
|
129
|
+
near.sort((a, b) => a - b);
|
|
130
|
+
const speeds = /* @__PURE__ */ new Map();
|
|
131
|
+
const vertices = /* @__PURE__ */ new Map();
|
|
132
|
+
const positions = [];
|
|
133
|
+
const indices = [];
|
|
134
|
+
const vertex = (v) => {
|
|
135
|
+
let at = vertices.get(v);
|
|
136
|
+
if (at === void 0) {
|
|
137
|
+
at = vertices.size;
|
|
138
|
+
vertices.set(v, at);
|
|
139
|
+
positions.push(v % vertsX, terrain.heights[v], Math.floor(v / vertsX));
|
|
140
|
+
}
|
|
141
|
+
return at;
|
|
142
|
+
};
|
|
143
|
+
for (let i = 0; i < near.length; i++) {
|
|
144
|
+
const cell = near[i];
|
|
145
|
+
if (cell === near[i - 1]) continue;
|
|
146
|
+
const ix = cell % width;
|
|
147
|
+
const iz = (cell - ix) / width;
|
|
148
|
+
if (!walkedCell(terrain, ix, iz)) continue;
|
|
149
|
+
speeds.set(cell, speedAt(ix + .5, iz + .5));
|
|
150
|
+
const a = iz * vertsX + ix;
|
|
151
|
+
const [va, vb, vc, vd] = [
|
|
152
|
+
vertex(a),
|
|
153
|
+
vertex(a + 1),
|
|
154
|
+
vertex(a + vertsX),
|
|
155
|
+
vertex(a + vertsX + 1)
|
|
156
|
+
];
|
|
157
|
+
indices.push(va, vc, vb, vb, vc, vd);
|
|
158
|
+
}
|
|
159
|
+
return {
|
|
160
|
+
build: {
|
|
161
|
+
positions: Float32Array.from(positions),
|
|
162
|
+
indices: Uint32Array.from(indices),
|
|
163
|
+
config
|
|
164
|
+
},
|
|
165
|
+
speedOf: (x, z) => speeds.get(Math.floor(z) * width + Math.floor(x)) ?? 1
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* More than this share of the tiles reshaped at once is cut whole, and nothing kept apart after. Only a reshape: a
|
|
170
|
+
* slowing layer painted is never cut whole (`groundChanged`), its tiles alone being quicker
|
|
171
|
+
*/
|
|
172
|
+
var MOST_TILES = .5;
|
|
173
|
+
/** The slot of the crowd's obstacle avoidance parameters every agent uses */
|
|
174
|
+
var AVOIDANCE_SLOT = 3;
|
|
175
|
+
/**
|
|
176
|
+
* A crowd on the navmesh with room for `maxAgents` agents, of any radius up to twice the one it was cut for, steering
|
|
177
|
+
* as `avoidance` says
|
|
178
|
+
*/
|
|
179
|
+
function crowdOf(navMesh, maxAgents, agentRadius, avoidance, weighs) {
|
|
180
|
+
const crowd = new Crowd(navMesh, {
|
|
181
|
+
maxAgents,
|
|
182
|
+
maxAgentRadius: Math.max(agentRadius * 2, 1)
|
|
183
|
+
});
|
|
184
|
+
crowd.navMeshQuery.defaultQueryHalfExtents = {
|
|
185
|
+
x: 2,
|
|
186
|
+
y: 6,
|
|
187
|
+
z: 2
|
|
188
|
+
};
|
|
189
|
+
if (weighs) setAreaCosts(crowd.getFilter(0));
|
|
190
|
+
const params = new Raw.Module.dtObstacleAvoidanceParams();
|
|
191
|
+
params.velBias = avoidance.velBias;
|
|
192
|
+
params.weightDesVel = avoidance.weightDesVel;
|
|
193
|
+
params.weightCurVel = avoidance.weightCurVel;
|
|
194
|
+
params.weightSide = avoidance.weightSide;
|
|
195
|
+
params.weightToi = avoidance.weightToi;
|
|
196
|
+
params.horizTime = avoidance.horizTime;
|
|
197
|
+
params.gridSize = avoidance.gridSize;
|
|
198
|
+
params.adaptiveDivs = avoidance.adaptiveDivs;
|
|
199
|
+
params.adaptiveRings = avoidance.adaptiveRings;
|
|
200
|
+
params.adaptiveDepth = avoidance.adaptiveDepth;
|
|
201
|
+
crowd.raw.setObstacleAvoidanceParams(AVOIDANCE_SLOT, params);
|
|
202
|
+
Raw.destroy(params);
|
|
203
|
+
return crowd;
|
|
204
|
+
}
|
|
205
|
+
var RecastNavigation = class RecastNavigation {
|
|
206
|
+
terrain;
|
|
207
|
+
navMesh;
|
|
208
|
+
tileCache;
|
|
209
|
+
crowd;
|
|
210
|
+
query;
|
|
211
|
+
agentRadius;
|
|
212
|
+
maxAgents;
|
|
213
|
+
maxObstacles;
|
|
214
|
+
maxNodes;
|
|
215
|
+
owned;
|
|
216
|
+
avoidance;
|
|
217
|
+
separation;
|
|
218
|
+
walls;
|
|
219
|
+
tiles;
|
|
220
|
+
heightAt;
|
|
221
|
+
ground;
|
|
222
|
+
cut;
|
|
223
|
+
/** One more each time walkable space changes (`version`) */
|
|
224
|
+
changes = 0;
|
|
225
|
+
/** What the ground's changes asked and is not done yet: none, mostly */
|
|
226
|
+
asked;
|
|
227
|
+
agents = /* @__PURE__ */ new Map();
|
|
228
|
+
mirrors = /* @__PURE__ */ new Map();
|
|
229
|
+
/**
|
|
230
|
+
* The crowd of the agents that walk through others (`setPhasing`), on the same navmesh, made as the first comes:
|
|
231
|
+
* Detour has no way to keep an agent out of the others' neighbours, so it walks where there are none. Walls,
|
|
232
|
+
* cliffs and obstacles are the navmesh's, and stop it as they stop anyone
|
|
233
|
+
*/
|
|
234
|
+
phasers;
|
|
235
|
+
/** How many agents the crowd of those that phase has room for now */
|
|
236
|
+
phasersRoom = 0;
|
|
237
|
+
obstacles = /* @__PURE__ */ new Map();
|
|
238
|
+
/** The room the crowd was first made with: a crowd made anew (`reseat`) starts there, as a loaded world's does */
|
|
239
|
+
firstMaxAgents = 0;
|
|
240
|
+
obstaclesDirty = false;
|
|
241
|
+
/** Obstacles are put down many at once (`holdObstacles`): their requests wait in the tile cache to be made into tiles together */
|
|
242
|
+
holding = false;
|
|
243
|
+
/** Requests waiting while held, and the columns of the tile grid they touch (x * 65536 + z) */
|
|
244
|
+
held = 0;
|
|
245
|
+
heldColumns = /* @__PURE__ */ new Set();
|
|
246
|
+
/** Points handed to the module, which copies them in: one, and a second for a path's end */
|
|
247
|
+
scratch = {
|
|
248
|
+
x: 0,
|
|
249
|
+
y: 0,
|
|
250
|
+
z: 0
|
|
251
|
+
};
|
|
252
|
+
scratchEnd = {
|
|
253
|
+
x: 0,
|
|
254
|
+
y: 0,
|
|
255
|
+
z: 0
|
|
256
|
+
};
|
|
257
|
+
/** How far `closestPoint` looks, set for each ask */
|
|
258
|
+
closestQuery = { halfExtents: {
|
|
259
|
+
x: 0,
|
|
260
|
+
y: 8,
|
|
261
|
+
z: 0
|
|
262
|
+
} };
|
|
263
|
+
/** What `steer` works in each tick, kept: the agents that count, where they are, and a grid of them */
|
|
264
|
+
near = [];
|
|
265
|
+
nearX = /* @__PURE__ */ new Float64Array(0);
|
|
266
|
+
nearZ = /* @__PURE__ */ new Float64Array(0);
|
|
267
|
+
nearNext = /* @__PURE__ */ new Int32Array(0);
|
|
268
|
+
nearHeads = /* @__PURE__ */ new Map();
|
|
269
|
+
/** The tiles made again alone since the ground was last cut whole (`groundChanged`, `reshape` of a part) */
|
|
270
|
+
overridden;
|
|
271
|
+
/**
|
|
272
|
+
* The obstacles about each column of the grid (`columnsOf`), by their keys, in the order they were put down: what a
|
|
273
|
+
* column made alone is made with. Kept while tiles are made alone, made from `obstacles` as the first is
|
|
274
|
+
*/
|
|
275
|
+
byColumn;
|
|
276
|
+
/** The grid the whole was cut on (`tileGridOf`): a part is made again alone only where the ground is cut on the same */
|
|
277
|
+
grid;
|
|
278
|
+
/** Columns of the grid obstacles were put down or taken up on, while tiles are made alone: made again from theirs */
|
|
279
|
+
requested = /* @__PURE__ */ new Set();
|
|
280
|
+
constructor(terrain, navMesh, tileCache, crowd, query, agentRadius, maxAgents, maxObstacles, maxNodes, owned, avoidance, separation, walls, tiles, heightAt = (x, z) => terrain.heightAt(x, z), ground, cut) {
|
|
281
|
+
this.terrain = terrain;
|
|
282
|
+
this.navMesh = navMesh;
|
|
283
|
+
this.tileCache = tileCache;
|
|
284
|
+
this.crowd = crowd;
|
|
285
|
+
this.query = query;
|
|
286
|
+
this.agentRadius = agentRadius;
|
|
287
|
+
this.maxAgents = maxAgents;
|
|
288
|
+
this.maxObstacles = maxObstacles;
|
|
289
|
+
this.maxNodes = maxNodes;
|
|
290
|
+
this.owned = owned;
|
|
291
|
+
this.avoidance = avoidance;
|
|
292
|
+
this.separation = separation;
|
|
293
|
+
this.walls = walls;
|
|
294
|
+
this.tiles = tiles;
|
|
295
|
+
this.heightAt = heightAt;
|
|
296
|
+
this.ground = ground;
|
|
297
|
+
this.cut = cut;
|
|
298
|
+
this.firstMaxAgents = maxAgents;
|
|
299
|
+
}
|
|
300
|
+
static async create(terrain, options = {}) {
|
|
301
|
+
const builder = options.builds?.builder;
|
|
302
|
+
if (builder && builder !== buildNavigationData) return RecastNavigation.made(terrain, options);
|
|
303
|
+
return inTurn(() => RecastNavigation.made(terrain, options));
|
|
304
|
+
}
|
|
305
|
+
static async made(terrain, options) {
|
|
306
|
+
await initRecast();
|
|
307
|
+
const cells = terrain.width * terrain.depth;
|
|
308
|
+
const { agentRadius = .5, maxSlope = 38, maxAgents = 512, maxObstacles = limitFor(cells, 8192), maxNodes = limitFor(cells / 4, 4096), cellSize = .25, surface = "ground", separation = .5, walls = "soft" } = options;
|
|
309
|
+
const avoidance = Object.freeze({
|
|
310
|
+
...DEFAULT_AVOIDANCE,
|
|
311
|
+
...walls === "soft" && SOFT_WALLS,
|
|
312
|
+
...AVOIDANCE_LEVELS[typeof options.avoidance === "string" ? options.avoidance : "medium"],
|
|
313
|
+
...typeof options.avoidance === "object" && options.avoidance
|
|
314
|
+
});
|
|
315
|
+
const cellHeight = .2;
|
|
316
|
+
const water = surface === "water";
|
|
317
|
+
const config = {
|
|
318
|
+
cs: cellSize,
|
|
319
|
+
ch: cellHeight,
|
|
320
|
+
tileSize: 48,
|
|
321
|
+
walkableSlopeAngle: maxSlope,
|
|
322
|
+
walkableHeight: Math.ceil(2 / cellHeight),
|
|
323
|
+
walkableClimb: Math.ceil(.6 / cellHeight),
|
|
324
|
+
walkableRadius: Math.ceil(agentRadius / cellSize),
|
|
325
|
+
maxSimplificationError: 1.1,
|
|
326
|
+
mergeRegionArea: 20,
|
|
327
|
+
maxVertsPerPoly: 6,
|
|
328
|
+
detailSampleDist: 4,
|
|
329
|
+
detailSampleMaxError: .5,
|
|
330
|
+
expectedLayersPerTile: 1,
|
|
331
|
+
maxObstacles
|
|
332
|
+
};
|
|
333
|
+
const speedAt = water ? void 0 : options.speedAt;
|
|
334
|
+
const cut = () => {
|
|
335
|
+
const { positions, indices } = water ? terrain.buildWaterMesh() : terrain.buildMesh(true);
|
|
336
|
+
const speeds = speedAt && speedsOf(terrain, speedAt);
|
|
337
|
+
return {
|
|
338
|
+
build: {
|
|
339
|
+
positions,
|
|
340
|
+
indices,
|
|
341
|
+
config,
|
|
342
|
+
...speeds && { speeds }
|
|
343
|
+
},
|
|
344
|
+
tiles: {
|
|
345
|
+
size: config.tileSize * cellSize,
|
|
346
|
+
originX: minOf(positions, indices, 0),
|
|
347
|
+
originZ: minOf(positions, indices, 2)
|
|
348
|
+
}
|
|
349
|
+
};
|
|
350
|
+
};
|
|
351
|
+
const first = cut();
|
|
352
|
+
const data = await navigationData(first.build, options.builds);
|
|
353
|
+
const process = speedAt ? groundMeshProcess(speedAt) : createDefaultTileCacheMeshProcess();
|
|
354
|
+
const { navMesh, tileCache, allocator, compressor } = importTileCache(data, process);
|
|
355
|
+
const query = new NavMeshQuery(navMesh, { maxNodes });
|
|
356
|
+
query.defaultQueryHalfExtents = {
|
|
357
|
+
x: 2,
|
|
358
|
+
y: 6,
|
|
359
|
+
z: 2
|
|
360
|
+
};
|
|
361
|
+
if (speedAt) setAreaCosts(query.defaultFilter);
|
|
362
|
+
const crowd = crowdOf(navMesh, maxAgents, agentRadius, avoidance, !!speedAt);
|
|
363
|
+
const navigation = new RecastNavigation(terrain, navMesh, tileCache, crowd, query, agentRadius, maxAgents, maxObstacles, maxNodes, [
|
|
364
|
+
process,
|
|
365
|
+
allocator,
|
|
366
|
+
compressor
|
|
367
|
+
], avoidance, separation, walls, first.tiles, water ? (x, z) => terrain.waterHeightAt(x, z) : void 0, speedAt && {
|
|
368
|
+
speedAt,
|
|
369
|
+
config
|
|
370
|
+
}, cut);
|
|
371
|
+
if (first.build.indices.length) navigation.grid = tileGridOf(first.build);
|
|
372
|
+
return navigation;
|
|
373
|
+
}
|
|
374
|
+
/** One more each time walkable space changes: what the ground's changes asked of it done first (`settleGround`) */
|
|
375
|
+
get version() {
|
|
376
|
+
if (this.asked) this.settleGround();
|
|
377
|
+
return this.changes;
|
|
378
|
+
}
|
|
379
|
+
/**
|
|
380
|
+
* The ground it is a navigation of was reshaped (`World.reshapeGround`): cut again from the ground as it is now, on
|
|
381
|
+
* this thread, as it was cut first (its options, its slow ground); what is in the way put down again where it was, in
|
|
382
|
+
* the order it was, and every agent moved over as it stood, as a crowd that grows is. Every machine cuts it the same.
|
|
383
|
+
*
|
|
384
|
+
* Told the part that changed (`area`, in cells), only the tiles it reaches are cut again (`reshapeTiles`), where the
|
|
385
|
+
* ground is still cut on the same grid and that is under half of the tiles: the rest of the navmesh, what is in the
|
|
386
|
+
* way and every agent stay as they are, and an agent whose way went over a tile cut again finds it again, as when a
|
|
387
|
+
* building goes up on it.
|
|
388
|
+
*
|
|
389
|
+
* Not at once: at the first thing asked of it after, or as the tick ends (`settleGround`), with what the other
|
|
390
|
+
* changes of the ground asked before then (a slowing layer painted on the same part, `groundChanged`), each tile once.
|
|
391
|
+
* Nothing asked of it sees the ground as it was. True where it has a ground to cut again; one that cannot be cut as it
|
|
392
|
+
* is now (no water left) is left as it was when the time comes
|
|
393
|
+
*/
|
|
394
|
+
reshape(area) {
|
|
395
|
+
if (!this.cut) return false;
|
|
396
|
+
const asked = this.ask();
|
|
397
|
+
const grid = this.grid;
|
|
398
|
+
if (!area || !grid || asked.whole) {
|
|
399
|
+
asked.whole = true;
|
|
400
|
+
return true;
|
|
401
|
+
}
|
|
402
|
+
const reach = 2 + grid.border;
|
|
403
|
+
const column = (x, origin, count) => Math.min(count - 1, Math.max(0, Math.floor((x - origin) / grid.tileSize)));
|
|
404
|
+
const tx0 = column(area.x - reach, grid.bbMin[0], grid.tileWidth);
|
|
405
|
+
const tx1 = column(area.x + area.width + reach, grid.bbMin[0], grid.tileWidth);
|
|
406
|
+
const ty0 = column(area.z - reach, grid.bbMin[2], grid.tileHeight);
|
|
407
|
+
const ty1 = column(area.z + area.depth + reach, grid.bbMin[2], grid.tileHeight);
|
|
408
|
+
if ((tx1 - tx0 + 1) * (ty1 - ty0 + 1) > grid.tileWidth * grid.tileHeight * MOST_TILES) asked.whole = true;
|
|
409
|
+
else for (let tx = tx0; tx <= tx1; tx++) for (let ty = ty0; ty <= ty1; ty++) asked.reshaped.add(tileKey(tx, ty));
|
|
410
|
+
return true;
|
|
411
|
+
}
|
|
412
|
+
/** What the ground's changes ask of it, one more ask */
|
|
413
|
+
ask() {
|
|
414
|
+
const asked = this.asked ??= {
|
|
415
|
+
asks: 0,
|
|
416
|
+
whole: false,
|
|
417
|
+
reshaped: /* @__PURE__ */ new Set(),
|
|
418
|
+
painted: /* @__PURE__ */ new Set()
|
|
419
|
+
};
|
|
420
|
+
asked.asks++;
|
|
421
|
+
return asked;
|
|
422
|
+
}
|
|
423
|
+
/**
|
|
424
|
+
* Does what the ground's changes asked of it and it has not done yet (`reshape`, `groundChanged`), all together: a
|
|
425
|
+
* tile reached by several once, from the ground as it is now. Each ask was weighed as it came (cut whole, or its
|
|
426
|
+
* tiles), so that what comes out is what doing them one by one makes, tile for tile: where a part of the ground was
|
|
427
|
+
* reshaped, the tiles it reaches cut again of the whole ground as it is now, with those a layer was painted on; a
|
|
428
|
+
* layer painted alone, of the ground about its tiles (`groundPart`). The version goes up once for each ask, as it
|
|
429
|
+
* would have. Asked before anything else is asked of it, and by the world as each tick ends
|
|
430
|
+
*/
|
|
431
|
+
settleGround() {
|
|
432
|
+
const asked = this.asked;
|
|
433
|
+
if (!asked) return;
|
|
434
|
+
this.asked = void 0;
|
|
435
|
+
const grid = this.grid;
|
|
436
|
+
if (!asked.whole && grid) {
|
|
437
|
+
if (asked.reshaped.size) {
|
|
438
|
+
const { build } = this.cut();
|
|
439
|
+
if (this.reshapeTiles(build, [...asked.reshaped, ...asked.painted])) {
|
|
440
|
+
this.changes += asked.asks;
|
|
441
|
+
return;
|
|
442
|
+
}
|
|
443
|
+
} else {
|
|
444
|
+
const keys = [...asked.painted].sort((a, b) => a - b);
|
|
445
|
+
const { build, speedOf } = groundPart(this.terrain, this.ground.config, this.ground.speedAt, keys, grid);
|
|
446
|
+
if (this.retile(build, keys, grid.cut, speedOf)) {
|
|
447
|
+
this.changes += asked.asks;
|
|
448
|
+
return;
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
if (this.cutWhole()) this.changes += asked.asks;
|
|
453
|
+
}
|
|
454
|
+
/** Cut again whole, of the ground as it is now, what is in the way and every agent put back as they were: false where it cannot be */
|
|
455
|
+
cutWhole() {
|
|
456
|
+
if (!this.cut) return false;
|
|
457
|
+
this.drain();
|
|
458
|
+
const { build, tiles } = this.cut();
|
|
459
|
+
let made;
|
|
460
|
+
try {
|
|
461
|
+
made = importTileCache(buildNavigationNow(build), this.owned[0]);
|
|
462
|
+
} catch {
|
|
463
|
+
return false;
|
|
464
|
+
}
|
|
465
|
+
const boxes = [...this.obstacles].flatMap(([key, obstacle]) => obstacle.type === "box" ? [[key, {
|
|
466
|
+
x: obstacle.position.x,
|
|
467
|
+
z: obstacle.position.z,
|
|
468
|
+
hw: obstacle.halfExtents.x - this.agentRadius,
|
|
469
|
+
hd: obstacle.halfExtents.z - this.agentRadius
|
|
470
|
+
}]] : []);
|
|
471
|
+
const agents = [...this.agents.keys()].map((id) => [id, this.saveAgent(id)]);
|
|
472
|
+
this.dropOverridden();
|
|
473
|
+
this.grid = build.indices.length ? tileGridOf(build) : void 0;
|
|
474
|
+
const old = [
|
|
475
|
+
this.crowd,
|
|
476
|
+
this.query,
|
|
477
|
+
this.tileCache,
|
|
478
|
+
this.navMesh
|
|
479
|
+
];
|
|
480
|
+
this.navMesh = made.navMesh;
|
|
481
|
+
this.tileCache = made.tileCache;
|
|
482
|
+
this.owned = [
|
|
483
|
+
this.owned[0],
|
|
484
|
+
made.allocator,
|
|
485
|
+
made.compressor
|
|
486
|
+
];
|
|
487
|
+
this.tiles = tiles;
|
|
488
|
+
this.query = new NavMeshQuery(made.navMesh, { maxNodes: this.maxNodes });
|
|
489
|
+
this.query.defaultQueryHalfExtents = {
|
|
490
|
+
x: 2,
|
|
491
|
+
y: 6,
|
|
492
|
+
z: 2
|
|
493
|
+
};
|
|
494
|
+
if (this.ground) setAreaCosts(this.query.defaultFilter);
|
|
495
|
+
this.crowd = crowdOf(made.navMesh, this.maxAgents, this.agentRadius, this.avoidance, !!this.ground);
|
|
496
|
+
this.obstacles.clear();
|
|
497
|
+
this.agents.clear();
|
|
498
|
+
this.phasers?.destroy();
|
|
499
|
+
this.phasers = void 0;
|
|
500
|
+
for (const each of old) each.destroy();
|
|
501
|
+
this.holding = false;
|
|
502
|
+
this.held = 0;
|
|
503
|
+
this.heldColumns.clear();
|
|
504
|
+
this.obstaclesDirty = false;
|
|
505
|
+
this.holdObstacles(true);
|
|
506
|
+
for (const [key, rect] of boxes) this.addObstacle(key, rect);
|
|
507
|
+
this.holdObstacles(false);
|
|
508
|
+
for (const [id, save] of agents) this.restoreAgent(id, save);
|
|
509
|
+
this.remakeMirrors();
|
|
510
|
+
return true;
|
|
511
|
+
}
|
|
512
|
+
/**
|
|
513
|
+
* A slowing layer of cells changed on these cells (`World.setCells`): the tiles they are in are cut again alone from
|
|
514
|
+
* the ground as it is now (`retile`), its triangles marked with their cells' speeds as a whole
|
|
515
|
+
* cut marks them, so that the polygons part where the speed does now and the navmesh is the one a world made or
|
|
516
|
+
* loaded now cuts whole, tile for tile and area for area: a game saved after it plays out the same loaded. Only the
|
|
517
|
+
* ground about those tiles is read (`groundPart`). Where the change may have made cells walkable or not
|
|
518
|
+
* (`walkability`, a thicket), the tiles whose border reaches them too: the ground kept from them by the agents' radius
|
|
519
|
+
* reaches over the tile's edge. Never cut whole, however many tiles: cutting them alone is quicker, even all of them
|
|
520
|
+
* (half the time of a whole cut on a 128 x 128 map, which also puts every obstacle and agent back). Not at once: with
|
|
521
|
+
* what the other changes of the ground asked, before the next thing asked of it or as the tick ends (`settleGround`)
|
|
522
|
+
*/
|
|
523
|
+
groundChanged(cells, walkability = false) {
|
|
524
|
+
if (!this.ground || !cells.length) return;
|
|
525
|
+
if (!this.grid && this.asked) this.settleGround();
|
|
526
|
+
const grid = this.grid;
|
|
527
|
+
if (!grid) return;
|
|
528
|
+
const { width } = this.terrain;
|
|
529
|
+
const column = (x, origin, count) => Math.min(count - 1, Math.max(0, Math.floor((x - origin) / grid.tileSize)));
|
|
530
|
+
const reach = walkability ? grid.border : 0;
|
|
531
|
+
const tiles = /* @__PURE__ */ new Set();
|
|
532
|
+
for (const cell of cells) {
|
|
533
|
+
const x = cell % width;
|
|
534
|
+
const z = (cell - x) / width;
|
|
535
|
+
if (!reach) {
|
|
536
|
+
tiles.add(tileKey(column(x + .5, grid.bbMin[0], grid.tileWidth), column(z + .5, grid.bbMin[2], grid.tileHeight)));
|
|
537
|
+
continue;
|
|
538
|
+
}
|
|
539
|
+
const tx1 = column(x + 1 + reach, grid.bbMin[0], grid.tileWidth);
|
|
540
|
+
const ty1 = column(z + 1 + reach, grid.bbMin[2], grid.tileHeight);
|
|
541
|
+
for (let tx = column(x - reach, grid.bbMin[0], grid.tileWidth); tx <= tx1; tx++) for (let ty = column(z - reach, grid.bbMin[2], grid.tileHeight); ty <= ty1; ty++) tiles.add(tileKey(tx, ty));
|
|
542
|
+
}
|
|
543
|
+
const asked = this.ask();
|
|
544
|
+
if (asked.whole) return;
|
|
545
|
+
for (const key of tiles) asked.painted.add(key);
|
|
546
|
+
}
|
|
547
|
+
/** The navmesh's tiles of a column of the grid made again: from its layers made alone where it is one of them */
|
|
548
|
+
buildTilesAt(key) {
|
|
549
|
+
const layers = this.overridden?.get(key);
|
|
550
|
+
if (layers) this.buildColumn(key, layers);
|
|
551
|
+
else this.tileCache.buildNavMeshTilesAt(Math.floor(key / 65536), key % 65536, this.navMesh);
|
|
552
|
+
}
|
|
553
|
+
/** Takes every layer of a column out of the navmesh */
|
|
554
|
+
removeTilesAt(tx, ty) {
|
|
555
|
+
for (let layer = 0; layer < 32; layer++) {
|
|
556
|
+
const ref = this.navMesh.getTileRefAt(tx, ty, layer);
|
|
557
|
+
if (ref) this.navMesh.removeTile(ref);
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
/**
|
|
561
|
+
* Cuts again only these tiles (their keys: those a part of the ground reshaped reaches, `reshape`, and those a slowing
|
|
562
|
+
* layer was painted on, `groundChanged`) of the whole ground as it is now (`retile`). False, with nothing changed,
|
|
563
|
+
* where it cannot be (the ground cut on another grid now): it is cut whole
|
|
564
|
+
*/
|
|
565
|
+
reshapeTiles(build, tiles) {
|
|
566
|
+
const grid = this.grid;
|
|
567
|
+
if (!grid || !build.indices.length) return false;
|
|
568
|
+
const now = tileGridOf(build);
|
|
569
|
+
const same = (a, b) => a.every((value, i) => value === b[i]);
|
|
570
|
+
if (now.tileWidth !== grid.tileWidth || now.tileHeight !== grid.tileHeight || !same(now.bbMin, grid.bbMin) || !same(now.bbMax, grid.bbMax)) return false;
|
|
571
|
+
const keys = [...new Set(tiles)].sort((a, b) => a - b);
|
|
572
|
+
return this.retile(build, keys, now.cut);
|
|
573
|
+
}
|
|
574
|
+
/**
|
|
575
|
+
* Cuts these columns of the grid again alone (their keys, in order), each from the build as a whole cut of it would
|
|
576
|
+
* make it (`groundTileLayers`; `speedOf` where the build is a part of the ground), and keeps their layers apart from
|
|
577
|
+
* the whole's tile cache (`overridden`, which Recast cannot take a tile out of): the navmesh's tiles there made again
|
|
578
|
+
* from them with the obstacles on them, in order (`buildColumn`). Only what these columns need is done, however many
|
|
579
|
+
* were made alone before. False, with nothing changed, where they could not be made: it is cut whole
|
|
580
|
+
*/
|
|
581
|
+
retile(build, keys, cut, speedOf) {
|
|
582
|
+
const made = groundTileLayers(build, keys, cut, speedOf);
|
|
583
|
+
if (!made) return false;
|
|
584
|
+
this.drain();
|
|
585
|
+
for (let i = 0; this.obstaclesDirty; i++) {
|
|
586
|
+
if (i > 1e5) throw new Error("Navigation: the obstacles never settled");
|
|
587
|
+
this.obstaclesDirty = !this.updateTiles();
|
|
588
|
+
}
|
|
589
|
+
if (!this.overridden) {
|
|
590
|
+
this.overridden = /* @__PURE__ */ new Map();
|
|
591
|
+
this.byColumn = /* @__PURE__ */ new Map();
|
|
592
|
+
for (const [key, obstacle] of this.obstacles) if (obstacle.type === "box") this.indexObstacle(key, obstacle, true);
|
|
593
|
+
}
|
|
594
|
+
for (const key of keys) {
|
|
595
|
+
this.overridden.set(key, made.get(key));
|
|
596
|
+
this.buildColumn(key, made.get(key));
|
|
597
|
+
}
|
|
598
|
+
return true;
|
|
599
|
+
}
|
|
600
|
+
/**
|
|
601
|
+
* The navmesh's tiles of a column made alone (`retile`) made again from its layers, as the whole's tile cache makes a
|
|
602
|
+
* tile: through a tile cache of that column alone, in the whole's allocator and compressor, with every obstacle about
|
|
603
|
+
* it put down on it (Detour carves an obstacle into the tiles it touches as it is put down, so the layers go in
|
|
604
|
+
* first), a batch at a time as Detour queues them. Every layer of the column taken out of the navmesh first: the
|
|
605
|
+
* ground as it is now may have fewer than it had. Every layer is made again, each once: those an obstacle touches by
|
|
606
|
+
* Detour as it puts it down, the rest after (an obstacle `columnsOf` puts about a column may touch none of it)
|
|
607
|
+
*/
|
|
608
|
+
buildColumn(key, layers) {
|
|
609
|
+
const tx = Math.floor(key / 65536);
|
|
610
|
+
const ty = key % 65536;
|
|
611
|
+
this.removeTilesAt(tx, ty);
|
|
612
|
+
if (!layers.length) return;
|
|
613
|
+
const near = [...this.byColumn?.get(key) ?? []];
|
|
614
|
+
const tileCache = columnTileCache(this.grid.cut, this.owned[0], {
|
|
615
|
+
tiles: layers.length,
|
|
616
|
+
obstacles: Math.max(1, near.length)
|
|
617
|
+
}, this.owned[1], this.owned[2]);
|
|
618
|
+
if (!tileCache) throw new Error(`Navigation: a tile cache for the tiles at ${tx}, ${ty} could not be made`);
|
|
619
|
+
const copies = [];
|
|
620
|
+
try {
|
|
621
|
+
for (const bytes of layers) {
|
|
622
|
+
const data = addTileLayer(tileCache, bytes);
|
|
623
|
+
if (!data) throw new Error(`Navigation: the tiles at ${tx}, ${ty} could not be made again`);
|
|
624
|
+
copies.push(data);
|
|
625
|
+
}
|
|
626
|
+
if (!near.length) {
|
|
627
|
+
tileCache.buildNavMeshTilesAt(tx, ty, this.navMesh);
|
|
628
|
+
return;
|
|
629
|
+
}
|
|
630
|
+
const settle = () => {
|
|
631
|
+
for (let i = 0; !tileCache.update(this.navMesh).upToDate; i++) if (i > 1e5) throw new Error("Navigation: the obstacles never settled");
|
|
632
|
+
};
|
|
633
|
+
let queued = 0;
|
|
634
|
+
for (const each of near) {
|
|
635
|
+
const obstacle = this.obstacles.get(each);
|
|
636
|
+
if (queued === MAX_REQUESTS) {
|
|
637
|
+
settle();
|
|
638
|
+
queued = 0;
|
|
639
|
+
}
|
|
640
|
+
tileCache.addBoxObstacle(obstacle.position, obstacle.halfExtents, obstacle.angle);
|
|
641
|
+
queued++;
|
|
642
|
+
}
|
|
643
|
+
settle();
|
|
644
|
+
if (layers.some((bytes) => !this.navMesh.getTileRefAt(tx, ty, layerOf(bytes)))) tileCache.buildNavMeshTilesAt(tx, ty, this.navMesh);
|
|
645
|
+
} finally {
|
|
646
|
+
tileCache.destroy();
|
|
647
|
+
for (const each of copies) each.destroy();
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
/** An obstacle put in the columns it is about (`byColumn`), or taken out of them */
|
|
651
|
+
indexObstacle(key, obstacle, add) {
|
|
652
|
+
const byColumn = this.byColumn;
|
|
653
|
+
if (!byColumn || obstacle.type !== "box") return;
|
|
654
|
+
const { position, halfExtents } = obstacle;
|
|
655
|
+
for (const column of this.columnsOf(position.x, position.z, halfExtents.x, halfExtents.z)) {
|
|
656
|
+
let keys = byColumn.get(column);
|
|
657
|
+
if (add) {
|
|
658
|
+
if (!keys) byColumn.set(column, keys = /* @__PURE__ */ new Set());
|
|
659
|
+
keys.add(key);
|
|
660
|
+
} else {
|
|
661
|
+
keys?.delete(key);
|
|
662
|
+
if (keys?.size === 0) byColumn.delete(column);
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
/** The tiles made alone let go of: the whole's tile cache is the navmesh's again */
|
|
667
|
+
dropOverridden() {
|
|
668
|
+
this.overridden = void 0;
|
|
669
|
+
this.byColumn = void 0;
|
|
670
|
+
this.requested.clear();
|
|
671
|
+
}
|
|
672
|
+
/**
|
|
673
|
+
* A step of the whole's tile cache's work on what was put down or taken up. Once it is done, the columns made alone
|
|
674
|
+
* that it made again from its own layers, or that an obstacle came to or went from (`requested`), are made again from
|
|
675
|
+
* theirs. Whether the whole's is done
|
|
676
|
+
*/
|
|
677
|
+
updateTiles() {
|
|
678
|
+
const upToDate = this.tileCache.update(this.navMesh).upToDate;
|
|
679
|
+
const overridden = this.overridden;
|
|
680
|
+
if (!overridden) return upToDate;
|
|
681
|
+
if (upToDate && this.requested.size) {
|
|
682
|
+
const columns = [...this.requested].filter((key) => overridden.has(key)).sort((a, b) => a - b);
|
|
683
|
+
this.requested.clear();
|
|
684
|
+
for (const key of columns) this.buildTilesAt(key);
|
|
685
|
+
}
|
|
686
|
+
return upToDate;
|
|
687
|
+
}
|
|
688
|
+
/** The limits it was made with, from the map's size or the options: obstacles, and the steps of a path search */
|
|
689
|
+
get limits() {
|
|
690
|
+
return {
|
|
691
|
+
maxObstacles: this.maxObstacles,
|
|
692
|
+
maxNodes: this.maxNodes
|
|
693
|
+
};
|
|
694
|
+
}
|
|
695
|
+
/** How many agents the crowd has room for before it has to make more */
|
|
696
|
+
get capacity() {
|
|
697
|
+
return this.maxAgents;
|
|
698
|
+
}
|
|
699
|
+
/**
|
|
700
|
+
* Makes room for twice as many agents. A crowd (Detour's) is made for a number of agents and cannot grow, so a new
|
|
701
|
+
* one is made and every agent moved over as it is: where it is, how fast it goes, where to
|
|
702
|
+
*/
|
|
703
|
+
grow() {
|
|
704
|
+
const saves = [...this.agents].map(([id, entry]) => [id, entry.phasing ? entry : this.saveAgent(id)]);
|
|
705
|
+
const old = this.crowd;
|
|
706
|
+
this.maxAgents *= 2;
|
|
707
|
+
this.crowd = crowdOf(this.navMesh, this.maxAgents, this.agentRadius, this.avoidance, !!this.ground);
|
|
708
|
+
this.agents.clear();
|
|
709
|
+
for (const [id, kept] of saves) if ("agent" in kept) this.agents.set(id, kept);
|
|
710
|
+
else this.restoreAgent(id, kept);
|
|
711
|
+
this.remakeMirrors();
|
|
712
|
+
old.destroy();
|
|
713
|
+
}
|
|
714
|
+
/** Makes room for twice as many agents that phase, as `grow` does for the others: their crowd made anew */
|
|
715
|
+
growPhasers() {
|
|
716
|
+
const saves = [...this.agents].map(([id, entry]) => [id, entry.phasing ? this.saveAgent(id) : entry]);
|
|
717
|
+
const old = this.phasers;
|
|
718
|
+
this.phasersRoom *= 2;
|
|
719
|
+
this.phasers = crowdOf(this.navMesh, this.phasersRoom, this.agentRadius, this.avoidance, !!this.ground);
|
|
720
|
+
this.agents.clear();
|
|
721
|
+
for (const [id, kept] of saves) if ("agent" in kept) this.agents.set(id, kept);
|
|
722
|
+
else this.restoreAgent(id, kept);
|
|
723
|
+
old.destroy();
|
|
724
|
+
}
|
|
725
|
+
/** The crowd an agent walks on: the one of those that phase, or everyone's */
|
|
726
|
+
crowdFor(entry) {
|
|
727
|
+
return entry.phasing ? this.phasers : this.crowd;
|
|
728
|
+
}
|
|
729
|
+
toVec3(p, into = this.scratch) {
|
|
730
|
+
into.x = p.x;
|
|
731
|
+
into.y = this.heightAt(p.x, p.z);
|
|
732
|
+
into.z = p.z;
|
|
733
|
+
return into;
|
|
734
|
+
}
|
|
735
|
+
addAgent(id, position, params) {
|
|
736
|
+
if (this.asked) this.settleGround();
|
|
737
|
+
this.place(id, position, params, false);
|
|
738
|
+
}
|
|
739
|
+
/** An agent put on the crowd, or on the crowd of those that phase (`setPhasing`) */
|
|
740
|
+
place(id, position, params, phasing) {
|
|
741
|
+
if (this.agents.has(id)) this.removeAgent(id);
|
|
742
|
+
const start = this.closestPoint(position, 8) ?? position;
|
|
743
|
+
const agentParams = {
|
|
744
|
+
radius: params.radius,
|
|
745
|
+
height: 2,
|
|
746
|
+
maxSpeed: params.speed,
|
|
747
|
+
maxAcceleration: params.speed * 10,
|
|
748
|
+
collisionQueryRange: params.radius * 8,
|
|
749
|
+
pathOptimizationRange: params.radius * 30,
|
|
750
|
+
separationWeight: this.separation,
|
|
751
|
+
updateFlags: phasing ? GHOST_FLAGS : RESTING_FLAGS,
|
|
752
|
+
obstacleAvoidanceType: AVOIDANCE_SLOT
|
|
753
|
+
};
|
|
754
|
+
if (phasing) agentParams.collisionQueryRange = .01;
|
|
755
|
+
const agent = phasing ? this.seatPhasing(start, agentParams) : this.seat(start, agentParams);
|
|
756
|
+
this.agents.set(id, {
|
|
757
|
+
agent,
|
|
758
|
+
radius: params.radius,
|
|
759
|
+
anchored: false,
|
|
760
|
+
anchorX: start.x,
|
|
761
|
+
anchorZ: start.z,
|
|
762
|
+
ghost: false,
|
|
763
|
+
...phasing && { phasing: true },
|
|
764
|
+
target: null,
|
|
765
|
+
flags: phasing ? GHOST_FLAGS : RESTING_FLAGS
|
|
766
|
+
});
|
|
767
|
+
}
|
|
768
|
+
/** An agent put on the crowd of those that phase: made as the first comes, and made bigger as it fills, as `seat` does */
|
|
769
|
+
seatPhasing(at, params) {
|
|
770
|
+
if (!this.phasers) {
|
|
771
|
+
this.phasersRoom = Math.min(this.firstMaxAgents, 64);
|
|
772
|
+
this.phasers = crowdOf(this.navMesh, this.phasersRoom, this.agentRadius, this.avoidance, !!this.ground);
|
|
773
|
+
}
|
|
774
|
+
const agent = this.phasers.addAgent(this.toVec3(at), params);
|
|
775
|
+
if (agent.agentIndex >= 0) return agent;
|
|
776
|
+
this.growPhasers();
|
|
777
|
+
const again = this.phasers.addAgent(this.toVec3(at), params);
|
|
778
|
+
if (again.agentIndex < 0) throw new Error(`Navigation: the crowd of those that phase has room for ${this.phasersRoom} agents and takes no more`);
|
|
779
|
+
return again;
|
|
780
|
+
}
|
|
781
|
+
/**
|
|
782
|
+
* An agent walks through every other and every other through it (`BuffDef.phasing`), or no longer does: moved over to
|
|
783
|
+
* the crowd of those that phase, or back, as it stands (where, how fast, where to)
|
|
784
|
+
*/
|
|
785
|
+
setPhasing(id, phasing) {
|
|
786
|
+
if (this.asked) this.settleGround();
|
|
787
|
+
const entry = this.agents.get(id);
|
|
788
|
+
if (!entry || !!entry.phasing === phasing) return;
|
|
789
|
+
const save = this.saveAgent(id);
|
|
790
|
+
this.restoreAgent(id, {
|
|
791
|
+
...save,
|
|
792
|
+
phasing: phasing || void 0
|
|
793
|
+
});
|
|
794
|
+
}
|
|
795
|
+
/** An agent put on the crowd. A full crowd says so with an index of -1, and an agent like that never moves: room is made, and it goes in again */
|
|
796
|
+
seat(at, params) {
|
|
797
|
+
const agent = this.crowd.addAgent(this.toVec3(at), params);
|
|
798
|
+
if (agent.agentIndex >= 0) return agent;
|
|
799
|
+
this.grow();
|
|
800
|
+
const again = this.crowd.addAgent(this.toVec3(at), params);
|
|
801
|
+
if (again.agentIndex < 0) throw new Error(`Navigation: the crowd has room for ${this.maxAgents} agents and takes no more`);
|
|
802
|
+
return again;
|
|
803
|
+
}
|
|
804
|
+
removeAgent(id) {
|
|
805
|
+
if (this.asked) this.settleGround();
|
|
806
|
+
const entry = this.agents.get(id);
|
|
807
|
+
if (!entry) return;
|
|
808
|
+
this.crowdFor(entry).removeAgent(entry.agent);
|
|
809
|
+
this.agents.delete(id);
|
|
810
|
+
}
|
|
811
|
+
readMotion(id, out) {
|
|
812
|
+
if (this.asked) this.settleGround();
|
|
813
|
+
const entry = this.agents.get(id);
|
|
814
|
+
if (!entry) return false;
|
|
815
|
+
const { raw } = entry.agent;
|
|
816
|
+
out.x = raw.get_npos(0);
|
|
817
|
+
out.y = raw.get_npos(1);
|
|
818
|
+
out.z = raw.get_npos(2);
|
|
819
|
+
out.vx = raw.get_vel(0);
|
|
820
|
+
out.vz = raw.get_vel(2);
|
|
821
|
+
return true;
|
|
822
|
+
}
|
|
823
|
+
addMirror(id, motion, radius, ghost) {
|
|
824
|
+
if (this.asked) this.settleGround();
|
|
825
|
+
this.removeMirror(id);
|
|
826
|
+
const mirror = this.mirrorAt({
|
|
827
|
+
x: motion.x,
|
|
828
|
+
z: motion.z
|
|
829
|
+
}, radius, ghost);
|
|
830
|
+
this.mirrors.set(id, mirror);
|
|
831
|
+
this.moveMirrorTo(mirror, motion);
|
|
832
|
+
}
|
|
833
|
+
/** Asleep from the first (Detour's `INVALID`, as an anchored agent is): of the crowd's step it is only ever a neighbour */
|
|
834
|
+
mirrorAt(at, radius, ghost) {
|
|
835
|
+
const agent = this.seat(at, {
|
|
836
|
+
radius,
|
|
837
|
+
height: 2,
|
|
838
|
+
maxSpeed: 0,
|
|
839
|
+
maxAcceleration: 0,
|
|
840
|
+
collisionQueryRange: .01,
|
|
841
|
+
pathOptimizationRange: .01,
|
|
842
|
+
separationWeight: 0,
|
|
843
|
+
updateFlags: 0,
|
|
844
|
+
obstacleAvoidanceType: AVOIDANCE_SLOT
|
|
845
|
+
});
|
|
846
|
+
agent.raw.state = INVALID;
|
|
847
|
+
return {
|
|
848
|
+
agent,
|
|
849
|
+
radius,
|
|
850
|
+
anchored: true,
|
|
851
|
+
anchorX: NaN,
|
|
852
|
+
anchorZ: NaN,
|
|
853
|
+
ghost,
|
|
854
|
+
target: null,
|
|
855
|
+
flags: 0,
|
|
856
|
+
y: NaN,
|
|
857
|
+
vx: NaN,
|
|
858
|
+
vz: NaN
|
|
859
|
+
};
|
|
860
|
+
}
|
|
861
|
+
moveMirror(id, motion) {
|
|
862
|
+
if (this.asked) this.settleGround();
|
|
863
|
+
const mirror = this.mirrors.get(id);
|
|
864
|
+
if (mirror) this.moveMirrorTo(mirror, motion);
|
|
865
|
+
}
|
|
866
|
+
/** Written only where it changed, each number a call into WebAssembly: one standing still costs nothing */
|
|
867
|
+
moveMirrorTo(mirror, { x, y, z, vx, vz }) {
|
|
868
|
+
const { raw } = mirror.agent;
|
|
869
|
+
if (x !== mirror.anchorX || y !== mirror.y || z !== mirror.anchorZ) {
|
|
870
|
+
mirror.anchorX = x;
|
|
871
|
+
mirror.y = y;
|
|
872
|
+
mirror.anchorZ = z;
|
|
873
|
+
if (!mirror.phasing) {
|
|
874
|
+
raw.set_npos(0, x);
|
|
875
|
+
raw.set_npos(1, y);
|
|
876
|
+
raw.set_npos(2, z);
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
if (vx !== mirror.vx || vz !== mirror.vz) {
|
|
880
|
+
mirror.vx = vx;
|
|
881
|
+
mirror.vz = vz;
|
|
882
|
+
raw.set_vel(0, vx);
|
|
883
|
+
raw.set_vel(2, vz);
|
|
884
|
+
raw.set_dvel(0, vx);
|
|
885
|
+
raw.set_dvel(2, vz);
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
setMirrorGhost(id, ghost) {
|
|
889
|
+
if (this.asked) this.settleGround();
|
|
890
|
+
const mirror = this.mirrors.get(id);
|
|
891
|
+
if (mirror) mirror.ghost = ghost;
|
|
892
|
+
}
|
|
893
|
+
setMirrorPhasing(id, phasing) {
|
|
894
|
+
if (this.asked) this.settleGround();
|
|
895
|
+
const mirror = this.mirrors.get(id);
|
|
896
|
+
if (!mirror || !!mirror.phasing === phasing) return;
|
|
897
|
+
if (phasing) mirror.phasing = true;
|
|
898
|
+
else delete mirror.phasing;
|
|
899
|
+
const { raw } = mirror.agent;
|
|
900
|
+
raw.set_npos(0, phasing ? PARKED : mirror.anchorX);
|
|
901
|
+
raw.set_npos(1, mirror.y);
|
|
902
|
+
raw.set_npos(2, phasing ? PARKED : mirror.anchorZ);
|
|
903
|
+
}
|
|
904
|
+
removeMirror(id) {
|
|
905
|
+
if (this.asked) this.settleGround();
|
|
906
|
+
const mirror = this.mirrors.get(id);
|
|
907
|
+
if (!mirror) return;
|
|
908
|
+
this.crowd.removeAgent(mirror.agent);
|
|
909
|
+
this.mirrors.delete(id);
|
|
910
|
+
}
|
|
911
|
+
/** The mirrors put on a crowd made anew, after its agents and in the order they were, as they stood */
|
|
912
|
+
remakeMirrors() {
|
|
913
|
+
const mirrors = [...this.mirrors];
|
|
914
|
+
this.mirrors.clear();
|
|
915
|
+
for (const [id, { anchorX: x, y, anchorZ: z, vx, vz, radius, ghost, phasing }] of mirrors) {
|
|
916
|
+
const mirror = this.mirrorAt({
|
|
917
|
+
x,
|
|
918
|
+
z
|
|
919
|
+
}, radius, ghost);
|
|
920
|
+
this.mirrors.set(id, mirror);
|
|
921
|
+
this.moveMirrorTo(mirror, {
|
|
922
|
+
x,
|
|
923
|
+
y,
|
|
924
|
+
z,
|
|
925
|
+
vx,
|
|
926
|
+
vz
|
|
927
|
+
});
|
|
928
|
+
if (phasing) this.setMirrorPhasing(id, true);
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
hasAgent(id) {
|
|
932
|
+
return this.agents.has(id);
|
|
933
|
+
}
|
|
934
|
+
setDestination(id, target) {
|
|
935
|
+
if (this.asked) this.settleGround();
|
|
936
|
+
const entry = this.agents.get(id);
|
|
937
|
+
if (!entry) return false;
|
|
938
|
+
const snapped = this.closestPoint(target, 6);
|
|
939
|
+
if (!snapped) return false;
|
|
940
|
+
this.wake(entry);
|
|
941
|
+
if (!entry.target && !entry.ghost && !entry.phasing) this.setFlags(entry, DEFAULT_FLAGS);
|
|
942
|
+
entry.target = snapped;
|
|
943
|
+
return entry.agent.requestMoveTarget(this.toVec3(snapped));
|
|
944
|
+
}
|
|
945
|
+
clearDestination(id) {
|
|
946
|
+
if (this.asked) this.settleGround();
|
|
947
|
+
const entry = this.agents.get(id);
|
|
948
|
+
if (!entry) return;
|
|
949
|
+
if (entry.target && !entry.ghost && !entry.phasing) this.setFlags(entry, RESTING_FLAGS);
|
|
950
|
+
entry.target = null;
|
|
951
|
+
entry.agent.resetMoveTarget();
|
|
952
|
+
}
|
|
953
|
+
teleport(id, position) {
|
|
954
|
+
if (this.asked) this.settleGround();
|
|
955
|
+
const entry = this.agents.get(id);
|
|
956
|
+
if (!entry) return;
|
|
957
|
+
const snapped = this.closestPoint(position, 8) ?? position;
|
|
958
|
+
entry.agent.teleport(this.toVec3(snapped));
|
|
959
|
+
entry.anchorX = snapped.x;
|
|
960
|
+
entry.anchorZ = snapped.z;
|
|
961
|
+
if (entry.anchored) entry.agent.raw.state = INVALID;
|
|
962
|
+
}
|
|
963
|
+
setAnchored(id, anchored) {
|
|
964
|
+
if (this.asked) this.settleGround();
|
|
965
|
+
const entry = this.agents.get(id);
|
|
966
|
+
if (!entry || entry.anchored === anchored) return;
|
|
967
|
+
if (!anchored) {
|
|
968
|
+
this.wake(entry);
|
|
969
|
+
return;
|
|
970
|
+
}
|
|
971
|
+
const { agent } = entry;
|
|
972
|
+
const { raw } = agent;
|
|
973
|
+
entry.anchored = true;
|
|
974
|
+
entry.anchorX = raw.get_npos(0);
|
|
975
|
+
entry.anchorZ = raw.get_npos(2);
|
|
976
|
+
if (entry.target && !entry.ghost && !entry.phasing) this.setFlags(entry, RESTING_FLAGS);
|
|
977
|
+
entry.target = null;
|
|
978
|
+
agent.resetMoveTarget();
|
|
979
|
+
for (let i = 0; i < 3; i++) raw.set_vel(i, 0);
|
|
980
|
+
raw.state = INVALID;
|
|
981
|
+
}
|
|
982
|
+
/** Lets an anchored agent go: walking again, from where it stood. Detour checks the ground under it on its next step */
|
|
983
|
+
wake(entry) {
|
|
984
|
+
if (!entry.anchored) return;
|
|
985
|
+
entry.anchored = false;
|
|
986
|
+
entry.agent.raw.state = WALKING;
|
|
987
|
+
}
|
|
988
|
+
setGhost(id, ghost) {
|
|
989
|
+
if (this.asked) this.settleGround();
|
|
990
|
+
const entry = this.agents.get(id);
|
|
991
|
+
if (!entry || entry.ghost === ghost) return;
|
|
992
|
+
entry.ghost = ghost;
|
|
993
|
+
if (entry.phasing) return;
|
|
994
|
+
entry.flags = ghost ? GHOST_FLAGS : entry.target ? DEFAULT_FLAGS : RESTING_FLAGS;
|
|
995
|
+
entry.agent.updateParameters({
|
|
996
|
+
updateFlags: entry.flags,
|
|
997
|
+
collisionQueryRange: ghost ? .01 : entry.radius * 8
|
|
998
|
+
});
|
|
999
|
+
}
|
|
1000
|
+
setSpeed(id, speed) {
|
|
1001
|
+
if (this.asked) this.settleGround();
|
|
1002
|
+
this.agents.get(id)?.agent.updateParameters({
|
|
1003
|
+
maxSpeed: speed,
|
|
1004
|
+
maxAcceleration: Math.max(speed * 10, BRAKING)
|
|
1005
|
+
});
|
|
1006
|
+
}
|
|
1007
|
+
saveAgent(id) {
|
|
1008
|
+
if (this.asked) this.settleGround();
|
|
1009
|
+
const entry = this.agents.get(id);
|
|
1010
|
+
if (!entry) return void 0;
|
|
1011
|
+
const { agent, radius, target, anchored, ghost } = entry;
|
|
1012
|
+
const p = agent.position();
|
|
1013
|
+
const v = agent.velocity();
|
|
1014
|
+
return {
|
|
1015
|
+
x: p.x,
|
|
1016
|
+
z: p.z,
|
|
1017
|
+
vx: v.x,
|
|
1018
|
+
vz: v.z,
|
|
1019
|
+
radius,
|
|
1020
|
+
speed: agent.maxSpeed,
|
|
1021
|
+
acceleration: agent.maxAcceleration,
|
|
1022
|
+
target: target && {
|
|
1023
|
+
x: target.x,
|
|
1024
|
+
z: target.z
|
|
1025
|
+
},
|
|
1026
|
+
anchored,
|
|
1027
|
+
anchor: anchored ? {
|
|
1028
|
+
x: entry.anchorX,
|
|
1029
|
+
z: entry.anchorZ
|
|
1030
|
+
} : void 0,
|
|
1031
|
+
ghost,
|
|
1032
|
+
...entry.phasing && { phasing: true }
|
|
1033
|
+
};
|
|
1034
|
+
}
|
|
1035
|
+
reseat(agents) {
|
|
1036
|
+
if (this.asked) this.settleGround();
|
|
1037
|
+
const old = this.crowd;
|
|
1038
|
+
this.maxAgents = this.firstMaxAgents;
|
|
1039
|
+
this.crowd = crowdOf(this.navMesh, this.maxAgents, this.agentRadius, this.avoidance, !!this.ground);
|
|
1040
|
+
this.agents.clear();
|
|
1041
|
+
this.mirrors.clear();
|
|
1042
|
+
old.destroy();
|
|
1043
|
+
this.phasers?.destroy();
|
|
1044
|
+
this.phasers = void 0;
|
|
1045
|
+
for (const [id, save] of agents) this.restoreAgent(id, save);
|
|
1046
|
+
}
|
|
1047
|
+
restoreAgent(id, save) {
|
|
1048
|
+
if (this.asked) this.settleGround();
|
|
1049
|
+
this.place(id, {
|
|
1050
|
+
x: save.x,
|
|
1051
|
+
z: save.z
|
|
1052
|
+
}, {
|
|
1053
|
+
radius: save.radius,
|
|
1054
|
+
speed: save.speed
|
|
1055
|
+
}, !!save.phasing);
|
|
1056
|
+
const entry = this.agents.get(id);
|
|
1057
|
+
const { agent } = entry;
|
|
1058
|
+
const at = save.anchored ? save.anchor ?? save : save;
|
|
1059
|
+
agent.teleport({
|
|
1060
|
+
x: at.x,
|
|
1061
|
+
y: this.heightAt(at.x, at.z),
|
|
1062
|
+
z: at.z
|
|
1063
|
+
});
|
|
1064
|
+
entry.anchorX = at.x;
|
|
1065
|
+
entry.anchorZ = at.z;
|
|
1066
|
+
if (save.acceleration !== void 0) agent.updateParameters({ maxAcceleration: save.acceleration });
|
|
1067
|
+
this.setGhost(id, save.ghost);
|
|
1068
|
+
if (save.target) this.setDestination(id, save.target);
|
|
1069
|
+
if (save.anchored) {
|
|
1070
|
+
this.setAnchored(id, true);
|
|
1071
|
+
return;
|
|
1072
|
+
}
|
|
1073
|
+
agent.raw.set_vel(0, save.vx);
|
|
1074
|
+
agent.raw.set_vel(2, save.vz);
|
|
1075
|
+
}
|
|
1076
|
+
settle(version) {
|
|
1077
|
+
this.drain();
|
|
1078
|
+
for (let i = 0; this.obstaclesDirty; i++) {
|
|
1079
|
+
if (i > 1e5) throw new Error("Navigation: the obstacles never settled");
|
|
1080
|
+
this.obstaclesDirty = !this.updateTiles();
|
|
1081
|
+
}
|
|
1082
|
+
this.changes = version;
|
|
1083
|
+
for (let i = 0; i < 1e3 && [...this.agents.values()].some(({ agent }) => PLANNING.has(agent.raw.targetState)); i++) {
|
|
1084
|
+
this.crowd.update(0);
|
|
1085
|
+
this.phasers?.update(0);
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1088
|
+
readAgent(id, out) {
|
|
1089
|
+
if (this.asked) this.settleGround();
|
|
1090
|
+
const entry = this.agents.get(id);
|
|
1091
|
+
if (!entry) return false;
|
|
1092
|
+
if (entry.anchored) {
|
|
1093
|
+
out.x = entry.anchorX;
|
|
1094
|
+
out.z = entry.anchorZ;
|
|
1095
|
+
out.vx = 0;
|
|
1096
|
+
out.vz = 0;
|
|
1097
|
+
out.cx = out.nx = entry.anchorX;
|
|
1098
|
+
out.cz = out.nz = entry.anchorZ;
|
|
1099
|
+
return true;
|
|
1100
|
+
}
|
|
1101
|
+
const raw = entry.agent.raw;
|
|
1102
|
+
out.x = raw.get_npos(0);
|
|
1103
|
+
out.z = raw.get_npos(2);
|
|
1104
|
+
out.vx = raw.get_vel(0);
|
|
1105
|
+
out.vz = raw.get_vel(2);
|
|
1106
|
+
const corners = raw.ncorners;
|
|
1107
|
+
if (corners > 0) {
|
|
1108
|
+
out.cx = raw.get_cornerVerts(0);
|
|
1109
|
+
out.cz = raw.get_cornerVerts(2);
|
|
1110
|
+
} else {
|
|
1111
|
+
out.cx = raw.get_targetPos(0);
|
|
1112
|
+
out.cz = raw.get_targetPos(2);
|
|
1113
|
+
}
|
|
1114
|
+
if (corners > 1) {
|
|
1115
|
+
out.nx = raw.get_cornerVerts(3);
|
|
1116
|
+
out.nz = raw.get_cornerVerts(5);
|
|
1117
|
+
} else {
|
|
1118
|
+
out.nx = out.cx;
|
|
1119
|
+
out.nz = out.cz;
|
|
1120
|
+
}
|
|
1121
|
+
return true;
|
|
1122
|
+
}
|
|
1123
|
+
update(dt) {
|
|
1124
|
+
this.drain();
|
|
1125
|
+
if (this.obstaclesDirty) {
|
|
1126
|
+
for (let i = 0; i < 32; i++) if (this.updateTiles()) {
|
|
1127
|
+
this.obstaclesDirty = false;
|
|
1128
|
+
break;
|
|
1129
|
+
}
|
|
1130
|
+
this.changes++;
|
|
1131
|
+
}
|
|
1132
|
+
if (this.walls === "soft") this.steer();
|
|
1133
|
+
this.crowd.update(dt);
|
|
1134
|
+
this.phasers?.update(dt);
|
|
1135
|
+
}
|
|
1136
|
+
/** The flags an agent steers by, set on the crowd only where they change: one call into WebAssembly */
|
|
1137
|
+
setFlags(entry, flags) {
|
|
1138
|
+
if (entry.flags === flags) return;
|
|
1139
|
+
entry.flags = flags;
|
|
1140
|
+
entry.agent.raw.params.updateFlags = flags;
|
|
1141
|
+
}
|
|
1142
|
+
/**
|
|
1143
|
+
* `walls: 'soft'`: an agent walking somewhere steers among velocities (obstacle avoidance) only while another agent
|
|
1144
|
+
* (walking or standing, anchored too, not a ghost) is within its reach, its collision query range (eight of its
|
|
1145
|
+
* radii); otherwise it follows its path, pushed apart from those near it (separation) but never slowed by a wall it
|
|
1146
|
+
* touches. Read from where every agent is as the tick starts, in a grid of cells as large as the longest reach, so
|
|
1147
|
+
* that a game loaded from a save steers as the game it was saved from (Detour's own lists of neighbours are of the
|
|
1148
|
+
* tick before, and a crowd made anew has none)
|
|
1149
|
+
*/
|
|
1150
|
+
steer() {
|
|
1151
|
+
const near = this.near;
|
|
1152
|
+
let count = 0;
|
|
1153
|
+
let walking = 0;
|
|
1154
|
+
let cell = 0;
|
|
1155
|
+
for (const entry of this.agents.values()) {
|
|
1156
|
+
if (entry.ghost || entry.phasing) continue;
|
|
1157
|
+
near[count++] = entry;
|
|
1158
|
+
if (entry.target && !entry.anchored) {
|
|
1159
|
+
walking++;
|
|
1160
|
+
cell = Math.max(cell, entry.radius * 8);
|
|
1161
|
+
}
|
|
1162
|
+
}
|
|
1163
|
+
if (walking > 0) {
|
|
1164
|
+
for (const mirror of this.mirrors.values()) if (!mirror.ghost) near[count++] = mirror;
|
|
1165
|
+
}
|
|
1166
|
+
near.length = count;
|
|
1167
|
+
if (walking === 0) return;
|
|
1168
|
+
if (this.nearX.length < count) {
|
|
1169
|
+
this.nearX = new Float64Array(count * 2);
|
|
1170
|
+
this.nearZ = new Float64Array(count * 2);
|
|
1171
|
+
this.nearNext = new Int32Array(count * 2);
|
|
1172
|
+
}
|
|
1173
|
+
const xs = this.nearX;
|
|
1174
|
+
const zs = this.nearZ;
|
|
1175
|
+
const next = this.nearNext;
|
|
1176
|
+
const heads = this.nearHeads;
|
|
1177
|
+
heads.clear();
|
|
1178
|
+
for (let i = 0; i < count; i++) {
|
|
1179
|
+
const entry = near[i];
|
|
1180
|
+
if (entry.anchored) {
|
|
1181
|
+
xs[i] = entry.anchorX;
|
|
1182
|
+
zs[i] = entry.anchorZ;
|
|
1183
|
+
} else {
|
|
1184
|
+
xs[i] = entry.agent.raw.get_npos(0);
|
|
1185
|
+
zs[i] = entry.agent.raw.get_npos(2);
|
|
1186
|
+
}
|
|
1187
|
+
const key = Math.floor(xs[i] / cell) * 65536 + Math.floor(zs[i] / cell);
|
|
1188
|
+
next[i] = heads.get(key) ?? -1;
|
|
1189
|
+
heads.set(key, i);
|
|
1190
|
+
}
|
|
1191
|
+
for (let i = 0; i < count; i++) {
|
|
1192
|
+
const entry = near[i];
|
|
1193
|
+
if (!entry.target || entry.anchored) continue;
|
|
1194
|
+
const reach = entry.radius * 8;
|
|
1195
|
+
const cx = Math.floor(xs[i] / cell);
|
|
1196
|
+
const cz = Math.floor(zs[i] / cell);
|
|
1197
|
+
let steers = false;
|
|
1198
|
+
for (let dx = -1; dx <= 1 && !steers; dx++) for (let dz = -1; dz <= 1 && !steers; dz++) for (let j = heads.get((cx + dx) * 65536 + cz + dz) ?? -1; j >= 0; j = next[j]) {
|
|
1199
|
+
if (j === i) continue;
|
|
1200
|
+
const ox = xs[j] - xs[i];
|
|
1201
|
+
const oz = zs[j] - zs[i];
|
|
1202
|
+
if (ox * ox + oz * oz < reach * reach) {
|
|
1203
|
+
steers = true;
|
|
1204
|
+
break;
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
this.setFlags(entry, steers ? DEFAULT_FLAGS : RESTING_FLAGS);
|
|
1208
|
+
}
|
|
1209
|
+
}
|
|
1210
|
+
addObstacle(key, rect) {
|
|
1211
|
+
if (this.asked) this.settleGround();
|
|
1212
|
+
this.removeObstacle(key);
|
|
1213
|
+
if (this.obstacles.size >= this.maxObstacles) return false;
|
|
1214
|
+
const y = this.terrain.heightAt(rect.x, rect.z);
|
|
1215
|
+
const half = {
|
|
1216
|
+
x: rect.hw + this.agentRadius,
|
|
1217
|
+
y: 4,
|
|
1218
|
+
z: rect.hd + this.agentRadius
|
|
1219
|
+
};
|
|
1220
|
+
this.makeRoom(rect.x, rect.z, half.x, half.z);
|
|
1221
|
+
const result = this.tileCache.addBoxObstacle({
|
|
1222
|
+
x: rect.x,
|
|
1223
|
+
y,
|
|
1224
|
+
z: rect.z
|
|
1225
|
+
}, half, 0);
|
|
1226
|
+
if (!result.success) return false;
|
|
1227
|
+
this.obstacles.set(key, result.obstacle);
|
|
1228
|
+
if (this.overridden) {
|
|
1229
|
+
this.indexObstacle(key, result.obstacle, true);
|
|
1230
|
+
for (const column of this.columnsOf(rect.x, rect.z, half.x, half.z)) this.requested.add(column);
|
|
1231
|
+
}
|
|
1232
|
+
this.flushObstacles();
|
|
1233
|
+
return true;
|
|
1234
|
+
}
|
|
1235
|
+
/**
|
|
1236
|
+
* Holds obstacles back (true) or lets them go (false): while held, a request to put one down or take one up waits in
|
|
1237
|
+
* the tile cache, and they are made into tiles together when let go or at the first thing asked of the navigation
|
|
1238
|
+
* before that, each tile once however many obstacles are on it. The same tiles come of it as of making them one by
|
|
1239
|
+
* one: a wooded tile is made once, not once a tree (RV42). The version goes up for each obstacle all the same
|
|
1240
|
+
*/
|
|
1241
|
+
holdObstacles(hold) {
|
|
1242
|
+
if (this.asked) this.settleGround();
|
|
1243
|
+
if (this.holding === hold) return;
|
|
1244
|
+
this.holding = hold;
|
|
1245
|
+
if (!hold) return this.drain();
|
|
1246
|
+
if (this.obstaclesDirty) {
|
|
1247
|
+
this.held = 1;
|
|
1248
|
+
this.drain();
|
|
1249
|
+
this.obstaclesDirty = true;
|
|
1250
|
+
}
|
|
1251
|
+
}
|
|
1252
|
+
/**
|
|
1253
|
+
* Makes room for one more held request, of an obstacle at (x, z) of these half sizes: the ones held are made into
|
|
1254
|
+
* tiles first when the tile cache would take no more of them (Detour queues 64), or when their tiles together would
|
|
1255
|
+
* be more than it makes again from one batch (64, past which it leaves the rest as they were)
|
|
1256
|
+
*/
|
|
1257
|
+
makeRoom(x, z, hw, hd) {
|
|
1258
|
+
if (!this.holding) return;
|
|
1259
|
+
const columns = this.columnsOf(x, z, hw, hd);
|
|
1260
|
+
let more = 0;
|
|
1261
|
+
for (const column of columns) if (!this.heldColumns.has(column)) more++;
|
|
1262
|
+
if (this.held + 1 > MAX_REQUESTS || this.heldColumns.size + more > MAX_HELD_COLUMNS) this.drain();
|
|
1263
|
+
for (const column of columns) this.heldColumns.add(column);
|
|
1264
|
+
}
|
|
1265
|
+
/**
|
|
1266
|
+
* The columns of the tile grid an obstacle touches, or more: Detour takes a box obstacle's bounds as a square 1.41 times
|
|
1267
|
+
* its longer half side about its middle, here 1.5 times, so that rounding never leaves one out. More, then, and not
|
|
1268
|
+
* Detour's own test (which also weighs each layer's walkable cells and heights): what is done with a column here holds
|
|
1269
|
+
* for one the obstacle does not touch (`buildColumn` makes every layer of it however that falls out)
|
|
1270
|
+
*/
|
|
1271
|
+
columnsOf(x, z, hw, hd) {
|
|
1272
|
+
const { size, originX, originZ } = this.tiles;
|
|
1273
|
+
const reach = 1.5 * Math.max(hw, hd);
|
|
1274
|
+
const x0 = Math.floor((x - reach - originX) / size);
|
|
1275
|
+
const x1 = Math.floor((x + reach - originX) / size);
|
|
1276
|
+
const z0 = Math.floor((z - reach - originZ) / size);
|
|
1277
|
+
const z1 = Math.floor((z + reach - originZ) / size);
|
|
1278
|
+
const columns = [];
|
|
1279
|
+
for (let tx = x0; tx <= x1; tx++) for (let tz = z0; tz <= z1; tz++) columns.push(tx * 65536 + tz);
|
|
1280
|
+
return columns;
|
|
1281
|
+
}
|
|
1282
|
+
/** Every held request made into tiles: the tile cache up to date */
|
|
1283
|
+
drain() {
|
|
1284
|
+
if (this.asked) this.settleGround();
|
|
1285
|
+
if (!this.held) return;
|
|
1286
|
+
this.held = 0;
|
|
1287
|
+
this.heldColumns.clear();
|
|
1288
|
+
for (let i = 0; !this.updateTiles(); i++) if (i > 1e5) throw new Error("Navigation: the obstacles never settled");
|
|
1289
|
+
this.obstaclesDirty = false;
|
|
1290
|
+
}
|
|
1291
|
+
obstacleRoom() {
|
|
1292
|
+
return this.maxObstacles - this.obstacles.size;
|
|
1293
|
+
}
|
|
1294
|
+
removeObstacle(key) {
|
|
1295
|
+
if (this.asked) this.settleGround();
|
|
1296
|
+
const obstacle = this.obstacles.get(key);
|
|
1297
|
+
if (!obstacle) return;
|
|
1298
|
+
if (this.holding && obstacle.type === "box") {
|
|
1299
|
+
const { position, halfExtents } = obstacle;
|
|
1300
|
+
this.makeRoom(position.x, position.z, halfExtents.x, halfExtents.z);
|
|
1301
|
+
}
|
|
1302
|
+
this.tileCache.removeObstacle(obstacle);
|
|
1303
|
+
this.obstacles.delete(key);
|
|
1304
|
+
if (this.overridden && obstacle.type === "box") {
|
|
1305
|
+
this.indexObstacle(key, obstacle, false);
|
|
1306
|
+
const { position, halfExtents } = obstacle;
|
|
1307
|
+
for (const column of this.columnsOf(position.x, position.z, halfExtents.x, halfExtents.z)) this.requested.add(column);
|
|
1308
|
+
}
|
|
1309
|
+
this.flushObstacles();
|
|
1310
|
+
}
|
|
1311
|
+
/**
|
|
1312
|
+
* The tile cache only queues a limited number of requests, so process them as they come: but while they are held
|
|
1313
|
+
* (`holdObstacles`), when they wait to be made into tiles together
|
|
1314
|
+
*/
|
|
1315
|
+
flushObstacles() {
|
|
1316
|
+
if (this.holding) this.held++;
|
|
1317
|
+
else this.obstaclesDirty = !this.updateTiles();
|
|
1318
|
+
this.changes++;
|
|
1319
|
+
}
|
|
1320
|
+
closestPoint(point, searchRadius = 4) {
|
|
1321
|
+
this.drain();
|
|
1322
|
+
const query = this.closestQuery;
|
|
1323
|
+
query.halfExtents.x = searchRadius;
|
|
1324
|
+
query.halfExtents.z = searchRadius;
|
|
1325
|
+
const result = this.query.findClosestPoint(this.toVec3(point), query);
|
|
1326
|
+
if (!result.success || result.polyRef === 0) return null;
|
|
1327
|
+
return {
|
|
1328
|
+
x: result.point.x,
|
|
1329
|
+
z: result.point.z
|
|
1330
|
+
};
|
|
1331
|
+
}
|
|
1332
|
+
findPath(from, to) {
|
|
1333
|
+
this.drain();
|
|
1334
|
+
const result = this.query.computePath(this.toVec3(from), this.toVec3(to, this.scratchEnd));
|
|
1335
|
+
if (!result.success || result.path.length === 0) return null;
|
|
1336
|
+
return result.path.map((p) => ({
|
|
1337
|
+
x: p.x,
|
|
1338
|
+
z: p.z
|
|
1339
|
+
}));
|
|
1340
|
+
}
|
|
1341
|
+
debugGeometry() {
|
|
1342
|
+
this.drain();
|
|
1343
|
+
const drawer = new DebugDrawerUtils();
|
|
1344
|
+
const primitives = drawer.drawNavMesh(this.navMesh);
|
|
1345
|
+
const triangles = [];
|
|
1346
|
+
const lines = [];
|
|
1347
|
+
for (const primitive of primitives) {
|
|
1348
|
+
const target = primitive.type === "tris" ? triangles : primitive.type === "lines" ? lines : null;
|
|
1349
|
+
if (!target) continue;
|
|
1350
|
+
for (const v of primitive.vertices) target.push(v[0], v[1], v[2]);
|
|
1351
|
+
}
|
|
1352
|
+
drawer.dispose();
|
|
1353
|
+
return {
|
|
1354
|
+
triangles: new Float32Array(triangles),
|
|
1355
|
+
lines: new Float32Array(lines)
|
|
1356
|
+
};
|
|
1357
|
+
}
|
|
1358
|
+
dispose() {
|
|
1359
|
+
this.asked = void 0;
|
|
1360
|
+
this.dropOverridden();
|
|
1361
|
+
this.crowd.destroy();
|
|
1362
|
+
this.phasers?.destroy();
|
|
1363
|
+
this.query.destroy();
|
|
1364
|
+
this.tileCache.destroy();
|
|
1365
|
+
this.navMesh.destroy();
|
|
1366
|
+
for (const each of this.owned) {
|
|
1367
|
+
const raw = each instanceof TileCacheMeshProcess ? each.raw : each;
|
|
1368
|
+
if (raw) Raw.destroy(raw);
|
|
1369
|
+
}
|
|
1370
|
+
this.owned = [];
|
|
1371
|
+
this.agents.clear();
|
|
1372
|
+
this.mirrors.clear();
|
|
1373
|
+
this.obstacles.clear();
|
|
1374
|
+
}
|
|
1375
|
+
};
|
|
1376
|
+
//#endregion
|
|
1377
|
+
export { AVOIDANCE_LEVELS, DEFAULT_AVOIDANCE, RecastNavigation, SOFT_WALLS };
|
|
1378
|
+
|
|
1379
|
+
//# sourceMappingURL=recast.js.map
|