Pārlūkot izejas kodu

Add waves to container views and more vore types for wolves

master
Fen Dweller pirms 5 gadiem
vecāks
revīzija
593a85dc45
7 mainītis faili ar 179 papildinājumiem un 45 dzēšanām
  1. +73
    -22
      src/components/ContainerView.vue
  2. +20
    -8
      src/components/Explore.vue
  3. +1
    -1
      src/game/creatures/human.ts
  4. +19
    -4
      src/game/creatures/wolf.ts
  5. +16
    -1
      src/game/maps/town.ts
  6. +40
    -5
      src/game/vore.ts
  7. +10
    -4
      src/game/world.ts

+ 73
- 22
src/components/ContainerView.vue Parādīt failu

@@ -1,8 +1,12 @@
<template>
<div v-if="container.fullness > 0" class="statblock">
<h3>{{container.name.capital}}</h3>
<div>{{container.fullness}} / {{container.capacity}}</div>
<div v-for="(prey, index) in container.contents" :key="'prey-' + index">{{prey.name}}</div>
<div v-show="container.fullness > 0" class="vore-container">
<div class="container-name">{{container.name.capital}}</div>
<div class="container-fullness">{{container.fullness}} / {{container.capacity}}</div>
<p v-if="container.contents.length > 0">Live prey:</p>
<div class="container-prey" v-for="(prey, index) in container.contents" :key="'live-prey-' + index">{{prey.name}}</div>
<p v-if="container.digested.length > 0">Digested:</p>
<div class="container-prey" v-for="(prey, index) in container.digested" :key="'dead-prey-' + index">{{prey.name}}</div>
<canvas class="container-waves"></canvas>
</div>
</template>

@@ -11,34 +15,81 @@ import { Component, Prop, Vue, Watch, Emit } from 'vue-property-decorator'
import { Creature } from '@/game/creature'
import { POV } from '@/game/language'
import { Stats, Stat } from '@/game/combat'
import { Container } from '@/game/vore'
import { Container, VoreContainer, Vore } from '@/game/vore'

// yoinked from https://jsfiddle.net/yckart/0adfw47y/

function draw (delta: number, dt: number, total: number, parent: HTMLElement, canvas: HTMLCanvasElement, container: VoreContainer) {
const ctx = canvas.getContext('2d') as CanvasRenderingContext2D

canvas.width = parent.clientWidth
canvas.height = parent.clientHeight
ctx.fillStyle = container.fluidColor
const fraction = container.fullness / container.capacity
const livingFraction = container.contents.reduce((total: number, prey: Vore) => total + prey.voreStats.Bulk, 0) / container.capacity
const deadFraction = container.digested.reduce((total: number, prey: Vore) => total + prey.voreStats.Bulk, 0) / container.capacity
const liveliness = livingFraction + deadFraction * 0.5

total += dt * liveliness

requestAnimationFrame((newDelta: number) => draw(newDelta, newDelta - delta, total, parent, canvas, container))

const randomLeft = Math.abs(Math.pow(Math.sin(total / 1000), 2)) * fraction * 100 + (1 - fraction) * canvas.height
const randomRight = Math.abs(Math.pow(Math.sin((total / 1000) + 10), 2)) * fraction * 100 + (1 - fraction) * canvas.height
const randomLeftConstraint = Math.abs(Math.pow(Math.sin((total / 1000) + 2), 2)) * fraction * 100 + (1 - fraction) * canvas.height
const randomRightConstraint = Math.abs(Math.pow(Math.sin((total / 1000) + 1), 2)) * fraction * 100 + (1 - fraction) * canvas.height

ctx.beginPath()
ctx.moveTo(0, randomLeft)

ctx.bezierCurveTo(canvas.width / 3, randomLeftConstraint, canvas.width / 3 * 2, randomRightConstraint, canvas.width, randomRight)
ctx.lineTo(canvas.width, canvas.height)
ctx.lineTo(0, canvas.height)
ctx.lineTo(0, randomLeft)

ctx.closePath()
ctx.fill()
}

