Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature added: Restrict Hungry Animals to an area (per age and gender) #151

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Languages/English/Keyed/Manager_Keyed.xml
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,10 @@
<FML.Training>Training</FML.Training>
<FML.RestrictToArea>Restrict animals to area?</FML.RestrictToArea>
<FML.RestrictToArea.Tip>Restrict animals to a specific area, optionally separated by gender and lifestage</FML.RestrictToArea.Tip>
<FML.RestrictToHungryArea>Restrict hungry animals</FML.RestrictToHungryArea>
<FML.RestrictToHungryArea.Tip>Restrict hungry animals to a specific area, optionally separated by gender and lifestage, as long as they are not restricted animals marked for slaughter.</FML.RestrictToHungryArea.Tip>
<FML.SendToHungryAreaMaximumFoodNeed.Label>Animal Food Need</FML.SendToHungryAreaMaximumFoodNeed.Label>
<FML.SendToHungryAreaMaximumFoodNeed.Tip>An animal whose food need is below or equal to this value will be restricted to this area.</FML.SendToHungryAreaMaximumFoodNeed.Tip>
<FML.ButcherExcess>Butcher excess livestock</FML.ButcherExcess>
<FML.ButcherExcess.Tip>Should excess livestock be butchered for meat?</FML.ButcherExcess.Tip>
<FML.ButcherTrained>Trained</FML.ButcherTrained>
Expand Down
16 changes: 16 additions & 0 deletions Source/Helpers/Utilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,22 @@ public static void DrawToggle( Rect rect, string label, string tooltip, bool che
DrawToggle( rect, label, tooltip, checkOn, !checkOn, on, off, expensive, size, margin, wrap );
}

public static void DrawSlider(Rect rect, string label, string tooltip, ref float value, float size = 5*SmallIconSize,
float margin = Margin, bool wrap = true)
{
// set up rects
var labelRect = rect;
var sliderRect = new Rect(rect.xMax - size - margin, 0f, size, labelRect.height/2f);
labelRect.xMax = sliderRect.xMin - Margin / 2f;
// finetune rects
sliderRect = sliderRect.CenteredOnYIn(labelRect);
// draw label
Label(rect, label, TextAnchor.MiddleLeft, GameFont.Small, margin: margin, wrap: wrap);
// tooltip
if (!tooltip.NullOrEmpty()) TooltipHandler.TipRegion(rect, tooltip );
// draw slider
value = Widgets.HorizontalSlider(sliderRect, value, 0f, 1f, true, String.Format("{0:P0}", value)); // GUI.HorizontalSlider(sliderRect, value, 0f, 1f);
}

public static void DrawToggle( Rect rect, string label, string tooltip, bool checkOn, bool checkOff, Action on,
Action off, bool expensive = false, float size = SmallIconSize,
Expand Down
17 changes: 17 additions & 0 deletions Source/ManagerJobs/ManagerJob_Livestock.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ public class ManagerJob_Livestock : ManagerJob
public bool RespectBonds = true;
public List<Area> RestrictArea;
public bool RestrictToArea;
public List<Area> RestrictHungryArea;
public bool RestrictToHungryArea;
public float SendToHungryAreaMaximumFoodNeed;
public bool SendToSlaughterArea;
public bool SendToTrainingArea;
public bool SetFollow;
Expand Down Expand Up @@ -72,6 +75,11 @@ public ManagerJob_Livestock( Manager manager ) : base( manager )
RestrictToArea = false;
RestrictArea = Utilities_Livestock.AgeSexArray.Select( k => (Area) null ).ToList();

// set hungry animals areas for restriction
RestrictToHungryArea = false;
SendToHungryAreaMaximumFoodNeed = 0.01f;
RestrictHungryArea = Utilities_Livestock.AgeSexArray.Select(k => (Area)null).ToList();

// set up sending animals designated for slaughter to an area (freezer)
SendToSlaughterArea = false;
SlaughterArea = null;
Expand Down Expand Up @@ -141,6 +149,7 @@ public override void ExposeData()
Scribe_References.Look( ref Master, "Master" );
Scribe_References.Look( ref Trainer, "Trainer" );
Scribe_Collections.Look( ref RestrictArea, "AreaRestrictions", LookMode.Reference );
Scribe_Collections.Look(ref RestrictHungryArea, "HungryAreaRestrictions", LookMode.Reference);
Scribe_Deep.Look( ref Trigger, "trigger", manager );
Scribe_Deep.Look( ref Training, "Training" );
Scribe_Deep.Look( ref _history, "History" );
Expand All @@ -149,6 +158,8 @@ public override void ExposeData()
Scribe_Values.Look( ref ButcherPregnant, "ButcherPregnant" );
Scribe_Values.Look( ref ButcherBonded, "ButcherBonded" );
Scribe_Values.Look( ref RestrictToArea, "RestrictToArea" );
Scribe_Values.Look( ref RestrictToHungryArea, "RestrictToHungryArea", false);
Scribe_Values.Look( ref SendToHungryAreaMaximumFoodNeed, "SendToHungryAreaMaximumFoodNeed", 0.01f);
Scribe_Values.Look( ref SendToSlaughterArea, "SendToSlaughterArea" );
Scribe_Values.Look( ref SendToTrainingArea, "SendToTrainingArea" );
Scribe_Values.Look( ref TryTameMore, "TryTameMore" );
Expand Down Expand Up @@ -221,6 +232,12 @@ private void DoAreaRestrictions( ref bool actionTaken )
p.playerSettings.AreaRestriction = SlaughterArea;
}

