private static void ValidateApparelForChangedPawn([NotNull] Pawn pawn, [NotNull] ThingDef oldRace) { Pawn_ApparelTracker apparel = pawn.apparel; if (apparel == null) { return; } _apparelCache.Clear(); _apparelCache.AddRange(apparel.WornApparel.MakeSafe()); foreach (Apparel ap in _apparelCache) //use a copy so we can remove them safely while iterating { if (!ApparelUtility.HasPartsToWear(pawn, ap.def)) { if (DebugLogUtils.ShouldLog(LogLevel.Messages)) { Log.Message($"removing {ap.Label}"); } if (apparel.TryDrop(ap)) { apparel.Remove(ap); } } } }
public override bool GizmoDisabled(out string reason) { if (base.GizmoDisabled(out reason)) { return(true); } if (pawn.GetMutagenicAbilityLevel() < def.level) { reason = AbilityUtilities.NOT_HIGH_ENOUGH_LEVEL_LABEL.Translate(def.level); return(true); } var entropyTracker = pawn.GetComp <MutagenicEntropyTracker>(); if (entropyTracker == null) { reason = $"{pawn.Name} does not have a mutagenic entropy tracker! this should not happen!"; DebugLogUtils.Warning(reason); return(true); } if (!entropyTracker.CanAcceptEntropyAmount(def.GetMutagenicEntropyGain())) { reason = AbilityUtilities.TOO_MUCH_ENTROPY_LABEL.Translate(def.label); return(true); } return(false); }
/// <summary> /// called every tick /// </summary> public override void CompTick() { base.CompTick(); if (_triggered) { return; } _triggered = true; try { var pawn = (Pawn)parent; var sTracker = pawn?.GetSapienceTracker(); if (sTracker == null) { DebugLogUtils.Warning($"unable to get sapience tracker on pawn {pawn?.LabelShort ?? "NULL"}"); return; } MakeMergedPawn(sTracker); } catch (InvalidCastException e) { Log.Error($"unable to case {parent.GetType().Name} to {nameof(Pawn)}!\n{e}"); } }
/// <summary> /// Posts the spawn setup. /// </summary> /// <param name="respawningAfterLoad">if set to <c>true</c> [respawning after load].</param> public override void PostSpawnSetup(bool respawningAfterLoad) { base.PostSpawnSetup(respawningAfterLoad); if (respawningAfterLoad) { return; } try { var pawn = (Pawn)parent; var sTracker = pawn?.GetSapienceTracker(); if (sTracker == null) { DebugLogUtils.Warning($"unable to get sapience tracker on pawn {pawn?.LabelShort ??"NULL"}"); return; } MakeMergedPawn(sTracker); } catch (InvalidCastException e) { Log.Error($"unable to case {parent.GetType().Name} to {nameof(Pawn)}!\n{e}"); } }
static void AddInteractionThoughts([NotNull] Pawn recipient, [NotNull] InteractionDef intDef, bool __result) { if (!__result) { return; } if ((recipient.IsFormerHuman() || recipient.GetSapienceState()?.StateDef == SapienceStateDefOf.Animalistic) && recipient.needs?.mood != null) { var memory = intDef.GetModExtension <InstinctEffector>()?.thought; //hacky, should come up with a better solution eventually if (memory == null) { return; } if (DebugLogUtils.ShouldLog(LogLevel.Messages)) { var msg = $"giving {recipient.Name} memory {memory.defName}"; Log.Message(msg); } //social thoughts to? recipient.TryGainMemory(memory); } }
private void TryAddMutationsToPawn([NotNull] Pawn original, [CanBeNull] Hediff requestCause, [NotNull] PawnKindDef requestOutputDef) { MorphDef mDef = null; if (requestCause != null) //first check the cause { foreach (MorphDef morphDef in MorphDef.AllDefs) { if (morphDef.fullTransformation == requestCause.def || morphDef.partialTransformation == requestCause.def) { mDef = morphDef; goto applyMutations; //ugly, but it's the easiest solution } } } mDef = MorphUtilities.TryGetBestMorphOfAnimal(requestOutputDef.race); if (mDef == null) { DebugLogUtils.LogMsg(LogLevel.Messages, $"could not apply mutations to {original} with cause {requestCause?.def?.defName ?? "NULL"} and target {requestOutputDef.defName}"); return; } applyMutations: MutationUtilities.AddAllMorphMutations(original, mDef); }
/// <summary> /// Exits the current sapience state. /// </summary> public void ExitState() { if (_sapienceState == null) { DebugLogUtils.Warning($"trying to exit sapience state in {Pawn.Name} but they aren't in one"); return; } _sapienceState.Exit(); _sapienceState = null; }
/// <summary> /// Generates the genomes. /// </summary> internal static void GenerateGenomes() { if (_allImplicitGenomes != null) { Log.Error("trying to generate genomes more then once!"); return; } _allImplicitGenomes = new List <ThingDef>(); var catDef = PMThingCategoryDefOf.PM_MutationGenome; catDef.childThingDefs = catDef?.childThingDefs ?? new List <ThingDef>(); foreach (MutationCategoryDef mDef in AllImplicitGenomeMutations) { ThingDef tDef = GenerateMutationGenome(mDef); mDef.implicitGenomeDef = tDef; _allImplicitGenomes.Add(tDef); } foreach (PawnKindDef pk in AllPKsWithGenomes) { ThingDef tDef = GenerateAnimalGenome(pk); _genomeDict[pk] = tDef; _allImplicitGenomes.Add(tDef); } foreach (ThingDef allImplicitGenome in _allImplicitGenomes) { try { Init(allImplicitGenome); DefDatabase <ThingDef> .Add(allImplicitGenome); catDef.childThingDefs.Add(allImplicitGenome); } catch (Exception e) { Log.Error($"could not initialize genome {allImplicitGenome.defName ?? "NO DEF NAME"}\n{e}"); } } if (DebugLogUtils.ShouldLog(LogLevel.Messages)) { var builder = new StringBuilder(); builder.Append($"Generated {_allImplicitGenomes.Count} genomes!:"); builder.AppendLine(_allImplicitGenomes.Join(t => t.defName, "\n")); Log.Message(builder.ToString()); } ResourceCounter.ResetDefs(); }
private static void MassPatchFormerHumanChecks([NotNull] Harmony harmonyInstance) { var staticFlags = BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public; var instanceFlags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public; List <MethodInfo> methodsToPatch = new List <MethodInfo>(); //bed stuff var bedUtilType = typeof(RestUtility); var canUseBedMethod = bedUtilType.GetMethod(nameof(RestUtility.CanUseBedEver), staticFlags); methodsToPatch.Add(canUseBedMethod); //animal tabs var methods = typeof(MainTabWindow_Animals).GetNestedTypes(staticFlags | instanceFlags)//looking for delegates used by the animal tab .Where(t => t.IsCompilerGenerated()) .SelectMany(t => t.GetMethods(instanceFlags).Where(m => m.HasSignature(typeof(Pawn)))); methodsToPatch.AddRange(methods); //map pawns methods = typeof(MapPawns).GetMethods(instanceFlags).Where(m => m.HasSignature(typeof(Faction))); methodsToPatch.AddRange(methods); //jobs and toils methodsToPatch.Add(typeof(JobDriver_Ingest).GetMethod("PrepareToIngestToils", instanceFlags)); //now patch them foreach (MethodInfo methodInfo in methodsToPatch) { if (methodInfo == null) { continue; } harmonyInstance.ILPatchCommonMethods(methodInfo); } StringBuilder builder = new StringBuilder(); builder.AppendLine("Patched:"); foreach (MethodInfo methodInfo in methodsToPatch) { if (methodInfo == null) { continue; } builder.AppendLine($"{methodInfo.Name}"); } Log.Message(builder.ToString()); DebugLogUtils.LogMsg(LogLevel.Messages, builder.ToString()); }
private static void MassPatchFormerHumanChecks([NotNull] Harmony harmonyInstance) { var staticFlags = BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public; var instanceFlags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public; List <MethodInfo> methodsToPatch = new List <MethodInfo>(); //bed stuff var bedUtilType = typeof(RestUtility); var canUseBedMethod = bedUtilType.GetMethod(nameof(RestUtility.CanUseBedEver), staticFlags); methodsToPatch.Add(canUseBedMethod); //map pawns var methods = typeof(MapPawns).GetMethods(instanceFlags).Where(m => m.HasSignature(typeof(Faction))); methodsToPatch.AddRange(methods); //jobs and toils methodsToPatch.Add(typeof(JobDriver_Ingest).GetMethod("PrepareToIngestToils", instanceFlags)); methodsToPatch.Add(typeof(GatheringWorker_MarriageCeremony).GetMethod("IsGuest", instanceFlags)); //now patch them foreach (MethodInfo methodInfo in methodsToPatch) { if (methodInfo == null) { continue; } harmonyInstance.ILPatchCommonMethods(methodInfo); } StringBuilder builder = new StringBuilder(); builder.AppendLine("Patched:"); foreach (MethodInfo methodInfo in methodsToPatch) { if (methodInfo == null) { continue; } builder.AppendLine($"{methodInfo.Name}"); } Log.Message(builder.ToString()); DebugLogUtils.LogMsg(LogLevel.Messages, builder.ToString()); }
/// <summary> /// Exits the current sapience state. /// </summary> /// <param name="recalculateComps">if set to <c>true</c> dynamic components will be recalculated after exiting the state.</param> public void ExitState(bool recalculateComps = true) { if (_sapienceState == null) { DebugLogUtils.Warning($"trying to exit sapience state in {Pawn.Name} but they aren't in one"); return; } _sapienceState.Exit(); _sapienceState = null; if (recalculateComps) { PawnComponentsUtility.AddAndRemoveDynamicComponents(Pawn); } }
public override void EjectContents() //should refactor the mutagenic chamber, make it a state machine { DebugLogUtils.Assert(innerContainer.Count == 1, "innerContainer.Count == 1"); var pawn = (Pawn)innerContainer[0]; if (pawn == null) { Log.Warning($"mutagenic chamber ejecting nothing"); return; } if (IsFinished) { TransformPawn(pawn); } else { base.EjectContents(); if (!Destroyed) { SoundDefOf.CryptosleepCasket_Eject.PlayOneShot(SoundInfo.InMap(new TargetInfo(base.Position, base.Map))); fuelComp.ConsumeFuel(fuelComp.Fuel); } if (_state != ChamberState.MergeOutOf || (linkTo?.daysIn ?? 0) < 1) { pawn.health.AddHediff(Hediffs.MorphTransformationDefOf.FullRandomTFAnyOutcome); } pawn.health.AddHediff(Hediffs.MorphTransformationDefOf.FullRandomTFAnyOutcome); if (_state == ChamberState.MergeInto) { linkTo?.EjectContents(); } } _state = ChamberState.Idle; daysIn = 0; }
static bool SubstituteInteraction(Pawn recipient, ref InteractionDef intDef, Pawn ___pawn) { var ext = intDef.GetModExtension <InteractionGroupExtension>(); InteractionDef alt = ext?.TryGetAlternativeFor(___pawn, recipient); if (alt != null) { if (DebugLogUtils.ShouldLog(LogLevel.Messages)) { var msg = $"substituting {alt.defName} for {intDef.defName} on {___pawn.Name} -> {recipient.Name}"; Log.Message(msg); } intDef = alt; } return(true); }
private static void CheckForObsoletedComponents() { IEnumerable <HediffDef> obsoleteHediffTypes = DefDatabase <HediffDef> .AllDefs.Where(h => h.hediffClass.HasAttribute <ObsoleteAttribute>()); //get all obsoleted hediffs in use foreach (HediffDef obsoleteDef in obsoleteHediffTypes) { Log.Warning($"obsolete hediff {obsoleteDef.hediffClass.Name} in {obsoleteDef.defName}"); } var tmp = new List <string>(); foreach (HediffDef hediffDef in DefDatabase <HediffDef> .AllDefs) { IEnumerable <HediffGiver> obsoleteGivers = hediffDef.GetAllHediffGivers().Where(g => g.GetType().HasAttribute <ObsoleteAttribute>()); var builder = new StringBuilder(); builder.AppendLine($"in {hediffDef.defName}"); foreach (HediffGiver obsoleteGiver in obsoleteGivers) { builder.AppendLine($"obsolete hediff giver: {obsoleteGiver.GetType().Name}".Indented()); } IEnumerable <HediffGiver> giversGivingBadHediffs = hediffDef .GetAllHediffGivers() //find hediff giver that are giving obsolete hediffs .Where(g => g.hediff?.GetType().HasAttribute <ObsoleteAttribute>() ?? false); foreach (HediffGiver giversGivingBadHediff in giversGivingBadHediffs) { tmp.Add($"giver {giversGivingBadHediff.GetType().Name} is giving obsolete hediff {giversGivingBadHediff.hediff.defName}"); } if (tmp.Count > 0) { builder.Append(string.Join("\n", tmp.ToArray()).Indented()); tmp.Clear(); DebugLogUtils.Warning(builder.ToString()); } } }
/// <summary> /// Generates the genomes. /// </summary> internal static void GenerateGenomes() { if (_allImplicitGenomes != null) { Log.Error("trying to generate genomes more then once!"); return; } _allImplicitGenomes = new List <ThingDef>(); foreach (MutationCategoryDef mDef in AllImplicitGenomeMutations) { ThingDef tDef = GenerateMutationGenome(mDef); mDef.implicitGenomeDef = tDef; _allImplicitGenomes.Add(tDef); } foreach (PawnKindDef pk in AllPKsWithGenomes) { ThingDef tDef = GenerateAnimalGenome(pk); _genomeDict[pk] = tDef; _allImplicitGenomes.Add(tDef); } foreach (ThingDef allImplicitGenome in _allImplicitGenomes) { GiveShortHash(allImplicitGenome); DefDatabase <ThingDef> .Add(allImplicitGenome); } if (DebugLogUtils.ShouldLog(LogLevel.Messages)) { var builder = new StringBuilder(); builder.Append($"Generated {_allImplicitGenomes.Count} genomes!:"); builder.AppendLine(_allImplicitGenomes.Join(t => t.defName, "\n")); Log.Message(builder.ToString()); } }
/// <summary> /// change the race of the pawn back to human /// </summary> /// <param name="pawn"></param> public static void RevertPawnToHuman([NotNull] Pawn pawn) { var race = pawn.def; var human = ThingDefOf.Human; if (race == human) { return; //do nothing } var oldMorph = pawn.def.GetMorphOfRace(); bool isHybrid = oldMorph != null; DebugLogUtils.Assert(isHybrid, "pawn.IsHybridRace()"); if (!isHybrid) { return; } var storedGraphics = pawn.GetComp <GraphicSys.InitialGraphicsComp>(); storedGraphics.RestoreGraphics(); ChangePawnRace(pawn, human); var morphRThought = oldMorph.transformSettings?.revertedMemory; morphRThought = morphRThought ?? PMThoughtDefOf.DefaultMorphRevertsToHuman; if (morphRThought != null) { pawn.TryGainMemory(morphRThought); } var messageStr = RACE_REVERT_MESSAGE_ID.Translate(pawn.LabelShort).CapitalizeFirst(); Messages.Message(messageStr, pawn, MessageTypeDefOf.NeutralEvent); }
/// <summary> /// notifies this instance that a connector was added /// </summary> /// <param name="comp">The comp.</param> /// <exception cref="ArgumentNullException">comp</exception> public void NotifyConnectorAdded([NotNull] SlurryNetComp comp) { if (comp == null) { throw new ArgumentNullException(nameof(comp)); } DebugLogUtils.LogMsg(LogLevel.Messages, $"adding connector for '{comp.parent.Label}'"); if (comp.Network != null || Nets.Any(n => n.Connectors.Contains(comp))) { Log.Error($"adding slurry comp {comp.parent.Label} which is already part of a network"); return; } List <SlurryNet> neighbors = comp.GetAdjacentSlurryComps() .Select(n => n.Network) .Where(n => n != null) .Distinct() .ToList(); if (neighbors.Count == 1) { neighbors[0].Register(comp); } else { foreach (SlurryNet slurryNet in neighbors) { DestroyNet(slurryNet); } SlurryNet net = CreateSlurryNetFrom(comp, null); _nets.Add(net); } }
public T this[int index] { get { lock (m_lock) { try { DebugLogEntry.Register(new MyDebugLogEntry(MyDebugLogEntry.Action.Index, m_head, m_tail, index)); if (m_tail + index >= m_head) { throw new ArgumentOutOfRangeException("index"); } return(m_buffer[m_tail + index]); } catch (Exception ex) { DebugLogEntry.Register(new DebugLogEntryString(ex.GetType().Name + ", " + ex.Message)); DebugLogUtils.DumpToFile(); throw; } } } }
/// <summary> /// preform the requested transform /// </summary> /// <param name="request">The request.</param> /// <returns></returns> protected override TransformedPawnSingle TransformImpl(TransformationRequest request) { Pawn original = request.originals[0]; if (request.addMutationToOriginal) { TryAddMutationsToPawn(original, request.cause, request.outputDef); } var reactionStatus = original.GetFormerHumanReactionStatus(); float newAge = TransformerUtility.ConvertAge(original, request.outputDef.race.race); Faction faction; faction = GetFaction(request, original); Gender newGender = TransformerUtility.GetTransformedGender(original, request.forcedGender, request.forcedGenderChance); var pRequest = FormerHumanUtilities.CreateSapientAnimalRequest(request.outputDef, original, faction, fixedGender: newGender); Pawn animalToSpawn = PawnGenerator.GeneratePawn(pRequest); //make the temp pawn animalToSpawn.needs.food.CurLevel = original.needs.food.CurLevel; // Copies the original pawn's food need to the animal's. animalToSpawn.needs.rest.CurLevel = original.needs.rest.CurLevel; // Copies the original pawn's rest need to the animal's. animalToSpawn.Name = original.Name; // Copies the original pawn's name to the animal's. float sapienceLevel = request.forcedSapienceLevel ?? GetSapienceLevel(original, animalToSpawn); if (request.forcedFaction == null && original.Faction != faction && original.Faction != animalToSpawn.Faction && FormerHumanUtilities.GetQuantizedSapienceLevel(sapienceLevel) <= SapienceLevel.MostlySapient) { //set the faction to the original's if mostly sapient or above animalToSpawn.SetFaction(original.Faction); } GiveTransformedPawnSapienceState(animalToSpawn, sapienceLevel); FormerHumanUtilities.InitializeTransformedPawn(original, animalToSpawn, sapienceLevel); //use a normal distribution? Pawn spawnedAnimal = SpawnAnimal(original, animalToSpawn); // Spawns the animal into the map. ReactionsHelper.OnPawnTransforms(original, animalToSpawn, reactionStatus); //this needs to happen before MakeSapientAnimal because that removes relations var rFaction = request.factionResponsible ?? GetFactionResponsible(original); var inst = new TransformedPawnSingle { original = original, animal = spawnedAnimal, factionResponsible = rFaction, reactionStatus = reactionStatus }; if (original.Spawned) { for (var i = 0; i < 10; i++) // Create a cloud of magic. { IntermittentMagicSprayer.ThrowMagicPuffDown(spawnedAnimal.Position.ToVector3(), spawnedAnimal.MapHeld); IntermittentMagicSprayer.ThrowMagicPuffUp(spawnedAnimal.Position.ToVector3(), spawnedAnimal.MapHeld); } } if (request.tale != null) // If a tale was provided, push it to the tale recorder. { TaleRecorder.RecordTale(request.tale, original, animalToSpawn); } Faction oFaction = original.FactionOrExtraHomeFaction; Map oMap = original.Map; //apply any other post tf effects ApplyPostTfEffects(original, animalToSpawn, request); TransformerUtility .CleanUpHumanPawnPostTf(original, request.cause); //now clean up the original pawn (remove apparel, drop'em, ect) //notify the faction that their member has been transformed oFaction?.Notify_MemberTransformed(original, animalToSpawn, oMap == null, oMap); if (!request.noLetter && reactionStatus == FormerHumanReactionStatus.Colonist || reactionStatus == FormerHumanReactionStatus.Prisoner) //only send the letter for colonists and prisoners { SendLetter(request, original, spawnedAnimal); } if (original.Spawned) { original.DeSpawn(); // Remove the original pawn from the current map. } DebugLogUtils.Assert(!PrisonBreakUtility.CanParticipateInPrisonBreak(original), $"{original.Name} has been cleaned up and de-spawned but can still participate in prison breaks"); return(inst); }
static void HandlePrisoner(Pawn pawn) { pawn.guest.Released = true; pawn.guest.SetGuestStatus(null); DebugLogUtils.Assert(!pawn.guest.IsPrisoner, $"{pawn.Name} is being cleaned up but is still a prisoner"); }