DEADSOFTWARE

update copyrights
[flatwaifu.git] / src / weapons.c
1 /* Copyright (C) 1996-1997 Aleksey Volynskov
2 * Copyright (C) 2011 Rambo
3 * Copyright (C) 2020 SovietPony
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, version 3 of the License ONLY.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
18 #include "glob.h"
19 #include <stdlib.h>
20 #include "view.h"
21 #include "bmap.h"
22 #include "dots.h"
23 #include "smoke.h"
24 #include "weapons.h"
25 #include "misc.h"
26 #include "files.h"
27 #include "game.h"
28 #include "player.h"
29 #include "monster.h"
30 #include "switch.h"
31 #include "my.h"
33 enum{NONE=0,ROCKET,PLASMA,APLASMA,BALL1,BALL2,BALL7,BFGBALL,BFGHIT,
34 MANF,REVF,FIRE};
36 weapon_t wp[MAXWPN];
38 static void *snd[14];
39 static void throw(int,int,int,int,int,int,int,int);
41 void WP_alloc (void) {
42 int i;
43 static char nm[14][6]={
44 "PISTOL",
45 "SHOTGN",
46 "DSHTGN",
47 "RLAUNC",
48 "RXPLOD",
49 "PLASMA",
50 "FIRSHT",
51 "FIRXPL",
52 "BAREXP",
53 "PUNCH",
54 "SAWHIT",
55 "MGUN",
56 "SPARK1",
57 "SPARK2"
58 };
59 for(i=0;i<14;++i) snd[i]=Z_getsnd(nm[i]);
60 }
62 void WP_init (void) {
63 int i;
65 for(i=0;i<MAXWPN;++i) wp[i].t=NONE;
66 }
68 void WP_act (void) {
69 int i,st;
70 static obj_t o;
72 for(i=0;i<MAXWPN;++i) if(wp[i].t) {
73 if(wp[i].t==ROCKET || wp[i].t==REVF)
74 SMK_gas(wp[i].o.x+Z_sign(wp[i].o.xv)*2,
75 wp[i].o.y-wp[i].o.h/2,3,3,
76 wp[i].o.xv+wp[i].o.vx,wp[i].o.yv+wp[i].o.vy,64
77 );
78 --wp[i].o.yv;st=Z_moveobj(&wp[i].o);
79 if(st&Z_FALLOUT) {wp[i].t=0;continue;}
80 if(st&Z_HITWATER) switch(wp[i].t) {
81 case PLASMA: case APLASMA:
82 case BFGBALL:
83 break;
84 default:
85 Z_splash(&wp[i].o,wp[i].o.r+wp[i].o.h);break;
86 }
87 switch(wp[i].t) {
88 case REVF:
89 if(Z_getobjpos(wp[i].target,&o))
90 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);
91 case ROCKET:
92 if(wp[i].s>=2) {if(++wp[i].s>=8) wp[i].t=0; break;}
93 if(st&Z_HITAIR) Z_set_speed(&wp[i].o,12);
94 if(st&(Z_HITWALL|Z_HITCEIL|Z_HITLAND)) {
95 wp[i].s=2;wp[i].o.xv=wp[i].o.yv=0;Z_sound(snd[4],128);
96 Z_explode(wp[i].o.x,wp[i].o.y,30,wp[i].own);break;}
97 else if(Z_hit(&wp[i].o,10,wp[i].own,HIT_SOME)) {
98 wp[i].s=2;wp[i].o.xv=wp[i].o.yv=0;Z_sound(snd[4],128);
99 Z_explode(wp[i].o.x,wp[i].o.y-wp[i].o.h/2,30,wp[i].own);break;}
100 bfg_fly(wp[i].o.x,wp[i].o.y-wp[i].o.h/2,wp[i].own);
101 break;
102 case PLASMA:
103 case APLASMA:
104 if(st&Z_INWATER) {
105 Z_sound(snd[12],128);
106 Z_water_trap(&wp[i].o);
107 Z_chktrap(1,10,wp[i].own,HIT_ELECTRO);
108 Z_untrap(5);
109 wp[i].t=0;break;
111 case BALL1:
112 case BALL7:
113 case BALL2:
114 case MANF:
115 if(wp[i].s>=2)
116 {if(++wp[i].s>=((wp[i].t==BALL1 || wp[i].t==BALL7 || wp[i].t==BALL2 || wp[i].t==MANF)?8:12)) wp[i].t=0; break;}
117 if(st&Z_HITAIR) Z_set_speed(&wp[i].o,16);
118 if(st&(Z_HITWALL|Z_HITCEIL|Z_HITLAND))
119 {wp[i].s=2;wp[i].o.xv=wp[i].o.yv=0;Z_sound(snd[7],128);break;}
120 else if(Z_hit(&wp[i].o,(wp[i].t==BALL7 || wp[i].t==MANF)?40:((wp[i].t==BALL2)?20:5),wp[i].own,HIT_SOME))
121 {wp[i].s=2;wp[i].o.xv=wp[i].o.yv=0;Z_sound(snd[7],128);break;}
122 wp[i].s^=1;break;
123 case BFGBALL:
124 if(st&Z_INWATER) {
125 Z_sound(snd[8],40);Z_sound(snd[13],128);
126 Z_water_trap(&wp[i].o);
127 Z_chktrap(1,1000,wp[i].own,HIT_ELECTRO);
128 Z_untrap(5);
129 wp[i].t=0;break;
131 if(wp[i].s>=2) {if(++wp[i].s>=14) wp[i].t=0; break;}
132 else if(st&(Z_HITWALL|Z_HITCEIL|Z_HITLAND)) {
133 Z_bfg9000(wp[i].o.x,wp[i].o.y,wp[i].own);
134 wp[i].s=2;wp[i].o.xv=wp[i].o.yv=0;Z_sound(snd[8],128);break;}
135 else if(Z_hit(&wp[i].o,100,wp[i].own,HIT_BFG)) {
136 Z_bfg9000(wp[i].o.x,wp[i].o.y,wp[i].own);
137 wp[i].s=2;wp[i].o.xv=wp[i].o.yv=0;Z_sound(snd[8],128);break;}
138 bfg_fly(wp[i].o.x,wp[i].o.y-wp[i].o.h/2,wp[i].own);
139 wp[i].s^=1;break;
140 case BFGHIT:
141 if(++wp[i].s>=8) wp[i].t=0;
142 break;
143 default: break;
148 void WP_gun (int x, int y, int xd, int yd, int o, int v) {
149 register dword d,m;
150 int sx,sy,lx,ly;
151 dword xe,ye,s;
152 byte f;
154 f=BM_MONSTER|BM_WALL;
155 if(o!=-1) f|=BM_PLR1;
156 if(o!=-2) f|=BM_PLR2;
157 if((xd-=x)>0) sx=1;
158 else if(xd<0) sx=-1;
159 else sx=0;
160 if((yd-=y)>0) sy=1;
161 else if(yd<0) sy=-1;
162 else sy=0;
163 if(!xd && !yd) return;
164 if((xd=abs(xd)) > (yd=abs(yd))) d=xd; else d=yd;
165 hit_xv=xd*10/d*sx;
166 hit_yv=yd*10/d*sy;
167 xe=ye=0;
168 lx=x;ly=y;
169 for(;;) {
170 if(x<0 || x>=FLDW*8 || y<0 || y>=FLDH*8) break;
171 if(((m=bmap[y>>5][x>>5])&f)) {
172 if(m&BM_WALL) if(fld[y>>3][x>>3]==1 || fld[y>>3][x>>3]==2) {
173 for(x=lx,y=ly,xe=ye=0;fld[y>>3][x>>3]!=1 && fld[y>>3][x>>3]!=2;) {
174 lx=x;ly=y;
175 if((xe+=xd)>=d) {xe-=d;x+=sx;}
176 if((ye+=yd)>=d) {ye-=d;y+=sy;}
178 DOT_spark(lx,ly,sx*10,sy*10,1);
179 break;
181 if(m&(BM_MONSTER|BM_PLR1|BM_PLR2)) if(Z_gunhit(x,y,o,sx*v,sy*v)) break;
182 lx=x;ly=y;
183 if((xe+=(xd<<3))>=d) {
184 x+=xe/d*sx;xe=xe%d;
186 if((ye+=(yd<<3))>=d) {
187 y+=ye/d*sy;ye=ye%d;
189 }else{
190 if(sx==0) m=0;
191 else{m=x&31;if(sx>0) m^=31; ++m;}
192 if(sy==0) s=0;
193 else{s=y&31;if(sy>0) s^=31; ++s;}
194 if((s<m && s!=0) || m==0) m=s;
195 lx=x;ly=y;
196 x+=(xd*m+xe)/d*sx;xe=(xd*m+xe)%d;
197 y+=(yd*m+ye)/d*sy;ye=(yd*m+ye)%d;
202 void WP_punch (int x, int y, int d, int own) {
203 obj_t o;
205 o.x=x;o.y=y;o.r=12;o.h=26;
206 o.xv=o.yv=o.vx=o.vy=0;
207 if(Z_hit(&o,d,own,HIT_SOME)) Z_sound(snd[9],128);
210 int WP_chainsaw (int x, int y, int d, int own) {
211 obj_t o;
213 o.x=x;o.y=y;o.r=12;o.h=26;
214 o.xv=o.yv=o.vx=o.vy=0;
215 if(Z_hit(&o,d,own,HIT_SOME)) return 1;
216 return 0;
219 static void throw(int i,int x,int y,int xd,int yd,int r,int h,int s) {
220 int m;
222 wp[i].o.x=x;wp[i].o.y=y+h/2;
223 yd-=y;xd-=x;
224 if(!(m=max(abs(xd),abs(yd)))) m=1;
225 wp[i].o.xv=xd*s/m;wp[i].o.yv=yd*s/m;
226 wp[i].o.r=r;wp[i].o.h=h;
227 wp[i].o.vx=wp[i].o.vy=0;
230 void WP_rocket (int x, int y, int xd, int yd, int o) {
231 int i;
233 for(i=0;i<MAXWPN;++i) if(!wp[i].t) {
234 Z_sound(snd[3],128);
235 wp[i].t=ROCKET;wp[i].s=(xd>=x)?1:0;
236 wp[i].own=o;
237 throw(i,x,y,xd,yd,2,5,12);
238 return;
242 void WP_revf (int x, int y, int xd, int yd, int o, int t) {
243 int i;
245 for(i=0;i<MAXWPN;++i) if(!wp[i].t) {
246 Z_sound(snd[3],128);
247 wp[i].t=REVF;wp[i].s=(xd>=x)?1:0;
248 wp[i].own=o;wp[i].target=t;
249 throw(i,x,y,xd,yd,2,5,12);
250 return;
254 void WP_plasma (int x, int y, int xd, int yd, int o) {
255 int i;
257 for(i=0;i<MAXWPN;++i) if(!wp[i].t) {
258 Z_sound(snd[5],64);
259 wp[i].t=PLASMA;wp[i].s=0;
260 wp[i].own=o;
261 throw(i,x,y,xd,yd,2,5,16);
262 return;
266 void WP_ball1 (int x, int y, int xd, int yd, int o) {
267 int i;
269 for(i=0;i<MAXWPN;++i) if(!wp[i].t) {
270 wp[i].t=BALL1;wp[i].s=0;
271 wp[i].own=o;
272 throw(i,x,y,xd,yd,2,5,16);
273 return;
277 void WP_ball2 (int x, int y, int xd, int yd, int o) {
278 int i;
280 for(i=0;i<MAXWPN;++i) if(!wp[i].t) {
281 wp[i].t=BALL2;wp[i].s=0;
282 wp[i].own=o;
283 throw(i,x,y,xd,yd,2,5,16);
284 return;
288 void WP_ball7 (int x, int y, int xd, int yd, int o) {
289 int i;
291 for(i=0;i<MAXWPN;++i) if(!wp[i].t) {
292 wp[i].t=BALL7;wp[i].s=0;
293 wp[i].own=o;
294 throw(i,x,y,xd,yd,2,5,16);
295 return;
299 void WP_aplasma (int x, int y, int xd, int yd, int o) {
300 int i;
302 for(i=0;i<MAXWPN;++i) if(!wp[i].t) {
303 Z_sound(snd[5],64);
304 wp[i].t=APLASMA;wp[i].s=0;
305 wp[i].own=o;
306 throw(i,x,y,xd,yd,2,5,16);
307 return;
311 void WP_manfire (int x, int y, int xd, int yd, int o) {
312 int i;
314 for(i=0;i<MAXWPN;++i) if(!wp[i].t) {
315 Z_sound(snd[6],128);
316 wp[i].t=MANF;wp[i].s=0;
317 wp[i].own=o;
318 throw(i,x,y,xd,yd,5,11,16);
319 return;
323 void WP_bfgshot (int x, int y, int xd, int yd, int o) {
324 int i;
326 for(i=0;i<MAXWPN;++i) if(!wp[i].t) {
327 wp[i].t=BFGBALL;wp[i].s=0;
328 wp[i].own=o;
329 throw(i,x,y,xd,yd,5,12,16);
330 return;
334 void WP_bfghit (int x, int y, int o) {
335 int i;
337 for(i=0;i<MAXWPN;++i) if(!wp[i].t) {
338 wp[i].t=BFGHIT;wp[i].s=0;
339 wp[i].o.x=x;wp[i].o.y=y;
340 wp[i].o.xv=wp[i].o.yv=0;
341 wp[i].o.r=0;wp[i].o.h=1;
342 wp[i].o.vx=wp[i].o.vy=0;
343 wp[i].own=o;
344 return;
348 void WP_pistol (int x,int y,int xd,int yd,int o) {
349 Z_sound(snd[0],96);
350 WP_gun(x,y,xd,yd,o,1);
351 if(g_dm) {
352 WP_gun(x,y+1,xd,yd+1,o,1);
353 WP_gun(x,y-1,xd,yd-1,o,1);
357 void WP_mgun (int x, int y, int xd, int yd, int o) {
358 Z_sound(snd[11],128);
359 WP_gun(x,y,xd,yd,o,1);
362 void WP_shotgun (int x, int y, int xd, int yd, int o) {
363 int i,j;
365 Z_sound(snd[1],128);
366 for(i=0;i<10;++i) {
367 j=myrand(4*2+1)-4;
368 WP_gun(x,y+j,xd,yd+j,o,i&1);
372 void WP_dshotgun (int x, int y, int xd, int yd, int o) {
373 int i,j;
375 Z_sound(snd[2],128);
376 for(i=(g_dm)?25:20;i>=0;--i) {
377 j=myrand(10*2+1)-10;
378 WP_gun(x,y+j,xd,yd+j,o,(i%3)?0:1);
382 void WP_ognemet (int x, int y, int xd, int yd, int xv, int yv, int o) {
383 int m;
385 m=abs(xd-x);if(!m) m=abs(yd-y);
386 SMK_flame(x,y,xv,yv,2,2,(xd-x)*3000/m,(yd-y)*3000/m,1,o);