Skip to content

EA 23.312 Nightly Patch 4 โ€‹

June 4, 2026

60 files modified. 17 new files created.

Important Changes โ€‹

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

ModManager (4) โ€‹

cs
public void ImportSourceLocalizations(string lang) 
cs
public void ImportAllModSourceSheets() 
cs
public void ImportAllModDialogs() 
cs
public void ImportAllModGodTalks() 

ModPackage (3) โ€‹

cs
public SortedDictionary<string, string> ExportSourceLocalizations() 
public override void GenerateCustomContentProfiles() 
cs
public void ImportSourceLocalizations(IReadOnlyDictionary<string, string> texts) 
public override void ImportSourceLocalizations(IReadOnlyDictionary<string, string> texts) 
cs
public void ClearSourceLocalizations(string lang) 
public override void ClearSourceLocalizations(string lang) 

ModUtil (7) โ€‹

cs
public static SourceImporter sourceImporter = new SourceImporter(SourceMapping); 
cs
public static void OnModsActivated() 
cs
private static void PostLoadCleanup(object context) 
cs
public static void ImportExcel(string pathToExcelFile, string sheetName, SourceData source) 
public static ModPackage FindFileProviderPackage(FileInfo file) 
cs
public static ModPackage FindSourceRowPackage(SourceData.BaseRow row) 
private static void OnReligionImporting(List<Religion> list) 
cs
public static string[] LoadBookList() 
cs
public static string[] LoadTopicFiles() 
public static void ImportModSourceSheets(string modId) 

Religion (21) โ€‹

cs
public void Init() 
public virtual void Init() 
cs
public void OnLoad() 
public virtual void OnLoad() 
cs
public void OnAdvanceDay() 
public virtual void OnAdvanceDay() 
cs
public Sprite GetSprite() 
public virtual Sprite GetSprite() 
cs
public void SetTextRelation(UIText text) 
public virtual void SetTextRelation(UIText text) 
cs
public string GetTextBenefit() 
public virtual string GetTextBenefit() 
cs
public string GetTextTemper(int _temper = -99999) 
public virtual string GetTextTemper(int _temper = -99999) 
cs
public void Revelation(string idTalk, int chance = 100) 
public virtual void Revelation(string idTalk, int chance = 100) 
cs
public void Talk(string idTalk, Card c = null, Card agent = null) 
public virtual void Talk(string idTalk, Card c = null, Card agent = null) 
cs
public string GetGodTalk(string suffix) 
public virtual string GetGodTalk(string idTalk) 
cs
public int GetOfferingValue(Thing t, int num = -1) 
public virtual int GetOfferingValue(Thing t, int num = -1) 
cs
public int GetGiftRank() 
public virtual int GetGiftRank() 
cs
public bool TryGetGift() 
public virtual bool TryGetGift() 
cs
public static Religion GetArtifactDeity(string id) 
public virtual void OnReforge(Thing t) 
cs
public bool IsValidArtifact(string id) 
public virtual bool IsValidArtifact(string id) 
cs
public static Thing Reforge(string id, Point pos = null, bool first = true) 
public virtual bool IsFaithElement(Element e) 
cs
public void JoinFaith(Chara c, ConvertType type = ConvertType.Default) 
public virtual void JoinFaith(Chara c, ConvertType type = ConvertType.Default) 
cs
public void LeaveFaith(Chara c, Religion newFaith, ConvertType type) 
public virtual void LeaveFaith(Chara c, Religion newFaith, ConvertType type) 
cs
public void Punish(Chara c) 
public virtual void Punish(Chara c) 
cs
public void PunishTakeOver(Chara c) 
public virtual void PunishTakeOver(Chara c) 
cs
public void OnChangeHour() 
public virtual void OnChangeHour() 

TraitChara (2) โ€‹

cs
public int GetAdvRank() 
public virtual int GetAdvRank() 
cs
public string GetAdvRankText() 
public virtual string GetAdvRankText() 

ACT โ€‹

public bool Perform(Chara _cc, Card _tc = null, Point _tp = null)

cs
		{
			_cc.mimicry.Kill();
		}
		return Perform(); 
		bool num = Perform(); 
		if (num) 
		{ 
			BaseModManager.PublishEvent("elin.act_performed", this); 
		} 
		return num; 
	}

	public virtual bool ValidatePerform(Chara _cc, Card _tc, Point _tp)

ActEffect โ€‹

void AddCon<T>(int rate, int power) where T : Condition

cs
		}
		CC.Say("abDraw", CC, TC);
		CC.PlaySound("draw");
		if (TC.HasCondition<ConGravity>()) 
		if (TC.HasCondition<ConGravity>() || TC.HasElement(493)) 
		{
			CC.SayNothingHappans();
			break;

public static bool Wish(string s, string name, int power, BlessedState state)

cs
				Debug.Log(_s + "/" + num + "/" + score);
				if (thing.HasTag(CTAG.godArtifact))
				{
					Religion.Reforge(thing.id); 
					EClass.game.religions.Reforge(thing.id); 
				}
				else
				{

BaseCard โ€‹

public void SetBool(int id, bool enable)

cs

	public int GetInt(int id, int? defaultInt = null)
	{
		if (mapInt.TryGetValue(id, out var value)) 
		{ 
			return value; 
		} 
		return defaultInt.GetValueOrDefault(); 
		return mapInt.GetValueOrDefault(id, defaultInt.GetValueOrDefault()); 
	}

	public void AddInt(int id, int value)

public void SetInt(int id, int value = 0)

cs
{
	if (value == 0)
	{
		if (mapInt.ContainsKey(id)) 
		{ 
			mapInt.Remove(id); 
		} 
		mapInt.Remove(id); 
	}
	else
	{

public void SetInt(int id, int value = 0)

cs

	public string GetStr(int id, string defaultStr = null)
	{
		if (mapStr.TryGetValue(id, out var value)) 
		{ 
			return value; 
		} 
		return defaultStr; 
		return mapStr.GetValueOrDefault(id, defaultStr); 
	}

	public void SetStr(int id, string value = null)
	{
		if (value.IsEmpty())
		{
			if (mapStr.ContainsKey(id)) 
			{ 
				mapStr.Remove(id); 
			} 
			mapStr.Remove(id); 
		}
		else
		{

public T GetObj<T>(int id)

cs
	{
		return default(T);
	}
	if (mapObj.TryGetValue(id, out var value) && value is T) 
	object valueOrDefault = mapObj.GetValueOrDefault(id); 
	if (valueOrDefault is T) 
	{
		return (T)value; 
		return (T)valueOrDefault; 
	}
	return default(T);
}

public void SetObj(int id, object o)

cs
	}
	if (o == null)
	{
		if (mapObj.ContainsKey(id)) 
		{ 
			mapObj.Remove(id); 
		} 
		mapObj.Remove(id); 
	}
	else
	{

public T SetObj<T>(int id, object o)

cs
	}
	if (o == null)
	{
		if (mapStr.ContainsKey(id)) 
		{ 
			mapObj.Remove(id); 
		} 
		mapObj.Remove(id); 
		return default(T);
	}
	mapObj[id] = o;

BaseStats โ€‹

public class BaseStats : EClass

cs

	public SourceStat.Row _source;

	public SourceStat.Row source => _source ?? (_source = EClass.sources.stats.map[id]); 
	public SourceStat.Row source 
	{ 
		get 
		{ 
			SourceStat.Row row = _source; 
			if (row == null) 
			{ 
				SourceStat.Row obj = EClass.sources.stats.map.TryGetValue(id) ?? EClass.sources.stats.alias["ConWet"]; 
				SourceStat.Row row2 = obj; 
				_source = obj; 
				row = row2; 
			} 
			return row; 
		} 
	} 

	public virtual Emo2 EmoIcon => Emo2.none;

Biography โ€‹

public void GenerateAppearance(Chara c)

cs
	{
		height /= 10;
	}
	if (c.source.tag.Contains("mini")) 
	if (c.source.tag.Contains("maxi")) 
	{
		height /= 10; 
		height *= 10; 
	}
	weight = height * height * (EClass.rnd(6) + 18) / 10000;
}

private int RndBio(string group)

cs

	private string StrBio(int id)
	{
		object obj; 
		if (!EClass.sources.langWord.map.ContainsKey(id)) 
		{ 
			obj = id.ToString(); 
			if (obj == null) 
			{ 
				return ""; 
			} 
		} 
		else
		if (!EClass.sources.langWord.map.TryGetValue(id, out var value)) 
		{
			obj = EClass.sources.langWord.map[id].GetText().Split(',')[0]; 
			return ""; 
		}
		return (string)obj; 
		return value.GetText().Split(',')[0]; 
	}

	public void SetGender(int g)

+CMOD โ€‹

File Created
cs
public static class CMOD
{
	public const string DramaOverride = "drama_override";

	public const string PortraitOverride = "portrait_override";

	public const string SpriteOverride = "sprite_override";

	public const string BiographyOverride = "biography_override";

	public const string MerchantOverride = "merchant_override";

	public const string PriceCalcOverride = "price_calc_override";

	public const string IsCustomContent = "custom_content";

	public const string IsCustomCwlContent = "cwl_tags_applied";

	public const string CustomContentId = "custom_content_id";

	public const string CustomContentPackage = "custom_content_package";

	public const string StayHomeZone = "StayHomeZone";
}

Card โ€‹

public bool CanInspect

cs

	public Vector3 InspectPosition => renderer.position;

	public bool GetBool(string id) 
	{ 
		return GetBool(id.GetHashCode()); 
	} 
	public void SetBool(string id, bool enable) 
	{ 
		SetBool(id.GetHashCode(), enable); 
	} 
	public int GetInt(string id, int? defaultInt = null) 
	{ 
		return GetInt(id.GetHashCode(), defaultInt); 
	} 
	public void AddInt(string id, int value) 
	{ 
		AddInt(id.GetHashCode(), value); 
	} 
	public void SetInt(string id, int value = 0) 
	{ 
		SetInt(id.GetHashCode(), value); 
	} 
	public string GetStr(string id, string defaultStr = null) 
	{ 
		return GetStr(id.GetHashCode(), defaultStr); 
	} 
	public void SetStr(string id, string value = null) 
	{ 
		SetStr(id.GetHashCode(), value); 
	} 
	public T GetObj<T>(string id) 
	{ 
		return GetObj<T>(id.GetHashCode()); 
	} 
	public void SetObj(string id, object o) 
	{ 
		SetObj(id.GetHashCode(), o); 
	} 
	public T SetObj<T>(string id, object o) 
	{ 
		return SetObj<T>(id.GetHashCode(), o); 
	} 
	public override string ToString()
	{
		return Name + "/" + pos?.ToString() + "/" + parent;

public void PurgeDuplicateArtifact(Thing af)

cs
			}
			foreach (Thing item2 in list2)
			{
				Religion artifactDeity = Religion.GetArtifactDeity(item2.id); 
				if (item2.isEquipped)
				{
					item.body.Unequip(item2);
				}
				item2.c_idDeity = artifactDeity?.id ?? null; 
				item2.c_idDeity = EClass.game.religions.GetArtifactDeity(item2.id)?.id; 
				Msg.Say("waterCurse", item2);
			}
		}

public virtual void HealHPHost(int a, HealSource origin = HealSource.None)

cs
	{
		if (Chara.parasite != null)
		{
			Chara.parasite.HealHP(a); 
			Chara.parasite.HealHP(a, origin); 
		}
		if (Chara.ride != null)
		{
			Chara.ride.HealHP(a); 
			Chara.ride.HealHP(a, origin); 
		}
	}
	HealHP(a, origin);

Cell โ€‹

public bool HasZoneStairs(bool includeLocked = true)

cs

	public override bool IsPathBlocked(IPathfindWalker walker, PathManager.MoveType moveType)
	{
		if (IsSky) 
		if (IsSky || outOfBounds) 
		{
			return true;
		}

Chara โ€‹

public override MoveResult _Move(Point newPoint, MoveType type = MoveType.Walk)

cs
		{
			flag2 = true;
		}
		if (flag2 && newPoint.Distance(pos) <= 1) 
		if (flag2 && !HasElement(493) && newPoint.Distance(pos) <= 1) 
		{
			Point randomNeighbor = pos.GetRandomNeighbor();
			if (CanMoveTo(randomNeighbor, allowDestroyPath: false))

public override MoveResult _Move(Point newPoint, MoveType type = MoveType.Walk)

cs
	if (effect != null && effect.id == 7)
	{
		CellEffect effect2 = base.Cell.effect;
		if (race.height < 500 && !race.tag.Contains("webfree") && EClass.rnd(effect2.power + 25) > EClass.rnd(base.STR + base.DEX + 1)) 
		if (race.height < 500 && !race.tag.Contains("webfree") && !HasElement(493) && EClass.rnd(effect2.power + 25) > EClass.rnd(base.STR + base.DEX + 1)) 
		{
			Say("abWeb_caught", this);
			PlaySound("web");

public override MoveResult _Move(Point newPoint, MoveType type = MoveType.Walk)

cs
	{
		DestroyPath(pos);
	}
	if (!isDead && pos.IsBlocked && EClass.rnd(2) == 0) 
	if (!isDead) 
	{
		stamina.Mod(-1); 
		if (Evalue(492) > 0 && EClass.rnd(10000 / (80 + Evalue(492) * 2)) == 0) 
		{ 
			AddExp(Mathf.Clamp((int)Mathf.Sqrt(base.ExpToNext / 100), 1, 1000)); 
		} 
		if (pos.IsBlocked && EClass.rnd(2) == 0) 
		{ 
			stamina.Mod(-1); 
		} 
	}
	hasMovedThisTurn = true;
	return MoveResult.Success;

public void SetPCCState(PCCState state)

cs

	public override Sprite GetSprite(int dir = 0)
	{
		string str = GetStr("sprite_override"); 
		if (!str.IsEmpty()) 
		{ 
			Sprite sprite = ModUtil.LoadSprite(str); 
			if ((bool)sprite) 
			{ 
				return sprite; 
			} 
		} 
		if (IsPCC)
		{
			PCC pCC = PCC.Get(pccData);

public override Sprite GetSprite(int dir = 0)

cs
	int skin = 0;
	if (spriteReplacer?.data != null)
	{
		Sprite sprite = spriteReplacer.GetSprite(dir, skin, snow); 
		if ((bool)sprite) 
		Sprite sprite2 = spriteReplacer.GetSprite(dir, skin, snow); 
		if ((bool)sprite2) 
		{
			return sprite; 
			return sprite2; 
		}
	}
	if (sourceCard.tiles.Length > 1)

public void ShowDialog()

cs
		{
			flag = false;
		}
		if (flag && File.Exists(PackageIterator.GetFiles("Dialog/Drama/" + id + ".xlsx").LastOrDefault()?.FullName ?? (CorePath.DramaData + id + ".xlsx"))) 
		{ 
			ShowDialog(id); 
		} 
		else
		string book = "_chara"; 
		if (flag) 
		{
			ShowDialog("_chara"); 
			string text = GetStr("drama_override").IsEmpty(id); 
			if (File.Exists(PackageIterator.GetFiles("Dialog/Drama/" + text + ".xlsx").LastOrDefault()?.FullName ?? (CorePath.DramaData + id + ".xlsx"))) 
			{ 
				book = text; 
			} 
		}
		ShowDialog(book); 
	}

	public LayerDrama ShowDialog(string book, string step = "main", string tag = "")

public Chara CreateReplacement()

cs

	public SourceThing.Row GetFavFood()
	{
		if (ModUtil.TryGetContent<CustomBiographyContent>("Biography/" + id, out var content)) 
		{ 
			content.RefreshCharaBio(this); 
			if (!content.favFood.IsEmpty() && EClass.sources.things.map.TryGetValue(content.favFood, out var value)) 
			{ 
				return value; 
			} 
		} 
		if (_listFavFood.Count == 0)
		{
			foreach (SourceThing.Row row in EClass.sources.things.rows)

public SourceThing.Row GetFavFood()

cs

	public SourceCategory.Row GetFavCat()
	{
		if (ModUtil.TryGetContent<CustomBiographyContent>("Biography/" + id, out var content)) 
		{ 
			content.RefreshCharaBio(this); 
			if (!content.favCategory.IsEmpty() && EClass.sources.categories.map.TryGetValue(content.favCategory, out var value) && value.gift > 0) 
			{ 
				return value; 
			} 
		} 
		SourceCategory.Row r = null;
		if (_listFavCat.Count == 0)
		{

public string GetIdPortraitCat()

cs

	public string GetIdPortrait()
	{
		string str = GetStr("portrait_override"); 
		if (!str.IsEmpty() && Portrait.allIds.Contains(str + ".png")) 
		{ 
			return str; 
		} 
		if (id == "olderyoungersister")
		{
			if (base.idSkin != 2)

public bool RequestProtection(Chara attacker, Action<Chara> action)

cs
		{
			continue;
		}
		int num = Mathf.Max(chara.Evalue(1649), (!chara.IsPC) ? ((!flag2) ? 1 : 3) : 0); 
		int num = Mathf.Max(chara.Evalue(1649), (!flag2) ? 1 : 3); 
		int num2 = Dist(chara);
		if (num2 > 25)
		{

public void RerollHobby(bool extraSlotChance = true)

cs
	else
	{
		string[] hobbies = source.hobbies;
		foreach (string key in hobbies) 
		foreach (string text in hobbies) 
		{
			AddHobby(EClass.sources.hobbies.alias[key].id); 
			if (EClass.sources.hobbies.alias.ContainsKey(text)) 
			{ 
				AddHobby(EClass.sources.hobbies.alias[text].id); 
				continue; 
			} 
			ModUtil.LogModError("source chara row '" + source.id + "' has invalid hobby '" + text + "'", source); 
		}
	}
	if (source.works.IsEmpty())

public void RerollHobby(bool extraSlotChance = true)

cs
	else
	{
		string[] hobbies = source.works;
		foreach (string key2 in hobbies) 
		foreach (string text2 in hobbies) 
		{
			AddWork(EClass.sources.hobbies.alias[key2].id); 
			if (EClass.sources.hobbies.alias.ContainsKey(text2)) 
			{ 
				AddWork(EClass.sources.hobbies.alias[text2].id); 
				continue; 
			} 
			ModUtil.LogModError("source chara row '" + source.id + "' has invalid work '" + text2 + "'", source); 
		}
	}
	GetWorkSummary().Reset();

CharaAbility โ€‹

using System.Collections.Generic;

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

public class CharaAbility : EClass

public CharaAbility(Chara _owner)

cs

	public void Refresh()
	{
		list.items.Clear(); 
		string[] actCombat = owner.source.actCombat; 
		for (int i = 0; i < actCombat.Length; i++) 
		this.list.items.Clear(); 
		List<string> list = owner.source.actCombat.ToList(); 
		bool flag = true; 
		for (int num = list.Count - 1; num >= 0; num--) 
		{ 
			string text = list[num]; 
			string text2 = text.Split('/')[0]; 
			if (text2.IsEmpty()) 
			{ 
				list.RemoveAt(num); 
				flag = false; 
			} 
			else if (!EClass.sources.elements.alias.ContainsKey(text2) || !ACT.dict.ContainsKey(text2)) 
			{ 
				if (EClass.sources.elements.fuzzyAlias.TryGetValue(text2, out var value) && ACT.dict.ContainsKey(value)) 
				{ 
					list[num] = text.Replace(text2, value); 
				} 
				else
				{ 
					list.RemoveAt(num); 
					ModUtil.LogModError("source chara row '" + owner.id + "' has invalid actCombat '" + text + "'", owner.source); 
				} 
				flag = false; 
			} 
		} 
		if (!flag) 
		{ 
			owner.source.actCombat = list.ToArray(); 
		} 
		foreach (string item in list) 
		{
			string[] array = actCombat[i].Split('/'); 
			list.items.Add(new ActList.Item
			string[] array = item.Split('/'); 
			this.list.items.Add(new ActList.Item
			{
				act = ACT.dict[ConvertID(array[0])],
				chance = ((array.Length > 1) ? array[1].ToInt() : 100),

public void Refresh()

cs
	}
	if (owner.trait.MaxRandomAbility > 0 && owner._listAbility == null)
	{
		int num = owner.trait.MaxRandomAbility + EClass.rnd(2) - list.items.Count; 
		if (num > 1) 
		int num2 = owner.trait.MaxRandomAbility + EClass.rnd(2) - this.list.items.Count; 
		if (num2 > 1) 
		{
			owner._listAbility = new List<int>();
			for (int j = 0; j < num; j++) 
			for (int i = 0; i < num2; i++) 
			{
				owner._listAbility.Add(GetRandomAbilityList().RandomItemWeighted((SourceElement.Row e) => e.chance).id);
			}

public void Refresh()

cs
	{
		return;
	}
	foreach (int item in owner._listAbility) 
	foreach (int item2 in owner._listAbility) 
	{
		string alias = EClass.sources.elements.map[Mathf.Abs(item)].alias; 
		list.items.Add(new ActList.Item
		string text3 = EClass.sources.elements.map.TryGetValue(Mathf.Abs(item2))?.alias; 
		if (!text3.IsEmpty()) 
		{
			act = ACT.dict[alias], 
			chance = 50, 
			pt = (item < 0) 
		}); 
			this.list.items.Add(new ActList.Item
			{ 
				act = ACT.dict[text3], 
				chance = 50, 
				pt = (item2 < 0) 
			}); 
		} 
	}
	string ConvertID(string s)
	{

+CharaExtension โ€‹

File Created
cs
public static class CharaExtension
{
	public static void RefreshSpriteRenderer(this Card card)
	{
		CardActor cardActor = card.renderer?.actor;
		if (!(cardActor?.sr == null))
		{
			cardActor.sr.sprite = card.GetSprite();
			if (!(cardActor.sr.sprite == null) && cardActor.mpb != null)
			{
				cardActor.mpb.SetTexture(SpriteHelper.MainTex, cardActor.sr.sprite.texture);
				cardActor.RefreshSprite();
			}
		}
	}

	public static void DestroyImmediate(this Chara chara)
	{
		chara.homeBranch?.BanishMember(chara, skipMsg: true);
		chara.SetFaction(EClass.Wilds);
		EClass.game.cards.listAdv.Remove(chara);
		chara.Destroy();
	}

	public static void SetSpriteOverride(this Chara chara, string spriteId = null)
	{
		chara.SetStr("sprite_override", spriteId);
		chara.RefreshSpriteRenderer();
	}

	public static void SetPortraitOverride(this Chara chara, string portraitId = null)
	{
		chara.SetStr("portrait_override", portraitId);
	}

	public static void SetDramaOverride(this Chara chara, string dramaId = null)
	{
		chara.SetStr("drama_override", dramaId);
	}
}

ConBuffStats โ€‹

public override string GetText()

cs
			}
			return list[1];
		}
		return base.GetText(); 
		return base.GetPhaseStr(); 
	}

	public override void PlayEffect()

ConWet โ€‹

public override void Tick()

cs
			Mod(-1);
		}
	}
	public override void OnStart() 
	{ 
		if (!EClass._zone.IsRegion && owner.HasElement(1254)) 
		{ 
			Point randomPoint = owner.pos.GetRandomPoint(2, requireLos: false, allowChara: false, allowBlocked: false, 200); 
			if (randomPoint != null && !randomPoint.Equals(BaseStats.CC.pos) && randomPoint.IsValid) 
			{ 
				Chara t = owner.Duplicate(); 
				EClass._zone.AddCard(t, randomPoint); 
				owner.Say("split", owner); 
			} 
		} 
	} 
}

Condition โ€‹

using System;

cs
using System;
using UnityEngine; 

public class Condition : BaseCondition
{

public static T Create<T>(int power = 100, Action<T> onCreate = null) where T :

cs

	public static Condition Create(string alias, int power = 100, Action<Condition> onCreate = null)
	{
		SourceStat.Row row = EClass.sources.stats.alias[alias]; 
		Condition condition = ClassCache.Create<Condition>(row.type.IsEmpty(alias), "Elin"); 
		SourceStat.Row row = EClass.sources.stats.alias.TryGetValue(alias); 
		if (row == null) 
		{ 
			row = EClass.sources.stats.alias["ConWet"]; 
			Debug.LogError("#source can't create condition from alias '" + alias + "'"); 
		} 
		string text = row.type.IsEmpty(alias); 
		Condition condition = ClassCache.Create<Condition>(text, "Elin"); 
		if (condition == null) 
		{ 
			condition = new ConWet(); 
			row = EClass.sources.stats.alias["ConWet"]; 
			ModUtil.LogModError("source condition row '" + alias + "' has invalid type '" + text + "'", row); 
		} 
		condition.power = power;
		condition.id = row.id;
		condition._source = row;

Core โ€‹

public class Core : BaseCore

cs
	[NonSerialized]
	public bool initialized;

	[NonSerialized] 
	public string[] launchArgs; 
	private bool? lastFullScreen;

	private float nextResolutionUpdate;

protected override void Awake()

cs
	{
		forceLangCode = debug.langCode.ToString();
	}
	string[] array = (Application.isEditor ? debug.command.Split(',') : Environment.GetCommandLineArgs()); 
	for (int i = 0; i < array.Length; i++) 
	launchArgs = (Application.isEditor ? debug.command.Split(',') : Environment.GetCommandLineArgs()); 
	for (int i = 0; i < launchArgs.Length; i++) 
	{
		string text = array[i]; 
		text = text.Replace("-", "").ToUpper(); 
		string text = launchArgs[i].Replace("-", "").ToUpper(); 
		launchArgs[i] = text; 
		Debug.Log("Commandline args:" + text);
		if (text.StartsWith("LANG_"))
		{

protected override void Awake()

cs
	};
	SoundManager.funcCanPlayBGM = () => !LayerDrama.haltPlaylist && !LayerDrama.keepBGM;
	FileDragAndDrop.onDrop = textures.OnDropFile;
	MOD.langs.Clear(); 
	MOD.OnAddPcc = pccs.Add;
	MOD.listTalk = new TalkDataList(); 
	MOD.tones = new ToneDataList(); 
	MOD.listMaps.Clear(); 
	MOD.listPartialMaps.Clear(); 
	MOD.ResetResources(); 
	Portrait.modPortraitBGFs = new ModItemList<Sprite>();
	Portrait.modPortraitBGs = new ModItemList<Sprite>();
	Portrait.modPortraits = new ModItemList<Sprite>();

public void Init()

cs
	Cal.Init();
	Colors.Init();
	gameSetting.Init();
	mods.InitLang(); 
	if (!Lang.isBuiltin) 
	{ 
		sources.ImportSourceTexts(); 
	} 
	PCCManager.current.Init();
	SpriteVariationManager.current.Init();
	scene.InitPass();

public void SetLang(string langCode, bool force = false)

cs
			game.Kill();
		}
		config.OnSetLang();
		mods.InitLang(); 
		if (!Lang.isBuiltin) 
		{ 
			sources.ImportSourceTexts(); 
		} 
		BaseModManager.PublishEvent("elin.source.lang_set", langCode);
	}
}

public static int[] ParseElements(string str)

cs
{
	if (string.IsNullOrEmpty(str))
	{
		return new int[0]; 
		return Array.Empty<int>(); 
	}
	string[] array = str.Replace("\n", "").Split(',');
	int[] array2 = new int[array.Length * 2];

public static int[] ParseElements(string str)

cs
	{
		string[] array3 = array[i].Split('/');
		array2[i * 2] = GetElement(array3[0]);
		array2[i * 2 + 1] = ((array3.Length == 1) ? 1 : int.Parse(array3[1])); 
		array2[i * 2 + 1] = ((!int.TryParse(array3.TryGet(1, returnNull: true), out var result)) ? 1 : result); 
	}
	return array2;
}

public static int GetElement(string id)

cs
	{
		sourceElement.Init();
	}
	if (!sourceElement.alias.TryGetValue(id ?? (id = "_void"), out var value)) 
	id = id?.Trim() ?? "_void"; 
	if (!sourceElement.alias.TryGetValue(id, out var value)) 
	{
		if (sourceElement.fuzzyAlias.TryGetValue(id, out var value2))
		{

CoreRef โ€‹

public void Init()

cs
public void RefreshBGM()
{
	dictBGM = new Dictionary<int, BGMData>();
	int num = 0; 
	foreach (BGMData bgm in bgms) 
	for (int num = bgms.Count - 1; num >= 0; num--) 
	{
		dictBGM[bgm.id] = bgm; 
		num++; 
		BGMData bGMData = bgms[num]; 
		if (!bGMData) 
		{ 
			bgms.RemoveAt(num); 
		} 
		else
		{ 
			dictBGM[bGMData.id] = bGMData; 
		} 
	}
	if (Core.Instance.debug.skipMod)
	{

+CustomBiographyContent โ€‹

File Created
cs
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;

[JsonObject(MemberSerialization.OptOut)]
public class CustomBiographyContent : CustomFileContent
{
	private const int FallbackWordKey = -100;

	private static int _lastWordKey;

	public string background;

	public int birthDay;

	public int birthMonth;

	public int birthYear;

	public string birthLocation;

	public string birthPlace;

	public string dad;

	public string mom;

	public string likeThing;

	public string likeHobby;

	public string favCategory;

	public string favFood;

	public static CustomBiographyContent CreateFromId(string biographyId, ModPackage owner = null)
	{
		var (fileInfo, eMod) = PackageIterator.GetFilesEx("Data/bio_" + biographyId + ".json").LastOrDefault();
		if (fileInfo == null)
		{
			return null;
		}
		if (owner == null)
		{
			owner = eMod as ModPackage;
		}
		return new CustomBiographyContent
		{
			ContentId = "Biography/" + biographyId,
			Owner = owner,
			File = fileInfo
		};
	}

	public override void OnSetLang(string lang)
	{
		CustomBiographyContent customBiographyContent = CreateFromId(base.ContentId.Split('/')[^1]);
		if (customBiographyContent != null)
		{
			base.File = customBiographyContent.File;
			base.LastModified = DateTime.MinValue;
		}
	}

	public void RefreshCharaBio(Chara chara)
	{
		Load();
		Biography bio = chara.bio;
		bio.birthDay = birthDay;
		bio.birthMonth = birthMonth;
		bio.birthYear = birthYear;
		Dictionary<int, LangWord.Row> langWord = EClass.sources.langWord.map;
		if (!langWord.ContainsKey(-100))
		{
			_lastWordKey = -100;
			SetTempWord("");
		}
		if (!birthPlace.IsEmpty())
		{
			bio.idHome = SetTempWord(birthPlace);
		}
		if (!birthLocation.IsEmpty())
		{
			bio.idLoc = SetTempWord(birthLocation);
		}
		if (!dad.IsEmpty())
		{
			bio.idAdvDad = -100;
			bio.idDad = SetTempWord(dad);
		}
		if (!mom.IsEmpty())
		{
			bio.idAdvMom = -100;
			bio.idMom = SetTempWord(mom);
		}
		if (!likeThing.IsEmpty() && EClass.sources.things.map.ContainsKey(likeThing))
		{
			bio.idLike = likeThing;
		}
		if (!likeHobby.IsEmpty() && Core.GetElement(likeHobby) != EClass.sources.elements.rows[0].id)
		{
			bio.idHobby = -100;
		}
		int SetTempWord(string text)
		{
			while (langWord.ContainsKey(_lastWordKey))
			{
				_lastWordKey--;
			}
			Dictionary<int, LangWord.Row> dictionary = langWord;
			int lastWordKey = _lastWordKey;
			LangWord.Row obj = new LangWord.Row
			{
				id = _lastWordKey
			};
			LangWord.Row row = obj;
			dictionary[lastWordKey] = obj;
			row.name = (row.name_JP = (row.name_L = text));
			return _lastWordKey;
		}
	}

	protected override void LoadContent()
	{
		CustomBiographyContent customBiographyContent = IO.LoadFile<CustomBiographyContent>(base.File.FullName);
		background = customBiographyContent.background;
		birthDay = customBiographyContent.birthDay;
		birthMonth = customBiographyContent.birthMonth;
		birthYear = customBiographyContent.birthYear;
		birthLocation = customBiographyContent.birthLocation;
		birthPlace = customBiographyContent.birthPlace;
		dad = customBiographyContent.dad;
		mom = customBiographyContent.mom;
		likeThing = customBiographyContent.likeThing;
		likeHobby = customBiographyContent.likeHobby;
		favCategory = customBiographyContent.favCategory;
		favFood = customBiographyContent.favFood;
	}
}

+CustomCharaContent โ€‹

File Created
cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Newtonsoft.Json;
using UnityEngine;

[JsonObject(MemberSerialization.OptOut)]
public class CustomCharaContent : CustomSourceContent
{
	public enum SpawnType
	{
		Common,
		Adventurer,
		Merchant,
		Unique
	}

	private static readonly Dictionary<string, SpawnType> _cachedSpawnTypes = new Dictionary<string, SpawnType>();

	public List<string> equipments = new List<string>();

	public Dictionary<string, int> mapInt = new Dictionary<string, int>();

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

	public SpawnType spawnType;

	public List<string> spawnZones = new List<string>();

	public List<string> stocks = new List<string>();

	public List<string> things = new List<string>();

	public override string SourceType => "SourceChara";

	public bool IsAdventurer => spawnType == SpawnType.Adventurer;

	public static CustomCharaContent CreateFromRow(SourceChara.Row r, ModPackage owner = null)
	{
		string trait = r.trait.TryGet(0, returnNull: true) ?? "Chara";
		if (owner == null)
		{
			owner = ModUtil.FindSourceRowPackage(r);
		}
		CustomCharaContent customCharaContent = new CustomCharaContent
		{
			ContentId = "Chara/" + r.id,
			SourceId = r.id,
			spawnType = GetSpawnTypeFromTrait(trait),
			Owner = owner
		};
		string[] tag = r.tag;
		for (int i = 0; i < tag.Length; i++)
		{
			var (text, text2, array) = CustomSourceContent.GetParams(tag[i]);
			switch (text)
			{
			case "addZone":
			case "addAdvZone":
				if (!text2.IsEmpty())
				{
					customCharaContent.spawnZones.Add(text2);
				}
				break;
			case "addEq":
			case "addAdvEq":
			case "addEquipment":
				if (!text2.IsEmpty())
				{
					customCharaContent.equipments.Add(text2);
				}
				break;
			case "addThing":
				if (!text2.IsEmpty())
				{
					customCharaContent.things.Add(text2);
				}
				break;
			case "addStock":
			{
				string text3 = text2.IsEmpty(r.id);
				if (!ModUtil.HasContent("MerchantStock/" + text3))
				{
					CustomMerchantStock customMerchantStock = CustomMerchantStock.CreateFromId(text3, owner);
					if (customMerchantStock == null)
					{
						break;
					}
					ModUtil.AddContent(customMerchantStock);
				}
				if (!customCharaContent.stocks.Contains(text3))
				{
					customCharaContent.stocks.Add(text3);
					customCharaContent.mapStr["merchant_override"] = string.Join('|', customCharaContent.stocks);
				}
				break;
			}
			case "addDrama":
				if (!text2.IsEmpty())
				{
					customCharaContent.mapStr["drama_override"] = text2;
				}
				break;
			case "addBio":
			case "addBiography":
			{
				string text4 = text2.IsEmpty(r.id);
				customCharaContent.mapStr["biography_override"] = text4;
				if (!ModUtil.HasContent("Biography/" + text4))
				{
					CustomBiographyContent customBiographyContent = CustomBiographyContent.CreateFromId(text4, owner);
					if (customBiographyContent != null)
					{
						ModUtil.AddContent(customBiographyContent);
					}
				}
				break;
			}
			case "addFlag":
			case "addInt":
				customCharaContent.mapInt[array[0]] = array.TryGet(1, returnNull: true)?.ToInt() ?? 1;
				break;
			case "addFlagValue":
			case "addStr":
				if (!array.TryGet(1, returnNull: true).IsEmpty())
				{
					customCharaContent.mapStr[array[0]] = array[1];
				}
				break;
			}
		}
		return customCharaContent;
	}

	public static SpawnType GetSpawnTypeFromTrait(string trait)
	{
		if (_cachedSpawnTypes.TryGetValue(trait, out var value))
		{
			return value;
		}
		Trait trait2 = ClassCache.Create<Trait>("Trait" + trait, "Elin");
		if (!(trait2 is TraitChara traitChara))
		{
			goto IL_005f;
		}
		SpawnType spawnType;
		if (traitChara.AdvType == TraitChara.Adv_Type.None)
		{
			if (!(trait2 is TraitMerchant))
			{
				if (!(trait2 is TraitUniqueChara))
				{
					goto IL_005f;
				}
				spawnType = SpawnType.Unique;
			}
			else
			{
				spawnType = SpawnType.Merchant;
			}
		}
		else
		{
			spawnType = SpawnType.Adventurer;
		}
		goto IL_0061;
		IL_0061:
		return _cachedSpawnTypes[trait] = spawnType;
		IL_005f:
		spawnType = SpawnType.Common;
		goto IL_0061;
	}

	public void OnCharaCreated(Chara chara)
	{
		if (chara.GetBool("custom_content") || chara.GetBool("cwl_tags_applied") || chara.id != base.SourceId)
		{
			return;
		}
		chara.SetBool("custom_content", enable: true);
		chara.SetStr("custom_content_id", base.ContentId);
		chara.SetStr("custom_content_package", base.Owner.id);
		string key2;
		foreach (KeyValuePair<string, string> item in mapStr)
		{
			item.Deconstruct(out var key, out key2);
			string id2 = key;
			string value = key2;
			chara.SetStr(id2, value);
		}
		foreach (KeyValuePair<string, int> item2 in mapInt)
		{
			item2.Deconstruct(out key2, out var value2);
			string id3 = key2;
			int value3 = value2;
			chara.SetInt(id3, value3);
		}
		if (things.Count > 0 || equipments.Count > 0)
		{
			chara.RemoveThings();
		}
		foreach (string[] item3 in equipments.Select((string t) => t.Split('#')))
		{
			if (!Enum.TryParse<Rarity>(item3.TryGet(1, returnNull: true), out var result))
			{
				result = Rarity.Random;
			}
			if (HasValidContentId(item3[0]))
			{
				chara.EQ_ID(item3[0], -1, result);
			}
		}
		foreach (string[] item4 in things.Select((string t) => t.Split('#')))
		{
			if (!int.TryParse(item4.TryGet(1, returnNull: true), out var result2))
			{
				result2 = 1;
			}
			if (HasValidContentId(item4[0]))
			{
				chara.AddThing(item4[0]).SetNum(result2);
			}
		}
		bool HasValidContentId(string id)
		{
			if (EClass.sources.cards.map.ContainsKey(id))
			{
				return true;
			}
			ModUtil.LogModError("source chara row '" + base.ContentId + "' has invalid addEq/addThing spec '" + id + "'", base.Owner);
			return false;
		}
	}

	public override void OnGameLoad(GameIOContext context)
	{
		if (spawnZones.Count == 0)
		{
			return;
		}
		Debug.Log($"#mod-content loading {this}");
		ILookup<string, Chara> lookup = EClass.game.cards.globalCharas.Values.ToLookup((Chara c) => c.id);
		List<Zone> list = new List<Zone>();
		foreach (string spawnZone in spawnZones)
		{
			Zone zone = ModUtil.FindZoneByFullName(spawnZone);
			if (zone != null)
			{
				list.Add(zone);
				continue;
			}
			ModUtil.LogModError("source chara row '" + base.SourceId + "' has invalid addZone spec '" + spawnZone + "'", base.Owner);
		}
		List<Chara> list2 = lookup[base.SourceId].ToList();
		int count = list2.Count;
		if (list.Count == 0 && count == 0)
		{
			ModUtil.LogModError("source chara row '" + base.SourceId + "' has invalid addZone spec", base.Owner);
			return;
		}
		int num = Math.Max(0, list.Count - count);
		int num2 = count;
		if (num2 <= 1)
		{
			if (num2 != 1)
			{
				goto IL_01d5;
			}
			if (IsAdventurer)
			{
				goto IL_017e;
			}
		}
		else if (IsAdventurer)
		{
			ModUtil.LogModError("adventurer '" + base.SourceId + "' has spawned more than once", base.Owner);
			return;
		}
		if (num == 0)
		{
			goto IL_017e;
		}
		goto IL_01d5;
		IL_017e:
		Debug.Log("#mod-content skipping existing character '" + base.SourceId + "', " + $"{count} at {string.Join('/', list2.Select((Chara c) => c.currentZone.ZoneFullName))}");
		return;
		IL_01d5:
		for (int i = 0; i < num; i++)
		{
			Zone z2 = list[i];
			Chara chara = SpawnToZone(z2);
			if (chara == null)
			{
				ModUtil.LogModError("can't spawn character '" + base.SourceId + "'", base.Owner);
				break;
			}
			if (IsAdventurer)
			{
				EClass.game.cards.listAdv.Add(chara);
				break;
			}
		}
		Chara SpawnToZone(Zone z)
		{
			Chara chara2 = CharaGen.Create(base.SourceId);
			if (chara2.id == "chicken")
			{
				return null;
			}
			chara2.SetHomeZone(z);
			chara2.MoveZone(z, ZoneTransition.EnterState.RandomVisit);
			Debug.Log("#mod-content spawned character '" + base.SourceId + "' to " + z.ZoneFullName);
			return chara2;
		}
	}

	public override string ToString()
	{
		StringBuilder stringBuilder = new StringBuilder();
		stringBuilder.AppendLine($"{base.ContentId}/{spawnType}/{base.Owner.id}");
		stringBuilder.AppendLine($" - zones({spawnZones.Count})/{string.Join(';', spawnZones)}");
		if (things.Count > 0)
		{
			stringBuilder.AppendLine($" - things({things.Count})/{string.Join(';', things)}");
		}
		if (equipments.Count > 0)
		{
			stringBuilder.AppendLine($" - equipments({equipments.Count})/{string.Join(';', equipments)}");
		}
		if (stocks.Count > 0)
		{
			stringBuilder.AppendLine(" - stocks/" + string.Join(';', stocks));
		}
		if (mapStr.Count > 0)
		{
			stringBuilder.AppendLine(" - str/" + string.Join(';', mapStr.Select((KeyValuePair<string, string> kv) => kv.Key + "=" + kv.Value)));
		}
		if (mapInt.Count > 0)
		{
			stringBuilder.AppendLine(" - int/" + string.Join(';', mapInt.Select((KeyValuePair<string, int> kv) => $"{kv.Key}={kv.Value}")));
		}
		return stringBuilder.ToString();
	}
}

+CustomContent โ€‹

File Created
cs
using Newtonsoft.Json;

public abstract class CustomContent : EClass, ICustomContent
{
	[JsonIgnore]
	public string ContentId { get; protected set; }

	[JsonIgnore]
	public EMod Owner { get; protected set; }

	public virtual void OnGameLoad(GameIOContext context)
	{
	}

	public virtual void OnGameSave(GameIOContext context)
	{
	}

	public override string ToString()
	{
		return ContentId;
	}
}

+CustomElementContent โ€‹

File Created
cs
using Newtonsoft.Json;

[JsonObject(MemberSerialization.OptOut)]
public class CustomElementContent : CustomSourceContent
{
	public bool addOnLoad;

	public override string SourceType => "SourceElement";

	public static CustomElementContent CreateFromRow(SourceElement.Row r, ModPackage owner = null)
	{
		if (owner == null)
		{
			owner = ModUtil.FindSourceRowPackage(r);
		}
		CustomElementContent customElementContent = new CustomElementContent
		{
			ContentId = "Element/" + r.alias,
			SourceId = r.alias,
			Owner = owner
		};
		string[] tag = r.tag;
		int i;
		for (i = 0; i < tag.Length; i++)
		{
			string item = CustomSourceContent.GetParams(tag[i]).action;
			if (item == "addEleOnLoad" || item == "addOnLoad")
			{
				customElementContent.addOnLoad = true;
			}
		}
		i = r.id;
		if (i > 10000 || i < 0)
		{
			switch (r.group)
			{
			case "FEAT":
			case "ABILITY":
			case "SPELL":
			{
				i = ((!(r.group == "FEAT")) ? 48 : 32);
				int num = i;
				ModUtil.AppendSpriteSheet(r.alias, num, num);
				break;
			}
			}
		}
		return customElementContent;
	}

	public override void OnGameLoad(GameIOContext context)
	{
		SourceElement.Row row = EClass.sources.elements.alias[base.SourceId];
		if (addOnLoad && !EClass.pc.HasElement(base.SourceId))
		{
			switch (row.group)
			{
			case "FEAT":
				EClass.pc.SetFeat(row.id, 1, msg: true);
				break;
			case "ABILITY":
			case "SPELL":
				EClass.pc.GainAbility(row.id);
				break;
			}
		}
	}

	public override string ToString()
	{
		return $"{base.ContentId}/addOnLoad={addOnLoad}";
	}
}

+CustomFileContent โ€‹

File Created
cs
using System;
using System.IO;
using Newtonsoft.Json;
using UnityEngine;

public abstract class CustomFileContent : CustomContent
{
	protected DateTime LastModified { get; set; } = DateTime.MinValue;


	[JsonIgnore]
	public FileInfo File { get; set; }

	public bool HasFileChanged()
	{
		File.Refresh();
		return File.LastWriteTimeUtc != LastModified;
	}

	public virtual void OnSetLang(string lang)
	{
	}

	public void Load()
	{
		if (!HasFileChanged())
		{
			return;
		}
		try
		{
			LoadContent();
		}
		catch (Exception message)
		{
			ModUtil.LogModError("exception while loading file '" + base.ContentId + "'", base.Owner);
			Debug.LogError(message);
		}
		finally
		{
			LastModified = File.LastWriteTimeUtc;
		}
	}

	protected abstract void LoadContent();
}

+CustomMaterialContent โ€‹

File Created
cs
public class CustomMaterialContent : CustomSourceContent
{
	public override string SourceType => "SourceMaterial";

	public static CustomMaterialContent CreateFromRow(SourceMaterial.Row r, ModPackage owner = null)
	{
		if (owner == null)
		{
			owner = ModUtil.FindSourceRowPackage(r);
		}
		return new CustomMaterialContent
		{
			ContentId = "Material/" + r.alias,
			SourceId = r.alias,
			Owner = owner
		};
	}
}

+CustomMerchantStock โ€‹

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

[JsonObject(MemberSerialization.OptOut)]
public class CustomMerchantStock : CustomFileContent
{
	public List<CustomThingContent> items = new List<CustomThingContent>();

	public List<Thing> Generate(Card owner)
	{
		Load();
		List<Thing> list = new List<Thing>();
		int createLv = owner?.trait?.ShopLv ?? (-1);
		foreach (CustomThingContent item2 in items)
		{
			try
			{
				Thing item = item2.Create(createLv);
				list.Add(item);
			}
			catch (Exception ex)
			{
				ModUtil.LogModError("can't create stock item '" + item2.ContentId + "'\n" + ex.Message, base.Owner);
				Debug.LogError(ex);
			}
		}
		return list;
	}

	public static CustomMerchantStock CreateFromId(string stockId, ModPackage owner)
	{
		var (fileInfo, eMod) = PackageIterator.GetFilesEx("Data/stock_" + stockId + ".json").LastOrDefault();
		if (fileInfo == null)
		{
			return null;
		}
		if (owner == null)
		{
			owner = eMod as ModPackage;
		}
		return new CustomMerchantStock
		{
			ContentId = "MerchantStock/" + stockId,
			Owner = owner,
			File = fileInfo
		};
	}

	protected override void LoadContent()
	{
		CustomMerchantStock customMerchantStock = IO.LoadFile<CustomMerchantStock>(base.File.FullName);
		items = customMerchantStock.items;
	}

	public override string ToString()
	{
		return $"{base.ContentId}/items({items.Count})";
	}
}

+CustomReligionContent โ€‹

File Created
cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Newtonsoft.Json;
using UnityEngine;

[JsonObject(MemberSerialization.OptOut)]
public class CustomReligionContent : CustomSourceContent
{
	public static Dictionary<string, ReligionCustom> managed = new Dictionary<string, ReligionCustom>();

	public List<string> artifacts = new List<string>();

	[JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
	public bool canJoin = true;

	public bool isMinorGod;

	public bool noPunish;

	public bool noPunishTakeover;

	public List<string> elements = new List<string>();

	public List<string> godAbilities = new List<string>();

	public Dictionary<string, int> offeringMtp = new Dictionary<string, int>();

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

	public override string SourceType => "SourceReligion";

	public string ChunkName => "custom_religion_" + base.SourceId;

	public static CustomReligionContent CreateFromRow(SourceReligion.Row r, ModPackage owner = null)
	{
		EClass.sources.religions.map.Remove(r.id);
		r.id = r.id.Split('#')[0];
		EClass.sources.religions.map[r.id] = r;
		if (owner == null)
		{
			owner = ModUtil.FindSourceRowPackage(r);
		}
		CustomReligionContent obj = new CustomReligionContent
		{
			ContentId = "Religion/" + r.id,
			SourceId = r.id,
			Owner = owner,
			canJoin = (!r.id.Contains("#noJoin") && !r.id.Contains("#cannot")),
			isMinorGod = r.id.Contains("#minor")
		};
		if (!Portrait.modPortraits.dict.ContainsKey("UN_" + r.id) && SpriteReplacer.dictModItems.TryGetValue(r.id, out var value))
		{
			Portrait.modPortraits.Add("UN_" + r.id, new FileInfo(value + ".png"));
		}
		obj.RegisterCustomReligion();
		return obj;
	}

	public void RegisterCustomReligion(ReligionCustom religionCustom = null)
	{
		Dictionary<string, ReligionCustom> dictionary = managed;
		string sourceId = base.SourceId;
		ReligionCustom obj = religionCustom ?? new ReligionCustom();
		ReligionCustom religionCustom2 = obj;
		dictionary[sourceId] = obj;
		religionCustom2.content = this;
	}

	public static void Init()
	{
		(FileInfo, EMod)[] filesEx = PackageIterator.GetFilesEx("Data/religion_data.json");
		for (int i = 0; i < filesEx.Length; i++)
		{
			var (fileInfo, package) = filesEx[i];
			try
			{
				foreach (var (key, customReligionContent2) in IO.LoadFile<Dictionary<string, CustomReligionContent>>(fileInfo.FullName))
				{
					if (managed.TryGetValue(key, out var value))
					{
						bool flag = customReligionContent2.canJoin;
						value.content.canJoin = flag;
						bool flag2 = customReligionContent2.isMinorGod;
						value.content.isMinorGod = flag2;
						value.content.artifacts = customReligionContent2.artifacts;
						value.content.offeringMtp = customReligionContent2.offeringMtp;
						value.content.offeringValue = customReligionContent2.offeringValue;
						value.content.godAbilities = customReligionContent2.godAbilities;
					}
				}
			}
			catch (Exception ex)
			{
				ModUtil.LogModError("exception while loading religion data '" + fileInfo.ShortPath() + "'\n" + ex.Message, package);
				Debug.LogError(ex);
			}
		}
		LoadDeprecatedCwlSpec();
		static void LoadDeprecatedCwlSpec()
		{
			foreach (SourceThing.Row row2 in EClass.sources.things.rows)
			{
				if (row2.HasTag(CTAG.godArtifact))
				{
					managed.Values.FirstOrDefault((ReligionCustom r) => row2.tag.Contains(r.id))?.content.artifacts.Add(row2.id);
				}
			}
			foreach (SourceElement.Row row in EClass.sources.elements.rows)
			{
				if (row.tag.Contains("godAbility"))
				{
					managed.Values.FirstOrDefault((ReligionCustom r) => row.tag.Contains(r.id))?.content.godAbilities.Add(row.alias);
				}
			}
			(FileInfo, EMod)[] filesEx2 = PackageIterator.GetFilesEx("Data/religion_elements.json");
			string key2;
			for (int j = 0; j < filesEx2.Length; j++)
			{
				var (fileInfo2, package2) = filesEx2[j];
				try
				{
					foreach (KeyValuePair<string, List<string>> item in IO.LoadFile<Dictionary<string, List<string>>>(fileInfo2.FullName))
					{
						item.Deconstruct(out key2, out var value2);
						string key3 = key2;
						List<string> collection = value2;
						if (managed.TryGetValue(key3, out var value3))
						{
							value3.content.elements.AddRange(collection);
						}
					}
				}
				catch (Exception ex2)
				{
					ModUtil.LogModError("exception while loading '" + fileInfo2.ShortPath() + "'\n" + ex2.Message, package2);
					Debug.LogError(ex2);
				}
			}
			filesEx2 = PackageIterator.GetFilesEx("Data/religion_offerings.json");
			for (int j = 0; j < filesEx2.Length; j++)
			{
				var (fileInfo3, package3) = filesEx2[j];
				try
				{
					foreach (KeyValuePair<string, Dictionary<string, int>> item2 in IO.LoadFile<Dictionary<string, Dictionary<string, int>>>(fileInfo3.FullName))
					{
						item2.Deconstruct(out key2, out var value4);
						string key4 = key2;
						Dictionary<string, int> other = value4;
						if (managed.TryGetValue(key4, out var value5))
						{
							value5.content.offeringMtp.Merge(other);
						}
					}
				}
				catch (Exception ex3)
				{
					ModUtil.LogModError("exception while loading '" + fileInfo3.ShortPath() + "'\n" + ex3.Message, package3);
					Debug.LogError(ex3);
				}
			}
		}
	}

	public static List<ReligionCustom> GetCustomReligions()
	{
		List<ReligionCustom> list = new List<ReligionCustom>();
		foreach (ReligionCustom value in managed.Values)
		{
			if (value.content != null && EClass.sources.religions.map.ContainsKey(value.content.SourceId))
			{
				value.relation = value.source.relation;
				list.Add(value);
				Debug.Log($"#mod-content {value.content}");
			}
		}
		return list;
	}

	internal static void LoadReligionData(GameIOContext context)
	{
		if (!context.Load<Dictionary<string, ReligionCustom>>("custom_religion_data", out var data))
		{
			return;
		}
		foreach (var (key, religionCustom2) in data)
		{
			if (EClass.game.religions.dictAll.TryGetValue(key, out var value))
			{
				Debug.Log($"#mod-content loading {religionCustom2.content}");
				value.mood = religionCustom2.mood;
				value.relation = religionCustom2.relation;
				value.giftRank = religionCustom2.giftRank;
			}
		}
	}

	internal static void SaveReligionData(GameIOContext context)
	{
		if (!context.Load<Dictionary<string, ReligionCustom>>("custom_religion_data", out var data))
		{
			data = new Dictionary<string, ReligionCustom>();
		}
		foreach (ReligionCustom item in EClass.game.religions.list.OfType<ReligionCustom>())
		{
			data[item.id] = item;
		}
		if (data.Count > 0)
		{
			context.SaveUncompressed("custom_religion_data", data);
		}
	}

	public override string ToString()
	{
		StringBuilder stringBuilder = new StringBuilder();
		stringBuilder.AppendLine($"{base.ContentId}/canJoin={canJoin}/minorGod={isMinorGod}");
		if (artifacts.Count > 0)
		{
			stringBuilder.AppendLine($" - artifacts({artifacts.Count})/{string.Join(';', artifacts)}");
		}
		if (elements.Count > 0)
		{
			stringBuilder.AppendLine($" - elements({elements.Count})/{string.Join(';', elements)}");
		}
		if (offeringMtp.Count > 0)
		{
			stringBuilder.AppendLine($" - offeringMtp({offeringMtp.Count})/{string.Join(';', offeringMtp.Select((KeyValuePair<string, int> kv) => $"{kv.Key}={kv.Value}"))}");
		}
		if (offeringValue.Count > 0)
		{
			stringBuilder.AppendLine(string.Format(" - offeringValue({0})/{1}", offeringValue.Count, string.Join(';', offeringValue.Select((KeyValuePair<string, string> kv) => kv.Key + "=" + kv.Value))));
		}
		if (godAbilities.Count > 0)
		{
			stringBuilder.AppendLine($" - godAbilities({godAbilities.Count})/{string.Join(';', godAbilities)}");
		}
		return stringBuilder.ToString();
	}
}

+CustomSourceContent โ€‹

File Created
cs
using System;
using Newtonsoft.Json;

public abstract class CustomSourceContent : CustomContent
{
	[JsonIgnore]
	public virtual string SourceType { get; }

	[JsonIgnore]
	public string SourceId { get; set; }

	public static (string action, string spec, string[] kv) GetParams(string tag)
	{
		if (tag.IsEmpty())
		{
			return (action: string.Empty, spec: string.Empty, kv: Array.Empty<string>());
		}
		int num = tag.IndexOf('(');
		string text;
		string text2;
		if (num >= 0)
		{
			text = tag[..num];
			text2 = tag.ExtractInBetween('(', ')');
		}
		else
		{
			text = tag.Split('_')[0];
			text2 = tag[text.Length..].TrimStart('_');
		}
		string[] item = text2.Split('=');
		return (action: text, spec: text2, kv: item);
	}
}

+CustomStatContent โ€‹

File Created
cs
using Newtonsoft.Json;

[JsonObject(MemberSerialization.OptOut)]
public class CustomStatContent : CustomSourceContent
{
	public bool addOnLoad;

	public override string SourceType => "SourceStat";

	public static CustomStatContent CreateFromRow(SourceStat.Row r, ModPackage owner = null)
	{
		if (owner == null)
		{
			owner = ModUtil.FindSourceRowPackage(r);
		}
		CustomStatContent result = new CustomStatContent
		{
			ContentId = "Stat/" + r.alias,
			SourceId = r.alias,
			Owner = owner
		};
		ModUtil.AppendSpriteSheet(r.alias, 32, 32);
		return result;
	}
}

+CustomThingContent โ€‹

File Created
cs
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using UnityEngine;

[JsonObject(MemberSerialization.OptOut)]
public class CustomThingContent : CustomSourceContent
{
	public enum SpawnType
	{
		Item,
		Block,
		Cassette,
		Currency,
		Category,
		Filter,
		Tag,
		Letter,
		Map,
		Perfume,
		Plan,
		Potion,
		Recipe,
		RedBook,
		Rod,
		Rune,
		RuneFree,
		Scroll,
		Skill,
		Spell,
		Usuihon
	}

	[JsonConverter(typeof(StringEnumConverter))]
	public BlessedState blessedState;

	public string id = "";

	[JsonConverter(typeof(StringEnumConverter))]
	public IDTLevel identifyLevel;

	public int lv = -1;

	public Dictionary<string, int> mapInt = new Dictionary<string, int>();

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

	public string material = "";

	public bool noCopy;

	public bool noRandomSocket;

	public int num = 1;

	[JsonConverter(typeof(StringEnumConverter))]
	public Rarity rarity;

	[JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
	public bool restock = true;

	public List<string> sockets = new List<string>();

	[JsonConverter(typeof(StringEnumConverter))]
	public SpawnType type;

	public string priceCalc = "";

	public override string SourceType => "SourceThing";

	public static CustomThingContent CreateFromRow(SourceThing.Row r, ModPackage mod = null)
	{
		CustomThingContent customThingContent = new CustomThingContent
		{
			ContentId = "Thing/" + r.id,
			SourceId = r.id,
			Owner = mod,
			id = r.id
		};
		string[] tag = r.tag;
		for (int i = 0; i < tag.Length; i++)
		{
			var (text, item, array) = CustomSourceContent.GetParams(tag[i]);
			switch (text)
			{
			case "forceRarity":
				customThingContent.rarity = r.quality.ToEnum<Rarity>();
				break;
			case "noCopy":
				if (r.elements.Contains(759))
				{
					customThingContent.noCopy = true;
				}
				break;
			case "noRandomSocket":
				customThingContent.noRandomSocket = true;
				break;
			case "noRestock":
				customThingContent.restock = false;
				break;
			case "addSocket":
				customThingContent.sockets.Add(item);
				break;
			case "addFlag":
			case "addInt":
				customThingContent.mapInt[array[0]] = array.TryGet(1, returnNull: true)?.ToInt() ?? 1;
				break;
			case "addFlagValue":
			case "addStr":
				if (!array.TryGet(1, returnNull: true).IsEmpty())
				{
					customThingContent.mapStr[array[0]] = array[1];
				}
				break;
			}
		}
		return customThingContent;
	}

	public void OnThingCreated(Thing thing)
	{
		if (thing.GetBool("custom_content") || thing.id != base.SourceId)
		{
			return;
		}
		thing.SetBool("custom_content", enable: true);
		thing.SetStr("custom_content_id", base.ContentId);
		thing.SetStr("custom_content_package", base.Owner.id);
		string key2;
		foreach (KeyValuePair<string, string> item in mapStr)
		{
			item.Deconstruct(out var key, out key2);
			string text = key;
			string value = key2;
			thing.SetStr(text, value);
		}
		foreach (KeyValuePair<string, int> item2 in mapInt)
		{
			item2.Deconstruct(out key2, out var value2);
			string text2 = key2;
			int value3 = value2;
			thing.SetInt(text2, value3);
		}
		thing.ChangeRarity(rarity);
		if (noCopy)
		{
			EClass.core.actionsNextFrame.Add(delegate
			{
				thing.elements?.SetBase(759, 10);
			});
		}
		if (sockets.Count <= 0)
		{
			return;
		}
		if (noRandomSocket)
		{
			thing.sockets.Clear();
		}
		int num = 0;
		foreach (string socket in sockets)
		{
			thing.AddSocket();
			if (socket.IsEmpty())
			{
				num++;
			}
			else
			{
				ApplyRangedSocket(socket);
			}
		}
		thing.sockets.RemoveAll((int s) => s == 0);
		for (int i = 0; i < num; i++)
		{
			thing.sockets.Add(0);
		}
		void ApplyRangedSocket(string socket)
		{
			int num2 = 3 + Mathf.Min(thing.genLv / 10, 15);
			if (!EClass.sources.elements.alias.TryGetValue(socket, out var value4))
			{
				ModUtil.LogModError("source thing row '" + base.ContentId + "' has invalid addSocket spec '" + socket + "'", base.Owner);
			}
			else
			{
				float num3 = Mathf.Sqrt((float)(thing.genLv * value4.encFactor) / 100f);
				float num4 = (float)num2 + num3;
				int num5 = (value4.mtp + EClass.rnd(value4.mtp + (int)num4)) / value4.mtp;
				if (value4.encFactor == 0 && num5 > 25)
				{
					num5 = 25;
				}
				thing.ApplySocket(value4.id, num5);
			}
		}
	}

	public Thing Create(int createLv = -1)
	{
		if (lv != -1)
		{
			createLv = lv;
		}
		CardBlueprint.SetRarity(rarity);
		int.TryParse(id, out var result);
		if (EClass.sources.elements.fuzzyAlias.TryGetValue(id, out var value))
		{
			result = EClass.sources.elements.alias[value].id;
		}
		Thing thing = null;
		int idMat = EClass.sources.materials.alias.TryGetValue(material)?.id ?? (-1);
		switch (type)
		{
		case SpawnType.Item:
			thing = ThingGen.Create(id, idMat, createLv).SetNum(num);
			break;
		case SpawnType.Block:
		{
			SourceBlock.Row row = EClass.sources.blocks.alias.TryGetValue(id);
			if (row != null)
			{
				thing = ThingGen.CreateBlock(row.id, idMat).SetNum(num);
			}
			break;
		}
		case SpawnType.Cassette:
			if (!EClass.core.refs.dictBGM.ContainsKey(result))
			{
				result = EClass.core.refs.dictBGM.RandomItem().id;
			}
			thing = ThingGen.CreateCassette(result);
			break;
		case SpawnType.Currency:
			thing = ThingGen.CreateCurrency(num, id);
			break;
		case SpawnType.Category:
			thing = ThingGen.CreateFromCategory(id, createLv).SetNum(num);
			break;
		case SpawnType.Filter:
			thing = ThingGen.CreateFromFilter(id, createLv).SetNum(num);
			break;
		case SpawnType.Tag:
			thing = ThingGen.CreateFromTag(id, createLv).SetNum(num);
			break;
		case SpawnType.Letter:
			thing = ThingGen.CreateLetter(id);
			break;
		case SpawnType.Map:
			thing = ThingGen.CreateMap(id, createLv);
			break;
		case SpawnType.Perfume:
			thing = ThingGen.CreatePerfume(result, createLv).SetNum(num);
			break;
		case SpawnType.Plan:
			thing = ThingGen.CreatePlan(result);
			break;
		case SpawnType.Potion:
			thing = ThingGen.CreatePotion(result, num);
			break;
		case SpawnType.Recipe:
			thing = ThingGen.CreateRecipe(id);
			break;
		case SpawnType.RedBook:
			thing = ThingGen.CreateRedBook(id);
			break;
		case SpawnType.Rod:
			thing = ThingGen.CreateRod(result, num);
			break;
		case SpawnType.Rune:
			thing = ThingGen.CreateRune(result, num);
			break;
		case SpawnType.RuneFree:
			thing = ThingGen.CreateRune(result, num, free: true);
			break;
		case SpawnType.Scroll:
			thing = ThingGen.CreateScroll(result, num);
			break;
		case SpawnType.Skill:
			thing = ThingGen.CreateSkillbook(result, num);
			break;
		case SpawnType.Spell:
			thing = ThingGen.CreateSpellbook(result, 1, num);
			break;
		case SpawnType.Usuihon:
			thing = ThingGen.Create("1084");
			thing.c_idRefName = EClass.game.religions.dictAll.TryGetValue(id)?.id;
			break;
		default:
			thing = ThingGen.Create(id);
			break;
		}
		if (thing == null)
		{
			return null;
		}
		thing.c_IDTState = (int)identifyLevel;
		thing.SetBlessedState(blessedState);
		if (!restock)
		{
			thing.SetBool(101, enable: true);
		}
		if (!priceCalc.IsEmpty())
		{
			thing.SetStr("price_calc_override", priceCalc);
		}
		return thing;
	}

	public override string ToString()
	{
		StringBuilder stringBuilder = new StringBuilder();
		stringBuilder.AppendLine($"{base.ContentId}/{type}/{base.Owner.id}");
		stringBuilder.AppendLine($" - num({num})/lv({lv})/restock({restock})/noCopy({noCopy})/{material}/{rarity}/{blessedState}/{identifyLevel}");
		if (sockets.Count > 0)
		{
			stringBuilder.AppendLine($" - sockets({sockets.Count})/noRandomSocket({noRandomSocket})/{string.Join(';', sockets)}");
		}
		if (mapStr.Count > 0)
		{
			stringBuilder.AppendLine(" - str/" + string.Join(';', mapStr.Select((KeyValuePair<string, string> kv) => kv.Key + "=" + kv.Value)));
		}
		if (mapInt.Count > 0)
		{
			stringBuilder.AppendLine(" - int/" + string.Join(';', mapInt.Select((KeyValuePair<string, int> kv) => $"{kv.Key}={kv.Value}")));
		}
		return stringBuilder.ToString();
	}
}

+CustomZoneContent โ€‹

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

[JsonObject(MemberSerialization.OptOut)]
public class CustomZoneContent : CustomSourceContent
{
	public string parent;

	public override string SourceType => "SourceZone";

	public static CustomZoneContent CreateFromRow(SourceZone.Row r, ModPackage owner = null)
	{
		List<string> list = r.tag.Where((string t) => t.StartsWith("add")).ToList();
		if (list.Count == 0)
		{
			return null;
		}
		if (owner == null)
		{
			owner = ModUtil.FindSourceRowPackage(r);
		}
		CustomZoneContent customZoneContent = new CustomZoneContent
		{
			ContentId = "Zone/" + r.id,
			SourceId = r.id,
			Owner = owner
		};
		foreach (string item in list)
		{
			var (text, str, _) = CustomSourceContent.GetParams(item);
			if (text == "addMap")
			{
				customZoneContent.parent = str.IsEmpty(r.parent.IsEmpty("ntyris"));
			}
		}
		return customZoneContent;
	}

	public override void OnGameLoad(GameIOContext context)
	{
		Debug.Log($"#mod-content loading {this}");
		if (EClass.game.spatials.Find(base.SourceId) != null)
		{
			Debug.Log("#mod-content skipping existing custom zone " + base.SourceId);
			return;
		}
		Zone zone = ModUtil.FindZoneByFullName(parent);
		if (zone != null)
		{
			Spatial arg = SpatialGen.Create(base.SourceId, zone, register: true);
			Debug.Log($"#mod-content spawned custom zone {arg}");
			return;
		}
		ModUtil.LogModError("source zone row '" + base.SourceId + "' has invalid addMap parent '" + parent + "'", base.Owner);
	}

	public override string ToString()
	{
		return base.ContentId + "/" + parent;
	}
}

ELEMENT โ€‹

public class ELEMENT

cs

	public const int water = 15;

	public const int heat = 16; 
	public const int decay = 17; 

	public const int taste = 18;

	public const int poison = 20;

	public const int decay = 17; 
	public const int heat = 16; 

	public const int cut = 22;

public class ELEMENT

cs
	{
		765, 763, 762, 751, 752, 753, 754, 755, 756, 759,
		760, 761, 750, 0, 10, 1, 2, 3, 5, 11,
		12, 13, 14, 15, 16, 18, 20, 17, 22, 23, 
		12, 13, 14, 15, 17, 18, 20, 16, 22, 23, 
		24, 25, 26, 29, 85, 21
	};
}

ENC โ€‹

public class ENC

cs

	public const int noDamage = 654;

	public const int r_mana = 641; 
	public const int living = 653;

	public const int r_PV = 651;

	public const int r_mana = 641; 
	public const int r_DV = 650; 
	public const int eco = 652;

	public const int absorbHP = 660;

	public const int r_DV = 650; 
	public const int r_life = 640; 

	public const int absorbMP = 661;

public class ENC

cs

	public const int convertFire = 850;

	public const int r_life = 640; 
	public const int mod_frustration = 624; 

	public const int convertImpact = 865;

public class ENC

cs

	public const int absorbSP = 662;

	public const int mod_frustration = 624; 
	public const int mod_feint = 623; 

	public const int sustain_STR = 440; 
	public const int sustain_END = 441; 

	public const int mod_cleave = 622; 
	public const int mod_flurry = 621; 

	public const int encTail = 419;

public class ENC

cs

	public const int negateSteal = 426;

	public const int negateNeckHunt = 427; 
	public const int innocence = 418; 

	public const int allNeckHunt = 428; 
	public const int negateNeckHunt = 427; 

	public const int breathing = 429;

public class ENC

cs

	public const int parry = 437;

	public const int innocence = 418; 
	public const int knightly = 438; 

	public const int loving = 417; 
	public const int allNeckHunt = 428; 

	public const int seeInvisible = 416; 
	public const int negateParry = 439; 
	public const int loving = 417; 

	public const int invisibility = 415;

public class ENC

cs

	public const int expMod = 403;

	public const int knightly = 438; 
	public const int seeInvisible = 416; 

	public const int weightMod = 404;

public class ENC

cs

	public const int encSpell = 411;

	public const int mod_feint = 623; 
	public const int mod_cleave = 622; 

	public const int encHit = 414;

	public const int slowDecay = 405;

	public const int negateParry = 439; 
	public const int sustain_STR = 440; 

	public const int slowCorruption = 412;

	public const int sustain_END = 441; 
	public const int safetyMeasure = 486; 
	public const int sustain_DEX = 442; 

	public const int creativeChef = 487;

public class ENC

cs

	public const int negateGravity = 491;

	public const int shiawaseStep = 492; 
	public const int freemove = 493; 
	public const int mod_ammo = 600;

	public const int mod_reload = 601;

	public const int mod_rapid = 602; 
	public const int mod_ammo_knockback = 603; 

	public const int mod_ammo_recover = 604;

public class ENC

cs

	public const int mod_chaser = 620;

	public const int mod_flurry = 621; 
	public const int safetyMeasure = 486; 

	public const int nonLethal = 485;

	public const int slot_rune = 484; 
	public const int mod_ammo_knockback = 603; 
	public const int force_weapon = 482; 
	public const int mod_rapid = 602; 

	public const int optimizeMana = 483;

	public const int sustain_DEX = 442; 
	public const int slot_rune = 484; 

	public const int sustain_PER = 443;

public class ENC

cs

	public const int sustain_WIL = 445;

	public const int sustain_CHA = 447; 
	public const int sustain_MAG = 446; 

	public const int sustain_figure = 450;

public class ENC

cs

	public const int bane_undead = 461;

	public const int sustain_MAG = 446; 
	public const int bane_fairy = 462; 

	public const int bane_animal = 463; 
	public const int sustain_CHA = 447; 

	public const int bane_man = 464;

public class ENC

cs

	public const int strongStomach = 480;

	public const int bane_fairy = 462; 
	public const int revealFaith = 481;

	public static readonly int[] IDS = new int[108] 
	public const int bane_animal = 463; 
	public const int force_weapon = 482; 
	public static readonly int[] IDS = new int[110] 
	{
		656, 655, 654, 641, 653, 651, 652, 660, 650, 661, 
		851, 663, 664, 665, 666, 667, 850, 640, 865, 864, 
		852, 662, 624, 440, 622, 419, 420, 421, 422, 423, 
		424, 425, 426, 427, 428, 429, 430, 431, 432, 435, 
		436, 437, 418, 417, 416, 415, 380, 381, 382, 383, 
		400, 401, 402, 403, 438, 404, 406, 407, 408, 409, 
		410, 411, 623, 414, 405, 439, 412, 441, 486, 487, 
		488, 489, 490, 491, 600, 601, 602, 604, 605, 606, 
		607, 608, 609, 620, 621, 485, 484, 603, 482, 483, 
		442, 443, 444, 445, 447, 450, 460, 461, 446, 463, 
		464, 465, 466, 467, 468, 480, 462, 481
		656, 655, 654, 653, 651, 641, 650, 652, 660, 640, 
		661, 851, 663, 664, 665, 666, 667, 850, 624, 865, 
		864, 852, 662, 623, 441, 621, 419, 420, 421, 422, 
		423, 424, 425, 426, 418, 427, 429, 430, 431, 432, 
		435, 436, 437, 438, 428, 439, 417, 415, 380, 381, 
		382, 383, 400, 401, 402, 403, 416, 404, 406, 407, 
		408, 409, 410, 411, 622, 414, 405, 440, 412, 442, 
		487, 488, 489, 490, 491, 492, 493, 600, 601, 603, 
		604, 605, 606, 607, 608, 609, 620, 486, 485, 602, 
		483, 484, 443, 444, 445, 446, 450, 460, 461, 462, 
		447, 464, 465, 466, 467, 468, 480, 481, 463, 482
	};
}

EVENT โ€‹

public class ElinDramaParseActionEventArgs : ElinEventArgs<string>

cs
	public const string CharaCreated = "elin.chara_created";

	public const string ThingCreated = "elin.thing_created";
	public const string ReligionImporting = "elin.religion_importing"; 
	public const string ActPerformed = "elin.act_performed"; 
}

ElementContainerCard โ€‹

public void SetOwner(Card c, bool applyFeat)

cs
	{
		owner = c;
		SourceValueType sourceValueType = ((c.IsEquipmentOrRangedOrAmmo && c.rarity < Rarity.Artifact && !c.isReplica) ? SourceValueType.EquipmentRandom : SourceValueType.Fixed);
		if (c.sourceCard.ContainsTag("fixedElement")) 
		{ 
			sourceValueType = SourceValueType.Fixed; 
		} 
		if (c.sourceCard.ContainsTag("randomElement")) 
		{ 
			sourceValueType = SourceValueType.EquipmentRandom; 
		} 
		ApplyElementMap(c.uid, sourceValueType, c.sourceCard.elementMap, (sourceValueType != SourceValueType.EquipmentRandom) ? 1 : c.LV, invert: false, applyFeat);
	}

FACTION โ€‹

public class FACTION

cs

	public const int bfTranquil = 3703;

	public const int fAttraction = 2206; 
	public const int fRation = 2207; 

	public const int bfVolcano = 3704;

public class FACTION

cs

	public const int fConstruction = 2003;

	public const int fRation = 2207; 
	public const int fAttraction = 2206; 

	public static readonly int[] IDS = new int[53]
	{
		3702, 3601, 3602, 3603, 3604, 3701, 3606, 3700, 3600, 3605,
		3500, 2118, 2205, 2204, 2203, 2202, 2201, 2200, 2120, 2119,
		2117, 2116, 3703, 2206, 3704, 4001, 3706, 4006, 4005, 4004, 
		2117, 2116, 3703, 2207, 3704, 4001, 3706, 4006, 4005, 4004, 
		4003, 4002, 2115, 4000, 3900, 3805, 3804, 3803, 3802, 3801,
		3800, 3784, 3783, 3782, 3781, 3780, 3710, 3709, 3708, 3707,
		3705, 2003, 2207
		3705, 2003, 2206
	};
}
public class Faction : EClass

FEAT โ€‹

public class FEAT

cs

	public const int featNirvana = 1231;

	public const int featAdam = 1230; 
	public const int featLittleOne = 1229; 

	public const int featDemigod = 1228;

public class FEAT

cs

	public const int featLife = 1610;

	public const int featLittleOne = 1229; 
	public const int featAdam = 1230; 

	public const int featArcher = 1404; 
	public const int featFarmer = 1403; 
	public const int featPaladin2 = 1408; 

	public const int featBoost = 1409;

public class FEAT

cs

	public const int featElite = 1424;

	public const int featMimic = 1425; 
	public const int featPaladin2 = 1408; 
	public const int featPaladin = 1407;

	public const int featTourist = 1406;

	public const int featPianist = 1405;

	public const int featArcher = 1404; 
	public const int featSadCreature = 1291; 
	public const int featGod_element1 = 1300;

	public const int featGod_earth1 = 1305;

public class FEAT

cs

	public const int featGod_harvest1 = 1325;

	public const int featGod_luck1 = 1330; 
	public const int featMimic = 1425; 

	public const int featNeckHunter = 1426; 
	public const int featGod_luck1 = 1330; 

	public const int featGod_harmony1 = 1335; 
	public const int featGod_oblivion1 = 1340; 

	public const int featGod_trickery1 = 1345;

public class FEAT

cs

	public const int featWizard = 1402;

	public const int featFarmer = 1403; 
	public const int featHarem = 1276; 
	public const int featBelovedOne = 1275; 

	public const int featGod_oblivion1 = 1340; 
	public const int featGod_harmony1 = 1335; 

	public const int featSadCreature = 1291; 
	public const int featNeckHunter = 1426; 

	public const int featDisguise = 1427;

	public const int featManyFace = 1429; 
	public const int featMurderer = 1428; 

	public const int featMassSummoner = 1240;

public class FEAT

cs

	public const int featCancer = 1253;

	public const int featSplitWater = 1254; 
	public const int featGoodKarma = 1270;

	public const int featBadKarma = 1271;

	public const int featPeacemaker = 1272; 
	public const int featDemon = 1239;

	public const int featMurderer = 1428; 
	public const int featGoddess = 1290; 

	public const int featElder = 1238;

	public const int featGoddess = 1290; 
	public const int featHarem = 1276; 

	public const int featAstralBody = 1430; 
	public const int featManyFace = 1429; 

	public const int featBelovedOne = 1275; 
	public const int featAstralBody = 1430; 

	public const int featSlimeEvolution = 1274;

	public const int featBloom = 1273;

	public const int featPeacemaker = 1272; 
	public const int featRoran = 1237;

	public static readonly int[] IDS = new int[152] 
	public static readonly int[] IDS = new int[153] 
	{
		1235, 1643, 1644, 1645, 1646, 1647, 1648, 1649, 1642, 1650,
		1652, 1653, 1654, 1655, 1656, 1657, 1658, 1651, 1641, 1640,

public class FEAT

cs
		1628, 1629, 1630, 1631, 1632, 1633, 1634, 1635, 1659, 1611,
		1660, 1662, 1214, 1213, 1212, 1211, 1210, 1209, 1208, 1215,
		1207, 1205, 1204, 1203, 1202, 1201, 1200, 1234, 1206, 1216,
		1217, 1218, 1663, 1664, 1750, 1233, 1232, 1231, 1230, 1228, 
		1217, 1218, 1663, 1664, 1750, 1233, 1232, 1231, 1229, 1228, 
		1227, 1226, 1225, 1224, 1223, 1222, 1221, 1220, 1219, 1661,
		1610, 1229, 1404, 1409, 1410, 1411, 1412, 1413, 1414, 1415, 
		1416, 1417, 1418, 1419, 1420, 1421, 1422, 1423, 1424, 1425, 
		1408, 1407, 1406, 1405, 1300, 1305, 1310, 1236, 1315, 1320, 
		1325, 1330, 1426, 1335, 1345, 1350, 1355, 1400, 1401, 1402, 
		1403, 1276, 1340, 1291, 1427, 1429, 1240, 1241, 1242, 1243, 
		1610, 1230, 1403, 1408, 1409, 1410, 1411, 1412, 1413, 1414, 
		1415, 1416, 1417, 1418, 1419, 1420, 1421, 1422, 1423, 1424, 
		1407, 1406, 1405, 1404, 1291, 1300, 1305, 1310, 1236, 1315, 
		1320, 1325, 1425, 1330, 1340, 1345, 1350, 1355, 1400, 1401, 
		1402, 1275, 1335, 1426, 1427, 1428, 1240, 1241, 1242, 1243, 
		1244, 1245, 1246, 1247, 1248, 1249, 1250, 1251, 1252, 1253,
		1270, 1271, 1272, 1239, 1428, 1238, 1290, 1430, 1275, 1274, 
		1273, 1237
		1254, 1270, 1271, 1239, 1290, 1238, 1276, 1429, 1430, 1274, 
		1273, 1272, 1237
	};
}
public class Feat : Element

GameSerializationBinder โ€‹

public override Type BindToType(string assemblyName, string typeName)

cs
	}
	catch (Exception ex)
	{
		Core.Instance.ui.Say("Possible Mod Error, please contact the mod auther."); 
		Core.Instance.ui.Say("Possible Mod Error, please contact the mod author."); 
		Core.Instance.ui.Say(ex.Message);
		Debug.LogError(ex.Message);
		Debug.LogError(assemblyName + "/" + typeName);
		if (ModUtil.fallbackTypes.ContainsKey(typeName)) 
		if (ModUtil.fallbackTypes.TryGetValue(typeName, out var value)) 
		{
			Debug.Log(typeName + "/" + Type.GetType(ModUtil.fallbackTypes[typeName])); 
			return Type.GetType(ModUtil.fallbackTypes[typeName]); 
			Debug.Log(typeName + "/" + Type.GetType(value)); 
			return Type.GetType(value); 
		}
		if (typeName.StartsWith("Quest"))
		{

public override Type BindToType(string assemblyName, string typeName)

cs
		{
			return typeof(Zone);
		}
		if (typeName.StartsWith("Religion")) 
		{ 
			return typeof(ReligionCustom); 
		} 
		return typeof(UnknownTypePlaceholder);
	}
}

GlobalGoalAdv โ€‹

public class GlobalGoalAdv : GlobalGoal

cs
{
	public override void OnAdvanceHour()
	{
		if (!owner.isDead && !owner.IsPCFaction && owner.currentZone != EClass._zone && ((EClass.debug.enable && EClass.rnd(24) == 0) || (hours > 720 && EClass.rnd(720) == 0))) 
		if (!owner.isDead && !owner.IsPCFaction && owner.currentZone != EClass._zone && !owner.GetBool("StayHomeZone") && ((EClass.debug.enable && EClass.rnd(24) == 0) || (hours > 720 && EClass.rnd(720) == 0))) 
		{
			Zone randomTown = EClass.world.region.GetRandomTown();
			if (randomTown != owner.currentZone)

LayerMod โ€‹

using System.Collections.Generic;

cs
using System.Collections.Generic;
using System.IO; 

public class LayerMod : ELayer
{

public override void OnInit()

cs
	list.dragEdgeSize = 34f;
	UIList uIList = list;
	UIList uIList2 = list2;
	UIList.Callback<BaseModPackage, ItemMod> obj = new UIList.Callback<BaseModPackage, ItemMod> 
	UIList.Callback<ModPackage, ItemMod> obj = new UIList.Callback<ModPackage, ItemMod> 
	{
		onClick = delegate
		{
		},
		onInstantiate = delegate(BaseModPackage a, ItemMod b) 
		onInstantiate = delegate(ModPackage a, ItemMod b) 
		{
			a.UpdateMeta(updateOnly: true);
			b.package = a;

public override void OnInit()

cs
						list.List();
						textRestart.SetActive(enable: true);
					});
					if (!a.isInPackages && !a.workshopId.IsEmpty()) 
					{ 
						uIContextMenu.AddButton("mod_convert_local", delegate
						{ 
							SE.Click(); 
							string path = ("Mod_" + a.workshopId + "_" + a.id).SanitizeDirectoryName(); 
							string text2 = Path.Combine(BaseModManager.rootMod, path); 
							a.CopyContentTo(text2); 
							ModPackage modPackage = manager.AddPackage(new DirectoryInfo(text2), isInPackages: true); 
							manager.packages.Move(modPackage, manager.packages.IndexOf(a) - manager.packages.Count + 2); 
							modPackage.willActivate = false; 
							modPackage.activated = false; 
							ELayer.core.mods.SaveLoadOrder(); 
							list.List(); 
							textRestart.SetActive(enable: true); 
						}); 
					} 
					if (a.isInPackages && a.IsSourceLocalizable) 
					{ 
						uIContextMenu.AddButton("mod_export_text", delegate
						{ 
							SE.Click(); 
							string text = a.UpdateSourceLocalizationFile(Lang.langCode, force: true); 
							ELayer.ui.Say(text); 
						}); 
					} 
				}
				uIContextMenu.AddButton("mod_info", delegate
				{

public override void OnInit()

cs
			}
		},
		onRefresh = Refresh,
		onDragReorder = delegate(BaseModPackage p, int a) 
		onDragReorder = delegate(ModPackage p, int a) 
		{
			BaseCore.Instance.FreezeScreen(0.1f);
			manager.packages.Move(p, a);

public override void OnInit()

cs
			ELayer.core.mods.SaveLoadOrder();
			list.List();
		},
		canDragReorder = (BaseModPackage p) => !p.builtin 
		canDragReorder = (ModPackage p) => !p.builtin 
	};
	UIList.ICallback callbacks = obj;
	uIList2.callbacks = obj;

MUTATION โ€‹

public class MUTATION

cs
public class MUTATION
{
	public const int mutationStr = 1520; 
	public const int mutationSpeedN = 1519; 

	public const int mutationStrN = 1521; 
	public const int mutationStr = 1520; 

	public const int mutationSkin = 1510;

	public const int etherWing = 1554; 
	public const int etherFeet = 1552; 
	public const int etherEye = 1553; 

	public const int etherUgly = 1551;

public class MUTATION

cs

	public const int mutationBodyN = 1531;

	public const int etherNeck = 1555; 
	public const int mutationBody = 1530;

	public const int mutationLightning = 1528; 
	public const int etherWing = 1554; 
	public const int mutationLightningN = 1529; 

	public const int mutationColdN = 1527;

public class MUTATION

cs

	public const int mutationCha = 1522;

	public const int mutationLightningN = 1529; 
	public const int mutationStrN = 1521; 

	public const int etherViolence = 1556; 
	public const int mutationLightning = 1528; 

	public const int etherEye = 1553; 
	public const int etherNeck = 1555; 

	public const int etherRain = 1558; 
	public const int etherFeet = 1552; 
	public const int etherHead = 1557; 

	public const int mutationSkinN = 1511;

public class MUTATION

cs

	public const int mutationDexN = 1515;

	public const int etherHead = 1557; 
	public const int etherViolence = 1556; 

	public const int mutationRegenN = 1517;

public class MUTATION

cs

	public const int mutationRegen = 1516;

	public const int etherPoisonHand = 1565; 
	public const int etherManaBattery = 1564;

	public const int etherProvoke = 1563;

public class MUTATION

cs

	public const int etherAddict = 1559;

	public const int mutationSpeedN = 1519; 
	public const int etherRain = 1558; 
	public const int etherPoisonHand = 1565; 

	public static readonly int[] IDS = new int[40]
	{
		1520, 1521, 1510, 1554, 1552, 1551, 1550, 1533, 1532, 1531, 
		1555, 1530, 1528, 1527, 1526, 1525, 1524, 1523, 1522, 1529, 
		1556, 1553, 1558, 1511, 1512, 1513, 1514, 1515, 1557, 1517, 
		1518, 1516, 1565, 1564, 1563, 1562, 1561, 1560, 1559, 1519
		1519, 1520, 1510, 1553, 1551, 1550, 1533, 1532, 1531, 1530, 
		1554, 1529, 1527, 1526, 1525, 1524, 1523, 1522, 1521, 1528, 
		1555, 1552, 1557, 1511, 1512, 1513, 1514, 1515, 1556, 1517, 
		1518, 1516, 1564, 1563, 1562, 1561, 1560, 1559, 1558, 1565
	};
}
public class Mutation : Feat

ModManager โ€‹

using HeathenEngineering.SteamworksIntegration;

cs
using HeathenEngineering.SteamworksIntegration;
using HeathenEngineering.SteamworksIntegration.API;
using IniParser.Model;
using Newtonsoft.Json; 
using Steamworks;
using UnityEngine;

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

cs
		Debug.Log("Workshop:" + dirWorkshop);
		Debug.Log("Packages:" + BaseModManager.rootMod);
		Debug.Log("Core Mod:" + BaseModManager.rootDefaultPacakge);
		BaseModManager.SubscribeEvent("elin.source.lang_set", delegate(object lang) 
		{ 
			if (ModManagerCore.useLocalizations) 
			{ 
				ImportSourceLocalizations(lang as string); 
				ModManagerCore.generateLocalizations = false; 
			} 
			ImportAllModDialogs(); 
			BookList.dict = null; 
		}); 
	}

	public void SaveLoadOrder()

public void LoadLoadOrder()

cs
		}
	}

	public void ImportSourceLocalizations(string lang) 
	{ 
		PackageIterator.RebuildAllMappings(lang); 
		SortedDictionary<string, string> sortedDictionary = new SortedDictionary<string, string>(); 
		Dictionary<string, SortedDictionary<string, string>> dictionary = new Dictionary<string, SortedDictionary<string, string>>(); 
		string value; 
		string key; 
		foreach (string item in FileMapping.FallbackLut[lang].Append(lang).Distinct()) 
		{ 
			(FileInfo, EMod)[] filesEx = PackageIterator.GetFilesEx(item + "/SourceLocalization.json", useCache: false); 
			for (int i = 0; i < filesEx.Length; i++) 
			{ 
				var (fileInfo, eMod) = filesEx[i]; 
				try
				{ 
					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}"); 
				} 
			} 
		} 
		JsonSerializerSettings setting = new JsonSerializerSettings
		{ 
			PreserveReferencesHandling = PreserveReferencesHandling.None, 
			NullValueHandling = NullValueHandling.Ignore 
		}; 
		foreach (BaseModPackage package in packages) 
		{ 
			if (!(package is ModPackage modPackage) || package.builtin || !package.activated) 
			{ 
				continue; 
			} 
			HashSet<SourceData.BaseRow> sourceRows = modPackage.sourceRows; 
			if (sourceRows == null || sourceRows.Count <= 0) 
			{ 
				continue; 
			} 
			modPackage.ImportSourceLocalizations(sortedDictionary); 
			if (!ModManagerCore.generateLocalizations || (!modPackage.isInPackages && !Application.isEditor)) 
			{ 
				continue; 
			} 
			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> item3 in sortedDictionary4) 
				{ 
					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.ContainsKey(kv.Key))) 
				{ 
					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) 
			{ 
				Debug.LogError($"#source localization failed to generate {modPackage}\n{arg2}"); 
			} 
		} 
	} 
	public void ImportAllModSourceSheets() 
	{ 
		try
		{ 
			SourceCache.InvalidateCacheVersion(); 
			SourceImporter.HotInit(new SourceData[2] 
			{ 
				EClass.sources.elements, 
				EClass.sources.materials 
			}); 
			List<string> list = new List<string>(); 
			foreach (ModPackage item in packages.OfType<ModPackage>()) 
			{ 
				if (item.builtin || !item.activated) 
				{ 
					continue; 
				} 
				foreach (FileInfo sourceSheet in item.Mapping.SourceSheets) 
				{ 
					if (!sourceSheet.Name.StartsWith(".") && !sourceSheet.Name.Contains("~")) 
					{ 
						ModUtil.sourceImporter.fileProviders[sourceSheet.FullName] = item; 
						list.Add(sourceSheet.FullName); 
					} 
				} 
			} 
			ModUtil.sourceImporter.ImportFilesCached(list); 
			SourceCache.FinalizeCache(); 
			SourceCache.InvalidateCacheBlobs(); 
			SourceCache.ClearDetail(); 
		} 
		catch (Exception message) 
		{ 
			Debug.LogError(message); 
		} 
		Debug.Log("#source finished importing workbooks"); 
	} 
	public void ImportAllModDialogs() 
	{ 
		Lang.extraExcelDialogs = new HashSet<string>(PathComparer.Default); 
		Lang.excelDialog = null; 
		FileInfo[] files = PackageIterator.GetFiles("Dialog/dialog.xlsx"); 
		foreach (FileInfo fileInfo in files) 
		{ 
			Lang.extraExcelDialogs.Add(fileInfo.FullName); 
			Debug.Log("#dialog loaded " + fileInfo.ShortPath()); 
		} 
	} 
	public void ImportAllModGodTalks() 
	{ 
		if (Lang.setting?.dir == null) 
		{ 
			return; 
		} 
		Dictionary<string, Dictionary<string, string>> map = EClass.sources.dataGodTalk.sheets["_default"].map; 
		foreach (ExcelData item in from f in PackageIterator.GetFiles("Data/god_talk.xlsx") 
			select new ExcelData(f.FullName, 3)) 
		{ 
			foreach (KeyValuePair<string, Dictionary<string, string>> item2 in map) 
			{ 
				item2.Deconstruct(out var key, out var _); 
				string text = key; 
				if (text.IsEmpty()) 
				{ 
					continue; 
				} 
				Dictionary<string, string> valueOrDefault = item.sheets["_default"].map.GetValueOrDefault(text); 
				if (valueOrDefault == null) 
				{ 
					continue; 
				} 
				foreach (KeyValuePair<string, string> item3 in valueOrDefault) 
				{ 
					item3.Deconstruct(out key, out var value2); 
					string text2 = key; 
					string value3 = value2; 
					if (text2 != "id") 
					{ 
						map[text][text2] = value3; 
					} 
				} 
			} 
			Debug.Log("#dialog loaded " + item.path.ShortPath()); 
		} 
	} 
	public IEnumerator RefreshMods(Action onComplete, bool syncMods)
	{
		bool flag = !BaseCore.IsOffline && syncMods && UserGeneratedContent.Client.GetNumSubscribedItems() != 0;

public ModPackage AddPackage(DirectoryInfo dir, bool isInPackages = false)

cs
{
	ModPackage modPackage = new ModPackage
	{
		dirInfo = dir, 
		dirInfo = new DirectoryInfo(dir.FullName.NormalizePath()), 
		installed = true,
		isInPackages = isInPackages,
		loadPriority = priorityIndex,

public ModPackage AddWorkshopPackage(WorkshopItem item, bool isInPackages = fals

cs
		ModPackage modPackage = AddPackage(directoryInfo, isInPackages);
		modPackage.installed = itemInstallInfo;
		modPackage.banned = item.IsBanned;
		modPackage.workshopId = item.FileId.ToString(); 
		return modPackage;
	}

public void LoadLocalPackages()

cs
	{
		if (!disableMod || !(directoryInfo.Name != "_Elona") || !(directoryInfo.Name != "_Lang_Chinese"))
		{
			AddPackage(directoryInfo, isInPackages: true); 
			if (directoryInfo.Name == "Mod_FixedPackageLoader") 
			{ 
				IO.DeleteDirectory(directoryInfo.FullName); 
			} 
			else
			{ 
				AddPackage(directoryInfo, isInPackages: true); 
			} 
		}
	}
}

ModPackage โ€‹

using System.Linq;

cs
using System.Linq;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using Newtonsoft.Json; 
using UnityEngine;

public class ModPackage : EMod

public struct SheetIndex

cs
		public int old;
	}

	public void CopyContentTo(string dir) 
	{ 
		IO.DeleteDirectory(dir); 
		IO.CopyAll(dirInfo.FullName, dir); 
		EClass.ui.Say(dir); 
	} 
	public IReadOnlyList<FileInfo> ParseTalkText(DirectoryInfo dir)
	{
		List<FileInfo> list = new List<FileInfo>();

public IReadOnlyList<FileInfo> ParseSound(DirectoryInfo dir)

cs
		return list;
	}

	public SortedDictionary<string, string> ExportSourceLocalizations() 
	public override void GenerateCustomContentProfiles() 
	{ 
		customContent.Clear(); 
		foreach (SourceData.BaseRow sourceRow in sourceRows) 
		{ 
			if (!(sourceRow is SourceChara.Row r)) 
			{ 
				if (!(sourceRow is SourceReligion.Row row)) 
				{ 
					if (!(sourceRow is SourceZone.Row r2)) 
					{ 
						if (!(sourceRow is SourceElement.Row r3)) 
						{ 
							if (!(sourceRow is SourceMaterial.Row r4)) 
							{ 
								if (!(sourceRow is SourceStat.Row r5)) 
								{ 
									if (!(sourceRow is SourceThing.Row r6)) 
									{ 
										if (!(sourceRow is SourceFaction.Row) && sourceRow is SourceQuest.Row) 
										{ 
										} 
									} 
									else
									{ 
										customContent.Add(CustomThingContent.CreateFromRow(r6, this)); 
									} 
								} 
								else
								{ 
									customContent.Add(CustomStatContent.CreateFromRow(r5, this)); 
								} 
							} 
							else
							{ 
								customContent.Add(CustomMaterialContent.CreateFromRow(r4, this)); 
							} 
						} 
						else
						{ 
							customContent.Add(CustomElementContent.CreateFromRow(r3, this)); 
						} 
					} 
					else
					{ 
						customContent.Add(CustomZoneContent.CreateFromRow(r2, this)); 
					} 
				} 
				else if (row.id.StartsWith("cwl") || row.id.StartsWith("custom")) 
				{ 
					customContent.Add(CustomReligionContent.CreateFromRow(row, this)); 
				} 
			} 
			else
			{ 
				ModUtil.FixDefaultCharaRowPref(r); 
				customContent.Add(CustomCharaContent.CreateFromRow(r, this)); 
			} 
		} 
		customContent.RemoveAll((ICustomContent p) => p == null); 
	} 
	public override SortedDictionary<string, string> ExportSourceLocalizations() 
	{
		SortedDictionary<string, string> sortedDictionary = new SortedDictionary<string, string>();
		try

public SortedDictionary<string, string> ExportSourceLocalizations()

cs
		return sortedDictionary;
	}

	public void ImportSourceLocalizations(IReadOnlyDictionary<string, string> texts) 
	public override void ImportSourceLocalizations(IReadOnlyDictionary<string, string> texts) 
	{
		foreach (SourceData.BaseRow sourceRow in sourceRows)
		{

public void ImportSourceLocalizations(IReadOnlyDictionary<string, string> texts)

cs
		}
	}

	public void ClearSourceLocalizations(string lang) 
	public override void ClearSourceLocalizations(string lang) 
	{
		Mapping.RebuildLangModMapping(lang);
		for (FileInfo fileInfo = Mapping.RelocateFile("SourceLocalization.json"); fileInfo != null; fileInfo = Mapping.RelocateFile("SourceLocalization.json"))
		{
			fileInfo.Delete();
			Debug.Log("#source localization deleted " + fileInfo.ShortPath()); 
			Debug.Log("#source-localization deleted " + fileInfo.ShortPath()); 
		}
		Mapping.RebuildLangModMapping(Lang.langCode);
	}

	public override string UpdateSourceLocalizationFile(string lang, bool force = false) 
	{ 
		if (!base.IsSourceLocalizable) 
		{ 
			return null; 
		} 
		IReadOnlyDictionary<string, string> modEntries = SourceLocalization.GetModEntries(id, lang); 
		SortedDictionary<string, string> sortedDictionary = ExportSourceLocalizations(); 
		SortedDictionary<string, string> final = new SortedDictionary<string, string>(); 
		foreach (var (key, defaultValue) in sortedDictionary) 
		{ 
			final[key] = modEntries.GetValueOrDefault(key, defaultValue); 
		} 
		string text3 = Path.Combine(dirInfo.FullName, "LangMod/" + lang + "/SourceLocalization.json"); 
		if (force || modEntries.Count != final.Count || modEntries.Any((KeyValuePair<string, string> kv) => !final.ContainsKey(kv.Key))) 
		{ 
			JsonSerializerSettings setting = new JsonSerializerSettings
			{ 
				PreserveReferencesHandling = PreserveReferencesHandling.None, 
				NullValueHandling = NullValueHandling.Ignore 
			}; 
			IO.SaveFile(text3, final, compress: false, setting); 
			SourceLocalization.UpdateModEntries(id, lang, final); 
		} 
		return text3; 
	} 
	public void AddOrUpdateLang(DirectoryInfo dir)
	{
		Core core = EClass.core;

ModUtil โ€‹

using System;

cs
using System;
using System.Collections; 
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis; 
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text; 
using System.Text.RegularExpressions;
using System.Threading;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using Newtonsoft.Json; 
using ReflexCLI.Attributes; 
using UnityEngine;
using UnityEngine.Networking;

[ConsoleCommandClassCustomizer("Mod")] 
public class ModUtil : EClass
{
	public static SourceImporter sourceImporter = new SourceImporter(SourceMapping); 
	public static Dictionary<string, string> fallbackTypes = new Dictionary<string, string>();

	private static readonly Dictionary<string, ICustomContent> _customContent = new Dictionary<string, ICustomContent>(); 
	private static readonly List<Func<string, object, int>> _customCalcEvaluator = new List<Func<string, object, int>>(); 
	private static readonly Dictionary<string, Texture2D> _cachedTextures = new Dictionary<string, Texture2D>(); 
	public static SourceImporter sourceImporter = new SourceImporter(SourceMapping); 
	public static IReadOnlyDictionary<string, SourceData> SourceMapping => (from f in typeof(SourceManager).GetFields()
		where typeof(SourceData).IsAssignableFrom(f.FieldType)
		select f).ToDictionary((FieldInfo f) => f.FieldType.Name, (FieldInfo f) => f.GetValue(EClass.sources) as SourceData);

	public static void OnModsActivated() 
	{ 
		SoundManager.current.soundLoaders.Add(LoadSoundData); 
		UIBook.topicLoaders.Add(LoadTopicFiles); 
		BookList.booklistLoaders.Add(LoadBookList); 
		BaseModManager.PublishEvent("elin.mods.activated"); 
		BaseModManager.SubscribeEvent("elin.game.post_load", PostLoadCleanup); 
	} 
	private static void PostLoadCleanup(object context) 
	{ 
		EClass.player.knownBGMs.RemoveWhere((int id) => !EClass.core.refs.dictBGM.ContainsKey(id)); 
	} 
	public static void LoadTypeFallback()
	{
		string text = "type_resolver.txt";
		string[] array = new string[0]; 
		string[] array = Array.Empty<string>(); 
		if (File.Exists(CorePath.RootData + text))
		{
			array = IO.LoadTextArray(CorePath.RootData + text);

public static void RegisterSerializedTypeFallback(string nameAssembly, string na

cs
		fallbackTypes[nameType] = nameFallbackType;
	}

	public static void LogModError(string message, BaseModPackage package = null) 
	{ 
		string text = "#mod/" + package?.id + "\n" + message; 
		UnityEngine.Debug.LogWarning(text.RemoveAllTags()); 
		if ((package?.isInPackages ?? false) || Application.isEditor) 
		{ 
			EGui.CreatePopup(text); 
		} 
	} 
	public static void LogModError(string message, SourceData.BaseRow row = null) 
	{ 
		LogModError(message, FindSourceRowPackage(row)); 
	} 
	public static void LogModError(string message, FileInfo file = null) 
	{ 
		LogModError(message, FindFileProviderPackage(file)); 
	} 
	public static void LogModError(string message, DirectoryInfo dir = null) 
	{ 
		LogModError(message, FindDirectoryProviderPackage(dir)); 
	} 
	public static ModPackage GetModPackage(string modId)
	{
		return ModManagerCore.Instance.MappedPackages.GetValueOrDefault(modId) as ModPackage;
	}

	public static void ImportExcel(string pathToExcelFile, string sheetName, SourceData source) 
	public static ModPackage FindFileProviderPackage(FileInfo file) 
	{
		UnityEngine.Debug.Log("ImportExcel source:" + source?.ToString() + " Path:" + pathToExcelFile); 
		using FileStream @is = File.Open(pathToExcelFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); 
		XSSFWorkbook xSSFWorkbook = new XSSFWorkbook((Stream)@is); 
		for (int i = 0; i < xSSFWorkbook.NumberOfSheets; i++) 
		string path = file.FullName.NormalizePath(); 
		return ModManager.Instance.packages.LastOrDefault((BaseModPackage p) => path.StartsWith(p.dirInfo.FullName)) as ModPackage; 
	} 
	public static ModPackage FindDirectoryProviderPackage(DirectoryInfo dir) 
	{ 
		string path = dir.FullName.NormalizePath(); 
		return ModManager.Instance.packages.LastOrDefault((BaseModPackage p) => path.StartsWith(p.dirInfo.FullName)) as ModPackage; 
	} 
	public static ModPackage FindSourceRowPackage(SourceData.BaseRow row) 
	{ 
		return ModManagerCore.Instance.packages.OfType<ModPackage>().LastOrDefault((ModPackage p) => p.sourceRows.Contains(row)); 
	} 
	public static Zone FindZoneByFullName(string zoneFullName = "ntyris/0", bool useRandomFallback = false) 
	{ 
		if (zoneFullName.IsEmpty()) 
		{
			ISheet sheetAt = xSSFWorkbook.GetSheetAt(i); 
			if (sheetAt.SheetName != sheetName) 
			return null; 
		} 
		zoneFullName = zoneFullName.Replace('/', '@'); 
		Zone zone = EClass.game.spatials.Find((Zone z) => z.ZoneFullName == zoneFullName); 
		if (zone != null) 
		{ 
			return zone; 
		} 
		int num = zoneFullName.LastIndexOf('@'); 
		int destLv = 0; 
		string zoneType; 
		if (num > 0 && num < zoneFullName.Length - 1) 
		{ 
			zoneType = zoneFullName[..num]; 
			destLv = zoneFullName[(num + 1)..].ToInt(); 
		} 
		else
		{ 
			zoneType = zoneFullName.Replace("@", ""); 
		} 
		string zoneId = zoneType.Replace("Zone_", ""); 
		zoneType = "Zone_" + zoneId; 
		zone = EClass.game.spatials.Find((Zone z) => z.GetType().Name == zoneType || z.id == zoneId)?.FindOrCreateLevel(destLv); 
		if (zone == null && (zoneId == "*" || useRandomFallback)) 
		{ 
			zone = (from z in EClass.game.spatials.map.Values.OfType<Zone>() 
				where z.CanSpawnAdv 
				select z).RandomItem(); 
		} 
		return zone; 
	} 
	public static void OnModsActivated() 
	{ 
		_cachedTextures.Clear(); 
		_customContent.Clear(); 
		SoundManager.current.soundLoaders.Add(LoadSoundData); 
		UIBook.topicLoaders.Add(LoadTopicFiles); 
		BookList.booklistLoaders.Add(LoadBookList); 
		Lang.excelDialogLoaders.Add(LoadExcelDialog); 
		BaseModManager.SubscribeEvent<GameIOContext>("elin.game.post_load", OnPostLoadInit); 
		BaseModManager.SubscribeEvent<GameIOContext>("elin.game.start_new", OnPostLoadInit); 
		BaseModManager.SubscribeEvent<GameIOContext>("elin.game.post_save", OnPostSaveInit); 
		BaseModManager.SubscribeEvent<string>("elin.source.lang_set", OnSetLang); 
		BaseModManager.SubscribeEvent<Chara>("elin.chara_created", OnCharaCreated); 
		BaseModManager.SubscribeEvent<Thing>("elin.thing_created", OnThingCreated); 
		BaseModManager.SubscribeEvent<List<Religion>>("elin.religion_importing", OnReligionImporting); 
		BaseModManager.SubscribeEvent<Act>("elin.act_performed", OnActPerformed); 
		BaseModManager.SubscribeEvent("elin.source.importing", OnSourceImporting); 
		BaseModManager.SubscribeEvent("elin.source.imported", OnSourceImported); 
		BaseModManager.PublishEvent("elin.mods.activated"); 
	} 
	private static void OnSourceImporting() 
	{ 
		if (ModManagerCore.enableSheetLoading) 
		{ 
			ImportAllModSourceSheets(); 
		} 
	} 
	private static void OnSourceImported() 
	{ 
		_customContent.Clear(); 
		foreach (EMod activatedUserMod in ModManager.Instance.ActivatedUserMods) 
		{ 
			try
			{
				continue; 
				activatedUserMod.GenerateCustomContentProfiles(); 
				foreach (ICustomContent item in activatedUserMod.customContent) 
				{ 
					AddContent(item); 
				} 
			}
			UnityEngine.Debug.Log("Importing Sheet:" + sheetName); 
			try
			catch (Exception ex) 
			{
				ExcelParser.path = pathToExcelFile; 
				if (!source.ImportData(sheetAt, new FileInfo(pathToExcelFile).Name, overwrite: true)) 
				LogModError("exception while generating custom source profiles\n" + ex.Message, activatedUserMod); 
				UnityEngine.Debug.LogError(ex); 
			} 
		} 
		CustomReligionContent.managed.Clear(); 
		foreach (CustomReligionContent item2 in _customContent.Values.OfType<CustomReligionContent>()) 
		{ 
			item2.RegisterCustomReligion(); 
		} 
		CustomReligionContent.Init(); 
	} 
	private static void OnPostLoadInit(GameIOContext context) 
	{ 
		EClass.player.knownBGMs.RemoveWhere((int id) => !EClass.core.refs.dictBGM.ContainsKey(id)); 
		List<ICustomContent> contents = new List<ICustomContent>(); 
		CustomReligionContent.LoadReligionData(context); 
		LoadCustomContent<CustomZoneContent>(); 
		LoadCustomContent<CustomCharaContent>(); 
		LoadOtherCustomContent(); 
		void LoadCustomContent<T>() where T : class, ICustomContent
		{ 
			UnityEngine.Debug.Log("#mod-content loading " + typeof(T).Name + "..."); 
			foreach (T item in _customContent.Values.OfType<T>()) 
			{ 
				try
				{
					UnityEngine.Debug.LogError(ERROR.msg); 
					break; 
					item.OnGameLoad(context); 
					contents.Add(item); 
				} 
				catch (Exception ex2) 
				{ 
					LogModError("exception while loading custom content '" + item.ContentId + "'\n" + ex2.Message, item.Owner); 
					UnityEngine.Debug.LogError(ex2); 
				} 
			} 
		} 
		void LoadOtherCustomContent() 
		{ 
			foreach (ICustomContent item2 in _customContent.Values.Except(contents)) 
			{ 
				try
				{ 
					item2.OnGameLoad(context); 
				} 
				catch (Exception ex) 
				{ 
					LogModError("exception while loading custom content '" + item2.ContentId + "'\n" + ex.Message, item2.Owner); 
					UnityEngine.Debug.LogError(ex); 
				}
				UnityEngine.Debug.Log("Imported " + sheetAt.SheetName); 
				source.Reset(); 
			} 
		} 
	} 
	private static void OnPostSaveInit(GameIOContext context) 
	{ 
		CustomReligionContent.SaveReligionData(context); 
		foreach (ICustomContent value in _customContent.Values) 
		{ 
			try
			{ 
				value.OnGameSave(context); 
			}
			catch (Exception ex)
			{
				UnityEngine.Debug.LogError("[Error] Skipping import " + sheetAt.SheetName + " :" + ex.Message + "/" + ex.Source + "/" + ex.StackTrace); 
				break; 
				LogModError("exception while saving custom content '" + value.ContentId + "'\n" + ex.Message, value.Owner); 
				UnityEngine.Debug.LogError(ex); 
			}
		}
	}

	public static ModPackage FindSourceRowPackage(SourceData.BaseRow row) 
	private static void OnReligionImporting(List<Religion> list) 
	{
		return ModManagerCore.Instance.packages.OfType<ModPackage>().LastOrDefault((ModPackage p) => p.sourceRows.Contains(row)); 
		list.AddRange(CustomReligionContent.GetCustomReligions()); 
	} 
	private static void OnCharaCreated(Chara chara) 
	{ 
		if (TryGetContent<CustomCharaContent>("Chara/" + chara.id, out var content)) 
		{ 
			content.OnCharaCreated(chara); 
		} 
		if (TryGetContent<CustomBiographyContent>("Biography/" + chara.id, out var content2)) 
		{ 
			content2.RefreshCharaBio(chara); 
		} 
	} 
	private static void OnThingCreated(Thing thing) 
	{ 
		if (TryGetContent<CustomThingContent>("Thing/" + thing.id, out var content)) 
		{ 
			content.OnThingCreated(thing); 
		} 
	} 
	private static void OnActPerformed(Act act) 
	{ 
		if (act.HasTag("godAbility")) 
		{ 
			CustomReligionContent.managed.Values.FirstOrDefault((ReligionCustom r) => r.content.godAbilities.Contains(act.ID))?.Talk("ability"); 
		} 
	} 
	private static void OnSetLang(string lang) 
	{ 
		PackageIterator.ClearCache(); 
		PackageIterator.RebuildAllMappings(lang); 
		SourceLocalization.SetLang(lang); 
		if (ModManagerCore.generateLocalizations) 
		{ 
			foreach (EMod activatedUserMod in ModManager.Instance.ActivatedUserMods) 
			{ 
				if (activatedUserMod.IsSourceLocalizable && (activatedUserMod.isInPackages || Application.isEditor)) 
				{ 
					activatedUserMod.UpdateSourceLocalizationFile(lang); 
				} 
			} 
			ModManagerCore.generateLocalizations = false; 
		} 
		foreach (string item in LoadGodTalk()) 
		{ 
			MOD.listGodTalk.Add(new ExcelData(item)); 
		} 
		BookList.dict = null; 
		BottleMessageList.list = null; 
		Lang.excelDialog = null; 
		foreach (CustomFileContent item2 in _customContent.Values.OfType<CustomFileContent>()) 
		{ 
			item2.OnSetLang(lang); 
		} 
	} 
	public static bool TryGetContent<T>(string contentId, [NotNullWhen(true)] out T content) where T : class, ICustomContent
	{ 
		ICustomContent value; 
		bool num = _customContent.TryGetValue(contentId, out value); 
		content = value as T; 
		if (num) 
		{ 
			return content != null; 
		} 
		return false; 
	} 
	public static bool HasContent(string contentId) 
	{ 
		return _customContent.ContainsKey(contentId); 
	} 
	public static void AddContent(ICustomContent content) 
	{ 
		UnityEngine.Debug.Log(_customContent.Remove(content.ContentId, out var value) ? ("#mod-content override '" + content.ContentId + "' '" + value.Owner.id + "' -> '" + content.Owner.id + "'") : ("#mod-content added '" + content.ContentId + "' from '" + content.Owner.id + "'")); 
		_customContent[content.ContentId] = content; 
	} 
	public static void FixDefaultCharaRowPref(SourceChara.Row r) 
	{ 
		r.pref = new SourcePref
		{ 
			pivotY = -10
		}; 
	} 
	public static List<Thing> GenerateMerchantStock(Card owner, string stockId = null, bool forceRestock = false) 
	{ 
		List<Thing> list = new List<Thing>(); 
		if (stockId.IsEmpty()) 
		{ 
			stockId = owner.GetStr("merchant_override"); 
		} 
		if (stockId.IsEmpty()) 
		{ 
			return list; 
		} 
		string[] array = stockId.Split('|'); 
		HashSet<string> orCreate = EClass.player.noRestocks.GetOrCreate(owner.trait.IdNoRestock, () => new HashSet<string>()); 
		string[] array2 = array; 
		foreach (string text in array2) 
		{ 
			if (!TryGetContent<CustomMerchantStock>("MerchantStock/" + text, out var content)) 
			{ 
				continue; 
			} 
			foreach (Thing item in content.Generate(owner)) 
			{ 
				bool @bool = item.GetBool(101); 
				if (!(!forceRestock && @bool) || !orCreate.Contains(item.trait.IdNoRestock)) 
				{ 
					if (@bool) 
					{ 
						orCreate.Add(item.trait.IdNoRestock); 
					} 
					list.Add(item); 
				} 
			} 
		} 
		return list; 
	} 
	public static Sprite AppendSpriteSheet(string id, int resizeWidth = 0, int resizeHeight = 0, string pattern = "@") 
	{ 
		Dictionary<string, string> dictModItems = SpriteReplacer.dictModItems; 
		if (!dictModItems.TryGetValue(id, out var value) && pattern != "") 
		{ 
			value = dictModItems.Where((KeyValuePair<string, string> kv) => kv.Key.StartsWith(pattern)).FirstOrDefault((KeyValuePair<string, string> kv) => id.StartsWith(kv.Key[pattern.Length..])).Value; 
		} 
		string spritePath = value; 
		string name = id; 
		Sprite sprite = LoadSprite(spritePath, null, name, resizeWidth, resizeHeight); 
		if (sprite == null) 
		{ 
			return null; 
		} 
		if (SpriteSheet.dict.TryGetValue(id, out var value2) && value2.texture.width == sprite.texture.width && value2.texture.height == sprite.texture.height) 
		{ 
			return value2; 
		} 
		return SpriteSheet.dict[sprite.name] = sprite; 
	} 
	public static List<string> LoadBookList() 
	{ 
		List<string> list = new List<string>(); 
		DirectoryInfo[] directories = PackageIterator.GetDirectories("Text"); 
		foreach (DirectoryInfo directoryInfo in directories) 
		{ 
			list.AddRange(Directory.GetDirectories(directoryInfo.FullName)); 
			UnityEngine.Debug.Log("#book list loaded " + directoryInfo.ShortPath()); 
		} 
		return list; 
	} 
	public static List<string> LoadTopicFiles() 
	{ 
		List<string> list = new List<string>(); 
		FileInfo[] files = PackageIterator.GetFiles("Text/Help/_topics.txt"); 
		foreach (FileInfo fileInfo in files) 
		{ 
			list.AddRange(IO.LoadTextArray(fileInfo.FullName)); 
			UnityEngine.Debug.Log("#book topic loaded " + fileInfo.ShortPath()); 
		} 
		return list; 
	} 
	public static List<string> LoadExcelDialog() 
	{ 
		List<string> list = new List<string>(); 
		FileInfo[] files = PackageIterator.GetFiles("Dialog/dialog.xlsx"); 
		foreach (FileInfo fileInfo in files) 
		{ 
			list.Add(fileInfo.FullName); 
			UnityEngine.Debug.Log("#dialog loaded " + fileInfo.ShortPath()); 
		} 
		return list; 
	} 
	public static Sprite LoadSprite(string spritePath, Vector2? pivot = null, string name = null, int resizeWidth = 0, int resizeHeight = 0) 
	{ 
		if (spritePath.IsEmpty()) 
		{ 
			return null; 
		} 
		if (!spritePath.EndsWith(".png")) 
		{ 
			if (SpriteReplacer.dictModItems.TryGetValue(spritePath, out var value)) 
			{ 
				spritePath = value; 
			} 
			spritePath += ".png"; 
		} 
		if (!File.Exists(spritePath)) 
		{ 
			FileInfo[] files = PackageIterator.GetFiles(Path.Combine("Texture", spritePath)); 
			if (files.IsEmpty()) 
			{ 
				return null; 
			} 
			spritePath = files[^1].FullName; 
		} 
		Vector2 valueOrDefault = pivot.GetValueOrDefault(); 
		if (!pivot.HasValue) 
		{ 
			valueOrDefault = new Vector2(0.5f, 0.5f); 
			pivot = valueOrDefault; 
		} 
		string text = $"{spritePath}/{pivot}/{resizeWidth}/{resizeHeight}"; 
		if (name == null) 
		{ 
			name = text; 
		} 
		try
		{ 
			if (!_cachedTextures.TryGetValue(text, out var value2)) 
			{ 
				value2 = IO.LoadPNG(spritePath); 
				if (value2 == null) 
				{ 
					return null; 
				} 
				if (resizeWidth != 0 && resizeHeight != 0 && value2.width != resizeWidth && value2.height != resizeHeight) 
				{ 
					Texture2D texture2D = value2.Rescale(resizeWidth, resizeHeight); 
					UnityEngine.Object.Destroy(value2); 
					value2 = texture2D; 
					value2.name = text; 
				} 
			} 
			_cachedTextures[text] = value2; 
		} 
		catch (Exception arg) 
		{ 
			UnityEngine.Debug.LogError($"#sprite failed to load {spritePath.ShortPath()}\n{arg}"); 
			return null; 
		} 
		Texture2D texture2D2 = _cachedTextures[text]; 
		Sprite sprite = Sprite.Create(texture2D2, new Rect(0f, 0f, texture2D2.width, texture2D2.height), pivot.Value, 100f, 0u, SpriteMeshType.FullRect); 
		sprite.name = name; 
		return sprite; 
	} 
	public static List<string> LoadGodTalk() 
	{ 
		List<string> list = new List<string>(); 
		FileInfo[] files = PackageIterator.GetFiles("Data/god_talk.xlsx"); 
		foreach (FileInfo fileInfo in files) 
		{ 
			list.Add(fileInfo.FullName); 
			UnityEngine.Debug.Log("#god-talk loaded " + fileInfo.ShortPath()); 
		} 
		return list; 
	}

	public static SerializableSoundData GetSoundMeta(string soundPath)

public static void SetBGMKnown(int bgmId, bool known = true)

cs
		}
	}

	public static string[] LoadBookList() 
	[Obsolete("use ImportModSourceSheets for proper caching and localizaiton support")] 
	public static void ImportExcel(string pathToExcelFile, string sheetName, SourceData source) 
	{
		return (from d in PackageIterator.GetDirectories("Text").SelectMany((DirectoryInfo d) => d.GetDirectories()) 
			select d.FullName).ToArray(); 
		UnityEngine.Debug.Log("ImportExcel source:" + source?.ToString() + " Path:" + pathToExcelFile); 
		using FileStream @is = File.Open(pathToExcelFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); 
		XSSFWorkbook xSSFWorkbook = new XSSFWorkbook((Stream)@is); 
		for (int i = 0; i < xSSFWorkbook.NumberOfSheets; i++) 
		{ 
			ISheet sheetAt = xSSFWorkbook.GetSheetAt(i); 
			if (sheetAt.SheetName != sheetName) 
			{ 
				continue; 
			} 
			UnityEngine.Debug.Log("Importing Sheet:" + sheetName); 
			try
			{ 
				ExcelParser.path = pathToExcelFile; 
				if (!source.ImportData(sheetAt, new FileInfo(pathToExcelFile).Name, overwrite: true)) 
				{ 
					UnityEngine.Debug.LogError(ERROR.msg); 
					break; 
				} 
				UnityEngine.Debug.Log("Imported " + sheetAt.SheetName); 
				source.Reset(); 
			} 
			catch (Exception ex) 
			{ 
				UnityEngine.Debug.LogError("[Error] Skipping import " + sheetAt.SheetName + " :" + ex.Message + "/" + ex.Source + "/" + ex.StackTrace); 
				break; 
			} 
		} 
	} 
	public static SourceData FindSourceByName(string sourceData) 
	{ 
		return sourceImporter.FindSourceByName(sourceData); 
	}

	public static string[] LoadTopicFiles() 
	public static void ImportModSourceSheets(string modId) 
	{
		return PackageIterator.GetFiles("Text/Help/_topics.txt").SelectMany((FileInfo f) => IO.LoadTextArray(f.FullName)).ToArray(); 
		try
		{ 
			SourceCache.InvalidateCacheVersion(); 
			EMod valueOrDefault = ModManager.Instance.MappedPackages.GetValueOrDefault(modId); 
			if (valueOrDefault == null) 
			{ 
				return; 
			} 
			List<string> list = new List<string>(); 
			foreach (FileInfo sourceSheet in valueOrDefault.Mapping.SourceSheets) 
			{ 
				sourceImporter.fileProviders[sourceSheet.FullName] = valueOrDefault; 
				list.Add(sourceSheet.FullName); 
			} 
			sourceImporter.ImportFilesCached(list); 
			if (ModManagerCore.enableSheetCaching) 
			{ 
				SourceCache.FinalizeCache(); 
			} 
			SourceCache.InvalidateCacheBlobs(); 
			SourceCache.ClearDetail(); 
			UnityEngine.Debug.Log("#source finished importing workbooks from " + modId); 
		} 
		catch (Exception exception) 
		{ 
			UnityEngine.Debug.LogException(exception); 
		} 
	} 
	public static void ImportAllModSourceSheets() 
	{ 
		try
		{ 
			SourceCache.InvalidateCacheVersion(); 
			SourceImporter.HotInit(new SourceData[2] 
			{ 
				EClass.sources.elements, 
				EClass.sources.materials 
			}); 
			List<string> list = new List<string>(); 
			foreach (BaseModPackage package in ModManager.Instance.packages) 
			{ 
				if (!(package is ModPackage modPackage) || !package.activated || package.id == null) 
				{ 
					continue; 
				} 
				foreach (FileInfo sourceSheet in modPackage.Mapping.SourceSheets) 
				{ 
					if (!sourceSheet.Name.StartsWith(".") && !sourceSheet.Name.Contains('~')) 
					{ 
						sourceImporter.fileProviders[sourceSheet.FullName] = modPackage; 
						list.Add(sourceSheet.FullName); 
					} 
				} 
			} 
			sourceImporter.ImportFilesCached(list); 
			if (ModManagerCore.enableSheetCaching) 
			{ 
				SourceCache.FinalizeCache(); 
			} 
			SourceCache.InvalidateCacheBlobs(); 
			SourceCache.ClearDetail(); 
		} 
		catch (Exception message) 
		{ 
			UnityEngine.Debug.LogError(message); 
		} 
		UnityEngine.Debug.Log("#source finished importing workbooks"); 
	} 
	public static string ExportSourceDataCsv(string sourceData, string delimiter = ",") 
	{ 
		SourceData sourceData2 = FindSourceByName(sourceData); 
		if (sourceData2 == null) 
		{ 
			return ""; 
		} 
		IReadOnlyDictionary<string, string> typeMapping = sourceData2.GetTypeMapping(); 
		IReadOnlyDictionary<string, int> rowMapping = sourceData2.GetRowMapping(); 
		StringBuilder stringBuilder = new StringBuilder(); 
		stringBuilder.AppendLine(string.Join(delimiter, rowMapping.Keys)); 
		stringBuilder.AppendLine(string.Join(delimiter, rowMapping.Keys.Select((string k) => typeMapping[k]))); 
		(string, string)[] array = (from kv in rowMapping 
			orderby kv.Value 
			select (Key: kv.Key, typeMapping[kv.Key])).ToArray(); 
		SourceData.BaseRow[] array2 = sourceData2.ExportRows(); 
		foreach (SourceData.BaseRow baseRow in array2) 
		{ 
			List<string> list = new List<string>(); 
			(string, string)[] array3 = array; 
			for (int j = 0; j < array3.Length; j++) 
			{ 
				(string, string) tuple = array3[j]; 
				string item = tuple.Item1; 
				string item2 = tuple.Item2; 
				object value = baseRow.GetRowFields()[item].GetValue(baseRow); 
				object obj = value; 
				IEnumerable enumerable; 
				if (!(obj is int[] array4)) 
				{ 
					if (!(obj is int key)) 
					{ 
						if (obj is string item3) 
						{ 
							list.Add(item3); 
							continue; 
						} 
						enumerable = obj as IEnumerable; 
						if (enumerable != null) 
						{ 
							goto IL_0221; 
						} 
					} 
					else if (item2 == "element_id") 
					{ 
						list.Add(EClass.sources.elements.map[key].alias); 
						continue; 
					} 
					list.Add(value.ToString()); 
					continue; 
				} 
				if (!(item2 == "elements")) 
				{ 
					enumerable = (IEnumerable)obj; 
					goto IL_0221; 
				} 
				List<string> list2 = new List<string>(); 
				for (int l = 0; l < array4.Length - 1; l += 2) 
				{ 
					string alias = EClass.sources.elements.map[array4[l]].alias; 
					string text = array4[l + 1].ToString(); 
					list2.Add(alias + "/" + text); 
				} 
				string item4 = string.Join(',', list2); 
				list.Add(item4); 
				continue; 
				IL_0221: 
				string item5 = string.Join(',', enumerable.OfType<object>()); 
				list.Add(item5); 
			} 
			stringBuilder.AppendLine(string.Join(delimiter, list.Select((string f) => "\"" + f.RemoveNewline() + "\""))); 
		} 
		return stringBuilder.ToString(); 
	} 
	public static void ExportAllSourceDataCsv(string dir) 
	{ 
		IO.CreateDirectory(dir); 
		foreach (string key in SourceMapping.Keys) 
		{ 
			File.WriteAllText(Path.Combine(dir, key + ".csv"), ExportSourceDataCsv(key)); 
		} 
	} 
	public static string ExportSourceDataJson(string sourceData, Formatting format = Formatting.Indented) 
	{ 
		SourceData sourceData2 = FindSourceByName(sourceData); 
		if (sourceData2 == null) 
		{ 
			return ""; 
		} 
		return JsonConvert.SerializeObject(sourceData2.ExportRows(), format); 
	} 
	public static void ExportAllSourceDataJson(string dir) 
	{ 
		IO.CreateDirectory(dir); 
		foreach (string key in SourceMapping.Keys) 
		{ 
			File.WriteAllText(Path.Combine(dir, key + ".json"), ExportSourceDataJson(key)); 
		} 
	}
}

POLICY โ€‹

public class POLICY

cs

	public const int legendary_heirloom = 2821;

	public const int livestock_priv = 2715; 
	public const int forcePanty = 2712; 

	public const int license_furniture = 2819;

public class POLICY

cs

	public const int incomeTransfer = 2711;

	public const int forcePanty = 2712; 
	public const int livestock_priv = 2715; 

	public const int home_discount = 2800;

public class POLICY

cs

	public static readonly int[] IDS = new int[51]
	{
		2822, 2828, 2827, 2826, 2825, 2824, 2823, 2821, 2715, 2819, 
		2822, 2828, 2827, 2826, 2825, 2824, 2823, 2821, 2712, 2819, 
		2700, 2516, 2515, 2514, 2513, 2507, 2820, 2500, 2701, 2501,
		2503, 2504, 2505, 2512, 2511, 2510, 2509, 2508, 2502, 2702,
		2506, 2704, 2703, 2711, 2712, 2800, 2810, 2811, 2812, 2813, 
		2506, 2704, 2703, 2711, 2715, 2800, 2810, 2811, 2812, 2813, 
		2814, 2710, 2816, 2817, 2818, 2709, 2708, 2707, 2706, 2705,
		2815
	};

Player โ€‹

public void OnStartNewGame()

cs
	chara.things.DestroyAll();
	CreateEquip();
	dateTravel = EClass.world.date.GetRaw();
	uidLastTravelZone = EClass.pc.currentZone.uid; 
	uidLastTravelZone = EClass.pc.currentZone?.uid ?? 0; 
	GenerateBackgroundText();
	EClass.pc.elements.CheckSkillActions();
	EClass.pc.hunger.value = 30;

public Thing DropReward(Thing t, bool silent = false)

cs

	public bool TooHeavyToMove()
	{
		if (!EClass.debug.ignoreWeight && EClass.pc.burden.GetPhase() == 4) 
		if (!EClass.debug.ignoreWeight && EClass.pc.burden.GetPhase() == 4 && !EClass.pc.HasElement(493)) 
		{
			Msg.Say("tooHeavyToMove");
			EClass.pc.renderer.NextFrame();

Portrait โ€‹

public void SetChara(Chara c, PCCData pccData = null)

cs
		imageChara.SetNativeSize();
		if (fixSpritePos)
		{
			imageChara.transform.localScale = (c.IsPCC ? new Vector3(1.3f, 1.4f, 1f) : new Vector3(1f, 1f, 1f)) * charaScale; 
			imageChara.rectTransform.pivot = (c.IsPCC ? new Vector2(0.5f, 0.3f) : new Vector2(0.5f, 0.2f)); 
			imageChara.rectTransform.anchoredPosition = (c.IsPCC ? new Vector2(-25f, 20f) : new Vector2(-25f, 20f)); 
			if (c.IsPCC) 
			{ 
				imageChara.rectTransform.localScale = new Vector3(1.3f, 1.4f, 1f) * charaScale; 
				imageChara.rectTransform.anchoredPosition = new Vector2(-25f, 10f); 
				imageChara.rectTransform.pivot = new Vector2(0.5f, 0.3f); 
			} 
			else
			{ 
				imageChara.rectTransform.localScale = Vector3.one * charaScale; 
				imageChara.rectTransform.anchoredPosition = new Vector2(-25f, 28f); 
				imageChara.rectTransform.pivot = c.source.renderData.imagePivot; 
				SourcePref pref = c.Pref; 
				float num = imageChara.sprite.rect.height / 128f; 
				imageChara.rectTransform.localPosition += new Vector3(pref.pivotX, (float)pref.pivotY * num, 0f); 
			} 
		}
	}
	if ((bool)imageFaith)

RefReligion โ€‹

using System.Collections.Generic;

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

public class RefReligion : EClass

public class RefReligion : EClass

cs

	private Religion _religion;

	public Religion Instance => _religion ?? (_religion = EClass.game.religions.dictAll[uid]); 
	public Religion Instance => _religion ?? (_religion = EClass.game.religions.dictAll.GetValueOrDefault(uid, EClass.game.religions.Eyth)); 

	public RefReligion()
	{

Religion โ€‹

public enum ConvertType

cs

	public static Religion recentWrath;

	public SourceReligion.Row _source; 
	private SourceReligion.Row _source; 

	public virtual string id => "";

	public virtual bool IsAvailable => false;

	public string Name => source.GetName(); 
	public virtual string Name => source.GetName(); 

	public SourceReligion.Row source => _source ?? (_source = EClass.sources.religions.map[id]); 
	public SourceReligion.Row source 
	{ 
		get 
		{ 
			SourceReligion.Row row = _source; 
			if (row == null) 
			{ 
				SourceReligion.Row obj = EClass.sources.religions.map.TryGetValue(id) ?? EClass.sources.religions.map["eyth"]; 
				SourceReligion.Row row2 = obj; 
				_source = obj; 
				row = row2; 
			} 
			return row; 
		} 
	} 

	public string NameShort => source.GetTextArray("name2")[1]; 
	public virtual string NameShort => source.GetTextArray("name2")[1]; 

	public string NameDomain => source.GetTextArray("name2")[0]; 
	public virtual string NameDomain => source.GetTextArray("name2")[0]; 

	public string TextType => ("sub_" + source.type).lang(); 
	public virtual string TextType => ("sub_" + source.type).lang(); 

	public string TextGodGender => source.GetText("textType"); 
	public virtual string TextGodGender => source.GetText("textType"); 

	public string TextMood => GetTextTemper(); 
	public virtual string TextMood => GetTextTemper(); 

	public bool IsEyth => id == "eyth";

public virtual SourceElement.Row GetFeat(int i)

cs
		return EClass.sources.elements.alias["featGod_" + id + i];
	}

	public void Init() 
	public virtual void Init() 
	{
		relation = source.relation;
	}

	public void OnLoad() 
	public virtual void OnLoad() 
	{
	}

	public void OnAdvanceDay() 
	public virtual void OnAdvanceDay() 
	{
	}

	public Sprite GetSprite() 
	public virtual Sprite GetSprite() 
	{
		return ResourceCache.Load<Sprite>("Media/Graphics/Image/Faction/" + source.id) ?? ResourceCache.Load<Sprite>("Media/Graphics/Image/Faction/eyth");
	}

	public void SetTextRelation(UIText text) 
	public virtual void SetTextRelation(UIText text) 
	{
		if (relation > 100)
		{

public void SetTextRelation(UIText text)

cs
		}
	}

	public string GetTextBenefit() 
	public virtual string GetTextBenefit() 
	{
		string text = "<color=green>";
		for (int i = 0; i < source.elements.Length; i += 2)

public string GetTextBenefit()

cs
		return source.GetText("textBenefit") + Environment.NewLine + Environment.NewLine + (IsEyth ? "" : "textBenefit".lang(text));
	}

	public string GetTextTemper(int _temper = -99999) 
	public virtual string GetTextTemper(int _temper = -99999) 
	{
		if (IsEyth)
		{

public string GetTextTemper(int _temper = -99999)

cs
		_temper = mood;
	}
	string[] list = Lang.GetList("temper");
	if (_temper <= -85) 
	{ 
		return list[0].ToTitleCase().TagColor(FontColor.Bad); 
	} 
	if (_temper <= -45) 
	{ 
		return list[1].ToTitleCase().TagColor(FontColor.Bad); 
	} 
	if (_temper <= -15)
	{
		return list[2].ToTitleCase(); 
	} 
	if (_temper < 15) 
	{ 
		return list[3].ToTitleCase(); 
		if (_temper > -85) 
		{ 
			if (_temper <= -45) 
			{ 
				return list[1].ToTitleCase().TagColor(FontColor.Bad); 
			} 
			return list[2].ToTitleCase(); 
		} 
		return list[0].ToTitleCase().TagColor(FontColor.Bad); 
	}
	if (_temper < 45)
	{
		if (_temper < 15) 
		{ 
			return list[3].ToTitleCase(); 
		} 
		return list[4].ToTitleCase();
	}
	if (_temper < 85)

public string GetTextTemper(int _temper = -99999)

cs
		return list[6].ToTitleCase().TagColor(FontColor.Good);
	}

	public void Revelation(string idTalk, int chance = 100) 
	public virtual void Revelation(string idTalk, int chance = 100) 
	{
		if (!IsEyth && EClass.rnd(100) <= chance)
		{

public void Revelation(string idTalk, int chance = 100)

cs
		}
	}

	public void Talk(string idTalk, Card c = null, Card agent = null) 
	public virtual void Talk(string idTalk, Card c = null, Card agent = null) 
	{
		Msg.SetColor(Msg.colors.TalkGod);
		Msg.Say("<i>" + GetGodTalk(idTalk) + " </i>", c ?? EClass.pc);
	}

	public string GetGodTalk(string suffix) 
	public virtual string GetGodTalk(string idTalk) 
	{
		return EClass.sources.dataGodTalk.GetText(id, suffix).Split(Environment.NewLine.ToCharArray()).RandomItem(); 
		return MOD.listGodTalk.GetTalk(id, idTalk); 
	}

	public virtual int GetOfferingMtp(Thing t)

public virtual int GetOfferingMtp(Thing t)

cs
		return 0;
	}

	public int GetOfferingValue(Thing t, int num = -1) 
	public virtual int GetOfferingValue(Thing t, int num = -1) 
	{
		t.CheckJustCooked();
		if (num == -1)

void SetValue(SourceCategory.Row cat, int mtp)

cs
		}
	}

	public int GetGiftRank() 
	public virtual int GetGiftRank() 
	{
		if (IsEyth || source.rewards.Length == 0)
		{

public int GetGiftRank()

cs
		return -1;
	}

	public bool TryGetGift() 
	public virtual bool TryGetGift() 
	{
		int num = GetGiftRank();
		if (num == -1)

public bool TryGetGift()

cs
		string[] array2 = array;
		foreach (string text in array2)
		{
			Reforge(text, point, text == array[0]); 
			EClass.game.religions.Reforge(text, point, text == array[0]); 
		}
		giftRank = 2;
		return true;

public bool TryGetGift()

cs
		}
	}

	public static Religion GetArtifactDeity(string id) 
	public virtual void OnReforge(Thing t) 
	{
		return id switch
		{ 
			"gun_mani" => EClass.game.religions.Machine,  
			"cloak_mani" => EClass.game.religions.Machine,  
			"scythe_kumi" => EClass.game.religions.Harvest,  
			"blunt_earth" => EClass.game.religions.Earth,  
			"luckydagger" => EClass.game.religions.Luck,  
			"staff_element" => EClass.game.religions.Element,  
			"windbow" => EClass.game.religions.Wind,  
			"shirt_wind" => EClass.game.religions.Wind,  
			"pole_holy" => EClass.game.religions.Healing,  
			"sword_muramasa2" => EClass.game.religions.MoonShadow,  
			"kogitsunemaru" => EClass.game.religions.Trickery,  
			"warmonger" => EClass.game.religions.Strife,  
			_ => null,  
		}; 
		t.c_idDeity = id; 
		foreach (Element value in t.elements.dict.Values) 
		{ 
			if (IsFaithElement(value)) 
			{ 
				value.vExp = -1; 
			} 
		} 
	}

	public bool IsValidArtifact(string id) 
	public virtual bool IsValidArtifact(string id) 
	{
		return this == GetArtifactDeity(id); 
		return false; 
	}

	public static Thing Reforge(string id, Point pos = null, bool first = true) 
	public virtual bool IsFaithElement(Element e) 
	{
		if (pos == null) 
		{ 
			pos = EClass.pc.pos.Copy(); 
		} 
		pos.Set(pos.GetNearestPoint(allowBlock: false, allowChara: false, allowInstalled: false, ignoreCenter: true) ?? pos); 
		Thing thing = ThingGen.Create(id); 
		foreach (Element value in thing.elements.dict.Values) 
		{ 
			if (value.id == 66 || value.id == 67 || value.id == 64 || value.id == 65 || value.id == 92) 
			{ 
				continue; 
			} 
			switch (id) 
			{ 
			case "gun_mani": 
				thing.c_idDeity = EClass.game.religions.Machine.id; 
				break; 
			case "cloak_mani": 
				if (value.id == 427 || value.id == 957 || value.id == 105 || value.id == 466 || value.id == 664) 
				{ 
					value.vExp = -1; 
				} 
				thing.c_idDeity = EClass.game.religions.Machine.id; 
				break; 
			case "scythe_kumi": 
				if (value.id == 6650 || value.id == 480 || value.id == 959 || value.id == 428 || value.id == 640 || value.id == 665) 
				{ 
					value.vExp = -1; 
				} 
				thing.c_idDeity = EClass.game.religions.Harvest.id; 
				break; 
			case "blunt_earth": 
				if (value.id == 70 || value.id == 55 || value.id == 56 || value.id == 954 || value.id == 423 || value.id == 421) 
				{ 
					value.vExp = -1; 
				} 
				thing.c_idDeity = EClass.game.religions.Earth.id; 
				break; 
			case "luckydagger": 
				if (value.id != 426) 
				{ 
					value.vExp = -1; 
				} 
				thing.c_idDeity = EClass.game.religions.Luck.id; 
				break; 
			case "staff_element": 
				if (value.id == 411 || (value is Resistance && value.id != 959)) 
				{ 
					value.vExp = -1; 
				} 
				thing.c_idDeity = EClass.game.religions.Element.id; 
				break; 
			case "windbow": 
				thing.c_idDeity = EClass.game.religions.Wind.id; 
				break; 
			case "shirt_wind": 
				if (!(value is Resistance) && value.id != 226 && value.id != 152 && value.id != 77) 
				{ 
					value.vExp = -1; 
				} 
				thing.c_idDeity = EClass.game.religions.Wind.id; 
				break; 
			case "pole_holy": 
				if (value.id == 60 || value.id == 461 || value.id == 423) 
				{ 
					value.vExp = -1; 
				} 
				thing.c_idDeity = EClass.game.religions.Healing.id; 
				break; 
			case "sword_muramasa2": 
				if (value.id == 401 || value.id == 916 || value.id == 661) 
				{ 
					value.vExp = -1; 
				} 
				thing.c_idDeity = EClass.game.religions.MoonShadow.id; 
				break; 
			case "kogitsunemaru": 
				if (value.id != 656) 
				{ 
					value.vExp = -1; 
				} 
				thing.c_idDeity = EClass.game.religions.Trickery.id; 
				break; 
			case "warmonger": 
				if (value.id == 468 || value.id == 423 || value.id == 463 || value.id == 460 || value.id == 464 || value.id == 465) 
				{ 
					value.vExp = -1; 
				} 
				thing.c_idDeity = EClass.game.religions.Strife.id; 
				break; 
			} 
		} 
		EClass._zone.AddCard(thing, pos); 
		pos.PlayEffect("aura_heaven"); 
		if (first) 
		{ 
			pos.PlaySound("godbless"); 
		} 
		return thing; 
		return false; 
	} 
	public virtual string[] GetValidArtifacts() 
	{ 
		return Array.Empty<string>(); 
	}

	public virtual void OnBecomeBranchFaith()
	{
	}

	public void JoinFaith(Chara c, ConvertType type = ConvertType.Default) 
	public virtual void JoinFaith(Chara c, ConvertType type = ConvertType.Default) 
	{
		if (!c.IsPC)
		{

public void JoinFaith(Chara c, ConvertType type = ConvertType.Default)

cs
		}
	}

	public void LeaveFaith(Chara c, Religion newFaith, ConvertType type) 
	public virtual void LeaveFaith(Chara c, Religion newFaith, ConvertType type) 
	{
		if (!IsEyth) 
		bool flag = (newFaith == EClass.game.religions.Trickery && this == EClass.game.religions.MoonShadow) || (newFaith == EClass.game.religions.MoonShadow && this == EClass.game.religions.Trickery); 
		if (c.IsPC) 
		{
			bool flag = (newFaith == EClass.game.religions.Trickery && this == EClass.game.religions.MoonShadow) || (newFaith == EClass.game.religions.MoonShadow && this == EClass.game.religions.Trickery); 
			if (c.IsPC) 
			Msg.Say("worship2"); 
			if (!flag && type != ConvertType.Campaign) 
			{
				Msg.Say("worship2"); 
				if (!flag && type != ConvertType.Campaign) 
				{ 
					Punish(c); 
				} 
			} 
			if (flag) 
			{ 
				Talk("regards"); 
				c.elements.SetBase(85, c.Evalue(85) / 2); 
			} 
			else
			{ 
				c.elements.SetBase(85, 0); 
				Punish(c); 
			}
		}
		if (flag) 
		{ 
			Talk("regards"); 
			c.elements.SetBase(85, c.Evalue(85) / 2); 
		} 
		else
		{ 
			c.elements.SetBase(85, 0); 
		} 
		if (c.IsPC)
		{
			EClass.pc.faction.charaElements.OnLeaveFaith();

public void LeaveFaith(Chara c, Religion newFaith, ConvertType type)

cs
		c.RefreshFaithElement();
	}

	public void Punish(Chara c) 
	public virtual void Punish(Chara c) 
	{
		if (c.mimicry != null)
		{

public void Punish(Chara c)

cs
		c.AddCondition<ConWrath>(2000 + (c.IsPC ? (EClass.pc.c_daysWithGod * 20) : 0));
	}

	public void PunishTakeOver(Chara c) 
	public virtual void PunishTakeOver(Chara c) 
	{
		if (c.mimicry != null)
		{

public virtual void OnLeaveFaith()

cs
	{
	}

	public void OnChangeHour() 
	public virtual void OnChangeHour() 
	{
		if (IsEyth)
		{

+ReligionCustom โ€‹

File Created
cs
using UnityEngine;

public class ReligionCustom : Religion
{
	public CustomReligionContent content;

	public override string id => content?.SourceId ?? "";

	public override bool CanJoin => content?.canJoin ?? true;

	public override bool IsMinorGod => content?.isMinorGod ?? false;

	public override bool IsAvailable => true;

	public override Sprite GetSprite()
	{
		return ModUtil.LoadSprite(id, null, null, 150, 200) ?? base.GetSprite();
	}

	public override bool IsValidArtifact(string thingId)
	{
		return content.artifacts.Contains(thingId);
	}

	public override string[] GetValidArtifacts()
	{
		return content.artifacts.ToArray();
	}

	public override bool IsFaithElement(Element e)
	{
		return content.elements.Contains(e.source.alias);
	}

	public override int GetOfferingMtp(Thing t)
	{
		if (content.offeringMtp.TryGetValue(t.id, out var value))
		{
			return value;
		}
		return base.GetOfferingMtp(t);
	}

	public override int GetOfferingValue(Thing t, int num = -1)
	{
		if (num == -1)
		{
			num = t.Num;
		}
		int offeringValue = base.GetOfferingValue(t, num);
		if (content.offeringValue.TryGetValue(t.id, out var value))
		{
			var args = new
			{
				@base = offeringValue,
				lv = t.LV,
				rarity = t.rarityLv
			};
			if (value.TryEvaluateAsCalc(out int result, (object)args))
			{
				return result;
			}
		}
		return offeringValue;
	}

	public override void Punish(Chara c)
	{
		if (content.noPunish)
		{
			c.SayNothingHappans();
		}
		else
		{
			base.Punish(c);
		}
	}

	public override void PunishTakeOver(Chara c)
	{
		if (content.noPunishTakeover)
		{
			c.SayNothingHappans();
		}
		else
		{
			base.PunishTakeOver(c);
		}
	}
}

ReligionEarth โ€‹

public class ReligionEarth : Religion

cs
	public override void OnBecomeBranchFaith()
	{
	}
	public override bool IsValidArtifact(string id) 
	{ 
		return id == "blunt_earth"; 
	} 
	public override string[] GetValidArtifacts() 
	{ 
		return new string[1] { "blunt_earth" }; 
	} 
	public override bool IsFaithElement(Element e) 
	{ 
		switch (e.id) 
		{ 
		case 55: 
		case 56: 
		case 70: 
		case 421: 
		case 423: 
		case 954: 
			return true; 
		default: 
			return false; 
		} 
	} 
}

ReligionElement โ€‹

public class ReligionElement : Religion

cs
public class ReligionElement : Religion
{
	public override string id => "element";
	public override bool IsValidArtifact(string id) 
	{ 
		return id == "staff_element"; 
	} 
	public override string[] GetValidArtifacts() 
	{ 
		return new string[1] { "staff_element" }; 
	} 
	public override bool IsFaithElement(Element e) 
	{ 
		if (e.id != 411) 
		{ 
			if (e is Resistance) 
			{ 
				return e.id != 959; 
			} 
			return false; 
		} 
		return true; 
	} 
}

+ReligionExtension โ€‹

File Created
cs
public static class ReligionExtension
{
	public static void SpawnAltar(this Religion religion)
	{
		Thing thing = ThingGen.Create("altar");
		(thing.trait as TraitAltar)?.SetDeity(religion.id);
		Point nearestPoint = EClass.pc.pos.GetNearestPoint(allowBlock: true, allowChara: false, allowInstalled: false);
		if (nearestPoint != null)
		{
			EClass._zone.AddCard(thing, nearestPoint).Install();
		}
	}
}

ReligionEyth โ€‹

public class ReligionEyth : Religion

cs
public class ReligionEyth : Religion
{
	public override string id => "eyth";
	public override void LeaveFaith(Chara c, Religion newFaith, ConvertType type) 
	{ 
		if (c.IsPC) 
		{ 
			EClass.pc.faction.charaElements.OnLeaveFaith(); 
		} 
		OnLeaveFaith(); 
		c.RefreshFaithElement(); 
	} 
}

ReligionHarvest โ€‹

public class ReligionHarvest : Religion

cs
public class ReligionHarvest : Religion
{
	public override string id => "harvest";
	public override bool IsValidArtifact(string id) 
	{ 
		return id == "scythe_kumi"; 
	} 
	public override string[] GetValidArtifacts() 
	{ 
		return new string[1] { "scythe_kumi" }; 
	} 
	public override bool IsFaithElement(Element e) 
	{ 
		switch (e.id) 
		{ 
		case 428: 
		case 480: 
		case 640: 
		case 665: 
		case 959: 
		case 6650: 
			return true; 
		default: 
			return false; 
		} 
	} 
}

ReligionHealing โ€‹

public class ReligionHealing : Religion

cs
	public override void OnBecomeBranchFaith()
	{
	}
	public override bool IsValidArtifact(string id) 
	{ 
		return id == "pole_holy"; 
	} 
	public override string[] GetValidArtifacts() 
	{ 
		return new string[1] { "pole_holy" }; 
	} 
	public override bool IsFaithElement(Element e) 
	{ 
		int num = e.id; 
		if (num == 60 || num == 423 || num == 461) 
		{ 
			return true; 
		} 
		return false; 
	} 
}

ReligionLuck โ€‹

public class ReligionLuck : Religion

cs
	public override void OnBecomeBranchFaith()
	{
	}
	public override bool IsValidArtifact(string id) 
	{ 
		return id == "luckydagger"; 
	} 
	public override string[] GetValidArtifacts() 
	{ 
		return new string[1] { "luckydagger" }; 
	} 
	public override bool IsFaithElement(Element e) 
	{ 
		return e.id != 426; 
	} 
}

ReligionMachine โ€‹

public class ReligionMachine : Religion

cs
public class ReligionMachine : Religion
{
	public override string id => "machine";
	public override void OnReforge(Thing t) 
	{ 
		t.c_idDeity = id; 
		if (t.id == "gun_mani") 
		{ 
			return; 
		} 
		foreach (Element value in t.elements.dict.Values) 
		{ 
			if (IsFaithElement(value)) 
			{ 
				value.vExp = -1; 
			} 
		} 
	} 
	public override bool IsValidArtifact(string id) 
	{ 
		if (!(id == "gun_mani")) 
		{ 
			return id == "cloak_mani"; 
		} 
		return true; 
	} 
	public override string[] GetValidArtifacts() 
	{ 
		return new string[2] { "gun_mani", "cloak_mani" }; 
	} 
	public override bool IsFaithElement(Element e) 
	{ 
		switch (e.id) 
		{ 
		case 105: 
		case 427: 
		case 466: 
		case 664: 
		case 957: 
			return true; 
		default: 
			return false; 
		} 
	} 
}

ReligionManager โ€‹

public void SetOwner()

cs
			Eyth, Wind, Earth, Healing, Luck, Machine, Element, Harvest, Oblivion, Harmony,
			Trickery, MoonShadow, Strife
		};
		BaseModManager.PublishEvent("elin.religion_importing", list); 
		foreach (Religion item in list)
		{
			dictAll.Add(item.id, item); 
			dictAll[item.id] = item; 
		}
	}

public void OnLoad()

cs

	public Religion Find(string id)
	{
		foreach (Religion value in dictAll.Values) 
		{ 
			if (value.id == id) 
			{ 
				return value; 
			} 
		} 
		return null; 
		return dictAll.TryGetValue(id); 
	}

	public Religion GetRandomReligion(bool onlyJoinable = true, bool includeMinor = false)

public Religion GetRandomReligion(bool onlyJoinable = true, bool includeMinor =

cs
		Debug.Log("hai");
		return true;
	}
	public Religion GetArtifactDeity(string id) 
	{ 
		return list.LastOrDefault((Religion a) => a.IsValidArtifact(id)); 
	} 
	public Thing Reforge(string id, Point pos = null, bool first = true) 
	{ 
		if (pos == null) 
		{ 
			pos = EClass.pc.pos.Copy(); 
		} 
		pos.Set(pos.GetNearestPoint(allowBlock: false, allowChara: false, allowInstalled: false, ignoreCenter: true) ?? pos); 
		Thing thing = ThingGen.Create(id); 
		GetArtifactDeity(id)?.OnReforge(thing); 
		EClass._zone.AddCard(thing, pos); 
		pos.PlayEffect("aura_heaven"); 
		if (first) 
		{ 
			pos.PlaySound("godbless"); 
		} 
		return thing; 
	} 
}

ReligionMoonShadow โ€‹

public override int GetOfferingMtp(Thing t)

cs
			return 0;
		}
	}
	public override bool IsValidArtifact(string id) 
	{ 
		return id == "sword_muramasa2"; 
	} 
	public override string[] GetValidArtifacts() 
	{ 
		return new string[1] { "sword_muramasa2" }; 
	} 
	public override bool IsFaithElement(Element e) 
	{ 
		int num = e.id; 
		if (num == 401 || num == 661 || num == 916) 
		{ 
			return true; 
		} 
		return false; 
	} 
}

ReligionStrife โ€‹

public class ReligionStrife : ReligionMinor

cs
public class ReligionStrife : ReligionMinor
{
	public override string id => "strife";
	public override bool IsValidArtifact(string id) 
	{ 
		return id == "warmonger"; 
	} 
	public override string[] GetValidArtifacts() 
	{ 
		return new string[1] { "warmonger" }; 
	} 
	public override bool IsFaithElement(Element e) 
	{ 
		switch (e.id) 
		{ 
		case 423: 
		case 460: 
		case 463: 
		case 464: 
		case 465: 
		case 468: 
			return true; 
		default: 
			return false; 
		} 
	} 
}

ReligionTrickery โ€‹

public override int GetOfferingMtp(Thing t)

cs
			return 0;
		}
	}
	public override bool IsValidArtifact(string id) 
	{ 
		return id == "kogitsunemaru"; 
	} 
	public override string[] GetValidArtifacts() 
	{ 
		return new string[1] { "kogitsunemaru" }; 
	} 
	public override bool IsFaithElement(Element e) 
	{ 
		return e.id != 656; 
	} 
}

ReligionWind โ€‹

public class ReligionWind : Religion

cs
public class ReligionWind : Religion
{
	public override string id => "wind";
	public override void OnReforge(Thing t) 
	{ 
		t.c_idDeity = id; 
		if (t.id == "windbow") 
		{ 
			return; 
		} 
		foreach (Element value in t.elements.dict.Values) 
		{ 
			if (IsFaithElement(value)) 
			{ 
				value.vExp = -1; 
			} 
		} 
	} 
	public override bool IsValidArtifact(string id) 
	{ 
		if (!(id == "windbow")) 
		{ 
			return id == "shirt_wind"; 
		} 
		return true; 
	} 
	public override string[] GetValidArtifacts() 
	{ 
		return new string[2] { "windbow", "shirt_wind" }; 
	} 
	public override bool IsFaithElement(Element e) 
	{ 
		if (!(e is Resistance) && e.id != 226 && e.id != 152) 
		{ 
			return e.id != 77; 
		} 
		return false; 
	} 
}

RenderRow โ€‹

public void SetRenderData()

cs
	{
		this.renderData = ResourceCache.Load<RenderData>(pathRenderData + idRenderData) ?? defaultRenderData;
	}
	if (!Application.isEditor && pref == null) 
	if (!Application.isEditor && !aliasPref.IsEmpty()) 
	{
		if (aliasPref.IsEmpty()) 
		{ 
			pref = new SourcePref(); 
		} 
		else
		{ 
			pref = sources.cards.map[aliasPref].pref; 
		} 
		pref = sources.cards.map[aliasPref].pref; 
	}
	if (pref == null)
	{

SKILL โ€‹

public class SKILL

cs

	public const int weaponCrossbow = 109;

	public const int climbing = 242; 
	public const int weaponScythe = 110; 

	public const int weaponBlunt = 111; 
	public const int climbing = 242; 

	public const int armorHeavy = 122;

public class SKILL

cs

	public const int fishing = 245;

	public const int weaponScythe = 110; 
	public const int weaponBlunt = 111; 

	public const int carpentry = 255;

public class SKILL

cs

	public static readonly int[] IDS = new int[134]
	{
		120, 50, 108, 109, 242, 111, 122, 132, 130, 241, 
		120, 50, 108, 109, 110, 242, 122, 132, 130, 241, 
		240, 237, 235, 230, 227, 226, 220, 123, 210, 200,
		152, 151, 150, 135, 134, 133, 131, 207, 225, 92,
		106, 71, 70, 68, 67, 66, 65, 72, 64, 61,
		60, 57, 56, 55, 51, 62, 73, 74, 75, 105,
		104, 103, 102, 101, 100, 94, 93, 91, 90, 80,
		79, 78, 77, 76, 107, 245, 110, 255, 916, 917, 
		79, 78, 77, 76, 107, 245, 111, 255, 916, 917, 
		918, 919, 921, 922, 923, 924, 925, 926, 950, 951,
		952, 953, 915, 954, 956, 957, 958, 959, 960, 961,
		962, 963, 964, 250, 972, 971, 970, 965, 955, 914,

ShopType โ€‹

public enum ShopType

cs
	Curry,
	KeeperOfGarden,
	TravelMerchant,
	TravelMerchant2 
	TravelMerchant2, 
	CustomContent 
}

SourceImporter โ€‹

public SourceData FindSourceByName(string name)

cs
			int count = list2.Count;
			Debug.Log("#source loading sheet " + sheetName);
			ExcelParser.path = file;
			ERROR.lastImported = 0; 
			string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(file);
			if (!sourceData.ImportData(sheet, fileNameWithoutExtension, overwrite: true))
			{
				throw new SourceParseException("#source failed to import data " + sourceData.GetType().Name + ":" + fileNameWithoutExtension + "/" + sheetName);
			}
			SourceData.BaseRow[] item = Array.Empty<SourceData.BaseRow>(); 
			int num = ERROR.msg.Split('/')[^1].ToInt(); 
			if (num > 0) 
			if (ERROR.lastImported > 0) 
			{
				item = list2.OfType<SourceData.BaseRow>().Skip(count).Take(num) 
				SourceData.BaseRow[] item = list2.OfType<SourceData.BaseRow>().Skip(count).Take(ERROR.lastImported) 
					.ToArray();
				return (sourceData, item); 
			}
			return (sourceData, item); 
		}
		catch (Exception arg)
		{
			Debug.LogError($"#source failed to load sheet {sheetName}\n{arg}");
		}
		return (null, null); 
		return (null, Array.Empty<SourceData.BaseRow>()); 
	}

	public IEnumerable<SourceData> ImportFilesCached(IEnumerable<string> imports, bool resetData = true)

where c.IsDirtyOrEmpty

cs
		}
		if (sourceCache.IsDirtyOrEmpty)
		{
			if (dictionary.TryGetValue(sourceCache, out var value2) && value2.Item3.Length != 0) 
			if (!dictionary.TryGetValue(sourceCache, out var value2) || value2.Item3.Length == 0) 
			{
				ISheet[] item = value2.Item3; 
				foreach (ISheet sheet in item) 
				continue; 
			} 
			ISheet[] item = value2.Item3; 
			foreach (ISheet sheet in item) 
			{ 
				SourceData.BaseRow[] item2 = LoadBySheetName(sheet, value2.Item1).Item2; 
				if (!item2.IsEmpty()) 
				{
					SourceData.BaseRow[] item2 = LoadBySheetName(sheet, value2.Item1).Item2; 
					sourceCache.EmplaceCache(sheet.SheetName, item2);
					value?.sourceRows.UnionWith(item2);
					Debug.Log($"#source workbook {arg}:{sheet.SheetName}:{item2.Length}");

SourceManager โ€‹

public class SourceManager : EMono

cs

	public SourceKeyItem keyItems;

	private ExcelData _dataGodTalk; 
	private List<SourceData> list = new List<SourceData>();

	public bool initialized;

	public ExcelData dataGodTalk => _dataGodTalk ?? (_dataGodTalk = new ExcelData(Lang.setting.dir + "Data/god_talk.xlsx", 3)); 
	public void InitLang()
	{
		langGeneral.Init();

public void InitLang()

cs

	public void OnChangeLang()
	{
		_dataGodTalk = null; 
	}

	public void Init()

public void Init()

cs
		}
	}
	BaseModManager.PublishEvent("elin.source.importing");
	if (ModManagerCore.enableSheetLoading) 
	{ 
		ModManager.Instance.ImportAllModSourceSheets(); 
	} 
	elements.Init();
	materials.Init();
	charas.Init();

SourceMaterial โ€‹

public void Init()

cs
		{
			matColors = new MatColors();
			string[] array = tag;
			foreach (string text in array) 
			for (int i = 0; i < array.Length; i++) 
			{
				if (text.StartsWith("addCol")) 
				var (text, s, _) = CustomSourceContent.GetParams(array[i]); 
				switch (text) 
				{
					if (text.Contains("_Main")) 
					{ 
						matColors.main = text.ExtractInBetween('(', ')').ToColor(); 
					} 
					if (text.Contains("_Alt")) 
					{ 
						matColors.alt = text.ExtractInBetween('(', ')').ToColor(); 
					} 
				case "addCol_Main": 
				case "addColorMain": 
					matColors.main = s.ToColor(); 
					break; 
				case "addCol_Alt": 
				case "addColorAlt": 
					matColors.alt = s.ToColor(); 
					break; 
				}
			}
			Core.Instance.Colors.matColors[alias] = matColors;

SpatialManager โ€‹

public void Add(Spatial s)

cs

	public Zone Somewhere => Find("somewhere");

	public List<Zone> Zones => map.Values.Where((Spatial a) => a is Zone).Cast<Zone>().ToList(); 
	public List<Zone> Zones => map.Values.OfType<Zone>().ToList(); 

	public void AssignUID(Spatial s)
	{

public List<Zone> ListReturnLocations()

cs
{
	if (EClass.debug.returnAnywhere)
	{
		List<Zone> list = (from Zone a in map.Values.Where((Spatial a) => a is Zone) 
		List<Zone> list = (from a in map.Values.OfType<Zone>() 
			where a != EClass._zone && (a.IsReturnLocation || a.IsPCFaction || (!(a is Zone_Field) && !a.IsInstance && !a.isRandomSite)) && a.parent == EClass.world.region && !a.source.tag.Contains("closed")
			select a).ToList();
		list.Sort((Zone a, Zone b) => a.GetSortVal() - b.GetSortVal());
		return list;
	}
	List<Zone> list2 = (from Zone a in map.Values.Where((Spatial a) => a is Zone) 
	List<Zone> list2 = (from a in map.Values.OfType<Zone>() 
		where a != EClass._zone && a.IsReturnLocation && a.GetTopZone().visitCount > 0 && (a.GetTopZone().FindDeepestZone() == a || EClass.pc.homeZone == a)
		select a).ToList();
	list2.Sort((Zone a, Zone b) => a.GetSortVal() - b.GetSortVal());

Thing โ€‹

public override string GetExtraName()

cs
		return text;
	}

	public override int GetPrice(CurrencyType currency = CurrencyType.Money, bool sell = false, PriceType priceType = PriceType.Default, Chara c = null) 
	{ 
		int price = base.GetPrice(currency, sell, priceType, c); 
		string str = GetStr("price_calc_override"); 
		if (!str.IsEmpty()) 
		{ 
			var args = new
			{ 
				@base = price, 
				lv = base.LV, 
				rarity = base.rarityLv 
			}; 
			if (str.TryEvaluateAsCalc(out int result, (object)args)) 
			{ 
				return result; 
			} 
		} 
		return price; 
	} 
	public List<Element> ListLimitedValidTraits(bool limit)
	{
		List<Element> list = new List<Element>();

Trait โ€‹

public virtual string IdSoundToggleOff

cs

	public virtual int NumCopyItem => 2 + Mathf.Min(owner.c_invest / 10, 3);

	public virtual ShopType ShopType => ShopType.None; 
	public virtual ShopType ShopType 
	{ 
		get 
		{ 
			if (!owner.GetStr("merchant_override").IsEmpty()) 
			{ 
				return ShopType.CustomContent; 
			} 
			return ShopType.None; 
		} 
	} 

	public virtual CurrencyType CurrencyType => CurrencyType.Money;

public virtual void OnBarter(bool reroll = false)

cs
				break;
			default:
			{
				if (!owner.GetStr("merchant_override").IsEmpty()) 
				{ 
					break; 
				} 
				float num2 = (float)(3 + Mathf.Min(ShopLv / 5, 10)) + Mathf.Sqrt(ShopLv);
				int num3 = 300;
				switch (ShopType)

public virtual void OnBarter(bool reroll = false)

cs
				break;
			}
			}
			foreach (RecipeSource item3 in RecipeManager.list) 
			string str = owner.GetStr("merchant_override"); 
			if (!str.IsEmpty()) 
			{ 
				foreach (Thing item3 in ModUtil.GenerateMerchantStock(owner, str)) 
				{ 
					AddThing(item3); 
				} 
			} 
			string text = ShopType.ToString(); 
			foreach (RecipeSource item4 in RecipeManager.list) 
			{
				if (item3.row.recipeKey.IsEmpty()) 
				if (item4.row.recipeKey.IsEmpty()) 
				{
					continue;
				}
				string[] array2 = item3.row.recipeKey; 
				string[] array2 = item4.row.recipeKey; 
				for (int k = 0; k < array2.Length; k++)
				{
					if (array2[k] == ShopType.ToString()) 
					if (array2[k] == text) 
					{
						NoRestock(ThingGen.CreateRecipe(item3.id)); 
						NoRestock(ThingGen.CreateRecipe(item4.id)); 
						break;
					}
				}

Thing AddThing(Thing _t)

cs
			}
			void NoRestock(Thing _t)
			{
				string text = owner.id; 
				string text2 = owner.id; 
				if (_t.idSkin != 0)
				{
					text = text + "_skin" + _t.idSkin; 
					text2 = text2 + "_skin" + _t.idSkin; 
				}
				HashSet<string> hashSet = EClass.player.noRestocks.TryGetValue(text); 
				HashSet<string> hashSet = EClass.player.noRestocks.TryGetValue(text2); 
				if (hashSet == null)
				{
					hashSet = new HashSet<string>();

void NoRestock(Thing _t)

cs
				if (!hashSet.Contains(_t.trait.IdNoRestock))
				{
					hashSet.Add(_t.trait.IdNoRestock);
					EClass.player.noRestocks[text] = hashSet; 
					EClass.player.noRestocks[text2] = hashSet; 
					_t.SetInt(101, 1);
					AddThing(_t);
				}

+TraitAdventurerCustom โ€‹

File Created
cs
public class TraitAdventurerCustom : TraitAdventurerBacker
{
	public override Adv_Type AdvType => Adv_Type.Adv_Custom;

	public override ShopType ShopType => ShopType.CustomContent;
}

TraitAltar โ€‹

public void OnOffer(Chara c, Thing t)

cs
		{
			_ = t.encLV;
			t.Destroy();
			Thing thing = Religion.Reforge(t.id); 
			Thing thing = EClass.game.religions.Reforge(t.id); 
			if (EClass.pc.IsEyth && EClass.pc.HasElement(1228) && IsEyth)
			{
				thing.c_idDeity = EClass.game.religions.Eyth.id;

TraitBaseSpellbook โ€‹

public override void SetName(ref string s)

cs
		s = "_titled".lang(Lang.GetList("ancientbook")[owner.refVal], s);
		if (owner.isOn)
		{
			s = "_deciphered ".lang(s); 
			s = "_deciphered".lang(s); 
		}
		break;
	case Type.Ero:

TraitChara โ€‹

public enum Adv_Type

cs
		None,
		Adv,
		Adv_Fairy,
		Adv_Backer 
		Adv_Backer, 
		Adv_Custom 
	}

	public static string[] ListRank = new string[7] { "E", "D", "C", "B", "A", "S", "S" };

public override int GetValue()

cs
		return owner.LV * 500 + 3000;
	}

	public int GetAdvRank() 
	public virtual int GetAdvRank() 
	{
		int min = 0;
		switch (owner.id)

public int GetAdvRank()

cs
		return Mathf.Clamp(owner.LV / 10, min, 6);
	}

	public string GetAdvRankText() 
	public virtual string GetAdvRankText() 
	{
		int advRank = GetAdvRank();
		return ListRank[advRank];

TraitDrink โ€‹

public override void OnBlend(Thing t, Chara c)

cs
	case EffectId.DrinkWater:
	{
		BlessedState blessedState = owner.blessedState;
		t = t.Split(1); 
		if (blessedState >= BlessedState.Blessed)
		{
			t = t.Split(1); 
			Msg.Say("waterBless", t);
			t.SetBlessedState(BlessedState.Blessed);
			c.Pick(t);
		}
		else if (blessedState <= BlessedState.Cursed)
		{
			t = t.Split(1); 
			Msg.Say("waterCurse", t);
			t.SetBlessedState(BlessedState.Cursed);
			c.Pick(t);

UICharaMaker โ€‹

public void ListRace()

cs
				t.note.AddHeader("lore");
				t.note.AddText("NoteText_long", a.GetDetail().IsEmpty(TextUnknown)).Hyphenate();
				t.note.Space(8);
				AddWeaponSkill(t.note, elementContainer); 
				t.note.Space(8); 
				t.note.Build();
			});
			if (first)

public void ListJob()

cs
				t.note.AddHeader("lore");
				t.note.AddText("NoteText_long", a.GetDetail().IsEmpty(TextUnknown)).Hyphenate();
				AddDomain(t.note, new ElementContainer().ImportElementMap(a.domain), button: false);
				AddWeaponSkill(t.note, elementContainer); 
				t.note.Build();
			});
			if (first)

public void AddDomain(UINote n, ElementContainer domains, bool button)

cs
		});
	}

	public void AddWeaponSkill(UINote n, ElementContainer eles) 
	{ 
		List<Element> list = eles.dict.Values.Where((Element e) => e.ValueWithoutLink > 1 && e.source.categorySub == "weapon").ToList(); 
		string text = ""; 
		foreach (Element item in list) 
		{ 
			text = text + ((item == list.First()) ? "" : ", ") + item.Name; 
		} 
		if (!text.IsEmpty()) 
		{ 
			n.AddTopic("TopicDomain", "skillsWeapon".lang(), text).button1.SetActive(enable: false); 
		} 
	} 
	public void ListGender()
	{
		EMono.ui.AddLayer<LayerList>().SetStringList(() => Lang.GetList("genders"), delegate(int a, string b)

WindowChara โ€‹

public void RefreshEquipment(UIList list, bool sort = true)

cs

	public void RefreshInfo()
	{
		if (ModUtil.TryGetContent<CustomBiographyContent>("Biography/" + chara.id, out var content)) 
		{ 
			content.RefreshCharaBio(chara); 
		} 
		textBirthday.text = bio.TextBirthDate(chara);
		textMom.text = chara.bio.nameMom.ToTitleCase(); 
		textDad.text = chara.bio.nameDad.ToTitleCase(); 
		textBirthplace.text = chara.bio.nameBirthplace.ToTitleCase(); 
		textLike.text = EClass.sources.cards.map.TryGetValue(bio.idLike, EClass.sources.cards.map["ash"]).GetName(); 
		textHobby.text = EClass.sources.elements.map[bio.idHobby].GetText(); 
		textMom.text = bio.nameMom.ToTitleCase().Trim(); 
		textDad.text = bio.nameDad.ToTitleCase().Trim(); 
		textBirthplace.text = bio.nameBirthplace.ToTitleCase(); 
		textLike.text = EClass.sources.cards.map.TryGetValue(bio.idLike, "ash").GetName(); 
		textHobby.text = EClass.sources.elements.map.TryGetValue(bio.idHobby, 100).GetText(); 
		textFaction.text = ((chara.faction == null) ? "???" : chara.faction.name.ToTitleCase());
		textFaith.text = chara.faith.Name.ToTitleCase();
	}

public static void RefreshNote(Chara chara, UINote n, bool shortMode = false)

cs
		}
		else
		{
			uIItem.text1.SetText("???"); 
			string text = "???"; 
			if (ModUtil.TryGetContent<CustomBiographyContent>("Biography/" + chara.id, out var content)) 
			{ 
				content.RefreshCharaBio(chara); 
				text = content.background; 
			} 
			uIItem.text1.SetText(text); 
			uIItem.button1.SetActive(enable: false);
		}
		n.Space(16);
		n.AddTopic("TopicDomain", "profile".lang(), biography.TextBio(chara) + " " + biography.TextBio2(chara));
	}
	string text = ""; 
	string text2 = ""; 
	ElementContainer elementContainer = (chara.IsPC ? EClass.player.GetDomains() : new ElementContainer().ImportElementMap(chara.job.domain));
	foreach (Element value in elementContainer.dict.Values)
	{
		text = text + ((value == elementContainer.dict.Values.First()) ? "" : ", ") + value.Name; 
		text2 = text2 + ((value == elementContainer.dict.Values.First()) ? "" : ", ") + value.Name; 
	}
	n.AddTopic("TopicDomain", "domain".lang(), text).button1.SetActive(enable: false); 
	string text2 = chara.GetFavCat().GetName(); 
	n.AddTopic("TopicDomain", "domain".lang(), text2).button1.SetActive(enable: false); 
	string text3 = chara.GetFavCat().GetName(); 
	string @ref = chara.GetFavFood().GetName();
	Add("favgift".lang(text2.ToLower().ToTitleCase(), @ref)); 
	Add("favgift".lang(text3.ToLower().ToTitleCase(), @ref)); 
	Add(chara.GetTextHobby());
	Add(chara.GetTextWork());
	if (chara.IsPC)
	{
		n.AddTopic("TopicDomain", "totalFeat".lang(), EClass.player.totalFeat.ToString() ?? "");
	}
	text = chara.GetFavWeaponSkill()?.Name ?? Element.Get(100).GetText(); 
	text = text + " / " + ("style" + chara.GetFavAttackStyle()).lang(); 
	n.AddTopic("TopicDomain", "attackStyle".lang(), text); 
	text2 = chara.GetFavWeaponSkill()?.Name ?? Element.Get(100).GetText(); 
	text2 = text2 + " / " + ("style" + chara.GetFavAttackStyle()).lang(); 
	n.AddTopic("TopicDomain", "attackStyle".lang(), text2); 
	n.AddTopic("TopicDomain", "armorStyle".lang(), chara.GetFavArmorSkill()?.Name ?? Element.Get(120).GetText());
	bool textAdded = false;
	if (chara.IsPC && EClass.pc.c_daysWithGod > 0)

Zone โ€‹

public class PortalReturnData

cs

	public static List<Thing> Suckers = new List<Thing>();

	public string ZoneFullName => $"Zone_{id}@{base.lv}"; 
	public Chara Boss
	{
		get

public virtual int MaxSoil

cs
		}
	}

	public Zone FindOrCreateLevel(int destLv, string subId = "") 
	{ 
		Zone zone = FindZone(destLv); 
		if (zone != null) 
		{ 
			return zone; 
		} 
		if (!(SpatialGen.Create(subId.IsEmpty(GetNewZoneID(destLv)), this, register: true) is Zone zone2)) 
		{ 
			return null; 
		} 
		zone2.lv = destLv; 
		zone2.x = base.x; 
		zone2.y = base.y; 
		return zone2; 
	} 
	public int Evalue(int ele)
	{
		return elements.Value(ele);

public virtual string GetNewZoneID(int level)

cs

	public override string ToString()
	{
		return Name + "(" + base.uid + ")(" + _regionPos?.ToString() + ") instance?" + IsInstance + "/" + EClass.world.date.GetRemainingHours(base.dateExpire) + "h"; 
		return Name + "(" + base.uid + ")(" + RegionPos?.ToString() + ") instance?" + IsInstance + "/" + EClass.world.date.GetRemainingHours(base.dateExpire) + "h"; 
	}

	public string TextLevel(int _lv)

public void Activate()

cs
	{
		UnloadMap();
	}
	Debug.Log(idExport + "/" + File.Exists(pathExport) + "/" + pathExport); 
	if (!base.isGenerated && (idExport.IsEmpty() || !File.Exists(pathExport))) 
	string fullName = pathExport; 
	string lhs = CorePath.ZoneSave + "_new.z"; 
	bool flag3 = File.Exists(fullName) && !PathComparer.Default.Equals(lhs, fullName); 
	bool flag4 = !idExport.IsEmpty(); 
	Debug.Log(idExport + "/" + flag3 + "/" + fullName); 
	if (!flag3 && (base.source.tag.Contains("addMap") || flag4)) 
	{ 
		string[] array = new string[4] 
		{ 
			"Maps/" + idExport + ".z", 
			"Maps/" + ZoneFullName + ".z", 
			"Map/" + idExport + ".z", 
			"Map/" + ZoneFullName + ".z"
		}; 
		for (int i = 0; i < array.Length; i++) 
		{ 
			FileInfo fileInfo = PackageIterator.GetFiles(array[i]).LastOrDefault(); 
			if (fileInfo != null) 
			{ 
				fullName = fileInfo.FullName; 
				flag3 = true; 
				flag4 = true; 
				break; 
			} 
		} 
	} 
	if (!base.isGenerated && (!flag4 || !flag3)) 
	{
		Debug.Log("generating random map");
		flag = true;

public void Activate()

cs
	else
	{
		subset = null;
		bool flag3 = (base.isGenerated && flag2) || (base.isGenerated && !IsInstance && !IsPCFaction && ShouldRegenerate && EClass.world.date.IsExpired(base.dateRegenerate)) || forceRegenerate; 
		if (pathExport.IsEmpty() || !File.Exists(pathExport) || EClass.game.isLoading || EClass.player.simulatingZone) 
		bool flag5 = (base.isGenerated && flag2) || (base.isGenerated && !IsInstance && !IsPCFaction && ShouldRegenerate && EClass.world.date.IsExpired(base.dateRegenerate)) || forceRegenerate; 
		if (!flag3 || EClass.game.isLoading || EClass.player.simulatingZone) 
		{
			flag3 = false; 
			flag5 = false; 
			flag2 = false;
		}
		Debug.Log(base.isGenerated + "/" + flag3 + "/" + flag2 + "/" + IDSubset); 
		if (!base.isGenerated || flag3 || flag2) 
		Debug.Log(base.isGenerated + "/" + flag5 + "/" + flag2 + "/" + IDSubset); 
		if (!base.isGenerated || flag5 || flag2) 
		{
			Debug.Log("importing map:" + pathExport); 
			Debug.Log("importing map:" + fullName); 
			flag = true;
			base.dateRegenerate = EClass.world.date.GetRaw() + 1440 * EClass.setting.balance.dateRegenerateZone;
			if (!flag3) 
			if (!flag5) 
			{
				IO.DeleteDirectory(pathTemp + "Texture Replace");
				Debug.Log(pathTemp);
			}
			try
			{
				zoneExportData = Import(pathExport); 
				zoneExportData = Import(fullName); 
				base.isGenerated = true;
				isImported = true;
				if (flag3) 
				if (flag5) 
				{
					zoneExportData.orgMap = GameIO.LoadFile<Map>(base.pathSave + "map");
				}

public void Activate()

cs
			}
		}
		EClass.game.countLoadedMaps++;
		Debug.Log("loading map: imported? " + isImported + " regenerate? " + flag3); 
		map = GameIO.LoadFile<Map>((isImported ? pathTemp : base.pathSave) + "map"); 
		if (map == null) 
		Debug.Log("loading map: imported? " + isImported + " regenerate? " + flag5); 
		string text = (isImported ? pathTemp : base.pathSave) + "map"; 
		try
		{ 
			map = GameIO.LoadFile<Map>(text); 
		} 
		catch (Exception message2) 
		{
			EClass.ui.Say("System.IO.EndOfStreamException: Unexpected end of stream:" + Environment.NewLine + "File may be corrupted. Try replacing the following file if you have a backup:" + Environment.NewLine + (isImported ? pathTemp : base.pathSave) + "map"); 
			EClass.ui.Say($"Can't load map '{base.uid}/{Name}'; File may be corrupted.\n" + "Try replacing the following file if you have a backup:\n" + text + "\nDefault file is at:\n" + fullName); 
			Debug.LogError(message2); 
			return;
		}
		map.SetZone(this);

public void Activate()

cs
		{
			map.deadCharas.Clear();
			map.OnImport(zoneExportData);
			if (UseFog && !flag3) 
			if (UseFog && !flag5) 
			{
				map.ForeachCell(delegate(Cell c)
				{

public void Activate()

cs
				map.charas = orgMap.charas;
				map.serializedCharas = orgMap.serializedCharas;
				map.deadCharas = orgMap.deadCharas;
				byte[] array = orgMap.TryLoadFile(base.pathSave, "flags", EClass._map.Size * EClass._map.Size); 
				if (array != null && array.Length == EClass._map.Size * EClass._map.Size) 
				byte[] array2 = orgMap.TryLoadFile(base.pathSave, "flags", EClass._map.Size * EClass._map.Size); 
				if (array2 != null && array2.Length == EClass._map.Size * EClass._map.Size) 
				{
					for (int i = 0; i < EClass._map.Size; i++) 
					for (int j = 0; j < EClass._map.Size; j++) 
					{
						for (int j = 0; j < EClass._map.Size; j++) 
						for (int k = 0; k < EClass._map.Size; k++) 
						{
							map.cells[i, j].isSeen = array[i * EClass._map.Size + j].GetBit(1); 
							map.cells[j, k].isSeen = array2[j * EClass._map.Size + k].GetBit(1); 
						}
					}
				}

public void Activate()

cs
		map.RefreshAllTiles();
		AddGlobalCharasOnActivate();
		map.OnLoad();
		if (flag3) 
		if (flag5) 
		{
			foreach (Card item3 in map.Cards.ToList())
			{

public void Activate()

cs
				instance.OnGenerateMap();
			}
		}
		if (isImported && !flag3 && !RevealRoom) 
		if (isImported && !flag5 && !RevealRoom) 
		{
			foreach (Room item4 in map.rooms.listRoom)
			{

public void Activate()

cs
				}
			}
		}
		if (flag3) 
		if (flag5) 
		{
			OnRegenerate();
		}