1 /**********************************************************************************
2 * Copyright (c) 2008, 2009 Derek Yu and Mossmouth, LLC
3 * Copyright (c) 2018, Ketmar Dark
5 * This file is part of Spelunky.
7 * You can redistribute and/or modify Spelunky, including its source code, under
8 * the terms of the Spelunky User License.
10 * Spelunky is distributed in the hope that it will be entertaining and useful,
11 * but WITHOUT WARRANTY. Please see the Spelunky User License for more details.
13 * The Spelunky User License should be available in "Game Information", which
14 * can be found in the Resource Explorer, or as an external file called COPYING.
15 * If not, please obtain a new copy of Spelunky from <http://spelunkyworld.com/>
17 **********************************************************************************/
18 transient string introString1;
19 transient string introString2;
20 transient string introString3;
22 transient int introPhase;
23 transient int introPhaseTimer;
24 transient int titleCutsceneSkip;
27 void introCutscenePlayerControl (PlayerPawn plr) {
28 auto payPress = isKeyPressed(GameConfig::Key.Pay);
29 auto payRelease = isKeyReleased(GameConfig::Key.Pay);
31 if (stats.introViewed && introPhase < 8) {
32 switch (titleCutsceneSkip) {
33 case 0: // nothing was pressed
34 if (payPress) titleCutsceneSkip = 1;
36 case 1: // waiting for pay release
37 if (payRelease) titleCutsceneSkip = 2;
39 case 2: // pay released, do skip
40 cameFromIntroRoom = false;
47 if (!plr.visible) return;
50 if (introPhase == 8) {
52 player.visible = true;
53 player.status = MapObject::CLIMBING;
54 MakeMapObject(player.ix, player.y1+1, 'oFlare');
58 if (introPhase == 9) {
59 if (plr.status != MapObject::CLIMBING) {
66 if (introPhase == 10) {
67 if (plr.iy < 100 || plr.status == MapObject::CLIMBING) {
74 if (introPhase == 11) {
76 cameFromIntroRoom = false;
82 if (introPhase == 4) {
90 if (introPhase == 5) {
92 if (introPhaseTimer == 2) plr.kRopePressed = true;
95 if (introPhase == 6) {
97 if (introPhaseTimer > 0) {
100 //writeln(plr.status);
101 if (plr.status != MapObject::CLIMBING) {
107 introPhaseTimer = 255;
115 final void renderTitleCutscenePhrase (int phnum, int alpha) {
116 if (phnum > introPhase) return;
119 case 1: ss = introString1; break;
120 case 2: ss = introString2; break;
121 case 3: ss = introString3; break;
124 sprStore.loadFont('sFontSmall');
125 Video.color = 0xff_ff_ff|(clamp(255-alpha, 0, 255)<<24);
126 auto twdt = sprStore.getTextWidth(ss);
127 drawTextAt((320-twdt)/2, 80-16-16+phnum*16, ss);
131 void renderTitleCutsceneOverlay () {
132 if (introPhase >= 8) {
137 if (introPhase == -1) {
138 Video.color = clamp(introPhaseTimer, 0, 255)<<24;
139 Video.fillRect(0, 0, Video.screenWidth, Video.screenHeight);
142 if (introPhase >= 1) {
143 renderTitleCutscenePhrase(1, (introPhase == 1 ? introPhaseTimer : 255));
144 renderTitleCutscenePhrase(2, (introPhase == 2 ? introPhaseTimer : 255));
145 renderTitleCutscenePhrase(3, (introPhase == 3 ? introPhaseTimer : 255));
148 if (introPhase == 7) {
149 Video.color = clamp(introPhaseTimer, 0, 255)<<24;
150 Video.fillRect(0, 0, Video.screenWidth, Video.screenHeight);
153 Video.color = 0xff_ff_ff;
157 void thinkFrameIntro () {
158 // don't let the player fall away
159 if (player.ix <= 0) player.iy = 11*16+8;
160 //writeln(player.ix, ",", player.iy);
162 if (introPhase == -1) {
163 introPhaseTimer += 3;
164 if (introPhaseTimer < 255) return;
166 introPhaseTimer = 15;
169 if (introPhase == 0) {
170 if (--introPhaseTimer <= 0) {
177 if (introPhase >= 1 && introPhase <= 3) {
178 introPhaseTimer += 3;
179 if (introPhaseTimer >= 255+30*3) {
186 if (introPhase == 4) {
187 player.visible = true;
190 player.ix = player.ix+1;
191 player.fallTimer = 0;
192 player.status = MapObject::STANDING;
193 if (player.ix < 0) return;
195 if (player.ix > 200 && player.xVel == 0) {
197 introPhaseTimer = 30;
201 if (introPhase == 5) {
202 if (--introPhaseTimer == 0) {
204 introPhaseTimer = 10;
208 if (introPhase == 7) {
209 introPhaseTimer -= 2;
210 if (introPhaseTimer <= 0) {
211 cameFromIntroRoom = true;
215 //player.visible = true;
221 void createIntroRoom () {
222 clearForTransition();
223 //global.darkLevel = true;
227 introPhaseTimer = 30;
228 titleCutsceneSkip = 0;
235 //introPhaseTimer = 255;
237 switch (global.randOther(1, 8)) {
238 case 1: introString1 = "AS THE SUN BURNED BRIGHT ABOVE, "; break;
239 case 2: introString1 = "WITH THE DESERT STRETCHING BEHIND ME, "; break;
240 case 3: introString1 = "AFTER I DOUBLE-CHECKED MY MAP, "; break;
241 case 4: introString1 = "MY LIPS CRACKED AND COVERED IN SAND, "; break;
242 case 5: introString1 = "WITH FATE GUIDING MY EVERY MOVE, "; break;
243 case 6: introString1 = "PUTTING THE FADED PHOTO IN MY POCKET, "; break;
244 case 7: introString1 = "AS I RECALLED MY FATHER'S LAST WORDS, "; break;
245 case 8: introString1 = "MY MEMORY SLIPPING AWAY FROM ME, "; break;
248 switch (global.randOther(1, 8)) {
249 case 1: introString2 = "I STRODE VALIANTLY TOWARD MY DESTINY, "; break;
250 case 2: introString2 = "I SQUEEZED THE WHIP AT MY SIDE, "; break;
251 case 3: introString2 = "I DRAINED THE REST OF MY CANTEEN, "; break;
252 case 4: introString2 = "I SPOTTED THE CAVE'S ENTRANCE, "; break;
253 case 5: introString2 = "I FURROWED MY BROW, "; break;
254 case 6: introString2 = "I PAID MY BEDOUIN GUIDE, "; break;
255 case 7: introString2 = "I DISMOUNTED MY CAMEL, "; break;
256 case 8: introString2 = "I SQUINTED INTO THE DARKNESS, "; break;
259 switch (global.randOther(1, 8)) {
260 case 1: introString3 = "AND THOUGHT OF HER ONE LAST TIME."; break;
261 case 2: introString3 = "AND HELD MY HAT AGAINST THE WIND."; break;
262 case 3: introString3 = "AND A COLD CHILL TOOK HOLD OF ME."; break;
263 case 4: introString3 = "AND WONDERED HOW LONG I'D BE BELOW."; break;
264 case 5: introString3 = "AND VOWED TO RETURN VICTORIOUS."; break;
265 case 6: introString3 = "AND SWORE I HEARD VOICES UP AHEAD."; break;
266 case 7: introString3 = "AND FELT THE GODS SMILING UPON ME."; break;
267 case 8: introString3 = "AND THAT'S WHEN IT ALL STARTED."; break;
270 setRoomBounds(0, 0, 304, 224-16);
271 levBGImgName = 'bgCave';
272 //levBGImgName = 'sTitleBG';
275 //MakeMapTile(0, 0, 'oIntro');
276 //MakeMapTile(1, 0, 'oBricks');
277 //MakeMapTile(0, 1, 'oGlobals');
278 //MakeMapTile(1, 1, 'oGame');
280 MakeMapTile(0, 0, 'oEnd2BG');
281 MakeMapTile(0, 0, 'oCaveBG3');
283 MakeMapTile(10, 0, 'oBrick');
284 MakeMapTile(11, 0, 'oBrick');
285 MakeMapTile(12, 0, 'oBrick');
286 MakeMapTile(13, 0, 'oBrick');
287 MakeMapTile(14, 0, 'oBrick');
288 MakeMapTile(15, 0, 'oBrick');
289 MakeMapTile(16, 0, 'oBrick');
290 MakeMapTile(17, 0, 'oBrick');
291 MakeMapTile(18, 0, 'oBrick');
292 MakeMapTile(19, 0, 'oBrick');
293 MakeMapTile(9, 1, 'oBrick');
294 MakeMapTile(10, 1, 'oBrick');
295 MakeMapTile(11, 1, 'oBrick');
296 MakeMapTile(12, 1, 'oBrick');
297 MakeMapTile(13, 1, 'oBrick');
298 MakeMapTile(14, 1, 'oBrick');
299 MakeMapTile(15, 1, 'oBrick');
300 MakeMapTile(16, 1, 'oBrick');
301 MakeMapTile(17, 1, 'oBrick');
302 MakeMapTile(18, 1, 'oBrick');
303 MakeMapTile(19, 1, 'oBrick');
304 MakeMapTile(9, 2, 'oBrick');
305 MakeMapTile(10, 2, 'oBrick');
306 MakeMapTile(11, 2, 'oBrick');
307 MakeMapTile(12, 2, 'oBrick');
308 MakeMapTile(13, 2, 'oBrick');
309 MakeMapTile(14, 2, 'oBrick');
310 MakeMapTile(15, 2, 'oBrick');
311 MakeMapTile(16, 2, 'oBrick');
312 MakeMapTile(17, 2, 'oBrick');
313 MakeMapTile(18, 2, 'oBrick');
314 MakeMapTile(19, 2, 'oBrick');
315 MakeMapTile(9, 3, 'oBrick');
316 MakeMapTile(10, 3, 'oBrick');
317 MakeMapTile(11, 3, 'oBrick');
318 MakeMapTile(12, 3, 'oBrick');
319 MakeMapTile(13, 3, 'oBrick');
320 MakeMapTile(14, 3, 'oBrick');
321 MakeMapTile(15, 3, 'oBrick');
322 MakeMapTile(16, 3, 'oBrick');
323 MakeMapTile(17, 3, 'oBrick');
324 MakeMapTile(18, 3, 'oBrick');
325 MakeMapTile(19, 3, 'oBrick');
326 MakeMapTile(8, 4, 'oBrick');
327 MakeMapTile(9, 4, 'oBrick');
328 MakeMapTile(10, 4, 'oBrick');
329 MakeMapTile(11, 4, 'oBrick');
330 MakeMapTile(12, 4, 'oBrick');
331 MakeMapTile(13, 4, 'oBrick');
332 MakeMapTile(14, 4, 'oBrick');
333 MakeMapTile(15, 4, 'oBrick');
334 MakeMapTile(16, 4, 'oBrick');
335 MakeMapTile(17, 4, 'oBrick');
336 MakeMapTile(18, 4, 'oBrick');
337 MakeMapTile(19, 4, 'oBrick');
338 MakeMapTile(8, 5, 'oBrick');
339 MakeMapTile(9, 5, 'oBrick');
340 MakeMapTile(10, 5, 'oBrick');
341 MakeMapTile(11, 5, 'oBrick');
342 MakeMapTile(12, 5, 'oBrick');
343 MakeMapTile(13, 5, 'oBrick');
344 MakeMapTile(14, 5, 'oBrick');
345 MakeMapTile(15, 5, 'oBrick');
346 MakeMapTile(16, 5, 'oBrick');
347 MakeMapTile(17, 5, 'oBrick');
348 MakeMapTile(18, 5, 'oBrick');
349 MakeMapTile(19, 5, 'oBrick');
350 MakeMapTile(7, 6, 'oBrick');
351 MakeMapTile(8, 6, 'oBrick');
352 MakeMapTile(9, 6, 'oBrick');
353 MakeMapTile(10, 6, 'oBrick');
354 MakeMapTile(11, 6, 'oBrick');
355 MakeMapTile(12, 6, 'oBrick');
356 MakeMapTile(13, 6, 'oBrick');
357 MakeMapTile(14, 6, 'oBrick');
358 MakeMapTile(15, 6, 'oBrick');
359 MakeMapTile(16, 6, 'oBrick');
360 MakeMapTile(17, 6, 'oBrick');
361 MakeMapTile(18, 6, 'oBrick');
362 MakeMapTile(19, 6, 'oBrick');
363 MakeMapTile(7, 7, 'oBrick');
364 MakeMapTile(8, 7, 'oBrick');
365 MakeMapTile(9, 7, 'oBrick');
366 MakeMapTile(10, 7, 'oBrick');
367 MakeMapTile(11, 7, 'oBrick');
368 MakeMapTile(12, 7, 'oBrick');
369 MakeMapTile(13, 7, 'oBrick');
370 MakeMapTile(14, 7, 'oBrick');
371 MakeMapTile(15, 7, 'oBrick');
372 MakeMapTile(16, 7, 'oBrick');
373 MakeMapTile(17, 7, 'oBrick');
374 MakeMapTile(18, 7, 'oBrick');
375 MakeMapTile(19, 7, 'oBrick');
376 MakeMapTile(6, 8, 'oBrick');
377 MakeMapTile(7, 8, 'oBrick');
378 MakeMapTile(8, 8, 'oBrick');
379 MakeMapTile(9, 8, 'oBrick');
380 MakeMapTile(10, 8, 'oBrick');
381 MakeMapTile(11, 8, 'oBrick');
382 MakeMapTile(12, 8, 'oBrick');
383 MakeMapTile(13, 8, 'oBrick');
384 MakeMapTile(14, 8, 'oBrick');
385 MakeMapTile(15, 8, 'oBrick');
386 MakeMapTile(16, 8, 'oBrick');
387 MakeMapTile(17, 8, 'oBrick');
388 MakeMapTile(18, 8, 'oBrick');
389 MakeMapTile(19, 8, 'oBrick');
390 MakeMapTile(0, 9, 'oBGEnd3');
391 MakeMapTile(5, 9, 'oBrick');
392 MakeMapTile(6, 9, 'oBrick');
393 MakeMapTile(7, 9, 'oCaveBG2');
394 MakeMapTile(7, 9, 'oBrick');
395 MakeMapTile(8, 9, 'oBrick');
396 MakeMapTile(9, 9, 'oCaveBG2');
397 MakeMapTile(11, 9, 'oCaveBG2');
398 MakeMapTile(12, 9, 'oBrick');
399 MakeMapTile(13, 9, 'oCaveBG2');
400 MakeMapTile(15, 9, 'oCaveBG2');
401 MakeMapTile(17, 9, 'oBrick');
402 MakeMapTile(17, 9, 'oCaveBG2');
403 MakeMapTile(18, 9, 'oBrick');
404 MakeMapTile(19, 9, 'oBrick');
405 MakeMapTile(5, 10, 'oBrick');
406 MakeMapTile(6, 10, 'oBrick');
407 MakeMapTile(18, 10, 'oBrick');
408 MakeMapTile(19, 10, 'oBrick');
409 MakeMapTile(0, 11, 'oDesertTop');
410 MakeMapTile(1, 11, 'oDesertTop');
411 MakeMapTile(2, 11, 'oDesertTop');
412 MakeMapTile(3, 11, 'oDesertTop');
413 MakeMapTile(4, 11, 'oDesertTop');
414 MakeMapTile(5, 11, 'oCaveBG2');
415 MakeMapTile(7, 11, 'oCaveBG2');
416 MakeMapTile(9, 11, 'oCaveBG2');
417 MakeMapTile(11, 11, 'oCaveBG2');
418 MakeMapTile(13, 11, 'oCaveBG2');
419 MakeMapTile(15, 11, 'oCaveBG2');
420 MakeMapTile(17, 11, 'oCaveBG2');
421 MakeMapTile(18, 11, 'oBrick');
422 MakeMapTile(19, 11, 'oBrick');
423 MakeMapTile(0, 12, 'oDesert2');
424 MakeMapTile(1, 12, 'oDesert2');
425 MakeMapTile(2, 12, 'oDesert2');
426 MakeMapTile(3, 12, 'oDesert2');
427 MakeMapTile(4, 12, 'oDesert2');
428 MakeMapTile(5, 12, 'oBrick');
429 MakeMapTile(6, 12, 'oBrick');
430 MakeMapTile(7, 12, 'oBrick');
431 MakeMapTile(8, 12, 'oBrick');
432 MakeMapTile(9, 12, 'oBrick');
433 MakeMapTile(10, 12, 'oBrick');
434 MakeMapTile(11, 12, 'oBrick');
435 MakeMapTile(12, 12, 'oBrick');
436 MakeMapTile(13, 12, 'oBrick');
437 MakeMapTile(14, 12, 'oBrick');
438 MakeMapTile(15, 12, 'oBrick');
439 MakeMapTile(16, 12, 'oBrick');
440 MakeMapTile(18, 12, 'oBrick');
441 MakeMapTile(19, 12, 'oBrick');
442 MakeMapTile(0, 13, 'oDesert');
443 MakeMapTile(1, 13, 'oDesert');
444 MakeMapTile(2, 13, 'oDesert');
445 MakeMapTile(3, 13, 'oDesert');
446 MakeMapTile(4, 13, 'oDesert');
447 MakeMapTile(5, 13, 'oDesert');
448 MakeMapTile(6, 13, 'oBrick');
449 MakeMapTile(7, 13, 'oBrick');
450 MakeMapTile(8, 13, 'oBrick');
451 MakeMapTile(9, 13, 'oBrick');
452 MakeMapTile(10, 13, 'oBrick');
453 MakeMapTile(11, 13, 'oBrick');
454 MakeMapTile(12, 13, 'oBrick');
455 MakeMapTile(13, 13, 'oBrick');
456 MakeMapTile(14, 13, 'oBrick');
457 MakeMapTile(15, 13, 'oBrick');
458 MakeMapTile(16, 13, 'oBrick');
459 MakeMapTile(17, 13, 'oCaveBG2');
460 MakeMapTile(18, 13, 'oBrick');
461 MakeMapTile(19, 13, 'oBrick');
462 MakeMapTile(0, 14, 'oDesert');
463 MakeMapTile(1, 14, 'oDesert');
464 MakeMapTile(2, 14, 'oDesert');
465 MakeMapTile(3, 14, 'oDesert');
466 MakeMapTile(4, 14, 'oDesert');
467 MakeMapTile(5, 14, 'oDesert');
468 MakeMapTile(6, 14, 'oBrick');
469 MakeMapTile(7, 14, 'oBrick');
470 MakeMapTile(8, 14, 'oBrick');
471 MakeMapTile(9, 14, 'oBrick');
472 MakeMapTile(10, 14, 'oBrick');
473 MakeMapTile(11, 14, 'oBrick');
474 MakeMapTile(12, 14, 'oBrick');
475 MakeMapTile(13, 14, 'oBrick');
476 MakeMapTile(14, 14, 'oBrick');
477 MakeMapTile(15, 14, 'oBrick');
478 MakeMapTile(16, 14, 'oBrick');
479 MakeMapTile(18, 14, 'oBrick');
480 MakeMapTile(19, 14, 'oBrick');
482 if (global.randOther(1, 3) > 1) MakeMapTileAtPix(0, 176, 'oShrub');
483 if (global.randOther(1, 3) > 1) MakeMapTileAtPix(32, 176, 'oShrub');
485 if (global.randOther(1, 4) > 1) {
487 do { pty = global.randOther(1, 6); } while (pty == 2);
488 MakeMapTileAtPix(0, 56+pty*8, (pty < 2 ? 'oPalmTree' : 'oPalmTreeFwd'));
491 if (global.randOther(1, 4) > 1) {
493 do { pty = global.randOther(1, 8); } while (pty == 2);
494 MakeMapTileAtPix(32, 56+pty*8, (pty < 2 ? 'oPalmTree' : 'oPalmTreeFwd'));
497 if (global.randOther(1, 4) == 1) {
499 switch (global.randOther(0, 3)) {
500 case 0: xx = 144; break;
501 case 1: xx = 176; break;
502 case 2: xx = 208; break;
503 case 3: xx = 256; break;
505 MakeMapObject(xx, 144, 'oWeb');
508 if (global.randOther(1, 4) > 1) {
510 switch (global.randOther(0, 2)) {
511 case 0: xx = 160; break;
512 case 1: xx = 224; break;
513 case 2: xx = 240; break;
515 MakeMapTileAtPix(xx, 144, 'oLamp');
518 if (global.randOther(1, 5) == 1) MakeMapObject(144+global.randOther(1, 12)*8, 176+12, 'oRock');
519 else if (global.randOther(1, 4) == 1) MakeMapObject(144+global.randOther(1, 12)*8, 176+10, 'oJar');
520 else if (global.randOther(1, 3) == 1) {
521 int n = 144+global.randOther(1, 12)*8;
522 MakeMapObject(n, 176, 'oBones');
523 MakeMapObject(n+12, 176+12, 'oSkull');
526 if (global.randOther(1, 2) == 1) MakeMapTileAtPix(112, 160, 'oBrick');
528 // so the player will not fall away
530 auto supptile = MakeMapTile(1, 11, 'oBrick');
532 supptile.updateGrid();
534 supptile = MakeMapTile(1, 11, 'oBrick');
536 supptile.updateGrid();
539 spawnPlayerAt(-16, 11*16+8);
540 player.dir = MapEntity::Dir.Right;
541 player.flying = true;
542 player.visible = false;