install: add install sources and resources
[doom2d-restoration.git] / GAME / WEAPONS.C
blob0d2c884009337eee017205cddec558a9cf0e93a3
1 #include "glob.h"
2 #include <stdlib.h>
3 #include <io.h>
4 #include "vga.h"
5 #include "error.h"
6 #include "sound.h"
7 #include "view.h"
8 #include "bmap.h"
9 #include "dots.h"
10 #include "smoke.h"
11 #include "weapons.h"
12 #include "misc.h"
14 extern int hit_xv,hit_yv;
16 void bfg_fly(int x,int y,int own);
18 enum{NONE=0,ROCKET,PLASMA,APLASMA,BALL1,BALL2,BALL7,BFGBALL,BFGHIT,
19      MANF,REVF,FIRE};
21 typedef struct{
22   obj_t o;
23   byte t,s;
24   int own;
25   short target;
26 }weapon_t;
28 static void *snd[14],*spr[49*2];
29 static char sprd[49*2];
30 static weapon_t wp[MAXWPN];
32 static void throw(int,int,int,int,int,int,int,int);
34 void WP_savegame(int h) {
35   int n;
37   for(n=MAXWPN;--n;) if(wp[n].t) break;
38   ++n;write(h,&n,4);write(h,wp,n*sizeof(wp[0]));
41 void WP_loadgame(int h) {
42   int n;
44   read(h,&n,4);read(h,wp,n*sizeof(wp[0]));
47 void WP_alloc(void) {
48   int i;
49   static char nm[14][6]={
50         "PISTOL",
51         "SHOTGN",
52         "DSHTGN",
53         "RLAUNC",
54         "RXPLOD",
55         "PLASMA",
56         "FIRSHT",
57         "FIRXPL",
58         "BAREXP",
59         "PUNCH",
60         "SAWHIT",
61         "MGUN",
62         "SPARK1",
63         "SPARK2"
64   };
66 //  logo("  weapons");
67   for(i=0;i<4;++i) {
68         spr[i*2]=Z_getspr("MISL",i,1,sprd+i*2);
69         spr[i*2+1]=Z_getspr("MISL",i,2,sprd+i*2+1);
70   }
71   for(;i<6;++i) {
72         spr[i*2]=Z_getspr("PLSS",i-4,1,sprd+i*2);
73         spr[i*2+1]=Z_getspr("PLSS",i-4,2,sprd+i*2+1);
74   }
75   for(;i<11;++i) {
76     spr[i*2]=Z_getspr("PLSE",i-6,1,sprd+i*2);
77     spr[i*2+1]=Z_getspr("PLSE",i-6,2,sprd+i*2+1);
78   }
79   for(;i<13;++i) {
80     spr[i*2]=Z_getspr("APLS",i-11,1,sprd+i*2);
81     spr[i*2+1]=Z_getspr("APLS",i-11,2,sprd+i*2+1);
82   }
83   for(;i<18;++i) {
84     spr[i*2]=Z_getspr("APBX",i-13,1,sprd+i*2);
85     spr[i*2+1]=Z_getspr("APBX",i-13,2,sprd+i*2+1);
86   }
87   for(;i<20;++i) {
88     spr[i*2]=Z_getspr("BFS1",i-18,1,sprd+i*2);
89     spr[i*2+1]=Z_getspr("BFS1",i-18,2,sprd+i*2+1);
90   }
91   for(;i<26;++i) {
92         spr[i*2]=Z_getspr("BFE1",i-20,1,sprd+i*2);
93         spr[i*2+1]=Z_getspr("BFE1",i-20,2,sprd+i*2+1);
94   }
95   for(;i<30;++i) {
96     spr[i*2]=Z_getspr("BFE2",i-26,1,sprd+i*2);
97     spr[i*2+1]=Z_getspr("BFE2",i-26,2,sprd+i*2+1);
98   }
99   for(;i<32;++i) {
100     spr[i*2]=Z_getspr("MISL",i-30+4,1,sprd+i*2);
101     spr[i*2+1]=Z_getspr("MISL",i-30+4,2,sprd+i*2+1);
102   }
103   for(;i<37;++i) {
104         spr[i*2]=Z_getspr("BAL1",i-32,1,sprd+i*2);
105         spr[i*2+1]=Z_getspr("BAL1",i-32,2,sprd+i*2+1);
106   }
107   for(;i<42;++i) {
108         spr[i*2]=Z_getspr("BAL7",i-37,1,sprd+i*2);
109         spr[i*2+1]=Z_getspr("BAL7",i-37,2,sprd+i*2+1);
110   }
111   for(;i<47;++i) {
112         spr[i*2]=Z_getspr("BAL2",i-42,1,sprd+i*2);
113         spr[i*2+1]=Z_getspr("BAL2",i-42,2,sprd+i*2+1);
114   }
115   for(;i<49;++i) {
116         spr[i*2]=Z_getspr("MANF",i-47,1,sprd+i*2);
117         spr[i*2+1]=Z_getspr("MANF",i-47,2,sprd+i*2+1);
118   }
119   for(i=0;i<14;++i) snd[i]=Z_getsnd(nm[i]);
122 void WP_init(void) {
123   int i;
125   for(i=0;i<MAXWPN;++i) wp[i].t=NONE;
128 void WP_act(void) {
129   int i,st;
130   static obj_t o;
132   for(i=0;i<MAXWPN;++i) if(wp[i].t) {
133         if(wp[i].t==ROCKET || wp[i].t==REVF)
134           SMK_gas(wp[i].o.x+Z_sign(wp[i].o.xv)*2,
135             wp[i].o.y-wp[i].o.h/2,3,3,
136             wp[i].o.xv+wp[i].o.vx,wp[i].o.yv+wp[i].o.vy,64
137           );
138         --wp[i].o.yv;st=Z_moveobj(&wp[i].o);
139         if(st&Z_FALLOUT) {wp[i].t=0;continue;}
140         if(st&Z_HITWATER) switch(wp[i].t) {
141           case PLASMA: case APLASMA:
142           case BFGBALL:
143                 break;
144           default:
145                 Z_splash(&wp[i].o,wp[i].o.r+wp[i].o.h);break;
146         }
147         switch(wp[i].t) {
148           case REVF:
149                 if(Z_getobjpos(wp[i].target,&o))
150                   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);
151           case ROCKET:
152                 if(wp[i].s>=2) {if(++wp[i].s>=8) wp[i].t=0; break;}
153                 if(st&Z_HITAIR) Z_set_speed(&wp[i].o,12);
154                 if(st&(Z_HITWALL|Z_HITCEIL|Z_HITLAND)) {
155                   wp[i].s=2;wp[i].o.xv=wp[i].o.yv=0;Z_sound(snd[4],128);
156                   Z_explode(wp[i].o.x,wp[i].o.y,30,wp[i].own);break;}
157                 else if(Z_hit(&wp[i].o,10,wp[i].own,HIT_SOME)) {
158                   wp[i].s=2;wp[i].o.xv=wp[i].o.yv=0;Z_sound(snd[4],128);
159                   Z_explode(wp[i].o.x,wp[i].o.y-wp[i].o.h/2,30,wp[i].own);break;}
160                 bfg_fly(wp[i].o.x,wp[i].o.y-wp[i].o.h/2,wp[i].own);
161                 break;
162           case PLASMA:
163           case APLASMA:
164                 if(st&Z_INWATER) {
165                   Z_sound(snd[12],128);
166                   Z_water_trap(&wp[i].o);
167                   Z_chktrap(1,10,wp[i].own,HIT_ELECTRO);
168                   Z_untrap(5);
169                   wp[i].t=0;break;
170                 }
171           case BALL1:
172           case BALL7:
173           case BALL2:
174           case MANF:
175                 if(wp[i].s>=2)
176                   {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;}
177                 if(st&Z_HITAIR) Z_set_speed(&wp[i].o,16);
178                 if(st&(Z_HITWALL|Z_HITCEIL|Z_HITLAND))
179                   {wp[i].s=2;wp[i].o.xv=wp[i].o.yv=0;Z_sound(snd[7],128);break;}
180                 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))
181                   {wp[i].s=2;wp[i].o.xv=wp[i].o.yv=0;Z_sound(snd[7],128);break;}
182                 wp[i].s^=1;break;
183           case BFGBALL:
184                 if(st&Z_INWATER) {
185                   Z_sound(snd[8],40);Z_sound(snd[13],128);
186                   Z_water_trap(&wp[i].o);
187                   Z_chktrap(1,1000,wp[i].own,HIT_ELECTRO);
188                   Z_untrap(5);
189                   wp[i].t=0;break;
190                 }
191                 if(wp[i].s>=2) {if(++wp[i].s>=14) wp[i].t=0; break;}
192                 else if(st&(Z_HITWALL|Z_HITCEIL|Z_HITLAND)) {
193                   Z_bfg9000(wp[i].o.x,wp[i].o.y,wp[i].own);
194                   wp[i].s=2;wp[i].o.xv=wp[i].o.yv=0;Z_sound(snd[8],128);break;}
195                 else if(Z_hit(&wp[i].o,100,wp[i].own,HIT_BFG)) {
196                   Z_bfg9000(wp[i].o.x,wp[i].o.y,wp[i].own);
197                   wp[i].s=2;wp[i].o.xv=wp[i].o.yv=0;Z_sound(snd[8],128);break;}
198                 bfg_fly(wp[i].o.x,wp[i].o.y-wp[i].o.h/2,wp[i].own);
199                 wp[i].s^=1;break;
200           case BFGHIT:
201                 if(++wp[i].s>=8) wp[i].t=0;
202                 break;
203           default: break;
204         }
205   }
208 void WP_draw(void) {
209   int i,s,d,x,y;
211   for(i=0;i<MAXWPN;++i) {
212     s=-1;d=0;
213     switch(wp[i].t) {
214       case NONE: default: break;
215       case REVF:
216       case ROCKET:
217                 if((d=wp[i].s)<2) {
218                   d=(wp[i].o.xv>0)?1:0;
219                   x=abs(wp[i].o.xv);y=wp[i].o.yv;s=0;
220                   if(y<0) {if(-y>=x) s=30;}
221                   else if(y>0) if(y>=x/2) s=31;
222                 }else {s=(d-2)/2+1;d=0;}
223                 break;
224           case MANF:
225             if((s=wp[i].s)>=2) {s/=2;break;}
226           case PLASMA:
227           case APLASMA:
228           case BALL1:
229           case BALL7:
230           case BALL2:
231                 if((s=wp[i].s)>=2) s=s/2+1;
232                 switch(wp[i].t) {
233                   case PLASMA: s+=4;break;
234                   case APLASMA: s+=11;break;
235                   case BALL1: s+=32;break;
236                   case BALL2: s+=42;break;
237                   case BALL7: s+=37;d=(wp[i].o.xv>=0)?1:0;break;
238                   case MANF: s+=47;d=(wp[i].o.xv>=0)?1:0;break;
239                 }break;
240           case BFGBALL:
241                 if((s=wp[i].s)>=2) s=s/2+1;
242                 s+=18;break;
243           case BFGHIT:
244                 s=wp[i].s/2+26;break;
245     }
246     if(s>=0) Z_drawspr(wp[i].o.x,wp[i].o.y,spr[s*2+d],sprd[s*2+d]);
247   }
250 void WP_gun(int x,int y,int xd,int yd,int o,int v) {
251   register dword d,m;
252   int sx,sy,lx,ly;
253   dword xe,ye,s;
254   byte f;
256   f=BM_MONSTER|BM_WALL;
257   if(o!=-1) f|=BM_PLR1;
258   if(o!=-2) f|=BM_PLR2;
259   if((xd-=x)>0) sx=1;
260   else if(xd<0) sx=-1;
261   else sx=0;
262   if((yd-=y)>0) sy=1;
263   else if(yd<0) sy=-1;
264   else sy=0;
265   if(!xd && !yd) return;
266   if((xd=abs(xd)) > (yd=abs(yd))) d=xd; else d=yd;
267   hit_xv=xd*10/d*sx;
268   hit_yv=yd*10/d*sy;
269   xe=ye=0;
270   lx=x;ly=y;
271   for(;;) {
272         if(x<0 || x>=FLDW*8 || y<0 || y>=FLDH*8) break;
273         if(((m=bmap[y>>5][x>>5])&f)) {
274 //        if(y>=(FLDH-4)*8) m=f;
275           if(m&BM_WALL) if(fld[y>>3][x>>3]==1 || fld[y>>3][x>>3]==2) {
276                 for(x=lx,y=ly,xe=ye=0;fld[y>>3][x>>3]!=1 && fld[y>>3][x>>3]!=2;) {
277                   lx=x;ly=y;
278                   if((xe+=xd)>=d) {xe-=d;x+=sx;}
279                   if((ye+=yd)>=d) {ye-=d;y+=sy;}
280                 }
281                 DOT_spark(lx,ly,sx*10,sy*10,1);
282                 break;
283           }
284           if(m&(BM_MONSTER|BM_PLR1|BM_PLR2)) if(Z_gunhit(x,y,o,sx*v,sy*v)) break;
285           lx=x;ly=y;
286           if((xe+=(xd<<3))>=d) {
287                 x+=xe/d*sx;xe=xe%d;
288           }
289           if((ye+=(yd<<3))>=d) {
290                 y+=ye/d*sy;ye=ye%d;
291           }
292         }else{
293           if(sx==0) m=0;
294           else{m=x&31;if(sx>0) m^=31; ++m;}
295           if(sy==0) s=0;
296           else{s=y&31;if(sy>0) s^=31; ++s;}
297           if((s<m && s!=0) || m==0) m=s;
298           lx=x;ly=y;
299                 x+=(xd*m+xe)/d*sx;xe=(xd*m+xe)%d;
300                 y+=(yd*m+ye)/d*sy;ye=(yd*m+ye)%d;
301         }
302   }
305 void WP_punch(int x,int y,int d,int own) {
306   obj_t o;
308   o.x=x;o.y=y;o.r=12;o.h=26;
309   o.xv=o.yv=o.vx=o.vy=0;
310   if(Z_hit(&o,d,own,HIT_SOME)) Z_sound(snd[9],128);
313 int WP_chainsaw(int x,int y,int d,int own) {
314   obj_t o;
316   o.x=x;o.y=y;o.r=12;o.h=26;
317   o.xv=o.yv=o.vx=o.vy=0;
318   if(Z_hit(&o,d,own,HIT_SOME)) return 1;
319   return 0;
322 static void throw(int i,int x,int y,int xd,int yd,int r,int h,int s) {
323   int m;
325   wp[i].o.x=x;wp[i].o.y=y+h/2;
326   yd-=y;xd-=x;
327   if(!(m=max(abs(xd),abs(yd)))) m=1;
328   wp[i].o.xv=xd*s/m;wp[i].o.yv=yd*s/m;
329   wp[i].o.r=r;wp[i].o.h=h;
330   wp[i].o.vx=wp[i].o.vy=0;
333 void WP_rocket(int x,int y,int xd,int yd,int o) {
334   int i;
336   for(i=0;i<MAXWPN;++i) if(!wp[i].t) {
337     Z_sound(snd[3],128);
338     wp[i].t=ROCKET;wp[i].s=(xd>=x)?1:0;
339         wp[i].own=o;
340         throw(i,x,y,xd,yd,2,5,12);
341         return;
342   }
345 void WP_revf(int x,int y,int xd,int yd,int o,int t) {
346   int i;
348   for(i=0;i<MAXWPN;++i) if(!wp[i].t) {
349     Z_sound(snd[3],128);
350     wp[i].t=REVF;wp[i].s=(xd>=x)?1:0;
351         wp[i].own=o;wp[i].target=t;
352         throw(i,x,y,xd,yd,2,5,12);
353         return;
354   }
357 void WP_plasma(int x,int y,int xd,int yd,int o) {
358   int i;
360   for(i=0;i<MAXWPN;++i) if(!wp[i].t) {
361     Z_sound(snd[5],64);
362     wp[i].t=PLASMA;wp[i].s=0;
363         wp[i].own=o;
364         throw(i,x,y,xd,yd,2,5,16);
365     return;
366   }
369 void WP_ball1(int x,int y,int xd,int yd,int o) {
370   int i;
372   for(i=0;i<MAXWPN;++i) if(!wp[i].t) {
373         wp[i].t=BALL1;wp[i].s=0;
374         wp[i].own=o;
375         throw(i,x,y,xd,yd,2,5,16);
376         return;
377   }
380 void WP_ball2(int x,int y,int xd,int yd,int o) {
381   int i;
383   for(i=0;i<MAXWPN;++i) if(!wp[i].t) {
384         wp[i].t=BALL2;wp[i].s=0;
385         wp[i].own=o;
386         throw(i,x,y,xd,yd,2,5,16);
387         return;
388   }
391 void WP_ball7(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=BALL7;wp[i].s=0;
396         wp[i].own=o;
397         throw(i,x,y,xd,yd,2,5,16);
398         return;
399   }
402 void WP_aplasma(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         Z_sound(snd[5],64);
407         wp[i].t=APLASMA;wp[i].s=0;
408         wp[i].own=o;
409         throw(i,x,y,xd,yd,2,5,16);
410         return;
411   }
414 void WP_manfire(int x,int y,int xd,int yd,int o) {
415   int i;
417   for(i=0;i<MAXWPN;++i) if(!wp[i].t) {
418         Z_sound(snd[6],128);
419         wp[i].t=MANF;wp[i].s=0;
420         wp[i].own=o;
421         throw(i,x,y,xd,yd,5,11,16);
422         return;
423   }
426 void WP_bfgshot(int x,int y,int xd,int yd,int o) {
427   int i;
429   for(i=0;i<MAXWPN;++i) if(!wp[i].t) {
430     wp[i].t=BFGBALL;wp[i].s=0;
431         wp[i].own=o;
432         throw(i,x,y,xd,yd,5,12,16);
433         return;
434   }
437 void WP_bfghit(int x,int y,int o) {
438   int i;
440   for(i=0;i<MAXWPN;++i) if(!wp[i].t) {
441     wp[i].t=BFGHIT;wp[i].s=0;
442     wp[i].o.x=x;wp[i].o.y=y;
443     wp[i].o.xv=wp[i].o.yv=0;
444     wp[i].o.r=0;wp[i].o.h=1;
445     wp[i].o.vx=wp[i].o.vy=0;
446     wp[i].own=o;
447     return;
448   }
451 void WP_pistol(int x,int y,int xd,int yd,int o) {
452   Z_sound(snd[0],96);
453   WP_gun(x,y,xd,yd,o,1);
454   if(g_dm) {
455     WP_gun(x,y+1,xd,yd+1,o,1);
456     WP_gun(x,y-1,xd,yd-1,o,1);
457   }
460 void WP_mgun(int x,int y,int xd,int yd,int o) {
461   Z_sound(snd[11],128);
462   WP_gun(x,y,xd,yd,o,1);
463 //  WP_gun(x,y+1,xd,yd+1,o,1);
466 void WP_shotgun(int x,int y,int xd,int yd,int o) {
467   int i,j;
469   Z_sound(snd[1],128);
470   for(i=0;i<10;++i) {
471     j=random(4*2+1)-4;
472     WP_gun(x,y+j,xd,yd+j,o,i&1);
473   }
476 void WP_dshotgun(int x,int y,int xd,int yd,int o) {
477   int i,j;
479   Z_sound(snd[2],128);
480   for(i=(g_dm)?25:20;i>=0;--i) {
481     j=random(10*2+1)-10;
482     WP_gun(x,y+j,xd,yd+j,o,(i%3)?0:1);
483   }
486 void WP_ognemet(int x,int y,int xd,int yd,int xv,int yv,int o) {
487   int m;
489   m=abs(xd-x);if(!m) m=abs(yd-y);
490   SMK_flame(x,y,xv,yv,2,2,(xd-x)*3000/m,(yd-y)*3000/m,1,o);