Преглед на файлове

Move away from Sets; add container display

vintage
Fen Dweller преди 5 години
родител
ревизия
cf68ed8cb7
променени са 10 файла, в които са добавени 107 реда и са изтрити 39 реда
  1. +2
    -5
      src/App.vue
  2. +13
    -3
      src/components/Combat.vue
  3. +42
    -0
      src/components/ContainerView.vue
  4. +9
    -3
      src/components/Statblock.vue
  5. +9
    -10
      src/game/combat.ts
  6. +1
    -1
      src/game/creatures/player.ts
  7. +1
    -1
      src/game/creatures/wolf.ts
  8. +14
    -6
      src/game/entity.ts
  9. +6
    -1
      src/game/interface.ts
  10. +10
    -9
      src/game/vore.ts

+ 2
- 5
src/App.vue Целия файл

@@ -1,8 +1,6 @@
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png">
<Statblock :subject="player" />
<Statblock :subject="enemy" />
<Combat :player="player" :enemy="enemy" />
</div>
</template>
@@ -10,14 +8,12 @@
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator'
import Combat from './components/Combat.vue'
import Statblock from './components/Statblock.vue'
import * as Creatures from '@/game/creatures'
import { Creature, POV } from '@/game/entity'

@Component({
components: {
Combat,
Statblock
Combat
}
})
export default class App extends Vue {
@@ -28,6 +24,7 @@ export default class App extends Vue {
this.player = new Creatures.Wolf()
this.player.perspective = POV.First
this.enemy = new Creatures.Wolf()
console.log(this.player)
}
}
</script>


+ 13
- 3
src/components/Combat.vue Целия файл

@@ -1,9 +1,12 @@
<template>
<div class="hello">
<h1>VORE TIME</h1>
<Statblock :subject="player" />
<Statblock :subject="enemy" />
<h2>Your moves</h2>
<button v-for="action in player.validActions(enemy)" :key="'player-' + action.name" v-on:click="log(action.execute(player, enemy))">{{action.name}}</button>
<button v-for="action in player.validActions(player)" :key="'palyer-' + action.name" v-on:click="log(action.execute(player, player))">{{action.name}}</button>
<button @mouseleave="actionDescription= ''" @mouseover="actionDescription = action.desc" v-for="action in player.validActions(enemy)" :key="'player-' + action.name" v-on:click="log(action.execute(player, enemy))">{{action.name}}</button>
<button @mouseleave="actionDescription= ''" @mouseover="actionDescription = action.desc" v-for="action in player.validActions(player)" :key="'player-' + action.name" v-on:click="log(action.execute(player, player))">{{action.name}}</button>
<div>{{actionDescription}}</div>
<div id="log"></div>
<h2>Enemy moves</h2>
<button v-for="action in enemy.validActions(player)" :key="'enemy-' + action.name" v-on:click="log(action.execute(enemy, player))">{{action.name}}</button>
@@ -15,8 +18,13 @@
import { Component, Prop, Vue, Watch, Emit } from 'vue-property-decorator'
import { Creature, POV } from '@/game/entity'
import { log, LogEntry } from '@/game/interface'
import Statblock from './Statblock.vue'

