memoscan
← all memos

Memo 0x972b9d86…b26463 on Ethereum

let cp2y = y - 134.8 * scaleY x += 130.5 * scaleX y -= 193.7 * scaleY g.bezierVertex(cp1x, cp1y, cp2x, cp2y, x, y) cp1x = x + 64.9 * scaleX cp1y = y - 76.8 * scaleY cp2x = x + 78.7 * scaleX cp2y = y - 250.3 * scaleY x += 100.8 * scaleX y -= 385.7 * scaleY g.bezierVertex(cp1x, cp1y, cp2x, cp2y, x, y) cp1x = x + 17.8 * scaleX cp1y = y - 109.2 * scaleY cp2x = x + 134.3 * scaleX cp2y = y - 225.2 * scaleY x += 272.5 * scaleX y -= 225.3 * scaleY g.bezierVertex(cp1x, cp1y, cp2x, cp2y, x, y) cp1x = 2 * x - cp2x cp1y = 2 * y - cp2y cp2x = x + 244.5 * scaleX cp2y = y + 116 * scaleY x += 263.8 * scaleX y += 265.3 * scaleY g.bezierVertex(cp1x, cp1y, cp2x, cp2y, x, y) cp1x = x + 42.3 * scaleX cp1y = y + 274.2 * scaleY cp2x = x + 91.2 * scaleX cp2y = y + 343 * scaleY x += 91.2 * scaleX y += 343 * scaleY g.bezierVertex(cp1x, cp1y, cp2x, cp2y, x, y) cp1x = x + 56.5 * scaleX cp1y = y + 79.5 * scaleY cp2x = x + 143.4 * scaleX cp2y = y + 199.4 * scaleY x += 143.4 * scaleX y += 199.4 * scaleY g.bezierVertex(cp1x, cp1y, cp2x, cp2y, x, y) y += 115.4 * scaleY g.vertex(x, y) cp1x = x + 0 * scaleX cp1y = y + 0 * scaleY cp2x = x - 1000.9 * scaleX cp2y = y + 2.7 * scaleY x -= 1000.9 * scaleX y += 2.7 * scaleY g.bezierVertex(cp1x, cp1y, cp2x, cp2y, x, y) x -= 1.2 * scaleX y -= 120.9 * scaleY g.vertex(x, y) g.endShape(CLOSE) } function drawDuxArchetype(g, scaleX, scaleY) { g.beginShape() g.vertex(531.5 * scaleX, 60.4 * scaleY) g.vertex(500.1 * scaleX, 10.9 * scaleY) g.vertex(472.5 * scaleX, 61.4 * scaleY) g.vertex(502.9 * scaleX, 88 * scaleY) g.endShape(CLOSE) g.beginShape() g.vertex(854.6 * scaleX, 792.0 * scaleY) g.vertex(748.3 * scaleX, 660.7 * scaleY) g.vertex(765.0 * scaleX, 506.9 * scaleY) g.vertex(841.7 * scaleX, 493.9 * scaleY) g.vertex(841.0 * scaleX, 492.7 * scaleY) g.vertex(849.8 * scaleX, 364.1 * scaleY) g.vertex(800.7 * scaleX, 423.5 * scaleY) g.vertex(768.8 * scaleX, 368.6 * scaleY) g.vertex(886.0 * scaleX, 238.3 * scaleY) g.vertex(859.1 * scaleX, 103.2 * scaleY) g.vertex(805.6 * scaleX, 202.7 * scaleY) g.vertex(560.1 * scaleX, 91.5 * scaleY) g.vertex(504.5 * scaleX, 111.0 * scaleY) g.vertex(440.9 * scaleX, 91.5 * scaleY) g.vertex(214.2 * scaleX, 190.9 * scaleY) g.vertex(145.1 * scaleX, 101.5 * scaleY) g.vertex(130.9 * scaleX, 232.4 * scaleY) g.vertex(239.3 * scaleX, 363.3 * scaleY) g.vertex(214.6 * scaleX, 411.3 * scaleY) g.vertex(161.5 * scaleX, 353.0 * scaleY) g.vertex(165.4 * scaleX, 506.8 * scaleY) g.vertex(164.1 * scaleX, 509.4 * scaleY) g.vertex(239.7 * scaleX, 516.1 * scaleY) g.vertex(261.4 * scaleX, 661.0 * scaleY) g.vertex(157.7 * scaleX, 794.8 * scaleY) g.vertex(-0.8 * scaleX, 825.7 * scaleY) g.vertex(0.0 * scaleX, 999.8 * scaleY) g.vertex(1000.3 * scaleX, 1000.0 * scaleY) g.vertex(1000.3 * scaleX, 820.2 * scaleY) g.endShape(CLOSE) } function drawBulwarkArchetype(g, scaleX, scaleY) { g.beginShape() g.vertex(958.3 * scaleX, 833.3 * scaleY) g.vertex(916.6 * scaleX, 795.8 * scaleY) g.vertex(962.3 * scaleX, 696.3 * scaleY) g.vertex(857.8 * scaleX, 742.9 * scaleY) g.vertex(838.9 * scaleX, 725.8 * scaleY) g.vertex(870.4 * scaleX, 657.3 * scaleY) g.vertex(798.4 * scaleX, 689.4 * scaleY) g.vertex(762.8 * scaleX, 657.3 * scaleY) g.vertex(801.8 * scaleX, 557.6 * scaleY) g.vertex(762.8 * scaleX, 512.4 * scaleY) g.vertex(826.2 * scaleX, 384.2 * scaleY) g.vertex(762.8 * scaleX, 326.4 * scaleY) g.vertex(852.5 * scaleX, 175.7 * scaleY) g.vertex(752.8 * scaleX, 102.5 * scaleY) g.vertex(253.8 * scaleX, 102.5 * scaleY) g.vertex(154.7 * scaleX, 175.7 * scaleY) g.vertex(243.8 * scaleX, 326.4 * scaleY) g.vertex(182.6 * scaleX, 384.2 * scaleY) g.vertex(243.8 * scaleX, 518.2 * scaleY) g.vertex(208.7 * scaleX, 557.6 * scaleY) g.vertex(243.8 * scaleX, 657.7 * scaleY) g.vertex(193.9 * scaleX, 704.4 * scaleY) g.vertex(132.8 * scaleX, 676.3 * scaleY) g.vertex(159.6 * scaleX, 736.5 * scaleY) g.vertex(144.5 * scaleX, 750.5 * scaleY) g.vertex(43.6 * scaleX, 704.2 * scaleY) g.vertex(87.9 * scaleX, 803.5 * scaleY) g.vertex(39 * scaleX, 849.3 * scaleY) g.vertex(0.1 * scaleX, 858.4 * scaleY) g.vertex(-1.2 * scaleX, 1001.1 * scaleY) g.vertex(1000.3 * scaleX, 1001.4 * scaleY) g.vertex(1000.4 * scaleX, 846.4 * scaleY) g.endShape(CLOSE) } function drawWardenArchetype(g, scaleX, scaleY) { g.beginShape() g.vertex(960 * scaleX, 662.3 * scaleY) g.vertex(960.8 * scaleX, 661.7 * scaleY) g.vertex(958.3 * scaleX, 661.7 * scaleY) g.vertex(909.1 * scaleX, 510 * scaleY) g.vertex(880.7 * scaleX, 654.7 * scaleY) g.vertex(859 * scaleX, 587.7 * scaleY) g.vertex(835.7 * scaleX, 659.4 * scaleY) g.vertex(790.1 * scaleX, 622 * scaleY) g.vertex(762.8 * scaleX, 528.5 * scaleY) g.vertex(776.2 * scaleX, 384.2 * scaleY) g.vertex(762.8 * scaleX, 326.4 * scaleY) g.vertex(742.5 * scaleX, 175.7 * scaleY) g.vertex(642.8 * scaleX, 102.5 * scaleY) g.vertex(363.8 * scaleX, 102.5 * scaleY) g.vertex(264.7 * scaleX, 175.7 * scaleY) g.vertex(243.8 * scaleX, 326.4 * scaleY) g.vertex(232.6 * scaleX, 384.2 * scaleY) g.vertex(243.8 * scaleX, 528.5 * scaleY) g.vertex(219.8 * scaleX, 622 * scaleY) g.vertex(178.4 * scaleX, 660.9 * scaleY) g.vertex(177.8 * scaleX, 660.9 * scaleY) g.vertex(155.2 * scaleX, 591.5 * scaleY) g.vertex(132.4 * scaleX, 661.8 * scaleY) g.vertex(131.6 * scaleX, 661.9 * scaleY) g.vertex(87.8 * scaleX, 510 * scaleY) g.vertex(51.7 * scaleX, 661.9 * scaleY) g.vertex(0.1 * scaleX, 673.5 * scaleY) g.vertex(-1.2 * scaleX, 1001.1 * scaleY) g.vertex(1000.3 * scaleX, 1001.4 * scaleY) g.vertex(1000.7 * scaleX, 673.5 * scaleY) g.endShape(CLOSE) } function drawShadeArchetype(g, scaleX, scaleY) { g.beginShape() g.vertex(909 * scaleX, 623.5 * scaleY) g.vertex(844 * scaleX, 651.3 * scaleY) g.vertex(707.2 * scaleX, 181.5 * scaleY) g.vertex(546.4 * scaleX, 106.5 * scaleY) g.vertex(509.6 * scaleX, 69.7 * scaleY) g.vertex(474.1 * scaleX, 105.2 * scaleY) g.vertex(309.5 * scaleX, 179.3 * scaleY) g.vertex(184.8 * scaleX, 651.3 * scaleY) g.vertex(124 * scaleX, 623.5 * scaleY) g.vertex(0.3 * scaleX, 988.8 * scaleY) g.vertex(0.5 * scaleX, 1003 * scaleY) g.vertex(1000 * scaleX, 1002.6 * scaleY) g.vertex(1001.2 * scaleX, 987.1 * scaleY) g.endShape(CLOSE) } function drawBruteArchetype(g, scaleX, scaleY) { g.beginShape() // Starting point g.vertex(940.1 * scaleX, 779.9 * scaleY) // l21.8-23.7 -> 961.9, 756.2 g.vertex(961.9 * scaleX, 756.2 * scaleY) // l-49.4,17.8 -> 912.5, 774 g.vertex(912.5 * scaleX, 774 * scaleY) // l-27.7-5.9 -> 884.8, 768.1 g.vertex(884.8 * scaleX, 768.1 * scaleY) // l29.2-44.7 -> 914, 723.4 g.vertex(914 * scaleX, 723.4 * scaleY) // l-92,31.3 -> 822, 754.7 g.vertex(822 * scaleX, 754.7 * scaleY) // l-12-2.6 -> 810, 752.1 g.vertex(810 * scaleX, 752.1 * scaleY) // l76.6-74 -> 886.6, 678.1 g.vertex(886.6 * scaleX, 678.1 * scaleY) // l-138.5,68.6 -> 748.1, 746.7 g.vertex(748.1 * scaleX, 746.7 * scaleY) // h.1 (tiny horizontal) g.vertex(748.2 * scaleX, 746.7 * scaleY) // c0,0-77.4,37.6-77.4,37.6 -> 670.8, 784.3 g.vertex(670.8 * scaleX, 784.3 * scaleY) // l41.5-73.4 -> 712.3, 710.9 g.vertex(712.3 * scaleX, 710.9 * scaleY) // l45.1-426.7 -> 757.4, 284.2 g.vertex(757.4 * scaleX, 284.2 * scaleY) // c77,23.1,137.3,227.8,137.3,149 (curve to 894.7, 433.2 but end at 894.7, 284.2) g.bezierVertex(834.4 * scaleX, 307.3 * scaleY, 894.7 * scaleX, 512 * scaleY, 894.7 * scaleX, 433.2 * scaleY) // c0-58.3-24.2-142.6-61.6-200.8 -> 833.1, 232.4 g.bezierVertex(894.7 * scaleX, 374.9 * scaleY, 870.5 * scaleX, 290.6 * scaleY, 833.1 * scaleX, 232.4 * scaleY) // c.6,0,1.1,0,1.7,0 -> 834.8, 232.4 g.vertex(834.8 * scaleX, 232.4 * scaleY) // c59.1,0,107.1-84.6,107.1-189.5 -> 941.9, 42.9 g.bezierVertex(893.9 * scaleX, 232.4 * scaleY, 941.9 * scaleX, 147.8 * scaleY, 941.9 * scaleX, 42.9 * scaleY) // s-37.6,72-87.3,101.1 (smooth curve) -> 854.6, 144 g.bezierVertex(941.9 * scaleX, 114.9 * scaleY, 904.3 * scaleX, 144 * scaleY, 854.6 * scaleX, 144 * scaleY) // l-219.5-27.7 -> 635.1, 116.3 g.vertex(635.1 * scaleX, 116.3 * scaleY) // l-274.6-.2 -> 360.5, 116.1 g.vertex(360.5 * scaleX, 116.1 * scaleY) // l-195.3,31.1 -> 165.2, 147.2 g.vertex(165.2 * scaleX, 147.2 * scaleY) // C112.4,126,71.5-11.5,71.5,43.1 (absolute curve) g.bezierVertex(112.4 * scaleX, 126 * scaleY, 71.5 * scaleX, -11.5 * scaleY, 71.5 * scaleX, 43.1 * scaleY) // s35.4,156.6,82.9,182.8 -> 154.4, 225.9 g.bezierVertex(71.5 * scaleX, 97.7 * scaleY, 106.9 * scaleX, 199.7 * scaleY, 154.4 * scaleX, 225.9 * scaleY) // c-38.2,48.5-63.1,127.7-63.1,217.5 -> 91.3, 443.4 g.bezierVertex(116.2 * scaleX, 274.4 * scaleY, 91.3 * scaleX, 353.6 * scaleY, 91.3 * scaleX, 443.4 * scaleY) // c0,83.5,67.7-151.1,151.1-151.1 -> 242.4, 292.3 g.bezierVertex(91.3 * scaleX, 526.9 * scaleY, 159 * scaleX, 292.3 * scaleY, 242.4 * scaleX, 292.3 * scaleY) // c3.3,0,6.6-.2,9.9-.6 -> 252.3, 291.7 g.vertex(252.3 * scaleX, 291.7 * scaleY) // l.4.6 -> 252.7, 292.3 g.vertex(252.7 * scaleX, 292.3 * scaleY) // l49.9,418.8 -> 302.6, 711.1 g.vertex(302.6 * scaleX, 711.1 * scaleY) // l40.7,75 -> 343.3, 786.1 g.vertex(343.3 * scaleX, 786.1 * scaleY) // l-123.5-52.2 -> 219.8, 733.9 g.vertex(219.8 * scaleX, 733.9 * scaleY) // l-126.3-68.6 -> 93.5, 665.3 g.vertex(93.5 * scaleX, 665.3 * scaleY) // l72.4,76.7 -> 165.9, 742 g.vertex(165.9 * scaleX, 742 * scaleY) // l-9.3,1.4 -> 156.6, 743.4 g.vertex(156.6 * scaleX, 743.4 * scaleY) // l-88.1-32.9 -> 68.5, 710.5 g.vertex(68.5 * scaleX, 710.5 * scaleY) // l25.2,42.3 -> 93.7, 752.8 g.vertex(93.7 * scaleX, 752.8 * scaleY) // l-32.5,4.9 -> 61.2, 757.7 g.vertex(61.2 * scaleX, 757.7 * scaleY) // l-36.4-14.4 -> 24.8, 743.3 g.vertex(24.8 * scaleX, 743.3 * scaleY) // l14.8,17.6 -> 39.6, 760.9 g.vertex(39.6 * scaleX, 760.9 * scaleY) // l-42.9,6.4 -> -3.3, 767.3 (clamp to 0) g.vertex(0 * scaleX, 767.3 * scaleY) // l1.6,231.7 -> 1.6, 999 g.vertex(1.6 * scaleX, 999 * scaleY) // h1001.1 -> 1002.7, 999 g.vertex(1002.7 * scaleX, 999 * scaleY) // v-206.5 -> 1002.7, 792.5 g.vertex(1002.7 * scaleX, 792.5 * scaleY) // l-59.4-12.7 -> 943.3, 779.8 (close to start) g.vertex(943.3 * scaleX, 779.8 * scaleY) g.endShape(CLOSE) } function drawEmperorArchetype(g, scaleX, scaleY) { // New Emperor form from updated SVG g.beginShape() // Start at 936.5, 608.1 g.vertex(936.5 * scaleX, 608.1 * scaleY) // Line to (936.5-142.7, 608.1-77.7) = (793.8, 530.4) g.vertex(793.8 * scaleX, 530.4 * scaleY) // The path continues with curves, but we'll approximate with vertices // c.5-2.5.8-5 .8-7.7 (relative curve, small adjustment) g.vertex(794.6 * scaleX, 522.7 * scaleY) // c0-10.8-4.9-20.5-12.5-27 g.vertex(782.1 * scaleX, 495.7 * scaleY) // l73.7-316.8 (line to relative) g.vertex(855.8 * scaleX, 178.9 * scaleY) // s-133.6-106.3-171.4-106 (smooth curve approximated) g.vertex(684.4 * scaleX, 72.9 * scaleY) // c-4.7-.7-5.6,7.6-3.8,9.5 (small curve) g.vertex(680.6 * scaleX, 82.4 * scaleY) // l61.5,65.5 g.vertex(742.1 * scaleX, 147.9 * scaleY) // l-17.4,7.6 g.vertex(724.7 * scaleX, 155.5 * scaleY) // c-18.2-4.2-42.9-7.7-71.7-10.6 g.vertex(653.0 * scaleX, 144.9 * scaleY) // l13.7-34.7 g.vertex(666.7 * scaleX, 110.2 * scaleY) // c-.6-3.2-3.3-5-6.3-4 (small adjustment) g.vertex(660.4 * scaleX, 106.2 * scaleY) // c-1.4.4-14.9,17.1-17.2,19.9 g.vertex(643.2 * scaleX, 126.1 * scaleY) // c-4.6,5.5-9.1,11.1-13.6,16.7 g.vertex(629.6 * scaleX, 142.8 * scaleY) // c-16-1.3-33-2.3-50.5-3.2 g.vertex(579.1 * scaleX, 139.6 * scaleY) // l32.7-82.7 g.vertex(611.8 * scaleX, 56.9 * scaleY) // c-.6-3.2-3.3-5-6.3-4 g.vertex(605.5 * scaleX, 52.9 * scaleY) // c-1.4.4-14.9,17.1-17.2,19.9 g.vertex(588.3 * scaleX, 72.8 * scaleY) // c-17.7,21.5-35.1,43.3-52.4,65.2 g.vertex(535.9 * scaleX, 138.0 * scaleY) // c-7.7-.2-15.4-.4-23.1-.5 g.vertex(512.8 * scaleX, 137.5 * scaleY) // l-13.5-38.5 g.vertex(499.3 * scaleX, 99.0 * scaleY) // c-1.4-4.1-7.3-4.1-8.6,0 g.vertex(490.7 * scaleX, 99.0 * scaleY) // l-12.6,38.2 g.vertex(478.1 * scaleX, 137.2 * scaleY) // c-7.6,0-15.1,0-22.6.2 g.vertex(455.5 * scaleX, 137.4 * scaleY) // c-20.8-22.1-41.5-44.3-62.6-66 g.vertex(392.9 * scaleX, 71.4 * scaleY) // c-2.6-2.7-17.7-18.4-19.2-18.8 g.vertex(373.7 * scaleX, 52.6 * scaleY) // c-3.3-.8-5.9,1.2-6.4,4.4 g.vertex(367.3 * scaleX, 57.0 * scaleY) // l39.7,81.8 g.vertex(407.0 * scaleX, 138.8 * scaleY) // c-19.1.8-37.5,2-54.6,3.5 g.vertex(352.4 * scaleX, 142.3 * scaleY) // c-4.6-4.8-9.1-9.5-13.7-14.2 g.vertex(338.7 * scaleX, 128.1 * scaleY) // c-2.6-2.7-17.7-18.4-19.2-18.8 g.vertex(319.5 * scaleX, 109.3 * scaleY) // c-3.3-.8-5.9,1.2-6.4,4.4 g.vertex(313.1 * scaleX, 113.7 * scaleY) // l15.2,31.2 g.vertex(328.3 * scaleX, 144.9 * scaleY) // c-22.5,2.7-41.9,6.2-56.7,10.5 g.vertex(271.6 * scaleX, 155.4 * scaleY) // l-16.9-7.5 g.vertex(254.7 * scaleX, 147.9 * scaleY) // l61.6-65.4 g.vertex(316.3 * scaleX, 82.5 * scaleY) // c1.8-1.9,1-10.2-3.7-9.5 g.vertex(312.6 * scaleX, 73.0 * scaleY) // c-78.6,24.3-171.4,105.7-171.4,105.7 g.vertex(141.2 * scaleX, 178.7 * scaleY) // l72.3,302.4 g.vertex(213.5 * scaleX, 481.1 * scaleY) // c-8.3,6.5-13.6,16.5-13.6,27.9 g.vertex(199.9 * scaleX, 509.0 * scaleY) // s.9,8.9,2.4,12.9 g.vertex(202.3 * scaleX, 521.9 * scaleY) // l-143.1,82.9 g.vertex(59.2 * scaleX, 604.8 * scaleY) // L-.7,834.6 (absolute line) g.vertex(-0.7 * scaleX, 834.6 * scaleY) // l1.6,166.5 g.vertex(0.9 * scaleX, 1001.1 * scaleY) // h1001.1 (horizontal line) g.vertex(1002.0 * scaleX, 1001.1 * scaleY) // v-172.3 (vertical line up) g.vertex(1002.0 * scaleX, 828.8 * scaleY) // l-65.5-220.7 g.vertex(936.5 * scaleX, 608.1 * scaleY) g.endShape(CLOSE) } function drawArmatusArchetype(g, scaleX, scaleY) { // Armatus form - angular armor-like silhouette with crown spikes g.beginShape() // Start at right side: 817.9, 763.3 g.vertex(817.9 * scaleX, 763.3 * scaleY) // l-130.2-633.3 (diagonal line up-left to shoulder) g.vertex(687.7 * scaleX, 130.0 * scaleY) // v-51.2 (vertical line up) g.vertex(687.7 * scaleX, 78.8 * scaleY) // l-22.2-10 (crown spike 1) g.vertex(665.5 * scaleX, 68.8 * scaleY) // v53.8 g.vertex(665.5 * scaleX, 122.6 * scaleY) // c-5.2-1.4-10.7-2.7-16.6-3.9 g.vertex(648.9 * scaleX, 118.7 * scaleY) // v-31.3 g.vertex(648.9 * scaleX, 87.4 * scaleY) // l-22.2-10 (crown spike 2) g.vertex(626.7 * scaleX, 77.4 * scaleY) // v37.3 g.vertex(626.7 * scaleX, 114.7 * scaleY) // c-5.4-.8-10.9-1.6-16.6-2.4 g.vertex(610.1 * scaleX, 112.3 * scaleY) // v-15 g.vertex(610.1 * scaleX, 97.3 * scaleY) // l-22.2-10 (crown spike 3) g.vertex(587.9 * scaleX, 87.3 * scaleY) // v22.5 g.vertex(587.9 * scaleX, 109.8 * scaleY) // c-5.4-.5-10.8-1-16.3-1.5 g.vertex(571.6 * scaleX, 108.3 * scaleY) // v-11 g.vertex(571.6 * scaleX, 97.3 * scaleY) // l-22.9-10 (crown spike 4) g.vertex(548.7 * scaleX, 87.3 * scaleY) // v19.5 g.vertex(548.7 * scaleX, 106.8 * scaleY) // c-5.4-.3-10.8-.6-16.2-.8 g.vertex(532.5 * scaleX, 106.0 * scaleY) // v-8.7 g.vertex(532.5 * scaleX, 97.3 * scaleY) // l-22.2-10 (crown spike 5) g.vertex(510.3 * scaleX, 87.3 * scaleY) // v18.1 g.vertex(510.3 * scaleX, 105.4 * scaleY) // c-5.5,0-11.1-.2-16.6-.2 g.vertex(493.7 * scaleX, 105.2 * scaleY) // v-17.9 g.vertex(493.7 * scaleX, 87.3 * scaleY) // l-22.1,10 (crown spike 6 - going back up) g.vertex(471.6 * scaleX, 97.3 * scaleY) // v8.1 g.vertex(471.6 * scaleX, 105.4 * scaleY) // c-5.6.1-11.2.3-16.7.5 g.vertex(454.9 * scaleX, 105.9 * scaleY) // v-18.6 g.vertex(454.9 * scaleX, 87.3 * scaleY) // l-21.8,10 (crown spike 7) g.vertex(433.1 * scaleX, 97.3 * scaleY) // v9.8 g.vertex(433.1 * scaleX, 107.1 * scaleY) // c-5.8.4-11.5.8-17,1.3 g.vertex(416.1 * scaleX, 108.4 * scaleY) // v-21.1 g.vertex(416.1 * scaleX, 87.3 * scaleY) // l-22.2,10 (crown spike 8) g.vertex(393.9 * scaleX, 97.3 * scaleY) // v13.5 g.vertex(393.9 * scaleX, 110.8 * scaleY) // c-5.7.7-11.3,1.6-16.6,2.5 g.vertex(377.3 * scaleX, 113.3 * scaleY) // v-36 g.vertex(377.3 * scaleX, 77.3 * scaleY) // l-22.2,10 (crown spike 9) g.vertex(355.1 * scaleX, 87.3 * scaleY) // v30.4 g.vertex(355.1 * scaleX, 117.7 * scaleY) // c-5.9,1.4-11.5,2.9-16.6,4.6 g.vertex(338.5 * scaleX, 122.3 * scaleY) // v-53.6 g.vertex(338.5 * scaleX, 68.7 * scaleY) // l-22.2,10 (crown spike 10) g.vertex(316.3 * scaleX, 78.7 * scaleY) // v62.9 g.vertex(316.3 * scaleX, 141.6 * scaleY) // l-157.9,618.3 (diagonal line down-left to bottom left) g.vertex(158.4 * scaleX, 759.9 * scaleY) // L-1.3,969.7 (line to bottom left corner area) g.vertex(-1.3 * scaleX, 969.7 * scaleY) // l1.6,29.3 g.vertex(0.3 * scaleX, 999.0 * scaleY) // h1001.1 (horizontal line across bottom) g.vertex(1001.4 * scaleX, 999.0 * scaleY) // v-30.1 g.vertex(1001.4 * scaleX, 968.9 * scaleY) // l-183.5-205.6 (diagonal line back to start) g.vertex(817.9 * scaleX, 763.3 * scaleY) g.endShape(CLOSE) } function drawTitanArchetype(g, scaleX, scaleY, maskCount) { g.beginShape() if (maskCount === "Conflux") { let x = 1000.2 * scaleX let y = 776.4 * scaleY g.vertex(x, y) let cp1x = x - 22.5 * scaleX let cp1y = y - 31.3 * scaleY let cp2x = x - 45.3 * scaleX let cp2y = y - 63.4 * scaleY x -= 65.5 * scaleX y -= 91.7 * scaleY g.bezierVertex(cp1x, cp1y, cp2x, cp2y, x, y) cp1x = x - 48.9 * scaleX cp1y = y - 68.7 * scaleY cp2x = x - 71.9 * scaleX cp2y = y - 193.7 * scaleY x -= 91.2 * scaleX y -= 343 * scaleY g.bezierVertex(cp1x, cp1y, cp2x, cp2y, x, y) cp1x = x - 19.3 * scaleX cp1y = y - 149.2 * scaleY cp2x = x - 176.1 * scaleX cp2y = y - 274.1 * scaleY x -= 360.8 * scaleX y -= 274.1 * scaleY g.bezierVertex(cp1x, cp1y, cp2x, cp2y, x, y) cp1x = 2 * x - cp2x cp1y = 2 * y - cp2y cp2x = x - 314.1 * scaleX cp2y = y + 124.9 * scaleY x -= 332 * scaleX y += 234.2 * scaleY g.bezierVertex(cp1x, cp1y, cp2x, cp2y, x, y) cp1x = x - 22.1 * scaleX cp1y = y + 135.4 * scaleY cp2x = x - 35.9 * scaleX cp2y = y + 308.9 * scaleY x -= 100.8 * scaleX y += 385.7 * scaleY g.bezierVertex(cp1x, cp1y, cp2x, cp2y, x, y) cp1x = 32 * scaleX cp1y = 708.7 * scaleY cp2x = 16.7 * scaleX cp2y = 728.9 * scaleY x = 0 * scaleX y = 751.7 * scaleY g.bezierVertex(cp1x, cp1y, cp2x, cp2y, x, y) x -= 0.2 * scaleX y += 248.5 * scaleY g.vertex(x, y) x += 1000.2 * scaleX y -= 0.3 * scaleY g.vertex(x, y) x += 0.3 * scaleX y -= 223.5 * scaleY g.vertex(x, y) } else { let x = -2.3 * scaleX let y = 881.6 * scaleY g.vertex(x, y) let cp1x = x + 34.5 * scaleX let cp1y = y - 70 * scaleY let cp2x = x + 80.7 * scaleX let cp2y = y - 134.8 * scaleY x += 130.5 * scaleX y -= 193.7 * scaleY g.bezierVertex(cp1x, cp1y, cp2x, cp2y, x, y) cp1x = x + 64.9 * scaleX cp1y = y - 76.8 * scaleY cp2x = x + 78.7 * scaleX cp2y = y - 250.3 * scaleY x += 100.8 * scaleX y -= 385.7 * scaleY g.bezierVertex(cp1x, cp1y, cp2x, cp2y, x, y) cp1x = x + 17.8 * scaleX cp1y = y - 109.2 * scaleY cp2x = x + 134.3 * scaleX cp2y = y - 225.2 * scaleY x += 272.5 * scaleX y -= 225.3 * scaleY g.bezierVertex(cp1x, cp1y, cp2x, cp2y, x, y) cp1x = 2 * x - cp2x cp1y = 2 * y - cp2y cp2x = x + 244.5 * scaleX cp2y = y + 116 * scaleY x += 263.8 * scaleX y += 265.3 * scaleY g.bezierVertex(cp1x, cp1y, cp2x, cp2y, x, y) cp1x = x + 42.3 * scaleX cp1y = y + 274.2 * scaleY cp2x = x + 91.2 * scaleX cp2y = y + 343 * scaleY x += 91.2 * scaleX y += 343 * scaleY g.bezierVertex(cp1x, cp1y, cp2x, cp2y, x, y) cp1x = x + 56.5 * scaleX cp1y = y + 79.5 * scaleY cp2x = x + 143.4 * scaleX cp2y = y + 199.4 * scaleY x += 143.4 * scaleX y += 199.4 * scaleY g.bezierVertex(cp1x, cp1y, cp2x, cp2y, x, y) y += 115.4 * scaleY g.vertex(x, y) cp1x = x + 0 * scaleX cp1y = y + 0 * scaleY cp2x = x - 1000.9 * scaleX cp2y = y + 2.7 * scaleY x -= 1000.9 * scaleX y += 2.7 * scaleY g.bezierVertex(cp1x, cp1y, cp2x, cp2y, x, y) x -= 1.2 * scaleX y -= 120.9 * scaleY g.vertex(x, y) } g.endShape(CLOSE) } /* ========================= MASK LAYOUT ========================= */ function layoutMasks() { const count = TRAITS.count const HEAD_ZONE_H = width // head zone is a square region at top, width x width const cx = width / 2, cy = HEAD_ZONE_H / 2 // v2: center in head zone, not full canvas const baseW = width * 0.62 const baseH = baseW * 1.18 if (count === "Mono") { masks.push(makeMask(cx, cy, baseW, baseH, 0, 0)) } else if (count === "Conflux") { const maskWidth = baseW * 0.86 const gap = maskWidth * 0.36 masks.push(makeMask(cx - gap / 2, cy, maskWidth, baseH * 0.86, -0.03, 0)) masks.push(makeMask(cx + gap / 2, cy, maskWidth, baseH * 0.86, 0.03, 1)) } } function makeMask(x, y, w, h, rot, maskIndex) { return { x, y, w, h, rot, maskIndex, edgeStyle: TRAITS.edgeStyle, sight: TRAITS.sight, voice: TRAITS.voice, scent: TRAITS.scent, ornament: TRAITS.ornament, hollows: TRAITS.hollows, } } function drawMaskEyesBlocking(pg, m) { pg.push() pg.translate(m.x, m.y) pg.rotate(PARAMS.axisLock ? 0 : m.rot) const rx = m.w * 0.22 const ry = m.h * 0.13 const ly = -m.h * 0.12 const left = { x: -m.w * 0.18, y: ly } const right = { x: m.w * 0.18, y: ly } pg.noStroke() pg.fill(0, 0, 10) if (TRAITS.iris === "Null" || TRAITS.iris === "Fury" || TRAITS.iris === "Plasma" || TRAITS.iris === "Omnia") { const strokeW = m.w * 0.03 if (m.sight === "Mono") { const center = { x: 0, y: ly } drawEye(pg, center, rx, ry, m.sight, strokeW) } else if (m.sight === "Verge") { drawVerticalAlmondTotal(pg, rx, ry, ly, m.w, strokeW) } else { drawEye(pg, left, rx, ry, m.sight, strokeW) drawEye(pg, right, rx, ry, m.sight, strokeW) } } else if (TRAITS.iris === "Abyss") { if (m.sight === "Mono") { const center = { x: 0, y: ly } drawEye(pg, center, rx, ry, m.sight, 0) } else if (m.sight === "Verge") { drawVerticalAlmondTotal(pg, rx, ry, ly, m.w, 0) } else { drawEye(pg, left, rx, ry, m.sight, 0) drawEye(pg, right, rx, ry, m.sight, 0) } } pg.pop() } function drawMaskEyes(pg, m) { pg.push() pg.translate(m.x, m.y) pg.rotate(PARAMS.axisLock ? 0 : m.rot) const rx = m.w * 0.22 const ry = m.h * 0.13 const ly = -m.h * 0.12 const left = { x: -m.w * 0.18, y: ly } const right = { x: m.w * 0.18, y: ly } pg.noStroke() if (TRAITS.iris === "Null") { pg.fill(0, 0, 100) if (m.sight === "Mono") { const center = { x: 0, y: ly } drawEye(pg, center, rx, ry, m.sight, 0) } else if (m.sight === "Verge") { drawVerticalAlmondTotal(pg, rx, ry, ly, m.w, 0) } else { drawEye(pg, left, rx, ry, m.sight, 0) drawEye(pg, right, rx, ry, m.sight, 0) } } else if (TRAITS.iris === "Fury") { pg.fill(0, 100, 100) if (m.sight === "Mono") { const center = { x: 0, y: ly } drawEye(pg, center, rx, ry, m.sight, 0) } else if (m.sight === "Verge") { drawVerticalAlmondTotal(pg, rx, ry, ly, m.w, 0) } else { drawEye(pg, left, rx, ry, m.sight, 0) drawEye(pg, right, rx, ry, m.sight, 0) } } else if (TRAITS.iris === "Plasma") { pg.fill(185, 100, 100) if (m.sight === "Mono") { const center = { x: 0, y: ly } drawEye(pg, center, rx, ry, m.sight, 0) } else if (m.sight === "Verge") { drawVerticalAlmondTotal(pg, rx, ry, ly, m.w, 0) } else { drawEye(pg, left, rx, ry, m.sight, 0) drawEye(pg, right, rx, ry, m.sight, 0) } } else if (TRAITS.iris === "Omnia") { const cycleSpeed = 0.08 const palette = PARAMS.palette const complementaryHues = palette.map(c => { const col = color(c) const h = hue(col) return (h + 180) % 360 }) const cyclePosition = (millis() * cycleSpeed) % (complementaryHues.length * 100) const colorIndex = floor(cyclePosition / 100) % complementaryHues.length const nextIndex = (colorIndex + 1) % complementaryHues.length const blend = (cyclePosition % 100) / 100 const currentHue = lerp(complementaryHues[colorIndex], complementaryHues[nextIndex], blend) pg.fill(currentHue, 100, 100) if (m.sight === "Mono") { const center = { x: 0, y: ly } drawEye(pg, center, rx, ry, m.sight, 0) } else if (m.sight === "Verge") { drawVerticalAlmondTotal(pg, rx, ry, ly, m.w, 0) } else { drawEye(pg, left, rx, ry, m.sight, 0) drawEye(pg, right, rx, ry, m.sight, 0) } } else if (TRAITS.iris === "Abyss") { const strokeW = m.w * 0.03 pg.fill(0, 0, 100) if (m.sight === "Mono") { const center = { x: 0, y: ly } drawEye(pg, center, rx, ry, m.sight, strokeW) } else if (m.sight === "Verge") { drawVerticalAlmondTotal(pg, rx, ry, ly, m.w, strokeW) } else { drawEye(pg, left, rx, ry, m.sight, strokeW) drawEye(pg, right, rx, ry, m.sight, strokeW) } pg.erase() if (m.sight === "Mono") { const center = { x: 0, y: ly } drawEye(pg, center, rx, ry, m.sight, 0) } else if (m.sight === "Verge") { drawVerticalAlmondTotal(pg, rx, ry, ly, m.w, 0) } else { drawEye(pg, left, rx, ry, m.sight, 0) drawEye(pg, right, rx, ry, m.sight, 0) } pg.noErase() } pg.pop() } function drawMaskEyesOmniaBase(pg, m) { pg.push() pg.translate(m.x, m.y) pg.rotate(PARAMS.axisLock ? 0 : m.rot) const rx = m.w * 0.22 const ry = m.h * 0.13 const ly = -m.h * 0.12 const left = { x: -m.w * 0.18, y: ly } const right = { x: m.w * 0.18, y: ly } pg.noStroke() pg.fill(0, 0, 100) // White fill - will be tinted if (m.sight === "Mono") { const center = { x: 0, y: ly } drawEye(pg, center, rx, ry, m.sight, 0) } else if (m.sight === "Verge") { drawVerticalAlmondTotal(pg, rx, ry, ly, m.w, 0) } else { drawEye(pg, left, rx, ry, m.sight, 0) drawEye(pg, right, rx, ry, m.sight, 0) } pg.pop() } function getOmniaColor() { const cycleSpeed = 0.08 const palette = PARAMS.palette const complementaryHues = palette.map(c => { const col = color(c) const h = hue(col) return (h + 180) % 360 }) const cyclePosition = (millis() * cycleSpeed) % (complementaryHues.length * 100) const colorIndex = floor(cyclePosition / 100) % complementaryHues.length const nextIndex = (colorIndex + 1) % complementaryHues.length const blend = (cyclePosition % 100) / 100 const currentHue = lerp(complementaryHues[colorIndex], complementaryHues[nextIndex], blend) return color(currentHue, 100, 100) } function drawMaskSilhouette(pg, m) { pg.push() pg.translate(m.x, m.y) pg.rotate(PARAMS.axisLock ? 0 : m.rot) pg.noStroke() pg.fill(255) drawMaskShape(pg, m) drawOrnaments(pg, m) drawTusks(pg, m) drawEyes(pg, m) pg.push() pg.erase() carveMouth(pg, m) carveNose(pg, m) carveCutouts(pg, m) pg.noErase() pg.pop() pg.pop() } function drawMaskShape(pg, m) { const pts = silhouettePoints(m.w, m.h, m.edgeStyle) if (m.edgeStyle === "Curved") { pg.beginShape() const first = pts[0], last = pts[pts.length - 1] pg.curveVertex(last.x, last.y) for (const p of pts) pg.curveVertex(p.x, p.y) pg.curveVertex(first.x, first.y) pg.curveVertex(pts[1].x, pts[1].y) pg.endShape(CLOSE) } else { pg.beginShape() for (const p of pts) pg.vertex(p.x, p.y) pg.endShape(CLOSE) } } function stylizeEdge(p, style, snap) { if (style === "Faceted") { return { x: round(p.x / snap) * snap, y: round(p.y / snap) * snap } } if (style === "Straight") { const ax = abs(p.x) > abs(p.y) ? { x: p.x, y: round(p.y / snap) * snap } : { x: round(p.x / snap) * snap, y: p.y } return ax } return p } function silhouettePoints(w, h, edgeStyle) { const bw = w * 0.5, bh = h * 0.5 let base = [ { x: 0, y: -bh * 0.92 }, { x: bw * 0.45, y: -bh * 0.78 }, { x: bw * 0.68, y: -bh * 0.35 }, { x: bw * 0.72, y: bh * 0.05 }, { x: bw * 0.58, y: bh * 0.55 }, { x: 0, y: bh * 0.72 }, { x: -bw * 0.58, y: bh * 0.55 }, { x: -bw * 0.72, y: bh * 0.05 }, { x: -bw * 0.68, y: -bh * 0.35 }, { x: -bw * 0.45, y: -bh * 0.78 }, ] const snap = min(w, h) * (edgeStyle === "Faceted" ? 0.05 : 0.035) base = base.map((p) => stylizeEdge(p, edgeStyle, snap)) return base } function drawTusks(pg, m) { if (m.voice !== "Downfall") return const y = m.h * 0.27 const tuskTopWidth = m.w * 0.12 const tuskTipWidth = m.w * 0.03 const tuskHeight = m.h * 0.25 const tuskSpacing = m.w * 0.18 pg.push() pg.fill(255) pg.noStroke() pg.push() pg.translate(-tuskSpacing, y) pg.beginShape() pg.vertex(-tuskTopWidth * 0.5, 0) pg.bezierVertex( -tuskTopWidth * 0.5, tuskHeight * 0.3, -tuskTipWidth * 0.8, tuskHeight * 0.7, -tuskTipWidth * 0.3, tuskHeight ) pg.vertex(0, tuskHeight * 0.95) pg.bezierVertex( tuskTipWidth * 0.3, tuskHeight * 0.7, tuskTopWidth * 0.3, tuskHeight * 0.3, tuskTopWidth * 0.5, 0 ) pg.endShape(CLOSE) pg.pop() pg.push() pg.translate(tuskSpacing, y) pg.beginShape() pg.vertex(-tuskTopWidth * 0.5, 0) pg.bezierVertex( -tuskTopWidth * 0.3, tuskHeight * 0.3, -tuskTipWidth * 0.3, tuskHeight * 0.7, 0, tuskHeight * 0.95 ) pg.vertex(tuskTipWidth * 0.3, tuskHeight) pg.bezierVertex( tuskTipWidth * 0.8, tuskHeight * 0.7, tuskTopWidth * 0.5, tuskHeight * 0.3, tuskTopWidth * 0.5, 0 ) pg.endShape(CLOSE) pg.pop() pg.pop() } function drawEyes(pg, m) { let eyeColor, strokeColor, strokeW; if (TRAITS.iris === "Null") { eyeColor = 255; strokeColor = 0; strokeW = m.w * 0.015; } else if (TRAITS.iris === "Abyss") { eyeColor = 0; strokeColor = 255; strokeW = m.w * 0.012; } else { eyeColor = 255; strokeColor = 0; strokeW = m.w * 0.012; } const rx = m.w * 0.22 const ry = m.h * 0.13 const ly = -m.h * 0.12 const left = { x: -m.w * 0.18, y: ly } const right = { x: m.w * 0.18, y: ly } pg.push() pg.noStroke() pg.fill(strokeColor) if (m.sight === "Mono") { const center = { x: 0, y: ly } drawEye(pg, center, rx, ry, m.sight, strokeW) } else if (m.sight === "Verge") { drawVerticalAlmondTotal(pg, rx, ry, ly, m.w, strokeW) } else { drawEye(pg, left, rx, ry, m.sight, strokeW) drawEye(pg, right, rx, ry, m.sight, strokeW) } pg.fill(eyeColor) if (m.sight === "Mono") { const center = { x: 0, y: ly } drawEye(pg, center, rx, ry, m.sight, 0) } else if (m.sight === "Verge") { drawVerticalAlmondTotal(pg, rx, ry, ly, m.w, 0) } else { drawEye(pg, left, rx, ry, m.sight, 0) drawEye(pg, right, rx, ry, m.sight, 0) } pg.pop() } function drawVerticalAlmondTotal(pg, rx, ry, ly, maskWidth, strokeW = 0) { const almondWidth = rx * 0.5 const almondHeight = ry * 1.8 const spacing = maskWidth * 0.15 const w = almondWidth + strokeW * 2 const h = almondHeight + strokeW * 2 for (let pos of [-spacing, 0, spacing]) { pg.push() pg.translate(pos, ly) const width = pos === 0 ? w * 1.1 : w const height = pos === 0 ? h : h pg.beginShape() pg.vertex(0, -height / 2) pg.bezierVertex( width * 0.5, -height * 0.3, width * 0.5, height * 0.3, 0, height / 2 ) pg.bezierVertex( -width * 0.5, height * 0.3, -width * 0.5, -height * 0.3, 0, -height / 2 ) pg.endShape(CLOSE) pg.pop() } } function drawEye(pg, c, rx, ry, type, strokeW = 0) { pg.push() pg.translate(c.x, c.y) pg.rectMode(CENTER) const hasPupil = type.includes("with Pupil") && TRAITS.count !== "Conflux" if (type === "Core") { pg.ellipse(0, 0, rx * 1.0 + strokeW * 2, ry * 2 + strokeW * 2) if (hasPupil && strokeW === 0) { pg.push() pg.fill(0, 0, 0) const pupilWidth = min(rx, ry) * 0.1 const pupilHeight = ry * 1.6 pg.ellipse(0, -ry * 0.25, pupilWidth, pupilHeight) pg.pop() } } else if (type === "Lune") { pg.push() const crescentRadius = ry * 0.7 + strokeW const cutoutRadius = ry * 0.95 const cutoutOffset = ry * 0.4 pg.beginShape() for (let a = 0; a <= PI; a += PI / 20) { pg.vertex(cos(a) * crescentRadius, sin(a) * crescentRadius - cutoutOffset) } for (let a = PI; a >= 0; a -= PI / 20) { pg.vertex(cos(a) * cutoutRadius, sin(a) * cutoutRadius - cutoutOffset) } pg.endShape(CLOSE) pg.pop() } else if (type === "Teardrop") { pg.push() const tearWidth = rx * 0.9 + strokeW const tearHeight = ry * 1.4 + strokeW const pointOffset = tearWidth * 0.7 const pointDir = c.x < 0 ? 1 : -1 pg.beginShape() pg.vertex(pointDir * pointOffset, 0) pg.bezierVertex( pointDir * pointOffset * 0.3, -tearHeight * 0.5, -pointDir * tearWidth * 0.3, -tearHeight * 0.6, -pointDir * tearWidth * 0.5, 0 ) pg.bezierVertex( -pointDir * tearWidth * 0.3, tearHeight * 0.6, pointDir * pointOffset * 0.3, tearHeight * 0.5, pointDir * pointOffset, 0 ) pg.endShape(CLOSE) pg.pop() } else if (type === "Mono") { const visorWidth = rx * 2.0 + strokeW * 2 const visorHeight = ry * 0.8 + strokeW * 2 const visorRadius = visorHeight * 0.4 pg.rect(0, 0, visorWidth, visorHeight, visorRadius) } else if (type === "Echo") { const ovalWidth = rx * 1.2 + strokeW * 2 const ovalHeight = ry * 0.35 + strokeW * 2 const gap = ry * 0.5 pg.ellipse(0, -gap, ovalWidth, ovalHeight) pg.ellipse(0, 0, ovalWidth * 1.1, ovalHeight) pg.ellipse(0, gap, ovalWidth, ovalHeight) } else if (type === "Slate") { const rectWidth = rx * 1.0 + strokeW * 2 const rectHeight = ry * 0.4 + strokeW * 2 const gap = ry * 0.9 const cornerRadius = rectHeight pg.rect(0, -gap, rectWidth, rectHeight, cornerRadius) pg.rect(0, 0, rectWidth * 1.0, rectHeight, rectHeight * 1.0) pg.rect(0, gap, rectWidth, rectHeight, rectHeight * 0.5) } else if (type === "Vert") { const segments = 5 const segWidth = rx * 0.33 + strokeW * 2 const totalHeight = ry * 1.6 const segHeight = totalHeight / segments + strokeW * 2 const gap = segHeight * 0.1 for (let i = 0; i < segments; i++) { const y = (i - (segments - 1) / 2) * (totalHeight / segments) pg.ellipse(0, y, segWidth, segHeight - gap) } } else if (type === "Signal") { const dashes = 3 const dashWidth = rx * 1.2 / dashes + strokeW * 2 const dashHeight = ry * 0.6 + strokeW * 2 const gap = dashWidth * 0.25 for (let i = 0; i < dashes; i++) { const x = (i - (dashes - 1) / 2) * (rx * 1.2 / dashes) pg.rect(x, 0, dashWidth - gap, dashHeight, dashHeight * 0.2) } } else if (type === "Pierce") { const dots = 1 const dotSize = min(rx, ry) * 0.75 + strokeW * 2 const spacing = rx * 0.5 for (let i = 0; i < dots; i++) { const x = (i - (dots - 1) / 2) * spacing pg.circle(x, 0, dotSize) } } else if (type === "Cross") { const crossWidth = rx * 0.3 + strokeW * 2 const crossHeight = ry * 1.6 + strokeW * 2 pg.rect(0, 0, crossWidth, crossHeight) pg.rect(0, 0, crossHeight * 0.6, crossWidth) } else if (type === "Cut") { const slitCount = 3 const slitWidth = rx * 0.7 + strokeW * 2 const slitHeight = ry * 0.2 + strokeW * 2 const gap = ry * 0.6 for (let i = 0; i < slitCount; i++) { const y = (i - (slitCount - 1) / 2) * gap pg.rect(0, y, slitWidth, slitHeight) } } else { pg.rect(0, 0, rx * 1.2 + strokeW * 2, ry * 0.4 + strokeW * 2, ry * 0.2) } pg.pop() } function carveMouth(pg, m) { const y = m.h * 0.22 if (TRAITS.count === "Conflux") { pg.push() const translateX = m.maskIndex === 0 ? m.w * 0.18 : -m.w * 0.18 pg.translate(translateX, 0) } pg.rectMode(CENTER) if (m.voice === "Still") { pg.rect(0, y, m.w * 0.35, m.h * 0.03) } else if (m.voice === "Prowl") { pg.ellipse(0, y, m.w * 0.09, m.h * 0.4) } else if (m.voice === "Forge") { pg.rect(0, y, m.w * 0.28, m.h * 0.06, m.h * 0.01) } else if (m.voice === "Sunder") { const segmentCount = 4 const totalWidth = m.w * 0.25 const segmentWidth = totalWidth / segmentCount const segmentHeight = m.h * 0.04 const gap = segmentWidth * 0.15 for (let i = 0; i < segmentCount; i++) { const x = (i - (segmentCount - 1) / 2) * segmentWidth pg.rect(x, y, segmentWidth - gap, segmentHeight, segmentHeight * 0.1) } } else if (m.voice === "Hollow") { pg.rect(0, y, m.w * 0.35, m.h * 0.02) } else if (m.voice === "Devour") { pg.beginShape() const points = 12 const width = m.w * 0.4 const height = m.h * 0.1 for (let i = 0; i <= points; i++) { const x = map(i, 0, points, -width / 2, width / 2) const yOffset = (i % 2 === 0) ? -height / 2 : height / 2 pg.vertex(x, y + yOffset) } pg.endShape() pg.strokeWeight(m.h * 0.01) pg.noFill() pg.beginShape() for (let i = 0; i <= points; i++) { const x = map(i, 0, points, -width / 2, width / 2) const yOffset = (i % 2 === 0) ? -height / 2 : height / 2 pg.vertex(x, y + yOffset) } pg.endShape() pg.noStroke() pg.fill(255) } else if (m.voice === "Viper") { const fangWidth = m.w * 0.06 const fangHeight = m.h * 0.08 const fangSpacing = m.w * 0.15 pg.push() pg.translate(-fangSpacing, y) pg.triangle(0, fangHeight, -fangWidth / 2, 0, fangWidth / 2, 0) pg.pop() pg.push() pg.translate(fangSpacing, y) pg.triangle(0, fangHeight, -fangWidth / 2, 0, fangWidth / 2, 0) pg.pop() } else if (m.voice === "Bind") { const mouthWidth = m.w * 0.35 const mouthHeight = m.h * 0.015 pg.rect(0, y, mouthWidth, mouthHeight) const stitchCount = 6 const stitchHeight = m.h * 0.03 const stitchWidth = m.w * 0.01 for (let i = 0; i < stitchCount; i++) { const x = (i - (stitchCount - 1) / 2) * (mouthWidth / (stitchCount - 1)) pg.rect(x, y, stitchWidth, stitchHeight) } } else if (m.voice === "Downfall") { pg.rect(0, y, m.w * 0.25, m.h * 0.015) } else if (m.voice === "Stun") { const mouthWidth = m.h * 0.12 const mouthHeight = m.h * 0.06 pg.push() pg.translate(0, y + mouthHeight) pg.beginShape() for (let a = PI; a <= TWO_PI; a += PI / 20) { const x = cos(a) * mouthWidth / 2 const yOffset = sin(a) * mouthHeight pg.vertex(x, yOffset) } pg.vertex(mouthWidth / 2, 0) pg.vertex(-mouthWidth / 2, 0) pg.endShape(CLOSE) pg.pop() } else if (m.voice === "Grate") { const barCount = 4 const barWidth = m.w * 0.3 const barHeight = m.h * 0.03 const spacing = m.h * 0.04 for (let i = 0; i < barCount; i++) { const barY = y + (i - (barCount - 1) / 2) * spacing pg.rect(0, barY, barWidth, barHeight) } } else if (m.voice === "Ease") { pg.push() pg.translate(0, y) const waveWidth = m.w * 0.4 const waveHeight = m.h * 0.025 pg.beginShape() const steps = 30 for (let i = 0; i <= steps; i++) { const t = i / steps const x = map(t, 0, 1, -waveWidth / 2, waveWidth / 2) const waveY = sin(t * PI * 3) * waveHeight pg.vertex(x, waveY) } for (let i = steps; i >= 0; i--) { const t = i / steps const x = map(t, 0, 1, -waveWidth / 2, waveWidth / 2) const waveY = sin(t * PI * 3) * waveHeight + m.h * 0.015 pg.vertex(x, waveY) } pg.endShape(CLOSE) pg.pop() } else { pg.rect(0, y, m.w * 0.45, m.h * 0.018) } if (TRAITS.count === "Conflux") { pg.pop() } } function carveNose(pg, m) { if (m.scent === "Sealed") return const y = m.h * 0.05 + 20 if (TRAITS.count === "Conflux") { pg.push() const translateX = m.maskIndex === 0 ? m.w * 0.18 : -m.w * 0.18 pg.translate(translateX, 0) } pg.rectMode(CENTER) if (m.scent === "Aero") { pg.rect(0, y, m.w * 0.05, m.h * 0.07) } else if (m.scent === "Sego") { const segments = 3 const totalHeight = m.h * 0.12 const segHeight = totalHeight / segments const gap = segHeight * 0.25 for (let i = 0; i < segments; i++) { const segY = y + (i - (segments - 1) / 2) * segHeight pg.rect(0, segY, m.w * 0.05, segHeight - gap) } } else if (m.scent === "Duos") { const dotSize = m.w * 0.025 const spacing = m.w * 0.04 pg.circle(-spacing / 2, y, dotSize) pg.circle(spacing / 2, y, dotSize) } else if (m.scent === "Jewel") { pg.push() pg.translate(0, y) const size = m.w * 0.04 pg.quad(0, -size, size, 0, 0, size, -size, 0) pg.pop() } else if (m.scent === "Dot") { const dotSize = m.w * 0.03 pg.circle(0, y, dotSize) } else if (m.scent === "Aexo") { pg.push() pg.translate(0, y) pg.triangle(0, m.h * 0.04, -m.w * 0.03, -m.h * 0.04, m.w * 0.03, -m.h * 0.04) pg.pop() } else if (m.scent === "Tri") { const dotSize = m.w * 0.02 const spacing = m.h * 0.04 pg.circle(0, y - spacing, dotSize) pg.circle(0, y, dotSize) pg.circle(0, y + spacing, dotSize) } if (TRAITS.count === "Conflux") { pg.pop() } } function carveCutouts(pg, m) { if (m.hollows === "Whole") return if (m.hollows === "Cleave") { if (TRAITS.count === "Conflux") { const isLeftMask = m.x < width / 2 if (isLeftMask) { pg.ellipse(-m.w * 0.28, m.h * 0.08, m.w * 0.08, m.h * 0.08) } else { pg.ellipse(m.w * 0.28, m.h * 0.08, m.w * 0.08, m.h * 0.08) } } else { pg.ellipse(-m.w * 0.28, m.h * 0.08, m.w * 0.08, m.h * 0.08) pg.ellipse(m.w * 0.28, m.h * 0.08, m.w * 0.08, m.h * 0.08) } } else if (m.hollows === "Mark") { pg.ellipse(0, -m.h * 0.32, m.w * 0.08, m.h * 0.08) } else if (m.hollows === "Maw") { pg.rectMode(CENTER) const hollowX = m.w * 0.30 const hollowY = m.h * 0.18 const hollowWidth = m.w * 0.18 const hollowHeight = m.h * 0.28 if (TRAITS.count === "Conflux") { const isLeftMask = m.maskIndex === 0 if (isLeftMask) { pg.push