/// <summary> /// Returns a list of MemberLocations, sorted by distance to the specified leader. /// </summary> private List <MemberLocation> GetMemberLocations(CreatureBoardAsset leaderAsset) { if (lastMemberLocations != null) { return(lastMemberLocations); } List <MemberLocation> memberLocations = new List <MemberLocation>(); foreach (string memberId in Data.Members) { MemberLocation memberLocation = new MemberLocation(); CreatureBoardAsset creatureBoardAsset = Talespire.Minis.GetCreatureBoardAsset(memberId); if (creatureBoardAsset == null) { continue; } memberLocation.Asset = creatureBoardAsset; memberLocation.Name = creatureBoardAsset.GetOnlyCreatureName(); memberLocation.Position = creatureBoardAsset.PlacedPosition; memberLocation.DistanceToLeader = (leaderAsset.PlacedPosition - creatureBoardAsset.PlacedPosition).magnitude; memberLocations.Add(memberLocation); } memberLocations = memberLocations.OrderBy(x => x.DistanceToLeader).ToList(); return(memberLocations); }
void PositionMember(MemberLocation memberLocation, Vector3 referencePosition, Vector3 totalDeltaMove, ref float offset) { Vector3 delta = totalDeltaMove * offset / totalDeltaMove.magnitude; Vector3 newPosition = referencePosition - delta; if (Data.Look == LookTowardMode.Movement) { memberLocation.Asset.RotateToFacePosition(newPosition); } memberLocation.Asset.MoveCreatureTo(newPosition); offset += Talespire.Convert.FeetToTiles(memberLocation.Asset.GetBaseRadiusFeet() + Data.Spacing); }
MemberLocation RemoveMemberClosestTo(List <MemberLocation> sourceMemberLocations, Vector3 targetPosition) { MemberLocation member = sourceMemberLocations.OrderBy(x => (x.Position - targetPosition).magnitude).FirstOrDefault(); if (member == null) { Talespire.Log.Error($"RemoveMemberClosestTo / member == null"); } sourceMemberLocations.Remove(member); return(member); }
void MoveMembersByProximity(List <MemberLocation> destinationMembers, List <MemberLocation> sourceMemberLocations, Vector3 targetPosition) { if (sourceMemberLocations.Count == 0) { return; } MemberLocation member = RemoveMemberClosestTo(sourceMemberLocations, targetPosition); if (member != null) { destinationMembers.Add(member); MoveMembersByProximity(destinationMembers, sourceMemberLocations, member.Position /* was targetPosition */); } }
public void ArrangeInCircle(float radiusFeet, float arcAngleDegrees, float spacingFeet, float rotationOffsetDegrees) { CreatureBoardAsset leaderAsset = OwnerCreature; if (Guard.IsNull(leaderAsset, "leaderAsset")) { return; } List <MemberLocation> memberLocations = GetMemberLocations(leaderAsset); if (memberLocations == null || memberLocations.Count == 0) { return; } float baseDiameterFeet = GetLargestBaseDiameterFeet(memberLocations); int minisToPlaceTotal = memberLocations.Count; GetCircleFormationVariables(radiusFeet, arcAngleDegrees, spacingFeet, baseDiameterFeet, minisToPlaceTotal, out Vector3 startingPoint, out float circumferenceFeet, out int numMinisCanFitInThisCircle, out float angleBetweenMinis, out float degreesToRotate); List <MemberLocation> allMembers = new List <MemberLocation>(memberLocations); int minisToPlaceThisCircle = Math.Min(allMembers.Count, numMinisCanFitInThisCircle); while (allMembers.Count > 0) { Vector3 newOffset = Quaternion.Euler(0, rotationOffsetDegrees + degreesToRotate, 0) * startingPoint; // rotate it Vector3 newPosition = leaderAsset.PlacedPosition + newOffset; // calculate rotated point MemberLocation member = RemoveMemberClosestTo(allMembers, newPosition); Vector3 delta = newPosition - member.Asset.PlacedPosition; Talespire.Minis.MoveRelative(member.Asset.CreatureId.ToString(), delta); minisToPlaceTotal--; minisToPlaceThisCircle--; degreesToRotate += angleBetweenMinis; if (minisToPlaceThisCircle <= 0 && allMembers.Count > 0) { radiusFeet += baseDiameterFeet + spacingFeet; GetCircleFormationVariables(radiusFeet, arcAngleDegrees, spacingFeet, baseDiameterFeet, minisToPlaceTotal, out startingPoint, out circumferenceFeet, out numMinisCanFitInThisCircle, out angleBetweenMinis, out degreesToRotate); minisToPlaceThisCircle = Math.Min(allMembers.Count, numMinisCanFitInThisCircle); } } UpdateLook(); }
public void ArrangeInRectangle(int columns, int spacingFeet, float percentVariance, int rotationDegrees) { CreatureBoardAsset leaderAsset = OwnerCreature; if (Guard.IsNull(leaderAsset, "leaderAsset")) { return; } List <MemberLocation> memberLocations = GetMemberLocations(leaderAsset); if (memberLocations == null || memberLocations.Count == 0) { return; } float baseDiameterFeet = GetLargestBaseDiameterFeet(memberLocations); float startingX = memberLocations[0].Position.x; float startingZ = memberLocations[0].Position.z; int rowIndex = 0; int columnIndex = 0; Vector3 centerPoint = leaderAsset.PlacedPosition; int minisInLastRow = memberLocations.Count % columns; int lastRowIndex = (int)Math.Floor((double)memberLocations.Count / columns); float normalRowLength = (columns - 1) * GetSpaceTiles(spacingFeet, baseDiameterFeet); float lengthLastRow = (minisInLastRow - 1) * GetSpaceTiles(spacingFeet, baseDiameterFeet); List <MemberLocation> allMembers = new List <MemberLocation>(memberLocations); while (allMembers.Count > 0) { float x; float gaggleFactor = 1; if (rowIndex == 0 && columnIndex == 0) { gaggleFactor = 0; } if (rowIndex == lastRowIndex) { if (minisInLastRow == 1) { x = startingX + normalRowLength / 2f + gaggleFactor * GetGaggleVariance(spacingFeet, percentVariance); } else { float lastRowStretchFactor = normalRowLength / lengthLastRow; x = startingX + columnIndex * GetSpaceTiles(spacingFeet, baseDiameterFeet) * lastRowStretchFactor + gaggleFactor * GetGaggleVariance(spacingFeet, percentVariance); } } else { x = startingX + columnIndex * GetSpaceTiles(spacingFeet, baseDiameterFeet) + gaggleFactor * GetGaggleVariance(spacingFeet, percentVariance); } float z = startingZ + rowIndex * GetSpaceTiles(spacingFeet, baseDiameterFeet) + gaggleFactor * GetGaggleVariance(spacingFeet, percentVariance); Vector3 newPosition = new Vector3(x, leaderAsset.PlacedPosition.y, z); if (rotationDegrees != 0) { Vector3 offset = centerPoint - newPosition; Vector3 newOffset = Quaternion.Euler(0, rotationDegrees + 180, 0) * offset; // rotate it newPosition = centerPoint + newOffset; // calculate rotated point } MemberLocation member = RemoveMemberClosestTo(allMembers, newPosition); Vector3 delta = newPosition - member.Position; Talespire.Minis.MoveRelative(member.Asset.CreatureId.ToString(), delta); columnIndex++; if (columnIndex >= columns) { columnIndex = 0; rowIndex++; } } CacheLastMemberLocations(memberLocations, leaderAsset); UpdateLook(); }