DEADSOFTWARE

5cf27f446e180fe3fe8d6b4d14e20052f830feba
[flatwaifu.git] / src / monster.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 <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include "vga.h"
28 #include "files.h"
29 #include "error.h"
30 #include "view.h"
31 #include "bmap.h"
32 #include "dots.h"
33 #include "weapons.h"
34 #include "player.h"
35 #include "monster.h"
36 #include "items.h"
37 #include "switch.h"
38 #include "misc.h"
39 #include "fx.h"
40 #include "smoke.h"
42 #define MANCOLOR 0xD0
44 #define MAX_ATM 90
46 #define MN_TN (MN__LAST-MN_DEMON)
48 extern byte z_mon;
50 enum{
51 SLEEP,GO,RUN,CLIMB,DIE,DEAD,ATTACK,SHOOT,PAIN,WAIT,REVIVE,RUNOUT
52 };
54 #pragma pack(1)
55 typedef struct{
56 obj_t o;
57 byte t,d,st,ftime;
58 int fobj;
59 int s;
60 char *ap;
61 int aim,life,pain,ac,tx,ty,ammo;
62 short atm;
63 }mn_t;
64 #pragma pack(0)
66 typedef struct{
67 int r,h,l,mp,rv,jv,sp,minp;
68 }mnsz_t;
70 byte nomon=1;
72 static char *sleepanim[MN_TN]={
73 "AAABBB","AAABBB","AAABBB","AAABBB","AAABBB","AAABBB","AAABBB","AAABBB",
74 "A","AAABBB","AAABBB","AAABBB","AAABBB","AAABBB","AAABBB","AAABBB","AAABBB",
75 "A","A","AAABBB"
76 }, *goanim[MN_TN]={
77 "AABBCCDD","AABBCCDD","AABBDDAACCDD","AABBDDAACCDD","AABBDDCCDDBB",
78 "AABBDDAACCDD","AABBCCDD","AABBCCDD","A","AABB","AABBCCBB",
79 "AABBCCDDEEFF","AABBCCDDEEFF","AABBCCDDEEFF","AABBCCDDEEFF","AABBCCDDEEFF",
80 "AABB","A","DDEEFFGGHHIIJJKKLLAABBCC","ACDABD"
81 }, *painanim[MN_TN]={
82 "H","H","G","G","G","G","H","H","F","E","G","I","I","J","L","Q","EECCDDCC",
83 "A","D","G"
84 }, *waitanim[MN_TN]={
85 "A","A","A","A","A","A","A","A","A","AABB","A","A","A","I","K","A","A",
86 "A","D","E"
87 }, *attackanim[MN_TN]={
88 "EEFFGG","EEFFGG","EEEEEF","EEEEEF","EEEEEF","EF","EEFFGG","EEFFGG",
89 "BBCCDD","CCDD","DDEEFF","GH","GH","GGGGHH","GGHHII",
90 "QQGGGHHHIIJJKKLLMMNNOOPP","BBFFAA","A","OOPPQQ","EEEEFF"
91 }, *dieanim[MN_TN]={
92 "IIIJJJKKKLLLMMM","IIIJJJKKKLLL","HHHIIIJJJKKK","HHHIIIJJJKKK",
93 "HHHIIIJJJKKKLLLMMMNNNOOO","HHHIIIJJJKKKLLLMMM",
94 "IIIJJJKKKLLLMMMNNN","IIIJJJKKKLLLMMMNNN","GGGHHHIIIJJJKKK",
95 "FFFGGGHHHIIIJJJKKK","HHHIIIJJJKKKLLLMMM",
96 "JJJJKKKKLLLLMMMMNNNNOOOOPPPPQQQQRRRR","JJJKKKLLLMMMNNNOOO",
97 "KKKLLLMMMNNNOOOPPPRRRSSS","MMMNNNOOOPPP","RRRSSSTTTUUUVVVWWWXXXYYY",
98 "DDDD","CCCDDDEEEFFFGGG","D","HHHHIIIIJJJJKKKKLLLLMMMM"
99 }, *slopanim[MN_TN]={
100 "","NNNOOOPPPRRRSSSTTT","MMMNNNOOOPPPRRRSSSTTT","MMMNNNOOOPPPRRRSSSTTT","",
101 "OOOPPPQQQRRRSSS","","","","","","","","","","","","","","OOPPQQRRSSTTUUVV"
102 }, *deadanim[MN_TN]={
103 "N","M","L","L","P","N","O","O","L","","","S","P","T","Q","Z","C","","D","N"
104 }, *messanim[MN_TN]={
105 "","U","U","U","","T","","","","","","","","","","","","","","W"
106 };
108 int hit_xv,hit_yv;
110 static void *spr[MN_TN][29*2],*fspr[8],*fsnd,*pauksnd,*trupsnd,*sgun[2];
111 static char sprd[MN_TN][29*2];
112 static void *snd[MN_TN][5],*impsitsnd[2],*impdthsnd[2],*firsnd,*slopsnd,*gsnd[4];
113 static void *swgsnd,*pchsnd,*pl_spr[2],*telesnd;
114 static void *positsnd[3],*podthsnd[3];
115 static mn_t mn[MAXMN];
116 static int mnum,gsndt;
117 static mnsz_t mnsz[MN_TN+1]={
118 //rad ht life pain rv jv slop min_pn
119 0, 0, 0, 0, 0, 0, 0, 0, // none
120 15, 28, 60, 20, 7,10, 0, 10, // demon
121 10, 28, 25, 15, 3,10, 30, 0, // imp
122 10, 28, 15, 10, 3,10, 30, 0, // zomby
123 10, 28, 20, 10, 3,10, 30, 0, // sergeant
124 20, 55, 500, 70, 5,10, 0, 50, // cyberdemon
125 12, 28, 60, 20, 3,10, 30, 10, // chaingunner
126 12, 32, 150, 40, 3,10, 0, 30, // baron of hell
127 12, 32, 75, 40, 3,10, 0, 30, // hell knight
128 15, 28, 100, 10, 4, 4, 0, 0, // cacodemon
129 8, 18, 60, 10, 4, 4, 0, 0, // lost soul
130 15, 28, 100, 10, 4, 4, 0, 0, // pain elemental
131 64, 50, 500, 70, 4,10, 0, 50, // spider mastermind
132 25, 27, 150, 20, 4,10, 0, 0, // arachnotron
133 18, 30, 200, 40, 3, 7, 0, 20, // mancubus
134 17, 36, 200, 40, 6,11, 0, 20, // revenant
135 17, 36, 150, 30, 7,12, 0, 10, // archvile
136 5, 5, 35, 20,14, 6, 0, 10, // fish
137 5, 17, 20, 0, 7, 6, 0, 0, // barrel
138 17, 38, 20, 40, 3, 6, 0, 20, // robot
139 8, 26, 400, 70, 8,10, 30, 50 // man
140 };
142 void MN_savegame(FILE* h) {
143 int n;
145 for(n=MAXMN;--n;) if(mn[n].t) break;
146 ++n;myfwrite(&n,1,4,h);
147 myfwrite(mn,1,n*sizeof(mn[0]),h);
148 myfwrite(&mnum,1,4,h);myfwrite(&gsndt,1,4,h);
151 static void setst(int,int);
153 static int MN_hit(int n,int d,int o,int t);
155 void MN_loadgame(FILE* h) {
156 int n,c;
158 myfread(&n,1,4,h);
159 myfread(mn,1,n*sizeof(mn[0]),h);
160 myfread(&mnum,1,4,h);myfread(&gsndt,1,4,h);
161 for(n=0;n<MAXMN;++n) if(mn[n].t) {
162 c=mn[n].ac;setst(n,mn[n].st);mn[n].ac=c;
166 #define GGAS_TOTAL (MN__LAST-MN_DEMON+16+10)
168 void MN_alloc(void) {
169 int i,j;
170 static char sn[MN_TN][5][6]={
171 {"DMACT","DMPAIN","SGTATK","SGTSIT","SGTDTH"},
172 {"BGACT","POPAIN","CLAW","",""},
173 {"POSACT","POPAIN","","",""},
174 {"POSACT","POPAIN","","",""},
175 {"","DMPAIN","HOOF","CYBSIT","CYBDTH"},
176 {"POSACT","POPAIN","","",""},
177 {"","DMPAIN","","BRSSIT","BRSDTH"},
178 {"","DMPAIN","","KNTSIT","KNTDTH"},
179 {"DMACT","DMPAIN","","CACSIT","CACDTH"},
180 {"DMACT","DMPAIN","SKLATK","SKLATK","FIRXPL"},
181 {"DMACT","PEPAIN","","PESIT","PEDTH"},
182 {"","DMPAIN","METAL","SPISIT","SPIDTH"},
183 {"BSPACT","DMPAIN","BSPWLK","BSPSIT","BSPDTH"},
184 {"DMACT","MNPAIN","MANATK","MANSIT","MANDTH"},
185 {"SKEACT","POPAIN","SKEATK","SKESIT","SKEDTH"},
186 {"VILACT","VIPAIN","VILATK","VILSIT","VILDTH"},
187 {"","","BITE1","",""},
188 {"","","","","BAREXP"},
189 {"BSPACT","","BSPWLK","BSPSIT","BSPDTH"},
190 {"HAHA1","PLPAIN","","STOP1","PDIEHI"}
191 },msn[MN_TN][4]={
192 "SARG","TROO","POSS","SPOS","CYBR","CPOS","BOSS","BOS2","HEAD","SKUL",
193 "PAIN","SPID","BSPI","FATT","SKEL","VILE","FISH","BAR1","ROBO","PLAY"
194 };
195 static char gsn[6]="GOOD0";
196 static int mms[MN_TN]={
197 14*2,21*2,21*2,21*2,16*2,20*2,15*2,15*2,12*2,11*2,13*2,19*2,16*2,
198 20*2,17*2,29*2,6*2,2*2,17*2,23*2
199 };
201 sgun[0]=Z_getspr("PWP4",0,1,NULL);
202 sgun[1]=Z_getspr("PWP4",1,1,NULL);
203 for(j=0;j<MN_TN;++j) {
204 for(i=0;i<mms[j];++i) spr[j][i]=Z_getspr(msn[j],i/2,(i&1)+1,&sprd[j][i]);
205 if(j==MN_BARREL-1)
206 for(i=4;i<14;++i) spr[j][i]=Z_getspr("BEXP",i/2-2,(i&1)+1,&sprd[j][i]);
207 for(i=0;i<5;++i)
208 if(sn[j][i][0]) snd[j][i]=Z_getsnd(sn[j][i]);
209 else snd[j][i]=NULL;
210 logo_gas(j+5,GGAS_TOTAL);
212 for(i=0;i<8;++i) fspr[i]=Z_getspr("FIRE",i,0,NULL);
213 pl_spr[0]=Z_getspr("PLAY",'N'-'A',0,NULL);
214 pl_spr[1]=Z_getspr("PLAY",'W'-'A',0,NULL);
215 impsitsnd[0]=Z_getsnd("BGSIT1");
216 impsitsnd[1]=Z_getsnd("BGSIT2");
217 impdthsnd[0]=Z_getsnd("BGDTH1");
218 impdthsnd[1]=Z_getsnd("BGDTH2");
219 positsnd[0]=Z_getsnd("POSIT1");
220 positsnd[1]=Z_getsnd("POSIT2");
221 positsnd[2]=Z_getsnd("POSIT3");
222 podthsnd[0]=Z_getsnd("PODTH1");
223 podthsnd[1]=Z_getsnd("PODTH2");
224 podthsnd[2]=Z_getsnd("PODTH3");
225 fsnd=Z_getsnd("FLAME");
226 firsnd=Z_getsnd("FIRSHT");
227 slopsnd=Z_getsnd("SLOP");
228 swgsnd=Z_getsnd("SKESWG");
229 pchsnd=Z_getsnd("SKEPCH");
230 telesnd=Z_getsnd("TELEPT");
231 pauksnd=Z_getsnd("PAUK1");
232 trupsnd=Z_getsnd("UTRUP");
233 for(i=0;i<4;++i) {gsn[4]=i+'1';gsnd[i]=Z_getsnd(gsn);}
236 void MN_init(void) {
237 int i;
239 for(i=0;i<MAXMN;++i) {mn[i].t=0;mn[i].st=SLEEP;}
240 gsndt=mnum=0;
243 static void setst(int i,int st) {
244 char *a;
245 int t;
247 switch(mn[i].st) {
248 case DIE: case DEAD:
249 if(st!=DEAD && st!=REVIVE) return;
251 mn[i].ac=0;
252 t=mn[i].t-1;
253 switch(mn[i].st=st) {
254 case SLEEP: a=sleepanim[t];break;
255 case PAIN: a=painanim[t];break;
256 case WAIT: a=waitanim[t];break;
257 case CLIMB:
258 case RUN: case RUNOUT:
259 case GO: a=goanim[t];break;
260 case SHOOT:
261 if(t==MN_SKEL-1) {a="KKKKJJ";break;}
262 if(t==MN_ROBO-1) {a="MN";break;}
263 case ATTACK: a=attackanim[t];
264 if(st==ATTACK && t==MN_VILE-1) a="[[\\\\]]";
265 break;
266 case DIE:
267 if(g_map==9 && t==MN_BSP-1) Z_sound(pauksnd,128);
268 a=dieanim[t];break;
269 case DEAD:
270 a=deadanim[t];
271 if(mn[i].ap==slopanim[t]) a=messanim[t];
272 if(t==MN_BARREL-1) {mn[i].t=0;}
273 break;
274 case REVIVE:
275 a=(mn[i].ap==messanim[t])?slopanim[t]:dieanim[t];
276 mn[i].ac=strlen(a)-1;
277 mn[i].o.r=mnsz[t+1].r;mn[i].o.h=mnsz[t+1].h;
278 mn[i].life=mnsz[t+1].l;mn[i].ammo=mn[i].pain=0;
279 ++mnum;
280 break;
282 mn[i].ap=a;
285 int MN_spawn(int x,int y,byte d,int t) {
286 int i;
288 if(g_dm && nomon && t<MN_PL_DEAD) return -1;
289 for(i=0;i<MAXMN;++i) if(!mn[i].t) goto ok;
290 for(i=0;i<MAXMN;++i) if(mn[i].t>=MN_PL_DEAD) goto ok;
291 return -1;
292 ok:
293 mn[i].o.x=x;mn[i].o.y=y;
294 mn[i].o.xv=mn[i].o.yv=mn[i].o.vx=mn[i].o.vy=0;
295 mn[i].d=d;mn[i].t=t;
296 mn[i].st=SLEEP;
297 if(t<MN_PL_DEAD) {
298 mn[i].o.r=mnsz[t].r;mn[i].o.h=mnsz[t].h;
299 mn[i].life=mnsz[t].l;
300 setst(i,SLEEP);mn[i].s=myrand(18);
301 ++mnum;
302 }else {mn[i].o.r=8;mn[i].o.h=6;mn[i].life=0;mn[i].st=DEAD;}
303 mn[i].aim=-3;mn[i].atm=0;
304 mn[i].pain=0;
305 mn[i].ammo=0;
306 mn[i].ftime=0;
307 return i;
310 int MN_spawn_deadpl(obj_t *o,byte c,int t) {
311 int i;
313 if((i=MN_spawn(o->x,o->y,c,t+MN_PL_DEAD))==-1) return -1;
314 mn[i].o=*o;return i;
317 static int isfriend(int a,int b) {
318 if(a==MN_BARREL || b==MN_BARREL) return 1;
319 if(a==b) switch(a) {
320 case MN_IMP: case MN_DEMON:
321 case MN_BARON: case MN_KNIGHT:
322 case MN_CACO: case MN_SOUL:
323 case MN_MANCUB: case MN_SKEL:
324 case MN_FISH:
325 return 1;
327 if(a==MN_SOUL && b==MN_PAIN) return 1;
328 if(b==MN_SOUL && a==MN_PAIN) return 1;
329 return 0;
332 static int MN_findnewprey(int i) {
333 int a,b,l;
335 a=!PL_isdead(&pl1);
336 if(_2pl) b=!PL_isdead(&pl2); else b=0;
337 if(a) {
338 if(b) mn[i].aim=(abs(mn[i].o.x-pl1.o.x)+abs(mn[i].o.y-pl1.o.y)
339 <= abs(mn[i].o.x-pl2.o.x)+abs(mn[i].o.y-pl2.o.y))?-1:-2;
340 else mn[i].aim=-1;
341 }else{
342 if(b) mn[i].aim=-2;
343 else{
344 for(a=0,b=32000,mn[i].aim=-3;a<MAXMN;++a)
345 if(mn[a].t && mn[a].st!=DEAD && a!=i && !isfriend(mn[a].t,mn[i].t))
346 if((l=abs(mn[i].o.x-mn[a].o.x)+abs(mn[i].o.y-mn[a].o.y))<b)
347 {mn[i].aim=a;b=l;}
348 if(mn[i].aim<0) {mn[i].atm=MAX_ATM;return 0;} else mn[i].atm=0;
351 return 1;
354 int Z_getobjpos(int i,obj_t *o) {
355 if(i==-1) {*o=pl1.o;return !PL_isdead(&pl1);}
356 if(_2pl) if(i==-2) {*o=pl2.o;return !PL_isdead(&pl2);}
357 if(i>=0 && i<MAXMN) if(mn[i].t && mn[i].st!=DEAD)
358 {*o=mn[i].o;return 1;}
359 return 0;
362 static void *wakeupsnd(int t) {
363 switch(t) {
364 case MN_IMP: return impsitsnd[myrand(2)];
365 case MN_ZOMBY: case MN_SERG: case MN_CGUN:
366 return positsnd[myrand(3)];
368 return snd[t-1][3];
371 static void *dthsnd(int t) {
372 switch(t) {
373 case MN_IMP: return impdthsnd[myrand(2)];
374 case MN_ZOMBY: case MN_SERG: case MN_CGUN:
375 return podthsnd[myrand(3)];
377 return snd[t-1][4];
380 static int canshoot(int t) {
381 switch(t) {
382 case MN_DEMON: case MN_FISH: case MN_BARREL:
383 return 0;
385 return 1;
388 static int shoot(int i,obj_t *o,int n) {
389 int xd,yd,m;
391 if(mn[i].ammo<0) return 0;
392 if(!n) switch(mn[i].t) {
393 case MN_FISH: case MN_BARREL:
394 case MN_DEMON: return 0;
395 case MN_CGUN:
396 case MN_BSP:
397 case MN_ROBO:
398 if(++mn[i].ammo>=50) mn[i].ammo=(mn[i].t==MN_ROBO)?-200:-50;
399 break;
400 case MN_MAN:
401 break;
402 case MN_MANCUB:
403 if(++mn[i].ammo>=5) mn[i].ammo=-50;
404 break;
405 case MN_SPIDER:
406 if(++mn[i].ammo>=100) mn[i].ammo=-50;
407 break;
408 case MN_CYBER:
409 if(rand()&1) return 0;
410 if(++mn[i].ammo>=10) mn[i].ammo=-50;
411 break;
412 case MN_BARON: case MN_KNIGHT:
413 if(rand()&7) return 0;
414 break;
415 case MN_SKEL:
416 if(rand()&31) return 0;
417 break;
418 case MN_VILE:
419 if(rand()&7) return 0;
420 break;
421 case MN_PAIN:
422 if(rand()&7) return 0;
423 break;
424 default:
425 if(rand()&15) return 0;
427 if(!Z_look(&mn[i].o,o,mn[i].d)) return 0;
428 mn[i].atm=0;
429 mn[i].tx=o->x+(o->xv+o->vx)*6;mn[i].ty=o->y-o->h/2+(o->yv+o->vy)*6;
430 if(abs(mn[i].tx-mn[i].o.x)<abs(mn[i].ty-mn[i].o.y+mn[i].o.h/2)) return 0;
431 switch(mn[i].t) {
432 case MN_IMP: case MN_BARON: case MN_KNIGHT: case MN_CACO:
433 setst(i,SHOOT);Z_sound(firsnd,128);break;
434 case MN_SKEL:
435 setst(i,SHOOT);Z_sound(snd[MN_SKEL-1][2],128);break;
436 case MN_VILE:
437 mn[i].tx=o->x;mn[i].ty=o->y;
438 setst(i,SHOOT);Z_sound(fsnd,128);
439 Z_sound(snd[MN_VILE-1][2],128);break;
440 case MN_SOUL:
441 setst(i,ATTACK);Z_sound(snd[MN_SOUL-1][2],128);
442 yd=mn[i].ty-mn[i].o.y+mn[i].o.h/2;xd=mn[i].tx-mn[i].o.x;
443 if(!(m=max(abs(xd),abs(yd)))) m=1;
444 mn[i].o.xv=xd*16/m;mn[i].o.yv=yd*16/m;
445 break;
446 case MN_MANCUB: if(mn[i].ammo==1) Z_sound(snd[MN_MANCUB-1][2],128);
447 case MN_ZOMBY: case MN_SERG: case MN_BSP: case MN_ROBO:
448 case MN_CYBER: case MN_CGUN: case MN_SPIDER:
449 case MN_PAIN: case MN_MAN:
450 setst(i,SHOOT);break;
451 default:
452 return 0;
454 return 1;
457 static int kick(int i,obj_t *o) {
458 switch(mn[i].t) {
459 case MN_FISH:
460 setst(i,ATTACK);return 1;
461 case MN_DEMON:
462 setst(i,ATTACK);Z_sound(snd[0][2],128);return 1;
463 case MN_IMP:
464 setst(i,ATTACK);Z_sound(snd[1][2],128);return 1;
465 case MN_SKEL:
466 setst(i,ATTACK);Z_sound(swgsnd,128);return 1;
467 case MN_ROBO:
468 setst(i,ATTACK);Z_sound(swgsnd,128);return 1;
469 case MN_BARON: case MN_KNIGHT: case MN_CACO: case MN_MANCUB:
470 return shoot(i,o,1);
472 return 0;
475 static int iscorpse(obj_t *o,int n) {
476 int i;
478 if(!n) if(rand()&7) return -3;
479 for(i=0;i<MAXMN;++i) if(mn[i].t) if(mn[i].st==DEAD)
480 if(Z_overlap(o,&mn[i].o)) switch(mn[i].t) {
481 case MN_SOUL: case MN_PAIN:
482 case MN_CYBER: case MN_SPIDER:
483 case MN_PL_DEAD: case MN_PL_MESS:
484 case MN_VILE: case MN_BARREL:
485 continue;
486 default:
487 return i;
489 return -3;
492 void MN_act(void) {
493 int i,st,sx,sy,t;
494 static obj_t o;
495 static int pt_x=0,pt_xs=1,pt_y=0,pt_ys=1;
497 if(abs(pt_x+=pt_xs) > 123) pt_xs=-pt_xs;
498 if(abs(pt_y+=pt_ys) > 50) pt_ys=-pt_ys;
499 if(gsndt>0) if(--gsndt==0) {
500 Z_sound(gsnd[myrand(4)],128);
502 for(i=0;i<MAXMN;++i) if((t=mn[i].t)!=0) {
503 switch(t) {
504 case MN_FISH:
505 if(!Z_inwater(mn[i].o.x,mn[i].o.y,mn[i].o.r,mn[i].o.h)) break;
506 case MN_SOUL: case MN_PAIN: case MN_CACO:
507 if(mn[i].st!=DIE && mn[i].st!=DEAD) --mn[i].o.yv;
508 break;
509 }z_mon=1;st=Z_moveobj(&mn[i].o);z_mon=0;
510 BM_mark(&mn[i].o,BM_MONSTER);
511 if(st&Z_FALLOUT) {
512 if(t==MN_ROBO) g_exit=1;
513 mn[i].t=0;--mnum;continue;
515 if(st&Z_HITWATER) Z_splash(&mn[i].o,mn[i].o.r+mn[i].o.h);
516 SW_press(mn[i].o.x,mn[i].o.y,mn[i].o.r,mn[i].o.h,8,i);
517 if(mn[i].ftime) {
518 --mn[i].ftime;
519 SMK_flame(mn[i].o.x,mn[i].o.y-mn[i].o.h/2,
520 mn[i].o.xv+mn[i].o.vx,mn[i].o.yv+mn[i].o.vy,
521 mn[i].o.r/2,mn[i].o.h/2,rand()%(200*2+1)-200,-500,1,mn[i].fobj);
523 if(st&Z_INWATER) mn[i].ftime=0;
524 if(mn[i].st==DEAD) continue;
525 if(st&Z_INWATER) if(!(rand()&31)) switch(t) {
526 case MN_FISH:
527 if(rand()&3) break;
528 case MN_ROBO: case MN_BARREL:
529 case MN_PL_DEAD: case MN_PL_MESS:
530 FX_bubble(mn[i].o.x+((rand()&1)*2-1)*myrand(mn[i].o.r+1),
531 mn[i].o.y-myrand(mn[i].o.h+1),0,0,1
532 );
533 break;
534 default:
535 FX_bubble(mn[i].o.x,mn[i].o.y-mn[i].o.h*3/4,0,0,5);
538 if(t==MN_BARREL) {
540 if(!mn[i].ap[++mn[i].ac]) {
541 mn[i].ac=0;if(mn[i].st==DIE || mn[i].st==DEAD) {mn[i].t=0;}
542 }else if(mn[i].st==DIE && mn[i].ac==2) Z_explode(mn[i].o.x,mn[i].o.y-8,30,mn[i].aim);
543 continue;
545 if(t==MN_SOUL) if(st&Z_HITAIR) Z_set_speed(&mn[i].o,16);
546 if(mn[i].ammo<0) ++mn[i].ammo;
547 if(mn[i].o.yv<0)
548 if(st&Z_INWATER) mn[i].o.yv=-4;
549 ++mn[i].atm;
550 switch(mn[i].st) {
551 case PAIN:
552 if(mn[i].pain>=mnsz[t].mp)
553 {mn[i].pain=mnsz[t].mp;Z_sound(snd[t-1][1],128);}
554 if((mn[i].pain-=5)<=mnsz[t].minp)
555 {setst(i,GO);mn[i].pain=0;mn[i].ammo=-9;}
556 break;
557 case SLEEP:
558 if(++mn[i].s>=18) mn[i].s=0; else break;
559 if(Z_look(&mn[i].o,&pl1.o,mn[i].d))
560 {setst(i,GO);mn[i].aim=-1;mn[i].atm=0;Z_sound(wakeupsnd(t),128);}
561 if(_2pl) if(Z_look(&mn[i].o,&pl2.o,mn[i].d))
562 {setst(i,GO);mn[i].aim=-2;mn[i].atm=0;Z_sound(wakeupsnd(t),128);}
563 break;
564 case WAIT:
565 if(--mn[i].s<0) setst(i,GO);
566 break;
567 case GO:
568 if(st&Z_BLOCK) {mn[i].d^=1;setst(i,RUNOUT);mn[i].s=40;break;}
569 if(t==MN_VILE) if(iscorpse(&mn[i].o,0)>=0) {
570 setst(i,ATTACK);mn[i].o.xv=0;break;
572 if(!Z_getobjpos(mn[i].aim,&o) || mn[i].atm>MAX_ATM)
573 if(!MN_findnewprey(i)) {
574 mn[i].aim=-3;
575 o.x=mn[i].o.x+pt_x;o.y=mn[i].o.y+pt_y;
576 o.xv=o.vx=o.yv=o.vy=o.r=0;o.h=1;
577 }else Z_getobjpos(mn[i].aim,&o);
578 if(Z_overlap(&mn[i].o,&o)) {
579 mn[i].atm=0;
580 if(kick(i,&o)) break;
582 sx=o.x-mn[i].o.x;
583 sy=o.y-o.h/2-mn[i].o.y+mn[i].o.h/2;
584 if(!(st&Z_BLOCK)) if(abs(sx)<20)
585 if(t!=MN_FISH) {setst(i,RUN);mn[i].s=15;mn[i].d=rand()&1;break;}
586 if(st&Z_HITWALL) {
587 if(SW_press(mn[i].o.x,mn[i].o.y,mn[i].o.r,mn[i].o.h,2,i))
588 {setst(i,WAIT);mn[i].s=4;break;}
589 switch(t) {
590 case MN_CACO: case MN_SOUL: case MN_PAIN: case MN_FISH:
591 break;
592 default:
593 if(Z_canstand(mn[i].o.x,mn[i].o.y,mn[i].o.r))
594 {mn[i].o.yv=-mnsz[t].jv;setst(i,CLIMB);break;}
595 }break;
597 mn[i].d=(sx>0)?1:0;
598 if(canshoot(t))
599 if(abs(sx)>abs(sy)) if(shoot(i,&o,0)) break;
601 switch(t) {
602 case MN_FISH:
603 if(!(st&Z_INWATER)) {
604 if(Z_canstand(mn[i].o.x,mn[i].o.y,mn[i].o.r)) {
605 mn[i].o.yv=-6;
606 mn[i].o.vx+=rand()%17-8;
607 }setst(i,PAIN);mn[i].pain+=50;break;
609 case MN_CACO: case MN_SOUL: case MN_PAIN:
610 if(abs(sy)>4) mn[i].o.yv=(sy<0)?-4:4; else mn[i].o.yv=0;
611 if(t==MN_FISH) if(mn[i].o.yv<0)
612 if(!Z_inwater(mn[i].o.x,mn[i].o.y-8,mn[i].o.r,mn[i].o.h))
613 {mn[i].o.yv=0;setst(i,RUN);mn[i].d=rand()&1;mn[i].s=20;}
614 break;
615 default:
616 if(sy<-20) if(Z_canstand(mn[i].o.x,mn[i].o.y,mn[i].o.r))
617 if(!(rand()&3)) mn[i].o.yv=-mnsz[t].jv;
619 if(++mn[i].s>=8) {
620 mn[i].s=0;
621 if(!(rand()&7)) Z_sound(snd[t-1][0],128);
623 mn[i].o.xv=((mn[i].d)?1:-1)*mnsz[t].rv;
624 if(st&Z_INWATER) mn[i].o.xv/=2;
625 else if(t==MN_FISH) mn[i].o.xv=0;
626 break;
627 case RUN:
628 if(st&Z_BLOCK) {setst(i,RUNOUT);mn[i].d^=1;mn[i].s=40;break;}
629 if(--mn[i].s<=0 || ((st&Z_HITWALL) && mn[i].o.yv+mn[i].o.vy==0)) {
630 setst(i,GO);mn[i].s=0;if(st&(Z_HITWALL|Z_BLOCK)) mn[i].d^=1;
631 if(!(rand()&7)) Z_sound(snd[t-1][0],128);
632 }mn[i].o.xv=((mn[i].d)?1:-1)*mnsz[t].rv;
633 if(st&Z_INWATER) mn[i].o.xv/=2;
634 else if(t==MN_FISH) mn[i].o.xv=0;
635 break;
636 case RUNOUT:
637 if(!(st&Z_BLOCK) && mn[i].s>0) mn[i].s=0;
638 if(--mn[i].s<=-18) {
639 setst(i,GO);mn[i].s=0;if(st&(Z_HITWALL|Z_BLOCK)) mn[i].d^=1;
640 if(!(rand()&7)) Z_sound(snd[t-1][0],128);
641 }mn[i].o.xv=((mn[i].d)?1:-1)*mnsz[t].rv;
642 if(st&Z_INWATER) mn[i].o.xv/=2;
643 else if(t==MN_FISH) mn[i].o.xv=0;
644 break;
645 case CLIMB:
646 if(mn[i].o.yv+mn[i].o.vy>=0 || !(st&Z_HITWALL)) {
647 setst(i,GO);mn[i].s=0;
648 if(st&(Z_HITWALL|Z_BLOCK)) {mn[i].d^=1;setst(i,RUN);mn[i].s=15;}
649 }mn[i].o.xv=((mn[i].d)?1:-1)*mnsz[t].rv;
650 if(st&Z_INWATER) mn[i].o.xv/=2;
651 else if(t==MN_FISH) mn[i].o.xv=0;
652 break;
653 case ATTACK:
654 case SHOOT:
655 if(t==MN_SOUL) {if(st&(Z_HITWALL|Z_HITCEIL|Z_HITLAND)) setst(i,GO); break;}
656 if(t!=MN_FISH) mn[i].o.xv=Z_dec(mn[i].o.xv,1);
657 if(t==MN_VILE && mn[i].st==SHOOT) {
658 if(!Z_getobjpos(mn[i].aim,&o)) {setst(i,GO);break;}
659 if(!Z_look(&mn[i].o,&o,mn[i].d)) {setst(i,GO);break;}
660 if(Z_inwater(o.x,o.y,o.r,o.h)) {setst(i,GO);break;}
661 mn[i].tx=o.x;mn[i].ty=o.y;
662 Z_hitobj(mn[i].aim,2,i,HIT_SOME);
663 }break;
665 if(mn[i].st==REVIVE) {
666 if(--mn[i].ac==0) setst(i,GO);
667 }else ++mn[i].ac;
668 if(!mn[i].ap[mn[i].ac]) switch(mn[i].st) {
669 case ATTACK:
670 switch(t) {
671 case MN_SOUL: mn[i].ac=0;
672 case MN_IMP:
673 case MN_DEMON:
674 if(Z_hit(&mn[i].o,15,i,HIT_SOME)) if(t==MN_SOUL) setst(i,GO);
675 break;
676 case MN_FISH:
677 if(Z_hit(&mn[i].o,10,i,HIT_SOME))
678 Z_sound(snd[MN_FISH-1][2],128);
679 break;
680 case MN_SKEL: case MN_ROBO:
681 o=mn[i].o;o.xv=mn[i].d?50:-50;
682 if(Z_hit(&o,50,i,HIT_SOME)) Z_sound(pchsnd,128);
683 break;
684 case MN_VILE:
685 sx=iscorpse(&mn[i].o,1);
686 if(sx==-3) break;
687 if(!mn[sx].t || mn[sx].st!=DEAD) break;
688 setst(sx,REVIVE);Z_sound(slopsnd,128);
689 hit_xv=hit_yv=0;MN_hit(i,5,-3,HIT_SOME);
690 break;
691 }if(t!=MN_SOUL && mn[i].st!=DIE) setst(i,GO);
692 break;
693 case SHOOT:
694 switch(t) {
695 case MN_IMP:
696 WP_ball1(mn[i].o.x+(mn[i].d*2-1)*mn[i].o.r,mn[i].o.y-mn[i].o.h/2,mn[i].tx,mn[i].ty,i);
697 break;
698 case MN_ZOMBY:
699 WP_pistol(mn[i].o.x+(mn[i].d*2-1)*mn[i].o.r,mn[i].o.y-mn[i].o.h/2,mn[i].tx,mn[i].ty,i);
700 break;
701 case MN_SERG:
702 WP_shotgun(mn[i].o.x+(mn[i].d*2-1)*mn[i].o.r,mn[i].o.y-mn[i].o.h/2,mn[i].tx,mn[i].ty,i);
703 break;
704 case MN_MAN:
705 WP_dshotgun(mn[i].o.x+(mn[i].d*2-1)*mn[i].o.r,mn[i].o.y-mn[i].o.h/2,mn[i].tx,mn[i].ty,i);
706 mn[i].ammo=-36;break;
707 case MN_CYBER:
708 WP_rocket(mn[i].o.x+(mn[i].d*2-1)*mn[i].o.r,mn[i].o.y-mn[i].o.h/2,mn[i].tx,mn[i].ty,i);
709 break;
710 case MN_SKEL:
711 WP_revf(mn[i].o.x+(mn[i].d*2-1)*mn[i].o.r,mn[i].o.y-mn[i].o.h/2,mn[i].tx,mn[i].ty,i,mn[i].aim);
712 break;
713 case MN_CGUN:
714 case MN_SPIDER:
715 WP_mgun(mn[i].o.x+(mn[i].d*2-1)*mn[i].o.r,mn[i].o.y-mn[i].o.h/2,mn[i].tx,mn[i].ty,i);
716 break;
717 case MN_BSP:
718 WP_aplasma(mn[i].o.x+(mn[i].d*2-1)*mn[i].o.r,mn[i].o.y-mn[i].o.h/2,mn[i].tx,mn[i].ty,i);
719 break;
720 case MN_ROBO:
721 WP_plasma(mn[i].o.x+(mn[i].d*2-1)*15,mn[i].o.y-30,mn[i].tx,mn[i].ty,i);
722 break;
723 case MN_MANCUB:
724 WP_manfire(mn[i].o.x+(mn[i].d*2-1)*mn[i].o.r,mn[i].o.y-mn[i].o.h/2,mn[i].tx,mn[i].ty,i);
725 break;
726 case MN_BARON: case MN_KNIGHT:
727 WP_ball7(mn[i].o.x,mn[i].o.y-mn[i].o.h/2,mn[i].tx,mn[i].ty,i);
728 break;
729 case MN_CACO:
730 WP_ball2(mn[i].o.x,mn[i].o.y-mn[i].o.h/2,mn[i].tx,mn[i].ty,i);
731 break;
732 case MN_PAIN:
733 if((sx=MN_spawn(mn[i].o.x,mn[i].o.y,mn[i].d,MN_SOUL))==-1) break;
734 Z_getobjpos(mn[sx].aim=mn[i].aim,&o);mn[sx].atm=0;
735 shoot(sx,&o,1);
736 break;
738 if(t==MN_CGUN || t==MN_SPIDER || t==MN_BSP || t==MN_MANCUB || t==MN_ROBO)
739 if(!Z_getobjpos(mn[i].aim,&o)) MN_findnewprey(i);
740 else if(shoot(i,&o,0)) break;
741 setst(i,GO);break;
742 case DIE:
743 setst(i,DEAD);
744 if(t==MN_PAIN || t==MN_SOUL) mn[i].ftime=0;
745 if(t==MN_PAIN) {
746 if((sx=MN_spawn(mn[i].o.x-15,mn[i].o.y,0,MN_SOUL))==-1) break;
747 setst(sx,GO);
748 if((sx=MN_spawn(mn[i].o.x+15,mn[i].o.y,1,MN_SOUL))==-1) break;
749 setst(sx,GO);
750 if((sx=MN_spawn(mn[i].o.x,mn[i].o.y-10,1,MN_SOUL))==-1) break;
751 setst(sx,GO);
752 }break;
753 default: mn[i].ac=0;
755 switch(mn[i].st) {
756 case GO: case RUN: case CLIMB: case RUNOUT:
757 if(t==MN_CYBER || t==MN_SPIDER || t==MN_BSP) {
758 if(mn[i].ac==0 || mn[i].ac==6) Z_sound(snd[t-1][2],128);
759 }else if(t==MN_ROBO)
760 if(mn[i].ac==0 || mn[i].ac==12) Z_sound(snd[t-1][2],128);
765 void MN_mark(void) {
766 int i;
767 for(i=0;i<MAXMN;++i) if(mn[i].t!=0) BM_mark(&mn[i].o,BM_MONSTER);
770 void MN_draw(void) {
771 int i;
773 for(i=0;i<MAXMN;++i) if(mn[i].t) {
775 if(mn[i].t>=MN_PL_DEAD) {
776 Z_drawmanspr(mn[i].o.x,mn[i].o.y,pl_spr[mn[i].t-MN_PL_DEAD],0,mn[i].d);
777 continue;
779 if((mn[i].t!=MN_SOUL && mn[i].t!=MN_PAIN) || mn[i].st!=DEAD) {
780 if(mn[i].t!=MN_MAN)
781 Z_drawspr(mn[i].o.x,mn[i].o.y,
782 spr[mn[i].t-1][(mn[i].ap[mn[i].ac]-'A')*2+mn[i].d],
783 sprd[mn[i].t-1][(mn[i].ap[mn[i].ac]-'A')*2+mn[i].d]);
784 else{
785 if(mn[i].ap[mn[i].ac]=='E' || mn[i].ap[mn[i].ac]=='F')
786 Z_drawspr(mn[i].o.x,mn[i].o.y,sgun[mn[i].ap[mn[i].ac]-'E'],mn[i].d);
787 Z_drawmanspr(mn[i].o.x,mn[i].o.y,
788 spr[mn[i].t-1][(mn[i].ap[mn[i].ac]-'A')*2+mn[i].d],
789 sprd[mn[i].t-1][(mn[i].ap[mn[i].ac]-'A')*2+mn[i].d],MANCOLOR);
792 if(mn[i].t==MN_VILE && mn[i].st==SHOOT) {
793 Z_drawspr(mn[i].tx,mn[i].ty,fspr[mn[i].ac/3],0);
798 int MN_hit(int n,int d,int o,int t) {
799 int i;
801 if(mn[n].st==DEAD || mn[n].st==DIE) return 0;
802 if(o==n) {
803 if(t!=HIT_ROCKET && t!=HIT_ELECTRO) return 0;
804 if(mn[n].t==MN_CYBER || mn[n].t==MN_BARREL) return 1;
806 if(o>=0) {
807 if(mn[o].t==MN_SOUL && mn[n].t==MN_PAIN) return 0;
808 if(mn[o].t==mn[n].t) switch(mn[n].t) {
809 case MN_IMP: case MN_DEMON:
810 case MN_BARON: case MN_KNIGHT:
811 case MN_CACO: case MN_SOUL:
812 case MN_MANCUB: case MN_SKEL:
813 case MN_FISH:
814 return 0;
817 if(t==HIT_FLAME) if(mn[n].ftime && mn[n].fobj==o) {if(g_time&31) return 1;}
818 else {mn[n].ftime=255;mn[n].fobj=o;}
819 if(t==HIT_ELECTRO) if(mn[n].t==MN_FISH)
820 {setst(n,RUN);mn[n].s=20;mn[n].d=rand()&1;return 1;}
821 if(t==HIT_TRAP) mn[n].life=-100;
822 if(mn[n].t==MN_ROBO) d=0;
823 if((mn[n].life-=d)<=0) --mnum;
824 if(!mn[n].pain) mn[n].pain=3;
825 mn[n].pain+=d;
826 if(mn[n].st!=PAIN) {
827 if(mn[n].pain>=mnsz[mn[n].t].minp) setst(n,PAIN);
829 if(mn[n].t!=MN_BARREL)
830 DOT_blood(mn[n].o.x,mn[n].o.y-mn[n].o.h/2,hit_xv,hit_yv,d*2);
831 mn[n].aim=o;mn[n].atm=0;
832 if(mn[n].life<=0) {
833 if(mn[n].t!=MN_BARREL)
834 if(o==-1) ++pl1.kills;
835 else if(o==-2) ++pl2.kills;
836 setst(n,DIE);
837 switch(mn[n].t) {
838 case MN_ZOMBY: i=I_CLIP;break;
839 case MN_SERG: i=I_SGUN;break;
840 case MN_CGUN: i=I_MGUN;break;
841 case MN_MAN: i=I_KEYR;break;
842 default: i=0;
843 }if(i) IT_spawn(mn[n].o.x,mn[n].o.y,i);
844 mn[n].o.xv=0;mn[n].o.h=6;
845 if(mn[n].life<=-mnsz[mn[n].t].sp)
846 switch(mn[n].t) {
847 case MN_IMP: case MN_ZOMBY: case MN_SERG: case MN_CGUN:
848 case MN_MAN:
849 mn[n].ap=slopanim[mn[n].t-1];
850 Z_sound(slopsnd,128);
851 break;
852 case MN_BSP: if(g_map==9) break;
853 default:
854 Z_sound(dthsnd(mn[n].t),128);
856 else if(mn[n].t!=MN_BSP || g_map!=9) Z_sound(dthsnd(mn[n].t),128);
857 mn[n].life=0;
858 }else if(mn[n].st==SLEEP) {setst(n,GO);mn[n].pain=mnsz[mn[n].t].mp;}
859 return 1;
862 #define hit(o,x,y) (y<=o.y && y>o.y-o.h && x>=o.x-o.r && x<=o.x+o.r)
864 int Z_gunhit(int x,int y,int o,int xv,int yv) {
865 int i;
867 if(o!=-1) if(hit(pl1.o,x,y)) if(PL_hit(&pl1,3,o,HIT_SOME))
868 {pl1.o.vx+=xv;pl1.o.vy+=yv;return -1;}
869 if(_2pl && o!=-2) if(hit(pl2.o,x,y)) if(PL_hit(&pl2,3,o,HIT_SOME))
870 {pl2.o.vx+=xv;pl2.o.vy+=yv;return -2;}
872 for(i=0;i<MAXMN;++i) if(mn[i].t && o!=i)
873 if(hit(mn[i].o,x,y)) if(MN_hit(i,3,o,HIT_SOME))
874 {mn[i].o.vx+=xv;mn[i].o.vy+=yv;return 1;}
875 return 0;
878 static void goodsnd(void) {
879 if(!g_dm) return;
880 gsndt=18;
883 int Z_hit(obj_t *o,int d,int own,int t) {
884 int i;
886 hit_xv=o->xv+o->vx;
887 hit_yv=o->yv+o->vy;
888 if(Z_overlap(o,&pl1.o)) if(PL_hit(&pl1,d,own,t)) {
889 pl1.o.vx+=(o->xv+o->vx)*((t==HIT_BFG)?8:1)/4;
890 pl1.o.vy+=(o->yv+o->vy)*((t==HIT_BFG)?8:1)/4;
891 if(t==HIT_BFG) goodsnd();
892 return -1;
894 if(_2pl) if(Z_overlap(o,&pl2.o)) if(PL_hit(&pl2,d,own,t)) {
895 pl2.o.vx+=(o->xv+o->vx)*((t==HIT_BFG)?8:1)/4;
896 pl2.o.vy+=(o->yv+o->vy)*((t==HIT_BFG)?8:1)/4;
897 if(t==HIT_BFG) goodsnd();
898 return -2;
901 for(i=0;i<MAXMN;++i) if(mn[i].t)
902 if(Z_overlap(o,&mn[i].o)) if(MN_hit(i,d,own,t)) {
903 mn[i].o.vx+=(o->xv+o->vx)*((t==HIT_BFG)?8:1)/4;
904 mn[i].o.vy+=(o->yv+o->vy)*((t==HIT_BFG)?8:1)/4;
905 return 1;
907 return 0;
910 void MN_killedp(void) {
911 int i;
913 for(i=0;i<MAXMN;++i) if(mn[i].t==MN_MAN)
914 if(mn[i].st!=DEAD && mn[i].st!=DIE && mn[i].st!=SLEEP)
915 Z_sound(trupsnd,128);
918 int Z_hitobj(int obj,int d,int own,int t) {
919 hit_xv=hit_yv=0;
920 if(obj==-1) return PL_hit(&pl1,d,own,t);
921 else if(obj==-2 && _2pl) return PL_hit(&pl2,d,own,t);
922 else if(obj<0 || obj>=MAXMN) return 0;
923 if(mn[obj].t) return MN_hit(obj,d,own,t);
924 return 0;
927 void Z_explode(int x,int y,int rad,int own) {
928 long r;
929 int dx,dy,m,i;
931 if(x<-100 || x>FLDW*CELW+100) return;
932 if(y<-100 || y>FLDH*CELH+100) return;
933 r=(long)rad*rad;
934 dx=pl1.o.x-x;dy=pl1.o.y-pl1.o.h/2-y;
935 if((long)dx*dx+(long)dy*dy<r) {
936 if(!(m=max(abs(dx),abs(dy)))) m=1;
937 pl1.o.vx+=hit_xv=dx*10/m;
938 pl1.o.vy+=hit_yv=dy*10/m;
939 PL_hit(&pl1,100*(rad-m)/rad,own,HIT_ROCKET);
941 if(_2pl) {
942 dx=pl2.o.x-x;dy=pl2.o.y-pl2.o.h/2-y;
943 if((long)dx*dx+(long)dy*dy<r) {
944 if(!(m=max(abs(dx),abs(dy)))) m=1;
945 pl2.o.vx+=hit_xv=dx*10/m;
946 pl2.o.vy+=hit_yv=dy*10/m;
947 PL_hit(&pl2,100*(rad-m)/rad,own,HIT_ROCKET);
950 for(i=0;i<MAXMN;++i) if(mn[i].t) {
951 dx=mn[i].o.x-x;dy=mn[i].o.y-mn[i].o.h/2-y;
952 if((long)dx*dx+(long)dy*dy<r) {
953 if(!(m=max(abs(dx),abs(dy)))) m=1;
954 mn[i].o.vx+=hit_xv=dx*10/m;
955 mn[i].o.vy+=hit_yv=dy*10/m;
956 MN_hit(i,mn[i].o.r*10*(rad-m)/rad,own,HIT_ROCKET);
961 void Z_bfg9000(int x,int y,int own) {
962 int dx,dy,i;
964 hit_xv=hit_yv=0;
965 if(x<-100 || x>FLDW*CELW+100) return;
966 if(y<-100 || y>FLDH*CELH+100) return;
967 dx=pl1.o.x-x;dy=pl1.o.y-pl1.o.h/2-y;
968 if(own!=-1) if((long)dx*dx+(long)dy*dy<16000)
969 if(Z_cansee(x,y,pl1.o.x,pl1.o.y-pl1.o.h/2)) {
970 if(PL_hit(&pl1,50,own,HIT_SOME))
971 WP_bfghit(pl1.o.x,pl1.o.y-pl1.o.h/2,own);
973 if(_2pl) {
974 dx=pl2.o.x-x;dy=pl2.o.y-pl2.o.h/2-y;
975 if(own!=-2) if((long)dx*dx+(long)dy*dy<16000)
976 if(Z_cansee(x,y,pl2.o.x,pl2.o.y-pl2.o.h/2)) {
977 if(PL_hit(&pl2,50,own,HIT_SOME))
978 WP_bfghit(pl2.o.x,pl2.o.y-pl2.o.h/2,own);
981 for(i=0;i<MAXMN;++i) if(mn[i].t && own!=i) {
982 dx=mn[i].o.x-x;dy=mn[i].o.y-mn[i].o.h/2-y;
983 if((long)dx*dx+(long)dy*dy<16000)
984 if(Z_cansee(x,y,mn[i].o.x,mn[i].o.y-mn[i].o.h/2)) {
985 if(MN_hit(i,50,own,HIT_SOME))
986 WP_bfghit(mn[i].o.x,mn[i].o.y-mn[i].o.h/2,own);
991 int Z_chktrap(int t,int d,int o,int ht) {
992 int i,s;
994 hit_xv=hit_yv=0;
995 s=0;
996 if(Z_istrapped(pl1.o.x,pl1.o.y,pl1.o.r,pl1.o.h)) {
997 s=1;
998 if(t) PL_hit(&pl1,d,o,ht);
1000 if(_2pl) if(Z_istrapped(pl2.o.x,pl2.o.y,pl2.o.r,pl2.o.h)) {
1001 s=1;
1002 if(t) PL_hit(&pl2,d,o,ht);
1004 for(i=0;i<MAXMN;++i) if(mn[i].t && mn[i].st!=DEAD)
1005 if(Z_istrapped(mn[i].o.x,mn[i].o.y,mn[i].o.r,mn[i].o.h)) {
1006 s=1;
1007 if(t) MN_hit(i,d,o,ht);
1009 return s;
1012 void Z_teleobj(int o,int x,int y) {
1013 obj_t *p;
1015 if(o==-1) p=&pl1.o;
1016 else if(o==-2) p=&pl2.o;
1017 else if(o>=0 && o<MAXMN) p=&mn[o].o;
1018 else return;
1019 FX_tfog(p->x,p->y);FX_tfog(p->x=x,p->y=y);
1020 Z_sound(telesnd,128);
1023 void MN_warning(int l,int t,int r,int b) {
1024 int i;
1026 for(i=0;i<MAXMN;++i) if(mn[i].t && mn[i].t!=MN_CACO && mn[i].t!=MN_SOUL
1027 && mn[i].t!=MN_PAIN && mn[i].t!=MN_FISH)
1028 if(mn[i].st!=DIE && mn[i].st!=DEAD && mn[i].st!=SLEEP)
1029 if(mn[i].o.x+mn[i].o.r>=l && mn[i].o.x-mn[i].o.r<=r
1030 && mn[i].o.y>=t && mn[i].o.y-mn[i].o.h<=b)
1031 if(Z_canstand(mn[i].o.x,mn[i].o.y,mn[i].o.r))
1032 mn[i].o.yv=-mnsz[mn[i].t].jv;