DEADSOFTWARE

Editing source tree for configuring with CMake
[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 <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{NONE=0,ROCKET,PLASMA,APLASMA,BALL1,BALL2,BALL7,BFGBALL,BFGHIT,
41 MANF,REVF,FIRE};
43 #pragma pack(1)
44 typedef struct{
45 obj_t o;
46 byte t,s;
47 int own;
48 short target;
49 }weapon_t;
50 #pragma pack()
52 static void *snd[14],*spr[49*2];
53 static char sprd[49*2];
54 static weapon_t wp[MAXWPN];
56 static void throw(int,int,int,int,int,int,int,int);
58 void WP_savegame(FILE* h) {
59 int n;
61 for(n=MAXWPN;--n;) if(wp[n].t) break;
62 ++n;myfwrite(&n,1,4,h);myfwrite(wp,1,n*sizeof(wp[0]),h);
63 }
65 void WP_loadgame(FILE* h) {
66 int n;
68 myfread(&n,1,4,h);myfread(wp,1,n*sizeof(wp[0]),h);
69 }
71 void WP_alloc(void) {
72 int i;
73 static char nm[14][6]={
74 "PISTOL",
75 "SHOTGN",
76 "DSHTGN",
77 "RLAUNC",
78 "RXPLOD",
79 "PLASMA",
80 "FIRSHT",
81 "FIRXPL",
82 "BAREXP",
83 "PUNCH",
84 "SAWHIT",
85 "MGUN",
86 "SPARK1",
87 "SPARK2"
88 };
90 for(i=0;i<4;++i) {
91 spr[i*2]=Z_getspr("MISL",i,1,sprd+i*2);
92 spr[i*2+1]=Z_getspr("MISL",i,2,sprd+i*2+1);
93 }
94 for(;i<6;++i) {
95 spr[i*2]=Z_getspr("PLSS",i-4,1,sprd+i*2);
96 spr[i*2+1]=Z_getspr("PLSS",i-4,2,sprd+i*2+1);
97 }
98 for(;i<11;++i) {
99 spr[i*2]=Z_getspr("PLSE",i-6,1,sprd+i*2);
100 spr[i*2+1]=Z_getspr("PLSE",i-6,2,sprd+i*2+1);
102 for(;i<13;++i) {
103 spr[i*2]=Z_getspr("APLS",i-11,1,sprd+i*2);
104 spr[i*2+1]=Z_getspr("APLS",i-11,2,sprd+i*2+1);
106 for(;i<18;++i) {
107 spr[i*2]=Z_getspr("APBX",i-13,1,sprd+i*2);
108 spr[i*2+1]=Z_getspr("APBX",i-13,2,sprd+i*2+1);
110 for(;i<20;++i) {
111 spr[i*2]=Z_getspr("BFS1",i-18,1,sprd+i*2);
112 spr[i*2+1]=Z_getspr("BFS1",i-18,2,sprd+i*2+1);
114 for(;i<26;++i) {
115 spr[i*2]=Z_getspr("BFE1",i-20,1,sprd+i*2);
116 spr[i*2+1]=Z_getspr("BFE1",i-20,2,sprd+i*2+1);
118 for(;i<30;++i) {
119 spr[i*2]=Z_getspr("BFE2",i-26,1,sprd+i*2);
120 spr[i*2+1]=Z_getspr("BFE2",i-26,2,sprd+i*2+1);
122 for(;i<32;++i) {
123 spr[i*2]=Z_getspr("MISL",i-30+4,1,sprd+i*2);
124 spr[i*2+1]=Z_getspr("MISL",i-30+4,2,sprd+i*2+1);
126 for(;i<37;++i) {
127 spr[i*2]=Z_getspr("BAL1",i-32,1,sprd+i*2);
128 spr[i*2+1]=Z_getspr("BAL1",i-32,2,sprd+i*2+1);
130 for(;i<42;++i) {
131 spr[i*2]=Z_getspr("BAL7",i-37,1,sprd+i*2);
132 spr[i*2+1]=Z_getspr("BAL7",i-37,2,sprd+i*2+1);
134 for(;i<47;++i) {
135 spr[i*2]=Z_getspr("BAL2",i-42,1,sprd+i*2);
136 spr[i*2+1]=Z_getspr("BAL2",i-42,2,sprd+i*2+1);
138 for(;i<49;++i) {
139 spr[i*2]=Z_getspr("MANF",i-47,1,sprd+i*2);
140 spr[i*2+1]=Z_getspr("MANF",i-47,2,sprd+i*2+1);
142 for(i=0;i<14;++i) snd[i]=Z_getsnd(nm[i]);
145 void WP_init(void) {
146 int i;
148 for(i=0;i<MAXWPN;++i) wp[i].t=NONE;
151 void WP_act(void) {
152 int i,st;
153 static obj_t o;
155 for(i=0;i<MAXWPN;++i) if(wp[i].t) {
156 if(wp[i].t==ROCKET || wp[i].t==REVF)
157 SMK_gas(wp[i].o.x+Z_sign(wp[i].o.xv)*2,
158 wp[i].o.y-wp[i].o.h/2,3,3,
159 wp[i].o.xv+wp[i].o.vx,wp[i].o.yv+wp[i].o.vy,64
160 );
161 --wp[i].o.yv;st=Z_moveobj(&wp[i].o);
162 if(st&Z_FALLOUT) {wp[i].t=0;continue;}
163 if(st&Z_HITWATER) switch(wp[i].t) {
164 case PLASMA: case APLASMA:
165 case BFGBALL:
166 break;
167 default:
168 Z_splash(&wp[i].o,wp[i].o.r+wp[i].o.h);break;
170 switch(wp[i].t) {
171 case REVF:
172 if(Z_getobjpos(wp[i].target,&o))
173 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);
174 case ROCKET:
175 if(wp[i].s>=2) {if(++wp[i].s>=8) wp[i].t=0; break;}
176 if(st&Z_HITAIR) Z_set_speed(&wp[i].o,12);
177 if(st&(Z_HITWALL|Z_HITCEIL|Z_HITLAND)) {
178 wp[i].s=2;wp[i].o.xv=wp[i].o.yv=0;Z_sound(snd[4],128);
179 Z_explode(wp[i].o.x,wp[i].o.y,30,wp[i].own);break;}
180 else if(Z_hit(&wp[i].o,10,wp[i].own,HIT_SOME)) {
181 wp[i].s=2;wp[i].o.xv=wp[i].o.yv=0;Z_sound(snd[4],128);
182 Z_explode(wp[i].o.x,wp[i].o.y-wp[i].o.h/2,30,wp[i].own);break;}
183 bfg_fly(wp[i].o.x,wp[i].o.y-wp[i].o.h/2,wp[i].own);
184 break;
185 case PLASMA:
186 case APLASMA:
187 if(st&Z_INWATER) {
188 Z_sound(snd[12],128);
189 Z_water_trap(&wp[i].o);
190 Z_chktrap(1,10,wp[i].own,HIT_ELECTRO);
191 Z_untrap(5);
192 wp[i].t=0;break;
194 case BALL1:
195 case BALL7:
196 case BALL2:
197 case MANF:
198 if(wp[i].s>=2)
199 {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;}
200 if(st&Z_HITAIR) Z_set_speed(&wp[i].o,16);
201 if(st&(Z_HITWALL|Z_HITCEIL|Z_HITLAND))
202 {wp[i].s=2;wp[i].o.xv=wp[i].o.yv=0;Z_sound(snd[7],128);break;}
203 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))
204 {wp[i].s=2;wp[i].o.xv=wp[i].o.yv=0;Z_sound(snd[7],128);break;}
205 wp[i].s^=1;break;
206 case BFGBALL:
207 if(st&Z_INWATER) {
208 Z_sound(snd[8],40);Z_sound(snd[13],128);
209 Z_water_trap(&wp[i].o);
210 Z_chktrap(1,1000,wp[i].own,HIT_ELECTRO);
211 Z_untrap(5);
212 wp[i].t=0;break;
214 if(wp[i].s>=2) {if(++wp[i].s>=14) wp[i].t=0; break;}
215 else if(st&(Z_HITWALL|Z_HITCEIL|Z_HITLAND)) {
216 Z_bfg9000(wp[i].o.x,wp[i].o.y,wp[i].own);
217 wp[i].s=2;wp[i].o.xv=wp[i].o.yv=0;Z_sound(snd[8],128);break;}
218 else if(Z_hit(&wp[i].o,100,wp[i].own,HIT_BFG)) {
219 Z_bfg9000(wp[i].o.x,wp[i].o.y,wp[i].own);
220 wp[i].s=2;wp[i].o.xv=wp[i].o.yv=0;Z_sound(snd[8],128);break;}
221 bfg_fly(wp[i].o.x,wp[i].o.y-wp[i].o.h/2,wp[i].own);
222 wp[i].s^=1;break;
223 case BFGHIT:
224 if(++wp[i].s>=8) wp[i].t=0;
225 break;
226 default: break;
231 void WP_draw(void) {
232 int i,s,d,x,y;
234 for(i=0;i<MAXWPN;++i) {
235 s=-1;d=0;
236 switch(wp[i].t) {
237 case NONE: default: break;
238 case REVF:
239 case ROCKET:
240 if((d=wp[i].s)<2) {
241 d=(wp[i].o.xv>0)?1:0;
242 x=abs(wp[i].o.xv);y=wp[i].o.yv;s=0;
243 if(y<0) {if(-y>=x) s=30;}
244 else if(y>0) if(y>=x/2) s=31;
245 }else {s=(d-2)/2+1;d=0;}
246 break;
247 case MANF:
248 if((s=wp[i].s)>=2) {s/=2;break;}
249 case PLASMA:
250 case APLASMA:
251 case BALL1:
252 case BALL7:
253 case BALL2:
254 if((s=wp[i].s)>=2) s=s/2+1;
255 switch(wp[i].t) {
256 case PLASMA: s+=4;break;
257 case APLASMA: s+=11;break;
258 case BALL1: s+=32;break;
259 case BALL2: s+=42;break;
260 case BALL7: s+=37;d=(wp[i].o.xv>=0)?1:0;break;
261 case MANF: s+=47;d=(wp[i].o.xv>=0)?1:0;break;
262 }break;
263 case BFGBALL:
264 if((s=wp[i].s)>=2) s=s/2+1;
265 s+=18;break;
266 case BFGHIT:
267 s=wp[i].s/2+26;break;
269 if(s>=0) Z_drawspr(wp[i].o.x,wp[i].o.y,spr[s*2+d],sprd[s*2+d]);
273 void WP_gun(int x,int y,int xd,int yd,int o,int v) {
274 register dword d,m;
275 int sx,sy,lx,ly;
276 dword xe,ye,s;
277 byte f;
279 f=BM_MONSTER|BM_WALL;
280 if(o!=-1) f|=BM_PLR1;
281 if(o!=-2) f|=BM_PLR2;
282 if((xd-=x)>0) sx=1;
283 else if(xd<0) sx=-1;
284 else sx=0;
285 if((yd-=y)>0) sy=1;
286 else if(yd<0) sy=-1;
287 else sy=0;
288 if(!xd && !yd) return;
289 if((xd=abs(xd)) > (yd=abs(yd))) d=xd; else d=yd;
290 hit_xv=xd*10/d*sx;
291 hit_yv=yd*10/d*sy;
292 xe=ye=0;
293 lx=x;ly=y;
294 for(;;) {
295 if(x<0 || x>=FLDW*8 || y<0 || y>=FLDH*8) break;
296 if(((m=bmap[y>>5][x>>5])&f)) {
297 if(m&BM_WALL) if(fld[y>>3][x>>3]==1 || fld[y>>3][x>>3]==2) {
298 for(x=lx,y=ly,xe=ye=0;fld[y>>3][x>>3]!=1 && fld[y>>3][x>>3]!=2;) {
299 lx=x;ly=y;
300 if((xe+=xd)>=d) {xe-=d;x+=sx;}
301 if((ye+=yd)>=d) {ye-=d;y+=sy;}
303 DOT_spark(lx,ly,sx*10,sy*10,1);
304 break;
306 if(m&(BM_MONSTER|BM_PLR1|BM_PLR2)) if(Z_gunhit(x,y,o,sx*v,sy*v)) break;
307 lx=x;ly=y;
308 if((xe+=(xd<<3))>=d) {
309 x+=xe/d*sx;xe=xe%d;
311 if((ye+=(yd<<3))>=d) {
312 y+=ye/d*sy;ye=ye%d;
314 }else{
315 if(sx==0) m=0;
316 else{m=x&31;if(sx>0) m^=31; ++m;}
317 if(sy==0) s=0;
318 else{s=y&31;if(sy>0) s^=31; ++s;}
319 if((s<m && s!=0) || m==0) m=s;
320 lx=x;ly=y;
321 x+=(xd*m+xe)/d*sx;xe=(xd*m+xe)%d;
322 y+=(yd*m+ye)/d*sy;ye=(yd*m+ye)%d;
327 void WP_punch(int x,int y,int d,int own) {
328 obj_t o;
330 o.x=x;o.y=y;o.r=12;o.h=26;
331 o.xv=o.yv=o.vx=o.vy=0;
332 if(Z_hit(&o,d,own,HIT_SOME)) Z_sound(snd[9],128);
335 int WP_chainsaw(int x,int y,int d,int own) {
336 obj_t o;
338 o.x=x;o.y=y;o.r=12;o.h=26;
339 o.xv=o.yv=o.vx=o.vy=0;
340 if(Z_hit(&o,d,own,HIT_SOME)) return 1;
341 return 0;
344 static void throw(int i,int x,int y,int xd,int yd,int r,int h,int s) {
345 int m;
347 wp[i].o.x=x;wp[i].o.y=y+h/2;
348 yd-=y;xd-=x;
349 if(!(m=max(abs(xd),abs(yd)))) m=1;
350 wp[i].o.xv=xd*s/m;wp[i].o.yv=yd*s/m;
351 wp[i].o.r=r;wp[i].o.h=h;
352 wp[i].o.vx=wp[i].o.vy=0;
355 void WP_rocket(int x,int y,int xd,int yd,int o) {
356 int i;
358 for(i=0;i<MAXWPN;++i) if(!wp[i].t) {
359 Z_sound(snd[3],128);
360 wp[i].t=ROCKET;wp[i].s=(xd>=x)?1:0;
361 wp[i].own=o;
362 throw(i,x,y,xd,yd,2,5,12);
363 return;
367 void WP_revf(int x,int y,int xd,int yd,int o,int t) {
368 int i;
370 for(i=0;i<MAXWPN;++i) if(!wp[i].t) {
371 Z_sound(snd[3],128);
372 wp[i].t=REVF;wp[i].s=(xd>=x)?1:0;
373 wp[i].own=o;wp[i].target=t;
374 throw(i,x,y,xd,yd,2,5,12);
375 return;
379 void WP_plasma(int x,int y,int xd,int yd,int o) {
380 int i;
382 for(i=0;i<MAXWPN;++i) if(!wp[i].t) {
383 Z_sound(snd[5],64);
384 wp[i].t=PLASMA;wp[i].s=0;
385 wp[i].own=o;
386 throw(i,x,y,xd,yd,2,5,16);
387 return;
391 void WP_ball1(int x,int y,int xd,int yd,int o) {
392 int i;
394 for(i=0;i<MAXWPN;++i) if(!wp[i].t) {
395 wp[i].t=BALL1;wp[i].s=0;
396 wp[i].own=o;
397 throw(i,x,y,xd,yd,2,5,16);
398 return;
402 void WP_ball2(int x,int y,int xd,int yd,int o) {
403 int i;
405 for(i=0;i<MAXWPN;++i) if(!wp[i].t) {
406 wp[i].t=BALL2;wp[i].s=0;
407 wp[i].own=o;
408 throw(i,x,y,xd,yd,2,5,16);
409 return;
413 void WP_ball7(int x,int y,int xd,int yd,int o) {
414 int i;
416 for(i=0;i<MAXWPN;++i) if(!wp[i].t) {
417 wp[i].t=BALL7;wp[i].s=0;
418 wp[i].own=o;
419 throw(i,x,y,xd,yd,2,5,16);
420 return;
424 void WP_aplasma(int x,int y,int xd,int yd,int o) {
425 int i;
427 for(i=0;i<MAXWPN;++i) if(!wp[i].t) {
428 Z_sound(snd[5],64);
429 wp[i].t=APLASMA;wp[i].s=0;
430 wp[i].own=o;
431 throw(i,x,y,xd,yd,2,5,16);
432 return;
436 void WP_manfire(int x,int y,int xd,int yd,int o) {
437 int i;
439 for(i=0;i<MAXWPN;++i) if(!wp[i].t) {
440 Z_sound(snd[6],128);
441 wp[i].t=MANF;wp[i].s=0;
442 wp[i].own=o;
443 throw(i,x,y,xd,yd,5,11,16);
444 return;
448 void WP_bfgshot(int x,int y,int xd,int yd,int o) {
449 int i;
451 for(i=0;i<MAXWPN;++i) if(!wp[i].t) {
452 wp[i].t=BFGBALL;wp[i].s=0;
453 wp[i].own=o;
454 throw(i,x,y,xd,yd,5,12,16);
455 return;
459 void WP_bfghit(int x,int y,int o) {
460 int i;
462 for(i=0;i<MAXWPN;++i) if(!wp[i].t) {
463 wp[i].t=BFGHIT;wp[i].s=0;
464 wp[i].o.x=x;wp[i].o.y=y;
465 wp[i].o.xv=wp[i].o.yv=0;
466 wp[i].o.r=0;wp[i].o.h=1;
467 wp[i].o.vx=wp[i].o.vy=0;
468 wp[i].own=o;
469 return;
473 void WP_pistol(int x,int y,int xd,int yd,int o) {
474 Z_sound(snd[0],96);
475 WP_gun(x,y,xd,yd,o,1);
476 if(g_dm) {
477 WP_gun(x,y+1,xd,yd+1,o,1);
478 WP_gun(x,y-1,xd,yd-1,o,1);
482 void WP_mgun(int x,int y,int xd,int yd,int o) {
483 Z_sound(snd[11],128);
484 WP_gun(x,y,xd,yd,o,1);
487 void WP_shotgun(int x,int y,int xd,int yd,int o) {
488 int i,j;
490 Z_sound(snd[1],128);
491 for(i=0;i<10;++i) {
492 j=myrand(4*2+1)-4;
493 WP_gun(x,y+j,xd,yd+j,o,i&1);
497 void WP_dshotgun(int x,int y,int xd,int yd,int o) {
498 int i,j;
500 Z_sound(snd[2],128);
501 for(i=(g_dm)?25:20;i>=0;--i) {
502 j=myrand(10*2+1)-10;
503 WP_gun(x,y+j,xd,yd+j,o,(i%3)?0:1);
507 void WP_ognemet(int x,int y,int xd,int yd,int xv,int yv,int o) {
508 int m;
510 m=abs(xd-x);if(!m) m=abs(yd-y);
511 SMK_flame(x,y,xv,yv,2,2,(xd-x)*3000/m,(yd-y)*3000/m,1,o);