code:
<?xml version="1.0" encoding="utf-8"?>
<Defs>
  <AnimationDef>
    <defName>InitiatorPawn_Missionary_Stage3</defName>
    <durationTicks>35</durationTicks>
    <animationParts>

        <key>Root</key>
        <value>
          <workerClass>Rimworld_Animations.AnimationWorker_KeyframesExtended</workerClass>
          <keyframes>

              <tick>0</tick>
              <angle>10</angle>
              <visible>true</visible>
              <offset>(-0.75, 0, 0.38)</offset>
              <scale>(1, 1, 1)</scale>
              <rotation>East</rotation>

              <tick>35</tick>
              <angle>15</angle>
              <visible>true</visible>
              <offset>(-0.65, 0, 0.42)</offset>
              <scale>(1, 1, 1)</scale>
              <rotation>East</rotation>

          </keyframes>
        </value>

        <key>Head</key>
        <value>
          <workerClass>Rimworld_Animations.AnimationWorker_KeyframesExtended</workerClass>
          <keyframes>

              <tick>0</tick>
              <angle>3</angle>
              <visible>true</visible>
              <scale>(1, 1, 1)</scale>
              <rotation>East</rotation>

              <tick>35</tick>
              <angle>20</angle>
              <visible>true</visible>
              <scale>(1, 1, 1)</scale>
              <rotation>East</rotation>

          </keyframes>
        </value>

        <key>RimNude_Penis</key>
        <value>
          <workerClass>Rimworld_Animations.AnimationWorker_KeyframesExtended</workerClass>
          <keyframes>

              <tick>0</tick>
              <angle>30</angle>
              <visible>true</visible>
              <scale>(1, 1, 1)</scale>
				<offset>(0, -3, 0)</offset>
              <rotation>East</rotation>

              <tick>35</tick>
              <angle>30</angle>
              <visible>true</visible>
              <scale>(1, 1, 1)</scale>
				<offset>(0, -3, 0)</offset>
              <rotation>East</rotation>

          </keyframes>
        </value>

    </animationParts>
  </AnimationDef>
  <AnimationDef>
    <defName>ReceiverPawn_Missionary_Stage3</defName>
    <durationTicks>35</durationTicks>
    <animationParts>

        <key>Root</key>
        <value>
          <workerClass>Rimworld_Animations.AnimationWorker_KeyframesExtended</workerClass>
          <keyframes>

              <tick>0</tick>
              <angle>90</angle>
              <visible>true</visible>
              <offset>(0.03, -1, 0)</offset>
              <scale>(1, 1, 1)</scale>
              <rotation>West</rotation>

              <tick>35</tick>
              <angle>95</angle>
              <visible>true</visible>
              <offset>(0.07, -1, 0)</offset>
              <scale>(1, 1, 1)</scale>
              <rotation>West</rotation>

          </keyframes>
        </value>

        <key>Head</key>
        <value>
          <workerClass>Rimworld_Animations.AnimationWorker_KeyframesExtended</workerClass>
          <keyframes>

              <tick>0</tick>
              <angle>-20</angle>
              <visible>true</visible>
              <scale>(1, 1, 1)</scale>
              <rotation>West</rotation>

              <tick>35</tick>
              <angle>-20</angle>
              <visible>true</visible>
              <scale>(1, 1, 1)</scale>
              <rotation>West</rotation>

          </keyframes>
        </value>

    </animationParts>
  </AnimationDef>
</Defs>


code:
<?xml version="1.0" encoding="utf-8"?>
<Defs>
  <AnimationDef>
    <defName>InitiatorPawn_Missionary_Stage4</defName>
    <durationTicks>20</durationTicks>
    <animationParts>

        <key>Root</key>
        <value>
          <workerClass>Rimworld_Animations.AnimationWorker_KeyframesExtended</workerClass>
          <keyframes>

              <tick>0</tick>
              <angle>15</angle>
              <visible>true</visible>
              <offset>(-0.65, 0, 0.42)</offset>
              <rotation>East</rotation>
              <sound>Fuck</sound>

              <tick>5</tick>
              <angle>0</angle>
              <visible>true</visible>
              <offset>(-0.42, 0, 0.42)</offset>
              <rotation>East</rotation>
              <voice>MoanShort</voice>

              <tick>20</tick>
              <angle>15</angle>
              <visible>true</visible>
              <offset>(-0.65, 0, 0.42)</offset>
              <rotation>East</rotation>

          </keyframes>
        </value>

        <key>Head</key>
        <value>
          <workerClass>Rimworld_Animations.AnimationWorker_KeyframesExtended</workerClass>
          <keyframes>

              <tick>0</tick>
              <angle>20</angle>
              <visible>true</visible>
              <rotation>East</rotation>

              <tick>5</tick>
              <angle>30</angle>
              <visible>true</visible>
              <rotation>East</rotation>

              <tick>20</tick>
              <angle>20</angle>
              <visible>true</visible>
              <rotation>East</rotation>

          </keyframes>
        </value>

        <key>RimNude_Penis</key>
        <value>
          <workerClass>Rimworld_Animations.AnimationWorker_KeyframesExtended</workerClass>
          <keyframes>

              <tick>35</tick>
              <angle>30</angle>
              <visible>true</visible>
              <offset>(0, -3, 0)</offset>
              <rotation>East</rotation>

          </keyframes>
        </value>

    </animationParts>
  </AnimationDef>
  <AnimationDef>
    <defName>ReceiverPawn_Missionary_Stage4</defName>
    <durationTicks>20</durationTicks>
    <animationParts>

        <key>Root</key>
        <value>
          <workerClass>Rimworld_Animations.AnimationWorker_KeyframesExtended</workerClass>
          <keyframes>

              <tick>0</tick>
              <angle>95</angle>
              <visible>true</visible>
              <offset>(0.07, -1, 0)</offset>
              <rotation>West</rotation>

              <tick>5</tick>
              <angle>100</angle>
              <visible>true</visible>
              <offset>(0.2, -1, 0)</offset>
              <rotation>West</rotation>
              <voice>MoanShort</voice>

              <tick>20</tick>
              <angle>95</angle>
              <visible>true</visible>
              <offset>(0.07, -1, 0)</offset>
              <rotation>West</rotation>

          </keyframes>
        </value>

        <key>Head</key>
        <value>
          <workerClass>Rimworld_Animations.AnimationWorker_KeyframesExtended</workerClass>
          <keyframes>

              <tick>0</tick>
              <angle>-20</angle>
              <visible>true</visible>
              <rotation>West</rotation>

              <tick>13</tick>
              <angle>-26</angle>
              <visible>true</visible>
              <rotation>West</rotation>

              <tick>20</tick>
              <angle>-20</angle>
              <visible>true</visible>
              <rotation>West</rotation>

          </keyframes>
        </value>

    </animationParts>
  </AnimationDef>
</Defs>

repo_name: SpitfireSmoke/rimworld

license: unknown


code:
<?xml version="1.0" encoding="utf-8"?>
<Defs>
  <AnimationDef>
    <defName>InitiatorPawn_Missionary_Stage5</defName>
    <durationTicks>13</durationTicks>
    <animationParts>

        <key>Root</key>
        <value>
          <workerClass>Rimworld_Animations.AnimationWorker_KeyframesExtended</workerClass>
          <keyframes>

              <tick>0</tick>
              <angle>15</angle>
              <visible>true</visible>
              <offset>(-0.65, 0, 0.42)</offset>
              <rotation>East</rotation>
              <sound>Fuck</sound>

              <tick>5</tick>
              <angle>0</angle>
              <visible>true</visible>
              <offset>(-0.45, 0, 0.42)</offset>
              <rotation>East</rotation>
              <voice>Grunt</voice>

              <tick>13</tick>
              <angle>15</angle>
              <visible>true</visible>
              <offset>(-0.65, 0, 0.42)</offset>
              <rotation>East</rotation>

          </keyframes>
        </value>

        <key>Head</key>
        <value>
          <workerClass>Rimworld_Animations.AnimationWorker_KeyframesExtended</workerClass>
          <keyframes>

              <tick>0</tick>
              <angle>20</angle>
              <visible>true</visible>
              <rotation>East</rotation>

              <tick>5</tick>
              <angle>40</angle>
              <visible>true</visible>
              <rotation>East</rotation>

              <tick>20</tick>
              <angle>20</angle>
              <visible>true</visible>
              <rotation>East</rotation>

          </keyframes>
        </value>

        <key>RimNude_Penis</key>
        <value>
          <workerClass>Rimworld_Animations.AnimationWorker_KeyframesExtended</workerClass>
          <keyframes>

              <tick>35</tick>
              <angle>30</angle>
              <visible>true</visible>
              <offset>(0, -3, 0)</offset>
              <rotation>East</rotation>

          </keyframes>
        </value>

    </animationParts>
  </AnimationDef>
  <AnimationDef>
    <defName>ReceiverPawn_Missionary_Stage5</defName>
    <durationTicks>13</durationTicks>
    <animationParts>

        <key>Root</key>
        <value>
          <workerClass>Rimworld_Animations.AnimationWorker_KeyframesExtended</workerClass>
          <keyframes>

              <tick>0</tick>
              <angle>95</angle>
              <visible>true</visible>
              <offset>(0.07, -1, 0)</offset>
              <rotation>West</rotation>

              <tick>3</tick>
              <angle>100</angle>
              <visible>true</visible>
              <offset>(0.16, -1, 0)</offset>
              <rotation>West</rotation>
              <voice>Grunt</voice>

              <tick>13</tick>
              <angle>95</angle>
              <visible>true</visible>
              <offset>(0.07, -1, 0)</offset>
              <rotation>West</rotation>

          </keyframes>
        </value>

        <key>Head</key>
        <value>
          <workerClass>Rimworld_Animations.AnimationWorker_KeyframesExtended</workerClass>
          <keyframes>

              <tick>0</tick>
              <angle>-20</angle>
              <visible>true</visible>
              <rotation>West</rotation>

              <tick>3</tick>
              <angle>-34</angle>
              <visible>true</visible>
              <rotation>West</rotation>

              <tick>13</tick>
              <angle>-20</angle>
              <visible>true</visible>
              <rotation>West</rotation>

          </keyframes>
        </value>

    </animationParts>
  </AnimationDef>
</Defs>


