Skip to content

EA 23.189 Nightly

August 28, 2025

21 files modified.

Important Changes

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

ZoneEventSiege (1)

cs
public virtual Chara CreateChara(Point p, bool boss = false) 
public virtual Chara CreateChara(Point p) 

AI_PlayMusic

public override IEnumerable<Status> Run()

cs
		case "harp":
			idSong = "harp_komori";
			break;
		case "shield_lute":
		case "lute":
			idSong = "guitar_sad";
			break;

ActThrow

public override bool CanPerform()

cs
	{
		Act.TP.Set(pcTarget.pos);
	}
	if (!Act.TP.IsHidden) 
	if (!Act.TP.IsHidden && !Act.TP.IsSky) 
	{
		return Act.CC.CanSeeLos(Act.TP);
	}

CalcPlat

public class CalcPlat : EClass

cs
public static int Learn(Chara c, Element e)
{
	int num = Mathf.Max(1, e.CostLearn * (c.HasElement(1202) ? 80 : 100) / 100);
	if (e.source.tag.Contains("guild") && Guild.Current.relation.rank < 2) 
	if (e.source.tag.Contains("guild") && Guild.CurrentDrama.relation.rank < 2) 
	{
		return num * 2;
	}

public static int Train(Chara c, Element _e)

cs
		return 0;
	}
	int num = Mathf.Max(1, element.CostTrain * (c.HasElement(1202) ? 80 : 100) / 100);
	if (element.source.tag.Contains("guild") && Guild.Current.relation.rank < 2) 
	if (element.source.tag.Contains("guild") && Guild.CurrentDrama.relation.rank < 2) 
	{
		return num * 2;
	}

Card

public static string ApplyTone(Chara c, ref string text, string _tones, int gend

cs
	string key = array[0];
	string text2 = "";
	MOD.tones.Initialize();
	Debug.Log(c.Name); 
	if (!Lang.setting.useTone || MOD.tones.list.Count == 0)
	{
		text2 = text.Replace("{", "").Replace("}", "");

public static string ApplyTone(Chara c, ref string text, string _tones, int gend

cs
		if (MOD.tones.all.ContainsKey(key))
		{
			StringBuilder stringBuilder = MOD.tones.ApplyTone(key, ref text, gender);
			if (Lang.isJP && c != null && c.trait.EnableTone) 
			if (Lang.isJP && c != null) 
			{
				if (array.Length >= 2)
				{

Chara

public void RestockEquip(bool onCreate)

cs
		if (trait is TraitBard)
		{
			AddThing(ThingGen.Create("lute"));
			if (EClass.debug.enable || EClass.rnd(50) == 0) 
			{ 
				EQ_ID("shield_lute"); 
			} 
		}
	}

DramaCustomSequence

public string GetRumor(Chara c)

cs
	}
	if (HasTopic("unique", c.id))
	{
		manager.enableTone = false; 
		return GetText(c, "unique", c.id);
	}
	if (EClass.rnd(2) == 0 && !c.trait.IDRumor.IsEmpty())

public string GetText(Chara c, string idSheet, string idTopic)

cs
		return manager.customTalkTopics[idTopic];
	}
	string[] dialog = Lang.GetDialog(idSheet, idTopic);
	if (!manager.enableTone && !(idSheet == "general")) 
	if (!(idSheet != "unique")) 
	{
		return dialog.RandomItem();
	}

DramaManager

public void ParseLine(Dictionary<string, string> item)

cs
			}
			if (tg != null && (actor == "tg" || actor.IsEmpty()))
			{
				text = tg.ApplyTone(text); 
				text = (enableTone ? tg.ApplyTone(text) : text); 
			}
			return text;
		})) as DramaEventTalk;

public bool CheckIF(string IF)

cs
	case "WindRest":
		return EMono._zone is Zone_WindRest;
	case "guild_promote":
		return Guild.Current.relation.exp >= Guild.Current.relation.ExpToNext; 
		return Guild.CurrentDrama.relation.exp >= Guild.CurrentDrama.relation.ExpToNext; 
	case "guild_maxpromote":
		return Guild.Current.relation.rank >= Guild.Current.relation.MaxRank; 
		return Guild.CurrentDrama.relation.rank >= Guild.CurrentDrama.relation.MaxRank; 
	case "scratch_check":
		return EMono.game.dateScratch > EMono.game.world.date.GetRaw();
	case "sister_money":

public bool CheckIF(string IF)

