/// <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();
        }
예제 #2
0
        /// <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);
        }