Beispiel #1
0
        public void LaunchAttack(List <Unit> UnitsList, GameObject TargetObj, AttackModes AttackMode)
        {
            //if this is an online game
            if (GameManager.MultiplayerGame == true)
            {
                //and this is the owner of the unit
                if (GameMgr.IsLocalPlayer(UnitsList[0].gameObject) == true)
                {
                    //send input action to the input manager
                    InputVars NewInputAction = new InputVars();
                    //mode:
                    NewInputAction.SourceMode = (byte)InputSourceMode.Group;
                    NewInputAction.TargetMode = (byte)InputTargetMode.Attack;

                    //source
                    NewInputAction.GroupSourceID = InputManager.UnitListToString(UnitsList);
                    NewInputAction.Target        = TargetObj;

                    NewInputAction.Value = (int)AttackMode;

                    //sent input
                    InputManager.SendInput(NewInputAction);
                }
            }
            else //single player game
            {
                //directly move the unit
                LaunchAttackLocal(UnitsList, TargetObj, AttackMode);
            }
        }
Beispiel #2
0
        public void LaunchAttack(Unit RefUnit, GameObject TargetObj, AttackModes AttackMode)
        {
            //if this is an online game
            if (GameManager.MultiplayerGame == true)
            {
                //and this is the owner of the unit
                if (GameMgr.IsLocalPlayer(RefUnit.gameObject) == true)
                {
                    //send input action to the input manager
                    InputVars NewInputAction = new InputVars();
                    //mode:
                    NewInputAction.SourceMode = (byte)InputSourceMode.Unit;
                    NewInputAction.TargetMode = (byte)InputTargetMode.Attack;

                    //source
                    NewInputAction.Source = RefUnit.gameObject;
                    NewInputAction.Target = TargetObj;

                    NewInputAction.InitialPos = RefUnit.transform.position;

                    NewInputAction.Value = (int)AttackMode;

                    //sent input
                    InputManager.SendInput(NewInputAction);
                }
            }
            else //single player game
            {
                //directly move the unit
                LaunchAttackLocal(RefUnit, TargetObj, AttackMode);
            }
        }
Beispiel #3
0
        //make a unit attack a target
        public void LaunchAttackLocal(Unit RefUnit, GameObject TargetObj, AttackModes AttackMode)
        {
            if (TargetObj == null)
            {
                return;
            }
            //attack stopping distance:
            float AttackStoppingDistance = 0.0f;
            //save the circle's radius here
            float CircleRadius = 0.0f;
            //the positions that the units will fill
            List <Vector3> Positions = new List <Vector3>();

            //set the initial radius distance depending on the unit's distance from the target.
            if (TargetObj.GetComponent <Unit>())
            {
                CircleRadius = TargetObj.GetComponent <Unit>().NavAgent.radius + AttackManager.Instance.RangeTypes[RefUnit.AttackMgr.RangeTypeID].UnitStoppingDistance;
            }
            else if (TargetObj.GetComponent <Building>())
            {
                CircleRadius = TargetObj.GetComponent <Building>().Radius + AttackManager.Instance.RangeTypes[RefUnit.AttackMgr.RangeTypeID].BuildingStoppingDistance;
            }
            else if (TargetObj.GetComponent <stats>())
            {
                CircleRadius = TargetObj.GetComponent <CharacterController>().radius + AttackManager.Instance.RangeTypes[RefUnit.AttackMgr.RangeTypeID].UnitStoppingDistance;
            }

            AttackStoppingDistance = CircleRadius;

            //trigger the target pos collider for the ref unit so that doesn't get detected as invalid destination
            RefUnit.TargetPosColl.isTrigger = false;

            //get a valid position for the unit to move to
            while (Positions.Count == 0)
            {
                Positions     = CircleFormation(TargetObj.transform.position, CircleRadius, RefUnit);
                CircleRadius += RefUnit.NavAgent.radius * 2f;
            }

            //Make the units attack the building/unit
            RefUnit.AttackMgr.SetAttackTargetLocal(TargetObj);

            if (Vector3.Distance(TargetObj.transform.position, RefUnit.transform.position) > AttackStoppingDistance)
            {
                RefUnit.CheckUnitPathLocal(Positions[GetClosestPosID(Positions, RefUnit.transform.position)], TargetObj, TargetObj.transform.position, MvtStoppingDistance, InputTargetMode.Attack);
            }
            else
            {
                RefUnit.CheckUnitPathLocal(RefUnit.transform.position, TargetObj, TargetObj.transform.position, MvtStoppingDistance, InputTargetMode.Attack);
            }

            RefUnit.TargetPosColl.isTrigger = true;
        }
