4 // Copyright 2007, 2008 Lancer-X/ASCEAI
6 // This file is part of Meritous.
8 // Meritous 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 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. 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: Lancer-X/Asceai",
369 "Sound Effects: Various (public domain) sources",
370 "Music: Various artists",
371 "Beta testing: Quasar",
372 "Beta testing: Terryn",
373 "Beta testing: Wervyn",
374 "\"Ambient Light\" Vogue of Triton",
375 "\"Battle of Ragnarok\" Frostbite",
376 "\"Dragon Cave\" TICAZ",
377 " cavern.xm Unknown",
378 "\"Caverns Boss\" Alexis Janson",
379 "\"Forest Boss\" Alexis Janson",
380 "\"Catacombs Boss\" Alexis Janson",
381 "\"Fear 2\" Mick Rippon",
382 "\"The Final Battle\" Goose/CéDA & iNVASiON",
383 "\"Ice Frontier\" Skaven/FC",
384 "\"KnarkLoader 1.0\" Rapacious",
385 "\"RPG-Battle\" Cyn",
386 "\"Metallic Forest\" Joseph Fox"
391 static SDL_Surface
*fin
= NULL
;
392 static SDL_Surface
*theend
[2] = {NULL
};
397 int n_credits
= sizeof(credits
)/sizeof(*credits
);
400 finish_point
= 400 + (n_credits
* 50);
405 SDL_FillRect(screen
, NULL
, 0);
408 fin
= IMG_Load("dat/i/fin.png");
410 theend
[0] = IMG_Load("dat/i/theend.png");
411 theend
[1] = IMG_Load("dat/i/true_end.png");
414 if (credits_scroll
>= (finish_point
+ 80)) {
415 SDL_BlitSurface(theend
[(player_shield
== 30)], NULL
, screen
, NULL
);
417 SDL_BlitSurface(fin
, NULL
, screen
, &draw_to
);
419 // Show each line of credits
421 for (i
= 0; i
< n_credits
; i
++) {
422 ypos
= 800 + (i
* 100) - credits_scroll
* 2;
424 if ((ypos
>= 0)&&(ypos
< 480)) {
425 c
= 255 - abs(ypos
- 240);
426 draw_text(120, ypos
, credits
[i
], c
);
432 for (i
= 0; i
< 128; i
++) {
435 ending_pal
[i
].b
= i
*2;
437 for (i
= 128; i
< 256; i
++) {
438 ending_pal
[i
].r
= (i
- 128)*2+1;
440 ending_pal
[i
].b
= 255;
443 // Dim palette if we're just starting
445 if (credits_scroll
< 80) {
446 for (i
= 0; i
< 256; i
++) {
447 ending_pal
[i
].r
= ending_pal
[i
].r
* credits_scroll
/ 80;
448 ending_pal
[i
].g
= ending_pal
[i
].g
* credits_scroll
/ 80;
449 ending_pal
[i
].b
= ending_pal
[i
].b
* credits_scroll
/ 80;
453 // Also palette if we're finishing
455 if ((credits_scroll
>= (finish_point
))&&(credits_scroll
< (finish_point
+ 80))) {
456 for (i
= 0; i
< 256; i
++) {
457 ending_pal
[i
].r
= ending_pal
[i
].r
* (finish_point
+80-credits_scroll
) / 80;
458 ending_pal
[i
].g
= ending_pal
[i
].g
* (finish_point
+80-credits_scroll
) / 80;
459 ending_pal
[i
].b
= ending_pal
[i
].b
* (finish_point
+80-credits_scroll
) / 80;
463 if ((credits_scroll
>= (finish_point
+ 80))&&(credits_scroll
< (finish_point
+ 160))) {
464 for (i
= 0; i
< 256; i
++) {
465 ending_pal
[i
].r
= ending_pal
[i
].r
* (credits_scroll
- (finish_point
+ 80)) / 80;
466 ending_pal
[i
].g
= ending_pal
[i
].g
* (credits_scroll
- (finish_point
+ 80)) / 80;
467 ending_pal
[i
].b
= ending_pal
[i
].b
* (credits_scroll
- (finish_point
+ 80)) / 80;
477 void RunParticleStorm(int offset
)
479 SDL_Rect draw_from
, draw_to
;
482 for (i
= 0; i
< 64; i
++) {
483 DrawRect(0, i
* 15 - offset
, 640, 15, 64 - i
);
486 for (i
= 0; i
< 500; i
++) {
495 draw_from
.x
= (rand()%3)*32;
500 draw_to
.x
= (int)pt_x
[i
] - 16;
501 draw_to
.y
= (int)pt_y
[i
] - 16 - offset
;
502 SDL_BlitSurface(glitter
, &draw_from
, screen
, &draw_to
);
505 for (i
= 0; i
< 128; i
++) {
506 ending_pal
[i
].r
= i
*2;
507 ending_pal
[i
].g
= i
*2;
510 for (i
= 128; i
< 256; i
++) {
511 ending_pal
[i
].r
= 255;
512 ending_pal
[i
].g
= 255;
513 ending_pal
[i
].b
= (i
- 128)*2+1;
520 void DrawStream(int t
)
526 SDL_Rect draw_from
, draw_to
;
528 for (i
= 0; i
< 256; i
++) {
530 ending_pal
[i
].g
= (i
* 7 / 8) + 16 + sin( (float)t
/ 8 )*16;
531 ending_pal
[i
].b
= (i
* 3 / 4) + 32 + sin( (float)t
/ 8 )*32;
536 scr_x
= 32 + rand()%32 - rand()%32;
541 scr_y
= (20 - t
* 2);
544 DrawLevel(scr_x
, scr_y
, 0, 0);
545 DrawPlayer(344 - scr_x
, 228 - scr_y
, 0, 0);
547 for (i
= 0; i
< 7; i
++) {
548 strm_scrl
= (t
* 20) % 128;
549 draw_to
.x
= 0 - strm_scrl
- scr_x
+ (128*i
);
550 draw_to
.y
= 19 - scr_y
;
553 draw_to
.y
+= rand()%4;
554 draw_to
.y
-= rand()%4;
556 SDL_BlitSurface(streamspr
, NULL
, screen
, &draw_to
);
560 for (i
= 0; i
< 20; i
++) {
561 draw_from
.x
= (rand()%3)*32;
566 draw_to
.x
= rand()%(640+32)-32;
567 draw_to
.y
= (rand()%(124)) + 3;
569 SDL_BlitSurface(glitter
, &draw_from
, screen
, &draw_to
);
575 SND_CircuitRelease(1000);
577 DrawCircle(320+32 - scr_x
, 240 - scr_y
, (t
- 254) * 10, 255);
578 DrawCircle(320+32 - scr_x
, 240 - scr_y
, (t
- 252) * 10, 225);
579 DrawCircle(320+32 - scr_x
, 240 - scr_y
, (t
- 250) * 10, 195);
587 char *PText
[10] = { "Activating the seal quickly unblocked the ley lines and allowed",
588 "psi to flow through the Dome again. The remaining shadows were",
589 "quickly flushed out.",
591 "Wervyn Anixil's unconventional use of the psi resulted in him",
592 "being burned out and rendered powerless. Merit will see to it",
593 "that he faces judgement for his crimes.",
595 "Neither of the two psi weapons housed within the Dome had been",
596 "touched. However . . ." };
597 char *PTextV
[10] ={ "Activating the seal quickly unblocked the ley lines and allowed",
598 "psi to flow through the Dome again. The remaining shadows were",
599 "quickly flushed out.",
601 "The traitor, who was never identified, perished in the Sealing.",
602 "It soon became clear that the traitor had managed to betray and",
603 "kill the real Wervyn Anixil during his experiments on the psi.",
604 "If the Agate Knife was never found, nobody would have been any",
605 "the wiser, and things could have turned out very differently.",
606 "However, there was one last thing for Merit to do."};
608 void DrawPText(int t
)
615 for (i
= 0; i
< 256; i
++) {
618 ending_pal
[i
].b
= (i
* 3 / 4) + 64;
623 for (i
= 0; i
< 10; i
++) {
624 c
= (255 + (i
* 100) - t
*10);
626 if (c
> 255) c
= 255;
628 if (player_shield
!= 30) {
629 draw_text(68, 180+i
*12, PText
[i
], c
);
631 draw_text(68, 180+i
*12, PTextV
[i
], c
);
635 for (i
= 0; i
< 10; i
++) {
638 if (player_shield
!= 30) {
639 draw_text(68, 180+i
*12, PText
[i
], c
);
641 draw_text(68, 180+i
*12, PTextV
[i
], c
);
646 for (i
= 0; i
< (32 * 8); i
++) {
650 c
= 237 + (i
/32*2) + (rand()% (19 - (i
/32) *2));
651 DrawRect(x
, y
, 20, 20, c
);
652 if(!(i
>138 && i
<148) || (t
< 265 || t
>= 300)) {
653 c
= 237 + (i
/32*2) + (rand()% (19 - (i
/32) *2));
654 DrawRect(x
, 460 - y
, 20, 20, c
);
658 if (t
>= 265 && t
< 300) {
659 DrawRect(220, 380, 200, 20, 255);
661 draw_text(320 - (strlen(enterstr
)*8)/2, 386, enterstr
, 0);
670 void DrawScrolly(int t
)
678 SDL_Rect draw_from
, draw_to
;
685 xp
= 8192 - 320 - 3180 + (t
* 4);
688 xp
= 8192 - 320 + ( (t
-795) * 10);
689 yp
= 795 * 20 - (t
-795)*10;
695 if ((rand() % 10)==9) {
698 for (i
= 0; i
< 256; i
++) {
699 bright
= sin((float)t
/ 10.0) * 0.2 + 0.4;
700 ending_pal
[i
].r
= (i
* bright
+ (256*(1.0-bright
))) * ((float)(all_blue
== 0) * 0.5 + 0.5);
701 ending_pal
[i
].g
= (i
* bright
+ (256*(1.0-bright
))) * ((float)(all_blue
== 0) * 0.5 + 0.5);
702 ending_pal
[i
].b
= i
* bright
+ (256*(1.0-bright
));
704 DrawLevel(xp
, yp
, 0, 0);
706 v_radius
= sin((float)t
/ 10.0)*20 + 100;
708 for (i
= 0; i
< 5; i
++) {
713 DrawCircleEx(x
, y
, r
+2, r
-4, 128);
714 DrawCircleEx(x
, y
, r
, r
-2, 255);
717 for (i
= 0; i
< 4; i
++) {
718 draw_from
.x
= (8 + i
) * 32;
723 a_dir
= ((float)t
/ 10.0) + (M_PI
*(float)i
/2);
725 for (j
= 10; j
>= 0; j
--) {
726 DrawCircleEx(320+cos(a_dir
)*v_radius
, 240+sin(a_dir
)*v_radius
, 22 + j
* 2, 0, abs(j
-3) * 15);
728 DrawCircleEx(320+cos(a_dir
)*v_radius
, 240+sin(a_dir
)*v_radius
, 20, 0, 0);
730 draw_to
.x
= 320 + cos(a_dir
) * v_radius
- 16;
731 draw_to
.y
= 240 + sin(a_dir
) * v_radius
- 16;
732 SDL_BlitSurface(artifact_spr
, &draw_from
, screen
, &draw_to
);
739 void DrawCircuitFlash(int t
, int method
)
741 static SDL_Surface
*circ
= NULL
;
742 static int xpos
, ypos
;
747 circ
= IMG_Load("dat/i/circuits_1.png");
765 SDL_BlitSurface(circ
, &from
, screen
, NULL
);
767 for (i
= 0; i
< 256; i
++) {
777 if (j
> 255) j
= 255;