public void ApplyCollarEffects( Pawn pawn, Apparel collar ) { if( originalFaction == null ) { if( pawn.Faction == Faction.OfPlayer ) { originalFaction = Find.FactionManager.FirstFactionOfDef( FactionDefOf.Spacer ); } else { originalFaction = pawn.Faction; } } if( originalPawnKind == null ) { originalPawnKind = pawn.kindDef; } pawn.kindDef = Data.PawnKindDefOf.Slave; if( ( pawn.story != null )&& ( pawn.story.traits != null )&& ( !pawn.story.traits.HasTrait( Data.TraitDefOf.Enslaved ) ) ) { pawn.story.traits.GainTrait( new Trait( Data.TraitDefOf.Enslaved ) ); } }
public Dialog_PawnApparelComparer(Pawn pawn, Apparel apparel) { this.doCloseX = true; this.closeOnEscapeKey = true; this.doCloseButton = true; this.pawn = pawn; this.apparel = apparel; }
public void ApplyApparelEffects( Pawn pawn, Apparel apparel ) { if( ( pawn.outfits != null )&& ( pawn.outfits.forcedHandler != null ) ) { pawn.outfits.forcedHandler.SetForced( apparel, true ); } pawn.Drawer.renderer.graphics.ResolveApparelGraphics(); if( apparel.IsSlaveCollar() ) { ApplyCollarEffects( pawn, apparel ); } if( apparel.IsRestraints() ) { ApplyRestraintsEffects( pawn, apparel ); } }
public static float ApparelScoreGain( Pawn pawn, Apparel ap ) { // only allow shields to be considered if a primary weapon is equipped and is melee if ( ap.def == ThingDefOf.Apparel_PersonalShield && pawn.equipment.Primary != null && !pawn.equipment.Primary.def.Verbs[0].MeleeRange ) { return - 1000f; } // get the score of the considered apparel float candidateScore = ApparelScoreRaw( ap, pawn ); // get the current list of worn apparel List<Apparel> wornApparel = pawn.apparel.WornApparel; // check if the candidate will replace existing gear bool willReplace = false; for ( int i = 0; i < wornApparel.Count; i++ ) { if ( !ApparelUtility.CanWearTogether( wornApparel[i].def, ap.def ) ) { // can't drop forced gear if ( !pawn.outfits.forcedHandler.AllowedToAutomaticallyDrop( wornApparel[i] ) ) { return - 1000f; } // if replaces, score is difference of the two pieces of gear candidateScore -= ApparelScoreRaw( wornApparel[i], pawn ); willReplace = true; } } // increase score if this piece can be worn without replacing existing gear. if ( !willReplace ) { candidateScore *= 10f; } return candidateScore; }
internal bool _TryDrop( Apparel ap, out Apparel resultingAp, IntVec3 pos, bool forbid = true ) { resultingAp = (Apparel) null; var wornApparel = this.wornApparel(); if( !wornApparel.Contains( ap ) ) { Verse.Log.Warning( this.pawn.LabelCap + " tried to drop apparel he didn't have: " + ap.LabelCap ); return false; } var compLock = ap.TryGetComp<CompLockable>(); if( compLock != null ) { if( ( !ap.wearer.health.Dead )&& ( compLock.Locked ) ) { // Can only take off slave collars of the dead Verse.Log.Message( string.Format( "{0} tried to remove apparel {1} with CompLockable which is locked but they aren't dead.", this.pawn.LabelShort, ap.Label ) ); return false; } } wornApparel.Remove( ap ); ap.wearer = (Pawn) null; Thing resultingThing = (Thing) null; bool flag = GenThing.TryDropAndSetForbidden( (Thing) ap, pos, ThingPlaceMode.Near, out resultingThing, forbid ); resultingAp = resultingThing as Apparel; ApparelChanged(); if( ( flag )&& ( this.pawn.outfits != null ) ) { this.pawn.outfits.forcedHandler.SetForced( ap, false ); } return flag; }
public static bool has_lock(this Apparel app) { return(app.TryGetComp <CompHoloCryptoStamped>() != null); }
private static void DoConflict(Apparel apprel, PawnCalcForApparel x, PawnCalcForApparel y, ref float? xPercentual) { if (!xPercentual.HasValue) { if (x.totalStats == null) x.totalStats = x.CalculateTotalStats(null); float xNoStats = x.CalculateTotalStats(apprel); xPercentual = x.totalStats / xNoStats; if (x.saveablePawn.pawn.apparel.WornApparel.Contains(apprel)) xPercentual *= 1.1f; } if (y.totalStats == null) y.totalStats = y.CalculateTotalStats(null); float yNoStats = y.CalculateTotalStats(apprel); float yPercentual = y.totalStats.Value / yNoStats; if (y.saveablePawn.pawn.apparel.WornApparel.Contains(apprel)) yPercentual *= 1.1f; if (xPercentual.Value > yPercentual) { #if LOG && CONFLICT MapComponent_AutoEquip.logMessage.AppendLine("Conflict: " + apprel.LabelCap + " Winner: " + x.pawn.LabelCap + " Looser: " + y.pawn.LabelCap); #endif y.LooseConflict(apprel); } else { #if LOG && CONFLICT MapComponent_AutoEquip.logMessage.AppendLine("Conflict: " + apprel.LabelCap + " Winner: " + y.pawn.LabelCap + " Looser: " + x.pawn.LabelCap); #endif x.LooseConflict(apprel); } }
private float CalculateTotalStats(Apparel ignore) { float num = 1.0f; foreach (Saveable_StatDef stat in this.stats) { float nint = stat.statDef.defaultBaseValue; foreach (Apparel a in this.calculedApparelItems) { if (a == ignore) continue; nint += a.def.equippedStatOffsets.GetStatOffsetFromList(stat.statDef); } foreach (Apparel a in this.calculedApparelItems) { if (a == ignore) continue; PawnCalcForApparel.DoApparelScoreRawStatsHandlers(this.pawn, a, stat.statDef, ref nint); } num += nint * stat.strength; } if (num == 0) Log.Warning("No Stat to optimize apparel"); return num; }
public static void DrawAddons(ref PawnRenderFlags flags, Vector3 vector, Pawn pawn, Quaternion quat, Rot4 bodyFacing, Mesh mesh, Rot4 headfacing, bool renderBody) { if (!pawn.RaceProps.Humanlike || PawnRenderFlagsExtension.FlagSet(flags, (PawnRenderFlags)4)) { return; } /* * // Log.Message(string.Concat(new string[] * { * "DRAWING EXTRAS FOR: " + pawn.NameFullColored + " | " + flags.ToString() + " | ", * (!pawn.RaceProps.Humanlike || PawnRenderFlagsExtension.FlagSet(flags, (PawnRenderFlags)4)).ToString(), * " | ", * PawnRenderFlagsExtension.FlagSet(flags, (PawnRenderFlags)4).ToString(), * " | ", * (!pawn.RaceProps.Humanlike).ToString() * })); */ // Log.Message("DrawAddons "+ flags.ToString()); if (flags.FlagSet(PawnRenderFlags.Invisible)) { // Log.Message("PawnRenderFlags.Invisible"); return; } bool portrait = flags.FlagSet(PawnRenderFlags.Portrait); Vector2 defaultSize = mesh?.bounds.size ?? (portrait ? MeshPool.humanlikeBodySet.MeshAt(bodyFacing).bounds.size : pawn.Drawer.renderer.graphics.nakedGraphic.MeshAt(bodyFacing).bounds.size); Vector2 size = mesh?.bounds.size ?? (portrait ? MeshPool.humanlikeBodySet.MeshAt(bodyFacing).bounds.size : pawn.Drawer.renderer.graphics.nakedGraphic.MeshAt(bodyFacing).bounds.size); if (pawn.RaceProps.Humanlike) { if (pawn.apparel != null && pawn.apparel.WornApparelCount > 0) { // Log.Message("DrawAddons for "+ pawn.apparel.WornApparelCount+" apparel"); if (AdeptusIntergrationUtility.enabled_AlienRaces) { PawnRenderUtility.AlienRacesPatch(pawn, bodyFacing, out size, portrait); } else { size = new Vector2(1.5f, 1.5f); } List <Apparel> worn = pawn.apparel.WornApparel; for (int wa = 0; wa < worn.Count; wa++) { Apparel apparel = worn[wa]; if (apparel is ApparelComposite composite) { // Log.Message("composite"); if (!composite.Pauldrons.NullOrEmpty() && AMAMod.settings.AllowPauldronDrawer) { for (int i = 0; i < composite.Pauldrons.Count; i++) { CompPauldronDrawer Pauldron = composite.Pauldrons[i] as CompPauldronDrawer; if (Pauldron != null) { Vector3 center = vector + (quat * Pauldron.GetOffsetFor(bodyFacing, false)); if (Pauldron.activeEntries.NullOrEmpty()) { Pauldron.Initialize(); } foreach (ShoulderPadEntry entry in Pauldron.activeEntries) { // entry.Drawer = Pauldron; if (entry.apparel == null) { entry.apparel = apparel; } if (entry.Drawer == null) { Log.Warning("Warning! Drawer null"); } /* * if (entry.ForceDynamicDraw) * { * continue; * } */ if (entry.ShouldDrawEntry(flags, bodyFacing, size, renderBody, out Graphic pauldronMat, out Mesh pauldronMesh, out Vector3 offset)) { if (Pauldron.onHead || renderBody) { GenDraw.DrawMeshNowOrLater ( // pauldronMesh, PawnRenderUtility.GetPawnMesh(portrait, pawn, entry.Props.flipWest && bodyFacing == Rot4.West ? bodyFacing.Opposite : bodyFacing, !Pauldron.onHead), center + (quat * offset), quat, PawnRenderUtility.OverrideMaterialIfNeeded(pauldronMat.MatAt(bodyFacing), pawn), flags.FlagSet(PawnRenderFlags.DrawNow) ); } } } } } } if (!composite.Extras.NullOrEmpty() && AMAMod.settings.AllowExtraPartDrawer) { for (int i = 0; i < composite.Extras.Count; i++) { CompApparelExtraPartDrawer ExtraDrawer = composite.Extras[i]; if (ExtraDrawer != null) { if (ExtraDrawer.hidesHead) { flags |= PawnRenderFlags.HeadStump; } Vector3 drawAt = vector; if (!ExtraDrawer.Props.ExtrasEntries.NullOrEmpty()) { bool onHead = ExtraDrawer.onHead || ExtraDrawer.ExtraPartEntry.OnHead || ExtraDrawer.Props.onHead; Rot4 facing = onHead ? headfacing : bodyFacing; if (ExtraDrawer.ExtraPartEntry.DynamicDraw) { continue; } if (ExtraDrawer.ShouldDrawExtra(pawn, apparel, facing, out Material extraMat)) { if (onHead || renderBody) { if (onHead) { Vector3 v = vector + quat * pawn.Drawer.renderer.BaseHeadOffsetAt(headfacing); drawAt = v + quat * new Vector3(ExtraDrawer.GetOffset(bodyFacing, ExtraDrawer.ExtraPartEntry).x *size.x, ExtraDrawer.GetOffset(bodyFacing, ExtraDrawer.ExtraPartEntry).y, ExtraDrawer.GetOffset(bodyFacing, ExtraDrawer.ExtraPartEntry).z *size.y); } else { drawAt = vector + (quat * new Vector3(ExtraDrawer.GetOffset(bodyFacing, ExtraDrawer.ExtraPartEntry).x *size.x, ExtraDrawer.GetOffset(bodyFacing, ExtraDrawer.ExtraPartEntry).y, ExtraDrawer.GetOffset(bodyFacing, ExtraDrawer.ExtraPartEntry).z *size.y)); } GenDraw.DrawMeshNowOrLater ( // pauldronMesh, PawnRenderUtility.GetPawnMesh(portrait, pawn, facing, !onHead), drawAt, quat, PawnRenderUtility.OverrideMaterialIfNeeded(extraMat, pawn), flags.FlagSet(PawnRenderFlags.DrawNow) || ExtraDrawer.ExtraPartEntry.DynamicDraw ); } // vector.y += CompApparelExtaDrawer.MinClippingDistance; } } } } } } else { // Log.Message("noncomposite"); for (int i = 0; i < apparel.AllComps.Count; i++) { if (AMAMod.settings.AllowPauldronDrawer) { CompPauldronDrawer Pauldron = apparel.AllComps[i] as CompPauldronDrawer; if (Pauldron != null) { // Log.Message("Pauldron"); Vector3 center = vector + (quat * Pauldron.GetOffsetFor(bodyFacing, false)); if (Pauldron.activeEntries.NullOrEmpty()) { Pauldron.Initialize(); } foreach (ShoulderPadEntry entry in Pauldron.activeEntries) { // entry.Drawer = Pauldron; if (entry.apparel == null) { entry.apparel = apparel; } if (entry.Drawer == null) { Log.Warning("Warning! Drawer null"); } if (entry.ForceDynamicDraw) { continue; } if (entry.ShouldDrawEntry(flags, bodyFacing, size, renderBody, out Graphic pauldronMat, out Mesh pauldronMesh, out Vector3 offset)) { if (Pauldron.onHead || renderBody && pauldronMat != null) { // Log.Message("Pauldron DrawMeshNowOrLater " + !flags.FlagSet(PawnRenderFlags.Cache)); GenDraw.DrawMeshNowOrLater ( // pauldronMesh, PawnRenderUtility.GetPawnMesh(portrait, pawn, entry.Props.flipWest && bodyFacing == Rot4.West ? bodyFacing.Opposite : bodyFacing, !Pauldron.onHead), center + (quat * offset), quat, PawnRenderUtility.OverrideMaterialIfNeeded(pauldronMat.MatAt(bodyFacing), pawn), flags.FlagSet(PawnRenderFlags.DrawNow) ); } } } } } if (AMAMod.settings.AllowExtraPartDrawer) { CompApparelExtraPartDrawer ExtraDrawer = apparel.AllComps[i] as CompApparelExtraPartDrawer; if (ExtraDrawer != null) { // Log.Message("ExtraDrawer"); Vector3 drawAt = vector; if (!ExtraDrawer.Props.ExtrasEntries.NullOrEmpty()) { bool onHead = ExtraDrawer.onHead || ExtraDrawer.ExtraPartEntry.OnHead || ExtraDrawer.Props.onHead; Rot4 facing = onHead ? headfacing : bodyFacing; if (ExtraDrawer.ExtraPartEntry.DynamicDraw) { continue; } if (ExtraDrawer.ShouldDrawExtra(pawn, apparel, facing, out Material extraMat)) { if (onHead || renderBody) { if (onHead) { Vector3 v = vector + quat * pawn.Drawer.renderer.BaseHeadOffsetAt(headfacing); drawAt = v + quat * new Vector3(ExtraDrawer.GetOffset(bodyFacing, ExtraDrawer.ExtraPartEntry).x *size.x, ExtraDrawer.GetOffset(bodyFacing, ExtraDrawer.ExtraPartEntry).y, ExtraDrawer.GetOffset(bodyFacing, ExtraDrawer.ExtraPartEntry).z *size.y); } else { drawAt = vector + (quat * new Vector3(ExtraDrawer.GetOffset(bodyFacing, ExtraDrawer.ExtraPartEntry).x *size.x, ExtraDrawer.GetOffset(bodyFacing, ExtraDrawer.ExtraPartEntry).y, ExtraDrawer.GetOffset(bodyFacing, ExtraDrawer.ExtraPartEntry).z *size.y)); } // Log.Message("ExtraDrawer DrawMeshNowOrLater "+ !flags.FlagSet(PawnRenderFlags.Cache)); GenDraw.DrawMeshNowOrLater ( // pauldronMesh, PawnRenderUtility.GetPawnMesh(portrait, pawn, facing, !onHead), drawAt, quat, PawnRenderUtility.OverrideMaterialIfNeeded(extraMat, pawn), flags.FlagSet(PawnRenderFlags.DrawNow) || ExtraDrawer.ExtraPartEntry.DynamicDraw ); } // vector.y += CompApparelExtaDrawer.MinClippingDistance; } } } } } } } } } if (!pawn.Dead && AMAMod.settings.AllowHediffPartDrawer) { Vector3 drawAt = vector; for (int i = 0; i < AdeptusHediffUtility.GraphicHediffs.Count; i++) { if (pawn.health.hediffSet.GetFirstHediffOfDef(AdeptusHediffUtility.GraphicHediffs[i]) is HediffWithComps hediff) { if (hediff.TryGetCompFast <HediffComp_DrawImplant_AdMech>() is HediffComp_DrawImplant_AdMech drawer) { Material material = null; if (drawer.implantDrawProps.implantDrawerType != ImplantDrawerType.Head) { drawAt.y += 0.005f; if (bodyFacing == Rot4.South && drawer.implantDrawProps.implantDrawerType == ImplantDrawerType.Backpack) { drawAt.y -= 0.3f; } material = drawer.ImplantMaterial(pawn, bodyFacing); // GenDraw.DrawMeshNowOrLater(mesh, drawAt, quat, material, portrait); } else { if (!pawn.Downed && !pawn.Dead && drawer.implantDrawProps.useHeadOffset) { drawAt = vector + pawn.Drawer.renderer.BaseHeadOffsetAt(headfacing); } else { if ((pawn.Downed || pawn.Dead) && drawer.implantDrawProps.useHeadOffset) { drawAt.y = vector.y + pawn.Drawer.renderer.BaseHeadOffsetAt(headfacing).y; } } drawAt.y += 0.005f; material = drawer.ImplantMaterial(pawn, headfacing); // GenDraw.DrawMeshNowOrLater(mesh, drawAt, quat, material, portrait); } if (material != null) { // GenDraw.DrawMeshNowOrLater(mesh, drawAt , quat, material, portrait); material = PawnRenderUtility.OverrideMaterialIfNeeded(material, pawn); // Angle calculation to not pick the shortest, taken from Quaternion.Angle and modified GenDraw.DrawMeshNowOrLater(mesh: mesh, loc: drawAt + drawer.offsetVector().RotatedBy(angle: Mathf.Acos(f: Quaternion.Dot(a: Quaternion.identity, b: quat)) * 2f * 57.29578f), quat: quat, mat: material, drawNow: flags.FlagSet(PawnRenderFlags.DrawNow)); drawAt.y += HediffComp_DrawImplant_AdMech.MinClippingDistance; } } } } /* * for (int hd = 0; hd < pawn.health.hediffSet.hediffs.Count; hd++) * { * Vector3 drawAt = vector; * HediffWithComps hediff = pawn.health.hediffSet.hediffs[hd] as HediffWithComps; * if (hediff != null) * { * for (int i = 0; i < hediff.comps.Count; i++) * { * HediffComp_DrawImplant_AdMech drawer = hediff.comps[i] as HediffComp_DrawImplant_AdMech; * if (drawer != null) * { * Material material = null; * if (drawer.implantDrawProps.implantDrawerType != ImplantDrawerType.Head) * { * drawAt.y += 0.005f; * if (bodyFacing == Rot4.South && drawer.implantDrawProps.implantDrawerType == ImplantDrawerType.Backpack) * { * drawAt.y -= 0.3f; * } * material = drawer.ImplantMaterial(pawn, bodyFacing); * // GenDraw.DrawMeshNowOrLater(mesh, drawAt, quat, material, portrait); * } * else * { * if (!pawn.Downed && !pawn.Dead && drawer.implantDrawProps.useHeadOffset) * { * drawAt = vector + pawn.Drawer.renderer.BaseHeadOffsetAt(headfacing); * } * else * { * if (pawn.Downed || pawn.Dead && drawer.implantDrawProps.useHeadOffset) * { * drawAt.y = vector.y + pawn.Drawer.renderer.BaseHeadOffsetAt(headfacing).y; * } * } * drawAt.y += 0.005f; * material = drawer.ImplantMaterial(pawn, headfacing); * // GenDraw.DrawMeshNowOrLater(mesh, drawAt, quat, material, portrait); * } * * if (material != null) * { * // GenDraw.DrawMeshNowOrLater(mesh, drawAt , quat, material, portrait); * * material = OverrideMaterialIfNeeded(material, pawn); * // Angle calculation to not pick the shortest, taken from Quaternion.Angle and modified * GenDraw.DrawMeshNowOrLater(mesh: mesh, loc: drawAt + drawer.offsetVector().RotatedBy(angle: Mathf.Acos(f: Quaternion.Dot(a: Quaternion.identity, b: quat)) * 2f * 57.29578f), * quat: quat, mat: material, drawNow: portrait); * * drawAt.y += HediffComp_DrawImplant_AdMech.MinClippingDistance; * } * } * HediffComp_Shield _Shield; * if ((_Shield = hediff.comps[i] as HediffComp_Shield) != null) * { * _Shield.DrawWornExtras(); * } * } * } * } */ } }
public float CalculateApparelScoreRawStats(Apparel apparel) { float num = 1.0f; float count = 1.0f; foreach (Saveable_StatDef stat in stats) { try { float nint = this.GetStatValue(apparel, stat); num += nint * stat.strength; count++; } catch (Exception e) { throw new Exception("Error Calculation Stat: " + stat.statDef, e); } } return num / count; }
internal static void Wear(this Pawn_ApparelTracker _this, Apparel newApparel, bool dropReplacedApparel = true) { SlotGroupUtility.Notify_TakingThing(newApparel); if (newApparel.Spawned) { newApparel.DeSpawn(); } if (!ApparelUtility.HasPartsToWear(_this.pawn, newApparel.def)) { Log.Warning(string.Concat(new object[] { _this.pawn, " tried to wear ", newApparel, " but he has no body parts required to wear it." })); return; } for (int i = _this.WornApparel.Count - 1; i >= 0; i--) { Apparel apparel = _this.WornApparel[i]; if (!ApparelUtility.CanWearTogether(newApparel.def, apparel.def)) { bool forbid = _this.pawn.Faction.HostileTo(Faction.OfPlayer); if (dropReplacedApparel) { Apparel apparel2; if (!_this.TryDrop(apparel, out apparel2, _this.pawn.Position, forbid)) { Log.Error(_this.pawn + " could not drop " + apparel); return; } } else { _this.Remove(apparel); } } } if (newApparel.wearer != null) { Log.Warning(string.Concat(new object[] { _this.pawn, " is trying to wear ", newApparel, " but this apparel already has a wearer (", newApparel.wearer, "). This may or may not cause bugs." })); } _this.WornApparel.Add(newApparel); newApparel.wearer = _this.pawn; _this.SortWornApparelIntoDrawOrder(); _this.ApparelChanged(); //CE PART CE_Utility.TryUpdateInventory(_this.pawn); // Apparel was added, update inventory MethodInfo methodInfo = typeof(Pawn_ApparelTracker).GetMethod("SortWornApparelIntoDrawOrder", BindingFlags.Instance | BindingFlags.NonPublic); methodInfo.Invoke(_this, new object[] { }); LongEventHandler.ExecuteWhenFinished(new Action(_this.ApparelChanged)); }
public void ForceApparelOnPawn( Pawn pawn, Apparel apparel ) { pawn.apparel.Wear( apparel, true ); // Try to lock the apparel var compLock = apparel.TryGetComp<CompLockable>(); if( compLock != null ) { compLock.ChangeLockState( true ); } ApplyApparelEffects( pawn, apparel ); }
[HarmonyPostfix] // Apparel apparel public static void Notify_Notify_ApparelAddedPostfix(Pawn_EquipmentTracker __instance, Apparel apparel) { if (apparel.TryGetComp <AbilitesExtended.CompAbilityItem>() != null && apparel.TryGetComp <AbilitesExtended.CompAbilityItem>() is AbilitesExtended.CompAbilityItem abilityItem) { Pawn pawn = __instance.pawn; if (!pawn.RaceProps.Humanlike) { return; } if (!abilityItem.Props.Abilities.NullOrEmpty()) { foreach (EquipmentAbilityDef def in abilityItem.Props.Abilities) { if (!__instance.pawn.abilities.abilities.Any(x => x.def == def) && (!def.requirePsyker || isPsyker(pawn))) { __instance.pawn.abilities.GainEquipmentAbility(def, apparel); Ability ability = __instance.pawn.abilities.abilities.Find(x => x.def == def); } } } } }
public void AddApparel(Apparel apparel) { _context.Apparel.Add(apparel); _context.SaveChanges(); }
protected override bool TryCastShot() { bool result = false; if (this.currentTarget != null && base.CasterPawn != null) { if (this.currentTarget.Thing != null && this.currentTarget.Thing is Pawn) { Pawn victim = this.currentTarget.Thing as Pawn; if (victim.Faction != null && victim.RaceProps.Humanlike && victim.story != null && victim.story.traits != null && !TM_Calc.IsUndeadNotVamp(victim)) { int traitsApplied = 0; List <Apparel> apparel = this.CasterPawn.apparel.WornApparel; List <Trait> orbTraits = new List <Trait>(); orbTraits.Clear(); CompEnchantedItem itemComp = null; if (apparel != null) { for (int i = 0; i < apparel.Count; i++) { Apparel item = apparel[i]; if (item != null && item.def == TorannMagicDefOf.TM_Artifact_OrbOfSouls_Full) { itemComp = item.GetComp <CompEnchantedItem>(); if (itemComp != null) { orbTraits = itemComp.SoulOrbTraits; } } } } if (orbTraits.Count > 0) { for (int i = 0; i < orbTraits.Count; i++) { bool conflicting = false; for (int j = 0; j < victim.story.traits.allTraits.Count; j++) { if (victim.story.traits.allTraits[j].def.ConflictsWith(orbTraits[i])) { conflicting = true; } } if (!conflicting) { AddTrait(victim, orbTraits[i]); traitsApplied++; } } if (traitsApplied > 0) { Effects(victim.Position); result = true; } else { Messages.Message("TM_NoTraitsApplied".Translate(victim), MessageTypeDefOf.RejectInput); result = false; } } else { Log.Message("no traits found in orb - was this dev-mode generated?"); result = true; //destroy anyways } } else { //invalid target Messages.Message("TM_InvalidTarget".Translate( this.CasterPawn.LabelShort, this.verbProps.label ), MessageTypeDefOf.RejectInput); } } else { //invalid target Messages.Message("TM_InvalidTarget".Translate( this.CasterPawn.LabelShort, this.verbProps.label ), MessageTypeDefOf.RejectInput); } } else { Log.Warning("failed to TryCastShot"); } this.burstShotsLeft = 0; //this.ability.TicksUntilCasting = (int)base.UseAbilityProps.SecondsToRecharge * 60; PostCastShot(result); return(false); }
[HarmonyPostfix] // Apparel apparel public static void Notify_ApparelRemovedPostfix(Pawn_EquipmentTracker __instance, Apparel apparel) { bool abilityitem = apparel.TryGetComp <AbilitesExtended.CompAbilityItem>() != null; if (abilityitem) { Pawn pawn = __instance.pawn; if (!pawn.RaceProps.Humanlike) { return; } foreach (AbilitesExtended.CompAbilityItem compAbilityItem in apparel.GetComps <AbilitesExtended.CompAbilityItem>()) { if (__instance.pawn.abilities.abilities.Any(x => compAbilityItem.Props.Abilities.Contains(x.def))) { foreach (AbilityDef abilityDef in compAbilityItem.Props.Abilities) { if (__instance.pawn.abilities.abilities.Any(x => compAbilityItem.Props.Abilities.Contains(abilityDef))) { Ability ability = __instance.pawn.abilities.abilities.Find(x => x.def == abilityDef); __instance.pawn.abilities.abilities.Remove(ability); } } } } } }
public static float ApparelScoreRaw( Apparel apparel, Pawn pawn ) { // relevant apparel stats HashSet<StatDef> equippedOffsets = new HashSet<StatDef>(); if ( apparel.def.equippedStatOffsets != null ) { foreach ( StatModifier equippedStatOffset in apparel.def.equippedStatOffsets ) { equippedOffsets.Add( equippedStatOffset.stat ); } } HashSet<StatDef> statBases = new HashSet<StatDef>(); if ( apparel.def.statBases != null ) { foreach ( StatModifier statBase in apparel.def.statBases ) { statBases.Add( statBase.stat ); } } // start score at 1 float score = 1; // make infusions ready InfusionSet infusions; bool infused = false; StatMod mod; InfusionDef prefix = null; InfusionDef suffix = null; if ( apparel.TryGetInfusions( out infusions ) ) { infused = true; prefix = infusions.Prefix.ToInfusionDef(); suffix = infusions.Suffix.ToInfusionDef(); } // add values for each statdef modified by the apparel foreach( ApparelStatCache.StatPriority statPriority in pawn.GetApparelStatCache().StatCache ) { // statbases, e.g. armor if ( statBases.Contains( statPriority.Stat ) ) { // add stat to base score before offsets are handled ( the pawn's apparel stat cache always has armors first as it is initialized with it). score += apparel.GetStatValue( statPriority.Stat ) * statPriority.Weight; } // equipped offsets, e.g. movement speeds if ( equippedOffsets.Contains( statPriority.Stat ) ) { // base value float norm = apparel.GetStatValue( statPriority.Stat ); float adjusted = norm; // add offset adjusted += apparel.def.equippedStatOffsets.GetStatOffsetFromList( statPriority.Stat ) * statPriority.Weight; // normalize if ( norm != 0 ) { adjusted /= norm; } // multiply score to favour items with multiple offsets score *= adjusted; //debug.AppendLine( statWeightPair.Key.LabelCap + ": " + score ); } // infusions if( infused ) { // prefix if ( !infusions.PassPre && prefix.GetStatValue( statPriority.Stat, out mod ) ) { score += mod.offset * statPriority.Weight; score += score * ( mod.multiplier - 1 ) * statPriority.Weight; //debug.AppendLine( statWeightPair.Key.LabelCap + " infusion: " + score ); } if ( !infusions.PassSuf && suffix.GetStatValue( statPriority.Stat, out mod ) ) { score += mod.offset * statPriority.Weight; score += score * ( mod.multiplier - 1 ) * statPriority.Weight; //debug.AppendLine( statWeightPair.Key.LabelCap + " infusion: " + score ); } } } // offset for apparel hitpoints if ( apparel.def.useHitPoints ) { // durability on 0-1 scale float x = apparel.HitPoints / (float)apparel.MaxHitPoints; score *= HitPointsPercentScoreFactorCurve.Evaluate( x ); } // temperature FloatRange targetTemperatures = pawn.GetApparelStatCache().TargetTemperatures; float minComfyTemperature = pawn.GetStatValue( StatDefOf.ComfyTemperatureMin ); float maxComfyTemperature = pawn.GetStatValue( StatDefOf.ComfyTemperatureMax ); // offsets on apparel float insulationCold = apparel.GetStatValue( StatDefOf.Insulation_Cold ); float insulationHeat = apparel.GetStatValue( StatDefOf.Insulation_Heat ); // offsets on apparel infusions if( infused ) { // prefix if( !infusions.PassPre && prefix.GetStatValue( StatDefOf.ComfyTemperatureMin, out mod ) ) { insulationCold += mod.offset; } if( !infusions.PassPre && prefix.GetStatValue( StatDefOf.ComfyTemperatureMax, out mod ) ) { insulationHeat += mod.offset; } // suffix if( !infusions.PassSuf && suffix.GetStatValue( StatDefOf.ComfyTemperatureMin, out mod ) ) { insulationCold += mod.offset; } if( !infusions.PassSuf && suffix.GetStatValue( StatDefOf.ComfyTemperatureMax, out mod ) ) { insulationHeat += mod.offset; } } // if this gear is currently worn, we need to make sure the contribution to the pawn's comfy temps is removed so the gear is properly scored if ( pawn.apparel.WornApparel.Contains( apparel ) ) { minComfyTemperature -= insulationCold; maxComfyTemperature -= insulationHeat; } // now for the interesting bit. float temperatureScoreOffset = 0f; float tempWeight = pawn.GetApparelStatCache().TemperatureWeight; float neededInsulation_Cold = targetTemperatures.TrueMin - minComfyTemperature; // isolation_cold is given as negative numbers < 0 means we're underdressed float neededInsulation_Warmth = targetTemperatures.TrueMax - maxComfyTemperature; // isolation_warm is given as positive numbers. // currently too cold if ( neededInsulation_Cold < 0 ) { temperatureScoreOffset += -insulationCold * tempWeight; } // currently warm enough else { // this gear would make us too cold if ( insulationCold > neededInsulation_Cold ) { temperatureScoreOffset += ( neededInsulation_Cold - insulationCold ) * tempWeight; } } // currently too warm if( neededInsulation_Warmth > 0 ) { temperatureScoreOffset += insulationHeat * tempWeight; } // currently cool enough else { // this gear would make us too warm if( insulationHeat < neededInsulation_Warmth ) { temperatureScoreOffset += -( neededInsulation_Warmth - insulationHeat ) * tempWeight; } } // adjust for temperatures score += temperatureScoreOffset / 10f; return score; }
public static ApparelGraphicRecord GraphicRecord(Pawn pawn, ApparelGraphicRecord record, Quaternion quat, Vector3 vector, bool renderBody, bool portrait, Rot4 bodyFacing, Rot4 headFacing) { Vector3 vector2 = vector; Vector3 vector3 = vector; bool flag12 = bodyFacing == Rot4.North; if (flag12) { vector2.y -= 0.02734375f; vector3.y = vector2.y + 0.0234375f; } else { vector2.y -= 0.0234375f; vector3.y = vector2.y + 0.02734375f; } Mesh mesh = null; Vector2 size = mesh?.bounds.size ?? (portrait ? MeshPool.humanlikeBodySet.MeshAt(bodyFacing).bounds.size : pawn.Drawer.renderer.graphics.nakedGraphic.MeshAt(bodyFacing).bounds.size); if (AdeptusIntergrationUtility.enabled_AlienRaces) { PawnRenderUtility.AlienRacesPatch(pawn, bodyFacing, out size, portrait); } else { size = new Vector2(1.5f, 1.5f); } Apparel apparel = record.sourceApparel; if (apparel is ApparelComposite composite) { if (!composite.Pauldrons.NullOrEmpty() && AMAMod.settings.AllowPauldronDrawer) { for (int i = 0; i < composite.Pauldrons.Count; i++) { CompPauldronDrawer Pauldron = composite.Pauldrons[i] as CompPauldronDrawer; if (Pauldron != null) { Vector3 center = vector; center.y = pawn.DrawPos.y; center = center + (quat * Pauldron.GetOffsetFor(bodyFacing, false)); if (Pauldron.activeEntries.NullOrEmpty()) { Pauldron.Initialize(); } foreach (ShoulderPadEntry entry in Pauldron.activeEntries) { // entry.Drawer = Pauldron; if (entry.apparel == null) { entry.apparel = apparel; } if (entry.Drawer == null) { Log.Warning("Warning! Drawer null"); } if (entry.ShouldDrawEntry(portrait, bodyFacing, size, renderBody, out Graphic pauldronMat, out Mesh pauldronMesh, out Vector3 offset)) { if (Pauldron.onHead || renderBody) { GenDraw.DrawMeshNowOrLater ( // pauldronMesh, PawnRenderUtility.GetPawnMesh(portrait, pawn, entry.Props.flipWest && bodyFacing == Rot4.West ? bodyFacing.Opposite : bodyFacing, !Pauldron.onHead), center + (quat * offset), quat, PawnRenderUtility.OverrideMaterialIfNeeded(pauldronMat.MatAt(bodyFacing), pawn), portrait ); } } } } } } if (!composite.Extras.NullOrEmpty() && AMAMod.settings.AllowExtraPartDrawer) { for (int i = 0; i < composite.Extras.Count; i++) { CompApparelExtraPartDrawer ExtraDrawer = composite.Extras[i] as CompApparelExtraPartDrawer; if (ExtraDrawer != null) { Vector3 drawAt = vector; if (!ExtraDrawer.Props.ExtrasEntries.NullOrEmpty()) { bool onHead = ExtraDrawer.onHead || ExtraDrawer.ExtraPartEntry.OnHead || ExtraDrawer.Props.onHead; Rot4 facing = onHead ? headFacing : bodyFacing; if (ExtraDrawer.ShouldDrawExtra(pawn, apparel, facing, out Material extraMat)) { if (onHead || renderBody) { if (onHead) { Vector3 v = vector + quat * pawn.Drawer.renderer.BaseHeadOffsetAt(headFacing); drawAt = v + quat * new Vector3(ExtraDrawer.GetOffset(bodyFacing, ExtraDrawer.ExtraPartEntry).x *size.x, ExtraDrawer.GetOffset(bodyFacing, ExtraDrawer.ExtraPartEntry).y, ExtraDrawer.GetOffset(bodyFacing, ExtraDrawer.ExtraPartEntry).z *size.y); } else { drawAt = vector + (quat * new Vector3(ExtraDrawer.GetOffset(bodyFacing, ExtraDrawer.ExtraPartEntry).x *size.x, ExtraDrawer.GetOffset(bodyFacing, ExtraDrawer.ExtraPartEntry).y, ExtraDrawer.GetOffset(bodyFacing, ExtraDrawer.ExtraPartEntry).z *size.y)); } GenDraw.DrawMeshNowOrLater ( // pauldronMesh, PawnRenderUtility.GetPawnMesh(portrait, pawn, facing, !onHead), drawAt, quat, PawnRenderUtility.OverrideMaterialIfNeeded(extraMat, pawn), portrait ); } // vector.y += CompApparelExtaDrawer.MinClippingDistance; } } } } } } else { if (PawnRenderUtility.CompositeApparel(apparel)) { for (int i = 0; i < apparel.AllComps.Count; i++) { if (AMAMod.settings.AllowPauldronDrawer) { CompPauldronDrawer Pauldron = apparel.AllComps[i] as CompPauldronDrawer; if (Pauldron != null) { Vector3 center = vector2; center.y = pawn.DrawPos.y; center = center + (quat * Pauldron.GetOffsetFor(bodyFacing, false)); if (Pauldron.activeEntries.NullOrEmpty()) { Pauldron.Initialize(); } foreach (ShoulderPadEntry entry in Pauldron.activeEntries) { // entry.Drawer = Pauldron; if (entry.apparel == null) { entry.apparel = apparel; } if (entry.Drawer == null) { Log.Warning("Warning! Drawer null"); } if (entry.ShouldDrawEntry(portrait, bodyFacing, size, renderBody, out Graphic pauldronMat, out Mesh pauldronMesh, out Vector3 offset)) { if (Pauldron.onHead || renderBody && pauldronMat != null) { GenDraw.DrawMeshNowOrLater ( // pauldronMesh, PawnRenderUtility.GetPawnMesh(portrait, pawn, entry.Props.flipWest && bodyFacing == Rot4.West ? bodyFacing.Opposite : bodyFacing, !Pauldron.onHead), center + (quat * offset), quat, PawnRenderUtility.OverrideMaterialIfNeeded(pauldronMat.MatAt(bodyFacing), pawn), portrait ); } } } } } if (AMAMod.settings.AllowExtraPartDrawer) { CompApparelExtraPartDrawer ExtraDrawer = apparel.AllComps[i] as CompApparelExtraPartDrawer; if (ExtraDrawer != null) { Vector3 drawAt = vector; if (!ExtraDrawer.Props.ExtrasEntries.NullOrEmpty()) { bool onHead = ExtraDrawer.onHead || ExtraDrawer.ExtraPartEntry.OnHead || ExtraDrawer.Props.onHead; Rot4 facing = onHead ? headFacing : bodyFacing; if (ExtraDrawer.ShouldDrawExtra(pawn, apparel, facing, out Material extraMat)) { if (onHead || renderBody) { if (onHead) { Vector3 v = vector + quat * pawn.Drawer.renderer.BaseHeadOffsetAt(headFacing); drawAt = v + quat * new Vector3(ExtraDrawer.GetOffset(bodyFacing, ExtraDrawer.ExtraPartEntry).x *size.x, ExtraDrawer.GetOffset(bodyFacing, ExtraDrawer.ExtraPartEntry).y, ExtraDrawer.GetOffset(bodyFacing, ExtraDrawer.ExtraPartEntry).z *size.y); } else { drawAt = vector + (quat * new Vector3(ExtraDrawer.GetOffset(bodyFacing, ExtraDrawer.ExtraPartEntry).x *size.x, ExtraDrawer.GetOffset(bodyFacing, ExtraDrawer.ExtraPartEntry).y, ExtraDrawer.GetOffset(bodyFacing, ExtraDrawer.ExtraPartEntry).z *size.y)); } GenDraw.DrawMeshNowOrLater ( // pauldronMesh, PawnRenderUtility.GetPawnMesh(portrait, pawn, facing, !onHead), drawAt, quat, PawnRenderUtility.OverrideMaterialIfNeeded(extraMat, pawn), portrait ); } // vector.y += CompApparelExtaDrawer.MinClippingDistance; } } } } } } } if (!pawn.Dead && AMAMod.settings.AllowHediffPartDrawer) { Vector3 drawAt = vector; for (int i = 0; i < AdeptusHediffUtility.GraphicHediffs.Count; i++) { if (pawn.health.hediffSet.GetFirstHediffOfDef(AdeptusHediffUtility.GraphicHediffs[i]) is HediffWithComps hediff) { if (hediff.TryGetCompFast <HediffComp_DrawImplant_AdMech>() is HediffComp_DrawImplant_AdMech hediffdrawer) { Material material = null; if (hediffdrawer.implantDrawProps.implantDrawerType != ImplantDrawerType.Head) { drawAt.y += 0.005f; if (bodyFacing == Rot4.South && hediffdrawer.implantDrawProps.implantDrawerType == ImplantDrawerType.Backpack) { drawAt.y -= 0.3f; } material = hediffdrawer.ImplantMaterial(pawn, bodyFacing); // GenDraw.DrawMeshNowOrLater(mesh, drawAt, quat, material, portrait); } else { if (!pawn.Downed && !pawn.Dead && hediffdrawer.implantDrawProps.useHeadOffset) { drawAt = vector + pawn.Drawer.renderer.BaseHeadOffsetAt(headFacing); } else { if (pawn.Downed || pawn.Dead && hediffdrawer.implantDrawProps.useHeadOffset) { drawAt.y = vector.y + pawn.Drawer.renderer.BaseHeadOffsetAt(headFacing).y; } } drawAt.y += 0.005f; material = hediffdrawer.ImplantMaterial(pawn, headFacing); // GenDraw.DrawMeshNowOrLater(mesh, drawAt, quat, material, portrait); } if (material != null) { // GenDraw.DrawMeshNowOrLater(mesh, drawAt , quat, material, portrait); material = PawnRenderUtility.OverrideMaterialIfNeeded(material, pawn); // Angle calculation to not pick the shortest, taken from Quaternion.Angle and modified GenDraw.DrawMeshNowOrLater(mesh: mesh, loc: drawAt + hediffdrawer.offsetVector().RotatedBy(angle: Mathf.Acos(f: Quaternion.Dot(a: Quaternion.identity, b: quat)) * 2f * 57.29578f), quat: quat, mat: material, drawNow: portrait); drawAt.y += HediffComp_DrawImplant_AdMech.MinClippingDistance; } } } } } return(record); }
private void TryEquipDraggedItem(Pawn p) { droppedDraggedItem = false; if (!EquipmentUtility.CanEquip(draggedItem, p, out string cantReason)) { Messages.Message("MessageCantEquipCustom".Translate(cantReason.CapitalizeFirst()), p, MessageTypeDefOf.RejectInput, historical: false); draggedItem = null; return; } if (draggedItem.def.IsWeapon) { if (p.WorkTagIsDisabled(WorkTags.Violent)) { Messages.Message("MessageCantEquipIncapableOfViolence".Translate(p.LabelShort, p), p, MessageTypeDefOf.RejectInput, historical: false); draggedItem = null; return; } if (!p.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation)) { Messages.Message("MessageCantEquipIncapableOfManipulation".Translate(), p, MessageTypeDefOf.RejectInput, historical: false); draggedItem = null; return; } } Apparel apparel = draggedItem as Apparel; ThingWithComps thingWithComps = draggedItem as ThingWithComps; if (apparel != null && p.apparel != null) { if (!ApparelUtility.HasPartsToWear(p, apparel.def)) { Messages.Message("MessageCantWearApparelMissingBodyParts".Translate(p.LabelShort, p), p, MessageTypeDefOf.RejectInput, historical: false); draggedItem = null; return; } if (CurrentWearerOf(apparel) != null && CurrentWearerOf(apparel).apparel.IsLocked(apparel)) { Messages.Message("MessageCantUnequipLockedApparel".Translate(), p, MessageTypeDefOf.RejectInput, historical: false); draggedItem = null; return; } if (p.apparel.WouldReplaceLockedApparel(apparel)) { Messages.Message("MessageWouldReplaceLockedApparel".Translate(p.LabelShort, p), p, MessageTypeDefOf.RejectInput, historical: false); draggedItem = null; return; } tmpExistingApparel.Clear(); tmpExistingApparel.AddRange(p.apparel.WornApparel); for (int i = 0; i < tmpExistingApparel.Count; i++) { if (!ApparelUtility.CanWearTogether(apparel.def, tmpExistingApparel[i].def, p.RaceProps.body)) { p.apparel.Remove(tmpExistingApparel[i]); Pawn pawn = CaravanInventoryUtility.FindPawnToMoveInventoryTo(tmpExistingApparel[i], Pawns, null); if (pawn != null) { pawn.inventory.innerContainer.TryAdd(tmpExistingApparel[i]); continue; } Log.Warning("Could not find any pawn to move " + tmpExistingApparel[i] + " to."); tmpExistingApparel[i].Destroy(); } } p.apparel.Wear((Apparel)apparel.SplitOff(1), dropReplacedApparel: false); if (p.outfits != null) { p.outfits.forcedHandler.SetForced(apparel, forced: true); } } else if (thingWithComps != null && p.equipment != null) { tmpExistingEquipment.Clear(); tmpExistingEquipment.AddRange(p.equipment.AllEquipmentListForReading); for (int j = 0; j < tmpExistingEquipment.Count; j++) { p.equipment.Remove(tmpExistingEquipment[j]); Pawn pawn2 = CaravanInventoryUtility.FindPawnToMoveInventoryTo(tmpExistingEquipment[j], Pawns, null); if (pawn2 != null) { pawn2.inventory.innerContainer.TryAdd(tmpExistingEquipment[j]); continue; } Log.Warning("Could not find any pawn to move " + tmpExistingEquipment[j] + " to."); tmpExistingEquipment[j].Destroy(); } p.equipment.AddEquipment((ThingWithComps)thingWithComps.SplitOff(1)); } else { Log.Warning("Could not make " + p + " equip or wear " + draggedItem); } draggedItem = null; }
public static float ApparelScoreRaw(Pawn pawn, Apparel apparel, NeededWarmth neededWarmth = NeededWarmth.Any) { var outfit = pawn?.outfits?.CurrentOutfit as ExtendedOutfit; if (pawn != null && outfit == null) { Log.ErrorOnce("Outfitted :: Not an ExtendedOutfit, something went wrong.", 399441); return(0f); } float score = 0.1f + ApparelScoreRawPriorities(apparel, outfit); if (pawn != null && outfit?.AutoWorkPriorities == true) { score += ApparelScoreAutoWorkPriorities(pawn, apparel); } if (apparel.def.useHitPoints) { float x = (float)apparel.HitPoints / apparel.MaxHitPoints; score *= HitPointsPercentScoreFactorCurve.Evaluate(x); } score += apparel.GetSpecialApparelScoreOffset(); if (pawn != null && outfit != null) { score += ApparelScoreRawInsulation(pawn, apparel, outfit, neededWarmth); } if (pawn?.def?.race?.Animal == false) { if (outfit?.PenaltyWornByCorpse == true && apparel.WornByCorpse && ThoughtUtility.CanGetThought_NewTemp(pawn, ThoughtDefOf.DeadMansApparel, true)) { score -= 0.5f; if (score > 0f) { score *= 0.1f; } } if (apparel.Stuff == ThingDefOf.Human.race.leatherDef) { if (ThoughtUtility.CanGetThought_NewTemp(pawn, ThoughtDefOf.HumanLeatherApparelSad, true)) { score -= 0.5f; if (score > 0f) { score *= 0.1f; } } if (ThoughtUtility.CanGetThought_NewTemp(pawn, ThoughtDefOf.HumanLeatherApparelHappy, true)) { score += 0.12f; } } } //royalty titles if (pawn?.royalty?.AllTitlesInEffectForReading?.Count > 0) { HashSet <ThingDef> tmpAllowedApparels = new HashSet <ThingDef>(); HashSet <ThingDef> tmpRequiredApparels = new HashSet <ThingDef>(); HashSet <BodyPartGroupDef> tmpBodyPartGroupsWithRequirement = new HashSet <BodyPartGroupDef>(); QualityCategory qualityCategory = QualityCategory.Awful; foreach (RoyalTitle item in pawn.royalty.AllTitlesInEffectForReading) { if (item.def.requiredApparel != null) { for (int i = 0; i < item.def.requiredApparel.Count; i++) { tmpAllowedApparels.AddRange(item.def.requiredApparel[i].AllAllowedApparelForPawn(pawn, ignoreGender: false, includeWorn: true)); tmpRequiredApparels.AddRange(item.def.requiredApparel[i].AllRequiredApparelForPawn(pawn, ignoreGender: false, includeWorn: true)); tmpBodyPartGroupsWithRequirement.AddRange(item.def.requiredApparel[i].bodyPartGroupsMatchAny); } } if (item.def.requiredMinimumApparelQuality > qualityCategory) { qualityCategory = item.def.requiredMinimumApparelQuality; } } if (apparel.TryGetQuality(out QualityCategory qc) && qc < qualityCategory) { score *= 0.25f; } bool isRequired = apparel.def.apparel.bodyPartGroups.Any(bp => tmpBodyPartGroupsWithRequirement.Contains(bp)); if (isRequired) { foreach (ThingDef tmpRequiredApparel in tmpRequiredApparels) { tmpAllowedApparels.Remove(tmpRequiredApparel); } if (tmpAllowedApparels.Contains(apparel.def)) { score *= 10f; } if (tmpRequiredApparels.Contains(apparel.def)) { score *= 25f; } } } return(score); }
public void Remove(Apparel a, bool forbidden = true) { this.DropApparel(a, forbidden); this.StoredApparel.Remove(a); }
/// <summary> /// Calculates damage through armor, depending on damage type, target and natural resistance. Also calculates deflection and adjusts damage type and impacted body part accordingly. /// </summary> /// <param name="originalDinfo">The pre-armor damage info</param> /// <param name="pawn">The damaged pawn</param> /// <param name="hitPart">The pawn's body part that has been hit</param> /// <param name="armorReduced">Whether sharp damage was deflected by armor</param> /// <param name="shieldAbsorbed">Returns true if attack did not penetrate pawn's melee shield</param> /// <param name="armorDeflected">Whether the attack was completely absorbed by the armor</param> /// <returns>If shot is deflected returns a new dinfo cloned from the original with damage amount, Def and ForceHitPart adjusted for deflection, otherwise a clone with only the damage adjusted</returns> public static DamageInfo GetAfterArmorDamage(DamageInfo originalDinfo, Pawn pawn, BodyPartRecord hitPart, out bool armorDeflected, out bool armorReduced, out bool shieldAbsorbed) { shieldAbsorbed = false; armorDeflected = false; armorReduced = false; if (originalDinfo.Def.armorCategory == null) { return(originalDinfo); } DamageInfo dinfo = new DamageInfo(originalDinfo); float dmgAmount = dinfo.Amount; bool involveArmor = dinfo.Def.harmAllLayersUntilOutside; bool isAmbientDamage = dinfo.IsAmbientDamage(); // In case of ambient damage (fire, electricity) we apply a percentage reduction formula based on the sum of all applicable armor if (isAmbientDamage) { dinfo.SetAmount(Mathf.CeilToInt(GetAmbientPostArmorDamage(dmgAmount, originalDinfo.Def.armorCategory.armorRatingStat, pawn, hitPart))); armorDeflected = dinfo.Amount <= 0; return(dinfo); } float penAmount = originalDinfo.ArmorPenetrationInt; //GetPenetrationValue(originalDinfo); // Apply worn armor if (involveArmor && pawn.apparel != null && !pawn.apparel.WornApparel.NullOrEmpty()) { List <Apparel> apparel = pawn.apparel.WornApparel; // Check for shields first Apparel shield = apparel.FirstOrDefault(x => x is Apparel_Shield); if (shield != null) { // Determine whether the hit is blocked by the shield bool blockedByShield = false; if (!(dinfo.Weapon?.IsMeleeWeapon ?? false)) { var shieldDef = shield.def.GetModExtension <ShieldDefExtension>(); if (shieldDef == null) { Log.ErrorOnce("CE :: shield " + shield.def.ToString() + " is Apparel_Shield but has no ShieldDefExtension", shield.def.GetHashCode() + 12748102); } else { bool hasCoverage = shieldDef.PartIsCoveredByShield(hitPart, pawn); if (hasCoverage) { // Right arm is vulnerable during warmup/attack/cooldown blockedByShield = !((pawn.stances?.curStance as Stance_Busy)?.verb != null && hitPart.IsInGroup(CE_BodyPartGroupDefOf.RightArm)); } } } // Try to penetrate the shield if (blockedByShield && !TryPenetrateArmor(dinfo.Def, shield.GetStatValue(dinfo.Def.armorCategory.armorRatingStat), ref penAmount, ref dmgAmount, shield)) { shieldAbsorbed = true; armorDeflected = true; dinfo.SetAmount(0); // Apply secondary damage to shield var props = dinfo.Weapon?.projectile as ProjectilePropertiesCE; if (props != null && !props.secondaryDamage.NullOrEmpty()) { foreach (SecondaryDamage sec in props.secondaryDamage) { if (shield.Destroyed) { break; } var secDinfo = sec.GetDinfo(); var pen = originalDinfo.ArmorPenetrationInt; //GetPenetrationValue(originalDinfo); var dmg = (float)secDinfo.Amount; TryPenetrateArmor(secDinfo.Def, shield.GetStatValue(secDinfo.Def.armorCategory.armorRatingStat), ref pen, ref dmg, shield); } } return(dinfo); } } // Apparel is arranged in draw order, we run through reverse to go from Shell -> OnSkin for (int i = apparel.Count - 1; i >= 0; i--) { if (apparel[i].def.apparel.CoversBodyPart(hitPart) && !TryPenetrateArmor(dinfo.Def, apparel[i].GetStatValue(dinfo.Def.armorCategory.armorRatingStat), ref penAmount, ref dmgAmount, apparel[i])) { // Hit was deflected, convert damage type //armorReduced = true; dinfo = GetDeflectDamageInfo(dinfo, hitPart); i++; // We apply this piece of apparel twice on conversion, this means we can't use deflection on Blunt or else we get an infinite loop of eternal deflection } if (dmgAmount <= 0) { dinfo.SetAmount(0); armorDeflected = true; return(dinfo); } } } // Apply natural armor List <BodyPartRecord> partsToHit = new List <BodyPartRecord>() { hitPart }; if (involveArmor) { BodyPartRecord curPart = hitPart; while (curPart.parent != null && curPart.depth == BodyPartDepth.Inside) { curPart = curPart.parent; partsToHit.Add(curPart); } } for (int i = partsToHit.Count - 1; i >= 0; i--) { BodyPartRecord curPart = partsToHit[i]; bool coveredByArmor = curPart.IsInGroup(CE_BodyPartGroupDefOf.CoveredByNaturalArmor); float partArmor = pawn.GetStatValue(CE_StatDefOf.BodyPartDensity); // How much armor is provided by sheer meat if (coveredByArmor) { partArmor += pawn.GetStatValue(dinfo.Def.armorCategory.armorRatingStat); } float unused = dmgAmount; // Only apply damage reduction when penetrating armored body parts if (coveredByArmor ? !TryPenetrateArmor(dinfo.Def, partArmor, ref penAmount, ref dmgAmount) : !TryPenetrateArmor(dinfo.Def, partArmor, ref penAmount, ref unused)) { dinfo.SetHitPart(curPart); if (coveredByArmor && pawn.RaceProps.IsMechanoid) { // For Mechanoid natural armor, apply deflection and blunt armor dinfo = GetDeflectDamageInfo(dinfo, curPart); TryPenetrateArmor(dinfo.Def, partArmor, ref penAmount, ref dmgAmount); } break; } if (dmgAmount <= 0) { dinfo.SetAmount(0); armorDeflected = true; return(dinfo); } } dinfo.SetAmount(Mathf.CeilToInt(dmgAmount)); return(dinfo); }
// Decompiled code is painful to read... Continue at your own risk public static List <FloatMenuOption> ChoicesForThing(Thing thing, Pawn pawn) { List <FloatMenuOption> opts = new List <FloatMenuOption>(); Thing t = thing; // Copied from FloatMenuMakerMap.AddHumanlikeOrders if (t.def.ingestible != null && pawn.RaceProps.CanEverEat(t) && t.IngestibleNow) { string text; if (t.def.ingestible.ingestCommandString.NullOrEmpty()) { text = "ConsumeThing".Translate(new NamedArgument[] { t.LabelShort }); } else { text = string.Format(t.def.ingestible.ingestCommandString, t.LabelShort); } if (!t.IsSociallyProper(pawn)) { text = text + " (" + "ReservedForPrisoners".Translate() + ")"; } FloatMenuOption item7; if (t.def.IsNonMedicalDrug && pawn.IsTeetotaler()) { item7 = new FloatMenuOption(text + " (" + TraitDefOf.DrugDesire.DataAtDegree(-1).label + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null); } else if (!pawn.CanReach(t, PathEndMode.OnCell, Danger.Deadly, false, TraverseMode.ByPawn)) { item7 = new FloatMenuOption(text + " (" + "NoPath".Translate() + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null); } else { MenuOptionPriority priority2 = (!(t is Corpse)) ? MenuOptionPriority.Default : MenuOptionPriority.Low; item7 = FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(text, delegate() { t.SetForbidden(false, true); Job job = new Job(JobDefOf.Ingest, t); job.count = FoodUtility.WillIngestStackCountOf(pawn, t.def, t.GetStatValue(StatDefOf.Nutrition, true)); pawn.jobs.TryTakeOrderedJob(job, JobTag.Misc); }, priority2, null, null, 0f, null, null), pawn, t, "ReservedBy"); } opts.Add(item7); } // Add equipment commands // Copied from FloatMenuMakerMap.AddHumanlikeOrders if (thing is ThingWithComps equipment && equipment.GetComp <CompEquippable>() != null) { string labelShort = equipment.LabelShort; FloatMenuOption item4; if (equipment.def.IsWeapon && pawn.WorkTagIsDisabled(WorkTags.Violent)) { item4 = new FloatMenuOption("CannotEquip".Translate(new NamedArgument[] { labelShort }) + " (" + "IsIncapableOfViolenceLower".Translate(new NamedArgument[] { pawn.LabelShort }) + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null); } else if (!pawn.CanReach(equipment, PathEndMode.ClosestTouch, Danger.Deadly, false, TraverseMode.ByPawn)) { item4 = new FloatMenuOption("CannotEquip".Translate(new NamedArgument[] { labelShort }) + " (" + "NoPath".Translate() + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null); } else if (!pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation)) { item4 = new FloatMenuOption("CannotEquip".Translate(new NamedArgument[] { labelShort }) + " (" + "Incapable".Translate() + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null); } else { string text5 = "Equip".Translate(new NamedArgument[] { labelShort }); if (equipment.def.IsRangedWeapon && pawn.story != null && pawn.story.traits.HasTrait(TraitDefOf.Brawler)) { text5 = text5 + " " + "EquipWarningBrawler".Translate(); } item4 = FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(text5, delegate() { equipment.SetForbidden(false, true); pawn.jobs.TryTakeOrderedJob(new Job(JobDefOf.Equip, equipment), JobTag.Misc); MoteMaker.MakeStaticMote(equipment.DrawPos, equipment.Map, ThingDefOf.Mote_FeedbackEquip, 1f); PlayerKnowledgeDatabase.KnowledgeDemonstrated(ConceptDefOf.EquippingWeapons, KnowledgeAmount.Total); }, MenuOptionPriority.High, null, null, 0f, null, null), pawn, equipment, "ReservedBy"); } opts.Add(item4); } // Add clothing commands Apparel apparel = thing as Apparel; if (apparel != null) { FloatMenuOption item5; if (!pawn.CanReach(apparel, PathEndMode.ClosestTouch, Danger.Deadly, false, TraverseMode.ByPawn)) { item5 = new FloatMenuOption("CannotWear".Translate(new NamedArgument[] { apparel.Label }) + " (" + "NoPath".Translate() + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null); } else if (!ApparelUtility.HasPartsToWear(pawn, apparel.def)) { item5 = new FloatMenuOption("CannotWear".Translate(new NamedArgument[] { apparel.Label }) + " (" + "CannotWearBecauseOfMissingBodyParts".Translate() + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null); } else { item5 = FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption("ForceWear".Translate(new NamedArgument[] { apparel.LabelShort }), delegate() { apparel.SetForbidden(false, true); Job job = new Job(JobDefOf.Wear, apparel); pawn.jobs.TryTakeOrderedJob(job, JobTag.Misc); }, MenuOptionPriority.High, null, null, 0f, null, null), pawn, apparel, "ReservedBy"); } opts.Add(item5); } // Add caravan commands if (pawn.IsFormingCaravan()) { if (thing != null && thing.def.EverHaulable) { Pawn packTarget = GiveToPackAnimalUtility.UsablePackAnimalWithTheMostFreeSpace(pawn) ?? pawn; JobDef jobDef = (packTarget != pawn) ? JobDefOf.GiveToPackAnimal : JobDefOf.TakeInventory; if (!pawn.CanReach(thing, PathEndMode.ClosestTouch, Danger.Deadly, false, TraverseMode.ByPawn)) { opts.Add(new FloatMenuOption("CannotLoadIntoCaravan".Translate(new NamedArgument[] { thing.Label }) + " (" + "NoPath".Translate() + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null)); } else if (MassUtility.WillBeOverEncumberedAfterPickingUp(packTarget, thing, 1)) { opts.Add(new FloatMenuOption("CannotLoadIntoCaravan".Translate(new NamedArgument[] { thing.Label }) + " (" + "TooHeavy".Translate() + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null)); } else { LordJob_FormAndSendCaravan lordJob = (LordJob_FormAndSendCaravan)pawn.GetLord().LordJob; float capacityLeft = CaravanFormingUtility.CapacityLeft(lordJob); if (thing.stackCount == 1) { float capacityLeft4 = capacityLeft - thing.GetStatValue(StatDefOf.Mass, true); opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(CaravanFormingUtility.AppendOverweightInfo("LoadIntoCaravan".Translate(new NamedArgument[] { thing.Label }), capacityLeft4), delegate() { thing.SetForbidden(false, false); Job job = new Job(jobDef, thing); job.count = 1; job.checkEncumbrance = (packTarget == pawn); pawn.jobs.TryTakeOrderedJob(job, JobTag.Misc); }, MenuOptionPriority.High, null, null, 0f, null, null), pawn, thing, "ReservedBy")); } else { if (MassUtility.WillBeOverEncumberedAfterPickingUp(packTarget, thing, thing.stackCount)) { opts.Add(new FloatMenuOption("CannotLoadIntoCaravanAll".Translate(new NamedArgument[] { thing.Label }) + " (" + "TooHeavy".Translate() + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null)); } else { float capacityLeft2 = capacityLeft - (float)thing.stackCount * thing.GetStatValue(StatDefOf.Mass, true); opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(CaravanFormingUtility.AppendOverweightInfo("LoadIntoCaravanAll".Translate(new NamedArgument[] { thing.Label }), capacityLeft2), delegate() { thing.SetForbidden(false, false); Job job = new Job(jobDef, thing); job.count = thing.stackCount; job.checkEncumbrance = (packTarget == pawn); pawn.jobs.TryTakeOrderedJob(job, JobTag.Misc); }, MenuOptionPriority.High, null, null, 0f, null, null), pawn, thing, "ReservedBy")); } opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption("LoadIntoCaravanSome".Translate(new NamedArgument[] { thing.LabelNoCount }), delegate() { int to = Mathf.Min(MassUtility.CountToPickUpUntilOverEncumbered(packTarget, thing), thing.stackCount); Dialog_Slider window = new Dialog_Slider(delegate(int val) { float capacityLeft3 = capacityLeft - (float)val * thing.GetStatValue(StatDefOf.Mass, true); return(CaravanFormingUtility.AppendOverweightInfo(string.Format("LoadIntoCaravanCount".Translate(new NamedArgument[] { thing.LabelNoCount }), val), capacityLeft3)); }, 1, to, delegate(int count) { thing.SetForbidden(false, false); Job job = new Job(jobDef, thing); job.count = count; job.checkEncumbrance = (packTarget == pawn); pawn.jobs.TryTakeOrderedJob(job, JobTag.Misc); }, int.MinValue); Find.WindowStack.Add(window); }, MenuOptionPriority.High, null, null, 0f, null, null), pawn, thing, "ReservedBy")); } } } } if (opts.Count == 0) { opts.Add(new FloatMenuOption("NoneBrackets".Translate(), null) { Disabled = true }); } return(opts); }
private static bool CoversHead(this Apparel a) { return(a.def.apparel.bodyPartGroups.Any(g => g == BodyPartGroupDefOf.Eyes || g == BodyPartGroupDefOf.UpperHead || g == BodyPartGroupDefOf.FullHead)); }
public override GizmoResult GizmoOnGUI(UnityEngine.Vector2 topLeft) { Rect overRect = new Rect(topLeft.x, topLeft.y, curWidth, Height); Widgets.DrawWindowBackground(overRect); //Equipment slot Pawn wearer = backpack.wearer; ThingWithComps dummy; Rect thingIconRect = new Rect(topLeft.x, topLeft.y, widthPerItem, Height / 2); int numOfCurItem = 0; List <Thing> things = wearer.inventory.container.ToList(); //Draw Gizmo for (int i = 0; i < numOfMaxItemsPerRow * numOfRow; i++) { if (i >= backpack.MaxItem) { thingIconRect.x = topLeft.x + widthPerItem * (i % numOfMaxItemsPerRow); thingIconRect.y = topLeft.y + (Height / 2) * (i / numOfMaxItemsPerRow); Widgets.DrawTextureFitted(thingIconRect, NoAvailableTex, 1.0f); continue; } if (i >= things.Count) { thingIconRect.x = topLeft.x + widthPerItem * (i % numOfMaxItemsPerRow); thingIconRect.y = topLeft.y + (Height / 2) * (i / numOfMaxItemsPerRow); Widgets.DrawTextureFitted(thingIconRect, EmptyTex, 1.0f); continue; } Thing item = things[i]; Widgets.DrawBox(thingIconRect, 1); Widgets.ThingIcon(thingIconRect, item); if (thingIconRect.Contains(Event.current.mousePosition)) { Widgets.DrawTextureFitted(thingIconRect, FilledTex, 1.0f); } //Interaction with item if (Widgets.ButtonInvisible(thingIconRect)) { thingIconSound = SoundDefOf.Click; if (Event.current.button == 0) { //Weapon if (item.def.equipmentType == EquipmentType.Primary) { if (wearer.equipment.Primary != null) { wearer.equipment.TryTransferEquipmentToContainer(wearer.equipment.Primary, wearer.inventory.container, out dummy); } else { backpack.numOfSavedItems--; } wearer.equipment.AddEquipment(item as ThingWithComps); wearer.inventory.container.Remove(item as ThingWithComps); if (wearer.jobs.curJob != null) { wearer.jobs.EndCurrentJob(JobCondition.InterruptForced); } } //Medicine else if (item.def.thingCategories.Contains(medicine)) { if (wearer.workSettings.WorkIsActive(WorkTypeDefOf.Doctor)) { Designator_ApplyMedicine designator = new Designator_ApplyMedicine(); designator.medicine = item; designator.doctor = wearer; designator.icon = item.def.uiIcon; designator.activateSound = SoundDef.Named("Click"); DesignatorManager.Select(designator); } else { Messages.Message(txtNoDoctor.Translate(), MessageSound.RejectInput); Messages.Update(); thingIconSound = SoundDefOf.ClickReject; } } //Food else if (item.def.thingCategories.Contains(foodMeals)) { if (wearer.needs.food.CurCategory != HungerCategory.Fed) { Job jobNew = new Job(JobDefOf.Ingest, item); jobNew.maxNumToCarry = 1; jobNew.ignoreForbidden = true; wearer.drafter.TakeOrderedJob(jobNew); } else { Messages.Message(txtCannotEatAnymore.Translate(), MessageSound.RejectInput); Messages.Update(); thingIconSound = SoundDefOf.ClickReject; } } //Apparel else if (item is Apparel) { //if (!wearer.apparel.CanWearWithoutDroppingAnything(item.def)) // wearer.apparel.WornApparel.Find(apparel => apparel.def.apparel.layers.Any); for (int index = wearer.apparel.WornApparel.Count - 1; index >= 0; --index) { Apparel ap = wearer.apparel.WornApparel[index]; if (!ApparelUtility.CanWearTogether(item.def, ap.def)) { Apparel resultingAp; wearer.apparel.TryDrop(ap, out resultingAp, wearer.Position, false); wearer.inventory.container.TryAdd(resultingAp); backpack.numOfSavedItems++; } } wearer.apparel.Wear(item as Apparel); wearer.inventory.container.Remove(item as ThingWithComps); backpack.numOfSavedItems--; } else { //Add another type of item you want to interact } } else if (Event.current.button == 1) { List <FloatMenuOption> options = new List <FloatMenuOption>(); options.Add(new FloatMenuOption(txtThingInfo, () => { Find.WindowStack.Add((Window) new Dialog_InfoCard(item)); })); options.Add(new FloatMenuOption(txtDropThing, () => { Thing dummy1; wearer.inventory.container.TryDrop(item, wearer.Position, ThingPlaceMode.Near, out dummy1); })); Find.WindowStack.Add((Window) new FloatMenu(options, item.LabelCap, false)); } SoundStarter.PlayOneShotOnCamera(thingIconSound); } numOfCurItem++; thingIconRect.x = topLeft.x + widthPerItem * (numOfCurItem % numOfMaxItemsPerRow); thingIconRect.y = topLeft.y + (Height / 2) * (numOfCurItem / numOfMaxItemsPerRow); } if (numOfCurItem == 0) { Rect textRect = new Rect(topLeft.x + Width / 2 - textWidth / 2, topLeft.y + Height / 2 - textHeight / 2, textWidth, textHeight); Widgets.Label(textRect, txtNoItem.Translate()); } return(new GizmoResult(GizmoState.Clear)); }
public void RemoveRestraintsEffects( Pawn pawn, Apparel restraints ) { foreach( var bodyPartGroup in restraints.def.apparel.bodyPartGroups ) { if( bodyPartGroup == Data.BodyPartGroupDefOf.Hands ) { RemoveHediffDefOn( pawn, Data.HediffDefOf.HandCuffed, pawn.health.hediffSet.GetBodyPartRecord( BodyPartDefOf.LeftHand ) ); RemoveHediffDefOn( pawn, Data.HediffDefOf.HandCuffed, pawn.health.hediffSet.GetBodyPartRecord( BodyPartDefOf.RightHand ) ); } if( bodyPartGroup == BodyPartGroupDefOf.Legs ) { RemoveHediffDefOn( pawn, Data.HediffDefOf.LegShackled, pawn.health.hediffSet.GetBodyPartRecord( BodyPartDefOf.LeftLeg ) ); RemoveHediffDefOn( pawn, Data.HediffDefOf.LegShackled, pawn.health.hediffSet.GetBodyPartRecord( BodyPartDefOf.RightLeg ) ); } } }
protected override IEnumerable <Toil> MakeNewToils() { yield return(Toils_General.Wait(10, TargetIndex.None)); yield return(new Toil { initAction = delegate() { Thing MarkedThing = CompUnloadChecker.getFirstMarked(pawn); if (MarkedThing == null) { EndJobWith(JobCondition.Succeeded); return; } // if (pawn.equipment.Contains(MarkedThing)) { Equipment = (ThingWithComps)MarkedThing; Apparel = null; } else { Apparel = pawn.apparel.Contains(MarkedThing) ? (Apparel)MarkedThing : null; Equipment = null; } ThingCount firstUnloadableThing = MarkedThing == null ? default(ThingCount) : new ThingCount(MarkedThing, MarkedThing.stackCount); IntVec3 c; if (!StoreUtility.TryFindStoreCellNearColonyDesperate(firstUnloadableThing.Thing, pawn, out c)) { Thing thing; pawn.inventory.innerContainer.TryDrop(firstUnloadableThing.Thing, ThingPlaceMode.Near, firstUnloadableThing.Count, out thing, null, null); EndJobWith(JobCondition.Succeeded); return; } job.SetTarget(TargetIndex.A, firstUnloadableThing.Thing); job.SetTarget(TargetIndex.B, c); countToDrop = firstUnloadableThing.Count; } }); yield return(Toils_Reserve.Reserve(TargetIndex.B, 1, -1, null)); yield return(Toils_Goto.GotoCell(TargetIndex.B, PathEndMode.Touch).FailOnDestroyedOrNull(TargetIndex.A).FailOn(delegate() { return !stillUnloadable(pawn.CurJob.GetTarget(TargetIndex.A).Thing); })); //preintiating unequip-delay Toil unequip = new Toil { initAction = delegate() { if (Equipment != null) { pawn.equipment.TryTransferEquipmentToContainer(Equipment, pawn.inventory.innerContainer); } else if (Apparel != null) { ThingOwner <Apparel> a = Traverse.Create(pawn.apparel).Field("wornApparel").GetValue <ThingOwner <Apparel> >(); a.TryTransferToContainer(Apparel, pawn.inventory.innerContainer); } } }; //if equiped, wait unequipping time Toil wait = new Toil(); wait.initAction = delegate() { ticker = 0; duration = Apparel != null?Apparel.GetStatValue(StatDefOf.EquipDelay, true) * 60f : Equipment != null ? 30 : 0; pawn.pather.StopDead(); }; wait.tickAction = delegate() { if (ticker >= duration) { ReadyForNextToil(); } ticker++; }; wait.defaultCompleteMode = ToilCompleteMode.Never; wait.WithProgressBar(TargetIndex.A, () => ticker / duration); //unequip to inventory yield return(wait); yield return(unequip); //hold in hands yield return(new Toil { initAction = delegate() { Thing thing = job.GetTarget(TargetIndex.A).Thing; CompUnloadChecker c = thing.TryGetComp <CompUnloadChecker>(); if (c == null || !c.ShouldUnload) { EndJobWith(JobCondition.Incompletable); return; } if (thing == null || !pawn.inventory.innerContainer.Contains(thing)) { EndJobWith(JobCondition.Incompletable); return; } if (!pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation) || !thing.def.EverStorable(false)) { pawn.inventory.innerContainer.TryDrop(thing, ThingPlaceMode.Near, countToDrop, out thing, null, null); EndJobWith(JobCondition.Succeeded); } else { pawn.inventory.innerContainer.TryTransferToContainer(thing, pawn.carryTracker.innerContainer, countToDrop, out thing, true); job.count = countToDrop; job.SetTarget(TargetIndex.A, thing); } thing.SetForbidden(false, false); } }); Toil carryToCell = Toils_Haul.CarryHauledThingToCell(TargetIndex.B).FailOnDestroyedOrNull(TargetIndex.A).FailOn(delegate() { return(!stillUnloadable(pawn.CurJob.GetTarget(TargetIndex.A).Thing)); }); yield return(carryToCell); yield return(Toils_Haul.PlaceHauledThingInCell(TargetIndex.B, carryToCell, true)); yield break; }
public float CalculateApparelScoreRawInsulationColdAjust(Apparel ap) { float num3 = 1f; if (this.needWarmCurve != null) { float statValueAbstract = ap.GetStatValue(StatDefOf.Insulation_Cold); num3 *= this.needWarmCurve.Evaluate(statValueAbstract); } if (this.needCoolCurve != null) { float statValueAbstract = ap.GetStatValue(StatDefOf.Insulation_Heat); num3 *= this.needCoolCurve.Evaluate(statValueAbstract); } return num3; }
static void Prefix(Pawn_ApparelTracker __instance, Apparel apparel) { WorldComp.ApparelColorTracker.PersistColor(apparel); ColorApparel(__instance.pawn, apparel); }
public float GetStatValue(Apparel apparel, Saveable_StatDef stat) { float baseStat = apparel.GetStatValue(stat.statDef, true); float currentStat = baseStat; currentStat += apparel.def.equippedStatOffsets.GetStatOffsetFromList(stat.statDef); PawnCalcForApparel.DoApparelScoreRawStatsHandlers(pawn, apparel, stat.statDef, ref currentStat); if (baseStat == 0) return currentStat; else return currentStat / baseStat; }
static void Postfix(Apparel apparel) { WorldComp.ApparelColorTracker.ResetColor(apparel); }
private bool CalculateApparelScoreGain(Apparel apparel, float score, out float gain) { if (apparel.def == ThingDefOf.Apparel_PersonalShield && this.pawn.equipment.Primary != null && !this.pawn.equipment.Primary.def.Verbs[0].MeleeRange) { gain = -1000f; return false; } gain = score; for (int i = 0; i < this.calculedApparelItems.Count; i++) { Apparel wornApparel = this.calculedApparelItems[i]; if (!ApparelUtility.CanWearTogether(wornApparel.def, apparel.def)) { if (!pawn.outfits.forcedHandler.AllowedToAutomaticallyDrop(wornApparel)) return false; gain -= this.calculedApparelScore[i]; } } return true; }
static void Postfix(Pawn pawn, ref Job __result) { #if BETTER_OUTFIT Log.Warning("Begin JobGiver_OptimizeApparel.Postfix(Pawn: " + pawn.Name.ToStringShort + " Job: " + ((__result == null) ? "<null>" : __result.ToString()) + ")"); #endif if (!DoDressersHaveApparel()) { return; } Thing thing = null; float baseApparelScore = 0f; if (__result != null && __result.targetA.Thing is Apparel) { thing = __result.targetA.Thing; baseApparelScore = JobGiver_OptimizeApparel.ApparelScoreGain(pawn, thing as Apparel); if (thing == null) { baseApparelScore = 0f; } else { #if BETTER_OUTFIT Log.Message(" Game Found Better Apparel: " + ((thing == null) ? "<null>" : thing.Label) + " Score: " + baseApparelScore); #endif } } Apparel a = null; Building_Dresser containingDresser = null; #if BETTER_OUTFIT Log.Message(" Loop Through Dressers:"); #endif foreach (Building_Dresser dresser in WorldComp.DressersToUse) { #if TRACE && BETTER_OUTFIT Log.Message(" Dresser: " + dresser.Label); #endif float score = baseApparelScore; if (dresser.FindBetterApparel(ref score, ref a, pawn, pawn.outfits.CurrentOutfit)) { thing = a; baseApparelScore = score; containingDresser = dresser; #if BETTER_OUTFIT Log.Message(" Dresser Found Better Apparel: " + ((a == null) ? "<null>" : a.Label) + " Score: " + baseApparelScore); #endif } } #if BETTER_OUTFIT Log.Message(" Best Apparel: " + ((a == null) ? "<null>" : a.Label) + " Score: " + baseApparelScore); #endif if (a != null && containingDresser != null) { __result = new Job(containingDresser.wearApparelFromStorageJobDef, containingDresser, a); } #if BETTER_OUTFIT Log.Warning("End JobGiver_OptimizeApparel.Postfix"); #endif }
private void LooseConflict(Apparel apprel) { this.optimized = false; this.totalStats = null; int index = this.calculedApparelItems.IndexOf(apprel); if (index == -1) Log.Warning("Warning on LooseConflict loser didnt have the apparel"); this.calculedApparelItems.RemoveAt(index); this.calculedApparelScore.RemoveAt(index); }
static bool Prefix(ref float __result, JobGiver_OptimizeApparel __instance, Pawn pawn, Apparel ap) { Log.Message("1 pawn is " + ((pawn == null) ? "null" : "not null")); if (pawn != null) { return(true); } Log.Message("2"); if (HitPointsPercentScoreFactorCurve == null) { HitPointsPercentScoreFactorCurve = typeof(JobGiver_OptimizeApparel).GetField("HitPointsPercentScoreFactorCurve", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null) as SimpleCurve; InsulationColdScoreFactorCurve_NeedWarm = typeof(JobGiver_OptimizeApparel).GetField("InsulationColdScoreFactorCurve_NeedWarm", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null) as SimpleCurve; NeedWarmthFI = typeof(JobGiver_OptimizeApparel).GetField("neededWarmth", BindingFlags.Static | BindingFlags.NonPublic); } Log.Message("HitPointsPercentScoreFactorCurve is " + ((HitPointsPercentScoreFactorCurve == null) ? "null" : "not null")); Log.Message("InsulationColdScoreFactorCurve_NeedWarm is " + ((InsulationColdScoreFactorCurve_NeedWarm == null) ? "null" : "not null")); Log.Message("NeedWarmthFI is " + ((NeedWarmthFI == null) ? "null" : "not null")); Log.Message("NeedWarmth is " + NeedWarmthFI.GetValue(null)); float result = 0.1f + ap.GetStatValue(StatDefOf.ArmorRating_Sharp) + ap.GetStatValue(StatDefOf.ArmorRating_Blunt); if (ap.def.useHitPoints) { float x = (float)ap.HitPoints / (float)ap.MaxHitPoints; result *= HitPointsPercentScoreFactorCurve.Evaluate(x); } result += ap.GetSpecialApparelScoreOffset(); float num3 = 1f; if ((NeededWarmth)NeedWarmthFI.GetValue(null) == NeededWarmth.Warm) { float statValue = ap.GetStatValue(StatDefOf.Insulation_Cold); num3 *= InsulationColdScoreFactorCurve_NeedWarm.Evaluate(statValue); } result *= num3; if (ap.WornByCorpse) { result -= 0.5f; if (result > 0f) { result *= 0.1f; } } if (ap.Stuff == ThingDefOf.Human.race.leatherDef) { result -= 0.5f; if (result > 0f) { result *= 0.1f; } } __result = result; return(false); }
static float ApparelScoreRawInsulation(Pawn pawn, Apparel apparel, ExtendedOutfit outfit, NeededWarmth neededWarmth) { float insulation; if (outfit.targetTemperaturesOverride) { // NOTE: We can't rely on the vanilla check for taking off gear for temperature, because // we need to consider all the wardrobe changes taken together; each individual change may // note push us over the thresholds, but several changes together may. // Return 1 for temperature offsets here, we'll look at the effects of any gear we have to // take off below. // NOTE: This is still suboptimal, because we're still only considering one piece of apparel // to wear at each time. A better solution would be reducing the problem to a series of linear // equations, and then solving that system. // I'm not sure that's feasible at all; first off for simple computational reasons: the linear // system to solve would be fairly massive, optimizing for dozens of pawns and hundreds of pieces // of gear simultaneously. Second, many of the stat functions aren't actually linear, and would // have to be made to be linear. bool currentlyWorn = pawn.apparel.WornApparel.Contains(apparel); var currentRange = pawn.ComfortableTemperatureRange(); var candidateRange = currentRange; if (outfit.AutoTemp) { var seasonalTemp = pawn.Map.mapTemperature.SeasonalTemp; outfit.targetTemperatures = new FloatRange(seasonalTemp - outfit.autoTempOffset, seasonalTemp + outfit.autoTempOffset); } var targetRange = outfit.targetTemperatures; var apparelOffset = GetInsulationStats(apparel); // effect of this piece of apparel candidateRange.min += apparelOffset.min; candidateRange.max += apparelOffset.max; if (!currentlyWorn) { foreach (var otherApparel in pawn.apparel.WornApparel) { // effect of taking off any other apparel that is incompatible if (!ApparelUtility.CanWearTogether(apparel.def, otherApparel.def, pawn.RaceProps.body)) { var otherInsulationRange = GetInsulationStats(otherApparel); candidateRange.min -= otherInsulationRange.min; candidateRange.max -= otherInsulationRange.max; } } } // did we get any closer to our target range? (smaller distance is better, negative values are overkill). var currentDistance = new FloatRange(Mathf.Max(currentRange.min - targetRange.min, 0f), Mathf.Max(targetRange.max - currentRange.max, 0f)); var candidateDistance = new FloatRange(Mathf.Max(candidateRange.min - targetRange.min, 0f), Mathf.Max(targetRange.max - candidateRange.max, 0f)); // improvement in distances insulation = InsulationFactorCurve.Evaluate(currentDistance.min - candidateDistance.min) + InsulationFactorCurve.Evaluate(currentDistance.max - candidateDistance.max); #if DEBUG Log.Message($"{pawn.Name.ToStringShort} :: {apparel.LabelCap}\n" + $"\ttarget range: {targetRange}, current range: {currentRange}, candidate range {candidateRange}\n" + $"\tcurrent distance: {currentDistance}, candidate distance: {candidateDistance}\n" + $"\timprovement: {(currentDistance.min - candidateDistance.min) + (currentDistance.max - candidateDistance.max)}, insulation score: {insulation}\n"); #endif } else { float statValue; if (neededWarmth == NeededWarmth.Warm) { statValue = apparel.GetStatValue(StatDefOf.Insulation_Cold, true); insulation = InsulationTemperatureScoreFactorCurve_Need.Evaluate(statValue); } else if (neededWarmth == NeededWarmth.Cool) { statValue = apparel.GetStatValue(StatDefOf.Insulation_Heat, true); insulation = InsulationTemperatureScoreFactorCurve_Need.Evaluate(statValue); } else { insulation = 1f; } } return(insulation); }
private void DrawThingRowModded(ref float y, float width, Apparel apparel) { if (apparel == null) { this.DrawThingRowVanilla(ref y, width, apparel); return; } Rect rect = new Rect(0f, y, width, ThingRowHeight); if (Mouse.IsOver(rect)) { GUI.color = HighlightColor; GUI.DrawTexture(rect, TexUI.HighlightTex); } GUI.color = ThingLabelColor; // LMB doubleclick if (Widgets.ButtonInvisible(rect)) { // Left Mouse Button Menu if (Event.current.button == 0) { Find.WindowStack.Add(new Window_Pawn_ApparelDetail(this.SelPawn, apparel)); } // RMB menu if (Event.current.button == 1) { List <FloatMenuOption> floatOptionList = new List <FloatMenuOption> { new FloatMenuOption( "ThingInfo".Translate(), delegate { Find.WindowStack.Add(new Dialog_InfoCard(apparel)); }) }; if (this.CanControl) { floatOptionList.Add( new FloatMenuOption( "OutfitterComparer".Translate(), delegate { Find.WindowStack.Add( new Dialog_PawnApparelComparer(this.SelPawnForGear, apparel)); })); Action dropApparel = delegate { SoundDefOf.Tick_High.PlayOneShotOnCamera(); this.InterfaceDrop(apparel); }; Action dropApparelHaul = delegate { SoundDefOf.Tick_High.PlayOneShotOnCamera(); this.InterfaceDropHaul(apparel); }; floatOptionList.Add(new FloatMenuOption("DropThing".Translate(), dropApparel)); floatOptionList.Add(new FloatMenuOption("DropThingHaul".Translate(), dropApparelHaul)); } FloatMenu window = new FloatMenu(floatOptionList, string.Empty); Find.WindowStack.Add(window); } } if (apparel.def.DrawMatSingle != null && apparel.def.DrawMatSingle.mainTexture != null) { Widgets.ThingIcon(new Rect(4f, y + 5f, ThingIconSize, ThingIconSize), apparel); } Text.Anchor = TextAnchor.MiddleLeft; GUI.color = ThingLabelColor; Rect textRect = new Rect(ThingLeftX, y, width - ThingLeftX, ThingRowHeight - Text.LineHeight); Rect scoreRect = new Rect(ThingLeftX, textRect.yMax, width - ThingLeftX, Text.LineHeight); ApparelStatCache conf = this.SelPawn.GetApparelStatCache(); string text = apparel.LabelCap; string textScore = Math.Round(conf.ApparelScoreRaw(apparel), 2).ToString("N2"); if (apparel is Apparel && this.SelPawn.outfits != null && this.SelPawn.outfits.forcedHandler.IsForced(apparel)) { text = text + ", " + "ApparelForcedLower".Translate(); Widgets.Label(textRect, text); } else { GUI.color = new Color(0.75f, 0.75f, 0.75f); if (apparel.def.useHitPoints) { float x = apparel.HitPoints / (float)apparel.MaxHitPoints; if (x < 0.5f) { GUI.color = Color.yellow; } if (x < 0.2f) { GUI.color = Color.red; } } Widgets.Label(textRect, text); GUI.color = Color.white; Widgets.Label(scoreRect, textScore); } y += ThingRowHeight; }
public static bool Replacement(Pawn_ApparelTracker __instance, ref bool __result, Apparel ap, ref Apparel resultingAp, ThingOwner <Apparel> ___wornApparel) { if (!__instance.pawn.IsGuest()) { return(true); } __result = ___wornApparel.TryTransferToContainer(ap, __instance.pawn.inventory.innerContainer); resultingAp = ap; return(false); //List<Apparel> wornApparel = __instance.pawn.apparel.WornApparel; //__result = true; //for (int i = wornApparel.Count - 1; i >= 0; i--) //{ // if (!ApparelUtility.CanWearTogether(ap.def, wornApparel[i].def, __instance.pawn.RaceProps.body)) // { // var apparel = wornApparel[i]; // __instance.pawn.apparel.Remove(apparel); // if (__instance.pawn.inventory.innerContainer.TryAdd(apparel)) // { // Log.Message(__instance.pawn.Name.ToStringShort + " should have taken " + apparel.Label + " to his inventory."); // __instance.pawn.apparel.Notify_ApparelRemoved(apparel); // resultingAp = apparel; // } // else // { // Log.Error(__instance.pawn + " could not add to inventory " + apparel.ToStringSafe()); // resultingAp = apparel; // } // break; // } //} //return false; }
public static void DoApparelScoreRawStatsHandlers(Pawn pawn, Apparel apparel, StatDef statDef, ref float num) { if (PawnCalcForApparel.ApparelScoreRawStatsHandlers != null) PawnCalcForApparel.ApparelScoreRawStatsHandlers(pawn, apparel, statDef, ref num); }
internal static void Notify_WornApparelDestroyed(this Pawn_ApparelTracker _this, Apparel apparel) { _this.Remove(apparel); CE_Utility.TryUpdateInventory(_this.pawn); // Apparel was destroyed, update inventory }
// Verse.MentalBreaker /* * PreFix * * By calling this code first, we can check if the pawn involved is wearing a straitjacket. * If the colonist is wearing a straitjacket, do not trigger a standard mental break. * Instead, declare te mental break averted. * */ public static bool TryDoRandomMoodCausedMentalBreakPreFix(MentalBreaker __instance) { //Declare variables for the process var pawn = (Pawn)AccessTools.Field(typeof(MentalBreaker), "pawn").GetValue(__instance); //IsWearingStraitJacket bool isWearingStraitJacket = false; if (pawn.apparel != null) { foreach (Apparel clothing in pawn.apparel.WornApparel) { if (clothing.def == StraitjacketDefOf.ROM_Straitjacket) { isWearingStraitJacket = true; } } } if (!isWearingStraitJacket) { return(true); } Thought thought = (Thought)AccessTools.Method(typeof(MentalBreaker), "RandomMentalBreakReason").Invoke(__instance, new object[] { }); IEnumerable <MentalBreakDef> mentalBreaksList = (IEnumerable <MentalBreakDef>)AccessTools.Property(typeof(MentalBreaker), "CurrentPossibleMoodBreaks").GetValue(__instance, null); string reason = (thought == null) ? null : thought.LabelCap; //Reset the mind state because we probably tried to start something before this process started. pawn.mindState.mentalStateHandler.Reset(); MentalBreakDef mentalBreakDef; if (!(mentalBreaksList.TryRandomElementByWeight((MentalBreakDef d) => d.Worker.CommonalityFor(pawn), out mentalBreakDef))) { return(false); } if (Rand.Range(0, 100) < 95) //95% of the time { Cthulhu.Utility.DebugReport("StraitJacket :: Mental Break Triggered"); MentalStateDef stateDef = mentalBreakDef.mentalState; /* string label = "MentalBreakAvertedLetterLabel".Translate() + ": " + stateDef.beginLetterLabel; * string text = string.Format(stateDef.beginLetter, pawn.Label).AdjustedFor(pawn).CapitalizeFirst(); * if (reason != null) * { * text = text + "\n\n" + "StraitjacketBenefit".Translate(new object[] * { * pawn.gender.GetPossessive(), * pawn.gender.GetObjective(), * pawn.gender.GetObjective() + "self" * }); * } * Find.LetterStack.ReceiveLetter(label, text, stateDef.beginLetterDef, pawn, null);*/ Log.Message(pawn.Label + " was going to break, and the straitjacket averted it. Hiding the message."); return(false); } //StripStraitJacket if (pawn.apparel != null) { Apparel droppedClothing = null; List <Apparel> clothingList = new List <Apparel>(pawn.apparel.WornApparel); foreach (Apparel clothing in clothingList) { if (clothing.def == StraitjacketDefOf.ROM_Straitjacket) { pawn.apparel.TryDrop(clothing, out droppedClothing, pawn.Position, true); } } } Messages.Message("StraitjacketEscape".Translate(pawn.LabelCap), MessageTypeDefOf.ThreatBig);// MessageSound.SeriousAlert); pawn.mindState.mentalStateHandler.TryStartMentalState(mentalBreakDef.mentalState, reason, false, true, null); return(false); }
/// <summary> /// Performs the actual melee attack part. Awards XP, calculates and applies whether an attack connected and the outcome. /// </summary> /// <returns>True if the attack connected, false otherwise</returns> protected override bool TryCastShot() { Pawn casterPawn = CasterPawn; if (casterPawn.stances.FullBodyBusy) { return(false); } Thing targetThing = currentTarget.Thing; if (!CanHitTarget(targetThing)) { Log.Warning(string.Concat(new object[] { casterPawn, " meleed ", targetThing, " from out of melee position." })); } casterPawn.rotationTracker.Face(targetThing.DrawPos); // Award XP as per vanilla bool targetImmobile = IsTargetImmobile(currentTarget); if (!targetImmobile && casterPawn.skills != null) { casterPawn.skills.Learn(SkillDefOf.Melee, HitXP * verbProps.AdjustedFullCycleTime(this, casterPawn), false); } // Hit calculations bool result; string moteText = ""; SoundDef soundDef; Pawn defender = targetThing as Pawn; //var hitRoll = Rand.Value; if (Rand.Chance(GetHitChance(targetThing))) { // Check for dodge if (!targetImmobile && !surpriseAttack && Rand.Chance(defender.GetStatValue(StatDefOf.MeleeDodgeChance))) { // Attack is evaded result = false; soundDef = SoundMiss(); CreateCombatLog((ManeuverDef maneuver) => maneuver.combatLogRulesDodge, false); moteText = "TextMote_Dodge".Translate(); defender.skills?.Learn(SkillDefOf.Melee, DodgeXP * verbProps.AdjustedFullCycleTime(this, casterPawn), false); } else { // Attack connects, calculate resolution //var resultRoll = Rand.Value; var counterParryBonus = 1 + (EquipmentSource?.GetStatValue(CE_StatDefOf.MeleeCounterParryBonus) ?? 0); var parryChance = GetComparativeChanceAgainst(defender, casterPawn, CE_StatDefOf.MeleeParryChance, BaseParryChance, counterParryBonus); if (!surpriseAttack && defender != null && CanDoParry(defender) && Rand.Chance(parryChance)) { // Attack is parried Apparel shield = defender.apparel.WornApparel.FirstOrDefault(x => x is Apparel_Shield); bool isShieldBlock = shield != null && Rand.Chance(ShieldBlockChance); Thing parryThing = isShieldBlock ? shield : defender.equipment?.Primary ?? defender; if (Rand.Chance(GetComparativeChanceAgainst(defender, casterPawn, CE_StatDefOf.MeleeCritChance, BaseCritChance))) { // Do a riposte DoParry(defender, parryThing, true); moteText = "CE_TextMote_Riposted".Translate(); CreateCombatLog((ManeuverDef maneuver) => maneuver.combatLogRulesDeflect, false); //placeholder defender.skills?.Learn(SkillDefOf.Melee, (CritXP + ParryXP) * verbProps.AdjustedFullCycleTime(this, casterPawn), false); } else { // Do a parry DoParry(defender, parryThing); moteText = "CE_TextMote_Parried".Translate(); CreateCombatLog((ManeuverDef maneuver) => maneuver.combatLogRulesMiss, false); //placeholder defender.skills?.Learn(SkillDefOf.Melee, ParryXP * verbProps.AdjustedFullCycleTime(this, casterPawn), false); } result = false; soundDef = SoundMiss(); // TODO Set hit sound to something more appropriate } else { BattleLogEntry_MeleeCombat log = CreateCombatLog((ManeuverDef maneuver) => maneuver.combatLogRulesHit, false); // Attack connects if (surpriseAttack || Rand.Chance(GetComparativeChanceAgainst(casterPawn, defender, CE_StatDefOf.MeleeCritChance, BaseCritChance))) { // Do a critical hit isCrit = true; ApplyMeleeDamageToTarget(currentTarget).AssociateWithLog(log); moteText = casterPawn.def.race.Animal ? "CE_TextMote_Knockdown".Translate() : "CE_TextMote_CriticalHit".Translate(); casterPawn.skills?.Learn(SkillDefOf.Melee, CritXP * verbProps.AdjustedFullCycleTime(this, casterPawn), false); } else { // Do a regular hit as per vanilla ApplyMeleeDamageToTarget(currentTarget).AssociateWithLog(log); } result = true; soundDef = targetThing.def.category == ThingCategory.Building ? SoundHitBuilding() : SoundHitPawn(); } } } else { // Attack missed result = false; soundDef = SoundMiss(); CreateCombatLog((ManeuverDef maneuver) => maneuver.combatLogRulesMiss, false); } if (!moteText.NullOrEmpty()) { MoteMaker.ThrowText(targetThing.PositionHeld.ToVector3Shifted(), targetThing.MapHeld, moteText); } soundDef.PlayOneShot(new TargetInfo(targetThing.PositionHeld, targetThing.MapHeld)); casterPawn.Drawer.Notify_MeleeAttackOn(targetThing); if (defender != null && !defender.Dead) { defender.stances.StaggerFor(95); if (casterPawn.MentalStateDef != MentalStateDefOf.SocialFighting || defender.MentalStateDef != MentalStateDefOf.SocialFighting) { defender.mindState.meleeThreat = casterPawn; defender.mindState.lastMeleeThreatHarmTick = Find.TickManager.TicksGame; } } casterPawn.rotationTracker.FaceCell(targetThing.Position); if (casterPawn.caller != null) { casterPawn.caller.Notify_DidMeleeAttack(); } return(result); }
public static void AddAppararelColorSelectionWidget(float left, float top, float width, ApparelColorSelectionsContainer apparelSelectionsContainer) { Text.Anchor = TextAnchor.MiddleCenter; if (apparelSelectionsContainer.Count == 0) { GUI.Label(new Rect(left, top, width, SelectionRowHeight), "ChangeDresser.NoClothingIsWorn".Translate(), MiddleCenter); } else { const float cellHeight = 40f; Rect apparelListRect = new Rect(left, top, width, 250f); Rect apparelScrollRect = new Rect(0f, 0f, width - 16f, apparelSelectionsContainer.Count * cellHeight + SelectionRowHeight); GUI.BeginGroup(apparelListRect); scrollPos = GUI.BeginScrollView(new Rect(GenUI.AtZero(apparelListRect)), scrollPos, apparelScrollRect); GUI.color = Color.white; Text.Font = GameFont.Small; if (Widgets.ButtonText(new Rect(20, 0, 100, SelectionRowHeight), "ChangeDresser.SelectAll".Translate())) { apparelSelectionsContainer.SelectAll(); } if (Widgets.ButtonText(new Rect(apparelScrollRect.width - 120, 0, 100, SelectionRowHeight), "ChangeDresser.DeselectAll".Translate())) { apparelSelectionsContainer.DeselectAll(); } Text.Font = GameFont.Medium; for (int i = 0; i < apparelSelectionsContainer.Count; ++i) { ApparelColorSelectionDTO dto = apparelSelectionsContainer[i]; Apparel apparel = dto.Apparel; GUI.BeginGroup(new Rect(0, SelectionRowHeight + 5f + i * cellHeight, apparelListRect.width, cellHeight)); Widgets.ThingIcon(new Rect(0f, 0f, 40f, cellHeight), apparel); Text.Font = GameFont.Small; Text.Anchor = TextAnchor.MiddleCenter; Rect textRect = new Rect(45f, 0f, apparelScrollRect.width - 90f, cellHeight); if (apparelSelectionsContainer.IsSelected(dto)) { GUI.color = Color.white; } else { GUI.color = Color.gray; } Widgets.Label(textRect, new GUIContent(apparel.Label, "ChangeDresser.SelectMultipleApparel".Translate())); if (Widgets.ButtonInvisible(textRect, false)) { apparelSelectionsContainer.Select(dto, Event.current.shift); } GUI.color = Color.white; if (Widgets.ButtonImage(new Rect(apparelScrollRect.width - 40f, 0, 32f, 16f), copyIconTexture)) { apparelSelectionsContainer.CopyColor = apparel.DrawColor; } if (apparelSelectionsContainer.CopyColorSelected) { if (Widgets.ButtonImage(new Rect(apparelScrollRect.width - 40f, 16f, 32f, 16f), pasteIconTexture)) { dto.SelectedColor = apparelSelectionsContainer.CopyColor; } } GUI.EndGroup(); } GUI.EndScrollView(); GUI.EndGroup(); /*if (Settings.UseColorPickerV2) * { * AddColorSelectorV2Widget(left, top + apparelListRect.height + 10f, width, apparelSelectionsContainer.SelectedApparel, apparelSelectionsContainer.ColorPresetsDTO); * } * else * {*/ AddColorSelectorWidget(left, top + apparelListRect.height + 10f, width, apparelSelectionsContainer.SelectedApparel, apparelSelectionsContainer.ColorPresetsDTO); //} } Text.Anchor = TextAnchor.UpperLeft; }
public ApparelItem(Apparel apparel, bool selected, ThingDef thingdef) { this.apparel = apparel; this.selected = selected; this.thingdef = thingdef; }
private static void ResolveHairDraw(RaceAddonComp racomp, RaceAddonThingDef thingDef, Apparel apparel) { if (racomp.drawHat) { if (thingDef.raceAddonSettings.graphicSetting.drawHair) { if (thingDef.raceAddonSettings.graphicSetting.drawHair_Exceptions.Find(x => x.thingDef == apparel.def) is var preset && preset != null) { if (preset.hairOption == 0) { racomp.drawUpperHair = false; racomp.drawLowerHair = false; } else if (preset.hairOption == 1) { racomp.drawUpperHair = false; racomp.drawLowerHair = true; } else if (preset.hairOption == 2) { racomp.drawUpperHair = true; racomp.drawLowerHair = false; } } else { racomp.drawUpperHair = true; racomp.drawLowerHair = true; } } else { if (thingDef.raceAddonSettings.graphicSetting.drawHair_Exceptions.Find(x => x.thingDef == apparel.def) is var preset && preset != null) { if (preset.hairOption == 0) { racomp.drawUpperHair = true; racomp.drawLowerHair = true; } else if (preset.hairOption == 1) { racomp.drawUpperHair = true; racomp.drawLowerHair = false; } else if (preset.hairOption == 2) { racomp.drawUpperHair = false; racomp.drawLowerHair = true; } }
public void RemoveApparelFromPawn( Pawn pawn, Apparel apparel, IntVec3 dropCell ) { // Try to unlock the apparel var compLock = apparel.TryGetComp<CompLockable>(); if( compLock != null ) { compLock.ChangeLockState( false ); } Apparel result = null; pawn.apparel.TryDrop( apparel, out result, dropCell, false ); if( apparel.IsRestraints() ) { RemoveRestraintsEffects( pawn, apparel ); } }
public float CalculateApparelScoreRawHitPointAjust(Apparel ap) { if (ap.def.useHitPoints) { float x = (float)ap.HitPoints / (float)ap.MaxHitPoints; return JobGiver_OptimizeApparelAutoEquip.HitPointsPercentScoreFactorCurve.Evaluate(x); } else return 1; }
public float CalculateApparelModifierRaw(Apparel ap) { float modHit = this.CalculateApparelScoreRawHitPointAjust(ap); float modCold = this.CalculateApparelScoreRawInsulationColdAjust(ap); if ((modHit < 0) && (modCold < 0)) return modHit * modCold * -1; else return modHit * modCold; }
public StoredApparel(Building_Dresser dresser, Apparel apparel) { this.Dresser = dresser; this.Apparel = apparel; }
private void DrawLine(ref Rect itemRect, Apparel apparelThing, string apparelText, float textureWidth, Pawn apparelEquipedThing, string apparelEquipedText, float apparelEquipedWidth, Pawn apparelOwnerThing, string apparelOwnerText, float apparelOwnerWidth, string apparelScoreText, float apparelScoreWidth, string apparelGainText, float apparelGainWidth) { Rect fieldRect; if (apparelThing != null) { fieldRect = new Rect(itemRect.xMin, itemRect.yMin, itemRect.height, itemRect.height); if (!string.IsNullOrEmpty(apparelText)) TooltipHandler.TipRegion(fieldRect, apparelText); if ((apparelThing.def.DrawMatSingle != null) && (apparelThing.def.DrawMatSingle.mainTexture != null)) Widgets.ThingIcon(fieldRect, apparelThing); if (Widgets.InvisibleButton(fieldRect)) { this.Close(true); Find.MainTabsRoot.EscapeCurrentTab(true); if (apparelEquipedThing != null) { Find.CameraMap.JumpTo(apparelEquipedThing.PositionHeld); Find.Selector.ClearSelection(); if (apparelEquipedThing.SpawnedInWorld) Find.Selector.Select(apparelEquipedThing, true, true); } else { Find.CameraMap.JumpTo(apparelThing.PositionHeld); Find.Selector.ClearSelection(); if (apparelThing.SpawnedInWorld) Find.Selector.Select(apparelThing, true, true); } return; } } else { if (!string.IsNullOrEmpty(apparelText)) { fieldRect = new Rect(itemRect.xMin, itemRect.yMin, textureWidth, itemRect.height); Text.Anchor = TextAnchor.UpperLeft; Widgets.Label(fieldRect, apparelText); } } itemRect.xMin += textureWidth; if (apparelEquipedThing != null) { fieldRect = new Rect(itemRect.xMin, itemRect.yMin, itemRect.height, itemRect.height); if (!string.IsNullOrEmpty(apparelEquipedText)) TooltipHandler.TipRegion(fieldRect, apparelEquipedText); if ((apparelEquipedThing.def.DrawMatSingle != null) && (apparelEquipedThing.def.DrawMatSingle.mainTexture != null)) Widgets.ThingIcon(fieldRect, apparelEquipedThing); if (Widgets.InvisibleButton(fieldRect)) { this.Close(true); Find.MainTabsRoot.EscapeCurrentTab(true); Find.CameraMap.JumpTo(apparelEquipedThing.PositionHeld); Find.Selector.ClearSelection(); if (apparelEquipedThing.SpawnedInWorld) Find.Selector.Select(apparelEquipedThing, true, true); return; } } else { if (!string.IsNullOrEmpty(apparelEquipedText)) { fieldRect = new Rect(itemRect.xMin, itemRect.yMin, apparelEquipedWidth, itemRect.height); Text.Anchor = TextAnchor.UpperLeft; Widgets.Label(fieldRect, apparelText); } } itemRect.xMin += apparelEquipedWidth; if (apparelOwnerThing != null) { fieldRect = new Rect(itemRect.xMin, itemRect.yMin, itemRect.height, itemRect.height); if (!string.IsNullOrEmpty(apparelOwnerText)) TooltipHandler.TipRegion(fieldRect, apparelOwnerText); if ((apparelOwnerThing.def.DrawMatSingle != null) && (apparelOwnerThing.def.DrawMatSingle.mainTexture != null)) Widgets.ThingIcon(fieldRect, apparelOwnerThing); if (Widgets.InvisibleButton(fieldRect)) { this.Close(true); Find.MainTabsRoot.EscapeCurrentTab(true); Find.CameraMap.JumpTo(apparelOwnerThing.PositionHeld); Find.Selector.ClearSelection(); if (apparelOwnerThing.SpawnedInWorld) Find.Selector.Select(apparelOwnerThing, true, true); return; } } else { if (!string.IsNullOrEmpty(apparelOwnerText)) { fieldRect = new Rect(itemRect.xMin, itemRect.yMin, apparelOwnerWidth, itemRect.height); Text.Anchor = TextAnchor.UpperLeft; Widgets.Label(fieldRect, apparelOwnerText); } } itemRect.xMin += apparelOwnerWidth; fieldRect = new Rect(itemRect.xMin, itemRect.yMin, apparelScoreWidth, itemRect.height); Text.Anchor = TextAnchor.UpperRight; Widgets.Label(fieldRect, apparelScoreText); if (apparelThing != null) { Text.Anchor = TextAnchor.UpperLeft; if (Widgets.InvisibleButton(fieldRect)) { this.Close(true); Find.MainTabsRoot.EscapeCurrentTab(true); Find.WindowStack.Add(new Dialog_PawnApparelDetail(this.pawn, apparelThing)); return; } } itemRect.xMin += apparelScoreWidth; Text.Anchor = TextAnchor.UpperRight; Widgets.Label(new Rect(itemRect.xMin, itemRect.yMin, apparelGainWidth, itemRect.height), apparelGainText); itemRect.xMin += apparelGainWidth; }
public bool CalculateApparelScoreGain(Apparel apparel, out float gain) { if (this.calculedApparelItems == null) this.InitializeCalculedApparelScoresFromWornApparel(); return this.CalculateApparelScoreGain(apparel, this.CalculateApparelScoreRaw(apparel), out gain); }
public float CalculateApparelScoreRaw(Apparel apparel) { return this.CalculateApparelScoreRawStats(apparel) * this.CalculateApparelModifierRaw(apparel); }
private static void ResolveHatDraw(RaceAddonComp racomp, RaceAddonThingDef thingDef, Apparel apparel) { if (thingDef.raceAddonSettings.graphicSetting.drawSize[racomp.drawSize].hideHat) { racomp.drawHat = false; return; } if (thingDef.raceAddonSettings.graphicSetting.drawHat) { if (thingDef.raceAddonSettings.graphicSetting.drawHat_Exceptions.Contains(apparel.def)) { racomp.drawHat = false; } else { racomp.drawHat = true; } } else { if (thingDef.raceAddonSettings.graphicSetting.drawHat_Exceptions.Contains(apparel.def)) { racomp.drawHat = true; } else { racomp.drawHat = false; } } }