This commit is contained in:
2025-07-22 19:07:21 +08:00
parent 4f524845a9
commit 15494e8a8e
26 changed files with 318 additions and 963 deletions

Binary file not shown.

View File

@@ -1,35 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Defs>
<AbilityDef>
<defName>WULA_EmergencyEnergyRestore</defName>
<label>后备隐藏能源超载</label>
<description>激活紧急能量协议暂时将能量需求锁定在100%持续10秒后恢复到原来的能量水平。只能在倒地时使用。</description>
<iconPath>UI/Abilities/MetalbloodInjection</iconPath>
<cooldownTicksRange>72000</cooldownTicksRange> <!-- 20分钟冷却 -->
<aiCanUse>true</aiCanUse>
<displayGizmoWhileUndrafted>true</displayGizmoWhileUndrafted>
<disableGizmoWhileUndrafted>false</disableGizmoWhileUndrafted>
<targetRequired>false</targetRequired>
<canUseAoeToGetTargets>false</canUseAoeToGetTargets>
<verbProperties>
<verbClass>Verb_CastAbility</verbClass>
<range>0</range>
<warmupTime>1</warmupTime>
<soundCast>Psycast_Skip_Entry</soundCast>
<targetParams>
<canTargetSelf>true</canTargetSelf>
<canTargetPawns>false</canTargetPawns>
<canTargetBuildings>false</canTargetBuildings>
</targetParams>
</verbProperties>
<comps>
<li Class="WulaFallenEmpire.CompProperties_AbilityEmergencyEnergyRestore">
<durationTicks>600</durationTicks> <!-- 10秒 -->
<hediffDef>WULA_EmergencyEnergyRestore_Hediff</hediffDef>
<requireDowned>true</requireDowned> <!-- 是否需要倒地才能使用 -->
</li>
</comps>
</AbilityDef>
</Defs>

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<HediffDef>
<defName>WULA_ChargingHediff</defName>
<label>能量充盈</label>
<description>乌拉正在从能量核心中持续吸收能量。</description>
<hediffClass>HediffWithComps</hediffClass>
<defaultLabelColor>(0.5, 0.5, 0.9)</defaultLabelColor>
<isBad>false</isBad>
<comps>
<li Class="WulaFallenEmpire.HediffCompProperties_WulaCharging">
<!-- 充能效果的总持续时间(以 tick 为单位60 ticks = 1 秒) -->
<durationTicks>600</durationTicks>
<!-- 备用能量恢复值:如果能量核心没有定义具体的能量值,则每 tick 恢复这么多能量 -->
<energyPerTick>0.02</energyPerTick>
</li>
</comps>
<stages>
<li>
<label>充能中</label>
<minSeverity>0</minSeverity>
</li>
</stages>
</HediffDef>
</Defs>

View File

@@ -1,31 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Defs>
<HediffDef>
<defName>WULA_EmergencyEnergyRestore_Hediff</defName>
<label>紧急能量恢复</label>
<description>紧急能量协议激活中能量需求被暂时锁定在100%。</description>
<hediffClass>WulaFallenEmpire.Hediff_EmergencyEnergyRestore</hediffClass>
<defaultLabelColor>(0.2, 0.8, 1.0)</defaultLabelColor>
<scenarioCanAdd>false</scenarioCanAdd>
<maxSeverity>1.0</maxSeverity>
<isBad>false</isBad>
<comps>
<li Class="HediffCompProperties_Disappears">
<disappearsAfterTicks>600</disappearsAfterTicks> <!-- 10秒 -->
<showRemainingTime>true</showRemainingTime>
</li>
</comps>
<stages>
<li>
<capMods>
<li>
<capacity>Consciousness</capacity>
<setMax>1.0</setMax>
</li>
</capMods>
</li>
</stages>
</HediffDef>
</Defs>

View File

@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<JobDef>
<defName>WULA_CastEmergencyEnergyRestore</defName>
<driverClass>WulaFallenEmpire.JobDriver_CastEmergencyEnergyRestore</driverClass>
<reportString>activating emergency energy restore.</reportString>
<suspendable>false</suspendable>
<neverShowWeapon>true</neverShowWeapon>
</JobDef>
</Defs>

View File

@@ -17,17 +17,24 @@
<Nutrition>1</Nutrition> <!-- Reverted to 1 as per user request --> <Nutrition>1</Nutrition> <!-- Reverted to 1 as per user request -->
</statBases> </statBases>
<ingestible> <ingestible>
<baseIngestTicks>270</baseIngestTicks>
<preferability>MealSimple</preferability> <!-- Reverted to MealSimple as per user request --> <preferability>MealSimple</preferability> <!-- Reverted to MealSimple as per user request -->
<optimalityOffsetHumanlikes>-1000</optimalityOffsetHumanlikes> <optimalityOffsetHumanlikes>-1000</optimalityOffsetHumanlikes>
<optimalityOffsetFeedingAnimals>-1000</optimalityOffsetFeedingAnimals> <optimalityOffsetFeedingAnimals>-1000</optimalityOffsetFeedingAnimals>
<ingestEffect>EatVegetarian</ingestEffect> <ingestEffect>EatVegetarian</ingestEffect>
<ingestSound>MechResurrectCast</ingestSound> <ingestSound>MechResurrectCast</ingestSound>
<outcomeDoers>
<li Class="IngestionOutcomeDoer_GiveHediff">
<hediffDef>WULA_ChargingHediff</hediffDef>
<severity>1.0</severity>
</li>
</outcomeDoers>
</ingestible> </ingestible>
<allowedArchonexusCount>200</allowedArchonexusCount> <allowedArchonexusCount>200</allowedArchonexusCount>
<tradeability>None</tradeability> <tradeability>None</tradeability>
<modExtensions> <modExtensions>
<li Class="WulaFallenEmpire.ThingDefExtension_EnergySource"> <li Class="WulaFallenEmpire.ThingDefExtension_EnergySource">
<energyAmount>1.0</energyAmount> <!-- Amount of energy this item provides --> <energyAmount>12.0</energyAmount> <!-- Amount of energy this item provides -->
</li> </li>
</modExtensions> </modExtensions>
</ThingDef> </ThingDef>

View File

@@ -184,7 +184,10 @@
<li Class="ThinkNode_PrioritySorter"> <li Class="ThinkNode_PrioritySorter">
<subNodes> <subNodes>
<li Class="JobGiver_Autofeed" MayRequire="Ludeon.RimWorld.Biotech" /> <li Class="JobGiver_Autofeed" MayRequire="Ludeon.RimWorld.Biotech" />
<li Class="WulaFallenEmpire.JobGiver_WulaGetEnergy"/> <li Class="WulaFallenEmpire.JobGiver_WulaGetEnergy">
<minEnergyLevelPercentage>0.3</minEnergyLevelPercentage>
<maxEnergyLevelPercentage>0.9</maxEnergyLevelPercentage>
</li>
<li Class="JobGiver_GetRest"/> <li Class="JobGiver_GetRest"/>
<li Class="JobGiver_SatisfyChemicalNeed"/> <li Class="JobGiver_SatisfyChemicalNeed"/>
<li Class="JobGiver_SatifyChemicalDependency" MayRequire="Ludeon.RimWorld.Biotech" /> <li Class="JobGiver_SatifyChemicalDependency" MayRequire="Ludeon.RimWorld.Biotech" />
@@ -272,12 +275,11 @@
<subNodes> <subNodes>
<li Class="WulaFallenEmpire.JobGiver_WulaGetEnergy"> <li Class="WulaFallenEmpire.JobGiver_WulaGetEnergy">
<leaveJoinableLordIfIssuesJob>true</leaveJoinableLordIfIssuesJob> <leaveJoinableLordIfIssuesJob>true</leaveJoinableLordIfIssuesJob>
<minEnergyLevelPercentage>0.5</minEnergyLevelPercentage>
<emergencyThreshold>0.1</emergencyThreshold>
<normalPriority>5</normalPriority>
<emergencyPriority>9.5</emergencyPriority>
<searchRadius>30</searchRadius> <!-- 搜索半径调整为30 --> <searchRadius>30</searchRadius> <!-- 搜索半径调整为30 -->
<ingestCount>1</ingestCount> <!-- 每次摄取1个能量核心 --> <ingestCount>1</ingestCount> <!-- 每次摄取1个能量核心 -->
<minEnergyLevelPercentage>0.3</minEnergyLevelPercentage>
<maxEnergyLevelPercentage>0.9</maxEnergyLevelPercentage>
<emergencyPriority>9.5</emergencyPriority>
</li> </li>
</subNodes> </subNodes>
</li> </li>

View File

