code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using RimWorld;
using rjw.Modules.Interactions.Helpers;
using rjw.Modules.Interactions.Objects;
using UnityEngine;
using Verse;
using Verse.AI;
using rjw.Modules.Interactions.Enums;

namespace Rimworld_Animations {
    public static class AnimationUtility {
        /*
         Note: always make the list in this order:
             Female pawns, animal female pawns, male pawns, animal male pawns
        */
        public static AnimationDef tryFindAnimation(ref List<Pawn> participants, rjw.xxx.rjwSextype sexType = 0, rjw.SexProps sexProps = null) {

            InteractionWithExtension interaction = InteractionHelper.GetWithExtension(sexProps.dictionaryKey);

            if(interaction.HasInteractionTag(InteractionTag.Reverse))
            {
                Pawn buffer = participants[1];
                participants[1] = participants[0];
                participants[0] = buffer;
            }

            participants =
                participants.OrderBy(p => p.jobs.curDriver is rjw.JobDriver_SexBaseInitiator)
                .OrderBy(p => rjw.xxx.can_fuck(p))
                .ToList();

            List<Pawn> localParticipants = new List<Pawn>(participants);

            IEnumerable<AnimationDef> options = DefDatabase<AnimationDef>.AllDefs.Where((AnimationDef x) => {

                if (x.actors.Count != localParticipants.Count) {
                    return false;
                }
                for (int i = 0; i < x.actors.Count; i++) {

                    if (rjw.RJWPreferenceSettings.Malesex == rjw.RJWPreferenceSettings.AllowedSex.Nohomo) {
                        if (rjw.xxx.is_male(localParticipants[i]) && x.actors[i].isFucked) {
                            return false;
                        }
                }
				if (x.actors[i].requiredGender != null && !x.actors[i].requiredGender.Contains(localParticipants[i].gender.ToStringSafe<Gender>()))
				{
					if (AnimationSettings.debugMode)
					{
						Log.Message(string.Concat(new string[]
						{
							x.defName.ToStringSafe<string>(),
							" not selected -- ",
							localParticipants[i].def.defName.ToStringSafe<string>(),
							" ",
							localParticipants[i].Name.ToStringSafe<Name>(),
							" does not match required gender"
						}));
					}
					return false;
				}
                    if ((x.actors[i].blacklistedRaces != null) && x.actors[i].blacklistedRaces.Contains(localParticipants[i].def.defName)) {
                        if(AnimationSettings.debugMode)
                            Log.Message(x.defName.ToStringSafe() + " not selected -- " + localParticipants[i].def.defName.ToStringSafe() + " " + localParticipants[i].Name.ToStringSafe() + " is blacklisted");
                        return false;
                    }

                    if(x.actors[i].defNames.Contains("Human")) {
                        if (!rjw.xxx.is_human(localParticipants[i])) {
                            if (AnimationSettings.debugMode)
                                Log.Message(x.defName.ToStringSafe() + " not selected -- " + localParticipants[i].def.defName.ToStringSafe() + " " + localParticipants[i].Name.ToStringSafe() + " is not human");

                            return false;
                        }

                    }
                    else if (!x.actors[i].bodyDefTypes.Contains(localParticipants[i].RaceProps.body)) {

                        if (!x.actors[i].defNames.Contains(localParticipants[i].def.defName)) {

                            if (rjw.RJWSettings.DevMode) {
                                string animInfo = x.defName.ToStringSafe() + " not selected -- " + localParticipants[i].def.defName.ToStringSafe() + " " + localParticipants[i].Name.ToStringSafe() + " is not ";
                                foreach(String defname in x.actors[i].defNames) {
                                    animInfo += defname + ", ";
                                }
                                if (AnimationSettings.debugMode)
                                    Log.Message(animInfo);
                            }

                            return false;
                        }
                    }
                    //genitals checking

                    if(!GenitalCheckForPawn(x.actors[i].requiredGenitals, localParticipants[i], out string failReason)) {
                        Debug.Log("Didn't select " + x.defName + ", " + localParticipants[i].Name + " " + failReason);
                        return false;
                    }

                    //TESTING ANIMATIONS ONLY REMEMBER TO COMMENT OUT BEFORE PUSH
                    /*
                    if (x.defName != "Cunnilingus")
                        return false;
                    */

                    if (x.actors[i].isFucking && !rjw.xxx.can_fuck(localParticipants[i])) {
                        if (AnimationSettings.debugMode)
                            Log.Message(x.defName.ToStringSafe() + " not selected -- " + localParticipants[i].def.defName.ToStringSafe() + " " + localParticipants[i].Name.ToStringSafe() + " can't fuck");
                        return false;
                    }

                    if (x.actors[i].isFucked && !rjw.xxx.can_be_fucked(localParticipants[i])) {
                        if (AnimationSettings.debugMode)
                            Log.Message(x.defName.ToStringSafe() + " not selected -- " + localParticipants[i].def.defName.ToStringSafe() + " " + localParticipants[i].Name.ToStringSafe() + " can't be fucked");
                        return false;
                    }
                }
                return true;
            });
            List<AnimationDef> optionsWithInteractionType = options.ToList().FindAll(x => x.interactionDefTypes != null && x.interactionDefTypes.Contains(sexProps.sexType.ToStringSafe()));
            if (optionsWithInteractionType.Any()) {
                if (AnimationSettings.debugMode)
                    Log.Message("Selecting animation for interaction type " + sexProps.sexType.ToStringSafe() + "...");
                return optionsWithInteractionType.RandomElement();
            }
            List<AnimationDef> optionsWithSexType = options.ToList().FindAll(x => x.sexTypes != null && x.sexTypes.Contains(sexType));
            if (optionsWithSexType.Any()) {
                if (AnimationSettings.debugMode)
                    Log.Message("Selecting animation for rjwSexType " + sexType.ToStringSafe() + "...");
                return optionsWithSexType.RandomElement();
            }

            /*
            if(optionsWithInitiator.Any()) {
                if (AnimationSettings.debugMode)
                    Log.Message("Selecting animation for initiators...");
            }
            */

            if (options != null && options.Any()) {
                if (AnimationSettings.debugMode)
                    Log.Message("Randomly selecting animation...");
                return options.RandomElement();
            }
            else
                return null;
        }

        public static void RenderPawnHeadMeshInAnimation1(Mesh mesh, Vector3 loc, Quaternion quaternion, Material material, bool drawNow, Pawn pawn) {

            if (pawn == null || pawn.Map != Find.CurrentMap) {
                GenDraw.DrawMeshNowOrLater(mesh, loc, quaternion, material, drawNow);
                return;
            }

            CompBodyAnimator pawnAnimator = pawn.TryGetComp<CompBodyAnimator>();

            if (pawnAnimator == null || !pawnAnimator.isAnimating) {
                GenDraw.DrawMeshNowOrLater(mesh, loc, quaternion, material, drawNow);
            } else {
                Vector3 pawnHeadPosition = pawnAnimator.getPawnHeadPosition();
                pawnHeadPosition.y = loc.y;
                GenDraw.DrawMeshNowOrLater(MeshPool.humanlikeHeadSet.MeshAt(pawnAnimator.headFacing), pawnHeadPosition, Quaternion.AngleAxis(pawnAnimator.headAngle, Vector3.up), material, true);
            }
        }

        public static void AdjustHead(ref Quaternion quat, ref Rot4 bodyFacing, ref Vector3 pos, ref float angle, Pawn pawn, PawnRenderFlags flags)
        {
            if (flags.FlagSet(PawnRenderFlags.Portrait)) return;

            CompBodyAnimator anim = pawn.TryGetComp<CompBodyAnimator>();
            if (anim.isAnimating)
            {
                bodyFacing = anim.headFacing;
                angle = anim.headAngle;
                quat = Quaternion.AngleAxis(anim.headAngle, Vector3.up);
                pos = anim.getPawnHeadOffset();

            }
        }

        public static void RenderPawnHeadMeshInAnimation(Mesh mesh, Vector3 loc, Quaternion quaternion, Material material, bool portrait, Pawn pawn, float bodySizeFactor = 1) {

            if (pawn == null) {
                GenDraw.DrawMeshNowOrLater(mesh, loc, quaternion, material, portrait);
                return;
            }

            CompBodyAnimator pawnAnimator = pawn.TryGetComp<CompBodyAnimator>();

            if (pawnAnimator == null || !pawnAnimator.isAnimating || portrait) {
                GenDraw.DrawMeshNowOrLater(mesh, loc, quaternion, material, portrait);
            }
            else {
                Vector3 pawnHeadPosition = pawnAnimator.getPawnHeadPosition();
                pawnHeadPosition.x *= bodySizeFactor;
                pawnHeadPosition.x *= bodySizeFactor;
                pawnHeadPosition.y = loc.y;
                GenDraw.DrawMeshNowOrLater(mesh, pawnHeadPosition, Quaternion.AngleAxis(pawnAnimator.headAngle, Vector3.up), material, portrait);
            }
        }

        public static bool GenitalCheckForPawn(List<string> requiredGenitals, Pawn pawn, out string failReason) {

            failReason = null;
            if (requiredGenitals != null) {
                if (requiredGenitals.Contains("Vagina")) {

                    if (!rjw.Genital_Helper.has_vagina(pawn)) {
                        failReason = "missing vagina";
                        return false;
                    }

                }

                if (requiredGenitals.Contains("Penis")) {

                    if (!(rjw.Genital_Helper.has_multipenis(pawn) || rjw.Genital_Helper.has_penis_infertile(pawn) || rjw.Genital_Helper.has_penis_fertile(pawn) || rjw.Genital_Helper.has_ovipositorM(pawn) || rjw.Genital_Helper.has_ovipositorF(pawn))) {
                        failReason = "missing penis";
                        return false;
                    }

                }

                if (requiredGenitals.Contains("Mouth")) {

                    if (!rjw.Genital_Helper.has_mouth(pawn)) {
                        failReason = "missing mouth";
                        return false;
                    }

                }

                if (requiredGenitals.Contains("Anus")) {

                    if (!rjw.Genital_Helper.has_anus(pawn)) {
                        failReason = "missing anus";
                        return false;
                    }

                }

                if (requiredGenitals.Contains("Breasts")) {
                    if (!rjw.Genital_Helper.can_do_breastjob(pawn)) {
                        failReason = "missing breasts";
                        return false;
                    }
                }

                if (requiredGenitals.Contains("NoVagina")) {

                    if (rjw.Genital_Helper.has_vagina(pawn)) {
                        failReason = "has vagina";
                        return false;
                    }

                }

                if (requiredGenitals.Contains("NoPenis")) {

                    if ((rjw.Genital_Helper.has_multipenis(pawn) || rjw.Genital_Helper.has_penis_infertile(pawn) || rjw.Genital_Helper.has_penis_fertile(pawn))) {
                        failReason = "has penis";
                        return false;
                    }

                }

                if (requiredGenitals.Contains("NoMouth")) {

                    if (rjw.Genital_Helper.has_mouth(pawn)) {
                        failReason = "has mouth";
                        return false;
                    }

                }

                if (requiredGenitals.Contains("NoAnus")) {

                    if (rjw.Genital_Helper.has_anus(pawn)) {
                        failReason = "has anus";
                        return false;
                    }

                }

                if (requiredGenitals.Contains("NoBreasts")) {
                    if (rjw.Genital_Helper.can_do_breastjob(pawn)) {
                        failReason = "has breasts";
                        return false;
                    }
                }
            }

            return true;

        }

        public static Rot4 PawnHeadRotInAnimation(Pawn pawn, Rot4 regularPos)
        {
            Debug.Log("Test");

            if(pawn?.TryGetComp<CompBodyAnimator>() != null && pawn.TryGetComp<CompBodyAnimator>().isAnimating)
            {
                return pawn.TryGetComp<CompBodyAnimator>().headFacing;
            }

            return regularPos;
        }
    }
}


code:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using Verse;

namespace Rimworld_Animations
{
    public class PatchOperationAddOrReplace : PatchOperationPathed
    {

        protected string key;
        private XmlContainer value;

