mirror of
https://gitgud.io/AbstractConcept/rimworld-animations-patch.git
synced 2024-08-15 00:43:27 +00:00
v 2.0.0
This commit is contained in:
parent
fcf187c7dd
commit
38ec4f86c1
68 changed files with 846 additions and 1934 deletions
|
@ -29,7 +29,7 @@ namespace Rimworld_Animations_Patch
|
|||
}))();
|
||||
}
|
||||
|
||||
catch (TypeLoadException ex) { }
|
||||
catch (TypeLoadException) { }
|
||||
}
|
||||
|
||||
public static bool Prefix_ShouldNotDrawAddonsForPawn(ref bool __result, Pawn pawn)
|
||||
|
|
|
@ -23,9 +23,9 @@ namespace Rimworld_Animations_Patch
|
|||
LocalTargetInfo b = jobdriver.job.targetB.IsValid ? jobdriver.job.targetB : jobdriver.job.targetQueueB.FirstValid();
|
||||
LocalTargetInfo targetC = jobdriver.job.targetC;
|
||||
|
||||
__result = JobUtility.GetResolvedJobReport(jobdriver.pawn.GetAnimationData().animationDef.label, a, b, targetC);
|
||||
//__result = JobUtility.GetResolvedJobReport(jobdriver.pawn.GetAnimationData().animationDef.label, a, b, targetC);
|
||||
|
||||
return false;
|
||||
//return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -17,11 +17,6 @@ namespace Rimworld_Animations_Patch
|
|||
{
|
||||
Harmony harmony = new Harmony("Rimworld_Animations_Patch");
|
||||
harmony.PatchAll(Assembly.GetExecutingAssembly());
|
||||
|
||||
Quirk voyeur = new Quirk("Voyeur", "VoyeurQuirk", null, null);
|
||||
|
||||
if (Quirk.All.Contains(voyeur) == false)
|
||||
{ Quirk.All.Add(voyeur); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,67 +12,11 @@ using rjw;
|
|||
|
||||
namespace Rimworld_Animations_Patch
|
||||
{
|
||||
/*[StaticConstructorOnStartup]
|
||||
[HarmonyPatch(typeof(PawnRenderer), "RenderPawnInternal", new Type[]
|
||||
{
|
||||
typeof(Vector3),
|
||||
typeof(float),
|
||||
typeof(bool),
|
||||
typeof(Rot4),
|
||||
typeof(RotDrawMode),
|
||||
typeof(PawnRenderFlags)
|
||||
}
|
||||
)]
|
||||
public static class HarmonyPatch_PawnRenderer_RenderPawnInternal
|
||||
{
|
||||
public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
List<CodeInstruction> ins = instructions.ToList();
|
||||
|
||||
for (int i = 0; i < instructions.Count(); i++)
|
||||
{
|
||||
bool runIns = true;
|
||||
|
||||
// Replaces the rotation that gets passed to DrawHeadHair with one that is based the current 'true' head orientation
|
||||
if (i + 8 < instructions.Count() && ins[i + 8].opcode == OpCodes.Call && ins[i + 8].operand != null && ins[i + 8].OperandIs(AccessTools.DeclaredMethod(typeof(PawnRenderer), "DrawHeadHair")))
|
||||
{
|
||||
// Get the true head rotation
|
||||
yield return new CodeInstruction(OpCodes.Ldarg_0);
|
||||
yield return new CodeInstruction(OpCodes.Ldfld, AccessTools.DeclaredField(typeof(PawnRenderer), "pawn"));
|
||||
yield return new CodeInstruction(OpCodes.Ldloc, (object)7); // local body facing
|
||||
yield return new CodeInstruction(OpCodes.Ldarg_S, (object)6); // renderer flags
|
||||
yield return new CodeInstruction(OpCodes.Call, AccessTools.DeclaredMethod(typeof(AnimationPatchUtility), "PawnHeadRotInAnimation"));
|
||||
yield return new CodeInstruction(OpCodes.Stloc_S, (object)7); // set local body facing to true head facing
|
||||
|
||||
// Pass this head rotation to a new DrawHeadHair call
|
||||
yield return new CodeInstruction(OpCodes.Ldarg_0);
|
||||
yield return new CodeInstruction(OpCodes.Ldarg_1);
|
||||
yield return new CodeInstruction(OpCodes.Ldloc_S, (object)6);
|
||||
yield return new CodeInstruction(OpCodes.Ldarg_2);
|
||||
yield return new CodeInstruction(OpCodes.Ldloc_S, (object)7); // local true head facing
|
||||
yield return new CodeInstruction(OpCodes.Ldloc_S, (object)7); // local true head facing
|
||||
yield return new CodeInstruction(OpCodes.Ldarg_S, (object)5); // bodyDrawType
|
||||
yield return new CodeInstruction(OpCodes.Ldarg_S, (object)6); // renderer flags
|
||||
yield return new CodeInstruction(OpCodes.Call, AccessTools.DeclaredMethod(typeof(PawnRenderer), "DrawHeadHair"));
|
||||
|
||||
// Skip the original call to DrawHeadHair
|
||||
i = i + 8;
|
||||
|
||||
runIns = false;
|
||||
}
|
||||
|
||||
if (runIns)
|
||||
{
|
||||
yield return ins[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
[StaticConstructorOnStartup]
|
||||
[HarmonyPatch(typeof(PawnGraphicSet), "ResolveAllGraphics")]
|
||||
public static class HarmonyPatch_PawnGraphicSet_ResolveAllGraphics
|
||||
{
|
||||
// Update whether body parts are visible after resolving graphics
|
||||
public static void Postfix(PawnGraphicSet __instance)
|
||||
{
|
||||
if (__instance?.pawn?.apparel == null)
|
||||
|
|
|
@ -7,7 +7,6 @@ using Verse;
|
|||
using Verse.AI;
|
||||
using rjw;
|
||||
using Rimworld_Animations;
|
||||
using RJW_ToysAndMasturbation;
|
||||
|
||||
namespace Rimworld_Animations_Patch
|
||||
{
|
||||
|
@ -16,48 +15,8 @@ namespace Rimworld_Animations_Patch
|
|||
{
|
||||
public static void Postfix(ref JobDriver_Sex __instance)
|
||||
{
|
||||
Pawn pawn = __instance.pawn;
|
||||
|
||||
// Sets ticks so that the orgasm meter starts empty, plus stop any running animations
|
||||
HarmonyPatch_JobDriver_Masturbate_setup_ticks.Postfix(ref __instance);
|
||||
|
||||
// Invite another for a threesome?
|
||||
if (RJWHookupSettings.QuickHookupsEnabled &&
|
||||
__instance is JobDriver_SexBaseInitiator &&
|
||||
pawn.GetAllSexParticipants().Count == 2 &&
|
||||
(__instance is JobDriver_JoinInSex) == false &&
|
||||
Random.value < BasicSettings.chanceForOtherToJoinInSex)
|
||||
{
|
||||
DebugMode.Message("Find another to join in sex");
|
||||
|
||||
List<Pawn> candidates = new List<Pawn>();
|
||||
float radius = 4f;
|
||||
|
||||
foreach (Thing thing in GenRadial.RadialDistinctThingsAround(pawn.Position, pawn.Map, radius, true))
|
||||
{
|
||||
Pawn other = thing as Pawn;
|
||||
ThoughtDef thoughtDef = SexInteractionUtility.GetThoughtsAboutSexAct(other, __instance, out Precept precept);
|
||||
|
||||
// Find candidates to invite
|
||||
if (other != null && thoughtDef?.hediff == null && SexInteractionUtility.InvitePasserbyForSex(other, pawn.GetAllSexParticipants()))
|
||||
{
|
||||
DebugMode.Message(other.NameShortColored + " is a potential candidate");
|
||||
candidates.Add(other);
|
||||
}
|
||||
}
|
||||
|
||||
// Invite a random candidate (weighted by attraction)
|
||||
if (candidates.Count > 0)
|
||||
{
|
||||
Pawn invitedPawn = candidates.RandomElementByWeight(x => SexAppraiser.would_fuck(pawn, x, false, false, true) + SexAppraiser.would_fuck(pawn.GetSexPartner(), x, false, false, true));
|
||||
pawn.GetSexInitiator().IsInBed(out Building bed);
|
||||
|
||||
DebugMode.Message(invitedPawn.NameShortColored + " was invited to join in sex");
|
||||
|
||||
Job job = new Job(DefDatabase<JobDef>.GetNamed("JoinInSex", false), pawn.GetSexPartner(), bed);
|
||||
invitedPawn.jobs.TryTakeOrderedJob(job);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -117,10 +76,10 @@ namespace Rimworld_Animations_Patch
|
|||
|
||||
SexProps sexProps = new SexProps();
|
||||
sexProps.pawn = __instance.pawn;
|
||||
sexProps.partner = __instance.pawn;
|
||||
sexProps.partner = null;
|
||||
sexProps.sexType = xxx.rjwSextype.Masturbation;
|
||||
|
||||
List<InteractionDef> interactionDefs = DefDatabase<InteractionDef>.AllDefs.Where(x => x.HasModExtension<InteractionExtension>()).ToList();
|
||||
IEnumerable<InteractionDef> interactionDefs = DefDatabase<InteractionDef>.AllDefs.Where(x => x.HasModExtension<InteractionExtension>());
|
||||
Dictionary<rjw.Modules.Interactions.Objects.InteractionWithExtension, float> interactionsPlusWeights = new Dictionary<rjw.Modules.Interactions.Objects.InteractionWithExtension, float>();
|
||||
|
||||
foreach (InteractionDef interactionDef in interactionDefs)
|
||||
|
@ -161,7 +120,6 @@ namespace Rimworld_Animations_Patch
|
|||
{ return; }
|
||||
|
||||
// Get animation data
|
||||
AnimationDef anim = __instance.pawn.GetAnimationData()?.animationDef;
|
||||
List<Pawn> pawnsToAnimate = __instance.pawn.GetAllSexParticipants();
|
||||
|
||||
// Sync animations across participants
|
||||
|
@ -276,8 +234,8 @@ namespace Rimworld_Animations_Patch
|
|||
if (sexProps.sexType != xxx.rjwSextype.Oral || pawnsToAnimate.Count != 2)
|
||||
{ return; }
|
||||
|
||||
List<AnimationDef> kissingAnims = DefDatabase<AnimationDef>.AllDefs.Where(x => x.defName.Contains("Kiss")).ToList();
|
||||
AnimationDef anim = kissingAnims[Random.Range(0, kissingAnims.Count)];
|
||||
IEnumerable<AnimationDef> kissingAnims = DefDatabase<AnimationDef>.AllDefs.Where(x => x.defName.Contains("Kiss"));
|
||||
AnimationDef anim = kissingAnims.ElementAt(Random.Range(0, kissingAnims.Count()));
|
||||
|
||||
if (anim == null)
|
||||
{ DebugMode.Message("No animation found"); return; }
|
||||
|
@ -299,41 +257,6 @@ namespace Rimworld_Animations_Patch
|
|||
}
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(JobDriver_Sex), "SexTick")]
|
||||
public static class HarmonyPatch_JobDriver_Sex_SexTick
|
||||
{
|
||||
// If pawns don't have privacy, they'll stop having sex
|
||||
public static void Postfix(ref JobDriver_Sex __instance, Pawn pawn)
|
||||
{
|
||||
if (pawn.IsHashIntervalTick(90))
|
||||
{
|
||||
if (pawn.IsMasturbating() && pawn.HasPrivacy(8f) == false)
|
||||
{ pawn.jobs.EndCurrentJob(JobCondition.InterruptForced, false, false); }
|
||||
|
||||
else if (pawn.IsHavingSex())
|
||||
{
|
||||
bool havePrivacy = true;
|
||||
List<Pawn> participants = pawn.GetAllSexParticipants();
|
||||
|
||||
foreach (Pawn participant in participants)
|
||||
{
|
||||
if (participant.HasPrivacy(8f) == false)
|
||||
{ havePrivacy = false; }
|
||||
}
|
||||
|
||||
if (__instance.Sexprops != null && (__instance.Sexprops.isRape || __instance.Sexprops.isWhoring))
|
||||
{ return; }
|
||||
|
||||
if (havePrivacy == false)
|
||||
{
|
||||
foreach (Pawn participant in participants)
|
||||
{ participant.jobs.EndCurrentJob(JobCondition.InterruptForced, false, false); }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(JobDriver_Sex), "Orgasm")]
|
||||
public static class HarmonyPatch_JobDriver_Sex_Orgasm
|
||||
{
|
||||
|
@ -346,7 +269,8 @@ namespace Rimworld_Animations_Patch
|
|||
return true;
|
||||
}
|
||||
|
||||
public static bool ParticipantsDesireMoreSex(JobDriver_Sex jobdriver)
|
||||
// Causes too much trouble...
|
||||
/*public static bool ParticipantsDesireMoreSex(JobDriver_Sex jobdriver)
|
||||
{
|
||||
List<Pawn> participants = jobdriver.pawn.GetAllSexParticipants();
|
||||
|
||||
|
@ -387,7 +311,7 @@ namespace Rimworld_Animations_Patch
|
|||
participants[1].jobs.StartJob(job, JobCondition.Succeeded);
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(JobDriver_SexBaseInitiator), "End")]
|
||||
|
@ -398,7 +322,7 @@ namespace Rimworld_Animations_Patch
|
|||
{
|
||||
if (__instance.Partner != null && __instance?.Partner?.jobs?.curDriver != null && __instance.Partner.Dead == false && __instance.Partner?.jobs.curDriver is JobDriver_SexBaseReciever)
|
||||
{
|
||||
foreach (Pawn participant in (__instance.Partner?.jobs.curDriver as JobDriver_SexBaseReciever).parteners.ToList())
|
||||
foreach (Pawn participant in (__instance.Partner?.jobs.curDriver as JobDriver_SexBaseReciever).parteners)
|
||||
{ participant.jobs.EndCurrentJob(JobCondition.Succeeded, false, true); }
|
||||
|
||||
(__instance.Partner?.jobs.curDriver as JobDriver_SexBaseReciever).parteners.Clear();
|
||||
|
@ -426,7 +350,7 @@ namespace Rimworld_Animations_Patch
|
|||
// Fixes mouth check
|
||||
public static bool Prefix(ref bool __result, Pawn pawn)
|
||||
{
|
||||
__result = pawn.health.hediffSet.GetNotMissingParts().Any(x => x.def.defName.ToLower().ContainsAny("mouth", "teeth", "jaw", "beak"));
|
||||
__result = pawn.health.hediffSet.GetNotMissingParts().Any(x => x.def.defName.ContainsAny("mouth", "teeth", "jaw", "beak", "Mouth", "Teeth", "Jaw", "Beak"));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ namespace Rimworld_Animations_Patch
|
|||
}))();
|
||||
}
|
||||
|
||||
catch (TypeLoadException ex) { }
|
||||
catch (TypeLoadException) { }
|
||||
}
|
||||
|
||||
public static bool Postfix_ThinkNode_ConditionalNude_Satisfied(ref bool __result, Pawn pawn)
|
||||
|
@ -34,7 +34,7 @@ namespace Rimworld_Animations_Patch
|
|||
if (__result == false && pawn?.apparel?.WornApparel != null)
|
||||
{
|
||||
// If 'isBeingWorn' has a value, the apparel has already been checked if it should be discarded
|
||||
if (pawn.apparel.WornApparel.Any(x => x.TryGetComp<CompApparelVisibility>() != null && x.TryGetComp<CompApparelVisibility>().isBeingWorn.HasValue))
|
||||
if (pawn.apparel.WornApparel.NullOrEmpty() || pawn.apparel.WornApparel.Any(x => x.TryGetComp<CompApparelVisibility>() != null && x.TryGetComp<CompApparelVisibility>().isBeingWorn.HasValue))
|
||||
{ __result = true; }
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ using RimNudeWorld;
|
|||
|
||||
namespace Rimworld_Animations_Patch
|
||||
{
|
||||
[StaticConstructorOnStartup]
|
||||
/*[StaticConstructorOnStartup]
|
||||
public static class HarmonyPatch_RimNudeWorld
|
||||
{
|
||||
static HarmonyPatch_RimNudeWorld()
|
||||
|
@ -33,5 +33,5 @@ namespace Rimworld_Animations_Patch
|
|||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ namespace Rimworld_Animations_Patch
|
|||
CompPawnSexData comp = participant.TryGetComp<CompPawnSexData>();
|
||||
if (comp == null) return;
|
||||
|
||||
comp.UpdateHands();
|
||||
comp.UpdateBodyPartCountAndSize();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -48,7 +48,7 @@ namespace Rimworld_Animations_Patch
|
|||
CompPawnSexData comp = __instance.pawn.TryGetComp<CompPawnSexData>();
|
||||
if (comp == null) return;
|
||||
|
||||
comp.handAnimationDef = DefDatabase<HandAnimationDef>.AllDefs.FirstOrDefault(x => x.animationDefName == __instance.pawn?.GetAnimationData()?.animationDef?.defName);
|
||||
comp.handAnimationDef = DefDatabase<HandAnimationDef>.AllDefs.FirstOrDefault(x => x.animationDef == __instance.pawn?.GetAnimationData()?.animationDef);
|
||||
}
|
||||
|
||||
// Extend the animation selector's body part check to include hands and whether the pawn is in bed or not
|
||||
|
@ -108,32 +108,32 @@ namespace Rimworld_Animations_Patch
|
|||
public static bool Prefix_DrawAddons(PawnRenderFlags renderFlags, Vector3 vector, Vector3 headOffset, Pawn pawn, Quaternion quat, Rot4 rotation)
|
||||
{
|
||||
if (!(pawn.def is ThingDef_AlienRace alienProps) || renderFlags.FlagSet(PawnRenderFlags.Invisible)) return false;
|
||||
if (AnimationPatchUtility.ShouldNotDrawAddonsForPawn(pawn))
|
||||
{ return false; }
|
||||
|
||||
// Get actor components and body addons
|
||||
List<AlienPartGenerator.BodyAddon> bodyAddons = alienProps.alienRace.generalSettings.alienPartGenerator.bodyAddons;
|
||||
AlienPartGenerator.AlienComp alienComp = pawn.GetComp<AlienPartGenerator.AlienComp>();
|
||||
CompBodyAnimator animatorComp = pawn.TryGetComp<CompBodyAnimator>();
|
||||
CompPawnSexData sexDataComp = pawn.TryGetComp<CompPawnSexData>();
|
||||
ActorAnimationData pawnAnimationData = pawn?.GetAnimationData();
|
||||
|
||||
// Try to draw apparel thrown on ground
|
||||
if (ApparelSettings.clothesThrownOnGround)
|
||||
{ ApparelAnimationUtility.TryToDrawApparelOnFloor(pawn); }
|
||||
|
||||
// Get actor components and body addons
|
||||
List<AlienPartGenerator.BodyAddon> bodyAddons = alienProps.alienRace.generalSettings.alienPartGenerator.bodyAddons.ToList();
|
||||
AlienPartGenerator.AlienComp alienComp = pawn.GetComp<AlienPartGenerator.AlienComp>();
|
||||
CompBodyAnimator animatorComp = pawn.TryGetComp<CompBodyAnimator>();
|
||||
CompPawnSexData sexDataComp = pawn.TryGetComp<CompPawnSexData>();
|
||||
if (sexDataComp == null) return true;
|
||||
// Exit clauses
|
||||
if (BasicSettings.useLegacyAnimationSystem || AnimationPatchUtility.ShouldNotDrawAddonsForPawn(pawn) || sexDataComp == null)
|
||||
{ return true; }
|
||||
|
||||
// Get available hands
|
||||
int handsAvailableCount = sexDataComp.GetNumberOfHands();
|
||||
|
||||
// Sort addons by their layer offset, otherwise body parts will actualy be layered according to their position in the list
|
||||
// Note that sorting the addons directly seems to mess up relations between lists need by AlienRace
|
||||
var sortedBodyAddons = bodyAddons.Select((x, i) => new KeyValuePair<AlienPartGenerator.BodyAddon, int>(x, i)).OrderBy(x => x.Key.offsets.GetOffset(rotation).layerOffset).ToList();
|
||||
List<int> idxBodyAddons = sortedBodyAddons.Select(x => x.Value).ToList();
|
||||
var sortedBodyAddons = bodyAddons.Select((x, i) => new KeyValuePair<AlienPartGenerator.BodyAddon, int>(x, i)).OrderBy(x => x.Key.offsets.GetOffset(rotation).layerOffset);
|
||||
IEnumerable<int> idxBodyAddons = sortedBodyAddons.Select(x => x.Value);
|
||||
|
||||
for (int idx = 0; idx < idxBodyAddons.Count; idx++)
|
||||
foreach(int i in idxBodyAddons)
|
||||
{
|
||||
int i = idxBodyAddons[idx];
|
||||
|
||||
// Get body addon components
|
||||
AlienPartGenerator.BodyAddon bodyAddon = bodyAddons[i];
|
||||
Graphic addonGraphic = alienComp.addonGraphics[i];
|
||||
|
@ -141,33 +141,33 @@ namespace Rimworld_Animations_Patch
|
|||
if (bodyAddonDatum == null) continue;
|
||||
|
||||
// Can draw?
|
||||
bool canDraw = addonGraphic.path.ToLower().Contains("featureless") == false && bodyAddonDatum.CanDraw();
|
||||
bool canDraw = addonGraphic.path.Contains("featureless") == false && addonGraphic.path.Contains("Featureless") == false && bodyAddonDatum.CanDraw();
|
||||
bool drawHand = BasicSettings.showHands && handsAvailableCount > 0 && renderFlags.FlagSet(PawnRenderFlags.Portrait) == false;
|
||||
|
||||
|
||||
if (canDraw == false && drawHand == false)
|
||||
{ continue; }
|
||||
|
||||
// Get body angle
|
||||
float bodyAngle = animatorComp?.isAnimating == true && renderFlags.FlagSet(PawnRenderFlags.Portrait) == false ? animatorComp.bodyAngle : quat.eulerAngles.y;
|
||||
bodyAngle = bodyAngle < 0f ? 360f + (bodyAngle % 360f) : bodyAngle % 360f;
|
||||
bodyAngle = MathUtility.ClampAngle(bodyAngle);
|
||||
|
||||
// Get the apparent rotation and body addon angle
|
||||
Rot4 apparentRotation = rotation;
|
||||
float bodyAddonAngle = bodyAddon.angle;
|
||||
|
||||
float bodyAddonAngle = MathUtility.ClampAngle(bodyAddon.angle);
|
||||
|
||||
if (renderFlags.FlagSet(PawnRenderFlags.Portrait) == false && animatorComp?.isAnimating == true)
|
||||
{
|
||||
apparentRotation = bodyAddonDatum.alignsWithHead ? animatorComp.headFacing : animatorComp.bodyFacing;
|
||||
|
||||
if (animatorComp.controlGenitalAngle && addonGraphic.path.ToLower().Contains("penis"))
|
||||
{ bodyAddonAngle += AnimationSettings.controlGenitalRotation ? animatorComp.genitalAngle : 0f; }
|
||||
|
||||
if (bodyAddonDatum.alignsWithHead)
|
||||
{ bodyAngle = animatorComp.headAngle; }
|
||||
{ bodyAngle = MathUtility.ClampAngle(animatorComp.headAngle); }
|
||||
|
||||
if (animatorComp.controlGenitalAngle && (addonGraphic.path.Contains("penis") || addonGraphic.path.Contains("Penis")))
|
||||
{ bodyAddonAngle = MathUtility.ClampAngle(bodyAddonAngle + (AnimationSettings.controlGenitalRotation ? MathUtility.ClampAngle(animatorComp.genitalAngle) : 0f)); }
|
||||
}
|
||||
|
||||
bodyAddonAngle = bodyAddonAngle < 0f ? 360f - (bodyAddonAngle % 360) : bodyAddonAngle % 360f;
|
||||
float combinedAngle = (bodyAngle + bodyAddonAngle) < 0f ? 360f + ((bodyAngle + bodyAddonAngle) % 360) : (bodyAngle + bodyAddonAngle) % 360f;
|
||||
float combinedAngle = MathUtility.ClampAngle(bodyAngle + bodyAddonAngle);
|
||||
|
||||
Vector3 vector_ = vector;
|
||||
Vector3 headOffset_ = bodyAddonDatum.alignsWithHead ? headOffset : Vector3.zero;
|
||||
|
@ -190,21 +190,45 @@ namespace Rimworld_Animations_Patch
|
|||
{
|
||||
GenDraw.DrawMeshNowOrLater(mesh: addonGraphic.MeshAt(rot: apparentRotation),
|
||||
loc: bodyAddonPosition,
|
||||
quat: Mathf.Approximately(combinedAngle, 0f) ? quat : Quaternion.AngleAxis(angle: combinedAngle, axis: Vector3.up),
|
||||
quat: Quaternion.AngleAxis(angle: combinedAngle, axis: Vector3.up),
|
||||
mat: addonGraphic.MatAt(rot: apparentRotation),
|
||||
drawNow: renderFlags.FlagSet(PawnRenderFlags.DrawNow));
|
||||
}
|
||||
|
||||
|
||||
// Draw hand over the body part if required
|
||||
if (drawHand)
|
||||
{
|
||||
float finalAngle = 0;
|
||||
|
||||
if (HandAnimationUtility.TryToDrawHand(pawn, addonGraphic.path, bodyAddonPosition, finalAngle, rotation, renderFlags))
|
||||
if (HandAnimationUtility.TryToDrawHand(pawn, pawnAnimationData, addonGraphic.path, bodyAddonPosition, finalAngle, rotation, renderFlags))
|
||||
{ handsAvailableCount--; }
|
||||
}
|
||||
}
|
||||
|
||||
// Add-ons
|
||||
if (animatorComp?.isAnimating == true)
|
||||
{
|
||||
//ActorAnimationData actorData = pawn.GetAnimationData();
|
||||
//PawnAnimationClipExt clip = actorData.animationDef.animationStages[actorData.currentStage].animationClips[actorData.actorID] as PawnAnimationClipExt;
|
||||
|
||||
/*foreach (ActorAddon addon in clip.Addons)
|
||||
{
|
||||
actorBodypart = actorBody.GetActorBodyPart(addon.AddonName);
|
||||
if (actorBodypart == null) continue;
|
||||
|
||||
ActorBody anchoringActorBody = actorBodies.GetComponentsInChildren<ActorBody>()?.FirstOrDefault(x => x.actorID == addon.AnchoringActor);
|
||||
Vector3 anchor = PawnUtility.GetBodyPartAnchor(anchoringActorBody, addon.anchorName);
|
||||
|
||||
actorBodypart.transform.position = anchor + new Vector3(addon.PosX.Evaluate(clipPercent), addon.PosZ.Evaluate(clipPercent), 0);
|
||||
actorBodypart.transform.eulerAngles = new Vector3(0, 0, -addon.Rotation.Evaluate(clipPercent));
|
||||
|
||||
actorBodypart.bodyPartRenderer.sortingLayerName = addon.Layer;
|
||||
//actorBodypart.bodyPartRenderer.sprite
|
||||
|
||||
actorBodypart.gameObject.SetActive(addon.Render);
|
||||
}*/
|
||||
}
|
||||
|
||||
// Body addons are sometimes are not appropriately concealed by long hair in portraits, so re-draw the pawn's hair here
|
||||
if (pawn.Drawer.renderer.graphics.headGraphic != null && renderFlags.FlagSet(PawnRenderFlags.Portrait) && BasicSettings.redrawHair)
|
||||
{
|
||||
|
@ -214,10 +238,10 @@ namespace Rimworld_Animations_Patch
|
|||
float headAngle = animatorComp != null && animatorComp.isAnimating && !renderFlags.FlagSet(PawnRenderFlags.Portrait) ? animatorComp.headAngle : quat.eulerAngles.y;
|
||||
RotDrawMode rotDrawMode = (RotDrawMode)AccessTools.Property(typeof(PawnRenderer), "CurRotDrawMode").GetValue(pawn.Drawer.renderer);
|
||||
|
||||
methodInfo.Invoke(pawn.Drawer.renderer, new object[] { vector + new Vector3(0f, YOffset_Head, 0f), headOffset, headAngle, headFacing, headFacing, rotDrawMode, renderFlags });
|
||||
methodInfo.Invoke(pawn.Drawer.renderer, new object[] { vector + new Vector3(0f, YOffset_Head, 0f), headOffset, headAngle, headFacing, headFacing, rotDrawMode, renderFlags, true });
|
||||
}
|
||||
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
// List of potentially useful layer offsets
|
||||
|
|
|
@ -1,107 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using RimWorld;
|
||||
using Verse;
|
||||
using HarmonyLib;
|
||||
|
||||
namespace Rimworld_Animations_Patch
|
||||
{
|
||||
[HarmonyPatch(typeof(ThoughtWorker_Precept_GroinChestHairOrFaceUncovered), "HasUncoveredGroinChestHairOrFace")]
|
||||
public static class HarmonyPatch_ThoughtWorker_Precept_GroinChestHairOrFaceUncovered
|
||||
{
|
||||
public static void Postfix(ref bool __result, Pawn p)
|
||||
{
|
||||
if (__result == false) return;
|
||||
|
||||
Pawn pawn = p;
|
||||
if (ApparelSettings.underwearSufficentForIdeos == false) return;
|
||||
|
||||
if (pawn?.apparel == null)
|
||||
{ __result = false; return; }
|
||||
|
||||
if (pawn.apparel.WornApparel.NullOrEmpty())
|
||||
{ __result = true; return; }
|
||||
|
||||
bool fullHeadCovered = pawn.apparel.WornApparel.Any(x => x.def.apparel.bodyPartGroups.Contains(BodyPartGroupDefOf.FullHead));
|
||||
bool groinCovered = pawn.apparel.WornApparel.Any(x => x.def.apparel.bodyPartGroups.Contains(BodyPartGroupDefOf.Legs) || x.def.apparel.bodyPartGroups.Contains(PatchBodyPartGroupDefOf.GenitalsBPG));
|
||||
bool chestCovered = pawn.apparel.WornApparel.Any(x => x.def.apparel.bodyPartGroups.Contains(BodyPartGroupDefOf.Torso) || x.def.apparel.bodyPartGroups.Contains(PatchBodyPartGroupDefOf.ChestBPG));
|
||||
bool faceCovered = fullHeadCovered || pawn.apparel.WornApparel.Any(x => x.def.apparel.bodyPartGroups.Contains(BodyPartGroupDefOf.Eyes));
|
||||
bool hairCovered = fullHeadCovered || pawn.apparel.WornApparel.Any(x => x.def.apparel.bodyPartGroups.Contains(BodyPartGroupDefOf.UpperHead));
|
||||
|
||||
__result = !(groinCovered && chestCovered && faceCovered && hairCovered);
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(ThoughtWorker_Precept_GroinChestOrHairUncovered), "HasUncoveredGroinChestOrHair")]
|
||||
public static class HarmonyPatch_ThoughtWorker_Precept_GroinChestOrHairUncovered
|
||||
{
|
||||
public static void Postfix(ref bool __result, Pawn p)
|
||||
{
|
||||
if (__result == false) return;
|
||||
|
||||
Pawn pawn = p;
|
||||
if (ApparelSettings.underwearSufficentForIdeos == false) return;
|
||||
|
||||
if (pawn?.apparel == null)
|
||||
{ __result = false; return; }
|
||||
|
||||
if (pawn.apparel.WornApparel.NullOrEmpty())
|
||||
{ __result = true; return; }
|
||||
|
||||
bool fullHeadCovered = pawn.apparel.WornApparel.Any(x => x.def.apparel.bodyPartGroups.Contains(BodyPartGroupDefOf.FullHead));
|
||||
bool groinCovered = pawn.apparel.WornApparel.Any(x => x.def.apparel.bodyPartGroups.Contains(BodyPartGroupDefOf.Legs) || x.def.apparel.bodyPartGroups.Contains(PatchBodyPartGroupDefOf.GenitalsBPG));
|
||||
bool chestCovered = pawn.apparel.WornApparel.Any(x => x.def.apparel.bodyPartGroups.Contains(BodyPartGroupDefOf.Torso) || x.def.apparel.bodyPartGroups.Contains(PatchBodyPartGroupDefOf.ChestBPG));
|
||||
bool hairCovered = fullHeadCovered || pawn.apparel.WornApparel.Any(x => x.def.apparel.bodyPartGroups.Contains(BodyPartGroupDefOf.UpperHead));
|
||||
|
||||
__result = !(groinCovered && chestCovered && hairCovered);
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(ThoughtWorker_Precept_GroinOrChestUncovered), "HasUncoveredGroinOrChest")]
|
||||
public static class HarmonyPatch_ThoughtWorker_Precept_HasUncoveredGroinOrChest
|
||||
{
|
||||
public static void Postfix(ref bool __result, Pawn p)
|
||||
{
|
||||
if (__result == false) return;
|
||||
|
||||
Pawn pawn = p;
|
||||
if (ApparelSettings.underwearSufficentForIdeos == false) return;
|
||||
|
||||
if (pawn?.apparel == null)
|
||||
{ __result = false; return; }
|
||||
|
||||
if (pawn.apparel.WornApparel.NullOrEmpty())
|
||||
{ __result = true; return; }
|
||||
|
||||
bool groinCovered = pawn.apparel.WornApparel.Any(x => x.def.apparel.bodyPartGroups.Contains(BodyPartGroupDefOf.Legs) || x.def.apparel.bodyPartGroups.Contains(PatchBodyPartGroupDefOf.GenitalsBPG));
|
||||
bool chestCovered = pawn.apparel.WornApparel.Any(x => x.def.apparel.bodyPartGroups.Contains(BodyPartGroupDefOf.Torso) || x.def.apparel.bodyPartGroups.Contains(PatchBodyPartGroupDefOf.ChestBPG));
|
||||
|
||||
__result = !(groinCovered && chestCovered);
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(ThoughtWorker_Precept_GroinUncovered), "HasUncoveredGroin")]
|
||||
public static class HarmonyPatch_ThoughtWorker_Precept_GroinUncovered
|
||||
{
|
||||
public static void Postfix(ref bool __result, Pawn p)
|
||||
{
|
||||
if (__result == false) return;
|
||||
|
||||
Pawn pawn = p;
|
||||
if (ApparelSettings.underwearSufficentForIdeos == false) return;
|
||||
|
||||
if (pawn?.apparel == null)
|
||||
{ __result = false; return; }
|
||||
|
||||
if (pawn.apparel.WornApparel.NullOrEmpty())
|
||||
{ __result = true; return; }
|
||||
|
||||
bool groinCovered = pawn.apparel.WornApparel.Any(x => x.def.apparel.bodyPartGroups.Contains(BodyPartGroupDefOf.Legs) || x.def.apparel.bodyPartGroups.Contains(PatchBodyPartGroupDefOf.GenitalsBPG));
|
||||
|
||||
__result = !groinCovered;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue