mirror of
				https://gitgud.io/c0ffeeeeeeee/rimworld-animations.git
				synced 2024-08-15 00:43:45 +00:00 
			
		
		
		
	added extended animator, animationstages, animator selects animations to play iteratively and queues them to be played; saving and loading as well
This commit is contained in:
		
							parent
							
								
									db4c2d3833
								
							
						
					
					
						commit
						43843a398f
					
				
					 26 changed files with 389 additions and 85 deletions
				
			
		
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							| 
						 | 
				
			
			@ -2,7 +2,7 @@
 | 
			
		|||
<Defs>
 | 
			
		||||
	<AnimationDef>
 | 
			
		||||
		<defName>TestAnimation2</defName>
 | 
			
		||||
		<durationTicks>200</durationTicks>
 | 
			
		||||
		<durationTicks>50</durationTicks>
 | 
			
		||||
		<startOnRandomTick>False</startOnRandomTick>
 | 
			
		||||
		<playWhenDowned>False</playWhenDowned>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -13,27 +13,27 @@
 | 
			
		|||
					<workerClass>Rimworld_Animations.AnimationWorker_KeyframesExtended</workerClass>
 | 
			
		||||
					<keyframes>
 | 
			
		||||
						<li Class="Rimworld_Animations.ExtendedKeyframe">
 | 
			
		||||
							<offset>(0, -1, 0)</offset>
 | 
			
		||||
							<offset>(1, -1, 0)</offset>
 | 
			
		||||
							<tick>0</tick>
 | 
			
		||||
							<angle>23</angle>
 | 
			
		||||
							<angle>0</angle>
 | 
			
		||||
							<rotation>North</rotation>
 | 
			
		||||
						</li>
 | 
			
		||||
						<li Class="Rimworld_Animations.ExtendedKeyframe">
 | 
			
		||||
						  <offset>(0, -1, 0)</offset>
 | 
			
		||||
						  <tick>6</tick>
 | 
			
		||||
						  <angle>-5</angle>
 | 
			
		||||
						  <tick>20</tick>
 | 
			
		||||
						  <angle>0</angle>
 | 
			
		||||
						  <rotation>North</rotation>
 | 
			
		||||
						</li>
 | 
			
		||||
						<li Class="Rimworld_Animations.ExtendedKeyframe">
 | 
			
		||||
						  <offset>(-1, -1, 0)</offset>
 | 
			
		||||
						  <tick>30</tick>
 | 
			
		||||
						  <angle>0</angle>
 | 
			
		||||
						  <rotation>North</rotation>
 | 
			
		||||
						</li>
 | 
			
		||||
						<li Class="Rimworld_Animations.ExtendedKeyframe">
 | 
			
		||||
						  <offset>(0, -1, 0)</offset>
 | 
			
		||||
						  <tick>12</tick>
 | 
			
		||||
						  <angle>4</angle>
 | 
			
		||||
						  <rotation>North</rotation>
 | 
			
		||||
						</li>
 | 
			
		||||
						<li Class="Rimworld_Animations.ExtendedKeyframe">
 | 
			
		||||
						  <offset>(0, -1, 0)</offset>
 | 
			
		||||
						  <tick>188</tick>
 | 
			
		||||
						  <angle>-1</angle>
 | 
			
		||||
						  <tick>40</tick>
 | 
			
		||||
						  <angle>0</angle>
 | 
			
		||||
						  <rotation>North</rotation>
 | 
			
		||||
						</li>
 | 
			
		||||
					</keyframes>
 | 
			
		||||
| 
						 | 
				
			
			@ -51,16 +51,16 @@
 | 
			
		|||
						</li>
 | 
			
		||||
						<li Class="Rimworld_Animations.ExtendedKeyframe">
 | 
			
		||||
							<tick>6</tick>
 | 
			
		||||
							<angle>-5</angle>
 | 
			
		||||
							<angle>0</angle>
 | 
			
		||||
							<rotation>North</rotation>
 | 
			
		||||
						</li>
 | 
			
		||||
						<li Class="Rimworld_Animations.ExtendedKeyframe">
 | 
			
		||||
							<tick>12</tick>
 | 
			
		||||
							<angle>4</angle>
 | 
			
		||||
							<angle>0</angle>
 | 
			
		||||
							<rotation>North</rotation>
 | 
			
		||||
						</li>
 | 
			
		||||
						<li Class="Rimworld_Animations.ExtendedKeyframe">
 | 
			
		||||
							<tick>128</tick>
 | 
			
		||||
							<tick>18</tick>
 | 
			
		||||
							<angle>0</angle>
 | 
			
		||||
							<rotation>North</rotation>
 | 
			
		||||
						</li>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,13 +4,6 @@
 | 
			
		|||
		<defName>TestGroupAnimation1</defName>
 | 
			
		||||
		<numActors>2</numActors>
 | 
			
		||||
		<animationStages>
 | 
			
		||||
			<li Class="Rimworld_Animations.AnimationStage_TicksDuration">
 | 
			
		||||
				<ticks>200</ticks>
 | 
			
		||||
				<animationDefs>
 | 
			
		||||
					<li>TestAnimation1</li>
 | 
			
		||||
					<li>TestAnimation2</li>
 | 
			
		||||
				</animationDefs>
 | 
			
		||||
			</li>
 | 
			
		||||
			<li Class="Rimworld_Animations.AnimationStage_LoopRandomSelectChance">
 | 
			
		||||
				<loops>10</loops>
 | 
			
		||||
				<loopOptions>
 | 
			
		||||
| 
						 | 
				
			
			@ -89,6 +82,12 @@
 | 
			
		|||
 | 
			
		||||
			</li>
 | 
			
		||||
		</contexts>
 | 
			
		||||
		<!--
 | 
			
		||||
		<OffsetDefs>
 | 
			
		||||
			<li>GroinToAppropriateHeight</li>
 | 
			
		||||
			<li>GroinToAppropriateHeight</li>
 | 
			
		||||
		</OffsetDefs>
 | 
			
		||||
		
 | 
			
		||||
		-->
 | 
			
		||||
	</Rimworld_Animations.GroupAnimationDef>
 | 
			
		||||
</Defs>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										37
									
								
								1.5/Defs/OffsetDefs/OffsetDef_GroinToAppropriateHeight.xml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								1.5/Defs/OffsetDefs/OffsetDef_GroinToAppropriateHeight.xml
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,37 @@
 | 
			
		|||
<?xml version="1.0" encoding="utf-8" ?>
 | 
			
		||||
<Defs>
 | 
			
		||||
	<Rimworld_Animations.OffsetDef>
 | 
			
		||||
		<defName>GroinToAppropriateHeight</defName>
 | 
			
		||||
		<bodyTypeOffsets>
 | 
			
		||||
			<li>
 | 
			
		||||
				<bodyType>Male</bodyType>
 | 
			
		||||
				<offset>(0, 0, 0.5)</offset>
 | 
			
		||||
			</li>
 | 
			
		||||
		</bodyTypeOffsets>
 | 
			
		||||
		<raceOffsets>
 | 
			
		||||
			<li Class="Rimworld_Animations.RaceOffsets_BodyTypes" MayRequire="erdelf.HumanoidAlienRaces,Minecraft.Mod">
 | 
			
		||||
				<def>MinecraftCreeper</def>
 | 
			
		||||
				<genderGraphics>
 | 
			
		||||
					<Female>
 | 
			
		||||
						<Hulk>(0, 0, 0.5)</Hulk>
 | 
			
		||||
						<Thin>(0, 0, 0.3)</Thin>
 | 
			
		||||
					</Female>
 | 
			
		||||
					<Male>
 | 
			
		||||
						<Hulk>(0, 0, 0.5)</Hulk>
 | 
			
		||||
						<Thin>(0, 0, 0.3)</Thin>
 | 
			
		||||
					</Male>
 | 
			
		||||
				</genderGraphics>
 | 
			
		||||
			</li>
 | 
			
		||||
			<li Class="Rimworld_Animations.RaceOffsets_DifferentBodyTypes" MayRequire="Specific.Mod,Other.Cool.Mod">
 | 
			
		||||
				<def>MinecraftPig</def>
 | 
			
		||||
				<bodyType>Male</bodyType>
 | 
			
		||||
				<offset>(0, 0, -0.5)</offset>
 | 
			
		||||
			</li>
 | 
			
		||||
			<li Class="Rimworld_Animations.RaceOffsets_DifferentBodyTypes" MayRequire="Specific.Minecraft.Mod">
 | 
			
		||||
				<def>MinecraftPig</def>
 | 
			
		||||
				<bodyType>Female</bodyType>
 | 
			
		||||
				<offset>(0, 0, -0.5)</offset>
 | 
			
		||||
			</li>
 | 
			
		||||
		</raceOffsets>
 | 
			
		||||
	</Rimworld_Animations.OffsetDef>
 | 
			
		||||
</Defs>
 | 
			
		||||
