DEADSOFTWARE

06bf44e85210d3f7a14c66a05fd86a60b5da1e96
[flatwaifu.git] / src / player.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 <stdlib.h>
25 #include <string.h>
26 #include "files.h"
27 #include "memory.h"
28 #include "vga.h"
29 #include "error.h"
30 #include "keyb.h"
31 #include "view.h"
32 #include "dots.h"
33 #include "smoke.h"
34 #include "weapons.h"
35 #include "monster.h"
36 #include "fx.h"
37 #include "items.h"
38 #include "switch.h"
39 #include "player.h"
40 #include "misc.h"
42 extern int hit_xv,hit_yv;
44 #define PL_RAD 8
45 #define PL_HT 26
47 #define PL_SWUP 4
48 #define PL_FLYUP 4
50 #define PL_AIR 360
51 #define PL_AQUA_AIR 1091
53 byte p_immortal=0,p_fly=0;
55 int PL_JUMP=10,PL_RUN=8;
57 int wp_it[11]={0,I_CSAW,0,I_SGUN,I_SGUN2,I_MGUN,I_LAUN,I_PLAS,I_BFG,I_GUN2,0};
59 enum{STAND,GO,DIE,SLOP,DEAD,MESS,OUT,FALL};
61 typedef void fire_f(int,int,int,int,int);
63 player_t pl1,pl2;
64 static int aitime;
65 static void *aisnd[3];
66 static void *pdsnd[5];
68 static void *spr[27*2],*snd[11];
69 static char sprd[27*2];
70 static void *wpn[11][6];
71 static byte goanim[]="BDACDA",
72 dieanim[]="HHHHIIIIJJJJKKKKLLLLMMMM",
73 slopanim[]="OOPPQQRRSSTTUUVVWW";
76 #pragma pack(1)
77 struct {
78 int ku,kd,kl,kr,kf,kj,kwl,kwr,kp;
79 } _keys;
80 #pragma pack()
82 void PL_savegame(FILE* h) {
83 myfwrite(&pl1,1,sizeof(pl1)-sizeof(_keys),h);//myfwrite(&pl1,1,sizeof(pl1),h);
84 if(_2pl) myfwrite(&pl2,1,sizeof(pl2)-sizeof(_keys),h);//myfwrite(&pl2,1,sizeof(pl2),h);
85 myfwrite(&PL_JUMP,1,4,h);myfwrite(&PL_RUN,1,4,h);myfwrite(&p_immortal,1,1,h);
86 }
88 void PL_loadgame(FILE* h) {
89 myfread(&pl1,1,sizeof(pl1)-sizeof(_keys),h);//myfread(&pl1,1,sizeof(pl1),h);
90 if(_2pl) myfread(&pl2,1,sizeof(pl2)-sizeof(_keys),h);//myfread(&pl2,1,sizeof(pl2),h);
91 myfread(&PL_JUMP,1,4,h);myfread(&PL_RUN,1,4,h);myfread(&p_immortal,1,1,h);
92 }
94 static int nonz(int a) {return (a)?a:1;}
96 static int firediry(player_t *p) {
97 if(p->f&PLF_UP) return -42;
98 if(p->f&PLF_DOWN) return 19;
99 return 0;
102 static void fire(player_t *p) {
103 static fire_f *ff[11]={
104 WP_pistol,WP_pistol,WP_pistol,WP_shotgun,WP_dshotgun,
105 WP_mgun,WP_rocket,WP_plasma,WP_bfgshot,WP_shotgun,WP_pistol};
106 static int ft[11]={5,2,6,18,36,2,12,2,0,2,1};
108 if(p->cwpn) return;
109 if(p->wpn==8) {
110 if(!p->fire)
111 if(keys[p->kf] && p->cell>=40)
112 {Z_sound(snd[5],128);p->fire=21;p->cell-=40;p->drawst|=PL_DRAWWPN;return;}
113 else return;
114 if(p->fire==1) p->cwpn=12;
115 else return;
116 }else if(p->wpn==1) {
117 if(!p->csnd) {
118 if(!keys[p->kf]) {Z_sound(snd[7],128);p->csnd=13;return;}
120 if(keys[p->kf] && !p->fire) {
121 p->fire=2;
122 WP_chainsaw(p->o.x+((p->d)?4:-4),p->o.y,(g_dm)?9:3,p->id);
123 if(!p->csnd) {Z_sound(snd[8],128);p->csnd=29;}
124 }return;
125 }else if(p->fire) return;
126 if(keys[p->kf] || p->wpn==8) {
127 switch(p->wpn) {
128 case 2: case 5:
129 if(!p->ammo) return;
130 --p->ammo;p->drawst|=PL_DRAWWPN;break;
131 case 3: case 9:
132 if(!p->shel) return;
133 --p->shel;p->drawst|=PL_DRAWWPN;break;
134 case 4:
135 if(p->shel<2) return;
136 p->shel-=2;p->drawst|=PL_DRAWWPN;break;
137 case 6:
138 if(!p->rock) return;
139 --p->rock;p->drawst|=PL_DRAWWPN;break;
140 case 7:
141 if(!p->cell) return;
142 --p->cell;p->drawst|=PL_DRAWWPN;break;
143 case 10:
144 if(!p->fuel) return;
145 --p->fuel;p->drawst|=PL_DRAWWPN;break;
147 if(p->wpn==10)
148 WP_ognemet(p->o.x,p->o.y-15,p->o.x+((p->d)?30:-30),p->o.y-15+firediry(p),
149 p->o.xv+p->o.vx,p->o.yv+p->o.vy,p->id);
150 else if(p->wpn>=1) ff[p->wpn] (p->o.x,p->o.y-15,p->o.x+((p->d)?30:-30),
151 p->o.y-15+firediry(p),p->id);
152 else WP_punch(p->o.x+((p->d)?4:-4),p->o.y,3,p->id);
153 p->fire=ft[p->wpn];
154 if(p->wpn>=2) p->f|=PLF_FIRE;
158 static void chgwpn(player_t *p) {
159 if(p->cwpn) return;
160 if(p->fire && p->wpn!=1) return;
161 if(keys[p->kwl]) {
162 do{ if(--p->wpn<0) p->wpn=10; }while(!(p->wpns&(1<<p->wpn)));
163 p->cwpn=3;
164 }else if(keys[p->kwr]) {
165 do{ if(++p->wpn>10) p->wpn=0; }while(!(p->wpns&(1<<p->wpn)));
166 p->cwpn=3;
168 if(p->cwpn) {
169 p->drawst|=PL_DRAWWPN;p->fire=0;
170 if(p->wpn==1) Z_sound(snd[6],128);
174 static void jump(player_t *p,int st) {
175 if(Z_canbreathe(p->o.x,p->o.y,p->o.r,p->o.h)) {
176 if(p->air<PL_AIR) {p->air=PL_AIR;p->drawst|=PL_DRAWAIR;}
177 }else {
178 if(--p->air < -9) {
179 p->air=0;
180 PL_hit(p,10,-3,HIT_WATER);
181 }else if((p->air&31)==0) {
182 FX_bubble(p->o.x,p->o.y-20,0,0,5);
184 p->drawst|=PL_DRAWAIR;
186 if(keys[p->kj]) {
187 if(p_fly) {
188 p->o.yv=-PL_FLYUP;
189 }else{
190 if(Z_canstand(p->o.x,p->o.y,p->o.r)) p->o.yv=-PL_JUMP;
191 else if(st&Z_INWATER) p->o.yv=-PL_SWUP;
196 int PL_isdead(player_t *p) {
197 switch(p->st) {
198 case DEAD: case MESS:
199 case OUT:
200 return 1;
202 return 0;
205 void PL_init(void) {
206 p_immortal=0;
207 PL_JUMP=10;PL_RUN=8;
208 aitime=0;
211 void PL_alloc(void) {
212 int i,j;
213 static char nm[][6]={
214 "OOF",
215 "PLPAIN",
216 "PLDETH",
217 "SLOP",
218 "PDIEHI",
219 "BFG",
220 "SAWUP",
221 "SAWIDL",
222 "SAWFUL",
223 "SAWHIT",
224 "PLFALL"
225 };
226 static char s[6];
228 for(i=0;i<27;++i) {
229 spr[i*2]=Z_getspr("PLAY",i,1,sprd+i*2);
230 spr[i*2+1]=Z_getspr("PLAY",i,2,sprd+i*2+1);
232 memcpy(s,"PWPx",4);
233 for(i=1;i<11;++i) {
234 s[3]=((i<10)?'0':('A'-10))+i;
235 for(j=0;j<6;++j) wpn[i][j]=Z_getspr(s,j,1,NULL);
237 for(i=0;i<11;++i) snd[i]=Z_getsnd(nm[i]);
238 memcpy(s,"AIx",4);
239 for(i=0;i<3;++i) {
240 s[2]=i+'1';
241 aisnd[i]=Z_getsnd(s);
243 memcpy(s,"PLDTHx",6);
244 for(i=0;i<5;++i) {
245 s[5]=i+'1';
246 pdsnd[i]=Z_getsnd(s);
250 void PL_restore(player_t *p) {
251 p->o.xv=p->o.yv=p->o.vx=p->o.vy=0;
252 p->o.r=PL_RAD;p->o.h=PL_HT;
253 p->pain=0;
254 p->invl=p->suit=0;
255 switch(p->st) {
256 case DEAD: case MESS: case OUT:
257 case DIE: case SLOP: case FALL:
258 p->life=100;p->armor=0;p->air=PL_AIR;
259 p->wpns=5;
260 p->wpn=2;
261 p->ammo=50;p->fuel=p->shel=p->rock=p->cell=0;
262 p->amul=1;
264 p->st=STAND;
265 p->fire=p->cwpn=p->csnd=0;
266 p->f=0;
267 p->drawst=0xFF;
268 p->looky=0;
269 p->keys=(g_dm)?0x70:0;
272 void PL_reset(void) {
273 pl1.st=pl2.st=DEAD;
274 pl1.frag=pl2.frag=0;
277 void PL_spawn(player_t *p,int x,int y,char d) {
278 PL_restore(p);
279 p->o.x=x;p->o.y=y;p->d=d;
280 p->kills=p->secrets=0;
283 int PL_hit(player_t *p,int d,int o,int t) {
284 if(!d) return 0;
285 switch(p->st) {
286 case DIE: case SLOP:
287 case DEAD: case MESS:
288 case OUT: case FALL:
289 return 0;
291 if(t==HIT_TRAP) {if(!p_immortal) {p->armor=0;p->life=-100;}}
292 else if(t!=HIT_ROCKET && t!=HIT_ELECTRO) {
293 if(p->id==-1) {if(o==-1) return 0;}
294 else if(o==-2) return 0;
296 if(t!=HIT_WATER && t!=HIT_ELECTRO)
297 DOT_blood(p->o.x,p->o.y-15,hit_xv,hit_yv,d*2);
298 else if(t==HIT_WATER) FX_bubble(p->o.x,p->o.y-20,0,0,d/2);
299 if(p_immortal || p->invl) return 1;
300 p->hit+=d;
301 p->hito=o;
302 return 1;
305 void PL_damage(player_t *p) {
306 int i;
308 if(!p->hit && p->life>0) return;
309 switch(p->st) {
310 case DIE: case SLOP:
311 case DEAD: case MESS:
312 case OUT: case FALL:
313 return;
315 i=p->hit*p->life/nonz(p->armor*3/4+p->life);
316 p->pain+=p->hit;
317 p->drawst|=PL_DRAWLIFE|PL_DRAWARMOR;
318 if((p->armor-=p->hit-i)<0) {p->life+=p->armor;p->armor=0;}
319 if((p->life-=i)<=0) {
320 if(p->life>-30) {p->st=DIE;p->s=0;Z_sound(pdsnd[rand()%5],128);}
321 else {p->st=SLOP;p->s=0;Z_sound(snd[3],128);}
322 if(p->amul>1) IT_spawn(p->o.x,p->o.y,I_BPACK);
323 if(!g_dm) {
324 if(p->keys&16) IT_spawn(p->o.x,p->o.y,I_KEYR);
325 if(p->keys&32) IT_spawn(p->o.x,p->o.y,I_KEYG);
326 if(p->keys&64) IT_spawn(p->o.x,p->o.y,I_KEYB);
328 for(i=1,p->wpns>>=1;i<11;++i,p->wpns>>=1)
329 if(i!=2) if(p->wpns&1) IT_spawn(p->o.x,p->o.y,wp_it[i]);
330 p->wpns=5;p->wpn=2;
331 p->f|=PLF_PNSND;
332 p->drawst|=PL_DRAWWPN;
333 if(g_dm && _2pl) {
334 if(p->id==-1) {
335 if(p->hito==-2) {++pl2.kills;++pl2.frag;}
336 else if(p->hito==-1) --pl1.frag;
337 }else{
338 if(p->hito==-1) {++pl1.kills;++pl1.frag;}
339 else if(p->hito==-2) --pl2.frag;
341 pl1.drawst|=PL_DRAWFRAG;
342 if(_2pl) pl2.drawst|=PL_DRAWFRAG;
344 p->life=0;return;
346 return;
349 void PL_cry(player_t *p) {
350 Z_sound(snd[(p->pain>20)?1:0],128);
351 p->f|=PLF_PNSND;
354 int PL_give(player_t *p,int t) {
355 int i;
357 switch(p->st) {
358 case DIE: case SLOP:
359 case DEAD: case MESS: case OUT:
360 return 0;
362 switch(t) {
363 case I_STIM: case I_MEDI:
364 if(p->life>=100) return 0;
365 if((p->life+=((t==I_MEDI)?25:10))>100) p->life=100;
366 p->drawst|=PL_DRAWLIFE;return 1;
367 case I_CLIP:
368 if(p->ammo>=200*p->amul) return 0;
369 if((p->ammo+=10)>200*p->amul) p->ammo=200*p->amul;
370 p->drawst|=PL_DRAWWPN;return 1;
371 case I_AMMO:
372 if(p->ammo>=200*p->amul) return 0;
373 if((p->ammo+=50)>200*p->amul) p->ammo=200*p->amul;
374 p->drawst|=PL_DRAWWPN;return 1;
375 case I_SHEL:
376 if(p->shel>=50*p->amul) return 0;
377 if((p->shel+=4)>50*p->amul) p->shel=50*p->amul;
378 p->drawst|=PL_DRAWWPN;return 1;
379 case I_SBOX:
380 if(p->shel>=50*p->amul) return 0;
381 if((p->shel+=25)>50*p->amul) p->shel=50*p->amul;
382 p->drawst|=PL_DRAWWPN;return 1;
383 case I_ROCKET:
384 if(p->rock>=50*p->amul) return 0;
385 if((++p->rock)>50*p->amul) p->rock=50*p->amul;
386 p->drawst|=PL_DRAWWPN;return 1;
387 case I_RBOX:
388 if(p->rock>=50*p->amul) return 0;
389 if((p->rock+=5)>50*p->amul) p->rock=50*p->amul;
390 p->drawst|=PL_DRAWWPN;return 1;
391 case I_CELL:
392 if(p->cell>=300*p->amul) return 0;
393 if((p->cell+=40)>300*p->amul) p->cell=300*p->amul;
394 p->drawst|=PL_DRAWWPN;return 1;
395 case I_CELP:
396 if(p->cell>=300*p->amul) return 0;
397 if((p->cell+=100)>300*p->amul) p->cell=300*p->amul;
398 p->drawst|=PL_DRAWWPN;return 1;
399 case I_BPACK:
400 if(p->amul==1) {p->amul=2;i=1;} else i=0;
401 i|=PL_give(p,I_CLIP);
402 i|=PL_give(p,I_SHEL);
403 i|=PL_give(p,I_ROCKET);
404 i|=PL_give(p,I_CELL);
405 return i;
406 case I_CSAW:
407 if(!(p->wpns&2)) {p->wpns|=2;p->drawst|=PL_DRAWWPN;return 1;}
408 return 0;
409 case I_GUN2:
410 i=PL_give(p,I_SHEL);
411 if(!(p->wpns&512)) {p->wpns|=512;i=1;}
412 p->drawst|=PL_DRAWWPN;return i;
413 case I_SGUN:
414 i=PL_give(p,I_SHEL);
415 if(!(p->wpns&8)) {p->wpns|=8;i=1;}
416 p->drawst|=PL_DRAWWPN;return i;
417 case I_SGUN2:
418 i=PL_give(p,I_SHEL);
419 if(!(p->wpns&16)) {p->wpns|=16;i=1;}
420 p->drawst|=PL_DRAWWPN;return i;
421 case I_MGUN:
422 i=PL_give(p,I_AMMO);
423 if(!(p->wpns&32)) {p->wpns|=32;i=1;}
424 p->drawst|=PL_DRAWWPN;return i;
425 case I_LAUN:
426 i=PL_give(p,I_ROCKET);
427 i|=PL_give(p,I_ROCKET);
428 if(!(p->wpns&64)) {p->wpns|=64;i=1;}
429 p->drawst|=PL_DRAWWPN;return i;
430 case I_PLAS:
431 i=PL_give(p,I_CELL);
432 if(!(p->wpns&128)) {p->wpns|=128;i=1;}
433 p->drawst|=PL_DRAWWPN;return i;
434 case I_BFG:
435 i=PL_give(p,I_CELL);
436 if(!(p->wpns&256)) {p->wpns|=256;i=1;}
437 p->drawst|=PL_DRAWWPN;return i;
438 case I_ARM1:
439 if(p->armor>=100) return 0;
440 p->armor=100;p->drawst|=PL_DRAWARMOR;return 1;
441 case I_ARM2:
442 if(p->armor>=200) return 0;
443 p->armor=200;p->drawst|=PL_DRAWARMOR;return 1;
444 case I_MEGA:
445 i=0;
446 if(p->life<200) {p->life=200;p->drawst|=PL_DRAWLIFE;i=1;}
447 if(p->armor<200) {p->armor=200;p->drawst|=PL_DRAWARMOR;i=1;}
448 return i;
449 case I_SUPER:
450 if(p->life<200) {p->life=min(p->life+100,200);p->drawst|=PL_DRAWLIFE;return 1;}
451 return 0;
452 case I_INVL:
453 p->invl=PL_POWERUP_TIME;
454 return 1;
455 case I_SUIT:
456 p->suit=PL_POWERUP_TIME;
457 return 1;
458 case I_AQUA:
459 if(p->air >= PL_AQUA_AIR) return 0;
460 p->air=PL_AQUA_AIR;p->drawst|=PL_DRAWAIR;
461 return 1;
462 case I_KEYR:
463 if(p->keys&16) return 0;
464 p->keys|=16;p->drawst|=PL_DRAWKEYS;return 1;
465 case I_KEYG:
466 if(p->keys&32) return 0;
467 p->keys|=32;p->drawst|=PL_DRAWKEYS;return 1;
468 case I_KEYB:
469 if(p->keys&64) return 0;
470 p->keys|=64;p->drawst|=PL_DRAWKEYS;return 1;
471 default:
472 return 0;
476 void PL_act(player_t *p) {
477 int st;
479 if(--aitime<0) aitime=0;
480 SW_press(p->o.x,p->o.y,p->o.r,p->o.h,4|p->keys,p->id);
481 if(!p->suit) if((g_time&15)==0)
482 PL_hit(p,Z_getacid(p->o.x,p->o.y,p->o.r,p->o.h),-3,HIT_SOME);
483 if(p->st!=FALL && p->st!=OUT) {
484 if(((st=Z_moveobj(&p->o))&Z_FALLOUT) && p->o.y>=FLDH*CELH+50) {
485 switch(p->st) {
486 case DEAD: case MESS: case DIE: case SLOP:
487 p->s=5;break;
488 default:
489 p->s=Z_sound(snd[10],128);
490 if(g_dm) --p->frag;
491 }p->st=FALL;
493 }else st=0;
494 if(st&Z_HITWATER) Z_splash(&p->o,PL_RAD+PL_HT);
495 if(p->f&PLF_FIRE) if(p->fire!=2) p->f-=PLF_FIRE;
496 if(keys[p->ku]) {p->f|=PLF_UP;p->looky-=5;}
497 else{
498 p->f&=0xFFFF-PLF_UP;
499 if(keys[p->kd])
500 {p->f|=PLF_DOWN;p->looky+=5;}
501 else {p->f&=0xFFFF-PLF_DOWN;p->looky=Z_dec(p->looky,5);}
503 if(keys[p->kp]) SW_press(p->o.x,p->o.y,p->o.r,p->o.h,1|p->keys,p->id);
504 if(p->fire) --p->fire;
505 if(p->cwpn) --p->cwpn;
506 if(p->csnd) --p->csnd;
507 if(p->invl) --p->invl;
508 if(p->suit) --p->suit;
509 switch(p->st) {
510 case DIE:
511 p->o.h=7;
512 if(!dieanim[++p->s]) {p->st=DEAD;MN_killedp();}
513 p->o.xv=Z_dec(p->o.xv,1);
514 break;
515 case SLOP:
516 p->o.h=6;
517 if(!slopanim[++p->s]) {p->st=MESS;MN_killedp();}
518 p->o.xv=Z_dec(p->o.xv,1);
519 break;
520 case GO:
521 chgwpn(p);fire(p);jump(p,st);
522 if(p_fly)
523 SMK_gas(p->o.x,p->o.y-2,2,3,p->o.xv+p->o.vx,p->o.yv+p->o.vy,128);
524 if((p->s+=abs(p->o.xv)/2) >= 24) p->s%=24;
525 if(!keys[p->kl] && !keys[p->kr]) {
526 if(p->o.xv) p->o.xv=Z_dec(p->o.xv,1);
527 else p->st=STAND;
528 break;
530 if(p->o.xv<PL_RUN && keys[p->kr]) {p->o.xv+=PL_RUN>>3;p->d=1;}
531 else if(PL_RUN>8)
532 SMK_gas(p->o.x,p->o.y-2,2,3,p->o.xv+p->o.vx,p->o.yv+p->o.vy,32);
533 if(p->o.xv>-PL_RUN && keys[p->kl]) {p->o.xv-=PL_RUN>>3;p->d=0;}
534 else if(PL_RUN>8)
535 SMK_gas(p->o.x,p->o.y-2,2,3,p->o.xv+p->o.vx,p->o.yv+p->o.vy,32);
536 break;
537 case STAND:
538 chgwpn(p);fire(p);jump(p,st);
539 if(p_fly)
540 SMK_gas(p->o.x,p->o.y-2,2,3,p->o.xv+p->o.vx,p->o.yv+p->o.vy,128);
541 if(keys[p->kl]) {p->st=GO;p->s=0;p->d=0;}
542 else if(keys[p->kr]) {p->st=GO;p->s=0;p->d=1;}
543 break;
544 case DEAD:
545 case MESS:
546 case OUT:
547 p->o.xv=Z_dec(p->o.xv,1);
548 if(keys[p->ku] || keys[p->kd] || keys[p->kl] || keys[p->kr] ||
549 keys[p->kf] || keys[p->kj] || keys[p->kp] || keys[p->kwl] || keys[p->kwr]) {
550 if(p->st!=OUT) MN_spawn_deadpl(&p->o,p->color,(p->st==MESS)?1:0);
551 PL_restore(p);
552 if(g_dm) {G_respawn_player(p);break;}
553 if(!_2pl) {
554 if(--p->lives==0) {G_start();break;}
555 else{p->o.x=dm_pos[0].x;p->o.y=dm_pos[0].y;p->d=dm_pos[0].d;}
556 p->drawst|=PL_DRAWLIVES;
558 if(p->id==-1)
559 {p->o.x=dm_pos[0].x;p->o.y=dm_pos[0].y;p->d=dm_pos[0].d;}
560 else {p->o.x=dm_pos[1].x;p->o.y=dm_pos[1].y;p->d=dm_pos[1].d;}
561 }break;
562 case FALL:
563 if(--p->s<=0) p->st=OUT;
564 break;
568 static int standspr(player_t *p) {
569 if(p->f&PLF_UP) return 'X';
570 if(p->f&PLF_DOWN) return 'Z';
571 return 'E';
574 static int wpnspr(player_t *p) {
575 if(p->f&PLF_UP) return 'C';
576 if(p->f&PLF_DOWN) return 'E';
577 return 'A';
580 void PL_draw(player_t *p) {
581 int s,w,wx,wy;
582 static int wytab[]={-1,-2,-1,0};
584 s='A';w=0;wx=wy=0;
585 switch(p->st) {
586 case STAND:
587 if(p->f&PLF_FIRE) {s=standspr(p)+1;w=wpnspr(p)+1;}
588 else if(p->pain) {s='G';w='A';wx=p->d?2:-2;wy=1;}
589 else {s=standspr(p);w=wpnspr(p);}
590 break;
591 case DEAD:
592 s='N';break;
593 case MESS:
594 s='W';break;
595 case GO:
596 if(p->pain) {s='G';w='A';wx=p->d?2:-2;wy=1;}
597 else {
598 s=goanim[p->s/8];w=(p->f&PLF_FIRE)?'B':'A';
599 wx=p->d?2:-2;wy=1+wytab[s-'A'];
601 break;
602 case DIE:
603 s=dieanim[p->s];break;
604 case SLOP:
605 s=slopanim[p->s];break;
606 case OUT:
607 s=0;break;
609 if(p->wpn==0) w=0;
610 if(w) Z_drawspr(p->o.x+wx,p->o.y+wy,wpn[p->wpn][w-'A'],p->d);
611 if(s) Z_drawmanspr(p->o.x,p->o.y,spr[(s-'A')*2+p->d],sprd[(s-'A')*2+p->d],p->color);
614 void *PL_getspr(int s,int d) {
615 return spr[(s-'A')*2+d];
618 static void chk_bfg(player_t *p,int x,int y) {
619 int dx,dy;
621 if(aitime) return;
622 switch(p->st) {
623 case DIE: case SLOP: case FALL:
624 case DEAD: case MESS: case OUT:
625 return;
627 dx=p->o.x-x;dy=p->o.y-p->o.h/2-y;
628 if(dx*dx+dy*dy<=1600) {
629 aitime=Z_sound(aisnd[rand()%3],128)*4;
633 void bfg_fly(int x,int y,int o) {
634 // if(!g_dm) return;
635 if(o!=-1) chk_bfg(&pl1,x,y);
636 if(_2pl) if(o!=-2) chk_bfg(&pl2,x,y);
637 if(o==-1 || o==-2) MN_warning(x-50,y-50,x+50,y+50);
640 void PL_drawst(player_t *p) {
641 V_setrect(WD,120,w_o,HT);Z_clrst();
642 int i;
644 if(p->drawst&PL_DRAWAIR)
645 if (p->air<PL_AIR)//
646 Z_drawstair(p->air);
647 if(p->drawst&PL_DRAWLIFE)
648 Z_drawstprcnt(0,p->life);
649 if(p->drawst&PL_DRAWARMOR)
650 Z_drawstprcnt(1,p->armor);
651 if(p->drawst&PL_DRAWWPN) {
652 switch(p->wpn) {
653 case 2: case 5:
654 i=p->ammo;break;
655 case 3: case 4: case 9:
656 i=p->shel;break;
657 case 6:
658 i=p->rock;break;
659 case 10:
660 i=p->fuel;break;
661 case 7: case 8:
662 i=p->cell;break;
664 Z_drawstwpn(p->wpn,i);
666 if(p->drawst&PL_DRAWFRAG) Z_drawstnum(p->frag);
667 if(p->drawst&PL_DRAWKEYS) Z_drawstkeys(p->keys);
668 if(!_2pl) if(p->drawst&PL_DRAWLIVES) Z_drawstlives(p->lives);