code:
<?xml version="1.0" encoding="utf-8"?>
<Defs>
  <AnimationDef>
    <defName>InitiatorPawn_Missionary_Stage6</defName>
    <durationTicks>200</durationTicks>
    <animationParts>

        <key>Root</key>
        <value>
          <workerClass>Rimworld_Animations.AnimationWorker_KeyframesExtended</workerClass>
          <keyframes>

              <tick>0</tick>
              <angle>15</angle>
              <visible>true</visible>
              <offset>(-0.65, 0, 0.42)</offset>
              <rotation>East</rotation>

              <tick>13</tick>
              <angle>-20</angle>
              <visible>true</visible>
              <offset>(-0.43, 0, 0.42)</offset>
              <rotation>East</rotation>
              <sound>Fuck</sound>
              <voice>Scream</voice>

              <tick>80</tick>
              <angle>-15</angle>
              <visible>true</visible>
              <offset>(-0.49, 0, 0.42)</offset>
              <rotation>East</rotation>
              <sound>Cum</sound>

              <tick>85</tick>
              <angle>-20</angle>
              <visible>true</visible>
              <offset>(-0.43, 0, 0.42)</offset>
              <rotation>East</rotation>

              <tick>150</tick>
              <angle>-15</angle>
              <visible>true</visible>
              <offset>(-0.49, 0, 0.42)</offset>
              <rotation>East</rotation>
              <sound>Cum</sound>

              <tick>155</tick>
              <angle>-20</angle>
              <visible>true</visible>
              <offset>(-0.43, 0, 0.42)</offset>
              <rotation>East</rotation>
              <voice>Scream</voice>

              <tick>200</tick>
              <angle>-15</angle>
              <visible>true</visible>
              <offset>(-0.49, 0, 0.42)</offset>
              <rotation>East</rotation>

          </keyframes>
        </value>

        <key>Head</key>
        <value>
          <workerClass>Rimworld_Animations.AnimationWorker_KeyframesExtended</workerClass>
          <keyframes>

              <tick>0</tick>
              <angle>20</angle>
              <visible>true</visible>
              <rotation>East</rotation>

              <tick>40</tick>
              <angle>25</angle>
              <visible>true</visible>
              <rotation>East</rotation>

              <tick>200</tick>
              <angle>30</angle>
              <visible>true</visible>
              <rotation>East</rotation>

          </keyframes>
        </value>

        <key>RimNude_Penis</key>
        <value>
          <workerClass>Rimworld_Animations.AnimationWorker_KeyframesExtended</workerClass>
          <keyframes>

              <tick>0</tick>
              <angle>30</angle>
              <visible>true</visible>
              <offset>(0, -3, 0)</offset>
              <rotation>East</rotation>

              <tick>13</tick>
              <angle>60</angle>
              <visible>true</visible>
              <offset>(0, -3, 0)</offset>
              <rotation>East</rotation>

          </keyframes>
        </value>

    </animationParts>
  </AnimationDef>
  <AnimationDef>
    <defName>ReceiverPawn_Missionary_Stage6</defName>
    <durationTicks>200</durationTicks>
    <animationParts>

        <key>Root</key>
        <value>
          <workerClass>Rimworld_Animations.AnimationWorker_KeyframesExtended</workerClass>
          <keyframes>

              <tick>0</tick>
              <angle>95</angle>
              <visible>true</visible>
              <offset>(0.07, -1, 0)</offset>
              <rotation>West</rotation>

              <tick>13</tick>
              <angle>100</angle>
              <visible>true</visible>
              <offset>(0.23, -1, 0)</offset>
              <rotation>West</rotation>
              <voice>Scream</voice>

              <tick>80</tick>
              <angle>100</angle>
              <visible>true</visible>
              <offset>(0.2, -1, 0)</offset>
              <rotation>West</rotation>
              <voice>Scream</voice>

              <tick>85</tick>
              <angle>100</angle>
              <visible>true</visible>
              <offset>(0.23, -1, 0)</offset>
              <rotation>West</rotation>

              <tick>150</tick>
              <angle>100</angle>
              <visible>true</visible>
              <offset>(0.2, -1, 0)</offset>
              <rotation>West</rotation>
              <voice>Scream</voice>

              <tick>155</tick>
              <angle>100</angle>
              <visible>true</visible>
              <offset>(0.23, -1, 0)</offset>
              <rotation>West</rotation>

              <tick>200</tick>
              <angle>100</angle>
              <visible>true</visible>
              <offset>(0.2, -1, 0)</offset>
              <rotation>West</rotation>

          </keyframes>
        </value>

        <key>Head</key>
        <value>
          <workerClass>Rimworld_Animations.AnimationWorker_KeyframesExtended</workerClass>
          <keyframes>

              <tick>0</tick>
              <angle>-20</angle>
              <visible>true</visible>
              <rotation>West</rotation>

              <tick>100</tick>
              <angle>-10</angle>
              <visible>true</visible>
              <rotation>West</rotation>

              <tick>200</tick>
              <angle>-23</angle>
              <visible>true</visible>
              <rotation>West</rotation>

          </keyframes>
        </value>

    </animationParts>
  </AnimationDef>
</Defs>


code:
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
	<AnimationDef>
		<defName>TestAnimation1</defName>
		<durationTicks>400</durationTicks>
		<playWhenDowned>False</playWhenDowned>
		<animationParts>

				<key>Root</key>
				<value>
					<workerClass>Rimworld_Animations.AnimationWorker_KeyframesExtended</workerClass>
					<keyframes>

							<sound>Fuck</sound>
							<tick>30</tick>
							<angle>0</angle>
							<visible>true</visible>

							<tick>100</tick>
							<angle>0</angle>
							<visible>true</visible>

							<tick>200</tick>
							<angle>0</angle>
							<visible>true</visible>

							<tick>300</tick>
							<angle>0</angle>
							<visible>true</visible>

					</keyframes>
				</value>

				<key>Body</key>
				<value>
					<workerClass>Rimworld_Animations.AnimationWorker_KeyframesExtended</workerClass>
					<keyframes>

							<tick>0</tick>
							<angle>0</angle>
							<rotation>North</rotation>
							<visible>true</visible>

							<tick>50</tick>
							<angle>0</angle>
							<rotation>South</rotation>
							<visible>true</visible>

							<tick>100</tick>
							<angle>30</angle>
							<rotation>East</rotation>
							<visible>true</visible>

					</keyframes>
				</value>

				<key>Head</key>
				<value>
					<workerClass>Rimworld_Animations.AnimationWorker_KeyframesExtended</workerClass>
					<keyframes>

							<tick>0</tick>
							<angle>0</angle>
							<rotation>North</rotation>
							<visible>true</visible>

							<tick>2</tick>
							<angle>0</angle>
							<rotation>East</rotation>
							<visible>true</visible>

							<tick>4</tick>
							<angle>0</angle>
							<rotation>South</rotation>
							<visible>true</visible>

							<tick>6</tick>
							<angle>0</angle>
							<rotation>West</rotation>
							<visible>false</visible>

							<tick>8</tick>
							<angle>0</angle>
							<rotation>North</rotation>
							<visible>false</visible>

					</keyframes>
				</value>

				<key>RenderNodeTag_Xray_Inside</key>
				<value>
					<workerClass>Rimworld_Animations.AnimationWorker_KeyframesExtended</workerClass>
					<keyframes>

							<tick>30</tick>
							<angle>0</angle>
							<visible>true</visible>

							<variant>1</variant>
							<tick>100</tick>
							<angle>0</angle>
							<visible>false</visible>

							<variant>2</variant>
							<tick>200</tick>
							<angle>0</angle>
							<visible>true</visible>

							<variant>1</variant>
							<tick>300</tick>
							<angle>0</angle>
							<visible>true</visible>

					</keyframes>
				</value>

		</animationParts>
	</AnimationDef>
</Defs>


code:
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
	<AnimationDef>
		<defName>TestAnimation2</defName>
		<durationTicks>400</durationTicks>
		<startOnRandomTick>False</startOnRandomTick>
		<playWhenDowned>False</playWhenDowned>

		<animationParts>

				<key>Root</key>
				<value>
					<workerClass>Rimworld_Animations.AnimationWorker_KeyframesExtended</workerClass>
					<keyframes>

							<tick>0</tick>
							<angle>0</angle>
							<rotation>South</rotation>

						  <tick>100</tick>
						  <angle>45</angle>
						  <rotation>South</rotation>

						  <tick>0</tick>
						  <offset>(-0.73, 0, -0.02)</offset>
						  <angle>0</angle>
						  <rotation>East</rotation>

						  <tick>200</tick>
						  <angle>90</angle>
						  <rotation>South</rotation>

						  <tick>300</tick>
						  <angle>135</angle>
						  <rotation>South</rotation>

					</keyframes>
				</value>

		</animationParts>
	</AnimationDef>
</Defs>


code:
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
	<AnimationDef>
		<defName>TestAnimation3</defName>
		<durationTicks>400</durationTicks>
		<playWhenDowned>False</playWhenDowned>
		<animationParts>

				<key>Root</key>
				<value>
					<workerClass>Rimworld_Animations.AnimationWorker_KeyframesExtended</workerClass>
					<keyframes>

							<sound>Fuck</sound>
							<tick>30</tick>
							<angle>90</angle>
							<rotation>East</rotation>
							<visible>true</visible>

							<tick>100</tick>
							<angle>80</angle>
							<rotation>East</rotation>
							<visible>true</visible>

							<tick>200</tick>
							<angle>90</angle>
							<rotation>East</rotation>
							<visible>true</visible>

							<tick>300</tick>
							<angle>80</angle>
							<rotation>East</rotation>
							<visible>true</visible>

					</keyframes>
				</value>

				<key>Head</key>
				<value>
					<workerClass>Rimworld_Animations.AnimationWorker_KeyframesExtended</workerClass>
					<keyframes>

							<tick>0</tick>
							<angle>-30</angle>
							<rotation>East</rotation>
							<visible>true</visible>

					</keyframes>
				</value>

				<key>RenderNodeTag_Knees</key>
				<value>
					<workerClass>Rimworld_Animations.AnimationWorker_KeyframesExtended</workerClass>
					<keyframes>

							<variant>1</variant>
							<tick>0</tick>
							<angle>0</angle>
							<visible>true</visible>

							<variant>1</variant>
							<tick>200</tick>
							<angle>3</angle>
							<visible>true</visible>

							<variant>1</variant>
							<tick>400</tick>
							<angle>0</angle>
							<visible>true</visible>

					</keyframes>
				</value>

				<key>RenderNodeTag_Arms</key>
				<value>
					<workerClass>Rimworld_Animations.AnimationWorker_KeyframesExtended</workerClass>
					<keyframes>

							<variant>1</variant>
							<tick>0</tick>
							<angle>0</angle>
							<visible>true</visible>

							<variant>1</variant>
							<tick>200</tick>
							<angle>3</angle>
							<visible>true</visible>

							<variant>1</variant>
							<tick>400</tick>
							<angle>0</angle>
							<visible>true</visible>

					</keyframes>
				</value>

				<key>RimNude_Penis</key>
				<value>
					<workerClass>Rimworld_Animations.AnimationWorker_KeyframesExtended</workerClass>
					<keyframes>

							<tick>0</tick>
							<angle>-30</angle>
							<visible>true</visible>
							<rotation>East</rotation>

							<tick>400</tick>
							<angle>-600</angle>
							<visible>true</visible>
							<rotation>East</rotation>

					</keyframes>
				</value>

		</animationParts>
	</AnimationDef>
</Defs>


code:
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
	<Rimworld_Animations.GroupAnimationDef>
		<defName>TestGroupAnimation1</defName>
		<numActors>2</numActors>
		<animationStages>

				<loops>10</loops>
				<loopOptions>

						<probability>3</probability>
						<animationDefs>

TestAnimation2

TestAnimation2

						</animationDefs>

						<probability>1</probability>
						<animationDefs>

TestAnimation2

TestAnimation2

						</animationDefs>

				</loopOptions>

		</animationStages>

		<offsetDefs>

GroinToAppropriateHeight

GroinToAppropriateHeight

		</offsetDefs>

	</Rimworld_Animations.GroupAnimationDef>
</Defs>


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

<Defs>
  <MainButtonDef>
    <defName>OffsetManager</defName>
    <label>offset manager</label>
    <description>Control pawn offsets</description>
    <tabWindowClass>Rimworld_Animations.MainTabWindow_OffsetConfigure</tabWindowClass>
    <order>54</order>
    <buttonVisible>false</buttonVisible>
    <iconPath>UI/MainTab</iconPath>
    <minimized>true</minimized>
  </MainButtonDef>

</Defs>


code:
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
	<Rimworld_Animations.AnimationOffsetDef>
		<defName>GroinToAppropriateHeight</defName>
		<offsets>

		</offsets>
	</Rimworld_Animations.AnimationOffsetDef>
</Defs>


code:
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
	<Rimworld_Animations.AnimationOffsetDef>
		<!-- Empty offsets -->
		<!-- Placeholder for when you haven't created offsets yet for specific pawn -->
		<defName>Offset_Placeholder</defName>
		<offsets>
		</offsets>
	</Rimworld_Animations.AnimationOffsetDef>
</Defs>


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

<Defs>
	<SoundDef>
		<defName>Cum</defName>
		<context>MapOnly</context>
		<eventNames />
		<maxSimultaneous>5</maxSimultaneous>
		<maxVoices>5</maxVoices>
		<subSounds>

				<grains>

						<clipPath>Sex/cum</clipPath>

				</grains>
				<volumeRange>
					<min>30</min>
					<max>40</max>
				</volumeRange>
				<pitchRange>
					<min>0.8</min>
					<max>1.2</max>
				</pitchRange>
				<distRange>
					<min>0</min>
					<max>51.86047</max>
				</distRange>
				<sustainLoop>False</sustainLoop>

		</subSounds>
	</SoundDef>
  <SoundDef>
		<defName>Sex</defName>
		<context>MapOnly</context>
		<eventNames />
		<maxSimultaneous>5</maxSimultaneous>
		<maxVoices>5</maxVoices>
		<subSounds>

				<grains>

						<clipPath>Sex/kucyu04</clipPath>

				</grains>
				<volumeRange>
					<min>16</min>
					<max>16</max>
				</volumeRange>
				<pitchRange>
					<min>0.8</min>
					<max>1.2</max>
				</pitchRange>
				<distRange>
					<min>0</min>
					<max>51.86047</max>
				</distRange>
				<sustainLoop>False</sustainLoop>

		</subSounds>
	</SoundDef>
	<SoundDef>
		<defName>Suck</defName>
		<context>MapOnly</context>
		<eventNames />
		<maxSimultaneous>5</maxSimultaneous>
		<maxVoices>5</maxVoices>
		<subSounds>

				<grains>

						<clipPath>Sex/Suck/Suck_1</clipPath>

						<clipPath>Sex/Suck/Suck_2</clipPath>

						<clipPath>Sex/Suck/Suck_3</clipPath>

						<clipPath>Sex/Suck/Suck_4</clipPath>

						<clipPath>Sex/Suck/Suck_5</clipPath>

					<clipPath>Sex/Suck/Suck_6</clipPath>

					<clipPath>Sex/Suck/Suck_7</clipPath>

					<clipPath>Sex/Suck/Suck_8</clipPath>

					<clipPath>Sex/Suck/Suck_9</clipPath>

					<clipPath>Sex/Suck/Suck_10</clipPath>

				</grains>
				<volumeRange>
          <min>20</min>
          <max>35</max>
				</volumeRange>
				<pitchRange>
					<min>1.0</min>
					<max>1.0</max>
				</pitchRange>
				<distRange>
					<min>0</min>
					<max>51.86047</max>
				</distRange>
				<repeatMode>NeverTwice</repeatMode>
				<sustainLoop>false</sustainLoop>

		</subSounds>
	</SoundDef>
  <SoundDef>
    <defName>Fuck</defName>
    <context>MapOnly</context>
    <eventNames />
    <maxSimultaneous>5</maxSimultaneous>
    <maxVoices>5</maxVoices>
    <subSounds>

        <grains>

            <clipPath>Sex/Clap_1</clipPath>

            <clipPath>Sex/Clap_2</clipPath>

            <clipPath>Sex/Clap_3</clipPath>

            <clipPath>Sex/Clap_4</clipPath>

            <clipPath>Sex/Clap_5</clipPath>

            <clipPath>Sex/Clap_6</clipPath>

            <clipPath>Sex/Clap_7</clipPath>

            <clipPath>Sex/Clap_8</clipPath>

        </grains>
        <volumeRange>35~45</volumeRange>
        <pitchRange>
          <min>1.0</min>
          <max>1.0</max>
        </pitchRange>
        <distRange>
          <min>0</min>
          <max>51.86047</max>
        </distRange>
        <repeatMode>NeverTwice</repeatMode>
        <sustainLoop>false</sustainLoop>

    </subSounds>
  </SoundDef>
  <SoundDef>
    <defName>Slimy</defName>
    <context>MapOnly</context>
    <eventNames />
    <maxSimultaneous>5</maxSimultaneous>
    <maxVoices>5</maxVoices>
    <subSounds>

        <grains>

            <clipPath>Sex/Slime/Slimy1</clipPath>

            <clipPath>Sex/Slime/Slimy2</clipPath>

            <clipPath>Sex/Slime/Slimy3</clipPath>

            <clipPath>Sex/Slime/Slimy4</clipPath>

            <clipPath>Sex/Slime/Slimy5</clipPath>

        </grains>
        <volumeRange>
          <min>45</min>
          <max>75</max>
        </volumeRange>
        <pitchRange>
          <min>1.4</min>
          <max>1.8</max>
        </pitchRange>
        <distRange>
          <min>0</min>
          <max>100</max>
        </distRange>
        <repeatMode>NeverTwice</repeatMode>
        <sustainLoop>false</sustainLoop>

    </subSounds>
  </SoundDef>
	<SoundDef>
		<defName>Slap</defName>
		<context>MapOnly</context>
		<eventNames />
		<maxSimultaneous>5</maxSimultaneous>
		<maxVoices>5</maxVoices>
		<subSounds>

				<grains>

						<clipPath>Sex/Slap/Slap_1</clipPath>

						<clipPath>Sex/Slap/Slap_2</clipPath>

						<clipPath>Sex/Slap/Slap_3</clipPath>

						<clipPath>Sex/Slap/Slap_4</clipPath>

						<clipPath>Sex/Slap/Slap_5</clipPath>

				</grains>
				<volumeRange>
					<min>75</min>
					<max>85</max>
				</volumeRange>
				<pitchRange>
					<min>0.8</min>
					<max>1.2</max>
				</pitchRange>
				<distRange>
					<min>0</min>
					<max>100</max>
				</distRange>
				<repeatMode>NeverTwice</repeatMode>
				<sustainLoop>false</sustainLoop>

		</subSounds>
	</SoundDef>
</Defs>


code:
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
	<Rimworld_Animations.TexPathVariantsDef>
		<defName>TexPathVariants_Arms</defName>
		<variants>

AnimationProps/Doggystyle/Doggy_Arms

		</variants>
	</Rimworld_Animations.TexPathVariantsDef>

</Defs>


code:
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
	<Rimworld_Animations.TexPathVariantsDef>
		<defName>TexPathVariants_Cat</defName>
		<variants>

AnimationProps/Cat/Cat1

AnimationProps/Cat/Cat2

		</variants>
	</Rimworld_Animations.TexPathVariantsDef>

</Defs>


code:
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
	<Rimworld_Animations.TexPathVariantsDef>
		<defName>TexPathVariants_Knees</defName>
		<variants>

AnimationProps/Doggystyle/Doggy_Legs

		</variants>
	</Rimworld_Animations.TexPathVariantsDef>

</Defs>


code:
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
	<Rimworld_Animations.TexPathVariantsDef>
		<defName>TexPathVariants_XrayPenis_Horse</defName>
		<variants>

AnimationProps/Cat/Cat1

AnimationProps/Cat/Cat2

		</variants>
	</Rimworld_Animations.TexPathVariantsDef>

</Defs>


code:
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
	<Rimworld_Animations.TexPathVariantsDef>
		<defName>TexPathVariants_XrayPenis_Human</defName>
		<variants>

AnimationProps/Cat/Cat1

AnimationProps/Cat/Cat2

		</variants>
	</Rimworld_Animations.TexPathVariantsDef>

</Defs>


code:
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
	<Rimworld_Animations.TexPathVariantsDef>
		<defName>TexPathVariants_Xray_Inside</defName>
		<variants>

AnimationProps/Cat/Cat1

AnimationProps/Cat/Cat2

		</variants>
	</Rimworld_Animations.TexPathVariantsDef>

</Defs>


