From: Andriy Shinkarchuck Date: Sun, 24 Jul 2011 16:16:15 +0000 (+0300) Subject: monster.c monster.h moved to repo. Added license notification X-Git-Url: http://deadsoftware.ru/gitweb?a=commitdiff_plain;h=b503c56e457d69abc69a1af804790b9f2151613e;p=flatwaifu.git monster.c monster.h moved to repo. Added license notification --- diff --git a/monster.c b/monster.c new file mode 100755 index 0000000..ed7604e --- /dev/null +++ b/monster.c @@ -0,0 +1,1031 @@ +/* + Copyright (C) Prikol Software 1996-1997 + Copyright (C) Aleksey Volynskov 1996-1997 + Copyright (C) 2011 + + This file is part of the Doom2D:Rembo project. + + Doom2D:Rembo is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 2 as + published by the Free Software Foundation. + + Doom2D:Rembo is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see or + write to the Free Software Foundation, Inc., + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "glob.h" +//#include +#include +#include +#include "vga.h" +#include "files.h" +#include "error.h" +#include "view.h" +#include "bmap.h" +#include "dots.h" +#include "weapons.h" +#include "player.h" +#include "monster.h" +#include "items.h" +#include "switch.h" +#include "misc.h" +#include "fx.h" +#include "smoke.h" + +#define MANCOLOR 0xD0 + +#define MAX_ATM 90 + +#define MN_TN (MN__LAST-MN_DEMON) + +extern byte z_mon; + +enum{ + SLEEP,GO,RUN,CLIMB,DIE,DEAD,ATTACK,SHOOT,PAIN,WAIT,REVIVE,RUNOUT +}; + +#pragma pack(1) +typedef struct{ + obj_t o; + byte t,d,st,ftime; + int fobj; + int s; + char *ap; + int aim,life,pain,ac,tx,ty,ammo; + short atm; +}mn_t; +#pragma pack(0) + +typedef struct{ + int r,h,l,mp,rv,jv,sp,minp; +}mnsz_t; + +byte nomon=1; + +static char *sleepanim[MN_TN]={ + "AAABBB","AAABBB","AAABBB","AAABBB","AAABBB","AAABBB","AAABBB","AAABBB", + "A","AAABBB","AAABBB","AAABBB","AAABBB","AAABBB","AAABBB","AAABBB","AAABBB", + "A","A","AAABBB" +}, *goanim[MN_TN]={ + "AABBCCDD","AABBCCDD","AABBDDAACCDD","AABBDDAACCDD","AABBDDCCDDBB", + "AABBDDAACCDD","AABBCCDD","AABBCCDD","A","AABB","AABBCCBB", + "AABBCCDDEEFF","AABBCCDDEEFF","AABBCCDDEEFF","AABBCCDDEEFF","AABBCCDDEEFF", + "AABB","A","DDEEFFGGHHIIJJKKLLAABBCC","ACDABD" +}, *painanim[MN_TN]={ + "H","H","G","G","G","G","H","H","F","E","G","I","I","J","L","Q","EECCDDCC", + "A","D","G" +}, *waitanim[MN_TN]={ + "A","A","A","A","A","A","A","A","A","AABB","A","A","A","I","K","A","A", + "A","D","E" +}, *attackanim[MN_TN]={ + "EEFFGG","EEFFGG","EEEEEF","EEEEEF","EEEEEF","EF","EEFFGG","EEFFGG", + "BBCCDD","CCDD","DDEEFF","GH","GH","GGGGHH","GGHHII", + "QQGGGHHHIIJJKKLLMMNNOOPP","BBFFAA","A","OOPPQQ","EEEEFF" +}, *dieanim[MN_TN]={ + "IIIJJJKKKLLLMMM","IIIJJJKKKLLL","HHHIIIJJJKKK","HHHIIIJJJKKK", + "HHHIIIJJJKKKLLLMMMNNNOOO","HHHIIIJJJKKKLLLMMM", + "IIIJJJKKKLLLMMMNNN","IIIJJJKKKLLLMMMNNN","GGGHHHIIIJJJKKK", + "FFFGGGHHHIIIJJJKKK","HHHIIIJJJKKKLLLMMM", + "JJJJKKKKLLLLMMMMNNNNOOOOPPPPQQQQRRRR","JJJKKKLLLMMMNNNOOO", + "KKKLLLMMMNNNOOOPPPRRRSSS","MMMNNNOOOPPP","RRRSSSTTTUUUVVVWWWXXXYYY", + "DDDD","CCCDDDEEEFFFGGG","D","HHHHIIIIJJJJKKKKLLLLMMMM" +}, *slopanim[MN_TN]={ + "","NNNOOOPPPRRRSSSTTT","MMMNNNOOOPPPRRRSSSTTT","MMMNNNOOOPPPRRRSSSTTT","", + "OOOPPPQQQRRRSSS","","","","","","","","","","","","","","OOPPQQRRSSTTUUVV" +}, *deadanim[MN_TN]={ + "N","M","L","L","P","N","O","O","L","","","S","P","T","Q","Z","C","","D","N" +}, *messanim[MN_TN]={ + "","U","U","U","","T","","","","","","","","","","","","","","W" +}; + +int hit_xv,hit_yv; + +static void *spr[MN_TN][29*2],*fspr[8],*fsnd,*pauksnd,*trupsnd,*sgun[2]; +static char sprd[MN_TN][29*2]; +static void *snd[MN_TN][5],*impsitsnd[2],*impdthsnd[2],*firsnd,*slopsnd,*gsnd[4]; +static void *swgsnd,*pchsnd,*pl_spr[2],*telesnd; +static void *positsnd[3],*podthsnd[3]; +static mn_t mn[MAXMN]; +static int mnum,gsndt; +static mnsz_t mnsz[MN_TN+1]={ +//rad ht life pain rv jv slop min_pn + 0, 0, 0, 0, 0, 0, 0, 0, // none + 15, 28, 60, 20, 7,10, 0, 10, // demon + 10, 28, 25, 15, 3,10, 30, 0, // imp + 10, 28, 15, 10, 3,10, 30, 0, // zomby + 10, 28, 20, 10, 3,10, 30, 0, // sergeant + 20, 55, 500, 70, 5,10, 0, 50, // cyberdemon + 12, 28, 60, 20, 3,10, 30, 10, // chaingunner + 12, 32, 150, 40, 3,10, 0, 30, // baron of hell + 12, 32, 75, 40, 3,10, 0, 30, // hell knight + 15, 28, 100, 10, 4, 4, 0, 0, // cacodemon + 8, 18, 60, 10, 4, 4, 0, 0, // lost soul + 15, 28, 100, 10, 4, 4, 0, 0, // pain elemental + 64, 50, 500, 70, 4,10, 0, 50, // spider mastermind + 25, 27, 150, 20, 4,10, 0, 0, // arachnotron + 18, 30, 200, 40, 3, 7, 0, 20, // mancubus + 17, 36, 200, 40, 6,11, 0, 20, // revenant + 17, 36, 150, 30, 7,12, 0, 10, // archvile + 5, 5, 35, 20,14, 6, 0, 10, // fish + 5, 17, 20, 0, 7, 6, 0, 0, // barrel + 17, 38, 20, 40, 3, 6, 0, 20, // robot + 8, 26, 400, 70, 8,10, 30, 50 // man +}; + +void MN_savegame(FILE* h) { + int n; + + for(n=MAXMN;--n;) if(mn[n].t) break; + ++n;myfwrite(&n,1,4,h); + myfwrite(mn,1,n*sizeof(mn[0]),h); + myfwrite(&mnum,1,4,h);myfwrite(&gsndt,1,4,h); +} + +static void setst(int,int); + +void MN_loadgame(FILE* h) { + int n,c; + + myfread(&n,1,4,h); + myfread(mn,1,n*sizeof(mn[0]),h); + myfread(&mnum,1,4,h);myfread(&gsndt,1,4,h); + for(n=0;n=MN_PL_DEAD) goto ok; + return -1; +ok: + mn[i].o.x=x;mn[i].o.y=y; + mn[i].o.xv=mn[i].o.yv=mn[i].o.vx=mn[i].o.vy=0; + mn[i].d=d;mn[i].t=t; + mn[i].st=SLEEP; + if(tx,o->y,c,t+MN_PL_DEAD))==-1) return -1; + mn[i].o=*o;return i; +} + +static int isfriend(int a,int b) { + if(a==MN_BARREL || b==MN_BARREL) return 1; + if(a==b) switch(a) { + case MN_IMP: case MN_DEMON: + case MN_BARON: case MN_KNIGHT: + case MN_CACO: case MN_SOUL: + case MN_MANCUB: case MN_SKEL: + case MN_FISH: + return 1; + } + if(a==MN_SOUL && b==MN_PAIN) return 1; + if(b==MN_SOUL && a==MN_PAIN) return 1; + return 0; +} + +static int MN_findnewprey(int i) { + int a,b,l; + + a=!PL_isdead(&pl1); + if(_2pl) b=!PL_isdead(&pl2); else b=0; + if(a) { + if(b) mn[i].aim=(abs(mn[i].o.x-pl1.o.x)+abs(mn[i].o.y-pl1.o.y) + <= abs(mn[i].o.x-pl2.o.x)+abs(mn[i].o.y-pl2.o.y))?-1:-2; + else mn[i].aim=-1; + }else{ + if(b) mn[i].aim=-2; + else{ + for(a=0,b=32000,mn[i].aim=-3;a=0 && i=50) mn[i].ammo=(mn[i].t==MN_ROBO)?-200:-50; + break; + case MN_MAN: + break; + case MN_MANCUB: + if(++mn[i].ammo>=5) mn[i].ammo=-50; + break; + case MN_SPIDER: + if(++mn[i].ammo>=100) mn[i].ammo=-50; + break; + case MN_CYBER: + if(rand()&1) return 0; + if(++mn[i].ammo>=10) mn[i].ammo=-50; + break; + case MN_BARON: case MN_KNIGHT: + if(rand()&7) return 0; + break; + case MN_SKEL: + if(rand()&31) return 0; + break; + case MN_VILE: + if(rand()&7) return 0; + break; + case MN_PAIN: + if(rand()&7) return 0; + break; + default: + if(rand()&15) return 0; + } + if(!Z_look(&mn[i].o,o,mn[i].d)) return 0; + mn[i].atm=0; + mn[i].tx=o->x+(o->xv+o->vx)*6;mn[i].ty=o->y-o->h/2+(o->yv+o->vy)*6; + if(abs(mn[i].tx-mn[i].o.x)x;mn[i].ty=o->y; + setst(i,SHOOT);Z_sound(fsnd,128); + Z_sound(snd[MN_VILE-1][2],128);break; + case MN_SOUL: + setst(i,ATTACK);Z_sound(snd[MN_SOUL-1][2],128); + yd=mn[i].ty-mn[i].o.y+mn[i].o.h/2;xd=mn[i].tx-mn[i].o.x; + if(!(m=max(abs(xd),abs(yd)))) m=1; + mn[i].o.xv=xd*16/m;mn[i].o.yv=yd*16/m; + break; + case MN_MANCUB: if(mn[i].ammo==1) Z_sound(snd[MN_MANCUB-1][2],128); + case MN_ZOMBY: case MN_SERG: case MN_BSP: case MN_ROBO: + case MN_CYBER: case MN_CGUN: case MN_SPIDER: + case MN_PAIN: case MN_MAN: + setst(i,SHOOT);break; + default: + return 0; + } + return 1; +} + +static int kick(int i,obj_t *o) { + switch(mn[i].t) { + case MN_FISH: + setst(i,ATTACK);return 1; + case MN_DEMON: + setst(i,ATTACK);Z_sound(snd[0][2],128);return 1; + case MN_IMP: + setst(i,ATTACK);Z_sound(snd[1][2],128);return 1; + case MN_SKEL: + setst(i,ATTACK);Z_sound(swgsnd,128);return 1; + case MN_ROBO: + setst(i,ATTACK);Z_sound(swgsnd,128);return 1; + case MN_BARON: case MN_KNIGHT: case MN_CACO: case MN_MANCUB: + return shoot(i,o,1); + } + return 0; +} + +static int iscorpse(obj_t *o,int n) { + int i; + + if(!n) if(rand()&7) return -3; + for(i=0;i 123) pt_xs=-pt_xs; + if(abs(pt_y+=pt_ys) > 50) pt_ys=-pt_ys; + if(gsndt>0) if(--gsndt==0) { + Z_sound(gsnd[myrand(4)],128); + } + for(i=0;i=mnsz[t].mp) + {mn[i].pain=mnsz[t].mp;Z_sound(snd[t-1][1],128);} + if((mn[i].pain-=5)<=mnsz[t].minp) + {setst(i,GO);mn[i].pain=0;mn[i].ammo=-9;} + break; + case SLEEP: + if(++mn[i].s>=18) mn[i].s=0; else break; + if(Z_look(&mn[i].o,&pl1.o,mn[i].d)) + {setst(i,GO);mn[i].aim=-1;mn[i].atm=0;Z_sound(wakeupsnd(t),128);} + if(_2pl) if(Z_look(&mn[i].o,&pl2.o,mn[i].d)) + {setst(i,GO);mn[i].aim=-2;mn[i].atm=0;Z_sound(wakeupsnd(t),128);} + break; + case WAIT: + if(--mn[i].s<0) setst(i,GO); + break; + case GO: + if(st&Z_BLOCK) {mn[i].d^=1;setst(i,RUNOUT);mn[i].s=40;break;} + if(t==MN_VILE) if(iscorpse(&mn[i].o,0)>=0) { + setst(i,ATTACK);mn[i].o.xv=0;break; + } + if(!Z_getobjpos(mn[i].aim,&o) || mn[i].atm>MAX_ATM) + if(!MN_findnewprey(i)) { + mn[i].aim=-3; + o.x=mn[i].o.x+pt_x;o.y=mn[i].o.y+pt_y; + o.xv=o.vx=o.yv=o.vy=o.r=0;o.h=1; + }else Z_getobjpos(mn[i].aim,&o); + if(Z_overlap(&mn[i].o,&o)) { + mn[i].atm=0; + if(kick(i,&o)) break; + } + sx=o.x-mn[i].o.x; + sy=o.y-o.h/2-mn[i].o.y+mn[i].o.h/2; + if(!(st&Z_BLOCK)) if(abs(sx)<20) + if(t!=MN_FISH) {setst(i,RUN);mn[i].s=15;mn[i].d=rand()&1;break;} + if(st&Z_HITWALL) { + if(SW_press(mn[i].o.x,mn[i].o.y,mn[i].o.r,mn[i].o.h,2,i)) + {setst(i,WAIT);mn[i].s=4;break;} + switch(t) { + case MN_CACO: case MN_SOUL: case MN_PAIN: case MN_FISH: + break; + default: + if(Z_canstand(mn[i].o.x,mn[i].o.y,mn[i].o.r)) + {mn[i].o.yv=-mnsz[t].jv;setst(i,CLIMB);break;} + }break; + } + mn[i].d=(sx>0)?1:0; + if(canshoot(t)) + if(abs(sx)>abs(sy)) if(shoot(i,&o,0)) break; + + switch(t) { + case MN_FISH: + if(!(st&Z_INWATER)) { + if(Z_canstand(mn[i].o.x,mn[i].o.y,mn[i].o.r)) { + mn[i].o.yv=-6; + mn[i].o.vx+=rand()%17-8; + }setst(i,PAIN);mn[i].pain+=50;break; + } + case MN_CACO: case MN_SOUL: case MN_PAIN: + if(abs(sy)>4) mn[i].o.yv=(sy<0)?-4:4; else mn[i].o.yv=0; + if(t==MN_FISH) if(mn[i].o.yv<0) + if(!Z_inwater(mn[i].o.x,mn[i].o.y-8,mn[i].o.r,mn[i].o.h)) + {mn[i].o.yv=0;setst(i,RUN);mn[i].d=rand()&1;mn[i].s=20;} + break; + default: + if(sy<-20) if(Z_canstand(mn[i].o.x,mn[i].o.y,mn[i].o.r)) + if(!(rand()&3)) mn[i].o.yv=-mnsz[t].jv; + } + if(++mn[i].s>=8) { + mn[i].s=0; + if(!(rand()&7)) Z_sound(snd[t-1][0],128); + } + mn[i].o.xv=((mn[i].d)?1:-1)*mnsz[t].rv; + if(st&Z_INWATER) mn[i].o.xv/=2; + else if(t==MN_FISH) mn[i].o.xv=0; + break; + case RUN: + if(st&Z_BLOCK) {setst(i,RUNOUT);mn[i].d^=1;mn[i].s=40;break;} + if(--mn[i].s<=0 || ((st&Z_HITWALL) && mn[i].o.yv+mn[i].o.vy==0)) { + setst(i,GO);mn[i].s=0;if(st&(Z_HITWALL|Z_BLOCK)) mn[i].d^=1; + if(!(rand()&7)) Z_sound(snd[t-1][0],128); + }mn[i].o.xv=((mn[i].d)?1:-1)*mnsz[t].rv; + if(st&Z_INWATER) mn[i].o.xv/=2; + else if(t==MN_FISH) mn[i].o.xv=0; + break; + case RUNOUT: + if(!(st&Z_BLOCK) && mn[i].s>0) mn[i].s=0; + if(--mn[i].s<=-18) { + setst(i,GO);mn[i].s=0;if(st&(Z_HITWALL|Z_BLOCK)) mn[i].d^=1; + if(!(rand()&7)) Z_sound(snd[t-1][0],128); + }mn[i].o.xv=((mn[i].d)?1:-1)*mnsz[t].rv; + if(st&Z_INWATER) mn[i].o.xv/=2; + else if(t==MN_FISH) mn[i].o.xv=0; + break; + case CLIMB: + if(mn[i].o.yv+mn[i].o.vy>=0 || !(st&Z_HITWALL)) { + setst(i,GO);mn[i].s=0; + if(st&(Z_HITWALL|Z_BLOCK)) {mn[i].d^=1;setst(i,RUN);mn[i].s=15;} + }mn[i].o.xv=((mn[i].d)?1:-1)*mnsz[t].rv; + if(st&Z_INWATER) mn[i].o.xv/=2; + else if(t==MN_FISH) mn[i].o.xv=0; + break; + case ATTACK: + case SHOOT: + if(t==MN_SOUL) {if(st&(Z_HITWALL|Z_HITCEIL|Z_HITLAND)) setst(i,GO); break;} + if(t!=MN_FISH) mn[i].o.xv=Z_dec(mn[i].o.xv,1); + if(t==MN_VILE && mn[i].st==SHOOT) { + if(!Z_getobjpos(mn[i].aim,&o)) {setst(i,GO);break;} + if(!Z_look(&mn[i].o,&o,mn[i].d)) {setst(i,GO);break;} + if(Z_inwater(o.x,o.y,o.r,o.h)) {setst(i,GO);break;} + mn[i].tx=o.x;mn[i].ty=o.y; + Z_hitobj(mn[i].aim,2,i,HIT_SOME); + }break; + } + if(mn[i].st==REVIVE) { + if(--mn[i].ac==0) setst(i,GO); + }else ++mn[i].ac; + if(!mn[i].ap[mn[i].ac]) switch(mn[i].st) { + case ATTACK: + switch(t) { + case MN_SOUL: mn[i].ac=0; + case MN_IMP: + case MN_DEMON: + if(Z_hit(&mn[i].o,15,i,HIT_SOME)) if(t==MN_SOUL) setst(i,GO); + break; + case MN_FISH: + if(Z_hit(&mn[i].o,10,i,HIT_SOME)) + Z_sound(snd[MN_FISH-1][2],128); + break; + case MN_SKEL: case MN_ROBO: + o=mn[i].o;o.xv=mn[i].d?50:-50; + if(Z_hit(&o,50,i,HIT_SOME)) Z_sound(pchsnd,128); + break; + case MN_VILE: + sx=iscorpse(&mn[i].o,1); + if(sx==-3) break; + if(!mn[sx].t || mn[sx].st!=DEAD) break; + setst(sx,REVIVE);Z_sound(slopsnd,128); + hit_xv=hit_yv=0;MN_hit(i,5,-3,HIT_SOME); + break; + }if(t!=MN_SOUL && mn[i].st!=DIE) setst(i,GO); + break; + case SHOOT: + switch(t) { + case MN_IMP: + 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); + break; + case MN_ZOMBY: + 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); + break; + case MN_SERG: + 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); + break; + case MN_MAN: + 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); + mn[i].ammo=-36;break; + case MN_CYBER: + 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); + break; + case MN_SKEL: + 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); + break; + case MN_CGUN: + case MN_SPIDER: + 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); + break; + case MN_BSP: + 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); + break; + case MN_ROBO: + WP_plasma(mn[i].o.x+(mn[i].d*2-1)*15,mn[i].o.y-30,mn[i].tx,mn[i].ty,i); + break; + case MN_MANCUB: + 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); + break; + case MN_BARON: case MN_KNIGHT: + WP_ball7(mn[i].o.x,mn[i].o.y-mn[i].o.h/2,mn[i].tx,mn[i].ty,i); + break; + case MN_CACO: + WP_ball2(mn[i].o.x,mn[i].o.y-mn[i].o.h/2,mn[i].tx,mn[i].ty,i); + break; + case MN_PAIN: + if((sx=MN_spawn(mn[i].o.x,mn[i].o.y,mn[i].d,MN_SOUL))==-1) break; + Z_getobjpos(mn[sx].aim=mn[i].aim,&o);mn[sx].atm=0; + shoot(sx,&o,1); + break; + } + if(t==MN_CGUN || t==MN_SPIDER || t==MN_BSP || t==MN_MANCUB || t==MN_ROBO) + if(!Z_getobjpos(mn[i].aim,&o)) MN_findnewprey(i); + else if(shoot(i,&o,0)) break; + setst(i,GO);break; + case DIE: + setst(i,DEAD); + if(t==MN_PAIN || t==MN_SOUL) mn[i].ftime=0; + if(t==MN_PAIN) { + if((sx=MN_spawn(mn[i].o.x-15,mn[i].o.y,0,MN_SOUL))==-1) break; + setst(sx,GO); + if((sx=MN_spawn(mn[i].o.x+15,mn[i].o.y,1,MN_SOUL))==-1) break; + setst(sx,GO); + if((sx=MN_spawn(mn[i].o.x,mn[i].o.y-10,1,MN_SOUL))==-1) break; + setst(sx,GO); + }break; + default: mn[i].ac=0; + } + switch(mn[i].st) { + case GO: case RUN: case CLIMB: case RUNOUT: + if(t==MN_CYBER || t==MN_SPIDER || t==MN_BSP) { + if(mn[i].ac==0 || mn[i].ac==6) Z_sound(snd[t-1][2],128); + }else if(t==MN_ROBO) + if(mn[i].ac==0 || mn[i].ac==12) Z_sound(snd[t-1][2],128); + } + } +} + +void MN_mark(void) { + int i; + for(i=0;i=MN_PL_DEAD) { + Z_drawmanspr(mn[i].o.x,mn[i].o.y,pl_spr[mn[i].t-MN_PL_DEAD],0,mn[i].d); + continue; + } + if((mn[i].t!=MN_SOUL && mn[i].t!=MN_PAIN) || mn[i].st!=DEAD) { + if(mn[i].t!=MN_MAN) + Z_drawspr(mn[i].o.x,mn[i].o.y, + spr[mn[i].t-1][(mn[i].ap[mn[i].ac]-'A')*2+mn[i].d], + sprd[mn[i].t-1][(mn[i].ap[mn[i].ac]-'A')*2+mn[i].d]); + else{ + if(mn[i].ap[mn[i].ac]=='E' || mn[i].ap[mn[i].ac]=='F') + Z_drawspr(mn[i].o.x,mn[i].o.y,sgun[mn[i].ap[mn[i].ac]-'E'],mn[i].d); + Z_drawmanspr(mn[i].o.x,mn[i].o.y, + spr[mn[i].t-1][(mn[i].ap[mn[i].ac]-'A')*2+mn[i].d], + sprd[mn[i].t-1][(mn[i].ap[mn[i].ac]-'A')*2+mn[i].d],MANCOLOR); + } + } + if(mn[i].t==MN_VILE && mn[i].st==SHOOT) { + Z_drawspr(mn[i].tx,mn[i].ty,fspr[mn[i].ac/3],0); + } + } +} + +int MN_hit(int n,int d,int o,int t) { + int i; + + if(mn[n].st==DEAD || mn[n].st==DIE) return 0; + if(o==n) { + if(t!=HIT_ROCKET && t!=HIT_ELECTRO) return 0; + if(mn[n].t==MN_CYBER || mn[n].t==MN_BARREL) return 1; + } + if(o>=0) { + if(mn[o].t==MN_SOUL && mn[n].t==MN_PAIN) return 0; + if(mn[o].t==mn[n].t) switch(mn[n].t) { + case MN_IMP: case MN_DEMON: + case MN_BARON: case MN_KNIGHT: + case MN_CACO: case MN_SOUL: + case MN_MANCUB: case MN_SKEL: + case MN_FISH: + return 0; + } + } + if(t==HIT_FLAME) if(mn[n].ftime && mn[n].fobj==o) {if(g_time&31) return 1;} + else {mn[n].ftime=255;mn[n].fobj=o;} + if(t==HIT_ELECTRO) if(mn[n].t==MN_FISH) + {setst(n,RUN);mn[n].s=20;mn[n].d=rand()&1;return 1;} + if(t==HIT_TRAP) mn[n].life=-100; + if(mn[n].t==MN_ROBO) d=0; + if((mn[n].life-=d)<=0) --mnum; + if(!mn[n].pain) mn[n].pain=3; + mn[n].pain+=d; + if(mn[n].st!=PAIN) { + if(mn[n].pain>=mnsz[mn[n].t].minp) setst(n,PAIN); + } + if(mn[n].t!=MN_BARREL) + DOT_blood(mn[n].o.x,mn[n].o.y-mn[n].o.h/2,hit_xv,hit_yv,d*2); + mn[n].aim=o;mn[n].atm=0; + if(mn[n].life<=0) { + if(mn[n].t!=MN_BARREL) + if(o==-1) ++pl1.kills; + else if(o==-2) ++pl2.kills; + setst(n,DIE); + switch(mn[n].t) { + case MN_ZOMBY: i=I_CLIP;break; + case MN_SERG: i=I_SGUN;break; + case MN_CGUN: i=I_MGUN;break; + case MN_MAN: i=I_KEYR;break; + default: i=0; + }if(i) IT_spawn(mn[n].o.x,mn[n].o.y,i); + mn[n].o.xv=0;mn[n].o.h=6; + if(mn[n].life<=-mnsz[mn[n].t].sp) + switch(mn[n].t) { + case MN_IMP: case MN_ZOMBY: case MN_SERG: case MN_CGUN: + case MN_MAN: + mn[n].ap=slopanim[mn[n].t-1]; + Z_sound(slopsnd,128); + break; + case MN_BSP: if(g_map==9) break; + default: + Z_sound(dthsnd(mn[n].t),128); + } + else if(mn[n].t!=MN_BSP || g_map!=9) Z_sound(dthsnd(mn[n].t),128); + mn[n].life=0; + }else if(mn[n].st==SLEEP) {setst(n,GO);mn[n].pain=mnsz[mn[n].t].mp;} + return 1; +} + +#define hit(o,x,y) (y<=o.y && y>o.y-o.h && x>=o.x-o.r && x<=o.x+o.r) + +int Z_gunhit(int x,int y,int o,int xv,int yv) { + int i; + + if(o!=-1) if(hit(pl1.o,x,y)) if(PL_hit(&pl1,3,o,HIT_SOME)) + {pl1.o.vx+=xv;pl1.o.vy+=yv;return -1;} + if(_2pl && o!=-2) if(hit(pl2.o,x,y)) if(PL_hit(&pl2,3,o,HIT_SOME)) + {pl2.o.vx+=xv;pl2.o.vy+=yv;return -2;} + + for(i=0;ixv+o->vx; + hit_yv=o->yv+o->vy; + if(Z_overlap(o,&pl1.o)) if(PL_hit(&pl1,d,own,t)) { + pl1.o.vx+=(o->xv+o->vx)*((t==HIT_BFG)?8:1)/4; + pl1.o.vy+=(o->yv+o->vy)*((t==HIT_BFG)?8:1)/4; + if(t==HIT_BFG) goodsnd(); + return -1; + } + if(_2pl) if(Z_overlap(o,&pl2.o)) if(PL_hit(&pl2,d,own,t)) { + pl2.o.vx+=(o->xv+o->vx)*((t==HIT_BFG)?8:1)/4; + pl2.o.vy+=(o->yv+o->vy)*((t==HIT_BFG)?8:1)/4; + if(t==HIT_BFG) goodsnd(); + return -2; + } + + for(i=0;ixv+o->vx)*((t==HIT_BFG)?8:1)/4; + mn[i].o.vy+=(o->yv+o->vy)*((t==HIT_BFG)?8:1)/4; + return 1; + } + return 0; +} + +void MN_killedp(void) { + int i; + + for(i=0;i=MAXMN) return 0; + if(mn[obj].t) return MN_hit(obj,d,own,t); + return 0; +} + +void Z_explode(int x,int y,int rad,int own) { + long r; + int dx,dy,m,i; + + if(x<-100 || x>FLDW*CELW+100) return; + if(y<-100 || y>FLDH*CELH+100) return; + r=(long)rad*rad; + dx=pl1.o.x-x;dy=pl1.o.y-pl1.o.h/2-y; + if((long)dx*dx+(long)dy*dyFLDW*CELW+100) return; + if(y<-100 || y>FLDH*CELH+100) return; + dx=pl1.o.x-x;dy=pl1.o.y-pl1.o.h/2-y; + if(own!=-1) if((long)dx*dx+(long)dy*dy<16000) + if(Z_cansee(x,y,pl1.o.x,pl1.o.y-pl1.o.h/2)) { + if(PL_hit(&pl1,50,own,HIT_SOME)) + WP_bfghit(pl1.o.x,pl1.o.y-pl1.o.h/2,own); + } + if(_2pl) { + dx=pl2.o.x-x;dy=pl2.o.y-pl2.o.h/2-y; + if(own!=-2) if((long)dx*dx+(long)dy*dy<16000) + if(Z_cansee(x,y,pl2.o.x,pl2.o.y-pl2.o.h/2)) { + if(PL_hit(&pl2,50,own,HIT_SOME)) + WP_bfghit(pl2.o.x,pl2.o.y-pl2.o.h/2,own); + } + } + for(i=0;i=0 && ox,p->y);FX_tfog(p->x=x,p->y=y); + Z_sound(telesnd,128); +} + +void MN_warning(int l,int t,int r,int b) { + int i; + + for(i=0;i=l && mn[i].o.x-mn[i].o.r<=r + && mn[i].o.y>=t && mn[i].o.y-mn[i].o.h<=b) + if(Z_canstand(mn[i].o.x,mn[i].o.y,mn[i].o.r)) + mn[i].o.yv=-mnsz[mn[i].t].jv; +} diff --git a/monster.h b/monster.h new file mode 100755 index 0000000..376b1a2 --- /dev/null +++ b/monster.h @@ -0,0 +1,44 @@ +/* + Copyright (C) Prikol Software 1996-1997 + Copyright (C) Aleksey Volynskov 1996-1997 + Copyright (C) 2011 + + This file is part of the Doom2D:Rembo project. + + Doom2D:Rembo is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 2 as + published by the Free Software Foundation. + + Doom2D:Rembo is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see or + write to the Free Software Foundation, Inc., + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +// Monsters + +#define MAXMN 200 + +enum{ + MN_NONE,MN_DEMON,MN_IMP,MN_ZOMBY,MN_SERG,MN_CYBER,MN_CGUN, + MN_BARON,MN_KNIGHT,MN_CACO,MN_SOUL,MN_PAIN,MN_SPIDER,MN_BSP, + MN_MANCUB,MN_SKEL,MN_VILE,MN_FISH,MN_BARREL,MN_ROBO,MN_MAN, + MN__LAST, + MN_PL_DEAD=100,MN_PL_MESS +}; + +void MN_init(void); +void MN_alloc(void); +int MN_spawn(int,int,byte,int); +int MN_spawn_deadpl(obj_t *,byte,int); +void MN_act(void); +void MN_mark(void); +void MN_draw(void); +void MN_warning(int l,int t,int r,int b); + +void MN_killedp(void);