// hungry
else if (RestrictToHungryArea && p.needs.food.CurLevelPercentage <= SendToHungryAreaMaximumFoodNeed)
{
actionTaken = true;
p.playerSettings.AreaRestriction = RestrictHungryArea[i];
}
// training
else if ( SendToTrainingArea && p.training.NextTrainableToTrain() != null )
{
Expand Down
98 changes: 60 additions & 38 deletions Source/ManagerTabs/ManagerTab_Livestock.cs
Original file line number Diff line number Diff line change
Expand Up @@ -361,44 +361,8 @@ private float DrawAreaRestrictionsSection( Vector2 pos, float width )

if ( _selectedCurrent.RestrictToArea )
{
// area selectors table
// set up a 3x3 table of rects
var cols = 3;
var fifth = width / 5;
float[] widths = {fifth, fifth * 2, fifth * 2};
float[] heights = {ListEntryHeight * 2 / 3, ListEntryHeight, ListEntryHeight};

var areaRects = new Rect[cols, cols];
for ( var x = 0; x < cols; x++ )
for ( var y = 0; y < cols; y++ )
areaRects[x, y] = new Rect(
widths.Take( x ).Sum(),
pos.y + heights.Take( y ).Sum(),
widths[x],
heights[y] );

// headers
Label( areaRects[1, 0], Gender.Female.ToString(), TextAnchor.LowerCenter, GameFont.Tiny );
Label( areaRects[2, 0], Gender.Male.ToString(), TextAnchor.LowerCenter, GameFont.Tiny );
Label( areaRects[0, 1], "FML.Adult".Translate(), TextAnchor.MiddleRight, GameFont.Tiny );
Label( areaRects[0, 2], "FML.Juvenile".Translate(), TextAnchor.MiddleRight, GameFont.Tiny );

// do the selectors
_selectedCurrent.RestrictArea[0] = AreaAllowedGUI.DoAllowedAreaSelectors( areaRects[1, 1],
_selectedCurrent.RestrictArea[
0], manager, Margin );
_selectedCurrent.RestrictArea[1] = AreaAllowedGUI.DoAllowedAreaSelectors( areaRects[2, 1],
_selectedCurrent.RestrictArea[
1], manager, Margin );
_selectedCurrent.RestrictArea[2] = AreaAllowedGUI.DoAllowedAreaSelectors( areaRects[1, 2],
_selectedCurrent.RestrictArea[
2], manager, Margin );
_selectedCurrent.RestrictArea[3] = AreaAllowedGUI.DoAllowedAreaSelectors( areaRects[2, 2],
_selectedCurrent.RestrictArea[
3], manager, Margin );

Text.Anchor = TextAnchor.UpperLeft; // DoAllowedAreaMode leaves the anchor in an incorrect state.
pos.y += 3 * ListEntryHeight;
DrawAreaSelectorPerGenderAndAge(pos, width, ref _selectedCurrent.RestrictArea);
pos.y += 3 * ListEntryHeight;
}

var sendToSlaughterAreaRect = new Rect( pos.x, pos.y, width, ListEntryHeight );
Expand Down Expand Up @@ -426,6 +390,29 @@ private float DrawAreaRestrictionsSection( Vector2 pos, float width )
color: Color.grey );
}

