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

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