Пример #1
0
        static void DrawCloneButton(ExtendedOutfit selectedOutfit)
        {
            Rect rect = new Rect(480, 0f, 150f, 35f);

            if (Widgets.ButtonText(rect, "CommandCopyZoneSettingsLabel".Translate(), true, true, true))
            {
                if (selectedOutfit == null)
                {
                    Messages.Message("NoOutfitSelected".Translate(), MessageTypeDefOf.RejectInput, false);
                    return;
                }

                List <FloatMenuOption> list2 = new List <FloatMenuOption>();
                foreach (Outfit outfit in Current.Game.outfitDatabase.AllOutfits)
                {
                    if (outfit == selectedOutfit)
                    {
                        continue;
                    }
                    list2.Add(new FloatMenuOption(outfit.label, () => selectedOutfit.CopyFrom((ExtendedOutfit)outfit), MenuOptionPriority.Default, null, null, 0f, null, null));
                }

                Find.WindowStack.Add(new FloatMenu(list2));
            }
        }
        static void DrawTemperatureStats(ExtendedOutfit selectedOutfit, ref Vector2 cur, Rect canvas)
        {
            // header
            Rect tempHeaderRect = new Rect(cur.x, cur.y, canvas.width, 30f);

            cur.y      += 30f;
            Text.Anchor = TextAnchor.LowerLeft;
            Widgets.Label(tempHeaderRect, ResourceBank.Strings.PreferedTemperature);
            Text.Anchor = TextAnchor.UpperLeft;

            // line
            GUI.color = Color.grey;
            Widgets.DrawLineHorizontal(cur.x, cur.y, canvas.width);
            GUI.color = Color.white;

            // some padding
            cur.y += marginVertical;

            // temperature slider
            Rect sliderRect    = new Rect(cur.x, cur.y, canvas.width - 20f, 40f);
            Rect tempResetRect = new Rect(sliderRect.xMax + 4f, cur.y + marginVertical, 16f, 16f);

            cur.y += 40f; // includes padding

            FloatRange targetTemps;

            if (selectedOutfit.targetTemperaturesOverride)
            {
                targetTemps = selectedOutfit.targetTemperatures;
                GUI.color   = Color.white;
            }
            else
            {
                targetTemps = MinMaxTemperatureRange;
                GUI.color   = Color.grey;
            }
            FloatRange minMaxTemps = MinMaxTemperatureRange;

            Widgets_FloatRange.FloatRange(sliderRect, 123123123, ref targetTemps, minMaxTemps, ToStringStyle.Temperature);
            GUI.color = Color.white;

            if (Math.Abs(targetTemps.min - selectedOutfit.targetTemperatures.min) > 1e-4 ||
                Math.Abs(targetTemps.max - selectedOutfit.targetTemperatures.max) > 1e-4)
            {
                selectedOutfit.targetTemperatures         = targetTemps;
                selectedOutfit.targetTemperaturesOverride = true;
            }

            if (selectedOutfit.targetTemperaturesOverride)
            {
                if (Widgets.ButtonImage(tempResetRect, ResourceBank.Textures.ResetButton))
                {
                    selectedOutfit.targetTemperaturesOverride = false;
                    selectedOutfit.targetTemperatures         = MinMaxTemperatureRange;
                }

                TooltipHandler.TipRegion(tempResetRect, ResourceBank.Strings.TemperatureRangeReset);
            }
        }
        static void DrawAutoWorkPrioritiesToggle(ExtendedOutfit outfit, ref Vector2 pos, Rect canvas)
        {
            Rect rect = new Rect(pos.x, pos.y, canvas.width, 30f);

            Widgets.CheckboxLabeled(rect, ResourceBank.Strings.AutoWorkPriorities,
                                    ref outfit.AutoWorkPriorities);
            TooltipHandler.TipRegion(rect, ResourceBank.Strings.AutoWorkPrioritiesTooltip);
            pos.y += rect.height;
        }
        static void DrawDeadmanToogle(ExtendedOutfit selectedOutfit, ref Vector2 cur, Rect canvas)
        {
            Rect rect = new Rect(cur.x, cur.y, canvas.width, 30f);

            Widgets.CheckboxLabeled(rect, ResourceBank.Strings.PenaltyWornByCorpse,
                                    ref selectedOutfit.PenaltyWornByCorpse);
            TooltipHandler.TipRegion(rect, ResourceBank.Strings.PenaltyWornByCorpseTooltip);
            cur.y += rect.height;
        }
Пример #5
0
        public static void Watch(ref ExtendedOutfit outfit)
        {
            selectedOutfitId = outfit.uniqueId;

            targetTemperaturesOverride.Watch(outfit);
            targetTemperatures.Watch(outfit);
            PenaltyWornByCorpse.Watch(outfit);
            AutoWorkPriorities.Watch(outfit);
            selectedStatPrioritySF.Watch(Instance);
        }
