📄 ship.cc
字号:
/* ship.cc (c) Richard Thrippleton Licensing terms are in the 'LICENSE' file If that file is not included with this source then permission is not given to use this source in any way whatsoever.*/#include <stdio.h>#include "calc.h"#include "error.h"#include "frag.h"#include "database.h"#include "planet.h"#include "equip.h"#include "server.h"#include "alliance.h"#include "constants.h"#include "protocol.h"#include "player.h"#include "ship.h"ship::ship(cord loc,ship* lshp,alliance* tali,int aity){ self=-1; if(!tali) throw error("Null alliance given"); if(!lshp) throw error("Null ship template given"); *this=*lshp; vel.ang=calc::rnd(360); vel.rad=0; this->loc=loc; this->all=tali; mlck=true; crip=false; ply=NULL; this->aity=aity; resequip(); if(freemass()<=0) { error::debug(cls,freemass()); }}ship::ship(){ self=-1; ply=NULL;}ship::~ship(){ if(self>=0 && self<ISIZE) ships[self]=NULL; for(int i=0;i<ISIZE;i++) { if(ships[i]) { if(ships[i]->enem==this) ships[i]->enem=NULL; if(ships[i]->frnd==this) ships[i]->frnd=NULL; } } frag::notifydelete(this); if(ply) ply->notifydelete();}void ship::init(){ for(int i=0;i<ISIZE;i++) ships[i]=NULL;}void ship::loadlib(){ char obnm[33]; //Object name for(int i=0;i<LIBSIZE;i++) { try { lib[i]=new ship(); try { sprintf(obnm,"ShipLib%hd",i); database::switchobj(obnm); lib[i]->load(); lib[i]->typ=i; } catch(error it) { if(lib[i]) delete lib[i]; lib[i]=NULL; } } catch(error it) { lib[i]=NULL; } }}void ship::purgeall(){ for(int i=0;i<ISIZE;i++) if(ships[i]) delete ships[i];}void ship::simulateall(){ for(int i=0;i<ISIZE;i++) { if(ships[i]) { ships[i]->physics(); ships[i]->maintain(); } }}void ship::behaveall(){ mstr=(mstr+1)%1000; //Increment the master strobe for(int i=0;i<ISIZE;i++) { if(ships[i] && !ships[i]->crip) //Ships that exist and are non-crippled should do behaviour ships[i]->behave(); } for(int i=0,j=0;i<10;i++) { j=(mstr*(i+1))%ISIZE; if(ships[j] && !ships[j]->crip) //Non-crippled ships need masslock checking periodically ships[j]->mlck=planet::masslock(ships[j]->loc); }}void ship::saveall(){ char obsc[16]; //Object name scratchpad for(int i=0;i<ISIZE;i++) { if(ships[i]) { sprintf(obsc,"Ship%hd",i); database::putobject(obsc); ships[i]->save(); } }}void ship::loadall(){ char obsc[16]; //Object name scratchpad for(int i=0;i<ISIZE;i++) { try { new ship(i); } catch(error it) { } } for(int i=0;i<ISIZE;i++) { try { if(ships[i]) { sprintf(obsc,"Ship%hd",i); database::switchobj(obsc); ships[i]->loadlink(); } } catch(error it) { } }}ship* ship::get(int indx){ if(indx>=0 && indx<ISIZE) { if(ships[indx]) return ships[indx]; else return NULL; } else { return NULL; }}ship* ship::libget(int indx){ if(indx>=0 && indx<LIBSIZE) { if(lib[indx]) return lib[indx]; else return NULL; } else { return NULL; }}bool ship::freeslot(){ for(int i=0;(i<(ISIZE-server::ISIZE));i++) if(!ships[i]) return true; return false;}void ship::turn(int dir){ if(pow && pow->cap>0) { if(dir==+1) vel.ang+=trn; if(dir==-1) vel.ang-=trn; if(vel.ang>=360) vel.ang-=360; if(vel.ang<0) vel.ang+=360; }}void ship::accel(int dir,bool wrp){ int pcon; //Power consumption double nsp; //New speed nsp=vel.rad; //Handle acceleration while at warp if(vel.rad>99) { if(dir==+1) nsp=vel.rad+awp; if(dir==-1) nsp=vel.rad-awp; if(nsp<100) if(wrp) nsp=mip; else nsp=100; } //Handle acceleration if currently at impulse //if(vel.rad<=mip) else { if(dir==+1) { nsp=vel.rad+aip; } if(dir==-1) { nsp=vel.rad-aip; } if(nsp>mip) { if(wrp) nsp=100; else nsp=mip; } } if(nsp>mip && nsp<100) nsp=mip; if(nsp>mwp) nsp=mwp; if(nsp<-(mip/3)) //Prevent going faster backwards than reverse speed nsp=-mip/3; if(nsp<0 && !wrp && vel.rad>=0) //Prevent moving into reverse if transition not specified nsp=0; if(nsp>=100) pcon=(int)(((vel.rad-nsp)*mss)/2000); else pcon=(int)(((vel.rad-nsp)*mss)/2); if(pcon<0) pcon=-pcon; if((nsp>=100 && vel.rad<100) || (nsp<100 && vel.rad>=100)) pcon=0; if(pow && pow->cap>=pcon) { pow->cap-=pcon; vel.rad=nsp; }}void ship::shoot(bool torp){ pol ptmp; vect vtmp; //Temporaries for calculations vect corr; //Correction vector pol ptrg; //Polar to target double dis; //Distance to target vect vtrg; //Vector to target cord cemt; //Location to emit frag at pol pemt; //Polar velocity to emit frag at vect vemt; //Vector to emit frag at double dif; //Angle difference long rng; //Range bool can; //Can shoot from this slot? equip* lnch; //Equipment doing the launching if(!see(enem)) return; if(vel.rad>=100) return; rng=0; for(int i=0;i<32;i++) { if(slots[i].item && ((torp && slots[i].item->typ==equip::LAUNCHER) || (!torp && slots[i].item->typ==equip::PHASER))) { lnch=slots[i].item; vtrg.xx=enem->loc.x-loc.x; vtrg.yy=enem->loc.y-loc.y; ptrg=vtrg.topol(); dis=ptrg.rad; can=false; if(lnch->typ==equip::PHASER) { rng=lnch->rng*lnch->trck; if(lnch->trck) { corr.xx=((enem->mov.xx-mov.xx)*(ptrg.rad/lnch->trck)); corr.yy=((enem->mov.yy-mov.yy)*(ptrg.rad/lnch->trck)); if(vtrg.xx && corr.xx*10/vtrg.xx<10) vtrg.xx+=corr.xx; if(vtrg.yy && corr.yy*10/vtrg.yy<10) vtrg.yy+=corr.yy; ptrg=vtrg.topol(); ptrg.rad=dis; } } if(lnch->typ==equip::LAUNCHER) rng=((lnch->rng*lnch->rng)/2)*lnch->trck; if(ptrg.rad<=rng) can=true; if(can) { dif=ptrg.ang-(vel.ang+slots[i].face); if(dif>180) dif=dif-360; if(dif<-180) dif=dif+360; if(dif>(lnch->acov) || dif<-(lnch->acov)) can=false; if(dif>(lnch->acov) || dif<-(lnch->acov)) can=false; if(lnch->typ==equip::PHASER && pow->cap<lnch->pow) can=false; if(lnch->typ==equip::LAUNCHER && !(slots[i].cap>0)) can=false; if(slots[i].rdy!=0) can=false; } if(can) { uncloak(); ptmp=slots[i].pos; ptmp.ang=(ptmp.ang+vel.ang); if(ptmp.ang>=360) ptmp.ang-=360; vtmp=ptmp.tovect(); cemt.x=vtmp.xx+loc.x; cemt.y=vtmp.yy+loc.y; if(torp) { pemt.ang=slots[i].face+vel.ang; //Sort out the angle a torpedo is shot at if(pemt.ang>=360) pemt.ang-=360; pemt.rad=lnch->trck*2; //and the speed } else { pemt.ang=ptrg.ang; //velocity of phaser fire emission, towards target at fixed speed for this weapon pemt.rad=lnch->trck; } vemt=pemt.tovect(); vemt.xx+=mov.xx; vemt.yy+=mov.yy; if(lnch->typ==equip::PHASER) { pow->cap-=lnch->pow; try { new frag(cemt,frag::ENERGY,lnch->spr,lnch->col,enem,this,vemt,((ptrg.ang+5)/10),lnch->pow,0,lnch->rng); } catch(error it) { } } if(lnch->typ==equip::LAUNCHER) { slots[i].cap--; try { new frag(cemt,frag::HOMER,lnch->spr,lnch->col,enem,this,vemt,0,lnch->pow,lnch->trck,lnch->rng); } catch(error it) { } } server::registernoise(this,lnch->snd); slots[i].rdy=lnch->rdy; if(torp) break; } } }}bool ship::see(ship* tshp){ double rng; //Effective range if(!tshp) //Null ship return false; if(tshp==this) //Can always see self return true; if(sens) //Set the sensor range, or default if no sensor suite rng=sens->item->rng; else rng=1000; if(tshp->vel.rad<20) //Slower ships less visible rng-=(((rng/2)*(20-tshp->vel.rad))/20); if(tshp->clk && tshp->clk->cap==tshp->clk->item->cap) //Cloaked ships even less visible rng/=8; if((tshp->loc.x-loc.x)>rng) //Bounds checking return false; if((tshp->loc.x-loc.x)<-rng) return false; if((tshp->loc.y-loc.y)>rng) return false; if((tshp->loc.y-loc.y)<-rng) return false; return true;}bool ship::see(planet* tpln){ double rng; //Effective range if(!tpln) //Null planet return false; if(sens) //Set the sensor range, or default if no sensor suite rng=sens->item->rng; else rng=1000; if(tpln->typ==planet::STAR) //Can always see stars return true; if((tpln->loc.x-loc.x)>rng) //Bounds checking return false; if((tpln->loc.x-loc.x)<-rng) return false; if((tpln->loc.y-loc.y)>rng) return false; if((tpln->loc.y-loc.y)<-rng) return false; return true; }bool ship::see(frag* tfrg){ double rng; //Effective range if(!tfrg) //Null frag return false; if(sens) //Set the sensor range, or default if no sensor suite rng=sens->item->rng; else rng=1000; if(tfrg->trg==this || tfrg->own==this) //For bandwidth spamming reasons, only see frags when really close unless they concern you { if((tfrg->loc.x-loc.x)>rng) return false; if((tfrg->loc.x-loc.x)<-rng) return false; if((tfrg->loc.y-loc.y)>rng) return false; if((tfrg->loc.y-loc.y)<-rng) return false; } else { if((tfrg->loc.x-loc.x)>500) return false; if((tfrg->loc.x-loc.x)<-500) return false; if((tfrg->loc.y-loc.y)>500) return false; if((tfrg->loc.y-loc.y)<-500) return false; } return true; }int ship::interact(char* txt,short cmod,short opr,ship* mshp){ char spd[32]; //Speed if(!(mshp && mshp->ply)) return -1; switch(cmod) { case CMOD_STAT: case CMOD_SCAN: if(opr==-1) { if(mshp->see(this)) { txt+=sprintf(txt,"%s\n",cls); if(mshp->all->opposes(all)) txt+=sprintf(txt,"Alignment:%s [hostile]\n",all->nam); else txt+=sprintf(txt,"Alignment:%s\n",all->nam); if(ply) txt+=sprintf(txt,"Commanded by %s\n",ply->nam); if(shd && shd->cap>0) txt+=sprintf(txt,"\nShields: Raised\n"); else txt+=sprintf(txt,"\nShields: Down\n"); calc::getspeed(mwp,spd); txt+=sprintf(txt,"Maximum velocity: %s\n",spd); if(shd) txt+=sprintf(txt,"Shield capability: %ld\n",shd->item->cap); else txt+=sprintf(txt,"No shields"); if(pow) txt+=sprintf(txt,"Maximum power capacity: %ld\n",pow->item->cap); else txt+=sprintf(txt,"No power plant"); if(ful) txt+=sprintf(txt,"Maximum fuel storage: %ld\n",ful->item->cap); else txt+=sprintf(txt,"No fuel storage"); txt+=sprintf(txt,"\nAvailable mass: %hd\n",freemass()); if(this==mshp) {// txt+=sprintf(txt,"\nAvailable mass: %hd\n",freemass()); txt+=sprintf(txt,"\nCredits: %ld\n",ply->cashi); } if(this==mshp->enem) txt+=sprintf(txt,"\n[1] Lay in an intercept course\n"); return spr; } else { txt+=sprintf(txt,"Target not visible\n"); if(this==mshp->enem) txt+=sprintf(txt,"\n[1] Lay in an intercept course\n"); return -1; } } if(opr==1 && this==mshp->enem) { mshp->aity=AI_AUTOPILOT; } break; case CMOD_EQUIP: if(!(esel>=0 && esel<32 && slots[esel].item)) { esel=-1; for(int i=0;i<32;i++) { if(slots[i].item) { esel=i; break; } } } if(opr==-1) { txt+=sprintf(txt,"Internal systems\n\n"); for(int i=0;i<32;i++) { if(slots[i].item) { if(slots[i].item->typ==equip::LAUNCHER) if(i==esel) txt+=sprintf(txt,">%s [%ld]<\n",slots[i].item->nam,slots[i].cap); else txt+=sprintf(txt," %s [%ld]\n",slots[i].item->nam,slots[i].cap); else if(slots[i].item->typ==equip::FUELTANK && slots[i].cap==0) if(i==esel) txt+=sprintf(txt,">%s< [empty]\n",slots[i].item->nam); else txt+=sprintf(txt," %s [empty]\n",slots[i].item->nam); else if(i==esel) txt+=sprintf(txt,">%s<\n",slots[i].item->nam); else txt+=sprintf(txt," %s\n",slots[i].item->nam); } else { if(slots[i].pos.rad>=0) { if(slots[i].face<=90 || slots[i].face>=270) txt+=sprintf(txt," <Free forward port>\n"); else txt+=sprintf(txt," <Free rear port>\n"); } } } txt+=sprintf(txt,"\n"); if(shd) txt+=sprintf(txt,"[1] Toggle shields\n"); if(clk) txt+=sprintf(txt,"[2] Toggle cloak\n"); txt+=sprintf(txt,"\n[3] Select equipment\n"); txt+=sprintf(txt,"[4] Jettison selection\n"); } if(opr==1) if(shd && shd->rdy==-1) shieldsup(); else shieldsdown(); if(opr==2) if(clk && clk->rdy==-1) cloak(); else uncloak(); if(opr==3) { for(int i=0,j=esel+1;i<32;i++,j++) { if(j>=32) j=0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -