diff --git a/assets/gamedata/gootower/level-001.json b/assets/gamedata/gootower/level-001.json index bbf786b..6707c93 100644 --- a/assets/gamedata/gootower/level-001.json +++ b/assets/gamedata/gootower/level-001.json @@ -99,16 +99,6 @@ "y": 834, "type": "common" }, - { - "x": 1160, - "y": 834, - "type": "common" - }, - { - "x": 1190, - "y": 834, - "type": "common" - }, { "x": 980, "y": 804, @@ -140,13 +130,23 @@ "type": "common" }, { - "x": 1160, - "y": 804, + "x": 980, + "y": 774, "type": "common" }, { - "x": 1190, - "y": 804, + "x": 1010, + "y": 774, + "type": "common" + }, + { + "x": 1040, + "y": 774, + "type": "common" + }, + { + "x": 1070, + "y": 774, "type": "common" } ], diff --git a/assets/gamedata/gootower/level-007.json b/assets/gamedata/gootower/level-007.json index 4891a6f..2e04209 100644 --- a/assets/gamedata/gootower/level-007.json +++ b/assets/gamedata/gootower/level-007.json @@ -4,10 +4,9 @@ "h": 1000 }, "level": 7, - "name": "Anchors Aweigh", - "chapter": 2, - "sandbox": true, - "tip": "Brown anchor goo sticks straight to rock and needs no friends. Start a span from a wall.", + "name": "Uphill", + "chapter": 1, + "tip": "Brace as you go. An unbraced column leans, and once it leans it keeps leaning.", "terrain": [ { "kind": "solid", @@ -34,20 +33,20 @@ "kind": "solid", "poly": [ [ - 400, - 300 + -30, + 0 ], [ - 460, - 300 + 6, + 0 ], [ - 460, - 850 + 6, + 1000 ], [ - 400, - 850 + -30, + 1000 ] ] }, @@ -55,39 +54,39 @@ "kind": "solid", "poly": [ [ - 1120, - 300 + 1594, + 0 ], [ - 1180, - 300 + 1630, + 0 ], [ - 1180, - 850 + 1630, + 1000 ], [ - 1120, - 850 + 1594, + 1000 ] ] } ], "balls": [ { - "x": 749, + "x": 566, "y": 836, "type": "common", "pinned": true }, { - "x": 811, + "x": 628, "y": 836, "type": "common", "pinned": true }, { - "x": 780, + "x": 597, "y": 782, "type": "common" } @@ -106,143 +105,133 @@ 1 ] ], - "pipe": { - "x": 780, - "y": 400, - "r": 46 - }, "pile": [ { - "x": 860, + "x": 857, "y": 834, - "type": "anchor" + "type": "common" }, { - "x": 890, + "x": 887, "y": 834, - "type": "anchor" + "type": "common" }, { - "x": 920, + "x": 917, "y": 834, - "type": "anchor" + "type": "common" }, { - "x": 950, + "x": 947, "y": 834, - "type": "anchor" + "type": "common" }, { - "x": 980, + "x": 977, "y": 834, - "type": "anchor" + "type": "common" }, { - "x": 1010, + "x": 1007, "y": 834, - "type": "anchor" + "type": "common" }, { - "x": 860, + "x": 1037, + "y": 834, + "type": "common" + }, + { + "x": 1067, + "y": 834, + "type": "common" + }, + { + "x": 857, "y": 804, "type": "common" }, { - "x": 890, + "x": 887, "y": 804, "type": "common" }, { - "x": 920, + "x": 917, "y": 804, "type": "common" }, { - "x": 950, + "x": 947, "y": 804, "type": "common" }, { - "x": 980, + "x": 977, "y": 804, "type": "common" }, { - "x": 1010, + "x": 1007, "y": 804, "type": "common" }, { - "x": 860, + "x": 1037, + "y": 804, + "type": "common" + }, + { + "x": 1067, + "y": 804, + "type": "common" + }, + { + "x": 857, "y": 774, "type": "common" }, { - "x": 890, + "x": 887, "y": 774, "type": "common" }, { - "x": 920, + "x": 917, "y": 774, "type": "common" }, { - "x": 950, + "x": 947, "y": 774, "type": "common" }, { - "x": 980, + "x": 977, "y": 774, "type": "common" }, { - "x": 1010, + "x": 1007, "y": 774, "type": "common" }, { - "x": 860, - "y": 744, + "x": 1037, + "y": 774, "type": "common" }, { - "x": 890, - "y": 744, - "type": "common" - }, - { - "x": 920, - "y": 744, - "type": "common" - }, - { - "x": 950, - "y": 744, - "type": "common" - }, - { - "x": 980, - "y": 744, - "type": "common" - }, - { - "x": 1010, - "y": 744, - "type": "common" - }, - { - "x": 860, - "y": 714, - "type": "common" - }, - { - "x": 890, - "y": 714, + "x": 1067, + "y": 774, "type": "common" } ], - "required": 5, - "ocdTarget": 12 + "pipe": { + "x": 597, + "y": 553, + "r": 46 + }, + "required": 4, + "ocdTarget": 9 } diff --git a/assets/gamedata/gootower/level-008.json b/assets/gamedata/gootower/level-008.json index 1522a59..82acdbb 100644 --- a/assets/gamedata/gootower/level-008.json +++ b/assets/gamedata/gootower/level-008.json @@ -4,10 +4,9 @@ "h": 1000 }, "level": 8, - "name": "Sticking Point", - "chapter": 2, - "sandbox": true, - "tip": "Pokey goo grips rock. There is no ground here worth building from.", + "name": "Higher Ground", + "chapter": 1, + "tip": "Brace as you go. An unbraced column leans, and once it leans it keeps leaning.", "terrain": [ { "kind": "solid", @@ -34,20 +33,20 @@ "kind": "solid", "poly": [ [ - 240, - 200 + -30, + 0 ], [ - 320, - 200 + 6, + 0 ], [ - 320, - 760 + 6, + 1000 ], [ - 240, - 760 + -30, + 1000 ] ] }, @@ -55,40 +54,40 @@ "kind": "solid", "poly": [ [ - 1120, - 200 + 1594, + 0 ], [ - 1200, - 200 + 1630, + 0 ], [ - 1200, - 760 + 1630, + 1000 ], [ - 1120, - 760 + 1594, + 1000 ] ] } ], "balls": [ { - "x": 340, - "y": 560, - "type": "pokey", + "x": 808, + "y": 836, + "type": "common", "pinned": true }, { - "x": 340, - "y": 498, - "type": "pokey", + "x": 870, + "y": 836, + "type": "common", "pinned": true }, { - "x": 398, - "y": 530, + "x": 839, + "y": 782, "type": "common" } ], @@ -106,153 +105,133 @@ 1 ] ], - "pipe": { - "x": 1080, - "y": 430, - "r": 46 - }, "pile": [ { - "x": 620, + "x": 1099, "y": 834, - "type": "pokey" + "type": "common" }, { - "x": 650, + "x": 1129, "y": 834, - "type": "pokey" + "type": "common" }, { - "x": 680, + "x": 1159, "y": 834, - "type": "pokey" + "type": "common" }, { - "x": 710, + "x": 1189, "y": 834, - "type": "pokey" + "type": "common" }, { - "x": 740, + "x": 1219, "y": 834, - "type": "pokey" + "type": "common" }, { - "x": 770, + "x": 1249, "y": 834, - "type": "pokey" + "type": "common" }, { - "x": 620, + "x": 1279, + "y": 834, + "type": "common" + }, + { + "x": 1309, + "y": 834, + "type": "common" + }, + { + "x": 1099, "y": 804, "type": "common" }, { - "x": 650, + "x": 1129, "y": 804, "type": "common" }, { - "x": 680, + "x": 1159, "y": 804, "type": "common" }, { - "x": 710, + "x": 1189, "y": 804, "type": "common" }, { - "x": 740, + "x": 1219, "y": 804, "type": "common" }, { - "x": 770, + "x": 1249, "y": 804, "type": "common" }, { - "x": 800, + "x": 1279, "y": 804, "type": "common" }, { - "x": 830, + "x": 1309, "y": 804, "type": "common" }, { - "x": 620, + "x": 1099, "y": 774, "type": "common" }, { - "x": 650, + "x": 1129, "y": 774, "type": "common" }, { - "x": 680, + "x": 1159, "y": 774, "type": "common" }, { - "x": 710, + "x": 1189, "y": 774, "type": "common" }, { - "x": 740, + "x": 1219, "y": 774, "type": "common" }, { - "x": 770, + "x": 1249, "y": 774, "type": "common" }, { - "x": 800, + "x": 1279, "y": 774, "type": "common" }, { - "x": 830, + "x": 1309, "y": 774, "type": "common" - }, - { - "x": 620, - "y": 744, - "type": "common" - }, - { - "x": 650, - "y": 744, - "type": "common" - }, - { - "x": 680, - "y": 744, - "type": "common" - }, - { - "x": 710, - "y": 744, - "type": "common" - }, - { - "x": 740, - "y": 744, - "type": "common" - }, - { - "x": 770, - "y": 744, - "type": "common" } ], + "pipe": { + "x": 839, + "y": 505, + "r": 46 + }, "required": 5, - "ocdTarget": 12 + "ocdTarget": 10 } diff --git a/assets/gamedata/gootower/level-009.json b/assets/gamedata/gootower/level-009.json index b9e7025..57f3d8b 100644 --- a/assets/gamedata/gootower/level-009.json +++ b/assets/gamedata/gootower/level-009.json @@ -4,10 +4,9 @@ "h": 1000 }, "level": 9, - "name": "Demolition", - "chapter": 2, - "sandbox": true, - "tip": "Drop a bomb by the fire and the soft rock goes with it. Or take the long way over.", + "name": "The Long Climb", + "chapter": 1, + "tip": "Brace as you go. An unbraced column leans, and once it leans it keeps leaning.", "terrain": [ { "kind": "solid", @@ -34,61 +33,60 @@ "kind": "solid", "poly": [ [ - 700, - 660 + -30, + 0 ], [ - 780, - 660 + 6, + 0 ], [ - 780, - 850 + 6, + 1000 ], [ - 700, - 850 + -30, + 1000 ] - ], - "destructible": true + ] }, { - "kind": "fire", + "kind": "solid", "poly": [ [ - 600, - 806 + 1594, + 0 ], [ - 680, - 806 + 1630, + 0 ], [ - 680, - 850 + 1630, + 1000 ], [ - 600, - 850 + 1594, + 1000 ] ] } ], "balls": [ { - "x": 369, + "x": 722, "y": 836, "type": "common", "pinned": true }, { - "x": 431, + "x": 784, "y": 836, "type": "common", "pinned": true }, { - "x": 400, + "x": 753, "y": 782, "type": "common" } @@ -107,159 +105,133 @@ 1 ] ], - "pipe": { - "x": 980, - "y": 700, - "r": 46 - }, - "waypoints": [ - { - "x": 740, - "y": 590 - } - ], "pile": [ { - "x": 160, + "x": 1013, "y": 834, - "type": "bomb" + "type": "common" }, { - "x": 190, + "x": 1043, "y": 834, - "type": "bomb" + "type": "common" }, { - "x": 220, + "x": 1073, "y": 834, - "type": "bomb" + "type": "common" }, { - "x": 250, + "x": 1103, "y": 834, - "type": "bomb" + "type": "common" }, { - "x": 160, + "x": 1133, + "y": 834, + "type": "common" + }, + { + "x": 1163, + "y": 834, + "type": "common" + }, + { + "x": 1193, + "y": 834, + "type": "common" + }, + { + "x": 1223, + "y": 834, + "type": "common" + }, + { + "x": 1013, "y": 804, "type": "common" }, { - "x": 190, + "x": 1043, "y": 804, "type": "common" }, { - "x": 220, + "x": 1073, "y": 804, "type": "common" }, { - "x": 250, + "x": 1103, "y": 804, "type": "common" }, { - "x": 280, + "x": 1133, "y": 804, "type": "common" }, { - "x": 310, + "x": 1163, "y": 804, "type": "common" }, { - "x": 340, + "x": 1193, "y": 804, "type": "common" }, { - "x": 160, + "x": 1223, + "y": 804, + "type": "common" + }, + { + "x": 1013, "y": 774, "type": "common" }, { - "x": 190, + "x": 1043, "y": 774, "type": "common" }, { - "x": 220, + "x": 1073, "y": 774, "type": "common" }, { - "x": 250, + "x": 1103, "y": 774, "type": "common" }, { - "x": 280, + "x": 1133, "y": 774, "type": "common" }, { - "x": 310, + "x": 1163, "y": 774, "type": "common" }, { - "x": 340, + "x": 1193, "y": 774, "type": "common" }, { - "x": 160, - "y": 744, - "type": "common" - }, - { - "x": 190, - "y": 744, - "type": "common" - }, - { - "x": 220, - "y": 744, - "type": "common" - }, - { - "x": 250, - "y": 744, - "type": "common" - }, - { - "x": 280, - "y": 744, - "type": "common" - }, - { - "x": 310, - "y": 744, - "type": "common" - }, - { - "x": 340, - "y": 744, - "type": "common" - }, - { - "x": 160, - "y": 714, - "type": "common" - }, - { - "x": 190, - "y": 714, - "type": "common" - }, - { - "x": 220, - "y": 714, + "x": 1223, + "y": 774, "type": "common" } ], - "required": 5, + "pipe": { + "x": 753, + "y": 455, + "r": 46 + }, + "required": 6, "ocdTarget": 12 } diff --git a/assets/gamedata/gootower/level-010.json b/assets/gamedata/gootower/level-010.json index c33d8a0..4c0ea61 100644 --- a/assets/gamedata/gootower/level-010.json +++ b/assets/gamedata/gootower/level-010.json @@ -4,11 +4,52 @@ "h": 1000 }, "level": 10, - "name": "Updraft", - "chapter": 2, - "sandbox": true, - "tip": "The updraft takes weight off everything inside it. Spans reach further in the wind.", + "name": "Across", + "chapter": 1, + "tip": "Triangles carry weight across a gap. Long chains just sag into the spikes.", "terrain": [ + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + }, { "kind": "solid", "poly": [ @@ -17,11 +58,11 @@ 700 ], [ - 600, + 628, 700 ], [ - 600, + 628, 1000 ], [ @@ -34,7 +75,7 @@ "kind": "solid", "poly": [ [ - 940, + 828, 700 ], [ @@ -46,7 +87,7 @@ 1000 ], [ - 940, + 828, 1000 ] ] @@ -55,19 +96,19 @@ "kind": "spike", "poly": [ [ - 600, + 628, 930 ], [ - 940, + 828, 930 ], [ - 940, + 828, 1000 ], [ - 600, + 628, 1000 ] ] @@ -77,14 +118,14 @@ "poly": [ [ 0, - 620 + 610 ], [ - 40, - 620 + 44, + 610 ], [ - 40, + 44, 700 ], [ @@ -92,34 +133,44 @@ 700 ] ] - } - ], - "fans": [ + }, { - "x": 600, - "y": 300, - "w": 340, - "h": 630, - "dx": 0, - "dy": -1, - "force": 1150 + "kind": "solid", + "poly": [ + [ + 584, + 610 + ], + [ + 628, + 610 + ], + [ + 628, + 700 + ], + [ + 584, + 700 + ] + ] } ], "balls": [ { - "x": 329, + "x": 407, "y": 686, "type": "common", "pinned": true }, { - "x": 391, + "x": 469, "y": 686, "type": "common", "pinned": true }, { - "x": 360, + "x": 438, "y": 632, "type": "common" } @@ -138,17 +189,17 @@ 1 ] ], - "pipe": { - "x": 1060, - "y": 630, - "r": 46 - }, "pile": [ { - "x": 120, + "x": 90, "y": 684, "type": "common" }, + { + "x": 120, + "y": 684, + "type": "ivy" + }, { "x": 150, "y": 684, @@ -157,7 +208,7 @@ { "x": 180, "y": 684, - "type": "common" + "type": "ivy" }, { "x": 210, @@ -167,17 +218,17 @@ { "x": 240, "y": 684, - "type": "common" + "type": "ivy" }, { - "x": 270, - "y": 684, + "x": 90, + "y": 654, "type": "common" }, { "x": 120, "y": 654, - "type": "common" + "type": "ivy" }, { "x": 150, @@ -187,7 +238,7 @@ { "x": 180, "y": 654, - "type": "common" + "type": "ivy" }, { "x": 210, @@ -197,17 +248,17 @@ { "x": 240, "y": 654, - "type": "common" + "type": "ivy" }, { - "x": 270, - "y": 654, + "x": 90, + "y": 624, "type": "common" }, { "x": 120, "y": 624, - "type": "common" + "type": "ivy" }, { "x": 150, @@ -217,7 +268,7 @@ { "x": 180, "y": 624, - "type": "common" + "type": "ivy" }, { "x": 210, @@ -227,17 +278,17 @@ { "x": 240, "y": 624, - "type": "common" + "type": "ivy" }, { - "x": 270, - "y": 624, + "x": 90, + "y": 594, "type": "common" }, { "x": 120, "y": 594, - "type": "common" + "type": "ivy" }, { "x": 150, @@ -260,8 +311,8 @@ "type": "common" }, { - "x": 270, - "y": 594, + "x": 90, + "y": 564, "type": "common" }, { @@ -273,8 +324,24 @@ "x": 150, "y": 564, "type": "common" + }, + { + "x": 180, + "y": 564, + "type": "common" + } + ], + "pipe": { + "x": 938, + "y": 640, + "r": 46 + }, + "waypoints": [ + { + "x": 728, + "y": 605 } ], "required": 4, - "ocdTarget": 12 + "ocdTarget": 8 } diff --git a/assets/gamedata/gootower/level-011.json b/assets/gamedata/gootower/level-011.json index a7ad9e0..198d150 100644 --- a/assets/gamedata/gootower/level-011.json +++ b/assets/gamedata/gootower/level-011.json @@ -4,24 +4,65 @@ "h": 1000 }, "level": 11, - "name": "Cogs", - "chapter": 2, - "sandbox": true, - "tip": "The cog is solid and it is turning. Anything it touches gets dragged along.", + "name": "Wider Still", + "chapter": 1, + "tip": "Triangles carry weight across a gap. Long chains just sag into the spikes.", "terrain": [ + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + }, { "kind": "solid", "poly": [ [ 0, - 850 + 700 ], [ - 1600, - 850 + 638, + 700 ], [ - 1600, + 638, 1000 ], [ @@ -29,33 +70,108 @@ 1000 ] ] - } - ], - "gears": [ + }, { - "x": 800, - "y": 470, - "r": 110, - "teeth": 9, - "omega": 1.4 + "kind": "solid", + "poly": [ + [ + 869, + 700 + ], + [ + 1600, + 700 + ], + [ + 1600, + 1000 + ], + [ + 869, + 1000 + ] + ] + }, + { + "kind": "spike", + "poly": [ + [ + 638, + 930 + ], + [ + 869, + 930 + ], + [ + 869, + 1000 + ], + [ + 638, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 0, + 610 + ], + [ + 44, + 610 + ], + [ + 44, + 700 + ], + [ + 0, + 700 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 594, + 610 + ], + [ + 638, + 610 + ], + [ + 638, + 700 + ], + [ + 594, + 700 + ] + ] } ], "balls": [ { - "x": 269, - "y": 836, + "x": 417, + "y": 686, "type": "common", "pinned": true }, { - "x": 331, - "y": 836, + "x": 479, + "y": 686, "type": "common", "pinned": true }, { - "x": 300, - "y": 782, + "x": 448, + "y": 632, "type": "common" } ], @@ -73,153 +189,159 @@ 1 ] ], - "pipe": { - "x": 1240, - "y": 560, - "r": 46 - }, "pile": [ { - "x": 1000, - "y": 834, + "x": 90, + "y": 684, "type": "common" }, { - "x": 1030, - "y": 834, + "x": 120, + "y": 684, + "type": "ivy" + }, + { + "x": 150, + "y": 684, "type": "common" }, { - "x": 1060, - "y": 834, + "x": 180, + "y": 684, + "type": "ivy" + }, + { + "x": 210, + "y": 684, "type": "common" }, { - "x": 1090, - "y": 834, + "x": 240, + "y": 684, + "type": "ivy" + }, + { + "x": 90, + "y": 654, "type": "common" }, { - "x": 1120, - "y": 834, + "x": 120, + "y": 654, + "type": "ivy" + }, + { + "x": 150, + "y": 654, "type": "common" }, { - "x": 1150, - "y": 834, + "x": 180, + "y": 654, + "type": "ivy" + }, + { + "x": 210, + "y": 654, "type": "common" }, { - "x": 1180, - "y": 834, + "x": 240, + "y": 654, + "type": "ivy" + }, + { + "x": 90, + "y": 624, "type": "common" }, { - "x": 1210, - "y": 834, + "x": 120, + "y": 624, + "type": "ivy" + }, + { + "x": 150, + "y": 624, "type": "common" }, { - "x": 1240, - "y": 834, + "x": 180, + "y": 624, + "type": "ivy" + }, + { + "x": 210, + "y": 624, "type": "common" }, { - "x": 1000, - "y": 804, + "x": 240, + "y": 624, + "type": "ivy" + }, + { + "x": 90, + "y": 594, "type": "common" }, { - "x": 1030, - "y": 804, + "x": 120, + "y": 594, + "type": "ivy" + }, + { + "x": 150, + "y": 594, "type": "common" }, { - "x": 1060, - "y": 804, + "x": 180, + "y": 594, "type": "common" }, { - "x": 1090, - "y": 804, + "x": 210, + "y": 594, "type": "common" }, { - "x": 1120, - "y": 804, + "x": 240, + "y": 594, "type": "common" }, { - "x": 1150, - "y": 804, + "x": 90, + "y": 564, "type": "common" }, { - "x": 1180, - "y": 804, + "x": 120, + "y": 564, "type": "common" }, { - "x": 1210, - "y": 804, + "x": 150, + "y": 564, "type": "common" }, { - "x": 1240, - "y": 804, - "type": "common" - }, - { - "x": 1000, - "y": 774, - "type": "common" - }, - { - "x": 1030, - "y": 774, - "type": "common" - }, - { - "x": 1060, - "y": 774, - "type": "common" - }, - { - "x": 1090, - "y": 774, - "type": "common" - }, - { - "x": 1120, - "y": 774, - "type": "common" - }, - { - "x": 1150, - "y": 774, - "type": "common" - }, - { - "x": 1180, - "y": 774, - "type": "common" - }, - { - "x": 1210, - "y": 774, - "type": "common" - }, - { - "x": 1240, - "y": 774, - "type": "common" - }, - { - "x": 1000, - "y": 744, + "x": 180, + "y": 564, "type": "common" } ], + "pipe": { + "x": 979, + "y": 640, + "r": 46 + }, + "waypoints": [ + { + "x": 753.5, + "y": 605 + } + ], "required": 5, - "ocdTarget": 13 + "ocdTarget": 10 } diff --git a/assets/gamedata/gootower/level-012.json b/assets/gamedata/gootower/level-012.json index e878e51..17bfff0 100644 --- a/assets/gamedata/gootower/level-012.json +++ b/assets/gamedata/gootower/level-012.json @@ -4,24 +4,65 @@ "h": 1000 }, "level": 12, - "name": "Lighter Than Air", - "chapter": 2, - "sandbox": true, - "tip": "Balloons pull up, blocks hold rigid, bits are cheap and weak. Mix them.", + "name": "The Drop", + "chapter": 1, + "tip": "Triangles carry weight across a gap. Long chains just sag into the spikes.", "terrain": [ + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + }, { "kind": "solid", "poly": [ [ 0, - 850 + 700 ], [ - 1600, - 850 + 582, + 700 ], [ - 1600, + 582, 1000 ], [ @@ -29,24 +70,108 @@ 1000 ] ] + }, + { + "kind": "solid", + "poly": [ + [ + 828, + 700 + ], + [ + 1600, + 700 + ], + [ + 1600, + 1000 + ], + [ + 828, + 1000 + ] + ] + }, + { + "kind": "spike", + "poly": [ + [ + 582, + 930 + ], + [ + 828, + 930 + ], + [ + 828, + 1000 + ], + [ + 582, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 0, + 610 + ], + [ + 44, + 610 + ], + [ + 44, + 700 + ], + [ + 0, + 700 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 538, + 610 + ], + [ + 582, + 610 + ], + [ + 582, + 700 + ], + [ + 538, + 700 + ] + ] } ], "balls": [ { - "x": 369, - "y": 836, + "x": 361, + "y": 686, "type": "common", "pinned": true }, { - "x": 431, - "y": 836, + "x": 423, + "y": 686, "type": "common", "pinned": true }, { - "x": 400, - "y": 782, + "x": 392, + "y": 632, "type": "common" } ], @@ -64,203 +189,159 @@ 1 ] ], - "pipe": { - "x": 400, - "y": 300, - "r": 46 - }, "pile": [ { - "x": 700, - "y": 834, - "type": "balloon" - }, - { - "x": 730, - "y": 834, - "type": "balloon" - }, - { - "x": 760, - "y": 834, - "type": "balloon" - }, - { - "x": 790, - "y": 834, - "type": "balloon" - }, - { - "x": 820, - "y": 834, - "type": "balloon" - }, - { - "x": 850, - "y": 834, - "type": "balloon" - }, - { - "x": 700, - "y": 800, - "type": "block" - }, - { - "x": 730, - "y": 800, - "type": "block" - }, - { - "x": 760, - "y": 800, - "type": "block" - }, - { - "x": 790, - "y": 800, - "type": "block" - }, - { - "x": 820, - "y": 800, - "type": "block" - }, - { - "x": 850, - "y": 800, - "type": "block" - }, - { - "x": 880, - "y": 800, - "type": "block" - }, - { - "x": 910, - "y": 800, - "type": "block" - }, - { - "x": 700, - "y": 766, - "type": "bit" - }, - { - "x": 730, - "y": 766, - "type": "bit" - }, - { - "x": 760, - "y": 766, - "type": "bit" - }, - { - "x": 790, - "y": 766, - "type": "bit" - }, - { - "x": 820, - "y": 766, - "type": "bit" - }, - { - "x": 850, - "y": 766, - "type": "bit" - }, - { - "x": 700, - "y": 734, + "x": 90, + "y": 684, "type": "common" }, { - "x": 730, - "y": 734, + "x": 120, + "y": 684, + "type": "ivy" + }, + { + "x": 150, + "y": 684, "type": "common" }, { - "x": 760, - "y": 734, + "x": 180, + "y": 684, + "type": "ivy" + }, + { + "x": 210, + "y": 684, "type": "common" }, { - "x": 790, - "y": 734, + "x": 240, + "y": 684, + "type": "ivy" + }, + { + "x": 90, + "y": 654, "type": "common" }, { - "x": 820, - "y": 734, + "x": 120, + "y": 654, + "type": "ivy" + }, + { + "x": 150, + "y": 654, "type": "common" }, { - "x": 850, - "y": 734, + "x": 180, + "y": 654, + "type": "ivy" + }, + { + "x": 210, + "y": 654, "type": "common" }, { - "x": 880, - "y": 734, + "x": 240, + "y": 654, + "type": "ivy" + }, + { + "x": 90, + "y": 624, "type": "common" }, { - "x": 910, - "y": 734, + "x": 120, + "y": 624, + "type": "ivy" + }, + { + "x": 150, + "y": 624, "type": "common" }, { - "x": 940, - "y": 734, + "x": 180, + "y": 624, + "type": "ivy" + }, + { + "x": 210, + "y": 624, "type": "common" }, { - "x": 700, - "y": 704, + "x": 240, + "y": 624, + "type": "ivy" + }, + { + "x": 90, + "y": 594, "type": "common" }, { - "x": 730, - "y": 704, + "x": 120, + "y": 594, + "type": "ivy" + }, + { + "x": 150, + "y": 594, "type": "common" }, { - "x": 760, - "y": 704, + "x": 180, + "y": 594, "type": "common" }, { - "x": 790, - "y": 704, + "x": 210, + "y": 594, "type": "common" }, { - "x": 820, - "y": 704, + "x": 240, + "y": 594, "type": "common" }, { - "x": 850, - "y": 704, + "x": 90, + "y": 564, "type": "common" }, { - "x": 880, - "y": 704, + "x": 120, + "y": 564, "type": "common" }, { - "x": 910, - "y": 704, + "x": 150, + "y": 564, "type": "common" }, { - "x": 940, - "y": 704, + "x": 180, + "y": 564, "type": "common" } ], - "required": 5, + "pipe": { + "x": 938, + "y": 640, + "r": 46 + }, + "waypoints": [ + { + "x": 705, + "y": 605 + } + ], + "required": 6, "ocdTarget": 12 } diff --git a/assets/gamedata/gootower/level-013.json b/assets/gamedata/gootower/level-013.json new file mode 100644 index 0000000..baa2d56 --- /dev/null +++ b/assets/gamedata/gootower/level-013.json @@ -0,0 +1,284 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 13, + "name": "Under It", + "chapter": 1, + "tip": "You cannot build through rock. Come out from under it first.", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + 0, + 850 + ], + [ + 1600, + 850 + ], + [ + 1600, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 260, + 607 + ], + [ + 759, + 607 + ], + [ + 759, + 677 + ], + [ + 260, + 677 + ] + ] + } + ], + "balls": [ + { + "x": 547, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 609, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 578, + "y": 782, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 879, + "y": 834, + "type": "common" + }, + { + "x": 909, + "y": 834, + "type": "ivy" + }, + { + "x": 939, + "y": 834, + "type": "common" + }, + { + "x": 969, + "y": 834, + "type": "ivy" + }, + { + "x": 999, + "y": 834, + "type": "common" + }, + { + "x": 1029, + "y": 834, + "type": "ivy" + }, + { + "x": 1059, + "y": 834, + "type": "common" + }, + { + "x": 1089, + "y": 834, + "type": "ivy" + }, + { + "x": 1119, + "y": 834, + "type": "common" + }, + { + "x": 879, + "y": 804, + "type": "ivy" + }, + { + "x": 909, + "y": 804, + "type": "common" + }, + { + "x": 939, + "y": 804, + "type": "ivy" + }, + { + "x": 969, + "y": 804, + "type": "common" + }, + { + "x": 999, + "y": 804, + "type": "ivy" + }, + { + "x": 1029, + "y": 804, + "type": "common" + }, + { + "x": 1059, + "y": 804, + "type": "ivy" + }, + { + "x": 1089, + "y": 804, + "type": "common" + }, + { + "x": 1119, + "y": 804, + "type": "ivy" + }, + { + "x": 879, + "y": 774, + "type": "common" + }, + { + "x": 909, + "y": 774, + "type": "ivy" + }, + { + "x": 939, + "y": 774, + "type": "common" + }, + { + "x": 969, + "y": 774, + "type": "common" + }, + { + "x": 999, + "y": 774, + "type": "common" + }, + { + "x": 1029, + "y": 774, + "type": "common" + }, + { + "x": 1059, + "y": 774, + "type": "common" + }, + { + "x": 1089, + "y": 774, + "type": "common" + }, + { + "x": 1119, + "y": 774, + "type": "common" + }, + { + "x": 879, + "y": 744, + "type": "common" + } + ], + "pipe": { + "x": 909, + "y": 547, + "r": 46 + }, + "waypoints": [ + { + "x": 799, + "y": 627 + } + ], + "required": 5, + "ocdTarget": 10 +} diff --git a/assets/gamedata/gootower/level-014.json b/assets/gamedata/gootower/level-014.json new file mode 100644 index 0000000..d2c0af8 --- /dev/null +++ b/assets/gamedata/gootower/level-014.json @@ -0,0 +1,284 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 14, + "name": "Round the Back", + "chapter": 1, + "tip": "You cannot build through rock. Come out from under it first.", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + 0, + 850 + ], + [ + 1600, + 850 + ], + [ + 1600, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 260, + 602 + ], + [ + 767, + 602 + ], + [ + 767, + 672 + ], + [ + 260, + 672 + ] + ] + } + ], + "balls": [ + { + "x": 520, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 582, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 551, + "y": 782, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 887, + "y": 834, + "type": "common" + }, + { + "x": 917, + "y": 834, + "type": "ivy" + }, + { + "x": 947, + "y": 834, + "type": "common" + }, + { + "x": 977, + "y": 834, + "type": "ivy" + }, + { + "x": 1007, + "y": 834, + "type": "common" + }, + { + "x": 1037, + "y": 834, + "type": "ivy" + }, + { + "x": 1067, + "y": 834, + "type": "common" + }, + { + "x": 1097, + "y": 834, + "type": "ivy" + }, + { + "x": 1127, + "y": 834, + "type": "common" + }, + { + "x": 887, + "y": 804, + "type": "ivy" + }, + { + "x": 917, + "y": 804, + "type": "common" + }, + { + "x": 947, + "y": 804, + "type": "ivy" + }, + { + "x": 977, + "y": 804, + "type": "common" + }, + { + "x": 1007, + "y": 804, + "type": "ivy" + }, + { + "x": 1037, + "y": 804, + "type": "common" + }, + { + "x": 1067, + "y": 804, + "type": "ivy" + }, + { + "x": 1097, + "y": 804, + "type": "common" + }, + { + "x": 1127, + "y": 804, + "type": "ivy" + }, + { + "x": 887, + "y": 774, + "type": "common" + }, + { + "x": 917, + "y": 774, + "type": "ivy" + }, + { + "x": 947, + "y": 774, + "type": "common" + }, + { + "x": 977, + "y": 774, + "type": "common" + }, + { + "x": 1007, + "y": 774, + "type": "common" + }, + { + "x": 1037, + "y": 774, + "type": "common" + }, + { + "x": 1067, + "y": 774, + "type": "common" + }, + { + "x": 1097, + "y": 774, + "type": "common" + }, + { + "x": 1127, + "y": 774, + "type": "common" + }, + { + "x": 887, + "y": 744, + "type": "common" + } + ], + "pipe": { + "x": 917, + "y": 542, + "r": 46 + }, + "waypoints": [ + { + "x": 807, + "y": 622 + } + ], + "required": 5, + "ocdTarget": 10 +} diff --git a/assets/gamedata/gootower/level-015.json b/assets/gamedata/gootower/level-015.json new file mode 100644 index 0000000..25dc1a0 --- /dev/null +++ b/assets/gamedata/gootower/level-015.json @@ -0,0 +1,284 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 15, + "name": "Out and Up", + "chapter": 1, + "tip": "You cannot build through rock. Come out from under it first.", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + 0, + 850 + ], + [ + 1600, + 850 + ], + [ + 1600, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 260, + 580 + ], + [ + 800, + 580 + ], + [ + 800, + 650 + ], + [ + 260, + 650 + ] + ] + } + ], + "balls": [ + { + "x": 561, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 623, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 592, + "y": 782, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 920, + "y": 834, + "type": "common" + }, + { + "x": 950, + "y": 834, + "type": "ivy" + }, + { + "x": 980, + "y": 834, + "type": "common" + }, + { + "x": 1010, + "y": 834, + "type": "ivy" + }, + { + "x": 1040, + "y": 834, + "type": "common" + }, + { + "x": 1070, + "y": 834, + "type": "ivy" + }, + { + "x": 1100, + "y": 834, + "type": "common" + }, + { + "x": 1130, + "y": 834, + "type": "ivy" + }, + { + "x": 1160, + "y": 834, + "type": "common" + }, + { + "x": 920, + "y": 804, + "type": "ivy" + }, + { + "x": 950, + "y": 804, + "type": "common" + }, + { + "x": 980, + "y": 804, + "type": "ivy" + }, + { + "x": 1010, + "y": 804, + "type": "common" + }, + { + "x": 1040, + "y": 804, + "type": "ivy" + }, + { + "x": 1070, + "y": 804, + "type": "common" + }, + { + "x": 1100, + "y": 804, + "type": "ivy" + }, + { + "x": 1130, + "y": 804, + "type": "common" + }, + { + "x": 1160, + "y": 804, + "type": "ivy" + }, + { + "x": 920, + "y": 774, + "type": "common" + }, + { + "x": 950, + "y": 774, + "type": "ivy" + }, + { + "x": 980, + "y": 774, + "type": "common" + }, + { + "x": 1010, + "y": 774, + "type": "common" + }, + { + "x": 1040, + "y": 774, + "type": "common" + }, + { + "x": 1070, + "y": 774, + "type": "common" + }, + { + "x": 1100, + "y": 774, + "type": "common" + }, + { + "x": 1130, + "y": 774, + "type": "common" + }, + { + "x": 1160, + "y": 774, + "type": "common" + }, + { + "x": 920, + "y": 744, + "type": "common" + } + ], + "pipe": { + "x": 950, + "y": 520, + "r": 46 + }, + "waypoints": [ + { + "x": 840, + "y": 600 + } + ], + "required": 6, + "ocdTarget": 13 +} diff --git a/assets/gamedata/gootower/level-016.json b/assets/gamedata/gootower/level-016.json new file mode 100644 index 0000000..174ca9e --- /dev/null +++ b/assets/gamedata/gootower/level-016.json @@ -0,0 +1,247 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 16, + "name": "Light Head", + "chapter": 2, + "tip": "Brace as you go. An unbraced column leans, and once it leans it keeps leaning.", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + 0, + 850 + ], + [ + 1600, + 850 + ], + [ + 1600, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + } + ], + "balls": [ + { + "x": 796, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 858, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 827, + "y": 782, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 1087, + "y": 834, + "type": "common" + }, + { + "x": 1117, + "y": 834, + "type": "balloon" + }, + { + "x": 1147, + "y": 834, + "type": "common" + }, + { + "x": 1177, + "y": 834, + "type": "balloon" + }, + { + "x": 1207, + "y": 834, + "type": "common" + }, + { + "x": 1237, + "y": 834, + "type": "balloon" + }, + { + "x": 1267, + "y": 834, + "type": "common" + }, + { + "x": 1297, + "y": 834, + "type": "balloon" + }, + { + "x": 1327, + "y": 834, + "type": "common" + }, + { + "x": 1087, + "y": 804, + "type": "balloon" + }, + { + "x": 1117, + "y": 804, + "type": "common" + }, + { + "x": 1147, + "y": 804, + "type": "balloon" + }, + { + "x": 1177, + "y": 804, + "type": "common" + }, + { + "x": 1207, + "y": 804, + "type": "common" + }, + { + "x": 1237, + "y": 804, + "type": "common" + }, + { + "x": 1267, + "y": 804, + "type": "common" + }, + { + "x": 1297, + "y": 804, + "type": "common" + }, + { + "x": 1327, + "y": 804, + "type": "common" + }, + { + "x": 1087, + "y": 774, + "type": "common" + }, + { + "x": 1117, + "y": 774, + "type": "common" + }, + { + "x": 1147, + "y": 774, + "type": "common" + }, + { + "x": 1177, + "y": 774, + "type": "common" + }, + { + "x": 1207, + "y": 774, + "type": "common" + }, + { + "x": 1237, + "y": 774, + "type": "common" + }, + { + "x": 1267, + "y": 774, + "type": "common" + }, + { + "x": 1297, + "y": 774, + "type": "common" + } + ], + "pipe": { + "x": 827, + "y": 472, + "r": 46 + }, + "required": 6, + "ocdTarget": 12 +} diff --git a/assets/gamedata/gootower/level-017.json b/assets/gamedata/gootower/level-017.json new file mode 100644 index 0000000..01d4752 --- /dev/null +++ b/assets/gamedata/gootower/level-017.json @@ -0,0 +1,247 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 17, + "name": "Buoyant", + "chapter": 2, + "tip": "Brace as you go. An unbraced column leans, and once it leans it keeps leaning.", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + 0, + 850 + ], + [ + 1600, + 850 + ], + [ + 1600, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + } + ], + "balls": [ + { + "x": 669, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 731, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 700, + "y": 782, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 960, + "y": 834, + "type": "common" + }, + { + "x": 990, + "y": 834, + "type": "balloon" + }, + { + "x": 1020, + "y": 834, + "type": "common" + }, + { + "x": 1050, + "y": 834, + "type": "balloon" + }, + { + "x": 1080, + "y": 834, + "type": "common" + }, + { + "x": 1110, + "y": 834, + "type": "balloon" + }, + { + "x": 1140, + "y": 834, + "type": "common" + }, + { + "x": 1170, + "y": 834, + "type": "balloon" + }, + { + "x": 1200, + "y": 834, + "type": "common" + }, + { + "x": 960, + "y": 804, + "type": "balloon" + }, + { + "x": 990, + "y": 804, + "type": "common" + }, + { + "x": 1020, + "y": 804, + "type": "balloon" + }, + { + "x": 1050, + "y": 804, + "type": "common" + }, + { + "x": 1080, + "y": 804, + "type": "common" + }, + { + "x": 1110, + "y": 804, + "type": "common" + }, + { + "x": 1140, + "y": 804, + "type": "common" + }, + { + "x": 1170, + "y": 804, + "type": "common" + }, + { + "x": 1200, + "y": 804, + "type": "common" + }, + { + "x": 960, + "y": 774, + "type": "common" + }, + { + "x": 990, + "y": 774, + "type": "common" + }, + { + "x": 1020, + "y": 774, + "type": "common" + }, + { + "x": 1050, + "y": 774, + "type": "common" + }, + { + "x": 1080, + "y": 774, + "type": "common" + }, + { + "x": 1110, + "y": 774, + "type": "common" + }, + { + "x": 1140, + "y": 774, + "type": "common" + }, + { + "x": 1170, + "y": 774, + "type": "common" + } + ], + "pipe": { + "x": 700, + "y": 448, + "r": 46 + }, + "required": 6, + "ocdTarget": 12 +} diff --git a/assets/gamedata/gootower/level-018.json b/assets/gamedata/gootower/level-018.json new file mode 100644 index 0000000..7b9e006 --- /dev/null +++ b/assets/gamedata/gootower/level-018.json @@ -0,0 +1,268 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 18, + "name": "Low Ceiling", + "chapter": 2, + "tip": "The ceiling bites. Stop short of it.", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + 0, + 850 + ], + [ + 1600, + 850 + ], + [ + 1600, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + }, + { + "kind": "spike", + "poly": [ + [ + 112, + 323 + ], + [ + 952, + 323 + ], + [ + 952, + 383 + ], + [ + 112, + 383 + ] + ] + } + ], + "balls": [ + { + "x": 501, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 563, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 532, + "y": 782, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 812, + "y": 834, + "type": "common" + }, + { + "x": 842, + "y": 834, + "type": "balloon" + }, + { + "x": 872, + "y": 834, + "type": "common" + }, + { + "x": 902, + "y": 834, + "type": "balloon" + }, + { + "x": 932, + "y": 834, + "type": "common" + }, + { + "x": 962, + "y": 834, + "type": "balloon" + }, + { + "x": 992, + "y": 834, + "type": "common" + }, + { + "x": 1022, + "y": 834, + "type": "balloon" + }, + { + "x": 1052, + "y": 834, + "type": "common" + }, + { + "x": 812, + "y": 804, + "type": "balloon" + }, + { + "x": 842, + "y": 804, + "type": "common" + }, + { + "x": 872, + "y": 804, + "type": "balloon" + }, + { + "x": 902, + "y": 804, + "type": "common" + }, + { + "x": 932, + "y": 804, + "type": "common" + }, + { + "x": 962, + "y": 804, + "type": "common" + }, + { + "x": 992, + "y": 804, + "type": "common" + }, + { + "x": 1022, + "y": 804, + "type": "common" + }, + { + "x": 1052, + "y": 804, + "type": "common" + }, + { + "x": 812, + "y": 774, + "type": "common" + }, + { + "x": 842, + "y": 774, + "type": "common" + }, + { + "x": 872, + "y": 774, + "type": "common" + }, + { + "x": 902, + "y": 774, + "type": "common" + }, + { + "x": 932, + "y": 774, + "type": "common" + }, + { + "x": 962, + "y": 774, + "type": "common" + }, + { + "x": 992, + "y": 774, + "type": "common" + }, + { + "x": 1022, + "y": 774, + "type": "common" + } + ], + "pipe": { + "x": 532, + "y": 488, + "r": 46 + }, + "required": 5, + "ocdTarget": 10 +} diff --git a/assets/gamedata/gootower/level-019.json b/assets/gamedata/gootower/level-019.json new file mode 100644 index 0000000..133135c --- /dev/null +++ b/assets/gamedata/gootower/level-019.json @@ -0,0 +1,268 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 19, + "name": "Mind Your Head", + "chapter": 2, + "tip": "The ceiling bites. Stop short of it.", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + 0, + 850 + ], + [ + 1600, + 850 + ], + [ + 1600, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + }, + { + "kind": "spike", + "poly": [ + [ + 186, + 298 + ], + [ + 1026, + 298 + ], + [ + 1026, + 358 + ], + [ + 186, + 358 + ] + ] + } + ], + "balls": [ + { + "x": 575, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 637, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 606, + "y": 782, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 886, + "y": 834, + "type": "common" + }, + { + "x": 916, + "y": 834, + "type": "balloon" + }, + { + "x": 946, + "y": 834, + "type": "common" + }, + { + "x": 976, + "y": 834, + "type": "balloon" + }, + { + "x": 1006, + "y": 834, + "type": "common" + }, + { + "x": 1036, + "y": 834, + "type": "balloon" + }, + { + "x": 1066, + "y": 834, + "type": "common" + }, + { + "x": 1096, + "y": 834, + "type": "balloon" + }, + { + "x": 1126, + "y": 834, + "type": "common" + }, + { + "x": 886, + "y": 804, + "type": "balloon" + }, + { + "x": 916, + "y": 804, + "type": "common" + }, + { + "x": 946, + "y": 804, + "type": "balloon" + }, + { + "x": 976, + "y": 804, + "type": "common" + }, + { + "x": 1006, + "y": 804, + "type": "common" + }, + { + "x": 1036, + "y": 804, + "type": "common" + }, + { + "x": 1066, + "y": 804, + "type": "common" + }, + { + "x": 1096, + "y": 804, + "type": "common" + }, + { + "x": 1126, + "y": 804, + "type": "common" + }, + { + "x": 886, + "y": 774, + "type": "common" + }, + { + "x": 916, + "y": 774, + "type": "common" + }, + { + "x": 946, + "y": 774, + "type": "common" + }, + { + "x": 976, + "y": 774, + "type": "common" + }, + { + "x": 1006, + "y": 774, + "type": "common" + }, + { + "x": 1036, + "y": 774, + "type": "common" + }, + { + "x": 1066, + "y": 774, + "type": "common" + }, + { + "x": 1096, + "y": 774, + "type": "common" + } + ], + "pipe": { + "x": 606, + "y": 463, + "r": 46 + }, + "required": 6, + "ocdTarget": 12 +} diff --git a/assets/gamedata/gootower/level-020.json b/assets/gamedata/gootower/level-020.json new file mode 100644 index 0000000..f5ced87 --- /dev/null +++ b/assets/gamedata/gootower/level-020.json @@ -0,0 +1,268 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 20, + "name": "Overhead", + "chapter": 2, + "tip": "The ceiling bites. Stop short of it.", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + 0, + 850 + ], + [ + 1600, + 850 + ], + [ + 1600, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + }, + { + "kind": "spike", + "poly": [ + [ + 306, + 282 + ], + [ + 1146, + 282 + ], + [ + 1146, + 342 + ], + [ + 306, + 342 + ] + ] + } + ], + "balls": [ + { + "x": 695, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 757, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 726, + "y": 782, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 1006, + "y": 834, + "type": "common" + }, + { + "x": 1036, + "y": 834, + "type": "balloon" + }, + { + "x": 1066, + "y": 834, + "type": "common" + }, + { + "x": 1096, + "y": 834, + "type": "balloon" + }, + { + "x": 1126, + "y": 834, + "type": "common" + }, + { + "x": 1156, + "y": 834, + "type": "balloon" + }, + { + "x": 1186, + "y": 834, + "type": "common" + }, + { + "x": 1216, + "y": 834, + "type": "balloon" + }, + { + "x": 1246, + "y": 834, + "type": "common" + }, + { + "x": 1006, + "y": 804, + "type": "balloon" + }, + { + "x": 1036, + "y": 804, + "type": "common" + }, + { + "x": 1066, + "y": 804, + "type": "balloon" + }, + { + "x": 1096, + "y": 804, + "type": "common" + }, + { + "x": 1126, + "y": 804, + "type": "common" + }, + { + "x": 1156, + "y": 804, + "type": "common" + }, + { + "x": 1186, + "y": 804, + "type": "common" + }, + { + "x": 1216, + "y": 804, + "type": "common" + }, + { + "x": 1246, + "y": 804, + "type": "common" + }, + { + "x": 1006, + "y": 774, + "type": "common" + }, + { + "x": 1036, + "y": 774, + "type": "common" + }, + { + "x": 1066, + "y": 774, + "type": "common" + }, + { + "x": 1096, + "y": 774, + "type": "common" + }, + { + "x": 1126, + "y": 774, + "type": "common" + }, + { + "x": 1156, + "y": 774, + "type": "common" + }, + { + "x": 1186, + "y": 774, + "type": "common" + }, + { + "x": 1216, + "y": 774, + "type": "common" + } + ], + "pipe": { + "x": 726, + "y": 447, + "r": 46 + }, + "required": 6, + "ocdTarget": 13 +} diff --git a/assets/gamedata/gootower/level-021.json b/assets/gamedata/gootower/level-021.json new file mode 100644 index 0000000..b4e7a3b --- /dev/null +++ b/assets/gamedata/gootower/level-021.json @@ -0,0 +1,272 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 21, + "name": "First Gust", + "chapter": 2, + "tip": "Brace as you go. An unbraced column leans, and once it leans it keeps leaning.", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + 0, + 850 + ], + [ + 1600, + 850 + ], + [ + 1600, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + } + ], + "balls": [ + { + "x": 455, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 517, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 486, + "y": 782, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 746, + "y": 834, + "type": "common" + }, + { + "x": 776, + "y": 834, + "type": "balloon" + }, + { + "x": 806, + "y": 834, + "type": "ivy" + }, + { + "x": 836, + "y": 834, + "type": "common" + }, + { + "x": 866, + "y": 834, + "type": "balloon" + }, + { + "x": 896, + "y": 834, + "type": "ivy" + }, + { + "x": 926, + "y": 834, + "type": "common" + }, + { + "x": 956, + "y": 834, + "type": "balloon" + }, + { + "x": 986, + "y": 834, + "type": "ivy" + }, + { + "x": 1016, + "y": 834, + "type": "common" + }, + { + "x": 746, + "y": 804, + "type": "balloon" + }, + { + "x": 776, + "y": 804, + "type": "ivy" + }, + { + "x": 806, + "y": 804, + "type": "common" + }, + { + "x": 836, + "y": 804, + "type": "balloon" + }, + { + "x": 866, + "y": 804, + "type": "common" + }, + { + "x": 896, + "y": 804, + "type": "common" + }, + { + "x": 926, + "y": 804, + "type": "common" + }, + { + "x": 956, + "y": 804, + "type": "common" + }, + { + "x": 986, + "y": 804, + "type": "common" + }, + { + "x": 1016, + "y": 804, + "type": "common" + }, + { + "x": 746, + "y": 774, + "type": "common" + }, + { + "x": 776, + "y": 774, + "type": "common" + }, + { + "x": 806, + "y": 774, + "type": "common" + }, + { + "x": 836, + "y": 774, + "type": "common" + }, + { + "x": 866, + "y": 774, + "type": "common" + }, + { + "x": 896, + "y": 774, + "type": "common" + }, + { + "x": 926, + "y": 774, + "type": "common" + }, + { + "x": 956, + "y": 774, + "type": "common" + }, + { + "x": 986, + "y": 774, + "type": "common" + }, + { + "x": 1016, + "y": 774, + "type": "common" + }, + { + "x": 746, + "y": 744, + "type": "common" + } + ], + "pipe": { + "x": 486, + "y": 552, + "r": 46 + }, + "required": 4, + "ocdTarget": 9 +} diff --git a/assets/gamedata/gootower/level-022.json b/assets/gamedata/gootower/level-022.json new file mode 100644 index 0000000..d544768 --- /dev/null +++ b/assets/gamedata/gootower/level-022.json @@ -0,0 +1,272 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 22, + "name": "Updraft", + "chapter": 2, + "tip": "Brace as you go. An unbraced column leans, and once it leans it keeps leaning.", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + 0, + 850 + ], + [ + 1600, + 850 + ], + [ + 1600, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + } + ], + "balls": [ + { + "x": 546, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 608, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 577, + "y": 782, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 837, + "y": 834, + "type": "common" + }, + { + "x": 867, + "y": 834, + "type": "balloon" + }, + { + "x": 897, + "y": 834, + "type": "ivy" + }, + { + "x": 927, + "y": 834, + "type": "common" + }, + { + "x": 957, + "y": 834, + "type": "balloon" + }, + { + "x": 987, + "y": 834, + "type": "ivy" + }, + { + "x": 1017, + "y": 834, + "type": "common" + }, + { + "x": 1047, + "y": 834, + "type": "balloon" + }, + { + "x": 1077, + "y": 834, + "type": "ivy" + }, + { + "x": 1107, + "y": 834, + "type": "common" + }, + { + "x": 837, + "y": 804, + "type": "balloon" + }, + { + "x": 867, + "y": 804, + "type": "ivy" + }, + { + "x": 897, + "y": 804, + "type": "common" + }, + { + "x": 927, + "y": 804, + "type": "balloon" + }, + { + "x": 957, + "y": 804, + "type": "common" + }, + { + "x": 987, + "y": 804, + "type": "common" + }, + { + "x": 1017, + "y": 804, + "type": "common" + }, + { + "x": 1047, + "y": 804, + "type": "common" + }, + { + "x": 1077, + "y": 804, + "type": "common" + }, + { + "x": 1107, + "y": 804, + "type": "common" + }, + { + "x": 837, + "y": 774, + "type": "common" + }, + { + "x": 867, + "y": 774, + "type": "common" + }, + { + "x": 897, + "y": 774, + "type": "common" + }, + { + "x": 927, + "y": 774, + "type": "common" + }, + { + "x": 957, + "y": 774, + "type": "common" + }, + { + "x": 987, + "y": 774, + "type": "common" + }, + { + "x": 1017, + "y": 774, + "type": "common" + }, + { + "x": 1047, + "y": 774, + "type": "common" + }, + { + "x": 1077, + "y": 774, + "type": "common" + }, + { + "x": 1107, + "y": 774, + "type": "common" + }, + { + "x": 837, + "y": 744, + "type": "common" + } + ], + "pipe": { + "x": 577, + "y": 523, + "r": 46 + }, + "required": 5, + "ocdTarget": 10 +} diff --git a/assets/gamedata/gootower/level-023.json b/assets/gamedata/gootower/level-023.json new file mode 100644 index 0000000..366a6c3 --- /dev/null +++ b/assets/gamedata/gootower/level-023.json @@ -0,0 +1,374 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 23, + "name": "Riding the Wind", + "chapter": 2, + "tip": "The updraft takes weight off everything inside it. Spans reach further in the wind.", + "element": "fan", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 0, + 700 + ], + [ + 560, + 700 + ], + [ + 560, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 967, + 700 + ], + [ + 1600, + 700 + ], + [ + 1600, + 1000 + ], + [ + 967, + 1000 + ] + ] + }, + { + "kind": "spike", + "poly": [ + [ + 560, + 930 + ], + [ + 967, + 930 + ], + [ + 967, + 1000 + ], + [ + 560, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 0, + 610 + ], + [ + 44, + 610 + ], + [ + 44, + 700 + ], + [ + 0, + 700 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 516, + 610 + ], + [ + 560, + 610 + ], + [ + 560, + 700 + ], + [ + 516, + 700 + ] + ] + } + ], + "balls": [ + { + "x": 339, + "y": 686, + "type": "common", + "pinned": true + }, + { + "x": 401, + "y": 686, + "type": "common", + "pinned": true + }, + { + "x": 370, + "y": 632, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 90, + "y": 684, + "type": "common" + }, + { + "x": 120, + "y": 684, + "type": "balloon" + }, + { + "x": 150, + "y": 684, + "type": "ivy" + }, + { + "x": 180, + "y": 684, + "type": "common" + }, + { + "x": 210, + "y": 684, + "type": "balloon" + }, + { + "x": 240, + "y": 684, + "type": "ivy" + }, + { + "x": 90, + "y": 654, + "type": "common" + }, + { + "x": 120, + "y": 654, + "type": "balloon" + }, + { + "x": 150, + "y": 654, + "type": "ivy" + }, + { + "x": 180, + "y": 654, + "type": "common" + }, + { + "x": 210, + "y": 654, + "type": "balloon" + }, + { + "x": 240, + "y": 654, + "type": "ivy" + }, + { + "x": 90, + "y": 624, + "type": "common" + }, + { + "x": 120, + "y": 624, + "type": "balloon" + }, + { + "x": 150, + "y": 624, + "type": "common" + }, + { + "x": 180, + "y": 624, + "type": "common" + }, + { + "x": 210, + "y": 624, + "type": "common" + }, + { + "x": 240, + "y": 624, + "type": "common" + }, + { + "x": 90, + "y": 594, + "type": "common" + }, + { + "x": 120, + "y": 594, + "type": "common" + }, + { + "x": 150, + "y": 594, + "type": "common" + }, + { + "x": 180, + "y": 594, + "type": "common" + }, + { + "x": 210, + "y": 594, + "type": "common" + }, + { + "x": 240, + "y": 594, + "type": "common" + }, + { + "x": 90, + "y": 564, + "type": "common" + }, + { + "x": 120, + "y": 564, + "type": "common" + }, + { + "x": 150, + "y": 564, + "type": "common" + }, + { + "x": 180, + "y": 564, + "type": "common" + }, + { + "x": 210, + "y": 564, + "type": "common" + }, + { + "x": 240, + "y": 564, + "type": "common" + }, + { + "x": 90, + "y": 534, + "type": "common" + } + ], + "pipe": { + "x": 1077, + "y": 640, + "r": 46 + }, + "fans": [ + { + "x": 560, + "y": 260, + "w": 407, + "h": 660, + "dx": 0, + "dy": -1, + "force": 1342 + } + ], + "waypoints": [ + { + "x": 763.5, + "y": 580 + } + ], + "required": 6, + "ocdTarget": 12 +} diff --git a/assets/gamedata/gootower/level-024.json b/assets/gamedata/gootower/level-024.json new file mode 100644 index 0000000..063e64a --- /dev/null +++ b/assets/gamedata/gootower/level-024.json @@ -0,0 +1,374 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 24, + "name": "Thermals", + "chapter": 2, + "tip": "The updraft takes weight off everything inside it. Spans reach further in the wind.", + "element": "fan", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 0, + 700 + ], + [ + 560, + 700 + ], + [ + 560, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 979, + 700 + ], + [ + 1600, + 700 + ], + [ + 1600, + 1000 + ], + [ + 979, + 1000 + ] + ] + }, + { + "kind": "spike", + "poly": [ + [ + 560, + 930 + ], + [ + 979, + 930 + ], + [ + 979, + 1000 + ], + [ + 560, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 0, + 610 + ], + [ + 44, + 610 + ], + [ + 44, + 700 + ], + [ + 0, + 700 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 516, + 610 + ], + [ + 560, + 610 + ], + [ + 560, + 700 + ], + [ + 516, + 700 + ] + ] + } + ], + "balls": [ + { + "x": 339, + "y": 686, + "type": "common", + "pinned": true + }, + { + "x": 401, + "y": 686, + "type": "common", + "pinned": true + }, + { + "x": 370, + "y": 632, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 90, + "y": 684, + "type": "common" + }, + { + "x": 120, + "y": 684, + "type": "balloon" + }, + { + "x": 150, + "y": 684, + "type": "ivy" + }, + { + "x": 180, + "y": 684, + "type": "common" + }, + { + "x": 210, + "y": 684, + "type": "balloon" + }, + { + "x": 240, + "y": 684, + "type": "ivy" + }, + { + "x": 90, + "y": 654, + "type": "common" + }, + { + "x": 120, + "y": 654, + "type": "balloon" + }, + { + "x": 150, + "y": 654, + "type": "ivy" + }, + { + "x": 180, + "y": 654, + "type": "common" + }, + { + "x": 210, + "y": 654, + "type": "balloon" + }, + { + "x": 240, + "y": 654, + "type": "ivy" + }, + { + "x": 90, + "y": 624, + "type": "common" + }, + { + "x": 120, + "y": 624, + "type": "balloon" + }, + { + "x": 150, + "y": 624, + "type": "common" + }, + { + "x": 180, + "y": 624, + "type": "common" + }, + { + "x": 210, + "y": 624, + "type": "common" + }, + { + "x": 240, + "y": 624, + "type": "common" + }, + { + "x": 90, + "y": 594, + "type": "common" + }, + { + "x": 120, + "y": 594, + "type": "common" + }, + { + "x": 150, + "y": 594, + "type": "common" + }, + { + "x": 180, + "y": 594, + "type": "common" + }, + { + "x": 210, + "y": 594, + "type": "common" + }, + { + "x": 240, + "y": 594, + "type": "common" + }, + { + "x": 90, + "y": 564, + "type": "common" + }, + { + "x": 120, + "y": 564, + "type": "common" + }, + { + "x": 150, + "y": 564, + "type": "common" + }, + { + "x": 180, + "y": 564, + "type": "common" + }, + { + "x": 210, + "y": 564, + "type": "common" + }, + { + "x": 240, + "y": 564, + "type": "common" + }, + { + "x": 90, + "y": 534, + "type": "common" + } + ], + "pipe": { + "x": 1089, + "y": 640, + "r": 46 + }, + "fans": [ + { + "x": 560, + "y": 260, + "w": 419, + "h": 660, + "dx": 0, + "dy": -1, + "force": 1332 + } + ], + "waypoints": [ + { + "x": 769.5, + "y": 580 + } + ], + "required": 6, + "ocdTarget": 13 +} diff --git a/assets/gamedata/gootower/level-025.json b/assets/gamedata/gootower/level-025.json new file mode 100644 index 0000000..485bf3f --- /dev/null +++ b/assets/gamedata/gootower/level-025.json @@ -0,0 +1,362 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 25, + "name": "Long Reach", + "chapter": 2, + "tip": "Triangles carry weight across a gap. Long chains just sag into the spikes.", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 0, + 700 + ], + [ + 562, + 700 + ], + [ + 562, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 819, + 700 + ], + [ + 1600, + 700 + ], + [ + 1600, + 1000 + ], + [ + 819, + 1000 + ] + ] + }, + { + "kind": "spike", + "poly": [ + [ + 562, + 930 + ], + [ + 819, + 930 + ], + [ + 819, + 1000 + ], + [ + 562, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 0, + 610 + ], + [ + 44, + 610 + ], + [ + 44, + 700 + ], + [ + 0, + 700 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 518, + 610 + ], + [ + 562, + 610 + ], + [ + 562, + 700 + ], + [ + 518, + 700 + ] + ] + } + ], + "balls": [ + { + "x": 341, + "y": 686, + "type": "common", + "pinned": true + }, + { + "x": 403, + "y": 686, + "type": "common", + "pinned": true + }, + { + "x": 372, + "y": 632, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 90, + "y": 684, + "type": "common" + }, + { + "x": 120, + "y": 684, + "type": "balloon" + }, + { + "x": 150, + "y": 684, + "type": "ivy" + }, + { + "x": 180, + "y": 684, + "type": "common" + }, + { + "x": 210, + "y": 684, + "type": "balloon" + }, + { + "x": 240, + "y": 684, + "type": "ivy" + }, + { + "x": 90, + "y": 654, + "type": "common" + }, + { + "x": 120, + "y": 654, + "type": "balloon" + }, + { + "x": 150, + "y": 654, + "type": "ivy" + }, + { + "x": 180, + "y": 654, + "type": "common" + }, + { + "x": 210, + "y": 654, + "type": "balloon" + }, + { + "x": 240, + "y": 654, + "type": "ivy" + }, + { + "x": 90, + "y": 624, + "type": "common" + }, + { + "x": 120, + "y": 624, + "type": "balloon" + }, + { + "x": 150, + "y": 624, + "type": "common" + }, + { + "x": 180, + "y": 624, + "type": "common" + }, + { + "x": 210, + "y": 624, + "type": "common" + }, + { + "x": 240, + "y": 624, + "type": "common" + }, + { + "x": 90, + "y": 594, + "type": "common" + }, + { + "x": 120, + "y": 594, + "type": "common" + }, + { + "x": 150, + "y": 594, + "type": "common" + }, + { + "x": 180, + "y": 594, + "type": "common" + }, + { + "x": 210, + "y": 594, + "type": "common" + }, + { + "x": 240, + "y": 594, + "type": "common" + }, + { + "x": 90, + "y": 564, + "type": "common" + }, + { + "x": 120, + "y": 564, + "type": "common" + }, + { + "x": 150, + "y": 564, + "type": "common" + }, + { + "x": 180, + "y": 564, + "type": "common" + }, + { + "x": 210, + "y": 564, + "type": "common" + }, + { + "x": 240, + "y": 564, + "type": "common" + }, + { + "x": 90, + "y": 534, + "type": "common" + } + ], + "pipe": { + "x": 929, + "y": 640, + "r": 46 + }, + "waypoints": [ + { + "x": 690.5, + "y": 605 + } + ], + "required": 6, + "ocdTarget": 12 +} diff --git a/assets/gamedata/gootower/level-026.json b/assets/gamedata/gootower/level-026.json new file mode 100644 index 0000000..9c19292 --- /dev/null +++ b/assets/gamedata/gootower/level-026.json @@ -0,0 +1,362 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 26, + "name": "The Wide Crossing", + "chapter": 2, + "tip": "Triangles carry weight across a gap. Long chains just sag into the spikes.", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 0, + 700 + ], + [ + 575, + 700 + ], + [ + 575, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 852, + 700 + ], + [ + 1600, + 700 + ], + [ + 1600, + 1000 + ], + [ + 852, + 1000 + ] + ] + }, + { + "kind": "spike", + "poly": [ + [ + 575, + 930 + ], + [ + 852, + 930 + ], + [ + 852, + 1000 + ], + [ + 575, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 0, + 610 + ], + [ + 44, + 610 + ], + [ + 44, + 700 + ], + [ + 0, + 700 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 531, + 610 + ], + [ + 575, + 610 + ], + [ + 575, + 700 + ], + [ + 531, + 700 + ] + ] + } + ], + "balls": [ + { + "x": 354, + "y": 686, + "type": "common", + "pinned": true + }, + { + "x": 416, + "y": 686, + "type": "common", + "pinned": true + }, + { + "x": 385, + "y": 632, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 90, + "y": 684, + "type": "common" + }, + { + "x": 120, + "y": 684, + "type": "balloon" + }, + { + "x": 150, + "y": 684, + "type": "ivy" + }, + { + "x": 180, + "y": 684, + "type": "common" + }, + { + "x": 210, + "y": 684, + "type": "balloon" + }, + { + "x": 240, + "y": 684, + "type": "ivy" + }, + { + "x": 90, + "y": 654, + "type": "common" + }, + { + "x": 120, + "y": 654, + "type": "balloon" + }, + { + "x": 150, + "y": 654, + "type": "ivy" + }, + { + "x": 180, + "y": 654, + "type": "common" + }, + { + "x": 210, + "y": 654, + "type": "balloon" + }, + { + "x": 240, + "y": 654, + "type": "ivy" + }, + { + "x": 90, + "y": 624, + "type": "common" + }, + { + "x": 120, + "y": 624, + "type": "balloon" + }, + { + "x": 150, + "y": 624, + "type": "common" + }, + { + "x": 180, + "y": 624, + "type": "common" + }, + { + "x": 210, + "y": 624, + "type": "common" + }, + { + "x": 240, + "y": 624, + "type": "common" + }, + { + "x": 90, + "y": 594, + "type": "common" + }, + { + "x": 120, + "y": 594, + "type": "common" + }, + { + "x": 150, + "y": 594, + "type": "common" + }, + { + "x": 180, + "y": 594, + "type": "common" + }, + { + "x": 210, + "y": 594, + "type": "common" + }, + { + "x": 240, + "y": 594, + "type": "common" + }, + { + "x": 90, + "y": 564, + "type": "common" + }, + { + "x": 120, + "y": 564, + "type": "common" + }, + { + "x": 150, + "y": 564, + "type": "common" + }, + { + "x": 180, + "y": 564, + "type": "common" + }, + { + "x": 210, + "y": 564, + "type": "common" + }, + { + "x": 240, + "y": 564, + "type": "common" + }, + { + "x": 90, + "y": 534, + "type": "common" + } + ], + "pipe": { + "x": 962, + "y": 640, + "r": 46 + }, + "waypoints": [ + { + "x": 713.5, + "y": 605 + } + ], + "required": 6, + "ocdTarget": 13 +} diff --git a/assets/gamedata/gootower/level-027.json b/assets/gamedata/gootower/level-027.json new file mode 100644 index 0000000..16229cc --- /dev/null +++ b/assets/gamedata/gootower/level-027.json @@ -0,0 +1,362 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 27, + "name": "Windswept", + "chapter": 2, + "tip": "Triangles carry weight across a gap. Long chains just sag into the spikes.", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 0, + 700 + ], + [ + 575, + 700 + ], + [ + 575, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 871, + 700 + ], + [ + 1600, + 700 + ], + [ + 1600, + 1000 + ], + [ + 871, + 1000 + ] + ] + }, + { + "kind": "spike", + "poly": [ + [ + 575, + 930 + ], + [ + 871, + 930 + ], + [ + 871, + 1000 + ], + [ + 575, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 0, + 610 + ], + [ + 44, + 610 + ], + [ + 44, + 700 + ], + [ + 0, + 700 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 531, + 610 + ], + [ + 575, + 610 + ], + [ + 575, + 700 + ], + [ + 531, + 700 + ] + ] + } + ], + "balls": [ + { + "x": 354, + "y": 686, + "type": "common", + "pinned": true + }, + { + "x": 416, + "y": 686, + "type": "common", + "pinned": true + }, + { + "x": 385, + "y": 632, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 90, + "y": 684, + "type": "common" + }, + { + "x": 120, + "y": 684, + "type": "balloon" + }, + { + "x": 150, + "y": 684, + "type": "ivy" + }, + { + "x": 180, + "y": 684, + "type": "common" + }, + { + "x": 210, + "y": 684, + "type": "balloon" + }, + { + "x": 240, + "y": 684, + "type": "ivy" + }, + { + "x": 90, + "y": 654, + "type": "common" + }, + { + "x": 120, + "y": 654, + "type": "balloon" + }, + { + "x": 150, + "y": 654, + "type": "ivy" + }, + { + "x": 180, + "y": 654, + "type": "common" + }, + { + "x": 210, + "y": 654, + "type": "balloon" + }, + { + "x": 240, + "y": 654, + "type": "ivy" + }, + { + "x": 90, + "y": 624, + "type": "common" + }, + { + "x": 120, + "y": 624, + "type": "balloon" + }, + { + "x": 150, + "y": 624, + "type": "common" + }, + { + "x": 180, + "y": 624, + "type": "common" + }, + { + "x": 210, + "y": 624, + "type": "common" + }, + { + "x": 240, + "y": 624, + "type": "common" + }, + { + "x": 90, + "y": 594, + "type": "common" + }, + { + "x": 120, + "y": 594, + "type": "common" + }, + { + "x": 150, + "y": 594, + "type": "common" + }, + { + "x": 180, + "y": 594, + "type": "common" + }, + { + "x": 210, + "y": 594, + "type": "common" + }, + { + "x": 240, + "y": 594, + "type": "common" + }, + { + "x": 90, + "y": 564, + "type": "common" + }, + { + "x": 120, + "y": 564, + "type": "common" + }, + { + "x": 150, + "y": 564, + "type": "common" + }, + { + "x": 180, + "y": 564, + "type": "common" + }, + { + "x": 210, + "y": 564, + "type": "common" + }, + { + "x": 240, + "y": 564, + "type": "common" + }, + { + "x": 90, + "y": 534, + "type": "common" + } + ], + "pipe": { + "x": 981, + "y": 640, + "r": 46 + }, + "waypoints": [ + { + "x": 723, + "y": 605 + } + ], + "required": 7, + "ocdTarget": 15 +} diff --git a/assets/gamedata/gootower/level-028.json b/assets/gamedata/gootower/level-028.json new file mode 100644 index 0000000..a6cc55f --- /dev/null +++ b/assets/gamedata/gootower/level-028.json @@ -0,0 +1,374 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 28, + "name": "Gale", + "chapter": 2, + "tip": "The updraft takes weight off everything inside it. Spans reach further in the wind.", + "element": "fan", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 0, + 700 + ], + [ + 560, + 700 + ], + [ + 560, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 981, + 700 + ], + [ + 1600, + 700 + ], + [ + 1600, + 1000 + ], + [ + 981, + 1000 + ] + ] + }, + { + "kind": "spike", + "poly": [ + [ + 560, + 930 + ], + [ + 981, + 930 + ], + [ + 981, + 1000 + ], + [ + 560, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 0, + 610 + ], + [ + 44, + 610 + ], + [ + 44, + 700 + ], + [ + 0, + 700 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 516, + 610 + ], + [ + 560, + 610 + ], + [ + 560, + 700 + ], + [ + 516, + 700 + ] + ] + } + ], + "balls": [ + { + "x": 339, + "y": 686, + "type": "common", + "pinned": true + }, + { + "x": 401, + "y": 686, + "type": "common", + "pinned": true + }, + { + "x": 370, + "y": 632, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 90, + "y": 684, + "type": "common" + }, + { + "x": 120, + "y": 684, + "type": "balloon" + }, + { + "x": 150, + "y": 684, + "type": "ivy" + }, + { + "x": 180, + "y": 684, + "type": "common" + }, + { + "x": 210, + "y": 684, + "type": "balloon" + }, + { + "x": 240, + "y": 684, + "type": "ivy" + }, + { + "x": 90, + "y": 654, + "type": "common" + }, + { + "x": 120, + "y": 654, + "type": "balloon" + }, + { + "x": 150, + "y": 654, + "type": "ivy" + }, + { + "x": 180, + "y": 654, + "type": "common" + }, + { + "x": 210, + "y": 654, + "type": "balloon" + }, + { + "x": 240, + "y": 654, + "type": "ivy" + }, + { + "x": 90, + "y": 624, + "type": "common" + }, + { + "x": 120, + "y": 624, + "type": "balloon" + }, + { + "x": 150, + "y": 624, + "type": "common" + }, + { + "x": 180, + "y": 624, + "type": "common" + }, + { + "x": 210, + "y": 624, + "type": "common" + }, + { + "x": 240, + "y": 624, + "type": "common" + }, + { + "x": 90, + "y": 594, + "type": "common" + }, + { + "x": 120, + "y": 594, + "type": "common" + }, + { + "x": 150, + "y": 594, + "type": "common" + }, + { + "x": 180, + "y": 594, + "type": "common" + }, + { + "x": 210, + "y": 594, + "type": "common" + }, + { + "x": 240, + "y": 594, + "type": "common" + }, + { + "x": 90, + "y": 564, + "type": "common" + }, + { + "x": 120, + "y": 564, + "type": "common" + }, + { + "x": 150, + "y": 564, + "type": "common" + }, + { + "x": 180, + "y": 564, + "type": "common" + }, + { + "x": 210, + "y": 564, + "type": "common" + }, + { + "x": 240, + "y": 564, + "type": "common" + }, + { + "x": 90, + "y": 534, + "type": "common" + } + ], + "pipe": { + "x": 1091, + "y": 640, + "r": 46 + }, + "fans": [ + { + "x": 560, + "y": 260, + "w": 421, + "h": 660, + "dx": 0, + "dy": -1, + "force": 1330 + } + ], + "waypoints": [ + { + "x": 770.5, + "y": 580 + } + ], + "required": 6, + "ocdTarget": 13 +} diff --git a/assets/gamedata/gootower/level-029.json b/assets/gamedata/gootower/level-029.json new file mode 100644 index 0000000..6cc1778 --- /dev/null +++ b/assets/gamedata/gootower/level-029.json @@ -0,0 +1,272 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 29, + "name": "Squall", + "chapter": 2, + "tip": "Brace as you go. An unbraced column leans, and once it leans it keeps leaning.", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + 0, + 850 + ], + [ + 1600, + 850 + ], + [ + 1600, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + } + ], + "balls": [ + { + "x": 512, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 574, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 543, + "y": 782, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 803, + "y": 834, + "type": "common" + }, + { + "x": 833, + "y": 834, + "type": "balloon" + }, + { + "x": 863, + "y": 834, + "type": "ivy" + }, + { + "x": 893, + "y": 834, + "type": "common" + }, + { + "x": 923, + "y": 834, + "type": "balloon" + }, + { + "x": 953, + "y": 834, + "type": "ivy" + }, + { + "x": 983, + "y": 834, + "type": "common" + }, + { + "x": 1013, + "y": 834, + "type": "balloon" + }, + { + "x": 1043, + "y": 834, + "type": "ivy" + }, + { + "x": 1073, + "y": 834, + "type": "common" + }, + { + "x": 803, + "y": 804, + "type": "balloon" + }, + { + "x": 833, + "y": 804, + "type": "ivy" + }, + { + "x": 863, + "y": 804, + "type": "common" + }, + { + "x": 893, + "y": 804, + "type": "balloon" + }, + { + "x": 923, + "y": 804, + "type": "common" + }, + { + "x": 953, + "y": 804, + "type": "common" + }, + { + "x": 983, + "y": 804, + "type": "common" + }, + { + "x": 1013, + "y": 804, + "type": "common" + }, + { + "x": 1043, + "y": 804, + "type": "common" + }, + { + "x": 1073, + "y": 804, + "type": "common" + }, + { + "x": 803, + "y": 774, + "type": "common" + }, + { + "x": 833, + "y": 774, + "type": "common" + }, + { + "x": 863, + "y": 774, + "type": "common" + }, + { + "x": 893, + "y": 774, + "type": "common" + }, + { + "x": 923, + "y": 774, + "type": "common" + }, + { + "x": 953, + "y": 774, + "type": "common" + }, + { + "x": 983, + "y": 774, + "type": "common" + }, + { + "x": 1013, + "y": 774, + "type": "common" + }, + { + "x": 1043, + "y": 774, + "type": "common" + }, + { + "x": 1073, + "y": 774, + "type": "common" + }, + { + "x": 803, + "y": 744, + "type": "common" + } + ], + "pipe": { + "x": 543, + "y": 432, + "r": 46 + }, + "required": 6, + "ocdTarget": 13 +} diff --git a/assets/gamedata/gootower/level-030.json b/assets/gamedata/gootower/level-030.json new file mode 100644 index 0000000..92c6969 --- /dev/null +++ b/assets/gamedata/gootower/level-030.json @@ -0,0 +1,247 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 30, + "name": "Headwind", + "chapter": 2, + "tip": "Brace as you go. An unbraced column leans, and once it leans it keeps leaning.", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + 0, + 850 + ], + [ + 1600, + 850 + ], + [ + 1600, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + } + ], + "balls": [ + { + "x": 764, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 826, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 795, + "y": 782, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 1055, + "y": 834, + "type": "common" + }, + { + "x": 1085, + "y": 834, + "type": "balloon" + }, + { + "x": 1115, + "y": 834, + "type": "common" + }, + { + "x": 1145, + "y": 834, + "type": "balloon" + }, + { + "x": 1175, + "y": 834, + "type": "common" + }, + { + "x": 1205, + "y": 834, + "type": "balloon" + }, + { + "x": 1235, + "y": 834, + "type": "common" + }, + { + "x": 1265, + "y": 834, + "type": "balloon" + }, + { + "x": 1295, + "y": 834, + "type": "common" + }, + { + "x": 1055, + "y": 804, + "type": "balloon" + }, + { + "x": 1085, + "y": 804, + "type": "common" + }, + { + "x": 1115, + "y": 804, + "type": "balloon" + }, + { + "x": 1145, + "y": 804, + "type": "common" + }, + { + "x": 1175, + "y": 804, + "type": "common" + }, + { + "x": 1205, + "y": 804, + "type": "common" + }, + { + "x": 1235, + "y": 804, + "type": "common" + }, + { + "x": 1265, + "y": 804, + "type": "common" + }, + { + "x": 1295, + "y": 804, + "type": "common" + }, + { + "x": 1055, + "y": 774, + "type": "common" + }, + { + "x": 1085, + "y": 774, + "type": "common" + }, + { + "x": 1115, + "y": 774, + "type": "common" + }, + { + "x": 1145, + "y": 774, + "type": "common" + }, + { + "x": 1175, + "y": 774, + "type": "common" + }, + { + "x": 1205, + "y": 774, + "type": "common" + }, + { + "x": 1235, + "y": 774, + "type": "common" + }, + { + "x": 1265, + "y": 774, + "type": "common" + } + ], + "pipe": { + "x": 795, + "y": 491, + "r": 46 + }, + "required": 5, + "ocdTarget": 11 +} diff --git a/assets/gamedata/gootower/level-031.json b/assets/gamedata/gootower/level-031.json new file mode 100644 index 0000000..581e1f3 --- /dev/null +++ b/assets/gamedata/gootower/level-031.json @@ -0,0 +1,287 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 31, + "name": "First Cog", + "chapter": 3, + "tip": "The cog is solid and it is turning. Whatever it touches gets dragged along.", + "element": "gear", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + 0, + 850 + ], + [ + 1600, + 850 + ], + [ + 1600, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + } + ], + "balls": [ + { + "x": 339, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 401, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 370, + "y": 782, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 1000, + "y": 834, + "type": "common" + }, + { + "x": 1030, + "y": 834, + "type": "block" + }, + { + "x": 1060, + "y": 834, + "type": "common" + }, + { + "x": 1090, + "y": 834, + "type": "block" + }, + { + "x": 1120, + "y": 834, + "type": "common" + }, + { + "x": 1150, + "y": 834, + "type": "block" + }, + { + "x": 1180, + "y": 834, + "type": "common" + }, + { + "x": 1210, + "y": 834, + "type": "block" + }, + { + "x": 1240, + "y": 834, + "type": "common" + }, + { + "x": 1000, + "y": 804, + "type": "block" + }, + { + "x": 1030, + "y": 804, + "type": "common" + }, + { + "x": 1060, + "y": 804, + "type": "block" + }, + { + "x": 1090, + "y": 804, + "type": "common" + }, + { + "x": 1120, + "y": 804, + "type": "block" + }, + { + "x": 1150, + "y": 804, + "type": "common" + }, + { + "x": 1180, + "y": 804, + "type": "block" + }, + { + "x": 1210, + "y": 804, + "type": "common" + }, + { + "x": 1240, + "y": 804, + "type": "common" + }, + { + "x": 1000, + "y": 774, + "type": "common" + }, + { + "x": 1030, + "y": 774, + "type": "common" + }, + { + "x": 1060, + "y": 774, + "type": "common" + }, + { + "x": 1090, + "y": 774, + "type": "common" + }, + { + "x": 1120, + "y": 774, + "type": "common" + }, + { + "x": 1150, + "y": 774, + "type": "common" + }, + { + "x": 1180, + "y": 774, + "type": "common" + }, + { + "x": 1210, + "y": 774, + "type": "common" + }, + { + "x": 1240, + "y": 774, + "type": "common" + }, + { + "x": 1000, + "y": 744, + "type": "common" + }, + { + "x": 1030, + "y": 744, + "type": "common" + }, + { + "x": 1060, + "y": 744, + "type": "common" + }, + { + "x": 1090, + "y": 744, + "type": "common" + }, + { + "x": 1120, + "y": 744, + "type": "common" + } + ], + "pipe": { + "x": 1170, + "y": 615, + "r": 46 + }, + "gears": [ + { + "x": 793, + "y": 515, + "r": 97, + "teeth": 9, + "omega": -1.1696241107210519 + } + ], + "required": 4, + "ocdTarget": 8 +} diff --git a/assets/gamedata/gootower/level-032.json b/assets/gamedata/gootower/level-032.json new file mode 100644 index 0000000..96c48c0 --- /dev/null +++ b/assets/gamedata/gootower/level-032.json @@ -0,0 +1,287 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 32, + "name": "Gearworks", + "chapter": 3, + "tip": "The cog is solid and it is turning. Whatever it touches gets dragged along.", + "element": "gear", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + 0, + 850 + ], + [ + 1600, + 850 + ], + [ + 1600, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + } + ], + "balls": [ + { + "x": 255, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 317, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 286, + "y": 782, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 1000, + "y": 834, + "type": "common" + }, + { + "x": 1030, + "y": 834, + "type": "block" + }, + { + "x": 1060, + "y": 834, + "type": "common" + }, + { + "x": 1090, + "y": 834, + "type": "block" + }, + { + "x": 1120, + "y": 834, + "type": "common" + }, + { + "x": 1150, + "y": 834, + "type": "block" + }, + { + "x": 1180, + "y": 834, + "type": "common" + }, + { + "x": 1210, + "y": 834, + "type": "block" + }, + { + "x": 1240, + "y": 834, + "type": "common" + }, + { + "x": 1000, + "y": 804, + "type": "block" + }, + { + "x": 1030, + "y": 804, + "type": "common" + }, + { + "x": 1060, + "y": 804, + "type": "block" + }, + { + "x": 1090, + "y": 804, + "type": "common" + }, + { + "x": 1120, + "y": 804, + "type": "block" + }, + { + "x": 1150, + "y": 804, + "type": "common" + }, + { + "x": 1180, + "y": 804, + "type": "block" + }, + { + "x": 1210, + "y": 804, + "type": "common" + }, + { + "x": 1240, + "y": 804, + "type": "common" + }, + { + "x": 1000, + "y": 774, + "type": "common" + }, + { + "x": 1030, + "y": 774, + "type": "common" + }, + { + "x": 1060, + "y": 774, + "type": "common" + }, + { + "x": 1090, + "y": 774, + "type": "common" + }, + { + "x": 1120, + "y": 774, + "type": "common" + }, + { + "x": 1150, + "y": 774, + "type": "common" + }, + { + "x": 1180, + "y": 774, + "type": "common" + }, + { + "x": 1210, + "y": 774, + "type": "common" + }, + { + "x": 1240, + "y": 774, + "type": "common" + }, + { + "x": 1000, + "y": 744, + "type": "common" + }, + { + "x": 1030, + "y": 744, + "type": "common" + }, + { + "x": 1060, + "y": 744, + "type": "common" + }, + { + "x": 1090, + "y": 744, + "type": "common" + }, + { + "x": 1120, + "y": 744, + "type": "common" + } + ], + "pipe": { + "x": 1194, + "y": 602, + "r": 46 + }, + "gears": [ + { + "x": 781, + "y": 502, + "r": 103, + "teeth": 9, + "omega": -1.3370113929565997 + } + ], + "required": 5, + "ocdTarget": 10 +} diff --git a/assets/gamedata/gootower/level-033.json b/assets/gamedata/gootower/level-033.json new file mode 100644 index 0000000..56940cc --- /dev/null +++ b/assets/gamedata/gootower/level-033.json @@ -0,0 +1,287 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 33, + "name": "Clockwise", + "chapter": 3, + "tip": "The cog is solid and it is turning. Whatever it touches gets dragged along.", + "element": "gear", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + 0, + 850 + ], + [ + 1600, + 850 + ], + [ + 1600, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + } + ], + "balls": [ + { + "x": 292, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 354, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 323, + "y": 782, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 1000, + "y": 834, + "type": "common" + }, + { + "x": 1030, + "y": 834, + "type": "block" + }, + { + "x": 1060, + "y": 834, + "type": "common" + }, + { + "x": 1090, + "y": 834, + "type": "block" + }, + { + "x": 1120, + "y": 834, + "type": "common" + }, + { + "x": 1150, + "y": 834, + "type": "block" + }, + { + "x": 1180, + "y": 834, + "type": "common" + }, + { + "x": 1210, + "y": 834, + "type": "block" + }, + { + "x": 1240, + "y": 834, + "type": "common" + }, + { + "x": 1000, + "y": 804, + "type": "block" + }, + { + "x": 1030, + "y": 804, + "type": "common" + }, + { + "x": 1060, + "y": 804, + "type": "block" + }, + { + "x": 1090, + "y": 804, + "type": "common" + }, + { + "x": 1120, + "y": 804, + "type": "block" + }, + { + "x": 1150, + "y": 804, + "type": "common" + }, + { + "x": 1180, + "y": 804, + "type": "block" + }, + { + "x": 1210, + "y": 804, + "type": "common" + }, + { + "x": 1240, + "y": 804, + "type": "common" + }, + { + "x": 1000, + "y": 774, + "type": "common" + }, + { + "x": 1030, + "y": 774, + "type": "common" + }, + { + "x": 1060, + "y": 774, + "type": "common" + }, + { + "x": 1090, + "y": 774, + "type": "common" + }, + { + "x": 1120, + "y": 774, + "type": "common" + }, + { + "x": 1150, + "y": 774, + "type": "common" + }, + { + "x": 1180, + "y": 774, + "type": "common" + }, + { + "x": 1210, + "y": 774, + "type": "common" + }, + { + "x": 1240, + "y": 774, + "type": "common" + }, + { + "x": 1000, + "y": 744, + "type": "common" + }, + { + "x": 1030, + "y": 744, + "type": "common" + }, + { + "x": 1060, + "y": 744, + "type": "common" + }, + { + "x": 1090, + "y": 744, + "type": "common" + }, + { + "x": 1120, + "y": 744, + "type": "common" + } + ], + "pipe": { + "x": 1209, + "y": 594, + "r": 46 + }, + "gears": [ + { + "x": 767, + "y": 494, + "r": 106, + "teeth": 9, + "omega": 1.4362818361772225 + } + ], + "required": 5, + "ocdTarget": 11 +} diff --git a/assets/gamedata/gootower/level-034.json b/assets/gamedata/gootower/level-034.json new file mode 100644 index 0000000..43384d7 --- /dev/null +++ b/assets/gamedata/gootower/level-034.json @@ -0,0 +1,287 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 34, + "name": "Widdershins", + "chapter": 3, + "tip": "The cog is solid and it is turning. Whatever it touches gets dragged along.", + "element": "gear", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + 0, + 850 + ], + [ + 1600, + 850 + ], + [ + 1600, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + } + ], + "balls": [ + { + "x": 344, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 406, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 375, + "y": 782, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 1000, + "y": 834, + "type": "common" + }, + { + "x": 1030, + "y": 834, + "type": "block" + }, + { + "x": 1060, + "y": 834, + "type": "common" + }, + { + "x": 1090, + "y": 834, + "type": "block" + }, + { + "x": 1120, + "y": 834, + "type": "common" + }, + { + "x": 1150, + "y": 834, + "type": "block" + }, + { + "x": 1180, + "y": 834, + "type": "common" + }, + { + "x": 1210, + "y": 834, + "type": "block" + }, + { + "x": 1240, + "y": 834, + "type": "common" + }, + { + "x": 1000, + "y": 804, + "type": "block" + }, + { + "x": 1030, + "y": 804, + "type": "common" + }, + { + "x": 1060, + "y": 804, + "type": "block" + }, + { + "x": 1090, + "y": 804, + "type": "common" + }, + { + "x": 1120, + "y": 804, + "type": "block" + }, + { + "x": 1150, + "y": 804, + "type": "common" + }, + { + "x": 1180, + "y": 804, + "type": "block" + }, + { + "x": 1210, + "y": 804, + "type": "common" + }, + { + "x": 1240, + "y": 804, + "type": "common" + }, + { + "x": 1000, + "y": 774, + "type": "common" + }, + { + "x": 1030, + "y": 774, + "type": "common" + }, + { + "x": 1060, + "y": 774, + "type": "common" + }, + { + "x": 1090, + "y": 774, + "type": "common" + }, + { + "x": 1120, + "y": 774, + "type": "common" + }, + { + "x": 1150, + "y": 774, + "type": "common" + }, + { + "x": 1180, + "y": 774, + "type": "common" + }, + { + "x": 1210, + "y": 774, + "type": "common" + }, + { + "x": 1240, + "y": 774, + "type": "common" + }, + { + "x": 1000, + "y": 744, + "type": "common" + }, + { + "x": 1030, + "y": 744, + "type": "common" + }, + { + "x": 1060, + "y": 744, + "type": "common" + }, + { + "x": 1090, + "y": 744, + "type": "common" + }, + { + "x": 1120, + "y": 744, + "type": "common" + } + ], + "pipe": { + "x": 1225, + "y": 585, + "r": 46 + }, + "gears": [ + { + "x": 776, + "y": 485, + "r": 110, + "teeth": 9, + "omega": 1.548741678437218 + } + ], + "required": 6, + "ocdTarget": 12 +} diff --git a/assets/gamedata/gootower/level-035.json b/assets/gamedata/gootower/level-035.json new file mode 100644 index 0000000..4be3dba --- /dev/null +++ b/assets/gamedata/gootower/level-035.json @@ -0,0 +1,277 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 35, + "name": "Rigid Thinking", + "chapter": 3, + "tip": "Brace as you go. An unbraced column leans, and once it leans it keeps leaning.", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + 0, + 850 + ], + [ + 1600, + 850 + ], + [ + 1600, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + } + ], + "balls": [ + { + "x": 712, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 774, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 743, + "y": 782, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 1003, + "y": 834, + "type": "common" + }, + { + "x": 1033, + "y": 834, + "type": "block" + }, + { + "x": 1063, + "y": 834, + "type": "common" + }, + { + "x": 1093, + "y": 834, + "type": "block" + }, + { + "x": 1123, + "y": 834, + "type": "common" + }, + { + "x": 1153, + "y": 834, + "type": "block" + }, + { + "x": 1183, + "y": 834, + "type": "common" + }, + { + "x": 1213, + "y": 834, + "type": "block" + }, + { + "x": 1243, + "y": 834, + "type": "common" + }, + { + "x": 1273, + "y": 834, + "type": "block" + }, + { + "x": 1303, + "y": 834, + "type": "common" + }, + { + "x": 1003, + "y": 804, + "type": "block" + }, + { + "x": 1033, + "y": 804, + "type": "common" + }, + { + "x": 1063, + "y": 804, + "type": "block" + }, + { + "x": 1093, + "y": 804, + "type": "common" + }, + { + "x": 1123, + "y": 804, + "type": "block" + }, + { + "x": 1153, + "y": 804, + "type": "common" + }, + { + "x": 1183, + "y": 804, + "type": "common" + }, + { + "x": 1213, + "y": 804, + "type": "common" + }, + { + "x": 1243, + "y": 804, + "type": "common" + }, + { + "x": 1273, + "y": 804, + "type": "common" + }, + { + "x": 1303, + "y": 804, + "type": "common" + }, + { + "x": 1003, + "y": 774, + "type": "common" + }, + { + "x": 1033, + "y": 774, + "type": "common" + }, + { + "x": 1063, + "y": 774, + "type": "common" + }, + { + "x": 1093, + "y": 774, + "type": "common" + }, + { + "x": 1123, + "y": 774, + "type": "common" + }, + { + "x": 1153, + "y": 774, + "type": "common" + }, + { + "x": 1183, + "y": 774, + "type": "common" + }, + { + "x": 1213, + "y": 774, + "type": "common" + }, + { + "x": 1243, + "y": 774, + "type": "common" + }, + { + "x": 1273, + "y": 774, + "type": "common" + } + ], + "pipe": { + "x": 743, + "y": 428, + "r": 46 + }, + "required": 6, + "ocdTarget": 13 +} diff --git a/assets/gamedata/gootower/level-036.json b/assets/gamedata/gootower/level-036.json new file mode 100644 index 0000000..0a37381 --- /dev/null +++ b/assets/gamedata/gootower/level-036.json @@ -0,0 +1,277 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 36, + "name": "Girders", + "chapter": 3, + "tip": "Brace as you go. An unbraced column leans, and once it leans it keeps leaning.", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + 0, + 850 + ], + [ + 1600, + 850 + ], + [ + 1600, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + } + ], + "balls": [ + { + "x": 481, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 543, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 512, + "y": 782, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 772, + "y": 834, + "type": "common" + }, + { + "x": 802, + "y": 834, + "type": "block" + }, + { + "x": 832, + "y": 834, + "type": "common" + }, + { + "x": 862, + "y": 834, + "type": "block" + }, + { + "x": 892, + "y": 834, + "type": "common" + }, + { + "x": 922, + "y": 834, + "type": "block" + }, + { + "x": 952, + "y": 834, + "type": "common" + }, + { + "x": 982, + "y": 834, + "type": "block" + }, + { + "x": 1012, + "y": 834, + "type": "common" + }, + { + "x": 1042, + "y": 834, + "type": "block" + }, + { + "x": 1072, + "y": 834, + "type": "common" + }, + { + "x": 772, + "y": 804, + "type": "block" + }, + { + "x": 802, + "y": 804, + "type": "common" + }, + { + "x": 832, + "y": 804, + "type": "block" + }, + { + "x": 862, + "y": 804, + "type": "common" + }, + { + "x": 892, + "y": 804, + "type": "block" + }, + { + "x": 922, + "y": 804, + "type": "common" + }, + { + "x": 952, + "y": 804, + "type": "common" + }, + { + "x": 982, + "y": 804, + "type": "common" + }, + { + "x": 1012, + "y": 804, + "type": "common" + }, + { + "x": 1042, + "y": 804, + "type": "common" + }, + { + "x": 1072, + "y": 804, + "type": "common" + }, + { + "x": 772, + "y": 774, + "type": "common" + }, + { + "x": 802, + "y": 774, + "type": "common" + }, + { + "x": 832, + "y": 774, + "type": "common" + }, + { + "x": 862, + "y": 774, + "type": "common" + }, + { + "x": 892, + "y": 774, + "type": "common" + }, + { + "x": 922, + "y": 774, + "type": "common" + }, + { + "x": 952, + "y": 774, + "type": "common" + }, + { + "x": 982, + "y": 774, + "type": "common" + }, + { + "x": 1012, + "y": 774, + "type": "common" + }, + { + "x": 1042, + "y": 774, + "type": "common" + } + ], + "pipe": { + "x": 512, + "y": 393, + "r": 46 + }, + "required": 7, + "ocdTarget": 15 +} diff --git a/assets/gamedata/gootower/level-037.json b/assets/gamedata/gootower/level-037.json new file mode 100644 index 0000000..d251d82 --- /dev/null +++ b/assets/gamedata/gootower/level-037.json @@ -0,0 +1,337 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 37, + "name": "Soft Rock", + "chapter": 3, + "tip": "Drop a bomb by the fire and the soft rock goes with it. Or take the long way over.", + "element": "bomb", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + 0, + 850 + ], + [ + 1600, + 850 + ], + [ + 1600, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 731, + 695 + ], + [ + 811, + 695 + ], + [ + 811, + 850 + ], + [ + 731, + 850 + ] + ], + "destructible": true + }, + { + "kind": "fire", + "poly": [ + [ + 621, + 806 + ], + [ + 701, + 806 + ], + [ + 701, + 850 + ], + [ + 621, + 850 + ] + ] + } + ], + "balls": [ + { + "x": 376, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 438, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 407, + "y": 782, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 117, + "y": 834, + "type": "common" + }, + { + "x": 147, + "y": 834, + "type": "block" + }, + { + "x": 177, + "y": 834, + "type": "bomb" + }, + { + "x": 207, + "y": 834, + "type": "common" + }, + { + "x": 237, + "y": 834, + "type": "block" + }, + { + "x": 267, + "y": 834, + "type": "bomb" + }, + { + "x": 297, + "y": 834, + "type": "common" + }, + { + "x": 117, + "y": 804, + "type": "block" + }, + { + "x": 147, + "y": 804, + "type": "bomb" + }, + { + "x": 177, + "y": 804, + "type": "common" + }, + { + "x": 207, + "y": 804, + "type": "block" + }, + { + "x": 237, + "y": 804, + "type": "bomb" + }, + { + "x": 267, + "y": 804, + "type": "common" + }, + { + "x": 297, + "y": 804, + "type": "block" + }, + { + "x": 117, + "y": 774, + "type": "common" + }, + { + "x": 147, + "y": 774, + "type": "block" + }, + { + "x": 177, + "y": 774, + "type": "common" + }, + { + "x": 207, + "y": 774, + "type": "block" + }, + { + "x": 237, + "y": 774, + "type": "common" + }, + { + "x": 267, + "y": 774, + "type": "block" + }, + { + "x": 297, + "y": 774, + "type": "common" + }, + { + "x": 117, + "y": 744, + "type": "common" + }, + { + "x": 147, + "y": 744, + "type": "common" + }, + { + "x": 177, + "y": 744, + "type": "common" + }, + { + "x": 207, + "y": 744, + "type": "common" + }, + { + "x": 237, + "y": 744, + "type": "common" + }, + { + "x": 267, + "y": 744, + "type": "common" + }, + { + "x": 297, + "y": 744, + "type": "common" + }, + { + "x": 117, + "y": 714, + "type": "common" + }, + { + "x": 147, + "y": 714, + "type": "common" + }, + { + "x": 177, + "y": 714, + "type": "common" + }, + { + "x": 207, + "y": 714, + "type": "common" + }, + { + "x": 237, + "y": 714, + "type": "common" + }, + { + "x": 267, + "y": 714, + "type": "common" + } + ], + "pipe": { + "x": 992, + "y": 700, + "r": 46 + }, + "waypoints": [ + { + "x": 771, + "y": 620 + } + ], + "required": 4, + "ocdTarget": 8 +} diff --git a/assets/gamedata/gootower/level-038.json b/assets/gamedata/gootower/level-038.json new file mode 100644 index 0000000..f2140b9 --- /dev/null +++ b/assets/gamedata/gootower/level-038.json @@ -0,0 +1,337 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 38, + "name": "Demolition", + "chapter": 3, + "tip": "Drop a bomb by the fire and the soft rock goes with it. Or take the long way over.", + "element": "bomb", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + 0, + 850 + ], + [ + 1600, + 850 + ], + [ + 1600, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 748, + 684 + ], + [ + 828, + 684 + ], + [ + 828, + 850 + ], + [ + 748, + 850 + ] + ], + "destructible": true + }, + { + "kind": "fire", + "poly": [ + [ + 638, + 806 + ], + [ + 718, + 806 + ], + [ + 718, + 850 + ], + [ + 638, + 850 + ] + ] + } + ], + "balls": [ + { + "x": 338, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 400, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 369, + "y": 782, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 79, + "y": 834, + "type": "common" + }, + { + "x": 109, + "y": 834, + "type": "block" + }, + { + "x": 139, + "y": 834, + "type": "bomb" + }, + { + "x": 169, + "y": 834, + "type": "common" + }, + { + "x": 199, + "y": 834, + "type": "block" + }, + { + "x": 229, + "y": 834, + "type": "bomb" + }, + { + "x": 259, + "y": 834, + "type": "common" + }, + { + "x": 79, + "y": 804, + "type": "block" + }, + { + "x": 109, + "y": 804, + "type": "bomb" + }, + { + "x": 139, + "y": 804, + "type": "common" + }, + { + "x": 169, + "y": 804, + "type": "block" + }, + { + "x": 199, + "y": 804, + "type": "bomb" + }, + { + "x": 229, + "y": 804, + "type": "common" + }, + { + "x": 259, + "y": 804, + "type": "block" + }, + { + "x": 79, + "y": 774, + "type": "common" + }, + { + "x": 109, + "y": 774, + "type": "block" + }, + { + "x": 139, + "y": 774, + "type": "common" + }, + { + "x": 169, + "y": 774, + "type": "block" + }, + { + "x": 199, + "y": 774, + "type": "common" + }, + { + "x": 229, + "y": 774, + "type": "block" + }, + { + "x": 259, + "y": 774, + "type": "common" + }, + { + "x": 79, + "y": 744, + "type": "common" + }, + { + "x": 109, + "y": 744, + "type": "common" + }, + { + "x": 139, + "y": 744, + "type": "common" + }, + { + "x": 169, + "y": 744, + "type": "common" + }, + { + "x": 199, + "y": 744, + "type": "common" + }, + { + "x": 229, + "y": 744, + "type": "common" + }, + { + "x": 259, + "y": 744, + "type": "common" + }, + { + "x": 79, + "y": 714, + "type": "common" + }, + { + "x": 109, + "y": 714, + "type": "common" + }, + { + "x": 139, + "y": 714, + "type": "common" + }, + { + "x": 169, + "y": 714, + "type": "common" + }, + { + "x": 199, + "y": 714, + "type": "common" + }, + { + "x": 229, + "y": 714, + "type": "common" + } + ], + "pipe": { + "x": 1017, + "y": 700, + "r": 46 + }, + "waypoints": [ + { + "x": 788, + "y": 609 + } + ], + "required": 5, + "ocdTarget": 10 +} diff --git a/assets/gamedata/gootower/level-039.json b/assets/gamedata/gootower/level-039.json new file mode 100644 index 0000000..39d2e69 --- /dev/null +++ b/assets/gamedata/gootower/level-039.json @@ -0,0 +1,337 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 39, + "name": "Blast Radius", + "chapter": 3, + "tip": "Drop a bomb by the fire and the soft rock goes with it. Or take the long way over.", + "element": "bomb", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + 0, + 850 + ], + [ + 1600, + 850 + ], + [ + 1600, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 737, + 675 + ], + [ + 817, + 675 + ], + [ + 817, + 850 + ], + [ + 737, + 850 + ] + ], + "destructible": true + }, + { + "kind": "fire", + "poly": [ + [ + 627, + 806 + ], + [ + 707, + 806 + ], + [ + 707, + 850 + ], + [ + 627, + 850 + ] + ] + } + ], + "balls": [ + { + "x": 368, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 430, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 399, + "y": 782, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 109, + "y": 834, + "type": "common" + }, + { + "x": 139, + "y": 834, + "type": "block" + }, + { + "x": 169, + "y": 834, + "type": "bomb" + }, + { + "x": 199, + "y": 834, + "type": "common" + }, + { + "x": 229, + "y": 834, + "type": "block" + }, + { + "x": 259, + "y": 834, + "type": "bomb" + }, + { + "x": 289, + "y": 834, + "type": "common" + }, + { + "x": 109, + "y": 804, + "type": "block" + }, + { + "x": 139, + "y": 804, + "type": "bomb" + }, + { + "x": 169, + "y": 804, + "type": "common" + }, + { + "x": 199, + "y": 804, + "type": "block" + }, + { + "x": 229, + "y": 804, + "type": "bomb" + }, + { + "x": 259, + "y": 804, + "type": "common" + }, + { + "x": 289, + "y": 804, + "type": "block" + }, + { + "x": 109, + "y": 774, + "type": "common" + }, + { + "x": 139, + "y": 774, + "type": "block" + }, + { + "x": 169, + "y": 774, + "type": "common" + }, + { + "x": 199, + "y": 774, + "type": "block" + }, + { + "x": 229, + "y": 774, + "type": "common" + }, + { + "x": 259, + "y": 774, + "type": "block" + }, + { + "x": 289, + "y": 774, + "type": "common" + }, + { + "x": 109, + "y": 744, + "type": "common" + }, + { + "x": 139, + "y": 744, + "type": "common" + }, + { + "x": 169, + "y": 744, + "type": "common" + }, + { + "x": 199, + "y": 744, + "type": "common" + }, + { + "x": 229, + "y": 744, + "type": "common" + }, + { + "x": 259, + "y": 744, + "type": "common" + }, + { + "x": 289, + "y": 744, + "type": "common" + }, + { + "x": 109, + "y": 714, + "type": "common" + }, + { + "x": 139, + "y": 714, + "type": "common" + }, + { + "x": 169, + "y": 714, + "type": "common" + }, + { + "x": 199, + "y": 714, + "type": "common" + }, + { + "x": 229, + "y": 714, + "type": "common" + }, + { + "x": 259, + "y": 714, + "type": "common" + } + ], + "pipe": { + "x": 1038, + "y": 700, + "r": 46 + }, + "waypoints": [ + { + "x": 777, + "y": 600 + } + ], + "required": 6, + "ocdTarget": 12 +} diff --git a/assets/gamedata/gootower/level-040.json b/assets/gamedata/gootower/level-040.json new file mode 100644 index 0000000..3d15b68 --- /dev/null +++ b/assets/gamedata/gootower/level-040.json @@ -0,0 +1,337 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 40, + "name": "Controlled Burn", + "chapter": 3, + "tip": "Drop a bomb by the fire and the soft rock goes with it. Or take the long way over.", + "element": "bomb", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + 0, + 850 + ], + [ + 1600, + 850 + ], + [ + 1600, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 718, + 664 + ], + [ + 798, + 664 + ], + [ + 798, + 850 + ], + [ + 718, + 850 + ] + ], + "destructible": true + }, + { + "kind": "fire", + "poly": [ + [ + 608, + 806 + ], + [ + 688, + 806 + ], + [ + 688, + 850 + ], + [ + 608, + 850 + ] + ] + } + ], + "balls": [ + { + "x": 360, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 422, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 391, + "y": 782, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 101, + "y": 834, + "type": "common" + }, + { + "x": 131, + "y": 834, + "type": "block" + }, + { + "x": 161, + "y": 834, + "type": "bomb" + }, + { + "x": 191, + "y": 834, + "type": "common" + }, + { + "x": 221, + "y": 834, + "type": "block" + }, + { + "x": 251, + "y": 834, + "type": "bomb" + }, + { + "x": 281, + "y": 834, + "type": "common" + }, + { + "x": 101, + "y": 804, + "type": "block" + }, + { + "x": 131, + "y": 804, + "type": "bomb" + }, + { + "x": 161, + "y": 804, + "type": "common" + }, + { + "x": 191, + "y": 804, + "type": "block" + }, + { + "x": 221, + "y": 804, + "type": "bomb" + }, + { + "x": 251, + "y": 804, + "type": "common" + }, + { + "x": 281, + "y": 804, + "type": "block" + }, + { + "x": 101, + "y": 774, + "type": "common" + }, + { + "x": 131, + "y": 774, + "type": "block" + }, + { + "x": 161, + "y": 774, + "type": "common" + }, + { + "x": 191, + "y": 774, + "type": "block" + }, + { + "x": 221, + "y": 774, + "type": "common" + }, + { + "x": 251, + "y": 774, + "type": "block" + }, + { + "x": 281, + "y": 774, + "type": "common" + }, + { + "x": 101, + "y": 744, + "type": "common" + }, + { + "x": 131, + "y": 744, + "type": "common" + }, + { + "x": 161, + "y": 744, + "type": "common" + }, + { + "x": 191, + "y": 744, + "type": "common" + }, + { + "x": 221, + "y": 744, + "type": "common" + }, + { + "x": 251, + "y": 744, + "type": "common" + }, + { + "x": 281, + "y": 744, + "type": "common" + }, + { + "x": 101, + "y": 714, + "type": "common" + }, + { + "x": 131, + "y": 714, + "type": "common" + }, + { + "x": 161, + "y": 714, + "type": "common" + }, + { + "x": 191, + "y": 714, + "type": "common" + }, + { + "x": 221, + "y": 714, + "type": "common" + }, + { + "x": 251, + "y": 714, + "type": "common" + } + ], + "pipe": { + "x": 1065, + "y": 700, + "r": 46 + }, + "waypoints": [ + { + "x": 758, + "y": 589 + } + ], + "required": 6, + "ocdTarget": 13 +} diff --git a/assets/gamedata/gootower/level-041.json b/assets/gamedata/gootower/level-041.json new file mode 100644 index 0000000..aa32b72 --- /dev/null +++ b/assets/gamedata/gootower/level-041.json @@ -0,0 +1,297 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 41, + "name": "The Machine", + "chapter": 3, + "tip": "The cog is solid and it is turning. Whatever it touches gets dragged along.", + "element": "gear", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + 0, + 850 + ], + [ + 1600, + 850 + ], + [ + 1600, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + } + ], + "balls": [ + { + "x": 260, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 322, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 291, + "y": 782, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 1000, + "y": 834, + "type": "common" + }, + { + "x": 1030, + "y": 834, + "type": "block" + }, + { + "x": 1060, + "y": 834, + "type": "bomb" + }, + { + "x": 1090, + "y": 834, + "type": "common" + }, + { + "x": 1120, + "y": 834, + "type": "block" + }, + { + "x": 1150, + "y": 834, + "type": "bomb" + }, + { + "x": 1180, + "y": 834, + "type": "common" + }, + { + "x": 1210, + "y": 834, + "type": "block" + }, + { + "x": 1240, + "y": 834, + "type": "bomb" + }, + { + "x": 1000, + "y": 804, + "type": "common" + }, + { + "x": 1030, + "y": 804, + "type": "block" + }, + { + "x": 1060, + "y": 804, + "type": "bomb" + }, + { + "x": 1090, + "y": 804, + "type": "common" + }, + { + "x": 1120, + "y": 804, + "type": "block" + }, + { + "x": 1150, + "y": 804, + "type": "common" + }, + { + "x": 1180, + "y": 804, + "type": "block" + }, + { + "x": 1210, + "y": 804, + "type": "common" + }, + { + "x": 1240, + "y": 804, + "type": "block" + }, + { + "x": 1000, + "y": 774, + "type": "common" + }, + { + "x": 1030, + "y": 774, + "type": "block" + }, + { + "x": 1060, + "y": 774, + "type": "common" + }, + { + "x": 1090, + "y": 774, + "type": "common" + }, + { + "x": 1120, + "y": 774, + "type": "common" + }, + { + "x": 1150, + "y": 774, + "type": "common" + }, + { + "x": 1180, + "y": 774, + "type": "common" + }, + { + "x": 1210, + "y": 774, + "type": "common" + }, + { + "x": 1240, + "y": 774, + "type": "common" + }, + { + "x": 1000, + "y": 744, + "type": "common" + }, + { + "x": 1030, + "y": 744, + "type": "common" + }, + { + "x": 1060, + "y": 744, + "type": "common" + }, + { + "x": 1090, + "y": 744, + "type": "common" + }, + { + "x": 1120, + "y": 744, + "type": "common" + }, + { + "x": 1150, + "y": 744, + "type": "common" + }, + { + "x": 1180, + "y": 744, + "type": "common" + } + ], + "pipe": { + "x": 1232, + "y": 581, + "r": 46 + }, + "gears": [ + { + "x": 756, + "y": 481, + "r": 112, + "teeth": 9, + "omega": -1.5957301009483635 + } + ], + "required": 6, + "ocdTarget": 13 +} diff --git a/assets/gamedata/gootower/level-042.json b/assets/gamedata/gootower/level-042.json new file mode 100644 index 0000000..cbe2079 --- /dev/null +++ b/assets/gamedata/gootower/level-042.json @@ -0,0 +1,297 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 42, + "name": "Grinding Gears", + "chapter": 3, + "tip": "The cog is solid and it is turning. Whatever it touches gets dragged along.", + "element": "gear", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + 0, + 850 + ], + [ + 1600, + 850 + ], + [ + 1600, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + } + ], + "balls": [ + { + "x": 258, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 320, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 289, + "y": 782, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 1000, + "y": 834, + "type": "common" + }, + { + "x": 1030, + "y": 834, + "type": "block" + }, + { + "x": 1060, + "y": 834, + "type": "bomb" + }, + { + "x": 1090, + "y": 834, + "type": "common" + }, + { + "x": 1120, + "y": 834, + "type": "block" + }, + { + "x": 1150, + "y": 834, + "type": "bomb" + }, + { + "x": 1180, + "y": 834, + "type": "common" + }, + { + "x": 1210, + "y": 834, + "type": "block" + }, + { + "x": 1240, + "y": 834, + "type": "bomb" + }, + { + "x": 1000, + "y": 804, + "type": "common" + }, + { + "x": 1030, + "y": 804, + "type": "block" + }, + { + "x": 1060, + "y": 804, + "type": "bomb" + }, + { + "x": 1090, + "y": 804, + "type": "common" + }, + { + "x": 1120, + "y": 804, + "type": "block" + }, + { + "x": 1150, + "y": 804, + "type": "common" + }, + { + "x": 1180, + "y": 804, + "type": "block" + }, + { + "x": 1210, + "y": 804, + "type": "common" + }, + { + "x": 1240, + "y": 804, + "type": "block" + }, + { + "x": 1000, + "y": 774, + "type": "common" + }, + { + "x": 1030, + "y": 774, + "type": "block" + }, + { + "x": 1060, + "y": 774, + "type": "common" + }, + { + "x": 1090, + "y": 774, + "type": "common" + }, + { + "x": 1120, + "y": 774, + "type": "common" + }, + { + "x": 1150, + "y": 774, + "type": "common" + }, + { + "x": 1180, + "y": 774, + "type": "common" + }, + { + "x": 1210, + "y": 774, + "type": "common" + }, + { + "x": 1240, + "y": 774, + "type": "common" + }, + { + "x": 1000, + "y": 744, + "type": "common" + }, + { + "x": 1030, + "y": 744, + "type": "common" + }, + { + "x": 1060, + "y": 744, + "type": "common" + }, + { + "x": 1090, + "y": 744, + "type": "common" + }, + { + "x": 1120, + "y": 744, + "type": "common" + }, + { + "x": 1150, + "y": 744, + "type": "common" + }, + { + "x": 1180, + "y": 744, + "type": "common" + } + ], + "pipe": { + "x": 1254, + "y": 569, + "r": 46 + }, + "gears": [ + { + "x": 775, + "y": 469, + "r": 117, + "teeth": 9, + "omega": -1.7502086996054276 + } + ], + "required": 7, + "ocdTarget": 15 +} diff --git a/assets/gamedata/gootower/level-043.json b/assets/gamedata/gootower/level-043.json new file mode 100644 index 0000000..31b632e --- /dev/null +++ b/assets/gamedata/gootower/level-043.json @@ -0,0 +1,297 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 43, + "name": "Flywheel", + "chapter": 3, + "tip": "The cog is solid and it is turning. Whatever it touches gets dragged along.", + "element": "gear", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + 0, + 850 + ], + [ + 1600, + 850 + ], + [ + 1600, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + } + ], + "balls": [ + { + "x": 286, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 348, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 317, + "y": 782, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 1000, + "y": 834, + "type": "common" + }, + { + "x": 1030, + "y": 834, + "type": "block" + }, + { + "x": 1060, + "y": 834, + "type": "bomb" + }, + { + "x": 1090, + "y": 834, + "type": "common" + }, + { + "x": 1120, + "y": 834, + "type": "block" + }, + { + "x": 1150, + "y": 834, + "type": "bomb" + }, + { + "x": 1180, + "y": 834, + "type": "common" + }, + { + "x": 1210, + "y": 834, + "type": "block" + }, + { + "x": 1240, + "y": 834, + "type": "bomb" + }, + { + "x": 1000, + "y": 804, + "type": "common" + }, + { + "x": 1030, + "y": 804, + "type": "block" + }, + { + "x": 1060, + "y": 804, + "type": "bomb" + }, + { + "x": 1090, + "y": 804, + "type": "common" + }, + { + "x": 1120, + "y": 804, + "type": "block" + }, + { + "x": 1150, + "y": 804, + "type": "common" + }, + { + "x": 1180, + "y": 804, + "type": "block" + }, + { + "x": 1210, + "y": 804, + "type": "common" + }, + { + "x": 1240, + "y": 804, + "type": "block" + }, + { + "x": 1000, + "y": 774, + "type": "common" + }, + { + "x": 1030, + "y": 774, + "type": "block" + }, + { + "x": 1060, + "y": 774, + "type": "common" + }, + { + "x": 1090, + "y": 774, + "type": "common" + }, + { + "x": 1120, + "y": 774, + "type": "common" + }, + { + "x": 1150, + "y": 774, + "type": "common" + }, + { + "x": 1180, + "y": 774, + "type": "common" + }, + { + "x": 1210, + "y": 774, + "type": "common" + }, + { + "x": 1240, + "y": 774, + "type": "common" + }, + { + "x": 1000, + "y": 744, + "type": "common" + }, + { + "x": 1030, + "y": 744, + "type": "common" + }, + { + "x": 1060, + "y": 744, + "type": "common" + }, + { + "x": 1090, + "y": 744, + "type": "common" + }, + { + "x": 1120, + "y": 744, + "type": "common" + }, + { + "x": 1150, + "y": 744, + "type": "common" + }, + { + "x": 1180, + "y": 744, + "type": "common" + } + ], + "pipe": { + "x": 1278, + "y": 556, + "r": 46 + }, + "gears": [ + { + "x": 816, + "y": 456, + "r": 122, + "teeth": 9, + "omega": 1.9166405162680893 + } + ], + "required": 8, + "ocdTarget": 17 +} diff --git a/assets/gamedata/gootower/level-044.json b/assets/gamedata/gootower/level-044.json new file mode 100644 index 0000000..0d3c817 --- /dev/null +++ b/assets/gamedata/gootower/level-044.json @@ -0,0 +1,314 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 44, + "name": "Under the Works", + "chapter": 3, + "tip": "You cannot build through rock. Come out from under it first.", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + 0, + 850 + ], + [ + 1600, + 850 + ], + [ + 1600, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 260, + 573 + ], + [ + 810, + 573 + ], + [ + 810, + 643 + ], + [ + 260, + 643 + ] + ] + } + ], + "balls": [ + { + "x": 495, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 557, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 526, + "y": 782, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 930, + "y": 834, + "type": "common" + }, + { + "x": 960, + "y": 834, + "type": "block" + }, + { + "x": 990, + "y": 834, + "type": "bomb" + }, + { + "x": 1020, + "y": 834, + "type": "common" + }, + { + "x": 1050, + "y": 834, + "type": "block" + }, + { + "x": 1080, + "y": 834, + "type": "bomb" + }, + { + "x": 1110, + "y": 834, + "type": "common" + }, + { + "x": 1140, + "y": 834, + "type": "block" + }, + { + "x": 1170, + "y": 834, + "type": "bomb" + }, + { + "x": 1200, + "y": 834, + "type": "common" + }, + { + "x": 1230, + "y": 834, + "type": "block" + }, + { + "x": 930, + "y": 804, + "type": "bomb" + }, + { + "x": 960, + "y": 804, + "type": "common" + }, + { + "x": 990, + "y": 804, + "type": "block" + }, + { + "x": 1020, + "y": 804, + "type": "common" + }, + { + "x": 1050, + "y": 804, + "type": "block" + }, + { + "x": 1080, + "y": 804, + "type": "common" + }, + { + "x": 1110, + "y": 804, + "type": "block" + }, + { + "x": 1140, + "y": 804, + "type": "common" + }, + { + "x": 1170, + "y": 804, + "type": "block" + }, + { + "x": 1200, + "y": 804, + "type": "common" + }, + { + "x": 1230, + "y": 804, + "type": "common" + }, + { + "x": 930, + "y": 774, + "type": "common" + }, + { + "x": 960, + "y": 774, + "type": "common" + }, + { + "x": 990, + "y": 774, + "type": "common" + }, + { + "x": 1020, + "y": 774, + "type": "common" + }, + { + "x": 1050, + "y": 774, + "type": "common" + }, + { + "x": 1080, + "y": 774, + "type": "common" + }, + { + "x": 1110, + "y": 774, + "type": "common" + }, + { + "x": 1140, + "y": 774, + "type": "common" + }, + { + "x": 1170, + "y": 774, + "type": "common" + }, + { + "x": 1200, + "y": 774, + "type": "common" + }, + { + "x": 1230, + "y": 774, + "type": "common" + }, + { + "x": 930, + "y": 744, + "type": "common" + } + ], + "pipe": { + "x": 960, + "y": 513, + "r": 46 + }, + "waypoints": [ + { + "x": 850, + "y": 593 + } + ], + "required": 6, + "ocdTarget": 13 +} diff --git a/assets/gamedata/gootower/level-045.json b/assets/gamedata/gootower/level-045.json new file mode 100644 index 0000000..70a11f7 --- /dev/null +++ b/assets/gamedata/gootower/level-045.json @@ -0,0 +1,314 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 45, + "name": "Assembly", + "chapter": 3, + "tip": "You cannot build through rock. Come out from under it first.", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + 0, + 850 + ], + [ + 1600, + 850 + ], + [ + 1600, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 260, + 560 + ], + [ + 831, + 560 + ], + [ + 831, + 630 + ], + [ + 260, + 630 + ] + ] + } + ], + "balls": [ + { + "x": 546, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 608, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 577, + "y": 782, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 951, + "y": 834, + "type": "common" + }, + { + "x": 981, + "y": 834, + "type": "block" + }, + { + "x": 1011, + "y": 834, + "type": "bomb" + }, + { + "x": 1041, + "y": 834, + "type": "common" + }, + { + "x": 1071, + "y": 834, + "type": "block" + }, + { + "x": 1101, + "y": 834, + "type": "bomb" + }, + { + "x": 1131, + "y": 834, + "type": "common" + }, + { + "x": 1161, + "y": 834, + "type": "block" + }, + { + "x": 1191, + "y": 834, + "type": "bomb" + }, + { + "x": 1221, + "y": 834, + "type": "common" + }, + { + "x": 1251, + "y": 834, + "type": "block" + }, + { + "x": 951, + "y": 804, + "type": "bomb" + }, + { + "x": 981, + "y": 804, + "type": "common" + }, + { + "x": 1011, + "y": 804, + "type": "block" + }, + { + "x": 1041, + "y": 804, + "type": "common" + }, + { + "x": 1071, + "y": 804, + "type": "block" + }, + { + "x": 1101, + "y": 804, + "type": "common" + }, + { + "x": 1131, + "y": 804, + "type": "block" + }, + { + "x": 1161, + "y": 804, + "type": "common" + }, + { + "x": 1191, + "y": 804, + "type": "block" + }, + { + "x": 1221, + "y": 804, + "type": "common" + }, + { + "x": 1251, + "y": 804, + "type": "common" + }, + { + "x": 951, + "y": 774, + "type": "common" + }, + { + "x": 981, + "y": 774, + "type": "common" + }, + { + "x": 1011, + "y": 774, + "type": "common" + }, + { + "x": 1041, + "y": 774, + "type": "common" + }, + { + "x": 1071, + "y": 774, + "type": "common" + }, + { + "x": 1101, + "y": 774, + "type": "common" + }, + { + "x": 1131, + "y": 774, + "type": "common" + }, + { + "x": 1161, + "y": 774, + "type": "common" + }, + { + "x": 1191, + "y": 774, + "type": "common" + }, + { + "x": 1221, + "y": 774, + "type": "common" + }, + { + "x": 1251, + "y": 774, + "type": "common" + }, + { + "x": 951, + "y": 744, + "type": "common" + } + ], + "pipe": { + "x": 981, + "y": 500, + "r": 46 + }, + "waypoints": [ + { + "x": 871, + "y": 580 + } + ], + "required": 7, + "ocdTarget": 15 +} diff --git a/assets/gamedata/gootower/level-046.json b/assets/gamedata/gootower/level-046.json new file mode 100644 index 0000000..1f15a35 --- /dev/null +++ b/assets/gamedata/gootower/level-046.json @@ -0,0 +1,335 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 46, + "name": "Handhold", + "chapter": 4, + "tip": "Anchor goo sticks straight to rock. The pillars are fair game.", + "element": "anchor", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + 0, + 850 + ], + [ + 1600, + 850 + ], + [ + 1600, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 420, + 349 + ], + [ + 480, + 349 + ], + [ + 480, + 850 + ], + [ + 420, + 850 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1040, + 349 + ], + [ + 1100, + 349 + ], + [ + 1100, + 850 + ], + [ + 1040, + 850 + ] + ] + } + ], + "balls": [ + { + "x": 729, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 791, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 760, + "y": 782, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 870, + "y": 834, + "type": "pokey" + }, + { + "x": 900, + "y": 834, + "type": "anchor" + }, + { + "x": 930, + "y": 834, + "type": "common" + }, + { + "x": 960, + "y": 834, + "type": "pokey" + }, + { + "x": 990, + "y": 834, + "type": "anchor" + }, + { + "x": 1020, + "y": 834, + "type": "common" + }, + { + "x": 870, + "y": 804, + "type": "pokey" + }, + { + "x": 900, + "y": 804, + "type": "anchor" + }, + { + "x": 930, + "y": 804, + "type": "common" + }, + { + "x": 960, + "y": 804, + "type": "pokey" + }, + { + "x": 990, + "y": 804, + "type": "anchor" + }, + { + "x": 1020, + "y": 804, + "type": "common" + }, + { + "x": 870, + "y": 774, + "type": "pokey" + }, + { + "x": 900, + "y": 774, + "type": "anchor" + }, + { + "x": 930, + "y": 774, + "type": "common" + }, + { + "x": 960, + "y": 774, + "type": "pokey" + }, + { + "x": 990, + "y": 774, + "type": "common" + }, + { + "x": 1020, + "y": 774, + "type": "pokey" + }, + { + "x": 870, + "y": 744, + "type": "common" + }, + { + "x": 900, + "y": 744, + "type": "pokey" + }, + { + "x": 930, + "y": 744, + "type": "common" + }, + { + "x": 960, + "y": 744, + "type": "common" + }, + { + "x": 990, + "y": 744, + "type": "common" + }, + { + "x": 1020, + "y": 744, + "type": "common" + }, + { + "x": 870, + "y": 714, + "type": "common" + }, + { + "x": 900, + "y": 714, + "type": "common" + }, + { + "x": 930, + "y": 714, + "type": "common" + }, + { + "x": 960, + "y": 714, + "type": "common" + }, + { + "x": 990, + "y": 714, + "type": "common" + }, + { + "x": 1020, + "y": 714, + "type": "common" + }, + { + "x": 870, + "y": 684, + "type": "common" + }, + { + "x": 900, + "y": 684, + "type": "common" + }, + { + "x": 930, + "y": 684, + "type": "common" + }, + { + "x": 960, + "y": 684, + "type": "common" + }, + { + "x": 990, + "y": 684, + "type": "common" + } + ], + "pipe": { + "x": 760, + "y": 409, + "r": 46 + }, + "required": 5, + "ocdTarget": 10 +} diff --git a/assets/gamedata/gootower/level-047.json b/assets/gamedata/gootower/level-047.json new file mode 100644 index 0000000..049585d --- /dev/null +++ b/assets/gamedata/gootower/level-047.json @@ -0,0 +1,335 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 47, + "name": "Two Pillars", + "chapter": 4, + "tip": "Anchor goo sticks straight to rock. The pillars are fair game.", + "element": "anchor", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + 0, + 850 + ], + [ + 1600, + 850 + ], + [ + 1600, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 420, + 342 + ], + [ + 480, + 342 + ], + [ + 480, + 850 + ], + [ + 420, + 850 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1040, + 342 + ], + [ + 1100, + 342 + ], + [ + 1100, + 850 + ], + [ + 1040, + 850 + ] + ] + } + ], + "balls": [ + { + "x": 729, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 791, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 760, + "y": 782, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 870, + "y": 834, + "type": "pokey" + }, + { + "x": 900, + "y": 834, + "type": "anchor" + }, + { + "x": 930, + "y": 834, + "type": "common" + }, + { + "x": 960, + "y": 834, + "type": "pokey" + }, + { + "x": 990, + "y": 834, + "type": "anchor" + }, + { + "x": 1020, + "y": 834, + "type": "common" + }, + { + "x": 870, + "y": 804, + "type": "pokey" + }, + { + "x": 900, + "y": 804, + "type": "anchor" + }, + { + "x": 930, + "y": 804, + "type": "common" + }, + { + "x": 960, + "y": 804, + "type": "pokey" + }, + { + "x": 990, + "y": 804, + "type": "anchor" + }, + { + "x": 1020, + "y": 804, + "type": "common" + }, + { + "x": 870, + "y": 774, + "type": "pokey" + }, + { + "x": 900, + "y": 774, + "type": "anchor" + }, + { + "x": 930, + "y": 774, + "type": "common" + }, + { + "x": 960, + "y": 774, + "type": "pokey" + }, + { + "x": 990, + "y": 774, + "type": "common" + }, + { + "x": 1020, + "y": 774, + "type": "pokey" + }, + { + "x": 870, + "y": 744, + "type": "common" + }, + { + "x": 900, + "y": 744, + "type": "pokey" + }, + { + "x": 930, + "y": 744, + "type": "common" + }, + { + "x": 960, + "y": 744, + "type": "common" + }, + { + "x": 990, + "y": 744, + "type": "common" + }, + { + "x": 1020, + "y": 744, + "type": "common" + }, + { + "x": 870, + "y": 714, + "type": "common" + }, + { + "x": 900, + "y": 714, + "type": "common" + }, + { + "x": 930, + "y": 714, + "type": "common" + }, + { + "x": 960, + "y": 714, + "type": "common" + }, + { + "x": 990, + "y": 714, + "type": "common" + }, + { + "x": 1020, + "y": 714, + "type": "common" + }, + { + "x": 870, + "y": 684, + "type": "common" + }, + { + "x": 900, + "y": 684, + "type": "common" + }, + { + "x": 930, + "y": 684, + "type": "common" + }, + { + "x": 960, + "y": 684, + "type": "common" + }, + { + "x": 990, + "y": 684, + "type": "common" + } + ], + "pipe": { + "x": 760, + "y": 402, + "r": 46 + }, + "required": 5, + "ocdTarget": 10 +} diff --git a/assets/gamedata/gootower/level-048.json b/assets/gamedata/gootower/level-048.json new file mode 100644 index 0000000..92d3ddb --- /dev/null +++ b/assets/gamedata/gootower/level-048.json @@ -0,0 +1,335 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 48, + "name": "Stepping Up", + "chapter": 4, + "tip": "Anchor goo sticks straight to rock. The pillars are fair game.", + "element": "anchor", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + 0, + 850 + ], + [ + 1600, + 850 + ], + [ + 1600, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 420, + 328 + ], + [ + 480, + 328 + ], + [ + 480, + 850 + ], + [ + 420, + 850 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1040, + 328 + ], + [ + 1100, + 328 + ], + [ + 1100, + 850 + ], + [ + 1040, + 850 + ] + ] + } + ], + "balls": [ + { + "x": 729, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 791, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 760, + "y": 782, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 870, + "y": 834, + "type": "pokey" + }, + { + "x": 900, + "y": 834, + "type": "anchor" + }, + { + "x": 930, + "y": 834, + "type": "common" + }, + { + "x": 960, + "y": 834, + "type": "pokey" + }, + { + "x": 990, + "y": 834, + "type": "anchor" + }, + { + "x": 1020, + "y": 834, + "type": "common" + }, + { + "x": 870, + "y": 804, + "type": "pokey" + }, + { + "x": 900, + "y": 804, + "type": "anchor" + }, + { + "x": 930, + "y": 804, + "type": "common" + }, + { + "x": 960, + "y": 804, + "type": "pokey" + }, + { + "x": 990, + "y": 804, + "type": "anchor" + }, + { + "x": 1020, + "y": 804, + "type": "common" + }, + { + "x": 870, + "y": 774, + "type": "pokey" + }, + { + "x": 900, + "y": 774, + "type": "anchor" + }, + { + "x": 930, + "y": 774, + "type": "common" + }, + { + "x": 960, + "y": 774, + "type": "pokey" + }, + { + "x": 990, + "y": 774, + "type": "common" + }, + { + "x": 1020, + "y": 774, + "type": "pokey" + }, + { + "x": 870, + "y": 744, + "type": "common" + }, + { + "x": 900, + "y": 744, + "type": "pokey" + }, + { + "x": 930, + "y": 744, + "type": "common" + }, + { + "x": 960, + "y": 744, + "type": "common" + }, + { + "x": 990, + "y": 744, + "type": "common" + }, + { + "x": 1020, + "y": 744, + "type": "common" + }, + { + "x": 870, + "y": 714, + "type": "common" + }, + { + "x": 900, + "y": 714, + "type": "common" + }, + { + "x": 930, + "y": 714, + "type": "common" + }, + { + "x": 960, + "y": 714, + "type": "common" + }, + { + "x": 990, + "y": 714, + "type": "common" + }, + { + "x": 1020, + "y": 714, + "type": "common" + }, + { + "x": 870, + "y": 684, + "type": "common" + }, + { + "x": 900, + "y": 684, + "type": "common" + }, + { + "x": 930, + "y": 684, + "type": "common" + }, + { + "x": 960, + "y": 684, + "type": "common" + }, + { + "x": 990, + "y": 684, + "type": "common" + } + ], + "pipe": { + "x": 760, + "y": 388, + "r": 46 + }, + "required": 6, + "ocdTarget": 12 +} diff --git a/assets/gamedata/gootower/level-049.json b/assets/gamedata/gootower/level-049.json new file mode 100644 index 0000000..e7ea843 --- /dev/null +++ b/assets/gamedata/gootower/level-049.json @@ -0,0 +1,383 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 49, + "name": "The Face", + "chapter": 4, + "tip": "Pokey goo grips bare rock and needs no friends. Start from the wall.", + "element": "anchor", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + 0, + 850 + ], + [ + 1600, + 850 + ], + [ + 1600, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 210, + 180 + ], + [ + 300, + 180 + ], + [ + 300, + 800 + ], + [ + 210, + 800 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1200, + 180 + ], + [ + 1290, + 180 + ], + [ + 1290, + 800 + ], + [ + 1200, + 800 + ] + ] + }, + { + "kind": "spike", + "poly": [ + [ + 300, + 930 + ], + [ + 1200, + 930 + ], + [ + 1200, + 1000 + ], + [ + 300, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 300, + 631 + ], + [ + 600, + 631 + ], + [ + 600, + 707 + ], + [ + 300, + 707 + ] + ] + } + ], + "balls": [ + { + "x": 340, + "y": 587, + "type": "pokey", + "pinned": true + }, + { + "x": 340, + "y": 525, + "type": "pokey", + "pinned": true + }, + { + "x": 398, + "y": 556, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 430, + "y": 615, + "type": "pokey" + }, + { + "x": 460, + "y": 615, + "type": "anchor" + }, + { + "x": 490, + "y": 615, + "type": "common" + }, + { + "x": 520, + "y": 615, + "type": "pokey" + }, + { + "x": 550, + "y": 615, + "type": "anchor" + }, + { + "x": 580, + "y": 615, + "type": "common" + }, + { + "x": 430, + "y": 585, + "type": "pokey" + }, + { + "x": 460, + "y": 585, + "type": "anchor" + }, + { + "x": 490, + "y": 585, + "type": "common" + }, + { + "x": 520, + "y": 585, + "type": "pokey" + }, + { + "x": 550, + "y": 585, + "type": "anchor" + }, + { + "x": 580, + "y": 585, + "type": "common" + }, + { + "x": 430, + "y": 555, + "type": "pokey" + }, + { + "x": 460, + "y": 555, + "type": "anchor" + }, + { + "x": 490, + "y": 555, + "type": "common" + }, + { + "x": 520, + "y": 555, + "type": "pokey" + }, + { + "x": 550, + "y": 555, + "type": "common" + }, + { + "x": 580, + "y": 555, + "type": "pokey" + }, + { + "x": 430, + "y": 525, + "type": "common" + }, + { + "x": 460, + "y": 525, + "type": "pokey" + }, + { + "x": 490, + "y": 525, + "type": "common" + }, + { + "x": 520, + "y": 525, + "type": "common" + }, + { + "x": 550, + "y": 525, + "type": "common" + }, + { + "x": 580, + "y": 525, + "type": "common" + }, + { + "x": 430, + "y": 495, + "type": "common" + }, + { + "x": 460, + "y": 495, + "type": "common" + }, + { + "x": 490, + "y": 495, + "type": "common" + }, + { + "x": 520, + "y": 495, + "type": "common" + }, + { + "x": 550, + "y": 495, + "type": "common" + }, + { + "x": 580, + "y": 495, + "type": "common" + }, + { + "x": 430, + "y": 465, + "type": "common" + }, + { + "x": 460, + "y": 465, + "type": "common" + }, + { + "x": 490, + "y": 465, + "type": "common" + }, + { + "x": 520, + "y": 465, + "type": "common" + }, + { + "x": 550, + "y": 465, + "type": "common" + } + ], + "pipe": { + "x": 1150, + "y": 450, + "r": 46 + }, + "waypoints": [ + { + "x": 740, + "y": 444 + } + ], + "required": 5, + "ocdTarget": 10 +} diff --git a/assets/gamedata/gootower/level-050.json b/assets/gamedata/gootower/level-050.json new file mode 100644 index 0000000..c58537d --- /dev/null +++ b/assets/gamedata/gootower/level-050.json @@ -0,0 +1,383 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 50, + "name": "Sheer", + "chapter": 4, + "tip": "Pokey goo grips bare rock and needs no friends. Start from the wall.", + "element": "anchor", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + 0, + 850 + ], + [ + 1600, + 850 + ], + [ + 1600, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 210, + 180 + ], + [ + 300, + 180 + ], + [ + 300, + 800 + ], + [ + 210, + 800 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1200, + 180 + ], + [ + 1290, + 180 + ], + [ + 1290, + 800 + ], + [ + 1200, + 800 + ] + ] + }, + { + "kind": "spike", + "poly": [ + [ + 300, + 930 + ], + [ + 1200, + 930 + ], + [ + 1200, + 1000 + ], + [ + 300, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 300, + 621 + ], + [ + 600, + 621 + ], + [ + 600, + 697 + ], + [ + 300, + 697 + ] + ] + } + ], + "balls": [ + { + "x": 340, + "y": 577, + "type": "pokey", + "pinned": true + }, + { + "x": 340, + "y": 515, + "type": "pokey", + "pinned": true + }, + { + "x": 398, + "y": 546, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 430, + "y": 605, + "type": "pokey" + }, + { + "x": 460, + "y": 605, + "type": "anchor" + }, + { + "x": 490, + "y": 605, + "type": "common" + }, + { + "x": 520, + "y": 605, + "type": "pokey" + }, + { + "x": 550, + "y": 605, + "type": "anchor" + }, + { + "x": 580, + "y": 605, + "type": "common" + }, + { + "x": 430, + "y": 575, + "type": "pokey" + }, + { + "x": 460, + "y": 575, + "type": "anchor" + }, + { + "x": 490, + "y": 575, + "type": "common" + }, + { + "x": 520, + "y": 575, + "type": "pokey" + }, + { + "x": 550, + "y": 575, + "type": "anchor" + }, + { + "x": 580, + "y": 575, + "type": "common" + }, + { + "x": 430, + "y": 545, + "type": "pokey" + }, + { + "x": 460, + "y": 545, + "type": "anchor" + }, + { + "x": 490, + "y": 545, + "type": "common" + }, + { + "x": 520, + "y": 545, + "type": "pokey" + }, + { + "x": 550, + "y": 545, + "type": "common" + }, + { + "x": 580, + "y": 545, + "type": "pokey" + }, + { + "x": 430, + "y": 515, + "type": "common" + }, + { + "x": 460, + "y": 515, + "type": "pokey" + }, + { + "x": 490, + "y": 515, + "type": "common" + }, + { + "x": 520, + "y": 515, + "type": "common" + }, + { + "x": 550, + "y": 515, + "type": "common" + }, + { + "x": 580, + "y": 515, + "type": "common" + }, + { + "x": 430, + "y": 485, + "type": "common" + }, + { + "x": 460, + "y": 485, + "type": "common" + }, + { + "x": 490, + "y": 485, + "type": "common" + }, + { + "x": 520, + "y": 485, + "type": "common" + }, + { + "x": 550, + "y": 485, + "type": "common" + }, + { + "x": 580, + "y": 485, + "type": "common" + }, + { + "x": 430, + "y": 455, + "type": "common" + }, + { + "x": 460, + "y": 455, + "type": "common" + }, + { + "x": 490, + "y": 455, + "type": "common" + }, + { + "x": 520, + "y": 455, + "type": "common" + }, + { + "x": 550, + "y": 455, + "type": "common" + } + ], + "pipe": { + "x": 1150, + "y": 443, + "r": 46 + }, + "waypoints": [ + { + "x": 740, + "y": 438 + } + ], + "required": 5, + "ocdTarget": 10 +} diff --git a/assets/gamedata/gootower/level-051.json b/assets/gamedata/gootower/level-051.json new file mode 100644 index 0000000..f6b4413 --- /dev/null +++ b/assets/gamedata/gootower/level-051.json @@ -0,0 +1,383 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 51, + "name": "Traverse", + "chapter": 4, + "tip": "Pokey goo grips bare rock and needs no friends. Start from the wall.", + "element": "anchor", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + 0, + 850 + ], + [ + 1600, + 850 + ], + [ + 1600, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 210, + 180 + ], + [ + 300, + 180 + ], + [ + 300, + 800 + ], + [ + 210, + 800 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1200, + 180 + ], + [ + 1290, + 180 + ], + [ + 1290, + 800 + ], + [ + 1200, + 800 + ] + ] + }, + { + "kind": "spike", + "poly": [ + [ + 300, + 930 + ], + [ + 1200, + 930 + ], + [ + 1200, + 1000 + ], + [ + 300, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 300, + 610 + ], + [ + 600, + 610 + ], + [ + 600, + 686 + ], + [ + 300, + 686 + ] + ] + } + ], + "balls": [ + { + "x": 340, + "y": 566, + "type": "pokey", + "pinned": true + }, + { + "x": 340, + "y": 504, + "type": "pokey", + "pinned": true + }, + { + "x": 398, + "y": 535, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 430, + "y": 594, + "type": "pokey" + }, + { + "x": 460, + "y": 594, + "type": "anchor" + }, + { + "x": 490, + "y": 594, + "type": "common" + }, + { + "x": 520, + "y": 594, + "type": "pokey" + }, + { + "x": 550, + "y": 594, + "type": "anchor" + }, + { + "x": 580, + "y": 594, + "type": "common" + }, + { + "x": 430, + "y": 564, + "type": "pokey" + }, + { + "x": 460, + "y": 564, + "type": "anchor" + }, + { + "x": 490, + "y": 564, + "type": "common" + }, + { + "x": 520, + "y": 564, + "type": "pokey" + }, + { + "x": 550, + "y": 564, + "type": "anchor" + }, + { + "x": 580, + "y": 564, + "type": "common" + }, + { + "x": 430, + "y": 534, + "type": "pokey" + }, + { + "x": 460, + "y": 534, + "type": "anchor" + }, + { + "x": 490, + "y": 534, + "type": "common" + }, + { + "x": 520, + "y": 534, + "type": "pokey" + }, + { + "x": 550, + "y": 534, + "type": "common" + }, + { + "x": 580, + "y": 534, + "type": "pokey" + }, + { + "x": 430, + "y": 504, + "type": "common" + }, + { + "x": 460, + "y": 504, + "type": "pokey" + }, + { + "x": 490, + "y": 504, + "type": "common" + }, + { + "x": 520, + "y": 504, + "type": "common" + }, + { + "x": 550, + "y": 504, + "type": "common" + }, + { + "x": 580, + "y": 504, + "type": "common" + }, + { + "x": 430, + "y": 474, + "type": "common" + }, + { + "x": 460, + "y": 474, + "type": "common" + }, + { + "x": 490, + "y": 474, + "type": "common" + }, + { + "x": 520, + "y": 474, + "type": "common" + }, + { + "x": 550, + "y": 474, + "type": "common" + }, + { + "x": 580, + "y": 474, + "type": "common" + }, + { + "x": 430, + "y": 444, + "type": "common" + }, + { + "x": 460, + "y": 444, + "type": "common" + }, + { + "x": 490, + "y": 444, + "type": "common" + }, + { + "x": 520, + "y": 444, + "type": "common" + }, + { + "x": 550, + "y": 444, + "type": "common" + } + ], + "pipe": { + "x": 1150, + "y": 435, + "r": 46 + }, + "waypoints": [ + { + "x": 740, + "y": 433 + } + ], + "required": 6, + "ocdTarget": 12 +} diff --git a/assets/gamedata/gootower/level-052.json b/assets/gamedata/gootower/level-052.json new file mode 100644 index 0000000..ba325b9 --- /dev/null +++ b/assets/gamedata/gootower/level-052.json @@ -0,0 +1,383 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 52, + "name": "Grip", + "chapter": 4, + "tip": "Pokey goo grips bare rock and needs no friends. Start from the wall.", + "element": "anchor", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + 0, + 850 + ], + [ + 1600, + 850 + ], + [ + 1600, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 210, + 180 + ], + [ + 300, + 180 + ], + [ + 300, + 800 + ], + [ + 210, + 800 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1200, + 180 + ], + [ + 1290, + 180 + ], + [ + 1290, + 800 + ], + [ + 1200, + 800 + ] + ] + }, + { + "kind": "spike", + "poly": [ + [ + 300, + 930 + ], + [ + 1200, + 930 + ], + [ + 1200, + 1000 + ], + [ + 300, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 300, + 605 + ], + [ + 600, + 605 + ], + [ + 600, + 681 + ], + [ + 300, + 681 + ] + ] + } + ], + "balls": [ + { + "x": 340, + "y": 561, + "type": "pokey", + "pinned": true + }, + { + "x": 340, + "y": 499, + "type": "pokey", + "pinned": true + }, + { + "x": 398, + "y": 530, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 430, + "y": 589, + "type": "pokey" + }, + { + "x": 460, + "y": 589, + "type": "anchor" + }, + { + "x": 490, + "y": 589, + "type": "common" + }, + { + "x": 520, + "y": 589, + "type": "pokey" + }, + { + "x": 550, + "y": 589, + "type": "anchor" + }, + { + "x": 580, + "y": 589, + "type": "common" + }, + { + "x": 430, + "y": 559, + "type": "pokey" + }, + { + "x": 460, + "y": 559, + "type": "anchor" + }, + { + "x": 490, + "y": 559, + "type": "common" + }, + { + "x": 520, + "y": 559, + "type": "pokey" + }, + { + "x": 550, + "y": 559, + "type": "anchor" + }, + { + "x": 580, + "y": 559, + "type": "common" + }, + { + "x": 430, + "y": 529, + "type": "pokey" + }, + { + "x": 460, + "y": 529, + "type": "anchor" + }, + { + "x": 490, + "y": 529, + "type": "common" + }, + { + "x": 520, + "y": 529, + "type": "pokey" + }, + { + "x": 550, + "y": 529, + "type": "common" + }, + { + "x": 580, + "y": 529, + "type": "pokey" + }, + { + "x": 430, + "y": 499, + "type": "common" + }, + { + "x": 460, + "y": 499, + "type": "pokey" + }, + { + "x": 490, + "y": 499, + "type": "common" + }, + { + "x": 520, + "y": 499, + "type": "common" + }, + { + "x": 550, + "y": 499, + "type": "common" + }, + { + "x": 580, + "y": 499, + "type": "common" + }, + { + "x": 430, + "y": 469, + "type": "common" + }, + { + "x": 460, + "y": 469, + "type": "common" + }, + { + "x": 490, + "y": 469, + "type": "common" + }, + { + "x": 520, + "y": 469, + "type": "common" + }, + { + "x": 550, + "y": 469, + "type": "common" + }, + { + "x": 580, + "y": 469, + "type": "common" + }, + { + "x": 430, + "y": 439, + "type": "common" + }, + { + "x": 460, + "y": 439, + "type": "common" + }, + { + "x": 490, + "y": 439, + "type": "common" + }, + { + "x": 520, + "y": 439, + "type": "common" + }, + { + "x": 550, + "y": 439, + "type": "common" + } + ], + "pipe": { + "x": 1150, + "y": 431, + "r": 46 + }, + "waypoints": [ + { + "x": 740, + "y": 431 + } + ], + "required": 6, + "ocdTarget": 12 +} diff --git a/assets/gamedata/gootower/level-053.json b/assets/gamedata/gootower/level-053.json new file mode 100644 index 0000000..e659aaa --- /dev/null +++ b/assets/gamedata/gootower/level-053.json @@ -0,0 +1,292 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 53, + "name": "Overhanging", + "chapter": 4, + "tip": "Brace as you go. An unbraced column leans, and once it leans it keeps leaning.", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + 0, + 850 + ], + [ + 1600, + 850 + ], + [ + 1600, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + } + ], + "balls": [ + { + "x": 730, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 792, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 761, + "y": 782, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 1021, + "y": 834, + "type": "pokey" + }, + { + "x": 1051, + "y": 834, + "type": "anchor" + }, + { + "x": 1081, + "y": 834, + "type": "common" + }, + { + "x": 1111, + "y": 834, + "type": "pokey" + }, + { + "x": 1141, + "y": 834, + "type": "anchor" + }, + { + "x": 1171, + "y": 834, + "type": "common" + }, + { + "x": 1201, + "y": 834, + "type": "pokey" + }, + { + "x": 1231, + "y": 834, + "type": "anchor" + }, + { + "x": 1261, + "y": 834, + "type": "common" + }, + { + "x": 1291, + "y": 834, + "type": "pokey" + }, + { + "x": 1321, + "y": 834, + "type": "anchor" + }, + { + "x": 1351, + "y": 834, + "type": "common" + }, + { + "x": 1021, + "y": 804, + "type": "pokey" + }, + { + "x": 1051, + "y": 804, + "type": "anchor" + }, + { + "x": 1081, + "y": 804, + "type": "common" + }, + { + "x": 1111, + "y": 804, + "type": "pokey" + }, + { + "x": 1141, + "y": 804, + "type": "common" + }, + { + "x": 1171, + "y": 804, + "type": "pokey" + }, + { + "x": 1201, + "y": 804, + "type": "common" + }, + { + "x": 1231, + "y": 804, + "type": "pokey" + }, + { + "x": 1261, + "y": 804, + "type": "common" + }, + { + "x": 1291, + "y": 804, + "type": "common" + }, + { + "x": 1321, + "y": 804, + "type": "common" + }, + { + "x": 1351, + "y": 804, + "type": "common" + }, + { + "x": 1021, + "y": 774, + "type": "common" + }, + { + "x": 1051, + "y": 774, + "type": "common" + }, + { + "x": 1081, + "y": 774, + "type": "common" + }, + { + "x": 1111, + "y": 774, + "type": "common" + }, + { + "x": 1141, + "y": 774, + "type": "common" + }, + { + "x": 1171, + "y": 774, + "type": "common" + }, + { + "x": 1201, + "y": 774, + "type": "common" + }, + { + "x": 1231, + "y": 774, + "type": "common" + }, + { + "x": 1261, + "y": 774, + "type": "common" + }, + { + "x": 1291, + "y": 774, + "type": "common" + }, + { + "x": 1321, + "y": 774, + "type": "common" + } + ], + "pipe": { + "x": 761, + "y": 425, + "r": 46 + }, + "required": 6, + "ocdTarget": 13 +} diff --git a/assets/gamedata/gootower/level-054.json b/assets/gamedata/gootower/level-054.json new file mode 100644 index 0000000..e888eed --- /dev/null +++ b/assets/gamedata/gootower/level-054.json @@ -0,0 +1,292 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 54, + "name": "Cliffhanger", + "chapter": 4, + "tip": "Brace as you go. An unbraced column leans, and once it leans it keeps leaning.", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + 0, + 850 + ], + [ + 1600, + 850 + ], + [ + 1600, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + } + ], + "balls": [ + { + "x": 692, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 754, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 723, + "y": 782, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 983, + "y": 834, + "type": "pokey" + }, + { + "x": 1013, + "y": 834, + "type": "anchor" + }, + { + "x": 1043, + "y": 834, + "type": "common" + }, + { + "x": 1073, + "y": 834, + "type": "pokey" + }, + { + "x": 1103, + "y": 834, + "type": "anchor" + }, + { + "x": 1133, + "y": 834, + "type": "common" + }, + { + "x": 1163, + "y": 834, + "type": "pokey" + }, + { + "x": 1193, + "y": 834, + "type": "anchor" + }, + { + "x": 1223, + "y": 834, + "type": "common" + }, + { + "x": 1253, + "y": 834, + "type": "pokey" + }, + { + "x": 1283, + "y": 834, + "type": "anchor" + }, + { + "x": 1313, + "y": 834, + "type": "common" + }, + { + "x": 983, + "y": 804, + "type": "pokey" + }, + { + "x": 1013, + "y": 804, + "type": "anchor" + }, + { + "x": 1043, + "y": 804, + "type": "common" + }, + { + "x": 1073, + "y": 804, + "type": "pokey" + }, + { + "x": 1103, + "y": 804, + "type": "common" + }, + { + "x": 1133, + "y": 804, + "type": "pokey" + }, + { + "x": 1163, + "y": 804, + "type": "common" + }, + { + "x": 1193, + "y": 804, + "type": "pokey" + }, + { + "x": 1223, + "y": 804, + "type": "common" + }, + { + "x": 1253, + "y": 804, + "type": "common" + }, + { + "x": 1283, + "y": 804, + "type": "common" + }, + { + "x": 1313, + "y": 804, + "type": "common" + }, + { + "x": 983, + "y": 774, + "type": "common" + }, + { + "x": 1013, + "y": 774, + "type": "common" + }, + { + "x": 1043, + "y": 774, + "type": "common" + }, + { + "x": 1073, + "y": 774, + "type": "common" + }, + { + "x": 1103, + "y": 774, + "type": "common" + }, + { + "x": 1133, + "y": 774, + "type": "common" + }, + { + "x": 1163, + "y": 774, + "type": "common" + }, + { + "x": 1193, + "y": 774, + "type": "common" + }, + { + "x": 1223, + "y": 774, + "type": "common" + }, + { + "x": 1253, + "y": 774, + "type": "common" + }, + { + "x": 1283, + "y": 774, + "type": "common" + } + ], + "pipe": { + "x": 723, + "y": 379, + "r": 46 + }, + "required": 7, + "ocdTarget": 15 +} diff --git a/assets/gamedata/gootower/level-055.json b/assets/gamedata/gootower/level-055.json new file mode 100644 index 0000000..d9c90fe --- /dev/null +++ b/assets/gamedata/gootower/level-055.json @@ -0,0 +1,383 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 55, + "name": "The Chimney", + "chapter": 4, + "tip": "Pokey goo grips bare rock and needs no friends. Start from the wall.", + "element": "anchor", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + 0, + 850 + ], + [ + 1600, + 850 + ], + [ + 1600, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 210, + 180 + ], + [ + 300, + 180 + ], + [ + 300, + 800 + ], + [ + 210, + 800 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1200, + 180 + ], + [ + 1290, + 180 + ], + [ + 1290, + 800 + ], + [ + 1200, + 800 + ] + ] + }, + { + "kind": "spike", + "poly": [ + [ + 300, + 930 + ], + [ + 1200, + 930 + ], + [ + 1200, + 1000 + ], + [ + 300, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 300, + 606 + ], + [ + 600, + 606 + ], + [ + 600, + 682 + ], + [ + 300, + 682 + ] + ] + } + ], + "balls": [ + { + "x": 340, + "y": 562, + "type": "pokey", + "pinned": true + }, + { + "x": 340, + "y": 500, + "type": "pokey", + "pinned": true + }, + { + "x": 398, + "y": 531, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 430, + "y": 590, + "type": "pokey" + }, + { + "x": 460, + "y": 590, + "type": "anchor" + }, + { + "x": 490, + "y": 590, + "type": "common" + }, + { + "x": 520, + "y": 590, + "type": "pokey" + }, + { + "x": 550, + "y": 590, + "type": "anchor" + }, + { + "x": 580, + "y": 590, + "type": "common" + }, + { + "x": 430, + "y": 560, + "type": "pokey" + }, + { + "x": 460, + "y": 560, + "type": "anchor" + }, + { + "x": 490, + "y": 560, + "type": "common" + }, + { + "x": 520, + "y": 560, + "type": "pokey" + }, + { + "x": 550, + "y": 560, + "type": "anchor" + }, + { + "x": 580, + "y": 560, + "type": "common" + }, + { + "x": 430, + "y": 530, + "type": "pokey" + }, + { + "x": 460, + "y": 530, + "type": "anchor" + }, + { + "x": 490, + "y": 530, + "type": "common" + }, + { + "x": 520, + "y": 530, + "type": "pokey" + }, + { + "x": 550, + "y": 530, + "type": "common" + }, + { + "x": 580, + "y": 530, + "type": "pokey" + }, + { + "x": 430, + "y": 500, + "type": "common" + }, + { + "x": 460, + "y": 500, + "type": "pokey" + }, + { + "x": 490, + "y": 500, + "type": "common" + }, + { + "x": 520, + "y": 500, + "type": "common" + }, + { + "x": 550, + "y": 500, + "type": "common" + }, + { + "x": 580, + "y": 500, + "type": "common" + }, + { + "x": 430, + "y": 470, + "type": "common" + }, + { + "x": 460, + "y": 470, + "type": "common" + }, + { + "x": 490, + "y": 470, + "type": "common" + }, + { + "x": 520, + "y": 470, + "type": "common" + }, + { + "x": 550, + "y": 470, + "type": "common" + }, + { + "x": 580, + "y": 470, + "type": "common" + }, + { + "x": 430, + "y": 440, + "type": "common" + }, + { + "x": 460, + "y": 440, + "type": "common" + }, + { + "x": 490, + "y": 440, + "type": "common" + }, + { + "x": 520, + "y": 440, + "type": "common" + }, + { + "x": 550, + "y": 440, + "type": "common" + } + ], + "pipe": { + "x": 1150, + "y": 432, + "r": 46 + }, + "waypoints": [ + { + "x": 740, + "y": 431 + } + ], + "required": 6, + "ocdTarget": 12 +} diff --git a/assets/gamedata/gootower/level-056.json b/assets/gamedata/gootower/level-056.json new file mode 100644 index 0000000..19f34a2 --- /dev/null +++ b/assets/gamedata/gootower/level-056.json @@ -0,0 +1,292 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 56, + "name": "Freeclimb", + "chapter": 4, + "tip": "Brace as you go. An unbraced column leans, and once it leans it keeps leaning.", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + 0, + 850 + ], + [ + 1600, + 850 + ], + [ + 1600, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + } + ], + "balls": [ + { + "x": 690, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 752, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 721, + "y": 782, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 981, + "y": 834, + "type": "pokey" + }, + { + "x": 1011, + "y": 834, + "type": "anchor" + }, + { + "x": 1041, + "y": 834, + "type": "common" + }, + { + "x": 1071, + "y": 834, + "type": "pokey" + }, + { + "x": 1101, + "y": 834, + "type": "anchor" + }, + { + "x": 1131, + "y": 834, + "type": "common" + }, + { + "x": 1161, + "y": 834, + "type": "pokey" + }, + { + "x": 1191, + "y": 834, + "type": "anchor" + }, + { + "x": 1221, + "y": 834, + "type": "common" + }, + { + "x": 1251, + "y": 834, + "type": "pokey" + }, + { + "x": 1281, + "y": 834, + "type": "anchor" + }, + { + "x": 1311, + "y": 834, + "type": "common" + }, + { + "x": 981, + "y": 804, + "type": "pokey" + }, + { + "x": 1011, + "y": 804, + "type": "anchor" + }, + { + "x": 1041, + "y": 804, + "type": "common" + }, + { + "x": 1071, + "y": 804, + "type": "pokey" + }, + { + "x": 1101, + "y": 804, + "type": "common" + }, + { + "x": 1131, + "y": 804, + "type": "pokey" + }, + { + "x": 1161, + "y": 804, + "type": "common" + }, + { + "x": 1191, + "y": 804, + "type": "pokey" + }, + { + "x": 1221, + "y": 804, + "type": "common" + }, + { + "x": 1251, + "y": 804, + "type": "common" + }, + { + "x": 1281, + "y": 804, + "type": "common" + }, + { + "x": 1311, + "y": 804, + "type": "common" + }, + { + "x": 981, + "y": 774, + "type": "common" + }, + { + "x": 1011, + "y": 774, + "type": "common" + }, + { + "x": 1041, + "y": 774, + "type": "common" + }, + { + "x": 1071, + "y": 774, + "type": "common" + }, + { + "x": 1101, + "y": 774, + "type": "common" + }, + { + "x": 1131, + "y": 774, + "type": "common" + }, + { + "x": 1161, + "y": 774, + "type": "common" + }, + { + "x": 1191, + "y": 774, + "type": "common" + }, + { + "x": 1221, + "y": 774, + "type": "common" + }, + { + "x": 1251, + "y": 774, + "type": "common" + }, + { + "x": 1281, + "y": 774, + "type": "common" + } + ], + "pipe": { + "x": 721, + "y": 432, + "r": 46 + }, + "required": 6, + "ocdTarget": 13 +} diff --git a/assets/gamedata/gootower/level-057.json b/assets/gamedata/gootower/level-057.json new file mode 100644 index 0000000..817a239 --- /dev/null +++ b/assets/gamedata/gootower/level-057.json @@ -0,0 +1,292 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 57, + "name": "The Notch", + "chapter": 4, + "tip": "Brace as you go. An unbraced column leans, and once it leans it keeps leaning.", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + 0, + 850 + ], + [ + 1600, + 850 + ], + [ + 1600, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + } + ], + "balls": [ + { + "x": 699, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 761, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 730, + "y": 782, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 990, + "y": 834, + "type": "pokey" + }, + { + "x": 1020, + "y": 834, + "type": "anchor" + }, + { + "x": 1050, + "y": 834, + "type": "common" + }, + { + "x": 1080, + "y": 834, + "type": "pokey" + }, + { + "x": 1110, + "y": 834, + "type": "anchor" + }, + { + "x": 1140, + "y": 834, + "type": "common" + }, + { + "x": 1170, + "y": 834, + "type": "pokey" + }, + { + "x": 1200, + "y": 834, + "type": "anchor" + }, + { + "x": 1230, + "y": 834, + "type": "common" + }, + { + "x": 1260, + "y": 834, + "type": "pokey" + }, + { + "x": 1290, + "y": 834, + "type": "anchor" + }, + { + "x": 1320, + "y": 834, + "type": "common" + }, + { + "x": 990, + "y": 804, + "type": "pokey" + }, + { + "x": 1020, + "y": 804, + "type": "anchor" + }, + { + "x": 1050, + "y": 804, + "type": "common" + }, + { + "x": 1080, + "y": 804, + "type": "pokey" + }, + { + "x": 1110, + "y": 804, + "type": "common" + }, + { + "x": 1140, + "y": 804, + "type": "pokey" + }, + { + "x": 1170, + "y": 804, + "type": "common" + }, + { + "x": 1200, + "y": 804, + "type": "pokey" + }, + { + "x": 1230, + "y": 804, + "type": "common" + }, + { + "x": 1260, + "y": 804, + "type": "common" + }, + { + "x": 1290, + "y": 804, + "type": "common" + }, + { + "x": 1320, + "y": 804, + "type": "common" + }, + { + "x": 990, + "y": 774, + "type": "common" + }, + { + "x": 1020, + "y": 774, + "type": "common" + }, + { + "x": 1050, + "y": 774, + "type": "common" + }, + { + "x": 1080, + "y": 774, + "type": "common" + }, + { + "x": 1110, + "y": 774, + "type": "common" + }, + { + "x": 1140, + "y": 774, + "type": "common" + }, + { + "x": 1170, + "y": 774, + "type": "common" + }, + { + "x": 1200, + "y": 774, + "type": "common" + }, + { + "x": 1230, + "y": 774, + "type": "common" + }, + { + "x": 1260, + "y": 774, + "type": "common" + }, + { + "x": 1290, + "y": 774, + "type": "common" + } + ], + "pipe": { + "x": 730, + "y": 404, + "r": 46 + }, + "required": 7, + "ocdTarget": 14 +} diff --git a/assets/gamedata/gootower/level-058.json b/assets/gamedata/gootower/level-058.json new file mode 100644 index 0000000..a4dfb67 --- /dev/null +++ b/assets/gamedata/gootower/level-058.json @@ -0,0 +1,382 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 58, + "name": "Crevasse", + "chapter": 4, + "tip": "Triangles carry weight across a gap. Long chains just sag into the spikes.", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 0, + 700 + ], + [ + 602, + 700 + ], + [ + 602, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 863, + 700 + ], + [ + 1600, + 700 + ], + [ + 1600, + 1000 + ], + [ + 863, + 1000 + ] + ] + }, + { + "kind": "spike", + "poly": [ + [ + 602, + 930 + ], + [ + 863, + 930 + ], + [ + 863, + 1000 + ], + [ + 602, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 0, + 610 + ], + [ + 44, + 610 + ], + [ + 44, + 700 + ], + [ + 0, + 700 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 558, + 610 + ], + [ + 602, + 610 + ], + [ + 602, + 700 + ], + [ + 558, + 700 + ] + ] + } + ], + "balls": [ + { + "x": 381, + "y": 686, + "type": "common", + "pinned": true + }, + { + "x": 443, + "y": 686, + "type": "common", + "pinned": true + }, + { + "x": 412, + "y": 632, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 90, + "y": 684, + "type": "pokey" + }, + { + "x": 120, + "y": 684, + "type": "anchor" + }, + { + "x": 150, + "y": 684, + "type": "common" + }, + { + "x": 180, + "y": 684, + "type": "pokey" + }, + { + "x": 210, + "y": 684, + "type": "anchor" + }, + { + "x": 240, + "y": 684, + "type": "common" + }, + { + "x": 90, + "y": 654, + "type": "pokey" + }, + { + "x": 120, + "y": 654, + "type": "anchor" + }, + { + "x": 150, + "y": 654, + "type": "common" + }, + { + "x": 180, + "y": 654, + "type": "pokey" + }, + { + "x": 210, + "y": 654, + "type": "anchor" + }, + { + "x": 240, + "y": 654, + "type": "common" + }, + { + "x": 90, + "y": 624, + "type": "pokey" + }, + { + "x": 120, + "y": 624, + "type": "anchor" + }, + { + "x": 150, + "y": 624, + "type": "common" + }, + { + "x": 180, + "y": 624, + "type": "pokey" + }, + { + "x": 210, + "y": 624, + "type": "common" + }, + { + "x": 240, + "y": 624, + "type": "pokey" + }, + { + "x": 90, + "y": 594, + "type": "common" + }, + { + "x": 120, + "y": 594, + "type": "pokey" + }, + { + "x": 150, + "y": 594, + "type": "common" + }, + { + "x": 180, + "y": 594, + "type": "common" + }, + { + "x": 210, + "y": 594, + "type": "common" + }, + { + "x": 240, + "y": 594, + "type": "common" + }, + { + "x": 90, + "y": 564, + "type": "common" + }, + { + "x": 120, + "y": 564, + "type": "common" + }, + { + "x": 150, + "y": 564, + "type": "common" + }, + { + "x": 180, + "y": 564, + "type": "common" + }, + { + "x": 210, + "y": 564, + "type": "common" + }, + { + "x": 240, + "y": 564, + "type": "common" + }, + { + "x": 90, + "y": 534, + "type": "common" + }, + { + "x": 120, + "y": 534, + "type": "common" + }, + { + "x": 150, + "y": 534, + "type": "common" + }, + { + "x": 180, + "y": 534, + "type": "common" + }, + { + "x": 210, + "y": 534, + "type": "common" + } + ], + "pipe": { + "x": 973, + "y": 640, + "r": 46 + }, + "waypoints": [ + { + "x": 732.5, + "y": 605 + } + ], + "required": 6, + "ocdTarget": 13 +} diff --git a/assets/gamedata/gootower/level-059.json b/assets/gamedata/gootower/level-059.json new file mode 100644 index 0000000..1fe912a --- /dev/null +++ b/assets/gamedata/gootower/level-059.json @@ -0,0 +1,382 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 59, + "name": "Exposure", + "chapter": 4, + "tip": "Triangles carry weight across a gap. Long chains just sag into the spikes.", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 0, + 700 + ], + [ + 638, + 700 + ], + [ + 638, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 922, + 700 + ], + [ + 1600, + 700 + ], + [ + 1600, + 1000 + ], + [ + 922, + 1000 + ] + ] + }, + { + "kind": "spike", + "poly": [ + [ + 638, + 930 + ], + [ + 922, + 930 + ], + [ + 922, + 1000 + ], + [ + 638, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 0, + 610 + ], + [ + 44, + 610 + ], + [ + 44, + 700 + ], + [ + 0, + 700 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 594, + 610 + ], + [ + 638, + 610 + ], + [ + 638, + 700 + ], + [ + 594, + 700 + ] + ] + } + ], + "balls": [ + { + "x": 417, + "y": 686, + "type": "common", + "pinned": true + }, + { + "x": 479, + "y": 686, + "type": "common", + "pinned": true + }, + { + "x": 448, + "y": 632, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 90, + "y": 684, + "type": "pokey" + }, + { + "x": 120, + "y": 684, + "type": "anchor" + }, + { + "x": 150, + "y": 684, + "type": "common" + }, + { + "x": 180, + "y": 684, + "type": "pokey" + }, + { + "x": 210, + "y": 684, + "type": "anchor" + }, + { + "x": 240, + "y": 684, + "type": "common" + }, + { + "x": 90, + "y": 654, + "type": "pokey" + }, + { + "x": 120, + "y": 654, + "type": "anchor" + }, + { + "x": 150, + "y": 654, + "type": "common" + }, + { + "x": 180, + "y": 654, + "type": "pokey" + }, + { + "x": 210, + "y": 654, + "type": "anchor" + }, + { + "x": 240, + "y": 654, + "type": "common" + }, + { + "x": 90, + "y": 624, + "type": "pokey" + }, + { + "x": 120, + "y": 624, + "type": "anchor" + }, + { + "x": 150, + "y": 624, + "type": "common" + }, + { + "x": 180, + "y": 624, + "type": "pokey" + }, + { + "x": 210, + "y": 624, + "type": "common" + }, + { + "x": 240, + "y": 624, + "type": "pokey" + }, + { + "x": 90, + "y": 594, + "type": "common" + }, + { + "x": 120, + "y": 594, + "type": "pokey" + }, + { + "x": 150, + "y": 594, + "type": "common" + }, + { + "x": 180, + "y": 594, + "type": "common" + }, + { + "x": 210, + "y": 594, + "type": "common" + }, + { + "x": 240, + "y": 594, + "type": "common" + }, + { + "x": 90, + "y": 564, + "type": "common" + }, + { + "x": 120, + "y": 564, + "type": "common" + }, + { + "x": 150, + "y": 564, + "type": "common" + }, + { + "x": 180, + "y": 564, + "type": "common" + }, + { + "x": 210, + "y": 564, + "type": "common" + }, + { + "x": 240, + "y": 564, + "type": "common" + }, + { + "x": 90, + "y": 534, + "type": "common" + }, + { + "x": 120, + "y": 534, + "type": "common" + }, + { + "x": 150, + "y": 534, + "type": "common" + }, + { + "x": 180, + "y": 534, + "type": "common" + }, + { + "x": 210, + "y": 534, + "type": "common" + } + ], + "pipe": { + "x": 1032, + "y": 640, + "r": 46 + }, + "waypoints": [ + { + "x": 780, + "y": 605 + } + ], + "required": 7, + "ocdTarget": 14 +} diff --git a/assets/gamedata/gootower/level-060.json b/assets/gamedata/gootower/level-060.json new file mode 100644 index 0000000..4ee23e7 --- /dev/null +++ b/assets/gamedata/gootower/level-060.json @@ -0,0 +1,292 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 60, + "name": "Summit", + "chapter": 4, + "tip": "Brace as you go. An unbraced column leans, and once it leans it keeps leaning.", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + 0, + 850 + ], + [ + 1600, + 850 + ], + [ + 1600, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + } + ], + "balls": [ + { + "x": 426, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 488, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 457, + "y": 782, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 717, + "y": 834, + "type": "pokey" + }, + { + "x": 747, + "y": 834, + "type": "anchor" + }, + { + "x": 777, + "y": 834, + "type": "common" + }, + { + "x": 807, + "y": 834, + "type": "pokey" + }, + { + "x": 837, + "y": 834, + "type": "anchor" + }, + { + "x": 867, + "y": 834, + "type": "common" + }, + { + "x": 897, + "y": 834, + "type": "pokey" + }, + { + "x": 927, + "y": 834, + "type": "anchor" + }, + { + "x": 957, + "y": 834, + "type": "common" + }, + { + "x": 987, + "y": 834, + "type": "pokey" + }, + { + "x": 1017, + "y": 834, + "type": "anchor" + }, + { + "x": 1047, + "y": 834, + "type": "common" + }, + { + "x": 717, + "y": 804, + "type": "pokey" + }, + { + "x": 747, + "y": 804, + "type": "anchor" + }, + { + "x": 777, + "y": 804, + "type": "common" + }, + { + "x": 807, + "y": 804, + "type": "pokey" + }, + { + "x": 837, + "y": 804, + "type": "common" + }, + { + "x": 867, + "y": 804, + "type": "pokey" + }, + { + "x": 897, + "y": 804, + "type": "common" + }, + { + "x": 927, + "y": 804, + "type": "pokey" + }, + { + "x": 957, + "y": 804, + "type": "common" + }, + { + "x": 987, + "y": 804, + "type": "common" + }, + { + "x": 1017, + "y": 804, + "type": "common" + }, + { + "x": 1047, + "y": 804, + "type": "common" + }, + { + "x": 717, + "y": 774, + "type": "common" + }, + { + "x": 747, + "y": 774, + "type": "common" + }, + { + "x": 777, + "y": 774, + "type": "common" + }, + { + "x": 807, + "y": 774, + "type": "common" + }, + { + "x": 837, + "y": 774, + "type": "common" + }, + { + "x": 867, + "y": 774, + "type": "common" + }, + { + "x": 897, + "y": 774, + "type": "common" + }, + { + "x": 927, + "y": 774, + "type": "common" + }, + { + "x": 957, + "y": 774, + "type": "common" + }, + { + "x": 987, + "y": 774, + "type": "common" + }, + { + "x": 1017, + "y": 774, + "type": "common" + } + ], + "pipe": { + "x": 457, + "y": 400, + "r": 46 + }, + "required": 7, + "ocdTarget": 14 +} diff --git a/assets/gamedata/gootower/level-061.json b/assets/gamedata/gootower/level-061.json new file mode 100644 index 0000000..87d4962 --- /dev/null +++ b/assets/gamedata/gootower/level-061.json @@ -0,0 +1,338 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 61, + "name": "Descent", + "chapter": 5, + "tip": "The ceiling bites. Stop short of it.", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + 0, + 850 + ], + [ + 1600, + 850 + ], + [ + 1600, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + }, + { + "kind": "spike", + "poly": [ + [ + 212, + 282 + ], + [ + 1052, + 282 + ], + [ + 1052, + 342 + ], + [ + 212, + 342 + ] + ] + } + ], + "balls": [ + { + "x": 601, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 663, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 632, + "y": 782, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 912, + "y": 834, + "type": "common" + }, + { + "x": 942, + "y": 834, + "type": "skull" + }, + { + "x": 972, + "y": 834, + "type": "bit" + }, + { + "x": 1002, + "y": 834, + "type": "balloon" + }, + { + "x": 1032, + "y": 834, + "type": "block" + }, + { + "x": 1062, + "y": 834, + "type": "common" + }, + { + "x": 1092, + "y": 834, + "type": "skull" + }, + { + "x": 1122, + "y": 834, + "type": "bit" + }, + { + "x": 1152, + "y": 834, + "type": "balloon" + }, + { + "x": 1182, + "y": 834, + "type": "block" + }, + { + "x": 1212, + "y": 834, + "type": "common" + }, + { + "x": 1242, + "y": 834, + "type": "skull" + }, + { + "x": 1272, + "y": 834, + "type": "bit" + }, + { + "x": 912, + "y": 804, + "type": "balloon" + }, + { + "x": 942, + "y": 804, + "type": "block" + }, + { + "x": 972, + "y": 804, + "type": "common" + }, + { + "x": 1002, + "y": 804, + "type": "skull" + }, + { + "x": 1032, + "y": 804, + "type": "bit" + }, + { + "x": 1062, + "y": 804, + "type": "balloon" + }, + { + "x": 1092, + "y": 804, + "type": "block" + }, + { + "x": 1122, + "y": 804, + "type": "common" + }, + { + "x": 1152, + "y": 804, + "type": "skull" + }, + { + "x": 1182, + "y": 804, + "type": "bit" + }, + { + "x": 1212, + "y": 804, + "type": "common" + }, + { + "x": 1242, + "y": 804, + "type": "skull" + }, + { + "x": 1272, + "y": 804, + "type": "bit" + }, + { + "x": 912, + "y": 774, + "type": "common" + }, + { + "x": 942, + "y": 774, + "type": "common" + }, + { + "x": 972, + "y": 774, + "type": "common" + }, + { + "x": 1002, + "y": 774, + "type": "common" + }, + { + "x": 1032, + "y": 774, + "type": "common" + }, + { + "x": 1062, + "y": 774, + "type": "common" + }, + { + "x": 1092, + "y": 774, + "type": "common" + }, + { + "x": 1122, + "y": 774, + "type": "common" + }, + { + "x": 1152, + "y": 774, + "type": "common" + }, + { + "x": 1182, + "y": 774, + "type": "common" + }, + { + "x": 1212, + "y": 774, + "type": "common" + }, + { + "x": 1242, + "y": 774, + "type": "common" + }, + { + "x": 1272, + "y": 774, + "type": "common" + }, + { + "x": 912, + "y": 744, + "type": "common" + } + ], + "pipe": { + "x": 632, + "y": 447, + "r": 46 + }, + "required": 6, + "ocdTarget": 13 +} diff --git a/assets/gamedata/gootower/level-062.json b/assets/gamedata/gootower/level-062.json new file mode 100644 index 0000000..dbe6722 --- /dev/null +++ b/assets/gamedata/gootower/level-062.json @@ -0,0 +1,338 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 62, + "name": "Low Roof", + "chapter": 5, + "tip": "The ceiling bites. Stop short of it.", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + 0, + 850 + ], + [ + 1600, + 850 + ], + [ + 1600, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + }, + { + "kind": "spike", + "poly": [ + [ + 251, + 261 + ], + [ + 1091, + 261 + ], + [ + 1091, + 321 + ], + [ + 251, + 321 + ] + ] + } + ], + "balls": [ + { + "x": 640, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 702, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 671, + "y": 782, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 951, + "y": 834, + "type": "common" + }, + { + "x": 981, + "y": 834, + "type": "skull" + }, + { + "x": 1011, + "y": 834, + "type": "bit" + }, + { + "x": 1041, + "y": 834, + "type": "balloon" + }, + { + "x": 1071, + "y": 834, + "type": "block" + }, + { + "x": 1101, + "y": 834, + "type": "common" + }, + { + "x": 1131, + "y": 834, + "type": "skull" + }, + { + "x": 1161, + "y": 834, + "type": "bit" + }, + { + "x": 1191, + "y": 834, + "type": "balloon" + }, + { + "x": 1221, + "y": 834, + "type": "block" + }, + { + "x": 1251, + "y": 834, + "type": "common" + }, + { + "x": 1281, + "y": 834, + "type": "skull" + }, + { + "x": 1311, + "y": 834, + "type": "bit" + }, + { + "x": 951, + "y": 804, + "type": "balloon" + }, + { + "x": 981, + "y": 804, + "type": "block" + }, + { + "x": 1011, + "y": 804, + "type": "common" + }, + { + "x": 1041, + "y": 804, + "type": "skull" + }, + { + "x": 1071, + "y": 804, + "type": "bit" + }, + { + "x": 1101, + "y": 804, + "type": "balloon" + }, + { + "x": 1131, + "y": 804, + "type": "block" + }, + { + "x": 1161, + "y": 804, + "type": "common" + }, + { + "x": 1191, + "y": 804, + "type": "skull" + }, + { + "x": 1221, + "y": 804, + "type": "bit" + }, + { + "x": 1251, + "y": 804, + "type": "common" + }, + { + "x": 1281, + "y": 804, + "type": "skull" + }, + { + "x": 1311, + "y": 804, + "type": "bit" + }, + { + "x": 951, + "y": 774, + "type": "common" + }, + { + "x": 981, + "y": 774, + "type": "common" + }, + { + "x": 1011, + "y": 774, + "type": "common" + }, + { + "x": 1041, + "y": 774, + "type": "common" + }, + { + "x": 1071, + "y": 774, + "type": "common" + }, + { + "x": 1101, + "y": 774, + "type": "common" + }, + { + "x": 1131, + "y": 774, + "type": "common" + }, + { + "x": 1161, + "y": 774, + "type": "common" + }, + { + "x": 1191, + "y": 774, + "type": "common" + }, + { + "x": 1221, + "y": 774, + "type": "common" + }, + { + "x": 1251, + "y": 774, + "type": "common" + }, + { + "x": 1281, + "y": 774, + "type": "common" + }, + { + "x": 1311, + "y": 774, + "type": "common" + }, + { + "x": 951, + "y": 744, + "type": "common" + } + ], + "pipe": { + "x": 671, + "y": 426, + "r": 46 + }, + "required": 7, + "ocdTarget": 15 +} diff --git a/assets/gamedata/gootower/level-063.json b/assets/gamedata/gootower/level-063.json new file mode 100644 index 0000000..c256793 --- /dev/null +++ b/assets/gamedata/gootower/level-063.json @@ -0,0 +1,338 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 63, + "name": "The Squeeze", + "chapter": 5, + "tip": "The ceiling bites. Stop short of it.", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + 0, + 850 + ], + [ + 1600, + 850 + ], + [ + 1600, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + }, + { + "kind": "spike", + "poly": [ + [ + 297, + 255 + ], + [ + 1137, + 255 + ], + [ + 1137, + 315 + ], + [ + 297, + 315 + ] + ] + } + ], + "balls": [ + { + "x": 686, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 748, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 717, + "y": 782, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 997, + "y": 834, + "type": "common" + }, + { + "x": 1027, + "y": 834, + "type": "skull" + }, + { + "x": 1057, + "y": 834, + "type": "bit" + }, + { + "x": 1087, + "y": 834, + "type": "balloon" + }, + { + "x": 1117, + "y": 834, + "type": "block" + }, + { + "x": 1147, + "y": 834, + "type": "common" + }, + { + "x": 1177, + "y": 834, + "type": "skull" + }, + { + "x": 1207, + "y": 834, + "type": "bit" + }, + { + "x": 1237, + "y": 834, + "type": "balloon" + }, + { + "x": 1267, + "y": 834, + "type": "block" + }, + { + "x": 1297, + "y": 834, + "type": "common" + }, + { + "x": 1327, + "y": 834, + "type": "skull" + }, + { + "x": 1357, + "y": 834, + "type": "bit" + }, + { + "x": 997, + "y": 804, + "type": "balloon" + }, + { + "x": 1027, + "y": 804, + "type": "block" + }, + { + "x": 1057, + "y": 804, + "type": "common" + }, + { + "x": 1087, + "y": 804, + "type": "skull" + }, + { + "x": 1117, + "y": 804, + "type": "bit" + }, + { + "x": 1147, + "y": 804, + "type": "balloon" + }, + { + "x": 1177, + "y": 804, + "type": "block" + }, + { + "x": 1207, + "y": 804, + "type": "common" + }, + { + "x": 1237, + "y": 804, + "type": "skull" + }, + { + "x": 1267, + "y": 804, + "type": "bit" + }, + { + "x": 1297, + "y": 804, + "type": "common" + }, + { + "x": 1327, + "y": 804, + "type": "skull" + }, + { + "x": 1357, + "y": 804, + "type": "bit" + }, + { + "x": 997, + "y": 774, + "type": "common" + }, + { + "x": 1027, + "y": 774, + "type": "common" + }, + { + "x": 1057, + "y": 774, + "type": "common" + }, + { + "x": 1087, + "y": 774, + "type": "common" + }, + { + "x": 1117, + "y": 774, + "type": "common" + }, + { + "x": 1147, + "y": 774, + "type": "common" + }, + { + "x": 1177, + "y": 774, + "type": "common" + }, + { + "x": 1207, + "y": 774, + "type": "common" + }, + { + "x": 1237, + "y": 774, + "type": "common" + }, + { + "x": 1267, + "y": 774, + "type": "common" + }, + { + "x": 1297, + "y": 774, + "type": "common" + }, + { + "x": 1327, + "y": 774, + "type": "common" + }, + { + "x": 1357, + "y": 774, + "type": "common" + }, + { + "x": 997, + "y": 744, + "type": "common" + } + ], + "pipe": { + "x": 717, + "y": 420, + "r": 46 + }, + "required": 7, + "ocdTarget": 15 +} diff --git a/assets/gamedata/gootower/level-064.json b/assets/gamedata/gootower/level-064.json new file mode 100644 index 0000000..9c890ec --- /dev/null +++ b/assets/gamedata/gootower/level-064.json @@ -0,0 +1,419 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 64, + "name": "Deep Wind", + "chapter": 5, + "tip": "The updraft takes weight off everything inside it. Spans reach further in the wind.", + "element": "fan", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 0, + 700 + ], + [ + 560, + 700 + ], + [ + 560, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 985, + 700 + ], + [ + 1600, + 700 + ], + [ + 1600, + 1000 + ], + [ + 985, + 1000 + ] + ] + }, + { + "kind": "spike", + "poly": [ + [ + 560, + 930 + ], + [ + 985, + 930 + ], + [ + 985, + 1000 + ], + [ + 560, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 0, + 610 + ], + [ + 44, + 610 + ], + [ + 44, + 700 + ], + [ + 0, + 700 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 516, + 610 + ], + [ + 560, + 610 + ], + [ + 560, + 700 + ], + [ + 516, + 700 + ] + ] + } + ], + "balls": [ + { + "x": 339, + "y": 686, + "type": "common", + "pinned": true + }, + { + "x": 401, + "y": 686, + "type": "common", + "pinned": true + }, + { + "x": 370, + "y": 632, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 90, + "y": 684, + "type": "common" + }, + { + "x": 120, + "y": 684, + "type": "skull" + }, + { + "x": 150, + "y": 684, + "type": "bit" + }, + { + "x": 180, + "y": 684, + "type": "balloon" + }, + { + "x": 210, + "y": 684, + "type": "block" + }, + { + "x": 240, + "y": 684, + "type": "common" + }, + { + "x": 90, + "y": 654, + "type": "skull" + }, + { + "x": 120, + "y": 654, + "type": "bit" + }, + { + "x": 150, + "y": 654, + "type": "balloon" + }, + { + "x": 180, + "y": 654, + "type": "block" + }, + { + "x": 210, + "y": 654, + "type": "common" + }, + { + "x": 240, + "y": 654, + "type": "skull" + }, + { + "x": 90, + "y": 624, + "type": "bit" + }, + { + "x": 120, + "y": 624, + "type": "balloon" + }, + { + "x": 150, + "y": 624, + "type": "block" + }, + { + "x": 180, + "y": 624, + "type": "common" + }, + { + "x": 210, + "y": 624, + "type": "skull" + }, + { + "x": 240, + "y": 624, + "type": "bit" + }, + { + "x": 90, + "y": 594, + "type": "balloon" + }, + { + "x": 120, + "y": 594, + "type": "block" + }, + { + "x": 150, + "y": 594, + "type": "common" + }, + { + "x": 180, + "y": 594, + "type": "skull" + }, + { + "x": 210, + "y": 594, + "type": "bit" + }, + { + "x": 240, + "y": 594, + "type": "common" + }, + { + "x": 90, + "y": 564, + "type": "skull" + }, + { + "x": 120, + "y": 564, + "type": "bit" + }, + { + "x": 150, + "y": 564, + "type": "common" + }, + { + "x": 180, + "y": 564, + "type": "common" + }, + { + "x": 210, + "y": 564, + "type": "common" + }, + { + "x": 240, + "y": 564, + "type": "common" + }, + { + "x": 90, + "y": 534, + "type": "common" + }, + { + "x": 120, + "y": 534, + "type": "common" + }, + { + "x": 150, + "y": 534, + "type": "common" + }, + { + "x": 180, + "y": 534, + "type": "common" + }, + { + "x": 210, + "y": 534, + "type": "common" + }, + { + "x": 240, + "y": 534, + "type": "common" + }, + { + "x": 90, + "y": 504, + "type": "common" + }, + { + "x": 120, + "y": 504, + "type": "common" + }, + { + "x": 150, + "y": 504, + "type": "common" + }, + { + "x": 180, + "y": 504, + "type": "common" + } + ], + "pipe": { + "x": 1095, + "y": 640, + "r": 46 + }, + "fans": [ + { + "x": 560, + "y": 260, + "w": 425, + "h": 660, + "dx": 0, + "dy": -1, + "force": 1327 + } + ], + "waypoints": [ + { + "x": 772.5, + "y": 580 + } + ], + "required": 6, + "ocdTarget": 13 +} diff --git a/assets/gamedata/gootower/level-065.json b/assets/gamedata/gootower/level-065.json new file mode 100644 index 0000000..a47d491 --- /dev/null +++ b/assets/gamedata/gootower/level-065.json @@ -0,0 +1,419 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 65, + "name": "The Shaft", + "chapter": 5, + "tip": "The updraft takes weight off everything inside it. Spans reach further in the wind.", + "element": "fan", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 0, + 700 + ], + [ + 560, + 700 + ], + [ + 560, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1006, + 700 + ], + [ + 1600, + 700 + ], + [ + 1600, + 1000 + ], + [ + 1006, + 1000 + ] + ] + }, + { + "kind": "spike", + "poly": [ + [ + 560, + 930 + ], + [ + 1006, + 930 + ], + [ + 1006, + 1000 + ], + [ + 560, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 0, + 610 + ], + [ + 44, + 610 + ], + [ + 44, + 700 + ], + [ + 0, + 700 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 516, + 610 + ], + [ + 560, + 610 + ], + [ + 560, + 700 + ], + [ + 516, + 700 + ] + ] + } + ], + "balls": [ + { + "x": 339, + "y": 686, + "type": "common", + "pinned": true + }, + { + "x": 401, + "y": 686, + "type": "common", + "pinned": true + }, + { + "x": 370, + "y": 632, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 90, + "y": 684, + "type": "common" + }, + { + "x": 120, + "y": 684, + "type": "skull" + }, + { + "x": 150, + "y": 684, + "type": "bit" + }, + { + "x": 180, + "y": 684, + "type": "balloon" + }, + { + "x": 210, + "y": 684, + "type": "block" + }, + { + "x": 240, + "y": 684, + "type": "common" + }, + { + "x": 90, + "y": 654, + "type": "skull" + }, + { + "x": 120, + "y": 654, + "type": "bit" + }, + { + "x": 150, + "y": 654, + "type": "balloon" + }, + { + "x": 180, + "y": 654, + "type": "block" + }, + { + "x": 210, + "y": 654, + "type": "common" + }, + { + "x": 240, + "y": 654, + "type": "skull" + }, + { + "x": 90, + "y": 624, + "type": "bit" + }, + { + "x": 120, + "y": 624, + "type": "balloon" + }, + { + "x": 150, + "y": 624, + "type": "block" + }, + { + "x": 180, + "y": 624, + "type": "common" + }, + { + "x": 210, + "y": 624, + "type": "skull" + }, + { + "x": 240, + "y": 624, + "type": "bit" + }, + { + "x": 90, + "y": 594, + "type": "balloon" + }, + { + "x": 120, + "y": 594, + "type": "block" + }, + { + "x": 150, + "y": 594, + "type": "common" + }, + { + "x": 180, + "y": 594, + "type": "skull" + }, + { + "x": 210, + "y": 594, + "type": "bit" + }, + { + "x": 240, + "y": 594, + "type": "common" + }, + { + "x": 90, + "y": 564, + "type": "skull" + }, + { + "x": 120, + "y": 564, + "type": "bit" + }, + { + "x": 150, + "y": 564, + "type": "common" + }, + { + "x": 180, + "y": 564, + "type": "common" + }, + { + "x": 210, + "y": 564, + "type": "common" + }, + { + "x": 240, + "y": 564, + "type": "common" + }, + { + "x": 90, + "y": 534, + "type": "common" + }, + { + "x": 120, + "y": 534, + "type": "common" + }, + { + "x": 150, + "y": 534, + "type": "common" + }, + { + "x": 180, + "y": 534, + "type": "common" + }, + { + "x": 210, + "y": 534, + "type": "common" + }, + { + "x": 240, + "y": 534, + "type": "common" + }, + { + "x": 90, + "y": 504, + "type": "common" + }, + { + "x": 120, + "y": 504, + "type": "common" + }, + { + "x": 150, + "y": 504, + "type": "common" + }, + { + "x": 180, + "y": 504, + "type": "common" + } + ], + "pipe": { + "x": 1116, + "y": 640, + "r": 46 + }, + "fans": [ + { + "x": 560, + "y": 260, + "w": 446, + "h": 660, + "dx": 0, + "dy": -1, + "force": 1310 + } + ], + "waypoints": [ + { + "x": 783, + "y": 580 + } + ], + "required": 7, + "ocdTarget": 15 +} diff --git a/assets/gamedata/gootower/level-066.json b/assets/gamedata/gootower/level-066.json new file mode 100644 index 0000000..2f864cb --- /dev/null +++ b/assets/gamedata/gootower/level-066.json @@ -0,0 +1,419 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 66, + "name": "Downdraft", + "chapter": 5, + "tip": "The updraft takes weight off everything inside it. Spans reach further in the wind.", + "element": "fan", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 0, + 700 + ], + [ + 560, + 700 + ], + [ + 560, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1023, + 700 + ], + [ + 1600, + 700 + ], + [ + 1600, + 1000 + ], + [ + 1023, + 1000 + ] + ] + }, + { + "kind": "spike", + "poly": [ + [ + 560, + 930 + ], + [ + 1023, + 930 + ], + [ + 1023, + 1000 + ], + [ + 560, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 0, + 610 + ], + [ + 44, + 610 + ], + [ + 44, + 700 + ], + [ + 0, + 700 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 516, + 610 + ], + [ + 560, + 610 + ], + [ + 560, + 700 + ], + [ + 516, + 700 + ] + ] + } + ], + "balls": [ + { + "x": 339, + "y": 686, + "type": "common", + "pinned": true + }, + { + "x": 401, + "y": 686, + "type": "common", + "pinned": true + }, + { + "x": 370, + "y": 632, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 90, + "y": 684, + "type": "common" + }, + { + "x": 120, + "y": 684, + "type": "skull" + }, + { + "x": 150, + "y": 684, + "type": "bit" + }, + { + "x": 180, + "y": 684, + "type": "balloon" + }, + { + "x": 210, + "y": 684, + "type": "block" + }, + { + "x": 240, + "y": 684, + "type": "common" + }, + { + "x": 90, + "y": 654, + "type": "skull" + }, + { + "x": 120, + "y": 654, + "type": "bit" + }, + { + "x": 150, + "y": 654, + "type": "balloon" + }, + { + "x": 180, + "y": 654, + "type": "block" + }, + { + "x": 210, + "y": 654, + "type": "common" + }, + { + "x": 240, + "y": 654, + "type": "skull" + }, + { + "x": 90, + "y": 624, + "type": "bit" + }, + { + "x": 120, + "y": 624, + "type": "balloon" + }, + { + "x": 150, + "y": 624, + "type": "block" + }, + { + "x": 180, + "y": 624, + "type": "common" + }, + { + "x": 210, + "y": 624, + "type": "skull" + }, + { + "x": 240, + "y": 624, + "type": "bit" + }, + { + "x": 90, + "y": 594, + "type": "balloon" + }, + { + "x": 120, + "y": 594, + "type": "block" + }, + { + "x": 150, + "y": 594, + "type": "common" + }, + { + "x": 180, + "y": 594, + "type": "skull" + }, + { + "x": 210, + "y": 594, + "type": "bit" + }, + { + "x": 240, + "y": 594, + "type": "common" + }, + { + "x": 90, + "y": 564, + "type": "skull" + }, + { + "x": 120, + "y": 564, + "type": "bit" + }, + { + "x": 150, + "y": 564, + "type": "common" + }, + { + "x": 180, + "y": 564, + "type": "common" + }, + { + "x": 210, + "y": 564, + "type": "common" + }, + { + "x": 240, + "y": 564, + "type": "common" + }, + { + "x": 90, + "y": 534, + "type": "common" + }, + { + "x": 120, + "y": 534, + "type": "common" + }, + { + "x": 150, + "y": 534, + "type": "common" + }, + { + "x": 180, + "y": 534, + "type": "common" + }, + { + "x": 210, + "y": 534, + "type": "common" + }, + { + "x": 240, + "y": 534, + "type": "common" + }, + { + "x": 90, + "y": 504, + "type": "common" + }, + { + "x": 120, + "y": 504, + "type": "common" + }, + { + "x": 150, + "y": 504, + "type": "common" + }, + { + "x": 180, + "y": 504, + "type": "common" + } + ], + "pipe": { + "x": 1133, + "y": 640, + "r": 46 + }, + "fans": [ + { + "x": 560, + "y": 260, + "w": 463, + "h": 660, + "dx": 0, + "dy": -1, + "force": 1296 + } + ], + "waypoints": [ + { + "x": 791.5, + "y": 580 + } + ], + "required": 8, + "ocdTarget": 17 +} diff --git a/assets/gamedata/gootower/level-067.json b/assets/gamedata/gootower/level-067.json new file mode 100644 index 0000000..864a343 --- /dev/null +++ b/assets/gamedata/gootower/level-067.json @@ -0,0 +1,327 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 67, + "name": "Deep Cogs", + "chapter": 5, + "tip": "The cog is solid and it is turning. Whatever it touches gets dragged along.", + "element": "gear", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + 0, + 850 + ], + [ + 1600, + 850 + ], + [ + 1600, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + } + ], + "balls": [ + { + "x": 298, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 360, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 329, + "y": 782, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 1000, + "y": 834, + "type": "common" + }, + { + "x": 1030, + "y": 834, + "type": "skull" + }, + { + "x": 1060, + "y": 834, + "type": "bit" + }, + { + "x": 1090, + "y": 834, + "type": "balloon" + }, + { + "x": 1120, + "y": 834, + "type": "block" + }, + { + "x": 1150, + "y": 834, + "type": "common" + }, + { + "x": 1180, + "y": 834, + "type": "skull" + }, + { + "x": 1210, + "y": 834, + "type": "bit" + }, + { + "x": 1240, + "y": 834, + "type": "balloon" + }, + { + "x": 1000, + "y": 804, + "type": "block" + }, + { + "x": 1030, + "y": 804, + "type": "common" + }, + { + "x": 1060, + "y": 804, + "type": "skull" + }, + { + "x": 1090, + "y": 804, + "type": "bit" + }, + { + "x": 1120, + "y": 804, + "type": "balloon" + }, + { + "x": 1150, + "y": 804, + "type": "block" + }, + { + "x": 1180, + "y": 804, + "type": "common" + }, + { + "x": 1210, + "y": 804, + "type": "skull" + }, + { + "x": 1240, + "y": 804, + "type": "bit" + }, + { + "x": 1000, + "y": 774, + "type": "balloon" + }, + { + "x": 1030, + "y": 774, + "type": "block" + }, + { + "x": 1060, + "y": 774, + "type": "common" + }, + { + "x": 1090, + "y": 774, + "type": "skull" + }, + { + "x": 1120, + "y": 774, + "type": "bit" + }, + { + "x": 1150, + "y": 774, + "type": "common" + }, + { + "x": 1180, + "y": 774, + "type": "skull" + }, + { + "x": 1210, + "y": 774, + "type": "bit" + }, + { + "x": 1240, + "y": 774, + "type": "common" + }, + { + "x": 1000, + "y": 744, + "type": "common" + }, + { + "x": 1030, + "y": 744, + "type": "common" + }, + { + "x": 1060, + "y": 744, + "type": "common" + }, + { + "x": 1090, + "y": 744, + "type": "common" + }, + { + "x": 1120, + "y": 744, + "type": "common" + }, + { + "x": 1150, + "y": 744, + "type": "common" + }, + { + "x": 1180, + "y": 744, + "type": "common" + }, + { + "x": 1210, + "y": 744, + "type": "common" + }, + { + "x": 1240, + "y": 744, + "type": "common" + }, + { + "x": 1000, + "y": 714, + "type": "common" + }, + { + "x": 1030, + "y": 714, + "type": "common" + }, + { + "x": 1060, + "y": 714, + "type": "common" + }, + { + "x": 1090, + "y": 714, + "type": "common" + } + ], + "pipe": { + "x": 1241, + "y": 577, + "r": 46 + }, + "gears": [ + { + "x": 726, + "y": 477, + "r": 114, + "teeth": 9, + "omega": -1.657384972431697 + } + ], + "required": 6, + "ocdTarget": 13 +} diff --git a/assets/gamedata/gootower/level-068.json b/assets/gamedata/gootower/level-068.json new file mode 100644 index 0000000..52f881e --- /dev/null +++ b/assets/gamedata/gootower/level-068.json @@ -0,0 +1,327 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 68, + "name": "The Grinder", + "chapter": 5, + "tip": "The cog is solid and it is turning. Whatever it touches gets dragged along.", + "element": "gear", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + 0, + 850 + ], + [ + 1600, + 850 + ], + [ + 1600, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + } + ], + "balls": [ + { + "x": 315, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 377, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 346, + "y": 782, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 1000, + "y": 834, + "type": "common" + }, + { + "x": 1030, + "y": 834, + "type": "skull" + }, + { + "x": 1060, + "y": 834, + "type": "bit" + }, + { + "x": 1090, + "y": 834, + "type": "balloon" + }, + { + "x": 1120, + "y": 834, + "type": "block" + }, + { + "x": 1150, + "y": 834, + "type": "common" + }, + { + "x": 1180, + "y": 834, + "type": "skull" + }, + { + "x": 1210, + "y": 834, + "type": "bit" + }, + { + "x": 1240, + "y": 834, + "type": "balloon" + }, + { + "x": 1000, + "y": 804, + "type": "block" + }, + { + "x": 1030, + "y": 804, + "type": "common" + }, + { + "x": 1060, + "y": 804, + "type": "skull" + }, + { + "x": 1090, + "y": 804, + "type": "bit" + }, + { + "x": 1120, + "y": 804, + "type": "balloon" + }, + { + "x": 1150, + "y": 804, + "type": "block" + }, + { + "x": 1180, + "y": 804, + "type": "common" + }, + { + "x": 1210, + "y": 804, + "type": "skull" + }, + { + "x": 1240, + "y": 804, + "type": "bit" + }, + { + "x": 1000, + "y": 774, + "type": "balloon" + }, + { + "x": 1030, + "y": 774, + "type": "block" + }, + { + "x": 1060, + "y": 774, + "type": "common" + }, + { + "x": 1090, + "y": 774, + "type": "skull" + }, + { + "x": 1120, + "y": 774, + "type": "bit" + }, + { + "x": 1150, + "y": 774, + "type": "common" + }, + { + "x": 1180, + "y": 774, + "type": "skull" + }, + { + "x": 1210, + "y": 774, + "type": "bit" + }, + { + "x": 1240, + "y": 774, + "type": "common" + }, + { + "x": 1000, + "y": 744, + "type": "common" + }, + { + "x": 1030, + "y": 744, + "type": "common" + }, + { + "x": 1060, + "y": 744, + "type": "common" + }, + { + "x": 1090, + "y": 744, + "type": "common" + }, + { + "x": 1120, + "y": 744, + "type": "common" + }, + { + "x": 1150, + "y": 744, + "type": "common" + }, + { + "x": 1180, + "y": 744, + "type": "common" + }, + { + "x": 1210, + "y": 744, + "type": "common" + }, + { + "x": 1240, + "y": 744, + "type": "common" + }, + { + "x": 1000, + "y": 714, + "type": "common" + }, + { + "x": 1030, + "y": 714, + "type": "common" + }, + { + "x": 1060, + "y": 714, + "type": "common" + }, + { + "x": 1090, + "y": 714, + "type": "common" + } + ], + "pipe": { + "x": 1260, + "y": 566, + "r": 46 + }, + "gears": [ + { + "x": 809, + "y": 466, + "r": 118, + "teeth": 9, + "omega": 1.7896977431932464 + } + ], + "required": 7, + "ocdTarget": 15 +} diff --git a/assets/gamedata/gootower/level-069.json b/assets/gamedata/gootower/level-069.json new file mode 100644 index 0000000..1449c9c --- /dev/null +++ b/assets/gamedata/gootower/level-069.json @@ -0,0 +1,327 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 69, + "name": "Millstone", + "chapter": 5, + "tip": "The cog is solid and it is turning. Whatever it touches gets dragged along.", + "element": "gear", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + 0, + 850 + ], + [ + 1600, + 850 + ], + [ + 1600, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + } + ], + "balls": [ + { + "x": 312, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 374, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 343, + "y": 782, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 1000, + "y": 834, + "type": "common" + }, + { + "x": 1030, + "y": 834, + "type": "skull" + }, + { + "x": 1060, + "y": 834, + "type": "bit" + }, + { + "x": 1090, + "y": 834, + "type": "balloon" + }, + { + "x": 1120, + "y": 834, + "type": "block" + }, + { + "x": 1150, + "y": 834, + "type": "common" + }, + { + "x": 1180, + "y": 834, + "type": "skull" + }, + { + "x": 1210, + "y": 834, + "type": "bit" + }, + { + "x": 1240, + "y": 834, + "type": "balloon" + }, + { + "x": 1000, + "y": 804, + "type": "block" + }, + { + "x": 1030, + "y": 804, + "type": "common" + }, + { + "x": 1060, + "y": 804, + "type": "skull" + }, + { + "x": 1090, + "y": 804, + "type": "bit" + }, + { + "x": 1120, + "y": 804, + "type": "balloon" + }, + { + "x": 1150, + "y": 804, + "type": "block" + }, + { + "x": 1180, + "y": 804, + "type": "common" + }, + { + "x": 1210, + "y": 804, + "type": "skull" + }, + { + "x": 1240, + "y": 804, + "type": "bit" + }, + { + "x": 1000, + "y": 774, + "type": "balloon" + }, + { + "x": 1030, + "y": 774, + "type": "block" + }, + { + "x": 1060, + "y": 774, + "type": "common" + }, + { + "x": 1090, + "y": 774, + "type": "skull" + }, + { + "x": 1120, + "y": 774, + "type": "bit" + }, + { + "x": 1150, + "y": 774, + "type": "common" + }, + { + "x": 1180, + "y": 774, + "type": "skull" + }, + { + "x": 1210, + "y": 774, + "type": "bit" + }, + { + "x": 1240, + "y": 774, + "type": "common" + }, + { + "x": 1000, + "y": 744, + "type": "common" + }, + { + "x": 1030, + "y": 744, + "type": "common" + }, + { + "x": 1060, + "y": 744, + "type": "common" + }, + { + "x": 1090, + "y": 744, + "type": "common" + }, + { + "x": 1120, + "y": 744, + "type": "common" + }, + { + "x": 1150, + "y": 744, + "type": "common" + }, + { + "x": 1180, + "y": 744, + "type": "common" + }, + { + "x": 1210, + "y": 744, + "type": "common" + }, + { + "x": 1240, + "y": 744, + "type": "common" + }, + { + "x": 1000, + "y": 714, + "type": "common" + }, + { + "x": 1030, + "y": 714, + "type": "common" + }, + { + "x": 1060, + "y": 714, + "type": "common" + }, + { + "x": 1090, + "y": 714, + "type": "common" + } + ], + "pipe": { + "x": 1290, + "y": 550, + "r": 46 + }, + "gears": [ + { + "x": 811, + "y": 450, + "r": 125, + "teeth": 9, + "omega": -2 + } + ], + "required": 8, + "ocdTarget": 17 +} diff --git a/assets/gamedata/gootower/level-070.json b/assets/gamedata/gootower/level-070.json new file mode 100644 index 0000000..ea2d35c --- /dev/null +++ b/assets/gamedata/gootower/level-070.json @@ -0,0 +1,367 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 70, + "name": "Deep Rock", + "chapter": 5, + "tip": "Drop a bomb by the fire and the soft rock goes with it. Or take the long way over.", + "element": "bomb", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + 0, + 850 + ], + [ + 1600, + 850 + ], + [ + 1600, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 681, + 662 + ], + [ + 761, + 662 + ], + [ + 761, + 850 + ], + [ + 681, + 850 + ] + ], + "destructible": true + }, + { + "kind": "fire", + "poly": [ + [ + 571, + 806 + ], + [ + 651, + 806 + ], + [ + 651, + 850 + ], + [ + 571, + 850 + ] + ] + } + ], + "balls": [ + { + "x": 355, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 417, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 386, + "y": 782, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 96, + "y": 834, + "type": "common" + }, + { + "x": 126, + "y": 834, + "type": "skull" + }, + { + "x": 156, + "y": 834, + "type": "bit" + }, + { + "x": 186, + "y": 834, + "type": "balloon" + }, + { + "x": 216, + "y": 834, + "type": "block" + }, + { + "x": 246, + "y": 834, + "type": "common" + }, + { + "x": 276, + "y": 834, + "type": "skull" + }, + { + "x": 96, + "y": 804, + "type": "bit" + }, + { + "x": 126, + "y": 804, + "type": "balloon" + }, + { + "x": 156, + "y": 804, + "type": "block" + }, + { + "x": 186, + "y": 804, + "type": "common" + }, + { + "x": 216, + "y": 804, + "type": "skull" + }, + { + "x": 246, + "y": 804, + "type": "bit" + }, + { + "x": 276, + "y": 804, + "type": "balloon" + }, + { + "x": 96, + "y": 774, + "type": "block" + }, + { + "x": 126, + "y": 774, + "type": "common" + }, + { + "x": 156, + "y": 774, + "type": "skull" + }, + { + "x": 186, + "y": 774, + "type": "bit" + }, + { + "x": 216, + "y": 774, + "type": "balloon" + }, + { + "x": 246, + "y": 774, + "type": "block" + }, + { + "x": 276, + "y": 774, + "type": "common" + }, + { + "x": 96, + "y": 744, + "type": "skull" + }, + { + "x": 126, + "y": 744, + "type": "bit" + }, + { + "x": 156, + "y": 744, + "type": "common" + }, + { + "x": 186, + "y": 744, + "type": "skull" + }, + { + "x": 216, + "y": 744, + "type": "bit" + }, + { + "x": 246, + "y": 744, + "type": "common" + }, + { + "x": 276, + "y": 744, + "type": "common" + }, + { + "x": 96, + "y": 714, + "type": "common" + }, + { + "x": 126, + "y": 714, + "type": "common" + }, + { + "x": 156, + "y": 714, + "type": "common" + }, + { + "x": 186, + "y": 714, + "type": "common" + }, + { + "x": 216, + "y": 714, + "type": "common" + }, + { + "x": 246, + "y": 714, + "type": "common" + }, + { + "x": 276, + "y": 714, + "type": "common" + }, + { + "x": 96, + "y": 684, + "type": "common" + }, + { + "x": 126, + "y": 684, + "type": "common" + }, + { + "x": 156, + "y": 684, + "type": "common" + }, + { + "x": 186, + "y": 684, + "type": "common" + }, + { + "x": 216, + "y": 684, + "type": "common" + } + ], + "pipe": { + "x": 1069, + "y": 700, + "r": 46 + }, + "waypoints": [ + { + "x": 721, + "y": 587 + } + ], + "required": 7, + "ocdTarget": 14 +} diff --git a/assets/gamedata/gootower/level-071.json b/assets/gamedata/gootower/level-071.json new file mode 100644 index 0000000..b8f8159 --- /dev/null +++ b/assets/gamedata/gootower/level-071.json @@ -0,0 +1,367 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 71, + "name": "Cave-In", + "chapter": 5, + "tip": "Drop a bomb by the fire and the soft rock goes with it. Or take the long way over.", + "element": "bomb", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + 0, + 850 + ], + [ + 1600, + 850 + ], + [ + 1600, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 692, + 652 + ], + [ + 772, + 652 + ], + [ + 772, + 850 + ], + [ + 692, + 850 + ] + ], + "destructible": true + }, + { + "kind": "fire", + "poly": [ + [ + 582, + 806 + ], + [ + 662, + 806 + ], + [ + 662, + 850 + ], + [ + 582, + 850 + ] + ] + } + ], + "balls": [ + { + "x": 409, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 471, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 440, + "y": 782, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 120, + "y": 834, + "type": "common" + }, + { + "x": 150, + "y": 834, + "type": "skull" + }, + { + "x": 180, + "y": 834, + "type": "bit" + }, + { + "x": 210, + "y": 834, + "type": "balloon" + }, + { + "x": 240, + "y": 834, + "type": "block" + }, + { + "x": 270, + "y": 834, + "type": "common" + }, + { + "x": 300, + "y": 834, + "type": "skull" + }, + { + "x": 120, + "y": 804, + "type": "bit" + }, + { + "x": 150, + "y": 804, + "type": "balloon" + }, + { + "x": 180, + "y": 804, + "type": "block" + }, + { + "x": 210, + "y": 804, + "type": "common" + }, + { + "x": 240, + "y": 804, + "type": "skull" + }, + { + "x": 270, + "y": 804, + "type": "bit" + }, + { + "x": 300, + "y": 804, + "type": "balloon" + }, + { + "x": 120, + "y": 774, + "type": "block" + }, + { + "x": 150, + "y": 774, + "type": "common" + }, + { + "x": 180, + "y": 774, + "type": "skull" + }, + { + "x": 210, + "y": 774, + "type": "bit" + }, + { + "x": 240, + "y": 774, + "type": "balloon" + }, + { + "x": 270, + "y": 774, + "type": "block" + }, + { + "x": 300, + "y": 774, + "type": "common" + }, + { + "x": 120, + "y": 744, + "type": "skull" + }, + { + "x": 150, + "y": 744, + "type": "bit" + }, + { + "x": 180, + "y": 744, + "type": "common" + }, + { + "x": 210, + "y": 744, + "type": "skull" + }, + { + "x": 240, + "y": 744, + "type": "bit" + }, + { + "x": 270, + "y": 744, + "type": "common" + }, + { + "x": 300, + "y": 744, + "type": "common" + }, + { + "x": 120, + "y": 714, + "type": "common" + }, + { + "x": 150, + "y": 714, + "type": "common" + }, + { + "x": 180, + "y": 714, + "type": "common" + }, + { + "x": 210, + "y": 714, + "type": "common" + }, + { + "x": 240, + "y": 714, + "type": "common" + }, + { + "x": 270, + "y": 714, + "type": "common" + }, + { + "x": 300, + "y": 714, + "type": "common" + }, + { + "x": 120, + "y": 684, + "type": "common" + }, + { + "x": 150, + "y": 684, + "type": "common" + }, + { + "x": 180, + "y": 684, + "type": "common" + }, + { + "x": 210, + "y": 684, + "type": "common" + }, + { + "x": 240, + "y": 684, + "type": "common" + } + ], + "pipe": { + "x": 1092, + "y": 700, + "r": 46 + }, + "waypoints": [ + { + "x": 732, + "y": 577 + } + ], + "required": 7, + "ocdTarget": 15 +} diff --git a/assets/gamedata/gootower/level-072.json b/assets/gamedata/gootower/level-072.json new file mode 100644 index 0000000..cf094a9 --- /dev/null +++ b/assets/gamedata/gootower/level-072.json @@ -0,0 +1,367 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 72, + "name": "The Last Charge", + "chapter": 5, + "tip": "Drop a bomb by the fire and the soft rock goes with it. Or take the long way over.", + "element": "bomb", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + 0, + 850 + ], + [ + 1600, + 850 + ], + [ + 1600, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 751, + 643 + ], + [ + 831, + 643 + ], + [ + 831, + 850 + ], + [ + 751, + 850 + ] + ], + "destructible": true + }, + { + "kind": "fire", + "poly": [ + [ + 641, + 806 + ], + [ + 721, + 806 + ], + [ + 721, + 850 + ], + [ + 641, + 850 + ] + ] + } + ], + "balls": [ + { + "x": 359, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 421, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 390, + "y": 782, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 100, + "y": 834, + "type": "common" + }, + { + "x": 130, + "y": 834, + "type": "skull" + }, + { + "x": 160, + "y": 834, + "type": "bit" + }, + { + "x": 190, + "y": 834, + "type": "balloon" + }, + { + "x": 220, + "y": 834, + "type": "block" + }, + { + "x": 250, + "y": 834, + "type": "common" + }, + { + "x": 280, + "y": 834, + "type": "skull" + }, + { + "x": 100, + "y": 804, + "type": "bit" + }, + { + "x": 130, + "y": 804, + "type": "balloon" + }, + { + "x": 160, + "y": 804, + "type": "block" + }, + { + "x": 190, + "y": 804, + "type": "common" + }, + { + "x": 220, + "y": 804, + "type": "skull" + }, + { + "x": 250, + "y": 804, + "type": "bit" + }, + { + "x": 280, + "y": 804, + "type": "balloon" + }, + { + "x": 100, + "y": 774, + "type": "block" + }, + { + "x": 130, + "y": 774, + "type": "common" + }, + { + "x": 160, + "y": 774, + "type": "skull" + }, + { + "x": 190, + "y": 774, + "type": "bit" + }, + { + "x": 220, + "y": 774, + "type": "balloon" + }, + { + "x": 250, + "y": 774, + "type": "block" + }, + { + "x": 280, + "y": 774, + "type": "common" + }, + { + "x": 100, + "y": 744, + "type": "skull" + }, + { + "x": 130, + "y": 744, + "type": "bit" + }, + { + "x": 160, + "y": 744, + "type": "common" + }, + { + "x": 190, + "y": 744, + "type": "skull" + }, + { + "x": 220, + "y": 744, + "type": "bit" + }, + { + "x": 250, + "y": 744, + "type": "common" + }, + { + "x": 280, + "y": 744, + "type": "common" + }, + { + "x": 100, + "y": 714, + "type": "common" + }, + { + "x": 130, + "y": 714, + "type": "common" + }, + { + "x": 160, + "y": 714, + "type": "common" + }, + { + "x": 190, + "y": 714, + "type": "common" + }, + { + "x": 220, + "y": 714, + "type": "common" + }, + { + "x": 250, + "y": 714, + "type": "common" + }, + { + "x": 280, + "y": 714, + "type": "common" + }, + { + "x": 100, + "y": 684, + "type": "common" + }, + { + "x": 130, + "y": 684, + "type": "common" + }, + { + "x": 160, + "y": 684, + "type": "common" + }, + { + "x": 190, + "y": 684, + "type": "common" + }, + { + "x": 220, + "y": 684, + "type": "common" + } + ], + "pipe": { + "x": 1114, + "y": 700, + "r": 46 + }, + "waypoints": [ + { + "x": 791, + "y": 568 + } + ], + "required": 8, + "ocdTarget": 17 +} diff --git a/assets/gamedata/gootower/level-073.json b/assets/gamedata/gootower/level-073.json new file mode 100644 index 0000000..babe8a3 --- /dev/null +++ b/assets/gamedata/gootower/level-073.json @@ -0,0 +1,317 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 73, + "name": "The Long Way Up", + "chapter": 5, + "tip": "Brace as you go. An unbraced column leans, and once it leans it keeps leaning.", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + 0, + 850 + ], + [ + 1600, + 850 + ], + [ + 1600, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + } + ], + "balls": [ + { + "x": 615, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 677, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 646, + "y": 782, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 906, + "y": 834, + "type": "common" + }, + { + "x": 936, + "y": 834, + "type": "skull" + }, + { + "x": 966, + "y": 834, + "type": "bit" + }, + { + "x": 996, + "y": 834, + "type": "balloon" + }, + { + "x": 1026, + "y": 834, + "type": "block" + }, + { + "x": 1056, + "y": 834, + "type": "common" + }, + { + "x": 1086, + "y": 834, + "type": "skull" + }, + { + "x": 1116, + "y": 834, + "type": "bit" + }, + { + "x": 1146, + "y": 834, + "type": "balloon" + }, + { + "x": 1176, + "y": 834, + "type": "block" + }, + { + "x": 1206, + "y": 834, + "type": "common" + }, + { + "x": 1236, + "y": 834, + "type": "skull" + }, + { + "x": 1266, + "y": 834, + "type": "bit" + }, + { + "x": 906, + "y": 804, + "type": "balloon" + }, + { + "x": 936, + "y": 804, + "type": "block" + }, + { + "x": 966, + "y": 804, + "type": "common" + }, + { + "x": 996, + "y": 804, + "type": "skull" + }, + { + "x": 1026, + "y": 804, + "type": "bit" + }, + { + "x": 1056, + "y": 804, + "type": "balloon" + }, + { + "x": 1086, + "y": 804, + "type": "block" + }, + { + "x": 1116, + "y": 804, + "type": "common" + }, + { + "x": 1146, + "y": 804, + "type": "skull" + }, + { + "x": 1176, + "y": 804, + "type": "bit" + }, + { + "x": 1206, + "y": 804, + "type": "common" + }, + { + "x": 1236, + "y": 804, + "type": "skull" + }, + { + "x": 1266, + "y": 804, + "type": "bit" + }, + { + "x": 906, + "y": 774, + "type": "common" + }, + { + "x": 936, + "y": 774, + "type": "common" + }, + { + "x": 966, + "y": 774, + "type": "common" + }, + { + "x": 996, + "y": 774, + "type": "common" + }, + { + "x": 1026, + "y": 774, + "type": "common" + }, + { + "x": 1056, + "y": 774, + "type": "common" + }, + { + "x": 1086, + "y": 774, + "type": "common" + }, + { + "x": 1116, + "y": 774, + "type": "common" + }, + { + "x": 1146, + "y": 774, + "type": "common" + }, + { + "x": 1176, + "y": 774, + "type": "common" + }, + { + "x": 1206, + "y": 774, + "type": "common" + }, + { + "x": 1236, + "y": 774, + "type": "common" + }, + { + "x": 1266, + "y": 774, + "type": "common" + }, + { + "x": 906, + "y": 744, + "type": "common" + } + ], + "pipe": { + "x": 646, + "y": 420, + "r": 46 + }, + "required": 6, + "ocdTarget": 13 +} diff --git a/assets/gamedata/gootower/level-074.json b/assets/gamedata/gootower/level-074.json new file mode 100644 index 0000000..862a474 --- /dev/null +++ b/assets/gamedata/gootower/level-074.json @@ -0,0 +1,317 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 74, + "name": "Ascent", + "chapter": 5, + "tip": "Brace as you go. An unbraced column leans, and once it leans it keeps leaning.", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + 0, + 850 + ], + [ + 1600, + 850 + ], + [ + 1600, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + } + ], + "balls": [ + { + "x": 780, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 842, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 811, + "y": 782, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 1071, + "y": 834, + "type": "common" + }, + { + "x": 1101, + "y": 834, + "type": "skull" + }, + { + "x": 1131, + "y": 834, + "type": "bit" + }, + { + "x": 1161, + "y": 834, + "type": "balloon" + }, + { + "x": 1191, + "y": 834, + "type": "block" + }, + { + "x": 1221, + "y": 834, + "type": "common" + }, + { + "x": 1251, + "y": 834, + "type": "skull" + }, + { + "x": 1281, + "y": 834, + "type": "bit" + }, + { + "x": 1311, + "y": 834, + "type": "balloon" + }, + { + "x": 1341, + "y": 834, + "type": "block" + }, + { + "x": 1371, + "y": 834, + "type": "common" + }, + { + "x": 1401, + "y": 834, + "type": "skull" + }, + { + "x": 1431, + "y": 834, + "type": "bit" + }, + { + "x": 1071, + "y": 804, + "type": "balloon" + }, + { + "x": 1101, + "y": 804, + "type": "block" + }, + { + "x": 1131, + "y": 804, + "type": "common" + }, + { + "x": 1161, + "y": 804, + "type": "skull" + }, + { + "x": 1191, + "y": 804, + "type": "bit" + }, + { + "x": 1221, + "y": 804, + "type": "balloon" + }, + { + "x": 1251, + "y": 804, + "type": "block" + }, + { + "x": 1281, + "y": 804, + "type": "common" + }, + { + "x": 1311, + "y": 804, + "type": "skull" + }, + { + "x": 1341, + "y": 804, + "type": "bit" + }, + { + "x": 1371, + "y": 804, + "type": "common" + }, + { + "x": 1401, + "y": 804, + "type": "skull" + }, + { + "x": 1431, + "y": 804, + "type": "bit" + }, + { + "x": 1071, + "y": 774, + "type": "common" + }, + { + "x": 1101, + "y": 774, + "type": "common" + }, + { + "x": 1131, + "y": 774, + "type": "common" + }, + { + "x": 1161, + "y": 774, + "type": "common" + }, + { + "x": 1191, + "y": 774, + "type": "common" + }, + { + "x": 1221, + "y": 774, + "type": "common" + }, + { + "x": 1251, + "y": 774, + "type": "common" + }, + { + "x": 1281, + "y": 774, + "type": "common" + }, + { + "x": 1311, + "y": 774, + "type": "common" + }, + { + "x": 1341, + "y": 774, + "type": "common" + }, + { + "x": 1371, + "y": 774, + "type": "common" + }, + { + "x": 1401, + "y": 774, + "type": "common" + }, + { + "x": 1431, + "y": 774, + "type": "common" + }, + { + "x": 1071, + "y": 744, + "type": "common" + } + ], + "pipe": { + "x": 811, + "y": 349, + "r": 46 + }, + "required": 7, + "ocdTarget": 15 +} diff --git a/assets/gamedata/gootower/level-075.json b/assets/gamedata/gootower/level-075.json new file mode 100644 index 0000000..b5f0ee1 --- /dev/null +++ b/assets/gamedata/gootower/level-075.json @@ -0,0 +1,317 @@ +{ + "world": { + "w": 1600, + "h": 1000 + }, + "level": 75, + "name": "Out", + "chapter": 5, + "tip": "Brace as you go. An unbraced column leans, and once it leans it keeps leaning.", + "terrain": [ + { + "kind": "solid", + "poly": [ + [ + 0, + 850 + ], + [ + 1600, + 850 + ], + [ + 1600, + 1000 + ], + [ + 0, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + -30, + 0 + ], + [ + 6, + 0 + ], + [ + 6, + 1000 + ], + [ + -30, + 1000 + ] + ] + }, + { + "kind": "solid", + "poly": [ + [ + 1594, + 0 + ], + [ + 1630, + 0 + ], + [ + 1630, + 1000 + ], + [ + 1594, + 1000 + ] + ] + } + ], + "balls": [ + { + "x": 589, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 651, + "y": 836, + "type": "common", + "pinned": true + }, + { + "x": 620, + "y": 782, + "type": "common" + } + ], + "strands": [ + [ + 2, + 0 + ], + [ + 2, + 1 + ], + [ + 0, + 1 + ] + ], + "pile": [ + { + "x": 880, + "y": 834, + "type": "common" + }, + { + "x": 910, + "y": 834, + "type": "skull" + }, + { + "x": 940, + "y": 834, + "type": "bit" + }, + { + "x": 970, + "y": 834, + "type": "balloon" + }, + { + "x": 1000, + "y": 834, + "type": "block" + }, + { + "x": 1030, + "y": 834, + "type": "common" + }, + { + "x": 1060, + "y": 834, + "type": "skull" + }, + { + "x": 1090, + "y": 834, + "type": "bit" + }, + { + "x": 1120, + "y": 834, + "type": "balloon" + }, + { + "x": 1150, + "y": 834, + "type": "block" + }, + { + "x": 1180, + "y": 834, + "type": "common" + }, + { + "x": 1210, + "y": 834, + "type": "skull" + }, + { + "x": 1240, + "y": 834, + "type": "bit" + }, + { + "x": 880, + "y": 804, + "type": "balloon" + }, + { + "x": 910, + "y": 804, + "type": "block" + }, + { + "x": 940, + "y": 804, + "type": "common" + }, + { + "x": 970, + "y": 804, + "type": "skull" + }, + { + "x": 1000, + "y": 804, + "type": "bit" + }, + { + "x": 1030, + "y": 804, + "type": "balloon" + }, + { + "x": 1060, + "y": 804, + "type": "block" + }, + { + "x": 1090, + "y": 804, + "type": "common" + }, + { + "x": 1120, + "y": 804, + "type": "skull" + }, + { + "x": 1150, + "y": 804, + "type": "bit" + }, + { + "x": 1180, + "y": 804, + "type": "common" + }, + { + "x": 1210, + "y": 804, + "type": "skull" + }, + { + "x": 1240, + "y": 804, + "type": "bit" + }, + { + "x": 880, + "y": 774, + "type": "common" + }, + { + "x": 910, + "y": 774, + "type": "common" + }, + { + "x": 940, + "y": 774, + "type": "common" + }, + { + "x": 970, + "y": 774, + "type": "common" + }, + { + "x": 1000, + "y": 774, + "type": "common" + }, + { + "x": 1030, + "y": 774, + "type": "common" + }, + { + "x": 1060, + "y": 774, + "type": "common" + }, + { + "x": 1090, + "y": 774, + "type": "common" + }, + { + "x": 1120, + "y": 774, + "type": "common" + }, + { + "x": 1150, + "y": 774, + "type": "common" + }, + { + "x": 1180, + "y": 774, + "type": "common" + }, + { + "x": 1210, + "y": 774, + "type": "common" + }, + { + "x": 1240, + "y": 774, + "type": "common" + }, + { + "x": 880, + "y": 744, + "type": "common" + } + ], + "pipe": { + "x": 620, + "y": 361, + "r": 46 + }, + "required": 7, + "ocdTarget": 15 +} diff --git a/assets/gamedata/gootower/levels.json b/assets/gamedata/gootower/levels.json index 7da1e78..d47503c 100644 --- a/assets/gamedata/gootower/levels.json +++ b/assets/gamedata/gootower/levels.json @@ -1,6 +1,6 @@ { - "version": 1, - "generatedAt": "1970-01-01T00:00:00.000Z", + "version": 2, + "seed": 6294814, "levels": [ { "level": 1, @@ -52,73 +52,623 @@ }, { "level": 7, - "name": "Anchors Aweigh", - "chapter": 2, + "name": "Uphill", + "chapter": 1, "file": "level-007.json", - "required": 5, - "ocdTarget": 12, - "sandbox": true + "required": 4, + "ocdTarget": 9 }, { "level": 8, - "name": "Sticking Point", - "chapter": 2, + "name": "Higher Ground", + "chapter": 1, "file": "level-008.json", "required": 5, - "ocdTarget": 12, - "sandbox": true + "ocdTarget": 10 }, { "level": 9, - "name": "Demolition", - "chapter": 2, + "name": "The Long Climb", + "chapter": 1, "file": "level-009.json", - "required": 5, - "ocdTarget": 12, - "sandbox": true + "required": 6, + "ocdTarget": 12 }, { "level": 10, - "name": "Updraft", - "chapter": 2, + "name": "Across", + "chapter": 1, "file": "level-010.json", "required": 4, - "ocdTarget": 12, - "sandbox": true + "ocdTarget": 8 }, { "level": 11, - "name": "Cogs", - "chapter": 2, + "name": "Wider Still", + "chapter": 1, "file": "level-011.json", "required": 5, - "ocdTarget": 13, - "sandbox": true + "ocdTarget": 10 }, { "level": 12, - "name": "Lighter Than Air", - "chapter": 2, + "name": "The Drop", + "chapter": 1, "file": "level-012.json", + "required": 6, + "ocdTarget": 12 + }, + { + "level": 13, + "name": "Under It", + "chapter": 1, + "file": "level-013.json", "required": 5, + "ocdTarget": 10 + }, + { + "level": 14, + "name": "Round the Back", + "chapter": 1, + "file": "level-014.json", + "required": 5, + "ocdTarget": 10 + }, + { + "level": 15, + "name": "Out and Up", + "chapter": 1, + "file": "level-015.json", + "required": 6, + "ocdTarget": 13 + }, + { + "level": 16, + "name": "Light Head", + "chapter": 2, + "file": "level-016.json", + "required": 6, + "ocdTarget": 12 + }, + { + "level": 17, + "name": "Buoyant", + "chapter": 2, + "file": "level-017.json", + "required": 6, + "ocdTarget": 12 + }, + { + "level": 18, + "name": "Low Ceiling", + "chapter": 2, + "file": "level-018.json", + "required": 5, + "ocdTarget": 10 + }, + { + "level": 19, + "name": "Mind Your Head", + "chapter": 2, + "file": "level-019.json", + "required": 6, + "ocdTarget": 12 + }, + { + "level": 20, + "name": "Overhead", + "chapter": 2, + "file": "level-020.json", + "required": 6, + "ocdTarget": 13 + }, + { + "level": 21, + "name": "First Gust", + "chapter": 2, + "file": "level-021.json", + "required": 4, + "ocdTarget": 9 + }, + { + "level": 22, + "name": "Updraft", + "chapter": 2, + "file": "level-022.json", + "required": 5, + "ocdTarget": 10 + }, + { + "level": 23, + "name": "Riding the Wind", + "chapter": 2, + "file": "level-023.json", + "required": 6, "ocdTarget": 12, - "sandbox": true + "element": "fan" + }, + { + "level": 24, + "name": "Thermals", + "chapter": 2, + "file": "level-024.json", + "required": 6, + "ocdTarget": 13, + "element": "fan" + }, + { + "level": 25, + "name": "Long Reach", + "chapter": 2, + "file": "level-025.json", + "required": 6, + "ocdTarget": 12 + }, + { + "level": 26, + "name": "The Wide Crossing", + "chapter": 2, + "file": "level-026.json", + "required": 6, + "ocdTarget": 13 + }, + { + "level": 27, + "name": "Windswept", + "chapter": 2, + "file": "level-027.json", + "required": 7, + "ocdTarget": 15 + }, + { + "level": 28, + "name": "Gale", + "chapter": 2, + "file": "level-028.json", + "required": 6, + "ocdTarget": 13, + "element": "fan" + }, + { + "level": 29, + "name": "Squall", + "chapter": 2, + "file": "level-029.json", + "required": 6, + "ocdTarget": 13 + }, + { + "level": 30, + "name": "Headwind", + "chapter": 2, + "file": "level-030.json", + "required": 5, + "ocdTarget": 11 + }, + { + "level": 31, + "name": "First Cog", + "chapter": 3, + "file": "level-031.json", + "required": 4, + "ocdTarget": 8, + "element": "gear" + }, + { + "level": 32, + "name": "Gearworks", + "chapter": 3, + "file": "level-032.json", + "required": 5, + "ocdTarget": 10, + "element": "gear" + }, + { + "level": 33, + "name": "Clockwise", + "chapter": 3, + "file": "level-033.json", + "required": 5, + "ocdTarget": 11, + "element": "gear" + }, + { + "level": 34, + "name": "Widdershins", + "chapter": 3, + "file": "level-034.json", + "required": 6, + "ocdTarget": 12, + "element": "gear" + }, + { + "level": 35, + "name": "Rigid Thinking", + "chapter": 3, + "file": "level-035.json", + "required": 6, + "ocdTarget": 13 + }, + { + "level": 36, + "name": "Girders", + "chapter": 3, + "file": "level-036.json", + "required": 7, + "ocdTarget": 15 + }, + { + "level": 37, + "name": "Soft Rock", + "chapter": 3, + "file": "level-037.json", + "required": 4, + "ocdTarget": 8, + "element": "bomb" + }, + { + "level": 38, + "name": "Demolition", + "chapter": 3, + "file": "level-038.json", + "required": 5, + "ocdTarget": 10, + "element": "bomb" + }, + { + "level": 39, + "name": "Blast Radius", + "chapter": 3, + "file": "level-039.json", + "required": 6, + "ocdTarget": 12, + "element": "bomb" + }, + { + "level": 40, + "name": "Controlled Burn", + "chapter": 3, + "file": "level-040.json", + "required": 6, + "ocdTarget": 13, + "element": "bomb" + }, + { + "level": 41, + "name": "The Machine", + "chapter": 3, + "file": "level-041.json", + "required": 6, + "ocdTarget": 13, + "element": "gear" + }, + { + "level": 42, + "name": "Grinding Gears", + "chapter": 3, + "file": "level-042.json", + "required": 7, + "ocdTarget": 15, + "element": "gear" + }, + { + "level": 43, + "name": "Flywheel", + "chapter": 3, + "file": "level-043.json", + "required": 8, + "ocdTarget": 17, + "element": "gear" + }, + { + "level": 44, + "name": "Under the Works", + "chapter": 3, + "file": "level-044.json", + "required": 6, + "ocdTarget": 13 + }, + { + "level": 45, + "name": "Assembly", + "chapter": 3, + "file": "level-045.json", + "required": 7, + "ocdTarget": 15 + }, + { + "level": 46, + "name": "Handhold", + "chapter": 4, + "file": "level-046.json", + "required": 5, + "ocdTarget": 10, + "element": "anchor" + }, + { + "level": 47, + "name": "Two Pillars", + "chapter": 4, + "file": "level-047.json", + "required": 5, + "ocdTarget": 10, + "element": "anchor" + }, + { + "level": 48, + "name": "Stepping Up", + "chapter": 4, + "file": "level-048.json", + "required": 6, + "ocdTarget": 12, + "element": "anchor" + }, + { + "level": 49, + "name": "The Face", + "chapter": 4, + "file": "level-049.json", + "required": 5, + "ocdTarget": 10, + "element": "anchor" + }, + { + "level": 50, + "name": "Sheer", + "chapter": 4, + "file": "level-050.json", + "required": 5, + "ocdTarget": 10, + "element": "anchor" + }, + { + "level": 51, + "name": "Traverse", + "chapter": 4, + "file": "level-051.json", + "required": 6, + "ocdTarget": 12, + "element": "anchor" + }, + { + "level": 52, + "name": "Grip", + "chapter": 4, + "file": "level-052.json", + "required": 6, + "ocdTarget": 12, + "element": "anchor" + }, + { + "level": 53, + "name": "Overhanging", + "chapter": 4, + "file": "level-053.json", + "required": 6, + "ocdTarget": 13 + }, + { + "level": 54, + "name": "Cliffhanger", + "chapter": 4, + "file": "level-054.json", + "required": 7, + "ocdTarget": 15 + }, + { + "level": 55, + "name": "The Chimney", + "chapter": 4, + "file": "level-055.json", + "required": 6, + "ocdTarget": 12, + "element": "anchor" + }, + { + "level": 56, + "name": "Freeclimb", + "chapter": 4, + "file": "level-056.json", + "required": 6, + "ocdTarget": 13 + }, + { + "level": 57, + "name": "The Notch", + "chapter": 4, + "file": "level-057.json", + "required": 7, + "ocdTarget": 14 + }, + { + "level": 58, + "name": "Crevasse", + "chapter": 4, + "file": "level-058.json", + "required": 6, + "ocdTarget": 13 + }, + { + "level": 59, + "name": "Exposure", + "chapter": 4, + "file": "level-059.json", + "required": 7, + "ocdTarget": 14 + }, + { + "level": 60, + "name": "Summit", + "chapter": 4, + "file": "level-060.json", + "required": 7, + "ocdTarget": 14 + }, + { + "level": 61, + "name": "Descent", + "chapter": 5, + "file": "level-061.json", + "required": 6, + "ocdTarget": 13 + }, + { + "level": 62, + "name": "Low Roof", + "chapter": 5, + "file": "level-062.json", + "required": 7, + "ocdTarget": 15 + }, + { + "level": 63, + "name": "The Squeeze", + "chapter": 5, + "file": "level-063.json", + "required": 7, + "ocdTarget": 15 + }, + { + "level": 64, + "name": "Deep Wind", + "chapter": 5, + "file": "level-064.json", + "required": 6, + "ocdTarget": 13, + "element": "fan" + }, + { + "level": 65, + "name": "The Shaft", + "chapter": 5, + "file": "level-065.json", + "required": 7, + "ocdTarget": 15, + "element": "fan" + }, + { + "level": 66, + "name": "Downdraft", + "chapter": 5, + "file": "level-066.json", + "required": 8, + "ocdTarget": 17, + "element": "fan" + }, + { + "level": 67, + "name": "Deep Cogs", + "chapter": 5, + "file": "level-067.json", + "required": 6, + "ocdTarget": 13, + "element": "gear" + }, + { + "level": 68, + "name": "The Grinder", + "chapter": 5, + "file": "level-068.json", + "required": 7, + "ocdTarget": 15, + "element": "gear" + }, + { + "level": 69, + "name": "Millstone", + "chapter": 5, + "file": "level-069.json", + "required": 8, + "ocdTarget": 17, + "element": "gear" + }, + { + "level": 70, + "name": "Deep Rock", + "chapter": 5, + "file": "level-070.json", + "required": 7, + "ocdTarget": 14, + "element": "bomb" + }, + { + "level": 71, + "name": "Cave-In", + "chapter": 5, + "file": "level-071.json", + "required": 7, + "ocdTarget": 15, + "element": "bomb" + }, + { + "level": 72, + "name": "The Last Charge", + "chapter": 5, + "file": "level-072.json", + "required": 8, + "ocdTarget": 17, + "element": "bomb" + }, + { + "level": 73, + "name": "The Long Way Up", + "chapter": 5, + "file": "level-073.json", + "required": 6, + "ocdTarget": 13 + }, + { + "level": 74, + "name": "Ascent", + "chapter": 5, + "file": "level-074.json", + "required": 7, + "ocdTarget": 15 + }, + { + "level": 75, + "name": "Out", + "chapter": 5, + "file": "level-075.json", + "required": 7, + "ocdTarget": 15 } ], "chapters": [ { "id": 1, - "name": "The Goo Filled Hills", - "blurb": "Learn to build.", + "name": "The Rolling Hills", + "blurb": "Learn to build. Everything after this assumes you can.", "from": 1, - "to": 6 + "to": 15 }, { "id": 2, - "name": "Sandbox", - "blurb": "One level per mechanic — throwaway, replaced in Wave 4.", - "from": 7, - "to": 12 + "name": "Windward", + "blurb": "Wind, balloons, and things that would rather float away.", + "from": 16, + "to": 30 + }, + { + "id": 3, + "name": "The Works", + "blurb": "Machinery. It does not care what you built.", + "from": 31, + "to": 45 + }, + { + "id": 4, + "name": "The Sticky Cliffs", + "blurb": "No ground worth standing on. Grip the rock.", + "from": 46, + "to": 60 + }, + { + "id": 5, + "name": "Down the Deep", + "blurb": "Everything you have learned, all at once.", + "from": 61, + "to": 75 } ] } diff --git a/docs/gootower-build-plan.md b/docs/gootower-build-plan.md index 3dd110f..793ff4e 100644 --- a/docs/gootower-build-plan.md +++ b/docs/gootower-build-plan.md @@ -3,11 +3,11 @@ Living plan doc. Survives context clears: **read this file first**, pick the next unchecked item, update the checkboxes and the "Status" line as work lands. -**Status:** **Waves 0–3 complete (2026-07-26).** All nine goo types and every hazard are -live, with a 6-level sandbox tier on top of the 6-level teaching chapter — -`node tools/verifyGooTower.js` → **303 checks green**, including a reference player that -beats all **12** levels headlessly. **Never opened in a browser** — Brian playtests, and -Waves 1–3 are not signed off until he has. +**Status:** **COMPLETE — all five waves done (2026-07-26).** Nine goo types, every hazard, +a level editor, and a **75-level campaign in 5 chapters** — +`node tools/verifyGooTower.js` → **1061 checks green**, including a reference player that +beats every one of the 75 levels headlessly. **Never opened in a browser** — Brian +playtests, and nothing here is signed off until he has. --- @@ -29,9 +29,9 @@ Waves 1–3 are not signed off until he has. | `src/games/gootower/tutorial.md` | `hasTutorial: true` | done | | `src/games/gootower/GooTowerEditor.js` | Level editor, `?gootower-editor=1` | Wave 2 done | | `src/games/gootower/GooTowerAuto.js` | Greedy reference player = the winnability gate | done | -| `tools/verifyGooTower.js` | Regression harness, **303 checks** | Waves 0–3 done | -| `tools/genGooTower.js` | Level bank writer (12 hand-tuned levels) | Wave 3 done | -| `assets/gamedata/gootower/levels.json` | Manifest + per-level `level-NNN.json` | 12 levels | +| `tools/verifyGooTower.js` | Regression harness, **1061 checks** | all waves | +| `tools/genGooTower.js` | Curriculum generator (5 chapters x 15) | Wave 4 done | +| `assets/gamedata/gootower/levels.json` | Manifest + per-level `level-NNN.json` | **75 levels** | `GooTowerAuto.js` lives in `src/`, not `tools/`, because the editor's "Test Winnable" button must run exactly the gate the verifier runs. diff --git a/src/games/gootower/GooTowerGame.js b/src/games/gootower/GooTowerGame.js index 20b5567..d58b4f0 100644 --- a/src/games/gootower/GooTowerGame.js +++ b/src/games/gootower/GooTowerGame.js @@ -40,17 +40,30 @@ const GOO_COLOR = { anchor: 0x5a4a3a, }; -// Phaser Containers render children in insertion order and IGNORE child depth, -// so every layer here is a root-level object with its own setDepth. +// Phaser Containers render children in insertion order and IGNORE child depth. +// The HUD and overlays are root-level objects ordered by these depths; the +// board's own layers live inside `this.board` and are ordered by insertion. const D = { sky: -10, terrain: 0, pipe: 4, strand: 8, ball: 10, ghost: 14, hud: 30, overlay: 60, overlayUI: 62, }; -// World-space -> screen-space. The world is 1600x1000 on a 1920x1080 canvas, -// so it fits outright and there is no camera to drive. -const OX = 160; -const OY = 70; +// World-space -> screen-space. +// +// Everything on the board is drawn at RAW WORLD COORDINATES into `this.board`, +// a container whose position and scale are the view transform. That is what +// makes zoom free: no drawing code knows the view exists. +// +// Phaser containers ignore child depth and render in insertion order, so the +// board's layers are added in the order they must paint: terrain, then the +// per-frame layer, then the drag ghost. +const WORLD_W = 1600; +const WORLD_H = 1000; +const VIEW_HOME = { scale: 1, ox: 160, oy: 70 }; +const ZOOM_MIN = 0.45; +const ZOOM_MAX = 9; +const ZOOM_STEP = 1.15; +const VIEW_KEEP = 0.35; // fraction of the viewport that must stay over the board const shade = (color, f) => { const ch = (s) => Math.min(255, Math.round(((color >> s) & 0xff) * f)); @@ -79,7 +92,7 @@ export default class GooTowerGame extends Phaser.Scene { this.canPersist = true; this.levelCache = new Map(); - this.view = 'select'; + this.viewMode = 'select'; this.level = 0; this.levelDef = null; this.state = null; @@ -88,6 +101,8 @@ export default class GooTowerGame extends Phaser.Scene { this.boardObjs = []; this.overlayUp = false; this.finished = false; + this.view = { ...VIEW_HOME }; + this.panFrom = null; } async create() { @@ -134,6 +149,8 @@ export default class GooTowerGame extends Phaser.Scene { this.dyn = null; this.ghost = null; this.terrainG = null; + this.board = null; + this.panFrom = null; this.needText = null; this.hudText = null; } @@ -150,75 +167,80 @@ export default class GooTowerGame extends Phaser.Scene { } showSelect() { - this.view = 'select'; + this.viewMode = 'select'; this.state = null; this.held = null; this.clearBoard(); const cx = GAME_WIDTH / 2; - this.track(this.add.text(cx, 70, 'Goo Tower', { - fontFamily: 'Righteous', fontSize: '58px', color: COLORS.textHex, + this.track(this.add.text(cx, 56, 'Goo Tower', { + fontFamily: 'Righteous', fontSize: '46px', color: COLORS.textHex, }).setOrigin(0.5).setDepth(D.hud)); this.tooltip = new Tooltip(this); - let y = 190; + // Five chapters of fifteen. Tiles are compact and evenly spread; the + // level's name lives in the hover tooltip rather than on the tile, because + // fifteen across leaves no room for it. + const TILE_W = 92; + const TILE_H = 66; + const STEP = 106; + let y = 148; for (const ch of this.chapters) { - this.track(this.add.text(140, y, ch.name, { - fontFamily: 'Righteous', fontSize: '30px', color: COLORS.goldHex, + const levels = this.manifest.filter((m) => m.level >= ch.from && m.level <= ch.to); + this.track(this.add.text(70, y, ch.name, { + fontFamily: 'Righteous', fontSize: '26px', color: COLORS.goldHex, }).setDepth(D.hud)); if (ch.blurb) { - this.track(this.add.text(140, y + 36, ch.blurb, { - fontFamily: '"Julius Sans One"', fontSize: '20px', color: '#9aa7b4', + this.track(this.add.text(70, y + 32, ch.blurb, { + fontFamily: '"Julius Sans One"', fontSize: '16px', color: '#8b98a6', }).setDepth(D.hud)); } - const levels = this.manifest.filter((m) => m.level >= ch.from && m.level <= ch.to); - let x = 150; + const rowW = (levels.length - 1) * STEP; + let x = GAME_WIDTH / 2 - rowW / 2; for (const m of levels) { const unlocked = m.level <= this.levelsCompleted + 1; const cleared = m.level <= this.levelsCompleted; - this.makeLevelTile(x, y + 110, m, unlocked, cleared); - x += 175; + this.makeLevelTile(x, y + 70, m, unlocked, cleared, TILE_W, TILE_H); + x += STEP; } - y += 260; + y += 168; } - this.track(new Button(this, cx, GAME_HEIGHT - 70, 'Back', () => this.scene.start('GameMenu'), - { variant: 'ghost', width: 200 }).setDepth(D.hud)); + this.track(new Button(this, cx, GAME_HEIGHT - 46, 'Back', () => this.scene.start('GameMenu'), + { variant: 'ghost', width: 180, height: 52 }).setDepth(D.hud)); if (this.levelsCompleted > 0) { - this.track(new Button(this, 210, GAME_HEIGHT - 70, 'Reset Progress', - () => this.resetProgress(), { variant: 'ghost', width: 260, fontSize: 20 }).setDepth(D.hud)); + this.track(new Button(this, 210, GAME_HEIGHT - 46, 'Reset Progress', + () => this.resetProgress(), { variant: 'ghost', width: 240, height: 52, fontSize: 19 }).setDepth(D.hud)); } } - makeLevelTile(x, y, m, unlocked, cleared) { - const w = 150; - const h = 120; + makeLevelTile(x, y, m, unlocked, cleared, w = 92, h = 66) { const g = this.add.graphics().setDepth(D.hud); const base = cleared ? 0x2b4a3a : unlocked ? 0x2a3547 : 0x1b2029; g.fillStyle(base, 1); - g.fillRoundedRect(x - w / 2, y - h / 2, w, h, 10); + g.fillRoundedRect(x - w / 2, y - h / 2, w, h, 8); g.lineStyle(2, cleared ? 0x63c132 : unlocked ? 0x5b7fa8 : 0x2a3038, 1); - g.strokeRoundedRect(x - w / 2, y - h / 2, w, h, 10); + g.strokeRoundedRect(x - w / 2, y - h / 2, w, h, 8); this.track(g); - this.track(this.add.text(x, y - 30, String(m.level), { - fontFamily: 'Righteous', fontSize: '34px', - color: unlocked ? COLORS.textHex : '#4a5560', - }).setOrigin(0.5).setDepth(D.hud)); - this.track(this.add.text(x, y + 12, unlocked ? m.name : 'Locked', { - fontFamily: '"Julius Sans One"', fontSize: '15px', - color: unlocked ? '#b9c6d2' : '#4a5560', - wordWrap: { width: w - 16 }, align: 'center', + const best = this.bestFor(m.level); + this.track(this.add.text(x, y - 10, String(m.level), { + fontFamily: 'Righteous', fontSize: '26px', + color: unlocked ? COLORS.textHex : '#455060', }).setOrigin(0.5).setDepth(D.hud)); - const best = this.bestFor(m.level); if (best.count > 0) { - this.track(this.add.text(x, y + 44, best.ocd ? `★ ${best.count}` : `${best.count}`, { - fontFamily: '"Julius Sans One"', fontSize: '16px', + this.track(this.add.text(x, y + 18, best.ocd ? `\u2605 ${best.count}` : `${best.count}`, { + fontFamily: '"Julius Sans One"', fontSize: '14px', color: best.ocd ? '#ffd166' : '#7f8c99', }).setOrigin(0.5).setDepth(D.hud)); + } else if (unlocked && m.element) { + // A pip naming the mechanic this level is built around. + this.track(this.add.text(x, y + 18, m.element, { + fontFamily: '"Julius Sans One"', fontSize: '12px', color: '#6f7c8a', + }).setOrigin(0.5).setDepth(D.hud)); } if (!unlocked) return; @@ -228,8 +250,12 @@ export default class GooTowerGame extends Phaser.Scene { hit.on('pointerup', () => this.startLevel(m.level)); if (this.tooltip) { this.tooltip.attachTo(hit, () => ({ - title: m.name, - lines: [`Collect ${m.required} to finish`, `OCD target: ${m.ocdTarget}`], + title: `${m.level}. ${m.name}`, + lines: [ + `Collect ${m.required} to finish`, + `OCD target: ${m.ocdTarget}`, + ...(best.count ? [`Best: ${best.count}${best.ocd ? ' \u2605 OCD' : ''}`] : []), + ], })); } this.track(hit); @@ -282,7 +308,7 @@ export default class GooTowerGame extends Phaser.Scene { if (!def) { this.showSelect(); return; } this.clearBoard(); - this.view = 'play'; + this.viewMode = 'play'; this.level = level; this.levelDef = def; this.state = createState(def, 0x60071e + level); @@ -291,10 +317,17 @@ export default class GooTowerGame extends Phaser.Scene { this.overlayUp = false; this.finished = false; - this.terrainG = this.track(this.add.graphics().setDepth(D.terrain)); + // One container for the whole board; its transform is the view. Children + // are added in paint order because containers ignore child depth. + this.board = this.track(this.add.container(0, 0).setDepth(D.terrain)); + this.terrainG = this.add.graphics(); + this.dyn = this.add.graphics(); + this.ghost = this.add.graphics(); + this.board.add([this.terrainG, this.dyn, this.ghost]); + + this.view = { ...VIEW_HOME }; + this.applyView(); this.drawTerrain(); - this.dyn = this.track(this.add.graphics().setDepth(D.strand)); - this.ghost = this.track(this.add.graphics().setDepth(D.ghost)); this.buildHud(); } @@ -305,7 +338,7 @@ export default class GooTowerGame extends Phaser.Scene { g.clear(); for (const t of this.state.terrain) { if (t.gear) continue; // gears rotate; they are drawn per-frame instead - const pts = t.poly.map(([x, y]) => ({ x: x + OX, y: y + OY })); + const pts = t.poly.map(([x, y]) => ({ x, y })); if (t.kind === 'solid') { g.fillStyle(DIRT, 1); g.fillPoints(pts, true); @@ -324,8 +357,7 @@ export default class GooTowerGame extends Phaser.Scene { g.lineStyle(1, 0xd9a066, 0.5); const bb = t.bounds; for (let x = bb.minX; x < bb.maxX + (bb.maxY - bb.minY); x += 16) { - g.lineBetween(x + OX, bb.minY + OY, - x - (bb.maxY - bb.minY) + OX, bb.maxY + OY); + g.lineBetween(x, bb.minY, x - (bb.maxY - bb.minY), bb.maxY); } } } @@ -335,15 +367,15 @@ export default class GooTowerGame extends Phaser.Scene { drawFans(g) { for (const f of this.state.fans) { g.fillStyle(0x8fd0e8, 0.07); - g.fillRect(f.x + OX, f.y + OY, f.w, f.h); + g.fillRect(f.x, f.y, f.w, f.h); g.lineStyle(1, 0x8fd0e8, 0.28); - g.strokeRect(f.x + OX, f.y + OY, f.w, f.h); + g.strokeRect(f.x, f.y, f.w, f.h); // Chevrons pointing the way the wind blows. const step = 56; for (let x = f.x + step / 2; x < f.x + f.w; x += step) { for (let y = f.y + step / 2; y < f.y + f.h; y += step) { - const cx = x + OX; - const cy = y + OY; + const cx = x; + const cy = y; const ax = f.dx * 12; const ay = f.dy * 12; g.lineStyle(2, 0x8fd0e8, 0.32); @@ -358,13 +390,13 @@ export default class GooTowerGame extends Phaser.Scene { drawGears(g) { for (const t of this.state.terrain) { if (!t.gear) continue; - const pts = t.poly.map(([x, y]) => ({ x: x + OX, y: y + OY })); + const pts = t.poly.map(([x, y]) => ({ x, y })); g.fillStyle(0x4a4260, 1); g.fillPoints(pts, true); g.lineStyle(3, 0x8a7fb0, 1); g.strokePoints(pts, true); - const cx = t.gear.cx + OX; - const cy = t.gear.cy + OY; + const cx = t.gear.cx; + const cy = t.gear.cy; g.fillStyle(0x2a2438, 1); g.fillCircle(cx, cy, t.gear.r * 0.3); // A spoke, so the rotation is legible. @@ -394,9 +426,9 @@ export default class GooTowerGame extends Phaser.Scene { const x0 = ax + step * k; const x1 = x0 + step; g.fillTriangle( - x0 + OX, mid + OY, - x1 + OX, mid + OY, - (x0 + x1) / 2 + OX, mid + OY + up * 20, + x0, mid, + x1, mid, + (x0 + x1) / 2, mid + up * 20, ); } } @@ -407,6 +439,9 @@ export default class GooTowerGame extends Phaser.Scene { this.hudText = this.track(this.add.text(40, 26, '', { fontFamily: '"Julius Sans One"', fontSize: '26px', color: COLORS.textHex, }).setDepth(D.hud)); + this.track(this.add.text(40, 58, 'wheel: zoom to cursor · right-drag: pan · 0: reset view', { + fontFamily: '"Julius Sans One"', fontSize: '15px', color: '#5f6b78', + }).setDepth(D.hud)); this.tipText = this.track(this.add.text(GAME_WIDTH / 2, 30, this.levelDef.tip || '', { fontFamily: '"Julius Sans One"', fontSize: '19px', color: '#9aa7b4', wordWrap: { width: 760 }, align: 'center', @@ -428,20 +463,83 @@ export default class GooTowerGame extends Phaser.Scene { ); } + // ── View: zoom and pan ──────────────────────────────────────────────────── + + applyView() { + this.clampView(); + if (!this.board) return; + this.board.setScale(this.view.scale); + this.board.setPosition(this.view.ox, this.view.oy); + } + + // Keep at least VIEW_KEEP of the viewport covered by board, rather than + // forcing the whole board on screen. Forcing it leaves the clamp fighting the + // zoom anchor near the edges -- the point under the cursor slides away, which + // is exactly what zoom-to-cursor is supposed to prevent. With this the anchor + // is pixel-exact everywhere except when you push past the bounds. + clampView() { + const clampAxis = (v, span, viewport) => Math.max( + viewport * VIEW_KEEP - span, + Math.min(viewport * (1 - VIEW_KEEP), v), + ); + this.view.ox = clampAxis(this.view.ox, WORLD_W * this.view.scale, GAME_WIDTH); + this.view.oy = clampAxis(this.view.oy, WORLD_H * this.view.scale, GAME_HEIGHT); + } + + // Zoom about a screen point: the world position under the cursor must stay + // under the cursor, which is the whole point of zooming to the mouse. + zoomAt(screenX, screenY, factor) { + const before = this.toWorld({ x: screenX, y: screenY }); + const next = Math.max(ZOOM_MIN, Math.min(ZOOM_MAX, this.view.scale * factor)); + if (next === this.view.scale) return; + this.view.scale = next; + this.view.ox = screenX - before.x * next; + this.view.oy = screenY - before.y * next; + this.applyView(); + } + + resetView() { + this.view = { ...VIEW_HOME }; + this.applyView(); + } + // ── Input ───────────────────────────────────────────────────────────────── bindInput() { + this.input.mouse?.disableContextMenu(); this.input.on('pointerdown', (p) => this.onDown(p)); this.input.on('pointermove', (p) => this.onMove(p)); this.input.on('pointerup', (p) => this.onUp(p)); - this.input.keyboard?.on('keydown-R', () => { if (this.view === 'play') this.startLevel(this.level); }); - this.input.keyboard?.on('keydown-ESC', () => { if (this.view === 'play') this.exitLevel(); }); + + this.input.on('wheel', (p, over, dx, dy) => { + if (this.viewMode !== 'play' || !this.state || this.overlayUp) return; + if (dy === 0) return; + this.zoomAt(p.x, p.y, dy < 0 ? ZOOM_STEP : 1 / ZOOM_STEP); + }); + this.input.keyboard?.on('keydown-ZERO', () => this.resetView()); + this.input.keyboard?.on('keydown-HOME', () => this.resetView()); + this.input.keyboard?.on('keydown-R', () => { if (this.viewMode === 'play') this.startLevel(this.level); }); + this.input.keyboard?.on('keydown-ESC', () => { if (this.viewMode === 'play') this.exitLevel(); }); } - toWorld(p) { return { x: p.x - OX, y: p.y - OY }; } + // Screen <-> world. The board container holds the forward transform; these + // are it and its inverse. + tx(x) { return x * this.view.scale + this.view.ox; } + + ty(y) { return y * this.view.scale + this.view.oy; } + + toWorld(p) { + return { x: (p.x - this.view.ox) / this.view.scale, y: (p.y - this.view.oy) / this.view.scale }; + } onDown(p) { - if (this.view !== 'play' || this.overlayUp || !this.state) return; + if (this.viewMode !== 'play' || this.overlayUp || !this.state) return; + // Right-drag pans. Zoomed in, you need a way to get around, and the left + // button is already spoken for by dragging goo. + if (p.rightButtonDown()) { + this.panFrom = { x: p.x, y: p.y, ox: this.view.ox, oy: this.view.oy }; + return; + } const w = this.toWorld(p); const ball = pickBallAt(this.state, w.x, w.y, 46); if (!ball) return; @@ -452,12 +550,19 @@ export default class GooTowerGame extends Phaser.Scene { } onMove(p) { + if (this.panFrom) { + this.view.ox = this.panFrom.ox + (p.x - this.panFrom.x); + this.view.oy = this.panFrom.oy + (p.y - this.panFrom.y); + this.applyView(); + return; + } if (!this.held || !this.state) return; const w = this.toWorld(p); dragTo(this.state, this.held, w.x, w.y); } onUp(p) { + if (this.panFrom) { this.panFrom = null; return; } if (!this.held || !this.state) return; const w = this.toWorld(p); const ball = this.held; @@ -471,7 +576,7 @@ export default class GooTowerGame extends Phaser.Scene { // ── Frame ───────────────────────────────────────────────────────────────── update(time, delta) { - if (this.view !== 'play' || !this.state) return; + if (this.viewMode !== 'play' || !this.state) return; // Fixed-timestep accumulator; the sim substeps internally at 240Hz. const dt = Math.min(delta / 1000, 0.05); @@ -519,7 +624,7 @@ export default class GooTowerGame extends Phaser.Scene { const color = lerpColor(STRAND, STRAND_HOT, stress); const width = 7 - 3 * stress; // strands thin as they are pulled taut g.lineStyle(width, color, 1); - g.lineBetween(a.x + OX, a.y + OY, b.x + OX, b.y + OY); + g.lineBetween(a.x, a.y, b.x, b.y); } // Balls. @@ -534,8 +639,8 @@ export default class GooTowerGame extends Phaser.Scene { drawBall(g, b) { const base = GOO_COLOR[b.type] ?? GOO_COLOR.common; - const x = b.x + OX; - const y = b.y + OY; + const x = b.x; + const y = b.y; // Squash along the direction of travel, so goo reads as soft. const vx = b.x - b.px; @@ -592,8 +697,8 @@ export default class GooTowerGame extends Phaser.Scene { drawPipe(g) { const p = this.state.pipe; if (!p) return; - const x = p.x + OX; - const y = p.y + OY; + const x = p.x; + const y = p.y; const open = p.open; g.fillStyle(PIPE_BODY, 1); @@ -626,19 +731,22 @@ export default class GooTowerGame extends Phaser.Scene { // a perfectly valid placement that kills it on contact. const color = !ok ? GHOST_NO : hazard ? 0xffb347 : GHOST_OK; + // Ghost strokes are UI, not physical: keep them a constant width on screen + // rather than letting 9x zoom turn them into slabs. + const px = 1 / this.view.scale; for (const id of targets) { const t = this.state.balls[id]; if (!t) continue; - g.lineStyle(3, color, 0.8); - g.lineBetween(b.x + OX, b.y + OY, t.x + OX, t.y + OY); + g.lineStyle(3 * px, color, 0.8); + g.lineBetween(b.x, b.y, t.x, t.y); } - g.lineStyle(2, color, 0.85); - g.strokeCircle(b.x + OX, b.y + OY, b.r + 8); + g.lineStyle(2 * px, color, 0.85); + g.strokeCircle(b.x, b.y, b.r + 8 * px); if (!ok || hazard) { const need = requiredStrands(this.state, b.x, b.y, b.type); - g.lineStyle(1, color, 0.35); - g.strokeCircle(b.x + OX, b.y + OY, TUNING.ATTACH_R); + g.lineStyle(1 * px, color, 0.35); + g.strokeCircle(b.x, b.y, TUNING.ATTACH_R); if (!this.needText) { this.needText = this.track(this.add.text(0, 0, '', { fontFamily: '"Julius Sans One"', fontSize: '18px', color: '#ff9d9d', @@ -647,7 +755,7 @@ export default class GooTowerGame extends Phaser.Scene { const label = !ok ? (need === 0 ? 'no hold' : `needs ${need}`) : (hazard === 'fire' && gooType(b.type).explodes ? 'will light!' : `${hazard}!`); - this.needText.setPosition(b.x + OX, b.y + OY - b.r - 26) + this.needText.setPosition(this.tx(b.x), this.ty(b.y) - b.r * this.view.scale - 26) .setColor(ok ? '#ffb347' : '#ff9d9d') .setText(label) .setVisible(true); diff --git a/src/games/gootower/GooTowerLogic.js b/src/games/gootower/GooTowerLogic.js index c45aa14..a0d0073 100644 --- a/src/games/gootower/GooTowerLogic.js +++ b/src/games/gootower/GooTowerLogic.js @@ -485,7 +485,12 @@ function integrate(state, dt) { const def = gooType(b.type); const fan = state.fans.length ? fanAccel(state, b) : null; const ax = fan ? fan.ax : 0; - const ay = TUNING.GRAVITY * def.buoyancy + (fan ? fan.ay : 0); + // Buoyancy only applies once the goo is part of a structure. Loose goo + // sits in the heap like everything else -- otherwise every balloon in a + // level's pile drifts off on frame one and dies on the nearest ceiling, + // and the level is unwinnable before the player has touched anything. + const lift = b.attached ? def.buoyancy : 1; + const ay = TUNING.GRAVITY * lift + (fan ? fan.ay : 0); let vx = (b.x - b.px) * TUNING.DRAG; let vy = (b.y - b.py) * TUNING.DRAG; diff --git a/src/games/gootower/tutorial.md b/src/games/gootower/tutorial.md index be4fdbd..171d5da 100644 --- a/src/games/gootower/tutorial.md +++ b/src/games/gootower/tutorial.md @@ -65,4 +65,11 @@ once it's down. - **OCD** is a separate, higher target for collecting far more than you needed. Reaching the required count doesn't end the level — hit *Keep Playing* and go for it. +## Getting a closer look + +- **Mouse wheel** zooms in and out, centred on whatever is under the cursor — so point at the + join you care about and roll in. It goes from a wide view right down to individual strands. +- **Right-click and drag** pans. +- **0** (or Home) snaps the view back. + Press **R** to retry, **Esc** for the level list. diff --git a/tools/genGooTower.js b/tools/genGooTower.js index 43fe3d2..6e3511e 100644 --- a/tools/genGooTower.js +++ b/tools/genGooTower.js @@ -1,44 +1,77 @@ -// Goo Tower — level bank writer. +// Goo Tower — level bank generator. // -// Wave 1: the six hand-designed teaching levels below are authored here and -// emitted verbatim. They are HAND-TUNED, not generated -- the script exists so -// the repetitive parts (goo piles, spike strips, the manifest) are constructed -// rather than typed, and so the bank is byte-reproducible. +// Wave 4 replaced the flat 12-level bank with a CURRICULUM: five named +// chapters of fifteen levels, built from blocks that introduce one mechanic, +// drill it, then combine it with what came before. // -// Wave 4 will add generated drill/sandbox tiers alongside these; when it does, -// levels 1-6 must be carried over untouched, exactly as genPeggleLevels.js -// freezes Peggle's hand-tuned 1-25. +// A physics sandbox has no BFS solver, so levels are not random-filled the way +// Jell-o Monsters' are. Instead each level is instantiated from a HAND-DESIGNED +// TEMPLATE (tower, bridge, overhang, updraft, cogs, demolition, cliff…) with +// its parameters swept across a difficulty band, and then has to survive four +// gates: // -// Usage: node tools/genGooTower.js [outDir] +// 1. CLEAN — settles without snapping a strand, losing goo, starting +// anything inside terrain, or starting two goo overlapping. +// 2. WINNABLE — the reference player in GooTowerAuto.js beats it. The +// gate is one-directional: if a naive builder can win, a +// human can. A failure means "redesign", never "impossible". +// 3. LOAD-BEARING — for enabling mechanics (updraft, wall-anchors), strip the +// element and the level must STOP being winnable. This is +// what keeps a "fan level" from being an ordinary level +// with a fan blowing somewhere irrelevant. +// 4. GENTLE — a teaching level may not open with an instant-fail: no +// hazard within reach of the starting structure. +// +// Levels 1-6 are the original hand-tuned teaching levels and are emitted +// VERBATIM, exactly as genPeggleLevels.js freezes Peggle's hand-tuned 1-25. +// +// Usage: +// node tools/genGooTower.js [seed] [outDir] +// +// Deterministic: same seed -> same bank. import { writeFileSync, mkdirSync } from 'node:fs'; import { dirname, join } from 'node:path'; import { fileURLToPath } from 'node:url'; +import { + createState, settlePhysics, insideSolid, gooType, liveStrands, +} from '../src/games/gootower/GooTowerLogic.js'; +import { autoPlay } from '../src/games/gootower/GooTowerAuto.js'; const __dirname = dirname(fileURLToPath(import.meta.url)); -const outDir = process.argv[2] || join(__dirname, '..', 'assets', 'gamedata', 'gootower'); +const SEED = process.argv[2] ? Number(process.argv[2]) >>> 0 : 0x600d1e; +const outDir = process.argv[3] || join(__dirname, '..', 'assets', 'gamedata', 'gootower'); const W = 1600; const H = 1000; const GROUND = 850; +// ── Seeded RNG (mulberry32) ───────────────────────────────────────────────── +function mulberry32(seed) { + let a = seed >>> 0; + return function rng() { + a = (a + 0x6d2b79f5) >>> 0; + let t = a; + t = Math.imul(t ^ (t >>> 15), t | 1); + t ^= t + Math.imul(t ^ (t >>> 7), t | 61); + return ((t ^ (t >>> 14)) >>> 0) / 4294967296; + }; +} + +const lerp = (a, b, t) => a + (b - a) * t; +const clamp = (v, lo, hi) => Math.max(lo, Math.min(hi, v)); + const rect = (x1, y1, x2, y2, kind = 'solid') => ({ kind, poly: [[x1, y1], [x2, y1], [x2, y2], [x1, y2]] }); const ground = (top = GROUND) => rect(0, top, W, H); -// A loose heap of goo resting on a surface. Laid out in rows so the balls start -// apart -- dumping them on one spot just makes the collision solver do work. -function pile(type, n, x, surfaceY, { perRow = 8, gap = 30 } = {}) { - const out = []; - for (let i = 0; i < n; i += 1) { - const row = Math.floor(i / perRow); - const col = i % perRow; - out.push({ x: x + col * gap, y: surfaceY - 16 - row * 30, type }); - } - return out; -} +// Side walls. EVERY template includes these: a heap that topples and rolls off +// the edge of the world loses goo before the player has touched anything, and +// it is always the top row of the heap that goes -- which is exactly where the +// scarce goo types sit. +const bounds = () => [rect(-30, 0, 6, H), rect(W - 6, 0, W + 30, H)]; -// A small planted tripod: two pinned feet and a free apex, already triangulated -// so the player has something legal to attach to on frame one. +// A planted tripod: two pinned feet and a free apex, already triangulated so +// the player has something legal to attach to on frame one. function footing(x, y, type = 'common') { return { balls: [ @@ -50,255 +83,634 @@ function footing(x, y, type = 'common') { }; } -const LEVELS = []; - -// ── 1 ─────────────────────────────────────────────────────────────────────── -{ - const f = footing(771, GROUND - 14); - LEVELS.push({ - level: 1, name: 'Ground Floor', chapter: 1, - tip: 'Drag goo from the heap onto the structure. Each ball needs two nearby friends to hold on to.', - terrain: [ground()], - ...f, - pipe: { x: 771, y: 600, r: 46 }, - pile: pile('common', 16, 980, GROUND), - required: 4, ocdTarget: 9, - }); +// A heap of loose goo. `mix` is [[type, count], ...]. Laid out in rows and kept +// clear of `avoid` (the footing's x): goo that starts inside other goo is +// ejected hard enough to snap its own strands. +function heap(mix, startX, surfaceY, { perRow = null, gap = 30, avoid = null } = {}) { + const out = []; + const total = mix.reduce((n, [, c]) => n + c, 0); + // Wide and low: a tall narrow heap topples and spills. Roughly 3 rows. + const cols = perRow || clamp(Math.round(total / 3), 6, 14); + // Interleave the types. Laid out in blocks, the rarest goo ends up in the + // top row -- the row most likely to roll away. + const order = []; + const pools = mix.map(([type, count]) => ({ type, left: count })); + while (pools.some((p) => p.left > 0)) { + for (const p of pools) { + if (p.left > 0) { order.push(p.type); p.left -= 1; } + } + } + let i = 0; + for (const [, count] of [[null, order.length]]) { + for (let k = 0; k < count; k += 1, i += 1) { + const type = order[k]; + const row = Math.floor(i / cols); + const col = i % cols; + out.push({ x: startX + col * gap, y: surfaceY - 16 - row * 30, type }); + } + } + // Shift the WHOLE heap clear of the footing rather than nudging individual + // balls: nudging piles two columns onto each other, and overlapping goo is + // ejected hard enough to snap strands. + if (avoid != null && out.length) { + const lo = Math.min(...out.map((b) => b.x)); + const hi = Math.max(...out.map((b) => b.x)); + const clearL = avoid - 110; + const clearR = avoid + 110; + if (hi > clearL && lo < clearR) { + const shift = (lo + hi) / 2 < avoid ? clearL - hi : clearR - lo; + for (const b of out) b.x += shift; + } + } + return out.filter((b) => b.x > 30 && b.x < W - 30); } -// ── 2 ─────────────────────────────────────────────────────────────────────── -{ - const f = footing(430, 686); - LEVELS.push({ - level: 2, name: 'Mind the Gap', chapter: 1, - tip: 'Spikes below. Build ACROSS — triangles carry weight, long chains do not.', - terrain: [ - rect(0, 700, 600, H), - rect(860, 700, W, H), - rect(600, 930, 860, H, 'spike'), - // Lip on the outer rim. Without it the heap spreads left, rolls off the - // edge of the world and the level quietly loses goo before the player - // has touched anything. - rect(0, 620, 40, 700), +const heapSize = (mix) => mix.reduce((n, [, c]) => n + c, 0); + +// ── Templates ─────────────────────────────────────────────────────────────── +// Each returns a level body. `d` is difficulty in 0..1 within its block. +// `gate` says how the load-bearing check should treat the featured element. + +export const TEMPLATES = { + // Straight-up climb. The bread and butter. + tower(rng, d, mix) { + const x = Math.round(lerp(430, 860, rng())); + const climb = Math.round(lerp(200, 470, d)); + const pileX = x + 260 < W - 300 ? x + 260 : x - 420; + return { + element: null, gate: 'none', + terrain: [ground(), ...bounds()], + ...footing(x, GROUND - 14), + pipe: { x, y: GROUND - 68 - climb, r: 46 }, + pile: heap(mix, clamp(pileX, 60, W - 300), GROUND, { avoid: x }), + tip: 'Brace as you go. An unbraced column leans, and once it leans it keeps leaning.', + }; + }, + + // A spike pit to bridge. + bridge(rng, d, mix) { + const ledgeY = 700; + const gap = Math.round(lerp(190, 330, d)); + const left = Math.round(lerp(560, 640, rng())); + const right = left + gap; + const fx = left - 190; + return { + element: null, gate: 'none', + terrain: [ + ...bounds(), + rect(0, ledgeY, left, H), + rect(right, ledgeY, W, H), + rect(left, 930, right, H, 'spike'), + rect(0, ledgeY - 90, 44, ledgeY), + rect(left - 44, ledgeY - 90, left, ledgeY), + ], + ...footing(fx, ledgeY - 14), + pipe: { x: right + 110, y: ledgeY - 60, r: 46 }, + pile: heap(mix, 90, ledgeY, { perRow: 6, avoid: fx }), + waypoints: [{ x: (left + right) / 2, y: ledgeY - 95 }], + tip: 'Triangles carry weight across a gap. Long chains just sag into the spikes.', + }; + }, + + // A slab overhead: come out from under it before climbing. + overhang(rng, d, mix) { + const fx = Math.round(lerp(470, 600, rng())); + const slabY = Math.round(lerp(620, 540, d)); + const slabR = Math.round(lerp(740, 860, d)); + return { + element: null, gate: 'none', + terrain: [ground(), ...bounds(), rect(260, slabY, slabR, slabY + 70)], + ...footing(fx, GROUND - 14), + pipe: { x: slabR + 150, y: slabY - 60, r: 46 }, + pile: heap(mix, slabR + 120, GROUND, { avoid: fx }), + waypoints: [{ x: slabR + 40, y: slabY + 20 }], + tip: 'You cannot build through rock. Come out from under it first.', + }; + }, + + // Spiked ceiling: stop short of it. + ceiling(rng, d, mix) { + const x = Math.round(lerp(500, 900, rng())); + const ceilY = Math.round(lerp(340, 240, d)); + return { + element: null, gate: 'none', + terrain: [ground(), ...bounds(), rect(clamp(x - 420, 0, W), ceilY, clamp(x + 420, 0, W), ceilY + 60, 'spike')], + ...footing(x, GROUND - 14), + pipe: { x, y: ceilY + 165, r: 46 }, + pile: heap(mix, clamp(x + 280, 60, W - 300), GROUND, { avoid: x }), + tip: 'The ceiling bites. Stop short of it.', + }; + }, + + // An updraft that lightens everything inside it, so the span reaches further + // than bare goo could manage. + updraft(rng, d, mix) { + const ledgeY = 700; + const gap = Math.round(lerp(360, 470, d)); + const left = 560; + const right = left + gap; + const fx = left - 190; + return { + element: 'fan', gate: 'enabling', + terrain: [ + ...bounds(), + rect(0, ledgeY, left, H), + rect(right, ledgeY, W, H), + rect(left, 930, right, H, 'spike'), + rect(0, ledgeY - 90, 44, ledgeY), + rect(left - 44, ledgeY - 90, left, ledgeY), + ], + fans: [{ + x: left, y: 260, w: gap, h: 660, dx: 0, dy: -1, + force: Math.round(lerp(1380, 1290, d)), + }], + ...footing(fx, ledgeY - 14), + pipe: { x: clamp(right + 110, 0, W - 70), y: ledgeY - 60, r: 46 }, + pile: heap(mix, 90, ledgeY, { perRow: 6, avoid: fx }), + waypoints: [{ x: (left + right) / 2, y: ledgeY - 120 }], + tip: 'The updraft takes weight off everything inside it. Spans reach further in the wind.', + }; + }, + + // A turning cog in the way. + cogs(rng, d, mix) { + const fx = Math.round(lerp(280, 380, rng())); + const gx = Math.round(lerp(720, 820, rng())); + const omega = (rng() < 0.5 ? -1 : 1) * lerp(1.1, 2.0, d); + return { + element: 'gear', gate: 'obstructing', + terrain: [ground(), ...bounds()], + gears: [{ + x: gx, y: Math.round(lerp(520, 450, d)), + r: Math.round(lerp(95, 125, d)), teeth: 9, omega, + }], + ...footing(fx, GROUND - 14), + pipe: { x: Math.round(lerp(1160, 1290, d)), y: Math.round(lerp(620, 550, d)), r: 46 }, + pile: heap(mix, 1000, GROUND, { perRow: 9, avoid: fx }), + tip: 'The cog is solid and it is turning. Whatever it touches gets dragged along.', + }; + }, + + // Soft rock in the way, a fire pit beside it, bombs in the heap. The bomb is + // a SHORTCUT, never the only route -- a mechanic that is the sole solution is + // a level nobody can find their way through. + demolition(rng, d, mix) { + const fx = Math.round(lerp(360, 440, rng())); + const rockX = Math.round(lerp(680, 760, rng())); + const rockTop = Math.round(lerp(700, 640, d)); + return { + element: 'bomb', gate: 'obstructing', + terrain: [ + ground(), ...bounds(), + { ...rect(rockX, rockTop, rockX + 80, GROUND), destructible: true }, + rect(rockX - 110, GROUND - 44, rockX - 30, GROUND, 'fire'), + ], + ...footing(fx, GROUND - 14), + pipe: { x: Math.round(lerp(980, 1120, d)), y: 700, r: 46 }, + pile: heap(mix, 120, GROUND, { perRow: 7, avoid: fx }), + waypoints: [{ x: rockX + 40, y: rockTop - 75 }], + tip: 'Drop a bomb by the fire and the soft rock goes with it. Or take the long way over.', + }; + }, + + // A wall start: no ground worth building from, so goo that grips rock is the + // only way to begin. + cliff(rng, d, mix) { + const wallX = 300; + const startY = Math.round(lerp(600, 520, d)); + return { + element: 'anchor', gate: 'enabling', + terrain: [ + ground(), ...bounds(), + rect(wallX - 90, 180, wallX, 800), + rect(1200, 180, 1290, 800), + rect(wallX, 930, 1200, H, 'spike'), + // A shelf directly under the starting structure. Without it the heap + // sits on the ground far below a wall-mounted start, loose goo walks to + // the foot of the wall and can never climb, and the pipe drinks nothing. + rect(wallX, startY + 44, wallX + 300, startY + 120), + ], + balls: [ + { x: wallX + 40, y: startY, type: 'pokey', pinned: true }, + { x: wallX + 40, y: startY - 62, type: 'pokey', pinned: true }, + { x: wallX + 98, y: startY - 31, type: 'common' }, + ], + strands: [[2, 0], [2, 1], [0, 1]], + pipe: { x: 1150, y: Math.round(lerp(460, 400, d)), r: 46 }, + pile: heap(mix, wallX + 130, startY + 44, { perRow: 6 }), + waypoints: [{ x: 740, y: Math.round(lerp(450, 410, d)) }], + tip: 'Pokey goo grips bare rock and needs no friends. Start from the wall.', + }; + }, + + // Pillars to anchor off on the way up. + pillars(rng, d, mix) { + const fx = 760; + const top = Math.round(lerp(360, 280, d)); + return { + element: 'anchor', gate: 'none', + terrain: [ground(), ...bounds(), rect(420, top, 480, GROUND), rect(1040, top, 1100, GROUND)], + ...footing(fx, GROUND - 14), + pipe: { x: fx, y: Math.round(lerp(420, 340, d)), r: 46 }, + pile: heap(mix, 830, GROUND, { perRow: 6, avoid: fx }), + tip: 'Anchor goo sticks straight to rock. The pillars are fair game.', + }; + }, +}; + +// ── The curriculum ────────────────────────────────────────────────────────── + +export const MIX = { + basic: [['common', 24]], + ivy: [['common', 18], ['ivy', 10]], + airy: [['common', 20], ['balloon', 6]], + windy: [['common', 22], ['balloon', 5], ['ivy', 4]], + works: [['common', 22], ['block', 8], ['bomb', 4]], + cog: [['common', 24], ['block', 8]], + sticky: [['pokey', 8], ['anchor', 5], ['common', 22]], + deep: [['common', 20], ['skull', 6], ['bit', 6], ['balloon', 4], ['block', 4]], +}; + +const CHAPTERS = [ + { + id: 1, + name: 'The Rolling Hills', + blurb: 'Learn to build. Everything after this assumes you can.', + frozen: 6, + blocks: [ + { template: 'tower', count: 3, d0: 0.15, d1: 0.45, mix: 'basic' }, + { template: 'bridge', count: 3, d0: 0.10, d1: 0.40, mix: 'ivy' }, + { template: 'overhang', count: 3, d0: 0.10, d1: 0.45, mix: 'ivy' }, ], - ...f, - pipe: { x: 980, y: 640, r: 46 }, - // perRow 7 keeps the heap clear of the footing at x=430; at 10 the last - // column landed 9px from a foot and the two were ejected apart on frame one. - pile: pile('common', 20, 150, 700, { perRow: 7 }), - required: 5, ocdTarget: 12, - }); -} - -// ── 3 ─────────────────────────────────────────────────────────────────────── -{ - // The footing sits UNDER the overhang, so the only way up is to walk the - // structure out sideways first. Keep the run short -- this is level 3, and - // an earlier draft asked for a 677px diagonal that nothing could build. - const f = footing(560, GROUND - 14); - LEVELS.push({ - level: 3, name: 'Headroom', chapter: 1, - tip: 'You cannot build through the slab. Come out from under it first.', - terrain: [ground(), rect(300, 540, 820, 610)], - ...f, - pipe: { x: 980, y: 470, r: 46 }, - pile: pile('common', 24, 1020, GROUND, { perRow: 8 }), - required: 5, ocdTarget: 12, - }); -} - -// ── 4 ─────────────────────────────────────────────────────────────────────── -{ - const f = footing(331, GROUND - 14, 'common'); - LEVELS.push({ - level: 4, name: 'Second Thoughts', chapter: 1, - tip: 'Green ivy goo can be pulled back off and used again. Grey goo is there for good.', - terrain: [ground()], - ...f, - // The heap must comfortably outlast the climb. An earlier draft gave - // exactly enough goo to REACH the pipe and nothing to feed it, so the - // level opened the pipe and was then unwinnable. - pipe: { x: 660, y: 560, r: 46 }, - pile: [ - ...pile('ivy', 12, 540, GROUND, { perRow: 6 }), - ...pile('common', 8, 860, GROUND, { perRow: 8 }), + names: ['Uphill', 'Higher Ground', 'The Long Climb', + 'Across', 'Wider Still', 'The Drop', + 'Under It', 'Round the Back', 'Out and Up'], + }, + { + id: 2, + name: 'Windward', + blurb: 'Wind, balloons, and things that would rather float away.', + blocks: [ + { template: 'tower', count: 2, d0: 0.35, d1: 0.55, mix: 'airy', teach: true }, + { template: 'ceiling', count: 3, d0: 0.20, d1: 0.55, mix: 'airy' }, + { template: 'updraft', count: 4, d0: 0.10, d1: 0.55, mix: 'windy', teach: true }, + { template: 'bridge', count: 3, d0: 0.45, d1: 0.70, mix: 'windy' }, + { template: 'updraft', count: 3, d0: 0.55, d1: 0.85, mix: 'windy' }, ], - required: 4, ocdTarget: 9, - }); -} - -// ── 5 ─────────────────────────────────────────────────────────────────────── -{ - const f = footing(791, GROUND - 14); - LEVELS.push({ - level: 5, name: 'Overhead', chapter: 1, - tip: 'The ceiling bites. Stop short of it.', - terrain: [ground(), rect(400, 180, 1200, 240, 'spike')], - ...f, - pipe: { x: 791, y: 340, r: 46 }, - pile: pile('common', 18, 1000, GROUND, { perRow: 9 }), - required: 5, ocdTarget: 11, - }); -} - -// ── 6 ─────────────────────────────────────────────────────────────────────── -{ - const f = footing(791, GROUND - 14); - LEVELS.push({ - level: 6, name: 'Tall Order', chapter: 1, - tip: 'A tower stands on compression and falls on sway. Brace every level.', - terrain: [ground()], - ...f, - pipe: { x: 791, y: 180, r: 46 }, - pile: pile('common', 26, 1020, GROUND, { perRow: 9 }), - required: 6, ocdTarget: 14, - }); -} - -// ── Sandbox tier (7-12) ───────────────────────────────────────────────────── -// One level per Wave 3 mechanic, so each can be played and judged on its own. -// This is THROWAWAY content, explicitly not the final curriculum -- Wave 4 -// replaces it with a designed 5-chapter ramp. - -// ── 7 · anchors ───────────────────────────────────────────────────────────── -{ - const f = footing(780, GROUND - 14); - LEVELS.push({ - level: 7, name: 'Anchors Aweigh', chapter: 2, sandbox: true, - tip: 'Brown anchor goo sticks straight to rock and needs no friends. Start a span from a wall.', - // Pillars must not stand BETWEEN the heap and the structure: loose goo - // walks along the ground, and a 550px wall is a wall. - terrain: [ground(), rect(400, 300, 460, GROUND), rect(1120, 300, 1180, GROUND)], - ...f, - pipe: { x: 780, y: 400, r: 46 }, - pile: [ - ...pile('anchor', 6, 860, GROUND, { perRow: 6 }), - ...pile('common', 20, 860, GROUND - 30, { perRow: 6 }), + names: ['Light Head', 'Buoyant', 'Low Ceiling', 'Mind Your Head', 'Overhead', + 'First Gust', 'Updraft', 'Riding the Wind', 'Thermals', + 'Long Reach', 'The Wide Crossing', 'Windswept', 'Gale', 'Squall', 'Headwind'], + }, + { + id: 3, + name: 'The Works', + blurb: 'Machinery. It does not care what you built.', + blocks: [ + { template: 'cogs', count: 4, d0: 0.10, d1: 0.55, mix: 'cog', teach: true }, + { template: 'tower', count: 2, d0: 0.55, d1: 0.75, mix: 'cog' }, + { template: 'demolition', count: 4, d0: 0.10, d1: 0.55, mix: 'works', teach: true }, + { template: 'cogs', count: 3, d0: 0.55, d1: 0.85, mix: 'works' }, + { template: 'overhang', count: 2, d0: 0.55, d1: 0.80, mix: 'works' }, ], - required: 5, ocdTarget: 12, - }); + names: ['First Cog', 'Gearworks', 'Clockwise', 'Widdershins', 'Rigid Thinking', + 'Girders', 'Soft Rock', 'Demolition', 'Blast Radius', 'Controlled Burn', + 'The Machine', 'Grinding Gears', 'Flywheel', 'Under the Works', 'Assembly'], + }, + { + id: 4, + name: 'The Sticky Cliffs', + blurb: 'No ground worth standing on. Grip the rock.', + blocks: [ + { template: 'pillars', count: 3, d0: 0.10, d1: 0.45, mix: 'sticky', teach: true }, + { template: 'cliff', count: 4, d0: 0.10, d1: 0.50, mix: 'sticky', teach: true }, + { template: 'tower', count: 2, d0: 0.60, d1: 0.80, mix: 'sticky' }, + { template: 'cliff', count: 3, d0: 0.50, d1: 0.85, mix: 'sticky' }, + { template: 'bridge', count: 3, d0: 0.55, d1: 0.85, mix: 'sticky' }, + ], + names: ['Handhold', 'Two Pillars', 'Stepping Up', 'The Face', 'Sheer', + 'Traverse', 'Grip', 'Overhanging', 'Cliffhanger', 'The Chimney', + 'Freeclimb', 'The Notch', 'Crevasse', 'Exposure', 'Summit'], + }, + { + id: 5, + name: 'Down the Deep', + blurb: 'Everything you have learned, all at once.', + blocks: [ + { template: 'ceiling', count: 3, d0: 0.60, d1: 0.90, mix: 'deep' }, + { template: 'updraft', count: 3, d0: 0.60, d1: 0.90, mix: 'deep' }, + { template: 'cogs', count: 3, d0: 0.65, d1: 0.95, mix: 'deep' }, + { template: 'demolition', count: 3, d0: 0.60, d1: 0.90, mix: 'deep' }, + { template: 'tower', count: 3, d0: 0.70, d1: 1.00, mix: 'deep' }, + ], + names: ['Descent', 'Low Roof', 'The Squeeze', 'Deep Wind', 'The Shaft', + 'Downdraft', 'Deep Cogs', 'The Grinder', 'Millstone', 'Deep Rock', + 'Cave-In', 'The Last Charge', 'The Long Way Up', 'Ascent', 'Out'], + }, +]; + +// ── Gates ─────────────────────────────────────────────────────────────────── + +function cleanCheck(def) { + const st = createState(def); + for (const b of st.balls) { + if (insideSolid(st, b.x, b.y)) return 'goo starts inside terrain'; + } + for (let i = 0; i < st.balls.length; i += 1) { + for (let j = i + 1; j < st.balls.length; j += 1) { + const a = st.balls[i]; + const b = st.balls[j]; + if (Math.hypot(b.x - a.x, b.y - a.y) < (a.r + b.r) * 0.6) return 'goo starts overlapping'; + } + } + if (st.pipe.open) return 'pipe starts open'; + settlePhysics(st, 10); + if (liveStrands(st).length !== st.strands.length) return 'a strand snaps on its own'; + const lost = st.balls.filter((b) => b.dead); + if (lost.length) { + const kinds = [...new Set(lost.map((b) => b.type))].join('/'); + return `goo dies before the player touches anything (${lost.length} ${kinds})`; + } + if (st.pile.length < def.ocdTarget) return 'not enough goo left for OCD'; + return null; } -// ── 8 · pokey (wall starts) ───────────────────────────────────────────────── -{ - LEVELS.push({ - level: 8, name: 'Sticking Point', chapter: 2, sandbox: true, - tip: 'Pokey goo grips rock. There is no ground here worth building from.', - terrain: [ground(), rect(240, 200, 320, 760), rect(1120, 200, 1200, 760)], - balls: [ - { x: 340, y: 560, type: 'pokey', pinned: true }, - { x: 340, y: 498, type: 'pokey', pinned: true }, - { x: 398, y: 530, type: 'common' }, - ], - strands: [[2, 0], [2, 1], [0, 1]], - pipe: { x: 1080, y: 430, r: 46 }, - pile: [ - ...pile('pokey', 6, 620, GROUND, { perRow: 6 }), - ...pile('common', 22, 620, GROUND - 30, { perRow: 8 }), - ], - required: 5, ocdTarget: 12, - }); +// A teaching level may not open with an instant-fail: nothing lethal within +// reach of the starting structure. +function gentleCheck(def) { + const st = createState(def); + const start = st.balls.filter((b) => b.attached); + for (const t of st.terrain) { + if (t.kind !== 'spike' && t.kind !== 'fire') continue; + for (const b of start) { + const bb = t.bounds; + const dx = Math.max(bb.minX - b.x, 0, b.x - bb.maxX); + const dy = Math.max(bb.minY - b.y, 0, b.y - bb.maxY); + if (Math.hypot(dx, dy) < 140) return 'a hazard sits on the doorstep'; + } + } + return null; } -// ── 9 · bombs, fire and destructible rock ─────────────────────────────────── -{ - const f = footing(400, GROUND - 14); - LEVELS.push({ - level: 9, name: 'Demolition', chapter: 2, sandbox: true, - tip: 'Drop a bomb by the fire and the soft rock goes with it. Or take the long way over.', - terrain: [ - ground(), - // Soft rock in the way -- blow it, or climb over. The fire sits BESIDE - // the rock at ground level, not on the climbing route: an earlier draft - // had it capping the rock, which made the bomb the only survivable way - // through and left the level unwinnable by ordinary building. - { ...rect(700, 660, 780, GROUND), destructible: true }, - rect(600, 806, 680, GROUND, 'fire'), - ], - ...f, - pipe: { x: 980, y: 700, r: 46 }, - // Greedy will not climb a wall unprompted -- that means building away from - // the pipe first -- so route it over the top. - waypoints: [{ x: 740, y: 590 }], - pile: [ - ...pile('bomb', 4, 160, GROUND, { perRow: 4 }), - ...pile('common', 24, 160, GROUND - 30, { perRow: 7 }), - ], - required: 5, ocdTarget: 12, - }); +// Strip the featured element; an "enabling" level must stop being winnable. +function loadBearingCheck(def, element) { + const stripped = JSON.parse(JSON.stringify(def)); + if (element === 'fan') stripped.fans = []; + else if (element === 'anchor') { + stripped.pile = stripped.pile.filter((p) => !gooType(p.type).sticksToTerrain); + stripped.balls = stripped.balls.map((b) => (gooType(b.type).sticksToTerrain + ? { ...b, type: 'common', pinned: false } : b)); + } else return null; + const r = autoPlay(stripped, { maxBalls: 50, maxSeconds: 30 }); + return r.won ? 'winnable without its own mechanic' : null; } -// ── 10 · fans ─────────────────────────────────────────────────────────────── -{ - const f = footing(360, 686); - LEVELS.push({ - level: 10, name: 'Updraft', chapter: 2, sandbox: true, - tip: 'The updraft takes weight off everything inside it. Spans reach further in the wind.', - terrain: [ - rect(0, 700, 600, H), - rect(940, 700, W, H), - rect(600, 930, 940, H, 'spike'), - rect(0, 620, 40, 700), - ], - fans: [{ x: 600, y: 300, w: 340, h: 630, dx: 0, dy: -1, force: 1150 }], - ...f, - pipe: { x: 1060, y: 630, r: 46 }, - pile: pile('common', 26, 120, 700, { perRow: 6 }), - required: 4, ocdTarget: 12, - }); +// ── Build ─────────────────────────────────────────────────────────────────── + +const rng = mulberry32(SEED); +const levels = frozenLevels(); +const stats = { tried: 0, rejected: {} }; +const reject = (why) => { stats.rejected[why] = (stats.rejected[why] || 0) + 1; }; + +for (const chapter of CHAPTERS) { + let nameIdx = 0; + const wanted = 15 - (chapter.frozen || 0); + let made = 0; + + for (const block of chapter.blocks) { + for (let k = 0; k < block.count && made < wanted; k += 1) { + const d = block.count > 1 ? lerp(block.d0, block.d1, k / (block.count - 1)) : block.d0; + const mix = MIX[block.mix]; + let accepted = null; + + for (let attempt = 0; attempt < 14 && !accepted; attempt += 1) { + stats.tried += 1; + // Jitter difficulty per attempt so retries actually differ. + const dd = clamp(d + (rng() - 0.5) * 0.12, 0, 1); + const body = TEMPLATES[block.template](rng, dd, mix); + const size = heapSize(mix); + const required = Math.round(lerp(4, 8, dd)); + const ocdTarget = clamp(Math.round(lerp(required + 4, required + 9, dd)), required, size - 5); + + const def = { + world: { w: W, h: H }, + level: levels.length + 1, + name: chapter.names[nameIdx] || `${chapter.name} ${nameIdx + 1}`, + chapter: chapter.id, + tip: body.tip, + element: body.element || undefined, + terrain: body.terrain, + balls: body.balls, + strands: body.strands, + pile: body.pile, + pipe: body.pipe, + fans: body.fans, + gears: body.gears, + waypoints: body.waypoints, + required, + ocdTarget, + }; + + const dirty = cleanCheck(def); + if (dirty) { reject(dirty); continue; } + if (block.teach) { + const harsh = gentleCheck(def); + if (harsh) { reject(harsh); continue; } + } + const r = autoPlay(def, { maxBalls: 70, maxSeconds: 45 }); + if (!r.won) { reject(`unwinnable (${r.pipeOpen ? 'pipe open' : 'pipe shut'})`); continue; } + if (body.gate === 'enabling') { + const weak = loadBearingCheck(def, body.element); + if (weak) { reject(weak); continue; } + } + accepted = def; + } + + if (!accepted) { + // Never leave a hole in the curriculum: fall back to a plain tower at + // the same difficulty rather than shipping a 13-level chapter. + for (let attempt = 0; attempt < 10 && !accepted; attempt += 1) { + const dd = clamp(d * 0.8 + (rng() - 0.5) * 0.1, 0, 1); + const body = TEMPLATES.tower(rng, dd, mix); + const size = heapSize(mix); + const required = Math.round(lerp(4, 8, dd)); + const def = { + world: { w: W, h: H }, + level: levels.length + 1, + name: chapter.names[nameIdx] || `${chapter.name} ${nameIdx + 1}`, + chapter: chapter.id, + tip: body.tip, + terrain: body.terrain, + balls: body.balls, + strands: body.strands, + pile: body.pile, + pipe: body.pipe, + required, + ocdTarget: clamp(Math.round(lerp(required + 4, required + 9, dd)), required, size - 5), + }; + if (cleanCheck(def)) continue; + if (!autoPlay(def, { maxBalls: 70, maxSeconds: 45 }).won) continue; + accepted = def; + } + if (accepted) reject(`fell back to tower (${block.template})`); + } + if (!accepted) { + console.warn(`\n[gen] ! ch${chapter.id} ${block.template} slot ${k} — no candidate survived`); + continue; + } + levels.push(accepted); + nameIdx += 1; + made += 1; + process.stdout.write(`\r[gen] ${levels.length} levels… `); + } + } + + // Top-up: every chapter ships exactly fifteen. If the blocks came up short, + // fill the remainder with plain towers rather than a ragged chapter. + let guard = 0; + while (made < wanted && guard < 60) { + guard += 1; + const dd = clamp(0.3 + rng() * 0.4, 0, 1); + const mix = MIX[chapter.blocks[0].mix]; + const body = TEMPLATES.tower(rng, dd, mix); + const size = heapSize(mix); + const required = Math.round(lerp(4, 8, dd)); + const def = { + world: { w: W, h: H }, + level: levels.length + 1, + name: chapter.names[nameIdx] || `${chapter.name} ${nameIdx + 1}`, + chapter: chapter.id, + tip: body.tip, + terrain: body.terrain, + balls: body.balls, + strands: body.strands, + pile: body.pile, + pipe: body.pipe, + required, + ocdTarget: clamp(Math.round(lerp(required + 4, required + 9, dd)), required, size - 5), + }; + if (cleanCheck(def)) continue; + if (!autoPlay(def, { maxBalls: 70, maxSeconds: 45 }).won) continue; + levels.push(def); + nameIdx += 1; + made += 1; + reject('top-up tower'); + process.stdout.write(`\r[gen] ${levels.length} levels… `); + } } -// ── 11 · gears ────────────────────────────────────────────────────────────── -{ - const f = footing(300, GROUND - 14); - LEVELS.push({ - level: 11, name: 'Cogs', chapter: 2, sandbox: true, - tip: 'The cog is solid and it is turning. Anything it touches gets dragged along.', - terrain: [ground()], - gears: [{ x: 800, y: 470, r: 110, teeth: 9, omega: 1.4 }], - ...f, - pipe: { x: 1240, y: 560, r: 46 }, - pile: pile('common', 28, 1000, GROUND, { perRow: 9 }), - required: 5, ocdTarget: 13, - }); -} - -// ── 12 · balloons, blocks and bits ────────────────────────────────────────── -{ - const f = footing(400, GROUND - 14); - LEVELS.push({ - level: 12, name: 'Lighter Than Air', chapter: 2, sandbox: true, - tip: 'Balloons pull up, blocks hold rigid, bits are cheap and weak. Mix them.', - terrain: [ground()], - ...f, - pipe: { x: 400, y: 300, r: 46 }, - pile: [ - ...pile('balloon', 6, 700, GROUND, { perRow: 6 }), - ...pile('block', 8, 700, GROUND - 34, { perRow: 8 }), - ...pile('bit', 6, 700, GROUND - 68, { perRow: 6 }), - ...pile('common', 18, 700, GROUND - 100, { perRow: 9 }), - ], - required: 5, ocdTarget: 12, - }); -} +// ── Emit ──────────────────────────────────────────────────────────────────── mkdirSync(outDir, { recursive: true }); -const manifest = { version: 1, generatedAt: new Date(0).toISOString(), levels: [] }; -for (const lv of LEVELS) { +const manifest = { version: 2, seed: SEED, levels: [] }; +for (let i = 0; i < levels.length; i += 1) { + const lv = levels[i]; + lv.level = i + 1; const file = `level-${String(lv.level).padStart(3, '0')}.json`; - const body = { world: { w: W, h: H }, ...lv }; - writeFileSync(join(outDir, file), `${JSON.stringify(body, null, 2)}\n`); + writeFileSync(join(outDir, file), `${JSON.stringify(lv, null, 2)}\n`); manifest.levels.push({ level: lv.level, name: lv.name, chapter: lv.chapter, file, required: lv.required, ocdTarget: lv.ocdTarget, - sandbox: lv.sandbox || undefined, + element: lv.element || undefined, }); } -manifest.chapters = [ - { id: 1, name: 'The Goo Filled Hills', blurb: 'Learn to build.', from: 1, to: 6 }, - { id: 2, name: 'Sandbox', blurb: 'One level per mechanic — throwaway, replaced in Wave 4.', from: 7, to: LEVELS.length }, -]; +manifest.chapters = CHAPTERS.map((c) => { + const own = manifest.levels.filter((m) => m.chapter === c.id); + return { + id: c.id, + name: c.name, + blurb: c.blurb, + from: own.length ? own[0].level : 0, + to: own.length ? own[own.length - 1].level : 0, + }; +}).filter((c) => c.from > 0); writeFileSync(join(outDir, 'levels.json'), `${JSON.stringify(manifest, null, 2)}\n`); -console.log(`[gen] wrote ${LEVELS.length} levels + manifest to ${outDir}`); +console.log(`\n[gen] wrote ${levels.length} levels + manifest to ${outDir}`); +console.log(`[gen] ${stats.tried} candidates tried`); +for (const [why, n] of Object.entries(stats.rejected).sort((a, b) => b[1] - a[1])) { + console.log(`[gen] rejected ${String(n).padStart(4)} ${why}`); +} + +// ── The frozen hand-tuned openers ─────────────────────────────────────────── +// Emitted verbatim. These were authored as the teaching set; the generator must +// never rewrite them. +function frozenLevels() { + const out = []; + { + const f = footing(771, GROUND - 14); + out.push({ + world: { w: W, h: H }, level: 1, name: 'Ground Floor', chapter: 1, + tip: 'Drag goo from the heap onto the structure. Each ball needs two nearby friends to hold on to.', + terrain: [ground()], ...f, + pipe: { x: 771, y: 600, r: 46 }, + pile: heap([['common', 16]], 980, GROUND), + required: 4, ocdTarget: 9, + }); + } + { + const f = footing(430, 686); + out.push({ + world: { w: W, h: H }, level: 2, name: 'Mind the Gap', chapter: 1, + tip: 'Spikes below. Build ACROSS — triangles carry weight, long chains do not.', + terrain: [ + rect(0, 700, 600, H), rect(860, 700, W, H), rect(600, 930, 860, H, 'spike'), + // Lip on the outer rim: without it the heap spreads left, rolls off the + // edge of the world and the level quietly loses goo. + rect(0, 620, 40, 700), + ], + ...f, + pipe: { x: 980, y: 640, r: 46 }, + pile: heap([['common', 20]], 150, 700, { perRow: 7 }), + required: 5, ocdTarget: 12, + }); + } + { + const f = footing(560, GROUND - 14); + out.push({ + world: { w: W, h: H }, level: 3, name: 'Headroom', chapter: 1, + tip: 'You cannot build through the slab. Come out from under it first.', + terrain: [ground(), rect(300, 540, 820, 610)], ...f, + pipe: { x: 980, y: 470, r: 46 }, + pile: heap([['common', 24]], 1020, GROUND, { perRow: 8 }), + required: 5, ocdTarget: 12, + }); + } + { + const f = footing(331, GROUND - 14); + out.push({ + world: { w: W, h: H }, level: 4, name: 'Second Thoughts', chapter: 1, + tip: 'Green ivy goo can be pulled back off and used again. Grey goo is there for good.', + terrain: [ground()], ...f, + pipe: { x: 660, y: 560, r: 46 }, + pile: [ + ...heap([['ivy', 12]], 540, GROUND, { perRow: 6 }), + ...heap([['common', 8]], 860, GROUND, { perRow: 8 }), + ], + required: 4, ocdTarget: 9, + }); + } + { + const f = footing(791, GROUND - 14); + out.push({ + world: { w: W, h: H }, level: 5, name: 'Overhead', chapter: 1, + tip: 'The ceiling bites. Stop short of it.', + terrain: [ground(), rect(400, 180, 1200, 240, 'spike')], ...f, + pipe: { x: 791, y: 340, r: 46 }, + pile: heap([['common', 18]], 1000, GROUND, { perRow: 9 }), + required: 5, ocdTarget: 11, + }); + } + { + const f = footing(791, GROUND - 14); + out.push({ + world: { w: W, h: H }, level: 6, name: 'Tall Order', chapter: 1, + tip: 'A tower stands on compression and falls on sway. Brace every level.', + terrain: [ground()], ...f, + pipe: { x: 791, y: 180, r: 46 }, + pile: heap([['common', 26]], 1020, GROUND, { perRow: 9 }), + required: 6, ocdTarget: 14, + }); + } + return out; +} diff --git a/tools/verifyGooTower.js b/tools/verifyGooTower.js index b689149..2c597fe 100644 --- a/tools/verifyGooTower.js +++ b/tools/verifyGooTower.js @@ -848,6 +848,25 @@ section('4g. Balloon, block, bit'); `${(GOO_TYPES.balloon.mass * -GOO_TYPES.balloon.buoyancy).toFixed(2)} ball-weights`); check('balloon goo takes a single strand', GOO_TYPES.balloon.maxStrands === 1); + // Buoyancy is a property of ATTACHED goo only. Loose balloons that drift + // away take every balloon in a level's heap with them -- they float up, + // hit whatever ceiling the level has, and die before the player has + // touched anything, leaving the level unwinnable. + const heap = createState(baseLevel({ + terrain: [ground(), { kind: 'spike', poly: [[300, 300], [1300, 300], [1300, 360], [300, 360]] }], + // Resting ON the ground: GROUND_Y here is 800, not the generator's 850. + pile: [ + { x: 600, y: GROUND_Y - 16, type: 'balloon' }, { x: 640, y: GROUND_Y - 16, type: 'balloon' }, + { x: 680, y: GROUND_Y - 16, type: 'common' }, + ], + })); + settle(heap, 12); + check('loose balloons stay in the heap', heap.balls.every((b) => !b.dead), + `${heap.balls.filter((b) => b.dead).length} floated off and died`); + check('loose balloons rest on the ground', + heap.balls.filter((b) => b.type === 'balloon').every((b) => b.y > GROUND_Y - 40), + heap.balls.filter((b) => b.type === 'balloon').map((b) => b.y.toFixed(0)).join(',')); + // Block goo is stiffer, so the same span sags less. const span = (type) => { const balls = [{ x: 300, y: 300, type, pinned: true }];