code:
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
	<SoundDef>
		<defName>Moan_HumanFemale</defName>
		<context>MapOnly</context>
		<eventNames />
		<maxSimultaneous>5</maxSimultaneous>
		<maxVoices>5</maxVoices>
		<subSounds>

				<grains>

						<clipPath>Voices/FVoice/Moan1</clipPath>

						<clipPath>Voices/FVoice/Moan2</clipPath>

						<clipPath>Voices/FVoice/Moan3</clipPath>

						<clipPath>Voices/FVoice/Moan4</clipPath>

				</grains>
				<volumeRange>40~50</volumeRange>
				<pitchRange>0.99~1.02</pitchRange>
				<distRange>10~50</distRange>
				<repeatMode>NeverTwice</repeatMode>
				<sustainLoop>false</sustainLoop>

		</subSounds>
	</SoundDef>

	<SoundDef>
		<defName>MoanShort_HumanFemale</defName>
		<context>MapOnly</context>
		<eventNames />
		<maxSimultaneous>5</maxSimultaneous>
		<maxVoices>5</maxVoices>
		<subSounds>

				<grains>

						<clipPath>Voices/FVoice/MoanShort1</clipPath>

						<clipPath>Voices/FVoice/MoanShort2</clipPath>

						<clipPath>Voices/FVoice/MoanShort3</clipPath>

				</grains>
				<volumeRange>40~50</volumeRange>
				<pitchRange>0.99~1.02</pitchRange>
				<distRange>10~50</distRange>
				<repeatMode>NeverTwice</repeatMode>
				<sustainLoop>false</sustainLoop>

		</subSounds>
	</SoundDef>

	<SoundDef>
		<defName>Grunt_HumanFemale</defName>
		<context>MapOnly</context>
		<eventNames />
		<maxSimultaneous>5</maxSimultaneous>
		<maxVoices>5</maxVoices>
		<subSounds>

				<grains>

						<clipPath>Voices/FVoice/Grunt1</clipPath>

						<clipPath>Voices/FVoice/Grunt2</clipPath>

						<clipPath>Voices/FVoice/Grunt3</clipPath>

						<clipPath>Voices/FVoice/Grunt4</clipPath>

						<clipPath>Voices/FVoice/Grunt5</clipPath>

						<clipPath>Voices/FVoice/Grunt6</clipPath>

				</grains>
				<volumeRange>40~50</volumeRange>
				<pitchRange>0.99~1.02</pitchRange>
				<distRange>10~50</distRange>
				<repeatMode>NeverTwice</repeatMode>
				<sustainLoop>false</sustainLoop>

		</subSounds>
	</SoundDef>

	<SoundDef>
		<defName>Scream_HumanFemale</defName>
		<context>MapOnly</context>
		<eventNames />
		<maxSimultaneous>5</maxSimultaneous>
		<maxVoices>5</maxVoices>
		<subSounds>

				<grains>

						<clipPath>Voices/FVoice/Scream1</clipPath>

						<clipPath>Voices/FVoice/Scream2</clipPath>

						<clipPath>Voices/FVoice/Scream3</clipPath>

						<clipPath>Voices/FVoice/Scream4</clipPath>

				</grains>

				<pitchRange>0.99~1.02</pitchRange>
				<volumeRange>40~50</volumeRange>
				<distRange>10~50</distRange>
				<repeatMode>NeverTwice</repeatMode>
				<sustainLoop>false</sustainLoop>

		</subSounds>
	</SoundDef>
</Defs>


code:
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
	<SoundDef>
		<defName>Moan_HumanMale</defName>
		<context>MapOnly</context>
		<eventNames />
		<maxSimultaneous>5</maxSimultaneous>
		<maxVoices>5</maxVoices>
		<subSounds>

				<grains>

						<clipPath>Voices/MVoice/Moan1</clipPath>

						<clipPath>Voices/MVoice/Moan2</clipPath>

						<clipPath>Voices/MVoice/Moan3</clipPath>

						<clipPath>Voices/MVoice/Moan4</clipPath>

				</grains>
				<pitchRange>0.99~1.02</pitchRange>
				<volumeRange>40~50</volumeRange>
				<distRange>10~50</distRange>
				<repeatMode>NeverTwice</repeatMode>
				<sustainLoop>false</sustainLoop>

		</subSounds>
	</SoundDef>

	<SoundDef>
		<defName>MoanShort_HumanMale</defName>
		<context>MapOnly</context>
		<eventNames />
		<maxSimultaneous>5</maxSimultaneous>
		<maxVoices>5</maxVoices>
		<subSounds>

				<grains>

						<clipPath>Voices/MVoice/MoanShort1</clipPath>

						<clipPath>Voices/MVoice/MoanShort2</clipPath>

						<clipPath>Voices/MVoice/MoanShort3</clipPath>

				</grains>
				<pitchRange>0.99~1.02</pitchRange>
				<volumeRange>40~50</volumeRange>
				<distRange>10~50</distRange>
				<repeatMode>NeverTwice</repeatMode>
				<sustainLoop>false</sustainLoop>

		</subSounds>
	</SoundDef>

	<SoundDef>
		<defName>Grunt_HumanMale</defName>
		<context>MapOnly</context>
		<eventNames />
		<maxSimultaneous>5</maxSimultaneous>
		<maxVoices>5</maxVoices>
		<subSounds>

				<grains>

						<clipPath>Voices/MVoice/Grunt1</clipPath>

						<clipPath>Voices/MVoice/Grunt2</clipPath>

						<clipPath>Voices/MVoice/Grunt3</clipPath>

						<clipPath>Voices/MVoice/Grunt4</clipPath>

				</grains>
				<pitchRange>0.99~1.02</pitchRange>
				<volumeRange>40~50</volumeRange>
				<distRange>10~50</distRange>
				<repeatMode>NeverTwice</repeatMode>
				<sustainLoop>false</sustainLoop>

		</subSounds>
	</SoundDef>

	<SoundDef>
		<defName>Scream_HumanMale</defName>
		<context>MapOnly</context>
		<eventNames />
		<maxSimultaneous>5</maxSimultaneous>
		<maxVoices>5</maxVoices>
		<subSounds>

				<grains>

						<clipPath>Voices/MVoice/Scream1</clipPath>

						<clipPath>Voices/MVoice/Scream2</clipPath>

						<clipPath>Voices/MVoice/Scream3</clipPath>

				</grains>
				<pitchRange>0.99~1.02</pitchRange>
				<volumeRange>40~50</volumeRange>
				<distRange>10~50</distRange>
				<repeatMode>NeverTwice</repeatMode>
				<sustainLoop>false</sustainLoop>

		</subSounds>
	</SoundDef>
</Defs>


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

	<Rimworld_Animations.VoiceDef>
		<defName>Voice_HumanFemale</defName>
		<gender>Female</gender>
		<sounds>

<key>Moan</key><value>Moan_HumanFemale</value>

<key>MoanShort</key><value>MoanShort_HumanFemale</value>

<key>Grunt</key><value>Grunt_HumanFemale</value>

<key>Scream</key><value>Scream_HumanFemale</value>

		</sounds>
	</Rimworld_Animations.VoiceDef>

	<Rimworld_Animations.VoiceDef>
		<defName>Voice_HumanMale</defName>
		<gender>Male</gender>
		<sounds>

<key>Moan</key><value>Moan_HumanMale</value>

<key>MoanShort</key><value>MoanShort_HumanMale</value>

<key>Grunt</key><value>Grunt_HumanMale</value>

<key>Scream</key><value>Scream_HumanMale</value>

		</sounds>
	</Rimworld_Animations.VoiceDef>

</Defs>


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

</Defs>


code:
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
	<Rimworld_Animations.VoiceTagDef>
		<defName>Moan</defName>
		<probability>0.2</probability>
	</Rimworld_Animations.VoiceTagDef>

	<Rimworld_Animations.VoiceTagDef>
		<defName>MoanShort</defName>
		<probability>0.1</probability>
	</Rimworld_Animations.VoiceTagDef>

	<Rimworld_Animations.VoiceTagDef>
		<defName>Grunt</defName>
		<probability>0.1</probability>
	</Rimworld_Animations.VoiceTagDef>

	<!-- Screams are guaranteed -->
	<!-- Play once during orgasm -->
	<Rimworld_Animations.VoiceTagDef>
		<defName>Scream</defName>
		<probability>1</probability>
	</Rimworld_Animations.VoiceTagDef>

</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>{BA766964-1716-422D-A09E-29426F8EB9D5}</ProjectGuid>
    <OutputType>Library</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>Patch_HatsDisplaySelection</RootNamespace>
    <AssemblyName>Patch_HatsDisplaySelection</AssemblyName>
    <TargetFrameworkVersion>v4.7.2</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.2\Assemblies\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </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\2009463077\Current\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="HatDisplaySelection">
      <HintPath>..\..\..\..\..\workshop\content\294100\1542291825\1.2\Assemblies\HatDisplaySelection.dll</HintPath>
      <Private>False</Private>
    </Reference>
    <Reference Include="Rimworld-Animations">
      <HintPath>..\1.2\Assemblies\Rimworld-Animations.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\Patches\Patch_HatsDisplaySelection.cs" />
  </ItemGroup>
  <ItemGroup>
    <Folder Include="1.2\Assemblies\" />
  </ItemGroup>
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>


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>{0AD4F9B2-AE28-4E42-86D6-611FB93B7FF0}</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>
    <TargetFrameworkProfile />
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <DebugSymbols>false</DebugSymbols>
    <DebugType>none</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>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="HugsLib">
      <HintPath>..\..\..\..\..\..\workshop\content\294100\818773962\v1.4\Assemblies\HugsLib.dll</HintPath>
      <Private>False</Private>
    </Reference>
    <Reference Include="Rimworld-Animations">
      <HintPath>..\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="HarmonyPatch_AlienRace.cs" />
    <Compile Include="Properties\AssemblyInfo.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("0ad4f9b2-ae28-4e42-86d6-611fb93b7ff0")]

// 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" ?>
<Patch>
	<Operation Class="PatchOperationFindMod">
    <mods>

Core SK

    </mods>
		<match Class="PatchOperationSequence">
			<operations>

					<xpath>Defs/ThingDef/comps</xpath>
					<success>Always</success>
					<nomatch Class="PatchOperationAdd">
						<xpath>Defs/ThingDef</xpath>
						<value>
							<comps />
						</value>
					</nomatch>

					<xpath>Defs/ThingDef[@Name="BaseAnimalPawn" or @Name="SK_BasePawn" or @Name="BasePawnSkynet"]/comps</xpath>
					<value>

					</value>

			</operations>
		</match>
	</Operation>
</Patch>


code:
<?xml version="1.0" encoding="utf-8" ?>
<Patch>
  <Operation Class="PatchOperationSequence">
    <success>Always</success>
    <operations>

		<success>Always</success>
		<xpath>Defs/ThingDef[race][not(comps)]</xpath>
		<value>
		  <comps />
		</value>

		<success>Always</success>
		<xpath>Defs/AlienRace.ThingDef_AlienRace[not(comps)]</xpath>
		<value>
		  <comps />
		</value>

        <xpath>Defs/ThingDef[@Name="BasePawn"]/comps</xpath>
        <value>

        </value>

        <xpath>Defs/AlienRace.ThingDef_AlienRace/comps</xpath>
        <value>

        </value>

    </operations>
  </Operation>
