newgamescreen.cpp 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062
  1. #include "pch.h"
  2. //////////////////////////////////////////////////////////////////////////////
  3. //
  4. // NewGame Screen
  5. //
  6. //////////////////////////////////////////////////////////////////////////////
  7. class NewGameScreen :
  8. public Screen,
  9. public EventTargetContainer<NewGameScreen>,
  10. public TrekClientEventSink
  11. {
  12. private:
  13. TRef<Pane> m_ppane;
  14. TRef<INameSpace> m_pns;
  15. TRef<EditPane> m_peditPaneGameName;
  16. TRef<EditPane> m_peditPaneGamePassword;
  17. TRef<ButtonPane> m_pbuttonBack;
  18. TRef<ButtonPane> m_pbuttonCancel;
  19. TRef<ButtonPane> m_pbuttonCreate;
  20. TRef<ButtonPane> m_pbuttonEjectPods;
  21. TRef<ButtonPane> m_pbuttonFriendlyFire;
  22. TRef<ButtonPane> m_pbuttonStatsCount;
  23. TRef<ButtonPane> m_pbuttonDefections;
  24. TRef<ButtonPane> m_pbuttonJoiners;
  25. TRef<ButtonPane> m_pbuttonSquadGame;
  26. TRef<ButtonPane> m_pbuttonInvulnerableStations;
  27. TRef<ButtonPane> m_pbuttonDevelopment;
  28. TRef<ButtonPane> m_pbuttonAllowShipyards;
  29. TRef<ButtonPane> m_pbuttonShowMap;
  30. TRef<ComboPane> m_pcomboGameType;
  31. TRef<ComboPane> m_pcomboTeamCount;
  32. //TRef<StringPane> m_ptextMinPlayers;
  33. TRef<StringPane> m_ptextMaxPlayers;
  34. TRef<ComboPane> m_pcomboMaxPlayers;
  35. TRef<ComboPane> m_pcomboMaxImbalance;
  36. TRef<ComboPane> m_pcomboSkillLevel;
  37. TRef<ComboPane> m_pcomboMapType;
  38. TRef<ComboPane> m_pcomboConnectivity;
  39. TRef<ComboPane> m_pcomboLives;
  40. TRef<ComboPane> m_pcomboResources;
  41. TRef<ComboPane> m_pcomboTotalMoney;
  42. TRef<ComboPane> m_pcomboStartingMoney;
  43. TRef<ComboPane> m_pcomboCountdownTime;
  44. TRef<ComboPane> m_pcomboDeathWatchKills;
  45. TRef<ComboPane> m_pcomboProsperity;
  46. TRef<ComboPane> m_pcomboArtifactCount;
  47. TRef<ComboPane> m_pcomboFlagCount;
  48. TRef<ComboPane> m_pcomboConquestBases;
  49. TRef<ComboPane> m_pcomboTerritory;
  50. TRef<StringPane> m_ptextCountdown;
  51. TRef<IKeyboardInput> m_pkeyboardInputOldFocus;
  52. TRef<Modeler> m_pmodeler;
  53. TRef<ModifiableNumber> m_pnumberCanChooseMaxPlayers;
  54. TRef<ModifiableNumber> m_pnumberIsCustomMap;
  55. bool m_bIsZoneClub;
  56. bool m_bLockGameOpen;
  57. bool m_bIgnoreGameTypeComboChanges;
  58. bool m_fQuitting;
  59. int GetResourceLevel(const MissionParams& missionparams)
  60. {
  61. int ResourceCount = missionparams.nPlayerSectorMineableAsteroids
  62. + missionparams.nNeutralSectorMineableAsteroids
  63. + missionparams.nPlayerSectorSpecialAsteroids
  64. + missionparams.nNeutralSectorAsteroids;
  65. if (ResourceCount > 9)
  66. return 4;
  67. else if (ResourceCount > 6)
  68. return 3;
  69. else if (ResourceCount > 5)
  70. return 2;
  71. else if (ResourceCount > 2)
  72. return 1;
  73. else
  74. return 0;
  75. }
  76. const MissionParams& GetBaseMissionParams()
  77. {
  78. return trekClient.MyMission()->GetMissionParams();
  79. }
  80. void RefreshMissionParams()
  81. {
  82. ApplyMissionParams(GetBaseMissionParams());
  83. }
  84. void ApplyMissionParams(const MissionParams& missionparams)
  85. {
  86. m_peditPaneGameName->SetString(missionparams.strGameName);
  87. m_peditPaneGamePassword->SetString(missionparams.strGamePassword);
  88. m_pbuttonEjectPods ->SetChecked(missionparams.bEjectPods);
  89. m_pbuttonFriendlyFire ->SetChecked(missionparams.bAllowFriendlyFire);
  90. m_pbuttonStatsCount ->SetChecked(missionparams.bScoresCount);
  91. m_pbuttonDefections ->SetChecked(missionparams.bAllowDefections);
  92. m_pbuttonJoiners ->SetChecked(missionparams.bAllowJoiners);
  93. m_pbuttonSquadGame ->SetChecked(missionparams.bSquadGame);
  94. m_pbuttonInvulnerableStations->SetChecked(missionparams.bInvulnerableStations);
  95. m_pbuttonDevelopment ->SetChecked(missionparams.bAllowDevelopments);
  96. m_pbuttonAllowShipyards ->SetChecked(missionparams.bAllowShipyardPath);
  97. m_pbuttonShowMap ->SetChecked(missionparams.bShowMap);
  98. m_pcomboTeamCount->SetSelection(FindClosestValue(missionparams.nTeams, "TeamCountValues"));
  99. m_pcomboMaxPlayers->SetSelection(FindClosestValue(missionparams.nMaxPlayersPerTeam, "MaxPlayersValues"));
  100. m_ptextMaxPlayers->SetString(ZString(missionparams.nMinPlayersPerTeam)
  101. + " - " + ZString(missionparams.nMaxPlayersPerTeam));
  102. //m_ptextMinPlayers->SetString(ZString(missionparams.nMinPlayersPerTeam));
  103. m_pcomboMaxImbalance ->SetSelection(FindClosestValue(missionparams.iMaxImbalance, "MaxImbalanceValues"));
  104. const char* vszSkillLevelNames[2] = {"GameSkillLevelMin", "GameSkillLevelMax"};
  105. float vfSkillLevel[2] = { (float)missionparams.iMinRank, (float)missionparams.iMaxRank };
  106. m_pcomboSkillLevel ->SetSelection(FindClosestValue(vfSkillLevel, vszSkillLevelNames, 2));
  107. m_pcomboConnectivity ->SetSelection(FindClosestValue(missionparams.iRandomEncounters, "ConnectivityValues"));
  108. m_pcomboLives ->SetSelection(FindClosestValue(missionparams.iLives, "LivesValues"));
  109. if (missionparams.szCustomMapFile[0] == '\0')
  110. {
  111. m_pcomboMapType->SetSelection(FindClosestValue(missionparams.mmMapType, "MapTypeValues"));
  112. m_pnumberIsCustomMap->SetValue(0.0f);
  113. }
  114. else
  115. {
  116. int mapTypeIndex = FindMapType(missionparams.szCustomMapFile);
  117. if (mapTypeIndex == NA)
  118. {
  119. m_pnumberIsCustomMap->SetValue(1.0f);
  120. }
  121. else
  122. {
  123. m_pnumberIsCustomMap->SetValue(0.0f);
  124. m_pcomboMapType->SetSelection(CustomMapIDToItemID(mapTypeIndex));
  125. }
  126. }
  127. const char* vszResourceNames[4] = {"ResourcesNeutralMinable",
  128. "ResourcesPlayerMinable", "ResourcesNeutralSpecial", "ResourcesPlayerSpecial"};
  129. float vfResourceLevels[4] = {
  130. (float)missionparams.nNeutralSectorMineableAsteroids,
  131. (float)missionparams.nPlayerSectorMineableAsteroids,
  132. (float)missionparams.nNeutralSectorSpecialAsteroids,
  133. (float)missionparams.nPlayerSectorSpecialAsteroids,
  134. };
  135. m_pcomboResources ->SetSelection(FindClosestValue(vfResourceLevels, vszResourceNames, 4));
  136. m_pcomboTotalMoney ->SetSelection(FindClosestValue(missionparams.fHe3Density, "TotalMoneyValues"));
  137. m_pcomboStartingMoney ->SetSelection(FindClosestValue(missionparams.fStartingMoney, "StartingMoneyValues"));
  138. m_pcomboCountdownTime ->SetSelection(FindClosestValue(missionparams.dtGameLength / 60.0f, "CountdownTimeValues"));
  139. m_pcomboDeathWatchKills->SetSelection(FindClosestValue(missionparams.nGoalTeamKills, "DeathWatchKillsValues"));
  140. m_pcomboProsperity ->SetSelection(FindClosestValue(missionparams.fGoalTeamMoney, "ProsperityTargetValues"));
  141. m_pcomboArtifactCount ->SetSelection(FindClosestValue(missionparams.nGoalArtifactsCount, "ArtifactCountValues"));
  142. m_pcomboFlagCount ->SetSelection(FindClosestValue(missionparams.nGoalFlagsCount, "FlagCountValues"));
  143. m_pcomboConquestBases ->SetSelection(FindClosestValue(missionparams.iGoalConquestPercentage, "ConquestPercentValues"));
  144. m_pcomboTerritory ->SetSelection(FindClosestValue(missionparams.iGoalTerritoryPercentage, "TerritoryValues"));
  145. m_bIsZoneClub = missionparams.bClubGame;
  146. m_bLockGameOpen = missionparams.bLockGameOpen;
  147. }
  148. public:
  149. ZString YesNo(bool b)
  150. {
  151. return b ? "yes" : "no";
  152. }
  153. ZString GetNthString(const char* szContentName, int index)
  154. {
  155. IObjectList* plist;
  156. CastTo(plist, m_pns->FindMember(szContentName));
  157. plist->GetFirst();
  158. while (index > 0) {
  159. plist->GetNext();
  160. index--;
  161. }
  162. return GetString(plist->GetCurrent());
  163. }
  164. ZString GetLives(const MissionParams& missionparams)
  165. {
  166. if (missionparams.iLives == 32767) {
  167. return "Unlimited";
  168. } else {
  169. return missionparams.iLives;
  170. }
  171. }
  172. ZString GetMapType(const MissionParams& missionparams)
  173. {
  174. if (missionparams.szCustomMapFile[0] == '\0') {
  175. return GetNthString("MapTypeNames", missionparams.mmMapType);
  176. } else {
  177. return "Custom Map " + ZString(missionparams.szCustomMapFile);
  178. }
  179. }
  180. ZString GetResourceString(const MissionParams& missionparams)
  181. {
  182. const char* vszResourceNames[4] = {
  183. "ResourcesNeutralMinable",
  184. "ResourcesPlayerMinable",
  185. "ResourcesNeutralSpecial",
  186. "ResourcesPlayerSpecial"
  187. };
  188. float vfResourceLevels[4] = {
  189. (float)missionparams.nNeutralSectorMineableAsteroids,
  190. (float)missionparams.nPlayerSectorMineableAsteroids,
  191. (float)missionparams.nNeutralSectorSpecialAsteroids,
  192. (float)missionparams.nPlayerSectorSpecialAsteroids,
  193. };
  194. return GetNthString("ResourcesNames", FindClosestValue(vfResourceLevels, vszResourceNames, 4));
  195. }
  196. NewGameScreen(Modeler* pmodeler, ZString& str)
  197. {
  198. //
  199. // Open the namespace
  200. //
  201. m_pmodeler = pmodeler;
  202. OpenMDLFile();
  203. //
  204. // Initialize just enough to allow the mission parameters to be written out as a string
  205. //
  206. const MissionParams& mp = trekClient.MyMission()->GetMissionParams();
  207. str =
  208. "Name: " + ZString(mp.strGameName) + "<p>"
  209. + "<p>"
  210. + "Lives: " + GetLives(mp) + "<p>"
  211. + "Map Type: " + GetMapType(mp) + "<p>"
  212. + "Resources: " + GetResourceString(mp) + "<p>"
  213. + "Scores Count: " + YesNo(mp.bScoresCount) + "<p>"
  214. + "Eject Pods: " + YesNo(mp.bEjectPods) + "<p>"
  215. + "Allow Friendly Fire: " + YesNo(mp.bAllowFriendlyFire) + "<p>"
  216. + "Allow Defections: " + YesNo(mp.bAllowDefections) + "<p>"
  217. + "Allow Joiners " + YesNo(mp.bAllowJoiners) + "<p>"
  218. + "Invulnerable Stations: " + YesNo(mp.bInvulnerableStations) + "<p>"
  219. + "Developments: " + YesNo(mp.bAllowDevelopments) + "<p>"
  220. + "Allow Shipyards: " + YesNo(mp.bAllowShipyardPath) + "<p>"
  221. + "<p>"
  222. ;
  223. }
  224. void OpenMDLFile()
  225. {
  226. TRef<INameSpace> pnsTeamScreenData = GetModeler()->CreateNameSpace("newgamescreendata");
  227. pnsTeamScreenData->AddMember("CanChooseMaxPlayers", m_pnumberCanChooseMaxPlayers = new ModifiableNumber(0));
  228. pnsTeamScreenData->AddMember("IsCustomMap", m_pnumberIsCustomMap = new ModifiableNumber(0));
  229. m_pns = m_pmodeler->GetNameSpace("newgamescreen");
  230. }
  231. NewGameScreen(Modeler* pmodeler)
  232. {
  233. //
  234. // Read the mdl file
  235. //
  236. m_pmodeler = pmodeler;
  237. OpenMDLFile();
  238. m_fQuitting = false;
  239. m_bIgnoreGameTypeComboChanges = false;
  240. CastTo(m_ppane, m_pns->FindMember("screen"));
  241. //
  242. // Buttons
  243. //
  244. CastTo(m_pbuttonCancel, m_pns->FindMember("cancelButtonPane"));
  245. CastTo(m_pbuttonBack, m_pns->FindMember("backButtonPane"));
  246. AddEventTarget(OnButtonBack, m_pbuttonBack->GetEventSource());
  247. CastTo(m_pbuttonCreate, m_pns->FindMember("createButtonPane"));
  248. AddEventTarget(OnButtonBack, m_pbuttonCancel->GetEventSource());
  249. AddEventTarget(OnButtonCreate, m_pbuttonCreate->GetEventSource());
  250. //
  251. // Edit controls
  252. //
  253. CastTo(m_peditPaneGameName, (Pane*)m_pns->FindMember("gameNameEditPane"));
  254. m_peditPaneGameName->SetMaxLength(c_cbGameName - 37);
  255. CastTo(m_peditPaneGamePassword, (Pane*)m_pns->FindMember("gamePasswordEditPane"));
  256. m_peditPaneGamePassword->SetMaxLength(c_cbGamePassword - 1);
  257. AddEventTarget(OnGameNameClick, m_peditPaneGameName->GetClickEvent());
  258. AddEventTarget(OnGamePasswordClick, m_peditPaneGamePassword->GetClickEvent());
  259. //
  260. // Checkboxes
  261. //
  262. CastTo(m_pbuttonEjectPods , m_pns->FindMember("ejectPodsCheckboxPane"));
  263. CastTo(m_pbuttonFriendlyFire , m_pns->FindMember("friendlyFireCheckboxPane"));
  264. CastTo(m_pbuttonStatsCount , m_pns->FindMember("statsCountCheckboxPane"));
  265. CastTo(m_pbuttonDefections , m_pns->FindMember("defectionsCheckboxPane"));
  266. CastTo(m_pbuttonJoiners , m_pns->FindMember("joinersCheckboxPane"));
  267. CastTo(m_pbuttonSquadGame , m_pns->FindMember("squadGameCheckboxPane"));
  268. CastTo(m_pbuttonInvulnerableStations, m_pns->FindMember("invulnerableStationsCheckboxPane"));
  269. CastTo(m_pbuttonDevelopment , m_pns->FindMember("developmentCheckboxPane"));
  270. CastTo(m_pbuttonAllowShipyards , m_pns->FindMember("allowShipyardsCheckboxPane"));
  271. CastTo(m_pbuttonShowMap , m_pns->FindMember("showMapCheckboxPane"));
  272. //
  273. // Combo boxes
  274. //
  275. CastTo(m_pcomboGameType , m_pns->FindMember("gameTypeComboPane"));
  276. CastTo(m_pcomboTeamCount , m_pns->FindMember("teamCountComboPane"));
  277. CastTo(m_pcomboMaxPlayers , m_pns->FindMember("maxPlayersComboPane"));
  278. CastTo(m_ptextMaxPlayers , m_pns->FindMember("maxPlayersStringPane"));
  279. //CastTo(m_ptextMinPlayers , m_pns->FindMember("minPlayersStringPane"));
  280. CastTo(m_pcomboMaxImbalance , m_pns->FindMember("maxImbalanceComboPane"));
  281. CastTo(m_pcomboSkillLevel , m_pns->FindMember("skillLevelComboPane"));
  282. CastTo(m_pcomboMapType , m_pns->FindMember("mapTypeComboPane"));
  283. CastTo(m_pcomboConnectivity , m_pns->FindMember("connectivityComboPane"));
  284. CastTo(m_pcomboLives , m_pns->FindMember("livesComboPane"));
  285. CastTo(m_pcomboResources , m_pns->FindMember("resourcesComboPane"));
  286. CastTo(m_pcomboTotalMoney , m_pns->FindMember("totalMoneyComboPane"));
  287. CastTo(m_pcomboStartingMoney , m_pns->FindMember("startingMoneyComboPane"));
  288. CastTo(m_pcomboCountdownTime , m_pns->FindMember("countdownTimeComboPane"));
  289. CastTo(m_pcomboDeathWatchKills , m_pns->FindMember("deathWatchKillsComboPane"));
  290. CastTo(m_pcomboProsperity , m_pns->FindMember("prosperityComboPane"));
  291. CastTo(m_pcomboArtifactCount , m_pns->FindMember("artifactCountComboPane"));
  292. CastTo(m_pcomboFlagCount , m_pns->FindMember("flagCountComboPane"));
  293. CastTo(m_pcomboConquestBases , m_pns->FindMember("conquestBasesComboPane"));
  294. CastTo(m_pcomboTerritory , m_pns->FindMember("territoryComboPane"));
  295. TList<TRef<GameType> >::Iterator gameTypesIter(GameType::GetGameTypes());
  296. int index = 0;
  297. while (!gameTypesIter.End())
  298. {
  299. m_pcomboGameType->AddItem(gameTypesIter.Value()->GetName(), index);
  300. gameTypesIter.Next();
  301. index++;
  302. }
  303. m_pcomboGameType->AddItem("Custom", index);
  304. MissionParams misparams = GetBaseMissionParams();
  305. FillCombo(m_pcomboMaxPlayers , "MaxPlayersNames");
  306. FillCombo(m_pcomboTeamCount , "TeamCountNames");
  307. FillCombo(m_pcomboMaxImbalance , "MaxImbalanceNames");
  308. FillCombo(m_pcomboSkillLevel , "GameSkillLevelNames");
  309. FillCombo(m_pcomboConnectivity , "ConnectivityNames");
  310. FillCombo(m_pcomboLives , "LivesNames");
  311. FillCombo(m_pcomboResources , "ResourcesNames");
  312. FillCombo(m_pcomboTotalMoney , "TotalMoneyNames");
  313. FillCombo(m_pcomboStartingMoney , "StartingMoneyNames");
  314. FillCombo(m_pcomboCountdownTime , "CountdownTimeNames");
  315. FillCombo(m_pcomboDeathWatchKills , "DeathWatchKillsNames");
  316. FillCombo(m_pcomboProsperity , "ProsperityTargetNames");
  317. FillCombo(m_pcomboArtifactCount , "ArtifactCountNames");
  318. FillCombo(m_pcomboFlagCount , "FlagCountNames");
  319. FillCombo(m_pcomboConquestBases , "ConquestPercentNames");
  320. FillCombo(m_pcomboTerritory , "TerritoryNames");
  321. FillCombo(m_pcomboMapType , "MapTypeNames");
  322. AddCustomMapTypes();
  323. AddEventTarget(OnPickGameType, m_pcomboGameType->GetEventSource());
  324. //
  325. // Countdown box
  326. //
  327. CastTo(m_ptextCountdown, (Pane*)m_pns->FindMember("textCountdown"));
  328. //
  329. // Add event hooks
  330. //
  331. AddEventTarget(OnMaxPlayersChange, m_pcomboMaxPlayers->GetEventSource());
  332. AddEventTarget(OnTeamCountChange, m_pcomboTeamCount->GetEventSource());
  333. AddEventTarget(OnGameTypeRelatedComboChange, m_pcomboLives->GetEventSource());
  334. AddEventTarget(OnGameTypeRelatedComboChange, m_pcomboCountdownTime->GetEventSource());
  335. AddEventTarget(OnGameTypeRelatedComboChange, m_pcomboDeathWatchKills->GetEventSource());
  336. AddEventTarget(OnGameTypeRelatedComboChange, m_pcomboProsperity->GetEventSource());
  337. AddEventTarget(OnGameTypeRelatedComboChange, m_pcomboArtifactCount->GetEventSource());
  338. AddEventTarget(OnGameTypeRelatedComboChange, m_pcomboFlagCount->GetEventSource());
  339. AddEventTarget(OnGameTypeRelatedComboChange, m_pcomboConquestBases->GetEventSource());
  340. AddEventTarget(OnGameTypeRelatedComboChange, m_pcomboTerritory->GetEventSource());
  341. AddEventTarget(OnGameTypeRelatedCheckboxChange, m_pbuttonInvulnerableStations->GetEventSource());
  342. AddEventTarget(OnGameTypeRelatedCheckboxChange, m_pbuttonDevelopment->GetEventSource());
  343. AddEventTarget(OnGameTypeRelatedCheckboxChange, m_pbuttonStatsCount->GetEventSource());
  344. //
  345. // set the keyboard focus
  346. //
  347. m_pkeyboardInputOldFocus = GetWindow()->GetFocus();
  348. if (CanEdit())
  349. GetWindow()->SetFocus(m_peditPaneGameName);
  350. if (g_bQuickstart) {
  351. OnButtonCreate();
  352. }
  353. //
  354. // Unload the namespace so that everything will be reset the next time we
  355. // come to this screen.
  356. //
  357. RefreshMissionParams();
  358. UpdateButtonStates();
  359. UpdateGameType();
  360. }
  361. ~NewGameScreen()
  362. {
  363. m_pmodeler->UnloadNameSpace("newgamescreen");
  364. if (m_pkeyboardInputOldFocus) {
  365. GetWindow()->SetFocus(m_pkeyboardInputOldFocus);
  366. }
  367. }
  368. //////////////////////////////////////////////////////////////////////////////
  369. //
  370. // Methods
  371. //
  372. //////////////////////////////////////////////////////////////////////////////
  373. void FillCombo(ComboPane* pcombo, const char* szContentName)
  374. {
  375. IObjectList* plist;
  376. CastTo(plist, m_pns->FindMember(szContentName));
  377. plist->GetFirst();
  378. int index = 0;
  379. while (plist->GetCurrent() != NULL) {
  380. pcombo->AddItem(GetString(plist->GetCurrent()), index);
  381. plist->GetNext();
  382. ++index;
  383. }
  384. }
  385. void FillIntComboWithLimit(ComboPane* pcombo, float fLimit, const char* szContentName, const char* szTableName)
  386. {
  387. IObjectList* plist;
  388. IObjectList* plistValue;
  389. CastTo(plist, m_pns->FindMember(szContentName));
  390. CastTo(plistValue, m_pns->FindMember(szTableName));
  391. plist->GetFirst();
  392. plistValue->GetFirst();
  393. bool bEliminatedItem = false;
  394. int index = 0;
  395. while (plist->GetCurrent() != NULL)
  396. {
  397. float fValue = GetNumber(plistValue->GetCurrent());
  398. if (fValue < fLimit)
  399. pcombo->AddItem(GetString(plist->GetCurrent()), (int)fValue);
  400. else
  401. bEliminatedItem = true;
  402. plist->GetNext();
  403. plistValue->GetNext();
  404. ++index;
  405. }
  406. if (bEliminatedItem)
  407. pcombo->AddItem(ZString((int)fLimit), (int)fLimit);
  408. }
  409. float FindValue(int index, const char* szTableName)
  410. {
  411. IObjectList* plist;
  412. CastTo(plist, m_pns->FindMember(szTableName));
  413. plist->GetFirst();
  414. while (index > 0)
  415. {
  416. plist->GetNext();
  417. --index;
  418. }
  419. return GetNumber(plist->GetCurrent());
  420. }
  421. int FindClosestValue(float fValue, const char* szTableName)
  422. {
  423. IObjectList* plist;
  424. CastTo(plist, m_pns->FindMember(szTableName));
  425. plist->GetFirst();
  426. int indexClosest = 0;
  427. float fDistanceClosest = 1e10f;
  428. int index = 0;
  429. while (plist->GetCurrent() != NULL)
  430. {
  431. float fDistance = fabs(fValue - GetNumber(plist->GetCurrent()));
  432. if (fDistance < fDistanceClosest)
  433. {
  434. fDistanceClosest = fDistance;
  435. indexClosest = index;
  436. }
  437. plist->GetNext();
  438. ++index;
  439. }
  440. return indexClosest;
  441. }
  442. int FindClosestValue(int nValue, const char* szTableName)
  443. {
  444. return FindClosestValue((float)nValue, szTableName);
  445. }
  446. int FindClosestValue(float fValue[], const char* szTableName[], int nLists)
  447. {
  448. TVector<IObjectList*> plists;
  449. {
  450. for (int nList = 0; nList < nLists; nList++)
  451. {
  452. IObjectList* plist;
  453. CastTo(plist, m_pns->FindMember(szTableName[nList]));
  454. plists.PushEnd(plist);
  455. plists[nList]->GetFirst();
  456. }
  457. }
  458. int indexClosest = 0;
  459. float fDistanceClosest = 1e10f;
  460. int index = 0;
  461. while (plists[0]->GetCurrent() != NULL) {
  462. float fDistance = 0;
  463. for (int nList = 0; nList < nLists; nList++)
  464. {
  465. fDistance += fabs(fValue[nList] - GetNumber(plists[nList]->GetCurrent()));
  466. plists[nList]->GetNext();
  467. }
  468. if (fDistance < fDistanceClosest)
  469. {
  470. fDistanceClosest = fDistance;
  471. indexClosest = index;
  472. }
  473. ++index;
  474. }
  475. return indexClosest;
  476. }
  477. void AddCustomMapTypes()
  478. {
  479. for (int i = 0; i < trekClient.GetNumStaticMaps(); i++)
  480. {
  481. m_pcomboMapType->AddItem(trekClient.GetStaticMapInfo(i).cbFriendlyName, CustomMapIDToItemID(i));
  482. }
  483. }
  484. int FindMapType(const char* szMapFile)
  485. {
  486. for (int i = 0; i < trekClient.GetNumStaticMaps(); i++)
  487. {
  488. if (strcmp(szMapFile, trekClient.GetStaticMapInfo(i).cbIGCFile) == 0)
  489. return i;
  490. }
  491. return NA;
  492. }
  493. int CustomMapIDToItemID(int mapID)
  494. {
  495. assert(mapID >= 0 && mapID < trekClient.GetNumStaticMaps());
  496. return -1 - mapID;
  497. }
  498. int ItemIDToCustomMapID(int itemID)
  499. {
  500. int mapID = -(itemID + 1);
  501. assert(mapID >= 0 && mapID < trekClient.GetNumStaticMaps());
  502. return mapID;
  503. }
  504. int ItemIDToMapType(int itemID)
  505. {
  506. if (itemID >= 0)
  507. return FindValue(itemID, "MapTypeValues");
  508. else
  509. return 0;
  510. }
  511. const char* ItemIDToMapFile(int itemID)
  512. {
  513. if (itemID >= 0)
  514. return "";
  515. else
  516. return trekClient.GetStaticMapInfo(ItemIDToCustomMapID(itemID)).cbIGCFile;
  517. }
  518. bool ValidateNumTeams(int cRequested, int itemID)
  519. {
  520. if (itemID >= 0)
  521. return true;
  522. else
  523. return trekClient.GetStaticMapInfo(ItemIDToCustomMapID(itemID)).nNumTeams == cRequested;
  524. }
  525. bool ValidateNumTeams(int cRequested, const char* szIGCFile)
  526. {
  527. int mapTypeIndex = FindMapType(szIGCFile);
  528. if (mapTypeIndex == NA)
  529. return true;
  530. else
  531. return ValidateNumTeams(cRequested, CustomMapIDToItemID(mapTypeIndex));
  532. }
  533. //////////////////////////////////////////////////////////////////////////////
  534. //
  535. // Events
  536. //
  537. //////////////////////////////////////////////////////////////////////////////
  538. bool OnMaxPlayersChange(int max)
  539. {
  540. //m_ptextMinPlayers->SetString(
  541. // ZString(FindValue(m_pcomboMaxPlayers->GetSelection(), "MinPlayersValues"))
  542. // );
  543. return true;
  544. }
  545. bool OnTeamCountChange(int max)
  546. {
  547. if (!m_bIsZoneClub)
  548. {
  549. m_ptextMaxPlayers->SetString(
  550. ZString(GetBaseMissionParams().nMinPlayersPerTeam) + " - "
  551. + ZString(GetBaseMissionParams().nTotalMaxPlayersPerGame
  552. / (int)FindValue(m_pcomboTeamCount->GetSelection(), "TeamCountValues"))
  553. );
  554. }
  555. return true;
  556. }
  557. bool OnGameNameClick()
  558. {
  559. GetWindow()->SetFocus(m_peditPaneGameName);
  560. return true;
  561. }
  562. bool OnGamePasswordClick()
  563. {
  564. GetWindow()->SetFocus(m_peditPaneGamePassword);
  565. return true;
  566. }
  567. bool OnButtonBack()
  568. {
  569. GetWindow()->screen(ScreenIDTeamScreen);
  570. return true;
  571. }
  572. bool OnPickGameType(int nType)
  573. {
  574. if (!m_bIgnoreGameTypeComboChanges)
  575. {
  576. TList<TRef<GameType> >::Iterator gameTypesIter(GameType::GetGameTypes());
  577. int index = 0;
  578. while (index < nType)
  579. {
  580. assert(!gameTypesIter.End());
  581. index++;
  582. gameTypesIter.Next();
  583. }
  584. if (!gameTypesIter.End())
  585. {
  586. MissionParams misparams;
  587. ReadControls(misparams);
  588. gameTypesIter.Value()->Apply(misparams);
  589. ApplyMissionParams(misparams);
  590. }
  591. }
  592. return true;
  593. }
  594. bool OnGameTypeRelatedCheckboxChange()
  595. {
  596. UpdateGameType();
  597. return true;
  598. }
  599. bool OnGameTypeRelatedComboChange(int nChange)
  600. {
  601. UpdateGameType();
  602. return true;
  603. }
  604. void UpdateGameType()
  605. {
  606. MissionParams misparams;
  607. ReadControls(misparams);
  608. TList<TRef<GameType> >::Iterator gameTypesIter(GameType::GetGameTypes());
  609. int nComboBoxIndex = 0;
  610. while (!gameTypesIter.End() && !gameTypesIter.Value()->IsGameType(misparams))
  611. {
  612. nComboBoxIndex++;
  613. gameTypesIter.Next();
  614. }
  615. if (m_pcomboGameType->GetSelection() != nComboBoxIndex)
  616. {
  617. m_bIgnoreGameTypeComboChanges = true;
  618. m_pcomboGameType->SetSelection(nComboBoxIndex);
  619. m_bIgnoreGameTypeComboChanges = false;
  620. }
  621. }
  622. void ReadControls(MissionParams& misparams)
  623. {
  624. misparams = GetBaseMissionParams();
  625. strcpy(misparams.strGameName, m_peditPaneGameName->GetString());
  626. strcpy(misparams.strGamePassword, m_peditPaneGamePassword->GetString());
  627. misparams.bEjectPods = m_pbuttonEjectPods->GetChecked();
  628. misparams.bAllowFriendlyFire = m_pbuttonFriendlyFire->GetChecked();
  629. misparams.bScoresCount = m_pbuttonStatsCount->GetChecked();
  630. misparams.bAllowDefections = m_pbuttonDefections->GetChecked();
  631. misparams.bAllowJoiners = m_pbuttonJoiners->GetChecked();
  632. misparams.bSquadGame = m_pbuttonSquadGame->GetChecked();
  633. misparams.bInvulnerableStations = m_pbuttonInvulnerableStations->GetChecked();
  634. misparams.bAllowDevelopments = m_pbuttonDevelopment->GetChecked();
  635. misparams.bAllowShipyardPath = m_pbuttonAllowShipyards->GetChecked();
  636. misparams.bShowMap = m_pbuttonShowMap->GetChecked();
  637. misparams.nTeams = FindValue(m_pcomboTeamCount->GetSelection(), "TeamCountValues");
  638. if (m_bIsZoneClub)
  639. {
  640. misparams.nMinPlayersPerTeam = FindValue(m_pcomboMaxPlayers->GetSelection(), "MinPlayersValues");
  641. misparams.nMaxPlayersPerTeam = FindValue(m_pcomboMaxPlayers->GetSelection(), "MaxPlayersValues");
  642. }
  643. else
  644. {
  645. misparams.nMinPlayersPerTeam = 1;
  646. misparams.nMaxPlayersPerTeam = misparams.nTotalMaxPlayersPerGame / misparams.nTeams;
  647. }
  648. misparams.iMaxImbalance = FindValue(m_pcomboMaxImbalance->GetSelection(), "MaxImbalanceValues");
  649. misparams.iMinRank = FindValue(m_pcomboSkillLevel->GetSelection(), "GameSkillLevelMin");
  650. misparams.iMaxRank = FindValue(m_pcomboSkillLevel->GetSelection(), "GameSkillLevelMax");
  651. misparams.mmMapType = ItemIDToMapType(m_pcomboMapType->GetSelection());
  652. strcpy(misparams.szCustomMapFile, ItemIDToMapFile(m_pcomboMapType->GetSelection()));
  653. misparams.iRandomEncounters = FindValue(m_pcomboConnectivity->GetSelection(), "ConnectivityValues");
  654. misparams.iLives = FindValue(m_pcomboLives->GetSelection(), "LivesValues");
  655. misparams.nNeutralSectorMineableAsteroids = FindValue(m_pcomboResources->GetSelection(), "ResourcesNeutralMinable");
  656. misparams.nPlayerSectorMineableAsteroids = FindValue(m_pcomboResources->GetSelection(), "ResourcesPlayerMinable");
  657. misparams.nNeutralSectorSpecialAsteroids = FindValue(m_pcomboResources->GetSelection(), "ResourcesNeutralSpecial");
  658. misparams.nPlayerSectorSpecialAsteroids = FindValue(m_pcomboResources->GetSelection(), "ResourcesPlayerSpecial");
  659. misparams.fHe3Density = FindValue(m_pcomboTotalMoney->GetSelection(), "TotalMoneyValues");
  660. misparams.fStartingMoney = FindValue(m_pcomboStartingMoney->GetSelection(), "StartingMoneyValues");
  661. misparams.dtGameLength = FindValue(m_pcomboCountdownTime->GetSelection(), "CountdownTimeValues") * 60.0f;
  662. misparams.nGoalTeamKills = FindValue(m_pcomboDeathWatchKills->GetSelection(), "DeathWatchKillsValues");
  663. misparams.fGoalTeamMoney = FindValue(m_pcomboProsperity->GetSelection(), "ProsperityTargetValues");
  664. misparams.nGoalArtifactsCount = FindValue(m_pcomboArtifactCount->GetSelection(), "ArtifactCountValues");
  665. misparams.nGoalFlagsCount = FindValue(m_pcomboFlagCount->GetSelection(), "FlagCountValues");
  666. misparams.iGoalConquestPercentage = FindValue(m_pcomboConquestBases->GetSelection(), "ConquestPercentValues");
  667. misparams.iGoalTerritoryPercentage = FindValue(m_pcomboTerritory->GetSelection(), "TerritoryValues");
  668. }
  669. bool OnButtonCreate()
  670. {
  671. BEGIN_PFM_CREATE_ALLOC(trekClient.m_fm, pfmMissionParams, CS, MISSIONPARAMS)
  672. END_PFM_CREATE
  673. ReadControls(pfmMissionParams->missionparams);
  674. const char* pszReason = pfmMissionParams->missionparams.Invalid(true);
  675. // don't let the player choose a game which they can't play in.
  676. RankID rankOwner = trekClient.MyPlayerInfo()->GetPersistScore(NA).GetRank();
  677. if (!pszReason)
  678. {
  679. if (rankOwner < pfmMissionParams->missionparams.iMinRank)
  680. {
  681. pszReason = "Skill Level must be set low enough for you to play.";
  682. }
  683. else if (rankOwner > pfmMissionParams->missionparams.iMaxRank)
  684. {
  685. pszReason = "Skill Level must be set high enough for you to play.";
  686. }
  687. else if (pfmMissionParams->missionparams.bSquadGame)
  688. {
  689. bool bFoundSquad = false;
  690. for (TList<SquadMembership>::Iterator iterSquad(trekClient.GetSquadMemberships());
  691. !iterSquad.End(); iterSquad.Next())
  692. {
  693. if (iterSquad.Value().GetIsLeader()
  694. || iterSquad.Value().GetIsAssistantLeader())
  695. {
  696. bFoundSquad = true;
  697. break;
  698. }
  699. }
  700. if (!bFoundSquad)
  701. pszReason = "You must be a squad leader or an assistant squad leader to create a squad game";
  702. }
  703. else if (!ValidateNumTeams(pfmMissionParams->missionparams.nTeams, pfmMissionParams->missionparams.szCustomMapFile))
  704. {
  705. int mapTypeIndex = FindMapType(pfmMissionParams->missionparams.szCustomMapFile);
  706. assert(mapTypeIndex != NA);
  707. const StaticMapInfo& mapinfo = trekClient.GetStaticMapInfo(mapTypeIndex);
  708. const char* szFormat = "The map type '%s' can only be played with %d teams";
  709. char* cbTemp = (char*)_alloca(strlen(szFormat) + c_cbName + 8 + 1);
  710. wsprintf(cbTemp, szFormat, mapinfo.cbFriendlyName, mapinfo.nNumTeams);
  711. pszReason = cbTemp;
  712. }
  713. }
  714. if (pszReason)
  715. {
  716. GetWindow()->GetPopupContainer()->OpenPopup(CreateMessageBox(pszReason, NULL),
  717. false);
  718. }
  719. else
  720. {
  721. trekClient.SetMessageType(BaseClient::c_mtGuaranteed);
  722. trekClient.m_fm.QueueExistingMsg((FEDMESSAGE *)pfmMissionParams);
  723. GetWindow()->SetWaitCursor();
  724. GetWindow()->GetPopupContainer()->OpenPopup(
  725. CreateMessageBox("Changing mission parameters...", NULL, false, false, 1.0f),
  726. false
  727. );
  728. m_fQuitting = true;
  729. }
  730. PFM_DEALLOC(pfmMissionParams);
  731. return true;
  732. }
  733. bool CanEdit()
  734. {
  735. return trekClient.GetPlayerInfo()->IsMissionOwner()
  736. && !(trekClient.MyMission()->WasObjectModelCreated() && m_bIsZoneClub)
  737. && trekClient.MyMission()->GetStage() == STAGE_NOTSTARTED;
  738. }
  739. void UpdateButtonStates()
  740. {
  741. bool bEnable = CanEdit();
  742. m_pnumberCanChooseMaxPlayers->SetValue((m_bIsZoneClub && bEnable) ? 1.0f : 0.0f);
  743. m_peditPaneGameName->SetReadOnly(!bEnable);
  744. m_peditPaneGamePassword->SetReadOnly(!bEnable || !m_bIsZoneClub);
  745. m_peditPaneGamePassword->SetType((bEnable && m_bIsZoneClub) ? EditPane::Normal : EditPane::Password);
  746. m_pbuttonEjectPods->SetEnabled(bEnable);
  747. m_pbuttonFriendlyFire->SetEnabled(bEnable);
  748. m_pbuttonStatsCount->SetEnabled(bEnable && m_bIsZoneClub);
  749. m_pbuttonDefections->SetEnabled(bEnable);
  750. m_pbuttonJoiners->SetEnabled(bEnable);
  751. m_pbuttonSquadGame->SetEnabled(bEnable && m_bIsZoneClub);
  752. m_pbuttonInvulnerableStations->SetEnabled(bEnable);
  753. m_pbuttonDevelopment->SetEnabled(bEnable);
  754. m_pbuttonAllowShipyards->SetEnabled(bEnable);
  755. m_pbuttonShowMap->SetEnabled(bEnable);
  756. m_pcomboTeamCount->SetEnabled(bEnable);
  757. m_pcomboMaxPlayers->SetEnabled(bEnable && !m_bLockGameOpen);
  758. m_pcomboMaxImbalance->SetEnabled(bEnable);
  759. m_pcomboSkillLevel->SetEnabled(bEnable);
  760. m_pcomboMapType->SetEnabled(bEnable);
  761. m_pcomboConnectivity->SetEnabled(bEnable);
  762. m_pcomboLives->SetEnabled(bEnable);
  763. m_pcomboResources->SetEnabled(bEnable);
  764. m_pcomboTotalMoney->SetEnabled(bEnable);
  765. m_pcomboStartingMoney->SetEnabled(bEnable);
  766. m_pcomboCountdownTime->SetEnabled(bEnable);
  767. m_pcomboDeathWatchKills->SetEnabled(bEnable);
  768. m_pcomboProsperity->SetEnabled(bEnable);
  769. m_pcomboArtifactCount->SetEnabled(bEnable);
  770. m_pcomboFlagCount->SetEnabled(bEnable);
  771. m_pcomboConquestBases->SetEnabled(bEnable);
  772. m_pcomboTerritory->SetEnabled(bEnable);
  773. m_pcomboGameType->SetEnabled(bEnable);
  774. m_pbuttonCreate->SetEnabled(bEnable);
  775. m_pbuttonCreate->SetHidden(!bEnable);
  776. m_pbuttonCancel->SetHidden(!bEnable);
  777. m_pbuttonBack->SetHidden(bEnable);
  778. }
  779. //////////////////////////////////////////////////////////////////////////////
  780. //
  781. // Fed Message handlers
  782. //
  783. //////////////////////////////////////////////////////////////////////////////
  784. void OnAddPlayer(MissionInfo* pMissionDef, SideID sideID, PlayerInfo* pPlayerInfo)
  785. {
  786. // if this is me...
  787. if (trekClient.MyPlayerInfo()->ShipID() == pPlayerInfo->ShipID())
  788. {
  789. // maybe I'm a new leader
  790. UpdateButtonStates();
  791. }
  792. }
  793. void OnPlayerStatusChange(MissionInfo* pMissionInfo, SideID sideID, PlayerInfo* pPlayerInfo)
  794. {
  795. if (trekClient.MyPlayerInfo()->ShipID() == pPlayerInfo->ShipID())
  796. {
  797. UpdateButtonStates();
  798. }
  799. }
  800. virtual void OnFrame()
  801. {
  802. UpdateCountdownText();
  803. }
  804. void UpdateCountdownText()
  805. {
  806. STAGE stage = trekClient.MyMission()->GetStage();
  807. if (stage == STAGE_STARTING
  808. && trekClient.GetSideID() != SIDE_TEAMLOBBY)
  809. {
  810. GetWindow()->screen(ScreenIDTeamScreen);
  811. }
  812. else if (stage == STAGE_STARTING
  813. || (trekClient.MyMission()->GetMissionParams().bAutoRestart && stage == STAGE_NOTSTARTED))
  814. {
  815. // note: have the timer lag by 1 second to give users the familiar countdown feel
  816. int nTimeLeft = max(0, int(trekClient.MyMission()->GetMissionParams().timeStart - Time::Now()) + 1);
  817. int nMinutesLeft = nTimeLeft/60;
  818. int nSecondsLeft = nTimeLeft - nMinutesLeft * 60;
  819. if (nMinutesLeft > 0)
  820. m_ptextCountdown->SetString(ZString(nMinutesLeft) +
  821. ((nSecondsLeft > 9) ? ":" : ":0") + ZString(nSecondsLeft));
  822. else
  823. m_ptextCountdown->SetString(ZString(nSecondsLeft));
  824. }
  825. else
  826. {
  827. m_ptextCountdown->SetString("");
  828. }
  829. }
  830. virtual void OnMissionCountdown(MissionInfo* pMissionDef)
  831. {
  832. UpdateButtonStates();
  833. }
  834. void OnMissionStarted(MissionInfo* pMissionDef)
  835. {
  836. // if this is our mission and we are not on the lobby side...
  837. if (pMissionDef == trekClient.MyMission() && trekClient.GetSideID() != SIDE_TEAMLOBBY)
  838. {
  839. // switch back the the lobby screen.
  840. GetWindow()->screen(ScreenIDTeamScreen);
  841. GetWindow()->SetWaitCursor();
  842. TRef<IMessageBox> pmsgBox = CreateMessageBox("The game is starting...", NULL, false, false, 1.0f);
  843. GetWindow()->GetPopupContainer()->OpenPopup(pmsgBox, false);
  844. }
  845. }
  846. void OnAddMission(MissionInfo* pMissionInfo)
  847. {
  848. if (pMissionInfo == trekClient.MyMission())
  849. {
  850. if (m_fQuitting)
  851. GetWindow()->screen(ScreenIDTeamScreen);
  852. else
  853. RefreshMissionParams();
  854. }
  855. }
  856. //////////////////////////////////////////////////////////////////////////////
  857. //
  858. // Screen Methods
  859. //
  860. //////////////////////////////////////////////////////////////////////////////
  861. Pane* GetPane()
  862. {
  863. return m_ppane;
  864. }
  865. };
  866. //////////////////////////////////////////////////////////////////////////////
  867. //
  868. // Constructor
  869. //
  870. //////////////////////////////////////////////////////////////////////////////
  871. TRef<Screen> CreateNewGameScreen(Modeler* pmodeler)
  872. {
  873. return new NewGameScreen(pmodeler);
  874. }
  875. TRef<IPopup> CreateMissionParametersPopup(Modeler* pmodeler)
  876. {
  877. ZString str;
  878. TRef<NewGameScreen> pngs = new NewGameScreen(pmodeler, str);
  879. return
  880. CreateMMLPopup(
  881. pmodeler,
  882. str,
  883. true
  884. );
  885. }