| @@ -13,6 +13,14 @@ | |||
| <div class="tooltip-body">{{ subject.desc }}</div> | |||
| </div> | |||
| </h2> | |||
| <div class="statblock-status-icons"> | |||
| <i :class="status.icon" v-for="(status, index) in subject.status" :key="'status' + index"> | |||
| <div class="tooltip-template"> | |||
| <div class="tooltip-title">{{ status.name }}</div> | |||
| <div class="tooltip-body">{{ status.desc }}</div> | |||
| </div> | |||
| </i> | |||
| </div> | |||
| <div class="stat-entry" v-for="vigor in Object.keys(subject.vigors)" v-bind:key="vigor"> | |||
| <div class="healthbar" v-bind:style="{'--fullness': (subject.vigors[vigor]/subject.maxVigors[vigor]*100) + '%', '--color': vigorColor(subject.vigors[vigor], subject.maxVigors[vigor]) }"> | |||
| <i :class="vigorIcons[vigor]" /> | |||
| @@ -44,7 +52,6 @@ | |||
| </div> | |||
| </div> | |||
| <button @click.stop="$emit('selectPredator')" v-if="subject.containedIn !== null">Select predator</button> | |||
| <div>Status: {{subject.status}}</div> | |||
| <button v-if="subject.perspective === POV.Third" @click.stop="subject.perspective = POV.Second">Second-person</button> | |||
| <button v-if="subject.perspective === POV.First" @click.stop="subject.perspective = POV.Third">Third-person</button> | |||
| <button v-if="subject.perspective === POV.Second" @click.stop="subject.perspective = POV.First">First-person</button> | |||
| @@ -57,9 +64,9 @@ | |||
| import { Component, Prop, Vue, Watch, Emit } from 'vue-property-decorator' | |||
| import { Creature } from '@/game/entity' | |||
| import { POV } from '@/game/language' | |||
| import { Stats, Stat, StatIcons, StatDescs, Vigor, VigorIcons, VigorDescs, VoreStatDescs, VoreStatIcons } from '@/game/combat' | |||
| import { Stats, Stat, StatIcons, StatDescs, Vigor, VigorIcons, VigorDescs, VoreStatDescs, VoreStatIcons, VisibleStatus } from '@/game/combat' | |||
| import ContainerView from './ContainerView.vue' | |||
| import tippy, { createSingleton } from 'tippy.js' | |||
| import tippy, { delegate, createSingleton } from 'tippy.js' | |||
| import 'tippy.js/dist/tippy.css' | |||
| @Component({ | |||
| @@ -119,6 +126,22 @@ export default class Statblock extends Vue { | |||
| }) | |||
| createSingleton(tippyInstances, { delay: 500 }) | |||
| } | |||
| @Watch('subject.status') | |||
| private statusChanged (a: Array<VisibleStatus>) { | |||
| this.$nextTick(() => { | |||
| const icons = Array.from(this.$el.querySelectorAll(".statblock-status-icons i")) as Array<HTMLElement> | |||
| icons.map(elem => { | |||
| const tooltip = elem.querySelector(".tooltip-template") as HTMLElement | |||
| console.log(elem, tooltip) | |||
| return tippy(elem, { | |||
| content: tooltip | |||
| }) | |||
| }) | |||
| }) | |||
| } | |||
| } | |||
| </script> | |||
| @@ -269,6 +292,16 @@ a { | |||
| .statblock[data-active] .if-not-selected { | |||
| display: none; | |||
| } | |||
| .statblock-status-icons { | |||
| display: flex; | |||
| justify-content: space-evenly; | |||
| min-height: 16pt; | |||
| } | |||
| .statblock-status-icons > i { | |||
| font-size: 16pt; | |||
| } | |||
| </style> | |||
| <style> | |||
| @@ -325,3 +325,12 @@ export abstract class GroupAction extends Action { | |||
| super(name, desc, conditions) | |||
| } | |||
| } | |||
| /** | |||
| * A displayable status effect (whether implicit, like being dead, or explicit, like having a stun effect on you) | |||
| */ | |||
| export class VisibleStatus { | |||
| constructor (public name: TextLike, public desc: TextLike, public icon: string) { | |||
| } | |||
| } | |||
| @@ -1,4 +1,4 @@ | |||
| import { DamageType, Damage, Combatant, Stats, Action, Vigor, VoreStats, VoreStat, Stat, Side, GroupAction, Vigors } from './combat' | |||
| import { DamageType, Damage, Combatant, Stats, Action, Vigor, VoreStats, VoreStat, Stat, Side, GroupAction, Vigors, VisibleStatus } from './combat' | |||
| import { Noun, Pronoun, TextLike, POV } from './language' | |||
| import { LogEntry, LogLine } from './interface' | |||
| import { Vore, VoreContainer, VoreType, Container } from './vore' | |||
| @@ -23,7 +23,7 @@ export interface Mortal extends Entity { | |||
| takeDamage: (damage: Damage) => void; | |||
| stats: Stats; | |||
| baseStats: Stats; | |||
| status: string; | |||
| status: VisibleStatus[]; | |||
| destroy: () => LogEntry; | |||
| } | |||
| @@ -148,21 +148,23 @@ export class Creature extends Vore implements Combatant { | |||
| } | |||
| } | |||
| get status (): string { | |||
| get status (): Array<VisibleStatus> { | |||
| const results: Array<VisibleStatus> = [] | |||
| if (this.vigors[Vigor.Health] <= 0) { | |||
| return "Dead" | |||
| results.push(new VisibleStatus('Dead', 'Out of health', 'fas fa-heart')) | |||
| } | |||
| if (this.vigors[Vigor.Stamina] <= 0) { | |||
| return "Unconscious" | |||
| results.push(new VisibleStatus('Unconscious', 'Out of stamina', 'fas fa-bolt')) | |||
| } | |||
| if (this.vigors[Vigor.Resolve] <= 0) { | |||
| return "Broken" | |||
| results.push(new VisibleStatus('Broken', 'Out of resolve', 'fas fa-brain')) | |||
| } | |||
| if (this.containedIn !== null) { | |||
| return `${this.containedIn.consumeVerb.past.capital} by ${this.containedIn.owner.name}` | |||
| results.push(new VisibleStatus('Eaten', 'Devoured by ' + this.containedIn.owner.name, 'fas fa-drumstick-bite')) | |||
| } | |||
| return "Normal" | |||
| return results | |||
| } | |||
| validActions (target: Creature): Array<Action> { | |||
| @@ -179,9 +181,8 @@ export class Creature extends Vore implements Combatant { | |||
| if (this.containedIn !== null) { | |||
| choices = choices.concat(this.containedIn.actions) | |||
| } | |||
| console.log(this, target) | |||
| return choices.filter(action => { | |||
| console.log(action, action.allowed(this, target)) | |||
| return action.allowed(this, target) | |||
| }) | |||
| } | |||
| @@ -1,5 +1,5 @@ | |||
| import { Mortal } from './entity' | |||
| import { Damage, DamageType, Stats, Actionable, Action, Vigor, VoreStats } from './combat' | |||
| import { Damage, DamageType, Stats, Actionable, Action, Vigor, VoreStats, VisibleStatus } from './combat' | |||
| import { LogLines, LogEntry, LogLine } from './interface' | |||
| import { Noun, Pronoun, ImproperNoun, TextLike, Verb, SecondPersonPronouns, PronounAsNoun, FirstPersonPronouns, PairLineArgs, SoloLine, POV } from './language' | |||
| import { DigestAction, DevourAction, ReleaseAction, StruggleAction } from './combat/actions' | |||
| @@ -47,7 +47,7 @@ export abstract class Vore implements Mortal { | |||
| abstract takeDamage (damage: Damage): LogEntry; | |||
| abstract stats: Stats; | |||
| abstract baseStats: Stats; | |||
| abstract status: string; | |||
| abstract status: VisibleStatus[]; | |||
| destroyed = false; | |||
| abstract preyPrefs: Set<VoreType>; | |||
| abstract voreStats: VoreStats; | |||
| @@ -70,9 +70,6 @@ export abstract class Vore implements Mortal { | |||
| }) | |||
| }) | |||
| console.log(released) | |||
| console.log(released.reduce((list: Array<string>, prey: Vore) => list.concat([prey.name.toString()]), [])) | |||
| const names = released.reduce((list: Array<string>, prey: Vore) => list.concat([prey.name.toString()]), []).joinGeneral(", ", " and ").join("") | |||
| if (released.length > 0) { | |||