|
- <template>
- <div class="explore-layout">
- <div class="explore-log">
- <div class="explore-log-filler"></div>
- </div>
- <div class="explore-worldinfo">
- <p class="worldinfo-date">{{ world.time.format("MMMM Do Y") }}</p>
- <p class="worldinfo-date">{{ world.time.format("hh:mm:ss a") }}</p>
- </div>
- <div class="explore-statblock">
- <Statblock :subject="world.player" :initiative="0" />
- <button @click="$emit('profile')">Show profile</button>
- </div>
- <div class="explore-containers">
- <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" />
- </transition-group>
- </div>
- <div class="explore-info">
- <h2 class="location-name">{{ location.name.capital }}</h2>
- <p class="location-desc">{{ location.desc }}</p>
- </div>
- <div class="explore-nav">
- <NavButton @click.native="writeLog(location.connections[direction].travel(world, world.player))" v-for="direction in Object.keys(location.connections)" :key="direction" :style="navBtnCss(direction)" :location="location" :direction="direction" />
- </div>
- <div class="explore-choices">
- <ChoiceButton @click.native="writeLog(choice.execute(world, world.player))" v-for="(choice, index) in location.choices.filter(choice => choice.visible(world))" :key="'choice' + index" :choice="choice" :world="world" />
- </div>
- </div>
- </template>
-
- <script lang="ts">
-
- import { Component, Prop, Vue } from 'vue-property-decorator'
- 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, ContainerView
- },
- data () {
- return {
- directions: Direction
- }
- }
- })
-
- export default class Explore extends Vue {
- get location () {
- return this.world.player.location
- }
-
- set location (loc: Place) {
- this.world.player.location = loc
- }
-
- @Prop({ type: World })
- world!: World
-
- navBtnCss (dir: string) {
- return {
- '--nav-direction': dir
- }
- }
-
- writeLog (entry: LogEntry) {
- const log = this.$el.querySelector(".explore-log")
- if (log !== null) {
- const rendered = entry.render()
- if (rendered.length > 0) {
- const holder = document.createElement("div")
- holder.classList.add("explore-log-entry")
-
- entry.render().forEach(element => {
- holder.appendChild(element)
- })
-
- holder.classList.add("explore-entry")
- const hline = document.createElement("div")
- hline.classList.add("explore-log-separator")
- log.appendChild(hline)
- log.appendChild(holder)
-
- log.scrollTo({ top: log.scrollHeight, left: 0, behavior: "smooth" })
- }
- }
- }
- }
-
- </script>
-
- <style scoped>
-
- .explore-layout {
- flex: 10;
- position: relative;
- display: grid;
- grid-template-areas: "info log log statblock"
- "info log log containers"
- "worldinfo log log containers"
- "nav nav choices containers ";
- grid-template-rows: fit-content(50%) 1fr 1fr 1fr;
- grid-template-columns: 1fr 1fr 1fr 1fr;
- width: 100%;
- height: 100%;
- max-width: 1500px;
- margin: auto;
- overflow: hidden;
- }
-
- .explore-containers {
- grid-area: containers;
- display: flex;
- flex-direction: column;
- flex-wrap: wrap;
- overflow-x: hidden;
- }
-
- .explore-containers > .vore-container {
- flex-basis: 25%;
- max-height: 125px;
- }
-
- .explore-log {
- grid-area: log;
- background: #222;
- overflow-y: scroll;
- padding: 8pt;
- }
-
- .explore-log-filler {
- height: 100%;
- }
-
- .explore-worldinfo {
- grid-area: worldinfo;
- background: #111;
- padding: 8px;
- }
-
- .worldinfo-date,
- .worldinfo-time {
- font-size: 1.25rem;
- }
-
- .explore-statblock {
- grid-area: statblock;
- }
-
- .explore-info {
- grid-area: info;
- background: #333;
- display: flex;
- flex-direction: column;
- flex-wrap: none;
- justify-content: start;
- align-items: center;
- padding: 8px;
- }
-
- .location-name {
- font-size: 2rem;
- margin: 8pt;
- }
-
- .location-desc {
- font-size: 1.5rem;
- color: #ccc;
- }
-
- .explore-nav {
- padding: 8px;
- position: relative;
- grid-area: nav;
- background: #444;
- display: grid;
- justify-content: center;
- align-content: center;
- grid-template-areas: "Northwest North Northeast"
- "West Center East "
- "Southwest South Southeast";
- grid-template-rows: 1fr 1fr 1fr;
- grid-template-columns: 1fr 1fr 1fr;
- width: calc(100% - 16px);
- height: calc(100% - 16px);
- justify-self: end;
- }
-
- .explore-choices {
- padding: 8px;
- grid-area: choices;
- background: #555;
- display: flex;
- flex-direction: column;
- overflow-y: scroll;
- }
-
- .container-enter {
- opacity: 0;
- }
-
- .container-enter-active {
- transition: opacity 2s;
- }
-
- .container-move {
- transition: transform 1s;
- }
-
- .container-leave-active {
- transition: opacity 5s;
- opacity: 0;
- }
-
- </style>
-
- <style>
-
- .explore-log-entry {
- animation: explore-entry-fade 1s;
- }
-
- @keyframes explore-entry-fade {
- from {
- opacity: 0;
- }
-
- to {
- opacity: 1
- }
- }
-
- .explore-log-separator {
- animation: explore-log-keyframes 0.5s;
- height: 4px;
- margin: 16pt auto 16pt;
- background: linear-gradient(90deg, transparent, #444 10%, #444 90%, transparent 100%);
- }
-
- @keyframes explore-log-keyframes {
- from {
- width: 0%;
- }
-
- to {
- width: 100%;
- }
- }
-
- .explore-log > div:last-child {
- margin-bottom: 8pt;
- }
- </style>
|