This commit is contained in:
2025-08-15 08:19:51 +08:00
19 changed files with 423 additions and 362 deletions

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<Defs> <Defs>
<FleshTypeDef> <FleshTypeDef>
<defName>WULA_Fleshtype</defName> <defName>WULA_Fleshtype</defName>
<corpseCategory>CorpsesMechanoid</corpseCategory> <corpseCategory>CorpsesMechanoid</corpseCategory>
<damageEffecter>Damage_HitMechanoid</damageEffecter> <damageEffecter>Damage_HitMechanoid</damageEffecter>
<isOrganic>true</isOrganic> <isOrganic>false</isOrganic>
<genericWounds> <genericWounds>
<li> <li>
<texture>Things/Pawn/Wounds/WoundMechA</texture> <texture>Things/Pawn/Wounds/WoundMechA</texture>

View File

@@ -4,37 +4,30 @@
<JobDef> <JobDef>
<defName>WULA_EnterMaintenancePod</defName> <defName>WULA_EnterMaintenancePod</defName>
<driverClass>WulaFallenEmpire.JobDriver_EnterMaintenancePod</driverClass> <driverClass>WulaFallenEmpire.JobDriver_EnterMaintenancePod</driverClass>
<reportString>正在进入维护舱</reportString> <reportString>正在进入维护舱</reportString>
<allowOpportunisticPrefix>true</allowOpportunisticPrefix> <allowOpportunisticPrefix>true</allowOpportunisticPrefix>
</JobDef> </JobDef>
<JobDef> <JobDef>
<defName>WULA_IngestWulaEnergy</defName> <defName>WULA_IngestWulaEnergy</defName>
<driverClass>WulaFallenEmpire.JobDriver_IngestWulaEnergy</driverClass> <driverClass>WulaFallenEmpire.JobDriver_IngestWulaEnergy</driverClass>
<reportString>正在摄取能量</reportString> <reportString>正在摄取能量</reportString>
<allowOpportunisticPrefix>true</allowOpportunisticPrefix> <allowOpportunisticPrefix>true</allowOpportunisticPrefix>
</JobDef> </JobDef>
<JobDef> <JobDef>
<defName>WULA_FeedWulaPatient</defName> <defName>WULA_FeedWulaPatient</defName>
<driverClass>WulaFallenEmpire.JobDriver_FeedWulaPatient</driverClass> <driverClass>WulaFallenEmpire.JobDriver_FeedWulaPatient</driverClass>
<reportString>正在喂食能量核心</reportString> <reportString>正在喂食能量核心</reportString>
<allowOpportunisticPrefix>true</allowOpportunisticPrefix> <allowOpportunisticPrefix>true</allowOpportunisticPrefix>
</JobDef> </JobDef>
<JobDef> <JobDef>
<defName>WULA_HaulToMaintenancePod</defName> <defName>WULA_HaulToMaintenancePod</defName>
<driverClass>WulaFallenEmpire.JobDriver_HaulToMaintenancePod</driverClass> <driverClass>WulaFallenEmpire.JobDriver_HaulToMaintenancePod</driverClass>
<reportString>正在将TargetA抬到TargetB</reportString> <reportString>正在将TargetA抬到TargetB</reportString>
<allowOpportunisticPrefix>true</allowOpportunisticPrefix> <allowOpportunisticPrefix>true</allowOpportunisticPrefix>
<casualInterruptible>false</casualInterruptible> <casualInterruptible>false</casualInterruptible>
</JobDef> </JobDef>
<JobDef>
<defName>WULA_LayDownToCharge</defName>
<driverClass>WulaFallenEmpire.JobDriver_WulaLayDownToCharge</driverClass>
<reportString>正在充电。</reportString>
<casualInterruptible>false</casualInterruptible>
</JobDef>
</Defs> </Defs>

View File

@@ -269,6 +269,7 @@
<ThingDef ParentName="BasicBedBase"> <ThingDef ParentName="BasicBedBase">
<defName>WULA_Charging_Station_Synth</defName> <defName>WULA_Charging_Station_Synth</defName>
<thingClass>Building_Bed</thingClass> <thingClass>Building_Bed</thingClass>
<tickerType>Normal</tickerType>
<label>合成人修复站</label> <label>合成人修复站</label>
<description>一台供乌拉帝国合成人进行机体修复的检修站。</description> <description>一台供乌拉帝国合成人进行机体修复的检修站。</description>
<tickerType>Normal</tickerType> <tickerType>Normal</tickerType>

View File

@@ -265,21 +265,30 @@
<emergency>true</emergency> <emergency>true</emergency>
</li> </li>
<!-- Get Wula energy (only if starving) --> <!-- Satisfy Needs -->
<li Class="ThinkNode_ConditionalNeedPercentageAbove">
<need>WULA_Energy</need>
<threshold>0.5</threshold> <!-- 能量低于10%时触发 -->
<invert>true</invert>
<subNodes>
<li Class="ThinkNode_Tagger"> <li Class="ThinkNode_Tagger">
<tagToGive>SatisfyingNeeds</tagToGive> <tagToGive>SatisfyingNeeds</tagToGive>
<subNodes> <subNodes>
<li Class="ThinkNode_PrioritySorter">
<subNodes>
<li Class="JobGiver_Autofeed" MayRequire="Ludeon.RimWorld.Biotech" />
<li Class="WulaFallenEmpire.JobGiver_WulaGetEnergy"> <li Class="WulaFallenEmpire.JobGiver_WulaGetEnergy">
<leaveJoinableLordIfIssuesJob>true</leaveJoinableLordIfIssuesJob> <leaveJoinableLordIfIssuesJob>true</leaveJoinableLordIfIssuesJob>
<minEnergyLevelPercentage>0.3</minEnergyLevelPercentage> <minEnergyLevelPercentage>0.3</minEnergyLevelPercentage>
<maxEnergyLevelPercentage>0.9</maxEnergyLevelPercentage> <maxEnergyLevelPercentage>1.0</maxEnergyLevelPercentage>
<emergencyPriority>9.5</emergencyPriority> <emergencyPriority>9.5</emergencyPriority>
</li> </li>
<li Class="JobGiver_SatisfyChemicalNeed"/>
<li Class="JobGiver_SatifyChemicalDependency" MayRequire="Ludeon.RimWorld.Biotech" />
<li Class="JobGiver_GetHemogen" MayRequire="Ludeon.RimWorld.Biotech" />
<li Class="JobGiver_GetDeathrest" MayRequire="Ludeon.RimWorld.Biotech" />
<li Class="ThinkNode_Priority_GetJoy">
<subNodes>
<li Class="JobGiver_GetJoy"/>
<li Class="JobGiver_GetJoyInBed"/>
</subNodes>
</li>
<li Class="JobGiver_Meditate"/>
</subNodes> </subNodes>
</li> </li>
</subNodes> </subNodes>

