改改改

This commit is contained in:
2025-10-17 17:41:51 +08:00
parent e06d1113a3
commit 0539703a6e
12 changed files with 571 additions and 155 deletions

Binary file not shown.

View File

@@ -45,7 +45,7 @@
<capacities>
<li>Cut</li>
</capacities>
<power>12</power>
<power>10</power>
<cooldownTime>1.3</cooldownTime>
<armorPenetration>0.50</armorPenetration>
</li>
@@ -54,7 +54,7 @@
<capacities>
<li>Poke</li>
</capacities>
<power>9</power>
<power>8</power>
<armorPenetration>0.20</armorPenetration>
<cooldownTime>1.5</cooldownTime>
<extraMeleeDamages>
@@ -120,13 +120,13 @@
<capacities>
<li>ARA_Whip</li>
</capacities>
<power>7</power>
<armorPenetration>1.25</armorPenetration>
<power>4</power>
<armorPenetration>0.85</armorPenetration>
<cooldownTime>1.75</cooldownTime>
<extraMeleeDamages>
<li>
<def>Stun</def>
<amount>8</amount>
<amount>6</amount>
</li>
</extraMeleeDamages>
<soundMeleeHit>ARA_MW_Cartilage_Whip_Hit</soundMeleeHit>
@@ -1287,7 +1287,7 @@
<projectile>
<speed>60</speed>
<damageDef>ARA_AcidBurn</damageDef>
<damageAmountBase>6</damageAmountBase>
<damageAmountBase>5</damageAmountBase>
<filth>Filth_SpentAcid</filth>
<filthCount>2</filthCount>
<explosionSpawnsSingleFilth>true</explosionSpawnsSingleFilth>
@@ -1423,7 +1423,7 @@
<projectile>
<speed>60</speed>
<damageDef>ARA_AcidBurn</damageDef>
<damageAmountBase>4</damageAmountBase>
<damageAmountBase>3</damageAmountBase>
<filth>Filth_SpentAcid</filth>
<filthCount>2</filthCount>
<explosionSpawnsSingleFilth>true</explosionSpawnsSingleFilth>

View File

@@ -64,15 +64,13 @@
<terrainAffordanceNeeded>ARA_Creep</terrainAffordanceNeeded>
<comps>
<!-- 标准的 CompRefuelable -->
<li Class="CompProperties_Refuelable">
<li Class="ArachnaeSwarm.CompProperties_ProductStorage">
<fuelLabel>精华素</fuelLabel>
<fuelGizmoLabel>精华素</fuelGizmoLabel>
<fuelCapacity>20</fuelCapacity>
<fuelConsumptionRate>0</fuelConsumptionRate>
<consumeFuelOnlyWhenUsed>true</consumeFuelOnlyWhenUsed>
<autoRefuelPercent>-1</autoRefuelPercent>
<initialAllowAutoRefuel>true</initialAllowAutoRefuel>
<fuelFilter>
<thingDefs>
@@ -80,6 +78,9 @@
</thingDefs>
</fuelFilter>
<allowRefuelIfNotEmpty>false</allowRefuelIfNotEmpty>
<drawFuelGaugeInMap>false</drawFuelGaugeInMap>
<drawOutOfFuelOverlay>false</drawOutOfFuelOverlay>
<targetFuelLevelConfigurable>false</targetFuelLevelConfigurable>
<showAllowAutoRefuelToggle>false</showAllowAutoRefuelToggle>
<canEjectFuel>true</canEjectFuel>
@@ -87,10 +88,11 @@
<!-- 燃料满了自动弹出 -->
<li Class="ArachnaeSwarm.CompProperties_AutoEjector">
<!-- 精确指定要监控的燃料组件 -->
<targetComp>CompRefuelable</targetComp>
<!-- 在燃料达到99%时弹出 -->
<checkInterval>60</checkInterval>
<ejectAtPercent>0.99</ejectAtPercent>
<allowEjectedFuel>true</allowEjectedFuel>
<monitorProductStorage>true</monitorProductStorage>
<monitorRefuelable>false</monitorRefuelable>
</li>
<li Class="ArachnaeSwarm.CompProperties_RefuelingVat">

