private Vector3 whereToMove(Unit squaddie, IHittable target, HashSet <IHittable> enemiesList, Unit.ClassType type) { switch (type) { case Unit.ClassType.Artillary: float smallestDistance = float.PositiveInfinity; IHittable closestThreat = null; //first, check if there are enemies closer than ArtillaryDesesperoRadius foreach (var enemy in enemiesList) { float currentDistance = Vector3.Distance(enemy.position, squaddie.position); if (currentDistance < smallestDistance) { smallestDistance = currentDistance; closestThreat = enemy; } } if (smallestDistance < ArtillaryDeseperoRadius) // if there are enemies whoa re too close { Vector3 result = (closestThreat.position - squaddie.position); result.Normalize(); //maybe we should multiply result for something here, if it is too small. return(result); } else { if (smallestDistance < ArtillaryDeseperoRadius + ArtillaryStillThreshold) { //this is to prevent archers from dancing in position. return(squaddie.position); } else { return(target.position); } } break; case Unit.ClassType.Infantry: case Unit.ClassType.Cavalry: return(target.position); default: return(squaddie.position); break; } }
private IHittable defineEnemy(Unit.ClassType squaddieType, HashSet <IHittable> enemiesList, Dictionary <IHittable, MeeleOrRanged> numberOfSiblingsOnEnemy, Unit squaddie) { IHittable currentTarget = null; //First, let's try to ignore the buildings HashSet <IHittable> buildingsList = new HashSet <IHittable>(); if (squaddieType != Unit.ClassType.Siege) // the following is for "human" troops only { foreach (var enemy in enemiesList) { if (enemy.getType() == RTS.HitType.Building) { buildingsList.Add(enemy); } } if (buildingsList.Count() == enemiesList.Count()) //if all enemies are buildings { enemiesList = buildingsList; } else { foreach (var building in buildingsList) { enemiesList.Remove(building); //focus on troops first } } } switch (squaddieType) { case Unit.ClassType.Infantry: float smallestDistance = float.PositiveInfinity; foreach (var enemy in enemiesList) { if (numberOfSiblingsOnEnemy[enemy].Meele < numberOfMeeleUnitsOnOneEnemy) //só atacar se tiver poucos "irmãos" atacando { float currentDistance = Vector3.Distance(enemy.position, squaddie.position); if (currentDistance < smallestDistance) { smallestDistance = currentDistance; currentTarget = enemy; } } } break; case Unit.ClassType.Artillary: float smallestHp = float.PositiveInfinity; foreach (var enemy in enemiesList) { if (numberOfSiblingsOnEnemy[enemy].Meele + numberOfSiblingsOnEnemy[enemy].Ranged < numberOfTotalUnitsOnOneEnemy) //não queremos arqueiros disperdiçando tiros e dando one-shot. 6 é um tanto arbitrário { if (enemy.getHp() < smallestHp) { smallestDistance = enemy.getHp(); currentTarget = enemy; } } } break; case Unit.ClassType.Cavalry: HashSet <IHittable> oldEnemiesList = enemiesList; HashSet <IHittable> archersList = new HashSet <IHittable>(); foreach (var enemy in enemiesList) { if (enemy.getType() == RTS.HitType.ArtillaryUnit) { archersList.Add(enemy); } } if (archersList.Count() > 0) //if there are archers { enemiesList = archersList; } float largestDistance = float.NegativeInfinity; foreach (var enemy in enemiesList) { if (numberOfSiblingsOnEnemy[enemy].Meele < numberOfMeeleUnitsOnOneEnemy) //só atacar se tiver poucos "irmãos" atacando { float currentDistance = Vector3.Distance(enemy.position, squaddie.position); if (currentDistance > largestDistance) { largestDistance = currentDistance; currentTarget = enemy; } } } if (currentTarget == null) //then none of the archers are avaiable (maybe because there are too many meele units around them { enemiesList = oldEnemiesList; foreach (var archer in archersList) { enemiesList.Remove(archer); } foreach (var enemy in enemiesList) { if (numberOfSiblingsOnEnemy[enemy].Meele < numberOfMeeleUnitsOnOneEnemy) //só atacar se tiver poucos "irmãos" atacando { float currentDistance = Vector3.Distance(enemy.position, squaddie.position); if (currentDistance > largestDistance) { largestDistance = currentDistance; currentTarget = enemy; } } } } break; default: currentTarget = null; break; } return(currentTarget); }
private bool AttackOrMove(Unit squaddie, IHittable target, HashSet <IHittable> enemiesList, Unit.ClassType type) { //true means attack, false means move switch (type) { case Unit.ClassType.Artillary: float smallestDistance = float.PositiveInfinity; //first, check if there are enemies closer than ArtillaryDesesperoRadius foreach (var enemy in enemiesList) { float currentDistance = Vector3.Distance(enemy.position, squaddie.position); if (currentDistance < smallestDistance) { smallestDistance = currentDistance; } } if (smallestDistance > ArtillaryDeseperoRadius) //then we are relatively safe, let's find the most weakened enemy { return(true); } else { return(false); } break; case Unit.ClassType.Infantry: case Unit.ClassType.Cavalry: float targetDistance = Vector3.Distance(target.position, squaddie.position); if (targetDistance < squaddie.Range) { return(true); } else { return(false); } default: return(false); break; } }