diff --git a/src/App.vue b/src/App.vue index aedc56c..3383973 100644 --- a/src/App.vue +++ b/src/App.vue @@ -2,7 +2,7 @@
- +
@@ -46,8 +46,13 @@ export default class App extends Vue { } created () { + const player = new Creatures.Wolf() + player.perspective = POV.Second + player.side = Side.Heroes + this.$data.encounters = [] + this.$data.encounters.push(new Encounter({ name: 'Wolf' }, [player, new Creatures.Wolf()])) this.$data.encounters.push(new Encounter({ name: 'Boss Fight' }, this.makeParty().concat([new Creatures.Withers(), new Creatures.Kenzie()]))) this.$data.encounters.push(new Encounter({ name: 'Cafat' }, this.makeParty().concat([new Creatures.Cafat()]))) this.$data.encounters.push(new Encounter({ name: 'Dragon' }, this.makeParty().concat([new Creatures.Dragon()]))) @@ -75,10 +80,6 @@ export default class App extends Vue { const bar = new Place('Bar', 'This is the bar') street.biconnect(Direction.East, bar) - - const player = new Creatures.Wolf() - player.perspective = POV.Second - player.side = Side.Heroes player.location = home this.$data.world = new World(player) } diff --git a/src/components/Combat.vue b/src/components/Combat.vue index 7758c0c..e3da25a 100644 --- a/src/components/Combat.vue +++ b/src/components/Combat.vue @@ -40,8 +40,11 @@ -
+
+
@@ -49,7 +52,7 @@ import { Component, Prop, Vue, Watch, Emit } from 'vue-property-decorator' import { Creature } from '@/game/creature' import { POV } from '@/game/language' -import { LogEntry } from '@/game/interface' +import { LogEntry, LogLine } from '@/game/interface' import Statblock from './Statblock.vue' import ActionButton from './ActionButton.vue' import { Side, Encounter } from '@/game/combat' @@ -93,7 +96,7 @@ export default class Combat extends Vue { executedLeft (entry: LogEntry) { this.writeLog(entry, "left-move") - this.writeLog(this.encounter.nextMove(), "left-move") + this.writeLog(this.encounter.nextMove(), "center-move") this.pickNext() } @@ -103,11 +106,11 @@ export default class Combat extends Vue { executedRight (entry: LogEntry) { this.writeLog(entry, "right-move") - this.writeLog(this.encounter.nextMove(), "right-move") + this.writeLog(this.encounter.nextMove(), "center-move") this.pickNext() } - writeLog (entry: LogEntry, cls: string) { + writeLog (entry: LogEntry, cls = "") { const log = this.$el.querySelector(".log") if (log !== null) { const before = log.querySelector("div.log-entry") @@ -118,7 +121,10 @@ export default class Combat extends Vue { holder.appendChild(element) }) - holder.classList.add(cls) + if (cls !== "") { + holder.classList.add(cls) + } + const hline = document.createElement("div") hline.classList.add("log-separator") log.insertBefore(hline, before) @@ -129,30 +135,41 @@ export default class Combat extends Vue { } pickNext () { - if (this.encounter.currentMove.side === Side.Heroes) { - this.$data.left = this.encounter.currentMove - - if (this.encounter.currentMove.containedIn !== null) { - this.$data.right = this.encounter.currentMove.containedIn.owner - } - } else if (this.encounter.currentMove.side === Side.Monsters) { - this.$data.right = this.encounter.currentMove - - if (this.encounter.currentMove.containedIn !== null) { - this.$data.left = this.encounter.currentMove.containedIn.owner + // Did one side win? + + if (this.encounter.winner !== null) { + this.writeLog( + new LogLine( + `game o-vore lmaoooooooo` + ), + "center-move" + ) + } else { + if (this.encounter.currentMove.side === Side.Heroes) { + this.$data.left = this.encounter.currentMove + + if (this.encounter.currentMove.containedIn !== null) { + this.$data.right = this.encounter.currentMove.containedIn.owner + } + } else if (this.encounter.currentMove.side === Side.Monsters) { + this.$data.right = this.encounter.currentMove + + if (this.encounter.currentMove.containedIn !== null) { + this.$data.left = this.encounter.currentMove.containedIn.owner + } } + // scroll to the newly selected creature + this.$nextTick(() => { + const creature: HTMLElement|null = this.$el.querySelector("[data-current-turn]") + if (creature !== null) { + this.scrollParentTo(creature) + } + const target: HTMLElement|null = this.$el.querySelector("[data-active]") + if (target !== null) { + this.scrollParentTo(target) + } + }) } - // scroll to the newly selected creature - this.$nextTick(() => { - const creature: HTMLElement|null = this.$el.querySelector("[data-current-turn]") - if (creature !== null) { - this.scrollParentTo(creature) - } - const target: HTMLElement|null = this.$el.querySelector("[data-active]") - if (target !== null) { - this.scrollParentTo(target) - } - }) } selectable (creature: Creature): boolean { @@ -243,6 +260,19 @@ export default class Combat extends Vue { min-height: 100%; } +.exit-combat { + grid-area: 2 / main-col-start / main-row-start / main-col-end; + width: 100%; + padding: 4pt; + flex: 0 1; + background: #333; + border-color: #666; + border-style: outset; + user-select: none; + color: #eee; + font-size: 36px; +} + .combat-layout { position: relative; display: grid; @@ -258,6 +288,7 @@ export default class Combat extends Vue { .log { grid-area: main-row-start / main-col-start / main-row-end / main-col-end; overflow-y: scroll; + overflow-x: hidden; font-size: 12pt; width: 100%; max-height: 100%; @@ -494,4 +525,56 @@ div.right-move { margin: 4pt 0pt 4pt; background: linear-gradient(90deg, transparent, #444 10%, #444 90%, transparent 100%); } + +.left-move { + animation: left-fly-in 1s; +} + +.right-move { + animation: right-fly-in 1s; +} + +.center-move { + animation: center-fly-in 1s; +} + +@keyframes left-fly-in { + 0% { + opacity: 0; + transform: translate(-50px, 0); + } + + 50% { + transform: translate(0, 0); + } + + 100% { + opacity: 1; + } +} + +@keyframes right-fly-in { + 0% { + opacity: 0; + transform: translate(50px, 0); + } + + 50% { + transform: translate(0, 0); + } + + 100% { + opacity: 1; + } +} + +@keyframes center-fly-in { + 0% { + opacity: 0; + } + + 100% { + opacity: 1; + } +} diff --git a/src/game/combat.ts b/src/game/combat.ts index c1e757a..fbd99cd 100644 --- a/src/game/combat.ts +++ b/src/game/combat.ts @@ -564,6 +564,16 @@ export class Encounter { return nilLog } + + get winner (): null|Side { + const remaining: Set = new Set(this.combatants.filter(combatant => !combatant.disabled).map(combatant => combatant.side)) + + if (remaining.size === 1) { + return Array.from(remaining)[0] + } else { + return null + } + } } export abstract class Consequence { diff --git a/src/game/creatures/wolf.ts b/src/game/creatures/wolf.ts index 390ec1b..180f62c 100644 --- a/src/game/creatures/wolf.ts +++ b/src/game/creatures/wolf.ts @@ -20,17 +20,17 @@ export class Wolf extends Creature { this.side = Side.Monsters const stomach = new Stomach(this, 50, new Damage( - { amount: 20, type: DamageType.Acid, target: Vigor.Health }, - { amount: 10, type: DamageType.Crush, target: Vigor.Stamina }, - { amount: 10, type: DamageType.Dominance, target: Vigor.Resolve } + { amount: 60, type: DamageType.Acid, target: Vigor.Health }, + { amount: 30, type: DamageType.Crush, target: Vigor.Stamina }, + { amount: 30, type: DamageType.Dominance, target: Vigor.Resolve } )) this.containers.push(stomach) const bowels = new Bowels(this, 50, new Damage( - { amount: 10, type: DamageType.Crush, target: Vigor.Health }, - { amount: 25, type: DamageType.Crush, target: Vigor.Stamina }, - { amount: 25, type: DamageType.Dominance, target: Vigor.Resolve } + { amount: 30, type: DamageType.Crush, target: Vigor.Health }, + { amount: 60, type: DamageType.Crush, target: Vigor.Stamina }, + { amount: 60, type: DamageType.Dominance, target: Vigor.Resolve } )) this.containers.push(bowels) diff --git a/src/game/vore.ts b/src/game/vore.ts index 3c19310..e8ca133 100644 --- a/src/game/vore.ts +++ b/src/game/vore.ts @@ -49,7 +49,7 @@ export abstract class Vore extends Mortal { get [VoreStat.PreyCount] () { return containers.reduce( (total: number, container: VoreContainer) => { - return total + container.contents.reduce( + return total + container.contents.concat(container.digested).reduce( (total: number, prey: Vore) => { return total + 1 + prey.voreStats[VoreStat.PreyCount] },