/// <summary> /// Does the find. /// </summary> /// <param name="worker">The worker.</param> /// <exception cref="System.NotImplementedException"></exception> protected override void DoFind(Pawn worker) { if (_chosenAnimalToScan == null) { Log.Error($"calling DoFind on {parent.ThingID} which does not have a chosen animal!"); return; } _scratchList.Clear(); _scratchList.AddRange(_chosenAnimalToScan.GetAllMutationsFrom().Where(m => !DB.StoredMutations.Contains(m))); if (_scratchList.Count == 0) { Log.Warning("unable to find mutation to give!"); _chosenAnimalToScan = null; return; } MutationDef mutation = _scratchList.RandomElement(); DB.AddToDatabase(mutation); TaggedString msg = MUTATION_GATHERED_LABEL.Translate(mutation.Named("mutation"), _chosenAnimalToScan.Named("animal") ); Messages.Message(msg, MessageTypeDefOf.PositiveEvent); if (_scratchList.Count - 1 == 0) { _chosenAnimalToScan = null; } }
private void StoreRemovedMutations(MutationDef mDef, List <Hediff_AddedMutation> mutations, List <RemoveMutationDurationComp.MutationEntry> outList) { if (mDef.RemoveComp == null) { return; } foreach (Hediff_AddedMutation mutation in mutations) { var mRmComp = mutation.TryGetComp <RemoveFromPartComp>(); if (mRmComp == null) { continue; } var otherMDef = mutation.def as MutationDef; if (otherMDef == null) { Log.Warning($"encountered mutation {mutation.def.defName} that does not use a MutationDef!"); } if (mRmComp.Layer == mDef.RemoveComp.layer && mDef.parts.MakeSafe().Contains(mutation.Part?.def)) { outList.Add(new RemoveMutationDurationComp.MutationEntry { mDef = otherMDef, severity = mutation.Severity, record = mutation.Part }); } } }
/// <summary> /// Constructor for MutationData used to gather all relevant information. /// </summary> /// <param name="mutation">The def of the mutation to add to the pawn.</param> /// <param name="part">The body part record to add the mutation to.</param> /// <param name="severity">The severity the mutation should be initialized with.</param> /// <param name="isHalted">Wether the mutation should be able to progress, or should be locked at it's current stage.</param> /// <param name="removing">Whether or not this entry is designated to instead remove mutations from the body part.</param> public MutationData(MutationDef mutation, BodyPartRecord part, float severity, bool isHalted, bool removing) { this.mutation = mutation; this.part = part; this.severity = severity; this.isHalted = isHalted; this.removing = removing; }
private static bool IsDepricated([NotNull] MutationDef def) { if (string.Compare("depricated", def.label, StringComparison.InvariantCultureIgnoreCase) == 0) { return(true); } return(string.Compare("obsolete", def.label, StringComparison.InvariantCultureIgnoreCase) == 0); }
/// <summary> /// Gets the required storage. /// </summary> /// <param name="mutationDef">The mutation definition.</param> /// <returns></returns> /// <exception cref="ArgumentNullException">mutationDef</exception> public static int GetRequiredStorage([NotNull] this MutationDef mutationDef) { if (mutationDef == null) { throw new ArgumentNullException(nameof(mutationDef)); } return((int)Mathf.Max(MIN_MUTATION_STORAGE_SPACE, mutationDef.value * STORAGE_PER_VALUE_MUTATION)); }
/// <summary> /// Tries to add the specified mutation to the database, returning false on failure. /// </summary> /// <param name="db">The database.</param> /// <param name="def">The definition.</param> /// <returns></returns> public static bool TryAddToDatabase([NotNull] this ChamberDatabase db, [NotNull] MutationDef def) { if (!db.CanAddToDatabase(def)) { return(false); } db.AddToDatabase(def); return(true); }
MutationEntry CreateEntry(MutationDef mDef) { return(new MutationEntry { addChance = 0.3f, blocks = false, mutation = mDef }); }
/// <summary> /// Adds the mutation to the given pawn /// </summary> /// <param name="pawn">The pawn.</param> /// <param name="mutation">The mutation.</param> /// <param name="parts">The parts.</param> /// <param name="countToAdd">The count to add.</param> /// <param name="ancillaryEffects">The ancillary effects.</param> /// <returns></returns> /// <exception cref="ArgumentNullException"> /// pawn /// or /// mutation /// </exception> public static MutationResult AddMutation([NotNull] Pawn pawn, [NotNull] MutationDef mutation, [CanBeNull] List <BodyPartDef> parts, int countToAdd = int.MaxValue, AncillaryMutationEffects?ancillaryEffects = null) { if (pawn == null) { throw new ArgumentNullException(nameof(pawn)); } if (mutation == null) { throw new ArgumentNullException(nameof(mutation)); } var addLst = new List <BodyPartRecord>(); if (parts != null) { foreach (BodyPartRecord notMissingPart in pawn.health.hediffSet.GetAllNonMissingWithoutProsthetics()) { if (parts.Contains(notMissingPart.def)) { addLst.Add(notMissingPart); if (parts.Count >= countToAdd) { break; } } } if (addLst.Count == 0) { return(MutationResult.Empty); } return(AddMutation(pawn, mutation, addLst, ancillaryEffects)); } var existingHediff = pawn.health.hediffSet.hediffs.FirstOrDefault(m => m.def == mutation && m.Part == null); if (existingHediff != null) { (existingHediff as Hediff_AddedMutation)?.ResumeAdaption(); return(MutationResult.Empty); } if (!(HediffMaker.MakeHediff(mutation, pawn) is Hediff_AddedMutation hDef)) { Log.Error($"{mutation.defName} is not a mutation but is being added like one!"); return(MutationResult.Empty); } pawn.health.AddHediff(hDef); DoAncillaryMutationEffects(pawn, mutation, hDef, ancillaryEffects ?? AncillaryMutationEffects.Default); return(new MutationResult(hDef)); }
/// <summary> /// Determines whether the specified hediff definition is an associated mutation . /// </summary> /// <param name="mutationDef">The hediff definition.</param> /// <returns> /// <c>true</c> if the specified hediff definition is an associated mutation; otherwise, <c>false</c>. /// </returns> /// <exception cref="ArgumentNullException">hediffDef</exception> public bool IsAnAssociatedMutation([NotNull] MutationDef mutationDef) { if (mutationDef == null) { throw new ArgumentNullException(nameof(mutationDef)); } return(AllAssociatedMutations.Contains(mutationDef)); }
/// <summary> /// checks if this mutation blocks the addition of a new mutation at the given part /// </summary> /// <param name="otherMutation">The other mutation.</param> /// <param name="addPart">The add part.</param> /// <returns></returns> /// <exception cref="ArgumentNullException">otherMutation</exception> public virtual bool Blocks([NotNull] MutationDef otherMutation, [CanBeNull] BodyPartRecord addPart) { if (otherMutation == null) { throw new ArgumentNullException(nameof(otherMutation)); } var mDef = def as MutationDef; return(mDef?.BlocksMutation(otherMutation, Part, addPart) == true); }
/// <summary> /// Determines whether this instance is tagged. /// </summary> /// <param name="mutationDef">The mutation definition.</param> /// <returns> /// <c>true</c> if the specified mutation definition is tagged; otherwise, <c>false</c>. /// </returns> /// <exception cref="ArgumentNullException">mutationDef</exception> public static bool IsTagged([NotNull] this MutationDef mutationDef) { if (mutationDef == null) { throw new ArgumentNullException(nameof(mutationDef)); } var db = Find.World.GetComponent <ChamberDatabase>(); return(db?.StoredMutations.Contains(mutationDef) == true); }
/// <summary> /// Gets the required storage. /// </summary> /// <param name="mutationDef">The mutation definition.</param> /// <returns></returns> /// <exception cref="ArgumentNullException">mutationDef</exception> public static int GetRequiredStorage([NotNull] this MutationDef mutationDef) { if (mutationDef == null) { throw new ArgumentNullException(nameof(mutationDef)); } float spvM = mutationDef.value * STORAGE_PER_VALUE_MUTATION; return(Mathf.Max(MIN_MUTATION_STORAGE_SPACE, Mathf.RoundToInt(spvM))); }
/// <summary> /// Determines whether this instance has the specified mutation. /// </summary> /// <param name="requiredMutation">The required mutation.</param> /// <returns> /// <c>true</c> if the specified required mutation has mutation; otherwise, <c>false</c>. /// </returns> /// <exception cref="NotImplementedException"></exception> public bool HasMutation([NotNull] MutationDef requiredMutation) { foreach (Hediff_AddedMutation mutation in _mutationList) { if (mutation.def == requiredMutation) { return(true); } } return(false); }
/// <summary> /// Initializes a new instance of the <see cref="MutationData"/> class. /// </summary> /// <param name="mData">The m data.</param> public MutationData([NotNull] IReadOnlyMutationData mData) { if (mData == null) { throw new ArgumentNullException(nameof(mData)); } mutation = mData.Mutation; part = mData.Part; severity = mData.Severity; isHalted = mData.IsHalted; removing = mData.Removing; }
/// <summary> /// Adds the mutation to the given pawn /// </summary> /// <param name="pawn">The pawn.</param> /// <param name="mutation">The mutation.</param> /// <param name="countToAdd">The count to add.</param> /// <param name="ancillaryEffects">The ancillary effects.</param> /// <returns></returns> /// <exception cref="ArgumentNullException"> /// pawn /// or /// mutation /// </exception> public static MutationResult AddMutation([NotNull] Pawn pawn, [NotNull] MutationDef mutation, int countToAdd = int.MaxValue, AncillaryMutationEffects?ancillaryEffects = null) { if (pawn == null) { throw new ArgumentNullException(nameof(pawn)); } if (mutation == null) { throw new ArgumentNullException(nameof(mutation)); } return(AddMutation(pawn, mutation, mutation.parts, countToAdd, ancillaryEffects)); }
/// <summary> /// Tries to add the specified mutation to the database, returning false on failure. /// </summary> /// <param name="db">The database.</param> /// <param name="def">The definition.</param> /// <param name="displayMessageIfAdded">if set to <c>true</c> [display message if added].</param> /// <returns></returns> public static bool TryAddToDatabase([NotNull] this ChamberDatabase db, [NotNull] MutationDef def, bool displayMessageIfAdded = true) { if (!db.CanAddToDatabase(def)) { return(false); } db.AddToDatabase(def); if (displayMessageIfAdded) { Messages.Message(MUTATION_ADDED_MESSAGE.Translate(def.Named("Mutation")), MessageTypeDefOf.PositiveEvent); } return(true); }
/// <summary> /// Determines whether this instance can generate the specified mutation. /// </summary> /// <param name="mDef">The m definition.</param> /// <returns> /// <c>true</c> if this instance with the specified m definition can generate ; otherwise, <c>false</c>. /// </returns> public bool CanGenerate(MutationDef mDef) { return(mutations?.Contains(mDef) == true); }
/// <summary> /// Adds a new entry to the list of mutations to give the pawn. /// </summary> /// <param name="mutation">The def of the mutation to add to the pawn.</param> /// <param name="part">The body part record to apply the mutation to.</param> /// <param name="severity">What severity the added mutation should be intialized with.</param> /// <param name="isHalted">Whether or not the addded mutation will be able to progress.</param> /// <param name="removing">Whether or not this entry is intended to remove the mutation.</param> public void AddData(MutationDef mutation, BodyPartRecord part, float severity, bool isHalted, bool removing) { mutationData.Add(new MutationData(mutation, part, severity, isHalted, removing)); }
public DebugMenu_AddMutation([NotNull] MutationDef mDef, [NotNull] Pawn pawn) { _mutationDef = mDef ?? throw new ArgumentNullException(nameof(mDef)); _pawn = pawn ?? throw new ArgumentNullException(nameof(pawn)); }
/// <summary> /// Gets the market value for this mutation. /// </summary> /// this can be negative for bad mutations /// <param name="mDef">The m definition.</param> /// <returns></returns> public static float GetMarketValueFor([NotNull] this MutationDef mDef) { return(mDef.value * MARKET_VALUE_PER_VALUE); }
void AddMutationAction([NotNull] MutationDef mutationDef) { Find.WindowStack.Add(new DebugMenu_AddMutation(mutationDef, _pawn)); }
public RowEntry(MutationDef mDef) { label = mDef.label; storageSpaceUsed = mDef.GetRequiredStorage(); def = mDef; }
private void DrawSeverityBar(ref float curY, ref Rect partListViewRect, MutationLayer layer, MutationDef mutationDef, List <Hediff_AddedMutation> mutationsOfDef) { // Draw the various labels for the severity bar (need to refine this later). string stageLabelText = $"Stage {mutationsOfDef.FirstOrDefault().CurStageIndex}: {mutationsOfDef.FirstOrDefault().LabelCap}"; Rect severityLabelsRect = new Rect(partListViewRect.x, curY, partListViewRect.width, Text.CalcHeight(stageLabelText, partListViewRect.width)); Text.Anchor = TextAnchor.MiddleLeft; Widgets.Label(severityLabelsRect, stageLabelText); Text.Anchor = TextAnchor.MiddleRight; Widgets.Label(severityLabelsRect, mutationsOfDef.FirstOrDefault().Severity.ToString("n2")); Text.Anchor = TextAnchor.UpperLeft; curY += severityLabelsRect.height; // Draw the severity slider float curSeverity = mutationsOfDef.Select(n => n.Severity).Average(); float newSeverity = Widgets.HorizontalSlider(new Rect(partListViewRect.x, curY, partListViewRect.width, SLIDER_HEIGHT), curSeverity, mutationDef.minSeverity, mutationDef.maxSeverity); if (curSeverity != newSeverity) { curSeverity = newSeverity; foreach (Hediff_AddedMutation mutationOfDef in mutationsOfDef) { MutationData relevantEntry = addedMutations.MutationsByPartAndLayer(mutationOfDef.Part, layer); if (relevantEntry != null) { relevantEntry.severity = newSeverity; } else { addedMutations.AddData(mutationOfDef.Def, mutationOfDef.Part, newSeverity, mutationOfDef.ProgressionHalted, false); } mutationOfDef.Severity = newSeverity; } recachePreview = true; } curY += SLIDER_HEIGHT; }
/// <summary> /// Adds the mutation to the given pawn /// </summary> /// <param name="pawn">The pawn.</param> /// <param name="mutation">The mutation.</param> /// <param name="records">The records to add mutations to</param> /// <param name="ancillaryEffects">The ancillary effects.</param> /// <exception cref="ArgumentNullException"> /// pawn /// or /// mutation /// or /// records /// </exception> public static MutationResult AddMutation([NotNull] Pawn pawn, [NotNull] MutationDef mutation, [NotNull] IEnumerable <BodyPartRecord> records, AncillaryMutationEffects?ancillaryEffects = null) { if (pawn == null) { throw new ArgumentNullException(nameof(pawn)); } if (mutation == null) { throw new ArgumentNullException(nameof(mutation)); } if (records == null) { throw new ArgumentNullException(nameof(records)); } HediffSet hSet = pawn.health?.hediffSet; if (hSet == null) { return(MutationResult.Empty); } List <Hediff_AddedMutation> lst = new List <Hediff_AddedMutation>(); foreach (BodyPartRecord bodyPartRecord in records) { if (bodyPartRecord.IsMissingAtAllIn(pawn)) { LogMsg(LogLevel.Pedantic, $"could not add {mutation.defName} to {pawn.Name} on {bodyPartRecord.Label} because it is missing or has a prosthetic"); continue; } if (HasAnyBlockingMutations(pawn, mutation, bodyPartRecord)) { continue; } var existingMutation = hSet.hediffs.FirstOrDefault(h => h.def == mutation && h.Part == bodyPartRecord); if (existingMutation != null) //resume adaption for mutations that are already added instead of re adding them { LogMsg(LogLevel.Pedantic, $"could not add {mutation.defName} to {pawn.Name} on {bodyPartRecord.Label} because it already has that mutation"); existingMutation.ResumeAdjustment(); //don't do count restarted mutations as new ones continue; } var hediff = HediffMaker.MakeHediff(mutation, pawn, bodyPartRecord) as Hediff_AddedMutation; if (hediff == null) { Log.Error($"{mutation.defName} is not a mutation but is being added like one!"); continue; } lst.Add(hediff); hSet.AddDirect(hediff); } AncillaryMutationEffects aEffects = ancillaryEffects ?? AncillaryMutationEffects.Default; if (lst.Count > 0) //only do this if we actually added any mutations { DoAncillaryMutationEffects(pawn, mutation, lst, aEffects); } return(new MutationResult(lst)); }
private static void ApplyMutations([NotNull] Pawn pawn, bool canApplyRestricted, bool setAtMaxStage, [NotNull] MorphPawnKindExtension kindExtension) { List <MutationDef> mutations; var addedPartsSet = new HashSet <BodyPartDef>(); if (!canApplyRestricted) { canApplyRestricted = pawn.CanReceiveRareMutations(); } if (canApplyRestricted) { mutations = kindExtension.GetRandomMutations(pawn.thingIDNumber).ToList(); } else { mutations = kindExtension.GetRandomMutations(pawn.thingIDNumber) .Where(g => !g.IsRestricted) //only keep the unrestricted mutations .ToList(); } if (mutations.Count == 0) { Warning($"could not get any mutations for {pawn.Name} using extension\n{kindExtension.ToStringFull()}"); } var toGive = new List <MutationDef>(); var addedList = new List <BodyPartRecord>(); int toGiveCount = kindExtension.hediffRange.RandomInRange; //get a random number of mutations to add int max = Mathf.Min(mutations.Count, toGiveCount); var i = 0; while (i < max) { if (mutations.Count == 0) { break; } while (true) { if (mutations.Count == 0) { break; } int rI = Rand.Range(0, mutations.Count); MutationDef mGiver = mutations[rI]; mutations.RemoveAt(rI); //remove the entry so we don't pull duplicates if (mGiver.parts.Any(p => p != null && addedPartsSet.Contains(p)) ) //make sure its for a part we haven't encountered yet { continue; } foreach (BodyPartDef part in mGiver.parts) { addedPartsSet.Add(part); } toGive.Add(mGiver); i++; //only count 1 regardless of what was added break; } } foreach (MutationDef giver in toGive) { giver.ClearOverlappingMutations(pawn); // make sure to remove any overlapping hediffs added during a different stage var result = MutationUtilities.AddMutation(pawn, giver, int.MaxValue, MutationUtilities.AncillaryMutationEffects.None); addedList.AddRange(result.Parts); } if (toGive.Count > 0 && (addedList.Count == 0 || !pawn.health.hediffSet.hediffs.OfType <Hediff_AddedMutation>().Any())) { LogMsg(LogLevel.Warnings, $"could not add mutations to pawn {pawn.Name} with ext\n{kindExtension}"); } if (setAtMaxStage) { var addedMutations = new List <Hediff_AddedMutation>(); List <Hediff_AddedMutation> allMutationsOnPawn = pawn.health.hediffSet.hediffs.OfType <Hediff_AddedMutation>().ToList(); //save these foreach (BodyPartRecord bodyPartRecord in addedList) //get a list of all mutations we just added { foreach (Hediff_AddedMutation mutation in allMutationsOnPawn) { if (mutation.Part == bodyPartRecord && toGive.Contains(mutation.def as MutationDef)) { if (!addedMutations.Contains(mutation)) { addedMutations.Add(mutation); } } } } foreach (Hediff_AddedMutation hediff in addedMutations) { if (hediff.pawn == null) { continue; //sometimes the hediffs are removed by other mutations } if (hediff.TryGetComp <HediffComp_Production>() != null) { continue; //do not increase production hediffs } var comp = hediff.TryGetComp <Comp_MutationSeverityAdjust>(); if (comp != null) { hediff.Severity = comp.NaturalSeverityLimit; continue; } HediffStage lastStage = hediff.def.stages?.LastOrDefault(); if (lastStage == null) { continue; } float severity = lastStage.minSeverity + 0.01f; hediff.Severity = severity; } } pawn.CheckRace(false); //don't apply missing mutations to avoid giving restricted mutations and to respect the limit }
private static void DoAncillaryMutationEffects(Pawn pawn, MutationDef mutation, List <Hediff_AddedMutation> addedParts, in AncillaryMutationEffects aEffects)
/// <summary> /// Determines whether this instance can generate the specified mutation. /// </summary> /// <param name="mDef">The m definition.</param> /// <returns> /// <c>true</c> if this instance with the specified m definition can generate ; otherwise, <c>false</c>. /// </returns> public bool CanGenerate(MutationDef mDef) { return(mDef.classInfluence.Contains(animalClass)); }