Complete disaster-recovery snapshot: engine/game source, game data assets, VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive. Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false, no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
1924 lines
50 KiB
C++
1924 lines
50 KiB
C++
//===========================================================================//
|
|
// File: Mech.cpp
|
|
//---------------------------------------------------------------------------//
|
|
// Date Who Modification //
|
|
// -------- --- ---------------------------------------------------------- //
|
|
// 09/09/98 JSE Inital base class based off of Shadowrun/Adept //
|
|
// 09/22/98 BDB Inital base Mech class based off Vehicle //
|
|
//---------------------------------------------------------------------------//
|
|
// Copyright (C) 1998, Fasa Interactive //
|
|
// All Rights reserved worldwide //
|
|
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
|
|
//===========================================================================//
|
|
|
|
#include "MW4Headers.hpp"
|
|
|
|
#include "Airplane.hpp"
|
|
#include "AirplaneAnimationStateEngine.hpp"
|
|
#include "helicopter.hpp"
|
|
#include "AI.hpp"
|
|
#include "aiutils.hpp"
|
|
#include "AI_Statistics.hpp"
|
|
|
|
#include <Adept\EntityManager.hpp>
|
|
#include <Adept\DamageObject.hpp>
|
|
#include <Adept\Effect.hpp>
|
|
#include <Adept\NameTable.hpp>
|
|
#include <Adept\CollisionGrid.hpp>
|
|
#include <Adept\Map.hpp>
|
|
#include <Adept\CollisionVolume.hpp>
|
|
|
|
stlport::vector<Scalar> *Airplane::m_Heights;
|
|
const Stuff::Scalar PlaneHeightSlotSize = 10.0f;
|
|
namespace MW4AI
|
|
{
|
|
extern Stuff::Scalar g_MaxBuildingHeight; // above the ground
|
|
extern Stuff::Scalar g_MaxAirHeight; // above the ground, to stay above movers
|
|
extern Stuff::Scalar MinZ, MaxZ, MinX, MaxX;
|
|
}
|
|
|
|
//#############################################################################
|
|
//################## Airplane::ExecutionStateEngine #####################
|
|
//#############################################################################
|
|
|
|
const StateEngine::StateEntry
|
|
Airplane::ExecutionStateEngine::StateEntries[]=
|
|
{
|
|
STATE_ENTRY(Airplane__ExecutionStateEngine, TakingOffMotion),
|
|
STATE_ENTRY(Airplane__ExecutionStateEngine, LandingMotion),
|
|
STATE_ENTRY(Airplane__ExecutionStateEngine, CrashingDeath),
|
|
STATE_ENTRY(Airplane__ExecutionStateEngine, Taxi),
|
|
STATE_ENTRY(Airplane__ExecutionStateEngine, Popup),
|
|
STATE_ENTRY(Airplane__ExecutionStateEngine, Popdown),
|
|
STATE_ENTRY(Airplane__ExecutionStateEngine, Float)
|
|
};
|
|
|
|
|
|
Airplane::ExecutionStateEngine::ClassData*
|
|
Airplane::ExecutionStateEngine::DefaultData = NULL;
|
|
|
|
DWORD MechWarrior4::Executed_Airplane_Count = 0;
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Airplane::ExecutionStateEngine::InitializeClass()
|
|
{
|
|
Check_Object(StateEngine::DefaultData);
|
|
Verify(!DefaultData);
|
|
|
|
DefaultData =
|
|
new ClassData(
|
|
Airplane__ExecutionStateEngineClassID,
|
|
"Airplane::ExecutionStateEngine",
|
|
BaseClass::DefaultData,
|
|
ELEMENTS(StateEntries), StateEntries,
|
|
(Entity::ExecutionStateEngine::Factory)Make,
|
|
(Entity::ExecutionStateEngine::FactoryRequest::Factory)
|
|
&FactoryRequest::ConstructFactoryRequest
|
|
);
|
|
Register_Object(DefaultData);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Airplane::ExecutionStateEngine::TerminateClass()
|
|
{
|
|
Unregister_Object(DefaultData);
|
|
delete DefaultData;
|
|
DefaultData = NULL;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Airplane::ExecutionStateEngine*
|
|
Airplane::ExecutionStateEngine::Make(
|
|
Airplane *mover,
|
|
FactoryRequest *request
|
|
)
|
|
{
|
|
Check_Object(mover);
|
|
Check_Object(request);
|
|
gos_PushCurrentHeap(Heap);
|
|
Airplane::ExecutionStateEngine *engine =
|
|
new Airplane::ExecutionStateEngine(DefaultData, mover, request);
|
|
gos_PopCurrentHeap();
|
|
return engine;
|
|
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
int
|
|
Airplane::ExecutionStateEngine::RequestState(
|
|
int new_state,
|
|
void* data
|
|
)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(owningEntity);
|
|
|
|
//
|
|
//----------------------------------------------
|
|
// Now, switch the state and tickle the watchers
|
|
//----------------------------------------------
|
|
//
|
|
|
|
Airplane *airplane;
|
|
airplane = Cast_Object(Airplane *, owningEntity);
|
|
if((new_state == TakingOffMotionState) && (currentState == FlyingMotionState))
|
|
return currentState;
|
|
if((new_state == LandingMotionState) && (currentState != FlyingMotionState))
|
|
return currentState;
|
|
if((new_state == CrashingDeathState) && (currentState == AlwaysExecuteState))
|
|
{
|
|
// airplane->shouldDie = true;
|
|
airplane->shouldLeaveReckage = true;
|
|
airplane->SetDying();
|
|
return currentState;
|
|
}
|
|
|
|
switch (BaseClass::RequestState(new_state, data))
|
|
{
|
|
|
|
case FlyingMotionState:
|
|
airplane->SetInAir();
|
|
break;
|
|
|
|
case TakingOffMotionState:
|
|
airplane->SetTakingOff();
|
|
break;
|
|
}
|
|
|
|
return currentState;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Airplane::ExecutionStateEngine::TestInstance() const
|
|
{
|
|
Verify(IsDerivedFrom(DefaultData));
|
|
}
|
|
|
|
//#############################################################################
|
|
//############################### Airplane ##############################
|
|
//#############################################################################
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Airplane::ClassData*
|
|
Airplane::DefaultData = NULL;
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Airplane::InitializeClass()
|
|
{
|
|
Check_Object(ExecutionStateEngine::DefaultData);
|
|
Verify(!DefaultData);
|
|
DefaultData =
|
|
new ClassData(
|
|
AirplaneClassID,
|
|
"MechWarrior4::Airplane",
|
|
BaseClass::DefaultData,
|
|
NULL, NULL,
|
|
(Entity::Factory)Make,
|
|
(Entity::CreateMessage::Factory)CreateMessage::ConstructCreateMessage,
|
|
ExecutionStateEngine::DefaultData,
|
|
(Entity::GameModel::Factory)GameModel::ConstructGameModel,
|
|
(Entity::GameModel::Factory)GameModel::ConstructOBBStream,
|
|
(Entity::GameModel::ReadAndVerifier)GameModel::ReadAndVerify,
|
|
(Entity::GameModel::ModelWrite)GameModel::WriteToText,
|
|
(Entity::GameModel::ModelSave)GameModel::SaveGameModel,
|
|
(AnimationStateEngine::Factory)AirplaneAnimationStateEngine::Make
|
|
);
|
|
Register_Object(DefaultData);
|
|
|
|
m_Heights = new stlport::vector<Scalar>;
|
|
Check_Pointer (m_Heights);
|
|
|
|
//Dave Need to add attribute entries
|
|
DIRECT_GAME_MODEL_ATTRIBUTE(
|
|
Airplane__GameModel,
|
|
FlyingAltitude,
|
|
flyingAltitude,
|
|
Scalar
|
|
);
|
|
|
|
DIRECT_GAME_MODEL_ATTRIBUTE(
|
|
Airplane__GameModel,
|
|
TiltSpeed,
|
|
tiltSpeed,
|
|
Radian
|
|
);
|
|
|
|
DIRECT_GAME_MODEL_ATTRIBUTE(
|
|
Airplane__GameModel,
|
|
TiltDegree,
|
|
tiltDegree,
|
|
Radian
|
|
);
|
|
|
|
DIRECT_GAME_MODEL_ATTRIBUTE(
|
|
Airplane__GameModel,
|
|
PercentageOfTurnToStartTilt,
|
|
percentageOfTurnToStartTilt,
|
|
Scalar
|
|
);
|
|
|
|
DIRECT_GAME_MODEL_ATTRIBUTE(
|
|
Airplane__GameModel,
|
|
PercentageOfSpeedToStartTilt,
|
|
percentageOfSpeedToStartTilt,
|
|
Scalar
|
|
);
|
|
|
|
DIRECT_GAME_MODEL_ATTRIBUTE(
|
|
Airplane__GameModel,
|
|
MaxTurnAngle,
|
|
maxTurnAngle,
|
|
Scalar
|
|
);
|
|
|
|
DIRECT_GAME_MODEL_ATTRIBUTE(
|
|
Airplane__GameModel,
|
|
ThrusterAcceleration,
|
|
thrusterAcceleration,
|
|
Scalar
|
|
);
|
|
|
|
DIRECT_GAME_MODEL_ATTRIBUTE(
|
|
Airplane__GameModel,
|
|
PitchSpeed,
|
|
pitchSpeed,
|
|
Radian
|
|
);
|
|
|
|
DIRECT_GAME_MODEL_ATTRIBUTE(
|
|
Airplane__GameModel,
|
|
PitchDegree,
|
|
pitchDegree,
|
|
Radian
|
|
);
|
|
|
|
DIRECT_GAME_MODEL_ATTRIBUTE(
|
|
Airplane__GameModel,
|
|
PercentageOfSpeedToStartPitch,
|
|
percentageOfSpeedToStartPitch,
|
|
Scalar
|
|
);
|
|
|
|
DIRECT_GAME_MODEL_ATTRIBUTE(
|
|
Airplane__GameModel,
|
|
TakeOffSpeed,
|
|
takeOffSpeed,
|
|
Scalar
|
|
);
|
|
|
|
CUSTOM_DIRECT_ATTRIBUTE(
|
|
Airplane,
|
|
TakingOffSFX,
|
|
takingOffSFX,
|
|
int,
|
|
IntClassID
|
|
);
|
|
|
|
CUSTOM_DIRECT_ATTRIBUTE(
|
|
Airplane,
|
|
InAirSFX,
|
|
inAirSFX,
|
|
int,
|
|
IntClassID
|
|
);
|
|
|
|
CUSTOM_DIRECT_ATTRIBUTE(
|
|
Airplane,
|
|
IdleSFX,
|
|
idleSFX,
|
|
int,
|
|
IntClassID
|
|
);
|
|
|
|
DIRECT_GAME_MODEL_ATTRIBUTE(
|
|
Airplane__GameModel,
|
|
MaxClimb,
|
|
maxClimb,
|
|
Scalar
|
|
);
|
|
|
|
DIRECT_GAME_MODEL_ATTRIBUTE(
|
|
Airplane__GameModel,
|
|
MaxDescent,
|
|
maxDescent,
|
|
Scalar
|
|
);
|
|
|
|
DIRECT_GAME_MODEL_ATTRIBUTE(
|
|
Airplane__GameModel,
|
|
TakeOffResource,
|
|
takeOffResource,
|
|
ResourceID
|
|
);
|
|
|
|
DIRECT_GAME_MODEL_ATTRIBUTE(
|
|
Airplane__GameModel,
|
|
TakeOffGroundResource,
|
|
takeOffGroundResource,
|
|
ResourceID
|
|
);
|
|
|
|
DIRECT_GAME_MODEL_ATTRIBUTE(
|
|
Airplane__GameModel,
|
|
LandingResource,
|
|
landingResource,
|
|
ResourceID
|
|
);
|
|
|
|
DIRECT_GAME_MODEL_ATTRIBUTE(
|
|
Airplane__GameModel,
|
|
LandingGroundResource,
|
|
landingGroundResource,
|
|
ResourceID
|
|
);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Airplane::TerminateClass()
|
|
{
|
|
Unregister_Object(DefaultData);
|
|
delete DefaultData;
|
|
DefaultData = NULL;
|
|
delete m_Heights;
|
|
m_Heights = NULL;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Airplane*
|
|
Airplane::Make(
|
|
CreateMessage *message,
|
|
ReplicatorID *base_id
|
|
)
|
|
{
|
|
Check_Object(message);
|
|
gos_PushCurrentHeap(Heap);
|
|
Airplane *new_entity = new
|
|
Airplane(DefaultData, message, base_id, NULL);
|
|
gos_PopCurrentHeap();
|
|
Check_Object(new_entity);
|
|
|
|
Check_Object(EntityManager::GetInstance());
|
|
EntityManager::GetInstance()->AddMover(new_entity);
|
|
|
|
return new_entity;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Replicator::CreateMessage*
|
|
Airplane::SaveMakeMessage(MemoryStream *stream, ResourceFile *res_file)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(stream);
|
|
|
|
stream->AllocateBytes(sizeof(CreateMessage));
|
|
BaseClass::SaveMakeMessage(stream, res_file);
|
|
CreateMessage *message =
|
|
Cast_Pointer(CreateMessage*, stream->GetPointer());
|
|
message->messageLength = sizeof(*message);
|
|
|
|
message->altitude = flyingAltitude;
|
|
return message;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Airplane::Airplane(
|
|
ClassData *class_data,
|
|
CreateMessage *message,
|
|
ReplicatorID *base_id,
|
|
ElementRenderer::Element *element
|
|
):
|
|
Vehicle(class_data, message, base_id, element),
|
|
m_PopupHeight(0),
|
|
m_PopdownHeight(0),
|
|
m_PopupClimbSpeed(0),
|
|
m_crashingEffect(NULL)
|
|
{
|
|
Check_Pointer(this);
|
|
Check_Object(message);
|
|
|
|
HookUpSubsystems();
|
|
CommonCreation(message);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Airplane::CommonCreation(CreateMessage *message)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(message);
|
|
|
|
m_OnGround = true;
|
|
takeOffTargetPosition = Point3D::Identity;
|
|
tiltAngle = 0.0f;
|
|
pitchAngle = 0.0f;
|
|
shouldDie = false;
|
|
hasTakeOffAnimationLoaded = false;
|
|
shouldLeaveReckage = false;
|
|
m_Attacking = false;
|
|
|
|
const GameModel *model = GetGameModel();
|
|
Check_Object(model);
|
|
|
|
|
|
|
|
m_LastState = ExecutionStateEngine::TaxiState;
|
|
|
|
flyingAltitude = message->altitude;
|
|
m_AttackAltitude = 0;
|
|
m_Attacking = false;
|
|
|
|
if(flyingAltitude == 0.0f)
|
|
flyingAltitude = model->flyingAltitude;
|
|
// AdjustAltitude ();
|
|
Max_Clamp (flyingAltitude,800);
|
|
|
|
SetIdle();
|
|
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Airplane::Respawn(Entity__CreateMessage *message)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(message);
|
|
|
|
BaseClass::Respawn(message);
|
|
CreateMessage *airplane_message = Cast_Pointer(CreateMessage *, message);
|
|
CommonCreation(airplane_message);
|
|
}
|
|
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
void
|
|
Airplane::LoadAnimationScripts()
|
|
{
|
|
Vehicle::LoadAnimationScripts();
|
|
|
|
const GameModel *model = GetGameModel();
|
|
Check_Object(model);
|
|
|
|
if (model->animScriptName[0] != NULL)
|
|
{
|
|
hasTakeOffAnimationLoaded = true;
|
|
Check_Object(animStateEngine);
|
|
animStateEngine->RequestState(AirplaneAnimationStateEngine::IdleState);
|
|
}
|
|
else
|
|
{
|
|
hasTakeOffAnimationLoaded = false;
|
|
}
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Airplane::~Airplane()
|
|
{
|
|
Check_Pointer(this);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Airplane::Reuse(
|
|
const CreateMessage *message,
|
|
ReplicatorID *base_id
|
|
)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(message);
|
|
|
|
STOP(("Not implemented"));
|
|
BaseClass::Reuse(message, base_id);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void Airplane::TurnOff (void)
|
|
{
|
|
m_LastState = executionState->GetState ();
|
|
executionState->RequestState(ExecutionStateEngine::AIMotionState);
|
|
}
|
|
|
|
void Airplane::TurnOn (void)
|
|
{
|
|
lastParameterization = gos_GetElapsedTime ();
|
|
executionState->RequestState(m_LastState);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Airplane::PreCollisionExecute(Time till)
|
|
{
|
|
Check_Object(this);
|
|
PRECOLLISION_LOGIC("Airplane");
|
|
|
|
BaseClass::PreCollisionExecute(till);
|
|
UnitVector3D world_down_in_local;
|
|
|
|
//
|
|
//---------------------------------
|
|
// If we aren't executing, stop now
|
|
//---------------------------------
|
|
//
|
|
Check_Object(executionState);
|
|
int pre_state = executionState->GetState();
|
|
Verify(pre_state != ExecutionStateEngine::NeverExecuteState);
|
|
Set_Statistic(Executed_Airplane_Count, Executed_Airplane_Count+1);
|
|
|
|
Scalar time_slice = GetTimeSlice(till);
|
|
Verify(time_slice > 0.0f);
|
|
|
|
switch (pre_state)
|
|
{
|
|
case ExecutionStateEngine::TaxiState:
|
|
GetLocalToWorld().GetWorldDownInLocal(&world_down_in_local);
|
|
localSpaceAcceleration.linearMotion.AddScaled(
|
|
localSpaceAcceleration.linearMotion,
|
|
world_down_in_local,
|
|
g_Gravity
|
|
);
|
|
ComputeForwardSpeed(time_slice);
|
|
UpdateVehiclePosition(time_slice);
|
|
break;
|
|
case ExecutionStateEngine::FlyingMotionState:
|
|
ComputeForwardSpeed(time_slice);
|
|
TiltPlane(time_slice);
|
|
FlyingMovementSimulation(till);
|
|
break;
|
|
|
|
case ExecutionStateEngine::TakingOffMotionState:
|
|
// TakeOffThrusterSimulation(till);
|
|
instantaniousAngularVelocity = Stuff::Vector3D::Identity;
|
|
animationVelocity = Stuff::Point3D::Identity;
|
|
|
|
Check_Object(animStateEngine);
|
|
|
|
if (hasTakeOffAnimationLoaded)
|
|
{
|
|
animStateEngine->RunStates(time_slice);
|
|
TakeOffThrusterSimulation(till, animationVelocity, instantaniousAngularVelocity,false);
|
|
if(animStateEngine->CurrentStateLoopedThisFrame())
|
|
{
|
|
animStateEngine->RequestState(AirplaneAnimationStateEngine::IdleState);
|
|
Check_Object(executionState);
|
|
executionState->RequestState(ExecutionStateEngine::FlyingMotionState);
|
|
currentSpeedMPS = 78.0f; // set to the last animation speed, hack but it works and we are two weeks from shipping.
|
|
m_OnGround = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
animationVelocity.z = 10;
|
|
animationVelocity.y = 10;
|
|
TakeOffThrusterSimulation(till, animationVelocity, instantaniousAngularVelocity,true);
|
|
m_OnGround = false;
|
|
// executionState->RequestState(ExecutionStateEngine::FlyingMotionState);
|
|
}
|
|
break;
|
|
//SPEW(("daberger","AnimVelocity z: %f y: %f", animationVelocity.z, animationVelocity.y));
|
|
|
|
case ExecutionStateEngine::LandingMotionState:
|
|
TiltPlane(time_slice);
|
|
LandingMovementSimulation(till);
|
|
break;
|
|
|
|
case ExecutionStateEngine::CrashingDeathState:
|
|
CrashingDeathMovementSimulation(till);
|
|
break;
|
|
|
|
case ExecutionStateEngine::PopupState:
|
|
PopUpOrDownSimulation(time_slice,m_PopupHeight);
|
|
break;
|
|
|
|
case ExecutionStateEngine::PopdownState:
|
|
PopUpOrDownSimulation(time_slice,m_PopdownHeight);
|
|
break;
|
|
|
|
case ExecutionStateEngine::FloatState:
|
|
FloatSimulation(time_slice);
|
|
break;
|
|
}
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void Airplane::ComputeForwardSpeed(Stuff::Scalar time_slice)
|
|
{
|
|
Check_Object(this);
|
|
const GameModel *model = GetGameModel();
|
|
Check_Object(model);
|
|
|
|
//
|
|
//----------------------------------------------------
|
|
// Set the demands to zero if the vehicle is shut down
|
|
//----------------------------------------------------
|
|
//
|
|
if (vehicleShutDown)
|
|
{
|
|
speedDemand = 0.0f;
|
|
speedDemandKPH = 0.0f;
|
|
}
|
|
|
|
Verify ((model->moveTypeFlag == MWObject__GameModel::FLYER_MOVETYPE)||(model->moveTypeFlag == MWObject__GameModel::HELI_MOVETYPE)||(model->moveTypeFlag == MWObject__GameModel::DROPSHIP_MOVETYPE));
|
|
|
|
//
|
|
//------------------------------------------------------------------------
|
|
// Figure out our desired speed. If we are stopped, set the KPH variables
|
|
// to zero and quit
|
|
//------------------------------------------------------------------------
|
|
//
|
|
if (speedDemand >= 0.0f)
|
|
speedDemandMPS = (speedDemand * GetMaxSpeed());
|
|
else
|
|
speedDemandMPS = -(speedDemand * model->maxReverseSpeed);
|
|
if (speedDemandMPS == 0.0f && currentSpeedMPS == 0.0f)
|
|
{
|
|
speedDemandKPH = 0.0f;
|
|
currentSpeedKPH = 0.0f;
|
|
return;
|
|
}
|
|
|
|
//
|
|
//--------------------------------------------------------------------
|
|
// If we are not going backwards, find out what speed we want after we
|
|
// consider braking
|
|
//--------------------------------------------------------------------
|
|
//
|
|
if (currentSpeedMPS >= 0.0f)
|
|
{
|
|
if (speedDemandMPS > currentSpeedMPS)
|
|
{
|
|
currentSpeedMPS += (model->acceleration * time_slice);
|
|
Max_Clamp(currentSpeedMPS, speedDemandMPS);
|
|
}
|
|
else if (speedDemandMPS < currentSpeedMPS)
|
|
{
|
|
currentSpeedMPS -= (model->decceleration * time_slice);
|
|
Min_Clamp(currentSpeedMPS, speedDemandMPS);
|
|
}
|
|
}
|
|
|
|
else
|
|
{
|
|
|
|
if (speedDemandMPS < currentSpeedMPS)
|
|
{
|
|
currentSpeedMPS -= (model->acceleration * model->reverseAccelerationMultiplier * time_slice);
|
|
Min_Clamp(currentSpeedMPS, speedDemandMPS);
|
|
}
|
|
else if (speedDemandMPS > currentSpeedMPS)
|
|
{
|
|
currentSpeedMPS += (model->decceleration * model->reverseDeccelerationMultiplier * time_slice);
|
|
Max_Clamp(currentSpeedMPS, speedDemandMPS);
|
|
}
|
|
}
|
|
|
|
//
|
|
//----------------------------------------------------
|
|
// Now adjust all this to the limits in the model file
|
|
//----------------------------------------------------
|
|
//
|
|
Clamp(currentSpeedMPS, model->maxReverseSpeed, GetMaxSpeed());
|
|
|
|
//
|
|
//---------------------------
|
|
// Set up the velocity vector
|
|
//---------------------------
|
|
//
|
|
localSpaceVelocity.linearMotion.z = currentSpeedMPS;
|
|
|
|
//
|
|
//----------------------
|
|
// Set the KPH variables
|
|
//----------------------
|
|
//
|
|
currentSpeedKPH = currentSpeedMPS * 3.6f;
|
|
speedDemandKPH = speedDemandMPS * 3.6f;
|
|
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
bool
|
|
Airplane::CollisionHandler(
|
|
Stuff::LinearMatrix4D *new_position,
|
|
Stuff::DynamicArrayOf<CollisionData> *collisions
|
|
)
|
|
{
|
|
Check_Object(this);
|
|
Entity::ExecutionStateEngine *engine = executionState;
|
|
if (engine->GetState() == ExecutionStateEngine::NeverExecuteState)
|
|
{
|
|
Verify(!newCollisions);
|
|
delete collisions;
|
|
return false;
|
|
}
|
|
|
|
Verify(GetInterestLevel() != DormantInterestLevel);
|
|
Verify(EntityManager::GetInstance()->IsInPostCollisionExecution(this));
|
|
|
|
//
|
|
//----------------------------------------------------------
|
|
// If we are destroyed, delete the collision list and return
|
|
//----------------------------------------------------------
|
|
//
|
|
if (IsDestroyed())
|
|
{
|
|
delete collisions;
|
|
Verify(!newCollisions);
|
|
return false;
|
|
}
|
|
|
|
//
|
|
//-----------------------
|
|
// Iterate the collisions
|
|
//-----------------------
|
|
//
|
|
for (int i=0; i<collisions->GetLength(); ++i)
|
|
{
|
|
CollisionData *data = &(*collisions)[i];
|
|
Check_Pointer(data);
|
|
|
|
//
|
|
//-------------------------------------------------------------------
|
|
// Airplanes don't collide with bridges. The don't collide if flying
|
|
//-------------------------------------------------------------------
|
|
//
|
|
Check_Object(executionState);
|
|
if ((executionState->GetState() == ExecutionStateEngine::FlyingMotionState) || // flying airplanes don't collide
|
|
(executionState->GetState() == ExecutionStateEngine::PopupState) ||
|
|
(executionState->GetState() == ExecutionStateEngine::FloatState) ||
|
|
(executionState->GetState() == ExecutionStateEngine::PopdownState))
|
|
continue;
|
|
|
|
//
|
|
//----------------------------------------------
|
|
// If we are crashing, reset to our old position
|
|
//----------------------------------------------
|
|
//
|
|
if (data->m_otherEntity->IsDerivedFrom (Airplane::DefaultData))
|
|
continue;
|
|
if(executionState->GetState() == ExecutionStateEngine::CrashingDeathState)
|
|
{
|
|
Check_Object(entityElement);
|
|
*new_position = entityElement->GetNewLocalToParent();
|
|
Point3D old_translation(entityElement->GetLocalToParent());
|
|
new_position->BuildTranslation(old_translation);
|
|
shouldDie = true;
|
|
shouldLeaveReckage = false;
|
|
DealSplashDamage();
|
|
delete collisions;
|
|
Verify(!newCollisions);
|
|
return true;
|
|
}
|
|
if (data->m_otherEntity->CanBeWalkedOn())
|
|
continue;
|
|
}
|
|
Verify(!newCollisions);
|
|
newCollisions = collisions;
|
|
return false;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Airplane::PostCollisionExecute(Time till)
|
|
{
|
|
Check_Object(this);
|
|
POSTCOLLISION_LOGIC("Airplane");
|
|
|
|
if (executionState->GetState() == ExecutionStateEngine::FlyingMotionState)
|
|
worldSpaceVelocity.linearMotion.Multiply(localSpaceVelocity.linearMotion,GetLocalToWorld());
|
|
lastParameterization = till;
|
|
initialLocalToParent = GetLocalToParent();
|
|
initialWorldSpaceVelocity = worldSpaceVelocity,
|
|
initialWorldSpaceAcceleration = worldSpaceAcceleration;
|
|
|
|
if (executionState->GetState() == ExecutionStateEngine::NeverExecuteState)
|
|
{
|
|
if (oldCollisions)
|
|
delete oldCollisions;
|
|
oldCollisions = NULL;
|
|
if (newCollisions)
|
|
delete newCollisions;
|
|
newCollisions = NULL;
|
|
return;
|
|
}
|
|
|
|
if(shouldDie)
|
|
{
|
|
const GameModel *model = GetGameModel();
|
|
Check_Object(model);
|
|
|
|
DealSplashDamage();
|
|
|
|
if(m_crashingEffect.GetCurrent())
|
|
{
|
|
m_crashingEffect.GetCurrent()->executionState->RequestState(Effect::ExecutionStateEngine::StoppingState);
|
|
m_crashingEffect.Remove();
|
|
m_OnGround = true;
|
|
}
|
|
Entity::ReactToDestruction(InternalDamageObject::DestructionDamageMode,ProjectileDamageType);
|
|
|
|
// SetDestroyedFlag(InternalDamageObject::DestructionDamageMode);
|
|
CreateEffect(model->secondaryDestroyedEffectResource, this);
|
|
if(shouldLeaveReckage)
|
|
{
|
|
if(!m_deathEntity.GetCurrent())
|
|
{
|
|
Entity *death_entity = CreateStaticHermitEntity(model->deathEntityResource);
|
|
if(death_entity)
|
|
{
|
|
m_deathEntity.Remove();
|
|
m_deathEntity.Add(death_entity);
|
|
}
|
|
}
|
|
}
|
|
RemoveCollision();
|
|
if (newCollisions)
|
|
{
|
|
delete newCollisions;
|
|
newCollisions = NULL;
|
|
}
|
|
|
|
// MSL 5.02 bug fix
|
|
// bug fix # 6523 - allow dropships to turn off
|
|
if ( m_AI && executionState->GetState() == Vehicle::ExecutionStateEngine::AIMotionState)
|
|
{
|
|
m_AI->TurnOn();
|
|
}
|
|
|
|
executionState->RequestState(ExecutionStateEngine::NeverExecuteState);
|
|
m_OnGround = true;
|
|
entityElement->SetAlwaysCullMode();
|
|
lastParameterization = till;
|
|
initialLocalToParent = GetLocalToParent();
|
|
SetDead();
|
|
SyncMatrices(true);
|
|
}
|
|
else
|
|
{
|
|
BaseClass::PostCollisionExecute(till);
|
|
}
|
|
}
|
|
|
|
inline Scalar FindTerrainHeight(Line3D& line, Adept::Entity* ignore)
|
|
{
|
|
Normal3D normal;
|
|
Entity::CollisionQuery query(&line, &normal, Entity::CanBeWalkedOnFlag, ignore);
|
|
|
|
CollisionGrid::Instance->ProjectLine(&query);
|
|
|
|
Point3D point;
|
|
line.FindEnd(&point);
|
|
|
|
return (point.y);
|
|
}
|
|
|
|
Scalar FindTerrainHeightFromPoint(const Point3D& point, Adept::Entity* ignore)
|
|
{
|
|
if ((point.x <= MW4AI::MinX) ||
|
|
(point.x >= MW4AI::MaxX) ||
|
|
(point.z <= MW4AI::MinZ) ||
|
|
(point.z >= MW4AI::MaxZ))
|
|
{
|
|
return (0);
|
|
}
|
|
|
|
Line3D line;
|
|
line.m_length = 1200.0f;
|
|
line.m_direction = Vector3D::Down;
|
|
line.SetOrigin(point);
|
|
|
|
return (FindTerrainHeight(line,ignore));
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void Airplane::FlyingMovementSimulation(Stuff::Time till)
|
|
{
|
|
Check_Object(this);
|
|
|
|
const GameModel *model = GetGameModel();
|
|
Scalar time_slice = GetTimeSlice(till);
|
|
Verify(time_slice > 0);
|
|
|
|
// STOP(("Not finished"));
|
|
// ComputeVelocity(time_slice);
|
|
|
|
const LinearMatrix4D &local_to_world = GetLocalToWorld();
|
|
|
|
Point3D old_loc(local_to_world);
|
|
|
|
//
|
|
// add the local adjustment to the current position
|
|
//
|
|
Point3D new_translation;
|
|
Vector3D local_motion;
|
|
local_motion.Multiply(localSpaceVelocity.linearMotion,local_to_world);
|
|
|
|
new_translation = old_loc;
|
|
new_translation.x += local_motion.x * time_slice;
|
|
new_translation.z += local_motion.z * time_slice;
|
|
|
|
UnitVector3D unit_forward;
|
|
local_to_world.GetLocalForwardInWorld(&unit_forward);
|
|
Point3D forward(unit_forward);
|
|
forward *= 25.0f;
|
|
|
|
Point3D point(local_to_world);
|
|
point += forward;
|
|
point.y += 100.0f;
|
|
|
|
Stuff::Scalar first_y(FindTerrainHeightFromPoint(point,this));
|
|
|
|
Point3D point2(local_to_world);
|
|
forward *= 4.0f;
|
|
point2 += forward;
|
|
point2.y += 100.0f;
|
|
|
|
UnitVector3D unit_left;
|
|
local_to_world.GetLocalLeftInWorld(&unit_left);
|
|
Point3D left(unit_left);
|
|
left *= 30.0f;
|
|
|
|
UnitVector3D unit_right;
|
|
local_to_world.GetLocalRightInWorld(&unit_right);
|
|
Point3D right(unit_right);
|
|
right *= 30.0f;
|
|
|
|
Point3D point3(point2);
|
|
|
|
point2 += left;
|
|
point3 += right;
|
|
|
|
Scalar second_y(FindTerrainHeightFromPoint(point2,this));
|
|
Scalar third_y(FindTerrainHeightFromPoint(point3,this));
|
|
|
|
Scalar worst_y(first_y);
|
|
if (second_y > worst_y)
|
|
{
|
|
worst_y = second_y;
|
|
}
|
|
if (third_y > worst_y)
|
|
{
|
|
worst_y = third_y;
|
|
}
|
|
|
|
Scalar delta,change;
|
|
|
|
if (m_Attacking)
|
|
delta = (m_AttackAltitude + worst_y) - old_loc.y;
|
|
else
|
|
delta = (flyingAltitude + worst_y) - old_loc.y;
|
|
|
|
if (delta > 0)
|
|
change = model->maxClimb * time_slice;
|
|
else
|
|
change = model->maxDescent * time_slice;
|
|
|
|
Clamp(delta,-change,change);
|
|
new_translation.y = old_loc.y + delta;
|
|
|
|
//
|
|
// get the current yawpitchroll from the local to world matrix
|
|
//
|
|
Scalar temp = Lerp(model->fullStopTurnRate, model->topSpeedTurnRate, currentSpeedMPS/GetMaxSpeed());
|
|
YawPitchRoll new_rotation(local_to_world);
|
|
temp *= time_slice;
|
|
new_rotation.yaw += yawDemand * temp;
|
|
new_rotation.pitch += pitchDemand * temp;
|
|
new_rotation.roll += rollDemand * temp;
|
|
|
|
// new_rotation = local_to_world;
|
|
new_rotation.yaw += (localSpaceVelocity.angularMotion.y * time_slice);
|
|
new_rotation.roll += (localSpaceVelocity.angularMotion.z * time_slice);
|
|
// new_rotation.pitch += (localSpaceVelocity.angularMotion.x * time_slice);
|
|
new_rotation.roll = -tiltAngle;
|
|
new_rotation.pitch = pitchAngle;
|
|
|
|
|
|
//
|
|
//----------------------------------------------
|
|
// Adjust position from network
|
|
//----------------------------------------------
|
|
//
|
|
|
|
YawPitchRoll correction_angle;
|
|
Point3D correction_position;
|
|
|
|
GetNetworkAdjustment(time_slice, correction_position, correction_angle);
|
|
|
|
new_translation += correction_position;
|
|
new_rotation.yaw.angle += correction_angle.yaw.angle;
|
|
new_rotation.pitch.angle += correction_angle.pitch.angle;
|
|
new_rotation.roll.angle += correction_angle.roll.angle;
|
|
|
|
|
|
//
|
|
//----------------------------------------------
|
|
// Set the new position
|
|
//----------------------------------------------
|
|
//
|
|
|
|
// worldSpaceVelocity.linearMotion.Multiply(localSpaceVelocity.linearMotion,GetLocalToWorld());
|
|
|
|
LinearMatrix4D new_local_to_world = LinearMatrix4D::Identity;
|
|
new_local_to_world.BuildTranslation(new_translation);
|
|
new_local_to_world.BuildRotation(new_rotation);
|
|
|
|
SetNewLocalToParent(new_local_to_world);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void Airplane::Land(void)
|
|
{
|
|
Check_Object(this);
|
|
}
|
|
|
|
void
|
|
Airplane::TakeOff(Stuff::Scalar runway_distance)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(executionState);
|
|
Check_Object(animStateEngine);
|
|
|
|
executionState->RequestState(ExecutionStateEngine::TakingOffMotionState);
|
|
m_OnGround = false;
|
|
|
|
if (hasTakeOffAnimationLoaded)
|
|
animStateEngine->RequestState(AirplaneAnimationStateEngine::TakeOffState);
|
|
}
|
|
|
|
void
|
|
Airplane::Popup(Stuff::Scalar to_height)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(executionState);
|
|
Check_Object(animStateEngine);
|
|
|
|
if (executionState->GetState() == Airplane::ExecutionStateEngine::PopupState)
|
|
{
|
|
return;
|
|
}
|
|
|
|
m_PopdownHeight = ((Stuff::Point3D)GetLocalToWorld()).y;
|
|
m_PopupHeight = to_height;
|
|
|
|
m_PopupClimbSpeed = 0;
|
|
m_YPR = GetLocalToWorld();
|
|
|
|
executionState->RequestState(ExecutionStateEngine::PopupState);
|
|
m_OnGround = false;
|
|
}
|
|
|
|
void
|
|
Airplane::Popdown(Stuff::Scalar to_height)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(executionState);
|
|
Check_Object(animStateEngine);
|
|
|
|
if (executionState->GetState() == Airplane::ExecutionStateEngine::PopdownState)
|
|
{
|
|
return;
|
|
}
|
|
|
|
m_PopupHeight = ((Stuff::Point3D)GetLocalToWorld()).y;
|
|
m_PopdownHeight = to_height;
|
|
|
|
m_PopupClimbSpeed = 0;
|
|
m_YPR = GetLocalToWorld();
|
|
|
|
executionState->RequestState(ExecutionStateEngine::PopdownState);
|
|
m_OnGround = false;
|
|
}
|
|
|
|
void
|
|
Airplane::Float(const Stuff::Point3D& dest)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(executionState);
|
|
Check_Object(animStateEngine);
|
|
|
|
if ((executionState->GetState() == Airplane::ExecutionStateEngine::FloatState) &&
|
|
(m_FloatTargetPosition == dest))
|
|
{
|
|
return;
|
|
}
|
|
|
|
m_YPR = GetLocalToWorld();
|
|
|
|
m_FloatSpeed = 0;
|
|
|
|
m_FloatTargetPosition = dest;
|
|
executionState->RequestState(ExecutionStateEngine::FloatState);
|
|
m_OnGround = false;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void Airplane::TakeOffThrusterSimulation(Stuff::Time till, const Stuff::Vector3D& new_velocity, const Stuff::Vector3D& instantanious_angular_velocity,bool canswitch)
|
|
{
|
|
Check_Object(this);
|
|
|
|
Scalar time_slice = GetTimeSlice(till);
|
|
if (canswitch)
|
|
{
|
|
executionState->RequestState(ExecutionStateEngine::FlyingMotionState);
|
|
}
|
|
|
|
//instantanious_angular_velocity.Divide(instantanious_angular_velocity, time_slice);
|
|
|
|
|
|
//
|
|
// get the local to world matrix from the locator
|
|
//
|
|
const Stuff::LinearMatrix4D &local_to_world = GetLocalToWorld();
|
|
|
|
//
|
|
// make a vector of where we want to go
|
|
//
|
|
Vector3D point = Point3D::Identity;
|
|
point.Multiply( new_velocity, time_slice );
|
|
|
|
//
|
|
// put it in local space
|
|
//
|
|
Vector3D adj;
|
|
adj.Multiply(point, local_to_world);
|
|
|
|
//
|
|
// add the local adjustment to the current position
|
|
//
|
|
Point3D new_translation;
|
|
new_translation = local_to_world;
|
|
new_translation += adj;
|
|
|
|
//
|
|
// get the current yawpitchroll from the local to world matrix
|
|
//
|
|
YawPitchRoll new_rotation(YawPitchRoll::Identity);
|
|
new_rotation = local_to_world;
|
|
|
|
|
|
//
|
|
// then add in the yaw, pitch, and roll demands from the animation
|
|
//
|
|
|
|
new_rotation.yaw += instantanious_angular_velocity.y * time_slice;
|
|
new_rotation.pitch += instantanious_angular_velocity.x * time_slice;
|
|
new_rotation.roll += instantanious_angular_velocity.z * time_slice;
|
|
|
|
|
|
//
|
|
// create a new matrix and build the translation and rotation
|
|
//
|
|
|
|
|
|
//
|
|
//----------------------------------------------
|
|
// Adjust position from network
|
|
//----------------------------------------------
|
|
//
|
|
|
|
YawPitchRoll correction_angle;
|
|
Point3D correction_position;
|
|
|
|
GetNetworkAdjustment(time_slice, correction_position, correction_angle);
|
|
|
|
|
|
new_translation += correction_position;
|
|
new_rotation.yaw.angle += correction_angle.yaw.angle;
|
|
new_rotation.pitch.angle += correction_angle.pitch.angle;
|
|
new_rotation.roll.angle += correction_angle.roll.angle;
|
|
|
|
//
|
|
//----------------------------------------------
|
|
// Set the new position
|
|
//----------------------------------------------
|
|
//
|
|
|
|
LinearMatrix4D new_local_to_world;
|
|
new_local_to_world.BuildTranslation(new_translation);
|
|
new_local_to_world.BuildRotation(new_rotation);
|
|
|
|
|
|
//
|
|
// set the local to parent to the new matrix created above
|
|
//
|
|
|
|
SetNewLocalToParent(new_local_to_world);
|
|
|
|
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Airplane::TakeOffMovementSimulation(Stuff::Time till)
|
|
{
|
|
|
|
Check_Object(this);
|
|
Scalar time_slice = GetTimeSlice(till);
|
|
Verify(time_slice > 0.0f);
|
|
|
|
const GameModel *model = GetGameModel();
|
|
Check_Object(model);
|
|
|
|
//
|
|
//-------------------------
|
|
// Compute the new location
|
|
//-------------------------
|
|
//
|
|
localSpaceVelocity.linearMotion.z += speedDemand * model->thrusterAcceleration * time_slice;
|
|
Clamp(localSpaceVelocity.linearMotion.z, 0.0f, GetMaxSpeed());
|
|
worldSpaceVelocity.linearMotion.Multiply(localSpaceVelocity.linearMotion, GetLocalToWorld());
|
|
Point3D plane_in_world(GetLocalToWorld());
|
|
plane_in_world.AddScaled(plane_in_world, worldSpaceVelocity.linearMotion, time_slice);
|
|
LinearMatrix4D local_to_new_world(true);
|
|
|
|
//
|
|
//-------------------------
|
|
// Compute the new rotation
|
|
//-------------------------
|
|
//
|
|
localSpaceVelocity.angularMotion.x = pitchDemand;
|
|
localSpaceVelocity.angularMotion.y = (yawDemand * model->fullStopTurnRate);
|
|
localSpaceVelocity.angularMotion.z = (rollDemand * model->fullStopTurnRate);
|
|
worldSpaceVelocity.angularMotion.Multiply(localSpaceVelocity.angularMotion, GetLocalToWorld());
|
|
|
|
//
|
|
//---------------------------------------------------
|
|
// Make a matrix representing the rotation this frame
|
|
//---------------------------------------------------
|
|
//
|
|
Vector3D world_angular_step;
|
|
world_angular_step.Multiply(worldSpaceVelocity.angularMotion, time_slice);
|
|
UnitQuaternion spin;
|
|
spin = world_angular_step;
|
|
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
// Convert the EulerAngles into a matrix and create the new rotation matrix
|
|
// through concatenation
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
UnitQuaternion old_world_rotation;
|
|
old_world_rotation = initialLocalToParent;
|
|
UnitQuaternion new_world_rotation;
|
|
new_world_rotation.Multiply(old_world_rotation, spin);
|
|
|
|
//
|
|
//----------------------------------------------
|
|
// Adjust position from network
|
|
//----------------------------------------------
|
|
//
|
|
|
|
YawPitchRoll correction_angle;
|
|
Point3D correction_position;
|
|
|
|
GetNetworkAdjustment(time_slice, correction_position, correction_angle);
|
|
|
|
YawPitchRoll new_rotation;
|
|
new_rotation = new_world_rotation;
|
|
|
|
plane_in_world += correction_position;
|
|
new_rotation.yaw.angle += correction_angle.yaw.angle;
|
|
new_rotation.pitch.angle += correction_angle.pitch.angle;
|
|
new_rotation.roll.angle += correction_angle.roll.angle;
|
|
|
|
//
|
|
//----------------------------------------------
|
|
// Set the new position
|
|
//----------------------------------------------
|
|
//
|
|
|
|
|
|
local_to_new_world.BuildTranslation(plane_in_world);
|
|
local_to_new_world.BuildRotation(new_rotation);
|
|
SetNewLocalToParent(local_to_new_world);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Airplane::CrashingDeathMovementSimulation(Stuff::Time till)
|
|
{
|
|
|
|
Check_Object(this);
|
|
Scalar time_slice = GetTimeSlice(till);
|
|
Verify(time_slice > 0.0f);
|
|
|
|
Vector3D new_speed = localSpaceVelocity.linearMotion;
|
|
|
|
UnitVector3D world_down_in_local,world_forward_in_local;
|
|
Vector3D tempvec = Vector3D::Identity;
|
|
GetLocalToWorld().GetWorldDownInLocal(&world_down_in_local);
|
|
GetLocalToWorld().GetWorldForwardInLocal (&world_forward_in_local);
|
|
|
|
// new_speed.AddScaled (tempvec,world_forward_in_local,currentSpeedMPS*time_slice);
|
|
new_speed.AddScaled (new_speed,world_down_in_local,g_Gravity*time_slice);
|
|
|
|
// new_speed.y -= g_Gravity * time_slice;
|
|
// new_speed.z = Fabs(new_speed.z);
|
|
|
|
// localSpaceVelocity.linearMotion= new_speed;
|
|
worldSpaceVelocity.linearMotion.Multiply(new_speed, GetLocalToWorld());
|
|
|
|
const Stuff::LinearMatrix4D &local_to_world = GetLocalToWorld();
|
|
|
|
Vector3D rotation_vector;
|
|
rotation_vector.x = 1.0f;
|
|
rotation_vector.y = 0.0f;
|
|
rotation_vector.z = 0.0f;
|
|
localSpaceVelocity.angularMotion = rotation_vector;
|
|
worldSpaceVelocity.angularMotion.Multiply(rotation_vector, GetLocalToWorld());
|
|
|
|
Point3D new_translation;
|
|
Vector3D local_motion;
|
|
local_motion.Multiply(localSpaceVelocity.linearMotion, GetLocalToWorld());
|
|
new_translation = local_to_world;
|
|
new_translation.x += local_motion.x * time_slice;
|
|
new_translation.y += local_motion.y * time_slice;
|
|
new_translation.z += local_motion.z * time_slice;
|
|
|
|
//
|
|
// get the current yawpitchroll from the local to world matrix
|
|
//
|
|
YawPitchRoll new_rotation(YawPitchRoll::Identity);
|
|
new_rotation = local_to_world;
|
|
new_rotation.yaw += (localSpaceVelocity.angularMotion.y * time_slice);
|
|
new_rotation.pitch += (localSpaceVelocity.angularMotion.x * time_slice);
|
|
Max_Clamp(new_rotation.pitch, 1.0f);
|
|
new_rotation.roll += (localSpaceVelocity.angularMotion.z * time_slice);
|
|
|
|
LinearMatrix4D new_local_to_world=LinearMatrix4D::Identity;
|
|
|
|
|
|
//
|
|
//----------------------------------------------
|
|
// Adjust position from network
|
|
//----------------------------------------------
|
|
//
|
|
|
|
YawPitchRoll correction_angle;
|
|
Point3D correction_position;
|
|
|
|
GetNetworkAdjustment(time_slice, correction_position, correction_angle);
|
|
|
|
new_translation += correction_position;
|
|
new_rotation.yaw.angle += correction_angle.yaw.angle;
|
|
new_rotation.pitch.angle += correction_angle.pitch.angle;
|
|
new_rotation.roll.angle += correction_angle.roll.angle;
|
|
|
|
|
|
new_local_to_world.BuildTranslation(new_translation);
|
|
new_local_to_world.BuildRotation(new_rotation);
|
|
|
|
|
|
Stuff::Line3D line;
|
|
UnitVector3D forward;
|
|
new_local_to_world.GetLocalForwardInWorld(&forward);
|
|
line.m_length = 3.5f;
|
|
line.m_direction = forward;
|
|
Point3D old_translation(GetLocalToWorld());
|
|
line.m_origin = old_translation;
|
|
|
|
|
|
|
|
SetNewLocalToParent(new_local_to_world);
|
|
|
|
//
|
|
// Prepare query
|
|
//
|
|
Stuff::Normal3D normal;
|
|
CollisionQuery query(&line, &normal, CanBeWalkedOnFlag, this);
|
|
|
|
//
|
|
// Cast ray
|
|
//
|
|
Adept::Entity *entity_hit;
|
|
Check_Object(CollisionGrid::Instance);
|
|
entity_hit = CollisionGrid::Instance->ProjectLine(&query);
|
|
|
|
if(entity_hit != NULL)
|
|
{
|
|
shouldDie = true;
|
|
shouldLeaveReckage = true;
|
|
}
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Stuff::Point3D&
|
|
Airplane::EstimateFuturePosition(
|
|
Stuff::Point3D *new_position,
|
|
Stuff::Scalar seconds,
|
|
bool consider_terrain
|
|
)
|
|
{
|
|
Check_Object(this);
|
|
Check_Pointer(new_position);
|
|
|
|
//
|
|
//-------------------------------------------------
|
|
// If we aren't moving, return our current position
|
|
//-------------------------------------------------
|
|
//
|
|
*new_position = GetLocalToWorld();
|
|
if ((Small_Enough(currentSpeedMPS)) || (IsDestroyed() == true))
|
|
return *new_position;
|
|
|
|
//
|
|
//--------------------------
|
|
// Project our forward speed
|
|
//--------------------------
|
|
//
|
|
Stuff::UnitVector3D local_forward;
|
|
GetLocalToWorld().GetLocalForwardInWorld(&local_forward);
|
|
new_position->AddScaled(*new_position, local_forward, seconds * currentSpeedMPS);
|
|
|
|
//
|
|
//-------------------------------------------------------------
|
|
// Assume that we swerve left at 1 mps at full stick deflection
|
|
//
|
|
// NOTE: This looks like doo-doo too
|
|
//-------------------------------------------------------------
|
|
//
|
|
Stuff::UnitVector3D local_left;
|
|
GetLocalToWorld().GetLocalLeftInWorld(&local_left);
|
|
new_position->AddScaled(*new_position, local_left, seconds * yawDemand);
|
|
|
|
return *new_position;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void Airplane::LandingMovementSimulation(Stuff::Time till)
|
|
{
|
|
Check_Object(this);
|
|
|
|
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void Airplane::TiltPlane(Stuff::Scalar time_slice)
|
|
{
|
|
const GameModel *model = GetGameModel();
|
|
|
|
Scalar max_turn_band = model->fullStopTurnRate;
|
|
Scalar min_turn_band = max_turn_band * model->percentageOfTurnToStartTilt;
|
|
|
|
Scalar max_speed_band = GetMaxSpeed();
|
|
Scalar min_speed_band = max_speed_band * model->percentageOfSpeedToStartTilt;
|
|
|
|
tiltRequest = 0.0f;
|
|
Scalar speed_ratio = 0.0f;
|
|
Scalar turn_ratio = 0.0f;
|
|
|
|
if (yawDemand*model->fullStopTurnRate > min_turn_band || yawDemand*model->fullStopTurnRate < -min_turn_band)
|
|
{
|
|
if (currentSpeedMPS > min_speed_band)
|
|
{
|
|
speed_ratio = (currentSpeedMPS - min_speed_band)/(max_speed_band - min_speed_band);
|
|
Max_Clamp(speed_ratio, 1.0f);
|
|
|
|
if (yawDemand > 0)
|
|
{
|
|
turn_ratio = (yawDemand*model->fullStopTurnRate - min_turn_band)/(max_turn_band - min_turn_band);
|
|
Max_Clamp(turn_ratio, 1.0f);
|
|
}
|
|
else
|
|
{
|
|
turn_ratio = -(-yawDemand*model->fullStopTurnRate - min_turn_band)/(max_turn_band - min_turn_band);
|
|
Min_Clamp(turn_ratio, -1.0f);
|
|
}
|
|
|
|
tiltRequest = model->tiltDegree * turn_ratio * speed_ratio;
|
|
}
|
|
}
|
|
|
|
if (tiltAngle < tiltRequest)
|
|
{
|
|
tiltAngle += (model->tiltSpeed*time_slice);
|
|
Max_Clamp(tiltAngle, tiltRequest);
|
|
}
|
|
else if (tiltAngle > tiltRequest)
|
|
{
|
|
tiltAngle -= (model->tiltSpeed*time_slice);
|
|
Min_Clamp(tiltAngle, tiltRequest);
|
|
}
|
|
|
|
Scalar max_pitch_speed_band = GetMaxSpeed();
|
|
Scalar min_pitch_speed_band = max_pitch_speed_band * model->percentageOfSpeedToStartPitch;
|
|
|
|
pitchRequest = 0.0f;
|
|
Scalar pitch_speed_ratio = 0.0f;
|
|
|
|
if (currentSpeedMPS > min_speed_band)
|
|
{
|
|
pitch_speed_ratio = (currentSpeedMPS - min_pitch_speed_band)/(max_pitch_speed_band - min_pitch_speed_band);
|
|
Max_Clamp(pitch_speed_ratio, 1.0f);
|
|
|
|
pitchRequest = model->pitchDegree * pitch_speed_ratio;
|
|
}
|
|
if (pitchAngle < pitchRequest)
|
|
{
|
|
pitchAngle += (model->pitchSpeed*time_slice);
|
|
Max_Clamp(pitchAngle, pitchRequest);
|
|
}
|
|
else if (pitchAngle > pitchRequest)
|
|
{
|
|
pitchAngle -= (model->pitchSpeed*time_slice);
|
|
Min_Clamp(pitchAngle, pitchRequest);
|
|
}
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
void
|
|
Airplane::ReactToDestruction(int damage_mode, int damage_type)
|
|
{
|
|
// if (!IsDestroyed())
|
|
// {
|
|
// Check_Object(executionState);
|
|
|
|
// }
|
|
switch(damage_mode)
|
|
{
|
|
case InternalDamageObject::DestructionDamageMode:
|
|
{
|
|
if((!IsDestroyed()) && (executionState->GetState() != ExecutionStateEngine::CrashingDeathState))
|
|
{
|
|
Check_Object(executionState);
|
|
executionState->RequestState(ExecutionStateEngine::CrashingDeathState);
|
|
if(m_AI)
|
|
{
|
|
Check_Object(m_AI);
|
|
m_AI->Die();
|
|
}
|
|
|
|
const GameModel *model = GetGameModel();
|
|
Check_Object(model);
|
|
Effect *effect;
|
|
effect = CreateEffect(model->destroyedEffectResource, this, true);
|
|
if(effect)
|
|
m_crashingEffect.Add(effect);
|
|
|
|
// DestroyChildren();
|
|
// Entity::ReactToDestruction(damage_mode, damage_type);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef LAB_ONLY
|
|
if (MW4AI::Statistics::Enabled() == true)
|
|
{
|
|
MW4AI::Statistics::NotifyDestroyed(objectID);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
void
|
|
Airplane::TestInstance() const
|
|
{
|
|
Verify(IsDerivedFrom(DefaultData));
|
|
}
|
|
|
|
void Airplane::AdjustAltitude (void)
|
|
{
|
|
|
|
if (flyingAltitude < MW4AI::g_MaxBuildingHeight)
|
|
{
|
|
flyingAltitude = MW4AI::g_MaxBuildingHeight+10;
|
|
}
|
|
Max_Clamp (flyingAltitude,800);
|
|
#if 0
|
|
stlport::vector<Scalar>::iterator iter;
|
|
Scalar min,max;
|
|
bool flag;
|
|
min = MW4AI::g_MaxBuildingHeight;
|
|
max = min;
|
|
flag = false;
|
|
for (iter = m_Heights->begin ();iter != m_Heights->end ();iter++)
|
|
{
|
|
if (*iter < min)
|
|
min = *iter;
|
|
if (*iter > max)
|
|
max = *iter;
|
|
if (!flag)
|
|
{
|
|
if (((flyingAltitude+PlaneHeightSlotSize) > *iter) && ((flyingAltitude-PlaneHeightSlotSize) < *iter))
|
|
{
|
|
flag = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
flyingAltitude = max + PlaneHeightSlotSize;
|
|
m_Heights->push_back (flyingAltitude);
|
|
#endif
|
|
}
|
|
|
|
void
|
|
Airplane::PopUpOrDownSimulation(Stuff::Scalar time_slice, Stuff::Scalar height)
|
|
{
|
|
//
|
|
//-------------------------
|
|
// Determine our current position
|
|
//-------------------------
|
|
//
|
|
Stuff::Point3D my_pos(GetLocalToWorld());
|
|
|
|
//
|
|
//-------------------------
|
|
// Figure out whether we want to move up or down
|
|
//-------------------------
|
|
//
|
|
Stuff::Scalar vertical_velocity(0);
|
|
if (height > my_pos.y)
|
|
{
|
|
vertical_velocity = GetGameModel()->maxClimb;
|
|
}
|
|
else
|
|
{
|
|
vertical_velocity = -(GetGameModel()->maxDescent);
|
|
}
|
|
|
|
//
|
|
//-------------------------
|
|
// Set the current fall/climb speed, using acceleration when we start moving and a scaled difference when we're near the destination height
|
|
//-------------------------
|
|
//
|
|
if (Stuff::Fabs(my_pos.y - height) < 8.0f)
|
|
{
|
|
m_PopupClimbSpeed = (vertical_velocity * (Stuff::Fabs(my_pos.y - height) / 8.0f));
|
|
}
|
|
else
|
|
{
|
|
m_PopupClimbSpeed += vertical_velocity * time_slice * 0.4f /* magic number to make it accelerate slowly */;
|
|
}
|
|
Clamp(m_PopupClimbSpeed,-(GetGameModel()->maxDescent),GetGameModel()->maxClimb);
|
|
|
|
//
|
|
//-------------------------
|
|
// Compute the new location
|
|
//-------------------------
|
|
//
|
|
localSpaceVelocity.linearMotion.x = 0;
|
|
localSpaceVelocity.linearMotion.y = m_PopupClimbSpeed;
|
|
localSpaceVelocity.linearMotion.z = 0;
|
|
worldSpaceVelocity.linearMotion.Multiply(localSpaceVelocity.linearMotion,GetLocalToWorld());
|
|
|
|
Stuff::LinearMatrix4D new_local_to_parent(GetLocalToWorld());
|
|
|
|
my_pos.AddScaled(my_pos,worldSpaceVelocity.linearMotion,time_slice);
|
|
|
|
m_YPR.yaw += yawDemand * time_slice;
|
|
m_YPR.pitch += pitchDemand * GetGameModel()->fullStopTurnRate * time_slice;
|
|
m_YPR.roll += rollDemand * GetGameModel()->fullStopTurnRate * time_slice;
|
|
|
|
Clamp(m_YPR.pitch,-0.35f,0.35f);
|
|
|
|
//
|
|
//----------------------------------------------
|
|
// Adjust position from network
|
|
//----------------------------------------------
|
|
//
|
|
|
|
YawPitchRoll correction_angle;
|
|
Point3D correction_position;
|
|
|
|
GetNetworkAdjustment(time_slice, correction_position, correction_angle);
|
|
|
|
my_pos += correction_position;
|
|
m_YPR.yaw.angle += correction_angle.yaw.angle;
|
|
m_YPR.pitch.angle += correction_angle.pitch.angle;
|
|
m_YPR.roll.angle += correction_angle.roll.angle;
|
|
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
// Plug it all into the matrix and make it happen
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
new_local_to_parent.BuildTranslation(my_pos);
|
|
new_local_to_parent.BuildRotation(m_YPR);
|
|
SetNewLocalToParent(new_local_to_parent);
|
|
}
|
|
|
|
void
|
|
Airplane::FloatSimulation(Stuff::Scalar time_slice)
|
|
{
|
|
//
|
|
//-------------------------
|
|
// Determine our current position
|
|
//-------------------------
|
|
//
|
|
Stuff::Point3D my_pos(GetLocalToWorld());
|
|
|
|
//
|
|
//-------------------------
|
|
// Determine the delta to where we want to be
|
|
//-------------------------
|
|
//
|
|
Stuff::Scalar height = GetHeightAtPoint(m_FloatTargetPosition,this);
|
|
if (height == -100000.0f)
|
|
{
|
|
height = my_pos.y;
|
|
}
|
|
else
|
|
{
|
|
height += flyingAltitude;
|
|
}
|
|
|
|
Stuff::Point3D delta;
|
|
delta.Subtract(m_FloatTargetPosition,my_pos);
|
|
delta.y = height - my_pos.y;
|
|
|
|
//
|
|
//-------------------------
|
|
// Determine our velocity
|
|
//-------------------------
|
|
//
|
|
const Stuff::Scalar max_throttle_multiplier(0.8f);
|
|
const Stuff::Scalar distance_to_slow_down(25.0f);
|
|
|
|
if (delta.GetApproximateLength() < distance_to_slow_down)
|
|
{
|
|
m_FloatSpeed = GetMaxSpeed() * max_throttle_multiplier * (delta.GetApproximateLength() / distance_to_slow_down);
|
|
|
|
if (m_YPR.roll < 0)
|
|
{
|
|
rollDemand = -(m_YPR.roll);
|
|
}
|
|
else
|
|
{
|
|
rollDemand = m_YPR.roll;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_FloatSpeed += GetGameModel()->acceleration * time_slice;
|
|
Clamp(m_FloatSpeed,0,GetMaxSpeed() * max_throttle_multiplier);
|
|
|
|
if (YawToPoint(GetLocalToWorld(),m_FloatTargetPosition) < 0)
|
|
{
|
|
if (m_YPR.roll < 0.2f)
|
|
{
|
|
rollDemand = 0.5f;
|
|
}
|
|
else
|
|
{
|
|
rollDemand = -0.1f;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (m_YPR.roll > -0.2f)
|
|
{
|
|
rollDemand = -0.5f;
|
|
}
|
|
else
|
|
{
|
|
rollDemand = 0.1f;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (Small_Enough(delta.GetLengthSquared()) == true)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
//-------------------------
|
|
// Multiply the delta
|
|
//-------------------------
|
|
//
|
|
delta.Normalize(delta);
|
|
delta *= m_FloatSpeed;
|
|
|
|
//
|
|
//-------------------------
|
|
// Compute the new location
|
|
//-------------------------
|
|
//
|
|
worldSpaceVelocity.linearMotion = delta;
|
|
localSpaceVelocity.linearMotion.MultiplyByInverse(worldSpaceVelocity.linearMotion,GetLocalToWorld());
|
|
|
|
Stuff::LinearMatrix4D new_local_to_parent(GetLocalToWorld());
|
|
|
|
my_pos.AddScaled(my_pos,worldSpaceVelocity.linearMotion,time_slice);
|
|
|
|
m_YPR.yaw += yawDemand * time_slice;
|
|
m_YPR.pitch += pitchDemand * GetGameModel()->fullStopTurnRate * time_slice;
|
|
m_YPR.roll += rollDemand * GetGameModel()->fullStopTurnRate * time_slice;
|
|
Clamp(m_YPR.roll,-0.2f,0.2f);
|
|
Clamp(m_YPR.pitch,-0.35f,0.35f);
|
|
|
|
|
|
//
|
|
//----------------------------------------------
|
|
// Adjust position from network
|
|
//----------------------------------------------
|
|
//
|
|
|
|
YawPitchRoll correction_angle;
|
|
Point3D correction_position;
|
|
|
|
GetNetworkAdjustment(time_slice, correction_position, correction_angle);
|
|
|
|
my_pos += correction_position;
|
|
m_YPR.yaw.angle += correction_angle.yaw.angle;
|
|
m_YPR.pitch.angle += correction_angle.pitch.angle;
|
|
m_YPR.roll.angle += correction_angle.roll.angle;
|
|
|
|
Stuff::Point3D p = my_pos;
|
|
p.x += 10;
|
|
p.z += 10;
|
|
Stuff::Scalar y_1(FindTerrainHeightFromPoint(p,this));
|
|
p.x -= 20;
|
|
p.z -= 20;
|
|
Stuff::Scalar y_2(FindTerrainHeightFromPoint(p,this));
|
|
|
|
Stuff::Scalar y_delta = (flyingAltitude + ((y_1 + y_2) * 0.5f)) - my_pos.y;
|
|
Stuff::Scalar change = 0;
|
|
|
|
const GameModel *model = GetGameModel();
|
|
if (y_delta > 0)
|
|
change = model->maxClimb * time_slice;
|
|
else
|
|
change = model->maxDescent * time_slice;
|
|
|
|
Clamp(y_delta,-change,change);
|
|
my_pos.y += y_delta;
|
|
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
// Plug it all into the matrix and make it happen
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
|
|
new_local_to_parent.BuildTranslation(my_pos);
|
|
new_local_to_parent.BuildRotation(m_YPR);
|
|
SetNewLocalToParent(new_local_to_parent);
|
|
}
|
|
|
|
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
void Airplane::GetNetworkPosition(Stuff::Point3D ¤t_position, Stuff::YawPitchRoll ¤t_rotation)
|
|
{
|
|
int pre_state = executionState->GetState();
|
|
|
|
switch(pre_state)
|
|
{
|
|
case ExecutionStateEngine::PopupState:
|
|
case ExecutionStateEngine::PopdownState:
|
|
case ExecutionStateEngine::FloatState:
|
|
current_position = GetLocalToWorld();
|
|
current_rotation = m_YPR;
|
|
break;
|
|
|
|
default:
|
|
current_position = GetLocalToWorld();
|
|
current_rotation = GetLocalToWorld();
|
|
break;
|
|
}
|
|
|
|
|
|
|
|
}
|