📄 ship.cc
字号:
if(hul==-1) hul=mhul; ply=false; mov.xx=0; mov.yy=0; frnd=NULL; enem=NULL; plnt=NULL; if(aity==-1) aity=AI_NULL; resequip();}void ship::insert(){ self=-1; if(ply) { for(int i=0;i<ISIZE && self==-1;i++) if(!ships[i]) self=i; } else { for(int i=0;(i<(ISIZE-server::ISIZE)) && self==-1;i++) if(!ships[i]) self=i; } if(self==-1) throw error("No free ship index available"); else ships[self]=this;}void ship::insert(int self){ this->self=-1; if(!(self>=0 && self<ISIZE)) return; this->self=self; if(ships[self]) delete ships[self]; ships[self]=this;}ship::ship(int self){ char obsc[16]; //Object name scratchpad sprintf(obsc,"Ship%hd",self); database::switchobj(obsc); load(); insert(self);}void ship::physics(){ vect nmov; //New movement vector //Slow down vessels at warp under masslock influence if(vel.rad>=100 && mlck) vel.rad=mip; //Handle ships in between warp 1 and maximum impulse if(vel.rad<100 && vel.rad>mip) vel.rad=mip; //Handle ships going beyond the boundaries of the 'universe'; they bounce if(loc.x>LIMIT || loc.x<-LIMIT || loc.y>LIMIT || loc.y<-LIMIT) { vel.ang=(vel.ang+180); if(vel.ang>=360) vel.ang-=360; } if(loc.x>LIMIT) loc.x=LIMIT; if(loc.x<-LIMIT) loc.x=-LIMIT; if(loc.y>LIMIT) loc.y=LIMIT; if(loc.y<-LIMIT) loc.y=-LIMIT; nmov=vel.tovect(); if(vel.rad<100 && (mss/100)!=0) { mov.xx+=(nmov.xx-mov.xx)/(mss/100); mov.yy+=(nmov.yy-mov.yy)/(mss/100); //loc.x+=(nmov.xx-mov.xx); //loc.y+=(nmov.yy-mov.yy); } else { mov=nmov; } loc.x+=mov.xx; loc.y+=mov.yy;}void ship::autonav(planet* tpln){ vect vtrg; //Vector to target pol ptrg; //Polar to target double dd; //Directional difference double tol; //Angular tolerance vtrg.xx=(self*497)%800-400+tpln->loc.x-loc.x; vtrg.yy=(self*273)%800-400+tpln->loc.y-loc.y; //Vector to deterministic but arbitrary location near target planet ptrg=vtrg.topol(); //...make polar dd=ptrg.ang-vel.ang; if(dd>180) dd=dd-360; if(dd<-180) dd=dd+360; //Evaluate angle between current heading and target bearing tol=trn+2; if(vel.rad<=5) tol=20; //Low speed; not too fussed about fine direction finding ptrg.rad-=150; //Stand off distance if(ptrg.rad<0) //Don't turn when too close dd=0; if(dd<tol && dd>-tol) //Don't turn when within angle tolerance dd=0; if(dd==0 && ptrg.rad>0) //Only accelerate when heading at target { if(vel.rad>=100) { if(vel.rad<sqrt(2*awp*ptrg.rad)-awp) accel(+1,true); else if(vel.rad>sqrt(2*awp*ptrg.rad)+awp) accel(-1,true); } else { if(vel.rad<(sqrt(2*aip*ptrg.rad)-aip)) //Intended speed is sqrt(2as) accel(+1,true); else if(vel.rad>(sqrt(3*aip*ptrg.rad))+aip) accel(-1,true); } } else accel(-1,false); if(dd>0) turn(+1); if(dd<0) turn(-1);}void ship::follow(ship* tshp){ vect vtrg; //Vector to target pol ptrg; //Polar to target double dd; //Directional difference double tol; //Angular tolerance ptrg.ang=tshp->vel.ang+90+(self*29)%180; //Find deterministic formation angle to hold at around target ship ptrg.rad=100+(self*17)%((sens ? sens->item->rng : 1000)/16); //Deterministic range to hold based on sensor range vtrg=ptrg.tovect(); vtrg.xx+=tshp->loc.x-loc.x; vtrg.yy+=tshp->loc.y-loc.y; ptrg=vtrg.topol(); //Get polar vector to this formation position dd=ptrg.ang-vel.ang; if(dd>180) dd=dd-360; if(dd<-180) dd=dd+360; //Evaluate angle between current heading and target bearing if(!see(tshp)) ptrg.rad-=(sens ? sens->item->rng : 1000)/3; //If you can't see the target, stand off a little tol=trn*2+2; if(vel.rad<=5) tol=20; //Low speed; not too fussed about fine direction finding ptrg.rad-=150; //Default stand off if(ptrg.rad<0) //Don't turn when too close dd=0; if(dd<tol && dd>-tol) //Don't turn when within angle tolerance dd=0; if(dd==0 && ptrg.rad>0) //Only accelerate when heading at target { if(vel.rad>=100) { if(vel.rad<sqrt(2*awp*ptrg.rad)-awp) accel(+1,true); else if(vel.rad>sqrt(2*awp*ptrg.rad)+awp) accel(-1,true); } else { if(vel.rad<(sqrt(2*aip*ptrg.rad)-2*aip)) //Intended speed is sqrt(2as) accel(+1,true); else if(vel.rad>(sqrt(2*aip*ptrg.rad)+2*aip)) accel(-1,true); } } else accel(-1,false); if(dd>0) turn(+1); if(dd<0) turn(-1);}void ship::attackpattern(ship* tshp,int str){ vect vtrg; //Vector to target pol ptrg; //Polar to target double dd; //Directional difference double tol; //Angular tolerance if(!see(tshp) || vel.rad>=100) //If you can't see or are warp pursuing the target ship, default to the follow method { follow(tshp); return; } if(str>(200+calc::rnd((self%7)*12)-50)) //Alternate on tailing target from one of two sides ptrg.ang=tshp->vel.ang+45+(str-self*29)%135; else ptrg.ang=tshp->vel.ang-45-(str+self*29)%135; ptrg.rad=100+(self*17)%((str+(sens ? sens->item->rng : 1000))/16); //Back off a little depending on sensor range vtrg=ptrg.tovect(); vtrg.xx+=tshp->loc.x-loc.x; vtrg.yy+=tshp->loc.y-loc.y; ptrg=vtrg.topol(); //And finally get a polar to the 'formation' position dd=ptrg.ang-vel.ang; if(dd>180) dd=dd-360; if(dd<-180) dd=dd+360; //Evaluate angle between current heading and target bearing if(!see(tshp)) ptrg.rad-=(sens ? sens->item->rng : 1000)/3; //If you can't see the target, stand off a little tol=trn*2+2; if(vel.rad<=5) tol=20; //Low speed; not too fussed about fine direction finding tol+=45; //Widen angle tolerance for close combat flair if(ptrg.rad<0) //Don't turn when too close dd=0; if(dd<tol && dd>-tol) //Don't turn when within angle tolerance dd=0; if(dd==0 && ptrg.rad>0) //Only accelerate when heading at target { if(vel.rad>=100) { if(ptrg.rad && (ptrg.rad/vel.rad) && ((vel.rad)/(12*ptrg.rad/vel.rad))>=awp-30) accel(-1,true); else accel(+1,true); } else { if(ptrg.rad && ((5*vel.rad*vel.rad)/(ptrg.rad))>=aip) accel(-1,true); else accel(+1,true); } } else accel(-1,false); if(dd>0) turn(+1); if(dd<0) turn(-1);}void ship::loadlink(){ frnd=get(database::getvalue("FriendTarget")); enem=get(database::getvalue("EnemyTarget")); plnt=planet::get(database::getvalue("PlanetTarget"));}void ship::maintain(){ if(crip) { if(shd) shd->rdy=-1; if(clk) clk->rdy=-1; if(calc::rnd(402)==0) hit(1000,loc,mov,NULL); } else { if(pow && ful) { if((pow->cap)<(pow->item->cap) && ful->cap>0) { ful->cap-=pow->item->pow; pow->cap+=pow->item->pow; if(ful->cap<0) ful->cap=0; } if((pow->cap)>(pow->item->cap)) { ful->cap+=(pow->cap)-(pow->item->cap); pow->cap=pow->item->cap; } } } for(int i=0;i<32;i++) { if(slots[i].item) { if(slots[i].rdy>0) slots[i].rdy--; else if(slots[i].rdy<0 && (slots[i].item->typ==equip::PHASER || slots[i].item->typ==equip::LAUNCHER || slots[i].item->typ==equip::TRANSPORTER)) slots[i].rdy=0; } } if(shd && shd->rdy==0 && pow && (pow->cap)>=shd->item->pow) { shd->cap+=shd->item->pow; pow->cap-=shd->item->pow; if(shd->cap>shd->item->cap) shd->cap=shd->item->cap; } else { if(shd) shd->cap/=2; } if(clk) { if(clk->rdy==0) { if(pow && (pow->cap)>=(clk->item->pow*mss)/20) pow->cap-=(clk->item->pow*mss)/20; else uncloak(); if(clk->cap<clk->item->cap) clk->cap++; } else { if(clk->cap>=0) clk->cap=0; else clk->cap++; } } if(pow && pow->cap<0) pow->cap=0; if((!ful || (ful && ful->cap==0)) && !ply && calc::rnd(100)==0) delete this;}void ship::behave(){ int istr; //Individual strobe for this ship bool amrt; //Run amortised cost code for this state? planet* tpln; //A planet for use in ai code ship* tshp; //A ship for use in ai code istr=(mstr+self*7)%400; if(istr%40==0) amrt=true; else amrt=false; //Run behaviours for each case of this ship's behaviour state switch(aity) { case AI_AUTOPILOT: if(enem) follow(enem); else if(plnt) autonav(plnt); break; case AI_PATROLLER: if(enem) { attackpattern(enem,istr); firecontrol(istr); } else if(plnt) autonav(plnt); if(amrt) { if(!enem) { shieldsdown(); enem=pickhostile(); } else { shieldsup(); if(plnt && !see(plnt)) enem=NULL; } if(!plnt || plnt->all!=all || vel.rad<=5) { tpln=planet::pick(all); if(tpln && tpln->typ!=planet::STAR && see(tpln)) plnt=tpln; } } break; case AI_INVADER: if(enem) { attackpattern(enem,istr); firecontrol(istr); } else if(plnt) autonav(plnt); if(amrt) { if(plnt) cloak(); if(enem && calc::rnd(10)==0) enem=NULL; if(!enem) { shieldsdown(); tshp=pickhostile(); if(tshp) { enem=tshp; plnt=NULL; } } else shieldsup(); if(!enem && !plnt) plnt=planet::pickhostile(all); } break; case AI_CARAVAN: if(enem) { firecontrol(istr); if((plnt && istr<200) || !plnt) attackpattern(enem,istr); else autonav(plnt); } else if(plnt) autonav(plnt); if(amrt) { if(!enem) { shieldsdown(); enem=pickhostile(); } else shieldsup(); if(!plnt || all->opposes(plnt->all) || vel.rad<=5) { tpln=planet::pickally(all); if(tpln && tpln->typ!=planet::STAR) plnt=tpln; } } break; case AI_BUDDY: if(enem) { attackpattern(enem,istr); firecontrol(istr); } else if(frnd) follow(frnd); if(amrt) { if(!enem) shieldsdown(); if(enem) { shieldsup(); if(calc::rnd(10)==0) enem=NULL; } if(!enem) enem=pickhostile(); if(frnd) { if(frnd->clk && frnd->clk->cap!=0) cloak(); if(enem && !see(frnd)) enem=NULL; if(frnd->frnd) frnd=frnd->frnd; if(frnd==this) frnd=NULL; } else frnd=pickally(); } break; case AI_FLEET: if(enem) { if(shd && shd->cap<shd->item->cap) attackpattern(enem,istr); else if(frnd) follow(frnd); firecontrol(istr); } else if(frnd) follow(frnd); if(amrt) { if(!enem) shieldsdown(); if(enem) { shieldsup(); if(calc::rnd(10)==0) enem=NULL; } if(!enem) if(frnd && frnd->enem) enem=frnd->enem; else enem=pickhostile(); if(frnd) { if(frnd->clk && frnd->clk->cap!=0) cloak(); if(enem && !see(frnd)) enem=NULL; if(frnd->frnd) frnd=frnd->frnd; if(frnd==this) frnd=NULL; } else frnd=pickally(); } break; }}ship* ship::pickhostile(){ for(int i=0,j=0;i<ISIZE;i++) { j=calc::rnd(ISIZE); if(ships[j] && ships[j]!=this && all->opposes(ships[j]->all) && see(ships[j])) return ships[j]; } return NULL;}ship* ship::pickally(){ for(int i=0,j=0;i<ISIZE;i++) { j=calc::rnd(ISIZE); if(ships[j] && ships[j]!=this && !ships[j]->ply && all==ships[j]->all && see(ships[j])) return ships[j]; } return NULL;}void ship::lynch(){ for(int i=0;i<ISIZE;i++) if(ships[i] && !ships[i]->ply && ships[i]!=this && !ships[i]->enem && ships[i]->see(this)) ships[i]->enem=this;}void ship::firecontrol(int str){ if(enem && see(enem)) { shoot(false); //Shoot torpedoes if they appear more threatening; i.e. have a greater maximum shield capacity if(str>50 && enem->shd && this->shd && ((enem->shd->item->cap)*2)>(this->shd->item->cap)) { shoot(true); } }}void ship::resequip(){ pow=NULL; shd=NULL; sens=NULL; clk=NULL; ful=NULL; for(int i=0;i<32;i++) { if(slots[i].item) { switch(slots[i].item->typ) { case equip::POWER: pow=&slots[i]; break; case equip::SHIELD: shd=&slots[i]; break; case equip::SENSOR: sens=&slots[i]; break; case equip::CLOAK: clk=&slots[i]; break; case equip::FUELTANK: ful=&slots[i]; break; } } }}ship* ship::ships[ISIZE];ship* ship::lib[LIBSIZE];int ship::mstr;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -