// событие начала движения объекта в бою в режиме реального времени void evt_bmv_act(obj *o,evt *e,lnk *l) { double dr,t=0.0,tx=l->tx,ty=l->ty; int mode=l->n; if(o->pl->bmode==1) { evt_bm_act(o,e,l); return; } // пошаговый режим free_lnk(NULL,l); e->l=NULL; del_evt(o,e); free_evt(o,e); o->s.me=NULL; dr=(GTIME-o->s.ct)*o->s.v; o->s.cx+=o->s.tx*dr; o->s.cy+=o->s.ty*dr; o->s.v=o->dev.pwr[1]/(1.0*o->dev.cm); if(mode!=0 && (tx!=0.0 || ty!=0.0)) // движение в указанную точку { tx-=o->s.cx; ty-=o->s.cy; dr=sqrt(tx*tx+ty*ty); t=dr/o->s.v; dr=1.0/dr; tx*=dr; ty*=dr; l=get_lnk(); l->tx=0.0; l->ty=0.0; l->n=0; e=get_evt(); evt_bmv_set(e,o,NULL,l,t); ins_evt(o,e); o->s.me=e; } else { dr=tx*tx+ty*ty; if(dr>1.001) { dr=1.0/sqrt(dr); tx*=dr; ty*=dr; } } o->s.tx=tx; o->s.ty=ty; if(tx!=0.0 || ty!=0.0) o->s.ct=GTIME; locs_send_mv(o); }
// событие смерти объекта в бою // объект выкидывается из боя // если объект управляемый, то еще телепортируется в портал // если не управляемый, то уничтожается void bkill_PERS_rt(obj *o,evt *e,lnk *l) { double x,y,dr; obj *po; lnk *ml; evt *me; // останавливаю корабль if(o->s.me!=NULL) // событие уже есть { me=o->s.me; me->t=GTIME; me->l->tx=0.0; me->l->ty=0.0; me->l->n=0; move_evt(o,me); } else // события нет, создаю { ml=get_lnk(); ml->tx=0.0; ml->ty=0.0; ml->n=0; me=get_evt(); evt_func_set[E_bmv](me,o,NULL,ml,0.0); ins_evt(o,me); o->s.me=me; } // loc_obj_unreg(o); // убираю корабль с карты po=o->port; ml=get_lnk(); ml->o=po; me=get_evt(); evt_func_set[E_prich_user](me,o,NULL,ml,0.1); ins_evt(o,me); /* dr=(GTIME-po->s.ct)*po->s.v; x=po->s.cx+po->s.tx*dr; y=po->s.cy+po->s.ty*dr; if(1.0*rand()/RAND_MAX>0.5) dr=-1.0; else dr=1.0; o->s.cx=x+po->s.xs*dr*(0.55+0.45*rand()/RAND_MAX); if(1.0*rand()/RAND_MAX>0.5) dr=-1.0; else dr=1.0; o->s.cy=y+po->s.ys*dr*(0.55+0.45*rand()/RAND_MAX); o->s.ct=GTIME; o->s.tx=0.0; o->s.ty=0.0; o->s.v=0.0; loc_obj_reg(o,0); // cmd_send_iam(o); // отправляю список объектов видимых локаций locs_send_obj(o); */ }
// выделяет ссылку на зависимое событие и добавляет ее в список // зависимых событий lnk *evt_lnk_ins(int tag,obj *o,evt *e,lnk *l2) { lnk *l1; if(tag>=ELST_NUM) return NULL; l1=get_lnk(); l1->tag=tag; l1->o=o; l1->e=e; l1->l=l2; l1->prev=NULL; l1->next=o->elst[tag]; if(o->elst[tag]!=NULL) o->elst[tag]->prev=l1; o->elst[tag]=l1; return l1; }
void spark_act_btl(obj *o,evt *e,lnk *l) { obj *bo=o->pl; obj *co,*eo=NULL; obj *wo1=NULL,*wo2=NULL; evt *me; double minr=0,dr,dx,dy,cx,cy,r; double wt1,wt2; // текущее время подготовки оружия к выстрелу double dt,ct; int n; char *b; lnk *nl; // del_evt(o,e); free_evt(o,e); dr=(GTIME-o->s.ct)*o->s.v; o->s.cx+=o->s.tx*dr; o->s.cy+=o->s.ty*dr; o->s.ct=GTIME; o->s.tx=0.0; o->s.ty=0.0; cx=o->s.cx; cy=o->s.cy; co=bo->bo; while(co!=NULL) { if(co->bside!=0 && co->bside!=o->bside) // противник найден { dr=(GTIME-co->s.ct)*co->s.v; dx=co->s.cx+co->s.tx*dr-cx; dy=co->s.cy+co->s.ty*dr-cy; dr=1.0/(dx*dx+dy*dy); if(dr>minr) { minr=dr; eo=co; } } co=co->next; } if(eo==NULL) // врагов нету, выхожу из боя { obj_ch_parent(o,o->pl->pl); me=get_evt(); evt_spark_set(me,o,NULL,NULL,1.0); ins_evt(o,me); return; } dr=(GTIME-eo->s.ct)*eo->s.v; minr=sqrt(minr); dx=eo->s.cx+eo->s.tx*dr-cx; dy=eo->s.cy+eo->s.ty*dr-cy; r=1.0/minr; dx*=minr; dy*=minr; // найдем параметры оружия co=o->bo; while(co!=NULL) { if(co->tag==T_WPN) if(co->s.img==1) wo1=co; else wo2=co; co=co->next; } wt1=GTIME-wo1->s.ct; wt2=GTIME-wo2->s.ct; if(wt1>=wo1->dev.pwr[2] && wo1->s.me==NULL) { // формирую команду выстрела по цели nl=get_lnk(); nl->st[0]=0; nl->o=eo; nl->tx=0.0; nl->ty=0.0; me=get_evt(); evt_buse_set(me,wo1,NULL,nl,0.0); ins_evt(wo1,me); wt1=0.0; } wt1=wo1->dev.pwr[2]-wt1; // время до следующего выстрела if(r<=wo2->dev.pwr[0] && wt2>=wo2->dev.pwr[2] && wo2->s.me==NULL) { // формирую команду выстрела по цели nl=get_lnk(); nl->st[0]=0; nl->o=eo; nl->tx=0.0; nl->ty=0.0; me=get_evt(); evt_buse_set(me,wo2,NULL,nl,0.0); ins_evt(wo2,me); dt=wo2->dev.pwr[2]; } else dt=wo2->dev.pwr[2]-wt2; if(r>wo2->dev.pwr[0]) // подсчитаем время подлета { dt=(r-wo2->dev.pwr[0])/o->s.v; // формирую команду подлета к цели o->s.ct=GTIME; o->s.tx=dx; o->s.ty=dy; } if(dt>wt1) dt=wt1; me=get_evt(); evt_spark_set(me,o,NULL,NULL,dt+1.0); ins_evt(o,me); }
// событие использования оружия в бою void buse_WPN_tb(obj *o,evt *e,lnk *l) { obj *eo=l->o,*co; obj *bo; obj *mo; double dr,r,rmin,d,ex=l->tx,ey=l->ty; double fi,rt,mx,my,tx,ty,fx,fy; float dmg[8][2],dmgsum=0.0; int i,n; char *b; lnk *ml; evt *me; free_lnk(NULL,l); e->l=NULL; del_evt(o,e); free_evt(o,e); o->s.me=NULL; mo=o->pl; while(mo->pl->tag!=T_BL) mo=mo->pl; bo=mo->pl; // проверяю готовность устройства if(o->rt==0.0) rt=o->dev.pwr[2]; else if(o->rt<bo->rt) rt=(bo->rt-o->rt)+(GTIME-bo->s.ct); else rt=GTIME-o->rt; if(rt<o->dev.pwr[2]) return; // объект не готов к использованию dr=(GTIME-mo->s.ct)*mo->s.v; mx=mo->s.cx+mo->s.tx*dr; my=mo->s.cy+mo->s.ty*dr; if(eo!=NULL) { dr=(GTIME-eo->s.ct)*eo->s.v; ex=eo->s.cx+eo->s.tx*dr; ey=eo->s.cy+eo->s.ty*dr; } // нужно стрельнуть и посмотреть куда попали // найдем направление выстрела tx=ex-mx; ty=ey-my; fi=(1.0-o->dev.pwr[1])/(0.636619772367581343+o->dev.pwr[1])*(1.0-2.0*rand()/RAND_MAX); fx=tx*cos(fi)-ty*sin(fi); fy=tx*sin(fi)+ty*cos(fi); // направление выстрела dr=fx*fx+fy*fy; dr=1.0/sqrt(dr); fx*=dr; fy*=dr; rmin=o->dev.pwr[1]*2.0; // дальность на которой повреждения 0 co=bo->bo; eo=NULL; while(co!=NULL) // пройдемся по объектам и найдем в кого попали { dr=(GTIME-co->s.ct)*co->s.v; ex=co->s.cx+co->s.tx*dr-mx; ey=co->s.cy+co->s.ty*dr-my; r=fx*ex+fy*ey; if(r>0.0 && r<rmin && co!=mo) // не очень правильно, ну да пусть будет так { r=fx*ey-fy*ex; if(r<co->s.r1) { eo=co; rmin=r; } } co=co->next; } if(eo==NULL) //никуда не попали, создадим сообщение и закончим на этом { n=snprintf(NULL,0,"<BUSE t=\"%f\" id=\"%x\" obj=\"%x\" trg=\"%f,%f\" res=\"0\" />",GTIME-bo->s.ct,mo,o,fx,fy)+1; b=mymalloc(n); snprintf(b,n,"<BUSE t=\"%f\" id=\"%x\" obj=\"%x\" trg=\"%f,%f\" res=\"0\" />",GTIME-bo->s.ct,mo,o,fx,fy); ml=get_lnk(); ml->next=bo->bo_turns; ml->prev=NULL; bo->bo_turns=ml; ml->o=mo; ml->b=b; o->rt=GTIME; return; } // подсчитаем повреждения for(i=0;i<7;i++) { dmg[i][0]=o->dev.atkp[i][0]+(o->dev.atkp[i][1]-o->dev.atkp[i][0])*rand()/RAND_MAX; } // найдем все генераторы поля dmg[7][0]=dmg[7][1]=0; ml=eo->dev.dvsl; while(ml!=NULL) { ml=get_slot_bytype(ml,'F'); if(ml!=NULL) { co=ml->o; for(i=0;i<7;i++) { dmg[i][1]=co->dev.defp[i][0]+(co->dev.defp[i][1]-co->dev.defp[i][0])*rand()/RAND_MAX; if(dmg[i][1]>dmg[i][0]) dmg[i][1]=dmg[i][0]; dmg[i][0]-=dmg[i][1]; dmg[7][0]+=dmg[i][1]; } dmg[7][1]=upd_FLD_tb(co); // состояние поля на текущий момент if(dmg[7][0]>dmg[7][1]) // заряда поля не достаточно, часть повреждений нужно вернуть { dr=(dmg[7][0]-dmg[7][1])/dmg[7][0]; for(i=0;i<7;i++) dmg[i][0]+=dmg[i][1]*dr; dmg[7][0]=dmg[7][1]; } dmgsum+=dmg[7][0]; co->dev.pwr[1]-=dmg[7][0]; if(dmg[7][0]>0.0) { n=snprintf(NULL,0,"<BFLD t=\"%f\" id=\"%x\" obj=\"%x\" dmg=\"%f\" />",GTIME-bo->s.ct,eo,co,dmg[7][0])+1; b=mymalloc(n); snprintf(b,n,"<BFLD t=\"%f\" id=\"%x\" obj=\"%x\" dmg=\"%f\" />",GTIME-bo->s.ct,eo,co,dmg[7][0]); ml=get_lnk(); ml->next=bo->bo_turns; ml->prev=NULL; bo->bo_turns=ml; ml->o=eo; ml->b=b; me=get_evt(); evt_buse_set(me,co,NULL,NULL,0.0); ins_evt(co,me); // ревизия состояния поля } } } // найдем все слои брони, в отличие от поля, броня поглощает часть повреждений, // а остальная часть идет на ее разрушение. Если состояние брони 0 то она // пропускает повреждения дальше dmg[7][0]=dmg[7][1]=0; ml=eo->dev.dvsl; while(ml!=NULL) { ml=get_slot_bytype(ml,'H'); if(ml!=NULL && ml->o->dev.chull>0.0) { co=ml->o; for(i=0;i<7;i++) { dmg[i][1]=co->dev.defp[i][0]+(co->dev.defp[i][1]-co->dev.defp[i][0])*rand()/RAND_MAX; if(dmg[i][1]>dmg[i][0]) dmg[i][1]=dmg[i][0]; dmg[i][0]-=dmg[i][1]; dmg[7][0]+=dmg[i][0]; } dmg[7][1]=co->dev.chull; // состояние брони на текущий момент if(dmg[7][0]>dmg[7][1]) { dr=(dmg[7][0]-dmg[7][1])/dmg[7][0]; for(i=0;i<7;i++) dmg[i][0]*=dr; dmg[7][0]=dmg[7][1]; } dmgsum+=dmg[7][0]; co->dev.chull-=dmg[7][0]; if(dmg[7][0]>0.0) { n=snprintf(NULL,0,"<BDMG t=\"%f\" id=\"%x\" obj=\"%x\" dmg=\"%f\" />",GTIME-bo->s.ct,eo,co,dmg[7][0])+1; b=mymalloc(n); snprintf(b,n,"<BDMG t=\"%f\" id=\"%x\" obj=\"%x\" dmg=\"%f\" />",GTIME-bo->s.ct,eo,co,dmg[7][0]); ml=get_lnk(); ml->next=bo->bo_turns; ml->prev=NULL; bo->bo_turns=ml; ml->o=eo; ml->b=b; } } } // найдем корпус корабля dmg[7][0]=dmg[7][1]=0; co=eo->dev.mysl->o; if(co->dev.chull>0.0) { for(i=0;i<7;i++) { dmg[i][1]=co->dev.defp[i][0]+(co->dev.defp[i][1]-co->dev.defp[i][0])*rand()/RAND_MAX; if(dmg[i][1]>dmg[i][0]) dmg[i][1]=dmg[i][0]; dmg[i][0]-=dmg[i][1]; dmg[7][0]+=dmg[i][0]; } dmg[7][1]=co->dev.chull; // состояние брони на текущий момент if(dmg[7][0]>dmg[7][1]) { dr=(dmg[7][0]-dmg[7][1])/dmg[7][0]; for(i=0;i<7;i++) dmg[i][0]*=dr; dmg[7][0]=dmg[7][1]; } dmgsum+=dmg[7][0]; co->dev.chull-=dmg[7][0]; if(dmg[7][0]>0.0) { n=snprintf(NULL,0,"<BDMG t=\"%f\" id=\"%x\" obj=\"%x\" dmg=\"%f\" />",GTIME-bo->s.ct,eo,co,dmg[7][0])+1; b=mymalloc(n); snprintf(b,n,"<BDMG t=\"%f\" id=\"%x\" obj=\"%x\" dmg=\"%f\" />",GTIME-bo->s.ct,eo,co,dmg[7][0]); ml=get_lnk(); ml->next=bo->bo_turns; ml->prev=NULL; bo->bo_turns=ml; ml->o=eo; ml->b=b; } } for(i=0;i<7;i++) dmgsum+=dmg[i][0]; n=snprintf(NULL,0,"<BUSE t=\"%f\" id=\"%x\" obj=\"%x\" trg=\"%f,%f\" res=\"%f\" tid=\"%x\" />",GTIME-bo->s.ct,mo,o,fx,fy,dmgsum,eo)+1; b=mymalloc(n); snprintf(b,n,"<BUSE t=\"%f\" id=\"%x\" obj=\"%x\" trg=\"%f,%f\" res=\"%f\" tid=\"%x\" />",GTIME-bo->s.ct,mo,o,fx,fy,dmgsum,eo); ml=get_lnk(); ml->next=bo->bo_turns; ml->prev=NULL; bo->bo_turns=ml; ml->o=mo; ml->b=b; // пока считаем что при состоянии корпуса корабля 0 объект умирает if(co->dev.chull<=0.0) { me=get_evt(); evt_bkill_set(me,eo,NULL,NULL,0.0); ins_evt(co,me); // убиваю объект } o->rt=GTIME; }
/* ファイルのロード */ EXPORT ERR load_file(TC *filename) { W err, i, fd; LINK l, v; F_LINK stat; F_STATE fs; /* アンロード処理 */ if (filename == NULL) { err = ER_OK; fd = ER_NOEXS; goto fin3; } /* 入力ファイルへのリンク取り出し */ err = get_lnk(filename, &l, F_NORM); if (err < ER_OK) { P(("load_file: get_lnk %d\n", err)); goto fin0; } /* 入力ファイルのオープン - 現在レコードはファイルの先頭 */ err = opn_fil(&l, F_READ | F_EXCL, NULL); if (err < ER_OK) { P(("load_file: opn_fil %d\n", err)); goto fin0; } fd = err; /* リンク数の獲得 */ err = ofl_sts(fd, NULL, &fs, NULL); if (err < ER_OK) { P(("load_file: ofl_sts %d\n", err)); goto fin1; } /* 仮身名用領域の確保 */ OBJentry = fs.f_nlink; if (OBJentry) { OBJname = calloc(OBJentry, sizeof(FNAME)); if (OBJname == NULL) { P(("load_file: calloc NULL\n")); err = ER_NOMEM; goto fin1; } } else { OBJname = NULL; } /* 全リンクの読み出し */ for (i = 0; i < OBJentry; i++) { err = fnd_lnk(fd, F_FWD, NULL, 0, NULL); if (err < ER_OK) { P(("load_file: fnd_lnk %d\n", err)); goto fin2; } err = rea_rec(fd, 0, (B *)&v, sizeof(VLINK), NULL, NULL); if (err < ER_OK) { P(("load_file: rea_rec %d\n", err)); goto fin2; } /* リンクファイル/リンクレコードに応じて処理 */ err = lnk_sts((LINK *)&v, &stat); if (err >= ER_OK) { memcpy(OBJname[i].tc, stat.f_name, sizeof(stat.f_name)); } else if (err == ER_NOLNK) { err = fil_sts((LINK *)&v, OBJname[i].tc, NULL, NULL); } if (err < ER_OK) { P(("load_file: fil_sts %d\n", err)); P(("load_file: warning, this object is ignored\n")); /* goto fin2; */ } err = see_rec(fd, 1, 0, NULL); if (err < ER_OK) { P(("load_flie: see_rec %d\n", err)); goto fin2; } } /* 主TADレコードへ移動 */ err = fnd_rec(fd, F_ENDTOP, (1 << 1), 0, NULL); if (err < ER_OK) { P(("load_file: fnd_rec %d\n", err)); goto fin2; } /* レコードサイズの取得 */ err = rea_rec(fd, 0, NULL, 0, &TADsize, NULL); if (err < ER_OK) { P(("load_file: rea_rec %d\n", err)); goto fin2; } /* メモリの確保 */ TADdata = malloc(TADsize); if (TADdata == NULL) { P(("load_file: malloc NULL\n")); err = ER_NOMEM; goto fin2; } /* レコード全体の読み込み */ err = rea_rec(fd, 0, (B *)TADdata, TADsize, NULL, NULL); if (err < ER_OK) { P(("load_file: rea_rec %d\n", err)); goto fin3; } DP(("load_file: TADsize %d, OBJentry %d\n", TADsize, OBJentry)); /* ファイルをクローズして終了 */ goto fin1; fin3: if (TADdata != NULL) { free(TADdata); TADdata = NULL; } fin2: if (OBJname != NULL) { free(OBJname); OBJname = NULL; } fin1: if (fd >= 0) cls_fil(fd); fin0: return err; }