View File

@@ -15,7 +15,7 @@
<TimeLeft>剩余时间</TimeLeft>
<ProjectedQuality>预计品质</ProjectedQuality>
<NotProducing>未在生产</NotProducing>
<ARA_NeedSpecificArachnaeToStartIncubation>未孵化,需要 {0} 交互</ARA_NeedSpecificArachnaeToStartIncubation>
<ARA_NeedSpecificArachnaeToStartIncubation>未孵化,需要 {0} 交互\n\n在生产完成时剩余的营养将重新转变为物品。</ARA_NeedSpecificArachnaeToStartIncubation>
<ARA_AnyArachnaeRace>任何阿拉克涅虫族</ARA_AnyArachnaeRace>
<ARA_ItemsAvailable>{0} 个物品可用</ARA_ItemsAvailable>
<QualityProgress>物品品质</QualityProgress>

View File

@@ -1,34 +1,14 @@
{
"Version": 1,
"WorkspaceRootPath": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\",
"WorkspaceRootPath": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\",
"Documents": [
{
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|e:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\pawn_comps\\ara_nodeswarmlifetime\\compnodeswarmlifetime.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:pawn_comps\\ara_nodeswarmlifetime\\compnodeswarmlifetime.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|d:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\building_comps\\ara_compinteractiveproducer\\compinteractiveproducer.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:building_comps\\ara_compinteractiveproducer\\compinteractiveproducer.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
},
{
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|e:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\hediffs\\hediffcomp_lifespandisplay.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:hediffs\\hediffcomp_lifespandisplay.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
},
{
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|e:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\hediffs\\hediffcomp_temperature.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:hediffs\\hediffcomp_temperature.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
},
{
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|e:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\hediffs\\hediffcomp_spawnpawnonremoved.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:hediffs\\hediffcomp_spawnpawnonremoved.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
},
{
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|e:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\hediffgiver\\hediffgiver_nonplayerfaction.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:hediffgiver\\hediffgiver_nonplayerfaction.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
},
{
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\storyteller\\incidentworker_customraid.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:storyteller\\incidentworker_customraid.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
},
{
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\storyteller\\raidwavedef.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:storyteller\\raidwavedef.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|d:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\building_comps\\ara_compinteractiveproducer\\compresearchproducer.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:building_comps\\ara_compinteractiveproducer\\compresearchproducer.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
}
],
"DocumentGroupContainers": [
@@ -38,8 +18,21 @@
"DocumentGroups": [
{
"DockedWidth": 200,
"SelectedChildIndex": 1,
"SelectedChildIndex": 2,
"Children": [
{
"$type": "Document",
"DocumentIndex": 1,
"Title": "CompResearchProducer.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\ARA_CompInteractiveProducer\\CompResearchProducer.cs",
"RelativeDocumentMoniker": "Building_Comps\\ARA_CompInteractiveProducer\\CompResearchProducer.cs",
"ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\ARA_CompInteractiveProducer\\CompResearchProducer.cs",
"RelativeToolTip": "Building_Comps\\ARA_CompInteractiveProducer\\CompResearchProducer.cs",
"ViewState": "AgIAADoBAAAAAAAAAAAkwFIBAAAmAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-10-17T09:09:18.518Z",
"EditorCaption": ""
},
{
"$type": "Bookmark",
"Name": "ST:0:0:{1c4feeaa-4718-4aa9-859d-94ce25d182ba}"
@@ -47,90 +40,15 @@
{
"$type": "Document",
"DocumentIndex": 0,
"Title": "CompNodeSwarmLifetime.cs",
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Pawn_Comps\\ARA_NodeSwarmLifetime\\CompNodeSwarmLifetime.cs",
"RelativeDocumentMoniker": "Pawn_Comps\\ARA_NodeSwarmLifetime\\CompNodeSwarmLifetime.cs",
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Pawn_Comps\\ARA_NodeSwarmLifetime\\CompNodeSwarmLifetime.cs",
"RelativeToolTip": "Pawn_Comps\\ARA_NodeSwarmLifetime\\CompNodeSwarmLifetime.cs",
"ViewState": "AgIAAPwAAAAAAAAAAAAYwBYBAABIAAAAAAAAAA==",
"Title": "CompInteractiveProducer.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\ARA_CompInteractiveProducer\\CompInteractiveProducer.cs",
"RelativeDocumentMoniker": "Building_Comps\\ARA_CompInteractiveProducer\\CompInteractiveProducer.cs",
"ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\ARA_CompInteractiveProducer\\CompInteractiveProducer.cs",
"RelativeToolTip": "Building_Comps\\ARA_CompInteractiveProducer\\CompInteractiveProducer.cs",
"ViewState": "AgIAAJMBAAAAAAAAAAAUwNcBAAAyAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-10-16T15:17:15.994Z",
"WhenOpened": "2025-10-17T09:00:51.526Z",
"EditorCaption": ""
},
{
"$type": "Document",
"DocumentIndex": 2,
"Title": "HediffComp_Temperature.cs",
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Hediffs\\HediffComp_Temperature.cs",
"RelativeDocumentMoniker": "Hediffs\\HediffComp_Temperature.cs",
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Hediffs\\HediffComp_Temperature.cs",
"RelativeToolTip": "Hediffs\\HediffComp_Temperature.cs",
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAwAAAAYAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-10-16T15:13:58.773Z",
"EditorCaption": ""
},
{
"$type": "Document",
"DocumentIndex": 3,
"Title": "HediffComp_SpawnPawnOnRemoved.cs",
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Hediffs\\HediffComp_SpawnPawnOnRemoved.cs",
"RelativeDocumentMoniker": "Hediffs\\HediffComp_SpawnPawnOnRemoved.cs",
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Hediffs\\HediffComp_SpawnPawnOnRemoved.cs",
"RelativeToolTip": "Hediffs\\HediffComp_SpawnPawnOnRemoved.cs",
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-10-16T15:13:49.858Z",
"EditorCaption": ""
},
{
"$type": "Document",
"DocumentIndex": 1,
"Title": "HediffComp_LifespanDisplay.cs",
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Hediffs\\HediffComp_LifespanDisplay.cs",
"RelativeDocumentMoniker": "Hediffs\\HediffComp_LifespanDisplay.cs",
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Hediffs\\HediffComp_LifespanDisplay.cs",
"RelativeToolTip": "Hediffs\\HediffComp_LifespanDisplay.cs",
"ViewState": "AgIAAAAAAAAAAAAAAAAAABMAAAANAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-10-16T15:13:38.519Z",
"EditorCaption": ""
},
{
"$type": "Document",
"DocumentIndex": 4,
"Title": "HediffGiver_NonPlayerFaction.cs",
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\HediffGiver\\HediffGiver_NonPlayerFaction.cs",
"RelativeDocumentMoniker": "HediffGiver\\HediffGiver_NonPlayerFaction.cs",
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\HediffGiver\\HediffGiver_NonPlayerFaction.cs",
"RelativeToolTip": "HediffGiver\\HediffGiver_NonPlayerFaction.cs",
"ViewState": "AgIAAAAAAAAAAAAAAAAAACoAAAAFAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-10-16T12:07:58.018Z",
"EditorCaption": ""
},
{
"$type": "Document",
"DocumentIndex": 6,
"Title": "RaidWaveDef.cs",
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Storyteller\\RaidWaveDef.cs",
"RelativeDocumentMoniker": "Storyteller\\RaidWaveDef.cs",
"ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Storyteller\\RaidWaveDef.cs*",
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAkAAAA9AAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-10-16T09:14:26.956Z"
},
{
"$type": "Document",
"DocumentIndex": 5,
"Title": "IncidentWorker_CustomRaid.cs",
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Storyteller\\IncidentWorker_CustomRaid.cs",
"RelativeDocumentMoniker": "Storyteller\\IncidentWorker_CustomRaid.cs",
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Storyteller\\IncidentWorker_CustomRaid.cs",
"RelativeToolTip": "Storyteller\\IncidentWorker_CustomRaid.cs",
"ViewState": "AgIAAHkBAAAAAAAAAAAUwJIBAAAfAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-10-16T07:14:58.682Z"
}
]
}

View File

@@ -106,6 +106,8 @@
<Compile Include="Building_Comps\ARA_Building_RefuelingVat\CompRefuelingVat.cs" />
<Compile Include="Building_Comps\ARA_CompInteractiveProducer\CompResearchProducer.cs" />
<Compile Include="Building_Comps\ARA_CompInteractiveProducer\JobDriver_StartResearchProduction.cs" />
<Compile Include="Building_Comps\ARA_ProductStorage\CompProductStorage.cs" />
<Compile Include="Building_Comps\ARA_ProductStorage\CompProperties_ProductStorage.cs" />
<Compile Include="EventSystem\CompOpenCustomUI.cs" />
<Compile Include="EventSystem\Condition.cs" />
<Compile Include="EventSystem\DebugActions.cs" />

View File

@@ -392,6 +392,12 @@ namespace ArachnaeSwarm
GenPlace.TryPlaceThing(product, parent.Position, parent.Map, ThingPlaceMode.Near);
}
// 新增:弹出剩余燃料
if (FuelComp != null && FuelComp.HasFuel)
{
EjectRemainingFuel();
}
if (Props.destroyOnSpawn)
{
parent.Destroy(DestroyMode.Vanish);
@@ -407,6 +413,81 @@ namespace ArachnaeSwarm
}
}
/// <summary>
/// 弹出剩余燃料为物品(减去初始燃料)
/// </summary>
private void EjectRemainingFuel()
{
if (FuelComp == null || !FuelComp.HasFuel) return;
// 获取当前剩余燃料量
float remainingFuel = FuelComp.Fuel;
// 获取初始燃料量
float initialFuel = GetInitialFuelAmount();
// 计算可弹出的燃料量:当前燃料 - 初始燃料
float fuelToEject = remainingFuel - initialFuel;
if (fuelToEject <= 0)
{
// 开发模式下显示为什么没有弹出燃料
if (Prefs.DevMode)
{
Messages.Message($"No fuel to eject: Current={remainingFuel}, Initial={initialFuel}, Difference={fuelToEject}",
MessageTypeDefOf.SilentInput);
}
return;
}
// 获取燃料过滤器允许的物品定义
ThingDef fuelDef = FuelComp.Props.fuelFilter.AnyAllowedDef;
if (fuelDef == null)
{
Log.Warning("No fuel definition found for ejecting remaining fuel.");
return;
}
// 计算可以生成的物品数量1:1比例
int itemCount = Mathf.FloorToInt(fuelToEject);
if (itemCount > 0)
{
// 生成物品
while (itemCount > 0)
{
Thing fuelThing = ThingMaker.MakeThing(fuelDef);
int stackSize = Mathf.Min(itemCount, fuelDef.stackLimit);
fuelThing.stackCount = stackSize;
itemCount -= stackSize;
// 放置在建筑旁边
GenPlace.TryPlaceThing(fuelThing, parent.Position, parent.Map, ThingPlaceMode.Near);
// 可选:添加消息通知
if (Prefs.DevMode)
{
Messages.Message($"Ejected {stackSize} {fuelDef.label} as remaining fuel (Current: {remainingFuel}, Initial: {initialFuel})",
MessageTypeDefOf.SilentInput);
}
}
// 只清空弹出的燃料量,保留初始燃料
FuelComp.ConsumeFuel(fuelToEject);
}
}
/// <summary>
/// 获取建筑的初始燃料量
/// </summary>
private float GetInitialFuelAmount()
{
// 方法1从CompProperties_RefuelableNutrition获取初始燃料百分比
var fuelProps = FuelComp?.Props;
if (fuelProps != null)
{
return fuelProps.fuelCapacity * fuelProps.initialFuelPercent;
}
// 方法2如果无法获取默认为0
return 0f;
}
private void ResetProduction()
{
if (FuelComp != null) FuelComp.currentConsumptionRate = 0f;

View File

@@ -332,6 +332,13 @@ namespace ArachnaeSwarm
techprint.stackCount = _selectedProcess.techprintCount;
GenPlace.TryPlaceThing(techprint, parent.Position, parent.Map, ThingPlaceMode.Near);
// 新增:弹出剩余燃料
if (FuelComp != null && FuelComp.HasFuel)
{
EjectRemainingFuel();
}
// 添加消息提示
string messageText = "ARA_TechprintProductionComplete".Translate(
_selectedProcess.techprintCount,
@@ -340,6 +347,7 @@ namespace ArachnaeSwarm
);
Messages.Message(messageText, parent, MessageTypeDefOf.PositiveEvent);
if (Props.destroyOnSpawn)
{
parent.Destroy(DestroyMode.Vanish);
@@ -355,6 +363,55 @@ namespace ArachnaeSwarm
}
}
/// <summary>
/// 弹出剩余燃料为物品
/// </summary>
private void EjectRemainingFuel()
{
if (FuelComp == null || !FuelComp.HasFuel) return;
// 获取当前剩余燃料量
float remainingFuel = FuelComp.Fuel;
if (remainingFuel <= 0) return;
// 获取燃料过滤器允许的物品定义
ThingDef fuelDef = FuelComp.Props.fuelFilter.AnyAllowedDef;
if (fuelDef == null)
{
Log.Warning("No fuel definition found for ejecting remaining fuel.");
return;
}
// 计算可以生成的物品数量1:1比例
int itemCount = Mathf.FloorToInt(remainingFuel);
if (itemCount > 0)
{
// 生成物品
while (itemCount > 0)
{
Thing fuelThing = ThingMaker.MakeThing(fuelDef);
int stackSize = Mathf.Min(itemCount, fuelDef.stackLimit);
fuelThing.stackCount = stackSize;
itemCount -= stackSize;
// 放置在建筑旁边
GenPlace.TryPlaceThing(fuelThing, parent.Position, parent.Map, ThingPlaceMode.Near);
// 可选:添加消息通知
if (Prefs.DevMode)
{
Messages.Message($"Ejected {stackSize} {fuelDef.label} as remaining fuel",
MessageTypeDefOf.SilentInput);
}
}
// 清空燃料
FuelComp.ConsumeFuel(remainingFuel);
}
}
private void ResetProduction()
{
if (FuelComp != null) FuelComp.currentConsumptionRate = 0f;

View File

@@ -0,0 +1,164 @@
using RimWorld;
using Verse;
using System.Collections.Generic;
using UnityEngine;
namespace ArachnaeSwarm
{
public class CompProductStorage : CompRefuelable
{
// 使用 new 关键字隐藏基类属性
public new bool IsFull => Fuel >= Props.fuelCapacity;
public float StoragePercent => Fuel / Props.fuelCapacity;
public float StorageAmount => Fuel;
public float StorageCapacity => Props.fuelCapacity;
public float StorageSpaceRemaining => Props.fuelCapacity - Fuel;
public override void PostSpawnSetup(bool respawningAfterLoad)
{
base.PostSpawnSetup(respawningAfterLoad);
// 禁用自动加燃料,但保留其他功能
allowAutoRefuel = false;
}
// === 供其他组件使用的产物管理API ===
/// <summary>
/// 尝试添加产物到储存槽
/// </summary>
public bool TryAddProduct(float amount)
{
if (IsFull || amount <= 0) return false;
// 使用基类的 Refuel 方法
Refuel(amount);
return true;
}
/// <summary>
/// 尝试从储存槽取出产物
/// </summary>
public bool TryRemoveProduct(float amount, out float actualAmount)
{
actualAmount = 0f;
if (Fuel <= 0 || amount <= 0) return false;
// 手动模拟减少燃料量
float newFuel = Fuel - amount;
if (newFuel < 0f)
{
actualAmount = Fuel;
// 使用基类方法将燃料设为0
Refuel(-Fuel); // 这会触发信号
}
else
{
actualAmount = amount;
// 使用基类方法减少燃料
Refuel(-amount); // 这会触发信号
}
return true;
}
/// <summary>
/// 清空储存槽
/// </summary>
public void ClearStorage()
{
// 使用基类方法将燃料设为0
Refuel(-Fuel);
}
/// <summary>
/// 设置储存量(用于初始化或重置)
/// </summary>
public void SetStorage(float amount)
{
float current = Fuel;
float difference = amount - current;
Refuel(difference);
}
// === 重写显示和交互 ===
public override void PostDraw()
{
// 重要:不调用 base.PostDraw(),避免绘制禁止自动填充的图标
// 只绘制燃料条,不绘制禁止图标
if (Props.drawFuelGaugeInMap)
{
GenDraw.FillableBarRequest r = default(GenDraw.FillableBarRequest);
r.center = parent.DrawPos + Vector3.up * 0.1f;
r.size = new Vector2(1f, 0.2f);
r.fillPercent = FuelPercentOfMax;
r.filledMat = SolidColorMaterials.SimpleSolidColorMaterial(new Color(0.6f, 0.56f, 0.13f));
r.unfilledMat = SolidColorMaterials.SimpleSolidColorMaterial(new Color(0.3f, 0.3f, 0.3f));
r.margin = 0.15f;
Rot4 rotation = parent.Rotation;
rotation.Rotate(RotationDirection.Clockwise);
r.rotation = rotation;
GenDraw.DrawFillableBar(r);
}
}
public override IEnumerable<Gizmo> CompGetGizmosExtra()
{
// 调用基类方法获取所有Gizmo包括燃料进度条
foreach (Gizmo gizmo in base.CompGetGizmosExtra())
{
// 但过滤掉我们不想要的Gizmo
if (ShouldShowGizmo(gizmo))
{
yield return gizmo;
}
}
// 添加开发模式下的调试Gizmo
if (Prefs.DevMode)
{
yield return CreateDebugGizmo();
}
}
/// <summary>
/// 决定是否显示特定的Gizmo
/// </summary>
private bool ShouldShowGizmo(Gizmo gizmo)
{
// 保留所有开发模式Gizmo
if (gizmo is Command_Action actionGizmo && actionGizmo.defaultLabel.Contains("Dev:"))
return true;
// 保留燃料进度条相关的Gizmo
if (gizmo is Gizmo_SetFuelLevel)
return true;
// 保留目标燃料设置(如果有)
if (gizmo is Command_SetTargetFuelLevel)
return true;
// 默认隐藏其他燃料相关Gizmo
return false;
}
/// <summary>
/// 创建开发模式下的调试Gizmo
/// </summary>
private Gizmo CreateDebugGizmo()
{
Command_Action debugGizmo = new Command_Action();
debugGizmo.defaultLabel = "Dev: Fill Product Storage";
debugGizmo.action = () =>
{
Refuel(Props.fuelCapacity - Fuel);
Messages.Message("Product storage filled to capacity", MessageTypeDefOf.TaskCompletion);
};
return debugGizmo;
}
}
}

View File

@@ -0,0 +1,52 @@
using RimWorld;
using Verse;
namespace ArachnaeSwarm
{
public class CompProperties_ProductStorage : CompProperties_Refuelable
{
public CompProperties_ProductStorage()
{
compClass = typeof(CompProductStorage);
// 只禁用特定的燃料相关功能保留UI显示
fuelConsumptionRate = 0f;
fuelConsumptionPerTickInRain = 0f;
autoRefuelPercent = 0f;
// 保留燃料Gizmo显示但禁用交互
showFuelGizmo = true; // 改为true以显示燃料状态
showAllowAutoRefuelToggle = false;
allowRefuelIfNotEmpty = false;
destroyOnNoFuel = false;
consumeFuelOnlyWhenUsed = false;
consumeFuelOnlyWhenPowered = false;
drawOutOfFuelOverlay = false; // 确保燃料耗尽覆盖层也被禁用
canEjectFuel = false;
// 保留这些为true以显示UI
hideGizmosIfNotPlayerFaction = false; // 改为false以允许非玩家派系查看
targetFuelLevelConfigurable = true; // 改为true以显示目标燃料设置
drawFuelGaugeInMap = true; // 改为true以在地图上显示燃料条
atomicFueling = false;
initialAllowAutoRefuel = false;
initialFuelPercent = 0f;
// 确保燃料倍数为1不受难度影响
factorByDifficulty = false;
}
public override void ResolveReferences(ThingDef parentDef)
{
base.ResolveReferences(parentDef);
// 确保燃料过滤器允许所有类型(或者根据需求设置)
if (fuelFilter == null)
{
fuelFilter = new ThingFilter();
}
}
}
}

View File

@@ -10,8 +10,9 @@ namespace ArachnaeSwarm
{
public int checkInterval = 250;
public float ejectAtPercent = 1.0f;
public Type targetComp = typeof(CompRefuelable);
public bool allowEjectedFuel = true; // 新增:控制弹出的燃料是否允许操作
public bool allowEjectedFuel = true;
public bool monitorProductStorage = true; // 新增:是否监控CompProductStorage
public bool monitorRefuelable = true; // 新增是否监控CompRefuelable
public CompProperties_AutoEjector()
{
@@ -23,65 +24,204 @@ namespace ArachnaeSwarm
{
private CompProperties_AutoEjector Props => (CompProperties_AutoEjector)this.props;
private CompRefuelable refuelableComp;
private CompProductStorage productStorageComp;
private bool isMonitoringProductStorage = false;
public override void PostSpawnSetup(bool respawningAfterLoad)
{
base.PostSpawnSetup(respawningAfterLoad);
this.refuelableComp = this.parent.GetComps<CompRefuelable>()
.FirstOrDefault(comp => comp.GetType() == this.Props.targetComp);
if (this.refuelableComp == null)
// 根据配置查找要监控的组件
if (Props.monitorProductStorage)
{
Log.Warning($"[ArachnaeSwarm] CompAutoEjector on {parent.def.defName} could not find a CompRefuelable of type '{this.Props.targetComp.FullName}' to monitor.");
productStorageComp = this.parent.GetComp<CompProductStorage>();
if (productStorageComp != null)
{
isMonitoringProductStorage = true;
Log.Message($"[ArachnaeSwarm] CompAutoEjector on {parent.def.defName} is monitoring CompProductStorage.");
return;
}
}
if (Props.monitorRefuelable)
{
refuelableComp = this.parent.GetComp<CompRefuelable>();
if (refuelableComp != null)
{
isMonitoringProductStorage = false;
Log.Message($"[ArachnaeSwarm] CompAutoEjector on {parent.def.defName} is monitoring CompRefuelable.");
return;
}
}
Log.Warning($"[ArachnaeSwarm] CompAutoEjector on {parent.def.defName} could not find any compatible storage component to monitor.");
}
public override void CompTick()
{
base.CompTick();
if (this.refuelableComp != null &&
this.parent.IsHashIntervalTick(this.Props.checkInterval))
if (this.parent.IsHashIntervalTick(this.Props.checkInterval))
{
if (this.refuelableComp.FuelPercentOfMax >= this.Props.ejectAtPercent)
CheckAndEject();
}
}
private void CheckAndEject()
{
if (isMonitoringProductStorage)
{
if (productStorageComp != null && productStorageComp.StoragePercent >= this.Props.ejectAtPercent)
{
// 使用自定义的弹出方法
EjectFuelWithoutForbid();
EjectFromProductStorage();
}
}
else
{
if (refuelableComp != null && refuelableComp.FuelPercentOfMax >= this.Props.ejectAtPercent)
{
EjectFromRefuelable();
}
}
}
/// <summary>
/// 自定义弹出燃料方法,弹出的物品允许操作
/// 从 CompProductStorage 弹出产物
/// </summary>
private void EjectFuelWithoutForbid()
private void EjectFromProductStorage()
{
var props = productStorageComp.Props;
ThingDef thingDef = props.fuelFilter.AllowedThingDefs.FirstOrDefault();
if (thingDef == null)
{
Log.Warning($"[ArachnaeSwarm] No allowed thing def found in fuel filter for {parent.def.defName}");
return;
}
float currentStorage = productStorageComp.StorageAmount;
int num = Mathf.FloorToInt(currentStorage);
if (num <= 0) return;
// 尝试取出产物
if (productStorageComp.TryRemoveProduct(num, out float actualAmount))
{
int actualCount = Mathf.FloorToInt(actualAmount);
while (actualCount > 0)
{
Thing thing = ThingMaker.MakeThing(thingDef);
thing.stackCount = Mathf.Min(actualCount, thingDef.stackLimit);
actualCount -= thing.stackCount;
// 放置物品
GenPlace.TryPlaceThing(thing, parent.Position, parent.Map, ThingPlaceMode.Near);
// 根据配置决定是否允许操作
if (Props.allowEjectedFuel)
{
thing.SetForbidden(false);
}
}
Log.Message($"[ArachnaeSwarm] Ejected {actualAmount} {thingDef.label} from CompProductStorage.");
}
}
/// <summary>
/// 从 CompRefuelable 弹出燃料
/// </summary>
private void EjectFromRefuelable()
{
var props = refuelableComp.Props;
ThingDef thingDef = props.fuelFilter.AllowedThingDefs.First();
int num = Mathf.FloorToInt(refuelableComp.Fuel);
ThingDef thingDef = props.fuelFilter.AllowedThingDefs.FirstOrDefault();
while (num > 0)
if (thingDef == null)
{
Thing thing = ThingMaker.MakeThing(thingDef);
thing.stackCount = Mathf.Min(num, thingDef.stackLimit);
num -= thing.stackCount;
// 放置物品
GenPlace.TryPlaceThing(thing, parent.Position, parent.Map, ThingPlaceMode.Near);
// 根据配置决定是否允许操作
if (Props.allowEjectedFuel)
{
thing.SetForbidden(false); // 允许操作
}
Log.Warning($"[ArachnaeSwarm] No allowed thing def found in fuel filter for {parent.def.defName}");
return;
}
float currentFuel = refuelableComp.Fuel;
int num = Mathf.FloorToInt(currentFuel);
// 重置燃料并发送信号
typeof(CompRefuelable).GetField("fuel", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)
?.SetValue(refuelableComp, 0f);
if (num <= 0) return;
// 使用反射设置燃料为0因为原版方法可能有其他逻辑
var fuelField = typeof(CompRefuelable).GetField("fuel",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
parent.BroadcastCompSignal("RanOutOfFuel");
if (fuelField != null)
{
fuelField.SetValue(refuelableComp, 0f);
while (num > 0)
{
Thing thing = ThingMaker.MakeThing(thingDef);
thing.stackCount = Mathf.Min(num, thingDef.stackLimit);
num -= thing.stackCount;
// 放置物品
GenPlace.TryPlaceThing(thing, parent.Position, parent.Map, ThingPlaceMode.Near);
// 根据配置决定是否允许操作
if (Props.allowEjectedFuel)
{
thing.SetForbidden(false);
}
}
// 发送信号
parent.BroadcastCompSignal("RanOutOfFuel");
Log.Message($"[ArachnaeSwarm] Ejected {currentFuel} {thingDef.label} from CompRefuelable.");
}
}
/// <summary>
/// 获取当前监控的组件类型信息(用于调试或显示)
/// </summary>
public string GetMonitoringInfo()
{
if (isMonitoringProductStorage && productStorageComp != null)
{
return $"Monitoring CompProductStorage: {productStorageComp.StorageAmount}/{productStorageComp.StorageCapacity}";
}
else if (refuelableComp != null)
{
return $"Monitoring CompRefuelable: {refuelableComp.Fuel}/{refuelableComp.Props.fuelCapacity}";
}
else
{
return "Not monitoring any storage component";
}
}
/// <summary>
/// 获取当前储存百分比
/// </summary>
public float GetCurrentStoragePercent()
{
if (isMonitoringProductStorage && productStorageComp != null)
{
return productStorageComp.StoragePercent;
}
else if (refuelableComp != null)
{
return refuelableComp.FuelPercentOfMax;
}
else
{
return 0f;
}
}
/// <summary>
/// 检查是否达到弹出条件
/// </summary>
public bool ShouldEject()
{
return GetCurrentStoragePercent() >= Props.ejectAtPercent;
}
}
}