/// <summary> /// This routine is called whenever an unit selection toggle on the combat gui is changed /// </summary> public void AddOrDeleteSelectedUnit() { if (GetComponent <Toggle>().isOn) { // Turn on the toggle on the remote computer GlobalDefinitions.WriteToCommandFile(GlobalDefinitions.SETCOMBATTOGGLEKEYWORD + " " + name); unit.GetComponent <UnitDatabaseFields>().isCommittedToAnAttack = true; GlobalDefinitions.HighlightUnit(unit); if (attackingUnitFlag) { // An attacking unit was added // Need to check for adding an attack from a fortress. if (unit.GetComponent <UnitDatabaseFields>().occupiedHex.GetComponent <HexDatabaseFields>().fortress) { AddDefendersOfFortressAttack(unit.GetComponent <UnitDatabaseFields>().occupiedHex); } else { RefreshDefendersBasedOnAttackers(); } } else { // A defending unit was added // If the defender that was just added is a unit in a fortress, go through and turn on all other units that // are in the fortress since attacking into a fortress means you have to attack all defenders // Loop through the other toggles if (unit.GetComponent <UnitDatabaseFields>().occupiedHex.GetComponent <HexDatabaseFields>().fortress) { foreach (Transform childTransform in transform.parent.transform) { if ((childTransform.gameObject.GetComponent <CombatToggleRoutines>() != null) && (childTransform.gameObject.GetComponent <CombatToggleRoutines>().unit != null) && (childTransform.gameObject.GetComponent <CombatToggleRoutines>().unit != unit) && (childTransform.gameObject.GetComponent <CombatToggleRoutines>().unit.GetComponent <UnitDatabaseFields>().occupiedHex == unit.GetComponent <UnitDatabaseFields>().occupiedHex) && !childTransform.GetComponent <Toggle>().isOn) { // This is another unit in the fotress, turn it on also. Note this doesn't add to the checks that need // to be done because it is on the same hex as the unit being checked already childTransform.GetComponent <Toggle>().isOn = true; } } } RefreshAttackersBasedOnDefenders(); } } else { // Turn off the toggle on the remote computer GlobalDefinitions.WriteToCommandFile(GlobalDefinitions.RESETCOMBATTOGGLEKEYWORD + " " + name); GlobalDefinitions.UnhighlightUnit(unit); unit.GetComponent <UnitDatabaseFields>().isCommittedToAnAttack = false; if (attackingUnitFlag) { // An attacking unit was removed // Need to check for removing an attack from a fortress. If there are no more units attacking from a fortress than remove the adjacent units. // They still may need to be attacked due to other units but that will be set by the process below. if (unit.GetComponent <UnitDatabaseFields>().occupiedHex.GetComponent <HexDatabaseFields>().fortress) { bool attackStillTakingPlace = false; foreach (Transform childTransform in transform.parent.transform) { if ((childTransform.gameObject.GetComponent <CombatToggleRoutines>() != null) && (childTransform.GetComponent <CombatToggleRoutines>().unit != null) && (childTransform.GetComponent <CombatToggleRoutines>().unit != unit) && (childTransform.GetComponent <CombatToggleRoutines>().unit.GetComponent <UnitDatabaseFields>().occupiedHex == unit.GetComponent <UnitDatabaseFields>().occupiedHex) && childTransform.GetComponent <Toggle>().isOn) { attackStillTakingPlace = true; } } if (!attackStillTakingPlace) { RemoveDefendersOfFortressAttack(unit.GetComponent <UnitDatabaseFields>().occupiedHex); } } else { RefreshDefendersBasedOnAttackers(); } } else { // A defending unit was removed // If the defender that was just removed is a unit in a fortress, go through and turn on all other units that // are in the fortress and turn them off also since you can't pick and choose what units to attack in a fortress // Loop through the other toggles if (unit.GetComponent <UnitDatabaseFields>().occupiedHex.GetComponent <HexDatabaseFields>().fortress) { foreach (Transform childTransform in transform.parent.transform) { if ((childTransform.gameObject.GetComponent <CombatToggleRoutines>() != null) && (childTransform.gameObject.GetComponent <CombatToggleRoutines>().unit != null) && (childTransform.gameObject.GetComponent <CombatToggleRoutines>().unit != unit) && (childTransform.gameObject.GetComponent <CombatToggleRoutines>().unit.GetComponent <UnitDatabaseFields>().occupiedHex == unit.GetComponent <UnitDatabaseFields>().occupiedHex) && childTransform.GetComponent <Toggle>().isOn) { // This is another unit in the fotress, turn it off also. Note this doesn't add to the checks that need // to be done because it is on the same hex as the unit being checked already childTransform.GetComponent <Toggle>().isOn = false; } } } RefreshAttackersBasedOnDefenders(); } } // Check if carpet bombing is available with the current set of defenders // When the game sets the state of a defender or an attacker it is executing this before the gui is finished and the code // below will cause an exception. Need to check that the toggle is there. if (GlobalDefinitions.combatCarpetBombingToggle != null) { if (CombatRoutines.CheckIfCarpetBombingIsAvailable(currentCombat)) { GlobalDefinitions.combatCarpetBombingToggle.GetComponent <Toggle>().interactable = true; } else { GlobalDefinitions.combatCarpetBombingToggle.GetComponent <Toggle>().isOn = false; GlobalDefinitions.combatCarpetBombingToggle.GetComponent <Toggle>().interactable = false; } } UpdateOddsText(); }
/// <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 looks through the attackers and defenders and determines if there are defenders that need to be added to the mustBeAttackedUnits due to being in the ZOC of a defender being attacked cross river /// </summary> public static bool CheckIfDefenderToBeAddedDueToCrossRiverAttack(List <GameObject> attackingUnits, List <GameObject> defendingUnits, bool shouldHighlight) { bool foundUnit = false; List <GameObject> adjacentUnits = new List <GameObject>(); if (attackingUnits.Count > 0) { // Get all adjacent defenders to the attacking units foreach (GameObject attackingUnit in attackingUnits) { foreach (GameObject defendingUnit in GameControl.combatRoutinesInstance.GetComponent <CombatRoutines>().ReturnAdjacentEnemyUnits(attackingUnit.GetComponent <UnitDatabaseFields>().occupiedHex, GlobalDefinitions.ReturnOppositeNationality(attackingUnits[0].GetComponent <UnitDatabaseFields>().nationality))) { if (!adjacentUnits.Contains(defendingUnit)) { adjacentUnits.Add(defendingUnit); } } } foreach (GameObject defendingUnit in defendingUnits) { if (defendingUnit.GetComponent <UnitDatabaseFields>().isCommittedToAnAttack) { //check if the defender is across a river from a committed attacker foreach (GameObject attackingUnit in attackingUnits) { if (attackingUnit.GetComponent <UnitDatabaseFields>().isCommittedToAnAttack) { // Go through each of the hexsides on the defending hexes and see if there is a river between the defender and the attacker foreach (HexDefinitions.HexSides hexSide in Enum.GetValues(typeof(HexDefinitions.HexSides))) { if ((defendingUnit.GetComponent <UnitDatabaseFields>().occupiedHex.GetComponent <HexDatabaseFields>().Neighbors[(int)hexSide] != null) && (defendingUnit.GetComponent <UnitDatabaseFields>().occupiedHex.GetComponent <HexDatabaseFields>().Neighbors[(int)hexSide] == attackingUnit.GetComponent <UnitDatabaseFields>().occupiedHex) && defendingUnit.GetComponent <UnitDatabaseFields>().occupiedHex.GetComponent <BooleanArrayData>().riverSides[(int)hexSide]) { // At this point we know that the defender is across the river from a committed attacker // Now check if there is a friendly unit in the ZOC of the defender and is adjacent to the attacker. If so, add it to must be attacked // Get all friendly units that are in the ZOC of the defender foreach (GameObject unit in ReturnFriendlyUnitsInZOC(defendingUnit)) { // Now check if any of the units are adjacent to the attacker with a river between them. If so, add it to must be attacked. if (adjacentUnits.Contains(unit) && GeneralHexRoutines.CheckForRiverBetweenTwoHexes(attackingUnit.GetComponent <UnitDatabaseFields>().occupiedHex, unit.GetComponent <UnitDatabaseFields>().occupiedHex) && !unit.GetComponent <UnitDatabaseFields>().isCommittedToAnAttack) { foundUnit = true; if (shouldHighlight) { GlobalDefinitions.HighlightUnit(unit); } } } } } } } } } } return(foundUnit); }
/// <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> /// Returns true if there are units that should be invovled in combat but aren't committed to an attack /// Will highlight all units that are uncommitted but should be involved in an attack if the shouldHighlight flag is true /// </summary> /// <param name="attackingNationality"></param> /// <param name="shouldHighlight"></param> public static bool CheckIfRequiredUnitsAreUncommitted(GlobalDefinitions.Nationality attackingNationality, bool shouldHighlight) { //GlobalDefinitions.writeToLogFile("checkIfRequiredUnitsAreUncommitted: executing"); bool unitFound = false; List <GameObject> attackingUnits; // I'm going to turn off all unit highlighting here. It will be added back on when the gui is dismissed if needed GlobalDefinitions.UnhighlightAllUnits(); if (attackingNationality == GlobalDefinitions.Nationality.German) { attackingUnits = GlobalDefinitions.germanUnitsOnBoard; } else { attackingUnits = GlobalDefinitions.alliedUnitsOnBoard; } foreach (GameObject unit in attackingUnits) { if (unit.GetComponent <UnitDatabaseFields>().nationality == GlobalDefinitions.Nationality.Allied) { // Add the clause below to check for a unit on a sea hex. This comes into play when a fortress is being attacked from // the sea since it isn't in a ZOC. if (unit.GetComponent <UnitDatabaseFields>().occupiedHex.GetComponent <HexDatabaseFields>().inGermanZOC || unit.GetComponent <UnitDatabaseFields>().occupiedHex.GetComponent <HexDatabaseFields>().sea) { // This is an allied unit that must perform an attack this turn if (!unit.GetComponent <UnitDatabaseFields>().isCommittedToAnAttack) { unitFound = true; if (shouldHighlight) { GlobalDefinitions.HighlightUnit(unit); } } // Get the German units that exert ZOC to this unit if (HighlightUnitsThatMustBeAttacked(GlobalDefinitions.Nationality.Allied, unit.GetComponent <UnitDatabaseFields>().occupiedHex, shouldHighlight)) { unitFound = true; } } } else { if (unit.GetComponent <UnitDatabaseFields>().occupiedHex.GetComponent <HexDatabaseFields>().inAlliedZOC) { // This is a German unit that must perform an attack this turn if (!unit.GetComponent <UnitDatabaseFields>().isCommittedToAnAttack) { unitFound = true; if (shouldHighlight) { GlobalDefinitions.HighlightUnit(unit); } } // Get the Allied units that exert ZOC to this unit if (HighlightUnitsThatMustBeAttacked(GlobalDefinitions.Nationality.German, unit.GetComponent <UnitDatabaseFields>().occupiedHex, shouldHighlight)) { unitFound = true; } } } } // Need to check all existing attacks and see if they are cross river and bring in additional defenders that aren't being attacked foreach (GameObject combat in GlobalDefinitions.allCombats) { if (CheckIfDefenderToBeAddedDueToCrossRiverAttack(combat.GetComponent <Combat>().attackingUnits, combat.GetComponent <Combat>().defendingUnits, shouldHighlight)) { unitFound = true; } } return(unitFound); }