Пример #6
0
        static void DrawAutoTempOffsetInput(ExtendedOutfit outfit, ref Vector2 pos, Rect canvas)
        {
            Rect rect = new Rect(pos.x, pos.y, canvas.width, 30f);
            //TODO: input label
            var autoTempOffsetString = outfit.autoTempOffset.ToString();

            Widgets.IntEntry(rect, ref outfit.autoTempOffset, ref autoTempOffsetString);
            TooltipHandler.TipRegion(rect, ResourceBank.Strings.AutoTempOffsetTooltip);
            pos.y += rect.height;
        }
Пример #7
0
        static void DrawAutoTempToggle(ExtendedOutfit outfit, ref Vector2 pos, Rect canvas)
        {
            Rect rect     = new Rect(pos.x, pos.y, canvas.width, 30f);
            var  autoTemp = outfit.AutoTemp;

            Widgets.CheckboxLabeled(rect, ResourceBank.Strings.AutoTemp,
                                    ref autoTemp);
            outfit.AutoTemp = autoTemp;
            TooltipHandler.TipRegion(rect, ResourceBank.Strings.AutoTempTooltip);
            pos.y += rect.height;
        }
Пример #8
0
 public void CopyFrom(ExtendedOutfit outfit)
 {
     filter.CopyAllowancesFrom(outfit.filter);
     targetTemperaturesOverride = outfit.targetTemperaturesOverride;
     targetTemperatures         = outfit.targetTemperatures;
     PenaltyWornByCorpse        = outfit.PenaltyWornByCorpse;
     statPriorities.Clear();
     statPriorities.AddRange(outfit.statPriorities);
     AutoWorkPriorities = outfit.AutoWorkPriorities;
     _autoTemp          = outfit._autoTemp;
     autoTempOffset     = outfit.autoTempOffset;
 }
Пример #9
0
        static float ApparelScoreRawPriorities(Apparel apparel, ExtendedOutfit outfit)
        {
            if (outfit?.StatPriorities.Any() != true)
            {
                return(0f);
            }

            return(outfit.StatPriorities
                   .Select(sp => new
            {
                weight = sp.Weight,
                value = apparel.def.equippedStatOffsets.GetStatOffsetFromList(sp.Stat) + apparel.GetStatValue(sp.Stat),
                def = sp.Stat.defaultBaseValue,
            })
                   .Average(sp => (Math.Abs(sp.def) < 0.001f ? sp.value : (sp.value - sp.def) / sp.def) * Mathf.Pow(sp.weight, 3)));
        }
Пример #10
0
        static void ExtendedOutfitSyncer(SyncWorker sync, ref ExtendedOutfit outfit)
        {
            if (sync.isWriting)
            {
                sync.Bind(ref outfit.uniqueId);
            }
            else
            {
                int uid = 0;

                sync.Bind(ref uid);

                var currentOutfit = Current.Game.outfitDatabase.AllOutfits.Find(o => o.uniqueId == uid);
                if (currentOutfit is ExtendedOutfit extendedOutfit)
                {
                    outfit = extendedOutfit;
                }
            }
        }
Пример #11
0
 public static void Watch(ref ExtendedOutfit outfit)
 {
     ProxyFields.Watch();
     ExtendedOutfitFields.Watch(outfit);
 }
