AutoDropBedding 1.1.0

This commit is contained in:
Lilian Jónsdóttir 2023-12-18 22:24:51 -08:00
commit e1fd2d30d6
12 changed files with 258 additions and 0 deletions

View file

@ -0,0 +1,41 @@
using AutoDropBedding;
namespace XRL.World.Parts
{
public class AutoDropBeddingMenu : IPart
{
private static string NAME = "SetUpBedroll";
public override bool WantEvent(int ID, int cascade) =>
ID == InventoryActionEvent.ID ||
ID == GetCookingActionsEvent.ID ||
base.WantEvent(ID, cascade);
public override bool HandleEvent(GetCookingActionsEvent E)
{
if (Config.AddMenuOptionToCamp && Helpers.HasBedroll())
{
Helpers.Log("Adding menu option.");
E.AddAction(NAME,
"Lay out bedding",
NAME,
Key: 'b',
Default: 0,
Priority: 200);
}
return base.HandleEvent(E);
}
public override bool HandleEvent(InventoryActionEvent E)
{
if (E.Command == NAME)
{
Helpers.Log("Got setup bed command.");
Helpers.PutDownBedroll(campfireCell: E.CellTarget);
E.RequestInterfaceExit();
}
return base.HandleEvent(E);
}
}
}

12
AutoDropBedding/Config.cs Executable file
View file

@ -0,0 +1,12 @@
using static XRL.UI.Options;
namespace AutoDropBedding
{
public static class Config
{
public static bool AutoDrop => GetOption("AutoDropBedding_AutoDrop").EqualsNoCase("Yes");
public static bool AddMenuOptionToCamp => GetOption("AutoDropBedding_AddMenuOptionToCamp").EqualsNoCase("Yes");
public static bool DebugLogging => GetOption("AutoDropBedding_DebugLogging").EqualsNoCase("Yes");
public static bool CompanionDrop => GetOption("AutoDropbedding_CompanionDrop").EqualsNoCase("Yes");
}
}

30
AutoDropBedding/Extensions.cs Executable file
View file

@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using XRL.World;
// maybe this is a little extra but whatever
namespace AutoDropBedding
{
public static class Extensions
{
// todo: find other things that set bedding on fire
private static readonly List<string> Firestarters = new List<string>() {"Campfire", "BlueCampfire"};
public static bool HasAnyLiquid(this Cell cell)
{
foreach (var _ in cell.GetObjects(o => o.HasPart("LiquidVolume")))
return true;
return false;
}
public static bool HasFirestarter(this Cell cell)
{
foreach (string thing in Firestarters)
{
if (cell.HasObject(thing))
return true;
}
return false;
}
}
}

View file

@ -0,0 +1,25 @@
using HarmonyLib;
using XRL.World;
using XRL.World.Parts.Skill;
namespace AutoDropBedding.HarmonyPatches
{
[HarmonyPatch(typeof(Survival_Camp), nameof(Survival_Camp.AttemptCamp))]
public static class Patch_Survival_Camp
{
public static void Postfix(ref bool __result, GameObject Actor)
{
if (__result && Actor.IsPlayer() && Config.AutoDrop)
{
Helpers.PutDownBedroll(who: Actor, first: true);
if (Config.CompanionDrop)
{
foreach (var companion in Actor.GetCompanions())
{
Helpers.PutDownBedroll(who: companion, first: true);
}
}
}
}
}
}

122
AutoDropBedding/Helpers.cs Executable file
View file

