| @@ -11,7 +11,7 @@ import Combat from './components/Combat.vue' | |||||
| import Header from './components/Header.vue' | import Header from './components/Header.vue' | ||||
| import * as Creatures from '@/game/creatures' | import * as Creatures from '@/game/creatures' | ||||
| import * as Items from '@/game/items' | import * as Items from '@/game/items' | ||||
| import { Creature } from '@/game/entity' | |||||
| import { Creature } from '@/game/creature' | |||||
| import { ProperNoun, TheyPronouns, FemalePronouns, MalePronouns, ImproperNoun } from '@/game/language' | import { ProperNoun, TheyPronouns, FemalePronouns, MalePronouns, ImproperNoun } from '@/game/language' | ||||
| import { Encounter } from './game/combat' | import { Encounter } from './game/combat' | ||||
| @@ -26,6 +26,8 @@ export default class App extends Vue { | |||||
| constructor () { | constructor () { | ||||
| super() | super() | ||||
| console.log(new Creatures.Cafat()) | |||||
| const fighter = new Creatures.Human(new ProperNoun("Redgar"), MalePronouns, { | const fighter = new Creatures.Human(new ProperNoun("Redgar"), MalePronouns, { | ||||
| stats: { | stats: { | ||||
| Toughness: 20, | Toughness: 20, | ||||
| @@ -9,7 +9,7 @@ | |||||
| import { Component, Prop, Vue, Watch, Emit } from 'vue-property-decorator' | import { Component, Prop, Vue, Watch, Emit } from 'vue-property-decorator' | ||||
| import { Action, GroupAction } from '@/game/combat' | import { Action, GroupAction } from '@/game/combat' | ||||
| import { Creature } from '@/game/entity' | |||||
| import { Creature } from '@/game/creature' | |||||
| @Component({}) | @Component({}) | ||||
| export default class ActionButton extends Vue { | export default class ActionButton extends Vue { | ||||
| @@ -43,7 +43,7 @@ | |||||
| <script lang="ts"> | <script lang="ts"> | ||||
| import { Component, Prop, Vue, Watch, Emit } from 'vue-property-decorator' | import { Component, Prop, Vue, Watch, Emit } from 'vue-property-decorator' | ||||
| import { Creature } from '@/game/entity' | |||||
| import { Creature } from '@/game/creature' | |||||
| import { POV } from '@/game/language' | import { POV } from '@/game/language' | ||||
| import { LogEntry } from '@/game/interface' | import { LogEntry } from '@/game/interface' | ||||
| import Statblock from './Statblock.vue' | import Statblock from './Statblock.vue' | ||||
| @@ -8,7 +8,7 @@ | |||||
| <script lang="ts"> | <script lang="ts"> | ||||
| import { Component, Prop, Vue, Watch, Emit } from 'vue-property-decorator' | import { Component, Prop, Vue, Watch, Emit } from 'vue-property-decorator' | ||||
| import { Creature } from '@/game/entity' | |||||
| import { Creature } from '@/game/creature' | |||||
| import { POV } from '@/game/language' | import { POV } from '@/game/language' | ||||
| import { Stats, Stat } from '@/game/combat' | import { Stats, Stat } from '@/game/combat' | ||||
| import { Container } from '@/game/vore' | import { Container } from '@/game/vore' | ||||
| @@ -66,7 +66,7 @@ | |||||
| <script lang="ts"> | <script lang="ts"> | ||||
| import { Component, Prop, Vue, Watch, Emit } from 'vue-property-decorator' | import { Component, Prop, Vue, Watch, Emit } from 'vue-property-decorator' | ||||
| import { Creature } from '@/game/entity' | |||||
| import { Creature } from '@/game/creature' | |||||
| import { POV } from '@/game/language' | import { POV } from '@/game/language' | ||||
| import { Stats, Stat, StatIcons, StatDescs, Vigor, VigorIcons, VigorDescs, VoreStatDescs, VoreStatIcons, VisibleStatus } from '@/game/combat' | import { Stats, Stat, StatIcons, StatDescs, Vigor, VigorIcons, VigorDescs, VoreStatDescs, VoreStatIcons, VisibleStatus } from '@/game/combat' | ||||
| import ContainerView from './ContainerView.vue' | import ContainerView from './ContainerView.vue' | ||||
| @@ -1,4 +1,4 @@ | |||||
| import { Creature } from './entity' | |||||
| import { Creature } from "./creature" | |||||
| import { TextLike, DynText, ToBe, LiveText } from './language' | import { TextLike, DynText, ToBe, LiveText } from './language' | ||||
| import { LogEntry, LogLines, FAElem, LogLine, FormatEntry, FormatOpt, PropElem, nilLog } from './interface' | import { LogEntry, LogLines, FAElem, LogLine, FormatEntry, FormatOpt, PropElem, nilLog } from './interface' | ||||
| @@ -1,6 +1,7 @@ | |||||
| import { StatTest, StatVigorTest } from './tests' | import { StatTest, StatVigorTest } from './tests' | ||||
| import { DynText, LiveText, TextLike, Verb, PairLine, PairLineArgs } from '../language' | import { DynText, LiveText, TextLike, Verb, PairLine, PairLineArgs } from '../language' | ||||
| import { Entity, Creature } from '../entity' | |||||
| import { Entity } from '../entity' | |||||
| import { Creature } from "../creature" | |||||
| import { Damage, DamageFormula, Stat, Vigor, Action } from '../combat' | import { Damage, DamageFormula, Stat, Vigor, Action } from '../combat' | ||||
| import { LogLine, LogLines, LogEntry, CompositeLog, nilLog } from '../interface' | import { LogLine, LogLines, LogEntry, CompositeLog, nilLog } from '../interface' | ||||
| import { VoreContainer, Container } from '../vore' | import { VoreContainer, Container } from '../vore' | ||||
| @@ -1,5 +1,5 @@ | |||||
| import { Condition, Vigor } from "../combat" | import { Condition, Vigor } from "../combat" | ||||
| import { Creature } from "../entity" | |||||
| import { Creature } from "../creature" | |||||
| import { Container } from '../vore' | import { Container } from '../vore' | ||||
| export class InverseCondition implements Condition { | export class InverseCondition implements Condition { | ||||
| @@ -1,6 +1,6 @@ | |||||
| import { StatusEffect, Damage, DamageType, Action } from '../combat' | import { StatusEffect, Damage, DamageType, Action } from '../combat' | ||||
| import { DynText, LiveText, ToBe, Verb } from '../language' | import { DynText, LiveText, ToBe, Verb } from '../language' | ||||
| import { Creature } from '../entity' | |||||
| import { Creature } from "../creature" | |||||
| import { LogLine, LogEntry, LogLines, FAElem, nilLog } from '../interface' | import { LogLine, LogEntry, LogLines, FAElem, nilLog } from '../interface' | ||||
| export class InstantKillEffect extends StatusEffect { | export class InstantKillEffect extends StatusEffect { | ||||
| @@ -1,5 +1,5 @@ | |||||
| import { CombatTest, Stat, Vigor } from '../combat' | import { CombatTest, Stat, Vigor } from '../combat' | ||||
| import { Creature } from '../entity' | |||||
| import { Creature } from "../creature" | |||||
| import { LogEntry, LogLines, PropElem, LogLine } from '../interface' | import { LogEntry, LogLines, PropElem, LogLine } from '../interface' | ||||
| function logistic (x0: number, L: number, k: number): (x: number) => number { | function logistic (x0: number, L: number, k: number): (x: number) => number { | ||||
| @@ -0,0 +1,104 @@ | |||||
| import { Damage, Combatant, Stats, Action, Vigor, Side, GroupAction, VisibleStatus, ImplicitStatus, StatusEffect } from './combat' | |||||
| import { Noun, Pronoun } from './language' | |||||
| import { LogEntry, LogLines } from './interface' | |||||
| import { Vore, VoreContainer, VoreType } from './vore' | |||||
| import { Item } from './items' | |||||
| import { PassAction } from './combat/actions' | |||||
| export class Creature extends Vore implements Combatant { | |||||
| actions: Array<Action> = []; | |||||
| containedIn: VoreContainer | null = null; | |||||
| desc = "Some creature"; | |||||
| effects: Array<StatusEffect> = []; | |||||
| groupActions: Array<GroupAction> = []; | |||||
| items: Array<Item> = []; | |||||
| otherActions: Array<Action> = []; | |||||
| side: Side; | |||||
| title = "Lv. 1 Creature"; | |||||
| constructor (name: Noun, kind: Noun, pronouns: Pronoun, stats: Stats, preyPrefs: Set<VoreType>, predPrefs: Set<VoreType>, mass: number) { | |||||
| super(name, kind, pronouns, stats, preyPrefs, predPrefs, mass) | |||||
| this.actions.push(new PassAction()) | |||||
| this.side = Side.Heroes | |||||
| } | |||||
| applyEffect (effect: StatusEffect): LogEntry { | |||||
| this.effects.push(effect) | |||||
| return effect.onApply(this) | |||||
| } | |||||
| /** | |||||
| * Determines how much damage an attack would do | |||||
| */ | |||||
| effectiveDamage (damage: Damage): Damage { | |||||
| return this.effects.reduce((modifiedDamage: Damage, effect: StatusEffect) => { | |||||
| return effect.preDamage(this, modifiedDamage) | |||||
| }, damage) | |||||
| } | |||||
| executeAction (action: Action, target: Creature): LogEntry { | |||||
| const effectResults = this.effects.map(effect => effect.preAction(this)) | |||||
| const blocking = effectResults.filter(result => result.prevented) | |||||
| if (blocking.length > 0) { | |||||
| return new LogLines(...blocking.map(result => result.log)) | |||||
| } else { | |||||
| return action.execute(this, target) | |||||
| } | |||||
| } | |||||
| removeEffect (effect: StatusEffect): LogEntry { | |||||
| this.effects = this.effects.filter(eff => eff !== effect) | |||||
| return effect.onRemove(this) | |||||
| } | |||||
| get status (): Array<VisibleStatus> { | |||||
| const results: Array<VisibleStatus> = [] | |||||
| if (this.vigors[Vigor.Health] <= 0) { | |||||
| results.push(new ImplicitStatus('Dead', 'Out of health', 'fas fa-heart')) | |||||
| } | |||||
| if (this.vigors[Vigor.Stamina] <= 0) { | |||||
| results.push(new ImplicitStatus('Unconscious', 'Out of stamina', 'fas fa-bolt')) | |||||
| } | |||||
| if (this.vigors[Vigor.Resolve] <= 0) { | |||||
| results.push(new ImplicitStatus('Broken', 'Out of resolve', 'fas fa-brain')) | |||||
| } | |||||
| if (this.containedIn !== null) { | |||||
| results.push(new ImplicitStatus('Eaten', 'Devoured by ' + this.containedIn.owner.name, 'fas fa-drumstick-bite')) | |||||
| } | |||||
| this.effects.forEach(effect => { | |||||
| results.push(effect) | |||||
| }) | |||||
| return results | |||||
| } | |||||
| validActions (target: Creature): Array<Action> { | |||||
| let choices = this.actions.concat( | |||||
| this.containers.flatMap(container => container.actions) | |||||
| ).concat( | |||||
| target.otherActions.concat( | |||||
| this.otherContainers.flatMap(container => container.actions).concat( | |||||
| this.items.flatMap(item => item.actions) | |||||
| ) | |||||
| ) | |||||
| ) | |||||
| if (this.containedIn !== null) { | |||||
| choices = choices.concat(this.containedIn.actions) | |||||
| } | |||||
| return choices.filter(action => { | |||||
| return action.allowed(this, target) | |||||
| }) | |||||
| } | |||||
| validGroupActions (targets: Array<Creature>): Array<GroupAction> { | |||||
| const choices = this.groupActions | |||||
| return choices.filter(action => { | |||||
| return targets.some(target => action.allowed(this, target)) | |||||
| }) | |||||
| } | |||||
| } | |||||
| @@ -1,8 +1,8 @@ | |||||
| import { Creature, Entity } from '../entity' | |||||
| import { Creature } from "../creature" | |||||
| import { Stat, Damage, DamageType, Vigor, ConstantDamageFormula, Side } from '../combat' | import { Stat, Damage, DamageType, Vigor, ConstantDamageFormula, Side } from '../combat' | ||||
| import { ProperNoun, TheyPronouns, ImproperNoun, FemalePronouns, Verb, POV, PairLineArgs, PairLine } from '../language' | |||||
| import { ProperNoun, TheyPronouns, ImproperNoun, FemalePronouns, Verb, PairLineArgs } from '../language' | |||||
| import { VoreType, Stomach, InnerStomach, VoreContainer } from '../vore' | import { VoreType, Stomach, InnerStomach, VoreContainer } from '../vore' | ||||
| import { LogLine, LogLines, LogEntry, FAElem, CompositeLog, ImgElem } from '../interface' | |||||
| import { LogLine, LogLines, LogEntry, FAElem, ImgElem } from '../interface' | |||||
| import { AttackAction, EatenAction, TransferAction, FeedAction } from '../combat/actions' | import { AttackAction, EatenAction, TransferAction, FeedAction } from '../combat/actions' | ||||
| import { InstantKillEffect } from '../combat/effects' | import { InstantKillEffect } from '../combat/effects' | ||||
| import * as Words from '../words' | import * as Words from '../words' | ||||
| @@ -1,8 +1,7 @@ | |||||
| import { Creature } from '../entity' | |||||
| import { Damage, DamageType, ConstantDamageFormula, Vigor, Stats, Vigors } from '../combat' | |||||
| import { MalePronouns, Noun, Pronoun, ImproperNoun } from '../language' | |||||
| import { Creature } from "../creature" | |||||
| import { Vigor, Stats, Vigors } from '../combat' | |||||
| import { Noun, Pronoun, ImproperNoun } from '../language' | |||||
| import { VoreType } from '../vore' | import { VoreType } from '../vore' | ||||
| import { AttackAction } from '../combat/actions' | |||||
| export class Human extends Creature { | export class Human extends Creature { | ||||
| constructor (name: Noun, pronouns: Pronoun, options: { | constructor (name: Noun, pronouns: Pronoun, options: { | ||||
| @@ -1,4 +1,4 @@ | |||||
| import { Creature } from '../entity' | |||||
| import { Creature } from "../creature" | |||||
| import { ProperNoun, ImproperNoun, FemalePronouns, Verb } from '../language' | import { ProperNoun, ImproperNoun, FemalePronouns, Verb } from '../language' | ||||
| import { VoreType, Stomach } from '../vore' | import { VoreType, Stomach } from '../vore' | ||||
| import { Side, Damage, DamageType, Vigor, StatDamageFormula, Stat, VoreStat, DamageFormula } from '../combat' | import { Side, Damage, DamageType, Vigor, StatDamageFormula, Stat, VoreStat, DamageFormula } from '../combat' | ||||
| @@ -1,6 +1,6 @@ | |||||
| import { Creature } from '../entity' | |||||
| import { Creature } from "../creature" | |||||
| import { ProperNoun, TheyPronouns, ImproperNoun, POV } from '../language' | import { ProperNoun, TheyPronouns, ImproperNoun, POV } from '../language' | ||||
| import { Stat, Damage, DamageType, Vigor, ConstantDamageFormula } from '../combat' | |||||
| import { Damage, DamageType, Vigor, ConstantDamageFormula } from '../combat' | |||||
| import { Stomach, Bowels, VoreType } from '../vore' | import { Stomach, Bowels, VoreType } from '../vore' | ||||
| import { AttackAction } from '../combat/actions' | import { AttackAction } from '../combat/actions' | ||||
| @@ -1,11 +1,11 @@ | |||||
| import { Creature } from '../entity' | |||||
| import { Creature } from "../creature" | |||||
| import { Damage, DamageType, ConstantDamageFormula, Vigor, Side, GroupAction, CombatTest, Stat, DamageFormula, UniformRandomDamageFormula, Action, DamageInstance, StatDamageFormula, VoreStat } from '../combat' | import { Damage, DamageType, ConstantDamageFormula, Vigor, Side, GroupAction, CombatTest, Stat, DamageFormula, UniformRandomDamageFormula, Action, DamageInstance, StatDamageFormula, VoreStat } from '../combat' | ||||
| import { ImproperNoun, ProperNoun, FemalePronouns, RandomWord, Adjective, Verb, POV, PairLine } from '../language' | |||||
| import { ImproperNoun, ProperNoun, FemalePronouns, RandomWord, Adjective, Verb, PairLine } from '../language' | |||||
| import { LogLine, LogLines, LogEntry, Newline } from '../interface' | import { LogLine, LogLines, LogEntry, Newline } from '../interface' | ||||
| import { VoreType, Stomach, VoreContainer, Vore, NormalContainer, Container, InnerStomach } from '../vore' | |||||
| import { AttackAction, FeedAction, TransferAction, EatenAction, DevourAction } from '../combat/actions' | |||||
| import { VoreType, Stomach, VoreContainer, Vore, NormalContainer, Container } from '../vore' | |||||
| import { AttackAction, FeedAction, TransferAction } from '../combat/actions' | |||||
| import { TogetherCondition, ContainsCondition, EnemyCondition, AllyCondition, PairCondition, CapableCondition } from '../combat/conditions' | import { TogetherCondition, ContainsCondition, EnemyCondition, AllyCondition, PairCondition, CapableCondition } from '../combat/conditions' | ||||
| import { InstantKillEffect, ShieldEffect, PredatorCounterEffect } from '../combat/effects' | |||||
| import { InstantKillEffect, ShieldEffect } from '../combat/effects' | |||||
| import * as Words from '../words' | import * as Words from '../words' | ||||
| import { StatVigorTest } from '../combat/tests' | import { StatVigorTest } from '../combat/tests' | ||||
| @@ -1,4 +1,4 @@ | |||||
| import { Creature } from '../entity' | |||||
| import { Creature } from "../creature" | |||||
| import { Damage, DamageType, ConstantDamageFormula, Vigor, Side } from '../combat' | import { Damage, DamageType, ConstantDamageFormula, Vigor, Side } from '../combat' | ||||
| import { MalePronouns, ImproperNoun } from '../language' | import { MalePronouns, ImproperNoun } from '../language' | ||||
| import { VoreType, Stomach, Bowels } from '../vore' | import { VoreType, Stomach, Bowels } from '../vore' | ||||
| @@ -1,9 +1,7 @@ | |||||
| import { DamageType, Damage, Combatant, Stats, Action, Vigor, VoreStats, VoreStat, Stat, Side, GroupAction, Vigors, VisibleStatus, ImplicitStatus, StatusEffect } from './combat' | |||||
| import { DamageType, Damage, Stats, Vigor, VoreStats, VoreStat, Stat, Vigors } from './combat' | |||||
| import { Noun, Pronoun, TextLike, POV, PronounAsNoun, FirstPersonPronouns, SecondPersonPronouns } from './language' | import { Noun, Pronoun, TextLike, POV, PronounAsNoun, FirstPersonPronouns, SecondPersonPronouns } from './language' | ||||
| import { LogEntry, LogLine, LogLines } from './interface' | |||||
| import { Vore, VoreContainer, VoreType, Container } from './vore' | |||||
| import { Item } from './items' | |||||
| import { PassAction } from './combat/actions' | |||||
| import { LogEntry, LogLine } from './interface' | |||||
| import { Container } from './vore' | |||||
| export abstract class Entity { | export abstract class Entity { | ||||
| get name (): Noun { | get name (): Noun { | ||||
| @@ -46,11 +44,10 @@ export abstract class Mortal extends Entity { | |||||
| constructor (name: Noun, kind: Noun, pronouns: Pronoun, public baseStats: Stats) { | constructor (name: Noun, kind: Noun, pronouns: Pronoun, public baseStats: Stats) { | ||||
| super(name, kind, pronouns) | super(name, kind, pronouns) | ||||
| this.stats = Object.keys(Stat).reduce((base: any, key) => { base[key] = baseStats[key as Stat]; return base }, {}) | |||||
| Object.entries(this.maxVigors).forEach(([key, val]) => { | Object.entries(this.maxVigors).forEach(([key, val]) => { | ||||
| this.vigors[key as Vigor] = val | this.vigors[key as Vigor] = val | ||||
| }) | }) | ||||
| this.stats = Object.keys(Stat).reduce((base: any, key) => { base[key] = baseStats[key as Stat]; return base }, {}) | |||||
| } | } | ||||
| get maxVigors (): Readonly<Vigors> { | get maxVigors (): Readonly<Vigors> { | ||||
| @@ -105,101 +102,3 @@ export abstract class Mortal extends Entity { | |||||
| abstract destroy (): LogEntry; | abstract destroy (): LogEntry; | ||||
| abstract effectiveDamage (damage: Damage): Damage | abstract effectiveDamage (damage: Damage): Damage | ||||
| } | } | ||||
| export class Creature extends Vore implements Combatant { | |||||
| actions: Array<Action> = [] | |||||
| containedIn: VoreContainer|null = null; | |||||
| desc = "Some creature" | |||||
| effects: Array<StatusEffect> = [] | |||||
| groupActions: Array<GroupAction> = [] | |||||
| items: Array<Item> = [] | |||||
| otherActions: Array<Action> = [] | |||||
| side: Side | |||||
| title = "Lv. 1 Creature" | |||||
| constructor (name: Noun, kind: Noun, pronouns: Pronoun, stats: Stats, preyPrefs: Set<VoreType>, predPrefs: Set<VoreType>, mass: number) { | |||||
| super(name, kind, pronouns, stats, preyPrefs, predPrefs, mass) | |||||
| this.actions.push(new PassAction()) | |||||
| this.side = Side.Heroes | |||||
| } | |||||
| applyEffect (effect: StatusEffect): LogEntry { | |||||
| this.effects.push(effect) | |||||
| return effect.onApply(this) | |||||
| } | |||||
| /** | |||||
| * Determines how much damage an attack would do | |||||
| */ | |||||
| effectiveDamage (damage: Damage): Damage { | |||||
| return this.effects.reduce((modifiedDamage: Damage, effect: StatusEffect) => { | |||||
| return effect.preDamage(this, modifiedDamage) | |||||
| }, damage) | |||||
| } | |||||
| executeAction (action: Action, target: Creature): LogEntry { | |||||
| const effectResults = this.effects.map(effect => effect.preAction(this)) | |||||
| const blocking = effectResults.filter(result => result.prevented) | |||||
| if (blocking.length > 0) { | |||||
| return new LogLines(...blocking.map(result => result.log)) | |||||
| } else { | |||||
| return action.execute(this, target) | |||||
| } | |||||
| } | |||||
| removeEffect (effect: StatusEffect): LogEntry { | |||||
| this.effects = this.effects.filter(eff => eff !== effect) | |||||
| return effect.onRemove(this) | |||||
| } | |||||
| get status (): Array<VisibleStatus> { | |||||
| const results: Array<VisibleStatus> = [] | |||||
| if (this.vigors[Vigor.Health] <= 0) { | |||||
| results.push(new ImplicitStatus('Dead', 'Out of health', 'fas fa-heart')) | |||||
| } | |||||
| if (this.vigors[Vigor.Stamina] <= 0) { | |||||
| results.push(new ImplicitStatus('Unconscious', 'Out of stamina', 'fas fa-bolt')) | |||||
| } | |||||
| if (this.vigors[Vigor.Resolve] <= 0) { | |||||
| results.push(new ImplicitStatus('Broken', 'Out of resolve', 'fas fa-brain')) | |||||
| } | |||||
| if (this.containedIn !== null) { | |||||
| results.push(new ImplicitStatus('Eaten', 'Devoured by ' + this.containedIn.owner.name, 'fas fa-drumstick-bite')) | |||||
| } | |||||
| this.effects.forEach(effect => { | |||||
| results.push(effect) | |||||
| }) | |||||
| return results | |||||
| } | |||||
| validActions (target: Creature): Array<Action> { | |||||
| let choices = this.actions.concat( | |||||
| this.containers.flatMap(container => container.actions) | |||||
| ).concat( | |||||
| target.otherActions.concat( | |||||
| this.otherContainers.flatMap(container => container.actions).concat( | |||||
| this.items.flatMap(item => item.actions) | |||||
| ) | |||||
| ) | |||||
| ) | |||||
| if (this.containedIn !== null) { | |||||
| choices = choices.concat(this.containedIn.actions) | |||||
| } | |||||
| return choices.filter(action => { | |||||
| return action.allowed(this, target) | |||||
| }) | |||||
| } | |||||
| validGroupActions (targets: Array<Creature>): Array<GroupAction> { | |||||
| const choices = this.groupActions | |||||
| return choices.filter(action => { | |||||
| return targets.some(target => action.allowed(this, target)) | |||||
| }) | |||||
| } | |||||
| } | |||||