@@ -66,7 +66,7 @@
</requiredCapacities> </requiredCapacities>
<modExtensions> <modExtensions>
<li Class="WulaFallenEmpire.WorkGiverDefExtension_FeedWula"> <li Class="WulaFallenEmpire.WorkGiverDefExtension_FeedWula">
<energySourceDef>WULA_Charge_Cube</energySourceDef> <feedThreshold>0.25</feedThreshold>
</li> </li>
</modExtensions> </modExtensions>
</WorkGiverDef> </WorkGiverDef>
@@ -84,7 +84,7 @@
</requiredCapacities> </requiredCapacities>
<modExtensions> <modExtensions>
<li Class="WulaFallenEmpire.WorkGiverDefExtension_FeedWula"> <li Class="WulaFallenEmpire.WorkGiverDefExtension_FeedWula">
<energySourceDef>WULA_Charge_Cube</energySourceDef> <feedThreshold>0.25</feedThreshold>
</li> </li>
</modExtensions> </modExtensions>
</WorkGiverDef> </WorkGiverDef>
@@ -102,7 +102,7 @@
</requiredCapacities> </requiredCapacities>
<modExtensions> <modExtensions>
<li Class="WulaFallenEmpire.WorkGiverDefExtension_FeedWula"> <li Class="WulaFallenEmpire.WorkGiverDefExtension_FeedWula">
<energySourceDef>WULA_Charge_Cube</energySourceDef> <feedThreshold>0.8</feedThreshold>
</li> </li>
</modExtensions> </modExtensions>
</WorkGiverDef> </WorkGiverDef>

View File