// restrict to hungry area
var RestrictHungryAreaRect = new Rect(pos.x, pos.y, width, ListEntryHeight);

DrawToggle(RestrictHungryAreaRect,
"FML.RestrictToHungryArea".Translate(),
"FML.RestrictToHungryArea.Tip".Translate(),
ref _selectedCurrent.RestrictToHungryArea);
pos.y += ListEntryHeight;
if (_selectedCurrent.RestrictToHungryArea)
{
if (_selectedCurrent.RestrictHungryArea.Count != _selectedCurrent.RestrictArea.Count)
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without this workaround, if you load an existing save, the GUI goes crazy (I assume because the new array has some sort of bad initialisation data).
I'm sure there is a better way, checking for null correctly, but after trying that I could not get it to work.

{
_selectedCurrent.RestrictHungryArea = Utilities_Livestock.AgeSexArray.Select(k => (Area)null).ToList();
}
DrawAreaSelectorPerGenderAndAge(pos, width, ref _selectedCurrent.RestrictHungryArea);
pos.y += 3 * ListEntryHeight;
var HungryAreaFoodFullness = new Rect(pos.x, pos.y, width, ListEntryHeight);
HungryAreaFoodFullness.xMin += 3 * Margin;
DrawSlider(HungryAreaFoodFullness, "FML.SendToHungryAreaMaximumFoodNeed.Label".Translate(), "FML.SendToHungryAreaMaximumFoodNeed.Tip".Translate(),
ref _selectedCurrent.SendToHungryAreaMaximumFoodNeed);
pos.y += ListEntryHeight;
}

var sendToTrainingAreaRect = new Rect( pos.x, pos.y, width, ListEntryHeight );
pos.y += ListEntryHeight;
if ( _selectedCurrent.Training.Any )
Expand Down Expand Up @@ -454,6 +441,41 @@ private float DrawAreaRestrictionsSection( Vector2 pos, float width )
return pos.y - start.y;
}



private void DrawAreaSelectorPerGenderAndAge(Vector2 pos, float width, ref List<Area> restrictArea)
{
// area selectors table
// set up a 3x3 table of rects
var cols = 3;
var fifth = width / 5;
float[] widths = { fifth, fifth * 2, fifth * 2 };
float[] heights = { ListEntryHeight * 2 / 3, ListEntryHeight, ListEntryHeight };

var areaRects = new Rect[cols, cols];
for (var x = 0; x < cols; x++)
for (var y = 0; y < cols; y++)
areaRects[x, y] = new Rect(
widths.Take(x).Sum(),
pos.y + heights.Take(y).Sum(),
widths[x],
heights[y]);

// headers
Label(areaRects[1, 0], Gender.Female.ToString(), TextAnchor.LowerCenter, GameFont.Tiny);
Label(areaRects[2, 0], Gender.Male.ToString(), TextAnchor.LowerCenter, GameFont.Tiny);
Label(areaRects[0, 1], "FML.Adult".Translate(), TextAnchor.MiddleRight, GameFont.Tiny);
Label(areaRects[0, 2], "FML.Juvenile".Translate(), TextAnchor.MiddleRight, GameFont.Tiny);

// do the selectors
restrictArea[0] = AreaAllowedGUI.DoAllowedAreaSelectors(areaRects[1, 1], restrictArea[0], manager, Margin);
restrictArea[1] = AreaAllowedGUI.DoAllowedAreaSelectors(areaRects[2, 1], restrictArea[1], manager, Margin);
restrictArea[2] = AreaAllowedGUI.DoAllowedAreaSelectors(areaRects[1, 2], restrictArea[2], manager, Margin);
restrictArea[3] = AreaAllowedGUI.DoAllowedAreaSelectors(areaRects[2, 2], restrictArea[3], manager, Margin);

Text.Anchor = TextAnchor.UpperLeft; // DoAllowedAreaMode leaves the anchor in an incorrect state.
}

private float DrawTrainingSection( Vector2 pos, float width )
{
var trainingRect = new Rect( pos.x, pos.y, width, ListEntryHeight );
Expand Down