DEADSOFTWARE

b3b757dc11724122aefce6874e89f6074a199b8f
[flatwaifu.git] / src / weapons.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 "view.h"
26 #include "bmap.h"
27 #include "dots.h"
28 #include "smoke.h"
29 #include "weapons.h"
30 #include "misc.h"
31 #include "files.h"
32 #include "game.h"
33 #include "player.h"
34 #include "monster.h"
35 #include "switch.h"
36 #include "my.h"
38 enum{NONE=0,ROCKET,PLASMA,APLASMA,BALL1,BALL2,BALL7,BFGBALL,BFGHIT,
39 MANF,REVF,FIRE};
41 weapon_t wp[MAXWPN];
43 static void *snd[14];
44 static void throw(int,int,int,int,int,int,int,int);
46 void WP_savegame (FILE *h) {
47 int i, n;
48 for (n = MAXWPN - 1; n >= 0 && wp[n].t == 0; n--) {
49 // empty
50 }
51 n += 1;
52 myfwrite32(n, h);
53 for (i = 0; i < n; i++) {
54 myfwrite32(wp[i].o.x, h);
55 myfwrite32(wp[i].o.y, h);
56 myfwrite32(wp[i].o.xv, h);
57 myfwrite32(wp[i].o.yv, h);
58 myfwrite32(wp[i].o.vx, h);
59 myfwrite32(wp[i].o.vy, h);
60 myfwrite32(wp[i].o.r, h);
61 myfwrite32(wp[i].o.h, h);
62 myfwrite8(wp[i].t, h);
63 myfwrite8(wp[i].s, h);
64 myfwrite32(wp[i].own, h);
65 myfwrite16(wp[i].target, h);
66 }
67 }
69 void WP_loadgame (FILE *h) {
70 int i, n;
71 n = myfread32(h);
72 for (i = 0; i < n; i++) {
73 wp[i].o.x = myfread32(h);
74 wp[i].o.y = myfread32(h);
75 wp[i].o.xv = myfread32(h);
76 wp[i].o.yv = myfread32(h);
77 wp[i].o.vx = myfread32(h);
78 wp[i].o.vy = myfread32(h);
79 wp[i].o.r = myfread32(h);
80 wp[i].o.h = myfread32(h);
81 wp[i].t = myfread8(h);
82 wp[i].s = myfread8(h);
83 wp[i].own = myfread32(h);
84 wp[i].target = myfread16(h);
85 }
86 }
88 void WP_alloc (void) {
89 int i;
90 static char nm[14][6]={
91 "PISTOL",
92 "SHOTGN",
93 "DSHTGN",
94 "RLAUNC",
95 "RXPLOD",
96 "PLASMA",
97 "FIRSHT",
98 "FIRXPL",
99 "BAREXP",
100 "PUNCH",
101 "SAWHIT",
102 "MGUN",
103 "SPARK1",
104 "SPARK2"
105 };
106 for(i=0;i<14;++i) snd[i]=Z_getsnd(nm[i]);
109 void WP_init (void) {
110 int i;
112 for(i=0;i<MAXWPN;++i) wp[i].t=NONE;
115 void WP_act (void) {
116 int i,st;
117 static obj_t o;
119 for(i=0;i<MAXWPN;++i) if(wp[i].t) {
120 if(wp[i].t==ROCKET || wp[i].t==REVF)
121 SMK_gas(wp[i].o.x+Z_sign(wp[i].o.xv)*2,
122 wp[i].o.y-wp[i].o.h/2,3,3,
123 wp[i].o.xv+wp[i].o.vx,wp[i].o.yv+wp[i].o.vy,64
124 );
125 --wp[i].o.yv;st=Z_moveobj(&wp[i].o);
126 if(st&Z_FALLOUT) {wp[i].t=0;continue;}
127 if(st&Z_HITWATER) switch(wp[i].t) {
128 case PLASMA: case APLASMA:
129 case BFGBALL:
130 break;
131 default:
132 Z_splash(&wp[i].o,wp[i].o.r+wp[i].o.h);break;
134 switch(wp[i].t) {
135 case REVF:
136 if(Z_getobjpos(wp[i].target,&o))
137 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);
138 case ROCKET:
139 if(wp[i].s>=2) {if(++wp[i].s>=8) wp[i].t=0; break;}
140 if(st&Z_HITAIR) Z_set_speed(&wp[i].o,12);
141 if(st&(Z_HITWALL|Z_HITCEIL|Z_HITLAND)) {
142 wp[i].s=2;wp[i].o.xv=wp[i].o.yv=0;Z_sound(snd[4],128);
143 Z_explode(wp[i].o.x,wp[i].o.y,30,wp[i].own);break;}
144 else if(Z_hit(&wp[i].o,10,wp[i].own,HIT_SOME)) {
145 wp[i].s=2;wp[i].o.xv=wp[i].o.yv=0;Z_sound(snd[4],128);
146 Z_explode(wp[i].o.x,wp[i].o.y-wp[i].o.h/2,30,wp[i].own);break;}
147 bfg_fly(wp[i].o.x,wp[i].o.y-wp[i].o.h/2,wp[i].own);
148 break;
149 case PLASMA:
150 case APLASMA:
151 if(st&Z_INWATER) {
152 Z_sound(snd[12],128);
153 Z_water_trap(&wp[i].o);
154 Z_chktrap(1,10,wp[i].own,HIT_ELECTRO);
155 Z_untrap(5);
156 wp[i].t=0;break;
158 case BALL1:
159 case BALL7:
160 case BALL2:
161 case MANF:
162 if(wp[i].s>=2)
163 {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;}
164 if(st&Z_HITAIR) Z_set_speed(&wp[i].o,16);
165 if(st&(Z_HITWALL|Z_HITCEIL|Z_HITLAND))
166 {wp[i].s=2;wp[i].o.xv=wp[i].o.yv=0;Z_sound(snd[7],128);break;}
167 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))
168 {wp[i].s=2;wp[i].o.xv=wp[i].o.yv=0;Z_sound(snd[7],128);break;}
169 wp[i].s^=1;break;
170 case BFGBALL:
171 if(st&Z_INWATER) {
172 Z_sound(snd[8],40);Z_sound(snd[13],128);
173 Z_water_trap(&wp[i].o);
174 Z_chktrap(1,1000,wp[i].own,HIT_ELECTRO);
175 Z_untrap(5);
176 wp[i].t=0;break;
178 if(wp[i].s>=2) {if(++wp[i].s>=14) wp[i].t=0; break;}
179 else if(st&(Z_HITWALL|Z_HITCEIL|Z_HITLAND)) {
180 Z_bfg9000(wp[i].o.x,wp[i].o.y,wp[i].own);
181 wp[i].s=2;wp[i].o.xv=wp[i].o.yv=0;Z_sound(snd[8],128);break;}
182 else if(Z_hit(&wp[i].o,100,wp[i].own,HIT_BFG)) {
183 Z_bfg9000(wp[i].o.x,wp[i].o.y,wp[i].own);
184 wp[i].s=2;wp[i].o.xv=wp[i].o.yv=0;Z_sound(snd[8],128);break;}
185 bfg_fly(wp[i].o.x,wp[i].o.y-wp[i].o.h/2,wp[i].own);
186 wp[i].s^=1;break;
187 case BFGHIT:
188 if(++wp[i].s>=8) wp[i].t=0;
189 break;
190 default: break;
195 void WP_gun (int x, int y, int xd, int yd, int o, int v) {
196 register dword d,m;
197 int sx,sy,lx,ly;
198 dword xe,ye,s;
199 byte f;
201 f=BM_MONSTER|BM_WALL;
202 if(o!=-1) f|=BM_PLR1;
203 if(o!=-2) f|=BM_PLR2;
204 if((xd-=x)>0) sx=1;
205 else if(xd<0) sx=-1;
206 else sx=0;
207 if((yd-=y)>0) sy=1;
208 else if(yd<0) sy=-1;
209 else sy=0;
210 if(!xd && !yd) return;
211 if((xd=abs(xd)) > (yd=abs(yd))) d=xd; else d=yd;
212 hit_xv=xd*10/d*sx;
213 hit_yv=yd*10/d*sy;
214 xe=ye=0;
215 lx=x;ly=y;
216 for(;;) {
217 if(x<0 || x>=FLDW*8 || y<0 || y>=FLDH*8) break;
218 if(((m=bmap[y>>5][x>>5])&f)) {
219 if(m&BM_WALL) if(fld[y>>3][x>>3]==1 || fld[y>>3][x>>3]==2) {
220 for(x=lx,y=ly,xe=ye=0;fld[y>>3][x>>3]!=1 && fld[y>>3][x>>3]!=2;) {
221 lx=x;ly=y;
222 if((xe+=xd)>=d) {xe-=d;x+=sx;}
223 if((ye+=yd)>=d) {ye-=d;y+=sy;}
225 DOT_spark(lx,ly,sx*10,sy*10,1);
226 break;
228 if(m&(BM_MONSTER|BM_PLR1|BM_PLR2)) if(Z_gunhit(x,y,o,sx*v,sy*v)) break;
229 lx=x;ly=y;
230 if((xe+=(xd<<3))>=d) {
231 x+=xe/d*sx;xe=xe%d;
233 if((ye+=(yd<<3))>=d) {
234 y+=ye/d*sy;ye=ye%d;
236 }else{
237 if(sx==0) m=0;
238 else{m=x&31;if(sx>0) m^=31; ++m;}
239 if(sy==0) s=0;
240 else{s=y&31;if(sy>0) s^=31; ++s;}
241 if((s<m && s!=0) || m==0) m=s;
242 lx=x;ly=y;
243 x+=(xd*m+xe)/d*sx;xe=(xd*m+xe)%d;
244 y+=(yd*m+ye)/d*sy;ye=(yd*m+ye)%d;
249 void WP_punch (int x, int y, int d, int own) {
250 obj_t o;
252 o.x=x;o.y=y;o.r=12;o.h=26;
253 o.xv=o.yv=o.vx=o.vy=0;
254 if(Z_hit(&o,d,own,HIT_SOME)) Z_sound(snd[9],128);
257 int WP_chainsaw (int x, int y, int d, int own) {
258 obj_t o;
260 o.x=x;o.y=y;o.r=12;o.h=26;
261 o.xv=o.yv=o.vx=o.vy=0;
262 if(Z_hit(&o,d,own,HIT_SOME)) return 1;
263 return 0;
266 static void throw(int i,int x,int y,int xd,int yd,int r,int h,int s) {
267 int m;
269 wp[i].o.x=x;wp[i].o.y=y+h/2;
270 yd-=y;xd-=x;
271 if(!(m=max(abs(xd),abs(yd)))) m=1;
272 wp[i].o.xv=xd*s/m;wp[i].o.yv=yd*s/m;
273 wp[i].o.r=r;wp[i].o.h=h;
274 wp[i].o.vx=wp[i].o.vy=0;
277 void WP_rocket (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 Z_sound(snd[3],128);
282 wp[i].t=ROCKET;wp[i].s=(xd>=x)?1:0;
283 wp[i].own=o;
284 throw(i,x,y,xd,yd,2,5,12);
285 return;
289 void WP_revf (int x, int y, int xd, int yd, int o, int t) {
290 int i;
292 for(i=0;i<MAXWPN;++i) if(!wp[i].t) {
293 Z_sound(snd[3],128);
294 wp[i].t=REVF;wp[i].s=(xd>=x)?1:0;
295 wp[i].own=o;wp[i].target=t;
296 throw(i,x,y,xd,yd,2,5,12);
297 return;
301 void WP_plasma (int x, int y, int xd, int yd, int o) {
302 int i;
304 for(i=0;i<MAXWPN;++i) if(!wp[i].t) {
305 Z_sound(snd[5],64);
306 wp[i].t=PLASMA;wp[i].s=0;
307 wp[i].own=o;
308 throw(i,x,y,xd,yd,2,5,16);
309 return;
313 void WP_ball1 (int x, int y, int xd, int yd, int o) {
314 int i;
316 for(i=0;i<MAXWPN;++i) if(!wp[i].t) {
317 wp[i].t=BALL1;wp[i].s=0;
318 wp[i].own=o;
319 throw(i,x,y,xd,yd,2,5,16);
320 return;
324 void WP_ball2 (int x, int y, int xd, int yd, int o) {
325 int i;
327 for(i=0;i<MAXWPN;++i) if(!wp[i].t) {
328 wp[i].t=BALL2;wp[i].s=0;
329 wp[i].own=o;
330 throw(i,x,y,xd,yd,2,5,16);
331 return;
335 void WP_ball7 (int x, int y, int xd, int yd, int o) {
336 int i;
338 for(i=0;i<MAXWPN;++i) if(!wp[i].t) {
339 wp[i].t=BALL7;wp[i].s=0;
340 wp[i].own=o;
341 throw(i,x,y,xd,yd,2,5,16);
342 return;
346 void WP_aplasma (int x, int y, int xd, int yd, int o) {
347 int i;
349 for(i=0;i<MAXWPN;++i) if(!wp[i].t) {
350 Z_sound(snd[5],64);
351 wp[i].t=APLASMA;wp[i].s=0;
352 wp[i].own=o;
353 throw(i,x,y,xd,yd,2,5,16);
354 return;
358 void WP_manfire (int x, int y, int xd, int yd, int o) {
359 int i;
361 for(i=0;i<MAXWPN;++i) if(!wp[i].t) {
362 Z_sound(snd[6],128);
363 wp[i].t=MANF;wp[i].s=0;
364 wp[i].own=o;
365 throw(i,x,y,xd,yd,5,11,16);
366 return;
370 void WP_bfgshot (int x, int y, int xd, int yd, int o) {
371 int i;
373 for(i=0;i<MAXWPN;++i) if(!wp[i].t) {
374 wp[i].t=BFGBALL;wp[i].s=0;
375 wp[i].own=o;
376 throw(i,x,y,xd,yd,5,12,16);
377 return;
381 void WP_bfghit (int x, int y, int o) {
382 int i;
384 for(i=0;i<MAXWPN;++i) if(!wp[i].t) {
385 wp[i].t=BFGHIT;wp[i].s=0;
386 wp[i].o.x=x;wp[i].o.y=y;
387 wp[i].o.xv=wp[i].o.yv=0;
388 wp[i].o.r=0;wp[i].o.h=1;
389 wp[i].o.vx=wp[i].o.vy=0;
390 wp[i].own=o;
391 return;
395 void WP_pistol (int x,int y,int xd,int yd,int o) {
396 Z_sound(snd[0],96);
397 WP_gun(x,y,xd,yd,o,1);
398 if(g_dm) {
399 WP_gun(x,y+1,xd,yd+1,o,1);
400 WP_gun(x,y-1,xd,yd-1,o,1);
404 void WP_mgun (int x, int y, int xd, int yd, int o) {
405 Z_sound(snd[11],128);
406 WP_gun(x,y,xd,yd,o,1);
409 void WP_shotgun (int x, int y, int xd, int yd, int o) {
410 int i,j;
412 Z_sound(snd[1],128);
413 for(i=0;i<10;++i) {
414 j=myrand(4*2+1)-4;
415 WP_gun(x,y+j,xd,yd+j,o,i&1);
419 void WP_dshotgun (int x, int y, int xd, int yd, int o) {
420 int i,j;
422 Z_sound(snd[2],128);
423 for(i=(g_dm)?25:20;i>=0;--i) {
424 j=myrand(10*2+1)-10;
425 WP_gun(x,y+j,xd,yd+j,o,(i%3)?0:1);
429 void WP_ognemet (int x, int y, int xd, int yd, int xv, int yv, int o) {
430 int m;
432 m=abs(xd-x);if(!m) m=abs(yd-y);
433 SMK_flame(x,y,xv,yv,2,2,(xd-x)*3000/m,(yd-y)*3000/m,1,o);