コード例 #1
0
        public static Thought_Memory GetSubstitute([NotNull] this Thought_Memory memory, [NotNull] Pawn pawn)
        {
            IEnumerable <ThoughtGroupDefExtension>
            tGroups = memory.def.modExtensions.MakeSafe().OfType <ThoughtGroupDefExtension>();

            foreach (ThoughtDef thoughtDef in tGroups.SelectMany(g => g.thoughts))
            {
                if (ThoughtUtility.CanGetThought(pawn, thoughtDef))
                {
                    int forcedStage = Mathf.Min(memory.CurStageIndex, thoughtDef.stages.Count - 1);

                    if (forcedStage != memory.CurStageIndex)
                    {
                        Log.Warning($"in memory {memory.def.defName}, substituted thought {thoughtDef.defName} does not the same number of stages\noriginal:{memory.def.stages.Count} sub:{thoughtDef.stages.Count}");
                    }

                    Thought_Memory newMemory = ThoughtMaker.MakeThought(thoughtDef, forcedStage);
                    if (newMemory == null)
                    {
                        Log.Error($"in thought {memory.def.defName} group, thought {thoughtDef.defName} is not a memory");
                        continue;
                    }

                    return(newMemory);
                }
            }

            return(memory);
        }
コード例 #2
0
        private void ApplyThought(Pawn thoughtReceiver, Pawn thoughtTarget, string defName)
        {
            var thought = ThoughtDef.Named(defName);

            if (ThoughtUtility.CanGetThought(thoughtReceiver, thought))
            {
                thoughtReceiver.needs.mood.thoughts.memories.TryGainMemory((Thought_Memory)ThoughtMaker.MakeThought(thought), thoughtTarget);
            }
        }
コード例 #3
0
        public static float ApparelScoreRaw(Pawn pawn, Apparel apparel, NeededWarmth neededWarmth = NeededWarmth.Any)
        {
            var outfit = pawn.outfits.CurrentOutfit as ExtendedOutfit;

            if (outfit == null)
            {
                Log.ErrorOnce("Outfitted :: Not an ExtendedOutfit, something went wrong.", 399441);
                return(0f);
            }

            float score = 0.1f + ApparelScoreRawPriorities(pawn, apparel, outfit);

            if (outfit.AutoWorkPriorities)
            {
                score += ApparelScoreAutoWorkPriorities(pawn, apparel);
            }

            if (apparel.def.useHitPoints)
            {
                float x = (float)apparel.HitPoints / apparel.MaxHitPoints;
                score *= HitPointsPercentScoreFactorCurve.Evaluate(x);
            }
            score += apparel.GetSpecialApparelScoreOffset();

            score += ApparelScoreRawInsulation(pawn, apparel, outfit, neededWarmth);

            if (outfit.PenaltyWornByCorpse && apparel.WornByCorpse && ThoughtUtility.CanGetThought(pawn, ThoughtDefOf.DeadMansApparel))
            {
                score -= 0.5f;
                if (score > 0f)
                {
                    score *= 0.1f;
                }
            }

            if (apparel.Stuff == ThingDefOf.Human.race.leatherDef)
            {
                if (ThoughtUtility.CanGetThought(pawn, ThoughtDefOf.HumanLeatherApparelSad))
                {
                    score -= 0.5f;
                    if (score > 0f)
                    {
                        score *= 0.1f;
                    }
                }
                if (ThoughtUtility.CanGetThought(pawn, ThoughtDefOf.HumanLeatherApparelHappy))
                {
                    score += 0.12f;
                }
            }

            return(score);
        }
コード例 #4
0
        public static bool HasSocialSituationalThought(Pawn pawn, Pawn other, ThoughtDef thought)
        {
            if (!ThoughtUtility.CanGetThought(pawn, thought))
            {
                return(false);
            }
            ThoughtState thoughtState = thought.Worker.CurrentSocialState(pawn, other);

            if (thoughtState.Active)
            {
                return(true);
            }
            return(false);
        }
コード例 #5
0
        /// <summary>
        /// Try to give this pawn a new memory. <br />
        /// If pawn does not have needs/mood/thoughts ect this call does nothing.
        /// </summary>
        /// <param name="pawn">The pawn.</param>
        /// <param name="thought">The thought.</param>
        /// <param name="otherPawn">The other pawn.</param>
        /// <param name="respectTraits">if ThoughtUtility.CanGetThought should be checked before giving the thought</param>
        /// <exception cref="ArgumentNullException">pawn</exception>
        public static void TryGainMemory([NotNull] this Pawn pawn, Thought_Memory thought, Pawn otherPawn = null, bool respectTraits = true) //move extension methods elsewhere?
        {
            if (pawn == null)
            {
                throw new ArgumentNullException(nameof(pawn));
            }
            if (respectTraits && !ThoughtUtility.CanGetThought(pawn, thought.def))
            {
                return;
            }


            pawn.needs?.mood?.thoughts?.memories?.TryGainMemory(thought, otherPawn);
        }
コード例 #6
0
        public static bool TryGainMemory(MemoryThoughtHandler __instance, Thought_Memory newThought, Pawn otherPawn = null)
        {
            if (!ThoughtUtility.CanGetThought(__instance.pawn, newThought.def))
            {
                return(false);
            }

            if (newThought is Thought_MemorySocial && newThought.otherPawn == null && otherPawn == null)
            {
                Log.Error(string.Concat("Can't gain social thought ", newThought.def, " because its otherPawn is null and otherPawn passed to this method is also null. Social thoughts must have otherPawn."));
                return(false);
            }

            newThought.pawn      = __instance.pawn;
            newThought.otherPawn = otherPawn;
            if (!newThought.TryMergeWithExistingMemory(out bool showBubble))
            {
                lock (__instance) //ADDED
                {
                    __instance.memories.Add(newThought);
                }
            }

            if (newThought.def.stackLimitForSameOtherPawn >= 0)
            {
                while (__instance.NumMemoriesInGroup(newThought) > newThought.def.stackLimitForSameOtherPawn)
                {
                    __instance.RemoveMemory(__instance.OldestMemoryInGroup(newThought));
                }
            }

            if (newThought.def.stackLimit >= 0)
            {
                while (__instance.NumMemoriesOfDef(newThought.def) > newThought.def.stackLimit)
                {
                    __instance.RemoveMemory(__instance.OldestMemoryOfDef(newThought.def));
                }
            }

            if (newThought.def.thoughtToMake != null)
            {
                __instance.TryGainMemory(newThought.def.thoughtToMake, newThought.otherPawn);
            }

            if (showBubble && newThought.def.showBubble && __instance.pawn.Spawned && PawnUtility.ShouldSendNotificationAbout(__instance.pawn))
            {
                MoteMaker.MakeMoodThoughtBubble(__instance.pawn, newThought);
            }
            return(false);
        }
コード例 #7
0
        public static ThoughtDef GetSubstitute([NotNull] this ThoughtDef def, [NotNull] Pawn pawn)
        {
            IEnumerable <ThoughtGroupDefExtension> tGroups = def.modExtensions.MakeSafe().OfType <ThoughtGroupDefExtension>();

            foreach (ThoughtDef thoughtDef in tGroups.SelectMany(g => g.thoughts))
            {
                if (ThoughtUtility.CanGetThought(pawn, thoughtDef)) //take the first one that matches
                {
                    return(thoughtDef);
                }
            }
            //no matches found
            return(def);
        }
コード例 #8
0
 public override void GameConditionTick()
 {
     base.GameConditionTick();
     if (firstTick)
     {
         foreach (Pawn pawn in Map.mapPawns.FreeColonistsAndPrisoners)
         {
             if (ThoughtUtility.CanGetThought(pawn, HPLDefOf.HPLovecraft_SawBloodMoonSad))
             {
                 pawn.needs.mood.thoughts.memories.TryGainMemory(HPLDefOf.HPLovecraft_SawBloodMoonSad);
             }
             else if (ThoughtUtility.CanGetThought(pawn, HPLDefOf.HPLovecraft_SawBloodMoonHappy))
             {
                 pawn.needs.mood.thoughts.memories.TryGainMemory(HPLDefOf.HPLovecraft_SawBloodMoonHappy);
             }
         }
         firstTick = false;
     }
 }
