/*
** Copyright (C) 1999 Microsoft Corporation. All Rights Reserved.
**
** File: training.cpp
**
** Author:
**
** Description:
** Implementation of the training library core.
**
** History:
*/
#include "pch.h"
#include "Training.h"
#include "Mission2.h"
#include "Mission3.h"
#include "Mission4.h"
#include "Mission5.h"
#include "Mission6.h"
#include "Mission8.h" //TheBored 06-JUL-07: Adding nanite mission.
namespace Training
{
//------------------------------------------------------------------------------
// global variabes
//------------------------------------------------------------------------------
ControlData g_allowableControlScalars; // yaw, pitch, roll, throttle
ControlData g_inputControls; // yaw, pitch, roll, throttle - the ones the player is actually inputing
ControlData g_setInputControls; // yaw, pitch, roll, throttle - the ones we are forcing on the player
int g_iAllowableActionMask;
int g_iSetInputAction; // fire, afterburners, ... - the ones we force on the player
TrainingMission* g_pMission = 0;
bool g_bIsMission7;
//------------------------------------------------------------------------------
// primary interface to the training missions
//------------------------------------------------------------------------------
bool StartMission (int iMissionIndex)
{
// assign default values to the control masks
g_allowableControlScalars.jsValues[c_axisYaw] = 1.0f;
g_allowableControlScalars.jsValues[c_axisPitch] = 1.0f;
g_allowableControlScalars.jsValues[c_axisRoll] = 1.0f;
g_allowableControlScalars.jsValues[c_axisThrottle] = 1.0f;
g_iAllowableActionMask = 0xffffffff;
// be sure the set controls are cleared
g_setInputControls.jsValues[c_axisYaw] = NA;
g_setInputControls.jsValues[c_axisPitch] = NA;
g_setInputControls.jsValues[c_axisRoll] = NA;
g_setInputControls.jsValues[c_axisThrottle] = NA;
g_iSetInputAction = 0;
// set the HUD overlay back to nothing
ClearTrainingOverlay ();
// clear the mission 7 flag
g_bIsMission7 = false;
// create the appropriate mission, and start it
switch (iMissionIndex)
{
case c_TM_2_Basic_Flight:
g_pMission = new Mission2;
break;
case c_TM_3_Basic_Weaponry:
g_pMission = new Mission3;
break;
case c_TM_4_Enemy_Engagement:
g_pMission = new Mission4;
break;
case c_TM_5_Command_View:
g_pMission = new Mission5;
break;
case c_TM_6_Practice_Arena:
g_pMission = new Mission6;
break;
//TheBored 06-JUL-07: adding nanite mission
case c_TM_8_Nanite:
g_pMission = new Mission8;
break;
//End TB
case c_TM_7_Live:
g_bIsMission7 = true;
// fall through
default:
// create no mission
return false;
}
assert (g_pMission);
g_pMission->Start ();
// start training missions with the throttle off
trekClient.OverrideThrottle (-1.0f);
// return true to indicate that we started a mission
return true;
}
//------------------------------------------------------------------------------
bool HandleMission (void)
{
// handle the mission if necessary
if (g_pMission and g_pMission->Frame ())
{
TrainingMission* pMission = g_pMission;
g_pMission = 0;
delete pMission;
}
return false;
}
//------------------------------------------------------------------------------
bool EndMission (void)
{
if (g_bIsMission7)
g_bIsMission7 = false;
if (g_pMission)
{
g_pMission->Terminate ();
return true;
}
return false;
}
//------------------------------------------------------------------------------
void SetSkipPostSlideshow (void)
{
if (g_pMission)
g_pMission->SetSkipPostSlideshow ();
}
//------------------------------------------------------------------------------
bool IsTraining (void)
{
return g_pMission ? true : false;
}
//------------------------------------------------------------------------------
bool IsInstalled (void)
{
return true;
/*
char szFilename[MAX_PATH + 1];
HRESULT hr = UTL::getFile ("trainingsounddef", ".mdl", szFilename, true, true);
return (hr == S_OK);
*/
}
//------------------------------------------------------------------------------
int GetTrainingMissionID (void)
{
if (g_bIsMission7)
return c_TM_7_Live;
else if (g_pMission)
return g_pMission->GetMissionID ();
return NA;
}
//------------------------------------------------------------------------------
SectorID GetStartSectorID (void)
{
assert (g_pMission);
return g_pMission->GetStartSectorID ();
}
//------------------------------------------------------------------------------
void SetupShipAndCamera (void)
{
assert (g_pMission);
g_pMission->SetupShipAndCamera ();
}
//------------------------------------------------------------------------------
// event trapping
//------------------------------------------------------------------------------
void RecordChat (ChatTarget recipient)
{
if (g_pMission)
g_pMission->RecordChat (recipient);
}
//------------------------------------------------------------------------------
bool RecordKeyPress (TrekKey key)
{
if (g_pMission)
return g_pMission->RecordKeyPress (key);
return true;
}
//------------------------------------------------------------------------------
bool ShipLanded (void)
{
if (g_pMission)
return g_pMission->ShipLanded ();
return true;
}
//------------------------------------------------------------------------------
void ShipDied (ImodelIGC* pLauncher)
{
if (g_pMission)
g_pMission->ShipDied (pLauncher);
}
//------------------------------------------------------------------------------
bool RestoreShip (void)
{
if (g_pMission)
return g_pMission->RestoreShip ();
return true;
}
//------------------------------------------------------------------------------
// control constraint functions - note that these could be inlined
//------------------------------------------------------------------------------
ControlData& ApproveControls (ControlData& inputControls)
{
// copy the input controls for later retrieval
g_inputControls = inputControls;
// the fundamental limiter here is a multiplier that allows the commander of
// the training mission to scale the control inputs as s/he sees fit. for the
// most part, I expect that these values will be 0.0f or 1.0f
inputControls.jsValues[c_axisYaw] *= g_allowableControlScalars.jsValues[c_axisYaw];
inputControls.jsValues[c_axisPitch] *= g_allowableControlScalars.jsValues[c_axisPitch];
inputControls.jsValues[c_axisRoll] *= g_allowableControlScalars.jsValues[c_axisRoll];
// the throttle is mapping the range -1.0f to 1.0f from the joystick to the
// more useful range 0.0f to 1.0f, as a result we have to translate the value
// before scaling, then translate it back
inputControls.jsValues[c_axisThrottle] = ((inputControls.jsValues[c_axisThrottle] + 1.0f) * g_allowableControlScalars.jsValues[c_axisThrottle]) - 1.0f;
// here we check to see if the controls are specifically being overridden, and
// if they are, we set them explicitly
if (g_setInputControls.jsValues[c_axisYaw] != NA)
inputControls.jsValues[c_axisYaw] = g_setInputControls.jsValues[c_axisYaw];
if (g_setInputControls.jsValues[c_axisPitch] != NA)
inputControls.jsValues[c_axisPitch] = g_setInputControls.jsValues[c_axisPitch];
if (g_setInputControls.jsValues[c_axisRoll] != NA)
inputControls.jsValues[c_axisRoll] = g_setInputControls.jsValues[c_axisRoll];
if (g_setInputControls.jsValues[c_axisThrottle] != NA)
inputControls.jsValues[c_axisThrottle] = (g_setInputControls.jsValues[c_axisThrottle] * 2.0f) - 1.0f;
// the manipulated data is returned so it can be expressly used as a
// parameter in a function call
return inputControls;
}
//------------------------------------------------------------------------------
int ApproveActions (int iInputMask)
{
// this gives the commander control over the actions by allowing her to
// mask out the control inputs. The mask is combined with the actual
// inputs using a "bitwise and", effectively disabling inputs whose mask
// bit is not 1
iInputMask &= g_iAllowableActionMask;
// turn on whatever controls are being forced on
iInputMask |= g_iSetInputAction;
// return the result
return iInputMask;
}
//------------------------------------------------------------------------------
}