View File

@@ -57,7 +57,7 @@
</li> </li>
</outcomeDoers> </outcomeDoers>
</ingestible> </ingestible>
<recipeMaker Inherit="False"/> <recipeMaker Inherit="False" IsNull="True"/>
<!-- <researchPrerequisite>PsychiteRefining</researchPrerequisite> <!-- <researchPrerequisite>PsychiteRefining</researchPrerequisite>
<soundWorking>Recipe_Drug</soundWorking> <soundWorking>Recipe_Drug</soundWorking>
<displayPriority>1700</displayPriority> <displayPriority>1700</displayPriority>

View File

@@ -1,9 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<JobDef>
<defName>WULA_LayDownToCharge</defName>
<driverClass>WulaFallenEmpire.JobDriver_WulaLayDownToCharge</driverClass>
<reportString>正在充电。</reportString>
<casualInterruptible>false</casualInterruptible>
</JobDef>
</Defs>

View File

@@ -33,6 +33,17 @@
<statFactors> <statFactors>
</statFactors> </statFactors>
</WeaponTraitDef> </WeaponTraitDef>
<WeaponTraitDef>
<defName>WULA_MissileLauncher</defName>
<label>乌拉帝国导弹</label>
<description>这把武器的抛射体会跟踪敌人,如果没有明确的敌人作为目标,则会在落地前散开以形成轰炸区。</description>
<commonality>1</commonality>
<weaponCategory>WULA_Missile</weaponCategory>
<statOffsets>
</statOffsets>
<statFactors>
</statFactors>
</WeaponTraitDef>
<WeaponTraitDef> <WeaponTraitDef>
<defName>WULA_Melee_Cleave</defName> <defName>WULA_Melee_Cleave</defName>
<label>溅射伤害</label> <label>溅射伤害</label>

View File

@@ -24,61 +24,71 @@ namespace WulaFallenEmpire
public override void CompTick() public override void CompTick()
{ {
base.CompTick(); base.CompTick();
Log.Message("[CompChargingBed] CompTick running.");
var bed = (Building_Bed)parent; var bed = (Building_Bed)parent;
if (!bed.AnyOccupants) var powerComp = parent.GetComp<CompPowerTrader>();
// 如果床没电,停止所有充电
if (powerComp is { PowerOn: false })
{ {
for (int i = chargingPawns.Count - 1; i >= 0; i--) StopAllCharging();
{
var p = chargingPawns[i];
var h = p.health.hediffSet.GetFirstHediffOfDef(Props.hediffDef);
if (h != null)
{
Log.Message($"[CompChargingBed] Bed empty. Removing hediff from {p.LabelShort}.");
p.health.RemoveHediff(h);
}
}
chargingPawns.Clear();
return; return;
} }
var currentOccupants = new HashSet<Pawn>(bed.CurOccupants); var currentOccupants = new HashSet<Pawn>(bed.CurOccupants);
Log.Message($"[CompChargingBed] Found {currentOccupants.Count} occupants.");
// 移除已经不在床上的 pawn 的充电效果
for (int i = chargingPawns.Count - 1; i >= 0; i--) for (int i = chargingPawns.Count - 1; i >= 0; i--)
{ {
var pawn = chargingPawns[i]; var pawn = chargingPawns[i];
if (!currentOccupants.Contains(pawn)) if (!currentOccupants.Contains(pawn))
{ {
Log.Message($"[CompChargingBed] Pawn {pawn.LabelShort} left the bed. Removing hediff."); StopCharging(pawn);
var hediff = pawn.health.hediffSet.GetFirstHediffOfDef(Props.hediffDef);
if (hediff != null)
{
pawn.health.RemoveHediff(hediff);
}
chargingPawns.RemoveAt(i); chargingPawns.RemoveAt(i);
} }
} }
// 为床上的新 pawn 开始充电
foreach (var pawn in currentOccupants) foreach (var pawn in currentOccupants)
{ {
Log.Message($"[CompChargingBed] Checking occupant: {pawn.LabelShort}."); if (ShouldCharge(pawn) && !chargingPawns.Contains(pawn))
bool hasNeed = pawn.needs.TryGetNeed<Need_WulaEnergy>() != null;
Log.Message($"[CompChargingBed] Does {pawn.LabelShort} have Need_WulaEnergy? {hasNeed}");
if (hasNeed)
{ {
if (!pawn.health.hediffSet.HasHediff(Props.hediffDef)) StartCharging(pawn);
{
Log.Message($"[CompChargingBed] Adding charging hediff to {pawn.LabelShort}.");
pawn.health.AddHediff(Props.hediffDef);
} }
}
}
private bool ShouldCharge(Pawn pawn)
{
return pawn.def.defName == Props.raceDefName;
}
private void StartCharging(Pawn pawn)
{
if (pawn.health.hediffSet.HasHediff(Props.hediffDef)) return;
pawn.health.AddHediff(Props.hediffDef);
if (!chargingPawns.Contains(pawn)) if (!chargingPawns.Contains(pawn))
{ {
chargingPawns.Add(pawn); chargingPawns.Add(pawn);
} }
} }
private void StopCharging(Pawn pawn)
{
var hediff = pawn.health.hediffSet.GetFirstHediffOfDef(Props.hediffDef);
if (hediff != null)
{
pawn.health.RemoveHediff(hediff);
}
}
private void StopAllCharging()
{
for (int i = chargingPawns.Count - 1; i >= 0; i--)
{
StopCharging(chargingPawns[i]);
chargingPawns.RemoveAt(i);
} }
} }

View File

@@ -16,17 +16,18 @@ namespace WulaFallenEmpire
public override bool IsMet(out string reason) public override bool IsMet(out string reason)
{ {
if (!EventContext.HasVariable(name)) var eventVarManager = Find.World.GetComponent<EventVariableManager>();
if (!eventVarManager.HasVariable(name))
{ {
EventContext.SetVariable(name, "0"); eventVarManager.SetVariable(name, "0");
} }
object variable = EventContext.GetVariable<object>(name); object variable = eventVarManager.GetVariable<object>(name);
string compareValue = value; string compareValue = value;
if (!string.IsNullOrEmpty(valueVariableName)) if (!string.IsNullOrEmpty(valueVariableName))
{ {
compareValue = EventContext.GetVariable<object>(valueVariableName)?.ToString(); compareValue = eventVarManager.GetVariable<object>(valueVariableName)?.ToString();
if (compareValue == null) if (compareValue == null)
{ {
reason = $"Comparison variable '{valueVariableName}' not set."; reason = $"Comparison variable '{valueVariableName}' not set.";
@@ -58,17 +59,18 @@ namespace WulaFallenEmpire
public override bool IsMet(out string reason) public override bool IsMet(out string reason)
{ {
if (!EventContext.HasVariable(name)) var eventVarManager = Find.World.GetComponent<EventVariableManager>();
if (!eventVarManager.HasVariable(name))
{ {
EventContext.SetVariable(name, 0f); eventVarManager.SetVariable(name, 0f);
} }
float variable = EventContext.GetVariable<float>(name); float variable = eventVarManager.GetVariable<float>(name);
float compareValue = value; float compareValue = value;
if (!string.IsNullOrEmpty(valueVariableName)) if (!string.IsNullOrEmpty(valueVariableName))
{ {
compareValue = EventContext.GetVariable<float>(valueVariableName, float.NaN); compareValue = eventVarManager.GetVariable<float>(valueVariableName, float.NaN);
if (float.IsNaN(compareValue)) if (float.IsNaN(compareValue))
{ {
reason = $"Comparison variable '{valueVariableName}' not set or not a number."; reason = $"Comparison variable '{valueVariableName}' not set or not a number.";
@@ -121,17 +123,18 @@ namespace WulaFallenEmpire
public override bool IsMet(out string reason) public override bool IsMet(out string reason)
{ {
if (!EventContext.HasVariable(name)) var eventVarManager = Find.World.GetComponent<EventVariableManager>();
if (!eventVarManager.HasVariable(name))
{ {
EventContext.SetVariable(name, "0"); eventVarManager.SetVariable(name, "0");
} }
object variable = EventContext.GetVariable<object>(name); object variable = eventVarManager.GetVariable<object>(name);
string compareValue = value; string compareValue = value;
if (!string.IsNullOrEmpty(valueVariableName)) if (!string.IsNullOrEmpty(valueVariableName))
{ {
compareValue = EventContext.GetVariable<object>(valueVariableName)?.ToString(); compareValue = eventVarManager.GetVariable<object>(valueVariableName)?.ToString();
if (compareValue == null) if (compareValue == null)
{ {
reason = $"Comparison variable '{valueVariableName}' not set."; reason = $"Comparison variable '{valueVariableName}' not set.";

View File

@@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text.RegularExpressions;
using UnityEngine; using UnityEngine;
using Verse; using Verse;
@@ -11,7 +12,7 @@ namespace WulaFallenEmpire
private EventDef def; private EventDef def;
private Texture2D portrait; private Texture2D portrait;
private Texture2D background; private Texture2D background;
private string selectedDescription; // Store the chosen description for this window instance private string selectedDescription;
private static EventUIConfigDef config; private static EventUIConfigDef config;
public static EventUIConfigDef Config public static EventUIConfigDef Config
@@ -34,7 +35,7 @@ namespace WulaFallenEmpire
{ {
return def.windowSize; return def.windowSize;
} }
return Config.defaultWindowSize; // Fallback to size from config return Config.defaultWindowSize;
} }
} }
@@ -45,22 +46,22 @@ namespace WulaFallenEmpire
this.absorbInputAroundWindow = true; this.absorbInputAroundWindow = true;
this.doCloseX = true; this.doCloseX = true;
// Select the description text var eventVarManager = Find.World.GetComponent<EventVariableManager>();
if (!def.descriptions.NullOrEmpty()) if (!def.descriptions.NullOrEmpty())
{ {
if (def.descriptionMode == DescriptionSelectionMode.Random) if (def.descriptionMode == DescriptionSelectionMode.Random)
{ {
selectedDescription = def.descriptions.RandomElement(); selectedDescription = def.descriptions.RandomElement();
} }
else // Sequential else
{ {
string indexVarName = $"_seq_desc_index_{def.defName}"; string indexVarName = $"_seq_desc_index_{def.defName}";
int currentIndex = EventContext.GetVariable<int>(indexVarName, 0); int currentIndex = eventVarManager.GetVariable<int>(indexVarName, 0);
selectedDescription = def.descriptions[currentIndex]; selectedDescription = def.descriptions[currentIndex];
int nextIndex = (currentIndex + 1) % def.descriptions.Count; int nextIndex = (currentIndex + 1) % def.descriptions.Count;
EventContext.SetVariable(indexVarName, nextIndex); eventVarManager.SetVariable(indexVarName, nextIndex);
} }
} }
else else
@@ -85,7 +86,6 @@ namespace WulaFallenEmpire
HandleAction(def.immediateEffects); HandleAction(def.immediateEffects);
// Append conditional descriptions
if (!def.conditionalDescriptions.NullOrEmpty()) if (!def.conditionalDescriptions.NullOrEmpty())
{ {
foreach (var condDesc in def.conditionalDescriptions) foreach (var condDesc in def.conditionalDescriptions)
@@ -98,19 +98,16 @@ namespace WulaFallenEmpire
} }
} }
// Format the description AFTER immediate effects have run and conditional text is appended
selectedDescription = FormatDescription(selectedDescription); selectedDescription = FormatDescription(selectedDescription);
} }
public override void DoWindowContents(Rect inRect) public override void DoWindowContents(Rect inRect)
{ {
// 1. Draw Background
if (background != null) if (background != null)
{ {
GUI.DrawTexture(inRect, background, ScaleMode.ScaleToFit); GUI.DrawTexture(inRect, background, ScaleMode.ScaleToFit);
} }
// 2. Draw Top-left defName and Label
if (Config.showDefName) if (Config.showDefName)
{ {
Text.Font = GameFont.Tiny; Text.Font = GameFont.Tiny;
@@ -123,10 +120,9 @@ namespace WulaFallenEmpire
{ {
Text.Font = Config.labelFont; Text.Font = Config.labelFont;
Widgets.Label(new Rect(5, 20f, inRect.width - 10, 30f), def.label); Widgets.Label(new Rect(5, 20f, inRect.width - 10, 30f), def.label);
Text.Font = GameFont.Small; // Reset to default Text.Font = GameFont.Small;
} }
// 3. Calculate Layout based on ConfigDef
float virtualWidth = Config.lihuiSize.x + Config.textSize.x; float virtualWidth = Config.lihuiSize.x + Config.textSize.x;
float virtualHeight = Config.lihuiSize.y; float virtualHeight = Config.lihuiSize.y;
@@ -147,8 +143,6 @@ namespace WulaFallenEmpire
float startX = (inRect.width - totalContentWidth) / 2; float startX = (inRect.width - totalContentWidth) / 2;
float startY = (inRect.height - totalContentHeight) / 2; float startY = (inRect.height - totalContentHeight) / 2;
// 4. Draw UI Elements
// lihui (Portrait)
Rect lihuiRect = new Rect(startX, startY, scaledLihuiWidth, scaledLihuiHeight); Rect lihuiRect = new Rect(startX, startY, scaledLihuiWidth, scaledLihuiHeight);
if (portrait != null) if (portrait != null)
{ {
@@ -156,18 +150,13 @@ namespace WulaFallenEmpire
} }
if (Config.drawBorders) if (Config.drawBorders)
{ {
GUI.color = Color.white;
Widgets.DrawBox(lihuiRect); Widgets.DrawBox(lihuiRect);
GUI.color = Color.white;
} }
// name
Rect nameRect = new Rect(lihuiRect.xMax, lihuiRect.y, scaledNameWidth, scaledNameHeight); Rect nameRect = new Rect(lihuiRect.xMax, lihuiRect.y, scaledNameWidth, scaledNameHeight);
if (Config.drawBorders) if (Config.drawBorders)
{ {
GUI.color = Color.white;
Widgets.DrawBox(nameRect); Widgets.DrawBox(nameRect);
GUI.color = Color.white;
} }
Text.Anchor = TextAnchor.MiddleCenter; Text.Anchor = TextAnchor.MiddleCenter;
Text.Font = GameFont.Medium; Text.Font = GameFont.Medium;
@@ -175,18 +164,14 @@ namespace WulaFallenEmpire
Text.Font = GameFont.Small; Text.Font = GameFont.Small;
Text.Anchor = TextAnchor.UpperLeft; Text.Anchor = TextAnchor.UpperLeft;
// text (Description)
Rect textRect = new Rect(nameRect.x, nameRect.yMax + Config.textNameOffset * scale, scaledTextWidth, scaledTextHeight); Rect textRect = new Rect(nameRect.x, nameRect.yMax + Config.textNameOffset * scale, scaledTextWidth, scaledTextHeight);
if (Config.drawBorders) if (Config.drawBorders)
{ {
GUI.color = Color.white;
Widgets.DrawBox(textRect); Widgets.DrawBox(textRect);
GUI.color = Color.white;
} }
Rect textInnerRect = textRect.ContractedBy(10f * scale); Rect textInnerRect = textRect.ContractedBy(10f * scale);
Widgets.Label(textInnerRect, selectedDescription); // Use the selected description Widgets.Label(textInnerRect, selectedDescription);
// option (Buttons)
Rect optionRect = new Rect(nameRect.x, textRect.yMax + Config.optionsTextOffset * scale, scaledOptionsWidth, lihuiRect.height - nameRect.height - textRect.height - (Config.textNameOffset + Config.optionsTextOffset) * scale); Rect optionRect = new Rect(nameRect.x, textRect.yMax + Config.optionsTextOffset * scale, scaledOptionsWidth, lihuiRect.height - nameRect.height - textRect.height - (Config.textNameOffset + Config.optionsTextOffset) * scale);
Listing_Standard listing = new Listing_Standard(); Listing_Standard listing = new Listing_Standard();
@@ -209,7 +194,7 @@ namespace WulaFallenEmpire
{ {
if (option.hideWhenDisabled) if (option.hideWhenDisabled)
{ {
continue; // Skip rendering this option entirely continue;
} }
Rect rect = listing.GetRect(30f); Rect rect = listing.GetRect(30f);
Widgets.ButtonText(rect, option.label, false, true, false); Widgets.ButtonText(rect, option.label, false, true, false);
@@ -229,8 +214,7 @@ namespace WulaFallenEmpire
foreach (var ce in conditionalEffects) foreach (var ce in conditionalEffects)
{ {
string reason; if (AreConditionsMet(ce.conditions, out _))
if (AreConditionsMet(ce.conditions, out reason))
{ {
if (!ce.effects.NullOrEmpty()) if (!ce.effects.NullOrEmpty())
{ {
@@ -276,14 +260,21 @@ namespace WulaFallenEmpire
base.PostClose(); base.PostClose();
HandleAction(def.dismissEffects); HandleAction(def.dismissEffects);
} }
private string FormatDescription(string description) private string FormatDescription(string description)
{ {
var variables = EventContext.GetAllVariables(); var eventVarManager = Find.World.GetComponent<EventVariableManager>();
foreach (var variable in variables) // Use regex to find all placeholders like {variableName}
return Regex.Replace(description, @"\{(.+?)\}", match =>
{ {
description = description.Replace("{" + variable.Key + "}", variable.Value.ToString()); string varName = match.Groups[1].Value;
if (eventVarManager.HasVariable(varName))
{
// Important: GetVariable<object> to get any type
return eventVarManager.GetVariable<object>(varName)?.ToString() ?? "";
} }
return description; return match.Value; // Keep placeholder if variable not found
});
} }
} }
} }

View File

@@ -8,7 +8,6 @@ namespace WulaFallenEmpire
{ {
public abstract class Effect public abstract class Effect
{ {
// Allow the dialog to be null for contexts where there isn't one (like quests)
public abstract void Execute(Dialog_CustomDisplay dialog = null); public abstract void Execute(Dialog_CustomDisplay dialog = null);
} }
@@ -44,7 +43,6 @@ namespace WulaFallenEmpire
{ {
if (nextDef.hiddenWindow) if (nextDef.hiddenWindow)
{ {
// Since effects are merged in PostLoad, we only need to execute dismissEffects here.
if (!nextDef.dismissEffects.NullOrEmpty()) if (!nextDef.dismissEffects.NullOrEmpty())
{ {
foreach (var conditionalEffect in nextDef.dismissEffects) foreach (var conditionalEffect in nextDef.dismissEffects)
@@ -98,7 +96,6 @@ namespace WulaFallenEmpire
{ {
public override void Execute(Dialog_CustomDisplay dialog = null) public override void Execute(Dialog_CustomDisplay dialog = null)
{ {
// Only close the dialog if it exists
dialog?.Close(); dialog?.Close();
} }
} }
@@ -174,21 +171,20 @@ namespace WulaFallenEmpire
public override void Execute(Dialog_CustomDisplay dialog = null) public override void Execute(Dialog_CustomDisplay dialog = null)
{ {
// Only set the variable if it doesn't already exist. var eventVarManager = Find.World.GetComponent<EventVariableManager>();
if (!EventContext.HasVariable(name)) if (!eventVarManager.HasVariable(name))
{ {
// Try to parse as int, then float, otherwise keep as string
if (int.TryParse(value, out int intValue)) if (int.TryParse(value, out int intValue))
{ {
EventContext.SetVariable(name, intValue); eventVarManager.SetVariable(name, intValue);
} }
else if (float.TryParse(value, out float floatValue)) else if (float.TryParse(value, out float floatValue))
{ {
EventContext.SetVariable(name, floatValue); eventVarManager.SetVariable(name, floatValue);
} }
else else
{ {
EventContext.SetVariable(name, value); eventVarManager.SetVariable(name, value);
} }
} }
} }
@@ -214,7 +210,7 @@ namespace WulaFallenEmpire
return; return;
} }
int goodwillChange = EventContext.GetVariable<int>(goodwillVariableName); int goodwillChange = Find.World.GetComponent<EventVariableManager>().GetVariable<int>(goodwillVariableName);
Faction.OfPlayer.TryAffectGoodwillWith(targetFaction, goodwillChange, canSendMessage: true, canSendHostilityLetter: true, reason: null, lookTarget: null); Faction.OfPlayer.TryAffectGoodwillWith(targetFaction, goodwillChange, canSendMessage: true, canSendHostilityLetter: true, reason: null, lookTarget: null);
} }
} }
@@ -238,6 +234,7 @@ namespace WulaFallenEmpire
return; return;
} }
var eventVarManager = Find.World.GetComponent<EventVariableManager>();
List<Pawn> spawnedPawns = new List<Pawn>(); List<Pawn> spawnedPawns = new List<Pawn>();
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
{ {
@@ -249,11 +246,11 @@ namespace WulaFallenEmpire
if (count == 1) if (count == 1)
{ {
EventContext.SetVariable(storeAs, spawnedPawns.First()); eventVarManager.SetVariable(storeAs, spawnedPawns.First());
} }
else else
{ {
EventContext.SetVariable(storeAs, spawnedPawns); eventVarManager.SetVariable(storeAs, spawnedPawns);
} }
} }
} }
@@ -363,12 +360,14 @@ namespace WulaFallenEmpire
return; return;
} }
if (!EventContext.HasVariable(name)) var eventVarManager = Find.World.GetComponent<EventVariableManager>();
if (!eventVarManager.HasVariable(name))
{ {
EventContext.SetVariable(name, 0f); eventVarManager.SetVariable(name, 0f);
} }
float currentValue = EventContext.GetVariable<float>(name); float currentValue = eventVarManager.GetVariable<float>(name);
switch (operation) switch (operation)
{ {
@@ -396,7 +395,7 @@ namespace WulaFallenEmpire
break; break;
} }
EventContext.SetVariable(name, currentValue); eventVarManager.SetVariable(name, currentValue);
} }
} }
@@ -411,7 +410,7 @@ namespace WulaFallenEmpire
Log.Error("[WulaFallenEmpire] Effect_ClearVariable has a null or empty name."); Log.Error("[WulaFallenEmpire] Effect_ClearVariable has a null or empty name.");
return; return;
} }
EventContext.ClearVariable(name); Find.World.GetComponent<EventVariableManager>().ClearVariable(name);
} }
} }
@@ -476,7 +475,6 @@ namespace WulaFallenEmpire
return; return;
} }
// If custom pawn groups are defined, use them.
if (!pawnGroupMakers.NullOrEmpty()) if (!pawnGroupMakers.NullOrEmpty())
{ {
IncidentParms parms = new IncidentParms IncidentParms parms = new IncidentParms
@@ -502,67 +500,19 @@ namespace WulaFallenEmpire
tile = map.Tile, tile = map.Tile,
points = this.points, points = this.points,
faction = factionInst, faction = factionInst,
raidStrategy = this.raidStrategy,
seed = parms.pawnGroupMakerSeed seed = parms.pawnGroupMakerSeed
}; };
if (!pawnGroupMakers.TryRandomElement(out var chosenGroupMaker)) List<Pawn> pawns = PawnGroupMakerUtility.GeneratePawns(groupMakerParms).ToList();
if (pawns.Any())
{ {
Log.Error($"[WulaFallenEmpire] Effect_TriggerRaid could not find a suitable PawnGroupMaker for {points} points with groupKind {groupMakerParms.groupKind.defName} from the provided list."); raidArrivalMode.Worker.Arrive(pawns, parms);
return; if (!string.IsNullOrEmpty(letterLabel) && !string.IsNullOrEmpty(letterText))
{
Find.LetterStack.ReceiveLetter(letterLabel, letterText, LetterDefOf.ThreatBig, pawns[0]);
} }
List<Pawn> pawns = chosenGroupMaker.GeneratePawns(groupMakerParms).ToList();
if (!pawns.Any())
{
Log.Error("[WulaFallenEmpire] Effect_TriggerRaid generated no pawns with the custom pawnGroupMakers.");
return;
} }
parms.raidArrivalMode.Worker.Arrive(pawns, parms);
parms.raidStrategy.Worker.MakeLords(parms, pawns);
TaggedString finalLabel;
if (!string.IsNullOrEmpty(this.letterLabel))
{
finalLabel = this.letterLabel;
}
else
{
finalLabel = "LetterLabelRaid".Translate(factionInst.def.label).CapitalizeFirst();
}
TaggedString finalText;
if (!string.IsNullOrEmpty(this.letterText))
{
finalText = this.letterText;
}
else
{
finalText = "LetterRaid".Translate(
factionInst.Name,
factionInst.def.pawnsPlural,
parms.raidStrategy.arrivalTextEnemy
).CapitalizeFirst();
}
Pawn mostImportantPawn = pawns.FirstOrDefault();
TargetInfo target = mostImportantPawn != null ? new TargetInfo(mostImportantPawn) : new TargetInfo(parms.spawnCenter, map);
Find.LetterStack.ReceiveLetter(finalLabel, finalText, LetterDefOf.ThreatBig, target, factionInst);
}
else // Fallback to default raid incident worker
{
IncidentParms parms = new IncidentParms
{
target = map,
points = this.points,
faction = factionInst,
raidStrategy = this.raidStrategy,
raidArrivalMode = this.raidArrivalMode,
forced = true
};
IncidentDefOf.RaidEnemy.Worker.TryExecute(parms);
} }
} }
} }
@@ -571,33 +521,44 @@ namespace WulaFallenEmpire
{ {
public FactionDef factionDef; public FactionDef factionDef;
public string variableName; public string variableName;
public List<Effect> successEffects;
public List<Effect> failureEffects;
public override void Execute(Dialog_CustomDisplay dialog = null) public override void Execute(Dialog_CustomDisplay dialog = null)
{ {
if (factionDef == null) if (factionDef == null)
{ {
Log.Error("Effect_CheckFactionGoodwill requires a factionDef."); Log.Error("[WulaFallenEmpire] Effect_CheckFactionGoodwill has a null faction Def.");
return; return;
} }
if (string.IsNullOrEmpty(variableName))
Faction targetFaction = Find.FactionManager.FirstFactionOfDef(factionDef);
if (targetFaction == null)
{ {
Log.Error("Effect_CheckFactionGoodwill requires a variableName."); Log.Warning($"[WulaFallenEmpire] Could not find an active faction for FactionDef '{factionDef.defName}'.");
ExecuteEffects(failureEffects, dialog);
return; return;
} }
Faction faction = Find.FactionManager.FirstFactionOfDef(factionDef); int requiredGoodwill = Find.World.GetComponent<EventVariableManager>().GetVariable<int>(variableName);
if (faction == null) int currentGoodwill = Faction.OfPlayer.GoodwillWith(targetFaction);
if (currentGoodwill >= requiredGoodwill)
{ {
// Faction doesn't exist, store a default value (e.g., 0 or a specific marker) ExecuteEffects(successEffects, dialog);
EventContext.SetVariable(variableName, 0);
Log.Warning($"Faction with def {factionDef.defName} not found. Setting '{variableName}' to 0.");
return;
}
int goodwill = faction.GoodwillWith(Faction.OfPlayer);
EventContext.SetVariable(variableName, goodwill);
} }
else
{
ExecuteEffects(failureEffects, dialog);
} }
} }
private void ExecuteEffects(List<Effect> effects, Dialog_CustomDisplay dialog)
{
if (effects.NullOrEmpty()) return;
foreach (var effect in effects)
{
effect.Execute(dialog);
}
}
}
}

View File

@@ -1,74 +0,0 @@
using System.Collections.Generic;
using Verse;
namespace WulaFallenEmpire
{
public static class EventContext
{
private static Dictionary<string, object> variables = new Dictionary<string, object>();
public static void SetVariable(string name, object value)
{
if (variables.ContainsKey(name))
{
variables[name] = value;
}
else
{
variables.Add(name, value);
}
Log.Message($"[EventContext] Set variable '{name}' to '{value}'.");
}
public static T GetVariable<T>(string name, T defaultValue = default)
{
if (variables.TryGetValue(name, out object value))
{
if (value is T typedValue)
{
return typedValue;
}
// Try to convert, e.g., from int to float
try
{
return (T)System.Convert.ChangeType(value, typeof(T));
}
catch (System.Exception)
{
Log.Warning($"[EventContext] Variable '{name}' is of type {value.GetType()} but could not be converted to {typeof(T)}.");
return defaultValue;
}
}
Log.Warning($"[EventContext] Variable '{name}' not found. Returning default value.");
return defaultValue;
}
public static bool HasVariable(string name)
{
return variables.ContainsKey(name);
}
public static Dictionary<string, object> GetAllVariables()
{
return new Dictionary<string, object>(variables);
}
public static void Clear()
{
variables.Clear();
Log.Message("[EventContext] All variables cleared.");
}
public static void ClearVariable(string name)
{
if (variables.Remove(name))
{
Log.Message($"[EventContext] Cleared variable '{name}'.");
}
else
{
Log.Warning($"[EventContext] Tried to clear variable '{name}' but it was not found.");
}
}
}
}

View File

@@ -0,0 +1,162 @@
using System.Collections.Generic;
using Verse;
using RimWorld;
using RimWorld.Planet;
namespace WulaFallenEmpire
{
public class EventVariableManager : WorldComponent
{
private Dictionary<string, int> intVars = new Dictionary<string, int>();
private Dictionary<string, float> floatVars = new Dictionary<string, float>();
private Dictionary<string, string> stringVars = new Dictionary<string, string>();
private Dictionary<string, Pawn> pawnVars = new Dictionary<string, Pawn>();
private Dictionary<string, List<Pawn>> pawnListVars = new Dictionary<string, List<Pawn>>();
// 用于Scribe的辅助列表
private List<string> pawnVarKeys;
private List<Pawn> pawnVarValues;
private List<string> pawnListVarKeys;
private List<List<Pawn>> pawnListVarValues;
// Required for WorldComponent
public EventVariableManager(World world) : base(world)
{
}
public override void ExposeData()
{
base.ExposeData();
Scribe_Collections.Look(ref intVars, "intVars", LookMode.Value, LookMode.Value);
Scribe_Collections.Look(ref floatVars, "floatVars", LookMode.Value, LookMode.Value);
Scribe_Collections.Look(ref stringVars, "stringVars", LookMode.Value, LookMode.Value);
Scribe_Collections.Look(ref pawnVars, "pawnVars", LookMode.Value, LookMode.Reference, ref pawnVarKeys, ref pawnVarValues);
Scribe_Collections.Look(ref pawnListVars, "pawnListVars", LookMode.Value, LookMode.Reference, ref pawnListVarKeys, ref pawnListVarValues);
// Ensure dictionaries are not null after loading
if (Scribe.mode == LoadSaveMode.PostLoadInit)
{
intVars ??= new Dictionary<string, int>();
floatVars ??= new Dictionary<string, float>();
stringVars ??= new Dictionary<string, string>();
pawnVars ??= new Dictionary<string, Pawn>();
pawnListVars ??= new Dictionary<string, List<Pawn>>();
}
}
public void SetVariable(string name, object value)
{
if (string.IsNullOrEmpty(name)) return;
// Clear any existing variable with the same name to prevent type confusion
ClearVariable(name);
if (value is int intValue)
{
intVars[name] = intValue;
}
else if (value is float floatValue)
{
floatVars[name] = floatValue;
}
else if (value is string stringValue)
{
stringVars[name] = stringValue;
}
else if (value is Pawn pawnValue)
{
pawnVars[name] = pawnValue;
}
else if (value is List<Pawn> pawnListValue)
{
pawnListVars[name] = pawnListValue;
}
else if (value != null)
{
stringVars[name] = value.ToString();
Log.Warning($"[WulaFallenEmpire] EventVariableManager: Variable '{name}' of type {value.GetType()} was converted to string for storage. This may lead to unexpected behavior.");
}
}
public T GetVariable<T>(string name, T defaultValue = default)
{
if (string.IsNullOrEmpty(name)) return defaultValue;
object value = null;
bool found = false;
if (typeof(T) == typeof(List<Pawn>) && pawnListVars.TryGetValue(name, out var pawnListVal))
{
value = pawnListVal;
found = true;
}
else if (typeof(T) == typeof(Pawn) && pawnVars.TryGetValue(name, out var pawnVal))
{
value = pawnVal;
found = true;
}
else if (typeof(T) == typeof(float) && floatVars.TryGetValue(name, out var floatVal))
{
value = floatVal;
found = true;
}
else if (typeof(T) == typeof(int) && intVars.TryGetValue(name, out var intVal))
{
value = intVal;
found = true;
}
else if (stringVars.TryGetValue(name, out var stringVal))
{
value = stringVal;
found = true;
}
if (found)
{
if (value is T typedValue)
{
return typedValue;
}
try
{
return (T)System.Convert.ChangeType(value, typeof(T));
}
catch (System.Exception)
{
Log.Warning($"[WulaFallenEmpire] EventVariableManager: Variable '{name}' of type {value.GetType()} could not be converted to {typeof(T)}.");
return defaultValue;
}
}
return defaultValue;
}
public bool HasVariable(string name)
{
return intVars.ContainsKey(name) ||
floatVars.ContainsKey(name) ||
stringVars.ContainsKey(name) ||
pawnVars.ContainsKey(name) ||
pawnListVars.ContainsKey(name);
}
public void ClearVariable(string name)
{
intVars.Remove(name);
floatVars.Remove(name);
stringVars.Remove(name);
pawnVars.Remove(name);
pawnListVars.Remove(name);
}
public void ClearAll()
{
intVars.Clear();
floatVars.Clear();
stringVars.Clear();
pawnVars.Clear();
pawnListVars.Clear();
}
}
}

