浏览代码

Detect when combat has ended; count dead creatures as prey

vintage
Fen Dweller 5 年前
父节点
当前提交
943f4c7bc8
共有 5 个文件被更改,包括 134 次插入40 次删除
  1. +6
    -5
      src/App.vue
  2. +111
    -28
      src/components/Combat.vue
  3. +10
    -0
      src/game/combat.ts
  4. +6
    -6
      src/game/creatures/wolf.ts
  5. +1
    -1
      src/game/vore.ts

+ 6
- 5
src/App.vue 查看文件

@@ -2,7 +2,7 @@
<div id="app">
<Header />
<Explore v-if="mode === 'explore'" :world="world" />
<Combat v-if="mode === 'combat'" :encounter="encounter" />
<Combat @leaveCombat="mode = 'explore'" v-if="mode === 'combat'" :encounter="encounter" />
</div>
</template>

@@ -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)
}


+ 111
- 28
src/components/Combat.vue 查看文件

@@ -40,8 +40,11 @@
<ActionButton @described="described" @executed="executedRight" v-for="(action, index) in right.validActions(right)" :key="'right-' + action.name + '-' + index" :action="action" :user="right" :target="right" :combatants="combatants" />
</div>
</div>
<div class="action-description">
<div v-if="encounter.winner === null" class="action-description">
</div>
<button @click="$emit('leaveCombat')" v-if="encounter.winner !== null" class="exit-combat">
Exit Combat
</button>
</div>
</template>

@@ -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;
}
}
</style>

+ 10
- 0
src/game/combat.ts 查看文件

@@ -564,6 +564,16 @@ export class Encounter {

return nilLog
}

get winner (): null|Side {
const remaining: Set<Side> = 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 {


+ 6
- 6
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)


+ 1
- 1
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]
},


正在加载...
取消
保存