airmovetype.cpp
来自「这是整套横扫千军3D版游戏的源码」· C++ 代码 · 共 1,197 行 · 第 1/3 页
CPP
1,197 行
owner->currentFuel = max (0.f, owner->currentFuel - (16.f/GAME_SPEED));
if(!reservedPad && aircraftState==AIRCRAFT_FLYING && owner->health<owner->maxHealth*repairBelowHealth && !owner->crashing){
CAirBaseHandler::LandingPad* lp=airBaseHandler->FindAirBase(owner,owner->unitDef->minAirBasePower);
if(lp){
AddDeathDependence(lp);
reservedPad=lp;
padStatus=0;
oldGoalPos=goalPos;
}
}
if(owner->pos!=oldSlowUpdatePos){
oldSlowUpdatePos=owner->pos;
if(owner->pos.y - ground->GetApproximateHeight(owner->pos.x, owner->pos.z) > wantedHeight * 5 + 100) //try to handle aircraft getting unlimited height
owner->pos.y = ground->GetApproximateHeight(owner->pos.x, owner->pos.z) + wantedHeight * 5 + 100;
int newmapSquare=ground->GetSquare(owner->pos);
if(newmapSquare!=owner->mapSquare){
owner->mapSquare=newmapSquare;
float oldlh=owner->losHeight;
float h=owner->pos.y-ground->GetApproximateHeight(owner->pos.x,owner->pos.z);
owner->losHeight=h+5;
loshandler->MoveUnit(owner,false);
if(owner->hasRadarCapacity)
radarhandler->MoveUnit(owner);
owner->losHeight=oldlh;
}
qf->MovedUnit(owner);
owner->isUnderWater=owner->pos.y+owner->model->height<0;
}
}
void CAirMoveType::UpdateManeuver(void)
{
#ifdef DEBUG_AIRCRAFT
if(selectedUnits.selectedUnits.find(this)!=selectedUnits.selectedUnits.end()){
logOutput.Print("UpdataMan %i %i",maneuver,maneuverSubState);
}
#endif
float speedf=owner->speed.Length();
switch(maneuver){
case 1:{ //immelman
int aileron=0,elevator=0;
if(owner->updir.y>0){
if(owner->rightdir.y>maxAileron*speedf){
aileron=1;
}else if(owner->rightdir.y<-maxAileron*speedf){
aileron=-1;
}
}
if(fabs(owner->rightdir.y)<maxAileron*3*speedf || owner->updir.y<0)
elevator=1;
UpdateAirPhysics(0,aileron,elevator,1,owner->frontdir);
if((owner->updir.y<0 && owner->frontdir.y<0) || speedf<0.8f)
maneuver=0;
if(owner->pos.y - ground->GetApproximateHeight(owner->pos.x, owner->pos.z) > wantedHeight * 4) //some seem to report that the "unlimited altitude" thing is because of these maneuvers
maneuver = 0;
break;}
case 2:{ //inverted immelman
int aileron=0,elevator=0;
if(maneuverSubState==0){
if(owner->rightdir.y>=0){
aileron=-1;
}else{
aileron=1;
}
}
if(owner->frontdir.y<-0.7f)
maneuverSubState=1;
if(maneuverSubState==1 || owner->updir.y<0)
elevator=1;
UpdateAirPhysics(0,aileron,elevator,1,owner->frontdir);
if((owner->updir.y>0 && owner->frontdir.y>0 && maneuverSubState==1) || speedf<0.2f)
maneuver=0;
break;}
default:
UpdateAirPhysics(0,0,0,1,owner->frontdir);
maneuver=0;
break;
}
}
void CAirMoveType::UpdateFighterAttack(void)
{
float3 &pos = owner->pos;
SyncedFloat3 &rightdir = owner->rightdir;
SyncedFloat3 &frontdir = owner->frontdir;
SyncedFloat3 &updir = owner->updir;
float3 &speed = owner->speed;
float speedf=owner->speed.Length();
if(speedf<0.01f){
UpdateAirPhysics(0,0,0,1,owner->frontdir);
return;
}
if(!((gs->frameNum+owner->id)&3))
CheckForCollision();
bool groundTarget=!owner->userTarget || !owner->userTarget->unitDef->canfly;
bool airTarget=owner->userTarget && owner->userTarget->unitDef->canfly && !owner->userTarget->unitDef->hoverAttack; //only "real" aircrafts (non gunship)
if(groundTarget){
if(frontdir.dot(goalPos-pos)<0 && (pos-goalPos).SqLength()<turnRadius*turnRadius*(loopbackAttack?4:1)){
float3 dif=pos-goalPos;
dif.y=0;
dif.Normalize();
goalPos=goalPos+dif*turnRadius*4;
} else if (loopbackAttack && !airTarget){
bool hasFired=false;
if(!owner->weapons.empty() && owner->weapons[0]->reloadStatus > gs->frameNum && owner->weapons[0]->salvoLeft==0)
hasFired=true;
if( frontdir.dot(goalPos-pos)<owner->maxRange*(hasFired?1.0f:0.7f)){
maneuver=1;
}
} else if(frontdir.dot(goalPos-pos)<owner->maxRange*0.7f){
goalPos+=exitVector*(owner->userTarget?owner->userTarget->radius+owner->radius+10:owner->radius+40);
}
}
float3 tgp=goalPos+(goalPos-oldGoalPos)*8;
oldGoalPos=goalPos;
goalPos=tgp;
float goalLength=(goalPos-pos).Length();
float3 goalDir=(goalPos-pos)/goalLength;
float aileron=0;
float rudder=0;
float elevator=0;
float engine=0;
float gHeight=ground->GetHeight(pos.x,pos.z);
float goalDot=rightdir.dot(goalDir);
goalDot/=goalDir.dot(frontdir)*0.5f+0.501f;
if(goalDir.dot(frontdir)<-0.2f+inefficientAttackTime*0.002f && frontdir.y>-0.2f && speedf>2.0f && gs->randFloat()>0.996f)
maneuver=1;
if(goalDir.dot(frontdir)<-0.2f+inefficientAttackTime*0.002f && fabs(frontdir.y)<0.2f && gs->randFloat()>0.996f && gHeight+400<pos.y){
maneuver=2;
maneuverSubState=0;
}
//roll
if(speedf>0.45f && pos.y+owner->speed.y*60*fabs(frontdir.y)+min(0.f,updir.y)*150>gHeight+60+fabs(rightdir.y)*150){
float goalBankDif=goalDot+rightdir.y*0.2f;
if(goalBankDif>maxAileron*speedf*4){
aileron=1;
} else if(goalBankDif<-maxAileron*speedf*4){
aileron=-1;
} else {
aileron=goalBankDif/(maxAileron*speedf*4);
}
} else {
if(rightdir.y>0){
if(rightdir.y>maxAileron*speedf || frontdir.y<-0.7f)
aileron=1;
else
aileron=rightdir.y/(maxAileron*speedf);
} else {
if(rightdir.y<-maxAileron*speedf || frontdir.y<-0.7f)
aileron=-1;
else
aileron=rightdir.y/(maxAileron*speedf);
}
}
//yaw
if(pos.y>gHeight+30){
if(goalDot<-maxRudder*speedf){
rudder=-1;
} else if(goalDot>maxRudder*speedf){
rudder=1;
} else {
rudder=goalDot/(maxRudder*speedf);
}
}
float upside=1;
if(updir.y<-0.3f)
upside=-1;
//pitch
if(speedf<1.5f){
if(frontdir.y<0.0f){
elevator=upside;
} else if(frontdir.y>0.0f){
elevator=-upside;
}
} else {
float gHeight2=ground->GetHeight(pos.x+speed.x*40,pos.z+speed.z*40);
float hdif=max(gHeight,gHeight2)+60-pos.y-frontdir.y*speedf*20;
float minPitch;//=min(1.0f,hdif/(maxElevator*speedf*speedf*20));
if(hdif<-(maxElevator*speedf*speedf*20)){
minPitch=-1;
} else if(hdif>(maxElevator*speedf*speedf*20)){
minPitch=1;
} else {
minPitch=hdif/(maxElevator*speedf*speedf*20);
}
/* if(pos.y+min(0,owner->speed.y)*70*fabs(frontdir.y)+min(0,updir.y)*50<gHeight+50){
if(frontdir.y<0.5f){
elevator=upside;
} else if(frontdir.y>0.55f){
elevator=-upside;
}*/
// } else {
if(lastColWarning && lastColWarningType==2 && frontdir.dot(lastColWarning->pos+lastColWarning->speed*20-pos-owner->speed*20)<0){
/* float pitchMod=updir.y>0?1:-1;
if(lastColWarning->pos.y>pos.y)
elevator=-pitchMod;
else
elevator=pitchMod;
/*/ elevator=updir.dot(lastColWarning->midPos-owner->midPos)>0?-1:1;/**/
} else {
float hdif=goalDir.dot(updir);
if(hdif<-maxElevator*speedf){
elevator=-1;
} else if(hdif>maxElevator*speedf){
elevator=1;
} else {
elevator=hdif/(maxElevator*speedf);
}
}
if(elevator*upside<minPitch)
elevator=minPitch*upside;
}
#ifdef DEBUG_AIRCRAFT
if(selectedUnits.selectedUnits.find(this)!=selectedUnits.selectedUnits.end()){
logOutput.Print("FAttack %.1f %.1f %.2f",pos.y-gHeight,goalLength,goalDir.dot(frontdir));
}
#endif
if(groundTarget)
engine=1;
else
engine=min(1.f,(float)(goalLength/owner->maxRange+1-goalDir.dot(frontdir)*0.7f));
UpdateAirPhysics(rudder,aileron,elevator,engine,owner->frontdir);
/*
std::vector<CWeapon*>::iterator wi;
for(wi=owner->weapons.begin();wi!=owner->weapons.end();++wi){
(*wi)->targetPos=goalPos;
if(owner->userTarget){
(*wi)->AttackUnit(owner->userTarget,true);
}
}*/
/* DrawLine dl;
dl.color=UpVector;
dl.pos1=pos;
dl.pos2=goalPos;
lines.push_back(dl);
dl.color=float3(1,0,0);
dl.pos1=pos;
dl.pos2=pos+frontdir*maxRange;
lines.push_back(dl);/**/
}
void CAirMoveType::UpdateAttack(void)
{
/* std::vector<CWeapon*>::iterator wi;
for(wi=owner->weapons.begin();wi!=owner->weapons.end();++wi){
(*wi)->targetPos=goalPos;
if(owner->userTarget){
(*wi)->AttackUnit(owner->userTarget,true);
}
}
*/
UpdateFlying(wantedHeight,1);
}
void CAirMoveType::UpdateFlying(float wantedHeight,float engine)
{
float3 &pos = owner->pos;
SyncedFloat3 &rightdir = owner->rightdir;
SyncedFloat3 &frontdir = owner->frontdir;
SyncedFloat3 &updir = owner->updir;
float3 &speed = owner->speed;
float speedf=speed.Length();
float goalLength=(goalPos-pos).Length();
float3 goalDir=(goalPos-pos)/goalLength;
goalDir.Normalize();
float aileron=0;
float rudder=0;
float elevator=0;
float gHeight=ground->GetHeight(pos.x,pos.z);
if(!((gs->frameNum+owner->id)&3))
CheckForCollision();
float otherThreat=0;
float3 otherDir;
if(lastColWarning){
float3 otherDif=lastColWarning->pos-pos;
float otherLength=otherDif.Length();
otherDir=otherDif/otherLength;
otherThreat=max(1200.f,goalLength)/otherLength*0.036f;
}
float goalDot=rightdir.dot(goalDir);
goalDot/=goalDir.dot(frontdir)*0.5f+0.501f;
if(goalDir.dot(frontdir)<-0.1f && goalLength<turnRadius
#ifdef DIRECT_CONTROL_ALLOWED
&& (!owner->directControl || owner->directControl->mouse2)
#endif
)
goalDot=-goalDot;
if(lastColWarning){
goalDot-=otherDir.dot(rightdir)*otherThreat;
}
//roll
if(speedf>1.5f && pos.y+speed.y*10>gHeight+wantedHeight*0.6f){
float goalBankDif=goalDot+rightdir.y*0.5f;
if(goalBankDif>maxAileron*speedf*4 && rightdir.y>-maxBank){
aileron=1;
} else if(goalBankDif<-maxAileron*speedf*4 && rightdir.y<maxBank){
aileron=-1;
} else {
if(fabs(rightdir.y)<maxBank)
aileron=goalBankDif/(maxAileron*speedf*4);
else {
if(rightdir.y<0 && goalBankDif<0)
aileron=-1;
else if(rightdir.y>0 && goalBankDif>0)
aileron=1;
}
}
} else {
if(rightdir.y>0.01f){
aileron=1;
} else if(rightdir.y<-0.01f){
aileron=-1;
}
}
//yaw
if(pos.y>gHeight+15){
if(goalDot<-maxRudder*speedf*2){
rudder=-1;;
} else if(goalDot>maxRudder*speedf*2){
rudder=1;
} else {
rudder=goalDot/(maxRudder*speedf*2);
}
}
//pitch
if (speedf > 0.8f) {
bool notColliding = true;
if (lastColWarningType == 2) {
const float3 dir = lastColWarning->midPos - owner->midPos;
const float3 sdir = lastColWarning->speed - owner->speed;
if (frontdir.dot(dir + sdir * 20) < 0) {
elevator = updir.dot(dir) > 0 ? -1 : 1;
notColliding = false;
}
}
if (notColliding) {
float gHeight2=ground->GetHeight(pos.x+speed.x*40,pos.z+speed.z*40);
float hdif=max(gHeight,gHeight2)+wantedHeight-pos.y-frontdir.y*speedf*20;
if(hdif<-(maxElevator*speedf*speedf*20) && frontdir.y>-maxPitch){
elevator=-1;
} else if(hdif>(maxElevator*speedf*speedf*20) && frontdir.y<maxPitch){
elevator=1;
} else {
if(fabs(frontdir.y)<maxPitch)
elevator=hdif/(maxElevator*speedf*speedf*20);
}
}
}
else {
if (frontdir.y < -0.1f) {
elevator = 1;
} else if (frontdir.y > 0.15f) {
elevator = -1;
}
}
UpdateAirPhysics(rudder, aileron, elevator, engine, owner->frontdir);
}
void CAirMoveType::UpdateLanded(void)
{
float3 &pos = owner->pos;
SyncedFloat3 &rightdir = owner->rightdir;
SyncedFloat3 &frontdir = owner->frontdir;
SyncedFloat3 &updir = owner->updir;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?