@Component
@Component(
{
components: { Statblock }
}
)
export default class Combat extends Vue {
@Prop({ type: Creature, required: true })
player!: Creature
@@ -24,6 +32,8 @@ export default class Combat extends Vue {
@Prop({ type: Creature, required: true })
enemy!: Creature

actionDescription = ''

private log: (entry: LogEntry) => void;

constructor () {


+ 42
- 0
src/components/ContainerView.vue Целия файл

@@ -0,0 +1,42 @@
<template>
<div v-if="container.fullness > 0" class="statblock">
<h3>{{container.name}}</h3>
<div>Fullness: {{container.fullness}} / {{container.capacity}}</div>
<div v-for="(prey, index) in container.contents" :key="'prey-' + index">{{prey.name}}</div>
</div>
</template>

<script lang="ts">
import { Component, Prop, Vue, Watch, Emit } from 'vue-property-decorator'
import { Creature, POV } from '@/game/entity'
import { Stats, Stat } from '@/game/combat'
import { Container } from '@/game/vore'

@Component
export default class ContainerView extends Vue {
@Prop({ required: true })
container!: Container

constructor () {
super()
}
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>

+ 9
- 3
src/components/Statblock.vue Целия файл

@@ -3,9 +3,10 @@
<h2>Stats</h2>
<div v-if="subject.perspective === firstperson">Player</div>
<div v-if="subject.perspective !== firstperson">Name: {{subject.name.all.capital}}</div>
<div>Health: {{subject.health.toFixed(0)}}</div>
<div v-for="stat in Object.keys(subject.stats)" :key="stat">{{stat}}: {{subject.stats[stat]}}</div>
<div>Health: {{subject.health.toFixed(0)}} / {{subject.maxHealth.toFixed(0)}}</div>
<div v-for="stat in Object.keys(subject.stats)" v-bind:key="stat">{{stat}}: {{subject.stats[stat]}}</div>
<div>Status: {{subject.state}}</div>
<ContainerView v-for="container in subject.containers" :key="container.name" :container="container" />
</div>
</template>

@@ -13,8 +14,13 @@
import { Component, Prop, Vue, Watch, Emit } from 'vue-property-decorator'
import { Creature, POV } from '@/game/entity'
import { Stats, Stat } from '@/game/combat'
import ContainerView from './ContainerView.vue'

@Component
@Component({
components: {
ContainerView
}
})
export default class Statblock extends Vue {
@Prop({ type: Creature, required: true })
subject!: Creature


+ 9
- 10
src/game/combat.ts Целия файл

@@ -51,15 +51,14 @@ export interface Combatant {
}

export abstract class Action {
public name: string;
allowed (user: Creature, target: Creature) {
return this.userStates.has(user.state) && this.targetStates.has(target.state)
}

abstract execute(user: Creature, target: Creature): LogEntry

constructor (name: string, public userStates: Set<State>, public targetStates: Set<State>) {
this.name = name
constructor (public name: string, public desc: string, public userStates: Set<State>, public targetStates: Set<State>) {
}

toString (): string {
@@ -100,7 +99,7 @@ export class AttackAction extends PairAction {
}

constructor (protected damage: Damage) {
super('Attack', new Set([State.Normal]), new Set([State.Normal]))
super('Attack', 'Attack the enemy', new Set([State.Normal]), new Set([State.Normal]))
}

execute (user: Creature, target: Creature): LogEntry {
@@ -122,7 +121,7 @@ export class DevourAction extends PairAction {
}

constructor (protected container: Container) {
super('Devour', new Set([State.Normal]), new Set([State.Normal]))
super('Devour', 'Try to consume your foe', new Set([State.Normal]), new Set([State.Normal]))
}

execute (user: Creature, target: Creature): LogEntry {
@@ -144,7 +143,7 @@ export class StruggleAction extends PairAction {
}

constructor () {
super('Struggle', new Set([State.Eaten]), new Set([State.Normal]))
super('Struggle', 'Try to escape your predator', new Set([State.Eaten]), new Set([State.Normal]))
}

execute (user: Creature, target: Creature): LogEntry {
@@ -168,8 +167,8 @@ export class DigestAction extends SelfAction {
}

allowed (user: Creature, target: Creature) {
if (Array.from(user.containers).some(container => {
return container.contents.size > 0
if (user.containers.some(container => {
return container.contents.length > 0
})) {
return super.allowed(user, target)
} else {
@@ -178,11 +177,11 @@ export class DigestAction extends SelfAction {
}

constructor () {
super('Digest', new Set([State.Normal]), new Set([State.Normal]))
super('Digest', 'Digest all of your current prey', new Set([State.Normal]), new Set([State.Normal]))
}

execute (user: Creature, target: Creature): LogEntry {
const results = new CompositeLog(...Array.from(user.containers).map(container => container.tick(60)))
const results = new CompositeLog(...user.containers.map(container => container.tick(60)))
return new CompositeLog(this.lines[user.perspective][target.perspective](user, target), results)
}
}


+ 1
- 1
src/game/creatures/player.ts Целия файл

@@ -10,7 +10,7 @@ export class Player extends Creature {

const stomach = new Stomach(this, 100, new Damage({ amount: 10, type: DamageType.Acid }, { amount: 10, type: DamageType.Crush }))

this.containers.add(stomach)
this.containers.push(stomach)
this.actions.push(new DevourAction(stomach))

this.perspective = POV.First


+ 1
- 1
src/game/creatures/wolf.ts Целия файл

@@ -20,7 +20,7 @@ export class Wolf extends Creature {

const stomach = new Stomach(this, 50, new Damage({ amount: 50, type: DamageType.Acid }, { amount: 500, type: DamageType.Crush }))

this.containers.add(stomach)
this.containers.push(stomach)
this.actions.push(new DevourAction(stomach))
this.actions.push(new StruggleAction())
this.actions.push(new DigestAction())


+ 14
- 6
src/game/entity.ts Целия файл

@@ -13,6 +13,7 @@ export interface Entity {

export interface Mortal extends Entity {
health: number;
maxHealth: number;
resistances: Map<DamageType, number>;
takeDamage: (damage: Damage) => void;
stats: Stats;
@@ -20,15 +21,22 @@ export interface Mortal extends Entity {

export class Creature implements Mortal, Pred, Prey, Combatant {
health = 100
maxHealth = 100
resistances: Map<DamageType, number> = new Map()
perspective: POV = POV.Third
state: State = State.Normal
containers: Set<Container> = new Set();
containers: Array<Container> = []
actions: Array<Action> = [];
containedIn: Container|null = null;
private baseBulk: number;

get bulk (): number {
return this.baseBulk
}

constructor (public name: Noun, public pronouns: Pronoun, public stats: Stats, public preyPrefs: Set<VoreType>, public predPrefs: Set<VoreType>, public bulk: number) {
containedIn: Container|null = null;

constructor (public name: Noun, public pronouns: Pronoun, public stats: Stats, public preyPrefs: Set<VoreType>, public predPrefs: Set<VoreType>, bulk: number) {
this.baseBulk = bulk
}

toString (): string {
@@ -37,8 +45,9 @@ export class Creature implements Mortal, Pred, Prey, Combatant {

takeDamage (damage: Damage): void {
damage.damages.forEach(instance => {
if (this.resistances.has(instance.type)) {
this.health -= instance.amount * this.resistances.get(instance.type)!
const resistance: number|undefined = this.resistances.get(instance.type)
if (resistance !== undefined) {
this.health -= instance.amount * resistance
} else {
this.health -= instance.amount
}
@@ -46,7 +55,6 @@ export class Creature implements Mortal, Pred, Prey, Combatant {
}

validActions (target: Creature): Array<Action> {
console.log(this)
return this.actions.filter(action => {
return action.allowed(this, target)
})


+ 6
- 1
src/game/interface.ts Целия файл

@@ -34,5 +34,10 @@ export class CompositeLog implements LogEntry {
}

export function log (entry: LogEntry): void {
entry.render().forEach(elem => document.querySelector('#log')?.appendChild(elem))
entry.render().forEach(elem => {
document.querySelector('#log')!.insertBefore(elem, document?.querySelector('#log > *'))
})

const entries: Array<HTMLElement> = Array.from(document.querySelectorAll('#log > *'))
entries.slice(5).forEach(element => element.remove())
}

+ 10
- 9
src/game/vore.ts Целия файл

@@ -1,6 +1,7 @@
import { Entity, Mortal, POV } from './entity'
import { Damage } from './combat'
import { LogLines, LogEntry, CompositeLog } from './interface'
import { ProperNoun } from './language'
export enum VoreType {Oral}

export interface Prey extends Mortal {
@@ -11,13 +12,13 @@ export interface Prey extends Mortal {

export interface Pred extends Entity {
predPrefs: Set<VoreType>;
containers: Set<Container>;
containers: Array<Container>;
}

export interface Container {
name: string;
voreTypes: Set<VoreType>;
contents: Set<Prey>;
contents: Array<Prey>;
capacity: number;
fullness: number;
canTake: (prey: Prey) => boolean;
@@ -32,7 +33,7 @@ export interface Container {
}

abstract class NormalContainer implements Container {
contents: Set<Prey>
contents: Array<Prey>

get fullness (): number {
return Array.from(this.contents.values()).reduce((total: number, prey: Prey) => total + prey.bulk, 0)
@@ -49,14 +50,14 @@ abstract class NormalContainer implements Container {
}

consume (prey: Prey): LogEntry {
this.contents.add(prey)
this.contents.push(prey)
prey.containedIn = this
return new LogLines('MUNCH')
}

release (prey: Prey): LogEntry {
prey.containedIn = null
this.contents.delete(prey)
this.contents = this.contents.filter(victim => victim !== prey)
return new LogLines('ANTI-MUNCH')
}

@@ -82,9 +83,9 @@ abstract class NormalContainer implements Container {
const digestedEntries = new CompositeLog(...digested.map(prey => this.digest(prey)))
const absorbedEntries = new CompositeLog(...digested.map(prey => this.absorb(prey)))

this.contents = new Set(Array.from(this.contents.values()).filter(prey => {
return prey.health > 0
}))
this.contents = this.contents.filter(prey => {
return prey.health > -100
})

return new CompositeLog(digestedEntries, absorbedEntries)
}
@@ -112,7 +113,7 @@ abstract class NormalContainer implements Container {
}

constructor (public name: string, protected owner: Pred, public voreTypes: Set<VoreType>, public capacity: number, private damage: Damage) {
this.contents = new Set()
this.contents = []
}
}



Loading…
Отказ
Запис