using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using HarmonyLib; using RimWorld; using UnityEngine; using Verse; using Verse.AI; namespace Rimworld_Animations { public static class AnimationUtility { public static void StartAnimation(List participants) { participants[0].Drawer.renderer.SetAnimation(AnimationDefOf.TestAnimation1); participants[1].Drawer.renderer.SetAnimation(AnimationDefOf.TestAnimation2); } //startgroupanimator with anchor //don't anchor to self if anchor is self public static void StartGroupAnimation(List participants, GroupAnimationDef groupAnimationDef, Thing anchor) { int seed = GenTicks.TicksGame; for (int i = 0; i < participants.Count; i++) { if (anchor is Pawn pawn && pawn == participants[i]) { participants[i].TryGetComp().PlayGroupAnimation(groupAnimationDef, null, i, seed, participants); } else { BaseExtendedAnimatorAnchor animatorAnchor = new ExtendedAnimatorAnchor_Thing(anchor); participants[i].TryGetComp().PlayGroupAnimation(groupAnimationDef, animatorAnchor, i, seed, participants); } } } //startgroupanimation without anchor; just play where standing public static void StartGroupAnimation(List participants, GroupAnimationDef groupAnimationDef) { int seed = GenTicks.TicksGame; for (int i = 0; i < participants.Count; i++) { participants[i].TryGetComp().PlayGroupAnimation(groupAnimationDef, i, seed, participants); } } public static void StopGroupAnimation(List participants) { foreach (Pawn pawn in participants) { pawn.TryGetComp()?.StopAnimating(); } } public static void StopGroupAnimation(Pawn participant) { participant.TryGetComp()?.StopAnimating(); } public static GroupAnimationDef FindGroupAnimation(List participants, out List pawnOrder) { /* This method is fooken expensive List<(GroupAnimationDef, List, int Priority)> potentialAnimations = new List<(GroupAnimationDef, List, int)>(); List> participantPermutations = GetPermutations(participants); //for each groupanimationdef where the number of participants matches the number of actors, foreach (GroupAnimationDef groupAnimationDef in DefDatabase.AllDefsListForReading.Where(x => x.numActors == participants.Count)) { //ignore groupanimations without contexts; those are usu. branches if (groupAnimationDef.contexts.NullOrEmpty()) continue; //check all permutations of the list of pawns, with each groupanimationdef foreach (List participantPermutation in participantPermutations) { //if groupanimation works with that particular pawn permutation, if (groupAnimationDef.CanAnimationBeUsed(participantPermutation, out int priority, out int contextNum)) { //add it to the list of potential animations, in a tuple with that permutation potentialAnimations.Add((groupAnimationDef, participantPermutation, priority)); } } } */ List<(GroupAnimationDef, List, int Priority)> potentialAnimations = new List<(GroupAnimationDef, List, int)>(); foreach (GroupAnimationDef groupAnimationDef in DefDatabase.AllDefsListForReading) { if (groupAnimationDef.CanAnimationBeUsed(participants, out List bestPermutation, out int highestPriority)) { potentialAnimations.Add((groupAnimationDef, bestPermutation, highestPriority)); } } //Randomize the list, potentialAnimations.OrderBy(_ => Rand.Int); (GroupAnimationDef, List, int) selectedAnimation; potentialAnimations.TryRandomElementByWeight(((GroupAnimationDef, List, int) x) => x.Item3, out selectedAnimation); //Find a highest priority animation, out as selectedAnimation // .TryMaxBy(((GroupAnimationDef, List, int) x) => x.Item3, out (GroupAnimationDef, List, int) selectedAnimation); //set pawnOrder as selected animation permutation pawnOrder = selectedAnimation.Item2; //return selected animation return selectedAnimation.Item1; } public static int GetAnimationLength(Pawn pawn) { return pawn.TryGetComp().AnimationLength; } public static string OffsetLookupKey(Pawn pawn) { string bodyTypeDef = (pawn.story?.bodyType != null) ? pawn.story.bodyType.ToString() : ""; CompExtendedAnimator extendedAnimator = pawn.TryGetComp(); return extendedAnimator.CurrentGroupAnimation.defName + pawn.def.defName + bodyTypeDef + extendedAnimator.ActorIndex; } static List> GetPermutations(List list) { if (list.Count == 0) return new List> { new List() }; var result = new List>(); for (int i = 0; i < list.Count; i++) { var element = list[i]; var remaining = list.Where((_, index) => index != i).ToList(); foreach (var permutation in GetPermutations(remaining)) { permutation.Insert(0, element); result.Add(permutation); } } return result; } } }