</Patch>


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

	<Operation Class="PatchOperationSequence">
		<success>Always</success>
		<operations>

				<xpath>/Defs/PawnRenderTreeDef/root/subworkerClasses</xpath>
				<success>Always</success>
				<nomatch Class="PatchOperationAdd">
					<xpath>/Defs/PawnRenderTreeDef/root</xpath>
					<value>
						<subworkerClasses />
					</value>
				</nomatch>

				<xpath>/Defs/PawnRenderTreeDef/root/subworkerClasses</xpath>
				<value>

Rimworld_Animations.PawnRenderSubWorker_ChangeOffset

				</value>

		</operations>
	</Operation>

</Patch>


code:
<?xml version="1.0" encoding="utf-8" ?>
<Patch>
  <Operation Class="PatchOperationSequence">
    <success>Always</success>
    <operations>

        <xpath>/Defs/ThingDef[@Name="BaseBaseAutocleaner"]/comps</xpath>
        <success>Always</success>
	    <match Class="PatchOperationAdd">
		  <xpath>/Defs/ThingDef[@Name="BaseBaseAutocleaner"]/comps</xpath>
		  <value>

		  </value>
	    </match>

    </operations>
  </Operation>
</Patch>


code:
<?xml version="1.0" encoding="utf-8" ?>
<Patch>
  <Operation Class="PatchOperationSequence">
    <success>Always</success>
    <operations>

        <xpath>/Defs/ThingDef[@Name="BasePawnSimple"]/comps</xpath>
        <success>Always</success>
	    <match Class="PatchOperationAdd">
		  <xpath>/Defs/ThingDef[@Name="BasePawnSimple"]/comps</xpath>
		  <value>

		  </value>
	    </match>

    </operations>
  </Operation>
</Patch>


code:
<?xml version="1.0" encoding="utf-8" ?>
<Patch>
  <Operation Class="PatchOperationSequence">
    <success>Always</success>
    <operations>

        <xpath>/Defs/ThingDef[@Name="BaseZombie"]/comps</xpath>
        <success>Always</success>
	    <match Class="PatchOperationAdd">
		  <xpath>/Defs/ThingDef[@Name="BaseZombie"]/comps</xpath>
		  <value>

		  </value>
	    </match>

    </operations>
  </Operation>
</Patch>


code:
<?xml version="1.0" encoding="utf-8"?>
<Patch>
  <Operation Class="PatchOperationFindMod">
    <mods>

[NL] Facial Animation - WIP

    </mods>
    <match Class="PatchOperationSequence">
      <success>Always</success>
      <operations>

          <xpath>/Defs/FacialAnimation.FaceAnimationDef[defName="Lovin" or defName="Lovin2"]/targetJobs</xpath>
          <success>Always</success>
          <value>

RJW_Masturbate

GettinBred

Bestiality

BestialityForFemale

ViolateCorpse

Quickie

GettingQuickie

GettinRaped

JoinInBed

GettinLoved

GettinLicked

GettinSucked

WhoreIsServingVisitors

JoinInBedAnimation

GettinLovedAnimation

          </value>

          <xpath>/Defs/FacialAnimation.FaceAnimationDef[defName="WaitCombat" or defName="Wait_Combat_Rare"]/targetJobs</xpath>
          <success>Always</success>
          <value>

RapeComfortPawn

RandomRape

RapeEnemy

          </value>

          <xpath>/Defs/FacialAnimation.FaceAnimationDef[defName="StandAndBeSociallyActive"]/targetJobs</xpath>
          <success>Always</success>
          <value>

WhoreInvitingVisitors

          </value>

          <xpath>/Defs/FacialAnimation.FaceAnimationDef[defName="Wear" or defName="Wear2" or defName="Wear3"]/targetJobs</xpath>
          <success>Always</success>
          <value>

CleanSelf

StruggleInBondageGear

          </value>

          <mods>

Rimworld-Animations

          </mods>
          <match Class="PatchOperationSequence">
            <success>Always</success>
            <operations>

                <xpath>/Defs/FacialAnimation.FaceAnimationDef[defName="Lovin" or defName="Lovin2"]/animationFrames/li[1]/headOffset</xpath>
                <success>Always</success>

                <xpath>/Defs/FacialAnimation.FaceAnimationDef[defName="Lovin"]/animationFrames/li[2]/headOffset</xpath>
                <success>Always</success>

                <xpath>/Defs/FacialAnimation.FaceAnimationDef[defName="Lovin"]/animationFrames/li[3]/headOffset</xpath>
                <success>Always</success>

            </operations>
          </match>

      </operations>
    </match>
  </Operation>
</Patch>


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

	<Operation Class="PatchOperationFindMod">
   		<mods>

Core SK

   		</mods>
		<match Class="PatchOperationSequence">
			<success>Always</success>
            <operations>

                    <xpath>/Defs/ThingDef/comps</xpath>
                    <success>Always</success>
                    <nomatch Class="PatchOperationAdd">
                        <xpath>/Defs/ThingDef</xpath>
                        <value>
                            <comps />
                        </value>
                    </nomatch>

                    <xpath>/Defs/ThingDef[@Name="SK_BasePawn"]/comps</xpath>
                    <value>

                    </value>

                    <xpath>/Defs/ThingDef[@Name="BaseAnimalPawn"]/comps</xpath>
                    <value>

                    </value>

            </operations>
		</match>
    </Operation>

</Patch>


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

</Patch>


code:
<?xml version="1.0" encoding="utf-8" ?>
<Patch>
	<!-- Add genitalia rendernode to pawns, body is parent
	<Operation Class="PatchOperationAdd">
		<xpath>Defs/PawnRenderTreeDef[defName="Humanlike"]/root/children/li[debugLabel="Body"]/children</xpath>
		<value>
			<li Class="PawnRenderNodeProperties_Overlay">
				<debugLabel>Genitalia</debugLabel>
				<workerClass>PawnRenderNodeWorker_OverlayWounds</workerClass>
				<overlayLayer>Body</overlayLayer>
				<baseLayer>3</baseLayer>
			</li>
		</value>
	</Operation>
	-->
</Patch>


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

namespace Rimworld_Animations {
    public class Actor {
        public List<string> defNames;
        public List<string> requiredGenitals;
        public List<AlienRaceOffset> raceOffsets;
        public List<string> blacklistedRaces;
        public bool initiator = false;
        public string gender;
        public bool isFucking = false;
        public bool isFucked = false;
        public bool controlGenitalAngle = false;
        public List<BodyDef> bodyDefTypes = new List<BodyDef>();
        public BodyTypeOffset bodyTypeOffset = new BodyTypeOffset();
        public Vector3 offset = new Vector2(0, 0);
		public List<string> requiredGender;
        public List<string> tags = new List<string>();
    }
}


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

namespace Rimworld_Animations {
    public class AlienRaceOffset {

        public string defName;
        public Vector2 offset;

    }
}


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

namespace Rimworld_Animations
{
    public class AnimationOffsetDef : Def
    {

        public List<BaseAnimationOffset> offsets;

        public bool FindOffset(Pawn pawn, out BaseAnimationOffset offset)
        {
            foreach (BaseAnimationOffset animOffset in offsets)
            {
                if (animOffset.appliesToPawn(pawn)) {

                    offset = animOffset;
                    return true;

                }
            }

            offset = null;
            return false;
        }
    }
}


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

namespace Rimworld_Animations
{
    public class AnimationOffset_AgeRange : BaseAnimationOffset
    {
        public List<BodyTypeOffset_AgeRange> offsetsMale;
        public List<BodyTypeOffset_AgeRange> offsetsFemale;

        public override Vector3? getOffset(Pawn pawn)
        {
            List<BodyTypeOffset_AgeRange> pawnOffsets = (pawn.gender == Gender.Male ? offsetsMale : offsetsFemale);
            return pawnOffsets.Find(x => x.bodyType == pawn.story.bodyType && x.ageRange.Includes(pawn.ageTracker.AgeBiologicalYears))?.offset ?? pawnOffsets.Last().offset;
        }

        public override int? getRotation(Pawn pawn)
        {
            List<BodyTypeOffset_AgeRange> pawnOffsets = (pawn.gender == Gender.Male ? offsetsMale : offsetsFemale);
            return pawnOffsets.Find(x => x.bodyType == pawn.story.bodyType && x.ageRange.Includes(pawn.ageTracker.AgeBiologicalYears))?.rotation ?? pawnOffsets.Last().rotation;
        }

        public override Vector3? getScale(Pawn pawn)
        {
            List<BodyTypeOffset_AgeRange> pawnOffsets = (pawn.gender == Gender.Male ? offsetsMale : offsetsFemale);
            return pawnOffsets.Find(x => x.bodyType == pawn.story.bodyType && x.ageRange.Includes(pawn.ageTracker.AgeBiologicalYears))?.scale ?? pawnOffsets.Last().scale;
        }
    }

    public class BodyTypeOffset_AgeRange : BodyTypeOffset
    {
        public FloatRange ageRange;

    }
}


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

namespace Rimworld_Animations
{
    public class AnimationOffset_BodyType : BaseAnimationOffset
    {

        public List<BodyTypeOffset> offsets;

        public override Vector3? getOffset(Pawn pawn)
        {
            return offsets.Find(x => x.bodyType == pawn.story.bodyType)?.offset;
        }

        public override int? getRotation(Pawn pawn)
        {
            return offsets.Find(x => x.bodyType == pawn.story.bodyType)?.rotation;
        }

        public override Vector3? getScale(Pawn pawn)
        {
            return offsets.Find(x => x.bodyType == pawn.story.bodyType)?.scale;
        }
    }

}


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

namespace Rimworld_Animations
{
    public class AnimationOffset_BodyTypeGendered : BaseAnimationOffset
    {

        public List<BodyTypeOffset> offsetsMale;
        public List<BodyTypeOffset> offsetsFemale;

        public override Vector3? getOffset(Pawn pawn)
        {
            if (pawn.gender == Gender.Female)
            {
                return offsetsFemale.Find(x => x.bodyType == pawn.story.bodyType)?.offset;
            }
            else
            {
                return offsetsMale.Find(x => x.bodyType == pawn.story.bodyType)?.offset;
            }

        }

        public override int? getRotation(Pawn pawn)
        {

            if (pawn.gender == Gender.Female)
            {
                return offsetsFemale.Find(x => x.bodyType == pawn.story.bodyType)?.rotation;
            }
            else
            {
                return offsetsMale.Find(x => x.bodyType == pawn.story.bodyType)?.rotation;
            }

        }

        public override Vector3? getScale(Pawn pawn)
        {

            if (pawn.gender == Gender.Female)
            {
                return offsetsFemale.Find(x => x.bodyType == pawn.story.bodyType)?.scale;
            }
            else
            {
                return offsetsMale.Find(x => x.bodyType == pawn.story.bodyType)?.scale;
            }

        }
    }
}


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

