Skip to content

Commit

Permalink
v1.1.1
Browse files Browse the repository at this point in the history
- Re-fixed "not allowed artisan builds" tooltip
- Fixed "Could not find player faction" error on new game
- Fixed ability to train animals if an animal has a food policy set
- New Global option: Allow food if malnourished (if a pawn is is suffering from malnutrition they will ignore all food rules) [Default: False]
- New Global option: Allow food if training (if an animal is being trained they ignore all food rules) [Default: False]
- Plans can be imported/exported between games. A plan consists of all rule presets and defaults bundled into one file.
  • Loading branch information
Jaxe-Dev committed Sep 14, 2018
1 parent 5fda731 commit 0664fa1
Show file tree
Hide file tree
Showing 36 changed files with 810 additions and 300 deletions.
4 changes: 2 additions & 2 deletions About/About.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@
<name>Pawn Rules</name>
<author>Jaxe</author>
<targetVersion>0.19.0</targetVersion>
<description>Mod Version: 1.1.0\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.</description>
<url>https://ludeon.com/forums/index.php?topic=43086.0</url>
<description>Mod Version: 1.1.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.</description>
<url>https://github.com/Jaxe-Dev/PawnRules</url>
</ModMetaData>
2 changes: 1 addition & 1 deletion About/ModSync.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<ModSyncNinjaData>
<ID>59f538ed-f86d-4506-a4a5-7e9faaa37508</ID>
<ModName>Pawn Rules</ModName>
<Version>v1.1.0</Version>
<Version>v1.1.1</Version>
<SaveBreaking>False</SaveBreaking>
<Host name="Github">
<Owner>Jaxe-Dev</Owner>
Expand Down
16 changes: 16 additions & 0 deletions Defs/UpdateFeaturesDef/UpdateFeatures.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>

<Defs>

<HugsLib.UpdateFeatureDef Abstract="true" Name="UpdateFeatureBase">
<modNameReadable>Pawn Rules</modNameReadable>
<modIdentifier>PawnRules</modIdentifier>
</HugsLib.UpdateFeatureDef>

<HugsLib.UpdateFeatureDef ParentName="UpdateFeatureBase">
<defName>PawnRules_1_1_1</defName>
<assemblyVersion>1.1.1</assemblyVersion>
<content>- Re-fixed "not allowed artisan builds" tooltip\n\n- Fixed "Could not find player faction" error on new game\n\n- Fixed ability to train animals if an animal has a food policy set\n\n- New Global option: Allow food if malnourished (if a pawn is is suffering from malnutrition they will ignore all food rules) [Default: False]\n\n- New Global option: Allow food if training (if an animal is being trained they ignore all food rules) [Default: False]\n\n- Plans can be imported/exported between games. A plan consists of all rule presets and defaults bundled into one file.</content>
</HugsLib.UpdateFeatureDef>

</Defs>
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>

<LanguageData>

<PawnRules.Button.OK>OK</PawnRules.Button.OK>
<PawnRules.Button.Cancel>Cancel</PawnRules.Button.Cancel>
<PawnRules.Button.Yes>Yes</PawnRules.Button.Yes>
Expand Down Expand Up @@ -92,7 +93,22 @@
<PawnRules.Gizmo.EditRulesDesc>Edit the rules for this {0}.</PawnRules.Gizmo.EditRulesDesc>

<PawnRules.Dialog_Global.Title>Global Options</PawnRules.Dialog_Global.Title>
<PawnRules.Dialog_Global.AllowEmergencyFood>Allow any food when malnourished</PawnRules.Dialog_Global.AllowEmergencyFood>
<PawnRules.Dialog_Global.AllowTrainingFood>Allow any food when training</PawnRules.Dialog_Global.AllowTrainingFood>
<PawnRules.Dialog_Global.ShowRule>Show {0}</PawnRules.Dialog_Global.ShowRule>
<PawnRules.Dialog_Global.Plans>Import/Export Plans</PawnRules.Dialog_Global.Plans>

