DEADSOFTWARE

5a8a80ebb361689b65c3dcd5a8d79e971177e49f
[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 "vga.h"
27 #include "keyb.h"
28 #include "view.h"
29 #include "dots.h"
30 #include "smoke.h"
31 #include "weapons.h"
32 #include "monster.h"
33 #include "fx.h"
34 #include "items.h"
35 #include "switch.h"
36 #include "player.h"
37 #include "misc.h"
39 extern int hit_xv,hit_yv;
41 #define PL_RAD 8
42 #define PL_HT 26
44 #define PL_SWUP 4
45 #define PL_FLYUP 4
47 #define PL_AIR 360
48 #define PL_AQUA_AIR 1091
50 byte p_immortal=0,p_fly=0;
52 int PL_JUMP=10,PL_RUN=8;
54 int wp_it[11]={0,I_CSAW,0,I_SGUN,I_SGUN2,I_MGUN,I_LAUN,I_PLAS,I_BFG,I_GUN2,0};
56 enum{STAND,GO,DIE,SLOP,DEAD,MESS,OUT,FALL};
58 typedef void fire_f(int,int,int,int,int);
60 player_t pl1,pl2;
61 static int aitime;
62 static void *aisnd[3];
63 static void *pdsnd[5];
65 static void *spr[27*2],*snd[11];
66 static char sprd[27*2];
67 static void *wpn[11][6];
68 static byte goanim[]="BDACDA",
69 dieanim[]="HHHHIIIIJJJJKKKKLLLLMMMM",
70 slopanim[]="OOPPQQRRSSTTUUVVWW";
73 #pragma pack(1)
74 struct {
75 int ku,kd,kl,kr,kf,kj,kwl,kwr,kp;
76 } _keys;
77 #pragma pack()
79 void PL_save_player (player_t *p, FILE *h) {
80 myfwrite32(p->o.x, h);
81 myfwrite32(p->o.y, h);
82 myfwrite32(p->o.xv, h);
83 myfwrite32(p->o.yv, h);
84 myfwrite32(p->o.vx, h);
85 myfwrite32(p->o.vy, h);
86 myfwrite32(p->o.r, h);
87 myfwrite32(p->o.h, h);
88 myfwrite32(p->looky, h);
89 myfwrite32(p->st, h);
90 myfwrite32(p->s, h);
91 myfwrite32(p->life, h);
92 myfwrite32(p->armor, h);
93 myfwrite32(p->hit, h);
94 myfwrite32(p->hito, h);
95 myfwrite32(p->pain, h);
96 myfwrite32(p->air, h);
97 myfwrite32(p->invl, h);
98 myfwrite32(p->suit, h);
99 myfwrite8(p->d, h);
100 myfwrite32(p->frag, h);
101 myfwrite32(p->ammo, h);
102 myfwrite32(p->shel, h);
103 myfwrite32(p->rock, h);
104 myfwrite32(p->cell, h);
105 myfwrite32(p->fuel, h);
106 myfwrite32(p->kills, h);
107 myfwrite32(p->secrets, h);
108 myfwrite8(p->fire, h);
109 myfwrite8(p->cwpn, h);
110 myfwrite8(p->csnd, h);
111 myfwrite8(p->amul, h);
112 myfwrite16(p->wpns, h);
113 myfwrite8(p->wpn, h);
114 myfwrite8(p->f, h);
115 myfwrite8(p->drawst, h);
116 myfwrite8(p->color, h);
117 myfwrite32(p->id, h);
118 myfwrite8(p->keys, h);
119 myfwrite8(p->lives, h);
120 // k* not saved
123 void PL_savegame (FILE *h) {
124 PL_save_player(&pl1, h);
125 if (_2pl) {
126 PL_save_player(&pl2, h);
128 myfwrite32(PL_JUMP, h);
129 myfwrite32(PL_RUN, h);
130 myfwrite8(p_immortal, h);
133 void PL_load_player (player_t *p, FILE *h) {
134 myfread32(&p->o.x, h);
135 myfread32(&p->o.y, h);
136 myfread32(&p->o.xv, h);
137 myfread32(&p->o.yv, h);
138 myfread32(&p->o.vx, h);
139 myfread32(&p->o.vy, h);
140 myfread32(&p->o.r, h);
141 myfread32(&p->o.h, h);
142 myfread32(&p->looky, h);
143 myfread32(&p->st, h);
144 myfread32(&p->s, h);
145 myfread32(&p->life, h);
146 myfread32(&p->armor, h);
147 myfread32(&p->hit, h);
148 myfread32(&p->hito, h);
149 myfread32(&p->pain, h);
150 myfread32(&p->air, h);
151 myfread32(&p->invl, h);
152 myfread32(&p->suit, h);
153 myfread8(&p->d, h);
154 myfread32(&p->frag, h);
155 myfread32(&p->ammo, h);
156 myfread32(&p->shel, h);
157 myfread32(&p->rock, h);
158 myfread32(&p->cell, h);
159 myfread32(&p->fuel, h);
160 myfread32(&p->kills, h);
161 myfread32(&p->secrets, h);
162 myfread8(&p->fire, h);
163 myfread8(&p->cwpn, h);
164 myfread8(&p->csnd, h);
165 myfread8(&p->amul, h);
166 myfread16(&p->wpns, h);
167 myfread8(&p->wpn, h);
168 myfread8(&p->f, h);
169 myfread8(&p->drawst, h);
170 myfread8(&p->color, h);
171 myfread32(&p->id, h);
172 myfread8(&p->keys, h);
173 myfread8(&p->lives, h);
174 // k* not saved
177 void PL_loadgame (FILE *h) {
178 PL_load_player(&pl1, h);
179 if (_2pl) {
180 PL_load_player(&pl2, h);
182 myfread32(&PL_JUMP, h);
183 myfread32(&PL_RUN, h);
184 myfread8(&p_immortal, h);
187 static int nonz(int a) {return (a)?a:1;}
189 static int firediry(player_t *p) {
190 if(p->f&PLF_UP) return -42;
191 if(p->f&PLF_DOWN) return 19;
192 return 0;
195 static void fire(player_t *p) {
196 static fire_f *ff[11]={
197 WP_pistol,WP_pistol,WP_pistol,WP_shotgun,WP_dshotgun,
198 WP_mgun,WP_rocket,WP_plasma,WP_bfgshot,WP_shotgun,WP_pistol};
199 static int ft[11]={5,2,6,18,36,2,12,2,0,2,1};
201 if(p->cwpn) return;
202 if(p->wpn==8) {
203 if(!p->fire)
204 if(keys[p->kf] && p->cell>=40)
205 {Z_sound(snd[5],128);p->fire=21;p->cell-=40;p->drawst|=PL_DRAWWPN;return;}
206 else return;
207 if(p->fire==1) p->cwpn=12;
208 else return;
209 }else if(p->wpn==1) {
210 if(!p->csnd) {
211 if(!keys[p->kf]) {Z_sound(snd[7],128);p->csnd=13;return;}
213 if(keys[p->kf] && !p->fire) {
214 p->fire=2;
215 WP_chainsaw(p->o.x+((p->d)?4:-4),p->o.y,(g_dm)?9:3,p->id);
216 if(!p->csnd) {Z_sound(snd[8],128);p->csnd=29;}
217 }return;
218 }else if(p->fire) return;
219 if(keys[p->kf] || p->wpn==8) {
220 switch(p->wpn) {
221 case 2: case 5:
222 if(!p->ammo) return;
223 --p->ammo;p->drawst|=PL_DRAWWPN;break;
224 case 3: case 9:
225 if(!p->shel) return;
226 --p->shel;p->drawst|=PL_DRAWWPN;break;
227 case 4:
228 if(p->shel<2) return;
229 p->shel-=2;p->drawst|=PL_DRAWWPN;break;
230 case 6:
231 if(!p->rock) return;
232 --p->rock;p->drawst|=PL_DRAWWPN;break;
233 case 7:
234 if(!p->cell) return;
235 --p->cell;p->drawst|=PL_DRAWWPN;break;
236 case 10:
237 if(!p->fuel) return;
238 --p->fuel;p->drawst|=PL_DRAWWPN;break;
240 if(p->wpn==10)
241 WP_ognemet(p->o.x,p->o.y-15,p->o.x+((p->d)?30:-30),p->o.y-15+firediry(p),
242 p->o.xv+p->o.vx,p->o.yv+p->o.vy,p->id);
243 else if(p->wpn>=1) ff[p->wpn] (p->o.x,p->o.y-15,p->o.x+((p->d)?30:-30),
244 p->o.y-15+firediry(p),p->id);
245 else WP_punch(p->o.x+((p->d)?4:-4),p->o.y,3,p->id);
246 p->fire=ft[p->wpn];
247 if(p->wpn>=2) p->f|=PLF_FIRE;
251 static void chgwpn(player_t *p) {
252 if(p->cwpn) return;
253 if(p->fire && p->wpn!=1) return;
254 if(keys[p->kwl]) {
255 do{ if(--p->wpn<0) p->wpn=10; }while(!(p->wpns&(1<<p->wpn)));
256 p->cwpn=3;
257 }else if(keys[p->kwr]) {
258 do{ if(++p->wpn>10) p->wpn=0; }while(!(p->wpns&(1<<p->wpn)));
259 p->cwpn=3;
261 if(p->cwpn) {
262 p->drawst|=PL_DRAWWPN;p->fire=0;
263 if(p->wpn==1) Z_sound(snd[6],128);
267 static void jump(player_t *p,int st) {
268 if(Z_canbreathe(p->o.x,p->o.y,p->o.r,p->o.h)) {
269 if(p->air<PL_AIR) {p->air=PL_AIR;p->drawst|=PL_DRAWAIR;}
270 }else {
271 if(--p->air < -9) {
272 p->air=0;
273 PL_hit(p,10,-3,HIT_WATER);
274 }else if((p->air&31)==0) {
275 FX_bubble(p->o.x,p->o.y-20,0,0,5);
277 p->drawst|=PL_DRAWAIR;
279 if(keys[p->kj]) {
280 if(p_fly) {
281 p->o.yv=-PL_FLYUP;
282 }else{
283 if(Z_canstand(p->o.x,p->o.y,p->o.r)) p->o.yv=-PL_JUMP;
284 else if(st&Z_INWATER) p->o.yv=-PL_SWUP;
289 int PL_isdead(player_t *p) {
290 switch(p->st) {
291 case DEAD: case MESS:
292 case OUT:
293 return 1;
295 return 0;
298 void PL_init(void) {
299 p_immortal=0;
300 PL_JUMP=10;PL_RUN=8;
301 aitime=0;
304 void PL_alloc(void) {
305 int i,j;
306 static char nm[][6]={
307 "OOF",
308 "PLPAIN",
309 "PLDETH",
310 "SLOP",
311 "PDIEHI",
312 "BFG",
313 "SAWUP",
314 "SAWIDL",
315 "SAWFUL",
316 "SAWHIT",
317 "PLFALL"
318 };
319 static char s[6];
321 for(i=0;i<27;++i) {
322 spr[i*2]=Z_getspr("PLAY",i,1,sprd+i*2);
323 spr[i*2+1]=Z_getspr("PLAY",i,2,sprd+i*2+1);
325 memcpy(s,"PWPx",4);
326 for(i=1;i<11;++i) {
327 s[3]=((i<10)?'0':('A'-10))+i;
328 for(j=0;j<6;++j) wpn[i][j]=Z_getspr(s,j,1,NULL);
330 for(i=0;i<11;++i) snd[i]=Z_getsnd(nm[i]);
331 memcpy(s,"AIx",4);
332 for(i=0;i<3;++i) {
333 s[2]=i+'1';
334 aisnd[i]=Z_getsnd(s);
336 memcpy(s,"PLDTHx",6);
337 for(i=0;i<5;++i) {
338 s[5]=i+'1';
339 pdsnd[i]=Z_getsnd(s);
343 void PL_restore(player_t *p) {
344 p->o.xv=p->o.yv=p->o.vx=p->o.vy=0;
345 p->o.r=PL_RAD;p->o.h=PL_HT;
346 p->pain=0;
347 p->invl=p->suit=0;
348 switch(p->st) {
349 case DEAD: case MESS: case OUT:
350 case DIE: case SLOP: case FALL:
351 p->life=100;p->armor=0;p->air=PL_AIR;
352 p->wpns=5;
353 p->wpn=2;
354 p->ammo=50;p->fuel=p->shel=p->rock=p->cell=0;
355 p->amul=1;
357 p->st=STAND;
358 p->fire=p->cwpn=p->csnd=0;
359 p->f=0;
360 p->drawst=0xFF;
361 p->looky=0;
362 p->keys=(g_dm)?0x70:0;
365 void PL_reset(void) {
366 pl1.st=pl2.st=DEAD;
367 pl1.frag=pl2.frag=0;
370 void PL_spawn(player_t *p,int x,int y,char d) {
371 PL_restore(p);
372 p->o.x=x;p->o.y=y;p->d=d;
373 p->kills=p->secrets=0;
376 int PL_hit(player_t *p,int d,int o,int t) {
377 if(!d) return 0;
378 switch(p->st) {
379 case DIE: case SLOP:
380 case DEAD: case MESS:
381 case OUT: case FALL:
382 return 0;
384 if(t==HIT_TRAP) {if(!p_immortal) {p->armor=0;p->life=-100;}}
385 else if(t!=HIT_ROCKET && t!=HIT_ELECTRO) {
386 if(p->id==-1) {if(o==-1) return 0;}
387 else if(o==-2) return 0;
389 if(t!=HIT_WATER && t!=HIT_ELECTRO)
390 DOT_blood(p->o.x,p->o.y-15,hit_xv,hit_yv,d*2);
391 else if(t==HIT_WATER) FX_bubble(p->o.x,p->o.y-20,0,0,d/2);
392 if(p_immortal || p->invl) return 1;
393 p->hit+=d;
394 p->hito=o;
395 return 1;
398 void PL_damage(player_t *p) {
399 int i;
401 if(!p->hit && p->life>0) return;
402 switch(p->st) {
403 case DIE: case SLOP:
404 case DEAD: case MESS:
405 case OUT: case FALL:
406 return;
408 i=p->hit*p->life/nonz(p->armor*3/4+p->life);
409 p->pain+=p->hit;
410 p->drawst|=PL_DRAWLIFE|PL_DRAWARMOR;
411 if((p->armor-=p->hit-i)<0) {p->life+=p->armor;p->armor=0;}
412 if((p->life-=i)<=0) {
413 if(p->life>-30) {p->st=DIE;p->s=0;Z_sound(pdsnd[rand()%5],128);}
414 else {p->st=SLOP;p->s=0;Z_sound(snd[3],128);}
415 if(p->amul>1) IT_spawn(p->o.x,p->o.y,I_BPACK);
416 if(!g_dm) {
417 if(p->keys&16) IT_spawn(p->o.x,p->o.y,I_KEYR);
418 if(p->keys&32) IT_spawn(p->o.x,p->o.y,I_KEYG);
419 if(p->keys&64) IT_spawn(p->o.x,p->o.y,I_KEYB);
421 for(i=1,p->wpns>>=1;i<11;++i,p->wpns>>=1)
422 if(i!=2) if(p->wpns&1) IT_spawn(p->o.x,p->o.y,wp_it[i]);
423 p->wpns=5;p->wpn=2;
424 p->f|=PLF_PNSND;
425 p->drawst|=PL_DRAWWPN;
426 if(g_dm && _2pl) {
427 if(p->id==-1) {
428 if(p->hito==-2) {++pl2.kills;++pl2.frag;}
429 else if(p->hito==-1) --pl1.frag;
430 }else{
431 if(p->hito==-1) {++pl1.kills;++pl1.frag;}
432 else if(p->hito==-2) --pl2.frag;
434 pl1.drawst|=PL_DRAWFRAG;
435 if(_2pl) pl2.drawst|=PL_DRAWFRAG;
437 p->life=0;return;
439 return;
442 void PL_cry(player_t *p) {
443 Z_sound(snd[(p->pain>20)?1:0],128);
444 p->f|=PLF_PNSND;
447 int PL_give(player_t *p,int t) {
448 int i;
450 switch(p->st) {
451 case DIE: case SLOP:
452 case DEAD: case MESS: case OUT:
453 return 0;
455 switch(t) {
456 case I_STIM: case I_MEDI:
457 if(p->life>=100) return 0;
458 if((p->life+=((t==I_MEDI)?25:10))>100) p->life=100;
459 p->drawst|=PL_DRAWLIFE;return 1;
460 case I_CLIP:
461 if(p->ammo>=200*p->amul) return 0;
462 if((p->ammo+=10)>200*p->amul) p->ammo=200*p->amul;
463 p->drawst|=PL_DRAWWPN;return 1;
464 case I_AMMO:
465 if(p->ammo>=200*p->amul) return 0;
466 if((p->ammo+=50)>200*p->amul) p->ammo=200*p->amul;
467 p->drawst|=PL_DRAWWPN;return 1;
468 case I_SHEL:
469 if(p->shel>=50*p->amul) return 0;
470 if((p->shel+=4)>50*p->amul) p->shel=50*p->amul;
471 p->drawst|=PL_DRAWWPN;return 1;
472 case I_SBOX:
473 if(p->shel>=50*p->amul) return 0;
474 if((p->shel+=25)>50*p->amul) p->shel=50*p->amul;
475 p->drawst|=PL_DRAWWPN;return 1;
476 case I_ROCKET:
477 if(p->rock>=50*p->amul) return 0;
478 if((++p->rock)>50*p->amul) p->rock=50*p->amul;
479 p->drawst|=PL_DRAWWPN;return 1;
480 case I_RBOX:
481 if(p->rock>=50*p->amul) return 0;
482 if((p->rock+=5)>50*p->amul) p->rock=50*p->amul;
483 p->drawst|=PL_DRAWWPN;return 1;
484 case I_CELL:
485 if(p->cell>=300*p->amul) return 0;
486 if((p->cell+=40)>300*p->amul) p->cell=300*p->amul;
487 p->drawst|=PL_DRAWWPN;return 1;
488 case I_CELP:
489 if(p->cell>=300*p->amul) return 0;
490 if((p->cell+=100)>300*p->amul) p->cell=300*p->amul;
491 p->drawst|=PL_DRAWWPN;return 1;
492 case I_BPACK:
493 if(p->amul==1) {p->amul=2;i=1;} else i=0;
494 i|=PL_give(p,I_CLIP);
495 i|=PL_give(p,I_SHEL);
496 i|=PL_give(p,I_ROCKET);
497 i|=PL_give(p,I_CELL);
498 return i;
499 case I_CSAW:
500 if(!(p->wpns&2)) {p->wpns|=2;p->drawst|=PL_DRAWWPN;return 1;}
501 return 0;
502 case I_GUN2:
503 i=PL_give(p,I_SHEL);
504 if(!(p->wpns&512)) {p->wpns|=512;i=1;}
505 p->drawst|=PL_DRAWWPN;return i;
506 case I_SGUN:
507 i=PL_give(p,I_SHEL);
508 if(!(p->wpns&8)) {p->wpns|=8;i=1;}
509 p->drawst|=PL_DRAWWPN;return i;
510 case I_SGUN2:
511 i=PL_give(p,I_SHEL);
512 if(!(p->wpns&16)) {p->wpns|=16;i=1;}
513 p->drawst|=PL_DRAWWPN;return i;
514 case I_MGUN:
515 i=PL_give(p,I_AMMO);
516 if(!(p->wpns&32)) {p->wpns|=32;i=1;}
517 p->drawst|=PL_DRAWWPN;return i;
518 case I_LAUN:
519 i=PL_give(p,I_ROCKET);
520 i|=PL_give(p,I_ROCKET);
521 if(!(p->wpns&64)) {p->wpns|=64;i=1;}
522 p->drawst|=PL_DRAWWPN;return i;
523 case I_PLAS:
524 i=PL_give(p,I_CELL);
525 if(!(p->wpns&128)) {p->wpns|=128;i=1;}
526 p->drawst|=PL_DRAWWPN;return i;
527 case I_BFG:
528 i=PL_give(p,I_CELL);
529 if(!(p->wpns&256)) {p->wpns|=256;i=1;}
530 p->drawst|=PL_DRAWWPN;return i;
531 case I_ARM1:
532 if(p->armor>=100) return 0;
533 p->armor=100;p->drawst|=PL_DRAWARMOR;return 1;
534 case I_ARM2:
535 if(p->armor>=200) return 0;
536 p->armor=200;p->drawst|=PL_DRAWARMOR;return 1;
537 case I_MEGA:
538 i=0;
539 if(p->life<200) {p->life=200;p->drawst|=PL_DRAWLIFE;i=1;}
540 if(p->armor<200) {p->armor=200;p->drawst|=PL_DRAWARMOR;i=1;}
541 return i;
542 case I_SUPER:
543 if(p->life<200) {p->life=min(p->life+100,200);p->drawst|=PL_DRAWLIFE;return 1;}
544 return 0;
545 case I_INVL:
546 p->invl=PL_POWERUP_TIME;
547 return 1;
548 case I_SUIT:
549 p->suit=PL_POWERUP_TIME;
550 return 1;
551 case I_AQUA:
552 if(p->air >= PL_AQUA_AIR) return 0;
553 p->air=PL_AQUA_AIR;p->drawst|=PL_DRAWAIR;
554 return 1;
555 case I_KEYR:
556 if(p->keys&16) return 0;
557 p->keys|=16;p->drawst|=PL_DRAWKEYS;return 1;
558 case I_KEYG:
559 if(p->keys&32) return 0;
560 p->keys|=32;p->drawst|=PL_DRAWKEYS;return 1;
561 case I_KEYB:
562 if(p->keys&64) return 0;
563 p->keys|=64;p->drawst|=PL_DRAWKEYS;return 1;
564 default:
565 return 0;
569 void PL_act(player_t *p) {
570 int st;
572 if(--aitime<0) aitime=0;
573 SW_press(p->o.x,p->o.y,p->o.r,p->o.h,4|p->keys,p->id);
574 if(!p->suit) if((g_time&15)==0)
575 PL_hit(p,Z_getacid(p->o.x,p->o.y,p->o.r,p->o.h),-3,HIT_SOME);
576 if(p->st!=FALL && p->st!=OUT) {
577 if(((st=Z_moveobj(&p->o))&Z_FALLOUT) && p->o.y>=FLDH*CELH+50) {
578 switch(p->st) {
579 case DEAD: case MESS: case DIE: case SLOP:
580 p->s=5;break;
581 default:
582 p->s=Z_sound(snd[10],128);
583 if(g_dm) --p->frag;
584 }p->st=FALL;
586 }else st=0;
587 if(st&Z_HITWATER) Z_splash(&p->o,PL_RAD+PL_HT);
588 if(p->f&PLF_FIRE) if(p->fire!=2) p->f-=PLF_FIRE;
589 if(keys[p->ku]) {p->f|=PLF_UP;p->looky-=5;}
590 else{
591 p->f&=0xFFFF-PLF_UP;
592 if(keys[p->kd])
593 {p->f|=PLF_DOWN;p->looky+=5;}
594 else {p->f&=0xFFFF-PLF_DOWN;p->looky=Z_dec(p->looky,5);}
596 if(keys[p->kp]) SW_press(p->o.x,p->o.y,p->o.r,p->o.h,1|p->keys,p->id);
597 if(p->fire) --p->fire;
598 if(p->cwpn) --p->cwpn;
599 if(p->csnd) --p->csnd;
600 if(p->invl) --p->invl;
601 if(p->suit) --p->suit;
602 switch(p->st) {
603 case DIE:
604 p->o.h=7;
605 if(!dieanim[++p->s]) {p->st=DEAD;MN_killedp();}
606 p->o.xv=Z_dec(p->o.xv,1);
607 break;
608 case SLOP:
609 p->o.h=6;
610 if(!slopanim[++p->s]) {p->st=MESS;MN_killedp();}
611 p->o.xv=Z_dec(p->o.xv,1);
612 break;
613 case GO:
614 chgwpn(p);fire(p);jump(p,st);
615 if(p_fly)
616 SMK_gas(p->o.x,p->o.y-2,2,3,p->o.xv+p->o.vx,p->o.yv+p->o.vy,128);
617 if((p->s+=abs(p->o.xv)/2) >= 24) p->s%=24;
618 if(!keys[p->kl] && !keys[p->kr]) {
619 if(p->o.xv) p->o.xv=Z_dec(p->o.xv,1);
620 else p->st=STAND;
621 break;
623 if(p->o.xv<PL_RUN && keys[p->kr]) {p->o.xv+=PL_RUN>>3;p->d=1;}
624 else if(PL_RUN>8)
625 SMK_gas(p->o.x,p->o.y-2,2,3,p->o.xv+p->o.vx,p->o.yv+p->o.vy,32);
626 if(p->o.xv>-PL_RUN && keys[p->kl]) {p->o.xv-=PL_RUN>>3;p->d=0;}
627 else if(PL_RUN>8)
628 SMK_gas(p->o.x,p->o.y-2,2,3,p->o.xv+p->o.vx,p->o.yv+p->o.vy,32);
629 break;
630 case STAND:
631 chgwpn(p);fire(p);jump(p,st);
632 if(p_fly)
633 SMK_gas(p->o.x,p->o.y-2,2,3,p->o.xv+p->o.vx,p->o.yv+p->o.vy,128);
634 if(keys[p->kl]) {p->st=GO;p->s=0;p->d=0;}
635 else if(keys[p->kr]) {p->st=GO;p->s=0;p->d=1;}
636 break;
637 case DEAD:
638 case MESS:
639 case OUT:
640 p->o.xv=Z_dec(p->o.xv,1);
641 if(keys[p->ku] || keys[p->kd] || keys[p->kl] || keys[p->kr] ||
642 keys[p->kf] || keys[p->kj] || keys[p->kp] || keys[p->kwl] || keys[p->kwr]) {
643 if(p->st!=OUT) MN_spawn_deadpl(&p->o,p->color,(p->st==MESS)?1:0);
644 PL_restore(p);
645 if(g_dm) {G_respawn_player(p);break;}
646 if(!_2pl) {
647 if(--p->lives==0) {G_start();break;}
648 else{p->o.x=dm_pos[0].x;p->o.y=dm_pos[0].y;p->d=dm_pos[0].d;}
649 p->drawst|=PL_DRAWLIVES;
651 if(p->id==-1)
652 {p->o.x=dm_pos[0].x;p->o.y=dm_pos[0].y;p->d=dm_pos[0].d;}
653 else {p->o.x=dm_pos[1].x;p->o.y=dm_pos[1].y;p->d=dm_pos[1].d;}
654 }break;
655 case FALL:
656 if(--p->s<=0) p->st=OUT;
657 break;
661 static int standspr(player_t *p) {
662 if(p->f&PLF_UP) return 'X';
663 if(p->f&PLF_DOWN) return 'Z';
664 return 'E';
667 static int wpnspr(player_t *p) {
668 if(p->f&PLF_UP) return 'C';
669 if(p->f&PLF_DOWN) return 'E';
670 return 'A';
673 void PL_draw(player_t *p) {
674 int s,w,wx,wy;
675 static int wytab[]={-1,-2,-1,0};
677 s='A';w=0;wx=wy=0;
678 switch(p->st) {
679 case STAND:
680 if(p->f&PLF_FIRE) {s=standspr(p)+1;w=wpnspr(p)+1;}
681 else if(p->pain) {s='G';w='A';wx=p->d?2:-2;wy=1;}
682 else {s=standspr(p);w=wpnspr(p);}
683 break;
684 case DEAD:
685 s='N';break;
686 case MESS:
687 s='W';break;
688 case GO:
689 if(p->pain) {s='G';w='A';wx=p->d?2:-2;wy=1;}
690 else {
691 s=goanim[p->s/8];w=(p->f&PLF_FIRE)?'B':'A';
692 wx=p->d?2:-2;wy=1+wytab[s-'A'];
694 break;
695 case DIE:
696 s=dieanim[p->s];break;
697 case SLOP:
698 s=slopanim[p->s];break;
699 case OUT:
700 s=0;break;
702 if(p->wpn==0) w=0;
703 if(w) Z_drawspr(p->o.x+wx,p->o.y+wy,wpn[p->wpn][w-'A'],p->d);
704 if(s) Z_drawmanspr(p->o.x,p->o.y,spr[(s-'A')*2+p->d],sprd[(s-'A')*2+p->d],p->color);
707 void *PL_getspr(int s,int d) {
708 return spr[(s-'A')*2+d];
711 static void chk_bfg(player_t *p,int x,int y) {
712 int dx,dy;
714 if(aitime) return;
715 switch(p->st) {
716 case DIE: case SLOP: case FALL:
717 case DEAD: case MESS: case OUT:
718 return;
720 dx=p->o.x-x;dy=p->o.y-p->o.h/2-y;
721 if(dx*dx+dy*dy<=1600) {
722 aitime=Z_sound(aisnd[rand()%3],128)*4;
726 void bfg_fly(int x,int y,int o) {
727 // if(!g_dm) return;
728 if(o!=-1) chk_bfg(&pl1,x,y);
729 if(_2pl) if(o!=-2) chk_bfg(&pl2,x,y);
730 if(o==-1 || o==-2) MN_warning(x-50,y-50,x+50,y+50);
733 void PL_drawst(player_t *p) {
734 V_setrect(WD,120,w_o,HT);Z_clrst();
735 int i;
737 if(p->drawst&PL_DRAWAIR)
738 if (p->air<PL_AIR)//
739 Z_drawstair(p->air);
740 if(p->drawst&PL_DRAWLIFE)
741 Z_drawstprcnt(0,p->life);
742 if(p->drawst&PL_DRAWARMOR)
743 Z_drawstprcnt(1,p->armor);
744 if(p->drawst&PL_DRAWWPN) {
745 switch(p->wpn) {
746 case 2: case 5:
747 i=p->ammo;break;
748 case 3: case 4: case 9:
749 i=p->shel;break;
750 case 6:
751 i=p->rock;break;
752 case 10:
753 i=p->fuel;break;
754 case 7: case 8:
755 i=p->cell;break;
757 Z_drawstwpn(p->wpn,i);
759 if(p->drawst&PL_DRAWFRAG) Z_drawstnum(p->frag);
760 if(p->drawst&PL_DRAWKEYS) Z_drawstkeys(p->keys);
761 if(!_2pl) if(p->drawst&PL_DRAWLIVES) Z_drawstlives(p->lives);