Пример #12
0
        static float ApparelScoreRawInsulation(Pawn pawn, Apparel apparel, ExtendedOutfit outfit, NeededWarmth neededWarmth)
        {
            float insulation;

            if (outfit.targetTemperaturesOverride)
            {
                // NOTE: We can't rely on the vanilla check for taking off gear for temperature, because
                // we need to consider all the wardrobe changes taken together; each individual change may
                // note push us over the thresholds, but several changes together may.
                // Return 1 for temperature offsets here, we'll look at the effects of any gear we have to
                // take off below.
                // NOTE: This is still suboptimal, because we're still only considering one piece of apparel
                // to wear at each time. A better solution would be reducing the problem to a series of linear
                // equations, and then solving that system.
                // I'm not sure that's feasible at all; first off for simple computational reasons: the linear
                // system to solve would be fairly massive, optimizing for dozens of pawns and hundreds of pieces
                // of gear simultaneously. Second, many of the stat functions aren't actually linear, and would
                // have to be made to be linear.
                bool currentlyWorn = pawn.apparel.WornApparel.Contains(apparel);

                var currentRange   = pawn.ComfortableTemperatureRange();
                var candidateRange = currentRange;
                if (outfit.AutoTemp)
                {
                    var seasonalTemp = pawn.Map.mapTemperature.SeasonalTemp;
                    outfit.targetTemperatures = new FloatRange(seasonalTemp - outfit.autoTempOffset, seasonalTemp + outfit.autoTempOffset);
                }
                var targetRange   = outfit.targetTemperatures;
                var apparelOffset = GetInsulationStats(apparel);

                // effect of this piece of apparel
                candidateRange.min += apparelOffset.min;
                candidateRange.max += apparelOffset.max;
                if (!currentlyWorn)
                {
                    foreach (var otherApparel in pawn.apparel.WornApparel)
                    {
                        // effect of taking off any other apparel that is incompatible
                        if (!ApparelUtility.CanWearTogether(apparel.def, otherApparel.def, pawn.RaceProps.body))
                        {
                            var otherInsulationRange = GetInsulationStats(otherApparel);

                            candidateRange.min -= otherInsulationRange.min;
                            candidateRange.max -= otherInsulationRange.max;
                        }
                    }
                }

                // did we get any closer to our target range? (smaller distance is better, negative values are overkill).
                var currentDistance = new FloatRange(Mathf.Max(currentRange.min - targetRange.min, 0f),
                                                     Mathf.Max(targetRange.max - currentRange.max, 0f));
                var candidateDistance = new FloatRange(Mathf.Max(candidateRange.min - targetRange.min, 0f),
                                                       Mathf.Max(targetRange.max - candidateRange.max, 0f));

                // improvement in distances
                insulation = InsulationFactorCurve.Evaluate(currentDistance.min - candidateDistance.min) +
                             InsulationFactorCurve.Evaluate(currentDistance.max - candidateDistance.max);
#if DEBUG
                Log.Message($"{pawn.Name.ToStringShort} :: {apparel.LabelCap}\n" +
                            $"\ttarget range: {targetRange}, current range: {currentRange}, candidate range {candidateRange}\n" +
                            $"\tcurrent distance: {currentDistance}, candidate distance: {candidateDistance}\n" +
                            $"\timprovement: {(currentDistance.min - candidateDistance.min) + (currentDistance.max - candidateDistance.max)}, insulation score: {insulation}\n");
#endif
            }
            else
            {
                float statValue;
                if (neededWarmth == NeededWarmth.Warm)
                {
                    statValue  = apparel.GetStatValue(StatDefOf.Insulation_Cold, true);
                    insulation = InsulationTemperatureScoreFactorCurve_Need.Evaluate(statValue);
                }
                else if (neededWarmth == NeededWarmth.Cool)
                {
                    statValue  = apparel.GetStatValue(StatDefOf.Insulation_Heat, true);
                    insulation = InsulationTemperatureScoreFactorCurve_Need.Evaluate(statValue);
                }
                else
                {
                    insulation = 1f;
                }
            }
            return(insulation);
        }
        static void DrawStatRow(ExtendedOutfit selectedOutfit, StatPriority statPriority, ref Vector2 cur, float width)
        {
            // set up rects
            Rect labelRect  = new Rect(cur.x, cur.y, (width - 24) / 2f, 30f);
            Rect sliderRect = new Rect(labelRect.xMax + 4f, cur.y + 5f, labelRect.width, 25f);
            Rect buttonRect = new Rect(sliderRect.xMax + 4f, cur.y + 3f, 16f, 16f);

            // draw label
            Text.Font = Text.CalcHeight(statPriority.Stat.LabelCap, labelRect.width) > labelRect.height
                            ? GameFont.Tiny
                            : GameFont.Small;

            GUI.color = AssigmentColor(statPriority);

            Widgets.Label(labelRect, statPriority.Stat.LabelCap);
            Text.Font = GameFont.Small;

            // draw button
            // if manually added, delete the priority
            string buttonTooltip = string.Empty;

            if (statPriority.IsManual)
            {
                buttonTooltip = ResourceBank.Strings.StatPriorityDelete(statPriority.Stat.LabelCap);
                if (Widgets.ButtonImage(buttonRect, ResourceBank.Textures.DeleteButton))
                {
                    selectedOutfit.RemoveStatPriority(statPriority.Stat);
                }
            }
            // if overridden auto assignment, reset to auto
            else if (statPriority.IsOverride)
            {
                buttonTooltip = ResourceBank.Strings.StatPriorityReset(statPriority.Stat.LabelCap);
                if (Widgets.ButtonImage(buttonRect, ResourceBank.Textures.ResetButton))
                {
                    statPriority.Weight = statPriority.Default;

                    if (MPApi.IsInMultiplayer)
                    {
                        ExtendedOutfitProxy.SetStatPriority(statPriority.Stat, statPriority.Default);
                    }
                }
            }

            // draw line behind slider
            GUI.color = new Color(.3f, .3f, .3f);
            for (int y = (int)cur.y; y < cur.y + 30; y += 5)
            {
                Widgets.DrawLineVertical((sliderRect.xMin + sliderRect.xMax) / 2f, y, 3f);
            }

            // draw slider
            GUI.color = AssigmentColor(statPriority);

            float weight = GUI.HorizontalSlider(sliderRect, statPriority.Weight, -MaxValue, MaxValue);

            if (Mathf.Abs(weight - statPriority.Weight) > 1e-4)
            {
                statPriority.Weight = weight;

                if (MPApi.IsInMultiplayer)
                {
                    ExtendedOutfitProxy.SetStatPriority(statPriority.Stat, weight);
                }
            }

            GUI.color = Color.white;

            // tooltips
            TooltipHandler.TipRegion(labelRect, statPriority.Stat.LabelCap + "\n\n" + statPriority.Stat.description);
            if (buttonTooltip != string.Empty)
            {
                TooltipHandler.TipRegion(buttonRect, buttonTooltip);
            }

            TooltipHandler.TipRegion(sliderRect, statPriority.Weight.ToStringByStyle(ToStringStyle.FloatTwo));

            // advance row
            cur.y += 30f;
        }
        static void DrawApparelStats(ExtendedOutfit selectedOutfit, Vector2 cur, Rect canvas)
        {
            // header
            Rect statsHeaderRect = new Rect(cur.x, cur.y, canvas.width, 30f);

            cur.y      += 30f;
            Text.Anchor = TextAnchor.LowerLeft;
            Text.Font   = GameFont.Small;
            Widgets.Label(statsHeaderRect, ResourceBank.Strings.PreferedStats);
            Text.Anchor = TextAnchor.UpperLeft;

            // add button
            Rect addStatRect = new Rect(statsHeaderRect.xMax - 16f, statsHeaderRect.yMin + marginVertical, 16f, 16f);

            if (Widgets.ButtonImage(addStatRect, ResourceBank.Textures.AddButton))
            {
                var options = new List <FloatMenuOption>();
                foreach (var def in selectedOutfit.UnassignedStats.OrderBy(i => i.label).OrderBy(i => i.category.displayOrder))
                {
                    FloatMenuOption option = new FloatMenuOption(def.LabelCap, delegate
                    {
                        selectedOutfit.AddStatPriority(def, 0f);
                    });
                    options.Add(option);
                }

                Find.WindowStack.Add(new FloatMenu(options));
            }

            TooltipHandler.TipRegion(addStatRect, ResourceBank.Strings.StatPriorityAdd);

            // line
            GUI.color = Color.grey;
            Widgets.DrawLineHorizontal(cur.x, cur.y, canvas.width);
            GUI.color = Color.white;

            // some padding
            cur.y += marginVertical;

            var stats = selectedOutfit.StatPriorities.ToList();

            // main content in scrolling view
            Rect contentRect = new Rect(cur.x, cur.y, canvas.width, canvas.height - cur.y);
            Rect viewRect    = new Rect(contentRect)
            {
                height = 30f * stats.Count
            };

            if (viewRect.height > contentRect.height)
            {
                viewRect.width -= 20f;
            }

            Widgets.BeginScrollView(contentRect, ref scrollPosition, viewRect);

            GUI.BeginGroup(viewRect);
            cur = Vector2.zero;

            // none label
            if (stats.Count > 0)
            {
                // legend kind of thingy.
                Rect legendRect = new Rect(cur.x + (viewRect.width - 24) / 2, cur.y, (viewRect.width - 24) / 2, 20f);
                Text.Font   = GameFont.Tiny;
                GUI.color   = Color.grey;
                Text.Anchor = TextAnchor.LowerLeft;
                Widgets.Label(legendRect, "-" + MaxValue.ToString("N1"));
                Text.Anchor = TextAnchor.LowerRight;
                Widgets.Label(legendRect, MaxValue.ToString("N1"));
                Text.Anchor = TextAnchor.UpperLeft;
                Text.Font   = GameFont.Small;
                GUI.color   = Color.white;
                cur.y      += 15f;

                // statPriority weight sliders
                foreach (var stat in stats)
                {
                    DrawStatRow(selectedOutfit, stat, ref cur, viewRect.width);
                }
            }
            else
            {
                Rect noneLabel = new Rect(cur.x, cur.y, viewRect.width, 30f);
                GUI.color   = Color.grey;
                Text.Anchor = TextAnchor.MiddleCenter;
                Widgets.Label(noneLabel, ResourceBank.Strings.None);
                Text.Anchor = TextAnchor.UpperLeft;
                GUI.color   = Color.white;
                cur.y      += 30f;
            }

            GUI.EndGroup();
            Widgets.EndScrollView();
        }