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
42 extern int hit_xv
, hit_yv
;
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 };
60 STAND
, GO
, DIE
, SLOP
, DEAD
, MESS
, OUT
, FALL
63 typedef void fire_f (int, int, int, int, int);
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",
92 static int nonz(int a
) {
96 static int firediry(player_t
* p
) {
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 };
118 if (K_held(p
->kf
) && (p
->cell
>= 40)) {
119 Z_sound(snd
[5], 128);
122 p
->drawst
|= PL_DRAWWPN
;
132 } else if (p
->wpn
== 1) {
134 if (!K_held(p
->kf
)) {
135 Z_sound(snd
[7], 128);
141 if (K_held(p
->kf
) && !p
->fire
) {
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);
151 } else if (p
->fire
) {
154 if (K_held(p
->kf
) || (p
->wpn
== 8)) {
162 p
->drawst
|= PL_DRAWWPN
;
171 p
->drawst
|= PL_DRAWWPN
;
179 p
->drawst
|= PL_DRAWWPN
;
187 p
->drawst
|= PL_DRAWWPN
;
195 p
->drawst
|= PL_DRAWWPN
;
203 p
->drawst
|= PL_DRAWWPN
;
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
);
213 WP_punch(p
->o
.x
+ ((p
->d
) ? 4 : -4), p
->o
.y
, 3, p
->id
);
215 p
->fire
= ft
[p
->wpn
];
221 static void chgwpn(player_t
* p
) {
225 if (p
->fire
&& (p
->wpn
!= 1))
228 if (K_held(p
->kwl
)) {
232 } while (!(p
->wpns
& (1 << p
->wpn
)));
234 } else if (K_held(p
->kwr
)) {
238 } while (!(p
->wpns
& (1 << p
->wpn
)));
242 p
->drawst
|= PL_DRAWWPN
;
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
) {
253 p
->drawst
|= PL_DRAWAIR
;
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
;
268 if (Z_canstand(p
->o
.x
, p
->o
.y
, p
->o
.r
))
270 else if (st
& Z_INWATER
)
276 int PL_isdead(player_t
* p
) {
293 void PL_alloc(void) {
295 static char nm
[][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
]);
323 for (i
= 0; i
< 3; ++i
) {
325 aisnd
[i
] = Z_getsnd(s
);
327 memcpy(s
, "PLDTHx", 6);
328 for (i
= 0; i
< 5; ++i
) {
330 pdsnd
[i
] = Z_getsnd(s
);
334 void PL_restore(player_t
* p
) {
335 p
->o
.xv
= p
->o
.yv
= p
->o
.vx
= p
->o
.vy
= 0;
339 p
->invl
= p
->suit
= 0;
354 p
->fuel
= p
->shel
= p
->rock
= p
->cell
= 0;
359 p
->fire
= p
->cwpn
= p
->csnd
= p
->cidl
= 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
) {
376 p
->kills
= p
->secrets
= 0;
379 int PL_hit(player_t
* p
, int d
, int o
, int t
) {
397 } else if ((t
!= HIT_ROCKET
) && (t
!= HIT_ELECTRO
)) {
401 } else if (o
== -2) {
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
)
417 void PL_damage(player_t
* p
) {
420 if (!p
->hit
&& (p
->life
> 0))
432 i
= p
->hit
* p
->life
/ nonz(p
->armor
* 3 / 4 + p
->life
);
434 p
->drawst
|= PL_DRAWLIFE
| PL_DRAWARMOR
;
435 if ((p
->armor
-= p
->hit
- i
) < 0) {
439 if ((p
->life
-= i
) <= 0) {
443 Z_sound(pdsnd
[rand() % 5], 128);
447 Z_sound(snd
[3], 128);
450 IT_spawn(p
->o
.x
, p
->o
.y
, I_BPACK
);
453 IT_spawn(p
->o
.x
, p
->o
.y
, I_KEYR
);
455 IT_spawn(p
->o
.x
, p
->o
.y
, I_KEYG
);
457 IT_spawn(p
->o
.x
, p
->o
.y
, I_KEYB
);
459 for (i
= 1, p
->wpns
>>= 1; i
< 11; ++i
, p
->wpns
>>= 1) {
462 IT_spawn(p
->o
.x
, p
->o
.y
, wp_it
[i
]);
468 p
->drawst
|= PL_DRAWWPN
;
474 } else if (p
->hito
== -1) {
481 } else if (p
->hito
== -2) {
485 pl1
.drawst
|= PL_DRAWFRAG
;
487 pl2
.drawst
|= PL_DRAWFRAG
;
494 void PL_cry(player_t
* p
) {
495 Z_sound(snd
[(p
->pain
> 20) ? 1 : 0], 128);
499 int PL_give(player_t
* p
, int t
) {
516 if ((p
->life
+= ((t
== I_MEDI
) ? 25 : 10)) > 100)
518 p
->drawst
|= PL_DRAWLIFE
;
522 if (p
->ammo
>= 200 * p
->amul
)
525 if ((p
->ammo
+= 10) > 200 * p
->amul
)
526 p
->ammo
= 200 * p
->amul
;
527 p
->drawst
|= PL_DRAWWPN
;
531 if (p
->ammo
>= 200 * p
->amul
)
534 if ((p
->ammo
+= 50) > 200 * p
->amul
)
535 p
->ammo
= 200 * p
->amul
;
536 p
->drawst
|= PL_DRAWWPN
;
540 if (p
->shel
>= 50 * p
->amul
)
543 if ((p
->shel
+= 4) > 50 * p
->amul
)
544 p
->shel
= 50 * p
->amul
;
545 p
->drawst
|= PL_DRAWWPN
;
549 if (p
->shel
>= 50 * p
->amul
)
552 if ((p
->shel
+= 25) > 50 * p
->amul
)
553 p
->shel
= 50 * p
->amul
;
554 p
->drawst
|= PL_DRAWWPN
;
558 if (p
->rock
>= 50 * p
->amul
)
561 if ((++p
->rock
) > 50 * p
->amul
)
562 p
->rock
= 50 * p
->amul
;
563 p
->drawst
|= PL_DRAWWPN
;
567 if (p
->rock
>= 50 * p
->amul
)
570 if ((p
->rock
+= 5) > 50 * p
->amul
)
571 p
->rock
= 50 * p
->amul
;
572 p
->drawst
|= PL_DRAWWPN
;
576 if (p
->cell
>= 300 * p
->amul
)
579 if ((p
->cell
+= 40) > 300 * p
->amul
)
580 p
->cell
= 300 * p
->amul
;
581 p
->drawst
|= PL_DRAWWPN
;
585 if (p
->cell
>= 300 * p
->amul
)
588 if ((p
->cell
+= 100) > 300 * p
->amul
)
589 p
->cell
= 300 * p
->amul
;
590 p
->drawst
|= PL_DRAWWPN
;
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
);
607 if (!(p
->wpns
& 2)) {
609 p
->drawst
|= PL_DRAWWPN
;
615 i
= PL_give(p
, I_SHEL
);
616 if (!(p
->wpns
& 512)) {
620 p
->drawst
|= PL_DRAWWPN
;
624 i
= PL_give(p
, I_SHEL
);
625 if (!(p
->wpns
& 8)) {
629 p
->drawst
|= PL_DRAWWPN
;
633 i
= PL_give(p
, I_SHEL
);
634 if (!(p
->wpns
& 16)) {
638 p
->drawst
|= PL_DRAWWPN
;
642 i
= PL_give(p
, I_AMMO
);
643 if (!(p
->wpns
& 32)) {
647 p
->drawst
|= PL_DRAWWPN
;
651 i
= PL_give(p
, I_ROCKET
);
652 i
|= PL_give(p
, I_ROCKET
);
653 if (!(p
->wpns
& 64)) {
657 p
->drawst
|= PL_DRAWWPN
;
661 i
= PL_give(p
, I_CELL
);
662 if (!(p
->wpns
& 128)) {
666 p
->drawst
|= PL_DRAWWPN
;
670 i
= PL_give(p
, I_CELL
);
671 if (!(p
->wpns
& 256)) {
675 p
->drawst
|= PL_DRAWWPN
;
683 p
->drawst
|= PL_DRAWARMOR
;
691 p
->drawst
|= PL_DRAWARMOR
;
698 p
->drawst
|= PL_DRAWLIFE
;
701 if (p
->armor
< 200) {
703 p
->drawst
|= PL_DRAWARMOR
;
710 p
->life
= min(p
->life
+ 100, 200);
711 p
->drawst
|= PL_DRAWLIFE
;
717 p
->invl
= PL_POWERUP_TIME
;
721 p
->suit
= PL_POWERUP_TIME
;
725 if (p
->air
>= PL_AQUA_AIR
)
728 p
->air
= PL_AQUA_AIR
;
729 p
->drawst
|= PL_DRAWAIR
;
737 p
->drawst
|= PL_DRAWKEYS
;
745 p
->drawst
|= PL_DRAWKEYS
;
753 p
->drawst
|= PL_DRAWKEYS
;
761 void PL_act(player_t
* p
) {
766 SW_press(p
->o
.x
, p
->o
.y
, p
->o
.r
, p
->o
.h
, 4 | p
->keys
, p
->id
);
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)) {
782 p
->s
= Z_sound(snd
[10], 128);
792 Z_splash(&p
->o
, PL_RAD
+ PL_HT
);
793 if (p
->f
& PLF_FIRE
) {
801 p
->f
&= 0xFFFF - PLF_UP
;
806 p
->f
&= 0xFFFF - PLF_DOWN
;
807 p
->looky
= Z_dec(p
->looky
, 5);
811 SW_press(p
->o
.x
, p
->o
.y
, p
->o
.r
, p
->o
.h
, 1 | p
->keys
, p
->id
);
825 if (!dieanim
[++p
->s
]) {
829 p
->o
.xv
= Z_dec(p
->o
.xv
, 1);
834 if (!slopanim
[++p
->s
]) {
838 p
->o
.xv
= Z_dec(p
->o
.xv
, 1);
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)
849 if (!K_held(p
->kl
) && !K_held(p
->kr
)) {
851 p
->o
.xv
= Z_dec(p
->o
.xv
, 1);
857 if (p
->o
.xv
< PL_RUN
)
858 p
->o
.xv
+= PL_RUN
>> 3;
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
);
864 if (p
->o
.xv
> -PL_RUN
)
865 p
->o
.xv
-= PL_RUN
>> 3;
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
);
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);
881 if (!K_held(p
->kh
)) p
->d
= !!K_held(p
->ks
);
882 } else if (K_held(p
->kr
)) {
885 if (!K_held(p
->kh
)) p
->d
= !K_held(p
->ks
);
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
))
897 MN_spawn_deadpl(&p
->o
, p
->color
, (p
->st
== MESS
) ? 1 : 0);
907 p
->o
.x
= dm_pos
[0].x
;
908 p
->o
.y
= dm_pos
[0].y
;
911 p
->o
.x
= dm_pos
[1].x
;
912 p
->o
.y
= dm_pos
[1].y
;
926 static int standspr(player_t
* p
) {
936 static int wpnspr(player_t
* p
) {
946 void PL_draw(player_t
* p
) {
948 static int wytab
[] = { -1, -2, -1, 0 };
955 if (p
->f
& PLF_FIRE
) {
958 } else if (p
->pain
) {
984 s
= goanim
[p
->s
/ 8];
985 w
= (p
->f
& PLF_FIRE
) ? 'B' : 'A';
987 wy
= 1 + wytab
[s
- 'A'];
1006 Z_drawspr(p
->o
.x
+ wx
, p
->o
.y
+ wy
, wpn
[p
->wpn
][w
- 'A'], p
->d
);
1008 Z_drawmanspr(p
->o
.x
, p
->o
.y
, spr
[(s
- 'A') * 2 + p
->d
], sprd
[(s
- 'A') * 2 + p
->d
], p
->color
);
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
) {
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;
1039 chk_bfg(&pl1
, x
, y
);
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
) {
1050 V_setrect(0, SCRW
, w_o
, HT
);
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
) {
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
);