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

<Defs>
  <Rimworld_Animations.AnimationDef>
    <defName>Doggystyle</defName>
    doggystyle
    <sounds>true</sounds>
    <actors>

        <defNames>

Human

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

        <defNames>

Human

        </defNames>
        <isFucking>true</isFucking>

    </actors>

    <animationStages>

        <stageName>Slow_Fuck</stageName>
        <isLooping>true</isLooping>
        <playTimeTicks>612</playTimeTicks>
        <stageIndex>0</stageIndex>
        <animationClips>

            <keyframes>

                <headBob>0</headBob>
                <tickDuration>10</tickDuration>
                <bodyAngle>27</bodyAngle>
                <bodyOffsetX>0.298</bodyOffsetX>
                <bodyOffsetZ>0.166</bodyOffsetZ>
                <headAngle>0</headAngle>
                <bodyFacing>1</bodyFacing>
                <headFacing>2</headFacing>

                <tickDuration>40</tickDuration>
                <bodyAngle>32</bodyAngle>
                <bodyOffsetX>0.326</bodyOffsetX>
                <bodyOffsetZ>0.190</bodyOffsetZ>
                <bodyFacing>1</bodyFacing>
                <headFacing>2</headFacing>

                <tickDuration>1</tickDuration>
                <bodyAngle>27</bodyAngle>
                <bodyOffsetX>0.298</bodyOffsetX>
                <bodyOffsetZ>0.166</bodyOffsetZ>
                <bodyFacing>1</bodyFacing>
                <headFacing>2</headFacing>

                <tickDuration>10</tickDuration>
                <bodyAngle>27</bodyAngle>
                <bodyOffsetX>0.298</bodyOffsetX>
                <bodyOffsetZ>0.166</bodyOffsetZ>
                <bodyFacing>1</bodyFacing>
                <headFacing>2</headFacing>

                <tickDuration>40</tickDuration>
                <bodyAngle>32</bodyAngle>
                <bodyOffsetX>0.326</bodyOffsetX>
                <bodyOffsetZ>0.190</bodyOffsetZ>
                <bodyFacing>1</bodyFacing>
                <headFacing>2</headFacing>

                <tickDuration>1</tickDuration>
                <bodyAngle>27</bodyAngle>
                <bodyOffsetX>0.298</bodyOffsetX>
                <bodyOffsetZ>0.166</bodyOffsetZ>
                <bodyFacing>1</bodyFacing>
                <headFacing>2</headFacing>

                <tickDuration>10</tickDuration>
                <bodyAngle>27</bodyAngle>
                <bodyOffsetX>0.298</bodyOffsetX>
                <bodyOffsetZ>0.166</bodyOffsetZ>
                <bodyFacing>1</bodyFacing>
                <headFacing>2</headFacing>

                <tickDuration>40</tickDuration>
                <bodyAngle>32</bodyAngle>
                <bodyOffsetX>0.326</bodyOffsetX>
                <bodyOffsetZ>0.190</bodyOffsetZ>
                <bodyFacing>1</bodyFacing>
                <headFacing>2</headFacing>

                <tickDuration>1</tickDuration>
                <bodyAngle>27</bodyAngle>
                <bodyOffsetX>0.298</bodyOffsetX>
                <bodyOffsetZ>0.166</bodyOffsetZ>
                <bodyFacing>1</bodyFacing>
                <headFacing>2</headFacing>

                <tickDuration>10</tickDuration>
                <bodyAngle>27</bodyAngle>
                <bodyOffsetX>0.298</bodyOffsetX>
                <bodyOffsetZ>0.166</bodyOffsetZ>
                <bodyFacing>1</bodyFacing>
                <headFacing>1</headFacing>

                <tickDuration>40</tickDuration>
                <bodyAngle>32</bodyAngle>
                <bodyOffsetX>0.326</bodyOffsetX>
                <bodyOffsetZ>0.190</bodyOffsetZ>
                <bodyFacing>1</bodyFacing>
                <headFacing>1</headFacing>

                <tickDuration>1</tickDuration>
                <bodyAngle>27</bodyAngle>
                <bodyOffsetX>0.298</bodyOffsetX>
                <bodyOffsetZ>0.166</bodyOffsetZ>
                <bodyFacing>1</bodyFacing>
                <headFacing>1</headFacing>

                <tickDuration>10</tickDuration>
                <bodyAngle>27</bodyAngle>
                <bodyOffsetX>0.298</bodyOffsetX>
                <bodyOffsetZ>0.166</bodyOffsetZ>
                <bodyFacing>1</bodyFacing>
                <headFacing>1</headFacing>

                <tickDuration>40</tickDuration>
                <bodyAngle>32</bodyAngle>
                <bodyOffsetX>0.326</bodyOffsetX>
                <bodyOffsetZ>0.190</bodyOffsetZ>
                <bodyFacing>1</bodyFacing>
                <headFacing>1</headFacing>

                <tickDuration>1</tickDuration>
                <bodyAngle>27</bodyAngle>
                <bodyOffsetX>0.298</bodyOffsetX>
                <bodyOffsetZ>0.166</bodyOffsetZ>
                <bodyFacing>1</bodyFacing>
                <headFacing>1</headFacing>

                <tickDuration>10</tickDuration>
                <bodyAngle>27</bodyAngle>
                <bodyOffsetX>0.298</bodyOffsetX>
                <bodyOffsetZ>0.166</bodyOffsetZ>
                <bodyFacing>1</bodyFacing>
                <headFacing>1</headFacing>

                <tickDuration>40</tickDuration>
                <bodyAngle>32</bodyAngle>
                <bodyOffsetX>0.326</bodyOffsetX>
                <bodyOffsetZ>0.190</bodyOffsetZ>
                <bodyFacing>1</bodyFacing>
                <headFacing>1</headFacing>

                <tickDuration>1</tickDuration>
                <bodyAngle>27</bodyAngle>
                <bodyOffsetX>0.298</bodyOffsetX>
                <bodyOffsetZ>0.166</bodyOffsetZ>
                <bodyFacing>1</bodyFacing>
                <headFacing>1</headFacing>

                <tickDuration>10</tickDuration>
                <bodyAngle>27</bodyAngle>
                <bodyOffsetX>0.298</bodyOffsetX>
                <bodyOffsetZ>0.166</bodyOffsetZ>
                <bodyFacing>1</bodyFacing>
                <headFacing>1</headFacing>

                <tickDuration>40</tickDuration>
                <bodyAngle>32</bodyAngle>
                <bodyOffsetX>0.326</bodyOffsetX>
                <bodyOffsetZ>0.190</bodyOffsetZ>
                <bodyFacing>1</bodyFacing>
                <headFacing>1</headFacing>

                <tickDuration>1</tickDuration>
                <bodyAngle>27</bodyAngle>
                <bodyOffsetX>0.298</bodyOffsetX>
                <bodyOffsetZ>0.166</bodyOffsetZ>
                <bodyFacing>1</bodyFacing>
                <headFacing>1</headFacing>

                <tickDuration>10</tickDuration>
                <bodyAngle>27</bodyAngle>
                <bodyOffsetX>0.298</bodyOffsetX>
                <bodyOffsetZ>0.166</bodyOffsetZ>
                <bodyFacing>1</bodyFacing>
                <headFacing>1</headFacing>

                <tickDuration>40</tickDuration>
                <bodyAngle>32</bodyAngle>
                <bodyOffsetX>0.326</bodyOffsetX>
                <bodyOffsetZ>0.190</bodyOffsetZ>
                <bodyFacing>1</bodyFacing>
                <headFacing>1</headFacing>

                <headBob>0</headBob>
                <tickDuration>1</tickDuration>
                <bodyAngle>27</bodyAngle>
                <bodyOffsetX>0.298</bodyOffsetX>
                <bodyOffsetZ>0.166</bodyOffsetZ>
                <headAngle>0</headAngle>
                <bodyFacing>1</bodyFacing>
                <headFacing>1</headFacing>

            </keyframes>

            <layer>LayingPawn</layer>
            <keyframes>

                <headBob>0</headBob>
                <tickDuration>10</tickDuration>
                <bodyAngle>16.6</bodyAngle>
                <bodyOffsetX>-0.217</bodyOffsetX>
                <bodyOffsetZ>0.175</bodyOffsetZ>
                <headAngle>3</headAngle>
                <bodyFacing>1</bodyFacing>
                <headFacing>1</headFacing>

                <tickDuration>40</tickDuration>
                <soundEffect>Fuck</soundEffect>
                <bodyAngle>-17</bodyAngle>
                <bodyOffsetX>-0.217</bodyOffsetX>
                <bodyOffsetZ>0.272</bodyOffsetZ>
                <headAngle>5.4</headAngle>
                <bodyFacing>1</bodyFacing>
                <headFacing>1</headFacing>

                <tickDuration>1</tickDuration>
                <bodyAngle>16.6</bodyAngle>
                <bodyOffsetX>-0.217</bodyOffsetX>
                <bodyOffsetZ>0.175</bodyOffsetZ>
                <headAngle>3</headAngle>
                <bodyFacing>1</bodyFacing>
                <headFacing>1</headFacing>
                <headBob>0</headBob>

            </keyframes>

        </animationClips>

        <stageName>Fast_Fuck</stageName>
        <isLooping>true</isLooping>
        <playTimeTicks>609</playTimeTicks>
        <stageIndex>0</stageIndex>
        <animationClips>

            <keyframes>

                <tickDuration>8</tickDuration>
                <bodyAngle>27</bodyAngle>
                <bodyOffsetX>0.298</bodyOffsetX>
                <bodyOffsetZ>0.166</bodyOffsetZ>
                <headAngle>1</headAngle>
                <bodyFacing>1</bodyFacing>
                <headFacing>1</headFacing>
                <headBob>0</headBob>

                <tickDuration>12</tickDuration>
                <bodyAngle>32</bodyAngle>
                <bodyOffsetX>0.326</bodyOffsetX>
                <bodyOffsetZ>0.190</bodyOffsetZ>
                <headAngle>4</headAngle>
                <bodyFacing>1</bodyFacing>
                <headFacing>1</headFacing>

                <tickDuration>1</tickDuration>
                <bodyAngle>27</bodyAngle>
                <bodyOffsetX>0.298</bodyOffsetX>
                <bodyOffsetZ>0.166</bodyOffsetZ>
                <headAngle>1</headAngle>
                <bodyFacing>1</bodyFacing>
                <headFacing>1</headFacing>
                <headBob>0</headBob>

            </keyframes>

            <layer>LayingPawn</layer>
            <keyframes>

                <tickDuration>8</tickDuration>
                <bodyAngle>11</bodyAngle>
                <bodyOffsetX>-0.217</bodyOffsetX>
                <bodyOffsetZ>0.175</bodyOffsetZ>
                <headAngle>8</headAngle>
                <bodyFacing>1</bodyFacing>
                <headFacing>1</headFacing>
                <headBob>0</headBob>

                <tickDuration>12</tickDuration>
                <soundEffect>Fuck</soundEffect>
                <bodyAngle>-12</bodyAngle>
                <bodyOffsetX>-0.217</bodyOffsetX>
                <bodyOffsetZ>0.272</bodyOffsetZ>
                <headAngle>9</headAngle>
                <bodyFacing>1</bodyFacing>
                <headFacing>1</headFacing>

                <tickDuration>1</tickDuration>
                <bodyAngle>11</bodyAngle>
                <bodyOffsetX>-0.217</bodyOffsetX>
                <bodyOffsetZ>0.175</bodyOffsetZ>
                <headAngle>8</headAngle>
                <bodyFacing>1</bodyFacing>
                <headFacing>1</headFacing>
                <headBob>0</headBob>

            </keyframes>

        </animationClips>

        <stageName>Cum</stageName>
        <isLooping>true</isLooping>
        <playTimeTicks>300</playTimeTicks>
        <stageIndex>0</stageIndex>
        <animationClips>

            <keyframes>

                <tickDuration>8</tickDuration>
                <bodyAngle>27</bodyAngle>
                <bodyOffsetX>0.298</bodyOffsetX>
                <bodyOffsetZ>0.166</bodyOffsetZ>
                <headAngle>0</headAngle>
                <bodyFacing>1</bodyFacing>
                <headFacing>1</headFacing>
                <headBob>0</headBob>

                <soundEffect>Cum</soundEffect>
                <tickDuration>100</tickDuration>
                <bodyAngle>32</bodyAngle>
                <bodyOffsetX>0.326</bodyOffsetX>
                <bodyOffsetZ>0.190</bodyOffsetZ>
                <headAngle>-1</headAngle>
                <bodyFacing>1</bodyFacing>
                <headFacing>1</headFacing>

                <tickDuration>12</tickDuration>
                <bodyAngle>35</bodyAngle>
                <bodyOffsetX>0.326</bodyOffsetX>
                <bodyOffsetZ>0.190</bodyOffsetZ>
                <headAngle>-14</headAngle>
                <bodyFacing>1</bodyFacing>
                <headFacing>1</headFacing>

                <tickDuration>1</tickDuration>
                <bodyAngle>27</bodyAngle>
                <bodyOffsetX>0.298</bodyOffsetX>
                <bodyOffsetZ>0.166</bodyOffsetZ>
                <headAngle>0</headAngle>
                <bodyFacing>1</bodyFacing>
                <headFacing>1</headFacing>
                <headBob>0</headBob>

            </keyframes>

            <layer>LayingPawn</layer>
            <keyframes>

                <tickDuration>8</tickDuration>
                <bodyAngle>11</bodyAngle>
                <bodyOffsetX>-0.217</bodyOffsetX>
                <bodyOffsetZ>0.175</bodyOffsetZ>
                <headAngle>-8</headAngle>
                <bodyFacing>1</bodyFacing>
                <headFacing>1</headFacing>
                <headBob>0</headBob>

                <tickDuration>100</tickDuration>
                <bodyAngle>-12</bodyAngle>
                <bodyOffsetX>-0.217</bodyOffsetX>
                <bodyOffsetZ>0.272</bodyOffsetZ>
                <headAngle>-9</headAngle>
                <bodyFacing>1</bodyFacing>
                <headFacing>1</headFacing>

                <tickDuration>12</tickDuration>
                <bodyAngle>-15</bodyAngle>
                <bodyOffsetX>-0.227</bodyOffsetX>
                <bodyOffsetZ>0.272</bodyOffsetZ>
                <headAngle>-4</headAngle>
                <bodyFacing>1</bodyFacing>
                <headFacing>1</headFacing>

                <tickDuration>1</tickDuration>
                <bodyAngle>11</bodyAngle>
                <bodyOffsetX>-0.217</bodyOffsetX>
                <bodyOffsetZ>0.175</bodyOffsetZ>
                <headAngle>-8</headAngle>
                <bodyFacing>1</bodyFacing>
                <headFacing>1</headFacing>
                <headBob>0</headBob>

            </keyframes>

        </animationClips>

    </animationStages>
  </Rimworld_Animations.AnimationDef>
  <Rimworld_Animations.AnimationDef>
    <defName>Blowjob</defName>
    blowjob
    <sounds>true</sounds>
    <actors>

        <defNames>

