airmovetype.cpp
来自「这是整套横扫千军3D版游戏的源码」· C++ 代码 · 共 1,197 行 · 第 1/3 页
CPP
1,197 行
#include "StdAfx.h"
#include "AirMoveType.h"
#include "Game/GameHelper.h"
#include "Game/Player.h"
#include "LogOutput.h"
#include "Map/Ground.h"
#include "Mobility.h"
#include "myMath.h"
#include "Rendering/UnitModels/3DOParser.h"
#include "Sim/Misc/GeometricObjects.h"
#include "Sim/Misc/LosHandler.h"
#include "Sim/Misc/QuadField.h"
#include "Sim/Misc/RadarHandler.h"
#include "Sim/Projectiles/Unsynced/SmokeProjectile.h"
#include "Sim/Units/COB/CobFile.h"
#include "Sim/Units/COB/CobInstance.h"
#include "Sim/Units/UnitDef.h"
#include "Sim/Weapons/Weapon.h"
#include "Sound.h"
#include "mmgr.h"
CR_BIND_DERIVED(CAirMoveType, CMoveType, (NULL));
CR_BIND(CAirMoveType::DrawLine, );
CR_BIND(CAirMoveType::RudderInfo, );
CR_REG_METADATA(CAirMoveType, (
CR_MEMBER(subState),
CR_MEMBER(maneuver),
CR_MEMBER(maneuverSubState),
CR_MEMBER(loopbackAttack),
CR_MEMBER(isFighter),
CR_MEMBER(collide),
CR_MEMBER(wingDrag),
CR_MEMBER(wingAngle),
CR_MEMBER(invDrag),
CR_MEMBER(frontToSpeed),
CR_MEMBER(speedToFront),
CR_MEMBER(myGravity),
CR_MEMBER(maxBank),
CR_MEMBER(maxPitch),
CR_MEMBER(maxSpeed),
CR_MEMBER(turnRadius),
CR_MEMBER(wantedHeight),
CR_MEMBER(maxAcc),
CR_MEMBER(maxAileron),
CR_MEMBER(maxElevator),
CR_MEMBER(maxRudder),
CR_MEMBER(goalPos),
CR_MEMBER(inSupply),
CR_MEMBER(reservedLandingPos),
CR_MEMBER(mySide),
CR_MEMBER(crashAileron),
CR_MEMBER(crashElevator),
CR_MEMBER(crashRudder),
CR_MEMBER(oldpos),
CR_MEMBER(oldGoalPos),
CR_MEMBER(oldSlowUpdatePos),
CR_MEMBER(lines),
CR_MEMBER(rudder),
CR_MEMBER(elevator),
CR_MEMBER(aileronRight),
CR_MEMBER(aileronLeft),
CR_MEMBER(rudders),
CR_MEMBER(lastRudderUpdate),
CR_MEMBER(lastRudderPos),
CR_MEMBER(lastElevatorPos),
CR_MEMBER(lastAileronPos),
CR_MEMBER(inefficientAttackTime),
CR_MEMBER(exitVector),
CR_MEMBER(lastColWarning),
CR_MEMBER(lastColWarningType),
CR_MEMBER(repairBelowHealth),
CR_MEMBER(reservedPad),
CR_MEMBER(padStatus),
CR_MEMBER(autoLand),
CR_RESERVED(63)
));
CR_REG_METADATA_SUB(CAirMoveType, DrawLine, (
CR_MEMBER(pos1), CR_MEMBER(pos2),
CR_MEMBER(color)));
CR_REG_METADATA_SUB(CAirMoveType, RudderInfo, (CR_MEMBER(rotation)));
CAirMoveType::CAirMoveType(CUnit* owner):
CMoveType(owner),
wingDrag(0.07f),
wingAngle(0.1f),
frontToSpeed(0.04f),
speedToFront(0.01f),
maxBank(0.55f),
maxPitch(0.35f),
maxAcc(0.006f),
maxAileron(0.04f),
maxElevator(0.02f),
maxRudder(0.01f),
goalPos(1000,0,1000),
wantedHeight(80),
invDrag(0.995f),
aircraftState(AIRCRAFT_LANDED),
inSupply(0),
subState(0),
myGravity(0.8f),
mySide(1),
isFighter(false),
collide(true),
oldpos(0,0,0),
oldGoalPos(0,1,0),
maneuver(0),
maneuverSubState(0),
inefficientAttackTime(0),
reservedLandingPos(-1,-1,-1),
oldSlowUpdatePos(-1,-1,-1),
lastColWarning(0),
lastColWarningType(0),
repairBelowHealth(0.30f),
padStatus(0),
reservedPad(0),
loopbackAttack(false),
autoLand(true)
{
turnRadius=150;
if (owner)owner->mapSquare+=1; //to force los recalculation
//From Aircraft::Init
maxRudder*=0.99f+gs->randFloat()*0.02f;
maxElevator*=0.99f+gs->randFloat()*0.02f;
maxAileron*=0.99f+gs->randFloat()*0.02f;
maxAcc*=0.99f+gs->randFloat()*0.02f;
crashAileron=1-gs->randFloat()*gs->randFloat();
if(gs->randInt()&1)
crashAileron=-crashAileron;
crashElevator=gs->randFloat();
crashRudder=gs->randFloat()-0.5f;
lastRudderUpdate=gs->frameNum;
lastElevatorPos=0;
lastRudderPos=0;
lastAileronPos=0;
exitVector=gs->randVector();
if(exitVector.y<0)
exitVector.y=-exitVector.y;
exitVector.y+=1;
}
CAirMoveType::~CAirMoveType(void)
{
if(reservedPad){
airBaseHandler->LeaveLandingPad(reservedPad);
reservedPad=0;
}
}
void CAirMoveType::Update(void)
{
float3 &pos=owner->pos;
//This is only set to false after the plane has finished constructing
if (useHeading) {
useHeading = false;
SetState(AIRCRAFT_TAKEOFF);
}
if (owner->stunned) {
UpdateAirPhysics(0, lastAileronPos, lastElevatorPos, 0, ZeroVector);
goto EndNormalControl;
}
#ifdef DIRECT_CONTROL_ALLOWED
if (owner->directControl && !(aircraftState == AIRCRAFT_CRASHING)) {
SetState(AIRCRAFT_FLYING);
DirectControlStruct* dc = owner->directControl;
inefficientAttackTime = 0;
if (dc->forward || dc->back || dc->left || dc->right) {
float aileron = 0;
float elevator = 0;
if (dc->forward)
elevator -= 1;
if (dc->back)
elevator += 1;
if (dc->right)
aileron += 1;
if (dc->left)
aileron -= 1;
UpdateAirPhysics(0, aileron, elevator, 1, owner->frontdir);
maneuver = 0;
goto EndNormalControl; //ok so goto is bad i know
}
}
#endif
if (reservedPad) {
CUnit* unit = reservedPad->GetUnit();
float3 relPos = unit->localmodel->GetPiecePos(reservedPad->GetPiece());
float3 pos = unit->pos + (unit->frontdir * relPos.z) + (unit->updir * relPos.y) + (unit->rightdir * relPos.x);
if (padStatus == 0) {
if (aircraftState != AIRCRAFT_FLYING && aircraftState != AIRCRAFT_TAKEOFF)
SetState(AIRCRAFT_FLYING);
goalPos = pos;
if (pos.distance2D(owner->pos) < 400) {
padStatus = 1;
}
// geometricObjects->AddLine(owner->pos,pos,1,0,1);
} else if (padStatus == 1) {
if (aircraftState != AIRCRAFT_LANDING)
SetState(AIRCRAFT_LANDING);
goalPos = pos;
reservedLandingPos = pos;
if (owner->pos.distance(pos) < 3 || aircraftState == AIRCRAFT_LANDED){
padStatus = 2;
}
// geometricObjects->AddLine(owner->pos,pos,10,0,1);
} else {
if (aircraftState != AIRCRAFT_LANDED)
SetState(AIRCRAFT_LANDED);
owner->pos = pos;
owner->AddBuildPower(unit->unitDef->buildSpeed/30,unit);
owner->currentFuel = min (owner->unitDef->maxFuel, owner->currentFuel + (owner->unitDef->maxFuel / (GAME_SPEED * owner->unitDef->refuelTime)));
if(owner->health>=owner->maxHealth-1 && owner->currentFuel >= owner->unitDef->maxFuel){
airBaseHandler->LeaveLandingPad(reservedPad);
reservedPad=0;
padStatus=0;
goalPos=oldGoalPos;
SetState(AIRCRAFT_TAKEOFF);
}
}
}
switch (aircraftState) {
case AIRCRAFT_FLYING:
#ifdef DEBUG_AIRCRAFT
if (selectedUnits.selectedUnits.find(this) != selectedUnits.selectedUnits.end()) {
logOutput.Print("Flying %i %i %.1f %i", moveState, fireState, inefficientAttackTime, (int) isFighter);
}
#endif
owner->restTime=0;
if(owner->userTarget || owner->userAttackGround){
inefficientAttackTime=min(inefficientAttackTime,(float)gs->frameNum-owner->lastFireWeapon);
if(owner->userTarget){
goalPos=owner->userTarget->pos;
} else {
goalPos=owner->userAttackPos;
}
if(maneuver){
UpdateManeuver();
inefficientAttackTime=0;
} else if(isFighter && goalPos.distance(pos)<owner->maxRange*4){
inefficientAttackTime++;
UpdateFighterAttack();
}else{
inefficientAttackTime=0;
UpdateAttack();
}
}else{
inefficientAttackTime=0;
UpdateFlying(wantedHeight,1);
}
break;
case AIRCRAFT_LANDED:
inefficientAttackTime=0;
UpdateLanded();
break;
case AIRCRAFT_LANDING:
inefficientAttackTime=0;
UpdateLanding();
break;
case AIRCRAFT_CRASHING:
owner->crashing=true;
UpdateAirPhysics(crashRudder,crashAileron,crashElevator,0,owner->frontdir);
SAFE_NEW CSmokeProjectile(owner->midPos,gs->randVector()*0.08f,100+gs->randFloat()*50,5,0.2f,owner,0.4f);
if(!(gs->frameNum&3) && max(0.f,ground->GetApproximateHeight(pos.x,pos.z))+5+owner->radius>pos.y)
owner->KillUnit(true,false,0);
break;
case AIRCRAFT_TAKEOFF:
UpdateTakeOff(wantedHeight);
default:
break;
}
EndNormalControl:
if (pos != oldpos) {
oldpos = pos;
bool hitBuilding = false;
if (collide && (aircraftState == AIRCRAFT_FLYING || aircraftState == AIRCRAFT_CRASHING)) {
vector<CUnit*> nearUnits = qf->GetUnitsExact(pos, owner->radius + 6);
vector<CUnit*>::iterator ui;
for (ui = nearUnits.begin(); ui != nearUnits.end(); ++ui) {
float sqDist = (pos - (*ui)->pos).SqLength();
float totRad = owner->radius + (*ui)->radius;
if (sqDist < totRad * totRad && sqDist != 0) {
float dist = sqrt(sqDist);
float3 dif = pos - (*ui)->pos;
dif /= dist;
if ((*ui)->immobile) {
pos -= dif * (dist - totRad);
owner->midPos = pos + owner->frontdir * owner->relMidPos.z + owner->updir * owner->relMidPos.y + owner->rightdir * owner->relMidPos.x;
owner->speed *= 0.99f;
float damage = (((*ui)->speed - owner->speed) * 0.1f).SqLength();
owner->DoDamage(DamageArray() * damage, 0, ZeroVector);
(*ui)->DoDamage(DamageArray() * damage, 0, ZeroVector);
hitBuilding = true;
} else {
float part = owner->mass / (owner->mass + (*ui)->mass);
pos -= dif * (dist - totRad) * (1 - part);
owner->midPos = pos + owner->frontdir * owner->relMidPos.z + owner->updir * owner->relMidPos.y + owner->rightdir * owner->relMidPos.x;
CUnit* u = (CUnit*)(*ui);
u->pos += dif * (dist - totRad) * (part);
u->midPos = u->pos + u->frontdir * u->relMidPos.z + u->updir * u->relMidPos.y + u->rightdir * u->relMidPos.x;
float damage = (((*ui)->speed - owner->speed) * 0.1f).SqLength();
owner->DoDamage(DamageArray() * damage, 0, ZeroVector);
(*ui)->DoDamage(DamageArray() * damage, 0, ZeroVector);
owner->speed *= 0.99f;
}
}
}
if (hitBuilding && owner->crashing) {
// if our collision sphere overlapped with that
// of a building and we're crashing, die right
// now rather than waiting until we're close
// enough to the ground (which may never happen
// if eg. we're going down over a crowded field
// of windmills due to col-det)
owner->KillUnit(true, false, 0);
return;
}
}
if(pos.x<0){
pos.x+=1.5f;
owner->midPos.x+=1.5f;
}else if(pos.x>float3::maxxpos){
pos.x-=1.5f;
owner->midPos.x-=1.5f;
}
if(pos.z<0){
pos.z+=1.5f;
owner->midPos.z+=1.5f;
}else if(pos.z>float3::maxzpos){
pos.z-=1.5f;
owner->midPos.z-=1.5f;
}
}
#ifdef DEBUG_AIRCRAFT
if(lastColWarningType==1){
int g=geometricObjects->AddLine(owner->pos,lastColWarning->pos,10,1,1);
geometricObjects->SetColor(g,0.2f,1,0.2f,0.6f);
} else if(lastColWarningType==2){
int g=geometricObjects->AddLine(owner->pos,lastColWarning->pos,10,1,1);
if(owner->frontdir.dot(lastColWarning->midPos+lastColWarning->speed*20 - owner->midPos - owner->speed*20)<0)
geometricObjects->SetColor(g,1,0.2f,0.2f,0.6f);
else
geometricObjects->SetColor(g,1,1,0.2f,0.6f);
}
#endif
}
void CAirMoveType::SlowUpdate(void)
{
if(aircraftState!=AIRCRAFT_LANDED && owner->unitDef->maxFuel>0)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?