| @@ -69,6 +69,7 @@ export default class App extends Vue { | |||
| player.side = Side.Heroes | |||
| player.equipment.set(Items.EquipmentSlot.MainHand, new Items.Sword()) | |||
| player.equipment.set(Items.EquipmentSlot.Head, new Items.Helmet()) | |||
| player.items.push(new Items.HealthPotion()) | |||
| player.items.push(new Items.Mace()) | |||
| player.items.push(new Items.Dagger()) | |||
| this.$data.world = new World(player) | |||
| @@ -166,7 +166,6 @@ export default class Combat extends Vue { | |||
| pickNext () { | |||
| // Did one side win? | |||
| console.log(this.encounter.winner, this.encounter.totalWinner) | |||
| if (this.encounter.totalWinner !== null && !this.$data.totalWon) { | |||
| this.$data.totalWon = true | |||
| @@ -158,7 +158,6 @@ export default class Statblock extends Vue { | |||
| this.statusChanged([]) | |||
| const picker = this.$el.querySelector(".ai-picker") as HTMLSelectElement | |||
| console.log(this.$data.ais.indexOf(this.subject.ai)) | |||
| picker.selectedIndex = this.$data.ais.findIndex((ai: AI) => ai.name === this.subject.ai.name) | |||
| } | |||
| } | |||
| @@ -347,7 +347,7 @@ export interface Combatant { | |||
| * An Action is anything that can be done by a [[Creature]] to a [[Creature]]. | |||
| */ | |||
| export abstract class Action { | |||
| constructor (public name: TextLike, public desc: TextLike, private conditions: Array<Condition> = []) { | |||
| constructor (public name: TextLike, public desc: TextLike, public conditions: Array<Condition> = []) { | |||
| } | |||
| @@ -590,7 +590,6 @@ export class Encounter { | |||
| if (effectResults.some(result => result.prevented)) { | |||
| const parts = effectResults.map(result => result.log).concat([this.nextMove()]) | |||
| console.log(parts) | |||
| return new LogLines( | |||
| ...parts | |||
| ) | |||
| @@ -42,6 +42,23 @@ export class DamageConsequence extends Consequence { | |||
| } | |||
| } | |||
| /** | |||
| * Same as [[DamageConsequence]], but it has healing text | |||
| */ | |||
| export class HealingConsequence extends Consequence { | |||
| constructor (private damageFormula: DamageFormula, conditions: Condition[] = []) { | |||
| super(conditions) | |||
| } | |||
| apply (user: Creature, target: Creature): LogEntry { | |||
| const damage = this.damageFormula.calc(user, target) | |||
| return new LogLines( | |||
| new LogLine(`${target.name.capital} ${target.name.conjugate(new Verb('heal'))} `, damage.renderShort(), `!`), | |||
| target.takeDamage(damage) | |||
| ) | |||
| } | |||
| } | |||
| /** | |||
| * Applies a status effect | |||
| */ | |||
| @@ -2,7 +2,7 @@ import { Damage, Combatant, Stats, Action, Vigor, Side, GroupAction, VisibleStat | |||
| import { Noun, Pronoun } from './language' | |||
| import { LogEntry, LogLines } from './interface' | |||
| import { Vore, VoreContainer, VoreType } from './vore' | |||
| import { Item, EquipmentSlot, Equipment } from './items' | |||
| import { Item, EquipmentSlot, Equipment, ItemKind } from './items' | |||
| import { PassAction } from './combat/actions' | |||
| import { AI, NoAI } from './ai' | |||
| @@ -102,7 +102,8 @@ export class Creature extends Vore implements Combatant { | |||
| this.containers.flatMap(container => container.actions), | |||
| target.otherActions, | |||
| this.otherContainers.flatMap(container => container.actions), | |||
| Array.from(this.equipment.values()).flatMap(item => item.actions) | |||
| Array.from(this.equipment.values()).flatMap(item => item.actions), | |||
| this.items.filter(item => item.kind === ItemKind.Consumable && !item.consumed).flatMap(item => item.actions) | |||
| ) | |||
| if (this.containedIn !== null) { | |||
| @@ -1,8 +1,12 @@ | |||
| import { TextLike, LiveText, DynText, Word, ImproperNoun, Verb } from './language' | |||
| import { Actionable, Action, DamageFormula, ConstantDamageFormula, Damage, DamageType, Vigor, StatDamageFormula, Stat, Effective } from './combat' | |||
| import { Actionable, Action, DamageFormula, ConstantDamageFormula, Damage, DamageType, Vigor, StatDamageFormula, Stat, Effective, CompositionAction, Condition } from './combat' | |||
| import { AttackAction } from './combat/actions' | |||
| import { Resistances } from './entity' | |||
| import { DamageTypeResistanceEffect } from './combat/effects' | |||
| import { DamageConsequence, LogConsequence, HealingConsequence } from './combat/consequences' | |||
| import { SoloCondition } from './combat/conditions' | |||
| import { LogLine, LogEntry } from './interface' | |||
| import { Creature } from './creature' | |||
| export enum ItemKind { | |||
| Key = "Key Item", | |||
| @@ -19,6 +23,7 @@ export const ItemKindIcons: {[key in ItemKind]: string} = { | |||
| export abstract class Item implements Actionable { | |||
| actions: Array<Action> = [] | |||
| effects: Array<Effective> = [] | |||
| consumed = false | |||
| abstract kind: ItemKind | |||
| constructor (public name: Word, public desc: TextLike) { | |||
| @@ -139,3 +144,64 @@ export class Helmet extends Armor { | |||
| ) | |||
| } | |||
| } | |||
| export class ItemAction extends Action { | |||
| constructor (name: TextLike, desc: TextLike, private item: Item, private action: Action) { | |||
| super(name, desc, action.conditions) | |||
| } | |||
| execute (user: Creature, target: Creature): LogEntry { | |||
| this.item.consumed = true | |||
| return this.action.execute(user, target) | |||
| } | |||
| describe (user: Creature, target: Creature): LogEntry { | |||
| return this.action.describe(user, target) | |||
| } | |||
| } | |||
| export class Consumable extends Item { | |||
| kind = ItemKind.Consumable | |||
| constructor (name: Word, desc: TextLike, onUse: Action) { | |||
| super(name, desc) | |||
| this.actions.push(new ItemAction( | |||
| onUse.name, | |||
| onUse.desc, | |||
| this, | |||
| onUse | |||
| )) | |||
| } | |||
| } | |||
| export class HealthPotion extends Consumable { | |||
| constructor () { | |||
| super( | |||
| new ImproperNoun("health potion"), | |||
| "Restores all of your vigors", | |||
| new CompositionAction( | |||
| "Drink Potion", | |||
| "Heals your vigors", | |||
| { | |||
| conditions: [ | |||
| new SoloCondition() | |||
| ], | |||
| consequences: [ | |||
| new LogConsequence( | |||
| (user, target) => new LogLine(`${user.name.capital} ${user.name.conjugate(new Verb('drink'))} a potion.`) | |||
| ), | |||
| new HealingConsequence( | |||
| new ConstantDamageFormula( | |||
| new Damage( | |||
| { amount: 100, target: Vigor.Health, type: DamageType.Heal }, | |||
| { amount: 100, target: Vigor.Stamina, type: DamageType.Heal }, | |||
| { amount: 100, target: Vigor.Resolve, type: DamageType.Heal } | |||
| ) | |||
| ) | |||
| ) | |||
| ] | |||
| } | |||
| ) | |||
| ) | |||
| } | |||
| } | |||