@Component
export default class ContainerView extends Vue {
@Prop({ required: true })
container!: Container

constructor () {
super()
mounted () {
if ((this.container as VoreContainer).fluidColor !== undefined) {
const canvas = this.$el.querySelector('.container-waves') as HTMLCanvasElement

canvas.width = (this.$el as HTMLElement).clientWidth
canvas.height = (this.$el as HTMLElement).clientHeight
canvas.width = canvas.width + 0
requestAnimationFrame((delta: number) => draw(delta, delta, Math.random() * 1000, this.$el as HTMLElement, canvas, (this.container as VoreContainer)))
}
}
}

</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
margin: 40px 0 0;
font-size: 125%;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
.vore-container {
position: relative;
min-width: 100pt;
}
.container-name {
margin: 8pt;
font-size: 150%;
}

.container-fullness {
margin: 6pt;
font-size: 125%;
}

.container-waves {
position: absolute;
top: 0;
left: 0;
}

</style>

+ 20
- 8
src/components/Explore.vue Parādīt failu

@@ -8,6 +8,9 @@
<p class="worldinfo-date">{{ world.time.format("hh:mm:ss a") }}</p>
</div>
<Statblock :subject="world.player" :initiative="0" />
<div class="explore-containers">
<ContainerView :container="container" v-for="(container, index) in world.player.containers" :key="'explore-container-' + index" />
</div>
<div class="explore-info">
<h2 class="location-name">{{ location.name.capital }}</h2>
<p class="location-desc">{{ location.desc }}</p>
@@ -28,11 +31,12 @@ import { Direction, World, Place } from '@/game/world'
import NavButton from './NavButton.vue'
import ChoiceButton from './ChoiceButton.vue'
import Statblock from './Statblock.vue'
import ContainerView from './ContainerView.vue'
import { LogEntry } from '@/game/interface'

@Component({
components: {
NavButton, ChoiceButton, Statblock
NavButton, ChoiceButton, Statblock, ContainerView
},
data () {
return {
@@ -89,18 +93,26 @@ export default class Explore extends Vue {
flex: 10;
position: relative;
display: grid;
grid-template-areas: "log worldinfo"
"log statblock"
"log info "
"log choices "
"nav choices ";
grid-template-rows: 0.5fr fit-content(250pt) 2fr 1fr 1fr;
grid-template-columns: 2fr 1fr;
grid-template-areas: "statblock containers containers"
"log log worldinfo"
"log log info "
"log log choices "
"nav nav choices ";
grid-template-rows: fit-content(30%) fit-content(250pt) 2fr 1fr 1fr;
grid-template-columns: 1fr 1fr 1fr;
width: 100%;
height: 100%;
overflow: hidden;
}

.explore-containers {
grid-area: containers;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
overflow-x: scroll;
}

.explore-log {
grid-area: log;
background: #222;


+ 1
- 1
src/game/creatures/human.ts Parādīt failu

@@ -21,7 +21,7 @@ export class Human extends Creature {
} else {
stats = options.stats
}
super(name, new ImproperNoun('human', 'humans'), pronouns, stats, new Set([VoreType.Oral, VoreType.Anal]), new Set([VoreType.Oral, VoreType.Anal]), 25)
super(name, new ImproperNoun('human', 'humans'), pronouns, stats, new Set([VoreType.Oral, VoreType.Anal, VoreType.Cock, VoreType.Unbirth]), new Set([VoreType.Oral, VoreType.Anal]), 25)

this.title = "Snack"
this.desc = "Definitely going on an adventure"


+ 19
- 4
src/game/creatures/wolf.ts Parādīt failu

@@ -1,12 +1,13 @@
import { Creature } from "../creature"
import { Damage, DamageType, ConstantDamageFormula, Vigor, Side } from '../combat'
import { MalePronouns, ImproperNoun } from '../language'
import { VoreType, Stomach, Bowels } from '../vore'
import { MalePronouns, ImproperNoun, ProperNoun, ObjectPronouns } from '../language'
import { VoreType, Stomach, Bowels, Cock, Balls } from '../vore'
import { AttackAction, TransferAction, FeedAction } from '../combat/actions'
import { Human } from '../creatures'

export class Wolf extends Creature {
constructor () {
super(new ImproperNoun('wolf', 'wolves'), 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)
super(new ImproperNoun('wolf', 'wolves'), new ImproperNoun('wolf', 'wolves'), MalePronouns, { Toughness: 20, Power: 20, Speed: 20, Willpower: 20, Charm: 20 }, new Set([VoreType.Oral, VoreType.Anal, VoreType.Cock]), new Set([VoreType.Oral, VoreType.Anal, VoreType.Cock]), 25)
this.actions.push(
new AttackAction(
new ConstantDamageFormula(
@@ -24,7 +25,6 @@ export class Wolf extends Creature {
{ amount: 30, type: DamageType.Crush, target: Vigor.Stamina },
{ amount: 30, type: DamageType.Dominance, target: Vigor.Resolve }
))

this.containers.push(stomach)

const bowels = new Bowels(this, 50, new Damage(
@@ -38,5 +38,20 @@ export class Wolf extends Creature {
this.actions.push(new TransferAction(bowels, stomach))

this.otherActions.push(new FeedAction(stomach))

const cock = new Cock(this, 50, new Damage(
{ amount: 30, type: DamageType.Crush, target: Vigor.Health },
{ amount: 60, type: DamageType.Crush, target: Vigor.Stamina },
{ amount: 60, type: DamageType.Dominance, target: Vigor.Resolve }
))

const balls = new Balls(this, 50, new Damage(
{ amount: 30, type: DamageType.Crush, target: Vigor.Health },
{ amount: 60, type: DamageType.Crush, target: Vigor.Stamina },
{ amount: 60, type: DamageType.Dominance, target: Vigor.Resolve }
), cock)

this.containers.push(balls)
this.containers.push(cock)
}
}

+ 16
- 1
src/game/maps/town.ts Parādīt failu

@@ -1,10 +1,12 @@
import { Place, Choice, Direction } from '../world'
import { ProperNoun, ImproperNoun, MalePronouns, FemalePronouns } from '../language'
import { ProperNoun, ImproperNoun, MalePronouns, FemalePronouns, TheyPronouns } from '../language'
import { Encounter } from '../combat'
import * as Creatures from '../creatures'
import * as Items from '../items'
import { LogLine, nilLog } from '../interface'
import { Creature } from '../creature'
import { DevourAction } from '../combat/actions'
import { SurrenderEffect } from '../combat/effects'

function makeParty (): Creature[] {
const fighter = new Creatures.Human(new ProperNoun("Redgar"), MalePronouns, {
@@ -126,6 +128,19 @@ export const Town = (): Place => {
)
]

home.choices.push(
new Choice(
"Eat someone",
"Slurp",
(world, executor) => {
const snack = new Creatures.Human(new ProperNoun("Snack"), TheyPronouns)
snack.applyEffect(new SurrenderEffect())
const options = executor.validActions(snack).filter(action => action instanceof DevourAction)
return options[Math.floor(options.length * Math.random())].execute(executor, snack)
}
)
)

bossEncounters.forEach(encounter => {
bosses.choices.push(
new Choice(


+ 40
- 5
src/game/vore.ts Parādīt failu

@@ -123,9 +123,9 @@ export abstract class NormalContainer implements Container {
contents: Array<Vore> = []
actions: Array<Action> = []

abstract consumeVerb: Verb
abstract releaseVerb: Verb
abstract struggleVerb: Verb
consumeVerb = new Verb('trap')
releaseVerb = new Verb('release', 'releases', 'releasing', 'released')
struggleVerb = new Verb('struggle', 'struggles', 'struggling', 'struggled')

constructor (name: Noun, public owner: Vore, public voreTypes: Set<VoreType>, public capacity: number) {
this.name = name.all
@@ -214,12 +214,14 @@ export interface VoreContainer extends Container {
digested: Array<Vore>;
tick: (dt: number) => LogEntry;
digest: (preys: Vore[]) => LogEntry;
fluidColor: string;
}

export abstract class NormalVoreContainer extends NormalContainer implements VoreContainer {
consumeVerb = new Verb('devour')
releaseVerb = new Verb('release', 'releases', 'releasing', 'released')
struggleVerb = new Verb('struggle', 'struggles', 'struggling', 'struggled')
fluidColor = "#00ff0088"

digested: Array<Vore> = []

@@ -231,6 +233,10 @@ export abstract class NormalVoreContainer extends NormalContainer implements Vor
this.actions.push(new DigestAction(this))
}

get fullness (): number {
return Array.from(this.contents.concat(this.digested).values()).reduce((total: number, prey: Vore) => total + prey.voreStats.Bulk, 0)
}

consumeLine: PairLineArgs<Vore, { container: Container }> = (user, target, args) => {
return new LogLine(`${user.name.capital} ${user.name.conjugate(this.consumeVerb)} ${target.name.objective}, forcing ${target.pronouns.objective} into ${user.pronouns.possessive} ${args.container.name}.`)
}
@@ -240,7 +246,7 @@ export abstract class NormalVoreContainer extends NormalContainer implements Vor
}

digestLine: PairLineArgs<Vore, { container: VoreContainer }> = (user, target, args) => {
return new LogLine(`${user.name.capital.possessive} ${args.container.name} finishes ${Words.Digests.present} ${target.name.objective} down, ${target.pronouns.possessive} ${Words.Struggles.singular} fading away.`)
return new LogLine(`${user.name.capital.possessive} ${args.container.name} ${args.container.name.conjugate(new Verb('finish', 'finishes'))} ${Words.Digests.present} ${target.name.objective} down, ${target.pronouns.possessive} ${Words.Struggles.singular} fading away.`)
}

tick (dt: number): LogEntry {
@@ -328,6 +334,35 @@ export class InnerStomach extends InnerVoreContainer {

export class Bowels extends NormalVoreContainer {
constructor (owner: Vore, capacity: number, damage: Damage) {
super(new ImproperNoun('bowel', 'bowels').plural, owner, new Set([VoreType.Anal]), capacity, damage)
super(new ImproperNoun('bowel', 'bowels').plural.all, owner, new Set([VoreType.Anal]), capacity, damage)
}
}

export class Cock extends NormalVoreContainer {
fluidColor = "#eeeeee66";

constructor (owner: Vore, capacity: number, damage: Damage) {
super(
new ImproperNoun('cock').all,
owner,
new Set([VoreType.Cock]),
capacity,
damage
)
}
}

export class Balls extends InnerVoreContainer {
fluidColor = "#eeeeeecc";

constructor (owner: Vore, capacity: number, damage: Damage, escape: Container) {
super(
new ImproperNoun('ball', 'balls').all.plural,
owner,
new Set([VoreType.Cock]),
capacity,
damage,
escape
)
}
}

+ 10
- 4
src/game/world.ts Parādīt failu

@@ -2,7 +2,7 @@ import { TextLike, Verb, Noun, ProperNoun } from './language'
import { Entity } from './entity'
import { Creature } from './creature'
import moment, { Moment, Duration } from 'moment'
import { LogEntry, LogLine } from './interface'
import { LogEntry, LogLine, LogLines } from './interface'
import { Encounter } from './combat'

export enum Direction {
@@ -57,9 +57,10 @@ export class Connection {
}

travel (world: World, traveler: Creature): LogEntry {
world.advance(moment.duration(5, "minutes"))
const advanceLogs = world.advance(moment.duration(5, "minutes"))
traveler.location = this.dst
return new LogLine(
return new LogLines(
advanceLogs,
`${traveler.name.capital} ${traveler.name.conjugate(new Verb('travel'))} to ${this.dst.name}.`
)
}
@@ -98,7 +99,12 @@ export class World {
this.creatures.push(player)
}

advance (dt: Duration) {
advance (dt: Duration): LogEntry {
this.time.add(dt)
return new LogLines(
...this.player.containers.map(
container => container.tick(dt.asSeconds())
)
)
}
}

Notiek ielāde…
Atcelt
Saglabāt