1 /**********************************************************************************
2 * Copyright (c) 2008, 2009 Derek Yu and Mossmouth, LLC
3 * Copyright (c) 2010, Moloch
4 * Copyright (c) 2018, Ketmar Dark
6 * This file is part of Spelunky.
8 * You can redistribute and/or modify Spelunky, including its source code, under
9 * the terms of the Spelunky User License.
11 * Spelunky is distributed in the hope that it will be entertaining and useful,
12 * but WITHOUT WARRANTY. Please see the Spelunky User License for more details.
14 * The Spelunky User License should be available in "Game Information", which
15 * can be found in the Resource Explorer, or as an external file called COPYING.
16 * If not, please obtain a new copy of Spelunky from <http://spelunkyworld.com/>
18 **********************************************************************************/
19 // ////////////////////////////////////////////////////////////////////////// //
20 void scrLevGenShopkeeper (int xpos, int ypos, name shopType) {
21 auto obj = MonsterShopkeeper(MakeMapObject(xpos, ypos, 'oShopkeeper'));
23 //if (shopType == 'Ankh') writeln("::: ", shopType, " :::");
25 if (shopType == 'Craps') obj.generatePrizes();
30 // ////////////////////////////////////////////////////////////////////////// //
37 MapObject scrGenerateItem (int objx, int objy, GenItemSet setType) {
41 case GenItemSet.Crate: // crate set
42 if (global.randRoom(1, 500) == 1) obj = MakeMapObject(objx, objy, 'oJetpack');
43 else if (global.randRoom(1, 200) == 1) obj = MakeMapObject(objx, objy, 'oCapePickup');
44 else if (global.randRoom(1, 100) == 1) obj = MakeMapObject(objx, objy, 'oShotgun');
45 else if (!global.isTunnelMan && global.randRoom(1, 100) == 1) obj = MakeMapObject(objx, objy, 'oMattock');
46 else if (global.randRoom(1, 100) == 1) obj = MakeMapObject(objx, objy, 'oTeleporter');
47 else if (global.randRoom(1, 90) == 1) obj = MakeMapObject(objx, objy, 'oGloves');
48 else if (global.randRoom(1, 90) == 1) obj = MakeMapObject(objx, objy, 'oSpectacles');
49 else if (global.randRoom(1, 80) == 1) obj = MakeMapObject(objx, objy, 'oWebCannon');
50 else if (global.randRoom(1, 80) == 1) obj = MakeMapObject(objx, objy, 'oPistol');
51 else if (global.randRoom(1, 80) == 1) obj = MakeMapObject(objx, objy, 'oMitt');
52 else if (global.randRoom(1, 60) == 1) obj = MakeMapObject(objx, objy, 'oPaste');
53 else if (global.randRoom(1, 60) == 1) obj = MakeMapObject(objx, objy, 'oSpringShoes');
54 else if (global.randRoom(1, 60) == 1) obj = MakeMapObject(objx, objy, 'oSpikeShoes');
55 else if (global.randRoom(1, 60) == 1) obj = MakeMapObject(objx, objy, 'oMachete');
56 else if (global.randRoom(1, 40) == 1) obj = MakeMapObject(objx, objy, 'oBombBox');
57 else if (global.randRoom(1, 40) == 1) obj = MakeMapObject(objx, objy, 'oBow');
58 else if (global.randRoom(1, 20) == 1) obj = MakeMapObject(objx, objy, 'oCompass');
59 else if (global.randRoom(1, 10) == 1) obj = MakeMapObject(objx, objy, 'oParaPickup');
60 else obj = MakeMapObject(objx, objy, 'oRopePile');
63 case GenItemSet.Craps: // high end set -- craps game prizes
64 if (global.randRoom(1, 40) == 1) obj = MakeMapObject(objx, objy, 'oJetpack');
65 else if (global.randRoom(1, 25) == 1) obj = MakeMapObject(objx, objy, 'oCapePickup');
66 else if (global.randRoom(1, 20) == 1) obj = MakeMapObject(objx, objy, 'oShotgun');
67 else if (global.randRoom(1, 10) == 1) obj = MakeMapObject(objx, objy, 'oGloves');
68 else if (global.randRoom(1, 10) == 1) obj = MakeMapObject(objx, objy, 'oTeleporter');
69 else if (!global.isTunnelMan && global.randRoom(1, 8) == 1) obj = MakeMapObject(objx, objy, 'oMattock');
70 else if (global.randRoom(1, 8) == 1) obj = MakeMapObject(objx, objy, 'oPaste');
71 else if (global.randRoom(1, 8) == 1) obj = MakeMapObject(objx, objy, 'oSpringShoes');
72 else if (global.randRoom(1, 8) == 1) obj = MakeMapObject(objx, objy, 'oSpikeShoes');
73 else if (global.randRoom(1, 8) == 1) obj = MakeMapObject(objx, objy, 'oCompass');
74 else if (global.randRoom(1, 8) == 1) obj = MakeMapObject(objx, objy, 'oPistol');
75 else if (global.randRoom(1, 8) == 1) obj = MakeMapObject(objx, objy, 'oMachete');
76 else obj = MakeMapObject(objx, objy, 'oBombBox');
78 case GenItemSet.Underground: // Underground Set (items hidden inside solid walls, see oBrick etc)
79 switch (global.randRoom(0, 18)) {
80 case 0: obj = MakeMapObject(objx, objy-2, 'oJetpack'); break;
81 case 1: obj = MakeMapObject(objx, objy, 'oCapePickup'); break;
82 case 2: obj = MakeMapObject(objx, objy, 'oShotgun'); break;
84 if (global.isTunnelMan) obj = MakeMapObject(objx, objy, 'oRopePile');
85 else obj = MakeMapObject(objx, objy, 'oMattock');
87 case 4: obj = MakeMapObject(objx, objy+3, 'oTeleporter'); break;
88 case 5: obj = MakeMapObject(objx, objy-1, 'oGloves'); break;
89 case 6: obj = MakeMapObject(objx, objy, 'oSpectacles'); break;
90 case 7: obj = MakeMapObject(objx-2, objy, 'oWebCannon'); break;
91 case 8: obj = MakeMapObject(objx, objy, 'oPistol'); break;
92 case 9: obj = MakeMapObject(objx, objy-1, 'oMitt'); break;
93 case 10: obj = MakeMapObject(objx, objy, 'oPaste'); break;
94 case 11: obj = MakeMapObject(objx, objy, 'oSpringShoes'); break;
95 case 12: obj = MakeMapObject(objx, objy, 'oSpikeShoes'); break;
96 case 13: obj = MakeMapObject(objx, objy, 'oMachete'); break;
97 case 14: obj = MakeMapObject(objx, objy-2, 'oBombBox'); break;
98 case 15: obj = MakeMapObject(objx, objy, 'oBow'); break;
99 case 16: obj = MakeMapObject(objx, objy, 'oCompass'); break;
100 case 17: obj = MakeMapObject(objx, objy, 'oParaPickup'); break;
101 case 18: obj = MakeMapObject(objx, objy, 'oRopePile'); break;
110 // generate shop items
111 MapObject scrShopItemsGen (int xpos, int ypos, name shopType) {
112 MapObject obj = none;
114 writeln("generating items for shop \"", shopType, "\"...");
116 if (shopType == 'Bomb') {
118 if (global.randRoom(1, 5) == 1) {
119 if (!findAnyObjectOfType('oPaste')) { obj = MakeMapObject(xpos+8, ypos+10, 'oPaste'); break; }
120 } else if (global.randRoom(1, 4) == 1) {
121 obj = MakeMapObject(xpos+8, ypos+8, 'oBombBox');
123 } else if (global.config.optSGAmmo && global.randRoom(1, 10) == 1) {
124 obj = MakeMapObject(xpos+4, ypos+10, 'oShells');
127 if (global.config.optSGAmmo && findAnyObjectOfType('oShotgun')) {
128 obj = MakeMapObject(xpos+4, ypos+10, 'oShells');
130 obj = MakeMapObject(xpos+8, ypos+10, 'oBombBag');
135 } else if (shopType == 'Weapon') {
138 int n = global.randRoom(1, 4);
140 obj = MakeMapObject(xpos+8, ypos+10, 'oBombBag');
142 } else if (global.randRoom(1, 12) == 1) {
143 if (!findAnyObjectOfType('oWebCannon')) { obj = MakeMapObject(xpos+8, ypos+12, 'oWebCannon'); break; }
144 } else if (global.randRoom(1, 10) == 1) {
145 if (!findAnyObjectOfType('oShotgun')) { obj = MakeMapObject(xpos+8, ypos+12, 'oShotgun'); break; }
146 } else if (global.randRoom(1, 6) == 1) {
147 obj = MakeMapObject(xpos+8, ypos+10, 'oBombBox');
150 if (!findAnyObjectOfType('oPistol')) { obj = MakeMapObject(xpos+8, ypos+12, 'oPistol'); break; }
152 if (!findAnyObjectOfType('oMachete')) { obj = MakeMapObject(xpos+8, ypos+12, 'oMachete'); break; }
154 if (global.config.optSGAmmo && findAnyObjectOfType('oShotgun')) {
155 obj = MakeMapObject(xpos+4, ypos+10, 'oShells');
157 obj = MakeMapObject(xpos+8, ypos+10, 'oBombBag');
161 if (!findAnyObjectOfType('oBow')) { obj = MakeMapObject(xpos+8, ypos+12, 'oBow'); break; }
165 } else if (shopType == 'Clothing') {
168 int n = global.randRoom(1, 6);
169 if (global.randRoom(1, m) == 1) { obj = MakeMapObject(xpos+8, ypos+11, 'oRopePile'); break; }
170 else if (n == 1) { if (!findAnyObjectOfType('oSpringShoes')) { obj = MakeMapObject(xpos+8, ypos+10, 'oSpringShoes'); break; } }
171 else if (n == 2) { if (!findAnyObjectOfType('oSpectacles')) { obj = MakeMapObject(xpos+8, ypos+10, 'oSpectacles'); break; } }
172 else if (n == 3) { if (!findAnyObjectOfType('oGloves')) { obj = MakeMapObject(xpos+8, ypos+8, 'oGloves'); break; } }
173 else if (n == 4) { if (!findAnyObjectOfType('oMitt')) { obj = MakeMapObject(xpos+8, ypos+8, 'oMitt'); break; } }
174 else if (n == 5) { if (!findAnyObjectOfType('oCapePickup')) { obj = MakeMapObject(xpos+8, ypos+10, 'oCapePickup'); break; } }
175 else if (n == 6) { if (!findAnyObjectOfType('oSpikeShoes')) { obj = MakeMapObject(xpos+8, ypos+10, 'oSpikeShoes'); break; } }
178 } else if (shopType == 'Rare') {
181 int n = global.randRoom(1, 11);
182 if (global.randRoom(1, m) == 1) { obj = MakeMapObject(xpos+8, ypos+8, 'oBombBox'); break; }
183 else if (n == 1) { if (!findAnyObjectOfType('oSpringShoes')) { obj = MakeMapObject(xpos+8, ypos+10, 'oSpringShoes'); break; } }
184 else if (n == 2) { if (!findAnyObjectOfType('oCompass')) { obj = MakeMapObject(xpos+8, ypos+10, 'oCompass'); break; } }
185 else if (n == 3) { if (!findAnyObjectOfType('oMattock') && !global.isTunnelMan) { obj = MakeMapObject(xpos+8, ypos+10, 'oMattock'); break; } }
186 else if (n == 4) { if (!findAnyObjectOfType('oSpectacles')) { obj = MakeMapObject(xpos+8, ypos+10, 'oSpectacles'); break; } }
187 else if (n == 5) { if (!findAnyObjectOfType('oJetpack')) { obj = MakeMapObject(xpos+8, ypos+8, 'oJetpack'); break; } }
188 else if (n == 6) { if (!findAnyObjectOfType('oGloves')) { obj = MakeMapObject(xpos+8, ypos+8, 'oGloves'); break; } }
189 else if (n == 7) { if (!findAnyObjectOfType('oMitt')) { obj = MakeMapObject(xpos+8, ypos+8, 'oMitt'); break; } }
190 else if (n == 8) { if (!findAnyObjectOfType('oWebCannon')) { obj = MakeMapObject(xpos+8, ypos+12, 'oWebCannon'); break; } }
191 else if (n == 9) { if (!findAnyObjectOfType('oCapePickup')) { obj = MakeMapObject(xpos+8, ypos+10, 'oCapePickup'); break; } }
192 else if (n == 10) { if (!findAnyObjectOfType('oTeleporter')) { obj = MakeMapObject(xpos+8, ypos+12, 'oTeleporter'); break; } }
193 else if (n == 11) { if (!findAnyObjectOfType('oSpikeShoes')) { obj = MakeMapObject(xpos+8, ypos+10, 'oSpikeShoes'); break; } }
198 int n = global.randRoom(1, 3);
199 if (global.randRoom(1, 20) == 1) { if (!findAnyObjectOfType('oMattock') && !global.isTunnelMan) { obj = MakeMapObject(xpos+8, ypos+10, 'oMattock'); break; } }
200 else if (global.randRoom(1, 10) == 1) { if (!findAnyObjectOfType('oGloves')) { obj = MakeMapObject(xpos+8, ypos+8, 'oGloves'); break; } }
201 else if (global.randRoom(1, 10) == 1) { if (!findAnyObjectOfType('oCompass')) { obj = MakeMapObject(xpos+8, ypos+10, 'oCompass'); break; } }
203 if (global.config.optSGAmmo && findAnyObjectOfType('oShotgun')) {
204 obj = MakeMapObject(xpos+4, ypos+10, 'oShells');
206 obj = MakeMapObject(xpos+8, ypos+10, 'oBombBag');
209 } else if (n == 2) { obj = MakeMapObject(xpos+8, ypos+11, 'oRopePile'); break; }
210 else if (n == 3) { obj = MakeMapObject(xpos+8, ypos+10, 'oParaPickup'); break; }
216 obj.shopType = shopType;
217 /+k8: cost is generated in item creation code
218 if (global.currLevel > 2) {
219 if (obj.cost <= 0) obj.cost = 100;
220 obj.cost += (obj.cost/100)*10*(global.currLevel-2);
221 //if (shopDesc == "") buyMessage = "A "+string_upper(type)+" FOR $"+string(cost)+".";
222 //else buyMessage = shopDesc+" FOR $"+string(cost)+".";
231 // ////////////////////////////////////////////////////////////////////////// //
232 //WARNING: keep this in sync with `ItemJar::onDestroy()`!
233 name scrLevGenCreateJarContents () {
236 if (global.randRoom(1, 3) == 1) ctx = 'oGoldChunk';
237 else if (global.config.optSGAmmo && global.randRoom(1, 4) == 1) ctx = 'oShellSingle';
238 else if (global.randRoom(1, 6) == 1) ctx = 'oGoldNugget';
239 else if (global.randRoom(1, 12) == 1) ctx = 'oEmeraldBig';
240 else if (global.randRoom(1, 12) == 1) ctx = 'oSapphireBig';
241 else if (global.randRoom(1, 12) == 1) ctx = 'oRubyBig';
242 else if (global.randRoom(1, 6) == 1) ctx = 'oSpider';
243 else if (global.randRoom(1, 12) == 1) { if (global.randRoom(1, 50) == 1) ctx = 'oCobra'; else ctx = 'oSnake'; }
244 else if (global.randRoom(1, 100) == 1) ctx = 'oAlien';
245 else if (global.randRoom(1, 300) == 1) ctx = 'oBlob';
248 switch (global.randRoom(0, 2)) {
249 case 0: ctx = 'oEmeraldBig'; break;
250 case 1: ctx = 'oSapphireBig'; break;
251 case 2: ctx = 'oRubyBig'; break;
261 final MapObject scrLevGenCreateJar (int x, int y) {
262 auto obj = MakeMapObject(x, y, 'oJar');
263 //MapItem(obj).contents = scrLevGenCreateJarContents();
268 // ////////////////////////////////////////////////////////////////////////// //
269 final bool cbIsGoldIdol (MapObject o) { return (o isa ItemGoldIdol); }
270 final bool cbIsGiantSpider (MapObject o) { return (o isa EnemyGiantSpider); }
271 final bool cbIsChestObject (MapObject o) { return (o isa ItemChest); }
273 final bool cbIsTreasureTile (MapTile t) { return !!t.gem; } //K8:FIXME: only real treasures?
274 final bool cbIsBadTile (MapTile t) { return (t.spikes || t.enter || t.exit); }
275 final bool cbIsBlockTile (MapTile t) { return (t.objType == 'oBlock'); }
276 final bool cbIsLiquidTile (MapTile t) { return (t.water || t.lava); }
279 // Generates crates, chests, gold, gems, and bones
280 void scrTreasureGen (int x, int y, optional int bonesChance) {
284 if (calcNearestEnterDist(x+8, y+8) < 32) return;
285 if (calcNearestExitDist(x+8, y+8) < 32) return;
286 if (calcNearestObjectDist(x+8, y+8, &cbIsGoldIdol) < 64) return;
289 isSolidAtPoint(x, y-16) ||
290 checkTileAtPoint(x, y-1, &cbIsTreasureTile) ||
291 isObjectAtTilePix(x, y-8, &cbIsChestObject) || //<-collision_point(x, y-8, oChest, 0, 0) &&
292 checkTileAtPoint(x, y-8, &cbIsBadTile);
295 if (global.randRoom(1, 100) == 1) { MakeMapObject(x+8, y-4, 'oRock'); return; }
296 if (global.randRoom(1, 40) == 1) { scrLevGenCreateJar(x+8, y-6); return; }
301 isSolidAtPoint(x, y-32) &&
302 (isSolidAtPoint(x-16, y-16) ||
303 isSolidAtPoint(x+16, y-16) ||
304 checkTileAtPoint(x-16, y-16, &cbIsBlockTile) ||
305 checkTileAtPoint(x+16, y-16, &cbIsBlockTile)))
308 if (calcNearestObjectDist(x+8, y+8, &cbIsGiantSpider) < 100) n = 5;
309 if (global.levelType != 2 && global.randRoom(1, n) == 1) {
310 MakeMapObject(x, y-16, 'oWeb');
311 } else if (global.genUdjatEye && !global.LockedChest) {
312 if (global.randRoom(1, global.lockedChestChance) == 1) {
313 MakeMapObject(x+8, y-16+4, 'oLockedChest');
314 global.LockedChest = true;
315 writeln("*** GENERATED LOCKED CHEST");
317 global.lockedChestChance -= 1;
319 } else if (global.randRoom(1, 10) == 1) {
320 scrLevGenCreateCrate(x+8, y-8);
321 } else if (global.randRoom(1, 15) == 1) {
322 scrLevGenCreateChest(x+8, y-8);
323 } else if (!global.damsel && global.randRoom(1, 8) == 1 && !checkTileAtPoint(x+8, y-8, &cbIsLiquidTile)) {
324 auto obj = MakeMapObject(x+8, y-8, 'oDamsel');
325 if (obj) global.damsel = true;
326 } else if (global.randRoom(1, 40-2*global.currLevel) <= 1+bonesChance) {
327 //writeln("=== BONES ===");
328 if (global.randRoom(1, 8) == 1) {
329 MakeMapObject(x, y-16, 'oFakeBones');
331 MakeMapObject(x, y-16, 'oBones');
332 MakeMapObject(x+12, y-4, 'oSkull');
335 else if (global.randRoom(1, 3) == 1) MakeMapObject(x+8, y-4, 'oGoldBar');
336 else if (global.randRoom(1, 6) == 1) MakeMapObject(x+8, y-8, 'oGoldBars');
337 else if (global.randRoom(1, 6) == 1) MakeMapObject(x+8, y-4, 'oEmeraldBig');
338 else if (global.randRoom(1, 8) == 1) MakeMapObject(x+8, y-4, 'oSapphireBig');
339 else if (global.randRoom(1, 10) == 1) MakeMapObject(x+8, y-4, 'oRubyBig');
340 //else if (global.bizarre && randRoom(1, 6) == 1) {obj = MakeMapObject(x+8, y-8, 'oAntidote'); obj.cost = 0; obj.forSale = false} // in the original
342 else if (!colStuff && isSolidAtPoint(x-16, y-16) && isSolidAtPoint(x+16, y-16)) {
344 if (calcNearestObjectDist(x+8, y+8, &cbIsGiantSpider) < 100) n = 10;
345 if (global.levelType != 2 && global.randRoom(1, n) == 1) MakeMapObject(x, y-16, 'oWeb');
346 else if (global.randRoom(1, 4) == 1) MakeMapObject(x+8, y-4, 'oGoldBar');
347 else if (global.randRoom(1, 8) == 1) MakeMapObject(x+8, y-8, 'oGoldBars');
348 else if (global.randRoom(1, 80-global.currLevel) <= 1+bonesChance) {
349 if (global.randRoom(1, 8) == 1) {
350 MakeMapObject(x, y-16, 'oFakeBones');
352 MakeMapObject(x, y-16, 'oBones');
353 MakeMapObject(x+12, y-4, 'oSkull');
356 else if (global.randRoom(1, 8) == 1) MakeMapObject(x+8, y-4, 'oEmeraldBig');
357 else if (global.randRoom(1, 9) == 1) MakeMapObject(x+8, y-4, 'oSapphireBig');
358 else if (global.randRoom(1, 10) == 1) MakeMapObject(x+8, y-4, 'oRubyBig');
359 //else if (global.bizarre && randRoom(1, 10) == 1) {obj = MakeMapObject(x+8, y-8, 'oAntidote'); obj.cost = 0; obj.forSale = false} // in the original
361 else if (!isSolidAtPoint(x, y-16) &&
362 isObjectAtTilePix(x, y-8, &cbIsChestObject) && //<-collision_point(x, y-8, oChest, 0, 0) &&
363 !checkTileAtPoint(x, y-8, &cbIsBadTile))
365 if (global.randRoom(1, 40) == 1) MakeMapObject(x+8, y-4, 'oGoldBar');
366 else if (global.randRoom(1, 50) == 1) MakeMapObject(x+8, y-8, 'oGoldBars');
367 else if (global.randRoom(1, 140-2*global.currLevel) <= 1+bonesChance) {
368 if (global.randRoom(1, 8) == 1) {
369 MakeMapObject(x, y-16, 'oFakeBones');
371 MakeMapObject(x, y-16, 'oBones');
372 MakeMapObject(x+12, y-4, 'oSkull');
379 // ////////////////////////////////////////////////////////////////////////// //
380 name scrGenGetFrogType () {
381 if (global.config.optEnemyVariations) {
382 int totdeath789 = stats.getDeathCountOnLevel(7)+stats.getDeathCountOnLevel(8)+stats.getDeathCountOnLevel(9);
383 if (totdeath789 < 22) {
384 if (global.randOther(0, 100) >= 99-(global.currLevel-4)*8) return 'oGreenFrog';
387 if (totdeath789 < 32) {
388 if (global.randOther(0, 100) >= 85-(global.currLevel-4)*8) return 'oGreenFrog';
391 if (totdeath789 < 42) {
392 if (global.randOther(0, 100) >= 75-(global.currLevel-4)*8) return 'oGreenFrog';
395 if (totdeath789 < 52) {
396 if (global.randOther(0, 100) >= 65-(global.currLevel-4)*8) return 'oGreenFrog';
399 if (totdeath789 < 62) {
400 if (global.randOther(0, 100) >= 55-(global.currLevel-4)*8) return 'oGreenFrog';
403 if (global.randOther(0, 100) >= 50-(global.currLevel-4)*8) return 'oGreenFrog';
409 // ////////////////////////////////////////////////////////////////////////// //
411 private final bool scrGenEntitiesInMinesCB (int tileX, int tileY, MapTile t) {
412 if (!isInShop(tileX, tileY) && tileY > 1) {
413 if (t.objType != 'Altar') {
414 scrTreasureGen(tileX*16, tileY*16);
417 tileXY2roomXY(tileX, tileY-1, roomX, roomY); //k8: why -1?
419 if (roomX != startRoomX || roomY != startRoomY) {
420 if (tileY < GameLevel::NormalTilesHeight-4 &&
421 !checkTilesInRect(tileX*16, (tileY+1)*16, 17, 33, &cbCollisionAnySolidOrLiquid) &&
422 !isObjectAtPoint(tileX*16+8, (tileY+1)*16+8))
424 if (global.genGiantSpider && !global.giantSpider &&
425 global.randRoom(1, trunci(fceil(40.0/global.config.enemyMult))) == 1 &&
426 !checkTilesInRect((tileX+1)*16, (tileY+1)*16, 17, 33, &cbCollisionAnySolid/*k8:???OrLiquid*/))
428 MakeMapObject(tileX*16, (tileY+1)*16, 'oGiantSpiderHang');
429 global.giantSpider = true;
431 else if (global.darkLevel && global.randRoom(1, 60) == 1) MakeMapTile(tileX, tileY+1, 'oLamp');
432 else if (global.darkLevel && global.randRoom(1, 40) == 1) MakeMapObject(tileX*16, (tileY+1)*16, 'oScarab');
433 else if (global.randRoom(1, trunci(fceil(60.0/global.config.enemyMult))) == 1) MakeMapObject(tileX*16, (tileY+1)*16, 'oBat');
434 else if (global.randRoom(1, trunci(fceil(80.0/global.config.enemyMult))) == 1) MakeMapObject(tileX*16, (tileY+1)*16, scrGenGetSpiderType());
436 if (global.giantSpider && global.config.enemyMult >= 2) {
437 if (global.randRoom(1, trunci(fceil(2400.0/global.config.enemyMult))) == 1) {
438 global.genGiantSpider = true;
439 global.giantSpider = false;
442 if (!checkTileAtPoint(tileX*16, (tileY-1)*16, &cbCollisionAnySolid/*k8:???OrLiquid*/)) {
443 if (global.randRoom(1, trunci(fceil(60.0/global.config.enemyMult))) == 1) {
444 MakeMapObject(tileX*16, (tileY-1)*16, scrGenGetSnakeType());
445 } else if (global.randRoom(1, trunci(fceil(800.0/global.config.enemyMult))) == 1) {
446 MakeMapObject(tileX*16, (tileY-1)*16, 'oCaveman');
451 // `false` means "continue"
457 // ////////////////////////////////////////////////////////////////////////// //
458 final bool isTreasureObjectCB (MapObject o) { return o.isTreasure; }
459 final bool isChestObjectCB (MapObject o) { return (o isa ItemOpenableContainer); } // not only chest, but a crate too