cs
	case "hasMelilithCurse":
		return EMono.pc.HasElement(1206);
	case "merchant":
		return Guild.Current == Guild.Merchant; 
		return Guild.CurrentDrama == Guild.Merchant; 
	case "fighter":
		return Guild.Current == Guild.Fighter; 
		return Guild.CurrentDrama == Guild.Fighter; 
	case "thief":
		return Guild.Current == Guild.Thief; 
		return Guild.CurrentDrama == Guild.Thief; 
	case "mage":
		return Guild.Current == Guild.Mage; 
		return Guild.CurrentDrama == Guild.Mage; 
	case "hasDLC":
		return Steam.HasDLC(array[1].ToEnum<ID_DLC>());
	case "hasFlag":

DramaOutcome

public static bool If(DramaChoice item, Chara c)

cs

	public void guild_trial()
	{
		if (Guild.Current == EMono.game.factions.Merchant) 
		if (Guild.CurrentDrama == EMono.game.factions.Merchant) 
		{
			EMono.game.quests.Start("guild_merchant", cc, assignQuest: false);
		}

public void guild_trial()

cs

	public void guild_join()
	{
		if (Guild.Current != EMono.game.factions.Merchant) 
		if (Guild.CurrentDrama != EMono.game.factions.Merchant) 
		{
			(cc.trait as TraitGuildDoorman).OnJoinGuild();
		}
		Msg.Say("guild_join", Guild.Current.Name); 
		Msg.Say("guild_join", Guild.CurrentDrama.Name); 
		SE.Play("questComplete");
		Guild.Current.relation.type = FactionRelation.RelationType.Member; 
		Guild.CurrentQuest.ChangePhase(10); 
		Guild.CurrentDrama.relation.type = FactionRelation.RelationType.Member; 
		Guild.CurrentDrama?.Quest.ChangePhase(10); 
	}

	public void guild_mageTrial()

public void guild_mageTrial()

cs

	public void guild_promote()
	{
		Guild.Current.relation.Promote(); 
		Guild.CurrentDrama.relation.Promote(); 
		Guild.GetCurrentGuild()?.RefreshDevelopment();
	}

GameLang

public static string ConvertDrama(string text, Chara c = null)

cs
	stringBuilder.Replace("#player", EClass.player.title);
	stringBuilder.Replace("#title", EClass.player.title);
	stringBuilder.Replace("#zone", EClass._zone.Name);
	stringBuilder.Replace("#guild_title", Guild.Current.relation.TextTitle); 
	stringBuilder.Replace("#guild", Guild.Current.Name); 
	stringBuilder.Replace("#guild_title", Guild.CurrentDrama.relation.TextTitle); 
	stringBuilder.Replace("#guild", Guild.CurrentDrama.Name); 
	stringBuilder.Replace("#race", EClass.pc.race.GetName());
	stringBuilder.Replace("#pc", EClass.pc.NameSimple);
	stringBuilder.Replace("#aka", EClass.pc.Aka);

Guild

public static Guild Current

cs
		}
	}

	public static Guild CurrentDrama 
	{ 
		get 
		{ 
			if ((bool)LayerDrama.Instance && EClass.game.IsSurvival) 
			{ 
				Chara chara = LayerDrama.Instance.drama.tg?.chara; 
				if (chara != null) 
				{ 
					switch (chara.id) 
					{ 
					case "guild_master_fighter": 
					case "guild_clerk_fighter": 
					case "guild_doorman_fighter": 
						return Fighter; 
					case "guild_master_thief": 
					case "guild_clerk_thief": 
					case "guild_doorman_thief": 
						return Thief; 
					case "guild_master_mage": 
					case "guild_clerk_mage": 
					case "guild_doorman_mage": 
						return Mage; 
					case "guild_master_merchant": 
					case "guild_clerk_merchant": 
						return Merchant; 
					} 
				} 
			} 
			return Current; 
		} 
	} 
	public static GuildFighter Fighter => EClass.game.factions.Fighter;

	public static GuildMage Mage => EClass.game.factions.Mage;

public static Guild Current

cs

	public static GuildMerchant Merchant => EClass.game.factions.Merchant;

	public static QuestGuild CurrentQuest => Current?.Quest; 
	public static QuestGuild CurrentQuest => CurrentDrama?.Quest; 

	public override string TextType => "sub_guild".lang();

Recipe

public bool IsValidIngredient(Thing t)

cs
		{
			return true;
		}
		Debug.Log(t.Name + "/" + tag + "/" + t.material.tag); 
		if (!tag.IsEmpty() && !t.material.tag.Contains(tag)) 
		{ 
			return false; 
		} 
		if (useCat)
		{
			if (t.category.IsChildOf(id))

SpawnSetting

public class SpawnSetting

cs
{
	public int filterLv = -1;

	public int dangerLv = -1; 
	public int fixedLv = -1;

	public int tries = 100;

SurvivalManager

public bool OnMineWreck(Point point)

cs
	default:
		return false;
	}
	if (EClass.rnd(3) == 0 && EClass.game.survival.flags.spawnedFloor < 4) 
	if (EClass.rnd(3 + EClass.game.survival.flags.spawnedFloor * 2) == 0 && EClass.game.survival.flags.spawnedFloor < 8) 
	{
		EClass.game.survival.flags.spawnedFloor++;
		return Pop(ThingGen.CreateFloor(40, 45).SetNum(3)); 
		switch (EClass.game.survival.flags.spawnedFloor) 
		{ 
		case 5: 
		case 6: 
			return Pop(ThingGen.CreateFloor(33, 97).SetNum(3)); 
		case 7: 
		case 8: 
			return Pop(ThingGen.CreateFloor(43, 66).SetNum(3)); 
		default: 
			return Pop(ThingGen.CreateFloor(40, 45).SetNum(3)); 
		} 
	}
	if (EClass.rnd(20) == 0)
	{

public Point GetRandomPoint()

cs
		case "littleOne":
			return false;
		default:
			return EClass.game.cards.globalCharas.Find(r.id) == null; 
			if (EClass.game.cards.globalCharas.Find(r.id) == null) 
			{ 
				return r.LV < flags.raidLv + 10; 
			} 
			return false; 
		}
	}).ToList();
}

TraitChara

public virtual bool CanSellPlan

cs

	public virtual Adv_Type AdvType => Adv_Type.None;

	public virtual bool EnableTone 
	{ 
		get 
		{ 
			if (IsUnique) 
			{ 
				return !LayerDrama.Instance; 
			} 
			return true; 
		} 
	} 
	public virtual bool CanBeTamed
	{
		get

TraitCoreDefense

public override void TrySetAct(ActPlan p)

cs
				return true;
			});
		}
		if (EClass.debug.enable) 
		{ 
			p.TrySetAct("50", delegate
			{ 
				SE.Play("warhorn"); 
				Msg.Say("warhorn"); 
				EClass.game.survival.flags.raidLv += 50; 
				return true; 
			}); 
		} 
	}
	ZoneEventDefenseGame ev = EClass._zone.events.GetEvent<ZoneEventDefenseGame>();
	if (ev == null)

TraitMod

public class TraitMod : TraitItem

cs

	public override bool CanStack => false;

	public SourceElement.Row source => EClass.sources.elements.map[owner.refVal]; 
	public SourceElement.Row source => EClass.sources.elements.map.TryGetValue(owner.refVal, DefaultEnc); 

	public override void OnCreate(int lv)
	{

TraitRecipe

public override void OnRead(Chara c)

cs
	public override void SetName(ref string s)
	{
		int num = EClass.player.recipes.knownRecipes.TryGetValue(ID, 0);
		s = "_recipe".lang(recipe.Name.ToTitleCase(), s) + ((num == 0) ? "" : "recipe_learnt".lang(num.ToString() ?? "")); 
		s = "_recipe".lang(recipe?.Name.ToTitleCase() ?? "???", s) + ((num == 0) ? "" : "recipe_learnt".lang(num.ToString() ?? "")); 
	}

	public override bool CanStackTo(Thing to)

Zone

public virtual bool UseLight

cs

	public virtual ZoneScaleType ScaleType => ZoneScaleType.None;

	public virtual bool ScaleMonsterLevel => false; 
	public virtual bool HiddenInRegionMap => false;

	public virtual FlockController.SpawnType FlockType => FlockController.SpawnType.Default;

public Chara SpawnMob(Point pos = null, SpawnSetting setting = null)

cs
			return s.biome == biome.name || s.biome.IsEmpty();
		}
	}) : SpawnList.Get(biome.spawn.GetRandomCharaId())))));
	int dangerLv = DangerLv; 
	int num = ((setting.dangerLv == -1) ? DangerLv : setting.dangerLv); 
	CardBlueprint cardBlueprint = new CardBlueprint
	{
		rarity = Rarity.Normal,
		idEle = setting.idEle
	};
	int num = ((setting.filterLv == -1) ? dangerLv : setting.filterLv); 
	int num2 = ((setting.filterLv == -1) ? num : setting.filterLv); 
	if (ScaleType == ZoneScaleType.Void)
	{
		num = ((dangerLv - 1) % 50 + 5) * 150 / 100; 
		if (num >= 20 && EClass.rnd(100) < num) 
		num2 = ((num - 1) % 50 + 5) * 150 / 100; 
		if (num2 >= 20 && EClass.rnd(100) < num2) 
		{
			num = dangerLv; 
			num2 = num; 
		}
	}
	CardRow cardRow = (setting.id.IsEmpty() ? spawnList.Select(num, setting.levelRange) : EClass.sources.cards.map[setting.id]); 
	int num2 = ((setting.fixedLv == -1) ? cardRow.LV : setting.fixedLv); 
	CardRow cardRow = (setting.id.IsEmpty() ? spawnList.Select(num2, setting.levelRange) : EClass.sources.cards.map[setting.id]); 
	int num3 = ((setting.fixedLv == -1) ? cardRow.LV : setting.fixedLv); 
	if (ScaleType == ZoneScaleType.Void)
	{
		num2 = (50 + cardRow.LV) * Mathf.Max(1, (dangerLv - 1) / 50); 
		num3 = (50 + cardRow.LV) * Mathf.Max(1, (num - 1) / 50); 
	}
	num2 += DangerLvBoost; 
	num3 += DangerLvBoost; 
	if (setting.rarity == Rarity.Random)
	{
		if (EClass.rnd(100) == 0)
		{
			cardBlueprint.rarity = Rarity.Legendary;
			num2 = num2 * 125 / 100; 
			num3 = num3 * 125 / 100; 
		}
	}
	else

