diff --git a/1.6/Assemblies/Rimworld-Animations.dll b/1.6/Assemblies/Rimworld-Animations.dll
index cf6a166..a52d4f5 100644
Binary files a/1.6/Assemblies/Rimworld-Animations.dll and b/1.6/Assemblies/Rimworld-Animations.dll differ
diff --git a/1.6/Defs/GroupAnimationDefs/Cunnilingus/GroupAnimation_Cunnilingus.xml b/1.6/Defs/GroupAnimationDefs/Cunnilingus/GroupAnimation_Cunnilingus.xml
index 68d4e4b..a7e6f5a 100644
--- a/1.6/Defs/GroupAnimationDefs/Cunnilingus/GroupAnimation_Cunnilingus.xml
+++ b/1.6/Defs/GroupAnimationDefs/Cunnilingus/GroupAnimation_Cunnilingus.xml
@@ -82,11 +82,7 @@
1
-
-
-
-
-
+
@@ -99,14 +95,18 @@
-
+
+
1
-
+
+
+
+
@@ -117,12 +117,6 @@
-
-
-
-
-
-
@@ -131,15 +125,6 @@
0
-
-
-
-
-
-
-
-
-
@@ -147,6 +132,12 @@
+
+
+
+
+
+
diff --git a/1.6/Patches/AnimationPatch_PawnRenderTree_OffsetSubWorker.xml b/1.6/Patches/AnimationPatch_PawnRenderTree_OffsetSubWorker.xml
index a12b7b6..6aa36a8 100644
--- a/1.6/Patches/AnimationPatch_PawnRenderTree_OffsetSubWorker.xml
+++ b/1.6/Patches/AnimationPatch_PawnRenderTree_OffsetSubWorker.xml
@@ -1,16 +1,20 @@
-
+
Always
-
+
+ /Defs/PawnRenderTreeDef/root/subworkerClasses
Always
- /Defs/PawnRenderTreeDef/root[not(subworkerClasses)]
-
-
-
+
+ /Defs/PawnRenderTreeDef/root
+
+
+
+
+
/Defs/PawnRenderTreeDef/root/subworkerClasses
@@ -19,4 +23,5 @@
+
\ No newline at end of file
diff --git a/1.6/Source/Animations/GroupAnimations/GroupAnimationContexts/GroupAnimationContext.cs b/1.6/Source/Animations/GroupAnimations/GroupAnimationContexts/GroupAnimationContext.cs
index 0cb13b6..74d91da 100644
--- a/1.6/Source/Animations/GroupAnimations/GroupAnimationContexts/GroupAnimationContext.cs
+++ b/1.6/Source/Animations/GroupAnimations/GroupAnimationContexts/GroupAnimationContext.cs
@@ -91,7 +91,7 @@ namespace Rimworld_Animations
public List FindAnyWorkingSet(List actors)
{
- if (whitelist.NullOrEmpty() || actors.Count != whitelist.Count) return null;
+ if (actors.Count != whitelist.Count) return null;
int numActors = actors.Count;
@@ -170,7 +170,7 @@ namespace Rimworld_Animations
return false;
}
- if (!blacklist.NullOrEmpty() && index < blacklist.Count && blacklist[index] != null && blacklist[index].PawnTest(actor))
+ if (!blacklist.NullOrEmpty() && blacklist[index].PawnTest(actor))
{
return false;
}
diff --git a/1.6/Source/Animations/GroupAnimations/GroupAnimationDef.cs b/1.6/Source/Animations/GroupAnimations/GroupAnimationDef.cs
index c314bef..30c9f61 100644
--- a/1.6/Source/Animations/GroupAnimations/GroupAnimationDef.cs
+++ b/1.6/Source/Animations/GroupAnimations/GroupAnimationDef.cs
@@ -167,9 +167,7 @@ namespace Rimworld_Animations
string bodyTypeDef = (pawn.story?.bodyType != null) ? pawn.story.bodyType.ToString() : "";
- //defs without offsetDefs (or fewer than numActors) just get no offset
- if (!offsetDefs.NullOrEmpty() && actor < offsetDefs.Count && offsetDefs[actor] != null
- && offsetDefs[actor].FindOffset(pawn, out BaseAnimationOffset animationOffset))
+ if (offsetDefs[actor].FindOffset(pawn, out BaseAnimationOffset animationOffset))
{
position = animationOffset.getOffset(pawn);
rotation = animationOffset.getRotation(pawn);
diff --git a/1.6/Source/Comps/CompExtendedAnimator.cs b/1.6/Source/Comps/CompExtendedAnimator.cs
index fe71c2a..17ce3a3 100644
--- a/1.6/Source/Comps/CompExtendedAnimator.cs
+++ b/1.6/Source/Comps/CompExtendedAnimator.cs
@@ -26,12 +26,6 @@ namespace Rimworld_Animations {
private VoiceDef voice;
private VoiceTagDef lastVoiceTag;
- //dead actors (corpses) in this pawn's animation; corpses only TickRare, so this comp ticks their animators for them
- private List drivenPawns;
-
- //the renderer's current animation isn't saved by vanilla; reapply it on the first tick after loading
- private bool restoreAnimationAfterLoad;
-
private bool isAnimating = false;
@@ -47,7 +41,7 @@ namespace Rimworld_Animations {
{
get
{
- return anchor != null && anchor.IsValid;
+ return anchor != null;
}
}
@@ -141,42 +135,6 @@ namespace Rimworld_Animations {
public override void CompTick()
{
- AnimatorTick();
-
- if (!drivenPawns.NullOrEmpty())
- {
- foreach (Pawn drivenPawn in drivenPawns.ToList())
- {
- CompExtendedAnimator drivenAnimator = drivenPawn?.TryGetComp();
-
- //stop driving if the corpse finished, was destroyed or got resurrected (it ticks itself again)
- if (drivenAnimator == null || !drivenAnimator.IsAnimating || !drivenPawn.Dead)
- {
- drivenPawns.Remove(drivenPawn);
- continue;
- }
-
- drivenAnimator.AnimatorTick();
- }
- }
-
- base.CompTick();
- }
-
- public void AddDrivenPawn(Pawn deadPawn)
- {
- if (drivenPawns == null) drivenPawns = new List();
- drivenPawns.AddDistinct(deadPawn);
- }
-
- public void AnimatorTick()
- {
- if (restoreAnimationAfterLoad)
- {
- restoreAnimationAfterLoad = false;
- RestoreAnimationAfterLoad();
- }
-
if (isAnimating)
{
animationTicks++;
@@ -199,6 +157,10 @@ namespace Rimworld_Animations {
CheckAndPlaySounds();
}
+
+
+
+ base.CompTick();
}
//returns false if still more animations
@@ -224,33 +186,8 @@ namespace Rimworld_Animations {
}
}
- private void RestoreAnimationAfterLoad()
- {
- if (!isAnimating || animationQueue.NullOrEmpty()) return;
-
- PawnRenderer renderer = pawn.Drawer?.renderer;
- if (renderer?.renderTree == null) return;
-
- renderer.SetAnimation(animationQueue[0]);
-
- //resume partway through the current animation instead of from its first frame
- renderer.renderTree.animationStartTick = GenTicks.TicksGame - animationTicks;
- renderer.SetAllGraphicsDirty();
- }
-
public void StopAnimating()
{
- //stop any corpses this pawn was animating, since they can't stop themselves
- if (!drivenPawns.NullOrEmpty())
- {
- List pawnsToStop = drivenPawns;
- drivenPawns = null;
- foreach (Pawn drivenPawn in pawnsToStop)
- {
- drivenPawn?.TryGetComp()?.StopAnimating();
- }
- }
-
isAnimating = false;
animationQueue = null;
anchor = null;
@@ -266,7 +203,6 @@ namespace Rimworld_Animations {
this.actorIndex = actorIndex;
this.currentGroupAnimation = groupAnimationDef;
- drivenPawns = null;
ticksSinceLastVoicePlayed = GenTicks.TicksGame;
ticksUntilNextVoice = 0;
@@ -300,23 +236,9 @@ namespace Rimworld_Animations {
Scribe_Collections.Look(ref animationQueue, "animations_queue");
Scribe_Defs.Look(ref currentGroupAnimation, "animations_groupAnimationDef");
Scribe_Deep.Look(ref this.anchor, "animations_anchor");
- //dead pawns count as destroyed, so their references must be saved with saveDestroyedThings or they load as null
- Scribe_Collections.Look(ref this.drivenPawns, "animations_drivenPawns", true, LookMode.Reference);
Scribe_Values.Look(ref this.offset, "animations_offset", Vector3.zero);
Scribe_Values.Look(ref this.rotation, "animations_rotationOffset", 0);
Scribe_Defs.Look(ref this.voice, "animations_voice");
-
- if (Scribe.mode == LoadSaveMode.PostLoadInit)
- {
- drivenPawns?.RemoveAll(x => x == null);
-
- if (isAnimating)
- {
- //animation defs can go missing between saves (e.g. an anim pack was removed)
- if (animationQueue.NullOrEmpty()) isAnimating = false;
- else restoreAnimationAfterLoad = true;
- }
- }
}
@@ -389,79 +311,123 @@ namespace Rimworld_Animations {
public void CheckAndPlaySounds()
{
- //use held position/map so it also works for pawns inside corpses
- Map map = pawn.MapHeld;
- if (map == null) return;
PawnRenderNode rootNode = pawn.Drawer?.renderer?.renderTree?.rootNode;
- //check the rootnode for sounds
- if (rootNode != null)
+ //check if the rootnode has sounds; if so play it
+ if (rootNode?.AnimationWorker is AnimationWorker_KeyframesExtended animWorker)
{
- PlaySoundsForNode(rootNode, map);
- }
-
- //do the same for all the child nodes
- if (rootNode?.children != null)
- {
- foreach (PawnRenderNode node in rootNode.children)
- {
- if (node != null) PlaySoundsForNode(node, map);
- }
- }
- }
-
- private void PlaySoundsForNode(PawnRenderNode node, Map map)
- {
- if (!(node.AnimationWorker is AnimationWorker_KeyframesExtended animWorker)) return;
-
- if (RJWAnimationSettings.playSounds)
- {
- SoundDef sound = animWorker.soundAtTick(node.tree.AnimationTick, node.tree.currentAnimation, node);
+ SoundDef sound = animWorker.soundAtTick(rootNode.tree.AnimationTick, rootNode.tree.currentAnimation, rootNode);
if (sound != null)
{
- SoundInfo soundInfo = new TargetInfo(pawn.PositionHeld, map);
+ SoundInfo soundInfo = new TargetInfo(pawn.Position, pawn.Map);
//temp; does not consider non-rjw animations
//todo: replace with value stored in comp or somewhere else?
soundInfo.volumeFactor = RJWAnimationSettings.soundVolume;
+
sound.PlayOneShot(soundInfo);
}
- }
- //corpses don't talk
- if (!RJWAnimationSettings.playVoices || pawn.Dead) return;
-
- //play voice sounds
- VoiceTagDef voiceTag = animWorker.voiceAtTick(node.tree.AnimationTick, node.tree.currentAnimation, node);
- if (voiceTag == null
- || (lastVoiceTag == voiceTag && ticksSinceLastVoicePlayed + ticksUntilNextVoice >= GenTicks.TicksGame)) //play a new voice tag, or wait until time elapsed
- {
- return;
- }
-
- lastVoiceTag = voiceTag;
- ticksSinceLastVoicePlayed = GenTicks.TicksGame;
-
- SoundInfo voiceInfo = new TargetInfo(pawn.PositionHeld, map);
- voiceInfo.volumeFactor = RJWAnimationSettings.voicesVolume;
-
- if (voice != null && voice.sounds.ContainsKey(voiceTag))
- {
- ticksUntilNextVoice = voice.ticksBetweenPlays.RandomInRange;
- voice.sounds[voiceTag].PlayOneShot(voiceInfo);
- }
- else if (pawn.RaceProps.Humanlike && RJWAnimationSettings.playHumanlikeVoicesAsDefault)
- {
- //play default voice
- VoiceDef pawnDefaultVoice = (pawn.gender == Gender.Male ? VoiceDefOf.Voice_HumanMale : VoiceDefOf.Voice_HumanFemale);
- if (pawnDefaultVoice.sounds.ContainsKey(voiceTag))
+ if (RJWAnimationSettings.playVoices)
{
- ticksUntilNextVoice = pawnDefaultVoice.ticksBetweenPlays.RandomInRange;
- pawnDefaultVoice.sounds[voiceTag].PlayOneShot(voiceInfo);
+ SoundInfo voiceInfo = new TargetInfo(pawn.Position, pawn.Map);
+ voiceInfo.volumeFactor = RJWAnimationSettings.voicesVolume;
+
+ //play voice sounds
+ VoiceTagDef voiceTag = animWorker.voiceAtTick(rootNode.tree.AnimationTick, rootNode.tree.currentAnimation, rootNode);
+ if (voiceTag != null
+ && (lastVoiceTag != voiceTag || ticksSinceLastVoicePlayed + ticksUntilNextVoice < GenTicks.TicksGame)) //play a new voice tag, or wait until time elapsed
+ {
+ lastVoiceTag = voiceTag;
+ ticksSinceLastVoicePlayed = GenTicks.TicksGame;
+
+ if (voice != null && voice.sounds.ContainsKey(voiceTag))
+ {
+ ticksUntilNextVoice = voice.ticksBetweenPlays.RandomInRange;
+ voice.sounds[voiceTag].PlayOneShot(voiceInfo);
+ }
+
+ else if (pawn.RaceProps.Humanlike && RJWAnimationSettings.playHumanlikeVoicesAsDefault)
+ {
+ //play default voice
+ VoiceDef pawnDefaultVoice = (pawn.gender == Gender.Male ? VoiceDefOf.Voice_HumanMale : VoiceDefOf.Voice_HumanFemale);
+
+ ticksUntilNextVoice = pawnDefaultVoice.ticksBetweenPlays.RandomInRange;
+
+ if (pawnDefaultVoice.sounds.ContainsKey(voiceTag))
+ {
+ ticksUntilNextVoice = pawnDefaultVoice.ticksBetweenPlays.RandomInRange;
+ pawnDefaultVoice.sounds[voiceTag].PlayOneShot(voiceInfo);
+ }
+
+
+ }
+
+ }
+ }
+
+
+ }
+
+ //check rootnodes and children
+ if (rootNode?.children != null)
+ {
+ foreach (PawnRenderNode node in rootNode?.children)
+ {
+ if (node?.AnimationWorker is AnimationWorker_KeyframesExtended childrenAnimWorker)
+ {
+
+
+ if (RJWAnimationSettings.playSounds)
+ {
+ SoundDef sound = childrenAnimWorker.soundAtTick(node.tree.AnimationTick, node.tree.currentAnimation, node);
+
+ if (sound != null)
+ {
+ SoundInfo soundInfo = new TargetInfo(pawn.Position, pawn.Map);
+ soundInfo.volumeFactor = RJWAnimationSettings.soundVolume;
+ sound.PlayOneShot(soundInfo);
+ }
+ }
+
+ if (RJWAnimationSettings.playVoices)
+ {
+
+ SoundInfo voiceInfo = new TargetInfo(pawn.Position, pawn.Map);
+ voiceInfo.volumeFactor = RJWAnimationSettings.voicesVolume;
+
+ //play voice sounds
+ VoiceTagDef voiceTag = childrenAnimWorker.voiceAtTick(rootNode.tree.AnimationTick, rootNode.tree.currentAnimation, rootNode);
+ if (voiceTag != null
+ && (lastVoiceTag != voiceTag || ticksSinceLastVoicePlayed + ticksUntilNextVoice < GenTicks.TicksGame)) //play a new voice tag, or wait until time elapsed
+ {
+ lastVoiceTag = voiceTag;
+ ticksSinceLastVoicePlayed = GenTicks.TicksGame;
+
+ if (voice != null && voice.sounds.ContainsKey(voiceTag))
+ {
+ ticksUntilNextVoice = voice.ticksBetweenPlays.RandomInRange;
+ voice.sounds[voiceTag].PlayOneShot(voiceInfo);
+ }
+ else if (pawn.RaceProps.Humanlike && RJWAnimationSettings.playHumanlikeVoicesAsDefault)
+ {
+
+ VoiceDef pawnDefaultVoice = (pawn.gender == Gender.Male ? VoiceDefOf.Voice_HumanMale : VoiceDefOf.Voice_HumanFemale);
+ if (pawnDefaultVoice.sounds.ContainsKey(voiceTag))
+ {
+ ticksUntilNextVoice = pawnDefaultVoice.ticksBetweenPlays.RandomInRange;
+ pawnDefaultVoice.sounds[voiceTag].PlayOneShot(voiceInfo);
+ }
+ }
+ }
+ }
+ }
}
}
+ //do the same for all the child nodes
+
}
diff --git a/1.6/Source/Comps/ExtendedAnimatorAnchor/BaseExtendedAnimatorAnchor.cs b/1.6/Source/Comps/ExtendedAnimatorAnchor/BaseExtendedAnimatorAnchor.cs
index 8cf28af..6116a8c 100644
--- a/1.6/Source/Comps/ExtendedAnimatorAnchor/BaseExtendedAnimatorAnchor.cs
+++ b/1.6/Source/Comps/ExtendedAnimatorAnchor/BaseExtendedAnimatorAnchor.cs
@@ -15,9 +15,6 @@ namespace Rimworld_Animations
public virtual void ExposeData() { }
public abstract Vector3 getDrawPos();
- //false if the anchor can't be drawn at anymore (e.g. the thing was destroyed)
- public virtual bool IsValid => true;
-
public string GetUniqueLoadID()
{
throw new NotImplementedException();
diff --git a/1.6/Source/Comps/ExtendedAnimatorAnchor/ExtendedAnimatorAnchor_Thing.cs b/1.6/Source/Comps/ExtendedAnimatorAnchor/ExtendedAnimatorAnchor_Thing.cs
index bd1fa4b..6f86334 100644
--- a/1.6/Source/Comps/ExtendedAnimatorAnchor/ExtendedAnimatorAnchor_Thing.cs
+++ b/1.6/Source/Comps/ExtendedAnimatorAnchor/ExtendedAnimatorAnchor_Thing.cs
@@ -26,9 +26,6 @@ namespace Rimworld_Animations
this.thing = thing;
}
- //spawned check also covers destroyed things, and things that didn't come back after loading
- public override bool IsValid => thing != null && thing.Spawned;
-
public override Vector3 getDrawPos()
{
//x and z position, regular altitude for pawns
diff --git a/1.6/Source/MainTabWindows/MainTabWindow_OffsetConfigure.cs b/1.6/Source/MainTabWindows/MainTabWindow_OffsetConfigure.cs
index 4b2878a..318e9c2 100644
--- a/1.6/Source/MainTabWindows/MainTabWindow_OffsetConfigure.cs
+++ b/1.6/Source/MainTabWindows/MainTabWindow_OffsetConfigure.cs
@@ -58,20 +58,13 @@ namespace Rimworld_Animations {
if (listingStandard.ButtonText("RimAnims_Reset".Translate()))
{
- //remove the saved override entirely; an entry left behind would keep overriding the def's offset with zeros
- RJWAnimationSettings.offsets?.Remove(AnimationUtility.OffsetLookupKey(curPawn));
-
- //go back to the offset from the animation's offsetDefs
- extendedAnimator.CurrentGroupAnimation.GetOffset(extendedAnimator.ActorIndex, curPawn, out Vector3? defOffset, out int? defRotation);
- extendedAnimator.Offset = defOffset;
- extendedAnimator.Rotation = defRotation;
-
- Vector3 resetOffset = defOffset ?? Vector3.zero;
- posX = resetOffset.x;
- posY = resetOffset.y;
- posZ = resetOffset.z;
- rot = defRotation ?? 0;
-
+ if (!RJWAnimationSettings.offsets.NullOrEmpty()
+ && RJWAnimationSettings.offsets.ContainsKey(AnimationUtility.OffsetLookupKey(curPawn)))
+ {
+ RJWAnimationSettings.offsets[AnimationUtility.OffsetLookupKey(curPawn)].Reset();
+ }
+ posX = posY = posZ = rot = 0;
+
}
listingStandard.GapLine();
diff --git a/1.6/Source/Patches/RJWPatches/JobDrivers/HarmonyPatch_JobDriver_Masturbate.cs b/1.6/Source/Patches/RJWPatches/JobDrivers/HarmonyPatch_JobDriver_Masturbate.cs
new file mode 100644
index 0000000..d7c9e98
--- /dev/null
+++ b/1.6/Source/Patches/RJWPatches/JobDrivers/HarmonyPatch_JobDriver_Masturbate.cs
@@ -0,0 +1,55 @@
+using HarmonyLib;
+using rjw;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Verse;
+using Verse.AI;
+
+namespace Rimworld_Animations
+{
+ [HarmonyPatch(typeof(JobDriver_Masturbate), "SetupDurationTicks")]
+ public class HarmonyPatch_JobDriver_Masturbate
+ {
+ public static void Postfix(JobDriver_Masturbate __instance)
+ {
+ //prevent early stoppage of masturbate jobdriver during animation
+
+ /* not needed anymore? Ticks are assigned during animation
+
+ __instance.duration = 10000000;
+ __instance.ticks_left = __instance.duration;
+
+ */
+
+ }
+ }
+
+ [HarmonyPatch(typeof(JobDriver_Masturbate), "MakeNewToils")]
+ public class HarmonyPatch_JobDriver_Masturbate2
+ {
+ public static void Postfix(JobDriver_Masturbate __instance, ref IEnumerable __result)
+ {
+
+ var toils = __result.ToList();
+
+ //sex toil
+ toils[1].initAction += delegate ()
+ {
+ CompExtendedAnimator pawnAnimator = __instance.pawn.TryGetComp();
+
+ // if pawn was given an animation to play,
+ if (pawnAnimator.IsAnimating)
+ {
+ //set duration of masturbate toil to anim length
+ toils[1].defaultDuration = pawnAnimator.AnimationLength;
+ }
+
+ };
+
+ __result = toils.AsEnumerable();
+ }
+ }
+}
diff --git a/1.6/Source/Patches/RJWPatches/JobDrivers/HarmonyPatch_JobDriver_Sex.cs b/1.6/Source/Patches/RJWPatches/JobDrivers/HarmonyPatch_JobDriver_Sex.cs
index d8d3ae2..622b7c1 100644
--- a/1.6/Source/Patches/RJWPatches/JobDrivers/HarmonyPatch_JobDriver_Sex.cs
+++ b/1.6/Source/Patches/RJWPatches/JobDrivers/HarmonyPatch_JobDriver_Sex.cs
@@ -30,57 +30,36 @@ namespace Rimworld_Animations
public static void Postfix(JobDriver_Sex __instance, Pawn pawn, Thing target)
{
//if neverending sex and pawn doesn't have an animation,
- //only retry about once a second; searching every animation def every tick is expensive when none fit
- if (!__instance.neverendingsex
- || !pawn.IsHashIntervalTick(60)
- || !(pawn.TryGetComp() is CompExtendedAnimator animator)
- || animator.IsAnimating)
+ if (__instance.neverendingsex
+ && !pawn.TryGetComp().IsAnimating)
{
- return;
- }
- //start a new animation for all the pawns paired with receiver job driver
- List participants;
- Thing anchor = __instance.Bed;
- if (target is Pawn receiverPawn)
- {
- participants = (receiverPawn.jobs?.curDriver as JobDriver_SexBaseReciever)?.parteners?.ToList();
- if (participants.NullOrEmpty()) return;
-
- if (!participants.Contains(receiverPawn))
+ //start a new animation for all the pawns paired with receiver job driver
+ List participants;
+ if (target is Pawn receiverPawn)
{
- participants.Add(receiverPawn);
+ participants = (receiverPawn?.jobs?.curDriver as JobDriver_SexBaseReciever)?.parteners;
+ if (!participants.NullOrEmpty() && !participants.Contains(receiverPawn))
+ {
+ participants = participants.Append(receiverPawn).ToList();
+ }
}
- anchor = anchor ?? receiverPawn;
- }
- else if (target is Corpse corpse && corpse.InnerPawn != null)
- {
- participants = new List { pawn, corpse.InnerPawn };
- anchor = anchor ?? corpse;
- }
- else
- {
- participants = new List { pawn };
- anchor = anchor ?? pawn;
- }
-
- GroupAnimationDef animation = AnimationUtility.FindGroupAnimation(participants, out List participantsOrdered);
- if (animation == null) return;
-
- AnimationUtility.StartGroupAnimation(participantsOrdered, animation, anchor);
-
- //keep rjw's timers in step with the new animation, same as when sex starts
- int animTicks = AnimationUtility.GetAnimationLength(pawn);
- foreach (Pawn participant in participants)
- {
- if (participant?.jobs?.curDriver is JobDriver_Sex participantJobDriver)
+ else
{
- participantJobDriver.ticks_left = animTicks;
- participantJobDriver.sex_ticks = animTicks;
- participantJobDriver.orgasmStartTick = animTicks;
- participantJobDriver.duration = animTicks;
+ participants = new List { pawn };
}
+
+
+ GroupAnimationDef animation = AnimationUtility.FindGroupAnimation(participants, out List participantsOrdered);
+ if (animation != null)
+ {
+ Thing anchor = (Thing)__instance.Bed ?? pawn;
+ AnimationUtility.StartGroupAnimation(participantsOrdered, animation, anchor);
+ }
+
+
}
+
}
}
diff --git a/1.6/Source/Patches/RJWPatches/JobDrivers/HarmonyPatch_JobDriver_SexBaseInitiator.cs b/1.6/Source/Patches/RJWPatches/JobDrivers/HarmonyPatch_JobDriver_SexBaseInitiator.cs
index d2680ce..36a1316 100644
--- a/1.6/Source/Patches/RJWPatches/JobDrivers/HarmonyPatch_JobDriver_SexBaseInitiator.cs
+++ b/1.6/Source/Patches/RJWPatches/JobDrivers/HarmonyPatch_JobDriver_SexBaseInitiator.cs
@@ -24,10 +24,6 @@ namespace Rimworld_Animations
{
participants = new List() { pawn };
}
- else if (partner == null)
- {
- return;
- }
else if (__instance is JobDriver_ViolateCorpse)
{
participants = new List() { pawn, partner };
@@ -56,23 +52,18 @@ namespace Rimworld_Animations
if (groupAnimation != null)
{
- //anchor to the corpse itself, not its InnerPawn; a pawn inside a corpse keeps the position it died at
- Thing anchor = (Thing)__instance.Bed ?? (Thing)(__instance.Target as Corpse) ?? partner;
+ Thing anchor = (Thing)__instance.Bed ?? partner;
AnimationUtility.StartGroupAnimation(participantsOrdered, groupAnimation, anchor);
int animTicks = AnimationUtility.GetAnimationLength(pawn);
- if (RJWAnimationSettings.debugMode)
- {
- Log.Message("InteractionDef: " + __instance.Sexprops?.dictionaryKey);
- }
-
+ Log.Message("InteractionDef: " + __instance.Sexprops.dictionaryKey);
foreach (Pawn participant in participants)
{
if (RJWAnimationSettings.debugMode)
{
- Log.Message("Participant: " + participant?.Name);
- Log.Message("JobDriver: " + participant?.CurJobDef?.defName);
+ Log.Message("Participant: " + participant.Name);
+ Log.Message("JobDriver: " + participant.CurJobDef.defName);
}
//null ref check for pawns that might have lost their jobs or become null for some reason
diff --git a/1.6/Source/Patches/RJWPatches/JobDrivers/SexBaseReceivers/HarmonyPatch_JobDriver_SexBaseReceiverRaped.cs b/1.6/Source/Patches/RJWPatches/JobDrivers/SexBaseReceivers/HarmonyPatch_JobDriver_SexBaseReceiverRaped.cs
new file mode 100644
index 0000000..703bdcc
--- /dev/null
+++ b/1.6/Source/Patches/RJWPatches/JobDrivers/SexBaseReceivers/HarmonyPatch_JobDriver_SexBaseReceiverRaped.cs
@@ -0,0 +1,29 @@
+using HarmonyLib;
+using rjw;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Verse.AI;
+
+namespace Rimworld_Animations
+{
+ [HarmonyPatch(typeof(JobDriver_SexBaseRecieverRaped), "MakeNewToils")]
+ public class HarmonyPatch_JobDriver_SexBaseReceiverRaped
+ {
+ /*
+ * Doesn't work; ienumerables are read-only, can't modify toil
+ * would need to harmonypatch; stopped partner animating in sexbaseinitiator instead
+ *
+ public static void Postfix(JobDriver_SexBaseRecieverRaped __instance, ref IEnumerable __result)
+ {
+ //added for sudden end of jobdriver
+ __result.Last().AddFinishAction(delegate {
+ AnimationUtility.StopGroupAnimation(__instance.pawn);
+ });
+ }
+
+ */
+ }
+}
diff --git a/1.6/Source/Patches/RimworldPatches/HarmonyPatch_PawnRenderTree.cs b/1.6/Source/Patches/RimworldPatches/HarmonyPatch_PawnRenderTree.cs
index 3070ff7..c62bcc4 100644
--- a/1.6/Source/Patches/RimworldPatches/HarmonyPatch_PawnRenderTree.cs
+++ b/1.6/Source/Patches/RimworldPatches/HarmonyPatch_PawnRenderTree.cs
@@ -57,7 +57,7 @@ namespace Rimworld_Animations
if (pivot != Vector3.zero) matrix *= Matrix4x4.Translate(pivot);
if (quaternion != Quaternion.identity) matrix *= Matrix4x4.Rotate(quaternion);
if (scale != Vector3.one) matrix *= Matrix4x4.Scale(scale);
- if (pivot != Vector3.zero) matrix *= Matrix4x4.Translate(pivot).inverse;
+ if (pivot != Vector3.zero) matrix *= Matrix4x4.Translate(scale).inverse;
float num = node.Worker.AltitudeFor(node, parms);
if (num != 0f)
@@ -96,7 +96,7 @@ namespace Rimworld_Animations
if (pivot != Vector3.zero) matrix *= Matrix4x4.Translate(pivot);
if (canRotate && rotation != Quaternion.identity) matrix *= Matrix4x4.Rotate(rotation);
if (canScale && scale != Vector3.one) matrix *= Matrix4x4.Scale(scale);
- if (pivot != Vector3.zero) matrix *= Matrix4x4.Translate(pivot).inverse;
+ if (pivot != Vector3.zero) matrix *= Matrix4x4.Translate(scale).inverse;
}
float num = node.Worker.AltitudeFor(node, parms);
diff --git a/1.6/Source/Patches/RimworldPatches/HarmonyPatch_Thing.cs b/1.6/Source/Patches/RimworldPatches/HarmonyPatch_Thing.cs
new file mode 100644
index 0000000..ec738f7
--- /dev/null
+++ b/1.6/Source/Patches/RimworldPatches/HarmonyPatch_Thing.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using HarmonyLib;
+using RimWorld;
+using Verse;
+
+namespace Rimworld_Animations
+{
+ [HarmonyPatch(typeof(Thing), "DrawAt")]
+ public static class HarmonyPatch_Thing
+ {
+ /*
+ public static bool Prefix(Thing __instance)
+ {
+ CompThingAnimator thingAnimator = __instance.TryGetComp();
+ if (thingAnimator != null && thingAnimator.isAnimating)
+ {
+ thingAnimator.AnimateThing(__instance);
+ return false;
+
+ }
+
+ return true;
+
+ }
+
+
+ */
+ }
+}
diff --git a/1.6/Source/Settings/PawnScaledOffsets.cs b/1.6/Source/Settings/PawnScaledOffsets.cs
index 38577e4..8f280a1 100644
--- a/1.6/Source/Settings/PawnScaledOffsets.cs
+++ b/1.6/Source/Settings/PawnScaledOffsets.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -46,7 +46,7 @@ public class PawnScaledOffsets : IExposable
{
smallestSizeOffset = largestSizeOffset = Vector3.zero;
smallestSizeRotation = largestSizeRotation = 0;
- smallestSize = largestSize = -1; //back to uninitialized
+ smallestSize = largestSize = 1;
}
public void GetOffsets(Pawn pawn, out Vector3 offset, out int rotation)
diff --git a/1.6/Source/Settings/RJWAnimationSettings.cs b/1.6/Source/Settings/RJWAnimationSettings.cs
index 184bb7f..2c594bc 100644
--- a/1.6/Source/Settings/RJWAnimationSettings.cs
+++ b/1.6/Source/Settings/RJWAnimationSettings.cs
@@ -27,25 +27,21 @@ namespace Rimworld_Animations {
{
base.ExposeData();
-
- //some load defaults below differ from the field defaults. keys equal to their load default were never written,
- //so a missing key in an existing file usually means the player chose that value; keep those load defaults
- //and force-save these keys so the file is always explicit from now on
Scribe_Values.Look(ref playVoices, "RJWAnimations_PlayVoices", true);
Scribe_Values.Look(ref playSounds, "RJWAnimations_PlaySounds", true);
Scribe_Values.Look(ref playHumanlikeVoicesAsDefault, "RJWAnimations-playHumanlikeVoicesAsDefault", true);
- Scribe_Values.Look(ref maleSounds, "RJWAnimations-maleSounds", true, true);
- Scribe_Values.Look(ref femaleSounds, "RJWAnimations-femaleSounds", true, true);
+ Scribe_Values.Look(ref maleSounds, "RJWAnimations-maleSounds", true);
+ Scribe_Values.Look(ref femaleSounds, "RJWAnimations-femaleSounds", true);
Scribe_Values.Look(ref debugMode, "RJWAnimations-AnimsDebugMode", false);
- Scribe_Values.Look(ref offsetTab, "RJWAnimations-EnableOffsetTab", false, true);
- Scribe_Values.Look(ref hearts, "RJWAnimation-heartsOnLovin", false, true);
+ Scribe_Values.Look(ref offsetTab, "RJWAnimations-EnableOffsetTab", false);
+ Scribe_Values.Look(ref hearts, "RJWAnimation-heartsOnLovin");
Scribe_Values.Look(ref soundOverride, "RJWAnimations-rjwAnimSoundOverride", true);
Scribe_Values.Look(ref maleAnalCanBeFucked, "RJWAnimations-maleAnalCanBeFucked", true);
Scribe_Values.Look(ref floatRangeInRenderTreeMenu, "RJWAnimations-FloatRangeRenderMenu", 1f);
Scribe_Values.Look(ref soundVolume, "RJWAnimations-soundVolume", 1f);
Scribe_Values.Look(ref voicesVolume, "RJWAnimations-voicesVolume", 1f);
- Scribe_Values.Look(ref voicesFrequencyTicks, "RJWAnimations-voicesFrequencyTicks", 1f, true);
+ Scribe_Values.Look(ref voicesFrequencyTicks, "RJWAnimations-voicesFrequencyTicks", 1f);
Scribe_Collections.Look(ref offsets, "RJWAnimations-animationScaledOffsets", LookMode.Value, LookMode.Deep);
diff --git a/1.6/Source/Utilities/AnimationUtility.cs b/1.6/Source/Utilities/AnimationUtility.cs
index 5f3aa2d..dfaddc9 100644
--- a/1.6/Source/Utilities/AnimationUtility.cs
+++ b/1.6/Source/Utilities/AnimationUtility.cs
@@ -27,9 +27,7 @@ namespace Rimworld_Animations {
for (int i = 0; i < participants.Count; i++)
{
- //don't anchor a pawn to itself, or a dead pawn to its own corpse
- if ((anchor is Pawn pawn && pawn == participants[i])
- || (anchor is Corpse corpse && corpse.InnerPawn == participants[i]))
+ if (anchor is Pawn pawn && pawn == participants[i])
{
participants[i].TryGetComp().PlayGroupAnimation(groupAnimationDef, null, i, seed, participants);
@@ -40,27 +38,6 @@ namespace Rimworld_Animations {
participants[i].TryGetComp().PlayGroupAnimation(groupAnimationDef, animatorAnchor, i, seed, participants);
}
}
-
- DriveDeadParticipants(participants);
- }
-
- //corpses only TickRare, so their animators never advance on their own;
- //hand them to a living participant's animator to tick
- private static void DriveDeadParticipants(List participants)
- {
- Pawn driver = participants.FirstOrDefault(x => !x.Dead);
- if (driver == null) return;
-
- CompExtendedAnimator driverAnimator = driver.TryGetComp();
- if (driverAnimator == null) return;
-
- foreach (Pawn participant in participants)
- {
- if (participant.Dead)
- {
- driverAnimator.AddDrivenPawn(participant);
- }
- }
}
//startgroupanimation without anchor; just play where standing
@@ -72,8 +49,6 @@ namespace Rimworld_Animations {
{
participants[i].TryGetComp().PlayGroupAnimation(groupAnimationDef, i, seed, participants);
}
-
- DriveDeadParticipants(participants);
}
@@ -92,9 +67,8 @@ namespace Rimworld_Animations {
public static GroupAnimationDef FindGroupAnimation(List participants, out List pawnOrder)
{
- pawnOrder = null;
- if (participants.NullOrEmpty() || participants.Contains(null)) return null;
+
/* This method is fooken expensive
List<(GroupAnimationDef, List, int Priority)> potentialAnimations = new List<(GroupAnimationDef, List, int)>();
@@ -134,17 +108,13 @@ namespace Rimworld_Animations {
}
+ //Randomize the list,
+ potentialAnimations.OrderBy(_ => Rand.Int);
(GroupAnimationDef, List, int) selectedAnimation;
- //pick randomly, weighted by priority
- //negative priorities count as 0 so they don't log "Negative weight" errors
- if (!potentialAnimations.TryRandomElementByWeight(((GroupAnimationDef, List, int) x) => Math.Max(x.Item3, 0), out selectedAnimation)
- && potentialAnimations.Count > 0)
- {
- //every candidate has priority <= 0 (weak/fallback contexts); pick evenly between the best of them
- int bestPriority = potentialAnimations.Max(x => x.Item3);
- potentialAnimations.Where(x => x.Item3 == bestPriority).TryRandomElement(out 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;
diff --git a/About/About.xml b/About/About.xml
index 9c21172..a37de85 100644
--- a/About/About.xml
+++ b/About/About.xml
@@ -8,7 +8,7 @@
1.6
c0ffee.rimworld.animations
- 2.2.1
+ 2.2.0
UI/MainTab
diff --git a/Languages/ChineseSimplified/DefInjected/MainButtonDef/MainButtonDef.xml b/Languages/ChineseSimplified/DefInjected/MainButtonDef/MainButtonDef.xml
deleted file mode 100644
index da8bf6c..0000000
--- a/Languages/ChineseSimplified/DefInjected/MainButtonDef/MainButtonDef.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
- 动画管理器
- 编辑角色动画的偏移量。
-
\ No newline at end of file
diff --git a/Languages/ChineseSimplified/DefInjected/Rimworld_Animations.AnimationPropDef/AnimationPropDef_Cowgirl_Xray.xml b/Languages/ChineseSimplified/DefInjected/Rimworld_Animations.AnimationPropDef/AnimationPropDef_Cowgirl_Xray.xml
deleted file mode 100644
index e1991a7..0000000
--- a/Languages/ChineseSimplified/DefInjected/Rimworld_Animations.AnimationPropDef/AnimationPropDef_Cowgirl_Xray.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
- 女牛仔式-透视
-
\ No newline at end of file
diff --git a/Languages/ChineseSimplified/DefInjected/Rimworld_Animations.AnimationPropDef/AnimationPropDef_Xray_Inside.xml b/Languages/ChineseSimplified/DefInjected/Rimworld_Animations.AnimationPropDef/AnimationPropDef_Xray_Inside.xml
deleted file mode 100644
index 5904ef1..0000000
--- a/Languages/ChineseSimplified/DefInjected/Rimworld_Animations.AnimationPropDef/AnimationPropDef_Xray_Inside.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
- 体内透视
-
\ No newline at end of file
diff --git a/Languages/ChineseSimplified/DefInjected/Rimworld_Animations.AnimationPropDef/AnimationPropDef_Xray_Penis.xml b/Languages/ChineseSimplified/DefInjected/Rimworld_Animations.AnimationPropDef/AnimationPropDef_Xray_Penis.xml
deleted file mode 100644
index dfd781e..0000000
--- a/Languages/ChineseSimplified/DefInjected/Rimworld_Animations.AnimationPropDef/AnimationPropDef_Xray_Penis.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
- 阴茎透视
-
\ No newline at end of file
diff --git a/Languages/ChineseSimplified/DefInjected/Rimworld_Animations.AnimationPropDef/AnimationPropDef_Xray_Race.xml b/Languages/ChineseSimplified/DefInjected/Rimworld_Animations.AnimationPropDef/AnimationPropDef_Xray_Race.xml
deleted file mode 100644
index f6253ee..0000000
--- a/Languages/ChineseSimplified/DefInjected/Rimworld_Animations.AnimationPropDef/AnimationPropDef_Xray_Race.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
- 阴道透视
- 阴道透视
-
\ No newline at end of file
diff --git a/Languages/ChineseSimplified/Keyed/RJWAnimations-LanguageData.xml b/Languages/ChineseSimplified/Keyed/RJWAnimations-LanguageData.xml
index 3addfa5..1d72019 100644
--- a/Languages/ChineseSimplified/Keyed/RJWAnimations-LanguageData.xml
+++ b/Languages/ChineseSimplified/Keyed/RJWAnimations-LanguageData.xml
@@ -1,25 +1,28 @@
-
+
- RJW 动画设置
- 启用声音覆盖
- 控制生殖器旋转
- 启用高潮颤抖
- 启用强奸颤动
- 性爱时启用心形
- 播放非性行为的动画 (牵手、亲热)
- 启用动画管理器选项卡
- 颤抖/颤动强度 (默认为 2):
- 在动画期间播放语音
- 如果没有找到外星种族的声音,则默认播放人类的声音
- 调试模式
- 调整渲染树偏移表单的浮动范围:
- 为男性角色播放肛交动画
- 在动画期间播放声音
- 语音音量:
- 声音音量:
- 动画管理器
- 警告--一般情况下,你不想更改人类偏移值,只想更改外星种族偏移值或动物偏移值
- 将偏移值复制到剪贴板
- 将偏移值粘贴到 OffsetDef 中,或在 Discord 中共享
- 重置
+
+
+ RJW Animation Settings
+ 启用声音覆盖
+ 控制生殖器旋转
+ 启用高潮颤抖
+ 启用强奸颤动
+ 性爱时启用心形
+ 播放非性行为的动画 (牵手、亲热)
+ 启用动画管理器选项卡
+ 颤抖/颤动强度 (默认为 2):
+ 在动画期间播放语音
+ 如果没有找到外星种族的声音,则默认播放人类的声音
+ 调试模式
+ 调整渲染树偏移表单的浮动范围:
+
+
+
+ Animation Manager
+ 警告--一般情况下,你不想更改人类偏移值,只想更改外星种族偏移值或动物偏移值
+ 将偏移值复制到剪贴板
+ 将偏移值粘贴到 OffsetDef 中,或在 Discord 中共享
+
+
+
\ No newline at end of file
diff --git a/LoadFolders.xml b/LoadFolders.xml
index e41f229..b369dab 100644
--- a/LoadFolders.xml
+++ b/LoadFolders.xml
@@ -35,6 +35,8 @@
/
1.6
+ Patch_HumanoidAlienRaces/1.5
+ Patch_SexToysMasturbation/1.5
Patch_NoRimNudeWorld/1.5
Patch_NoRimNudeWorldZoo/1.5