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; }; //------------------------------------------------------------------------------