Human

        </defNames>

        <defNames>

Human

        </defNames>
        <isFucking>true</isFucking>

    </actors>
    <animationStages>

        <stageName>Slow_Suck</stageName>
        <isLooping>true</isLooping>
        <playTimeTicks>1140</playTimeTicks>
        <stageIndex>0</stageIndex>
        <animationClips>

            <keyframes>

                <tickDuration>35</tickDuration>
                <bodyAngle>0</bodyAngle>
                <headAngle>0</headAngle>
                <bodyOffsetX>0</bodyOffsetX>
                <bodyOffsetZ>-0.255</bodyOffsetZ>
                <bodyFacing>0</bodyFacing>
                <headFacing>0</headFacing>
                <headBob>0</headBob>

                <soundEffect>Suck</soundEffect>
                <tickDuration>59</tickDuration>
                <bodyAngle>0</bodyAngle>
                <bodyOffsetX>0</bodyOffsetX>
                <bodyOffsetZ>-0.33</bodyOffsetZ>
                <bodyFacing>0</bodyFacing>
                <headFacing>0</headFacing>
                <headBob>-0.16</headBob>

                <tickDuration>1</tickDuration>
                <bodyAngle>0</bodyAngle>
                <headAngle>0</headAngle>
                <bodyOffsetX>0</bodyOffsetX>
                <bodyOffsetZ>-0.255</bodyOffsetZ>
                <bodyFacing>0</bodyFacing>
                <headFacing>0</headFacing>
                <headBob>0</headBob>

                <tickDuration>35</tickDuration>
                <bodyAngle>0</bodyAngle>
                <headAngle>0</headAngle>
                <bodyOffsetX>0</bodyOffsetX>
                <bodyOffsetZ>-0.255</bodyOffsetZ>
                <bodyFacing>0</bodyFacing>
                <headFacing>0</headFacing>
                <headBob>0</headBob>

                <soundEffect>Suck</soundEffect>
                <tickDuration>59</tickDuration>
                <bodyAngle>0</bodyAngle>
                <bodyOffsetX>0</bodyOffsetX>
                <bodyOffsetZ>-0.33</bodyOffsetZ>
                <bodyFacing>0</bodyFacing>
                <headFacing>0</headFacing>
                <headBob>-0.15</headBob>

                <tickDuration>1</tickDuration>
                <bodyAngle>0</bodyAngle>
                <headAngle>0</headAngle>
                <bodyOffsetX>0</bodyOffsetX>
                <bodyOffsetZ>-0.255</bodyOffsetZ>
                <bodyFacing>0</bodyFacing>
                <headFacing>0</headFacing>
                <headBob>0</headBob>

                <tickDuration>35</tickDuration>
                <bodyAngle>0</bodyAngle>
                <headAngle>0</headAngle>
                <bodyOffsetX>0</bodyOffsetX>
                <bodyOffsetZ>-0.255</bodyOffsetZ>
                <bodyFacing>0</bodyFacing>
                <headFacing>0</headFacing>
                <headBob>0</headBob>

                <soundEffect>Suck</soundEffect>
                <tickDuration>59</tickDuration>
                <bodyAngle></bodyAngle>
                <headAngle>6</headAngle>
                <bodyOffsetX>0</bodyOffsetX>
                <bodyOffsetZ>-0.33</bodyOffsetZ>
                <bodyFacing>0</bodyFacing>
                <headFacing>0</headFacing>
                <headBob>-0.13</headBob>

                <tickDuration>1</tickDuration>
                <bodyAngle>0</bodyAngle>
                <headAngle>0</headAngle>
                <bodyOffsetX>0</bodyOffsetX>
                <bodyOffsetZ>-0.255</bodyOffsetZ>
                <bodyFacing>0</bodyFacing>
                <headFacing>0</headFacing>
                <headBob>0</headBob>

                <tickDuration>35</tickDuration>
                <bodyAngle>0</bodyAngle>
                <headAngle>0</headAngle>
                <bodyOffsetX>0</bodyOffsetX>
                <bodyOffsetZ>-0.255</bodyOffsetZ>
                <bodyFacing>0</bodyFacing>
                <headFacing>0</headFacing>
                <headBob>0</headBob>

                <soundEffect>Suck</soundEffect>
                <tickDuration>59</tickDuration>
                <bodyAngle>0</bodyAngle>
                <headAngle>-4</headAngle>
                <bodyOffsetX>0</bodyOffsetX>
                <bodyOffsetZ>-0.33</bodyOffsetZ>
                <bodyFacing>0</bodyFacing>
                <headFacing>0</headFacing>
                <headBob>-0.12</headBob>

                <tickDuration>1</tickDuration>
                <bodyAngle>0</bodyAngle>
                <headAngle>0</headAngle>
                <bodyOffsetX>0</bodyOffsetX>
                <bodyOffsetZ>-0.255</bodyOffsetZ>
                <bodyFacing>0</bodyFacing>
                <headFacing>0</headFacing>
                <headBob>0</headBob>

            </keyframes>

            <keyframes>

                <tickDuration>35</tickDuration>
                <bodyAngle>0</bodyAngle>
                <headAngle>0</headAngle>
                <bodyOffsetX>0</bodyOffsetX>
                <bodyOffsetZ>0.473</bodyOffsetZ>
                <bodyFacing>2</bodyFacing>
                <headFacing>2</headFacing>
                <headBob>0</headBob>

                <tickDuration>59</tickDuration>
                <bodyAngle>0</bodyAngle>
                <bodyOffsetX>0</bodyOffsetX>
                <bodyOffsetZ>0.490</bodyOffsetZ>
                <bodyFacing>2</bodyFacing>
                <headFacing>2</headFacing>
                <headBob>-0.003</headBob>

                <tickDuration>1</tickDuration>
                <bodyAngle>0</bodyAngle>
                <headAngle>0</headAngle>
                <bodyOffsetX>0</bodyOffsetX>
                <bodyOffsetZ>0.473</bodyOffsetZ>
                <bodyFacing>2</bodyFacing>
                <headFacing>2</headFacing>
                <headBob>0</headBob>

            </keyframes>

        </animationClips>

        <stageName>Face_Fuck</stageName>
        <isLooping>true</isLooping>
        <playTimeTicks>300</playTimeTicks>
        <stageIndex>0</stageIndex>
        <animationClips>

            <keyframes>

                <tickDuration>15</tickDuration>
                <bodyAngle>0</bodyAngle>
                <headAngle>0</headAngle>
                <bodyOffsetX>0</bodyOffsetX>
                <bodyOffsetZ>-0.255</bodyOffsetZ>
                <bodyFacing>0</bodyFacing>
                <headFacing>0</headFacing>
                <headBob>0</headBob>

                <soundEffect>Suck</soundEffect>
                <tickDuration>14</tickDuration>
                <bodyAngle>0</bodyAngle>
                <bodyOffsetX>0</bodyOffsetX>
                <bodyOffsetZ>-0.270</bodyOffsetZ>
                <bodyFacing>0</bodyFacing>
                <headFacing>0</headFacing>
                <headBob>-0.06</headBob>

                <tickDuration>1</tickDuration>
                <bodyAngle>0</bodyAngle>
                <headAngle>0</headAngle>
                <bodyOffsetX>0</bodyOffsetX>
                <bodyOffsetZ>-0.255</bodyOffsetZ>
                <bodyFacing>0</bodyFacing>
                <headFacing>0</headFacing>
                <headBob>0</headBob>

            </keyframes>

            <keyframes>

                <tickDuration>15</tickDuration>
                <bodyAngle>0</bodyAngle>
                <headAngle>0</headAngle>
                <bodyOffsetX>0</bodyOffsetX>
                <bodyOffsetZ>0.473</bodyOffsetZ>
                <bodyFacing>2</bodyFacing>
                <headFacing>2</headFacing>
                <headBob>0</headBob>

                <tickDuration>14</tickDuration>
                <bodyAngle>0</bodyAngle>
                <bodyOffsetX>0</bodyOffsetX>
                <bodyOffsetZ>0.575</bodyOffsetZ>
                <bodyFacing>2</bodyFacing>
                <headFacing>2</headFacing>
                <headBob>-0.051</headBob>

                <tickDuration>1</tickDuration>
                <bodyAngle>0</bodyAngle>
                <headAngle>0</headAngle>
                <bodyOffsetX>0</bodyOffsetX>
                <bodyOffsetZ>0.473</bodyOffsetZ>
                <bodyFacing>2</bodyFacing>
                <headFacing>2</headFacing>
                <headBob>0</headBob>

            </keyframes>

        </animationClips>

        <stageName>Cum</stageName>
        <isLooping>true</isLooping>
        <playTimeTicks>600</playTimeTicks>
        <stageIndex>0</stageIndex>
        <animationClips>

            <keyframes>

                <tickDuration>12</tickDuration>
                <bodyAngle>0</bodyAngle>
                <headAngle>0</headAngle>
                <bodyOffsetX>0</bodyOffsetX>
                <bodyOffsetZ>-0.255</bodyOffsetZ>
                <bodyFacing>0</bodyFacing>
                <headFacing>0</headFacing>
                <headBob>0</headBob>

                <tickDuration>7</tickDuration>
                <bodyAngle>0</bodyAngle>
                <bodyOffsetX>0</bodyOffsetX>
                <bodyOffsetZ>-0.290</bodyOffsetZ>
                <bodyFacing>0</bodyFacing>
                <headFacing>0</headFacing>
                <headBob>-0.06</headBob>

                <tickDuration>7</tickDuration>
                <soundEffect>Suck</soundEffect>
                <bodyAngle>0</bodyAngle>
                <bodyOffsetX>0</bodyOffsetX>
                <bodyOffsetZ>-0.290</bodyOffsetZ>
                <bodyFacing>0</bodyFacing>
                <headFacing>0</headFacing>
                <headBob>-0.008</headBob>

                <tickDuration>60</tickDuration>
                <bodyAngle>0</bodyAngle>
                <bodyOffsetX>0</bodyOffsetX>
                <bodyOffsetZ>-0.290</bodyOffsetZ>
                <bodyFacing>0</bodyFacing>
                <headFacing>0</headFacing>
                <headBob>-0.06</headBob>

                <tickDuration>14</tickDuration>
                <bodyAngle>0</bodyAngle>
                <bodyOffsetX>0</bodyOffsetX>
                <bodyOffsetZ>-0.290</bodyOffsetZ>
                <bodyFacing>0</bodyFacing>
                <headFacing>0</headFacing>
                <headBob>-0.06</headBob>

                <tickDuration>1</tickDuration>
                <bodyAngle>0</bodyAngle>
                <headAngle>0</headAngle>
                <bodyOffsetX>0</bodyOffsetX>
                <bodyOffsetZ>-0.255</bodyOffsetZ>
                <bodyFacing>0</bodyFacing>
                <headFacing>0</headFacing>
                <headBob>0</headBob>

            </keyframes>

            <keyframes>

                <tickDuration>12</tickDuration>
                <bodyAngle>0</bodyAngle>
                <headAngle>0</headAngle>
                <bodyOffsetX>0</bodyOffsetX>
                <bodyOffsetZ>0.473</bodyOffsetZ>
                <bodyFacing>2</bodyFacing>
                <headFacing>2</headFacing>
                <headBob>0</headBob>

                <tickDuration>7</tickDuration>
                <soundEffect>Cum</soundEffect>
                <bodyAngle>0</bodyAngle>
                <bodyOffsetX>0</bodyOffsetX>
                <bodyOffsetZ>0.575</bodyOffsetZ>
                <bodyFacing>2</bodyFacing>
                <headFacing>2</headFacing>
                <headBob>-0.051</headBob>

                <tickDuration>7</tickDuration>
                <bodyAngle>0</bodyAngle>
                <bodyOffsetX>0</bodyOffsetX>
                <bodyOffsetZ>0.50</bodyOffsetZ>
                <bodyFacing>2</bodyFacing>
                <headFacing>2</headFacing>
                <headBob>-0.04</headBob>

                <tickDuration>60</tickDuration>
                <bodyAngle>0</bodyAngle>
                <bodyOffsetX>0</bodyOffsetX>
                <bodyOffsetZ>0.575</bodyOffsetZ>
                <bodyFacing>2</bodyFacing>
                <headFacing>2</headFacing>
                <headBob>-0.051</headBob>

                <tickDuration>14</tickDuration>
                <bodyAngle>0</bodyAngle>
                <bodyOffsetX>0</bodyOffsetX>
                <bodyOffsetZ>0.575</bodyOffsetZ>
                <bodyFacing>2</bodyFacing>
                <headFacing>2</headFacing>
                <headBob>-0.051</headBob>

                <tickDuration>1</tickDuration>
                <bodyAngle>0</bodyAngle>
                <headAngle>0</headAngle>
                <bodyOffsetX>0</bodyOffsetX>
                <bodyOffsetZ>0.473</bodyOffsetZ>
                <bodyFacing>2</bodyFacing>
                <headFacing>2</headFacing>
                <headBob>0</headBob>

            </keyframes>

        </animationClips>

    </animationStages>

  </Rimworld_Animations.AnimationDef>