コード例 #9
0
        public override void GameConditionTick()
        {
            base.GameConditionTick();
            if (!firstTick)
            {
                return;
            }

            firstTick = false;

            var affectedPawns = new List <Pawn>();

            foreach (var map in AffectedMaps)
            {
                affectedPawns.AddRange(map.mapPawns.FreeColonistsAndPrisoners);

                //Add a wolf pack
                var wolfType = map.mapTemperature.OutdoorTemp > 0f
                    ? PawnKindDef.Named("Wolf_Timber")
                    : PawnKindDef.Named("Wolf_Arctic");
                RCellFinder.TryFindRandomPawnEntryCell(out var loc, map, CellFinder.EdgeRoadChance_Animal);
                var numberOfWolves = Rand.Range(3, 6);
                for (var i = 0; i < numberOfWolves; i++)
                {
                    var newWolf = PawnGenerator.GeneratePawn(wolfType);
                    GenSpawn.Spawn(newWolf, loc, map);
                }
            }

            foreach (var pawn in affectedPawns)
            {
                if (ThoughtUtility.CanGetThought(pawn, HPLDefOf.HPLovecraft_SawBloodMoonSad))
                {
                    pawn.needs.mood.thoughts.memories.TryGainMemory(HPLDefOf.HPLovecraft_SawBloodMoonSad);
                    continue;
                }

                if (ThoughtUtility.CanGetThought(pawn, HPLDefOf.HPLovecraft_SawBloodMoonHappy))
                {
                    pawn.needs.mood.thoughts.memories.TryGainMemory(HPLDefOf.HPLovecraft_SawBloodMoonHappy);
                }
            }
        }
コード例 #10
0
            private static void CanGetThoughtPostfix([NotNull] Pawn pawn, [NotNull] ThoughtDef def, ref bool __result)
            {
                var tracker = pawn.GetAspectTracker();

                if (tracker != null)
                {
                    foreach (Aspect aspect in tracker)
                    {
                        if (aspect.NullifiedThoughts.Contains(def))
                        {
                            __result = false;
                            break;
                        }
                    }
                }

                var tGroup = def.GetModExtension <ThoughtGroupDefExtension>();

                if (tGroup != null && !__result)
                {
                    //if the default thought is invalid and it has a thought group extension check if any of the specific thoughts are valid
                    foreach (ThoughtDef tGroupThought in tGroup.thoughts)
                    {
                        if (tGroupThought.HasModExtension <ThoughtGroupDefExtension>())
                        {
                            Log.Warning($"thought in {def.defName} has thought {tGroupThought.defName} with thought group extension! this is not currently supported as it may cause infinite recursion");
                            continue;
                        }

                        if (ThoughtUtility.CanGetThought(pawn, tGroupThought))
                        {
                            __result = true;
                            return;
                        }
                    }
                }

                if (__result)
                {
                    __result = def.IsValidFor(pawn);
                }
            }
コード例 #11
0
        public static void GainSocialThought(Pawn initiator, Pawn target, ThoughtDef thoughtDef)
        {
            if (!ThoughtUtility.CanGetThought(target, thoughtDef))
            {
                return;
            }

            float impact        = initiator.GetStatValue(StatDefOf.SocialImpact);
            var   thoughtMemory = (Thought_Memory)ThoughtMaker.MakeThought(thoughtDef);

            thoughtMemory.moodPowerFactor = impact;

            var thoughtSocialMemory = thoughtMemory as Thought_MemorySocial;

            if (thoughtSocialMemory != null)
            {
                thoughtSocialMemory.opinionOffset *= impact;
            }
            target.needs.mood.thoughts.memories.TryGainMemory(thoughtMemory, initiator);
        }
コード例 #12
0
        HandleRelatedPawnsReaction(Pawn original, Pawn animalPawn,
                                   EventType type)     //use PotentiallyRelatedPawns to get all relationships not DirectRelations for some reason
        {
            foreach (Pawn pReactor in original.relations.PotentiallyRelatedPawns)
            {
                if (pReactor == animalPawn)
                {
                    continue;                        //make sure pawns don't react to themselves as if it were a different pawn
                }
                if (pReactor == original)
                {
                    continue;
                }
                if (pReactor.needs?.mood == null)
                {
                    continue;
                }
                PawnRelationDef importantRelation = pReactor.GetMostImportantRelation(original);
                var             modExt            = importantRelation?.GetModExtension <RelationshipDefExtension>();

                if (modExt != null)
                {
                    ThoughtDef thought = modExt.GetThoughtDef(type, original.gender);
                    if (thought == null)
                    {
                        Log.Warning($"relation {importantRelation.defName} has (Pawnmorpher) extension but no thought for {type}, is this intentional?");
                        continue;
                    }

                    if (ThoughtUtility.CanGetThought(pReactor, thought))
                    {
                        pReactor.TryGainMemory(thought);
                    }
                }
            }

            //TODO handle bond animal reverted?
        }