@ -0,0 +1,122 @@
using System.Collections.Generic;
using System.Linq;
using XRL.Core;
using XRL.Rules;
using XRL.World;
namespace AutoDropBedding
{
public static class Helpers
{
public static void Log(string msg)
{
if (Config.DebugLogging)
UnityEngine.Debug.Log("[AutoDropBedding] " + msg);
}
public static List<GameObject> GetBedsInInventory(GameObject who = null)
{
Helpers.Log("Checking for beds in inventory.");
return who.Inventory.GetObjects(o => o.HasPart("Bed"));
}
public static Cell FindNearestCampfire(GameObject who = null)
{
foreach (var cell in who.CurrentCell.GetAdjacentCells())
{
if (cell.HasFirestarter())
{
Helpers.Log("Found campfire in cell " + cell.Pos2D.ToString());
return cell;
}
}
Helpers.Log("Couldn't find campfire???");
return null;
}
public static bool HasBedroll(GameObject who = null)
{
if (who == null)
who = XRLCore.Core?.Game?.Player?.Body;
foreach (var _ in GetBedsInInventory(who))
return true;
return false;
}
public static Cell PickBedrollCell(Cell dropperCell, Cell campfireCell)
{
if (dropperCell == null)
dropperCell = XRLCore.Core?.Game?.Player?.Body.CurrentCell;
if (campfireCell == null)
campfireCell = FindNearestCampfire(XRLCore.Core?.Game?.Player?.Body);
Log("Picking cell for bed.");
List<Cell> nearDropperCells = dropperCell.GetAdjacentCells();
nearDropperCells.Add(dropperCell); // ensure bedroll isn't dropped in campfire if dropper is in same cell
if (campfireCell == null)
{
Log("Couldn't find a campfire anywhere, falling back to player cell.");
return dropperCell;
}
string nearbyMsg = "cells nearby: ";
nearDropperCells.ForEach(cell => nearbyMsg += cell.Pos2D.ToString() + " ");
Log(nearbyMsg);
List<Cell> nearCampfireCells = campfireCell.GetAdjacentCells()
.Where(cell => cell.IsEmpty() &&
cell.IsVisible() &&
!cell.HasFirestarter() &&
!cell.HasAnyLiquid())
.ToList();
string campMsg = "cells nearby campfire: ";
nearCampfireCells.ForEach(cell => campMsg += cell.Pos2D.ToString() + " ");
Log(campMsg);
List<Cell> commonCells = nearDropperCells.Intersect(nearCampfireCells).ToList();
string commonMsg = "common cells: ";
commonCells.ForEach(cell => commonMsg += cell.Pos2D.ToString() + " ");
Log(commonMsg);
// return random cell adjacent to both campfire and bedroll dropper, or dropper cell if none
int randy = Stat.GetSeededRandomGenerator(dropperCell.Pos2D.ToString()).Next(0, commonCells.Count);
return commonCells.Count > 0 ? commonCells[randy] : dropperCell;
}
public static void PutDownBedroll(GameObject who = null, Cell campfireCell = null, bool first = false)
{
if (who == null)
who = XRLCore.Core?.Game?.Player?.Body;
if (campfireCell == null)
campfireCell = FindNearestCampfire(who);
if (HasBedroll(who))
{
Cell bedrollCell = PickBedrollCell(who.CurrentCell, campfireCell);
GameObject bed;
List<GameObject> beds = GetBedsInInventory(who);
if (first || beds.Count == 1)
bed = beds[0];
else
bed = XRL.UI.PickItem.ShowPicker(beds);
// why isn't there Inventory.Drop() or something
var newBed = bedrollCell.AddObject(bed);
who.Inventory.RemoveObject(bed);
Log("Putting " + newBed.ShortDisplayName + " into cell.");
IComponent<GameObject>.XDidY(who, "set out", newBed.a + newBed.ShortDisplayName);
}
}
}
}

View file

@ -0,0 +1,5 @@
<objects>
<object Name="Campfire" Load="Merge">
<part Name="AutoDropBeddingMenu" />
</object>
</objects>

7
AutoDropBedding/Options.xml Executable file
View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8" ?>
<options>
<option ID="AutoDropBedding_AutoDrop" DisplayText="Automatically lay out bedding when using the 'Make Camp' ability" Category="Automation" Type="Checkbox" Default="Yes" />
<option ID="AutoDropBedding_AddMenuOptionToCamp" DisplayText="Add 'Lay Out Bedding' option to campfire menu" Category="User Interface" Type="Checkbox" Default="Yes" />
<option ID="AutoDropBedding_DebugLogging" DisplayText="Send AutoDropBedding nonsense to Player.log" Category="Debug" Type="Checkbox" Default="No" />
<option ID="AutoDropbedding_CompanionDrop" DisplayText="Companions also lay out bedding when using the 'Make Camp' ability" Category="Automation" Type="Checkbox" Default="No" />
</options>

8
AutoDropBedding/manifest.json Executable file
View file

@ -0,0 +1,8 @@
{
"id": "AutoDropBedding",
"title": "{{auto drop bedding|Auto Drop Bedding}}",
"description": "Put out a bedroll when you make camp, if you have one. Also adds the option to lay out bedding to the campfire menu.",
"version": "1.1.0",
"author": "{{paisley|Celediel}}",
"previewImage": "preview.png"
}

BIN
AutoDropBedding/preview.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

8
AutoDropBedding/workshop.json Executable file
View file

@ -0,0 +1,8 @@
{
"WorkshopId": 2721168249,
"Title": "Auto Drop Bedding",
"Description": "Put out a bedroll when you make camp, if you have one. Also adds the option to lay out bedding to the campfire menu.",
"Tags": "Script,UX",
"Visibility": "2",
"ImagePath": "preview.png"
}