#include #include #include #include #include #include #include #include #include //#include #include #include #include "engine1.h" #include "globals.h" #define S_jmeno 128 #define S_kouzlo 129 #define S_zivel 131 #define S_level 133 #define S_mge 134 #define S_hpnorm_min 135 #define S_hpnorm_max 136 #define S_hpzivl_min 137 #define S_hpzivl_max 138 #define S_vlastnost 139 #define S_vls_kolik 140 #define S_trvani 141 #define S_cil 142 #define S_throw_item 142 #define S_create_item 143 #define S_backfire 144 #define S_povaha 145 #define S_special 146 #define S_pvls 147 #define S_animace 148 #define S_zvuk 149 #define S_wait 150 #define S_set 151 #define S_reset 152 #define S_drain_min 153 #define S_drain_max 154 #define S_accnum 155 #define S_kondice 156 #define S_mana 157 #define S_create_weapon 158 #define S_mana_clip 159 #define S_mana_steal 160 #define S_rand_min 161 #define S_rand_max 162 #define S_location_sector 163 #define S_location_map 164 #define S_location_dir 165 #define S_location_x 166 #define S_location_y 167 #define C_kouzelnik 0 #define C_postava 1 #define C_policko 2 #define C_druzina 2 #define C_policko_pred 3 #define C_mrtva_postava 4 #define C_postava_jinde 5 #define C_nahodna_postava 6 #define C_jiny_cil 7 #define SP_AUTOMAP4 1 #define SP_AUTOMAP8 2 #define SP_AUTOMAP15 3 #define SP_PRIPOJENI1 4 #define SP_PRIPOJENI3 5 #define SP_PRIPOJENIA 6 #define SP_CHVENI 7 #define SP_DEFAULT_EFFEKT 8 #define SP_TRUE_SEEING 9 #define SP_SCORE 10 #define SP_HALUCINACE 11 #define SP_TELEPORT 12 #define SP_SUMMON 13 #define SP_HLUBINA1 14 #define SP_HLUBINA2 15 #define SP_MANABAT 16 #define SP_VAHY 17 #define SP_RYCHLOST 18 #define SP_VIR 19 #define SP_DEMON1 20 #define SP_DEMON2 21 #define SP_DEMON3 22 #define SP_VZPLANUTI1 23 #define SP_VZPLANUTI2 24 #define SP_VZPLANUTI3 25 #define SP_PHASEDOOR 26 #define SP_TELEPORT_SECT 27 #define SP_OPEN_TELEPORT 28 #define SS_invis 1 #define SS_oko 2 #define SS_tvar 4 #define FLG_TRUESEEING 0x10000 //zapnuty TRUESEEING #define FLG_HLUBINA1 0x20000 //zapnuta HLUBINA pro vsechny #define FLG_HLUBINA2 0x40000 //zapnuta HLUBINA pro potvory #define FLG_SCORE 0x80000 //zapnute ukazovani score nad potvorama. #define FLG_HALUCINACE 0x100000 // zapne halucinaci #define GET_WORD(c) *(word *)c;c+=2 #define MAX_SPELLS 500 char running_anm=0; char hlubina_level=0; word *anim_render_buffer; short teleport_target=0; //cil teleportace typedef struct tteleportlocation { short loc_x; short loc_y; const char *map; word sector; word dir; }TTELEPLOCATION; static TTELEPLOCATION TelepLocation; typedef struct tkouzlo { word num,um,mge; word pc; short owner,accnum; //accnum = akumulacni cislo, owner = kdo kouzlo seslal int start; short cil; //kladna cisla jsou postavy zaporna potvory (0 je bez urceni postavy) char povaha; word backfire; //backfire / 1 = demon , 0 = bez demona word wait; //wait - cekani pocet animaci word delay; //delay - cekani pocet kol char traceon; //jinak noanim - neprehravaji se animace a zvuky char spellname[28]; word teleport_target; }TKOUZLO; TKOUZLO *spell_table[MAX_SPELLS]; short *vls_table[MAX_SPELLS]; //nove vlastnosti postav //pokud je cislo vetsi nez 0x7f00 pak dolni byte uvadi percentualni pomer static long _flag_map[MAX_SPELLS]; //tabulka nastavenych priznaku pro kouzlo. //prvnich 16 bitu je pro postavu //hornich 16 bitu je globalne short parm1,parm2; char twins; static short rand_value; static word *paleta; void show_full_lfb12e(void *target,void *buff,void *paleta); //#pragma aux show_full_lfb12e parm[edi][esi][ebx] modify [eax ecx] void show_delta_lfb12e(void *target,void *buff,void *paleta); //#pragma aux show_delta_lfb12e parm[edi][esi][ebx] modify [eax ecx] char mob_check_next_sector(int sect,int dir,char alone,char passable); void call_spell(int i); int calculatePhaseDoor(int sector, int dir, int um); static void animace_kouzla(int act,void *data, int ssize) { switch (act) { case MGIF_LZW: case MGIF_COPY:show_full_lfb12e(anim_render_buffer,data,paleta);break; case MGIF_DELTA:show_delta_lfb12e(anim_render_buffer,data,paleta);break; case MGIF_PAL:paleta=data;*paleta|=0x8000;break; } } static void play_anim(va_list args) //tasked animation //#pragma aux play_anim parm [] { int block=va_arg(args,int); #define ANIM_SIZE (320*180*2) void *anm; long *l,c; if (running_anm) { SEND_LOG("(ERROR)(ANIM) Animation's mutex is already in use!",0,0); return; } SEND_LOG("(ANIM) Running animation number %xh",block,0); anim_render_buffer=getmem(ANIM_SIZE); mgif_install_proc(animace_kouzla); running_anm=1; l=(void *)anim_render_buffer; c=ANIM_SIZE/4;do *l++=0x80008000; while (--c); alock(block); anm=open_mgif(ablock(block)); c=0; SEND_LOG("(ANIM) Buffer is now ready...",0,0); while (anm!=NULL) { task_wait_event(E_KOUZLO_ANM); c++; SEND_LOG("(ANIM) Rendering frame %d in animation %xh",c,block); anm=mgif_play(anm); neco_v_pohybu=1; } task_wait_event(E_KOUZLO_ANM); close_mgif(); running_anm=0; free(anim_render_buffer); SEND_LOG("(ANIM) Closing animation %xh",block,0); aunlock(block); } void play_big_mgif_animation(int block) { add_task(2048,play_anim,block); task_sleep(NULL); } int get_spell_mana(int num) { TKOUZLO *p; p=(TKOUZLO *)ablock(H_KOUZLA); return p[num].mge; } int get_spell_um(int num) { TKOUZLO *p; p=(TKOUZLO *)ablock(H_KOUZLA); return p[num].um; } int get_spell_used(int num) { TKOUZLO *p; p=(TKOUZLO *)ablock(H_KOUZLA); return (p[num].start!=0); } char get_spell_track(int num) { TKOUZLO *p; p=(TKOUZLO *)ablock(H_KOUZLA); return (p[num].traceon & 1); } char get_spell_teleport(int num) { TKOUZLO *p; p=(TKOUZLO *)ablock(H_KOUZLA); return (p[num].traceon & 2); } int get_spell_color(THUMAN *p,int num) { TKOUZLO *z; z=(TKOUZLO *)ablock(H_KOUZLA); z+=num; if (!z->start) return 1; if (z->mge>p->mana) return 1; if (z->um<=p->vlastnosti[VLS_SMAGIE]) return 0; if (z->um<=(p->vlastnosti[VLS_SMAGIE]*2)) return 2; return 1; } char get_rune_enable(THUMAN *p,int strnum) { int i; for(i=0;i<3;i++) if (get_spell_color(p,strnum+i)!=1) return 1; return 0; } char *get_rune_name(int strnum) { TKOUZLO *z; z=(TKOUZLO *)ablock(H_KOUZLA); z+=strnum; return z->spellname; } void spell_anim(char *name) { int i; i=find_handle(name,NULL); if (i==-1) i=end_ptr++; def_handle(i,name,NULL,SR_ITEMS); add_task(8196,play_anim,i); } void spell_sound(char *name) { int i; i=find_handle(name,wav_load); if (i==-1) i=end_ptr++; def_handle(i,name,wav_load,SR_ZVUKY); play_sample_at_channel(i,0,100); } void get_sector_dir(int cil,word *sector,char *dir) { if (cil>0) { cil--; if (postavy[cil].used) *sector=postavy[cil].sektor,*dir=postavy[cil].direction; } else if (cil<0) { cil=-cil-1; *sector=mobs[cil].sector; *dir=mobs[cil].dir; } } static void spell_vzplanuti3(int ss,int hit,int zivel) { if (map_coord[ss].flags & MC_PLAYER) { THUMAN *h;int i; for(i=0,h=postavy;iused && h->lives && h->sektor==ss) { int ochrana=mgochrana(h->vlastnosti[VLS_OHEN+zivel]); player_hit(h,hit*ochrana/100,1); } } if (mob_map[ss]) { int i=mob_map[ss]; while(i) { TMOB *m=mobs+i-1; int ochrana=mgochrana(m->vlastnosti[VLS_OHEN+zivel]); vybrana_zbran=-1; mob_hit(m,hit*ochrana/100); i=m->next; } } } static void spell_vzplanuti2(THE_TIMER *tt) { int ss,ss1,ss2,i,dp,dl,du; int zivel; i=tt->userdata[2];if (i<1) i++; du=tt->userdata[1] & 0xff; ss=tt->userdata[0]; zivel=tt->userdata[1] >> 8; if (map_sides[(ss<<2)+du].flags & SD_PLAY_IMPS) return; ss1=ss2=ss=map_sectors[ss].step_next[du]; if (ss==0) return; dp=du+1&3; dl=du+3&3; do { if (ss1!=0) { add_spectxtr(ss1,H_ARMAGED,H_ARMA_CNT,1,0); spell_vzplanuti3(ss1,tt->userdata[3],zivel); } if (ss2!=ss1 && ss2!=0) { add_spectxtr(ss2,H_ARMAGED,H_ARMA_CNT,1,0); spell_vzplanuti3(ss2,tt->userdata[3],zivel); } if (~map_sides[(ss1<<2)+dp].flags & SD_PLAY_IMPS) ss1=map_sectors[ss1].step_next[dp]; if (~map_sides[(ss2<<2)+dl].flags & SD_PLAY_IMPS) ss2=map_sectors[ss2].step_next[dl]; } while(--i); if (tt->userdata[2]) tt->userdata[2]++; //tt->userdata[3]=tt->userdata[3]*2/3; tt->userdata[0]=ss; } static void spell_vzplanuti(int cil,int count,int hit,char mode,char zivel) { THE_TIMER *tt; int sector,smer; int i,o,d; if (cil<0) { TMOB *m=&mobs[-cil-1]; sector=m->sector; smer=m->dir; } else if (cil>0) { THUMAN *h=postavy+cil-1; sector=h->sektor; smer=h->direction; } if (mode) {o=smer;d=smer+1;}else o=0,d=4; for(i=o;i1) tt=add_to_timer(TM_VZPLANUTI,25,count-1,spell_vzplanuti2); else tt=&tts; tt->userdata[0]=sector; tt->userdata[1]=i+(zivel<<8); tt->userdata[2]=!mode; tt->userdata[3]=hit; spell_vzplanuti2(tt); } neco_v_pohybu=1; } void spell_create(int cil,int what) { word sector=0; char dir; short p[2]; get_sector_dir(cil,§or,&dir); p[0]=what+1; p[1]=0; push_item(sector,dir,p); } void spell_create_weapon(int cil,int what) { THUMAN *h=postavy+cil-1; short lr,pr; lr=h->wearing[PO_RUKA_L]; pr=h->wearing[PO_RUKA_R]; if (lr && glob_items[lr-1].umisteni==PL_OBOUR) pr=lr; else if (pr && glob_items[pr-1].umisteni==PL_OBOUR) lr=pr; if (lr && pr) { char s[256]; sprintf(s,texty[86],h->jmeno); bott_disp_text(s); return; } if (!pr) h->wearing[PO_RUKA_R]=what+1; else if (!lr) h->wearing[PO_RUKA_L]=what+1; prepocitat_postavu(h); } void spell_throw(int cil,int what) { word sector=0; char dir; LETICI_VEC *fly; get_sector_dir(cil,§or,&dir); fly=create_fly(); fly->item=what+1; fly->items=NULL; fly->xpos=-63; fly->ypos=0; fly->zpos=80; fly->speed=32; fly->velocity=0; fly->flags=FLY_NEHMOTNA | FLY_DESTROY; fly->sector=sector; fly->smer=dir; fly->owner=cil; fly->hit_bonus=0; fly->damage=0; fly->lives=glob_items[what].user_value; fly->counter = 0; add_fly(fly); } void zmen_vlastnost(int num,int cil,int what,int how) { if (!how) return; if (cil<0) { cil=-cil-1; if (mobs[cil].vlastnosti[what]+how<0) how=-mobs[cil].vlastnosti[what]; vls_table[num][what]-=how; mobs[cil].vlastnosti[what]+=how; } else if(cil>0) { THUMAN *p; vls_table[num][what]-=how; cil--; p=&postavy[cil]; postavy[cil].stare_vls[what]+=how; prepocitat_postavu(&postavy[cil]); if (p->lives>p->vlastnosti[VLS_MAXHIT]) p->lives=p->vlastnosti[VLS_MAXHIT]; //if (p->mana>p->vlastnosti[VLS_MAXMANA]) p->lives=p->vlastnosti[VLS_MAXMANA]; if (p->kondice>p->vlastnosti[VLS_KONDIC]) p->lives=p->vlastnosti[VLS_KONDIC]; } } void zmen_vlastnost_percent(int num,int cil,int what,int how) { int x; int c; if (cil<0) { c=-cil-1; x=mobs[c].vlastnosti[what]; } else { c=cil-1; x=postavy[c].vlastnosti[what]; } x=x*abs(how)/100;if (how<0) x=-x; zmen_vlastnost(num,cil,what,x); } char hod_na_uspech(int cil,TKOUZLO *k) { if (!k->povaha) return 1; if (cil) { int z,zv; short *p; if (cil<0) { cil=-cil-1; p=mobs[cil].vlastnosti+VLS_OHEN; } else if(cil>0) { cil--; p=postavy[cil].vlastnosti+VLS_OHEN; } zv=mgochrana(p[k->pc]); z=rnd(100); return (z<=zv); } return 0; } void spell_end_global() { long l=0; int i; for(i=0;isektor=q->sektor; p->direction=q->direction; p->groupnum=q->groupnum; p->demon_save=q; } static void zmena_z_demona(int hrac) { THUMAN *q=postavy+hrac; THUMAN *p=q->demon_save; p->sektor=q->sektor; p->direction=q->direction; p->groupnum=q->groupnum; *q=*p; free(p); } static void zmena_demona(int hrac,int demon,char smer) { THUMAN *p=postavy+hrac; if (postavy[hrac].stare_vls[VLS_KOUZLA] & SPL_DEMON && smer!=0) return; if (~postavy[hrac].stare_vls[VLS_KOUZLA] & SPL_DEMON && smer==0) return; if (smer!=0) zmena_na_demona(hrac,demon);else zmena_z_demona(hrac); if (smer!=0) { p->lives=p->vlastnosti[VLS_MAXHIT]; p->kondice=p->vlastnosti[VLS_KONDIC]; p->mana=p->vlastnosti[VLS_MAXMANA]; p->jidlo=MAX_HLAD(p); p->voda=MAX_ZIZEN(p); } reg_grafiku_postav(); } static void unaffect_after_demon(int cil) { int i; char a; TKOUZLO *spl; SEND_LOG("(SPELLS) Unaffecting after demon...",0,0); do { a=0; for(i=0;spl=spell_table[i],icil==cil && spl->backfire==1) { if (spl->wait) { spl->wait=0;call_spell(i); a=1; } if (spl->cil>0) { spl->delay=0;call_spell(i); a=1; } } } while(a); } void spell_end(int num,int ccil,int owner) { int i,l; int cil=ccil; for(i=0;i0) { cil--; if (_flag_map[num] & SPL_DEMON) { unaffect_after_demon(ccil); zmena_demona(cil,owner,0); _flag_map[num]&=~SPL_DEMON; SEND_LOG("(SPELLS) Spell 'Demon' has ended...",0,0); } postavy[cil].stare_vls[VLS_KOUZLA]&=~_flag_map[num]; if (cil>=0 && cilcil==ccil && ccil>0 && spell_table[i]->owner>=0) { postavy[cil].spell=1; bott_draw(0); break; }; l=_flag_map[num]; _flag_map[num]=0; if (l>0xffff) spell_end_global(); SEND_LOG("(SPELLS) Spell ID %d ends.",num,0); } static void spell_demon(int num,TKOUZLO *spl,int cil,int demon) { cil--; if (postavy[cil].stare_vls[VLS_KOUZLA] & SPL_DEMON) return; spl->owner=demon; zmena_demona(cil,demon,1); postavy[cil].stare_vls[VLS_KOUZLA]|=SPL_DEMON; _flag_map[num]|=SPL_DEMON; bott_draw(1); } void spell_hit(int cil,int min,int max,int owner) { if (cil) if (cil<0) { TMOB *m; cil=-cil-1; m=&mobs[cil]; select_player=owner; vybrana_zbran=-1; mob_hit(m,min+rnd(max-min)); } else if(cil>0) { THUMAN *h; int vysl; cil--; h=&postavy[cil]; vysl=min+rnd(max-min); if (vysl<0) { h->lives-=vysl,h->lives=min(h->lives,h->vlastnosti[VLS_MAXHIT]); if (h->groupnum==0) h->groupnum=cur_group; } else player_hit(h,vysl,1); bott_draw(0); } } void spell_hit_zivel(int cil,int min,int max,int owner,int zivel) { int ochrana; if (cil) if (cil<0) { TMOB *m; cil=-cil-1; m=&mobs[cil]; select_player=owner; ochrana=mgochrana(m->vlastnosti[VLS_OHEN+zivel]); vybrana_zbran=-1; mob_hit(m,(min+rnd(max-min))*ochrana/100); } else if(cil>0) { THUMAN *h; cil--; h=&postavy[cil]; ochrana=mgochrana(h->vlastnosti[VLS_OHEN+zivel]); player_hit(h,(min+rnd(max-min))*ochrana/100,0); bott_draw(0); } } void set_flag(int num,int cil,int flag,int what) { if (cil>0) { cil--; if (what) { postavy[cil].stare_vls[VLS_KOUZLA]|=flag; _flag_map[num]|=flag; } else { postavy[cil].stare_vls[VLS_KOUZLA]&=~flag; _flag_map[num]&=~flag; } zneplatnit_block(cil+H_CHARS); prepocitat_postavu(postavy+cil); } if (cil<0) { cil=-cil-1; if (what) { mobs[cil].vlastnosti[VLS_KOUZLA]|=flag; _flag_map[num]|=flag; } else { mobs[cil].vlastnosti[VLS_KOUZLA]&=~flag; _flag_map[num]&=~flag; } } } void spell_automap(int kolik,int cil) { int x1,y1; int xx,yy; int i,layer; THUMAN *p; if (cil<=0) return; cil--; p=&postavy[cil]; x1=map_coord[p->sektor].x; y1=map_coord[p->sektor].y; layer=map_coord[p->sektor].layer; for(i=1;isektor; if (map_coord[from_sect].flags & MC_NOSUMMON) { char *s; s=(char *)alloca(strlen(texty[87])+30); sprintf(s,texty[87],p->jmeno); bott_disp_text(s); return; } p->sektor=postavy[owner].sektor; kolik--; for(i=0;igroupnum && postavy[i].sektor==from_sect) { postavy[i].sektor=viewsector; kolik--; } for(i=0;isektor=viewsector; kolik--; } add_spectxtr(viewsector,H_TELEP_PCX,14,1,0); auto_group(); for(i=0;ijmeno); bott_disp_text(s); } bott_draw(0); build_player_map(); } void spell_teleport(int cil,int owner, int teleport_target) { if (teleport_target==-1) { int sektor; int dir; int um; if (cil>0) {sektor=postavy[cil-1].sektor;dir=postavy[cil-1].direction;} else if (cil<0) {sektor=mobs[-cil-1].sector;dir=mobs[-cil-1].dir;} if (owner>=0) um=postavy[owner].vlastnosti[VLS_SMAGIE]; teleport_target=calculatePhaseDoor(sektor,dir,um); } if (map_coord[teleport_target].flags & MC_NOSUMMON) { if (owner>=0) bott_disp_text(texty[88]); return; } if (cil>0) { if (mob_map[teleport_target]) { if (owner>=0) bott_disp_text(texty[85]); return; } destroy_player_map(); cil--; postavy_teleport_effect(teleport_target,postavy[cil].direction,1<=0) zmen_skupinu(postavy+owner); } else if (cil<0) { if (map_coord[teleport_target].flags & MC_PLAYER) { if (owner>=0) bott_disp_text(texty[85]); return; } cil=-cil-1; play_sample_at_sector(H_SND_TELEPOUT,viewsector,mobs[cil].sector,0,0); add_spectxtr(mobs[cil].sector,H_TELEP_PCX,14,1,0); mobs[cil].sector=teleport_target; play_sample_at_sector(H_SND_TELEPOUT,viewsector,teleport_target,0,0); add_spectxtr(teleport_target,H_TELEP_PCX,14,1,0); mobs[cil].next=0; refresh_mob_map(); } //schovej_mysku(); } void spell_teleport_sector(int cil,int owner) { if (cil<0) { if (owner>=0) bott_disp_text(texty[85]); return; } if (cil>0) { cil--; if (TelepLocation.map) { destroy_player_map(); if (stricmp(TelepLocation.map,level_fname)!=0) { int sector=postavy[cil].sektor; int i; if (cil!=owner) return; postavy_teleport_effect(0,0,0,1); strncpy(loadlevel.name,TelepLocation.map,12); loadlevel.name[12]=0; loadlevel.start_pos=TelepLocation.sector; loadlevel.dir=TelepLocation.dir; send_message(E_CLOSE_MAP); save_map=1; for(i=0;i=0) zmen_skupinu(postavy+owner); } } else { int sector=postavy[cil].sektor; int dir=postavy[cil].direction; int x=map_coord[sector].x; int y=map_coord[sector].y; int stpx=0,stpy=0,diffx=0,diffy=0; switch (dir) { case 0: stpy=-1;diffx=1;break; case 1: stpx=1;diffy=1;break; case 2: stpy=1;diffx=-1;break; case 3: stpx=-1;diffy=-1;break; }; { int newx=x+TelepLocation.loc_x*stpx+TelepLocation.loc_y*diffx; int newy=y+TelepLocation.loc_x*stpx+TelepLocation.loc_y*diffy; int i; int dist; int nearest=0; int nearestdst=0x7FFFFFFF; for (i=1;i=0) bott_disp_text(texty[88]); return; } destroy_player_map(); postavy_teleport_effect(sector,postavy[cil].direction,1<=0) zmen_skupinu(postavy+owner); } } } static void spell_summon(int cil) { short sector,i,rn,rno,slc; char stdir,p; if (cil>0) sector=postavy[cil-1].sektor; if (cil<0) sector=mobs[-cil-1].sector; for(i=0;ivlajky & MOB_LIVE && ~m->vlajky & MOB_RELOAD) break; } if (i==MAX_MOBS) return; slc=i; rno=rn=rnd(256)+1; do { for(i=0;istay_strategy & (MOB_WATCH|MOB_WALK)) == (MOB_WATCH|MOB_WALK) && (m->vlajky & MOB_LIVE) && (~m->vlajky & MOB_PASSABLE) && (~m->vlajky & MOB_MOBILE)) { rn--;if (!rn) break; } } } while (i==MAX_MOBS && rn!=rno); if (i==MAX_MOBS) return; memcpy(mobs+slc,mobs+i,sizeof(TMOB)); p=map_coord[sector].flags & MC_PLAYER; if (!p) { int m; m=mob_map[sector]-1; p=mobs[m].stay_strategy & MOB_BIG || mobs[m].next; } if (p) { int i; stdir=rnd(4); for(i=0;i<4;i++,stdir=stdir+1&3) if (!mob_check_next_sector(sector,stdir,mobs[slc].stay_strategy,0)) break; if (i==4) { mobs[slc].vlajky&=~MOB_LIVE; return; } sector=map_sectors[sector].step_next[stdir]; } mobs[slc].sector=sector; if (cil>0) mobs[slc].dir=postavy[cil-1].direction+2&3; if (cil<0) mobs[slc].dir=mobs[-cil-1].dir; refresh_mob_map(); } static void spell_manabat(int cil) { if (cil>0) { cil--; if (postavy[cil].mana_battery>postavy[cil].mana) postavy[cil].mana_battery=postavy[cil].mana; else postavy[cil].mana=postavy[cil].mana_battery; } } static void spell_vahy_osudu(int zivel,char povaha) { int i; int min; THUMAN *h; TMOB *m; min=32767; for(i=0,h=postavy;iused && h->lives && min>h->lives) min=h->lives; for(i=0,m=mobs;ivlajky & MOB_LIVE && m->vlajky & MOB_IN_BATTLE && m->liveslives; for(i=0,h=postavy;iused && h->lives) { int obr=mgochrana(h->vlastnosti[VLS_OHEN+zivel]); if (!povaha || rnd(100)<=obr) { h->lives=min; display_spell_in_icone(H_SPELLDEF,1<vlajky & MOB_LIVE && m->vlajky & MOB_IN_BATTLE && m->livesvlastnosti[VLS_OHEN+zivel]); if (!povaha || rnd(100)<=obr) m->lives=min; } bott_draw(1); } static void spell_open_teleport(int cil, int owner) { int sector; int dir; if (cil<0) {sector=mobs[-cil-1].sector;dir=mobs[-cil-1].dir;} else if (cil>0) {sector=postavy[cil-1].sektor;dir=postavy[cil-1].direction;} else return; if (map_sectors[sector].step_next[dir] && (~map_sides[sector*4+dir].flags & SD_THING_IMPS)) sector=map_sectors[sector].step_next[dir]; if (map_coord[sector].flags & MC_NOSUMMON) { if (owner>=0) bott_disp_text(texty[88]); return; } if (mob_map[sector]) { if (owner>=0) bott_disp_text(texty[85]); return; } if (map_sectors[sector].sector_type>=S_USERTELEPORT && map_sectors[sector].sector_type<=S_USERTELEPORT_END) { int i; int otherside; map_sectors[sector].sector_type-=S_USERTELEPORT ; otherside=map_sectors[sector].sector_tag; for (i=0;i<4;i++) {map_sides[sector*4+i].flags&=~SD_SEC_VIS;map_sides[sector*4+i].sec_anim=0;map_sides[sector*4+i].sec=0;} map_sectors[sector].sector_tag=0; add_spectxtr(sector,H_TELEP_PCX,14,1,0); play_sample_at_sector(H_SND_TELEPOUT,viewsector,sector,0,0); if (otherside!=sector && otherside) { map_sectors[otherside].sector_type-=S_USERTELEPORT ; for (i=0;i<4;i++) {map_sides[otherside*4+i].flags&=~SD_SEC_VIS;map_sides[otherside*4+i].sec_anim=0;map_sides[otherside*4+i].sec=0;} map_sectors[otherside].sector_tag=0; add_spectxtr(otherside,H_TELEP_PCX,14,1,0); play_sample_at_sector(H_SND_TELEPOUT,viewsector,otherside,0,0); } } else { int type=map_sectors[sector].sector_type; int i; char allowed=1; if (type!=S_NORMAL && (type=S_VODA)) allowed=0; if (allowed && map_sectors[sector].sector_tag!=0) allowed=0; if (allowed) for (i=0;i<4;i++) if (map_sides[sector*4+i].sec) allowed=0; if (allowed) { TSTENA *st,*stt; int templateSect=0; int i,j; for (i=0;templateSect==0 && i=0) bott_disp_text(texty[85]); return; } map_sectors[sector].sector_type+=S_USERTELEPORT; st=map_sides+4*sector; stt=map_sides+4*templateSect; for (i=0;i<4;i++) { st->flags|=SD_SEC_VIS|SD_SEC_ANIM; st->sec_anim=stt->sec_anim; st->sec=stt->sec; st++; } for (i=0;i=S_USERTELEPORT && map_sectors[i].sector_type<=S_USERTELEPORT_END) if (map_sectors[i].sector_tag==i) break; if (i!=mapsize) { map_sectors[sector].sector_tag=i; map_sectors[sector].side_tag=map_sectors[i].side_tag; map_sectors[i].sector_tag=sector; map_sectors[i].side_tag=(dir+2)&3; } else { map_sectors[sector].sector_tag=sector; map_sectors[sector].side_tag=(dir+2)&3; } add_spectxtr(sector,H_TELEP_PCX,14,1,0); play_sample_at_sector(H_SND_TELEPOUT,viewsector,sector,0,0); } else if (owner>=0) bott_disp_text(texty[85]); } } static void spell_rychlost(int num,int cil) { short *c; if (cil>0) c=postavy[cil-1].vlastnosti; else c=mobs[-cil-1].vlastnosti; if (c[VLS_POHYB]<15) zmen_vlastnost(num,cil,VLS_POHYB,15-c[VLS_POHYB]); } void spell_special(int num,TKOUZLO *spl,int spc) { switch (spc) { case SP_AUTOMAP4:spell_automap(4,spl->cil);break; case SP_AUTOMAP8:spell_automap(8,spl->cil);break; case SP_AUTOMAP15:spell_automap(15,spl->cil);break; case SP_PRIPOJENI1:spell_pripojeni(1,spl->cil,spl->owner);break; case SP_PRIPOJENI3:spell_pripojeni(3,spl->cil,spl->owner);break; case SP_PRIPOJENIA:spell_pripojenia(spl->owner);break; case SP_CHVENI:chveni(100);break; case SP_DEFAULT_EFFEKT: if (spl->cil>0)display_spell_in_icone(H_SPELLDEF,1<<(spl->cil-1));break; case SP_TRUE_SEEING: true_seeing=1;_flag_map[num]|=FLG_TRUESEEING;break; case SP_SCORE:show_lives=1;_flag_map[num]|=FLG_SCORE;break; case SP_HALUCINACE:set_halucination=1;_flag_map[num]|=FLG_HALUCINACE; hal_sector=rnd(mapsize-1)+1;hal_dir=rnd(4); break; case SP_TELEPORT:if (hod_na_uspech(spl->cil,spl)) spell_teleport(spl->cil,spl->owner,spl->teleport_target);break; case SP_PHASEDOOR:if (hod_na_uspech(spl->cil,spl)) spell_teleport(spl->cil,spl->owner,-1);break; case SP_SUMMON: spell_summon(spl->cil); case SP_HLUBINA1:if (hlubina_level==0) hlubina_level=1;_flag_map[num]|=FLG_HLUBINA1; break; case SP_HLUBINA2:hlubina_level=2;_flag_map[num]|=FLG_HLUBINA2; break; case SP_MANABAT:spell_manabat(spl->cil); break; case SP_VAHY:spell_vahy_osudu(spl->pc,spl->povaha);break; case SP_RYCHLOST:spell_rychlost(num,spl->cil);break; case SP_DEMON1:spell_demon(num,spl,spl->cil,0);break; case SP_DEMON2:spell_demon(num,spl,spl->cil,1);break; case SP_DEMON3:spell_demon(num,spl,spl->cil,2);break; case SP_VZPLANUTI1:spell_vzplanuti(spl->cil,1,rand_value,1,spl->pc);break; case SP_VZPLANUTI2:spell_vzplanuti(spl->cil,5,rand_value,1,spl->pc);break; case SP_VZPLANUTI3:spell_vzplanuti(spl->cil,5,rand_value,0,spl->pc);break; case SP_TELEPORT_SECT: if (hod_na_uspech(spl->cil,spl)) spell_teleport_sector(spl->cil,spl->owner);break; case SP_OPEN_TELEPORT: spell_open_teleport(spl->cil,spl->owner);break; } } void spell_drain(TKOUZLO *p,int cil,int min,int max) { int drw; int sect,dir; drw=min+rnd(max-min); if (cil>0) { cil--; sect=postavy[cil].sektor; dir=postavy[cil].direction; if (map_sides[(sect<<2)+dir].flags & SD_PLAY_IMPS) { postavy[cil].lives-=drw; player_check_death(&postavy[cil],0); } else { int chaos;int potvora,ochrana; TMOB *m; potvora=vyber_potvoru(sect,dir,&chaos); if (potvora==-1) return; m=mobs+potvora; ochrana=mgochrana(m->vlastnosti[VLS_OHEN+p->pc]); drw=ochrana*drw/100; vybrana_zbran=-1; mob_hit(m,drw); battle=1; postavy[cil].lives+=drw/4; if (postavy[cil].lives>postavy[cil].vlastnosti[VLS_MAXHIT]) postavy[cil].lives=postavy[cil].vlastnosti[VLS_MAXHIT]; } } } static void set_kondice_mana(int kolik,TKOUZLO *p,int what,char clip) { int cil=p->cil; if (cil>0) { THUMAN *p; cil--; p=postavy+cil; if (what==S_kondice) { p->kondice+=kolik; if (p->kondice<0) p->kondice=0; if (clip) if (p->kondice>p->vlastnosti[VLS_KONDIC]) p->kondice=p->vlastnosti[VLS_KONDIC]; } if (what==S_mana) { p->mana+=kolik; if (p->mana<0) p->mana=0; if (clip) if (p->mana>p->vlastnosti[VLS_MAXMANA]) p->mana=p->vlastnosti[VLS_MAXMANA]; } } } static void spell_mana_steal(int kolik,int cil,int owner) { if (cil>0) { THUMAN *h=postavy+cil-1; h->mana-=h->vlastnosti[VLS_MAXMANA]*kolik/100; if (h->mana<0) h->mana=0; } if (cil<0) { if (owner>=0) { THUMAN *h=postavy+owner; if (h->manavlastnosti[VLS_MAXMANA]) h->mana+=h->vlastnosti[VLS_MAXMANA]*kolik/100; } } } static void calc_rand_value(int val1,int val2) { rand_value=val1+rnd(val2-val1+1); } void call_spell(int i) { TKOUZLO *p; char *c; int z; char ext=0; int cil; SEND_LOG("(SPELLS) Calculating spell ID: %d",i,0); p=spell_table[i]; if (p==NULL) return; cil=p->cil; if (cil>0) { cil--; if (postavy[cil].stare_vls[VLS_KOUZLA] & SPL_DEMON && ~_flag_map[i] & SPL_DEMON && p->backfire==0) { p->wait=1; return; } } if (p->delay) return; if (p->wait) return; c=(char *)ablock(H_KOUZLA); c+=p->start; twins=0; do switch (twins=twins==3?0:twins,*c++) { case S_zivel:p->pc=GET_WORD(c); if (p->owner>=0 && !GlobEvent(MAGLOB_ONFIREMAGIC+p->pc,postavy[p->owner].sektor,postavy[p->owner].direction)) { spell_end(i,p->cil,p->owner); return; } break; case S_hpnorm_min:parm1=GET_WORD(c);twins|=1;if (twins==3) spell_hit(p->cil,parm1,parm2,p->owner);break; case S_hpnorm_max:parm2=GET_WORD(c);twins|=2;if (twins==3) spell_hit(p->cil,parm1,parm2,p->owner);break; case S_hpzivl_min:parm1=GET_WORD(c);twins|=1;if (twins==3) spell_hit_zivel(p->cil,parm1,parm2,p->owner,p->pc);break; case S_hpzivl_max:parm2=GET_WORD(c);twins|=2;if (twins==3) spell_hit_zivel(p->cil,parm1,parm2,p->owner,p->pc);break; case S_vlastnost:parm1=GET_WORD(c);twins|=1; if (twins==3) if (hod_na_uspech(p->cil,p)) zmen_vlastnost(i,p->cil,parm1,parm2);break; case S_vls_kolik:parm2=GET_WORD(c);twins|=2; if (twins==3) if (hod_na_uspech(p->cil,p)) zmen_vlastnost(i,p->cil,parm1,parm2);break; case S_trvani:p->delay=GET_WORD(c);p->wait=0;ext=1;break; case S_throw_item:z=GET_WORD(c);spell_throw(p->cil,z);break; case S_create_item:z=GET_WORD(c);spell_create(p->cil,z);break; case S_create_weapon:z=GET_WORD(c);spell_create_weapon(p->cil,z);break; case S_animace:if (p->owner>=0 && !p->traceon)spell_anim(c);c=strchr(c,0);c++;break; case S_zvuk:if (p->owner>=0 && !p->traceon)spell_sound(c);c=strchr(c,0);c++;break; case S_wait:p->wait=GET_WORD(c);if (p->owner>=0) ext=1;break; case 0xff:spell_end(i,p->cil,p->owner);return; case S_pvls:parm2=GET_WORD(c);twins|=2; if (twins==3) if (hod_na_uspech(p->cil,p)) zmen_vlastnost_percent(i,p->cil,parm1,parm2);break; case S_set:parm2=GET_WORD(c);if (hod_na_uspech(p->cil,p)) set_flag(i,p->cil,parm2,1);break; case S_reset:parm2=GET_WORD(c);if (hod_na_uspech(p->cil,p)) set_flag(i,p->cil,parm2,0);break; case S_special:parm2=GET_WORD(c);spell_special(i,p,parm2);break; case S_drain_min:parm1=GET_WORD(c);twins|=1;if (twins==3) spell_drain(p,p->cil,parm1,parm2);break; case S_drain_max:parm2=GET_WORD(c);twins|=2;if (twins==3) spell_drain(p,p->cil,parm1,parm2);break; case S_rand_min:parm1=GET_WORD(c);twins|=1;if (twins==3) calc_rand_value(parm1,parm2);break; case S_rand_max:parm2=GET_WORD(c);twins|=2;if (twins==3) calc_rand_value(parm1,parm2);break; case S_mana:parm1=GET_WORD(c);set_kondice_mana(parm1,p,S_mana,0);break; case S_kondice:parm1=GET_WORD(c);set_kondice_mana(parm1,p,S_kondice,1);break; case S_mana_clip:parm1=GET_WORD(c);set_kondice_mana(parm1,p,S_mana,1);break; case S_mana_steal:parm1=GET_WORD(c);spell_mana_steal(parm1,p->cil,p->owner);break; case S_location_sector: parm1=GET_WORD(c); TelepLocation.sector=parm1; TelepLocation.loc_x=0; TelepLocation.loc_y=0; break; case S_location_map: TelepLocation.map=c;c=strchr(c,0);c++;break; case S_location_dir: parm1=GET_WORD(c);TelepLocation.dir=parm1;break; case S_location_x: TelepLocation.loc_x=GET_WORD(c);TelepLocation.map=0;break; case S_location_y: TelepLocation.loc_y=GET_WORD(c);TelepLocation.map=0;break; default: { char *d="Chyba v popisu kouzel: Program narazil na neznamou instrukci %d (%02X) pri zpracovani kouzla s cislem %d. Kouzlo bylo ukon‡eno"; c=alloca(strlen(d)+20); sprintf(c,d,*(c-1),*(c-1),p->num); bott_disp_text(c); spell_end(i,p->cil,p->owner); return; } } while(!ext); p->start=c-(char *)ablock(H_KOUZLA); } int add_spell(int num,int cil,int owner,char noanim) { int i,nl=-1; TKOUZLO *p; TKOUZLO *q; int accnum; char time_acc=1; SEND_LOG("(SPELLS) Casting spell number %d",num,0); alock(H_KOUZLA); q=(TKOUZLO *)ablock(H_KOUZLA)+num; accnum=q->accnum; if (accnum<0) { time_acc=0; accnum=abs(accnum); } if (!accnum) accnum=-1; for(i=0;iaccnum)!=accnum || spell_table[i]->cil!=cil);i++) if (spell_table[i]==NULL) nl=i; if (i==MAX_SPELLS) i=nl; if (i==-1) { SEND_LOG("(ERROR) Too many spells in game!",0,0); return -1; } if (spell_table[i]!=NULL) { if (!time_acc) return -1; spell_end(i,spell_table[i]->cil,spell_table[i]->owner); } SEND_LOG("(SPELLS) Current spell number %d was assigned to ID number : %d",num,i); p=New(TKOUZLO); vls_table[i]=NewArr(short,24); memset(vls_table[i],0,2*24); memcpy(p,q,sizeof(TKOUZLO)); p->cil=cil; p->num=num; p->owner=owner; p->traceon=noanim; p->teleport_target=teleport_target; if (cil>0) p->backfire=(postavy[cil-1].stare_vls[VLS_KOUZLA] & SPL_DEMON)!=0; aunlock(H_KOUZLA); spell_table[i]=p; if (cil>0 && owner>=0) postavy[cil-1].spell=1; call_spell(i); return i; } void kouzla_kola(EVENT_MSG *msg,void **unused) { unused; if (msg->msg==E_KOUZLO_KOLO) { int i; for(i=0;idelay) { neco_v_pohybu=1; if (!(--spell_table[i]->delay)) call_spell(i); } } } void kouzla_anm(EVENT_MSG *msg,void **unused) { unused; if (msg->msg==E_KOUZLO_ANM) { int i; for(i=0;iwait) { neco_v_pohybu=1; if (!(--spell_table[i]->wait)) call_spell(i); } } } char add_group_spell(int num,int sector,int owner,int mode,char noanim) { char c=1; if (mob_map[sector]) { int m; m=mob_map[sector]; add_spell(num,-m,owner,noanim); c=0; if (mobs[m-1].next) add_spell(num,-mobs[m-1].next,owner,noanim); } if (map_coord[sector].flags & MC_PLAYER) { int i,j; if (mode==C_nahodna_postava) { i=0;j=rnd(POCET_POSTAV)+1; do { if (i>=POCET_POSTAV) i=0; if (postavy[i].sektor==sector) j--; if (j) i++; } while (j); add_spell(num,i+1,owner,noanim); } else { for(i=0;icil==C_kouzelnik) return 1; if (k->cil==C_postava) return 2; if (k->cil==C_mrtva_postava) return 3; if (k->cil==C_postava_jinde) return 4; return 0; } static word last_sector; static char get_valid_sector(word sector) { last_sector=sector; return 1; } void cast(int num,THUMAN *p,int owner, char backfire) { int i,um,cil,num2; TKOUZLO *k; if (num>511) { cil=num>>9; num2=num & 511; } else { cil=0; num2=num; } SEND_LOG("(SPELLS) Cast num %d cil %d",num2,cil); k=((TKOUZLO *)ablock(H_KOUZLA))+num2; SEND_LOG("(SPELLS) Cast spell name %s",k->spellname,0); if (cil>0 && k->cil!=C_postava_jinde) { THUMAN *h1=postavy+cil-1; char s[256]; if ((abs(map_coord[h1->sektor].x-map_coord[p->sektor].x)>5) || (abs(map_coord[h1->sektor].y-map_coord[p->sektor].y)>5) ) { sprintf(s,texty[37+(h1->female==1)],h1->jmeno,p->jmeno); bott_disp_text(s); return; } } if (battle && k->traceon & 1 && trace_path(p->sektor,p->direction)==-255) return; if (!backfire && p->manamge) return; if (p->vlastnosti[VLS_KOUZLA] & SPL_INVIS) { p->stare_vls[VLS_KOUZLA]&=~SPL_INVIS; prepocitat_postavu(p); build_all_players(); } if (!backfire && (um=p->vlastnosti[VLS_SMAGIE])um) { int per1,per2; if (um*2um) return; per1=(um-k->um/2)*128/k->um; per2=rnd(64); if ((per1/2+32)backfire || (game_extras & EX_RANDOM_BACKFIRES)!=0)) { p->mana-=k->mge; if ((game_extras & EX_RANDOM_BACKFIRES)!=0) { labyrinth_find_path(p->sektor,65535,SD_PLAY_IMPS,get_valid_sector,NULL); teleport_target=last_sector; cast(rand()*105/RAND_MAX+(cil*512),p,p-postavy,1); return; } cast(k->backfire+(cil<<9),p,owner,1); return; } if(per1mana-=k->mge/2; return; } per1=(64-per1)/2; per2=rnd(64); if(per1>per2) p->stare_vls[VLS_SMAGIE]++; } if (!GlobEvent(MAGLOB_BEFOREMAGIC,p->sektor,p->direction)) return; if (!GlobEvents(MAGLOB_ONSPELLID1,MAGLOB_ONSPELLID9,p->sektor,p->direction,num2)) return; if (cil && (k->cil==C_postava || k->cil==C_mrtva_postava || k->cil==C_postava_jinde)) i=add_spell(num2,cil,owner,0); else { if (k->cil==C_policko) if (add_group_spell(num2,p->sektor,owner,C_policko,0)) goto end; if (k->cil==C_kouzelnik) add_spell(num2,p-postavy+1,owner,0); if (k->cil==C_policko_pred || k->cil==C_nahodna_postava) { int s; s=p->sektor; if (!(map_sides[(s<<2)+p->direction].flags & SD_PLAY_IMPS) && !backfire) s=map_sectors[s].step_next[p->direction]; if (add_group_spell(num2,s,owner,k->cil,0)) goto end; } } if (!backfire) p->mana-=k->mge; p->exp+=k->mge; check_player_new_level(p); if (p->mana>p->mana_battery) { if (p->mana_battery>=0)p->mana=p->mana_battery; else SEND_LOG("(ERROR) Mana battery error on character %d",p-postavy,0); p->mana_battery=32767; } end: GlobEvent(MAGLOB_AFTERMAGIC,p->sektor,p->direction); } void mob_cast(int num,TMOB *m,int mob_num) { TKOUZLO *k; SEND_LOG("(SPELLS) Enemy tries to cast the spell (mob: %d, spell: %d",mob_num,num); k=((TKOUZLO *)ablock(H_KOUZLA))+num; switch (k->cil) { case C_postava: case C_kouzelnik:add_spell(num,-(mob_num+1),-1,1);break; case C_policko:add_group_spell(num,m->sector,-1,C_policko,1);break; case C_policko_pred: case C_nahodna_postava: { int s; s=m->sector; if (!(map_sides[(s<<2)+m->dir].flags & SD_PLAY_IMPS)) s=map_sectors[s].step_next[m->dir]; add_group_spell(num,s,-1,k->cil,1); } break; } } static int calculatePhaseDoor(int sector, int dir, int um) { int x=map_coord[sector].x; int y=map_coord[sector].y; int stpx=0,stpy=0,diffx=0,diffy=0; switch (dir) { case 0: stpy=-1;diffx=1;break; case 1: stpx=1;diffy=1;break; case 2: stpy=1;diffx=1;break; case 3: stpx=-1;diffy=1;break; }; { int dist=1+rand()*(um/4)/RAND_MAX; int difs=rand()*2*dist/RAND_MAX-dist; int newx=x+dist*stpx+difs*diffx; int newy=y+dist*stpy+difs*diffy; int i; int nearest=0; int nearestdst=0x7FFFFFFF; for (i=1;isektor,h->direction,h->vlastnosti[VLS_SMAGIE]); } switch (k->cil) { case C_nahodna_postava: case C_postava: case C_kouzelnik:if (postavy[postava].lives) add_spell(num,postava+1,postava,noanim);break; case C_mrtva_postava:if (!postavy[postava].lives) add_spell(num,postava+1,postava,noanim);break; case C_policko:add_group_spell(num,sector,postava,k->cil,noanim);break; case C_policko_pred: { int s; s=sector; if (~map_sides[(s<<2)+h->direction].flags & SD_PLAY_IMPS) s=map_sectors[s].step_next[h->direction]; add_group_spell(num,s,postava,k->cil,noanim); } break; case C_jiny_cil:if (victim!=NULL) add_spell(num,-(victim-mobs+1),postava,noanim);break; } } void area_cast(int num,int sector,int owner,char noanim) { SEND_LOG("(SPELLS) Area casts the spell (sector: %d, spell: %d)",sector,num); add_group_spell(num,sector,owner,C_policko,noanim); } void kouzla_init() { SEND_LOG("(SPELLS) Init...",0,0); send_message(E_ADD,E_KOUZLO_ANM,kouzla_anm); send_message(E_ADD,E_KOUZLO_KOLO,kouzla_kola); memset(spell_table,0,sizeof(spell_table)); memset(vls_table,0,sizeof(vls_table)); memset(_flag_map,0,sizeof(_flag_map)); true_seeing=0; hlubina_level=0; show_lives=0; set_halucination=0; } void reinit_kouzla_full() { int i; SEND_LOG("(SPELLS) Reinit...",0,0); for(i=0;iwait) { spell_table[i]->wait=0;call_spell(i); a=1; } if (spell_table[i]->cil<0) { spell_table[i]->delay=0;call_spell(i); a=1; } } } while(a); } int save_spells(FILE *f) { char res=0; int i,s; SEND_LOG("(SPELLS) Saving spell table...",0,0); for(i=0,s=0;iwait) { spell_table[i]->wait=0;call_spell(i); a=1; } if (spell_table[i]->cil>0) { spell_table[i]->delay=0;call_spell(i); a=1; } } } while(a); SEND_LOG("(WIZARD) Unaffect... done",0,0); } void unaffect_demon(int cil) { int i; TKOUZLO *spl; char a; cil++; SEND_LOG("(SPELLS) Demon returns to astral spaces...",0,0); for(i=0;spl=spell_table[i],icil==cil) { while (spell_table[i]!=NULL) { if (spell_table[i]->wait) { spell_table[i]->wait=0;call_spell(i); a=1; } if (spell_table[i]->cil>0) { spell_table[i]->delay=0;call_spell(i); a=1; } } } }