コード例 #13
0
        private void TryAddMemory(Pawn pawn, ThoughtDef memory)
        {
            ThoughtHandler thoughts = pawn.needs?.mood?.thoughts;

            if (thoughts == null)
            {
                return;
            }

            if (!ThoughtUtility.CanGetThought(pawn, memory))
            {
                return;
            }

            var counter = 0;
            int max     = PMUtilities.GetSettings().maxMutationThoughts;

            if (!ignoreThoughtLimit)
            {
                foreach (Thought_Memory thought in thoughts.memories.Memories)
                {
                    if (MutationUtilities.AllMutationMemories.Contains(thought.def))
                    {
                        counter++;
                    }

                    counter++;
                    if (counter >= max)
                    {
                        return;                 //make sure to only add so many thoughts at once
                    }
                }
            }

            pawn.TryGainMemory(memory);
        }
コード例 #14
0
        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(pawn, ThoughtDefOf.DeadMansApparel, true))
                {
                    score -= 0.5f;
                    if (score > 0f)
                    {
                        score *= 0.1f;
                    }
                }

                if (apparel.Stuff == ThingDefOf.Human.race.leatherDef)
                {
                    if (ThoughtUtility.CanGetThought(pawn, ThoughtDefOf.HumanLeatherApparelSad, true))
                    {
                        score -= 0.5f;
                        if (score > 0f)
                        {
                            score *= 0.1f;
                        }
                    }
                    if (ThoughtUtility.CanGetThought(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);
        }
コード例 #15
0
        public override void DoWindowContents(Rect inRect)
        {
            ApparelStatCache conf = this._pawn.GetApparelStatCache();

            Rect conRect = new Rect(inRect);

            conRect.height -= 50f;

            BeginArea(conRect);

            // begin main group
            BeginVertical();

            Label(this.GetTitle(), this._headline);
            Text.Font = GameFont.Small;

            // GUI.BeginGroup(contentRect);
            float labelWidth = conRect.width - BaseValue - BaseValue - BaseValue - 48f;

            this.DrawLine("Status", labelWidth, "BaseMod", "Strength", "Score", this._fontBold);

            Space(6f);
            Label(string.Empty, this._whiteLine, Height(1));
            Space(6f);

            ApparelEntry apparelEntry = conf.GetAllOffsets(this._apparel);

            HashSet <StatDef> equippedOffsets = apparelEntry.EquippedOffsets;
            HashSet <StatDef> statBases       = apparelEntry.StatBases;
            HashSet <StatDef> infusedOffsets  = apparelEntry.InfusedOffsets;

            this._scrollPosition = BeginScrollView(this._scrollPosition, Width(conRect.width));

            // relevant apparel stats

            // start score at 1
            float score = 1;

            // add values for each statdef modified by the apparel
            foreach (StatPriority statPriority in this._pawn.GetApparelStatCache().StatCache
                     .OrderBy(i => i.Stat.LabelCap))
            {
                StatDef stat      = statPriority.Stat;
                string  statLabel = stat.LabelCap;

                // statbases, e.g. armor

                // StatCache.DoApparelScoreRaw_PawnStatsHandlers(_pawn, _apparel, statPriority.Stat, ref currentStat);
                if (statBases.Contains(stat))
                {
                    float statValue = this._apparel.GetStatValue(stat);
                    float statScore = 0f;
                    if (ApparelStatCache.SpecialStats.Contains(stat))
                    {
                        ApparelStatCache.CalculateScoreForSpecialStats(this._apparel, statPriority, this._pawn, statValue, ref statScore);
                    }
                    else
                    {
                        // statValue += StatCache.StatInfused(infusionSet, statPriority, ref baseInfused);
                        statScore = statValue * statPriority.Weight;
                    }

                    score += statScore;

                    this.DrawLine(
                        statLabel,
                        labelWidth,
                        statValue.ToStringPercent("N1"),
                        statPriority.Weight.ToString("N2"),
                        statScore.ToString("N2"));
                }

                if (equippedOffsets.Contains(stat))
                {
                    float statValue = this._apparel.GetEquippedStatValue(this._pawn, stat);

                    // statValue += StatCache.StatInfused(infusionSet, statPriority, ref equippedInfused);
                    float statScore = 0f;
                    if (ApparelStatCache.SpecialStats.Contains(stat))
                    {
                        ApparelStatCache.CalculateScoreForSpecialStats(this._apparel, statPriority, this._pawn, statValue, ref statScore);
                    }
                    else
                    {
                        statScore = statValue * statPriority.Weight;
                    }

                    score += statScore;

                    this.DrawLine(
                        statLabel,
                        labelWidth,
                        statValue.ToStringPercent("N1"),
                        statPriority.Weight.ToString("N2"),
                        statScore.ToString("N2"));
                }

                if (infusedOffsets.Contains(stat))
                {
                    GUI.color = Color.green; // new Color(0.5f, 1f, 1f, 1f);

                    // float statInfused = StatCache.StatInfused(infusionSet, statPriority, ref dontcare);
                    ApparelStatCache.DoApparelScoreRaw_PawnStatsHandlers(this._apparel, stat, out float statValue);

                    bool flag = true;

                    float statScore = 0f;
                    if (ApparelStatCache.SpecialStats.Contains(stat))
                    {
                        ApparelStatCache.CalculateScoreForSpecialStats(this._apparel,
                                                                       statPriority, this._pawn,
                                                                       statValue,
                                                                       ref statScore);
                    }
                    else
                    {
                        // Bug with Infused and "Ancient", it completely kills the pawn's armor
                        if (statValue < 0 &&
                            (stat == StatDefOf.ArmorRating_Blunt || stat == StatDefOf.ArmorRating_Sharp))
                        {
                            score = -2f;
                            flag  = false;
                        }

                        statScore = statValue * statPriority.Weight;
                    }

                    this.DrawLine(
                        statLabel,
                        labelWidth,
                        statValue.ToStringPercent("N1"),
                        statPriority.Weight.ToString("N2"),
                        statScore.ToString("N2"));

                    GUI.color = Color.white;

                    if (flag)
                    {
                        score += statScore;
                    }
                    else
                    {
                        break;
                    }
                }
            }

            GUI.color = Color.white;

            // end upper group
            EndScrollView();

            // begin lower group
            FlexibleSpace();
            Space(6f);
            Label(string.Empty, this._whiteLine, Height(1));
            Space(6f);
            this.DrawLine(string.Empty, labelWidth, "Modifier", string.Empty, "Subtotal");

            this.DrawLine("BasicStatusOfApparel".Translate(), labelWidth, "1.00", "+", score.ToString("N2"));

            float special = this._apparel.GetSpecialApparelScoreOffset();

            if (Math.Abs(special) > 0f)
            {
                score += special;

                this.DrawLine(
                    "OutfitterSpecialScore".Translate(),
                    labelWidth,
                    special.ToString("N2"),
                    "+",
                    score.ToString("N2"));
            }

            float armor = ApparelStatCache.ApparelScoreRaw_ProtectionBaseStat(this._apparel);

            if (Math.Abs(armor) > 0.01f)
            {
                score += armor;

                this.DrawLine("OutfitterArmor".Translate(), labelWidth, armor.ToString("N2"), "+", score.ToString("N2"));
            }

            if (this._apparel.def.useHitPoints)
            {
                // durability on 0-1 scale
                float x = this._apparel.HitPoints / (float)this._apparel.MaxHitPoints;
                score *= ApparelStatsHelper.HitPointsPercentScoreFactorCurve.Evaluate(x);

                this.DrawLine(
                    "OutfitterHitPoints".Translate(),
                    labelWidth,
                    x.ToString("N2"),
                    "weighted",
                    score.ToString("N2"));

                GUI.color = Color.white;
            }

            if (this._apparel.WornByCorpse && ThoughtUtility.CanGetThought(this._pawn, ThoughtDefOf.DeadMansApparel))
            {
                score -= 0.5f;
                if (score > 0f)
                {
                    score *= 0.1f;
                }

                this.DrawLine(
                    "OutfitterWornByCorpse".Translate(),
                    labelWidth,
                    "modified",
                    "weighted",
                    score.ToString("N2"));
            }

            if (this._apparel.Stuff == ThingDefOf.Human.race.leatherDef)
            {
                if (ThoughtUtility.CanGetThought(this._pawn, ThoughtDefOf.HumanLeatherApparelSad))
                {
                    score -= 0.5f;
                    if (score > 0f)
                    {
                        score *= 0.1f;
                    }
                }

                if (ThoughtUtility.CanGetThought(this._pawn, ThoughtDefOf.HumanLeatherApparelHappy))
                {
                    score *= 2f;
                }

                this.DrawLine(
                    "OutfitterHumanLeather".Translate(),
                    labelWidth,
                    "modified",
                    "weighted",
                    score.ToString("N2"));
            }

            float temperature = conf.ApparelScoreRaw_Temperature(this._apparel);

            if (Math.Abs(temperature - 1f) > 0)
            {
                score *= temperature;

                this.DrawLine(
                    "OutfitterTemperature".Translate(),
                    labelWidth,
                    temperature.ToString("N2"),
                    "*",
                    score.ToString("N2"));
            }

            this.DrawLine(
                "OutfitterTotal".Translate(),
                labelWidth,
                string.Empty,
                "=",
                conf.ApparelScoreRaw(this._apparel).ToString("N2"));

            GUI.color   = Color.white;
            Text.Anchor = TextAnchor.UpperLeft;

            // end main group
            EndVertical();
            EndArea();
        }
コード例 #16
0
        public float ApparelScoreRaw([NotNull] Apparel ap)
        {
            if (this.RawScoreDict.ContainsKey(ap))
            {
                return(this.RawScoreDict[ap]);
            }

            // only allow shields to be considered if a primary weapon is equipped and is melee
            Pawn thisPawn = this._pawn;

            if (ap.def.thingClass == typeof(ShieldBelt) && thisPawn.equipment.Primary?.def.IsRangedWeapon == true)
            {
                return(-1f);
            }

            // Fail safe to prevent pawns get out of the regular temperature.
            // Might help making pawn drop equipped apparel if it's too cold/warm.
            // this.GetInsulationStats(ap, out float insulationCold, out float insulationHeat);
            // FloatRange temperatureRange = this.pawn.ComfortableTemperatureRange();
            // if (ap.Wearer != thisPawn)
            // {
            // temperatureRange.min += insulationCold;
            // temperatureRange.max += insulationHeat;
            // }
            // if (temperatureRange.min > 12 && insulationCold > 0 || temperatureRange.max < 32 && insulationHeat < 0)
            // {
            // return -3f;
            // }

            // relevant apparel stats
            ApparelEntry entry = this.GetAllOffsets(ap);

            HashSet <StatDef> statBases       = entry.StatBases;
            HashSet <StatDef> equippedOffsets = entry.EquippedOffsets;
            HashSet <StatDef> infusedOffsets  = entry.InfusedOffsets;

            // start score at 1
            float score = 1;

            // add values for each statdef modified by the apparel
            List <StatPriority> stats = thisPawn.GetApparelStatCache().StatCache;

            foreach (StatPriority statPriority in stats.Where(statPriority => statPriority != null))
            {
                StatDef stat = statPriority.Stat;

                if (statBases.Contains(stat))
                {
                    float apStat = ap.GetStatValue(stat);

                    if (SpecialStats.Contains(stat))
                    {
                        CalculateScoreForSpecialStats(ap, statPriority, thisPawn, apStat, ref score);
                    }
                    else
                    {
                        // 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 += apStat * statPriority.Weight;
                    }
                }

                // equipped offsets, e.g. movement speeds
                if (equippedOffsets.Contains(stat))
                {
                    float apStat = ap.GetEquippedStatValue(this._pawn, stat);

                    if (SpecialStats.Contains(stat))
                    {
                        CalculateScoreForSpecialStats(ap, statPriority, thisPawn, apStat, ref score);
                    }
                    else
                    {
                        score += apStat * statPriority.Weight;
                    }

                    // multiply score to favour items with multiple offsets
                    // score *= adjusted;

                    // debug.AppendLine( statWeightPair.Key.LabelCap + ": " + score );
                }

                // infusions
                if (infusedOffsets.Contains(stat))
                {
                    // float statInfused = StatInfused(infusionSet, statPriority, ref dontcare);
                    DoApparelScoreRaw_PawnStatsHandlers(ap, stat, out float statInfused);

                    if (SpecialStats.Contains(stat))
                    {
                        CalculateScoreForSpecialStats(ap, statPriority, thisPawn, statInfused, ref score);
                    }
                    else
                    {
                        // Bug with Infused and "Ancient", it completely kills the pawn's armor
                        if (statInfused < 0 && (stat == StatDefOf.ArmorRating_Blunt ||
                                                stat == StatDefOf.ArmorRating_Sharp))
                        {
                            score = -2f;
                            return(score);
                        }

                        score += statInfused * statPriority.Weight;
                    }
                }
            }

            score += ap.GetSpecialApparelScoreOffset();

            score += ApparelScoreRaw_ProtectionBaseStat(ap);

            // offset for apparel hitpoints
            if (ap.def.useHitPoints)
            {
                float x = ap.HitPoints / (float)ap.MaxHitPoints;
                score *= ApparelStatsHelper.HitPointsPercentScoreFactorCurve.Evaluate(x);
            }

            if (ap.WornByCorpse && ThoughtUtility.CanGetThought(thisPawn, ThoughtDefOf.DeadMansApparel))
            {
                score -= 0.5f;
                if (score > 0f)
                {
                    score *= 0.1f;
                }
            }

            if (ap.Stuff == ThingDefOf.Human.race.leatherDef)
            {
                if (ThoughtUtility.CanGetThought(thisPawn, ThoughtDefOf.HumanLeatherApparelSad))
                {
                    score -= 0.5f;
                    if (score > 0f)
                    {
                        score *= 0.1f;
                    }
                }

                if (ThoughtUtility.CanGetThought(thisPawn, ThoughtDefOf.HumanLeatherApparelHappy))
                {
                    score *= 2f;
                }
            }

            score *= this.ApparelScoreRaw_Temperature(ap);

            this.RawScoreDict.Add(ap, score);

            return(score);
        }
コード例 #17
0
        /// <summary>
        ///     call when 2 pawns are merged into one meld/merge to handle giving the correct thoughts to colonists
        /// </summary>
        /// <param name="merge0">the first pawn of the merge</param>
        /// <param name="wasPrisoner0">if the first pawn was a prisoner</param>
        /// <param name="merge1">the second pawn of the merge</param>
        /// <param name="wasPrisoner1">if the second pawn was a prisoner</param>
        /// <param name="animalPawn">the resulting animal pawn</param>
        public static void OnPawnsMerged(Pawn merge0, bool wasPrisoner0, Pawn merge1, bool wasPrisoner1, Pawn animalPawn) //TODO take reaction status into account
        {
            _scratchList.Clear();
            _scratchList.AddRange(PawnsFinder.AllMapsCaravansAndTravelingTransportPods_Alive_FreeColonists
                                  .Where(p => p != merge0 && p != merge1));
            //don't give the merged pawns thoughts about themselves

            HandleColonistReactions(merge0, animalPawn, wasPrisoner0 ? FormerHumanReactionStatus.Prisoner : FormerHumanReactionStatus.Colonist, EventType.Merged, _scratchList);
            HandleColonistReactions(merge1, animalPawn, wasPrisoner1 ? FormerHumanReactionStatus.Prisoner : FormerHumanReactionStatus.Colonist, EventType.Merged, _scratchList);


            //need to handle relationships manually

            _scratchList.Clear();

            bool IsValidRelation(Pawn p)
            {
                return(p != merge0 && p != merge1 && p.needs?.mood != null && p.relations != null);
            }

            IEnumerable <Pawn> linq = merge0.relations.PotentiallyRelatedPawns.Where(IsValidRelation);


            foreach (Pawn rPawn in linq)
            {
                PawnRelationDef relation = rPawn.GetMostImportantRelation(merge0);
                var             modExt   = relation?.GetModExtension <RelationshipDefExtension>();
                if (modExt == null)
                {
                    continue;
                }

                ThoughtDef thought = modExt.GetThoughtDef(EventType.Merged, merge0.gender);
                if (thought == null)
                {
                    Log.Warning($"relationship {relation.defName} has (pawnmorpher) extension but no thought for morphing, is this intentional?");
                    continue;
                }

                if (ThoughtUtility.CanGetThought(rPawn, thought))
                {
                    rPawn.TryGainMemory(thought);
                }
            }

            foreach (Pawn rPawn in merge1.relations.PotentiallyRelatedPawns.Where(IsValidRelation))
            {
                PawnRelationDef relation = rPawn.GetMostImportantRelation(merge1);
                var             modExt   = relation?.GetModExtension <RelationshipDefExtension>();
                if (modExt == null)
                {
                    continue;
                }

                ThoughtDef thought = modExt.GetThoughtDef(EventType.Merged, merge0.gender);
                if (thought == null)
                {
                    Log.Warning($"relationship {relation.defName} has (pawnmorpher) extension but no thought for morphing, is this intentional?");
                    continue;
                }

                if (ThoughtUtility.CanGetThought(rPawn, thought))
                {
                    rPawn.TryGainMemory(thought);
                }
            }
        }
コード例 #18
0
        public static float ApparelScoreRaw(Pawn pawn, Apparel ap)
        {
            float num  = 0.1f + ap.def.apparel.scoreOffset;
            float num2 = ap.GetStatValue(StatDefOf.ArmorRating_Sharp) + ap.GetStatValue(StatDefOf.ArmorRating_Blunt) + ap.GetStatValue(StatDefOf.ArmorRating_Heat);

            num += num2;
            if (ap.def.useHitPoints)
            {
                float x = (float)ap.HitPoints / (float)ap.MaxHitPoints;
                num *= HitPointsPercentScoreFactorCurve.Evaluate(x);
            }
            num += ap.GetSpecialApparelScoreOffset();
            float num3 = 1f;

            //if (neededWarmth == NeededWarmth.Warm)
            //{
            //	float statValue = ap.GetStatValue(StatDefOf.Insulation_Cold);
            //	num3 *= InsulationColdScoreFactorCurve_NeedWarm.Evaluate(statValue);
            //}
            num *= num3;
            if (ap.WornByCorpse && (pawn == null || ThoughtUtility.CanGetThought(pawn, ThoughtDefOf.DeadMansApparel, checkIfNullified: true)))
            {
                num -= 0.5f;
                if (num > 0f)
                {
                    num *= 0.1f;
                }
            }
            if (ap.Stuff == ThingDefOf.Human.race.leatherDef)
            {
                if (pawn == null || ThoughtUtility.CanGetThought(pawn, ThoughtDefOf.HumanLeatherApparelSad, checkIfNullified: true))
                {
                    num -= 0.5f;
                    if (num > 0f)
                    {
                        num *= 0.1f;
                    }
                }
                if (pawn != null && ThoughtUtility.CanGetThought(pawn, ThoughtDefOf.HumanLeatherApparelHappy, checkIfNullified: true))
                {
                    num += 0.12f;
                }
            }
            if (pawn != null && !ap.def.apparel.CorrectGenderForWearing(pawn.gender))
            {
                num *= 0.01f;
            }
            if (pawn != null && pawn.royalty != null && pawn.royalty.AllTitlesInEffectForReading.Count > 0)
            {
                tmpAllowedApparels.Clear();
                tmpRequiredApparels.Clear();
                tmpBodyPartGroupsWithRequirement.Clear();
                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 ((int)item.def.requiredMinimumApparelQuality > (int)qualityCategory)
                    {
                        qualityCategory = item.def.requiredMinimumApparelQuality;
                    }
                }
                bool num4 = ap.def.apparel.bodyPartGroups.Any((BodyPartGroupDef bp) => tmpBodyPartGroupsWithRequirement.Contains(bp));
                if (ap.TryGetQuality(out QualityCategory qc) && (int)qc < (int)qualityCategory)
                {
                    num *= 0.25f;
                }
                if (num4)
                {
                    foreach (ThingDef tmpRequiredApparel in tmpRequiredApparels)
                    {
                        tmpAllowedApparels.Remove(tmpRequiredApparel);
                    }
                    if (tmpAllowedApparels.Contains(ap.def))
                    {
                        num *= 10f;
                    }
                    if (tmpRequiredApparels.Contains(ap.def))
                    {
                        num *= 25f;
                    }
                }
            }
            return(num);
        }
