vines and ladders are invincible in the original
[k8vacspelynky.git] / roomIntro.vc
blob2ff9538741e8ebb80c00a3b6ee5197a5046e357c
1 /**********************************************************************************
2  * Copyright (c) 2008, 2009 Derek Yu and Mossmouth, LLC
3  * Copyright (c) 2010, Moloch
4  * Copyright (c) 2018, Ketmar Dark
5  *
6  * This file is part of Spelunky.
7  *
8  * You can redistribute and/or modify Spelunky, including its source code, under
9  * the terms of the Spelunky User License.
10  *
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.
13  *
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/>
17  *
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;
36         break;
37       case 1: // waiting for pay release
38         if (payRelease) titleCutsceneSkip = 2;
39         break;
40       case 2: // pay released, do skip
41         cameFromIntroRoom = false;
42         inIntroCutscene = 0;
43         restartTitle();
44         return;
45     }
46   }
48   if (!plr.visible) return;
50   // in title room
51   if (introPhase == 8) {
52     player.iy = 4;
53     player.visible = true;
54     player.status = MapObject::CLIMBING;
55     MakeMapObject(player.ix, player.y1+1, 'oFlare');
56     ++introPhase;
57   }
59   if (introPhase == 9) {
60     if (plr.status != MapObject::CLIMBING) {
61       plr.kUp = true;
62       return;
63     }
64     ++introPhase;
65   }
67   if (introPhase == 10) {
68     if (plr.iy < 100 || plr.status == MapObject::CLIMBING) {
69       plr.kDown = true;
70       return;
71     }
72     ++introPhase;
73   }
75   if (introPhase == 11) {
76     inIntroCutscene = 0;
77     cameFromIntroRoom = false;
78     ++stats.introViewed;
79     return;
80   }
82   // in intro room
83   if (introPhase == 4) {
84     //plr.kRight = true;
85     if (plr.ix < 262) {
86       plr.kRight = true;
87     }
88     return;
89   }
91   if (introPhase == 5) {
92     plr.kDown = true;
93     if (introPhaseTimer == 2) plr.kRopePressed = true;
94   }
96   if (introPhase == 6) {
97     plr.kDown = true;
98     if (introPhaseTimer > 0) {
99       --introPhaseTimer;
100     } else {
101       //writeln(plr.status);
102       if (plr.status != MapObject::CLIMBING) {
103         plr.kRight = true;
104       } else {
105         if (plr.iy > 280) {
106           plr.visible = false;
107           ++introPhase;
108           introPhaseTimer = 255;
109         }
110       }
111     }
112   }
116 final void renderTitleCutscenePhrase (int phnum, int alpha) {
117   if (phnum > introPhase) return;
118   string ss;
119   switch (phnum) {
120     case 1: ss = introString1; break;
121     case 2: ss = introString2; break;
122     case 3: ss = introString3; break;
123     default: return;
124   }
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) {
134     // in title room
135     return;
136   }
138   if (introPhase == -1) {
139     Video.color = clamp(introPhaseTimer, 0, 255)<<24;
140     Video.fillRect(0, 0, Video.screenWidth, Video.screenHeight);
141   }
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));
147   }
149   if (introPhase == 7) {
150     Video.color = clamp(introPhaseTimer, 0, 255)<<24;
151     Video.fillRect(0, 0, Video.screenWidth, Video.screenHeight);
152   }
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;
166     ++introPhase;
167     introPhaseTimer = 15;
168   }
170   if (introPhase == 0) {
171     if (--introPhaseTimer <= 0) {
172       ++introPhase;
173       introPhaseTimer = 0;
174     }
175     return;
176   }
178   if (introPhase >= 1 && introPhase <= 3) {
179     introPhaseTimer += 3;
180     if (introPhaseTimer >= 255+30*3) {
181       ++introPhase;
182       introPhaseTimer = 0;
183     }
184     return;
185   }
187   if (introPhase == 4) {
188     player.visible = true;
189     if (player.ix < 0) {
190       player.iy = 11*16+8;
191       player.ix = player.ix+1;
192       player.fallTimer = 0;
193       player.status = MapObject::STANDING;
194       if (player.ix < 0) return;
195     }
196     if (player.ix > 200 && player.xVel == 0) {
197       ++introPhase;
198       introPhaseTimer = 30;
199     }
200   }
202   if (introPhase == 5) {
203     if (--introPhaseTimer == 0) {
204       ++introPhase;
205       introPhaseTimer = 10;
206     }
207   }
209   if (introPhase == 7) {
210     introPhaseTimer -= 2;
211     if (introPhaseTimer <= 0) {
212       cameFromIntroRoom = true;
213       restartTitle();
214       ++introPhase;
215       //player.iy = 4;
216       //player.visible = true;
217     }
218   }
222 void createIntroRoom () {
223   clearForTransition();
224   //global.darkLevel = true;
226   inIntroCutscene = 1;
227   introPhase = 0;
228   introPhaseTimer = 30;
229   titleCutsceneSkip = 0;
231   // fade in
232   introPhase = -1;
233   introPhaseTimer = 0;
235   //introPhase = 3;
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;
247   }
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;
258   }
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;
269   }
271   setRoomBounds(0, 0, 304, 224-16);
272   levBGImgName = 'bgCave';
273   //levBGImgName = 'sTitleBG';
274   //levBGImgName = '';
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) {
487     int pty;
488     do { pty = global.randOther(1, 6); } while (pty == 2);
489     MakeMapTileAtPix(0, 56+pty*8, (pty < 2 ? 'oPalmTree' : 'oPalmTreeFwd'));
490   }
492   if (global.randOther(1, 4) > 1) {
493     int pty;
494     do { pty = global.randOther(1, 8); } while (pty == 2);
495     MakeMapTileAtPix(32, 56+pty*8, (pty < 2 ? 'oPalmTree' : 'oPalmTreeFwd'));
496   }
498   if (global.randOther(1, 4) == 1) {
499     int xx;
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;
505     }
506     MakeMapObject(xx, 144, 'oWeb');
507   }
509   if (global.randOther(1, 4) > 1) {
510     int xx;
511     switch (global.randOther(0, 2)) {
512       case 0: xx = 160; break;
513       case 1: xx = 224; break;
514       case 2: xx = 240; break;
515     }
516     MakeMapTileAtPix(xx, 144, 'oLamp');
517   }
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');
525   }
527   if (global.randOther(1, 2) == 1) MakeMapTileAtPix(112, 160, 'oBrick');
529   // so the player will not fall away
530   /*
531   auto supptile = MakeMapTile(1, 11, 'oBrick');
532   supptile.ix = -16;
533   supptile.updateGrid();
535   supptile = MakeMapTile(1, 11, 'oBrick');
536   supptile.ix = -16*2;
537   supptile.updateGrid();
538   */
540   spawnPlayerAt(-16, 11*16+8);
541   player.dir = MapEntity::Dir.Right;
542   player.flying = true;
543   player.visible = false;