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

Add a very large Lycanroc; fix some Vue warnings

vintage
Fen Dweller преди 5 години
родител
ревизия
002ff554b9
променени са 10 файла, в които са добавени 155 реда и са изтрити 79 реда
  1. +2
    -1
      .eslintrc.js
  2. +2
    -1
      src/App.vue
  3. +4
    -4
      src/components/Combat.vue
  4. +5
    -31
      src/game/combat.ts
  5. +51
    -18
      src/game/combat/actions.ts
  6. +25
    -1
      src/game/combat/conditions.ts
  7. +2
    -1
      src/game/creatures.ts
  8. +34
    -0
      src/game/creatures/kenzie.ts
  9. +23
    -16
      src/game/creatures/withers.ts
  10. +7
    -6
      src/game/vore.ts

+ 2
- 1
.eslintrc.js Целия файл

@@ -16,6 +16,7 @@ module.exports = {
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-useless-constructor': 'off',
'@typescript-eslint/no-unused-vars': 'off',
'quotes': 'off'
'quotes': 'off',
'function-paren-newline': ['error', 'multiline-arguments']
}
}

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

@@ -73,7 +73,8 @@ export default class App extends Vue {

this.left = fighter
this.right = new Creatures.Withers()
this.combatants = [this.left, this.right, wizard, rogue, cleric]
const kenzie = new Creatures.Kenzie()
this.combatants = [this.left, this.right, wizard, rogue, cleric, kenzie]
console.log(this.left)
console.log(this.right)
}


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

@@ -1,10 +1,10 @@
<template>
<div class="combat-layout">
<div @wheel="horizWheelLeft" class="stat-column" id="left-stats">
<Statblock v-on:click.native="left = combatant" class="left-stats" :data-active="combatant === left" v-for="combatant in combatants.filter(c => c.side == Side.Heroes && !c.digested)" v-bind:key="combatant.name" :subject="combatant" />
<Statblock v-on:click.native="left = combatant" class="left-stats" :data-active="combatant === left" v-for="(combatant, index) in combatants.filter(c => c.side == Side.Heroes && !c.digested)" v-bind:key="'left-stat-' + index" :subject="combatant" />
</div>
<div @wheel="horizWheelRight" class="stat-column" id="right-stats">
<Statblock v-on:click.native="right = combatant" class="right-stats" :data-active="combatant === right" v-for="combatant in combatants.filter(c => c.side == Side.Monsters && !c.digested)" v-bind:key="combatant.name" :subject="combatant" />
<Statblock v-on:click.native="right = combatant" class="right-stats" :data-active="combatant === right" v-for="(combatant, index) in combatants.filter(c => c.side == Side.Monsters && !c.digested)" v-bind:key="'right-stat-' + index" :subject="combatant" />
</div>
<div id="log">
</div>
@@ -18,7 +18,7 @@
<i class="action-label fas fa-user-friends" v-if="left.validActions(right).length > 0"></i>
<ActionButton @described="described" @executed="executedLeft" v-for="action in left.validActions(right)" :key="'left' + action.name" :action="action" :user="left" :target="right" :combatants="combatants" />
<i class="action-label fas fa-user" v-if="left.validActions(left).length > 0"></i>
<ActionButton @described="described" @executed="executedLeft" v-for="action in left.validActions(left)" :key="'left' + action.name" :action="action" :user="left" :target="right" :combatants="combatants" />
<ActionButton @described="described" @executed="executedLeft" v-for="action in left.validActions(left)" :key="'left' + action.name" :action="action" :user="left" :target="left" :combatants="combatants" />
</div>
<div>{{actionDescription}}</div>
</div>
@@ -32,7 +32,7 @@
<i class="action-label fas fa-user-friends" v-if="right.validActions(left).length > 0"></i>
<ActionButton @described="described" @executed="executedRight" v-for="action in right.validActions(left)" :key="'right' + action.name" :action="action" :user="right" :target="left" :combatants="combatants" />
<i class="action-label fas fa-user" v-if="right.validActions(right).length > 0"></i>
<ActionButton @described="described" @executed="executedRight" v-for="action in right.validActions(right)" :key="'right' + action.name" :action="action" :user="right" :target="left" :combatants="combatants" />
<ActionButton @described="described" @executed="executedRight" v-for="action in right.validActions(right)" :key="'right' + action.name" :action="action" :user="right" :target="right" :combatants="combatants" />
</div>
</div>
<div id="action-desc">


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