</Defs>


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

<Defs>
  <JobDef>
    <defName>JoinInBedAnimation</defName>
    <driverClass>Rimworld_Animations.JobDriver_SexCasualForAnimation</driverClass>
    <reportString>joining someone in bed.</reportString>
    <casualInterruptible>false</casualInterruptible>
  </JobDef>

  <JobDef>
    <defName>GettinLovedAnimation</defName>
    <driverClass>Rimworld_Animations.JobDriver_SexBaseRecieverLovedForAnimation</driverClass>
    <reportString>lovin'.</reportString>
    <casualInterruptible>false</casualInterruptible>
  </JobDef>
</Defs>

repo_name: TaekwondoBoxing/rimworld

license: unknown


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

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

				<grains>

						<clipFolderPath>Sex/cum</clipFolderPath>

				</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>1</maxSimultaneous>
		<subSounds>

				<grains>

						<clipFolderPath>Sex/kucyu04</clipFolderPath>

				</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>1</maxSimultaneous>
		<subSounds>

				<grains>

						<clipFolderPath>Sex/Suck/Suck_1</clipFolderPath>

						<clipFolderPath>Sex/Suck/Suck_2</clipFolderPath>

						<clipFolderPath>Sex/Suck/Suck_3</clipFolderPath>

						<clipFolderPath>Sex/Suck/Suck_4</clipFolderPath>

						<clipFolderPath>Sex/Suck/Suck_5</clipFolderPath>

            <clipFolderPath>Sex/Suck/Suck_6</clipFolderPath>

            <clipFolderPath>Sex/Suck/Suck_7</clipFolderPath>

            <clipFolderPath>Sex/Suck/Suck_8</clipFolderPath>

            <clipFolderPath>Sex/Suck/Suck_9</clipFolderPath>

            <clipFolderPath>Sex/Suck/Suck_10</clipFolderPath>

				</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>1</maxSimultaneous>
    <subSounds>

        <grains>

            <clipFolderPath>Sex/Clap_1</clipFolderPath>

            <clipFolderPath>Sex/Clap_2</clipFolderPath>

            <clipFolderPath>Sex/Clap_3</clipFolderPath>

            <clipFolderPath>Sex/Clap_4</clipFolderPath>

            <clipFolderPath>Sex/Clap_5</clipFolderPath>

            <clipFolderPath>Sex/Clap_6</clipFolderPath>

            <clipFolderPath>Sex/Clap_7</clipFolderPath>

            <clipFolderPath>Sex/Clap_8</clipFolderPath>

        </grains>
        <volumeRange>
          <min>45</min>
          <max>70</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>Slimy</defName>
    <context>MapOnly</context>
    <eventNames />
    <maxSimultaneous>1</maxSimultaneous>
    <subSounds>

        <grains>

            <clipFolderPath>Sex/Slime/Slimy1</clipFolderPath>

            <clipFolderPath>Sex/Slime/Slimy2</clipFolderPath>

            <clipFolderPath>Sex/Slime/Slimy3</clipFolderPath>

            <clipFolderPath>Sex/Slime/Slimy4</clipFolderPath>

            <clipFolderPath>Sex/Slime/Slimy5</clipFolderPath>

        </grains>
        <volumeRange>
          <min>15</min>
          <max>25</max>
        </volumeRange>
        <pitchRange>
          <min>1.4</min>
          <max>1.8</max>
        </pitchRange>
        <distRange>
          <min>0</min>
          <max>25</max>
        </distRange>
        <repeatMode>NeverTwice</repeatMode>
        <sustainLoop>false</sustainLoop>

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


code:
<?xml version="1.0" encoding="utf-8" ?>
<Patch>
  <Operation 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/comps</xpath>
        <value>

        </value>

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


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

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

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

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

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


code:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProjectGuid>{71B05D71-67B2-4014-82CD-18C20AC0882F}</ProjectGuid>
    <OutputType>Library</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>Rimworld_Animations</RootNamespace>
    <AssemblyName>Rimworld-Animations</AssemblyName>
    <TargetFrameworkVersion>v4.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.1\Assemblies\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <DebugType>none</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin\Release\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="0Harmony, Version=2.0.0.8, Culture=neutral, processorArchitecture=MSIL">
      <SpecificVersion>False</SpecificVersion>
      <HintPath>..\..\..\..\workshop\content\294100\2009463077\v1.1\Assemblies\0Harmony.dll</HintPath>
      <Private>False</Private>
    </Reference>
    <Reference Include="Assembly-CSharp, Version=1.1.7397.36407, Culture=neutral, processorArchitecture=MSIL">
      <SpecificVersion>False</SpecificVersion>
      <HintPath>..\..\RimWorldWin64_Data\Managed\Assembly-CSharp.dll</HintPath>
      <Private>False</Private>
    </Reference>
    <Reference Include="RJW, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
      <SpecificVersion>False</SpecificVersion>
      <HintPath>..\rjw-master\1.1\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, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
      <SpecificVersion>False</SpecificVersion>
      <HintPath>..\..\RimWorldWin64_Data\Managed\UnityEngine.dll</HintPath>
      <Private>False</Private>
    </Reference>
    <Reference Include="UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
      <SpecificVersion>False</SpecificVersion>
      <HintPath>..\..\RimWorldWin64_Data\Managed\UnityEngine.CoreModule.dll</HintPath>
      <Private>False</Private>
    </Reference>
  </ItemGroup>
  <ItemGroup>
    <Compile Include="Properties\AssemblyInfo.cs" />
    <Compile Include="Source\Actors\Actor.cs" />
    <Compile Include="Source\Animations\AnimationStage.cs" />
    <Compile Include="Source\Animations\Clips\BaseAnimationClip.cs" />
    <Compile Include="Source\Animations\Clips\PawnAnimationClip.cs" />
    <Compile Include="Source\Animations\Clips\ThingAnimationClip.cs" />
    <Compile Include="Source\Animations\Keyframes\Keyframe.cs" />
    <Compile Include="Source\Animations\Keyframes\PawnKeyframe.cs" />
    <Compile Include="Source\Animations\Keyframes\ThingKeyframe.cs" />
    <Compile Include="Source\AnimationUtility.cs" />
    <Compile Include="Source\Comps\CompBodyAnimator.cs" />
    <Compile Include="Source\Comps\CompProperties_BodyAnimator.cs" />
    <Compile Include="Source\Comps\CompProperties_ThingAnimator.cs" />
    <Compile Include="Source\Comps\CompThingAnimator.cs" />
    <Compile Include="Source\Defs\AnimationDef.cs" />
    <Compile Include="Source\JobDrivers\JobDriver_SexBaseRecieverLovedForAnimation.cs" />
    <Compile Include="Source\JobDrivers\JobDriver_SexCasualForAnimation.cs" />
    <Compile Include="Source\MainTabWindows\MainTabWindow_SexAnimator.cs" />
    <Compile Include="Source\Patches\HarmonyPatch_AlienRace.cs" />
    <Compile Include="Source\Patches\HarmonyPatch_FacialAnimation.cs" />
    <Compile Include="Source\Patches\HarmonyPatch_PawnRenderer.cs" />
    <Compile Include="Source\Patches\HarmonyPatch_Pawn_DrawTracker.cs" />
    <Compile Include="Source\Patches\HarmonyPatch_ShowHairWithHats.cs" />
    <Compile Include="Source\Patches\Harmony_PatchAll.cs" />
    <Compile Include="Source\Patches\rjwPatches\HarmonyPatch_DoLovinAnimationPatch.cs" />
    <Compile Include="Source\Patches\rjwPatches\HarmonyPatch_JobDriver_SexBaseInitiator.cs" />
    <Compile Include="Source\Patches\rjwPatches\HarmonyPatch_JoinInBedGiveJob.cs" />
    <Compile Include="Source\Patches\rjwPatches\HarmonyPatch_SexTick.cs" />
    <Compile Include="Source\Patches\rjwPatches\HarmonyPatch_WorkGiverSex.cs" />
  </ItemGroup>
  <ItemGroup />
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>


code:
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29905.134
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rimworld-Animations", "Rimworld-Animations.csproj", "{71B05D71-67B2-4014-82CD-18C20AC0882F}"
EndProject
Global
	GlobalSection(SolutionConfigurationPlatforms) = preSolution
		Debug|Any CPU = Debug|Any CPU
		Release|Any CPU = Release|Any CPU
	EndGlobalSection
	GlobalSection(ProjectConfigurationPlatforms) = postSolution
		{71B05D71-67B2-4014-82CD-18C20AC0882F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
		{71B05D71-67B2-4014-82CD-18C20AC0882F}.Debug|Any CPU.Build.0 = Debug|Any CPU
		{71B05D71-67B2-4014-82CD-18C20AC0882F}.Release|Any CPU.ActiveCfg = Release|Any CPU
		{71B05D71-67B2-4014-82CD-18C20AC0882F}.Release|Any CPU.Build.0 = Release|Any CPU
	EndGlobalSection
	GlobalSection(SolutionProperties) = preSolution
		HideSolutionNode = FALSE
	EndGlobalSection
	GlobalSection(ExtensibilityGlobals) = postSolution
		SolutionGuid = {7E01292A-D76F-4CA3-AA64-085B84ECD905}
	EndGlobalSection
EndGlobal


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

namespace Rimworld_Animations {
    public class Actor {
        public List<string> defNames;
        public List<string> requiredGenitals;
        public bool activeRole = false;
        public string gender;
        public bool isFucking = false;
        public bool isFucked = false;
        public Vector3 offset = new Vector3(0, 0, 0);
    }
}


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

namespace Rimworld_Animations {
    public static class AnimationUtility {
        /*
         Note: always make the list in this order:
             Female pawns, animal female pawns, male pawns, animal male pawns
        */
        public static AnimationDef tryFindAnimation(ref List<Pawn> participants) {

            //aggressors first
            participants = participants.OrderByDescending(p => p.jobs.curDriver is rjw.JobDriver_SexBaseInitiator).ToList();

            //fucked first, fucking second
            participants = participants.OrderBy(p => rjw.xxx.can_fuck(p)).ToList();

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

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

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

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

                            return false;
                        }

                    } else {

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

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

                            return false;
                        }
                    }

                    if(x.actors[i].requiredGenitals != null && x.actors[i].requiredGenitals.Contains("Vagina")) {

                        if (!rjw.Genital_Helper.has_vagina(localParticipants[i])) {
                            Log.Message(x.defName.ToStringSafe() + " not selected -- " + localParticipants[i].def.defName.ToStringSafe() + " " + localParticipants[i].Name.ToStringSafe() + " doesn't have vagina");
                            return false;
                        }

                    }

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

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

                    if (x.actors[i].isFucked && !rjw.xxx.can_be_fucked(localParticipants[i])) {
                        Log.Message(x.defName.ToStringSafe() + " not selected -- " + localParticipants[i].def.defName.ToStringSafe() + " " + localParticipants[i].Name.ToStringSafe() + " can't be fucked");
                        return false;
                    }
                }
                return true;
            });

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

            else
                return null;
        }

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

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

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

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


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

namespace Rimworld_Animations {
    public class AnimationStage
    {
        public string stageName;
        public int stageIndex;
        public int playTimeTicks = 0;
        public bool isLooping;
        public List<BaseAnimationClip> animationClips;

        public void initialize() {
            foreach (BaseAnimationClip clip in animationClips) {
                clip.buildSimpleCurves();
                //select playTimeTicks as longest playtime of all the animations
                if(clip.duration > playTimeTicks) {
                    playTimeTicks = clip.duration;
                }
            }
        }
    }
}


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

namespace Rimworld_Animations {
    public abstract class BaseAnimationClip
    {
        public List<ThingDef> types; //types of participants
        public int duration;
        public abstract void buildSimpleCurves();
        public string soundDef = null; //for playing sounds
        public int actor;

    }
}


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

namespace Rimworld_Animations {
    public class PawnAnimationClip : BaseAnimationClip {

        public List<PawnKeyframe> keyframes;
        public AltitudeLayer layer = AltitudeLayer.Pawn;

        public Dictionary<int, string> SoundEffects = new Dictionary<int, string>();
        public SimpleCurve BodyAngle = new SimpleCurve();
        public SimpleCurve HeadAngle = new SimpleCurve();
        public SimpleCurve HeadBob = new SimpleCurve();
        public SimpleCurve BodyOffsetX = new SimpleCurve();
        public SimpleCurve BodyOffsetZ = new SimpleCurve();
        public SimpleCurve HeadFacing = new SimpleCurve();
        public SimpleCurve BodyFacing = new SimpleCurve();

        public override void buildSimpleCurves() {

            int duration = 0;
            //getting the length of the whole clip
            foreach(PawnKeyframe frame in keyframes) {
                duration += frame.tickDuration;
            }

            //guarantees loops don't get cut off mid-anim
            this.duration = duration;

            int keyframePosition = 0;
            foreach (PawnKeyframe frame in keyframes) {

                if (frame.atTick.HasValue) {
                    if (frame.bodyAngle.HasValue)
                        BodyAngle.Add((float)frame.atTick / (float)duration, frame.bodyAngle.Value, true);

                    if (frame.headAngle.HasValue)
                        HeadAngle.Add((float)frame.atTick / (float)duration, frame.headAngle.Value, true);

                    if (frame.bodyOffsetX.HasValue)
                        BodyOffsetX.Add((float)frame.atTick / (float)duration, frame.bodyOffsetX.Value, true);

                    if (frame.bodyOffsetZ.HasValue)
                        BodyOffsetZ.Add((float)frame.atTick / (float)duration, frame.bodyOffsetZ.Value, true);

                    if (frame.headFacing.HasValue)
                        HeadFacing.Add((float)frame.atTick / (float)duration, frame.headFacing.Value, true);

                    if (frame.bodyFacing.HasValue)
                        BodyFacing.Add((float)frame.atTick / (float)duration, frame.bodyFacing.Value, true);

                    if (frame.headBob.HasValue)
                        HeadBob.Add((float)frame.atTick / (float)duration, frame.headBob.Value, true);

                    if (frame.soundEffect != null) {
                        SoundEffects.Add((int)frame.atTick, frame.soundEffect);
                    }
                }
                else {
                    if (frame.bodyAngle.HasValue)
                        BodyAngle.Add((float)keyframePosition / (float)duration, frame.bodyAngle.Value, true);

                    if (frame.headAngle.HasValue)
                        HeadAngle.Add((float)keyframePosition / (float)duration, frame.headAngle.Value, true);

                    if (frame.bodyOffsetX.HasValue)
                        BodyOffsetX.Add((float)keyframePosition / (float)duration, frame.bodyOffsetX.Value, true);

                    if (frame.bodyOffsetZ.HasValue)
                        BodyOffsetZ.Add((float)keyframePosition / (float)duration, frame.bodyOffsetZ.Value, true);

                    if (frame.headFacing.HasValue)
                        HeadFacing.Add((float)keyframePosition / (float)duration, frame.headFacing.Value, true);

                    if (frame.bodyFacing.HasValue)
                        BodyFacing.Add((float)keyframePosition / (float)duration, frame.bodyFacing.Value, true);

                    if (frame.headBob.HasValue)
                        HeadBob.Add((float)keyframePosition / (float)duration, frame.headBob.Value, true);

                    if (frame.soundEffect != null) {
                        SoundEffects.Add(keyframePosition, frame.soundEffect);
                    }

                    keyframePosition += frame.tickDuration;

                }

            }

        }

    }
}


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

