shift pistol HUD sprite
[d2d-psx.git] / src / player.c
bloba2dbf98bf4f94a9904f27d33fbc7c91541976c5d
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 PSX project.
8 * Doom2D PSX 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 PSX 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
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 {
60 STAND, GO, DIE, SLOP, DEAD, MESS, OUT, FALL
63 typedef void fire_f (int, int, int, int, int);
65 player_t pl1, pl2;
66 static int aitime;
67 static void * aisnd[3];
68 static void * pdsnd[5];
70 static void * spr[27 * 2], * snd[11];
71 static char sprd[27 * 2];
72 static void * wpn[11][6];
73 static byte goanim[] = "BDACDA",
74 dieanim[] = "HHHHIIIIJJJJKKKKLLLLMMMM",
75 slopanim[] = "OOPPQQRRSSTTUUVVWW";
77 const u_long plk_ofs[PLK_NUMKEYS] = {
78 offsetof(player_t, ku), offsetof(player_t, kd),
79 offsetof(player_t, kl), offsetof(player_t, kr),
80 offsetof(player_t, kf), offsetof(player_t, kj),
81 offsetof(player_t, kwl), offsetof(player_t, kwr),
82 offsetof(player_t, kp), offsetof(player_t, ks),
83 offsetof(player_t, kh)
86 const char *plk_names[PLK_NUMKEYS] = {
87 "UP", "DOWN", "LEFT", "RIGHT", "FIRE",
88 "JUMP", "PREV WPN", "NEXT WPN", "USE", "FLIP",
89 "STRAFE"
92 static int nonz(int a) {
93 return (a) ? a : 1;
96 static int firediry(player_t * p) {
97 if (p->f & PLF_UP)
98 return -42;
100 if (p->f & PLF_DOWN)
101 return 19;
103 return 0;
106 static void fire(player_t * p) {
107 static fire_f * ff[11] = {
108 WP_pistol, WP_pistol, WP_pistol, WP_shotgun, WP_dshotgun,
109 WP_mgun, WP_rocket, WP_plasma, WP_bfgshot, WP_shotgun, WP_pistol
111 static int ft[11] = { 5, 2, 6, 18, 36, 2, 12, 2, 0, 2, 1 };
113 if (p->cwpn)
114 return;
116 if (p->wpn == 8) {
117 if (!p->fire) {
118 if (K_held(p->kf) && (p->cell >= 40)) {
119 Z_sound(snd[5], 128);
120 p->fire = 21;
121 p->cell -= 40;
122 p->drawst |= PL_DRAWWPN;
123 return;
124 } else {
125 return;
128 if (p->fire == 1)
129 p->cwpn = 12;
130 else
131 return;
132 } else if (p->wpn == 1) {
133 if (!p->csnd) {
134 if (!K_held(p->kf)) {
135 Z_sound(snd[7], 128);
136 p->csnd = 13;
137 p->cidl = 1;
138 return;
141 if (K_held(p->kf) && !p->fire) {
142 p->fire = 2;
143 WP_chainsaw(p->o.x + ((p->d) ? 4 : -4), p->o.y, (g_dm) ? 9 : 3, p->id);
144 if (!p->csnd || p->cidl) {
145 Z_sound(snd[8], 128);
146 p->csnd = 29;
147 p->cidl = 0;
150 return;
151 } else if (p->fire) {
152 return;
154 if (K_held(p->kf) || (p->wpn == 8)) {
155 switch (p->wpn) {
156 case 2:
157 case 5:
158 if (!p->ammo)
159 return;
161 --p->ammo;
162 p->drawst |= PL_DRAWWPN;
163 break;
165 case 3:
166 case 9:
167 if (!p->shel)
168 return;
170 --p->shel;
171 p->drawst |= PL_DRAWWPN;
172 break;
174 case 4:
175 if (p->shel < 2)
176 return;
178 p->shel -= 2;
179 p->drawst |= PL_DRAWWPN;
180 break;
182 case 6:
183 if (!p->rock)
184 return;
186 --p->rock;
187 p->drawst |= PL_DRAWWPN;
188 break;
190 case 7:
191 if (!p->cell)
192 return;
194 --p->cell;
195 p->drawst |= PL_DRAWWPN;
196 break;
198 case 10:
199 if (!p->fuel)
200 return;
202 --p->fuel;
203 p->drawst |= PL_DRAWWPN;
204 break;
206 if (p->wpn == 10) {
207 WP_ognemet(p->o.x, p->o.y - 15, p->o.x + ((p->d) ? 30 : -30), p->o.y - 15 + firediry(p),
208 p->o.xv + p->o.vx, p->o.yv + p->o.vy, p->id);
209 } else if (p->wpn >= 1) {
210 ff[p->wpn] (p->o.x, p->o.y - 15, p->o.x + ((p->d) ? 30 : -30),
211 p->o.y - 15 + firediry(p), p->id);
212 } else {
213 WP_punch(p->o.x + ((p->d) ? 4 : -4), p->o.y, 3, p->id);
215 p->fire = ft[p->wpn];
216 if (p->wpn >= 2)
217 p->f |= PLF_FIRE;
219 } /* fire */
221 static void chgwpn(player_t * p) {
222 if (p->cwpn)
223 return;
225 if (p->fire && (p->wpn != 1))
226 return;
228 if (K_held(p->kwl)) {
229 do {
230 if (--p->wpn < 0)
231 p->wpn = 10;
232 } while (!(p->wpns & (1 << p->wpn)));
233 p->cwpn = 3;
234 } else if (K_held(p->kwr)) {
235 do {
236 if (++p->wpn > 10)
237 p->wpn = 0;
238 } while (!(p->wpns & (1 << p->wpn)));
239 p->cwpn = 3;
241 if (p->cwpn) {
242 p->drawst |= PL_DRAWWPN;
243 p->fire = 0;
244 if (p->wpn == 1)
245 Z_sound(snd[6], 128);
249 static void jump(player_t * p, int st) {
250 if (Z_canbreathe(p->o.x, p->o.y, p->o.r, p->o.h)) {
251 if (p->air < PL_AIR) {
252 p->air = PL_AIR;
253 p->drawst |= PL_DRAWAIR;
255 } else {
256 if (--p->air < -9) {
257 p->air = 0;
258 PL_hit(p, 10, -3, HIT_WATER);
259 } else if ((p->air & 31) == 0) {
260 FX_bubble(p->o.x, p->o.y - 20, 0, 0, 5);
262 p->drawst |= PL_DRAWAIR;
264 if (K_held(p->kj)) {
265 if (p_fly) {
266 p->o.yv = -PL_FLYUP;
267 } else {
268 if (Z_canstand(p->o.x, p->o.y, p->o.r))
269 p->o.yv = -PL_JUMP;
270 else if (st & Z_INWATER)
271 p->o.yv = -PL_SWUP;
276 int PL_isdead(player_t * p) {
277 switch (p->st) {
278 case DEAD:
279 case MESS:
280 case OUT:
281 return 1;
283 return 0;
286 void PL_init(void) {
287 p_immortal = 0;
288 PL_JUMP = 10;
289 PL_RUN = 8;
290 aitime = 0;
293 void PL_alloc(void) {
294 int i, j;
295 static char nm[][6] = {
296 "OOF",
297 "PLPAIN",
298 "PLDETH",
299 "SLOP",
300 "PDIEHI",
301 "BFG",
302 "SAWUP",
303 "SAWIDL",
304 "SAWFUL",
305 "SAWHIT",
306 "PLFALL"
308 static char s[6];
310 for (i = 0; i < 27; ++i) {
311 spr[i * 2] = Z_getspr("PLAY", i, 1, sprd + i * 2);
312 spr[i * 2 + 1] = Z_getspr("PLAY", i, 2, sprd + i * 2 + 1);
314 memcpy(s, "PWPx", 4);
315 for (i = 1; i < 11; ++i) {
316 s[3] = ((i < 10) ? '0' : ('A' - 10)) + i;
317 for (j = 0; j < 6; ++j)
318 wpn[i][j] = Z_getspr(s, j, 1, NULL);
320 for (i = 0; i < 11; ++i)
321 snd[i] = Z_getsnd(nm[i]);
322 memcpy(s, "AIx", 4);
323 for (i = 0; i < 3; ++i) {
324 s[2] = i + '1';
325 aisnd[i] = Z_getsnd(s);
327 memcpy(s, "PLDTHx", 6);
328 for (i = 0; i < 5; ++i) {
329 s[5] = i + '1';
330 pdsnd[i] = Z_getsnd(s);
332 } /* PL_alloc */
334 void PL_restore(player_t * p) {
335 p->o.xv = p->o.yv = p->o.vx = p->o.vy = 0;
336 p->o.r = PL_RAD;
337 p->o.h = PL_HT;
338 p->pain = 0;
339 p->invl = p->suit = 0;
340 if (!g_loaded) {
341 switch (p->st) {
342 case DEAD:
343 case MESS:
344 case OUT:
345 case DIE:
346 case SLOP:
347 case FALL:
348 p->life = 100;
349 p->armor = 0;
350 p->air = PL_AIR;
351 p->wpns = 5;
352 p->wpn = 2;
353 p->ammo = 50;
354 p->fuel = p->shel = p->rock = p->cell = 0;
355 p->amul = 1;
358 p->st = STAND;
359 p->fire = p->cwpn = p->csnd = p->cidl = 0;
360 p->f = 0;
361 p->drawst = 0xFF;
362 p->looky = 0;
363 p->keys = (g_dm) ? 0x70 : 0;
366 void PL_reset(void) {
367 pl1.st = pl2.st = DEAD;
368 pl1.frag = pl2.frag = 0;
371 void PL_spawn(player_t * p, int x, int y, signed char d) {
372 PL_restore(p);
373 p->o.x = x;
374 p->o.y = y;
375 p->d = d;
376 p->kills = p->secrets = 0;
379 int PL_hit(player_t * p, int d, int o, int t) {
380 if (!d)
381 return 0;
383 switch (p->st) {
384 case DIE:
385 case SLOP:
386 case DEAD:
387 case MESS:
388 case OUT:
389 case FALL:
390 return 0;
392 if (t == HIT_TRAP) {
393 if (!p_immortal) {
394 p->armor = 0;
395 p->life = -100;
397 } else if ((t != HIT_ROCKET) && (t != HIT_ELECTRO)) {
398 if (p->id == -1) {
399 if (o == -1)
400 return 0;
401 } else if (o == -2) {
402 return 0;
405 if ((t != HIT_WATER) && (t != HIT_ELECTRO))
406 DOT_blood(p->o.x, p->o.y - 15, hit_xv, hit_yv, d * 2);
407 else if (t == HIT_WATER)
408 FX_bubble(p->o.x, p->o.y - 20, 0, 0, d / 2);
409 if (p_immortal || p->invl)
410 return 1;
412 p->hit += d;
413 p->hito = o;
414 return 1;
415 } /* PL_hit */
417 void PL_damage(player_t * p) {
418 int i;
420 if (!p->hit && (p->life > 0))
421 return;
423 switch (p->st) {
424 case DIE:
425 case SLOP:
426 case DEAD:
427 case MESS:
428 case OUT:
429 case FALL:
430 return;
432 i = p->hit * p->life / nonz(p->armor * 3 / 4 + p->life);
433 p->pain += p->hit;
434 p->drawst |= PL_DRAWLIFE | PL_DRAWARMOR;
435 if ((p->armor -= p->hit - i) < 0) {
436 p->life += p->armor;
437 p->armor = 0;
439 if ((p->life -= i) <= 0) {
440 if (p->life > -30) {
441 p->st = DIE;
442 p->s = 0;
443 Z_sound(pdsnd[rand() % 5], 128);
444 } else {
445 p->st = SLOP;
446 p->s = 0;
447 Z_sound(snd[3], 128);
449 if (p->amul > 1)
450 IT_spawn(p->o.x, p->o.y, I_BPACK);
451 if (!g_dm) {
452 if (p->keys & 16)
453 IT_spawn(p->o.x, p->o.y, I_KEYR);
454 if (p->keys & 32)
455 IT_spawn(p->o.x, p->o.y, I_KEYG);
456 if (p->keys & 64)
457 IT_spawn(p->o.x, p->o.y, I_KEYB);
459 for (i = 1, p->wpns >>= 1; i < 11; ++i, p->wpns >>= 1) {
460 if (i != 2) {
461 if (p->wpns & 1)
462 IT_spawn(p->o.x, p->o.y, wp_it[i]);
465 p->wpns = 5;
466 p->wpn = 2;
467 p->f |= PLF_PNSND;
468 p->drawst |= PL_DRAWWPN;
469 if (g_dm && _2pl) {
470 if (p->id == -1) {
471 if (p->hito == -2) {
472 ++pl2.kills;
473 ++pl2.frag;
474 } else if (p->hito == -1) {
475 --pl1.frag;
477 } else {
478 if (p->hito == -1) {
479 ++pl1.kills;
480 ++pl1.frag;
481 } else if (p->hito == -2) {
482 --pl2.frag;
485 pl1.drawst |= PL_DRAWFRAG;
486 if (_2pl)
487 pl2.drawst |= PL_DRAWFRAG;
489 p->life = 0;
490 return;
492 } /* PL_damage */
494 void PL_cry(player_t * p) {
495 Z_sound(snd[(p->pain > 20) ? 1 : 0], 128);
496 p->f |= PLF_PNSND;
499 int PL_give(player_t * p, int t) {
500 int i;
502 switch (p->st) {
503 case DIE:
504 case SLOP:
505 case DEAD:
506 case MESS:
507 case OUT:
508 return 0;
510 switch (t) {
511 case I_STIM:
512 case I_MEDI:
513 if (p->life >= 100)
514 return 0;
516 if ((p->life += ((t == I_MEDI) ? 25 : 10)) > 100)
517 p->life = 100;
518 p->drawst |= PL_DRAWLIFE;
519 return 1;
521 case I_CLIP:
522 if (p->ammo >= 200 * p->amul)
523 return 0;
525 if ((p->ammo += 10) > 200 * p->amul)
526 p->ammo = 200 * p->amul;
527 p->drawst |= PL_DRAWWPN;
528 return 1;
530 case I_AMMO:
531 if (p->ammo >= 200 * p->amul)
532 return 0;
534 if ((p->ammo += 50) > 200 * p->amul)
535 p->ammo = 200 * p->amul;
536 p->drawst |= PL_DRAWWPN;
537 return 1;
539 case I_SHEL:
540 if (p->shel >= 50 * p->amul)
541 return 0;
543 if ((p->shel += 4) > 50 * p->amul)
544 p->shel = 50 * p->amul;
545 p->drawst |= PL_DRAWWPN;
546 return 1;
548 case I_SBOX:
549 if (p->shel >= 50 * p->amul)
550 return 0;
552 if ((p->shel += 25) > 50 * p->amul)
553 p->shel = 50 * p->amul;
554 p->drawst |= PL_DRAWWPN;
555 return 1;
557 case I_ROCKET:
558 if (p->rock >= 50 * p->amul)
559 return 0;
561 if ((++p->rock) > 50 * p->amul)
562 p->rock = 50 * p->amul;
563 p->drawst |= PL_DRAWWPN;
564 return 1;
566 case I_RBOX:
567 if (p->rock >= 50 * p->amul)
568 return 0;
570 if ((p->rock += 5) > 50 * p->amul)
571 p->rock = 50 * p->amul;
572 p->drawst |= PL_DRAWWPN;
573 return 1;
575 case I_CELL:
576 if (p->cell >= 300 * p->amul)
577 return 0;
579 if ((p->cell += 40) > 300 * p->amul)
580 p->cell = 300 * p->amul;
581 p->drawst |= PL_DRAWWPN;
582 return 1;
584 case I_CELP:
585 if (p->cell >= 300 * p->amul)
586 return 0;
588 if ((p->cell += 100) > 300 * p->amul)
589 p->cell = 300 * p->amul;
590 p->drawst |= PL_DRAWWPN;
591 return 1;
593 case I_BPACK:
594 if (p->amul == 1) {
595 p->amul = 2;
596 i = 1;
597 } else {
598 i = 0;
600 i |= PL_give(p, I_CLIP);
601 i |= PL_give(p, I_SHEL);
602 i |= PL_give(p, I_ROCKET);
603 i |= PL_give(p, I_CELL);
604 return i;
606 case I_CSAW:
607 if (!(p->wpns & 2)) {
608 p->wpns |= 2;
609 p->drawst |= PL_DRAWWPN;
610 return 1;
612 return 0;
614 case I_GUN2:
615 i = PL_give(p, I_SHEL);
616 if (!(p->wpns & 512)) {
617 p->wpns |= 512;
618 i = 1;
620 p->drawst |= PL_DRAWWPN;
621 return i;
623 case I_SGUN:
624 i = PL_give(p, I_SHEL);
625 if (!(p->wpns & 8)) {
626 p->wpns |= 8;
627 i = 1;
629 p->drawst |= PL_DRAWWPN;
630 return i;
632 case I_SGUN2:
633 i = PL_give(p, I_SHEL);
634 if (!(p->wpns & 16)) {
635 p->wpns |= 16;
636 i = 1;
638 p->drawst |= PL_DRAWWPN;
639 return i;
641 case I_MGUN:
642 i = PL_give(p, I_AMMO);
643 if (!(p->wpns & 32)) {
644 p->wpns |= 32;
645 i = 1;
647 p->drawst |= PL_DRAWWPN;
648 return i;
650 case I_LAUN:
651 i = PL_give(p, I_ROCKET);
652 i |= PL_give(p, I_ROCKET);
653 if (!(p->wpns & 64)) {
654 p->wpns |= 64;
655 i = 1;
657 p->drawst |= PL_DRAWWPN;
658 return i;
660 case I_PLAS:
661 i = PL_give(p, I_CELL);
662 if (!(p->wpns & 128)) {
663 p->wpns |= 128;
664 i = 1;
666 p->drawst |= PL_DRAWWPN;
667 return i;
669 case I_BFG:
670 i = PL_give(p, I_CELL);
671 if (!(p->wpns & 256)) {
672 p->wpns |= 256;
673 i = 1;
675 p->drawst |= PL_DRAWWPN;
676 return i;
678 case I_ARM1:
679 if (p->armor >= 100)
680 return 0;
682 p->armor = 100;
683 p->drawst |= PL_DRAWARMOR;
684 return 1;
686 case I_ARM2:
687 if (p->armor >= 200)
688 return 0;
690 p->armor = 200;
691 p->drawst |= PL_DRAWARMOR;
692 return 1;
694 case I_MEGA:
695 i = 0;
696 if (p->life < 200) {
697 p->life = 200;
698 p->drawst |= PL_DRAWLIFE;
699 i = 1;
701 if (p->armor < 200) {
702 p->armor = 200;
703 p->drawst |= PL_DRAWARMOR;
704 i = 1;
706 return i;
708 case I_SUPER:
709 if (p->life < 200) {
710 p->life = min(p->life + 100, 200);
711 p->drawst |= PL_DRAWLIFE;
712 return 1;
714 return 0;
716 case I_INVL:
717 p->invl = PL_POWERUP_TIME;
718 return 1;
720 case I_SUIT:
721 p->suit = PL_POWERUP_TIME;
722 return 1;
724 case I_AQUA:
725 if (p->air >= PL_AQUA_AIR)
726 return 0;
728 p->air = PL_AQUA_AIR;
729 p->drawst |= PL_DRAWAIR;
730 return 1;
732 case I_KEYR:
733 if (p->keys & 16)
734 return 0;
736 p->keys |= 16;
737 p->drawst |= PL_DRAWKEYS;
738 return 1;
740 case I_KEYG:
741 if (p->keys & 32)
742 return 0;
744 p->keys |= 32;
745 p->drawst |= PL_DRAWKEYS;
746 return 1;
748 case I_KEYB:
749 if (p->keys & 64)
750 return 0;
752 p->keys |= 64;
753 p->drawst |= PL_DRAWKEYS;
754 return 1;
756 default:
757 return 0;
759 } /* PL_give */
761 void PL_act(player_t * p) {
762 int st;
764 if (--aitime < 0)
765 aitime = 0;
766 SW_press(p->o.x, p->o.y, p->o.r, p->o.h, 4 | p->keys, p->id);
767 if (!p->suit) {
768 if ((g_time & 15) == 0)
769 PL_hit(p, Z_getacid(p->o.x, p->o.y, p->o.r, p->o.h), -3, HIT_SOME);
771 if ((p->st != FALL) && (p->st != OUT)) {
772 if (((st = Z_moveobj(&p->o)) & Z_FALLOUT) && (p->o.y >= FLDH * CELH + 50)) {
773 switch (p->st) {
774 case DEAD:
775 case MESS:
776 case DIE:
777 case SLOP:
778 p->s = 5;
779 break;
781 default:
782 p->s = Z_sound(snd[10], 128);
783 if (g_dm)
784 --p->frag;
786 p->st = FALL;
788 } else {
789 st = 0;
791 if (st & Z_HITWATER)
792 Z_splash(&p->o, PL_RAD + PL_HT);
793 if (p->f & PLF_FIRE) {
794 if (p->fire != 2)
795 p->f -= PLF_FIRE;
797 if (K_held(p->ku)) {
798 p->f |= PLF_UP;
799 p->looky -= 5;
800 } else {
801 p->f &= 0xFFFF - PLF_UP;
802 if (K_held(p->kd)) {
803 p->f |= PLF_DOWN;
804 p->looky += 5;
805 } else {
806 p->f &= 0xFFFF - PLF_DOWN;
807 p->looky = Z_dec(p->looky, 5);
810 if (K_held(p->kp))
811 SW_press(p->o.x, p->o.y, p->o.r, p->o.h, 1 | p->keys, p->id);
812 if (p->fire)
813 --p->fire;
814 if (p->cwpn)
815 --p->cwpn;
816 if (p->csnd)
817 --p->csnd;
818 if (p->invl)
819 --p->invl;
820 if (p->suit)
821 --p->suit;
822 switch (p->st) {
823 case DIE:
824 p->o.h = 7;
825 if (!dieanim[++p->s]) {
826 p->st = DEAD;
827 MN_killedp();
829 p->o.xv = Z_dec(p->o.xv, 1);
830 break;
832 case SLOP:
833 p->o.h = 6;
834 if (!slopanim[++p->s]) {
835 p->st = MESS;
836 MN_killedp();
838 p->o.xv = Z_dec(p->o.xv, 1);
839 break;
841 case GO:
842 chgwpn(p);
843 fire(p);
844 jump(p, st);
845 if (p_fly)
846 SMK_gas(p->o.x, p->o.y - 2, 2, 3, p->o.xv + p->o.vx, p->o.yv + p->o.vy, 128);
847 if ((p->s += abs(p->o.xv) / 2) >= 24)
848 p->s %= 24;
849 if (!K_held(p->kl) && !K_held(p->kr)) {
850 if (p->o.xv)
851 p->o.xv = Z_dec(p->o.xv, 1);
852 else
853 p->st = STAND;
854 break;
856 if (K_held(p->kr)) {
857 if (p->o.xv < PL_RUN)
858 p->o.xv += PL_RUN >> 3;
859 else if (PL_RUN > 8)
860 SMK_gas(p->o.x, p->o.y - 2, 2, 3, p->o.xv + p->o.vx, p->o.yv + p->o.vy, 32);
861 if (!K_held(p->kh)) p->d = !K_held(p->ks);
863 if (K_held(p->kl)) {
864 if (p->o.xv > -PL_RUN)
865 p->o.xv -= PL_RUN >> 3;
866 else if (PL_RUN > 8)
867 SMK_gas(p->o.x, p->o.y - 2, 2, 3, p->o.xv + p->o.vx, p->o.yv + p->o.vy, 32);
868 if (!K_held(p->kh)) p->d = !!K_held(p->ks);
870 break;
872 case STAND:
873 chgwpn(p);
874 fire(p);
875 jump(p, st);
876 if (p_fly)
877 SMK_gas(p->o.x, p->o.y - 2, 2, 3, p->o.xv + p->o.vx, p->o.yv + p->o.vy, 128);
878 if (K_held(p->kl)) {
879 p->st = GO;
880 p->s = 0;
881 if (!K_held(p->kh)) p->d = !!K_held(p->ks);
882 } else if (K_held(p->kr)) {
883 p->st = GO;
884 p->s = 0;
885 if (!K_held(p->kh)) p->d = !K_held(p->ks);
887 break;
889 case DEAD:
890 case MESS:
891 case OUT:
892 p->o.xv = Z_dec(p->o.xv, 1);
893 if (K_held(p->ku) || K_held(p->kd) || K_held(p->kl) || K_held(p->kr) ||
894 K_held(p->kf) || K_held(p->kj) || K_held(p->kp) || K_held(p->kwl) || K_held(p->kwr))
896 if (p->st != OUT)
897 MN_spawn_deadpl(&p->o, p->color, (p->st == MESS) ? 1 : 0);
898 PL_restore(p);
899 if (g_dm) {
900 G_respawn_player(p);
901 break;
903 if (!_2pl) {
904 G_start();
905 } else {
906 if (p->id == -1) {
907 p->o.x = dm_pos[0].x;
908 p->o.y = dm_pos[0].y;
909 p->d = dm_pos[0].d;
910 } else {
911 p->o.x = dm_pos[1].x;
912 p->o.y = dm_pos[1].y;
913 p->d = dm_pos[1].d;
917 break;
919 case FALL:
920 if (--p->s <= 0)
921 p->st = OUT;
922 break;
924 } /* PL_act */
926 static int standspr(player_t * p) {
927 if (p->f & PLF_UP)
928 return 'X';
930 if (p->f & PLF_DOWN)
931 return 'Z';
933 return 'E';
936 static int wpnspr(player_t * p) {
937 if (p->f & PLF_UP)
938 return 'C';
940 if (p->f & PLF_DOWN)
941 return 'E';
943 return 'A';
946 void PL_draw(player_t * p) {
947 int s, w, wx, wy;
948 static int wytab[] = { -1, -2, -1, 0 };
950 s = 'A';
951 w = 0;
952 wx = wy = 0;
953 switch (p->st) {
954 case STAND:
955 if (p->f & PLF_FIRE) {
956 s = standspr(p) + 1;
957 w = wpnspr(p) + 1;
958 } else if (p->pain) {
959 s = 'G';
960 w = 'A';
961 wx = p->d ? 2 : -2;
962 wy = 1;
963 } else {
964 s = standspr(p);
965 w = wpnspr(p);
967 break;
969 case DEAD:
970 s = 'N';
971 break;
973 case MESS:
974 s = 'W';
975 break;
977 case GO:
978 if (p->pain) {
979 s = 'G';
980 w = 'A';
981 wx = p->d ? 2 : -2;
982 wy = 1;
983 } else {
984 s = goanim[p->s / 8];
985 w = (p->f & PLF_FIRE) ? 'B' : 'A';
986 wx = p->d ? 2 : -2;
987 wy = 1 + wytab[s - 'A'];
989 break;
991 case DIE:
992 s = dieanim[p->s];
993 break;
995 case SLOP:
996 s = slopanim[p->s];
997 break;
999 case OUT:
1000 s = 0;
1001 break;
1003 if (p->wpn == 0)
1004 w = 0;
1005 if (w)
1006 Z_drawspr(p->o.x + wx, p->o.y + wy, wpn[p->wpn][w - 'A'], p->d);
1007 if (s)
1008 Z_drawmanspr(p->o.x, p->o.y, spr[(s - 'A') * 2 + p->d], sprd[(s - 'A') * 2 + p->d], p->color);
1009 } /* PL_draw */
1011 void * PL_getspr(int s, int d) {
1012 return spr[(s - 'A') * 2 + d];
1015 static void chk_bfg(player_t * p, int x, int y) {
1016 int dx, dy;
1018 if (aitime)
1019 return;
1021 switch (p->st) {
1022 case DIE:
1023 case SLOP:
1024 case FALL:
1025 case DEAD:
1026 case MESS:
1027 case OUT:
1028 return;
1030 dx = p->o.x - x;
1031 dy = p->o.y - p->o.h / 2 - y;
1032 if (dx * dx + dy * dy <= 1600)
1033 aitime = Z_sound(aisnd[rand() % 3], 128) * 4;
1036 void bfg_fly(int x, int y, int o) {
1037 // if(!g_dm) return;
1038 if (o != -1)
1039 chk_bfg(&pl1, x, y);
1040 if (_2pl) {
1041 if (o != -2)
1042 chk_bfg(&pl2, x, y);
1044 if ((o == -1) || (o == -2))
1045 MN_warning(x - 50, y - 50, x + 50, y + 50);
1048 void PL_drawst(player_t * p) {
1049 int i;
1050 V_setrect(0, SCRW, w_o, HT);
1051 Z_clrst();
1053 if (p->drawst & PL_DRAWAIR)
1054 Z_drawstair(p->air);
1055 if (p->drawst & PL_DRAWLIFE)
1056 Z_drawstprcnt(0, p->life);
1057 if (p->drawst & PL_DRAWARMOR)
1058 Z_drawstprcnt(1, p->armor);
1059 if (p->drawst & PL_DRAWWPN) {
1060 switch (p->wpn) {
1061 case 2:
1062 case 5:
1063 i = p->ammo;
1064 break;
1066 case 3:
1067 case 4:
1068 case 9:
1069 i = p->shel;
1070 break;
1072 case 6:
1073 i = p->rock;
1074 break;
1076 case 10:
1077 i = p->fuel;
1078 break;
1080 case 7:
1081 case 8:
1082 i = p->cell;
1083 break;
1085 Z_drawstwpn(p->wpn, i);
1087 if (p->drawst & PL_DRAWFRAG)
1088 Z_drawstnum(p->frag);
1089 if (p->drawst & PL_DRAWKEYS)
1090 Z_drawstkeys(p->keys);
1091 } /* PL_drawst */