public PawnBodyGraphic(CompBodyAnimator compAni) { this.CompAni = compAni; this._pawn = compAni.Pawn; this.Initialize(); }
public static void DoAttackAnimationOffsetsWeapons(Pawn pawn, ref float weaponAngle, ref Vector3 weaponPosition, bool flipped, CompBodyAnimator animator, out bool noTween) { CompEquippable primaryEq = pawn.equipment?.PrimaryEq; noTween = false; // DamageDef damageDef = primaryEq?.PrimaryVerb?.verbProps?.meleeDamageDef; if (primaryEq?.parent?.def == null) { return; } Stance_Busy busy = pawn.stances.curStance as Stance_Busy; if (busy == null) { return; } if (busy.verb == null || !busy.verb.IsMeleeAttack) { return; } DamageDef damageDef = busy.verb.GetDamageDef(); //ThingUtility.PrimaryMeleeWeaponDamageType(primaryEq.parent.def); if (damageDef == null) { return; } // total weapon angle change during animation sequence int totalSwingAngle = 0; Vector3 currentOffset = animator.Jitterer.CurrentOffset; float jitterMax = animator.JitterMax; float magnitude = currentOffset.magnitude; float animationPhasePercent = magnitude / jitterMax; if (damageDef == DamageDefOf.Stab) { weaponPosition += currentOffset; // + new Vector3(0, 0, Mathf.Pow(this.CompFace.Jitterer.CurrentOffset.magnitude, 0.25f))/2; } else if (damageDef == DamageDefOf.Blunt || damageDef == DamageDefOf.Cut) { totalSwingAngle = 120; weaponPosition += currentOffset + new Vector3(0, 0, Mathf.Sin(magnitude * Mathf.PI / jitterMax) / 10); weaponAngle += flipped ? -animationPhasePercent * totalSwingAngle : animationPhasePercent * totalSwingAngle; noTween = true; } }
private static void RecalcRootLocY(ref Vector3 rootLoc, Pawn pawn, CompBodyAnimator compAnimator) { Vector3 loc = rootLoc; CellRect viewRect = Find.CameraDriver.CurrentViewRect; viewRect = viewRect.ExpandedBy(1); List <Pawn> pawns = new List <Pawn>(); foreach (Pawn otherPawn in pawn.Map.mapPawns.AllPawnsSpawned) { if (!viewRect.Contains(otherPawn.Position)) { continue; } if (otherPawn == pawn) { continue; } if (otherPawn.DrawPos.x < loc.x - 0.5f) { continue; } if (otherPawn.DrawPos.x > loc.x + 0.5f) { continue; } if (otherPawn.DrawPos.z >= loc.z) { continue; } // ignore above pawns.Add(otherPawn); } // pawns = pawn.Map.mapPawns.AllPawnsSpawned // .Where( // otherPawn => _viewRect.Contains(otherPawn.Position) && // otherPawn != pawn && // otherPawn.DrawPos.x >= loc.x - 1 && // otherPawn.DrawPos.x <= loc.x + 1 && // otherPawn.DrawPos.z <= loc.z).ToList(); // List<Pawn> leftOfPawn = pawns.Where(other => other.DrawPos.x <= loc.x).ToList(); bool flag = compAnimator != null; if (!pawns.NullOrEmpty()) { float pawnOffset = YOffsetPawns * pawns.Count; loc.y -= pawnOffset; if (flag) { compAnimator.DrawOffsetY = pawnOffset; } // loc.y -= 0.1f * leftOfPawn.Count; } else { if (flag) { compAnimator.DrawOffsetY = 0f; } } rootLoc = loc; }
public static bool Prefix(PawnRenderer __instance, ref Vector3 rootLoc, float angle, bool renderBody, Rot4 bodyFacing, Rot4 headFacing, RotDrawMode bodyDrawType, bool portrait, bool headStump) { // Pawn pawn = (Pawn)PawnFieldInfo?.GetValue(__instance); PawnGraphicSet graphics = __instance.graphics; Pawn pawn = graphics.pawn; if (!pawn.RaceProps.Humanlike && !Controller.settings.UsePaws) { return(true); } if (!graphics.AllResolved) { graphics.ResolveAllGraphics(); } CompFace compFace = pawn.GetCompFace(); bool hasFace = compFace != null; // Let vanilla do the job if no FacePawn or pawn not a teenager or any other known mod accessing the renderer if (hasFace) { if (compFace.IsChild || compFace.Deactivated) { return(true); } } CompBodyAnimator compAnim = pawn.GetCompAnim(); bool showFeet = compAnim != null && Controller.settings.UseFeet; // No face, no animator, return if (!hasFace && compAnim == null) { return(true); } PawnWoundDrawer woundDrawer = (PawnWoundDrawer)WoundOverlayFieldInfo?.GetValue(__instance); // if (Patches2.Plants) // { // if (pawn.Spawned) // { // Plant plant = (pawn.Position + IntVec3.South).GetPlant(pawn.Map); // if (plant != null && Patches2.plantMoved.Contains(plant)) // { // rootLoc.y = plant.DrawPos.y - (Patches2.steps / 2); // } // } // } // Try to move the y position behind while another pawn is standing near if (compAnim != null && (!portrait && pawn.Spawned && !compAnim.IsRider)) { RecalcRootLocY(ref rootLoc, pawn, compAnim); } Vector3 baseDrawLoc = rootLoc; // Let's save the basic location for later Vector3 footPos = baseDrawLoc; // No face => must be animal, simplify it Quaternion quat = Quaternion.AngleAxis(angle, Vector3.up); Quaternion bodyQuat = quat; Quaternion footQuat = bodyQuat; if (MainTabWindow_WalkAnimator.IsOpen) { bodyFacing = MainTabWindow_BaseAnimator.BodyRot; headFacing = MainTabWindow_BaseAnimator.HeadRot; } compFace?.TickDrawers(bodyFacing, headFacing, graphics); compAnim?.TickDrawers(bodyFacing, graphics); // Use the basic quat Quaternion headQuat = bodyQuat; // Rotate head if possible and wobble around if (!portrait || MainTabWindow_WalkAnimator.IsOpen) { if (showFeet) { compAnim.ApplyBodyWobble(ref baseDrawLoc, ref footPos, ref bodyQuat); } // Reset the quat as it has been changed headQuat = bodyQuat; compFace?.ApplyHeadRotation(renderBody, ref headQuat); } // Regular FacePawn rendering 14+ years // Render body // if (renderBody) compAnim?.DrawBody(baseDrawLoc, bodyQuat, bodyDrawType, woundDrawer, renderBody, portrait); Vector3 bodyPos = baseDrawLoc; Vector3 headPos = baseDrawLoc; if (bodyFacing == Rot4.North) { headPos.y += YOffset_Shell; bodyPos.y += YOffset_Head; } else { headPos.y += YOffset_Head; bodyPos.y += YOffset_Shell; } if (graphics.headGraphic != null) { // Rendererd pawn faces Vector3 offsetAt = !hasFace ? __instance.BaseHeadOffsetAt(bodyFacing) : compFace.BaseHeadOffsetAt(portrait); Vector3 b = bodyQuat * offsetAt; Vector3 headDrawLoc = headPos + b; if (!hasFace) { Material material = graphics.HeadMatAt(headFacing, bodyDrawType, headStump); if (material != null) { Mesh mesh2 = MeshPool.humanlikeHeadSet.MeshAt(headFacing); GenDraw.DrawMeshNowOrLater(mesh2, headDrawLoc, quat, material, portrait); } } else { compFace.DrawBasicHead(out bool headDrawn, bodyDrawType, portrait, headStump, headDrawLoc, headQuat); if (headDrawn) { if (bodyDrawType != RotDrawMode.Dessicated && !headStump) { if (compFace.Props.hasWrinkles) { Vector3 wrinkleLoc = headDrawLoc; wrinkleLoc.y += YOffset_Wrinkles; compFace.DrawWrinkles(bodyDrawType, wrinkleLoc, headQuat, portrait); } if (compFace.Props.hasEyes) { Vector3 eyeLoc = headDrawLoc; eyeLoc.y += YOffset_Eyes; compFace.DrawNaturalEyes(eyeLoc, portrait, headQuat); Vector3 browLoc = headDrawLoc; browLoc.y += YOffset_Brows; // the brow above compFace.DrawBrows(browLoc, headQuat, portrait); // and now the added eye parts Vector3 unnaturalEyeLoc = headDrawLoc; unnaturalEyeLoc.y += YOffset_UnnaturalEyes; compFace.DrawUnnaturalEyeParts(unnaturalEyeLoc, headQuat, portrait); } // Portrait obviously ignores the y offset, thus render the beard after the body apparel (again) if (compFace.Props.hasBeard) { Vector3 beardLoc = headDrawLoc; Vector3 tacheLoc = headDrawLoc; beardLoc.y += headFacing == Rot4.North ? -YOffset_Head - YOffset_Beard : YOffset_Beard; tacheLoc.y += headFacing == Rot4.North ? -YOffset_Head - YOffset_Tache : YOffset_Tache; compFace.DrawBeardAndTache(beardLoc, tacheLoc, portrait, headQuat); } if (compFace.Props.hasMouth) { Vector3 mouthLoc = headDrawLoc; mouthLoc.y += YOffset_Mouth; compFace.DrawNaturalMouth(mouthLoc, portrait, headQuat); } // Deactivated, looks kinda crappy ATM // if (pawn.Dead) // { // Material deadEyeMat = faceComp.DeadEyeMatAt(headFacing, bodyDrawType); // if (deadEyeMat != null) // { // GenDraw.DrawMeshNowOrLater(mesh2, locFacialY, headQuat, deadEyeMat, portrait); // locFacialY.y += YOffsetInterval_OnFace; // } // } // else } } } if (!headStump) { Vector3 overHead = baseDrawLoc + b; overHead.y += YOffset_OnHead; Vector3 hairLoc = overHead; Vector3 headgearLoc = overHead; Vector3 hatInFrontOfFace = baseDrawLoc + b; hairLoc.y += YOffset_HairOnHead; headgearLoc.y += YOffset_GearOnHead; hatInFrontOfFace.y += ((!(headFacing == Rot4.North)) ? YOffset_PostHead : YOffset_Behind); compFace?.DrawHairAndHeadGear(hairLoc, headgearLoc, bodyDrawType, portrait, renderBody, headQuat, hatInFrontOfFace); compFace?.DrawAlienHeadAddons(headPos, portrait, headQuat, overHead); } } if (!portrait) { // Traverse.Create(__instance).Method("DrawEquipment", rootLoc).GetValue(); DrawEquipmentMethodInfo?.Invoke(__instance, new object[] { baseDrawLoc }); } if (!portrait) { if (pawn.apparel != null) { List <Apparel> wornApparel = pawn.apparel.WornApparel; foreach (Apparel ap in wornApparel) { DrawPos_Patch.offset = baseDrawLoc; DrawPos_Patch.offsetEnabled = true; ap.DrawWornExtras(); DrawPos_Patch.offsetEnabled = false; } } Vector3 bodyLoc = baseDrawLoc; bodyLoc.y += YOffset_Status; PawnHeadOverlays headOverlays = (PawnHeadOverlays)PawnHeadOverlaysFieldInfo?.GetValue(__instance); if (headOverlays != null) { compFace?.DrawHeadOverlays(headOverlays, bodyLoc, headQuat); } } compAnim?.DrawApparel(bodyQuat, bodyPos, portrait, renderBody); compAnim?.DrawAlienBodyAddons(bodyQuat, bodyPos, portrait, renderBody, bodyFacing); if (!portrait && pawn.RaceProps.Animal && pawn.inventory != null && pawn.inventory.innerContainer.Count > 0 && graphics.packGraphic != null) { Mesh mesh = graphics.nakedGraphic.MeshAt(bodyFacing); Graphics.DrawMesh(mesh, bodyPos, quat, graphics.packGraphic.MatAt(bodyFacing), 0); } // No wobble for equipment, looks funnier - nah! // Vector3 equipPos = rootLoc; // equipPos.y = drawPos.y; //compAnim.DrawEquipment(drawPos, portrait); bool showHands = Controller.settings.UseHands; Vector3 handPos = bodyPos; if (renderBody || Controller.settings.IgnoreRenderBody) { if (showHands) { // Reset the position for the hands handPos.y = baseDrawLoc.y; compAnim?.DrawHands(bodyQuat, handPos, portrait); } if (showFeet) { compAnim.DrawFeet(bodyQuat, footQuat, footPos, portrait); } } return(false); }
public BodyAnimator(Pawn p, CompBodyAnimator compAnim) { this._compAnim = compAnim; }
public static void SetPositionsForHandsOnWeapons(Vector3 weaponPosition, bool flipped, float weaponAngle, [CanBeNull] CompProperties_WeaponExtensions compWeaponExtensions, CompBodyAnimator animator, float sizeMod) { // Prepare everything for DrawHands, but don't draw if (compWeaponExtensions == null) { return; } animator.FirstHandPosition = compWeaponExtensions.RightHandPosition; animator.SecondHandPosition = compWeaponExtensions.LeftHandPosition; // Only put the second hand on when aiming or not moving => free left hand for running // bool leftOnWeapon = true;// aiming || !animator.IsMoving; if (animator.FirstHandPosition != Vector3.zero) { float x = animator.FirstHandPosition.x; float y = animator.FirstHandPosition.y; float z = animator.FirstHandPosition.z; if (flipped) { x *= -1f; y *= -1f; } //if (pawn.Rotation == Rot4.North) //{ // y *= -1f; //} x *= sizeMod; z *= sizeMod; animator.FirstHandPosition = weaponPosition + new Vector3(x, y, z).RotatedBy(weaponAngle); } if (animator.HasLeftHandPosition) { float x2 = animator.SecondHandPosition.x; float y2 = animator.SecondHandPosition.y; float z2 = animator.SecondHandPosition.z; if (flipped) { x2 *= -1f; y2 *= -1f; } x2 *= sizeMod; z2 *= sizeMod; //if (pawn.Rotation == Rot4.North) //{ // y2 *= -1f; //} animator.SecondHandPosition = weaponPosition + new Vector3(x2, y2, z2).RotatedBy(weaponAngle); } // Swap left and right hand position when flipped animator.WeaponQuat = Quaternion.AngleAxis(weaponAngle, Vector3.up); }