namespace Rimworld_Animations {
    public class ThingAnimationClip : BaseAnimationClip
    {
        public List<ThingKeyframe> keyframes;

        public override void buildSimpleCurves() {
        }
    }
}


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

namespace Rimworld_Animations {
    public abstract class Keyframe
    {
        public int tickDuration = 1;

    }
}


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

namespace Rimworld_Animations {
    public class PawnKeyframe : Keyframe
    {
        public float? bodyAngle;
        public float? headAngle;

        public float? bodyOffsetZ;
        public float? bodyOffsetX;

        public float? headBob;
        //todo: add headOffsets l/r?

        public int? bodyFacing;
        public int? headFacing;

        public string soundEffect;

        public float? atTick;
    }
}


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

namespace Rimworld_Animations {
    public class ThingKeyframe : Keyframe
    {
    }
}


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

namespace Rimworld_Animations {
    class CompBodyAnimator : ThingComp
    {
        public Pawn pawn => base.parent as Pawn;
        public PawnGraphicSet Graphics;

        public CompProperties_BodyAnimator Props => (CompProperties_BodyAnimator)(object)base.props;

        public bool isAnimating {
            get {
                return Animating;
            }
            set {
                Animating = value;

                if(value == true) {
                    xxx.DrawNude(pawn);
                } else {
                    pawn.Drawer.renderer.graphics.ResolveAllGraphics();
                    resetPosition = true;
                }

                PortraitsCache.SetDirty(pawn);
            }
        }

        public bool resetPosition {
            get {
                if (resetPos) {
                    resetPos = false;
                    return true;
                }
                return false;
            }
            set {
                resetPos = value;
            }
        }

        private bool Animating, resetPos = false;
        private bool mirror = false;
        private int actor;

        private int animTicks = 0, stageTicks = 0, clipTicks = 0;
        private int curStage = 0;
        private float clipPercent = 0;

        public IntVec3 positionReset;
        public Vector3 anchor, deltaPos, headBob;
        public float bodyAngle, headAngle;
        public Rot4 headFacing, bodyFacing;

        private AnimationDef anim;
        private AnimationStage stage => anim.animationStages[curStage];
        private PawnAnimationClip clip => (PawnAnimationClip)stage.animationClips[actor];

        public void setAnchor(IntVec3 pos)
        {
            positionReset = pos;
            anchor = pos.ToVector3Shifted();
        }
        public void setAnchor(Thing thing) {

            //center on bed
            positionReset = thing.Position;
            if(thing is Building_Bed) {
                anchor = thing.Position.ToVector3();
                if (((Building_Bed)thing).SleepingSlotsCount == 2) {
                    if (thing.Rotation.AsInt == 0) {
                        anchor.x += 1;
                        anchor.z += 1;
                    }
                    else if (thing.Rotation.AsInt == 1) {
                        anchor.x += 1;
                    }
                    else if(thing.Rotation.AsInt == 3) {
                        anchor.z += 1;
                    }

                }
                else {
                    if(thing.Rotation.AsInt == 0) {
                        anchor.x += 0.5f;
                        anchor.z += 1f;
                    }
                    else if(thing.Rotation.AsInt == 1) {
                        anchor.x += 1f;
                        anchor.z += 0.5f;
                    }
                    else if(thing.Rotation.AsInt == 2) {
                        anchor.x += 0.5f;
                    } else {
                        anchor.z += 0.5f;
                    }
                }
            }
            else {
                anchor = thing.Position.ToVector3Shifted();
            }
        }
        public void StartAnimation(AnimationDef anim, int actor, bool mirror = false) {

            isAnimating = true;

            pawn.jobs.posture = PawnPosture.Standing;

            this.actor = actor;
            this.anim = anim;
            this.mirror = mirror;

            curStage = 0;
            animTicks = 0;
            stageTicks = 0;
            clipTicks = 0;

            //tick once for initialization
            tickAnim();

        }
        public override void CompTick() {
            base.CompTick();

            if(isAnimating) {
                tickAnim();
                if (pawn?.jobs?.curDriver == null || (pawn?.jobs?.curDriver != null && !(pawn?.jobs?.curDriver is rjw.JobDriver_Sex))) {

                    isAnimating = false;
                }
            }
        }
        public void animatePawn(ref Vector3 rootLoc, ref float angle, ref Rot4 bodyFacing, ref Rot4 headFacing) {

            if(!isAnimating) {
                return;
            }
            rootLoc = anchor + deltaPos;
            angle = bodyAngle;
            bodyFacing = this.bodyFacing;
            headFacing = this.headFacing;

        }

        public void tickGraphics(PawnGraphicSet graphics) {
            this.Graphics = graphics;
        }

        public void tickAnim() {

            if (!isAnimating) return;

            animTicks++;
            if (animTicks < anim.animationTimeTicks) {
                tickStage();
            } else {
                isAnimating = false;
            }
        }

        public void tickStage()
        {
            stageTicks++;

            if(stageTicks >= stage.playTimeTicks) {
                curStage++;
                stageTicks = 0;
                clipTicks = 0;
                clipPercent = 0;
            }

            tickClip();

        }

        public void tickClip() {

            clipTicks++;

            //play sound effect
            if(rjw.RJWSettings.sounds_enabled && clip.SoundEffects.ContainsKey(clipTicks)) {
                SoundDef.Named(clip.SoundEffects[clipTicks]).PlayOneShot(new TargetInfo(pawn.Position, pawn.Map));
            }

            //loop animation if possible
            if (clipPercent >= 1 && stage.isLooping) {
                clipTicks = 1;//warning: don't set to zero or else calculations go wrong
            }
            clipPercent = (float)clipTicks / (float)clip.duration;

            calculateDrawValues();
        }

        public void calculateDrawValues() {

            deltaPos = new Vector3(clip.BodyOffsetX.Evaluate(clipPercent) * (mirror ? -1 : 1), clip.layer.AltitudeFor(), clip.BodyOffsetZ.Evaluate(clipPercent));
            bodyAngle = clip.BodyAngle.Evaluate(clipPercent) * (mirror ? -1 : 1);
            headAngle = clip.HeadAngle.Evaluate(clipPercent) * (mirror ? -1 : 1);
            bodyFacing = mirror ? new Rot4((int)clip.BodyFacing.Evaluate(clipPercent)).Opposite : new Rot4((int)clip.BodyFacing.Evaluate(clipPercent));

            bodyFacing = new Rot4((int)clip.BodyFacing.Evaluate(clipPercent));
            if(bodyFacing.IsHorizontal && mirror) {
                bodyFacing = bodyFacing.Opposite;
            }

            headFacing = new Rot4((int)clip.HeadFacing.Evaluate(clipPercent));
            if(headFacing.IsHorizontal && mirror) {
                headFacing = headFacing.Opposite;
            }
            headBob = new Vector3(0, 0, clip.HeadBob.Evaluate(clipPercent));
        }

        public Vector3 getPawnHeadPosition() {

            return anchor + deltaPos + Quaternion.AngleAxis(bodyAngle, Vector3.up) * (pawn.Drawer.renderer.BaseHeadOffsetAt(headFacing) + headBob);

        }

        public override void PostExposeData() {
            base.PostExposeData();

            Scribe_Defs.Look(ref anim, "anim");

            Scribe_Values.Look(ref animTicks, "animTicks", 1);
            Scribe_Values.Look(ref stageTicks, "stageTicks", 1);
            Scribe_Values.Look(ref clipTicks, "clipTicks", 1);
            Scribe_Values.Look(ref clipPercent, "clipPercent", 1);

            Scribe_Values.Look(ref mirror, "mirror");

            Scribe_Values.Look(ref curStage, "curStage", 0);
            Scribe_Values.Look(ref actor, "actor");

            Scribe_Values.Look(ref Animating, "Animating");
            Scribe_Values.Look(ref anchor, "anchor");
            Scribe_Values.Look(ref deltaPos, "deltaPos");
            Scribe_Values.Look(ref headBob, "headBob");
            Scribe_Values.Look(ref bodyAngle, "bodyAngle");
            Scribe_Values.Look(ref headAngle, "headAngle");

            Scribe_Values.Look(ref headFacing, "headFacing");
            Scribe_Values.Look(ref headFacing, "bodyFacing");
        }

    }
}


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

namespace Rimworld_Animations {
    class CompProperties_BodyAnimator : CompProperties
    {
        public CompProperties_BodyAnimator() {

            base.compClass = typeof(CompBodyAnimator);
        }
    }
}


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

namespace Rimworld_Animations {
    class CompProperties_ThingAnimator
    {
    }
}


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

namespace Rimworld_Animations {
    class CompThingAnimator
    {
    }
}


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

namespace Rimworld_Animations {
    public class AnimationDef : Def
    {
        public List<AnimationStage> animationStages;
        public List<Actor> actors;
        public int animationTimeTicks = 0; //do not set manually
        public bool sounds = false;

        public override void PostLoad() {
            base.PostLoad();
            foreach(AnimationStage stage in animationStages) {
                stage.initialize();
                animationTimeTicks += stage.playTimeTicks;
            }
        }
    }
}


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

namespace Rimworld_Animations {
	public class JobDriver_SexBaseRecieverLovedForAnimation : JobDriver_SexBaseReciever {

		public readonly TargetIndex ipartner = TargetIndex.A;
		public readonly TargetIndex ibed = TargetIndex.B;

		public Pawn Partner => (Pawn)(job.GetTarget(ipartner));
		public new Building_Bed Bed => (Building_Bed)(job.GetTarget(ibed));

