static AlienPartGenerator.BodyAddon CloneAddon([NotNull] AlienPartGenerator.BodyAddon addon) { var pType = typeof(AlienPartGenerator.BodyAddon); var shaderField = pType.GetField("shaderType", BindingFlags.Instance | BindingFlags.NonPublic); var prioritizationField = pType.GetField("prioritization", BindingFlags.Instance | BindingFlags.NonPublic); var colorChannelField = pType.GetField("colorChannel", BindingFlags.Instance | BindingFlags.NonPublic); var copy = new AlienPartGenerator.BodyAddon() { angle = addon.angle, backstoryGraphics = addon.backstoryGraphics.MakeSafe().ToList(), backstoryRequirement = addon.backstoryRequirement, bodyPart = addon.bodyPart, debug = addon.debug, drawForFemale = addon.drawForFemale, drawForMale = addon.drawForMale, drawnInBed = addon.drawnInBed, drawnOnGround = addon.drawnOnGround, drawSize = addon.drawSize, hiddenUnderApparelFor = addon.hiddenUnderApparelFor.MakeSafe().ToList(), path = addon.path, offsets = addon.offsets, linkVariantIndexWithPrevious = addon.linkVariantIndexWithPrevious, inFrontOfBody = addon.inFrontOfBody, layerInvert = addon.layerInvert, variantCount = addon.variantCount, hediffGraphics = addon.hediffGraphics.MakeSafe().ToList(), layerOffset = addon.layerOffset, hiddenUnderApparelTag = addon.hiddenUnderApparelTag, }; shaderField.SetValue(copy, addon.ShaderType); prioritizationField.SetValue(copy, addon.Prioritization.ToList()); colorChannelField.SetValue(copy, addon.ColorChannel); return(copy); }
/// <summary> /// Checks a body addon if it should be drawn. This checks if the pawn is: /// - Dead /// - In a lit room /// - Asleep /// - Severely incompacitated. /// </summary> /// <param name="__result">If we should draw this addon.</param> /// <param name="pawn">The pawn the addon belongs to.</param> /// <returns>Returns true if we want to continue checking the addon in the regular method, false if we don't want to draw this addon.</returns> private static bool CuteboldCanDrawAddonPrefix(Pawn pawn, ref bool __result, AlienPartGenerator.BodyAddon __instance) { if (pawn.def.defName != Cutebold_Assemblies.RaceName || (__instance.bodyPart != "left eye" && __instance.bodyPart != "right eye")) { return(true); } __result = true; if (pawn.Dead || ((pawn.ParentHolder as Map) != null ? pawn.Map.glowGrid.GameGlowAt(pawn.Position) : (pawn.CarriedBy != null ? pawn.CarriedBy.Map.glowGrid.GameGlowAt(pawn.CarriedBy.Position) : 0.5f)) >= 0.3f || (pawn.CurJob != null && pawn.jobs.curDriver.asleep) || pawn.health.capacities.GetLevel(PawnCapacityDefOf.Sight) == 0f || pawn.health.capacities.GetLevel(PawnCapacityDefOf.Consciousness) <= 0.1f) { __result = false; } else if (eyeBlink) { // Blink Fucntion; somewhat regular blinking, but not exactly even nor completely random. var offsetTicks = Math.Abs(pawn.HashOffsetTicks()); if (Math.Abs((offsetTicks % 182) / 1.8 - Math.Abs(80 * Math.Sin(offsetTicks / 89))) < 1) { __result = false; } } return(__result); }
private static List <AlienPartGenerator.BodyAddon> GenerateBodyAddons(List <AlienPartGenerator.BodyAddon> human, MorphDef morph) { List <AlienPartGenerator.BodyAddon> returnList = new List <AlienPartGenerator.BodyAddon>(); #if TEST_BODY_SIZE var bodySizes = GetDebugBodySizes(morph); Vector2?bodySize = bodySizes?.body; Vector2?headSize = bodySizes?.head; if (bodySizes != null) { Log.Message($"{morph.defName} draw sizes are: bodySize={bodySizes.Value.body}, headSize={bodySizes.Value.head}"); } #else Vector2?bodySize = morph?.raceSettings?.graphicsSettings?.customDrawSize; Vector2?headSize = morph?.raceSettings?.graphicsSettings?.customHeadDrawSize; #endif List <string> headParts = new List <string>(); headParts.Add("Jaw"); headParts.Add("Ear"); headParts.Add("left ear"); headParts.Add("right ear"); headParts.Add("Skull"); List <string> bodyParts = new List <string>(); bodyParts.Add("Arm"); bodyParts.Add("Tail"); bodyParts.Add("Waist"); foreach (AlienPartGenerator.BodyAddon addon in human) { AlienPartGenerator.BodyAddon temp = new AlienPartGenerator.BodyAddon() { path = addon.path, bodyPart = addon.bodyPart, offsets = GenerateBodyAddonOffsets(addon.offsets, morph), linkVariantIndexWithPrevious = addon.linkVariantIndexWithPrevious, angle = addon.angle, inFrontOfBody = addon.inFrontOfBody, layerOffset = addon.layerOffset, layerInvert = addon.layerInvert, drawnOnGround = addon.drawnOnGround, drawnInBed = addon.drawnInBed, drawForMale = addon.drawForMale, drawForFemale = addon.drawForFemale, drawSize = addon.drawSize, variantCount = addon.variantCount, hediffGraphics = addon.hediffGraphics, backstoryGraphics = addon.backstoryGraphics, hiddenUnderApparelFor = addon.hiddenUnderApparelFor, hiddenUnderApparelTag = addon.hiddenUnderApparelTag, backstoryRequirement = addon.backstoryRequirement }; if (headParts.Contains(temp.bodyPart)) { if (headSize != null) { temp.drawSize = headSize.GetValueOrDefault(); } if (bodySize != null) { if (temp?.offsets?.south?.bodyTypes != null) { foreach (AlienPartGenerator.BodyTypeOffset bodyType in temp.offsets.south.bodyTypes) { bodyType.offset.y += 0.34f * (bodySize.GetValueOrDefault().y - 1f); } } if (temp?.offsets?.north?.bodyTypes != null) { foreach (AlienPartGenerator.BodyTypeOffset bodyType in temp.offsets.north.bodyTypes) { bodyType.offset.y += 0.34f * (bodySize.GetValueOrDefault().y - 1f); } } if (temp?.offsets?.east?.bodyTypes != null) { foreach (AlienPartGenerator.BodyTypeOffset bodyType in temp.offsets.east.bodyTypes) { bodyType.offset.y += 0.34f * (bodySize.GetValueOrDefault().y - 1f); } } if (temp?.offsets?.west?.bodyTypes != null) { foreach (AlienPartGenerator.BodyTypeOffset bodyType in temp.offsets.west.bodyTypes) { bodyType.offset.y += 0.34f * (bodySize.GetValueOrDefault().y - 1f); } } } } if (bodySize != null && bodyParts.Contains(temp.bodyPart)) { temp.drawSize = bodySize.GetValueOrDefault(); } returnList.Add(temp); } return(returnList); }
//public static bool DrawAddons_Prefix(bool portrait, Pawn pawn, Vector3 vector, Quaternion quat, Rot4 rotation) //{ // if (pawn.ageTracker.CurLifeStageIndex < AgeStage.Child) // { return false; } // return true; //} public static bool DrawAddons_Prefix(bool portrait, Pawn pawn, Vector3 vector, Quaternion quat, Rot4 rotation) { if (!(pawn.def is ThingDef_AlienRace alienProps)) { return(false); } // don't make addon for baby & toddler if (pawn.ageTracker.CurLifeStageIndex < AgeStage.Child) { return(false); } List <AlienPartGenerator.BodyAddon> addons = alienProps.alienRace.generalSettings.alienPartGenerator.bodyAddons; AlienPartGenerator.AlienComp alienComp = pawn.GetComp <AlienPartGenerator.AlienComp>(); for (int i = 0; i < addons.Count; i++) { AlienPartGenerator.BodyAddon ba = addons[index : i]; if (!ba.CanDrawAddon(pawn: pawn)) { continue; } AlienPartGenerator.RotationOffset offset = rotation == Rot4.South ? ba.offsets.south : rotation == Rot4.North ? ba.offsets.north : rotation == Rot4.East ? ba.offsets.east : ba.offsets.west; Vector2 bodyOffset = (portrait ? offset?.portraitBodyTypes ?? offset?.bodyTypes : offset?.bodyTypes)?.FirstOrDefault(predicate: to => to.bodyType == pawn.story.bodyType) ?.offset ?? Vector2.zero; Vector2 crownOffset = (portrait ? offset?.portraitCrownTypes ?? offset?.crownTypes : offset?.crownTypes)?.FirstOrDefault(predicate: to => to.crownType == alienComp.crownType) ?.offset ?? Vector2.zero; //Defaults for tails //south 0.42f, -0.3f, -0.22f //north 0f, 0.3f, -0.55f //east -0.42f, -0.3f, -0.22f float moffsetX = 0.42f; float moffsetZ = -0.22f; float moffsetY = ba.inFrontOfBody ? 0.3f + ba.layerOffset : -0.3f - ba.layerOffset; float num = ba.angle; if (rotation == Rot4.North) { moffsetX = 0f; moffsetY = !ba.inFrontOfBody ? -0.3f - ba.layerOffset : 0.3f + ba.layerOffset; moffsetZ = -0.55f; num = 0; } moffsetX += bodyOffset.x + crownOffset.x; moffsetZ += bodyOffset.y + crownOffset.y; if (rotation == Rot4.East) { moffsetX = -moffsetX; num = -num; //Angle } Vector3 offsetVector = new Vector3(x: moffsetX, y: moffsetY, z: moffsetZ); Material dmat = alienComp.addonGraphics[index : i].MatAt(rot : rotation); Vector3 rootloc = vector; // adjust tail scale if (pawn.ageTracker.CurLifeStageIndex == AgeStage.Child && !ba.inFrontOfBody) { const float TextureScaleX = 1.225f; const float TextureScaleY = 1.225f; const float TextureOffsetX = -0.09f; const float TextureOffsetY = 0f; const float dVectorOffsetX = 0.16f; const float dVectorOffsetY = 0f; const float dVectorOffsetZ = 0.32f; Material xmat = new Material(dmat); //float TextureScaleX = CnP_Settings.option_debug_scale_X; //float TextureScaleY = CnP_Settings.option_debug_scale_Y; //float TextureOffsetX = CnP_Settings.option_debug_offset_X; //float TextureOffsetY = CnP_Settings.option_debug_offset_Y; //float dVectorOffsetX = 0.16f; // CnP_Settings.option_debug_loc_X; //float dVectorOffsetY = 0f; // CnP_Settings.option_debug_loc_Y; //float dVectorOffsetZ = 0.32f; // CnP_Settings.option_debug_loc_Z; if (rotation == Rot4.East) { offsetVector.x += dVectorOffsetX; } if (rotation == Rot4.West) { offsetVector.x -= dVectorOffsetX; } offsetVector.y += dVectorOffsetY; offsetVector.z += dVectorOffsetZ; xmat.mainTextureScale = new Vector2(TextureScaleX, TextureScaleY); xmat.mainTextureOffset = new Vector2(TextureOffsetX, TextureOffsetY); dmat = xmat; } ////////////////////////////////////////////////////////////////////////////////////////////////// GenDraw.DrawMeshNowOrLater(mesh: alienComp.addonGraphics[index: i].MeshAt(rot: rotation), loc: rootloc + offsetVector.RotatedBy(angle: Mathf.Acos(f: Quaternion.Dot(a: Quaternion.identity, b: quat)) * 2f * 57.29578f), quat: Quaternion.AngleAxis(angle: num, axis: Vector3.up) * quat, mat: dmat, drawNow: portrait); } return(false); }