DEADSOFTWARE

ppc: fix saves and more map loading improvements
[flatwaifu.git] / src / game.c
1 /*
2 Copyright (C) Prikol Software 1996-1997
3 Copyright (C) Aleksey Volynskov 1996-1997
4 Copyright (C) <ARembo@gmail.com> 2011
6 This file is part of the Doom2D:Rembo project.
8 Doom2D:Rembo is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License version 2 as
10 published by the Free Software Foundation.
12 Doom2D:Rembo is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, see <http://www.gnu.org/licenses/> or
19 write to the Free Software Foundation, Inc.,
20 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 */
23 #include "glob.h"
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include "files.h"
28 #include "memory.h"
29 #include "vga.h"
30 #include "keyb.h"
31 #include "sound.h"
32 #include "view.h"
33 #include "bmap.h"
34 #include "fx.h"
35 #include "switch.h"
36 #include "weapons.h"
37 #include "items.h"
38 #include "dots.h"
39 #include "smoke.h"
40 #include "player.h"
41 #include "monster.h"
42 #include "menu.h"
43 #include "misc.h"
44 #include "map.h"
46 #include <SDL_keysym.h>
48 #define LT_DELAY 8
49 #define LT_HITTIME 6
51 #define GETIME 1092
54 int A8_start(char*);
55 int A8_nextframe(void);
56 void A8_close(void);
59 void FX_trans1(int t);
60 extern unsigned char fx_scr1[64000],fx_scr2[64000];
62 extern short lastkey;
65 extern int hit_xv,hit_yv;
67 extern vgapal std_pal;
68 void setgamma(int);
70 extern int sw_secrets;
72 #define PL_FLASH 90
74 extern int PL_JUMP;
76 extern map_block_t blk;
78 extern byte clrmap[256*12];
80 extern byte cheat;
82 byte _2pl=0,g_dm=0,g_st=GS_TITLE,g_exit=0,g_map=1,_warp=0,g_music[8]="MENU";
83 byte _net=0;
84 int g_sttm=1092;
85 dword g_time;
86 int dm_pnum,dm_pl1p,dm_pl2p;
87 pos_t dm_pos[100];
89 static void *telepsnd;
90 static void *scrnh[3];
91 void *cd_scr;
93 extern int sky_type;
94 void *ltn[2][2];
95 int lt_time,lt_type,lt_side,lt_ypos,lt_force;
96 void *ltnsnd[2];
98 int g_trans=0,g_transt;
100 static void set_trans(int st) {
101 switch(g_st) {
102 case GS_ENDANIM: case GS_END2ANIM: case GS_DARKEN:
103 case GS_BVIDEO: case GS_EVIDEO: case GS_END3ANIM:
104 g_st=st;return;
106 switch(g_st=st) {
107 case GS_ENDANIM: case GS_END2ANIM: case GS_DARKEN:
108 case GS_BVIDEO: case GS_EVIDEO: case GS_END3ANIM:
109 return;
111 g_trans=1;g_transt=0;
114 void G_savegame(FILE* h) {
115 myfwrite8(_2pl, h);
116 myfwrite8(g_dm, h);
117 myfwrite8(g_exit, h);
118 myfwrite8(g_map, h);
119 myfwrite32(g_time, h);
120 myfwrite32(dm_pl1p, h);
121 myfwrite32(dm_pl2p, h);
122 myfwrite32(dm_pnum, h);
123 int i = 0;
124 while (i < dm_pnum) {
125 myfwrite32(dm_pos[i].x, h);
126 myfwrite32(dm_pos[i].y, h);
127 myfwrite8(dm_pos[i].d, h);
128 i += 1;
130 myfwrite8(cheat, h);
131 myfwrite(g_music, 8, 1, h);
134 void G_loadgame(FILE* h) {
135 myfread8(&_2pl, h);
136 myfread8(&g_dm, h);
137 myfread8(&g_exit, h);
138 myfread8(&g_map, h);
139 myfread32(&g_time, h);
140 myfread32(&dm_pl1p, h);
141 myfread32(&dm_pl2p, h);
142 myfread32(&dm_pnum, h);
143 int i = 0;
144 while (i < dm_pnum) {
145 myfread32(&dm_pos[i].x, h);
146 myfread32(&dm_pos[i].y, h);
147 myfread8(&dm_pos[i].d, h);
148 i += 1;
150 myfread8(&cheat, h);
151 myfread(g_music, 8, 1, h);
152 F_loadmus(g_music);
155 int G_load (FILE *h) {
156 switch (blk.t) {
157 case MB_MUSIC:
158 myfread(g_music, 8, 1, h);
159 if (music_random) {
160 F_randmus(g_music);
162 F_loadmus(g_music);
163 return 1;
165 return 0;
168 void load_game(int n) {
169 F_freemus();
170 W_init();
171 F_loadgame(n);
172 set_trans(GS_GAME);
173 V_setscr((g_trans)?fx_scr2:scrbuf);V_setrect(0,SCRW,0,SCRH);//V_setrect(0,320,0,200);
174 V_clr(0,SCRW,0,SCRH,0);//V_clr(0,320,0,200,0);
175 if(_2pl) {w_o=0;Z_clrst();w_o=SCRH/2;Z_clrst();}//if(_2pl) {w_o=0;Z_clrst();w_o=100;Z_clrst();}
176 else {w_o=0;Z_clrst();}//else {w_o=50;Z_clrst();}
177 V_setscr(scrbuf);
178 pl1.drawst=0xFF;
179 if(_2pl) pl2.drawst=0xFF;
180 BM_remapfld();
181 BM_clear(BM_PLR1|BM_PLR2|BM_MONSTER);
182 BM_mark(&pl1.o,BM_PLR1);
183 if(_2pl) BM_mark(&pl2.o,BM_PLR2);
184 MN_mark();
185 S_startmusic(music_time);
188 void G_start(void) {
189 char s[8];
191 F_freemus();
192 sprintf(s,"MAP%02u",(word)g_map);
193 F_loadmap(s);
194 set_trans(GS_GAME);
195 V_setscr((g_trans)?fx_scr2:scrbuf);V_setrect(0,SCRW,0,SCRH);//V_setrect(0,320,0,200);
196 V_clr(0,SCRW,0,SCRH,0);//V_clr(0,320,0,200,0);
197 if(_2pl) {w_o=0;Z_clrst();w_o=SCRH/2;Z_clrst();}//if(_2pl) {w_o=0;Z_clrst();w_o=100;Z_clrst();}
198 else {w_o=0;Z_clrst();}//else {w_o=50;Z_clrst();}
199 V_setscr(scrbuf);
200 pl1.drawst=0xFF;
201 if(_2pl) pl2.drawst=0xFF;
202 g_exit=0;
203 itm_rtime=(g_dm)?1092:0;
204 p_immortal=0;PL_JUMP=10;
205 g_time=0;
206 lt_time=1000;
207 lt_force=1;
208 if(!_2pl) pl1.lives=3;
209 BM_remapfld();
210 BM_clear(BM_PLR1|BM_PLR2|BM_MONSTER);
211 BM_mark(&pl1.o,BM_PLR1);
212 if(_2pl) BM_mark(&pl2.o,BM_PLR2);
213 MN_mark();
214 S_startmusic(music_time);
217 #define GGAS_TOTAL (MN__LAST-MN_DEMON+16+10)
219 void G_init(void) {
220 int i,j;
221 char s[9];
223 logo("G_init: настройка ресурсов игры ");
224 logo_gas(5,GGAS_TOTAL);
225 telepsnd=Z_getsnd("TELEPT");
226 scrnh[0]=V_loadvgaimg("TITLEPIC");
227 scrnh[1]=V_loadvgaimg("INTERPIC");
228 scrnh[2]=V_loadvgaimg("ENDPIC");
229 cd_scr=V_loadvgaimg("CD1PIC");
230 for(i=0;i<2;++i) {
231 sprintf(s,"LTN%c",i+'1');
232 for(j=0;j<2;++j)
233 ltn[i][j]=Z_getspr(s,j,0,NULL);
235 ltnsnd[0]=Z_getsnd("THUND1");
236 ltnsnd[1]=Z_getsnd("THUND2");
237 DOT_alloc();
238 SMK_alloc();
239 FX_alloc();
240 WP_alloc();
241 IT_alloc();
242 SW_alloc();
243 PL_alloc();
244 MN_alloc();
245 Z_initst();
246 logo_gas(GGAS_TOTAL,GGAS_TOTAL);
247 logo("\n");
248 GM_init();
249 pl1.color=0x70;
250 pl2.color=0x60;
251 g_trans=0;
254 int G_beg_video(void) {
255 /*
256 switch(g_map) {
257 case 3: return A8_start("FALL");
258 case 4: return A8_start("KORIDOR");
259 case 5: return A8_start("SKULL");
260 case 6: return A8_start("TORCHES");
261 case 7: return A8_start("CACO");
262 case 8: return A8_start("DARTS");
263 case 9: return A8_start("FISH");
264 case 10: return A8_start("TRAP");
265 case 11: return A8_start("JAIL");
266 case 12: return A8_start("MMON1");
267 case 13: return A8_start("TOWER");
268 case 14: return A8_start("SAPOG");
269 case 15: return A8_start("SWITCH");
270 case 16: return A8_start("ACCEL");
271 case 17: return A8_start("MEAT");
272 case 18: return A8_start("LEGION");
273 case 19: return A8_start("CLOUDS");
275 */
276 return 0;
280 int G_end_video(void) {
281 /*
282 switch(g_map) {
283 case 1: return A8_start("TRUBA");
284 case 10: return A8_start("GOTCHA");
286 */
287 return 0;
291 static byte transdraw=0;
293 void G_act(void) {
294 static byte pcnt=0;
295 /*
296 if(g_trans) {
297 if(g_transt==0) {
298 V_setscr(NULL);memcpy(fx_scr1,scra,64000);
299 V_setscr(fx_scr2);
300 transdraw=1;G_draw();transdraw=0;
301 V_setscr(scrbuf);
303 FX_trans1(g_transt*2);
304 V_copytoscr(0,320,0,200);
305 if(++g_transt>32) {
306 g_trans=0;
308 return;
309 g_trans=0;
311 */ g_trans=0;
314 if(g_st==GS_BVIDEO || g_st==GS_EVIDEO) {
315 if(!A8_nextframe() || lastkey==SDLK_ESCAPE) {
316 if(lastkey==SDLK_ESCAPE) lastkey=0;
317 A8_close();
318 if(g_st==GS_BVIDEO) G_start();
319 else goto inter;
321 V_copytoscr(0,SCRW,0,SCRH);//V_copytoscr(0,320,0,200);
322 return;
323 }else if(g_st==GS_ENDANIM || g_st==GS_END2ANIM || g_st==GS_END3ANIM) {
324 if(!A8_nextframe()) {
325 switch(g_st) {
326 case GS_ENDANIM: g_st=GS_DARKEN;break;
327 case GS_END2ANIM: g_st=GS_END3ANIM;A8_start("KONEC");break;
328 case GS_END3ANIM: g_st=GS_ENDSCR;lastkey=0;break;
329 }g_sttm=0;return;
331 V_copytoscr(0,SCRW,0,SCRH);//V_copytoscr(0,320,0,200);
332 return;
333 }else if(g_st==GS_DARKEN) {
334 g_st=GS_END2ANIM;A8_start("CREDITS");
335 return;
338 if(GM_act()) return;
342 switch(g_st) {
343 case GS_TITLE: case GS_ENDSCR:
345 return;
346 case GS_INTER:
347 #ifdef DEMO
348 if(keys[0x39] || keys[0x1C] || keys[0x9C]) {
349 set_trans(GS_TITLE);
351 #else
352 if(keys[SDLK_SPACE] || keys[SDLK_RETURN] || keys[SDLK_KP_ENTER])//if(keys[0x39] || keys[0x1C] || keys[0x9C])
353 if(!G_beg_video()) G_start(); else {
354 g_st=GS_BVIDEO;F_freemus();
356 #endif
357 return;
361 if(sky_type==2) {
362 if(lt_time>LT_DELAY || lt_force) {
363 if(!(rand()&31) || lt_force) {
364 lt_force=0;
365 lt_time=-LT_HITTIME;
366 lt_type=rand()%2;
367 lt_side=rand()&1;
368 lt_ypos=rand()&31;
369 Z_sound(ltnsnd[rand()&1],128);
371 }else ++lt_time;
373 ++g_time;
374 pl1.hit=0;pl1.hito=-3;
375 if(_2pl) {pl2.hit=0;pl2.hito=-3;}
376 G_code();
378 W_act();
379 IT_act();
380 SW_act();
381 if(_2pl) {
382 if(pcnt) {PL_act(&pl1);PL_act(&pl2);}
383 else {PL_act(&pl2);PL_act(&pl1);}
384 pcnt^=1;
385 }else PL_act(&pl1);
386 MN_act();
387 if(fld_need_remap) BM_remapfld();
388 BM_clear(BM_PLR1|BM_PLR2|BM_MONSTER);
389 BM_mark(&pl1.o,BM_PLR1);
390 if(_2pl) BM_mark(&pl2.o,BM_PLR2);
391 MN_mark();
392 WP_act();
393 DOT_act();
394 SMK_act();
395 FX_act();
396 if(_2pl) {
397 PL_damage(&pl1);PL_damage(&pl2);
398 if(!(pl1.f&PLF_PNSND) && pl1.pain) PL_cry(&pl1);
399 if(!(pl2.f&PLF_PNSND) && pl2.pain) PL_cry(&pl2);
400 if((pl1.pain-=5) < 0) {pl1.pain=0;pl1.f&=(0xFFFF-PLF_PNSND);}
401 if((pl2.pain-=5) < 0) {pl2.pain=0;pl2.f&=(0xFFFF-PLF_PNSND);}
402 }else{
403 PL_damage(&pl1);
404 if(!(pl1.f&PLF_PNSND) && pl1.pain) PL_cry(&pl1);
405 if((pl1.pain-=5) < 0) {pl1.pain=0;pl1.f&=(0xFFFF-PLF_PNSND);}
407 if(g_exit==1) {
409 if(G_end_video()) {
410 F_freemus();
411 g_st=GS_EVIDEO;
412 return;
415 inter:
416 switch(g_map) {
417 case 19: g_st=GS_ENDANIM;A8_start("FINAL");break;
418 case 31: case 32: g_map=16;set_trans(GS_INTER);break;
419 default: ++g_map;set_trans(GS_INTER);break;
421 F_freemus();
422 if(g_st==GS_INTER) {
423 F_loadmus("INTERMUS");
424 }else {F_loadmus("\x8a\x8e\x8d\x85\x96\x0");if(mus_vol>0) {S_volumemusic(128);} }
425 S_startmusic(0);
426 }else if(g_exit==2) {
427 switch(g_map) {
428 case 31: g_map=32;set_trans(GS_INTER);break;
429 case 32: g_map=16;set_trans(GS_INTER);break;
430 default: g_map=31;set_trans(GS_INTER);break;
432 F_freemus();
433 F_loadmus("INTERMUS");
434 S_startmusic(0);
437 #ifdef DEMO
438 if(g_dm && g_time>10920) {set_trans(GS_INTER);}
439 #endif
442 /*
443 static void drawview(player_t *p) {
444 if(p->looky<-50) p->looky=-50;
445 else if(p->looky>50) p->looky=50;
446 w_x=p->o.x;w_y=p->o.y-12+p->looky;W_draw();PL_drawst(p);
448 */
449 static void drawview(player_t *p) {
450 if(p->looky<-SCRH/4) p->looky=-SCRH/4;
451 else if(p->looky>SCRH/4) p->looky=SCRH/4;
452 w_x=p->o.x;w_y=p->o.y-12+p->looky;
453 W_draw();
454 PL_drawst(p);
457 static int get_pu_st(int t) {
458 if(t>=PL_FLASH) return 1;
459 if((t/9)&1) return 0;
460 return 1;
463 static void pl_info(player_t *p,int y) {
464 dword t;
466 t=p->kills*10920/g_time;
467 Z_gotoxy(25,y);Z_printbf("KILLS");//Z_gotoxy(25,y);Z_printbf("KILLS");
468 Z_gotoxy(25,y+15);Z_printbf("KPM");//Z_gotoxy(25,y+15);Z_printbf("KPM");
469 Z_gotoxy(25,y+30);Z_printbf("SECRETS %u / %u",p->secrets,sw_secrets);//Z_gotoxy(25,y+30);Z_printbf("SECRETS %u / %u",p->secrets,sw_secrets);
470 Z_gotoxy(255,y);Z_printbf("%u",p->kills);//Z_gotoxy(255,y);Z_printbf("%u",p->kills);
471 Z_gotoxy(255,y+15);Z_printbf("%u.%u",t/10,t%10);//Z_gotoxy(255,y+15);Z_printbf("%u.%u",t/10,t%10);
474 void G_draw(void) {
475 int h;
476 word hr,mn,sc;
478 if(g_trans && !transdraw) return;
479 switch(g_st) {
480 case GS_ENDANIM: case GS_END2ANIM: case GS_DARKEN:
481 case GS_BVIDEO: case GS_EVIDEO: case GS_END3ANIM:
482 return;
483 case GS_TITLE:
484 V_center(1);//
485 V_pic(0,0,scrnh[0]);
486 V_center(0);//
487 break;
488 case GS_ENDSCR:
489 V_center(1);//
490 V_clr(0,SCRW,0,SCRH,0);V_pic(0,0,scrnh[2]);//V_clr(0,320,0,200,0);V_pic(0,0,scrnh[2]);
491 V_center(0);//
492 break;
493 case GS_INTER:
494 V_center(1);//
495 V_clr(0,SCRW,0,SCRH,0);//
496 V_pic(0,0,scrnh[1]);
497 Z_gotoxy(60,20);Z_printbf("LEVEL COMPLETE");
498 Z_calc_time(g_time,&hr,&mn,&sc);
499 Z_gotoxy(115,40);Z_printbf("TIME %u:%02u:%02u",hr,mn,sc);
500 h=60;
501 if(_2pl) {
502 Z_gotoxy(80,h);Z_printbf("PLAYER ONE");
503 Z_gotoxy(80,h+70);Z_printbf("PLAYER TWO");
504 h+=SCRH/10;//h+=20;
506 pl_info(&pl1,h);
507 if(_2pl) pl_info(&pl2,h+70);
508 V_center(0);//
509 break;
511 V_center(1);//
512 if(g_st!=GS_GAME) {
513 if(g_trans) return;
514 GM_draw();
515 V_copytoscr(0,SCRW,0,SCRH);//V_copytoscr(0,320,0,200);
516 return;
518 V_center(0);//
520 if(_2pl) {
521 w_o=0;WD=SCRW-120;HT=SCRH/2-2;drawview(&pl1);//w_o=0;drawview(&pl1);
522 w_o=SCRH/2;WD=SCRW-120;HT=SCRH/2-2;drawview(&pl2);//w_o=100;drawview(&pl2);
523 }else{
524 w_o=0;WD=SCRW-120;HT=SCRH-2;drawview(&pl1);//w_o=50;drawview(&pl1);
526 if(g_trans) return;
527 V_center(1);//
528 if(GM_draw()) {
529 pl1.drawst=pl2.drawst=0xFF;//pl1.drawst=pl2.drawst=0;
530 V_copytoscr(0,SCRW,0,SCRH);//V_copytoscr(0,320,0,200);
531 return;
533 V_center(0);//
534 if(pl1.invl) h=get_pu_st(pl1.invl)*6;
535 else if(pl1.pain<15) h=0;
536 else if(pl1.pain<35) h=1;
537 else if(pl1.pain<55) h=2;
538 else if(pl1.pain<75) h=3;
539 else if(pl1.pain<95) h=4;
540 else h=5;
541 if(h) V_maptoscr(0,SCRW-120,1,(_2pl)?(SCRH/2-2):(SCRH-2),clrmap+h*256);//if(h) V_maptoscr(0,200,(_2pl)?1:51,98,clrmap+h*256);
542 else V_copytoscr(0,SCRW-120,1,(_2pl)?(SCRH/2-2):(SCRH-2)); //else V_copytoscr(0,200,(_2pl)?1:51,98);
543 if(pl1.drawst) V_copytoscr(SCRW-120,120,0,_2pl?(SCRH/2):SCRH);//if(pl1.drawst) V_copytoscr(200,120,(_2pl)?0:50,100);
544 pl1.drawst=0xFF;//pl1.drawst=0;
545 if(_2pl) {
546 if(pl2.invl) h=get_pu_st(pl2.invl)*6;
547 else if(pl2.pain<15) h=0;
548 else if(pl2.pain<35) h=1;
549 else if(pl2.pain<55) h=2;
550 else if(pl2.pain<75) h=3;
551 else if(pl2.pain<95) h=4;
552 else h=5;
553 if(h) V_maptoscr(0,SCRW-120,SCRH/2+1,SCRH/2-2,clrmap+h*256);//if(h) V_maptoscr(0,200,101,98,clrmap+h*256);
554 else V_copytoscr(0,SCRW-120,SCRH/2+1,SCRH/2-2);//else V_copytoscr(0,200,101,98);
555 if(pl2.drawst) V_copytoscr(SCRW-120,120,SCRH/2,SCRH/2);//if(pl2.drawst) V_copytoscr(200,120,100,100);
556 pl2.drawst=0xFF;//pl2.drawst=0;
560 void G_respawn_player(player_t *p) {
561 int i;
563 if(dm_pnum==2) {
564 if(p==&pl1) i=dm_pl1p^=1;
565 else i=dm_pl2p^=1;
566 p->o.x=dm_pos[i].x;p->o.y=dm_pos[i].y;p->d=dm_pos[i].d;
567 FX_tfog(dm_pos[i].x,dm_pos[i].y);Z_sound(telepsnd,128);
568 return;
570 do{i=myrand(dm_pnum);}while(i==dm_pl1p || i==dm_pl2p);
571 p->o.x=dm_pos[i].x;p->o.y=dm_pos[i].y;p->d=dm_pos[i].d;
572 if(p==&pl1) dm_pl1p=i; else dm_pl2p=i;
573 FX_tfog(dm_pos[i].x,dm_pos[i].y);Z_sound(telepsnd,128);