Skip to content

EA 23.76 Nightly

January 14, 2025

37 files modified. 4 new files created.

Important Changes

Possible breaking changes. Click the filename to view the chunk.

Player (1)

cs
public int GetShippingBonus(int _a) 
public int GetShippingBonus(long _a) 

PropSet (3)

cs
public void Add(Card c) 
public new void Add(Card c) 
cs
public void Remove(Card c) 
public new void Remove(Card c) 
cs
public bool Contains(Card c) 

AI_Clean

@@ -25,7 +25,7 @@ public static Point GetCleanPoint(Chara c, int r = -1, int tries = 10)

cs
			{
				continue;
			}
			if (point.HasDirt || point.cell.HasLiquid) 
			if ((point.HasDirt && !EClass._map.config.retainDecal) || point.cell.HasLiquid) 
			{
				return point;
			}

ActPlan

@@ -740,6 +740,20 @@ public void _Update(PointTarget target)

cs
									return true;
								}, t);
							}
							if (t.trait.CanName) 
							{ 
								TrySetAct("changeName", delegate
								{ 
									Dialog.InputName("dialogChangeName", t.c_refText.IsEmpty(""), delegate(bool cancel, string text) 
									{ 
										if (!cancel) 
										{ 
											t.c_refText = text; 
										} 
									}); 
									return false; 
								}, t); 
							} 
						}
					}
					if (isKey)

BaseTileSelector

@@ -168,7 +168,7 @@ public void OnUpdate()

cs
		}
		EMono.ui.hud.hint.UpdateText();
	}
	if (!hitPoint.IsValid || EMono.ui.isPointerOverUI || EMono.ui.wasActive || mode.selectType == SelectType.None || !EMono.pc.ai.ShowCursor) 
	if (!hitPoint.IsValid || EMono.ui.isPointerOverUI || EMono.ui.wasActive || mode.selectType == SelectType.None || !EMono.pc.ai.ShowCursor || (UIDragPanel.dragging && Input.GetMouseButton(0))) 
	{
		return;
	}

CardActor

@@ -226,7 +226,11 @@ public virtual void RefreshSprite()

cs
	switch (type)
	{
	case Type.Canvas:
		if (owner != null && owner.c_textureData != null && (bool)sr2) 
		if (owner == null || !sr2) 
		{ 
			break; 
		} 
		if (owner.c_textureData != null) 
		{
			sr2.sprite = owner.GetPaintSprite();
			if (owner.trait is TraitCanvas traitCanvas)

@@ -234,6 +238,10 @@ public virtual void RefreshSprite()

cs
				sr2.transform.SetLocalScale(traitCanvas.Scale, traitCanvas.Scale, 1f);
			}
		}
		else
		{ 
			sr2.sprite = null; 
		} 
		break;
	case Type.Boat:
		sr2.SetActive(owner.Cell.IsFloorWater);

CardRenderer

@@ -359,8 +359,16 @@ public SourcePref GetPref()

cs
		switch (owner.sourceCard.tiles.TryGet(owner.idSkin))
		{
		case 2319:
		case 2619: 
		case 2621: 
		case 2623: 
		case 2625: 
			return EClass.core.refs.prefs.sonwputit1;
		case 2320:
		case 2620: 
		case 2622: 
		case 2624: 
		case 2626: 
			return EClass.core.refs.prefs.snowputit2;
		}
	}

@@ -455,10 +463,6 @@ public void RemoveExtra(string id)

cs

	public override void OnLeaveScreen()
	{
		if (!isSynced) 
		{ 
			Debug.LogWarning("renderer alraedy not synced:" + owner); 
		} 
		isSynced = false;
		if (hasActor && (!owner.ExistsOnMap || !data.persistActor))
		{

CellDetail

@@ -1,5 +1,4 @@

cs
using System.Collections.Generic;
using UnityEngine; 

public class CellDetail
{

@@ -52,7 +51,6 @@ public void MoveThingToBottom(Thing t)

cs
		for (int i = 0; i < things.Count && things[i].IsInstalled; i++)
		{
			things[i].stackOrder = i;
			Debug.Log(things[i].Name + "/" + things[i].stackOrder); 
		}
	}
}

Chara

@@ -3407,7 +3407,7 @@ public void TickConditions()

cs
					AddCondition<ConBlind>(200);
				}
			}
			if (turn % (2000 * (100 + Evalue(412) * 2) / Mathf.Max(100 + Evalue(409) * 10, 100)) == 0) 
			if (turn % (200000 / Mathf.Max(100 + Evalue(409) * 10, 50)) == 0) 
			{
				ModCorruption(1);
			}

@@ -3416,7 +3416,7 @@ public void TickConditions()

cs
	if (!IsPC)
	{
		int num2 = Evalue(409);
		if (num2 > 0 && turn % 2000 * (100 + Evalue(412) * 2) / (100 + num2 * 10) == 0) 
		if (num2 > 0 && turn % (200000 / Mathf.Max(100 + num2 * 10, 50)) == 0) 
		{
			ModCorruption(1);
		}

@@ -4029,7 +4029,7 @@ public void HoldCard(Card t, int num = -1)

cs
	}
	if (t.GetRootCard() != this)
	{
		t = Pick(t.Thing, msg: false); 
		t = Pick(t.Thing, msg: false, tryStack: false); 
		if (t.GetRootCard() != this)
		{
			return;

@@ -5527,7 +5527,14 @@ public void Cuddle(Chara c, bool headpat = false)

cs
public Chara SetEnemy(Chara c = null)
{
	enemy = c;
	if (c != null) 
	if (c == null) 
	{ 
		if (ai is GoalCombat) 
		{ 
			ai.Cancel(); 
		} 
	} 
	else
	{
		calmCheckTurn = 10 + EClass.rnd(30);
	}

@@ -5638,7 +5645,7 @@ public void DoHostileAction(Card _tg, bool immediate = false)

cs
		{
			GoHostile(chara);
			chara.GoHostile(this);
			if (base.isHidden && !chara.CanSee(this) && !chara.IsDisabled && !chara.IsPCParty && !chara.IsPCPartyMinion && EClass.rnd(6) == 0) 
			if (base.isHidden && !chara.CanSee(this) && !chara.IsDisabled && !chara.IsPCParty && !chara.IsPCPartyMinion && EClass.rnd(10 + Dist(chara) * 10) == 0) 
			{
				Thing t = ThingGen.Create("49");
				ActThrow.Throw(chara, pos, t);

@@ -5673,6 +5680,10 @@ public bool FindNewEnemy()

cs
	{
		return false;
	}
	if (IsPCParty && EClass.pc.isHidden && base.isHidden) 
	{ 
		return false; 
	} 
	bool flag = enemy != null || ai is GoalCombat;
	int num = (base.PER + Evalue(210) * 2) * ((!flag) ? 1 : 2);
	bool flag2 = IsPCParty && !IsPC && EClass.game.config.tactics.dontWander;

@@ -6191,6 +6202,10 @@ public void ChangeMemberType(FactionMemberType type)

cs
public void ShowDialog()
{
	Zone_Nymelle zone_Nymelle = EClass._zone as Zone_Nymelle;
	if (conSuspend != null && IsPCParty) 
	{ 
		RemoveCondition<ConSuspend>(); 
	} 
	if (IsDeadOrSleeping)
	{
		ShowDialog("_chara", "sleep");

@@ -6436,9 +6451,9 @@ public void ClearBed(Map map = null)

cs
	{
		map = EClass._map;
	}
	foreach (Card value in map.props.installed.all.Values) 
	foreach (Card item in map.props.installed.all) 
	{
		if (value.trait is TraitBed traitBed && traitBed.IsHolder(this)) 
		if (item.trait is TraitBed traitBed && traitBed.IsHolder(this)) 
		{
			traitBed.RemoveHolder(this);
		}

@@ -6447,9 +6462,9 @@ public void ClearBed(Map map = null)

cs

	public TraitBed FindBed()
	{
		foreach (Card value in EClass._map.props.installed.all.Values) 
		foreach (Card item in EClass._map.props.installed.all) 
		{
			if (value.trait is TraitBed traitBed && traitBed.IsHolder(this)) 
			if (item.trait is TraitBed traitBed && traitBed.IsHolder(this)) 
			{
				return traitBed;
			}

@@ -6463,9 +6478,9 @@ public TraitBed TryAssignBed()

cs
	{
		return null;
	}
	foreach (Card value in EClass._map.props.installed.all.Values) 
	foreach (Card item in EClass._map.props.installed.all) 
	{
		if (value.trait is TraitBed traitBed && traitBed.CanAssign(this)) 
		if (item.trait is TraitBed traitBed && traitBed.CanAssign(this)) 
		{
			traitBed.AddHolder(this);
			Msg.Say("claimBed", this);

@@ -8688,32 +8703,45 @@ public void ModWeight(int a, bool ignoreLimit = false)

cs

	public void ModCorruption(int a)
	{
		if (a > 0 && ResistLv(962) > 0 && EClass.rnd(ResistLv(962) + 1) != 0) 
		if (a > 0) 
		{ 
			if (ResistLv(962) > 0 && EClass.rnd(ResistLv(962) + 1) != 0) 
			{ 
				return; 
			} 
			int num = Evalue(412); 
			if (num != 0) 
			{ 
				float num2 = (float)a * 100f / (float)Mathf.Max(100 + num * 2, 10); 
				a = (int)num2 + ((EClass.rndf(1f) > num2 % 1f) ? 1 : 0); 
			} 
		} 
		if (a == 0) 
		{
			return;
		}
		int num = (corruption + a) / 100 - corruption / 100; 
		for (int i = 0; i < Mathf.Abs(num); i++) 
		int num3 = (corruption + a) / 100 - corruption / 100; 
		for (int i = 0; i < Mathf.Abs(num3); i++) 
		{
			if (!MutateRandom((num > 0) ? 1 : (-1), 100, ether: true)) 
			if (!MutateRandom((num3 > 0) ? 1 : (-1), 100, ether: true)) 
			{
				break;
			}
		}
		corruption += a;
		int num2 = 0; 
		int num4 = 0; 
		foreach (Element value in elements.dict.Values)
		{
			if (value.source.category == "ether")
			{
				num2 += value.Value; 
				num4 += value.Value; 
			}
		}
		if (num2 > 0 && IsPC) 
		if (num4 > 0 && IsPC) 
		{
			Tutorial.Reserve("ether");
		}
		corruption = num2 * 100 + corruption % 100; 
		corruption = num4 * 100 + corruption % 100; 
	}

	public List<Element> ListAvailabeFeats(bool pet = false, bool showAll = false)

ConInvisibility

@@ -4,6 +4,18 @@ public class ConInvisibility : BaseBuff

cs

	public override bool ShouldRefresh => true;

	public override void OnStart() 
	{ 
		owner.isHidden = true; 
		foreach (Chara chara in EClass._map.charas) 
		{ 
			if (chara.enemy == owner && !chara.CanSeeLos(owner)) 
			{ 
				chara.SetEnemy(); 
			} 
		} 
	} 

	public override void OnRefresh()
	{
		owner.isHidden = true;

CoreDebug

@@ -905,14 +905,7 @@ public void UpdateInput()

cs
	}
	if (Input.GetKeyDown(KeyCode.F2))
	{
		Chara targetChara = EClass.scene.mouseTarget.TargetChara; 
		if (targetChara != null) 
		{ 
			EClass.pc.Pick(targetChara.MakeMilk()); 
			EClass.pc.Pick(targetChara.MakeGene()); 
			EClass.pc.Pick(targetChara.MakeBraineCell()); 
			EClass.pc.Pick(targetChara.MakeEgg(effect: true, 10)); 
		} 
		EClass.pc.ModCorruption(1); 
		return;
	}
	if (Input.GetKeyDown(KeyCode.F3))

@@ -1136,7 +1129,7 @@ public void UpdateInput()

cs
		}
		if (key)
		{
			foreach (Card item2 in EClass._map.Roaming.all.GetList<Card>()) 
			foreach (Card item2 in EClass._map.Roaming.all) 
			{
				EClass._zone.RemoveCard(item2);
			}

Game

@@ -440,6 +440,17 @@ public void OnLoad()

cs
			}
		}
	});
	if (version.IsBelow(0, 23, 76)) 
	{ 
		QuestDebt questDebt = EClass.game.quests.Get<QuestDebt>(); 
		if (questDebt != null && questDebt.stage == 6 && player.debt == 19530000) 
		{ 
			EClass.pc.AddCard(ThingGen.Create("loytel_mart")); 
			EClass.pc.AddCard(ThingGen.Create("ticket_massage")); 
			player.debt = 19500000; 
			questDebt.stage = 5; 
		} 
	} 
	if (version.IsBelow(0, 23, 72))
	{
		foreach (Chara value2 in EClass.game.cards.globalCharas.Values)

+GameContractResolver

File Created
cs
using Newtonsoft.Json.Serialization;

public class GameContractResolver : DefaultContractResolver
{
	public static readonly GameContractResolver Instance = new GameContractResolver();
}

GameDate

@@ -252,7 +252,11 @@ public void ShipGoods()

cs
	ShippingResult shippingResult = new ShippingResult();
	shippingResult.rawDate = EClass.world.date.GetRaw();
	shippingResult.uidZone = zone.uid;
	shippingResult.total = EClass.player.stats.shipMoney; 
	if (EClass.player.stats.shipMoney < 0) 
	{ 
		EClass.player.stats.shipMoney = 2147483647L; 
	} 
	shippingResult.total = (int)EClass.player.stats.shipMoney; 
	shippingResult.hearthLv = zone.branch.lv;
	shippingResult.hearthExp = zone.branch.exp;
	shippingResult.debt = EClass.player.debt;

GameIO

@@ -152,6 +152,10 @@ public static Game LoadGame(string id, string root, bool cloud)

cs
	Game.id = id;
	GameIndex gameIndex = IO.LoadFile<GameIndex>(root + "/index.txt");
	string path = root + "/game.txt";
	foreach (KeyValuePair<string, string> fallbackType in gameIndex.fallbackTypes) 
	{ 
		ModUtil.fallbackTypes[fallbackType.Key] = fallbackType.Value; 
	} 
	if (cloud)
	{
		gameIndex.cloud = true;

GameIndex

@@ -1,4 +1,5 @@

cs
using System;
using System.Collections.Generic; 
using Newtonsoft.Json;
using UnityEngine;

@@ -41,6 +42,8 @@ public class GameIndex : EClass

cs

	public bool cloud;

	public Dictionary<string, string> fallbackTypes = new Dictionary<string, string>(); 

	[JsonIgnore]
	public string path;

@@ -67,6 +70,7 @@ public GameIndex Create(Game game)

cs
		idJob = EClass.pc.job.id;
		days = EClass.player.stats.days;
		deepest = EClass.player.stats.deepest;
		fallbackTypes = ModUtil.fallbackTypes; 
		Color color = EClass.pc.pccData?.GetHairColor(applyMod: true) ?? Color.white;
		this.color = ColorUtility.ToHtmlStringRGBA(color);
	}

GameSerializationBinder

@@ -16,6 +16,11 @@ public override Type BindToType(string assemblyName, string typeName)

cs
	{
		Debug.LogError(ex.Message);
		Debug.LogError(assemblyName + "/" + typeName);
		if (ModUtil.fallbackTypes.ContainsKey(typeName)) 
		{ 
			Debug.Log(typeName + "/" + Type.GetType(ModUtil.fallbackTypes[typeName])); 
			return Type.GetType(ModUtil.fallbackTypes[typeName]); 
		} 
		if (typeName.Contains("Quest"))
		{
			return typeof(QuestDummy);

GameUpdater

@@ -121,6 +121,10 @@ public override void FixedUpdate()

cs
					cell.decal = 0;
				}
			}
			if (EClass.rnd(30) == 0 && cell.decal != 0 && !pos.IsInBounds) 
			{ 
				cell.decal = 0; 
			} 
			x++;
			if (x >= Size)
			{

GoalCombat

@@ -58,6 +58,7 @@ public override IEnumerable<Status> Run()

cs
	bool dontWander = owner.IsPCParty && !owner.IsPC && EClass.game.config.tactics.dontWander;
	while (true)
	{
		bool canSeeLos = false; 
		if (EClass.debug.logCombat)
		{
			Debug.Log("■" + owner.Name + "/" + count + "/" + lostCount);

@@ -78,15 +79,19 @@ public override IEnumerable<Status> Run()

cs
			}
		}
		tc = owner.enemy;
		if (tc != null && owner.IsPCFaction && !EClass.pc.ai.ShouldAllyAttack(tc)) 
		if (tc != null && owner.IsPCFaction) 
		{
			tc = (owner.enemy = null); 
		} 
		if (tc != null && !tc.isDead && tc.ExistsOnMap && tc.pos.IsInBounds && lostCount < (owner.IsPowerful ? 50 : 5)) 
		{ 
			lostCount = ((!owner.CanSeeLos(tc)) ? (lostCount + 1) : 0); 
			if (EClass.pc.isHidden && owner.isHidden) 
			{ 
				owner.enemy = null; 
				yield return Success(); 
			} 
			if (!EClass.pc.ai.ShouldAllyAttack(tc)) 
			{ 
				tc = (owner.enemy = null); 
			} 
		}
		else
		if (tc == null || tc.isDead || !tc.ExistsOnMap || !tc.pos.IsInBounds || lostCount >= (owner.IsPowerful ? 50 : 5)) 
		{
			tc = (owner.enemy = null);
			if (owner.IsPC && EClass.game.config.autoCombat.abortOnKill)

@@ -101,6 +106,11 @@ public override IEnumerable<Status> Run()

cs
			}
			tc = owner.enemy;
		}
		else
		{ 
			canSeeLos = owner.CanSeeLos(tc); 
			lostCount = ((!canSeeLos) ? (lostCount + 1) : 0); 
		} 
		if (owner.IsPC && tc.HasEditorTag(EditorTag.Invulnerable))
		{
			Msg.Say("abort_idle");

@@ -231,7 +241,7 @@ public override IEnumerable<Status> Run()

cs
				}
			}
		}
		if (owner.IsPC && EClass.game.config.autoCombat.bDontChase) 
		if ((owner.IsPC && EClass.game.config.autoCombat.bDontChase) || (!canSeeLos && tc.isHidden)) 
		{
			move = false;
			haltSecondMove = true;

GuildFighter

@@ -38,7 +38,7 @@ public bool CanGiveContribution(Chara c)

cs

	public bool ShowBounty(Chara c)
	{
		return false; 
		return true; 
	}

	public bool HasBounty(Chara c)

InvOwner

@@ -231,7 +231,14 @@ public bool Process(bool startTransaction = false)

cs
				{
					EClass.pc.ModCurrency(-price, IDCurrency);
				}
				ShopTransaction.current.Process(thing2, thing2.Num, sell); 
				if (sell && !thing2.IsIdentified) 
				{ 
					thing2.Identify(show: true, IDTSource.SuperiorIdentify); 
				} 
				else
				{ 
					ShopTransaction.current.Process(thing2, thing2.Num, sell); 
				} 
				Msg.Say(sell ? "sold" : "bought", thing2, Lang._currency(Mathf.Abs(price), IDCurrency));
				if (thing2.id == "statue_weird" && sell)
				{

LayerHome

@@ -251,11 +251,11 @@ public void RefreshSpots()

cs
		},
		onList = delegate
		{
			foreach (Card value in ELayer._map.Installed.all.Values) 
			foreach (Card item in ELayer._map.Installed.all) 
			{
				if (value.trait.IsSpot) 
				if (item.trait.IsSpot) 
				{
					listArea.Add(value.trait); 
					listArea.Add(item.trait); 
				}
			}
		},

LayerShippingResult

@@ -107,26 +107,26 @@ public void Refresh()

cs
	float num = (float)update / (float)maxUpdate;
	int income = result.GetIncome();
	income = (int)((float)income * num);
	int a = result.total + income; 
	long num2 = result.total + income; 
	textIncome.text = Lang._currency(income, showUnit: true);
	textIncomeTotal.text = Lang._currency(a, showUnit: true); 
	textIncomeTotal.text = Lang._currency(num2, showUnit: true); 
	int shippingBonus = ELayer.player.stats.GetShippingBonus(result.total);
	int shippingBonus2 = ELayer.player.stats.GetShippingBonus(a); 
	int shippingBonus2 = ELayer.player.stats.GetShippingBonus(num2); 
	int lastShippingExp = ELayer.player.stats.lastShippingExp;
	int lastShippingExpMax = ELayer.player.stats.lastShippingExpMax;
	int hearthLv = result.hearthLv;
	int num2 = (int)((float)result.hearthExpGained * num); 
	int num3 = (int)((float)result.hearthExpGained * num); 
	int nextExp = branch.GetNextExp(hearthLv);
	int num3 = result.hearthExp + num2; 
	int num4 = result.hearthExp + num3; 
	gaugeGold.rectTransform.sizeDelta = new Vector2(Mathf.Min(300, 300 * lastShippingExp / lastShippingExpMax), 50f);
	gaugeHearth.rectTransform.sizeDelta = new Vector2(Mathf.Min(300, 300 * num3 / nextExp), 50f); 
	gaugeHearth.rectTransform.sizeDelta = new Vector2(Mathf.Min(300, 300 * num4 / nextExp), 50f); 
	gaugeDebt.rectTransform.sizeDelta = new Vector2(Mathf.Min(300f, 300f * ((float)result.debt / 20000000f)), 50f);
	textGold.text = "shipping_nextGold".lang(lastShippingExp.ToFormat(), lastShippingExpMax.ToFormat());
	int num4 = shippingBonus2 - shippingBonus; 
	textGold2.text = ((num4 == 0) ? "" : ("+" + num4)); 
	textHearth.text = "shipping_hearth".lang(hearthLv.ToString() ?? "", (100f * (float)num3 / (float)nextExp).ToString("F1")); 
	float num5 = 100f * (float)num2 / (float)nextExp; 
	textHearth2.text = ((num5 == 0f) ? "" : ("+" + num5.ToString("F1") + "%")); 
	int num5 = shippingBonus2 - shippingBonus; 
	textGold2.text = ((num5 == 0) ? "" : ("+" + num5)); 
	textHearth.text = "shipping_hearth".lang(hearthLv.ToString() ?? "", (100f * (float)num4 / (float)nextExp).ToString("F1")); 
	float num6 = 100f * (float)num3 / (float)nextExp; 
	textHearth2.text = ((num6 == 0f) ? "" : ("+" + num6.ToString("F1") + "%")); 
	textDebt.text = (ELayer.game.quests.IsStarted<QuestDebt>() ? (Lang._currency(result.debt, showUnit: true) ?? "") : "???");
	gaugeDebt.SetActive(ELayer.game.quests.IsStarted<QuestDebt>());
	if (shippingBonus2 - shippingBonus != lastBonus)

Map

@@ -2631,7 +2631,7 @@ public Thing FindThing(string workTag, BaseArea area1 = null, BaseArea area2 = n

cs
	PropSet orCreate = EClass._map.Installed.workMap.GetOrCreate(workTag);
	if (area1 != null)
	{
		IEnumerable<Card> enumerable = orCreate.Values.Where((Card a) => a.pos.HasRoomOrArea(area1)); 
		IEnumerable<Card> enumerable = orCreate.Where((Card a) => a.pos.HasRoomOrArea(area1)); 
		if (enumerable.Count() > 0)
		{
			thing = enumerable.RandomItem() as Thing;

@@ -2639,7 +2639,7 @@ public Thing FindThing(string workTag, BaseArea area1 = null, BaseArea area2 = n

cs
	}
	if (thing == null && area2 != null)
	{
		IEnumerable<Card> enumerable2 = orCreate.Values.Where((Card a) => a.pos.HasRoomOrArea(area2)); 
		IEnumerable<Card> enumerable2 = orCreate.Where((Card a) => a.pos.HasRoomOrArea(area2)); 
		if (enumerable2.Count() > 0)
		{
			thing = enumerable2.RandomItem() as Thing;

@@ -2651,7 +2651,9 @@ public Thing FindThing(string workTag, BaseArea area1 = null, BaseArea area2 = n

cs
public Thing FindThing(string workTag, Chara c)
{
	Thing result = null;
	IEnumerable<Card> enumerable = EClass._map.Installed.workMap.GetOrCreate(workTag).Values.Where((Card a) => a.pos.IsPublicSpace()); 
	IEnumerable<Card> enumerable = from a in EClass._map.Installed.workMap.GetOrCreate(workTag) 
		where a.pos.IsPublicSpace() 
		select a; 
	if (enumerable.Count() > 0)
	{
		result = enumerable.RandomItem() as Thing;

ModManager

@@ -203,6 +203,7 @@ public IEnumerator RefreshMods(Action onComplete, bool syncMods)

cs
			}
		}
	}
	ModUtil.OnModsActivated(); 
	BaseModManager.isInitialized = true;
	yield return new WaitForEndOfFrame();
	onComplete?.Invoke();

@@ -215,6 +216,10 @@ public IEnumerator RefreshMods(Action onComplete, bool syncMods)

cs

	public void SaveLoadOrder()
	{
		if (disableMod) 
		{ 
			return; 
		} 
		List<string> list = new List<string>();
		foreach (BaseModPackage package in packages)
		{

ModUtil

@@ -1,4 +1,5 @@

cs
using System;
using System.Collections.Generic; 
using System.IO;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;

@@ -6,11 +7,23 @@

cs

public class ModUtil : EClass
{
	public static Dictionary<string, string> fallbackTypes = new Dictionary<string, string>(); 

	public static void Test()
	{
		ImportExcel("", "", EClass.sources.charas);
	}

	public static void OnModsActivated() 
	{ 
		RegisterSerializedTypeFallback("TrueArena", "ArenaWaveEvent", "ZoneEvent"); 
	} 

	public static void RegisterSerializedTypeFallback(string nameAssembly, string nameType, string nameFallbackType) 
	{ 
		fallbackTypes[nameType] = nameFallbackType; 
	} 

	public static void ImportExcel(string pathToExcelFile, string sheetName, SourceData source)
	{
		Debug.Log("ImportExcel source:" + source?.ToString() + " Path:" + pathToExcelFile);

Player

@@ -83,8 +83,6 @@ public class Stats

cs

		public int shipNum;

		public int shipMoney; 

		public int slept;

		public int death;

@@ -97,16 +95,21 @@ public class Stats

cs

		public int gambleChestOpen;

		public long shipMoney; 

		[JsonIgnore]
		public int lastShippingExp;

		[JsonIgnore]
		public int lastShippingExpMax;

		public int GetShippingBonus(int _a) 
		public int GetShippingBonus(long _a) 
		{
			int p = 0; 
			long p = 0L; 
			bool first = true;
			SetBonus(1000000000, 50000); 
			SetBonus(100000000, 20000); 
			SetBonus(10000000, 10000); 
			SetBonus(500000, 5000);
			SetBonus(250000, 3000);
			SetBonus(100000, 2000);

@@ -114,7 +117,7 @@ public int GetShippingBonus(int _a)

cs
		SetBonus(6000, 500);
		SetBonus(2000, 200);
		SetBonus(0, 100);
		return p; 
		return (int)p; 
		void SetBonus(int threshold, int div)
		{
			if (_a >= threshold)

@@ -122,7 +125,7 @@ void SetBonus(int threshold, int div)

cs
				p += (_a - threshold) / div;
				if (first)
				{
					lastShippingExp = (_a - threshold) % div; 
					lastShippingExp = (int)((_a - threshold) % div); 
					lastShippingExpMax = div;
					first = false;
				}

@@ -794,6 +797,9 @@ public void OnLeaveZone()

cs
	[JsonProperty]
	public string memo = "";

	[JsonProperty] 
	public string memo2 = ""; 

	[JsonProperty]
	public Pref pref = new Pref();

@@ -1155,7 +1161,7 @@ public void OnCreateGame()

cs
		flags.toggleHotbarHighlightDisabled = true;
		layerAbilityConfig.hideDepletedSpell = true;
		layerAbilityConfig.bgAlpha = 70;
		memo = "memo_blank".lang(); 
		memo = (memo2 = "memo_blank".lang()); 
	}

	public void OnStartNewGame()

PropSet

@@ -1,24 +1,19 @@

cs
using System.Collections.Generic;

public class PropSet : Dictionary<int, Card> 
public class PropSet : HashSet<Card> 
{
	public int num;

	public void Add(Card c) 
	public new void Add(Card c) 
	{
		ModNum(c.Num);
		Add(c.uid, c); 
		base.Add(c); 
	}

	public void Remove(Card c) 
	public new void Remove(Card c) 
	{
		ModNum(-c.Num);
		Remove(c.uid); 
	} 

	public bool Contains(Card c) 
	{ 
		return ContainsKey(c.uid); 
		base.Remove(c); 
	}

	public virtual void ModNum(int a)

Props

@@ -1,4 +1,5 @@

cs
using System.Collections.Generic;
using System.Linq; 
using Newtonsoft.Json;
using UnityEngine;

@@ -61,6 +62,14 @@ public void Init()

cs

	public void Add(Card t)
	{
		if (all.Contains(t)) 
		{ 
			Debug.Log(t.props); 
			Debug.Log(t.parent); 
			Debug.Log(things.Contains(t) + "/" + cardMap.ContainsKey(t.id)); 
			Debug.LogError(t?.ToString() + " alreadin in " + this); 
			return; 
		} 
		if (t.props != null)
		{
			t.props.Remove(t);

@@ -79,11 +88,6 @@ public void Add(Card t)

cs
			EClass._map.Stocked.Add(thing);
		}
	}
	if (all.Contains(t)) 
	{ 
		Debug.LogError(t?.ToString() + " alreadin in " + this); 
		return; 
	} 
	weight += t.Num;
	all.Add(t);
	things.Add(t.Thing);

@@ -187,11 +191,11 @@ public Thing GetAvailableThing(string id, int idMat)

cs
	{
		return null;
	}
	foreach (Card value in propSet.Values) 
	foreach (Card item in propSet) 
	{
		if (value.idMaterial == idMat) 
		if (item.idMaterial == idMat) 
		{
			return value as Thing; 
			return item as Thing; 
		}
	}
	return null;

@@ -236,12 +240,12 @@ void Find(string id)

cs
		});
		if (EClass._zone.IsPCFaction || EClass._zone is Zone_Tent || EClass.debug.enable)
		{
			foreach (Card value in cardMap.GetOrCreate(id).Values) 
			foreach (Card item3 in cardMap.GetOrCreate(id)) 
			{
				Card obj = value.parent as Card; 
				Card obj = item3.parent as Card; 
				if (obj != null && obj.c_lockLv == 0)
				{
					TryAdd(value.Thing); 
					TryAdd(item3.Thing); 
				}
			}
		}

@@ -375,10 +379,10 @@ public Thing Find(string id, string idMat)

cs

	public Thing Find(string id, int idMat = -1, int refVal = -1, bool shared = false)
	{
		Dictionary<int, Card>.ValueCollection valueCollection = cardMap.TryGetValue(id)?.Values; 
		if (valueCollection != null) 
		PropSet propSet = cardMap.TryGetValue(id); 
		if (propSet != null) 
		{
			foreach (Card item in valueCollection) 
			foreach (Card item in propSet) 
			{
				if ((!shared || item.parent is Thing { IsSharedContainer: not false }) && (idMat == -1 || item.material.id == idMat) && (refVal == -1 || item.refVal == refVal))
				{

@@ -392,11 +396,11 @@ public Thing Find(string id, int idMat = -1, int refVal = -1, bool shared = fals

cs
public int GetNum(string id, bool onlyShared = false)
{
	int num = 0;
	foreach (Card value in cardMap.GetOrCreate(id).Values) 
	foreach (Card item in cardMap.GetOrCreate(id)) 
	{
		if (!onlyShared || (value.parentThing != null && value.parentThing.IsSharedContainer)) 
		if (!onlyShared || (item.parentThing != null && item.parentThing.IsSharedContainer)) 
		{
			num += value.Num; 
			num += item.Num; 
		}
	}
	return num;

@@ -412,9 +416,9 @@ public void Validate()

cs
	foreach (KeyValuePair<string, PropSet> item in cardMap)
	{
		int num = 0;
		foreach (Card value in item.Value.Values) 
		foreach (Card item2 in item.Value) 
		{
			num += value.Num; 
			num += item2.Num; 
		}
		if (num != item.Value.num)
		{

Scene

@@ -316,7 +316,7 @@ public void Init(Mode newMode)

cs
		{
			EMono.ui.widgets.Activate("QuestTracker");
		}
		if (EMono._zone is Zone_Town && !EMono._zone.isMapSaved && !EMono.debug.enable) 
		if ((EMono._zone is Zone_Town || EMono._zone is Zone_Tent) && !EMono._zone.isMapSaved && !EMono.debug.ignoreAutoSave) 
		{
			EMono.game.Save();
		}

ShippingResult

@@ -34,12 +34,12 @@ public int income

cs
	}

	[JsonProperty]
	public int[] ints = new int[10]; 
	public long[] ints = new long[10]; 

	[JsonProperty]
	public List<Item> items = new List<Item>();

	public int total 
	public long total 
	{
		get
		{

@@ -55,7 +55,7 @@ public int rawDate

cs
{
	get
	{
		return ints[1]; 
		return (int)ints[1]; 
	}
	set
	{

@@ -67,7 +67,7 @@ public int uidZone

cs
{
	get
	{
		return ints[2]; 
		return (int)ints[2]; 
	}
	set
	{

@@ -79,7 +79,7 @@ public int hearthLv

cs
{
	get
	{
		return ints[3]; 
		return (int)ints[3]; 
	}
	set
	{

@@ -91,7 +91,7 @@ public int hearthExp

cs
{
	get
	{
		return ints[4]; 
		return (int)ints[4]; 
	}
	set
	{

@@ -103,7 +103,7 @@ public int hearthExpGained

cs
{
	get
	{
		return ints[5]; 
		return (int)ints[5]; 
	}
	set
	{

@@ -115,7 +115,7 @@ public int debt

cs
{
	get
	{
		return ints[6]; 
		return (int)ints[6]; 
	}
	set
	{

Thing

@@ -1503,10 +1503,10 @@ public override void SetRenderParam(RenderParam p)

cs
	}
	if (trait.IdSkin != 0)
	{
		int num6 = trait.IdSkin - 1; 
		int index = trait.IdSkin - 1; 
		if (sourceCard.skins.Length != 0)
		{
			p.tile += ((p.tile < 0f) ? (-sourceCard.skins[num6]) : sourceCard.skins[num6]); 
			p.tile += ((p.tile < 0f) ? (-sourceCard.skins.TryGet(index)) : sourceCard.skins.TryGet(index)); 
		}
	}
}

ThingContainer

@@ -428,12 +428,15 @@ public DestData GetDest(Thing t, bool tryStack = true)

cs
	_listContainers.Add(this);
	TrySearchContainer(owner);
	_listContainers.Sort((ThingContainer a, ThingContainer b) => (b.owner.GetWindowSaveData()?.priority ?? 0) * 10 + (b.owner.IsPC ? 1 : 0) - ((a.owner.GetWindowSaveData()?.priority ?? 0) * 10 + (a.owner.IsPC ? 1 : 0)));
	foreach (ThingContainer listContainer in _listContainers) 
	if (tryStack) 
	{
		SearchDest(listContainer, searchEmpty: false, searchStack: true); 
		if (d.IsValid) 
		foreach (ThingContainer listContainer in _listContainers) 
		{
			return d; 
			SearchDest(listContainer, searchEmpty: false, searchStack: true); 
			if (d.IsValid) 
			{ 
				return d; 
			} 
		}
	}
	foreach (ThingContainer listContainer2 in _listContainers)

TileType

@@ -336,9 +336,8 @@ public HitResult _HitTest(Point pos, Card target, bool canIgnore = true)

cs
		{
			return HitResult.Invalid;
		}
		if (IsDoor && pos.HasWallOrFence && pos.cell.blockDir == 2) 
		if (IsDoor && !pos.HasWallOrFence) 
		{
			return HitResult.Invalid; 
		}
	}
	else if (IsDoor)

TraitDrinkMilkMother

@@ -64,15 +64,23 @@ public override void OnDrink(Chara c)

cs
			c.Say("grow_adult", c);
			c.PlaySound("mutation");
			c.PlayEffect("mutation");
			string id = c.id; 
			if (!(id == "putty_snow")) 
			{ 
				if (id == "putty_snow_gold" && c.idSkin >= 1) 
				{ 
					c.idSkin = 0; 
				} 
			} 
			else if (c.idSkin >= 4) 
			{ 
				c.idSkin = (c.idSkin - 4) / 2; 
			} 
		}
		else
		{
			c.Say("grow_baby", c);
			c.PlaySound("ding_potential");
			if (c.id == "putty_snow" && c.idSkin >= 4) 
			{ 
				c.idSkin = 0; 
			} 
		}
		c.PlayEffect("buff");
		EClass.pc.ModExp(237, 100);

TraitFoodEggFertilized

@@ -64,9 +64,17 @@ public static Chara Incubate(Thing egg, Point pos, Card incubator = null)

cs
	public static void MakeBaby(Chara c, int baby)
	{
		c.SetFeat(1232, baby, msg: true);
		if (c.id == "putty_snow" && c.idSkin == 0) 
		string id = c.id; 
		if (!(id == "putty_snow")) 
		{
			c.idSkin = 4 + EClass.rnd(2); 
			if (id == "putty_snow_gold" && c.idSkin == 0) 
			{ 
				c.idSkin = 1 + EClass.rnd(2); 
			} 
		} 
		else if (c.idSkin <= 3) 
		{ 
			c.idSkin = 4 + c.idSkin * 2 + EClass.rnd(2); 
		}
	}

+TraitLightAlwaysAnime

File Created
cs
public class TraitLightAlwaysAnime : TraitLight
{
	public override bool IsAnimeOn => true;

	public override bool UseExtra => true;
}

+TraitMannequin

File Created
cs
using System.Collections.Generic;

public class TraitMannequin : TraitItem
{
	public override bool UseAltTiles => owner.things.Count > 0;

	public override bool CanUseFromInventory => false;

	public override bool CanName => true;

	public override bool CanUse(Chara c)
	{
		if (base.CanUse(c))
		{
			if (!EClass._zone.IsPCFaction)
			{
				return EClass._zone is Zone_Tent;
			}
			return true;
		}
		return false;
	}

	public override bool OnUse(Chara c)
	{
		List<Thing> list = new List<Thing>();
		foreach (BodySlot slot in EClass.pc.body.slots)
		{
			if (slot.elementId != 44 && slot.elementId != 45 && slot.thing != null && slot.thing.blessedState >= BlessedState.Normal)
			{
				list.Add(slot.thing);
			}
		}
		if (owner.things.Count == 0)
		{
			foreach (Thing item in list)
			{
				owner.AddCard(item);
			}
		}
		else
		{
			List<Thing> list2 = new List<Thing>();
			foreach (Thing thing in owner.things)
			{
				list2.Add(thing);
			}
			foreach (Thing item2 in list)
			{
				owner.AddCard(item2);
			}
			foreach (Thing item3 in list2)
			{
				EClass.pc.PickOrDrop(EClass.pc.pos, item3, msg: false);
				if (item3.GetRootCard().IsPC)
				{
					EClass.pc.body.Equip(item3, null, msg: false);
				}
			}
		}
		SE.Equip();
		return true;
	}
}

TraitRadio

@@ -5,7 +5,7 @@ public class TraitRadio : TraitItem

cs
	public List<string> ids = new List<string>
	{
		"none", "amb_fire", "amb_bbq", "amb_crowd", "amb_seagull", "amb_horror", "amb_pub", "amb_smelter", "amb_clockwork", "amb_dead",
		"amb_magic", "amb_fountain", "amb_clock", "amb_boat", "amb_waterfall"
		"amb_magic", "amb_fountain", "amb_clock", "amb_boat", "amb_waterfall", "amb_rag1", "amb_squeak1"
	};

	public override string IDActorEx => owner.GetStr(52);

WidgetMemo

@@ -5,6 +5,8 @@ public class WidgetMemo : Widget

cs
{
	public static WidgetMemo Instance;

	public int id; 

	public InputField input;

	public Window window;

@@ -23,7 +25,7 @@ public class WidgetMemo : Widget

cs

	public override void OnActivate()
	{
		input.text = EMono.player.memo; 
		input.text = ((id == 0) ? EMono.player.memo : EMono.player.memo2); 
		buttonEdit.SetOnClick(delegate
		{
			ToggleInput(!input.isFocused);

@@ -33,7 +35,7 @@ public override void OnActivate()

cs

	public override void OnDeactivate()
	{
		EMono.player.memo = input.text; 
		SaveText(); 
	}

	public void ToggleInput(bool enable)

@@ -50,7 +52,19 @@ public void ToggleInput(bool enable)

cs

	public override void OnUpdateConfig()
	{
		EMono.player.memo = input.text; 
		SaveText(); 
	} 

	public void SaveText() 
	{ 
		if (id == 0) 
		{ 
			EMono.player.memo = input.text; 
		} 
		else
		{ 
			EMono.player.memo2 = input.text; 
		} 
	}

	private void Update()

WidgetSearch

@@ -134,22 +134,22 @@ public override void Search(string s)

cs
					newCards.Add(thing2);
				}
			}
			foreach (Card value in EMono._map.props.stocked.all.Values) 
			foreach (Card item in EMono._map.props.stocked.all) 
			{
				if (!(value.parent is Thing { c_lockLv: <=0, IsContainer: not false })) 
				if (!(item.parent is Thing { c_lockLv: <=0, IsContainer: not false })) 
				{
					continue;
				}
				if (encSearch)
				{
					if (value.MatchEncSearch(s)) 
					if (item.MatchEncSearch(s)) 
					{
						newCards.Add(value); 
						newCards.Add(item); 
					}
				}
				else if (value.Name.ToLower().Contains(s) || value.sourceCard.GetSearchName(jp: false).Contains(s)) 
				else if (item.Name.ToLower().Contains(s) || item.sourceCard.GetSearchName(jp: false).Contains(s)) 
				{
					newCards.Add(value); 
					newCards.Add(item); 
				}
			}
		}

ZoneEvent

@@ -114,6 +114,10 @@ public void OnLoad(Zone _zone)

cs

	public void Kill()
	{
		if (zone == null) 
		{ 
			zone = EClass._zone; 
		} 
		zone.events.list.Remove(this);
		OnKill();
	}

+Zone_Exile

File Created
cs
public class Zone_Exile : Zone_SubTown
{
}