4 // Copyright 2007, 2008 Lancer-X/ASCEAI
6 // This file is part of Meritous Recharged.
8 // Meritous Recharged is free software: you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation, either version 3 of the License, or
11 // (at your option) any later version.
13 // Meritous Recharged is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU General Public License for more details.
18 // You should have received a copy of the GNU General Public License
19 // along with Meritous Recharged. If not, see <http://www.gnu.org/licenses/>.
26 #include <SDL_image.h>
29 #include "levelblit.h"
34 void DrawScrolly(int t
);
35 void DrawPText(int t
);
36 void DrawSText(int t
);
37 void DrawSTextV(int t
);
38 void DrawCircuitFlash(int t
, int method
);
39 void DrawStream(int t
);
41 void InitParticleStorm();
42 void RunParticleStorm(int offset
);
44 SDL_Surface
*streamspr
= NULL
, *glitter
= NULL
;
46 SDL_Color ending_pal
[256];
50 SDL_SetPalette(screen
, SDL_PHYSPAL
, ending_pal
, 0, 256);
55 int credits_scroll
= 0;
59 static SDL_Event event
;
67 while (SDL_PollEvent(&event
)) {
68 if (event
.type
== SDL_KEYDOWN
) {
69 switch (event
.key
.keysym
.sym
) {
78 if (event
.type
== SDL_JOYBUTTONDOWN
) {
79 switch (event
.jbutton
.button
) {
88 if (event
.type
== SDL_QUIT
) {
100 if (streamspr
== NULL
) {
101 streamspr
= IMG_Load("dat/i/stream.png");
102 SDL_SetColorKey(streamspr
, SDL_SRCCOLORKEY
| SDL_RLEACCEL
, 0);
103 glitter
= IMG_Load("dat/i/glitter.png");
104 SDL_SetColorKey(glitter
, SDL_SRCCOLORKEY
| SDL_RLEACCEL
, 0);
107 for (i
= 0; i
< 500; i
+= 1) {
108 if (((i
% 60) >= 24)&&((i
% 60) < 34)) {
109 DrawCircuitFlash((i
% 60) - 24, 0);
114 if (EndingEvents()==1) return;
116 for (i
= 0; i
< 30; i
++) {
117 DrawCircuitFlash(i
, 1);
120 if (EndingEvents()==1) return;
122 SDL_FillRect(screen
, NULL
, 255);
130 event_type
= EndingEvents();
131 if (event_type
== 1) return;
132 if (event_type
== 2) break;
134 for (i
=300; i
<350; i
++) {
137 if (EndingEvents()) return;
140 Paint(0, 0, 22, 27, "dat/d/cstream.loc");
142 if (player_shield
< 30) {
143 for (i
= 0; i
< 400; i
++) {
146 if (EndingEvents()==1) return;
149 for (i
= 0; i
< 240; i
++) {
150 RunParticleStorm(240-i
);
152 if (EndingEvents()==1) return;
154 for (i
= 0; i
< 60; i
++) {
157 if (EndingEvents()==1) return;
159 for (i
= 0; i
< 180; i
++) {
160 RunParticleStorm(i
*3);
162 if (EndingEvents()==1) return;
170 event_type
= EndingEvents();
171 if (event_type
== 1) return;
172 if (event_type
== 2) break;
174 for (i
=400; i
<500; i
++) {
177 if (EndingEvents()==1) return;
180 for (i
= 0; i
< 250; i
++) {
183 if (EndingEvents()==1) return;
191 event_type
= EndingEvents();
192 if (event_type
== 1) return;
193 if (event_type
== 2) break;
195 for (i
=400; i
<500; i
++) {
198 if (EndingEvents()==1) return;
206 if (EndingEvents()==1) return;
210 char *SText
[15] = { "Merit released the locks on the psi flowing through the Dome,",
211 "releasing the flow of psi into the atmosphere.",
213 "The Orcus Dome was originally built to centralise the limited",
214 "psi available to everyone. However, this made the existing",
215 "reserves more vulnerable to malicious psi users",
217 "While other psi users initially resented Merit for his rash",
218 "behaviour, they eventually adjusted to the decentralisation.",
220 "Eventually, psi users grew so adept at manipulating the",
221 "diluted flows of psi that they were capable of the same things",
222 "as before. Each psi user would keep their own individual",
223 "reserves of psi for when they needed to weild greater power,",
224 "and the balance of power was restored." };
226 char *STextV
[15] = {"Merit decided to assume the role of custodian over the Orcus",
227 "Dome, in Wervyn Anixil's place. He resumed the experiments on",
228 "psi and found ways of making the Dome's remaining supply go as",
231 "Other psi users were suspicious of Merit, just as they were",
232 "wary of Wervyn Anixil before him, but they soon adjusted.",
234 "The balance of power was quickly restored, and stabilised for",
235 "eternity due to the work of Wervyn Anixil and now Merit.",
238 " [[ BEST ENDING ]]",
242 char* enterstr
= "Press [Enter]";
244 void DrawSText(int t
)
248 offset
= 540 + (t
/ 2);
261 for (i
= 0; i
< 64; i
++) {
262 DrawRect(0, i
* 15 - offset
, 640, 15, (64 - i
) * cl
/ 350);
264 for (i
= 64; i
< 128; i
++) {
265 DrawRect(0, i
* 15 - offset
, 640, 15, (i
- 64) * cl
/ 350);
269 for (i
= 0; i
< 15; i
++) {
270 c
= (255 + (i
* 100) - t
*10);
272 if (c
> 255) c
= 255;
274 draw_text(68, 150+i
*12, SText
[i
], 255-c
);
277 for (i
= 0; i
< 15; i
++) {
280 draw_text(68, 150+i
*12, SText
[i
], 255-c
);
285 if (t
>= 245 && t
< 280) {
287 draw_text(320 - (strlen(enterstr
)*8)/2, 386, enterstr
, 255);
294 void DrawSTextV(int t
)
298 offset
= 540 + (t
/ 2);
311 for (i
= 0; i
< 64; i
++) {
312 DrawRect(0, i
* 15 - offset
, 640, 15, (64 - i
) * cl
/ 350);
314 for (i
= 64; i
< 128; i
++) {
315 DrawRect(0, i
* 15 - offset
, 640, 15, (i
- 64) * cl
/ 350);
319 for (i
= 0; i
< 15; i
++) {
320 c
= (255 + (i
* 100) - t
*10);
322 if (c
> 255) c
= 255;
324 draw_text(68, 150+i
*12, STextV
[i
], 255-c
);
327 for (i
= 0; i
< 15; i
++) {
330 draw_text(68, 150+i
*12, STextV
[i
], 255-c
);
334 if (t
>= 245 && t
< 280) {
336 draw_text(320 - (strlen(enterstr
)*8)/2, 386, enterstr
, 255);
351 void InitParticleStorm()
355 for (i
= 0; i
< 500; i
++) {
358 pt_vx
[i
] = (float)(rand()%101) / 33.333 - 1.5;
359 pt_vy
[i
] = (float)(rand()%101) / 10.0 - 16.1;
360 pt_t
[i
] = rand()%100;
365 "Concept: Lancer-X/Asceai",
366 "Game design: Lancer-X/Asceai",
367 "Graphics: Lancer-X/Asceai",
368 "Programming (until v1.2): Lancer-X/Asceai",
369 "Programming (since v1.3): Wuzzy",
370 "Sound Effects: Various (public domain) sources",
371 "Music: Various artists",
372 "Beta testing: Quasar",
373 "Beta testing: Terryn",
374 "Beta testing: Wervyn",
375 "\"Ambient Light\" Vogue of Triton",
376 "\"Battle of Ragnarok\" Frostbite",
377 "\"Dragon Cave\" TICAZ",
378 " cavern.xm Unknown",
379 "\"Caverns Boss\" Alexis Janson",
380 "\"Forest Boss\" Alexis Janson",
381 "\"Catacombs Boss\" Alexis Janson",
382 "\"Fear 2\" Mick Rippon",
383 "\"The Final Battle\" Goose/CéDA & iNVASiON",
384 "\"Ice Frontier\" Skaven/FC",
385 "\"KnarkLoader 1.0\" Rapacious",
386 "\"RPG-Battle\" Cyn",
387 "\"Metallic Forest\" Joseph Fox"
392 static SDL_Surface
*fin
= NULL
;
393 static SDL_Surface
*theend
[2] = {NULL
};
398 int n_credits
= sizeof(credits
)/sizeof(*credits
);
401 finish_point
= 400 + (n_credits
* 50);
406 SDL_FillRect(screen
, NULL
, 0);
409 fin
= IMG_Load("dat/i/fin.png");
411 theend
[0] = IMG_Load("dat/i/theend.png");
412 theend
[1] = IMG_Load("dat/i/true_end.png");
415 if (credits_scroll
>= (finish_point
+ 80)) {
416 SDL_BlitSurface(theend
[(player_shield
== 30)], NULL
, screen
, NULL
);
418 SDL_BlitSurface(fin
, NULL
, screen
, &draw_to
);
420 // Show each line of credits
422 for (i
= 0; i
< n_credits
; i
++) {
423 ypos
= 800 + (i
* 100) - credits_scroll
* 2;
425 if ((ypos
>= 0)&&(ypos
< 480)) {
426 c
= 255 - abs(ypos
- 240);
427 draw_text(120, ypos
, credits
[i
], c
);
433 for (i
= 0; i
< 128; i
++) {
436 ending_pal
[i
].b
= i
*2;
438 for (i
= 128; i
< 256; i
++) {
439 ending_pal
[i
].r
= (i
- 128)*2+1;
441 ending_pal
[i
].b
= 255;
444 // Dim palette if we're just starting
446 if (credits_scroll
< 80) {
447 for (i
= 0; i
< 256; i
++) {
448 ending_pal
[i
].r
= ending_pal
[i
].r
* credits_scroll
/ 80;
449 ending_pal
[i
].g
= ending_pal
[i
].g
* credits_scroll
/ 80;
450 ending_pal
[i
].b
= ending_pal
[i
].b
* credits_scroll
/ 80;
454 // Also palette if we're finishing
456 if ((credits_scroll
>= (finish_point
))&&(credits_scroll
< (finish_point
+ 80))) {
457 for (i
= 0; i
< 256; i
++) {
458 ending_pal
[i
].r
= ending_pal
[i
].r
* (finish_point
+80-credits_scroll
) / 80;
459 ending_pal
[i
].g
= ending_pal
[i
].g
* (finish_point
+80-credits_scroll
) / 80;
460 ending_pal
[i
].b
= ending_pal
[i
].b
* (finish_point
+80-credits_scroll
) / 80;
464 if ((credits_scroll
>= (finish_point
+ 80))&&(credits_scroll
< (finish_point
+ 160))) {
465 for (i
= 0; i
< 256; i
++) {
466 ending_pal
[i
].r
= ending_pal
[i
].r
* (credits_scroll
- (finish_point
+ 80)) / 80;
467 ending_pal
[i
].g
= ending_pal
[i
].g
* (credits_scroll
- (finish_point
+ 80)) / 80;
468 ending_pal
[i
].b
= ending_pal
[i
].b
* (credits_scroll
- (finish_point
+ 80)) / 80;
478 void RunParticleStorm(int offset
)
480 SDL_Rect draw_from
, draw_to
;
483 for (i
= 0; i
< 64; i
++) {
484 DrawRect(0, i
* 15 - offset
, 640, 15, 64 - i
);
487 for (i
= 0; i
< 500; i
++) {
496 draw_from
.x
= (rand()%3)*32;
501 draw_to
.x
= (int)pt_x
[i
] - 16;
502 draw_to
.y
= (int)pt_y
[i
] - 16 - offset
;
503 SDL_BlitSurface(glitter
, &draw_from
, screen
, &draw_to
);
506 for (i
= 0; i
< 128; i
++) {
507 ending_pal
[i
].r
= i
*2;
508 ending_pal
[i
].g
= i
*2;
511 for (i
= 128; i
< 256; i
++) {
512 ending_pal
[i
].r
= 255;
513 ending_pal
[i
].g
= 255;
514 ending_pal
[i
].b
= (i
- 128)*2+1;
521 void DrawStream(int t
)
527 SDL_Rect draw_from
, draw_to
;
529 for (i
= 0; i
< 256; i
++) {
531 ending_pal
[i
].g
= (i
* 7 / 8) + 16 + sin( (float)t
/ 8 )*16;
532 ending_pal
[i
].b
= (i
* 3 / 4) + 32 + sin( (float)t
/ 8 )*32;
537 scr_x
= 32 + rand()%32 - rand()%32;
542 scr_y
= (20 - t
* 2);
545 DrawLevel(scr_x
, scr_y
, 0, 0);
546 DrawPlayer(344 - scr_x
, 228 - scr_y
, 0, 0);
548 for (i
= 0; i
< 7; i
++) {
549 strm_scrl
= (t
* 20) % 128;
550 draw_to
.x
= 0 - strm_scrl
- scr_x
+ (128*i
);
551 draw_to
.y
= 19 - scr_y
;
554 draw_to
.y
+= rand()%4;
555 draw_to
.y
-= rand()%4;
557 SDL_BlitSurface(streamspr
, NULL
, screen
, &draw_to
);
561 for (i
= 0; i
< 20; i
++) {
562 draw_from
.x
= (rand()%3)*32;
567 draw_to
.x
= rand()%(640+32)-32;
568 draw_to
.y
= (rand()%(124)) + 3;
570 SDL_BlitSurface(glitter
, &draw_from
, screen
, &draw_to
);
576 SND_CircuitRelease(1000);
578 DrawCircle(320+32 - scr_x
, 240 - scr_y
, (t
- 254) * 10, 255);
579 DrawCircle(320+32 - scr_x
, 240 - scr_y
, (t
- 252) * 10, 225);
580 DrawCircle(320+32 - scr_x
, 240 - scr_y
, (t
- 250) * 10, 195);
588 char *PText
[10] = { "Activating the seal quickly unblocked the ley lines and allowed",
589 "psi to flow through the Dome again. The remaining shadows were",
590 "quickly flushed out.",
592 "Wervyn Anixil's unconventional use of the psi resulted in him",
593 "being burned out and rendered powerless. Merit will see to it",
594 "that he faces judgement for his crimes.",
596 "Neither of the two psi weapons housed within the Dome had been",
597 "touched. However . . ." };
598 char *PTextV
[10] ={ "Activating the seal quickly unblocked the ley lines and allowed",
599 "psi to flow through the Dome again. The remaining shadows were",
600 "quickly flushed out.",
602 "The traitor, who was never identified, perished in the Sealing.",
603 "It soon became clear that the traitor had managed to betray and",
604 "kill the real Wervyn Anixil during his experiments on the psi.",
605 "If the Agate Knife was never found, nobody would have been any",
606 "the wiser, and things could have turned out very differently.",
607 "However, there was one last thing for Merit to do."};
609 void DrawPText(int t
)
616 for (i
= 0; i
< 256; i
++) {
619 ending_pal
[i
].b
= (i
* 3 / 4) + 64;
624 for (i
= 0; i
< 10; i
++) {
625 c
= (255 + (i
* 100) - t
*10);
627 if (c
> 255) c
= 255;
629 if (player_shield
!= 30) {
630 draw_text(68, 180+i
*12, PText
[i
], c
);
632 draw_text(68, 180+i
*12, PTextV
[i
], c
);
636 for (i
= 0; i
< 10; i
++) {
639 if (player_shield
!= 30) {
640 draw_text(68, 180+i
*12, PText
[i
], c
);
642 draw_text(68, 180+i
*12, PTextV
[i
], c
);
647 for (i
= 0; i
< (32 * 8); i
++) {
651 c
= 237 + (i
/32*2) + (rand()% (19 - (i
/32) *2));
652 DrawRect(x
, y
, 20, 20, c
);
653 if(!(i
>138 && i
<148) || (t
< 265 || t
>= 300)) {
654 c
= 237 + (i
/32*2) + (rand()% (19 - (i
/32) *2));
655 DrawRect(x
, 460 - y
, 20, 20, c
);
659 if (t
>= 265 && t
< 300) {
660 DrawRect(220, 380, 200, 20, 255);
662 draw_text(320 - (strlen(enterstr
)*8)/2, 386, enterstr
, 0);
671 void DrawScrolly(int t
)
679 SDL_Rect draw_from
, draw_to
;
686 xp
= 8192 - 320 - 3180 + (t
* 4);
689 xp
= 8192 - 320 + ( (t
-795) * 10);
690 yp
= 795 * 20 - (t
-795)*10;
696 if ((rand() % 10)==9) {
699 for (i
= 0; i
< 256; i
++) {
700 bright
= sin((float)t
/ 10.0) * 0.2 + 0.4;
701 ending_pal
[i
].r
= (i
* bright
+ (256*(1.0-bright
))) * ((float)(all_blue
== 0) * 0.5 + 0.5);
702 ending_pal
[i
].g
= (i
* bright
+ (256*(1.0-bright
))) * ((float)(all_blue
== 0) * 0.5 + 0.5);
703 ending_pal
[i
].b
= i
* bright
+ (256*(1.0-bright
));
705 DrawLevel(xp
, yp
, 0, 0);
707 v_radius
= sin((float)t
/ 10.0)*20 + 100;
709 for (i
= 0; i
< 5; i
++) {
714 DrawCircleEx(x
, y
, r
+2, r
-4, 128);
715 DrawCircleEx(x
, y
, r
, r
-2, 255);
718 for (i
= 0; i
< 4; i
++) {
719 draw_from
.x
= (8 + i
) * 32;
724 a_dir
= ((float)t
/ 10.0) + (M_PI
*(float)i
/2);
726 for (j
= 10; j
>= 0; j
--) {
727 DrawCircleEx(320+cos(a_dir
)*v_radius
, 240+sin(a_dir
)*v_radius
, 22 + j
* 2, 0, abs(j
-3) * 15);
729 DrawCircleEx(320+cos(a_dir
)*v_radius
, 240+sin(a_dir
)*v_radius
, 20, 0, 0);
731 draw_to
.x
= 320 + cos(a_dir
) * v_radius
- 16;
732 draw_to
.y
= 240 + sin(a_dir
) * v_radius
- 16;
733 SDL_BlitSurface(artifact_spr
, &draw_from
, screen
, &draw_to
);
740 void DrawCircuitFlash(int t
, int method
)
742 static SDL_Surface
*circ
= NULL
;
743 static int xpos
, ypos
;
748 circ
= IMG_Load("dat/i/circuits_1.png");
766 SDL_BlitSurface(circ
, &from
, screen
, NULL
);
768 for (i
= 0; i
< 256; i
++) {
778 if (j
> 255) j
= 255;