Skip to content

EA 23.287 Stable Patch 3

March 21, 2026

10 files modified.

Important Changes

None.

ActThrow

public static EffectIRenderer Throw(Card c, Point p, Card target, Thing t, Throw

cs
	c.Say("throw", c, t.GetName(NameStyle.Full, 1));
	c.LookAt(p);
	c.renderer.NextFrame();
	c.PlaySound("throw"); 
	if (t.id == "1177") 
	{ 
		c.PlaySound("throw_beachball"); 
	} 
	else
	{ 
		c.PlaySound("throw"); 
	} 
	EffectIRenderer result = null;
	if (c.isSynced || p.IsSync)
	{

public static EffectIRenderer Throw(Card c, Point p, Card target, Thing t, Throw

cs
				c.Talk("snow_hit");
			}
			Act.TC.Say("ball_hit");
			Act.TC.Chara?.Pick(t); 
			Act.TC.Chara?.Pick(t, msg: false); 
			c.ModExp(108, 50);
		}
		break;

BaseListPeople

public override void OnInstantiate(Chara a, ItemGeneral b)

cs
			}
		}
		AddSubButtonWork(b, a);
		Room room = a.FindRoom(); 
		TraitBed bed = a.FindBed(); 
		if (a.memberType == FactionMemberType.Default) 
		if (memberType == FactionMemberType.Default) 
		{
			b.AddSubButton(EClass.core.refs.icons.home, delegate
			Room room = a.FindRoom(); 
			TraitBed bed = a.FindBed(); 
			UIButton uIButton = b.AddSubButton(EClass.core.refs.icons.home, delegate
			{
				if (room == null)
				{

public override void OnInstantiate(Chara a, ItemGeneral b)

cs
					{
					});
				}
			}, "home").icon.SetAlpha((bed != null) ? 1f : 0.4f); 
			}, "home"); 
			uIButton.icon.SetAlpha((bed != null) ? 1f : 0.4f); 
			uIButton.SetActive(enable: true); 
		}
		else
		{ 
			b.AddSubButton(EClass.core.refs.icons.home, null, null, null, "home").SetActive(enable: false); 
		} 
	} 
	else
	{ 
		b.AddSubButton(EClass.core.refs.icons.work, null, null, null, "room").SetActive(enable: false); 
		b.AddSubButton(EClass.core.refs.icons.home, null, null, null, "home").SetActive(enable: false); 
	}
	if (ShowCharaSheet && EClass.debug.showExtra)
	{

public void AddSubButtonWork(ItemGeneral b, Chara a)

cs
			break;
		}
	}
	b.AddSubButton(EClass.core.refs.icons.work, delegate
	UIButton uIButton = b.AddSubButton(EClass.core.refs.icons.work, delegate 
	{
		if (roomWork == null)
		{

public void AddSubButtonWork(ItemGeneral b, Chara a)

cs
		}, null, delegate(UITooltip t)
		{
			WriteHobbies(t, a, roomWork);
		}, "room").icon.SetAlpha(flag ? 1f : 0.4f); 
		}, "room"); 
		uIButton.icon.SetAlpha(flag ? 1f : 0.4f); 
		uIButton.SetActive(enable: true); 
	}

	public void WriteHobbies(UITooltip t, Chara a, BaseArea roomWork)

void AddText(Hobby h, string lang, bool fix)

cs
						num = 1f;
					}
				}
				num = (float)Math.Round(num, 1); 
				t.note.AddText("NoteText_small", "・ " + "work_produce".lang(s.ToTitleCase(), num.ToString() ?? ""));
			}
			if (!h.source.elements.IsEmpty())

CoreDebug

public void UpdateInput()

cs
	}
	if (Input.GetKeyDown(KeyCode.F3))
	{
		Thing thing = EClass._map.things.First((Thing _t) => _t.id == "cloud"); 
		if (thing != null) 
		for (int i = 0; i < 10; i++) 
		{
			Debug.Log(EClass.sources.cards.map["cloud"].pref == thing.Pref); 
			Debug.Log(EClass.sources.cards.map["cloud"].pref == thing.renderer.GetPref()); 
			Thing thing = ThingGen.Create("egg_fertilized"); 
			thing.TryMakeRandomItem(40); 
			thing.SetEncLv(200); 
			EClass.pc.Pick(thing); 
		}
		foreach (Chara deadChara in EClass._map.deadCharas) 
		{ 
			Debug.Log(deadChara); 
		} 
		EClass.core.steam.CheckUpdate(); 
		EClass.player.flags.loytelMartLv++; 
		Msg.Say("loytelmart:" + EClass.player.flags.loytelMartLv); 
		Guild.Fighter.relation.rank = 20; 
		Guild.Mage.relation.rank = 20; 
		Guild.Thief.relation.rank = 20; 
		Guild.Merchant.relation.rank = 20; 
		if (EClass.Branch != null) 
		{ 
			EClass.Branch.ModExp(EClass.Branch.GetNextExp()); 
		} 
		foreach (Chara item in EClass._map.charas.ToList()) 
		{ 
			item.AddExp(item.ExpToNext); 
			item.Vomit(); 
		} 
		EClass.pc.PlayEffect("boost"); 
		EClass.pc.PlaySound("boost"); 
		EClass.pc.elements.SetBase(306, 100); 
		EClass.pc.elements.SetBase(85, 100); 
		EClass.pc.feat += 10; 
		EClass.player.totalFeat += 10; 
		return;
	}
	if (Input.GetKeyDown(KeyCode.F4))

public void UpdateInput()

cs
		if (Input.GetKey(KeyCode.F9))
		{
			EClass.scene.paused = false;
			for (int i = 0; i < advanceMin; i++) 
			for (int j = 0; j < advanceMin; j++) 
			{
				EClass.game.updater.FixedUpdate();
			}

public void UpdateInput()

cs
	{
		if (Input.GetMouseButtonDown(0))
		{
			foreach (Card item in list) 
			foreach (Card item2 in list) 
			{
				Debug.Log(item.Name + "/" + item.dir + "/" + item.flipX + "/" + item.angle); 
				Debug.Log(item2.Name + "/" + item2.dir + "/" + item2.flipX + "/" + item2.angle); 
			}
		}
		if (Input.GetMouseButtonDown(1))

public void UpdateInput()

cs
		}
		if (key)
		{
			foreach (Card item2 in EClass._map.Roaming.all) 
			foreach (Card item3 in EClass._map.Roaming.all) 
			{
				EClass._zone.RemoveCard(item2); 
				EClass._zone.RemoveCard(item3); 
			}
		}
		else if (hitPoint.detail != null)

public void UpdateInput()

cs
		{
			break;
		}
		foreach (Card item3 in hitPoint.ListCards()) 
		foreach (Card item4 in hitPoint.ListCards()) 
		{
			item3.renderer.PlayAnime(num5.ToEnum<AnimeID>()); 
			item4.renderer.PlayAnime(num5.ToEnum<AnimeID>()); 
		}
		Debug.Log(num5.ToEnum<AnimeID>());
		break;

ItemGeneral

public UIButton AddSubButton(Sprite sprite, Action action, string lang = null, A

cs
		return uIButton;
	}

	public UIButton GetSubButton(string id) 
	{ 
		return subButtons.TryGetValue(id); 
	} 
	public void SetMainText(string lang, Sprite sprite = null, bool disableMask = true)
	{
		button1.mainText.SetText(lang.lang());

ListPeople

public override string TextTab

cs
		}
	}

	public override string TextHeader => memberType switch
	{ 
		FactionMemberType.Default => "_listOf".lang("residents".lang()),  
		FactionMemberType.Livestock => "_listOf".lang("livestock".lang()),  
		FactionMemberType.Guest => "_listOf".lang("guests".lang()),  
		_ => textTab,  
	}; 
	public override bool ShowCharaSheet => true;

	public override bool ShowGoto => true;

ModManager

public override void Init(string path, string defaultPackage = "_Elona")

cs
		if (ModManagerCore.useLocalizations)
		{
			ImportSourceLocalizations(lang as string);
			ModManagerCore.generateLocalizations = false; 
		}
		ImportAllModDialogs();
	});

public void LoadLoadOrder()

cs

	public void ImportSourceLocalizations(string lang)
	{
		string text = lang + "/SourceLocalization.json"; 
		(FileInfo file, EMod package)[] filesEx = PackageIterator.GetFilesEx(text); 
		PackageIterator.RebuildAllMappings(lang); 
		SortedDictionary<string, string> sortedDictionary = new SortedDictionary<string, string>();
		Dictionary<string, SortedDictionary<string, string>> dictionary = new Dictionary<string, SortedDictionary<string, string>>();
		(FileInfo, EMod)[] array = filesEx; 
		string key; 
		string value;
		for (int i = 0; i < array.Length; i++) 
		string key; 
		foreach (string item in FileMapping.FallbackLut[lang].Append(lang).Distinct()) 
		{
			var (fileInfo, eMod) = array[i]; 
			try
			(FileInfo, EMod)[] filesEx = PackageIterator.GetFilesEx(item + "/SourceLocalization.json", useCache: false); 
			for (int i = 0; i < filesEx.Length; i++) 
			{
				SortedDictionary<string, string> sortedDictionary2 = IO.LoadFile<SortedDictionary<string, string>>(fileInfo.FullName); 
				foreach (KeyValuePair<string, string> item in sortedDictionary2) 
				var (fileInfo, eMod) = filesEx[i]; 
				try
				{
					item.Deconstruct(out key, out value); 
					string key2 = key; 
					string value2 = value; 
					sortedDictionary[key2] = value2; 
					SortedDictionary<string, string> sortedDictionary2 = IO.LoadFile<SortedDictionary<string, string>>(fileInfo.FullName); 
					foreach (KeyValuePair<string, string> item2 in sortedDictionary2) 
					{ 
						item2.Deconstruct(out value, out key); 
						string key2 = value; 
						string value2 = key; 
						sortedDictionary[key2] = value2; 
					} 
					dictionary[eMod.id] = sortedDictionary2; 
				} 
				catch (Exception arg) 
				{ 
					Debug.LogError($"#source localization failed to load {fileInfo.ShortPath()}\n{arg}"); 
				}
				dictionary[eMod.id] = sortedDictionary2; 
			} 
			catch (Exception arg) 
			{ 
				Debug.LogError($"#source localization failed to load {fileInfo.ShortPath()}\n{arg}"); 
			}
		}
		JsonSerializerSettings setting = new JsonSerializerSettings

public void ImportSourceLocalizations(string lang)

cs
		PreserveReferencesHandling = PreserveReferencesHandling.None,
		NullValueHandling = NullValueHandling.Ignore
	};
	foreach (EMod value4 in base.MappedPackages.Values) 
	foreach (BaseModPackage package in packages) 
	{
		if (!(value4 is ModPackage modPackage) || value4.builtin || !value4.activated) 
		if (!(package is ModPackage modPackage) || package.builtin || !package.activated) 
		{
			continue;
		}
		HashSet<SourceData.BaseRow> sourceRows = value4.sourceRows; 
		HashSet<SourceData.BaseRow> sourceRows = modPackage.sourceRows; 
		if (sourceRows == null || sourceRows.Count <= 0)
		{
			continue;

public void ImportSourceLocalizations(string lang)

cs
		{
			continue;
		}
		if (Lang.IsBuiltin(lang)) 
		{ 
			break; 
		} 
		try
		{
			SortedDictionary<string, string> sortedDictionary3 = dictionary.GetValueOrDefault(modPackage.id) ?? new SortedDictionary<string, string>();
			SortedDictionary<string, string> sortedDictionary4 = modPackage.ExportSourceLocalizations();
			SortedDictionary<string, string> final = new SortedDictionary<string, string>();
			foreach (KeyValuePair<string, string> item2 in sortedDictionary4) 
			foreach (KeyValuePair<string, string> item3 in sortedDictionary4) 
			{
				item2.Deconstruct(out value, out key); 
				string key3 = value; 
				string defaultValue = key; 
				item3.Deconstruct(out key, out value); 
				string key3 = key; 
				string defaultValue = value; 
				final[key3] = sortedDictionary3.GetValueOrDefault(key3, defaultValue);
			}
			if (sortedDictionary3.Count != final.Count || sortedDictionary3.Any((KeyValuePair<string, string> kv) => !final.TryGetValue(kv.Key, out var value3) || value3 != kv.Value)) 
			if (sortedDictionary3.Count != final.Count || sortedDictionary3.Any((KeyValuePair<string, string> kv) => !final.ContainsKey(kv.Key))) 
			{
				IO.SaveFile(Path.Combine(modPackage.dirInfo.FullName, "LangMod", text), final, compress: false, setting); 
				Debug.Log($"#source localization updated {text} / {modPackage}"); 
				string path = Path.Combine(modPackage.dirInfo.FullName, "LangMod/" + lang + "/SourceLocalization.json"); 
				IO.SaveFile(path, final, compress: false, setting); 
				Debug.Log($"#source localization updated {path.ShortPath()} / {modPackage}"); 
			}
		}
		catch (Exception arg2)

public void ImportAllModSourceSheets()

cs
			EClass.sources.materials
		});
		List<string> list = new List<string>();
		foreach (EMod value in base.MappedPackages.Values) 
		foreach (ModPackage item in packages.OfType<ModPackage>()) 
		{
			if (value.builtin || !value.activated) 
			if (item.builtin || !item.activated) 
			{
				continue;
			}
			foreach (FileInfo sourceSheet in value.Mapping.SourceSheets) 
			foreach (FileInfo sourceSheet in item.Mapping.SourceSheets) 
			{
				if (!sourceSheet.Name.StartsWith(".") && !sourceSheet.Name.Contains("~"))
				{
					ModUtil.sourceImporter.fileProviders[sourceSheet.FullName] = value; 
					ModUtil.sourceImporter.fileProviders[sourceSheet.FullName] = item; 
					list.Add(sourceSheet.FullName);
				}
			}

ModUtil

public static void ImportExcel(string pathToExcelFile, string sheetName, SourceD

cs

	public static ModPackage FindSourceRowPackage(SourceData.BaseRow row)
	{
		return ModManagerCore.Instance.MappedPackages.Values.FirstOrDefault((EMod p) => p.sourceRows.Contains(row)) as ModPackage; 
		return ModManagerCore.Instance.packages.OfType<ModPackage>().FirstOrDefault((ModPackage p) => p.sourceRows.Contains(row)); 
	}

	public static ModPackage GetModPackage(string modId)

SourceImporter

where c.IsDirtyOrEmpty

cs
	foreach (SourceCache sourceCache2 in array2)
	{
		string text2 = sourceCache2.SheetFile.ShortPath();
		string key; 
		if (sourceCache2.IsDirtyOrEmpty)
		{
			if (!dictionary.TryGetValue(sourceCache2, out var value3) || value3.Item2.Length == 0)

where c.IsDirtyOrEmpty

cs
			ISheet[] item = value3.Item2;
			foreach (ISheet sheet2 in item)
			{
				key = sheet2.SheetName; 
				if (key == "Element" || key == "Material") 
				if (prefetchSheetNames.Contains(sheet2.SheetName)) 
				{
					continue;
				}

where c.IsDirtyOrEmpty

cs
		}
		foreach (KeyValuePair<string, SourceData.BaseRow[]> item3 in sourceCache2.Source)
		{
			item3.Deconstruct(out key, out var value4); 
			item3.Deconstruct(out var key, out var value4); 
			string text3 = key;
			SourceData.BaseRow[] array5 = value4;
			SourceData sourceData2 = FindSourceByName(text3);

TraitGarokkHammer

public class TraitGarokkHammer : TraitItem

cs
public class TraitGarokkHammer : TraitItem
{
	public override bool CanUse(Chara c) 
	{ 
		if (base.CanUse(c)) 
		{ 
			return !owner.isNPCProperty; 
		} 
		return false; 
	} 
	public override bool OnUse(Chara c)
	{
		ActEffect.Proc(EffectId.ChangeRarity, EClass.pc, null, 100, new ActRef

TraitTicketFurniture

public int GetPrice(Thing t)

cs
		{
			num = 10;
		}
		if (t.trait is TraitGarokkHammer) 
		{ 
			num = 50; 
		} 
		num = Mathf.Max(num + EClass.player.little_dead - EClass.player.little_saved / 5, num);
	}
	return num;