namespace Rimworld_Animations
{
    public class AnimationOffset_Single : BaseAnimationOffset
    {

        public Vector3 offset;
        public int? rotation;
        public Vector3? scale = Vector3.one;

        public override Vector3? getOffset(Pawn pawn)
        {
            return offset;
        }

        public override int? getRotation(Pawn pawn)
        {
            return rotation;
        }

        public override Vector3? getScale(Pawn pawn)
        {
            return scale;
        }
    }
}


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

namespace Rimworld_Animations
{
    public abstract class BaseAnimationOffset
    {
        public List<ThingDef> races;

        public abstract Vector3? getOffset(Pawn pawn);

        public abstract int? getRotation(Pawn pawn);

        public abstract Vector3? getScale(Pawn pawn);

        public bool appliesToPawn(Pawn pawn)
        {
            return races.Contains(pawn.def);

        }

    }
}


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

namespace Rimworld_Animations
{

    public class BodyTypeOffset
    {
        public BodyTypeDef bodyType;
        public int rotation = 0;
        public Vector3 offset;
        public Vector3 scale = Vector3.one;
    }
}


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

namespace Rimworld_Animations
{
    public class AnimationPropDef : Def
    {

        public PawnRenderNodeProperties animPropProperties;

    }
}


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

namespace Rimworld_Animations
{
    public class AnimationWorker_KeyframesExtended : AnimationWorker_Keyframes
    {

        public AnimationWorker_KeyframesExtended(AnimationDef def, Pawn pawn, AnimationPart part, PawnRenderNode node) : base(def, pawn, part, node)
        {
        }

        public override bool Enabled()
        {
            return true;
        }

        public override Vector3 OffsetAtTick(int tick, PawnDrawParms parms)
        {
            //Todo: Use this for bodyoffsets
            //or maybe make a rendersubworker for it instead
            return base.OffsetAtTick(tick, parms);
        }

        public VoiceTagDef voiceAtTick(int tick)
        {

            Verse.Keyframe keyframe2 = this.part.keyframes[this.part.keyframes.Count - 1];
            foreach (Verse.Keyframe keyframe in this.part.keyframes)
            {
                if (tick == keyframe.tick)
                {
                    VoiceTagDef voiceTag = (keyframe as ExtendedKeyframe).voice;

                    //probability checking null fix
                    if (voiceTag != null && Rand.Chance(voiceTag.probability))
                    {

                        return voiceTag;

                    }

                    return null;
                }

            }

            return null;

        }

        public SoundDef soundAtTick(int tick)
        {

            //Verse.Keyframe keyframe = this.part.keyframes[0];
            Verse.Keyframe keyframe2 = this.part.keyframes[this.part.keyframes.Count - 1];
            foreach (Verse.Keyframe keyframe in this.part.keyframes)
            {
                if (tick == keyframe.tick)
                {
                    return (keyframe as ExtendedKeyframe).sound;
                }

            }

            return null;
        }

        //use extendedkeyframes to determine addon facing
        public Rot4 facingAtTick(int tick)
        {

            //if ticks are < first keyframe tick, just be stuck to first keyframe rot
            if (tick <= this.part.keyframes[0].tick) {

                return (this.part.keyframes[0] as ExtendedKeyframe).rotation;

            }

            //if ticks are > last keyframe tick, just be stuck to last keyframe rot
            if (tick >= this.part.keyframes[this.part.keyframes.Count - 1].tick)
            {

                return (this.part.keyframes[this.part.keyframes.Count - 1] as ExtendedKeyframe).rotation;

            }
            Verse.Keyframe keyframe = this.part.keyframes[0];
            Verse.Keyframe keyframe2 = this.part.keyframes[this.part.keyframes.Count - 1];
            int i = 0;
            while (i < this.part.keyframes.Count)
            {
                if (tick <= this.part.keyframes[i].tick)
                {
                    keyframe2 = this.part.keyframes[i];
                    if (i > 0)
                    {
                        keyframe = this.part.keyframes[i - 1];
                        break;
                    }
                    break;
                }
                else
                {
                    i++;
                }
            }

            return (keyframe as ExtendedKeyframe).rotation;

        }
        public bool visibleAtTick(int tick)
        {
            //if ticks are < first keyframe tick, just be stuck to first keyframe rot
            if (tick <= this.part.keyframes[0].tick)
            {

                return (this.part.keyframes[0] as ExtendedKeyframe).visible;

            }

            //if ticks are > last keyframe tick, just be stuck to last keyframe rot
            if (tick >= this.part.keyframes[this.part.keyframes.Count - 1].tick)
            {

                return (this.part.keyframes[this.part.keyframes.Count - 1] as ExtendedKeyframe).visible;

            }

            Verse.Keyframe keyframe = this.part.keyframes[0];
            Verse.Keyframe keyframe2 = this.part.keyframes[this.part.keyframes.Count - 1];

            int i = 0;
            while (i < this.part.keyframes.Count)
            {
                if (tick <= this.part.keyframes[i].tick)
                {
                    keyframe2 = this.part.keyframes[i];
                    if (i > 0)
                    {
                        keyframe = this.part.keyframes[i - 1];
                        break;
                    }
                    break;
                }
                else
                {
                    i++;
                }
            }

            return (keyframe as ExtendedKeyframe).visible;

        }

        public virtual bool shouldRecache(int tick)
        {
            if (facingAtTick(tick) != facingAtTick(tick - 1)
                || visibleAtTick(tick) != visibleAtTick(tick - 1)
                || TexPathVariantAtTick(tick) != TexPathVariantAtTick(tick - 1))
            {
                return true;
            }

            return true;
        }

        public int? TexPathVariantAtTick(int tick)
        {

            //if ticks are < first keyframe tick, just be stuck to first keyframe rot
            if (tick <= this.part.keyframes[0].tick)
            {

                return (this.part.keyframes[0] as ExtendedKeyframe).variant;

            }

            //if ticks are > last keyframe tick, just be stuck to last keyframe rot
            if (tick >= this.part.keyframes[this.part.keyframes.Count - 1].tick)
            {

                return (this.part.keyframes[this.part.keyframes.Count - 1] as ExtendedKeyframe).variant;

            }
            Verse.Keyframe keyframe = this.part.keyframes[0];
            Verse.Keyframe keyframe2 = this.part.keyframes[this.part.keyframes.Count - 1];
            int i = 0;
            while (i < this.part.keyframes.Count)
            {
                if (tick <= this.part.keyframes[i].tick)
                {
                    keyframe2 = this.part.keyframes[i];
                    if (i > 0)
                    {
                        keyframe = this.part.keyframes[i - 1];
                        break;
                    }
                    break;
                }
                else
                {
                    i++;
                }
            }

            return (keyframe as ExtendedKeyframe).variant;

        }
    }
}


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

namespace Rimworld_Animations
{
    public abstract class BaseGroupAnimationContext
    {
        public int actorShift = 0;
        public int priority = 0;

        public List<BasePawnTest> whitelist;
        public List<BasePawnTest> blacklist;

        public virtual bool CanAnimationBeUsed(List<Pawn> actors, int numActors)
        {

            if (numActors != actors.Count)
            {
                return false;
            }

            if (!whitelist.NullOrEmpty())
            {
                for (int i = 0; i < whitelist.Count; i++)
                {
                    // check whitelist to make sure pawn can be in this act
                    //for each whitelist item, pawntest must hold true for that pawn
                    if (!whitelist[i].PawnTest(actors[i]))
                    {
                        return false;
                    }

                }
            }

            if (!blacklist.NullOrEmpty())
            {
                for (int i = 0; i < blacklist.Count; i++)
                {
                    // check blacklist to make sure pawn can be in this act
                    // for each blacklist item, pawntest must hold false for that pawn
                    if (blacklist[i].PawnTest(actors[i]))
                    {
                        return false;
                    }

                }
            }

            return true;
        }
        public virtual int AnimationReorder()
        {
            return actorShift;
        }
        public virtual int AnimationPriority()
        {
            return priority;
        }
        public abstract string DebugMessage();

        //cool class for designating contexts for animations
        // configure CanAnimationBeUsed to test whether it can be used
    }
}


code:
using RimWorld;
using rjw;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Verse;
using static rjw.xxx;

namespace Rimworld_Animations
{
    public class GroupAnimationContext_RJWSex : BaseGroupAnimationContext
    {

        public List<InteractionDef> interactionDefs;

        public override bool CanAnimationBeUsed(List<Pawn> actors, int numActors)
        {

            JobDriver_SexBaseInitiator latestSexBaseInitiator = (actors.FindLast(x => x.jobs?.curDriver is JobDriver_SexBaseInitiator).jobs.curDriver as JobDriver_SexBaseInitiator);

            if (!interactionDefs.Contains(latestSexBaseInitiator.Sexprops.dictionaryKey)) {
                return false;
            }

            return base.CanAnimationBeUsed(actors, numActors);
        }

        public override string DebugMessage()
        {
            return "Checking for RJWSex AnimationContext\n"
                + "InteractionDefs: " + interactionDefs;
        }
    }
}


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

namespace Rimworld_Animations
{
    public class GroupAnimationDef : Def
    {
        public int numActors;
        public List<AnimationStage> animationStages;
        public List<BaseGroupAnimationContext> contexts;
        public List<AnimationOffsetDef> offsetDefs;

        public bool canAnimationBeUsed(List<Pawn> actors)
        {

            if (!contexts.NullOrEmpty())
            {
                foreach (BaseGroupAnimationContext context in contexts)
                {
                    if (context.CanAnimationBeUsed(actors, numActors))
                    {
                        //find all where context matches actors
                        return true;

                    }
                }
            }

            return false;
        }

        public int Priority(List<Pawn> actors)
        {
            int priority = -999999999;

            foreach (BaseGroupAnimationContext context in contexts)
            {
                if (context.CanAnimationBeUsed(actors, numActors))
                {
                    if (context.AnimationPriority() > priority)
                    {
                        //get highest priority context for fitting animation
                        priority = context.AnimationPriority();

                    }

                }
            }

            return priority;

        }

        public int Reorder(List<Pawn> actors)
        {
            int priority = -999999999;
            int reorder = 0;

            foreach (BaseGroupAnimationContext context in contexts)
            {
                if (context.CanAnimationBeUsed(actors, numActors))
                {
                    if (context.AnimationPriority() > priority)
                    {
                        //get the reorder for highest priority context for fitting animation
                        priority = context.AnimationPriority();
                        reorder = context.AnimationReorder();

                    }

                }
            }

            return reorder;

        }