<PawnRules.Dialog_Plans.Title>Import/Export Plans</PawnRules.Dialog_Plans.Title>
<PawnRules.Dialog_Plans.NoneFound>No saved plans available for import</PawnRules.Dialog_Plans.NoneFound>
<PawnRules.Dialog_Plans.Import>Import selected</PawnRules.Dialog_Plans.Import>
<PawnRules.Dialog_Plans.ImportDesc>All rules presets and defaults from this plan will be imported into this game.\nAny current presets that have the same name as an imported one will be overwritten.</PawnRules.Dialog_Plans.ImportDesc>
<PawnRules.Dialog_Plans.Delete>Delete selected</PawnRules.Dialog_Plans.Delete>
<PawnRules.Dialog_Plans.DeleteDesc>This deletes the selected plan permanently. This cannot be undone.</PawnRules.Dialog_Plans.DeleteDesc>
<PawnRules.Dialog_Plans.Export>Export current plan</PawnRules.Dialog_Plans.Export>
<PawnRules.Dialog_Plans.ExportDesc>All rules presets and defaults will be saved to your computer in a single plan and can be imported in a different game.</PawnRules.Dialog_Plans.ExportDesc>
<PawnRules.Dialog_Plans.ConfirmDelete>Are you sure you want to delete the plan '{0}'?</PawnRules.Dialog_Plans.ConfirmDelete>
<PawnRules.Dialog_Plans.LoadSuccess>Plan '{0}' successfully imported.</PawnRules.Dialog_Plans.LoadSuccess>
<PawnRules.Dialog_Plans.LoadFail>Plan '{0}' failed to import.</PawnRules.Dialog_Plans.LoadFail>

<PawnRules.Dialog_Rules.Title>Rules for {0}, {1}</PawnRules.Dialog_Rules.Title>
<PawnRules.Dialog_Rules.TitleDefault>Default Rules for {0}</PawnRules.Dialog_Rules.TitleDefault>
Expand All @@ -116,7 +132,12 @@
<PawnRules.Dialog_Restrictions.TitlePawn>{0} for {1}, {2}</PawnRules.Dialog_Restrictions.TitlePawn>
<PawnRules.Dialog_Restrictions.HeaderCategory>Category</PawnRules.Dialog_Restrictions.HeaderCategory>

<PawnRules.Dialog_PresetName.Title>Preset [{0}]</PawnRules.Dialog_PresetName.Title>
<PawnRules.Dialog_PresetName.TitleNew>Create Preset</PawnRules.Dialog_PresetName.TitleNew>
<PawnRules.Dialog_PresetName.Label>Enter new name:</PawnRules.Dialog_PresetName.Label>
<PawnRules.Dialog_SetName.PresetTitle>Preset [{0}]</PawnRules.Dialog_SetName.PresetTitle>
<PawnRules.Dialog_SetName.PresetTitleNew>Create Preset</PawnRules.Dialog_SetName.PresetTitleNew>
<PawnRules.Dialog_SetName.PresetLabel>Enter new name:</PawnRules.Dialog_SetName.PresetLabel>
<PawnRules.Dialog_SetName.PlanTitle>Export</PawnRules.Dialog_SetName.PlanTitle>
<PawnRules.Dialog_SetName.PlanLabel>Choose a name for this plan:</PawnRules.Dialog_SetName.PlanLabel>

<PawnRules.Settings.NoGame>There are no settings for this mod outside of a game.</PawnRules.Settings.NoGame>

