DEADSOFTWARE

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