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); } }
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); } }
//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; }
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]); }
//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); } }
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); } }
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); } }
//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); } } } }
//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); }
//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); } }
//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); } }
//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); }
//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 } }
//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; }