		protected override IEnumerable<Toil> MakeNewToils() {
			setup_ticks();
			parteners.Add(Partner);// add job starter, so this wont fail, before Initiator starts his job
								   //--Log.Message("[RJW]JobDriver_GettinLoved::MakeNewToils is called");

			float partner_ability = xxx.get_sex_ability(Partner);

			// More/less hearts based on partner ability.
			if (partner_ability < 0.8f)
				ticks_between_thrusts += 100;
			else if (partner_ability > 2.0f)
				ticks_between_thrusts -= 25;

			// More/less hearts based on opinion.
			if (pawn.relations.OpinionOf(Partner) < 0)
				ticks_between_hearts += 50;
			else if (pawn.relations.OpinionOf(Partner) > 60)
				ticks_between_hearts -= 25;

			this.FailOnDespawnedOrNull(ipartner);
			this.FailOn(() => !Partner.health.capacities.CanBeAwake);
			this.FailOn(() => pawn.Drafted);
			this.KeepLyingDown(ibed);
			yield return Toils_Reserve.Reserve(ipartner, 1, 0);
			yield return Toils_Reserve.Reserve(ibed, Bed.SleepingSlotsCount, 0);

			Toil get_loved = Toils_LayDown.LayDown(ibed, true, false, false, false);
			get_loved.FailOn(() => Partner.CurJobDef != DefDatabase<JobDef>.GetNamed("JoinInBedAnimation", true));
			get_loved.defaultCompleteMode = ToilCompleteMode.Never;
			get_loved.socialMode = RandomSocialMode.Off;
			get_loved.AddPreTickAction(delegate {
				if (pawn.IsHashIntervalTick(ticks_between_hearts))
					MoteMaker.ThrowMetaIcon(pawn.Position, pawn.Map, ThingDefOf.Mote_Heart);
				if (pawn.IsHashIntervalTick(ticks_between_thrusts))
					xxx.sexTick(pawn, Partner, false);
			});
			get_loved.AddFinishAction(delegate {
				if (xxx.is_human(pawn))
					pawn.Drawer.renderer.graphics.ResolveApparelGraphics();
			});
			yield return get_loved;

		}
	}
}


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

namespace Rimworld_Animations {
    class JobDriver_SexCasualForAnimation : JobDriver_SexBaseInitiator {

        public readonly TargetIndex ipartner = TargetIndex.A;
        public readonly TargetIndex ibed = TargetIndex.B;

        public Pawn Partner => (Pawn)job.GetTarget(ipartner);
        public new Building_Bed Bed => (Building_Bed)job.GetTarget(ibed);

        public override bool TryMakePreToilReservations(bool errorOnFailed) {
            return ReservationUtility.Reserve(base.pawn, Partner, job, xxx.max_rapists_per_prisoner, 0, null, errorOnFailed);
        }

        protected override IEnumerable<Toil> MakeNewToils() {
            setup_ticks();
            this.FailOnDespawnedOrNull(ipartner);
            this.FailOnDespawnedOrNull(ibed);
            this.FailOn(() => !Partner.health.capacities.CanBeAwake);

            yield return Toils_Reserve.Reserve(ipartner, xxx.max_rapists_per_prisoner, 0, null);

            Toil goToPawnInBed = Toils_Goto.GotoThing(ipartner, PathEndMode.OnCell);
            goToPawnInBed.FailOn(() => !RestUtility.InBed(Partner) && !xxx.in_same_bed(Partner, pawn));

            yield return goToPawnInBed;

            Toil startPartnerSex = new Toil();
            startPartnerSex.initAction = delegate {

                Job gettinLovedJob = JobMaker.MakeJob(DefDatabase<JobDef>.GetNamed("GettinLovedAnimation"), pawn, Bed); // new gettin loved toil that wakes up the pawn goes here

                Partner.jobs.jobQueue.EnqueueFirst(gettinLovedJob);
                Partner.jobs.EndCurrentJob(JobCondition.InterruptForced);
            };
            yield return startPartnerSex;

            Toil sexToil = new Toil();
            sexToil.FailOn(() => (Partner.CurJobDef == null) || Partner.CurJobDef != DefDatabase<JobDef>.GetNamed("GettinLovedAnimation", true)); //partner jobdriver is not sexbaserecieverlovedforanim
            sexToil.socialMode = RandomSocialMode.Off;
            sexToil.defaultCompleteMode = ToilCompleteMode.Never;
            sexToil.initAction = delegate {

                usedCondom = (CondomUtility.TryUseCondom(base.pawn) || CondomUtility.TryUseCondom(Partner));
                Start();
            };

            sexToil.AddPreTickAction(delegate {

                ticks_left--;
                if(Gen.IsHashIntervalTick(pawn, ticks_between_hearts)) {
                    MoteMaker.ThrowMetaIcon(pawn.Position, pawn.Map, ThingDefOf.Mote_Heart);
                }
                PawnUtility.GainComfortFromCellIfPossible(pawn, false);
                PawnUtility.GainComfortFromCellIfPossible(Partner, false);
                xxx.reduce_rest(Partner);
                xxx.reduce_rest(pawn, 2);
                if (ticks_left <= 0)
                    ReadyForNextToil();

            });
            sexToil.AddFinishAction(delegate {

                End();
                if(xxx.is_human(pawn)) {
                    pawn.Drawer.renderer.graphics.ResolveApparelGraphics();
                }

            });
            yield return sexToil;

            Toil finish = new Toil();
            finish.initAction = delegate {
                SexUtility.ProcessSex(pawn, Partner, usedCondom);
            };
            finish.defaultCompleteMode = ToilCompleteMode.Instant;
            yield return finish;

        }
    }
}


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

namespace Rimworld_Animations {
    class MainTabWindow_SexAnimator : MainTabWindow
    {
        //todo: add animation maker window
    }
}


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

namespace Rimworld_Animations {
    [StaticConstructorOnStartup]
    public static class HarmonyPatch_AlienRace {
        static HarmonyPatch_AlienRace () {
			try {
				((Action)(() => {
					if (LoadedModManager.RunningModsListForReading.Any(x => x.Name == "Humanoid Alien Races 2.0")) {
						(new Harmony("rjw")).Patch(AccessTools.Method(typeof(PawnGraphicSet), "ResolveApparelGraphics"),
							prefix: new HarmonyMethod(AccessTools.Method(typeof(HarmonyPatch_AlienRace), "Prefix_StopResolveAllGraphicsWhileSex")));
					}
				}))();
			}
			catch (TypeLoadException ex) {

			}
		}

		public static bool Prefix_StopResolveAllGraphicsWhileSex(ref Pawn ___pawn) {

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

    }
}


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

namespace Rimworld_Animations {
	[StaticConstructorOnStartup]
	public static class Patch_FacialAnimation {

		static Patch_FacialAnimation() {
			try {
				((Action)(() => {
					if (LoadedModManager.RunningModsListForReading.Any(x => x.Name == "[NL] Facial Animation - WIP")) {
						(new Harmony("rjw")).Patch(AccessTools.Method(AccessTools.TypeByName("FacialAnimation.DrawFaceGraphicsComp"), "DrawGraphics"),
							prefix: new HarmonyMethod(AccessTools.Method(typeof(Patch_FacialAnimation), "Prefix")));
					}
				}))();
			}
			catch (TypeLoadException ex) {

			}
		}

		public static bool Prefix(ref Pawn ___pawn, ref Rot4 headFacing, ref Vector3 headOrigin, ref Quaternion quaternion, ref bool portrait) {

			CompBodyAnimator bodyAnim = ___pawn.TryGetComp<CompBodyAnimator>();

			if (bodyAnim != null && bodyAnim.isAnimating && !portrait) {

				headFacing = bodyAnim.headFacing;
				headOrigin = new Vector3(bodyAnim.getPawnHeadPosition().x, headOrigin.y, bodyAnim.getPawnHeadPosition().z);
				quaternion = Quaternion.AngleAxis(bodyAnim.headAngle, Vector3.up);
			}

			return true;
		}
	}
}


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

namespace Rimworld_Animations {

	[HarmonyPatch(typeof(PawnRenderer), "RenderPawnInternal", new Type[]
	{
		typeof(Vector3),
		typeof(float),
		typeof(bool),
		typeof(Rot4),
		typeof(Rot4),
		typeof(RotDrawMode),
		typeof(bool),
		typeof(bool),
		typeof(bool)
	})]

	public static class HarmonyPatch_PawnRenderer
    {

		[HarmonyBefore(new string[] { "showhair.kv.rw", "erdelf.HumanoidAlienRaces", "Nals.FacialAnimation" })]
		public static void Prefix(PawnRenderer __instance, ref Vector3 rootLoc, ref float angle, bool renderBody, ref Rot4 bodyFacing, ref Rot4 headFacing, RotDrawMode bodyDrawType, bool portrait, bool headStump, bool invisible)
		{
			PawnGraphicSet graphics = __instance.graphics;
			Pawn pawn = graphics.pawn;
			CompBodyAnimator bodyAnim = pawn.TryGetComp<CompBodyAnimator>();

			if (!graphics.AllResolved) {
				graphics.ResolveAllGraphics();
			}

			if (bodyAnim != null && bodyAnim.isAnimating && !portrait) {
				bodyAnim.tickGraphics(graphics);
				pawn.TryGetComp<CompBodyAnimator>().animatePawn(ref rootLoc, ref angle, ref bodyFacing, ref headFacing);

			}
		}

		[HarmonyAfter(new string[] { "showhair.kv.rw", "erdelf.HumanoidAlienRaces", "Nals.FacialAnimation" })]
		[HarmonyReversePatch(HarmonyReversePatchType.Snapshot)]
		public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) {

			MethodInfo drawMeshNowOrLater = AccessTools.Method(typeof(GenDraw), "DrawMeshNowOrLater");//typeof(GenDraw).GetMethod("DrawMeshNowOrLater", BindingFlags.Static | BindingFlags.Public);
			FieldInfo headGraphic = AccessTools.Field(typeof(PawnGraphicSet), "headGraphic");

			List<CodeInstruction> codes = instructions.ToList();
			bool forHead = true;
			for(int i = 0; i < codes.Count(); i++) {

				//Instead of calling drawmeshnoworlater, add pawn to the stack and call my special static method
				if (codes[i].OperandIs(drawMeshNowOrLater) && forHead) {

					yield return new CodeInstruction(OpCodes.Ldarg_0);
					yield return new CodeInstruction(OpCodes.Ldfld, AccessTools.DeclaredField(typeof(PawnRenderer), "pawn"));
					yield return new CodeInstruction(OpCodes.Call, AccessTools.DeclaredMethod(typeof(AnimationUtility), nameof(AnimationUtility.RenderPawnHeadMeshInAnimation)));

				}
				//checking for if(graphics.headGraphic != null)
				else if (codes[i].opcode == OpCodes.Ldfld && codes[i].OperandIs(headGraphic)) {
					forHead = true;
					yield return codes[i];
				}
				//checking for if(renderbody)
				else if(codes[i].opcode == OpCodes.Ldarg_3) {
					forHead = false;
					yield return codes[i];
				}
				else {
					yield return codes[i];
				}
			}
		}
    }
}


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