View File

@@ -0,0 +1,33 @@
using HarmonyLib;
using Verse;
using System.Reflection;
namespace WulaFallenEmpire
{
[HarmonyPatch(typeof(Pawn_HealthTracker), "get_CanBleed")]
public static class NoBloodForWula_CanBleed_Patch
{
public static void Postfix(Pawn_HealthTracker __instance, ref bool __result)
{
// 使用反射获取Pawn_HealthTracker的私有pawn字段
Pawn pawn = (Pawn)typeof(Pawn_HealthTracker).GetField("pawn", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(__instance);
if (pawn.def.defName == "WulaSpecies")
{
__result = false;
}
}
}
[HarmonyPatch(typeof(Hediff_Injury), "get_BleedRate")]
public static class NoBloodForWula_BleedRate_Patch
{
public static void Postfix(Hediff_Injury __instance, ref float __result)
{
if (__instance.pawn.def.defName == "WulaSpecies")
{
__result = 0f;
}
}
}
}

View File

@@ -1,45 +0,0 @@
using RimWorld;
using System.Collections.Generic;
using Verse;
using Verse.AI;
namespace WulaFallenEmpire
{
public class JobDriver_WulaLayDownToCharge : JobDriver
{
public override bool TryMakePreToilReservations(bool errorOnFailed)
{
return pawn.Reserve(job.targetA, job, 1, -1, null, errorOnFailed);
}
protected override IEnumerable<Toil> MakeNewToils()
{
yield return Toils_Bed.GotoBed(TargetIndex.A);
Toil layDownAndCharge = Toils_LayDown.LayDown(TargetIndex.A, true, false, false, false);
layDownAndCharge.tickAction = delegate
{
if (pawn.IsHashIntervalTick(60))
{
var bed = (Building_Bed)job.targetA.Thing;
var powerComp = bed.GetComp<CompPowerTrader>();
if (powerComp != null && !powerComp.PowerOn)
{
EndJobWith(JobCondition.Incompletable);
return;
}
Need_WulaEnergy energyNeed = pawn.needs.TryGetNeed<Need_WulaEnergy>();
if (energyNeed != null && energyNeed.CurLevelPercentage >= 0.99f)
{
EndJobWith(JobCondition.Succeeded);
}
}
};
yield return layDownAndCharge;
}
}
}

View File

@@ -8,60 +8,65 @@ namespace WulaFallenEmpire
public class JobGiver_WulaGetEnergy : ThinkNode_JobGiver public class JobGiver_WulaGetEnergy : ThinkNode_JobGiver
{ {
public float minEnergyLevelPercentage = 0.3f; public float minEnergyLevelPercentage = 0.3f;
public float maxEnergyLevelPercentage = 0.9f; public float maxEnergyLevelPercentage = 1.0f;
public float emergencyPriority = 9.5f; public float emergencyPriority = 9.5f;
public override float GetPriority(Pawn pawn) public override float GetPriority(Pawn pawn)
{ {
if (pawn.health.hediffSet.HasHediff(DefDatabase<HediffDef>.GetNamed("WULA_ChargingHediff"))) var energyNeed = pawn.needs.TryGetNeed<Need_WulaEnergy>();
{
Log.Message($"[JobGiver_WulaGetEnergy] {pawn.Name.ToStringShort} already has charging hediff. Priority 0.");
return 0f;
}
Need_WulaEnergy energyNeed = pawn.needs.TryGetNeed<Need_WulaEnergy>();
if (energyNeed == null) if (energyNeed == null)
{ {
return 0f; return 0f;
} }
// 如果能量已充满,则不需要充电
if (energyNeed.CurLevel >= energyNeed.MaxLevel)
{
return 0f;
}
// 如果Pawn正在执行充电Job并且能量尚未充满则保持高优先级
if ((pawn.CurJobDef == JobDefOf.LayDown ||
pawn.CurJobDef == DefDatabase<JobDef>.GetNamed("WULA_IngestWulaEnergy")) &&
energyNeed.CurLevel < energyNeed.MaxLevel)
{
return emergencyPriority; // 保持高优先级,直到充满
}
// 如果能量低于阈值,则需要充电
if (energyNeed.CurLevelPercentage < minEnergyLevelPercentage) if (energyNeed.CurLevelPercentage < minEnergyLevelPercentage)
{ {
return emergencyPriority; return emergencyPriority;
} }
return 0f;
return 0f; // 否则不需要充电返回0
} }
protected override Job TryGiveJob(Pawn pawn) protected override Job TryGiveJob(Pawn pawn)
{ {
Log.Message($"[JobGiver_WulaGetEnergy] Trying to give job to {pawn.Name.ToStringShort}."); var energyNeed = pawn.needs.TryGetNeed<Need_WulaEnergy>();
if (energyNeed == null)
if (pawn.health.hediffSet.HasHediff(DefDatabase<HediffDef>.GetNamed("WULA_ChargingHediff")))
{ {
Log.Message($"[JobGiver_WulaGetEnergy] {pawn.Name.ToStringShort} already has charging hediff. Job cancelled.");
return null; return null;
} }
Need_WulaEnergy energyNeed = pawn.needs.TryGetNeed<Need_WulaEnergy>(); if (energyNeed.CurLevelPercentage >= maxEnergyLevelPercentage)
if (energyNeed == null || energyNeed.CurLevelPercentage >= maxEnergyLevelPercentage)
{ {
Log.Message($"[JobGiver_WulaGetEnergy] Energy level for {pawn.Name.ToStringShort} is sufficient. Job cancelled.");
return null; return null;
} }
if (!TryFindBestEnergySourceFor(pawn, out Thing energySource)) if (!TryFindBestEnergySourceFor(pawn, out var energySource))
{ {
Log.Message($"[JobGiver_WulaGetEnergy] No energy source found for {pawn.Name.ToStringShort}. Job cancelled.");
return null; return null;
} }
if (energySource is Building_Bed) if (energySource is Building_Bed)
{ {
Log.Message($"[JobGiver_WulaGetEnergy] Found bed for {pawn.Name.ToStringShort}. Creating WULA_LayDownToCharge job."); return JobMaker.MakeJob(JobDefOf.LayDown, energySource);
return JobMaker.MakeJob(DefDatabase<JobDef>.GetNamed("WULA_LayDownToCharge"), energySource);
} }
Job job = JobMaker.MakeJob(DefDatabase<JobDef>.GetNamed("WULA_IngestWulaEnergy"), energySource); var job = JobMaker.MakeJob(DefDatabase<JobDef>.GetNamed("WULA_IngestWulaEnergy"), energySource);
job.count = 1; job.count = 1;
return job; return job;
} }
@@ -109,20 +114,16 @@ namespace WulaFallenEmpire
9999f, 9999f,
b => b =>
{ {
Building_Bed bed_internal = b as Building_Bed; if (!(b is Building_Bed bed_internal)) return false;
if (bed_internal == null) return false;
var chargingComp = bed_internal.GetComp<CompChargingBed>(); if (bed_internal.GetComp<CompChargingBed>() == null) return false;
if (chargingComp == null) return false;
var powerComp = bed_internal.GetComp<CompPowerTrader>(); var powerComp = bed_internal.GetComp<CompPowerTrader>();
return !bed_internal.IsForbidden(pawn) &&
pawn.CanReserve(bed_internal) && // 使用 pawn.CanReserve 是最可靠的方法,它包含了对 ملكية، حظر، منطقة، الخ 的所有检查。
!bed_internal.Medical && return powerComp != null &&
!bed_internal.IsBurning() &&
powerComp != null &&
powerComp.PowerOn && powerComp.PowerOn &&
!bed_internal.CurOccupants.Any(); pawn.CanReserve(bed_internal);
} }
); );
return bed; return bed;

View File

@@ -0,0 +1,13 @@
using Verse;
namespace WulaFallenEmpire
{
[StaticConstructorOnStartup]
public static class StartupLogger
{
static StartupLogger()
{
Log.Message("WulaFallenEmpire Mod DLL, version 1.0.2, has been loaded.");
}
}
}

View File

@@ -86,7 +86,7 @@
<Compile Include="EventSystem\DelayedActionManager.cs" /> <Compile Include="EventSystem\DelayedActionManager.cs" />
<Compile Include="EventSystem\Dialog_CustomDisplay.cs" /> <Compile Include="EventSystem\Dialog_CustomDisplay.cs" />
<Compile Include="EventSystem\Effect.cs" /> <Compile Include="EventSystem\Effect.cs" />
<Compile Include="EventSystem\EventContext.cs" /> <Compile Include="EventSystem\EventVariableManager.cs" />
<Compile Include="EventSystem\EventDef.cs" /> <Compile Include="EventSystem\EventDef.cs" />
<Compile Include="EventSystem\EventUIConfigDef.cs" /> <Compile Include="EventSystem\EventUIConfigDef.cs" />
<Compile Include="EventSystem\Letter_EventChoice.cs" /> <Compile Include="EventSystem\Letter_EventChoice.cs" />
@@ -97,6 +97,7 @@
<Compile Include="HarmonyPatches\MechanitorUtility_InMechanitorCommandRange_Patch.cs" /> <Compile Include="HarmonyPatches\MechanitorUtility_InMechanitorCommandRange_Patch.cs" />
<Compile Include="HarmonyPatches\Projectile_Launch_Patch.cs" /> <Compile Include="HarmonyPatches\Projectile_Launch_Patch.cs" />
<Compile Include="HarmonyPatches\Patch_JobGiver_GatherOfferingsForPsychicRitual.cs" /> <Compile Include="HarmonyPatches\Patch_JobGiver_GatherOfferingsForPsychicRitual.cs" />
<Compile Include="HarmonyPatches\NoBloodForWulaPatch.cs" />
<Compile Include="HediffComp_RegenerateBackstory.cs" /> <Compile Include="HediffComp_RegenerateBackstory.cs" />
<Compile Include="HediffComp_WulaCharging.cs" /> <Compile Include="HediffComp_WulaCharging.cs" />
<Compile Include="IngestPatch.cs" /> <Compile Include="IngestPatch.cs" />
@@ -104,7 +105,6 @@
<Compile Include="JobDriver_EnterMaintenancePod.cs" /> <Compile Include="JobDriver_EnterMaintenancePod.cs" />
<Compile Include="JobDriver_HaulToMaintenancePod.cs" /> <Compile Include="JobDriver_HaulToMaintenancePod.cs" />
<Compile Include="JobDriver_IngestWulaEnergy.cs" /> <Compile Include="JobDriver_IngestWulaEnergy.cs" />
<Compile Include="JobDriver_WulaLayDownToCharge.cs" />
<Compile Include="JobGiver_WulaGetEnergy.cs" /> <Compile Include="JobGiver_WulaGetEnergy.cs" />
<Compile Include="JobGiver_WulaPackEnergy.cs" /> <Compile Include="JobGiver_WulaPackEnergy.cs" />
<Compile Include="Job_Maintenance.cs" /> <Compile Include="Job_Maintenance.cs" />
@@ -151,6 +151,7 @@
<Compile Include="HediffComp_DamageResponse.cs" /> <Compile Include="HediffComp_DamageResponse.cs" />
<Compile Include="JobDefOf_WULA.cs" /> <Compile Include="JobDefOf_WULA.cs" />
<Compile Include="ThingDefOf_WULA.cs" /> <Compile Include="ThingDefOf_WULA.cs" />
<Compile Include="StartupLogger.cs" />
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- 自定义清理任务删除obj文件夹中的临时文件 --> <!-- 自定义清理任务删除obj文件夹中的临时文件 -->