        public List<AnimationDef> GetAllAnimationsForActor(int actor, int seed, int reorder = 0)
        {
            List<AnimationDef> animations = new List<AnimationDef>();
            int actorNumber = (actor + reorder) % numActors;

            foreach (AnimationStage stage in animationStages)
            {
                //add all new animations to list of animations
                animations.AddRange(stage.GetAnimations(actorNumber, seed));
            }

            return animations;
        }

        public bool GetOffset(int actor, Pawn pawn, out Vector3? position, out int? rotation, int reorder = 0)
        {

            position = null;
            rotation = null;

            //element at or default to stop errors
            if (offsetDefs == null) return false;
            if ((actor + reorder) % numActors >= offsetDefs.Count) return false;
            if (offsetDefs[(actor + reorder) % numActors].FindOffset(pawn, out BaseAnimationOffset animationOffset))
            {
                position = animationOffset.getOffset(pawn);
                rotation = animationOffset.getRotation(pawn);
                return true;
            }

            return false;
        }
    }
}


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

namespace Rimworld_Animations
{
    public abstract class AnimationStage
    {

        //Return a list containing a tuple; int for how long the animation should play for
        public int loops;
        public abstract List<AnimationDef> GetAnimations(int actorNumber, int seed);

    }
}


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

namespace Rimworld_Animations
{
    public class AnimationStage_Branch : AnimationStage
    {
        public List<GroupAnimationDef> paths;
        public override List<AnimationDef> GetAnimations(int actorNumber, int seed)
        {
            List<AnimationDef> animationDefs = new List<AnimationDef>();

            for (int i = 0; i < loops; i++)
            {
                GroupAnimationDef selectedDef = paths[Rand.RangeSeeded(0, paths.Count, seed + i)];

                animationDefs.AddRange(selectedDef.GetAllAnimationsForActor(actorNumber, seed));

            }

            return animationDefs;
        }
    }
}


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

namespace Rimworld_Animations
{
    public class AnimationStage_LoopRandomSelectChance : AnimationStage
    {
        public List<AnimationLoopOption> loopOptions;

        public override List<AnimationDef> GetAnimations(int actorNumber, int seed)
        {
            int numberOfActors = loopOptions[0].animationDefs.Count;
            List<AnimationDef> animations = new List<AnimationDef>();

            for (int i = 0; i < loops; i++)
            {
                AnimationLoopOption option = getAnimationLoopOptionByWeight(seed + i);
                animations.Add(option.animationDefs[actorNumber]);
            }

            return animations;
        }

        //select random element from loop options by weight; also calculate the longest anim length
        private AnimationLoopOption getAnimationLoopOptionByWeight(int seed)
        {
            int totalWeight = loopOptions.Sum(x => x.probability);
            int randomNumber = Rand.RangeInclusiveSeeded(0, loopOptions.Count - 1, seed);

            int cumulativeWeight = 0;
            for (int i = 0; i < loopOptions.Count; i++) {

                cumulativeWeight += loopOptions[i].probability;

                //random number is same for all pawns because they all have the same seed

                if (randomNumber <= cumulativeWeight)
                {
                    return loopOptions[i];
                }
            }

            //default
            return loopOptions.Last();
        }
    }

    public class AnimationLoopOption
    {
        public int probability;
        public List<AnimationDef> animationDefs;
    }
}


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

namespace Rimworld_Animations
{
    /* don't use? just use looprandomselect once
    public class AnimationStage_TicksDuration : AnimationStage
    {
        public int ticks;
        public List<AnimationDef> animationDefs;

        public override List<Tuple<int, AnimationDef>> GetAnimations(int actor, int seed)
        {
            return new List<Tuple<int, AnimationDef>>() { Tuple.Create(ticks, animationDefs[actor]) };
        }
    }

    */
}


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

namespace Rimworld_Animations
{
    public class ExtendedKeyframe : Verse.Keyframe
    {
        public int? variant;
        public Rot4 rotation = Rot4.North;
        public SoundDef sound = null;
        public VoiceTagDef voice = null;
        public bool visible = false;
    }
}


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

namespace Rimworld_Animations
{
    public abstract class BasePawnTest
    {
        public abstract bool PawnTest(Pawn pawn);

    }
}


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

namespace Rimworld_Animations
{
    public class PawnTest_Always : BasePawnTest
    {
        public override bool PawnTest(Pawn pawn)
        {
            return true;
        }
    }
}


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

namespace Rimworld_Animations
{
    public class PawnTest_BodyType : BasePawnTest
    {
        public BodyTypeDef bodyType = null;
        public List<BodyTypeDef> bodyTypes = null;

        public override bool PawnTest(Pawn pawn)
        {

            if (pawn.story.bodyType == bodyType)
            {
                return true;
            }

            else if(bodyTypes != null && bodyTypes.Contains(pawn.story.bodyType))
            {
                return true;
            }

            return false;

        }
    }
}


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

namespace Rimworld_Animations
{
    public class PawnTest_Hediff : BasePawnTest
    {
        public HediffDef hediffDef; //hediff you want to check for
        float minSeverity = -1; //optional param; min severity the hediff needs to be

        public override bool PawnTest(Pawn pawn)
        {
            Hediff hediff = pawn.health.hediffSet.GetFirstHediffOfDef(hediffDef);

            if (hediff != null)
            {
                if (minSeverity != -1)
                {
                    return hediff.Severity > minSeverity;
                }

                return true;
            }

            return false;
        }
    }
}


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

namespace Rimworld_Animations
{
    public class PawnTest_Humanlike : BasePawnTest
    {
        public override bool PawnTest(Pawn pawn)
        {
            return pawn.RaceProps.Humanlike;
        }
    }
}


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

namespace Rimworld_Animations
{
    public class PawnTest_JobDef : BasePawnTest
    {
        public JobDef jobDef;

        public override bool PawnTest(Pawn pawn)
        {
            if (pawn.CurJobDef == jobDef)
            {
                return true;
            }
            return false;
        }
    }
}


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

namespace Rimworld_Animations
{
    public class PawnTest_Multi : BasePawnTest
    {
        public List<BasePawnTest> tests = new List<BasePawnTest>();
        public override bool PawnTest(Pawn pawn)
        {
            //check all different pawn tests in list for pawn
            foreach (BasePawnTest test in tests)
            {
                if (!test.PawnTest(pawn))
                {
                    return false;
                }
            }

            return true;
        }
    }
}


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

namespace Rimworld_Animations
{
    public class PawnTest_Never : BasePawnTest
    {
        public override bool PawnTest(Pawn pawn)
        {
            return false;
        }
    }
}


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

namespace Rimworld_Animations
{
    class PawnTest_PrisonerOfColony : BasePawnTest
    {
        public override bool PawnTest(Pawn pawn)
        {
            return pawn.IsPrisonerOfColony;
        }
    }
}


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

namespace Rimworld_Animations
{
    public class PawnTest_RJWCanBeFucked : BasePawnTest
    {
        public override bool PawnTest(Pawn pawn)
        {
            return xxx.can_be_fucked(pawn);
        }
    }
}


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

namespace Rimworld_Animations
{
    public class PawnTest_RJWCanFuck : BasePawnTest
    {
        public override bool PawnTest(Pawn pawn)
        {
            return xxx.can_fuck(pawn);
        }
    }
}


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

namespace Rimworld_Animations
{
    public class PawnTest_Race : BasePawnTest
    {

        public List<ThingDef> races = new List<ThingDef>();

        public override bool PawnTest(Pawn pawn)
        {

            foreach (ThingDef race in races)
            {
                if (pawn.def == race)
                {
                    return true;
                }
            }

            return false;

        }
    }
}


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

namespace Rimworld_Animations
{
    class PawnTest_SlaveOfColony : BasePawnTest
    {
        public override bool PawnTest(Pawn pawn)
        {
            return pawn.IsSlaveOfColony;
        }
    }
}


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

namespace Rimworld_Animations
{
    public class PawnTest_Trait : BasePawnTest
    {
        TraitDef traitDef;
        int? degree;

        public override bool PawnTest(Pawn pawn)
        {

            if (degree != null)
            {
                return pawn.story.traits.HasTrait(traitDef, (int)degree);
            }

            return pawn.story.traits.HasTrait(traitDef);
        }
    }
}


code:
using System;
using System.Collections.Generic;
using System.Linq;
using RimWorld;
using rjw;
using UnityEngine;
using Verse;
using Verse.AI;
using Verse.Sound;

namespace Rimworld_Animations {
    public class CompExtendedAnimator : ThingComp
    {

        // CompExtendedAnimator
        // Helps manage AnimationQueue, AbsolutePosition
        //ticks of current animation
        private int animationTicks;

        private List<AnimationDef> animationQueue;
        private BaseExtendedAnimatorAnchor anchor;
        private VoiceDef voice;

        private bool isAnimating = false;

        public bool IsAnimating
        {
            get
            {
                return isAnimating;
            }
        }

        public bool IsAnchored
        {
            get
            {
                return anchor != null;
            }
        }

        private Vector3? offset;

        public Vector3? Offset
        {
            get
            {
                return offset;
            }
            set
            {
                this.offset = value;
            }
        }

        private int? rotation;

        public int? Rotation
        {
            get
            {
                return rotation;
            }
            set
            {
                this.rotation = value;
            }
        }

        public int AnimationLength
        {
            get
            {
                if (!IsAnimating) return 0;

                int groupAnimLength = 0;
                foreach(AnimationDef anim in animationQueue)
                {
                    groupAnimLength += anim.durationTicks;
                }

                return groupAnimLength;

            }
        }

        public AnimationDef CurrentAnimation {

            get
            {
                return IsAnimating ? animationQueue[0] : null;
            }

        }

        public override void PostSpawnSetup(bool respawningAfterLoad)
        {
            if (voice == null)
            {
                AssignNewVoice();
            }

        }

        public Vector3 getAnchor()
        {
            return anchor.getDrawPos();
        }

        public override void CompTick()
        {
            if (isAnimating)
            {
                animationTicks++;

                //if animationticks is equal to cur. anim duration,
                if (animationTicks >= animationQueue[0].durationTicks)
                {
                    //dequeue; returns false if more animations
                    if (!PopAnimationQueue())
                    {
                        //play next if more anims still
                        PlayNextAnimation();
                    }
                    else
                    {
                        StopAnimating();
                    }
                }

                CheckAndPlaySounds();

            }

            base.CompTick();
        }

        //returns false if still more animations
        public bool PopAnimationQueue()
        {

            if (!animationQueue.Empty())
            {
                //pop queue
                animationQueue.RemoveAt(0);
            }

            return animationQueue.Empty();
        }

        public void PlayNextAnimation()
        {
            if (!animationQueue.Empty())
            {
                isAnimating = true;
                animationTicks = 0;
                pawn.Drawer.renderer.SetAnimation(animationQueue[0]);
            }
        }