namespace Rimworld_Animations {

    [HarmonyPatch(typeof(Pawn_DrawTracker), "DrawPos", MethodType.Getter)]
    public static class HarmonyPatch_Pawn_DrawTracker {
        public static bool Prefix(ref Pawn ___pawn, ref Vector3 __result) {

            if(___pawn.TryGetComp<CompBodyAnimator>() != null) {

                if(___pawn.TryGetComp<CompBodyAnimator>().isAnimating) {
                    __result = ___pawn.TryGetComp<CompBodyAnimator>().anchor + ___pawn.TryGetComp<CompBodyAnimator>().deltaPos;
                    ___pawn.Position = __result.ToIntVec3();
                    return false;
                } else if(___pawn.TryGetComp<CompBodyAnimator>().resetPosition) {
                    //resetting position to anchor
                    __result = ___pawn.TryGetComp<CompBodyAnimator>().anchor;
                    ___pawn.Position = ___pawn.TryGetComp<CompBodyAnimator>().positionReset;
                    return false;

                }

            }
            return true;

        }
    }

    [HarmonyPatch(typeof(Pawn_PathFollower), "StartPath")]
    public static class HarmonyPatch_ResetPositionIfPathing {
        public static void Prefix(ref Pawn ___pawn) {

            if(___pawn.TryGetComp<CompBodyAnimator>() != null) {
                if(___pawn.TryGetComp<CompBodyAnimator>().isAnimating || ___pawn.TryGetComp<CompBodyAnimator>().resetPosition) {
                    ___pawn.TryGetComp<CompBodyAnimator>().isAnimating = false;
                    ___pawn.Position = ___pawn.TryGetComp<CompBodyAnimator>().positionReset;
                }
            }
        }
    }
}


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

namespace Rimworld_Animations {
    [StaticConstructorOnStartup]
    public static class Patch_ShowHairWithHats {

		static Patch_ShowHairWithHats() {
			try {
				((Action)(() =>
				{
					if (LoadedModManager.RunningModsListForReading.Any(x => x.Name == "[KV] Show Hair With Hats or Hide All Hats - 1.1")) {
						(new Harmony("rjw")).Patch(AccessTools.Method(AccessTools.TypeByName("ShowHair.Patch_PawnRenderer_RenderPawnInternal"), "Postfix"), //typeof(ShowHair.Patch_PawnRenderer_RenderPawnInternal), nameof(ShowHair.Patch_PawnRenderer_RenderPawnInternal.Postfix)),
							transpiler: new HarmonyMethod(AccessTools.Method(typeof(Patch_ShowHairWithHats), "Transpiler")));
					}
				}))();
			}
			catch (TypeLoadException ex) { }
		}

