Feast 2.0!
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 
 

348 строки
7.8 KiB

  1. <template>
  2. <div class="combat-layout">
  3. <div @wheel="horizWheelLeft" class="stat-column" id="left-stats">
  4. <Statblock v-on:click.native="left = combatant" class="left-stats" :data-active="combatant === left" v-for="combatant in combatants.filter(c => c.side == Side.Heroes && !c.digested)" v-bind:key="combatant.name" :subject="combatant" />
  5. </div>
  6. <div @wheel="horizWheelRight" class="stat-column" id="right-stats">
  7. <Statblock v-on:click.native="right = combatant" class="right-stats" :data-active="combatant === right" v-for="combatant in combatants.filter(c => c.side == Side.Monsters && !c.digested)" v-bind:key="combatant.name" :subject="combatant" />
  8. </div>
  9. <div id="log">
  10. </div>
  11. <div class="left-actions">
  12. <div class="vert-display">
  13. <h2>Group-moves</h2>
  14. <ActionButton @described="described" @executed="executedLeft" v-for="action in left.validGroupActions(combatants)" :key="'right' + action.name" :action="action" :user="left" :target="right" :combatants="combatants" />
  15. <h2>Moves</h2>
  16. <ActionButton @described="described" @executed="executedLeft" v-for="action in left.validActions(right)" :key="'left' + action.name" :action="action" :user="left" :target="right" :combatants="combatants" />
  17. <h2>Self-moves</h2>
  18. <ActionButton @described="described" @executed="executedLeft" v-for="action in left.validActions(left)" :key="'left' + action.name" :action="action" :user="left" :target="right" :combatants="combatants" />
  19. </div>
  20. <div>{{actionDescription}}</div>
  21. </div>
  22. <div class="right-actions">
  23. <div class="vert-display">
  24. <h2>Group-moves</h2>
  25. <ActionButton @described="described" @executed="executedRight" v-for="action in right.validGroupActions(combatants)" :key="'right' + action.name" :action="action" :user="right" :target="left" :combatants="combatants" />
  26. <h2>Moves</h2>
  27. <ActionButton @described="described" @executed="executedRight" v-for="action in right.validActions(left)" :key="'right' + action.name" :action="action" :user="right" :target="left" :combatants="combatants" />
  28. <h2>Self-moves</h2>
  29. <ActionButton @described="described" @executed="executedRight" v-for="action in right.validActions(right)" :key="'right' + action.name" :action="action" :user="right" :target="left" :combatants="combatants" />
  30. </div>
  31. </div>
  32. <div id="action-desc">
  33. </div>
  34. </div>
  35. </template>
  36. <script lang="ts">
  37. import { Component, Prop, Vue, Watch, Emit } from 'vue-property-decorator'
  38. import { Creature, POV } from '@/game/entity'
  39. import { LogEntry } from '@/game/interface'
  40. import Statblock from './Statblock.vue'
  41. import ActionButton from './ActionButton.vue'
  42. import { Side } from '@/game/combat'
  43. @Component(
  44. {
  45. components: { Statblock, ActionButton },
  46. methods: {
  47. horizWheelLeft (event: MouseWheelEvent) {
  48. const target = this.$el.querySelector("#left-stats")
  49. console.log(target)
  50. if (target !== null) {
  51. target.scrollBy({ top: 0, left: event.deltaY, behavior: 'smooth' })
  52. }
  53. },
  54. horizWheelRight (event: MouseWheelEvent) {
  55. const target = this.$el.querySelector("#right-stats")
  56. console.log(target)
  57. if (target !== null) {
  58. target.scrollBy({ top: 0, left: -event.deltaY, behavior: 'smooth' })
  59. }
  60. }
  61. }
  62. }
  63. )
  64. export default class Combat extends Vue {
  65. @Prop({ type: Creature, required: true })
  66. left!: Creature
  67. @Prop({ type: Creature, required: true })
  68. right!: Creature
  69. @Prop()
  70. combatants!: Array<Creature>
  71. Side = Side
  72. actionDescription = ''
  73. constructor () {
  74. super()
  75. }
  76. @Emit("executedLeft")
  77. executedLeft (entry: LogEntry) {
  78. const log = document.querySelector("#log")
  79. if (log !== null) {
  80. const holder = document.createElement("div")
  81. entry.render().forEach(element => {
  82. holder.appendChild(element)
  83. })
  84. holder.classList.add("left-move")
  85. log.appendChild(holder)
  86. log.scrollTo({ top: 10000000000, left: 0 })
  87. }
  88. }
  89. @Emit("executedRight")
  90. executedRight (entry: LogEntry) {
  91. const log = document.querySelector("#log")
  92. if (log !== null) {
  93. const holder = document.createElement("div")
  94. entry.render().forEach(element => {
  95. holder.appendChild(element)
  96. })
  97. holder.classList.add("right-move")
  98. log.appendChild(holder)
  99. log.scrollTo({ top: 10000000000, left: 0 })
  100. }
  101. }
  102. @Emit("described")
  103. described (entry: LogEntry) {
  104. const actionDesc = document.querySelector("#action-desc")
  105. if (actionDesc !== null) {
  106. const holder = document.createElement("div")
  107. entry.render().forEach(element => {
  108. holder.appendChild(element)
  109. })
  110. actionDesc.innerHTML = ''
  111. actionDesc.appendChild(holder)
  112. }
  113. }
  114. }
  115. </script>
  116. <!-- Add "scoped" attribute to limit CSS to this component only -->
  117. <style scoped>
  118. .combat-layout {
  119. display: grid;
  120. grid-template-rows: minmax(160pt, 20%) [main-row-start] 1fr 1fr [main-row-end] 20%;
  121. grid-template-columns: 20% [main-col-start] 1fr 1fr [main-col-end] 20%;
  122. width: 100%;
  123. height: 100%;
  124. flex: 10;
  125. }
  126. #log {
  127. grid-area: main-row-start / main-col-start / main-row-end / main-col-end;
  128. overflow-y: scroll;
  129. font-size: 12pt;
  130. width: 100%;
  131. max-height: 100%;
  132. align-self: end;
  133. }
  134. #left-stats,
  135. #right-stats {
  136. display: flex;
  137. }
  138. #left-stats {
  139. flex-direction: row-reverse;
  140. }
  141. #right-stats {
  142. flex-direction: row;
  143. }
  144. #left-stats {
  145. grid-area: 1 / 1 / 2 / 3
  146. }
  147. #right-stats {
  148. grid-area: 1 / 3 / 2 / 5;
  149. }
  150. .stat-column {
  151. overflow-y: auto;
  152. }
  153. .left-actions {
  154. grid-area: 2 / 1 / 4 / 2;
  155. }
  156. .right-actions {
  157. grid-area: 2 / 4 / 4 / 5;
  158. }
  159. .left-actions,
  160. .right-actions {
  161. overflow-y: auto;
  162. display: flex;
  163. flex-direction: column;
  164. }
  165. #action-desc {
  166. grid-area: main-row-end / main-col-start / 6 / main-col-end
  167. }
  168. h3 {
  169. margin: 40px 0 0;
  170. }
  171. ul {
  172. list-style-type: none;
  173. padding: 0;
  174. }
  175. li {
  176. display: inline-block;
  177. margin: 0 10px;
  178. }
  179. a {
  180. color: #42b983;
  181. }
  182. .horiz-display {
  183. display: flex;
  184. justify-content: center;
  185. }
  186. .vert-display {
  187. display: flex;
  188. flex-direction: column;
  189. align-items: center;
  190. flex-wrap: wrap;
  191. justify-content: start;
  192. height: 100%;
  193. }
  194. .statblock:hover {
  195. background: #444;
  196. }
  197. .statblock:hover[data-active] {
  198. background: #666;
  199. }
  200. </style>
  201. <style>
  202. .log-damage {
  203. font-weight: bold;
  204. }
  205. .damage-instance {
  206. white-space: nowrap;
  207. }
  208. #log > div {
  209. color: #888;
  210. padding-top: 4pt;
  211. padding-bottom: 4pt;
  212. }
  213. div.left-move,
  214. div.right-move {
  215. color: #888;
  216. }
  217. div.left-move {
  218. text-align: start;
  219. margin-right: 25%;
  220. margin-left: 5%;
  221. }
  222. div.right-move {
  223. text-align: end;
  224. margin-left: 25%;
  225. margin-right: 5%;
  226. }
  227. #log img {
  228. width: 75%;
  229. }
  230. #log > div.left-move:nth-last-child(7) {
  231. padding-top: 8pt;
  232. color: #988;
  233. }
  234. #log > div.left-move:nth-last-child(6) {
  235. padding-top: 12pt;
  236. color: #a88;
  237. }
  238. #log > div.left-move:nth-last-child(5) {
  239. padding-top: 16pt;
  240. color: #b88;
  241. }
  242. #log > div.left-move:nth-last-child(4) {
  243. padding-top: 20pt;
  244. color: #c88;
  245. }
  246. #log > div.left-move:nth-last-child(3) {
  247. padding-top: 24pt;
  248. color: #d88;
  249. }
  250. #log > div.left-move:nth-last-child(2) {
  251. padding-top: 28pt;
  252. color: #e88;
  253. }
  254. #log > div.left-move:nth-last-child(1) {
  255. padding-top: 32pt;
  256. color: #f88;
  257. }
  258. #log > div.right-move:nth-last-child(7) {
  259. padding-top: 8pt;
  260. color: #988;
  261. }
  262. #log > div.right-move:nth-last-child(6) {
  263. padding-top: 12pt;
  264. color: #a88;
  265. }
  266. #log > div.right-move:nth-last-child(5) {
  267. padding-top: 16pt;
  268. color: #b88;
  269. }
  270. #log > div.right-move:nth-last-child(4) {
  271. padding-top: 20pt;
  272. color: #c88;
  273. }
  274. #log > div.right-move:nth-last-child(3) {
  275. padding-top: 24pt;
  276. color: #d88;
  277. }
  278. #log > div.right-move:nth-last-child(2) {
  279. padding-top: 28pt;
  280. color: #e88;
  281. }
  282. #log > div.right-move:nth-last-child(1) {
  283. padding-top: 32pt;
  284. color: #f88;
  285. }
  286. .left-selector,
  287. .right-selector {
  288. display: flex;
  289. flex-wrap: wrap;
  290. }
  291. .combatant-picker {
  292. flex: 1 1;
  293. }
  294. </style>