public static void Helper_GetForeAndAftZoneEntities(ArcenSparseLookup <GameEntity, ArcenPoint> entitiesToPlace, out List <GameEntity> foreZoneEntities, out List <GameEntity> aftZoneEntities) { foreZoneEntities = new List <GameEntity>(); for (int i = 0; i < entitiesToPlace.GetPairCount(); i++) { ArcenSparseLookupPair <GameEntity, ArcenPoint> pair = entitiesToPlace.GetPairByIndex(i); if (pair.Value != ArcenPoint.OutOfRange) { continue; } foreZoneEntities.Add(pair.Key); } // sorting these so that the first one we want to place is at the end, and working back from there foreZoneEntities.Sort(delegate(GameEntity Left, GameEntity Right) { int val; int leftRange = 0; for (int i = 0; i < Left.Systems.Count; i++) { leftRange = Math.Max(leftRange, Left.Systems[i].BalanceStats.Range); } int rightRange = 0; for (int i = 0; i < Right.Systems.Count; i++) { rightRange = Math.Max(rightRange, Right.Systems[i].BalanceStats.Range); } val = leftRange.CompareTo(rightRange); if (val != 0) { return(val); } val = Right.TypeData.Radius.CompareTo(Left.TypeData.Radius); if (val != 0) { return(val); } val = Right.TypeData.BalanceStats.StrengthPerSquad.CompareTo(Left.TypeData.BalanceStats.StrengthPerSquad); if (val != 0) { return(val); } return(Left.PrimaryKeyID.CompareTo(Right.PrimaryKeyID)); }); aftZoneEntities = new List <GameEntity>(); int entitiesToLeaveInFore = foreZoneEntities.Count / 2; for (int i = foreZoneEntities.Count - 1; i > entitiesToLeaveInFore; i--) { aftZoneEntities.Add(foreZoneEntities[i]); foreZoneEntities.RemoveAt(i); } }
public static void Helper_ActuallyIssueMoveOrders(bool isQueuedCommand, ArcenSparseLookup <GameEntity, ArcenPoint> entitiesToPlace) { for (int i = 0; i < entitiesToPlace.GetPairCount(); i++) { ArcenSparseLookupPair <GameEntity, ArcenPoint> pair = entitiesToPlace.GetPairByIndex(i); if (pair.Value == ArcenPoint.OutOfRange) { continue; } UtilityFunctions_Formation.Helper_SendMoveCommand(pair.Key, pair.Value, isQueuedCommand); } }
public void DoLongRangePlanning(WorldSide side, ArcenLongTermPlanningContext Context) { ArcenSparseLookup <Planet, List <GameEntity> > unassignedThreatShipsByPlanet = new ArcenSparseLookup <Planet, List <GameEntity> >(); side.Entities.DoForEntities(GameEntityCategory.Ship, delegate(GameEntity entity) { if (entity.LongRangePlanningData == null) { return(DelReturn.Continue); // if created after the start of this planning cycle, skip } Planet planet = World_AIW2.Instance.GetPlanetByIndex(entity.LongRangePlanningData.CurrentPlanetIndex); if (entity.TypeData.GetHasTag(DYSON_SPHERE_TAG)) { // the sphere itself } else { // something the sphere spawned if (entity.LongRangePlanningData.FinalDestinationPlanetIndex != -1 && entity.LongRangePlanningData.FinalDestinationPlanetIndex != entity.LongRangePlanningData.CurrentPlanetIndex) { return(DelReturn.Continue); // if heading somewhere else, skip } if (!unassignedThreatShipsByPlanet.GetHasKey(planet)) { unassignedThreatShipsByPlanet[planet] = new List <GameEntity>(); } unassignedThreatShipsByPlanet[planet].Add(entity); } return(DelReturn.Continue); }); int pairCount = unassignedThreatShipsByPlanet.GetPairCount(); for (int i = 0; i < pairCount; i++) { ArcenSparseLookupPair <Planet, List <GameEntity> > pair = unassignedThreatShipsByPlanet.GetPairByIndex(i); FactionUtilityMethods.Helper_SendThreatOnRaid(pair.Value, side, World_AIW2.Instance.SetOfGalaxies.Galaxies[0], pair.Key, false, Context); } }
private static void Helper_DoPlacementWithinProjectedZone(List <GameEntity> entitiesToPlaceWithinZone, ArcenSparseLookup <GameEntity, ArcenPoint> overallEntitySet, bool isQueuedCommand, int paddingAroundEachUnit, bool quadrantExpandsOnXAxis, bool quadrantExpandsInPositiveDirection, int quadrantMainAxisStart, int quadrantOtherAxisStart, int quadrantOtherAxisEnd) { ArcenPoint workingPoint; if (quadrantExpandsOnXAxis) { workingPoint.X = quadrantMainAxisStart; workingPoint.Y = quadrantOtherAxisStart; } else { workingPoint.X = quadrantOtherAxisStart; workingPoint.Y = quadrantMainAxisStart; } int furthestPointAlongMainAxis = quadrantExpandsOnXAxis ? workingPoint.X : workingPoint.Y; for (int i = 0; i < entitiesToPlaceWithinZone.Count; i++) { GameEntity entity = entitiesToPlaceWithinZone[i]; ArcenRectangle placementRect = ArcenRectangle.AllZerosInstance; placementRect.Width = entity.TypeData.Radius + entity.TypeData.Radius + paddingAroundEachUnit; placementRect.Height = placementRect.Width; placementRect.X = workingPoint.X; placementRect.Y = workingPoint.Y; int placementRectOtherAxisMax = quadrantExpandsOnXAxis ? placementRect.Bottom : placementRect.Right; if (placementRectOtherAxisMax > quadrantOtherAxisEnd) { if (quadrantExpandsOnXAxis) { workingPoint.X = furthestPointAlongMainAxis; workingPoint.Y = quadrantOtherAxisStart; } else { workingPoint.X = quadrantOtherAxisStart; workingPoint.Y = furthestPointAlongMainAxis; } placementRect.X = workingPoint.X; placementRect.Y = workingPoint.Y; // no need to recheck, as by definition there will be room unless there's a single unit that doesn't fit within the other axis } if (quadrantExpandsOnXAxis) { if (!quadrantExpandsInPositiveDirection) { placementRect.X -= placementRect.Width; } } else { if (!quadrantExpandsInPositiveDirection) { placementRect.Y -= placementRect.Height; } } overallEntitySet[entity] = placementRect.CalculateCenterPoint(); if (quadrantExpandsOnXAxis) { if (quadrantExpandsInPositiveDirection) { furthestPointAlongMainAxis = Math.Max(furthestPointAlongMainAxis, placementRect.Right); } else { furthestPointAlongMainAxis = Math.Min(furthestPointAlongMainAxis, placementRect.Left); } workingPoint.Y += placementRect.Height; } else { if (quadrantExpandsInPositiveDirection) { furthestPointAlongMainAxis = Math.Max(furthestPointAlongMainAxis, placementRect.Bottom); } else { furthestPointAlongMainAxis = Math.Min(furthestPointAlongMainAxis, placementRect.Top); } workingPoint.X += placementRect.Width; } } }
private static int Helper_PlaceRings(List <GameEntity> entitiesToPlaceWithinZone, ArcenSparseLookup <GameEntity, ArcenPoint> overallEntitySet, bool isQueuedCommand, int paddingAroundEachUnit, ArcenPoint Center, int CurrentOccupiedRadius, NonSimAngleDegrees StartingAngle, NonSimAngleDegrees ArcWidth) { NonSimAngleRadians arcWidthRadians = ArcWidth.ToRadians(); int unitIndex = 0; while (unitIndex < entitiesToPlaceWithinZone.Count) { GameEntity firstEntityOnRing = entitiesToPlaceWithinZone[unitIndex]; int firstUnitRadius = firstEntityOnRing.TypeData.Radius + paddingAroundEachUnit; int radiusOfNewRing = CurrentOccupiedRadius + firstUnitRadius; NonSimAngleRadians workingAngle = StartingAngle.ToRadians(); NonSimAngleRadians sumOfArcIncreases = NonSimAngleRadians.Create(0); int lastUnitRadius = 0; ArcenPoint firstPointFound = ArcenPoint.OutOfRange; for ( ; unitIndex < entitiesToPlaceWithinZone.Count; unitIndex++) { GameEntity entity = entitiesToPlaceWithinZone[unitIndex]; int thisUnitRadius = entity.TypeData.Radius + paddingAroundEachUnit; int distanceNeededFromPreviousPoint = 0; if (lastUnitRadius > 0) { distanceNeededFromPreviousPoint = lastUnitRadius + thisUnitRadius; } lastUnitRadius = thisUnitRadius; if (distanceNeededFromPreviousPoint > 0) { if (distanceNeededFromPreviousPoint > radiusOfNewRing) { break; } if (radiusOfNewRing <= 0) { break; } float unitDistanceNeeded = (float)distanceNeededFromPreviousPoint / (float)radiusOfNewRing; //translating this to "distance" on the unit circle //Given point A at angle M on a circle, increasing the angle by N results in another point at a distance of 2*sin(N/2) from point A //D=2*sin(N/2) //D/2=sin(N/2) //arcsin(D/2)=N/2 //2*arcsin(D/2)=N NonSimAngleRadians angleChangeNeeded = NonSimAngleRadians.Create(2 * Mathf.Asin(unitDistanceNeeded / 2)); sumOfArcIncreases = sumOfArcIncreases.Add(angleChangeNeeded); if (sumOfArcIncreases.Raw_GetIsGreaterThan(arcWidthRadians)) { break; // if this would bring us past the ending angle, stop and go to next "ring" in arc } workingAngle = workingAngle.Add(angleChangeNeeded); } Vector2 pointOnCircle = Center.ToVector2(); pointOnCircle.x += (float)(radiusOfNewRing * workingAngle.Cos()); pointOnCircle.y += (float)(radiusOfNewRing * workingAngle.Sin()); ArcenPoint pointOnCircleAsArcenPoint = pointOnCircle.ToArcenPoint(); if (firstPointFound == ArcenPoint.OutOfRange) { firstPointFound = pointOnCircleAsArcenPoint; } else if (firstPointFound.GetDistanceTo(pointOnCircleAsArcenPoint, false) < (firstUnitRadius + thisUnitRadius)) { break; // we've come full circle, and don't want to overlap } overallEntitySet[entity] = pointOnCircleAsArcenPoint; } CurrentOccupiedRadius = radiusOfNewRing + firstUnitRadius; } return(CurrentOccupiedRadius); }
public static void Helper_FindAndPlaceCoreUnit(ControlGroup Group, ArcenPoint MoveOrderPoint, out ArcenSparseLookup <GameEntity, ArcenPoint> _entitiesToPlace, out GameEntity coreUnit, out int shieldCoverageRadiusOrEquivalent, out int paddingAroundEachUnit, out ArcenRectangle firstUnitRect) { Planet localPlanet = Engine_AIW2.Instance.NonSim_GetPlanetBeingCurrentlyViewed(); ArcenSparseLookup <GameEntity, ArcenPoint> entitiesToPlace = _entitiesToPlace = new ArcenSparseLookup <GameEntity, ArcenPoint>(); Group.DoForEntities(delegate(GameEntity entity) { if (entity.Combat.Planet != localPlanet) { return(DelReturn.Continue); } entitiesToPlace[entity] = ArcenPoint.OutOfRange; return(DelReturn.Continue); }); coreUnit = null; GameEntity backupCoreUnit = null; for (int i = 0; i < entitiesToPlace.GetPairCount(); i++) { GameEntity entity = entitiesToPlace.GetPairByIndex(i).Key; if (entity.TypeData.ShieldRadius <= 0) { if (coreUnit == null) { if (backupCoreUnit != null) { if (entity.TypeData.BalanceStats.StrengthPerSquad <= backupCoreUnit.TypeData.BalanceStats.StrengthPerSquad) { continue; } } backupCoreUnit = entity; } continue; } if (coreUnit != null) { if (entity.TypeData.ShieldRadius < coreUnit.TypeData.ShieldRadius) { continue; } if (entity.TypeData.ShieldRadius == coreUnit.TypeData.ShieldRadius && entity.TypeData.BalanceStats.ShieldPoints <= coreUnit.TypeData.BalanceStats.ShieldPoints) { continue; } } coreUnit = entity; } if (coreUnit == null) { backupCoreUnit = coreUnit; } int initialCoreRadius = 4; shieldCoverageRadiusOrEquivalent = initialCoreRadius; if (coreUnit != null) { entitiesToPlace[coreUnit] = MoveOrderPoint; initialCoreRadius = coreUnit.TypeData.Radius; shieldCoverageRadiusOrEquivalent = Math.Max(initialCoreRadius, coreUnit.GetCurrentShieldRadius()); } paddingAroundEachUnit = 20; firstUnitRect.Width = initialCoreRadius + initialCoreRadius + paddingAroundEachUnit; firstUnitRect.Height = firstUnitRect.Width; firstUnitRect.X = MoveOrderPoint.X - initialCoreRadius; firstUnitRect.Y = MoveOrderPoint.Y - initialCoreRadius; }
public static void Helper_RotatePointsAccordingToAngleFromCoreUnit(ArcenPoint MoveOrderPoint, bool isQueuedCommand, ArcenSparseLookup <GameEntity, ArcenPoint> entitiesToPlace, GameEntity coreUnit) { // rotate points according to angle from first unit to target Vector2 originPoint = coreUnit.WorldLocation.ToVector2(); if (isQueuedCommand) { for (int i = 0; i < coreUnit.EntitySpecificOrders.QueuedOrders.Count; i++) { EntityOrder order = coreUnit.EntitySpecificOrders.QueuedOrders[i]; if (order.TypeData.Type != EntityOrderType.Move) { continue; } originPoint = order.RelatedPoint.ToVector2(); } } Vector2 moveOrderVectorPoint = MoveOrderPoint.ToVector2(); NonSimAngleDegrees angle = originPoint.GetAngleToDegrees(moveOrderVectorPoint); NonSimAngleDegrees baseAngle = NonSimAngleDegrees.Create(0); NonSimAngleDegrees rotationAngle = angle.Add(baseAngle); for (int i = 0; i < entitiesToPlace.GetPairCount(); i++) { ArcenSparseLookupPair <GameEntity, ArcenPoint> pair = entitiesToPlace.GetPairByIndex(i); Vector2 destinationPoint = pair.Value.ToVector2(); NonSimAngleDegrees subAngle = moveOrderVectorPoint.GetAngleToDegrees(destinationPoint); Vector2 movementVector = destinationPoint - moveOrderVectorPoint; float distance = movementVector.magnitude;//involves sqrt, is awful, but in interface code of this kind it's probably fine NonSimAngleDegrees finalAngle = rotationAngle.Add(subAngle); Vector2 rotatedPoint = moveOrderVectorPoint; rotatedPoint.x += (float)(distance * finalAngle.Cos()); rotatedPoint.y += (float)(distance * finalAngle.Sin()); entitiesToPlace[pair.Key] = rotatedPoint.ToArcenPoint(); } }