Beispiel #4
0
    public SkillConfig GetSkillConfig(AttackModes mode)
    {
        Dictionary <AttackModes, SkillConfig> configsDict = new Dictionary <AttackModes, SkillConfig>()
        {
            { AttackModes.None, null },
            { AttackModes.Attack, unitClass.baseAttack },
            { AttackModes.MainAbility, unitClass.mainAbility },
            { AttackModes.SecondaryAbility, unitClass.secondaryAbility },
        };

        return(configsDict[mode]);
    }
Beispiel #5
0
        //make a unit attack a target
        public void LaunchAttackLocal(Unit RefUnit, GameObject TargetObj, AttackModes AttackMode)
        {
            //attack stopping distance:
            float AttackStoppingDistance = 0.0f;
            //save the circle's radius here
            float CircleRadius = 0.0f;
            //the positions that the units will fill
            List <Vector3> Positions = new List <Vector3>();

            //set the initial radius distance depending on the unit's distance from the target.
            if (TargetObj.GetComponent <Unit>())
            {
                CircleRadius = TargetObj.GetComponent <Unit>().NavAgent.radius + AttackManager.Instance.RangeTypes[RefUnit.AttackMgr.RangeTypeID].UnitStoppingDistance;
            }
            else if (TargetObj.GetComponent <Building>())
            {
                CircleRadius = TargetObj.GetComponent <Building>().Radius + AttackManager.Instance.RangeTypes[RefUnit.AttackMgr.RangeTypeID].BuildingStoppingDistance;
            }

            AttackStoppingDistance = CircleRadius;

            //trigger the target pos collider for the ref unit so that doesn't get detected as invalid destination
            RefUnit.TargetPosColl.isTrigger = false;

            //get a valid position for the unit to move to
            while (Positions.Count == 0)
            {
                Positions     = CircleFormation(TargetObj.transform.position, CircleRadius, RefUnit);
                CircleRadius += RefUnit.NavAgent.radius * 2f;
            }

            //Make the units attack the building/unit
            RefUnit.AttackMgr.SetAttackTargetLocal(TargetObj);

            if (Vector3.Distance(TargetObj.transform.position, RefUnit.transform.position) > AttackStoppingDistance)
            {
                RefUnit.CheckUnitPathLocal(Positions[GetClosestPosID(Positions, RefUnit.transform.position)], TargetObj, TargetObj.transform.position, MvtStoppingDistance, InputTargetMode.Attack);
            }
            else
            {
                RefUnit.CheckUnitPathLocal(RefUnit.transform.position, TargetObj, TargetObj.transform.position, MvtStoppingDistance, InputTargetMode.Attack);
            }

            RefUnit.TargetPosColl.isTrigger = true;

            //flash the selection plane of the target object:
            if (RefUnit.FactionID == GameManager.PlayerFactionID && (AttackMode == AttackModes.Full || AttackMode == AttackModes.Assigned))
            {
                SelectionMgr.FlashSelection(TargetObj, false);
                AudioManager.PlayAudio(GameMgr.GeneralAudioSource.gameObject, RefUnit.AttackMgr.AttackOrderSound, false);
            }
        }
