EA 23.92 Patch 3
February 13, 2025
22 files modified. 3 new files created.
Important Changes
Possible breaking changes. Click the filename to view the chunk.
GameIO (1)
public static List<GameIndex> GetGameList(string path, bool sortByName = false)
public static List<GameIndex> GetGameList(string path, bool sortByName = false, bool includeEmptyFolder = false)
AI_Idle
@@ -186,10 +186,14 @@ public override IEnumerable<Status> Run()
{
if (owner.IsRestrainedResident && owner.stamina.value > owner.stamina.max / 2)
{
owner.SetAI(new AI_Torture
TraitShackle traitShackle = owner.pos.FindThing<TraitShackle>();
if (traitShackle != null && traitShackle.AllowTraining)
{
shackle = owner.pos.FindThing<TraitShackle>()
});
owner.SetAI(new AI_Torture
{
shackle = traitShackle
});
}
yield return Restart();
}
if (EClass.rnd(20) == 0)
@@ -586,11 +590,15 @@ public override IEnumerable<Status> Run()
}
if (owner.IsRestrainedResident && owner.stamina.value > owner.stamina.max / 2)
{
owner.SetAI(new AI_Torture
TraitShackle traitShackle2 = owner.pos.FindThing<TraitShackle>();
if (traitShackle2 != null && traitShackle2.AllowTraining)
{
shackle = owner.pos.FindThing<TraitShackle>()
});
yield return Restart();
owner.SetAI(new AI_Torture
{
shackle = traitShackle2
});
yield return Restart();
}
}
if (!owner.IsPCFactionOrMinion && EClass.rnd(owner.isSynced ? 50 : 2000) == 0 && owner.hostility == Hostility.Neutral && EClass.pc.party.HasElement(1563) && !owner.race.tag.Contains("animal") && EClass._zone.IsTown && !EClass._zone.IsPCFaction && !owner.HasCondition<ConIncognito>())
{
AI_PlayMusic
@@ -382,7 +382,7 @@ void LevelSong(int a)
public void Evaluate(bool success)
{
if (!owner.IsPC)
if (owner == null || !owner.IsPC)
{
return;
}
AM_Adv
@@ -155,9 +155,9 @@ public bool IsPressing()
private float gearAngle;
protected bool updatePlans;
public bool updatePlans;
protected bool isMoving;
public bool isMoving;
private Vector3 lastCamPos;
ActPlan
@@ -528,12 +528,16 @@ public void _Update(PointTarget target)
}
if (c2.host != EClass.pc)
{
TraitShackle traitShackle = c2.pos.FindThing<TraitShackle>();
if (c2.IsRestrainedResident)
{
TrySetAct(new AI_PracticeDummy
if (traitShackle != null && traitShackle.AllowTraining)
{
target = c2
});
TrySetAct(new AI_PracticeDummy
{
target = c2
});
}
}
else if ((c2.IsHostile() || altAction || c2.isRestrained) && c2.IsAliveInCurrentZone)
{
@@ -834,6 +838,7 @@ void func()
{
_ = cc.held;
cc.PickHeld(msg: true);
ActionMode.AdvOrRegion.updatePlans = true;
return false;
}, cc.held, CursorSystem.Inventory, 1, isHostileAct: false, localAct: false);
}
ActRestrain
@@ -33,14 +33,17 @@ public override bool Perform()
return true;
}
SE.Change();
if (!shackle.owner.IsInstalled)
{
EClass._zone.AddCard(shackle.owner, Act.TP);
shackle.owner.SetPlaceState(PlaceState.installed);
}
shackle.Restrain(Act.TC, msg: true);
EClass._zone.AddCard(shackle.owner, Act.TP);
shackle.owner.SetPlaceState(PlaceState.installed);
if (!Act.TC.IsPCFaction)
{
EClass.player.ModKarma(-1);
}
if (Act.TC.IsPCFaction && EClass._zone.IsPCFaction)
if (Act.TC.IsPCFaction && EClass._zone.IsPCFaction && shackle.AllowTraining)
{
Act.TC.Chara?.SetAI(new AI_Torture
{
CTAG
@@ -33,5 +33,6 @@ public enum CTAG
noWish,
dish_bonus,
dish_fail,
random_color
random_color,
noRandomEnc
}
Card
@@ -3049,7 +3049,18 @@ public void RemoveThing(Thing thing)
{
if ((GetRootCard() as Chara)?.held == thing)
{
(GetRootCard() as Chara).held = null;
Chara obj = GetRootCard() as Chara;
obj.held = null;
if (obj.IsPC)
{
WidgetCurrentTool instance = WidgetCurrentTool.Instance;
if ((bool)instance && instance.selected != -1 && instance.selectedButton.card != null && instance.selectedButton.card == thing)
{
instance.selectedButton.card = null;
}
EClass.player.RefreshCurrentHotItem();
ActionMode.AdvOrRegion.updatePlans = true;
}
RecalculateFOV();
}
dirtyWeight = true;
@@ -4581,7 +4592,7 @@ public void SpawnLoot(Card origin)
}
bool flag2 = Chara.race.corpse[1].ToInt() > EClass.rnd(1500) || (Chara.IsPowerful && !IsPCFaction) || EClass.debug.godFood;
int num = 1;
if (Chara.race.IsAnimal && EClass.rnd(EClass._zone.IsPCFaction ? 3 : 5) == 0)
if (!IsMinion && Chara.race.IsAnimal && EClass.rnd(EClass._zone.IsPCFaction ? 3 : 5) == 0)
{
flag2 = true;
}
@@ -4590,7 +4601,7 @@ public void SpawnLoot(Card origin)
flag2 = true;
num = EClass.rndHalf(4 + 10 * (50 + Mathf.Max(0, (int)MathF.Sqrt(EClass.pc.Evalue(290) * 10))) / 100);
}
else if (origin != null && origin.HasElement(290))
else if (origin != null && origin.HasElement(290) && !IsMinion)
{
if (!flag2 && Chara.race.corpse[1].ToInt() > EClass.rnd(150000 / (100 + (int)Mathf.Sqrt(origin.Evalue(290)) * 5)))
{
@@ -4809,7 +4820,7 @@ bool chance(int i)
}
if (IsMinion)
{
i *= 2;
i *= 5;
}
if (EClass.rnd(i) == 0)
{
ContentHomeLog
@@ -24,7 +24,7 @@ public void RefreshLog()
{
b.text1.SetColor(a.col.ToEnum<FontColor>());
}
b.text2.text = a.date.month + "/" + a.date.day + " " + a.date.hour + ":" + a.date.min;
b.text2.text = a.date.month + "/" + a.date.day + " " + ((a.date.hour < 10) ? "0" : "") + a.date.hour + ":" + ((a.date.min < 10) ? "0" : "") + a.date.min;
}
};
uIList.Clear();
Core
@@ -406,6 +406,8 @@ private void LateUpdate()
public void OnApplicationFocus(bool focus)
{
Resources.UnloadUnusedAssets();
GC.Collect();
if (config == null)
{
return;
FactionBranch
@@ -1199,6 +1199,17 @@ public void OnClaimZone()
public void OnUnclaimZone()
{
List<Element> list = owner.ListLandFeats();
elements.SetBase(list[1].id, 0);
elements.SetBase(list[2].id, 0);
if (lv < 5)
{
return;
}
foreach (Element item in list.Where((Element a) => a.HasTag("network")).ToList())
{
EClass.pc.faction.elements.ModBase(item.id, -item.Value);
}
}
public void ValidateUpgradePolicies()
GameIO
@@ -283,7 +283,7 @@ public static void DeleteGame(string id, bool cloud, bool deleteBackup = true)
}
}
public static List<GameIndex> GetGameList(string path, bool sortByName = false)
public static List<GameIndex> GetGameList(string path, bool sortByName = false, bool includeEmptyFolder = false)
{
List<GameIndex> list = new List<GameIndex>();
DirectoryInfo directoryInfo = new DirectoryInfo(path);
@@ -303,9 +303,22 @@ public static List<GameIndex> GetGameList(string path, bool sortByName = false)
gameIndex.path = directoryInfo2.FullName;
list.Add(gameIndex);
}
catch (Exception)
catch (Exception message)
{
Debug.Log(message);
goto IL_0097;
}
continue;
}
goto IL_0097;
IL_0097:
if (includeEmptyFolder && Directory.Exists(CorePath.PathBackup + directoryInfo2.Name))
{
GameIndex gameIndex2 = new GameIndex();
gameIndex2.id = directoryInfo2.Name;
gameIndex2.path = directoryInfo2.FullName;
gameIndex2.date = (gameIndex2.real = new Date());
list.Add(gameIndex2);
}
}
if (sortByName)
GameIndex
@@ -55,6 +55,18 @@ public class GameIndex : EClass
public string FormTitle => id + ": " + zoneName + "(" + factionName + ") " + RealDate;
public bool IsCorrupted
{
get
{
if (zoneName == null)
{
return pcName == null;
}
return false;
}
}
public GameIndex Create(Game game)
{
if (game != null)
LayerLoadGame
@@ -12,6 +12,8 @@ public class LayerLoadGame : ELayer
public GameObject goNoInfo;
public GameObject goInfo2;
public GameObject goCloudWarn;
public UINote note;
@@ -108,7 +110,7 @@ public void RefreshList()
windows[0].SetCaption("saveList".lang() + (cloud ? (" " + "isCloud".lang()) : ""));
}
pathRoot = (backup ? pathBackup : (cloud ? CorePath.RootSaveCloud : CorePath.RootSave));
worlds = GameIO.GetGameList(pathRoot, backup);
worlds = GameIO.GetGameList(pathRoot, backup, !backup && !cloud);
goCloudWarn.SetActive(cloud && !backup);
goInfo.SetActive(value: false);
goNoInfo.SetActive(value: true);
@@ -151,8 +153,14 @@ public void RefreshInfo(GameIndex i)
note.AddTopic("date_real".lang(), i.RealDate);
note.AddTopic("date_game".lang(), i.GameData);
note.AddTopic("ID", i.id);
bool flag = ELayer.core.version.IsSaveCompatible(i.version);
if (!flag)
bool flag = ELayer.core.version.IsSaveCompatible(i.version) && !i.IsCorrupted;
goInfo2.SetActive(flag);
if (i.IsCorrupted)
{
note.Space();
note.AddText("corrupted_folder".lang(), FontColor.Bad);
}
else if (!flag)
{
note.Space();
note.AddText("incompatible".lang(), FontColor.Bad);
LayerUploader
@@ -19,6 +19,8 @@ public class LayerUploader : ELayer
public InputField inputPassword;
public InputField inputWelcome;
public IniData ini;
public UIText textInvalidId;
@@ -31,6 +33,8 @@ public class LayerUploader : ELayer
public UIButton buttonSave;
public UIButton toggleClearLocalCharas;
public int limitSec;
public HashSet<string> invalidIds = new HashSet<string>();
@@ -49,6 +53,20 @@ public override void OnInit()
string text = ini.GetKey("pass") ?? "password";
inputId.text = ELayer._map.custom?.id ?? "new_zone";
inputPassword.text = text;
if (ELayer._map.exportSetting == null)
{
ELayer._map.exportSetting = new MapExportSetting();
}
MapExportSetting ex = ELayer._map.exportSetting;
inputWelcome.text = ex.textWelcome.IsEmpty("");
inputWelcome.onValueChanged.AddListener(delegate(string s)
{
ex.textWelcome = s;
});
toggleClearLocalCharas.SetToggle(ex.clearLocalCharas, delegate(bool on)
{
ex.clearLocalCharas = on;
});
}
private void Update()
Map
@@ -69,6 +69,9 @@ public class Map : MapBounds, IPathfindGrid
[JsonProperty]
public Dictionary<int, PlantData> plants = new Dictionary<int, PlantData>();
[JsonProperty]
public MapExportSetting exportSetting;
public BitArray32 bits;
public Playlist plDay;
export.serializedCards.cards.Clear();
if (partial == null)
{
MapExportSetting mapExportSetting = exportSetting ?? new MapExportSetting();
foreach (Chara chara2 in charas)
{
if (export.usermap)
{
if (!chara2.trait.IsUnique && !chara2.IsPC)
if ((!mapExportSetting.clearLocalCharas || chara2.IsPCFactionOrMinion) && !chara2.trait.IsUnique && !chara2.IsPC)
{
export.serializedCards.Add(chara2);
}
+MapExportSetting
File Created
using Newtonsoft.Json;
public class MapExportSetting
{
[JsonProperty]
public bool clearLocalCharas;
[JsonProperty]
public string textWelcome;
}
MsgLog
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using Newtonsoft.Json;
public class MsgLog : EClass
@@ -36,6 +38,18 @@ public int maxLog
}
}
[OnSerializing]
private void OnSerializing(StreamingContext context)
{
foreach (int item in dict.Keys.ToList())
{
if (item >= currentLogIndex || item <= currentLogIndex - maxLog)
{
dict.Remove(item);
}
}
}
public void Add(Data data)
{
dict.Add(currentLogIndex, data);
Player
@@ -1969,13 +1969,17 @@ public void EquipTool(Thing a, bool setHotItem = true)
public void RefreshCurrentHotItem()
{
WidgetCurrentTool instance = WidgetCurrentTool.Instance;
if (!instance)
{
return;
}
if (currentHotItem != null)
{
if ((bool)instance)
{
instance.buttonHotItem.Refresh();
}
if (currentHotItem is HotItemHeld && currentHotItem.Thing != EClass.pc.held)
if (currentHotItem is HotItemHeld && (currentHotItem.Thing != EClass.pc.held || currentHotItem.Thing.GetRootCard() != EClass.pc))
{
currentHotItem = null;
}
@@ -1990,7 +1994,7 @@ public void RefreshCurrentHotItem()
}
if (currentHotItem == null)
{
if ((bool)instance && instance.selected != -1 && instance.selectedButton.card != null && instance.selectedButton.card.GetRootCard() == EClass.pc)
if ((bool)instance && instance.selected != -1 && instance.selectedButton.card != null && instance.selectedButton.card.GetRootCard() == EClass.pc && !instance.selectedButton.card.GetRootCard().isDestroyed)
{
currentHotItem = instance.selectedButton.card.trait.GetHotItem();
}
@@ -1999,6 +2003,7 @@ public void RefreshCurrentHotItem()
currentHotItem = hotItemNoItem;
}
}
Debug.Log(currentHotItem);
if (currentHotItem != lastHotItem)
{
if (lastHotItem != null)
TaskDump
@@ -272,7 +272,7 @@ public List<Thing> ListThingsToPut(Thing c)
return list;
bool ExcludeDump(Thing t)
{
if (t.isEquipped || t.c_isImportant || !t.trait.CanBeDropped || t.IsHotItem || t.trait is TraitToolBelt || t.trait is TraitAbility)
if (t.isEquipped || t.c_isImportant || t.trait.CanOnlyCarry || !t.trait.CanBeDropped || t.IsHotItem || t.trait is TraitToolBelt || t.trait is TraitAbility)
{
return true;
}
Thing
@@ -208,7 +208,7 @@ public override void OnCreate(int genLv)
{
num = EClass.rnd(2) + 1;
}
if (num > 0 && !HasTag(CTAG.godArtifact))
if (num > 0 && !HasTag(CTAG.godArtifact) && !HasTag(CTAG.noRandomEnc))
{
for (int i = 0; i < num; i++)
{
+TraitCage
File Created
using UnityEngine;
public class TraitCage : TraitShackle
{
public override Vector3 GetRestrainPos => default(Vector3);
}
+TraitCageBreeding
File Created
using UnityEngine;
public class TraitCageBreeding : TraitCage
{
public override Vector3 GetRestrainPos => default(Vector3);
public override bool AllowTraining => false;
}
TraitShackle
@@ -10,6 +10,8 @@ public class TraitShackle : Trait
public override string LangUse => "ActRestrain";
public virtual bool AllowTraining => true;
public override bool CanStackTo(Thing to)
{
return false;
Zone
@@ -1508,44 +1508,49 @@ public void AddGlobalCharasOnActivate()
{
Chara chara = c.parent as Chara;
c.currentZone = chara.currentZone;
continue;
}
c.isRestrained = false;
if (c.isDead)
{
continue;
}
if (c.global.transition != null)
else
{
Point pos = (c.IsPC ? spawnPosPC : (c.IsPCParty ? spawnPosPC.GetNearestPoint(allowBlock: false, allowChara: false, allowInstalled: true, ignoreCenter: true) : GetSpawnPos(c)));
if (c.IsPCParty && !c.IsPC)
if (c.isDead)
{
if (c.host == EClass.pc)
{
pos.Set(spawnPosPC);
}
else if (pos.Equals(spawnPosPC) || !PathManager.Instance.IsPathClear(spawnPosPC, pos, c, 5))
continue;
}
if (c.isRestrained && c.currentZone == EClass.pc.currentZone && c.pos.FindThing<TraitShackle>() == null)
{
c.isRestrained = false;
}
if (c.global.transition != null)
{
Point pos = (c.IsPC ? spawnPosPC : (c.IsPCParty ? spawnPosPC.GetNearestPoint(allowBlock: false, allowChara: false, allowInstalled: true, ignoreCenter: true) : GetSpawnPos(c)));
if (c.IsPCParty && !c.IsPC)
{
c.pos.Set(spawnPosPC);
if (!spawnPosPC.ForeachNearestPoint(delegate(Point p)
if (c.host == EClass.pc)
{
pos.Set(spawnPosPC);
}
else if (pos.Equals(spawnPosPC) || !PathManager.Instance.IsPathClear(spawnPosPC, pos, c, 5))
{
if (PathManager.Instance.IsPathClear(spawnPosPC, p, c, 10) && !p.Equals(spawnPosPC))
c.pos.Set(spawnPosPC);
if (!spawnPosPC.ForeachNearestPoint(delegate(Point p)
{
pos.Set(p);
return true;
if (PathManager.Instance.IsPathClear(spawnPosPC, p, c, 10) && !p.Equals(spawnPosPC))
{
pos.Set(p);
return true;
}
return false;
}, allowBlock: false, EClass.pc.party.members.Count >= 12, allowInstalled: true, ignoreCenter: true, EClass._zone.IsRegion ? 2 : 6))
{
pos.Set(spawnPosPC);
}
return false;
}, allowBlock: false, EClass.pc.party.members.Count >= 12, allowInstalled: true, ignoreCenter: true, EClass._zone.IsRegion ? 2 : 6))
{
pos.Set(spawnPosPC);
}
}
c.pos.Set(pos);
c.global.transition = null;
}
c.pos.Set(pos);
c.global.transition = null;
map.charas.Add(c);
map.AddCardOnActivate(c);
}
map.charas.Add(c);
map.AddCardOnActivate(c);
}
foreach (Chara item in EClass.player.listSummon)
{
@@ -2869,7 +2874,7 @@ public List<Element> ListLandFeats()
List<Element> list2 = new List<Element>();
foreach (int landFeat in landFeats)
{
list2.Add(Element.Create(landFeat));
list2.Add(Element.Create(landFeat, 1));
}
return list2;
}
Zone_User
@@ -19,4 +19,16 @@ public class Zone_User : Zone
public override int BaseElectricity => 1000;
public override bool RevealRoom => true;
public override void OnActivate()
{
base.OnActivate();
if (EClass._map.exportSetting != null && !EClass._map.exportSetting.textWelcome.IsEmpty())
{
WidgetMainText.Instance.NewLine();
Msg.SetColor("save");
Msg.SayRaw("<i>" + EClass._map.exportSetting.textWelcome + "</i>");
WidgetMainText.Instance.NewLine();
}
}
}