@@ -295,37 +295,7 @@ export interface Actionable {
actions: Array<Action>;
}

export abstract class SelfAction extends Action {
allowed (user: Creature, target: Creature) {
if (user === target) {
return super.allowed(user, target)
} else {
return false
}
}
}

export abstract class PairAction extends Action {
allowed (user: Creature, target: Creature) {
if (user !== target) {
return super.allowed(user, target)
} else {
return false
}
}
}

export abstract class TogetherAction extends PairAction {
allowed (user: Creature, target: Creature) {
if (user.containedIn === target.containedIn) {
return super.allowed(user, target)
} else {
return false
}
}
}

export abstract class GroupAction extends PairAction {
export abstract class GroupAction extends Action {
allowedGroup (user: Creature, targets: Array<Creature>): Array<Creature> {
return targets.filter(target => this.allowed(user, target))
}
@@ -335,4 +305,8 @@ export abstract class GroupAction extends PairAction {
}

abstract describeGroup (user: Creature, targets: Array<Creature>): LogEntry

constructor (name: TextLike, desc: TextLike, conditions: Array<Condition>) {
super(name, desc, conditions)
}
}

+ 51
- 18
src/game/combat/actions.ts Целия файл

@@ -1,12 +1,12 @@
import { StatTest, StatVigorTest } from './tests'
import { POVPairArgs, POVPair, DynText, LiveText, TextLike } from '../language'
import { Entity, POV, Creature } from '../entity'
import { Damage, DamageFormula, Stat, Vigor, TogetherAction, PairAction, SelfAction } from '../combat'
import { Damage, DamageFormula, Stat, Vigor, Action } from '../combat'
import { LogLine, LogLines, LogEntry, CompositeLog } from '../interface'
import { VoreContainer, Container } from '../vore'
import { CapableCondition, DrainedVigorCondition } from './conditions'
import { CapableCondition, DrainedVigorCondition, TogetherCondition, EnemyCondition, SoloCondition, PairCondition } from './conditions'

export class AttackAction extends TogetherAction {
export class AttackAction extends Action {
protected test: StatTest

protected successLines: POVPairArgs<Entity, Entity, { damage: Damage }> = new POVPairArgs([
@@ -31,7 +31,11 @@ export class AttackAction extends TogetherAction {
])

constructor (protected damage: DamageFormula) {
super('Attack', 'Attack the enemy', [new CapableCondition()])
super(
'Attack',
'Attack the enemy',
[new CapableCondition(), new TogetherCondition(), new EnemyCondition()]
)
this.test = new StatTest(Stat.Power)
}

@@ -51,7 +55,7 @@ export class AttackAction extends TogetherAction {
}
}

export class DevourAction extends TogetherAction {
export class DevourAction extends Action {
private test: StatVigorTest

protected failLines: POVPairArgs<Entity, Entity, { container: Container }> = new POVPairArgs([
@@ -73,7 +77,11 @@ export class DevourAction extends TogetherAction {
}

constructor (protected container: Container) {
super(new DynText(new LiveText(container, x => x.consumeVerb.capital), ' (', new LiveText(container, x => x.name.all), ')'), new LiveText(container, x => `Try to ${x.consumeVerb} your foe`), [new CapableCondition()])
super(
new DynText(new LiveText(container, x => x.consumeVerb.capital), ' (', new LiveText(container, x => x.name.all), ')'),
new LiveText(container, x => `Try to ${x.consumeVerb} your foe`),
[new CapableCondition(), new TogetherCondition()]
)
this.test = new StatVigorTest(Stat.Power)
}

@@ -90,7 +98,7 @@ export class DevourAction extends TogetherAction {
}
}

export class FeedAction extends TogetherAction {
export class FeedAction extends Action {
private test: StatTest

protected failLines: POVPair<Entity, Entity> = new POVPair([
@@ -112,7 +120,11 @@ export class FeedAction extends TogetherAction {
}

constructor (protected container: Container) {
super('Feed', 'Feed yourself to your opponent', [new DrainedVigorCondition(Vigor.Resolve)])
super(
'Feed',
'Feed yourself to your opponent',
[new DrainedVigorCondition(Vigor.Resolve), new TogetherCondition()]
)
this.name += ` (${container.name})`
this.test = new StatTest(Stat.Power)
}
@@ -126,7 +138,7 @@ export class FeedAction extends TogetherAction {
}
}

export class StruggleAction extends PairAction {
export class StruggleAction extends Action {
private test: StatVigorTest

protected failLines: POVPair<Entity, Entity> = new POVPair([
@@ -144,7 +156,11 @@ export class StruggleAction extends PairAction {
}

constructor (public container: Container) {
super(new DynText('Struggle (', new LiveText(container, x => x.name.all), ')'), 'Try to escape from your foe', [new CapableCondition()])
super(
new DynText('Struggle (', new LiveText(container, x => x.name.all), ')'),
'Try to escape from your foe',
[new CapableCondition(), new PairCondition()]
)
this.test = new StatVigorTest(Stat.Power)
}

@@ -165,7 +181,7 @@ export class StruggleAction extends PairAction {
}
}

export abstract class EatenAction extends PairAction {
export abstract class EatenAction extends Action {
protected lines: POVPair<Entity, Entity> = new POVPair([])

allowed (user: Creature, target: Creature) {
@@ -177,10 +193,15 @@ export abstract class EatenAction extends PairAction {
}

constructor (public container: Container, name: TextLike, desc: string) {
super(new DynText(name, ' (', new LiveText(container, x => x.name.all), ')'), desc, [new CapableCondition()])
super(
new DynText(name, ' (', new LiveText(container, x => x.name.all), ')'),
desc,
[new CapableCondition(), new PairCondition()]
)
}
}
export class DigestAction extends SelfAction {

export class DigestAction extends Action {
protected lines: POVPair<Entity, Entity> = new POVPair([])

allowed (user: Creature, target: Creature) {
@@ -192,7 +213,11 @@ export class DigestAction extends SelfAction {
}

constructor (protected container: VoreContainer) {
super(new DynText('Digest (', new LiveText(container, container => container.name.all), ')'), 'Digest your prey', [new CapableCondition()])
super(
new DynText('Digest (', new LiveText(container, container => container.name.all), ')'),
'Digest your prey',
[new CapableCondition(), new SoloCondition()]
)
}

execute (user: Creature, target: Creature): LogEntry {
@@ -205,7 +230,7 @@ export class DigestAction extends SelfAction {
}
}

export class ReleaseAction extends PairAction {
export class ReleaseAction extends Action {
allowed (user: Creature, target: Creature) {
if (target.containedIn === this.container && this.container.contents.indexOf(target) >= 0) {
return super.allowed(user, target)
@@ -215,7 +240,11 @@ export class ReleaseAction extends PairAction {
}

constructor (protected container: Container) {
super(new DynText('Release (', new LiveText(container, x => x.name.all), ')'), 'Release one of your prey', [new CapableCondition()])
super(
new DynText('Release (', new LiveText(container, x => x.name.all), ')'),
'Release one of your prey',
[new CapableCondition(), new PairCondition()]
)
}

execute (user: Creature, target: Creature): LogEntry {
@@ -227,7 +256,7 @@ export class ReleaseAction extends PairAction {
}
}

export class TransferAction extends PairAction {
export class TransferAction extends Action {
lines: POVPairArgs<Entity, Entity, { from: Container; to: Container }> = new POVPairArgs([
[[POV.First, POV.Third], (user, target, args) => new LogLine(`You squeeze ${target.name} from your ${args.from.name} to your ${args.to.name}`)],
[[POV.Third, POV.First], (user, target, args) => new LogLine(`You're squeezed from ${user.name}'s ${args.from.name} to ${user.pronouns.possessive} ${args.to.name}`)],
@@ -243,7 +272,11 @@ export class TransferAction extends PairAction {
}

constructor (protected from: Container, protected to: Container, name = 'Transfer') {
super(name, `${from.name.all.capital} to ${to.name.all}`, [new CapableCondition()])
super(
name,
`${from.name.all.capital} to ${to.name.all}`,
[new CapableCondition(), new PairCondition()]
)
}

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


+ 25
- 1
src/game/combat/conditions.ts Целия файл

@@ -27,9 +27,21 @@ export class DrainedVigorCondition implements Condition {
}
}

export class SoloCondition implements Condition {
allowed (user: Creature, target: Creature): boolean {
return user === target
}
}

export class PairCondition implements Condition {
allowed (user: Creature, target: Creature): boolean {
return user !== target
}
}

export class TogetherCondition implements Condition {
allowed (user: Creature, target: Creature): boolean {
return user.containedIn === target.containedIn
return user.containedIn === target.containedIn && user !== target
}
}

@@ -42,3 +54,15 @@ export class ContainerCondition implements Condition {

}
}

export class AllyCondition implements Condition {
allowed (user: Creature, target: Creature): boolean {
return user.side === target.side
}
}

export class EnemyCondition implements Condition {
allowed (user: Creature, target: Creature): boolean {
return user.side !== target.side
}
}

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

@@ -3,5 +3,6 @@ import { Player } from './creatures/player'
import { Cafat } from './creatures/cafat'
import { Human } from './creatures/human'
import { Withers } from './creatures/withers'
import { Kenzie } from './creatures/kenzie'

export { Wolf, Player, Cafat, Human, Withers }
export { Wolf, Player, Cafat, Human, Withers, Kenzie }

+ 34
- 0
src/game/creatures/kenzie.ts Целия файл

@@ -0,0 +1,34 @@
import { Creature, POV } from '../entity'
import { ProperNoun, ImproperNoun, FemalePronouns, POVPairArgs, POVPair } from '../language'
import { VoreType, Stomach, Vore } from '../vore'
import { Side, Damage, DamageType, Vigor, UniformRandomDamageFormula } from '../combat'
import { LogLine } from '../interface'
import { FeedAction, TransferAction } from '../combat/actions'
import * as Words from '../words'

export class Kenzie extends Creature {
title = "Large Lycanroc"
desc = "Will eat your party"

constructor () {
super(
new ProperNoun('Kenzie'),
new ImproperNoun('lycanroc', 'lycanrocs'),
FemalePronouns,
{ Toughness: 60, Power: 70, Speed: 40, Willpower: 60, Charm: 120 },
new Set(),
new Set([VoreType.Oral]),
1000
)

this.side = Side.Monsters

const stomach = new Stomach(this, 50, new Damage(
{ amount: 100, type: DamageType.Acid, target: Vigor.Health },
{ amount: 100, type: DamageType.Crush, target: Vigor.Stamina },
{ amount: 100, type: DamageType.Dominance, target: Vigor.Resolve }
))

this.containers.push(stomach)
}
}

+ 23
- 16
src/game/creatures/withers.ts Целия файл

@@ -1,10 +1,10 @@
import { Creature, POV } from '../entity'
import { Damage, DamageType, ConstantDamageFormula, Vigor, Side, GroupAction, CombatTest, Stat, Action, DamageFormula, UniformRandomDamageFormula, PairAction } from '../combat'
import { Damage, DamageType, ConstantDamageFormula, Vigor, Side, GroupAction, CombatTest, Stat, DamageFormula, UniformRandomDamageFormula, Action } from '../combat'
import { ImproperNoun, POVPair, ProperNoun, FemalePronouns, RandomWord, Adjective, POVPairArgs, POVSoloArgs, Verb } from '../language'
import { LogLine, LogLines, LogEntry, Newline } from '../interface'
import { VoreType, Stomach, VoreContainer, Vore, NormalContainer, Container } from '../vore'
import { AttackAction, FeedAction, TransferAction, EatenAction } from '../combat/actions'
import { TogetherCondition, ContainerCondition } from '../combat/conditions'
import { TogetherCondition, ContainerCondition, EnemyCondition } from '../combat/conditions'
import { InstantKill } from '../combat/effects'
import * as Words from '../words'
import { StatVigorTest } from '../combat/tests'
@@ -92,12 +92,14 @@ class BootContainer extends NormalContainer {
constructor (owner: Vore) {
super(new ImproperNoun('boot'), owner, new Set(), 50)

const flex = new FlexToesAction(new UniformRandomDamageFormula(new Damage(
{ target: Vigor.Health, type: DamageType.Crush, amount: 50 },
{ target: Vigor.Stamina, type: DamageType.Crush, amount: 50 },
{ target: Vigor.Resolve, type: DamageType.Crush, amount: 50 }
), 0.5),
this)
const flex = new FlexToesAction(
new UniformRandomDamageFormula(new Damage(
{ target: Vigor.Health, type: DamageType.Crush, amount: 50 },
{ target: Vigor.Stamina, type: DamageType.Crush, amount: 50 },
{ target: Vigor.Resolve, type: DamageType.Crush, amount: 50 }
), 0.5),
this
)

this.actions.push(flex)
}
@@ -179,7 +181,8 @@ class StompAction extends GroupAction {

constructor () {
super('Stomp', 'STOMP!', [
new TogetherCondition()
new TogetherCondition(),
new EnemyCondition()
])
}
}
@@ -222,7 +225,8 @@ class DevourAllAction extends GroupAction {

constructor (private container: VoreContainer) {
super('Devour All', 'GULP!', [
new TogetherCondition()
new TogetherCondition(),
new EnemyCondition()
])
this.test = new StatVigorTest(Stat.Power)
}
@@ -240,7 +244,8 @@ export class Withers extends Creature {
{ Toughness: 60, Power: 70, Speed: 40, Willpower: 60, Charm: 120 },
new Set(),
new Set([VoreType.Oral]),
5000)
5000
)

this.actions.push(new BiteAction())
this.groupActions.push(new StompAction())
@@ -274,11 +279,13 @@ export class Withers extends Creature {

this.otherContainers.push(maw)

this.actions.push(new ChewAction(new UniformRandomDamageFormula(new Damage(
{ target: Vigor.Health, type: DamageType.Crush, amount: 10000 }
), 0.5),
maw,
new TransferAction(maw, stomach)))
this.actions.push(new ChewAction(
new UniformRandomDamageFormula(new Damage(
{ target: Vigor.Health, type: DamageType.Crush, amount: 10000 }
), 0.5),
maw,
new TransferAction(maw, stomach)
))

const boot = new BootContainer(this)
this.otherContainers.push(boot)


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

@@ -3,6 +3,7 @@ import { Damage, DamageType, Stats, Actionable, Action, Vigor, VoreStats } from
import { LogLines, LogEntry, CompositeLog, LogLine } from './interface'
import { Noun, Pronoun, POVPair, POVPairArgs, ImproperNoun, POVSolo, TextLike, Verb, Word } from './language'
import { DigestAction, DevourAction, ReleaseAction, StruggleAction } from './combat/actions'
import * as Words from './words'

export enum VoreType {
Oral = "Oral Vore",
@@ -242,15 +243,15 @@ export class Stomach extends NormalVoreContainer {
])

tickLines = new POVPairArgs<Vore, Vore, { damage: Damage }>([
[[POV.First, POV.Third], (user, target, args) => new LogLine(`Your stomach gurgles ${target.name} for `, args.damage.renderShort())],
[[POV.Third, POV.First], (user, target, args) => new LogLine(`${user.name.capital}'s stomach churns you for `, args.damage.renderShort())],
[[POV.Third, POV.Third], (user, target, args) => new LogLine(`${user.name.capital} churns ${target.name} for `, args.damage.renderShort())]
[[POV.First, POV.Third], (user, target, args) => new LogLine(`Your stomach ${Words.Churns.singular} ${target.name} for `, args.damage.renderShort())],
[[POV.Third, POV.First], (user, target, args) => new LogLine(`${user.name.capital}'s stomach ${Words.Churns.singular} you for `, args.damage.renderShort())],
[[POV.Third, POV.Third], (user, target, args) => new LogLine(`${user.name.capital} ${Words.Churns.singular} ${target.name} for `, args.damage.renderShort())]
])

digestLines = new POVPair<Vore, Vore>([
[[POV.First, POV.Third], (user, target) => new LogLine(`Your stomach overwhelms ${target.name}`)],
[[POV.Third, POV.First], (user, target) => new LogLine(`${user.name.capital}'s stomach finishes you off`)],
[[POV.Third, POV.Third], (user, target) => new LogLine(`${target.name.capital}'s squirms fade, overwhelmed by the stomach of ${user.name}`)]
[[POV.First, POV.Third], (user, target) => new LogLine(`Your stomach ${Words.Digests.singular} ${target.name}`)],
[[POV.Third, POV.First], (user, target) => new LogLine(`${user.name.capital}'s stomach ${Words.Digests.singular} you`)],
[[POV.Third, POV.Third], (user, target) => new LogLine(`${target.name.capital}'s ${Words.Struggles.present} fades as the ${target.kind.all} is ${Words.Digests.past} by the ${user.kind.all}'s ${this.name}.`)]
])

absorbLines = new POVPair<Vore, Vore>([


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