Beispiel #6
0
        public void LaunchAttack(List <Unit> UnitsList, GameObject TargetObj, AttackModes AttackMode)
        {
            //if this is an online game
            if (GameManager.MultiplayerGame == true)
            {
                Debug.Log("entered here1");

                //and this is the owner of the unit
                if (GameMgr.IsLocalPlayer(UnitsList[0].gameObject) == true)
                {
                    stats rpgPlayer = null;
                    if (TargetObj.GetComponent <SelectionObj>())
                    {
                        rpgPlayer = TargetObj.GetComponent <SelectionObj>().MainObj.GetComponent <stats>();
                    }
                    if (rpgPlayer)
                    {
                        if (UnitsList[0].team != rpgPlayer.Team && !rpgPlayer.DeadFlag)
                        {
                            Debug.Log("entered here3");
                            string unitIdString = InputManager.UnitListToString(UnitsList);
                            //  if (unitId >= 0)
                            //  {
                            InputManager.UNET_Mgr.CmdAttackRpgList(unitIdString, TargetObj.GetComponent <SelectionObj>().MainObj.GetComponent <stats>().Team);
                            // }
                        }
                    }
                    else
                    {
                        //send input action to the input manager
                        InputVars NewInputAction = new InputVars();
                        //mode:
                        NewInputAction.SourceMode = (byte)InputSourceMode.Group;
                        NewInputAction.TargetMode = (byte)InputTargetMode.Attack;

                        //source
                        NewInputAction.GroupSourceID = InputManager.UnitListToString(UnitsList);
                        NewInputAction.Target        = TargetObj;

                        NewInputAction.Value = (int)AttackMode;

                        //sent input
                        InputManager.SendInput(NewInputAction);
                    }
                }
            }
            else //single player game
            {
                //directly move the unit
                LaunchAttackLocal(UnitsList, TargetObj, AttackMode);
            }
        }
Beispiel #7
0
        public void LaunchAttack(Unit RefUnit, GameObject TargetObj, AttackModes AttackMode)
        {
            //if this is an online game
            if (GameManager.MultiplayerGame == true)
            {
                //and this is the owner of the unit


                if (GameMgr.IsLocalPlayer(RefUnit.gameObject) == true)
                {
                    if (TargetObj.GetComponent <stats>())
                    {
                        if (!TargetObj.GetComponent <stats>().DeadFlag&& RefUnit.team != TargetObj.GetComponent <stats>().Team)
                        {
                            GameObject item   = RefUnit.gameObject;
                            int        UnitId = InputManager.Instance.SpawnedObjects.IndexOf(item);

                            InputManager.UNET_Mgr.CmdAttackRpg(UnitId, TargetObj.GetComponent <stats>().Team);
                        }
                    }
                    else
                    {
                        //send input action to the input manager
                        InputVars NewInputAction = new InputVars();
                        //mode:
                        NewInputAction.SourceMode = (byte)InputSourceMode.Unit;
                        NewInputAction.TargetMode = (byte)InputTargetMode.Attack;

                        //source
                        NewInputAction.Source = RefUnit.gameObject;
                        NewInputAction.Target = TargetObj;

                        NewInputAction.InitialPos = RefUnit.transform.position;

                        NewInputAction.Value = (int)AttackMode;

                        //sent input
                        InputManager.SendInput(NewInputAction);
                    }
                }
            }
            else //single player game
            {
                //directly move the unit
                LaunchAttackLocal(RefUnit, TargetObj, AttackMode);
            }
        }
