| @@ -11,6 +11,9 @@ | |||||
| <Statblock :subject="world.player" :initiative="0" /> | <Statblock :subject="world.player" :initiative="0" /> | ||||
| <button @click="$emit('profile')">Show profile</button> | <button @click="$emit('profile')">Show profile</button> | ||||
| </div> | </div> | ||||
| <div class="explore-wallet"> | |||||
| <WalletView :subject="world.player" /> | |||||
| </div> | |||||
| <div class="explore-containers"> | <div class="explore-containers"> | ||||
| <transition-group name="container"> | <transition-group name="container"> | ||||
| <ContainerView v-show="container.contents.concat(container.digested).length > 0" :container="container" v-for="(container, index) in world.player.containers" :key="'explore-container-' + index" /> | <ContainerView v-show="container.contents.concat(container.digested).length > 0" :container="container" v-for="(container, index) in world.player.containers" :key="'explore-container-' + index" /> | ||||
| @@ -37,11 +40,12 @@ import NavButton from './NavButton.vue' | |||||
| import ChoiceButton from './ChoiceButton.vue' | import ChoiceButton from './ChoiceButton.vue' | ||||
| import Statblock from './Statblock.vue' | import Statblock from './Statblock.vue' | ||||
| import ContainerView from './ContainerView.vue' | import ContainerView from './ContainerView.vue' | ||||
| import WalletView from './WalletView.vue' | |||||
| import { LogEntry } from '@/game/interface' | import { LogEntry } from '@/game/interface' | ||||
| @Component({ | @Component({ | ||||
| components: { | components: { | ||||
| NavButton, ChoiceButton, Statblock, ContainerView | |||||
| NavButton, ChoiceButton, Statblock, ContainerView, WalletView | |||||
| }, | }, | ||||
| data () { | data () { | ||||
| return { | return { | ||||
| @@ -102,8 +106,9 @@ export default class Explore extends Vue { | |||||
| display: grid; | display: grid; | ||||
| grid-template-areas: "info log log statblock" | grid-template-areas: "info log log statblock" | ||||
| "worldinfo log log statblock" | "worldinfo log log statblock" | ||||
| "worldinfo log log wallet" | |||||
| "nav nav choices containers "; | "nav nav choices containers "; | ||||
| grid-template-rows: fit-content(50%) 1fr 18rem; | |||||
| grid-template-rows: fit-content(50%) 1fr fit-content(10%) 18rem; | |||||
| grid-template-columns: 1fr 1fr 1fr 1fr; | grid-template-columns: 1fr 1fr 1fr 1fr; | ||||
| width: 100%; | width: 100%; | ||||
| height: 100%; | height: 100%; | ||||
| @@ -151,6 +156,10 @@ export default class Explore extends Vue { | |||||
| grid-area: statblock; | grid-area: statblock; | ||||
| } | } | ||||
| .explore-wallet { | |||||
| grid-area: wallet; | |||||
| } | |||||
| .explore-info { | .explore-info { | ||||
| grid-area: info; | grid-area: info; | ||||
| background: #333; | background: #333; | ||||
| @@ -0,0 +1,77 @@ | |||||
| <template> | |||||
| <div class="wallet-view"> | |||||
| <div v-for="currency in Object.keys(Currency)" :key="currency"> {{ subject.wallet[currency] === 1 ? CurrencyData[currency].name.capital.all : CurrencyData[currency].name.capital.all.plural }}: {{ subject.wallet[currency]}} </div> | |||||
| </div> | |||||
| </template> | |||||
| <script lang="ts"> | |||||
| 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, VoreContainer, Vore } from '@/game/vore' | |||||
| import { Item, ItemKindIcons, ItemKind, Currency, CurrencyData } from '@/game/items' | |||||
| @Component({ | |||||
| data () { | |||||
| return { | |||||
| Currency: Currency, | |||||
| CurrencyData: CurrencyData | |||||
| } | |||||
| } | |||||
| }) | |||||
| export default class WalletView extends Vue { | |||||
| @Prop({ required: true }) | |||||
| subject!: Creature | |||||
| } | |||||
| </script> | |||||
| <!-- Add "scoped" attribute to limit CSS to this component only --> | |||||
| <style scoped> | |||||
| .item-view { | |||||
| position: relative; | |||||
| border: 4px outset; | |||||
| border-radius: 4px; | |||||
| margin: 4px; | |||||
| } | |||||
| .item-content { | |||||
| position: relative; | |||||
| padding: 4px; | |||||
| z-index: 1; | |||||
| } | |||||
| .item-name { | |||||
| font-size: 1.5rem; | |||||
| } | |||||
| .item-icon { | |||||
| color: #666; | |||||
| font-size: 250%; | |||||
| position: absolute; | |||||
| top: 65%; | |||||
| left: 50%; | |||||
| transform: translate(-50%, -50%); | |||||
| } | |||||
| .item-hover { | |||||
| display: none; | |||||
| --item-hover-text: "oops"; | |||||
| } | |||||
| .item-view:hover .item-hover { | |||||
| position: absolute; | |||||
| display: grid; | |||||
| place-items: center; | |||||
| top: 0; | |||||
| left: 0; | |||||
| background: #ffffff; | |||||
| color: black; | |||||
| opacity: 0.5; | |||||
| width: 100%; | |||||
| height: 100%; | |||||
| z-index: 2; | |||||
| user-select: none; | |||||
| } | |||||
| </style> | |||||
| @@ -2,7 +2,7 @@ import { Damage, Combatant, Stats, Action, Vigor, Side, GroupAction, VisibleStat | |||||
| import { Noun, Pronoun } from './language' | import { Noun, Pronoun } from './language' | ||||
| import { LogEntry, LogLines } from './interface' | import { LogEntry, LogLines } from './interface' | ||||
| import { Vore, VoreContainer, VoreType } from './vore' | import { Vore, VoreContainer, VoreType } from './vore' | ||||
| import { Item, EquipmentSlot, Equipment, ItemKind } from './items' | |||||
| import { Item, EquipmentSlot, Equipment, ItemKind, Currency } from './items' | |||||
| import { PassAction } from './combat/actions' | import { PassAction } from './combat/actions' | ||||
| import { AI, NoAI } from './ai' | import { AI, NoAI } from './ai' | ||||
| @@ -22,6 +22,7 @@ export class Creature extends Vore implements Combatant { | |||||
| statusEffects: Array<StatusEffect> = []; | statusEffects: Array<StatusEffect> = []; | ||||
| groupActions: Array<GroupAction> = []; | groupActions: Array<GroupAction> = []; | ||||
| items: Array<Item> = []; | items: Array<Item> = []; | ||||
| wallet: { [key in Currency]: number } = Object.keys(Currency).reduce((total: any, key) => { total[key] = 0; return total }, {}); | |||||
| otherActions: Array<Action> = []; | otherActions: Array<Action> = []; | ||||
| side: Side; | side: Side; | ||||
| title = "Lv. 1 Creature"; | title = "Lv. 1 Creature"; | ||||
| @@ -1,4 +1,4 @@ | |||||
| import { TextLike, LiveText, DynText, Word, ImproperNoun, Verb } from './language' | |||||
| import { TextLike, LiveText, DynText, Word, ImproperNoun, Verb, Noun } from './language' | |||||
| import { Actionable, Action, DamageFormula, ConstantDamageFormula, Damage, DamageType, Vigor, StatDamageFormula, Stat, Effective, CompositionAction, Condition, CompositeDamageFormula } from './combat' | import { Actionable, Action, DamageFormula, ConstantDamageFormula, Damage, DamageType, Vigor, StatDamageFormula, Stat, Effective, CompositionAction, Condition, CompositeDamageFormula } from './combat' | ||||
| import { AttackAction } from './combat/actions' | import { AttackAction } from './combat/actions' | ||||
| import { Resistances } from './entity' | import { Resistances } from './entity' | ||||
| @@ -8,6 +8,16 @@ import { SoloCondition } from './combat/conditions' | |||||
| import { LogLine, LogEntry } from './interface' | import { LogLine, LogEntry } from './interface' | ||||
| import { Creature } from './creature' | import { Creature } from './creature' | ||||
| export enum Currency { | |||||
| Gold = "Gold" | |||||
| } | |||||
| export const CurrencyData: {[key in Currency]: { name: Noun }} = { | |||||
| [Currency.Gold]: { | |||||
| name: new ImproperNoun("gold piece", "gold pieces") | |||||
| } | |||||
| } | |||||
| export enum ItemKind { | export enum ItemKind { | ||||
| Key = "Key Item", | Key = "Key Item", | ||||
| Consumable = "Consumable", | Consumable = "Consumable", | ||||
| @@ -31,6 +41,14 @@ export abstract class Item implements Actionable { | |||||
| } | } | ||||
| } | } | ||||
| export class KeyItem extends Item { | |||||
| kind = ItemKind.Key | |||||
| constructor (name: Word, desc: TextLike) { | |||||
| super(name, desc) | |||||
| } | |||||
| } | |||||
| export enum EquipmentSlot { | export enum EquipmentSlot { | ||||
| Head = "Head", | Head = "Head", | ||||
| Chest = "Chest", | Chest = "Chest", | ||||
| @@ -248,6 +248,25 @@ export const Town = (): Place => { | |||||
| ) | ) | ||||
| ) | ) | ||||
| square.choices.push( | |||||
| new Choice( | |||||
| "Buy a shiny rock", | |||||
| "This rock has no use.", | |||||
| (world, executor) => { | |||||
| if (executor.wallet.Gold >= 500) { | |||||
| executor.wallet.Gold -= 500 | |||||
| executor.items.push( | |||||
| new Items.KeyItem(new ProperNoun("Shiny Rock"), "Very shiny") | |||||
| ) | |||||
| return new LogLine(`You buy a shiny rock`) | |||||
| } else { | |||||
| return new LogLine(`Shiny rocks are 500 gold coins, loser!`) | |||||
| } | |||||
| } | |||||
| ) | |||||
| ) | |||||
| alley.choices.push( | alley.choices.push( | ||||
| new Choice( | new Choice( | ||||
| "Kuro", | "Kuro", | ||||
| @@ -351,6 +370,17 @@ export const Town = (): Place => { | |||||
| ) | ) | ||||
| ) | ) | ||||
| debug.choices.push( | |||||
| new Choice( | |||||
| "Add money", | |||||
| "Get some money", | |||||
| (world, executor) => { | |||||
| executor.wallet.Gold += 1000 | |||||
| return new LogLine(`$$$$$$$$$$$$$$$$$`) | |||||
| } | |||||
| ) | |||||
| ) | |||||
| home.biconnect(Direction.South, debug) | home.biconnect(Direction.South, debug) | ||||
| home.biconnect(Direction.North, westAve) | home.biconnect(Direction.North, westAve) | ||||
| westAve.biconnect(Direction.West, westRoad) | westAve.biconnect(Direction.West, westRoad) | ||||