</LanguageData>
34 changes: 20 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,46 +1,49 @@
# Pawn Rules
![](https://img.shields.io/badge/Version-1.1.0-brightgreen.svg)

Built for **RimWorld B19**\
Powered by **Harmony**\
Supports **ModSync RW**
![](https://img.shields.io/badge/Mod_Version-1.1.1-blue.svg)
![](https://img.shields.io/badge/Built_for_RimWorld-B19-blue.svg)
![](https://img.shields.io/badge/Powered_by_Harmony-1.2.0.1-blue.svg)

[Link to Steam Workshop page](https://steamcommunity.com/sharedfiles/filedetails/?id=1499843448)\
[Link to Ludeon Forum thread](https://ludeon.com/forums/index.php?topic=43086.0)

------------
---

Pawn Rules is a mod that allows custom rules to be assigned individually to your colonists, animals, guests and prisoners.

Currently the following rules can be applied:
- Disallow certain foods
- *Ignored if binging on food*
- *Ignored if binging on food or optionally if malnourished or training an animal*
- Disallow bonding with certain animals
- *This has no effect on existing bonds*
- Disallow new romances
- *This has no effect on existing relations and engaged couples can still get married*
- Disallow constructing items that have a quality level
- *Can still haul materials to blueprints*

Any of these rules can be disabled and hidden from the rules window.
Any of these rules can be disabled and hidden from the rules window. Rules presets and defaults can be imported and exported between games.

------------
---

Supports addons created by other modders by allowing easy creation of new rule options while handling the GUI and world storage saving. For more information check out the [wiki page on Addons](https://github.com/Jaxe-Dev/PawnRules/wiki/Addons).

------------
---

##### STEAM INSTALLATION
- **[Go to the Steam Workshop page](https://steamcommunity.com/sharedfiles/filedetails/?id=1499843448) and subscribe to the mod.**

---

##### INSTALLATION
##### NON-STEAM INSTALLATION
- **[Download the latest release](https://github.com/Jaxe-Dev/PawnRules/releases/latest) and unzip it into your *RimWorld/Mods* folder.**

------------
---

###### TECHINICAL DETAILS
>This mod can be safely removed from a save without breaking the game. To do so go to *Options* from the main rules window for a character and select *Remove Mod*.
>This mod can be safely removed from a save without breaking the game. To do so go to *Show settings* from the *Mod Settings* menu and select *Remove Mod*.
>
> A save of your world will be made with no traces of this mod and the game will restart. Skipping the *Remove Mod* step will result in errors being displayed the first time a save is loaded although no further problems should occur.
------------
---

The following base methods are patched with Harmony:
```C#
Expand All @@ -55,7 +58,10 @@ Prefix : RimWorld.JoyGiver_Ingest.CanIngestForJoy
Prefix : RimWorld.Pawn_GuestTracker.SetGuestStatus
Postfix : RimWorld.PawnUtility.TrySpawnHatchedOrBornPawn
Prefix : RimWorld.RelationsUtility.TryDevelopBondRelation
Prefix : RimWorld.WorkGiver_InteractAnimal.TakeFoodForAnimalInteractJob
Postfix : Verse.Game.FinalizeInit
Prefix : Verse.Game.InitNewGame
Prefix : Verse.Game.LoadGame
Postfix : Verse.Pawn.GetGizmos
Postfix : Verse.Pawn.Kill
Prefix : Verse.Pawn.SetFaction
Expand Down
3 changes: 3 additions & 0 deletions Source/Data/AddonManager.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using Verse;

Expand Down Expand Up @@ -29,5 +30,7 @@ public static void Add(AddonOption addon)

HasAddons = true;
}

public static AddonOption GetAddon(string key) => Options.FirstOrDefault(option => option.Key == key);
}
}
64 changes: 64 additions & 0 deletions Source/Data/Persistent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Xml.Linq;
using RimWorld;
using Verse;

namespace PawnRules.Data
{
internal static class Persistent
{
private const string ExportsDirectoryName = "Plans";
private const string ExportsExtension = ".xml";
private const string ExportPrefix = "Plan_";

private static readonly Regex ValidNameRegex = new Regex("^(?:[a-zA-Z0-9_\\-]|[a-zA-Z0-9_\\-]+[a-zA-Z0-9_\\- ]*[a-zA-Z0-9_\\-]+)$");

private static readonly DirectoryInfo ExportsDirectory = Mod.ConfigDirectory.CreateSubdirectory(ExportsDirectoryName);

private static FileInfo GetPlanFile(string name) => new FileInfo(Path.Combine(ExportsDirectory.FullName, ExportPrefix + name + ExportsExtension));
private static string GetPlanName(FileInfo file) => Path.GetFileNameWithoutExtension(file.Name).Substring(ExportPrefix.Length);

public static IEnumerable<string> GetPlans() => ExportsDirectory.GetFiles(ExportPrefix + "*" + ExportsExtension).OrderByDescending(file => file.LastAccessTime).Select(GetPlanName);

public static void DeletePlan(string name)
{
var file = GetPlanFile(name);

Mod.Warning($"Delete => {file.FullName}");
if (!file.Exists) { return; }

file.Delete();
}

public static bool Load(string name)
{
var file = GetPlanFile(name);
if (!file.Exists) { return false; }

var xml = XDocument.Load(file.FullName).Root;

Registry.FromXml(xml);

return true;
}

public static void Save(string name = null)
{
var file = GetPlanFile(name.NullOrEmpty() ? CreateDefaultName() : name);
if (file.Exists) { file.Delete(); }

var doc = new XDocument();
doc.Add(Registry.ToXml());

doc.Save(file.FullName);
}

public static bool NameIsValid(string name) => !name.NullOrEmpty() && (name.Length <= 250 - ExportsDirectory.FullName.Length) && ValidNameRegex.IsMatch(name);

public static string CreateDefaultName() => Faction.OfPlayer.Name + "_" + DateTime.Now.ToString("yyyy-MM-dd-hh-mm-ss");
}
}
31 changes: 28 additions & 3 deletions Source/Data/Presetable.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
using System;
using System.Text.RegularExpressions;
using System.Xml.Linq;
using PawnRules.Interface;
using Verse;

namespace PawnRules.Data
{
internal abstract class Presetable : IExposable, ILoadReferenceable
{
private const int MaxIdLength = 20;
protected static readonly string VoidName = Lang.Get("Preset.None");
private static readonly Regex NameRegex = new Regex("^(?:[a-zA-Z0-9]|[a-zA-Z0-9]+[a-zA-Z0-9 ]*[a-zA-Z0-9]+)$");

public static readonly string VoidName = Lang.Get("Preset.None");

private static readonly Regex ValidNameRegex = new Regex("^(?:[a-zA-Z0-9]|[a-zA-Z0-9]+[a-zA-Z0-9 ]*[a-zA-Z0-9]+)$");

private static int _count;
protected readonly int Id;
Expand All @@ -31,8 +35,29 @@ protected Presetable()

protected abstract void ExposePresetData();
internal abstract bool IsIgnored();
public abstract XElement ToXml();

public static void SetName<T>(IPresetableType type, Action<T> onCreate) where T : Presetable
{
var localType = type;
void OnCommit(string name)
{
var preset = Registry.CreatePreset<T>(localType, name);
onCreate(preset);
}

Dialog_SetName.Open(Lang.Get("Dialog_SetName.PresetTitleNew"), Lang.Get("Dialog_SetName.PresetLabel"), OnCommit, name => NameIsValid<T>(type, name));
}

public static void SetName<T>(T preset, Action<T> onRename) where T : Presetable
{
var localPreset = preset;
void OnCommit(string name) => onRename(Registry.RenamePreset(localPreset, name));

Dialog_SetName.Open(Lang.Get("Dialog_SetName.PresetTitle", preset.Name), Lang.Get("Dialog_SetName.PresetLabel"), OnCommit, name => NameIsValid<T>(preset.Type, name), preset.Name);
}

public static bool NameIsValid<T>(IPresetableType type, string name) => (name.Length <= MaxIdLength) && !string.Equals(name, Lang.Get("Preset.None"), StringComparison.OrdinalIgnoreCase) && !string.Equals(name, Lang.Get("Preset.Personalized"), StringComparison.OrdinalIgnoreCase) && NameRegex.IsMatch(name) && !Registry.PresetNameExists<T>(type, name);
public static bool NameIsValid<T>(IPresetableType type, string name) => (name.Length <= MaxIdLength) && !string.Equals(name, Lang.Get("Preset.None"), StringComparison.OrdinalIgnoreCase) && !string.Equals(name, Lang.Get("Preset.Personalized"), StringComparison.OrdinalIgnoreCase) && ValidNameRegex.IsMatch(name) && !Registry.PresetNameExists<T>(type, name);

public static T CreateVoidPreset<T>(IPresetableType type) where T : Presetable
{
Expand Down
Loading

0 comments on commit 0664fa1

Please sign in to comment.