Feast 2.0!
25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.
 
 
 
 
 

310 satır
6.5 KiB

  1. <template>
  2. <div class="explore-layout">
  3. <div class="explore-log">
  4. <div class="explore-log-filler"></div>
  5. </div>
  6. <div class="explore-worldinfo">
  7. <p class="worldinfo-date">{{ world.time.format("MMMM Do Y") }}</p>
  8. <p class="worldinfo-date">{{ world.time.format("hh:mm:ss a") }}</p>
  9. </div>
  10. <div class="explore-statblock">
  11. <Statblock v-on="$listeners" :subject="world.player" />
  12. </div>
  13. <div class="explore-wallet">
  14. <WalletView :subject="world.player" />
  15. </div>
  16. <div class="explore-containers">
  17. <transition-group name="container">
  18. <ContainerView v-show="container.contents.concat(container.digested).length > 0" :container="container" v-for="(container, index) in world.player.containers" :key="'explore-container-' + index" />
  19. </transition-group>
  20. </div>
  21. <div class="explore-info">
  22. <h2 class="location-name">{{ location.name.capital }}</h2>
  23. <p class="location-desc">{{ location.desc }}</p>
  24. </div>
  25. <div class="explore-nav">
  26. <NavButton @click.native="clearLog(); writeLog(location.connections[direction].travel(world, world.player))" v-for="direction in Object.keys(directions).filter(dir => Object.keys(location.connections).includes(dir))" :key="direction" :style="navBtnCss(direction)" :location="location" :direction="direction" />
  27. </div>
  28. <div class="explore-choices">
  29. <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" />
  30. </div>
  31. </div>
  32. </template>
  33. <script lang="ts">
  34. import { Component, Prop, Vue } from 'vue-property-decorator'
  35. import { Direction, World, Place } from '@/game/world'
  36. import NavButton from './NavButton.vue'
  37. import ChoiceButton from './ChoiceButton.vue'
  38. import Statblock from './Statblock.vue'
  39. import ContainerView from './ContainerView.vue'
  40. import WalletView from './WalletView.vue'
  41. import { LogEntry } from '@/game/interface'
  42. @Component({
  43. components: {
  44. NavButton, ChoiceButton, Statblock, ContainerView, WalletView
  45. },
  46. data () {
  47. return {
  48. directions: Direction
  49. }
  50. }
  51. })
  52. export default class Explore extends Vue {
  53. get location () {
  54. return this.world.player.location
  55. }
  56. set location (loc: Place) {
  57. this.world.player.location = loc
  58. }
  59. @Prop({ type: World })
  60. world!: World
  61. navBtnCss (dir: string) {
  62. return {
  63. '--nav-direction': dir
  64. }
  65. }
  66. clearLog () {
  67. const log = this.$el.querySelector(".explore-log")
  68. if (log !== null) {
  69. log.innerHTML = ""
  70. }
  71. }
  72. writeLog (entry: LogEntry) {
  73. const log = this.$el.querySelector(".explore-log")
  74. if (log !== null) {
  75. const rendered = entry.render()
  76. if (rendered.length > 0) {
  77. const holder = document.createElement("div")
  78. holder.classList.add("explore-log-entry")
  79. entry.render().forEach(element => {
  80. holder.appendChild(element)
  81. })
  82. holder.classList.add("explore-entry")
  83. const hline = document.createElement("div")
  84. hline.classList.add("explore-log-separator")
  85. log.appendChild(hline)
  86. log.appendChild(holder)
  87. log.scrollTo({ top: log.scrollHeight, left: 0, behavior: "smooth" })
  88. }
  89. }
  90. }
  91. }
  92. </script>
  93. <style scoped>
  94. .explore-layout {
  95. flex: 10;
  96. position: relative;
  97. display: grid;
  98. grid-template-areas: "info log log statblock"
  99. "worldinfo log log statblock"
  100. "worldinfo log log wallet"
  101. "nav nav choices containers ";
  102. grid-template-rows: fit-content(50%) 1fr fit-content(10%) 12rem;
  103. grid-template-columns: 1fr 1fr 1fr 1fr;
  104. grid-gap: 8px;
  105. width: 100%;
  106. height: calc(100% - 16px);
  107. margin-top: 8px;
  108. margin-left: auto;
  109. margin-right: auto;
  110. margin-bottom: 8px;
  111. overflow: hidden;
  112. }
  113. .explore-containers {
  114. background: #222;
  115. grid-area: containers;
  116. display: flex;
  117. flex-direction: column;
  118. flex-wrap: wrap;
  119. overflow-x: hidden;
  120. }
  121. .explore-containers > .vore-container {
  122. flex-basis: 25%;
  123. max-height: 125px;
  124. }
  125. .explore-log {
  126. grid-area: log;
  127. background: #222;
  128. overflow-y: scroll;
  129. padding: 8pt;
  130. }
  131. .explore-log-filler {
  132. height: 100%;
  133. }
  134. .explore-worldinfo {
  135. grid-area: worldinfo;
  136. background: #222;
  137. padding: 8px;
  138. }
  139. .worldinfo-date,
  140. .worldinfo-time {
  141. font-size: 1.25rem;
  142. }
  143. .explore-statblock {
  144. background: #222;
  145. grid-area: statblock;
  146. }
  147. .explore-wallet {
  148. background: #222;
  149. grid-area: wallet;
  150. }
  151. .explore-info {
  152. grid-area: info;
  153. background: #222;
  154. display: flex;
  155. flex-direction: column;
  156. flex-wrap: none;
  157. justify-content: start;
  158. align-items: center;
  159. padding: 8px;
  160. }
  161. .location-name {
  162. font-size: 2rem;
  163. margin: 8pt;
  164. }
  165. .location-desc {
  166. font-size: 1.5rem;
  167. color: #ccc;
  168. }
  169. .explore-nav {
  170. padding: 8px;
  171. position: relative;
  172. grid-area: nav;
  173. background: #222;
  174. display: grid;
  175. justify-content: center;
  176. align-content: center;
  177. grid-template-areas: "Northwest North Northeast"
  178. "West Center East "
  179. "Southwest South Southeast";
  180. grid-template-rows: 1fr 1fr 1fr;
  181. grid-template-columns: 1fr 1fr 1fr;
  182. width: calc(100% - 16px);
  183. height: calc(100% - 16px);
  184. justify-self: end;
  185. }
  186. .explore-choices {
  187. padding: 8px;
  188. grid-area: choices;
  189. background: #222;
  190. display: flex;
  191. flex-direction: column;
  192. overflow-y: scroll;
  193. }
  194. .container-enter {
  195. opacity: 0;
  196. }
  197. .container-enter-active {
  198. transition: opacity 2s;
  199. }
  200. .container-move {
  201. transition: transform 1s;
  202. }
  203. .container-leave-active {
  204. transition: opacity 5s;
  205. opacity: 0;
  206. }
  207. .show-profile {
  208. grid-area: var(--nav-direction);
  209. padding: 5%;
  210. background: #555;
  211. color: #ccc;
  212. font-size: 1rem;
  213. border-color: #ccc;
  214. border-width: 3px;
  215. border-radius: 8px;
  216. border-style: outset;
  217. outline: none;
  218. width: 100%;
  219. height: 4rem;
  220. z-index: 1;
  221. user-select: none;
  222. }
  223. .show-profile:hover {
  224. background: #666;
  225. }
  226. .show-profile:active {
  227. background: #777;
  228. border-style: inset;
  229. }
  230. .show-profile:focus {
  231. background: #666;
  232. }
  233. </style>
  234. <style>
  235. .explore-log-entry {
  236. animation: explore-entry-fade 1s;
  237. }
  238. @keyframes explore-entry-fade {
  239. from {
  240. opacity: 0;
  241. }
  242. to {
  243. opacity: 1
  244. }
  245. }
  246. .explore-log-separator {
  247. animation: explore-log-keyframes 0.5s;
  248. height: 4px;
  249. margin: 16pt auto 16pt;
  250. background: linear-gradient(90deg, transparent, #444 10%, #444 90%, transparent 100%);
  251. }
  252. @keyframes explore-log-keyframes {
  253. from {
  254. width: 0%;
  255. }
  256. to {
  257. width: 100%;
  258. }
  259. }
  260. .explore-log > div:last-child {
  261. margin-bottom: 8pt;
  262. }
  263. </style>