        protected override bool ApplyWorker(XmlDocument xml)
        {
            XmlNode valNode = value.node;
            bool result = false;
            IEnumerator enumerator = xml.SelectNodes(xpath).GetEnumerator();
            try
            {
                while (enumerator.MoveNext())
                {
                    object obj = enumerator.Current;
                    result = true;
                    XmlNode parentNode = obj as XmlNode;
                    XmlNode xmlNode = parentNode.SelectSingleNode(key);
                    if (xmlNode == null)
                    {
                        // Add - Add node if not existing
                        xmlNode = parentNode.OwnerDocument.CreateElement(key);
                        parentNode.AppendChild(xmlNode);
                    }
                    else
                    {
                        // Replace - Clear existing children
                        xmlNode.RemoveAll();
                    }
                    // (Re)add value
                    xmlNode.AppendChild(parentNode.OwnerDocument.ImportNode(valNode.FirstChild, true));
                }
            }
            finally
            {
                IDisposable disposable = enumerator as IDisposable;
                if (disposable != null)
                {
                    disposable.Dispose();
                }
            }
            return result;
        }

    }

}

license: unknown


code:
<?xml version="1.0" encoding="utf-8"?>

<ModMetaData>
	<name>Rimworld-Animations</name>
	<author>C0ffee</author>
  <url>https://gitgud.io/c0ffeeeeeeee/rimworld-animations</url>
	<supportedVersions>

1.1

1.2

1.3

1.4

	</supportedVersions>
	<packageId>c0ffee.rimworld.animations</packageId>
	<modDependencies>

			<packageId>brrainz.harmony</packageId>
			<displayName>Harmony</displayName>
			<steamWorkshopUrl>steam://url/CommunityFilePage/2009463077</steamWorkshopUrl>
			<downloadUrl>https://github.com/pardeike/HarmonyRimWorld/releases/latest</downloadUrl>

			<packageId>UnlimitedHugs.HugsLib</packageId>
			<displayName>HugsLib</displayName>
			<downloadUrl>https://github.com/UnlimitedHugs/RimworldHugsLib/releases/latest</downloadUrl>
			<steamWorkshopUrl>steam://url/CommunityFilePage/818773962</steamWorkshopUrl>

			<packageId>rim.job.world</packageId>
			<displayName>RimJobWorld</displayName>
			<downloadUrl>https://www.loverslab.com/topic/110270-mod-rimjobworld/</downloadUrl>

			<packageId>erdelf.HumanoidAlienRaces</packageId>
			<displayName>Humanoid Alien Races 2.0</displayName>
			<steamWorkshopUrl>https://steamcommunity.com/sharedfiles/filedetails/?id=839005762</steamWorkshopUrl>

	</modDependencies>
	<loadAfter>

UnlimitedHugs.HugsLib

brrainz.harmony

erdelf.humanoidalienraces

nals.facialanimation

com.yayo.yayoAni

	</loadAfter>
	<loadBefore>
	</loadBefore>
	<incompatibleWith>
	</incompatibleWith>
	<description>
    Rimworld Animations! Hurray!

    Questions or bugs?
    Chat with me on the forums: https://www.loverslab.com/topic/140386-rjw-animations/
    Or on the rjw discord: https://discord.gg/CXwHhv8

  </description>
</ModMetaData>


code:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Manifest>
  <identifier>Rimworld-Animations</identifier>
  <version>1.3.0</version>
</Manifest>


code:
<?xml version="1.0" encoding="utf-8"?>
<LanguageData>

  <OffsetManager.label>gerenciador de posições</OffsetManager.label>
  <OffsetManager.description>Controla as posições sexuais dos colonos.</OffsetManager.description>

</LanguageData>


code:
<?xml version="1.0" encoding="utf-8"?>
<LanguageData>

  <Dog_Doggystyle.label>estilo cachorrinho</Dog_Doggystyle.label>
  <Horse_Cowgirl.label>vaqueira</Horse_Cowgirl.label>

</LanguageData>


code:
<?xml version="1.0" encoding="utf-8"?>
<LanguageData>

  <Tribadism.label>tribadismo</Tribadism.label>
  <Cunnilingus.label>cunilíngua</Cunnilingus.label>

</LanguageData>


code:
<?xml version="1.0" encoding="utf-8"?>
<LanguageData>

  <Double_Penetration.label>dupla penetração</Double_Penetration.label>

</LanguageData>


code:
<?xml version="1.0" encoding="utf-8"?>
<LanguageData>

  <Doggystyle.label>estilo cachorrinho</Doggystyle.label>
  <Blowjob.label>boquete</Blowjob.label>
  <ReverseStandAndCarry.label>69</ReverseStandAndCarry.label>
  <Cowgirl.label>vaqueira</Cowgirl.label>

</LanguageData>


code:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<loadFolders>
	<v1.1>

/

1.1

	</v1.1>
	<v1.2>

/

1.2

Patch_HatsDisplaySelection/1.2

	</v1.2>
	<v1.3>

/

1.3

Patch_HatsDisplaySelection/1.2

Patch_SexToysMasturbation

Patch_SexToysMasturbation/1.3

	</v1.3>
	<v1.4>

/

1.4

Patch_HumanoidAlienRaces/1.4

Patch_HatsDisplaySelection/1.2

Patch_SexToysMasturbation

Patch_SexToysMasturbation/1.4

	</v1.4>

</loadFolders>


code:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProjectGuid>{C76F3790-9AC0-4827-ACD5-84174238954F}</ProjectGuid>
    <OutputType>Library</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>Patch_HumanoidAlienRaces</RootNamespace>
    <AssemblyName>Patch_HumanoidAlienRaces</AssemblyName>
    <TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
    <FileAlignment>512</FileAlignment>
    <Deterministic>true</Deterministic>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <DebugSymbols>false</DebugSymbols>
    <DebugType>none</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>1.4\Assemblies\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
    <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin\Release\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="0Harmony">
      <HintPath>..\..\..\..\..\workshop\content\294100\839005762\1.4\Assemblies\0Harmony.dll</HintPath>
      <Private>False</Private>
    </Reference>
    <Reference Include="AlienRace">
      <HintPath>..\..\..\..\..\workshop\content\294100\839005762\1.4\Assemblies\AlienRace.dll</HintPath>
      <Private>False</Private>
    </Reference>
    <Reference Include="Assembly-CSharp">
      <HintPath>..\..\..\RimWorldWin64_Data\Managed\Assembly-CSharp.dll</HintPath>
      <Private>False</Private>
    </Reference>
    <Reference Include="Rimworld-Animations">
      <HintPath>..\1.4\Assemblies\Rimworld-Animations.dll</HintPath>
      <Private>False</Private>
    </Reference>
    <Reference Include="RJW">
      <HintPath>..\..\rjw\1.4\Assemblies\RJW.dll</HintPath>
      <Private>False</Private>
    </Reference>
    <Reference Include="System" />
    <Reference Include="System.Core" />
    <Reference Include="System.Xml.Linq" />
    <Reference Include="System.Data.DataSetExtensions" />
    <Reference Include="Microsoft.CSharp" />
    <Reference Include="System.Data" />
    <Reference Include="System.Net.Http" />
    <Reference Include="System.Xml" />
    <Reference Include="UnityEngine">
      <HintPath>..\..\..\RimWorldWin64_Data\Managed\UnityEngine.dll</HintPath>
      <Private>False</Private>
    </Reference>
    <Reference Include="UnityEngine.CoreModule">
      <HintPath>..\..\..\RimWorldWin64_Data\Managed\UnityEngine.CoreModule.dll</HintPath>
      <Private>False</Private>
    </Reference>
  </ItemGroup>
  <ItemGroup>
    <Compile Include="Properties\AssemblyInfo.cs" />
    <Compile Include="Source\HarmonyPatch_AlienRace.cs" />
  </ItemGroup>
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>


