@datamoc/mw_games 0.1.1
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/LICENSE +373 -0
- package/README.md +327 -0
- package/dist/actors/Advancement.d.ts +73 -0
- package/dist/actors/Advancement.d.ts.map +1 -0
- package/dist/actors/Advancement.js +98 -0
- package/dist/actors/Advancement.js.map +1 -0
- package/dist/actors/Affix.d.ts +44 -0
- package/dist/actors/Affix.d.ts.map +1 -0
- package/dist/actors/Affix.js +35 -0
- package/dist/actors/Affix.js.map +1 -0
- package/dist/actors/Appearances.d.ts +36 -0
- package/dist/actors/Appearances.d.ts.map +1 -0
- package/dist/actors/Appearances.js +50 -0
- package/dist/actors/Appearances.js.map +1 -0
- package/dist/actors/Charges.d.ts +31 -0
- package/dist/actors/Charges.d.ts.map +1 -0
- package/dist/actors/Charges.js +35 -0
- package/dist/actors/Charges.js.map +1 -0
- package/dist/actors/Equipment.d.ts +40 -0
- package/dist/actors/Equipment.d.ts.map +1 -0
- package/dist/actors/Equipment.js +57 -0
- package/dist/actors/Equipment.js.map +1 -0
- package/dist/actors/Inventory.d.ts +50 -0
- package/dist/actors/Inventory.d.ts.map +1 -0
- package/dist/actors/Inventory.js +56 -0
- package/dist/actors/Inventory.js.map +1 -0
- package/dist/actors/ItemState.d.ts +21 -0
- package/dist/actors/ItemState.d.ts.map +1 -0
- package/dist/actors/ItemState.js +34 -0
- package/dist/actors/ItemState.js.map +1 -0
- package/dist/actors/Loot.d.ts +24 -0
- package/dist/actors/Loot.d.ts.map +1 -0
- package/dist/actors/Loot.js +14 -0
- package/dist/actors/Loot.js.map +1 -0
- package/dist/actors/Progression.d.ts +30 -0
- package/dist/actors/Progression.d.ts.map +1 -0
- package/dist/actors/Progression.js +39 -0
- package/dist/actors/Progression.js.map +1 -0
- package/dist/actors/Resource.d.ts +23 -0
- package/dist/actors/Resource.d.ts.map +1 -0
- package/dist/actors/Resource.js +28 -0
- package/dist/actors/Resource.js.map +1 -0
- package/dist/actors/Scaling.d.ts +22 -0
- package/dist/actors/Scaling.d.ts.map +1 -0
- package/dist/actors/Scaling.js +9 -0
- package/dist/actors/Scaling.js.map +1 -0
- package/dist/actors/Shop.d.ts +25 -0
- package/dist/actors/Shop.d.ts.map +1 -0
- package/dist/actors/Shop.js +33 -0
- package/dist/actors/Shop.js.map +1 -0
- package/dist/actors/SkillPoints.d.ts +45 -0
- package/dist/actors/SkillPoints.d.ts.map +1 -0
- package/dist/actors/SkillPoints.js +58 -0
- package/dist/actors/SkillPoints.js.map +1 -0
- package/dist/actors/StatBlock.d.ts +52 -0
- package/dist/actors/StatBlock.d.ts.map +1 -0
- package/dist/actors/StatBlock.js +80 -0
- package/dist/actors/StatBlock.js.map +1 -0
- package/dist/actors/StatusEffect.d.ts +38 -0
- package/dist/actors/StatusEffect.d.ts.map +1 -0
- package/dist/actors/StatusEffect.js +28 -0
- package/dist/actors/StatusEffect.js.map +1 -0
- package/dist/actors/craft.d.ts +26 -0
- package/dist/actors/craft.d.ts.map +1 -0
- package/dist/actors/craft.js +34 -0
- package/dist/actors/craft.js.map +1 -0
- package/dist/actors/index.d.ts +33 -0
- package/dist/actors/index.d.ts.map +1 -0
- package/dist/actors/index.js +18 -0
- package/dist/actors/index.js.map +1 -0
- package/dist/actors/skillCheck.d.ts +13 -0
- package/dist/actors/skillCheck.d.ts.map +1 -0
- package/dist/actors/skillCheck.js +16 -0
- package/dist/actors/skillCheck.js.map +1 -0
- package/dist/assets/index.d.ts +37 -0
- package/dist/assets/index.d.ts.map +1 -0
- package/dist/assets/index.js +62 -0
- package/dist/assets/index.js.map +1 -0
- package/dist/audio/Music.d.ts +22 -0
- package/dist/audio/Music.d.ts.map +1 -0
- package/dist/audio/Music.js +67 -0
- package/dist/audio/Music.js.map +1 -0
- package/dist/audio/Playable.d.ts +16 -0
- package/dist/audio/Playable.d.ts.map +1 -0
- package/dist/audio/Playable.js +6 -0
- package/dist/audio/Playable.js.map +1 -0
- package/dist/audio/Sound.d.ts +23 -0
- package/dist/audio/Sound.d.ts.map +1 -0
- package/dist/audio/Sound.js +30 -0
- package/dist/audio/Sound.js.map +1 -0
- package/dist/audio/index.d.ts +7 -0
- package/dist/audio/index.d.ts.map +1 -0
- package/dist/audio/index.js +4 -0
- package/dist/audio/index.js.map +1 -0
- package/dist/battle/BattleAI.d.ts +24 -0
- package/dist/battle/BattleAI.d.ts.map +1 -0
- package/dist/battle/BattleAI.js +47 -0
- package/dist/battle/BattleAI.js.map +1 -0
- package/dist/battle/Evolution.d.ts +22 -0
- package/dist/battle/Evolution.d.ts.map +1 -0
- package/dist/battle/Evolution.js +25 -0
- package/dist/battle/Evolution.js.map +1 -0
- package/dist/battle/Field.d.ts +25 -0
- package/dist/battle/Field.d.ts.map +1 -0
- package/dist/battle/Field.js +31 -0
- package/dist/battle/Field.js.map +1 -0
- package/dist/battle/Hooks.d.ts +29 -0
- package/dist/battle/Hooks.d.ts.map +1 -0
- package/dist/battle/Hooks.js +20 -0
- package/dist/battle/Hooks.js.map +1 -0
- package/dist/battle/Move.d.ts +32 -0
- package/dist/battle/Move.d.ts.map +1 -0
- package/dist/battle/Move.js +10 -0
- package/dist/battle/Move.js.map +1 -0
- package/dist/battle/Party.d.ts +21 -0
- package/dist/battle/Party.d.ts.map +1 -0
- package/dist/battle/Party.js +49 -0
- package/dist/battle/Party.js.map +1 -0
- package/dist/battle/Species.d.ts +40 -0
- package/dist/battle/Species.d.ts.map +1 -0
- package/dist/battle/Species.js +31 -0
- package/dist/battle/Species.js.map +1 -0
- package/dist/battle/StatStages.d.ts +38 -0
- package/dist/battle/StatStages.d.ts.map +1 -0
- package/dist/battle/StatStages.js +50 -0
- package/dist/battle/StatStages.js.map +1 -0
- package/dist/battle/TypeMatrix.d.ts +14 -0
- package/dist/battle/TypeMatrix.d.ts.map +1 -0
- package/dist/battle/TypeMatrix.js +24 -0
- package/dist/battle/TypeMatrix.js.map +1 -0
- package/dist/battle/index.d.ts +16 -0
- package/dist/battle/index.d.ts.map +1 -0
- package/dist/battle/index.js +10 -0
- package/dist/battle/index.js.map +1 -0
- package/dist/board/Classics.d.ts +123 -0
- package/dist/board/Classics.d.ts.map +1 -0
- package/dist/board/Classics.js +260 -0
- package/dist/board/Classics.js.map +1 -0
- package/dist/board/Engine.d.ts +23 -0
- package/dist/board/Engine.d.ts.map +1 -0
- package/dist/board/Engine.js +87 -0
- package/dist/board/Engine.js.map +1 -0
- package/dist/board/Tactics.d.ts +46 -0
- package/dist/board/Tactics.d.ts.map +1 -0
- package/dist/board/Tactics.js +108 -0
- package/dist/board/Tactics.js.map +1 -0
- package/dist/board/chess.d.ts +67 -0
- package/dist/board/chess.d.ts.map +1 -0
- package/dist/board/chess.js +439 -0
- package/dist/board/chess.js.map +1 -0
- package/dist/board/index.d.ts +9 -0
- package/dist/board/index.d.ts.map +1 -0
- package/dist/board/index.js +5 -0
- package/dist/board/index.js.map +1 -0
- package/dist/core/Achievements.d.ts +53 -0
- package/dist/core/Achievements.d.ts.map +1 -0
- package/dist/core/Achievements.js +80 -0
- package/dist/core/Achievements.js.map +1 -0
- package/dist/core/Collection.d.ts +46 -0
- package/dist/core/Collection.d.ts.map +1 -0
- package/dist/core/Collection.js +61 -0
- package/dist/core/Collection.js.map +1 -0
- package/dist/core/Game.d.ts +115 -0
- package/dist/core/Game.d.ts.map +1 -0
- package/dist/core/Game.js +236 -0
- package/dist/core/Game.js.map +1 -0
- package/dist/core/Hex.d.ts +45 -0
- package/dist/core/Hex.d.ts.map +1 -0
- package/dist/core/Hex.js +120 -0
- package/dist/core/Hex.js.map +1 -0
- package/dist/core/Input.d.ts +41 -0
- package/dist/core/Input.d.ts.map +1 -0
- package/dist/core/Input.js +132 -0
- package/dist/core/Input.js.map +1 -0
- package/dist/core/Log.d.ts +39 -0
- package/dist/core/Log.d.ts.map +1 -0
- package/dist/core/Log.js +50 -0
- package/dist/core/Log.js.map +1 -0
- package/dist/core/Random.d.ts +64 -0
- package/dist/core/Random.d.ts.map +1 -0
- package/dist/core/Random.js +178 -0
- package/dist/core/Random.js.map +1 -0
- package/dist/core/Replay.d.ts +71 -0
- package/dist/core/Replay.d.ts.map +1 -0
- package/dist/core/Replay.js +102 -0
- package/dist/core/Replay.js.map +1 -0
- package/dist/core/Save.d.ts +52 -0
- package/dist/core/Save.d.ts.map +1 -0
- package/dist/core/Save.js +81 -0
- package/dist/core/Save.js.map +1 -0
- package/dist/core/Scene.d.ts +40 -0
- package/dist/core/Scene.d.ts.map +1 -0
- package/dist/core/Scene.js +56 -0
- package/dist/core/Scene.js.map +1 -0
- package/dist/core/SceneStack.d.ts +37 -0
- package/dist/core/SceneStack.d.ts.map +1 -0
- package/dist/core/SceneStack.js +67 -0
- package/dist/core/SceneStack.js.map +1 -0
- package/dist/core/Signal.d.ts +24 -0
- package/dist/core/Signal.d.ts.map +1 -0
- package/dist/core/Signal.js +41 -0
- package/dist/core/Signal.js.map +1 -0
- package/dist/core/index.d.ts +23 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +14 -0
- package/dist/core/index.js.map +1 -0
- package/dist/i18n/index.d.ts +51 -0
- package/dist/i18n/index.d.ts.map +1 -0
- package/dist/i18n/index.js +74 -0
- package/dist/i18n/index.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/mw_games.global.js +993 -0
- package/dist/render/ActorAnimator.d.ts +60 -0
- package/dist/render/ActorAnimator.d.ts.map +1 -0
- package/dist/render/ActorAnimator.js +76 -0
- package/dist/render/ActorAnimator.js.map +1 -0
- package/dist/render/AnimatedSprite.d.ts +57 -0
- package/dist/render/AnimatedSprite.d.ts.map +1 -0
- package/dist/render/AnimatedSprite.js +105 -0
- package/dist/render/AnimatedSprite.js.map +1 -0
- package/dist/render/Autotile.d.ts +42 -0
- package/dist/render/Autotile.d.ts.map +1 -0
- package/dist/render/Autotile.js +117 -0
- package/dist/render/Autotile.js.map +1 -0
- package/dist/render/Camera.d.ts +88 -0
- package/dist/render/Camera.d.ts.map +1 -0
- package/dist/render/Camera.js +145 -0
- package/dist/render/Camera.js.map +1 -0
- package/dist/render/ColorTransformBatcher.d.ts +57 -0
- package/dist/render/ColorTransformBatcher.d.ts.map +1 -0
- package/dist/render/ColorTransformBatcher.js +212 -0
- package/dist/render/ColorTransformBatcher.js.map +1 -0
- package/dist/render/LayeredSprite.d.ts +27 -0
- package/dist/render/LayeredSprite.d.ts.map +1 -0
- package/dist/render/LayeredSprite.js +53 -0
- package/dist/render/LayeredSprite.js.map +1 -0
- package/dist/render/Projectile.d.ts +37 -0
- package/dist/render/Projectile.d.ts.map +1 -0
- package/dist/render/Projectile.js +50 -0
- package/dist/render/Projectile.js.map +1 -0
- package/dist/render/SpriteSheet.d.ts +38 -0
- package/dist/render/SpriteSheet.d.ts.map +1 -0
- package/dist/render/SpriteSheet.js +79 -0
- package/dist/render/SpriteSheet.js.map +1 -0
- package/dist/render/TileMap.d.ts +188 -0
- package/dist/render/TileMap.d.ts.map +1 -0
- package/dist/render/TileMap.js +488 -0
- package/dist/render/TileMap.js.map +1 -0
- package/dist/render/TintedSprite.d.ts +47 -0
- package/dist/render/TintedSprite.d.ts.map +1 -0
- package/dist/render/TintedSprite.js +173 -0
- package/dist/render/TintedSprite.js.map +1 -0
- package/dist/render/index.d.ts +18 -0
- package/dist/render/index.d.ts.map +1 -0
- package/dist/render/index.js +11 -0
- package/dist/render/index.js.map +1 -0
- package/dist/roguelike/Blob.d.ts +46 -0
- package/dist/roguelike/Blob.d.ts.map +1 -0
- package/dist/roguelike/Blob.js +98 -0
- package/dist/roguelike/Blob.js.map +1 -0
- package/dist/roguelike/Boss.d.ts +67 -0
- package/dist/roguelike/Boss.d.ts.map +1 -0
- package/dist/roguelike/Boss.js +114 -0
- package/dist/roguelike/Boss.js.map +1 -0
- package/dist/roguelike/Combat.d.ts +23 -0
- package/dist/roguelike/Combat.d.ts.map +1 -0
- package/dist/roguelike/Combat.js +27 -0
- package/dist/roguelike/Combat.js.map +1 -0
- package/dist/roguelike/Doors.d.ts +60 -0
- package/dist/roguelike/Doors.d.ts.map +1 -0
- package/dist/roguelike/Doors.js +102 -0
- package/dist/roguelike/Doors.js.map +1 -0
- package/dist/roguelike/Elevation.d.ts +26 -0
- package/dist/roguelike/Elevation.d.ts.map +1 -0
- package/dist/roguelike/Elevation.js +37 -0
- package/dist/roguelike/Elevation.js.map +1 -0
- package/dist/roguelike/FieldOfView.d.ts +72 -0
- package/dist/roguelike/FieldOfView.d.ts.map +1 -0
- package/dist/roguelike/FieldOfView.js +134 -0
- package/dist/roguelike/FieldOfView.js.map +1 -0
- package/dist/roguelike/Level.d.ts +96 -0
- package/dist/roguelike/Level.d.ts.map +1 -0
- package/dist/roguelike/Level.js +137 -0
- package/dist/roguelike/Level.js.map +1 -0
- package/dist/roguelike/MonsterAI.d.ts +40 -0
- package/dist/roguelike/MonsterAI.d.ts.map +1 -0
- package/dist/roguelike/MonsterAI.js +69 -0
- package/dist/roguelike/MonsterAI.js.map +1 -0
- package/dist/roguelike/Pathfinder.d.ts +82 -0
- package/dist/roguelike/Pathfinder.d.ts.map +1 -0
- package/dist/roguelike/Pathfinder.js +192 -0
- package/dist/roguelike/Pathfinder.js.map +1 -0
- package/dist/roguelike/Scheduler.d.ts +45 -0
- package/dist/roguelike/Scheduler.d.ts.map +1 -0
- package/dist/roguelike/Scheduler.js +82 -0
- package/dist/roguelike/Scheduler.js.map +1 -0
- package/dist/roguelike/Secrets.d.ts +44 -0
- package/dist/roguelike/Secrets.d.ts.map +1 -0
- package/dist/roguelike/Secrets.js +64 -0
- package/dist/roguelike/Secrets.js.map +1 -0
- package/dist/roguelike/Targeting.d.ts +66 -0
- package/dist/roguelike/Targeting.d.ts.map +1 -0
- package/dist/roguelike/Targeting.js +150 -0
- package/dist/roguelike/Targeting.js.map +1 -0
- package/dist/roguelike/generate.d.ts +44 -0
- package/dist/roguelike/generate.d.ts.map +1 -0
- package/dist/roguelike/generate.js +88 -0
- package/dist/roguelike/generate.js.map +1 -0
- package/dist/roguelike/index.d.ts +23 -0
- package/dist/roguelike/index.d.ts.map +1 -0
- package/dist/roguelike/index.js +15 -0
- package/dist/roguelike/index.js.map +1 -0
- package/dist/rpg/Event.d.ts +33 -0
- package/dist/rpg/Event.d.ts.map +1 -0
- package/dist/rpg/Event.js +19 -0
- package/dist/rpg/Event.js.map +1 -0
- package/dist/rpg/EventRunner.d.ts +72 -0
- package/dist/rpg/EventRunner.d.ts.map +1 -0
- package/dist/rpg/EventRunner.js +76 -0
- package/dist/rpg/EventRunner.js.map +1 -0
- package/dist/rpg/GameState.d.ts +22 -0
- package/dist/rpg/GameState.d.ts.map +1 -0
- package/dist/rpg/GameState.js +35 -0
- package/dist/rpg/GameState.js.map +1 -0
- package/dist/rpg/GridMover.d.ts +51 -0
- package/dist/rpg/GridMover.d.ts.map +1 -0
- package/dist/rpg/GridMover.js +91 -0
- package/dist/rpg/GridMover.js.map +1 -0
- package/dist/rpg/Quest.d.ts +67 -0
- package/dist/rpg/Quest.d.ts.map +1 -0
- package/dist/rpg/Quest.js +92 -0
- package/dist/rpg/Quest.js.map +1 -0
- package/dist/rpg/TiledMap.d.ts +107 -0
- package/dist/rpg/TiledMap.d.ts.map +1 -0
- package/dist/rpg/TiledMap.js +123 -0
- package/dist/rpg/TiledMap.js.map +1 -0
- package/dist/rpg/automap.d.ts +40 -0
- package/dist/rpg/automap.d.ts.map +1 -0
- package/dist/rpg/automap.js +81 -0
- package/dist/rpg/automap.js.map +1 -0
- package/dist/rpg/index.d.ts +14 -0
- package/dist/rpg/index.d.ts.map +1 -0
- package/dist/rpg/index.js +8 -0
- package/dist/rpg/index.js.map +1 -0
- package/dist/stage/DialogueStage.d.ts +75 -0
- package/dist/stage/DialogueStage.d.ts.map +1 -0
- package/dist/stage/DialogueStage.js +207 -0
- package/dist/stage/DialogueStage.js.map +1 -0
- package/dist/stage/index.d.ts +7 -0
- package/dist/stage/index.d.ts.map +1 -0
- package/dist/stage/index.js +4 -0
- package/dist/stage/index.js.map +1 -0
- package/dist/stage/script.d.ts +111 -0
- package/dist/stage/script.d.ts.map +1 -0
- package/dist/stage/script.js +133 -0
- package/dist/stage/script.js.map +1 -0
- package/dist/stage/twee.d.ts +42 -0
- package/dist/stage/twee.d.ts.map +1 -0
- package/dist/stage/twee.js +169 -0
- package/dist/stage/twee.js.map +1 -0
- package/dist/ui/IconGrid.d.ts +110 -0
- package/dist/ui/IconGrid.d.ts.map +1 -0
- package/dist/ui/IconGrid.js +284 -0
- package/dist/ui/IconGrid.js.map +1 -0
- package/dist/ui/Label.d.ts +26 -0
- package/dist/ui/Label.d.ts.map +1 -0
- package/dist/ui/Label.js +41 -0
- package/dist/ui/Label.js.map +1 -0
- package/dist/ui/ListView.d.ts +67 -0
- package/dist/ui/ListView.d.ts.map +1 -0
- package/dist/ui/ListView.js +167 -0
- package/dist/ui/ListView.js.map +1 -0
- package/dist/ui/MessageBox.d.ts +66 -0
- package/dist/ui/MessageBox.d.ts.map +1 -0
- package/dist/ui/MessageBox.js +161 -0
- package/dist/ui/MessageBox.js.map +1 -0
- package/dist/ui/NinePatch.d.ts +34 -0
- package/dist/ui/NinePatch.d.ts.map +1 -0
- package/dist/ui/NinePatch.js +45 -0
- package/dist/ui/NinePatch.js.map +1 -0
- package/dist/ui/VerticalLabel.d.ts +46 -0
- package/dist/ui/VerticalLabel.d.ts.map +1 -0
- package/dist/ui/VerticalLabel.js +81 -0
- package/dist/ui/VerticalLabel.js.map +1 -0
- package/dist/ui/Window.d.ts +71 -0
- package/dist/ui/Window.d.ts.map +1 -0
- package/dist/ui/Window.js +126 -0
- package/dist/ui/Window.js.map +1 -0
- package/dist/ui/WindowStack.d.ts +40 -0
- package/dist/ui/WindowStack.d.ts.map +1 -0
- package/dist/ui/WindowStack.js +106 -0
- package/dist/ui/WindowStack.js.map +1 -0
- package/dist/ui/index.d.ts +18 -0
- package/dist/ui/index.d.ts.map +1 -0
- package/dist/ui/index.js +10 -0
- package/dist/ui/index.js.map +1 -0
- package/dist/ui/theme.d.ts +50 -0
- package/dist/ui/theme.d.ts.map +1 -0
- package/dist/ui/theme.js +36 -0
- package/dist/ui/theme.js.map +1 -0
- package/dist/world/Encounters.d.ts +20 -0
- package/dist/world/Encounters.d.ts.map +1 -0
- package/dist/world/Encounters.js +9 -0
- package/dist/world/Encounters.js.map +1 -0
- package/dist/world/Overworld.d.ts +25 -0
- package/dist/world/Overworld.d.ts.map +1 -0
- package/dist/world/Overworld.js +26 -0
- package/dist/world/Overworld.js.map +1 -0
- package/dist/world/TurnClock.d.ts +25 -0
- package/dist/world/TurnClock.d.ts.map +1 -0
- package/dist/world/TurnClock.js +33 -0
- package/dist/world/TurnClock.js.map +1 -0
- package/dist/world/World.d.ts +50 -0
- package/dist/world/World.d.ts.map +1 -0
- package/dist/world/World.js +77 -0
- package/dist/world/World.js.map +1 -0
- package/dist/world/index.d.ts +8 -0
- package/dist/world/index.d.ts.map +1 -0
- package/dist/world/index.js +5 -0
- package/dist/world/index.js.map +1 -0
- package/package.json +76 -0
- package/tools/compile-resources.mjs +129 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Modifier, ModifierOp } from './StatBlock.ts';
|
|
2
|
+
/**
|
|
3
|
+
* Level-scaled item modifiers: the shape passive gear whose bonus grows with its own
|
|
4
|
+
* upgrade level shares, without any one game's scaling curve.
|
|
5
|
+
*
|
|
6
|
+
* A ring that grants +1 evasion per level and a weapon that hastes 5% per level are the
|
|
7
|
+
* same thing here: each entry names a stat, an op, a value at level 0, and a per-level
|
|
8
|
+
* increment, resolved to plain `Modifier`s for a given level. `mwg` picks no curve
|
|
9
|
+
* beyond linear - anything fancier (diminishing returns, breakpoints) is a game's own
|
|
10
|
+
* `from` function on a derived stat, not a framework formula.
|
|
11
|
+
*/
|
|
12
|
+
export interface LevelScale {
|
|
13
|
+
stat: string;
|
|
14
|
+
op: ModifierOp;
|
|
15
|
+
/** the modifier value at level 0 */
|
|
16
|
+
base: number;
|
|
17
|
+
/** added once per level above 0 */
|
|
18
|
+
perLevel: number;
|
|
19
|
+
}
|
|
20
|
+
/** resolves every scale entry at `level`: value = base + perLevel * level */
|
|
21
|
+
export declare function scaledModifiers(level: number, scales: readonly LevelScale[]): Modifier[];
|
|
22
|
+
//# sourceMappingURL=Scaling.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Scaling.d.ts","sourceRoot":"","sources":["../../src/actors/Scaling.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE3D;;;;;;;;;GASG;AAEH,MAAM,WAAW,UAAU;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,UAAU,CAAC;IAEf,oCAAoC;IACpC,IAAI,EAAE,MAAM,CAAC;IAEb,mCAAmC;IACnC,QAAQ,EAAE,MAAM,CAAC;CACjB;AAED,6EAA6E;AAC7E,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,UAAU,EAAE,GAAG,QAAQ,EAAE,CAMxF"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** resolves every scale entry at `level`: value = base + perLevel * level */
|
|
2
|
+
export function scaledModifiers(level, scales) {
|
|
3
|
+
return scales.map((scale) => ({
|
|
4
|
+
stat: scale.stat,
|
|
5
|
+
op: scale.op,
|
|
6
|
+
value: scale.base + scale.perLevel * level,
|
|
7
|
+
}));
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=Scaling.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Scaling.js","sourceRoot":"","sources":["../../src/actors/Scaling.ts"],"names":[],"mappings":"AAwBA,6EAA6E;AAC7E,MAAM,UAAU,eAAe,CAAC,KAAa,EAAE,MAA6B;IAC3E,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAC7B,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,EAAE,EAAE,KAAK,CAAC,EAAE;QACZ,KAAK,EAAE,KAAK,CAAC,IAAI,GAAG,KAAK,CAAC,QAAQ,GAAG,KAAK;KAC1C,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { StatBlock } from './StatBlock.ts';
|
|
2
|
+
import type { Inventory } from './Inventory.ts';
|
|
3
|
+
/**
|
|
4
|
+
* A buy/sell transaction between two `Inventory`s, paid for from a `StatBlock` stat acting as
|
|
5
|
+
* currency - the same role `craft()` fills for a recipe: check everything first, touch
|
|
6
|
+
* nothing until every check passes, and if any later step fails (the buyer's bag has no
|
|
7
|
+
* room), roll back whatever the earlier steps already did rather than losing stock or coin
|
|
8
|
+
* for nothing.
|
|
9
|
+
*/
|
|
10
|
+
export interface Price {
|
|
11
|
+
/** cost to buy one unit from the shop */
|
|
12
|
+
buy: number;
|
|
13
|
+
/** amount refunded per unit sold to the shop */
|
|
14
|
+
sell: number;
|
|
15
|
+
}
|
|
16
|
+
export interface ShopOptions {
|
|
17
|
+
/** the `StatBlock` stat name holding the spendable currency */
|
|
18
|
+
currency: string;
|
|
19
|
+
prices: ReadonlyMap<string, Price>;
|
|
20
|
+
}
|
|
21
|
+
/** @returns false, touching nothing, if the price is unknown, stock is short, or coin is short */
|
|
22
|
+
export declare function buy(wallet: StatBlock, stock: Inventory, bag: Inventory, id: string, quantity: number, options: ShopOptions): boolean;
|
|
23
|
+
/** @returns false, touching nothing, if the price is unknown or the seller lacks the quantity */
|
|
24
|
+
export declare function sell(wallet: StatBlock, stock: Inventory, bag: Inventory, id: string, quantity: number, options: ShopOptions): boolean;
|
|
25
|
+
//# sourceMappingURL=Shop.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Shop.d.ts","sourceRoot":"","sources":["../../src/actors/Shop.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD;;;;;;GAMG;AACH,MAAM,WAAW,KAAK;IACrB,yCAAyC;IACzC,GAAG,EAAE,MAAM,CAAC;IACZ,gDAAgD;IAChD,IAAI,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,WAAW;IAC3B,+DAA+D;IAC/D,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;CACnC;AAED,kGAAkG;AAClG,wBAAgB,GAAG,CAClB,MAAM,EAAE,SAAS,EACjB,KAAK,EAAE,SAAS,EAChB,GAAG,EAAE,SAAS,EACd,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,WAAW,GAClB,OAAO,CAkBT;AAED,iGAAiG;AACjG,wBAAgB,IAAI,CACnB,MAAM,EAAE,SAAS,EACjB,KAAK,EAAE,SAAS,EAChB,GAAG,EAAE,SAAS,EACd,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,WAAW,GAClB,OAAO,CAWT"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/** @returns false, touching nothing, if the price is unknown, stock is short, or coin is short */
|
|
2
|
+
export function buy(wallet, stock, bag, id, quantity, options) {
|
|
3
|
+
const price = options.prices.get(id);
|
|
4
|
+
if (!price)
|
|
5
|
+
return false;
|
|
6
|
+
const forSale = stock.find(id);
|
|
7
|
+
if (!forSale || forSale.quantity < quantity)
|
|
8
|
+
return false;
|
|
9
|
+
const cost = price.buy * quantity;
|
|
10
|
+
if (wallet.base(options.currency) < cost)
|
|
11
|
+
return false;
|
|
12
|
+
stock.remove(id, quantity);
|
|
13
|
+
if (!bag.add({ ...forSale, quantity })) {
|
|
14
|
+
stock.add({ ...forSale, quantity }); //the buyer's bag had no room - put the stock back
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
wallet.setBase(options.currency, wallet.base(options.currency) - cost);
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
/** @returns false, touching nothing, if the price is unknown or the seller lacks the quantity */
|
|
21
|
+
export function sell(wallet, stock, bag, id, quantity, options) {
|
|
22
|
+
const price = options.prices.get(id);
|
|
23
|
+
if (!price)
|
|
24
|
+
return false;
|
|
25
|
+
const item = bag.find(id);
|
|
26
|
+
if (!item || item.quantity < quantity)
|
|
27
|
+
return false;
|
|
28
|
+
bag.remove(id, quantity);
|
|
29
|
+
stock.add({ ...item, quantity });
|
|
30
|
+
wallet.setBase(options.currency, wallet.base(options.currency) + price.sell * quantity);
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=Shop.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Shop.js","sourceRoot":"","sources":["../../src/actors/Shop.ts"],"names":[],"mappings":"AAuBA,kGAAkG;AAClG,MAAM,UAAU,GAAG,CAClB,MAAiB,EACjB,KAAgB,EAChB,GAAc,EACd,EAAU,EACV,QAAgB,EAChB,OAAoB;IAEpB,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACrC,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IAEzB,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC/B,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,QAAQ,GAAG,QAAQ;QAAE,OAAO,KAAK,CAAC;IAE1D,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,GAAG,QAAQ,CAAC;IAClC,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,IAAI;QAAE,OAAO,KAAK,CAAC;IAEvD,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;IAC3B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,GAAG,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;QACxC,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,kDAAkD;QACvF,OAAO,KAAK,CAAC;IACd,CAAC;IAED,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,CAAC;IACvE,OAAO,IAAI,CAAC;AACb,CAAC;AAED,iGAAiG;AACjG,MAAM,UAAU,IAAI,CACnB,MAAiB,EACjB,KAAgB,EAChB,GAAc,EACd,EAAU,EACV,QAAgB,EAChB,OAAoB;IAEpB,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACrC,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IAEzB,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC1B,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,QAAQ,GAAG,QAAQ;QAAE,OAAO,KAAK,CAAC;IAEpD,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;IACzB,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;IACjC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,KAAK,CAAC,IAAI,GAAG,QAAQ,CAAC,CAAC;IACxF,OAAO,IAAI,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { StatBlock } from './StatBlock.ts';
|
|
2
|
+
export interface SkillPointsOptions {
|
|
3
|
+
/** the highest rank a stat can be raised to via `spend`; uncapped if omitted */
|
|
4
|
+
cap?: (stat: string) => number;
|
|
5
|
+
/** points one more rank of `stat` costs, given the rank being bought (1 for the first
|
|
6
|
+
* point spent into it, 2 for the second, and so on); a flat 1 per rank if omitted */
|
|
7
|
+
cost?: (stat: string, rank: number) => number;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* The seam `StatBlock` and `Progression` never had: a levelling curve already tells a game
|
|
11
|
+
* how many levels it just gained, and a stat block already holds any named stat a game
|
|
12
|
+
* invents - `lockpicking` exactly as well as `strength` - but nothing turns "gained a level"
|
|
13
|
+
* into "has a point to spend", or spends one with the usual rules a skill spend wants (a
|
|
14
|
+
* cap, a cost that rises the more of a stat is already bought).
|
|
15
|
+
*
|
|
16
|
+
* Deliberately not a wrapper around `Progression` itself: a game grants points from
|
|
17
|
+
* levelling (`grant(levelsGained)` after `Progression.addExperience` returns a positive
|
|
18
|
+
* number), from a quest reward, from a trainer NPC, or all three - this only tracks the
|
|
19
|
+
* ledger and the spend rule, the same way `skillCheck` is a dice roll and nothing about who
|
|
20
|
+
* is rolling it.
|
|
21
|
+
*/
|
|
22
|
+
export declare class SkillPoints {
|
|
23
|
+
private stats;
|
|
24
|
+
private capFor;
|
|
25
|
+
private costFor;
|
|
26
|
+
private available;
|
|
27
|
+
constructor(stats: StatBlock, options?: SkillPointsOptions);
|
|
28
|
+
/** points not yet spent */
|
|
29
|
+
get points(): number;
|
|
30
|
+
/** adds points to the ledger - typically levels gained times however many a level grants */
|
|
31
|
+
grant(points: number): void;
|
|
32
|
+
/** whether `stat` could be raised one more rank right now - affordable, and under its cap */
|
|
33
|
+
canSpend(stat: string): boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Raises `stat`'s base value by one rank, spending whatever that rank costs.
|
|
36
|
+
*
|
|
37
|
+
* @returns false, spending nothing, if the rank is capped or not affordable
|
|
38
|
+
*/
|
|
39
|
+
spend(stat: string): boolean;
|
|
40
|
+
/** the cost of `stat`'s next rank, or `null` if it is capped or unaffordable - computes
|
|
41
|
+
* the cost callback exactly once, so `canSpend` and `spend` never call it twice between
|
|
42
|
+
* them for the same decision */
|
|
43
|
+
private nextRankCost;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=SkillPoints.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SkillPoints.d.ts","sourceRoot":"","sources":["../../src/actors/SkillPoints.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD,MAAM,WAAW,kBAAkB;IAClC,gFAAgF;IAChF,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAE/B;yFACqF;IACrF,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CAC9C;AAED;;;;;;;;;;;;GAYG;AACH,qBAAa,WAAW;IACvB,OAAO,CAAC,KAAK,CAAY;IACzB,OAAO,CAAC,MAAM,CAA2B;IACzC,OAAO,CAAC,OAAO,CAAyC;IAExD,OAAO,CAAC,SAAS,CAAK;IAEtB,YAAY,KAAK,EAAE,SAAS,EAAE,OAAO,GAAE,kBAAuB,EAI7D;IAED,2BAA2B;IAC3B,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,4FAA4F;IAC5F,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAE1B;IAED,6FAA6F;IAC7F,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE9B;IAED;;;;OAIG;IACH,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAQ3B;IAED;;oCAEgC;IAChC,OAAO,CAAC,YAAY;CAOpB"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The seam `StatBlock` and `Progression` never had: a levelling curve already tells a game
|
|
3
|
+
* how many levels it just gained, and a stat block already holds any named stat a game
|
|
4
|
+
* invents - `lockpicking` exactly as well as `strength` - but nothing turns "gained a level"
|
|
5
|
+
* into "has a point to spend", or spends one with the usual rules a skill spend wants (a
|
|
6
|
+
* cap, a cost that rises the more of a stat is already bought).
|
|
7
|
+
*
|
|
8
|
+
* Deliberately not a wrapper around `Progression` itself: a game grants points from
|
|
9
|
+
* levelling (`grant(levelsGained)` after `Progression.addExperience` returns a positive
|
|
10
|
+
* number), from a quest reward, from a trainer NPC, or all three - this only tracks the
|
|
11
|
+
* ledger and the spend rule, the same way `skillCheck` is a dice roll and nothing about who
|
|
12
|
+
* is rolling it.
|
|
13
|
+
*/
|
|
14
|
+
export class SkillPoints {
|
|
15
|
+
constructor(stats, options = {}) {
|
|
16
|
+
this.available = 0;
|
|
17
|
+
this.stats = stats;
|
|
18
|
+
this.capFor = options.cap ?? (() => Infinity);
|
|
19
|
+
this.costFor = options.cost ?? (() => 1);
|
|
20
|
+
}
|
|
21
|
+
/** points not yet spent */
|
|
22
|
+
get points() {
|
|
23
|
+
return this.available;
|
|
24
|
+
}
|
|
25
|
+
/** adds points to the ledger - typically levels gained times however many a level grants */
|
|
26
|
+
grant(points) {
|
|
27
|
+
this.available += points;
|
|
28
|
+
}
|
|
29
|
+
/** whether `stat` could be raised one more rank right now - affordable, and under its cap */
|
|
30
|
+
canSpend(stat) {
|
|
31
|
+
return this.nextRankCost(stat) !== null;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Raises `stat`'s base value by one rank, spending whatever that rank costs.
|
|
35
|
+
*
|
|
36
|
+
* @returns false, spending nothing, if the rank is capped or not affordable
|
|
37
|
+
*/
|
|
38
|
+
spend(stat) {
|
|
39
|
+
const cost = this.nextRankCost(stat);
|
|
40
|
+
if (cost === null)
|
|
41
|
+
return false;
|
|
42
|
+
const rank = this.stats.base(stat);
|
|
43
|
+
this.available -= cost;
|
|
44
|
+
this.stats.setBase(stat, rank + 1);
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
/** the cost of `stat`'s next rank, or `null` if it is capped or unaffordable - computes
|
|
48
|
+
* the cost callback exactly once, so `canSpend` and `spend` never call it twice between
|
|
49
|
+
* them for the same decision */
|
|
50
|
+
nextRankCost(stat) {
|
|
51
|
+
const rank = this.stats.base(stat);
|
|
52
|
+
if (rank >= this.capFor(stat))
|
|
53
|
+
return null;
|
|
54
|
+
const cost = this.costFor(stat, rank + 1);
|
|
55
|
+
return this.available >= cost ? cost : null;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=SkillPoints.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SkillPoints.js","sourceRoot":"","sources":["../../src/actors/SkillPoints.ts"],"names":[],"mappings":"AAWA;;;;;;;;;;;;GAYG;AACH,MAAM,OAAO,WAAW;IAOvB,YAAY,KAAgB,EAAE,OAAO,GAAuB,EAAE;QAFtD,cAAS,GAAG,CAAC,CAAC;QAGrB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,CAAC;QAC9C,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;IAC1C,CAAC;IAED,2BAA2B;IAC3B,IAAI,MAAM;QACT,OAAO,IAAI,CAAC,SAAS,CAAC;IACvB,CAAC;IAED,4FAA4F;IAC5F,KAAK,CAAC,MAAc;QACnB,IAAI,CAAC,SAAS,IAAI,MAAM,CAAC;IAC1B,CAAC;IAED,6FAA6F;IAC7F,QAAQ,CAAC,IAAY;QACpB,OAAO,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC;IACzC,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,IAAY;QACjB,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QACrC,IAAI,IAAI,KAAK,IAAI;YAAE,OAAO,KAAK,CAAC;QAEhC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnC,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC;QACvB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,CAAC,CAAC,CAAC;QACnC,OAAO,IAAI,CAAC;IACb,CAAC;IAED;;oCAEgC;IACxB,YAAY,CAAC,IAAY;QAChC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnC,IAAI,IAAI,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;QAE3C,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,CAAC,CAAC,CAAC;QAC1C,OAAO,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;IAC7C,CAAC;CACD"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A character's numbers: base attributes, values derived from them, and the modifiers -
|
|
3
|
+
* equipment, buffs, states - that push either around.
|
|
4
|
+
*
|
|
5
|
+
* This is deliberately the *shape*, not a formula. A game names its own base attributes
|
|
6
|
+
* (`strength`, `sanity`, whatever it needs) and its own derived ones (`maxHp` from
|
|
7
|
+
* `vitality`, say); mwg supplies the machinery that combines a base value with however many
|
|
8
|
+
* modifiers are active, in a stated order, and keeps it correct as either side changes.
|
|
9
|
+
*/
|
|
10
|
+
export type Stats = Record<string, number>;
|
|
11
|
+
/** how a modifier combines with a stat's running value */
|
|
12
|
+
export type ModifierOp = 'add' | 'multiply' | 'set';
|
|
13
|
+
export interface Modifier {
|
|
14
|
+
stat: string;
|
|
15
|
+
op: ModifierOp;
|
|
16
|
+
value: number;
|
|
17
|
+
/**
|
|
18
|
+
* Modifiers apply in ascending order within their own op (see `resolve`). Equal order
|
|
19
|
+
* preserves the order they were added in.
|
|
20
|
+
*/
|
|
21
|
+
order?: number;
|
|
22
|
+
/** whatever granted this modifier - an equipped item, an active buff - for bulk removal */
|
|
23
|
+
source?: unknown;
|
|
24
|
+
}
|
|
25
|
+
export interface DerivedStat {
|
|
26
|
+
name: string;
|
|
27
|
+
/** reads every base attribute and any derived stat already resolved earlier in the list */
|
|
28
|
+
from: (stats: Readonly<Stats>) => number;
|
|
29
|
+
}
|
|
30
|
+
export interface StatBlockOptions {
|
|
31
|
+
base: Stats;
|
|
32
|
+
derived?: DerivedStat[];
|
|
33
|
+
}
|
|
34
|
+
export declare class StatBlock {
|
|
35
|
+
private baseValues;
|
|
36
|
+
private derived;
|
|
37
|
+
private modifiers;
|
|
38
|
+
private cache;
|
|
39
|
+
constructor(options: StatBlockOptions);
|
|
40
|
+
/** the unmodified base value; 0 for a name that was never given one */
|
|
41
|
+
base(name: string): number;
|
|
42
|
+
setBase(name: string, value: number): void;
|
|
43
|
+
addModifier(modifier: Modifier): void;
|
|
44
|
+
removeModifier(modifier: Modifier): void;
|
|
45
|
+
/** removes every modifier carrying this `source`, such as an item just unequipped */
|
|
46
|
+
removeModifiersFrom(source: unknown): void;
|
|
47
|
+
/** the final value: a base attribute or a derived stat, with every modifier resolved */
|
|
48
|
+
get(name: string): number;
|
|
49
|
+
private resolveAll;
|
|
50
|
+
private modifiersFor;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=StatBlock.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StatBlock.d.ts","sourceRoot":"","sources":["../../src/actors/StatBlock.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAE3C,0DAA0D;AAC1D,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,UAAU,GAAG,KAAK,CAAC;AAEpD,MAAM,WAAW,QAAQ;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,UAAU,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IAEd;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,2FAA2F;IAC3F,MAAM,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,2FAA2F;IAC3F,IAAI,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,KAAK,MAAM,CAAC;CACzC;AAED,MAAM,WAAW,gBAAgB;IAChC,IAAI,EAAE,KAAK,CAAC;IACZ,OAAO,CAAC,EAAE,WAAW,EAAE,CAAC;CACxB;AAqBD,qBAAa,SAAS;IACrB,OAAO,CAAC,UAAU,CAAQ;IAC1B,OAAO,CAAC,OAAO,CAAgB;IAC/B,OAAO,CAAC,SAAS,CAAkB;IACnC,OAAO,CAAC,KAAK,CAAsB;IAEnC,YAAY,OAAO,EAAE,gBAAgB,EAGpC;IAED,uEAAuE;IACvE,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEzB;IAED,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAGzC;IAED,WAAW,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAGpC;IAED,cAAc,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAIvC;IAED,qFAAqF;IACrF,mBAAmB,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAGzC;IAED,wFAAwF;IACxF,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAExB;IAED,OAAO,CAAC,UAAU;IAelB,OAAO,CAAC,YAAY;CAGpB"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A character's numbers: base attributes, values derived from them, and the modifiers -
|
|
3
|
+
* equipment, buffs, states - that push either around.
|
|
4
|
+
*
|
|
5
|
+
* This is deliberately the *shape*, not a formula. A game names its own base attributes
|
|
6
|
+
* (`strength`, `sanity`, whatever it needs) and its own derived ones (`maxHp` from
|
|
7
|
+
* `vitality`, say); mwg supplies the machinery that combines a base value with however many
|
|
8
|
+
* modifiers are active, in a stated order, and keeps it correct as either side changes.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Resolves one stat's modifiers into a single number.
|
|
12
|
+
*
|
|
13
|
+
* Every `add` modifier applies first (summed together), then every `multiply` (each
|
|
14
|
+
* scaling the running total), then every `set` (the last one wins) - a stated, fixed order,
|
|
15
|
+
* so a +10% ring and a cursed -2 sword combine the same way regardless of equip order, and
|
|
16
|
+
* a `set` modifier (a polymorph, a stat drained to exactly zero) always wins over the rest.
|
|
17
|
+
*/
|
|
18
|
+
function resolve(base, modifiers) {
|
|
19
|
+
const byOp = (op) => modifiers.filter((m) => m.op === op).sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
|
|
20
|
+
let value = base;
|
|
21
|
+
for (const m of byOp('add'))
|
|
22
|
+
value += m.value;
|
|
23
|
+
for (const m of byOp('multiply'))
|
|
24
|
+
value *= m.value;
|
|
25
|
+
for (const m of byOp('set'))
|
|
26
|
+
value = m.value;
|
|
27
|
+
return value;
|
|
28
|
+
}
|
|
29
|
+
export class StatBlock {
|
|
30
|
+
constructor(options) {
|
|
31
|
+
this.modifiers = [];
|
|
32
|
+
this.cache = null;
|
|
33
|
+
this.baseValues = { ...options.base };
|
|
34
|
+
this.derived = options.derived ?? [];
|
|
35
|
+
}
|
|
36
|
+
/** the unmodified base value; 0 for a name that was never given one */
|
|
37
|
+
base(name) {
|
|
38
|
+
return this.baseValues[name] ?? 0;
|
|
39
|
+
}
|
|
40
|
+
setBase(name, value) {
|
|
41
|
+
this.baseValues[name] = value;
|
|
42
|
+
this.cache = null;
|
|
43
|
+
}
|
|
44
|
+
addModifier(modifier) {
|
|
45
|
+
this.modifiers.push(modifier);
|
|
46
|
+
this.cache = null;
|
|
47
|
+
}
|
|
48
|
+
removeModifier(modifier) {
|
|
49
|
+
const i = this.modifiers.indexOf(modifier);
|
|
50
|
+
if (i !== -1)
|
|
51
|
+
this.modifiers.splice(i, 1);
|
|
52
|
+
this.cache = null;
|
|
53
|
+
}
|
|
54
|
+
/** removes every modifier carrying this `source`, such as an item just unequipped */
|
|
55
|
+
removeModifiersFrom(source) {
|
|
56
|
+
this.modifiers = this.modifiers.filter((m) => m.source !== source);
|
|
57
|
+
this.cache = null;
|
|
58
|
+
}
|
|
59
|
+
/** the final value: a base attribute or a derived stat, with every modifier resolved */
|
|
60
|
+
get(name) {
|
|
61
|
+
return this.resolveAll()[name] ?? 0;
|
|
62
|
+
}
|
|
63
|
+
resolveAll() {
|
|
64
|
+
if (this.cache)
|
|
65
|
+
return this.cache;
|
|
66
|
+
const result = { ...this.baseValues };
|
|
67
|
+
for (const name of Object.keys(result)) {
|
|
68
|
+
result[name] = resolve(result[name], this.modifiersFor(name));
|
|
69
|
+
}
|
|
70
|
+
for (const d of this.derived) {
|
|
71
|
+
result[d.name] = resolve(d.from(result), this.modifiersFor(d.name));
|
|
72
|
+
}
|
|
73
|
+
this.cache = result;
|
|
74
|
+
return result;
|
|
75
|
+
}
|
|
76
|
+
modifiersFor(stat) {
|
|
77
|
+
return this.modifiers.filter((m) => m.stat === stat);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=StatBlock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StatBlock.js","sourceRoot":"","sources":["../../src/actors/StatBlock.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAiCH;;;;;;;GAOG;AACH,SAAS,OAAO,CAAC,IAAY,EAAE,SAA8B;IAC5D,MAAM,IAAI,GAAG,CAAC,EAAc,EAAE,EAAE,CAC/B,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC;IAEtF,IAAI,KAAK,GAAG,IAAI,CAAC;IACjB,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC;QAAE,KAAK,IAAI,CAAC,CAAC,KAAK,CAAC;IAC9C,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC;QAAE,KAAK,IAAI,CAAC,CAAC,KAAK,CAAC;IACnD,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC;QAAE,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC;IAC7C,OAAO,KAAK,CAAC;AACd,CAAC;AAED,MAAM,OAAO,SAAS;IAMrB,YAAY,OAAyB;QAH7B,cAAS,GAAe,EAAE,CAAC;QAC3B,UAAK,GAAiB,IAAI,CAAC;QAGlC,IAAI,CAAC,UAAU,GAAG,EAAE,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;QACtC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC;IACtC,CAAC;IAED,uEAAuE;IACvE,IAAI,CAAC,IAAY;QAChB,OAAO,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACnC,CAAC;IAED,OAAO,CAAC,IAAY,EAAE,KAAa;QAClC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;QAC9B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;IACnB,CAAC;IAED,WAAW,CAAC,QAAkB;QAC7B,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC9B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;IACnB,CAAC;IAED,cAAc,CAAC,QAAkB;QAChC,MAAM,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC3C,IAAI,CAAC,KAAK,CAAC,CAAC;YAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC1C,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;IACnB,CAAC;IAED,qFAAqF;IACrF,mBAAmB,CAAC,MAAe;QAClC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;QACnE,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;IACnB,CAAC;IAED,wFAAwF;IACxF,GAAG,CAAC,IAAY;QACf,OAAO,IAAI,CAAC,UAAU,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrC,CAAC;IAEO,UAAU;QACjB,IAAI,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAC,KAAK,CAAC;QAElC,MAAM,MAAM,GAAU,EAAE,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;QAC7C,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YACxC,MAAM,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC;QAC/D,CAAC;QACD,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAC9B,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QACrE,CAAC;QAED,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC;QACpB,OAAO,MAAM,CAAC;IACf,CAAC;IAEO,YAAY,CAAC,IAAY;QAChC,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;IACtD,CAAC;CACD"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { StatBlock, type Modifier } from './StatBlock.ts';
|
|
2
|
+
/**
|
|
3
|
+
* The shape `TurnClock.add` needs - declared here rather than imported from `mwg/world`, so
|
|
4
|
+
* `mwg/actors` stays independent of it the same way every other pair of sibling modules is;
|
|
5
|
+
* `TurnClock` already satisfies this structurally, with nothing to wire up on its side.
|
|
6
|
+
*/
|
|
7
|
+
export interface EffectClock {
|
|
8
|
+
add(effect: {
|
|
9
|
+
tick: (turn: number) => void;
|
|
10
|
+
duration?: number;
|
|
11
|
+
onExpire?: () => void;
|
|
12
|
+
}): symbol;
|
|
13
|
+
remove(id: symbol): void;
|
|
14
|
+
}
|
|
15
|
+
export interface StatusEffectOptions {
|
|
16
|
+
/** applied for the duration, then removed automatically - `source` is filled in, not given */
|
|
17
|
+
modifiers: readonly Omit<Modifier, 'source'>[];
|
|
18
|
+
/** turns until the modifiers are removed */
|
|
19
|
+
duration: number;
|
|
20
|
+
/** called once per turn the effect is active, such as a poison tick's own damage */
|
|
21
|
+
tick?: (turn: number) => void;
|
|
22
|
+
}
|
|
23
|
+
/** ends a `StatusEffect` early, removing its modifiers immediately rather than at expiry */
|
|
24
|
+
export interface StatusEffectHandle {
|
|
25
|
+
cancel(): void;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* A temporary buff or debuff: applies `modifiers` to `stats` and registers their expiry with
|
|
29
|
+
* `clock`, so a game never has to remember to remove what it added. The seam `TurnClock` and
|
|
30
|
+
* `StatBlock` never had on their own - `TurnClock` ticks and expires effects, `StatBlock`
|
|
31
|
+
* resolves modifiers, but nothing tied one's expiry to the other's removal.
|
|
32
|
+
*
|
|
33
|
+
* `cancel()` on the returned handle removes the modifiers immediately and unregisters the
|
|
34
|
+
* clock entry - needed because `TurnClock.remove` alone only stops future ticks, it does not
|
|
35
|
+
* know this entry ever touched a `StatBlock` at all.
|
|
36
|
+
*/
|
|
37
|
+
export declare function applyStatusEffect(stats: StatBlock, clock: EffectClock, options: StatusEffectOptions): StatusEffectHandle;
|
|
38
|
+
//# sourceMappingURL=StatusEffect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StatusEffect.d.ts","sourceRoot":"","sources":["../../src/actors/StatusEffect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE1D;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC3B,GAAG,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;KAAE,GAAG,MAAM,CAAC;IAChG,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,MAAM,WAAW,mBAAmB;IACnC,8FAA8F;IAC9F,SAAS,EAAE,SAAS,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE,CAAC;IAE/C,4CAA4C;IAC5C,QAAQ,EAAE,MAAM,CAAC;IAEjB,oFAAoF;IACpF,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC9B;AAED,4FAA4F;AAC5F,MAAM,WAAW,kBAAkB;IAClC,MAAM,IAAI,IAAI,CAAC;CACf;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAChC,KAAK,EAAE,SAAS,EAChB,KAAK,EAAE,WAAW,EAClB,OAAO,EAAE,mBAAmB,GAC1B,kBAAkB,CAgBpB"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { StatBlock } from './StatBlock.js';
|
|
2
|
+
/**
|
|
3
|
+
* A temporary buff or debuff: applies `modifiers` to `stats` and registers their expiry with
|
|
4
|
+
* `clock`, so a game never has to remember to remove what it added. The seam `TurnClock` and
|
|
5
|
+
* `StatBlock` never had on their own - `TurnClock` ticks and expires effects, `StatBlock`
|
|
6
|
+
* resolves modifiers, but nothing tied one's expiry to the other's removal.
|
|
7
|
+
*
|
|
8
|
+
* `cancel()` on the returned handle removes the modifiers immediately and unregisters the
|
|
9
|
+
* clock entry - needed because `TurnClock.remove` alone only stops future ticks, it does not
|
|
10
|
+
* know this entry ever touched a `StatBlock` at all.
|
|
11
|
+
*/
|
|
12
|
+
export function applyStatusEffect(stats, clock, options) {
|
|
13
|
+
const source = Symbol('statusEffect');
|
|
14
|
+
for (const modifier of options.modifiers)
|
|
15
|
+
stats.addModifier({ ...modifier, source });
|
|
16
|
+
const id = clock.add({
|
|
17
|
+
duration: options.duration,
|
|
18
|
+
tick: (turn) => options.tick?.(turn),
|
|
19
|
+
onExpire: () => stats.removeModifiersFrom(source),
|
|
20
|
+
});
|
|
21
|
+
return {
|
|
22
|
+
cancel: () => {
|
|
23
|
+
clock.remove(id);
|
|
24
|
+
stats.removeModifiersFrom(source);
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=StatusEffect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StatusEffect.js","sourceRoot":"","sources":["../../src/actors/StatusEffect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAiB,MAAM,gBAAgB,CAAC;AA4B1D;;;;;;;;;GASG;AACH,MAAM,UAAU,iBAAiB,CAChC,KAAgB,EAChB,KAAkB,EAClB,OAA4B;IAE5B,MAAM,MAAM,GAAG,MAAM,CAAC,cAAc,CAAC,CAAC;IACtC,KAAK,MAAM,QAAQ,IAAI,OAAO,CAAC,SAAS;QAAE,KAAK,CAAC,WAAW,CAAC,EAAE,GAAG,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;IAErF,MAAM,EAAE,GAAG,KAAK,CAAC,GAAG,CAAC;QACpB,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,IAAI,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC;QACpC,QAAQ,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,mBAAmB,CAAC,MAAM,CAAC;KACjD,CAAC,CAAC;IAEH,OAAO;QACN,MAAM,EAAE,GAAG,EAAE;YACZ,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YACjB,KAAK,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC;QACnC,CAAC;KACD,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Inventory, InventoryItem } from './Inventory.ts';
|
|
2
|
+
export interface Recipe {
|
|
3
|
+
/** what gets consumed, by id and how much of each */
|
|
4
|
+
ingredients: Array<{
|
|
5
|
+
id: string;
|
|
6
|
+
quantity: number;
|
|
7
|
+
}>;
|
|
8
|
+
/** what one crafting resolves to - a full item, since it needs its own weight/stackable */
|
|
9
|
+
result: InventoryItem;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Resolves a recipe against an inventory: every ingredient checked, consumed, and the
|
|
13
|
+
* result added, all in one call - the same small-focused-function shape `skillCheck`
|
|
14
|
+
* already is, not a crafting subsystem of its own. `Inventory` only ever stacks, weighs and
|
|
15
|
+
* adds/removes what a game already hands it; nothing there turns one stack of items into a
|
|
16
|
+
* different one, which is the entire gap this closes.
|
|
17
|
+
*
|
|
18
|
+
* All or nothing: if any ingredient is missing or too few, nothing is touched. If every
|
|
19
|
+
* ingredient is present but the result would not fit (`Inventory`'s own capacity, unrelated
|
|
20
|
+
* to crafting itself), the ingredients are put back exactly as they were rather than being
|
|
21
|
+
* spent for nothing.
|
|
22
|
+
*
|
|
23
|
+
* @returns whether the recipe resolved
|
|
24
|
+
*/
|
|
25
|
+
export declare function craft(inventory: Inventory, recipe: Recipe): boolean;
|
|
26
|
+
//# sourceMappingURL=craft.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"craft.d.ts","sourceRoot":"","sources":["../../src/actors/craft.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE/D,MAAM,WAAW,MAAM;IACtB,qDAAqD;IACrD,WAAW,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAErD,2FAA2F;IAC3F,MAAM,EAAE,aAAa,CAAC;CACtB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,KAAK,CAAC,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAiBnE"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolves a recipe against an inventory: every ingredient checked, consumed, and the
|
|
3
|
+
* result added, all in one call - the same small-focused-function shape `skillCheck`
|
|
4
|
+
* already is, not a crafting subsystem of its own. `Inventory` only ever stacks, weighs and
|
|
5
|
+
* adds/removes what a game already hands it; nothing there turns one stack of items into a
|
|
6
|
+
* different one, which is the entire gap this closes.
|
|
7
|
+
*
|
|
8
|
+
* All or nothing: if any ingredient is missing or too few, nothing is touched. If every
|
|
9
|
+
* ingredient is present but the result would not fit (`Inventory`'s own capacity, unrelated
|
|
10
|
+
* to crafting itself), the ingredients are put back exactly as they were rather than being
|
|
11
|
+
* spent for nothing.
|
|
12
|
+
*
|
|
13
|
+
* @returns whether the recipe resolved
|
|
14
|
+
*/
|
|
15
|
+
export function craft(inventory, recipe) {
|
|
16
|
+
for (const ingredient of recipe.ingredients) {
|
|
17
|
+
const held = inventory.find(ingredient.id);
|
|
18
|
+
if (!held || held.quantity < ingredient.quantity)
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
//captured before anything is removed, so a failed add below can restore exactly this
|
|
22
|
+
const consumed = recipe.ingredients.map((ingredient) => ({
|
|
23
|
+
...inventory.find(ingredient.id),
|
|
24
|
+
quantity: ingredient.quantity,
|
|
25
|
+
}));
|
|
26
|
+
for (const ingredient of recipe.ingredients)
|
|
27
|
+
inventory.remove(ingredient.id, ingredient.quantity);
|
|
28
|
+
if (inventory.add(recipe.result))
|
|
29
|
+
return true;
|
|
30
|
+
for (const item of consumed)
|
|
31
|
+
inventory.add(item);
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=craft.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"craft.js","sourceRoot":"","sources":["../../src/actors/craft.ts"],"names":[],"mappings":"AAUA;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,KAAK,CAAC,SAAoB,EAAE,MAAc;IACzD,KAAK,MAAM,UAAU,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;QAC7C,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;QAC3C,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,QAAQ,GAAG,UAAU,CAAC,QAAQ;YAAE,OAAO,KAAK,CAAC;IAChE,CAAC;IAED,qFAAqF;IACrF,MAAM,QAAQ,GAAG,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;QACxD,GAAG,SAAS,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAE;QACjC,QAAQ,EAAE,UAAU,CAAC,QAAQ;KAC7B,CAAC,CAAC,CAAC;IAEJ,KAAK,MAAM,UAAU,IAAI,MAAM,CAAC,WAAW;QAAE,SAAS,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC;IAClG,IAAI,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC;QAAE,OAAO,IAAI,CAAC;IAE9C,KAAK,MAAM,IAAI,IAAI,QAAQ;QAAE,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACjD,OAAO,KAAK,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export { StatBlock } from './StatBlock.ts';
|
|
2
|
+
export type { Stats, Modifier, ModifierOp, DerivedStat, StatBlockOptions } from './StatBlock.ts';
|
|
3
|
+
export { Progression, powerCurve } from './Progression.ts';
|
|
4
|
+
export type { GrowthCurve } from './Progression.ts';
|
|
5
|
+
export { skillCheck } from './skillCheck.ts';
|
|
6
|
+
export { SkillPoints } from './SkillPoints.ts';
|
|
7
|
+
export type { SkillPointsOptions } from './SkillPoints.ts';
|
|
8
|
+
export { EquipmentSlots } from './Equipment.ts';
|
|
9
|
+
export type { EquippableItem, EquipmentOptions } from './Equipment.ts';
|
|
10
|
+
export { Inventory } from './Inventory.ts';
|
|
11
|
+
export type { InventoryItem, InventoryOptions } from './Inventory.ts';
|
|
12
|
+
export { craft } from './craft.ts';
|
|
13
|
+
export type { Recipe } from './craft.ts';
|
|
14
|
+
export { applyStatusEffect } from './StatusEffect.ts';
|
|
15
|
+
export type { EffectClock, StatusEffectOptions, StatusEffectHandle } from './StatusEffect.ts';
|
|
16
|
+
export { identify, enchant, damageItem, repairItem } from './ItemState.ts';
|
|
17
|
+
export { Charges } from './Charges.ts';
|
|
18
|
+
export type { ChargesOptions } from './Charges.ts';
|
|
19
|
+
export { rollLoot } from './Loot.ts';
|
|
20
|
+
export type { LootEntry, LootTable } from './Loot.ts';
|
|
21
|
+
export { Advancement } from './Advancement.ts';
|
|
22
|
+
export type { AdvancementOption, AdvancementTier, AdvancementTierKind, AdvancementTrack } from './Advancement.ts';
|
|
23
|
+
export { rollAffix, affixOf, applyAffix, removeAffix } from './Affix.ts';
|
|
24
|
+
export type { AffixDef, AffixTable, AffixTrigger } from './Affix.ts';
|
|
25
|
+
export { scaledModifiers } from './Scaling.ts';
|
|
26
|
+
export type { LevelScale } from './Scaling.ts';
|
|
27
|
+
export { assignAppearances, Appearances } from './Appearances.ts';
|
|
28
|
+
export type { AppearanceTable } from './Appearances.ts';
|
|
29
|
+
export { buy, sell } from './Shop.ts';
|
|
30
|
+
export type { Price, ShopOptions } from './Shop.ts';
|
|
31
|
+
export { canAfford, spend } from './Resource.ts';
|
|
32
|
+
export type { ResourceCost } from './Resource.ts';
|
|
33
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/actors/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,YAAY,EAAE,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACjG,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC3D,YAAY,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,YAAY,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,YAAY,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACvE,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,YAAY,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACtE,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,YAAY,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,YAAY,EAAE,WAAW,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAC9F,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC3E,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,YAAY,EAAE,iBAAiB,EAAE,eAAe,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAClH,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzE,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,YAAY,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAClE,YAAY,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACtC,YAAY,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACjD,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export { StatBlock } from './StatBlock.js';
|
|
2
|
+
export { Progression, powerCurve } from './Progression.js';
|
|
3
|
+
export { skillCheck } from './skillCheck.js';
|
|
4
|
+
export { SkillPoints } from './SkillPoints.js';
|
|
5
|
+
export { EquipmentSlots } from './Equipment.js';
|
|
6
|
+
export { Inventory } from './Inventory.js';
|
|
7
|
+
export { craft } from './craft.js';
|
|
8
|
+
export { applyStatusEffect } from './StatusEffect.js';
|
|
9
|
+
export { identify, enchant, damageItem, repairItem } from './ItemState.js';
|
|
10
|
+
export { Charges } from './Charges.js';
|
|
11
|
+
export { rollLoot } from './Loot.js';
|
|
12
|
+
export { Advancement } from './Advancement.js';
|
|
13
|
+
export { rollAffix, affixOf, applyAffix, removeAffix } from './Affix.js';
|
|
14
|
+
export { scaledModifiers } from './Scaling.js';
|
|
15
|
+
export { assignAppearances, Appearances } from './Appearances.js';
|
|
16
|
+
export { buy, sell } from './Shop.js';
|
|
17
|
+
export { canAfford, spend } from './Resource.js';
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/actors/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE3D,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEhD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAEtD,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC3E,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAErC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzE,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAElE,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEtC,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A skill checked against a difficulty.
|
|
3
|
+
*
|
|
4
|
+
* The default mechanic - a proficiency plus a die roll, compared against a target number -
|
|
5
|
+
* is deliberately the simplest one that exists, because it is a shape every game recognises
|
|
6
|
+
* and every game also wants to replace with its own dice. Pass `roll` to use anything else;
|
|
7
|
+
* the default draws from `mwg/core`'s seeded RNG, so a check replays the same way from a
|
|
8
|
+
* save file.
|
|
9
|
+
*
|
|
10
|
+
* @returns true if the check succeeds
|
|
11
|
+
*/
|
|
12
|
+
export declare function skillCheck(value: number, difficulty: number, roll?: () => number): boolean;
|
|
13
|
+
//# sourceMappingURL=skillCheck.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skillCheck.d.ts","sourceRoot":"","sources":["../../src/actors/skillCheck.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CACzB,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,MAAM,EAClB,IAAI,GAAE,MAAM,MAAkC,GAC5C,OAAO,CAET"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import * as Random from '../core/Random.js';
|
|
2
|
+
/**
|
|
3
|
+
* A skill checked against a difficulty.
|
|
4
|
+
*
|
|
5
|
+
* The default mechanic - a proficiency plus a die roll, compared against a target number -
|
|
6
|
+
* is deliberately the simplest one that exists, because it is a shape every game recognises
|
|
7
|
+
* and every game also wants to replace with its own dice. Pass `roll` to use anything else;
|
|
8
|
+
* the default draws from `mwg/core`'s seeded RNG, so a check replays the same way from a
|
|
9
|
+
* save file.
|
|
10
|
+
*
|
|
11
|
+
* @returns true if the check succeeds
|
|
12
|
+
*/
|
|
13
|
+
export function skillCheck(value, difficulty, roll = () => Random.range(1, 20)) {
|
|
14
|
+
return value + roll() >= difficulty;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=skillCheck.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skillCheck.js","sourceRoot":"","sources":["../../src/actors/skillCheck.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,mBAAmB,CAAC;AAE5C;;;;;;;;;;GAUG;AACH,MAAM,UAAU,UAAU,CACzB,KAAa,EACb,UAAkB,EAClB,IAAI,GAAiB,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;IAE9C,OAAO,KAAK,GAAG,IAAI,EAAE,IAAI,UAAU,CAAC;AACrC,CAAC"}
|