gloomhaven.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580
  1. const genGloomhaven = () => {
  2. const items = [];
  3. [...Array(7).keys()].forEach((_, index) => {
  4. items.push({
  5. type: "image",
  6. content: `https://raw.githubusercontent.com/romgar/gloomhaven/master/images/monster-ability-cards/archer/ma-ar-${
  7. index + 1
  8. }.png`,
  9. backContent: `https://raw.githubusercontent.com/romgar/gloomhaven/master/images/monster-ability-cards/archer/ma-ar-back.png`,
  10. width: 100,
  11. x: 200,
  12. y: 200,
  13. });
  14. });
  15. [...Array(7).keys()].forEach((_, index) => {
  16. items.push({
  17. type: "image",
  18. content: `https://raw.githubusercontent.com/romgar/gloomhaven/master/images/monster-ability-cards/guard/ma-gu-${
  19. index + 1
  20. }.png`,
  21. backContent: `https://raw.githubusercontent.com/romgar/gloomhaven/master/images/monster-ability-cards/guard/ma-gu-back.png`,
  22. width: 100,
  23. x: 200,
  24. y: 300,
  25. });
  26. });
  27. [...Array(7).keys()].forEach((_, index) => {
  28. items.push({
  29. type: "image",
  30. content: `https://raw.githubusercontent.com/romgar/gloomhaven/master/images/monster-ability-cards/living-bones/ma-lb-${
  31. index + 1
  32. }.png`,
  33. backContent: `https://raw.githubusercontent.com/romgar/gloomhaven/master/images/monster-ability-cards/living-bones/ma-lb-back.png`,
  34. width: 100,
  35. x: 200,
  36. y: 500,
  37. });
  38. });
  39. // map-tiles
  40. [
  41. "a4",
  42. "b4",
  43. "c2",
  44. "d2",
  45. "e1",
  46. "f1",
  47. "g2",
  48. "h3",
  49. "i2",
  50. "j2",
  51. "k2",
  52. "l3",
  53. "m1",
  54. "n1",
  55. ].forEach((ln, index) => {
  56. const [l, n] = Array.from(ln);
  57. [...Array(n).keys()].forEach((y, index) => {
  58. items.push({
  59. type: "image",
  60. content: `https://raw.githubusercontent.com/romgar/gloomhaven/master/images/map-tiles/${l}${
  61. y + 1
  62. }a.png`,
  63. backContent: `https://raw.githubusercontent.com/romgar/gloomhaven/master/images/map-tiles/${l}${
  64. y + 1
  65. }b.png`,
  66. text: `${l}${y}a`,
  67. backText: `${l}${y}b`,
  68. x: 558,
  69. y: 80,
  70. });
  71. });
  72. });
  73. // character-mats
  74. items.push({
  75. type: "image",
  76. content:
  77. "https://raw.githubusercontent.com/romgar/gloomhaven/master/images/character-mats/brute.png",
  78. backContent:
  79. "https://raw.githubusercontent.com/romgar/gloomhaven/master/images/character-mats/brute-back.png",
  80. width: 300,
  81. x: 500,
  82. y: 500,
  83. });
  84. items.push({
  85. type: "image",
  86. content:
  87. "https://raw.githubusercontent.com/romgar/gloomhaven/master/images/character-mats/spellweaver.png",
  88. backContent:
  89. "https://raw.githubusercontent.com/romgar/gloomhaven/master/images/character-mats/spellweaver-back.png",
  90. width: 300,
  91. x: 500,
  92. y: 700,
  93. });
  94. items.push({
  95. type: "image",
  96. content:
  97. "https://raw.githubusercontent.com/romgar/gloomhaven/master/images/character-perks/brute-perks.png",
  98. width: 300,
  99. x: 1000,
  100. y: 500,
  101. });
  102. items.push({
  103. type: "image",
  104. content:
  105. "https://raw.githubusercontent.com/romgar/gloomhaven/master/images/character-perks/spellweaver-perks.png",
  106. width: 300,
  107. x: 1000,
  108. y: 700,
  109. });
  110. // Attack modifiers
  111. [...Array(19).keys()].forEach((_, index) => {
  112. const number = index < 9 ? "0" + (index + 1) : "" + (index + 1);
  113. items.push({
  114. type: "image",
  115. content: `https://raw.githubusercontent.com/romgar/gloomhaven/master/images/attack-modifiers/base/player/am-p-${number}.png`,
  116. backContent: "/games/gloom/attackback.png",
  117. width: 100,
  118. flipped: true,
  119. x: 300,
  120. y: 200,
  121. });
  122. });
  123. [...Array(19).keys()].forEach((_, index) => {
  124. const number = index < 9 ? "0" + (index + 1) : "" + (index + 1);
  125. items.push({
  126. type: "image",
  127. content: `https://raw.githubusercontent.com/romgar/gloomhaven/master/images/attack-modifiers/base/player/am-p-${number}.png`,
  128. backContent: "/games/gloom/attackback.png",
  129. width: 100,
  130. flipped: true,
  131. x: 300,
  132. y: 600,
  133. });
  134. });
  135. [...Array(19).keys()].forEach((_, index) => {
  136. const number = index < 9 ? "0" + (index + 1) : "" + (index + 1);
  137. items.push({
  138. type: "image",
  139. content: `https://raw.githubusercontent.com/romgar/gloomhaven/master/images/attack-modifiers/base/monster/am-m-${number}.png`,
  140. backContent: "/games/gloom/attackback.png",
  141. width: 100,
  142. flipped: true,
  143. x: 1000,
  144. y: 300,
  145. });
  146. });
  147. // monster tokens
  148. [...Array(10).keys()].forEach((_, index) => {
  149. items.push({
  150. type: "image",
  151. content:
  152. "https://raw.githubusercontent.com/romgar/gloomhaven/master/images/monster-tokens/bandit-guard.png",
  153. x: 1400 + 60 * index,
  154. y: 0,
  155. width: 60,
  156. text: `${index}`,
  157. overlay: {
  158. content: `https://raw.githubusercontent.com/romgar/gloomhaven/master/images/monster-tokens/${
  159. index < 7 ? "normal" : "elite"
  160. }-monster-overlay.svg`,
  161. },
  162. });
  163. items.push({
  164. type: "image",
  165. content:
  166. "https://raw.githubusercontent.com/romgar/gloomhaven/master/images/monster-tokens/bandit-archer.png",
  167. x: 1400 + 60 * index,
  168. y: 50,
  169. width: 60,
  170. text: `${index}`,
  171. overlay: {
  172. content: `https://raw.githubusercontent.com/romgar/gloomhaven/master/images/monster-tokens/${
  173. index < 7 ? "normal" : "elite"
  174. }-monster-overlay.svg`,
  175. },
  176. });
  177. items.push({
  178. type: "image",
  179. content:
  180. "https://raw.githubusercontent.com/romgar/gloomhaven/master/images/monster-tokens/living-bones.png",
  181. x: 1400 + 60 * index,
  182. y: 100,
  183. width: 60,
  184. text: `${index}`,
  185. overlay: {
  186. content: `https://raw.githubusercontent.com/romgar/gloomhaven/master/images/monster-tokens/${
  187. index < 7 ? "normal" : "elite"
  188. }-monster-overlay.svg`,
  189. },
  190. });
  191. });
  192. const monsters = ["bandit-guard", "bandit-archer", "living-bones"];
  193. monsters.forEach((monsterName, index) => {
  194. items.push({
  195. type: "image",
  196. content: `https://raw.githubusercontent.com//romgar/gloomhaven/master/images/monster-stat-cards/${monsterName}-0.png`,
  197. x: 1300 + 200 * index,
  198. y: 300,
  199. width: 200,
  200. });
  201. });
  202. // Overlay tokens
  203. [...Array(20).keys()].forEach((_, index) => {
  204. items.push({
  205. type: "image",
  206. content:
  207. "https://raw.githubusercontent.com//romgar/gloomhaven/master/images/overlay-tokens/treasures/coin-1.png",
  208. x: 1100 + 20 * index,
  209. y: 200,
  210. width: 50,
  211. });
  212. });
  213. items.push({
  214. type: "counter",
  215. label: "Life #1",
  216. value: 0,
  217. x: 100,
  218. y: 100,
  219. width: 50,
  220. });
  221. items.push({
  222. type: "counter",
  223. label: "Life #2",
  224. value: 0,
  225. x: 100,
  226. y: 300,
  227. width: 50,
  228. });
  229. items.push({
  230. type: "counter",
  231. label: "XP #1",
  232. value: 0,
  233. x: 300,
  234. y: 100,
  235. width: 50,
  236. });
  237. items.push({
  238. type: "counter",
  239. label: "XP #2",
  240. value: 0,
  241. x: 300,
  242. y: 300,
  243. width: 50,
  244. });
  245. items.push({
  246. type: "counter",
  247. label: "Gold #1",
  248. value: 0,
  249. x: 100,
  250. y: 600,
  251. width: 50,
  252. });
  253. items.push({
  254. type: "counter",
  255. label: "Gold #2",
  256. value: 0,
  257. x: 100,
  258. y: 900,
  259. width: 50,
  260. });
  261. [...Array(3).keys()].forEach(() => {
  262. [...Array(9).keys()].forEach((_, index) => {
  263. items.push({
  264. type: "counter",
  265. label: `Monster #${index + 1}`,
  266. value: 0,
  267. x: 200 + 10 * index,
  268. y: 900 + 10 * index,
  269. width: 50,
  270. });
  271. });
  272. });
  273. items.push({
  274. type: "image",
  275. content:
  276. "https://raw.githubusercontent.com//romgar/gloomhaven/master/images/overlay-tokens/treasures/treasure.png",
  277. x: 1100,
  278. y: 250,
  279. width: 50,
  280. });
  281. [...Array(2).keys()].forEach((_, index) => {
  282. items.push({
  283. type: "image",
  284. content:
  285. "https://raw.githubusercontent.com//romgar/gloomhaven/master/images/overlay-tokens/doors/stone-door.png",
  286. x: 1100 + 20 * index,
  287. y: 300,
  288. width: 50,
  289. });
  290. });
  291. [...Array(2).keys()].forEach((_, index) => {
  292. items.push({
  293. type: "image",
  294. content:
  295. "https://raw.githubusercontent.com//romgar/gloomhaven/master/images/overlay-tokens/traps/spike-pit-trap.png",
  296. x: 1100 + 20 * index,
  297. y: 350,
  298. width: 50,
  299. });
  300. });
  301. [...Array(2).keys()].forEach((_, index) => {
  302. items.push({
  303. type: "image",
  304. content:
  305. "https://raw.githubusercontent.com//romgar/gloomhaven/master/images/overlay-tokens/obstacles/table.png",
  306. x: 1100 + 20 * index,
  307. y: 400,
  308. width: 50,
  309. });
  310. });
  311. // Character ability cards
  312. const brute = {
  313. code: "BR",
  314. abilityCards: {
  315. "level-1": [
  316. "eye-for-an-eye",
  317. "grab-and-go",
  318. "leaping-cleave",
  319. "overwhelming-assault",
  320. "provoking-roar",
  321. "shield-bash",
  322. "spare-dagger",
  323. "sweeping-blow",
  324. "trample",
  325. "warding-strength",
  326. ],
  327. "level-X": ["balanced-measure", "skewer", "wall-of-doom"],
  328. "level-2": ["fatal-advance", "juggernaut"],
  329. "level-3": ["brute-force", "hook-and-chain"],
  330. "level-4": ["devastating-hack", "unstoppable-charge"],
  331. "level-5": ["skirmishing-maneuver", "whirlwind"],
  332. "level-6": ["immovable-phalanx", "quietus"],
  333. "level-7": ["crippling-offensive", "defensive-tactics"],
  334. "level-8": ["frenzied-onslaught", "selfish-retribution"],
  335. "level-9": ["face-your-end", "king-of-the-hill"],
  336. },
  337. backCard:
  338. "https://raw.githubusercontent.com//romgar/gloomhaven/master/images/character-ability-cards/BR/br-back.png",
  339. icon:
  340. "https://raw.githubusercontent.com/romgar/gloomhaven/master/images/character-icons/brute-icon.png",
  341. token:
  342. "https://raw.githubusercontent.com/romgar/gloomhaven/master/images/character-icons/brute-character-token.png",
  343. };
  344. brute.abilityCards["level-1"].forEach((abilityName, index) => {
  345. items.push({
  346. type: "image",
  347. content: `https://raw.githubusercontent.com//romgar/gloomhaven/master/images/character-ability-cards/${brute.code}/${abilityName}.png`,
  348. backContent: `${brute.backCard}`,
  349. x: 0 + 100 * index,
  350. y: 1000,
  351. width: 100,
  352. });
  353. });
  354. items.push({
  355. type: "image",
  356. content: brute.icon,
  357. x: 450,
  358. y: 500,
  359. width: 40,
  360. });
  361. [...Array(5).keys()].forEach((_, index) => {
  362. items.push({
  363. type: "image",
  364. content: brute.token,
  365. x: 350 + 20 * index,
  366. y: 500,
  367. width: 20,
  368. });
  369. });
  370. const spellWeaver = {
  371. code: "SW",
  372. abilityCards: {
  373. "level-1": [
  374. "fire-orbs",
  375. "flame-strike",
  376. "freezing-nova",
  377. "frost-armor",
  378. "impaling-eruption",
  379. "mana-bolt",
  380. "reviving-ether",
  381. "ride-the-wind",
  382. ],
  383. "level-X": ["crackling-air", "hardened-spikes", "aid-from-the-ether"],
  384. "level-2": ["flashing-burst", "icy-blast"],
  385. "level-3": ["elemental-aid", "cold-fire"],
  386. "level-4": ["forked-beam", "spirit-of-doom"],
  387. "level-5": ["engulfed-in-flames", "chromatic-explosion"],
  388. "level-6": ["frozen-night", "living-torch"],
  389. "level-7": ["stone-fists", "twin-restoration"],
  390. "level-8": ["zephyr-wings", "cold-front"],
  391. "level-9": ["inferno", "black-hole"],
  392. },
  393. backCard:
  394. "https://raw.githubusercontent.com//romgar/gloomhaven/master/images/character-ability-cards/SW/sw-back.png",
  395. icon:
  396. "https://raw.githubusercontent.com/romgar/gloomhaven/master/images/character-icons/spellweaver-icon.png",
  397. token:
  398. "https://raw.githubusercontent.com/romgar/gloomhaven/master/images/character-icons/spellweaver-character-token.png",
  399. };
  400. spellWeaver.abilityCards["level-1"].forEach((abilityName, index) => {
  401. items.push({
  402. type: "image",
  403. content: `https://raw.githubusercontent.com//romgar/gloomhaven/master/images/character-ability-cards/${spellWeaver.code}/${abilityName}.png`,
  404. backContent: `${spellWeaver.backCard}`,
  405. x: 0 + 100 * index,
  406. y: 1150,
  407. width: 100,
  408. });
  409. });
  410. items.push({
  411. type: "image",
  412. content: spellWeaver.icon,
  413. x: 450,
  414. y: 700,
  415. width: 40,
  416. });
  417. [...Array(5).keys()].forEach((_, index) => {
  418. items.push({
  419. type: "image",
  420. content: spellWeaver.token,
  421. x: 350 + 20 * index,
  422. y: 700,
  423. width: 20,
  424. });
  425. });
  426. const elements = ["ice", "air", "earth", "fire", "dark", "light"];
  427. elements.forEach((elementName, index) => {
  428. items.push({
  429. type: "image",
  430. content: `https://raw.githubusercontent.com/romgar/gloomhaven/master/images/elements/${elementName}-element.svg`,
  431. x: 0 + 30 * index,
  432. y: 0,
  433. width: 30,
  434. });
  435. });
  436. items.push({
  437. type: "image",
  438. content:
  439. "https://raw.githubusercontent.com/romgar/gloomhaven/master/images/elements/element-matboard.png",
  440. x: 0,
  441. y: 100,
  442. width: 300,
  443. });
  444. const ailments = [
  445. "reinforcement",
  446. "disarm",
  447. "immobilise",
  448. "wound",
  449. "stun",
  450. "invisible",
  451. "confusion",
  452. "poison",
  453. ];
  454. [...Array(5).keys()].forEach((_, rowIndex) => {
  455. ailments.forEach((ailmentName, index) => {
  456. items.push({
  457. type: "image",
  458. content: `https://raw.githubusercontent.com/romgar/gloomhaven/master/images/ailments/${ailmentName}.png`,
  459. x: 0 + 30 * index,
  460. y: 100 + 40 * rowIndex,
  461. width: 30,
  462. });
  463. });
  464. const battleGoals = [
  465. "aggressor",
  466. "diehard",
  467. "dynamo",
  468. "executioner",
  469. "explorer",
  470. "fasthealer",
  471. "hoarder",
  472. "hunter",
  473. "indigent",
  474. "layabout",
  475. "masochist",
  476. "neutralizer",
  477. "opener",
  478. "pacifist",
  479. "plunderer",
  480. "professional",
  481. "protector",
  482. "purist",
  483. "sadist",
  484. "scrambler",
  485. "straggler",
  486. "streamliner",
  487. "workhorse",
  488. "zealot",
  489. ];
  490. battleGoals.forEach((battleGoalName, index) => {
  491. items.push({
  492. type: "image",
  493. content: `https://raw.githubusercontent.com/romgar/gloomhaven/master/images/battle-goals/${battleGoalName}.png`,
  494. backContent:
  495. "https://raw.githubusercontent.com/romgar/gloomhaven/master/images/battle-goals/battlegoal-back.png",
  496. x: 200 + 1 * index,
  497. y: 0 + 1 * index,
  498. flipped: true,
  499. width: 30,
  500. });
  501. });
  502. const characterItems = [
  503. "boots-of-striding",
  504. "cloak-of-invisibility",
  505. "eagle-eye-goggles",
  506. "heater-shield",
  507. "hide-armor",
  508. "iron-helmet",
  509. "leather-armor",
  510. "minor-healing-potion",
  511. "minor-power-potion",
  512. "minor-stamina-potion",
  513. "piercing-bow",
  514. "poison-dagger",
  515. "war-hammer",
  516. "winged-shoes",
  517. ];
  518. characterItems.forEach((itemName, index) => {
  519. items.push({
  520. type: "image",
  521. content: `https://raw.githubusercontent.com/romgar/gloomhaven/master/images/items/1-14/${itemName}.png`,
  522. x: 1500 + 40 * index,
  523. y: 1500,
  524. flipped: true,
  525. width: 40,
  526. });
  527. });
  528. });
  529. return {
  530. items,
  531. board: { size: 3000, scale: 0.5 },
  532. };
  533. };
  534. export const game = genGloomhaven();
  535. export default game;