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

310 строки
6.8 KiB

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