| 
						 | 
				
			
			@ -15,6 +15,12 @@ namespace Rimworld_Animations
 | 
			
		|||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override Vector3 OffsetAtTick(int tick, PawnDrawParms parms)
 | 
			
		||||
        {
 | 
			
		||||
            //Todo: Use this for bodyoffsets
 | 
			
		||||
            return base.OffsetAtTick(tick, parms);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        //use extendedkeyframes to determine addon facing
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,7 +11,121 @@ using Verse.Sound;
 | 
			
		|||
namespace Rimworld_Animations {
 | 
			
		||||
    public class CompExtendedAnimator : ThingComp
 | 
			
		||||
    {
 | 
			
		||||
        List<Tuple<int, AnimationDef>> animationQueue;
 | 
			
		||||
 | 
			
		||||
        // CompExtendedAnimator
 | 
			
		||||
        // Helps manage AnimationQueue, AbsolutePosition
 | 
			
		||||
        
 | 
			
		||||
        private List<AnimationDef> animationQueue;
 | 
			
		||||
        private BaseExtendedAnimatorAnchor anchor;
 | 
			
		||||
        private bool isAnimating = false;
 | 
			
		||||
 | 
			
		||||
        
 | 
			
		||||
        public bool IsAnimating
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return isAnimating;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public bool IsAnchored
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return anchor != null;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public Vector3 getAnchor()
 | 
			
		||||
        {
 | 
			
		||||
            return anchor.getDrawPos();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //ticks of current animation
 | 
			
		||||
        private int animationTicks;
 | 
			
		||||
 | 
			
		||||
        public override void CompTick()
 | 
			
		||||
        {
 | 
			
		||||
            if (isAnimating)
 | 
			
		||||
            {
 | 
			
		||||
                animationTicks++;
 | 
			
		||||
 | 
			
		||||
                //if animationticks is equal to cur. anim duration,
 | 
			
		||||
                if (animationTicks >= animationQueue[0].durationTicks)
 | 
			
		||||
                {
 | 
			
		||||
                    //dequeue; returns false if more animations
 | 
			
		||||
                    if (!PopAnimationQueue())
 | 
			
		||||
                    {
 | 
			
		||||
                        //play next if more anims still
 | 
			
		||||
                        PlayNextAnimation();
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        StopAnimating();
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            base.CompTick();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //returns false if still more animations
 | 
			
		||||
        public bool PopAnimationQueue()
 | 
			
		||||
        {
 | 
			
		||||
            
 | 
			
		||||
            if (!animationQueue.Empty())
 | 
			
		||||
            {
 | 
			
		||||
                //pop queue
 | 
			
		||||
                animationQueue.RemoveAt(0);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return animationQueue.Empty();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void PlayNextAnimation()
 | 
			
		||||
        {
 | 
			
		||||
            if (!animationQueue.Empty())
 | 
			
		||||
            {
 | 
			
		||||
                isAnimating = true;
 | 
			
		||||
                animationTicks = 0;
 | 
			
		||||
                pawn.Drawer.renderer.SetAnimation(animationQueue[0]);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void StopAnimating()
 | 
			
		||||
        {
 | 
			
		||||
            isAnimating = false;
 | 
			
		||||
            animationQueue = null;
 | 
			
		||||
            anchor = null;
 | 
			
		||||
            pawn.Drawer.renderer.SetAnimation(null);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void PlayGroupAnimation(List<AnimationDef> groupAnimation)
 | 
			
		||||
        {
 | 
			
		||||
            animationQueue = groupAnimation;
 | 
			
		||||
            PlayNextAnimation();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void PlayGroupAnimation(List<AnimationDef> groupAnimation, BaseExtendedAnimatorAnchor anchor)
 | 
			
		||||
        {
 | 
			
		||||
            this.anchor = anchor;
 | 
			
		||||
            animationQueue = groupAnimation;
 | 
			
		||||
            PlayNextAnimation();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override void PostExposeData()
 | 
			
		||||
        {
 | 
			
		||||
            base.PostExposeData();
 | 
			
		||||
            Scribe_Values.Look<bool>(ref this.isAnimating, "animations_isAnimating", false);
 | 
			
		||||
 | 
			
		||||
            Scribe_Collections.Look<AnimationDef>(ref animationQueue, "animations_queue");
 | 
			
		||||
            Scribe_Deep.Look<BaseExtendedAnimatorAnchor>(ref this.anchor, "animations_anchor");
 | 
			
		||||
            
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private Pawn pawn => base.parent as Pawn;
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,6 +12,7 @@ namespace Rimworld_Animations {
 | 
			
		|||
        public CompProperties_ExtendedAnimator()
 | 
			
		||||
        {
 | 
			
		||||
            base.compClass = typeof(CompExtendedAnimator);
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,23 @@
 | 
			
		|||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using UnityEngine;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace Rimworld_Animations
 | 
			
		||||
{
 | 
			
		||||
    public abstract class BaseExtendedAnimatorAnchor : IExposable
 | 
			
		||||
    {
 | 
			
		||||
        public BaseExtendedAnimatorAnchor() { }
 | 
			
		||||
 | 
			
		||||
        public virtual void ExposeData() { }
 | 
			
		||||
        public abstract Vector3 getDrawPos();
 | 
			
		||||
 | 
			
		||||
        public string GetUniqueLoadID()
 | 
			
		||||
        {
 | 
			
		||||
            throw new NotImplementedException();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,34 @@
 | 
			
		|||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using UnityEngine;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace Rimworld_Animations
 | 
			
		||||
{
 | 
			
		||||
    public class ExtendedAnimatorAnchor_Thing : BaseExtendedAnimatorAnchor
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        private Thing thing;
 | 
			
		||||
 | 
			
		||||
        public ExtendedAnimatorAnchor_Thing() : base() { }
 | 
			
		||||
 | 
			
		||||
        public ExtendedAnimatorAnchor_Thing(Thing thing) : base()
 | 
			
		||||
        {
 | 
			
		||||
            this.thing = thing;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override Vector3 getDrawPos()
 | 
			
		||||
        {
 | 
			
		||||
            return thing.DrawPos;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override void ExposeData()
 | 
			
		||||
        {
 | 
			
		||||
            base.ExposeData();
 | 
			
		||||
            Scribe_References.Look<Thing>(ref this.thing, "animations_anchor_thing", false);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,33 @@
 | 
			
		|||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using UnityEngine;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace Rimworld_Animations
 | 
			
		||||
{
 | 
			
		||||
    public class ExtendedAnimatorAnchor_Vector3 : BaseExtendedAnimatorAnchor
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        public ExtendedAnimatorAnchor_Vector3() : base() { }
 | 
			
		||||
 | 
			
		||||
        private Vector3 position;
 | 
			
		||||
        public ExtendedAnimatorAnchor_Vector3(Vector3 position) : base()
 | 
			
		||||
        {
 | 
			
		||||
            this.position = position;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override Vector3 getDrawPos()
 | 
			
		||||
        {
 | 
			
		||||
            return position;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override void ExposeData()
 | 
			
		||||
        {
 | 
			
		||||
            base.ExposeData();
 | 
			
		||||
            Scribe_Values.Look<Vector3>(ref position, "animations_anchor_position", Vector3.zero);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -11,6 +11,7 @@ namespace Rimworld_Animations
 | 
			
		|||
    {
 | 
			
		||||
        public int actorShift = 0;
 | 
			
		||||
        public abstract bool CanAnimationBeUsed(List<Pawn> actors, out int reorder);
 | 
			
		||||
        public abstract string DebugMessage();
 | 
			
		||||
 | 
			
		||||
        //cool class for designating contexts for animations
 | 
			
		||||
        // configure CanAnimationBeUsed to test whether it can be used
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,7 +17,6 @@ namespace Rimworld_Animations
 | 
			
		|||
 | 
			
		||||
        public override bool CanAnimationBeUsed(List<Pawn> actors, out int reorder)
 | 
			
		||||
        {
 | 
			
		||||
            Log.Message("Testing this animation");
 | 
			
		||||
 | 
			
		||||
            JobDriver_SexBaseInitiator latestSexBaseInitiator = (actors.FindLast(x => x.jobs?.curDriver is JobDriver_SexBaseInitiator).jobs.curDriver as JobDriver_SexBaseInitiator);
 | 
			
		||||
            reorder = base.actorShift;
 | 
			
		||||
| 
						 | 
				
			
			@ -25,5 +24,11 @@ namespace Rimworld_Animations
 | 
			
		|||
 | 
			
		||||
            return interactionDefs.Contains(latestSexBaseInitiator.Sexprops.dictionaryKey);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override string DebugMessage()
 | 
			
		||||
        {
 | 
			
		||||
            return "Checking for RJWSex AnimationContext\n" 
 | 
			
		||||
                + "InteractionDefs: " + interactionDefs;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,6 +16,11 @@ namespace Rimworld_Animations
 | 
			
		|||
 | 
			
		||||
        public bool canAnimationBeUsed(List<Pawn> actors, out int reorder)
 | 
			
		||||
        {
 | 
			
		||||
            if (AnimationSettings.debugMode)
 | 
			
		||||
            {
 | 
			
		||||
                Log.Message("[anims] Checking if " + defName + " is valid animation");
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            
 | 
			
		||||
            foreach (BaseGroupAnimationContext context in contexts)
 | 
			
		||||
            {
 | 
			
		||||
| 
						 | 
				
			
			@ -28,5 +33,20 @@ namespace Rimworld_Animations
 | 
			
		|||
            reorder = 0;
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public List<AnimationDef> GetAllAnimationsForActor(int actor, int seed, int reorder = 0)
 | 
			
		||||
        {
 | 
			
		||||
            List<AnimationDef> animations = new List<AnimationDef>();
 | 
			
		||||
            int actorNumber = (actor + reorder) % numActors;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            foreach (AnimationStage stage in animationStages)
 | 
			
		||||
            {
 | 
			
		||||
                //add all new animations to list of animations
 | 
			
		||||
                animations.AddRange(stage.GetAnimations(actorNumber, seed));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return animations;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,7 +11,7 @@ namespace Rimworld_Animations
 | 
			
		|||
    {
 | 
			
		||||
 | 
			
		||||
        //Return a list containing a tuple; int for how long the animation should play for
 | 
			
		||||
        public abstract List<Tuple<int, AnimationDef>> GetAnimations(int actor, int seed);
 | 
			
		||||
        public abstract List<AnimationDef> GetAnimations(int actorNumber, int seed);
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,9 +10,9 @@ namespace Rimworld_Animations
 | 
			
		|||
    public class AnimationStage_Branch : AnimationStage
 | 
			
		||||
    {
 | 
			
		||||
        public List<AnimationStage> paths;
 | 
			
		||||
        public override List<Tuple<int, AnimationDef>> GetAnimations(int actor, int seed)
 | 
			
		||||
        public override List<AnimationDef> GetAnimations(int actorNumber, int seed)
 | 
			
		||||
        {
 | 
			
		||||
            return paths[(seed * 59) % paths.Count].GetAnimations(actor, seed);
 | 
			
		||||
            return paths[(seed * 59) % paths.Count].GetAnimations(actorNumber, seed);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,48 +12,50 @@ namespace Rimworld_Animations
 | 
			
		|||
        public int loops;
 | 
			
		||||
        public List<AnimationLoopOption> loopOptions;
 | 
			
		||||
 | 
			
		||||
        public override List<Tuple<int, AnimationDef>> GetAnimations(int actor, int seed)
 | 
			
		||||
        public override List<AnimationDef> GetAnimations(int actorNumber, int seed)
 | 
			
		||||
        {
 | 
			
		||||
            int numberOfActors = loopOptions[0].animationDefs.Count;
 | 
			
		||||
            List<Tuple<int, AnimationDef>> animations = new List<Tuple<int, AnimationDef>>();
 | 
			
		||||
            List<AnimationDef> animations = new List<AnimationDef>();
 | 
			
		||||
 | 
			
		||||
            for (int i = 0; i < loops; i++)
 | 
			
		||||
            {
 | 
			
		||||
 | 
			
		||||
                AnimationLoopOption option = getAnimationLoopOptionByWeight(seed + i, out int longestAnimLength);
 | 
			
		||||
                Tuple<int, AnimationDef> animation = Tuple.Create(longestAnimLength, option.animationDefs[actor]);
 | 
			
		||||
                animations.Append(animation);
 | 
			
		||||
                AnimationLoopOption option = getAnimationLoopOptionByWeight(seed + i);
 | 
			
		||||
                animations.Add(option.animationDefs[actorNumber]);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return animations;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        //select random element from loop options by weight; also calculate the longest anim length
 | 
			
		||||
        private AnimationLoopOption getAnimationLoopOptionByWeight(int seed)
 | 
			
		||||
        {
 | 
			
		||||
            int totalWeight = loopOptions.Sum(x => x.probability);
 | 
			
		||||
            int randomNumber = ((seed * 59) % totalWeight) + 1;
 | 
			
		||||
 | 
			
		||||
            int cumulativeWeight = 0;
 | 
			
		||||
            for (int i = 0; i < loopOptions.Count; i++) {
 | 
			
		||||
 | 
			
		||||
                
 | 
			
		||||
                cumulativeWeight += loopOptions[i].probability;
 | 
			
		||||
 | 
			
		||||
                //random number is same for all pawns because they all have the same seed
 | 
			
		||||
                
 | 
			
		||||
                if (randomNumber <= cumulativeWeight)
 | 
			
		||||
                {
 | 
			
		||||
                    return loopOptions[i];
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            //default
 | 
			
		||||
            return loopOptions.Last();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public class AnimationLoopOption
 | 
			
		||||
    {
 | 
			
		||||
        public int probability;
 | 
			
		||||
        public List<AnimationDef> animationDefs;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
        //select random element from loop options by weight; also calculate the longest anim length
 | 
			
		||||
        public AnimationLoopOption getAnimationLoopOptionByWeight(int seed, out int longestAnimLength)
 | 
			
		||||
        {
 | 
			
		||||
            int totalWeight = loopOptions.Sum(x => x.probability);
 | 
			
		||||
            int randomNumber = (seed * 56) % totalWeight;
 | 
			
		||||
 | 
			
		||||
            int cumulativeWeight = 0;
 | 
			
		||||
            foreach(AnimationLoopOption option in loopOptions) {
 | 
			
		||||
                cumulativeWeight += option.probability;
 | 
			
		||||
                if (randomNumber <= cumulativeWeight)
 | 
			
		||||
                {
 | 
			
		||||
                    longestAnimLength = option.animationDefs.Max(x => x.durationTicks);
 | 
			
		||||
                    return option;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            longestAnimLength = loopOptions[0].animationDefs.Max(x => x.durationTicks);
 | 
			
		||||
            return loopOptions[0];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,14 +7,17 @@ using Verse;
 | 
			
		|||
 | 
			
		||||
namespace Rimworld_Animations
 | 
			
		||||
{
 | 
			
		||||
    /* don't use? just use looprandomselect once
 | 
			
		||||
    public class AnimationStage_TicksDuration : AnimationStage
 | 
			
		||||
    {
 | 
			
		||||
        int ticks;
 | 
			
		||||
        List<AnimationDef> animationDefs;
 | 
			
		||||
        public int ticks;
 | 
			
		||||
        public List<AnimationDef> animationDefs;
 | 
			
		||||
 | 
			
		||||
        public override List<Tuple<int, AnimationDef>> GetAnimations(int actor, int seed)
 | 
			
		||||
        {
 | 
			
		||||
            return new List<Tuple<int, AnimationDef>>() { Tuple.Create(ticks, animationDefs[actor]) };
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    */
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -42,10 +42,9 @@ namespace Rimworld_Animations {
 | 
			
		|||
				List<Pawn> participants = partnerSexBaseReceiver.parteners.Append(partner).ToList();
 | 
			
		||||
 | 
			
		||||
				GroupAnimationDef groupAnimation = AnimationUtility.FindGroupAnimation(participants, out int reorder);
 | 
			
		||||
 | 
			
		||||
				if (groupAnimation != null)
 | 
			
		||||
                {
 | 
			
		||||
					AnimationUtility.StartGroupAnimation(participants, groupAnimation, reorder);
 | 
			
		||||
					AnimationUtility.StartGroupAnimation(participants, groupAnimation, reorder, partner);
 | 
			
		||||
				}
 | 
			
		||||
				
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,26 +18,28 @@ namespace Rimworld_Animations
 | 
			
		|||
        {
 | 
			
		||||
            if (__instance.AnimationWorker is AnimationWorker_KeyframesExtended extendedAnimWorker)
 | 
			
		||||
            {
 | 
			
		||||
                //INVIS IF ANIM CALLS FOR IT
 | 
			
		||||
                //replace maybe?
 | 
			
		||||
                if (!extendedAnimWorker.visibleAtTick(__instance.tree.AnimationTick))
 | 
			
		||||
                {
 | 
			
		||||
                    __instance.requestRecache = true;
 | 
			
		||||
                    return false;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                // HEAD ROTATION ADJUST FACING get rotated textures
 | 
			
		||||
                // ADJUST FACING get rotated textures
 | 
			
		||||
                // compare the previous tick to the current tick; if the current tick rotation is different, recache
 | 
			
		||||
 | 
			
		||||
                Rot4 animFacing = extendedAnimWorker.facingAtTick(__instance.tree.AnimationTick);
 | 
			
		||||
 | 
			
		||||
                if (parms.facing != animFacing)
 | 
			
		||||
                if (extendedAnimWorker.facingAtTick(__instance.tree.AnimationTick - 1) != extendedAnimWorker.facingAtTick(__instance.tree.AnimationTick))
 | 
			
		||||
                {
 | 
			
		||||
                    //requestRecache or else it won't update properly
 | 
			
		||||
                    __instance.requestRecache = true;
 | 
			
		||||
                    parms.facing = animFacing;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                //INVIS IF ANIM CALLS FOR IT
 | 
			
		||||
                //replace maybe?
 | 
			
		||||
 | 
			
		||||
                //cheaper call now comparing prev tick to cur tick
 | 
			
		||||
                if (extendedAnimWorker.visibleAtTick(__instance.tree.AnimationTick - 1) != extendedAnimWorker.visibleAtTick(__instance.tree.AnimationTick))
 | 
			
		||||
                {
 | 
			
		||||
                    __instance.requestRecache = true;
 | 
			
		||||
                    return extendedAnimWorker.visibleAtTick(__instance.tree.AnimationTick);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return true;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,6 +28,7 @@ namespace Rimworld_Animations
 | 
			
		|||
                && node.tree.rootNode.AnimationWorker is AnimationWorker_KeyframesExtended rootNodeAnimationWorker)
 | 
			
		||||
            {
 | 
			
		||||
                
 | 
			
		||||
                // this is only for the Vector3 position to work right
 | 
			
		||||
                parms.facing = rootNodeAnimationWorker.facingAtTick(node.tree.AnimationTick);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,23 +9,18 @@ namespace Rimworld_Animations {
 | 
			
		|||
    public static class HarmonyPatch_Pawn_DrawTracker {
 | 
			
		||||
        public static bool Prefix(ref Pawn ___pawn, ref Vector3 __result) {
 | 
			
		||||
 | 
			
		||||
            // If animating and is sexbaseinitiator jobdriver,
 | 
			
		||||
            if (___pawn?.Drawer?.renderer?.renderTree?.rootNode?.AnimationWorker is AnimationWorker_KeyframesExtended
 | 
			
		||||
                && ___pawn.jobs?.curDriver is JobDriver_SexBaseInitiator sexdriver)
 | 
			
		||||
 | 
			
		||||
            CompExtendedAnimator animator = ___pawn.TryGetComp<CompExtendedAnimator>();
 | 
			
		||||
 | 
			
		||||
            //align pos on top of partner, position, etc., based on animatoranchor
 | 
			
		||||
            if (animator != null && animator.IsAnchored)
 | 
			
		||||
            {
 | 
			
		||||
 | 
			
		||||
                //align pos on top of partner
 | 
			
		||||
                if (sexdriver?.Partner?.Drawer?.DrawPos != null)
 | 
			
		||||
                    __result = sexdriver.Partner.Drawer.DrawPos;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                __result = animator.getAnchor();
 | 
			
		||||
                return false;
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return true;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -29,7 +29,7 @@ namespace Rimworld_Animations {
 | 
			
		|||
            Scribe_Values.Look(ref orgasmQuiver, "RJWAnimations-orgasmQuiver");
 | 
			
		||||
            Scribe_Values.Look(ref fastAnimForQuickie, "RJWAnimations-fastAnimForQuickie");
 | 
			
		||||
            Scribe_Values.Look(ref rapeShiver, "RJWAnimations-rapeShiver");
 | 
			
		||||
            Scribe_Values.Look(ref hearts, "RJWAnimation-sheartsOnLovin");
 | 
			
		||||
            Scribe_Values.Look(ref hearts, "RJWAnimation-heartsOnLovin");
 | 
			
		||||
            Scribe_Values.Look(ref PlayAnimForNonsexualActs, "RJWAnims-PlayAnimForNonsexualActs");
 | 
			
		||||
            Scribe_Values.Look(ref applySemenOnAnimationOrgasm, "RJWAnimations-applySemenOnOrgasm", false);
 | 
			
		||||
            Scribe_Values.Look(ref soundOverride, "RJWAnimations-rjwAnimSoundOverride", true);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,15 +21,42 @@ namespace Rimworld_Animations {
 | 
			
		|||
            participants[1].Drawer.renderer.SetAnimation(AnimationDefOf.TestAnimation2);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //startgroupanimator with anchor
 | 
			
		||||
        //don't anchor to self if anchor is self
 | 
			
		||||
        public static void StartGroupAnimation(List<Pawn> participants, GroupAnimationDef groupAnimationDef, int reorder, Thing anchor)
 | 
			
		||||
        {
 | 
			
		||||
 | 
			
		||||
            int seed = GenTicks.TicksGame;
 | 
			
		||||
 | 
			
		||||
            for (int i = 0; i < participants.Count; i++)
 | 
			
		||||
            {
 | 
			
		||||
                if (anchor is Pawn pawn && pawn == participants[i])
 | 
			
		||||
                {
 | 
			
		||||
 | 
			
		||||
                    List<AnimationDef> allAnimationsForPawn = groupAnimationDef.GetAllAnimationsForActor(i, seed, reorder);
 | 
			
		||||
                    participants[i].TryGetComp<CompExtendedAnimator>().PlayGroupAnimation(allAnimationsForPawn);
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    //each participant gets their own unique extendedanimatoranchor, important for scribe_deep saving
 | 
			
		||||
 | 
			
		||||
                    List<AnimationDef> allAnimationsForPawn = groupAnimationDef.GetAllAnimationsForActor(i, seed, reorder);
 | 
			
		||||
                    BaseExtendedAnimatorAnchor animatorAnchor = new ExtendedAnimatorAnchor_Thing(anchor);
 | 
			
		||||
 | 
			
		||||
                    participants[i].TryGetComp<CompExtendedAnimator>().PlayGroupAnimation(allAnimationsForPawn, animatorAnchor);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        //startgroupanimation without anchor; just play where standing
 | 
			
		||||
        public static void StartGroupAnimation(List<Pawn> participants, GroupAnimationDef groupAnimationDef, int reorder)
 | 
			
		||||
        {
 | 
			
		||||
            for(int i = 0; i < participants.Count; i++)
 | 
			
		||||
            int seed = GenTicks.TicksGame;
 | 
			
		||||
 | 
			
		||||
            for (int i = 0; i < participants.Count; i++)
 | 
			
		||||
            {
 | 
			
		||||
                //todo: pass all animationstages to ExtendedAnimator, and queue animations
 | 
			
		||||
                participants[i].Drawer.renderer.SetAnimation(
 | 
			
		||||
                    groupAnimationDef.animationStages[0]
 | 
			
		||||
                    .GetAnimations((i + reorder) % participants.Count, GenTicks.TicksGame)[0].Item2);
 | 
			
		||||
                List<AnimationDef> allAnimationsForPawn = groupAnimationDef.GetAllAnimationsForActor(i, seed, reorder);
 | 
			
		||||
                participants[i].TryGetComp<CompExtendedAnimator>().PlayGroupAnimation(allAnimationsForPawn);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -38,13 +65,13 @@ namespace Rimworld_Animations {
 | 
			
		|||
        {
 | 
			
		||||
            foreach(Pawn pawn in participants)
 | 
			
		||||
            {
 | 
			
		||||
                pawn.Drawer.renderer.SetAnimation(null);
 | 
			
		||||
                pawn.TryGetComp<CompExtendedAnimator>()?.StopAnimating();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        public static void StopGroupAnimation(Pawn participant)
 | 
			
		||||
        {
 | 
			
		||||
            participant?.Drawer?.renderer?.SetAnimation(null);
 | 
			
		||||
            participant.TryGetComp<CompExtendedAnimator>()?.StopAnimating();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static GroupAnimationDef FindGroupAnimation(List<Pawn> participants, out int reorder)
 | 
			
		||||
| 
						 | 
				
			
			@ -55,8 +82,6 @@ namespace Rimworld_Animations {
 | 
			
		|||
 | 
			
		||||
            int reorder2 = 0;
 | 
			
		||||
 | 
			
		||||
            Log.Message(DefDatabase<GroupAnimationDef>.AllDefsListForReading[0].defName);
 | 
			
		||||
 | 
			
		||||
            DefDatabase<GroupAnimationDef>.AllDefsListForReading.TryRandomElement((GroupAnimationDef x) =>
 | 
			
		||||
                x.canAnimationBeUsed(participants, out reorder2), out GroupAnimationDef result);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
										
											Binary file not shown.
										
									
								
							| 
						 | 
				
			
			@ -77,6 +77,9 @@
 | 
			
		|||
    <Compile Include="1.5\Source\Comps\CompProperties_ExtendedAnimator.cs" />
 | 
			
		||||
    <Compile Include="1.5\Source\Comps\CompProperties_ThingAnimator.cs" />
 | 
			
		||||
    <Compile Include="1.5\Source\Comps\CompThingAnimator.cs" />
 | 
			
		||||
    <Compile Include="1.5\Source\Comps\ExtendedAnimatorAnchor\BaseExtendedAnimatorAnchor.cs" />
 | 
			
		||||
    <Compile Include="1.5\Source\Comps\ExtendedAnimatorAnchor\ExtendedAnimatorAnchor_Thing.cs" />
 | 
			
		||||
    <Compile Include="1.5\Source\Comps\ExtendedAnimatorAnchor\ExtendedAnimatorAnchor_Vector3.cs" />
 | 
			
		||||
    <Compile Include="1.5\Source\Defs\AnimationDefOf.cs" />
 | 
			
		||||
    <Compile Include="1.5\Source\GroupAnimations\GroupAnimationContexts\BaseGroupAnimationContext.cs" />
 | 
			
		||||
    <Compile Include="1.5\Source\GroupAnimations\GroupAnimationContexts\GroupAnimationContext_RJWSex.cs" />
 | 
			
		||||
| 
						 | 
				
			
			@ -114,6 +117,7 @@
 | 
			
		|||
    <Content Include="1.5\Defs\AnimationDefs\TestAnimation2.xml" />
 | 
			
		||||
    <Content Include="1.5\Defs\GroupAnimationDefs\TestGroupAnimation1.xml" />
 | 
			
		||||
    <Content Include="1.5\Defs\MainTabDefs\MainButtonDef.xml" />
 | 
			
		||||
    <Content Include="1.5\Defs\OffsetDefs\OffsetDef_GroinToAppropriateHeight.xml" />
 | 
			
		||||
    <Content Include="1.5\Defs\SoundDefs\Sounds_Sex.xml" />
 | 
			
		||||
    <Content Include="1.5\Patches\AnimationPatchHSK.xml" />
 | 
			
		||||
    <Content Include="1.5\Patches\AnimationPatch_CompExtendedAnimator.xml" />
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue