using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text.Json;
using BepInEx;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppSystem.Collections.Generic;
using SOD.Common;
using SOD.Common.BepInEx;
using SOD.Common.BepInEx.Configuration;
using SOD.Common.Extensions;
using SOD.Common.Helpers;
using SOD.Common.Helpers.DialogObjects;
using SOD.Common.Helpers.ObjectiveObjects;
using SOD.Common.Helpers.SyncDiskObjects;
using SOD.LifeAndLiving.Bindings.EconomicBindings;
using SOD.LifeAndLiving.Bindings.ImRequirementBindings;
using SOD.LifeAndLiving.Bindings.RelationBindings;
using SOD.LifeAndLiving.Bindings.SyncDiskBindings;
using SOD.LifeAndLiving.Content.SocialRelation;
using SOD.LifeAndLiving.Content.SocialRelation.Dialogs;
using SOD.LifeAndLiving.Content.SyncDisks;
using SOD.LifeAndLiving.Patches.EconomyRebalancePatches;
using SOD.RelationsPlus;
using SOD.RelationsPlus.Objects;
using UnityEngine;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("SOD.LifeAndLiving")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+105368c6fd0dd8757a25de203851c1af249c7651")]
[assembly: AssemblyProduct("SOD.LifeAndLiving")]
[assembly: AssemblyTitle("SOD.LifeAndLiving")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace SOD.LifeAndLiving
{
public interface IPluginBindings : ISideJobBindings, IMurderCaseBindings, ISpawnRateBindings, IHousingBindings, SOD.LifeAndLiving.Bindings.EconomicBindings.IDialogBindings, IMoneyBindings, IShopsBindings, IItemPriceBindings, SOD.LifeAndLiving.Bindings.RelationBindings.IDialogBindings, ImRequirementBindings, ISyncDiskBindings
{
}
[BepInPlugin("Venomaus.SOD.LifeAndLiving", "LifeAndLiving", "3.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class Plugin : PluginController<Plugin, IPluginBindings>
{
public const string PLUGIN_GUID = "Venomaus.SOD.LifeAndLiving";
public const string PLUGIN_NAME = "LifeAndLiving";
public const string PLUGIN_VERSION = "3.0.0";
public readonly Random Random = new Random();
public override void Load()
{
Lib.SaveGame.OnBeforeLoad += SaveGame_OnBeforeLoad;
Lib.SaveGame.OnAfterLoad += SaveGame_OnAfterLoad;
Lib.SaveGame.OnBeforeSave += SaveGame_OnBeforeSave;
Lib.SaveGame.OnBeforeDelete += SaveGame_OnBeforeDelete;
CivilianDialogAdditions.Initialize();
Echolocation.Initialize();
base.Harmony.PatchAll(Assembly.GetExecutingAssembly());
PluginController<Plugin, IPluginBindings>.Log.LogInfo((object)"Plugin is patched.");
}
public override void OnConfigureBindings()
{
base.OnConfigureBindings();
base.UpdateConfigFileLayout();
}
private void SaveGame_OnBeforeDelete(object sender, SaveGameArgs e)
{
string uniqueString = Lib.SaveGame.GetUniqueString(e.FilePath);
NewGameLocationPatches.NewGameLocation_GetPrice.Delete(uniqueString);
PlayerInterests.Instance.Delete(uniqueString);
}
private void SaveGame_OnBeforeSave(object sender, SaveGameArgs e)
{
string uniqueString = Lib.SaveGame.GetUniqueString(e.FilePath);
NewGameLocationPatches.NewGameLocation_GetPrice.Save(uniqueString);
PlayerInterests.Instance.Save(uniqueString);
}
private void SaveGame_OnBeforeLoad(object sender, SaveGameArgs e)
{
string uniqueString = Lib.SaveGame.GetUniqueString(e.FilePath);
NewGameLocationPatches.NewGameLocation_GetPrice.Load(uniqueString);
PlayerInterests.Instance.Load(uniqueString);
}
private void SaveGame_OnAfterLoad(object sender, SaveGameArgs e)
{
//IL_007b: Unknown result type (might be due to invalid IL or missing references)
//IL_0080: Unknown result type (might be due to invalid IL or missing references)
//IL_008a: Unknown result type (might be due to invalid IL or missing references)
//IL_009b: Unknown result type (might be due to invalid IL or missing references)
//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
Random random = null;
List<KeyValuePair<InteractablePreset, int>> list = new List<KeyValuePair<InteractablePreset, int>>();
Enumerator<Company> enumerator = CityData.Instance.companyDirectory.GetEnumerator();
while (enumerator.MoveNext())
{
Company current = enumerator.Current;
Enumerator<InteractablePreset, int> enumerator2 = current.prices.GetEnumerator();
while (enumerator2.MoveNext())
{
KeyValuePair<InteractablePreset, int> current2 = enumerator2.Current;
list.Add(new KeyValuePair<InteractablePreset, int>(current2.Key, current2.Value));
}
foreach (KeyValuePair<InteractablePreset, int> item in list)
{
Vector2 value = item.Key.value;
if ((float)item.Value < value.x || (float)item.Value > value.y)
{
if (random == null)
{
random = new Random((int)Lib.SaveGame.GetUniqueNumber(CityData.Instance.seed));
}
current.prices[item.Key] = random.Next((int)value.x, (int)value.y + 1);
}
}
list.Clear();
}
}
}
}
namespace SOD.LifeAndLiving.Content.SyncDisks
{
internal static class Echolocation
{
private static int _effectId;
internal static Color Color { get; private set; }
internal static void Initialize()
{
//IL_0064: Unknown result type (might be due to invalid IL or missing references)
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
if (((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.IncludeEcholocationSyncDisk)
{
try
{
Color color = ColorTranslator.FromHtml(((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.EcholocationTextColor);
Color = new Color((float)(int)color.R, (float)(int)color.G, (float)(int)color.B, (float)(int)color.A);
}
catch
{
PluginController<Plugin, IPluginBindings>.Log.LogError((object)"Unable to read config value for \"NpcChatterTextColor\", using fallback cyan color.");
Color = Color.cyan;
}
Lib.SyncDisks.OnAfterSyncDiskInstalled += OnSyncDiskInstall;
Lib.SyncDisks.OnAfterSyncDiskUninstalled += OnSyncDiskUninstall;
Lib.SyncDisks.Builder("Echolocation", "Venomaus.SOD.LifeAndLiving", true).SetPrice(((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.EcholocationDiskPrice).SetManufacturer((Manufacturer)5)
.SetRarity((Rarity)3)
.AddEffect("Echolocation", "Highlights civilian chatter for your selected case if their voice is identified and their profile is on your selected case board.", ref _effectId, (string)null)
.AddSaleLocation((SyncDiskSaleLocation[])(object)new SyncDiskSaleLocation[1] { (SyncDiskSaleLocation)23 })
.CreateAndRegister();
}
}
private static void OnSyncDiskUninstall(object sender, SyncDiskArgs e)
{
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
if (e.Effect.HasValue && e.Effect.Value.Id == _effectId)
{
SpeechController_Update.EffectEnabled = false;
SpeechController_Update.ClearActors();
}
}
private static void OnSyncDiskInstall(object sender, SyncDiskArgs e)
{
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
if (e.Effect.HasValue && e.Effect.Value.Id == _effectId)
{
SpeechController_Update.EffectEnabled = true;
SpeechController_Update.ClearActors();
SpeechController_Update.SetActorsOfCurrentCase();
}
}
}
[HarmonyPatch(typeof(CasePanelController), "UpdatePinned")]
internal static class CasePanelController_UpdatePinned
{
[HarmonyPostfix]
internal static void Postfix(CasePanelController __instance)
{
if (!MainMenuController.Instance.mainMenuActive && __instance.activeCase != null)
{
SpeechController_Update.SetActorsOfCurrentCase();
}
}
}
[HarmonyPatch(typeof(CasePanelController), "SetActiveCase")]
internal static class CasePanelController_SetActiveCase
{
private static Case _currentCase;
[HarmonyPrefix]
internal static void Prefix(CasePanelController __instance)
{
_currentCase = __instance.activeCase;
}
[HarmonyPostfix]
internal static void Postfix(CasePanelController __instance)
{
if ((_currentCase != null || __instance.activeCase != null) && ((_currentCase == null && __instance.activeCase != null) || (_currentCase != null && __instance.activeCase == null) || _currentCase.id != __instance.activeCase.id))
{
SpeechController_Update.ClearActors();
SpeechController_Update.SetActorsOfCurrentCase();
}
}
}
[HarmonyPatch(typeof(SpeechController), "Update")]
internal static class SpeechController_Update
{
private static readonly HashSet<int> _actorsOnCurrentCaseboard = new HashSet<int>();
private static bool _speechActive = false;
private static Color _originalColor;
internal static bool IsDirty = false;
internal static bool EffectEnabled = false;
private static readonly HashSet<int> _empty = new HashSet<int>();
[HarmonyPostfix]
internal static void Postfix(SpeechController __instance)
{
//IL_007c: Unknown result type (might be due to invalid IL or missing references)
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_0066: Unknown result type (might be due to invalid IL or missing references)
bool flag = (Object)(object)__instance.activeSpeechBubble != (Object)null;
if ((_speechActive == flag && !IsDirty) || (!IsDirty && (!EffectEnabled || _actorsOnCurrentCaseboard.Count == 0)))
{
return;
}
_speechActive = flag;
if (!((Object)(object)__instance.activeSpeechBubble == (Object)null))
{
if (flag && !IsDirty)
{
_originalColor = ((Graphic)__instance.activeSpeechBubble.text).color;
}
((Graphic)__instance.activeSpeechBubble.text).color = GetColorForActor(__instance.actor);
IsDirty = false;
}
}
internal static void ClearActors()
{
_actorsOnCurrentCaseboard.Clear();
IsDirty = true;
}
internal static void SetActorsOfCurrentCase()
{
if (CasePanelController.Instance.activeCase == null)
{
AdjustActors(_empty);
return;
}
HashSet<int> hashSet = null;
Enumerator<CaseElement> enumerator = CasePanelController.Instance.activeCase.caseElements.GetEnumerator();
Evidence val = default(Evidence);
while (enumerator.MoveNext())
{
CaseElement current = enumerator.Current;
if (!Toolbox.Instance.TryGetEvidence(current.id, ref val))
{
continue;
}
EvidenceCitizen val2 = ((Il2CppObjectBase)val).TryCast<EvidenceCitizen>();
if (val2 != null && val.GetTiedKeys(current.dk).Contains((DataKey)4))
{
if (hashSet == null)
{
hashSet = new HashSet<int>();
}
hashSet.Add(val2.witnessController.humanID);
}
}
AdjustActors(hashSet ?? _empty);
}
private static Color GetColorForActor(Actor actor)
{
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_004a: Unknown result type (might be due to invalid IL or missing references)
if (!EffectEnabled || !((Object)(object)actor.ai != (Object)null) || !((Object)(object)actor.ai.human != (Object)null) || !_actorsOnCurrentCaseboard.Contains(actor.ai.human.humanID))
{
return _originalColor;
}
return Echolocation.Color;
}
private static void AdjustActors(HashSet<int> actorIds)
{
if (_actorsOnCurrentCaseboard.Count == 0 && actorIds.Count == 0)
{
return;
}
HashSet<int> hashSet = _actorsOnCurrentCaseboard.ToHashSet();
_actorsOnCurrentCaseboard.Clear();
foreach (int actorId in actorIds)
{
_actorsOnCurrentCaseboard.Add(actorId);
}
IsDirty = hashSet.Count != _actorsOnCurrentCaseboard.Count || !hashSet.All((int a) => _actorsOnCurrentCaseboard.Contains(a));
}
}
}
namespace SOD.LifeAndLiving.Content.SocialRelation
{
internal static class CivilianDialogAdditions
{
public static void Initialize()
{
TheUsualDialog.Register();
}
}
public class PlayerInterests
{
private static PlayerInterests _instance;
public static PlayerInterests Instance => _instance ?? (_instance = new PlayerInterests());
public bool ContainsContent
{
get
{
if (ItemsPurchased.Count <= 0)
{
return PurchasedItemsFrom.Count > 0;
}
return true;
}
}
public Dictionary<int, Dictionary<string, int>> ItemsPurchased { get; set; } = new Dictionary<int, Dictionary<string, int>>();
public Dictionary<int, Dictionary<string, int>> PurchasedItemsFrom { get; set; } = new Dictionary<int, Dictionary<string, int>>();
public void RecordPurchasedItem(int companyId, string itemName, Actor from = null)
{
if (!ItemsPurchased.TryGetValue(companyId, out var value))
{
value = (ItemsPurchased[companyId] = new Dictionary<string, int>());
}
if (!value.ContainsKey(itemName))
{
value.Add(itemName, 1);
}
else
{
value[itemName]++;
}
Human val = (Human)(object)((from is Human) ? from : null);
if ((Object)(object)val != (Object)null)
{
if (!PurchasedItemsFrom.TryGetValue(val.humanID, out var value2))
{
value2 = (PurchasedItemsFrom[val.humanID] = new Dictionary<string, int>());
}
string uniqueString = Lib.SaveGame.GetUniqueString(companyId + "_" + itemName);
if (!value2.ContainsKey(uniqueString))
{
value2.Add(uniqueString, 1);
}
else
{
value2[uniqueString]++;
}
}
}
internal void Load(string hash)
{
string savestoreDirectoryPath = Lib.SaveGame.GetSavestoreDirectoryPath(Assembly.GetExecutingAssembly(), "PlayerInterests_" + hash + ".json");
if (File.Exists(savestoreDirectoryPath))
{
PlayerInterests playerInterests = JsonSerializer.Deserialize<PlayerInterests>(File.ReadAllText(savestoreDirectoryPath));
ItemsPurchased = playerInterests.ItemsPurchased;
PurchasedItemsFrom = playerInterests.PurchasedItemsFrom;
}
}
internal void Save(string hash)
{
string savestoreDirectoryPath = Lib.SaveGame.GetSavestoreDirectoryPath(Assembly.GetExecutingAssembly(), "PlayerInterests_" + hash + ".json");
if (!ContainsContent)
{
if (File.Exists(savestoreDirectoryPath))
{
File.Delete(savestoreDirectoryPath);
}
}
else
{
string contents = JsonSerializer.Serialize(this, new JsonSerializerOptions
{
WriteIndented = false
});
File.WriteAllText(savestoreDirectoryPath, contents);
}
}
internal void Delete(string hash)
{
string savestoreDirectoryPath = Lib.SaveGame.GetSavestoreDirectoryPath(Assembly.GetExecutingAssembly(), "PlayerInterests_" + hash + ".json");
if (File.Exists(savestoreDirectoryPath))
{
File.Delete(savestoreDirectoryPath);
}
}
}
}
namespace SOD.LifeAndLiving.Content.SocialRelation.Dialogs
{
internal class TheUsualDialog : IDialogLogic
{
private class Item
{
public string Name { get; }
public InteractablePreset Preset { get; }
public int Price { get; set; }
public bool Discount { get; set; }
public Item(string itemName, InteractablePreset preset, int price)
{
Name = itemName;
Preset = preset;
Price = price;
}
}
private static Guid _positiveResponse;
private static Guid _positiveDiscountResponse;
private static Guid _positiveFreeResponse;
private static Item _item;
private readonly Dictionary<int, (int Hash, bool Received)> _discountCache = new Dictionary<int, (int, bool)>();
internal static void Register()
{
Func<string> func = () => ((int)((Human)Player.Instance).gender != 0) ? (((int)((Human)Player.Instance).gender != 1) ? ("Good choice, one " + _item?.Name + " coming right up!") : ("Good choice ma'am, one " + _item?.Name + " coming right up!")) : ("Good choice sir, one " + _item?.Name + " coming right up!");
Lib.Dialogs.Builder((string)null).SetText("For me, the usual as always.").AddCustomResponse(func, ref _positiveResponse)
.AddCustomResponse((Func<string>)(() => $"You're lucky, this {_item?.Name ?? "item"} has a {((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.TheUsualDiscountValue}% discount!"), ref _positiveDiscountResponse)
.AddCustomResponse((Func<string>)(() => "Coming right up, this " + (_item?.Name ?? "item") + " is on the house!"), ref _positiveFreeResponse)
.AddResponse((Func<string>)(() => "Looks like you can't afford " + (_item?.Name ?? "it") + " today."), false, true)
.ModifyDialogOptions((Action<DialogPreset>)delegate(DialogPreset a)
{
a.useSuccessTest = true;
a.ranking = int.MaxValue;
})
.SetDialogLogic((IDialogLogic)(object)new TheUsualDialog())
.CreateAndRegister();
}
public bool IsDialogShown(DialogPreset preset, Citizen saysTo, SideJob jobRef)
{
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Invalid comparison between Unknown and I4
CitizenRelation val = default(CitizenRelation);
if (!RelationManager.Instance.TryGetValue(((Human)saysTo).humanID, ref val) || (int)val.GetKnowRelation() < 2)
{
return false;
}
if (!((Object)(object)saysTo == (Object)null) && ((Actor)saysTo).isAtWork)
{
Occupation job = ((Human)saysTo).job;
if (((job != null) ? job.employer : null) != null && FirstPersonItemController.Instance.IsSlotAvailable())
{
if (!PlayerInterests.Instance.PurchasedItemsFrom.TryGetValue(((Human)saysTo).humanID, out var value))
{
return false;
}
return value.Any((KeyValuePair<string, int> a) => a.Value >= 4);
}
}
return false;
}
public void OnDialogExecute(DialogController instance, Citizen saysTo, Interactable saysToInteractable, NewNode where, Actor saidBy, bool success, NewRoom roomRef, SideJob jobRef)
{
//IL_0138: Unknown result type (might be due to invalid IL or missing references)
//IL_013e: Unknown result type (might be due to invalid IL or missing references)
//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
if (success && _item != null)
{
_item.Preset.SpawnIntoInventory();
if (PluginController<Plugin, IPluginBindings>.Instance.Random.Next(0, 100) < ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.PositiveInteractionChance)
{
CitizenRelation obj = RelationManager.Instance[((Human)saysTo).humanID];
obj.Like += 0.05f;
}
CitizenRelation obj2 = RelationManager.Instance[((Human)saysTo).humanID];
obj2.Know += 0.05f;
if (_item.Price > 0)
{
GameplayController.Instance.AddMoney(-_item.Price, false, "Purchase");
((Actor)saysTo).speechController.Speak("dds.blocks", _item.Discount ? _positiveDiscountResponse.ToString() : _positiveResponse.ToString(), false, false, false, 0f, false, default(Color), (Human)null, true, false, (SideJob)null, (DialogPreset)null, (AISpeechPreset)null, (Interactable)null);
}
else if (_item.Price == 0)
{
((Actor)saysTo).speechController.Speak("dds.blocks", _positiveFreeResponse.ToString(), false, false, false, 0f, false, default(Color), (Human)null, true, false, (SideJob)null, (DialogPreset)null, (AISpeechPreset)null, (Interactable)null);
}
if ((Object)(object)((Actor)Player.Instance).currentGameLocation != (Object)null && (Object)(object)((Actor)Player.Instance).currentGameLocation.thisAsAddress != (Object)null && ((Actor)Player.Instance).currentGameLocation.thisAsAddress.company != null && ((Actor)Player.Instance).currentGameLocation.thisAsAddress.company.preset.enableLoiteringBehaviour)
{
((Actor)Player.Instance).currentGameLocation.LoiteringPurchase();
}
}
_item = null;
}
public ForceSuccess ShouldDialogSucceedOverride(DialogController instance, DialogOption dialog, Citizen saysTo, NewNode where, Actor saidBy)
{
if (Object.op_Implicit((Object)(object)saysTo))
{
_item = CollectMostPurchasedItem(PlayerInterests.Instance.PurchasedItemsFrom[((Human)saysTo).humanID], ((Human)saysTo).job.employer);
if (_item == null)
{
PluginController<Plugin, IPluginBindings>.Log.LogInfo((object)"Could not find item, this should not have happened.");
return (ForceSuccess)2;
}
int deterministicHashCode = GetDeterministicHashCode((Human)(object)saysTo);
if (!_discountCache.TryGetValue(((Human)saysTo).humanID, out (int, bool) value))
{
value = (_discountCache[((Human)saysTo).humanID] = (deterministicHashCode, false));
}
if (value.Item1 != deterministicHashCode)
{
value = (_discountCache[((Human)saysTo).humanID] = (deterministicHashCode, false));
}
if (!value.Item2)
{
int num = new Random(deterministicHashCode).Next(0, 100);
if (num < ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.TheUsualFreeChance)
{
_item.Price = 0;
_discountCache[((Human)saysTo).humanID] = (deterministicHashCode, true);
}
else if (num < ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.TheUsualDiscountChance)
{
_item.Price -= (int)Math.Round((float)(_item.Price / 100) * (float)((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.TheUsualDiscountValue);
_item.Discount = true;
_discountCache[((Human)saysTo).humanID] = (deterministicHashCode, true);
}
}
if (_item.Price < 0)
{
_item.Price = 0;
}
if (GameplayController.Instance.money >= _item.Price)
{
return (ForceSuccess)0;
}
return (ForceSuccess)2;
}
return (ForceSuccess)0;
}
private static int GetDeterministicHashCode(Human citizen)
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
TimeData currentDateTime = Lib.Time.CurrentDateTime;
return TypeExtensions.GetFnvHashCode($"{((TimeData)(ref currentDateTime)).Year}_{((TimeData)(ref currentDateTime)).Month}_{((TimeData)(ref currentDateTime)).Day}_{((TimeData)(ref currentDateTime)).Hour}_{citizen.humanID}");
}
private static Item CollectMostPurchasedItem(Dictionary<string, int> items, Company company)
{
string key = (from a in items
where a.Value >= 5
orderby a.Value descending
select a).First().Key;
string text = null;
foreach (KeyValuePair<int, Dictionary<string, int>> item in PlayerInterests.Instance.ItemsPurchased)
{
int key2 = item.Key;
foreach (KeyValuePair<string, int> item2 in item.Value)
{
string uniqueString = Lib.SaveGame.GetUniqueString(key2 + "_" + item2.Key);
if (key == uniqueString)
{
text = item2.Key;
break;
}
}
if (text != null)
{
break;
}
}
return GetItem(text, company);
}
private static Item GetItem(string itemName, Company company)
{
if (itemName == null)
{
return null;
}
Enumerator<InteractablePreset, int> enumerator = company.prices.GetEnumerator();
while (enumerator.MoveNext())
{
KeyValuePair<InteractablePreset, int> current = enumerator.Current;
if (((SoCustomComparison)current.key).presetName == itemName)
{
return new Item(itemName, current.Key, current.Value);
}
}
return null;
}
}
}
namespace SOD.LifeAndLiving.Content.EconomyRebalance
{
internal class LostAndFoundPatches
{
[HarmonyPatch(typeof(NewBuilding), "TriggerNewLostAndFound")]
internal class NewBuilding_TriggerNewLostAndFound
{
private static HashSet<int> _lostAndFound;
[HarmonyPrefix]
internal static void Prefix(NewBuilding __instance)
{
_lostAndFound = (from a in EnumerableExtensions.AsEnumerable<LostAndFound>(__instance.lostAndFound)
select HashCode.Combine(a.ownerID, a.buildingID, a.spawnedItem, a.rewardMoney)).ToHashSet();
}
[HarmonyPostfix]
internal static void Postfix(NewBuilding __instance)
{
int payoutReductionLostItems = ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.PayoutReductionLostItems;
int num = 0;
Enumerator<LostAndFound> enumerator = __instance.lostAndFound.GetEnumerator();
while (enumerator.MoveNext())
{
LostAndFound current = enumerator.Current;
int item = HashCode.Combine(current.ownerID, current.buildingID, current.spawnedItem, current.rewardMoney);
if (!_lostAndFound.Contains(item))
{
current.rewardMoney -= (int)((float)(current.rewardMoney / 100) * (float)payoutReductionLostItems);
_lostAndFound.Add(item);
num++;
}
}
_lostAndFound = null;
}
}
[HarmonyPatch(typeof(InteractableCreator), "CreateFurnitureSpawnedInteractableThreadSafe")]
internal class InteractableCreator_CreateFurnitureSpawnedInteractableThreadSafe
{
[HarmonyPrefix]
internal static void Prefix(InteractablePreset preset, List<Passed> passedVars)
{
if ((SoCustomComparison)(object)preset != (SoCustomComparison)null && ((SoCustomComparison)preset).Equals((SoCustomComparison)(object)CityControls.Instance.lostAndFoundNote))
{
Passed val = EnumerableExtensions.AsEnumerable<Passed>(passedVars).FirstOrDefault((Func<Passed, bool>)((Passed a) => (int)a.varType == 25));
if (val != null)
{
int payoutReductionLostItems = ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.PayoutReductionLostItems;
val.value -= (float)(int)(val.value / 100f * (float)payoutReductionLostItems);
}
}
}
}
}
}
namespace SOD.LifeAndLiving.Patches.SocialRelationPatches
{
internal class PurchaseItemPatches
{
[HarmonyPatch(typeof(ShopSelectButtonController), "PurchaseExecute")]
internal static class ShopSelectButtonController_PurchaseExecute
{
[HarmonyPrefix]
internal static void Prefix(out int __state)
{
__state = EnumerableExtensions.Select<InventorySlot, InventorySlot>(FirstPersonItemController.Instance.slots, (Func<InventorySlot, InventorySlot>)((InventorySlot a) => a)).Count((InventorySlot a) => (int)a.isStatic == 0 && a.GetInteractable() == null);
}
[HarmonyPostfix]
internal static void Postfix(ShopSelectButtonController __instance, int __state)
{
if (EnumerableExtensions.Select<InventorySlot, InventorySlot>(FirstPersonItemController.Instance.slots, (Func<InventorySlot, InventorySlot>)((InventorySlot a) => a)).Count((InventorySlot a) => (int)a.isStatic == 0 && a.GetInteractable() == null) == __state)
{
_purchasedFrom = null;
return;
}
NewGameLocation currentGameLocation = ((Actor)Player.Instance).currentGameLocation;
object obj;
if (currentGameLocation == null)
{
obj = null;
}
else
{
NewAddress thisAsAddress = currentGameLocation.thisAsAddress;
obj = ((thisAsAddress != null) ? thisAsAddress.company : null);
}
Company val = (Company)obj;
if (val != null)
{
PlayerInterests.Instance.RecordPurchasedItem(val.companyID, ((SoCustomComparison)__instance.preset).presetName, _purchasedFrom);
}
if ((Object)(object)_purchasedFrom != (Object)null && _resetFieldAction == null)
{
_resetFieldAction = delegate
{
_purchasedFrom = null;
__instance.thisWindow.OnWindowClosed -= WindowClosed.op_Implicit(_resetFieldAction);
_resetFieldAction = null;
};
__instance.thisWindow.OnWindowClosed += WindowClosed.op_Implicit(_resetFieldAction);
}
}
}
[HarmonyPatch(typeof(DialogController), "BuySomething")]
internal static class DialogController_BuySomething
{
[HarmonyPrefix]
internal static void Prefix(Citizen saysTo, bool success)
{
if (!success)
{
_purchasedFrom = null;
}
else
{
_purchasedFrom = (Actor)(object)saysTo;
}
}
}
private static Actor _purchasedFrom;
private static Action _resetFieldAction;
}
}
namespace SOD.LifeAndLiving.Patches.ImmersiveRequirementPatches
{
internal class AirVentScrewdriverPatches
{
[HarmonyPatch(typeof(Interactable), "OnInteraction", new Type[]
{
typeof(InteractionAction),
typeof(Actor),
typeof(bool),
typeof(float)
})]
internal class Interactable_OnInteraction
{
private static void Prefix(Interactable __instance, InteractionAction action, Actor who)
{
if (!((SoCustomComparison)(object)__instance.preset == (SoCustomComparison)null) && !string.IsNullOrWhiteSpace(((SoCustomComparison)__instance.preset).presetName) && ((SoCustomComparison)__instance.preset).presetName.Equals("AirVent") && action != null && !((Object)(object)who == (Object)null) && who.isPlayer && ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.RequireScrewdriverForVents && (action.interactionName.Equals("Open") || action.interactionName.Equals("Close")))
{
_attemptOpenOrCloseAirVent = true;
}
}
}
[HarmonyPatch(typeof(Interactable), "SetSwitchState")]
internal class Interactable_SetSwitchState
{
private static bool Prefix(Actor interactor)
{
if ((Object)(object)interactor == (Object)null || !interactor.isPlayer || !_attemptOpenOrCloseAirVent)
{
return true;
}
_attemptOpenOrCloseAirVent = false;
Interactable[] array = default(Interactable[]);
if (!Lib.Gameplay.HasInteractableInInventory("Screwdriver", ref array))
{
Lib.GameMessage.ShowPlayerSpeech("I could open this with a screwdriver, maybe I should look for one.", 5f, true);
return false;
}
return true;
}
}
[HarmonyPatch(typeof(ChapterIntro), "InvestigateWriterAddress")]
internal class ChapterIntro_InvestigateWriterAddress
{
private static void Prefix(ChapterIntro __instance)
{
if (!((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.RequireScrewdriverForVents)
{
return;
}
Interactable[] array = default(Interactable[]);
if (Lib.Gameplay.HasInteractableInInventory("Screwdriver", ref array))
{
PluginController<Plugin, IPluginBindings>.Log.LogInfo((object)"Already have a screwdriver in the inventory, no need to add objective or spawn a new one.");
return;
}
AirVent[] array2 = default(AirVent[]);
if (!Lib.Gameplay.AirVentExistsInHouse(__instance.kidnapper.home, ref array2))
{
PluginController<Plugin, IPluginBindings>.Log.LogInfo((object)"No airvents found, no need to spawn a screwdriver.");
return;
}
Interactable[] source = default(Interactable[]);
if (!Lib.Gameplay.InteractableExistsInHouse("Screwdriver", __instance.kidnapper.home, ref source))
{
PluginController<Plugin, IPluginBindings>.Log.LogInfo((object)"No screwdrivers found, spawning atleast one.");
FurnitureLocation val = default(FurnitureLocation);
Lib.Gameplay.AddInteractableToHouse("Screwdriver", __instance.kidnapper.home, ref val, ref ScrewDriverForVent, (Human)null, (Human)null, (Human)null, (OwnedPlacementRule)0);
PluginController<Plugin, IPluginBindings>.Log.LogInfo((object)("Screwdriver was spawned in: " + ScrewDriverForVent.node.room.name));
}
else
{
PluginController<Plugin, IPluginBindings>.Log.LogInfo((object)"A screwdriver is already present, no need to spawn an extra one.");
ScrewDriverForVent = source.First();
}
Lib.CaseObjectives.OnObjectiveCompleted += CaseObjectives_OnObjectiveCompleted;
}
private static void CaseObjectives_OnObjectiveCompleted(object sender, ObjectiveArgs e)
{
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
if (ScrewDriverForVent != null && e.EntryRef.StartsWith("Look around for vents for a potential quick exit"))
{
Lib.CaseObjectives.Builder(e.Case).SetText("Look around for a screwdriver to open the air vent").SetIcon((Icon)0)
.SetPointer(ScrewDriverForVent.GetWorldPosition(true))
.SetCompletionTrigger(PredefinedTrigger.GoToNode(ScrewDriverForVent.node))
.Register();
ScrewDriverForVent = null;
Lib.CaseObjectives.OnObjectiveCompleted -= CaseObjectives_OnObjectiveCompleted;
}
}
}
private static bool _attemptOpenOrCloseAirVent;
private static Interactable ScrewDriverForVent;
}
}
namespace SOD.LifeAndLiving.Patches.EconomyRebalancePatches
{
internal class ActionControllerPatches
{
[HarmonyPatch(typeof(ActionController), "TakeLockpickKit")]
internal class ActionController_TakeLockpickKit
{
private static int _previousLockPicks;
[HarmonyPrefix]
internal static void Prefix()
{
_previousLockPicks = GameplayController.Instance.lockPicks;
}
[HarmonyPostfix]
internal static void Postfix()
{
int num = GameplayController.Instance.lockPicks - _previousLockPicks;
GameplayController.Instance.AddLockpicks(-num + ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.LockPickKitAmount, false);
}
}
}
internal class BuyInterfacePatches
{
[HarmonyPatch(typeof(BuyInterfaceController), "UpdateElements")]
internal class BuyInterfaceController_UpdateElements
{
[HarmonyPostfix]
internal static void Postfix(BuyInterfaceController __instance)
{
//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
//IL_00e4: Expected O, but got Unknown
List<ShopSelectButtonController> spawned = __instance.spawned;
bool flag = __instance.company != null && __instance.company.preset.enableSellingOfIllegalItems;
int maxSellPriceAllItemsGeneral = ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.MaxSellPriceAllItemsGeneral;
int maxSellPriceAllItemsBlackMarket = ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.MaxSellPriceAllItemsBlackMarket;
bool flag2 = false;
int num = 0;
Enumerator<ShopSelectButtonController> enumerator = spawned.GetEnumerator();
while (enumerator.MoveNext())
{
ShopSelectButtonController current = enumerator.Current;
if (current.sellInteractable != null && current.sellMode && !((SoCustomComparison)current.sellInteractable.preset).presetName.Equals("Diamond"))
{
int price = current.price;
current.price = Math.Min(current.price, flag ? maxSellPriceAllItemsBlackMarket : maxSellPriceAllItemsGeneral);
if (price != current.price)
{
((ButtonController)current).UpdateButtonText();
flag2 = true;
num++;
}
}
}
if (flag2)
{
__instance.UpdatePurchaseAbility();
ManualLogSource log = PluginController<Plugin, IPluginBindings>.Log;
bool flag3 = default(bool);
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(49, 1, ref flag3);
if (flag3)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Capped sale price of \"");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(num);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("\" items at store interface.");
}
log.LogInfo(val);
}
}
}
}
internal class CityControlsPatches
{
[HarmonyPatch(typeof(CityControls), "Awake")]
internal class CityControls_Awake
{
[HarmonyPrefix]
internal static void Prefix(CityControls __instance)
{
__instance.hotelCostLower = ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.CostLowerSuiteHotel;
__instance.hotelCostUpper = ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.CostHigherSuiteHotel;
PluginController<Plugin, IPluginBindings>.Log.LogInfo((object)"Updated hotel suite prices.");
}
}
}
internal class GameplayControlsPatches
{
[HarmonyPatch(typeof(GameplayControls), "Awake")]
internal class GameplayControls_Awake
{
private static bool _appliedOnce;
[HarmonyPostfix]
internal static void Postfix(GameplayControls __instance)
{
if (!_appliedOnce)
{
_appliedOnce = true;
ReduceMurderPayouts(__instance);
}
}
private static void ReduceMurderPayouts(GameplayControls __instance)
{
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
//IL_004b: Unknown result type (might be due to invalid IL or missing references)
//IL_006a: Unknown result type (might be due to invalid IL or missing references)
//IL_0077: Unknown result type (might be due to invalid IL or missing references)
//IL_009b: Unknown result type (might be due to invalid IL or missing references)
//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
//IL_0155: Unknown result type (might be due to invalid IL or missing references)
//IL_015c: Expected O, but got Unknown
//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
//IL_00de: Unknown result type (might be due to invalid IL or missing references)
//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
//IL_010c: Unknown result type (might be due to invalid IL or missing references)
//IL_0132: Unknown result type (might be due to invalid IL or missing references)
int payoutReductionMurders = ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.PayoutReductionMurders;
int minimumMurderResolveQuestionPayout = ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.MinimumMurderResolveQuestionPayout;
int num = 0;
Enumerator<ResolveQuestion> enumerator = __instance.murderResolveQuestions.GetEnumerator();
while (enumerator.MoveNext())
{
ResolveQuestion current = enumerator.Current;
int num2 = Math.Max(minimumMurderResolveQuestionPayout, (int)current.rewardRange.x - (int)(current.rewardRange.x / 100f * (float)payoutReductionMurders));
int num3 = Math.Max(minimumMurderResolveQuestionPayout, (int)current.rewardRange.y - (int)(current.rewardRange.y / 100f * (float)payoutReductionMurders));
current.rewardRange = new Vector2((float)num2, (float)num3);
if (current.penaltyRange.x > 0f && current.penaltyRange.y > 0f)
{
num2 = Math.Max(minimumMurderResolveQuestionPayout, (int)current.penaltyRange.x + (int)(current.penaltyRange.x / 100f * (float)(payoutReductionMurders / 4)));
num3 = Math.Max(minimumMurderResolveQuestionPayout, (int)current.penaltyRange.y + (int)(current.penaltyRange.y / 100f * (float)(payoutReductionMurders / 4)));
current.penaltyRange = new Vector2((float)num2, (float)num3);
}
num++;
}
ManualLogSource log = PluginController<Plugin, IPluginBindings>.Log;
bool flag = default(bool);
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(43, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Reduced \"");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(num);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("\" murder resolve question payouts.");
}
log.LogInfo(val);
}
}
}
internal class InteractablePatches
{
[HarmonyPatch(typeof(Interactable), "UpdateName")]
internal class Interactable_SetValue
{
[HarmonyPrefix]
internal static void Prefix(Interactable __instance)
{
if (!((SoCustomComparison)(object)__instance.preset == (SoCustomComparison)null))
{
Dictionary<string, int> dictionary = new Dictionary<string, int>
{
{
"M1",
((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.MaxM1Crows
},
{
"M2",
((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.MaxM2Crows
},
{
"M3",
((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.MaxM3Crows
},
{
"M4",
((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.MaxM4Crows
}
};
if (__instance.preset.isMoney && dictionary.TryGetValue(((SoCustomComparison)__instance.preset).presetName, out var value) && __instance.val > (float)value)
{
__instance.val = value;
}
}
}
}
}
internal class NewGameLocationPatches
{
[HarmonyPatch(typeof(NewGameLocation), "GetPrice")]
internal class NewGameLocation_GetPrice
{
private static readonly Random _valueRandom = new Random();
internal static readonly Dictionary<string, int> ApartementPriceCache = new Dictionary<string, int>();
[HarmonyPostfix]
internal static void Postfix(NewGameLocation __instance, ref int __result)
{
string key = __instance.building.buildingID + "_" + __instance.residenceNumber;
if (ApartementPriceCache.TryGetValue(key, out var value))
{
__result = value;
return;
}
__result += __result / 100 * ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.ApartementCostPercentage;
if (__result < ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.MinimumApartementCost)
{
int num = ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.MinimumApartementCost / 2;
int num2 = num / 100 * 25;
__result = RoundToNearestInterval(_valueRandom.Next(num, num + num2) * 2, 50, 100);
}
ApartementPriceCache.Add(key, __result);
}
private static int RoundToNearestInterval(int number, int lowerInterval, int higherInterval)
{
int num = (int)Math.Round((double)number / (double)lowerInterval) * lowerInterval;
int num2 = (int)Math.Round((double)number / (double)higherInterval) * higherInterval;
int num3 = Math.Abs(number - num);
int num4 = Math.Abs(number - num2);
if (num3 < num4)
{
return num;
}
return num2;
}
internal static void Load(string hash)
{
ApartementPriceCache.Clear();
string savestoreDirectoryPath = Lib.SaveGame.GetSavestoreDirectoryPath(Assembly.GetExecutingAssembly(), "apartmentpricecache_" + hash + ".json");
if (!File.Exists(savestoreDirectoryPath))
{
return;
}
foreach (KeyValuePair<string, int> item in JsonSerializer.Deserialize<Dictionary<string, int>>(File.ReadAllText(savestoreDirectoryPath)))
{
ApartementPriceCache.Add(item.Key, item.Value);
}
PluginController<Plugin, IPluginBindings>.Log.LogInfo((object)"Loaded apartment price cache.");
}
internal static void Save(string hash)
{
if (ApartementPriceCache.Count > 0)
{
string savestoreDirectoryPath = Lib.SaveGame.GetSavestoreDirectoryPath(Assembly.GetExecutingAssembly(), "apartmentpricecache_" + hash + ".json");
string contents = JsonSerializer.Serialize(ApartementPriceCache, new JsonSerializerOptions
{
WriteIndented = false
});
File.WriteAllText(savestoreDirectoryPath, contents);
PluginController<Plugin, IPluginBindings>.Log.LogInfo((object)"Saved apartment price cache.");
}
}
internal static void Delete(string hash)
{
string savestoreDirectoryPath = Lib.SaveGame.GetSavestoreDirectoryPath(Assembly.GetExecutingAssembly(), "apartmentpricecache_" + hash + ".json");
if (File.Exists(savestoreDirectoryPath))
{
File.Delete(savestoreDirectoryPath);
PluginController<Plugin, IPluginBindings>.Log.LogInfo((object)"Deleted apartment price cache.");
}
}
}
}
internal class PriceVisualPatches
{
[HarmonyPatch(typeof(MurderController), "UpdateResolveQuestions")]
internal class MurderController_UpdateResolveQuestions
{
[HarmonyPostfix]
internal static void Postfix(MurderController __instance)
{
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
if (__instance.currentActiveCase != null)
{
Enumerator<ResolveQuestion> enumerator = __instance.currentActiveCase.resolveQuestions.GetEnumerator();
while (enumerator.MoveNext())
{
ResolveQuestion current = enumerator.Current;
current.reward = Mathf.RoundToInt(Toolbox.Instance.VectorToRandom(current.rewardRange) * Game.Instance.jobRewardMultiplier);
current.penalty = Mathf.RoundToInt(Toolbox.Instance.VectorToRandom(current.penaltyRange) * Game.Instance.jobPenaltyMultiplier);
}
}
}
}
[HarmonyPatch(typeof(SideJob), "GenerateResolveQuestions")]
internal class SideJob_GenerateResolveQuestions
{
[HarmonyPostfix]
internal static void Postfix(SideJob __instance)
{
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_002c: Invalid comparison between Unknown and I4
//IL_007b: Unknown result type (might be due to invalid IL or missing references)
//IL_00de: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
//IL_0062: Unknown result type (might be due to invalid IL or missing references)
__instance.reward = 0;
Enumerator<ResolveQuestion> enumerator = __instance.resolveQuestions.GetEnumerator();
while (enumerator.MoveNext())
{
ResolveQuestion current = enumerator.Current;
float num = 1f;
if ((int)current.inputType == 3)
{
RevengeObjective revengeObjective = __instance.GetRevengeObjective(current);
if ((SoCustomComparison)(object)revengeObjective != (SoCustomComparison)null)
{
float num2 = Toolbox.Instance.Rand(0f, 1f, false);
num = Mathf.Lerp(revengeObjective.rewardMultiplier.x, revengeObjective.rewardMultiplier.y, num2);
}
}
current.reward = Mathf.RoundToInt(Toolbox.Instance.VectorToRandom(current.rewardRange) * Game.Instance.jobRewardMultiplier * num * GameplayControls.Instance.sideJobDifficultyRewardMultiplier.Evaluate(__instance.GetDifficulty()));
current.reward = Mathf.RoundToInt((float)current.reward * (1f + UpgradeEffectController.Instance.GetUpgradeEffect((Effect)17)));
current.penalty = Mathf.RoundToInt(Toolbox.Instance.VectorToRandom(current.penaltyRange) * Game.Instance.jobPenaltyMultiplier * GameplayControls.Instance.sideJobDifficultyRewardMultiplier.Evaluate(__instance.GetDifficulty()));
__instance.reward += current.reward;
}
}
}
}
internal class ToolboxPatches
{
[HarmonyPatch(typeof(Toolbox), "LoadAll")]
internal class Toolbox_LoadAll
{
private static bool _appliedOnce;
[HarmonyPostfix]
internal static void Postfix(Toolbox __instance)
{
if (!_appliedOnce)
{
_appliedOnce = true;
ReduceJobPayouts(__instance);
AdjustInteractableSpawns(__instance);
AdjustFurnitureCostPrices(__instance);
AdjustDialogCostPrices(__instance);
AdjustItemPrices(__instance);
AdjustCompanyItemSellMultipliers(__instance);
}
}
private static void AdjustDialogCostPrices(Toolbox __instance)
{
//IL_0064: Unknown result type (might be due to invalid IL or missing references)
//IL_006b: Expected O, but got Unknown
int dialogCostPricePercentage = ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.DialogCostPricePercentage;
int num = 0;
Enumerator<DialogPreset> enumerator = __instance.allDialog.GetEnumerator();
while (enumerator.MoveNext())
{
DialogPreset current = enumerator.Current;
if (current.cost > 0)
{
current.cost += (int)((float)current.cost / 100f * (float)dialogCostPricePercentage);
num++;
}
}
ManualLogSource log = PluginController<Plugin, IPluginBindings>.Log;
bool flag = default(bool);
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(31, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Adjusted \"");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(num);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("\" dialog cost prices.");
}
log.LogInfo(val);
}
private static void AdjustFurnitureCostPrices(Toolbox __instance)
{
//IL_0064: Unknown result type (might be due to invalid IL or missing references)
//IL_006b: Expected O, but got Unknown
int furniteCostPercentage = ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.FurniteCostPercentage;
int num = 0;
Enumerator<FurniturePreset> enumerator = __instance.allFurniture.GetEnumerator();
while (enumerator.MoveNext())
{
FurniturePreset current = enumerator.Current;
if (current.cost > 0)
{
current.cost += (int)((float)current.cost / 100f * (float)furniteCostPercentage);
num++;
}
}
ManualLogSource log = PluginController<Plugin, IPluginBindings>.Log;
bool flag = default(bool);
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(34, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Adjusted \"");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(num);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("\" furniture cost prices.");
}
log.LogInfo(val);
}
private static void AdjustCompanyItemSellMultipliers(Toolbox __instance)
{
//IL_0077: Unknown result type (might be due to invalid IL or missing references)
//IL_007e: Expected O, but got Unknown
int percentageSalePriceGeneral = ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.PercentageSalePriceGeneral;
int percentageSalePriceBlackMarket = ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.PercentageSalePriceBlackMarket;
int num = 0;
Enumerator<CompanyPreset> enumerator = __instance.allCompanyPresets.GetEnumerator();
while (enumerator.MoveNext())
{
CompanyPreset current = enumerator.Current;
if (current.enableSellingOfIllegalItems)
{
current.sellValueMultiplier = (float)percentageSalePriceBlackMarket / 100f;
}
else
{
current.sellValueMultiplier = (float)percentageSalePriceGeneral / 100f;
}
num++;
}
ManualLogSource log = PluginController<Plugin, IPluginBindings>.Log;
bool flag = default(bool);
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(25, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Adjusted \"");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(num);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("\" store prices.");
}
log.LogInfo(val);
}
private static void AdjustItemPrices(Toolbox __instance)
{
//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
//IL_01ea: Expected O, but got Unknown
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_0135: Unknown result type (might be due to invalid IL or missing references)
//IL_014a: Unknown result type (might be due to invalid IL or missing references)
//IL_0156: Unknown result type (might be due to invalid IL or missing references)
//IL_0164: Unknown result type (might be due to invalid IL or missing references)
//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
//IL_00be: Invalid comparison between Unknown and I4
//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
//IL_00d9: Invalid comparison between Unknown and I4
Random random = new Random(1000);
int num = 0;
Enumerator<string, InteractablePreset> enumerator = __instance.objectPresetDictionary.GetEnumerator();
while (enumerator.MoveNext())
{
InteractablePreset value = enumerator.Current.value;
if ((SoCustomComparison)(object)value != (SoCustomComparison)null && value.value.y > 0f && !((SoCustomComparison)value).presetName.Equals("Diamond") && !((SoCustomComparison)value).presetName.Equals("SyncDiskUpgrade"))
{
int num2 = ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.PercentageValueIncreaseGeneral;
int num3 = ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.MinGeneralItemValue;
if ((SoCustomComparison)(object)value.retailItem != (SoCustomComparison)null && value.retailItem.isConsumable && ((int)value.retailItem.menuCategory == 1 || (int)value.retailItem.menuCategory == 0 || (int)value.retailItem.menuCategory == 2) && (value.retailItem.nourishment > 0f || value.retailItem.hydration > 0f))
{
num2 = ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.PercentageValueIncreaseFood;
num3 = ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.MinFoodItemValue;
}
float num4 = (float)num2 / 100f + 1f;
int num5 = Math.Max(num3, (int)value.value.x);
int num6 = Math.Max(num5 + ((int)value.value.y - (int)value.value.x), (int)value.value.y);
num5 = (int)((float)num5 * num4);
num6 = (int)((float)num6 * num4);
int num7 = num5 - num3;
if (num7 > 0)
{
num5 -= random.Next(0, Math.Min(num7, 15) + 1);
}
num6 += random.Next(0, 16);
value.value = new Vector2((float)num5, (float)num6);
num++;
}
}
ManualLogSource log = PluginController<Plugin, IPluginBindings>.Log;
bool flag = default(bool);
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(33, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Adjusted \"");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(num);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("\" item purchase prices.");
}
log.LogInfo(val);
}
private static void ReduceJobPayouts(Toolbox __instance)
{
//IL_014d: Unknown result type (might be due to invalid IL or missing references)
//IL_0154: Expected O, but got Unknown
//IL_0060: Unknown result type (might be due to invalid IL or missing references)
//IL_006d: Unknown result type (might be due to invalid IL or missing references)
//IL_008c: Unknown result type (might be due to invalid IL or missing references)
//IL_0099: Unknown result type (might be due to invalid IL or missing references)
//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
//IL_0121: Unknown result type (might be due to invalid IL or missing references)
List<JobPreset> allSideJobs = __instance.allSideJobs;
int payoutReductionJobs = ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.PayoutReductionJobs;
int num = 0;
int minSideJobReward = ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.MinSideJobReward;
Enumerator<JobPreset> enumerator = allSideJobs.GetEnumerator();
while (enumerator.MoveNext())
{
JobPreset current = enumerator.Current;
int num2 = 0;
int num3 = 0;
Enumerator<ResolveQuestion> enumerator2 = current.resolveQuestions.GetEnumerator();
while (enumerator2.MoveNext())
{
ResolveQuestion current2 = enumerator2.Current;
int num4 = Math.Max(1, (int)current2.rewardRange.x - (int)(current2.rewardRange.x / 100f * (float)payoutReductionJobs));
int num5 = Math.Max(1, (int)current2.rewardRange.y - (int)(current2.rewardRange.y / 100f * (float)payoutReductionJobs));
current2.rewardRange = new Vector2((float)num4, (float)num5);
num2 += num4;
num3 += num5;
}
if (num2 < minSideJobReward || num3 < minSideJobReward)
{
int num6 = (int)Math.Ceiling((float)minSideJobReward / (float)current.resolveQuestions.Count);
enumerator2 = current.resolveQuestions.GetEnumerator();
while (enumerator2.MoveNext())
{
enumerator2.Current.rewardRange = new Vector2((float)num6, (float)num6);
}
}
num++;
}
ManualLogSource log = PluginController<Plugin, IPluginBindings>.Log;
bool flag = default(bool);
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(23, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Reduced \"");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(num);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("\" job payouts.");
}
log.LogInfo(val);
}
private static void AdjustInteractableSpawns(Toolbox __instance)
{
//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
//IL_0183: Unknown result type (might be due to invalid IL or missing references)
InteractablePreset interactablePreset = __instance.GetInteractablePreset("Diamond");
InteractablePreset interactablePreset2 = __instance.GetInteractablePreset("Hairpin");
InteractablePreset interactablePreset3 = __instance.GetInteractablePreset("Paperclip");
InteractablePreset interactablePreset4 = __instance.GetInteractablePreset("SyncDiskUpgrade");
InteractablePreset interactablePreset5 = __instance.GetInteractablePreset("SyncDisk");
InteractablePreset[] looseChange = new string[4] { "M1", "M2", "M3", "M4" }.Select((string a) => __instance.GetInteractablePreset(a)).ToArray();
if (((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.ReduceDiamondSpawnPerAddress)
{
interactablePreset.perRoomLimit = 1;
interactablePreset.perAddressLimit = 1;
interactablePreset.limitPerRoom = true;
interactablePreset.limitPerAddress = true;
}
interactablePreset.value = new Vector2((float)((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.MinDiamondValue, (float)((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.MaxDiamondValue);
if (((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.SpawnDiamondsOnlyInApartements)
{
interactablePreset.autoPlacement = (AutoPlacement)2;
}
if (((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.LimitSpawnrateSyncDiskUpgradeModules)
{
interactablePreset4.perRoomLimit = 1;
interactablePreset4.perAddressLimit = 2;
interactablePreset4.perObjectLimit = 1;
interactablePreset4.perCommercialLimit = 2;
interactablePreset4.limitInCommercial = true;
interactablePreset4.limitPerRoom = true;
interactablePreset4.limitPerAddress = true;
interactablePreset4.limitPerObject = true;
}
interactablePreset4.value = new Vector2((float)((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.MinSyncDiskUpgradeModuleValue, (float)((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.MaxSyncDiskUpgradeModuleValue);
if (((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.LimitSpawnrateSyncDisks)
{
interactablePreset5.perRoomLimit = 1;
interactablePreset5.perAddressLimit = 2;
interactablePreset5.perObjectLimit = 1;
interactablePreset5.perCommercialLimit = 2;
interactablePreset5.limitInCommercial = true;
interactablePreset5.limitPerRoom = true;
interactablePreset5.limitPerAddress = true;
interactablePreset5.limitPerObject = true;
}
AdjustHairPins(interactablePreset2);
AdjustPaperClips(interactablePreset3);
AdjustLooseChange(looseChange);
PluginController<Plugin, IPluginBindings>.Log.LogInfo((object)"Adjusted spawn rate of interactables.");
}
private static void AdjustLooseChange(InteractablePreset[] looseChange)
{
foreach (InteractablePreset val in looseChange)
{
val.perRoomLimit = 1;
val.perAddressLimit = 1;
val.frequencyPerOwnerMax = 1;
val.limitPerAddress = true;
val.limitPerRoom = true;
val.limitPerObject = true;
if (((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.LimitLooseMoneyToApartementsOnly)
{
val.autoPlacement = (AutoPlacement)2;
}
}
}
private static void AdjustPaperClips(InteractablePreset paperClipPreset)
{
paperClipPreset.frequencyPerOwnerMin = 0;
paperClipPreset.frequencyPerOwnerMax = 1;
if (((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.ReduceLockPickSpawnPerRoom)
{
paperClipPreset.perRoomLimit = 1;
paperClipPreset.limitPerRoom = true;
}
if (((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.ReduceLockPickSpawnPerAddress)
{
paperClipPreset.perAddressLimit = 2;
paperClipPreset.limitPerAddress = true;
}
if (((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.LimitPaperclipToOfficeOnly)
{
paperClipPreset.autoPlacement = (AutoPlacement)1;
}
}
private static void AdjustHairPins(InteractablePreset hairPinPreset)
{
hairPinPreset.frequencyPerOwnerMin = 0;
hairPinPreset.frequencyPerOwnerMax = 1;
if (((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.ReduceLockPickSpawnPerRoom)
{
hairPinPreset.perRoomLimit = 1;
hairPinPreset.limitPerRoom = true;
}
if (((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.ReduceLockPickSpawnPerAddress)
{
hairPinPreset.perAddressLimit = 2;
hairPinPreset.limitPerAddress = true;
}
if (((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.LimitHairPinToHomeOnly)
{
hairPinPreset.autoPlacement = (AutoPlacement)2;
}
}
}
}
}
namespace SOD.LifeAndLiving.Bindings.SyncDiskBindings
{
public interface ISyncDiskBindings
{
[Binding(true, "Add's the Echolocation sync disk to the game.", "LifeAndLiving.SyncDisks.IncludeEcholocationSyncDisk")]
bool IncludeEcholocationSyncDisk { get; set; }
[Binding("#00fbff", "The color for the Echolocation in hex.", "LifeAndLiving.SyncDisks.EcholocationTextColor")]
string EcholocationTextColor { get; set; }
[Binding(1250, "The price of the Echolocation sync disk.", "LifeAndLiving.SyncDisks.EcholocationDiskPrice")]
int EcholocationDiskPrice { get; set; }
}
}
namespace SOD.LifeAndLiving.Bindings.RelationBindings
{
public interface IDialogBindings
{
[Binding(10, "The percentage chance of the usual being free.", "LifeAndLiving.RelationsDialog.TheUsualFreeChance")]
int TheUsualFreeChance { get; set; }
[Binding(25, "The percentage chance to get a discount on the usual.", "LifeAndLiving.RelationsDialog.TheUsualDiscountChance")]
int TheUsualDiscountChance { get; set; }
[Binding(35, "The percentage value of the usual's discount.", "LifeAndLiving.RelationsDialog.TheUsualDiscountValuePercentage")]
int TheUsualDiscountValue { get; set; }
[Binding(10, "The percentage chance to get a positive interaction when having certain dialog with an npc.", "LifeAndLiving.RelationsDialog.PositiveInteractionChance")]
int PositiveInteractionChance { get; set; }
}
}
namespace SOD.LifeAndLiving.Bindings.ImRequirementBindings
{
public interface ImRequirementBindings
{
[Binding(true, "Should the player need a screwdriver in their inventory to open vents?", "LifeAndLiving.ImmersiveRequirements.RequireScrewdriverForVents")]
bool RequireScrewdriverForVents { get; set; }
}
}
namespace SOD.LifeAndLiving.Bindings.EconomicBindings
{
public interface ISideJobBindings
{
[Binding(150, "The minimum amount a side job should reward.", "LifeAndLiving.SideJobs.MinSideJobReward")]
int MinSideJobReward { get; set; }
[Binding(75, "The percentage reduction of job resolve payouts.", "LifeAndLiving.SideJobs.PayoutReductionJobs")]
int PayoutReductionJobs { get; set; }
[Binding(-150, "The percentage reduction of lost items payouts.", "LifeAndLiving.SideJobs.PayoutReductionLostItems")]
int PayoutReductionLostItems { get; set; }
}
public interface IMurderCaseBindings
{
[Binding(80, "The percentage reduction of murder case resolve payouts.", "LifeAndLiving.MurderCases.PayoutReductionMurders")]
int PayoutReductionMurders { get; set; }
[Binding(50, "The minimum a resolve question of a murder case should payout.", "LifeAndLiving.MurderCases.MinimumMurderResolveQuestionPayout")]
int MinimumMurderResolveQuestionPayout { get; set; }
}
public interface ISpawnRateBindings
{
[Binding(true, "This drastically reduces lockpicks per room", "LifeAndLiving.SpawnRate.ReduceLockPickSpawnPerRoom")]
bool ReduceLockPickSpawnPerRoom { get; set; }
[Binding(true, "This drastically reduces lockpicks per address", "LifeAndLiving.SpawnRate.ReduceLockPickSpawnPerAddress")]
bool ReduceLockPickSpawnPerAddress { get; set; }
[Binding(true, "This drastically reduces diamonds spawned per address", "LifeAndLiving.SpawnRate.ReduceDiamondSpawnPerAddress")]
bool ReduceDiamondSpawnPerAddress { get; set; }
[Binding(true, "Should diamonds only spawn in apartements.", "LifeAndLiving.SpawnRate.SpawnDiamondsOnlyInApartements")]
bool SpawnDiamondsOnlyInApartements { get; set; }
[Binding(true, "Should hair pins only spawn in apartment homes?", "LifeAndLiving.SpawnRate.LimitHairPinToHomeOnly")]
bool LimitHairPinToHomeOnly { get; set; }
[Binding(true, "Should paper clips only spawn in office buildings?", "LifeAndLiving.SpawnRate.LimitPaperclipToOfficeOnly")]
bool LimitPaperclipToOfficeOnly { get; set; }
[Binding(true, "Should loose change only spawn in apartements.", "LifeAndLiving.SpawnRate.LimitLooseMoneyToApartementsOnly")]
bool LimitLooseMoneyToApartementsOnly { get; set; }
[Binding(true, "This drastically reduces sync disk upgrade modules spawns.", "LifeAndLiving.SpawnRate.LimitSpawnrateSyncDiskUpgradeModules")]
bool LimitSpawnrateSyncDiskUpgradeModules { get; set; }
[Binding(true, "This drastically reduces sync disk spawns.", "LifeAndLiving.SpawnRate.LimitSpawnrateSyncDisks")]
bool LimitSpawnrateSyncDisks { get; set; }
}
public interface IHousingBindings
{
[Binding(50, "The percentage increase of apartement cost based on the existing price", "LifeAndLiving.Housing.ApartementCostPercentage")]
int ApartementCostPercentage { get; set; }
[Binding(5000, "The minimum $ cost of an apartement, if the percentage increase does not cover this minimum it will be adjusted.", "LifeAndLiving.Housing.MinimumApartementCost")]
int MinimumApartementCost { get; set; }
[Binding(40, "The percentage increase of furniture cost based on the existing price", "LifeAndLiving.Housing.FurniteCostPercentage")]
int FurniteCostPercentage { get; set; }
[Binding(250, "The cost of a lower suite in a hotel per day.", "LifeAndLiving.Housing.CostLowerSuiteHotel")]
int CostLowerSuiteHotel { get; set; }
[Binding(500, "The cost of a higher suite in a hotel per day.", "LifeAndLiving.Housing.CostHigherSuiteHotel")]
int CostHigherSuiteHotel { get; set; }
}
public interface IDialogBindings
{
[Binding(80, "The percentage increase of things such as guest pass cost, things within dialogs.", "LifeAndLiving.Dialog.DialogCostPricePercentage")]
int DialogCostPricePercentage { get; set; }
}
public interface IMoneyBindings
{
[Binding(7, "The maximum $ of loose change in a small stack.", "LifeAndLiving.Money.MaxM1Crows")]
int MaxM1Crows { get; set; }
[Binding(14, "The maximum $ of loose change in a medium stack.", "LifeAndLiving.Money.MaxM2Crows")]
int MaxM2Crows { get; set; }
[Binding(18, "The maximum $ of loose change in a big stack.", "LifeAndLiving.Money.MaxM3Crows")]
int MaxM3Crows { get; set; }
[Binding(25, "The maximum $ of loose change in a huge stack.", "LifeAndLiving.Money.MaxM4Crows")]
int MaxM4Crows { get; set; }
}
public interface IShopsBindings
{
[Binding(5, "The amount of lockpicks the buyable kit should give", "LifeAndLiving.Shops.LockPickKitAmount")]
int LockPickKitAmount { get; set; }
[Binding(15, "The percentage of item value that is taken for selling items to general stores (default game is 50%)", "LifeAndLiving.Shops.PercentageSalePriceGeneral")]
int PercentageSalePriceGeneral { get; set; }
[Binding(40, "The percentage of item value that is taken for selling items to blackmarket (default game is 80%)", "LifeAndLiving.Shops.PercentageSalePriceBlackMarket")]
int PercentageSalePriceBlackMarket { get; set; }
[Binding(70, "The max price an item can be sold for in general stores. (diamond excluded)", "LifeAndLiving.Shops.MaxSellPriceAllItemsGeneral")]
int MaxSellPriceAllItemsGeneral { get; set; }
[Binding(200, "The max price an item can be sold for in blackmarket. (diamond excluded)", "LifeAndLiving.Shops.MaxSellPriceAllItemsBlackMarket")]
int MaxSellPriceAllItemsBlackMarket { get; set; }
}
public interface IItemPriceBindings
{
[Binding(65, "The percentage the value should increase of general items that isn't food.", "LifeAndLiving.ItemPrice.PercentageValueIncreaseGeneral")]
int PercentageValueIncreaseGeneral { get; set; }
[Binding(25, "The percentage the value should increase of edible food items.", "LifeAndLiving.ItemPrice.PercentageValueIncreaseFood")]
int PercentageValueIncreaseFood { get; set; }
[Binding(25, "The minimum value of a general item that isn't food.", "LifeAndLiving.ItemPrice.MinGeneralItemValue")]
int MinGeneralItemValue { get; set; }
[Binding(10, "The minimum value of an edible food item.", "LifeAndLiving.ItemPrice.MinFoodItemValue")]
int MinFoodItemValue { get; set; }
[Binding(300, "The minimum value of a diamond.", "LifeAndLiving.ItemPrice.MinDiamondValue")]
int MinDiamondValue { get; set; }
[Binding(1000, "The maximum value of a diamond.", "LifeAndLiving.ItemPrice.MaxDiamondValue")]
int MaxDiamondValue { get; set; }
[Binding(750, "The minimum value of a sync disk upgrade module.", "LifeAndLiving.ItemPrice.MinSyncDiskUpgradeModuleValue")]
int MinSyncDiskUpgradeModuleValue { get; set; }
[Binding(1000, "The maximum value of a sync disk upgrade module.", "LifeAndLiving.ItemPrice.MaxSyncDiskUpgradeModuleValue")]
int MaxSyncDiskUpgradeModuleValue { get; set; }
}
}