コード例 #19
0
        private static void HandleColonistReactions(Pawn original, Pawn transformedPawn, FormerHumanReactionStatus reactionStatus, EventType type,
                                                    IEnumerable <Pawn> pawns = null)
        {
            pawns = pawns
                    ?? PawnsFinder.AllMapsCaravansAndTravelingTransportPods_Alive_FreeColonists
                    .Where(p => p != original);            //use all colonists except the original pawn as the default



            ThoughtDef defaultThought;

            switch (type)
            {
            case EventType.Transformation:
                defaultThought = ThoughtDefOfs.DefaultTransformationReaction;
                break;

            case EventType.Reverted:
                defaultThought = ThoughtDefOfs.DefaultRevertedPawnReaction;
                break;

            case EventType.PermanentlyFeral:
                defaultThought = ThoughtDefOfs.DefaultPermanentlyFeralReaction;
                break;

            case EventType.Merged:
                defaultThought = ThoughtDefOfs.DefaultMergedThought;
                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(type), type, null);
            }

            int defaultStage = (int)reactionStatus;

            defaultStage = Mathf.Min(defaultStage, (defaultThought?.stages?.Count - 1) ?? 0);


            foreach (Pawn reactor in pawns)
            {
                if (reactor == transformedPawn)
                {
                    continue;                            //make sure pawns don't react to themselves as if they were a different pawn
                }
                ThoughtDef opinionThought = GetOpinionThought(original, reactor, type);
                ThoughtDef def;
                if (opinionThought != null)
                {
                    def          = opinionThought;
                    defaultStage = 0;
                }
                else
                {
                    def = defaultThought;
                }

                if (def == null)
                {
                    continue;
                }
                if (ThoughtUtility.CanGetThought(reactor, def))
                {
                    var memory = ThoughtMaker.MakeThought(def, defaultStage);
                    reactor.TryGainMemory(memory);
                }
            }
        }