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 + -
显示快捷键?