Browse Source

Add new stats; add tooltips

master
Fen Dweller 5 years ago
parent
commit
de6de6cd5e
7 changed files with 85 additions and 38 deletions
  1. +1
    -0
      src/App.vue
  2. +44
    -8
      src/components/Statblock.vue
  3. +17
    -13
      src/game/combat.ts
  4. +13
    -7
      src/game/creatures/cafat.ts
  5. +1
    -1
      src/game/creatures/player.ts
  6. +5
    -5
      src/game/creatures/wolf.ts
  7. +4
    -4
      src/game/entity.ts

+ 1
- 0
src/App.vue View File

@@ -44,6 +44,7 @@ body, html {
background: #181818; background: #181818;
width: 100%; width: 100%;
height: 100%; height: 100%;
overflow-x: hidden;
} }


#app { #app {


+ 44
- 8
src/components/Statblock.vue View File

@@ -2,14 +2,18 @@
<div class="statblock"> <div class="statblock">
<h2 v-if="subject.perspective === firstperson">You</h2> <h2 v-if="subject.perspective === firstperson">You</h2>
<h2 v-if="subject.perspective !== firstperson">{{subject.name.all.capital}}</h2> <h2 v-if="subject.perspective !== firstperson">{{subject.name.all.capital}}</h2>
<div class="stat-line"><i class="fas fa-heart" /> {{ subject.vigors[vigor.Health].toFixed(0) }}</div>
<div class="stat-line"><i class="fas fa-bolt" /> {{ subject.vigors[vigor.Stamina].toFixed(0) }}</div>
<div class="stat-line"><i class="fas fa-brain" /> {{ subject.vigors[vigor.Willpower].toFixed(0) }}</div>
<div class="stat-line">
<div class="stat-entry" :data-tooltip="vigor" v-for="vigor in Object.keys(subject.vigors)" v-bind:key="vigor"><i :class="vigorIcons[vigor]" /><div>{{subject.vigors[vigor]}}</div></div>
</div>
<br> <br>
<div class="stat-line" v-for="stat in Object.keys(subject.stats)" v-bind:key="stat"><i :class="statIcons[stat]" /> {{subject.stats[stat]}}</div>
<div class="stat-line">
<div class="stat-entry" :data-tooltip="stat" v-for="stat in Object.keys(subject.stats)" v-bind:key="stat"><i :class="statIcons[stat]" /> {{subject.stats[stat]}}</div>
</div>
<br> <br>
<div class="stat-line"><i class="fas fa-weight-hanging" /> {{subject.bulk}}</div>
<div class="stat-line"><i class="fas fa-utensils" /> {{ subject.containers.reduce((total, container) => total + container.contents.length, 0) }} </div>
<div class="stat-line">
<div class="stat-entry" data-tooltip="Bulk"><i class="fas fa-weight-hanging" /> {{subject.bulk}}</div>
<div class="stat-entry" data-tooltip="Prey Count"><i class="fas fa-utensils" /> {{ subject.containers.reduce((total, container) => total + container.contents.length, 0) }} </div>
</div>
<br> <br>
<div>Status: {{subject.status}}</div> <div>Status: {{subject.status}}</div>
<ContainerView v-for="container in subject.containers" :key="container.name.toString()" :container="container" /> <ContainerView v-for="container in subject.containers" :key="container.name.toString()" :container="container" />
@@ -19,9 +23,8 @@
<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, POV } from '@/game/entity' import { Creature, POV } from '@/game/entity'
import { Stats, Stat, StatIcons, Vigor } from '@/game/combat'
import { Stats, Stat, StatIcons, Vigor, VigorIcons } from '@/game/combat'
import ContainerView from './ContainerView.vue' import ContainerView from './ContainerView.vue'

@Component({ @Component({
components: { components: {
ContainerView ContainerView
@@ -31,6 +34,7 @@ export default class Statblock extends Vue {
@Prop({ type: Creature, required: true }) @Prop({ type: Creature, required: true })
subject!: Creature subject!: Creature


private vigorIcons = VigorIcons
private statIcons = StatIcons private statIcons = StatIcons
private vigor = Vigor private vigor = Vigor


@@ -61,11 +65,43 @@ a {
.statblock { .statblock {
margin: 16px; margin: 16px;
} }

.stat-line { .stat-line {
width: 100%;
display: flex;
justify-content: space-around;
flex-wrap: wrap;
}

.stat-entry {
position: relative;
font-size: 2vh; font-size: 2vh;
padding-top: 4pt; padding-top: 4pt;
padding-bottom: 4pt; padding-bottom: 4pt;
display: flex; display: flex;
flex-direction: column;
justify-content: space-evenly; justify-content: space-evenly;
user-select: none;
}

.stat-entry::after {
opacity: 0;
position: absolute;
color: #eee;
font-size: 0pt;
content: attr(data-tooltip);
transition: 0.1s;
pointer-events: none;
left: 0pt;
top: 0pt;
transform: translate(calc(-50% + 16pt), -100%);
background: #555;
padding: 8pt;
border-radius: 8pt;
}

.stat-entry:hover::after {
font-size: 18pt;
opacity: 1;
} }
</style> </style>

+ 17
- 13
src/game/combat.ts View File

@@ -21,29 +21,33 @@ export interface DamageInstance {
export enum Vigor { export enum Vigor {
Health = "Health", Health = "Health",
Stamina = "Stamina", Stamina = "Stamina",
Willpower = "Willpower"
Resolve = "Resolve"
} }


export const VigorIcons: {[key in Vigor]: string} = { export const VigorIcons: {[key in Vigor]: string} = {
[Vigor.Health]: "fas fa-heart", [Vigor.Health]: "fas fa-heart",
[Vigor.Stamina]: "fas fa-bolt", [Vigor.Stamina]: "fas fa-bolt",
[Vigor.Willpower]: "fas fa-brain"
[Vigor.Resolve]: "fas fa-brain"
} }


export type Vigors = {[key in Vigor]: number} export type Vigors = {[key in Vigor]: number}


export enum Stat { export enum Stat {
STR = 'Strength',
DEX = 'Dexterity',
CON = 'Constitution'
Toughness = "Toughness",
Power = "Power",
Speed = "Speed",
Willpower = "Willpower",
Charm = "Charm"
} }


export type Stats = {[key in Stat]: number} export type Stats = {[key in Stat]: number}


export const StatIcons: {[key in Stat]: string} = { export const StatIcons: {[key in Stat]: string} = {
[Stat.STR]: 'fas fa-fist-raised',
[Stat.DEX]: 'fas fa-feather',
[Stat.CON]: 'fas fa-heartbeat'
[Stat.Toughness]: 'fas fa-heartbeat',
[Stat.Power]: 'fas fa-fist-raised',
[Stat.Speed]: 'fas fa-feather',
[Stat.Willpower]: 'fas fa-book',
[Stat.Charm]: 'fas fa-comments'
} }
export interface CombatTest { export interface CombatTest {
test: (user: Creature, target: Creature) => boolean; test: (user: Creature, target: Creature) => boolean;
@@ -311,7 +315,7 @@ export class AttackAction extends TogetherAction {


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


execute (user: Creature, target: Creature): LogEntry { execute (user: Creature, target: Creature): LogEntry {
@@ -348,7 +352,7 @@ export class DevourAction extends TogetherAction {


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


execute (user: Creature, target: Creature): LogEntry { execute (user: Creature, target: Creature): LogEntry {
@@ -382,9 +386,9 @@ export class FeedAction extends TogetherAction {
} }


constructor (protected container: Container) { constructor (protected container: Container) {
super('Feed', 'Feed yourself to your opponent', [new DrainedVigorCondition(Vigor.Willpower)])
super('Feed', 'Feed yourself to your opponent', [new DrainedVigorCondition(Vigor.Resolve)])
this.name += ` (${container.name})` this.name += ` (${container.name})`
this.test = new StatTest(Stat.STR)
this.test = new StatTest(Stat.Power)
} }


execute (user: Creature, target: Creature): LogEntry { execute (user: Creature, target: Creature): LogEntry {
@@ -411,7 +415,7 @@ export class StruggleAction extends PairAction {


constructor (public container: Container) { 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()])
this.test = new StatVigorTest(Stat.STR)
this.test = new StatVigorTest(Stat.Power)
} }


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


+ 13
- 7
src/game/creatures/cafat.ts View File

@@ -79,19 +79,25 @@ class CrushAction extends EatenAction {


export class Cafat extends Creature { export class Cafat extends Creature {
constructor () { constructor () {
super(new ProperNoun('Cafat'), [TheyPronouns, FemalePronouns][Math.floor(Math.random() * 2)], { [Stat.STR]: 30, [Stat.DEX]: 15, [Stat.CON]: 25 }, new Set([VoreType.Oral, VoreType.Anal]), new Set([VoreType.Oral, VoreType.Anal]), 150)
super(new ProperNoun('Cafat'), [TheyPronouns, FemalePronouns][Math.floor(Math.random() * 2)], {
[Stat.Toughness]: 30,
[Stat.Power]: 30,
[Stat.Speed]: 15,
[Stat.Willpower]: 25,
[Stat.Charm]: 20
}, new Set([VoreType.Oral, VoreType.Anal]), new Set([VoreType.Oral, VoreType.Anal]), 150)


this.vigors.Health = 200 this.vigors.Health = 200
this.maxVigors.Health = 200 this.maxVigors.Health = 200
this.vigors.Stamina = 250 this.vigors.Stamina = 250
this.maxVigors.Stamina = 250 this.maxVigors.Stamina = 250
this.vigors.Willpower = 150
this.maxVigors.Willpower = 150
this.vigors.Resolve = 150
this.maxVigors.Resolve = 150


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


stomach.name = new ImproperNoun("upper stomach", "upper stomachs").all stomach.name = new ImproperNoun("upper stomach", "upper stomachs").all
@@ -101,7 +107,7 @@ export class Cafat extends Creature {
const lowerStomach = new InnerStomach(this, 100, new Damage( const lowerStomach = new InnerStomach(this, 100, new Damage(
{ amount: 40, type: DamageType.Acid, target: Vigor.Health }, { amount: 40, type: DamageType.Acid, target: Vigor.Health },
{ amount: 20, type: DamageType.Crush, target: Vigor.Stamina }, { amount: 20, type: DamageType.Crush, target: Vigor.Stamina },
{ amount: 20, type: DamageType.Dominance, target: Vigor.Willpower }
{ amount: 20, type: DamageType.Dominance, target: Vigor.Resolve }
), stomach) ), stomach)


lowerStomach.name = new ImproperNoun("lower stomach", "lower stomachs").all lowerStomach.name = new ImproperNoun("lower stomach", "lower stomachs").all
@@ -127,9 +133,9 @@ export class Cafat extends Creature {
this.actions.push(new TransferAction(lowerStomach, stomach)) this.actions.push(new TransferAction(lowerStomach, stomach))


this.actions.push(new AttackAction(new Damage({ amount: 40, type: DamageType.Crush, target: Vigor.Health }))) this.actions.push(new AttackAction(new Damage({ amount: 40, type: DamageType.Crush, target: Vigor.Health })))
this.actions.push(new BellyCrushAction(new Damage({ amount: 10, type: DamageType.Crush, target: Vigor.Health }, { amount: 10, type: DamageType.Dominance, target: Vigor.Willpower })))
this.actions.push(new BellyCrushAction(new Damage({ amount: 10, type: DamageType.Crush, target: Vigor.Health }, { amount: 10, type: DamageType.Dominance, target: Vigor.Resolve })))
this.actions.push(new BelchAction(new Damage( this.actions.push(new BelchAction(new Damage(
{ amount: 100, target: Vigor.Willpower, type: DamageType.Acid }
{ amount: 100, target: Vigor.Resolve, type: DamageType.Acid }
))) )))
this.otherActions.push(new FeedAction(stomach)) this.otherActions.push(new FeedAction(stomach))
} }


+ 1
- 1
src/game/creatures/player.ts View File

@@ -5,7 +5,7 @@ import { Stomach, Bowels, VoreType } from '../vore'


export class Player extends Creature { export class Player extends Creature {
constructor () { constructor () {
super(new ProperNoun('The Dude'), TheyPronouns, { [Stat.STR]: 20, [Stat.DEX]: 20, [Stat.CON]: 20 }, new Set([VoreType.Oral, VoreType.Anal]), new Set([VoreType.Oral, VoreType.Anal]), 50)
super(new ProperNoun('The Dude'), TheyPronouns, { Toughness: 20, Power: 20, Speed: 20, Willpower: 20, Charm: 20 }, new Set([VoreType.Oral, VoreType.Anal]), new Set([VoreType.Oral, VoreType.Anal]), 50)


this.actions.push(new AttackAction(new Damage({ type: DamageType.Pierce, amount: 20, target: Vigor.Health }, { type: DamageType.Pierce, amount: 20, target: Vigor.Stamina }))) this.actions.push(new AttackAction(new Damage({ type: DamageType.Pierce, amount: 20, target: Vigor.Health }, { type: DamageType.Pierce, amount: 20, target: Vigor.Stamina })))




+ 5
- 5
src/game/creatures/wolf.ts View File

@@ -34,22 +34,22 @@ class HypnoAction extends AttackAction {
]) ])


constructor () { constructor () {
super(new Damage({ amount: 30, type: DamageType.Dominance, target: Vigor.Willpower }))
this.test = new StatTest(Stat.CON)
super(new Damage({ amount: 30, type: DamageType.Dominance, target: Vigor.Resolve }))
this.test = new StatTest(Stat.Willpower)
this.name = "Hypnotize" this.name = "Hypnotize"
} }
} }


export class Wolf extends Creature { export class Wolf extends Creature {
constructor () { constructor () {
super(new ImproperNoun('wolf', 'wolves'), MalePronouns, { [Stat.STR]: 15, [Stat.DEX]: 15, [Stat.CON]: 25 }, new Set([VoreType.Oral, VoreType.Anal]), new Set([VoreType.Oral, VoreType.Anal]), 25)
super(new ImproperNoun('wolf', 'wolves'), MalePronouns, { Toughness: 20, Power: 20, Speed: 20, Willpower: 20, Charm: 20 }, new Set([VoreType.Oral, VoreType.Anal]), new Set([VoreType.Oral, VoreType.Anal]), 25)
this.actions.push(new BiteAction()) this.actions.push(new BiteAction())
this.actions.push(new HypnoAction()) this.actions.push(new HypnoAction())


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


this.containers.push(stomach) this.containers.push(stomach)
@@ -57,7 +57,7 @@ export class Wolf extends Creature {
const bowels = new Bowels(this, 50, new Damage( const bowels = new Bowels(this, 50, new Damage(
{ amount: 10, type: DamageType.Crush, target: Vigor.Health }, { amount: 10, type: DamageType.Crush, target: Vigor.Health },
{ amount: 25, type: DamageType.Crush, target: Vigor.Stamina }, { amount: 25, type: DamageType.Crush, target: Vigor.Stamina },
{ amount: 25, type: DamageType.Dominance, target: Vigor.Willpower }
{ amount: 25, type: DamageType.Dominance, target: Vigor.Resolve }
)) ))


this.containers.push(bowels) this.containers.push(bowels)


+ 4
- 4
src/game/entity.ts View File

@@ -26,13 +26,13 @@ export class Creature extends Vore implements Combatant {
vigors = { vigors = {
[Vigor.Health]: 100, [Vigor.Health]: 100,
[Vigor.Stamina]: 100, [Vigor.Stamina]: 100,
[Vigor.Willpower]: 100
[Vigor.Resolve]: 100
} }


maxVigors = { maxVigors = {
[Vigor.Health]: 100, [Vigor.Health]: 100,
[Vigor.Stamina]: 100, [Vigor.Stamina]: 100,
[Vigor.Willpower]: 100
[Vigor.Resolve]: 100
} }


get disabled (): boolean { get disabled (): boolean {
@@ -85,7 +85,7 @@ export class Creature extends Vore implements Combatant {
if (this.vigors[Vigor.Stamina] <= -100) { if (this.vigors[Vigor.Stamina] <= -100) {
return "Unconscious" return "Unconscious"
} }
if (this.vigors[Vigor.Willpower] <= -100) {
if (this.vigors[Vigor.Resolve] <= -100) {
return "Broken" return "Broken"
} }
if (this.vigors[Vigor.Health] <= 0) { if (this.vigors[Vigor.Health] <= 0) {
@@ -94,7 +94,7 @@ export class Creature extends Vore implements Combatant {
if (this.vigors[Vigor.Stamina] <= 0) { if (this.vigors[Vigor.Stamina] <= 0) {
return "Exhausted" return "Exhausted"
} }
if (this.vigors[Vigor.Willpower] <= 0) {
if (this.vigors[Vigor.Resolve] <= 0) {
return "Overpowered" return "Overpowered"
} }
if (this.containedIn !== null) { if (this.containedIn !== null) {


Loading…
Cancel
Save