Beispiel #8
0
        //make a list of units launch an attack on a target object:
        public void LaunchAttackLocal(List <Unit> UnitsList, GameObject TargetObj, AttackModes AttackMode)
        {
            //change the target?
            bool ChangeTarget = (AttackMode == AttackModes.Full || AttackMode == AttackModes.Change) ? true : false;
            //assigned attack only?
            bool AssignedAttackOnly = (AttackMode == AttackModes.Full || AttackMode == AttackModes.Assigned) ? true : false;

            //this will hold all different types of the selected units with their main settings
            List <UnitTypes> SelectedUnitTypes = SetSelectedUnitsTypes(UnitsList, true); //true to let the function know that we need to remove all units who don't have an attack component

            if (SelectedUnitTypes.Count > 0)
            {
                //sort unit types depending on their attack stopping distances
                SortSelectedUnitTypes((TargetObj.GetComponent <Unit>()) ? UnitSortType.UnitStopDistance : UnitSortType.BuildingStopDistance, ref SelectedUnitTypes); //sort the selected units by type

                Unit MainAttackUnit = null;                                                                                                                          //This is the unit that will trigger the attack order audio clip
                //attack stopping distance:
                float AttackStoppingDistance = 0.0f;
                //save the circle's radius here
                float CircleRadius = 0.0f;
                //the positions that the units will fill
                List <Vector3> Positions = new List <Vector3>();

                //go through each unit type list:
                foreach (UnitTypes UnitGroup in SelectedUnitTypes)
                {
                    Positions.Clear();
                    List <Unit> CurrentUnitsList = UnitGroup.UnitsList;

                    SortUnitsByDistance(ref CurrentUnitsList, TargetObj.transform.position); //sort the selected units by distance so the closer units get there first

                    MainAttackUnit = CurrentUnitsList[0];                                    //this unit will play the attack order audio clip

                    //set the stopping distance depending on the unit's distance from the target.
                    if (TargetObj.GetComponent <Unit>())
                    {
                        CircleRadius = TargetObj.GetComponent <Unit>().NavAgent.radius + AttackManager.Instance.RangeTypes[UnitGroup.RangeTypeID].UnitStoppingDistance;
                    }
                    else if (TargetObj.GetComponent <Building>())
                    {
                        CircleRadius = TargetObj.GetComponent <Building>().Radius + AttackManager.Instance.RangeTypes[UnitGroup.RangeTypeID].BuildingStoppingDistance;
                    }

                    AttackStoppingDistance = CircleRadius;

                    //go through the unit list and trigger the target position collider
                    for (int i = 0; i < CurrentUnitsList.Count; i++)
                    {
                        CurrentUnitsList[i].TargetPosColl.isTrigger = false;
                    }

                    for (int i = 0; i < CurrentUnitsList.Count; i++)
                    {
                        //if this unit is valid
                        if (CurrentUnitsList[i] != null)
                        {
                            //make sure that the unit can attack when the target is assigned or if that is not forced:
                            if (AssignedAttackOnly == false || CurrentUnitsList[i].AttackMgr.AttackOnAssign == true)
                            {
                                //make sure that this unit can attack when invisible, if it's invisible:
                                if (CurrentUnitsList[i].IsInvisible == false || CurrentUnitsList[i].InvisibilityMgr.CanAttack == true)
                                {
                                    //either we can change the unit's target or the unit doesn't have a target to begin with
                                    if (CurrentUnitsList[i].AttackMgr.AttackTarget == null || ChangeTarget == true)
                                    {
                                        //check if the unit can actually attack the target:
                                        if (AttackManager.Instance.CanAttackTarget(CurrentUnitsList[i].AttackMgr, TargetObj) == true)
                                        {
                                            //get a valid position for the unit to move to
                                            while (Positions.Count == 0)
                                            {
                                                Positions     = CircleFormation(TargetObj.transform.position, CircleRadius, CurrentUnitsList[i]);
                                                CircleRadius += CurrentUnitsList[i].NavAgent.radius * 2f;
                                            }

                                            //Make the units attack the building/unit
                                            CurrentUnitsList[i].AttackMgr.SetAttackTargetLocal(TargetObj);

                                            if (Vector3.Distance(TargetObj.transform.position, CurrentUnitsList[i].transform.position) > AttackStoppingDistance)
                                            {
                                                int ID = GetClosestPosID(Positions, CurrentUnitsList[i].transform.position);
                                                CurrentUnitsList[i].CheckUnitPathLocal(Positions[ID], TargetObj, TargetObj.transform.position, MvtStoppingDistance, InputTargetMode.Attack);

                                                Positions.RemoveAt(ID);
                                            }
                                            else
                                            {
                                                CurrentUnitsList[i].CheckUnitPathLocal(CurrentUnitsList[i].transform.position, TargetObj, TargetObj.transform.position, MvtStoppingDistance, InputTargetMode.Attack);
                                            }

                                            CurrentUnitsList[i].TargetPosColl.isTrigger = true;
                                        }
                                        else
                                        {
                                            if (CurrentUnitsList[i].FactionID == GameManager.PlayerFactionID)
                                            {
                                                UIMgr.ShowPlayerMessage("Unit can't attack that target!", UIManager.MessageTypes.Error);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }


                if (MainAttackUnit)
                {
                    if (MainAttackUnit.FactionID == GameManager.PlayerFactionID)
                    {
                        SelectionMgr.FlashSelection(TargetObj, false);
                        AudioManager.PlayAudio(GameMgr.GeneralAudioSource.gameObject, MainAttackUnit.AttackMgr.AttackOrderSound, false);
                    }
                }
            }
        }
Beispiel #9
0
 //a method that launches an attack movement for a a list of units locally
 public void LaunchAttackLocal(List <Unit> units, FactionEntity targetEntity, Vector3 targetPosition, AttackModes attackMode, bool playerCommand)
 {
     PrepareMove(units, targetPosition, targetEntity ? targetEntity.GetRadius() : 0.0f, targetEntity,
                 InputMode.attack, playerCommand, true, attackMode, targetEntity);
 }
Beispiel #10
0
        //a method that launches the attack movement of a list of units
        public void LaunchAttack(List <Unit> units, FactionEntity targetEntity, Vector3 targetPosition, AttackModes attackMode, bool playerCommand)
        {
            if (units.Count == 1) //one unit only?
            {
                //use the one-unit attack movement
                LaunchAttack(units[0], targetEntity, targetPosition, attackMode, playerCommand);
                return;
            }

            if (GameManager.MultiplayerGame == false) //single player game, directly prepare the unit's attack movement
            {
                PrepareMove(units, targetPosition, targetEntity ? targetEntity.GetRadius() : 0.0f, targetEntity,
                            InputMode.attack, playerCommand, true, attackMode, targetEntity);
            }
            else if (RTSHelper.IsLocalPlayer(units[0]) == true) //multiplayer game and this is the local player
            {
                //send input action to the input manager
                NetworkInput newInput = new NetworkInput()
                {
                    sourceMode     = (byte)InputMode.unitGroup,
                    targetMode     = (byte)InputMode.attack,
                    targetPosition = targetPosition,
                    value          = (int)attackMode,
                    groupSourceID  = InputManager.UnitListToString(units)
                };

                //sent input
                InputManager.SendInput(newInput, null, targetEntity);
            }
        }
Beispiel #11
0
        //a method that launches an attack movement for a single unit
        public void LaunchAttack(Unit unit, FactionEntity targetEntity, Vector3 targetPosition, AttackModes attackMode, bool playerCommand)
        {
            if (GameManager.MultiplayerGame == false) //single player game, directly prepare the unit's attack movement
            {
                PrepareMove(unit, targetPosition, targetEntity ? targetEntity.GetRadius() : 0.0f, targetEntity,
                            InputMode.attack, playerCommand, true, attackMode, targetEntity);
            }
            else if (RTSHelper.IsLocalPlayer(unit) == true) //multiplayer game and this is the local player
            {
                //send input action to the input manager
                NetworkInput newInput = new NetworkInput()
                {
                    sourceMode      = (byte)InputMode.unit,
                    targetMode      = (byte)InputMode.attack,
                    initialPosition = unit.transform.position,
                    targetPosition  = targetPosition,
                    value           = (int)attackMode,
                };

                //sent input
                InputManager.SendInput(newInput, unit, targetEntity);
            }
        }
Beispiel #12
0
        //a method that sorts a list of units depending on the sort type and return a chained sorted list of the sorted units
        private ChainedSortedList <float, Unit> SortUnits(List <Unit> units, UnitSortTypes sortType, float offsetRadius, AttackModes attackMode = AttackModes.none, FactionEntity targetEntity = null, Vector3 targetPosition = default, bool playerCommand = false)
        {
            ChainedSortedList <float, Unit> sortedUnits = new ChainedSortedList <float, Unit>(); //this will hold the sorted list of the units.

            //attack only:
            //change the target?
            bool canChangeTarget = (attackMode == AttackModes.full || attackMode == AttackModes.change) ? true : false;
            //assigned attack only?
            bool assignedAttackOnly = (attackMode == AttackModes.full || attackMode == AttackModes.assigned) ? true : false;

            foreach (Unit unit in units)                       //go through the list of units.
            {
                if (unit.MovementComp.CanMove() == false)      //if the unit can't move
                {
                    if (sortType == UnitSortTypes.attackRange) //if this is an attack movement, just check if the target is in range or not
                    {
                        LaunchNonMovementAttackLocal(unit, targetEntity, playerCommand);

                        continue;
                    }
                    else
                    {
                        if (playerCommand == true && unit.FactionID == GameManager.PlayerFactionID) //player notification message
                        {
                            ErrorMessageHandler.OnErrorMessage(ErrorMessage.notMovable, unit);
                        }
                        continue;
                    }
                }

                float sortKey = unit.MovementComp.GetAgentRadius();                                                                //sort key is set to agent radius by default

                if (sortType != UnitSortTypes.radius)                                                                              //if we're not sorting by radius <=> we're not sorting for a simple movement but for an attack movement and therefore:
                {
                    if (CanProceedAttackMovement(unit, playerCommand, assignedAttackOnly, canChangeTarget, targetEntity) == false) //do not proceed if the attack is not possible
                    {
                        continue;
                    }

                    sortKey = unit.AttackComp.RangeType.GetStoppingDistance(targetEntity == null ? EntityTypes.none : targetEntity.Type); //update sort key

                    if (Vector3.Distance(unit.transform.position, targetPosition) < sortKey + offsetRadius)                               //if the attack unit is already inside its target range
                    {
                        //attack directly
                        EnqueueMovementTask(new MovementTask
                        {
                            unit                 = unit,
                            targetPosition       = unit.transform.position,
                            lookAtPosition       = targetPosition,
                            target               = targetEntity,
                            targetMode           = InputMode.attack,
                            attack               = true,
                            attackTarget         = targetEntity,
                            attackTargetPosition = targetPosition,
                        });       //add a new movement task to the movement queue to attack directly
                        continue; //move to next unit
                    }
                }

                unit.MovementComp.TriggerTargetPositionCollider(false); //disable the target position collider first so that it won't intefer in the movement calculations
                sortedUnits.Add(sortKey, unit);                         //add the new alongside its radius as the key.
            }

            return(sortedUnits);
        }
Beispiel #13
0
        //the PrepareMove method prepares the movement of a list of units by sorting them based on their radius, distance to target and generating target positions
        public void PrepareMove(List <Unit> units, Vector3 destination, float offsetRadius, Entity target, InputMode targetMode, bool playerCommand, bool attackMovement = false, AttackModes attackMode = AttackModes.none, FactionEntity targetEntity = null)
        {
            //create a new chained sorted list where units will be sorted based on their radius or stopping distance towards the target unit/building (in case of an attack)
            ChainedSortedList <float, Unit> radiusSortedUnits = SortUnits(units, attackMovement ? UnitSortTypes.attackRange : UnitSortTypes.radius, offsetRadius, attackMode, targetEntity, destination, playerCommand);

            float currOffsetRadius = offsetRadius;                           //set the current offset radius (we might need the same original offsetRadius value later)

            AudioClip movementOrderAudio = null;                             //we'll just pick one of the movement order audios from the units list

            if (playerCommand && (!targetEntity || attackMovement == false)) //if this is a player command and it's not an attack movement with an assigned target
            {
                SpawnTargetEffect(!attackMovement, destination);
            }

            foreach (KeyValuePair <float, List <Unit> > currUnits in radiusSortedUnits) //for each different list of units that share the same radius
            {
                if (attackMovement == true)                                             //if this is an attack movement
                {
                    currOffsetRadius += currUnits.Key;                                  //increment the offset radius by the attack range (which is represented by the key in case)
                }
                //sort units in ascending order of the distance to the target position
                currUnits.Value.Sort((x, y) => Vector3.Distance(x.transform.position, destination).CompareTo(Vector3.Distance(y.transform.position, destination)));

                UnitMovement movementRef = currUnits.Value[0].MovementComp; //reference movement component

                Vector3 unitsDirection = Vector3.zero;                      //direction of units regarding the target position
                foreach (Unit unit in currUnits.Value)
                {
                    unitsDirection += (destination - unit.transform.position).normalized;
                }

                unitsDirection /= currUnits.Value.Count;

                Formations currentFormation = GetFormation(currUnits.Value[0], attackMovement); //current movement formation for this units group

                List <Vector3> targetPositions = GenerateTargetPositions(currentFormation,
                                                                         destination, currUnits.Value.Count,
                                                                         movementRef.GetAgentRadius(),
                                                                         movementRef.GetAgentAreaMask(),
                                                                         movementRef.CanFly(),
                                                                         ref currOffsetRadius, unitsDirection);   //get the target positions for the current units list

                for (int i = 0; i < currUnits.Value.Count; i++)                                                   //go through the sorted units list
                {
                    if (targetPositions.Count == 0)                                                               //no more target positions available?
                    {
                        if (playerCommand == true && currUnits.Value[i].FactionID == GameManager.PlayerFactionID) //if this is a player command then inform the player
                        {
                            ErrorMessageHandler.OnErrorMessage(ErrorMessage.targetPositionNotFound, currUnits.Value[i]);
                        }
                        continue;
                    }

                    switch (currentFormation)
                    {
                    case Formations.circular:
                        if (attackMovement == true)                                                                                                                                           //only pick the closest target position in case this is an attack movement type and we're using the circular formation
                        {
                            targetPositions.Sort((x, y) => Vector3.Distance(x, currUnits.Value[i].transform.position).CompareTo(Vector3.Distance(y, currUnits.Value[i].transform.position))); //sort the target positions list depending on the distance to the actual unit to move
                        }
                        break;

                    case Formations.rectangular:                                                                                                                                          //if this is a rectangular formation, then the closest unit always gets to the farthest position
                        targetPositions.Sort((x, y) => Vector3.Distance(y, currUnits.Value[i].transform.position).CompareTo(Vector3.Distance(x, currUnits.Value[i].transform.position))); //sort the target positions list depending on the distance to the actual unit to move
                        break;
                    }

                    if (movementOrderAudio == null)                                                                                                                       //if the movement order audio hasn't been set yet
                    {
                        movementOrderAudio = attackMovement == true ? currUnits.Value[i].AttackComp.GetOrderAudio() : currUnits.Value[i].MovementComp.GetMvtOrderAudio(); //set it.
                    }
                    EnqueueMovementTask(new MovementTask
                    {
                        unit                 = currUnits.Value[i],
                        targetPosition       = targetPositions[0],
                        lookAtPosition       = targetPositions[0] + unitsDirection,
                        target               = target,
                        targetMode           = targetMode,
                        attack               = attackMovement,
                        attackTarget         = targetEntity,
                        attackTargetPosition = destination,
                    }); //add a new movement task to the movement queue

                    targetPositions.RemoveAt(0);
                }
            }

            if (playerCommand)                                                                 //if this is a player command
            {
                AudioManager.Play(gameMgr.GetGeneralAudioSource(), movementOrderAudio, false); //play the movement order audio
            }
        }
Beispiel #14
0
        //the PrepareMove method prepares the movement of a single unit
        public void PrepareMove(Unit unit, Vector3 destination, float offsetRadius, Entity target, InputMode targetMode, bool playerCommand, bool attackMovement = false, AttackModes attackMode = AttackModes.none, FactionEntity targetEntity = null)
        {
            if (!unit.MovementComp.CanMove()) //if the unit can't move and this is no attack movement
            {
                if (attackMovement)           //if this is an attack movement, just check if the target is in range or not
                {
                    LaunchNonMovementAttackLocal(unit, targetEntity, playerCommand);
                    return;
                }
                else
                {
                    if (playerCommand == true && unit.FactionID == GameManager.PlayerFactionID) //player notification message
                    {
                        ErrorMessageHandler.OnErrorMessage(ErrorMessage.notMovable, unit);
                    }

                    unit.MovementComp.OnInvalidPath(true, false);
                    return; //nothing to do here
                }
            }

            if (attackMovement == true) //if this is an attack movement
            {
                //change the target?
                bool canChangeTarget = (attackMode == AttackModes.full || attackMode == AttackModes.change) ? true : false;
                //assigned attack only?
                bool assignedAttackOnly = (attackMode == AttackModes.full || attackMode == AttackModes.assigned) ? true : false;

                if (CanProceedAttackMovement(unit, playerCommand, assignedAttackOnly, canChangeTarget, targetEntity) == false) //do not proceed if the attack is not possible
                {
                    return;
                }

                offsetRadius += unit.AttackComp.RangeType.GetStoppingDistance(targetEntity == null ? EntityTypes.none : targetEntity.Type); //update sort key

                if (Vector3.Distance(unit.transform.position, destination) < offsetRadius)                                                  //if the attack unit is already inside its target range
                {
                    //attack directly
                    EnqueueMovementTask(new MovementTask
                    {
                        unit                 = unit,
                        targetPosition       = unit.transform.position,
                        lookAtPosition       = destination,
                        target               = target,
                        targetMode           = InputMode.attack,
                        attack               = true,
                        attackTarget         = targetEntity,
                        attackTargetPosition = destination
                    });     //add a new movement task to the movement queue to attack directly
                    return; //move to next unit
                }
            }

            unit.MovementComp.TriggerTargetPositionCollider(false);          //disable the target position collider so it won't intefer in the target position collider

            if (playerCommand && (!targetEntity || attackMovement == false)) //if this is a player command and it's not an attack movement with an assigned target
            {
                SpawnTargetEffect(!attackMovement, destination);
            }

            Vector3 originalDestination = destination; //save the original destination here

            //first check if the actual destination is a valid target position, if it can't be then search for a target position
            if (offsetRadius > 0.0f || IsPositionClear(ref destination, unit.MovementComp.GetAgentRadius(), unit.MovementComp.GetAgentAreaMask(), unit.MovementComp.CanFly()) == false)
            {
                List <Vector3> targetPositions = GenerateTargetPositions(Formations.circular, //it doesn't really matter what formation to use for one unit
                                                                         destination, 1,
                                                                         unit.MovementComp.GetAgentRadius(),
                                                                         unit.MovementComp.GetAgentAreaMask(),
                                                                         unit.MovementComp.CanFly(),
                                                                         ref offsetRadius, Vector3.zero); //get the target positions for the current units list

                if (targetPositions.Count == 0)                                                           //no target positions found?
                {
                    if (playerCommand == true && unit.FactionID == GameManager.PlayerFactionID)           //if this is a player command then inform the player
                    {
                        ErrorMessageHandler.OnErrorMessage(ErrorMessage.targetPositionNotFound, unit);
                    }

                    unit.CancelJob(Unit.jobType.all); //cancel all the unit's jobs.
                    return;
                }

                targetPositions.Sort((x, y) => Vector3.Distance(x, unit.transform.position).CompareTo(Vector3.Distance(y, unit.transform.position))); //sort the target positions list depending on the distance to the actual unit to move

                destination = targetPositions[0];                                                                                                     //get the nearest target position
            }

            EnqueueMovementTask(new MovementTask
            {
                unit                 = unit,
                targetPosition       = destination,
                lookAtPosition       = originalDestination,
                target               = target,
                targetMode           = targetMode,
                attack               = attackMovement,
                attackTarget         = targetEntity,
                attackTargetPosition = originalDestination,
            });                                                                                                                                                             //add a new movement task to the movement queue.

            if (playerCommand)                                                                                                                                              //if this is a player command
            {
                AudioManager.Play(gameMgr.GetGeneralAudioSource(), attackMovement == true ? unit.AttackComp.GetOrderAudio() : unit.MovementComp.GetMvtOrderAudio(), false); //play the movement order audio
            }
        }
 public void ChangeAttackMode(AttackModes mode)
 {
     AttackMode = AttackMode == mode ? AttackModes.None : mode;
 }