public Chara SpawnMob(Point pos = null, SpawnSetting setting = null)

cs
	}
	if (setting.isBoss)
	{
		num2 = num2 * 150 / 100; 
		num3 = num3 * 150 / 100; 
	}
	if (setting.isEvolved)
	{
		num2 = num2 * 2 + 20; 
		num3 = num3 * 2 + 20; 
	}
	if (num2 != cardRow.LV) 
	if (num3 != cardRow.LV) 
	{
		cardBlueprint.lv = num2; 
		cardBlueprint.lv = num3; 
	}
	CardBlueprint.Set(cardBlueprint);
	Chara chara = CharaGen.Create(cardRow.id, num); 
	Chara chara = CharaGen.Create(cardRow.id, num2); 
	AddCard(chara, pos);
	if (setting.forcedHostility.HasValue)
	{

ZoneEventRaid

public class ZoneEventRaid : ZoneEventSiege

cs
	public override void OnInit()
	{
		lv = Mathf.Max(1, EClass.game.survival.flags.raidLv);
		max = 5 + lv / 5; 
		max = 5 + lv / 4; 
		base.OnInit();
	}

ZoneEventSiege

public class ZoneEventSiege : ZoneEvent

cs

	public override string id => "trial_siege";

	public override float roundInterval => Mathf.Max(0.5f, 1.5f - 0.01f * (float)lv); 
	public override float roundInterval => Mathf.Max(0.1f, 1.5f - 0.01f * (float)lv); 

	public override Playlist playlist => EClass.Sound.playlistBattle;

	public virtual Chara CreateChara(Point p, bool boss = false) 
	public virtual Chara CreateChara(Point p) 
	{
		return EClass._zone.SpawnMob(p, boss ? SpawnSetting.Boss(lv) : SpawnSetting.DefenseEnemy(lv)); 
		bool flag = idx == max - 1; 
		SpawnSetting spawnSetting = ((lv >= 50 && idx == max - 2) ? SpawnSetting.Evolved(lv) : (flag ? SpawnSetting.Boss(lv) : SpawnSetting.DefenseEnemy(lv))); 
		spawnSetting.dangerLv = lv + 1; 
		return EClass._zone.SpawnMob(p, spawnSetting); 
	}

	public override void OnInit()

public override void OnVisit()

cs
public void SpawnMob()
{
	Point spawnPos = GetSpawnPos();
	Chara chara = CreateChara(spawnPos, idx == max - 1); 
	Chara chara = CreateChara(spawnPos); 
	chara.hostility = Hostility.Enemy;
	members.Add(chara);
	uids.Add(chara.uid);

Zone_StartSiteSky

public class Zone_StartSiteSky : Zone_StartSite

cs

	public override string IdBiome => "Plain";

	public override bool ScaleMonsterLevel 
	public override ZoneScaleType ScaleType 
	{
		get
		{
			if (EClass.game.IsSurvival) 
			if (!EClass.game.IsSurvival || EClass.game.survival.flags.raidLv < 100) 
			{
				return EClass.game.survival.flags.raidLv >= 100; 
				return ZoneScaleType.None; 
			}
			return false; 
			return ZoneScaleType.Void; 
		}
	}
}