Files
RP412/RP/VTVMPPR.cpp
T
CydandClaude Opus 4.8 4abbf8879f 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>
2026-06-30 07:59:51 -05:00

959 lines
25 KiB
C++

#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());
}