/// <summary> /// Executes when the user selects Assign Combat from the static gui /// </summary> public void LoadCombat() { if (GUIRoutines.guiList.Count == 0) { GlobalDefinitions.WriteToCommandFile(GlobalDefinitions.LOADCOMBATKEYWORD); GlobalDefinitions.GuiUpdateStatusMessage("Select a hex to attack; hex must contain enemy units that are adjacent to friendly units"); if (GameControl.gameStateControlInstance.GetComponent <GameStateControl>().currentState.name == "alliedInvasionStateInstance") { GameControl.gameStateControlInstance.GetComponent <GameStateControl>().currentState.executeMethod = GameControl.gameStateControlInstance.GetComponent <GameStateControl>().currentState.GetComponent <AlliedInvasionState>().LoadCombat; } if (GameControl.gameStateControlInstance.GetComponent <GameStateControl>().currentState.name == "alliedAirborneStateInstance") { GameControl.gameStateControlInstance.GetComponent <GameStateControl>().currentState.executeMethod = GameControl.gameStateControlInstance.GetComponent <GameStateControl>().currentState.GetComponent <AlliedAirborneState>().LoadCombat; } if ((GameControl.gameStateControlInstance.GetComponent <GameStateControl>().currentState.name == "alliedMovementStateInstance") || (GameControl.gameStateControlInstance.GetComponent <GameStateControl>().currentState.name == "germanMovementStateInstance")) { GameControl.gameStateControlInstance.GetComponent <GameStateControl>().currentState.executeMethod = GameControl.gameStateControlInstance.GetComponent <GameStateControl>().currentState.GetComponent <MovementState>().LoadCombat; } if ((GameControl.gameStateControlInstance.GetComponent <GameStateControl>().currentState.name == "alliedCombatStateInstance") || (GameControl.gameStateControlInstance.GetComponent <GameStateControl>().currentState.name == "germanCombatStateInstance")) { GameControl.gameStateControlInstance.GetComponent <GameStateControl>().currentState.executeMethod = GameControl.gameStateControlInstance.GetComponent <GameStateControl>().currentState.GetComponent <CombatState>().ExecuteSelectUnit; } } else { GlobalDefinitions.GuiUpdateStatusMessage("Resolve the currently displayed menu before assigning combat"); } }
/// <summary> /// Determines the hex that the selected unit will invade from. /// </summary> /// <param name="selectedUnit"></param> public void GetUnitInvasionHex(GameObject selectedUnit, GameObject selectedHex) { if (selectedHex != null) { if (selectedHex.GetComponent <HexDatabaseFields>().availableForMovement) { GameControl.movementRoutinesInstance.GetComponent <MovementRoutines>().LandAlliedUnitFromOffBoard(selectedUnit, selectedHex, false); } else { GlobalDefinitions.GuiDisplayUnitsOnHex(selectedHex); GlobalDefinitions.GuiUpdateStatusMessage("Hex selected is not available for invasion, must select a highlighted hex"); } } else { GlobalDefinitions.GuiUpdateStatusMessage("No hex selected, must select a highlighted hex"); } if (GlobalDefinitions.selectedUnit != null) { GlobalDefinitions.UnhighlightUnit(GlobalDefinitions.selectedUnit); } GlobalDefinitions.selectedUnit = null; foreach (GameObject hex in HexDefinitions.allHexesOnBoard) { GlobalDefinitions.UnhighlightHex(hex.gameObject); hex.GetComponent <HexDatabaseFields>().availableForMovement = false; } }
/// <summary> /// Executes when the user wants to display the current combats /// </summary> public void ExecuteCombatResolution() { if (GUIRoutines.guiList.Count == 0) { if (GlobalDefinitions.allCombats.Count > 0) { // Turn off the button GameObject.Find("ResolveCombatButton").GetComponent <Button>().interactable = false; CombatResolutionRoutines.CombatResolutionDisplay(); // When this is called by the AI then the line below end up calling two guis when the command file is being read if (!GlobalDefinitions.AICombat) { GlobalDefinitions.WriteToCommandFile(GlobalDefinitions.DISPLAYCOMBATRESOLUTIONKEYWORD); } } else { GlobalDefinitions.GuiUpdateStatusMessage("No combats have been assigned therefore there is nothing to resolve"); } } else { GlobalDefinitions.GuiUpdateStatusMessage("Resolve the currently displayed menu before trying to bring up combat display"); } }
/// <summary> /// Write out the current configuration settings to the configuration file /// </summary> /// <param name="difficultySetting"></param> /// <param name="aggresivenessSetting"></param> public void WriteSettingsFile(int difficultySetting, int aggressiveSetting) { if (File.Exists(GlobalGameFields.settingsFile)) { File.Delete(GlobalGameFields.settingsFile); } StreamWriter fileWriter = new StreamWriter(GlobalGameFields.settingsFile); GlobalDefinitions.WriteToLogFile("writeSettingsFile: creating file = " + GlobalGameFields.settingsFile); if (fileWriter == null) { GlobalDefinitions.GuiUpdateStatusMessage("Unable to create the settings file " + GameControl.path + "TGCSettingsFile.txt"); } else { GlobalDefinitions.difficultySetting = Convert.ToInt32(difficultySetting); GlobalDefinitions.aggressiveSetting = Convert.ToInt32(aggressiveSetting); fileWriter.WriteLine("Difficulty " + difficultySetting); GlobalDefinitions.WriteToLogFile("writeSettingsFile: Difficulty = " + difficultySetting); fileWriter.WriteLine("Aggressive " + aggressiveSetting); GlobalDefinitions.WriteToLogFile("writeSettingsFile: Aggressive = " + aggressiveSetting); fileWriter.Close(); } }
public void SelectUnitToMove() { GlobalDefinitions.WriteToCommandFile(GlobalDefinitions.MULTIUNITSELECTIONKEYWORD + " " + name); List <GameObject> movementHexes = new List <GameObject>(); if (GetComponent <Toggle>().isOn) { if (unit.GetComponent <UnitDatabaseFields>().isCommittedToAnAttack) { GlobalDefinitions.GuiUpdateStatusMessage("Unit selected is committed to an attack\nCancel attack if you want to move this unit"); GetComponent <Toggle>().isOn = false; } else { GlobalDefinitions.HighlightUnit(unit); GlobalDefinitions.selectedUnit = unit; GlobalDefinitions.startHex = unit.GetComponent <UnitDatabaseFields>().occupiedHex; // We don't want to highlight the movement hexes if we're in setup mode if (GameControl.gameStateControlInstance.GetComponent <GameStateControl>().currentState.name != "setUpStateInstance") { movementHexes = GameControl.movementRoutinesInstance.GetComponent <MovementRoutines>().ReturnAvailableMovementHexes(GlobalDefinitions.startHex, GlobalDefinitions.selectedUnit); foreach (GameObject hex in movementHexes) { GlobalDefinitions.HighlightHexForMovement(hex); } } GUIRoutines.RemoveGUI(transform.parent.gameObject); if ((GameControl.gameStateControlInstance.GetComponent <GameStateControl>().currentState.name == "alliedMovementStateInstance") || (GameControl.gameStateControlInstance.GetComponent <GameStateControl>().currentState.name == "germanMovementStateInstance")) { GameControl.gameStateControlInstance.GetComponent <GameStateControl>().currentState.executeMethod = GameControl.gameStateControlInstance.GetComponent <GameStateControl>().currentState.GetComponent <MovementState>().ExecuteSelectUnitDestination; } else if (GameControl.gameStateControlInstance.GetComponent <GameStateControl>().currentState.name == "setUpStateInstance") { GameControl.gameStateControlInstance.GetComponent <GameStateControl>().currentState.executeMethod = GameControl.gameStateControlInstance.GetComponent <GameStateControl>().currentState.GetComponent <SetUpState>().ExecuteSelectUnitDestination; } //if (GlobalDefinitions.localControl && (GlobalDefinitions.gameMode == GlobalDefinitions.GameModeValues.Network)) // GameControl.sendMouseClickToNetwork(GlobalDefinitions.selectedUnit, GlobalDefinitions.startHex); } } else { // This actually should never happen since when the toggle is selected the gui is removed so there is never a chance to unselect the toggle GUIRoutines.RemoveGUI(transform.parent.gameObject); } }
/// <summary> /// Button the ends the current phase on the static gui /// </summary> public void GoToNextPhase() { // Check if there is a gui up before we move to the next phase since it could result in unknown state if (GUIRoutines.guiList.Count == 0) { // Need to do this first since during changes in control the next phase routine passes control so this would never be sent GlobalDefinitions.WriteToCommandFile(GlobalDefinitions.NEXTPHASEKEYWORD); // Quit the current game state GameControl.gameStateControlInstance.GetComponent <GameStateControl>().currentState.ExecuteQuit(); } else { GlobalDefinitions.GuiUpdateStatusMessage("Resolve displayed menu before trying advancing to the next phase"); } }
// Called when the user select to change the status of air support on the combat resolution gui public void AddAttackAirSupport() { if (GetComponent <Toggle>().isOn) { GlobalDefinitions.WriteToCommandFile(GlobalDefinitions.ADDCOMBATAIRSUPPORTKEYWORD + " " + name); if (GlobalDefinitions.tacticalAirMissionsThisTurn < GlobalDefinitions.maxNumberOfTacticalAirMissions) { curentCombat.GetComponent <Combat>().attackAirSupport = true; GlobalDefinitions.WriteToLogFile("addAttackAirSupport: incrementing GlobalDefinitions.tacticalAirMissionsThisTurn"); GlobalDefinitions.tacticalAirMissionsThisTurn++; attackFactorTextGameObject.GetComponent <TextMeshProUGUI>().text = CalculateBattleOddsRoutines.CalculateAttackFactor( curentCombat.GetComponent <Combat>().attackingUnits, curentCombat.GetComponent <Combat>().attackAirSupport).ToString(); oddsTextGameObject.GetComponent <TextMeshProUGUI>().text = GlobalDefinitions.ConvertOddsToString( CalculateBattleOddsRoutines.ReturnCombatOdds(curentCombat.GetComponent <Combat>().defendingUnits, curentCombat.GetComponent <Combat>().attackingUnits, curentCombat.GetComponent <Combat>().attackAirSupport)); } else { GlobalDefinitions.GuiUpdateStatusMessage("No more air support missions left to assign"); GetComponent <Toggle>().isOn = false; } } else { GlobalDefinitions.WriteToCommandFile(GlobalDefinitions.REMOVECOMBATAIRSUPPORTKEYWORD + " " + name); curentCombat.GetComponent <Combat>().attackAirSupport = false; GlobalDefinitions.tacticalAirMissionsThisTurn--; attackFactorTextGameObject.GetComponent <TextMeshProUGUI>().text = CalculateBattleOddsRoutines.CalculateAttackFactor( curentCombat.GetComponent <Combat>().attackingUnits, curentCombat.GetComponent <Combat>().attackAirSupport).ToString(); oddsTextGameObject.GetComponent <TextMeshProUGUI>().text = GlobalDefinitions.ConvertOddsToString( CalculateBattleOddsRoutines.ReturnCombatOdds( curentCombat.GetComponent <Combat>().defendingUnits, curentCombat.GetComponent <Combat>().attackingUnits, curentCombat.GetComponent <Combat>().attackAirSupport)); } }
/// <summary> /// User selects Main Menu from the static gui /// </summary> public void GoToMainMenu() { // If this is a network game and the player isn't in control do not allow to reset. Player has to quit to exit in this case. if (!GlobalDefinitions.localControl && (GlobalDefinitions.gameMode == GlobalDefinitions.GameModeValues.Peer2PeerNetwork)) { GlobalDefinitions.GuiUpdateStatusMessage("Cannot reset game when not in control"); return; } // Turn off the button so that the same gui can't be pulled up GlobalDefinitions.mainMenuButton.GetComponent <Button>().interactable = false; // Turn off any guis that are on if (GUIRoutines.guiList.Count > 0) { foreach (GameObject gui in GUIRoutines.guiList) { gui.SetActive(false); } } GlobalDefinitions.AskUserYesNoQuestion("Are you sure you want to quit?", ref yesButton, ref noButton, YesMain, NoMain); }
/// <summary> /// Called when a unit is selected from the gui to retreat when there are multiple units avaialble /// </summary> public void SelectUnitsToMove() { if (GetComponent <Toggle>().isOn) { GlobalDefinitions.WriteToCommandFile(GlobalDefinitions.RETREATSELECTIONKEYWORD + " " + name); // The unit has been selected so move it to the zero position in the list since that is what will be moved GlobalDefinitions.retreatingUnits.Remove(GetComponent <RetreatToggleRoutines>().unit); GlobalDefinitions.retreatingUnits.Insert(0, GetComponent <RetreatToggleRoutines>().unit); List <GameObject> retreatHexes = CombatResolutionRoutines.ReturnRetreatHexes(GetComponent <RetreatToggleRoutines>().unit); if (retreatHexes.Count > 0) { GlobalDefinitions.HighlightUnit(unit); foreach (GameObject hex in retreatHexes) { GlobalDefinitions.HighlightHexForMovement(hex); } GameControl.gameStateControlInstance.GetComponent <GameStateControl>().currentState.executeMethod = GameControl.gameStateControlInstance.GetComponent <GameStateControl>().currentState.GetComponent <CombatState>().ExecuteRetreatMovement; } // This executes when there is no retreat available for the unit. While the units without retreat available is checked early on, // this is a case where there was more than one unit that needed to retreat but there wasn't room for all of them else { GlobalDefinitions.GuiUpdateStatusMessage("No retreat available - eliminating unit" + unit.name); GlobalDefinitions.MoveUnitToDeadPile(unit); GlobalDefinitions.retreatingUnits.RemoveAt(0); // Need to call selection routines in case there are more units that cannot retreat CombatResolutionRoutines.SelectUnitsForRetreat(); } GUIRoutines.RemoveGUI(transform.parent.gameObject); } }
/// <summary> /// This routine goes through a series of checks to see if the units are setup properly. /// </summary> /// <returns></returns> public static bool UpdateHexFields() { bool returnState = true; // Do an initial load of the GermanUnitsOnBoardList GlobalDefinitions.germanUnitsOnBoard.Clear(); // Clear it out first in case multiple passes are made. foreach (Transform unit in GameObject.Find("Units On Board").transform) { if (unit.GetComponent <UnitDatabaseFields>().nationality == GlobalDefinitions.Nationality.German) { GlobalDefinitions.germanUnitsOnBoard.Add(unit.gameObject); } } GlobalDefinitions.WriteToLogFile("updateHexFields: executing ... number of German units on board = " + GlobalDefinitions.germanUnitsOnBoard.Count); foreach (GameObject unit in GlobalDefinitions.germanUnitsOnBoard) { // Unhighlight the unit so that if all units pass they will be unhighlighted GlobalDefinitions.UnhighlightUnit(unit); // Not sure if this is needed. Can't really be in "Units On Board" without a hex assignment if (unit.GetComponent <UnitDatabaseFields>().occupiedHex == null) { GlobalDefinitions.GuiUpdateStatusMessage("Internal Error - Unit " + unit.GetComponent <UnitDatabaseFields>().name + " is not assigned a hex locunit.GetComponent<UnitDatabaseFields>().ation"); GlobalDefinitions.HighlightUnit(unit); returnState = false; } // German static units must be on a coast or inland port hex else if (unit.GetComponent <UnitDatabaseFields>().germanStatic&& !unit.GetComponent <UnitDatabaseFields>().occupiedHex.GetComponent <HexDatabaseFields>().coast&& !unit.GetComponent <UnitDatabaseFields>().occupiedHex.GetComponent <HexDatabaseFields>().inlandPort&& !unit.GetComponent <UnitDatabaseFields>().occupiedHex.GetComponent <HexDatabaseFields>().coastalPort) { GlobalDefinitions.GuiUpdateStatusMessage(unit.GetComponent <UnitDatabaseFields>().unitDesignation + " is a static unit and must start on a coast hex, a port, or an inland port"); GlobalDefinitions.HighlightUnit(unit); returnState = false; } else if (((unit.name == "Armor-German-3SS") || (unit.name == "Armor-German-9SS") || (unit.name == "Armor-German-25SS") || (unit.name == "Armor-German-49SS") || (unit.name == "Armor-German-51SS") || (unit.name == "Armor-German-106") || (unit.name == "Armor-German-15SS")) && (!unit.GetComponent <UnitDatabaseFields>().occupiedHex.GetComponent <HexDatabaseFields>().germanRepalcement)) { GlobalDefinitions.GuiUpdateStatusMessage(unit.GetComponent <UnitDatabaseFields>().unitDesignation + " must start on a replacement hex (hexes in Germany with a star on them"); GlobalDefinitions.HighlightUnit(unit); returnState = false; } // Setup the ZOC for the hex and its neighbors. Note that I did not bother to do this while the user was moving // units around since I think it makes sense to just do it once when he is done. unit.GetComponent <UnitDatabaseFields>().occupiedHex.GetComponent <HexDatabaseFields>().inGermanZOC = true; foreach (HexDefinitions.HexSides hexSides in Enum.GetValues(typeof(HexDefinitions.HexSides))) { if ((unit.GetComponent <UnitDatabaseFields>().occupiedHex.GetComponent <HexDatabaseFields>().Neighbors[(int)hexSides] != null) && (unit.GetComponent <UnitDatabaseFields>().occupiedHex.GetComponent <BooleanArrayData>().exertsZOC[(int)hexSides])) { unit.GetComponent <UnitDatabaseFields>().occupiedHex.GetComponent <HexDatabaseFields>().Neighbors[(int)hexSides].GetComponent <HexDatabaseFields>().inGermanZOC = true; } } } if (!returnState) { GlobalDefinitions.GuiUpdateStatusMessage("Cannot exit setup until all issues are resolved"); } return(returnState); }
/// <summary> /// This routine gets an invading unit from Britain /// </summary> /// <returns></returns> public GameObject GetInvadingUnit(GameObject selectedUnit) { GlobalDefinitions.WriteToLogFile("getInvadingUnit: executing for unit = " + selectedUnit.name); // Check for valid unit if (selectedUnit == null) { GlobalDefinitions.GuiUpdateStatusMessage("No unit selected; select a unit in Britain that is available to invade this turn"); } // Check if the unit is on a sea hex, this would make it a unit that has already been deployed for an invasion // The user may be picking it in order to undo the selection. else if ((selectedUnit.GetComponent <UnitDatabaseFields>().occupiedHex != null) && (selectedUnit.GetComponent <UnitDatabaseFields>().occupiedHex.GetComponent <HexDatabaseFields>().sea)) { // Hghlight the unit GlobalDefinitions.HighlightUnit(selectedUnit); return(selectedUnit); } // If the unit selected isn't in Britain than display the units in the gui else if (!selectedUnit.GetComponent <UnitDatabaseFields>().inBritain) { if (selectedUnit.GetComponent <UnitDatabaseFields>().occupiedHex != null) { GlobalDefinitions.GuiDisplayUnitsOnHex(selectedUnit.GetComponent <UnitDatabaseFields>().occupiedHex); } } else if (selectedUnit.GetComponent <UnitDatabaseFields>().HQ) { GlobalDefinitions.GuiUpdateStatusMessage("HQ units are not allowed to invade"); } else if (selectedUnit.GetComponent <UnitDatabaseFields>().turnAvailable > GlobalDefinitions.turnNumber) { GlobalDefinitions.GuiUpdateStatusMessage("Unit selected is not available until turn " + selectedUnit.GetComponent <UnitDatabaseFields>().turnAvailable); } else { // Check if the unit is available for the first invasion area if (GlobalDefinitions.turnNumber == 1) { if (GlobalDefinitions.invasionAreas[GlobalDefinitions.firstInvasionAreaIndex].totalUnitsUsedThisTurn < ReturnMaxTotalUnitsForInvasionAreaThisTurn(GlobalDefinitions.invasionAreas[GlobalDefinitions.firstInvasionAreaIndex])) { if (selectedUnit.GetComponent <UnitDatabaseFields>().armor) { if (GlobalDefinitions.invasionAreas[GlobalDefinitions.firstInvasionAreaIndex].armorUnitsUsedThisTurn < ReturnMaxArmorUnitsForInvasionAreaThisTurn(GlobalDefinitions.invasionAreas[GlobalDefinitions.firstInvasionAreaIndex])) { // Valid unit so highlight the hexes available in the invasion area GlobalDefinitions.HighlightUnit(selectedUnit); HighlightAvailableInvasionHexes(GlobalDefinitions.invasionAreas[GlobalDefinitions.firstInvasionAreaIndex]); return(selectedUnit); } } else if (selectedUnit.GetComponent <UnitDatabaseFields>().infantry || selectedUnit.GetComponent <UnitDatabaseFields>().airborne) { //GlobalDefinitions.writeToLogFile("getInvadingUnit: infantry units used this turn = " + GlobalDefinitions.invasionAreas[GlobalDefinitions.firstInvasionAreaIndex].infantryUnitsUsedThisTurn); //GlobalDefinitions.writeToLogFile("getInvadingUnit: max infantry units this turn = " + returnMaxInfantryUnitsForInvasionAreaThisTurn(GlobalDefinitions.invasionAreas[GlobalDefinitions.firstInvasionAreaIndex])); // Need to check for using infantry against the armor limit if ((GlobalDefinitions.invasionAreas[GlobalDefinitions.firstInvasionAreaIndex].infantryUnitsUsedThisTurn < ReturnMaxInfantryUnitsForInvasionAreaThisTurn(GlobalDefinitions.invasionAreas[GlobalDefinitions.firstInvasionAreaIndex])) || (GlobalDefinitions.invasionAreas[GlobalDefinitions.firstInvasionAreaIndex].armorUnitsUsedThisTurn < ReturnMaxArmorUnitsForInvasionAreaThisTurn(GlobalDefinitions.invasionAreas[GlobalDefinitions.firstInvasionAreaIndex]))) { // Valid unit so highlight the hexes available in the invasion area GlobalDefinitions.HighlightUnit(selectedUnit); HighlightAvailableInvasionHexes(GlobalDefinitions.invasionAreas[GlobalDefinitions.firstInvasionAreaIndex]); return(selectedUnit); } } else { // Don't know why we would ever get here but if we do return a null GlobalDefinitions.GuiUpdateStatusMessage("Internal Error - Selected unit is not recognized as armor, infantry, or airborne"); } } } else { // Need to check the second invasion area if (GlobalDefinitions.invasionAreas[GlobalDefinitions.secondInvasionAreaIndex].totalUnitsUsedThisTurn < ReturnMaxTotalUnitsForInvasionAreaThisTurn(GlobalDefinitions.invasionAreas[GlobalDefinitions.secondInvasionAreaIndex])) { if (selectedUnit.GetComponent <UnitDatabaseFields>().armor) { if (GlobalDefinitions.invasionAreas[GlobalDefinitions.secondInvasionAreaIndex].armorUnitsUsedThisTurn < ReturnMaxArmorUnitsForInvasionAreaThisTurn(GlobalDefinitions.invasionAreas[GlobalDefinitions.secondInvasionAreaIndex])) { // Valid unit so highlight the hexes available in the invasion area GlobalDefinitions.HighlightUnit(selectedUnit); HighlightAvailableInvasionHexes(GlobalDefinitions.invasionAreas[GlobalDefinitions.secondInvasionAreaIndex]); return(selectedUnit); } } else if (selectedUnit.GetComponent <UnitDatabaseFields>().infantry || selectedUnit.GetComponent <UnitDatabaseFields>().airborne) { // Need to check for using infantry against the armor limit if ((GlobalDefinitions.invasionAreas[GlobalDefinitions.secondInvasionAreaIndex].infantryUnitsUsedThisTurn < ReturnMaxInfantryUnitsForInvasionAreaThisTurn(GlobalDefinitions.invasionAreas[GlobalDefinitions.secondInvasionAreaIndex])) || (GlobalDefinitions.invasionAreas[GlobalDefinitions.secondInvasionAreaIndex].armorUnitsUsedThisTurn < ReturnMaxArmorUnitsForInvasionAreaThisTurn(GlobalDefinitions.invasionAreas[GlobalDefinitions.secondInvasionAreaIndex]))) { // Valid unit so highlight the hexes available in the invasion area GlobalDefinitions.HighlightUnit(selectedUnit); HighlightAvailableInvasionHexes(GlobalDefinitions.invasionAreas[GlobalDefinitions.secondInvasionAreaIndex]); return(selectedUnit); } } } } } return(null); }
/// <summary> /// This routine pulls all the defenders and attackers based on the hex passed and then calls the combat selection GUI /// </summary> /// <param name="defendingNationality"></param> public void PrepForCombatDisplay(GameObject hex, GlobalDefinitions.Nationality defendingNationality) { // First thing we need to do is check that the combat assignment gui isn't already active. If it is do not load anoether one. if (GameObject.Find("CombatGUIInstance") != null) { GlobalDefinitions.GuiUpdateStatusMessage("Resolve current combat assignment before assigning another"); return; } GameObject singleCombat = new GameObject("prepForCombatDisplay"); singleCombat.AddComponent <Combat>(); // Check if the hex has uncommittted units of the right nationality on it and there are adjacent enemies if ((hex != null) && (hex.GetComponent <HexDatabaseFields>().occupyingUnit.Count > 0) && (hex.GetComponent <HexDatabaseFields>().occupyingUnit[0].GetComponent <UnitDatabaseFields>().nationality == defendingNationality) && NonCommittedDefendersAvailable(hex) && (ReturnUncommittedUnits(ReturnAdjacentEnemyUnits(hex, GlobalDefinitions.ReturnOppositeNationality(defendingNationality))).Count > 0)) { // Get all the available defending units singleCombat.GetComponent <Combat>().defendingUnits = ReturnUncommittedUnits(hex.GetComponent <HexDatabaseFields>().occupyingUnit); singleCombat.GetComponent <Combat>().attackingUnits = ReturnUncommittedUnits(ReturnAdjacentEnemyUnits(hex, GlobalDefinitions.ReturnOppositeNationality(defendingNationality))); // Fianlly we have to get all potential defenders that are adjacent to the attackers foreach (GameObject defender in ReturnUncommittedUnits(ReturnAdjacentDefenders(hex, singleCombat))) { if (!singleCombat.GetComponent <Combat>().defendingUnits.Contains(defender)) { singleCombat.GetComponent <Combat>().defendingUnits.Add(defender); } } CallCombatDisplay(singleCombat); } else { if (hex == null) { GlobalDefinitions.GuiUpdateStatusMessage("No valid hex selected for combat; hex selected must contain enemy units"); } else if (hex.GetComponent <HexDatabaseFields>().occupyingUnit.Count == 0) { GlobalDefinitions.GuiUpdateStatusMessage("No units found on hex selected for combat; hex selected must contain enemy units"); } else if (!NonCommittedDefendersAvailable(hex)) { GlobalDefinitions.GuiUpdateStatusMessage("No uncommitted defenders found on hex selected; all units on hex are already assigned to combat. Cancel attacks and reassign combat to add additional attacking units."); } else if (ReturnUncommittedUnits(ReturnAdjacentEnemyUnits(hex, GlobalDefinitions.ReturnOppositeNationality(defendingNationality))).Count == 0) { GlobalDefinitions.GuiUpdateStatusMessage("No units are available to attack the hex selected"); } //else if (hex.GetComponent<HexDatabaseFields>().occupyingUnit[0].GetComponent<UnitDatabaseFields>().nationality != defendingNationality) else { GlobalDefinitions.GuiDisplayUnitsOnHex(hex); } if ((GameControl.gameStateControlInstance.GetComponent <GameStateControl>().currentState.name == "alliedMovementStateInstance") || (GameControl.gameStateControlInstance.GetComponent <GameStateControl>().currentState.name == "germanMovementStateInstance")) { GameControl.gameStateControlInstance.GetComponent <GameStateControl>().currentState.executeMethod = GameControl.gameStateControlInstance.GetComponent <GameStateControl>().currentState.GetComponent <MovementState>().ExecuteSelectUnit; } else if (GameControl.gameStateControlInstance.GetComponent <GameStateControl>().currentState.name == "alliedInvasionStateInstance") { GameControl.gameStateControlInstance.GetComponent <GameStateControl>().currentState.executeMethod = GameControl.gameStateControlInstance.GetComponent <GameStateControl>().currentState.GetComponent <AlliedInvasionState>().ExecuteSelectUnit; } else if (GameControl.gameStateControlInstance.GetComponent <GameStateControl>().currentState.name == "alliedAirborneStateInstance") { GameControl.gameStateControlInstance.GetComponent <GameStateControl>().currentState.executeMethod = GameControl.gameStateControlInstance.GetComponent <GameStateControl>().currentState.GetComponent <AlliedAirborneState>().ExecuteSelectUnit; } else { GameControl.gameStateControlInstance.GetComponent <GameStateControl>().currentState.executeMethod = GameControl.gameStateControlInstance.GetComponent <GameStateControl>().currentState.GetComponent <CombatState>().ExecuteSelectUnit; } } }
// Use this for initialization void Start() { GlobalDefinitions.InitializeFileNames(); // Set up the log file path = System.IO.Directory.GetCurrentDirectory() + "\\"; // Put the log and command file in a try block since an exception will be thrown if the game was installed in an un-writeable folder try { if (File.Exists(path + GlobalGameFields.logfile)) { File.Delete(path + GlobalGameFields.logfile); } using (StreamWriter logFile = File.AppendText(GameControl.path + GlobalGameFields.logfile)) { logFile.WriteLine("Starting game at: " + DateTime.Now); logFile.WriteLine("GameControl start(): path = " + System.IO.Directory.GetCurrentDirectory() + "\\"); } } catch { MessageBox.Show("ERROR: Cannot access log file - cannot continue"); GlobalDefinitions.GuiUpdateStatusMessage("Internal Error - Cannot access log file - cannot continue"); } GlobalDefinitions.WriteToLogFile("Game Version " + GlobalDefinitions.releaseVersion); // There are three files that should have been installed with the game. Note, I could get rid of all three of these and just have the // board and the units built into the game rather than reading them. But I haven't done this based on a somewhat vauge idea that this will // make future games easier to build. // The three files are: // TGCBoardSetup.txt - this has been split into four files, each checked at time of execution 7/25/20 // TGCBritainUnitLocation.txt // TGCGermanSetup.txt // Check here that the files exist. If they don't then exit out now if (!File.Exists(path + GlobalGameFields.britainUnitLocationFile)) { MessageBox.Show("ERROR: " + GlobalGameFields.britainUnitLocationFile + " file not found - cannot continue"); UnityEngine.Application.Quit(); } else { GlobalGameFields.britainUnitLocationFile = path + GlobalGameFields.britainUnitLocationFile; } //if (!File.Exists(path + "TGCGermanSetup.txt")) if (!File.Exists(path + "GermanSetup//TGCGermanSetup1.txt")) { MessageBox.Show("ERROR: TGCGermanSetup1.txt file not found - cannot continue"); UnityEngine.Application.Quit(); } GlobalDefinitions.nextPhaseButton.GetComponent <UnityEngine.UI.Button>().interactable = false; GlobalDefinitions.undoButton.GetComponent <UnityEngine.UI.Button>().interactable = false; GlobalDefinitions.MustAttackToggle.GetComponent <Toggle>().interactable = false; GlobalDefinitions.AssignCombatButton.GetComponent <UnityEngine.UI.Button>().interactable = false; GlobalDefinitions.DisplayAllCombatsButton.GetComponent <UnityEngine.UI.Button>().interactable = false; GlobalDefinitions.AlliedSupplyRangeToggle.GetComponent <Toggle>().interactable = false; GlobalDefinitions.GermanSupplyRangeToggle.GetComponent <Toggle>().interactable = false; GlobalDefinitions.AlliedSupplySourcesButton.GetComponent <UnityEngine.UI.Button>().interactable = false; // Hide the chat screen. We will turn it back on if the user selects a network game GameObject.Find("ChatInputField").GetComponent <InputField>().onEndEdit.AddListener(delegate { GlobalDefinitions.ExecuteChatMessage(); }); GlobalDefinitions.chatPanel = GameObject.Find("ChatPanel"); GlobalDefinitions.chatPanel.SetActive(false); // Add a canvas to add UI elements (i.e. text) to the board GlobalDefinitions.mapText = new GameObject(); GlobalDefinitions.mapText.name = "Map Text"; GlobalDefinitions.mapText.transform.SetParent(GameObject.Find("Map Graphics").transform); GlobalDefinitions.mapGraphicCanvas = GlobalDefinitions.mapText.AddComponent <Canvas>(); GlobalDefinitions.mapText.AddComponent <CanvasScaler>(); GlobalDefinitions.mapGraphicCanvas.renderMode = RenderMode.WorldSpace; GlobalDefinitions.mapGraphicCanvas.sortingLayerName = "Text"; // The first thing that needs to be done is store the locations of the units. They // are sitting on the order of battle sheet and this will be their "dead" location GlobalDefinitions.WriteToLogFile("Setting unit OOB locations"); foreach (Transform unit in GameObject.Find("Units Eliminated").transform) { unit.GetComponent <UnitDatabaseFields>().OOBLocation = unit.position; } GlobalDefinitions.WriteToLogFile("GameControl start(): Creating Singletons"); // Create singletons of each of the routine classes CreateSingletons(); GlobalDefinitions.WriteToLogFile("GameControl start(): Setting up the map"); // Set up the map from the read location createBoardInstance.GetComponent <CreateBoard>().ReadMapSetup(); // Load the global for storing all hexes on the board //foreach (Transform hex in GameObject.Find("Board").transform) // HexDefinitions.allHexesOnBoard.Add(hex.gameObject); // Deal with the configuration settings GlobalGameFields.settingsFile = path + GlobalGameFields.settingsFile; // Check if the setting file is present, if it isn't write out a default if (!File.Exists(GlobalGameFields.settingsFile)) { GlobalDefinitions.difficultySetting = 5; GlobalDefinitions.aggressiveSetting = 3; readWriteRoutinesInstance.GetComponent <ReadWriteRoutines>().WriteSettingsFile(5, 3); } else { // If the file exists read the configuration settings readWriteRoutinesInstance.GetComponent <ReadWriteRoutines>().ReadSettingsFile(); } // Reset the min/max odds since the aggressiveness has just been read CombatResolutionRoutines.AdjustAggressiveness(); AIRoutines.SetIntrinsicHexValues(); // AI TESTING hexValueGuiInstance = new GameObject(); Canvas hexValueCanvas = hexValueGuiInstance.AddComponent <Canvas>(); hexValueGuiInstance.AddComponent <CanvasScaler>(); hexValueCanvas.renderMode = RenderMode.WorldSpace; hexValueCanvas.sortingLayerName = "Hex"; hexValueGuiInstance.name = "hexValueGuiInstance"; // AI TESTING //foreach (GameObject hex in HexDefinitions.allHexesOnBoard) // GlobalDefinitions.createHexText(Convert.ToString(hex.GetComponent<HexDatabaseFields>().hexValue), hex.name + "HexValueText", 20, 20, hex.position.x, hex.position.y, 14, hexValueCanvas); GlobalDefinitions.WriteToLogFile("GameControl start(): Putting Allied units in Britain - reading from file: " + GlobalGameFields.britainUnitLocationFile); // When restarting a game the units won't have their Britain location loaded so this needs to be done before a restart file is read createBoardInstance.GetComponent <CreateBoard>().ReadBritainPlacement(GlobalGameFields.britainUnitLocationFile); GlobalDefinitions.WriteToLogFile("GameControl start(): Setting up invasion areas"); createBoardInstance.GetComponent <CreateBoard>().SetupInvasionAreas(); // Make sure the game doesn't start with selected unit or hex GlobalDefinitions.selectedUnit = null; GlobalDefinitions.startHex = null; // Reset the list of active GUI's GUIRoutines.guiList.Clear(); gameStateControlInstance = new GameObject("gameStateControl"); gameStateControlInstance.AddComponent <GameStateControl>(); inputMessage = new GameObject("inputMessage"); inputMessage.AddComponent <InputMessage>(); GlobalDefinitions.allUnitsOnBoard = GameObject.Find("Units On Board"); // Turn off the background of the unit display panel GameObject.Find("UnitDisplayPanel").GetComponent <CanvasGroup>().alpha = 0; // Setup the state for when victory is achieved victoryState = new GameObject("victoryState"); victoryState.AddComponent <VictoryState>(); // At this point everything has been setup. Call up GUI to have the user select the type of game being played GlobalDefinitions.WriteToLogFile("GameControl start(): calling getGameModeUI()"); MainMenuRoutines.GetGameModeUI(); }
/// <summary> /// This routine is called when the user selects the Resolve button for a combat /// </summary> public void ResolutionSelected() { // Write out the name of the toggle being executed in order to send it once the die roll is known if (GlobalDefinitions.localControl) { GlobalDefinitions.CombatResultToggleName = name; } // If combat resolution hasn't started then check to make sure all required combats have been created if (!GlobalDefinitions.combatResolutionStarted) { if (CombatRoutines.CheckIfRequiredUnitsAreUncommitted(GameControl.gameStateControlInstance.GetComponent <GameStateControl>().currentState.currentNationality, true)) { GlobalDefinitions.GuiUpdateStatusMessage("Cannot start combat resolution, highlighted units must be committed to combat first."); } else { // All required units are attacking or being attacked GlobalDefinitions.combatResolutionStarted = true; // Get rid of the "Continue" button since combat resolution has started GlobalDefinitions.combatResolutionOKButton.SetActive(false); // Once combat resolution starts, canceling an attack is no longer an option so get rid of all cancel buttons // Also can't assign any more air support so make those toggles non-interactive foreach (GameObject combat in GlobalDefinitions.allCombats) { if (GameControl.gameStateControlInstance.GetComponent <GameStateControl>().currentState.currentNationality == GlobalDefinitions.Nationality.Allied) { combat.GetComponent <Combat>().airSupportToggle.interactable = false; } DestroyImmediate(combat.GetComponent <Combat>().cancelButton.gameObject); } // Only check for carpet bombing if Allies are attacking. This is needed to keep the German attacks from being loaded if (GameControl.gameStateControlInstance.GetComponent <GameStateControl>().currentState.currentNationality == GlobalDefinitions.Nationality.Allied) { GlobalDefinitions.combatResultsFromLastTurn.Clear(); GlobalDefinitions.hexesAttackedLastTurn.Clear(); // Store all hexes being attacked this turn. Used for carpet bombing availability next turn foreach (GameObject combat in GlobalDefinitions.allCombats) { foreach (GameObject defender in combat.GetComponent <Combat>().defendingUnits) { if (!GlobalDefinitions.hexesAttackedLastTurn.Contains(defender.GetComponent <UnitDatabaseFields>().occupiedHex)) { GlobalDefinitions.hexesAttackedLastTurn.Add(defender.GetComponent <UnitDatabaseFields>().occupiedHex); } } } } } } if (GlobalDefinitions.combatResolutionStarted) { CombatResolutionRoutines.DetermineCombatResults(curentCombat, gameObject.GetComponent <RectTransform>().anchoredPosition); // Get rid of the locate button on the attack being resolved, can't gaurantee that the units are still there after resolution DestroyImmediate(curentCombat.GetComponent <Combat>().locateButton.gameObject); //Get rid of the resolve button since the battle has been resolved. This is also used to determine if all combats have been resolved. //DestroyImmediate(GameObject.Find(GlobalDefinitions.CombatResultToggleName)); GUIRoutines.RemoveGUI(gameObject); } // Check if all the attacks have been resolved by seeing if there are any more Resolve buttons left bool allAttacksResolved = true; foreach (GameObject combat in GlobalDefinitions.allCombats) { if (combat.GetComponent <Combat>().resolveButton != null) { allAttacksResolved = false; } } // If all attacks have been resolved turn on the quit button (which is the continue button with the text changed if (allAttacksResolved) { GlobalDefinitions.combatResolutionOKButton.SetActive(true); GlobalDefinitions.combatResolutionOKButton.GetComponent <Button>().GetComponentInChildren <Text>().text = "Quit"; } }
/// <summary> /// This is the routine called to write out the save turn file /// </summary> public void WriteSaveTurnFile(string saveFileType) { // There are three types of saved files: setup, end of Allied turn, and end of German turn. The name of the file reflects this using the string passed string turnString; if (GlobalDefinitions.turnNumber < 10) { turnString = "0" + GlobalDefinitions.turnNumber.ToString(); } else { turnString = GlobalDefinitions.turnNumber.ToString(); } StreamWriter fileWriter = new StreamWriter(GameControl.path + "TGCOutputFiles\\TGCSaveFile_Turn" + turnString + "_" + saveFileType + ".txt"); if (fileWriter == null) { GlobalDefinitions.GuiUpdateStatusMessage("Unable to open save file " + GameControl.path + "TGCOutputFiles\\TGCSaveFile_Turn" + turnString + "_" + saveFileType + ".txt"); } else { fileWriter.WriteLine("Turn " + GlobalDefinitions.turnNumber); fileWriter.Write("Global_Definitions "); GlobalDefinitions.WriteGlobalVariables(fileWriter); fileWriter.WriteLine("Hexes"); foreach (GameObject hex in HexDefinitions.allHexesOnBoard) { hex.GetComponent <HexDatabaseFields>().WriteHexFields(fileWriter); } fileWriter.WriteLine("End"); fileWriter.WriteLine("Units"); foreach (Transform unit in GameObject.Find("Units Eliminated").transform) { unit.GetComponent <UnitDatabaseFields>().WriteUnitFields(fileWriter); } foreach (Transform unit in GlobalDefinitions.allUnitsOnBoard.transform) { unit.GetComponent <UnitDatabaseFields>().WriteUnitFields(fileWriter); } foreach (Transform unit in GameObject.Find("Units In Britain").transform) { unit.GetComponent <UnitDatabaseFields>().WriteUnitFields(fileWriter); } fileWriter.WriteLine("End"); // In network mode the Game Control loads the currentState and it works best if everything is set before it gets called. fileWriter.Write("Game_Control "); if (saveFileType == "Setup") { fileWriter.Write("German"); } else { fileWriter.Write(GameControl.gameStateControlInstance.GetComponent <GameStateControl>().currentState.currentNationality); } fileWriter.WriteLine(); fileWriter.Close(); // A new saved file has been written so delete the current command file and load the new turn file if (!GlobalDefinitions.commandFileBeingRead) { if (File.Exists(GameControl.path + GlobalGameFields.commandFile)) { GlobalDefinitions.DeleteCommandFile(); } using (StreamWriter writeFile = File.AppendText(GameControl.path + GlobalGameFields.commandFile)) { writeFile.WriteLine(GlobalDefinitions.AGGRESSIVESETTINGKEYWORD + " " + GlobalDefinitions.aggressiveSetting); writeFile.WriteLine(GlobalDefinitions.DIFFICULTYSETTINGKEYWORD + " " + GlobalDefinitions.difficultySetting); writeFile.WriteLine("SavedTurnFile " + GameControl.path + "TGCOutputFiles\\TGCSaveFile_Turn" + turnString + "_" + saveFileType + ".txt"); } } } }
public void MoveSelectedUnit() { if (GetComponent <Toggle>().isOn) { GlobalDefinitions.WriteToCommandFile(GlobalDefinitions.SELECTPOSTCOMBATMOVEMENTKEYWORD + " " + name); // The user has selected a unit. If there is only one hex available move it there. // Otherwise turn off the gui, highlight the hexes available and wait for user selection if (GlobalDefinitions.hexesAvailableForPostCombatMovement.Count == 0) { // This should never happen GlobalDefinitions.GuiUpdateStatusMessage("Internal Error - Post-combat unit selected for move but no hexes available"); } else if (GlobalDefinitions.hexesAvailableForPostCombatMovement.Count == 1) { if (GlobalDefinitions.HexUnderStackingLimit(GlobalDefinitions.hexesAvailableForPostCombatMovement[0], GameControl.gameStateControlInstance.GetComponent <GameStateControl>().currentState.currentNationality)) { // Don't need to wait for user input since there is only one hex available // If the unit is on a sea hex than this is a successful invasion if (gameObject.GetComponent <PostCombatMovementToggleRoutines>().unit.GetComponent <UnitDatabaseFields>().occupiedHex.GetComponent <HexDatabaseFields>().sea) { GlobalDefinitions.hexesAvailableForPostCombatMovement[0].GetComponent <HexDatabaseFields>().successfullyInvaded = true; GlobalDefinitions.hexesAvailableForPostCombatMovement[0].GetComponent <HexDatabaseFields>().alliedControl = true; } GameControl.movementRoutinesInstance.GetComponent <MovementRoutines>().MoveUnit(GlobalDefinitions.hexesAvailableForPostCombatMovement[0], gameObject.GetComponent <PostCombatMovementToggleRoutines>().unit.GetComponent <UnitDatabaseFields>().occupiedHex, gameObject.GetComponent <PostCombatMovementToggleRoutines>().unit); } else { GlobalDefinitions.GuiUpdateStatusMessage("Hex is at stacking limit; cannot move unit"); GetComponent <Toggle>().isOn = false; } } else { // The user has options so turn off the gui, highlight the available hexes, load the unit selected, and set the flag to wait for user input GlobalDefinitions.postCombatMovementGuiInstance.SetActive(false); foreach (GameObject hex in GlobalDefinitions.hexesAvailableForPostCombatMovement) { if (GlobalDefinitions.HexUnderStackingLimit(hex, GameControl.gameStateControlInstance.GetComponent <GameStateControl>().currentState.currentNationality)) { hex.GetComponent <HexDatabaseFields>().availableForMovement = true; GlobalDefinitions.HighlightHexForMovement(hex); } } GlobalDefinitions.unitSelectedForPostCombatMovement = gameObject.GetComponent <PostCombatMovementToggleRoutines>().unit; GameControl.gameStateControlInstance.GetComponent <GameStateControl>().currentState.executeMethod = GameControl.gameStateControlInstance.GetComponent <GameStateControl>().currentState.GetComponent <CombatState>().ExecutePostCombatMovement; } } // This executes when a unit is deselected else { GlobalDefinitions.WriteToCommandFile(GlobalDefinitions.DESELECTPOSTCOMBATMOVEMENTKEYWORD + " " + name); // Take the unit and move it back to its beginning hex GameControl.movementRoutinesInstance.GetComponent <MovementRoutines>().MoveUnit(beginningHex, gameObject.GetComponent <PostCombatMovementToggleRoutines>().unit.GetComponent <UnitDatabaseFields>().occupiedHex, gameObject.GetComponent <PostCombatMovementToggleRoutines>().unit); } }