private static void MakeFeral(Pawn pawn) { var loader = Find.World.GetComponent <PawnmorphGameComp>(); var inst = loader.GetTransformedPawnContaining(pawn)?.Item1; var singleInst = inst as TransformedPawnSingle; //hacky, need to come up with a better solution eventually foreach (var instOriginalPawn in inst?.OriginalPawns ?? Enumerable.Empty <Pawn>()) { ReactionsHelper.OnPawnPermFeral(instOriginalPawn, pawn, singleInst?.reactionStatus ?? FormerHumanReactionStatus.Wild); } //remove the original and destroy the pawns foreach (var instOriginalPawn in inst?.OriginalPawns ?? Enumerable.Empty <Pawn>()) { instOriginalPawn.Destroy(); } if (inst != null) { loader.RemoveInstance(inst); } if (inst != null || pawn.Faction == Faction.OfPlayer) { Find.LetterStack.ReceiveLetter("LetterHediffFromPermanentTFLabel".Translate(pawn.LabelShort).CapitalizeFirst(), "LetterHediffFromPermanentTF".Translate(pawn.LabelShort).CapitalizeFirst(), LetterDefOf.NegativeEvent, pawn, null, null); } }
/// <summary> /// Tries to revert the transformed pawn instance, implementation. /// </summary> /// <param name="transformedPawn">The transformed pawn.</param> /// <returns></returns> protected override bool TryRevertImpl(TransformedPawnSingle transformedPawn) { if (transformedPawn == null) { throw new ArgumentNullException(nameof(transformedPawn)); } if (!transformedPawn.IsValid) { Log.Warning(nameof(SimpleMechaniteMutagen) + " received an invalid transformed pawn to revert"); return(false); } Pawn animal = transformedPawn.animal; if (animal == null) { return(false); } var rFaction = transformedPawn.FactionResponsible; var spawned = (Pawn)GenSpawn.Spawn(transformedPawn.original, animal.PositionHeld, animal.MapHeld); if (spawned.Faction != animal.Faction && rFaction == null) //if the responsible faction is null (no one knows who did it) have the reverted pawn join that faction { spawned.SetFaction(animal.Faction); } for (var i = 0; i < 10; i++) { IntermittentMagicSprayer.ThrowMagicPuffDown(spawned.Position.ToVector3(), spawned.MapHeld); IntermittentMagicSprayer.ThrowMagicPuffUp(spawned.Position.ToVector3(), spawned.MapHeld); } //transfer hediffs from the former human back onto the original pawn FormerHumanUtilities.TransferHediffs(animal, spawned); SetHumanoidSapience(spawned, animal); FixBondRelationship(spawned, animal); FormerHumanUtilities.TransferEverything(animal, spawned); spawned.Faction?.Notify_MemberReverted(spawned, animal, spawned.Map == null, spawned.Map); ReactionsHelper.OnPawnReverted(spawned, animal, transformedPawn.reactionStatus); spawned.health.AddHediff(MorphTransformationDefOf.StabiliserHigh); //add stabilizer on reversion TransformerUtility.CleanUpHumanPawnPostTf(animal, null); animal.Destroy(); return(true); }
/// <summary> /// Tries to revert the transformed pawn instance, implementation. /// </summary> /// <param name="transformedPawn">The transformed pawn.</param> /// <returns></returns> protected override bool TryRevertImpl(TransformedPawnSingle transformedPawn) { if (transformedPawn == null) { throw new ArgumentNullException(nameof(transformedPawn)); } if (!transformedPawn.IsValid) { Log.Warning(nameof(SimpleMechaniteMutagen) + " received an invalid transformed pawn to revert"); return(false); } Pawn animal = transformedPawn.animal; Hediff tfHumanHediff = animal?.health?.hediffSet?.GetFirstHediffOfDef(TfHediffDefOf.TransformedHuman); if (tfHumanHediff == null) { return(false); } var rFaction = transformedPawn.FactionResponsible; Log.Message($"going to spawn {transformedPawn.original.Name} {transformedPawn.original.KindLabel}"); var spawned = (Pawn)GenSpawn.Spawn(transformedPawn.original, animal.PositionHeld, animal.MapHeld); if (spawned.Faction != animal.Faction && rFaction == null) //if the responsible faction is null (no one knows who did it) have the reverted pawn join that faction { spawned.SetFaction(animal.Faction); } for (var i = 0; i < 10; i++) { IntermittentMagicSprayer.ThrowMagicPuffDown(spawned.Position.ToVector3(), spawned.MapHeld); IntermittentMagicSprayer.ThrowMagicPuffUp(spawned.Position.ToVector3(), spawned.MapHeld); } FixBondRelationship(spawned, animal); PawnTransferUtilities.TransferRelations(animal, spawned, r => r != PawnRelationDefOf.Bond); //transfer whatever relations from the animal to the human pawn PawnTransferUtilities.TransferSkills(animal, spawned, PawnTransferUtilities.SkillTransferMode.Max); //keep any skills they learned as an animal //do NOT transfer the bond relationship to humans, Rimworld doesn't like that AddReversionThought(spawned, tfHumanHediff.CurStageIndex); spawned.Faction?.Notify_MemberReverted(spawned, animal, spawned.Map == null, spawned.Map); ReactionsHelper.OnPawnReverted(spawned, animal, transformedPawn.reactionStatus); spawned.health.AddHediff(MorphTransformationDefOf.StabiliserHigh); //add stabilizer on reversion animal.Destroy(); return(true); }
internal void MakePermanentlyFeral() { Hediff fHediff; if (StateDef.forcedHediff != null) { fHediff = Pawn.health.hediffSet.GetFirstHediffOfDef(StateDef.forcedHediff); } else { fHediff = null; } //transfer relationships back if possible var gComp = Find.World.GetComponent <PawnmorphGameComp>(); Pawn oPawn = gComp.GetTransformedPawnContaining(Pawn)?.Item1?.OriginalPawns.FirstOrDefault(); if (oPawn == Pawn) { oPawn = null; } Pawn_RelationsTracker aRelations = Pawn.relations; if (aRelations != null && oPawn != null) { FormerHumanUtilities.TransferRelationsToOriginal(oPawn, Pawn); } Pawn.health.AddHediff(TfHediffDefOf.PermanentlyFeral); if (fHediff != null) { Pawn.health.RemoveHediff(fHediff); } var loader = Find.World.GetComponent <PawnmorphGameComp>(); TransformedPawn inst = loader.GetTransformedPawnContaining(Pawn)?.Item1; var singleInst = inst as TransformedPawnSingle; //hacky, need to come up with a better solution foreach (Pawn instOriginalPawn in inst?.OriginalPawns ?? Enumerable.Empty <Pawn>() ) //needed to handle merges correctly { ReactionsHelper.OnPawnPermFeral(instOriginalPawn, Pawn, singleInst?.reactionStatus ?? FormerHumanReactionStatus.Wild); } //remove the original and destroy the pawns foreach (Pawn instOriginalPawn in inst?.OriginalPawns ?? Enumerable.Empty <Pawn>()) { instOriginalPawn.Destroy(); } if (inst != null) { loader.RemoveInstance(inst); } if (inst != null || Pawn.Faction == Faction.OfPlayer) { Find.LetterStack.ReceiveLetter("LetterHediffFromPermanentTFLabel".Translate(Pawn.LabelShort).CapitalizeFirst(), "LetterHediffFromPermanentTF".Translate(Pawn.LabelShort).CapitalizeFirst(), LetterDefOf.NegativeEvent, Pawn); } Pawn.needs?.AddOrRemoveNeedsAsAppropriate(); //make sure any comps get added/removed as appropriate PawnComponentsUtility.AddAndRemoveDynamicComponents(Pawn); }
/// <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); }
/// <summary> /// preform the requested transform /// </summary> /// <param name="request">The request.</param> /// <returns></returns> protected override MergedPawns TransformImpl(TransformationRequest request) { Pawn firstPawn = request.originals[0]; Pawn secondPawn = request.originals[1]; float averageAge = firstPawn.ageTracker.AgeBiologicalYearsFloat + secondPawn.ageTracker.AgeBiologicalYearsFloat; averageAge /= 2; float newAge = averageAge * request.outputDef.race.race.lifeExpectancy / firstPawn.RaceProps.lifeExpectancy; Faction faction = request.forcedFaction ?? Faction.OfPlayer; var pRequest = FormerHumanUtilities.CreateMergedAnimalRequest(request.outputDef, request.originals, faction); Pawn meldToSpawn = PawnGenerator.GeneratePawn(pRequest); HediffDef hediffToAdd = HediffDef.Named(FORMER_HUMAN_HEDIFF); //make sure hediff is added before spawning meld //make them count as former humans var tracker = meldToSpawn.GetFormerHumanTracker(); if (tracker == null) { Log.Error($"{meldToSpawn.def.defName} is a meld but does not have a former human tracker!"); } else { tracker.MakeFormerHuman(1); } Hediff hediff = HediffMaker.MakeHediff(hediffToAdd, meldToSpawn); hediff.Severity = Rand.Range(request.minSeverity, request.maxSeverity); meldToSpawn.health.AddHediff(hediff); Pawn_NeedsTracker needs = meldToSpawn.needs; needs.food.CurLevel = firstPawn.needs.food.CurLevel; needs.rest.CurLevel = firstPawn.needs.rest.CurLevel; meldToSpawn.training.SetWantedRecursive(TrainableDefOf.Obedience, true); meldToSpawn.training.Train(TrainableDefOf.Obedience, null, true); meldToSpawn.Name = firstPawn.Name; var meld = (Pawn)GenSpawn.Spawn(meldToSpawn, firstPawn.PositionHeld, firstPawn.MapHeld); for (var i = 0; i < 10; i++) { IntermittentMagicSprayer.ThrowMagicPuffDown(meld.Position.ToVector3(), meld.MapHeld); IntermittentMagicSprayer.ThrowMagicPuffUp(meld.Position.ToVector3(), meld.MapHeld); } meld.SetFaction(Faction.OfPlayer); ReactionsHelper.OnPawnsMerged(firstPawn, firstPawn.IsPrisoner, secondPawn, secondPawn.IsPrisoner, meld); TransformerUtility.CleanUpHumanPawnPostTf(firstPawn, null); TransformerUtility.CleanUpHumanPawnPostTf(secondPawn, null); var inst = new MergedPawns { originals = request.originals.ToList(), //we want to make a copy here meld = meld, mutagenDef = def, factionResponsible = Faction.OfPlayer }; return(inst); }
/// <summary> /// Tries to revert the transformed pawn instance, implementation. /// </summary> /// <param name="transformedPawn">The transformed pawn.</param> /// <returns></returns> protected override bool TryRevertImpl(MergedPawns transformedPawn) { if (!transformedPawn.IsValid) { return(false); } if (transformedPawn.originals.Count != 2) { return(false); } HediffDef hDef = HediffDef.Named(FORMER_HUMAN_HEDIFF); Pawn meld = transformedPawn.meld; Hediff formerHumanHediff = meld?.health?.hediffSet?.hediffs?.FirstOrDefault(h => h.def == hDef); if (formerHumanHediff == null) { return(false); } PawnRelationDef mergMateDef = DefDatabase <PawnRelationDef> .GetNamed("MergeMate"); PawnRelationDef mergeMateEx = DefDatabase <PawnRelationDef> .GetNamed("ExMerged"); //TODO put these in a DefOf var firstO = (Pawn)GenSpawn.Spawn(transformedPawn.originals[0], meld.PositionHeld, meld.MapHeld); var secondO = (Pawn)GenSpawn.Spawn(transformedPawn.originals[1], meld.PositionHeld, meld.MapHeld); var thoughtDef = AddRandomThought(firstO, formerHumanHediff.CurStageIndex); AddRandomThought(secondO, formerHumanHediff.CurStageIndex); for (var i = 0; i < 10; i++) { IntermittentMagicSprayer.ThrowMagicPuffDown(meld.Position.ToVector3(), meld.MapHeld); IntermittentMagicSprayer.ThrowMagicPuffUp(meld.Position.ToVector3(), meld.MapHeld); } PawnRelationDef addDef; bool relationIsMergeMate = thoughtDef == def.revertedThoughtGood; addDef = relationIsMergeMate ? mergMateDef : mergeMateEx; //first element is "WasMerged" firstO.relations.AddDirectRelation(addDef, secondO); firstO.SetFaction(Faction.OfPlayer); secondO.SetFaction(Faction.OfPlayer); //TransformerUtility.RemoveAllMutations(firstO); //TransformerUtility.RemoveAllMutations(secondO); ReactionsHelper.OnPawnReverted(firstO, meld); ReactionsHelper.OnPawnReverted(secondO, meld); CheckForBrainDamage(meld, firstO, secondO); meld.DeSpawn(); return(true); }