diff --git a/About/About.xml b/About/About.xml index 015bfc5..946c52f 100644 --- a/About/About.xml +++ b/About/About.xml @@ -4,5 +4,5 @@ Pawn Rules Jaxe 1.0.0 - Mod Version: 1.2.1\n\n\nPawn Rules is a mod that allows custom rules to be assigned individually to your colonists, animals, guests and prisoners.\n\nCurrently the following rules can be applied:\n\n- Disallow certain foods\n- Disallow bonding with certain animals\n- Disallow new romances\n- Disallow constructing items that have a quality level\n\nAny of these rules can be disabled and hidden from the rules window. Rules presets and defaults can be imported and exported between games. + Mod Version: 1.2.2\n\n\nPawn Rules is a mod that allows custom rules to be assigned individually to your colonists, animals, guests and prisoners.\n\nCurrently the following rules can be applied:\n\n- Disallow certain foods\n- Disallow bonding with certain animals\n- Disallow new romances\n- Disallow constructing items that have a quality level\n\nAny of these rules can be disabled and hidden from the rules window. Rules presets and defaults can be imported and exported between games. diff --git a/About/Manifest.xml b/About/Manifest.xml index 09c91b2..9cac1e5 100644 --- a/About/Manifest.xml +++ b/About/Manifest.xml @@ -2,7 +2,7 @@ PawnRules - 1.2.1 + 1.2.2 https://raw.githubusercontent.com/Jaxe-Dev/PawnRules/master/About/Manifest.xml https://github.com/Jaxe-Dev/PawnRules/releases/latest diff --git a/Languages/English/Keyed/Keys.xml b/Languages/English/Keyed/Keys.xml index 7a46f03..a58b714 100644 --- a/Languages/English/Keyed/Keys.xml +++ b/Languages/English/Keyed/Keys.xml @@ -52,8 +52,8 @@ Unrestricted Personalized - Ingestible Policy - Ingestible Policies + Food Policy + Food Policies Ingestibles Bonding Policy Bonding Policies @@ -71,8 +71,8 @@ Persons Individual - Ingestible policy: {0} - Click to choose which ingestibles can be consumed. + Food policy: {0} + Click to choose which foods, drinks or other ingestibles can be consumed. Bonding policy: {0} Click to choose which animals can be bonded with. Allow Courting @@ -95,6 +95,7 @@ Global Options Allow any food when malnourished Allow any food when training + Allow drugs to be restricted Show {0} Import/Export Plans diff --git a/README.md b/README.md index 472f752..61bfa34 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Pawn Rules -![Mod Version](https://img.shields.io/badge/Mod_Version-1.2.1-blue.svg) +![Mod Version](https://img.shields.io/badge/Mod_Version-1.2.2-blue.svg) ![RimWorld Version](https://img.shields.io/badge/Built_for_RimWorld-1.0-blue.svg) ![Harmony Version](https://img.shields.io/badge/Powered_by_Harmony-1.2.0.1-blue.svg)\ ![Steam Subscribers](https://img.shields.io/badge/dynamic/xml.svg?label=Steam+Subscribers&query=//table/tr[2]/td[1]&colorB=blue&url=https://steamcommunity.com/sharedfiles/filedetails/%3Fid=1499843448&suffix=+total) diff --git a/Source/Data/Registry.cs b/Source/Data/Registry.cs index b6e5964..296063e 100644 --- a/Source/Data/Registry.cs +++ b/Source/Data/Registry.cs @@ -28,6 +28,7 @@ internal class Registry : WorldObject public static bool ShowAllowCourting { get => _instance._showAllowCourting; set => _instance._showAllowCourting = value; } public static bool ShowAllowArtisan { get => _instance._showAllowArtisan; set => _instance._showAllowArtisan = value; } + public static bool AllowDrugsRestriction { get => _instance._allowDrugsRestriction; set => _instance._allowDrugsRestriction = value; } public static bool AllowEmergencyFood { get => _instance._allowEmergencyFood; set => _instance._allowEmergencyFood = value; } public static bool AllowTrainingFood { get => _instance._allowTrainingFood; set => _instance._allowTrainingFood = value; } public static Pawn ExemptedTrainer { get => _instance._exemptedTrainer; set => _instance._exemptedTrainer = value; } @@ -48,6 +49,7 @@ internal class Registry : WorldObject private bool _showAllowCourting = true; private bool _showAllowArtisan = true; + private bool _allowDrugsRestriction; private bool _allowEmergencyFood; private bool _allowTrainingFood; @@ -324,6 +326,7 @@ public override void ExposeData() Scribe_Values.Look(ref _showAllowCourting, "showAllowCourting", true); Scribe_Values.Look(ref _showAllowArtisan, "showAllowArtisan", true); + Scribe_Values.Look(ref _allowDrugsRestriction, "allowDrugsRestriction"); Scribe_Values.Look(ref _allowEmergencyFood, "allowEmergencyFood"); Scribe_Values.Look(ref _allowTrainingFood, "allowTrainingFood"); diff --git a/Source/Data/Restriction.cs b/Source/Data/Restriction.cs index dbb279d..8f8db49 100644 --- a/Source/Data/Restriction.cs +++ b/Source/Data/Restriction.cs @@ -36,7 +36,7 @@ public Restriction(XElement xml) var defs = xml.Element("Defs")?.Elements(); if (defs == null) { return; } - foreach (var def in defs) { _defs.Add(def.Value); } + foreach (var def in defs.Where(def => RestrictionTemplate.IsValidDefName(def.Value, Type))) { _defs.Add(def.Value); } } public bool Matches(RestrictionTemplate template) => _defs.SequenceEqual(from category in template.Categories from member in category.Members where !member.Value select member.Def.defName); @@ -48,7 +48,7 @@ public void Update(RestrictionTemplate template) } public bool Allows(Def def) => !_defs.Contains(def.defName); - public bool AllowsFood(ThingDef def, Pawn pawn) => IsVoid || pawn.InMentalState || !_defs.Contains(def.defName) || (Registry.AllowEmergencyFood && (pawn.health?.hediffSet?.HasHediff(HediffDefOf.Malnutrition) ?? false)); + public bool AllowsFood(ThingDef def, Pawn pawn) => IsVoid || pawn.InMentalState || (def.IsDrug && !Registry.AllowDrugsRestriction) || !_defs.Contains(def.defName) || (Registry.AllowEmergencyFood && (pawn.health?.hediffSet?.HasHediff(HediffDefOf.Malnutrition) ?? false)); protected override void ExposePresetData() { diff --git a/Source/Data/RestrictionTemplate.cs b/Source/Data/RestrictionTemplate.cs index f17b085..45be0fe 100644 --- a/Source/Data/RestrictionTemplate.cs +++ b/Source/Data/RestrictionTemplate.cs @@ -22,6 +22,14 @@ public void ToggleAll(bool value) } } + public static bool IsValidDefName(string defName, RestrictionType type) + { + if (type == RestrictionType.Food) { return FoodCache.Any(def => def.defName == defName); } + if (type == RestrictionType.Bonding) { return AnimalCache.Any(def => def.defName == defName); } + + throw new Mod.Exception("Invalid restriction type"); + } + private static RestrictionTemplate GetFoodsCategorized(Restriction restriction) { var list = new Dictionary { [ThingCategoryDefOf.FoodMeals.LabelCap] = new Category(ThingCategoryDefOf.FoodMeals.LabelCap) }; diff --git a/Source/Interface/Dialog_Alert.cs b/Source/Interface/Dialog_Alert.cs index 3cd4cb6..70e62a9 100644 --- a/Source/Interface/Dialog_Alert.cs +++ b/Source/Interface/Dialog_Alert.cs @@ -40,13 +40,13 @@ public override void DoWindowContents(Rect rect) var listing = new Listing_Standard(); var vGrid = rect.GetVGrid(4f, -1f, 30f); - listing.Begin(vGrid[0]); + listing.Begin(vGrid[1]); listing.Label(_message); listing.End(); - var hGrid = vGrid[1].GetHGrid(4f, 100f, -1f); + var hGrid = vGrid[2].GetHGrid(4f, 100f, -1f); - listing.Begin(_buttons == Buttons.Ok ? vGrid[1] : hGrid[0]); + listing.Begin(_buttons == Buttons.Ok ? vGrid[3] : hGrid[1]); if (listing.ButtonText(_buttons == Buttons.YesNo ? Lang.Get("Button.Yes") : Lang.Get("Button.OK"))) { @@ -59,7 +59,7 @@ public override void DoWindowContents(Rect rect) if (_buttons == Buttons.Ok) { return; } - listing.Begin(hGrid[1]); + listing.Begin(hGrid[2]); if (listing.ButtonText(_buttons == Buttons.YesNo ? Lang.Get("Button.No") : Lang.Get("Button.Cancel"))) { Close(); } listing.End(); } diff --git a/Source/Interface/Dialog_Global.cs b/Source/Interface/Dialog_Global.cs index 9efea8e..72c3fa4 100644 --- a/Source/Interface/Dialog_Global.cs +++ b/Source/Interface/Dialog_Global.cs @@ -17,6 +17,7 @@ protected override void DoContent(Rect rect) var listing = new Listing_StandardPlus(); listing.Begin(rect); + Registry.AllowDrugsRestriction = listing.CheckboxLabeled(Lang.Get("Dialog_Global.AllowDrugsRestriction"), Registry.AllowDrugsRestriction); Registry.AllowEmergencyFood = listing.CheckboxLabeled(Lang.Get("Dialog_Global.AllowEmergencyFood"), Registry.AllowEmergencyFood); Registry.AllowTrainingFood = listing.CheckboxLabeled(Lang.Get("Dialog_Global.AllowTrainingFood"), Registry.AllowTrainingFood); diff --git a/Source/Interface/Dialog_Plans.cs b/Source/Interface/Dialog_Plans.cs index 069e249..e2ba146 100644 --- a/Source/Interface/Dialog_Plans.cs +++ b/Source/Interface/Dialog_Plans.cs @@ -57,7 +57,7 @@ protected override void DoContent(Rect rect) var hasPlans = _plans.Any(); if (hasPlans) { - _listing.Begin(vGrid[0], true); + _listing.Begin(vGrid[1], true); foreach (var plan in _plans) { if (_listing.RadioButton(plan, _selected == plan)) { _selected = plan; } @@ -65,17 +65,17 @@ protected override void DoContent(Rect rect) } else { - _listing.Begin(vGrid[0]); + _listing.Begin(vGrid[1]); _listing.Label(Lang.Get("Dialog_Plans.NoneFound")); } _listing.End(); - var tGrid = vGrid[1].GetHGrid(4f, -1f, -1f); - var bGrid = vGrid[2].GetHGrid(4f, -1f, -1f); - if (GuiPlus.ButtonText(tGrid[0], Lang.Get("Dialog_Plans.Import"), Lang.Get("Dialog_Plans.ImportDesc"), !_selected.NullOrEmpty())) { LoadPlan(); } - if (GuiPlus.ButtonText(tGrid[1], Lang.Get("Dialog_Plans.Delete"), Lang.Get("Dialog_Plans.DeleteDesc"), !_selected.NullOrEmpty())) { Dialog_Alert.Open(Lang.Get("Dialog_Plans.ConfirmDelete", _selected), Dialog_Alert.Buttons.YesNo, DeletePlan); } - if (GuiPlus.ButtonText(bGrid[0], Lang.Get("Dialog_Plans.Export"), Lang.Get("Dialog_Plans.ExportDesc"))) { Dialog_SetName.Open(Lang.Get("Dialog_SetName.PlanTitle"), Lang.Get("Dialog_SetName.PlanLabel"), SavePlan, Persistent.NameIsValid, Persistent.CreateDefaultName()); } - if (GuiPlus.ButtonText(bGrid[1], "CloseButton".Translate())) { Close(); } + var tGrid = vGrid[2].GetHGrid(4f, -1f, -1f); + var bGrid = vGrid[3].GetHGrid(4f, -1f, -1f); + if (GuiPlus.ButtonText(tGrid[1], Lang.Get("Dialog_Plans.Import"), Lang.Get("Dialog_Plans.ImportDesc"), !_selected.NullOrEmpty())) { LoadPlan(); } + if (GuiPlus.ButtonText(tGrid[2], Lang.Get("Dialog_Plans.Delete"), Lang.Get("Dialog_Plans.DeleteDesc"), !_selected.NullOrEmpty())) { Dialog_Alert.Open(Lang.Get("Dialog_Plans.ConfirmDelete", _selected), Dialog_Alert.Buttons.YesNo, DeletePlan); } + if (GuiPlus.ButtonText(bGrid[1], Lang.Get("Dialog_Plans.Export"), Lang.Get("Dialog_Plans.ExportDesc"))) { Dialog_SetName.Open(Lang.Get("Dialog_SetName.PlanTitle"), Lang.Get("Dialog_SetName.PlanLabel"), SavePlan, Persistent.NameIsValid, Persistent.CreateDefaultName()); } + if (GuiPlus.ButtonText(bGrid[2], "CloseButton".Translate())) { Close(); } } } } diff --git a/Source/Interface/Dialog_Restrictions.cs b/Source/Interface/Dialog_Restrictions.cs index dd6de86..8b5a723 100644 --- a/Source/Interface/Dialog_Restrictions.cs +++ b/Source/Interface/Dialog_Restrictions.cs @@ -1,4 +1,6 @@ -using PawnRules.Data; +using System.Collections.Generic; +using System.Linq; +using PawnRules.Data; using PawnRules.Patch; using UnityEngine; using Verse; @@ -55,11 +57,7 @@ void OnAccept() void OnCancel() { - if (_presetList.IsUnsaved) - { - //Registry.DeletePreset(_presetList.Selected); - _presetList.Revert(); - } + if (_presetList.IsUnsaved) { _presetList.Revert(); } base.Close(doCloseSound); } @@ -78,96 +76,105 @@ protected override void DoContent(Rect rect) _color = GUI.color; var vGrid = rect.GetVGrid(4f, 42f, -1f); - var hGrid = vGrid[1].GetHGrid(8f, 200f, -1f, -1f); - DoHeader(vGrid[0]); + DoHeader(vGrid[1]); - _presetList.DoContent(hGrid[0]); - DoCategories(hGrid[1]); - DoMembers(hGrid[2]); + var hGrid = vGrid[2].GetHGrid(8f, 200f, -1f, -1f); + _presetList.DoContent(hGrid[1]); + DoCategories(hGrid[2], hGrid[3]); } private void DoHeader(Rect rect) { var grid = rect.GetHGrid(8f, 200f, -1f, -1f); - _headerList.Begin(grid[0]); + _headerList.Begin(grid[1]); _headerList.Label(Lang.Get("Preset.Header").Italic().Bold()); _headerList.GapLine(); _headerList.End(); - _headerList.Begin(grid[1]); + _headerList.Begin(grid[2]); _headerList.Label(Lang.Get("Dialog_Restrictions.HeaderCategory").Italic().Bold()); _headerList.GapLine(); _headerList.End(); - _headerList.Begin(grid[2]); + _headerList.Begin(grid[3]); _headerList.Label(_type.Categorization.Italic().Bold()); _headerList.GapLine(); _headerList.End(); } - private void DoCategories(Rect rect) + private void DoCategories(Rect categoriesRect, Rect membersRect) { - var vGrid = rect.GetVGrid(4f, -1f, 30f); - _categoryList.Begin(vGrid[0], true); + var vGrid = categoriesRect.GetVGrid(4f, -1f, 30f); + _categoryList.Begin(vGrid[1], true); + + var members = new Dictionary(); foreach (var category in _template.Categories) { var state = category.GetListState(); + var showAll = _presetList.EditMode || (_rules.Pawn == null); + if (_type == RestrictionType.Food) { members[category.Label] = category.Members.Where(member => member.Def is ThingDef def && (!def.IsDrug || Registry.AllowDrugsRestriction) && (showAll || _rules.Pawn.RaceProps.CanEverEat(def))).ToArray(); } + else if (_type == RestrictionType.Bonding) { members[category.Label] = category.Members.ToArray(); } + else { throw new Mod.Exception("Unsupported restriction type"); } + + if (members[category.Label].Length == 0) { continue; } + if (_presetList.EditMode) { _categoryList.CheckboxPartial(category.Label, ref state); category.UpdateState(state); - continue; } + else + { + GUI.color = GuiPlus.ReadOnlyColor; + _categoryList.CheckboxPartial(category.Label, ref state); + GUI.color = _color; + } + } - if ((_type == RestrictionType.Food) && (_rules.Pawn != null) && !category.Members.Any(member => _rules.Pawn.RaceProps.CanEverEat((ThingDef) member.Def))) { continue; } + _membersList.Gap(); + _categoryList.End(); - GUI.color = GuiPlus.ReadOnlyColor; - _categoryList.CheckboxPartial(category.Label, ref state); - GUI.color = _color; + if (!_presetList.EditMode) + { + DoMembers(membersRect, members); + return; } - _categoryList.End(); - if (!_presetList.EditMode) { return; } + var hGrid = vGrid[2].GetHGrid(4f, -1f, -1f); + var categoryButtons = new Listing_Standard(); + categoryButtons.Begin(hGrid[1]); + if (categoryButtons.ButtonText(Lang.Get("Button.RestrictionsAllowOn"))) { _template.ToggleAll(true); } + categoryButtons.End(); + categoryButtons.Begin(hGrid[2]); + if (categoryButtons.ButtonText(Lang.Get("Button.RestrictionsAllowOff"))) { _template.ToggleAll(false); } + categoryButtons.End(); - var hGrid = vGrid[1].GetHGrid(4f, -1f, -1f); - _categoryList.Begin(hGrid[0]); - if (_categoryList.ButtonText(Lang.Get("Button.RestrictionsAllowOn"))) { _template.ToggleAll(true); } - _categoryList.End(); - _categoryList.Begin(hGrid[1]); - if (_categoryList.ButtonText(Lang.Get("Button.RestrictionsAllowOff"))) { _template.ToggleAll(false); } - _categoryList.End(); + DoMembers(membersRect, members); } - private void DoMembers(Rect rect) + private void DoMembers(Rect membersRect, Dictionary categories) { - _membersList.Begin(rect, true); + _membersList.Begin(membersRect, true); - foreach (var category in _template.Categories) + foreach (var category in categories.Where(category => category.Value.Length > 0)) { - if ((_type == RestrictionType.Food) && (_rules.Pawn != null) && !category.Members.Any(member => _rules.Pawn.RaceProps.CanEverEat((ThingDef) member.Def))) { continue; } - - _membersList.LabelTiny(category.Label.Bold()); + _membersList.LabelTiny(category.Key.Bold()); - foreach (var member in category.Members) + foreach (var member in category.Value) { - if (_presetList.EditMode) + if (_presetList.EditMode) { _membersList.CheckboxLabeled(member.Def.LabelCap, ref member.Value, member.Def.description); } + else { - _membersList.CheckboxLabeled(member.Def.LabelCap, ref member.Value, member.Def.description); - continue; + GUI.color = GuiPlus.ReadOnlyColor; + _membersList.CheckboxLabeled(member.Def.LabelCap, ref member.Value, member.Def.description, false); + GUI.color = _color; } - - if ((_type == RestrictionType.Food) && (_rules.Pawn != null) && !_rules.Pawn.RaceProps.CanEverEat((ThingDef) member.Def)) { continue; } - - GUI.color = GuiPlus.ReadOnlyColor; - _membersList.CheckboxLabeled(member.Def.LabelCap, ref member.Value, member.Def.description, false); - GUI.color = _color; } - - _membersList.Gap(); } + _membersList.Gap(); _membersList.End(); } } diff --git a/Source/Interface/Dialog_Rules.cs b/Source/Interface/Dialog_Rules.cs index e82dae2..6963ef5 100644 --- a/Source/Interface/Dialog_Rules.cs +++ b/Source/Interface/Dialog_Rules.cs @@ -202,16 +202,16 @@ protected override void DoContent(Rect rect) var listing = new Listing_StandardPlus(); var hGrid = rect.GetHGrid(8f, 200f, -1f); - var lGrid = hGrid[0].GetVGrid(4f, 42f, -1f); + var lGrid = hGrid[1].GetVGrid(4f, 42f, -1f); - listing.Begin(lGrid[0]); + listing.Begin(lGrid[1]); listing.Label(Lang.Get("Preset.Header").Italic().Bold()); listing.GapLine(); listing.End(); - _preset.DoContent(lGrid[1]); + _preset.DoContent(lGrid[2]); - var vGrid = hGrid[1].GetVGrid(4f, 42f, -1f, 62f); - listing.Begin(vGrid[0]); + var vGrid = hGrid[2].GetVGrid(4f, 42f, -1f, 62f); + listing.Begin(vGrid[1]); listing.Label(Lang.Get("Dialog_Rules.Configuration").Italic().Bold()); listing.GapLine(); listing.End(); @@ -221,7 +221,7 @@ protected override void DoContent(Rect rect) var color = GUI.color; if (!editMode) { GUI.color = GuiPlus.ReadOnlyColor; } - listing.Begin(vGrid[1]); + listing.Begin(vGrid[2]); if (Registry.ShowFoodPolicy && listing.ButtonText(Lang.Get("Rules.FoodRestrictions", GetRestrictionDisplayName(_template.GetRestriction(RestrictionType.Food))), Lang.Get("Rules.FoodRestrictionsDesc")) && editMode) { ChangeRestriction(RestrictionType.Food); } if (_template.Type == PawnType.Colonist) { @@ -238,7 +238,7 @@ protected override void DoContent(Rect rect) if (_template.HasAddons) { - var addonsRect = vGrid[1].GetVGrid(4f, listing.CurHeight, -1f)[1]; + var addonsRect = vGrid[2].GetVGrid(4f, listing.CurHeight, -1f)[2]; _addons.Begin(addonsRect, addonsRect.height <= _template.AddonsRectHeight); GuiPlus.DoAddonsListing(_addons, _template, editMode); _addons.End(); @@ -246,12 +246,12 @@ protected override void DoContent(Rect rect) GUI.color = color; - var optionGrid = vGrid[2].GetVGrid(2f, -1f, -1f); - listing.Begin(optionGrid[0]); + var optionGrid = vGrid[3].GetVGrid(2f, -1f, -1f); + listing.Begin(optionGrid[1]); if (listing.ButtonText(Lang.Get("Button.AssignTo"), Lang.Get("Button.AssignToDesc"), (_floatMenuAssign.Count > 0) && (!editMode || (_template == _personalized)))) { Find.WindowStack.Add(new FloatMenu(_floatMenuAssign)); } listing.End(); - listing.Begin(optionGrid[1]); + listing.Begin(optionGrid[2]); if (listing.ButtonText(_type == null ? Lang.Get("Button.ViewType", Lang.Get("PawnType.Individual")) : Lang.Get("Button.ViewTypeDefault", _type.LabelPlural), Lang.Get("Button.ViewTypeDesc"), !editMode || (_template == _personalized))) { Find.WindowStack.Add(new FloatMenu(_floatMenuViews)); } listing.End(); diff --git a/Source/Interface/Dialog_SetName.cs b/Source/Interface/Dialog_SetName.cs index 5918d8e..1476f0d 100644 --- a/Source/Interface/Dialog_SetName.cs +++ b/Source/Interface/Dialog_SetName.cs @@ -56,11 +56,11 @@ protected override void DoContent(Rect rect) var grid = rect.AdjustedBy(0f, listing.CurHeight, 0f, -listing.CurHeight).GetHGrid(4f, -1f, -1f); - listing.Begin(grid[0]); + listing.Begin(grid[1]); if (listing.ButtonText(Lang.Get("Button.OK"), null, NameIsValid())) { CommitName(); } listing.End(); - listing.Begin(grid[1]); + listing.Begin(grid[2]); if (listing.ButtonText(Lang.Get("Button.Cancel"))) { Close(); } listing.End(); } diff --git a/Source/Interface/Listing_Preset.cs b/Source/Interface/Listing_Preset.cs index 6ff2adb..88f13ea 100644 --- a/Source/Interface/Listing_Preset.cs +++ b/Source/Interface/Listing_Preset.cs @@ -59,7 +59,7 @@ public void DoContent(Rect rect) var presetGrid = rect.GetVGrid(4f, _listing.CurHeight, -1f, 62f); - _presetListing.Begin(presetGrid[1], true); + _presetListing.Begin(presetGrid[2], true); foreach (var preset in presets) { var isSelected = (Selected == preset) || (Selected.Name == preset.Name); @@ -67,8 +67,8 @@ public void DoContent(Rect rect) } _presetListing.End(); - var buttonGrid = presetGrid[2].GetHGrid(4f, -1f, -1f); - _listing.Begin(buttonGrid[0]); + var buttonGrid = presetGrid[3].GetHGrid(4f, -1f, -1f); + _listing.Begin(buttonGrid[1]); if (_listing.ButtonText(Lang.Get("Button.PresetNew"), Lang.Get("Button.PresetNewDesc"), !EditMode)) { Presetable.SetName(Type, CreatePreset); } @@ -91,7 +91,7 @@ public void DoContent(Rect rect) } _listing.End(); - _listing.Begin(buttonGrid[1]); + _listing.Begin(buttonGrid[2]); if (_listing.ButtonText(Lang.Get("Button.PresetDelete"), Lang.Get("Button.PresetDeleteDesc"), !Selected.IsVoid && Selected.IsPreset && !EditMode)) { Dialog_Alert.Open(Lang.Get("Button.PresetDeleteConfirm", Selected.Name), Dialog_Alert.Buttons.YesNo, DeletePreset); } diff --git a/Source/Mod.cs b/Source/Mod.cs index 0f547ff..dd96430 100644 --- a/Source/Mod.cs +++ b/Source/Mod.cs @@ -13,7 +13,7 @@ internal class Mod : Verse.Mod { public const string Id = "PawnRules"; public const string Name = "Pawn Rules"; - public const string Version = "1.2.1"; + public const string Version = "1.2.2"; public static readonly DirectoryInfo ConfigDirectory = new DirectoryInfo(Path.Combine(GenFilePaths.ConfigFolderPath, Id)); @@ -40,7 +40,7 @@ public Mod(ModContentPack contentPack) : base(contentPack) public override string SettingsCategory() => Name; public override void DoSettingsWindowContents(Rect inRect) { - var rect = inRect.GetHGrid(1f, -1f, 400f, -1f)[1]; + var rect = inRect.GetHGrid(1f, -1f, 400f, -1f)[2]; var listing = new Listing_Standard(); listing.Begin(rect); diff --git a/Source/Patch/Extensions.cs b/Source/Patch/Extensions.cs index 1ede6ef..6e95ba4 100644 --- a/Source/Patch/Extensions.cs +++ b/Source/Patch/Extensions.cs @@ -1,4 +1,5 @@ using System.Collections; +using System.Collections.Generic; using PawnRules.Data; using RimWorld; using UnityEngine; @@ -30,13 +31,15 @@ public static PawnType GetTargetType(this Pawn self) public static string GetDisplayName(this Presetable self) => self == null ? Lang.Get("Preset.None") : self.Name ?? Lang.Get("Preset.Personalized"); public static Rect AdjustedBy(this Rect self, float x, float y, float width, float height) => new Rect(self.x + x, self.y + y, self.width + width, self.height + height); + public static Rect Round(this Rect self) => new Rect(Mathf.Round(self.x), Mathf.Round(self.y), Mathf.Round(self.width), Mathf.Round(self.height)); - public static Rect[] GetHGrid(this Rect self, float spacing, params float[] widths) + public static Rect[] GetHGrid(this Rect self, float padding, params float[] widths) { var unfixedCount = 0; var currentX = self.x; var fixedWidths = 0f; - var rects = new Rect[widths.Length]; + + var rects = new List { self }; for (var index = 0; index < widths.Length; index++) { @@ -44,37 +47,38 @@ public static Rect[] GetHGrid(this Rect self, float spacing, params float[] widt if (width >= 0f) { fixedWidths += width; } else { unfixedCount++; } - if (index != widths.LastIndex()) { fixedWidths += spacing; } + if (index != widths.LastIndex()) { fixedWidths += padding; } } - var unfixedWidth = unfixedCount > 0 ? (self.width - fixedWidths) / unfixedCount : 0f; + var unfixedWidth = unfixedCount > 0 ? Mathf.Max(0f, (self.width - fixedWidths) / unfixedCount) : 0f; - for (var index = 0; index < widths.Length; index++) + foreach (var width in widths) { - var width = widths[index]; float newWidth; + if (width >= 0f) { newWidth = width; - rects[index] = new Rect(currentX, self.y, newWidth, self.height); + rects.Add(new Rect(currentX, self.y, newWidth, self.height).Round()); } else { newWidth = unfixedWidth; - rects[index] = new Rect(currentX, self.y, newWidth, self.height); + rects.Add(new Rect(currentX, self.y, newWidth, self.height).Round()); } - currentX += newWidth + spacing; + + currentX = Mathf.Min(self.xMax, currentX + newWidth + (newWidth > 0f ? padding : 0f)); } - return rects; + return rects.ToArray(); } - - public static Rect[] GetVGrid(this Rect self, float spacing, params float[] heights) + public static Rect[] GetVGrid(this Rect self, float padding, params float[] heights) { var unfixedCount = 0; var currentY = self.y; var fixedHeights = 0f; - var rects = new Rect[heights.Length]; + + var rects = new List { self }; for (var index = 0; index < heights.Length; index++) { @@ -82,29 +86,31 @@ public static Rect[] GetVGrid(this Rect self, float spacing, params float[] heig if (height >= 0f) { fixedHeights += height; } else { unfixedCount++; } - if (index != heights.LastIndex()) { fixedHeights += spacing; } + if (index != heights.LastIndex()) { fixedHeights += padding; } } - var unfixedWidth = unfixedCount > 0 ? (self.height - fixedHeights) / unfixedCount : 0f; + var unfixedHeight = unfixedCount > 0 ? Mathf.Max(0f, (self.height - fixedHeights) / unfixedCount) : 0f; - for (var index = 0; index < heights.Length; index++) + foreach (var height in heights) { - var height = heights[index]; float newHeight; + if (height >= 0f) { newHeight = height; - rects[index] = new Rect(self.x, currentY, self.width, newHeight); + rects.Add(new Rect(self.x, currentY, self.width, newHeight).Round()); } else { - newHeight = unfixedWidth; - rects[index] = new Rect(self.x, currentY, self.width, newHeight); + newHeight = unfixedHeight; + rects.Add(new Rect(self.x, currentY, self.width, newHeight).Round()); } - currentY += newHeight + spacing; + + currentY = Mathf.Min(self.yMax, currentY + newHeight + (newHeight > 0f ? padding : 0f)); } - return rects; + return rects.ToArray(); } + } }