code:
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Patch_HumanoidAlienRaces")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Patch_HumanoidAlienRaces")]
[assembly: AssemblyCopyright("Copyright ©  2022")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

// Setting ComVisible to false makes the types in this assembly not visible
// to COM components.  If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("c76f3790-9ac0-4827-acd5-84174238954f")]

// Version information for an assembly consists of the following four values:
//
//      Major Version
//      Minor Version
//      Build Number
//      Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]


code:
using HarmonyLib;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
using Verse;
using AlienRace;

namespace Rimworld_Animations {

	[StaticConstructorOnStartup]
	public static class HarmonyPatch_AlienRace
	{
		static HarmonyPatch_AlienRace()
		{
			(new Harmony("rjwanim")).Patch(AccessTools.Method(AccessTools.TypeByName("AlienRace.HarmonyPatches"), "DrawAddons"),
							prefix: new HarmonyMethod(AccessTools.Method(typeof(HarmonyPatch_AlienRace), "Prefix_AnimateHeadAddons")));
		}

		/* todo: replace jank prefix with this
		public static void Prefix_DrawAddonsFinalHook(ref Pawn pawn, ref AlienPartGenerator.BodyAddon addon, ref Rot4 rot, ref Graphic graphic, ref Vector3 offsetVector, ref float angle, ref Material mat)
        {
			CompBodyAnimator animator = pawn.TryGetComp<CompBodyAnimator>();

			if (animator == null || !animator.isAnimating)
            {
				return;
            }

			if(addon.alignWithHead || addon.drawnInBed)
            {
				rot = animator.headFacing;
				angle = animator.headAngle;
				offsetVector += animator.deltaPos + animator.bodyAngle * animator.headBob;

			}
			else
            {
				rot = animator.bodyFacing;
				angle = animator.bodyAngle;
				offsetVector += animator.deltaPos;
            }

        }
		*/
		public static bool Prefix_AnimateHeadAddons(PawnRenderFlags renderFlags, Vector3 vector, Vector3 headOffset, Pawn pawn, Quaternion quat, Rot4 rotation)
		{

			if (renderFlags.FlagSet(PawnRenderFlags.Portrait) || pawn.TryGetComp<CompBodyAnimator>() == null || !pawn.TryGetComp<CompBodyAnimator>().isAnimating) return true;
			if (!(pawn.def is ThingDef_AlienRace alienProps) || renderFlags.FlagSet(PawnRenderFlags.Invisible)) return false;

			List<AlienPartGenerator.BodyAddon> addons = alienProps.alienRace.generalSettings.alienPartGenerator.bodyAddons;
			AlienPartGenerator.AlienComp comp = pawn.GetComp<AlienPartGenerator.AlienComp>();
			CompBodyAnimator pawnAnimator = pawn.TryGetComp<CompBodyAnimator>();

			bool flag = renderFlags.FlagSet(PawnRenderFlags.Portrait);
			bool flag2 = renderFlags.FlagSet(PawnRenderFlags.Invisible);

			for (int i = 0; i < addons.Count; i++)
			{
				AlienPartGenerator.BodyAddon ba = addons[index: i];

				if (!ba.CanDrawAddon(pawn: pawn)) continue;

				bool forceDrawForBody = false;
				if (alienProps.defName.Contains("Orassan") && ba.path.ToLower().Contains("tail"))
                {
					forceDrawForBody = true;
                }
				AlienPartGenerator.RotationOffset offset = ba.defaultOffsets.GetOffset((ba.drawnInBed && !forceDrawForBody) || ba.alignWithHead ? pawnAnimator.headFacing : pawnAnimator.bodyFacing);
				Vector3 a = (offset != null) ? offset.GetOffset(renderFlags.FlagSet(PawnRenderFlags.Portrait), pawn.story.bodyType, pawn.story.headType) : Vector3.zero;
				AlienPartGenerator.RotationOffset offset2 = ba.offsets.GetOffset((ba.drawnInBed && !forceDrawForBody) || ba.alignWithHead ? pawnAnimator.headFacing : pawnAnimator.bodyFacing);
				Vector3 vector2 = a + ((offset2 != null) ? offset2.GetOffset(renderFlags.FlagSet(PawnRenderFlags.Portrait), pawn.story.bodyType, pawn.story.headType) : Vector3.zero);
				vector2.y = (ba.inFrontOfBody ? (0.3f + vector2.y) : (-0.3f - vector2.y));
				float num = ba.angle;
				if (((ba.drawnInBed && !forceDrawForBody) || ba.alignWithHead ? pawnAnimator.headFacing : pawnAnimator.bodyFacing) == Rot4.North)
				{
					if (ba.layerInvert)
					{
						vector2.y = 0f - vector2.y;
					}
					num = 0f;
				}
				if (((ba.drawnInBed && !forceDrawForBody) || ba.alignWithHead ? pawnAnimator.headFacing : pawnAnimator.bodyFacing) == Rot4.East)
				{
					num = 0f - num;
					vector2.x = 0f - vector2.x;
				}
				Graphic addonGraphic = comp.addonGraphics[i];

				addonGraphic.drawSize = ((flag && ba.drawSizePortrait != Vector2.zero) ? ba.drawSizePortrait : ba.drawSize) * (ba.scaleWithPawnDrawsize ? (ba.alignWithHead ? ((flag ? comp.customPortraitHeadDrawSize : comp.customHeadDrawSize) * (ModsConfig.BiotechActive ? (pawn.ageTracker.CurLifeStage.headSizeFactor ?? 1.5f) : 1.5f)) : ((flag ? comp.customPortraitDrawSize : comp.customDrawSize) * (ModsConfig.BiotechActive ? pawn.ageTracker.CurLifeStage.bodySizeFactor : 1f) * 1.5f)) : (Vector2.one * 1.5f));

				if ((ba.drawnInBed && !forceDrawForBody) || ba.alignWithHead)
				{

					Quaternion addonRotation = Quaternion.AngleAxis(pawnAnimator.headAngle < 0 ? 360 - (360 % pawnAnimator.headAngle) : pawnAnimator.headAngle, Vector3.up);

					GenDraw.DrawMeshNowOrLater(mesh: addonGraphic.MeshAt(rot: pawnAnimator.headFacing), loc: vector + (ba.alignWithHead ? headOffset : headOffset - addonRotation * pawn.Drawer.renderer.BaseHeadOffsetAt(pawnAnimator.headFacing)) + vector2.RotatedBy(angle: Mathf.Acos(f: Quaternion.Dot(a: Quaternion.identity, b: addonRotation)) * 2f * 57.29578f),
					quat: Quaternion.AngleAxis(angle: num, axis: Vector3.up) * addonRotation, mat: addonGraphic.MatAt(rot: pawnAnimator.headFacing), renderFlags.FlagSet(PawnRenderFlags.DrawNow));

				}

				else
				{
					Quaternion addonRotation = Quaternion.AngleAxis(pawnAnimator.bodyAngle, Vector3.up);
					if (AnimationSettings.controlGenitalRotation && pawnAnimator.controlGenitalAngle && ba?.hediffGraphics != null && ba.hediffGraphics.Count != 0 && ba.hediffGraphics[0]?.path != null && (ba.hediffGraphics[0].path.Contains("Penis") || ba.hediffGraphics[0].path.Contains("penis")))
					{
						GenDraw.DrawMeshNowOrLater(mesh: addonGraphic.MeshAt(rot: rotation), loc: vector + (ba.alignWithHead ? headOffset : Vector3.zero) + vector2.RotatedBy(angle: Mathf.Acos(f: Quaternion.Dot(a: Quaternion.identity, b: addonRotation)) * 2f * 57.29578f),
						quat: Quaternion.AngleAxis(angle: pawnAnimator.genitalAngle, axis: Vector3.up), mat: addonGraphic.MatAt(rot: rotation), renderFlags.FlagSet(PawnRenderFlags.DrawNow));
					}

					else
                    {
						GenDraw.DrawMeshNowOrLater(mesh: addonGraphic.MeshAt(rot: rotation), loc: vector + (ba.alignWithHead ? headOffset : Vector3.zero) + vector2.RotatedBy(angle: Mathf.Acos(f: Quaternion.Dot(a: Quaternion.identity, b: addonRotation)) * 2f * 57.29578f),
						quat: Quaternion.AngleAxis(angle: num, axis: Vector3.up) * addonRotation, mat: addonGraphic.MatAt(rot: rotation), renderFlags.FlagSet(PawnRenderFlags.DrawNow));
					}

				}

			}

			return false;
		}
	}

	[HarmonyPatch(typeof(PawnGraphicSet), "ResolveApparelGraphics")]
	public static class HarmonyPatch_ResolveApparelGraphics
	{
		public static bool Prefix(ref Pawn ___pawn)
		{

			if (___pawn.TryGetComp<CompBodyAnimator>() != null && ___pawn.TryGetComp<CompBodyAnimator>().isAnimating)
			{
				return false;
			}
			return true;
		}
	}

	/*

    [HarmonyPatch(typeof(AlienRace.HarmonyPatches), "DrawAddons")]
    public static class HarmonyPatch_AlienRace {

		public static void RenderHeadAddonInAnimation(Mesh mesh, Vector3 loc, Quaternion quat, Material mat, bool drawNow, Graphic graphic, AlienPartGenerator.BodyAddon bodyAddon, Vector3 v, Vector3 headOffset, Pawn pawn, PawnRenderFlags renderFlags, Vector3 vector, Rot4 rotation)
        {

			CompBodyAnimator pawnAnimator = pawn.TryGetComp<CompBodyAnimator>();
			AlienPartGenerator.AlienComp comp = pawn.GetComp<AlienPartGenerator.AlienComp>();

			if (pawnAnimator != null && pawnAnimator.isAnimating)
            {

				if((bodyAddon.drawnInBed || bodyAddon.alignWithHead))
                {

					AlienPartGenerator.RotationOffset offset = bodyAddon.defaultOffsets.GetOffset(rotation);
					Vector3 a = (offset != null) ? offset.GetOffset(renderFlags.FlagSet(PawnRenderFlags.Portrait), pawn.story.bodyType, comp.crownType) : Vector3.zero;
					AlienPartGenerator.RotationOffset offset2 = bodyAddon.offsets.GetOffset(rotation);
					Vector3 vector2 = a + ((offset2 != null) ? offset2.GetOffset(renderFlags.FlagSet(PawnRenderFlags.Portrait), pawn.story.bodyType, comp.crownType) : Vector3.zero);
					vector2.y = (bodyAddon.inFrontOfBody ? (0.3f + vector2.y) : (-0.3f - vector2.y));
					float num = bodyAddon.angle;
					if (rotation == Rot4.North)
					{
						if (bodyAddon.layerInvert)
						{
							vector2.y = -vector2.y;
						}
						num = 0f;
					}
					if (rotation == Rot4.East)
					{
						num = -num;
						vector2.x = -vector2.x;
					}

					vector = vector + Quaternion.AngleAxis(pawnAnimator.bodyAngle, Vector3.up) * pawn.Drawer.renderer.BaseHeadOffsetAt(pawnAnimator.bodyFacing) - pawnAnimator.getPawnHeadOffset(); //convert vector into pseudo body pos for head
					quat = Quaternion.AngleAxis(pawnAnimator.headAngle, Vector3.up);
					loc = vector + (bodyAddon.alignWithHead ? headOffset : Vector3.zero) + vector2.RotatedBy(Mathf.Acos(Quaternion.Dot(Quaternion.identity, quat)) * 2f * 57.29578f);
					mat = graphic.MatAt(rot: pawnAnimator.headFacing);
				}
				else
                {

					AlienPartGenerator.RotationOffset offset = bodyAddon.defaultOffsets.GetOffset(rotation);
					Vector3 a = (offset != null) ? offset.GetOffset(renderFlags.FlagSet(PawnRenderFlags.Portrait), pawn.story.bodyType, comp.crownType) : Vector3.zero;
					AlienPartGenerator.RotationOffset offset2 = bodyAddon.offsets.GetOffset(rotation);
					Vector3 vector2 = a + ((offset2 != null) ? offset2.GetOffset(renderFlags.FlagSet(PawnRenderFlags.Portrait), pawn.story.bodyType, comp.crownType) : Vector3.zero);
					vector2.y = (bodyAddon.inFrontOfBody ? (0.3f + vector2.y) : (-0.3f - vector2.y));
					float num = bodyAddon.angle;
					if (rotation == Rot4.North)
					{
						if (bodyAddon.layerInvert)
						{
							vector2.y = -vector2.y;
						}
						num = 0f;
					}
					if (rotation == Rot4.East)
					{
						num = -num;
						vector2.x = -vector2.x;
					}
					quat = Quaternion.AngleAxis(pawnAnimator.bodyAngle, Vector3.up);
					loc = vector + (bodyAddon.alignWithHead ? headOffset : Vector3.zero) + vector2.RotatedBy(Mathf.Acos(Quaternion.Dot(Quaternion.identity, quat)) * 2f * 57.29578f);

				}

			}
			GenDraw.DrawMeshNowOrLater(mesh, loc, quat, mat, drawNow);

			/*
			if (pawnAnimator != null && !renderFlags.FlagSet(PawnRenderFlags.Portrait) && pawnAnimator.isAnimating && (bodyAddon.drawnInBed || bodyAddon.alignWithHead))
            {

				if ((pawn.def as ThingDef_AlienRace).defName == "Alien_Orassan")
                {
					orassan = true;

					if(bodyAddon.path.Contains("closed"))
                    {
						return;
                    }

					if (bodyAddon.bodyPart.Contains("ear"))

					{
						orassan = true;

						orassanv = new Vector3(0, 0, 0.23f);
						if (pawnAnimator.headFacing == Rot4.North)
						{
							orassanv.z -= 0.1f;
							orassanv.y += 1f;

							if(bodyAddon.bodyPart.Contains("left"))
                            {
								orassanv.x += 0.03f;
                            } else
                            {
								orassanv.x -= 0.03f;
							}

						}
						else if (pawnAnimator.headFacing == Rot4.East)
						{
							orassanv.x -= 0.1f;
						}
						else if (pawnAnimator.headFacing == Rot4.West)
						{
							orassanv.x = 0.1f;
						}
						else
                        {
							orassanv.z -= 0.1f;
							orassanv.y += 1f;

							if (bodyAddon.bodyPart.Contains("right"))
							{
								orassanv.x += 0.05f;
							}
							else
							{
								orassanv.x -= 0.05f;
							}
						}
						orassanv = orassanv.RotatedBy(pawnAnimator.headAngle);
					}
				}

			GenDraw.DrawMeshNowOrLater(mesh: graphic.MeshAt(rot: headRotInAnimation), loc: loc + orassanv + (bodyAddon.alignWithHead ? headOffset : Vector3.zero),// + v.RotatedBy(Mathf.Acos(Quaternion.Dot(Quaternion.identity, quat)) * 2f * 57.29578f),
					quat: Quaternion.AngleAxis(angle: num, axis: Vector3.up) * headQuatInAnimation, mat: graphic.MatAt(rot: pawnAnimator.headFacing), drawNow: drawNow);;
			}

			else
            {

			}

		}

		public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
        {
			List<CodeInstruction> ins = instructions.ToList();
			for (int i = 0; i < ins.Count; i++)
            {

				Type[] type = new Type[] { typeof(Mesh), typeof(Vector3), typeof(Quaternion), typeof(Material), typeof(bool) };

				if (ins[i].OperandIs(AccessTools.Method(typeof(GenDraw), "DrawMeshNowOrLater", type)))
                {

					yield return new CodeInstruction(OpCodes.Ldloc, (object)7); //graphic
					yield return new CodeInstruction(OpCodes.Ldloc, (object)4); //bodyAddon
					yield return new CodeInstruction(OpCodes.Ldloc, (object)5); //offsetVector/AddonOffset (v)
					yield return new CodeInstruction(OpCodes.Ldarg, (object)2); //headOffset
					yield return new CodeInstruction(OpCodes.Ldarg, (object)3); //pawn
					yield return new CodeInstruction(OpCodes.Ldarg, (object)0); //renderflags
					yield return new CodeInstruction(OpCodes.Ldarg, (object)1); //vector
					yield return new CodeInstruction(OpCodes.Ldarg, (object)5); //rotation

					yield return new CodeInstruction(OpCodes.Call, AccessTools.DeclaredMethod(typeof(HarmonyPatch_AlienRace), "RenderHeadAddonInAnimation"));

                }

				else
                {
					yield return ins[i];
				}
            }
        }

		public static bool Prefix(PawnRenderFlags renderFlags, ref Vector3 vector, ref Vector3 headOffset, Pawn pawn, ref Quaternion quat, ref Rot4 rotation)
		{
			if(pawn == null)
            {
				return true;
			}

			CompBodyAnimator anim = pawn.TryGetComp<CompBodyAnimator>();

			if(anim == null)
            {
				return true;
            }

			if (anim != null && !renderFlags.FlagSet(PawnRenderFlags.Portrait) && anim.isAnimating)
			{
				//quat = Quaternion.AngleAxis(anim.bodyAngle, Vector3.up);
			}

			return true;

		}
	}

	*/

}


code:
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
	<Patch_SexToysMasturbation.SexToyAnimationDef>
		<defName>Masturbation_DildoVaginal</defName>
		dildo masturbation
		<requiredBodyPart>vagina</requiredBodyPart>
		<sounds>true</sounds>
		<sexTypes>

Masturbation

		</sexTypes>
		<actors>

				<defNames>

Human

				</defNames>
				<isFucked>true</isFucked>

		</actors>

		<animationStages>

				<stageName>Masturbating</stageName>
				<isLooping>true</isLooping>
				<playTimeTicks>917</playTimeTicks>
				<stageIndex>0</stageIndex>
				<animationClips>

						<layer>LayingPawn</layer>
						<keyframes>

								<tickDuration>40</tickDuration>
								<bodyAngle>73.01611</bodyAngle>
								<headAngle>40.0739746</headAngle>
								<genitalAngle>0</genitalAngle>
								<bodyOffsetZ>0.054543376</bodyOffsetZ>
								<bodyOffsetX>0.112624526</bodyOffsetX>
								<headBob>0</headBob>
								<bodyFacing>3</bodyFacing>
								<headFacing>3</headFacing>

								<soundEffect>Slimy</soundEffect>
								<tickDuration>30</tickDuration>
								<bodyAngle>76.4867554</bodyAngle>
								<headAngle>45.3887634</headAngle>
								<genitalAngle>0</genitalAngle>
								<bodyOffsetZ>0.0506898165</bodyOffsetZ>
								<bodyOffsetX>0.08564949</bodyOffsetX>
								<headBob>0</headBob>
								<bodyFacing>3</bodyFacing>
								<headFacing>3</headFacing>

								<tickDuration>30</tickDuration>
								<bodyAngle>78.22131</bodyAngle>
								<headAngle>48.0072327</headAngle>
								<genitalAngle>0</genitalAngle>
								<bodyOffsetZ>0.039129138</bodyOffsetZ>
								<bodyOffsetX>0.07794231</bodyOffsetX>
								<headBob>0</headBob>
								<bodyFacing>3</bodyFacing>
								<headFacing>3</headFacing>

								<tickDuration>30</tickDuration>
								<bodyAngle>76.4867554</bodyAngle>
								<headAngle>45.3887634</headAngle>
								<genitalAngle>0</genitalAngle>
								<bodyOffsetZ>0.0506898165</bodyOffsetZ>
								<bodyOffsetX>0.08564949</bodyOffsetX>
								<headBob>0</headBob>
								<bodyFacing>3</bodyFacing>
								<headFacing>3</headFacing>

								<tickDuration>1</tickDuration>
								<bodyAngle>73.01611</bodyAngle>
								<headAngle>40.0739746</headAngle>
								<genitalAngle>0</genitalAngle>
								<bodyOffsetZ>0.054543376</bodyOffsetZ>
								<bodyOffsetX>0.112624526</bodyOffsetX>
								<headBob>0</headBob>
								<bodyFacing>3</bodyFacing>
								<headFacing>3</headFacing>

						</keyframes>

						<keyframes>

								<tickDuration>40</tickDuration>
								<positionX>-0.359264076</positionX>
								<positionZ>-0.00901746</positionZ>
								<rotation>114.011215</rotation>

								<tickDuration>30</tickDuration>
								<positionX>-0.2783391</positionX>
								<positionZ>-0.0514066666</positionZ>
								<rotation>81.16443</rotation>

								<tickDuration>30</tickDuration>
								<positionX>-0.1704393</positionX>
								<positionZ>-0.0668209046</positionZ>
								<rotation>72.8611145</rotation>

								<tickDuration>30</tickDuration>
								<positionX>-0.2783391</positionX>
								<positionZ>-0.0514066666</positionZ>
								<rotation>81.16443</rotation>

								<tickDuration>1</tickDuration>
								<positionX>-0.359264076</positionX>
								<positionZ>-0.00901746</positionZ>
								<rotation>114.011215</rotation>

						</keyframes>

				</animationClips>

				<stageName>GettingIntoPosition</stageName>
				<isLooping>false</isLooping>
				<stageIndex>0</stageIndex>
				<animationClips>

						<layer>LayingPawn</layer>
						<keyframes>

								<tickDuration>50</tickDuration>
								<bodyAngle>73.01611</bodyAngle>
								<headAngle>40.0739746</headAngle>
								<genitalAngle>0</genitalAngle>
								<bodyOffsetZ>0.054543376</bodyOffsetZ>
								<bodyOffsetX>0.112624526</bodyOffsetX>
								<headBob>0</headBob>
								<bodyFacing>3</bodyFacing>
								<headFacing>3</headFacing>

								<soundEffect>Slimy</soundEffect>
								<tickDuration>1</tickDuration>
								<bodyAngle>81.65927</bodyAngle>
								<headAngle>58.8843079</headAngle>
								<genitalAngle>0</genitalAngle>
								<bodyOffsetZ>0.03912908</bodyOffsetZ>
								<bodyOffsetX>0.08950315</bodyOffsetX>
								<headBob>0</headBob>
								<bodyFacing>3</bodyFacing>
								<headFacing>3</headFacing>

						</keyframes>

						<keyframes>

								<tickDuration>50</tickDuration>
								<positionX>-0.359264076</positionX>
								<positionZ>-0.00901746</positionZ>
								<rotation>114.011215</rotation>

								<tickDuration>1</tickDuration>
								<positionX>-0.2899</positionX>
								<positionZ>-0.0282852575</positionZ>
								<rotation>98.13748</rotation>

						</keyframes>

				</animationClips>

				<stageName>FastMasturbation</stageName>
				<isLooping>true</isLooping>
				<stageIndex>0</stageIndex>
				<playTimeTicks>1610</playTimeTicks>
				<animationClips>

						<layer>LayingPawn</layer>
						<keyframes>

								<tickDuration>20</tickDuration>
								<bodyAngle>81.65927</bodyAngle>
								<headAngle>58.8843079</headAngle>
								<genitalAngle>0</genitalAngle>
								<bodyOffsetZ>0.03912908</bodyOffsetZ>
								<bodyOffsetX>0.08950315</bodyOffsetX>
								<headBob>0</headBob>
								<bodyFacing>3</bodyFacing>
								<headFacing>3</headFacing>

								<soundEffect>Slimy</soundEffect>
								<tickDuration>25</tickDuration>
								<bodyAngle>85.17255</bodyAngle>
								<headAngle>58.0615845</headAngle>
								<genitalAngle>0</genitalAngle>
								<bodyOffsetZ>0.03527552</bodyOffsetZ>
								<bodyOffsetX>0.0471138731</bodyOffsetX>
								<headBob>0</headBob>
								<bodyFacing>3</bodyFacing>
								<headFacing>3</headFacing>

								<tickDuration>1</tickDuration>
								<bodyAngle>81.65927</bodyAngle>
								<headAngle>58.8843079</headAngle>
								<genitalAngle>0</genitalAngle>
								<bodyOffsetZ>0.03912908</bodyOffsetZ>
								<bodyOffsetX>0.08950315</bodyOffsetX>
								<headBob>0</headBob>
								<bodyFacing>3</bodyFacing>
								<headFacing>3</headFacing>

						</keyframes>

						<keyframes>

								<tickDuration>25</tickDuration>
								<positionX>-0.2899</positionX>
								<positionZ>-0.0282852575</positionZ>
								<rotation>98.13748</rotation>

								<tickDuration>20</tickDuration>
								<positionX>-0.178146541</positionX>
								<positionZ>-0.01672452</positionZ>
								<rotation>96.95889</rotation>

								<tickDuration>1</tickDuration>
								<positionX>-0.2899</positionX>
								<positionZ>-0.0282852575</positionZ>
								<rotation>98.13748</rotation>

						</keyframes>

				</animationClips>

				<stageName>VeryFastMasturbation</stageName>
				<isLooping>true</isLooping>
				<stageIndex>0</stageIndex>
				<playTimeTicks>225</playTimeTicks>
				<animationClips>

						<layer>LayingPawn</layer>
						<keyframes>

								<tickDuration>6</tickDuration>
								<bodyAngle>81.65927</bodyAngle>
								<headAngle>58.8843079</headAngle>
								<genitalAngle>0</genitalAngle>
								<bodyOffsetZ>0.03912908</bodyOffsetZ>
								<bodyOffsetX>0.08950315</bodyOffsetX>
								<headBob>0</headBob>
								<bodyFacing>3</bodyFacing>
								<headFacing>3</headFacing>

								<soundEffect>Slimy</soundEffect>
								<tickDuration>8</tickDuration>
								<bodyAngle>85.17255</bodyAngle>
								<headAngle>58.0615845</headAngle>
								<genitalAngle>0</genitalAngle>
								<bodyOffsetZ>0.03527552</bodyOffsetZ>
								<bodyOffsetX>0.0471138731</bodyOffsetX>
								<headBob>0</headBob>
								<bodyFacing>3</bodyFacing>
								<headFacing>3</headFacing>

								<tickDuration>1</tickDuration>
								<bodyAngle>81.65927</bodyAngle>
								<headAngle>58.8843079</headAngle>
								<genitalAngle>0</genitalAngle>
								<bodyOffsetZ>0.03912908</bodyOffsetZ>
								<bodyOffsetX>0.08950315</bodyOffsetX>
								<headBob>0</headBob>
								<bodyFacing>3</bodyFacing>
								<headFacing>3</headFacing>

						</keyframes>

						<keyframes>

								<tickDuration>6</tickDuration>
								<positionX>-0.2899</positionX>
								<positionZ>-0.0282852575</positionZ>
								<rotation>98.13748</rotation>

								<tickDuration>8</tickDuration>
								<positionX>-0.178146541</positionX>
								<positionZ>-0.01672452</positionZ>
								<rotation>96.95889</rotation>

								<tickDuration>1</tickDuration>
								<positionX>-0.2899</positionX>
								<positionZ>-0.0282852575</positionZ>
								<rotation>98.13748</rotation>

						</keyframes>

				</animationClips>

				<stageName>Orgasm</stageName>
				<isLooping>false</isLooping>
				<stageIndex>0</stageIndex>
				<animationClips>

						<layer>LayingPawn</layer>
						<keyframes>

								<soundEffect>Slimy</soundEffect>
								<tickDuration>6</tickDuration>
								<bodyAngle>81.65927</bodyAngle>
								<headAngle>58.8843079</headAngle>
								<genitalAngle>0</genitalAngle>
								<bodyOffsetZ>0.03912908</bodyOffsetZ>
								<bodyOffsetX>0.08950315</bodyOffsetX>
								<headBob>0</headBob>
								<bodyFacing>3</bodyFacing>
								<headFacing>3</headFacing>

								<quiver>True</quiver>
								<soundEffect>Cum</soundEffect>
								<tickDuration>80</tickDuration>
								<bodyAngle>85.17255</bodyAngle>
								<headAngle>58.0615845</headAngle>
								<genitalAngle>0</genitalAngle>
								<bodyOffsetZ>0.03527552</bodyOffsetZ>
								<bodyOffsetX>0.0471138731</bodyOffsetX>
								<headBob>0</headBob>
								<bodyFacing>3</bodyFacing>
								<headFacing>3</headFacing>

								<quiver>True</quiver>
								<soundEffect>Cum</soundEffect>
								<tickDuration>90</tickDuration>
								<bodyAngle>92.15109</bodyAngle>
								<headAngle>96.34238</headAngle>
								<genitalAngle>0</genitalAngle>
								<bodyOffsetZ>0.0237147212</bodyOffsetZ>
								<bodyOffsetX>0.0432603136</bodyOffsetX>
								<headBob>0</headBob>
								<bodyFacing>3</bodyFacing>
								<headFacing>3</headFacing>

								<quiver>True</quiver>
								<soundEffect>Cum</soundEffect>
								<tickDuration>70</tickDuration>
								<bodyAngle>92.15109</bodyAngle>
								<headAngle>96.34238</headAngle>
								<genitalAngle>0</genitalAngle>
								<bodyOffsetZ>0.0237147212</bodyOffsetZ>
								<bodyOffsetX>0.0432603136</bodyOffsetX>
								<headBob>0</headBob>
								<bodyFacing>3</bodyFacing>
								<headFacing>3</headFacing>

								<tickDuration>70</tickDuration>
								<bodyAngle>92.15109</bodyAngle>
								<headAngle>96.34238</headAngle>
								<genitalAngle>0</genitalAngle>
								<bodyOffsetZ>0.0237147212</bodyOffsetZ>
								<bodyOffsetX>0.0432603136</bodyOffsetX>
								<headBob>0</headBob>
								<bodyFacing>3</bodyFacing>
								<headFacing>3</headFacing>

								<tickDuration>1</tickDuration>
								<bodyAngle>81.65927</bodyAngle>
								<headAngle>58.8843079</headAngle>
								<genitalAngle>0</genitalAngle>
								<bodyOffsetZ>0.03912908</bodyOffsetZ>
								<bodyOffsetX>0.08950315</bodyOffsetX>
								<headBob>0</headBob>
								<bodyFacing>3</bodyFacing>
								<headFacing>3</headFacing>

						</keyframes>

						<keyframes>

								<tickDuration>6</tickDuration>
								<positionX>-0.2899</positionX>
								<positionZ>-0.0282852575</positionZ>
								<rotation>98.13748</rotation>

								<tickDuration>80</tickDuration>
								<positionX>-0.178146541</positionX>
								<positionZ>-0.01672452</positionZ>
								<rotation>96.95889</rotation>

								<tickDuration>90</tickDuration>
								<positionX>-0.178146541</positionX>
								<positionZ>-0.01672452</positionZ>
								<rotation>96.95889</rotation>

								<tickDuration>70</tickDuration>
								<positionX>-0.178146541</positionX>
								<positionZ>-0.01672452</positionZ>
								<rotation>96.95889</rotation>

								<tickDuration>70</tickDuration>
								<positionX>-0.178146541</positionX>
								<positionZ>-0.01672452</positionZ>
								<rotation>96.95889</rotation>

								<tickDuration>1</tickDuration>
								<positionX>-0.2899</positionX>
								<positionZ>-0.0282852575</positionZ>
								<rotation>98.13748</rotation>

						</keyframes>

				</animationClips>

		</animationStages>
	</Patch_SexToysMasturbation.SexToyAnimationDef>
</Defs>


code:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProjectGuid>{87763712-0536-4D5F-9EAA-520F15D4F84E}</ProjectGuid>
    <OutputType>Library</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>Patch_SexToysMasturbation</RootNamespace>
    <AssemblyName>Patch_SexToysMasturbation</AssemblyName>
    <TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
    <FileAlignment>512</FileAlignment>
    <Deterministic>true</Deterministic>
    <TargetFrameworkProfile />
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <DebugSymbols>false</DebugSymbols>
    <DebugType>none</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>1.4\Assemblies\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
    <GenerateSerializationAssemblies>Auto</GenerateSerializationAssemblies>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin\Release\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="0Harmony">
      <HintPath>..\..\..\..\..\workshop\content\294100\1127530465\1.3\Assemblies\0Harmony.dll</HintPath>
      <Private>False</Private>
    </Reference>
    <Reference Include="Assembly-CSharp">
      <HintPath>..\..\..\RimWorldWin64_Data\Managed\Assembly-CSharp.dll</HintPath>
      <Private>False</Private>
    </Reference>
    <Reference Include="Rimworld-Animations, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
      <SpecificVersion>False</SpecificVersion>
      <HintPath>..\1.3\Assemblies\Rimworld-Animations.dll</HintPath>
      <Private>False</Private>
    </Reference>
    <Reference Include="RJW">
      <HintPath>..\..\rjw\1.4\Assemblies\RJW.dll</HintPath>
      <Private>False</Private>
    </Reference>
    <Reference Include="RJW-ToysAndMasturbation">
      <HintPath>..\..\rjw-toys-and-masturbation\Assemblies\RJW-ToysAndMasturbation.dll</HintPath>
      <Private>False</Private>
    </Reference>
    <Reference Include="System" />
    <Reference Include="System.Core" />
    <Reference Include="System.Xml.Linq" />
    <Reference Include="System.Data.DataSetExtensions" />
    <Reference Include="Microsoft.CSharp" />
    <Reference Include="System.Data" />
    <Reference Include="System.Net.Http" />
    <Reference Include="System.Xml" />
    <Reference Include="UnityEngine">
      <HintPath>..\..\..\RimWorldWin64_Data\Managed\UnityEngine.dll</HintPath>
      <Private>False</Private>
    </Reference>
    <Reference Include="UnityEngine.CoreModule">
      <HintPath>..\..\..\RimWorldWin64_Data\Managed\UnityEngine.CoreModule.dll</HintPath>
      <Private>False</Private>
    </Reference>
  </ItemGroup>
  <ItemGroup>
    <Compile Include="Properties\AssemblyInfo.cs" />
    <Compile Include="Source\Defs\SexToyAnimationDef.cs" />
    <Compile Include="Source\Harmony\Harmony_PatchAll.cs" />
    <Compile Include="Source\Patches\HarmonyPatch_JobDriver_SexBaseInitiator.cs" />
    <Compile Include="Source\Utilities\AnimSexToyUtility.cs" />
  </ItemGroup>
  <ItemGroup>
    <Folder Include="1.3\Assemblies\" />
  </ItemGroup>
  <ItemGroup>
    <Content Include="1.3\Defs\AnimationDefs\Animations_Dildo.xml" />
  </ItemGroup>
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>


code:
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Patch_SexToysMasturbation")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Patch_SexToysMasturbation")]
[assembly: AssemblyCopyright("Copyright ©  2022")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

// Setting ComVisible to false makes the types in this assembly not visible
// to COM components.  If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("87763712-0536-4d5f-9eaa-520f15d4f84e")]

// Version information for an assembly consists of the following four values:
//
//      Major Version
//      Minor Version
//      Build Number
//      Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]


code:
using Rimworld_Animations;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Patch_SexToysMasturbation
{
    public class SexToyAnimationDef : AnimationDef
    {

        public String requiredBodyPart = null;

    }
}


code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Verse;
using HarmonyLib;
using System.Reflection;

namespace Patch_SexToysMasturbation
{

    [StaticConstructorOnStartup]
    public static class Harmony_PatchAll {

        static Harmony_PatchAll() {

            Harmony val = new Harmony("animtoyspatch");
            val.PatchAll(Assembly.GetExecutingAssembly());

        }
    }
}


code:
using HarmonyLib;
using Rimworld_Animations;
using rjw;
using RJW_ToysAndMasturbation;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Verse;

namespace Patch_SexToysMasturbation
{
    [HarmonyPatch(typeof(JobDriver_SexBaseInitiator), "Start")]
    public class HarmonyPatch_JobDriver_SexBaseInitiator
    {

        public static void Postfix(ref JobDriver_SexBaseInitiator __instance)
        {

            if(__instance is JobDriver_MasturbateWithToy masturbateJobDriver)
            {

                Log.Message("Rerolling animations...");
                Pawn pawn = masturbateJobDriver.pawn;
                Thing sexToy = masturbateJobDriver.dildo;

                RerollAnimationsForSexToy(pawn, sexToy, masturbateJobDriver.Bed);
            }

        }

        public static void RerollAnimationsForSexToy(Pawn pawn, Thing thing, Thing bed)
        {
            CompSexToy sextoy = thing.TryGetComp<CompSexToy>();

            SexToyAnimationDef anim = AnimSexToyUtility.tryFindAnimation(sextoy, pawn);

            if (anim != null)
            {
                Log.Message("Playing anim " + anim.defName);

                if(bed != null)
                {
                    pawn.TryGetComp<CompBodyAnimator>().setAnchor(bed);
                    thing.TryGetComp<CompThingAnimator>().setAnchor(bed);
                }
                else
                {
                    pawn.TryGetComp<CompBodyAnimator>().setAnchor(pawn.Position);
                    thing.TryGetComp<CompThingAnimator>().setAnchor(pawn.Position);
                }

                bool mirror = GenTicks.TicksGame % 2 == 0;

                pawn.TryGetComp<CompBodyAnimator>().StartAnimation(anim, new List<Pawn> { pawn }, 0, mirror);
                thing.TryGetComp<CompThingAnimator>().StartAnimation(anim, pawn, mirror);

                (pawn.jobs.curDriver as JobDriver_Sex).ticks_left = anim.animationTimeTicks;
                (pawn.jobs.curDriver as JobDriver_Sex).sex_ticks = anim.animationTimeTicks;
                (pawn.jobs.curDriver as JobDriver_Sex).duration = anim.animationTimeTicks;
            }
            else
            {
                Log.Message("No animation found");
            }

        }

    }

}


code:
using rjw;
using RJW_ToysAndMasturbation;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Verse;

namespace Patch_SexToysMasturbation
{
    public class AnimSexToyUtility
    {

        public static SexToyAnimationDef tryFindAnimation(CompSexToy sexToy, Pawn pawn)
        {

            IEnumerable<SexToyAnimationDef> options = DefDatabase<SexToyAnimationDef>.AllDefs.Where((SexToyAnimationDef x) =>
            {

                if(!sexToy.Props.requiredBodyParts.Contains(x.requiredBodyPart))
                {
                    return false;
                }

                if(x.requiredBodyPart == "vagina" && !Genital_Helper.has_vagina(pawn))
                {
                    return false;
                }

                return true;

            });

            if(options != null && options.Any())
            {
                return options.RandomElement();
            }
            else
            {
                return null;
            }

        }

    }
}


code:
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Rimworld-Animations")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Rimworld-Animations")]
[assembly: AssemblyCopyright("Copyright ©  2020")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

// Setting ComVisible to false makes the types in this assembly not visible
// to COM components.  If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("71b05d71-67b2-4014-82cd-18c20ac0882f")]

// Version information for an assembly consists of the following four values:
//
//      Major Version
//      Minor Version
//      Build Number
//      Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]


code:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProjectGuid>{71B05D71-67B2-4014-82CD-18C20AC0882F}</ProjectGuid>
    <OutputType>Library</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>Rimworld_Animations</RootNamespace>
    <AssemblyName>Rimworld-Animations</AssemblyName>
    <TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
    <FileAlignment>512</FileAlignment>
    <Deterministic>true</Deterministic>
    <TargetFrameworkProfile />
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <DebugSymbols>false</DebugSymbols>
    <DebugType>none</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>1.4\Assemblies\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <DebugType>none</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin\Release\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="0Harmony">
      <HintPath>..\..\..\..\workshop\content\294100\839005762\1.4\Assemblies\0Harmony.dll</HintPath>
      <Private>False</Private>
    </Reference>
    <Reference Include="AlienRace">
      <HintPath>..\..\..\..\workshop\content\294100\839005762\1.4\Assemblies\AlienRace.dll</HintPath>
      <Private>False</Private>
    </Reference>
    <Reference Include="Assembly-CSharp">
      <HintPath>..\..\RimWorldWin64_Data\Managed\Assembly-CSharp.dll</HintPath>
      <Private>False</Private>
    </Reference>
    <Reference Include="RJW">
      <HintPath>..\rjw\1.4\Assemblies\RJW.dll</HintPath>
      <Private>False</Private>
    </Reference>
    <Reference Include="RJW-ToysAndMasturbation">
      <HintPath>..\rjw-toys-and-masturbation\Assemblies\RJW-ToysAndMasturbation.dll</HintPath>
      <Private>False</Private>
    </Reference>
    <Reference Include="System" />
    <Reference Include="System.Core" />
    <Reference Include="System.Xml.Linq" />
    <Reference Include="System.Data.DataSetExtensions" />
    <Reference Include="Microsoft.CSharp" />
    <Reference Include="System.Data" />
    <Reference Include="System.Net.Http" />
    <Reference Include="System.Xml" />
    <Reference Include="UnityEngine">
      <HintPath>..\..\RimWorldWin64_Data\Managed\UnityEngine.dll</HintPath>
      <Private>False</Private>
    </Reference>
    <Reference Include="UnityEngine.CoreModule">
      <HintPath>..\..\RimWorldWin64_Data\Managed\UnityEngine.CoreModule.dll</HintPath>
      <Private>False</Private>
    </Reference>
  </ItemGroup>
  <ItemGroup>
    <Compile Include="1.4\Source\Actors\Actor.cs" />
    <Compile Include="1.4\Source\Actors\AlienRaceOffset.cs" />
    <Compile Include="1.4\Source\Actors\BodyTypeOffset.cs" />
    <Compile Include="1.4\Source\Animations\AnimationStage.cs" />
    <Compile Include="1.4\Source\Animations\Clips\BaseAnimationClip.cs" />
    <Compile Include="1.4\Source\Animations\Clips\PawnAnimationClip.cs" />
    <Compile Include="1.4\Source\Animations\Clips\ThingAnimationClip.cs" />
    <Compile Include="1.4\Source\Animations\Keyframes\Keyframe.cs" />
    <Compile Include="1.4\Source\Animations\Keyframes\PawnKeyframe.cs" />
    <Compile Include="1.4\Source\Animations\Keyframes\ThingKeyframe.cs" />
    <Compile Include="1.4\Source\Comps\CompBodyAnimator.cs" />
    <Compile Include="1.4\Source\Comps\CompProperties_BodyAnimator.cs" />
    <Compile Include="1.4\Source\Comps\CompProperties_ThingAnimator.cs" />
    <Compile Include="1.4\Source\Comps\CompThingAnimator.cs" />
    <Compile Include="1.4\Source\Defs\AnimationDef.cs" />
    <Compile Include="1.4\Source\Extensions\PawnWoundDrawerExtension.cs" />
    <Compile Include="1.4\Source\MainTabWindows\MainTabWindow_OffsetConfigure.cs" />
    <Compile Include="1.4\Source\MainTabWindows\OffsetMainButtonDefOf.cs" />
    <Compile Include="1.4\Source\MainTabWindows\WorldComponent_UpdateMainTab.cs" />
    <Compile Include="1.4\Source\Patches\Harmony_PatchAll.cs" />
    <Compile Include="1.4\Source\Patches\OtherModPatches\HarmonyPatch_CSL.cs" />
    <Compile Include="1.4\Source\Patches\OtherModPatches\HarmonyPatch_DontShaveYourHead.cs" />
    <Compile Include="1.4\Source\Patches\OtherModPatches\HarmonyPatch_FacialAnimation.cs" />
    <Compile Include="1.4\Source\Patches\OtherModPatches\HarmonyPatch_HatsDisplaySelection.cs" />
    <Compile Include="1.4\Source\Patches\OtherModPatches\HarmonyPatch_ShowHairWithHats.cs" />
    <Compile Include="1.4\Source\Patches\RimworldPatches\HarmonyPatch_HeadHair.cs" />
    <Compile Include="1.4\Source\Patches\RimworldPatches\HarmonyPatch_PawnRenderer.cs" />
    <Compile Include="1.4\Source\Patches\RimworldPatches\HarmonyPatch_PawnRotation.cs" />
    <Compile Include="1.4\Source\Patches\RimworldPatches\HarmonyPatch_Pawn_DrawTracker.cs" />
    <Compile Include="1.4\Source\Patches\RimworldPatches\HarmonyPatch_SetPawnAnimatable.cs" />
    <Compile Include="1.4\Source\Patches\RimworldPatches\HarmonyPatch_Thing.cs" />
    <Compile Include="1.4\Source\Patches\RJWPatches\HarmonyPatch_PlaySexSounds.cs" />
    <Compile Include="1.4\Source\Patches\RJWPatches\HarmonyPatch_SexTick.cs" />
    <Compile Include="1.4\Source\Patches\RJWPatches\HarmonyPatch_WorkGiverSex.cs" />
    <Compile Include="1.4\Source\Patches\RJWPatches\JobDrivers\HarmonyPatch_JobDriver_JoinInBed.cs" />
    <Compile Include="1.4\Source\Patches\RJWPatches\JobDrivers\HarmonyPatch_JobDriver_SexBaseInitiator.cs" />
    <Compile Include="1.4\Source\Patches\RJWPatches\JobDrivers\HarmonyPatch_JobDriver_SexBaseReceiverLoved.cs" />
    <Compile Include="1.4\Source\Settings\AnimationSettings.cs" />
    <Compile Include="1.4\Source\Utilities\AnimationUtility.cs" />
    <Compile Include="1.4\Source\Utilities\PatchOperationAddOrReplace.cs" />
    <Compile Include="Properties\AssemblyInfo.cs" />
  </ItemGroup>
  <ItemGroup>
    <Content Include="1.1\Assemblies\Rimworld-Animations.dll" />
    <Content Include="1.4\Assemblies\Rimworld-Animations.dll" />
    <Content Include="1.4\Defs\AnimationDefs\Animations_Beast.xml" />
    <Content Include="1.4\Defs\AnimationDefs\Animations_Lesbian.xml" />
    <Content Include="1.4\Defs\AnimationDefs\Animations_Masturbate.xml" />
    <Content Include="1.4\Defs\AnimationDefs\Animations_Multi.xml" />
    <Content Include="1.4\Defs\AnimationDefs\Animations_SexToys.xml" />
    <Content Include="1.4\Defs\AnimationDefs\Animations_vanilla.xml" />
    <Content Include="1.4\Defs\AnimationDefs\Animations_Vanilla2.xml" />
    <Content Include="1.4\Defs\AnimationDefs\TemplateAnimation.xml" />
    <Content Include="1.4\Defs\MainTabDefs\MainButtonDef.xml" />
    <Content Include="1.4\Defs\SoundDefs\Sounds_Sex.xml" />
    <Content Include="1.4\Patches\AnimationPatchHSK.xml" />
    <Content Include="1.4\Patches\AnimationPatch_CompBodyAnimator.xml" />
    <Content Include="1.4\Patches\CompatibilityPatch_FacialAnimation.xml" />
    <Content Include="1.4\Patches\CompatibilityPatch_HCSK.xml" />
    <Content Include="1.4\Patches\CompPatches\AutoCleaner.xml" />
    <Content Include="1.4\Patches\CompPatches\CombatExtended.xml" />
    <Content Include="1.4\Patches\CompPatches\ZombieLand.xml" />
    <Content Include="1.4\Patches\RacePatches\Epona race Renaissance.xml" />
    <Content Include="1.4\Patches\RacePatches\Nyaron.xml" />
    <Content Include="1.4\Sounds\Sex\Clap_1.wav" />
    <Content Include="1.4\Sounds\Sex\Clap_2.wav" />
    <Content Include="1.4\Sounds\Sex\Clap_3.wav" />
    <Content Include="1.4\Sounds\Sex\Clap_4.wav" />
    <Content Include="1.4\Sounds\Sex\Clap_5.wav" />
    <Content Include="1.4\Sounds\Sex\Clap_6.wav" />
    <Content Include="1.4\Sounds\Sex\Clap_7.wav" />
    <Content Include="1.4\Sounds\Sex\Clap_8.wav" />
    <Content Include="1.4\Sounds\Sex\cum.wav" />
    <Content Include="1.4\Sounds\Sex\kucyu04.wav" />
    <Content Include="1.4\Sounds\Sex\Slime\Slimy1.wav" />
    <Content Include="1.4\Sounds\Sex\Slime\Slimy2.wav" />
    <Content Include="1.4\Sounds\Sex\Slime\Slimy3.wav" />
    <Content Include="1.4\Sounds\Sex\Slime\Slimy4.wav" />
    <Content Include="1.4\Sounds\Sex\Slime\Slimy5.wav" />
    <Content Include="1.4\Sounds\Sex\Suck\Suck_1.wav" />
    <Content Include="1.4\Sounds\Sex\Suck\Suck_10.wav" />
    <Content Include="1.4\Sounds\Sex\Suck\suck_2.wav" />
    <Content Include="1.4\Sounds\Sex\Suck\Suck_3.wav" />
    <Content Include="1.4\Sounds\Sex\Suck\Suck_4.wav" />
    <Content Include="1.4\Sounds\Sex\Suck\Suck_5.wav" />
    <Content Include="1.4\Sounds\Sex\Suck\Suck_6.wav" />
    <Content Include="1.4\Sounds\Sex\Suck\Suck_7.wav" />
    <Content Include="1.4\Sounds\Sex\Suck\Suck_8.wav" />
    <Content Include="1.4\Sounds\Sex\Suck\Suck_9.wav" />
    <Content Include="1.4\Sounds\Sex\Suck\Swallow_1.wav" />
    <Content Include="1.4\Sounds\Sex\Suck\Swallow_2.wav" />
    <Content Include="1.4\Sounds\Sex\Suck\Swallow_3.wav" />
    <Content Include="1.4\Textures\UI\MainTab.png" />
    <Content Include="About\About.xml" />
    <Content Include="About\Manifest.xml" />
    <Content Include="Languages\PortugueseBrazilian\DefInjected\MainButtonDef\MainButtonDef.xml" />
    <Content Include="Languages\PortugueseBrazilian\DefInjected\Rimworld_Animations.AnimationDef\Animations_Beast.xml" />
    <Content Include="Languages\PortugueseBrazilian\DefInjected\Rimworld_Animations.AnimationDef\Animations_Lesbian.xml" />
    <Content Include="Languages\PortugueseBrazilian\DefInjected\Rimworld_Animations.AnimationDef\Animations_Multi.xml" />
    <Content Include="Languages\PortugueseBrazilian\DefInjected\Rimworld_Animations.AnimationDef\Animations_vanilla.xml" />
    <Content Include="LoadFolders.xml" />
  </ItemGroup>
  <ItemGroup>
    <Folder Include="1.2\" />
  </ItemGroup>
  <ItemGroup>
    <None Include="1.4\Defs\AnimationDefs\AnimationDefs.rar" />
    <None Include="1.4\Patch_HatsDisplaySelection\Patch_HatsDisplaySelection.csproj" />
  </ItemGroup>
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>


code:
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29905.134
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rimworld-Animations", "Rimworld-Animations.csproj", "{71B05D71-67B2-4014-82CD-18C20AC0882F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Patch_HatsDisplaySelection", "Patch_HatsDisplaySelection\Patch_HatsDisplaySelection.csproj", "{BA766964-1716-422D-A09E-29426F8EB9D5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Patch_SexToysMasturbation", "Patch_SexToysMasturbation\Patch_SexToysMasturbation.csproj", "{87763712-0536-4D5F-9EAA-520F15D4F84E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Patch_HumanoidAlienRaces", "Patch_HumanoidAlienRaces\Patch_HumanoidAlienRaces.csproj", "{C76F3790-9AC0-4827-ACD5-84174238954F}"
EndProject
Global
	GlobalSection(SolutionConfigurationPlatforms) = preSolution
		Debug|Any CPU = Debug|Any CPU
		Release|Any CPU = Release|Any CPU
	EndGlobalSection
	GlobalSection(ProjectConfigurationPlatforms) = postSolution
		{71B05D71-67B2-4014-82CD-18C20AC0882F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
		{71B05D71-67B2-4014-82CD-18C20AC0882F}.Debug|Any CPU.Build.0 = Debug|Any CPU
		{71B05D71-67B2-4014-82CD-18C20AC0882F}.Release|Any CPU.ActiveCfg = Release|Any CPU
		{71B05D71-67B2-4014-82CD-18C20AC0882F}.Release|Any CPU.Build.0 = Release|Any CPU
		{BA766964-1716-422D-A09E-29426F8EB9D5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
		{BA766964-1716-422D-A09E-29426F8EB9D5}.Release|Any CPU.ActiveCfg = Release|Any CPU
		{BA766964-1716-422D-A09E-29426F8EB9D5}.Release|Any CPU.Build.0 = Release|Any CPU
		{87763712-0536-4D5F-9EAA-520F15D4F84E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
		{87763712-0536-4D5F-9EAA-520F15D4F84E}.Debug|Any CPU.Build.0 = Debug|Any CPU
		{87763712-0536-4D5F-9EAA-520F15D4F84E}.Release|Any CPU.ActiveCfg = Release|Any CPU
		{87763712-0536-4D5F-9EAA-520F15D4F84E}.Release|Any CPU.Build.0 = Release|Any CPU
		{C76F3790-9AC0-4827-ACD5-84174238954F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
		{C76F3790-9AC0-4827-ACD5-84174238954F}.Debug|Any CPU.Build.0 = Debug|Any CPU
		{C76F3790-9AC0-4827-ACD5-84174238954F}.Release|Any CPU.ActiveCfg = Release|Any CPU
		{C76F3790-9AC0-4827-ACD5-84174238954F}.Release|Any CPU.Build.0 = Release|Any CPU
	EndGlobalSection
	GlobalSection(SolutionProperties) = preSolution
		HideSolutionNode = FALSE
	EndGlobalSection
	GlobalSection(ExtensibilityGlobals) = postSolution
		SolutionGuid = {7E01292A-D76F-4CA3-AA64-085B84ECD905}
	EndGlobalSection
EndGlobal


code:
tweego*
stjohns*.html
.vscode/
.*.sw*

repo_name: allisonedwards/st

path: .gitignore

license: mit


code:
stages:
  - build

image: allisonedwards/twinetools

variables:
    TWEEGO: /root/main

build_game:
  tags:
      - docker
  stage: build
  artifacts:
    paths:
      - stjohns-latest.html
  script:
      - ./make.sh


code:
CID=`git rev-parse --short HEAD`
VERSION=`cat VERSION`
"$TWEEGO" $DEBUG -f harlowe-2 "$@" -s "Disclaimer"  -o stjohns-$VERSION-$CID.html src
if [ "$?" = 0 ]; then
    cp stjohns-$VERSION-$CID.html stjohns-latest.html
    echo  stjohns-$VERSION-$CID.html created successfully.;
fi


code:
:: Dance Changing room start
(set: $attireLast = $attire)

Not really knowing where to go, you follow the rest of the class to what you hope is their next lesson, hoping you \
might find some manner of escape possible, and keeping a low profile. Your are somewhat surprised to  find your self in a girl's \
changing room. There is a locker with the name 'Juliet' on it an nobody standing beside it.

You look around the room for some escape; but the room is beginning to fill up with half naked girls; many of whom seem to be putting on leotard tutus similar to the one in the bedroom wardrobe.

(link: "Enjoy the sight of naked girls")[\
    You've haven't had the opportunities before so see so many almost naked girls together at one time, you \
    take pleasure and drink in the usually forbidden sights, and feel you cock hardening with pleasure as you do so.
    (set: _d = $myns.get().increaseHorny(30))\
    (set: _d = $myns.get().increaseSissy(-15))\
    (if: $horniness > 60)[\
        |teacher>["Juilet, What do you think you are doing?"]. You realise a teacher had walked in while you where fantasing about being able to lick some of the lovely breasts on display, and then that your hand is under your skirt is rubbing your (if: $caged)[caged] cock.
        |pcSpeech>[(if: $gagged)["Mmph, Mmph"](else:)["I,.. I,.. "]], you stammer, as you notice the rest of the class look at comprising display.
        |enemySpeech>["Eww, You pevert"]. says one of the girls in the class.
        |worriedthoughts>[Oh shit, I how am I going to get out of this]
        (if: $caged)[\
            |teacher>["You might well stammer, Go and see Mrs Jones after class, or it'll be the reform school
            for you. That sort of behaviour isn't tolerated in proper Ladies. 20 demerits"]\
            (set: $demerits to 20 + it)\
        ](else:)[\
            (if: $needs_mistress_visit)[\
                |teacher>["You have already been asked once to visit the Headmistress, it's clear I need to take you there myself. 15 demerits for this behavoiur."]\
                (set: $demerits = $demerits + 15)\
                The teacher takes a firm grip on your arm and the girls all seem to instinctively clear the way to the door, as the teacher marches you through it and down the corridor to the Headmistress' office. You try to resist but her hold is too tight.
                (replace: "Change you mind and try to leave")[]\
                (replace: "Get changed and try not to be noticed")[]\
                (link: "continue")[
                    <!-- Some variable Hackiness; to support a during a lesson visit to the headmistress -->\
                    (set: $nextLessonNr=$currentLessonNr)(set: $nextLesson="Mrs Jones makes you wear a Tutu")\
                    (display: "Headmistress 1")
                ]
            ](else:)[\
                |teacher>["Aftger the lesson go and see the headmistress. That sort of behaviour is not tolerated in this school. 10 Demerits]\
                (set: $demerits to it + 10)\
                (set: $needs_mistress_visit= true)\
                (replace: "Get changed and try not to be noticed")["Get Changed"]
            ]
        ]\
]]
(link: "Get changed and try not to be noticed")[
(replace: "Change you mind and try to leave")[]\
(replace: "Enjoy the sight of naked girls")[]\
You realise you are just going to have to go with the flow, resistance here and how is going to go badly. At some point you will find an \
opportunity to leave the school, but it not going to be until after this lesson as well.
You face your locker and open it, finding just as you expected all the kit required for a dance lesson. \
You put the tights on first, so you can keep to the secret between your legs hidden, and then strip and quickly
put the tutu on. |worriedthoughts>[I mean I don't have any choice do I?]\
(set: _d = $myns.get().increaseSissy(15))\
(set: $attire= "tutu")\
(show: ?startclass) \
]\
(if: $sissyness < 50)[
(link: "Change you mind and try to leave")[\
(replace: "Get changed and try not to be noticed")[]\
(replace: "Enjoy the sight of naked girls")[]\
You try to turn around and force your way back against the tide of girls entering the room, \
(if: $horniness > 75)[ despite the obvious opportunities that a girls changing room holds. ]\
(else:)[ but you can't imagine staying here is going to be best way to keep your male pride intact. ]\

You just about reach the main doorway and make out into the corridor, when you almost walk into right the teacher coming the other way.
|teacher>["Juliet. I'm Mrs Wickham your Dance teacher, I'm disappointed to find you seem to have left you dance kit, in the dorm.."], she passes you a large bag, |teacher>["You better get changing quickly now, tights on first"] . She stands there while you fumble in the bag to find a pair of opaque white tights. Under the stern gaze of the teacher you take off your shoes and undies to put to put on the tights.
|teacher>["Now the ballet shoes"], delving further in the bag which it is clear also contains a tutu you, find some ballet shoes, you take off the Mary janes you took form the dorm room first, and start to put \
on the ballet slippers, but fumble with the ribbon straps not knowing what to do with them. Unfortunately the teacher notices your indecision.
|teacher>["You really are useless, aren't you Juliet? Look the straps do up like this."] , she shows you how to tie the ribbons off properly, |teacher>["Now get undressed and put this on"], she says pratically throwing the tutu into your arms.
The teacher is looking at you so sternly, you realise you have little option but to comply. You strip off your (if: $attire is "summer")[dress](else:)[skirt and blouse], and remove your bra, facing the lockers as you do so to prevent the embrassement of the uncomfortable forms stuck to your chest. you quickly pull on the tutu leotard, which seems to be made out of a some sort of stretchy material, before the teacher can find something else to punish you for.

You resignedly follow on after the rest of the class into the Dance studio. You hesitate as the other girls file
over and stand obediently in line by the mirror of the far wall.

(set: $attire= "tutu")\
(show: ?startclass) \
]]

:: Ballet [class]
(set: $attireRandomise = false)\
(if: $attire is "tutu")[  (set: $attireRandomise = true)\
](else:)[(display: "Dance Changing room start")\
]

|startclass)[\
\
|teacher>["$girlCharacter, Take your place at the barre"], Miss Wickham replies says indicating towards the rest of the class. |teacher>["I'm sure you can make it up later"]

(link:"Try and make a run for it")[
You look round and thing about making a run for but then you capture a look of yourself in the mirror. If there is one thing you can say for the way you look, you, it is will draw attention in the street. Let alone in your Boys school dorm rooms. There is no way you want to be caught outside, or worse at your school  wearing a tutu. (set: _d = $myns.get().increaseSissy(-10) )
]
(link:"Join the rest of the class")[(replace: "Try and make a run for it")[]\
You join the (if: $sissyness >= 30)[other] girls at mirror, and the Miss wickham starts to tell you about the arm positions in ballet, and start at some point you realise she is shouting numbers and expecting you to put your arms into the appropriate position.

(live: 1s)[\
(set: _x to $myns.get().askAboutTaskEffort("How much effort to pose you arms like a girl are you going to take","balletarms","Pose!", "armscore", "feettask") )\
(print: _x )\
(stop:)]\
|feettask)[
|teacher>["Now we shall do the feet positions girls"], and the teachers starts off with the numbers again, but this is really hard, and you can't even see your own feet with the tutu on.

(set: _x to $myns.get().askAboutTaskEffort("How much pain and effort are you going put into the feet positions","balletfeet","Pose!", "feetscore", "packet") )\
(print: _x )
]

|packet)[
(set: $feetscore = _feetscore) <!-- Allow data to escape the hook -->
|teacher>["Right girls, time now to sit of the floor, and we can look at how well you've all been doing practicing your Entrechat.

"$enemyCharacter , you are up first".]

You had intended to sit by yourself, but a girl comes to sit beside you.
|girlspeech>["I'm  $friendCharacter - nice to meet you"], She puts her fingers to her lips suggesting you are quiet, |girlspeech>["I know your secret"], she continues in a whisper, |girlspeech>["You might find these really useful"]. She passes you a packet of what look like throat lozenges.

|take1>[(link: "Take the packet")[(set: $has_throatsweet = true) You accept the packet of sweets. (replace: ?refuse1)[](show:?entrechat)]]
|refuse1>[(link: "Refuse the packet")[You try to refuse the offer but $friendCharacter tries to insist, "look if you don't take one you won't be able to keep your secret and then you'll end up in detention" (replace: ?take1)[]
|take2>[(link: "Take the packet after all")[(set: $has_throatsweets =true) Given the warnings you accept the packet of sweets, just in case. (replace: ?refuse2)[](show:?entrechat)]]
|refuse2>[(link: "Refuse the packet again")[You refuse the paket again. $friendCharacter looks at you . |girlspeech>["Well it's your funeral"] (replace: ?take2)[] (show:?entrechat) ]
]]]]
]

|entrechat)[
You watch the other girls go up one by one and contort their feet into some impossible position and then jump in the air waggling their feet.  You have no idea how you'll manage idea of that.

(if: $feetscore < 55) [However when in comes to your turn the teacher saves you.

|teacher>["$girlCharacter your feet positions are not good enough for this yet.  10 demerits, and I hope you do better next time,"(set: $demerits=$demerits+10)
"and the rest of you should help her in your free practice time."]
](else:)[\
|teacher>["$girlCharacter, now it's your turn. Start with you feet turned in an jump."

Not knowing what ekse to do you come the the front of the class and attempt to repeat wht youhave seen the ohter girls do. As you jumo in the air you catch sight of yourself in the mirror once more, seeing a rather clumsy girl in a tutu jump in the air, and with all the unfamiliar sensations, you loose you concentration and land painfully, almost falling over.

|teacher>["$girlCharacter! That was hardly graceful was it. 20 demerits. A girl should be graceful at all times."] (set: $demerits = it +20)

]]
(display: "Dance Changing room end")
]\
]\
(if: $attireRandomise)[(show: ?startclass)]\

:: Dance Changing room end

(set: _notsissy to false)\
(set: _balletprincess to false )\
(set: _other to false )\
(if: $sissyness < 40)[(set: _notsissy to true)]\
(else-if: $sissyness > 70)[(set: _balletprincess to true)]\
(else:)[(set: _other to true)]\
After the exertions of the Dance class, and (if: _notsissy)[humiliation] (if: _balletprincess)[joy] \
(if: _other)[discomfort] of wearing a Tutu, you follow the class back to the changing rooms \
without a great dealt of thought.

You stand in front of your locker and take off the leotard and tutu, hoping that by facing the locker \
your secret will stay hidden as you reach in for your \
(if: $attireLast is "summer")[dress] \
(else:)[skirt].

As you do $friendCharacter, throws a towel at you and says, |girlspeech>["Come-on, let get in the shower."]

You take the towel, and start to wrap in round your waist, |girlspeech>["No - up here."], hisses \
$friendCharacter , |girlspeech>["You don't want people to think you are a boy, do you?"].
Wrapping the towel round your chest just adds extra weight to the unsupported breast forms that already\
feel like they are trying to pull your skin \
off. But you persevere, and allow her to drag you into the shower area.

The shower area is thankfully divided into sections, and not fully communal, but they aren't \
individual cubicles either. $friendCharacter, pulls you into one, |girlspeech>["Don't worry nobody else \
likes this one."]  She hangs your and her towels at the edge, and starts the water running.

You start to yelp, as the warm water starts to course over you body, \
(if: $gagged)[\
    you scream into the even present intruder in your mouth but all that comes out is a gaspinging like sound.
    $girlCharacter gives you a peck on the check, and you \
](else:)[\
    but your cry of surprise is cut short as $friendCharacter covers your mouth with her own.

You \
]\
feel her hand reach down and \
(if: not $caged)[\
     grab your cock, and start slowly stroking it.\
     (if: $horniness <30)[\
         You've cum quite recently so it takes her a some effort to make you hard \
         but she gets there eventually.\
     ](else-if: $horniness < 80)[\
         It takes her the work of a few moments to get your attention but nothing \
         more, after which she drop to her kness and takes you inside her mouth.\
         (if: "Sex Education" is in $lessonsComplete)[ \
            She applies all the skills from the Sex-ed class you had, and it doesn't \
            take long before you are done.\
         ](else:)[\
            You don't know where whe learned the skill she has with her tongue but,\
            it doesn't take much for her to push you over the edge.\
         ]\
    ](else:)[\
        She has barely gotten a good grip when you can't help yourself and make a bit of mess. You get \
        treated to a final pout as a result of your performance |friend>["Typical man, never considers the lady"]. She \
        flounces of flinging you a uniform dress and a towel to dry yourself off with.\
    ]\
(set: _dummy = $myns.get().increaseSissy(-10) ) (set: _dummy = $myns.get().increaseHorny(-1 * $horniness ) )
](else:)[\
 playfully fondles your cage. |friend>["Turn round"], she says, coming up for air. And start to man hand you\
to face the wall, |freind>["I'll wash your back"], you can feel her hands rub your back as if giving you a massage and you \
muscles start to relax you suddenly feel and invasion lower down. |girlspeech>["ssh, you enjoy this"], and then |worriedthoughts>[Oh my GOD!] \
she finds something senistive.., something sensitive around the back, and you just start to feel pleasure rush over you and can't \
resist any longer, and surrender to the pleasure.
(set: _dummy = $myns.get().increaseSissy(25) ) (set: _dummy = $myns.get().increaseHorny(-1 * $horniness ) )\
]\

(set: $attire = $attireLast)\
(show: ?endLesson)

:: Mrs Jones makes you wear a Tutu
(set: $currentLesson="ballet")\
(set: $attire="tutu")\

As you turn to go to your next lesson, Mrs Jones stops you |jonesSpeech>["Isn't your next lesson Ballet?
I'm sure it is. I'll help you get changed quickly without a fuss."] She grabs you by the arm before and pulls you through the door behind her into a private room, closing the door behind her. You can see a clothes rail with all sort of different costumes hanging from it. She selects a pink tutu with the widest skirt you can imagine. |jonesSpeech>["Our novice uniform should be ideal for you"], she says hold out the dress to you.

You realise that she is standing between you and the door.  You don't rate your chances of being able to push past her.

|enthuasticwear)[(replace: ?wearDecision)[]\
(set: _d = myns.get().increaseSissy(40)]\
(set: _d = myns.get().increaseHorny(30)]\

You realise you've always wanted the chance to wear a tutu, but it's not the sort of thing you can admit to as a boy without be sure of receiving quite a bit of ridicule in return. And you never even had courage to go into a Dance store and see them up close. And now is chance to wear one, with complete deniable. After all you were forced into it weren't you? |worriedthoughts>[People will believe that won't they?.]

You take off you uniform and underwear, carefully. You don't want to appear to eager, but judging by her smile you think Mrs Jones knows anyway.
|jonesSpeech>["These first"], she says handing you some dance tights when you are finally undressed.

You pull the tights on savouring the unusually sensations as you pull them up you legs, and reach out for the tutu, and Mrs Jones pull it out of your reach, just for a moment. But a long enough moment to force an involuntary moan of dismay from you for she hands you the leotard and it's sewn in tutu.

Mrs Jones giggles, as you hold it against you looking in the mirror. |jonesSpeech>["Such a sissy. Go on put it on."]

|worriedthoughts>[Busted!]

You put on the tutu, looking at your reflection in mirror, realising the only think which is feminine than the way it looks on you, is the way it feels.

|jonesSpeech>["Hop along, to class now"]

And you  can't resist doing just that because it seems so silly and fun to hop in a Tutu, so pushing down the sides of the skirt so you can get through the door, you start to hop and then skip until you reach the Dance studio.

]\
|timidwear)[(replace: ?wearDecision)[
(set: _d = myns.get().increaseSissy(15)]\
You slowly take outer uniform, hoping you can put off the moment before you have to consider that item of unbridled femininity which Mrs Jones is
offering you. She just stands there impassive watching.

You hold your hand out for the Tutu, but she just looks at you |jonesSpeech>["Knickers, as well, Girl."]. And so you take off your knickers as well, leaving standing starkers(if $caged:)[, apart from a pink plastic case affixed to you cock and balls with a small brass padlock. Mrs Jones appears to notice your attention. |jonesSpeech>["Well, we can't have one of those wandering about freely. This is a Girl's school."] (set: $seenCage = true) ]

|jonesSpeech>["Put these on first"], Mrs Jones asks passing you a pair of what you assume must be dance tights.

You struggle to put the tights on, almost tripping yourself up, but the sensation as you draw them up your legs is nothing like you have felt before. You hardly get a moment to think about before Mrs Jones ask you to step into the Tutu, and she helps you put your arms into the leotard
portion at the top.
|jonesSpeech>["There you go. A proper girl, of to her first ballet lesson. Toddle along. Have fun"], she steps out of the way for you to pass.

You approach the door, to leave anything to get out of this new nightmare. You take a step forward discovering the way the skirt bounces with every slight movement you make, and tugging in slightly uncomfortable ways on the leotard as it does so. But most annoyingly you realise you skirt is actually wider than the door.

Mrs Jones, watches you and laughs, |jonesSpeech>["Go out sideways, and bend over a little, The doors not that much small you know."]

You take her advise and run back to ballet class, in the hope to perhaps it will somehow make the lesson finish sooner. But all it does it
make you more aware of how feminine you must like running down the corridor in a pink tutu.
]\
|fight)[(replace: ?wearDecision)[]
You look at the Mrs Jones, carefully try to judge your attack, You settle on trying to rush her. Perhaps if you surprise her, you
can get the upper hand. But as you rush forward in the small space you see her produce a syringe from behind her back.

You completely fail to dodge the syringe, and she plunges whatever drug it contains into you as you try to pass.
Everything fades to black as you fall to the floor.

[[Wake up->Disobedient ending]]
]\
|wearDecision>[
(set: _toq to $myns.get().sissyObedienceQuotient() ) \
(if: _toq > 120)[ (show:  ?enthuasticwear) ]
(else:)[\
(link: "I've always wanted to wear a tutu, and I'm not afraid to show it")[(show ?enthuasticwear)]
(link: "Put on the tutu since you don't have much choice")[(show: ?timidwear)]
(if: _toq < 80)[\
(link: "Fight your way out")[(show: ?fight)]]
]]\


code:
:: Drama Changing room start
(set: $attireLast = $attire)
You change into a prom dress in the changing rooms
TODO (Changing room - beginning)
 	- Make this changing room passage have some real content
	- Specificaly creating an enemy in $enemyCharacter.
	- She asks to swap dresses if you don't she is enemy.
	- If you do you you have to kiss the shcool bully not your firend
	- one of the dress option is awedding dress.

(set: $enemy = true)\
(set: $attire="prom")

:: Drama [class]
(if: $attire is "prom")[  (set: $attireLast = (either: "summer", "winter"))\
](else:)[
(display: "Drama Changing room start")]
(set: $frenchkiss = false)(set: $friendAgrees= false)\

You can't help but swish into the drama studio the the long and full skirts of the dress seem to have and mind of their own. You can't ignore the sensual feel of the petticoat continually stroking your legs. But what worries you when you enter the room is it has most of your classmates from the Grammar school already here, including $bestFriend (if: $sissyness < 60)[your·best friend](else:)[a really sweet boy from your class].

Before you can worry to much about that; |teacher>["Good morning Girls"], another different teacher greets you for this class.

(text-colour:"Lime")[(text-style:"italic")["Good morning miss"]]; is the reply from the class \
(if: $used_throatsweet is 0 )[ you mumbly quietly to try to hide you boy's voice ](else:)[]
The teacher continues, |teacher>[".. as you can see we have the Grammar school boys in for the joint play, we are doing at the end of term and I can see you are already wearing your costumes ready. Today we are going to practice kissing"].

[(if: $sissyness <50)[Kissing!. Oh god, your not going to have to kiss one of your class are you.](else:)[Great, an opportunity to kiss some boyss.]]<worriedthoughts|

|teacher>["If you can pair up with the boys now.."]

You make your way over to $bestFriend as quickly as you can; perhaps
he will help you out of this predicament.

(if: $madeEnemy)[ $enemyCharacter looks at you and says |enemyspeech>["Straight for the good looking ones, heh. You are such a slut. You better make a good show of this or I'm tellin gthe teacher you've been wanking.]]

You look at $bestFriend and  whisper to him. |pcspeech>["$bestFriend it's me $boyCharacter, I got into Juliet's knickers but if they catch me I'm in trouble - lend me some kit when this lesson is over"]

(live:1s)[\
(if: $used_throatsweet >0)[|boyspeech>["You don't even sound like him. You can't be boy with a voice like that. I don't what you're trying to pull but unless you kiss me properly I'm telling the teacher you refused to kiss me."](set: $friendAgrees = false)(show: ?kisstask)
] (else-if: $makeup_quality > 0)[\
$bestFriend looks at look and laughs, |boyspeech>["oh priceless $boyCharacter. No I think your going to have to get out of this by yourself. You've even put makeup on trying to fit in." He whips his phone out his pocket and takes a photo of you with an exsapersated look, and says. "The lads are really going to laugh at this"]. (set: $photoMakeup = $makeup_quality)
(if: $makeup_quality > 20 )[ |boyspeech>["But you do look hot. So perhaps if you let me french kiss you I won't show anybody and will think about lending you the kit"]

|worriedthoughts>[What!. Is $bestFriend gay?]

(set: _fkoq=$myns.get().sissyObedienceQuotient())
(if: _fkoq > 70)[You can't resist the opportunity to kiss $boyCharacter, he looks hot too.(set: $frenchkiss = true)(set: $friendAgrees = true) |pcspeech>["Yeah , ok I suppose"], you reply. You don't want to appear to keen.(show: ?kisstask)]\
(else-if: _fkoq > 45)[(link: "Agree to french kissing")[(set: $frenchkiss = true)(set: $friendAgrees = true) "Yeah , ok I suppose", you reply. Your not keen but it seem the best way out.(show: ?kisstask)]](else:)[You can't bring yourself to agree.]
(if: _fkoq <= 70)[(link: "Refuse french kissing")[|pcspeech>["Not a chance"], you reply.
$bestFriends looks at you as says |boyspeech>["I guess you must like it in skirts then, you sissy."](set: $friendAgrees = false)(show: ?kisstask)]]]
(else:)[(show: ?kisstask)]
]
(else:)[|boyspeech>["Gawd,  $boyCharacter - Yeah  of course . I've got some rugger kit in my bag I can lend you - come with me to the boys changing room after the lesson."](set: $friendAgrees = true)(show: ?kisstask)]\
(stop:)]\

|kisstask)[
|teacher>["So, girls stage kissing is a little different from real kissing. ..", the teacher starts and drones on for a while.]

(set: _x to $myns.get().askAboutTaskEffort("How much effort are you going put giving your mate a good Kiss?","kissslide", "Kiss!", "kissscore", "kissedhook") )\
(print: _x )\
]

|kissedhook)[
(if: $friendAgrees)[\
	(if: $frenchkiss)[[|pcSpeech>["Well, what about that kit then?"], you ask at the end of the lesson]
	(if: _kissscore < 20)[|boySpeech>["Not after that pathetic attempt at kissing. Your mates are going to find this photo really great. I think I might put it on the house noticeboard when I get back."]
	|worriedthoughts>[Oh no. Your really are going to be a laughing stock if you ever get out of this.]
	](else-if: _kissscore <40)[ <|-- An ok kisser - Grudingly allows fkit--> ]
    (else:)[<!-- A surpisly good kisser - Gives kit and necklace; dnagles the promise of  date -->]
	](else:)[<!-- French kissing not needed -->]]
(else:)[After the lesson you return to the changing room with the rest of girls, disappointed with the fact you failed to make any progress on your escape attempt. (set: _d= $myns.get().increaseSissy(Math.max(0,_kissscore/2)))
]
(display: "Drama Changing room end") ]

:: Drama Changing room end
After the lesson you return to the changing rooms and put on your uniform.
TODO - Make this changing room passage have some real content
(set: $attire = $attireLast)\
\
(show: ?endLesson)

:: Boy's changing rooms after Drama
TDO Double-click this passage to edit it.

[[[ Back to your own school ->Boy's school]]
(if: not $caged)[[ Discovered ->Headmistress 1]]\
(else:)[[[Discovered->Disappointed Ending]]  ]