/// <summary> /// returns amount spent on guardians /// </summary> private FInt Helper_SeedGuardians(ArcenSimContext Context, Planet ThisPlanet, ArcenPoint centerPoint, GameEntity entityToGuard, List <GameEntityTypeData> guardianTypes, FInt budget, FInt minDistanceFactor, FInt maxDistanceFactor, EntityBehaviorType behavior, Boolean isMobilePatrol, int MaxCountToSeed) { int minDistance = (ExternalConstants.Instance.Balance_AverageGravWellRadius * minDistanceFactor).IntValue; int maxDistance = (ExternalConstants.Instance.Balance_AverageGravWellRadius * maxDistanceFactor).IntValue; FInt result = FInt.Zero; while (budget > FInt.Zero) { GameEntityTypeData guardianData = guardianTypes[Context.QualityRandom.Next(0, guardianTypes.Count)]; budget -= guardianData.BalanceStats.StrengthPerSquad; ArcenPoint point = ThisPlanet.Combat.GetSafePlacementPoint(Context, guardianData, centerPoint, minDistance, maxDistance); if (point == ArcenPoint.ZeroZeroPoint) { continue; } result += guardianData.BalanceStats.StrengthPerSquad; GameEntity newEntity = GameEntity.CreateNew(entityToGuard.Side, guardianData, point, Context); newEntity.EntitySpecificOrders.Behavior = behavior; newEntity.GuardedObject = entityToGuard; switch (behavior) { case EntityBehaviorType.Guard_Guardian_Anchored: break; case EntityBehaviorType.Guard_Guardian_Patrolling: newEntity.GuardingOffsets.Add(newEntity.WorldLocation - newEntity.GuardedObject.WorldLocation); if (isMobilePatrol) { AngleDegrees initialAngle = centerPoint.GetAngleToDegrees(newEntity.WorldLocation); int initialDistance = centerPoint.GetDistanceTo(newEntity.WorldLocation, false); int step = (AngleDegrees.MaxValue / 6).IntValue; for (int i = step; i < AngleDegrees.MaxValue; i += step) { AngleDegrees angleToThisPoint = initialAngle.Add(AngleDegrees.Create((FInt)i)); ArcenPoint thisPoint = centerPoint.GetPointAtAngleAndDistance(angleToThisPoint, initialDistance); newEntity.GuardingOffsets.Add(thisPoint - newEntity.GuardedObject.WorldLocation); } } break; } if (MaxCountToSeed > 0) { MaxCountToSeed--; if (MaxCountToSeed == 0) { break; } } } return(result); }
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); }