@v12-engine/engine 0.1.0 → 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
package/dist/manaBurn.js
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { manaChanged } from "./engineEvents.js";
|
|
2
|
+
import { scaled } from "./abilities/scaled.js";
|
|
3
|
+
import { valueOf } from "./abilities/amounts.js";
|
|
4
|
+
import { defineEffect, effectTargets } from "./abilities/effects.js";
|
|
5
|
+
//#region src/manaBurn.ts
|
|
6
|
+
/**
|
|
7
|
+
* The mana burn pack's id
|
|
8
|
+
*
|
|
9
|
+
* @beta
|
|
10
|
+
*/
|
|
11
|
+
var MANA_BURN = "core.manaBurn";
|
|
12
|
+
/**
|
|
13
|
+
* Takes up to `amount` of a unit's mana and hurts it by as much as it took (times `ratio`), from `source`: what the
|
|
14
|
+
* `manaBurn` effect does, for a game's own rules. Gives back the mana it took: none of a unit that has none, and no
|
|
15
|
+
* damage then
|
|
16
|
+
*
|
|
17
|
+
* @beta
|
|
18
|
+
*/
|
|
19
|
+
function burnMana(world, target, amount, source, options = {}) {
|
|
20
|
+
const burnt = Math.min(Math.max(amount, 0), target.mana);
|
|
21
|
+
if (burnt <= 0) return 0;
|
|
22
|
+
target.mana -= burnt;
|
|
23
|
+
world.events.emit(manaChanged, {
|
|
24
|
+
entity: target,
|
|
25
|
+
amount: -burnt,
|
|
26
|
+
ability: options.ability,
|
|
27
|
+
source
|
|
28
|
+
});
|
|
29
|
+
const damage = burnt * (options.ratio ?? 1);
|
|
30
|
+
if (damage > 0) world.damage(target, damage, source, {
|
|
31
|
+
damageType: options.damageType ?? "magic",
|
|
32
|
+
ability: options.ability
|
|
33
|
+
});
|
|
34
|
+
return burnt;
|
|
35
|
+
}
|
|
36
|
+
var manaBurnEffect = defineEffect({
|
|
37
|
+
type: "manaBurn",
|
|
38
|
+
run: (context, effect) => {
|
|
39
|
+
const { world, caster, level } = context;
|
|
40
|
+
const amount = scaled(world, caster, valueOf(context, effect.amount), effect.scaling, level);
|
|
41
|
+
for (const entity of effectTargets(context, effect, "enemies")) burnMana(world, entity, amount, caster, {
|
|
42
|
+
ratio: effect.ratio,
|
|
43
|
+
damageType: effect.damageType,
|
|
44
|
+
ability: context.ability.id
|
|
45
|
+
});
|
|
46
|
+
},
|
|
47
|
+
fields: [
|
|
48
|
+
"amount",
|
|
49
|
+
"scaling",
|
|
50
|
+
"damageType",
|
|
51
|
+
{
|
|
52
|
+
path: "ratio",
|
|
53
|
+
kind: "number",
|
|
54
|
+
min: 0,
|
|
55
|
+
hint: "Times the mana taken it hurts by: 1 when left out"
|
|
56
|
+
}
|
|
57
|
+
]
|
|
58
|
+
});
|
|
59
|
+
/**
|
|
60
|
+
* Mana burn, as in classic RTS games: the `manaBurn` effect (`EffectTypes.manaBurn`) takes `amount` of what it reaches of its
|
|
61
|
+
* mana and hurts it by as much (times `ratio`). The demon hunter's spell is an ability with it; Feedback is a passive
|
|
62
|
+
* whose `onHit` has it. `burnMana` does it in code
|
|
63
|
+
*
|
|
64
|
+
* @beta
|
|
65
|
+
*/
|
|
66
|
+
function manaBurnPack() {
|
|
67
|
+
return {
|
|
68
|
+
id: MANA_BURN,
|
|
69
|
+
effects: [manaBurnEffect]
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
//#endregion
|
|
73
|
+
export { MANA_BURN, burnMana, manaBurnPack };
|
|
74
|
+
|
|
75
|
+
//# sourceMappingURL=manaBurn.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manaBurn.js","names":[],"sources":["../src/manaBurn.ts"],"sourcesContent":["import { defineEffect, effectTargets } from './abilities/effects'\nimport { valueOf } from './abilities/amounts'\nimport { scaled } from './abilities/scaled'\nimport type { DamageType } from './defs'\nimport { manaChanged } from './engineEvents'\nimport type { Entity } from './entity'\nimport type { GamePack } from './packs/pack'\nimport type { World } from './world'\n\n/*\n * Mana burn, an opt-in pack (review RV95): the `manaBurn` effect takes a unit's mana and hurts it by as much, as the\n * demon hunter's spell does, and on every hit with `onHit` (Feedback)\n */\n\n/**\n * The mana burn pack's id\n *\n * @beta\n */\nexport const MANA_BURN = 'core.manaBurn'\n\n/**\n * How mana is burnt (`burnMana`)\n *\n * @beta\n */\nexport interface BurnOptions {\n\t/** Damage for each point of mana burnt: 1 when left out */\n\tratio?: number\n\t/** Magic when left out */\n\tdamageType?: DamageType\n\t/** The ability that burnt it, by id: for the damage and the mana told */\n\tability?: string\n}\n\n/**\n * Takes up to `amount` of a unit's mana and hurts it by as much as it took (times `ratio`), from `source`: what the\n * `manaBurn` effect does, for a game's own rules. Gives back the mana it took: none of a unit that has none, and no\n * damage then\n *\n * @beta\n */\nexport function burnMana(world: World, target: Entity, amount: number, source?: Entity, options: BurnOptions = {}): number {\n\tconst burnt = Math.min(Math.max(amount, 0), target.mana)\n\tif (burnt <= 0) return 0\n\ttarget.mana -= burnt\n\tworld.events.emit(manaChanged, { entity: target, amount: -burnt, ability: options.ability, source })\n\tconst damage = burnt * (options.ratio ?? 1)\n\tif (damage > 0) world.damage(target, damage, source, { damageType: options.damageType ?? 'magic', ability: options.ability })\n\treturn burnt\n}\n\nconst manaBurnEffect = defineEffect({ type: 'manaBurn', run: (context, effect) => {\n\t\tconst { world, caster, level } = context\n\t\tconst amount = scaled(world, caster, valueOf(context, effect.amount), effect.scaling, level)\n\t\tfor (const entity of effectTargets(context, effect, 'enemies'))\n\t\t\tburnMana(world, entity, amount, caster, { ratio: effect.ratio, damageType: effect.damageType, ability: context.ability.id })\n\t}, fields: ['amount', 'scaling', 'damageType', { path: 'ratio', kind: 'number', min: 0, hint: 'Times the mana taken it hurts by: 1 when left out' }] })\n\n/**\n * Mana burn, as in classic RTS games: the `manaBurn` effect (`EffectTypes.manaBurn`) takes `amount` of what it reaches of its\n * mana and hurts it by as much (times `ratio`). The demon hunter's spell is an ability with it; Feedback is a passive\n * whose `onHit` has it. `burnMana` does it in code\n *\n * @beta\n */\nexport function manaBurnPack(): GamePack {\n\treturn { id: MANA_BURN, effects: [manaBurnEffect] }\n}\n"],"mappings":";;;;;;;;;;AAmBA,IAAa,YAAY;;;;;;;;AAuBzB,SAAgB,SAAS,OAAc,QAAgB,QAAgB,QAAiB,UAAuB,CAAC,GAAW;CAC1H,MAAM,QAAQ,KAAK,IAAI,KAAK,IAAI,QAAQ,CAAC,GAAG,OAAO,IAAI;CACvD,IAAI,SAAS,GAAG,OAAO;CACvB,OAAO,QAAQ;CACf,MAAM,OAAO,KAAK,aAAa;EAAE,QAAQ;EAAQ,QAAQ,CAAC;EAAO,SAAS,QAAQ;EAAS;CAAO,CAAC;CACnG,MAAM,SAAS,SAAS,QAAQ,SAAS;CACzC,IAAI,SAAS,GAAG,MAAM,OAAO,QAAQ,QAAQ,QAAQ;EAAE,YAAY,QAAQ,cAAc;EAAS,SAAS,QAAQ;CAAQ,CAAC;CAC5H,OAAO;AACR;AAEA,IAAM,iBAAiB,aAAa;CAAE,MAAM;CAAY,MAAM,SAAS,WAAW;EAChF,MAAM,EAAE,OAAO,QAAQ,UAAU;EACjC,MAAM,SAAS,OAAO,OAAO,QAAQ,QAAQ,SAAS,OAAO,MAAM,GAAG,OAAO,SAAS,KAAK;EAC3F,KAAK,MAAM,UAAU,cAAc,SAAS,QAAQ,SAAS,GAC5D,SAAS,OAAO,QAAQ,QAAQ,QAAQ;GAAE,OAAO,OAAO;GAAO,YAAY,OAAO;GAAY,SAAS,QAAQ,QAAQ;EAAG,CAAC;CAC7H;CAAG,QAAQ;EAAC;EAAU;EAAW;EAAc;GAAE,MAAM;GAAS,MAAM;GAAU,KAAK;GAAG,MAAM;EAAoD;CAAC;AAAE,CAAC;;;;;;;;AASvJ,SAAgB,eAAyB;CACxC,OAAO;EAAE,IAAI;EAAW,SAAS,CAAC,cAAc;CAAE;AACnD"}
|
package/dist/map/file.d.ts
CHANGED
|
@@ -8,12 +8,19 @@ import { type CellRect, type GameMap, type MapCamera, type MapCamp, type MapDay,
|
|
|
8
8
|
* @beta
|
|
9
9
|
*/
|
|
10
10
|
export interface MapFile {
|
|
11
|
+
/** The file format's version (`MAP_FORMAT` when written), which the reader brings older files up from */
|
|
11
12
|
format: number;
|
|
13
|
+
/** The map's name (`GameMap.name`) */
|
|
12
14
|
name: string;
|
|
15
|
+
/** The map's description (`GameMap.description`) */
|
|
13
16
|
description: string;
|
|
17
|
+
/** The game the map was made for, by the id of its module (`GameMap.game`); any game when left out */
|
|
14
18
|
game?: string;
|
|
19
|
+
/** The map's width in cells */
|
|
15
20
|
width: number;
|
|
21
|
+
/** The map's depth in cells */
|
|
16
22
|
depth: number;
|
|
23
|
+
/** How much higher a level stands than the one below (`GameMap.cliffHeight`) */
|
|
17
24
|
cliffHeight: number;
|
|
18
25
|
/**
|
|
19
26
|
* The layers of the ground, a line of text for each row (since format 3: before, one line for the whole layer): two
|
|
@@ -21,9 +28,13 @@ export interface MapFile {
|
|
|
21
28
|
* corners along x for each z; the rest by cell, a row of cells for each z
|
|
22
29
|
*/
|
|
23
30
|
ground: string[];
|
|
31
|
+
/** The cliff levels, a line of text per row of cells (`GameMap.levels`) */
|
|
24
32
|
levels: string[];
|
|
33
|
+
/** The ramp flags, a line of text per row of cells (`GameMap.ramps`) */
|
|
25
34
|
ramps: string[];
|
|
35
|
+
/** The water layer, a line of text per row of cells (`GameMap.water`) */
|
|
26
36
|
water: string[];
|
|
37
|
+
/** The paint layer, a line of text per row of cells (`GameMap.tiles`) */
|
|
27
38
|
tiles: string[];
|
|
28
39
|
/** The game's layers of cells (`GameMap.cells`), by id, a line of text for each row as the layers above. Left out for none */
|
|
29
40
|
cells?: Record<string, string[]>;
|
|
@@ -31,31 +42,51 @@ export interface MapFile {
|
|
|
31
42
|
pathing?: string[];
|
|
32
43
|
/** See `GameMap.tileset`. Since format 2 */
|
|
33
44
|
tileset: string[];
|
|
45
|
+
/** The players who can take part (`GameMap.players`) */
|
|
34
46
|
players: MapPlayer[];
|
|
47
|
+
/** What stands on the map when the game begins (`GameMap.objects`) */
|
|
35
48
|
objects: MapObject[];
|
|
49
|
+
/** The creeps that guard spots (`GameMap.camps`) */
|
|
36
50
|
camps: MapCamp[];
|
|
37
51
|
/** Left out when there are none, as files made before regions were have none */
|
|
38
52
|
regions?: MapRegion[];
|
|
39
53
|
/** Left out when there are none */
|
|
40
54
|
points?: MapPoint[];
|
|
55
|
+
/** The named lines of the map (`GameMap.paths`); left out when there are none */
|
|
41
56
|
paths?: MapPath[];
|
|
57
|
+
/** The scenery of the map (`GameMap.doodads`); left out when there are none */
|
|
42
58
|
doodads?: MapDoodad[];
|
|
59
|
+
/** The saved views of the map (`GameMap.cameras`); left out when there are none */
|
|
43
60
|
cameras?: MapCamera[];
|
|
61
|
+
/** The groups that placed things can be drawn from (`GameMap.randomGroups`) */
|
|
44
62
|
randomGroups?: MapRandomGroup[];
|
|
63
|
+
/** The tables of what drops when something dies (`GameMap.itemTables`) */
|
|
45
64
|
itemTables?: MapItemTable[];
|
|
46
65
|
/** The map's own definitions (`GameMap.definitions`) */
|
|
47
66
|
definitions?: GameData;
|
|
67
|
+
/** The map's teams, named (`GameMap.forces`) */
|
|
48
68
|
forces?: MapForce[];
|
|
69
|
+
/** The races a lobby offers on the map, by id (`GameMap.races`) */
|
|
49
70
|
races?: string[];
|
|
71
|
+
/** Who made the map (`GameMap.author`) */
|
|
50
72
|
author?: string;
|
|
73
|
+
/** The map's checks it does not want, by their rules' ids (`GameMap.silence`) */
|
|
51
74
|
silence?: string[];
|
|
75
|
+
/** Who the map is for, as lists show it (`GameMap.meantFor`) */
|
|
52
76
|
meantFor?: string;
|
|
77
|
+
/** Whether the whole map starts explored (`GameMap.explored`) */
|
|
53
78
|
explored?: boolean;
|
|
79
|
+
/** What the loading screen says (`GameMap.loading`) */
|
|
54
80
|
loading?: string;
|
|
81
|
+
/** A small picture of the map as a data URL, for lists of maps (`GameMap.preview`) */
|
|
55
82
|
preview?: string;
|
|
83
|
+
/** What the map looks like beyond its ground: its water, light, sky (`GameMap.environment`) */
|
|
56
84
|
environment?: MapEnvironment;
|
|
85
|
+
/** The hour the game starts at and whether it moves (`GameMap.day`) */
|
|
57
86
|
day?: MapDay;
|
|
87
|
+
/** How the map was made when a generator made it: the seed and options (`GameMap.generated`) */
|
|
58
88
|
generated?: GeneratedWith;
|
|
89
|
+
/** The part of the map play happens in, in cells (`GameMap.bounds`) */
|
|
59
90
|
bounds?: CellRect;
|
|
60
91
|
/** Left out when the game keeps nothing with the map */
|
|
61
92
|
data?: Record<string, unknown>;
|
|
@@ -88,16 +119,38 @@ export declare function serializeMap(map: GameMap): MapFile;
|
|
|
88
119
|
*
|
|
89
120
|
* export const maps = mapsFrom({ './maps/field.vgmap.json': field, './maps/hills.vgmap.json': hills })
|
|
90
121
|
*
|
|
91
|
-
*
|
|
122
|
+
* Given what loads each file in place of the file (`import.meta.glob('./maps/*.vgmap.json', { import: 'default' })`, not
|
|
123
|
+
* `eager`; or `() => import('./field.vgmap.json')`), nothing is fetched or read until a map is asked for: the result is
|
|
124
|
+
* then `LazyMaps`, each a function giving the map (a promise), and the page carries one chunk a map. `appScenes` takes
|
|
125
|
+
* both
|
|
92
126
|
*
|
|
93
|
-
*
|
|
127
|
+
* export const maps = mapsFrom(import.meta.glob('./maps/*.vgmap.json', { import: 'default' }))
|
|
128
|
+
* const field = await maps.field()
|
|
129
|
+
*
|
|
130
|
+
* Throws for two files of one name, for files some given and some loaded, and with the path of a file that cannot be read
|
|
131
|
+
*
|
|
132
|
+
* @public
|
|
133
|
+
*/
|
|
134
|
+
export declare function mapsFrom(files: Readonly<Record<string, () => unknown>>): LazyMaps;
|
|
135
|
+
/**
|
|
136
|
+
* The maps of map files given whole, read at once (see above for loaders)
|
|
137
|
+
*
|
|
138
|
+
* @public
|
|
94
139
|
*/
|
|
95
140
|
export declare function mapsFrom(files: Readonly<Record<string, unknown>>): Record<string, GameMap>;
|
|
96
141
|
/**
|
|
97
|
-
*
|
|
142
|
+
* The maps of a game, each read as it is asked for (`mapsFrom` given loaders): a function giving the map, a promise. A
|
|
143
|
+
* map is read (`parseMap`) once, when first asked; the next ask gets the same map, which a game copies before it changes
|
|
144
|
+
* anything (`structuredClone`)
|
|
98
145
|
*
|
|
99
146
|
* @beta
|
|
100
147
|
*/
|
|
148
|
+
export type LazyMaps = Readonly<Record<string, () => Promise<GameMap>>>;
|
|
149
|
+
/**
|
|
150
|
+
* Reads a map file, of this format or an older one. Throws with what is wrong with it
|
|
151
|
+
*
|
|
152
|
+
* @public
|
|
153
|
+
*/
|
|
101
154
|
export declare function parseMap(file: unknown): GameMap;
|
|
102
155
|
/**
|
|
103
156
|
* A copy that shares nothing with the original
|
package/dist/map/file.js
ADDED
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
import { plain } from "../plain.js";
|
|
2
|
+
import "./types.js";
|
|
3
|
+
import { LEGACY_TILESET } from "../tiles.js";
|
|
4
|
+
import { packBytes, unpackBytes } from "../bytes.js";
|
|
5
|
+
import { KNOWN, MAP_FIELD_SPECS } from "./schema.js";
|
|
6
|
+
//#region src/map/file.ts
|
|
7
|
+
var isObject = (value) => typeof value === "object" && value !== null;
|
|
8
|
+
/** The steps from each format to the one after it, by the format they start from */
|
|
9
|
+
var MIGRATIONS = {
|
|
10
|
+
1: (file) => ({
|
|
11
|
+
...file,
|
|
12
|
+
tileset: [...LEGACY_TILESET]
|
|
13
|
+
}),
|
|
14
|
+
2: (file) => {
|
|
15
|
+
const width = Number(file.width);
|
|
16
|
+
const depth = Number(file.depth);
|
|
17
|
+
const split = (key, count, bytes) => {
|
|
18
|
+
const packed = file[key];
|
|
19
|
+
const whole = typeof packed === "string" ? unpackBytes(packed, count * bytes) : void 0;
|
|
20
|
+
return whole ? rowsOf(whole, bytes) : packed;
|
|
21
|
+
};
|
|
22
|
+
return {
|
|
23
|
+
...file,
|
|
24
|
+
ground: split("ground", depth + 1, (width + 1) * 4),
|
|
25
|
+
levels: split("levels", depth, width),
|
|
26
|
+
ramps: split("ramps", depth, width),
|
|
27
|
+
water: split("water", depth, width),
|
|
28
|
+
tiles: split("tiles", depth, width)
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
/** The layers of cells of a map with anything in them, as the file has them: none when there are none */
|
|
33
|
+
function mapCells(map) {
|
|
34
|
+
const layers = Object.entries(map.cells ?? {}).filter(([, cells]) => cells.some((value) => value !== 0));
|
|
35
|
+
return layers.length ? Object.fromEntries(layers.sort(([a], [b]) => a < b ? -1 : 1).map(([id, cells]) => [id, rowsOf(cells, map.width)])) : void 0;
|
|
36
|
+
}
|
|
37
|
+
/** Bytes as a line of text for each row of `bytes` of them */
|
|
38
|
+
function rowsOf(bytes, row) {
|
|
39
|
+
const lines = [];
|
|
40
|
+
for (let at = 0; at < bytes.length; at += row) lines.push(pack(bytes.subarray(at, at + row)));
|
|
41
|
+
return lines;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* A map file brought up to the format this reader knows, step by step. Throws for what is not a map file, and for
|
|
45
|
+
* one of a newer format: what changed in it cannot be known here. `to` and `steps` are the reader's own when left out
|
|
46
|
+
*
|
|
47
|
+
* @beta
|
|
48
|
+
*/
|
|
49
|
+
function migrateMap(data, to = 3, steps = MIGRATIONS) {
|
|
50
|
+
if (!isObject(data)) throw new Error("Map file: not a map");
|
|
51
|
+
let file = data;
|
|
52
|
+
const format = file.format;
|
|
53
|
+
if (typeof format !== "number" || !Number.isInteger(format) || format < 1) throw new Error(`Map file: format ${String(format)} is not one this game reads`);
|
|
54
|
+
if (format > to) throw new Error(`Map file: format ${format} is newer than this game reads (${to}): it was saved by a newer version of the editor`);
|
|
55
|
+
for (let from = format; from < to; from++) {
|
|
56
|
+
const step = steps[from];
|
|
57
|
+
if (!step) throw new Error(`Map file: there is no way from format ${from} to ${from + 1}`);
|
|
58
|
+
file = {
|
|
59
|
+
...step(file),
|
|
60
|
+
format: from + 1
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
return file;
|
|
64
|
+
}
|
|
65
|
+
var pack = packBytes;
|
|
66
|
+
function unpack(text, length, what) {
|
|
67
|
+
const bytes = unpackBytes(text, length);
|
|
68
|
+
if (!bytes) throw new Error(`Map file: ${what} does not match the size of the map`);
|
|
69
|
+
return bytes;
|
|
70
|
+
}
|
|
71
|
+
/** Whether a value holds anything: text not empty, a list or an object with something in it, a layer with a cell set */
|
|
72
|
+
function filled(value) {
|
|
73
|
+
if (value === void 0 || value === null || value === "" || value === false) return false;
|
|
74
|
+
if (value instanceof Uint8Array) return value.some((each) => each !== 0);
|
|
75
|
+
if (Array.isArray(value)) return value.length > 0;
|
|
76
|
+
if (typeof value === "object") return Object.keys(value).length > 0;
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
/** The bytes of a layer, and how many to a row: the heights by corner (four bytes each), the rest by cell */
|
|
80
|
+
function layerBytes(map, field, layer) {
|
|
81
|
+
return field.perVertex ? {
|
|
82
|
+
bytes: new Uint8Array(layer.buffer, layer.byteOffset, layer.byteLength),
|
|
83
|
+
row: (map.width + 1) * 4
|
|
84
|
+
} : {
|
|
85
|
+
bytes: layer,
|
|
86
|
+
row: map.width
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
/** A field as its file has it, or none where the file leaves it out (`MapFieldSpec.written`) */
|
|
90
|
+
function written(map, field) {
|
|
91
|
+
const value = map[field.key];
|
|
92
|
+
if (field.written === "defined" && value === void 0) return void 0;
|
|
93
|
+
if (field.kind === "layers") return mapCells(map);
|
|
94
|
+
if (field.written === "filled" && !filled(value)) return void 0;
|
|
95
|
+
switch (field.kind) {
|
|
96
|
+
case "layer":
|
|
97
|
+
case "mask": {
|
|
98
|
+
const { bytes, row } = layerBytes(map, field, value);
|
|
99
|
+
return rowsOf(bytes, row);
|
|
100
|
+
}
|
|
101
|
+
case "names": return field.written === "filled" ? [...value] : value;
|
|
102
|
+
case "object": return field.plain ? plain(value, field.key, "Map", "keep numbers, text, lists and plain objects with a map") : value;
|
|
103
|
+
default: return value;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* A map as its file. Throws when what the game keeps with it (`data`) is not plain data, saying where
|
|
108
|
+
*
|
|
109
|
+
* @beta
|
|
110
|
+
*/
|
|
111
|
+
function serializeMap(map) {
|
|
112
|
+
const file = {
|
|
113
|
+
...map.extra,
|
|
114
|
+
format: 3
|
|
115
|
+
};
|
|
116
|
+
for (const field of MAP_FIELD_SPECS) {
|
|
117
|
+
const value = written(map, field);
|
|
118
|
+
if (value === void 0 || field.kind === "object" && field.written === "filled" && !filled(value)) continue;
|
|
119
|
+
file[field.key] = value;
|
|
120
|
+
}
|
|
121
|
+
return file;
|
|
122
|
+
}
|
|
123
|
+
function mapsFrom(files) {
|
|
124
|
+
const entries = Object.entries(files);
|
|
125
|
+
const lazy = typeof entries[0]?.[1] === "function";
|
|
126
|
+
const maps = {};
|
|
127
|
+
for (const [path, file] of entries) {
|
|
128
|
+
const name = mapFileName(path);
|
|
129
|
+
if (name in maps) throw new Error(`mapsFrom: two files are named "${name}"`);
|
|
130
|
+
if (typeof file === "function" !== lazy) throw new Error("mapsFrom: some files are given and some loaded: give them all one way");
|
|
131
|
+
const read = (loaded) => {
|
|
132
|
+
try {
|
|
133
|
+
return parseMap(mapFileOf(loaded));
|
|
134
|
+
} catch (error) {
|
|
135
|
+
throw new Error(`${path}: ${error.message}`);
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
let loading;
|
|
139
|
+
maps[name] = lazy ? () => loading ??= (async () => read(await file()))().catch((error) => (loading = void 0, Promise.reject(error))) : read(file);
|
|
140
|
+
}
|
|
141
|
+
return maps;
|
|
142
|
+
}
|
|
143
|
+
/** The name of a map file: its path without the folder and `.vgmap.json` */
|
|
144
|
+
function mapFileName(path) {
|
|
145
|
+
return (path.split("/").pop() ?? path).replace(/\.vgmap\.json$|\.json$/, "");
|
|
146
|
+
}
|
|
147
|
+
/** What a loader gave: the file itself, or a module whose default is the file (a lazy glob without `import: 'default'`) */
|
|
148
|
+
function mapFileOf(loaded) {
|
|
149
|
+
return isObject(loaded) && !Array.isArray(loaded) && !("format" in loaded) && "default" in loaded ? loaded.default : loaded;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Reads a map file, of this format or an older one. Throws with what is wrong with it
|
|
153
|
+
*
|
|
154
|
+
* @public
|
|
155
|
+
*/
|
|
156
|
+
function parseMap(file) {
|
|
157
|
+
const data = migrateMap(file);
|
|
158
|
+
const width = Number(data.width);
|
|
159
|
+
const depth = Number(data.depth);
|
|
160
|
+
const inRange = (size) => Number.isInteger(size) && size >= 8 && size <= 512;
|
|
161
|
+
if (!inRange(width) || !inRange(depth)) throw new Error(`Map file: the size is out of range, between 8 and 512 cells each way`);
|
|
162
|
+
/** A layer of the ground as its rows have it, back in one piece: `bytes` to a row */
|
|
163
|
+
const rows = (lines, count, bytes, what) => {
|
|
164
|
+
if (!Array.isArray(lines) || lines.length !== count || lines.some((line) => typeof line !== "string")) throw new Error(`Map file: ${what} does not match the size of the map`);
|
|
165
|
+
const whole = new Uint8Array(count * bytes);
|
|
166
|
+
lines.forEach((line, row) => whole.set(unpack(line, bytes, what), row * bytes));
|
|
167
|
+
return whole;
|
|
168
|
+
};
|
|
169
|
+
const layer = (field, lines, what = field.what ?? field.key) => field.perVertex ? new Float32Array(rows(lines, depth + 1, (width + 1) * 4, what).buffer) : rows(lines, depth, width, what);
|
|
170
|
+
/** A list's entries, each an object, with an id where the list is of things with ids (`byId`) */
|
|
171
|
+
const entries = (field, list) => {
|
|
172
|
+
list.forEach((entry, at) => {
|
|
173
|
+
if (!isObject(entry) || Array.isArray(entry)) throw new Error(`Map file: ${field.key}[${at}] is not an object`);
|
|
174
|
+
if (field.byId && !Number.isFinite(entry.id)) throw new Error(`Map file: ${field.key}[${at}] has no id`);
|
|
175
|
+
});
|
|
176
|
+
return list;
|
|
177
|
+
};
|
|
178
|
+
const map = {};
|
|
179
|
+
for (const field of MAP_FIELD_SPECS) {
|
|
180
|
+
const value = data[field.key];
|
|
181
|
+
let read;
|
|
182
|
+
switch (field.kind) {
|
|
183
|
+
case "text":
|
|
184
|
+
read = typeof value === "string" ? value : void 0;
|
|
185
|
+
break;
|
|
186
|
+
case "number":
|
|
187
|
+
read = field.key === "width" ? width : field.key === "depth" ? depth : Number(value) || void 0;
|
|
188
|
+
break;
|
|
189
|
+
case "boolean":
|
|
190
|
+
read = typeof value === "boolean" ? value : void 0;
|
|
191
|
+
break;
|
|
192
|
+
case "layer":
|
|
193
|
+
read = layer(field, value);
|
|
194
|
+
break;
|
|
195
|
+
case "mask":
|
|
196
|
+
read = value === void 0 ? void 0 : layer(field, value);
|
|
197
|
+
break;
|
|
198
|
+
case "layers":
|
|
199
|
+
read = isObject(value) ? Object.fromEntries(Object.keys(value).map((id) => [id, layer(field, value[id], `the cells of ${id}`)])) : void 0;
|
|
200
|
+
break;
|
|
201
|
+
case "names":
|
|
202
|
+
if (field.required) {
|
|
203
|
+
if (!Array.isArray(value)) throw new Error(`Map file: ${field.key} is missing`);
|
|
204
|
+
if (value.length > 255 || value.some((id) => typeof id !== "string")) throw new Error("Map file: the tileset is not a list of tile names");
|
|
205
|
+
read = value;
|
|
206
|
+
} else read = Array.isArray(value) ? value.filter((name) => typeof name === "string") : void 0;
|
|
207
|
+
break;
|
|
208
|
+
case "list":
|
|
209
|
+
if (field.required && !Array.isArray(value)) throw new Error(`Map file: ${field.key} is missing`);
|
|
210
|
+
read = Array.isArray(value) ? entries(field, value) : void 0;
|
|
211
|
+
break;
|
|
212
|
+
case "object": read = isObject(value) && !(field.plain && Array.isArray(value)) ? value : void 0;
|
|
213
|
+
}
|
|
214
|
+
if (read === void 0) read = field.empty?.();
|
|
215
|
+
if (read !== void 0) map[field.key] = read;
|
|
216
|
+
}
|
|
217
|
+
map.objects = map.objects.map((object) => ({
|
|
218
|
+
...object,
|
|
219
|
+
scale: object.scale ?? 1
|
|
220
|
+
}));
|
|
221
|
+
const extra = Object.fromEntries(Object.entries(data).filter(([key]) => !KNOWN.has(key)));
|
|
222
|
+
if (Object.keys(extra).length > 0) map.extra = extra;
|
|
223
|
+
return map;
|
|
224
|
+
}
|
|
225
|
+
/** A copy of a field's value that shares nothing with it */
|
|
226
|
+
function copied(field, value) {
|
|
227
|
+
switch (field.kind) {
|
|
228
|
+
case "layer":
|
|
229
|
+
case "mask": return value.slice();
|
|
230
|
+
case "layers": return Object.fromEntries(Object.entries(value).map(([id, cells]) => [id, cells.slice()]));
|
|
231
|
+
case "names": return [...value];
|
|
232
|
+
case "list":
|
|
233
|
+
case "object": return structuredClone(value);
|
|
234
|
+
default: return value;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* A copy that shares nothing with the original
|
|
239
|
+
*
|
|
240
|
+
* @beta
|
|
241
|
+
*/
|
|
242
|
+
function cloneMap(map) {
|
|
243
|
+
const copy = { ...map };
|
|
244
|
+
for (const field of MAP_FIELD_SPECS) {
|
|
245
|
+
const value = map[field.key];
|
|
246
|
+
if (value !== void 0) copy[field.key] = copied(field, value);
|
|
247
|
+
}
|
|
248
|
+
return copy;
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* The map without what its editor keeps of its own (`GameMap.editor`): what a game is given to play. The very map
|
|
252
|
+
* where it has none
|
|
253
|
+
*
|
|
254
|
+
* @beta
|
|
255
|
+
*/
|
|
256
|
+
function withoutEditor(map) {
|
|
257
|
+
if (!map.editor) return map;
|
|
258
|
+
const { editor: _, ...rest } = map;
|
|
259
|
+
return rest;
|
|
260
|
+
}
|
|
261
|
+
//#endregion
|
|
262
|
+
export { cloneMap, mapsFrom, migrateMap, parseMap, serializeMap, withoutEditor };
|
|
263
|
+
|
|
264
|
+
//# sourceMappingURL=file.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file.js","names":[],"sources":["../../src/map/file.ts"],"sourcesContent":["import type { GameData } from '../gameData'\n/*\n * A map as its file: written, read, brought up from an older format, copied (design review E8a: `map.ts` in parts)\n */\nimport { packBytes, unpackBytes } from '../bytes'\nimport type { GeneratedWith } from '../generate'\nimport { plain } from '../plain'\nimport { LEGACY_TILESET, MAX_TILES } from '../tiles'\nimport type { MapEnvironment } from './look'\nimport { KNOWN, MAP_FIELD_SPECS, type MapFieldSpec } from './schema'\nimport {\n\ttype CellRect,\n\ttype GameMap,\n\tMAP_FORMAT,\n\tMAX_MAP_SIZE,\n\tMIN_MAP_SIZE,\n\ttype MapCamera,\n\ttype MapCamp,\n\ttype MapDay,\n\ttype MapDoodad,\n\ttype MapForce,\n\ttype MapItemTable,\n\ttype MapObject,\n\ttype MapPath,\n\ttype MapPlayer,\n\ttype MapPoint,\n\ttype MapRandomGroup,\n\ttype MapRegion\n} from './types'\n\n// ---- files\n\n/**\n * A map the way it is written to a file: JSON, with the layers packed\n *\n * @beta\n */\nexport interface MapFile {\n\t/** The file format's version (`MAP_FORMAT` when written), which the reader brings older files up from */\n\tformat: number\n\t/** The map's name (`GameMap.name`) */\n\tname: string\n\t/** The map's description (`GameMap.description`) */\n\tdescription: string\n\t/** The game the map was made for, by the id of its module (`GameMap.game`); any game when left out */\n\tgame?: string\n\t/** The map's width in cells */\n\twidth: number\n\t/** The map's depth in cells */\n\tdepth: number\n\t/** How much higher a level stands than the one below (`GameMap.cliffHeight`) */\n\tcliffHeight: number\n\t/**\n\t * The layers of the ground, a line of text for each row (since format 3: before, one line for the whole layer): two\n\t * people who change different rows change different lines, which git merges. The heights by corner, a row of the\n\t * corners along x for each z; the rest by cell, a row of cells for each z\n\t */\n\tground: string[]\n\t/** The cliff levels, a line of text per row of cells (`GameMap.levels`) */\n\tlevels: string[]\n\t/** The ramp flags, a line of text per row of cells (`GameMap.ramps`) */\n\tramps: string[]\n\t/** The water layer, a line of text per row of cells (`GameMap.water`) */\n\twater: string[]\n\t/** The paint layer, a line of text per row of cells (`GameMap.tiles`) */\n\ttiles: string[]\n\t/** The game's layers of cells (`GameMap.cells`), by id, a line of text for each row as the layers above. Left out for none */\n\tcells?: Record<string, string[]>\n\t/** What is kept off cells by hand (`GameMap.pathing`), a line of text for each row as the layers above. Left out for none */\n\tpathing?: string[]\n\t/** See `GameMap.tileset`. Since format 2 */\n\ttileset: string[]\n\t/** The players who can take part (`GameMap.players`) */\n\tplayers: MapPlayer[]\n\t/** What stands on the map when the game begins (`GameMap.objects`) */\n\tobjects: MapObject[]\n\t/** The creeps that guard spots (`GameMap.camps`) */\n\tcamps: MapCamp[]\n\t/** Left out when there are none, as files made before regions were have none */\n\tregions?: MapRegion[]\n\t/** Left out when there are none */\n\tpoints?: MapPoint[]\n\t/** The named lines of the map (`GameMap.paths`); left out when there are none */\n\tpaths?: MapPath[]\n\t/** The scenery of the map (`GameMap.doodads`); left out when there are none */\n\tdoodads?: MapDoodad[]\n\t/** The saved views of the map (`GameMap.cameras`); left out when there are none */\n\tcameras?: MapCamera[]\n\t/** The groups that placed things can be drawn from (`GameMap.randomGroups`) */\n\trandomGroups?: MapRandomGroup[]\n\t/** The tables of what drops when something dies (`GameMap.itemTables`) */\n\titemTables?: MapItemTable[]\n\t/** The map's own definitions (`GameMap.definitions`) */\n\tdefinitions?: GameData\n\t/** The map's teams, named (`GameMap.forces`) */\n\tforces?: MapForce[]\n\t/** The races a lobby offers on the map, by id (`GameMap.races`) */\n\traces?: string[]\n\t/** Who made the map (`GameMap.author`) */\n\tauthor?: string\n\t/** The map's checks it does not want, by their rules' ids (`GameMap.silence`) */\n\tsilence?: string[]\n\t/** Who the map is for, as lists show it (`GameMap.meantFor`) */\n\tmeantFor?: string\n\t/** Whether the whole map starts explored (`GameMap.explored`) */\n\texplored?: boolean\n\t/** What the loading screen says (`GameMap.loading`) */\n\tloading?: string\n\t/** A small picture of the map as a data URL, for lists of maps (`GameMap.preview`) */\n\tpreview?: string\n\t/** What the map looks like beyond its ground: its water, light, sky (`GameMap.environment`) */\n\tenvironment?: MapEnvironment\n\t/** The hour the game starts at and whether it moves (`GameMap.day`) */\n\tday?: MapDay\n\t/** How the map was made when a generator made it: the seed and options (`GameMap.generated`) */\n\tgenerated?: GeneratedWith\n\t/** The part of the map play happens in, in cells (`GameMap.bounds`) */\n\tbounds?: CellRect\n\t/** Left out when the game keeps nothing with the map */\n\tdata?: Record<string, unknown>\n\t/** Left out when the editor keeps nothing with the map */\n\teditor?: Record<string, unknown>\n}\n\nconst isObject = (value: unknown): value is Record<string, unknown> => typeof value === 'object' && value !== null\n\n/**\n * Brings a file of one format up to the next\n *\n * @beta\n */\nexport type MapMigration = (file: Record<string, unknown>) => Record<string, unknown>\n\n/** The steps from each format to the one after it, by the format they start from */\nconst MIGRATIONS: Record<number, MapMigration> = {\n\t// format 2 says which tile each index of the paint is. Before, the index was into the client's own list\n\t1: (file) => ({ ...file, tileset: [...LEGACY_TILESET] }),\n\t// format 3 writes each layer of the ground a row to a line, for git to merge. Before, a layer was one line\n\t2: (file) => {\n\t\tconst width = Number(file.width)\n\t\tconst depth = Number(file.depth)\n\t\tconst split = (key: string, count: number, bytes: number) => {\n\t\t\tconst packed = file[key]\n\t\t\tconst whole = typeof packed === 'string' ? unpackBytes(packed, count * bytes) : undefined\n\t\t\t// what does not match is left for the reader to say so\n\t\t\treturn whole ? rowsOf(whole, bytes) : packed\n\t\t}\n\t\treturn {\n\t\t\t...file,\n\t\t\tground: split('ground', depth + 1, (width + 1) * 4),\n\t\t\tlevels: split('levels', depth, width),\n\t\t\tramps: split('ramps', depth, width),\n\t\t\twater: split('water', depth, width),\n\t\t\ttiles: split('tiles', depth, width)\n\t\t}\n\t}\n}\n\n/** The layers of cells of a map with anything in them, as the file has them: none when there are none */\nfunction mapCells(map: GameMap): Record<string, string[]> | undefined {\n\tconst layers = Object.entries(map.cells ?? {}).filter(([, cells]) => cells.some((value) => value !== 0))\n\treturn layers.length\n\t\t? Object.fromEntries(layers.sort(([a], [b]) => (a < b ? -1 : 1)).map(([id, cells]) => [id, rowsOf(cells, map.width)]))\n\t\t: undefined\n}\n\n/** Bytes as a line of text for each row of `bytes` of them */\nfunction rowsOf(bytes: Uint8Array, row: number): string[] {\n\tconst lines: string[] = []\n\tfor (let at = 0; at < bytes.length; at += row) lines.push(pack(bytes.subarray(at, at + row)))\n\treturn lines\n}\n\n/**\n * A map file brought up to the format this reader knows, step by step. Throws for what is not a map file, and for\n * one of a newer format: what changed in it cannot be known here. `to` and `steps` are the reader's own when left out\n *\n * @beta\n */\nexport function migrateMap(data: unknown, to: number = MAP_FORMAT, steps: Record<number, MapMigration> = MIGRATIONS): Record<string, unknown> {\n\tif (!isObject(data)) throw new Error('Map file: not a map')\n\tlet file = data\n\tconst format = file.format\n\tif (typeof format !== 'number' || !Number.isInteger(format) || format < 1)\n\t\tthrow new Error(`Map file: format ${String(format)} is not one this game reads`)\n\tif (format > to) throw new Error(`Map file: format ${format} is newer than this game reads (${to}): it was saved by a newer version of the editor`)\n\tfor (let from = format; from < to; from++) {\n\t\tconst step = steps[from]\n\t\tif (!step) throw new Error(`Map file: there is no way from format ${from} to ${from + 1}`)\n\t\tfile = { ...step(file), format: from + 1 }\n\t}\n\treturn file\n}\n\nconst pack = packBytes\n\nfunction unpack(text: string, length: number, what: string): Uint8Array {\n\tconst bytes = unpackBytes(text, length)\n\tif (!bytes) throw new Error(`Map file: ${what} does not match the size of the map`)\n\treturn bytes\n}\n\n/** Whether a value holds anything: text not empty, a list or an object with something in it, a layer with a cell set */\nfunction filled(value: unknown): boolean {\n\tif (value === undefined || value === null || value === '' || value === false) return false\n\tif (value instanceof Uint8Array) return value.some((each) => each !== 0)\n\tif (Array.isArray(value)) return value.length > 0\n\tif (typeof value === 'object') return Object.keys(value).length > 0\n\treturn true\n}\n\n/** The bytes of a layer, and how many to a row: the heights by corner (four bytes each), the rest by cell */\nfunction layerBytes(map: GameMap, field: MapFieldSpec, layer: Float32Array | Uint8Array): { bytes: Uint8Array; row: number } {\n\treturn field.perVertex\n\t\t? { bytes: new Uint8Array(layer.buffer, layer.byteOffset, layer.byteLength), row: (map.width + 1) * 4 }\n\t\t: { bytes: layer as Uint8Array, row: map.width }\n}\n\n/** A field as its file has it, or none where the file leaves it out (`MapFieldSpec.written`) */\nfunction written(map: GameMap, field: MapFieldSpec): unknown {\n\tconst value = map[field.key] as unknown\n\tif (field.written === 'defined' && value === undefined) return undefined\n\tif (field.kind === 'layers') return mapCells(map)\n\tif (field.written === 'filled' && !filled(value)) return undefined\n\tswitch (field.kind) {\n\t\tcase 'layer':\n\t\tcase 'mask': {\n\t\t\tconst { bytes, row } = layerBytes(map, field, value as Float32Array | Uint8Array)\n\t\t\treturn rowsOf(bytes, row)\n\t\t}\n\t\tcase 'names':\n\t\t\t// a list of names asked only where it holds any is a copy; the tileset is the map's own\n\t\t\treturn field.written === 'filled' ? [...(value as string[])] : value\n\t\tcase 'object':\n\t\t\treturn field.plain ? plain(value, field.key, 'Map', 'keep numbers, text, lists and plain objects with a map') : value\n\t\tdefault:\n\t\t\treturn value\n\t}\n}\n\n/**\n * A map as its file. Throws when what the game keeps with it (`data`) is not plain data, saying where\n *\n * @beta\n */\nexport function serializeMap(map: GameMap): MapFile {\n\t// first, so that nothing in it stands in for what this reader does know\n\tconst file: Record<string, unknown> = { ...map.extra, format: MAP_FORMAT }\n\tfor (const field of MAP_FIELD_SPECS) {\n\t\tconst value = written(map, field)\n\t\t// plain data that comes to nothing is left out, as an empty object is\n\t\tif (value === undefined || (field.kind === 'object' && field.written === 'filled' && !filled(value))) continue\n\t\tfile[field.key] = value\n\t}\n\treturn file as unknown as MapFile\n}\n\n/**\n * The maps of map files, by the name of each file without its folder and `.vgmap.json`: `./maps/field.vgmap.json` is\n * `field`. The files by their paths, read (`parseMap`): imported one by one, or Vite's\n * `import.meta.glob('./maps/*.vgmap.json', { eager: true, import: 'default' })` where only a page reads them\n *\n * export const maps = mapsFrom({ './maps/field.vgmap.json': field, './maps/hills.vgmap.json': hills })\n *\n * Given what loads each file in place of the file (`import.meta.glob('./maps/*.vgmap.json', { import: 'default' })`, not\n * `eager`; or `() => import('./field.vgmap.json')`), nothing is fetched or read until a map is asked for: the result is\n * then `LazyMaps`, each a function giving the map (a promise), and the page carries one chunk a map. `appScenes` takes\n * both\n *\n * export const maps = mapsFrom(import.meta.glob('./maps/*.vgmap.json', { import: 'default' }))\n * const field = await maps.field()\n *\n * Throws for two files of one name, for files some given and some loaded, and with the path of a file that cannot be read\n *\n * @public\n */\nexport function mapsFrom(files: Readonly<Record<string, () => unknown>>): LazyMaps\n/**\n * The maps of map files given whole, read at once (see above for loaders)\n *\n * @public\n */\nexport function mapsFrom(files: Readonly<Record<string, unknown>>): Record<string, GameMap>\nexport function mapsFrom(files: Readonly<Record<string, unknown>>): Record<string, GameMap> | LazyMaps {\n\tconst entries = Object.entries(files)\n\tconst lazy = typeof entries[0]?.[1] === 'function'\n\tconst maps: Record<string, GameMap | (() => Promise<GameMap>)> = {}\n\tfor (const [path, file] of entries) {\n\t\tconst name = mapFileName(path)\n\t\tif (name in maps) throw new Error(`mapsFrom: two files are named \"${name}\"`)\n\t\tif ((typeof file === 'function') !== lazy) throw new Error('mapsFrom: some files are given and some loaded: give them all one way')\n\t\tconst read = (loaded: unknown): GameMap => {\n\t\t\ttry {\n\t\t\t\treturn parseMap(mapFileOf(loaded))\n\t\t\t} catch (error) {\n\t\t\t\tthrow new Error(`${path}: ${(error as Error).message}`)\n\t\t\t}\n\t\t}\n\t\tlet loading: Promise<GameMap> | undefined\n\t\t// read when asked, once; a file that failed is tried again the next time\n\t\tmaps[name] = lazy\n\t\t\t? () => (loading ??= (async () => read(await (file as () => unknown)()))().catch((error) => ((loading = undefined), Promise.reject(error))))\n\t\t\t: read(file)\n\t}\n\treturn maps as Record<string, GameMap> | LazyMaps\n}\n\n/**\n * The maps of a game, each read as it is asked for (`mapsFrom` given loaders): a function giving the map, a promise. A\n * map is read (`parseMap`) once, when first asked; the next ask gets the same map, which a game copies before it changes\n * anything (`structuredClone`)\n *\n * @beta\n */\nexport type LazyMaps = Readonly<Record<string, () => Promise<GameMap>>>\n\n/** The name of a map file: its path without the folder and `.vgmap.json` */\nfunction mapFileName(path: string): string {\n\treturn (path.split('/').pop() ?? path).replace(/\\.vgmap\\.json$|\\.json$/, '')\n}\n\n/** What a loader gave: the file itself, or a module whose default is the file (a lazy glob without `import: 'default'`) */\nfunction mapFileOf(loaded: unknown): unknown {\n\treturn isObject(loaded) && !Array.isArray(loaded) && !('format' in loaded) && 'default' in loaded ? loaded.default : loaded\n}\n\n/**\n * Reads a map file, of this format or an older one. Throws with what is wrong with it\n *\n * @public\n */\nexport function parseMap(file: unknown): GameMap {\n\tconst data = migrateMap(file)\n\tconst width = Number(data.width)\n\tconst depth = Number(data.depth)\n\tconst inRange = (size: number) => Number.isInteger(size) && size >= MIN_MAP_SIZE && size <= MAX_MAP_SIZE\n\tif (!inRange(width) || !inRange(depth)) {\n\t\tthrow new Error(`Map file: the size is out of range, between ${MIN_MAP_SIZE} and ${MAX_MAP_SIZE} cells each way`)\n\t}\n\t/** A layer of the ground as its rows have it, back in one piece: `bytes` to a row */\n\tconst rows = (lines: unknown, count: number, bytes: number, what: string) => {\n\t\tif (!Array.isArray(lines) || lines.length !== count || lines.some((line) => typeof line !== 'string'))\n\t\t\tthrow new Error(`Map file: ${what} does not match the size of the map`)\n\t\tconst whole = new Uint8Array(count * bytes)\n\t\tlines.forEach((line: string, row) => whole.set(unpack(line, bytes, what), row * bytes))\n\t\treturn whole\n\t}\n\tconst layer = (field: MapFieldSpec, lines: unknown, what = field.what ?? field.key) =>\n\t\tfield.perVertex ? new Float32Array(rows(lines, depth + 1, (width + 1) * 4, what).buffer) : rows(lines, depth, width, what)\n\t/** A list's entries, each an object, with an id where the list is of things with ids (`byId`) */\n\tconst entries = (field: MapFieldSpec, list: unknown[]) => {\n\t\tlist.forEach((entry, at) => {\n\t\t\tif (!isObject(entry) || Array.isArray(entry)) throw new Error(`Map file: ${field.key}[${at}] is not an object`)\n\t\t\tif (field.byId && !Number.isFinite((entry as { id?: unknown }).id)) throw new Error(`Map file: ${field.key}[${at}] has no id`)\n\t\t})\n\t\treturn list\n\t}\n\tconst map: Record<string, unknown> = {}\n\tfor (const field of MAP_FIELD_SPECS) {\n\t\tconst value = data[field.key]\n\t\tlet read: unknown\n\t\tswitch (field.kind) {\n\t\t\tcase 'text':\n\t\t\t\tread = typeof value === 'string' ? value : undefined\n\t\t\t\tbreak\n\t\t\tcase 'number':\n\t\t\t\tread = field.key === 'width' ? width : field.key === 'depth' ? depth : Number(value) || undefined\n\t\t\t\tbreak\n\t\t\tcase 'boolean':\n\t\t\t\tread = typeof value === 'boolean' ? value : undefined\n\t\t\t\tbreak\n\t\t\tcase 'layer':\n\t\t\t\tread = layer(field, value)\n\t\t\t\tbreak\n\t\t\tcase 'mask':\n\t\t\t\tread = value === undefined ? undefined : layer(field, value)\n\t\t\t\tbreak\n\t\t\tcase 'layers':\n\t\t\t\tread = isObject(value) ? Object.fromEntries(Object.keys(value).map((id) => [id, layer(field, value[id], `the cells of ${id}`)])) : undefined\n\t\t\t\tbreak\n\t\t\tcase 'names':\n\t\t\t\tif (field.required) {\n\t\t\t\t\tif (!Array.isArray(value)) throw new Error(`Map file: ${field.key} is missing`)\n\t\t\t\t\tif (value.length > MAX_TILES || value.some((id) => typeof id !== 'string'))\n\t\t\t\t\t\tthrow new Error('Map file: the tileset is not a list of tile names')\n\t\t\t\t\tread = value\n\t\t\t\t} else read = Array.isArray(value) ? value.filter((name): name is string => typeof name === 'string') : undefined\n\t\t\t\tbreak\n\t\t\tcase 'list':\n\t\t\t\tif (field.required && !Array.isArray(value)) throw new Error(`Map file: ${field.key} is missing`)\n\t\t\t\tread = Array.isArray(value) ? entries(field, value) : undefined\n\t\t\t\tbreak\n\t\t\tcase 'object':\n\t\t\t\tread = isObject(value) && !(field.plain && Array.isArray(value)) ? value : undefined\n\t\t\t\tbreak\n\t\t}\n\t\tif (read === undefined) read = field.empty?.()\n\t\tif (read !== undefined) map[field.key] = read\n\t}\n\t// a thing placed is as big as its type unless the file says otherwise\n\tmap.objects = (map.objects as MapObject[]).map((object) => ({ ...object, scale: object.scale ?? 1 }))\n\tconst extra = Object.fromEntries(Object.entries(data).filter(([key]) => !KNOWN.has(key)))\n\tif (Object.keys(extra).length > 0) map.extra = extra\n\treturn map as unknown as GameMap\n}\n\n/** A copy of a field's value that shares nothing with it */\nfunction copied(field: MapFieldSpec, value: unknown): unknown {\n\tswitch (field.kind) {\n\t\tcase 'layer':\n\t\tcase 'mask':\n\t\t\treturn (value as Uint8Array | Float32Array).slice()\n\t\tcase 'layers':\n\t\t\treturn Object.fromEntries(Object.entries(value as Record<string, Uint8Array>).map(([id, cells]) => [id, cells.slice()]))\n\t\tcase 'names':\n\t\t\treturn [...(value as string[])]\n\t\tcase 'list':\n\t\tcase 'object':\n\t\t\treturn structuredClone(value)\n\t\tdefault:\n\t\t\treturn value\n\t}\n}\n\n/**\n * A copy that shares nothing with the original\n *\n * @beta\n */\nexport function cloneMap(map: GameMap): GameMap {\n\tconst copy: Record<string, unknown> = { ...map }\n\tfor (const field of MAP_FIELD_SPECS) {\n\t\tconst value = map[field.key] as unknown\n\t\tif (value !== undefined) copy[field.key] = copied(field, value)\n\t}\n\treturn copy as unknown as GameMap\n}\n\n/**\n * The map without what its editor keeps of its own (`GameMap.editor`): what a game is given to play. The very map\n * where it has none\n *\n * @beta\n */\nexport function withoutEditor(map: GameMap): GameMap {\n\tif (!map.editor) return map\n\tconst { editor: _, ...rest } = map\n\treturn rest\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { clamp } from "../math.js";
|
|
2
|
+
//#region src/map/images.ts
|
|
3
|
+
/**
|
|
4
|
+
* Heights from the pixels of a picture (RGBA, as a canvas gives them): dark is `low`, light is `high`, the picture
|
|
5
|
+
* stretched over the corners of the map's ground. A heightmap made elsewhere, read into a map
|
|
6
|
+
*
|
|
7
|
+
* @beta
|
|
8
|
+
*/
|
|
9
|
+
function heightsFromPixels(pixels, imageWidth, imageHeight, map, low, high) {
|
|
10
|
+
const row = map.width + 1;
|
|
11
|
+
const ground = new Float32Array(row * (map.depth + 1));
|
|
12
|
+
const at = (x, y) => {
|
|
13
|
+
const i = (clamp(y, 0, imageHeight - 1) * imageWidth + clamp(x, 0, imageWidth - 1)) * 4;
|
|
14
|
+
return (pixels[i] * .299 + pixels[i + 1] * .587 + pixels[i + 2] * .114) / 255;
|
|
15
|
+
};
|
|
16
|
+
for (let iz = 0; iz <= map.depth; iz++) for (let ix = 0; ix <= map.width; ix++) {
|
|
17
|
+
const fx = ix / map.width * (imageWidth - 1);
|
|
18
|
+
const fy = iz / map.depth * (imageHeight - 1);
|
|
19
|
+
const x = Math.floor(fx);
|
|
20
|
+
const y = Math.floor(fy);
|
|
21
|
+
const tx = fx - x;
|
|
22
|
+
const ty = fy - y;
|
|
23
|
+
const top = at(x, y) * (1 - tx) + at(x + 1, y) * tx;
|
|
24
|
+
const bottom = at(x, y + 1) * (1 - tx) + at(x + 1, y + 1) * tx;
|
|
25
|
+
ground[iz * row + ix] = low + (top * (1 - ty) + bottom * ty) * (high - low);
|
|
26
|
+
}
|
|
27
|
+
return ground;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The heights of a terrain as the pixels of a picture (RGBA), a pixel a corner: the lowest black, the highest white
|
|
31
|
+
*
|
|
32
|
+
* @beta
|
|
33
|
+
*/
|
|
34
|
+
function heightsToPixels(heights, width, depth) {
|
|
35
|
+
let low = Infinity;
|
|
36
|
+
let high = -Infinity;
|
|
37
|
+
for (const h of heights) {
|
|
38
|
+
low = Math.min(low, h);
|
|
39
|
+
high = Math.max(high, h);
|
|
40
|
+
}
|
|
41
|
+
const span = high - low || 1;
|
|
42
|
+
const pixels = new Uint8ClampedArray((width + 1) * (depth + 1) * 4);
|
|
43
|
+
for (let i = 0; i < heights.length; i++) {
|
|
44
|
+
const value = Math.round((heights[i] - low) / span * 255);
|
|
45
|
+
pixels.set([
|
|
46
|
+
value,
|
|
47
|
+
value,
|
|
48
|
+
value,
|
|
49
|
+
255
|
|
50
|
+
], i * 4);
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
pixels,
|
|
54
|
+
low,
|
|
55
|
+
high
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
//#endregion
|
|
59
|
+
export { heightsFromPixels, heightsToPixels };
|
|
60
|
+
|
|
61
|
+
//# sourceMappingURL=images.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"images.js","names":[],"sources":["../../src/map/images.ts"],"sourcesContent":["/*\n * Heights to and from the pixels of a picture (design review E8a: `map.ts` in parts)\n */\nimport { clamp } from '../math'\nimport type { GameMap } from './types'\n\n/**\n * Heights from the pixels of a picture (RGBA, as a canvas gives them): dark is `low`, light is `high`, the picture\n * stretched over the corners of the map's ground. A heightmap made elsewhere, read into a map\n *\n * @beta\n */\nexport function heightsFromPixels(\n\tpixels: ArrayLike<number>,\n\timageWidth: number,\n\timageHeight: number,\n\tmap: Pick<GameMap, 'width' | 'depth'>,\n\tlow: number,\n\thigh: number\n): Float32Array {\n\tconst row = map.width + 1\n\tconst ground = new Float32Array(row * (map.depth + 1))\n\tconst at = (x: number, y: number) => {\n\t\tconst i = (clamp(y, 0, imageHeight - 1) * imageWidth + clamp(x, 0, imageWidth - 1)) * 4\n\t\t// the brightness of it, as the eye sees it\n\t\treturn (pixels[i] * 0.299 + pixels[i + 1] * 0.587 + pixels[i + 2] * 0.114) / 255\n\t}\n\tfor (let iz = 0; iz <= map.depth; iz++) {\n\t\tfor (let ix = 0; ix <= map.width; ix++) {\n\t\t\t// between the four pixels around where this corner falls\n\t\t\tconst fx = (ix / map.width) * (imageWidth - 1)\n\t\t\tconst fy = (iz / map.depth) * (imageHeight - 1)\n\t\t\tconst x = Math.floor(fx)\n\t\t\tconst y = Math.floor(fy)\n\t\t\tconst tx = fx - x\n\t\t\tconst ty = fy - y\n\t\t\tconst top = at(x, y) * (1 - tx) + at(x + 1, y) * tx\n\t\t\tconst bottom = at(x, y + 1) * (1 - tx) + at(x + 1, y + 1) * tx\n\t\t\tground[iz * row + ix] = low + (top * (1 - ty) + bottom * ty) * (high - low)\n\t\t}\n\t}\n\treturn ground\n}\n\n/**\n * The heights of a terrain as the pixels of a picture (RGBA), a pixel a corner: the lowest black, the highest white\n *\n * @beta\n */\nexport function heightsToPixels(heights: Float32Array, width: number, depth: number): { pixels: Uint8ClampedArray; low: number; high: number } {\n\tlet low = Infinity\n\tlet high = -Infinity\n\tfor (const h of heights) {\n\t\tlow = Math.min(low, h)\n\t\thigh = Math.max(high, h)\n\t}\n\tconst span = high - low || 1\n\tconst pixels = new Uint8ClampedArray((width + 1) * (depth + 1) * 4)\n\tfor (let i = 0; i < heights.length; i++) {\n\t\tconst value = Math.round(((heights[i] - low) / span) * 255)\n\t\tpixels.set([value, value, value, 255], i * 4)\n\t}\n\treturn { pixels, low, high }\n}\n"],"mappings":";;;;;;;;AAYA,SAAgB,kBACf,QACA,YACA,aACA,KACA,KACA,MACe;CACf,MAAM,MAAM,IAAI,QAAQ;CACxB,MAAM,SAAS,IAAI,aAAa,OAAO,IAAI,QAAQ,EAAE;CACrD,MAAM,MAAM,GAAW,MAAc;EACpC,MAAM,KAAK,MAAM,GAAG,GAAG,cAAc,CAAC,IAAI,aAAa,MAAM,GAAG,GAAG,aAAa,CAAC,KAAK;EAEtF,QAAQ,OAAO,KAAK,OAAQ,OAAO,IAAI,KAAK,OAAQ,OAAO,IAAI,KAAK,QAAS;CAC9E;CACA,KAAK,IAAI,KAAK,GAAG,MAAM,IAAI,OAAO,MACjC,KAAK,IAAI,KAAK,GAAG,MAAM,IAAI,OAAO,MAAM;EAEvC,MAAM,KAAM,KAAK,IAAI,SAAU,aAAa;EAC5C,MAAM,KAAM,KAAK,IAAI,SAAU,cAAc;EAC7C,MAAM,IAAI,KAAK,MAAM,EAAE;EACvB,MAAM,IAAI,KAAK,MAAM,EAAE;EACvB,MAAM,KAAK,KAAK;EAChB,MAAM,KAAK,KAAK;EAChB,MAAM,MAAM,GAAG,GAAG,CAAC,KAAK,IAAI,MAAM,GAAG,IAAI,GAAG,CAAC,IAAI;EACjD,MAAM,SAAS,GAAG,GAAG,IAAI,CAAC,KAAK,IAAI,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC,IAAI;EAC5D,OAAO,KAAK,MAAM,MAAM,OAAO,OAAO,IAAI,MAAM,SAAS,OAAO,OAAO;CACxE;CAED,OAAO;AACR;;;;;;AAOA,SAAgB,gBAAgB,SAAuB,OAAe,OAAyE;CAC9I,IAAI,MAAM;CACV,IAAI,OAAO;CACX,KAAK,MAAM,KAAK,SAAS;EACxB,MAAM,KAAK,IAAI,KAAK,CAAC;EACrB,OAAO,KAAK,IAAI,MAAM,CAAC;CACxB;CACA,MAAM,OAAO,OAAO,OAAO;CAC3B,MAAM,SAAS,IAAI,mBAAmB,QAAQ,MAAM,QAAQ,KAAK,CAAC;CAClE,KAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;EACxC,MAAM,QAAQ,KAAK,OAAQ,QAAQ,KAAK,OAAO,OAAQ,GAAG;EAC1D,OAAO,IAAI;GAAC;GAAO;GAAO;GAAO;EAAG,GAAG,IAAI,CAAC;CAC7C;CACA,OAAO;EAAE;EAAQ;EAAK;CAAK;AAC5B"}
|
package/dist/map/look.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* paint like the game's. An open interface: the client adds what it draws by (its water, light, sky, fog, weather,
|
|
5
5
|
* lights and the rest), as a game adds its commands (`Commands`)
|
|
6
6
|
*
|
|
7
|
-
* @
|
|
7
|
+
* @public
|
|
8
8
|
*/
|
|
9
9
|
export interface MapEnvironment {
|
|
10
10
|
/** Ground of the map's own to paint with, past the game's tiles (see `MapTile`): the rules' paint, by id */
|
package/dist/map/look.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { environmentChanged } from "../engineEvents.js";
|
|
2
|
+
import { replicateEvent } from "../replication.js";
|
|
3
|
+
import "../tiles.js";
|
|
4
|
+
//#region src/map/look.ts
|
|
5
|
+
/**
|
|
6
|
+
* The ids of a map's own tiles (`MapEnvironment.tiles`)
|
|
7
|
+
*
|
|
8
|
+
* @beta
|
|
9
|
+
*/
|
|
10
|
+
var mapTileIds = (environment) => (environment?.tiles ?? []).map((tile) => tile.id);
|
|
11
|
+
/**
|
|
12
|
+
* The tiles a world from a map is painted with: the game's, then the map's own that are none of them, as many as a map
|
|
13
|
+
* can hold. The order a played ground's paint is in, and its looks
|
|
14
|
+
*
|
|
15
|
+
* @beta
|
|
16
|
+
*/
|
|
17
|
+
function playTileset(gameTiles, environment) {
|
|
18
|
+
const own = mapTileIds(environment).filter((id) => !gameTiles.includes(id));
|
|
19
|
+
return [...gameTiles, ...own].slice(0, 255);
|
|
20
|
+
}
|
|
21
|
+
/** The map's light, fog and sky changed (`world.setEnvironment`): to everyone */
|
|
22
|
+
var toldEnvironment = replicateEvent(environmentChanged, "environment", ({ environment, over }) => ({
|
|
23
|
+
type: "environment",
|
|
24
|
+
environment: structuredClone(environment),
|
|
25
|
+
...over && { over }
|
|
26
|
+
}));
|
|
27
|
+
//#endregion
|
|
28
|
+
export { mapTileIds, playTileset, toldEnvironment };
|
|
29
|
+
|
|
30
|
+
//# sourceMappingURL=look.js.map
|