Initial import of Red Planet v4.10 Win32 source
Imports the current Win32 source for the pod-racing game 'Red Planet', built on the MUNGA engine and its L4 (Win32/DirectX) platform layer: - MUNGA / MUNGA_L4: cross-platform engine core and Win32 backend - RP / RP_L4: Red Planet game logic and Win32 application - DivLoader, Setup1: asset loader and installer project - lib, MUNGA_L4/openal, MUNGA_L4/sos: third-party audio dependencies Removed stale Subversion metadata and added .gitignore/.gitattributes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+958
@@ -0,0 +1,958 @@
|
||||
#include "rp.h"
|
||||
#pragma hdrstop
|
||||
|
||||
#include "vtvmppr.h"
|
||||
#include "vtvpwr.h"
|
||||
#include "..\munga\icom.h"
|
||||
#include "..\munga\app.h"
|
||||
#include "rpplayer.h"
|
||||
#include "vtv.h"
|
||||
|
||||
//#############################################################################
|
||||
// Shared Data Support
|
||||
//
|
||||
VTVControlsMapper::SharedData
|
||||
VTVControlsMapper::DefaultData(
|
||||
VTVControlsMapper::GetClassDerivations(),
|
||||
VTVControlsMapper::GetMessageHandlers(),
|
||||
VTVControlsMapper::GetAttributeIndex(),
|
||||
VTVControlsMapper::StateCount
|
||||
);
|
||||
|
||||
Derivation* VTVControlsMapper::GetClassDerivations()
|
||||
{
|
||||
static Derivation classDerivations(VTVSubsystem::GetClassDerivations(), "VTVControlsMapper");
|
||||
return &classDerivations;
|
||||
}
|
||||
|
||||
//#############################################################################
|
||||
// Messaging Support
|
||||
//
|
||||
const Receiver::HandlerEntry
|
||||
VTVControlsMapper::MessageHandlerEntries[]=
|
||||
{
|
||||
MESSAGE_ENTRY(VTVControlsMapper, ConfigureControls),
|
||||
MESSAGE_ENTRY(VTVControlsMapper, ConfigureSideSlipMappables),
|
||||
MESSAGE_ENTRY(VTVControlsMapper, ChooseSideSlip),
|
||||
MESSAGE_ENTRY(VTVControlsMapper, ConfigureLiftCutMappables),
|
||||
MESSAGE_ENTRY(VTVControlsMapper, ChooseLiftCut),
|
||||
MESSAGE_ENTRY(VTVControlsMapper, ConfigureHornMappables),
|
||||
MESSAGE_ENTRY(VTVControlsMapper, ChooseHorn),
|
||||
MESSAGE_ENTRY(VTVControlsMapper, ActivateHorn),
|
||||
MESSAGE_ENTRY(VTVControlsMapper, ConfigurePTTMappables),
|
||||
MESSAGE_ENTRY(VTVControlsMapper, ChoosePTT),
|
||||
MESSAGE_ENTRY(VTVControlsMapper, ActivatePTT),
|
||||
MESSAGE_ENTRY(VTVControlsMapper, ToggleReticle)
|
||||
};
|
||||
|
||||
Receiver::MessageHandlerSet& VTVControlsMapper::GetMessageHandlers()
|
||||
{
|
||||
static Receiver::MessageHandlerSet messageHandlers(ELEMENTS(VTVControlsMapper::MessageHandlerEntries), VTVControlsMapper::MessageHandlerEntries, VTVSubsystem::GetMessageHandlers());
|
||||
return messageHandlers;
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
void
|
||||
VTVControlsMapper::ConfigureControlsMessageHandler(
|
||||
#if DEBUG_LEVEL>0
|
||||
ReceiverDataMessageOf<ControlsButton> *message
|
||||
#else
|
||||
ReceiverDataMessageOf<ControlsButton> *
|
||||
#endif
|
||||
)
|
||||
{
|
||||
Check(this);
|
||||
Check(message);
|
||||
|
||||
#if 0
|
||||
THIS STUFF IS BASICALLY OBSOLETE
|
||||
//
|
||||
//------------------------
|
||||
// Get the control manager
|
||||
//------------------------
|
||||
//
|
||||
Check(application);
|
||||
ControlsManager *control = application->GetControlsManager();
|
||||
Check(control);
|
||||
|
||||
//
|
||||
//----------------------------------------------------------------------
|
||||
// If the config button was pressed, set all hardwired buttons to config
|
||||
// mode, otherwise set them all back to active mode, and clear out any
|
||||
// temporary mappings to the mappable buttons
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
if (message->dataContents > 0)
|
||||
{
|
||||
if (GetSimulationState() == ConfigurationState)
|
||||
{
|
||||
control->SetHardwiredButtonsFilter(ActiveFilter, 0);
|
||||
control->StopMappableButtonsConfigure(
|
||||
ConfigurationFilter,
|
||||
mustMatch,
|
||||
mayMatch
|
||||
);
|
||||
SetSimulationState(DefaultState);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (controlMode != BasicMode)
|
||||
{
|
||||
control->SetHardwiredButtonsFilter(ConfigurationFilter, 0);
|
||||
SetSimulationState(ConfigurationState);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
Check_Fpu();
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
void
|
||||
VTVControlsMapper::ConfigureSideSlipMappablesMessageHandler(
|
||||
ReceiverDataMessageOf<ControlsButton> *message
|
||||
)
|
||||
{
|
||||
Check(this);
|
||||
Check(message);
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// If the hardwired button was pressed, process presses of the mappable
|
||||
// buttons, otherwise it was released, so erase any temporary mappings
|
||||
//---------------------------------------------------------------------
|
||||
if (message->dataContents > 0)
|
||||
{
|
||||
EnterConfiguration(
|
||||
&sideSlip, // direct target
|
||||
this, // receiver
|
||||
(Receiver::MessageID) 0, // activation message ID (none here)
|
||||
ChooseSideSlipMessageID // configuration message ID
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
ExitConfiguration();
|
||||
}
|
||||
Check_Fpu();
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
void
|
||||
VTVControlsMapper::ChooseSideSlipMessageHandler(
|
||||
ReceiverDataMessageOf<ControlsButton> *message
|
||||
)
|
||||
{
|
||||
Check(this);
|
||||
Check(message);
|
||||
|
||||
if (message->dataContents > 0)
|
||||
{
|
||||
AddOrErase(message->dataContents, &sideSlip);
|
||||
}
|
||||
Check_Fpu();
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
void
|
||||
VTVControlsMapper::ConfigureLiftCutMappablesMessageHandler(
|
||||
ReceiverDataMessageOf<ControlsButton> *message
|
||||
)
|
||||
{
|
||||
Check(this);
|
||||
Check(message);
|
||||
|
||||
//
|
||||
//---------------------------------------------------------------------
|
||||
// If the hardwired button was pressed, process presses of the mappable
|
||||
// buttons, otherwise it was released, so erase any temporary mappings
|
||||
//---------------------------------------------------------------------
|
||||
//
|
||||
if (message->dataContents > 0)
|
||||
{
|
||||
EnterConfiguration(
|
||||
&liftCut, // direct target
|
||||
this, // receiver
|
||||
(Receiver::MessageID) 0, // activation message ID (none here)
|
||||
ChooseLiftCutMessageID // configuration message ID
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
ExitConfiguration();
|
||||
}
|
||||
Check_Fpu();
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
void
|
||||
VTVControlsMapper::ChooseLiftCutMessageHandler(
|
||||
ReceiverDataMessageOf<ControlsButton> *message
|
||||
)
|
||||
{
|
||||
Check(this);
|
||||
Check(message);
|
||||
|
||||
if (message->dataContents > 0)
|
||||
{
|
||||
AddOrErase(message->dataContents, &liftCut);
|
||||
}
|
||||
Check_Fpu();
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
void
|
||||
VTVControlsMapper::ConfigureHornMappablesMessageHandler(
|
||||
ReceiverDataMessageOf<ControlsButton> *message
|
||||
)
|
||||
{
|
||||
Check(this);
|
||||
Check(message);
|
||||
|
||||
//
|
||||
//---------------------------------------------------------------------
|
||||
// If the hardwired button was pressed, process presses of the mappable
|
||||
// buttons, otherwise it was released, so erase any temporary mappings
|
||||
//---------------------------------------------------------------------
|
||||
//
|
||||
|
||||
if (message->dataContents > 0)
|
||||
{
|
||||
EnterConfiguration(
|
||||
NULL, // direct target (none here)
|
||||
this, // receiver
|
||||
ActivateHornMessageID, // activation message ID
|
||||
ChooseHornMessageID // configuration message ID
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
ExitConfiguration();
|
||||
}
|
||||
Check_Fpu();
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
void
|
||||
VTVControlsMapper::ChooseHornMessageHandler(
|
||||
ReceiverDataMessageOf<ControlsButton> *message
|
||||
)
|
||||
{
|
||||
Check(this);
|
||||
Check(message);
|
||||
|
||||
if (message->dataContents > 0)
|
||||
{
|
||||
AddOrErase(message->dataContents, this, ActivateHornMessageID);
|
||||
}
|
||||
Check_Fpu();
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
void
|
||||
VTVControlsMapper::ActivateHornMessageHandler(
|
||||
ReceiverDataMessageOf<ControlsButton> *message
|
||||
)
|
||||
{
|
||||
Check(this);
|
||||
Check(message);
|
||||
|
||||
hornBlast = message->dataContents;
|
||||
// hornBlast = (hornBlast == -1) ? 1 : -1;
|
||||
|
||||
// HACK - ECH 7/31/95 - Propagate horn blast
|
||||
Check(GetEntity());
|
||||
GetEntity()->hornBlast = hornBlast;
|
||||
GetEntity()->ForceUpdate();
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
void
|
||||
VTVControlsMapper::ConfigurePTTMappablesMessageHandler(
|
||||
ReceiverDataMessageOf<ControlsButton> *message
|
||||
)
|
||||
{
|
||||
Check(this);
|
||||
Check(message);
|
||||
|
||||
//
|
||||
//---------------------------------------------------------------------
|
||||
// If the hardwired button was pressed, process presses of the mappable
|
||||
// buttons, otherwise it was released, so erase any temporary mappings
|
||||
//---------------------------------------------------------------------
|
||||
//
|
||||
if (message->dataContents > 0)
|
||||
{
|
||||
EnterConfiguration(
|
||||
NULL, // direct target (none here)
|
||||
this, // receiver
|
||||
ActivatePTTMessageID, // activation message ID
|
||||
ChoosePTTMessageID // configuration message ID
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
ExitConfiguration();
|
||||
}
|
||||
Check_Fpu();
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
void
|
||||
VTVControlsMapper::ChoosePTTMessageHandler(
|
||||
ReceiverDataMessageOf<ControlsButton> *message
|
||||
)
|
||||
{
|
||||
Check(this);
|
||||
Check(message);
|
||||
|
||||
if (message->dataContents > 0)
|
||||
{
|
||||
AddOrErase(message->dataContents, &pttStatus);
|
||||
}
|
||||
Check_Fpu();
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
void
|
||||
VTVControlsMapper::ActivatePTTMessageHandler(
|
||||
ReceiverDataMessageOf<ControlsButton> *message
|
||||
)
|
||||
{
|
||||
Check(this);
|
||||
Check(message);
|
||||
|
||||
pttStatus = message->dataContents;
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
void
|
||||
VTVControlsMapper::ToggleReticleMessageHandler(
|
||||
ReceiverDataMessageOf<ControlsButton> *message
|
||||
)
|
||||
{
|
||||
Check(this);
|
||||
Check(message);
|
||||
|
||||
if (message->dataContents > 0)
|
||||
{
|
||||
VTV* vtv = GetEntity();
|
||||
Check(vtv);
|
||||
Reticle *reticle = &vtv->targetReticle;
|
||||
Check(reticle);
|
||||
reticle->reticleState =
|
||||
(Reticle::ReticleState)(reticle->reticleState^Reticle::ReticleOn);
|
||||
}
|
||||
}
|
||||
|
||||
//#############################################################################
|
||||
// Attribute Support
|
||||
//
|
||||
const VTVControlsMapper::IndexEntry
|
||||
VTVControlsMapper::AttributePointers[]=
|
||||
{
|
||||
ATTRIBUTE_ENTRY(VTVControlsMapper, StickPosition, stickPosition),
|
||||
ATTRIBUTE_ENTRY(VTVControlsMapper, ThrottlePosition, throttlePosition),
|
||||
ATTRIBUTE_ENTRY(VTVControlsMapper, PedalsPosition, pedalsPosition),
|
||||
ATTRIBUTE_ENTRY(VTVControlsMapper, ReverseThrust, reverseThrust),
|
||||
ATTRIBUTE_ENTRY(VTVControlsMapper, LiftCut, liftCut),
|
||||
ATTRIBUTE_ENTRY(VTVControlsMapper, SideSlip, sideSlip),
|
||||
ATTRIBUTE_ENTRY(VTVControlsMapper, PowerDemand, powerDemand),
|
||||
ATTRIBUTE_ENTRY(
|
||||
VTVControlsMapper,
|
||||
AngularVelocityDemand,
|
||||
angularVelocityDemand
|
||||
),
|
||||
ATTRIBUTE_ENTRY(VTVControlsMapper, BrakeLights, brakeLights),
|
||||
ATTRIBUTE_ENTRY(VTVControlsMapper, LookLeft, lookLeft),
|
||||
ATTRIBUTE_ENTRY(VTVControlsMapper, LookRight, lookRight),
|
||||
ATTRIBUTE_ENTRY(VTVControlsMapper, LookBehind, lookBehind),
|
||||
ATTRIBUTE_ENTRY(VTVControlsMapper, LookUp, lookUp),
|
||||
ATTRIBUTE_ENTRY(VTVControlsMapper, ControlMode, controlMode),
|
||||
ATTRIBUTE_ENTRY(VTVControlsMapper, HornBlast, hornBlast),
|
||||
ATTRIBUTE_ENTRY(VTVControlsMapper, MustMatch, mustMatch),
|
||||
ATTRIBUTE_ENTRY(VTVControlsMapper, ReverseThrustEngaged,reverseThrustEngaged), // ECH 8/3/95 - HACK - deal with thrust
|
||||
ATTRIBUTE_ENTRY(VTVControlsMapper, LiftCutEngaged, liftCutEngaged),
|
||||
ATTRIBUTE_ENTRY(VTVControlsMapper, PTTStatus, pttStatus)
|
||||
};
|
||||
|
||||
VTVControlsMapper::AttributeIndexSet& VTVControlsMapper::GetAttributeIndex()
|
||||
{
|
||||
static VTVControlsMapper::AttributeIndexSet attributeIndex(ELEMENTS(VTVControlsMapper::AttributePointers),
|
||||
VTVControlsMapper::AttributePointers,
|
||||
VTVSubsystem::GetAttributeIndex()
|
||||
);
|
||||
return attributeIndex;
|
||||
}
|
||||
|
||||
//#############################################################################
|
||||
// Model Support
|
||||
//
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
void
|
||||
VTVControlsMapper::InterpretControls(Scalar)
|
||||
{
|
||||
Scalar demand;
|
||||
|
||||
Check(this);
|
||||
|
||||
VTV* vtv = GetEntity();
|
||||
Check(vtv);
|
||||
VTVPower *power_system =
|
||||
Cast_Object(VTVPower*, vtv->GetSubsystem(VTV::PowerSubsystem));
|
||||
|
||||
//
|
||||
//----------------------------------------------
|
||||
// Make sure the control inputs are within range
|
||||
//----------------------------------------------
|
||||
//
|
||||
Verify(throttlePosition >= 0.0f && throttlePosition <= 1.0f);
|
||||
Verify(stickPosition.x >= -1.0f && stickPosition.x <= 1.0f);
|
||||
Verify(stickPosition.y >= -1.0f && stickPosition.y <= 1.0f);
|
||||
Verify(pedalsPosition >= -1.0f && pedalsPosition <= 1.0f);
|
||||
|
||||
//
|
||||
//----------------------------------------------------------------
|
||||
// Figure out the proper control model to use based upon the speed
|
||||
//----------------------------------------------------------------
|
||||
//
|
||||
Scalar lateral_power = power_system->maxAccelerationOutput * ZIPPY;
|
||||
powerDemand = Vector3D::Identity;
|
||||
int slow_mode =
|
||||
fabs(vtv->localVelocity.linearMotion.z) <
|
||||
lateral_power / vtv->maxYawVelocity;
|
||||
Check_Fpu();
|
||||
angularVelocityDemand = Vector3D::Identity;
|
||||
Scalar kick_turn = (reverseThrust>0) ? throttlePosition : -throttlePosition;
|
||||
powerDemand.z = kick_turn;
|
||||
Logical no_steal = False;
|
||||
liftCutEngaged = False;
|
||||
reverseThrustEngaged = False;
|
||||
|
||||
//
|
||||
//----------------------------------------------------
|
||||
// If we are in basic mode, do that autothrottle thing
|
||||
//----------------------------------------------------
|
||||
//
|
||||
if (controlMode == BasicMode)
|
||||
{
|
||||
Scalar desired_speed =
|
||||
powerDemand.z
|
||||
* power_system->maxAccelerationOutput
|
||||
/ vtv->negativeLinearDragCoefficients.z;
|
||||
Check_Fpu();
|
||||
Scalar reverse = (reverseThrust>0) ? 1.0f : -1.0f;
|
||||
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
// If we have no boosters on, and we are going too fast, and the stick is
|
||||
// not pushed near full forward, change the throttle setting
|
||||
//-----------------------------------------------------------------------
|
||||
//
|
||||
if (
|
||||
!vtv->BoosterOn()
|
||||
&& throttlePosition < 0.1f
|
||||
&& desired_speed > vtv->localVelocity.linearMotion.z
|
||||
)
|
||||
{
|
||||
no_steal = True;
|
||||
powerDemand.z = -reverse;
|
||||
|
||||
// ECH 8/3/95 - HACK - deal with thrust
|
||||
Scalar temp = Abs(vtv->localVelocity.linearMotion.z) / 60.0f;
|
||||
Clamp(temp, 0.0f, 1.0f);
|
||||
powerDemand.z *= pow(temp, 0.5f);
|
||||
}
|
||||
|
||||
//
|
||||
//--------------------------------------------------------
|
||||
// If we are sliding against the engines, go to full power
|
||||
//--------------------------------------------------------
|
||||
//
|
||||
else if (vtv->localVelocity.linearMotion.z * reverse < 0.0f)
|
||||
{
|
||||
no_steal = True;
|
||||
|
||||
// ECH 8/3/95 - HACK - deal with thrust
|
||||
if (throttlePosition < 0.1f)
|
||||
{
|
||||
Scalar temp = Abs(vtv->localVelocity.linearMotion.z) / 60.0f;
|
||||
Clamp(temp, 0.0f, 1.0f);
|
||||
powerDemand.z *= pow(temp, 0.5f);
|
||||
}
|
||||
}
|
||||
}
|
||||
brakeLights = (powerDemand.z * vtv->localVelocity.linearMotion.z) < 0.0f;
|
||||
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
// If we are in slow mode, match the lateral power to the turn rate, giving
|
||||
// it priority over thrust, so that we will be able to turn a perfect circle
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
if (slow_mode && sideSlip < 1 && controlMode < MasterMode)
|
||||
{
|
||||
angularVelocityDemand.y += stickPosition.x * vtv->maxYawVelocity;
|
||||
powerDemand.x =
|
||||
-vtv->maxYawVelocity
|
||||
* fabs(vtv->localVelocity.linearMotion.z)
|
||||
* stickPosition.x
|
||||
/ lateral_power;
|
||||
Check_Fpu();
|
||||
if (reverseThrust>0 && vtv->localVelocity.linearMotion.z > 0.0f)
|
||||
{
|
||||
powerDemand.x = -powerDemand.x;
|
||||
}
|
||||
demand = powerDemand.x*powerDemand.x + powerDemand.z*powerDemand.z;
|
||||
Check_Fpu();
|
||||
if (demand>1.0f)
|
||||
{
|
||||
if (powerDemand.z > 0.0f)
|
||||
{
|
||||
powerDemand.z = Sqrt(1.0f - powerDemand.x*powerDemand.x);
|
||||
}
|
||||
else
|
||||
{
|
||||
powerDemand.z = -Sqrt(1.0f - powerDemand.x*powerDemand.x);
|
||||
}
|
||||
}
|
||||
Check_Fpu();
|
||||
}
|
||||
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
// If we aren't in slow mode, match the turning rate to the power setting
|
||||
// on the stick, sharing power equally between forward and sideways demands
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
else
|
||||
{
|
||||
powerDemand.x = -stickPosition.x;
|
||||
demand = powerDemand.x*powerDemand.x + powerDemand.z*powerDemand.z;
|
||||
Check_Fpu();
|
||||
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
// If we are asking for more power than is available, steal from anything
|
||||
// but braking so we can turn quicker if we are in a wimp mode
|
||||
//-----------------------------------------------------------------------
|
||||
//
|
||||
if (demand>1.0f)
|
||||
{
|
||||
if (controlMode < MasterMode && powerDemand.z < 0.0f && !no_steal)
|
||||
{
|
||||
powerDemand.z = -Sqrt(1.0f - powerDemand.x*powerDemand.x);
|
||||
Check_Fpu();
|
||||
}
|
||||
else
|
||||
{
|
||||
demand = Sqrt(demand);
|
||||
powerDemand.x /= demand;
|
||||
powerDemand.z /= demand;
|
||||
Check_Fpu();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
// The amount of power required for height as requested by the stick should
|
||||
// range between 1m height and the service ceiling
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
JointSubsystem *joint_subsystem = vtv->GetJointSubsystem();
|
||||
Check(joint_subsystem);
|
||||
Verify(joint_subsystem->GetJointCount());
|
||||
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
// If the lift cut button is on, go ahead and put all the power on X and Z.
|
||||
// In basic mode, if the height is greater than 5m and the stick is pushed
|
||||
// mostly forward
|
||||
//------------------------------------------------------------------------
|
||||
//
|
||||
if (
|
||||
liftCut > 0
|
||||
|| controlMode < VeteranMode
|
||||
&& stickPosition.y <= -0.8f
|
||||
&& vtv->heightAboveTerrain >= 5.0f
|
||||
)
|
||||
{
|
||||
powerDemand.y = vtv->powerDive;
|
||||
if (powerDemand.y)
|
||||
{
|
||||
Scalar reduction = Sqrt(1.0f - powerDemand.y*powerDemand.y);
|
||||
powerDemand.x *= reduction;
|
||||
powerDemand.z *= reduction;
|
||||
}
|
||||
liftCutEngaged = True;
|
||||
}
|
||||
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
// Otherwise, give altitude everything it wants, and split the rest up for
|
||||
// X and Z
|
||||
//------------------------------------------------------------------------
|
||||
//
|
||||
else
|
||||
{
|
||||
if (!vtv->groundEffectDomainSquared)
|
||||
{
|
||||
if (vtv->heightAboveTerrain >= 2.0f)
|
||||
{
|
||||
powerDemand.y = 0.0f;
|
||||
liftCutEngaged = True;
|
||||
}
|
||||
else
|
||||
{
|
||||
demand =
|
||||
power_system->maxAccelerationOutput +
|
||||
joint_subsystem->GetJointCount() *
|
||||
vtv->groundEffectRange;
|
||||
powerDemand.y = vtv->GetEnvironment()->gravityConstant/demand;
|
||||
}
|
||||
}
|
||||
else if (controlMode > StandardMode)
|
||||
{
|
||||
demand =
|
||||
power_system->maxAccelerationOutput
|
||||
+ joint_subsystem->GetJointCount()
|
||||
* (vtv->groundEffectRange
|
||||
/ (1.0f + vtv->groundEffectDomainSquared));
|
||||
Check_Fpu();
|
||||
demand = vtv->GetEnvironment()->gravityConstant/demand;
|
||||
powerDemand.y =
|
||||
0.5f * ((1.0f - demand) * stickPosition.y + (1.0f + demand));
|
||||
Max_Clamp(powerDemand.y, 1.0f);
|
||||
Check_Fpu();
|
||||
}
|
||||
else
|
||||
{
|
||||
Scalar seek_height = vtv->heightAboveTerrain;
|
||||
Scalar height_clamp = 30.0f;
|
||||
Max_Clamp(seek_height, height_clamp);
|
||||
if (stickPosition.y < 0.0f)
|
||||
{
|
||||
seek_height =
|
||||
::Lerp(seek_height, 1.0f, -stickPosition.y);
|
||||
}
|
||||
else
|
||||
{
|
||||
seek_height =
|
||||
::Lerp(seek_height, height_clamp, stickPosition.y);
|
||||
}
|
||||
demand =
|
||||
power_system->maxAccelerationOutput +
|
||||
joint_subsystem->GetJointCount() *
|
||||
(
|
||||
vtv->groundEffectRange
|
||||
/ (
|
||||
1.0f
|
||||
+ vtv->groundEffectDomainSquared*seek_height*seek_height
|
||||
)
|
||||
);
|
||||
Check_Fpu();
|
||||
powerDemand.y = vtv->GetEnvironment()->gravityConstant/demand;
|
||||
if (controlMode == BasicMode)
|
||||
{
|
||||
Max_Clamp(powerDemand.y, 0.85f);
|
||||
}
|
||||
else
|
||||
{
|
||||
Max_Clamp(powerDemand.y, 1.0f);
|
||||
}
|
||||
Check_Fpu();
|
||||
}
|
||||
demand = Sqrt(1.0f - powerDemand.y*powerDemand.y);
|
||||
powerDemand.x *= demand;
|
||||
powerDemand.z *= demand;
|
||||
}
|
||||
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
// Apply the rudders, and simulate a kick turn in basic mode
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
if (controlMode == BasicMode)
|
||||
{
|
||||
Scalar temp = stickPosition.x * stickPosition.x;
|
||||
temp *= stickPosition.x;
|
||||
angularVelocityDemand.y += temp * vtv->maxYawVelocity;
|
||||
}
|
||||
else if (pedalsPosition < 0.0f)
|
||||
{
|
||||
angularVelocityDemand.y -=
|
||||
vtv->maxYawVelocity * pedalsPosition*pedalsPosition;
|
||||
}
|
||||
else
|
||||
{
|
||||
angularVelocityDemand.y +=
|
||||
vtv->maxYawVelocity * pedalsPosition*pedalsPosition;
|
||||
}
|
||||
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
// If we are not is slow mode, apply yaw to the craft to sufficient to make
|
||||
// it turn a perfect circle, then clamp to maximum velocity
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
if (!slow_mode && controlMode < MasterMode && sideSlip < 1)
|
||||
{
|
||||
angularVelocityDemand.y +=
|
||||
-powerDemand.x
|
||||
* ZIPPY
|
||||
* power_system->maxAccelerationOutput
|
||||
/ fabs(vtv->localVelocity.linearMotion.z);
|
||||
Check_Fpu();
|
||||
if (reverseThrust>0 && vtv->localVelocity.linearMotion.z > 0.0f)
|
||||
{
|
||||
powerDemand.x = -powerDemand.x;
|
||||
}
|
||||
}
|
||||
Clamp(
|
||||
angularVelocityDemand.y,
|
||||
-vtv->maxYawVelocity,
|
||||
vtv->maxYawVelocity
|
||||
);
|
||||
|
||||
//
|
||||
//----------------------------------------
|
||||
// Turn the eyepoint the direction we want
|
||||
//----------------------------------------
|
||||
//
|
||||
vtv->eyepointRotation = EulerAngles::Identity;
|
||||
if (lookLeft > 0)
|
||||
{
|
||||
vtv->eyepointRotation.yaw = 0.3f * PI;
|
||||
}
|
||||
else if (lookRight > 0)
|
||||
{
|
||||
vtv->eyepointRotation.yaw = -0.3f * PI;
|
||||
}
|
||||
else if (lookBehind > 0)
|
||||
{
|
||||
vtv->eyepointRotation.yaw = PI;
|
||||
}
|
||||
else if (lookUp > 0)
|
||||
{
|
||||
vtv->eyepointRotation.pitch = PI / 8.0f;
|
||||
}
|
||||
|
||||
// ECH - HACK - deal with thrust and lift cut
|
||||
averageOfForwardThrustDemand.Add(powerDemand.z);
|
||||
forwardThrustDemand = averageOfForwardThrustDemand.CalculateAverage();
|
||||
switch (controlMode)
|
||||
{
|
||||
case BasicMode:
|
||||
// Lift cut has been set, see above
|
||||
// Reverse thrust if demand over 0.15
|
||||
reverseThrustEngaged = (forwardThrustDemand > 0.15f);
|
||||
break;
|
||||
|
||||
case StandardMode:
|
||||
// Lift cut has been set, see above
|
||||
// Reverse thrust based on button
|
||||
reverseThrustEngaged = (reverseThrust > 0);
|
||||
break;
|
||||
|
||||
case VeteranMode:
|
||||
case MasterMode:
|
||||
// Lift cut based on button
|
||||
// Reverse thrust based on button
|
||||
liftCutEngaged = (liftCut > 0);
|
||||
reverseThrustEngaged = (reverseThrust > 0);
|
||||
break;
|
||||
}
|
||||
Check(GetEntity());
|
||||
if (GetEntity()->GetSimulationState() == VTV::BurningState)
|
||||
{
|
||||
liftCutEngaged = False;
|
||||
reverseThrustEngaged = False;
|
||||
}
|
||||
|
||||
//
|
||||
//----------------------------------------------------------------
|
||||
// Send PTT status to intercom
|
||||
//----------------------------------------------------------------
|
||||
//
|
||||
if (pttStatus != previousPTTStatus)
|
||||
{
|
||||
previousPTTStatus = pttStatus;
|
||||
|
||||
Player
|
||||
*player_pointer = vtv->GetPlayerLink();
|
||||
Check(player_pointer);
|
||||
Icom
|
||||
*intercom = player_pointer->GetIntercom();
|
||||
Check(intercom);
|
||||
|
||||
intercom->SetPTTStatus((Logical) pttStatus > 0);
|
||||
}
|
||||
|
||||
Check_Fpu();
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
void
|
||||
VTVControlsMapper::CreateTemporaryEventMappings(
|
||||
Receiver */*receiver*/,
|
||||
Receiver::MessageID /*config_message_id*/
|
||||
)
|
||||
{
|
||||
Fail("Unhandled mapping!\n");
|
||||
}
|
||||
|
||||
void
|
||||
VTVControlsMapper::RemoveTemporaryEventMappings()
|
||||
{
|
||||
Fail("Unhandled mapping!\n");
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
void
|
||||
VTVControlsMapper::AddOrErase(
|
||||
unsigned int,
|
||||
Receiver *,
|
||||
Receiver::MessageID
|
||||
)
|
||||
{
|
||||
Fail("Unhandled mapping!\n");
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
void
|
||||
VTVControlsMapper::AddOrErase(
|
||||
unsigned int,
|
||||
ControlsButton *
|
||||
)
|
||||
{
|
||||
Fail("Unhandled mapping!\n");
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
void
|
||||
VTVControlsMapper::SetConfigurationState(Logical enter_config)
|
||||
{
|
||||
Check(this);
|
||||
|
||||
if (enter_config)
|
||||
{
|
||||
if (GetSimulationState() != ConfigurationState)
|
||||
{
|
||||
SetSimulationState(ConfigurationState);
|
||||
NotifyOfConfigurationModeChange(enter_config);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GetSimulationState() == ConfigurationState)
|
||||
{
|
||||
SetSimulationState(DefaultState);
|
||||
NotifyOfConfigurationModeChange(enter_config);
|
||||
}
|
||||
}
|
||||
Check_Fpu();
|
||||
}
|
||||
|
||||
void
|
||||
VTVControlsMapper::NotifyOfControlModeChange(int /*new_mode*/)
|
||||
{
|
||||
Check(this);
|
||||
// defaults to no-operation: intended to be processed by
|
||||
// platform-specific derived class
|
||||
Check_Fpu();
|
||||
}
|
||||
|
||||
void
|
||||
VTVControlsMapper::NotifyOfConfigurationModeChange(Logical /*new_state*/)
|
||||
{
|
||||
Check(this);
|
||||
// defaults to no-operation: intended to be processed by
|
||||
// platform-specific derived class
|
||||
Check_Fpu();
|
||||
}
|
||||
|
||||
//#############################################################################
|
||||
// Construction and Destruction
|
||||
//
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
VTVControlsMapper::VTVControlsMapper(
|
||||
VTV *owner,
|
||||
int subsystem_ID,
|
||||
SubsystemResource *subsystem_resource,
|
||||
SharedData &shared_data
|
||||
):
|
||||
VTVSubsystem(
|
||||
owner,
|
||||
subsystem_ID,
|
||||
subsystem_resource,
|
||||
shared_data
|
||||
),
|
||||
averageOfForwardThrustDemand(4) // ECH 8/3/95 - HACK - To deal with reverse thrust
|
||||
{
|
||||
if (owner->GetInstance() == VTV::MasterInstance && owner->IsDynamic())
|
||||
{
|
||||
SetPerformance(&VTVControlsMapper::InterpretControls);
|
||||
}
|
||||
|
||||
stickPosition.x = 0.0f;
|
||||
stickPosition.y = 0.0f;
|
||||
throttlePosition = 0.0f;
|
||||
pedalsPosition = 0.0f;
|
||||
|
||||
reverseThrust = 0;
|
||||
liftCut = 0;
|
||||
sideSlip = 0;
|
||||
powerDemand = Vector3D::Identity;
|
||||
angularVelocityDemand = Vector3D::Identity;
|
||||
brakeLights = 0;
|
||||
lookLeft = 0;
|
||||
lookRight = 0;
|
||||
lookBehind = 0;
|
||||
lookUp = 0;
|
||||
hornBlast = 0;
|
||||
controlMode = BasicMode;
|
||||
forwardThrustDemand = 0.0f;
|
||||
liftCutEngaged = False;
|
||||
reverseThrustEngaged = False;
|
||||
|
||||
pttStatus = 0;
|
||||
previousPTTStatus = 0;
|
||||
|
||||
Check_Fpu();
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
VTVControlsMapper::~VTVControlsMapper()
|
||||
{
|
||||
Check(this);
|
||||
Check_Fpu();
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
Logical
|
||||
VTVControlsMapper::TestInstance() const
|
||||
{
|
||||
return IsDerivedFrom(*GetClassDerivations());
|
||||
}
|
||||
Reference in New Issue
Block a user