using System; // Required for Activator using System.Collections.Generic; using System.Linq; using UnityEngine; using Verse; using RimWorld; namespace WulaFallenEmpire { public abstract class EffectBase { public float weight = 1.0f; public abstract void Execute(Window dialog = null); } public class Effect_OpenCustomUI : EffectBase { public string defName; public int delayTicks = 0; public override void Execute(Window dialog = null) { if (delayTicks > 0) { var actionManager = Find.World.GetComponent(); if (actionManager != null) { actionManager.AddAction(defName, delayTicks); } else { WulaLog.Debug("[WulaFallenEmpire] DelayedActionManager not found. Cannot schedule delayed UI opening."); } } else { OpenUI(); } } private void OpenUI() { EventDef nextDef = DefDatabase.GetNamed(defName); if (nextDef != null) { if (nextDef.hiddenWindow) { if (!nextDef.dismissEffects.NullOrEmpty()) { foreach (var conditionalEffect in nextDef.dismissEffects) { string reason; if (AreConditionsMet(conditionalEffect.conditions, out reason)) { conditionalEffect.Execute(null); } } } } else { Find.WindowStack.Add((Window)Activator.CreateInstance(nextDef.windowType, nextDef)); } } else { WulaLog.Debug($"[WulaFallenEmpire] Effect_OpenCustomUI could not find EventDef named '{defName}'"); } } private bool AreConditionsMet(List conditions, out string reason) { reason = ""; if (conditions.NullOrEmpty()) { return true; } foreach (var condition in conditions) { if (!condition.IsMet(out string singleReason)) { reason = singleReason; return false; } } return true; } } public class Effect_CloseDialog : EffectBase { public override void Execute(Window dialog = null) { dialog?.Close(); } } public class Effect_ShowMessage : EffectBase { public string message; public MessageTypeDef messageTypeDef; public override void Execute(Window dialog = null) { if (messageTypeDef == null) { messageTypeDef = MessageTypeDefOf.PositiveEvent; } Messages.Message(message, messageTypeDef); } } public class Effect_FireIncident : EffectBase { public IncidentDef incident; public override void Execute(Window dialog = null) { if (incident == null) { WulaLog.Debug("[WulaFallenEmpire] Effect_FireIncident has a null incident Def."); return; } IncidentParms parms = new IncidentParms { target = Find.CurrentMap, forced = true }; if (!incident.Worker.TryExecute(parms)) { WulaLog.Debug($"[WulaFallenEmpire] Could not fire incident {incident.defName}"); } } } public class Effect_ChangeFactionRelation : EffectBase { public FactionDef faction; public int goodwillChange; public override void Execute(Window dialog = null) { if (faction == null) { WulaLog.Debug("[WulaFallenEmpire] Effect_ChangeFactionRelation has a null faction Def."); return; } Faction targetFaction = Find.FactionManager.FirstFactionOfDef(faction); if (targetFaction == null) { WulaLog.Debug($"[WulaFallenEmpire] Could not find an active faction for FactionDef '{faction.defName}'."); return; } Faction.OfPlayer.TryAffectGoodwillWith(targetFaction, goodwillChange, canSendMessage: true, canSendHostilityLetter: true, reason: null, lookTarget: null); } } public class Effect_SetVariable : EffectBase { public string name; public string value; public string type; // Int, Float, String, Bool public bool forceSet = false; public override void Execute(Window dialog = null) { var eventVarManager = Find.World.GetComponent(); if (!forceSet && eventVarManager.HasVariable(name)) { return; } object realValue = value; if (!string.IsNullOrEmpty(type)) { if (type.Equals("int", System.StringComparison.OrdinalIgnoreCase) && int.TryParse(value, out int intVal)) { realValue = intVal; } else if (type.Equals("float", System.StringComparison.OrdinalIgnoreCase) && float.TryParse(value, out float floatVal)) { realValue = floatVal; } else if (type.Equals("bool", System.StringComparison.OrdinalIgnoreCase) && bool.TryParse(value, out bool boolVal)) { realValue = boolVal; } } eventVarManager.SetVariable(name, realValue); } } public class Effect_ChangeFactionRelation_FromVariable : EffectBase { public FactionDef faction; public string goodwillVariableName; public override void Execute(Window dialog = null) { if (faction == null) { WulaLog.Debug("[WulaFallenEmpire] Effect_ChangeFactionRelation_FromVariable has a null faction Def."); return; } Faction targetFaction = Find.FactionManager.FirstFactionOfDef(faction); if (targetFaction == null) { WulaLog.Debug($"[WulaFallenEmpire] Could not find an active faction for FactionDef '{faction.defName}'."); return; } int goodwillChange = Find.World.GetComponent().GetVariable(goodwillVariableName); Faction.OfPlayer.TryAffectGoodwillWith(targetFaction, goodwillChange, canSendMessage: true, canSendHostilityLetter: true, reason: null, lookTarget: null); } } public class Effect_SpawnPawnAndStore : EffectBase { public PawnKindDef kindDef; public int count = 1; public string storeAs; public override void Execute(Window dialog = null) { if (kindDef == null) { WulaLog.Debug("[WulaFallenEmpire] Effect_SpawnPawnAndStore has a null kindDef."); return; } if (storeAs.NullOrEmpty()) { WulaLog.Debug("[WulaFallenEmpire] Effect_SpawnPawnAndStore needs a 'storeAs' variable name."); return; } var eventVarManager = Find.World.GetComponent(); List spawnedPawns = new List(); for (int i = 0; i < count; i++) { Pawn newPawn = PawnGenerator.GeneratePawn(kindDef, Faction.OfPlayer); IntVec3 loc = CellFinder.RandomSpawnCellForPawnNear(Find.CurrentMap.mapPawns.FreeColonists.First().Position, Find.CurrentMap, 10); GenSpawn.Spawn(newPawn, loc, Find.CurrentMap); spawnedPawns.Add(newPawn); } if (count == 1) { eventVarManager.SetVariable(storeAs, spawnedPawns.First()); } else { eventVarManager.SetVariable(storeAs, spawnedPawns); } } } public class Effect_GiveThing : EffectBase { public ThingDef thingDef; public int count = 1; public override void Execute(Window dialog = null) { if (thingDef == null) { WulaLog.Debug("[WulaFallenEmpire] Effect_GiveThing has a null thingDef."); return; } Map currentMap = Find.CurrentMap; if (currentMap == null) { WulaLog.Debug("[WulaFallenEmpire] Effect_GiveThing cannot execute without a current map."); return; } Thing thing = ThingMaker.MakeThing(thingDef); thing.stackCount = count; IntVec3 dropCenter = DropCellFinder.TradeDropSpot(currentMap); DropPodUtility.DropThingsNear(dropCenter, currentMap, new List { thing }, 110, false, false, false, false); Messages.Message("LetterLabelCargoPodCrash".Translate(), new TargetInfo(dropCenter, currentMap), MessageTypeDefOf.PositiveEvent); } } public class Effect_SpawnPawn : EffectBase { public PawnKindDef kindDef; public int count = 1; public bool joinPlayerFaction = true; public string letterLabel; public string letterText; public LetterDef letterDef; public override void Execute(Window dialog = null) { if (kindDef == null) { WulaLog.Debug("[WulaFallenEmpire] Effect_SpawnPawn has a null kindDef."); return; } Map map = Find.CurrentMap; if (map == null) { WulaLog.Debug("[WulaFallenEmpire] Effect_SpawnPawn cannot execute without a current map."); return; } for (int i = 0; i < count; i++) { Faction faction = joinPlayerFaction ? Faction.OfPlayer : null; PawnGenerationRequest request = new PawnGenerationRequest( kindDef, faction, PawnGenerationContext.NonPlayer, -1, true, false, false, false, true, 20f, false, true, false, true, true, false, false, false, false, 0f, 0f, null, 1f, null, null, null, null, null, null, null, null, null, null, null, null, false ); Pawn pawn = PawnGenerator.GeneratePawn(request); if (!CellFinder.TryFindRandomEdgeCellWith((IntVec3 c) => map.reachability.CanReachColony(c) && !c.Fogged(map), map, CellFinder.EdgeRoadChance_Neutral, out IntVec3 cell)) { cell = DropCellFinder.RandomDropSpot(map); } GenSpawn.Spawn(pawn, cell, map, WipeMode.Vanish); if (!string.IsNullOrEmpty(letterLabel) && !string.IsNullOrEmpty(letterText)) { TaggedString finalLabel = letterLabel.Formatted(pawn.Named("PAWN")).AdjustedFor(pawn); TaggedString finalText = letterText.Formatted(pawn.Named("PAWN")).AdjustedFor(pawn); PawnRelationUtility.TryAppendRelationsWithColonistsInfo(ref finalText, ref finalLabel, pawn); Find.LetterStack.ReceiveLetter(finalLabel, finalText, letterDef ?? LetterDefOf.PositiveEvent, pawn); } } } } public enum VariableOperation { Add, Subtract, Multiply, Divide } public class Effect_ModifyVariable : EffectBase { public string name; public string value; public string valueVariableName; public VariableOperation operation; public override void Execute(Window dialog = null) { if (string.IsNullOrEmpty(name)) { WulaLog.Debug("[WulaFallenEmpire] Effect_ModifyVariable has a null or empty name."); return; } var eventVarManager = Find.World.GetComponent(); // Determine the value to modify by string valueStr = value; if (!string.IsNullOrEmpty(valueVariableName)) { valueStr = eventVarManager.GetVariable(valueVariableName)?.ToString(); if (valueStr == null) { WulaLog.Debug($"[WulaFallenEmpire] Effect_ModifyVariable: valueVariableName '{valueVariableName}' not found."); return; } } // Get the target variable, or initialize it object variable = eventVarManager.GetVariable(name); if (variable == null) { WulaLog.Debug($"[EventSystem] Effect_ModifyVariable: Variable '{name}' not found, initializing to 0."); variable = 0; } object originalValue = variable; object newValue = null; // Perform operation based on type try { if (variable is int || (variable is float && !valueStr.Contains("."))) // Allow int ops { int currentVal = System.Convert.ToInt32(variable); int modVal = int.Parse(valueStr); newValue = (int)Modify((float)currentVal, (float)modVal, operation); } else // Default to float operation { float currentVal = System.Convert.ToSingle(variable); float modVal = float.Parse(valueStr); newValue = Modify(currentVal, modVal, operation); } WulaLog.Debug($"[EventSystem] Modifying variable '{name}'. Operation: {operation}. Value: {valueStr}. From: {originalValue} To: {newValue}"); eventVarManager.SetVariable(name, newValue); } catch (System.Exception e) { WulaLog.Debug($"[WulaFallenEmpire] Effect_ModifyVariable: Could not parse or operate on value '{valueStr}' for variable '{name}'. Error: {e.Message}"); } } private float Modify(float current, float modifier, VariableOperation op) { switch (op) { case VariableOperation.Add: return current + modifier; case VariableOperation.Subtract: return current - modifier; case VariableOperation.Multiply: return current * modifier; case VariableOperation.Divide: if (modifier != 0) return current / modifier; WulaLog.Debug($"[WulaFallenEmpire] Effect_ModifyVariable tried to divide by zero."); return current; default: return current; } } } public class Effect_ClearVariable : EffectBase { public string name; public override void Execute(Window dialog = null) { if (string.IsNullOrEmpty(name)) { WulaLog.Debug("[WulaFallenEmpire] Effect_ClearVariable has a null or empty name."); return; } Find.World.GetComponent().ClearVariable(name); } } public class Effect_AddQuest : EffectBase { public QuestScriptDef quest; public override void Execute(Window dialog = null) { if (quest == null) { WulaLog.Debug("[WulaFallenEmpire] Effect_AddQuest has a null quest Def."); return; } // ʹ�ñ�׼���������ɷ����������Ǵ���raw quest Quest newQuest = QuestUtility.GenerateQuestAndMakeAvailable(quest, 0); if (newQuest != null) { WulaLog.Debug($"[WulaFallenEmpire] Successfully added quest: {quest.defName}"); // ��������Զ����ܵ����񣬷��Ϳ����ż� if (!newQuest.root.autoAccept) { QuestUtility.SendLetterQuestAvailable(newQuest); } } else { WulaLog.Debug($"[WulaFallenEmpire] Failed to generate quest: {quest.defName}"); } } } public class Effect_FinishResearch : EffectBase { public ResearchProjectDef research; public override void Execute(Window dialog = null) { if (research == null) { WulaLog.Debug("[WulaFallenEmpire] Effect_FinishResearch has a null research Def."); return; } Find.ResearchManager.FinishProject(research); } } public class Effect_TriggerRaid : EffectBase { public float points; public FactionDef faction; public RaidStrategyDef raidStrategy; public PawnsArrivalModeDef raidArrivalMode; public PawnGroupKindDef groupKind; public List pawnGroupMakers; public string letterLabel; public string letterText; public override void Execute(Window dialog = null) { Map map = Find.CurrentMap; if (map == null) { WulaLog.Debug("[WulaFallenEmpire] Effect_TriggerRaid cannot execute without a current map."); return; } Faction factionInst = Find.FactionManager.FirstFactionOfDef(this.faction); if (factionInst == null) { WulaLog.Debug($"[WulaFallenEmpire] Effect_TriggerRaid could not find an active faction for FactionDef '{this.faction?.defName}'."); return; } IncidentParms parms = new IncidentParms { target = map, points = this.points, faction = factionInst, raidStrategy = this.raidStrategy, raidArrivalMode = this.raidArrivalMode, pawnGroupMakerSeed = Rand.Int, forced = true }; if (!RCellFinder.TryFindRandomPawnEntryCell(out parms.spawnCenter, map, CellFinder.EdgeRoadChance_Hostile)) { WulaLog.Debug("[WulaFallenEmpire] Effect_TriggerRaid could not find a valid spawn center."); return; } PawnGroupMakerParms groupMakerParms = new PawnGroupMakerParms { groupKind = this.groupKind ?? PawnGroupKindDefOf.Combat, tile = map.Tile, points = this.points, faction = factionInst, raidStrategy = this.raidStrategy, seed = parms.pawnGroupMakerSeed }; List pawns; if (!pawnGroupMakers.NullOrEmpty()) { var groupMaker = pawnGroupMakers.RandomElementByWeight(x => x.commonality); pawns = groupMaker.GeneratePawns(groupMakerParms).ToList(); } else { pawns = PawnGroupMakerUtility.GeneratePawns(groupMakerParms).ToList(); } if (pawns.Any()) { raidArrivalMode.Worker.Arrive(pawns, parms); // Assign Lord and LordJob to make the pawns actually perform the raid. raidStrategy.Worker.MakeLords(parms, pawns); if (!string.IsNullOrEmpty(letterLabel) && !string.IsNullOrEmpty(letterText)) { Find.LetterStack.ReceiveLetter(letterLabel, letterText, LetterDefOf.ThreatBig, pawns[0]); } } } } public class Effect_CheckFactionGoodwill : EffectBase { public FactionDef factionDef; public string variableName; public override void Execute(Window dialog = null) { if (factionDef == null || string.IsNullOrEmpty(variableName)) { WulaLog.Debug("[WulaFallenEmpire] Effect_CheckFactionGoodwill is not configured correctly."); return; } var eventVarManager = Find.World.GetComponent(); Faction faction = Find.FactionManager.FirstFactionOfDef(factionDef); if (faction != null) { int goodwill = faction.GoodwillWith(Faction.OfPlayer); WulaLog.Debug($"[EventSystem] Storing goodwill for faction '{faction.Name}' ({goodwill}) into variable '{variableName}'."); eventVarManager.SetVariable(variableName, goodwill); } else { WulaLog.Debug($"[EventSystem] Effect_CheckFactionGoodwill: Faction '{factionDef.defName}' not found. Storing 0 in variable '{variableName}'."); eventVarManager.SetVariable(variableName, 0); } } } public class Effect_StoreRealPlayTime : EffectBase { public string variableName; public override void Execute(Window dialog = null) { if (string.IsNullOrEmpty(variableName)) { WulaLog.Debug("[WulaFallenEmpire] Effect_StoreRealPlayTime is not configured correctly (missing variableName)."); return; } var eventVarManager = Find.World.GetComponent(); float realPlayTime = Find.GameInfo.RealPlayTimeInteracting; WulaLog.Debug($"[EventSystem] Storing real play time ({realPlayTime}s) into variable '{variableName}'."); eventVarManager.SetVariable(variableName, realPlayTime); } } public class Effect_StoreDaysPassed : EffectBase { public string variableName; public override void Execute(Window dialog = null) { if (string.IsNullOrEmpty(variableName)) { WulaLog.Debug("[WulaFallenEmpire] Effect_StoreDaysPassed is not configured correctly (missing variableName)."); return; } var eventVarManager = Find.World.GetComponent(); int daysPassed = GenDate.DaysPassed; WulaLog.Debug($"[EventSystem] Storing days passed ({daysPassed}) into variable '{variableName}'."); eventVarManager.SetVariable(variableName, daysPassed); } } public class Effect_StoreColonyWealth : EffectBase { public string variableName; public override void Execute(Window dialog = null) { if (string.IsNullOrEmpty(variableName)) { WulaLog.Debug("[WulaFallenEmpire] Effect_StoreColonyWealth is not configured correctly (missing variableName)."); return; } Map currentMap = Find.CurrentMap; if (currentMap == null) { WulaLog.Debug("[WulaFallenEmpire] Effect_StoreColonyWealth cannot execute without a current map."); return; } var eventVarManager = Find.World.GetComponent(); float wealth = currentMap.wealthWatcher.WealthTotal; WulaLog.Debug($"[EventSystem] Storing colony wealth ({wealth}) into variable '{variableName}'."); eventVarManager.SetVariable(variableName, wealth); } } }