@@ -3,32 +3,24 @@
"WorkspaceRootPath": "C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\3516260226\\Source\\WulaFallenEmpire\\", "WorkspaceRootPath": "C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\3516260226\\Source\\WulaFallenEmpire\\",
"Documents": [ "Documents": [
{ {
"AbsoluteMoniker": "D:0:0:{F5AE8C3B-0221-4C16-A128-9A62D521A8FF}|WulaFallenEmpire.csproj|c:\\steam\\steamapps\\common\\rimworld\\mods\\3516260226\\source\\wulafallenempire\\jobgiver_wulapackenergy.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", "AbsoluteMoniker": "D:0:0:{F5AE8C3B-0221-4C16-A128-9A62D521A8FF}|WulaFallenEmpire.csproj|c:\\steam\\steamapps\\common\\rimworld\\mods\\3516260226\\source\\wulafallenempire\\ingestpatch.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{F5AE8C3B-0221-4C16-A128-9A62D521A8FF}|WulaFallenEmpire.csproj|solutionrelative:jobgiver_wulapackenergy.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" "RelativeMoniker": "D:0:0:{F5AE8C3B-0221-4C16-A128-9A62D521A8FF}|WulaFallenEmpire.csproj|solutionrelative:ingestpatch.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
}, },
{ {
"AbsoluteMoniker": "D:0:0:{F5AE8C3B-0221-4C16-A128-9A62D521A8FF}|WulaFallenEmpire.csproj|C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\3516260226\\Source\\WulaFallenEmpire\\jobgiver_wulagetenergy.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", "AbsoluteMoniker": "D:0:0:{F5AE8C3B-0221-4C16-A128-9A62D521A8FF}|WulaFallenEmpire.csproj|C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\3516260226\\Source\\WulaFallenEmpire\\hediffcomp_regeneratebackstory.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{F5AE8C3B-0221-4C16-A128-9A62D521A8FF}|WulaFallenEmpire.csproj|solutionrelative:jobgiver_wulagetenergy.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" "RelativeMoniker": "D:0:0:{F5AE8C3B-0221-4C16-A128-9A62D521A8FF}|WulaFallenEmpire.csproj|solutionrelative:hediffcomp_regeneratebackstory.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
},
{
"AbsoluteMoniker": "D:0:0:{F5AE8C3B-0221-4C16-A128-9A62D521A8FF}|WulaFallenEmpire.csproj|c:\\steam\\steamapps\\common\\rimworld\\mods\\3516260226\\source\\wulafallenempire\\compuseeffect_wulaskilltrainer.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{F5AE8C3B-0221-4C16-A128-9A62D521A8FF}|WulaFallenEmpire.csproj|solutionrelative:compuseeffect_wulaskilltrainer.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
},
{
"AbsoluteMoniker": "D:0:0:{F5AE8C3B-0221-4C16-A128-9A62D521A8FF}|WulaFallenEmpire.csproj|C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\3516260226\\Source\\WulaFallenEmpire\\wulafallenempiremod.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{F5AE8C3B-0221-4C16-A128-9A62D521A8FF}|WulaFallenEmpire.csproj|solutionrelative:wulafallenempiremod.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
}, },
{ {
"AbsoluteMoniker": "D:0:0:{F5AE8C3B-0221-4C16-A128-9A62D521A8FF}|WulaFallenEmpire.csproj|C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\3516260226\\Source\\WulaFallenEmpire\\building_wula_darkenergy_engine.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", "AbsoluteMoniker": "D:0:0:{F5AE8C3B-0221-4C16-A128-9A62D521A8FF}|WulaFallenEmpire.csproj|C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\3516260226\\Source\\WulaFallenEmpire\\building_wula_darkenergy_engine.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{F5AE8C3B-0221-4C16-A128-9A62D521A8FF}|WulaFallenEmpire.csproj|solutionrelative:building_wula_darkenergy_engine.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" "RelativeMoniker": "D:0:0:{F5AE8C3B-0221-4C16-A128-9A62D521A8FF}|WulaFallenEmpire.csproj|solutionrelative:building_wula_darkenergy_engine.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
}, },
{ {
"AbsoluteMoniker": "D:0:0:{F5AE8C3B-0221-4C16-A128-9A62D521A8FF}|WulaFallenEmpire.csproj|C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\3516260226\\Source\\WulaFallenEmpire\\ingestpatch.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", "AbsoluteMoniker": "D:0:0:{F5AE8C3B-0221-4C16-A128-9A62D521A8FF}|WulaFallenEmpire.csproj|C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\3516260226\\Source\\WulaFallenEmpire\\compuseeffect_wulaskilltrainer.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{F5AE8C3B-0221-4C16-A128-9A62D521A8FF}|WulaFallenEmpire.csproj|solutionrelative:ingestpatch.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" "RelativeMoniker": "D:0:0:{F5AE8C3B-0221-4C16-A128-9A62D521A8FF}|WulaFallenEmpire.csproj|solutionrelative:compuseeffect_wulaskilltrainer.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
}, },
{ {
"AbsoluteMoniker": "D:0:0:{F5AE8C3B-0221-4C16-A128-9A62D521A8FF}|WulaFallenEmpire.csproj|C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\3516260226\\Source\\WulaFallenEmpire\\hediffcomp_regeneratebackstory.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", "AbsoluteMoniker": "D:0:0:{F5AE8C3B-0221-4C16-A128-9A62D521A8FF}|WulaFallenEmpire.csproj|C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\3516260226\\Source\\WulaFallenEmpire\\wulafallenempiremod.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{F5AE8C3B-0221-4C16-A128-9A62D521A8FF}|WulaFallenEmpire.csproj|solutionrelative:hediffcomp_regeneratebackstory.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" "RelativeMoniker": "D:0:0:{F5AE8C3B-0221-4C16-A128-9A62D521A8FF}|WulaFallenEmpire.csproj|solutionrelative:wulafallenempiremod.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
}, },
{ {
"AbsoluteMoniker": "D:0:0:{F5AE8C3B-0221-4C16-A128-9A62D521A8FF}|WulaFallenEmpire.csproj|C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\3516260226\\Source\\WulaFallenEmpire\\mechanitorpatch.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", "AbsoluteMoniker": "D:0:0:{F5AE8C3B-0221-4C16-A128-9A62D521A8FF}|WulaFallenEmpire.csproj|C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\3516260226\\Source\\WulaFallenEmpire\\mechanitorpatch.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
@@ -42,7 +34,7 @@
"DocumentGroups": [ "DocumentGroups": [
{ {
"DockedWidth": 200, "DockedWidth": 200,
"SelectedChildIndex": 2, "SelectedChildIndex": 1,
"Children": [ "Children": [
{ {
"$type": "Bookmark", "$type": "Bookmark",
@@ -50,7 +42,20 @@
}, },
{ {
"$type": "Document", "$type": "Document",
"DocumentIndex": 2, "DocumentIndex": 0,
"Title": "IngestPatch.cs",
"DocumentMoniker": "C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\3516260226\\Source\\WulaFallenEmpire\\IngestPatch.cs",
"RelativeDocumentMoniker": "IngestPatch.cs",
"ToolTip": "C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\3516260226\\Source\\WulaFallenEmpire\\IngestPatch.cs",
"RelativeToolTip": "IngestPatch.cs",
"ViewState": "AQIAACUAAAAAAAAAAAAAwEcAAAAJAAAA",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-07-20T17:09:27.916Z",
"EditorCaption": ""
},
{
"$type": "Document",
"DocumentIndex": 3,
"Title": "CompUseEffect_WulaSkillTrainer.cs", "Title": "CompUseEffect_WulaSkillTrainer.cs",
"DocumentMoniker": "C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\3516260226\\Source\\WulaFallenEmpire\\CompUseEffect_WulaSkillTrainer.cs", "DocumentMoniker": "C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\3516260226\\Source\\WulaFallenEmpire\\CompUseEffect_WulaSkillTrainer.cs",
"RelativeDocumentMoniker": "CompUseEffect_WulaSkillTrainer.cs", "RelativeDocumentMoniker": "CompUseEffect_WulaSkillTrainer.cs",
@@ -58,38 +63,11 @@
"RelativeToolTip": "CompUseEffect_WulaSkillTrainer.cs", "RelativeToolTip": "CompUseEffect_WulaSkillTrainer.cs",
"ViewState": "AQIAAEAAAAAAAAAAAAAUwFMAAAABAAAA", "ViewState": "AQIAAEAAAAAAAAAAAAAUwFMAAAABAAAA",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-07-22T07:52:56.407Z", "WhenOpened": "2025-07-22T07:52:56.407Z"
"EditorCaption": ""
}, },
{ {
"$type": "Document", "$type": "Document",
"DocumentIndex": 0, "DocumentIndex": 2,
"Title": "JobGiver_WulaPackEnergy.cs",
"DocumentMoniker": "C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\3516260226\\Source\\WulaFallenEmpire\\JobGiver_WulaPackEnergy.cs",
"RelativeDocumentMoniker": "JobGiver_WulaPackEnergy.cs",
"ToolTip": "C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\3516260226\\Source\\WulaFallenEmpire\\JobGiver_WulaPackEnergy.cs",
"RelativeToolTip": "JobGiver_WulaPackEnergy.cs",
"ViewState": "AQIAAAAAAAAAAAAAAAAAAAgAAAAoAAAA",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-07-22T07:19:52.552Z",
"EditorCaption": ""
},
{
"$type": "Document",
"DocumentIndex": 1,
"Title": "JobGiver_WulaGetEnergy.cs",
"DocumentMoniker": "C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\3516260226\\Source\\WulaFallenEmpire\\JobGiver_WulaGetEnergy.cs",
"RelativeDocumentMoniker": "JobGiver_WulaGetEnergy.cs",
"ToolTip": "C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\3516260226\\Source\\WulaFallenEmpire\\JobGiver_WulaGetEnergy.cs",
"RelativeToolTip": "JobGiver_WulaGetEnergy.cs",
"ViewState": "AQIAADsAAAAAAAAAAAAUwGEAAAAlAAAA",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-07-22T07:19:46.094Z",
"EditorCaption": ""
},
{
"$type": "Document",
"DocumentIndex": 4,
"Title": "Building_Wula_DarkEnergy_Engine.cs", "Title": "Building_Wula_DarkEnergy_Engine.cs",
"DocumentMoniker": "C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\3516260226\\Source\\WulaFallenEmpire\\Building_Wula_DarkEnergy_Engine.cs", "DocumentMoniker": "C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\3516260226\\Source\\WulaFallenEmpire\\Building_Wula_DarkEnergy_Engine.cs",
"RelativeDocumentMoniker": "Building_Wula_DarkEnergy_Engine.cs", "RelativeDocumentMoniker": "Building_Wula_DarkEnergy_Engine.cs",
@@ -101,19 +79,7 @@
}, },
{ {
"$type": "Document", "$type": "Document",
"DocumentIndex": 5, "DocumentIndex": 1,
"Title": "IngestPatch.cs",
"DocumentMoniker": "C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\3516260226\\Source\\WulaFallenEmpire\\IngestPatch.cs",
"RelativeDocumentMoniker": "IngestPatch.cs",
"ToolTip": "C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\3516260226\\Source\\WulaFallenEmpire\\IngestPatch.cs",
"RelativeToolTip": "IngestPatch.cs",
"ViewState": "AQIAACEAAAAAAAAAAAAowEwAAAAAAAAA",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-07-20T17:09:27.916Z"
},
{
"$type": "Document",
"DocumentIndex": 6,
"Title": "HediffComp_RegenerateBackstory.cs", "Title": "HediffComp_RegenerateBackstory.cs",
"DocumentMoniker": "C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\3516260226\\Source\\WulaFallenEmpire\\HediffComp_RegenerateBackstory.cs", "DocumentMoniker": "C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\3516260226\\Source\\WulaFallenEmpire\\HediffComp_RegenerateBackstory.cs",
"RelativeDocumentMoniker": "HediffComp_RegenerateBackstory.cs", "RelativeDocumentMoniker": "HediffComp_RegenerateBackstory.cs",
@@ -125,7 +91,7 @@
}, },
{ {
"$type": "Document", "$type": "Document",
"DocumentIndex": 3, "DocumentIndex": 4,
"Title": "WulaFallenEmpireMod.cs", "Title": "WulaFallenEmpireMod.cs",
"DocumentMoniker": "C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\3516260226\\Source\\WulaFallenEmpire\\WulaFallenEmpireMod.cs", "DocumentMoniker": "C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\3516260226\\Source\\WulaFallenEmpire\\WulaFallenEmpireMod.cs",
"RelativeDocumentMoniker": "WulaFallenEmpireMod.cs", "RelativeDocumentMoniker": "WulaFallenEmpireMod.cs",
@@ -133,8 +99,7 @@
"RelativeToolTip": "WulaFallenEmpireMod.cs", "RelativeToolTip": "WulaFallenEmpireMod.cs",
"ViewState": "AQIAAAAAAAAAAAAAAAAAAA4AAAA+AAAA", "ViewState": "AQIAAAAAAAAAAAAAAAAAAA4AAAA+AAAA",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-07-18T10:23:17.898Z", "WhenOpened": "2025-07-18T10:23:17.898Z"
"EditorCaption": ""
}, },
{ {
"$type": "Bookmark", "$type": "Bookmark",
@@ -142,7 +107,7 @@
}, },
{ {
"$type": "Document", "$type": "Document",
"DocumentIndex": 7, "DocumentIndex": 5,
"Title": "MechanitorPatch.cs", "Title": "MechanitorPatch.cs",
"DocumentMoniker": "C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\3516260226\\Source\\WulaFallenEmpire\\MechanitorPatch.cs", "DocumentMoniker": "C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\3516260226\\Source\\WulaFallenEmpire\\MechanitorPatch.cs",
"RelativeDocumentMoniker": "MechanitorPatch.cs", "RelativeDocumentMoniker": "MechanitorPatch.cs",

View File

@@ -1,60 +0,0 @@
using RimWorld;
using Verse;
namespace WulaFallenEmpire
{
public class CompAbilityEffect_EmergencyEnergyRestore : CompAbilityEffect
{
public new CompProperties_AbilityEmergencyEnergyRestore Props => (CompProperties_AbilityEmergencyEnergyRestore)props;
public override void Apply(LocalTargetInfo target, LocalTargetInfo dest)
{
Log.Message($"[EmergencyEnergyRestore] Apply method called for {parent.pawn?.LabelShort}");
base.Apply(target, dest);
Pawn caster = parent.pawn;
if (caster == null) return;
// 检查是否是乌拉族
if (!IsWulaRace(caster))
{
Messages.Message("只有乌拉族才能使用紧急能量恢复", MessageTypeDefOf.RejectInput, false);
return;
}
// 检查是否倒地(如果需要的话)
if (Props.requireDowned && !caster.Downed)
{
Messages.Message("只能在倒地时使用紧急能量恢复", MessageTypeDefOf.RejectInput, false);
return;
}
// 添加Hediff
if (Props.hediffDef != null)
{
var hediff = HediffMaker.MakeHediff(Props.hediffDef, caster);
caster.health.AddHediff(hediff);
Messages.Message($"{caster.LabelShort}激活了紧急能量恢复协议", MessageTypeDefOf.PositiveEvent, false);
if (Prefs.DevMode)
{
Log.Message($"[EmergencyEnergyRestore] Applied to {caster.LabelShort}");
}
}
}
public override bool CanApplyOn(LocalTargetInfo target, LocalTargetInfo dest)
{
Log.Message($"[EmergencyEnergyRestore] CanApplyOn called. Pawn: {parent.pawn?.LabelShort}");
// 暂时强制返回true以排除CanApplyOn的限制
return true;
}
private bool IsWulaRace(Pawn pawn)
{
if (pawn?.def == null) return false;
return pawn.def.defName == "WulaSpecies";
}
}
}

View File

@@ -1,18 +0,0 @@
using RimWorld;
using Verse;
namespace WulaFallenEmpire
{
public class CompProperties_AbilityEmergencyEnergyRestore : CompProperties_AbilityEffect
{
public int durationTicks = 600; // 默认10秒
public HediffDef hediffDef;
public bool requireDowned = true; // 是否需要倒地才能使用
public SoundDef soundCast;
public CompProperties_AbilityEmergencyEnergyRestore()
{
compClass = typeof(CompAbilityEffect_EmergencyEnergyRestore);
}
}
}

View File

@@ -1,122 +0,0 @@
using HarmonyLib;
using RimWorld;
using System; // Added for Type
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
using Verse;
namespace WulaFallenEmpire
{
[HarmonyPatch]
public static class EmergencyAbilityPatches
{
// 修复倒地时无法使用能力的问题
[HarmonyPatch(typeof(Ability), "get_CanCast")]
[HarmonyPostfix]
public static void CanCast_Postfix(Ability __instance, ref AcceptanceReport __result)
{
if (__instance.def.defName == "WULA_EmergencyEnergyRestore")
{
var comp = __instance.CompOfType<CompAbilityEffect_EmergencyEnergyRestore>();
if (comp != null && comp.Props.requireDowned)
{
if (!__instance.pawn.Downed)
{
__result = new AcceptanceReport("只能在倒地时使用");
}
else
{
__result = true;
}
}
}
}
// 修复倒地时无法显示能力按钮的问题
[HarmonyPatch(typeof(Pawn_AbilityTracker), "get_AllAbilitiesForReading")]
[HarmonyPostfix]
public static void GetAbilitiesForDisplay_Postfix(Pawn_AbilityTracker __instance, ref List<Ability> __result)
{
// 检查pawn是否倒地
if (__instance.pawn.Downed)
{
// 添加紧急能量恢复能力即使pawn倒地
foreach (Ability ability in __instance.abilities)
{
if (ability.def.defName == "WULA_EmergencyEnergyRestore" && !__result.Contains(ability))
{
__result.Add(ability);
}
}
}
}
// 修复倒地时无法使用能力的UI限制 - 直接修补Ability.GizmoDisabled方法
[HarmonyPatch(typeof(Ability), "GizmoDisabled")]
[HarmonyPostfix]
public static void Ability_GizmoDisabled_Postfix(Ability __instance, ref bool __result, ref string reason)
{
if (__instance.def.defName == "WULA_EmergencyEnergyRestore")
{
if (__result)
{
// 检查是否是因为倒地而被禁用
if (__instance.pawn.Downed && reason != null &&
(reason.Contains("失去知觉") || reason.Contains("unconscious") || reason.Contains("CommandDisabledUnconscious")))
{
// 对于紧急能量恢复能力,我们允许在倒地时使用
__result = false;
reason = null;
}
}
}
}
// 额外的安全措施修复Command_Ability的禁用检查
[HarmonyPatch(typeof(Command_Ability), "get_Disabled")]
[HarmonyPostfix]
public static void Command_Ability_GizmoDisabled_Postfix(Command_Ability __instance, ref bool __result)
{
var ability = (Ability)typeof(Command_Ability).GetField("ability", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(__instance);
if (ability.def.defName == "WULA_EmergencyEnergyRestore")
{
if (__result && ability.pawn.Downed)
{
// 对于紧急能量恢复能力,我们允许在倒地时使用
__result = false;
}
}
}
// 新增补丁检查ApparelPreventsShooting是否阻止了施法
[HarmonyPatch(typeof(Verb), "ApparelPreventsShooting")]
[HarmonyPostfix]
public static void ApparelPreventsShooting_Postfix(Verb __instance, ref bool __result)
{
if (__instance is Verb_CastAbility castAbilityVerb && castAbilityVerb.ability?.def.defName == "WULA_EmergencyEnergyRestore")
{
}
}
// 最终诊断补丁检查Verb.TryStartCastOn是否被调用
[HarmonyPatch(typeof(Verb), "TryStartCastOn", new Type[] { typeof(LocalTargetInfo), typeof(LocalTargetInfo), typeof(bool), typeof(bool), typeof(bool), typeof(bool) })]
[HarmonyPrefix]
public static void TryStartCastOn_DiagnosticPrefix(Verb __instance, LocalTargetInfo castTarg, LocalTargetInfo destTarg, ref bool __result)
{
if (__instance is Verb_CastAbility castAbilityVerb && castAbilityVerb.ability?.def.defName == "WULA_EmergencyEnergyRestore")
{
}
}
// 诊断补丁检查Verb_CastAbility.TryCastShot是否被调用
[HarmonyPatch(typeof(Verb_CastAbility), "TryCastShot")]
[HarmonyPrefix]
public static void TryCastShot_DiagnosticPrefix(Verb_CastAbility __instance, ref bool __result)
{
if (__instance.ability?.def.defName == "WULA_EmergencyEnergyRestore")
{
}
}
}
}

View File

@@ -0,0 +1,65 @@
using Verse;
using RimWorld;
namespace WulaFallenEmpire
{
public class HediffCompProperties_WulaCharging : HediffCompProperties
{
public float energyPerTick = 0.001f; // 每tick补充的能量量
public int durationTicks = 600; // 持续时间例如600ticks = 10秒
public HediffCompProperties_WulaCharging()
{
this.compClass = typeof(HediffComp_WulaCharging);
}
}
public class HediffComp_WulaCharging : HediffComp
{
public HediffCompProperties_WulaCharging Props => (HediffCompProperties_WulaCharging)this.props;
private int ticksPassed = 0;
private Thing sourceThing; // 新增字段,用于存储能量核心物品
public void SetSourceThing(Thing thing)
{
this.sourceThing = thing;
}
public override void CompPostTick(ref float severityAdjustment)
{
base.CompPostTick(ref severityAdjustment);
ticksPassed++;
if (ticksPassed >= Props.durationTicks)
{
// 持续时间结束移除Hediff
this.parent.pawn.health.RemoveHediff(this.parent);
return;
}
Need_WulaEnergy energyNeed = this.parent.pawn.needs.TryGetNeed<Need_WulaEnergy>();
if (energyNeed != null)
{
// 从sourceThing的ThingDefExtension_EnergySource获取能量量
ThingDefExtension_EnergySource ext = sourceThing?.def.GetModExtension<ThingDefExtension_EnergySource>();
if (ext != null)
{
energyNeed.CurLevel += ext.energyAmount / Props.durationTicks; // 将总能量量分摊到每个tick
}
else
{
// 如果没有找到能量来源扩展则使用默认的energyPerTick
energyNeed.CurLevel += Props.energyPerTick;
}
}
}
public override void CompExposeData()
{
base.CompExposeData();
Scribe_Values.Look(ref ticksPassed, "ticksPassed", 0);
Scribe_References.Look(ref sourceThing, "sourceThing"); // 保存sourceThing
}
}
}

View File

@@ -1,71 +0,0 @@
using RimWorld;
using Verse;
namespace WulaFallenEmpire
{
public class Hediff_EmergencyEnergyRestore : HediffWithComps
{
private float originalEnergyLevel = 0f;
private bool hasStoredOriginalLevel = false;
public override void PostAdd(DamageInfo? dinfo)
{
base.PostAdd(dinfo);
// 存储原始能量水平
var energyNeed = pawn.needs?.TryGetNeed<Need_WulaEnergy>();
if (energyNeed != null)
{
originalEnergyLevel = energyNeed.CurLevel;
hasStoredOriginalLevel = true;
// 立即将能量设置为100%
energyNeed.CurLevel = 1.0f;
if (Prefs.DevMode)
{
Log.Message($"[EmergencyEnergyRestore] Stored original energy: {originalEnergyLevel:F2}, set to 1.0");
}
}
}
public override void PostRemoved()
{
base.PostRemoved();
// 恢复原始能量水平
if (hasStoredOriginalLevel)
{
var energyNeed = pawn.needs?.TryGetNeed<Need_WulaEnergy>();
if (energyNeed != null)
{
energyNeed.CurLevel = originalEnergyLevel;
if (Prefs.DevMode)
{
Log.Message($"[EmergencyEnergyRestore] Restored energy to: {originalEnergyLevel:F2}");
}
}
}
}
public override void Tick()
{
base.Tick();
// 确保能量保持在100%
var energyNeed = pawn.needs?.TryGetNeed<Need_WulaEnergy>();
if (energyNeed != null && energyNeed.CurLevel < 1.0f)
{
energyNeed.CurLevel = 1.0f;
}
}
public override void ExposeData()
{
base.ExposeData();
Scribe_Values.Look(ref originalEnergyLevel, "originalEnergyLevel", 0f);
Scribe_Values.Look(ref hasStoredOriginalLevel, "hasStoredOriginalLevel", false);
}
}
}

View File

@@ -1,32 +0,0 @@
using System.Collections.Generic;
using Verse;
using Verse.AI;
using RimWorld; // Added for AbilityDef
namespace WulaFallenEmpire
{
public class JobDriver_CastEmergencyEnergyRestore : JobDriver
{
public override bool TryMakePreToilReservations(bool errorOnFailed)
{
return true;
}
protected override IEnumerable<Toil> MakeNewToils()
{
this.FailOnDespawnedOrNull(TargetIndex.A);
yield return new Toil
{
initAction = delegate
{
var ability = pawn.abilities.GetAbility(DefDatabase<AbilityDef>.GetNamed("WULA_EmergencyEnergyRestore"));
if (ability != null)
{
ability.Activate(pawn.Position, pawn);
}
},
defaultCompleteMode = ToilCompleteMode.Instant
};
}
}
}

View File

@@ -1,5 +1,4 @@
using System.Collections.Generic; using System.Collections.Generic;
using UnityEngine;
using Verse; using Verse;
using Verse.AI; using Verse.AI;
using RimWorld; using RimWorld;
@@ -11,17 +10,16 @@ namespace WulaFallenEmpire
private const TargetIndex FoodSourceInd = TargetIndex.A; private const TargetIndex FoodSourceInd = TargetIndex.A;
private const TargetIndex PatientInd = TargetIndex.B; private const TargetIndex PatientInd = TargetIndex.B;
private Thing FoodSource => job.GetTarget(FoodSourceInd).Thing; protected Thing Food => job.GetTarget(FoodSourceInd).Thing;
private Pawn Patient => (Pawn)job.GetTarget(PatientInd).Thing; protected Pawn Patient => (Pawn)job.GetTarget(PatientInd).Thing;
public override bool TryMakePreToilReservations(bool errorOnFailed) public override bool TryMakePreToilReservations(bool errorOnFailed)
{ {
// 预留食物来源和病患 if (!pawn.Reserve(Patient, job, 1, -1, null, errorOnFailed))
if (!pawn.Reserve(FoodSource, job, 1, -1, null, errorOnFailed))
{ {
return false; return false;
} }
if (!pawn.Reserve(Patient, job, 1, -1, null, errorOnFailed)) if (!pawn.Reserve(Food, job, 1, -1, null, errorOnFailed))
{ {
return false; return false;
} }
@@ -30,110 +28,22 @@ namespace WulaFallenEmpire
protected override IEnumerable<Toil> MakeNewToils() protected override IEnumerable<Toil> MakeNewToils()
{ {
// 失败条件:如果病患被摧毁、为空或不在床上 this.FailOnDespawnedNullOrForbidden(PatientInd);
this.FailOn(() => Patient.DestroyedOrNull()); this.FailOn(() => !FeedPatientUtility.ShouldBeFed(Patient));
this.FailOn(() => !Patient.InBed());
// Toil 0: 检查医生库存中是否有能量核心 if (pawn.inventory != null && pawn.inventory.Contains(Food))
Toil checkInventoryToil = ToilMaker.MakeToil("CheckInventory");
checkInventoryToil.initAction = delegate
{ {
Thing inventoryFood = null; yield return Toils_Misc.TakeItemFromInventoryToCarrier(pawn, FoodSourceInd);
foreach (Thing t in pawn.inventory.innerContainer) }
{ else
ThingDefExtension_EnergySource energySourceExt = t.def.GetModExtension<ThingDefExtension_EnergySource>();
if (energySourceExt != null && t.IngestibleNow)
{
inventoryFood = t;
break;
}
}
if (inventoryFood != null)
{
// 如果库存中有食物则将Job的目标设置为库存食物并跳过拾取步骤直接前往病患
job.SetTarget(FoodSourceInd, inventoryFood);
pawn.jobs.curDriver.JumpToToil(Toils_Goto.GotoThing(PatientInd, PathEndMode.Touch)); // 跳转到前往病患的Toil
}
// 如果库存中没有则继续执行下一个Toil前往地图上的食物来源
};
yield return checkInventoryToil;
// Toil 1: 前往食物来源 (如果库存中没有则执行此Toil)
yield return Toils_Goto.GotoThing(FoodSourceInd, PathEndMode.ClosestTouch)
.FailOnDespawnedNullOrForbidden(FoodSourceInd)
.FailOn(() => !pawn.CanReserve(FoodSource, 1, -1, null, false)); // 在这里预留食物来源
// Toil 2: 拾取食物来源 (如果库存中没有则执行此Toil)
yield return Toils_Haul.StartCarryThing(FoodSourceInd); // 使用 StartCarryThing 拾取物品
// Toil 3: 前往病患
yield return Toils_Goto.GotoThing(PatientInd, PathEndMode.Touch)
.FailOnDespawnedOrNull(PatientInd);
// Toil 4: 喂食病患
Toil feedToil = ToilMaker.MakeToil("FeedWulaPatient");
feedToil.initAction = delegate
{ {
Pawn actor = feedToil.actor; yield return Toils_Goto.GotoThing(FoodSourceInd, PathEndMode.ClosestTouch).FailOnForbidden(FoodSourceInd);
Thing food = actor.carryTracker.CarriedThing; // 医生携带的食物 (从地图拾取) yield return Toils_Ingest.PickupIngestible(FoodSourceInd, pawn);
}
// 如果医生没有携带食物,检查是否在库存中 (从库存获取) yield return Toils_Goto.GotoThing(PatientInd, PathEndMode.Touch);
if (food == null) yield return Toils_Ingest.ChewIngestible(Patient, 1.5f, FoodSourceInd, TargetIndex.None).FailOnCannotTouch(PatientInd, PathEndMode.Touch);
{ yield return Toils_Ingest.FinalizeIngest(Patient, FoodSourceInd);
food = job.GetTarget(FoodSourceInd).Thing; // 此时FoodSourceInd应该指向库存中的物品
if (food == null || !actor.inventory.innerContainer.Contains(food))
{
actor.jobs.EndCurrentJob(JobCondition.Incompletable);
return;
}
}
// 获取乌拉能量需求
Need_WulaEnergy energyNeed = Patient.needs.TryGetNeed<Need_WulaEnergy>();
if (energyNeed == null)
{
actor.jobs.EndCurrentJob(JobCondition.Errored);
return;
}
// 检查食物来源是否有自定义能量扩展
ThingDefExtension_EnergySource ext = food.def.GetModExtension<ThingDefExtension_EnergySource>();
if (ext == null)
{
actor.jobs.EndCurrentJob(JobCondition.Errored);
return;
}
// 补充乌拉的能量
energyNeed.CurLevel += ext.energyAmount;
// 消耗物品
if (actor.carryTracker.CarriedThing == food) // 如果是携带的物品
{
food.Destroy(DestroyMode.Vanish); // 销毁医生携带的物品
actor.carryTracker.innerContainer.ClearAndDestroyContents(); // 移除医生携带的物品
}
else if (actor.inventory.innerContainer.Contains(food)) // 如果是库存中的物品
{
food.stackCount--; // 减少库存物品数量
if (food.stackCount <= 0)
{
food.Destroy(DestroyMode.Vanish); // 如果数量为0销毁物品
}
}
else
{
// 理论上不应该发生
actor.jobs.EndCurrentJob(JobCondition.Errored);
return;
}
// 记录能量摄入 (可选)
// Patient.records.AddTo(RecordDefOf.NutritionEaten, ext.energyAmount);
};
feedToil.defaultCompleteMode = ToilCompleteMode.Instant;
yield return feedToil;
} }
} }
} }

View File

@@ -1,29 +1,28 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; // Added for FirstOrDefault
using UnityEngine;
using Verse; using Verse;
using Verse.AI; using Verse.AI;
using RimWorld; // For ThingDefOf, StatDefOf, etc. using RimWorld;
namespace WulaFallenEmpire namespace WulaFallenEmpire
{ {
public class JobDriver_IngestWulaEnergy : JobDriver public class JobDriver_IngestWulaEnergy : JobDriver
{ {
private const TargetIndex IngestibleSourceInd = TargetIndex.A; private bool eatingFromInventory;
private bool eatingFromInventory; // 新增字段
private Toil chewing; // 新增咀嚼Toil字段 private const TargetIndex IngestibleSourceInd = TargetIndex.A;
private Thing IngestibleSource => job.GetTarget(IngestibleSourceInd).Thing; private Thing IngestibleSource => job.GetTarget(IngestibleSourceInd).Thing;
// 新增咀嚼时间乘数属性
private float ChewDurationMultiplier private float ChewDurationMultiplier
{ {
get get
{ {
Thing ingestibleSource = IngestibleSource; Thing ingestibleSource = IngestibleSource;
// 假设乌拉能量核心也有EatingSpeed属性影响咀嚼速度或者固定为1f if (ingestibleSource.def.ingestible != null)
return 1f / pawn.GetStatValue(StatDefOf.EatingSpeed); {
return 1f / pawn.GetStatValue(StatDefOf.EatingSpeed);
}
return 1f;
} }
} }
@@ -33,12 +32,17 @@ namespace WulaFallenEmpire
Scribe_Values.Look(ref eatingFromInventory, "eatingFromInventory", defaultValue: false); Scribe_Values.Look(ref eatingFromInventory, "eatingFromInventory", defaultValue: false);
} }
public override void Notify_Starting()
{
base.Notify_Starting();
eatingFromInventory = pawn.inventory != null && pawn.inventory.Contains(IngestibleSource);
}
public override bool TryMakePreToilReservations(bool errorOnFailed) public override bool TryMakePreToilReservations(bool errorOnFailed)
{ {
if (pawn.Faction != null) if (pawn.Faction != null)
{ {
Thing ingestibleSource = IngestibleSource; Thing ingestibleSource = IngestibleSource;
// 使用FoodUtility.GetMaxAmountToPickup
int maxAmountToPickup = FoodUtility.GetMaxAmountToPickup(ingestibleSource, pawn, job.count); int maxAmountToPickup = FoodUtility.GetMaxAmountToPickup(ingestibleSource, pawn, job.count);
if (!pawn.Reserve(ingestibleSource, job, 10, maxAmountToPickup, null, errorOnFailed)) if (!pawn.Reserve(ingestibleSource, job, 10, maxAmountToPickup, null, errorOnFailed))
{ {
@@ -51,60 +55,21 @@ namespace WulaFallenEmpire
protected override IEnumerable<Toil> MakeNewToils() protected override IEnumerable<Toil> MakeNewToils()
{ {
// 失败条件:如果能量核心被摧毁、为空或被禁止 this.FailOn(() => !IngestibleSource.Destroyed && !IngestibleSource.IngestibleNow);
this.FailOn(() => IngestibleSource.DestroyedOrNull() || !IngestibleSource.IngestibleNow);
// 初始化 eatingFromInventory Toil chew = Toils_Ingest.ChewIngestible(pawn, ChewDurationMultiplier, IngestibleSourceInd, TargetIndex.None)
eatingFromInventory = pawn.inventory != null && pawn.inventory.Contains(IngestibleSource);
// 定义咀嚼Toil
chewing = Toils_Ingest.ChewIngestible(pawn, ChewDurationMultiplier, IngestibleSourceInd, TargetIndex.None)
.FailOn((Toil x) => !IngestibleSource.Spawned && (pawn.carryTracker == null || pawn.carryTracker.CarriedThing != IngestibleSource)) .FailOn((Toil x) => !IngestibleSource.Spawned && (pawn.carryTracker == null || pawn.carryTracker.CarriedThing != IngestibleSource))
.FailOnCannotTouch(IngestibleSourceInd, PathEndMode.Touch); .FailOnCannotTouch(IngestibleSourceInd, PathEndMode.Touch);
// 根据是否从背包摄入选择不同的Toil序列 foreach (Toil item in PrepareToIngestToils(chew))
foreach (Toil item in PrepareToIngestToils(chewing))
{ {
yield return item; yield return item;
} }
yield return chewing; yield return chew;
yield return Toils_Ingest.FinalizeIngest(pawn, IngestibleSourceInd);
// 最终处理能量摄取
Toil finalizeToil = ToilMaker.MakeToil("FinalizeWulaEnergyIngest");
finalizeToil.initAction = delegate
{
Pawn actor = finalizeToil.actor;
Thing thing = actor.carryTracker.CarriedThing; // 从carryTracker获取因为Toils_Ingest.ChewIngestible会处理携带
if (thing == null)
{
actor.jobs.EndCurrentJob(JobCondition.Incompletable);
return;
}
Need_WulaEnergy energyNeed = actor.needs.TryGetNeed<Need_WulaEnergy>();
if (energyNeed == null)
{
actor.jobs.EndCurrentJob(JobCondition.Errored);
return;
}
ThingDefExtension_EnergySource ext = thing.def.GetModExtension<ThingDefExtension_EnergySource>();
if (ext == null)
{
actor.jobs.EndCurrentJob(JobCondition.Errored);
return;
}
energyNeed.CurLevel += ext.energyAmount;
thing.Destroy(DestroyMode.Vanish);
};
finalizeToil.defaultCompleteMode = ToilCompleteMode.Instant;
yield return finalizeToil;
} }
// 辅助方法根据情况返回不同的Toil序列
private IEnumerable<Toil> PrepareToIngestToils(Toil chewToil) private IEnumerable<Toil> PrepareToIngestToils(Toil chewToil)
{ {
if (eatingFromInventory) if (eatingFromInventory)
@@ -113,14 +78,9 @@ namespace WulaFallenEmpire
} }
else else
{ {
// 类似原版JobDriver_Ingest的ToolUser逻辑 yield return Toils_Goto.GotoThing(IngestibleSourceInd, PathEndMode.ClosestTouch).FailOnDespawnedNullOrForbidden(IngestibleSourceInd);
yield return Toils_Goto.GotoThing(IngestibleSourceInd, PathEndMode.ClosestTouch)
.FailOnDespawnedNullOrForbidden(IngestibleSourceInd);
yield return Toils_Ingest.PickupIngestible(IngestibleSourceInd, pawn); yield return Toils_Ingest.PickupIngestible(IngestibleSourceInd, pawn);
} }
// 不处理FindAdjacentEatSurface因为乌拉能量核心可能不需要“吃表面”
// 也不处理takeExtraIngestibles因为乌拉能量核心通常是单次消耗
yield break; // 确保迭代器结束
} }
} }
} }

View File

@@ -1,12 +0,0 @@
using Verse;
namespace WulaFallenEmpire
{
public class JobGiverDefExtension_WulaGetEnergy : DefModExtension
{
public float minEnergyLevelPercentage = 0.3f;
public float emergencyThreshold = 0.1f;
public float normalPriority = 5f;
public float emergencyPriority = 9.5f;
}
}

View File

@@ -1,118 +1,75 @@
using RimWorld; using RimWorld;
using Verse; using Verse;
using Verse.AI; using Verse.AI;
using System.Linq; // For FirstOrDefault
namespace WulaFallenEmpire 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 emergencyThreshold = 0.1f; public float maxEnergyLevelPercentage = 0.9f;
public float normalPriority = 5f;
public float emergencyPriority = 9.5f; public float emergencyPriority = 9.5f;
public float searchRadius = 20f; // 添加 searchRadius
public int ingestCount = 1; // 添加 ingestCount
public override ThinkNode DeepCopy(bool resolve = true)
{
JobGiver_WulaGetEnergy obj = (JobGiver_WulaGetEnergy)base.DeepCopy(resolve);
obj.minEnergyLevelPercentage = minEnergyLevelPercentage;
obj.emergencyThreshold = emergencyThreshold;
obj.normalPriority = normalPriority;
obj.emergencyPriority = emergencyPriority;
obj.searchRadius = searchRadius;
obj.ingestCount = ingestCount;
return obj;
}
public override float GetPriority(Pawn pawn) public override float GetPriority(Pawn pawn)
{ {
Need_WulaEnergy energyNeed = pawn.needs.TryGetNeed<Need_WulaEnergy>(); Need_WulaEnergy energyNeed = pawn.needs.TryGetNeed<Need_WulaEnergy>();
if (energyNeed == null) if (energyNeed == null || pawn.health.hediffSet.HasHediff(DefDatabase<HediffDef>.GetNamed("WULA_ChargingHediff")))
{ {
return 0f; return 0f;
} }
// 如果能量充足,则不需要寻找能量核心 if (energyNeed.CurLevelPercentage < minEnergyLevelPercentage)
if (energyNeed.CurLevelPercentage > minEnergyLevelPercentage)
{
return 0f;
}
// 如果能量非常低,给予高优先级
if (energyNeed.CurLevelPercentage < emergencyThreshold)
{ {
return emergencyPriority; return emergencyPriority;
} }
return 0f;
// 否则,给予中等优先级
return normalPriority;
} }
protected override Job TryGiveJob(Pawn pawn) protected override Job TryGiveJob(Pawn pawn)
{ {
if (pawn.Downed) if (pawn.health.hediffSet.HasHediff(DefDatabase<HediffDef>.GetNamed("WULA_ChargingHediff")))
{ {
return null; return null;
} }
Need_WulaEnergy energyNeed = pawn.needs.TryGetNeed<Need_WulaEnergy>(); Need_WulaEnergy energyNeed = pawn.needs.TryGetNeed<Need_WulaEnergy>();
if (energyNeed == null || energyNeed.CurLevelPercentage > minEnergyLevelPercentage) if (energyNeed == null || energyNeed.CurLevelPercentage >= maxEnergyLevelPercentage)
{ {
return null; return null;
} }
// 优先检查小人背包中的能量核心 if (!TryFindBestEnergySourceFor(pawn, out Thing energySource))
foreach (Thing t in pawn.inventory.innerContainer)
{ {
ThingDefExtension_EnergySource energySourceExt = t.def.GetModExtension<ThingDefExtension_EnergySource>(); return null;
if (energySourceExt != null && t.IngestibleNow)
{
Job job = JobMaker.MakeJob(DefDatabase<JobDef>.GetNamed("WULA_IngestWulaEnergy"), t);
job.count = ingestCount;
return job;
}
} }
// 如果背包中没有,则寻找最佳能量核心 Job job = JobMaker.MakeJob(DefDatabase<JobDef>.GetNamed("WULA_IngestWulaEnergy"), energySource);
Thing bestEnergySource = GenClosest.ClosestThingReachable( job.count = 1;
return job;
}
private bool TryFindBestEnergySourceFor(Pawn pawn, out Thing energySource)
{
// 优先从背包中寻找
Thing thing = pawn.inventory.innerContainer.FirstOrFallback(t => t.def.GetModExtension<ThingDefExtension_EnergySource>() != null && t.IngestibleNow);
if (thing != null)
{
energySource = thing;
return true;
}
// 否则,在地图上寻找
energySource = GenClosest.ClosestThingReachable(
pawn.Position, pawn.Position,
pawn.Map, pawn.Map,
ThingRequest.ForGroup(ThingRequestGroup.HaulableEver), // 扫描所有可搬运的物品 ThingRequest.ForGroup(ThingRequestGroup.HaulableEver),
PathEndMode.ClosestTouch, PathEndMode.ClosestTouch,
TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), TraverseParms.For(pawn),
searchRadius, // 使用类中的 searchRadius 9999f,
(Thing t) => t => t.def.GetModExtension<ThingDefExtension_EnergySource>() != null && t.IngestibleNow && !t.IsForbidden(pawn) && pawn.CanReserve(t)
{
// 检查物品是否是能量核心
ThingDefExtension_EnergySource energySourceExt = t.def.GetModExtension<ThingDefExtension_EnergySource>();
if (energySourceExt == null)
{
return false;
}
// 检查物品是否可摄取
if (!t.IngestibleNow)
{
return false;
}
// 检查物品是否被禁止或无法预留
if (t.IsForbidden(pawn) || !pawn.CanReserve(t, 1, -1, null, false))
{
return false;
}
return true;
}
); );
if (bestEnergySource != null) return energySource != null;
{
// 创建摄取能量核心的Job
Job job = JobMaker.MakeJob(DefDatabase<JobDef>.GetNamed("WULA_IngestWulaEnergy"), bestEnergySource);
job.count = ingestCount; // 使用类中的 ingestCount
return job;
}
return null;
} }
} }
} }

View File

@@ -108,5 +108,10 @@ namespace WulaFallenEmpire
threshPercents.Clear(); threshPercents.Clear();
base.DrawOnGUI(rect, maxThresholdMarkers, customMargin, drawArrows, doTooltip, rectForTooltip, drawLabel); base.DrawOnGUI(rect, maxThresholdMarkers, customMargin, drawArrows, doTooltip, rectForTooltip, drawLabel);
} }
public override void ExposeData()
{
base.ExposeData();
}
} }
} }

View File

@@ -4,7 +4,6 @@ namespace WulaFallenEmpire
{ {
public class WorkGiverDefExtension_FeedWula : DefModExtension public class WorkGiverDefExtension_FeedWula : DefModExtension
{ {
// The ThingDef of the item to be used as energy source. public float feedThreshold = 0.25f;
public ThingDef energySourceDef;
} }
} }

View File

@@ -1,28 +1,14 @@
using RimWorld; using RimWorld;
using System.Collections.Generic;
using System.Linq;
using Verse; using Verse;
using Verse.AI; using Verse.AI;
using System.Collections.Generic;
using System.Linq;
namespace WulaFallenEmpire namespace WulaFallenEmpire
{ {
public class WorkGiver_FeedWulaPatient : WorkGiver_Scanner public class WorkGiver_FeedWulaPatient : WorkGiver_Scanner
{ {
private WorkGiverDefExtension_FeedWula ext; public override ThingRequest PotentialWorkThingRequest => ThingRequest.ForGroup(ThingRequestGroup.Pawn);
private WorkGiverDefExtension_FeedWula Ext
{
get
{
if (ext == null)
{
ext = def.GetModExtension<WorkGiverDefExtension_FeedWula>();
}
return ext;
}
}
public override ThingRequest PotentialWorkThingRequest => ThingRequest.ForDef(ThingDef.Named("WulaSpecies"));
public override PathEndMode PathEndMode => PathEndMode.ClosestTouch; public override PathEndMode PathEndMode => PathEndMode.ClosestTouch;
@@ -30,52 +16,47 @@ namespace WulaFallenEmpire
public override IEnumerable<Thing> PotentialWorkThingsGlobal(Pawn pawn) public override IEnumerable<Thing> PotentialWorkThingsGlobal(Pawn pawn)
{ {
// Mimic vanilla: Scan all pawns in bed. return pawn.Map.mapPawns.AllPawns.Where(p => p.needs.TryGetNeed<Need_WulaEnergy>() != null && FeedPatientUtility.ShouldBeFed(p));
return pawn.Map.mapPawns.AllPawns.Where(p => p.InBed());
} }
public override bool HasJobOnThing(Pawn pawn, Thing t, bool forced = false) public override bool HasJobOnThing(Pawn pawn, Thing t, bool forced = false)
{ {
Pawn patient = t as Pawn; if (!(t is Pawn patient) || patient == pawn)
{
// Basic validation, similar to vanilla return false;
if (patient == null || patient == pawn || !patient.InBed() || patient.def.defName != "WulaSpecies") }
// 如果病患正在充能,则不需要喂食
if (patient.health.hediffSet.HasHediff(DefDatabase<HediffDef>.GetNamed("WULA_ChargingHediff")))
{ {
return false; return false;
} }
// Our custom check: Is the Wula in shutdown?
Need_WulaEnergy energyNeed = patient.needs.TryGetNeed<Need_WulaEnergy>(); Need_WulaEnergy energyNeed = patient.needs.TryGetNeed<Need_WulaEnergy>();
if (energyNeed == null || !energyNeed.IsShutdown) var extension = def.GetModExtension<WorkGiverDefExtension_FeedWula>();
if (energyNeed == null || energyNeed.CurLevelPercentage >= extension.feedThreshold)
{ {
return false; return false;
} }
// CRITICAL vanilla check: If the patient is a prisoner, this is a warden's job, not a doctor's. if (!FeedPatientUtility.ShouldBeFed(patient))
// This prevents conflicts between two different work types trying to do the same thing. {
return false;
}
if (WardenFeedUtility.ShouldBeFed(patient)) if (WardenFeedUtility.ShouldBeFed(patient))
{ {
return false; return false;
} }
// CRITICAL vanilla check: Can the doctor reserve the patient?
// This prevents multiple doctors from trying to feed the same patient at the same time.
if (!pawn.CanReserve(patient, 1, -1, null, forced)) if (!pawn.CanReserve(patient, 1, -1, null, forced))
{ {
return false; return false;
} }
// Check for our energy source if (!TryFindBestEnergySourceFor(pawn, patient, out _, out _))
if (Ext == null || Ext.energySourceDef == null)
{ {
Log.ErrorOnce("WorkGiver_FeedWulaPatient is missing the DefModExtension with a valid energySourceDef.", def.GetHashCode()); JobFailReason.Is("NoWulaEnergyToFeed".Translate(patient.LabelShort, patient));
return false;
}
if (!FindBestEnergySourceFor(pawn, patient, out _, out _))
{
// Mimic vanilla: Provide a reason for failure.
JobFailReason.Is("NoFood".Translate()); // Using vanilla translation key for simplicity
return false; return false;
} }
@@ -85,39 +66,30 @@ namespace WulaFallenEmpire
public override Job JobOnThing(Pawn pawn, Thing t, bool forced = false) public override Job JobOnThing(Pawn pawn, Thing t, bool forced = false)
{ {
Pawn patient = (Pawn)t; Pawn patient = (Pawn)t;
if (FindBestEnergySourceFor(pawn, patient, out Thing energySource, out _)) if (TryFindBestEnergySourceFor(pawn, patient, out Thing energySource, out _))
{ {
Job job = JobMaker.MakeJob(DefDatabase<JobDef>.GetNamed("WULA_FeedWulaPatient"), energySource, patient); Job job = JobMaker.MakeJob(DefDatabase<JobDef>.GetNamed("WULA_FeedWulaPatient"), energySource, patient);
job.count = 1; // Energy cores are single-use. job.count = 1;
return job; return job;
} }
return null; return null;
} }
private bool FindBestEnergySourceFor(Pawn getter, Pawn eater, out Thing foodSource, out ThingDef foodDef) private bool TryFindBestEnergySourceFor(Pawn getter, Pawn eater, out Thing energySource, out ThingDef energyDef)
{ {
foodSource = null; energySource = null;
foodDef = null; energyDef = null;
if (Ext == null || Ext.energySourceDef == null) var allowedThings = getter.Map.listerThings.ThingsInGroup(ThingRequestGroup.HaulableEver)
.Where(x => x.def.GetModExtension<ThingDefExtension_EnergySource>() != null);
Thing thing = GenClosest.ClosestThing_Global(eater.Position, allowedThings, 99999f,
t => t.IngestibleNow && !t.IsForbidden(getter) && getter.CanReserve(t));
if (thing != null)
{ {
return false; energySource = thing;
} energyDef = thing.def;
// CRITICAL vanilla check is embedded here: CanReserve(x) on the food source itself.
foodSource = GenClosest.ClosestThingReachable(
getter.Position,
getter.Map,
ThingRequest.ForDef(Ext.energySourceDef),
PathEndMode.OnCell,
TraverseParms.For(getter),
9999f,
(Thing x) => !x.IsForbidden(getter) && getter.CanReserve(x)
);
if (foodSource != null)
{
foodDef = foodSource.def;
return true; return true;
} }

View File

@@ -1,115 +1,50 @@
using RimWorld; using RimWorld;
using Verse; using Verse;
using Verse.AI; using Verse.AI;
using System.Linq;
namespace WulaFallenEmpire namespace WulaFallenEmpire
{ {
public class WorkGiver_Warden_DeliverEnergy : WorkGiver_Scanner public class WorkGiver_Warden_DeliverEnergy : WorkGiver_Warden
{ {
private WorkGiverDefExtension_FeedWula ext;
private WorkGiverDefExtension_FeedWula Ext
{
get
{
if (ext == null)
{
ext = def.GetModExtension<WorkGiverDefExtension_FeedWula>();
}
return ext;
}
}
public override ThingRequest PotentialWorkThingRequest => ThingRequest.ForDef(ThingDef.Named("WulaSpecies"));
public override PathEndMode PathEndMode => PathEndMode.ClosestTouch;
public override Danger MaxPathDanger(Pawn pawn) => Danger.Deadly;
public override bool HasJobOnThing(Pawn pawn, Thing t, bool forced = false)
{
Pawn prisoner = t as Pawn;
if (prisoner == null || prisoner == pawn || !prisoner.IsPrisonerOfColony || !prisoner.guest.CanBeBroughtFood)
{
return false;
}
Need_WulaEnergy energyNeed = prisoner.needs.TryGetNeed<Need_WulaEnergy>();
if (energyNeed == null)
{
return false;
}
NeedDefExtension_Energy ext = energyNeed.def.GetModExtension<NeedDefExtension_Energy>();
float threshold = (ext != null) ? ext.deliverEnergyThreshold : 0.5f;
if (energyNeed.CurLevelPercentage > threshold)
{
return false;
}
if (WardenFeedUtility.ShouldBeFed(prisoner))
{
return false;
}
if (!pawn.CanReserve(prisoner, 1, -1, null, forced))
{
return false;
}
if (Ext == null || Ext.energySourceDef == null)
{
Log.ErrorOnce("WorkGiver_Warden_DeliverEnergy is missing the DefModExtension with a valid energySourceDef.", def.GetHashCode());
return false;
}
if (!FindBestEnergySourceFor(pawn, prisoner, out _, out _))
{
JobFailReason.Is("NoFood".Translate());
return false;
}
return true;
}
public override Job JobOnThing(Pawn pawn, Thing t, bool forced = false) public override Job JobOnThing(Pawn pawn, Thing t, bool forced = false)
{ {
Pawn prisoner = (Pawn)t; if (!(t is Pawn prisoner) || !ShouldTakeCareOfPrisoner(pawn, prisoner))
if (FindBestEnergySourceFor(pawn, prisoner, out Thing energySource, out _))
{ {
Job job = JobMaker.MakeJob(JobDefOf.DeliverFood, energySource, prisoner); return null;
job.count = 1;
job.targetC = RCellFinder.SpotToChewStandingNear(prisoner, energySource);
return job;
} }
return null;
if (!WardenFeedUtility.ShouldBeFed(prisoner) || prisoner.health.hediffSet.HasHediff(DefDatabase<HediffDef>.GetNamed("WULA_ChargingHediff")))
{
return null;
}
if (!TryFindBestEnergySourceFor(pawn, prisoner, out Thing energySource, out _))
{
return null;
}
Job job = JobMaker.MakeJob(JobDefOf.DeliverFood, energySource, prisoner);
job.count = 1;
job.targetC = RCellFinder.SpotToChewStandingNear(prisoner, energySource);
return job;
} }
private bool FindBestEnergySourceFor(Pawn getter, Pawn eater, out Thing foodSource, out ThingDef foodDef) private bool TryFindBestEnergySourceFor(Pawn getter, Pawn eater, out Thing energySource, out ThingDef energyDef)
{ {
foodSource = null; energySource = null;
foodDef = null; energyDef = null;
if (Ext == null || Ext.energySourceDef == null) var allowedThings = getter.Map.listerThings.ThingsInGroup(ThingRequestGroup.HaulableEver)
.Where(x => x.def.GetModExtension<ThingDefExtension_EnergySource>() != null);
Thing thing = GenClosest.ClosestThing_Global(eater.Position, allowedThings, 99999f,
t => t.IngestibleNow && !t.IsForbidden(getter) && getter.CanReserve(t));
if (thing != null)
{ {
return false; energySource = thing;
} energyDef = thing.def;
foodSource = GenClosest.ClosestThingReachable(
getter.Position,
getter.Map,
ThingRequest.ForDef(Ext.energySourceDef),
PathEndMode.OnCell,
TraverseParms.For(getter),
9999f,
(Thing x) => !x.IsForbidden(getter) && getter.CanReserve(x) && x.GetRoom() != eater.GetRoom()
);
if (foodSource != null)
{
foodDef = foodSource.def;
return true; return true;
} }

View File

@@ -1,111 +1,61 @@
using RimWorld; using RimWorld;
using Verse; using Verse;
using Verse.AI; using Verse.AI;
using System.Linq;
namespace WulaFallenEmpire namespace WulaFallenEmpire
{ {
public class WorkGiver_Warden_FeedWula : WorkGiver_Scanner public class WorkGiver_Warden_FeedWula : WorkGiver_Warden
{ {
private WorkGiverDefExtension_FeedWula ext;
private WorkGiverDefExtension_FeedWula Ext
{
get
{
if (ext == null)
{
ext = def.GetModExtension<WorkGiverDefExtension_FeedWula>();
}
return ext;
}
}
public override ThingRequest PotentialWorkThingRequest => ThingRequest.ForDef(ThingDef.Named("WulaSpecies"));
public override PathEndMode PathEndMode => PathEndMode.ClosestTouch;
public override Danger MaxPathDanger(Pawn pawn) => Danger.Deadly;
public override bool HasJobOnThing(Pawn pawn, Thing t, bool forced = false)
{
Pawn prisoner = t as Pawn;
// Basic validation, similar to vanilla's WorkGiver_Warden_Feed
if (prisoner == null || prisoner == pawn || !prisoner.IsPrisonerOfColony || !prisoner.guest.CanBeBroughtFood)
{
return false;
}
// Our custom check: Is the Wula in shutdown?
Need_WulaEnergy energyNeed = prisoner.needs.TryGetNeed<Need_WulaEnergy>();
if (energyNeed == null || !energyNeed.IsShutdown)
{
return false;
}
// Vanilla check: Is the prisoner unable to feed themselves?
if (!WardenFeedUtility.ShouldBeFed(prisoner))
{
return false;
}
// CRITICAL vanilla check: Can the warden reserve the prisoner?
if (!pawn.CanReserve(prisoner, 1, -1, null, forced))
{
return false;
}
// Check for our energy source
if (Ext == null || Ext.energySourceDef == null)
{
Log.ErrorOnce("WorkGiver_Warden_FeedWula is missing the DefModExtension with a valid energySourceDef.", def.GetHashCode());
return false;
}
if (!FindBestEnergySourceFor(pawn, prisoner, out _, out _))
{
JobFailReason.Is("NoFood".Translate());
return false;
}
return true;
}
public override Job JobOnThing(Pawn pawn, Thing t, bool forced = false) public override Job JobOnThing(Pawn pawn, Thing t, bool forced = false)
{ {
Pawn prisoner = (Pawn)t; if (!(t is Pawn prisoner) || !ShouldFeed(pawn, prisoner))
if (FindBestEnergySourceFor(pawn, prisoner, out Thing energySource, out _))
{ {
Job job = JobMaker.MakeJob(DefDatabase<JobDef>.GetNamed("WULA_FeedWulaPatient"), energySource, prisoner); return null;
job.count = 1;
return job;
} }
return null;
Need_WulaEnergy energyNeed = prisoner.needs.TryGetNeed<Need_WulaEnergy>();
var extension = def.GetModExtension<WorkGiverDefExtension_FeedWula>();
if (energyNeed == null || energyNeed.CurLevelPercentage >= extension.feedThreshold)
{
return null;
}
if (prisoner.health.hediffSet.HasHediff(DefDatabase<HediffDef>.GetNamed("WULA_ChargingHediff")))
{
return null;
}
if (!TryFindBestEnergySourceFor(pawn, prisoner, out Thing energySource, out _))
{
return null;
}
Job job = JobMaker.MakeJob(DefDatabase<JobDef>.GetNamed("WULA_FeedWulaPatient"), energySource, prisoner);
job.count = 1;
return job;
} }
private bool FindBestEnergySourceFor(Pawn getter, Pawn eater, out Thing foodSource, out ThingDef foodDef) private bool ShouldFeed(Pawn warden, Pawn prisoner)
{ {
foodSource = null; return prisoner.IsPrisonerOfColony && prisoner.guest.CanBeBroughtFood && prisoner.needs.TryGetNeed<Need_WulaEnergy>() != null;
foodDef = null; }
if (Ext == null || Ext.energySourceDef == null) private bool TryFindBestEnergySourceFor(Pawn getter, Pawn eater, out Thing energySource, out ThingDef energyDef)
{
energySource = null;
energyDef = null;
var allowedThings = getter.Map.listerThings.ThingsInGroup(ThingRequestGroup.HaulableEver)
.Where(x => x.def.GetModExtension<ThingDefExtension_EnergySource>() != null);
Thing thing = GenClosest.ClosestThing_Global(eater.Position, allowedThings, 99999f,
t => t.IngestibleNow && !t.IsForbidden(getter) && getter.CanReserve(t));
if (thing != null)
{ {
return false; energySource = thing;
} energyDef = thing.def;
foodSource = GenClosest.ClosestThingReachable(
getter.Position,
getter.Map,
ThingRequest.ForDef(Ext.energySourceDef),
PathEndMode.OnCell,
TraverseParms.For(getter),
9999f,
(Thing x) => !x.IsForbidden(getter) && getter.CanReserve(x)
);
if (foodSource != null)
{
foodDef = foodSource.def;
return true; return true;
} }

View File

@@ -79,13 +79,9 @@
<Compile Include="CompUseEffect_WulaSkillTrainer.cs" /> <Compile Include="CompUseEffect_WulaSkillTrainer.cs" />
<Compile Include="Verb_ShootBeamExplosive.cs" /> <Compile Include="Verb_ShootBeamExplosive.cs" />
<Compile Include="VerbPropertiesExplosiveBeam.cs" /> <Compile Include="VerbPropertiesExplosiveBeam.cs" />
<Compile Include="Hediff_EmergencyEnergyRestore.cs" /> <Compile Include="HediffComp_WulaCharging.cs" />
<Compile Include="CompProperties_AbilityEmergencyEnergyRestore.cs" />
<Compile Include="CompAbilityEffect_EmergencyEnergyRestore.cs" />
<Compile Include="EmergencyAbilityPatches.cs" />
<Compile Include="JobGiver_WulaGetEnergy.cs" /> <Compile Include="JobGiver_WulaGetEnergy.cs" />
<Compile Include="JobGiverDefExtension_WulaGetEnergy.cs" /> <Compile Include="JobGiverDefExtension_WulaGetEnergy.cs" />
<Compile Include="JobDriver_CastEmergencyEnergyRestore.cs" />
<Compile Include="JobGiver_WulaPackEnergy.cs" /> <Compile Include="JobGiver_WulaPackEnergy.cs" />
<Compile Include="JobGiverDefExtension_WulaPackEnergy.cs" /> <Compile Include="JobGiverDefExtension_WulaPackEnergy.cs" />
</ItemGroup> </ItemGroup>