        public void StopAnimating()
        {
            isAnimating = false;
            animationQueue = null;
            anchor = null;
            offset = null;
            pawn.Drawer.renderer.SetAnimation(null);

            pawn.Drawer.renderer.SetAllGraphicsDirty();
        }

        public void PlayGroupAnimation(List<AnimationDef> groupAnimation, Vector3? positionOffset, int? rotationOffset)
        {
            this.Offset = positionOffset;
            this.Rotation = rotationOffset;
            animationQueue = groupAnimation;

            //set all graphics dirty; necessary because sometimes rjw doesn't call during threesomes
            pawn.Drawer.renderer.SetAllGraphicsDirty();

            PlayNextAnimation();
        }

        public void PlayGroupAnimation(List<AnimationDef> groupAnimation, Vector3? positionOffset, int? rotationOffset, BaseExtendedAnimatorAnchor anchor)
        {
            this.anchor = anchor;
            PlayGroupAnimation(groupAnimation, positionOffset, rotationOffset);
        }

        public override void PostExposeData()
        {
            base.PostExposeData();
            Scribe_Values.Look<bool>(ref this.isAnimating, "animations_isAnimating", false);
            Scribe_Values.Look<int>(ref this.animationTicks, "animations_ticks", 0);
            Scribe_Collections.Look<AnimationDef>(ref animationQueue, "animations_queue");
            Scribe_Deep.Look<BaseExtendedAnimatorAnchor>(ref this.anchor, "animations_anchor");
            Scribe_Defs.Look<VoiceDef>(ref this.voice, "animations_voice");

        }

        public override List<PawnRenderNode> CompRenderNodes()
        {
            //only if pawn is animating for performance
            if (IsAnimating)
            {

                List<PawnRenderNode> animRenderNodes = new List<PawnRenderNode>();

                // for all animationpropdefs,
                foreach (AnimationPropDef animationProp in DefDatabase<AnimationPropDef>.AllDefsListForReading)
                {
                    //if animation makes use of prop,
                    if (AnimationMakesUseOfProp(animationProp))
                    {
                        PawnRenderNodeProperties props = animationProp.animPropProperties;

                        if (props.texPath.NullOrEmpty())
                        {

                            props.texPath = "AnimationProps/MissingTexture/MissingTexture";
                        }

                        //create new render node
                        PawnRenderNode animRenderNode = (PawnRenderNode)Activator.CreateInstance(props.nodeClass, new object[] {
                            this.pawn,
                            props,
                            pawn.Drawer.renderer.renderTree
                        });

                        animRenderNodes.Add(animRenderNode);
                    }

                }

                //return list of rendernodes that should animate
                return animRenderNodes;

            }
            else
            {
                return null;
            }

        }

        public void AssignNewVoice()
        {
            //all voice options
            List<VoiceDef> voiceOptions =
                DefDatabase<VoiceDef>.AllDefsListForReading
                .FindAll(voiceDef => voiceDef.VoiceFitsPawn(pawn));

            //all voice options, with priority (for traitdef specific voices)
            List<VoiceDef> voiceOptionsWithPriority =
                voiceOptions.FindAll(voiceDef => voiceDef.takesPriority);

            if (!voiceOptionsWithPriority.NullOrEmpty())
            {
                voice = voiceOptionsWithPriority.RandomElementByWeight(x => x.randomChanceFactor);

            }
            else if (!voiceOptions.NullOrEmpty())
            {
                voice = voiceOptions.RandomElementByWeight(x => x.randomChanceFactor);
            }

        }

        public void CheckAndPlaySounds()
        {

            PawnRenderNode rootNode = pawn.Drawer?.renderer?.renderTree?.rootNode;

            //check if the rootnode has sounds; if so play it
            if (rootNode?.AnimationWorker is AnimationWorker_KeyframesExtended animWorker)
            {
                SoundDef sound = animWorker.soundAtTick(rootNode.tree.AnimationTick);

                if (sound != null)
                {
                    SoundInfo soundInfo = new TargetInfo(pawn.Position, pawn.Map);

                    //temp; does not consider non-rjw animations
                    //todo: replace with value stored in comp or somewhere else?
                    soundInfo.volumeFactor = RJWSettings.sounds_sex_volume;

                    sound.PlayOneShot(soundInfo);
                }

                if (RJWAnimationSettings.playVoices)
                {
                    SoundInfo voiceInfo = new TargetInfo(pawn.Position, pawn.Map);
                    voiceInfo.volumeFactor = RJWSettings.sounds_voice_volume;

                    //play voice sounds
                    VoiceTagDef voiceTag = animWorker.voiceAtTick(rootNode.tree.AnimationTick);
                    if (voiceTag != null)
                    {
                        if (voice != null && voice.sounds.ContainsKey(voiceTag))
                        {
                            voice.sounds[voiceTag].PlayOneShot(voiceInfo);
                        }

                        else if (pawn.RaceProps.Humanlike && RJWAnimationSettings.playHumanlikeVoicesAsDefault)
                        {
                            //play default voice
                            VoiceDef pawnDefaultVoice = (pawn.gender == Gender.Male ? VoiceDefOf.Voice_HumanMale : VoiceDefOf.Voice_HumanFemale);
                            if (pawnDefaultVoice.sounds.ContainsKey(voiceTag))
                            {
                                pawnDefaultVoice.sounds[voiceTag].PlayOneShot(voiceInfo);
                            }

                        }

                    }
                }

            }

            //check rootnodes and children
            if (rootNode?.children != null)
            {
                foreach (PawnRenderNode node in rootNode?.children)
                {
                    if (node?.AnimationWorker is AnimationWorker_KeyframesExtended childrenAnimWorker)
                    {

                        SoundDef sound = childrenAnimWorker.soundAtTick(node.tree.AnimationTick);
                        if (sound != null)
                        {
                            SoundInfo soundInfo = new TargetInfo(pawn.Position, pawn.Map);
                            soundInfo.volumeFactor = RJWSettings.sounds_sex_volume;
                            sound.PlayOneShot(soundInfo);
                        }

                        if (RJWAnimationSettings.playVoices)
                        {

                            SoundInfo voiceInfo = new TargetInfo(pawn.Position, pawn.Map);
                            voiceInfo.volumeFactor = RJWSettings.sounds_voice_volume;

                            //play voice sounds
                            VoiceTagDef voiceTag = childrenAnimWorker.voiceAtTick(rootNode.tree.AnimationTick);
                            if (voiceTag != null)
                            {
                                if (voice != null && voice.sounds.ContainsKey(voiceTag))
                                {
                                    voice.sounds[voiceTag].PlayOneShot(voiceInfo);
                                }
                                else if (pawn.RaceProps.Humanlike && RJWAnimationSettings.playHumanlikeVoicesAsDefault)
                                {

                                    VoiceDef pawnDefaultVoice = (pawn.gender == Gender.Male ? VoiceDefOf.Voice_HumanMale : VoiceDefOf.Voice_HumanFemale);
                                    if (pawnDefaultVoice.sounds.ContainsKey(voiceTag))
                                    {
                                        pawnDefaultVoice.sounds[voiceTag].PlayOneShot(voiceInfo);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            //do the same for all the child nodes

        }

        public bool AnimationMakesUseOfProp(AnimationPropDef animationProp)
        {
            // never true if not animating; anim props shouldn't be attached
            if (!IsAnimating) return false;

            //for all anims in queue (because it's only recached at start)
            foreach (AnimationDef animation in animationQueue)
            {
                foreach (PawnRenderNodeTagDef propTag in animation.animationParts.Keys)
                {

                    // if that proptag is the same as the one for animationProp,
                    if (propTag == animationProp.animPropProperties.tagDef)
                    {
                        //that prop is being used in the animation
                        return true;
                    }
                }

            }

            return false;
        }

        private Pawn pawn => base.parent as Pawn;

    }

}


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

namespace Rimworld_Animations {
    public class CompProperties_ExtendedAnimator : CompProperties
    {
        public CompProperties_ExtendedAnimator()
        {
            base.compClass = typeof(CompExtendedAnimator);

        }
    }
}


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

namespace Rimworld_Animations {
    public class CompProperties_ThingAnimator : CompProperties
    {

        public CompProperties_ThingAnimator()
        {
            base.compClass = typeof(CompThingAnimator);
        }
    }
}


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

namespace Rimworld_Animations {
    public class CompThingAnimator : ThingComp
    {

        public override void CompTick()
        {
            //todo: If item is held by pawn, and pawn is doing thingcomp animation,
            //animate thingcomp; see CompPowerPlantWind for how thingcomps are animated
            return;
        }
    }

}


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

namespace Rimworld_Animations
{
    public abstract class BaseExtendedAnimatorAnchor : IExposable
    {
        public BaseExtendedAnimatorAnchor() { }

        public virtual void ExposeData() { }
        public abstract Vector3 getDrawPos();

        public string GetUniqueLoadID()
        {
            throw new NotImplementedException();
        }
    }
}


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

namespace Rimworld_Animations
{
    public class ExtendedAnimatorAnchor_Thing : BaseExtendedAnimatorAnchor
    {

        private Thing thing;

        public ExtendedAnimatorAnchor_Thing() : base() { }

        public ExtendedAnimatorAnchor_Thing(Thing thing) : base()
        {
            this.thing = thing;
        }

        public override Vector3 getDrawPos()
        {
            //x and z position, regular altitude for pawns
            return new Vector3(thing.DrawPos.x, AltitudeLayer.Pawn.AltitudeFor(), thing.DrawPos.z);
        }

        public override void ExposeData()
        {
            base.ExposeData();
            Scribe_References.Look<Thing>(ref this.thing, "animations_anchor_thing", false);
        }
    }
}


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

namespace Rimworld_Animations
{
    public class ExtendedAnimatorAnchor_Vector3 : BaseExtendedAnimatorAnchor
    {

        public ExtendedAnimatorAnchor_Vector3() : base() { }

        private Vector3 position;
        public ExtendedAnimatorAnchor_Vector3(Vector3 position) : base()
        {
            //default to altitude for layer for y
            this.position = new Vector3(position.x, AltitudeLayer.Pawn.AltitudeFor(), position.z);
        }

        public override Vector3 getDrawPos()
        {
            return position;
        }

        public override void ExposeData()
        {
            base.ExposeData();
            Scribe_Values.Look<Vector3>(ref position, "animations_anchor_position", Vector3.zero);
        }
    }
}


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

namespace Rimworld_Animations
{
    [DefOf]
    public static class AnimationDefOf
    {
        static AnimationDefOf()
        {
            DefOfHelper.EnsureInitializedInCtor(typeof(AnimationDefOf));
        }

        public static AnimationDef TestAnimation1;
        public static AnimationDef TestAnimation2;
    }
}