@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,173 @@
|
|
|
1
|
+
import { Sprite, ExtensionType, extensions } from 'pixi.js';
|
|
2
|
+
import { ColorTransformBatcher, packColorAdd, packTintAdd } from './ColorTransformBatcher.js';
|
|
3
|
+
const TINTED_SPRITE_PIPE = 'mwg-tinted-sprite';
|
|
4
|
+
/**
|
|
5
|
+
* A sprite that can be pulled *towards* a colour, not just darkened.
|
|
6
|
+
*
|
|
7
|
+
* `tint` multiplies, as it does on any Pixi sprite. `colorAdd` is added on top, which is
|
|
8
|
+
* what makes effects like these possible:
|
|
9
|
+
*
|
|
10
|
+
* ```ts
|
|
11
|
+
* const rat = new TintedSprite({ texture });
|
|
12
|
+
* rat.lerpTint(0x00ff00, 0.5); // half-way to green: poisoned
|
|
13
|
+
* rat.flash(0xffffff, 0.8); // nearly white: just took a hit
|
|
14
|
+
* rat.tint = 0x404060; // plain multiply: standing in the dark
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* Both terms ride in the same batch, so a screen full of tinted sprites is still one draw
|
|
18
|
+
* call. See ColorTransformBatcher for how, and for the caveat about Pixi internals.
|
|
19
|
+
*/
|
|
20
|
+
export class TintedSprite extends Sprite {
|
|
21
|
+
constructor(options) {
|
|
22
|
+
super(options);
|
|
23
|
+
this._colorAdd = 0;
|
|
24
|
+
//Sprite's constructor points this at Pixi's own pipe; redirect it to ours, which
|
|
25
|
+
//is what puts this sprite in the colour-transform batch
|
|
26
|
+
this.renderPipeId = TINTED_SPRITE_PIPE;
|
|
27
|
+
}
|
|
28
|
+
/** the packed additive colour; use `setColorAdd` or `lerpTint` rather than setting it raw */
|
|
29
|
+
get colorAdd() {
|
|
30
|
+
return this._colorAdd;
|
|
31
|
+
}
|
|
32
|
+
set colorAdd(value) {
|
|
33
|
+
if (this._colorAdd === value)
|
|
34
|
+
return;
|
|
35
|
+
this._colorAdd = value;
|
|
36
|
+
//the vertex data holds the packed colour, so the batch has to be repacked
|
|
37
|
+
this.onViewUpdate();
|
|
38
|
+
}
|
|
39
|
+
/** @param r @param g @param b each 0 to 1 @param a extra alpha to add, usually 0 */
|
|
40
|
+
setColorAdd(r, g, b, a = 0) {
|
|
41
|
+
this.colorAdd = packColorAdd(r, g, b, a);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Moves the sprite `strength` of the way towards `color`, leaving its shading intact.
|
|
45
|
+
*
|
|
46
|
+
* This sets both halves of the transform: the tint carries `1 - strength` and the
|
|
47
|
+
* additive term carries `color × strength`.
|
|
48
|
+
*/
|
|
49
|
+
lerpTint(color, strength) {
|
|
50
|
+
const keep = Math.round((1 - strength) * 0xff);
|
|
51
|
+
this.tint = (keep << 16) | (keep << 8) | keep;
|
|
52
|
+
this.colorAdd = packTintAdd(color, strength);
|
|
53
|
+
}
|
|
54
|
+
/** a solid silhouette in `color`, keeping only the sprite's shape */
|
|
55
|
+
silhouette(color) {
|
|
56
|
+
this.tint = 0x000000;
|
|
57
|
+
this.colorAdd = packTintAdd(color, 1);
|
|
58
|
+
}
|
|
59
|
+
/** back to the texture's own colours */
|
|
60
|
+
resetColor() {
|
|
61
|
+
this.tint = 0xffffff;
|
|
62
|
+
this.colorAdd = 0;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Routes TintedSprite through the colour-transform batcher.
|
|
67
|
+
*
|
|
68
|
+
* Pixi decides which batcher an object joins from `batcherName` on its batchable element,
|
|
69
|
+
* and that element is built by a render pipe. So selecting a different batcher means
|
|
70
|
+
* supplying a pipe; this one mirrors Pixi's own SpritePipe and changes two things: the
|
|
71
|
+
* batcher name, and copying `colorAdd` across before each pack.
|
|
72
|
+
*/
|
|
73
|
+
class TintedSpritePipe {
|
|
74
|
+
/** @internal */
|
|
75
|
+
static { this.extension = {
|
|
76
|
+
type: [ExtensionType.WebGLPipes, ExtensionType.WebGPUPipes, ExtensionType.CanvasPipes],
|
|
77
|
+
name: TINTED_SPRITE_PIPE,
|
|
78
|
+
}; }
|
|
79
|
+
constructor(renderer) {
|
|
80
|
+
this.renderer = renderer;
|
|
81
|
+
}
|
|
82
|
+
addRenderable(sprite, instructionSet) {
|
|
83
|
+
const element = this.element(sprite);
|
|
84
|
+
if (sprite.didViewUpdate)
|
|
85
|
+
this.sync(sprite, element);
|
|
86
|
+
this.renderer.renderPipes.batch.addToBatch(element, instructionSet);
|
|
87
|
+
}
|
|
88
|
+
updateRenderable(sprite) {
|
|
89
|
+
const element = this.element(sprite);
|
|
90
|
+
if (sprite.didViewUpdate)
|
|
91
|
+
this.sync(sprite, element);
|
|
92
|
+
element._batcher.updateElement(element);
|
|
93
|
+
}
|
|
94
|
+
validateRenderable(sprite) {
|
|
95
|
+
const element = this.element(sprite);
|
|
96
|
+
return !element._batcher.checkAndUpdateTexture(element, sprite.texture);
|
|
97
|
+
}
|
|
98
|
+
sync(sprite, element) {
|
|
99
|
+
element.bounds = sprite.visualBounds;
|
|
100
|
+
element.texture = sprite.texture;
|
|
101
|
+
element.colorAdd = sprite.colorAdd;
|
|
102
|
+
}
|
|
103
|
+
element(sprite) {
|
|
104
|
+
const gpuData = sprite._gpuData;
|
|
105
|
+
return gpuData[this.renderer.uid] ?? this.create(sprite, gpuData);
|
|
106
|
+
}
|
|
107
|
+
create(sprite, gpuData) {
|
|
108
|
+
const element = new BatchableTintedSprite();
|
|
109
|
+
element.renderable = sprite;
|
|
110
|
+
element.transform = sprite.groupTransform;
|
|
111
|
+
element.texture = sprite.texture;
|
|
112
|
+
element.bounds = sprite.visualBounds;
|
|
113
|
+
element.roundPixels = (this.renderer._roundPixels |
|
|
114
|
+
sprite._roundPixels);
|
|
115
|
+
element.colorAdd = sprite.colorAdd;
|
|
116
|
+
gpuData[this.renderer.uid] = element;
|
|
117
|
+
return element;
|
|
118
|
+
}
|
|
119
|
+
destroy() {
|
|
120
|
+
this.renderer = null;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/** the same shape as Pixi's BatchableSprite, plus the additive colour */
|
|
124
|
+
class BatchableTintedSprite {
|
|
125
|
+
constructor() {
|
|
126
|
+
this.batcherName = ColorTransformBatcher.extension.name;
|
|
127
|
+
this.topology = 'triangle-list';
|
|
128
|
+
this.attributeSize = 4;
|
|
129
|
+
this.indexSize = 6;
|
|
130
|
+
this.packAsQuad = true;
|
|
131
|
+
this.roundPixels = 0;
|
|
132
|
+
this.colorAdd = 0;
|
|
133
|
+
//Pixi fills these in while batching; they exist on its own element type too
|
|
134
|
+
this._attributeStart = 0;
|
|
135
|
+
this._textureId = 0;
|
|
136
|
+
this._indexStart = 0;
|
|
137
|
+
this._batcher = null;
|
|
138
|
+
this._batch = null;
|
|
139
|
+
}
|
|
140
|
+
get blendMode() {
|
|
141
|
+
return this.renderable.groupBlendMode;
|
|
142
|
+
}
|
|
143
|
+
get color() {
|
|
144
|
+
return this.renderable.groupColorAlpha;
|
|
145
|
+
}
|
|
146
|
+
reset() {
|
|
147
|
+
this.renderable = null;
|
|
148
|
+
this.texture = null;
|
|
149
|
+
this._batcher = null;
|
|
150
|
+
this._batch = null;
|
|
151
|
+
this.bounds = null;
|
|
152
|
+
this.colorAdd = 0;
|
|
153
|
+
}
|
|
154
|
+
destroy() {
|
|
155
|
+
this.reset();
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
let registered = false;
|
|
159
|
+
/**
|
|
160
|
+
* Registers the batcher and pipe with Pixi.
|
|
161
|
+
*
|
|
162
|
+
* Called automatically the first time a TintedSprite is rendered is not possible, because
|
|
163
|
+
* registration has to happen before the renderer is created — so `Game` calls this during
|
|
164
|
+
* start-up, and it is exported for anyone building their own renderer.
|
|
165
|
+
*/
|
|
166
|
+
export function registerColorTransform() {
|
|
167
|
+
if (registered)
|
|
168
|
+
return;
|
|
169
|
+
registered = true;
|
|
170
|
+
extensions.add(ColorTransformBatcher);
|
|
171
|
+
extensions.add(TintedSpritePipe);
|
|
172
|
+
}
|
|
173
|
+
//# sourceMappingURL=TintedSprite.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TintedSprite.js","sourceRoot":"","sources":["../../src/render/TintedSprite.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export { ColorTransformBatcher, packColorAdd, packTintAdd, NO_COLOR_ADD, } from './ColorTransformBatcher.ts';
|
|
2
|
+
export type { HasColorAdd } from './ColorTransformBatcher.ts';
|
|
3
|
+
export { TintedSprite, registerColorTransform } from './TintedSprite.ts';
|
|
4
|
+
export { AnimatedSprite, Animation } from './AnimatedSprite.ts';
|
|
5
|
+
export type { AnimationOptions } from './AnimatedSprite.ts';
|
|
6
|
+
export { SpriteSheet } from './SpriteSheet.ts';
|
|
7
|
+
export { Camera, createCamera } from './Camera.ts';
|
|
8
|
+
export type { CameraOptions } from './Camera.ts';
|
|
9
|
+
export { TileMap, EMPTY, tileFrame, tileFrameSheet, tileFrameIndex } from './TileMap.ts';
|
|
10
|
+
export type { TileMapOptions } from './TileMap.ts';
|
|
11
|
+
export { LayeredSprite } from './LayeredSprite.ts';
|
|
12
|
+
export { Projectile } from './Projectile.ts';
|
|
13
|
+
export type { ProjectilePoint, ProjectileOptions } from './Projectile.ts';
|
|
14
|
+
export { ActorAnimator } from './ActorAnimator.ts';
|
|
15
|
+
export type { ActorAnimationState, ActorAnimatorOptions } from './ActorAnimator.ts';
|
|
16
|
+
export { blobIndex, autotileFrames, BLOB_SHAPES } from './Autotile.ts';
|
|
17
|
+
export type { NeighborMask } from './Autotile.ts';
|
|
18
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/render/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,qBAAqB,EACrB,YAAY,EACZ,WAAW,EACX,YAAY,GACZ,MAAM,4BAA4B,CAAC;AACpC,YAAY,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAE9D,OAAO,EAAE,YAAY,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AACzE,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChE,YAAY,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACnD,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACzF,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,YAAY,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAE1E,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,YAAY,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAEpF,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACvE,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export { ColorTransformBatcher, packColorAdd, packTintAdd, NO_COLOR_ADD, } from './ColorTransformBatcher.js';
|
|
2
|
+
export { TintedSprite, registerColorTransform } from './TintedSprite.js';
|
|
3
|
+
export { AnimatedSprite, Animation } from './AnimatedSprite.js';
|
|
4
|
+
export { SpriteSheet } from './SpriteSheet.js';
|
|
5
|
+
export { Camera, createCamera } from './Camera.js';
|
|
6
|
+
export { TileMap, EMPTY, tileFrame, tileFrameSheet, tileFrameIndex } from './TileMap.js';
|
|
7
|
+
export { LayeredSprite } from './LayeredSprite.js';
|
|
8
|
+
export { Projectile } from './Projectile.js';
|
|
9
|
+
export { ActorAnimator } from './ActorAnimator.js';
|
|
10
|
+
export { blobIndex, autotileFrames, BLOB_SHAPES } from './Autotile.js';
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/render/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,qBAAqB,EACrB,YAAY,EACZ,WAAW,EACX,YAAY,GACZ,MAAM,4BAA4B,CAAC;AAGpC,OAAO,EAAE,YAAY,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AACzE,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAEhE,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEnD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAEzF,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAG7C,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGnD,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A spreading area effect over the grid: fire, gas, caustic ooze - anything with a
|
|
3
|
+
* volume per cell that creeps into its neighbours and thins out over time.
|
|
4
|
+
*
|
|
5
|
+
* Deliberately dumber than a simulation: `mwg` holds the volumes and diffuses them, and
|
|
6
|
+
* the game decides what a volume *means* (reading `cellsAbove` each turn to burn, poison
|
|
7
|
+
* or corrode whoever stands there). Per-creature timers (`applyStatusEffect`) already
|
|
8
|
+
* cover "this victim burns for 3 turns"; this covers the other half, "this *place*
|
|
9
|
+
* burns until it burns out".
|
|
10
|
+
*/
|
|
11
|
+
export declare class Blob {
|
|
12
|
+
readonly width: number;
|
|
13
|
+
readonly height: number;
|
|
14
|
+
private volume;
|
|
15
|
+
constructor(width: number, height: number);
|
|
16
|
+
/** how much effect sits on `(x, y)` right now; 0 off-map */
|
|
17
|
+
volumeAt(x: number, y: number): number;
|
|
18
|
+
/** the total volume across the whole map - useful for "has it burned out yet" */
|
|
19
|
+
total(): number;
|
|
20
|
+
/** adds `amount` to whatever is already on `(x, y)`; off-map is a no-op */
|
|
21
|
+
seed(x: number, y: number, amount: number): void;
|
|
22
|
+
/**
|
|
23
|
+
* One diffusion step: every cell shares `spread` of its volume equally among its
|
|
24
|
+
* passable 4-neighbours (a cell with no open neighbour keeps it all), then every
|
|
25
|
+
* cell keeps only `decay` of what it ends up with. `decay: 1` conserves volume and
|
|
26
|
+
* only moves it around; anything lower thins the effect out over time.
|
|
27
|
+
*/
|
|
28
|
+
spread(passable: (x: number, y: number) => boolean, spread?: number, decay?: number): void;
|
|
29
|
+
/** every cell holding at least `minimum` - the cells a game applies its effect on */
|
|
30
|
+
cellsAbove(minimum: number): Array<{
|
|
31
|
+
x: number;
|
|
32
|
+
y: number;
|
|
33
|
+
volume: number;
|
|
34
|
+
}>;
|
|
35
|
+
toJSON(): {
|
|
36
|
+
width: number;
|
|
37
|
+
height: number;
|
|
38
|
+
volume: number[];
|
|
39
|
+
};
|
|
40
|
+
static fromJSON(data: {
|
|
41
|
+
width: number;
|
|
42
|
+
height: number;
|
|
43
|
+
volume: number[];
|
|
44
|
+
}): Blob;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=Blob.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Blob.d.ts","sourceRoot":"","sources":["../../src/roguelike/Blob.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AAEH,qBAAa,IAAI;IAChB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAExB,OAAO,CAAC,MAAM,CAAe;IAE7B,YAAY,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAIxC;IAED,4DAA4D;IAC5D,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAGrC;IAED,iFAAiF;IACjF,KAAK,IAAI,MAAM,CAId;IAED,2EAA2E;IAC3E,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAG/C;IAED;;;;;OAKG;IACH,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,OAAO,EAAE,MAAM,SAAO,EAAE,KAAK,SAAM,GAAG,IAAI,CAgCpF;IAED,qFAAqF;IACrF,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,KAAK,CAAC;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAS3E;IAED,MAAM,IAAI;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,CAE5D;IAED,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,GAAG,IAAI,CAI/E;CACD"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { neighbourOffsets } from './Level.js';
|
|
2
|
+
/**
|
|
3
|
+
* A spreading area effect over the grid: fire, gas, caustic ooze - anything with a
|
|
4
|
+
* volume per cell that creeps into its neighbours and thins out over time.
|
|
5
|
+
*
|
|
6
|
+
* Deliberately dumber than a simulation: `mwg` holds the volumes and diffuses them, and
|
|
7
|
+
* the game decides what a volume *means* (reading `cellsAbove` each turn to burn, poison
|
|
8
|
+
* or corrode whoever stands there). Per-creature timers (`applyStatusEffect`) already
|
|
9
|
+
* cover "this victim burns for 3 turns"; this covers the other half, "this *place*
|
|
10
|
+
* burns until it burns out".
|
|
11
|
+
*/
|
|
12
|
+
export class Blob {
|
|
13
|
+
constructor(width, height) {
|
|
14
|
+
this.width = width;
|
|
15
|
+
this.height = height;
|
|
16
|
+
this.volume = new Float32Array(width * height);
|
|
17
|
+
}
|
|
18
|
+
/** how much effect sits on `(x, y)` right now; 0 off-map */
|
|
19
|
+
volumeAt(x, y) {
|
|
20
|
+
if (x < 0 || y < 0 || x >= this.width || y >= this.height)
|
|
21
|
+
return 0;
|
|
22
|
+
return this.volume[y * this.width + x];
|
|
23
|
+
}
|
|
24
|
+
/** the total volume across the whole map - useful for "has it burned out yet" */
|
|
25
|
+
total() {
|
|
26
|
+
let sum = 0;
|
|
27
|
+
for (let i = 0; i < this.volume.length; i++)
|
|
28
|
+
sum += this.volume[i];
|
|
29
|
+
return sum;
|
|
30
|
+
}
|
|
31
|
+
/** adds `amount` to whatever is already on `(x, y)`; off-map is a no-op */
|
|
32
|
+
seed(x, y, amount) {
|
|
33
|
+
if (x < 0 || y < 0 || x >= this.width || y >= this.height)
|
|
34
|
+
return;
|
|
35
|
+
this.volume[y * this.width + x] += amount;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* One diffusion step: every cell shares `spread` of its volume equally among its
|
|
39
|
+
* passable 4-neighbours (a cell with no open neighbour keeps it all), then every
|
|
40
|
+
* cell keeps only `decay` of what it ends up with. `decay: 1` conserves volume and
|
|
41
|
+
* only moves it around; anything lower thins the effect out over time.
|
|
42
|
+
*/
|
|
43
|
+
spread(passable, spread = 0.25, decay = 0.9) {
|
|
44
|
+
const next = new Float32Array(this.volume.length);
|
|
45
|
+
for (let y = 0; y < this.height; y++) {
|
|
46
|
+
for (let x = 0; x < this.width; x++) {
|
|
47
|
+
const here = y * this.width + x;
|
|
48
|
+
const amount = this.volume[here];
|
|
49
|
+
if (amount <= 0)
|
|
50
|
+
continue;
|
|
51
|
+
const open = [];
|
|
52
|
+
for (const [dx, dy] of neighbourOffsets(4)) {
|
|
53
|
+
const nx = x + dx;
|
|
54
|
+
const ny = y + dy;
|
|
55
|
+
if (nx < 0 || ny < 0 || nx >= this.width || ny >= this.height)
|
|
56
|
+
continue;
|
|
57
|
+
if (passable(nx, ny))
|
|
58
|
+
open.push(ny * this.width + nx);
|
|
59
|
+
}
|
|
60
|
+
if (open.length === 0) {
|
|
61
|
+
next[here] += amount;
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
const share = (amount * spread) / open.length;
|
|
65
|
+
next[here] += amount - share * open.length;
|
|
66
|
+
for (const cell of open)
|
|
67
|
+
next[cell] += share;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
for (let i = 0; i < next.length; i++) {
|
|
72
|
+
const kept = next[i] * decay;
|
|
73
|
+
//snap float dust to zero so a burned-out effect actually reads as gone
|
|
74
|
+
this.volume[i] = kept < 0.001 ? 0 : kept;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/** every cell holding at least `minimum` - the cells a game applies its effect on */
|
|
78
|
+
cellsAbove(minimum) {
|
|
79
|
+
const out = [];
|
|
80
|
+
for (let y = 0; y < this.height; y++) {
|
|
81
|
+
for (let x = 0; x < this.width; x++) {
|
|
82
|
+
const volume = this.volume[y * this.width + x];
|
|
83
|
+
if (volume >= minimum)
|
|
84
|
+
out.push({ x, y, volume });
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return out;
|
|
88
|
+
}
|
|
89
|
+
toJSON() {
|
|
90
|
+
return { width: this.width, height: this.height, volume: [...this.volume] };
|
|
91
|
+
}
|
|
92
|
+
static fromJSON(data) {
|
|
93
|
+
const blob = new Blob(data.width, data.height);
|
|
94
|
+
blob.volume.set(data.volume.slice(0, blob.volume.length));
|
|
95
|
+
return blob;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=Blob.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Blob.js","sourceRoot":"","sources":["../../src/roguelike/Blob.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A phased boss fight: HP-fraction thresholds that fire enter-once hooks, plus a
|
|
3
|
+
* cooldown rotation for the boss's abilities.
|
|
4
|
+
*
|
|
5
|
+
* The shape every multi-stage boss shares, whether it teleports at half health, enrages
|
|
6
|
+
* at a third, or summons adds at each bracket: the fight is a ladder of phases entered
|
|
7
|
+
* top-down, and each turn the boss ticks its abilities and uses whatever is ready. `mwg`
|
|
8
|
+
* tracks the ladder and the timers; what a phase *does* (relocate, spawn, change the
|
|
9
|
+
* arena) and what an ability *is* stay the game's own code, fired from the hooks and
|
|
10
|
+
* picks this returns.
|
|
11
|
+
*/
|
|
12
|
+
export declare class BossPhases {
|
|
13
|
+
private thresholds;
|
|
14
|
+
private current;
|
|
15
|
+
/**
|
|
16
|
+
* @param thresholds HP fractions that open a new phase, highest first (e.g.
|
|
17
|
+
* `[0.66, 0.33]` for a three-stage fight) - descending order is required, since a
|
|
18
|
+
* lower bracket must never open before a higher one
|
|
19
|
+
*/
|
|
20
|
+
constructor(thresholds?: readonly number[]);
|
|
21
|
+
/** which phase the fight is in: the count of thresholds at or above `hpFraction` */
|
|
22
|
+
get phase(): number;
|
|
23
|
+
/**
|
|
24
|
+
* Moves the fight to whatever phase `hpFraction` belongs in.
|
|
25
|
+
*
|
|
26
|
+
* @returns the newly entered phase indices, in order - empty when nothing changed, so
|
|
27
|
+
* a game fires each phase's enter-hook exactly once; a single massive hit can enter
|
|
28
|
+
* several at once, and all of them are reported
|
|
29
|
+
*/
|
|
30
|
+
update(hpFraction: number): number[];
|
|
31
|
+
/** restarts the fight at phase 0, for a rematch or a reused boss object */
|
|
32
|
+
reset(): void;
|
|
33
|
+
toJSON(): {
|
|
34
|
+
phase: number;
|
|
35
|
+
};
|
|
36
|
+
static fromJSON(thresholds: readonly number[], data: {
|
|
37
|
+
phase: number;
|
|
38
|
+
}): BossPhases;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* One ability per named slot, each with its own cooldown in turns: `tick()` counts every
|
|
42
|
+
* cooldown down by one turn, `ready()` lists whatever may fire now, and `use(id)` spends
|
|
43
|
+
* one - resetting its full cooldown - reporting whether it was actually ready, so a game
|
|
44
|
+
* can tell "fired" from "still waiting" without tracking the counters itself.
|
|
45
|
+
*/
|
|
46
|
+
export declare class AbilityCycle {
|
|
47
|
+
private cooldowns;
|
|
48
|
+
private remaining;
|
|
49
|
+
constructor(cooldowns: Record<string, number>);
|
|
50
|
+
/** counts every cooling-down ability one turn closer to ready */
|
|
51
|
+
tick(): void;
|
|
52
|
+
/** ids that may fire right now, in definition order */
|
|
53
|
+
ready(): string[];
|
|
54
|
+
/**
|
|
55
|
+
* Fires `id`, resetting its full cooldown.
|
|
56
|
+
*
|
|
57
|
+
* @returns false, changing nothing, for an unknown id or one still cooling down
|
|
58
|
+
*/
|
|
59
|
+
use(id: string): boolean;
|
|
60
|
+
toJSON(): {
|
|
61
|
+
remaining: [string, number][];
|
|
62
|
+
};
|
|
63
|
+
static fromJSON(cooldowns: Record<string, number>, data: {
|
|
64
|
+
remaining: [string, number][];
|
|
65
|
+
}): AbilityCycle;
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=Boss.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Boss.d.ts","sourceRoot":"","sources":["../../src/roguelike/Boss.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,qBAAa,UAAU;IACtB,OAAO,CAAC,UAAU,CAAoB;IACtC,OAAO,CAAC,OAAO,CAAK;IAEpB;;;;OAIG;IACH,YAAY,UAAU,GAAE,SAAS,MAAM,EAAO,EAO7C;IAED,oFAAoF;IACpF,IAAI,KAAK,IAAI,MAAM,CAElB;IAED;;;;;;OAMG;IACH,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAUnC;IAED,2EAA2E;IAC3E,KAAK,IAAI,IAAI,CAEZ;IAED,MAAM,IAAI;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAE1B;IAED,MAAM,CAAC,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,EAAE,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,UAAU,CAIlF;CACD;AAED;;;;;GAKG;AACH,qBAAa,YAAY;IACxB,OAAO,CAAC,SAAS,CAA8B;IAC/C,OAAO,CAAC,SAAS,CAA6B;IAE9C,YAAY,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAE5C;IAED,iEAAiE;IACjE,IAAI,IAAI,IAAI,CAKX;IAED,uDAAuD;IACvD,KAAK,IAAI,MAAM,EAAE,CAMhB;IAED;;;;OAIG;IACH,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAKvB;IAED,MAAM,IAAI;QAAE,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAA;KAAE,CAE1C;IAED,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,IAAI,EAAE;QAAE,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAA;KAAE,GAAG,YAAY,CAIxG;CACD"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A phased boss fight: HP-fraction thresholds that fire enter-once hooks, plus a
|
|
3
|
+
* cooldown rotation for the boss's abilities.
|
|
4
|
+
*
|
|
5
|
+
* The shape every multi-stage boss shares, whether it teleports at half health, enrages
|
|
6
|
+
* at a third, or summons adds at each bracket: the fight is a ladder of phases entered
|
|
7
|
+
* top-down, and each turn the boss ticks its abilities and uses whatever is ready. `mwg`
|
|
8
|
+
* tracks the ladder and the timers; what a phase *does* (relocate, spawn, change the
|
|
9
|
+
* arena) and what an ability *is* stay the game's own code, fired from the hooks and
|
|
10
|
+
* picks this returns.
|
|
11
|
+
*/
|
|
12
|
+
export class BossPhases {
|
|
13
|
+
/**
|
|
14
|
+
* @param thresholds HP fractions that open a new phase, highest first (e.g.
|
|
15
|
+
* `[0.66, 0.33]` for a three-stage fight) - descending order is required, since a
|
|
16
|
+
* lower bracket must never open before a higher one
|
|
17
|
+
*/
|
|
18
|
+
constructor(thresholds = []) {
|
|
19
|
+
this.current = 0;
|
|
20
|
+
for (let i = 1; i < thresholds.length; i++) {
|
|
21
|
+
if (thresholds[i] >= thresholds[i - 1]) {
|
|
22
|
+
throw new Error('boss phase thresholds must descend');
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
this.thresholds = thresholds;
|
|
26
|
+
}
|
|
27
|
+
/** which phase the fight is in: the count of thresholds at or above `hpFraction` */
|
|
28
|
+
get phase() {
|
|
29
|
+
return this.current;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Moves the fight to whatever phase `hpFraction` belongs in.
|
|
33
|
+
*
|
|
34
|
+
* @returns the newly entered phase indices, in order - empty when nothing changed, so
|
|
35
|
+
* a game fires each phase's enter-hook exactly once; a single massive hit can enter
|
|
36
|
+
* several at once, and all of them are reported
|
|
37
|
+
*/
|
|
38
|
+
update(hpFraction) {
|
|
39
|
+
let phase = 0;
|
|
40
|
+
while (phase < this.thresholds.length && hpFraction <= this.thresholds[phase])
|
|
41
|
+
phase++;
|
|
42
|
+
const entered = [];
|
|
43
|
+
while (this.current < phase) {
|
|
44
|
+
this.current++;
|
|
45
|
+
entered.push(this.current);
|
|
46
|
+
}
|
|
47
|
+
return entered;
|
|
48
|
+
}
|
|
49
|
+
/** restarts the fight at phase 0, for a rematch or a reused boss object */
|
|
50
|
+
reset() {
|
|
51
|
+
this.current = 0;
|
|
52
|
+
}
|
|
53
|
+
toJSON() {
|
|
54
|
+
return { phase: this.current };
|
|
55
|
+
}
|
|
56
|
+
static fromJSON(thresholds, data) {
|
|
57
|
+
const phases = new BossPhases(thresholds);
|
|
58
|
+
phases.current = data.phase;
|
|
59
|
+
return phases;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* One ability per named slot, each with its own cooldown in turns: `tick()` counts every
|
|
64
|
+
* cooldown down by one turn, `ready()` lists whatever may fire now, and `use(id)` spends
|
|
65
|
+
* one - resetting its full cooldown - reporting whether it was actually ready, so a game
|
|
66
|
+
* can tell "fired" from "still waiting" without tracking the counters itself.
|
|
67
|
+
*/
|
|
68
|
+
export class AbilityCycle {
|
|
69
|
+
constructor(cooldowns) {
|
|
70
|
+
this.remaining = new Map();
|
|
71
|
+
this.cooldowns = new Map(Object.entries(cooldowns));
|
|
72
|
+
}
|
|
73
|
+
/** counts every cooling-down ability one turn closer to ready */
|
|
74
|
+
tick() {
|
|
75
|
+
for (const [id, left] of this.remaining) {
|
|
76
|
+
if (left <= 1)
|
|
77
|
+
this.remaining.delete(id);
|
|
78
|
+
else
|
|
79
|
+
this.remaining.set(id, left - 1);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/** ids that may fire right now, in definition order */
|
|
83
|
+
ready() {
|
|
84
|
+
const out = [];
|
|
85
|
+
for (const id of this.cooldowns.keys()) {
|
|
86
|
+
if (!this.remaining.has(id))
|
|
87
|
+
out.push(id);
|
|
88
|
+
}
|
|
89
|
+
return out;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Fires `id`, resetting its full cooldown.
|
|
93
|
+
*
|
|
94
|
+
* @returns false, changing nothing, for an unknown id or one still cooling down
|
|
95
|
+
*/
|
|
96
|
+
use(id) {
|
|
97
|
+
const cooldown = this.cooldowns.get(id);
|
|
98
|
+
if (cooldown === undefined || this.remaining.has(id))
|
|
99
|
+
return false;
|
|
100
|
+
if (cooldown > 0)
|
|
101
|
+
this.remaining.set(id, cooldown);
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
104
|
+
toJSON() {
|
|
105
|
+
return { remaining: [...this.remaining] };
|
|
106
|
+
}
|
|
107
|
+
static fromJSON(cooldowns, data) {
|
|
108
|
+
const cycle = new AbilityCycle(cooldowns);
|
|
109
|
+
for (const [id, left] of data.remaining)
|
|
110
|
+
cycle.remaining.set(id, left);
|
|
111
|
+
return cycle;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=Boss.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Boss.js","sourceRoot":"","sources":["../../src/roguelike/Boss.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export type CombatEvent = 'beforeAttack' | 'beforeDamage' | 'afterDamage' | 'onKill' | string;
|
|
2
|
+
export interface DamageContext<C> {
|
|
3
|
+
attacker: C;
|
|
4
|
+
defender: C;
|
|
5
|
+
amount: number;
|
|
6
|
+
prevented: boolean;
|
|
7
|
+
[kind: string]: unknown;
|
|
8
|
+
}
|
|
9
|
+
export interface CombatHook<C> {
|
|
10
|
+
event: CombatEvent;
|
|
11
|
+
handler: (context: DamageContext<C>) => void;
|
|
12
|
+
source?: unknown;
|
|
13
|
+
}
|
|
14
|
+
/** Generic combat lifecycle hooks; the game owns HP, formulas, and when each event fires. */
|
|
15
|
+
export declare class CombatHooks<C> {
|
|
16
|
+
private hooks;
|
|
17
|
+
on(event: CombatEvent, handler: (context: DamageContext<C>) => void, source?: unknown): void;
|
|
18
|
+
offSource(source: unknown): void;
|
|
19
|
+
emit(event: CombatEvent, context: DamageContext<C>): void;
|
|
20
|
+
/** Runs the pre-damage seam and clamps the resulting amount at zero. */
|
|
21
|
+
modifyDamage(attacker: C, defender: C, amount: number): DamageContext<C>;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=Combat.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Combat.d.ts","sourceRoot":"","sources":["../../src/roguelike/Combat.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG,cAAc,GAAG,cAAc,GAAG,aAAa,GAAG,QAAQ,GAAG,MAAM,CAAC;AAE9F,MAAM,WAAW,aAAa,CAAC,CAAC;IAC/B,QAAQ,EAAE,CAAC,CAAC;IACZ,QAAQ,EAAE,CAAC,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,OAAO,CAAC;IACnB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,UAAU,CAAC,CAAC;IAC5B,KAAK,EAAE,WAAW,CAAC;IACnB,OAAO,EAAE,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;IAC7C,MAAM,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,6FAA6F;AAC7F,qBAAa,WAAW,CAAC,CAAC;IACzB,OAAO,CAAC,KAAK,CAAuB;IAEpC,EAAE,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,IAAI,CAE3F;IAED,SAAS,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAE/B;IAED,IAAI,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,IAAI,CAExD;IAED,wEAAwE;IACxE,YAAY,CAAC,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,aAAa,CAAC,CAAC,CAAC,CAMvE;CACD"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/** Generic combat lifecycle hooks; the game owns HP, formulas, and when each event fires. */
|
|
2
|
+
export class CombatHooks {
|
|
3
|
+
constructor() {
|
|
4
|
+
this.hooks = [];
|
|
5
|
+
}
|
|
6
|
+
on(event, handler, source) {
|
|
7
|
+
this.hooks.push({ event, handler, source });
|
|
8
|
+
}
|
|
9
|
+
offSource(source) {
|
|
10
|
+
this.hooks = this.hooks.filter((hook) => hook.source !== source);
|
|
11
|
+
}
|
|
12
|
+
emit(event, context) {
|
|
13
|
+
for (const hook of this.hooks)
|
|
14
|
+
if (hook.event === event)
|
|
15
|
+
hook.handler(context);
|
|
16
|
+
}
|
|
17
|
+
/** Runs the pre-damage seam and clamps the resulting amount at zero. */
|
|
18
|
+
modifyDamage(attacker, defender, amount) {
|
|
19
|
+
const context = { attacker, defender, amount, prevented: false };
|
|
20
|
+
this.emit('beforeDamage', context);
|
|
21
|
+
context.amount = Math.max(0, context.amount);
|
|
22
|
+
if (context.amount === 0)
|
|
23
|
+
context.prevented = true;
|
|
24
|
+
return context;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=Combat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Combat.js","sourceRoot":"","sources":["../../src/roguelike/Combat.ts"],"names":[],"mappings":"AAgBA,6FAA6F;AAC7F,MAAM,OAAO,WAAW;IAAxB;QACS,UAAK,GAAoB,EAAE,CAAC;IAsBrC,CAAC;IApBA,EAAE,CAAC,KAAkB,EAAE,OAA4C,EAAE,MAAgB;QACpF,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;IAC7C,CAAC;IAED,SAAS,CAAC,MAAe;QACxB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;IAClE,CAAC;IAED,IAAI,CAAC,KAAkB,EAAE,OAAyB;QACjD,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK;YAAE,IAAI,IAAI,CAAC,KAAK,KAAK,KAAK;gBAAE,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAChF,CAAC;IAED,wEAAwE;IACxE,YAAY,CAAC,QAAW,EAAE,QAAW,EAAE,MAAc;QACpD,MAAM,OAAO,GAAqB,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;QACnF,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;QACnC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QAC7C,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;QACnD,OAAO,OAAO,CAAC;IAChB,CAAC;CACD"}
|