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 transient string introString1;
20 transient string introString2;
21 transient string introString3;
23 transient int introPhase;
24 transient int introPhaseTimer;
25 transient int titleCutsceneSkip;
28 void introCutscenePlayerControl (PlayerPawn plr) {
29 auto payPress = isKeyPressed(GameConfig::Key.Pay);
30 auto payRelease = isKeyReleased(GameConfig::Key.Pay);
32 if (stats.introViewed && introPhase < 8) {
33 switch (titleCutsceneSkip) {
34 case 0: // nothing was pressed
35 if (payPress) titleCutsceneSkip = 1;
37 case 1: // waiting for pay release
38 if (payRelease) titleCutsceneSkip = 2;
40 case 2: // pay released, do skip
41 cameFromIntroRoom = false;
48 if (!plr.visible) return;
51 if (introPhase == 8) {
53 player.visible = true;
54 player.status = MapObject::CLIMBING;
55 MakeMapObject(player.ix, player.y1+1, 'oFlare');
59 if (introPhase == 9) {
60 if (plr.status != MapObject::CLIMBING) {
67 if (introPhase == 10) {
68 if (plr.iy < 100 || plr.status == MapObject::CLIMBING) {
75 if (introPhase == 11) {
77 cameFromIntroRoom = false;
83 if (introPhase == 4) {
91 if (introPhase == 5) {
93 if (introPhaseTimer == 2) plr.kRopePressed = true;
96 if (introPhase == 6) {
98 if (introPhaseTimer > 0) {
101 //writeln(plr.status);
102 if (plr.status != MapObject::CLIMBING) {
108 introPhaseTimer = 255;
116 final void renderTitleCutscenePhrase (int phnum, int alpha) {
117 if (phnum > introPhase) return;
120 case 1: ss = introString1; break;
121 case 2: ss = introString2; break;
122 case 3: ss = introString3; break;
125 sprStore.loadFont('sFontSmall');
126 Video.color = 0xff_ff_ff|(clamp(255-alpha, 0, 255)<<24);
127 auto twdt = sprStore.getTextWidth(ss);
128 drawTextAt((320-twdt)/2, 80-16-16+phnum*16, ss);
132 void renderTitleCutsceneOverlay () {
133 if (introPhase >= 8) {
138 if (introPhase == -1) {
139 Video.color = clamp(introPhaseTimer, 0, 255)<<24;
140 Video.fillRect(0, 0, Video.screenWidth, Video.screenHeight);
143 if (introPhase >= 1) {
144 renderTitleCutscenePhrase(1, (introPhase == 1 ? introPhaseTimer : 255));
145 renderTitleCutscenePhrase(2, (introPhase == 2 ? introPhaseTimer : 255));
146 renderTitleCutscenePhrase(3, (introPhase == 3 ? introPhaseTimer : 255));
149 if (introPhase == 7) {
150 Video.color = clamp(introPhaseTimer, 0, 255)<<24;
151 Video.fillRect(0, 0, Video.screenWidth, Video.screenHeight);
154 Video.color = 0xff_ff_ff;
158 void thinkFrameIntro () {
159 // don't let the player fall away
160 if (player.ix <= 0) player.iy = 11*16+8;
161 //writeln(player.ix, ",", player.iy);
163 if (introPhase == -1) {
164 introPhaseTimer += 3;
165 if (introPhaseTimer < 255) return;
167 introPhaseTimer = 15;
170 if (introPhase == 0) {
171 if (--introPhaseTimer <= 0) {
178 if (introPhase >= 1 && introPhase <= 3) {
179 introPhaseTimer += 3;
180 if (introPhaseTimer >= 255+30*3) {
187 if (introPhase == 4) {
188 player.visible = true;
191 player.ix = player.ix+1;
192 player.fallTimer = 0;
193 player.status = MapObject::STANDING;
194 if (player.ix < 0) return;
196 if (player.ix > 200 && player.xVel == 0) {
198 introPhaseTimer = 30;
202 if (introPhase == 5) {
203 if (--introPhaseTimer == 0) {
205 introPhaseTimer = 10;
209 if (introPhase == 7) {
210 introPhaseTimer -= 2;
211 if (introPhaseTimer <= 0) {
212 cameFromIntroRoom = true;
216 //player.visible = true;
222 void createIntroRoom () {
223 clearForTransition();
224 //global.darkLevel = true;
228 introPhaseTimer = 30;
229 titleCutsceneSkip = 0;
236 //introPhaseTimer = 255;
238 switch (global.randOther(1, 8)) {
239 case 1: introString1 = "AS THE SUN BURNED BRIGHT ABOVE, "; break;
240 case 2: introString1 = "WITH THE DESERT STRETCHING BEHIND ME, "; break;
241 case 3: introString1 = "AFTER I DOUBLE-CHECKED MY MAP, "; break;
242 case 4: introString1 = "MY LIPS CRACKED AND COVERED IN SAND, "; break;
243 case 5: introString1 = "WITH FATE GUIDING MY EVERY MOVE, "; break;
244 case 6: introString1 = "PUTTING THE FADED PHOTO IN MY POCKET, "; break;
245 case 7: introString1 = "AS I RECALLED MY FATHER'S LAST WORDS, "; break;
246 case 8: introString1 = "MY MEMORY SLIPPING AWAY FROM ME, "; break;
249 switch (global.randOther(1, 8)) {
250 case 1: introString2 = "I STRODE VALIANTLY TOWARD MY DESTINY, "; break;
251 case 2: introString2 = "I SQUEEZED THE WHIP AT MY SIDE, "; break;
252 case 3: introString2 = "I DRAINED THE REST OF MY CANTEEN, "; break;
253 case 4: introString2 = "I SPOTTED THE CAVE'S ENTRANCE, "; break;
254 case 5: introString2 = "I FURROWED MY BROW, "; break;
255 case 6: introString2 = "I PAID MY BEDOUIN GUIDE, "; break;
256 case 7: introString2 = "I DISMOUNTED MY CAMEL, "; break;
257 case 8: introString2 = "I SQUINTED INTO THE DARKNESS, "; break;
260 switch (global.randOther(1, 8)) {
261 case 1: introString3 = "AND THOUGHT OF HER ONE LAST TIME."; break;
262 case 2: introString3 = "AND HELD MY HAT AGAINST THE WIND."; break;
263 case 3: introString3 = "AND A COLD CHILL TOOK HOLD OF ME."; break;
264 case 4: introString3 = "AND WONDERED HOW LONG I'D BE BELOW."; break;
265 case 5: introString3 = "AND VOWED TO RETURN VICTORIOUS."; break;
266 case 6: introString3 = "AND SWORE I HEARD VOICES UP AHEAD."; break;
267 case 7: introString3 = "AND FELT THE GODS SMILING UPON ME."; break;
268 case 8: introString3 = "AND THAT'S WHEN IT ALL STARTED."; break;
271 setRoomBounds(0, 0, 304, 224-16);
272 levBGImgName = 'bgCave';
273 //levBGImgName = 'sTitleBG';
276 //MakeMapTile(0, 0, 'oIntro');
277 //MakeMapTile(1, 0, 'oBricks');
278 //MakeMapTile(0, 1, 'oGlobals');
279 //MakeMapTile(1, 1, 'oGame');
281 MakeMapTile(0, 0, 'oEnd2BG');
282 MakeMapTile(0, 0, 'oCaveBG3');
284 MakeMapTile(10, 0, 'oBrick');
285 MakeMapTile(11, 0, 'oBrick');
286 MakeMapTile(12, 0, 'oBrick');
287 MakeMapTile(13, 0, 'oBrick');
288 MakeMapTile(14, 0, 'oBrick');
289 MakeMapTile(15, 0, 'oBrick');
290 MakeMapTile(16, 0, 'oBrick');
291 MakeMapTile(17, 0, 'oBrick');
292 MakeMapTile(18, 0, 'oBrick');
293 MakeMapTile(19, 0, 'oBrick');
294 MakeMapTile(9, 1, 'oBrick');
295 MakeMapTile(10, 1, 'oBrick');
296 MakeMapTile(11, 1, 'oBrick');
297 MakeMapTile(12, 1, 'oBrick');
298 MakeMapTile(13, 1, 'oBrick');
299 MakeMapTile(14, 1, 'oBrick');
300 MakeMapTile(15, 1, 'oBrick');
301 MakeMapTile(16, 1, 'oBrick');
302 MakeMapTile(17, 1, 'oBrick');
303 MakeMapTile(18, 1, 'oBrick');
304 MakeMapTile(19, 1, 'oBrick');
305 MakeMapTile(9, 2, 'oBrick');
306 MakeMapTile(10, 2, 'oBrick');
307 MakeMapTile(11, 2, 'oBrick');
308 MakeMapTile(12, 2, 'oBrick');
309 MakeMapTile(13, 2, 'oBrick');
310 MakeMapTile(14, 2, 'oBrick');
311 MakeMapTile(15, 2, 'oBrick');
312 MakeMapTile(16, 2, 'oBrick');
313 MakeMapTile(17, 2, 'oBrick');
314 MakeMapTile(18, 2, 'oBrick');
315 MakeMapTile(19, 2, 'oBrick');
316 MakeMapTile(9, 3, 'oBrick');
317 MakeMapTile(10, 3, 'oBrick');
318 MakeMapTile(11, 3, 'oBrick');
319 MakeMapTile(12, 3, 'oBrick');
320 MakeMapTile(13, 3, 'oBrick');
321 MakeMapTile(14, 3, 'oBrick');
322 MakeMapTile(15, 3, 'oBrick');
323 MakeMapTile(16, 3, 'oBrick');
324 MakeMapTile(17, 3, 'oBrick');
325 MakeMapTile(18, 3, 'oBrick');
326 MakeMapTile(19, 3, 'oBrick');
327 MakeMapTile(8, 4, 'oBrick');
328 MakeMapTile(9, 4, 'oBrick');
329 MakeMapTile(10, 4, 'oBrick');
330 MakeMapTile(11, 4, 'oBrick');
331 MakeMapTile(12, 4, 'oBrick');
332 MakeMapTile(13, 4, 'oBrick');
333 MakeMapTile(14, 4, 'oBrick');
334 MakeMapTile(15, 4, 'oBrick');
335 MakeMapTile(16, 4, 'oBrick');
336 MakeMapTile(17, 4, 'oBrick');
337 MakeMapTile(18, 4, 'oBrick');
338 MakeMapTile(19, 4, 'oBrick');
339 MakeMapTile(8, 5, 'oBrick');
340 MakeMapTile(9, 5, 'oBrick');
341 MakeMapTile(10, 5, 'oBrick');
342 MakeMapTile(11, 5, 'oBrick');
343 MakeMapTile(12, 5, 'oBrick');
344 MakeMapTile(13, 5, 'oBrick');
345 MakeMapTile(14, 5, 'oBrick');
346 MakeMapTile(15, 5, 'oBrick');
347 MakeMapTile(16, 5, 'oBrick');
348 MakeMapTile(17, 5, 'oBrick');
349 MakeMapTile(18, 5, 'oBrick');
350 MakeMapTile(19, 5, 'oBrick');
351 MakeMapTile(7, 6, 'oBrick');
352 MakeMapTile(8, 6, 'oBrick');
353 MakeMapTile(9, 6, 'oBrick');
354 MakeMapTile(10, 6, 'oBrick');
355 MakeMapTile(11, 6, 'oBrick');
356 MakeMapTile(12, 6, 'oBrick');
357 MakeMapTile(13, 6, 'oBrick');
358 MakeMapTile(14, 6, 'oBrick');
359 MakeMapTile(15, 6, 'oBrick');
360 MakeMapTile(16, 6, 'oBrick');
361 MakeMapTile(17, 6, 'oBrick');
362 MakeMapTile(18, 6, 'oBrick');
363 MakeMapTile(19, 6, 'oBrick');
364 MakeMapTile(7, 7, 'oBrick');
365 MakeMapTile(8, 7, 'oBrick');
366 MakeMapTile(9, 7, 'oBrick');
367 MakeMapTile(10, 7, 'oBrick');
368 MakeMapTile(11, 7, 'oBrick');
369 MakeMapTile(12, 7, 'oBrick');
370 MakeMapTile(13, 7, 'oBrick');
371 MakeMapTile(14, 7, 'oBrick');
372 MakeMapTile(15, 7, 'oBrick');
373 MakeMapTile(16, 7, 'oBrick');
374 MakeMapTile(17, 7, 'oBrick');
375 MakeMapTile(18, 7, 'oBrick');
376 MakeMapTile(19, 7, 'oBrick');
377 MakeMapTile(6, 8, 'oBrick');
378 MakeMapTile(7, 8, 'oBrick');
379 MakeMapTile(8, 8, 'oBrick');
380 MakeMapTile(9, 8, 'oBrick');
381 MakeMapTile(10, 8, 'oBrick');
382 MakeMapTile(11, 8, 'oBrick');
383 MakeMapTile(12, 8, 'oBrick');
384 MakeMapTile(13, 8, 'oBrick');
385 MakeMapTile(14, 8, 'oBrick');
386 MakeMapTile(15, 8, 'oBrick');
387 MakeMapTile(16, 8, 'oBrick');
388 MakeMapTile(17, 8, 'oBrick');
389 MakeMapTile(18, 8, 'oBrick');
390 MakeMapTile(19, 8, 'oBrick');
391 MakeMapTile(0, 9, 'oBGEnd3');
392 MakeMapTile(5, 9, 'oBrick');
393 MakeMapTile(6, 9, 'oBrick');
394 MakeMapTile(7, 9, 'oCaveBG2');
395 MakeMapTile(7, 9, 'oBrick');
396 MakeMapTile(8, 9, 'oBrick');
397 MakeMapTile(9, 9, 'oCaveBG2');
398 MakeMapTile(11, 9, 'oCaveBG2');
399 MakeMapTile(12, 9, 'oBrick');
400 MakeMapTile(13, 9, 'oCaveBG2');
401 MakeMapTile(15, 9, 'oCaveBG2');
402 MakeMapTile(17, 9, 'oBrick');
403 MakeMapTile(17, 9, 'oCaveBG2');
404 MakeMapTile(18, 9, 'oBrick');
405 MakeMapTile(19, 9, 'oBrick');
406 MakeMapTile(5, 10, 'oBrick');
407 MakeMapTile(6, 10, 'oBrick');
408 MakeMapTile(18, 10, 'oBrick');
409 MakeMapTile(19, 10, 'oBrick');
410 MakeMapTile(0, 11, 'oDesertTop');
411 MakeMapTile(1, 11, 'oDesertTop');
412 MakeMapTile(2, 11, 'oDesertTop');
413 MakeMapTile(3, 11, 'oDesertTop');
414 MakeMapTile(4, 11, 'oDesertTop');
415 MakeMapTile(5, 11, 'oCaveBG2');
416 MakeMapTile(7, 11, 'oCaveBG2');
417 MakeMapTile(9, 11, 'oCaveBG2');
418 MakeMapTile(11, 11, 'oCaveBG2');
419 MakeMapTile(13, 11, 'oCaveBG2');
420 MakeMapTile(15, 11, 'oCaveBG2');
421 MakeMapTile(17, 11, 'oCaveBG2');
422 MakeMapTile(18, 11, 'oBrick');
423 MakeMapTile(19, 11, 'oBrick');
424 MakeMapTile(0, 12, 'oDesert2');
425 MakeMapTile(1, 12, 'oDesert2');
426 MakeMapTile(2, 12, 'oDesert2');
427 MakeMapTile(3, 12, 'oDesert2');
428 MakeMapTile(4, 12, 'oDesert2');
429 MakeMapTile(5, 12, 'oBrick');
430 MakeMapTile(6, 12, 'oBrick');
431 MakeMapTile(7, 12, 'oBrick');
432 MakeMapTile(8, 12, 'oBrick');
433 MakeMapTile(9, 12, 'oBrick');
434 MakeMapTile(10, 12, 'oBrick');
435 MakeMapTile(11, 12, 'oBrick');
436 MakeMapTile(12, 12, 'oBrick');
437 MakeMapTile(13, 12, 'oBrick');
438 MakeMapTile(14, 12, 'oBrick');
439 MakeMapTile(15, 12, 'oBrick');
440 MakeMapTile(16, 12, 'oBrick');
441 MakeMapTile(18, 12, 'oBrick');
442 MakeMapTile(19, 12, 'oBrick');
443 MakeMapTile(0, 13, 'oDesert');
444 MakeMapTile(1, 13, 'oDesert');
445 MakeMapTile(2, 13, 'oDesert');
446 MakeMapTile(3, 13, 'oDesert');
447 MakeMapTile(4, 13, 'oDesert');
448 MakeMapTile(5, 13, 'oDesert');
449 MakeMapTile(6, 13, 'oBrick');
450 MakeMapTile(7, 13, 'oBrick');
451 MakeMapTile(8, 13, 'oBrick');
452 MakeMapTile(9, 13, 'oBrick');
453 MakeMapTile(10, 13, 'oBrick');
454 MakeMapTile(11, 13, 'oBrick');
455 MakeMapTile(12, 13, 'oBrick');
456 MakeMapTile(13, 13, 'oBrick');
457 MakeMapTile(14, 13, 'oBrick');
458 MakeMapTile(15, 13, 'oBrick');
459 MakeMapTile(16, 13, 'oBrick');
460 MakeMapTile(17, 13, 'oCaveBG2');
461 MakeMapTile(18, 13, 'oBrick');
462 MakeMapTile(19, 13, 'oBrick');
463 MakeMapTile(0, 14, 'oDesert');
464 MakeMapTile(1, 14, 'oDesert');
465 MakeMapTile(2, 14, 'oDesert');
466 MakeMapTile(3, 14, 'oDesert');
467 MakeMapTile(4, 14, 'oDesert');
468 MakeMapTile(5, 14, 'oDesert');
469 MakeMapTile(6, 14, 'oBrick');
470 MakeMapTile(7, 14, 'oBrick');
471 MakeMapTile(8, 14, 'oBrick');
472 MakeMapTile(9, 14, 'oBrick');
473 MakeMapTile(10, 14, 'oBrick');
474 MakeMapTile(11, 14, 'oBrick');
475 MakeMapTile(12, 14, 'oBrick');
476 MakeMapTile(13, 14, 'oBrick');
477 MakeMapTile(14, 14, 'oBrick');
478 MakeMapTile(15, 14, 'oBrick');
479 MakeMapTile(16, 14, 'oBrick');
480 MakeMapTile(18, 14, 'oBrick');
481 MakeMapTile(19, 14, 'oBrick');
483 if (global.randOther(1, 3) > 1) MakeMapTileAtPix(0, 176, 'oShrub');
484 if (global.randOther(1, 3) > 1) MakeMapTileAtPix(32, 176, 'oShrub');
486 if (global.randOther(1, 4) > 1) {
488 do { pty = global.randOther(1, 6); } while (pty == 2);
489 MakeMapTileAtPix(0, 56+pty*8, (pty < 2 ? 'oPalmTree' : 'oPalmTreeFwd'));
492 if (global.randOther(1, 4) > 1) {
494 do { pty = global.randOther(1, 8); } while (pty == 2);
495 MakeMapTileAtPix(32, 56+pty*8, (pty < 2 ? 'oPalmTree' : 'oPalmTreeFwd'));
498 if (global.randOther(1, 4) == 1) {
500 switch (global.randOther(0, 3)) {
501 case 0: xx = 144; break;
502 case 1: xx = 176; break;
503 case 2: xx = 208; break;
504 case 3: xx = 256; break;
506 MakeMapObject(xx, 144, 'oWeb');
509 if (global.randOther(1, 4) > 1) {
511 switch (global.randOther(0, 2)) {
512 case 0: xx = 160; break;
513 case 1: xx = 224; break;
514 case 2: xx = 240; break;
516 MakeMapTileAtPix(xx, 144, 'oLamp');
519 if (global.randOther(1, 5) == 1) MakeMapObject(144+global.randOther(1, 12)*8, 176+12, 'oRock');
520 else if (global.randOther(1, 4) == 1) MakeMapObject(144+global.randOther(1, 12)*8, 176+10, 'oJar');
521 else if (global.randOther(1, 3) == 1) {
522 int n = 144+global.randOther(1, 12)*8;
523 MakeMapObject(n, 176, 'oBones');
524 MakeMapObject(n+12, 176+12, 'oSkull');
527 if (global.randOther(1, 2) == 1) MakeMapTileAtPix(112, 160, 'oBrick');
529 // so the player will not fall away
531 auto supptile = MakeMapTile(1, 11, 'oBrick');
533 supptile.updateGrid();
535 supptile = MakeMapTile(1, 11, 'oBrick');
537 supptile.updateGrid();
540 spawnPlayerAt(-16, 11*16+8);
541 player.dir = MapEntity::Dir.Right;
542 player.flying = true;
543 player.visible = false;