		public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) {

			MethodInfo drawMeshNowOrLater = AccessTools.Method(typeof(GenDraw), "DrawMeshNowOrLater");

			List<CodeInstruction> codes = instructions.ToList();
			for (int i = 0; i < codes.Count(); i++) {

				//Instead of calling drawmeshnoworlater, add pawn to the stack and call my special static method
				if (codes[i].OperandIs(drawMeshNowOrLater)) {

					yield return new CodeInstruction(OpCodes.Ldarg_0);
					yield return new CodeInstruction(OpCodes.Ldfld, AccessTools.DeclaredField(typeof(PawnRenderer), "pawn"));
					yield return new CodeInstruction(OpCodes.Call, AccessTools.DeclaredMethod(typeof(AnimationUtility), nameof(AnimationUtility.RenderPawnHeadMeshInAnimation)));

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


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

namespace Rimworld_Animations {

    [StaticConstructorOnStartup]
    public static class Harmony_PatchAll {

        static Harmony_PatchAll() {

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

        }
    }
}


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

namespace Rimworld_Animations {

    [HarmonyPatch(typeof(JobGiver_DoLovin), "TryGiveJob")]
    public static class HarmonyPatch_DoLovinAnimationPatch {

        public static void Postfix(ref Pawn pawn, ref Job __result) {

            if(__result != null) {
                Pawn partnerInMyBed = LovePartnerRelationUtility.GetPartnerInMyBed(pawn);
                RestUtility.WakeUp(pawn);
                __result = JobMaker.MakeJob(DefDatabase<JobDef>.GetNamed("JoinInBedAnimation", true), partnerInMyBed, partnerInMyBed.CurrentBed());
            }

        }
    }
}


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

namespace Rimworld_Animations {

    [HarmonyPatch(typeof(JobDriver_SexBaseInitiator), "Start")]
    static class HarmonyPatch_JobDriver_SexBaseInitiator_Start {
        public static void Postfix(ref JobDriver_SexBaseInitiator __instance) {

			if(__instance is JobDriver_JoinInBed) {
				Log.Warning("Tried to start wrong JobDriver with Rimworld-Animations installed. If you see this warning soon after installing this mod, it's fine and animated sex will start soon. If you see this a long time after installing, that's a problem.");
				return;
			}

			Pawn Target = __instance.Target;
			Pawn pawn = __instance.pawn;

			Building_Bed bed = __instance.Bed;

			if (__instance is JobDriver_BestialityForFemale)
				bed = (__instance as JobDriver_BestialityForFemale).Bed;
			else if (__instance is JobDriver_WhoreIsServingVisitors) {
				bed = (__instance as JobDriver_WhoreIsServingVisitors).Bed;
			}
			else if(__instance is JobDriver_SexCasualForAnimation) {
				bed = (__instance as JobDriver_SexCasualForAnimation).Bed;
			}

			if (__instance.Target.jobs?.curDriver is JobDriver_SexBaseReciever) {

				if (!(Target.jobs.curDriver as JobDriver_SexBaseReciever).parteners.Contains(pawn)) {
					(Target.jobs.curDriver as JobDriver_SexBaseReciever).parteners.Add(pawn);
				}

				if (bed != null) {
					RerollAnimations(Target, __instance.duration, bed as Thing);
				}
				else {
					RerollAnimations(Target, __instance.duration);
				}
			}
		}

		public static void RerollAnimations(Pawn pawn, int duration, Thing bed = null) {

			if(pawn == null || !(pawn.jobs?.curDriver is JobDriver_SexBaseReciever)) {
				Log.Message("Error: Tried to reroll animations when pawn isn't sexing");
				return;
			}

			List<Pawn> pawnsToAnimate = (pawn.jobs.curDriver as JobDriver_SexBaseReciever).parteners.ToList();

			if (!pawnsToAnimate.Contains(pawn)) {
				pawnsToAnimate = pawnsToAnimate.Append(pawn).ToList();
			}

			AnimationDef anim = AnimationUtility.tryFindAnimation(ref pawnsToAnimate);

			if (anim != null) {

				Log.Message("Now playing " + anim.defName);

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

				IntVec3 pos = pawn.Position;

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

					if (bed != null)
						pawnsToAnimate[i].TryGetComp<CompBodyAnimator>().setAnchor(bed);
					else {

						pawnsToAnimate[i].TryGetComp<CompBodyAnimator>().setAnchor(pos);
					}

					pawnsToAnimate[i].TryGetComp<CompBodyAnimator>().StartAnimation(anim, i, mirror);
					(pawnsToAnimate[i].jobs.curDriver as JobDriver_Sex).ticks_left = anim.animationTimeTicks;
					(pawnsToAnimate[i].jobs.curDriver as JobDriver_Sex).ticksLeftThisToil = anim.animationTimeTicks;
					(pawnsToAnimate[i].jobs.curDriver as JobDriver_Sex).duration = anim.animationTimeTicks;
					(pawnsToAnimate[i].jobs.curDriver as JobDriver_Sex).ticks_remaining = anim.animationTimeTicks;

				}
			}
			else {
				Log.Message("Anim not found");
				//if pawn isn't already animating,
				if (!pawn.TryGetComp<CompBodyAnimator>().isAnimating) {
					(pawn.jobs.curDriver as JobDriver_SexBaseReciever).increase_time(duration);
					//they'll just do the thrusting anim
				}
			}

		}
	}

	[HarmonyPatch(typeof(JobDriver_SexBaseInitiator), "End")]
	static class HarmonyPatch_JobDriver_SexBaseInitiator_End {

		public static void Postfix(ref JobDriver_SexBaseInitiator __instance) {

			//Stolen from vanilla lovin
			//to make sure vanilla lovin variables are set
			if(__instance.pawn?.mindState?.canLovinTick != null) {

				SimpleCurve LovinIntervalHoursFromAgeCurve = new SimpleCurve
				{
					new CurvePoint(16f, 1.5f),
					new CurvePoint(22f, 1.5f),
					new CurvePoint(30f, 4f),
					new CurvePoint(50f, 12f),
					new CurvePoint(75f, 36f)
				};

				int ticksToNextLovin;
				if (DebugSettings.alwaysDoLovin) {

					ticksToNextLovin = 100;

				} else {

					float centerX = LovinIntervalHoursFromAgeCurve.Evaluate(__instance.pawn.ageTracker.AgeBiologicalYearsFloat);

					centerX = Rand.Gaussian(centerX, 0.3f);
					if (centerX < 0.5f) {
						centerX = 0.5f;
					}
					ticksToNextLovin = (int)(centerX * 2500f);
				}
				__instance.pawn.mindState.canLovinTick = Find.TickManager.TicksGame + ticksToNextLovin;
			}

			if (__instance.Target.jobs?.curDriver is JobDriver_SexBaseReciever) {
				if (__instance.pawn.TryGetComp<CompBodyAnimator>().isAnimating) {

					List<Pawn> parteners = (__instance.Target.jobs.curDriver as JobDriver_SexBaseReciever).parteners;

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

						//prevents pawns who started a new anim from stopping their new anim
						if (!((parteners[i].jobs.curDriver as JobDriver_SexBaseInitiator) != null && (parteners[i].jobs.curDriver as JobDriver_SexBaseInitiator).Target != __instance.pawn)) {
							parteners[i].TryGetComp<CompBodyAnimator>().isAnimating = false;
						}

					}

					__instance.Target.TryGetComp<CompBodyAnimator>().isAnimating = false;

					if (xxx.is_human(__instance.Target)) {
						__instance.Target.Drawer.renderer.graphics.ResolveApparelGraphics();
						PortraitsCache.SetDirty(__instance.Target);
					}
				}

				(__instance.Target.jobs.curDriver as JobDriver_SexBaseReciever).parteners.Remove(__instance.pawn);

			}

			if (xxx.is_human(__instance.pawn)) {
				__instance.pawn.Drawer.renderer.graphics.ResolveApparelGraphics();
				PortraitsCache.SetDirty(__instance.pawn);
			}
		}
	}
}


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

namespace Rimworld_Animations {
    [HarmonyPatch(typeof(JobGiver_JoinInBed), "TryGiveJob")]
    public static class HarmonyPatch_JoinInBedGiveJob {

        public static bool Prefix(ref Job __result, ref Pawn pawn) {

			__result = null;

			if (!RJWHookupSettings.HookupsEnabled)
				return false;

			if (pawn.Drafted)
				return false;

			if (!SexUtility.ReadyForHookup(pawn))
				return false;

			// We increase the time right away to prevent the fairly expensive check from happening too frequently
			SexUtility.IncreaseTicksToNextHookup(pawn);

			// If the pawn is a whore, or recently had sex, skip the job unless they're really horny
			if (!xxx.is_frustrated(pawn) && (xxx.is_whore(pawn) || !SexUtility.ReadyForLovin(pawn)))
				return false;

			// This check attempts to keep groups leaving the map, like guests or traders, from turning around to hook up
			if (pawn.mindState?.duty?.def == DutyDefOf.TravelOrLeave) {
				// TODO: Some guest pawns keep the TravelOrLeave duty the whole time, I think the ones assigned to guard the pack animals.
				// That's probably ok, though it wasn't the intention.
				if (RJWSettings.DebugLogJoinInBed) Log.Message($"[RJW] JoinInBed.TryGiveJob:({xxx.get_pawnname(pawn)}): has TravelOrLeave, no time for lovin!");
				return false;
			}

			if (pawn.CurJob == null || pawn.CurJob.def == JobDefOf.LayDown) {
				//--Log.Message("   checking pawn and abilities");
				if (xxx.can_fuck(pawn) || xxx.can_be_fucked(pawn)) {
					//--Log.Message("   finding partner");
					Pawn partner = JobGiver_JoinInBed.find_pawn_to_fuck(pawn, pawn.Map);

					//--Log.Message("   checking partner");
					if (partner == null)
						return false;

					// Can never be null, since find checks for bed.
					Building_Bed bed = partner.CurrentBed();

					// Interrupt current job.
					if (pawn.CurJob != null && pawn.jobs.curDriver != null)
						pawn.jobs.curDriver.EndJobWith(JobCondition.InterruptForced);

					__result = JobMaker.MakeJob(DefDatabase<JobDef>.GetNamed("JoinInBedAnimation", true), partner, bed);
					return false;
				}
			}

			return false;

		}

	}
}


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

namespace Rimworld_Animations {

    [HarmonyPatch(typeof(xxx), "sexTick")]
    public static class HarmonyPatch_SexTick {

        public static bool Prefix(ref Pawn pawn, ref Pawn partner, ref bool enablerotation, ref bool pawnnude, ref bool partnernude) {

			if (enablerotation) {
				pawn.rotationTracker.Face(((Thing)partner).DrawPos);
				partner.rotationTracker.Face(((Thing)pawn).DrawPos);
			}
			if (RJWSettings.sounds_enabled && !pawn.TryGetComp<CompBodyAnimator>().isAnimating) {
				SoundDef.Named("Sex").PlayOneShot(new TargetInfo(pawn.Position, pawn.Map));
			}
			pawn.Drawer.Notify_MeleeAttackOn((Thing)(object)partner);
			if (enablerotation) {
				pawn.rotationTracker.FaceCell(partner.Position);
			}
			if (pawnnude && !xxx.has_quirk(pawn, "Endytophile")) {
				xxx.DrawNude(pawn);
			}
			if (partnernude && !xxx.has_quirk(pawn, "Endytophile")) {
				xxx.DrawNude(partner);
			}

			return false;
		}

    }
}


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

namespace Rimworld_Animations {

    [HarmonyPatch(typeof(WorkGiver_Sex), "JobOnThing")]
    public static class HarmonyPatch_WorkGiverSex {

        public static bool Prefix(ref Job __result, ref Thing t) {

            Building_Bed bed = RestUtility.CurrentBed(t as Pawn);
            if (bed == null) {
                return false;
            }
            __result = JobMaker.MakeJob(DefDatabase<JobDef>.GetNamed("JoinInBedAnimation", true), t as Pawn, bed);
            return false;

        }

    }
}


code:
**/Jquery.js
**/mousetrap.js
**/sugarCubeConfig.js
**/format.js
**/displayVariables.js
**/dTree.min.js
**/optionsMacro.js
temp.**
**.temp

repo_name: Welptard/fc

path: .eslintignore

license: mit


code:
{
	"root": true,
	"env": {
		"browser": true,
		"es6": true,
		"jquery": true
	},
	"extends": ["eslint:recommended"],
	"plugins": [
		"jsdoc",
		"sonarjs"
	],
	"globals": {
		"SugarCube": false,
		"Config": false,
		"State": false,
		"Story": false,
		"settings": false,
		"setup": false,
		"App": false,
		"prehistory": true,
		"predisplay": true,
		"prerender": true,
		"postrender": true,
		"postdisplay": true
	},
	"parserOptions": {
		"ecmaVersion": 2019,
		"sourceType": "script",
		"ecmaFeatures": {
			"impliedStrict": true
		}
	},
	"settings": {
		"jsdoc": {
			"mode": "typescript"
		}
	},
	"rules": {
		"no-prototype-builtins": "off",
		"semi": ["warn", "always"],
		"semi-spacing": "warn",
		"semi-style": "warn",
		"block-spacing": ["warn", "always"],
		"curly": ["warn", "all"],
		"eqeqeq": ["warn", "smart"],
		"space-before-function-paren": ["warn", {
			"anonymous": "never",
			"named": "never",
			"asyncArrow": "always"
		}],
		"template-curly-spacing": ["warn", "never"],
		"no-trailing-spaces": "warn",
		"no-mixed-spaces-and-tabs": ["warn", "smart-tabs"],
		"no-unneeded-ternary": "warn",
		"camelcase": "warn",
		"padded-blocks": ["warn", "never"],
		"comma-spacing": "warn",
		"comma-style": "warn",
		"object-curly-newline": ["warn",
			{
				"ObjectExpression":{
					"minProperties": 4,
					"consistent": true
				},
				"ImportDeclaration": {
					"minProperties": 4,
					"consistent": true
				},
				"ExportDeclaration": {
					"minProperties": 4,
					"consistent": true
				},
				"ObjectPattern": {
					"minProperties": 8,
					"consistent": true
				}
			}
		],
		"object-curly-spacing": "warn",
		"no-var": "warn",
		"spaced-comment": "warn",
		"no-undef": "off",
		"indent": ["error", "tab", { "SwitchCase": 1 }],
		"no-unused-vars": ["error", {"args": "none"}],
		"block-scoped-var": "error",
		"dot-notation": "warn",
		"eol-last": "warn",
		"unicode-bom": ["error", "never"],
		"brace-style": ["warn", "1tbs",
			{
				"allowSingleLine": true
			}
		],
		"no-sequences": "warn",
		"no-unreachable-loop": "warn",
		"jsdoc/check-alignment": 1,
		"jsdoc/check-examples": 0, // interferes with SugarCube examples
		"jsdoc/check-indentation": 0,
		"jsdoc/check-param-names": 1,
		"jsdoc/check-property-names": 1,
		"jsdoc/check-syntax": 1,
		"jsdoc/check-tag-names": 1,
		"jsdoc/check-types": 1,
		"jsdoc/implements-on-classes": 1,
		"jsdoc/match-description": 0, // rejects SugarCube syntax
		"jsdoc/newline-after-description": 0,
		"jsdoc/no-types": 0,
		"jsdoc/no-undefined-types": 0,
		"jsdoc/require-jsdoc": 0,
		"jsdoc/require-param": 0,
		"jsdoc/require-param-description": 0,
		"jsdoc/require-param-name": 1,
		"jsdoc/require-param-type": 1,
		"jsdoc/require-returns": 0,
		"jsdoc/require-returns-check": 1,
		"jsdoc/require-returns-description": 0,
		"jsdoc/require-returns-type": 1,
		"jsdoc/valid-types": 1,
		"sonarjs/no-all-duplicated-branches": "error",
		"sonarjs/no-element-overwrite": "error",
		"sonarjs/no-extra-arguments": "error",
		"sonarjs/no-identical-conditions": "error",
		"sonarjs/no-identical-expressions": "error",
		"sonarjs/no-one-iteration-loop": "error",
		"sonarjs/no-use-of-empty-return-value": "error",
		"sonarjs/no-collection-size-mischeck": "warn",
		"sonarjs/no-same-line-conditional": "warn",
		"sonarjs/no-unused-collection": "warn"
	}
}


code:
*.bat	text eol=crlf
*.js	text eol=lf
*.tw	text eol=lf
*.sh	text eol=lf
*.py	text eol=lf
*.txt	text eol=lf

path: .gitattributes


code:
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# Vim stuff
[._]*.s[a-v][a-z]
[._]*.sw[a-p]
[._]s[a-rt-v][a-z]
[._]ss[a-gi-z]
[._]sw[a-p]
Session.vim
Sessionx.vim
.netrwhist
*~
tags
[._]*.un~

# celery beat schedule file
celerybeat-schedule

# dotenv
.env

# virtualenv
venv/
ENV/

# Spyder project settings
.spyderproject

# Rope project settings
.ropeproject

# Start.tw
src/config/start.tw

# eslint
node_modules
package-lock.json
yarn.lock

# Visual Studio Code
.vscode/settings.json
.vscode/tasks.json
*.code-workspace

# WebStorm
.idea

# backup
*.bak
*.gho
*.ori
*.orig
*.tmp

# misc
fc-pregmod
bin/*
*.outline
*.todo
TODO.txt
temp.*
*.temp
src/002-config/fc-version.js.commitHash.js

path: .gitignore


code:
## Expected Behavior
<!--- If you're describing a bug, tell us what should happen -->
<!--- If you're suggesting a change/improvement, tell us how it should work -->

## Current Behavior
<!-- If describing a bug, tell us what happens instead of the expected behavior. Provide a Screenshots if possible. -->
<!-- If suggesting a change/improvement, explain the difference from current behavior -->

## Possible Solution
<!-- Not obligatory, but suggest a fix/reason for the bug, -->
<!-- or ideas how to implement the addition or change -->

## Steps to Reproduce (for bugs)
<!-- Provide an unambiguous sequence of steps to reproduce the bug. -->
1.
2.
3.
4.

## Additional information
<!-- Release ID and commit can be found on the starting splash screen or the options page. -->
* Release ID:
* Commit: (if available)
* Save file


code:
[submodule "submodules/sugarcube-2"]
	path = submodules/sugarcube-2
	url = https://gitgud.io/Arkerthan/sugarcube-2.git
	branch = fc

path: .gitmodules


brace_style: collapse,preserve-inline

path: .jsbeautifyrc


code:
// Minified files
**/dTree.min.js
**/js/displayVariables.js

path: .jshintignore