fix map selector starting the game
[d2d-psx.git] / src / weapons.c
blobe4ae764892b8cd60c7efb9ca2da12939ebabfd1f
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 <io.h>
26 #include "vga.h"
27 #include "error.h"
28 #include "sound.h"
29 #include "view.h"
30 #include "bmap.h"
31 #include "dots.h"
32 #include "smoke.h"
33 #include "weapons.h"
34 #include "misc.h"
36 extern int hit_xv, hit_yv;
38 void bfg_fly(int x, int y, int own);
40 enum {
41 NONE = 0, ROCKET, PLASMA, APLASMA, BALL1, BALL2, BALL7, BFGBALL, BFGHIT,
42 MANF, REVF, FIRE
45 #pragma pack(1)
46 typedef struct {
47 obj_t o;
48 byte t, s;
49 int own;
50 short target;
51 } weapon_t;
52 #pragma pack()
54 static void * snd[14], * spr[49 * 2];
55 static char sprd[49 * 2];
56 static weapon_t wp[MAXWPN];
58 static void throw(int, int, int, int, int, int, int, int);
60 void WP_alloc(void) {
61 int i;
62 static char nm[14][6] = {
63 "PISTOL",
64 "SHOTGN",
65 "DSHTGN",
66 "RLAUNC",
67 "RXPLOD",
68 "PLASMA",
69 "FIRSHT",
70 "FIRXPL",
71 "BAREXP",
72 "PUNCH",
73 "SAWHIT",
74 "MGUN",
75 "SPARK1",
76 "SPARK2"
79 for (i = 0; i < 4; ++i) {
80 spr[i * 2] = Z_getspr("MISL", i, 1, sprd + i * 2);
81 spr[i * 2 + 1] = Z_getspr("MISL", i, 2, sprd + i * 2 + 1);
83 for (; i < 6; ++i) {
84 spr[i * 2] = Z_getspr("PLSS", i - 4, 1, sprd + i * 2);
85 spr[i * 2 + 1] = Z_getspr("PLSS", i - 4, 2, sprd + i * 2 + 1);
87 for (; i < 11; ++i) {
88 spr[i * 2] = Z_getspr("PLSE", i - 6, 1, sprd + i * 2);
89 spr[i * 2 + 1] = Z_getspr("PLSE", i - 6, 2, sprd + i * 2 + 1);
91 for (; i < 13; ++i) {
92 spr[i * 2] = Z_getspr("APLS", i - 11, 1, sprd + i * 2);
93 spr[i * 2 + 1] = Z_getspr("APLS", i - 11, 2, sprd + i * 2 + 1);
95 for (; i < 18; ++i) {
96 spr[i * 2] = Z_getspr("APBX", i - 13, 1, sprd + i * 2);
97 spr[i * 2 + 1] = Z_getspr("APBX", i - 13, 2, sprd + i * 2 + 1);
99 for (; i < 20; ++i) {
100 spr[i * 2] = Z_getspr("BFS1", i - 18, 1, sprd + i * 2);
101 spr[i * 2 + 1] = Z_getspr("BFS1", i - 18, 2, sprd + i * 2 + 1);
103 for (; i < 26; ++i) {
104 spr[i * 2] = Z_getspr("BFE1", i - 20, 1, sprd + i * 2);
105 spr[i * 2 + 1] = Z_getspr("BFE1", i - 20, 2, sprd + i * 2 + 1);
107 for (; i < 30; ++i) {
108 spr[i * 2] = Z_getspr("BFE2", i - 26, 1, sprd + i * 2);
109 spr[i * 2 + 1] = Z_getspr("BFE2", i - 26, 2, sprd + i * 2 + 1);
111 for (; i < 32; ++i) {
112 spr[i * 2] = Z_getspr("MISL", i - 30 + 4, 1, sprd + i * 2);
113 spr[i * 2 + 1] = Z_getspr("MISL", i - 30 + 4, 2, sprd + i * 2 + 1);
115 for (; i < 37; ++i) {
116 spr[i * 2] = Z_getspr("BAL1", i - 32, 1, sprd + i * 2);
117 spr[i * 2 + 1] = Z_getspr("BAL1", i - 32, 2, sprd + i * 2 + 1);
119 for (; i < 42; ++i) {
120 spr[i * 2] = Z_getspr("BAL7", i - 37, 1, sprd + i * 2);
121 spr[i * 2 + 1] = Z_getspr("BAL7", i - 37, 2, sprd + i * 2 + 1);
123 for (; i < 47; ++i) {
124 spr[i * 2] = Z_getspr("BAL2", i - 42, 1, sprd + i * 2);
125 spr[i * 2 + 1] = Z_getspr("BAL2", i - 42, 2, sprd + i * 2 + 1);
127 for (; i < 49; ++i) {
128 spr[i * 2] = Z_getspr("MANF", i - 47, 1, sprd + i * 2);
129 spr[i * 2 + 1] = Z_getspr("MANF", i - 47, 2, sprd + i * 2 + 1);
131 for (i = 0; i < 14; ++i)
132 snd[i] = Z_getsnd(nm[i]);
133 } /* WP_alloc */
135 void WP_init(void) {
136 int i;
138 for (i = 0; i < MAXWPN; ++i)
139 wp[i].t = NONE;
142 void WP_act(void) {
143 int i, st;
144 static obj_t o;
146 for (i = 0; i < MAXWPN; ++i) {
147 if (wp[i].t) {
148 if ((wp[i].t == ROCKET) || (wp[i].t == REVF)) {
149 SMK_gas(wp[i].o.x + Z_sign(wp[i].o.xv) * 2,
150 wp[i].o.y - wp[i].o.h / 2, 3, 3,
151 wp[i].o.xv + wp[i].o.vx, wp[i].o.yv + wp[i].o.vy, 64
154 --wp[i].o.yv;
155 st = Z_moveobj(&wp[i].o);
156 if (st & Z_FALLOUT) {
157 wp[i].t = 0;
158 continue;
160 if (st & Z_HITWATER) {
161 switch (wp[i].t) {
162 case PLASMA:
163 case APLASMA:
164 case BFGBALL:
165 break;
167 default:
168 Z_splash(&wp[i].o, wp[i].o.r + wp[i].o.h);
169 break;
172 switch (wp[i].t) {
173 case REVF:
174 if (Z_getobjpos(wp[i].target, &o))
175 throw(i, wp[i].o.x, wp[i].o.y - 2, o.x + o.xv + o.vx, o.y + o.yv + o.vy, 2, 5, 12);
177 case ROCKET:
178 if (wp[i].s >= 2) {
179 if (++wp[i].s >= 8)
180 wp[i].t = 0;
181 break;
183 if (st & Z_HITAIR)
184 Z_set_speed(&wp[i].o, 12);
185 if (st & (Z_HITWALL | Z_HITCEIL | Z_HITLAND)) {
186 wp[i].s = 2;
187 wp[i].o.xv = wp[i].o.yv = 0;
188 Z_sound(snd[8], 128);
189 Z_explode(wp[i].o.x, wp[i].o.y, 30, wp[i].own);
190 break;
191 } else if (Z_hit(&wp[i].o, 10, wp[i].own, HIT_SOME)) {
192 wp[i].s = 2;
193 wp[i].o.xv = wp[i].o.yv = 0;
194 Z_sound(snd[8], 128);
195 Z_explode(wp[i].o.x, wp[i].o.y - wp[i].o.h / 2, 30, wp[i].own);
196 break;
198 bfg_fly(wp[i].o.x, wp[i].o.y - wp[i].o.h / 2, wp[i].own);
199 break;
201 case PLASMA:
202 case APLASMA:
203 if (st & Z_INWATER) {
204 Z_sound(snd[12], 128);
205 Z_water_trap(&wp[i].o);
206 Z_chktrap(1, 10, wp[i].own, HIT_ELECTRO);
207 Z_untrap(5);
208 wp[i].t = 0;
209 break;
212 case BALL1:
213 case BALL7:
214 case BALL2:
215 case MANF:
216 if (wp[i].s >= 2) {
217 if (++wp[i].s >=
218 (((wp[i].t == BALL1) || (wp[i].t == BALL7) || (wp[i].t == BALL2) ||
219 (wp[i].t == MANF)) ? 8 : 12))
220 wp[i].t = 0;
221 break;
223 if (st & Z_HITAIR)
224 Z_set_speed(&wp[i].o, 16);
225 if (st & (Z_HITWALL | Z_HITCEIL | Z_HITLAND)) {
226 wp[i].s = 2;
227 wp[i].o.xv = wp[i].o.yv = 0;
228 Z_sound(snd[7], 128);
229 break;
230 } else if (Z_hit(&wp[i].o,
231 ((wp[i].t == BALL7) || (wp[i].t == MANF)) ? 40 : ((wp[i].t == BALL2) ? 20 : 5), wp[i].own,
232 HIT_SOME))
234 wp[i].s = 2;
235 wp[i].o.xv = wp[i].o.yv = 0;
236 Z_sound(snd[7], 128);
237 break;
239 wp[i].s ^= 1;
240 break;
242 case BFGBALL:
243 if (st & Z_INWATER) {
244 Z_sound(snd[4], 40);
245 Z_sound(snd[13], 128);
246 Z_water_trap(&wp[i].o);
247 Z_chktrap(1, 1000, wp[i].own, HIT_ELECTRO);
248 Z_untrap(5);
249 wp[i].t = 0;
250 break;
252 if (wp[i].s >= 2) {
253 if (++wp[i].s >= 14)
254 wp[i].t = 0;
255 break;
256 } else if (st & (Z_HITWALL | Z_HITCEIL | Z_HITLAND)) {
257 Z_bfg9000(wp[i].o.x, wp[i].o.y, wp[i].own);
258 wp[i].s = 2;
259 wp[i].o.xv = wp[i].o.yv = 0;
260 Z_sound(snd[4], 128);
261 break;
262 } else if (Z_hit(&wp[i].o, 100, wp[i].own, HIT_BFG)) {
263 Z_bfg9000(wp[i].o.x, wp[i].o.y, wp[i].own);
264 wp[i].s = 2;
265 wp[i].o.xv = wp[i].o.yv = 0;
266 Z_sound(snd[4], 128);
267 break;
269 bfg_fly(wp[i].o.x, wp[i].o.y - wp[i].o.h / 2, wp[i].own);
270 wp[i].s ^= 1;
271 break;
273 case BFGHIT:
274 if (++wp[i].s >= 8)
275 wp[i].t = 0;
276 break;
278 default:
279 break;
283 } /* WP_act */
285 void WP_draw(void) {
286 int i, s, d, x, y;
288 for (i = 0; i < MAXWPN; ++i) {
289 s = -1;
290 d = 0;
291 switch (wp[i].t) {
292 case NONE:
293 default:
294 break;
296 case REVF:
297 case ROCKET:
298 if ((d = wp[i].s) < 2) {
299 d = (wp[i].o.xv > 0) ? 1 : 0;
300 x = abs(wp[i].o.xv);
301 y = wp[i].o.yv;
302 s = 0;
303 if (y < 0) {
304 if (-y >= x)
305 s = 30;
306 } else if (y > 0) {
307 if (y >= x / 2)
308 s = 31;
310 } else {
311 s = (d - 2) / 2 + 1;
312 d = 0;
314 break;
316 case MANF:
317 if ((s = wp[i].s) >= 2) {
318 s /= 2;
319 break;
322 case PLASMA:
323 case APLASMA:
324 case BALL1:
325 case BALL7:
326 case BALL2:
327 if ((s = wp[i].s) >= 2)
328 s = s / 2 + 1;
329 switch (wp[i].t) {
330 case PLASMA:
331 s += 4;
332 break;
334 case APLASMA:
335 s += 11;
336 break;
338 case BALL1:
339 s += 32;
340 break;
342 case BALL2:
343 s += 42;
344 break;
346 case BALL7:
347 s += 37;
348 d = (wp[i].o.xv >= 0) ? 1 : 0;
349 break;
351 case MANF:
352 s += 47;
353 d = (wp[i].o.xv >= 0) ? 1 : 0;
354 break;
356 break;
358 case BFGBALL:
359 if ((s = wp[i].s) >= 2)
360 s = s / 2 + 1;
361 s += 18;
362 break;
364 case BFGHIT:
365 s = wp[i].s / 2 + 26;
366 break;
368 if (s >= 0)
369 Z_drawspr(wp[i].o.x, wp[i].o.y, spr[s * 2 + d], sprd[s * 2 + d]);
371 } /* WP_draw */
373 void WP_gun(int x, int y, int xd, int yd, int o, int v) {
374 register dword d, m;
375 int sx, sy, lx, ly;
376 dword xe, ye, s;
377 byte f;
379 f = BM_MONSTER | BM_WALL;
380 if (o != -1)
381 f |= BM_PLR1;
382 if (o != -2)
383 f |= BM_PLR2;
384 if ((xd -= x) > 0)
385 sx = 1;
386 else if (xd < 0)
387 sx = -1;
388 else
389 sx = 0;
390 if ((yd -= y) > 0)
391 sy = 1;
392 else if (yd < 0)
393 sy = -1;
394 else
395 sy = 0;
396 if (!xd && !yd)
397 return;
399 if ((xd = abs(xd)) > (yd = abs(yd)))
400 d = xd;
401 else
402 d = yd;
403 hit_xv = xd * 10 / d * sx;
404 hit_yv = yd * 10 / d * sy;
405 xe = ye = 0;
406 lx = x;
407 ly = y;
408 for (;;) {
409 if ((x < 0) || (x >= FLDW * 8) || (y < 0) || (y >= FLDH * 8))
410 break;
411 if (((m = bmap[y >> 5][x >> 5]) & f)) {
412 if (m & BM_WALL) {
413 if ((fld[y >> 3][x >> 3] == 1) || (fld[y >> 3][x >> 3] == 2)) {
414 for (x = lx, y = ly, xe = ye = 0; fld[y >> 3][x >> 3] != 1 && fld[y >> 3][x >> 3] != 2;) {
415 lx = x;
416 ly = y;
417 if ((xe += xd) >= d) {
418 xe -= d;
419 x += sx;
421 if ((ye += yd) >= d) {
422 ye -= d;
423 y += sy;
426 DOT_spark(lx, ly, sx * 10, sy * 10, 1);
427 break;
430 if (m & (BM_MONSTER | BM_PLR1 | BM_PLR2)) {
431 if (Z_gunhit(x, y, o, sx * v, sy * v))
432 break;
434 lx = x;
435 ly = y;
436 if ((xe += (xd << 3)) >= d) {
437 x += xe / d * sx;
438 xe = xe % d;
440 if ((ye += (yd << 3)) >= d) {
441 y += ye / d * sy;
442 ye = ye % d;
444 } else {
445 if (sx == 0) {
446 m = 0;
447 } else {
448 m = x & 31;
449 if (sx > 0)
450 m ^= 31;
451 ++m;
453 if (sy == 0) {
454 s = 0;
455 } else {
456 s = y & 31;
457 if (sy > 0)
458 s ^= 31;
459 ++s;
461 if (((s < m) && (s != 0)) || (m == 0))
462 m = s;
463 lx = x;
464 ly = y;
465 x += (xd * m + xe) / d * sx;
466 xe = (xd * m + xe) % d;
467 y += (yd * m + ye) / d * sy;
468 ye = (yd * m + ye) % d;
471 } /* WP_gun */
473 void WP_punch(int x, int y, int d, int own) {
474 obj_t o;
476 o.x = x;
477 o.y = y;
478 o.r = 12;
479 o.h = 26;
480 o.xv = o.yv = o.vx = o.vy = 0;
481 if (Z_hit(&o, d, own, HIT_SOME))
482 Z_sound(snd[9], 128);
485 int WP_chainsaw(int x, int y, int d, int own) {
486 obj_t o;
488 o.x = x;
489 o.y = y;
490 o.r = 12;
491 o.h = 26;
492 o.xv = o.yv = o.vx = o.vy = 0;
493 if (Z_hit(&o, d, own, HIT_SOME))
494 return 1;
496 return 0;
499 static void throw(int i, int x, int y, int xd, int yd, int r, int h, int s) {
500 int m;
502 wp[i].o.x = x;
503 wp[i].o.y = y + h / 2;
504 yd -= y;
505 xd -= x;
506 if (!(m = max(abs(xd), abs(yd))))
507 m = 1;
508 wp[i].o.xv = xd * s / m;
509 wp[i].o.yv = yd * s / m;
510 wp[i].o.r = r;
511 wp[i].o.h = h;
512 wp[i].o.vx = wp[i].o.vy = 0;
515 void WP_rocket(int x, int y, int xd, int yd, int o) {
516 int i;
518 for (i = 0; i < MAXWPN; ++i) {
519 if (!wp[i].t) {
520 Z_sound(snd[3], 128);
521 wp[i].t = ROCKET;
522 wp[i].s = (xd >= x) ? 1 : 0;
523 wp[i].own = o;
524 throw(i, x, y, xd, yd, 2, 5, 12);
525 return;
530 void WP_revf(int x, int y, int xd, int yd, int o, int t) {
531 int i;
533 for (i = 0; i < MAXWPN; ++i) {
534 if (!wp[i].t) {
535 Z_sound(snd[3], 128);
536 wp[i].t = REVF;
537 wp[i].s = (xd >= x) ? 1 : 0;
538 wp[i].own = o;
539 wp[i].target = t;
540 throw(i, x, y, xd, yd, 2, 5, 12);
541 return;
546 void WP_plasma(int x, int y, int xd, int yd, int o) {
547 int i;
549 for (i = 0; i < MAXWPN; ++i) {
550 if (!wp[i].t) {
551 Z_sound(snd[5], 64);
552 wp[i].t = PLASMA;
553 wp[i].s = 0;
554 wp[i].own = o;
555 throw(i, x, y, xd, yd, 2, 5, 16);
556 return;
561 void WP_ball1(int x, int y, int xd, int yd, int o) {
562 int i;
564 for (i = 0; i < MAXWPN; ++i) {
565 if (!wp[i].t) {
566 wp[i].t = BALL1;
567 wp[i].s = 0;
568 wp[i].own = o;
569 throw(i, x, y, xd, yd, 2, 5, 16);
570 return;
575 void WP_ball2(int x, int y, int xd, int yd, int o) {
576 int i;
578 for (i = 0; i < MAXWPN; ++i) {
579 if (!wp[i].t) {
580 wp[i].t = BALL2;
581 wp[i].s = 0;
582 wp[i].own = o;
583 throw(i, x, y, xd, yd, 2, 5, 16);
584 return;
589 void WP_ball7(int x, int y, int xd, int yd, int o) {
590 int i;
592 for (i = 0; i < MAXWPN; ++i) {
593 if (!wp[i].t) {
594 wp[i].t = BALL7;
595 wp[i].s = 0;
596 wp[i].own = o;
597 throw(i, x, y, xd, yd, 2, 5, 16);
598 return;
603 void WP_aplasma(int x, int y, int xd, int yd, int o) {
604 int i;
606 for (i = 0; i < MAXWPN; ++i) {
607 if (!wp[i].t) {
608 Z_sound(snd[5], 64);
609 wp[i].t = APLASMA;
610 wp[i].s = 0;
611 wp[i].own = o;
612 throw(i, x, y, xd, yd, 2, 5, 16);
613 return;
618 void WP_manfire(int x, int y, int xd, int yd, int o) {
619 int i;
621 for (i = 0; i < MAXWPN; ++i) {
622 if (!wp[i].t) {
623 Z_sound(snd[6], 128);
624 wp[i].t = MANF;
625 wp[i].s = 0;
626 wp[i].own = o;
627 throw(i, x, y, xd, yd, 5, 11, 16);
628 return;
633 void WP_bfgshot(int x, int y, int xd, int yd, int o) {
634 int i;
636 for (i = 0; i < MAXWPN; ++i) {
637 if (!wp[i].t) {
638 wp[i].t = BFGBALL;
639 wp[i].s = 0;
640 wp[i].own = o;
641 throw(i, x, y, xd, yd, 5, 12, 16);
642 return;
647 void WP_bfghit(int x, int y, int o) {
648 int i;
650 for (i = 0; i < MAXWPN; ++i) {
651 if (!wp[i].t) {
652 wp[i].t = BFGHIT;
653 wp[i].s = 0;
654 wp[i].o.x = x;
655 wp[i].o.y = y;
656 wp[i].o.xv = wp[i].o.yv = 0;
657 wp[i].o.r = 0;
658 wp[i].o.h = 1;
659 wp[i].o.vx = wp[i].o.vy = 0;
660 wp[i].own = o;
661 return;
666 void WP_pistol(int x, int y, int xd, int yd, int o) {
667 Z_sound(snd[0], 96);
668 WP_gun(x, y, xd, yd, o, 1);
669 if (g_dm) {
670 WP_gun(x, y + 1, xd, yd + 1, o, 1);
671 WP_gun(x, y - 1, xd, yd - 1, o, 1);
675 void WP_mgun(int x, int y, int xd, int yd, int o) {
676 Z_sound(snd[11], 128);
677 WP_gun(x, y, xd, yd, o, 1);
680 void WP_shotgun(int x, int y, int xd, int yd, int o) {
681 int i, j;
683 Z_sound(snd[1], 128);
684 for (i = 0; i < 10; ++i) {
685 j = myrand(4 * 2 + 1) - 4;
686 WP_gun(x, y + j, xd, yd + j, o, i & 1);
690 void WP_dshotgun(int x, int y, int xd, int yd, int o) {
691 int i, j;
693 Z_sound(snd[2], 128);
694 for (i = (g_dm) ? 25 : 20; i >= 0; --i) {
695 j = myrand(10 * 2 + 1) - 10;
696 WP_gun(x, y + j, xd, yd + j, o, (i % 3) ? 0 : 1);
700 void WP_ognemet(int x, int y, int xd, int yd, int xv, int yv, int o) {
701 int m;
703 m = abs(xd - x);
704 if (!m)
705 m = abs(yd - y);
706 SMK_flame(x, y, xv, yv, 2, 2, (xd - x) * 3000 / m, (yd - y) * 3000 / m, 1, o);