diff --git a/VS2017/training.vcxproj b/VS2017/training.vcxproj
index 00d7e002..bc023a95 100644
--- a/VS2017/training.vcxproj
+++ b/VS2017/training.vcxproj
@@ -146,6 +146,7 @@
+
@@ -239,6 +240,7 @@
+
@@ -293,4 +295,4 @@
-
\ No newline at end of file
+
diff --git a/src/WinTrek/WinTrek.cpp b/src/WinTrek/WinTrek.cpp
index 929f8a6c..99381250 100644
--- a/src/WinTrek/WinTrek.cpp
+++ b/src/WinTrek/WinTrek.cpp
@@ -2474,7 +2474,7 @@ class TrekWindowImpl :
{
extern TRef g_pnumberMissionNumber;
int iMission = static_cast (g_pnumberMissionNumber->GetValue ());
- ZAssert ((iMission >= 1) && (iMission <= 8)); //TheBored 06-JUL-07: second condition must be (iMission <= (number of training missions))
+ ZAssert ((iMission >= 1) && (iMission <= 10)); //TheBored 06-JUL-07: second condition must be (iMission <= (number of training missions))
char* strNamespace[] =
{
"",
@@ -2484,8 +2484,10 @@ class TrekWindowImpl :
"tm_4_enemy_engagement_post",
"tm_5_command_view_post",
"tm_6_practice_arena_post",
- "", //TheBored 06-JUL-07: Mish #7, blank because its never used
- "tm_8_nanite_post", //TheBored 06-JUL-07: Mish #8 postgame panels
+ "", //TheBored 06-JUL-07: Mish #7, blank because its never used
+ "tm_8_nanite_post", //TheBored 06-JUL-07: Mish #8 postgame panels
+ "",
+ "tm_6_practice_arena_post" //05-NOV-17: FreeFlight pseudo training mission - use same post slides as tm6 (showing station instead of text in ui-stretch beta)
};
SetUiScreen(CreatePostTrainingSlideshow (GetModeler (), strNamespace[iMission]));
break;
diff --git a/src/WinTrek/teampane.cpp b/src/WinTrek/teampane.cpp
index d152e04f..fda7512f 100644
--- a/src/WinTrek/teampane.cpp
+++ b/src/WinTrek/teampane.cpp
@@ -1241,19 +1241,35 @@ public TrekClientEventSink
//
// assert (pplayer->SideID() != SIDE_TEAMLOBBY);
{
- if (Training::IsTraining ())
+ if (Training::IsTraining())
{
- ImissionIGC* pCore = trekClient.GetCore ();
- IshipIGC* pShip = pCore->GetShip (shipID);
- IclusterIGC* pCluster = pShip->GetCluster ();
- if (!pCluster)
+ if (Training::CommandViewEnabled())
{
- IstationIGC* pStation = pShip->GetStation ();
- assert (pStation);
- pCluster = pStation->GetCluster ();
- assert (pCluster);
+ ImissionIGC* pCore = trekClient.GetCore();
+ IshipIGC* pShip = pCore->GetShip(shipID); //pplayer->GetShip() should be the same
+ IclusterIGC* pCluster = pShip->GetCluster();
+ const Vector* ppos;
+ if (!pCluster)
+ {
+ IstationIGC* pStation = pShip->GetStation();
+ assert(pStation);
+ pCluster = pStation->GetCluster();
+ assert(pCluster);
+ debugf("Ship is in station in %s.\n", pCluster->GetName());
+ ppos = pStation && pStation->SeenBySide(trekClient.GetSide()) ? &(pStation->GetPosition()) : NULL;
+ }
+ else
+ ppos = pShip && pShip->SeenBySide(trekClient.GetSide()) ? &(pShip->GetPosition()) : NULL;
+
+ IclusterIGC* pClusterShip = trekClient.GetShip()->GetCluster();
+ if ((pClusterShip == NULL) || (pClusterShip == pCluster)) { //check if in station or in the same sector
+ if (GetWindow()->GetViewMode() != TrekWindow::vmCommand)
+ GetWindow()->SetViewMode(TrekWindow::vmCommand);
+
+ //trekClient.RequestViewCluster (pCluster, pplayer->GetShip()); //fails for ships in stations
+ trekClient.SetViewCluster(pCluster, ppos);
+ }
}
- trekClient.RequestViewCluster (pCluster, pplayer->GetShip());
}
else if (pplayer->GetShipStatus().GetSectorID() != NA)
{
@@ -1279,7 +1295,7 @@ public TrekClientEventSink
}
}
- GetWindow()->GetConsoleImage()->GetConsoleData()->PickShip(pplayer->GetShip());
+ GetWindow()->GetConsoleImage()->GetConsoleData()->PickShip(pplayer->GetShip()); //Select the ship
}
}
diff --git a/src/WinTrek/trainingscreen.cpp b/src/WinTrek/trainingscreen.cpp
index d45a80f1..7d1f051b 100644
--- a/src/WinTrek/trainingscreen.cpp
+++ b/src/WinTrek/trainingscreen.cpp
@@ -93,7 +93,7 @@ class TrainingScreen :
m_pbuttonTrain->SetChecked (true);
#ifdef _DEBUG
if (bStartTraining) {
- g_pnumberMissionNumber->SetValue(6);
+ g_pnumberMissionNumber->SetValue(Training::c_TM_10_Free_Flight);
OnButtonTrain();
}
#endif
@@ -195,15 +195,27 @@ class TrainingScreen :
case Training::c_TM_4_Enemy_Engagement:
case Training::c_TM_5_Command_View:
case Training::c_TM_6_Practice_Arena:
- case Training::c_TM_8_Nanite: //TheBored 06-JUL-07: nanite mission
+ case Training::c_TM_8_Nanite:
// note that the training slideshow can get the mission number from the global
// value when subsequently launching.
- GetWindow ()->screen (ScreenIDTrainSlideshow);
+ GetWindow()->screen(ScreenIDTrainSlideshow);
+ break;
+ case Training::c_TM_10_Free_Flight:
+ //Skip slideshow -- Let stuff load before changing it
+ TRef pMsgBox = CreateMessageBox("Training simulation initiated...", NULL, false);
+ GetWindow()->GetPopupContainer()->OpenPopup(pMsgBox, false);
+ AddEventTarget(&TrainingScreen::OnFreeFlightSwitchOut, GetWindow(), 0.1f);
break;
}
return true;
}
+ bool OnFreeFlightSwitchOut(void)
+ {
+ GetWindow()->StartTraining(Training::c_TM_10_Free_Flight);
+ return false;
+ }
+
bool OnButtonMission(const int iMission)
{
g_pnumberMissionNumber->SetValue(iMission);
diff --git a/src/WinTrek/trekigc.cpp b/src/WinTrek/trekigc.cpp
index dc9f21f2..d2722c79 100644
--- a/src/WinTrek/trekigc.cpp
+++ b/src/WinTrek/trekigc.cpp
@@ -2106,7 +2106,7 @@ class ThingSiteImpl : public ThingSitePrivate
if (Training::IsTraining ())
{
- if ((trekClient.GetShip ()->GetSide () != side) && (Training::GetTrainingMissionID () != Training::c_TM_6_Practice_Arena))
+ if ((trekClient.GetShip()->GetSide() != side) && (Training::GetTrainingMissionID() != Training::c_TM_6_Practice_Arena) && (Training::GetTrainingMissionID() != Training::c_TM_10_Free_Flight))
return false;
}
return m_sideVisibility.fVisible();
@@ -4235,7 +4235,7 @@ void WinTrekClient::ReceiveChat(IshipIGC* pshipSender,
if (Training::IsTraining ())
{
// prevent players from giving commands to themselves
- if (pshipSender && (oidRecipient == pshipSender->GetObjectID ()))
+ if (pshipSender && (oidRecipient == pshipSender->GetObjectID ()) && !Training::CommandViewEnabled())
pmodelTarget = NULL;
// send out the chat we are getting to see if we are waiting for it...
diff --git a/src/training/Training.cpp b/src/training/Training.cpp
index f9a3ea31..c67f1101 100644
--- a/src/training/Training.cpp
+++ b/src/training/Training.cpp
@@ -17,7 +17,8 @@
#include "Mission4.h"
#include "Mission5.h"
#include "Mission6.h"
-#include "Mission8.h" //TheBored 06-JUL-07: Adding nanite mission.
+#include "Mission8.h" //TheBored 06-JUL-07: Adding nanite mission.
+#include "Mission10.h"
namespace Training
{
@@ -75,11 +76,12 @@ namespace Training
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_8_Nanite: //TheBored 06-JUL-07: adding nanite mission
+ g_pMission = new Mission8;
+ break;
+ case c_TM_10_Free_Flight:
+ g_pMission = new Mission10;
+ break;
case c_TM_7_Live:
g_bIsMission7 = true;
// fall through
@@ -147,6 +149,11 @@ namespace Training
*/
}
+ //------------------------------------------------------------------------------
+ bool CommandViewEnabled(void) {
+ return g_pMission ? g_pMission->GetCommandViewEnabled() : false;
+ }
+
//------------------------------------------------------------------------------
int GetTrainingMissionID (void)
{
diff --git a/src/training/Training.h b/src/training/Training.h
index 934aa8e4..21a56c30 100644
--- a/src/training/Training.h
+++ b/src/training/Training.h
@@ -27,7 +27,8 @@ namespace Training
c_TM_5_Command_View = 5,
c_TM_6_Practice_Arena = 6,
c_TM_7_Live = 7,
- c_TM_8_Nanite = 8 //TheBored 06-JUL-07: adding nanite mission
+ c_TM_8_Nanite = 8, //TheBored 06-JUL-07: adding nanite mission
+ c_TM_10_Free_Flight = 10
};
//------------------------------------------------------------------------------
@@ -39,6 +40,7 @@ namespace Training
void SetSkipPostSlideshow (void);
bool IsTraining (void);
bool IsInstalled (void);
+ bool CommandViewEnabled(void);
int GetTrainingMissionID (void);
SectorID GetStartSectorID (void);
void SetupShipAndCamera (void);
diff --git a/src/training/mission10.cpp b/src/training/mission10.cpp
new file mode 100644
index 00000000..824b6060
--- /dev/null
+++ b/src/training/mission10.cpp
@@ -0,0 +1,186 @@
+/*
+** File: Mission10.cpp
+**
+** Description:
+** Implementation of the tenth pseudo training mission "Free Flight", intended for dev use.
+** Cloned mission 6 without intro and with less constraints.
+*/
+#include "pch.h"
+#include "Mission10.h"
+
+#include "Training.h"
+#include "GoalList.h"
+#include "ConditionalAction.h"
+#include "GetShipIsDestroyedCondition.h"
+#include "FalseCondition.h"
+#include "ElapsedTimeCondition.h"
+#include "SetDisplayModeAction.h"
+#include "CreateDroneAction.h"
+#include "MessageAction.h"
+
+namespace Training
+{
+ //------------------------------------------------------------------------------
+ // class methods
+ //------------------------------------------------------------------------------
+ /* void */ Mission10::~Mission10(void)
+ {
+ }
+
+ //------------------------------------------------------------------------------
+ int Mission10::GetMissionID(void)
+ {
+ return c_TM_10_Free_Flight;
+ }
+
+ //------------------------------------------------------------------------------
+ SectorID Mission10::GetStartSectorID(void)
+ {
+ return 1030;
+ }
+
+ //------------------------------------------------------------------------------
+ bool Mission10::RestoreShip(void)
+ {
+ // end the mission
+ Terminate();
+
+ // and return false so the engine stays in the override camera mode
+ return false;
+ }
+
+ //------------------------------------------------------------------------------
+ void Mission10::CreateUniverse(void)
+ {
+ LoadUniverse("training_3", 488, 1030); // a fighter 3
+ trekClient.fGroupFire = true; // activate all the starting weapons
+
+ // put the commander ship in the station
+ ImissionIGC* pCore = trekClient.GetCore();
+ ImodelIGC* pStation = pCore->GetModel(OT_station, 1030);
+ IshipIGC* pCommander = pCore->GetShip(m_commanderID);
+ pCommander->SetStation(static_cast (pStation));
+ pCommander->SetCommand(c_cmdAccepted, NULL, c_cidDoNothing);
+ pCommander->SetCommand(c_cmdCurrent, NULL, c_cidDoNothing);
+ pCommander->SetAutopilot(false);
+ }
+
+ //------------------------------------------------------------------------------
+ Condition* Mission10::CreateMission(void)
+ {
+ debugf("Creating mission 10.\n");
+ m_commandViewEnabled = true;
+
+ GoalList* pGoalList = new GoalList;
+
+ // wait .1 seconds, so stuff is initialized
+ pGoalList->AddGoal(new Goal(new ElapsedTimeCondition(0.1f)));
+
+ // play the introductory audio and change camera
+ {
+ Goal* pGoal = CreatePlaySoundGoal(salCommenceScanSound);
+ pGoal->AddStartAction(new SetDisplayModeAction(TrekWindow::cmCockpit));
+ pGoalList->AddGoal(pGoal);
+ }
+
+ pGoalList->AddGoal(new Goal(new ElapsedTimeCondition(1.0f)));
+
+ // tm_6_02
+ // Iron Coalition Intelligence reports inbound enemy craft.
+ // They're using an old code for their comms, so we can hear
+ // them. Watch your message stream to see what they're up to.
+ {
+ Goal* pGoal = CreatePlaySoundGoal(tm_6_02Sound);
+ pGoal->AddStartAction(new MessageAction("Watch the chat to see what the enemy craft are after."));
+ pGoalList->AddGoal(pGoal);
+ }
+
+ // wait half second
+ pGoalList->AddGoal(new Goal(new ElapsedTimeCondition(0.5f)));
+
+ // tm_6_03
+ // DEFEND THE MINERS! This simulation is over when you die.
+ pGoalList->AddGoal(CreatePlaySoundGoal(tm_6_03Sound));
+
+ // wait two more seconds
+ pGoalList->AddGoal(new Goal(new ElapsedTimeCondition(2.0f)));
+
+ // need this
+ ImissionIGC* pMission = trekClient.GetCore();
+ ImodelIGC* pStation = pMission->GetModel(OT_station, 1030);
+
+ // wait for player to be dead
+ {
+ Goal* pGoal = new Goal(new FalseCondition);
+
+ // create enemy ships
+ ShipID enemyShipID = pMission->GenerateNewShipID();
+ CreateDroneAction* pCreateDroneAction = new CreateDroneAction("Enemy Support", enemyShipID, 310, 1, c_ptWingman);
+ pCreateDroneAction->SetCreatedLocation(GetStartSectorID(), Vector(3800.0f, 4275.0f, 855.0f));
+ Condition* pShipIsDestroyedcondition = new GetShipIsDestroyedCondition2(OT_ship, static_cast (enemyShipID));
+ pGoal->AddConstraintCondition(new ConditionalAction(pShipIsDestroyedcondition, pCreateDroneAction));
+
+ enemyShipID = pMission->GenerateNewShipID();
+ pCreateDroneAction = new CreateDroneAction("Enemy Fighter", enemyShipID, 315, 1, c_ptWingman);
+ pCreateDroneAction->SetCreatedLocation(GetStartSectorID(), Vector(3800.0f, 4175.0f, 855.0f));
+ pShipIsDestroyedcondition = new GetShipIsDestroyedCondition2(OT_ship, static_cast (enemyShipID));
+ pGoal->AddConstraintCondition(new ConditionalAction(pShipIsDestroyedcondition, pCreateDroneAction));
+
+ pGoalList->AddGoal(pGoal);
+ }
+
+ // build the goal that we'll return
+ {
+ Goal* pGoal = new Goal(pGoalList);
+
+ // create friendly miners
+ Vector pos = pStation->GetPosition();
+ pos.x += random(-1000.0f, 1000.0f);
+ pos.y += random(-1000.0f, 1000.0f);
+ pos.z += random(-1000.0f, 1000.0f);
+
+ ShipID minerShipID = pMission->GenerateNewShipID();
+ CreateDroneAction* pCreateDroneAction = new CreateDroneAction("Miner 01", minerShipID, 436, 0, c_ptMiner);
+ pCreateDroneAction->SetCreatedLocation(GetStartSectorID(), pos);
+ Condition* pShipIsDestroyedcondition = new GetShipIsDestroyedCondition2(OT_ship, static_cast (minerShipID));
+ pGoal->AddConstraintCondition(new ConditionalAction(pShipIsDestroyedcondition, pCreateDroneAction));
+
+ pos = pStation->GetPosition();
+ pos.x += random(-1000.0f, 1000.0f);
+ pos.y += random(-1000.0f, 1000.0f);
+ pos.z += random(-1000.0f, 1000.0f);
+
+ minerShipID = pMission->GenerateNewShipID();
+ pCreateDroneAction = new CreateDroneAction("Miner 02", minerShipID, 436, 0, c_ptMiner);
+ pCreateDroneAction->SetCreatedLocation(GetStartSectorID(), pos);
+ pShipIsDestroyedcondition = new GetShipIsDestroyedCondition2(OT_ship, static_cast (minerShipID));
+ pGoal->AddConstraintCondition(new ConditionalAction(pShipIsDestroyedcondition, pCreateDroneAction));
+
+ pos = pStation->GetPosition();
+ pos.x += random(-1000.0f, 1000.0f);
+ pos.y += random(-1000.0f, 1000.0f);
+ pos.z += random(-1000.0f, 1000.0f);
+
+ minerShipID = pMission->GenerateNewShipID();
+ pCreateDroneAction = new CreateDroneAction("Miner 03", minerShipID, 436, 0, c_ptMiner);
+ pCreateDroneAction->SetCreatedLocation(GetStartSectorID(), pos);
+ pShipIsDestroyedcondition = new GetShipIsDestroyedCondition2(OT_ship, static_cast (minerShipID));
+ pGoal->AddConstraintCondition(new ConditionalAction(pShipIsDestroyedcondition, pCreateDroneAction));
+
+ pos = pStation->GetPosition();
+ pos.x += random(-1000.0f, 1000.0f);
+ pos.y += random(-1000.0f, 1000.0f);
+ pos.z += random(-1000.0f, 1000.0f);
+
+ minerShipID = pMission->GenerateNewShipID();
+ pCreateDroneAction = new CreateDroneAction("Miner 04", minerShipID, 436, 0, c_ptMiner);
+ pCreateDroneAction->SetCreatedLocation(GetStartSectorID(), pos);
+ pShipIsDestroyedcondition = new GetShipIsDestroyedCondition2(OT_ship, static_cast (minerShipID));
+ pGoal->AddConstraintCondition(new ConditionalAction(pShipIsDestroyedcondition, pCreateDroneAction));
+
+ return pGoal;
+ }
+ }
+
+ //------------------------------------------------------------------------------
+}
diff --git a/src/training/mission10.h b/src/training/mission10.h
new file mode 100644
index 00000000..4bc42dc8
--- /dev/null
+++ b/src/training/mission10.h
@@ -0,0 +1,41 @@
+/*
+** File: mission10.h
+**
+** Description:
+** Header file for the training library "Mission FreeFlight" interface.
+*/
+
+#ifndef _MISSION_FREEFLIGHT_H_
+#define _MISSION_FREEFLIGHT_H_
+
+#ifndef _TRAINING_MISSION_H_
+#include "TrainingMission.h"
+#endif
+
+#ifndef _GOAL_H_
+#include "Goal.h"
+#endif
+
+
+namespace Training
+{
+ //------------------------------------------------------------------------------
+ // class definitions
+ //------------------------------------------------------------------------------
+ class Mission10 : public TrainingMission
+ {
+ public:
+ virtual /* void */ ~Mission10(void);
+ virtual int GetMissionID(void);
+ virtual SectorID GetStartSectorID(void);
+ virtual bool RestoreShip(void);
+
+ protected:
+ virtual void CreateUniverse(void);
+ virtual Condition* CreateMission(void);
+ };
+
+ //------------------------------------------------------------------------------
+}
+
+#endif //_MISSION_FREEFLIGHT_H_
diff --git a/src/training/mission6.cpp b/src/training/mission6.cpp
index 29c67901..0dba9324 100644
--- a/src/training/mission6.cpp
+++ b/src/training/mission6.cpp
@@ -6,7 +6,7 @@
** Author:
**
** Description:
-** Implementation of the fifth training mission
+** Implementation of the sixth training mission
**
** History:
*/
@@ -88,8 +88,12 @@ namespace Training
// outpost here in case you need to replenish yourself.
pGoalList->AddGoal (CreatePlaySoundGoal (tm_6_01Sound));
- // wait two more seconds
- pGoalList->AddGoal (new Goal (new ElapsedTimeCondition (2.0f)));
+ // wait two more seconds in cockpit
+ {
+ Goal* pGoal = new Goal(new ElapsedTimeCondition(2.0f));
+ pGoal->AddStartAction(new SetDisplayModeAction(TrekWindow::cmCockpit));
+ pGoalList->AddGoal(pGoal);
+ }
// tm_6_02
// Iron Coalition Intelligence reports inbound enemy craft.
@@ -97,7 +101,6 @@ namespace Training
// them. Watch your message stream to see what they're up to.
{
Goal* pGoal = CreatePlaySoundGoal (tm_6_02Sound);
- pGoal->AddStartAction (new SetDisplayModeAction (TrekWindow::cmCockpit));
pGoal->AddStartAction (new MessageAction ("Watch the chat to see what the enemy craft are after."));
pGoalList->AddGoal (pGoal);
}
diff --git a/src/training/trainingmission.cpp b/src/training/trainingmission.cpp
index d398992d..cd8548f7 100644
--- a/src/training/trainingmission.cpp
+++ b/src/training/trainingmission.cpp
@@ -64,7 +64,8 @@ namespace Training
m_pDeadCondition (0),
m_commanderID (NA),
m_pChatCondition (0),
- m_bSkipPostSlideShow (false)
+ m_bSkipPostSlideShow (false),
+ m_commandViewEnabled(false)
{
// get the window pointer
TrekWindow* pWindow = GetWindow ();
@@ -257,18 +258,6 @@ namespace Training
// check the key for tm conditions
switch (key)
{
- // XXX hack to disable some keys in training
- case TK_ViewCommand:
- case TK_ConModeCommand:
- case TK_ConModeInvest:
- case TK_TargetSelf:
- case TK_Suicide:
- case TK_ConModeGameState:
- case TK_ConModeTeleport:
- case TK_ToggleAutoPilot:
- case TK_RejectCommand: // pkk - Some training missions can't be finished
- return false;
-
case TK_PauseTM:
{
// if the game is paused
@@ -310,6 +299,20 @@ namespace Training
break;
#endif
+ // XXX hack to disable some keys in training
+ case TK_ViewCommand:
+ case TK_ConModeCommand:
+ case TK_ConModeInvest:
+ case TK_TargetSelf:
+ case TK_Suicide:
+ case TK_ConModeGameState:
+ case TK_ConModeTeleport:
+ case TK_ToggleAutoPilot:
+ case TK_RejectCommand: // pkk - Some training missions can't be finished
+ if (GetMissionID() != 10) //Training::c_TM_10_Free_Flight
+ return false;
+ //fallthrough otherwise
+
default:
{
// iterate over the key conditions with the unknown key
@@ -488,6 +491,12 @@ namespace Training
m_bSkipPostSlideShow = true;
}
+ //------------------------------------------------------------------------------
+ bool TrainingMission::GetCommandViewEnabled(void)
+ {
+ return m_commandViewEnabled;
+ }
+
//------------------------------------------------------------------------------
void TrainingMission::LoadUniverse (const ZString& name, HullID hullID, StationID homeStationID)
{
diff --git a/src/training/trainingmission.h b/src/training/trainingmission.h
index 69d7ac26..ccaae8b3 100644
--- a/src/training/trainingmission.h
+++ b/src/training/trainingmission.h
@@ -46,6 +46,7 @@ namespace Training
void AddPartToShip (PartID part, Mount mount, short ammo = 0);
IshipIGC* CreateDrone (const ZString& name, ShipID shipID, HullID hullID, SideID sideID, PilotType pilotType);
void SetSkipPostSlideshow (void);
+ bool GetCommandViewEnabled(void);
protected:
virtual void CreateUniverse (void) = 0;
@@ -71,6 +72,7 @@ namespace Training
TrekWindow::ViewMode m_deadViewMode;
TrekWindow::CameraMode m_deadCameraMode;
bool m_bSkipPostSlideShow;
+ bool m_commandViewEnabled;
};
//------------------------------------------------------------------------------