diff --git a/.gitignore b/.gitignore
index 4ce6fdd..1c79e0c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -337,4 +337,14 @@ ASALocalRun/
.localhistory/
# BeatPulse healthcheck temp database
-healthchecksdb
\ No newline at end of file
+healthchecksdb
+/Source/Patches/PawnAnimationPatches/HarmonyPatch_Pawn_DrawTracker.cs
+/Source/Patches/PawnAnimationPatches/HarmonyPatch_PawnRotation.cs
+/Source/Patches/PawnAnimationPatches/HarmonyPatch_PawnRenderer.cs
+/Source/Patches/OtherModPatches/HarmonyPatch_ShowHairWithHats.cs
+/Source/Patches/OtherModPatches/HarmonyPatch_FacialAnimation.cs
+/Source/Patches/OtherModPatches/HarmonyPatch_DontShaveYourHead.cs
+/Source/Patches/OtherModPatches/HarmonyPatch_CSL.cs
+/Source/Patches/OtherModPatches/HarmonyPatch_AlienRace.cs
+/Source/Patches/ThingAnimationPatches/HarmonyPatch_ThingDrawAt.cs
+/Defs/AnimationDefs/Animations_SexToys.xml
diff --git a/1.1/Assemblies/0Harmony.dll b/1.1/Assemblies/0Harmony.dll
deleted file mode 100644
index 947c81c..0000000
Binary files a/1.1/Assemblies/0Harmony.dll and /dev/null differ
diff --git a/1.1/Assemblies/0Harmony.xml b/1.1/Assemblies/0Harmony.xml
deleted file mode 100644
index 6bcea2e..0000000
--- a/1.1/Assemblies/0Harmony.xml
+++ /dev/null
@@ -1,2900 +0,0 @@
-
-
-
- 0Harmony
-
-
-
- A factory to create delegate types
-
-
- Default constructor
-
-
- Creates a delegate type for a method
- The method
- The new delegate type
-
-
-
- A getter delegate type
- Type that getter gets field/property value from
- Type of the value that getter gets
- The instance get getter uses
- An delegate
-
-
-
- A setter delegate type
- Type that setter sets field/property value for
- Type of the value that setter sets
- The instance the setter uses
- The value the setter uses
- An delegate
-
-
-
- A constructor delegate type
- Type that constructor creates
- An delegate
-
-
-
- A helper class for fast access to getters and setters
-
-
- Creates an instantiation delegate
- Type that constructor creates
- The new instantiation delegate
-
-
-
- Creates an getter delegate for a property
- Type that getter reads property from
- Type of the property that gets accessed
- The property
- The new getter delegate
-
-
-
- Creates an getter delegate for a field
- Type that getter reads field from
- Type of the field that gets accessed
- The field
- The new getter delegate
-
-
-
- Creates an getter delegate for a field (with a list of possible field names)
- Type that getter reads field/property from
- Type of the field/property that gets accessed
- A list of possible field names
- The new getter delegate
-
-
-
- Creates an setter delegate
- Type that setter assigns property value to
- Type of the property that gets assigned
- The property
- The new setter delegate
-
-
-
- Creates an setter delegate for a field
- Type that setter assigns field value to
- Type of the field that gets assigned
- The field
- The new getter delegate
-
-
-
- A delegate to invoke a method
- The instance
- The method parameters
- The method result
-
-
- A helper class to invoke method with delegates
-
-
- Creates a fast invocation handler from a method
- The method to invoke
- Controls if boxed value object is accessed/updated directly
- The
-
-
- The directBoxValueAccess option controls how value types passed by reference (e.g. ref int, out my_struct) are handled in the arguments array
- passed to the fast invocation handler.
- Since the arguments array is an object array, any value types contained within it are actually references to a boxed value object.
- Like any other object, there can be other references to such boxed value objects, other than the reference within the arguments array.
- For example,
-
- var val = 5;
- var box = (object)val;
- var arr = new object[] { box };
- handler(arr); // for a method with parameter signature: ref/out/in int
-
-
-
-
- If directBoxValueAccess is true , the boxed value object is accessed (and potentially updated) directly when the handler is called,
- such that all references to the boxed object reflect the potentially updated value.
- In the above example, if the method associated with the handler updates the passed (boxed) value to 10, both box and arr[0]
- now reflect the value 10. Note that the original val is not updated, since boxing always copies the value into the new boxed value object.
-
-
- If directBoxValueAccess is false (default), the boxed value object in the arguments array is replaced with a "reboxed" value object,
- such that potential updates to the value are reflected only in the arguments array.
- In the above example, if the method associated with the handler updates the passed (boxed) value to 10, only arr[0] now reflects the value 10.
-
-
-
-
- A low level memory helper
-
-
- Mark method for no inlining (currently only works on Mono)
- The method/constructor to change
-
-
- Detours a method
- The original method/constructor
- The replacement method/constructor
- An error string
-
-
-
- Writes a jump to memory
- The memory address
- Jump destination
- An error string
-
-
-
- Gets the start of a method in memory
- The method/constructor
- [out] Details of the exception
- The method start address
-
-
-
- special parameter names that can be used in prefix and postfix methods
-
-
- Patch function helpers
-
-
- Adds a prefix
- The patch info
- The owner (Harmony ID)
- The annotation info
-
-
-
- Removes a prefix
- The patch info
- The owner (Harmony ID)
-
-
-
- Adds a postfix
- The patch info
- The owner (Harmony ID)
- The annotation info
-
-
-
- Removes a postfix
- The patch info
- The owner (Harmony ID)
-
-
-
- Adds a transpiler
- The patch info
- The owner (Harmony ID)
- The annotation info
-
-
-
- Removes a transpiler
- The patch info
- The owner (Harmony ID)
-
-
-
- Adds a finalizer
- The patch info
- The owner (Harmony ID)
- The annotation info
-
-
-
- Removes a finalizer
- The patch info
- The owner (Harmony ID)
-
-
-
- Removes a patch method
- The patch info
- The patch method
-
-
-
- Sorts patch methods by their priority rules
- The original method
- Patches to sort
- Use debug mode
- The sorted patch methods
-
-
-
- Creates new replacement method with the latest patches and detours the original method
- The original method
- Information describing the patches
- The newly created replacement method
-
-
-
- Creates a patch sorter
- Array of patches that will be sorted
- Use debugging
-
-
- Sorts internal PatchSortingWrapper collection and caches the results.
- After first run the result is provided from the cache.
- The original method
- The sorted patch methods
-
-
- Checks if the sorter was created with the same patch list and as a result can be reused to
- get the sorted order of the patches.
- List of patches to check against
- true if equal
-
-
- Removes one unresolved dependency from the least important patch.
-
-
- Outputs all unblocked patches from the waiting list to results list
-
-
- Adds patch to both results list and handled patches set
- Patch to add
-
-
- Wrapper used over the Patch object to allow faster dependency access and
- dependency removal in case of cyclic dependencies
-
-
- Create patch wrapper object used for sorting
- Patch to wrap
-
-
- Determines how patches sort
- The other patch
- integer to define sort order (-1, 0, 1)
-
-
- Determines whether patches are equal
- The other patch
- true if equal
-
-
- Hash function
- A hash code
-
-
- Bidirectionally registers Patches as after dependencies
- List of dependencies to register
-
-
- Bidirectionally registers Patches as before dependencies
- List of dependencies to register
-
-
- Bidirectionally removes Patch from after dependencies
- Patch to remove
-
-
- Bidirectionally removes Patch from before dependencies
- Patch to remove
-
-
- Specifies the type of method
-
-
-
- This is a normal method
-
-
- This is a getter
-
-
- This is a setter
-
-
- This is a constructor
-
-
- This is a static constructor
-
-
- Specifies the type of argument
-
-
-
- This is a normal argument
-
-
- This is a reference argument (ref)
-
-
- This is an out argument (out)
-
-
- This is a pointer argument (&)
-
-
- Specifies the type of patch
-
-
-
- Any patch
-
-
- A prefix patch
-
-
- A postfix patch
-
-
- A transpiler
-
-
- A finalizer
-
-
- A reverse patch
-
-
- Specifies the type of reverse patch
-
-
-
- Use the unmodified original method (directly from IL)
-
-
- Use the original as it is right now including previous patches but excluding future ones
-
-
- Specifies the type of method call dispatching mechanics
-
-
-
- Call the method using dynamic dispatching if method is virtual (including overriden)
-
-
- This is the built-in form of late binding (a.k.a. dynamic binding) and is the default dispatching mechanic in C#.
- This directly corresponds with the instruction.
-
-
- For virtual (including overriden) methods, the instance type's most-derived/overriden implementation of the method is called.
- For non-virtual (including static) methods, same behavior as : the exact specified method implementation is called.
-
-
- Note: This is not a fully dynamic dispatch, since non-virtual (including static) methods are still called non-virtually.
- A fully dynamic dispatch in C# involves using
- the dynamic type
- (actually a fully dynamic binding, since even the name and overload resolution happens at runtime), which does not support.
-
-
-
-
- Call the method using static dispatching, regardless of whether method is virtual (including overriden) or non-virtual (including static)
-
-
- a.k.a. non-virtual dispatching, early binding, or static binding.
- This directly corresponds with the instruction.
-
-
- For both virtual (including overriden) and non-virtual (including static) methods, the exact specified method implementation is called, without virtual/override mechanics.
-
-
-
-
- The base class for all Harmony annotations (not meant to be used directly)
-
-
-
- The common information for all attributes
-
-
- Annotation to define your Harmony patch methods
-
-
-
- An empty annotation can be used together with TargetMethod(s)
-
-
-
- An annotation that specifies a class to patch
- The declaring class/type
-
-
-
- An annotation that specifies a method, property or constructor to patch
- The declaring class/type
- The argument types of the method or constructor to patch
-
-
-
- An annotation that specifies a method, property or constructor to patch
- The declaring class/type
- The name of the method, property or constructor to patch
-
-
-
- An annotation that specifies a method, property or constructor to patch
- The declaring class/type
- The name of the method, property or constructor to patch
- An array of argument types to target overloads
-
-
-
- An annotation that specifies a method, property or constructor to patch
- The declaring class/type
- The name of the method, property or constructor to patch
- An array of argument types to target overloads
- Array of
-
-
-
- An annotation that specifies a method, property or constructor to patch
- The declaring class/type
- The
-
-
-
- An annotation that specifies a method, property or constructor to patch
- The declaring class/type
- The
- An array of argument types to target overloads
-
-
-
- An annotation that specifies a method, property or constructor to patch
- The declaring class/type
- The
- An array of argument types to target overloads
- Array of
-
-
-
- An annotation that specifies a method, property or constructor to patch
- The declaring class/type
- The name of the method, property or constructor to patch
- The
-
-
-
- An annotation that specifies a method, property or constructor to patch
- The name of the method, property or constructor to patch
-
-
-
- An annotation that specifies a method, property or constructor to patch
- The name of the method, property or constructor to patch
- An array of argument types to target overloads
-
-
-
- An annotation that specifies a method, property or constructor to patch
- The name of the method, property or constructor to patch
- An array of argument types to target overloads
- An array of
-
-
-
- An annotation that specifies a method, property or constructor to patch
- The name of the method, property or constructor to patch
- The
-
-
-
- An annotation that specifies a method, property or constructor to patch
- The
-
-
-
- An annotation that specifies a method, property or constructor to patch
- The
- An array of argument types to target overloads
-
-
-
- An annotation that specifies a method, property or constructor to patch
- The
- An array of argument types to target overloads
- An array of
-
-
-
- An annotation that specifies a method, property or constructor to patch
- An array of argument types to target overloads
-
-
-
- An annotation that specifies a method, property or constructor to patch
- An array of argument types to target overloads
- An array of
-
-
-
- Annotation to define the original method for delegate injection
-
-
-
- An annotation that specifies a class to patch
- The declaring class/type
-
-
-
- An annotation that specifies a method, property or constructor to patch
- The declaring class/type
- The argument types of the method or constructor to patch
-
-
-
- An annotation that specifies a method, property or constructor to patch
- The declaring class/type
- The name of the method, property or constructor to patch
-
-
-
- An annotation that specifies a method, property or constructor to patch
- The declaring class/type
- The name of the method, property or constructor to patch
- An array of argument types to target overloads
-
-
-
- An annotation that specifies a method, property or constructor to patch
- The declaring class/type
- The name of the method, property or constructor to patch
- An array of argument types to target overloads
- Array of
-
-
-
- An annotation that specifies a method, property or constructor to patch
- The declaring class/type
- The
-
-
-
- An annotation that specifies a method, property or constructor to patch
- The declaring class/type
- The
- An array of argument types to target overloads
-
-
-
- An annotation that specifies a method, property or constructor to patch
- The declaring class/type
- The
- An array of argument types to target overloads
- Array of
-
-
-
- An annotation that specifies a method, property or constructor to patch
- The declaring class/type
- The name of the method, property or constructor to patch
- The
-
-
-
- An annotation that specifies a method, property or constructor to patch
- The name of the method, property or constructor to patch
-
-
-
- An annotation that specifies a method, property or constructor to patch
- The name of the method, property or constructor to patch
- An array of argument types to target overloads
-
-
-
- An annotation that specifies a method, property or constructor to patch
- The name of the method, property or constructor to patch
- An array of argument types to target overloads
- An array of
-
-
-
- An annotation that specifies a method, property or constructor to patch
- The name of the method, property or constructor to patch
- The
-
-
-
- An annotation that specifies call dispatching mechanics for the delegate
- The
-
-
-
- An annotation that specifies a method, property or constructor to patch
- The
- An array of argument types to target overloads
-
-
-
- An annotation that specifies a method, property or constructor to patch
- The
- An array of argument types to target overloads
- An array of
-
-
-
- An annotation that specifies a method, property or constructor to patch
- An array of argument types to target overloads
-
-
-
- An annotation that specifies a method, property or constructor to patch
- An array of argument types to target overloads
- An array of
-
-
-
- Annotation to define your standin methods for reverse patching
-
-
-
- An annotation that specifies the type of reverse patching
- The of the reverse patch
-
-
-
- A Harmony annotation to define that all methods in a class are to be patched
-
-
-
- A Harmony annotation
-
-
-
- A Harmony annotation to define patch priority
- The priority
-
-
-
- A Harmony annotation
-
-
-
- A Harmony annotation to define that a patch comes before another patch
- The array of harmony IDs of the other patches
-
-
-
- A Harmony annotation
-
-
- A Harmony annotation to define that a patch comes after another patch
- The array of harmony IDs of the other patches
-
-
-
- A Harmony annotation
-
-
- A Harmony annotation to debug a patch (output uses to log to your Desktop)
-
-
-
- Specifies the Prepare function in a patch class
-
-
-
- Specifies the Cleanup function in a patch class
-
-
-
- Specifies the TargetMethod function in a patch class
-
-
-
- Specifies the TargetMethods function in a patch class
-
-
-
- Specifies the Prefix function in a patch class
-
-
-
- Specifies the Postfix function in a patch class
-
-
-
- Specifies the Transpiler function in a patch class
-
-
-
- Specifies the Finalizer function in a patch class
-
-
-
- A Harmony annotation
-
-
-
- The name of the original argument
-
-
-
- The index of the original argument
-
-
-
- The new name of the original argument
-
-
-
- An annotation to declare injected arguments by name
-
-
-
- An annotation to declare injected arguments by index
- Zero-based index
-
-
-
- An annotation to declare injected arguments by renaming them
- Name of the original argument
- New name
-
-
-
- An annotation to declare injected arguments by index and renaming them
- Zero-based index
- New name
-
-
-
- An abstract wrapper around OpCode and their operands. Used by transpilers
-
-
-
- The opcode
-
-
-
- The operand
-
-
-
- All labels defined on this instruction
-
-
-
- All exception block boundaries defined on this instruction
-
-
-
- Creates a new CodeInstruction with a given opcode and optional operand
- The opcode
- The operand
-
-
-
- Create a full copy (including labels and exception blocks) of a CodeInstruction
- The to copy
-
-
-
- Clones a CodeInstruction and resets its labels and exception blocks
- A lightweight copy of this code instruction
-
-
-
- Clones a CodeInstruction, resets labels and exception blocks and sets its opcode
- The opcode
- A copy of this CodeInstruction with a new opcode
-
-
-
- Clones a CodeInstruction, resets labels and exception blocks and sets its operand
- The operand
- A copy of this CodeInstruction with a new operand
-
-
-
- Creates a CodeInstruction calling a method (CALL)
- The class/type where the method is declared
- The name of the method (case sensitive)
- Optional parameters to target a specific overload of the method
- Optional list of types that define the generic version of the method
- A code instruction that calls the method matching the arguments
-
-
-
- Creates a CodeInstruction calling a method (CALL)
- The target method in the form TypeFullName:MethodName , where the type name matches a form recognized by Type.GetType like Some.Namespace.Type .
- Optional parameters to target a specific overload of the method
- Optional list of types that define the generic version of the method
- A code instruction that calls the method matching the arguments
-
-
-
- Creates a CodeInstruction calling a method (CALL)
- The lambda expression using the method
-
-
-
-
- Creates a CodeInstruction calling a method (CALL)
- The lambda expression using the method
-
-
-
-
- Creates a CodeInstruction calling a method (CALL)
- The lambda expression using the method
-
-
-
-
- Creates a CodeInstruction calling a method (CALL)
- The lambda expression using the method
-
-
-
-
- Creates a CodeInstruction loading a field (LD[S]FLD[A])
- The class/type where the field is defined
- The name of the field (case sensitive)
- Use address of field
-
-
-
- Creates a CodeInstruction storing to a field (ST[S]FLD)
- The class/type where the field is defined
- The name of the field (case sensitive)
-
-
-
- Returns a string representation of the code instruction
- A string representation of the code instruction
-
-
-
- Exception block types
-
-
-
- The beginning of an exception block
-
-
-
- The beginning of a catch block
-
-
-
- The beginning of an except filter block
-
-
-
- The beginning of a fault block
-
-
-
- The beginning of a finally block
-
-
-
- The end of an exception block
-
-
-
- An exception block
-
-
-
- Block type
-
-
-
- Catch type
-
-
-
- Creates an exception block
- The
- The catch type
-
-
-
- The Harmony instance is the main entry to Harmony. After creating one with an unique identifier, it is used to patch and query the current application domain
-
-
-
- The unique identifier
-
-
-
- Set to true before instantiating Harmony to debug Harmony or use an environment variable to set HARMONY_DEBUG to '1' like this: cmd /C "set HARMONY_DEBUG=1 && game.exe"
- This is for full debugging. To debug only specific patches, use the attribute
-
-
-
- Creates a new Harmony instance
- A unique identifier (you choose your own)
- A Harmony instance
-
-
-
- Searches the current assembly for Harmony annotations and uses them to create patches
-
-
-
- Creates a empty patch processor for an original method
- The original method/constructor
- A new instance
-
-
-
- Creates a patch class processor from an annotated class
- The class/type
- A new instance
-
-
-
- Creates a reverse patcher for one of your stub methods
- The original method/constructor
- The stand-in stub method as
- A new instance
-
-
-
- Searches an assembly for Harmony annotations and uses them to create patches
- The assembly
-
-
-
- Creates patches by manually specifying the methods
- The original method/constructor
- An optional prefix method wrapped in a object
- An optional postfix method wrapped in a object
- An optional transpiler method wrapped in a object
- An optional finalizer method wrapped in a object
- The replacement method that was created to patch the original method
-
-
-
- Patches a foreign method onto a stub method of yours and optionally applies transpilers during the process
- The original method/constructor you want to duplicate
- Your stub method as that will become the original. Needs to have the correct signature (either original or whatever your transpilers generates)
- An optional transpiler as method that will be applied during the process
- The replacement method that was created to patch the stub method
-
-
-
- Unpatches methods by patching them with zero patches. Fully unpatching is not supported. Be careful, unpatching is global
- The optional Harmony ID to restrict unpatching to a specific Harmony instance
- This method could be static if it wasn't for the fact that unpatching creates a new replacement method that contains your harmony ID
-
-
-
- Unpatches a method by patching it with zero patches. Fully unpatching is not supported. Be careful, unpatching is global
- The original method/constructor
- The
- The optional Harmony ID to restrict unpatching to a specific Harmony instance
-
-
-
- Unpatches a method by patching it with zero patches. Fully unpatching is not supported. Be careful, unpatching is global
- The original method/constructor
- The patch method as method to remove
-
-
-
- Test for patches from a specific Harmony ID
- The Harmony ID
- True if patches for this ID exist
-
-
-
- Gets patch information for a given original method
- The original method/constructor
- The patch information as
-
-
-
- Gets the methods this instance has patched
- An enumeration of original methods/constructors
-
-
-
- Gets all patched original methods in the appdomain
- An enumeration of patched original methods/constructors
-
-
-
- Gets Harmony version for all active Harmony instances
- [out] The current Harmony version
- A dictionary containing assembly versions keyed by Harmony IDs
-
-
-
- Under Mono, HarmonyException wraps IL compile errors with detailed information about the failure
-
-
-
- Default serialization constructor (not implemented)
- The info
- The context
-
-
-
- Get a list of IL instructions in pairs of offset+code
- A list of key/value pairs which represent an offset and the code at that offset
-
-
-
- Get a list of IL instructions without offsets
- A list of
-
-
-
- Get the error offset of the errornous IL instruction
- The offset
-
-
-
- Get the index of the errornous IL instruction
- The index into the list of instructions or -1 if not found
-
-
-
- A wrapper around a method to use it as a patch (for example a Prefix)
-
-
-
- The original method
-
-
-
- Class/type declaring this patch
-
-
-
- Patch method name
-
-
-
- Optional patch
-
-
-
- Array of argument types of the patch method
-
-
-
- of the patch
-
-
-
- Install this patch before patches with these Harmony IDs
-
-
-
- Install this patch after patches with these Harmony IDs
-
-
-
- Reverse patch type, see
-
-
-
- Create debug output for this patch
-
-
-
- Whether to use (true ) or (false ) mechanics
- for -attributed delegate
-
-
-
- Default constructor
-
-
-
- Creates a patch from a given method
- The original method
-
-
-
- Creates a patch from a given method
- The original method
- The patch
- A list of harmony IDs that should come after this patch
- A list of harmony IDs that should come before this patch
- Set to true to generate debug output
-
-
-
- Creates a patch from a given method
- The patch class/type
- The patch method name
- The optional argument types of the patch method (for overloaded methods)
-
-
-
- Gets the names of all internal patch info fields
- A list of field names
-
-
-
- Merges annotations
- The list of to merge
- The merged
-
-
-
- Returns a string that represents the annotation
- A string representation
-
-
-
- Annotation extensions
-
-
-
- Copies annotation information
- The source
- The destination
-
-
-
- Clones an annotation
- The to clone
- A copied
-
-
-
- Merges annotations
- The master
- The detail
- A new, merged
-
-
-
- Gets all annotations on a class/type
- The class/type
- A list of all
-
-
-
- Gets merged annotations on a class/type
- The class/type
- The merged
-
-
-
- Gets all annotations on a method
- The method/constructor
- A list of
-
-
-
- Gets merged annotations on a method
- The method/constructor
- The merged
-
-
-
-
- A mutable representation of an inline signature, similar to Mono.Cecil's CallSite.
- Used by the calli instruction, can be used by transpilers
-
-
-
-
- See
-
-
-
- See
-
-
-
- See
-
-
-
- The list of all parameter types or function pointer signatures received by the call site
-
-
-
- The return type or function pointer signature returned by the call site
-
-
-
- Returns a string representation of the inline signature
- A string representation of the inline signature
-
-
-
-
- A mutable representation of a parameter type with an attached type modifier,
- similar to Mono.Cecil's OptionalModifierType / RequiredModifierType and C#'s modopt / modreq
-
-
-
-
- Whether this is a modopt (optional modifier type) or a modreq (required modifier type)
-
-
-
- The modifier type attached to the parameter type
-
-
-
- The modified parameter type
-
-
-
- Returns a string representation of the modifier type
- A string representation of the modifier type
-
-
-
- Patch serialization
-
-
-
- Control the binding of a serialized object to a type
- Specifies the assembly name of the serialized object
- Specifies the type name of the serialized object
- The type of the object the formatter creates a new instance of
-
-
-
- Serializes a patch info
- The
- The serialized data
-
-
-
- Deserialize a patch info
- The serialized data
- A
-
-
-
- Compare function to sort patch priorities
- The patch
- Zero-based index
- The priority
- A standard sort integer (-1, 0, 1)
-
-
-
- Serializable patch information
-
-
-
- Prefixes as an array of
-
-
-
- Postfixes as an array of
-
-
-
- Transpilers as an array of
-
-
-
- Finalizers as an array of
-
-
-
- Default constructor
-
-
-
- Returns if any of the patches wants debugging turned on
-
-
-
- Adds a prefix
-
- The prefix method
- An owner (Harmony ID)
- The priority, see
- A list of Harmony IDs for prefixes that should run after this prefix
- A list of Harmony IDs for prefixes that should run before this prefix
- A flag that will log the replacement method via every time this prefix is used to build the replacement, even in the future
-
-
-
- Removes prefixes
- The owner of the prefix or * for any prefix
-
-
-
- Adds a postfix
- The postfix method
- An owner (Harmony ID)
- The priority, see
- A list of Harmony IDs for postfixes that should run after this postfix
- A list of Harmony IDs for postfixes that should run before this postfix
- A flag that will log the replacement method via every time this postfix is used to build the replacement, even in the future
-
-
-
- Removes postfixes
- The owner of the postfix or * for any postfix
-
-
-
- Adds a transpiler
- The transpiler method
- An owner (Harmony ID)
- The priority, see
- A list of Harmony IDs for transpilers that should run after this transpiler
- A list of Harmony IDs for transpilers that should run before this transpiler
- A flag that will log the replacement method via every time this patch is used to build the replacement, even in the future
-
-
-
- Removes transpilers
- The owner of the transpiler or * for any transpiler
-
-
-
- Adds a finalizer
- The finalizer method
- An owner (Harmony ID)
- The priority, see
- A list of Harmony IDs for finalizers that should run after this finalizer
- A list of Harmony IDs for finalizers that should run before this finalizer
- A flag that will log the replacement method via every time this patch is used to build the replacement, even in the future
-
-
-
- Removes finalizers
- The owner of the finalizer or * for any finalizer
-
-
-
- Removes a patch using its method
- The method of the patch to remove
-
-
-
- A serializable patch
-
-
-
- Zero-based index
-
-
-
- The owner (Harmony ID)
-
-
-
- The priority, see
-
-
-
- Keep this patch before the patches indicated in the list of Harmony IDs
-
-
-
- Keep this patch after the patches indicated in the list of Harmony IDs
-
-
-
- A flag that will log the replacement method via every time this patch is used to build the replacement, even in the future
-
-
-
- The method of the static patch method
-
-
-
- Creates a patch
- The method of the patch
- Zero-based index
- An owner (Harmony ID)
- The priority, see
- A list of Harmony IDs for patches that should run after this patch
- A list of Harmony IDs for patches that should run before this patch
- A flag that will log the replacement method via every time this patch is used to build the replacement, even in the future
-
-
-
- Get the patch method or a DynamicMethod if original patch method is a patch factory
- The original method/constructor
- The method of the patch
-
-
-
- Determines whether patches are equal
- The other patch
- true if equal
-
-
-
- Determines how patches sort
- The other patch
- integer to define sort order (-1, 0, 1)
-
-
-
- Hash function
- A hash code
-
-
-
- A PatchClassProcessor used to turn on a class/type into patches
-
-
-
- Creates a patch class processor by pointing out a class. Similar to PatchAll() but without searching through all classes.
- The Harmony instance
- The class to process (need to have at least a [HarmonyPatch] attribute)
-
-
-
- Applies the patches
- A list of all created replacement methods or null if patch class is not annotated
-
-
-
- A group of patches
-
-
-
- A collection of prefix
-
-
-
- A collection of postfix
-
-
-
- A collection of transpiler
-
-
-
- A collection of finalizer
-
-
-
- Gets all owners (Harmony IDs) or all known patches
- The patch owners
-
-
-
- Creates a group of patches
- An array of prefixes as
- An array of postfixes as
- An array of transpileres as
- An array of finalizeres as
-
-
-
- A PatchProcessor handles patches on a method/constructor
-
-
-
- Creates an empty patch processor
- The Harmony instance
- The original method/constructor
-
-
-
- Adds a prefix
- The prefix as a
- A for chaining calls
-
-
-
- Adds a prefix
- The prefix method
- A for chaining calls
-
-
-
- Adds a postfix
- The postfix as a
- A for chaining calls
-
-
-
- Adds a postfix
- The postfix method
- A for chaining calls
-
-
-
- Adds a transpiler
- The transpiler as a
- A for chaining calls
-
-
-
- Adds a transpiler
- The transpiler method
- A for chaining calls
-
-
-
- Adds a finalizer
- The finalizer as a
- A for chaining calls
-
-
-
- Adds a finalizer
- The finalizer method
- A for chaining calls
-
-
-
- Gets all patched original methods in the appdomain
- An enumeration of patched method/constructor
-
-
-
- Applies all registered patches
- The generated replacement method
-
-
-
- Unpatches patches of a given type and/or Harmony ID
- The patch type
- Harmony ID or * for any
- A for chaining calls
-
-
-
- Unpatches a specific patch
- The method of the patch
- A for chaining calls
-
-
-
- Gets patch information on an original
- The original method/constructor
- The patch information as
-
-
-
- Sort patch methods by their priority rules
- The original method
- Patches to sort
- The sorted patch methods
-
-
-
- Gets Harmony version for all active Harmony instances
- [out] The current Harmony version
- A dictionary containing assembly version keyed by Harmony ID
-
-
-
- Creates a new empty generator to use when reading method bodies
- A new
-
-
-
- Creates a new generator matching the method/constructor to use when reading method bodies
- The original method/constructor to copy method information from
- A new
-
-
-
- Returns the methods unmodified list of code instructions
- The original method/constructor
- Optionally an existing generator that will be used to create all local variables and labels contained in the result (if not specified, an internal generator is used)
- A list containing all the original
-
-
-
- Returns the methods unmodified list of code instructions
- The original method/constructor
- A new generator that now contains all local variables and labels contained in the result
- A list containing all the original
-
-
-
- Returns the methods current list of code instructions after all existing transpilers have been applied
- The original method/constructor
- Apply only the first count of transpilers
- Optionally an existing generator that will be used to create all local variables and labels contained in the result (if not specified, an internal generator is used)
- A list of
-
-
-
- Returns the methods current list of code instructions after all existing transpilers have been applied
- The original method/constructor
- A new generator that now contains all local variables and labels contained in the result
- Apply only the first count of transpilers
- A list of
-
-
-
- A low level way to read the body of a method. Used for quick searching in methods
- The original method
- All instructions as opcode/operand pairs
-
-
-
- A low level way to read the body of a method. Used for quick searching in methods
- The original method
- An existing generator that will be used to create all local variables and labels contained in the result
- All instructions as opcode/operand pairs
-
-
-
- A patch priority
-
-
-
- Patch last
-
-
-
- Patch with very low priority
-
-
-
- Patch with low priority
-
-
-
- Patch with lower than normal priority
-
-
-
- Patch with normal priority
-
-
-
- Patch with higher than normal priority
-
-
-
- Patch with high priority
-
-
-
- Patch with very high priority
-
-
-
- Patch first
-
-
-
- A reverse patcher
-
-
-
- Creates a reverse patcher
- The Harmony instance
- The original method/constructor
- Your stand-in stub method as
-
-
-
- Applies the patch
- The type of patch, see
- The generated replacement method
-
-
-
- A collection of commonly used transpilers
-
-
-
- A transpiler that replaces all occurrences of a given method with another one
- The enumeration of to act on
- Method or constructor to search for
- Method or constructor to replace with
- Modified enumeration of
-
-
-
- A transpiler that alters instructions that match a predicate by calling an action
- The enumeration of to act on
- A predicate selecting the instructions to change
- An action to apply to matching instructions
- Modified enumeration of
-
-
-
- A transpiler that logs a text at the beginning of the method
- The instructions to act on
- The log text
- Modified enumeration of
-
-
-
- A helper class for reflection related functions
-
-
-
- Shortcut for to simplify the use of reflections and make it work for any access level
-
-
-
- Shortcut for to simplify the use of reflections and make it work for any access level but only within the current type
-
-
-
- Gets a type by name. Prefers a full name with namespace but falls back to the first type matching the name otherwise
- The name
- A type or null if not found
-
-
-
- Gets all successfully loaded types from a given assembly
- The assembly
- An array of types
-
- This calls and returns , while catching any thrown .
- If such an exception is thrown, returns the successfully loaded types ( ,
- filtered for non-null values).
-
-
-
-
- Applies a function going up the type hierarchy and stops at the first non null result
- Result type of func()
- The class/type to start with
- The evaluation function returning T
- Returns the first non null result or default(T) when reaching the top level type object
-
-
-
- Applies a function going into inner types and stops at the first non null result
- Generic type parameter
- The class/type to start with
- The evaluation function returning T
- Returns the first non null result or null with no match
-
-
-
- Gets the reflection information for a directly declared field
- The class/type where the field is defined
- The name of the field
- A field or null when type/name is null or when the field cannot be found
-
-
-
- Gets the reflection information for a field by searching the type and all its super types
- The class/type where the field is defined
- The name of the field (case sensitive)
- A field or null when type/name is null or when the field cannot be found
-
-
-
- Gets the reflection information for a field
- The class/type where the field is declared
- The zero-based index of the field inside the class definition
- A field or null when type is null or when the field cannot be found
-
-
-
- Gets the reflection information for a directly declared property
- The class/type where the property is declared
- The name of the property (case sensitive)
- A property or null when type/name is null or when the property cannot be found
-
-
-
- Gets the reflection information for the getter method of a directly declared property
- The class/type where the property is declared
- The name of the property (case sensitive)
- A method or null when type/name is null or when the property cannot be found
-
-
-
- Gets the reflection information for the setter method of a directly declared property
- The class/type where the property is declared
- The name of the property (case sensitive)
- A method or null when type/name is null or when the property cannot be found
-
-
-
- Gets the reflection information for a property by searching the type and all its super types
- The class/type
- The name
- A property or null when type/name is null or when the property cannot be found
-
-
-
- Gets the reflection information for the getter method of a property by searching the type and all its super types
- The class/type
- The name
- A method or null when type/name is null or when the property cannot be found
-
-
-
- Gets the reflection information for the setter method of a property by searching the type and all its super types
- The class/type
- The name
- A method or null when type/name is null or when the property cannot be found
-
-
-
- Gets the reflection information for a directly declared method
- The class/type where the method is declared
- The name of the method (case sensitive)
- Optional parameters to target a specific overload of the method
- Optional list of types that define the generic version of the method
- A method or null when type/name is null or when the method cannot be found
-
-
-
- Gets the reflection information for a method by searching the type and all its super types
- The class/type where the method is declared
- The name of the method (case sensitive)
- Optional parameters to target a specific overload of the method
- Optional list of types that define the generic version of the method
- A method or null when type/name is null or when the method cannot be found
-
-
-
- Gets the reflection information for a method by searching the type and all its super types
- The target method in the form TypeFullName:MethodName , where the type name matches a form recognized by Type.GetType like Some.Namespace.Type .
- Optional parameters to target a specific overload of the method
- Optional list of types that define the generic version of the method
- A method or null when type/name is null or when the method cannot be found
-
-
-
- Gets the names of all method that are declared in a type
- The declaring class/type
- A list of method names
-
-
-
- Gets the names of all method that are declared in the type of the instance
- An instance of the type to search in
- A list of method names
-
-
-
- Gets the names of all fields that are declared in a type
- The declaring class/type
- A list of field names
-
-
-
- Gets the names of all fields that are declared in the type of the instance
- An instance of the type to search in
- A list of field names
-
-
-
- Gets the names of all properties that are declared in a type
- The declaring class/type
- A list of property names
-
-
-
- Gets the names of all properties that are declared in the type of the instance
- An instance of the type to search in
- A list of property names
-
-
-
- Gets the type of any class member of
- A member
- The class/type of this member
-
-
-
- Test if a class member is actually an concrete implementation
- A member
- True if the member is a declared
-
-
-
- Gets the real implementation of a class member
- A member
- The member itself if its declared. Otherwise the member that is actually implemented in some base type
-
-
-
- Gets the reflection information for a directly declared constructor
- The class/type where the constructor is declared
- Optional parameters to target a specific overload of the constructor
- Optional parameters to only consider static constructors
- A constructor info or null when type is null or when the constructor cannot be found
-
-
-
- Gets the reflection information for a constructor by searching the type and all its super types
- The class/type where the constructor is declared
- Optional parameters to target a specific overload of the method
- Optional parameters to only consider static constructors
- A constructor info or null when type is null or when the method cannot be found
-
-
-
- Gets reflection information for all declared constructors
- The class/type where the constructors are declared
- Optional parameters to only consider static constructors
- A list of constructor infos
-
-
-
- Gets reflection information for all declared methods
- The class/type where the methods are declared
- A list of methods
-
-
-
- Gets reflection information for all declared properties
- The class/type where the properties are declared
- A list of properties
-
-
-
- Gets reflection information for all declared fields
- The class/type where the fields are declared
- A list of fields
-
-
-
- Gets the return type of a method or constructor
- The method/constructor
- The return type
-
-
-
- Given a type, returns the first inner type matching a recursive search by name
- The class/type to start searching at
- The name of the inner type (case sensitive)
- The inner type or null if type/name is null or if a type with that name cannot be found
-
-
-
- Given a type, returns the first inner type matching a recursive search with a predicate
- The class/type to start searching at
- The predicate to search with
- The inner type or null if type/predicate is null or if a type with that name cannot be found
-
-
-
- Given a type, returns the first method matching a predicate
- The class/type to start searching at
- The predicate to search with
- The method or null if type/predicate is null or if a type with that name cannot be found
-
-
-
- Given a type, returns the first constructor matching a predicate
- The class/type to start searching at
- The predicate to search with
- The constructor info or null if type/predicate is null or if a type with that name cannot be found
-
-
-
- Given a type, returns the first property matching a predicate
- The class/type to start searching at
- The predicate to search with
- The property or null if type/predicate is null or if a type with that name cannot be found
-
-
-
- Returns an array containing the type of each object in the given array
- An array of objects
- An array of types or an empty array if parameters is null (if an object is null, the type for it will be object)
-
-
-
- Creates an array of input parameters for a given method and a given set of potential inputs
- The method/constructor you are planing to call
- The possible input parameters in any order
- An object array matching the method signature
-
-
-
- A read/writable reference to an instance field
- The class the field is defined in or "object" if type cannot be accessed at compile time
- The type of the field
- The runtime instance to access the field (leave empty for static fields)
- An readable/assignable object representing the field
-
-
-
- Creates an instance field reference
- The class the field is defined in
- The type of the field
- The name of the field
- A read and writable field reference delegate
-
-
-
- Creates an instance field reference for a specific instance
- The class the field is defined in
- The type of the field
- The instance
- The name of the field
- An readable/assignable object representing the field
-
-
-
- Creates an instance field reference delegate for a private type
- The type of the field
- The class/type
- The name of the field
- A read and writable delegate
-
-
-
- Creates an instance field reference delegate for a fieldinfo
- The class the field is defined in or "object" if type cannot be accessed at compile time
- The type of the field
- The field of the field
- A read and writable delegate
-
-
-
- Creates a static field reference
- The class the field is defined in or "object" if type cannot be accessed at compile time
- The type of the field
- The name of the field
- An readable/assignable object representing the static field
-
-
-
- Creates a static field reference
- The type of the field
- The class/type
- The name of the field
- An readable/assignable object representing the static field
-
-
-
- Creates a static field reference
- The class the field is defined in or "object" if type cannot be accessed at compile time
- The type of the field
- The field
- An readable/assignable object representing the static field
-
-
-
- A read/writable reference delegate to a static field
- The type of the field
- An readable/assignable object representing the static field
-
-
-
- Creates a static field reference delegate
- The type of the field
- The field
- A read and writable delegate
-
-
-
- Creates a delegate to a given method
- The delegate Type
- The method to create a delegate from.
-
- Only applies for instance methods. If null (default), returned delegate is an open (a.k.a. unbound) instance delegate
- where an instance is supplied as the first argument to the delegate invocation; else, delegate is a closed (a.k.a. bound)
- instance delegate where the delegate invocation always applies to the given .
-
-
- Only applies for instance methods. If true (default) and is virtual, invocation of the delegate
- calls the instance method virtually (the instance type's most-derived/overriden implementation of the method is called);
- else, invocation of the delegate calls the exact specified (this is useful for calling base class methods)
- Note: if false and is an interface method, an ArgumentException is thrown.
-
- A delegate of given to given
-
-
- Delegate invocation is more performant and more convenient to use than
- at a one-time setup cost.
-
-
- Works for both type of static and instance methods, both open and closed (a.k.a. unbound and bound) instance methods,
- and both class and struct methods.
-
-
-
-
-
- Creates a delegate for a given delegate definition, attributed with [ ]
- The delegate Type, attributed with [ ]
-
- Only applies for instance methods. If null (default), returned delegate is an open (a.k.a. unbound) instance delegate
- where an instance is supplied as the first argument to the delegate invocation; else, delegate is a closed (a.k.a. bound)
- instance delegate where the delegate invocation always applies to the given .
-
- A delegate of given to the method specified via [ ]
- attributes on
-
- This calls with the method and virtualCall arguments
- determined from the [ ] attributes on ,
- and the given (for closed instance delegates).
-
-
-
-
- Returns who called the current method
- The calling method/constructor (excluding the caller)
-
-
-
- Rethrows an exception while preserving its stack trace (throw statement typically clobbers existing stack traces)
- The exception to rethrow
-
-
-
- True if the current runtime is based on Mono, false otherwise (.NET)
-
-
-
- True if the current runtime is .NET Framework, false otherwise (.NET Core or Mono, although latter isn't guaranteed)
-
-
-
- True if the current runtime is .NET Core, false otherwise (Mono or .NET Framework)
-
-
-
- Throws a missing member runtime exception
- The type that is involved
- A list of names
-
-
-
- Gets default value for a specific type
- The class/type
- The default value
-
-
-
- Creates an (possibly uninitialized) instance of a given type
- The class/type
- The new instance
-
-
-
- Makes a deep copy of any object
- The type of the instance that should be created
- The original object
- A copy of the original object but of type T
-
-
-
- Makes a deep copy of any object
- The type of the instance that should be created
- The original object
- [out] The copy of the original object
- Optional value transformation function (taking a field name and src/dst instances)
- The optional path root to start with
-
-
-
- Makes a deep copy of any object
- The original object
- The type of the instance that should be created
- Optional value transformation function (taking a field name and src/dst instances)
- The optional path root to start with
- The copy of the original object
-
-
-
- Tests if a type is a struct
- The type
- True if the type is a struct
-
-
-
- Tests if a type is a class
- The type
- True if the type is a class
-
-
-
- Tests if a type is a value type
- The type
- True if the type is a value type
-
-
-
- Tests if a type is an integer type
- The type
- True if the type represents some integer
-
-
-
- Tests if a type is a floating point type
- The type
- True if the type represents some floating point
-
-
-
- Tests if a type is a numerical type
- The type
- True if the type represents some number
-
-
-
- Tests if a type is void
- The type
- True if the type is void
-
-
-
- Test whether an instance is of a nullable type
- Type of instance
- An instance to test
- True if instance is of nullable type, false if not
-
-
-
- Tests whether a type or member is static, as defined in C#
- The type or member
- True if the type or member is static
-
-
-
- Tests whether a type is static, as defined in C#
- The type
- True if the type is static
-
-
-
- Tests whether a property is static, as defined in C#
- The property
- True if the property is static
-
-
-
- Tests whether an event is static, as defined in C#
- The event
- True if the event is static
-
-
-
- Calculates a combined hash code for an enumeration of objects
- The objects
- The hash code
-
-
-
- General extensions for common cases
-
-
-
- Joins an enumeration with a value converter and a delimiter to a string
- The inner type of the enumeration
- The enumeration
- An optional value converter (from T to string)
- An optional delimiter
- The values joined into a string
-
-
-
- Converts an array of types (for example methods arguments) into a human readable form
- The array of types
- A human readable description including brackets
-
-
-
- A full description of a type
- The type
- A human readable description
-
-
-
- A a full description of a method or a constructor without assembly details but with generics
- The method/constructor
- A human readable description
-
-
-
- A helper converting parameter infos to types
- The array of parameter infos
- An array of types
-
-
-
- A helper to access a value via key from a dictionary
- The key type
- The value type
- The dictionary
- The key
- The value for the key or the default value (of T) if that key does not exist
-
-
-
- A helper to access a value via key from a dictionary with extra casting
- The value type
- The dictionary
- The key
- The value for the key or the default value (of T) if that key does not exist or cannot be cast to T
-
-
-
- Escapes Unicode and ASCII non printable characters
- The string to convert
- The string to convert
- A string literal surrounded by
-
-
-
- Extensions for
-
-
-
- Shortcut for testing whether the operand is equal to a non-null value
- The
- The value
- True if the operand has the same type and is equal to the value
-
-
-
- Shortcut for testing whether the operand is equal to a non-null value
- The
- The value
- True if the operand is equal to the value
- This is an optimized version of for
-
-
-
- Shortcut for code.opcode == opcode && code.OperandIs(operand)
- The
- The
- The operand value
- True if the opcode is equal to the given opcode and the operand has the same type and is equal to the given operand
-
-
-
- Shortcut for code.opcode == opcode && code.OperandIs(operand)
- The
- The
- The operand value
- True if the opcode is equal to the given opcode and the operand is equal to the given operand
- This is an optimized version of for
-
-
-
- Tests for any form of Ldarg*
- The
- The (optional) index
- True if it matches one of the variations
-
-
-
- Tests for Ldarga/Ldarga_S
- The
- The (optional) index
- True if it matches one of the variations
-
-
-
- Tests for Starg/Starg_S
- The
- The (optional) index
- True if it matches one of the variations
-
-
-
- Tests for any form of Ldloc*
- The
- The optional local variable
- True if it matches one of the variations
-
-
-
- Tests for any form of Stloc*
- The
- The optional local variable
- True if it matches one of the variations
-
-
-
- Tests if the code instruction branches
- The
- The label if the instruction is a branch operation or if not
- True if the instruction branches
-
-
-
- Tests if the code instruction calls the method/constructor
- The
- The method
- True if the instruction calls the method or constructor
-
-
-
- Tests if the code instruction loads a constant
- The
- True if the instruction loads a constant
-
-
-
- Tests if the code instruction loads an integer constant
- The
- The integer constant
- True if the instruction loads the constant
-
-
-
- Tests if the code instruction loads a floating point constant
- The
- The floating point constant
- True if the instruction loads the constant
-
-
-
- Tests if the code instruction loads an enum constant
- The
- The enum
- True if the instruction loads the constant
-
-
-
- Tests if the code instruction loads a field
- The
- The field
- Set to true if the address of the field is loaded
- True if the instruction loads the field
-
-
-
- Tests if the code instruction stores a field
- The
- The field
- True if the instruction stores this field
-
-
-
- Adds labels to the code instruction and return it
- The
- One or several to add
- The same code instruction
-
-
- Adds labels to the code instruction and return it
- The
- An enumeration of
- The same code instruction
-
-
- Extracts all labels from the code instruction and returns them
- The
- A list of
-
-
- Moves all labels from the code instruction to a different one
- The to move the labels from
- The to move the labels to
- The code instruction labels were moved from (now empty)
-
-
- Moves all labels from a different code instruction to the current one
- The to move the labels from
- The to move the labels to
- The code instruction that received the labels
-
-
- Adds ExceptionBlocks to the code instruction and return it
- The
- One or several to add
- The same code instruction
-
-
- Adds ExceptionBlocks to the code instruction and return it
- The
- An enumeration of
- The same code instruction
-
-
- Extracts all ExceptionBlocks from the code instruction and returns them
- The
- A list of
-
-
- Moves all ExceptionBlocks from the code instruction to a different one
- The to move the ExceptionBlocks from
- The to move the ExceptionBlocks to
- The code instruction blocks were moved from (now empty)
-
-
- Moves all ExceptionBlocks from a different code instruction to the current one
- The to move the ExceptionBlocks from
- The to move the ExceptionBlocks to
- The code instruction that received the blocks
-
-
- General extensions for collections
-
-
-
- A simple way to execute code for every element in a collection
- The inner type of the collection
- The collection
- The action to execute
-
-
-
- A simple way to execute code for elements in a collection matching a condition
- The inner type of the collection
- The collection
- The predicate
- The action to execute
-
-
-
- A helper to add an item to a collection
- The inner type of the collection
- The collection
- The item to add
- The collection containing the item
-
-
-
- A helper to add an item to an array
- The inner type of the collection
- The array
- The item to add
- The array containing the item
-
-
-
- A helper to add items to an array
- The inner type of the collection
- The array
- The items to add
- The array containing the items
-
-
-
- General extensions for collections
-
-
-
- Tests a class member if it has an IL method body (external methods for example don't have a body)
- The member to test
- Returns true if the member has an IL body or false if not
-
-
- A file log for debugging
-
-
-
- Full pathname of the log file, defaults to a file called harmony.log.txt on your Desktop
-
-
-
- The indent character. The default is tab
-
-
-
- The current indent level
-
-
-
- Changes the indentation level
- The value to add to the indentation level
-
-
-
- Log a string in a buffered way. Use this method only if you are sure that FlushBuffer will be called
- or else logging information is incomplete in case of a crash
- The string to log
-
-
-
- Logs a list of string in a buffered way. Use this method only if you are sure that FlushBuffer will be called
- or else logging information is incomplete in case of a crash
- A list of strings to log (they will not be re-indented)
-
-
-
- Returns the log buffer and optionally empties it
- True to empty the buffer
- The buffer.
-
-
-
- Replaces the buffer with new lines
- The lines to store
-
-
-
- Flushes the log buffer to disk (use in combination with LogBuffered)
-
-
-
- Log a string directly to disk. Slower method that prevents missing information in case of a crash
- The string to log.
-
-
-
- Resets and deletes the log
-
-
-
- Logs some bytes as hex values
- The pointer to some memory
- The length of bytes to log
-
-
-
- A helper class to retrieve reflection info for non-private methods
-
-
-
- Given a lambda expression that calls a method, returns the method info
- The lambda expression using the method
- The method in the lambda expression
-
-
-
- Given a lambda expression that calls a method, returns the method info
- The generic type
- The lambda expression using the method
- The method in the lambda expression
-
-
-
- Given a lambda expression that calls a method, returns the method info
- The generic type
- The generic result type
- The lambda expression using the method
- The method in the lambda expression
-
-
-
- Given a lambda expression that calls a method, returns the method info
- The lambda expression using the method
- The method in the lambda expression
-
-
-
- A reflection helper to read and write private elements
- The result type defined by GetValue()
-
-
-
- Creates a traverse instance from an existing instance
- The existing instance
-
-
-
- Gets/Sets the current value
- The value to read or write
-
-
-
- A reflection helper to read and write private elements
-
-
-
- Creates a new traverse instance from a class/type
- The class/type
- A instance
-
-
-
- Creates a new traverse instance from a class T
- The class
- A instance
-
-
-
- Creates a new traverse instance from an instance
- The object
- A instance
-
-
-
- Creates a new traverse instance from a named type
- The type name, for format see
- A instance
-
-
-
- Creates a new and empty traverse instance
-
-
-
- Creates a new traverse instance from a class/type
- The class/type
-
-
-
- Creates a new traverse instance from an instance
- The object
-
-
-
- Gets the current value
- The value
-
-
-
- Gets the current value
- The type of the value
- The value
-
-
-
- Invokes the current method with arguments and returns the result
- The method arguments
- The value returned by the method
-
-
-
- Invokes the current method with arguments and returns the result
- The type of the value
- The method arguments
- The value returned by the method
-
-
-
- Sets a value of the current field or property
- The value
- The same traverse instance
-
-
-
- Gets the type of the current field or property
- The type
-
-
-
- Moves the current traverse instance to a inner type
- The type name
- A traverse instance
-
-
-
- Moves the current traverse instance to a field
- The type name
- A traverse instance
-
-
-
- Moves the current traverse instance to a field
- The type of the field
- The type name
- A traverse instance
-
-
-
- Gets all fields of the current type
- A list of field names
-
-
-
- Moves the current traverse instance to a property
- The type name
- Optional property index
- A traverse instance
-
-
-
- Moves the current traverse instance to a field
- The type of the property
- The type name
- Optional property index
- A traverse instance
-
-
-
- Gets all properties of the current type
- A list of property names
-
-
-
- Moves the current traverse instance to a method
- The name of the method
- The arguments defining the argument types of the method overload
- A traverse instance
-
-
-
- Moves the current traverse instance to a method
- The name of the method
- The argument types of the method
- The arguments for the method
- A traverse instance
-
-
-
- Gets all methods of the current type
- A list of method names
-
-
-
- Checks if the current traverse instance is for a field
- True if its a field
-
-
-
- Checks if the current traverse instance is for a property
- True if its a property
-
-
-
- Checks if the current traverse instance is for a method
- True if its a method
-
-
-
- Checks if the current traverse instance is for a type
- True if its a type
-
-
-
- Iterates over all fields of the current type and executes a traverse action
- Original object
- The action receiving a instance for each field
-
-
-
- Iterates over all fields of the current type and executes a traverse action
- Original object
- Target object
- The action receiving a pair of instances for each field pair
-
-
-
- Iterates over all fields of the current type and executes a traverse action
- Original object
- Target object
- The action receiving a dot path representing the field pair and the instances
-
-
-
- Iterates over all properties of the current type and executes a traverse action
- Original object
- The action receiving a instance for each property
-
-
-
- Iterates over all properties of the current type and executes a traverse action
- Original object
- Target object
- The action receiving a pair of instances for each property pair
-
-
-
- Iterates over all properties of the current type and executes a traverse action
- Original object
- Target object
- The action receiving a dot path representing the property pair and the instances
-
-
-
- A default field action that copies fields to fields
-
-
-
- Returns a string that represents the current traverse
- A string representation
-
-
-
-
diff --git a/1.1/Assemblies/Rimworld-Animations.dll b/1.1/Assemblies/Rimworld-Animations.dll
index 7a5e864..b2bba40 100644
Binary files a/1.1/Assemblies/Rimworld-Animations.dll and b/1.1/Assemblies/Rimworld-Animations.dll differ
diff --git a/1.2/Assemblies/Rimworld-Animations.dll b/1.2/Assemblies/Rimworld-Animations.dll
new file mode 100644
index 0000000..13afe5e
Binary files /dev/null and b/1.2/Assemblies/Rimworld-Animations.dll differ
diff --git a/Defs/AnimationDefs/AnimationDefs.rar b/1.2/Defs/AnimationDefs/AnimationDefs.rar
similarity index 100%
rename from Defs/AnimationDefs/AnimationDefs.rar
rename to 1.2/Defs/AnimationDefs/AnimationDefs.rar
diff --git a/Defs/AnimationDefs/Animations_Beast.xml b/1.2/Defs/AnimationDefs/Animations_Beast.xml
similarity index 99%
rename from Defs/AnimationDefs/Animations_Beast.xml
rename to 1.2/Defs/AnimationDefs/Animations_Beast.xml
index 8cda024..30d14fc 100644
--- a/Defs/AnimationDefs/Animations_Beast.xml
+++ b/1.2/Defs/AnimationDefs/Animations_Beast.xml
@@ -8,6 +8,12 @@
Anal
Vaginal
+
+
+ VaginalBreeding
+ AnalBreeding
+
+
@@ -1154,6 +1160,12 @@
Anal
Vaginal
+
+
+ RequestVaginalBreeding
+ RequestAnalBreeding
+
+
diff --git a/Defs/AnimationDefs/Animations_Lesbian.xml b/1.2/Defs/AnimationDefs/Animations_Lesbian.xml
similarity index 99%
rename from Defs/AnimationDefs/Animations_Lesbian.xml
rename to 1.2/Defs/AnimationDefs/Animations_Lesbian.xml
index e8da71b..56d805a 100644
--- a/Defs/AnimationDefs/Animations_Lesbian.xml
+++ b/1.2/Defs/AnimationDefs/Animations_Lesbian.xml
@@ -678,7 +678,26 @@
Oral
Fingering
+ Cunnilingus
+
+
+ Cunnilingus
+ CunnilingusF
+ CunnilingusRape
+ CunnilingusRapeF
+
+ Fingering
+ FingeringF
+ FingeringRape
+ FingeringRapeF
+
+ Fisting
+ FistingF
+ FistingRape
+ FistingRapeF
+
+
diff --git a/Defs/AnimationDefs/Animations_Masturbate.xml b/1.2/Defs/AnimationDefs/Animations_Masturbate.xml
similarity index 100%
rename from Defs/AnimationDefs/Animations_Masturbate.xml
rename to 1.2/Defs/AnimationDefs/Animations_Masturbate.xml
diff --git a/Defs/AnimationDefs/Animations_Multi.xml b/1.2/Defs/AnimationDefs/Animations_Multi.xml
similarity index 97%
rename from Defs/AnimationDefs/Animations_Multi.xml
rename to 1.2/Defs/AnimationDefs/Animations_Multi.xml
index a5c2ba5..ce4e595 100644
--- a/Defs/AnimationDefs/Animations_Multi.xml
+++ b/1.2/Defs/AnimationDefs/Animations_Multi.xml
@@ -18,6 +18,7 @@
Human
+ true
true
true
@@ -25,6 +26,7 @@
Human
+ true
true
true
@@ -78,6 +80,7 @@
LayingPawn
+ -10
30
12
-14.1
@@ -98,6 +101,7 @@
0
+ -10
1
12
-14.1
@@ -114,6 +118,7 @@
LayingPawn
+ 43
27
8.7
15.1
@@ -135,6 +140,7 @@
0
+ 43
1
8.7
15.1
@@ -205,6 +211,7 @@
LayingPawn
+ -10
13
12
-14.1
@@ -225,6 +232,7 @@
0
+ -10
1
12
-14.1
@@ -241,6 +249,7 @@
LayingPawn
+ 43
13
8.7
15.1
@@ -262,6 +271,7 @@
0
+ 43
1
8.7
15.1
@@ -417,6 +427,7 @@
LayingPawn
+ -10
9
9
-14.1
@@ -518,6 +529,7 @@
3
3
0
+ -10
@@ -527,6 +539,7 @@
LayingPawn
+ 43
9
8.7
15.1
@@ -622,6 +635,7 @@
0
+ 43
1
8.7
15.1
diff --git a/Defs/AnimationDefs/Animations_Vanilla2.xml b/1.2/Defs/AnimationDefs/Animations_Vanilla2.xml
similarity index 100%
rename from Defs/AnimationDefs/Animations_Vanilla2.xml
rename to 1.2/Defs/AnimationDefs/Animations_Vanilla2.xml
diff --git a/Defs/AnimationDefs/Animations_vanilla.xml b/1.2/Defs/AnimationDefs/Animations_vanilla.xml
similarity index 93%
rename from Defs/AnimationDefs/Animations_vanilla.xml
rename to 1.2/Defs/AnimationDefs/Animations_vanilla.xml
index f8e5e1c..079753a 100644
--- a/Defs/AnimationDefs/Animations_vanilla.xml
+++ b/1.2/Defs/AnimationDefs/Animations_vanilla.xml
@@ -9,6 +9,16 @@
Vaginal
Anal
+
+
+ AnalSex
+ AnalSexF
+ AnalRape
+ VaginalSex
+ VaginalSexF
+ VaginalRape
+
+
@@ -21,6 +31,7 @@
Human
+ true
true
true
@@ -247,6 +258,7 @@
LayingPawn
+ 27
0
10
16.6
@@ -276,6 +288,7 @@
1
1
0
+ 27
@@ -324,6 +337,7 @@
LayingPawn
+ 27
8
11
-0.217
@@ -353,6 +367,7 @@
1
1
0
+ 27
@@ -412,6 +427,7 @@
LayingPawn
+ 27
8
11
-0.217
@@ -448,6 +464,7 @@
1
1
0
+ 27
@@ -461,7 +478,31 @@
true
Oral
+ Fellatio
+
+ Handjob
+ HandjobF
+ HandjobRape
+ HandjobRapeF
+
+ Breastjob
+ BreastjobF
+ BreastjobRape
+ BreastjobRapeF
+
+ Fellatio
+ FellatioF
+ FellatioRape
+ FellatioRapeF
+
+ Beakjob
+ BeakjobF
+ BeakjobRape
+ BeakjobRapeF
+
+
+
@@ -881,6 +922,14 @@
Anal
Vaginal
+
+ AnalSex
+ AnalSexF
+ AnalRape
+ VaginalSex
+ VaginalSexF
+ VaginalRape
+
@@ -898,6 +947,7 @@
true
true
+ true
(0, 0.2)
@@ -949,6 +999,7 @@
LayingPawn
+ 6
30
-3.18
-0.41
@@ -959,6 +1010,7 @@
0
+ 40
Fuck
29
17.11
@@ -978,6 +1030,7 @@
3
3
0
+ 6
@@ -1615,6 +1668,7 @@
LayingPawn
+ 6
13
-3.18
-0.41
@@ -1625,6 +1679,7 @@
0
+ 40
Fuck
12
17.11
@@ -1644,6 +1699,7 @@
3
3
0
+ 6
@@ -1838,6 +1894,7 @@
LayingPawn
+ 6
7
-3.18
-0.41
@@ -1848,6 +1905,7 @@
0
+ 40
Fuck
7
17.11
@@ -1859,6 +1917,7 @@
0
+ 6
1
-3.18
-0.41
@@ -1870,6 +1929,7 @@
+ 6
7
-3.18
-0.41
@@ -1880,6 +1940,7 @@
0
+ 40
Fuck
7
17.11
@@ -1891,6 +1952,7 @@
0
+ 6
1
-3.18
-0.41
@@ -1902,6 +1964,7 @@
+ 6
7
-3.18
-0.41
@@ -1912,6 +1975,7 @@
0
+ 40
Fuck
7
17.11
@@ -1923,6 +1987,7 @@
0
+ 6
1
-3.18
-0.41
@@ -1934,16 +1999,18 @@
- 7
- -3.18
- -0.41
- 0.122
- 0.356
- 3
- 3
- 0
-
-
+ 6
+ 7
+ -3.18
+ -0.41
+ 0.122
+ 0.356
+ 3
+ 3
+ 0
+
+
+ 40
Cum
75
17.11
@@ -1955,6 +2022,7 @@
0
+ 40
27
17.11
-2.87
@@ -1965,6 +2033,7 @@
0
+ 6
1
-3.18
-0.41
@@ -1989,6 +2058,15 @@
Anal
Vaginal
+
+
+ AnalSex
+ AnalSexF
+ AnalRapeF
+ VaginalSex
+ VaginalSexF
+ VaginalRapeF
+
@@ -2201,7 +2279,7 @@
LayingPawn
- 33
+ 16
180
180
0
@@ -2211,17 +2289,39 @@
0
0
+
+ 17
+ 180
+ 180
+ 0
+ -0.347
+ 2
+ 2
+ 0.015
+ -15
+
- 33
+ 16
180
180
0
- -0.313
+ -0.331
2
2
- 0.045
+ 0.03
0
+
+ 17
+ 180
+ 180
+ 0
+ -0.315
+ 2
+ 2
+ 0.045
+ 15
+
1
180
@@ -2233,6 +2333,127 @@
0
0
+
+ 16
+ 180
+ 180
+ 0
+ -0.363
+ 2
+ 2
+ 0
+ 0
+
+
+ 17
+ 180
+ 180
+ 0
+ -0.347
+ 2
+ 2
+ 0.015
+ -15
+
+
+ 16
+ 180
+ 180
+ 0
+ -0.331
+ 2
+ 2
+ 0.03
+ 0
+
+
+ 17
+ 180
+ 180
+ 0
+ -0.315
+ 2
+ 2
+ 0.045
+ 15
+
+
+ 1
+ 180
+ 180
+ 0
+ -0.363
+ 2
+ 2
+ 0
+ 0
+
+
+ 33
+ 180
+ 180
+ 0
+ -0.363
+ 2
+ 2
+ 0
+ 0
+
+
+ 33
+ 180
+ 180
+ 0
+ -0.315
+ 2
+ 2
+ 0.045
+ 0
+
+
+ 1
+ 180
+ 180
+ 0
+ -0.363
+ 2
+ 2
+ 0
+ 0
+
+
+ 33
+ 180
+ 180
+ 0
+ -0.363
+ 2
+ 2
+ 0
+ 0
+
+
+ 33
+ 180
+ 180
+ 0
+ -0.315
+ 2
+ 2
+ 0.045
+ 0
+
+
+ 1
+ 180
+ 180
+ 0
+ -0.363
+ 2
+ 2
+ 0
+ 0
+
diff --git a/Defs/AnimationDefs/TemplateAnimation.xml b/1.2/Defs/AnimationDefs/TemplateAnimation.xml
similarity index 100%
rename from Defs/AnimationDefs/TemplateAnimation.xml
rename to 1.2/Defs/AnimationDefs/TemplateAnimation.xml
diff --git a/Defs/JobDefs/Jobs_SexForAnim.xml b/1.2/Defs/JobDefs/Jobs_SexForAnim.xml
similarity index 100%
rename from Defs/JobDefs/Jobs_SexForAnim.xml
rename to 1.2/Defs/JobDefs/Jobs_SexForAnim.xml
diff --git a/Defs/MainTabDefs/MainButtonDef.xml b/1.2/Defs/MainTabDefs/MainButtonDef.xml
similarity index 100%
rename from Defs/MainTabDefs/MainButtonDef.xml
rename to 1.2/Defs/MainTabDefs/MainButtonDef.xml
diff --git a/Defs/SoundDefs/Sounds_Sex.xml b/1.2/Defs/SoundDefs/Sounds_Sex.xml
similarity index 97%
rename from Defs/SoundDefs/Sounds_Sex.xml
rename to 1.2/Defs/SoundDefs/Sounds_Sex.xml
index 7d3500c..4cce5d0 100644
--- a/Defs/SoundDefs/Sounds_Sex.xml
+++ b/1.2/Defs/SoundDefs/Sounds_Sex.xml
@@ -6,6 +6,7 @@
MapOnly
1
+ 1
@@ -34,6 +35,7 @@
MapOnly
1
+ 1
@@ -62,6 +64,7 @@
MapOnly
1
+ 1
@@ -118,6 +121,7 @@
MapOnly
1
+ 1
@@ -168,6 +172,7 @@
MapOnly
1
+ 1
diff --git a/1.2/Patch_HatsDisplaySelection/Patch_HatsDisplaySelection.csproj b/1.2/Patch_HatsDisplaySelection/Patch_HatsDisplaySelection.csproj
new file mode 100644
index 0000000..8da21a6
--- /dev/null
+++ b/1.2/Patch_HatsDisplaySelection/Patch_HatsDisplaySelection.csproj
@@ -0,0 +1,75 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {BA766964-1716-422D-A09E-29426F8EB9D5}
+ Library
+ Properties
+ Patch_HatsDisplaySelection
+ Patch_HatsDisplaySelection
+ v4.7.2
+ 512
+ true
+
+
+ false
+ none
+ false
+ 1.2\Assemblies\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\..\..\..\..\workshop\content\294100\2009463077\Current\Assemblies\0Harmony.dll
+ False
+
+
+ ..\..\..\RimWorldWin64_Data\Managed\Assembly-CSharp.dll
+ False
+
+
+ ..\..\..\..\..\workshop\content\294100\1542291825\1.2\Assemblies\HatDisplaySelection.dll
+ False
+
+
+ ..\1.2\Assemblies\Rimworld-Animations.dll
+ False
+
+
+
+
+
+
+
+
+
+
+ ..\..\..\RimWorldWin64_Data\Managed\UnityEngine.dll
+ False
+
+
+ ..\..\..\RimWorldWin64_Data\Managed\UnityEngine.CoreModule.dll
+ False
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/1.2/Patch_HatsDisplaySelection/Properties/AssemblyInfo.cs b/1.2/Patch_HatsDisplaySelection/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..6905d78
--- /dev/null
+++ b/1.2/Patch_HatsDisplaySelection/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Patch_HatsDisplaySelection")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Patch_HatsDisplaySelection")]
+[assembly: AssemblyCopyright("Copyright © 2021")]
+[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("ba766964-1716-422d-a09e-29426f8eb9d5")]
+
+// 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")]
diff --git a/1.2/Patch_HatsDisplaySelection/Source/Patches/Patch_HatsDisplaySelection.cs b/1.2/Patch_HatsDisplaySelection/Source/Patches/Patch_HatsDisplaySelection.cs
new file mode 100644
index 0000000..6f00a5a
--- /dev/null
+++ b/1.2/Patch_HatsDisplaySelection/Source/Patches/Patch_HatsDisplaySelection.cs
@@ -0,0 +1,47 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using HarmonyLib;
+using HatDisplaySelection;
+using Rimworld_Animations;
+using UnityEngine;
+using Verse;
+
+namespace Patch_HatsDisplaySelection
+{
+ [HarmonyBefore(new string[] { "velc.HatsDisplaySelection" })]
+ [HarmonyPatch(typeof(HatDisplaySelection.Patch), "Patch_PawnRenderer_RenderPawnInternal_Initialize")]
+ public class Patch_HatsDisplaySelectionInitialize
+
+ {
+
+ public static void Prefix(PawnRenderer __instance, ref Pawn ___pawn, ref Vector3 rootLoc, ref float angle, ref Rot4 bodyFacing, ref Rot4 headFacing)
+ {
+
+ CompBodyAnimator bodyAnim = ___pawn.TryGetComp();
+ bodyAnim.animatePawn(ref rootLoc, ref angle, ref bodyFacing, ref headFacing);
+ }
+
+ public static void Postfix(PawnRenderer __instance)
+ {
+ PawnGraphicSet graphics = __instance.graphics;
+ Pawn pawn = graphics.pawn;
+ CompBodyAnimator bodyAnim = pawn.TryGetComp();
+
+ if (!graphics.AllResolved)
+ {
+ graphics.ResolveAllGraphics();
+ }
+
+
+ if (bodyAnim != null && bodyAnim.isAnimating && pawn.Map == Find.CurrentMap)
+ {
+ bodyAnim.tickGraphics(graphics);
+
+
+ }
+ }
+ }
+}
diff --git a/Patches/AnimationPatch_CompBodyAnimator.xml b/1.2/Patches/AnimationPatch_CompBodyAnimator.xml
similarity index 100%
rename from Patches/AnimationPatch_CompBodyAnimator.xml
rename to 1.2/Patches/AnimationPatch_CompBodyAnimator.xml
diff --git a/1.2/Patches/CompatibilityPatch_FacialAnimation.xml b/1.2/Patches/CompatibilityPatch_FacialAnimation.xml
new file mode 100644
index 0000000..125d79f
--- /dev/null
+++ b/1.2/Patches/CompatibilityPatch_FacialAnimation.xml
@@ -0,0 +1,130 @@
+
+
+
+
+ [NL] Facial Animation - WIP
+
+
+ Always
+
+
+ /Defs/FacialAnimation.FaceAnimationDef[defName="Lovin" or defName="Lovin2"]/targetJobs
+ Always
+
+ RJW_Masturbate
+ GettinBred
+ Bestiality
+ BestialityForFemale
+ ViolateCorpse
+ Quickie
+ GettingQuickie
+ GettinRaped
+ JoinInBed
+ GettinLoved
+ GettinLicked
+ GettinSucked
+ WhoreIsServingVisitors
+ JoinInBedAnimation
+ GettinLovedAnimation
+
+
+
+ /Defs/FacialAnimation.FaceAnimationDef[defName="WaitCombat" or defName="Wait_Combat_Rare"]/targetJobs
+ Always
+
+ RapeComfortPawn
+ RandomRape
+ RapeEnemy
+
+
+
+ /Defs/FacialAnimation.FaceAnimationDef[defName="StandAndBeSociallyActive"]/targetJobs
+ Always
+
+ WhoreInvitingVisitors
+
+
+
+ /Defs/FacialAnimation.FaceAnimationDef[defName="Wear" or defName="Wear2" or defName="Wear3"]/targetJobs
+ Always
+
+ CleanSelf
+ StruggleInBondageGear
+
+
+
+
+ Rimworld-Animations
+
+
+ Always
+
+
+ /Defs/FacialAnimation.FaceAnimationDef[defName="Lovin" or defName="Lovin2"]/animationFrames/li[1]/headOffset
+ Always
+
+
+ /Defs/FacialAnimation.FaceAnimationDef[defName="Lovin"]/animationFrames/li[2]/headOffset
+ Always
+
+
+ /Defs/FacialAnimation.FaceAnimationDef[defName="Lovin"]/animationFrames/li[3]/headOffset
+ Always
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Patches/CompatibilityPatch_HCSK.xml b/1.2/Patches/CompatibilityPatch_HCSK.xml
similarity index 100%
rename from Patches/CompatibilityPatch_HCSK.xml
rename to 1.2/Patches/CompatibilityPatch_HCSK.xml
diff --git a/Sounds/Sex/Clap_1.wav b/1.2/Sounds/Sex/Clap_1.wav
similarity index 100%
rename from Sounds/Sex/Clap_1.wav
rename to 1.2/Sounds/Sex/Clap_1.wav
diff --git a/Sounds/Sex/Clap_2.wav b/1.2/Sounds/Sex/Clap_2.wav
similarity index 100%
rename from Sounds/Sex/Clap_2.wav
rename to 1.2/Sounds/Sex/Clap_2.wav
diff --git a/Sounds/Sex/Clap_3.wav b/1.2/Sounds/Sex/Clap_3.wav
similarity index 100%
rename from Sounds/Sex/Clap_3.wav
rename to 1.2/Sounds/Sex/Clap_3.wav
diff --git a/Sounds/Sex/Clap_4.wav b/1.2/Sounds/Sex/Clap_4.wav
similarity index 100%
rename from Sounds/Sex/Clap_4.wav
rename to 1.2/Sounds/Sex/Clap_4.wav
diff --git a/Sounds/Sex/Clap_5.wav b/1.2/Sounds/Sex/Clap_5.wav
similarity index 100%
rename from Sounds/Sex/Clap_5.wav
rename to 1.2/Sounds/Sex/Clap_5.wav
diff --git a/Sounds/Sex/Clap_6.wav b/1.2/Sounds/Sex/Clap_6.wav
similarity index 100%
rename from Sounds/Sex/Clap_6.wav
rename to 1.2/Sounds/Sex/Clap_6.wav
diff --git a/Sounds/Sex/Clap_7.wav b/1.2/Sounds/Sex/Clap_7.wav
similarity index 100%
rename from Sounds/Sex/Clap_7.wav
rename to 1.2/Sounds/Sex/Clap_7.wav
diff --git a/Sounds/Sex/Clap_8.wav b/1.2/Sounds/Sex/Clap_8.wav
similarity index 100%
rename from Sounds/Sex/Clap_8.wav
rename to 1.2/Sounds/Sex/Clap_8.wav
diff --git a/1.2/Sounds/Sex/Slime/Slimy1.wav b/1.2/Sounds/Sex/Slime/Slimy1.wav
new file mode 100644
index 0000000..3cfbd74
Binary files /dev/null and b/1.2/Sounds/Sex/Slime/Slimy1.wav differ
diff --git a/1.2/Sounds/Sex/Slime/Slimy2.wav b/1.2/Sounds/Sex/Slime/Slimy2.wav
new file mode 100644
index 0000000..36a9197
Binary files /dev/null and b/1.2/Sounds/Sex/Slime/Slimy2.wav differ
diff --git a/1.2/Sounds/Sex/Slime/Slimy3.wav b/1.2/Sounds/Sex/Slime/Slimy3.wav
new file mode 100644
index 0000000..40aff1e
Binary files /dev/null and b/1.2/Sounds/Sex/Slime/Slimy3.wav differ
diff --git a/1.2/Sounds/Sex/Slime/Slimy4.wav b/1.2/Sounds/Sex/Slime/Slimy4.wav
new file mode 100644
index 0000000..0b6404e
Binary files /dev/null and b/1.2/Sounds/Sex/Slime/Slimy4.wav differ
diff --git a/1.2/Sounds/Sex/Slime/Slimy5.wav b/1.2/Sounds/Sex/Slime/Slimy5.wav
new file mode 100644
index 0000000..ea310db
Binary files /dev/null and b/1.2/Sounds/Sex/Slime/Slimy5.wav differ
diff --git a/1.2/Sounds/Sex/Suck/Suck_1.wav b/1.2/Sounds/Sex/Suck/Suck_1.wav
new file mode 100644
index 0000000..4f1eafd
Binary files /dev/null and b/1.2/Sounds/Sex/Suck/Suck_1.wav differ
diff --git a/1.2/Sounds/Sex/Suck/Suck_10.wav b/1.2/Sounds/Sex/Suck/Suck_10.wav
new file mode 100644
index 0000000..284cda3
Binary files /dev/null and b/1.2/Sounds/Sex/Suck/Suck_10.wav differ
diff --git a/1.2/Sounds/Sex/Suck/Suck_3.wav b/1.2/Sounds/Sex/Suck/Suck_3.wav
new file mode 100644
index 0000000..95e7348
Binary files /dev/null and b/1.2/Sounds/Sex/Suck/Suck_3.wav differ
diff --git a/1.2/Sounds/Sex/Suck/Suck_4.wav b/1.2/Sounds/Sex/Suck/Suck_4.wav
new file mode 100644
index 0000000..753a023
Binary files /dev/null and b/1.2/Sounds/Sex/Suck/Suck_4.wav differ
diff --git a/1.2/Sounds/Sex/Suck/Suck_5.wav b/1.2/Sounds/Sex/Suck/Suck_5.wav
new file mode 100644
index 0000000..8ecda9c
Binary files /dev/null and b/1.2/Sounds/Sex/Suck/Suck_5.wav differ
diff --git a/1.2/Sounds/Sex/Suck/Suck_6.wav b/1.2/Sounds/Sex/Suck/Suck_6.wav
new file mode 100644
index 0000000..08567d6
Binary files /dev/null and b/1.2/Sounds/Sex/Suck/Suck_6.wav differ
diff --git a/1.2/Sounds/Sex/Suck/Suck_7.wav b/1.2/Sounds/Sex/Suck/Suck_7.wav
new file mode 100644
index 0000000..a63b0e4
Binary files /dev/null and b/1.2/Sounds/Sex/Suck/Suck_7.wav differ
diff --git a/1.2/Sounds/Sex/Suck/Suck_8.wav b/1.2/Sounds/Sex/Suck/Suck_8.wav
new file mode 100644
index 0000000..320da09
Binary files /dev/null and b/1.2/Sounds/Sex/Suck/Suck_8.wav differ
diff --git a/1.2/Sounds/Sex/Suck/Suck_9.wav b/1.2/Sounds/Sex/Suck/Suck_9.wav
new file mode 100644
index 0000000..7ab538a
Binary files /dev/null and b/1.2/Sounds/Sex/Suck/Suck_9.wav differ
diff --git a/1.2/Sounds/Sex/Suck/Swallow_1.wav b/1.2/Sounds/Sex/Suck/Swallow_1.wav
new file mode 100644
index 0000000..f3276cc
Binary files /dev/null and b/1.2/Sounds/Sex/Suck/Swallow_1.wav differ
diff --git a/1.2/Sounds/Sex/Suck/Swallow_2.wav b/1.2/Sounds/Sex/Suck/Swallow_2.wav
new file mode 100644
index 0000000..09a7a00
Binary files /dev/null and b/1.2/Sounds/Sex/Suck/Swallow_2.wav differ
diff --git a/1.2/Sounds/Sex/Suck/Swallow_3.wav b/1.2/Sounds/Sex/Suck/Swallow_3.wav
new file mode 100644
index 0000000..2817b29
Binary files /dev/null and b/1.2/Sounds/Sex/Suck/Swallow_3.wav differ
diff --git a/1.2/Sounds/Sex/Suck/suck_2.wav b/1.2/Sounds/Sex/Suck/suck_2.wav
new file mode 100644
index 0000000..a8305c1
Binary files /dev/null and b/1.2/Sounds/Sex/Suck/suck_2.wav differ
diff --git a/Sounds/Sex/cum.wav b/1.2/Sounds/Sex/cum.wav
similarity index 100%
rename from Sounds/Sex/cum.wav
rename to 1.2/Sounds/Sex/cum.wav
diff --git a/Sounds/Sex/kucyu04.wav b/1.2/Sounds/Sex/kucyu04.wav
similarity index 100%
rename from Sounds/Sex/kucyu04.wav
rename to 1.2/Sounds/Sex/kucyu04.wav
diff --git a/Textures/UI/MainTab.png b/1.2/Textures/UI/MainTab.png
similarity index 100%
rename from Textures/UI/MainTab.png
rename to 1.2/Textures/UI/MainTab.png
diff --git a/1.3/Assemblies/Rimworld-Animations.dll b/1.3/Assemblies/Rimworld-Animations.dll
new file mode 100644
index 0000000..7f376ba
Binary files /dev/null and b/1.3/Assemblies/Rimworld-Animations.dll differ
diff --git a/1.3/Defs/AnimationDefs/AnimationDefs.rar b/1.3/Defs/AnimationDefs/AnimationDefs.rar
new file mode 100644
index 0000000..e7bf2a1
Binary files /dev/null and b/1.3/Defs/AnimationDefs/AnimationDefs.rar differ
diff --git a/1.3/Defs/AnimationDefs/Animations_Beast.xml b/1.3/Defs/AnimationDefs/Animations_Beast.xml
new file mode 100644
index 0000000..30d14fc
--- /dev/null
+++ b/1.3/Defs/AnimationDefs/Animations_Beast.xml
@@ -0,0 +1,2180 @@
+
+
+
+ Dog_Doggystyle
+ dog doggystyle
+ true
+
+ Anal
+ Vaginal
+
+
+
+ VaginalBreeding
+ AnalBreeding
+
+
+
+
+
+ Human
+
+ true
+
+
+
+ Wolf_Timber
+ Wolf_Arctic
+ Whitefox
+ Warg
+ Husky
+ LabradorRetriever
+
+ AEXP_WelshTerrier
+ AEXP_Rottweiler
+ AEXP_Poodle
+ AEXP_GreatDane
+ AEXP_GermanShepherd
+ AEXP_FrenchBulldog
+ AEXP_Corgi
+ AEXP_CatAbyssinian
+ AEXP_CatBengal
+ AEXP_CatMaineCoon
+ AEXP_CatSphynx
+
+
+ QuadrupedAnimalWithHooves
+ QuadrupedAnimalWithPawsAndTail
+
+ true
+ true
+
+
+
+
+
+
+
+ Fuck
+ true
+ 765
+ 0
+
+
+ LayingPawn
+
+
+
+ 10
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+ 0
+
+
+ 6
+ 53.7
+ 5.4
+ 0.068
+ -0.038
+ 1
+ 1
+
+
+ 1
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+
+
+ 10
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+ 6
+ 53.7
+ 5.4
+ 0.068
+ -0.038
+ 1
+ 1
+
+
+ 1
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+
+
+ 10
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+ 6
+ 53.7
+ 5.4
+ 0.068
+ -0.038
+ 1
+ 1
+
+
+ 1
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+
+
+ 10
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+ 6
+ 53.7
+ 5.4
+ 0.068
+ -0.038
+ 1
+ 1
+
+
+ 1
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+
+
+ 10
+ 56.7
+ 27.5
+ 0.057
+ -0.038
+ 1
+ 2
+
+
+ 6
+ 53.7
+ 25.4
+ 0.068
+ -0.038
+ 1
+ 2
+
+
+ 1
+ 56.7
+ 27.5
+ 0.057
+ -0.038
+ 1
+ 2
+
+
+
+
+ 10
+ 56.7
+ 27.5
+ 0.057
+ -0.038
+ 1
+ 2
+
+
+ 6
+ 53.7
+ 25.4
+ 0.068
+ -0.038
+ 1
+ 2
+
+
+ 1
+ 56.7
+ 27.5
+ 0.057
+ -0.038
+ 1
+ 2
+
+
+
+
+ 10
+ 56.7
+ 27.5
+ 0.057
+ -0.038
+ 1
+ 2
+
+
+ 6
+ 53.7
+ 25.4
+ 0.068
+ -0.038
+ 1
+ 2
+
+
+ 1
+ 56.7
+ 27.5
+ 0.057
+ -0.038
+ 1
+ 2
+
+
+
+
+ 10
+ 56.7
+ 27.5
+ 0.057
+ -0.038
+ 1
+ 2
+
+
+ 6
+ 53.7
+ 25.4
+ 0.068
+ -0.038
+ 1
+ 2
+
+
+ 1
+ 56.7
+ 27.5
+ 0.057
+ -0.038
+ 1
+ 2
+
+
+
+
+
+ 10
+ 56.7
+ 27.5
+ 0.057
+ -0.038
+ 1
+ 2
+
+
+ 6
+ 53.7
+ 25.4
+ 0.068
+ -0.038
+ 1
+ 2
+
+
+ 1
+ 56.7
+ 27.5
+ 0.057
+ -0.038
+ 1
+ 2
+
+
+
+
+ 10
+ 56.7
+ 27.5
+ 0.057
+ -0.038
+ 1
+ 2
+
+
+ 6
+ 53.7
+ 25.4
+ 0.068
+ -0.038
+ 1
+ 2
+
+
+ 1
+ 56.7
+ 27.5
+ 0.057
+ -0.038
+ 1
+ 2
+
+
+
+
+ 10
+ 56.7
+ 27.5
+ 0.057
+ -0.038
+ 1
+ 2
+
+
+ 6
+ 53.7
+ 25.4
+ 0.068
+ -0.038
+ 1
+ 2
+
+
+ 1
+ 56.7
+ 27.5
+ 0.057
+ -0.038
+ 1
+ 2
+
+
+
+
+ 10
+ 56.7
+ 27.5
+ 0.057
+ -0.038
+ 1
+ 2
+
+
+ 6
+ 53.7
+ 25.4
+ 0.068
+ -0.038
+ 1
+ 2
+
+
+ 1
+ 56.7
+ 27.5
+ 0.057
+ -0.038
+ 1
+ 2
+
+
+
+
+ 10
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+ 6
+ 53.7
+ 5.4
+ 0.068
+ -0.038
+ 1
+ 1
+
+
+ 1
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+
+
+ 10
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+ 6
+ 53.7
+ 5.4
+ 0.068
+ -0.038
+ 1
+ 1
+
+
+ 1
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+
+
+ 10
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+ 6
+ 53.7
+ 5.4
+ 0.068
+ -0.038
+ 1
+ 1
+
+
+ 1
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+
+
+ 10
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+ 6
+ 53.7
+ 5.4
+ 0.068
+ -0.038
+ 1
+ 1
+
+
+ 1
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+
+ 10
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+ 6
+ 53.7
+ 5.4
+ 0.068
+ -0.038
+ 1
+ 1
+
+
+ 1
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+
+
+ 10
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+ 6
+ 53.7
+ 5.4
+ 0.068
+ -0.038
+ 1
+ 1
+
+
+ 1
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+
+
+ 10
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+ 6
+ 53.7
+ 5.4
+ 0.068
+ -0.038
+ 1
+ 1
+
+
+ 1
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+
+
+ 10
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+ 6
+ 53.7
+ 5.4
+ 0.068
+ -0.038
+ 1
+ 1
+
+
+ 1
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+
+ 10
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+ 6
+ 53.7
+ 5.4
+ 0.068
+ -0.038
+ 1
+ 1
+
+
+ 1
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+
+
+ 10
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+ 6
+ 53.7
+ 5.4
+ 0.068
+ -0.038
+ 1
+ 1
+
+
+ 1
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+
+
+ 10
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+ 6
+ 53.7
+ 5.4
+ 0.068
+ -0.038
+ 1
+ 1
+
+
+ 1
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+
+
+ 10
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+ 6
+ 53.7
+ 5.4
+ 0.068
+ -0.038
+ 1
+ 1
+
+
+ 1
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+
+ 10
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+ 6
+ 53.7
+ 5.4
+ 0.068
+ -0.038
+ 1
+ 1
+
+
+ 1
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+
+
+ 10
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+ 6
+ 53.7
+ 5.4
+ 0.068
+ -0.038
+ 1
+ 1
+
+
+ 1
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+
+
+ 10
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+ 6
+ 53.7
+ 5.4
+ 0.068
+ -0.038
+ 1
+ 1
+
+
+ 1
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+
+
+ 10
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+ 6
+ 53.7
+ 5.4
+ 0.068
+ -0.038
+ 1
+ 1
+
+
+ 1
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+ 0
+
+
+
+
+
+
+
+
+ 8
+ -33.7
+ 0
+ -0.492
+ 0.266
+ 1
+ 0
+ 0
+
+
+ 8
+ Fuck
+ -39.6
+ 0
+ -0.353
+ 0.256
+ 1
+ 0
+
+
+ 1
+ -33.7
+ 0
+ -0.492
+ 0.266
+ 1
+ 0
+ 0
+
+
+
+
+
+
+ Knot
+ False
+ 71
+ 0
+
+
+ LayingPawn
+
+
+ true
+ 60
+ 53.7
+ 25.4
+ 0.068
+ -0.038
+ 1
+ 1
+ 0
+
+
+ 6
+ Cum
+ 53.7
+ 28.4
+ 0.068
+ -0.038
+ 1
+ 1
+
+
+ 4
+ 51.7
+ 33.4
+ 0.098
+ -0.038
+ 1
+ 1
+
+
+ 1
+ 53.7
+ 25.4
+ 0.068
+ -0.038
+ 1
+ 1
+ 0
+
+
+
+
+
+
+
+
+ 60
+ -33.7
+ 0
+ -0.492
+ 0.266
+ 1
+ 0
+ 0
+
+
+ 6
+ -39.6
+ 0
+ -0.353
+ 0.256
+ 1
+ 0
+
+
+ 4
+ Fuck
+ -41.6
+ 0
+ -0.383
+ 0.256
+ 1
+ 0
+
+
+ 1
+ -39.6
+ 0
+ -0.353
+ 0.256
+ 1
+ 0
+ 0
+
+
+
+
+
+
+
+
+ Cum
+ true
+ 600
+ 0
+
+
+ LayingPawn
+
+
+ 40
+ 53.7
+ 25.4
+ 0.068
+ -0.038
+ 1
+ 1
+ 0
+
+
+ 40
+ Cum
+ 57.7
+ 28.4
+ 0.073
+ -0.038
+ 1
+ 1
+
+
+ 1
+ 53.7
+ 25.4
+ 0.068
+ -0.038
+ 1
+ 1
+ 0
+
+
+
+
+
+
+
+
+ 10
+ -39.6
+ 0
+ -0.353
+ 0.256
+ 1
+ 0
+ 0
+
+
+ 10
+ -40.6
+ 0
+ -0.358
+ 0.256
+ 1
+ 0
+
+
+ 10
+ -39.6
+ 0
+ -0.353
+ 0.256
+ 1
+ 0
+
+
+ 10
+ -40.6
+ 0
+ -0.358
+ 0.256
+ 1
+ 0
+
+
+ 10
+ -39.6
+ 0
+ -0.353
+ 0.256
+ 1
+ 0
+
+
+ 10
+ -40.6
+ 0
+ -0.358
+ 0.256
+ 1
+ 0
+
+
+ 10
+ -39.6
+ 0
+ -0.353
+ 0.256
+ 1
+ 0
+
+
+ 10
+ -40.6
+ 0
+ -0.358
+ 0.256
+ 1
+ 0
+
+
+ 1
+ -39.6
+ 0
+ -0.353
+ 0.256
+ 1
+ 0
+ 0
+
+
+
+
+
+
+
+
+
+
+
+
+ Horse_Cowgirl
+ HorseCowgirl
+ true
+
+ Anal
+ Vaginal
+
+
+
+ RequestVaginalBreeding
+ RequestAnalBreeding
+
+
+
+
+
+ Human
+
+ true
+ true
+
+ (0, 0.2)
+
+
+
+
+ Horse
+
+
+ QuadrupedAnimalWithHooves
+
+ true
+
+
+
+
+
+
+
+ Insertion
+ false
+ 0
+
+
+
+
+ 180
+ -24.337
+ -37.1218948
+ 0
+ 0.698042035
+ -0.20718734
+ 0
+ 3
+ 3
+
+
+ 70
+ -2.54239845
+ 7.31265259
+ 0
+ 0.606091142
+ -0.045959726
+ 0
+ 3
+ 3
+ Slimy
+
+
+ 60
+ -4.84361649
+ -23.6405125
+ 0
+ 0.650456548
+ -0.0570534021
+ 0
+ 3
+ 3
+ Slimy
+
+
+ 1
+ -35.01766
+ -26.3706665
+ 0
+ 0.455286169
+ -0.3646413
+ 0
+ 3
+ 3
+ Slimy
+
+
+
+
+ LayingPawn
+
+
+ 250
+ 177.083145
+ 0
+ 0
+ -0.256229281
+ -0.362511069
+ 0
+ 1
+ 0
+
+
+
+ 60
+ 177.981537
+ 0
+ 0
+ -0.24524799
+ -0.358849227
+ 0
+ 1
+ 0
+
+
+ 1
+ 179.6811
+ 0
+ 0
+ -0.267210543
+ -0.3991253
+ 0
+ 1
+ 0
+
+
+
+
+
+
+
+ SlowFuck
+ true
+ 1300
+ 0
+
+
+
+
+ 80
+ -35.01766
+ -26.3706665
+ 0
+ 0.455286169
+ -0.3646413
+ 0
+ 3
+ 3
+
+
+ 49
+ -49.8178673
+ -35.7418823
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 3
+ Slimy
+
+
+ 1
+ -35.01766
+ -26.3706665
+ 0
+ 0.455286169
+ -0.3646413
+ 0
+ 3
+ 3
+ Fuck
+
+
+
+
+ LayingPawn
+
+
+ 80
+ 179.6811
+ 0
+ 0
+ -0.267210543
+ -0.3991253
+ 0
+ 1
+ 0
+
+
+ 49
+ 177.981537
+ 0
+ 0
+ -0.24524799
+ -0.358849227
+ 0
+ 1
+ 0
+
+
+ 1
+ 179.6811
+ 0
+ 0
+ -0.267210543
+ -0.3991253
+ 0
+ 1
+ 0
+
+
+
+
+
+
+
+ Transition
+ false
+ 0
+
+
+
+
+ 50
+ -35.01766
+ -26.3706665
+ 0
+ 0.455286169
+ -0.3646413
+ 0
+ 3
+ 3
+ Fuck
+
+
+
+ 15
+ -49.8178673
+ -35.7418823
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 3
+ Slimy
+
+
+
+ 80
+ -49.8178673
+ -8.273987
+ 0
+ 0.506531835
+ -0.55575326
+ 0
+ 3
+ 3
+
+
+
+ 1
+ -49.8178673
+ -14.1647339
+ 0
+ 0.48456946
+ -0.489136577
+ 0
+ 3
+ 3
+
+
+
+
+ LayingPawn
+
+
+ 50
+ 179.6811
+ 0
+ 0
+ -0.267210543
+ -0.3991253
+ 0
+ 1
+ 0
+
+
+
+ 15
+ 177.981537
+ 0
+ 0
+ -0.24524799
+ -0.358849227
+ 0
+ 1
+ 0
+
+
+
+ 80
+ 175.467651
+ 0
+ 0
+ -0.2123042
+ -0.5309518
+ 0
+ 1
+ 0
+ Fuck
+
+
+
+ 1
+ 177.981537
+ 0
+ 0
+ -0.24524799
+ -0.358849227
+ 0
+ 1
+ 0
+
+
+
+
+
+
+
+ FastFuck
+ true
+ 1260
+ 0
+
+
+
+
+
+ 10
+ -49.8178673
+ -14.1647339
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 3
+ Slimy
+
+
+ 24
+ -49.8178673
+ -8.273987
+ 0
+ 0.506531835
+ -0.55575326
+ 0
+ 3
+ 3
+
+
+ 1
+ -49.8178673
+ -14.1647339
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 3
+ Slimy
+
+
+
+ 10
+ -49.8178673
+ -14.1647339
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 3
+ Slimy
+
+
+ 24
+ -49.8178673
+ -8.273987
+ 0
+ 0.506531835
+ -0.55575326
+ 0
+ 3
+ 3
+
+
+ 1
+ -49.8178673
+ -14.1647339
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 3
+ Slimy
+
+
+
+ 10
+ -49.8178673
+ -14.1647339
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 2
+ Slimy
+
+
+ 24
+ -49.8178673
+ -8.273987
+ 0
+ 0.506531835
+ -0.55575326
+ 0
+ 3
+ 2
+
+
+ 1
+ -49.8178673
+ -14.1647339
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 2
+ Slimy
+
+
+
+ 10
+ -49.8178673
+ -14.1647339
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 2
+ Slimy
+
+
+ 24
+ -49.8178673
+ -8.273987
+ 0
+ 0.506531835
+ -0.55575326
+ 0
+ 3
+ 2
+
+
+ 1
+ -49.8178673
+ -14.1647339
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 2
+ Slimy
+
+
+
+ 10
+ -49.8178673
+ -14.1647339
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 2
+ Slimy
+
+
+ 24
+ -49.8178673
+ -8.273987
+ 0
+ 0.506531835
+ -0.55575326
+ 0
+ 3
+ 2
+
+
+ 1
+ -49.8178673
+ -14.1647339
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 2
+ Slimy
+
+
+
+ 10
+ -49.8178673
+ -14.1647339
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 2
+ Slimy
+
+
+ 24
+ -49.8178673
+ -8.273987
+ 0
+ 0.506531835
+ -0.55575326
+ 0
+ 3
+ 2
+
+
+ 1
+ -49.8178673
+ -14.1647339
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 2
+ Slimy
+
+
+
+ 10
+ -49.8178673
+ -14.1647339
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 2
+ Slimy
+
+
+ 24
+ -49.8178673
+ -8.273987
+ 0
+ 0.506531835
+ -0.55575326
+ 0
+ 3
+ 2
+
+
+ 1
+ -49.8178673
+ -14.1647339
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 2
+ Slimy
+
+
+
+ 10
+ -49.8178673
+ -14.1647339
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 2
+ Slimy
+
+
+ 24
+ -49.8178673
+ -8.273987
+ 0
+ 0.506531835
+ -0.55575326
+ 0
+ 3
+ 2
+
+
+ 1
+ -49.8178673
+ -14.1647339
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 2
+ Slimy
+
+
+
+ 10
+ -49.8178673
+ -14.1647339
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 3
+ Slimy
+
+
+ 24
+ -49.8178673
+ -8.273987
+ 0
+ 0.506531835
+ -0.55575326
+ 0
+ 3
+ 3
+
+
+ 1
+ -49.8178673
+ -14.1647339
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 3
+ Slimy
+
+
+
+ 10
+ -49.8178673
+ -14.1647339
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 3
+ Slimy
+
+
+ 24
+ -49.8178673
+ -8.273987
+ 0
+ 0.506531835
+ -0.55575326
+ 0
+ 3
+ 3
+
+
+ 1
+ -49.8178673
+ -14.1647339
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 3
+ Slimy
+
+
+
+ 10
+ -49.8178673
+ -14.1647339
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 3
+ Slimy
+
+
+ 24
+ -49.8178673
+ -8.273987
+ 0
+ 0.506531835
+ -0.55575326
+ 0
+ 3
+ 3
+
+
+ 1
+ -49.8178673
+ -14.1647339
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 3
+ Slimy
+
+
+
+ 10
+ -49.8178673
+ -14.1647339
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 3
+ Slimy
+
+
+ 24
+ -49.8178673
+ -8.273987
+ 0
+ 0.506531835
+ -0.55575326
+ 0
+ 3
+ 3
+
+
+ 1
+ -49.8178673
+ -14.1647339
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 3
+ Slimy
+
+
+
+
+ LayingPawn
+
+
+
+ 10
+ 177.981537
+ 0
+ 0
+ -0.24524799
+ -0.358849227
+ 0
+ 1
+ 0
+
+
+ 24
+ 175.467651
+ 0
+ 0
+ -0.2123042
+ -0.5309518
+ 0
+ 1
+ 0
+ Fuck
+
+
+ 1
+ 177.981537
+ 0
+ 0
+ -0.24524799
+ -0.358849227
+ 0
+ 1
+ 0
+
+
+
+
+
+
+
+ FasterFuck
+ true
+ 418
+ 0
+
+
+
+
+
+ 10
+ -49.8178673
+ -14.1647339
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 3
+
+
+ 8
+ -49.8178673
+ -8.273987
+ 0
+ 0.506531835
+ -0.55575326
+ 0
+ 3
+ 3
+
+
+ 1
+ -49.8178673
+ -14.1647339
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 3
+ Slimy
+
+
+
+
+ LayingPawn
+
+
+ 10
+ 177.981537
+ 0
+ 0
+ -0.24524799
+ -0.358849227
+ 0
+ 1
+ 0
+
+
+ 8
+ 175.467651
+ 0
+ 0
+ -0.2123042
+ -0.5309518
+ 0
+ 1
+ 0
+ Fuck
+
+
+ 1
+ 177.981537
+ 0
+ 0
+ -0.24524799
+ -0.358849227
+ 0
+ 1
+ 0
+
+
+
+
+
+
+
+ Cum
+ True
+ 318
+ 0
+
+
+
+
+
+ 10
+ -49.8178673
+ -14.1647339
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 3
+
+
+
+ true
+ 80
+ -49.8178673
+ -8.273987
+ 0
+ 0.506531835
+ -0.55575326
+ 0
+ 3
+ 3
+ Cum
+
+
+ 25
+ -49.8178673
+ 2.654541
+ 0
+ 0.5175133
+ -0.547725141
+ 0
+ 3
+ 3
+
+
+ 1
+ -49.8178673
+ -14.1647339
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 3
+
+
+
+
+
+ LayingPawn
+
+
+
+ 10
+ 177.981537
+ 0
+ 0
+ -0.24524799
+ -0.358849227
+ 0
+ 1
+ 0
+
+
+ 80
+ 175.467651
+ 0
+ 0
+ -0.2123042
+ -0.5309518
+ 0
+ 1
+ 0
+
+
+ 25
+ 173.81427
+ 0
+ 0
+ -0.197662517
+ -0.545600235
+ 0
+ 1
+ 0
+
+
+ 1
+ 177.981537
+ 0
+ 0
+ -0.24524799
+ -0.358849227
+ 0
+ 1
+ 0
+
+
+
+
+
+
+
+
+
+
+
diff --git a/1.3/Defs/AnimationDefs/Animations_Lesbian.xml b/1.3/Defs/AnimationDefs/Animations_Lesbian.xml
new file mode 100644
index 0000000..56d805a
--- /dev/null
+++ b/1.3/Defs/AnimationDefs/Animations_Lesbian.xml
@@ -0,0 +1,1782 @@
+
+
+
+ Tribadism
+ scissoring
+ true
+
+ Scissoring
+
+
+
+
+
+ Human
+
+ true
+
+ Vagina
+
+
+
+
+ Human
+
+ true
+ true
+
+ Vagina
+
+
+
+
+
+
+
+ Tribbing
+ true
+ 992
+ 0
+
+
+ LayingPawn
+
+
+
+ 20
+ -81.3
+ -81.3
+ -0.218
+ 0.073
+ 2
+ 2
+ 0
+
+
+ 20
+ -79.56
+ -79.56
+ -0.218
+ 0.082
+ 2
+ 2
+ 0
+
+
+ 20
+ -81.53
+ -81.53
+ -0.219
+ 0.07
+ 2
+ 2
+ 0
+
+
+ Slimy
+ 1
+ -81.3
+ -81.3
+ -0.218
+ 0.073
+ 2
+ 2
+ 0
+
+
+
+
+
+
+
+ 20
+ 9.97
+ -7.61
+ 0.444
+ 0.368
+ 3
+ 3
+ 0
+
+
+ 20
+ 23.82
+ -6.90
+ 0.432
+ 0.403
+ 3
+ 3
+ 0
+
+
+ 20
+ 5.19
+ -6.19
+ 0.442
+ 0.388
+ 3
+ 3
+ 0
+
+
+ 1
+ 9.97
+ -7.61
+ 0.444
+ 0.368
+ 3
+ 3
+ 0
+
+
+
+
+
+
+
+ TribadismFast
+ true
+ 682
+ 0
+
+
+ LayingPawn
+
+
+
+ 10
+ -81.3
+ -81.3
+ -0.218
+ 0.073
+ 2
+ 1
+ 0
+
+
+ 10
+ -79.56
+ -79.56
+ -0.218
+ 0.082
+ 2
+ 1
+ 0
+
+
+ 10
+ -81.53
+ -81.53
+ -0.219
+ 0.07
+ 2
+ 1
+ 0
+
+
+ Slimy
+ 1
+ -81.3
+ -81.3
+ -0.218
+ 0.073
+ 2
+ 1
+ 0
+
+
+
+ 10
+ -81.3
+ -81.3
+ -0.218
+ 0.073
+ 2
+ 1
+ 0
+
+
+ 10
+ -79.56
+ -79.56
+ -0.218
+ 0.082
+ 2
+ 1
+ 0
+
+
+ 10
+ -81.53
+ -81.53
+ -0.219
+ 0.07
+ 2
+ 1
+ 0
+
+
+ Slimy
+ 1
+ -81.3
+ -81.3
+ -0.218
+ 0.073
+ 2
+ 1
+ 0
+
+
+
+
+ 10
+ -81.3
+ -81.3
+ -0.218
+ 0.073
+ 2
+ 1
+ 0
+
+
+ 10
+ -79.56
+ -79.56
+ -0.218
+ 0.082
+ 2
+ 1
+ 0
+
+
+ 10
+ -81.53
+ -81.53
+ -0.219
+ 0.07
+ 2
+ 1
+ 0
+
+
+ Slimy
+ 1
+ -81.3
+ -81.3
+ -0.218
+ 0.073
+ 2
+ 1
+ 0
+
+
+
+ 10
+ -81.3
+ -81.3
+ -0.218
+ 0.073
+ 2
+ 1
+ 0
+
+
+ 10
+ -79.56
+ -79.56
+ -0.218
+ 0.082
+ 2
+ 1
+ 0
+
+
+ 10
+ -81.53
+ -81.53
+ -0.219
+ 0.07
+ 2
+ 1
+ 0
+
+
+ Slimy
+ 1
+ -81.3
+ -81.3
+ -0.218
+ 0.073
+ 2
+ 1
+ 0
+
+
+
+
+
+ 10
+ -81.3
+ -73.04
+ -0.218
+ 0.073
+ 2
+ 2
+ 0
+
+
+ 10
+ -79.56
+ -77.66
+ -0.218
+ 0.082
+ 2
+ 2
+ 0
+
+
+ 10
+ -81.53
+ -77.74
+ -0.219
+ 0.07
+ 2
+ 2
+ 0
+
+
+ Slimy
+ 1
+ -81.3
+ -73.04
+ -0.218
+ 0.073
+ 2
+ 2
+ 0
+
+
+
+
+
+ 10
+ -81.3
+ -73.04
+ -0.218
+ 0.073
+ 2
+ 2
+ 0
+
+
+ 10
+ -79.56
+ -77.66
+ -0.218
+ 0.082
+ 2
+ 2
+ 0
+
+
+ 10
+ -81.53
+ -77.74
+ -0.219
+ 0.07
+ 2
+ 2
+ 0
+
+
+ Slimy
+ 1
+ -81.3
+ -73.04
+ -0.218
+ 0.073
+ 2
+ 2
+ 0
+
+
+
+
+
+ 10
+ -81.3
+ -73.04
+ -0.218
+ 0.073
+ 2
+ 2
+ 0
+
+
+ 10
+ -79.56
+ -77.66
+ -0.218
+ 0.082
+ 2
+ 2
+ 0
+
+
+ 10
+ -81.53
+ -77.74
+ -0.219
+ 0.07
+ 2
+ 2
+ 0
+
+
+ Slimy
+ 1
+ -81.3
+ -73.04
+ -0.218
+ 0.073
+ 2
+ 2
+ 0
+
+
+
+
+
+ 10
+ -81.3
+ -73.04
+ -0.218
+ 0.073
+ 2
+ 2
+ 0
+
+
+ 10
+ -79.56
+ -77.66
+ -0.218
+ 0.082
+ 2
+ 2
+ 0
+
+
+ 10
+ -81.53
+ -77.74
+ -0.219
+ 0.07
+ 2
+ 2
+ 0
+
+
+ Slimy
+ 1
+ -81.3
+ -73.04
+ -0.218
+ 0.073
+ 2
+ 2
+ 0
+
+
+
+
+
+ 10
+ -81.3
+ -73.04
+ -0.218
+ 0.073
+ 2
+ 2
+ 0
+
+
+ 10
+ -79.56
+ -77.66
+ -0.218
+ 0.082
+ 2
+ 2
+ 0
+
+
+ 10
+ -81.53
+ -77.74
+ -0.219
+ 0.07
+ 2
+ 2
+ 0
+
+
+ Slimy
+ 1
+ -81.3
+ -73.04
+ -0.218
+ 0.073
+ 2
+ 2
+ 0
+
+
+
+
+
+ 10
+ -81.3
+ -73.04
+ -0.218
+ 0.073
+ 2
+ 2
+ 0
+
+
+ 10
+ -79.56
+ -77.66
+ -0.218
+ 0.082
+ 2
+ 2
+ 0
+
+
+ 10
+ -81.53
+ -77.74
+ -0.219
+ 0.07
+ 2
+ 2
+ 0
+
+
+ Slimy
+ 1
+ -81.3
+ -73.04
+ -0.218
+ 0.073
+ 2
+ 2
+ 0
+
+
+
+
+ 10
+ -81.3
+ -81.3
+ -0.218
+ 0.073
+ 2
+ 1
+ 0
+
+
+ 10
+ -79.56
+ -79.56
+ -0.218
+ 0.082
+ 2
+ 1
+ 0
+
+
+ 10
+ -81.53
+ -81.53
+ -0.219
+ 0.07
+ 2
+ 1
+ 0
+
+
+ Slimy
+ 1
+ -81.3
+ -81.3
+ -0.218
+ 0.073
+ 2
+ 1
+ 0
+
+
+
+
+
+
+
+ 10
+ 9.97
+ -7.61
+ 0.444
+ 0.368
+ 3
+ 3
+ 0
+
+
+ 10
+ 23.82
+ -6.90
+ 0.432
+ 0.403
+ 3
+ 3
+ 0
+
+
+ 10
+ 5.19
+ -6.19
+ 0.442
+ 0.388
+ 3
+ 3
+ 0
+
+
+ 1
+ 9.97
+ -7.61
+ 0.444
+ 0.368
+ 3
+ 3
+ 0
+
+
+
+
+
+
+
+
+
+
+ Cunnilingus
+ cunnilingus
+ true
+
+ Oral
+ Fingering
+ Cunnilingus
+
+
+
+ Cunnilingus
+ CunnilingusF
+ CunnilingusRape
+ CunnilingusRapeF
+
+ Fingering
+ FingeringF
+ FingeringRape
+ FingeringRapeF
+
+ Fisting
+ FistingF
+ FistingRape
+ FistingRapeF
+
+
+
+
+
+ Human
+
+ true
+
+ Vagina
+
+
+ (-0.2, 0.1)
+
+
+
+
+ Human
+
+ true
+
+ (-0.1, 0.15)
+
+
+
+
+
+
+
+
+ Initial
+ False
+ 0
+
+
+
+
+ 60
+ -81.06536
+ -56.4483032
+ 0
+ -0.0624052179
+ -0.437134951
+ 0
+ 1
+ 1
+
+
+ 1
+ -87.3645554
+ -69.70276
+ 0
+ -0.0692383763
+ -0.440020353
+ 0
+ 1
+ 1
+
+
+
+
+ LayingPawn
+
+
+ 60
+ -27.578373
+ 0.2816162
+ 0
+ 0.102704488
+ 0.50675
+ 0
+ 3
+ 3
+
+
+ 1
+ -47.9400826
+ -21.93164
+ 0
+ -0.04209958
+ 0.467844343
+ -0.1
+ 3
+ 3
+ Slimy
+
+
+
+
+
+
+
+
+ Slow
+ True
+ 1497
+ 0
+
+
+
+
+ 98
+ -87.3645554
+ -69.70276
+ 0
+ -0.0692383763
+ -0.440020353
+ 0
+ 1
+ 1
+
+
+ 40
+ -87.26528
+ -65.901825
+ 0
+ -0.0737426062
+ -0.432820916
+ 0
+ 1
+ 1
+
+
+ 1
+ -87.3645554
+ -69.70276
+ 0
+ -0.0692383763
+ -0.440020353
+ 0
+ 1
+ 1
+
+
+
+ 98
+ -87.3645554
+ -69.70276
+ 0
+ -0.0692383763
+ -0.440020353
+ 0
+ 1
+ 1
+
+
+ 40
+ -87.26528
+ -65.901825
+ 0
+ -0.0737426062
+ -0.432820916
+ 0
+ 1
+ 1
+
+
+ 1
+ -87.3645554
+ -69.70276
+ 0
+ -0.0692383763
+ -0.440020353
+ 0
+ 1
+ 1
+
+
+
+ 60
+ -87.3645554
+ -69.70276
+ 0
+ -0.0692383763
+ -0.440020353
+ 0
+ 1
+ 1
+
+
+ 120
+ -86.52611
+ -68.86432
+ 0
+ -0.05432228
+ -0.439906
+ 0
+ 1
+ 1
+
+
+ 40
+ -88.36286
+ -84.3309
+ 0
+ -0.06637782
+ -0.440140843
+ 0
+ 1
+ 1
+
+
+ 1
+ -87.3645554
+ -69.70276
+ 0
+ -0.0692383763
+ -0.440020353
+ 0
+ 1
+ 1
+
+
+
+
+ LayingPawn
+
+
+ 80
+ -47.9400826
+ -21.93164
+ 0
+ -0.04209958
+ 0.467844343
+ -0.1
+ 3
+ 3
+
+
+ 18
+ -41.1054764
+ -10.1737061
+ 0
+ 0.04582855
+ 0.462155169
+ 0
+ 3
+ 3
+
+
+ 40
+ -38.1903877
+ -31.6517334
+ 0
+ 0.0384018831
+ 0.4874894
+ 0
+ 3
+ 3
+
+
+ 1
+ -47.9400826
+ -21.93164
+ 0
+ -0.04209958
+ 0.467844343
+ -0.1
+ 3
+ 3
+ Slimy
+
+
+
+ 80
+ -47.9400826
+ -21.93164
+ 0
+ -0.04209958
+ 0.467844343
+ -0.1
+ 3
+ 3
+
+
+ 18
+ -41.1054764
+ -10.1737061
+ 0
+ 0.04582855
+ 0.462155169
+ 0
+ 3
+ 3
+
+
+ 40
+ -38.1903877
+ -31.6517334
+ 0
+ 0.0384018831
+ 0.4874894
+ 0
+ 3
+ 3
+
+
+ 1
+ -47.9400826
+ -21.93164
+ 0
+ -0.04209958
+ 0.467844343
+ -0.1
+ 3
+ 3
+ Slimy
+
+
+
+ 60
+ -47.9400826
+ -21.93164
+ 0
+ -0.04209958
+ 0.467844343
+ -0.1
+ 3
+ 3
+ Slimy
+
+
+ 40
+ -45.2595444
+ -13.57782
+ 0
+ 0.009577712
+ 0.4726282
+ 0
+ 3
+ 3
+ Slimy
+
+
+ 20
+ -45.2595444
+ -24.2278748
+ 0
+ 0.0315402448
+ 0.415024319
+ 0
+ 3
+ 3
+
+
+
+ 40
+ -45.2595444
+ -13.57782
+ 0
+ 0.009577712
+ 0.4726282
+ 0
+ 3
+ 3
+ Slimy
+
+
+ 20
+ -45.2595444
+ -24.2278748
+ 0
+ 0.0315402448
+ 0.415024319
+ 0
+ 3
+ 3
+
+
+
+ 40
+ -45.2595444
+ -13.57782
+ 0
+ 0.009577712
+ 0.4726282
+ 0
+ 3
+ 3
+ Slimy
+
+
+ 1
+ -47.9400826
+ -21.93164
+ 0
+ -0.04209958
+ 0.467844343
+ -0.1
+ 3
+ 3
+ Slimy
+
+
+
+
+
+
+
+
+ Transition
+ False
+ 0
+
+
+
+
+ 40
+ -87.3645554
+ -69.70276
+ 0
+ -0.06923838
+ -0.440020353
+ 0
+ 1
+ 1
+
+
+ 30
+ -97.90959
+ -69.72717
+ 0
+ -0.0259781852
+ -0.445601642
+ 0
+ 1
+ 1
+
+
+ 1
+ -87.3645554
+ -69.70276
+ 0
+ -0.06923838
+ -0.440020353
+ 0
+ 1
+ 1
+
+
+
+
+ LayingPawn
+
+
+ 40
+ -47.9400826
+ -21.93164
+ 0
+ -0.04209958
+ 0.467844343
+ -0.1
+ 3
+ 3
+ Slimy
+
+
+ 30
+ -35.8792953
+ -9.312592
+ 0
+ 0.03684573
+ 0.4285702
+ 0
+ 3
+ 3
+ Slimy
+
+
+ 1
+ -47.9400826
+ -21.93164
+ 0
+ -0.04209958
+ 0.467844343
+ 0
+ 3
+ 3
+ Slimy
+
+
+
+
+
+
+
+ Fast
+ True
+ 710
+ 0
+
+
+
+
+ 40
+ -87.3645554
+ -69.70276
+ 0
+ -0.06923838
+ -0.440020353
+ 0
+ 1
+ 1
+
+
+ 30
+ -97.90959
+ -69.72717
+ 0
+ -0.0259781852
+ -0.445601642
+ 0
+ 1
+ 1
+
+
+ 1
+ -87.3645554
+ -69.70276
+ 0
+ -0.06923838
+ -0.440020353
+ 0
+ 1
+ 1
+
+
+
+ 40
+ -87.3645554
+ -69.70276
+ 0
+ -0.06923838
+ -0.440020353
+ 0
+ 1
+ 1
+
+
+ 30
+ -97.90959
+ -69.72717
+ 0
+ -0.0259781852
+ -0.445601642
+ 0
+ 1
+ 1
+
+
+ 1
+ -87.3645554
+ -69.70276
+ 0
+ -0.06923838
+ -0.440020353
+ 0
+ 1
+ 1
+
+
+
+ 40
+ -87.3645554
+ -79.70276
+ 0
+ -0.06923838
+ -0.440020353
+ 0
+ 1
+ 2
+
+
+ 30
+ -97.90959
+ -79.72717
+ 0
+ -0.0259781852
+ -0.445601642
+ 0
+ 1
+ 2
+
+
+ 1
+ -87.3645554
+ -79.70276
+ 0
+ -0.06923838
+ -0.440020353
+ 0
+ 1
+ 2
+
+
+
+ 40
+ -87.3645554
+ -79.70276
+ 0
+ -0.06923838
+ -0.440020353
+ 0
+ 1
+ 2
+
+
+ 30
+ -97.90959
+ -79.72717
+ 0
+ -0.0259781852
+ -0.445601642
+ 0
+ 1
+ 2
+
+
+ 1
+ -87.3645554
+ -79.70276
+ 0
+ -0.06923838
+ -0.440020353
+ 0
+ 1
+ 2
+
+
+
+ 40
+ -87.3645554
+ -79.70276
+ 0
+ -0.06923838
+ -0.440020353
+ 0
+ 1
+ 2
+
+
+ 30
+ -97.90959
+ -79.72717
+ 0
+ -0.0259781852
+ -0.445601642
+ 0
+ 1
+ 2
+
+
+ 1
+ -87.3645554
+ -79.70276
+ 0
+ -0.06923838
+ -0.440020353
+ 0
+ 1
+ 2
+
+
+
+ 40
+ -87.3645554
+ -69.70276
+ 0
+ -0.06923838
+ -0.440020353
+ 0
+ 1
+ 1
+
+
+ 30
+ -97.90959
+ -69.72717
+ 0
+ -0.0259781852
+ -0.445601642
+ 0
+ 1
+ 1
+
+
+ 1
+ -87.3645554
+ -69.70276
+ 0
+ -0.06923838
+ -0.440020353
+ 0
+ 1
+ 1
+
+
+
+
+ LayingPawn
+
+
+ 40
+ -47.9400826
+ -21.93164
+ 0
+ -0.04209958
+ 0.467844343
+ 0
+ 3
+ 3
+ Slimy
+
+
+ 30
+ -35.8792953
+ -3.312592
+ 0
+ 0.03684573
+ 0.4285702
+ 0
+ 3
+ 3
+ Slimy
+
+
+ 1
+ -47.9400826
+ -21.93164
+ 0
+ -0.04209958
+ 0.467844343
+ 0
+ 3
+ 3
+ Slimy
+
+
+
+
+
+
+ Faster
+ True
+ 360
+ 0
+
+
+
+
+ 20
+ -87.3645554
+ -69.70276
+ 0
+ -0.06923838
+ -0.440020353
+ 0
+ 1
+ 1
+
+
+ 15
+ -97.90959
+ -69.72717
+ 0
+ -0.0259781852
+ -0.445601642
+ 0
+ 1
+ 1
+
+
+ 1
+ -87.3645554
+ -69.70276
+ 0
+ -0.06923838
+ -0.440020353
+ 0
+ 1
+ 1
+
+
+
+
+ LayingPawn
+
+
+ 20
+ -47.9400826
+ -21.93164
+ 0
+ -0.04209958
+ 0.467844343
+ 0
+ 3
+ 3
+ Slimy
+
+
+ 15
+ -35.8792953
+ -9.312592
+ 0
+ 0.03684573
+ 0.4285702
+ 0
+ 3
+ 3
+ Slimy
+
+
+ 1
+ -47.9400826
+ -21.93164
+ 0
+ -0.04209958
+ 0.467844343
+ 0
+ 3
+ 3
+ Slimy
+
+
+
+
+
+
+ Cum
+ True
+ 639
+ 0
+
+
+
+
+ 20
+ -87.3645554
+ -69.70276
+ 0
+ -0.06923838
+ -0.440020353
+ 0
+ 1
+ 1
+
+
+ 15
+ -97.90959
+ -69.72717
+ 0
+ -0.0259781852
+ -0.445601642
+ 0
+ 1
+ 1
+
+
+ 1
+ -87.3645554
+ -69.70276
+ 0
+ -0.06923838
+ -0.440020353
+ 0
+ 1
+ 1
+
+
+
+ 20
+ -87.3645554
+ -69.70276
+ 0
+ -0.06923838
+ -0.440020353
+ 0
+ 1
+ 1
+
+
+ 15
+ -97.90959
+ -69.72717
+ 0
+ -0.0259781852
+ -0.445601642
+ 0
+ 1
+ 1
+
+
+ 1
+ -87.3645554
+ -69.70276
+ 0
+ -0.06923838
+ -0.440020353
+ 0
+ 1
+ 1
+
+
+
+ 20
+ -87.3645554
+ -69.70276
+ 0
+ -0.06923838
+ -0.440020353
+ 0
+ 1
+ 1
+
+
+ True
+ 80
+ -97.90959
+ -69.72717
+ 0
+ -0.0259781852
+ -0.445601642
+ 0
+ 1
+ 1
+ Cum
+
+
+ 40
+ -99.80413
+ -94.4023743
+ 0
+ -0.01950606
+ -0.447728932
+ 0
+ 1
+ 1
+
+
+ 1
+ -87.3645554
+ -69.70276
+ 0
+ -0.06923838
+ -0.440020353
+ 0
+ 1
+ 1
+
+
+
+
+ LayingPawn
+
+
+
+ 20
+ -47.9400826
+ -21.93164
+ 0
+ -0.04209958
+ 0.467844343
+ 0
+ 3
+ 3
+ Slimy
+
+
+ 15
+ -35.8792953
+ -9.312592
+ 0
+ 0.03684573
+ 0.4285702
+ 0
+ 3
+ 3
+ Slimy
+
+
+ 1
+ -47.9400826
+ -21.93164
+ 0
+ -0.04209958
+ 0.467844343
+ 0
+ 3
+ 3
+ Slimy
+
+
+
+ 20
+ -47.9400826
+ -21.93164
+ 0
+ -0.04209958
+ 0.467844343
+ 0
+ 3
+ 3
+ Slimy
+
+
+ 15
+ -35.8792953
+ -9.312592
+ 0
+ 0.03684573
+ 0.4285702
+ 0
+ 3
+ 3
+ Slimy
+
+
+ 1
+ -47.9400826
+ -21.93164
+ 0
+ -0.04209958
+ 0.467844343
+ 0
+ 3
+ 3
+ Slimy
+
+
+
+ 20
+ -47.9400826
+ -21.93164
+ 0
+ -0.04209958
+ 0.467844343
+ 0
+ 3
+ 3
+ Slimy
+
+
+ 80
+ -35.8792953
+ -9.312592
+ 0
+ 0.03684573
+ 0.4285702
+ 0
+ 3
+ 3
+
+
+ 40
+ -38.5277061
+ -1.13140869
+ 0
+ 0.0376501828
+ 0.42935127
+ 0
+ 3
+ 3
+
+
+ 1
+ -47.9400826
+ -21.93164
+ 0
+ -0.04209958
+ 0.467844343
+ 0
+ 3
+ 3
+ Slimy
+
+
+
+
+
+
+
+
+
+
diff --git a/1.3/Defs/AnimationDefs/Animations_Masturbate.xml b/1.3/Defs/AnimationDefs/Animations_Masturbate.xml
new file mode 100644
index 0000000..2968fa1
--- /dev/null
+++ b/1.3/Defs/AnimationDefs/Animations_Masturbate.xml
@@ -0,0 +1,9 @@
+
+
+
+
\ No newline at end of file
diff --git a/1.3/Defs/AnimationDefs/Animations_Multi.xml b/1.3/Defs/AnimationDefs/Animations_Multi.xml
new file mode 100644
index 0000000..af7ea7a
--- /dev/null
+++ b/1.3/Defs/AnimationDefs/Animations_Multi.xml
@@ -0,0 +1,660 @@
+
+
+
+ Double_Penetration
+ double penetration
+ true
+
+ DoublePenetration
+ Anal
+ Oral
+ Vaginal
+
+
+
+
+ Human
+
+ true
+
+
+
+ Human
+
+ true
+ true
+ true
+
+
+
+ Human
+
+ true
+ true
+ true
+
+
+
+
+
+ Slow
+ true
+ 976
+ 0
+
+
+
+
+
+ 25
+ 62.7
+ 0.2
+ 0.01
+ 0.118
+ 1
+ 1
+ 0
+
+
+ 35
+ 48.1
+ 16.3
+ 0
+ 0.188
+ 1
+ 1
+ 0
+
+
+ Suck
+ 1
+ 62.7
+ 0.2
+ 0.01
+ 0.118
+ 1
+ 1
+ 0
+
+
+
+
+
+ LayingPawn
+
+
+ -10
+ 30
+ 12
+ -14.1
+ 0.674
+ 0.378
+ 3
+ 3
+ 0
+
+
+ 30
+ 12
+ -15.1
+ 0.729
+ 0.378
+ 3
+ 3
+ 0
+
+
+ -10
+ 1
+ 12
+ -14.1
+ 0.674
+ 0.378
+ 3
+ 3
+ 0
+
+
+
+
+
+ LayingPawn
+
+
+ 43
+ 27
+ 8.7
+ 15.1
+ -0.70
+ 0.378
+ 1
+ 1
+ 0
+
+
+ Fuck
+ 33
+ -6.7
+ 14.1
+ -0.53
+ 0.378
+ 1
+ 1
+ 0
+
+
+ 43
+ 1
+ 8.7
+ 15.1
+ -0.70
+ 0.378
+ 1
+ 1
+ 0
+
+
+
+
+
+
+ Face_Fuck
+ true
+ 650
+ 0
+
+
+
+
+
+ 13
+ 62.7
+ 0.2
+ 0.01
+ 0.118
+ 1
+ 1
+ 0
+
+
+ 6
+ 60.7
+ 5.6
+ 0.025
+ 0.118
+ 1
+ 1
+ 0
+
+
+ 6
+ 62.7
+ 0.2
+ 0.08
+ 0.118
+ 1
+ 1
+ 0
+
+
+ Suck
+ 1
+ 62.7
+ 0.2
+ 0.01
+ 0.118
+ 1
+ 1
+ 0
+
+
+
+
+
+ LayingPawn
+
+
+ -10
+ 13
+ 12
+ -14.1
+ 0.674
+ 0.378
+ 3
+ 3
+ 0
+
+
+ 12
+ 2
+ -15.1
+ 0.729
+ 0.378
+ 3
+ 3
+ 0
+
+
+ -10
+ 1
+ 12
+ -14.1
+ 0.674
+ 0.378
+ 3
+ 3
+ 0
+
+
+
+
+
+ LayingPawn
+
+
+ 43
+ 13
+ 8.7
+ 15.1
+ -0.70
+ 0.378
+ 1
+ 1
+ 0
+
+
+ Fuck
+ 12
+ -6.7
+ 14.1
+ -0.53
+ 0.378
+ 1
+ 1
+ 0
+
+
+ 43
+ 1
+ 8.7
+ 15.1
+ -0.70
+ 0.378
+ 1
+ 1
+ 0
+
+
+
+
+
+
+ Cum
+ true
+ 392
+ 0
+
+
+
+
+
+ 9
+ 62.7
+ 0.2
+ 0.01
+ 0.118
+ 1
+ 1
+ 0
+
+
+ 4
+ 60.7
+ 5.6
+ 0.025
+ 0.118
+ 1
+ 1
+ 0
+
+
+ 4
+ 62.7
+ 0.2
+ 0.056
+ 0.118
+ 1
+ 1
+ 0
+
+
+ Suck
+ 1
+ 62.7
+ 0.2
+ 0.01
+ 0.118
+ 1
+ 1
+ 0
+
+
+
+ 9
+ 62.7
+ 0.2
+ 0.01
+ 0.118
+ 1
+ 1
+ 0
+
+
+ 4
+ 60.7
+ 5.6
+ 0.025
+ 0.118
+ 1
+ 1
+ 0
+
+
+ 4
+ 62.7
+ 0.2
+ 0.056
+ 0.118
+ 1
+ 1
+ 0
+
+
+ Suck
+ 1
+ 62.7
+ 0.2
+ 0.01
+ 0.118
+ 1
+ 1
+ 0
+
+
+
+ 9
+ 62.7
+ 0.2
+ 0.01
+ 0.118
+ 1
+ 1
+ 0
+
+
+ true
+ 120
+ 60.7
+ 5.6
+ 0.025
+ 0.118
+ 1
+ 1
+ 0
+
+
+ 30
+ 62.7
+ 0.2
+ 0.056
+ 0.118
+ 1
+ 1
+ 0
+
+
+ Suck
+ 1
+ 62.7
+ 0.2
+ 0.01
+ 0.118
+ 1
+ 1
+ 0
+
+
+
+
+
+ LayingPawn
+
+
+ -10
+ 9
+ 9
+ -14.1
+ 0.674
+ 0.378
+ 3
+ 3
+ 0
+
+
+ 8
+ 0
+ -15.1
+ 0.729
+ 0.378
+ 3
+ 3
+ 0
+
+
+ 1
+ 9
+ -14.1
+ 0.674
+ 0.378
+ 3
+ 3
+ 0
+
+
+
+ 9
+ 9
+ -14.1
+ 0.674
+ 0.378
+ 3
+ 3
+ 0
+
+
+ 8
+ 0
+ -15.1
+ 0.729
+ 0.378
+ 3
+ 3
+ 0
+
+
+ 1
+ 9
+ -14.1
+ 0.674
+ 0.378
+ 3
+ 3
+ 0
+
+
+
+
+ 9
+ 9
+ -14.1
+ 0.674
+ 0.378
+ 3
+ 3
+ 0
+
+
+ 120
+ 9
+ -15.1
+ 0.674
+ 0.378
+ 3
+ 3
+ 0
+
+
+ 30
+ 9
+ 7
+ 0.674
+ 0.378
+ 3
+ 3
+ 0
+
+
+ 1
+ 9
+ -14.1
+ 0.674
+ 0.378
+ 3
+ 3
+ 0
+ -10
+
+
+
+
+
+
+ LayingPawn
+
+
+ 43
+ 9
+ 8.7
+ 15.1
+ -0.70
+ 0.378
+ 1
+ 1
+ 0
+
+
+ Fuck
+ 8
+ -6.7
+ 14.1
+ -0.53
+ 0.378
+ 1
+ 1
+ 0
+
+
+ 1
+ 8.7
+ 15.1
+ -0.70
+ 0.378
+ 1
+ 1
+ 0
+
+
+
+ 9
+ 8.7
+ 15.1
+ -0.70
+ 0.378
+ 1
+ 1
+ 0
+
+
+ Fuck
+ 8
+ -6.7
+ 14.1
+ -0.53
+ 0.378
+ 1
+ 1
+ 0
+
+
+ 1
+ 8.7
+ 15.1
+ -0.70
+ 0.378
+ 1
+ 1
+ 0
+
+
+
+ 9
+ 8.7
+ 15.1
+ -0.70
+ 0.378
+ 1
+ 1
+ 0
+
+
+ Cum
+ 120
+ -6.7
+ 14.1
+ -0.53
+ 0.378
+ 1
+ 1
+ 0
+
+
+ 30
+ -6.7
+ -7
+ -0.53
+ 0.378
+ 1
+ 1
+ 0
+
+
+ 43
+ 1
+ 8.7
+ 15.1
+ -0.70
+ 0.378
+ 1
+ 1
+ 0
+
+
+
+
+
+
+
+
+
+
+
diff --git a/1.3/Defs/AnimationDefs/Animations_SexToys.xml b/1.3/Defs/AnimationDefs/Animations_SexToys.xml
new file mode 100644
index 0000000..320d3aa
--- /dev/null
+++ b/1.3/Defs/AnimationDefs/Animations_SexToys.xml
@@ -0,0 +1,59 @@
+
+
+
+
diff --git a/1.3/Defs/AnimationDefs/Animations_Vanilla2.xml b/1.3/Defs/AnimationDefs/Animations_Vanilla2.xml
new file mode 100644
index 0000000..71b02a9
--- /dev/null
+++ b/1.3/Defs/AnimationDefs/Animations_Vanilla2.xml
@@ -0,0 +1,378 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/1.3/Defs/AnimationDefs/Animations_vanilla.xml b/1.3/Defs/AnimationDefs/Animations_vanilla.xml
new file mode 100644
index 0000000..0fd61d5
--- /dev/null
+++ b/1.3/Defs/AnimationDefs/Animations_vanilla.xml
@@ -0,0 +1,2799 @@
+
+
+
+
+ Doggystyle
+ doggystyle
+ true
+
+ Vaginal
+ Anal
+ DoublePenetration
+
+
+
+ AnalSex
+ AnalSexF
+ AnalRape
+ VaginalSex
+ VaginalSexF
+ VaginalRape
+
+
+
+
+
+
+ Human
+
+ true
+
+
+
+ Human
+
+ true
+ true
+ true
+
+ (0, 0.2)
+
+
+
+
+
+
+ Slow_Fuck
+ true
+ 612
+ 0
+
+
+
+
+ 0
+ 10
+ 27
+ 0.298
+ 0.166
+ 0
+ 1
+ 2
+
+
+ 40
+ 32
+ 0.326
+ 0.190
+ 1
+ 2
+
+
+ 1
+ 27
+ 0.298
+ 0.166
+ 1
+ 2
+
+
+
+ 10
+ 27
+ 0.298
+ 0.166
+ 1
+ 2
+
+
+ 40
+ 32
+ 0.326
+ 0.190
+ 1
+ 2
+
+
+ 1
+ 27
+ 0.298
+ 0.166
+ 1
+ 2
+
+
+
+ 10
+ 27
+ 0.298
+ 0.166
+ 1
+ 2
+
+
+ 40
+ 32
+ 0.326
+ 0.190
+ 1
+ 2
+
+
+ 1
+ 27
+ 0.298
+ 0.166
+ 1
+ 2
+
+
+
+ 10
+ 27
+ 0.298
+ 0.166
+ 1
+ 1
+
+
+ 40
+ 32
+ 0.326
+ 0.190
+ 1
+ 1
+
+
+ 1
+ 27
+ 0.298
+ 0.166
+ 1
+ 1
+
+
+
+ 10
+ 27
+ 0.298
+ 0.166
+ 1
+ 1
+
+
+ 40
+ 32
+ 0.326
+ 0.190
+ 1
+ 1
+
+
+ 1
+ 27
+ 0.298
+ 0.166
+ 1
+ 1
+
+
+
+ 10
+ 27
+ 0.298
+ 0.166
+ 1
+ 1
+
+
+ 40
+ 32
+ 0.326
+ 0.190
+ 1
+ 1
+
+
+ 1
+ 27
+ 0.298
+ 0.166
+ 1
+ 1
+
+
+
+ 10
+ 27
+ 0.298
+ 0.166
+ 1
+ 1
+
+
+ 40
+ 32
+ 0.326
+ 0.190
+ 1
+ 1
+
+
+ 1
+ 27
+ 0.298
+ 0.166
+ 1
+ 1
+
+
+
+ 10
+ 27
+ 0.298
+ 0.166
+ 1
+ 1
+
+
+ 40
+ 32
+ 0.326
+ 0.190
+ 1
+ 1
+
+
+ 0
+ 1
+ 27
+ 0.298
+ 0.166
+ 0
+ 1
+ 1
+
+
+
+
+ LayingPawn
+
+
+ 27
+ 0
+ 10
+ 16.6
+ -0.217
+ 0.175
+ 3
+ 1
+ 1
+
+
+
+ 40
+ Fuck
+ -17
+ -0.217
+ 0.272
+ 5.4
+ 1
+ 1
+
+
+ 1
+ 16.6
+ -0.217
+ 0.175
+ 3
+ 1
+ 1
+ 0
+ 27
+
+
+
+
+
+
+ Fast_Fuck
+ true
+ 609
+ 0
+
+
+
+
+ 8
+ 27
+ 0.298
+ 0.166
+ 1
+ 1
+ 1
+ 0
+
+
+ 12
+ 32
+ 0.326
+ 0.190
+ 4
+ 1
+ 1
+
+
+ 1
+ 27
+ 0.298
+ 0.166
+ 1
+ 1
+ 1
+ 0
+
+
+
+
+ LayingPawn
+
+
+ 27
+ 8
+ 11
+ -0.217
+ 0.175
+ 8
+ 1
+ 1
+ 0
+
+
+
+ 12
+ Fuck
+ -12
+ -0.217
+ 0.272
+ 9
+ 1
+ 1
+
+
+ 1
+ 11
+ -0.217
+ 0.175
+ 8
+ 1
+ 1
+ 0
+ 27
+
+
+
+
+
+
+ Cum
+ true
+ 300
+ 0
+
+
+
+
+ 8
+ 27
+ 0.298
+ 0.166
+ 0
+ 1
+ 1
+ 0
+
+
+ Cum
+ 100
+ 32
+ 0.326
+ 0.190
+ -1
+ 1
+ 1
+ true
+
+
+ 12
+ 35
+ 0.326
+ 0.190
+ -14
+ 1
+ 1
+
+
+ 1
+ 27
+ 0.298
+ 0.166
+ 0
+ 1
+ 1
+ 0
+
+
+
+
+ LayingPawn
+
+
+ 27
+ 8
+ 11
+ -0.217
+ 0.175
+ -8
+ 1
+ 1
+ 0
+
+
+ 100
+ -12
+ -0.217
+ 0.272
+ -9
+ 1
+ 1
+
+
+ 12
+ -15
+ -0.227
+ 0.272
+ -4
+ 1
+ 1
+
+
+ 1
+ 11
+ -0.217
+ 0.175
+ -8
+ 1
+ 1
+ 0
+ 27
+
+
+
+
+
+
+
+
+ Blowjob
+ blowjob
+ true
+
+ Oral
+ Fellatio
+
+
+ Handjob
+ HandjobF
+ HandjobRape
+ HandjobRapeF
+
+ Breastjob
+ BreastjobF
+ BreastjobRape
+ BreastjobRapeF
+
+ Fellatio
+ FellatioF
+ FellatioRape
+ FellatioRapeF
+
+ Beakjob
+ BeakjobF
+ BeakjobRape
+ BeakjobRapeF
+
+
+
+
+
+
+
+ Human
+
+
+ (0, -0.2)
+
+
+
+
+ Human
+
+ true
+ true
+ true
+
+ (0, 0.2)
+
+
+
+
+
+ Slow_Suck
+ true
+ 1140
+ 0
+
+
+
+
+ 35
+ 0
+ 0
+ 0
+ -0.255
+ 0
+ 0
+ 0
+
+
+ Suck
+ 59
+ 0
+ 0
+ -0.33
+ 0
+ 0
+ -0.16
+
+
+ 1
+ 0
+ 0
+ 0
+ -0.255
+ 0
+ 0
+ 0
+
+
+
+ 35
+ 0
+ 0
+ 0
+ -0.255
+ 0
+ 0
+ 0
+
+
+ Suck
+ 59
+ 0
+ 0
+ -0.33
+ 0
+ 0
+ -0.15
+
+
+ 1
+ 0
+ 0
+ 0
+ -0.255
+ 0
+ 0
+ 0
+
+
+
+ 35
+ 0
+ 0
+ 0
+ -0.255
+ 0
+ 0
+ 0
+
+
+ Suck
+ 59
+
+ 6
+ 0
+ -0.33
+ 0
+ 0
+ -0.13
+
+
+ 1
+ 0
+ 0
+ 0
+ -0.255
+ 0
+ 0
+ 0
+
+
+
+ 35
+ 0
+ 0
+ 0
+ -0.255
+ 0
+ 0
+ 0
+
+
+ Suck
+ 59
+ 0
+ -4
+ 0
+ -0.33
+ 0
+ 0
+ -0.12
+
+
+ 1
+ 0
+ 0
+ 0
+ -0.255
+ 0
+ 0
+ 0
+
+
+
+
+ LayingPawn
+
+
+ 35
+ 0
+ 0
+ 0
+ 0.473
+ 2
+ 2
+ 0
+ 180
+
+
+ 59
+ 0
+ 0
+ 0.490
+ 2
+ 2
+ -0.003
+
+
+ 1
+ 0
+ 0
+ 0
+ 0.473
+ 2
+ 2
+ 0
+ 180
+
+
+
+
+
+
+ Face_Fuck
+ true
+ 300
+ 0
+
+
+
+
+ 15
+ 0
+ 0
+ 0
+ -0.255
+ 0
+ 0
+ 0
+
+
+ Suck
+ 14
+ 0
+ 0
+ -0.270
+ 0
+ 0
+ -0.06
+
+
+ 1
+ 0
+ 0
+ 0
+ -0.255
+ 0
+ 0
+ 0
+
+
+
+
+ LayingPawn
+
+
+ 15
+ 0
+ 0
+ 0
+ 0.473
+ 2
+ 2
+ 0
+ 180
+
+
+ 14
+ 0
+ 0
+ 0.575
+ 2
+ 2
+ -0.051
+
+
+ 1
+ 0
+ 0
+ 0
+ 0.473
+ 2
+ 2
+ 0
+ 180
+
+
+
+
+
+
+ Cum
+ true
+ 600
+ 0
+
+
+
+
+ 12
+ 0
+ 0
+ 0
+ -0.255
+ 0
+ 0
+ 0
+
+
+ 7
+ 0
+ 0
+ -0.290
+ 0
+ 0
+ -0.06
+
+
+ 7
+ Suck
+ 0
+ 0
+ -0.290
+ 0
+ 0
+ -0.008
+
+
+ 60
+ 0
+ 0
+ -0.290
+ 0
+ 0
+ -0.06
+
+
+ 14
+ 0
+ 0
+ -0.290
+ 0
+ 0
+ -0.06
+
+
+ 1
+ 0
+ 0
+ 0
+ -0.255
+ 0
+ 0
+ 0
+
+
+
+
+ LayingPawn
+
+
+ 12
+ 0
+ 0
+ 0
+ 0.473
+ 2
+ 2
+ 0
+ 180
+
+
+ 7
+ Cum
+ 0
+ 0
+ 0.575
+ 2
+ 2
+ -0.051
+
+
+ 7
+ 0
+ 0
+ 0.50
+ 2
+ 2
+ -0.04
+
+
+ true
+ 60
+ 0
+ 0
+ 0.575
+ 2
+ 2
+ -0.051
+
+
+ 14
+ 0
+ 0
+ 0.575
+ 2
+ 2
+ -0.051
+
+
+ 1
+ 0
+ 0
+ 0
+ 0.473
+ 2
+ 2
+ 0
+ 180
+
+
+
+
+
+
+
+
+
+ ReverseStandAndCarry
+ reverse stand-and-carry
+ true
+
+ Anal
+ Vaginal
+ DoublePenetration
+
+
+ AnalSex
+ AnalSexF
+ AnalRape
+ VaginalSex
+ VaginalSexF
+ VaginalRape
+
+
+
+
+
+ Human
+
+ true
+
+ (0, 0.2)
+
+
+
+
+ Human
+
+ true
+ true
+ true
+
+ (0, 0.2)
+
+
+
+
+
+
+ Slow_Fuck
+ true
+ 1080
+ 0
+
+
+
+
+ 30
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+ 29
+ 6.04
+ 15
+ -0.175
+ 0.437
+ 3
+ 3
+ 0
+
+
+ 1
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+
+
+ LayingPawn
+
+
+ 6
+ 30
+ -3.18
+ -0.41
+ 0.122
+ 0.356
+ 3
+ 3
+ 0
+
+
+ 40
+ Fuck
+ 29
+ 17.11
+ -2.87
+ 0.114
+ 0.359
+ 3
+ 3
+ 0
+
+
+ 1
+ -3.18
+ -0.41
+ 0.122
+ 0.356
+ 3
+ 3
+ 0
+ 6
+
+
+
+
+
+
+
+ Fast_Fuck
+ true
+ 780
+ 0
+
+
+
+
+ 6
+ 10.6
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+ 7
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+ 12
+ 6.04
+ 15
+ -0.175
+ 0.437
+ 3
+ 3
+ 0
+
+
+ 1
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+
+ 6
+ 10.6
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+ 7
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+ 12
+ 6.04
+ 15
+ -0.175
+ 0.437
+ 3
+ 3
+ 0
+
+
+ 1
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+
+
+ 6
+ 10.6
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 2
+ 0
+
+
+ 7
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 2
+ 0
+
+
+ 12
+ 6.04
+ 15
+ -0.175
+ 0.437
+ 3
+ 2
+ 0
+
+
+ 1
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 2
+ 0
+
+
+
+ 6
+ 10.6
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 2
+ 0
+
+
+ 7
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 2
+ 0
+
+
+ 12
+ 6.04
+ 15
+ -0.175
+ 0.437
+ 3
+ 2
+ 0
+
+
+ 1
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 2
+ 0
+
+
+
+ 6
+ 10.6
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 2
+ 0
+
+
+ 7
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 2
+ 0
+
+
+ 12
+ 6.04
+ 15
+ -0.175
+ 0.437
+ 3
+ 2
+ 0
+
+
+ 1
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 2
+ 0
+
+
+
+ 6
+ 10.6
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 2
+ 0
+
+
+ 7
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 2
+ 0
+
+
+ 12
+ 6.04
+ 15
+ -0.175
+ 0.437
+ 3
+ 2
+ 0
+
+
+ 1
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 2
+ 0
+
+
+
+ 6
+ 10.6
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 2
+ 0
+
+
+ 7
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 2
+ 0
+
+
+ 12
+ 6.04
+ 15
+ -0.175
+ 0.437
+ 3
+ 2
+ 0
+
+
+ 1
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 2
+ 0
+
+
+
+ 6
+ 10.6
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 2
+ 0
+
+
+ 7
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 2
+ 0
+
+
+ 12
+ 6.04
+ 15
+ -0.175
+ 0.437
+ 3
+ 2
+ 0
+
+
+ 1
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 2
+ 0
+
+
+
+ 6
+ 10.6
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 2
+ 0
+
+
+ 7
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 2
+ 0
+
+
+ 12
+ 6.04
+ 15
+ -0.175
+ 0.437
+ 3
+ 2
+ 0
+
+
+ 1
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 2
+ 0
+
+
+
+
+
+ 6
+ 10.6
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+ 7
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+ 12
+ 6.04
+ 15
+ -0.175
+ 0.437
+ 3
+ 3
+ 0
+
+
+ 1
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+
+ 6
+ 10.6
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+ 7
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+ 12
+ 6.04
+ 15
+ -0.175
+ 0.437
+ 3
+ 3
+ 0
+
+
+ 1
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+
+ 6
+ 10.6
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+ 7
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+ 12
+ 6.04
+ 15
+ -0.175
+ 0.437
+ 3
+ 3
+ 0
+
+
+ 1
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+
+ 6
+ 10.6
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+ 7
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+ 12
+ 6.04
+ 15
+ -0.175
+ 0.437
+ 3
+ 3
+ 0
+
+
+ 1
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+
+ 6
+ 10.6
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+ 7
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+ 12
+ 6.04
+ 15
+ -0.175
+ 0.437
+ 3
+ 3
+ 0
+
+
+ 1
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+
+ 6
+ 10.6
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+ 7
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+ 12
+ 6.04
+ 15
+ -0.175
+ 0.437
+ 3
+ 3
+ 0
+
+
+ 1
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+
+
+ LayingPawn
+
+
+ 6
+ 13
+ -3.18
+ -0.41
+ 0.122
+ 0.356
+ 3
+ 3
+ 0
+
+
+ 40
+ Fuck
+ 12
+ 17.11
+ -2.87
+ 0.114
+ 0.359
+ 3
+ 3
+ 0
+
+
+ 1
+ -3.18
+ -0.41
+ 0.122
+ 0.356
+ 3
+ 3
+ 0
+ 6
+
+
+
+
+
+
+
+ Cum
+ true
+ 415
+ 0
+
+
+
+
+ 3
+ 10.6
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+ 4
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+ 7
+ 6.04
+ 15
+ -0.175
+ 0.437
+ 3
+ 3
+ 0
+
+
+ 1
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+
+ 3
+ 10.6
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+ 4
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+ 7
+ 6.04
+ 15
+ -0.175
+ 0.437
+ 3
+ 3
+ 0
+
+
+ 1
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+
+ 3
+ 10.6
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+ 4
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+ 7
+ 6.04
+ 15
+ -0.175
+ 0.437
+ 3
+ 3
+ 0
+
+
+ 1
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+
+ 3
+ 10.6
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+ 4
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+ true
+ 75
+ 6.04
+ 15
+ -0.175
+ 0.437
+ 3
+ 3
+ 0
+
+
+ 27
+ 6.04
+ 15
+ -0.175
+ 0.437
+ 3
+ 3
+ 0
+
+
+ 1
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+
+
+ LayingPawn
+
+
+ 6
+ 7
+ -3.18
+ -0.41
+ 0.122
+ 0.356
+ 3
+ 3
+ 0
+
+
+ 40
+ Fuck
+ 7
+ 17.11
+ -2.87
+ 0.114
+ 0.359
+ 3
+ 3
+ 0
+
+
+ 6
+ 1
+ -3.18
+ -0.41
+ 0.122
+ 0.356
+ 3
+ 3
+ 0
+
+
+
+ 6
+ 7
+ -3.18
+ -0.41
+ 0.122
+ 0.356
+ 3
+ 3
+ 0
+
+
+ 40
+ Fuck
+ 7
+ 17.11
+ -2.87
+ 0.114
+ 0.359
+ 3
+ 3
+ 0
+
+
+ 6
+ 1
+ -3.18
+ -0.41
+ 0.122
+ 0.356
+ 3
+ 3
+ 0
+
+
+
+ 6
+ 7
+ -3.18
+ -0.41
+ 0.122
+ 0.356
+ 3
+ 3
+ 0
+
+
+ 40
+ Fuck
+ 7
+ 17.11
+ -2.87
+ 0.114
+ 0.359
+ 3
+ 3
+ 0
+
+
+ 6
+ 1
+ -3.18
+ -0.41
+ 0.122
+ 0.356
+ 3
+ 3
+ 0
+
+
+
+ 6
+ 7
+ -3.18
+ -0.41
+ 0.122
+ 0.356
+ 3
+ 3
+ 0
+
+
+ 40
+ Cum
+ 75
+ 17.11
+ -2.87
+ 0.114
+ 0.359
+ 3
+ 3
+ 0
+
+
+ 40
+ 27
+ 17.11
+ -2.87
+ 0.114
+ 0.359
+ 3
+ 3
+ 0
+
+
+ 6
+ 1
+ -3.18
+ -0.41
+ 0.122
+ 0.356
+ 3
+ 3
+ 0
+
+
+
+
+
+
+
+
+
+ Cowgirl
+ cowgirl
+ true
+
+ Anal
+ Vaginal
+ DoublePenetration
+
+
+
+ AnalSex
+ AnalSexF
+ AnalRapeF
+ VaginalSex
+ VaginalSexF
+ VaginalRapeF
+
+
+
+
+
+
+
+ Human
+
+ true
+ true
+
+ (0, 0.2)
+
+
+
+
+
+ Human
+
+ true
+ true
+
+ (0, -0.2)
+
+
+
+
+
+
+
+ Slow_Fuck
+ true
+ 1340
+ 0
+
+
+
+
+
+ 16
+ 0
+ 0
+ 0
+ 0.554
+ 2
+ 2
+ 0
+
+
+ 17
+ 3.5
+ 0
+ -0.03
+ 0.624
+ 2
+ 2
+ -0.02
+
+
+ 16
+ 0
+ 0
+ 0
+ 0.694
+ 2
+ 2
+ -0.03
+
+
+ 17
+ -3.5
+ 0
+ 0.03
+ 0.624
+ 2
+ 2
+ -0.02
+
+
+ 1
+ Fuck
+ 0
+ 0
+ 0
+ 0.554
+ 2
+ 2
+ 0
+
+
+
+ 16
+ 0
+ 0
+ 0
+ 0.554
+ 2
+ 2
+ 0
+
+
+ 17
+ 3.5
+ 0
+ -0.03
+ 0.624
+ 2
+ 2
+ -0.02
+
+
+ 16
+ 0
+ 0
+ 0
+ 0.694
+ 2
+ 2
+ -0.03
+
+
+ 17
+ -3.5
+ 0
+ 0.03
+ 0.624
+ 2
+ 2
+ -0.02
+
+
+ 1
+ Fuck
+ 0
+ 0
+ 0
+ 0.554
+ 2
+ 2
+ 0
+
+
+
+
+ 33
+ 0
+ 0
+ 0
+ 0.554
+ 2
+ 2
+ 0
+
+
+ 33
+ 0
+ 0
+ 0
+ 0.694
+ 2
+ 2
+ -0.03
+
+
+ 1
+ Fuck
+ 0
+ 0
+ 0
+ 0.554
+ 2
+ 2
+ 0
+
+
+
+ 33
+ 0
+ 0
+ 0
+ 0.554
+ 2
+ 2
+ 0
+
+
+ 33
+ 0
+ 0
+ 0
+ 0.694
+ 2
+ 2
+ -0.03
+
+
+ 1
+ Fuck
+ 0
+ 0
+ 0
+ 0.554
+ 2
+ 2
+ 0
+
+
+
+
+ LayingPawn
+
+
+ 16
+ 180
+ 180
+ 0
+ -0.363
+ 2
+ 2
+ 0
+ 0
+
+
+ 17
+ 180
+ 180
+ 0
+ -0.347
+ 2
+ 2
+ 0.015
+ -15
+
+
+ 16
+ 180
+ 180
+ 0
+ -0.331
+ 2
+ 2
+ 0.03
+ 0
+
+
+ 17
+ 180
+ 180
+ 0
+ -0.315
+ 2
+ 2
+ 0.045
+ 15
+
+
+ 1
+ 180
+ 180
+ 0
+ -0.363
+ 2
+ 2
+ 0
+ 0
+
+
+ 16
+ 180
+ 180
+ 0
+ -0.363
+ 2
+ 2
+ 0
+ 0
+
+
+ 17
+ 180
+ 180
+ 0
+ -0.347
+ 2
+ 2
+ 0.015
+ -15
+
+
+ 16
+ 180
+ 180
+ 0
+ -0.331
+ 2
+ 2
+ 0.03
+ 0
+
+
+ 17
+ 180
+ 180
+ 0
+ -0.315
+ 2
+ 2
+ 0.045
+ 15
+
+
+ 1
+ 180
+ 180
+ 0
+ -0.363
+ 2
+ 2
+ 0
+ 0
+
+
+ 33
+ 180
+ 180
+ 0
+ -0.363
+ 2
+ 2
+ 0
+ 0
+
+
+ 33
+ 180
+ 180
+ 0
+ -0.315
+ 2
+ 2
+ 0.045
+ 0
+
+
+ 1
+ 180
+ 180
+ 0
+ -0.363
+ 2
+ 2
+ 0
+ 0
+
+
+ 33
+ 180
+ 180
+ 0
+ -0.363
+ 2
+ 2
+ 0
+ 0
+
+
+ 33
+ 180
+ 180
+ 0
+ -0.315
+ 2
+ 2
+ 0.045
+ 0
+
+
+ 1
+ 180
+ 180
+ 0
+ -0.363
+ 2
+ 2
+ 0
+ 0
+
+
+
+
+
+
+ Fast_Fuck
+ true
+ 780
+ 0
+
+
+
+
+ 13
+ 0
+ 0
+ 0
+ 0.554
+ 2
+ 2
+ 0
+
+
+ 13
+ 0
+ 0
+ 0
+ 0.694
+ 2
+ 2
+ -0.03
+
+
+ 1
+ Fuck
+ 0
+ 0
+ 0
+ 0.554
+ 2
+ 2
+ 0
+
+
+
+
+ LayingPawn
+
+
+ 13
+ 180
+ 180
+ 0
+ -0.363
+ 2
+ 2
+ 0
+ 0
+
+
+ 13
+ 180
+ 180
+ 0
+ -0.313
+ 2
+ 2
+ 0.045
+ 0
+
+
+ 1
+ 180
+ 180
+ 0
+ -0.363
+ 2
+ 2
+ 0
+ 0
+
+
+
+
+
+
+ Cum
+ true
+ 594
+ 0
+
+
+
+
+ 10
+ 0
+ 0
+ 0
+ 0.554
+ 2
+ 2
+ 0
+
+
+ 10
+ 0
+ 0
+ 0
+ 0.694
+ 2
+ 2
+ -0.03
+
+
+ 1
+ Fuck
+ 0
+ 0
+ 0
+ 0.554
+ 2
+ 2
+ 0
+
+
+
+ 10
+ 0
+ 0
+ 0
+ 0.554
+ 2
+ 2
+ 0
+
+
+ 10
+ 0
+ 0
+ 0
+ 0.694
+ 2
+ 2
+ -0.03
+
+
+ 1
+ Fuck
+ 0
+ 0
+ 0
+ 0.554
+ 2
+ 2
+ 0
+
+
+
+ 10
+ 0
+ 0
+ 0
+ 0.554
+ 2
+ 2
+ 0
+
+
+ 10
+ 0
+ 0
+ 0
+ 0.694
+ 2
+ 2
+ -0.03
+
+
+ true
+ 45
+ Cum
+ 0
+ 0
+ 0
+ 0.554
+ 2
+ 2
+ 0
+
+
+ true
+ 40
+ 0
+ 0
+ 0
+ 0.534
+ 2
+ 2
+ 0
+
+
+ 1
+ 0
+ 0
+ 0
+ 0.554
+ 2
+ 2
+ 0
+
+
+
+
+ LayingPawn
+
+
+ 10
+ 180
+ 180
+ 0
+ -0.363
+ 2
+ 2
+ 0
+ 0
+
+
+ 10
+ 180
+ 180
+ 0
+ -0.313
+ 2
+ 2
+ 0.045
+
+
+ 1
+ 180
+ 180
+ 0
+ -0.363
+ 2
+ 2
+ 0
+
+
+
+ 10
+ 180
+ 180
+ 0
+ -0.363
+ 2
+ 2
+ 0
+
+
+ 10
+ 180
+ 180
+ 0
+ -0.313
+ 2
+ 2
+ 0.045
+
+
+ 1
+ 180
+ 180
+ 0
+ -0.363
+ 2
+ 2
+ 0
+
+
+
+ 10
+ 180
+ 180
+ 0
+ -0.363
+ 2
+ 2
+ 0
+
+
+ 10
+ 180
+ 180
+ 0
+ -0.313
+ 2
+ 2
+ 0.045
+
+
+ 45
+ 180
+ 180
+ 0
+ -0.363
+ 2
+ 2
+ 0
+
+
+ 40
+ 180
+ 180
+ 0
+ -0.363
+ 2
+ 2
+ 0
+
+
+ 1
+ 180
+ 180
+ 0
+ -0.363
+ 2
+ 2
+ 0
+ 0
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/1.3/Defs/AnimationDefs/TemplateAnimation.xml b/1.3/Defs/AnimationDefs/TemplateAnimation.xml
new file mode 100644
index 0000000..0305903
--- /dev/null
+++ b/1.3/Defs/AnimationDefs/TemplateAnimation.xml
@@ -0,0 +1,54 @@
+
+
+
+
diff --git a/1.3/Defs/MainTabDefs/MainButtonDef.xml b/1.3/Defs/MainTabDefs/MainButtonDef.xml
new file mode 100644
index 0000000..0674d24
--- /dev/null
+++ b/1.3/Defs/MainTabDefs/MainButtonDef.xml
@@ -0,0 +1,15 @@
+
+
+
+
+ OffsetManager
+ offset manager
+ Control pawn offsets
+ Rimworld_Animations.MainTabWindow_OffsetConfigure
+ 54
+ false
+ UI/MainTab
+ true
+
+
+
\ No newline at end of file
diff --git a/1.3/Defs/SoundDefs/Sounds_Sex.xml b/1.3/Defs/SoundDefs/Sounds_Sex.xml
new file mode 100644
index 0000000..4cce5d0
--- /dev/null
+++ b/1.3/Defs/SoundDefs/Sounds_Sex.xml
@@ -0,0 +1,212 @@
+
+
+
+
+ Cum
+ MapOnly
+
+ 1
+ 1
+
+
+
+
+ Sex/cum
+
+
+
+ 30
+ 40
+
+
+ 0.8
+ 1.2
+
+
+ 0
+ 51.86047
+
+ False
+
+
+
+
+ Sex
+ MapOnly
+
+ 1
+ 1
+
+
+
+
+ Sex/kucyu04
+
+
+
+ 16
+ 16
+
+
+ 0.8
+ 1.2
+
+
+ 0
+ 51.86047
+
+ False
+
+
+
+
+ Suck
+ MapOnly
+
+ 1
+ 1
+
+
+
+
+ Sex/Suck/Suck_1
+
+
+ Sex/Suck/Suck_2
+
+
+ Sex/Suck/Suck_3
+
+
+ Sex/Suck/Suck_4
+
+
+ Sex/Suck/Suck_5
+
+
+ Sex/Suck/Suck_6
+
+
+ Sex/Suck/Suck_7
+
+
+ Sex/Suck/Suck_8
+
+
+ Sex/Suck/Suck_9
+
+
+ Sex/Suck/Suck_10
+
+
+
+ 20
+ 35
+
+
+ 1.0
+ 1.0
+
+
+ 0
+ 51.86047
+
+ NeverTwice
+ false
+
+
+
+
+ Fuck
+ MapOnly
+
+ 1
+ 1
+
+
+
+
+ Sex/Clap_1
+
+
+ Sex/Clap_2
+
+
+ Sex/Clap_3
+
+
+ Sex/Clap_4
+
+
+ Sex/Clap_5
+
+
+ Sex/Clap_6
+
+
+ Sex/Clap_7
+
+
+ Sex/Clap_8
+
+
+
+ 45
+ 70
+
+
+ 1.0
+ 1.0
+
+
+ 0
+ 51.86047
+
+ NeverTwice
+ false
+
+
+
+
+ Slimy
+ MapOnly
+
+ 1
+ 1
+
+
+
+
+ Sex/Slime/Slimy1
+
+
+ Sex/Slime/Slimy2
+
+
+ Sex/Slime/Slimy3
+
+
+ Sex/Slime/Slimy4
+
+
+ Sex/Slime/Slimy5
+
+
+
+ 45
+ 75
+
+
+ 1.4
+ 1.8
+
+
+ 0
+ 100
+
+ NeverTwice
+ false
+
+
+
+
\ No newline at end of file
diff --git a/1.3/Patch_HatsDisplaySelection/Patch_HatsDisplaySelection.csproj b/1.3/Patch_HatsDisplaySelection/Patch_HatsDisplaySelection.csproj
new file mode 100644
index 0000000..8da21a6
--- /dev/null
+++ b/1.3/Patch_HatsDisplaySelection/Patch_HatsDisplaySelection.csproj
@@ -0,0 +1,75 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {BA766964-1716-422D-A09E-29426F8EB9D5}
+ Library
+ Properties
+ Patch_HatsDisplaySelection
+ Patch_HatsDisplaySelection
+ v4.7.2
+ 512
+ true
+
+
+ false
+ none
+ false
+ 1.2\Assemblies\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\..\..\..\..\workshop\content\294100\2009463077\Current\Assemblies\0Harmony.dll
+ False
+
+
+ ..\..\..\RimWorldWin64_Data\Managed\Assembly-CSharp.dll
+ False
+
+
+ ..\..\..\..\..\workshop\content\294100\1542291825\1.2\Assemblies\HatDisplaySelection.dll
+ False
+
+
+ ..\1.2\Assemblies\Rimworld-Animations.dll
+ False
+
+
+
+
+
+
+
+
+
+
+ ..\..\..\RimWorldWin64_Data\Managed\UnityEngine.dll
+ False
+
+
+ ..\..\..\RimWorldWin64_Data\Managed\UnityEngine.CoreModule.dll
+ False
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/1.3/Patches/AnimationPatchHSK.xml b/1.3/Patches/AnimationPatchHSK.xml
new file mode 100644
index 0000000..74038ea
--- /dev/null
+++ b/1.3/Patches/AnimationPatchHSK.xml
@@ -0,0 +1,31 @@
+
+
+
+
+ Core SK
+
+
+
+
+
+ Defs/ThingDef/comps
+ Always
+
+ Defs/ThingDef
+
+
+
+
+
+
+
+ Defs/ThingDef[@Name="BaseAnimalPawn" or @Name="SK_BasePawn" or @Name="BasePawnSkynet"]/comps
+
+
+
+
+
+
+
+
+
diff --git a/1.3/Patches/AnimationPatch_CompBodyAnimator.xml b/1.3/Patches/AnimationPatch_CompBodyAnimator.xml
new file mode 100644
index 0000000..e645747
--- /dev/null
+++ b/1.3/Patches/AnimationPatch_CompBodyAnimator.xml
@@ -0,0 +1,35 @@
+
+
+
+ Always
+
+
+ Always
+ Defs/ThingDef[race][not(comps)]
+
+
+
+
+
+ Always
+ Defs/AlienRace.ThingDef_AlienRace[not(comps)]
+
+
+
+
+
+
+ Defs/ThingDef[@Name="BasePawn"]/comps
+
+
+
+
+
+ Defs/AlienRace.ThingDef_AlienRace/comps
+
+
+
+
+
+
+
diff --git a/1.3/Patches/CompPatches/AutoCleaner.xml b/1.3/Patches/CompPatches/AutoCleaner.xml
new file mode 100644
index 0000000..c2ad860
--- /dev/null
+++ b/1.3/Patches/CompPatches/AutoCleaner.xml
@@ -0,0 +1,19 @@
+
+
+
+ Always
+
+
+ /Defs/ThingDef[@Name="BaseBaseAutocleaner"]/comps
+ Always
+
+ /Defs/ThingDef[@Name="BaseBaseAutocleaner"]/comps
+
+
+
+
+
+
+
+
+
diff --git a/1.3/Patches/CompPatches/CombatExtended.xml b/1.3/Patches/CompPatches/CombatExtended.xml
new file mode 100644
index 0000000..7d35127
--- /dev/null
+++ b/1.3/Patches/CompPatches/CombatExtended.xml
@@ -0,0 +1,18 @@
+
+
+
+ Always
+
+
+ /Defs/ThingDef[@Name="BasePawnSimple"]/comps
+ Always
+
+ /Defs/ThingDef[@Name="BasePawnSimple"]/comps
+
+
+
+
+
+
+
+
diff --git a/1.3/Patches/CompPatches/ZombieLand.xml b/1.3/Patches/CompPatches/ZombieLand.xml
new file mode 100644
index 0000000..e950e0e
--- /dev/null
+++ b/1.3/Patches/CompPatches/ZombieLand.xml
@@ -0,0 +1,18 @@
+
+
+
+ Always
+
+
+ /Defs/ThingDef[@Name="BaseZombie"]/comps
+ Always
+
+ /Defs/ThingDef[@Name="BaseZombie"]/comps
+
+
+
+
+
+
+
+
diff --git a/1.3/Patches/CompatibilityPatch_FacialAnimation.xml b/1.3/Patches/CompatibilityPatch_FacialAnimation.xml
new file mode 100644
index 0000000..125d79f
--- /dev/null
+++ b/1.3/Patches/CompatibilityPatch_FacialAnimation.xml
@@ -0,0 +1,130 @@
+
+
+
+
+ [NL] Facial Animation - WIP
+
+
+ Always
+
+
+ /Defs/FacialAnimation.FaceAnimationDef[defName="Lovin" or defName="Lovin2"]/targetJobs
+ Always
+
+ RJW_Masturbate
+ GettinBred
+ Bestiality
+ BestialityForFemale
+ ViolateCorpse
+ Quickie
+ GettingQuickie
+ GettinRaped
+ JoinInBed
+ GettinLoved
+ GettinLicked
+ GettinSucked
+ WhoreIsServingVisitors
+ JoinInBedAnimation
+ GettinLovedAnimation
+
+
+
+ /Defs/FacialAnimation.FaceAnimationDef[defName="WaitCombat" or defName="Wait_Combat_Rare"]/targetJobs
+ Always
+
+ RapeComfortPawn
+ RandomRape
+ RapeEnemy
+
+
+
+ /Defs/FacialAnimation.FaceAnimationDef[defName="StandAndBeSociallyActive"]/targetJobs
+ Always
+
+ WhoreInvitingVisitors
+
+
+
+ /Defs/FacialAnimation.FaceAnimationDef[defName="Wear" or defName="Wear2" or defName="Wear3"]/targetJobs
+ Always
+
+ CleanSelf
+ StruggleInBondageGear
+
+
+
+
+ Rimworld-Animations
+
+
+ Always
+
+
+ /Defs/FacialAnimation.FaceAnimationDef[defName="Lovin" or defName="Lovin2"]/animationFrames/li[1]/headOffset
+ Always
+
+
+ /Defs/FacialAnimation.FaceAnimationDef[defName="Lovin"]/animationFrames/li[2]/headOffset
+ Always
+
+
+ /Defs/FacialAnimation.FaceAnimationDef[defName="Lovin"]/animationFrames/li[3]/headOffset
+ Always
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/1.3/Patches/CompatibilityPatch_HCSK.xml b/1.3/Patches/CompatibilityPatch_HCSK.xml
new file mode 100644
index 0000000..ead8783
--- /dev/null
+++ b/1.3/Patches/CompatibilityPatch_HCSK.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+ Core SK
+
+
+ Always
+
+
+ /Defs/ThingDef/comps
+ Always
+
+ /Defs/ThingDef
+
+
+
+
+
+
+
+ /Defs/ThingDef[@Name="SK_BasePawn"]/comps
+
+
+
+
+
+
+ /Defs/ThingDef[@Name="BaseAnimalPawn"]/comps
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/1.3/Patches/RacePatches/Epona race Renaissance.xml b/1.3/Patches/RacePatches/Epona race Renaissance.xml
new file mode 100644
index 0000000..f39b509
--- /dev/null
+++ b/1.3/Patches/RacePatches/Epona race Renaissance.xml
@@ -0,0 +1,19 @@
+
+
+
+
+ Epona race Renaissance
+
+
+
+
+ /Defs/AlienRace.ThingDef_AlienRace[defName = "Alien_Epona"]/alienRace/generalSettings/alienPartGenerator/bodyAddons/li[hediffGraphics/Epona_OHPG_female="Things/Pawn/Addons/Breasts/Breasts"]/drawnInBed
+
+ false
+
+
+
+
+
+
+
diff --git a/1.3/Patches/RacePatches/Nyaron.xml b/1.3/Patches/RacePatches/Nyaron.xml
new file mode 100644
index 0000000..0a7a08e
--- /dev/null
+++ b/1.3/Patches/RacePatches/Nyaron.xml
@@ -0,0 +1,19 @@
+
+
+
+
+ Nyaron race
+
+
+
+
+ /Defs/AlienRace.ThingDef_AlienRace[defName = "Alien_Nyaron"]/alienRace/generalSettings/alienPartGenerator/bodyAddons/li[bodyPart="tail"]
+
+ false
+
+
+
+
+
+
+
diff --git a/1.3/Sounds/Sex/Clap_1.wav b/1.3/Sounds/Sex/Clap_1.wav
new file mode 100644
index 0000000..bccd0f2
Binary files /dev/null and b/1.3/Sounds/Sex/Clap_1.wav differ
diff --git a/1.3/Sounds/Sex/Clap_2.wav b/1.3/Sounds/Sex/Clap_2.wav
new file mode 100644
index 0000000..a382f59
Binary files /dev/null and b/1.3/Sounds/Sex/Clap_2.wav differ
diff --git a/1.3/Sounds/Sex/Clap_3.wav b/1.3/Sounds/Sex/Clap_3.wav
new file mode 100644
index 0000000..65cf39b
Binary files /dev/null and b/1.3/Sounds/Sex/Clap_3.wav differ
diff --git a/1.3/Sounds/Sex/Clap_4.wav b/1.3/Sounds/Sex/Clap_4.wav
new file mode 100644
index 0000000..3ae1b3e
Binary files /dev/null and b/1.3/Sounds/Sex/Clap_4.wav differ
diff --git a/1.3/Sounds/Sex/Clap_5.wav b/1.3/Sounds/Sex/Clap_5.wav
new file mode 100644
index 0000000..65144e7
Binary files /dev/null and b/1.3/Sounds/Sex/Clap_5.wav differ
diff --git a/1.3/Sounds/Sex/Clap_6.wav b/1.3/Sounds/Sex/Clap_6.wav
new file mode 100644
index 0000000..0026325
Binary files /dev/null and b/1.3/Sounds/Sex/Clap_6.wav differ
diff --git a/1.3/Sounds/Sex/Clap_7.wav b/1.3/Sounds/Sex/Clap_7.wav
new file mode 100644
index 0000000..6d7de2a
Binary files /dev/null and b/1.3/Sounds/Sex/Clap_7.wav differ
diff --git a/1.3/Sounds/Sex/Clap_8.wav b/1.3/Sounds/Sex/Clap_8.wav
new file mode 100644
index 0000000..1af5710
Binary files /dev/null and b/1.3/Sounds/Sex/Clap_8.wav differ
diff --git a/1.3/Sounds/Sex/Slime/Slimy1.wav b/1.3/Sounds/Sex/Slime/Slimy1.wav
new file mode 100644
index 0000000..3cfbd74
Binary files /dev/null and b/1.3/Sounds/Sex/Slime/Slimy1.wav differ
diff --git a/1.3/Sounds/Sex/Slime/Slimy2.wav b/1.3/Sounds/Sex/Slime/Slimy2.wav
new file mode 100644
index 0000000..36a9197
Binary files /dev/null and b/1.3/Sounds/Sex/Slime/Slimy2.wav differ
diff --git a/1.3/Sounds/Sex/Slime/Slimy3.wav b/1.3/Sounds/Sex/Slime/Slimy3.wav
new file mode 100644
index 0000000..40aff1e
Binary files /dev/null and b/1.3/Sounds/Sex/Slime/Slimy3.wav differ
diff --git a/1.3/Sounds/Sex/Slime/Slimy4.wav b/1.3/Sounds/Sex/Slime/Slimy4.wav
new file mode 100644
index 0000000..0b6404e
Binary files /dev/null and b/1.3/Sounds/Sex/Slime/Slimy4.wav differ
diff --git a/1.3/Sounds/Sex/Slime/Slimy5.wav b/1.3/Sounds/Sex/Slime/Slimy5.wav
new file mode 100644
index 0000000..ea310db
Binary files /dev/null and b/1.3/Sounds/Sex/Slime/Slimy5.wav differ
diff --git a/1.3/Sounds/Sex/Suck/Suck_1.wav b/1.3/Sounds/Sex/Suck/Suck_1.wav
new file mode 100644
index 0000000..4f1eafd
Binary files /dev/null and b/1.3/Sounds/Sex/Suck/Suck_1.wav differ
diff --git a/1.3/Sounds/Sex/Suck/Suck_10.wav b/1.3/Sounds/Sex/Suck/Suck_10.wav
new file mode 100644
index 0000000..284cda3
Binary files /dev/null and b/1.3/Sounds/Sex/Suck/Suck_10.wav differ
diff --git a/1.3/Sounds/Sex/Suck/Suck_3.wav b/1.3/Sounds/Sex/Suck/Suck_3.wav
new file mode 100644
index 0000000..95e7348
Binary files /dev/null and b/1.3/Sounds/Sex/Suck/Suck_3.wav differ
diff --git a/1.3/Sounds/Sex/Suck/Suck_4.wav b/1.3/Sounds/Sex/Suck/Suck_4.wav
new file mode 100644
index 0000000..753a023
Binary files /dev/null and b/1.3/Sounds/Sex/Suck/Suck_4.wav differ
diff --git a/1.3/Sounds/Sex/Suck/Suck_5.wav b/1.3/Sounds/Sex/Suck/Suck_5.wav
new file mode 100644
index 0000000..8ecda9c
Binary files /dev/null and b/1.3/Sounds/Sex/Suck/Suck_5.wav differ
diff --git a/1.3/Sounds/Sex/Suck/Suck_6.wav b/1.3/Sounds/Sex/Suck/Suck_6.wav
new file mode 100644
index 0000000..08567d6
Binary files /dev/null and b/1.3/Sounds/Sex/Suck/Suck_6.wav differ
diff --git a/1.3/Sounds/Sex/Suck/Suck_7.wav b/1.3/Sounds/Sex/Suck/Suck_7.wav
new file mode 100644
index 0000000..a63b0e4
Binary files /dev/null and b/1.3/Sounds/Sex/Suck/Suck_7.wav differ
diff --git a/1.3/Sounds/Sex/Suck/Suck_8.wav b/1.3/Sounds/Sex/Suck/Suck_8.wav
new file mode 100644
index 0000000..320da09
Binary files /dev/null and b/1.3/Sounds/Sex/Suck/Suck_8.wav differ
diff --git a/1.3/Sounds/Sex/Suck/Suck_9.wav b/1.3/Sounds/Sex/Suck/Suck_9.wav
new file mode 100644
index 0000000..7ab538a
Binary files /dev/null and b/1.3/Sounds/Sex/Suck/Suck_9.wav differ
diff --git a/1.3/Sounds/Sex/Suck/Swallow_1.wav b/1.3/Sounds/Sex/Suck/Swallow_1.wav
new file mode 100644
index 0000000..f3276cc
Binary files /dev/null and b/1.3/Sounds/Sex/Suck/Swallow_1.wav differ
diff --git a/1.3/Sounds/Sex/Suck/Swallow_2.wav b/1.3/Sounds/Sex/Suck/Swallow_2.wav
new file mode 100644
index 0000000..09a7a00
Binary files /dev/null and b/1.3/Sounds/Sex/Suck/Swallow_2.wav differ
diff --git a/1.3/Sounds/Sex/Suck/Swallow_3.wav b/1.3/Sounds/Sex/Suck/Swallow_3.wav
new file mode 100644
index 0000000..2817b29
Binary files /dev/null and b/1.3/Sounds/Sex/Suck/Swallow_3.wav differ
diff --git a/1.3/Sounds/Sex/Suck/suck_2.wav b/1.3/Sounds/Sex/Suck/suck_2.wav
new file mode 100644
index 0000000..a8305c1
Binary files /dev/null and b/1.3/Sounds/Sex/Suck/suck_2.wav differ
diff --git a/1.3/Sounds/Sex/cum.wav b/1.3/Sounds/Sex/cum.wav
new file mode 100644
index 0000000..ef98437
Binary files /dev/null and b/1.3/Sounds/Sex/cum.wav differ
diff --git a/1.3/Sounds/Sex/kucyu04.wav b/1.3/Sounds/Sex/kucyu04.wav
new file mode 100644
index 0000000..3ae1ce8
Binary files /dev/null and b/1.3/Sounds/Sex/kucyu04.wav differ
diff --git a/Source/Actors/Actor.cs b/1.3/Source/Actors/Actor.cs
similarity index 89%
rename from Source/Actors/Actor.cs
rename to 1.3/Source/Actors/Actor.cs
index 55e4f79..3b382dd 100644
--- a/Source/Actors/Actor.cs
+++ b/1.3/Source/Actors/Actor.cs
@@ -20,6 +20,7 @@ namespace Rimworld_Animations {
public List bodyDefTypes = new List();
public BodyTypeOffset bodyTypeOffset = new BodyTypeOffset();
public Vector3 offset = new Vector2(0, 0);
-
+ public List requiredGender;
+ public List tags = new List();
}
}
diff --git a/Source/Actors/AlienRaceOffset.cs b/1.3/Source/Actors/AlienRaceOffset.cs
similarity index 100%
rename from Source/Actors/AlienRaceOffset.cs
rename to 1.3/Source/Actors/AlienRaceOffset.cs
diff --git a/Source/Actors/BodyTypeOffset.cs b/1.3/Source/Actors/BodyTypeOffset.cs
similarity index 100%
rename from Source/Actors/BodyTypeOffset.cs
rename to 1.3/Source/Actors/BodyTypeOffset.cs
diff --git a/Source/Animations/AnimationStage.cs b/1.3/Source/Animations/AnimationStage.cs
similarity index 88%
rename from Source/Animations/AnimationStage.cs
rename to 1.3/Source/Animations/AnimationStage.cs
index 475c079..7a1304e 100644
--- a/Source/Animations/AnimationStage.cs
+++ b/1.3/Source/Animations/AnimationStage.cs
@@ -10,9 +10,10 @@ namespace Rimworld_Animations {
public string stageName;
public int stageIndex;
public int playTimeTicks = 0;
+ public int playTimeTicksQuick = -1;
public bool isLooping;
public List animationClips;
-
+ public List tags = new List();
public void initialize() {
foreach (BaseAnimationClip clip in animationClips) {
diff --git a/Source/Animations/Clips/BaseAnimationClip.cs b/1.3/Source/Animations/Clips/BaseAnimationClip.cs
similarity index 76%
rename from Source/Animations/Clips/BaseAnimationClip.cs
rename to 1.3/Source/Animations/Clips/BaseAnimationClip.cs
index 1aaf03f..aa35b31 100644
--- a/Source/Animations/Clips/BaseAnimationClip.cs
+++ b/1.3/Source/Animations/Clips/BaseAnimationClip.cs
@@ -9,11 +9,12 @@ using Verse;
namespace Rimworld_Animations {
public abstract class BaseAnimationClip
{
+ public Dictionary SoundEffects = new Dictionary();
public List types; //types of participants
public int duration;
public abstract void buildSimpleCurves();
public string soundDef = null; //for playing sounds
public int actor;
-
+ public List tags = new List();
}
}
diff --git a/Source/Animations/Clips/PawnAnimationClip.cs b/1.3/Source/Animations/Clips/PawnAnimationClip.cs
similarity index 98%
rename from Source/Animations/Clips/PawnAnimationClip.cs
rename to 1.3/Source/Animations/Clips/PawnAnimationClip.cs
index 746c3f4..e9d2489 100644
--- a/Source/Animations/Clips/PawnAnimationClip.cs
+++ b/1.3/Source/Animations/Clips/PawnAnimationClip.cs
@@ -12,7 +12,6 @@ namespace Rimworld_Animations {
public List keyframes;
public AltitudeLayer layer = AltitudeLayer.Pawn;
- public Dictionary SoundEffects = new Dictionary();
public Dictionary quiver = new Dictionary();
public SimpleCurve GenitalAngle = new SimpleCurve();
public SimpleCurve BodyAngle = new SimpleCurve();
diff --git a/1.3/Source/Animations/Clips/ThingAnimationClip.cs b/1.3/Source/Animations/Clips/ThingAnimationClip.cs
new file mode 100644
index 0000000..26f4d4c
--- /dev/null
+++ b/1.3/Source/Animations/Clips/ThingAnimationClip.cs
@@ -0,0 +1,74 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Verse;
+using RimWorld;
+
+namespace Rimworld_Animations {
+ public class ThingAnimationClip : BaseAnimationClip
+ {
+ public List keyframes;
+
+ public SimpleCurve PositionX = new SimpleCurve();
+ public SimpleCurve PositionZ = new SimpleCurve();
+ public SimpleCurve Rotation = new SimpleCurve();
+
+
+ public override void buildSimpleCurves() {
+ int duration = 0;
+ //getting the length of the whole clip
+ foreach (ThingKeyframe frame in keyframes)
+ {
+ duration += frame.tickDuration;
+ }
+
+ //guarantees loops don't get cut off mid-anim
+ this.duration = duration;
+
+ int keyframePosition = 0;
+ foreach (ThingKeyframe frame in keyframes)
+ {
+
+ if (frame.atTick.HasValue)
+ {
+ if (frame.positionX.HasValue)
+ PositionX.Add((float)frame.atTick / (float)duration, frame.positionX.Value, true);
+
+ if (frame.positionZ.HasValue)
+ PositionZ.Add((float)frame.atTick / (float)duration, frame.positionZ.Value, true);
+
+ if (frame.rotation.HasValue)
+ Rotation.Add((float)frame.atTick / (float)duration, frame.rotation.Value, true);
+
+ if (frame.soundEffect != null)
+ {
+ SoundEffects.Add((int)frame.atTick, frame.soundEffect);
+ }
+
+
+ }
+ else
+ {
+ if (frame.positionX.HasValue)
+ PositionX.Add((float)keyframePosition / (float)duration, frame.positionX.Value, true);
+
+ if (frame.positionZ.HasValue)
+ PositionZ.Add((float)keyframePosition / (float)duration, frame.positionZ.Value, true);
+
+ if (frame.rotation.HasValue)
+ Rotation.Add((float)keyframePosition / (float)duration, frame.rotation.Value, true);
+
+ if (frame.soundEffect != null)
+ {
+ SoundEffects.Add(keyframePosition, frame.soundEffect);
+ }
+ keyframePosition += frame.tickDuration;
+
+ }
+
+ }
+ }
+ }
+}
diff --git a/Source/Animations/Keyframes/Keyframe.cs b/1.3/Source/Animations/Keyframes/Keyframe.cs
similarity index 66%
rename from Source/Animations/Keyframes/Keyframe.cs
rename to 1.3/Source/Animations/Keyframes/Keyframe.cs
index 8b49841..8cd859d 100644
--- a/Source/Animations/Keyframes/Keyframe.cs
+++ b/1.3/Source/Animations/Keyframes/Keyframe.cs
@@ -8,7 +8,8 @@ namespace Rimworld_Animations {
public abstract class Keyframe
{
public int tickDuration = 1;
-
-
+ public float? atTick;
+ public string soundEffect;
+ public List tags = new List();
}
}
diff --git a/Source/Animations/Keyframes/PawnKeyframe.cs b/1.3/Source/Animations/Keyframes/PawnKeyframe.cs
similarity index 89%
rename from Source/Animations/Keyframes/PawnKeyframe.cs
rename to 1.3/Source/Animations/Keyframes/PawnKeyframe.cs
index 685009e..e710981 100644
--- a/Source/Animations/Keyframes/PawnKeyframe.cs
+++ b/1.3/Source/Animations/Keyframes/PawnKeyframe.cs
@@ -22,9 +22,7 @@ namespace Rimworld_Animations {
public int? bodyFacing;
public int? headFacing;
- public string soundEffect;
public bool? quiver;
- public float? atTick;
}
}
diff --git a/Source/Animations/Keyframes/ThingKeyframe.cs b/1.3/Source/Animations/Keyframes/ThingKeyframe.cs
similarity index 67%
rename from Source/Animations/Keyframes/ThingKeyframe.cs
rename to 1.3/Source/Animations/Keyframes/ThingKeyframe.cs
index 9d35a96..6604f5e 100644
--- a/Source/Animations/Keyframes/ThingKeyframe.cs
+++ b/1.3/Source/Animations/Keyframes/ThingKeyframe.cs
@@ -7,5 +7,12 @@ using System.Threading.Tasks;
namespace Rimworld_Animations {
public class ThingKeyframe : Keyframe
{
+
+ public float? positionX;
+ public float? positionZ;
+ public float? rotation;
+
+
+
}
}
diff --git a/Source/Comps/CompBodyAnimator.cs b/1.3/Source/Comps/CompBodyAnimator.cs
similarity index 56%
rename from Source/Comps/CompBodyAnimator.cs
rename to 1.3/Source/Comps/CompBodyAnimator.cs
index 33bd110..7910f7d 100644
--- a/Source/Comps/CompBodyAnimator.cs
+++ b/1.3/Source/Comps/CompBodyAnimator.cs
@@ -11,12 +11,12 @@ using Verse;
using Verse.Sound;
namespace Rimworld_Animations {
- class CompBodyAnimator : ThingComp
+ public class CompBodyAnimator : ThingComp
{
public Pawn pawn => base.parent as Pawn;
public PawnGraphicSet Graphics;
-
- public CompProperties_BodyAnimator Props => (CompProperties_BodyAnimator)(object)base.props;
+
+ //public CompProperties_BodyAnimator Props => (CompProperties_BodyAnimator)(object)base.props;
public bool isAnimating {
get {
@@ -25,10 +25,11 @@ namespace Rimworld_Animations {
set {
Animating = value;
- if(value == true) {
+ if (value == true) {
SexUtility.DrawNude(pawn);
} else {
pawn.Drawer.renderer.graphics.ResolveAllGraphics();
+ actorsInCurrentAnimation = null;
}
PortraitsCache.SetDirty(pawn);
@@ -48,10 +49,19 @@ namespace Rimworld_Animations {
public float bodyAngle = 0, headAngle = 0, genitalAngle = 0;
public Rot4 headFacing = Rot4.North, bodyFacing = Rot4.North;
+ public List actorsInCurrentAnimation;
+
public bool controlGenitalAngle = false;
+ public bool fastAnimForQuickie = false;
private AnimationDef anim;
- private AnimationStage stage => anim.animationStages[curStage];
+ private AnimationStage stage {
+ get
+ {
+ return anim.animationStages[curStage];
+ }
+
+ }
private PawnAnimationClip clip => (PawnAnimationClip)stage.animationClips[actor];
public bool Mirror {
@@ -102,8 +112,14 @@ namespace Rimworld_Animations {
anchor = thing.Position.ToVector3Shifted();
}
}
- public void StartAnimation(AnimationDef anim, int actor, bool mirror = false, bool shiver = false, bool fastAnimForQuickie = false) {
+ public void StartAnimation(AnimationDef anim, List actors, int actor, bool mirror = false, bool shiver = false, bool fastAnimForQuickie = false) {
+ actorsInCurrentAnimation = actors;
+
+ if (anim.actors.Count <= actor)
+ {
+ return;
+ }
AlienRaceOffset raceOffset = anim?.actors[actor]?.raceOffsets?.Find(x => x.defName == pawn.def.defName);
if (raceOffset != null) {
@@ -140,9 +156,18 @@ namespace Rimworld_Animations {
this.actor = actor;
this.anim = anim;
this.mirror = mirror;
+ this.fastAnimForQuickie = fastAnimForQuickie;
- curStage = fastAnimForQuickie ? 1 : 0;
- animTicks = 0;
+ if (fastAnimForQuickie && anim.animationStages.Any(x => x.playTimeTicksQuick >= 0) == false)
+ {
+ curStage = 1;
+ animTicks = anim.animationStages[0].playTimeTicks;
+ } else
+ {
+ curStage = 0;
+ animTicks = 0;
+ }
+
stageTicks = 0;
clipTicks = 0;
@@ -155,14 +180,16 @@ namespace Rimworld_Animations {
//tick once for initialization
tickAnim();
-
-
}
+
public override void CompTick() {
base.CompTick();
if(isAnimating) {
+
+ GlobalTextureAtlasManager.TryMarkPawnFrameSetDirty(pawn);
+
if (pawn.Dead || pawn?.jobs?.curDriver == null || (pawn?.jobs?.curDriver != null && !(pawn?.jobs?.curDriver is rjw.JobDriver_Sex))) {
isAnimating = false;
}
@@ -171,7 +198,7 @@ namespace Rimworld_Animations {
}
}
}
- public void animatePawn(ref Vector3 rootLoc, ref float angle, ref Rot4 bodyFacing, ref Rot4 headFacing) {
+ public void animatePawnBody(ref Vector3 rootLoc, ref float angle, ref Rot4 bodyFacing) {
if(!isAnimating) {
return;
@@ -179,35 +206,63 @@ namespace Rimworld_Animations {
rootLoc = anchor + deltaPos;
angle = bodyAngle;
bodyFacing = this.bodyFacing;
- headFacing = this.headFacing;
-
-
-
}
+ public Rot4 AnimateHeadFacing()
+ {
+ return this.headFacing;
+ }
+
+
public void tickGraphics(PawnGraphicSet graphics) {
this.Graphics = graphics;
}
public void tickAnim() {
+
+
if (!isAnimating) return;
+ if (anim == null) {
+ isAnimating = false;
+ return;
+ }
+
animTicks++;
+
if (animTicks < anim.animationTimeTicks) {
tickStage();
} else {
- isAnimating = false;
+ if(LoopNeverending())
+ {
+ ResetOnLoop();
+ } else
+ {
+ isAnimating = false;
+ }
+
+
}
+
+
+
}
public void tickStage()
{
+
+ if(stage == null)
+ {
+ isAnimating = false;
+ return;
+ }
+
stageTicks++;
- if(stageTicks >= stage.playTimeTicks) {
+ if(stageTicks >= stage.playTimeTicks || (fastAnimForQuickie && stage.playTimeTicksQuick >= 0 && stageTicks >= stage.playTimeTicksQuick)) {
curStage++;
@@ -217,9 +272,16 @@ namespace Rimworld_Animations {
}
if(curStage >= anim.animationStages.Count) {
- isAnimating = false;
- pawn.jobs.curDriver.ReadyForNextToil();
-
+ if (LoopNeverending())
+ {
+ ResetOnLoop();
+ }
+ else
+ {
+ isAnimating = false;
+ pawn.jobs.curDriver.ReadyForNextToil();
+ }
+
} else {
tickClip();
}
@@ -234,18 +296,34 @@ namespace Rimworld_Animations {
//play sound effect
if(rjw.RJWSettings.sounds_enabled && clip.SoundEffects.ContainsKey(clipTicks) && AnimationSettings.soundOverride) {
- SoundDef.Named(clip.SoundEffects[clipTicks]).PlayOneShot(new TargetInfo(pawn.Position, pawn.Map));
+
- if (AnimationSettings.applySemenOnAnimationOrgasm && (pawn?.jobs?.curDriver is JobDriver_Sex) && clip.SoundEffects[clipTicks] == "Cum") {
+ SoundInfo sound = new TargetInfo(pawn.Position, pawn.Map);
+ string soundEffectName = clip.SoundEffects[clipTicks];
- Pawn partner = (pawn.jobs.curDriver as JobDriver_Sex)?.Partner;
- if(anim.sexTypes.Contains((pawn.jobs.curDriver as JobDriver_Sex).sexType)) {
- SemenHelper.calculateAndApplySemen(pawn, partner, (pawn.jobs.curDriver as JobDriver_Sex).sexType);
- }
-
+ if ((pawn.jobs.curDriver as JobDriver_Sex).isAnimalOnAnimal)
+ {
+ sound.volumeFactor *= RJWSettings.sounds_animal_on_animal_volume;
}
+ if(soundEffectName.StartsWith("Voiceline_"))
+ {
+ sound.volumeFactor *= RJWSettings.sounds_voice_volume;
+ }
+
+ if (clip.SoundEffects[clipTicks] == "Cum") {
+
+ sound.volumeFactor *= RJWSettings.sounds_cum_volume;
+ //considerApplyingSemen();
+
+ } else
+ {
+ sound.volumeFactor *= RJWSettings.sounds_sex_volume;
+ }
+
+ SoundDef.Named(soundEffectName).PlayOneShot(sound);
+
}
if(AnimationSettings.orgasmQuiver && clip.quiver.ContainsKey(clipTicks)) {
quiver = clip.quiver[clipTicks];
@@ -260,6 +338,18 @@ namespace Rimworld_Animations {
calculateDrawValues();
}
+ public void considerApplyingSemen()
+ {
+ if(AnimationSettings.applySemenOnAnimationOrgasm && (pawn?.jobs?.curDriver is JobDriver_Sex))
+ {
+
+ if (anim.sexTypes.Contains((pawn.jobs.curDriver as JobDriver_Sex).Sexprops.sexType))
+ {
+ //SemenHelper.calculateAndApplySemen((pawn.jobs.curDriver as JobDriver_Sex).Sexprops);
+ }
+ }
+ }
+
public void calculateDrawValues() {
/*if(Find.TickManager.TickRateMultiplier > 1 && (lastDrawFrame + 1 >= RealTime.frameCount || RealTime.deltaTime < 0.05f)) {
@@ -268,9 +358,11 @@ namespace Rimworld_Animations {
deltaPos = new Vector3(clip.BodyOffsetX.Evaluate(clipPercent) * (mirror ? -1 : 1), clip.layer.AltitudeFor(), clip.BodyOffsetZ.Evaluate(clipPercent));
- if (AnimationSettings.offsets != null && AnimationSettings.offsets.ContainsKey(CurrentAnimation.defName + pawn.def.defName + ActorIndex)) {
- deltaPos.x += AnimationSettings.offsets[CurrentAnimation.defName + pawn.def.defName + ActorIndex].x * (mirror ? -1 : 1);
- deltaPos.z += AnimationSettings.offsets[CurrentAnimation.defName + pawn.def.defName + ActorIndex].y;
+ string bodyTypeDef = (pawn.story?.bodyType != null) ? pawn.story.bodyType.ToString() : "";
+
+ if (AnimationSettings.offsets != null && AnimationSettings.offsets.ContainsKey(CurrentAnimation.defName + pawn.def.defName + bodyTypeDef + ActorIndex)) {
+ deltaPos.x += AnimationSettings.offsets[CurrentAnimation.defName + pawn.def.defName + bodyTypeDef + ActorIndex].x * (mirror ? -1 : 1);
+ deltaPos.z += AnimationSettings.offsets[CurrentAnimation.defName + pawn.def.defName + bodyTypeDef + ActorIndex].y;
}
@@ -281,8 +373,8 @@ namespace Rimworld_Animations {
genitalAngle = clip.GenitalAngle.Evaluate(clipPercent) * (mirror ? -1 : 1);
}
- if (AnimationSettings.rotation != null && AnimationSettings.rotation.ContainsKey(CurrentAnimation.defName + pawn.def.defName + ActorIndex)) {
- float offsetRotation = AnimationSettings.rotation[CurrentAnimation.defName + pawn.def.defName + ActorIndex] * (Mirror ? -1 : 1);
+ if (AnimationSettings.rotation != null && AnimationSettings.rotation.ContainsKey(CurrentAnimation.defName + pawn.def.defName + bodyTypeDef + ActorIndex)) {
+ float offsetRotation = AnimationSettings.rotation[CurrentAnimation.defName + pawn.def.defName + bodyTypeDef + ActorIndex] * (Mirror ? -1 : 1);
genitalAngle += offsetRotation;
bodyAngle += offsetRotation;
headAngle += offsetRotation;
@@ -290,6 +382,7 @@ namespace Rimworld_Animations {
//don't go past 360 or less than 0
+
if (bodyAngle < 0) bodyAngle = 360 - ((-1f*bodyAngle) % 360);
if (bodyAngle > 360) bodyAngle %= 360;
@@ -298,7 +391,7 @@ namespace Rimworld_Animations {
if (headAngle > 360) headAngle %= 360;
if (genitalAngle < 0) genitalAngle = 360 - ((-1f * genitalAngle) % 360);
- if (genitalAngle > 360) genitalAngle %= 360;
+ if (genitalAngle > 360) genitalAngle %= 360;
bodyFacing = mirror ? new Rot4((int)clip.BodyFacing.Evaluate(clipPercent)).Opposite : new Rot4((int)clip.BodyFacing.Evaluate(clipPercent));
@@ -326,6 +419,11 @@ namespace Rimworld_Animations {
}
+ public Vector3 getPawnHeadOffset()
+ {
+ return Quaternion.AngleAxis(bodyAngle, Vector3.up) * (pawn.Drawer.renderer.BaseHeadOffsetAt(headFacing) + headBob);
+
+ }
public AnimationDef CurrentAnimation {
get {
@@ -342,33 +440,88 @@ namespace Rimworld_Animations {
public override void PostExposeData() {
base.PostExposeData();
- Scribe_Defs.Look(ref anim, "anim");
+ Scribe_Defs.Look(ref anim, "RJWAnimations-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 animTicks, "RJWAnimations-animTicks", 1);
+ Scribe_Values.Look(ref stageTicks, "RJWAnimations-stageTicks", 1);
+ Scribe_Values.Look(ref clipTicks, "RJWAnimations-clipTicks", 1);
+ Scribe_Values.Look(ref clipPercent, "RJWAnimations-clipPercent", 1);
+ Scribe_Values.Look(ref mirror, "RJWAnimations-mirror");
- Scribe_Values.Look(ref mirror, "mirror");
+ Scribe_Values.Look(ref curStage, "RJWAnimations-curStage", 0);
+ Scribe_Values.Look(ref actor, "RJWAnimations-actor");
- Scribe_Values.Look(ref curStage, "curStage", 0);
- Scribe_Values.Look(ref actor, "actor");
+ Scribe_Values.Look(ref anchor, "RJWAnimations-anchor");
+ Scribe_Values.Look(ref deltaPos, "RJWAnimations-deltaPos");
+ Scribe_Values.Look(ref headBob, "RJWAnimations-headBob");
+ Scribe_Values.Look(ref bodyAngle, "RJWAnimations-bodyAngle");
+ Scribe_Values.Look(ref headAngle, "RJWAnimations-headAngle");
- 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 genitalAngle, "RJWAnimations-GenitalAngle");
+ Scribe_Values.Look(ref controlGenitalAngle, "RJWAnimations-controlGenitalAngle");
- Scribe_Values.Look(ref genitalAngle, "GenitalAngle");
- Scribe_Values.Look(ref controlGenitalAngle, "controlGenitalAngle");
+ Scribe_Values.Look(ref headFacing, "RJWAnimations-headFacing");
+ Scribe_Values.Look(ref headFacing, "RJWAnimations-bodyFacing");
- Scribe_Values.Look(ref headFacing, "headFacing");
- Scribe_Values.Look(ref headFacing, "bodyFacing");
-
- Scribe_Values.Look(ref quiver, "orgasmQuiver");
+ Scribe_Values.Look(ref quiver, "RJWAnimations-orgasmQuiver");
}
+ public void shiftActorPositionAndRestartAnimation() {
+ actor = (actor == anim.actors.Count - 1 ? 0 : actor + 1);
+
+ if (pawn?.story?.bodyType != null) {
+ if (pawn.story.bodyType == BodyTypeDefOf.Fat && anim?.actors[actor]?.bodyTypeOffset?.Fat != null) {
+ anchor.x += anim.actors[actor].bodyTypeOffset.Fat.Value.x * (mirror ? -1f : 1f);
+ anchor.z += anim.actors[actor].bodyTypeOffset.Fat.Value.y;
+ }
+ else if (pawn.story.bodyType == BodyTypeDefOf.Female && anim?.actors[actor]?.bodyTypeOffset?.Female != null) {
+ anchor.x += anim.actors[actor].bodyTypeOffset.Female.Value.x * (mirror ? -1f : 1f);
+ anchor.z += anim.actors[actor].bodyTypeOffset.Female.Value.y;
+ }
+ else if (pawn.story.bodyType == BodyTypeDefOf.Male && anim?.actors[actor]?.bodyTypeOffset?.Male != null) {
+ anchor.x += anim.actors[actor].bodyTypeOffset.Male.Value.x * (mirror ? -1f : 1f);
+ anchor.z += anim.actors[actor].bodyTypeOffset.Male.Value.y;
+ }
+ else if (pawn.story.bodyType == BodyTypeDefOf.Thin && anim?.actors[actor]?.bodyTypeOffset?.Thin != null) {
+ anchor.x += anim.actors[actor].bodyTypeOffset.Thin.Value.x * (mirror ? -1f : 1f);
+ anchor.z += anim.actors[actor].bodyTypeOffset.Thin.Value.y;
+ }
+ else if (pawn.story.bodyType == BodyTypeDefOf.Hulk && anim?.actors[actor]?.bodyTypeOffset?.Hulk != null) {
+ anchor.x += anim.actors[actor].bodyTypeOffset.Hulk.Value.x * (mirror ? -1f : 1f);
+ anchor.z += anim.actors[actor].bodyTypeOffset.Hulk.Value.y;
+ }
+ }
+
+ curStage = 0;
+ animTicks = 0;
+ stageTicks = 0;
+ clipTicks = 0;
+
+ controlGenitalAngle = anim.actors[actor].controlGenitalAngle;
+
+ tickAnim();
+ }
+
+ public bool LoopNeverending()
+ {
+ if(pawn?.jobs?.curDriver != null &&
+ (pawn.jobs.curDriver is JobDriver_Sex) && (pawn.jobs.curDriver as JobDriver_Sex).neverendingsex ||
+ (pawn.jobs.curDriver is JobDriver_SexBaseReciever) && (pawn.jobs.curDriver as JobDriver_Sex).Partner?.jobs?.curDriver != null && ((pawn.jobs.curDriver as JobDriver_Sex).Partner.jobs.curDriver as JobDriver_Sex).neverendingsex)
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ public void ResetOnLoop()
+ {
+ curStage = 1;
+ animTicks = 0;
+ stageTicks = 0;
+ clipTicks = 0;
+
+ tickAnim();
+ }
}
}
diff --git a/Source/Comps/CompProperties_BodyAnimator.cs b/1.3/Source/Comps/CompProperties_BodyAnimator.cs
similarity index 68%
rename from Source/Comps/CompProperties_BodyAnimator.cs
rename to 1.3/Source/Comps/CompProperties_BodyAnimator.cs
index cc40925..09df7ce 100644
--- a/Source/Comps/CompProperties_BodyAnimator.cs
+++ b/1.3/Source/Comps/CompProperties_BodyAnimator.cs
@@ -7,10 +7,10 @@ using Verse;
using RimWorld;
namespace Rimworld_Animations {
- class CompProperties_BodyAnimator : CompProperties
+ public class CompProperties_BodyAnimator : CompProperties
{
- public CompProperties_BodyAnimator() {
-
+ public CompProperties_BodyAnimator()
+ {
base.compClass = typeof(CompBodyAnimator);
}
}
diff --git a/1.3/Source/Comps/CompProperties_ThingAnimator.cs b/1.3/Source/Comps/CompProperties_ThingAnimator.cs
new file mode 100644
index 0000000..34c67b1
--- /dev/null
+++ b/1.3/Source/Comps/CompProperties_ThingAnimator.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Verse;
+
+namespace Rimworld_Animations {
+ public class CompProperties_ThingAnimator : CompProperties
+ {
+
+ public CompProperties_ThingAnimator()
+ {
+ base.compClass = typeof(CompThingAnimator);
+ }
+ }
+}
diff --git a/1.3/Source/Comps/CompThingAnimator.cs b/1.3/Source/Comps/CompThingAnimator.cs
new file mode 100644
index 0000000..f5315e4
--- /dev/null
+++ b/1.3/Source/Comps/CompThingAnimator.cs
@@ -0,0 +1,245 @@
+using RimWorld;
+using rjw;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using UnityEngine;
+using Verse;
+
+namespace Rimworld_Animations {
+ public class CompThingAnimator : ThingComp
+ {
+ Vector3 anchor;
+
+ Pawn pawn;
+
+ public bool isAnimating = false, mirror;
+
+ int animTicks = 0, stageTicks = 0, clipTicks = 0, curStage = 0;
+ float rotation = 0;
+ float clipPercent = 0;
+
+ public Vector3 deltaPos;
+
+ AnimationDef anim;
+ private ThingAnimationClip clip => (ThingAnimationClip)stage.animationClips[1];
+ private AnimationStage stage
+ {
+ get
+ {
+ return anim.animationStages[curStage];
+ }
+
+ }
+
+ public void StartAnimation(AnimationDef anim, Pawn pawn, bool mirror = false)
+ {
+ isAnimating = true;
+
+ this.anim = anim;
+ this.pawn = pawn;
+ this.mirror = mirror;
+
+ animTicks = 0;
+ stageTicks = 0;
+ clipTicks = 0;
+
+ curStage = 0;
+ clipPercent = 0;
+
+ tickAnim();
+
+ }
+
+ public void setAnchor(IntVec3 position)
+ {
+ anchor = position.ToVector3();
+ }
+
+ public override void CompTick()
+ {
+ base.CompTick();
+
+ if(isAnimating)
+ {
+ if (pawn.Dead || pawn?.jobs?.curDriver == null || (pawn?.jobs?.curDriver != null && !(pawn?.jobs?.curDriver is rjw.JobDriver_Sex)))
+ {
+ isAnimating = false;
+ }
+ else
+ {
+ tickAnim();
+ }
+ }
+
+
+ }
+
+ public void tickAnim()
+ {
+ if (!isAnimating) return;
+ animTicks++;
+
+ if (animTicks < anim.animationTimeTicks)
+ {
+ tickStage();
+ }
+ else
+ {
+ if (LoopNeverending())
+ {
+ ResetOnLoop();
+ }
+ else
+ {
+ isAnimating = false;
+ }
+
+
+ }
+
+ }
+
+ public void tickStage()
+ {
+ if (stage == null)
+ {
+ isAnimating = false;
+ return;
+ }
+
+ stageTicks++;
+
+ if (stageTicks >= stage.playTimeTicks)
+ {
+
+ curStage++;
+
+ stageTicks = 0;
+ clipTicks = 0;
+ clipPercent = 0;
+ }
+
+ if (curStage >= anim.animationStages.Count)
+ {
+ if (LoopNeverending())
+ {
+ ResetOnLoop();
+ }
+ else
+ {
+ isAnimating = false;
+ }
+
+ }
+ else
+ {
+ tickClip();
+ }
+ }
+
+ public void tickClip()
+ {
+ clipTicks++;
+
+ 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 setAnchor(Thing thing)
+ {
+
+ //center on bed
+ 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();
+ }
+
+ anchor -= new Vector3(0.5f, 0, 0.5f);
+ }
+ private void calculateDrawValues()
+ {
+
+ //shift up and right 0.5f to align center
+ deltaPos = new Vector3((clip.PositionX.Evaluate(clipPercent)) * (mirror ? -1 : 1) + 0.5f, AltitudeLayer.Item.AltitudeFor(), clip.PositionZ.Evaluate(clipPercent) + 0.5f);
+ //Log.Message("Clip percent: " + clipPercent + " deltaPos: " + deltaPos);
+ rotation = clip.Rotation.Evaluate(clipPercent) * (mirror ? -1 : 1);
+ }
+
+ public void AnimateThing(Thing thing)
+ {
+ thing.Graphic.Draw(deltaPos + anchor, mirror ? Rot4.West : Rot4.East, thing, rotation);
+ }
+
+ public bool LoopNeverending()
+ {
+ if (pawn?.jobs?.curDriver != null &&
+ (pawn.jobs.curDriver is JobDriver_Sex) && (pawn.jobs.curDriver as JobDriver_Sex).neverendingsex)
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ public void ResetOnLoop()
+ {
+ curStage = 1;
+ animTicks = 0;
+ stageTicks = 0;
+ clipTicks = 0;
+
+ tickAnim();
+ }
+
+ }
+}
diff --git a/Source/Defs/AnimationDef.cs b/1.3/Source/Defs/AnimationDef.cs
similarity index 80%
rename from Source/Defs/AnimationDef.cs
rename to 1.3/Source/Defs/AnimationDef.cs
index 064f10b..395ff83 100644
--- a/Source/Defs/AnimationDef.cs
+++ b/1.3/Source/Defs/AnimationDef.cs
@@ -13,7 +13,9 @@ namespace Rimworld_Animations {
public List actors;
public int animationTimeTicks = 0; //do not set manually
public bool sounds = false;
- public List sexTypes;
+ public List sexTypes = null;
+ public List interactionDefTypes = null;
+ public List tags = new List();
public override void PostLoad() {
base.PostLoad();
diff --git a/1.3/Source/Extensions/PawnWoundDrawerExtension.cs b/1.3/Source/Extensions/PawnWoundDrawerExtension.cs
new file mode 100644
index 0000000..4901de2
--- /dev/null
+++ b/1.3/Source/Extensions/PawnWoundDrawerExtension.cs
@@ -0,0 +1,34 @@
+using System;
+using System.Collections.Generic;
+using RimWorld;
+using UnityEngine;
+using Verse;
+using Rimworld_Animations;
+
+namespace Rimworld_Animations
+{
+ [StaticConstructorOnStartup]
+ public static class PawnWoundDrawerExtension
+ {
+ public static void RenderOverBody(this PawnWoundDrawer pawnWoundDrawer, Vector3 drawLoc, Mesh bodyMesh, Quaternion quat, bool drawNow, BodyTypeDef.WoundLayer layer, Rot4 pawnRot, bool? overApparel = null, Pawn pawn = null, PawnRenderFlags flags = new PawnRenderFlags())
+ {
+ if (pawn == null)
+ { return; }
+
+ if (!flags.FlagSet(PawnRenderFlags.Portrait) && layer == BodyTypeDef.WoundLayer.Head)
+ {
+ CompBodyAnimator pawnAnimator = pawn.TryGetComp();
+ if (pawnAnimator != null && pawnAnimator.isAnimating && pawn.Drawer.renderer.graphics.headGraphic != null)
+ {
+ pawnRot = pawnAnimator.headFacing;
+ quat = Quaternion.AngleAxis(angle: pawnAnimator.headAngle, axis: Vector3.up);
+ float y = drawLoc.y;
+ drawLoc = pawnAnimator.getPawnHeadPosition() - Quaternion.AngleAxis(pawnAnimator.headAngle, Vector3.up) * pawn.Drawer.renderer.BaseHeadOffsetAt(pawnAnimator.headFacing);
+ drawLoc.y = y;
+ }
+ }
+
+ pawnWoundDrawer.RenderOverBody(drawLoc, bodyMesh, quat, drawNow, layer, pawnRot, overApparel);
+ }
+ }
+}
diff --git a/1.3/Source/MainTabWindows/MainTabWindow_OffsetConfigure.cs b/1.3/Source/MainTabWindows/MainTabWindow_OffsetConfigure.cs
new file mode 100644
index 0000000..b7fef1d
--- /dev/null
+++ b/1.3/Source/MainTabWindows/MainTabWindow_OffsetConfigure.cs
@@ -0,0 +1,143 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Verse;
+using RimWorld;
+using UnityEngine;
+
+namespace Rimworld_Animations {
+ class MainTabWindow_OffsetConfigure : MainTabWindow
+ {
+
+ public override Vector2 RequestedTabSize => new Vector2(505, 380);
+ public override void DoWindowContents(Rect inRect) {
+
+ Rect position = new Rect(inRect.x, inRect.y, inRect.width, inRect.height);
+
+
+ Listing_Standard listingStandard = new Listing_Standard();
+ listingStandard.Begin(position);
+
+ listingStandard.Label("Animation Manager");
+
+ listingStandard.GapLine();
+
+
+ if (Find.Selector.SingleSelectedThing is Pawn) {
+
+ Pawn curPawn = Find.Selector.SingleSelectedThing as Pawn;
+
+ if (curPawn.TryGetComp().isAnimating) {
+
+ AnimationDef def = curPawn.TryGetComp().CurrentAnimation;
+ int ActorIndex = curPawn.TryGetComp().ActorIndex;
+ float offsetX = 0, offsetZ = 0, rotation = 0;
+
+ string bodyTypeDef = (curPawn.story?.bodyType != null) ? curPawn.story.bodyType.ToString() : "";
+
+ if (AnimationSettings.offsets.ContainsKey(def.defName + curPawn.def.defName + bodyTypeDef + ActorIndex)) {
+ offsetX = AnimationSettings.offsets[def.defName + curPawn.def.defName + bodyTypeDef + ActorIndex].x;
+ offsetZ = AnimationSettings.offsets[def.defName + curPawn.def.defName + bodyTypeDef + ActorIndex].y;
+ } else {
+ AnimationSettings.offsets.Add(def.defName + curPawn.def.defName + bodyTypeDef + ActorIndex, new Vector2(0, 0));
+ }
+
+ if (AnimationSettings.rotation.ContainsKey(def.defName + curPawn.def.defName + bodyTypeDef + ActorIndex)) {
+ rotation = AnimationSettings.rotation[def.defName + curPawn.def.defName + bodyTypeDef + ActorIndex];
+ }
+ else {
+ AnimationSettings.rotation.Add(def.defName + curPawn.def.defName + bodyTypeDef + ActorIndex, 0);
+ }
+
+ listingStandard.Label("Name: " + curPawn.Name + " Race: " + curPawn.def.defName + " Actor Index: " + curPawn.TryGetComp().ActorIndex + " Body Type (if any): " + bodyTypeDef + " Animation: " + def.label + (curPawn.TryGetComp().Mirror ? " mirrored" : ""));
+
+ if(curPawn.def.defName == "Human") {
+ listingStandard.Label("Warning--You generally don't want to change human offsets, only alien offsets");
+ }
+
+ bool mirrored = curPawn.TryGetComp().Mirror;
+
+ float.TryParse(listingStandard.TextEntryLabeled("X Offset: ", offsetX.ToString()), out offsetX);
+ offsetX = listingStandard.Slider(offsetX, -2 * (mirrored ? -1 : 1), 2 * (mirrored ? -1 : 1));
+
+ float.TryParse(listingStandard.TextEntryLabeled("Z Offset: ", offsetZ.ToString()), out offsetZ);
+ offsetZ = listingStandard.Slider(offsetZ, -2, 2);
+
+ float.TryParse(listingStandard.TextEntryLabeled("Rotation: ", rotation.ToString()), out rotation);
+ rotation = listingStandard.Slider(rotation, -180, 180);
+
+ if(listingStandard.ButtonText("Reset All")) {
+ offsetX = 0;
+ offsetZ = 0;
+ rotation = 0;
+ }
+
+ listingStandard.GapLine();
+
+ if(listingStandard.ButtonText("Shift Actors")) {
+
+ if(AnimationSettings.debugMode) {
+ Log.Message("Shifting actors in animation...");
+ }
+
+ for(int i = 0; i < curPawn.TryGetComp().actorsInCurrentAnimation.Count; i++) {
+
+ Pawn actor = curPawn.TryGetComp().actorsInCurrentAnimation[i];
+
+ actor.TryGetComp()?.shiftActorPositionAndRestartAnimation();
+
+ //reset the clock time of every pawn in animation
+ if(actor.jobs.curDriver is rjw.JobDriver_Sex) {
+ (actor.jobs.curDriver as rjw.JobDriver_Sex).ticks_left = def.animationTimeTicks;
+ (actor.jobs.curDriver as rjw.JobDriver_Sex).ticksLeftThisToil = def.animationTimeTicks;
+ (actor.jobs.curDriver as rjw.JobDriver_Sex).duration = def.animationTimeTicks;
+ }
+
+ }
+
+ }
+
+ if (offsetX != AnimationSettings.offsets[def.defName + curPawn.def.defName + bodyTypeDef + ActorIndex].x || offsetZ != AnimationSettings.offsets[def.defName + curPawn.def.defName + bodyTypeDef + ActorIndex].y) {
+ AnimationSettings.offsets[def.defName + curPawn.def.defName + bodyTypeDef + ActorIndex] = new Vector2(offsetX, offsetZ);
+
+ }
+
+ if(rotation != AnimationSettings.rotation[def.defName + curPawn.def.defName + bodyTypeDef + ActorIndex]) {
+ AnimationSettings.rotation[def.defName + curPawn.def.defName + bodyTypeDef + ActorIndex] = rotation;
+ }
+
+ }
+
+ }
+ else {
+ listingStandard.Label("Select a pawn currently in an animation to change their offsets");
+ }
+
+ listingStandard.End();
+
+ }
+
+ public override void PreOpen() {
+ base.PreOpen();
+ if(AnimationSettings.offsets == null) {
+ if (AnimationSettings.debugMode)
+ Log.Message("New offsets");
+ AnimationSettings.offsets = new Dictionary();
+ }
+
+ if(AnimationSettings.rotation == null) {
+ if (AnimationSettings.debugMode)
+ Log.Message("New rotation");
+ AnimationSettings.rotation = new Dictionary();
+ }
+ }
+
+ public override void PostClose() {
+ base.PostClose();
+
+ LoadedModManager.GetMod().WriteSettings();
+ }
+ }
+}
diff --git a/Source/MainTabWindows/OffsetMainButtonDefOf.cs b/1.3/Source/MainTabWindows/OffsetMainButtonDefOf.cs
similarity index 100%
rename from Source/MainTabWindows/OffsetMainButtonDefOf.cs
rename to 1.3/Source/MainTabWindows/OffsetMainButtonDefOf.cs
diff --git a/Source/MainTabWindows/WorldComponent_UpdateMainTab.cs b/1.3/Source/MainTabWindows/WorldComponent_UpdateMainTab.cs
similarity index 100%
rename from Source/MainTabWindows/WorldComponent_UpdateMainTab.cs
rename to 1.3/Source/MainTabWindows/WorldComponent_UpdateMainTab.cs
diff --git a/Source/Patches/Harmony_PatchAll.cs b/1.3/Source/Patches/Harmony_PatchAll.cs
similarity index 87%
rename from Source/Patches/Harmony_PatchAll.cs
rename to 1.3/Source/Patches/Harmony_PatchAll.cs
index 3a0a7bb..1c1d63f 100644
--- a/Source/Patches/Harmony_PatchAll.cs
+++ b/1.3/Source/Patches/Harmony_PatchAll.cs
@@ -14,7 +14,7 @@ namespace Rimworld_Animations {
static Harmony_PatchAll() {
- Harmony val = new Harmony("rimworldanim");
+ Harmony val = new Harmony("rjwanim");
val.PatchAll(Assembly.GetExecutingAssembly());
}
diff --git a/1.3/Source/Patches/OtherModPatches/HarmonyPatch_AlienRace.cs b/1.3/Source/Patches/OtherModPatches/HarmonyPatch_AlienRace.cs
new file mode 100644
index 0000000..b7198da
--- /dev/null
+++ b/1.3/Source/Patches/OtherModPatches/HarmonyPatch_AlienRace.cs
@@ -0,0 +1,397 @@
+using HarmonyLib;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Text;
+using System.Threading.Tasks;
+using UnityEngine;
+using Verse;
+using AlienRace;
+
+namespace Rimworld_Animations {
+
+
+ [StaticConstructorOnStartup]
+ public static class HarmonyPatch_AlienRace
+ {
+ static HarmonyPatch_AlienRace()
+ {
+ (new Harmony("rjwanim")).Patch(AccessTools.Method(AccessTools.TypeByName("AlienRace.HarmonyPatches"), "DrawAddons"),
+ prefix: new HarmonyMethod(AccessTools.Method(typeof(HarmonyPatch_AlienRace), "Prefix_AnimateHeadAddons")));
+ }
+
+
+ public static bool Prefix_AnimateHeadAddons(PawnRenderFlags renderFlags, Vector3 vector /*rootloc*/, Vector3 headOffset, Pawn pawn, Quaternion quat, Rot4 rotation)
+ {
+
+ if (renderFlags.FlagSet(PawnRenderFlags.Portrait) || pawn.TryGetComp() == null || !pawn.TryGetComp().isAnimating) return true;
+ if (!(pawn.def is ThingDef_AlienRace alienProps) || renderFlags.FlagSet(PawnRenderFlags.Invisible)) return false;
+
+ List addons = alienProps.alienRace.generalSettings.alienPartGenerator.bodyAddons;
+ AlienPartGenerator.AlienComp comp = pawn.GetComp();
+ CompBodyAnimator pawnAnimator = pawn.TryGetComp();
+
+ for (int i = 0; i < addons.Count; i++)
+ {
+ AlienPartGenerator.BodyAddon ba = addons[index: i];
+
+ if (!ba.CanDrawAddon(pawn: pawn)) continue;
+
+ bool forceDrawForBody = false;
+ if (alienProps.defName.Contains("Orassan") && ba.path.ToLower().Contains("tail"))
+ {
+ forceDrawForBody = true;
+ }
+ AlienPartGenerator.RotationOffset offset = ba.defaultOffsets.GetOffset((ba.drawnInBed && !forceDrawForBody) || ba.alignWithHead ? pawnAnimator.headFacing : pawnAnimator.bodyFacing);
+ Vector3 a = (offset != null) ? offset.GetOffset(renderFlags.FlagSet(PawnRenderFlags.Portrait), pawn.story.bodyType, comp.crownType) : Vector3.zero;
+ AlienPartGenerator.RotationOffset offset2 = ba.offsets.GetOffset((ba.drawnInBed && !forceDrawForBody) || ba.alignWithHead ? pawnAnimator.headFacing : pawnAnimator.bodyFacing);
+ Vector3 vector2 = a + ((offset2 != null) ? offset2.GetOffset(renderFlags.FlagSet(PawnRenderFlags.Portrait), pawn.story.bodyType, comp.crownType) : Vector3.zero);
+ vector2.y = (ba.inFrontOfBody ? (0.3f + vector2.y) : (-0.3f - vector2.y));
+ float num = ba.angle;
+ if (rotation == Rot4.North)
+ {
+ if (ba.layerInvert)
+ {
+ vector2.y = 0f - vector2.y;
+ }
+ num = 0f;
+ }
+ if (rotation == Rot4.East)
+ {
+ num = 0f - num;
+ vector2.x = 0f - vector2.x;
+ }
+ Graphic addonGraphic = comp.addonGraphics[i];
+
+ addonGraphic.drawSize = ((renderFlags.FlagSet(PawnRenderFlags.Portrait) && ba.drawSizePortrait != Vector2.zero) ? ba.drawSizePortrait : ba.drawSize) * (ba.scaleWithPawnDrawsize ? (ba.alignWithHead ? (renderFlags.FlagSet(PawnRenderFlags.Portrait) ? comp.customPortraitHeadDrawSize : comp.customHeadDrawSize) : (renderFlags.FlagSet(PawnRenderFlags.Portrait) ? comp.customPortraitDrawSize : comp.customDrawSize)) : Vector2.one) * 1.5f;
+
+ Vector3 orassanv = Vector3.zero;
+ bool orassan = false;
+ if ((pawn.def as ThingDef_AlienRace).defName == "Alien_Orassan")
+ {
+ orassan = true;
+
+ if (ba.path.Contains("closed"))
+ {
+ continue;
+ }
+
+ if (ba.bodyPart.Contains("ear"))
+
+ {
+ orassan = true;
+
+ orassanv = new Vector3(0, 0, 0.23f);
+ if (pawnAnimator.headFacing == Rot4.North)
+ {
+ orassanv.z -= 0.1f;
+ orassanv.y += 1f;
+
+ if (ba.bodyPart.Contains("left"))
+ {
+ orassanv.x += 0.03f;
+ }
+ else
+ {
+ orassanv.x -= 0.03f;
+ }
+
+ }
+ else if (pawnAnimator.headFacing == Rot4.East)
+ {
+ orassanv.x -= 0.1f;
+ }
+ else if (pawnAnimator.headFacing == Rot4.West)
+ {
+ orassanv.x = 0.1f;
+ }
+ else
+ {
+ orassanv.z -= 0.1f;
+ orassanv.y += 1f;
+
+ if (ba.bodyPart.Contains("right"))
+ {
+ //orassanv.x += 0.3f;
+ }
+ else
+ {
+ //orassanv.x -= 0.3f;
+ }
+ }
+ orassanv = orassanv.RotatedBy(pawnAnimator.headAngle);
+ }
+ }
+
+
+ if ((ba.drawnInBed && !forceDrawForBody) || ba.alignWithHead)
+ {
+
+ Quaternion addonRotation = Quaternion.AngleAxis(pawnAnimator.headAngle < 0 ? 360 - (360 % pawnAnimator.headAngle) : pawnAnimator.headAngle, Vector3.up);
+ /*
+ *
+ * genital rotation is borked
+ if (AnimationSettings.controlGenitalRotation && pawnAnimator.controlGenitalAngle && ba?.hediffGraphics != null && ba.hediffGraphics.Count != 0 && ba.hediffGraphics[0]?.path != null && (ba.hediffGraphics[0].path.Contains("Penis") || ba.hediffGraphics[0].path.Contains("penis")))
+ {
+ addonRotation = Quaternion.AngleAxis(angle: pawnAnimator.genitalAngle < 0 ? 360 - (360 % pawnAnimator.genitalAngle) : pawnAnimator.genitalAngle, axis: Vector3.up);
+ }
+
+ */
+
+ GenDraw.DrawMeshNowOrLater(mesh: addonGraphic.MeshAt(rot: pawnAnimator.headFacing), loc: vector /*rootloc*/ + orassanv + (ba.alignWithHead && !orassan ? headOffset : headOffset - addonRotation * pawn.Drawer.renderer.BaseHeadOffsetAt(pawnAnimator.headFacing)) + vector2.RotatedBy(angle: Mathf.Acos(f: Quaternion.Dot(a: Quaternion.identity, b: addonRotation)) * 2f * 57.29578f),
+ quat: Quaternion.AngleAxis(angle: num, axis: Vector3.up) * addonRotation, mat: addonGraphic.MatAt(rot: pawnAnimator.headFacing), renderFlags.FlagSet(PawnRenderFlags.DrawNow));
+
+
+ }
+
+ else
+ {
+ Quaternion addonRotation = Quaternion.AngleAxis(pawnAnimator.bodyAngle, Vector3.up);
+ if (AnimationSettings.controlGenitalRotation && pawnAnimator.controlGenitalAngle && ba?.hediffGraphics != null && ba.hediffGraphics.Count != 0 && ba.hediffGraphics[0]?.path != null && (ba.hediffGraphics[0].path.Contains("Penis") || ba.hediffGraphics[0].path.Contains("penis")))
+ {
+ GenDraw.DrawMeshNowOrLater(mesh: addonGraphic.MeshAt(rot: rotation), loc: vector + (ba.alignWithHead ? headOffset : Vector3.zero) + vector2.RotatedBy(angle: Mathf.Acos(f: Quaternion.Dot(a: Quaternion.identity, b: addonRotation)) * 2f * 57.29578f),
+ quat: Quaternion.AngleAxis(angle: pawnAnimator.genitalAngle, axis: Vector3.up), mat: addonGraphic.MatAt(rot: rotation), renderFlags.FlagSet(PawnRenderFlags.DrawNow));
+ }
+
+ else
+ {
+ GenDraw.DrawMeshNowOrLater(mesh: addonGraphic.MeshAt(rot: rotation), loc: vector + (ba.alignWithHead ? headOffset : Vector3.zero) + vector2.RotatedBy(angle: Mathf.Acos(f: Quaternion.Dot(a: Quaternion.identity, b: addonRotation)) * 2f * 57.29578f),
+ quat: Quaternion.AngleAxis(angle: num, axis: Vector3.up) * addonRotation, mat: addonGraphic.MatAt(rot: rotation), renderFlags.FlagSet(PawnRenderFlags.DrawNow));
+ }
+
+ }
+
+
+ }
+
+ return false;
+ }
+ }
+
+ [HarmonyPatch(typeof(PawnGraphicSet), "ResolveApparelGraphics")]
+ public static class HarmonyPatch_ResolveApparelGraphics
+ {
+ public static bool Prefix(ref Pawn ___pawn)
+ {
+
+ if (___pawn.TryGetComp() != null && ___pawn.TryGetComp().isAnimating)
+ {
+ return false;
+ }
+ return true;
+ }
+ }
+
+ /*
+
+ [HarmonyPatch(typeof(AlienRace.HarmonyPatches), "DrawAddons")]
+ public static class HarmonyPatch_AlienRace {
+
+ public static void RenderHeadAddonInAnimation(Mesh mesh, Vector3 loc, Quaternion quat, Material mat, bool drawNow, Graphic graphic, AlienPartGenerator.BodyAddon bodyAddon, Vector3 v, Vector3 headOffset, Pawn pawn, PawnRenderFlags renderFlags, Vector3 vector, Rot4 rotation)
+ {
+
+ CompBodyAnimator pawnAnimator = pawn.TryGetComp();
+ AlienPartGenerator.AlienComp comp = pawn.GetComp();
+
+ if (pawnAnimator != null && pawnAnimator.isAnimating)
+ {
+
+ if((bodyAddon.drawnInBed || bodyAddon.alignWithHead))
+ {
+
+ AlienPartGenerator.RotationOffset offset = bodyAddon.defaultOffsets.GetOffset(rotation);
+ Vector3 a = (offset != null) ? offset.GetOffset(renderFlags.FlagSet(PawnRenderFlags.Portrait), pawn.story.bodyType, comp.crownType) : Vector3.zero;
+ AlienPartGenerator.RotationOffset offset2 = bodyAddon.offsets.GetOffset(rotation);
+ Vector3 vector2 = a + ((offset2 != null) ? offset2.GetOffset(renderFlags.FlagSet(PawnRenderFlags.Portrait), pawn.story.bodyType, comp.crownType) : Vector3.zero);
+ vector2.y = (bodyAddon.inFrontOfBody ? (0.3f + vector2.y) : (-0.3f - vector2.y));
+ float num = bodyAddon.angle;
+ if (rotation == Rot4.North)
+ {
+ if (bodyAddon.layerInvert)
+ {
+ vector2.y = -vector2.y;
+ }
+ num = 0f;
+ }
+ if (rotation == Rot4.East)
+ {
+ num = -num;
+ vector2.x = -vector2.x;
+ }
+
+ vector = vector + Quaternion.AngleAxis(pawnAnimator.bodyAngle, Vector3.up) * pawn.Drawer.renderer.BaseHeadOffsetAt(pawnAnimator.bodyFacing) - pawnAnimator.getPawnHeadOffset(); //convert vector into pseudo body pos for head
+ quat = Quaternion.AngleAxis(pawnAnimator.headAngle, Vector3.up);
+ loc = vector + (bodyAddon.alignWithHead ? headOffset : Vector3.zero) + vector2.RotatedBy(Mathf.Acos(Quaternion.Dot(Quaternion.identity, quat)) * 2f * 57.29578f);
+ mat = graphic.MatAt(rot: pawnAnimator.headFacing);
+ }
+ else
+ {
+
+ AlienPartGenerator.RotationOffset offset = bodyAddon.defaultOffsets.GetOffset(rotation);
+ Vector3 a = (offset != null) ? offset.GetOffset(renderFlags.FlagSet(PawnRenderFlags.Portrait), pawn.story.bodyType, comp.crownType) : Vector3.zero;
+ AlienPartGenerator.RotationOffset offset2 = bodyAddon.offsets.GetOffset(rotation);
+ Vector3 vector2 = a + ((offset2 != null) ? offset2.GetOffset(renderFlags.FlagSet(PawnRenderFlags.Portrait), pawn.story.bodyType, comp.crownType) : Vector3.zero);
+ vector2.y = (bodyAddon.inFrontOfBody ? (0.3f + vector2.y) : (-0.3f - vector2.y));
+ float num = bodyAddon.angle;
+ if (rotation == Rot4.North)
+ {
+ if (bodyAddon.layerInvert)
+ {
+ vector2.y = -vector2.y;
+ }
+ num = 0f;
+ }
+ if (rotation == Rot4.East)
+ {
+ num = -num;
+ vector2.x = -vector2.x;
+ }
+ quat = Quaternion.AngleAxis(pawnAnimator.bodyAngle, Vector3.up);
+ loc = vector + (bodyAddon.alignWithHead ? headOffset : Vector3.zero) + vector2.RotatedBy(Mathf.Acos(Quaternion.Dot(Quaternion.identity, quat)) * 2f * 57.29578f);
+
+ }
+
+ }
+ GenDraw.DrawMeshNowOrLater(mesh, loc, quat, mat, drawNow);
+
+ /*
+ if (pawnAnimator != null && !renderFlags.FlagSet(PawnRenderFlags.Portrait) && pawnAnimator.isAnimating && (bodyAddon.drawnInBed || bodyAddon.alignWithHead))
+ {
+
+
+ if ((pawn.def as ThingDef_AlienRace).defName == "Alien_Orassan")
+ {
+ orassan = true;
+
+ if(bodyAddon.path.Contains("closed"))
+ {
+ return;
+ }
+
+ if (bodyAddon.bodyPart.Contains("ear"))
+
+ {
+ orassan = true;
+
+ orassanv = new Vector3(0, 0, 0.23f);
+ if (pawnAnimator.headFacing == Rot4.North)
+ {
+ orassanv.z -= 0.1f;
+ orassanv.y += 1f;
+
+ if(bodyAddon.bodyPart.Contains("left"))
+ {
+ orassanv.x += 0.03f;
+ } else
+ {
+ orassanv.x -= 0.03f;
+ }
+
+ }
+ else if (pawnAnimator.headFacing == Rot4.East)
+ {
+ orassanv.x -= 0.1f;
+ }
+ else if (pawnAnimator.headFacing == Rot4.West)
+ {
+ orassanv.x = 0.1f;
+ }
+ else
+ {
+ orassanv.z -= 0.1f;
+ orassanv.y += 1f;
+
+ if (bodyAddon.bodyPart.Contains("right"))
+ {
+ orassanv.x += 0.05f;
+ }
+ else
+ {
+ orassanv.x -= 0.05f;
+ }
+ }
+ orassanv = orassanv.RotatedBy(pawnAnimator.headAngle);
+ }
+ }
+
+
+
+
+
+ GenDraw.DrawMeshNowOrLater(mesh: graphic.MeshAt(rot: headRotInAnimation), loc: loc + orassanv + (bodyAddon.alignWithHead ? headOffset : Vector3.zero),// + v.RotatedBy(Mathf.Acos(Quaternion.Dot(Quaternion.identity, quat)) * 2f * 57.29578f),
+ quat: Quaternion.AngleAxis(angle: num, axis: Vector3.up) * headQuatInAnimation, mat: graphic.MatAt(rot: pawnAnimator.headFacing), drawNow: drawNow);;
+ }
+
+ else
+ {
+
+ }
+
+
+ }
+
+
+ public static IEnumerable Transpiler(IEnumerable instructions)
+ {
+ List ins = instructions.ToList();
+ for (int i = 0; i < ins.Count; i++)
+ {
+
+ Type[] type = new Type[] { typeof(Mesh), typeof(Vector3), typeof(Quaternion), typeof(Material), typeof(bool) };
+
+
+ if (ins[i].OperandIs(AccessTools.Method(typeof(GenDraw), "DrawMeshNowOrLater", type)))
+ {
+
+ yield return new CodeInstruction(OpCodes.Ldloc, (object)7); //graphic
+ yield return new CodeInstruction(OpCodes.Ldloc, (object)4); //bodyAddon
+ yield return new CodeInstruction(OpCodes.Ldloc, (object)5); //offsetVector/AddonOffset (v)
+ yield return new CodeInstruction(OpCodes.Ldarg, (object)2); //headOffset
+ yield return new CodeInstruction(OpCodes.Ldarg, (object)3); //pawn
+ yield return new CodeInstruction(OpCodes.Ldarg, (object)0); //renderflags
+ yield return new CodeInstruction(OpCodes.Ldarg, (object)1); //vector
+ yield return new CodeInstruction(OpCodes.Ldarg, (object)5); //rotation
+
+ yield return new CodeInstruction(OpCodes.Call, AccessTools.DeclaredMethod(typeof(HarmonyPatch_AlienRace), "RenderHeadAddonInAnimation"));
+
+ }
+
+ else
+ {
+ yield return ins[i];
+ }
+ }
+ }
+
+ public static bool Prefix(PawnRenderFlags renderFlags, ref Vector3 vector, ref Vector3 headOffset, Pawn pawn, ref Quaternion quat, ref Rot4 rotation)
+ {
+ if(pawn == null)
+ {
+ return true;
+ }
+
+ CompBodyAnimator anim = pawn.TryGetComp();
+
+ if(anim == null)
+ {
+ return true;
+ }
+
+ if (anim != null && !renderFlags.FlagSet(PawnRenderFlags.Portrait) && anim.isAnimating)
+ {
+ //quat = Quaternion.AngleAxis(anim.bodyAngle, Vector3.up);
+ }
+
+ return true;
+
+ }
+ }
+
+
+ */
+
+}
+
+
diff --git a/Source/Patches/HarmonyPatch_CSL.cs b/1.3/Source/Patches/OtherModPatches/HarmonyPatch_CSL.cs
similarity index 100%
rename from Source/Patches/HarmonyPatch_CSL.cs
rename to 1.3/Source/Patches/OtherModPatches/HarmonyPatch_CSL.cs
diff --git a/Source/Patches/HarmonyPatch_DontShaveYourHead.cs b/1.3/Source/Patches/OtherModPatches/HarmonyPatch_DontShaveYourHead.cs
similarity index 71%
rename from Source/Patches/HarmonyPatch_DontShaveYourHead.cs
rename to 1.3/Source/Patches/OtherModPatches/HarmonyPatch_DontShaveYourHead.cs
index fa5a5cc..3cb2a63 100644
--- a/Source/Patches/HarmonyPatch_DontShaveYourHead.cs
+++ b/1.3/Source/Patches/OtherModPatches/HarmonyPatch_DontShaveYourHead.cs
@@ -17,7 +17,7 @@ namespace Rimworld_Animations {
((Action)(() =>
{
if (LoadedModManager.RunningModsListForReading.Any(x => x.Name == "Don't Shave Your Head 1.0")) {
- (new Harmony("rjw")).Patch(AccessTools.Method(AccessTools.TypeByName("DontShaveYourHead.Harmony_PawnRenderer"), "DrawHairReroute"), //typeof(ShowHair.Patch_PawnRenderer_RenderPawnInternal), nameof(ShowHair.Patch_PawnRenderer_RenderPawnInternal.Postfix)),
+ (new Harmony("rjwanim")).Patch(AccessTools.Method(AccessTools.TypeByName("DontShaveYourHead.Harmony_PawnRenderer"), "DrawHairReroute"), //typeof(ShowHair.Patch_PawnRenderer_RenderPawnInternal), nameof(ShowHair.Patch_PawnRenderer_RenderPawnInternal.Postfix)),
transpiler: new HarmonyMethod(AccessTools.Method(typeof(Patch_ShowHairWithHats), "Transpiler")));
}
}))();
diff --git a/Source/Patches/HarmonyPatch_FacialAnimation.cs b/1.3/Source/Patches/OtherModPatches/HarmonyPatch_FacialAnimation.cs
similarity index 77%
rename from Source/Patches/HarmonyPatch_FacialAnimation.cs
rename to 1.3/Source/Patches/OtherModPatches/HarmonyPatch_FacialAnimation.cs
index 6d561de..83ffd5b 100644
--- a/Source/Patches/HarmonyPatch_FacialAnimation.cs
+++ b/1.3/Source/Patches/OtherModPatches/HarmonyPatch_FacialAnimation.cs
@@ -18,15 +18,8 @@ namespace Rimworld_Animations {
try {
((Action)(() => {
if (LoadedModManager.RunningModsListForReading.Any(x => x.Name == "[NL] Facial Animation - WIP")) {
- (new Harmony("rjw")).Patch(AccessTools.Method(AccessTools.TypeByName("FacialAnimation.DrawFaceGraphicsComp"), "DrawGraphics"),
+ (new Harmony("rjwanim")).Patch(AccessTools.Method(AccessTools.TypeByName("FacialAnimation.DrawFaceGraphicsComp"), "DrawGraphics"),
prefix: new HarmonyMethod(AccessTools.Method(typeof(Patch_FacialAnimation), "Prefix")));
-
-
- (new Harmony("rjw")).Patch(AccessTools.Method(AccessTools.TypeByName("FacialAnimation.FaceAnimationDef"), "IsSame", new Type[] { typeof(JobDef) }),
- prefix: new HarmonyMethod(AccessTools.Method(typeof(Patch_FacialAnimation), "Prefix_IsSameA")));
-
- (new Harmony("rjw")).Patch(AccessTools.Method(AccessTools.TypeByName("FacialAnimation.FaceAnimationDef"), "IsSame", new Type[] { typeof(string) }),
- prefix: new HarmonyMethod(AccessTools.Method(typeof(Patch_FacialAnimation), "Prefix_IsSameB")));
}
}))();
}
@@ -48,7 +41,7 @@ namespace Rimworld_Animations {
return true;
}
-
+ /*
public static List rjwLovinDefNames = new List{
"Lovin",
"Quickie",
@@ -72,6 +65,11 @@ namespace Rimworld_Animations {
"UseFM"
};
+ public static List rjwRapeDefNames = new List {
+ "RapeComfortPawn",
+ "RandomRape",
+ "RapeEnemy"
+ };
public static bool Prefix_IsSameA(JobDef job, string ___jobDef, ref bool __result) {
@@ -79,6 +77,11 @@ namespace Rimworld_Animations {
__result = true;
return false;
}
+ else if (___jobDef != null && ___jobDef == "Wait_Combat" && job?.defName != null && rjwRapeDefNames.Contains(job?.defName)) {
+ __result = true;
+ return false;
+ }
+
return true;
}
@@ -89,8 +92,13 @@ namespace Rimworld_Animations {
__result = true;
return false;
}
+ if (___jobDef != null && ___jobDef == "Wait_Combat" && jobName != null && rjwRapeDefNames.Contains(jobName)) {
+ __result = true;
+ return false;
+ }
return true;
}
+ */
}
-}
+}
\ No newline at end of file
diff --git a/1.3/Source/Patches/OtherModPatches/HarmonyPatch_HatsDisplaySelection.cs b/1.3/Source/Patches/OtherModPatches/HarmonyPatch_HatsDisplaySelection.cs
new file mode 100644
index 0000000..1cd5707
--- /dev/null
+++ b/1.3/Source/Patches/OtherModPatches/HarmonyPatch_HatsDisplaySelection.cs
@@ -0,0 +1,77 @@
+/*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 {
+ public static class HarmonyPatch_HatsDisplaySelection {
+
+ public static void PatchHatsDisplaySelectionArgs() {
+ (new Harmony("rjw")).Patch(AccessTools.Method(AccessTools.TypeByName("HatDisplaySelection.Patch"), "DrawHatCEWithHair"),
+ transpiler: new HarmonyMethod(AccessTools.Method(typeof(HarmonyPatch_HatsDisplaySelection), "ReplaceDrawMeshOrLaterWithAnimate")));
+
+ (new Harmony("rjw")).Patch(AccessTools.Method(AccessTools.TypeByName("HatDisplaySelection.Patch"), "DrawHatWithHair"),
+ transpiler: new HarmonyMethod(AccessTools.Method(typeof(HarmonyPatch_HatsDisplaySelection), "ReplaceDrawMeshOrLaterWithAnimate")));
+
+ (new Harmony("rjw")).Patch(AccessTools.Method(AccessTools.TypeByName("HatDisplaySelection.Patch"), "DrawHeadApparelWithHair"),
+ prefix: new HarmonyMethod(AccessTools.Method(typeof(HarmonyPatch_HatsDisplaySelection), "PrefixPatchForDrawHeadApparelWithHair")));
+
+
+ }
+
+ public static void PrefixPatchForDrawHeadApparelWithHair(PawnRenderer renderer, ref Vector3 rootLoc, ref float angle, bool renderBody, ref Rot4 bodyFacing, ref Rot4 headFacing, RotDrawMode bodyDrawType, bool portrait, bool headStump, bool invisible)
+ {
+ PawnGraphicSet graphics = renderer.graphics;
+ Pawn pawn = graphics.pawn;
+ CompBodyAnimator bodyAnim = pawn.TryGetComp();
+
+ if (!graphics.AllResolved)
+ {
+ graphics.ResolveAllGraphics();
+ }
+
+
+ if (bodyAnim != null && bodyAnim.isAnimating && !portrait && pawn.Map == Find.CurrentMap)
+ {
+ bodyAnim.tickGraphics(graphics);
+ bodyAnim.animatePawn(ref rootLoc, ref angle, ref bodyFacing, ref headFacing);
+
+ }
+ }
+
+
+ public static IEnumerable ReplaceDrawMeshOrLaterWithAnimate(IEnumerable instructions) {
+
+ MethodInfo drawMeshNowOrLater = AccessTools.Method(typeof(GenDraw), "DrawMeshNowOrLater");
+ List codes = instructions.ToList();
+ for (int i = 0; i < instructions.Count(); i++) {
+
+
+ if (codes[i].
+
+
+(drawMeshNowOrLater)) {
+
+ yield return new CodeInstruction(OpCodes.Ldarg_0);
+ yield return new CodeInstruction(OpCodes.Ldfld, AccessTools.DeclaredField(AccessTools.TypeByName("HatDisplaySelection.Patch"), "pawn"));
+ yield return new CodeInstruction(OpCodes.Call, AccessTools.DeclaredMethod(typeof(AnimationUtility), nameof(AnimationUtility.RenderPawnHeadMeshInAnimation), new Type[] { typeof(Mesh), typeof(Vector3), typeof(Quaternion), typeof(Material), typeof(bool), typeof(Pawn) }));
+
+ }
+ else {
+ yield return codes[i];
+ }
+
+ }
+
+ }
+
+ }
+}
+*/
\ No newline at end of file
diff --git a/Source/Patches/HarmonyPatch_ShowHairWithHats.cs b/1.3/Source/Patches/OtherModPatches/HarmonyPatch_ShowHairWithHats.cs
similarity index 86%
rename from Source/Patches/HarmonyPatch_ShowHairWithHats.cs
rename to 1.3/Source/Patches/OtherModPatches/HarmonyPatch_ShowHairWithHats.cs
index 3714503..a42ab7d 100644
--- a/Source/Patches/HarmonyPatch_ShowHairWithHats.cs
+++ b/1.3/Source/Patches/OtherModPatches/HarmonyPatch_ShowHairWithHats.cs
@@ -18,7 +18,7 @@ namespace Rimworld_Animations {
((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)),
+ (new Harmony("rjwanim")).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")));
}
}))();
diff --git a/1.3/Source/Patches/RJWPatches/HarmonyPatch_PlaySexSounds.cs b/1.3/Source/Patches/RJWPatches/HarmonyPatch_PlaySexSounds.cs
new file mode 100644
index 0000000..6544f13
--- /dev/null
+++ b/1.3/Source/Patches/RJWPatches/HarmonyPatch_PlaySexSounds.cs
@@ -0,0 +1,25 @@
+using HarmonyLib;
+using rjw;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Verse;
+
+namespace Rimworld_Animations
+{
+ [HarmonyPatch(typeof(JobDriver_Sex), "PlaySexSound")]
+ class HarmonyPatch_PlaySexSounds
+ {
+ public static bool Prefix(JobDriver_Sex __instance)
+ {
+ if (__instance.pawn.TryGetComp().isAnimating)
+ {
+ return false;
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/1.3/Source/Patches/RJWPatches/HarmonyPatch_SexTick.cs b/1.3/Source/Patches/RJWPatches/HarmonyPatch_SexTick.cs
new file mode 100644
index 0000000..9ba03b2
--- /dev/null
+++ b/1.3/Source/Patches/RJWPatches/HarmonyPatch_SexTick.cs
@@ -0,0 +1,61 @@
+using HarmonyLib;
+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
+{
+ [HarmonyPatch(typeof(JobDriver_Sex), "SexTick")]
+ public class HarmonyPatch_SexTick
+ {
+ public static bool Prefix(JobDriver_Sex __instance, Pawn pawn, Thing target)
+ {
+
+ if ((target is Pawn) &&
+ !(
+ (target as Pawn)?.jobs?.curDriver is JobDriver_SexBaseReciever
+ &&
+ ((target as Pawn).jobs.curDriver as JobDriver_SexBaseReciever).parteners.Any()
+ &&
+ ((target as Pawn).jobs.curDriver as JobDriver_SexBaseReciever).parteners[0] == pawn))
+ {
+
+ __instance.ticks_left--;
+ __instance.sex_ticks--;
+ __instance.Orgasm();
+
+
+ if (pawn.IsHashIntervalTick(__instance.ticks_between_thrusts))
+ {
+ __instance.ChangePsyfocus(pawn, target);
+ __instance.Animate(pawn, target);
+ __instance.PlaySexSound();
+ if (!__instance.Sexprops.isRape)
+ {
+ pawn.GainComfortFromCellIfPossible(false);
+ if (target is Pawn)
+ {
+ (target as Pawn).GainComfortFromCellIfPossible(false);
+ }
+ }
+ if(!__instance.isEndytophile)
+ {
+ SexUtility.DrawNude(pawn, false);
+ }
+ }
+
+ return false;
+ }
+
+ return true;
+ }
+
+ }
+
+}
diff --git a/Source/Patches/rjwPatches/HarmonyPatch_WorkGiverSex.cs b/1.3/Source/Patches/RJWPatches/HarmonyPatch_WorkGiverSex.cs
similarity index 98%
rename from Source/Patches/rjwPatches/HarmonyPatch_WorkGiverSex.cs
rename to 1.3/Source/Patches/RJWPatches/HarmonyPatch_WorkGiverSex.cs
index 5b7479f..af4a755 100644
--- a/Source/Patches/rjwPatches/HarmonyPatch_WorkGiverSex.cs
+++ b/1.3/Source/Patches/RJWPatches/HarmonyPatch_WorkGiverSex.cs
@@ -10,7 +10,7 @@ using RimWorld;
using Verse.AI;
namespace Rimworld_Animations {
-
+ /*
[HarmonyPatch(typeof(WorkGiver_Sex), "JobOnThing")]
public static class HarmonyPatch_WorkGiverSex {
@@ -26,4 +26,6 @@ namespace Rimworld_Animations {
}
}
+
+ */
}
diff --git a/1.3/Source/Patches/RJWPatches/JobDrivers/HarmonyPatch_JobDriver_JoinInBed.cs b/1.3/Source/Patches/RJWPatches/JobDrivers/HarmonyPatch_JobDriver_JoinInBed.cs
new file mode 100644
index 0000000..18c955e
--- /dev/null
+++ b/1.3/Source/Patches/RJWPatches/JobDrivers/HarmonyPatch_JobDriver_JoinInBed.cs
@@ -0,0 +1,84 @@
+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 System.Reflection.Emit;
+using Verse.AI;
+
+namespace Rimworld_Animations
+{
+
+ [HarmonyPatch(typeof(Bed_Utility), "in_same_bed")]
+ public static class HarmonyPatch_JobDriver_InSameBedPatch
+ {
+
+ public static bool Prefix(Pawn partner, ref bool __result)
+ {
+
+ if(partner != null && partner.CurJobDef == xxx.casual_sex)
+ {
+ __result = true;
+ return false;
+ }
+
+ return true;
+
+ }
+
+
+
+ }
+
+ [HarmonyPatch(typeof(JobDriver_JoinInBed), "MakeNewToils")]
+ public static class HarmonyPatch_JobDriver_JoinInBed
+ {
+
+ public static void Postfix(JobDriver_JoinInBed __instance, ref IEnumerable __result)
+ {
+
+ var toils = __result.ToList();
+
+ Toil goToPawnInBed = Toils_Goto.GotoThing(__instance.iTarget, PathEndMode.OnCell);
+ goToPawnInBed.FailOn(() => !RestUtility.InBed(__instance.Partner) && __instance.Partner.CurJobDef != xxx.gettin_loved && !Bed_Utility.in_same_bed(__instance.Partner, __instance.pawn));
+
+ toils[1] = goToPawnInBed;
+
+
+ Toil startPartnerSex = new Toil();
+ startPartnerSex.initAction = delegate {
+
+
+ if (!(__instance.Partner.jobs.curDriver is JobDriver_SexBaseReciever)) // allows threesomes
+ {
+ Job gettinLovedJob = JobMaker.MakeJob(xxx.gettin_loved, __instance.pawn, __instance.Bed); // new gettin loved toil that wakes up the pawn goes here
+ __instance.Partner.jobs.jobQueue.EnqueueFirst(gettinLovedJob);
+ __instance.Partner.jobs.EndCurrentJob(JobCondition.InterruptForced);
+ }
+
+ };
+
+ toils[2] = startPartnerSex;
+
+ toils[3].AddPreTickAction(() =>
+ {
+ if (!__instance.Partner.TryGetComp().isAnimating)
+ {
+ __instance.pawn.TryGetComp().isAnimating = false;
+ }
+ });
+
+
+ __result = toils.AsEnumerable();
+
+
+ }
+
+
+
+ }
+}
diff --git a/Source/Patches/rjwPatches/HarmonyPatch_JobDriver_SexBaseInitiator.cs b/1.3/Source/Patches/RJWPatches/JobDrivers/HarmonyPatch_JobDriver_SexBaseInitiator.cs
similarity index 63%
rename from Source/Patches/rjwPatches/HarmonyPatch_JobDriver_SexBaseInitiator.cs
rename to 1.3/Source/Patches/RJWPatches/JobDrivers/HarmonyPatch_JobDriver_SexBaseInitiator.cs
index 04cdef2..260d924 100644
--- a/Source/Patches/rjwPatches/HarmonyPatch_JobDriver_SexBaseInitiator.cs
+++ b/1.3/Source/Patches/RJWPatches/JobDrivers/HarmonyPatch_JobDriver_SexBaseInitiator.cs
@@ -13,7 +13,6 @@ namespace Rimworld_Animations {
[HarmonyPatch(typeof(JobDriver_SexBaseInitiator), "Start")]
static class HarmonyPatch_JobDriver_SexBaseInitiator_Start {
public static void Postfix(ref JobDriver_SexBaseInitiator __instance) {
-
/*
These particular jobs need special code
don't play anim for now
@@ -22,49 +21,49 @@ namespace Rimworld_Animations {
return;
}
+ if(!AnimationSettings.PlayAnimForNonsexualActs && NonSexualAct(__instance))
+ {
+ return;
+ }
+
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;
- }
- else if (__instance is JobDriver_Masturbate)
- bed = (__instance as JobDriver_Masturbate).Bed;
- else if (__instance is JobDriver_Rape)
- bed = (__instance?.Partner?.jobs?.curDriver as JobDriver_Sex)?.Bed;
-
- */
-
if ((__instance.Target as Pawn)?.jobs?.curDriver is JobDriver_SexBaseReciever) {
Pawn Target = __instance.Target as Pawn;
- if (!(Target.jobs.curDriver as JobDriver_SexBaseReciever).parteners.Contains(pawn)) {
- (Target.jobs.curDriver as JobDriver_SexBaseReciever).parteners.Add(pawn);
- }
-
bool quickie = (__instance is JobDriver_SexQuick) && AnimationSettings.fastAnimForQuickie;
+ int preAnimDuration = __instance.duration;
+ int AnimationTimeTicks = 0;
+
+
if (bed != null) {
- RerollAnimations(Target, __instance.duration, bed as Thing, __instance.sexType, quickie, sexProps: __instance.Sexprops);
- }
+ RerollAnimations(Target, out AnimationTimeTicks, bed as Thing, __instance.Sexprops.sexType, quickie, sexProps: __instance.Sexprops);
+ }
else {
- RerollAnimations(Target, __instance.duration, sexType: __instance.sexType, fastAnimForQuickie: quickie, sexProps: __instance.Sexprops);
+ RerollAnimations(Target, out AnimationTimeTicks, sexType: __instance.Sexprops.sexType, fastAnimForQuickie: quickie, sexProps: __instance.Sexprops);
}
+
+
+ //Modify Orgasm ticks to only orgasm as many times as RJW stock orgasm allows
+ if(AnimationTimeTicks != 0)
+ {
+ __instance.orgasmstick = preAnimDuration * __instance.orgasmstick / AnimationTimeTicks;
+ }
+
+
}
}
- public static void RerollAnimations(Pawn pawn, int duration, Thing bed = null, xxx.rjwSextype sexType = xxx.rjwSextype.None, bool fastAnimForQuickie = false, rjw.SexProps sexProps = null) {
+ public static void RerollAnimations(Pawn pawn, out int AnimationTimeTicks, Thing bed = null, xxx.rjwSextype sexType = xxx.rjwSextype.None, bool fastAnimForQuickie = false, rjw.SexProps sexProps = null) {
+
+ AnimationTimeTicks = 0;
if(pawn == null || !(pawn.jobs?.curDriver is JobDriver_SexBaseReciever)) {
- Log.Message("Error: Tried to reroll animations when pawn isn't sexing");
+ Log.Error("Error: Tried to reroll animations when pawn isn't sexing");
return;
}
@@ -74,15 +73,26 @@ namespace Rimworld_Animations {
pawnsToAnimate = pawnsToAnimate.Append(pawn).ToList();
}
+ for(int i = 0; i < pawnsToAnimate.Count; i++) {
+
+ if(pawnsToAnimate[i].TryGetComp() == null) {
+ Log.Error("Error: " + pawnsToAnimate[i].Name + " of race " + pawnsToAnimate[i].def.defName + " does not have CompBodyAnimator attached!");
+ break;
+ }
+ }
+
AnimationDef anim = AnimationUtility.tryFindAnimation(ref pawnsToAnimate, sexType, sexProps);
if (anim != null) {
bool mirror = GenTicks.TicksGame % 2 == 0;
- Log.Message("Now playing " + anim.defName + (mirror ? " mirrored" : ""));
-
IntVec3 pos = pawn.Position;
+
+ for (int i = 0; i < anim.actors.Count; i++)
+ {
+ pawnsToAnimate[i].TryGetComp().isAnimating = false;
+ }
for (int i = 0; i < pawnsToAnimate.Count; i++) {
@@ -94,11 +104,16 @@ namespace Rimworld_Animations {
}
bool shiver = pawnsToAnimate[i].jobs.curDriver is JobDriver_SexBaseRecieverRaped;
- pawnsToAnimate[i].TryGetComp().StartAnimation(anim, i, mirror, shiver, fastAnimForQuickie);
- (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;
+ pawnsToAnimate[i].TryGetComp().StartAnimation(anim, pawnsToAnimate, i, mirror, shiver, fastAnimForQuickie);
+
+ int animTicks = anim.animationTimeTicks - (fastAnimForQuickie ? anim.animationStages[0].playTimeTicks : 0);
+ (pawnsToAnimate[i].jobs.curDriver as JobDriver_Sex).ticks_left = animTicks;
+ (pawnsToAnimate[i].jobs.curDriver as JobDriver_Sex).sex_ticks = animTicks;
+ (pawnsToAnimate[i].jobs.curDriver as JobDriver_Sex).duration = animTicks;
+
+
+ AnimationTimeTicks = animTicks;
+
if(!AnimationSettings.hearts) {
(pawnsToAnimate[i].jobs.curDriver as JobDriver_Sex).ticks_between_hearts = Int32.MaxValue;
}
@@ -106,16 +121,35 @@ namespace Rimworld_Animations {
}
}
else {
- Log.Message("Anim not found");
+ Log.Message("No animation found");
+
+ /*
+
//if pawn isn't already animating,
if (!pawn.TryGetComp().isAnimating) {
(pawn.jobs.curDriver as JobDriver_SexBaseReciever).increase_time(duration);
//they'll just do the thrusting anim
}
+
+ */
}
-
-
}
+
+
+ static IEnumerable NonSexActRulePackDefNames = new String[]
+ {
+ "MutualHandholdingRP",
+ "MutualMakeoutRP",
+ };
+
+ public static bool NonSexualAct(JobDriver_SexBaseInitiator sexBaseInitiator)
+ {
+ if(NonSexActRulePackDefNames.Contains(sexBaseInitiator.Sexprops.rulePack))
+ {
+ return true;
+ }
+ return false;
+ }
}
[HarmonyPatch(typeof(JobDriver_SexBaseInitiator), "End")]
diff --git a/1.3/Source/Patches/RJWPatches/JobDrivers/HarmonyPatch_JobDriver_SexBaseReceiverLoved.cs b/1.3/Source/Patches/RJWPatches/JobDrivers/HarmonyPatch_JobDriver_SexBaseReceiverLoved.cs
new file mode 100644
index 0000000..d328d2b
--- /dev/null
+++ b/1.3/Source/Patches/RJWPatches/JobDrivers/HarmonyPatch_JobDriver_SexBaseReceiverLoved.cs
@@ -0,0 +1,40 @@
+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 System.Reflection.Emit;
+
+namespace Rimworld_Animations
+{
+
+ [HarmonyPatch(typeof(JobDriver_SexBaseRecieverLoved), "MakeSexToil")]
+ public static class HarmonyPatch_JobDriver_SexBaseReceiverLoved
+ {
+
+ public static IEnumerable Transpiler(IEnumerable codeInstructions)
+ {
+
+ var ins = codeInstructions.ToList();
+ for(int i = 0; i < ins.Count; i++)
+ {
+ if(i + 13 < ins.Count && ins[i + 13].opcode == OpCodes.Call && ins[i + 13].OperandIs(AccessTools.DeclaredMethod(typeof(Toils_LayDown), "LayDown"))) {
+
+ ins.RemoveRange(i, 14);
+
+ }
+
+ else
+ {
+ yield return ins[i];
+ }
+ }
+
+ }
+
+ }
+}
diff --git a/1.3/Source/Patches/RimworldPatches/HarmonyPatch_HeadHair.cs b/1.3/Source/Patches/RimworldPatches/HarmonyPatch_HeadHair.cs
new file mode 100644
index 0000000..37ba6ce
--- /dev/null
+++ b/1.3/Source/Patches/RimworldPatches/HarmonyPatch_HeadHair.cs
@@ -0,0 +1,22 @@
+using HarmonyLib;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Verse;
+using RimWorld;
+using UnityEngine;
+
+namespace Rimworld_Animations
+{
+ [HarmonyPatch(typeof(PawnRenderer), "DrawHeadHair")]
+ public static class HarmonyPatch_HeadHair
+ {
+ public static void Prefix(ref Vector3 headOffset, ref float angle)
+ {
+
+ }
+
+ }
+}
diff --git a/1.3/Source/Patches/RimworldPatches/HarmonyPatch_PawnRenderer.cs b/1.3/Source/Patches/RimworldPatches/HarmonyPatch_PawnRenderer.cs
new file mode 100644
index 0000000..218e45b
--- /dev/null
+++ b/1.3/Source/Patches/RimworldPatches/HarmonyPatch_PawnRenderer.cs
@@ -0,0 +1,84 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+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(RotDrawMode),
+ typeof(PawnRenderFlags)
+ }
+ )]
+ 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, RotDrawMode bodyDrawType, PawnRenderFlags flags)
+ {
+
+ if (flags.FlagSet(PawnRenderFlags.Portrait)) return;
+
+ PawnGraphicSet graphics = __instance.graphics;
+ Pawn pawn = graphics.pawn;
+ CompBodyAnimator bodyAnim = pawn.TryGetComp();
+
+
+ if (bodyAnim != null && bodyAnim.isAnimating && pawn.Map == Find.CurrentMap)
+ {
+ bodyAnim.animatePawnBody(ref rootLoc, ref angle, ref bodyFacing);
+
+ }
+
+ }
+
+ public static IEnumerable Transpiler(IEnumerable instructions)
+ {
+ List ins = instructions.ToList();
+
+ for(int i = 0; i < instructions.Count(); i++)
+ {
+
+ if (i - 3 >= 0 && ins[i - 3].opcode == OpCodes.Call && ins[i - 3].operand != null && ins[i - 3].OperandIs(AccessTools.DeclaredMethod(typeof(PawnRenderer), "BaseHeadOffsetAt")))
+ {
+
+ yield return new CodeInstruction(OpCodes.Ldloca, (object)0);
+ yield return new CodeInstruction(OpCodes.Ldloca, (object)7);
+ yield return new CodeInstruction(OpCodes.Ldloca, (object)6);
+ yield return new CodeInstruction(OpCodes.Ldarga, (object)2);
+ yield return new CodeInstruction(OpCodes.Ldarg_0);
+ yield return new CodeInstruction(OpCodes.Ldfld, AccessTools.DeclaredField(typeof(PawnRenderer), "pawn"));
+ yield return new CodeInstruction(OpCodes.Ldarg, (object)6);
+ yield return new CodeInstruction(OpCodes.Call, AccessTools.DeclaredMethod(typeof(AnimationUtility), "AdjustHead"));
+ yield return ins[i];
+ //headFacing equals true
+ }
+
+ // Fixes the offsets for eye implants and wounds on the head during animations
+ else if (ins[i].opcode == OpCodes.Callvirt && ins[i].operand != null && ins[i].OperandIs(AccessTools.DeclaredMethod(typeof(PawnWoundDrawer), "RenderOverBody")))
+ {
+ // Pass some additional info to a new overload of RenderOverBody
+ yield return new CodeInstruction(OpCodes.Ldarg_0);
+ yield return new CodeInstruction(OpCodes.Ldfld, AccessTools.DeclaredField(typeof(PawnRenderer), "pawn"));
+ yield return new CodeInstruction(OpCodes.Ldarg_S, (object)6); // renderer flags
+ yield return new CodeInstruction(OpCodes.Call, AccessTools.DeclaredMethod(typeof(PawnWoundDrawerExtension), "RenderOverBody"));
+ }
+
+ else
+ {
+ yield return ins[i];
+ }
+ }
+ }
+ }
+}
diff --git a/Source/Patches/HarmonyPatch_PawnRotation.cs b/1.3/Source/Patches/RimworldPatches/HarmonyPatch_PawnRotation.cs
similarity index 99%
rename from Source/Patches/HarmonyPatch_PawnRotation.cs
rename to 1.3/Source/Patches/RimworldPatches/HarmonyPatch_PawnRotation.cs
index 9fb95ef..7ec75a1 100644
--- a/Source/Patches/HarmonyPatch_PawnRotation.cs
+++ b/1.3/Source/Patches/RimworldPatches/HarmonyPatch_PawnRotation.cs
@@ -25,4 +25,5 @@ namespace Rimworld_Animations {
}
}
+
}
diff --git a/Source/Patches/HarmonyPatch_Pawn_DrawTracker.cs b/1.3/Source/Patches/RimworldPatches/HarmonyPatch_Pawn_DrawTracker.cs
similarity index 100%
rename from Source/Patches/HarmonyPatch_Pawn_DrawTracker.cs
rename to 1.3/Source/Patches/RimworldPatches/HarmonyPatch_Pawn_DrawTracker.cs
diff --git a/1.3/Source/Patches/RimworldPatches/HarmonyPatch_SetPawnAnimatable.cs b/1.3/Source/Patches/RimworldPatches/HarmonyPatch_SetPawnAnimatable.cs
new file mode 100644
index 0000000..b8c66b8
--- /dev/null
+++ b/1.3/Source/Patches/RimworldPatches/HarmonyPatch_SetPawnAnimatable.cs
@@ -0,0 +1,40 @@
+using HarmonyLib;
+using RimWorld;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection.Emit;
+using System.Text;
+using System.Threading.Tasks;
+using UnityEngine;
+using Verse;
+
+namespace Rimworld_Animations
+{
+ [HarmonyPatch(typeof(PawnRenderer), "RenderPawnAt")]
+ public static class PawnRenderer_RenderPawnAt_Patch
+ {
+ static bool ClearCache(Pawn pawn)
+ {
+ return pawn.IsInvisible() || (pawn.TryGetComp() != null && pawn.TryGetComp().isAnimating);
+ }
+
+ public static IEnumerable Transpiler(IEnumerable instructions)
+ {
+ var list = instructions.ToList();
+
+ foreach (CodeInstruction i in instructions)
+ {
+ if (i.OperandIs(AccessTools.Method(typeof(PawnUtility), "IsInvisible")))
+ {
+ yield return new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(PawnRenderer_RenderPawnAt_Patch), "ClearCache"));
+ }
+ else
+ {
+ yield return i;
+ }
+ }
+ }
+ }
+
+}
diff --git a/1.3/Source/Patches/RimworldPatches/HarmonyPatch_Thing.cs b/1.3/Source/Patches/RimworldPatches/HarmonyPatch_Thing.cs
new file mode 100644
index 0000000..9477abf
--- /dev/null
+++ b/1.3/Source/Patches/RimworldPatches/HarmonyPatch_Thing.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using HarmonyLib;
+using RimWorld;
+using Verse;
+
+namespace Rimworld_Animations
+{
+ [HarmonyPatch(typeof(Thing), "DrawAt")]
+ public static class HarmonyPatch_Thing
+ {
+
+ public static bool Prefix(Thing __instance)
+ {
+ CompThingAnimator thingAnimator = __instance.TryGetComp();
+ if (thingAnimator != null && thingAnimator.isAnimating)
+ {
+ thingAnimator.AnimateThing(__instance);
+ return false;
+
+ }
+
+ return true;
+
+ }
+
+ }
+}
diff --git a/Source/Settings/AnimationSettings.cs b/1.3/Source/Settings/AnimationSettings.cs
similarity index 64%
rename from Source/Settings/AnimationSettings.cs
rename to 1.3/Source/Settings/AnimationSettings.cs
index 75308b8..0a96621 100644
--- a/Source/Settings/AnimationSettings.cs
+++ b/1.3/Source/Settings/AnimationSettings.cs
@@ -11,8 +11,9 @@ namespace Rimworld_Animations {
public class AnimationSettings : ModSettings {
- public static bool orgasmQuiver, rapeShiver, soundOverride = true, hearts = true, controlGenitalRotation = false, applySemenOnAnimationOrgasm = false, fastAnimForQuickie = false;
- public static bool offsetTab = false;
+ public static bool orgasmQuiver, rapeShiver, soundOverride = true, hearts = true, controlGenitalRotation = false, applySemenOnAnimationOrgasm = false, fastAnimForQuickie = false,
+ PlayAnimForNonsexualActs = true;
+ public static bool offsetTab = false, debugMode = false;
public static float shiverIntensity = 2f;
public static Dictionary offsets = new Dictionary();
@@ -22,19 +23,21 @@ namespace Rimworld_Animations {
base.ExposeData();
- Scribe_Values.Look(ref offsetTab, "EnableOffsetTab", false);
- Scribe_Values.Look(ref controlGenitalRotation, "controlGenitalRotation", false);
- Scribe_Values.Look(ref orgasmQuiver, "orgasmQuiver");
- Scribe_Values.Look(ref fastAnimForQuickie, "fastAnimForQuickie");
- Scribe_Values.Look(ref rapeShiver, "rapeShiver");
- Scribe_Values.Look(ref hearts, "heartsOnLovin");
- Scribe_Values.Look(ref applySemenOnAnimationOrgasm, "applySemenOnOrgasm", false);
- Scribe_Values.Look(ref soundOverride, "rjwAnimSoundOverride", true);
- Scribe_Values.Look(ref shiverIntensity, "shiverIntensity", 2f);
+ Scribe_Values.Look(ref debugMode, "RJWAnimations-AnimsDebugMode", false);
+ Scribe_Values.Look(ref offsetTab, "RJWAnimations-EnableOffsetTab", false);
+ Scribe_Values.Look(ref controlGenitalRotation, "RJWAnimations-controlGenitalRotation", false);
+ Scribe_Values.Look(ref orgasmQuiver, "RJWAnimations-orgasmQuiver");
+ Scribe_Values.Look(ref fastAnimForQuickie, "RJWAnimations-fastAnimForQuickie");
+ Scribe_Values.Look(ref rapeShiver, "RJWAnimations-rapeShiver");
+ Scribe_Values.Look(ref hearts, "RJWAnimation-sheartsOnLovin");
+ Scribe_Values.Look(ref PlayAnimForNonsexualActs, "RJWAnims-PlayAnimForNonsexualActs");
+ Scribe_Values.Look(ref applySemenOnAnimationOrgasm, "RJWAnimations-applySemenOnOrgasm", false);
+ Scribe_Values.Look(ref soundOverride, "RJWAnimations-rjwAnimSoundOverride", true);
+ Scribe_Values.Look(ref shiverIntensity, "RJWAnimations-shiverIntensity", 2f);
//todo: save offsetsByDefName
- Scribe_Collections.Look(ref offsets, "animationOffsets");
- Scribe_Collections.Look(ref rotation, "rotationOffsets");
+ Scribe_Collections.Look(ref offsets, "RJWAnimations-animationOffsets");
+ Scribe_Collections.Look(ref rotation, "RJWAnimations-rotationOffsets");
@@ -69,12 +72,14 @@ namespace Rimworld_Animations {
listingStandard.CheckboxLabeled("Enable Orgasm Quiver", ref AnimationSettings.orgasmQuiver);
listingStandard.CheckboxLabeled("Enable Rape Shiver", ref AnimationSettings.rapeShiver);
listingStandard.CheckboxLabeled("Enable hearts during lovin'", ref AnimationSettings.hearts);
-
- listingStandard.CheckboxLabeled("Enable Offset Tab", ref AnimationSettings.offsetTab);
+ listingStandard.CheckboxLabeled("Play animation for nonsexual acts (handholding, makeout)", ref AnimationSettings.PlayAnimForNonsexualActs);
+ listingStandard.CheckboxLabeled("Enable Animation Manager Tab", ref AnimationSettings.offsetTab);
listingStandard.Label("Shiver/Quiver Intensity (default 2): " + AnimationSettings.shiverIntensity);
AnimationSettings.shiverIntensity = listingStandard.Slider(AnimationSettings.shiverIntensity, 0.0f, 12f);
+ listingStandard.CheckboxLabeled("Debug Mode", ref AnimationSettings.debugMode);
+
listingStandard.End();
base.DoSettingsWindowContents(inRect);
diff --git a/1.3/Source/Utilities/AnimationUtility.cs b/1.3/Source/Utilities/AnimationUtility.cs
new file mode 100644
index 0000000..a75fc32
--- /dev/null
+++ b/1.3/Source/Utilities/AnimationUtility.cs
@@ -0,0 +1,319 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using RimWorld;
+using rjw.Modules.Interactions.Helpers;
+using rjw.Modules.Interactions.Objects;
+using UnityEngine;
+using Verse;
+using Verse.AI;
+using rjw.Modules.Interactions.Enums;
+
+namespace Rimworld_Animations {
+ public static class AnimationUtility {
+ /*
+ Note: always make the list in this order:
+ Female pawns, animal female pawns, male pawns, animal male pawns
+ */
+ public static AnimationDef tryFindAnimation(ref List participants, rjw.xxx.rjwSextype sexType = 0, rjw.SexProps sexProps = null) {
+
+
+ InteractionWithExtension interaction = InteractionHelper.GetWithExtension(sexProps.dictionaryKey);
+
+
+ if(interaction.HasInteractionTag(InteractionTag.Reverse))
+ {
+ Pawn buffer = participants[1];
+ participants[1] = participants[0];
+ participants[0] = buffer;
+ }
+
+ participants =
+ participants.OrderBy(p => p.jobs.curDriver is rjw.JobDriver_SexBaseInitiator)
+ .OrderBy(p => rjw.xxx.can_fuck(p))
+ .ToList();
+
+
+ List localParticipants = new List(participants);
+
+ IEnumerable options = DefDatabase.AllDefs.Where((AnimationDef x) => {
+
+
+ if (x.actors.Count != localParticipants.Count) {
+ return false;
+ }
+ for (int i = 0; i < x.actors.Count; i++) {
+
+ if (rjw.RJWPreferenceSettings.Malesex == rjw.RJWPreferenceSettings.AllowedSex.Nohomo) {
+ if (rjw.xxx.is_male(localParticipants[i]) && x.actors[i].isFucked) {
+ return false;
+ }
+ }
+ if (x.actors[i].requiredGender != null && !x.actors[i].requiredGender.Contains(localParticipants[i].gender.ToStringSafe()))
+ {
+ if (AnimationSettings.debugMode)
+ {
+ Log.Message(string.Concat(new string[]
+ {
+ x.defName.ToStringSafe(),
+ " not selected -- ",
+ localParticipants[i].def.defName.ToStringSafe(),
+ " ",
+ localParticipants[i].Name.ToStringSafe(),
+ " does not match required gender"
+ }));
+ }
+ return false;
+ }
+ if ((x.actors[i].blacklistedRaces != null) && x.actors[i].blacklistedRaces.Contains(localParticipants[i].def.defName)) {
+ if(AnimationSettings.debugMode)
+ Log.Message(x.defName.ToStringSafe() + " not selected -- " + localParticipants[i].def.defName.ToStringSafe() + " " + localParticipants[i].Name.ToStringSafe() + " is blacklisted");
+ return false;
+ }
+
+ if(x.actors[i].defNames.Contains("Human")) {
+ if (!rjw.xxx.is_human(localParticipants[i])) {
+ if (AnimationSettings.debugMode)
+ Log.Message(x.defName.ToStringSafe() + " not selected -- " + localParticipants[i].def.defName.ToStringSafe() + " " + localParticipants[i].Name.ToStringSafe() + " is not human");
+
+ return false;
+ }
+
+ }
+ else if (!x.actors[i].bodyDefTypes.Contains(localParticipants[i].RaceProps.body)) {
+
+ if (!x.actors[i].defNames.Contains(localParticipants[i].def.defName)) {
+
+ if (rjw.RJWSettings.DevMode) {
+ string animInfo = x.defName.ToStringSafe() + " not selected -- " + localParticipants[i].def.defName.ToStringSafe() + " " + localParticipants[i].Name.ToStringSafe() + " is not ";
+ foreach(String defname in x.actors[i].defNames) {
+ animInfo += defname + ", ";
+ }
+ if (AnimationSettings.debugMode)
+ Log.Message(animInfo);
+ }
+
+ return false;
+ }
+ }
+ //genitals checking
+
+ if(!GenitalCheckForPawn(x.actors[i].requiredGenitals, localParticipants[i], out string failReason)) {
+ Debug.Log("Didn't select " + x.defName + ", " + localParticipants[i].Name + " " + failReason);
+ return false;
+ }
+
+ //TESTING ANIMATIONS ONLY REMEMBER TO COMMENT OUT BEFORE PUSH
+ /*
+ if (x.defName != "Cunnilingus")
+ return false;
+ */
+
+
+ if (x.actors[i].isFucking && !rjw.xxx.can_fuck(localParticipants[i])) {
+ if (AnimationSettings.debugMode)
+ Log.Message(x.defName.ToStringSafe() + " not selected -- " + localParticipants[i].def.defName.ToStringSafe() + " " + localParticipants[i].Name.ToStringSafe() + " can't fuck");
+ return false;
+ }
+
+ if (x.actors[i].isFucked && !rjw.xxx.can_be_fucked(localParticipants[i])) {
+ if (AnimationSettings.debugMode)
+ Log.Message(x.defName.ToStringSafe() + " not selected -- " + localParticipants[i].def.defName.ToStringSafe() + " " + localParticipants[i].Name.ToStringSafe() + " can't be fucked");
+ return false;
+ }
+ }
+ return true;
+ });
+ List optionsWithInteractionType = options.ToList().FindAll(x => x.interactionDefTypes != null && x.interactionDefTypes.Contains(sexProps.sexType.ToStringSafe()));
+ if (optionsWithInteractionType.Any()) {
+ if (AnimationSettings.debugMode)
+ Log.Message("Selecting animation for interaction type " + sexProps.sexType.ToStringSafe() + "...");
+ return optionsWithInteractionType.RandomElement();
+ }
+ List optionsWithSexType = options.ToList().FindAll(x => x.sexTypes != null && x.sexTypes.Contains(sexType));
+ if (optionsWithSexType.Any()) {
+ if (AnimationSettings.debugMode)
+ Log.Message("Selecting animation for rjwSexType " + sexType.ToStringSafe() + "...");
+ return optionsWithSexType.RandomElement();
+ }
+
+ /*
+ if(optionsWithInitiator.Any()) {
+ if (AnimationSettings.debugMode)
+ Log.Message("Selecting animation for initiators...");
+ }
+ */
+
+ if (options != null && options.Any()) {
+ if (AnimationSettings.debugMode)
+ Log.Message("Randomly selecting animation...");
+ return options.RandomElement();
+ }
+ else
+ return null;
+ }
+
+ public static void RenderPawnHeadMeshInAnimation1(Mesh mesh, Vector3 loc, Quaternion quaternion, Material material, bool drawNow, Pawn pawn) {
+
+ if (pawn == null || pawn.Map != Find.CurrentMap) {
+ GenDraw.DrawMeshNowOrLater(mesh, loc, quaternion, material, drawNow);
+ return;
+ }
+
+ CompBodyAnimator pawnAnimator = pawn.TryGetComp();
+
+ if (pawnAnimator == null || !pawnAnimator.isAnimating) {
+ GenDraw.DrawMeshNowOrLater(mesh, loc, quaternion, material, drawNow);
+ } else {
+ Vector3 pawnHeadPosition = pawnAnimator.getPawnHeadPosition();
+ pawnHeadPosition.y = loc.y;
+ GenDraw.DrawMeshNowOrLater(MeshPool.humanlikeHeadSet.MeshAt(pawnAnimator.headFacing), pawnHeadPosition, Quaternion.AngleAxis(pawnAnimator.headAngle, Vector3.up), material, true);
+ }
+ }
+
+ public static void AdjustHead(ref Quaternion quat, ref Rot4 bodyFacing, ref Vector3 pos, ref float angle, Pawn pawn, PawnRenderFlags flags)
+ {
+ if (flags.FlagSet(PawnRenderFlags.Portrait)) return;
+
+ CompBodyAnimator anim = pawn.TryGetComp();
+ if (anim.isAnimating)
+ {
+ bodyFacing = anim.headFacing;
+ angle = anim.headAngle;
+ quat = Quaternion.AngleAxis(anim.headAngle, Vector3.up);
+ pos = anim.getPawnHeadOffset();
+
+ }
+ }
+
+ public static void RenderPawnHeadMeshInAnimation(Mesh mesh, Vector3 loc, Quaternion quaternion, Material material, bool portrait, Pawn pawn, float bodySizeFactor = 1) {
+
+ if (pawn == null) {
+ GenDraw.DrawMeshNowOrLater(mesh, loc, quaternion, material, portrait);
+ return;
+ }
+
+ CompBodyAnimator pawnAnimator = pawn.TryGetComp();
+
+ if (pawnAnimator == null || !pawnAnimator.isAnimating || portrait) {
+ GenDraw.DrawMeshNowOrLater(mesh, loc, quaternion, material, portrait);
+ }
+ else {
+ Vector3 pawnHeadPosition = pawnAnimator.getPawnHeadPosition();
+ pawnHeadPosition.x *= bodySizeFactor;
+ pawnHeadPosition.x *= bodySizeFactor;
+ pawnHeadPosition.y = loc.y;
+ GenDraw.DrawMeshNowOrLater(mesh, pawnHeadPosition, Quaternion.AngleAxis(pawnAnimator.headAngle, Vector3.up), material, portrait);
+ }
+ }
+
+ public static bool GenitalCheckForPawn(List requiredGenitals, Pawn pawn, out string failReason) {
+
+ failReason = null;
+ if (requiredGenitals != null) {
+ if (requiredGenitals.Contains("Vagina")) {
+
+ if (!rjw.Genital_Helper.has_vagina(pawn)) {
+ failReason = "missing vagina";
+ return false;
+ }
+
+ }
+
+ if (requiredGenitals.Contains("Penis")) {
+
+ if (!(rjw.Genital_Helper.has_multipenis(pawn) || rjw.Genital_Helper.has_penis_infertile(pawn) || rjw.Genital_Helper.has_penis_fertile(pawn) || rjw.Genital_Helper.has_ovipositorM(pawn) || rjw.Genital_Helper.has_ovipositorF(pawn))) {
+ failReason = "missing penis";
+ return false;
+ }
+
+ }
+
+ if (requiredGenitals.Contains("Mouth")) {
+
+ if (!rjw.Genital_Helper.has_mouth(pawn)) {
+ failReason = "missing mouth";
+ return false;
+ }
+
+ }
+
+ if (requiredGenitals.Contains("Anus")) {
+
+ if (!rjw.Genital_Helper.has_anus(pawn)) {
+ failReason = "missing anus";
+ return false;
+ }
+
+ }
+
+ if (requiredGenitals.Contains("Breasts")) {
+ if (!rjw.Genital_Helper.can_do_breastjob(pawn)) {
+ failReason = "missing breasts";
+ return false;
+ }
+ }
+
+ if (requiredGenitals.Contains("NoVagina")) {
+
+ if (rjw.Genital_Helper.has_vagina(pawn)) {
+ failReason = "has vagina";
+ return false;
+ }
+
+ }
+
+ if (requiredGenitals.Contains("NoPenis")) {
+
+ if ((rjw.Genital_Helper.has_multipenis(pawn) || rjw.Genital_Helper.has_penis_infertile(pawn) || rjw.Genital_Helper.has_penis_fertile(pawn))) {
+ failReason = "has penis";
+ return false;
+ }
+
+ }
+
+ if (requiredGenitals.Contains("NoMouth")) {
+
+ if (rjw.Genital_Helper.has_mouth(pawn)) {
+ failReason = "has mouth";
+ return false;
+ }
+
+ }
+
+ if (requiredGenitals.Contains("NoAnus")) {
+
+ if (rjw.Genital_Helper.has_anus(pawn)) {
+ failReason = "has anus";
+ return false;
+ }
+
+ }
+
+ if (requiredGenitals.Contains("NoBreasts")) {
+ if (rjw.Genital_Helper.can_do_breastjob(pawn)) {
+ failReason = "has breasts";
+ return false;
+ }
+ }
+ }
+
+ return true;
+
+ }
+
+ public static Rot4 PawnHeadRotInAnimation(Pawn pawn, Rot4 regularPos)
+ {
+ Debug.Log("Test");
+
+ if(pawn?.TryGetComp() != null && pawn.TryGetComp().isAnimating)
+ {
+ return pawn.TryGetComp().headFacing;
+ }
+
+ return regularPos;
+ }
+ }
+}
diff --git a/1.3/Source/Utilities/PatchOperationAddOrReplace.cs b/1.3/Source/Utilities/PatchOperationAddOrReplace.cs
new file mode 100644
index 0000000..4e1bd85
--- /dev/null
+++ b/1.3/Source/Utilities/PatchOperationAddOrReplace.cs
@@ -0,0 +1,59 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Xml;
+using Verse;
+
+namespace Rimworld_Animations
+{
+ public class PatchOperationAddOrReplace : PatchOperationPathed
+ {
+
+ protected string key;
+ private XmlContainer value;
+
+ protected override bool ApplyWorker(XmlDocument xml)
+ {
+ XmlNode valNode = value.node;
+ bool result = false;
+ IEnumerator enumerator = xml.SelectNodes(xpath).GetEnumerator();
+ try
+ {
+ while (enumerator.MoveNext())
+ {
+ object obj = enumerator.Current;
+ result = true;
+ XmlNode parentNode = obj as XmlNode;
+ XmlNode xmlNode = parentNode.SelectSingleNode(key);
+ if (xmlNode == null)
+ {
+ // Add - Add node if not existing
+ xmlNode = parentNode.OwnerDocument.CreateElement(key);
+ parentNode.AppendChild(xmlNode);
+ }
+ else
+ {
+ // Replace - Clear existing children
+ xmlNode.RemoveAll();
+ }
+ // (Re)add value
+ xmlNode.AppendChild(parentNode.OwnerDocument.ImportNode(valNode.FirstChild, true));
+ }
+ }
+ finally
+ {
+ IDisposable disposable = enumerator as IDisposable;
+ if (disposable != null)
+ {
+ disposable.Dispose();
+ }
+ }
+ return result;
+ }
+
+ }
+
+}
diff --git a/1.3/Textures/UI/MainTab.png b/1.3/Textures/UI/MainTab.png
new file mode 100644
index 0000000..92f855f
Binary files /dev/null and b/1.3/Textures/UI/MainTab.png differ
diff --git a/1.4/Assemblies/Rimworld-Animations.dll b/1.4/Assemblies/Rimworld-Animations.dll
new file mode 100644
index 0000000..0b959d9
Binary files /dev/null and b/1.4/Assemblies/Rimworld-Animations.dll differ
diff --git a/1.4/Defs/AnimationDefs/AnimationDefs.rar b/1.4/Defs/AnimationDefs/AnimationDefs.rar
new file mode 100644
index 0000000..e7bf2a1
Binary files /dev/null and b/1.4/Defs/AnimationDefs/AnimationDefs.rar differ
diff --git a/1.4/Defs/AnimationDefs/Animations_Beast.xml b/1.4/Defs/AnimationDefs/Animations_Beast.xml
new file mode 100644
index 0000000..30d14fc
--- /dev/null
+++ b/1.4/Defs/AnimationDefs/Animations_Beast.xml
@@ -0,0 +1,2180 @@
+
+
+
+ Dog_Doggystyle
+ dog doggystyle
+ true
+
+ Anal
+ Vaginal
+
+
+
+ VaginalBreeding
+ AnalBreeding
+
+
+
+
+
+ Human
+
+ true
+
+
+
+ Wolf_Timber
+ Wolf_Arctic
+ Whitefox
+ Warg
+ Husky
+ LabradorRetriever
+
+ AEXP_WelshTerrier
+ AEXP_Rottweiler
+ AEXP_Poodle
+ AEXP_GreatDane
+ AEXP_GermanShepherd
+ AEXP_FrenchBulldog
+ AEXP_Corgi
+ AEXP_CatAbyssinian
+ AEXP_CatBengal
+ AEXP_CatMaineCoon
+ AEXP_CatSphynx
+
+
+ QuadrupedAnimalWithHooves
+ QuadrupedAnimalWithPawsAndTail
+
+ true
+ true
+
+
+
+
+
+
+
+ Fuck
+ true
+ 765
+ 0
+
+
+ LayingPawn
+
+
+
+ 10
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+ 0
+
+
+ 6
+ 53.7
+ 5.4
+ 0.068
+ -0.038
+ 1
+ 1
+
+
+ 1
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+
+
+ 10
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+ 6
+ 53.7
+ 5.4
+ 0.068
+ -0.038
+ 1
+ 1
+
+
+ 1
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+
+
+ 10
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+ 6
+ 53.7
+ 5.4
+ 0.068
+ -0.038
+ 1
+ 1
+
+
+ 1
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+
+
+ 10
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+ 6
+ 53.7
+ 5.4
+ 0.068
+ -0.038
+ 1
+ 1
+
+
+ 1
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+
+
+ 10
+ 56.7
+ 27.5
+ 0.057
+ -0.038
+ 1
+ 2
+
+
+ 6
+ 53.7
+ 25.4
+ 0.068
+ -0.038
+ 1
+ 2
+
+
+ 1
+ 56.7
+ 27.5
+ 0.057
+ -0.038
+ 1
+ 2
+
+
+
+
+ 10
+ 56.7
+ 27.5
+ 0.057
+ -0.038
+ 1
+ 2
+
+
+ 6
+ 53.7
+ 25.4
+ 0.068
+ -0.038
+ 1
+ 2
+
+
+ 1
+ 56.7
+ 27.5
+ 0.057
+ -0.038
+ 1
+ 2
+
+
+
+
+ 10
+ 56.7
+ 27.5
+ 0.057
+ -0.038
+ 1
+ 2
+
+
+ 6
+ 53.7
+ 25.4
+ 0.068
+ -0.038
+ 1
+ 2
+
+
+ 1
+ 56.7
+ 27.5
+ 0.057
+ -0.038
+ 1
+ 2
+
+
+
+
+ 10
+ 56.7
+ 27.5
+ 0.057
+ -0.038
+ 1
+ 2
+
+
+ 6
+ 53.7
+ 25.4
+ 0.068
+ -0.038
+ 1
+ 2
+
+
+ 1
+ 56.7
+ 27.5
+ 0.057
+ -0.038
+ 1
+ 2
+
+
+
+
+
+ 10
+ 56.7
+ 27.5
+ 0.057
+ -0.038
+ 1
+ 2
+
+
+ 6
+ 53.7
+ 25.4
+ 0.068
+ -0.038
+ 1
+ 2
+
+
+ 1
+ 56.7
+ 27.5
+ 0.057
+ -0.038
+ 1
+ 2
+
+
+
+
+ 10
+ 56.7
+ 27.5
+ 0.057
+ -0.038
+ 1
+ 2
+
+
+ 6
+ 53.7
+ 25.4
+ 0.068
+ -0.038
+ 1
+ 2
+
+
+ 1
+ 56.7
+ 27.5
+ 0.057
+ -0.038
+ 1
+ 2
+
+
+
+
+ 10
+ 56.7
+ 27.5
+ 0.057
+ -0.038
+ 1
+ 2
+
+
+ 6
+ 53.7
+ 25.4
+ 0.068
+ -0.038
+ 1
+ 2
+
+
+ 1
+ 56.7
+ 27.5
+ 0.057
+ -0.038
+ 1
+ 2
+
+
+
+
+ 10
+ 56.7
+ 27.5
+ 0.057
+ -0.038
+ 1
+ 2
+
+
+ 6
+ 53.7
+ 25.4
+ 0.068
+ -0.038
+ 1
+ 2
+
+
+ 1
+ 56.7
+ 27.5
+ 0.057
+ -0.038
+ 1
+ 2
+
+
+
+
+ 10
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+ 6
+ 53.7
+ 5.4
+ 0.068
+ -0.038
+ 1
+ 1
+
+
+ 1
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+
+
+ 10
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+ 6
+ 53.7
+ 5.4
+ 0.068
+ -0.038
+ 1
+ 1
+
+
+ 1
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+
+
+ 10
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+ 6
+ 53.7
+ 5.4
+ 0.068
+ -0.038
+ 1
+ 1
+
+
+ 1
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+
+
+ 10
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+ 6
+ 53.7
+ 5.4
+ 0.068
+ -0.038
+ 1
+ 1
+
+
+ 1
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+
+ 10
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+ 6
+ 53.7
+ 5.4
+ 0.068
+ -0.038
+ 1
+ 1
+
+
+ 1
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+
+
+ 10
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+ 6
+ 53.7
+ 5.4
+ 0.068
+ -0.038
+ 1
+ 1
+
+
+ 1
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+
+
+ 10
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+ 6
+ 53.7
+ 5.4
+ 0.068
+ -0.038
+ 1
+ 1
+
+
+ 1
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+
+
+ 10
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+ 6
+ 53.7
+ 5.4
+ 0.068
+ -0.038
+ 1
+ 1
+
+
+ 1
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+
+ 10
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+ 6
+ 53.7
+ 5.4
+ 0.068
+ -0.038
+ 1
+ 1
+
+
+ 1
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+
+
+ 10
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+ 6
+ 53.7
+ 5.4
+ 0.068
+ -0.038
+ 1
+ 1
+
+
+ 1
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+
+
+ 10
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+ 6
+ 53.7
+ 5.4
+ 0.068
+ -0.038
+ 1
+ 1
+
+
+ 1
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+
+
+ 10
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+ 6
+ 53.7
+ 5.4
+ 0.068
+ -0.038
+ 1
+ 1
+
+
+ 1
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+
+ 10
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+ 6
+ 53.7
+ 5.4
+ 0.068
+ -0.038
+ 1
+ 1
+
+
+ 1
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+
+
+ 10
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+ 6
+ 53.7
+ 5.4
+ 0.068
+ -0.038
+ 1
+ 1
+
+
+ 1
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+
+
+ 10
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+ 6
+ 53.7
+ 5.4
+ 0.068
+ -0.038
+ 1
+ 1
+
+
+ 1
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+
+
+ 10
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+
+
+ 6
+ 53.7
+ 5.4
+ 0.068
+ -0.038
+ 1
+ 1
+
+
+ 1
+ 56.7
+ 7.5
+ 0.057
+ -0.038
+ 1
+ 1
+ 0
+
+
+
+
+
+
+
+
+ 8
+ -33.7
+ 0
+ -0.492
+ 0.266
+ 1
+ 0
+ 0
+
+
+ 8
+ Fuck
+ -39.6
+ 0
+ -0.353
+ 0.256
+ 1
+ 0
+
+
+ 1
+ -33.7
+ 0
+ -0.492
+ 0.266
+ 1
+ 0
+ 0
+
+
+
+
+
+
+ Knot
+ False
+ 71
+ 0
+
+
+ LayingPawn
+
+
+ true
+ 60
+ 53.7
+ 25.4
+ 0.068
+ -0.038
+ 1
+ 1
+ 0
+
+
+ 6
+ Cum
+ 53.7
+ 28.4
+ 0.068
+ -0.038
+ 1
+ 1
+
+
+ 4
+ 51.7
+ 33.4
+ 0.098
+ -0.038
+ 1
+ 1
+
+
+ 1
+ 53.7
+ 25.4
+ 0.068
+ -0.038
+ 1
+ 1
+ 0
+
+
+
+
+
+
+
+
+ 60
+ -33.7
+ 0
+ -0.492
+ 0.266
+ 1
+ 0
+ 0
+
+
+ 6
+ -39.6
+ 0
+ -0.353
+ 0.256
+ 1
+ 0
+
+
+ 4
+ Fuck
+ -41.6
+ 0
+ -0.383
+ 0.256
+ 1
+ 0
+
+
+ 1
+ -39.6
+ 0
+ -0.353
+ 0.256
+ 1
+ 0
+ 0
+
+
+
+
+
+
+
+
+ Cum
+ true
+ 600
+ 0
+
+
+ LayingPawn
+
+
+ 40
+ 53.7
+ 25.4
+ 0.068
+ -0.038
+ 1
+ 1
+ 0
+
+
+ 40
+ Cum
+ 57.7
+ 28.4
+ 0.073
+ -0.038
+ 1
+ 1
+
+
+ 1
+ 53.7
+ 25.4
+ 0.068
+ -0.038
+ 1
+ 1
+ 0
+
+
+
+
+
+
+
+
+ 10
+ -39.6
+ 0
+ -0.353
+ 0.256
+ 1
+ 0
+ 0
+
+
+ 10
+ -40.6
+ 0
+ -0.358
+ 0.256
+ 1
+ 0
+
+
+ 10
+ -39.6
+ 0
+ -0.353
+ 0.256
+ 1
+ 0
+
+
+ 10
+ -40.6
+ 0
+ -0.358
+ 0.256
+ 1
+ 0
+
+
+ 10
+ -39.6
+ 0
+ -0.353
+ 0.256
+ 1
+ 0
+
+
+ 10
+ -40.6
+ 0
+ -0.358
+ 0.256
+ 1
+ 0
+
+
+ 10
+ -39.6
+ 0
+ -0.353
+ 0.256
+ 1
+ 0
+
+
+ 10
+ -40.6
+ 0
+ -0.358
+ 0.256
+ 1
+ 0
+
+
+ 1
+ -39.6
+ 0
+ -0.353
+ 0.256
+ 1
+ 0
+ 0
+
+
+
+
+
+
+
+
+
+
+
+
+ Horse_Cowgirl
+ HorseCowgirl
+ true
+
+ Anal
+ Vaginal
+
+
+
+ RequestVaginalBreeding
+ RequestAnalBreeding
+
+
+
+
+
+ Human
+
+ true
+ true
+
+ (0, 0.2)
+
+
+
+
+ Horse
+
+
+ QuadrupedAnimalWithHooves
+
+ true
+
+
+
+
+
+
+
+ Insertion
+ false
+ 0
+
+
+
+
+ 180
+ -24.337
+ -37.1218948
+ 0
+ 0.698042035
+ -0.20718734
+ 0
+ 3
+ 3
+
+
+ 70
+ -2.54239845
+ 7.31265259
+ 0
+ 0.606091142
+ -0.045959726
+ 0
+ 3
+ 3
+ Slimy
+
+
+ 60
+ -4.84361649
+ -23.6405125
+ 0
+ 0.650456548
+ -0.0570534021
+ 0
+ 3
+ 3
+ Slimy
+
+
+ 1
+ -35.01766
+ -26.3706665
+ 0
+ 0.455286169
+ -0.3646413
+ 0
+ 3
+ 3
+ Slimy
+
+
+
+
+ LayingPawn
+
+
+ 250
+ 177.083145
+ 0
+ 0
+ -0.256229281
+ -0.362511069
+ 0
+ 1
+ 0
+
+
+
+ 60
+ 177.981537
+ 0
+ 0
+ -0.24524799
+ -0.358849227
+ 0
+ 1
+ 0
+
+
+ 1
+ 179.6811
+ 0
+ 0
+ -0.267210543
+ -0.3991253
+ 0
+ 1
+ 0
+
+
+
+
+
+
+
+ SlowFuck
+ true
+ 1300
+ 0
+
+
+
+
+ 80
+ -35.01766
+ -26.3706665
+ 0
+ 0.455286169
+ -0.3646413
+ 0
+ 3
+ 3
+
+
+ 49
+ -49.8178673
+ -35.7418823
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 3
+ Slimy
+
+
+ 1
+ -35.01766
+ -26.3706665
+ 0
+ 0.455286169
+ -0.3646413
+ 0
+ 3
+ 3
+ Fuck
+
+
+
+
+ LayingPawn
+
+
+ 80
+ 179.6811
+ 0
+ 0
+ -0.267210543
+ -0.3991253
+ 0
+ 1
+ 0
+
+
+ 49
+ 177.981537
+ 0
+ 0
+ -0.24524799
+ -0.358849227
+ 0
+ 1
+ 0
+
+
+ 1
+ 179.6811
+ 0
+ 0
+ -0.267210543
+ -0.3991253
+ 0
+ 1
+ 0
+
+
+
+
+
+
+
+ Transition
+ false
+ 0
+
+
+
+
+ 50
+ -35.01766
+ -26.3706665
+ 0
+ 0.455286169
+ -0.3646413
+ 0
+ 3
+ 3
+ Fuck
+
+
+
+ 15
+ -49.8178673
+ -35.7418823
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 3
+ Slimy
+
+
+
+ 80
+ -49.8178673
+ -8.273987
+ 0
+ 0.506531835
+ -0.55575326
+ 0
+ 3
+ 3
+
+
+
+ 1
+ -49.8178673
+ -14.1647339
+ 0
+ 0.48456946
+ -0.489136577
+ 0
+ 3
+ 3
+
+
+
+
+ LayingPawn
+
+
+ 50
+ 179.6811
+ 0
+ 0
+ -0.267210543
+ -0.3991253
+ 0
+ 1
+ 0
+
+
+
+ 15
+ 177.981537
+ 0
+ 0
+ -0.24524799
+ -0.358849227
+ 0
+ 1
+ 0
+
+
+
+ 80
+ 175.467651
+ 0
+ 0
+ -0.2123042
+ -0.5309518
+ 0
+ 1
+ 0
+ Fuck
+
+
+
+ 1
+ 177.981537
+ 0
+ 0
+ -0.24524799
+ -0.358849227
+ 0
+ 1
+ 0
+
+
+
+
+
+
+
+ FastFuck
+ true
+ 1260
+ 0
+
+
+
+
+
+ 10
+ -49.8178673
+ -14.1647339
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 3
+ Slimy
+
+
+ 24
+ -49.8178673
+ -8.273987
+ 0
+ 0.506531835
+ -0.55575326
+ 0
+ 3
+ 3
+
+
+ 1
+ -49.8178673
+ -14.1647339
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 3
+ Slimy
+
+
+
+ 10
+ -49.8178673
+ -14.1647339
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 3
+ Slimy
+
+
+ 24
+ -49.8178673
+ -8.273987
+ 0
+ 0.506531835
+ -0.55575326
+ 0
+ 3
+ 3
+
+
+ 1
+ -49.8178673
+ -14.1647339
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 3
+ Slimy
+
+
+
+ 10
+ -49.8178673
+ -14.1647339
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 2
+ Slimy
+
+
+ 24
+ -49.8178673
+ -8.273987
+ 0
+ 0.506531835
+ -0.55575326
+ 0
+ 3
+ 2
+
+
+ 1
+ -49.8178673
+ -14.1647339
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 2
+ Slimy
+
+
+
+ 10
+ -49.8178673
+ -14.1647339
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 2
+ Slimy
+
+
+ 24
+ -49.8178673
+ -8.273987
+ 0
+ 0.506531835
+ -0.55575326
+ 0
+ 3
+ 2
+
+
+ 1
+ -49.8178673
+ -14.1647339
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 2
+ Slimy
+
+
+
+ 10
+ -49.8178673
+ -14.1647339
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 2
+ Slimy
+
+
+ 24
+ -49.8178673
+ -8.273987
+ 0
+ 0.506531835
+ -0.55575326
+ 0
+ 3
+ 2
+
+
+ 1
+ -49.8178673
+ -14.1647339
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 2
+ Slimy
+
+
+
+ 10
+ -49.8178673
+ -14.1647339
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 2
+ Slimy
+
+
+ 24
+ -49.8178673
+ -8.273987
+ 0
+ 0.506531835
+ -0.55575326
+ 0
+ 3
+ 2
+
+
+ 1
+ -49.8178673
+ -14.1647339
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 2
+ Slimy
+
+
+
+ 10
+ -49.8178673
+ -14.1647339
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 2
+ Slimy
+
+
+ 24
+ -49.8178673
+ -8.273987
+ 0
+ 0.506531835
+ -0.55575326
+ 0
+ 3
+ 2
+
+
+ 1
+ -49.8178673
+ -14.1647339
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 2
+ Slimy
+
+
+
+ 10
+ -49.8178673
+ -14.1647339
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 2
+ Slimy
+
+
+ 24
+ -49.8178673
+ -8.273987
+ 0
+ 0.506531835
+ -0.55575326
+ 0
+ 3
+ 2
+
+
+ 1
+ -49.8178673
+ -14.1647339
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 2
+ Slimy
+
+
+
+ 10
+ -49.8178673
+ -14.1647339
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 3
+ Slimy
+
+
+ 24
+ -49.8178673
+ -8.273987
+ 0
+ 0.506531835
+ -0.55575326
+ 0
+ 3
+ 3
+
+
+ 1
+ -49.8178673
+ -14.1647339
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 3
+ Slimy
+
+
+
+ 10
+ -49.8178673
+ -14.1647339
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 3
+ Slimy
+
+
+ 24
+ -49.8178673
+ -8.273987
+ 0
+ 0.506531835
+ -0.55575326
+ 0
+ 3
+ 3
+
+
+ 1
+ -49.8178673
+ -14.1647339
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 3
+ Slimy
+
+
+
+ 10
+ -49.8178673
+ -14.1647339
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 3
+ Slimy
+
+
+ 24
+ -49.8178673
+ -8.273987
+ 0
+ 0.506531835
+ -0.55575326
+ 0
+ 3
+ 3
+
+
+ 1
+ -49.8178673
+ -14.1647339
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 3
+ Slimy
+
+
+
+ 10
+ -49.8178673
+ -14.1647339
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 3
+ Slimy
+
+
+ 24
+ -49.8178673
+ -8.273987
+ 0
+ 0.506531835
+ -0.55575326
+ 0
+ 3
+ 3
+
+
+ 1
+ -49.8178673
+ -14.1647339
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 3
+ Slimy
+
+
+
+
+ LayingPawn
+
+
+
+ 10
+ 177.981537
+ 0
+ 0
+ -0.24524799
+ -0.358849227
+ 0
+ 1
+ 0
+
+
+ 24
+ 175.467651
+ 0
+ 0
+ -0.2123042
+ -0.5309518
+ 0
+ 1
+ 0
+ Fuck
+
+
+ 1
+ 177.981537
+ 0
+ 0
+ -0.24524799
+ -0.358849227
+ 0
+ 1
+ 0
+
+
+
+
+
+
+
+ FasterFuck
+ true
+ 418
+ 0
+
+
+
+
+
+ 10
+ -49.8178673
+ -14.1647339
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 3
+
+
+ 8
+ -49.8178673
+ -8.273987
+ 0
+ 0.506531835
+ -0.55575326
+ 0
+ 3
+ 3
+
+
+ 1
+ -49.8178673
+ -14.1647339
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 3
+ Slimy
+
+
+
+
+ LayingPawn
+
+
+ 10
+ 177.981537
+ 0
+ 0
+ -0.24524799
+ -0.358849227
+ 0
+ 1
+ 0
+
+
+ 8
+ 175.467651
+ 0
+ 0
+ -0.2123042
+ -0.5309518
+ 0
+ 1
+ 0
+ Fuck
+
+
+ 1
+ 177.981537
+ 0
+ 0
+ -0.24524799
+ -0.358849227
+ 0
+ 1
+ 0
+
+
+
+
+
+
+
+ Cum
+ True
+ 318
+ 0
+
+
+
+
+
+ 10
+ -49.8178673
+ -14.1647339
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 3
+
+
+
+ true
+ 80
+ -49.8178673
+ -8.273987
+ 0
+ 0.506531835
+ -0.55575326
+ 0
+ 3
+ 3
+ Cum
+
+
+ 25
+ -49.8178673
+ 2.654541
+ 0
+ 0.5175133
+ -0.547725141
+ 0
+ 3
+ 3
+
+
+ 1
+ -49.8178673
+ -14.1647339
+ 0
+ 0.484569454
+ -0.489136577
+ 0
+ 3
+ 3
+
+
+
+
+
+ LayingPawn
+
+
+
+ 10
+ 177.981537
+ 0
+ 0
+ -0.24524799
+ -0.358849227
+ 0
+ 1
+ 0
+
+
+ 80
+ 175.467651
+ 0
+ 0
+ -0.2123042
+ -0.5309518
+ 0
+ 1
+ 0
+
+
+ 25
+ 173.81427
+ 0
+ 0
+ -0.197662517
+ -0.545600235
+ 0
+ 1
+ 0
+
+
+ 1
+ 177.981537
+ 0
+ 0
+ -0.24524799
+ -0.358849227
+ 0
+ 1
+ 0
+
+
+
+
+
+
+
+
+
+
+
diff --git a/1.4/Defs/AnimationDefs/Animations_Lesbian.xml b/1.4/Defs/AnimationDefs/Animations_Lesbian.xml
new file mode 100644
index 0000000..56d805a
--- /dev/null
+++ b/1.4/Defs/AnimationDefs/Animations_Lesbian.xml
@@ -0,0 +1,1782 @@
+
+
+
+ Tribadism
+ scissoring
+ true
+
+ Scissoring
+
+
+
+
+
+ Human
+
+ true
+
+ Vagina
+
+
+
+
+ Human
+
+ true
+ true
+
+ Vagina
+
+
+
+
+
+
+
+ Tribbing
+ true
+ 992
+ 0
+
+
+ LayingPawn
+
+
+
+ 20
+ -81.3
+ -81.3
+ -0.218
+ 0.073
+ 2
+ 2
+ 0
+
+
+ 20
+ -79.56
+ -79.56
+ -0.218
+ 0.082
+ 2
+ 2
+ 0
+
+
+ 20
+ -81.53
+ -81.53
+ -0.219
+ 0.07
+ 2
+ 2
+ 0
+
+
+ Slimy
+ 1
+ -81.3
+ -81.3
+ -0.218
+ 0.073
+ 2
+ 2
+ 0
+
+
+
+
+
+
+
+ 20
+ 9.97
+ -7.61
+ 0.444
+ 0.368
+ 3
+ 3
+ 0
+
+
+ 20
+ 23.82
+ -6.90
+ 0.432
+ 0.403
+ 3
+ 3
+ 0
+
+
+ 20
+ 5.19
+ -6.19
+ 0.442
+ 0.388
+ 3
+ 3
+ 0
+
+
+ 1
+ 9.97
+ -7.61
+ 0.444
+ 0.368
+ 3
+ 3
+ 0
+
+
+
+
+
+
+
+ TribadismFast
+ true
+ 682
+ 0
+
+
+ LayingPawn
+
+
+
+ 10
+ -81.3
+ -81.3
+ -0.218
+ 0.073
+ 2
+ 1
+ 0
+
+
+ 10
+ -79.56
+ -79.56
+ -0.218
+ 0.082
+ 2
+ 1
+ 0
+
+
+ 10
+ -81.53
+ -81.53
+ -0.219
+ 0.07
+ 2
+ 1
+ 0
+
+
+ Slimy
+ 1
+ -81.3
+ -81.3
+ -0.218
+ 0.073
+ 2
+ 1
+ 0
+
+
+
+ 10
+ -81.3
+ -81.3
+ -0.218
+ 0.073
+ 2
+ 1
+ 0
+
+
+ 10
+ -79.56
+ -79.56
+ -0.218
+ 0.082
+ 2
+ 1
+ 0
+
+
+ 10
+ -81.53
+ -81.53
+ -0.219
+ 0.07
+ 2
+ 1
+ 0
+
+
+ Slimy
+ 1
+ -81.3
+ -81.3
+ -0.218
+ 0.073
+ 2
+ 1
+ 0
+
+
+
+
+ 10
+ -81.3
+ -81.3
+ -0.218
+ 0.073
+ 2
+ 1
+ 0
+
+
+ 10
+ -79.56
+ -79.56
+ -0.218
+ 0.082
+ 2
+ 1
+ 0
+
+
+ 10
+ -81.53
+ -81.53
+ -0.219
+ 0.07
+ 2
+ 1
+ 0
+
+
+ Slimy
+ 1
+ -81.3
+ -81.3
+ -0.218
+ 0.073
+ 2
+ 1
+ 0
+
+
+
+ 10
+ -81.3
+ -81.3
+ -0.218
+ 0.073
+ 2
+ 1
+ 0
+
+
+ 10
+ -79.56
+ -79.56
+ -0.218
+ 0.082
+ 2
+ 1
+ 0
+
+
+ 10
+ -81.53
+ -81.53
+ -0.219
+ 0.07
+ 2
+ 1
+ 0
+
+
+ Slimy
+ 1
+ -81.3
+ -81.3
+ -0.218
+ 0.073
+ 2
+ 1
+ 0
+
+
+
+
+
+ 10
+ -81.3
+ -73.04
+ -0.218
+ 0.073
+ 2
+ 2
+ 0
+
+
+ 10
+ -79.56
+ -77.66
+ -0.218
+ 0.082
+ 2
+ 2
+ 0
+
+
+ 10
+ -81.53
+ -77.74
+ -0.219
+ 0.07
+ 2
+ 2
+ 0
+
+
+ Slimy
+ 1
+ -81.3
+ -73.04
+ -0.218
+ 0.073
+ 2
+ 2
+ 0
+
+
+
+
+
+ 10
+ -81.3
+ -73.04
+ -0.218
+ 0.073
+ 2
+ 2
+ 0
+
+
+ 10
+ -79.56
+ -77.66
+ -0.218
+ 0.082
+ 2
+ 2
+ 0
+
+
+ 10
+ -81.53
+ -77.74
+ -0.219
+ 0.07
+ 2
+ 2
+ 0
+
+
+ Slimy
+ 1
+ -81.3
+ -73.04
+ -0.218
+ 0.073
+ 2
+ 2
+ 0
+
+
+
+
+
+ 10
+ -81.3
+ -73.04
+ -0.218
+ 0.073
+ 2
+ 2
+ 0
+
+
+ 10
+ -79.56
+ -77.66
+ -0.218
+ 0.082
+ 2
+ 2
+ 0
+
+
+ 10
+ -81.53
+ -77.74
+ -0.219
+ 0.07
+ 2
+ 2
+ 0
+
+
+ Slimy
+ 1
+ -81.3
+ -73.04
+ -0.218
+ 0.073
+ 2
+ 2
+ 0
+
+
+
+
+
+ 10
+ -81.3
+ -73.04
+ -0.218
+ 0.073
+ 2
+ 2
+ 0
+
+
+ 10
+ -79.56
+ -77.66
+ -0.218
+ 0.082
+ 2
+ 2
+ 0
+
+
+ 10
+ -81.53
+ -77.74
+ -0.219
+ 0.07
+ 2
+ 2
+ 0
+
+
+ Slimy
+ 1
+ -81.3
+ -73.04
+ -0.218
+ 0.073
+ 2
+ 2
+ 0
+
+
+
+
+
+ 10
+ -81.3
+ -73.04
+ -0.218
+ 0.073
+ 2
+ 2
+ 0
+
+
+ 10
+ -79.56
+ -77.66
+ -0.218
+ 0.082
+ 2
+ 2
+ 0
+
+
+ 10
+ -81.53
+ -77.74
+ -0.219
+ 0.07
+ 2
+ 2
+ 0
+
+
+ Slimy
+ 1
+ -81.3
+ -73.04
+ -0.218
+ 0.073
+ 2
+ 2
+ 0
+
+
+
+
+
+ 10
+ -81.3
+ -73.04
+ -0.218
+ 0.073
+ 2
+ 2
+ 0
+
+
+ 10
+ -79.56
+ -77.66
+ -0.218
+ 0.082
+ 2
+ 2
+ 0
+
+
+ 10
+ -81.53
+ -77.74
+ -0.219
+ 0.07
+ 2
+ 2
+ 0
+
+
+ Slimy
+ 1
+ -81.3
+ -73.04
+ -0.218
+ 0.073
+ 2
+ 2
+ 0
+
+
+
+
+ 10
+ -81.3
+ -81.3
+ -0.218
+ 0.073
+ 2
+ 1
+ 0
+
+
+ 10
+ -79.56
+ -79.56
+ -0.218
+ 0.082
+ 2
+ 1
+ 0
+
+
+ 10
+ -81.53
+ -81.53
+ -0.219
+ 0.07
+ 2
+ 1
+ 0
+
+
+ Slimy
+ 1
+ -81.3
+ -81.3
+ -0.218
+ 0.073
+ 2
+ 1
+ 0
+
+
+
+
+
+
+
+ 10
+ 9.97
+ -7.61
+ 0.444
+ 0.368
+ 3
+ 3
+ 0
+
+
+ 10
+ 23.82
+ -6.90
+ 0.432
+ 0.403
+ 3
+ 3
+ 0
+
+
+ 10
+ 5.19
+ -6.19
+ 0.442
+ 0.388
+ 3
+ 3
+ 0
+
+
+ 1
+ 9.97
+ -7.61
+ 0.444
+ 0.368
+ 3
+ 3
+ 0
+
+
+
+
+
+
+
+
+
+
+ Cunnilingus
+ cunnilingus
+ true
+
+ Oral
+ Fingering
+ Cunnilingus
+
+
+
+ Cunnilingus
+ CunnilingusF
+ CunnilingusRape
+ CunnilingusRapeF
+
+ Fingering
+ FingeringF
+ FingeringRape
+ FingeringRapeF
+
+ Fisting
+ FistingF
+ FistingRape
+ FistingRapeF
+
+
+
+
+
+ Human
+
+ true
+
+ Vagina
+
+
+ (-0.2, 0.1)
+
+
+
+
+ Human
+
+ true
+
+ (-0.1, 0.15)
+
+
+
+
+
+
+
+
+ Initial
+ False
+ 0
+
+
+
+
+ 60
+ -81.06536
+ -56.4483032
+ 0
+ -0.0624052179
+ -0.437134951
+ 0
+ 1
+ 1
+
+
+ 1
+ -87.3645554
+ -69.70276
+ 0
+ -0.0692383763
+ -0.440020353
+ 0
+ 1
+ 1
+
+
+
+
+ LayingPawn
+
+
+ 60
+ -27.578373
+ 0.2816162
+ 0
+ 0.102704488
+ 0.50675
+ 0
+ 3
+ 3
+
+
+ 1
+ -47.9400826
+ -21.93164
+ 0
+ -0.04209958
+ 0.467844343
+ -0.1
+ 3
+ 3
+ Slimy
+
+
+
+
+
+
+
+
+ Slow
+ True
+ 1497
+ 0
+
+
+
+
+ 98
+ -87.3645554
+ -69.70276
+ 0
+ -0.0692383763
+ -0.440020353
+ 0
+ 1
+ 1
+
+
+ 40
+ -87.26528
+ -65.901825
+ 0
+ -0.0737426062
+ -0.432820916
+ 0
+ 1
+ 1
+
+
+ 1
+ -87.3645554
+ -69.70276
+ 0
+ -0.0692383763
+ -0.440020353
+ 0
+ 1
+ 1
+
+
+
+ 98
+ -87.3645554
+ -69.70276
+ 0
+ -0.0692383763
+ -0.440020353
+ 0
+ 1
+ 1
+
+
+ 40
+ -87.26528
+ -65.901825
+ 0
+ -0.0737426062
+ -0.432820916
+ 0
+ 1
+ 1
+
+
+ 1
+ -87.3645554
+ -69.70276
+ 0
+ -0.0692383763
+ -0.440020353
+ 0
+ 1
+ 1
+
+
+
+ 60
+ -87.3645554
+ -69.70276
+ 0
+ -0.0692383763
+ -0.440020353
+ 0
+ 1
+ 1
+
+
+ 120
+ -86.52611
+ -68.86432
+ 0
+ -0.05432228
+ -0.439906
+ 0
+ 1
+ 1
+
+
+ 40
+ -88.36286
+ -84.3309
+ 0
+ -0.06637782
+ -0.440140843
+ 0
+ 1
+ 1
+
+
+ 1
+ -87.3645554
+ -69.70276
+ 0
+ -0.0692383763
+ -0.440020353
+ 0
+ 1
+ 1
+
+
+
+
+ LayingPawn
+
+
+ 80
+ -47.9400826
+ -21.93164
+ 0
+ -0.04209958
+ 0.467844343
+ -0.1
+ 3
+ 3
+
+
+ 18
+ -41.1054764
+ -10.1737061
+ 0
+ 0.04582855
+ 0.462155169
+ 0
+ 3
+ 3
+
+
+ 40
+ -38.1903877
+ -31.6517334
+ 0
+ 0.0384018831
+ 0.4874894
+ 0
+ 3
+ 3
+
+
+ 1
+ -47.9400826
+ -21.93164
+ 0
+ -0.04209958
+ 0.467844343
+ -0.1
+ 3
+ 3
+ Slimy
+
+
+
+ 80
+ -47.9400826
+ -21.93164
+ 0
+ -0.04209958
+ 0.467844343
+ -0.1
+ 3
+ 3
+
+
+ 18
+ -41.1054764
+ -10.1737061
+ 0
+ 0.04582855
+ 0.462155169
+ 0
+ 3
+ 3
+
+
+ 40
+ -38.1903877
+ -31.6517334
+ 0
+ 0.0384018831
+ 0.4874894
+ 0
+ 3
+ 3
+
+
+ 1
+ -47.9400826
+ -21.93164
+ 0
+ -0.04209958
+ 0.467844343
+ -0.1
+ 3
+ 3
+ Slimy
+
+
+
+ 60
+ -47.9400826
+ -21.93164
+ 0
+ -0.04209958
+ 0.467844343
+ -0.1
+ 3
+ 3
+ Slimy
+
+
+ 40
+ -45.2595444
+ -13.57782
+ 0
+ 0.009577712
+ 0.4726282
+ 0
+ 3
+ 3
+ Slimy
+
+
+ 20
+ -45.2595444
+ -24.2278748
+ 0
+ 0.0315402448
+ 0.415024319
+ 0
+ 3
+ 3
+
+
+
+ 40
+ -45.2595444
+ -13.57782
+ 0
+ 0.009577712
+ 0.4726282
+ 0
+ 3
+ 3
+ Slimy
+
+
+ 20
+ -45.2595444
+ -24.2278748
+ 0
+ 0.0315402448
+ 0.415024319
+ 0
+ 3
+ 3
+
+
+
+ 40
+ -45.2595444
+ -13.57782
+ 0
+ 0.009577712
+ 0.4726282
+ 0
+ 3
+ 3
+ Slimy
+
+
+ 1
+ -47.9400826
+ -21.93164
+ 0
+ -0.04209958
+ 0.467844343
+ -0.1
+ 3
+ 3
+ Slimy
+
+
+
+
+
+
+
+
+ Transition
+ False
+ 0
+
+
+
+
+ 40
+ -87.3645554
+ -69.70276
+ 0
+ -0.06923838
+ -0.440020353
+ 0
+ 1
+ 1
+
+
+ 30
+ -97.90959
+ -69.72717
+ 0
+ -0.0259781852
+ -0.445601642
+ 0
+ 1
+ 1
+
+
+ 1
+ -87.3645554
+ -69.70276
+ 0
+ -0.06923838
+ -0.440020353
+ 0
+ 1
+ 1
+
+
+
+
+ LayingPawn
+
+
+ 40
+ -47.9400826
+ -21.93164
+ 0
+ -0.04209958
+ 0.467844343
+ -0.1
+ 3
+ 3
+ Slimy
+
+
+ 30
+ -35.8792953
+ -9.312592
+ 0
+ 0.03684573
+ 0.4285702
+ 0
+ 3
+ 3
+ Slimy
+
+
+ 1
+ -47.9400826
+ -21.93164
+ 0
+ -0.04209958
+ 0.467844343
+ 0
+ 3
+ 3
+ Slimy
+
+
+
+
+
+
+
+ Fast
+ True
+ 710
+ 0
+
+
+
+
+ 40
+ -87.3645554
+ -69.70276
+ 0
+ -0.06923838
+ -0.440020353
+ 0
+ 1
+ 1
+
+
+ 30
+ -97.90959
+ -69.72717
+ 0
+ -0.0259781852
+ -0.445601642
+ 0
+ 1
+ 1
+
+
+ 1
+ -87.3645554
+ -69.70276
+ 0
+ -0.06923838
+ -0.440020353
+ 0
+ 1
+ 1
+
+
+
+ 40
+ -87.3645554
+ -69.70276
+ 0
+ -0.06923838
+ -0.440020353
+ 0
+ 1
+ 1
+
+
+ 30
+ -97.90959
+ -69.72717
+ 0
+ -0.0259781852
+ -0.445601642
+ 0
+ 1
+ 1
+
+
+ 1
+ -87.3645554
+ -69.70276
+ 0
+ -0.06923838
+ -0.440020353
+ 0
+ 1
+ 1
+
+
+
+ 40
+ -87.3645554
+ -79.70276
+ 0
+ -0.06923838
+ -0.440020353
+ 0
+ 1
+ 2
+
+
+ 30
+ -97.90959
+ -79.72717
+ 0
+ -0.0259781852
+ -0.445601642
+ 0
+ 1
+ 2
+
+
+ 1
+ -87.3645554
+ -79.70276
+ 0
+ -0.06923838
+ -0.440020353
+ 0
+ 1
+ 2
+
+
+
+ 40
+ -87.3645554
+ -79.70276
+ 0
+ -0.06923838
+ -0.440020353
+ 0
+ 1
+ 2
+
+
+ 30
+ -97.90959
+ -79.72717
+ 0
+ -0.0259781852
+ -0.445601642
+ 0
+ 1
+ 2
+
+
+ 1
+ -87.3645554
+ -79.70276
+ 0
+ -0.06923838
+ -0.440020353
+ 0
+ 1
+ 2
+
+
+
+ 40
+ -87.3645554
+ -79.70276
+ 0
+ -0.06923838
+ -0.440020353
+ 0
+ 1
+ 2
+
+
+ 30
+ -97.90959
+ -79.72717
+ 0
+ -0.0259781852
+ -0.445601642
+ 0
+ 1
+ 2
+
+
+ 1
+ -87.3645554
+ -79.70276
+ 0
+ -0.06923838
+ -0.440020353
+ 0
+ 1
+ 2
+
+
+
+ 40
+ -87.3645554
+ -69.70276
+ 0
+ -0.06923838
+ -0.440020353
+ 0
+ 1
+ 1
+
+
+ 30
+ -97.90959
+ -69.72717
+ 0
+ -0.0259781852
+ -0.445601642
+ 0
+ 1
+ 1
+
+
+ 1
+ -87.3645554
+ -69.70276
+ 0
+ -0.06923838
+ -0.440020353
+ 0
+ 1
+ 1
+
+
+
+
+ LayingPawn
+
+
+ 40
+ -47.9400826
+ -21.93164
+ 0
+ -0.04209958
+ 0.467844343
+ 0
+ 3
+ 3
+ Slimy
+
+
+ 30
+ -35.8792953
+ -3.312592
+ 0
+ 0.03684573
+ 0.4285702
+ 0
+ 3
+ 3
+ Slimy
+
+
+ 1
+ -47.9400826
+ -21.93164
+ 0
+ -0.04209958
+ 0.467844343
+ 0
+ 3
+ 3
+ Slimy
+
+
+
+
+
+
+ Faster
+ True
+ 360
+ 0
+
+
+
+
+ 20
+ -87.3645554
+ -69.70276
+ 0
+ -0.06923838
+ -0.440020353
+ 0
+ 1
+ 1
+
+
+ 15
+ -97.90959
+ -69.72717
+ 0
+ -0.0259781852
+ -0.445601642
+ 0
+ 1
+ 1
+
+
+ 1
+ -87.3645554
+ -69.70276
+ 0
+ -0.06923838
+ -0.440020353
+ 0
+ 1
+ 1
+
+
+
+
+ LayingPawn
+
+
+ 20
+ -47.9400826
+ -21.93164
+ 0
+ -0.04209958
+ 0.467844343
+ 0
+ 3
+ 3
+ Slimy
+
+
+ 15
+ -35.8792953
+ -9.312592
+ 0
+ 0.03684573
+ 0.4285702
+ 0
+ 3
+ 3
+ Slimy
+
+
+ 1
+ -47.9400826
+ -21.93164
+ 0
+ -0.04209958
+ 0.467844343
+ 0
+ 3
+ 3
+ Slimy
+
+
+
+
+
+
+ Cum
+ True
+ 639
+ 0
+
+
+
+
+ 20
+ -87.3645554
+ -69.70276
+ 0
+ -0.06923838
+ -0.440020353
+ 0
+ 1
+ 1
+
+
+ 15
+ -97.90959
+ -69.72717
+ 0
+ -0.0259781852
+ -0.445601642
+ 0
+ 1
+ 1
+
+
+ 1
+ -87.3645554
+ -69.70276
+ 0
+ -0.06923838
+ -0.440020353
+ 0
+ 1
+ 1
+
+
+
+ 20
+ -87.3645554
+ -69.70276
+ 0
+ -0.06923838
+ -0.440020353
+ 0
+ 1
+ 1
+
+
+ 15
+ -97.90959
+ -69.72717
+ 0
+ -0.0259781852
+ -0.445601642
+ 0
+ 1
+ 1
+
+
+ 1
+ -87.3645554
+ -69.70276
+ 0
+ -0.06923838
+ -0.440020353
+ 0
+ 1
+ 1
+
+
+
+ 20
+ -87.3645554
+ -69.70276
+ 0
+ -0.06923838
+ -0.440020353
+ 0
+ 1
+ 1
+
+
+ True
+ 80
+ -97.90959
+ -69.72717
+ 0
+ -0.0259781852
+ -0.445601642
+ 0
+ 1
+ 1
+ Cum
+
+
+ 40
+ -99.80413
+ -94.4023743
+ 0
+ -0.01950606
+ -0.447728932
+ 0
+ 1
+ 1
+
+
+ 1
+ -87.3645554
+ -69.70276
+ 0
+ -0.06923838
+ -0.440020353
+ 0
+ 1
+ 1
+
+
+
+
+ LayingPawn
+
+
+
+ 20
+ -47.9400826
+ -21.93164
+ 0
+ -0.04209958
+ 0.467844343
+ 0
+ 3
+ 3
+ Slimy
+
+
+ 15
+ -35.8792953
+ -9.312592
+ 0
+ 0.03684573
+ 0.4285702
+ 0
+ 3
+ 3
+ Slimy
+
+
+ 1
+ -47.9400826
+ -21.93164
+ 0
+ -0.04209958
+ 0.467844343
+ 0
+ 3
+ 3
+ Slimy
+
+
+
+ 20
+ -47.9400826
+ -21.93164
+ 0
+ -0.04209958
+ 0.467844343
+ 0
+ 3
+ 3
+ Slimy
+
+
+ 15
+ -35.8792953
+ -9.312592
+ 0
+ 0.03684573
+ 0.4285702
+ 0
+ 3
+ 3
+ Slimy
+
+
+ 1
+ -47.9400826
+ -21.93164
+ 0
+ -0.04209958
+ 0.467844343
+ 0
+ 3
+ 3
+ Slimy
+
+
+
+ 20
+ -47.9400826
+ -21.93164
+ 0
+ -0.04209958
+ 0.467844343
+ 0
+ 3
+ 3
+ Slimy
+
+
+ 80
+ -35.8792953
+ -9.312592
+ 0
+ 0.03684573
+ 0.4285702
+ 0
+ 3
+ 3
+
+
+ 40
+ -38.5277061
+ -1.13140869
+ 0
+ 0.0376501828
+ 0.42935127
+ 0
+ 3
+ 3
+
+
+ 1
+ -47.9400826
+ -21.93164
+ 0
+ -0.04209958
+ 0.467844343
+ 0
+ 3
+ 3
+ Slimy
+
+
+
+
+
+
+
+
+
+
diff --git a/1.4/Defs/AnimationDefs/Animations_Masturbate.xml b/1.4/Defs/AnimationDefs/Animations_Masturbate.xml
new file mode 100644
index 0000000..2968fa1
--- /dev/null
+++ b/1.4/Defs/AnimationDefs/Animations_Masturbate.xml
@@ -0,0 +1,9 @@
+
+
+
+
\ No newline at end of file
diff --git a/1.4/Defs/AnimationDefs/Animations_Multi.xml b/1.4/Defs/AnimationDefs/Animations_Multi.xml
new file mode 100644
index 0000000..af7ea7a
--- /dev/null
+++ b/1.4/Defs/AnimationDefs/Animations_Multi.xml
@@ -0,0 +1,660 @@
+
+
+
+ Double_Penetration
+ double penetration
+ true
+
+ DoublePenetration
+ Anal
+ Oral
+ Vaginal
+
+
+
+
+ Human
+
+ true
+
+
+
+ Human
+
+ true
+ true
+ true
+
+
+
+ Human
+
+ true
+ true
+ true
+
+
+
+
+
+ Slow
+ true
+ 976
+ 0
+
+
+
+
+
+ 25
+ 62.7
+ 0.2
+ 0.01
+ 0.118
+ 1
+ 1
+ 0
+
+
+ 35
+ 48.1
+ 16.3
+ 0
+ 0.188
+ 1
+ 1
+ 0
+
+
+ Suck
+ 1
+ 62.7
+ 0.2
+ 0.01
+ 0.118
+ 1
+ 1
+ 0
+
+
+
+
+
+ LayingPawn
+
+
+ -10
+ 30
+ 12
+ -14.1
+ 0.674
+ 0.378
+ 3
+ 3
+ 0
+
+
+ 30
+ 12
+ -15.1
+ 0.729
+ 0.378
+ 3
+ 3
+ 0
+
+
+ -10
+ 1
+ 12
+ -14.1
+ 0.674
+ 0.378
+ 3
+ 3
+ 0
+
+
+
+
+
+ LayingPawn
+
+
+ 43
+ 27
+ 8.7
+ 15.1
+ -0.70
+ 0.378
+ 1
+ 1
+ 0
+
+
+ Fuck
+ 33
+ -6.7
+ 14.1
+ -0.53
+ 0.378
+ 1
+ 1
+ 0
+
+
+ 43
+ 1
+ 8.7
+ 15.1
+ -0.70
+ 0.378
+ 1
+ 1
+ 0
+
+
+
+
+
+
+ Face_Fuck
+ true
+ 650
+ 0
+
+
+
+
+
+ 13
+ 62.7
+ 0.2
+ 0.01
+ 0.118
+ 1
+ 1
+ 0
+
+
+ 6
+ 60.7
+ 5.6
+ 0.025
+ 0.118
+ 1
+ 1
+ 0
+
+
+ 6
+ 62.7
+ 0.2
+ 0.08
+ 0.118
+ 1
+ 1
+ 0
+
+
+ Suck
+ 1
+ 62.7
+ 0.2
+ 0.01
+ 0.118
+ 1
+ 1
+ 0
+
+
+
+
+
+ LayingPawn
+
+
+ -10
+ 13
+ 12
+ -14.1
+ 0.674
+ 0.378
+ 3
+ 3
+ 0
+
+
+ 12
+ 2
+ -15.1
+ 0.729
+ 0.378
+ 3
+ 3
+ 0
+
+
+ -10
+ 1
+ 12
+ -14.1
+ 0.674
+ 0.378
+ 3
+ 3
+ 0
+
+
+
+
+
+ LayingPawn
+
+
+ 43
+ 13
+ 8.7
+ 15.1
+ -0.70
+ 0.378
+ 1
+ 1
+ 0
+
+
+ Fuck
+ 12
+ -6.7
+ 14.1
+ -0.53
+ 0.378
+ 1
+ 1
+ 0
+
+
+ 43
+ 1
+ 8.7
+ 15.1
+ -0.70
+ 0.378
+ 1
+ 1
+ 0
+
+
+
+
+
+
+ Cum
+ true
+ 392
+ 0
+
+
+
+
+
+ 9
+ 62.7
+ 0.2
+ 0.01
+ 0.118
+ 1
+ 1
+ 0
+
+
+ 4
+ 60.7
+ 5.6
+ 0.025
+ 0.118
+ 1
+ 1
+ 0
+
+
+ 4
+ 62.7
+ 0.2
+ 0.056
+ 0.118
+ 1
+ 1
+ 0
+
+
+ Suck
+ 1
+ 62.7
+ 0.2
+ 0.01
+ 0.118
+ 1
+ 1
+ 0
+
+
+
+ 9
+ 62.7
+ 0.2
+ 0.01
+ 0.118
+ 1
+ 1
+ 0
+
+
+ 4
+ 60.7
+ 5.6
+ 0.025
+ 0.118
+ 1
+ 1
+ 0
+
+
+ 4
+ 62.7
+ 0.2
+ 0.056
+ 0.118
+ 1
+ 1
+ 0
+
+
+ Suck
+ 1
+ 62.7
+ 0.2
+ 0.01
+ 0.118
+ 1
+ 1
+ 0
+
+
+
+ 9
+ 62.7
+ 0.2
+ 0.01
+ 0.118
+ 1
+ 1
+ 0
+
+
+ true
+ 120
+ 60.7
+ 5.6
+ 0.025
+ 0.118
+ 1
+ 1
+ 0
+
+
+ 30
+ 62.7
+ 0.2
+ 0.056
+ 0.118
+ 1
+ 1
+ 0
+
+
+ Suck
+ 1
+ 62.7
+ 0.2
+ 0.01
+ 0.118
+ 1
+ 1
+ 0
+
+
+
+
+
+ LayingPawn
+
+
+ -10
+ 9
+ 9
+ -14.1
+ 0.674
+ 0.378
+ 3
+ 3
+ 0
+
+
+ 8
+ 0
+ -15.1
+ 0.729
+ 0.378
+ 3
+ 3
+ 0
+
+
+ 1
+ 9
+ -14.1
+ 0.674
+ 0.378
+ 3
+ 3
+ 0
+
+
+
+ 9
+ 9
+ -14.1
+ 0.674
+ 0.378
+ 3
+ 3
+ 0
+
+
+ 8
+ 0
+ -15.1
+ 0.729
+ 0.378
+ 3
+ 3
+ 0
+
+
+ 1
+ 9
+ -14.1
+ 0.674
+ 0.378
+ 3
+ 3
+ 0
+
+
+
+
+ 9
+ 9
+ -14.1
+ 0.674
+ 0.378
+ 3
+ 3
+ 0
+
+
+ 120
+ 9
+ -15.1
+ 0.674
+ 0.378
+ 3
+ 3
+ 0
+
+
+ 30
+ 9
+ 7
+ 0.674
+ 0.378
+ 3
+ 3
+ 0
+
+
+ 1
+ 9
+ -14.1
+ 0.674
+ 0.378
+ 3
+ 3
+ 0
+ -10
+
+
+
+
+
+
+ LayingPawn
+
+
+ 43
+ 9
+ 8.7
+ 15.1
+ -0.70
+ 0.378
+ 1
+ 1
+ 0
+
+
+ Fuck
+ 8
+ -6.7
+ 14.1
+ -0.53
+ 0.378
+ 1
+ 1
+ 0
+
+
+ 1
+ 8.7
+ 15.1
+ -0.70
+ 0.378
+ 1
+ 1
+ 0
+
+
+
+ 9
+ 8.7
+ 15.1
+ -0.70
+ 0.378
+ 1
+ 1
+ 0
+
+
+ Fuck
+ 8
+ -6.7
+ 14.1
+ -0.53
+ 0.378
+ 1
+ 1
+ 0
+
+
+ 1
+ 8.7
+ 15.1
+ -0.70
+ 0.378
+ 1
+ 1
+ 0
+
+
+
+ 9
+ 8.7
+ 15.1
+ -0.70
+ 0.378
+ 1
+ 1
+ 0
+
+
+ Cum
+ 120
+ -6.7
+ 14.1
+ -0.53
+ 0.378
+ 1
+ 1
+ 0
+
+
+ 30
+ -6.7
+ -7
+ -0.53
+ 0.378
+ 1
+ 1
+ 0
+
+
+ 43
+ 1
+ 8.7
+ 15.1
+ -0.70
+ 0.378
+ 1
+ 1
+ 0
+
+
+
+
+
+
+
+
+
+
+
diff --git a/1.4/Defs/AnimationDefs/Animations_SexToys.xml b/1.4/Defs/AnimationDefs/Animations_SexToys.xml
new file mode 100644
index 0000000..320d3aa
--- /dev/null
+++ b/1.4/Defs/AnimationDefs/Animations_SexToys.xml
@@ -0,0 +1,59 @@
+
+
+
+
diff --git a/1.4/Defs/AnimationDefs/Animations_Vanilla2.xml b/1.4/Defs/AnimationDefs/Animations_Vanilla2.xml
new file mode 100644
index 0000000..71b02a9
--- /dev/null
+++ b/1.4/Defs/AnimationDefs/Animations_Vanilla2.xml
@@ -0,0 +1,378 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/1.4/Defs/AnimationDefs/Animations_vanilla.xml b/1.4/Defs/AnimationDefs/Animations_vanilla.xml
new file mode 100644
index 0000000..0fd61d5
--- /dev/null
+++ b/1.4/Defs/AnimationDefs/Animations_vanilla.xml
@@ -0,0 +1,2799 @@
+
+
+
+
+ Doggystyle
+ doggystyle
+ true
+
+ Vaginal
+ Anal
+ DoublePenetration
+
+
+
+ AnalSex
+ AnalSexF
+ AnalRape
+ VaginalSex
+ VaginalSexF
+ VaginalRape
+
+
+
+
+
+
+ Human
+
+ true
+
+
+
+ Human
+
+ true
+ true
+ true
+
+ (0, 0.2)
+
+
+
+
+
+
+ Slow_Fuck
+ true
+ 612
+ 0
+
+
+
+
+ 0
+ 10
+ 27
+ 0.298
+ 0.166
+ 0
+ 1
+ 2
+
+
+ 40
+ 32
+ 0.326
+ 0.190
+ 1
+ 2
+
+
+ 1
+ 27
+ 0.298
+ 0.166
+ 1
+ 2
+
+
+
+ 10
+ 27
+ 0.298
+ 0.166
+ 1
+ 2
+
+
+ 40
+ 32
+ 0.326
+ 0.190
+ 1
+ 2
+
+
+ 1
+ 27
+ 0.298
+ 0.166
+ 1
+ 2
+
+
+
+ 10
+ 27
+ 0.298
+ 0.166
+ 1
+ 2
+
+
+ 40
+ 32
+ 0.326
+ 0.190
+ 1
+ 2
+
+
+ 1
+ 27
+ 0.298
+ 0.166
+ 1
+ 2
+
+
+
+ 10
+ 27
+ 0.298
+ 0.166
+ 1
+ 1
+
+
+ 40
+ 32
+ 0.326
+ 0.190
+ 1
+ 1
+
+
+ 1
+ 27
+ 0.298
+ 0.166
+ 1
+ 1
+
+
+
+ 10
+ 27
+ 0.298
+ 0.166
+ 1
+ 1
+
+
+ 40
+ 32
+ 0.326
+ 0.190
+ 1
+ 1
+
+
+ 1
+ 27
+ 0.298
+ 0.166
+ 1
+ 1
+
+
+
+ 10
+ 27
+ 0.298
+ 0.166
+ 1
+ 1
+
+
+ 40
+ 32
+ 0.326
+ 0.190
+ 1
+ 1
+
+
+ 1
+ 27
+ 0.298
+ 0.166
+ 1
+ 1
+
+
+
+ 10
+ 27
+ 0.298
+ 0.166
+ 1
+ 1
+
+
+ 40
+ 32
+ 0.326
+ 0.190
+ 1
+ 1
+
+
+ 1
+ 27
+ 0.298
+ 0.166
+ 1
+ 1
+
+
+
+ 10
+ 27
+ 0.298
+ 0.166
+ 1
+ 1
+
+
+ 40
+ 32
+ 0.326
+ 0.190
+ 1
+ 1
+
+
+ 0
+ 1
+ 27
+ 0.298
+ 0.166
+ 0
+ 1
+ 1
+
+
+
+
+ LayingPawn
+
+
+ 27
+ 0
+ 10
+ 16.6
+ -0.217
+ 0.175
+ 3
+ 1
+ 1
+
+
+
+ 40
+ Fuck
+ -17
+ -0.217
+ 0.272
+ 5.4
+ 1
+ 1
+
+
+ 1
+ 16.6
+ -0.217
+ 0.175
+ 3
+ 1
+ 1
+ 0
+ 27
+
+
+
+
+
+
+ Fast_Fuck
+ true
+ 609
+ 0
+
+
+
+
+ 8
+ 27
+ 0.298
+ 0.166
+ 1
+ 1
+ 1
+ 0
+
+
+ 12
+ 32
+ 0.326
+ 0.190
+ 4
+ 1
+ 1
+
+
+ 1
+ 27
+ 0.298
+ 0.166
+ 1
+ 1
+ 1
+ 0
+
+
+
+
+ LayingPawn
+
+
+ 27
+ 8
+ 11
+ -0.217
+ 0.175
+ 8
+ 1
+ 1
+ 0
+
+
+
+ 12
+ Fuck
+ -12
+ -0.217
+ 0.272
+ 9
+ 1
+ 1
+
+
+ 1
+ 11
+ -0.217
+ 0.175
+ 8
+ 1
+ 1
+ 0
+ 27
+
+
+
+
+
+
+ Cum
+ true
+ 300
+ 0
+
+
+
+
+ 8
+ 27
+ 0.298
+ 0.166
+ 0
+ 1
+ 1
+ 0
+
+
+ Cum
+ 100
+ 32
+ 0.326
+ 0.190
+ -1
+ 1
+ 1
+ true
+
+
+ 12
+ 35
+ 0.326
+ 0.190
+ -14
+ 1
+ 1
+
+
+ 1
+ 27
+ 0.298
+ 0.166
+ 0
+ 1
+ 1
+ 0
+
+
+
+
+ LayingPawn
+
+
+ 27
+ 8
+ 11
+ -0.217
+ 0.175
+ -8
+ 1
+ 1
+ 0
+
+
+ 100
+ -12
+ -0.217
+ 0.272
+ -9
+ 1
+ 1
+
+
+ 12
+ -15
+ -0.227
+ 0.272
+ -4
+ 1
+ 1
+
+
+ 1
+ 11
+ -0.217
+ 0.175
+ -8
+ 1
+ 1
+ 0
+ 27
+
+
+
+
+
+
+
+
+ Blowjob
+ blowjob
+ true
+
+ Oral
+ Fellatio
+
+
+ Handjob
+ HandjobF
+ HandjobRape
+ HandjobRapeF
+
+ Breastjob
+ BreastjobF
+ BreastjobRape
+ BreastjobRapeF
+
+ Fellatio
+ FellatioF
+ FellatioRape
+ FellatioRapeF
+
+ Beakjob
+ BeakjobF
+ BeakjobRape
+ BeakjobRapeF
+
+
+
+
+
+
+
+ Human
+
+
+ (0, -0.2)
+
+
+
+
+ Human
+
+ true
+ true
+ true
+
+ (0, 0.2)
+
+
+
+
+
+ Slow_Suck
+ true
+ 1140
+ 0
+
+
+
+
+ 35
+ 0
+ 0
+ 0
+ -0.255
+ 0
+ 0
+ 0
+
+
+ Suck
+ 59
+ 0
+ 0
+ -0.33
+ 0
+ 0
+ -0.16
+
+
+ 1
+ 0
+ 0
+ 0
+ -0.255
+ 0
+ 0
+ 0
+
+
+
+ 35
+ 0
+ 0
+ 0
+ -0.255
+ 0
+ 0
+ 0
+
+
+ Suck
+ 59
+ 0
+ 0
+ -0.33
+ 0
+ 0
+ -0.15
+
+
+ 1
+ 0
+ 0
+ 0
+ -0.255
+ 0
+ 0
+ 0
+
+
+
+ 35
+ 0
+ 0
+ 0
+ -0.255
+ 0
+ 0
+ 0
+
+
+ Suck
+ 59
+
+ 6
+ 0
+ -0.33
+ 0
+ 0
+ -0.13
+
+
+ 1
+ 0
+ 0
+ 0
+ -0.255
+ 0
+ 0
+ 0
+
+
+
+ 35
+ 0
+ 0
+ 0
+ -0.255
+ 0
+ 0
+ 0
+
+
+ Suck
+ 59
+ 0
+ -4
+ 0
+ -0.33
+ 0
+ 0
+ -0.12
+
+
+ 1
+ 0
+ 0
+ 0
+ -0.255
+ 0
+ 0
+ 0
+
+
+
+
+ LayingPawn
+
+
+ 35
+ 0
+ 0
+ 0
+ 0.473
+ 2
+ 2
+ 0
+ 180
+
+
+ 59
+ 0
+ 0
+ 0.490
+ 2
+ 2
+ -0.003
+
+
+ 1
+ 0
+ 0
+ 0
+ 0.473
+ 2
+ 2
+ 0
+ 180
+
+
+
+
+
+
+ Face_Fuck
+ true
+ 300
+ 0
+
+
+
+
+ 15
+ 0
+ 0
+ 0
+ -0.255
+ 0
+ 0
+ 0
+
+
+ Suck
+ 14
+ 0
+ 0
+ -0.270
+ 0
+ 0
+ -0.06
+
+
+ 1
+ 0
+ 0
+ 0
+ -0.255
+ 0
+ 0
+ 0
+
+
+
+
+ LayingPawn
+
+
+ 15
+ 0
+ 0
+ 0
+ 0.473
+ 2
+ 2
+ 0
+ 180
+
+
+ 14
+ 0
+ 0
+ 0.575
+ 2
+ 2
+ -0.051
+
+
+ 1
+ 0
+ 0
+ 0
+ 0.473
+ 2
+ 2
+ 0
+ 180
+
+
+
+
+
+
+ Cum
+ true
+ 600
+ 0
+
+
+
+
+ 12
+ 0
+ 0
+ 0
+ -0.255
+ 0
+ 0
+ 0
+
+
+ 7
+ 0
+ 0
+ -0.290
+ 0
+ 0
+ -0.06
+
+
+ 7
+ Suck
+ 0
+ 0
+ -0.290
+ 0
+ 0
+ -0.008
+
+
+ 60
+ 0
+ 0
+ -0.290
+ 0
+ 0
+ -0.06
+
+
+ 14
+ 0
+ 0
+ -0.290
+ 0
+ 0
+ -0.06
+
+
+ 1
+ 0
+ 0
+ 0
+ -0.255
+ 0
+ 0
+ 0
+
+
+
+
+ LayingPawn
+
+
+ 12
+ 0
+ 0
+ 0
+ 0.473
+ 2
+ 2
+ 0
+ 180
+
+
+ 7
+ Cum
+ 0
+ 0
+ 0.575
+ 2
+ 2
+ -0.051
+
+
+ 7
+ 0
+ 0
+ 0.50
+ 2
+ 2
+ -0.04
+
+
+ true
+ 60
+ 0
+ 0
+ 0.575
+ 2
+ 2
+ -0.051
+
+
+ 14
+ 0
+ 0
+ 0.575
+ 2
+ 2
+ -0.051
+
+
+ 1
+ 0
+ 0
+ 0
+ 0.473
+ 2
+ 2
+ 0
+ 180
+
+
+
+
+
+
+
+
+
+ ReverseStandAndCarry
+ reverse stand-and-carry
+ true
+
+ Anal
+ Vaginal
+ DoublePenetration
+
+
+ AnalSex
+ AnalSexF
+ AnalRape
+ VaginalSex
+ VaginalSexF
+ VaginalRape
+
+
+
+
+
+ Human
+
+ true
+
+ (0, 0.2)
+
+
+
+
+ Human
+
+ true
+ true
+ true
+
+ (0, 0.2)
+
+
+
+
+
+
+ Slow_Fuck
+ true
+ 1080
+ 0
+
+
+
+
+ 30
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+ 29
+ 6.04
+ 15
+ -0.175
+ 0.437
+ 3
+ 3
+ 0
+
+
+ 1
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+
+
+ LayingPawn
+
+
+ 6
+ 30
+ -3.18
+ -0.41
+ 0.122
+ 0.356
+ 3
+ 3
+ 0
+
+
+ 40
+ Fuck
+ 29
+ 17.11
+ -2.87
+ 0.114
+ 0.359
+ 3
+ 3
+ 0
+
+
+ 1
+ -3.18
+ -0.41
+ 0.122
+ 0.356
+ 3
+ 3
+ 0
+ 6
+
+
+
+
+
+
+
+ Fast_Fuck
+ true
+ 780
+ 0
+
+
+
+
+ 6
+ 10.6
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+ 7
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+ 12
+ 6.04
+ 15
+ -0.175
+ 0.437
+ 3
+ 3
+ 0
+
+
+ 1
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+
+ 6
+ 10.6
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+ 7
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+ 12
+ 6.04
+ 15
+ -0.175
+ 0.437
+ 3
+ 3
+ 0
+
+
+ 1
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+
+
+ 6
+ 10.6
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 2
+ 0
+
+
+ 7
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 2
+ 0
+
+
+ 12
+ 6.04
+ 15
+ -0.175
+ 0.437
+ 3
+ 2
+ 0
+
+
+ 1
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 2
+ 0
+
+
+
+ 6
+ 10.6
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 2
+ 0
+
+
+ 7
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 2
+ 0
+
+
+ 12
+ 6.04
+ 15
+ -0.175
+ 0.437
+ 3
+ 2
+ 0
+
+
+ 1
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 2
+ 0
+
+
+
+ 6
+ 10.6
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 2
+ 0
+
+
+ 7
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 2
+ 0
+
+
+ 12
+ 6.04
+ 15
+ -0.175
+ 0.437
+ 3
+ 2
+ 0
+
+
+ 1
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 2
+ 0
+
+
+
+ 6
+ 10.6
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 2
+ 0
+
+
+ 7
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 2
+ 0
+
+
+ 12
+ 6.04
+ 15
+ -0.175
+ 0.437
+ 3
+ 2
+ 0
+
+
+ 1
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 2
+ 0
+
+
+
+ 6
+ 10.6
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 2
+ 0
+
+
+ 7
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 2
+ 0
+
+
+ 12
+ 6.04
+ 15
+ -0.175
+ 0.437
+ 3
+ 2
+ 0
+
+
+ 1
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 2
+ 0
+
+
+
+ 6
+ 10.6
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 2
+ 0
+
+
+ 7
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 2
+ 0
+
+
+ 12
+ 6.04
+ 15
+ -0.175
+ 0.437
+ 3
+ 2
+ 0
+
+
+ 1
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 2
+ 0
+
+
+
+ 6
+ 10.6
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 2
+ 0
+
+
+ 7
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 2
+ 0
+
+
+ 12
+ 6.04
+ 15
+ -0.175
+ 0.437
+ 3
+ 2
+ 0
+
+
+ 1
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 2
+ 0
+
+
+
+
+
+ 6
+ 10.6
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+ 7
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+ 12
+ 6.04
+ 15
+ -0.175
+ 0.437
+ 3
+ 3
+ 0
+
+
+ 1
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+
+ 6
+ 10.6
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+ 7
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+ 12
+ 6.04
+ 15
+ -0.175
+ 0.437
+ 3
+ 3
+ 0
+
+
+ 1
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+
+ 6
+ 10.6
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+ 7
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+ 12
+ 6.04
+ 15
+ -0.175
+ 0.437
+ 3
+ 3
+ 0
+
+
+ 1
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+
+ 6
+ 10.6
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+ 7
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+ 12
+ 6.04
+ 15
+ -0.175
+ 0.437
+ 3
+ 3
+ 0
+
+
+ 1
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+
+ 6
+ 10.6
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+ 7
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+ 12
+ 6.04
+ 15
+ -0.175
+ 0.437
+ 3
+ 3
+ 0
+
+
+ 1
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+
+ 6
+ 10.6
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+ 7
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+ 12
+ 6.04
+ 15
+ -0.175
+ 0.437
+ 3
+ 3
+ 0
+
+
+ 1
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+
+
+ LayingPawn
+
+
+ 6
+ 13
+ -3.18
+ -0.41
+ 0.122
+ 0.356
+ 3
+ 3
+ 0
+
+
+ 40
+ Fuck
+ 12
+ 17.11
+ -2.87
+ 0.114
+ 0.359
+ 3
+ 3
+ 0
+
+
+ 1
+ -3.18
+ -0.41
+ 0.122
+ 0.356
+ 3
+ 3
+ 0
+ 6
+
+
+
+
+
+
+
+ Cum
+ true
+ 415
+ 0
+
+
+
+
+ 3
+ 10.6
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+ 4
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+ 7
+ 6.04
+ 15
+ -0.175
+ 0.437
+ 3
+ 3
+ 0
+
+
+ 1
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+
+ 3
+ 10.6
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+ 4
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+ 7
+ 6.04
+ 15
+ -0.175
+ 0.437
+ 3
+ 3
+ 0
+
+
+ 1
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+
+ 3
+ 10.6
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+ 4
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+ 7
+ 6.04
+ 15
+ -0.175
+ 0.437
+ 3
+ 3
+ 0
+
+
+ 1
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+
+ 3
+ 10.6
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+ 4
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+ true
+ 75
+ 6.04
+ 15
+ -0.175
+ 0.437
+ 3
+ 3
+ 0
+
+
+ 27
+ 6.04
+ 15
+ -0.175
+ 0.437
+ 3
+ 3
+ 0
+
+
+ 1
+ 11.23
+ 11.23
+ -0.183
+ 0.468
+ 3
+ 3
+ 0
+
+
+
+
+ LayingPawn
+
+
+ 6
+ 7
+ -3.18
+ -0.41
+ 0.122
+ 0.356
+ 3
+ 3
+ 0
+
+
+ 40
+ Fuck
+ 7
+ 17.11
+ -2.87
+ 0.114
+ 0.359
+ 3
+ 3
+ 0
+
+
+ 6
+ 1
+ -3.18
+ -0.41
+ 0.122
+ 0.356
+ 3
+ 3
+ 0
+
+
+
+ 6
+ 7
+ -3.18
+ -0.41
+ 0.122
+ 0.356
+ 3
+ 3
+ 0
+
+
+ 40
+ Fuck
+ 7
+ 17.11
+ -2.87
+ 0.114
+ 0.359
+ 3
+ 3
+ 0
+
+
+ 6
+ 1
+ -3.18
+ -0.41
+ 0.122
+ 0.356
+ 3
+ 3
+ 0
+
+
+
+ 6
+ 7
+ -3.18
+ -0.41
+ 0.122
+ 0.356
+ 3
+ 3
+ 0
+
+
+ 40
+ Fuck
+ 7
+ 17.11
+ -2.87
+ 0.114
+ 0.359
+ 3
+ 3
+ 0
+
+
+ 6
+ 1
+ -3.18
+ -0.41
+ 0.122
+ 0.356
+ 3
+ 3
+ 0
+
+
+
+ 6
+ 7
+ -3.18
+ -0.41
+ 0.122
+ 0.356
+ 3
+ 3
+ 0
+
+
+ 40
+ Cum
+ 75
+ 17.11
+ -2.87
+ 0.114
+ 0.359
+ 3
+ 3
+ 0
+
+
+ 40
+ 27
+ 17.11
+ -2.87
+ 0.114
+ 0.359
+ 3
+ 3
+ 0
+
+
+ 6
+ 1
+ -3.18
+ -0.41
+ 0.122
+ 0.356
+ 3
+ 3
+ 0
+
+
+
+
+
+
+
+
+
+ Cowgirl
+ cowgirl
+ true
+
+ Anal
+ Vaginal
+ DoublePenetration
+
+
+
+ AnalSex
+ AnalSexF
+ AnalRapeF
+ VaginalSex
+ VaginalSexF
+ VaginalRapeF
+
+
+
+
+
+
+
+ Human
+
+ true
+ true
+
+ (0, 0.2)
+
+
+
+
+
+ Human
+
+ true
+ true
+
+ (0, -0.2)
+
+
+
+
+
+
+
+ Slow_Fuck
+ true
+ 1340
+ 0
+
+
+
+
+
+ 16
+ 0
+ 0
+ 0
+ 0.554
+ 2
+ 2
+ 0
+
+
+ 17
+ 3.5
+ 0
+ -0.03
+ 0.624
+ 2
+ 2
+ -0.02
+
+
+ 16
+ 0
+ 0
+ 0
+ 0.694
+ 2
+ 2
+ -0.03
+
+
+ 17
+ -3.5
+ 0
+ 0.03
+ 0.624
+ 2
+ 2
+ -0.02
+
+
+ 1
+ Fuck
+ 0
+ 0
+ 0
+ 0.554
+ 2
+ 2
+ 0
+
+
+
+ 16
+ 0
+ 0
+ 0
+ 0.554
+ 2
+ 2
+ 0
+
+
+ 17
+ 3.5
+ 0
+ -0.03
+ 0.624
+ 2
+ 2
+ -0.02
+
+
+ 16
+ 0
+ 0
+ 0
+ 0.694
+ 2
+ 2
+ -0.03
+
+
+ 17
+ -3.5
+ 0
+ 0.03
+ 0.624
+ 2
+ 2
+ -0.02
+
+
+ 1
+ Fuck
+ 0
+ 0
+ 0
+ 0.554
+ 2
+ 2
+ 0
+
+
+
+
+ 33
+ 0
+ 0
+ 0
+ 0.554
+ 2
+ 2
+ 0
+
+
+ 33
+ 0
+ 0
+ 0
+ 0.694
+ 2
+ 2
+ -0.03
+
+
+ 1
+ Fuck
+ 0
+ 0
+ 0
+ 0.554
+ 2
+ 2
+ 0
+
+
+
+ 33
+ 0
+ 0
+ 0
+ 0.554
+ 2
+ 2
+ 0
+
+
+ 33
+ 0
+ 0
+ 0
+ 0.694
+ 2
+ 2
+ -0.03
+
+
+ 1
+ Fuck
+ 0
+ 0
+ 0
+ 0.554
+ 2
+ 2
+ 0
+
+
+
+
+ LayingPawn
+
+
+ 16
+ 180
+ 180
+ 0
+ -0.363
+ 2
+ 2
+ 0
+ 0
+
+
+ 17
+ 180
+ 180
+ 0
+ -0.347
+ 2
+ 2
+ 0.015
+ -15
+
+
+ 16
+ 180
+ 180
+ 0
+ -0.331
+ 2
+ 2
+ 0.03
+ 0
+
+
+ 17
+ 180
+ 180
+ 0
+ -0.315
+ 2
+ 2
+ 0.045
+ 15
+
+
+ 1
+ 180
+ 180
+ 0
+ -0.363
+ 2
+ 2
+ 0
+ 0
+
+
+ 16
+ 180
+ 180
+ 0
+ -0.363
+ 2
+ 2
+ 0
+ 0
+
+
+ 17
+ 180
+ 180
+ 0
+ -0.347
+ 2
+ 2
+ 0.015
+ -15
+
+
+ 16
+ 180
+ 180
+ 0
+ -0.331
+ 2
+ 2
+ 0.03
+ 0
+
+
+ 17
+ 180
+ 180
+ 0
+ -0.315
+ 2
+ 2
+ 0.045
+ 15
+
+
+ 1
+ 180
+ 180
+ 0
+ -0.363
+ 2
+ 2
+ 0
+ 0
+
+
+ 33
+ 180
+ 180
+ 0
+ -0.363
+ 2
+ 2
+ 0
+ 0
+
+
+ 33
+ 180
+ 180
+ 0
+ -0.315
+ 2
+ 2
+ 0.045
+ 0
+
+
+ 1
+ 180
+ 180
+ 0
+ -0.363
+ 2
+ 2
+ 0
+ 0
+
+
+ 33
+ 180
+ 180
+ 0
+ -0.363
+ 2
+ 2
+ 0
+ 0
+
+
+ 33
+ 180
+ 180
+ 0
+ -0.315
+ 2
+ 2
+ 0.045
+ 0
+
+
+ 1
+ 180
+ 180
+ 0
+ -0.363
+ 2
+ 2
+ 0
+ 0
+
+
+
+
+
+
+ Fast_Fuck
+ true
+ 780
+ 0
+
+
+
+
+ 13
+ 0
+ 0
+ 0
+ 0.554
+ 2
+ 2
+ 0
+
+
+ 13
+ 0
+ 0
+ 0
+ 0.694
+ 2
+ 2
+ -0.03
+
+
+ 1
+ Fuck
+ 0
+ 0
+ 0
+ 0.554
+ 2
+ 2
+ 0
+
+
+
+
+ LayingPawn
+
+
+ 13
+ 180
+ 180
+ 0
+ -0.363
+ 2
+ 2
+ 0
+ 0
+
+
+ 13
+ 180
+ 180
+ 0
+ -0.313
+ 2
+ 2
+ 0.045
+ 0
+
+
+ 1
+ 180
+ 180
+ 0
+ -0.363
+ 2
+ 2
+ 0
+ 0
+
+
+
+
+
+
+ Cum
+ true
+ 594
+ 0
+
+
+
+
+ 10
+ 0
+ 0
+ 0
+ 0.554
+ 2
+ 2
+ 0
+
+
+ 10
+ 0
+ 0
+ 0
+ 0.694
+ 2
+ 2
+ -0.03
+
+
+ 1
+ Fuck
+ 0
+ 0
+ 0
+ 0.554
+ 2
+ 2
+ 0
+
+
+
+ 10
+ 0
+ 0
+ 0
+ 0.554
+ 2
+ 2
+ 0
+
+
+ 10
+ 0
+ 0
+ 0
+ 0.694
+ 2
+ 2
+ -0.03
+
+
+ 1
+ Fuck
+ 0
+ 0
+ 0
+ 0.554
+ 2
+ 2
+ 0
+
+
+
+ 10
+ 0
+ 0
+ 0
+ 0.554
+ 2
+ 2
+ 0
+
+
+ 10
+ 0
+ 0
+ 0
+ 0.694
+ 2
+ 2
+ -0.03
+
+
+ true
+ 45
+ Cum
+ 0
+ 0
+ 0
+ 0.554
+ 2
+ 2
+ 0
+
+
+ true
+ 40
+ 0
+ 0
+ 0
+ 0.534
+ 2
+ 2
+ 0
+
+
+ 1
+ 0
+ 0
+ 0
+ 0.554
+ 2
+ 2
+ 0
+
+
+
+
+ LayingPawn
+
+
+ 10
+ 180
+ 180
+ 0
+ -0.363
+ 2
+ 2
+ 0
+ 0
+
+
+ 10
+ 180
+ 180
+ 0
+ -0.313
+ 2
+ 2
+ 0.045
+
+
+ 1
+ 180
+ 180
+ 0
+ -0.363
+ 2
+ 2
+ 0
+
+
+
+ 10
+ 180
+ 180
+ 0
+ -0.363
+ 2
+ 2
+ 0
+
+
+ 10
+ 180
+ 180
+ 0
+ -0.313
+ 2
+ 2
+ 0.045
+
+
+ 1
+ 180
+ 180
+ 0
+ -0.363
+ 2
+ 2
+ 0
+
+
+
+ 10
+ 180
+ 180
+ 0
+ -0.363
+ 2
+ 2
+ 0
+
+
+ 10
+ 180
+ 180
+ 0
+ -0.313
+ 2
+ 2
+ 0.045
+
+
+ 45
+ 180
+ 180
+ 0
+ -0.363
+ 2
+ 2
+ 0
+
+
+ 40
+ 180
+ 180
+ 0
+ -0.363
+ 2
+ 2
+ 0
+
+
+ 1
+ 180
+ 180
+ 0
+ -0.363
+ 2
+ 2
+ 0
+ 0
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/1.4/Defs/AnimationDefs/TemplateAnimation.xml b/1.4/Defs/AnimationDefs/TemplateAnimation.xml
new file mode 100644
index 0000000..0305903
--- /dev/null
+++ b/1.4/Defs/AnimationDefs/TemplateAnimation.xml
@@ -0,0 +1,54 @@
+
+
+
+
diff --git a/1.4/Defs/MainTabDefs/MainButtonDef.xml b/1.4/Defs/MainTabDefs/MainButtonDef.xml
new file mode 100644
index 0000000..0674d24
--- /dev/null
+++ b/1.4/Defs/MainTabDefs/MainButtonDef.xml
@@ -0,0 +1,15 @@
+
+
+
+
+ OffsetManager
+ offset manager
+ Control pawn offsets
+ Rimworld_Animations.MainTabWindow_OffsetConfigure
+ 54
+ false
+ UI/MainTab
+ true
+
+
+
\ No newline at end of file
diff --git a/1.4/Defs/SoundDefs/Sounds_Sex.xml b/1.4/Defs/SoundDefs/Sounds_Sex.xml
new file mode 100644
index 0000000..f05a1a8
--- /dev/null
+++ b/1.4/Defs/SoundDefs/Sounds_Sex.xml
@@ -0,0 +1,212 @@
+
+
+
+
+ Cum
+ MapOnly
+
+ 1
+ 1
+
+
+
+
+ Sex/cum
+
+
+
+ 30
+ 40
+
+
+ 0.8
+ 1.2
+
+
+ 0
+ 51.86047
+
+ False
+
+
+
+
+ Sex
+ MapOnly
+
+ 1
+ 1
+
+
+
+
+ Sex/kucyu04
+
+
+
+ 16
+ 16
+
+
+ 0.8
+ 1.2
+
+
+ 0
+ 51.86047
+
+ False
+
+
+
+
+ Suck
+ MapOnly
+
+ 1
+ 1
+
+
+
+
+ Sex/Suck/Suck_1
+
+
+ Sex/Suck/Suck_2
+
+
+ Sex/Suck/Suck_3
+
+
+ Sex/Suck/Suck_4
+
+
+ Sex/Suck/Suck_5
+
+
+ Sex/Suck/Suck_6
+
+
+ Sex/Suck/Suck_7
+
+
+ Sex/Suck/Suck_8
+
+
+ Sex/Suck/Suck_9
+
+
+ Sex/Suck/Suck_10
+
+
+
+ 20
+ 35
+
+
+ 1.0
+ 1.0
+
+
+ 0
+ 51.86047
+
+ NeverTwice
+ false
+
+
+
+
+ Fuck
+ MapOnly
+
+ 1
+ 1
+
+
+
+
+ Sex/Clap_1
+
+
+ Sex/Clap_2
+
+
+ Sex/Clap_3
+
+
+ Sex/Clap_4
+
+
+ Sex/Clap_5
+
+
+ Sex/Clap_6
+
+
+ Sex/Clap_7
+
+
+ Sex/Clap_8
+
+
+
+ 45
+ 70
+
+
+ 1.0
+ 1.0
+
+
+ 0
+ 51.86047
+
+ NeverTwice
+ false
+
+
+
+
+ Slimy
+ MapOnly
+
+ 1
+ 1
+
+
+
+
+ Sex/Slime/Slimy1
+
+
+ Sex/Slime/Slimy2
+
+
+ Sex/Slime/Slimy3
+
+
+ Sex/Slime/Slimy4
+
+
+ Sex/Slime/Slimy5
+
+
+
+ 45
+ 75
+
+
+ 1.4
+ 1.8
+
+
+ 0
+ 100
+
+ NeverTwice
+ false
+
+
+
+
\ No newline at end of file
diff --git a/1.4/Patch_HatsDisplaySelection/Patch_HatsDisplaySelection.csproj b/1.4/Patch_HatsDisplaySelection/Patch_HatsDisplaySelection.csproj
new file mode 100644
index 0000000..8da21a6
--- /dev/null
+++ b/1.4/Patch_HatsDisplaySelection/Patch_HatsDisplaySelection.csproj
@@ -0,0 +1,75 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {BA766964-1716-422D-A09E-29426F8EB9D5}
+ Library
+ Properties
+ Patch_HatsDisplaySelection
+ Patch_HatsDisplaySelection
+ v4.7.2
+ 512
+ true
+
+
+ false
+ none
+ false
+ 1.2\Assemblies\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\..\..\..\..\workshop\content\294100\2009463077\Current\Assemblies\0Harmony.dll
+ False
+
+
+ ..\..\..\RimWorldWin64_Data\Managed\Assembly-CSharp.dll
+ False
+
+
+ ..\..\..\..\..\workshop\content\294100\1542291825\1.2\Assemblies\HatDisplaySelection.dll
+ False
+
+
+ ..\1.2\Assemblies\Rimworld-Animations.dll
+ False
+
+
+
+
+
+
+
+
+
+
+ ..\..\..\RimWorldWin64_Data\Managed\UnityEngine.dll
+ False
+
+
+ ..\..\..\RimWorldWin64_Data\Managed\UnityEngine.CoreModule.dll
+ False
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/1.4/Patches/AnimationPatchHSK.xml b/1.4/Patches/AnimationPatchHSK.xml
new file mode 100644
index 0000000..74038ea
--- /dev/null
+++ b/1.4/Patches/AnimationPatchHSK.xml
@@ -0,0 +1,31 @@
+
+
+
+
+ Core SK
+
+
+
+
+
+ Defs/ThingDef/comps
+ Always
+
+ Defs/ThingDef
+
+
+
+
+
+
+
+ Defs/ThingDef[@Name="BaseAnimalPawn" or @Name="SK_BasePawn" or @Name="BasePawnSkynet"]/comps
+
+
+
+
+
+
+
+
+
diff --git a/1.4/Patches/AnimationPatch_CompBodyAnimator.xml b/1.4/Patches/AnimationPatch_CompBodyAnimator.xml
new file mode 100644
index 0000000..e645747
--- /dev/null
+++ b/1.4/Patches/AnimationPatch_CompBodyAnimator.xml
@@ -0,0 +1,35 @@
+
+
+
+ Always
+
+
+ Always
+ Defs/ThingDef[race][not(comps)]
+
+
+
+
+
+ Always
+ Defs/AlienRace.ThingDef_AlienRace[not(comps)]
+
+
+
+
+
+
+ Defs/ThingDef[@Name="BasePawn"]/comps
+
+
+
+
+
+ Defs/AlienRace.ThingDef_AlienRace/comps
+
+
+
+
+
+
+
diff --git a/1.4/Patches/CompPatches/AutoCleaner.xml b/1.4/Patches/CompPatches/AutoCleaner.xml
new file mode 100644
index 0000000..c2ad860
--- /dev/null
+++ b/1.4/Patches/CompPatches/AutoCleaner.xml
@@ -0,0 +1,19 @@
+
+
+
+ Always
+
+
+ /Defs/ThingDef[@Name="BaseBaseAutocleaner"]/comps
+ Always
+
+ /Defs/ThingDef[@Name="BaseBaseAutocleaner"]/comps
+
+
+
+
+
+
+
+
+
diff --git a/1.4/Patches/CompPatches/CombatExtended.xml b/1.4/Patches/CompPatches/CombatExtended.xml
new file mode 100644
index 0000000..7d35127
--- /dev/null
+++ b/1.4/Patches/CompPatches/CombatExtended.xml
@@ -0,0 +1,18 @@
+
+
+
+ Always
+
+
+ /Defs/ThingDef[@Name="BasePawnSimple"]/comps
+ Always
+
+ /Defs/ThingDef[@Name="BasePawnSimple"]/comps
+
+
+
+
+
+
+
+
diff --git a/1.4/Patches/CompPatches/ZombieLand.xml b/1.4/Patches/CompPatches/ZombieLand.xml
new file mode 100644
index 0000000..e950e0e
--- /dev/null
+++ b/1.4/Patches/CompPatches/ZombieLand.xml
@@ -0,0 +1,18 @@
+
+
+
+ Always
+
+
+ /Defs/ThingDef[@Name="BaseZombie"]/comps
+ Always
+
+ /Defs/ThingDef[@Name="BaseZombie"]/comps
+
+
+
+
+
+
+
+
diff --git a/1.4/Patches/CompatibilityPatch_FacialAnimation.xml b/1.4/Patches/CompatibilityPatch_FacialAnimation.xml
new file mode 100644
index 0000000..125d79f
--- /dev/null
+++ b/1.4/Patches/CompatibilityPatch_FacialAnimation.xml
@@ -0,0 +1,130 @@
+
+
+
+
+ [NL] Facial Animation - WIP
+
+
+ Always
+
+
+ /Defs/FacialAnimation.FaceAnimationDef[defName="Lovin" or defName="Lovin2"]/targetJobs
+ Always
+
+ RJW_Masturbate
+ GettinBred
+ Bestiality
+ BestialityForFemale
+ ViolateCorpse
+ Quickie
+ GettingQuickie
+ GettinRaped
+ JoinInBed
+ GettinLoved
+ GettinLicked
+ GettinSucked
+ WhoreIsServingVisitors
+ JoinInBedAnimation
+ GettinLovedAnimation
+
+
+
+ /Defs/FacialAnimation.FaceAnimationDef[defName="WaitCombat" or defName="Wait_Combat_Rare"]/targetJobs
+ Always
+
+ RapeComfortPawn
+ RandomRape
+ RapeEnemy
+
+
+
+ /Defs/FacialAnimation.FaceAnimationDef[defName="StandAndBeSociallyActive"]/targetJobs
+ Always
+
+ WhoreInvitingVisitors
+
+
+
+ /Defs/FacialAnimation.FaceAnimationDef[defName="Wear" or defName="Wear2" or defName="Wear3"]/targetJobs
+ Always
+
+ CleanSelf
+ StruggleInBondageGear
+
+
+
+
+ Rimworld-Animations
+
+
+ Always
+
+
+ /Defs/FacialAnimation.FaceAnimationDef[defName="Lovin" or defName="Lovin2"]/animationFrames/li[1]/headOffset
+ Always
+
+
+ /Defs/FacialAnimation.FaceAnimationDef[defName="Lovin"]/animationFrames/li[2]/headOffset
+ Always
+
+
+ /Defs/FacialAnimation.FaceAnimationDef[defName="Lovin"]/animationFrames/li[3]/headOffset
+ Always
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/1.4/Patches/CompatibilityPatch_HCSK.xml b/1.4/Patches/CompatibilityPatch_HCSK.xml
new file mode 100644
index 0000000..ead8783
--- /dev/null
+++ b/1.4/Patches/CompatibilityPatch_HCSK.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+ Core SK
+
+
+ Always
+
+
+ /Defs/ThingDef/comps
+ Always
+
+ /Defs/ThingDef
+
+
+
+
+
+
+
+ /Defs/ThingDef[@Name="SK_BasePawn"]/comps
+
+
+
+
+
+
+ /Defs/ThingDef[@Name="BaseAnimalPawn"]/comps
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/1.4/Patches/RacePatches/Epona race Renaissance.xml b/1.4/Patches/RacePatches/Epona race Renaissance.xml
new file mode 100644
index 0000000..f39b509
--- /dev/null
+++ b/1.4/Patches/RacePatches/Epona race Renaissance.xml
@@ -0,0 +1,19 @@
+
+
+
+
+ Epona race Renaissance
+
+
+
+
+ /Defs/AlienRace.ThingDef_AlienRace[defName = "Alien_Epona"]/alienRace/generalSettings/alienPartGenerator/bodyAddons/li[hediffGraphics/Epona_OHPG_female="Things/Pawn/Addons/Breasts/Breasts"]/drawnInBed
+
+ false
+
+
+
+
+
+
+
diff --git a/1.4/Patches/RacePatches/Nyaron.xml b/1.4/Patches/RacePatches/Nyaron.xml
new file mode 100644
index 0000000..0a7a08e
--- /dev/null
+++ b/1.4/Patches/RacePatches/Nyaron.xml
@@ -0,0 +1,19 @@
+
+
+
+
+ Nyaron race
+
+
+
+
+ /Defs/AlienRace.ThingDef_AlienRace[defName = "Alien_Nyaron"]/alienRace/generalSettings/alienPartGenerator/bodyAddons/li[bodyPart="tail"]
+
+ false
+
+
+
+
+
+
+
diff --git a/1.4/Sounds/Sex/Clap_1.wav b/1.4/Sounds/Sex/Clap_1.wav
new file mode 100644
index 0000000..bccd0f2
Binary files /dev/null and b/1.4/Sounds/Sex/Clap_1.wav differ
diff --git a/1.4/Sounds/Sex/Clap_2.wav b/1.4/Sounds/Sex/Clap_2.wav
new file mode 100644
index 0000000..a382f59
Binary files /dev/null and b/1.4/Sounds/Sex/Clap_2.wav differ
diff --git a/1.4/Sounds/Sex/Clap_3.wav b/1.4/Sounds/Sex/Clap_3.wav
new file mode 100644
index 0000000..65cf39b
Binary files /dev/null and b/1.4/Sounds/Sex/Clap_3.wav differ
diff --git a/1.4/Sounds/Sex/Clap_4.wav b/1.4/Sounds/Sex/Clap_4.wav
new file mode 100644
index 0000000..3ae1b3e
Binary files /dev/null and b/1.4/Sounds/Sex/Clap_4.wav differ
diff --git a/1.4/Sounds/Sex/Clap_5.wav b/1.4/Sounds/Sex/Clap_5.wav
new file mode 100644
index 0000000..65144e7
Binary files /dev/null and b/1.4/Sounds/Sex/Clap_5.wav differ
diff --git a/1.4/Sounds/Sex/Clap_6.wav b/1.4/Sounds/Sex/Clap_6.wav
new file mode 100644
index 0000000..0026325
Binary files /dev/null and b/1.4/Sounds/Sex/Clap_6.wav differ
diff --git a/1.4/Sounds/Sex/Clap_7.wav b/1.4/Sounds/Sex/Clap_7.wav
new file mode 100644
index 0000000..6d7de2a
Binary files /dev/null and b/1.4/Sounds/Sex/Clap_7.wav differ
diff --git a/1.4/Sounds/Sex/Clap_8.wav b/1.4/Sounds/Sex/Clap_8.wav
new file mode 100644
index 0000000..1af5710
Binary files /dev/null and b/1.4/Sounds/Sex/Clap_8.wav differ
diff --git a/1.4/Sounds/Sex/Slime/Slimy1.wav b/1.4/Sounds/Sex/Slime/Slimy1.wav
new file mode 100644
index 0000000..3cfbd74
Binary files /dev/null and b/1.4/Sounds/Sex/Slime/Slimy1.wav differ
diff --git a/1.4/Sounds/Sex/Slime/Slimy2.wav b/1.4/Sounds/Sex/Slime/Slimy2.wav
new file mode 100644
index 0000000..36a9197
Binary files /dev/null and b/1.4/Sounds/Sex/Slime/Slimy2.wav differ
diff --git a/1.4/Sounds/Sex/Slime/Slimy3.wav b/1.4/Sounds/Sex/Slime/Slimy3.wav
new file mode 100644
index 0000000..40aff1e
Binary files /dev/null and b/1.4/Sounds/Sex/Slime/Slimy3.wav differ
diff --git a/1.4/Sounds/Sex/Slime/Slimy4.wav b/1.4/Sounds/Sex/Slime/Slimy4.wav
new file mode 100644
index 0000000..0b6404e
Binary files /dev/null and b/1.4/Sounds/Sex/Slime/Slimy4.wav differ
diff --git a/1.4/Sounds/Sex/Slime/Slimy5.wav b/1.4/Sounds/Sex/Slime/Slimy5.wav
new file mode 100644
index 0000000..ea310db
Binary files /dev/null and b/1.4/Sounds/Sex/Slime/Slimy5.wav differ
diff --git a/1.4/Sounds/Sex/Suck/Suck_1.wav b/1.4/Sounds/Sex/Suck/Suck_1.wav
new file mode 100644
index 0000000..4f1eafd
Binary files /dev/null and b/1.4/Sounds/Sex/Suck/Suck_1.wav differ
diff --git a/1.4/Sounds/Sex/Suck/Suck_10.wav b/1.4/Sounds/Sex/Suck/Suck_10.wav
new file mode 100644
index 0000000..284cda3
Binary files /dev/null and b/1.4/Sounds/Sex/Suck/Suck_10.wav differ
diff --git a/1.4/Sounds/Sex/Suck/Suck_2.wav b/1.4/Sounds/Sex/Suck/Suck_2.wav
new file mode 100644
index 0000000..a8305c1
Binary files /dev/null and b/1.4/Sounds/Sex/Suck/Suck_2.wav differ
diff --git a/1.4/Sounds/Sex/Suck/Suck_3.wav b/1.4/Sounds/Sex/Suck/Suck_3.wav
new file mode 100644
index 0000000..95e7348
Binary files /dev/null and b/1.4/Sounds/Sex/Suck/Suck_3.wav differ
diff --git a/1.4/Sounds/Sex/Suck/Suck_4.wav b/1.4/Sounds/Sex/Suck/Suck_4.wav
new file mode 100644
index 0000000..753a023
Binary files /dev/null and b/1.4/Sounds/Sex/Suck/Suck_4.wav differ
diff --git a/1.4/Sounds/Sex/Suck/Suck_5.wav b/1.4/Sounds/Sex/Suck/Suck_5.wav
new file mode 100644
index 0000000..8ecda9c
Binary files /dev/null and b/1.4/Sounds/Sex/Suck/Suck_5.wav differ
diff --git a/1.4/Sounds/Sex/Suck/Suck_6.wav b/1.4/Sounds/Sex/Suck/Suck_6.wav
new file mode 100644
index 0000000..08567d6
Binary files /dev/null and b/1.4/Sounds/Sex/Suck/Suck_6.wav differ
diff --git a/1.4/Sounds/Sex/Suck/Suck_7.wav b/1.4/Sounds/Sex/Suck/Suck_7.wav
new file mode 100644
index 0000000..a63b0e4
Binary files /dev/null and b/1.4/Sounds/Sex/Suck/Suck_7.wav differ
diff --git a/1.4/Sounds/Sex/Suck/Suck_8.wav b/1.4/Sounds/Sex/Suck/Suck_8.wav
new file mode 100644
index 0000000..320da09
Binary files /dev/null and b/1.4/Sounds/Sex/Suck/Suck_8.wav differ
diff --git a/1.4/Sounds/Sex/Suck/Suck_9.wav b/1.4/Sounds/Sex/Suck/Suck_9.wav
new file mode 100644
index 0000000..7ab538a
Binary files /dev/null and b/1.4/Sounds/Sex/Suck/Suck_9.wav differ
diff --git a/1.4/Sounds/Sex/Suck/Swallow_1.wav b/1.4/Sounds/Sex/Suck/Swallow_1.wav
new file mode 100644
index 0000000..f3276cc
Binary files /dev/null and b/1.4/Sounds/Sex/Suck/Swallow_1.wav differ
diff --git a/1.4/Sounds/Sex/Suck/Swallow_2.wav b/1.4/Sounds/Sex/Suck/Swallow_2.wav
new file mode 100644
index 0000000..09a7a00
Binary files /dev/null and b/1.4/Sounds/Sex/Suck/Swallow_2.wav differ
diff --git a/1.4/Sounds/Sex/Suck/Swallow_3.wav b/1.4/Sounds/Sex/Suck/Swallow_3.wav
new file mode 100644
index 0000000..2817b29
Binary files /dev/null and b/1.4/Sounds/Sex/Suck/Swallow_3.wav differ
diff --git a/1.4/Sounds/Sex/cum.wav b/1.4/Sounds/Sex/cum.wav
new file mode 100644
index 0000000..ef98437
Binary files /dev/null and b/1.4/Sounds/Sex/cum.wav differ
diff --git a/1.4/Sounds/Sex/kucyu04.wav b/1.4/Sounds/Sex/kucyu04.wav
new file mode 100644
index 0000000..3ae1ce8
Binary files /dev/null and b/1.4/Sounds/Sex/kucyu04.wav differ
diff --git a/1.4/Source/Actors/Actor.cs b/1.4/Source/Actors/Actor.cs
new file mode 100644
index 0000000..3b382dd
--- /dev/null
+++ b/1.4/Source/Actors/Actor.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using UnityEngine;
+using Verse;
+
+namespace Rimworld_Animations {
+ public class Actor {
+ public List defNames;
+ public List requiredGenitals;
+ public List raceOffsets;
+ public List blacklistedRaces;
+ public bool initiator = false;
+ public string gender;
+ public bool isFucking = false;
+ public bool isFucked = false;
+ public bool controlGenitalAngle = false;
+ public List bodyDefTypes = new List();
+ public BodyTypeOffset bodyTypeOffset = new BodyTypeOffset();
+ public Vector3 offset = new Vector2(0, 0);
+ public List requiredGender;
+ public List tags = new List();
+ }
+}
diff --git a/Source/Comps/CompProperties_ThingAnimator.cs b/1.4/Source/Actors/AlienRaceOffset.cs
similarity index 57%
rename from Source/Comps/CompProperties_ThingAnimator.cs
rename to 1.4/Source/Actors/AlienRaceOffset.cs
index f9b76bd..a5bbe20 100644
--- a/Source/Comps/CompProperties_ThingAnimator.cs
+++ b/1.4/Source/Actors/AlienRaceOffset.cs
@@ -3,9 +3,13 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using UnityEngine;
namespace Rimworld_Animations {
- class CompProperties_ThingAnimator
- {
+ public class AlienRaceOffset {
+
+ public string defName;
+ public Vector2 offset;
+
}
}
diff --git a/1.4/Source/Actors/BodyTypeOffset.cs b/1.4/Source/Actors/BodyTypeOffset.cs
new file mode 100644
index 0000000..82a23a3
--- /dev/null
+++ b/1.4/Source/Actors/BodyTypeOffset.cs
@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using UnityEngine;
+
+namespace Rimworld_Animations {
+ public class BodyTypeOffset {
+
+ public Vector2? Male;
+ public Vector2? Female;
+ public Vector2? Thin;
+ public Vector2? Hulk;
+ public Vector2? Fat;
+
+ }
+}
diff --git a/1.4/Source/Animations/AnimationStage.cs b/1.4/Source/Animations/AnimationStage.cs
new file mode 100644
index 0000000..7a1304e
--- /dev/null
+++ b/1.4/Source/Animations/AnimationStage.cs
@@ -0,0 +1,28 @@
+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 int playTimeTicksQuick = -1;
+ public bool isLooping;
+ public List animationClips;
+ public List tags = new List();
+
+ 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;
+ }
+ }
+ }
+ }
+}
diff --git a/1.4/Source/Animations/Clips/BaseAnimationClip.cs b/1.4/Source/Animations/Clips/BaseAnimationClip.cs
new file mode 100644
index 0000000..aa35b31
--- /dev/null
+++ b/1.4/Source/Animations/Clips/BaseAnimationClip.cs
@@ -0,0 +1,20 @@
+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 Dictionary SoundEffects = new Dictionary();
+ public List types; //types of participants
+ public int duration;
+ public abstract void buildSimpleCurves();
+ public string soundDef = null; //for playing sounds
+ public int actor;
+ public List tags = new List();
+ }
+}
diff --git a/1.4/Source/Animations/Clips/PawnAnimationClip.cs b/1.4/Source/Animations/Clips/PawnAnimationClip.cs
new file mode 100644
index 0000000..e9d2489
--- /dev/null
+++ b/1.4/Source/Animations/Clips/PawnAnimationClip.cs
@@ -0,0 +1,115 @@
+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 keyframes;
+ public AltitudeLayer layer = AltitudeLayer.Pawn;
+
+ public Dictionary quiver = new Dictionary();
+ public SimpleCurve GenitalAngle = new SimpleCurve();
+ 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.genitalAngle.HasValue)
+ GenitalAngle.Add((float)frame.atTick / (float)duration, frame.genitalAngle.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.genitalAngle.HasValue)
+ GenitalAngle.Add((float)keyframePosition / (float)duration, frame.genitalAngle.Value, true);
+
+ if (frame.soundEffect != null) {
+ SoundEffects.Add(keyframePosition, frame.soundEffect);
+ }
+
+ if(frame.tickDuration != 1 && frame.quiver.HasValue) {
+
+ quiver.Add(keyframePosition, true);
+ quiver.Add(keyframePosition + frame.tickDuration - 1, false);
+ }
+ keyframePosition += frame.tickDuration;
+
+ }
+
+ }
+
+ }
+
+ }
+}
diff --git a/1.4/Source/Animations/Clips/ThingAnimationClip.cs b/1.4/Source/Animations/Clips/ThingAnimationClip.cs
new file mode 100644
index 0000000..26f4d4c
--- /dev/null
+++ b/1.4/Source/Animations/Clips/ThingAnimationClip.cs
@@ -0,0 +1,74 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Verse;
+using RimWorld;
+
+namespace Rimworld_Animations {
+ public class ThingAnimationClip : BaseAnimationClip
+ {
+ public List keyframes;
+
+ public SimpleCurve PositionX = new SimpleCurve();
+ public SimpleCurve PositionZ = new SimpleCurve();
+ public SimpleCurve Rotation = new SimpleCurve();
+
+
+ public override void buildSimpleCurves() {
+ int duration = 0;
+ //getting the length of the whole clip
+ foreach (ThingKeyframe frame in keyframes)
+ {
+ duration += frame.tickDuration;
+ }
+
+ //guarantees loops don't get cut off mid-anim
+ this.duration = duration;
+
+ int keyframePosition = 0;
+ foreach (ThingKeyframe frame in keyframes)
+ {
+
+ if (frame.atTick.HasValue)
+ {
+ if (frame.positionX.HasValue)
+ PositionX.Add((float)frame.atTick / (float)duration, frame.positionX.Value, true);
+
+ if (frame.positionZ.HasValue)
+ PositionZ.Add((float)frame.atTick / (float)duration, frame.positionZ.Value, true);
+
+ if (frame.rotation.HasValue)
+ Rotation.Add((float)frame.atTick / (float)duration, frame.rotation.Value, true);
+
+ if (frame.soundEffect != null)
+ {
+ SoundEffects.Add((int)frame.atTick, frame.soundEffect);
+ }
+
+
+ }
+ else
+ {
+ if (frame.positionX.HasValue)
+ PositionX.Add((float)keyframePosition / (float)duration, frame.positionX.Value, true);
+
+ if (frame.positionZ.HasValue)
+ PositionZ.Add((float)keyframePosition / (float)duration, frame.positionZ.Value, true);
+
+ if (frame.rotation.HasValue)
+ Rotation.Add((float)keyframePosition / (float)duration, frame.rotation.Value, true);
+
+ if (frame.soundEffect != null)
+ {
+ SoundEffects.Add(keyframePosition, frame.soundEffect);
+ }
+ keyframePosition += frame.tickDuration;
+
+ }
+
+ }
+ }
+ }
+}
diff --git a/1.4/Source/Animations/Keyframes/Keyframe.cs b/1.4/Source/Animations/Keyframes/Keyframe.cs
new file mode 100644
index 0000000..8cd859d
--- /dev/null
+++ b/1.4/Source/Animations/Keyframes/Keyframe.cs
@@ -0,0 +1,15 @@
+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;
+ public float? atTick;
+ public string soundEffect;
+ public List tags = new List();
+ }
+}
diff --git a/1.4/Source/Animations/Keyframes/PawnKeyframe.cs b/1.4/Source/Animations/Keyframes/PawnKeyframe.cs
new file mode 100644
index 0000000..e710981
--- /dev/null
+++ b/1.4/Source/Animations/Keyframes/PawnKeyframe.cs
@@ -0,0 +1,28 @@
+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? genitalAngle;
+
+ public float? bodyOffsetZ;
+ public float? bodyOffsetX;
+
+ public float? headBob;
+ //todo: add headOffsets l/r?
+
+ public int? bodyFacing;
+ public int? headFacing;
+
+ public bool? quiver;
+
+ }
+}
diff --git a/Source/Comps/CompThingAnimator.cs b/1.4/Source/Animations/Keyframes/ThingKeyframe.cs
similarity index 53%
rename from Source/Comps/CompThingAnimator.cs
rename to 1.4/Source/Animations/Keyframes/ThingKeyframe.cs
index bb3c944..6604f5e 100644
--- a/Source/Comps/CompThingAnimator.cs
+++ b/1.4/Source/Animations/Keyframes/ThingKeyframe.cs
@@ -5,7 +5,14 @@ using System.Text;
using System.Threading.Tasks;
namespace Rimworld_Animations {
- class CompThingAnimator
+ public class ThingKeyframe : Keyframe
{
+
+ public float? positionX;
+ public float? positionZ;
+ public float? rotation;
+
+
+
}
}
diff --git a/1.4/Source/Comps/CompBodyAnimator.cs b/1.4/Source/Comps/CompBodyAnimator.cs
new file mode 100644
index 0000000..5d355a6
--- /dev/null
+++ b/1.4/Source/Comps/CompBodyAnimator.cs
@@ -0,0 +1,529 @@
+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 {
+ public 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) {
+ SexUtility.DrawNude(pawn);
+ } else {
+ pawn.Drawer.renderer.graphics.ResolveAllGraphics();
+ actorsInCurrentAnimation = null;
+ }
+
+ PortraitsCache.SetDirty(pawn);
+ }
+ }
+ private bool Animating = false;
+ private bool mirror = false, quiver = false, shiver = false;
+ private int actor;
+
+ private int lastDrawFrame = -1;
+
+ private int animTicks = 0, stageTicks = 0, clipTicks = 0;
+ private int curStage = 0;
+ private float clipPercent = 0;
+
+ public Vector3 anchor = Vector3.zero, deltaPos = Vector3.zero, headBob = Vector3.zero;
+ public float bodyAngle = 0, headAngle = 0, genitalAngle = 0;
+ public Rot4 headFacing = Rot4.North, bodyFacing = Rot4.North;
+
+ public List actorsInCurrentAnimation;
+
+ public bool controlGenitalAngle = false;
+ public bool fastAnimForQuickie = false;
+
+ private AnimationDef anim;
+ private AnimationStage stage {
+ get
+ {
+ return anim.animationStages[curStage];
+ }
+
+ }
+ private PawnAnimationClip clip => (PawnAnimationClip)stage.animationClips[actor];
+
+ public bool Mirror {
+ get {
+ return mirror;
+ }
+ }
+
+ public void setAnchor(IntVec3 pos)
+ {
+ anchor = pos.ToVector3Shifted();
+ }
+ public void setAnchor(Thing thing) {
+
+ //center on bed
+ 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, List actors, int actor, bool mirror = false, bool shiver = false, bool fastAnimForQuickie = false) {
+
+ actorsInCurrentAnimation = actors;
+
+ if (anim.actors.Count <= actor)
+ {
+ return;
+ }
+ AlienRaceOffset raceOffset = anim?.actors[actor]?.raceOffsets?.Find(x => x.defName == pawn.def.defName);
+
+ if (raceOffset != null) {
+ anchor.x += mirror ? raceOffset.offset.x * -1f : raceOffset.offset.x;
+ anchor.z += raceOffset.offset.y;
+ }
+
+ //change the offset based on pawn body type
+ if(pawn?.story?.bodyType != null) {
+ if (pawn.story.bodyType == BodyTypeDefOf.Fat && anim?.actors[actor]?.bodyTypeOffset?.Fat != null) {
+ anchor.x += anim.actors[actor].bodyTypeOffset.Fat.Value.x * (mirror ? -1f : 1f);
+ anchor.z += anim.actors[actor].bodyTypeOffset.Fat.Value.y;
+ }
+ else if (pawn.story.bodyType == BodyTypeDefOf.Female && anim?.actors[actor]?.bodyTypeOffset?.Female != null) {
+ anchor.x += anim.actors[actor].bodyTypeOffset.Female.Value.x * (mirror ? -1f : 1f);
+ anchor.z += anim.actors[actor].bodyTypeOffset.Female.Value.y;
+ }
+ else if (pawn.story.bodyType == BodyTypeDefOf.Male && anim?.actors[actor]?.bodyTypeOffset?.Male != null) {
+ anchor.x += anim.actors[actor].bodyTypeOffset.Male.Value.x * (mirror ? -1f : 1f);
+ anchor.z += anim.actors[actor].bodyTypeOffset.Male.Value.y;
+ }
+ else if (pawn.story.bodyType == BodyTypeDefOf.Thin && anim?.actors[actor]?.bodyTypeOffset?.Thin != null) {
+ anchor.x += anim.actors[actor].bodyTypeOffset.Thin.Value.x * (mirror ? -1f : 1f);
+ anchor.z += anim.actors[actor].bodyTypeOffset.Thin.Value.y;
+ }
+ else if (pawn.story.bodyType == BodyTypeDefOf.Hulk && anim?.actors[actor]?.bodyTypeOffset?.Hulk != null) {
+ anchor.x += anim.actors[actor].bodyTypeOffset.Hulk.Value.x * (mirror ? -1f : 1f);
+ anchor.z += anim.actors[actor].bodyTypeOffset.Hulk.Value.y;
+ }
+ }
+
+ pawn.jobs.posture = PawnPosture.Standing;
+
+ this.actor = actor;
+ this.anim = anim;
+ this.mirror = mirror;
+ this.fastAnimForQuickie = fastAnimForQuickie;
+
+ if (fastAnimForQuickie && anim.animationStages.Any(x => x.playTimeTicksQuick >= 0) == false)
+ {
+ curStage = 1;
+ animTicks = anim.animationStages[0].playTimeTicks;
+ } else
+ {
+ curStage = 0;
+ animTicks = 0;
+ }
+
+ stageTicks = 0;
+ clipTicks = 0;
+
+ quiver = false;
+ this.shiver = shiver && AnimationSettings.rapeShiver;
+
+ controlGenitalAngle = anim.actors[actor].controlGenitalAngle;
+
+ isAnimating = true;
+ //tick once for initialization
+ tickAnim();
+
+ }
+
+ public override void CompTick() {
+
+ base.CompTick();
+
+ if(isAnimating) {
+
+ GlobalTextureAtlasManager.TryMarkPawnFrameSetDirty(pawn);
+
+ if (pawn.Dead || pawn?.jobs?.curDriver == null || (pawn?.jobs?.curDriver != null && !(pawn?.jobs?.curDriver is rjw.JobDriver_Sex))) {
+ isAnimating = false;
+ }
+ else {
+ tickAnim();
+ }
+ }
+ }
+ public void animatePawnBody(ref Vector3 rootLoc, ref float angle, ref Rot4 bodyFacing) {
+
+ if(!isAnimating) {
+ return;
+ }
+ rootLoc = anchor + deltaPos;
+ angle = bodyAngle;
+ bodyFacing = this.bodyFacing;
+
+ }
+
+ public Rot4 AnimateHeadFacing()
+ {
+ return this.headFacing;
+ }
+
+
+ public void tickGraphics(PawnGraphicSet graphics) {
+ this.Graphics = graphics;
+ }
+
+ public void tickAnim() {
+
+
+
+ if (!isAnimating) return;
+
+ if (anim == null) {
+ isAnimating = false;
+ return;
+ }
+
+ animTicks++;
+
+ if (animTicks < anim.animationTimeTicks) {
+ tickStage();
+ } else {
+
+ if(LoopNeverending())
+ {
+ ResetOnLoop();
+ } else
+ {
+ isAnimating = false;
+ }
+
+
+ }
+
+
+
+ }
+
+ public void tickStage()
+ {
+
+ if(stage == null)
+ {
+ isAnimating = false;
+ return;
+ }
+
+ stageTicks++;
+
+ if(stageTicks >= stage.playTimeTicks || (fastAnimForQuickie && stage.playTimeTicksQuick >= 0 && stageTicks >= stage.playTimeTicksQuick)) {
+
+ curStage++;
+
+ stageTicks = 0;
+ clipTicks = 0;
+ clipPercent = 0;
+ }
+
+ if(curStage >= anim.animationStages.Count) {
+ if (LoopNeverending())
+ {
+ ResetOnLoop();
+ }
+ else
+ {
+ isAnimating = false;
+ pawn.jobs.curDriver.ReadyForNextToil();
+ }
+
+ } else {
+ tickClip();
+ }
+
+
+
+ }
+
+ public void tickClip() {
+
+ clipTicks++;
+
+ //play sound effect
+ if(rjw.RJWSettings.sounds_enabled && clip.SoundEffects.ContainsKey(clipTicks) && AnimationSettings.soundOverride) {
+
+
+ SoundInfo sound = new TargetInfo(pawn.Position, pawn.Map);
+ string soundEffectName = clip.SoundEffects[clipTicks];
+
+
+ if ((pawn.jobs.curDriver as JobDriver_Sex).isAnimalOnAnimal)
+ {
+ sound.volumeFactor *= RJWSettings.sounds_animal_on_animal_volume;
+ }
+
+ if(soundEffectName.StartsWith("Voiceline_"))
+ {
+ sound.volumeFactor *= RJWSettings.sounds_voice_volume;
+ }
+
+ if (clip.SoundEffects[clipTicks] == "Cum") {
+
+ sound.volumeFactor *= RJWSettings.sounds_cum_volume;
+ //considerApplyingSemen();
+
+ } else
+ {
+ sound.volumeFactor *= RJWSettings.sounds_sex_volume;
+ }
+
+ SoundDef.Named(soundEffectName).PlayOneShot(sound);
+
+ }
+ if(AnimationSettings.orgasmQuiver && clip.quiver.ContainsKey(clipTicks)) {
+ quiver = clip.quiver[clipTicks];
+ }
+
+ //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 considerApplyingSemen()
+ {
+ if(AnimationSettings.applySemenOnAnimationOrgasm && (pawn?.jobs?.curDriver is JobDriver_Sex))
+ {
+
+ if (anim.sexTypes.Contains((pawn.jobs.curDriver as JobDriver_Sex).Sexprops.sexType))
+ {
+ //SemenHelper.calculateAndApplySemen((pawn.jobs.curDriver as JobDriver_Sex).Sexprops);
+ }
+ }
+ }
+
+ public void calculateDrawValues() {
+
+ /*if(Find.TickManager.TickRateMultiplier > 1 && (lastDrawFrame + 1 >= RealTime.frameCount || RealTime.deltaTime < 0.05f)) {
+ return;
+ }*/
+
+ deltaPos = new Vector3(clip.BodyOffsetX.Evaluate(clipPercent) * (mirror ? -1 : 1), clip.layer.AltitudeFor(), clip.BodyOffsetZ.Evaluate(clipPercent));
+
+ string bodyTypeDef = (pawn.story?.bodyType != null) ? pawn.story.bodyType.ToString() : "";
+
+ if (AnimationSettings.offsets != null && AnimationSettings.offsets.ContainsKey(CurrentAnimation.defName + pawn.def.defName + bodyTypeDef + ActorIndex)) {
+ deltaPos.x += AnimationSettings.offsets[CurrentAnimation.defName + pawn.def.defName + bodyTypeDef + ActorIndex].x * (mirror ? -1 : 1);
+ deltaPos.z += AnimationSettings.offsets[CurrentAnimation.defName + pawn.def.defName + bodyTypeDef + ActorIndex].y;
+ }
+
+
+ bodyAngle = (clip.BodyAngle.Evaluate(clipPercent) + (quiver || shiver ? ((Rand.Value * AnimationSettings.shiverIntensity) - (AnimationSettings.shiverIntensity / 2f)) : 0f)) * (mirror ? -1 : 1);
+ headAngle = clip.HeadAngle.Evaluate(clipPercent) * (mirror ? -1 : 1);
+
+ if (controlGenitalAngle) {
+ genitalAngle = clip.GenitalAngle.Evaluate(clipPercent) * (mirror ? -1 : 1);
+ }
+
+ if (AnimationSettings.rotation != null && AnimationSettings.rotation.ContainsKey(CurrentAnimation.defName + pawn.def.defName + bodyTypeDef + ActorIndex)) {
+ float offsetRotation = AnimationSettings.rotation[CurrentAnimation.defName + pawn.def.defName + bodyTypeDef + ActorIndex] * (Mirror ? -1 : 1);
+ genitalAngle += offsetRotation;
+ bodyAngle += offsetRotation;
+ headAngle += offsetRotation;
+ }
+
+
+ //don't go past 360 or less than 0
+
+ if (bodyAngle < 0) bodyAngle = 360 - ((-1f*bodyAngle) % 360);
+ if (bodyAngle > 360) bodyAngle %= 360;
+
+
+ if (headAngle < 0) headAngle = 360 - ((-1f * headAngle) % 360);
+ if (headAngle > 360) headAngle %= 360;
+
+ if (genitalAngle < 0) genitalAngle = 360 - ((-1f * genitalAngle) % 360);
+ if (genitalAngle > 360) genitalAngle %= 360;
+
+
+ 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));
+ Vector2 bodyScale = (pawn.story?.bodyType?.bodyGraphicScale != null ? pawn.story.bodyType.bodyGraphicScale : Vector2.one);
+ headBob.z *= bodyScale.x;
+
+ lastDrawFrame = RealTime.frameCount;
+
+ }
+
+ public Vector3 getPawnHeadPosition() {
+
+ Vector3 headPos = anchor + deltaPos + Quaternion.AngleAxis(bodyAngle, Vector3.up) * (pawn.Drawer.renderer.BaseHeadOffsetAt(headFacing) + headBob);
+
+ return headPos;
+
+ }
+
+ public Vector3 getPawnHeadOffset()
+ {
+ return Quaternion.AngleAxis(bodyAngle, Vector3.up) * (pawn.Drawer.renderer.BaseHeadOffsetAt(headFacing) + headBob);
+
+ }
+
+ public AnimationDef CurrentAnimation {
+ get {
+ return anim;
+ }
+ }
+
+ public int ActorIndex {
+ get {
+ return actor;
+ }
+ }
+
+ public override void PostExposeData() {
+ base.PostExposeData();
+
+ Scribe_Defs.Look(ref anim, "RJWAnimations-Anim");
+
+ Scribe_Values.Look(ref animTicks, "RJWAnimations-animTicks", 1);
+ Scribe_Values.Look(ref stageTicks, "RJWAnimations-stageTicks", 1);
+ Scribe_Values.Look(ref clipTicks, "RJWAnimations-clipTicks", 1);
+ Scribe_Values.Look(ref clipPercent, "RJWAnimations-clipPercent", 1);
+ Scribe_Values.Look(ref mirror, "RJWAnimations-mirror");
+
+ Scribe_Values.Look(ref curStage, "RJWAnimations-curStage", 0);
+ Scribe_Values.Look(ref actor, "RJWAnimations-actor");
+
+ Scribe_Values.Look(ref anchor, "RJWAnimations-anchor");
+ Scribe_Values.Look(ref deltaPos, "RJWAnimations-deltaPos");
+ Scribe_Values.Look(ref headBob, "RJWAnimations-headBob");
+ Scribe_Values.Look(ref bodyAngle, "RJWAnimations-bodyAngle");
+ Scribe_Values.Look(ref headAngle, "RJWAnimations-headAngle");
+
+ Scribe_Values.Look(ref genitalAngle, "RJWAnimations-GenitalAngle");
+ Scribe_Values.Look(ref controlGenitalAngle, "RJWAnimations-controlGenitalAngle");
+
+ Scribe_Values.Look(ref headFacing, "RJWAnimations-headFacing");
+ Scribe_Values.Look(ref headFacing, "RJWAnimations-bodyFacing");
+
+ Scribe_Values.Look(ref quiver, "RJWAnimations-orgasmQuiver");
+ }
+
+ public void shiftActorPositionAndRestartAnimation() {
+ actor = (actor == anim.actors.Count - 1 ? 0 : actor + 1);
+
+ if (pawn?.story?.bodyType != null) {
+ if (pawn.story.bodyType == BodyTypeDefOf.Fat && anim?.actors[actor]?.bodyTypeOffset?.Fat != null) {
+ anchor.x += anim.actors[actor].bodyTypeOffset.Fat.Value.x * (mirror ? -1f : 1f);
+ anchor.z += anim.actors[actor].bodyTypeOffset.Fat.Value.y;
+ }
+ else if (pawn.story.bodyType == BodyTypeDefOf.Female && anim?.actors[actor]?.bodyTypeOffset?.Female != null) {
+ anchor.x += anim.actors[actor].bodyTypeOffset.Female.Value.x * (mirror ? -1f : 1f);
+ anchor.z += anim.actors[actor].bodyTypeOffset.Female.Value.y;
+ }
+ else if (pawn.story.bodyType == BodyTypeDefOf.Male && anim?.actors[actor]?.bodyTypeOffset?.Male != null) {
+ anchor.x += anim.actors[actor].bodyTypeOffset.Male.Value.x * (mirror ? -1f : 1f);
+ anchor.z += anim.actors[actor].bodyTypeOffset.Male.Value.y;
+ }
+ else if (pawn.story.bodyType == BodyTypeDefOf.Thin && anim?.actors[actor]?.bodyTypeOffset?.Thin != null) {
+ anchor.x += anim.actors[actor].bodyTypeOffset.Thin.Value.x * (mirror ? -1f : 1f);
+ anchor.z += anim.actors[actor].bodyTypeOffset.Thin.Value.y;
+ }
+ else if (pawn.story.bodyType == BodyTypeDefOf.Hulk && anim?.actors[actor]?.bodyTypeOffset?.Hulk != null) {
+ anchor.x += anim.actors[actor].bodyTypeOffset.Hulk.Value.x * (mirror ? -1f : 1f);
+ anchor.z += anim.actors[actor].bodyTypeOffset.Hulk.Value.y;
+ }
+ }
+
+ curStage = 0;
+ animTicks = 0;
+ stageTicks = 0;
+ clipTicks = 0;
+
+ controlGenitalAngle = anim.actors[actor].controlGenitalAngle;
+
+ tickAnim();
+ }
+
+ public bool LoopNeverending()
+ {
+ if(pawn?.jobs?.curDriver != null &&
+ (pawn.jobs.curDriver is JobDriver_Sex) && (pawn.jobs.curDriver as JobDriver_Sex).neverendingsex ||
+ (pawn.jobs.curDriver is JobDriver_SexBaseReciever) && (pawn.jobs.curDriver as JobDriver_Sex).Partner?.jobs?.curDriver != null && ((pawn.jobs.curDriver as JobDriver_Sex).Partner.jobs.curDriver as JobDriver_Sex).neverendingsex)
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ public void ResetOnLoop()
+ {
+ curStage = 1;
+ animTicks = 0;
+ stageTicks = 0;
+ clipTicks = 0;
+
+ tickAnim();
+ }
+ }
+}
diff --git a/1.4/Source/Comps/CompProperties_BodyAnimator.cs b/1.4/Source/Comps/CompProperties_BodyAnimator.cs
new file mode 100644
index 0000000..09df7ce
--- /dev/null
+++ b/1.4/Source/Comps/CompProperties_BodyAnimator.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Verse;
+using RimWorld;
+
+namespace Rimworld_Animations {
+ public class CompProperties_BodyAnimator : CompProperties
+ {
+ public CompProperties_BodyAnimator()
+ {
+ base.compClass = typeof(CompBodyAnimator);
+ }
+ }
+}
diff --git a/1.4/Source/Comps/CompProperties_ThingAnimator.cs b/1.4/Source/Comps/CompProperties_ThingAnimator.cs
new file mode 100644
index 0000000..34c67b1
--- /dev/null
+++ b/1.4/Source/Comps/CompProperties_ThingAnimator.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Verse;
+
+namespace Rimworld_Animations {
+ public class CompProperties_ThingAnimator : CompProperties
+ {
+
+ public CompProperties_ThingAnimator()
+ {
+ base.compClass = typeof(CompThingAnimator);
+ }
+ }
+}
diff --git a/1.4/Source/Comps/CompThingAnimator.cs b/1.4/Source/Comps/CompThingAnimator.cs
new file mode 100644
index 0000000..f5315e4
--- /dev/null
+++ b/1.4/Source/Comps/CompThingAnimator.cs
@@ -0,0 +1,245 @@
+using RimWorld;
+using rjw;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using UnityEngine;
+using Verse;
+
+namespace Rimworld_Animations {
+ public class CompThingAnimator : ThingComp
+ {
+ Vector3 anchor;
+
+ Pawn pawn;
+
+ public bool isAnimating = false, mirror;
+
+ int animTicks = 0, stageTicks = 0, clipTicks = 0, curStage = 0;
+ float rotation = 0;
+ float clipPercent = 0;
+
+ public Vector3 deltaPos;
+
+ AnimationDef anim;
+ private ThingAnimationClip clip => (ThingAnimationClip)stage.animationClips[1];
+ private AnimationStage stage
+ {
+ get
+ {
+ return anim.animationStages[curStage];
+ }
+
+ }
+
+ public void StartAnimation(AnimationDef anim, Pawn pawn, bool mirror = false)
+ {
+ isAnimating = true;
+
+ this.anim = anim;
+ this.pawn = pawn;
+ this.mirror = mirror;
+
+ animTicks = 0;
+ stageTicks = 0;
+ clipTicks = 0;
+
+ curStage = 0;
+ clipPercent = 0;
+
+ tickAnim();
+
+ }
+
+ public void setAnchor(IntVec3 position)
+ {
+ anchor = position.ToVector3();
+ }
+
+ public override void CompTick()
+ {
+ base.CompTick();
+
+ if(isAnimating)
+ {
+ if (pawn.Dead || pawn?.jobs?.curDriver == null || (pawn?.jobs?.curDriver != null && !(pawn?.jobs?.curDriver is rjw.JobDriver_Sex)))
+ {
+ isAnimating = false;
+ }
+ else
+ {
+ tickAnim();
+ }
+ }
+
+
+ }
+
+ public void tickAnim()
+ {
+ if (!isAnimating) return;
+ animTicks++;
+
+ if (animTicks < anim.animationTimeTicks)
+ {
+ tickStage();
+ }
+ else
+ {
+ if (LoopNeverending())
+ {
+ ResetOnLoop();
+ }
+ else
+ {
+ isAnimating = false;
+ }
+
+
+ }
+
+ }
+
+ public void tickStage()
+ {
+ if (stage == null)
+ {
+ isAnimating = false;
+ return;
+ }
+
+ stageTicks++;
+
+ if (stageTicks >= stage.playTimeTicks)
+ {
+
+ curStage++;
+
+ stageTicks = 0;
+ clipTicks = 0;
+ clipPercent = 0;
+ }
+
+ if (curStage >= anim.animationStages.Count)
+ {
+ if (LoopNeverending())
+ {
+ ResetOnLoop();
+ }
+ else
+ {
+ isAnimating = false;
+ }
+
+ }
+ else
+ {
+ tickClip();
+ }
+ }
+
+ public void tickClip()
+ {
+ clipTicks++;
+
+ 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 setAnchor(Thing thing)
+ {
+
+ //center on bed
+ 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();
+ }
+
+ anchor -= new Vector3(0.5f, 0, 0.5f);
+ }
+ private void calculateDrawValues()
+ {
+
+ //shift up and right 0.5f to align center
+ deltaPos = new Vector3((clip.PositionX.Evaluate(clipPercent)) * (mirror ? -1 : 1) + 0.5f, AltitudeLayer.Item.AltitudeFor(), clip.PositionZ.Evaluate(clipPercent) + 0.5f);
+ //Log.Message("Clip percent: " + clipPercent + " deltaPos: " + deltaPos);
+ rotation = clip.Rotation.Evaluate(clipPercent) * (mirror ? -1 : 1);
+ }
+
+ public void AnimateThing(Thing thing)
+ {
+ thing.Graphic.Draw(deltaPos + anchor, mirror ? Rot4.West : Rot4.East, thing, rotation);
+ }
+
+ public bool LoopNeverending()
+ {
+ if (pawn?.jobs?.curDriver != null &&
+ (pawn.jobs.curDriver is JobDriver_Sex) && (pawn.jobs.curDriver as JobDriver_Sex).neverendingsex)
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ public void ResetOnLoop()
+ {
+ curStage = 1;
+ animTicks = 0;
+ stageTicks = 0;
+ clipTicks = 0;
+
+ tickAnim();
+ }
+
+ }
+}
diff --git a/1.4/Source/Defs/AnimationDef.cs b/1.4/Source/Defs/AnimationDef.cs
new file mode 100644
index 0000000..395ff83
--- /dev/null
+++ b/1.4/Source/Defs/AnimationDef.cs
@@ -0,0 +1,28 @@
+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 animationStages;
+ public List actors;
+ public int animationTimeTicks = 0; //do not set manually
+ public bool sounds = false;
+ public List sexTypes = null;
+ public List interactionDefTypes = null;
+ public List tags = new List();
+
+ public override void PostLoad() {
+ base.PostLoad();
+ foreach(AnimationStage stage in animationStages) {
+ stage.initialize();
+ animationTimeTicks += stage.playTimeTicks;
+ }
+ }
+ }
+}
diff --git a/1.4/Source/Extensions/PawnWoundDrawerExtension.cs b/1.4/Source/Extensions/PawnWoundDrawerExtension.cs
new file mode 100644
index 0000000..417f8ed
--- /dev/null
+++ b/1.4/Source/Extensions/PawnWoundDrawerExtension.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Collections.Generic;
+using RimWorld;
+using UnityEngine;
+using Verse;
+using Rimworld_Animations;
+
+namespace Rimworld_Animations {
+
+ [StaticConstructorOnStartup]
+ public static class PawnWoundDrawerExtension
+ {
+ public static void RenderPawnOverlay(this PawnWoundDrawer pawnWoundDrawer, Vector3 drawLoc, Mesh bodyMesh, Quaternion quat, bool drawNow, PawnOverlayDrawer.OverlayLayer layer, Rot4 pawnRot, bool? overApparel = null, Pawn pawn = null, PawnRenderFlags flags = new PawnRenderFlags())
+ {
+ if (pawn == null)
+ { return; }
+
+ if (!flags.FlagSet(PawnRenderFlags.Portrait) && layer == PawnOverlayDrawer.OverlayLayer.Head)
+ {
+ CompBodyAnimator pawnAnimator = pawn.TryGetComp();
+ if (pawnAnimator != null && pawnAnimator.isAnimating && pawn.Drawer.renderer.graphics.headGraphic != null)
+ {
+ pawnRot = pawnAnimator.headFacing;
+ quat = Quaternion.AngleAxis(angle: pawnAnimator.headAngle, axis: Vector3.up);
+ float y = drawLoc.y;
+ drawLoc = pawnAnimator.getPawnHeadPosition() - Quaternion.AngleAxis(pawnAnimator.headAngle, Vector3.up) * pawn.Drawer.renderer.BaseHeadOffsetAt(pawnAnimator.headFacing);
+ drawLoc.y = y;
+ }
+ }
+
+ pawnWoundDrawer.RenderPawnOverlay(drawLoc, bodyMesh, quat, drawNow, layer, pawnRot, overApparel);
+ }
+ }
+
+}
diff --git a/1.4/Source/MainTabWindows/MainTabWindow_OffsetConfigure.cs b/1.4/Source/MainTabWindows/MainTabWindow_OffsetConfigure.cs
new file mode 100644
index 0000000..b7fef1d
--- /dev/null
+++ b/1.4/Source/MainTabWindows/MainTabWindow_OffsetConfigure.cs
@@ -0,0 +1,143 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Verse;
+using RimWorld;
+using UnityEngine;
+
+namespace Rimworld_Animations {
+ class MainTabWindow_OffsetConfigure : MainTabWindow
+ {
+
+ public override Vector2 RequestedTabSize => new Vector2(505, 380);
+ public override void DoWindowContents(Rect inRect) {
+
+ Rect position = new Rect(inRect.x, inRect.y, inRect.width, inRect.height);
+
+
+ Listing_Standard listingStandard = new Listing_Standard();
+ listingStandard.Begin(position);
+
+ listingStandard.Label("Animation Manager");
+
+ listingStandard.GapLine();
+
+
+ if (Find.Selector.SingleSelectedThing is Pawn) {
+
+ Pawn curPawn = Find.Selector.SingleSelectedThing as Pawn;
+
+ if (curPawn.TryGetComp().isAnimating) {
+
+ AnimationDef def = curPawn.TryGetComp().CurrentAnimation;
+ int ActorIndex = curPawn.TryGetComp().ActorIndex;
+ float offsetX = 0, offsetZ = 0, rotation = 0;
+
+ string bodyTypeDef = (curPawn.story?.bodyType != null) ? curPawn.story.bodyType.ToString() : "";
+
+ if (AnimationSettings.offsets.ContainsKey(def.defName + curPawn.def.defName + bodyTypeDef + ActorIndex)) {
+ offsetX = AnimationSettings.offsets[def.defName + curPawn.def.defName + bodyTypeDef + ActorIndex].x;
+ offsetZ = AnimationSettings.offsets[def.defName + curPawn.def.defName + bodyTypeDef + ActorIndex].y;
+ } else {
+ AnimationSettings.offsets.Add(def.defName + curPawn.def.defName + bodyTypeDef + ActorIndex, new Vector2(0, 0));
+ }
+
+ if (AnimationSettings.rotation.ContainsKey(def.defName + curPawn.def.defName + bodyTypeDef + ActorIndex)) {
+ rotation = AnimationSettings.rotation[def.defName + curPawn.def.defName + bodyTypeDef + ActorIndex];
+ }
+ else {
+ AnimationSettings.rotation.Add(def.defName + curPawn.def.defName + bodyTypeDef + ActorIndex, 0);
+ }
+
+ listingStandard.Label("Name: " + curPawn.Name + " Race: " + curPawn.def.defName + " Actor Index: " + curPawn.TryGetComp().ActorIndex + " Body Type (if any): " + bodyTypeDef + " Animation: " + def.label + (curPawn.TryGetComp().Mirror ? " mirrored" : ""));
+
+ if(curPawn.def.defName == "Human") {
+ listingStandard.Label("Warning--You generally don't want to change human offsets, only alien offsets");
+ }
+
+ bool mirrored = curPawn.TryGetComp().Mirror;
+
+ float.TryParse(listingStandard.TextEntryLabeled("X Offset: ", offsetX.ToString()), out offsetX);
+ offsetX = listingStandard.Slider(offsetX, -2 * (mirrored ? -1 : 1), 2 * (mirrored ? -1 : 1));
+
+ float.TryParse(listingStandard.TextEntryLabeled("Z Offset: ", offsetZ.ToString()), out offsetZ);
+ offsetZ = listingStandard.Slider(offsetZ, -2, 2);
+
+ float.TryParse(listingStandard.TextEntryLabeled("Rotation: ", rotation.ToString()), out rotation);
+ rotation = listingStandard.Slider(rotation, -180, 180);
+
+ if(listingStandard.ButtonText("Reset All")) {
+ offsetX = 0;
+ offsetZ = 0;
+ rotation = 0;
+ }
+
+ listingStandard.GapLine();
+
+ if(listingStandard.ButtonText("Shift Actors")) {
+
+ if(AnimationSettings.debugMode) {
+ Log.Message("Shifting actors in animation...");
+ }
+
+ for(int i = 0; i < curPawn.TryGetComp().actorsInCurrentAnimation.Count; i++) {
+
+ Pawn actor = curPawn.TryGetComp().actorsInCurrentAnimation[i];
+
+ actor.TryGetComp()?.shiftActorPositionAndRestartAnimation();
+
+ //reset the clock time of every pawn in animation
+ if(actor.jobs.curDriver is rjw.JobDriver_Sex) {
+ (actor.jobs.curDriver as rjw.JobDriver_Sex).ticks_left = def.animationTimeTicks;
+ (actor.jobs.curDriver as rjw.JobDriver_Sex).ticksLeftThisToil = def.animationTimeTicks;
+ (actor.jobs.curDriver as rjw.JobDriver_Sex).duration = def.animationTimeTicks;
+ }
+
+ }
+
+ }
+
+ if (offsetX != AnimationSettings.offsets[def.defName + curPawn.def.defName + bodyTypeDef + ActorIndex].x || offsetZ != AnimationSettings.offsets[def.defName + curPawn.def.defName + bodyTypeDef + ActorIndex].y) {
+ AnimationSettings.offsets[def.defName + curPawn.def.defName + bodyTypeDef + ActorIndex] = new Vector2(offsetX, offsetZ);
+
+ }
+
+ if(rotation != AnimationSettings.rotation[def.defName + curPawn.def.defName + bodyTypeDef + ActorIndex]) {
+ AnimationSettings.rotation[def.defName + curPawn.def.defName + bodyTypeDef + ActorIndex] = rotation;
+ }
+
+ }
+
+ }
+ else {
+ listingStandard.Label("Select a pawn currently in an animation to change their offsets");
+ }
+
+ listingStandard.End();
+
+ }
+
+ public override void PreOpen() {
+ base.PreOpen();
+ if(AnimationSettings.offsets == null) {
+ if (AnimationSettings.debugMode)
+ Log.Message("New offsets");
+ AnimationSettings.offsets = new Dictionary();
+ }
+
+ if(AnimationSettings.rotation == null) {
+ if (AnimationSettings.debugMode)
+ Log.Message("New rotation");
+ AnimationSettings.rotation = new Dictionary();
+ }
+ }
+
+ public override void PostClose() {
+ base.PostClose();
+
+ LoadedModManager.GetMod().WriteSettings();
+ }
+ }
+}
diff --git a/1.4/Source/MainTabWindows/OffsetMainButtonDefOf.cs b/1.4/Source/MainTabWindows/OffsetMainButtonDefOf.cs
new file mode 100644
index 0000000..e7ad9eb
--- /dev/null
+++ b/1.4/Source/MainTabWindows/OffsetMainButtonDefOf.cs
@@ -0,0 +1,22 @@
+using RimWorld;
+using Verse;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Rimworld_Animations {
+
+ [DefOf]
+ public static class OffsetMainButtonDefOf {
+
+ public static MainButtonDef OffsetManager;
+
+
+ static OffsetMainButtonDefOf() {
+ DefOfHelper.EnsureInitializedInCtor(typeof(OffsetMainButtonDefOf));
+ }
+
+ }
+}
diff --git a/1.4/Source/MainTabWindows/WorldComponent_UpdateMainTab.cs b/1.4/Source/MainTabWindows/WorldComponent_UpdateMainTab.cs
new file mode 100644
index 0000000..2694419
--- /dev/null
+++ b/1.4/Source/MainTabWindows/WorldComponent_UpdateMainTab.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using RimWorld;
+using RimWorld.Planet;
+using Verse;
+
+namespace Rimworld_Animations {
+ public class WorldComponent_UpdateMainTab : WorldComponent {
+
+ public WorldComponent_UpdateMainTab(World world) : base(world) {
+
+ }
+
+ public override void FinalizeInit() {
+ base.FinalizeInit();
+ OffsetMainButtonDefOf.OffsetManager.buttonVisible = AnimationSettings.offsetTab;
+ }
+
+
+ }
+}
diff --git a/1.4/Source/Patches/Harmony_PatchAll.cs b/1.4/Source/Patches/Harmony_PatchAll.cs
new file mode 100644
index 0000000..1c1d63f
--- /dev/null
+++ b/1.4/Source/Patches/Harmony_PatchAll.cs
@@ -0,0 +1,22 @@
+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("rjwanim");
+ val.PatchAll(Assembly.GetExecutingAssembly());
+
+ }
+ }
+}
diff --git a/1.4/Source/Patches/OtherModPatches/HarmonyPatch_AlienRace.cs b/1.4/Source/Patches/OtherModPatches/HarmonyPatch_AlienRace.cs
new file mode 100644
index 0000000..c53edb4
--- /dev/null
+++ b/1.4/Source/Patches/OtherModPatches/HarmonyPatch_AlienRace.cs
@@ -0,0 +1,358 @@
+/*using HarmonyLib;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Text;
+using System.Threading.Tasks;
+using UnityEngine;
+using Verse;
+using AlienRace;
+
+namespace Rimworld_Animations {
+
+
+ [StaticConstructorOnStartup]
+ public static class HarmonyPatch_AlienRace
+ {
+ static HarmonyPatch_AlienRace()
+ {
+ (new Harmony("rjwanim")).Patch(AccessTools.Method(AccessTools.TypeByName("AlienRace.HarmonyPatches"), "DrawAddons"),
+ prefix: new HarmonyMethod(AccessTools.Method(typeof(HarmonyPatch_AlienRace), "Prefix_AnimateHeadAddons")));
+ }
+
+ /* todo: replace jank prefix with this
+ public static void Prefix_DrawAddonsFinalHook(ref Pawn pawn, ref AlienPartGenerator.BodyAddon addon, ref Rot4 rot, ref Graphic graphic, ref Vector3 offsetVector, ref float angle, ref Material mat)
+ {
+ CompBodyAnimator animator = pawn.TryGetComp();
+
+ if (animator == null || !animator.isAnimating)
+ {
+ return;
+ }
+
+ if(addon.alignWithHead || addon.drawnInBed)
+ {
+ rot = animator.headFacing;
+ angle = animator.headAngle;
+ offsetVector += animator.deltaPos + animator.bodyAngle * animator.headBob;
+
+ }
+ else
+ {
+ rot = animator.bodyFacing;
+ angle = animator.bodyAngle;
+ offsetVector += animator.deltaPos;
+ }
+
+ }
+
+ public static bool Prefix_AnimateHeadAddons(PawnRenderFlags renderFlags, Vector3 vector, Vector3 headOffset, Pawn pawn, Quaternion quat, Rot4 rotation)
+ {
+
+ if (renderFlags.FlagSet(PawnRenderFlags.Portrait) || pawn.TryGetComp() == null || !pawn.TryGetComp().isAnimating) return true;
+ if (!(pawn.def is ThingDef_AlienRace alienProps) || renderFlags.FlagSet(PawnRenderFlags.Invisible)) return false;
+
+ List addons = alienProps.alienRace.generalSettings.alienPartGenerator.bodyAddons;
+ AlienPartGenerator.AlienComp comp = pawn.GetComp();
+ CompBodyAnimator pawnAnimator = pawn.TryGetComp();
+
+ bool flag = renderFlags.FlagSet(PawnRenderFlags.Portrait);
+ bool flag2 = renderFlags.FlagSet(PawnRenderFlags.Invisible);
+
+ for (int i = 0; i < addons.Count; i++)
+ {
+ AlienPartGenerator.BodyAddon ba = addons[index: i];
+
+ if (!ba.CanDrawAddon(pawn: pawn)) continue;
+
+ bool forceDrawForBody = false;
+ if (alienProps.defName.Contains("Orassan") && ba.path.ToLower().Contains("tail"))
+ {
+ forceDrawForBody = true;
+ }
+ AlienPartGenerator.RotationOffset offset = ba.defaultOffsets.GetOffset((ba.drawnInBed && !forceDrawForBody) || ba.alignWithHead ? pawnAnimator.headFacing : pawnAnimator.bodyFacing);
+ Vector3 a = (offset != null) ? offset.GetOffset(renderFlags.FlagSet(PawnRenderFlags.Portrait), pawn.story.bodyType, pawn.story.headType) : Vector3.zero;
+ AlienPartGenerator.RotationOffset offset2 = ba.offsets.GetOffset((ba.drawnInBed && !forceDrawForBody) || ba.alignWithHead ? pawnAnimator.headFacing : pawnAnimator.bodyFacing);
+ Vector3 vector2 = a + ((offset2 != null) ? offset2.GetOffset(renderFlags.FlagSet(PawnRenderFlags.Portrait), pawn.story.bodyType, pawn.story.headType) : Vector3.zero);
+ vector2.y = (ba.inFrontOfBody ? (0.3f + vector2.y) : (-0.3f - vector2.y));
+ float num = ba.angle;
+ if (((ba.drawnInBed && !forceDrawForBody) || ba.alignWithHead ? pawnAnimator.headFacing : pawnAnimator.bodyFacing) == Rot4.North)
+ {
+ if (ba.layerInvert)
+ {
+ vector2.y = 0f - vector2.y;
+ }
+ num = 0f;
+ }
+ if (((ba.drawnInBed && !forceDrawForBody) || ba.alignWithHead ? pawnAnimator.headFacing : pawnAnimator.bodyFacing) == Rot4.East)
+ {
+ num = 0f - num;
+ vector2.x = 0f - vector2.x;
+ }
+ Graphic addonGraphic = comp.addonGraphics[i];
+
+ addonGraphic.drawSize = ((flag && ba.drawSizePortrait != Vector2.zero) ? ba.drawSizePortrait : ba.drawSize) * (ba.scaleWithPawnDrawsize ? (ba.alignWithHead ? ((flag ? comp.customPortraitHeadDrawSize : comp.customHeadDrawSize) * (ModsConfig.BiotechActive ? (pawn.ageTracker.CurLifeStage.headSizeFactor ?? 1.5f) : 1.5f)) : ((flag ? comp.customPortraitDrawSize : comp.customDrawSize) * (ModsConfig.BiotechActive ? pawn.ageTracker.CurLifeStage.bodySizeFactor : 1f) * 1.5f)) : (Vector2.one * 1.5f));
+
+ if ((ba.drawnInBed && !forceDrawForBody) || ba.alignWithHead)
+ {
+
+ Quaternion addonRotation = Quaternion.AngleAxis(pawnAnimator.headAngle < 0 ? 360 - (360 % pawnAnimator.headAngle) : pawnAnimator.headAngle, Vector3.up);
+
+ GenDraw.DrawMeshNowOrLater(mesh: addonGraphic.MeshAt(rot: pawnAnimator.headFacing), loc: vector + (ba.alignWithHead ? headOffset : headOffset - addonRotation * pawn.Drawer.renderer.BaseHeadOffsetAt(pawnAnimator.headFacing)) + vector2.RotatedBy(angle: Mathf.Acos(f: Quaternion.Dot(a: Quaternion.identity, b: addonRotation)) * 2f * 57.29578f),
+ quat: Quaternion.AngleAxis(angle: num, axis: Vector3.up) * addonRotation, mat: addonGraphic.MatAt(rot: pawnAnimator.headFacing), renderFlags.FlagSet(PawnRenderFlags.DrawNow));
+
+
+ }
+
+ else
+ {
+ Quaternion addonRotation = Quaternion.AngleAxis(pawnAnimator.bodyAngle, Vector3.up);
+ if (AnimationSettings.controlGenitalRotation && pawnAnimator.controlGenitalAngle && ba?.hediffGraphics != null && ba.hediffGraphics.Count != 0 && ba.hediffGraphics[0]?.path != null && (ba.hediffGraphics[0].path.Contains("Penis") || ba.hediffGraphics[0].path.Contains("penis")))
+ {
+ GenDraw.DrawMeshNowOrLater(mesh: addonGraphic.MeshAt(rot: rotation), loc: vector + (ba.alignWithHead ? headOffset : Vector3.zero) + vector2.RotatedBy(angle: Mathf.Acos(f: Quaternion.Dot(a: Quaternion.identity, b: addonRotation)) * 2f * 57.29578f),
+ quat: Quaternion.AngleAxis(angle: pawnAnimator.genitalAngle, axis: Vector3.up), mat: addonGraphic.MatAt(rot: rotation), renderFlags.FlagSet(PawnRenderFlags.DrawNow));
+ }
+
+ else
+ {
+ GenDraw.DrawMeshNowOrLater(mesh: addonGraphic.MeshAt(rot: rotation), loc: vector + (ba.alignWithHead ? headOffset : Vector3.zero) + vector2.RotatedBy(angle: Mathf.Acos(f: Quaternion.Dot(a: Quaternion.identity, b: addonRotation)) * 2f * 57.29578f),
+ quat: Quaternion.AngleAxis(angle: num, axis: Vector3.up) * addonRotation, mat: addonGraphic.MatAt(rot: rotation), renderFlags.FlagSet(PawnRenderFlags.DrawNow));
+ }
+
+ }
+
+
+ }
+
+ return false;
+ }
+ }
+
+ [HarmonyPatch(typeof(PawnGraphicSet), "ResolveApparelGraphics")]
+ public static class HarmonyPatch_ResolveApparelGraphics
+ {
+ public static bool Prefix(ref Pawn ___pawn)
+ {
+
+ if (___pawn.TryGetComp() != null && ___pawn.TryGetComp().isAnimating)
+ {
+ return false;
+ }
+ return true;
+ }
+ }
+*/
+/*
+
+[HarmonyPatch(typeof(AlienRace.HarmonyPatches), "DrawAddons")]
+public static class HarmonyPatch_AlienRace {
+
+ public static void RenderHeadAddonInAnimation(Mesh mesh, Vector3 loc, Quaternion quat, Material mat, bool drawNow, Graphic graphic, AlienPartGenerator.BodyAddon bodyAddon, Vector3 v, Vector3 headOffset, Pawn pawn, PawnRenderFlags renderFlags, Vector3 vector, Rot4 rotation)
+ {
+
+ CompBodyAnimator pawnAnimator = pawn.TryGetComp();
+ AlienPartGenerator.AlienComp comp = pawn.GetComp();
+
+ if (pawnAnimator != null && pawnAnimator.isAnimating)
+ {
+
+ if((bodyAddon.drawnInBed || bodyAddon.alignWithHead))
+ {
+
+ AlienPartGenerator.RotationOffset offset = bodyAddon.defaultOffsets.GetOffset(rotation);
+ Vector3 a = (offset != null) ? offset.GetOffset(renderFlags.FlagSet(PawnRenderFlags.Portrait), pawn.story.bodyType, comp.crownType) : Vector3.zero;
+ AlienPartGenerator.RotationOffset offset2 = bodyAddon.offsets.GetOffset(rotation);
+ Vector3 vector2 = a + ((offset2 != null) ? offset2.GetOffset(renderFlags.FlagSet(PawnRenderFlags.Portrait), pawn.story.bodyType, comp.crownType) : Vector3.zero);
+ vector2.y = (bodyAddon.inFrontOfBody ? (0.3f + vector2.y) : (-0.3f - vector2.y));
+ float num = bodyAddon.angle;
+ if (rotation == Rot4.North)
+ {
+ if (bodyAddon.layerInvert)
+ {
+ vector2.y = -vector2.y;
+ }
+ num = 0f;
+ }
+ if (rotation == Rot4.East)
+ {
+ num = -num;
+ vector2.x = -vector2.x;
+ }
+
+ vector = vector + Quaternion.AngleAxis(pawnAnimator.bodyAngle, Vector3.up) * pawn.Drawer.renderer.BaseHeadOffsetAt(pawnAnimator.bodyFacing) - pawnAnimator.getPawnHeadOffset(); //convert vector into pseudo body pos for head
+ quat = Quaternion.AngleAxis(pawnAnimator.headAngle, Vector3.up);
+ loc = vector + (bodyAddon.alignWithHead ? headOffset : Vector3.zero) + vector2.RotatedBy(Mathf.Acos(Quaternion.Dot(Quaternion.identity, quat)) * 2f * 57.29578f);
+ mat = graphic.MatAt(rot: pawnAnimator.headFacing);
+ }
+ else
+ {
+
+ AlienPartGenerator.RotationOffset offset = bodyAddon.defaultOffsets.GetOffset(rotation);
+ Vector3 a = (offset != null) ? offset.GetOffset(renderFlags.FlagSet(PawnRenderFlags.Portrait), pawn.story.bodyType, comp.crownType) : Vector3.zero;
+ AlienPartGenerator.RotationOffset offset2 = bodyAddon.offsets.GetOffset(rotation);
+ Vector3 vector2 = a + ((offset2 != null) ? offset2.GetOffset(renderFlags.FlagSet(PawnRenderFlags.Portrait), pawn.story.bodyType, comp.crownType) : Vector3.zero);
+ vector2.y = (bodyAddon.inFrontOfBody ? (0.3f + vector2.y) : (-0.3f - vector2.y));
+ float num = bodyAddon.angle;
+ if (rotation == Rot4.North)
+ {
+ if (bodyAddon.layerInvert)
+ {
+ vector2.y = -vector2.y;
+ }
+ num = 0f;
+ }
+ if (rotation == Rot4.East)
+ {
+ num = -num;
+ vector2.x = -vector2.x;
+ }
+ quat = Quaternion.AngleAxis(pawnAnimator.bodyAngle, Vector3.up);
+ loc = vector + (bodyAddon.alignWithHead ? headOffset : Vector3.zero) + vector2.RotatedBy(Mathf.Acos(Quaternion.Dot(Quaternion.identity, quat)) * 2f * 57.29578f);
+
+ }
+
+ }
+ GenDraw.DrawMeshNowOrLater(mesh, loc, quat, mat, drawNow);
+
+ /*
+ if (pawnAnimator != null && !renderFlags.FlagSet(PawnRenderFlags.Portrait) && pawnAnimator.isAnimating && (bodyAddon.drawnInBed || bodyAddon.alignWithHead))
+ {
+
+
+ if ((pawn.def as ThingDef_AlienRace).defName == "Alien_Orassan")
+ {
+ orassan = true;
+
+ if(bodyAddon.path.Contains("closed"))
+ {
+ return;
+ }
+
+ if (bodyAddon.bodyPart.Contains("ear"))
+
+ {
+ orassan = true;
+
+ orassanv = new Vector3(0, 0, 0.23f);
+ if (pawnAnimator.headFacing == Rot4.North)
+ {
+ orassanv.z -= 0.1f;
+ orassanv.y += 1f;
+
+ if(bodyAddon.bodyPart.Contains("left"))
+ {
+ orassanv.x += 0.03f;
+ } else
+ {
+ orassanv.x -= 0.03f;
+ }
+
+ }
+ else if (pawnAnimator.headFacing == Rot4.East)
+ {
+ orassanv.x -= 0.1f;
+ }
+ else if (pawnAnimator.headFacing == Rot4.West)
+ {
+ orassanv.x = 0.1f;
+ }
+ else
+ {
+ orassanv.z -= 0.1f;
+ orassanv.y += 1f;
+
+ if (bodyAddon.bodyPart.Contains("right"))
+ {
+ orassanv.x += 0.05f;
+ }
+ else
+ {
+ orassanv.x -= 0.05f;
+ }
+ }
+ orassanv = orassanv.RotatedBy(pawnAnimator.headAngle);
+ }
+ }
+
+
+
+
+
+ GenDraw.DrawMeshNowOrLater(mesh: graphic.MeshAt(rot: headRotInAnimation), loc: loc + orassanv + (bodyAddon.alignWithHead ? headOffset : Vector3.zero),// + v.RotatedBy(Mathf.Acos(Quaternion.Dot(Quaternion.identity, quat)) * 2f * 57.29578f),
+ quat: Quaternion.AngleAxis(angle: num, axis: Vector3.up) * headQuatInAnimation, mat: graphic.MatAt(rot: pawnAnimator.headFacing), drawNow: drawNow);;
+ }
+
+ else
+ {
+
+ }
+
+
+ }
+
+
+ public static IEnumerable Transpiler(IEnumerable instructions)
+ {
+ List ins = instructions.ToList();
+ for (int i = 0; i < ins.Count; i++)
+ {
+
+ Type[] type = new Type[] { typeof(Mesh), typeof(Vector3), typeof(Quaternion), typeof(Material), typeof(bool) };
+
+
+ if (ins[i].OperandIs(AccessTools.Method(typeof(GenDraw), "DrawMeshNowOrLater", type)))
+ {
+
+ yield return new CodeInstruction(OpCodes.Ldloc, (object)7); //graphic
+ yield return new CodeInstruction(OpCodes.Ldloc, (object)4); //bodyAddon
+ yield return new CodeInstruction(OpCodes.Ldloc, (object)5); //offsetVector/AddonOffset (v)
+ yield return new CodeInstruction(OpCodes.Ldarg, (object)2); //headOffset
+ yield return new CodeInstruction(OpCodes.Ldarg, (object)3); //pawn
+ yield return new CodeInstruction(OpCodes.Ldarg, (object)0); //renderflags
+ yield return new CodeInstruction(OpCodes.Ldarg, (object)1); //vector
+ yield return new CodeInstruction(OpCodes.Ldarg, (object)5); //rotation
+
+ yield return new CodeInstruction(OpCodes.Call, AccessTools.DeclaredMethod(typeof(HarmonyPatch_AlienRace), "RenderHeadAddonInAnimation"));
+
+ }
+
+ else
+ {
+ yield return ins[i];
+ }
+ }
+ }
+
+ public static bool Prefix(PawnRenderFlags renderFlags, ref Vector3 vector, ref Vector3 headOffset, Pawn pawn, ref Quaternion quat, ref Rot4 rotation)
+ {
+ if(pawn == null)
+ {
+ return true;
+ }
+
+ CompBodyAnimator anim = pawn.TryGetComp();
+
+ if(anim == null)
+ {
+ return true;
+ }
+
+ if (anim != null && !renderFlags.FlagSet(PawnRenderFlags.Portrait) && anim.isAnimating)
+ {
+ //quat = Quaternion.AngleAxis(anim.bodyAngle, Vector3.up);
+ }
+
+ return true;
+
+ }
+}
+
+
+
+
+}
+
+
+*/
\ No newline at end of file
diff --git a/Source/Patches/HarmonyPatch_PawnRenderer.cs b/1.4/Source/Patches/OtherModPatches/HarmonyPatch_CSL.cs
similarity index 55%
rename from Source/Patches/HarmonyPatch_PawnRenderer.cs
rename to 1.4/Source/Patches/OtherModPatches/HarmonyPatch_CSL.cs
index 8bad2f2..8345ede 100644
--- a/Source/Patches/HarmonyPatch_PawnRenderer.cs
+++ b/1.4/Source/Patches/OtherModPatches/HarmonyPatch_CSL.cs
@@ -1,55 +1,54 @@
-using System;
+/*
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HarmonyLib;
-using RimWorld;
+using rjw;
using Verse;
-using UnityEngine;
-using System.Reflection;
+using RimWorld;
using System.Reflection.Emit;
+using System.Reflection;
+using UnityEngine;
namespace Rimworld_Animations {
+ [StaticConstructorOnStartup]
+ public static class HarmonyPatch_CSL {
+ static HarmonyPatch_CSL() {
+ try {
+ ((Action)(() => {
+ if (LoadedModManager.RunningModsListForReading.Any(x => x.Name == "Children, school and learning")) {
- [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
- {
+ (new Harmony("rjw")).Patch(AccessTools.Method(AccessTools.TypeByName("Children.PawnRenderer_RenderPawnInternal_Patch"), "RenderPawnInternalScaled"),
+ prefix: new HarmonyMethod(AccessTools.Method(typeof(HarmonyPatch_CSL), "Prefix_CSL")),
+ transpiler: new HarmonyMethod(AccessTools.Method(typeof(HarmonyPatch_CSL), "Transpiler_CSL")));
+ }
+ }))();
+ }
+ catch (TypeLoadException ex) {
+
+ }
+ }
+
+ public static void Prefix_CSL(PawnRenderer __instance, Pawn pawn, ref Vector3 rootLoc, ref float angle, bool renderBody, ref Rot4 bodyFacing, ref Rot4 headFacing, RotDrawMode bodyDrawType, bool portrait, bool headStump, bool invisible) {
- [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();
if (!graphics.AllResolved) {
graphics.ResolveAllGraphics();
}
-
- if (bodyAnim != null && bodyAnim.isAnimating && !portrait && pawn.Map == Find.CurrentMap) {
+
+ if (bodyAnim != null && bodyAnim.isAnimating && !portrait) {
bodyAnim.tickGraphics(graphics);
- bodyAnim.animatePawn(ref rootLoc, ref angle, ref bodyFacing, ref headFacing);
+ pawn.TryGetComp().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 Transpiler(IEnumerable instructions) {
+ public static IEnumerable Transpiler_CSL(IEnumerable instructions) {
MethodInfo drawMeshNowOrLater = AccessTools.Method(typeof(GenDraw), "DrawMeshNowOrLater");
FieldInfo headGraphic = AccessTools.Field(typeof(PawnGraphicSet), "headGraphic");
@@ -57,23 +56,24 @@ namespace Rimworld_Animations {
List codes = instructions.ToList();
bool forHead = true;
- for(int i = 0; i < codes.Count(); i++) {
+ 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), new Type[] { typeof(Mesh), typeof(Vector3), typeof(Quaternion), typeof(Material), typeof(bool), typeof(Pawn) }));
+ yield return new CodeInstruction(OpCodes.Ldarg_2);
+ yield return new CodeInstruction(OpCodes.Call, AccessTools.DeclaredMethod(typeof(AnimationUtility), nameof(AnimationUtility.RenderPawnHeadMeshInAnimation), new Type[] { typeof(Mesh), typeof(Vector3), typeof(Quaternion), typeof(Material), typeof(bool), typeof(Pawn), typeof(float) }));
}
//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) {
+ else if (codes[i].opcode == OpCodes.Ldarg_3) {
forHead = false;
yield return codes[i];
}
@@ -82,5 +82,6 @@ namespace Rimworld_Animations {
}
}
}
- }
-}
+
+ }
+}*/
diff --git a/1.4/Source/Patches/OtherModPatches/HarmonyPatch_DontShaveYourHead.cs b/1.4/Source/Patches/OtherModPatches/HarmonyPatch_DontShaveYourHead.cs
new file mode 100644
index 0000000..3cb2a63
--- /dev/null
+++ b/1.4/Source/Patches/OtherModPatches/HarmonyPatch_DontShaveYourHead.cs
@@ -0,0 +1,29 @@
+using HarmonyLib;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Verse;
+
+namespace Rimworld_Animations {
+ class HarmonyPatch_DontShaveYourHead {
+
+ [StaticConstructorOnStartup]
+ public static class Patch_DontShaveYourHead {
+
+ static Patch_DontShaveYourHead() {
+ try {
+ ((Action)(() =>
+ {
+ if (LoadedModManager.RunningModsListForReading.Any(x => x.Name == "Don't Shave Your Head 1.0")) {
+ (new Harmony("rjwanim")).Patch(AccessTools.Method(AccessTools.TypeByName("DontShaveYourHead.Harmony_PawnRenderer"), "DrawHairReroute"), //typeof(ShowHair.Patch_PawnRenderer_RenderPawnInternal), nameof(ShowHair.Patch_PawnRenderer_RenderPawnInternal.Postfix)),
+ transpiler: new HarmonyMethod(AccessTools.Method(typeof(Patch_ShowHairWithHats), "Transpiler")));
+ }
+ }))();
+ }
+ catch (TypeLoadException ex) { }
+ }
+ }
+ }
+}
diff --git a/1.4/Source/Patches/OtherModPatches/HarmonyPatch_FacialAnimation.cs b/1.4/Source/Patches/OtherModPatches/HarmonyPatch_FacialAnimation.cs
new file mode 100644
index 0000000..83ffd5b
--- /dev/null
+++ b/1.4/Source/Patches/OtherModPatches/HarmonyPatch_FacialAnimation.cs
@@ -0,0 +1,104 @@
+using HarmonyLib;
+using RimWorld;
+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("rjwanim")).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();
+
+ 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;
+ }
+ /*
+ public static List rjwLovinDefNames = new List{
+ "Lovin",
+ "Quickie",
+ "GettingQuickie",
+ "JoinInBed",
+ "JoinInBedAnimation",
+ "GettinLovedAnimation",
+ "GettinLoved",
+ "GettinLicked",
+ "GettinSucked",
+ "GettinRaped",
+ "ViolateCorpse",
+ "RJW_Masturbate",
+ "GettinBred",
+ "Breed",
+ "RJW_Mate",
+ "Bestiality",
+ "BestialityForFemale",
+ "StruggleInBondageGear",
+ "WhoreIsServingVisitors",
+ "UseFM"
+ };
+
+ public static List rjwRapeDefNames = new List {
+ "RapeComfortPawn",
+ "RandomRape",
+ "RapeEnemy"
+ };
+
+ public static bool Prefix_IsSameA(JobDef job, string ___jobDef, ref bool __result) {
+
+ if(___jobDef != null && ___jobDef == "Lovin" && job?.defName != null && rjwLovinDefNames.Contains(job?.defName)) {
+ __result = true;
+ return false;
+ }
+ else if (___jobDef != null && ___jobDef == "Wait_Combat" && job?.defName != null && rjwRapeDefNames.Contains(job?.defName)) {
+ __result = true;
+ return false;
+ }
+
+
+ return true;
+ }
+
+ public static bool Prefix_IsSameB(string jobName, string ___jobDef, ref bool __result) {
+
+ if (___jobDef != null && ___jobDef == "Lovin" && jobName != null && rjwLovinDefNames.Contains(jobName)) {
+ __result = true;
+ return false;
+ }
+ if (___jobDef != null && ___jobDef == "Wait_Combat" && jobName != null && rjwRapeDefNames.Contains(jobName)) {
+ __result = true;
+ return false;
+ }
+
+ return true;
+ }
+ */
+ }
+}
\ No newline at end of file
diff --git a/1.4/Source/Patches/OtherModPatches/HarmonyPatch_HatsDisplaySelection.cs b/1.4/Source/Patches/OtherModPatches/HarmonyPatch_HatsDisplaySelection.cs
new file mode 100644
index 0000000..1cd5707
--- /dev/null
+++ b/1.4/Source/Patches/OtherModPatches/HarmonyPatch_HatsDisplaySelection.cs
@@ -0,0 +1,77 @@
+/*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 {
+ public static class HarmonyPatch_HatsDisplaySelection {
+
+ public static void PatchHatsDisplaySelectionArgs() {
+ (new Harmony("rjw")).Patch(AccessTools.Method(AccessTools.TypeByName("HatDisplaySelection.Patch"), "DrawHatCEWithHair"),
+ transpiler: new HarmonyMethod(AccessTools.Method(typeof(HarmonyPatch_HatsDisplaySelection), "ReplaceDrawMeshOrLaterWithAnimate")));
+
+ (new Harmony("rjw")).Patch(AccessTools.Method(AccessTools.TypeByName("HatDisplaySelection.Patch"), "DrawHatWithHair"),
+ transpiler: new HarmonyMethod(AccessTools.Method(typeof(HarmonyPatch_HatsDisplaySelection), "ReplaceDrawMeshOrLaterWithAnimate")));
+
+ (new Harmony("rjw")).Patch(AccessTools.Method(AccessTools.TypeByName("HatDisplaySelection.Patch"), "DrawHeadApparelWithHair"),
+ prefix: new HarmonyMethod(AccessTools.Method(typeof(HarmonyPatch_HatsDisplaySelection), "PrefixPatchForDrawHeadApparelWithHair")));
+
+
+ }
+
+ public static void PrefixPatchForDrawHeadApparelWithHair(PawnRenderer renderer, ref Vector3 rootLoc, ref float angle, bool renderBody, ref Rot4 bodyFacing, ref Rot4 headFacing, RotDrawMode bodyDrawType, bool portrait, bool headStump, bool invisible)
+ {
+ PawnGraphicSet graphics = renderer.graphics;
+ Pawn pawn = graphics.pawn;
+ CompBodyAnimator bodyAnim = pawn.TryGetComp();
+
+ if (!graphics.AllResolved)
+ {
+ graphics.ResolveAllGraphics();
+ }
+
+
+ if (bodyAnim != null && bodyAnim.isAnimating && !portrait && pawn.Map == Find.CurrentMap)
+ {
+ bodyAnim.tickGraphics(graphics);
+ bodyAnim.animatePawn(ref rootLoc, ref angle, ref bodyFacing, ref headFacing);
+
+ }
+ }
+
+
+ public static IEnumerable ReplaceDrawMeshOrLaterWithAnimate(IEnumerable instructions) {
+
+ MethodInfo drawMeshNowOrLater = AccessTools.Method(typeof(GenDraw), "DrawMeshNowOrLater");
+ List codes = instructions.ToList();
+ for (int i = 0; i < instructions.Count(); i++) {
+
+
+ if (codes[i].
+
+
+(drawMeshNowOrLater)) {
+
+ yield return new CodeInstruction(OpCodes.Ldarg_0);
+ yield return new CodeInstruction(OpCodes.Ldfld, AccessTools.DeclaredField(AccessTools.TypeByName("HatDisplaySelection.Patch"), "pawn"));
+ yield return new CodeInstruction(OpCodes.Call, AccessTools.DeclaredMethod(typeof(AnimationUtility), nameof(AnimationUtility.RenderPawnHeadMeshInAnimation), new Type[] { typeof(Mesh), typeof(Vector3), typeof(Quaternion), typeof(Material), typeof(bool), typeof(Pawn) }));
+
+ }
+ else {
+ yield return codes[i];
+ }
+
+ }
+
+ }
+
+ }
+}
+*/
\ No newline at end of file
diff --git a/1.4/Source/Patches/OtherModPatches/HarmonyPatch_ShowHairWithHats.cs b/1.4/Source/Patches/OtherModPatches/HarmonyPatch_ShowHairWithHats.cs
new file mode 100644
index 0000000..a42ab7d
--- /dev/null
+++ b/1.4/Source/Patches/OtherModPatches/HarmonyPatch_ShowHairWithHats.cs
@@ -0,0 +1,51 @@
+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_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("rjwanim")).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 Transpiler(IEnumerable instructions) {
+
+ MethodInfo drawMeshNowOrLater = AccessTools.Method(typeof(GenDraw), "DrawMeshNowOrLater");
+
+ List 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), new Type[] { typeof(Mesh), typeof(Vector3), typeof(Quaternion), typeof(Material), typeof(bool), typeof(Pawn) }));
+
+ }
+ else {
+ yield return codes[i];
+ }
+ }
+ }
+ }
+}
diff --git a/1.4/Source/Patches/RJWPatches/HarmonyPatch_PlaySexSounds.cs b/1.4/Source/Patches/RJWPatches/HarmonyPatch_PlaySexSounds.cs
new file mode 100644
index 0000000..6544f13
--- /dev/null
+++ b/1.4/Source/Patches/RJWPatches/HarmonyPatch_PlaySexSounds.cs
@@ -0,0 +1,25 @@
+using HarmonyLib;
+using rjw;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Verse;
+
+namespace Rimworld_Animations
+{
+ [HarmonyPatch(typeof(JobDriver_Sex), "PlaySexSound")]
+ class HarmonyPatch_PlaySexSounds
+ {
+ public static bool Prefix(JobDriver_Sex __instance)
+ {
+ if (__instance.pawn.TryGetComp().isAnimating)
+ {
+ return false;
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/1.4/Source/Patches/RJWPatches/HarmonyPatch_SexTick.cs b/1.4/Source/Patches/RJWPatches/HarmonyPatch_SexTick.cs
new file mode 100644
index 0000000..9ba03b2
--- /dev/null
+++ b/1.4/Source/Patches/RJWPatches/HarmonyPatch_SexTick.cs
@@ -0,0 +1,61 @@
+using HarmonyLib;
+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
+{
+ [HarmonyPatch(typeof(JobDriver_Sex), "SexTick")]
+ public class HarmonyPatch_SexTick
+ {
+ public static bool Prefix(JobDriver_Sex __instance, Pawn pawn, Thing target)
+ {
+
+ if ((target is Pawn) &&
+ !(
+ (target as Pawn)?.jobs?.curDriver is JobDriver_SexBaseReciever
+ &&
+ ((target as Pawn).jobs.curDriver as JobDriver_SexBaseReciever).parteners.Any()
+ &&
+ ((target as Pawn).jobs.curDriver as JobDriver_SexBaseReciever).parteners[0] == pawn))
+ {
+
+ __instance.ticks_left--;
+ __instance.sex_ticks--;
+ __instance.Orgasm();
+
+
+ if (pawn.IsHashIntervalTick(__instance.ticks_between_thrusts))
+ {
+ __instance.ChangePsyfocus(pawn, target);
+ __instance.Animate(pawn, target);
+ __instance.PlaySexSound();
+ if (!__instance.Sexprops.isRape)
+ {
+ pawn.GainComfortFromCellIfPossible(false);
+ if (target is Pawn)
+ {
+ (target as Pawn).GainComfortFromCellIfPossible(false);
+ }
+ }
+ if(!__instance.isEndytophile)
+ {
+ SexUtility.DrawNude(pawn, false);
+ }
+ }
+
+ return false;
+ }
+
+ return true;
+ }
+
+ }
+
+}
diff --git a/1.4/Source/Patches/RJWPatches/HarmonyPatch_WorkGiverSex.cs b/1.4/Source/Patches/RJWPatches/HarmonyPatch_WorkGiverSex.cs
new file mode 100644
index 0000000..af4a755
--- /dev/null
+++ b/1.4/Source/Patches/RJWPatches/HarmonyPatch_WorkGiverSex.cs
@@ -0,0 +1,31 @@
+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.GetNamed("JoinInBedAnimation", true), t as Pawn, bed);
+ return false;
+
+ }
+
+ }
+
+ */
+}
diff --git a/1.4/Source/Patches/RJWPatches/JobDrivers/HarmonyPatch_JobDriver_JoinInBed.cs b/1.4/Source/Patches/RJWPatches/JobDrivers/HarmonyPatch_JobDriver_JoinInBed.cs
new file mode 100644
index 0000000..18c955e
--- /dev/null
+++ b/1.4/Source/Patches/RJWPatches/JobDrivers/HarmonyPatch_JobDriver_JoinInBed.cs
@@ -0,0 +1,84 @@
+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 System.Reflection.Emit;
+using Verse.AI;
+
+namespace Rimworld_Animations
+{
+
+ [HarmonyPatch(typeof(Bed_Utility), "in_same_bed")]
+ public static class HarmonyPatch_JobDriver_InSameBedPatch
+ {
+
+ public static bool Prefix(Pawn partner, ref bool __result)
+ {
+
+ if(partner != null && partner.CurJobDef == xxx.casual_sex)
+ {
+ __result = true;
+ return false;
+ }
+
+ return true;
+
+ }
+
+
+
+ }
+
+ [HarmonyPatch(typeof(JobDriver_JoinInBed), "MakeNewToils")]
+ public static class HarmonyPatch_JobDriver_JoinInBed
+ {
+
+ public static void Postfix(JobDriver_JoinInBed __instance, ref IEnumerable __result)
+ {
+
+ var toils = __result.ToList();
+
+ Toil goToPawnInBed = Toils_Goto.GotoThing(__instance.iTarget, PathEndMode.OnCell);
+ goToPawnInBed.FailOn(() => !RestUtility.InBed(__instance.Partner) && __instance.Partner.CurJobDef != xxx.gettin_loved && !Bed_Utility.in_same_bed(__instance.Partner, __instance.pawn));
+
+ toils[1] = goToPawnInBed;
+
+
+ Toil startPartnerSex = new Toil();
+ startPartnerSex.initAction = delegate {
+
+
+ if (!(__instance.Partner.jobs.curDriver is JobDriver_SexBaseReciever)) // allows threesomes
+ {
+ Job gettinLovedJob = JobMaker.MakeJob(xxx.gettin_loved, __instance.pawn, __instance.Bed); // new gettin loved toil that wakes up the pawn goes here
+ __instance.Partner.jobs.jobQueue.EnqueueFirst(gettinLovedJob);
+ __instance.Partner.jobs.EndCurrentJob(JobCondition.InterruptForced);
+ }
+
+ };
+
+ toils[2] = startPartnerSex;
+
+ toils[3].AddPreTickAction(() =>
+ {
+ if (!__instance.Partner.TryGetComp().isAnimating)
+ {
+ __instance.pawn.TryGetComp().isAnimating = false;
+ }
+ });
+
+
+ __result = toils.AsEnumerable();
+
+
+ }
+
+
+
+ }
+}
diff --git a/1.4/Source/Patches/RJWPatches/JobDrivers/HarmonyPatch_JobDriver_SexBaseInitiator.cs b/1.4/Source/Patches/RJWPatches/JobDrivers/HarmonyPatch_JobDriver_SexBaseInitiator.cs
new file mode 100644
index 0000000..260d924
--- /dev/null
+++ b/1.4/Source/Patches/RJWPatches/JobDrivers/HarmonyPatch_JobDriver_SexBaseInitiator.cs
@@ -0,0 +1,191 @@
+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) {
+ /*
+ These particular jobs need special code
+ don't play anim for now
+ */
+ if(__instance is JobDriver_Masturbate || __instance is JobDriver_ViolateCorpse) {
+ return;
+ }
+
+ if(!AnimationSettings.PlayAnimForNonsexualActs && NonSexualAct(__instance))
+ {
+ return;
+ }
+
+ Pawn pawn = __instance.pawn;
+
+ Building_Bed bed = __instance.Bed;
+
+ if ((__instance.Target as Pawn)?.jobs?.curDriver is JobDriver_SexBaseReciever) {
+
+ Pawn Target = __instance.Target as Pawn;
+
+ bool quickie = (__instance is JobDriver_SexQuick) && AnimationSettings.fastAnimForQuickie;
+
+ int preAnimDuration = __instance.duration;
+ int AnimationTimeTicks = 0;
+
+
+ if (bed != null) {
+ RerollAnimations(Target, out AnimationTimeTicks, bed as Thing, __instance.Sexprops.sexType, quickie, sexProps: __instance.Sexprops);
+ }
+ else {
+ RerollAnimations(Target, out AnimationTimeTicks, sexType: __instance.Sexprops.sexType, fastAnimForQuickie: quickie, sexProps: __instance.Sexprops);
+ }
+
+
+ //Modify Orgasm ticks to only orgasm as many times as RJW stock orgasm allows
+ if(AnimationTimeTicks != 0)
+ {
+ __instance.orgasmstick = preAnimDuration * __instance.orgasmstick / AnimationTimeTicks;
+ }
+
+
+ }
+ }
+
+ public static void RerollAnimations(Pawn pawn, out int AnimationTimeTicks, Thing bed = null, xxx.rjwSextype sexType = xxx.rjwSextype.None, bool fastAnimForQuickie = false, rjw.SexProps sexProps = null) {
+
+ AnimationTimeTicks = 0;
+
+ if(pawn == null || !(pawn.jobs?.curDriver is JobDriver_SexBaseReciever)) {
+ Log.Error("Error: Tried to reroll animations when pawn isn't sexing");
+ return;
+ }
+
+ List pawnsToAnimate = (pawn.jobs.curDriver as JobDriver_SexBaseReciever).parteners.ToList();
+
+ if (!pawnsToAnimate.Contains(pawn)) {
+ pawnsToAnimate = pawnsToAnimate.Append(pawn).ToList();
+ }
+
+ for(int i = 0; i < pawnsToAnimate.Count; i++) {
+
+ if(pawnsToAnimate[i].TryGetComp() == null) {
+ Log.Error("Error: " + pawnsToAnimate[i].Name + " of race " + pawnsToAnimate[i].def.defName + " does not have CompBodyAnimator attached!");
+ break;
+ }
+ }
+
+ AnimationDef anim = AnimationUtility.tryFindAnimation(ref pawnsToAnimate, sexType, sexProps);
+
+ if (anim != null) {
+
+ bool mirror = GenTicks.TicksGame % 2 == 0;
+
+ IntVec3 pos = pawn.Position;
+
+ for (int i = 0; i < anim.actors.Count; i++)
+ {
+ pawnsToAnimate[i].TryGetComp().isAnimating = false;
+ }
+
+ for (int i = 0; i < pawnsToAnimate.Count; i++) {
+
+ if (bed != null)
+ pawnsToAnimate[i].TryGetComp().setAnchor(bed);
+ else {
+
+ pawnsToAnimate[i].TryGetComp().setAnchor(pos);
+ }
+
+ bool shiver = pawnsToAnimate[i].jobs.curDriver is JobDriver_SexBaseRecieverRaped;
+ pawnsToAnimate[i].TryGetComp().StartAnimation(anim, pawnsToAnimate, i, mirror, shiver, fastAnimForQuickie);
+
+ int animTicks = anim.animationTimeTicks - (fastAnimForQuickie ? anim.animationStages[0].playTimeTicks : 0);
+ (pawnsToAnimate[i].jobs.curDriver as JobDriver_Sex).ticks_left = animTicks;
+ (pawnsToAnimate[i].jobs.curDriver as JobDriver_Sex).sex_ticks = animTicks;
+ (pawnsToAnimate[i].jobs.curDriver as JobDriver_Sex).duration = animTicks;
+
+
+ AnimationTimeTicks = animTicks;
+
+ if(!AnimationSettings.hearts) {
+ (pawnsToAnimate[i].jobs.curDriver as JobDriver_Sex).ticks_between_hearts = Int32.MaxValue;
+ }
+
+ }
+ }
+ else {
+ Log.Message("No animation found");
+
+ /*
+
+ //if pawn isn't already animating,
+ if (!pawn.TryGetComp().isAnimating) {
+ (pawn.jobs.curDriver as JobDriver_SexBaseReciever).increase_time(duration);
+ //they'll just do the thrusting anim
+ }
+
+ */
+ }
+ }
+
+
+ static IEnumerable NonSexActRulePackDefNames = new String[]
+ {
+ "MutualHandholdingRP",
+ "MutualMakeoutRP",
+ };
+
+ public static bool NonSexualAct(JobDriver_SexBaseInitiator sexBaseInitiator)
+ {
+ if(NonSexActRulePackDefNames.Contains(sexBaseInitiator.Sexprops.rulePack))
+ {
+ return true;
+ }
+ return false;
+ }
+ }
+
+ [HarmonyPatch(typeof(JobDriver_SexBaseInitiator), "End")]
+ static class HarmonyPatch_JobDriver_SexBaseInitiator_End {
+
+ public static void Postfix(ref JobDriver_SexBaseInitiator __instance) {
+
+ if ((__instance.Target as Pawn)?.jobs?.curDriver is JobDriver_SexBaseReciever) {
+ if (__instance.pawn.TryGetComp().isAnimating) {
+
+ List parteners = ((__instance.Target as Pawn)?.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().isAnimating = false;
+
+ }
+
+ __instance.Target.TryGetComp().isAnimating = false;
+
+ if (xxx.is_human((__instance.Target as Pawn))) {
+ (__instance.Target as Pawn)?.Drawer.renderer.graphics.ResolveApparelGraphics();
+ PortraitsCache.SetDirty((__instance.Target as Pawn));
+ }
+ }
+
+ ((__instance.Target as Pawn)?.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);
+ }
+ }
+ }
+}
diff --git a/1.4/Source/Patches/RJWPatches/JobDrivers/HarmonyPatch_JobDriver_SexBaseReceiverLoved.cs b/1.4/Source/Patches/RJWPatches/JobDrivers/HarmonyPatch_JobDriver_SexBaseReceiverLoved.cs
new file mode 100644
index 0000000..dfa116e
--- /dev/null
+++ b/1.4/Source/Patches/RJWPatches/JobDrivers/HarmonyPatch_JobDriver_SexBaseReceiverLoved.cs
@@ -0,0 +1,46 @@
+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 System.Reflection.Emit;
+using Verse.AI;
+
+namespace Rimworld_Animations
+{
+
+ [HarmonyPatch(typeof(JobDriver_SexBaseRecieverLoved), "MakeSexToil")]
+ public static class HarmonyPatch_JobDriver_SexBaseReceiverLoved
+ {
+ public static IEnumerable Transpiler(IEnumerable codeInstructions)
+ {
+
+ var ins = codeInstructions.ToList();
+ for(int i = 0; i < ins.Count; i++)
+ {
+ if(i < ins.Count && ins[i].opcode == OpCodes.Call && ins[i].OperandIs(AccessTools.DeclaredMethod(typeof(Toils_LayDown), "LayDown"))) {
+
+ ins[i].operand = AccessTools.DeclaredMethod(typeof(HarmonyPatch_JobDriver_SexBaseReceiverLoved), "DoNotLayDown");
+ yield return ins[i];
+
+ }
+
+ else
+ {
+ yield return ins[i];
+ }
+ }
+
+ }
+
+ public static Toil DoNotLayDown(TargetIndex bedOrRestSpotIndex, bool hasBed, bool lookForOtherJobs, bool canSleep = true, bool gainRestAndHealth = true, PawnPosture noBedLayingPosture = PawnPosture.LayingMask, bool deathrest = false)
+ {
+ return new Toil();
+ }
+
+ }
+}
diff --git a/1.4/Source/Patches/RimworldPatches/HarmonyPatch_HeadHair.cs b/1.4/Source/Patches/RimworldPatches/HarmonyPatch_HeadHair.cs
new file mode 100644
index 0000000..37ba6ce
--- /dev/null
+++ b/1.4/Source/Patches/RimworldPatches/HarmonyPatch_HeadHair.cs
@@ -0,0 +1,22 @@
+using HarmonyLib;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Verse;
+using RimWorld;
+using UnityEngine;
+
+namespace Rimworld_Animations
+{
+ [HarmonyPatch(typeof(PawnRenderer), "DrawHeadHair")]
+ public static class HarmonyPatch_HeadHair
+ {
+ public static void Prefix(ref Vector3 headOffset, ref float angle)
+ {
+
+ }
+
+ }
+}
diff --git a/1.4/Source/Patches/RimworldPatches/HarmonyPatch_PawnRenderer.cs b/1.4/Source/Patches/RimworldPatches/HarmonyPatch_PawnRenderer.cs
new file mode 100644
index 0000000..b7ff70d
--- /dev/null
+++ b/1.4/Source/Patches/RimworldPatches/HarmonyPatch_PawnRenderer.cs
@@ -0,0 +1,82 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+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(RotDrawMode),
+ typeof(PawnRenderFlags)
+ }
+ )]
+ 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, RotDrawMode bodyDrawType, PawnRenderFlags flags)
+ {
+
+ if (flags.FlagSet(PawnRenderFlags.Portrait)) return;
+
+ PawnGraphicSet graphics = __instance.graphics;
+ Pawn pawn = graphics.pawn;
+ CompBodyAnimator bodyAnim = pawn.TryGetComp();
+
+
+ if (bodyAnim != null && bodyAnim.isAnimating && pawn.Map == Find.CurrentMap)
+ {
+ bodyAnim.animatePawnBody(ref rootLoc, ref angle, ref bodyFacing);
+
+ }
+
+ }
+
+ public static IEnumerable Transpiler(IEnumerable instructions)
+ {
+ List ins = instructions.ToList();
+
+ for(int i = 0; i < instructions.Count(); i++)
+ {
+
+ if (i - 3 >= 0 && ins[i - 3].opcode == OpCodes.Call && ins[i - 3].operand != null && ins[i - 3].OperandIs(AccessTools.DeclaredMethod(typeof(PawnRenderer), "BaseHeadOffsetAt")))
+ {
+
+ yield return new CodeInstruction(OpCodes.Ldloca, (object)0);
+ yield return new CodeInstruction(OpCodes.Ldloca, (object)9);
+ yield return new CodeInstruction(OpCodes.Ldloca, (object)8);
+ yield return new CodeInstruction(OpCodes.Ldarga, (object)2);
+ yield return new CodeInstruction(OpCodes.Ldarg_0);
+ yield return new CodeInstruction(OpCodes.Ldfld, AccessTools.DeclaredField(typeof(PawnRenderer), "pawn"));
+ yield return new CodeInstruction(OpCodes.Ldarg, (object)6);
+ yield return new CodeInstruction(OpCodes.Call, AccessTools.DeclaredMethod(typeof(AnimationUtility), "AdjustHead"));
+ yield return ins[i];
+ //headFacing equals true
+ }
+ // Fixes the offsets for eye implants and wounds on the head during animations
+ else if (ins[i].opcode == OpCodes.Callvirt && ins[i].operand != null && ins[i].OperandIs(AccessTools.DeclaredMethod(typeof(PawnOverlayDrawer), "RenderPawnOverlay")))
+ {
+ // Pass some additional info to a new overload of RenderOverBody
+ yield return new CodeInstruction(OpCodes.Ldarg_0);
+ yield return new CodeInstruction(OpCodes.Ldfld, AccessTools.DeclaredField(typeof(PawnRenderer), "pawn"));
+ yield return new CodeInstruction(OpCodes.Ldarg_S, (object)6); // renderer flags
+ yield return new CodeInstruction(OpCodes.Call, AccessTools.DeclaredMethod(typeof(PawnWoundDrawerExtension), "RenderPawnOverlay"));
+ }
+ else
+ {
+ yield return ins[i];
+ }
+ }
+ }
+ }
+}
diff --git a/1.4/Source/Patches/RimworldPatches/HarmonyPatch_PawnRotation.cs b/1.4/Source/Patches/RimworldPatches/HarmonyPatch_PawnRotation.cs
new file mode 100644
index 0000000..7ec75a1
--- /dev/null
+++ b/1.4/Source/Patches/RimworldPatches/HarmonyPatch_PawnRotation.cs
@@ -0,0 +1,29 @@
+using HarmonyLib;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Verse;
+
+namespace Rimworld_Animations {
+ [HarmonyPatch(typeof(Thing), "Rotation", MethodType.Getter)]
+ public static class HarmonyPatch_PawnRotation {
+
+ public static bool Prefix(Thing __instance, ref Rot4 __result) {
+
+ if(!(__instance is Pawn) || (__instance as Pawn)?.TryGetComp() == null || !(__instance as Pawn).TryGetComp().isAnimating) {
+ return true;
+ }
+
+ Pawn pawn = (__instance as Pawn);
+ __result = pawn.TryGetComp().bodyFacing;
+
+ return false;
+
+
+ }
+
+ }
+
+}
diff --git a/1.4/Source/Patches/RimworldPatches/HarmonyPatch_Pawn_DrawTracker.cs b/1.4/Source/Patches/RimworldPatches/HarmonyPatch_Pawn_DrawTracker.cs
new file mode 100644
index 0000000..5cdcfce
--- /dev/null
+++ b/1.4/Source/Patches/RimworldPatches/HarmonyPatch_Pawn_DrawTracker.cs
@@ -0,0 +1,26 @@
+using HarmonyLib;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using UnityEngine;
+using Verse;
+
+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) {
+
+ CompBodyAnimator bodyAnim = ___pawn.TryGetComp();
+
+ if (bodyAnim != null && bodyAnim.isAnimating) {
+ __result = ___pawn.TryGetComp().anchor + ___pawn.TryGetComp().deltaPos;
+
+ return false;
+ }
+ return true;
+ }
+ }
+}
diff --git a/1.4/Source/Patches/RimworldPatches/HarmonyPatch_SetPawnAnimatable.cs b/1.4/Source/Patches/RimworldPatches/HarmonyPatch_SetPawnAnimatable.cs
new file mode 100644
index 0000000..b8c66b8
--- /dev/null
+++ b/1.4/Source/Patches/RimworldPatches/HarmonyPatch_SetPawnAnimatable.cs
@@ -0,0 +1,40 @@
+using HarmonyLib;
+using RimWorld;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection.Emit;
+using System.Text;
+using System.Threading.Tasks;
+using UnityEngine;
+using Verse;
+
+namespace Rimworld_Animations
+{
+ [HarmonyPatch(typeof(PawnRenderer), "RenderPawnAt")]
+ public static class PawnRenderer_RenderPawnAt_Patch
+ {
+ static bool ClearCache(Pawn pawn)
+ {
+ return pawn.IsInvisible() || (pawn.TryGetComp() != null && pawn.TryGetComp().isAnimating);
+ }
+
+ public static IEnumerable Transpiler(IEnumerable instructions)
+ {
+ var list = instructions.ToList();
+
+ foreach (CodeInstruction i in instructions)
+ {
+ if (i.OperandIs(AccessTools.Method(typeof(PawnUtility), "IsInvisible")))
+ {
+ yield return new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(PawnRenderer_RenderPawnAt_Patch), "ClearCache"));
+ }
+ else
+ {
+ yield return i;
+ }
+ }
+ }
+ }
+
+}
diff --git a/1.4/Source/Patches/RimworldPatches/HarmonyPatch_Thing.cs b/1.4/Source/Patches/RimworldPatches/HarmonyPatch_Thing.cs
new file mode 100644
index 0000000..9477abf
--- /dev/null
+++ b/1.4/Source/Patches/RimworldPatches/HarmonyPatch_Thing.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using HarmonyLib;
+using RimWorld;
+using Verse;
+
+namespace Rimworld_Animations
+{
+ [HarmonyPatch(typeof(Thing), "DrawAt")]
+ public static class HarmonyPatch_Thing
+ {
+
+ public static bool Prefix(Thing __instance)
+ {
+ CompThingAnimator thingAnimator = __instance.TryGetComp();
+ if (thingAnimator != null && thingAnimator.isAnimating)
+ {
+ thingAnimator.AnimateThing(__instance);
+ return false;
+
+ }
+
+ return true;
+
+ }
+
+ }
+}
diff --git a/1.4/Source/Settings/AnimationSettings.cs b/1.4/Source/Settings/AnimationSettings.cs
new file mode 100644
index 0000000..0a96621
--- /dev/null
+++ b/1.4/Source/Settings/AnimationSettings.cs
@@ -0,0 +1,98 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Verse;
+using UnityEngine;
+using RimWorld;
+
+namespace Rimworld_Animations {
+
+ public class AnimationSettings : ModSettings {
+
+ public static bool orgasmQuiver, rapeShiver, soundOverride = true, hearts = true, controlGenitalRotation = false, applySemenOnAnimationOrgasm = false, fastAnimForQuickie = false,
+ PlayAnimForNonsexualActs = true;
+ public static bool offsetTab = false, debugMode = false;
+ public static float shiverIntensity = 2f;
+
+ public static Dictionary offsets = new Dictionary();
+ public static Dictionary rotation = new Dictionary();
+
+ public override void ExposeData() {
+
+ base.ExposeData();
+
+ Scribe_Values.Look(ref debugMode, "RJWAnimations-AnimsDebugMode", false);
+ Scribe_Values.Look(ref offsetTab, "RJWAnimations-EnableOffsetTab", false);
+ Scribe_Values.Look(ref controlGenitalRotation, "RJWAnimations-controlGenitalRotation", false);
+ Scribe_Values.Look(ref orgasmQuiver, "RJWAnimations-orgasmQuiver");
+ Scribe_Values.Look(ref fastAnimForQuickie, "RJWAnimations-fastAnimForQuickie");
+ Scribe_Values.Look(ref rapeShiver, "RJWAnimations-rapeShiver");
+ Scribe_Values.Look(ref hearts, "RJWAnimation-sheartsOnLovin");
+ Scribe_Values.Look(ref PlayAnimForNonsexualActs, "RJWAnims-PlayAnimForNonsexualActs");
+ Scribe_Values.Look(ref applySemenOnAnimationOrgasm, "RJWAnimations-applySemenOnOrgasm", false);
+ Scribe_Values.Look(ref soundOverride, "RJWAnimations-rjwAnimSoundOverride", true);
+ Scribe_Values.Look(ref shiverIntensity, "RJWAnimations-shiverIntensity", 2f);
+ //todo: save offsetsByDefName
+
+ Scribe_Collections.Look(ref offsets, "RJWAnimations-animationOffsets");
+ Scribe_Collections.Look(ref rotation, "RJWAnimations-rotationOffsets");
+
+
+
+ //needs to be rewritten
+ //probably somewhere in options?
+
+ }
+
+ }
+
+ public class RJW_Animations : Mod {
+
+ public RJW_Animations(ModContentPack content) : base(content) {
+ GetSettings();
+
+ }
+
+ public override void DoSettingsWindowContents(Rect inRect) {
+
+ Listing_Standard listingStandard = new Listing_Standard();
+ listingStandard.Begin(inRect);
+
+ listingStandard.CheckboxLabeled("Enable Sound Override", ref AnimationSettings.soundOverride);
+ listingStandard.CheckboxLabeled("Control Genital Rotation", ref AnimationSettings.controlGenitalRotation);
+ listingStandard.CheckboxLabeled("Play Fast Animation for Quickie", ref AnimationSettings.fastAnimForQuickie);
+ listingStandard.CheckboxLabeled("Apply Semen on Animation Orgasm", ref AnimationSettings.applySemenOnAnimationOrgasm);
+
+ if(AnimationSettings.applySemenOnAnimationOrgasm) {
+ listingStandard.Label("Recommended--turn down \"Cum on body percent\" in RJW settings to about 33%");
+ }
+
+ listingStandard.CheckboxLabeled("Enable Orgasm Quiver", ref AnimationSettings.orgasmQuiver);
+ listingStandard.CheckboxLabeled("Enable Rape Shiver", ref AnimationSettings.rapeShiver);
+ listingStandard.CheckboxLabeled("Enable hearts during lovin'", ref AnimationSettings.hearts);
+ listingStandard.CheckboxLabeled("Play animation for nonsexual acts (handholding, makeout)", ref AnimationSettings.PlayAnimForNonsexualActs);
+ listingStandard.CheckboxLabeled("Enable Animation Manager Tab", ref AnimationSettings.offsetTab);
+
+ listingStandard.Label("Shiver/Quiver Intensity (default 2): " + AnimationSettings.shiverIntensity);
+ AnimationSettings.shiverIntensity = listingStandard.Slider(AnimationSettings.shiverIntensity, 0.0f, 12f);
+
+ listingStandard.CheckboxLabeled("Debug Mode", ref AnimationSettings.debugMode);
+
+
+ listingStandard.End();
+ base.DoSettingsWindowContents(inRect);
+ }
+
+ public override void WriteSettings() {
+ base.WriteSettings();
+ OffsetMainButtonDefOf.OffsetManager.buttonVisible = AnimationSettings.offsetTab;
+
+ }
+
+ public override string SettingsCategory() {
+ return "RJW Animation Settings";
+ }
+ }
+}
diff --git a/1.4/Source/Utilities/AnimationUtility.cs b/1.4/Source/Utilities/AnimationUtility.cs
new file mode 100644
index 0000000..a75fc32
--- /dev/null
+++ b/1.4/Source/Utilities/AnimationUtility.cs
@@ -0,0 +1,319 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using RimWorld;
+using rjw.Modules.Interactions.Helpers;
+using rjw.Modules.Interactions.Objects;
+using UnityEngine;
+using Verse;
+using Verse.AI;
+using rjw.Modules.Interactions.Enums;
+
+namespace Rimworld_Animations {
+ public static class AnimationUtility {
+ /*
+ Note: always make the list in this order:
+ Female pawns, animal female pawns, male pawns, animal male pawns
+ */
+ public static AnimationDef tryFindAnimation(ref List participants, rjw.xxx.rjwSextype sexType = 0, rjw.SexProps sexProps = null) {
+
+
+ InteractionWithExtension interaction = InteractionHelper.GetWithExtension(sexProps.dictionaryKey);
+
+
+ if(interaction.HasInteractionTag(InteractionTag.Reverse))
+ {
+ Pawn buffer = participants[1];
+ participants[1] = participants[0];
+ participants[0] = buffer;
+ }
+
+ participants =
+ participants.OrderBy(p => p.jobs.curDriver is rjw.JobDriver_SexBaseInitiator)
+ .OrderBy(p => rjw.xxx.can_fuck(p))
+ .ToList();
+
+
+ List localParticipants = new List(participants);
+
+ IEnumerable options = DefDatabase.AllDefs.Where((AnimationDef x) => {
+
+
+ if (x.actors.Count != localParticipants.Count) {
+ return false;
+ }
+ for (int i = 0; i < x.actors.Count; i++) {
+
+ if (rjw.RJWPreferenceSettings.Malesex == rjw.RJWPreferenceSettings.AllowedSex.Nohomo) {
+ if (rjw.xxx.is_male(localParticipants[i]) && x.actors[i].isFucked) {
+ return false;
+ }
+ }
+ if (x.actors[i].requiredGender != null && !x.actors[i].requiredGender.Contains(localParticipants[i].gender.ToStringSafe()))
+ {
+ if (AnimationSettings.debugMode)
+ {
+ Log.Message(string.Concat(new string[]
+ {
+ x.defName.ToStringSafe(),
+ " not selected -- ",
+ localParticipants[i].def.defName.ToStringSafe(),
+ " ",
+ localParticipants[i].Name.ToStringSafe(),
+ " does not match required gender"
+ }));
+ }
+ return false;
+ }
+ if ((x.actors[i].blacklistedRaces != null) && x.actors[i].blacklistedRaces.Contains(localParticipants[i].def.defName)) {
+ if(AnimationSettings.debugMode)
+ Log.Message(x.defName.ToStringSafe() + " not selected -- " + localParticipants[i].def.defName.ToStringSafe() + " " + localParticipants[i].Name.ToStringSafe() + " is blacklisted");
+ return false;
+ }
+
+ if(x.actors[i].defNames.Contains("Human")) {
+ if (!rjw.xxx.is_human(localParticipants[i])) {
+ if (AnimationSettings.debugMode)
+ Log.Message(x.defName.ToStringSafe() + " not selected -- " + localParticipants[i].def.defName.ToStringSafe() + " " + localParticipants[i].Name.ToStringSafe() + " is not human");
+
+ return false;
+ }
+
+ }
+ else if (!x.actors[i].bodyDefTypes.Contains(localParticipants[i].RaceProps.body)) {
+
+ if (!x.actors[i].defNames.Contains(localParticipants[i].def.defName)) {
+
+ if (rjw.RJWSettings.DevMode) {
+ string animInfo = x.defName.ToStringSafe() + " not selected -- " + localParticipants[i].def.defName.ToStringSafe() + " " + localParticipants[i].Name.ToStringSafe() + " is not ";
+ foreach(String defname in x.actors[i].defNames) {
+ animInfo += defname + ", ";
+ }
+ if (AnimationSettings.debugMode)
+ Log.Message(animInfo);
+ }
+
+ return false;
+ }
+ }
+ //genitals checking
+
+ if(!GenitalCheckForPawn(x.actors[i].requiredGenitals, localParticipants[i], out string failReason)) {
+ Debug.Log("Didn't select " + x.defName + ", " + localParticipants[i].Name + " " + failReason);
+ return false;
+ }
+
+ //TESTING ANIMATIONS ONLY REMEMBER TO COMMENT OUT BEFORE PUSH
+ /*
+ if (x.defName != "Cunnilingus")
+ return false;
+ */
+
+
+ if (x.actors[i].isFucking && !rjw.xxx.can_fuck(localParticipants[i])) {
+ if (AnimationSettings.debugMode)
+ Log.Message(x.defName.ToStringSafe() + " not selected -- " + localParticipants[i].def.defName.ToStringSafe() + " " + localParticipants[i].Name.ToStringSafe() + " can't fuck");
+ return false;
+ }
+
+ if (x.actors[i].isFucked && !rjw.xxx.can_be_fucked(localParticipants[i])) {
+ if (AnimationSettings.debugMode)
+ Log.Message(x.defName.ToStringSafe() + " not selected -- " + localParticipants[i].def.defName.ToStringSafe() + " " + localParticipants[i].Name.ToStringSafe() + " can't be fucked");
+ return false;
+ }
+ }
+ return true;
+ });
+ List optionsWithInteractionType = options.ToList().FindAll(x => x.interactionDefTypes != null && x.interactionDefTypes.Contains(sexProps.sexType.ToStringSafe()));
+ if (optionsWithInteractionType.Any()) {
+ if (AnimationSettings.debugMode)
+ Log.Message("Selecting animation for interaction type " + sexProps.sexType.ToStringSafe() + "...");
+ return optionsWithInteractionType.RandomElement();
+ }
+ List optionsWithSexType = options.ToList().FindAll(x => x.sexTypes != null && x.sexTypes.Contains(sexType));
+ if (optionsWithSexType.Any()) {
+ if (AnimationSettings.debugMode)
+ Log.Message("Selecting animation for rjwSexType " + sexType.ToStringSafe() + "...");
+ return optionsWithSexType.RandomElement();
+ }
+
+ /*
+ if(optionsWithInitiator.Any()) {
+ if (AnimationSettings.debugMode)
+ Log.Message("Selecting animation for initiators...");
+ }
+ */
+
+ if (options != null && options.Any()) {
+ if (AnimationSettings.debugMode)
+ Log.Message("Randomly selecting animation...");
+ return options.RandomElement();
+ }
+ else
+ return null;
+ }
+
+ public static void RenderPawnHeadMeshInAnimation1(Mesh mesh, Vector3 loc, Quaternion quaternion, Material material, bool drawNow, Pawn pawn) {
+
+ if (pawn == null || pawn.Map != Find.CurrentMap) {
+ GenDraw.DrawMeshNowOrLater(mesh, loc, quaternion, material, drawNow);
+ return;
+ }
+
+ CompBodyAnimator pawnAnimator = pawn.TryGetComp();
+
+ if (pawnAnimator == null || !pawnAnimator.isAnimating) {
+ GenDraw.DrawMeshNowOrLater(mesh, loc, quaternion, material, drawNow);
+ } else {
+ Vector3 pawnHeadPosition = pawnAnimator.getPawnHeadPosition();
+ pawnHeadPosition.y = loc.y;
+ GenDraw.DrawMeshNowOrLater(MeshPool.humanlikeHeadSet.MeshAt(pawnAnimator.headFacing), pawnHeadPosition, Quaternion.AngleAxis(pawnAnimator.headAngle, Vector3.up), material, true);
+ }
+ }
+
+ public static void AdjustHead(ref Quaternion quat, ref Rot4 bodyFacing, ref Vector3 pos, ref float angle, Pawn pawn, PawnRenderFlags flags)
+ {
+ if (flags.FlagSet(PawnRenderFlags.Portrait)) return;
+
+ CompBodyAnimator anim = pawn.TryGetComp();
+ if (anim.isAnimating)
+ {
+ bodyFacing = anim.headFacing;
+ angle = anim.headAngle;
+ quat = Quaternion.AngleAxis(anim.headAngle, Vector3.up);
+ pos = anim.getPawnHeadOffset();
+
+ }
+ }
+
+ public static void RenderPawnHeadMeshInAnimation(Mesh mesh, Vector3 loc, Quaternion quaternion, Material material, bool portrait, Pawn pawn, float bodySizeFactor = 1) {
+
+ if (pawn == null) {
+ GenDraw.DrawMeshNowOrLater(mesh, loc, quaternion, material, portrait);
+ return;
+ }
+
+ CompBodyAnimator pawnAnimator = pawn.TryGetComp