几个comps修改

This commit is contained in:
2025-10-09 12:02:11 +08:00
parent d16f1cee31
commit 64847d6e88
16 changed files with 681 additions and 77 deletions

Binary file not shown.

View File

@@ -1388,7 +1388,7 @@
<iconPath>ArachnaeSwarm/UI/Abilities/ARA_Suicide_Ability</iconPath> <iconPath>ArachnaeSwarm/UI/Abilities/ARA_Suicide_Ability</iconPath>
<cooldownTicksRange>1</cooldownTicksRange> <cooldownTicksRange>1</cooldownTicksRange>
<aiCanUse>true</aiCanUse> <aiCanUse>true</aiCanUse>
<displayOrder>300</displayOrder> <displayOrder>9900</displayOrder>
<displayGizmoWhileUndrafted>true</displayGizmoWhileUndrafted> <displayGizmoWhileUndrafted>true</displayGizmoWhileUndrafted>
<disableGizmoWhileUndrafted>false</disableGizmoWhileUndrafted> <disableGizmoWhileUndrafted>false</disableGizmoWhileUndrafted>
<warmupStartSound>AcidSpray_Warmup</warmupStartSound> <warmupStartSound>AcidSpray_Warmup</warmupStartSound>
@@ -1419,7 +1419,7 @@
<cooldownTicksRange>144000</cooldownTicksRange> <cooldownTicksRange>144000</cooldownTicksRange>
<targetRequired>false</targetRequired> <targetRequired>false</targetRequired>
<casterMustBeCapableOfViolence>false</casterMustBeCapableOfViolence> <casterMustBeCapableOfViolence>false</casterMustBeCapableOfViolence>
<displayOrder>301</displayOrder> <displayOrder>9901</displayOrder>
<verbProperties> <verbProperties>
<verbClass>Verb_CastAbility</verbClass> <verbClass>Verb_CastAbility</verbClass>
<drawAimPie>false</drawAimPie> <drawAimPie>false</drawAimPie>

View File

@@ -229,6 +229,13 @@
<customLabel>温度要求</customLabel> <customLabel>温度要求</customLabel>
<showCurrentTemperature>true</showCurrentTemperature> <showCurrentTemperature>true</showCurrentTemperature>
</li> </li>
<li Class="ArachnaeSwarm.CompProperties_AbilityShowInteractiveThing">
<cocoonBuildingDef>ARA_Cocoon_Cloth</cocoonBuildingDef>
<customLabel>可孵化物品列表</customLabel>
<showResearchRequirements>true</showResearchRequirements>
<showNutritionCost>true</showNutritionCost>
<showIncubationTime>true</showIncubationTime>
</li>
</comps> </comps>
</AbilityDef> </AbilityDef>
<AbilityDef ParentName="ARA_CocoonSpew_Base"> <AbilityDef ParentName="ARA_CocoonSpew_Base">
@@ -245,6 +252,13 @@
<customLabel>温度要求</customLabel> <customLabel>温度要求</customLabel>
<showCurrentTemperature>true</showCurrentTemperature> <showCurrentTemperature>true</showCurrentTemperature>
</li> </li>
<li Class="ArachnaeSwarm.CompProperties_AbilityShowInteractiveThing">
<cocoonBuildingDef>ARA_Cocoon_Weapon</cocoonBuildingDef>
<customLabel>可孵化物品列表</customLabel>
<showResearchRequirements>true</showResearchRequirements>
<showNutritionCost>true</showNutritionCost>
<showIncubationTime>true</showIncubationTime>
</li>
</comps> </comps>
</AbilityDef> </AbilityDef>
<!-- T1 --> <!-- T1 -->
@@ -262,6 +276,13 @@
<customLabel>温度要求</customLabel> <customLabel>温度要求</customLabel>
<showCurrentTemperature>true</showCurrentTemperature> <showCurrentTemperature>true</showCurrentTemperature>
</li> </li>
<li Class="ArachnaeSwarm.CompProperties_AbilityShowInteractiveThing">
<cocoonBuildingDef>ARA_Cocoon_Cloth_1Stage</cocoonBuildingDef>
<customLabel>可孵化物品列表</customLabel>
<showResearchRequirements>true</showResearchRequirements>
<showNutritionCost>true</showNutritionCost>
<showIncubationTime>true</showIncubationTime>
</li>
</comps> </comps>
</AbilityDef> </AbilityDef>
<AbilityDef ParentName="ARA_CocoonSpew_Base"> <AbilityDef ParentName="ARA_CocoonSpew_Base">
@@ -278,6 +299,13 @@
<customLabel>温度要求</customLabel> <customLabel>温度要求</customLabel>
<showCurrentTemperature>true</showCurrentTemperature> <showCurrentTemperature>true</showCurrentTemperature>
</li> </li>
<li Class="ArachnaeSwarm.CompProperties_AbilityShowInteractiveThing">
<cocoonBuildingDef>ARA_Cocoon_Weapon_1Stage</cocoonBuildingDef>
<customLabel>可孵化物品列表</customLabel>
<showResearchRequirements>true</showResearchRequirements>
<showNutritionCost>true</showNutritionCost>
<showIncubationTime>true</showIncubationTime>
</li>
</comps> </comps>
</AbilityDef> </AbilityDef>
<!-- T2 --> <!-- T2 -->
@@ -295,10 +323,17 @@
<customLabel>温度要求</customLabel> <customLabel>温度要求</customLabel>
<showCurrentTemperature>true</showCurrentTemperature> <showCurrentTemperature>true</showCurrentTemperature>
</li> </li>
<li Class="ArachnaeSwarm.CompProperties_AbilityShowInteractiveThing">
<cocoonBuildingDef>ARA_Cocoon_Cloth_2Stage</cocoonBuildingDef>
<customLabel>可孵化物品列表</customLabel>
<showResearchRequirements>true</showResearchRequirements>
<showNutritionCost>true</showNutritionCost>
<showIncubationTime>true</showIncubationTime>
</li>
</comps> </comps>
</AbilityDef> </AbilityDef>
<AbilityDef ParentName="ARA_CocoonSpew_Base"> <AbilityDef ParentName="ARA_CocoonSpew_Base">
<defName>ARA_Cocoon_Weapon_2Stage_Ability</defName> <defName>ARA_Cocoon_Weapon_2Stage</defName>
<label>武装器官孵化茧——等级2</label> <label>武装器官孵化茧——等级2</label>
<description>投放一枚武装器官茧,内含可以孵化一套基础武装器官的营养和遗传物质——参阅茧的超链接,了解其能生产的所有装备的特点。</description> <description>投放一枚武装器官茧,内含可以孵化一套基础武装器官的营养和遗传物质——参阅茧的超链接,了解其能生产的所有装备的特点。</description>
<iconPath>ArachnaeSwarm/UI/Abilities/ARA_Cocoon_Weapon_2Stage</iconPath> <iconPath>ArachnaeSwarm/UI/Abilities/ARA_Cocoon_Weapon_2Stage</iconPath>
@@ -311,6 +346,13 @@
<customLabel>温度要求</customLabel> <customLabel>温度要求</customLabel>
<showCurrentTemperature>true</showCurrentTemperature> <showCurrentTemperature>true</showCurrentTemperature>
</li> </li>
<li Class="ArachnaeSwarm.CompProperties_AbilityShowInteractiveThing">
<cocoonBuildingDef>ARA_Cocoon_Weapon_2Stage</cocoonBuildingDef>
<customLabel>可孵化物品列表</customLabel>
<showResearchRequirements>true</showResearchRequirements>
<showNutritionCost>true</showNutritionCost>
<showIncubationTime>true</showIncubationTime>
</li>
</comps> </comps>
</AbilityDef> </AbilityDef>

View File

@@ -319,7 +319,7 @@
<li Class="HediffCompProperties_GiveAbility"> <li Class="HediffCompProperties_GiveAbility">
<abilityDefs> <abilityDefs>
<li>ARA_Cocoon_Cloth_2Stage</li> <li>ARA_Cocoon_Cloth_2Stage</li>
<li>ARA_Cocoon_Weapon_2Stage_Ability</li> <li>ARA_Cocoon_Weapon_2Stage</li>
</abilityDefs> </abilityDefs>
</li> </li>
</comps> </comps>

View File

@@ -26,7 +26,7 @@
<takeFootprints>True</takeFootprints> <takeFootprints>True</takeFootprints>
<avoidWander>false</avoidWander> <avoidWander>false</avoidWander>
<statBases> <statBases>
<Beauty>-6</Beauty> <Beauty>0</Beauty>
<CleaningTimeFactor>0.25</CleaningTimeFactor> <CleaningTimeFactor>0.25</CleaningTimeFactor>
<Cleanliness>0</Cleanliness> <Cleanliness>0</Cleanliness>
<Flammability>0</Flammability> <Flammability>0</Flammability>
@@ -75,7 +75,7 @@
<li>Substructure</li> <li>Substructure</li>
</affordances> </affordances>
<statBases> <statBases>
<Beauty>-6</Beauty> <Beauty>0</Beauty>
<CleaningTimeFactor>0.25</CleaningTimeFactor> <CleaningTimeFactor>0.25</CleaningTimeFactor>
<Cleanliness>0</Cleanliness> <Cleanliness>0</Cleanliness>
<Flammability>0</Flammability> <Flammability>0</Flammability>
@@ -122,7 +122,7 @@
<staticSunShadowHeight>0</staticSunShadowHeight> <staticSunShadowHeight>0</staticSunShadowHeight>
<statBases> <statBases>
<MarketValue>0</MarketValue> <MarketValue>0</MarketValue>
<Beauty>-6</Beauty> <Beauty>0</Beauty>
<MaxHitPoints>1000</MaxHitPoints> <MaxHitPoints>1000</MaxHitPoints>
<WorkToBuild>1500</WorkToBuild> <WorkToBuild>1500</WorkToBuild>
<Flammability>0</Flammability> <Flammability>0</Flammability>
@@ -198,7 +198,7 @@
<MaxHitPoints>1200</MaxHitPoints> <MaxHitPoints>1200</MaxHitPoints>
<Flammability>0</Flammability> <Flammability>0</Flammability>
<WorkToBuild>1000</WorkToBuild> <WorkToBuild>1000</WorkToBuild>
<Beauty>-10</Beauty> <Beauty>0</Beauty>
<DoorOpenSpeed>2</DoorOpenSpeed> <DoorOpenSpeed>2</DoorOpenSpeed>
</statBases> </statBases>
<costStuffCount>10</costStuffCount> <costStuffCount>10</costStuffCount>
@@ -687,7 +687,7 @@
<WorkToBuild>750</WorkToBuild> <WorkToBuild>750</WorkToBuild>
<Mass>5</Mass> <Mass>5</Mass>
<Flammability>1.0</Flammability> <Flammability>1.0</Flammability>
<Beauty>-5</Beauty> <Beauty>0</Beauty>
<Comfort>0.70</Comfort> <Comfort>0.70</Comfort>
<StyleDominance MayRequire="Ludeon.RimWorld.Ideology">5</StyleDominance> <StyleDominance MayRequire="Ludeon.RimWorld.Ideology">5</StyleDominance>
</statBases> </statBases>
@@ -760,7 +760,7 @@
<WorkToBuild>750</WorkToBuild> <WorkToBuild>750</WorkToBuild>
<Mass>10</Mass> <Mass>10</Mass>
<Flammability>1.0</Flammability> <Flammability>1.0</Flammability>
<Beauty>5</Beauty> <Beauty>1</Beauty>
<StyleDominance MayRequire="Ludeon.RimWorld.Ideology">10</StyleDominance> <StyleDominance MayRequire="Ludeon.RimWorld.Ideology">10</StyleDominance>
</statBases> </statBases>
<researchPrerequisites> <researchPrerequisites>

View File

@@ -727,7 +727,7 @@
<li>InsectJelly</li> <li>InsectJelly</li>
</disallowedThingDefs> </disallowedThingDefs>
</fuelFilter> </fuelFilter>
<fuelCapacity>50</fuelCapacity> <fuelCapacity>20</fuelCapacity>
<fuelConsumptionRate>0</fuelConsumptionRate> <fuelConsumptionRate>0</fuelConsumptionRate>
<consumeFuelOnlyWhenUsed>true</consumeFuelOnlyWhenUsed> <consumeFuelOnlyWhenUsed>true</consumeFuelOnlyWhenUsed>
@@ -757,7 +757,7 @@
</li> </li>
<li Class="ArachnaeSwarm.CompProperties_NutritionToFuelConverter"> <li Class="ArachnaeSwarm.CompProperties_NutritionToFuelConverter">
<checkInterval>200</checkInterval> <checkInterval>200</checkInterval>
<nutritionCost>1</nutritionCost> <nutritionCost>0.25</nutritionCost>
<workAmount>2000</workAmount> <workAmount>2000</workAmount>
<fuelAmount>1</fuelAmount> <fuelAmount>1</fuelAmount>
</li> </li>

View File

@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LanguageData> <LanguageData>
<EstimatedQuality>预计品质</EstimatedQuality> <EstimatedQuality>预计品质</EstimatedQuality>
<QualityScore>品质评分</QualityScore> <QualityScore>品质评分</QualityScore>
<TemperaturePenalty>温度惩罚</TemperaturePenalty> <TemperaturePenalty>温度惩罚</TemperaturePenalty>
@@ -8,17 +7,20 @@
<SafeTemperatureRange>安全范围</SafeTemperatureRange> <SafeTemperatureRange>安全范围</SafeTemperatureRange>
<CannotStartProduction>无法开始生产</CannotStartProduction> <CannotStartProduction>无法开始生产</CannotStartProduction>
<NoFuel>无燃料</NoFuel> <NoFuel>无燃料</NoFuel>
<StartProduction>开始生产 {0}</StartProduction> <StartProduction>开始生产 {0}{1} 营养)</StartProduction>
<CommandCancelProduction>取消生产</CommandCancelProduction> <CommandCancelProduction>取消生产</CommandCancelProduction>
<CommandCancelProductionDesc>停止当前的生产流程。</CommandCancelProductionDesc> <CommandCancelProductionDesc>停止当前的生产流程。</CommandCancelProductionDesc>
<Producing>正在生产 {0}</Producing> <Producing>正在生产 {0}</Producing>
<TimeLeft>剩余时间</TimeLeft> <TimeLeft>剩余时间</TimeLeft>
<ProjectedQuality>预计品质</ProjectedQuality> <ProjectedQuality>预计品质</ProjectedQuality>
<NotProducing>未在生产</NotProducing> <NotProducing>未在生产</NotProducing>
<ARA_NeedArachnaeToStartIncubation>未孵化,需要阿拉克涅工艺种交互</ARA_NeedArachnaeToStartIncubation> <ARA_NeedSpecificArachnaeToStartIncubation>未孵化,需要 {0} 交互({1}</ARA_NeedSpecificArachnaeToStartIncubation>
<ARA_AnyArachnaeRace>任何阿拉克涅虫族</ARA_AnyArachnaeRace>
<ARA_ItemsAvailable>{0} 个物品可用</ARA_ItemsAvailable>
<!-- Added for CompQueuedPawnSpawner --> <!-- Added for CompQueuedPawnSpawner -->
<NutritionNeeded>所需营养</NutritionNeeded> <NutritionNeeded>所需营养</NutritionNeeded>
<ARA_Incubate>孵化 {0}</ARA_Incubate> <ARA_Incubate>孵化 {0}</ARA_Incubate>
<ARA_CocoonCooldown>茧正在稳定中:{0}</ARA_CocoonCooldown>
</LanguageData> </LanguageData>

View File

@@ -3,8 +3,16 @@
"WorkspaceRootPath": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\", "WorkspaceRootPath": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\",
"Documents": [ "Documents": [
{ {
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|d:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\abilities\\ara_queenability\\compabilityeffect_needcost.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:abilities\\ara_queenability\\compabilityeffect_needcost.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|D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\hediffs\\moharhediffs\\hediffcomp_spawner.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:hediffs\\moharhediffs\\hediffcomp_spawner.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\\abilities\\ara_showtemperaturerange\\compabilityeffect_abilityshowtemperaturerange.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:abilities\\ara_showtemperaturerange\\compabilityeffect_abilityshowtemperaturerange.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
} }
], ],
"DocumentGroupContainers": [ "DocumentGroupContainers": [
@@ -23,14 +31,40 @@
{ {
"$type": "Document", "$type": "Document",
"DocumentIndex": 0, "DocumentIndex": 0,
"Title": "CompAbilityEffect_NeedCost.cs", "Title": "CompInteractiveProducer.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_QueenAbility\\CompAbilityEffect_NeedCost.cs", "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\ARA_CompInteractiveProducer\\CompInteractiveProducer.cs",
"RelativeDocumentMoniker": "Abilities\\ARA_QueenAbility\\CompAbilityEffect_NeedCost.cs", "RelativeDocumentMoniker": "Building_Comps\\ARA_CompInteractiveProducer\\CompInteractiveProducer.cs",
"ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_QueenAbility\\CompAbilityEffect_NeedCost.cs", "ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\ARA_CompInteractiveProducer\\CompInteractiveProducer.cs",
"RelativeToolTip": "Abilities\\ARA_QueenAbility\\CompAbilityEffect_NeedCost.cs", "RelativeToolTip": "Building_Comps\\ARA_CompInteractiveProducer\\CompInteractiveProducer.cs",
"ViewState": "AgIAACUAAAAAAAAAAAAAAEgAAAAAAAAAAAAAAA==", "ViewState": "AgIAAEgAAAAAAAAAAAA4wDcAAABHAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-10-08T08:23:27.533Z", "WhenOpened": "2025-10-09T03:57:32.708Z",
"EditorCaption": ""
},
{
"$type": "Document",
"DocumentIndex": 1,
"Title": "HediffComp_Spawner.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Hediffs\\MoharHediffs\\HediffComp_Spawner.cs",
"RelativeDocumentMoniker": "Hediffs\\MoharHediffs\\HediffComp_Spawner.cs",
"ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Hediffs\\MoharHediffs\\HediffComp_Spawner.cs",
"RelativeToolTip": "Hediffs\\MoharHediffs\\HediffComp_Spawner.cs",
"ViewState": "AgIAAAQAAAAAAAAAAAAswBIAAAAAAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-10-09T03:45:03.599Z",
"EditorCaption": ""
},
{
"$type": "Document",
"DocumentIndex": 2,
"Title": "CompAbilityEffect_AbilityShowTemperatureRange.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_ShowTemperatureRange\\CompAbilityEffect_AbilityShowTemperatureRange.cs",
"RelativeDocumentMoniker": "Abilities\\ARA_ShowTemperatureRange\\CompAbilityEffect_AbilityShowTemperatureRange.cs",
"ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_ShowTemperatureRange\\CompAbilityEffect_AbilityShowTemperatureRange.cs",
"RelativeToolTip": "Abilities\\ARA_ShowTemperatureRange\\CompAbilityEffect_AbilityShowTemperatureRange.cs",
"ViewState": "AgIAAC8AAAAAAAAAAAAUwAYAAAAXAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-10-09T02:18:27.532Z",
"EditorCaption": "" "EditorCaption": ""
} }
] ]

View File

@@ -0,0 +1,214 @@
using RimWorld;
using Verse;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace ArachnaeSwarm
{
public class CompAbilityEffect_ShowInteractiveThing : CompAbilityEffect
{
public new CompProperties_AbilityShowInteractiveThing Props => (CompProperties_AbilityShowInteractiveThing)props;
public override void Apply(LocalTargetInfo target, LocalTargetInfo dest)
{
// 这个组件只用于显示信息,不执行实际效果
}
public override bool Valid(LocalTargetInfo target, bool throwMessages = false)
{
return true;
}
// 重写工具提示方法,显示可孵化的物品列表
public override string ExtraTooltipPart()
{
StringBuilder stringBuilder = new StringBuilder();
// 获取所有可孵化的物品
var incubatableItems = GetIncubatableItems();
if (incubatableItems.Count == 0)
{
return null; // 没有可显示的内容
}
stringBuilder.AppendLine(Props.customLabel + ":");
stringBuilder.AppendLine();
// 显示每个可孵化的物品
foreach (var item in incubatableItems)
{
string entryText = $" • {item.thingDef.LabelCap}";
// 显示营养需求
if (Props.showNutritionCost)
{
float nutritionCost = GetIncubationCost(item.thingDef);
entryText += $" ({nutritionCost.ToString("F1")} 营养)";
}
// 显示孵化时间
if (Props.showIncubationTime)
{
int incubationTicks = GetIncubationTimeTicks(item.thingDef);
entryText += $" [{incubationTicks.ToStringTicksToPeriod()}]";
}
// 显示科技需求
if (Props.showResearchRequirements && item.requiredResearch != null)
{
bool researched = item.requiredResearch.IsFinished;
string researchStatus = researched ? "✓" : "✗";
entryText += $" <color={(researched ? "green" : "red")}>[{researchStatus}{item.requiredResearch.LabelCap}]</color>";
}
stringBuilder.AppendLine(entryText);
}
return stringBuilder.ToString().TrimEndNewlines();
}
// 获取所有可孵化的物品(基于 CompExtraIncubationInfo
private List<ProcessDef> GetIncubatableItems()
{
var result = new List<ProcessDef>();
if (Props.cocoonBuildingDef == null)
{
Log.Error("CompAbilityEffect_ShowInteractiveThing: cocoonBuildingDef is null");
return result;
}
// 扫描所有定义了 CompExtraIncubationInfo 的物品
foreach (ThingDef thingDef in DefDatabase<ThingDef>.AllDefs)
{
var incubationCompProps = thingDef.GetCompProperties<CompProperties_ExtraIncubationInfo>();
if (incubationCompProps != null)
{
bool isMatch = false;
if (!incubationCompProps.cocoonDefs.NullOrEmpty())
{
isMatch = incubationCompProps.cocoonDefs.Contains(Props.cocoonBuildingDef);
}
else if (incubationCompProps.cocoonDef != null)
{
isMatch = incubationCompProps.cocoonDef == Props.cocoonBuildingDef;
}
if (isMatch)
{
// 获取研究前提
ResearchProjectDef researchPrerequisite = GetResearchPrerequisite(thingDef);
// 创建 ProcessDef与 CompInteractiveProducer 中的结构一致)
ProcessDef process = new ProcessDef
{
thingDef = thingDef,
productionTicks = GetIncubationTimeTicks(thingDef),
totalNutritionNeeded = GetIncubationCost(thingDef),
requiredResearch = researchPrerequisite
};
result.Add(process);
}
}
}
// 按物品名称排序
result.SortBy(p => p.thingDef.label);
return result;
}
// 获取研究前提(与 CompInteractiveProducer 中的逻辑一致)
private ResearchProjectDef GetResearchPrerequisite(ThingDef thingDef)
{
ResearchProjectDef researchPrerequisite = null;
// 方法1从 recipeMaker.researchPrerequisite 获取
if (thingDef.recipeMaker?.researchPrerequisite != null)
{
researchPrerequisite = thingDef.recipeMaker.researchPrerequisite;
}
// 方法2从 recipeMaker.researchPrerequisites 获取第一个
else if (thingDef.recipeMaker?.researchPrerequisites?.Count > 0)
{
researchPrerequisite = thingDef.recipeMaker.researchPrerequisites[0];
}
// 方法3从 thingDef.researchPrerequisites 获取(备用)
else if (thingDef.researchPrerequisites?.Count > 0)
{
researchPrerequisite = thingDef.researchPrerequisites[0];
}
return researchPrerequisite;
}
// 获取孵化时间(与 CompInteractiveProducer 中的逻辑一致)
private int GetIncubationTimeTicks(ThingDef thingDef)
{
StatDef incubationTimeStat = DefDatabase<StatDef>.GetNamedSilentFail("ARA_IncubationTime");
if (incubationTimeStat != null && thingDef.statBases != null)
{
var statValue = thingDef.statBases.FirstOrDefault(s => s.stat == incubationTimeStat);
if (statValue != null)
{
// ARA_IncubationTime 是以天为单位,转换为 ticks (1天 = 60000 ticks)
return Mathf.RoundToInt(statValue.value * 60000f);
}
}
// 默认值1 天
return 60000;
}
// 获取孵化所需营养(与 CompInteractiveProducer 中的逻辑一致)
private float GetIncubationCost(ThingDef thingDef)
{
StatDef incubationCostStat = DefDatabase<StatDef>.GetNamedSilentFail("ARA_IncubationCost");
if (incubationCostStat != null && thingDef.statBases != null)
{
var statValue = thingDef.statBases.FirstOrDefault(s => s.stat == incubationCostStat);
if (statValue != null)
{
return statValue.value;
}
}
// 默认值10 营养
return 10f;
}
// 获取所有可孵化的物品种类(用于其他用途)
public List<ThingDef> GetIncubatableThingDefs()
{
var incubatableItems = GetIncubatableItems();
var result = new List<ThingDef>();
foreach (var item in incubatableItems)
{
if (item.thingDef != null && (item.requiredResearch == null || item.requiredResearch.IsFinished))
{
result.Add(item.thingDef);
}
}
return result;
}
// 检查特定物品是否可孵化
public bool CanIncubateThingDef(ThingDef thingDef)
{
var incubatableItems = GetIncubatableItems();
foreach (var item in incubatableItems)
{
if (item.thingDef == thingDef &&
(item.requiredResearch == null || item.requiredResearch.IsFinished))
{
return true;
}
}
return false;
}
}
}

View File

@@ -0,0 +1,19 @@
using RimWorld;
using Verse;
namespace ArachnaeSwarm
{
public class CompProperties_AbilityShowInteractiveThing : CompProperties_AbilityEffect
{
public ThingDef cocoonBuildingDef; // 指向的茧建筑定义
public string customLabel = "可孵化物品"; // 自定义标签
public bool showResearchRequirements = true; // 是否显示科技需求
public bool showNutritionCost = true; // 是否显示营养需求
public bool showIncubationTime = true; // 是否显示孵化时间
public CompProperties_AbilityShowInteractiveThing()
{
this.compClass = typeof(CompAbilityEffect_ShowInteractiveThing);
}
}
}

View File

@@ -2,6 +2,7 @@ using RimWorld;
using Verse; using Verse;
using System.Text; using System.Text;
using System.Collections.Generic; using System.Collections.Generic;
using UnityEngine;
namespace ArachnaeSwarm namespace ArachnaeSwarm
{ {
@@ -19,7 +20,7 @@ namespace ArachnaeSwarm
return true; return true;
} }
// Override tooltip method to display temperature range information // Override tooltip method to display temperature range information with progress bar
public override string ExtraTooltipPart() public override string ExtraTooltipPart()
{ {
StringBuilder stringBuilder = new StringBuilder(); StringBuilder stringBuilder = new StringBuilder();
@@ -31,23 +32,84 @@ namespace ArachnaeSwarm
return null; // No content to display return null; // No content to display
} }
// 第一行:安全温度范围
stringBuilder.AppendLine(Props.customLabel.Translate() + ":"); stringBuilder.AppendLine(Props.customLabel.Translate() + ":");
stringBuilder.AppendLine();
// Display temperature range // 第二行:当前温度
stringBuilder.AppendLine(" " + "AbilityCheckSafeTemperatureRange".Translate(tempCompProps.minSafeTemperature, tempCompProps.maxSafeTemperature)); float currentTemp = parent.pawn != null && parent.pawn.Map != null ?
GenTemperature.GetTemperatureForCell(parent.pawn.Position, parent.pawn.Map) : 0f;
stringBuilder.AppendLine($" 当前温度: {currentTemp:0.0}°C");
// Display current temperature (if enabled) // 第三行和第四行:温度标签和进度条
if (Props.showCurrentTemperature && parent.pawn != null && parent.pawn.Map != null) var (tempLabels, progressBar) = GetTemperatureProgressBar(currentTemp, tempCompProps.minSafeTemperature, tempCompProps.maxSafeTemperature);
{ stringBuilder.AppendLine(tempLabels);
float currentTemp = GenTemperature.GetTemperatureForCell(parent.pawn.Position, parent.pawn.Map); stringBuilder.AppendLine(progressBar);
// 第五行:温度状态
string tempStatus = GetTemperatureStatus(currentTemp, tempCompProps.minSafeTemperature, tempCompProps.maxSafeTemperature); string tempStatus = GetTemperatureStatus(currentTemp, tempCompProps.minSafeTemperature, tempCompProps.maxSafeTemperature);
stringBuilder.AppendLine(); string statusColor = GetTemperatureStatusColor(currentTemp, tempCompProps.minSafeTemperature, tempCompProps.maxSafeTemperature);
stringBuilder.AppendLine("AbilityCheckCurrentTemperature".Translate(currentTemp.ToString("F1"), tempStatus)); stringBuilder.AppendLine($" <color={statusColor}>{tempStatus}</color>");
}
return stringBuilder.ToString().TrimEndNewlines(); return stringBuilder.ToString().TrimEndNewlines();
} }
// Get temperature progress bar display
private (string tempLabels, string progressBar) GetTemperatureProgressBar(float currentTemp, float minSafe, float maxSafe)
{
const int barLength = 20;
// Use only the safe temperature range for display
float displayMin = minSafe;
float displayMax = maxSafe;
// Calculate current position in the bar
float normalizedPos = Mathf.Clamp01((currentTemp - displayMin) / (displayMax - displayMin));
int currentPos = Mathf.RoundToInt(normalizedPos * (barLength - 1));
// Build temperature labels line (第三行)
string minTempLabel = $"{displayMin:0}°C";
string maxTempLabel = $"{displayMax:0}°C";
// Calculate spacing to align labels with progress bar
int totalSpaces = barLength + 2 - minTempLabel.Length - maxTempLabel.Length; // +2 for brackets
string spacing = new string(' ', Mathf.Max(1, totalSpaces));
string tempLabels = $" {minTempLabel}{spacing}{maxTempLabel}";
// Build progress bar (第四行)
StringBuilder bar = new StringBuilder();
bar.Append(" [");
for (int i = 0; i < barLength; i++)
{
if (i == currentPos)
{
// Current temperature indicator - color based on position
string markerColor = GetMarkerColor(currentTemp, minSafe, maxSafe);
bar.Append($"<color={markerColor}>|</color>");
}
else
{
// Regular segment - always green since we're only showing the safe range
bar.Append("<color=green>─</color>");
}
}
bar.Append("]");
return (tempLabels, bar.ToString());
}
// Get color for the current temperature marker
private string GetMarkerColor(float currentTemp, float minSafe, float maxSafe)
{
if (currentTemp < minSafe)
return "blue"; // Below minimum - blue
else if (currentTemp > maxSafe)
return "red"; // Above maximum - red
else
return "green"; // Within safe range - green
}
// Get temperature status description // Get temperature status description
private string GetTemperatureStatus(float currentTemp, float minSafe, float maxSafe) private string GetTemperatureStatus(float currentTemp, float minSafe, float maxSafe)
{ {
@@ -59,6 +121,17 @@ namespace ArachnaeSwarm
return "AbilityCheckTemperatureSafe".Translate(); return "AbilityCheckTemperatureSafe".Translate();
} }
// Get color for temperature status
private string GetTemperatureStatusColor(float currentTemp, float minSafe, float maxSafe)
{
if (currentTemp < minSafe)
return "blue";
else if (currentTemp > maxSafe)
return "red";
else
return "green";
}
// Get temperature control component from building definition // Get temperature control component from building definition
private CompProperties_TemperatureRuinableDamage GetTemperatureCompFromBuilding() private CompProperties_TemperatureRuinableDamage GetTemperatureCompFromBuilding()
{ {

View File

@@ -95,6 +95,8 @@
<Compile Include="Abilities\ARA_QueenAbility\CompAbilityEffect_ResearchPrereq.cs" /> <Compile Include="Abilities\ARA_QueenAbility\CompAbilityEffect_ResearchPrereq.cs" />
<Compile Include="Abilities\ARA_QueenAbility\CompAbilityEffect_SprayLiquidMulti.cs" /> <Compile Include="Abilities\ARA_QueenAbility\CompAbilityEffect_SprayLiquidMulti.cs" />
<Compile Include="Abilities\ARA_QueenAbility\CompProperties_AbilitySprayLiquidMulti.cs" /> <Compile Include="Abilities\ARA_QueenAbility\CompProperties_AbilitySprayLiquidMulti.cs" />
<Compile Include="Abilities\ARA_ShowInteractiveThing\CompAbilityEffect_ShowInteractiveThing.cs" />
<Compile Include="Abilities\ARA_ShowInteractiveThing\CompProperties_AbilityShowInteractiveThing.cs" />
<Compile Include="Abilities\ARA_ShowSpawnablePawnsList\CompAbilityEffect_AbilityShowSpawnablePawns.cs" /> <Compile Include="Abilities\ARA_ShowSpawnablePawnsList\CompAbilityEffect_AbilityShowSpawnablePawns.cs" />
<Compile Include="Abilities\ARA_ShowSpawnablePawnsList\CompProperties_AbilityShowSpawnablePawns.cs" /> <Compile Include="Abilities\ARA_ShowSpawnablePawnsList\CompProperties_AbilityShowSpawnablePawns.cs" />
<Compile Include="Buildings\Building_TurretGunHasSpeed.cs" /> <Compile Include="Buildings\Building_TurretGunHasSpeed.cs" />

View File

@@ -35,13 +35,28 @@ namespace ArachnaeSwarm
private int ticksUnderOptimalConditions; private int ticksUnderOptimalConditions;
private float temperaturePenaltyPercent; private float temperaturePenaltyPercent;
private List<ProcessDef> _cachedProcesses; private List<ProcessDef> _cachedProcesses;
private int spawnTick = -1; // 新增:记录生成时间
private const int COOLDOWN_TICKS = 120; // 新增120 tick冷却时间
private CompRefuelableNutrition _fuelComp; private CompRefuelableNutrition _fuelComp;
private static readonly Texture2D CancelIcon = ContentFinder<Texture2D>.Get("UI/Designators/Cancel"); private static readonly Texture2D CancelIcon = ContentFinder<Texture2D>.Get("UI/Designators/Cancel");
public bool InProduction => _selectedProcess != null; public bool InProduction => _selectedProcess != null;
public bool InCooldown => spawnTick > 0 && Find.TickManager.TicksGame < spawnTick + COOLDOWN_TICKS; // 新增:冷却状态检查
public CompProperties_InteractiveProducer Props => (CompProperties_InteractiveProducer)props; public CompProperties_InteractiveProducer Props => (CompProperties_InteractiveProducer)props;
// 生产进度0-1
public float ProductionProgress
{
get
{
if (!InProduction || productionUntilTick <= 0) return 0f;
int totalTicks = _selectedProcess.productionTicks;
int elapsedTicks = totalTicks - (productionUntilTick - Find.TickManager.TicksGame);
return Mathf.Clamp01((float)elapsedTicks / totalTicks);
}
}
// 自动生成的 ProcessDef 列表 // 自动生成的 ProcessDef 列表
public List<ProcessDef> Processes public List<ProcessDef> Processes
{ {
@@ -69,6 +84,12 @@ namespace ArachnaeSwarm
base.PostSpawnSetup(respawningAfterLoad); base.PostSpawnSetup(respawningAfterLoad);
_fuelComp = parent.GetComp<CompRefuelableNutrition>(); _fuelComp = parent.GetComp<CompRefuelableNutrition>();
BuildProcessList(); // 确保进程列表在生成时构建 BuildProcessList(); // 确保进程列表在生成时构建
// 新增:记录生成时间(仅在首次生成时,不是加载后)
if (!respawningAfterLoad)
{
spawnTick = Find.TickManager.TicksGame;
}
} }
public override void PostExposeData() public override void PostExposeData()
@@ -82,6 +103,7 @@ namespace ArachnaeSwarm
Scribe_Values.Look(ref productionUntilTick, "productionUntilTick", -1); Scribe_Values.Look(ref productionUntilTick, "productionUntilTick", -1);
Scribe_Values.Look(ref ticksUnderOptimalConditions, "ticksUnderOptimalConditions", 0); Scribe_Values.Look(ref ticksUnderOptimalConditions, "ticksUnderOptimalConditions", 0);
Scribe_Values.Look(ref temperaturePenaltyPercent, "temperaturePenaltyPercent", 0f); Scribe_Values.Look(ref temperaturePenaltyPercent, "temperaturePenaltyPercent", 0f);
Scribe_Values.Look(ref spawnTick, "spawnTick", -1); // 新增:序列化生成时间
// 加载时重建 selectedProcess // 加载时重建 selectedProcess
if (Scribe.mode == LoadSaveMode.LoadingVars && selectedProcessThingDef != null) if (Scribe.mode == LoadSaveMode.LoadingVars && selectedProcessThingDef != null)
@@ -264,27 +286,38 @@ namespace ArachnaeSwarm
public override IEnumerable<FloatMenuOption> CompFloatMenuOptions(Pawn selPawn) public override IEnumerable<FloatMenuOption> CompFloatMenuOptions(Pawn selPawn)
{ {
// 新增:冷却期内不提供任何交互选项
if (InCooldown)
{
int remainingTicks = (spawnTick + COOLDOWN_TICKS) - Find.TickManager.TicksGame;
yield return new FloatMenuOption($"ARA_CocoonCooldown".Translate(remainingTicks.ToStringTicksToPeriod()), null);
yield break;
}
if (InProduction || !selPawn.CanReach(parent, PathEndMode.InteractionCell, Danger.Deadly)) yield break; if (InProduction || !selPawn.CanReach(parent, PathEndMode.InteractionCell, Danger.Deadly)) yield break;
if (Props.whitelist != null && !Props.whitelist.Contains(selPawn.kindDef)) yield break; if (Props.whitelist != null && !Props.whitelist.Contains(selPawn.kindDef)) yield break;
if (FuelComp == null) yield break; if (FuelComp == null) yield break;
if (!FuelComp.HasFuel || FuelComp.NutritionStored < Props.minNutritionToStart) if (!FuelComp.HasFuel || FuelComp.NutritionStored < Props.minNutritionToStart)
{ {
yield return new FloatMenuOption("CannotStartProduction".Translate() + ": " + "NoFuel".Translate(), null); yield return new FloatMenuOption("CannotStartProduction".Translate() + ": " + "NoFuel".Translate(), null);
yield break; yield break;
} }
// 使用自动生成的 Processes 列表 // 使用自动生成的 Processes 列表
foreach (var process in Processes) foreach (var process in Processes)
{ {
// 获取营养需求 - 直接从 ProcessDef 中读取
float nutritionCost = process.totalNutritionNeeded;
if (process.requiredResearch != null && !process.requiredResearch.IsFinished) if (process.requiredResearch != null && !process.requiredResearch.IsFinished)
{ {
string disabledText = "StartProduction".Translate(process.thingDef.label) + " (" + "Requires".Translate() + ": " + process.requiredResearch.label + ")"; // 修改:在未研究完成的情况下也显示营养需求
string disabledText = "StartProduction".Translate(process.thingDef.label, nutritionCost.ToString("F1")) +
" (" + "Requires".Translate() + ": " + process.requiredResearch.label + ")";
yield return new FloatMenuOption(disabledText, null); yield return new FloatMenuOption(disabledText, null);
} }
else else
{ {
yield return new FloatMenuOption("StartProduction".Translate(process.thingDef.label), () => // 修改:使用新的翻译键显示营养需求
yield return new FloatMenuOption("StartProduction".Translate(process.thingDef.label, nutritionCost.ToString("F1")), () =>
{ {
this._selectedProcess = process; this._selectedProcess = process;
Job job = JobMaker.MakeJob(DefDatabase<JobDef>.GetNamed("ARA_StartInteractiveProduction"), parent); Job job = JobMaker.MakeJob(DefDatabase<JobDef>.GetNamed("ARA_StartInteractiveProduction"), parent);
@@ -296,6 +329,13 @@ namespace ArachnaeSwarm
public void StartProduction() public void StartProduction()
{ {
// 新增:冷却期内不允许开始生产
if (InCooldown)
{
Log.Warning("Attempted to start production during cooldown period.");
return;
}
if (_selectedProcess == null) return; if (_selectedProcess == null) return;
productionUntilTick = Find.TickManager.TicksGame + _selectedProcess.productionTicks; productionUntilTick = Find.TickManager.TicksGame + _selectedProcess.productionTicks;
ticksUnderOptimalConditions = 0; ticksUnderOptimalConditions = 0;
@@ -377,38 +417,173 @@ namespace ArachnaeSwarm
temperaturePenaltyPercent = 0f; temperaturePenaltyPercent = 0f;
} }
// 新增:绘制进度条的方法
private string GetProgressBar(float progress, int barLength = 20)
{
int filledLength = Mathf.RoundToInt(progress * barLength);
int emptyLength = barLength - filledLength;
StringBuilder bar = new StringBuilder();
bar.Append("[");
for (int i = 0; i < filledLength; i++)
{
bar.Append("=");
}
for (int i = 0; i < emptyLength; i++)
{
bar.Append("-");
}
bar.Append("]");
return bar.ToString();
}
// 新增:绘制质量进度条的方法
private string GetQualityProgressBar(float baseScore, float penalty, int barLength = 20)
{
int baseLength = Mathf.RoundToInt(baseScore * barLength);
int penaltyLength = Mathf.RoundToInt(penalty * barLength);
int actualLength = Mathf.Max(0, baseLength - penaltyLength);
int penaltyStart = actualLength;
int emptyLength = barLength - baseLength;
StringBuilder bar = new StringBuilder();
bar.Append("[");
// 实际质量部分(绿色)
for (int i = 0; i < actualLength; i++)
{
bar.Append("=");
}
// 温度惩罚部分(黄色)
for (int i = penaltyStart; i < baseLength; i++)
{
bar.Append("-");
}
// 剩余部分(灰色)
for (int i = baseLength; i < barLength; i++)
{
bar.Append(".");
}
bar.Append("]");
return bar.ToString();
}
public override string CompInspectStringExtra() public override string CompInspectStringExtra()
{ {
// 新增:显示冷却信息
if (InCooldown)
{
int remainingTicks = (spawnTick + COOLDOWN_TICKS) - Find.TickManager.TicksGame;
return "ARA_CocoonCooldown".Translate(remainingTicks.ToStringTicksToPeriod());
}
if (InProduction) if (InProduction)
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.AppendLine("Producing".Translate(this._selectedProcess.thingDef.label)); sb.AppendLine("Producing".Translate(this._selectedProcess.thingDef.label));
// 生产进度条
float progress = ProductionProgress;
int remainingTicks = productionUntilTick - Find.TickManager.TicksGame; int remainingTicks = productionUntilTick - Find.TickManager.TicksGame;
sb.AppendLine("Progress".Translate() + ": " + GetProgressBar(progress) + " " + progress.ToStringPercent("F0"));
sb.AppendLine("TimeLeft".Translate() + ": " + remainingTicks.ToStringTicksToPeriod()); sb.AppendLine("TimeLeft".Translate() + ": " + remainingTicks.ToStringTicksToPeriod());
// 质量进度条
var qualityDetails = GetEstimatedQualityDetails(); var qualityDetails = GetEstimatedQualityDetails();
sb.AppendLine("EstimatedQuality".Translate() + ": " + qualityDetails.quality.GetLabel()); sb.AppendLine("EstimatedQuality".Translate() + ": " + qualityDetails.quality.GetLabel());
sb.AppendLine($" {"QualityScore".Translate()}: {qualityDetails.baseScore.ToStringPercent("F0")}"); sb.AppendLine("QualityProgress".Translate() + ": " +
sb.AppendLine($" {"TemperaturePenalty".Translate()}: -{qualityDetails.penalty.ToStringPercent("F0")}"); GetQualityProgressBar(qualityDetails.baseScore, qualityDetails.penalty) + " " +
(qualityDetails.baseScore - qualityDetails.penalty).ToStringPercent("F0"));
// 温度信息
string tempStr = "CurrentTemperature".Translate(parent.AmbientTemperature.ToStringTemperature("F0")); string tempStr = "CurrentTemperature".Translate(parent.AmbientTemperature.ToStringTemperature("F0"));
tempStr += $" ({"SafeTemperatureRange".Translate()}: {Props.minSafeTemperature.ToStringTemperature("F0")} ~ {Props.maxSafeTemperature.ToStringTemperature("F0")})"; tempStr += $" ({"SafeTemperatureRange".Translate()}: {Props.minSafeTemperature.ToStringTemperature("F0")} ~ {Props.maxSafeTemperature.ToStringTemperature("F0")})";
sb.AppendLine(tempStr); sb.AppendLine(tempStr);
return sb.ToString().TrimEnd(); return sb.ToString().TrimEnd();
} }
if (!InProduction) if (!InProduction)
{ {
// 显示可生产的物品数量 // 显示可生产的物品数量
int availableProcesses = Processes.Count(p => p.requiredResearch == null || p.requiredResearch.IsFinished); int availableProcesses = Processes.Count(p => p.requiredResearch == null || p.requiredResearch.IsFinished);
return "ARA_NeedArachnaeToStartIncubation".Translate() + $" ({availableProcesses} items available)";
// 构建可交互的种族名称列表
string allowedRaces = "";
if (Props.whitelist != null && Props.whitelist.Count > 0)
{
// 获取所有可交互种族的显示名称
var raceNames = Props.whitelist.Select(pkd => pkd.LabelCap).Distinct();
allowedRaces = string.Join(", ", raceNames);
}
else
{
allowedRaces = "ARA_AnyArachnaeRace".Translate(); // 如果没有白名单,显示"任何阿拉克涅虫族"
}
// 使用新的翻译键,包含种族信息和物品数量
return "ARA_NeedSpecificArachnaeToStartIncubation".Translate(allowedRaces, availableProcesses);
} }
return null; return null;
} }
// 新增:在物体上方绘制进度条
public override void PostDraw()
{
base.PostDraw();
if (InProduction)
{
// 在物体上方绘制生产进度条
Vector3 drawPos = parent.DrawPos;
drawPos.y += 0.15f; // 稍微抬高一点
float progress = ProductionProgress;
GenDraw.DrawFillableBar(new GenDraw.FillableBarRequest
{
center = drawPos,
size = new Vector2(1f, 0.15f),
fillPercent = progress,
filledMat = SolidColorMaterials.SimpleSolidColorMaterial(Color.green),
unfilledMat = SolidColorMaterials.SimpleSolidColorMaterial(Color.gray),
margin = 0.1f,
rotation = Rot4.North
});
// 在进度条上方绘制质量进度条
if (Props.qualityThresholds != null && Props.qualityThresholds.Count > 0)
{
var qualityDetails = GetEstimatedQualityDetails();
float qualityProgress = Mathf.Clamp01(qualityDetails.baseScore - qualityDetails.penalty);
drawPos.y += 0.2f;
GenDraw.DrawFillableBar(new GenDraw.FillableBarRequest
{
center = drawPos,
size = new Vector2(1f, 0.1f),
fillPercent = qualityProgress,
filledMat = SolidColorMaterials.SimpleSolidColorMaterial(Color.blue),
unfilledMat = SolidColorMaterials.SimpleSolidColorMaterial(Color.gray),
margin = 0.1f,
rotation = Rot4.North
});
}
}
}
public override IEnumerable<Gizmo> CompGetGizmosExtra() public override IEnumerable<Gizmo> CompGetGizmosExtra()
{ {
foreach (var g in base.CompGetGizmosExtra()) yield return g; foreach (var g in base.CompGetGizmosExtra()) yield return g;
// 新增冷却期内不显示任何Gizmo
if (InCooldown) yield break;
if (InProduction) if (InProduction)
{ {
yield return new Command_Action yield return new Command_Action
@@ -426,6 +601,19 @@ namespace ArachnaeSwarm
defaultLabel = "Debug: Force Finish", defaultLabel = "Debug: Force Finish",
action = () => FinishProduction() action = () => FinishProduction()
}; };
// 调试命令:显示详细进度信息
yield return new Command_Action
{
defaultLabel = "Debug: Show Progress Info",
action = () =>
{
float progress = ProductionProgress;
var qualityDetails = GetEstimatedQualityDetails();
Messages.Message($"Progress: {progress:P0}\nBase Score: {qualityDetails.baseScore:P0}\nPenalty: {qualityDetails.penalty:P0}\nFinal: {qualityDetails.quality}",
MessageTypeDefOf.SilentInput);
}
};
} }
} }
} }

View File

@@ -350,6 +350,10 @@ namespace ArachnaeSwarm.MoharHediffs
public bool TryDoSpawn() public bool TryDoSpawn()
{ {
Pawn pawn = this.parent.pawn; Pawn pawn = this.parent.pawn;
if (this.Props.animalThing)
{
// 动物生成逻辑保持不变
if (this.Props.spawnMaxAdjacent > 0 && pawn.Map.mapPawns.AllPawns.Where(delegate(Pawn mP) if (this.Props.spawnMaxAdjacent > 0 && pawn.Map.mapPawns.AllPawns.Where(delegate(Pawn mP)
{ {
ThingDef defToCompare = this.Props.animalThing ? this.Props.animalToSpawn?.race : this.Props.thingToSpawn; ThingDef defToCompare = this.Props.animalThing ? this.Props.animalToSpawn?.race : this.Props.thingToSpawn;
@@ -362,12 +366,12 @@ namespace ArachnaeSwarm.MoharHediffs
{ {
return false; return false;
} }
if (this.Props.animalThing)
{
if (this.Props.animalToSpawn == null) if (this.Props.animalToSpawn == null)
{ {
return false; return false;
} }
Faction faction = this.Props.factionOfPlayerAnimal ? Faction.OfPlayer : null; Faction faction = this.Props.factionOfPlayerAnimal ? Faction.OfPlayer : null;
int i = 0; int i = 0;
while (i < this.calculatedQuantity) while (i < this.calculatedQuantity)
@@ -401,22 +405,47 @@ namespace ArachnaeSwarm.MoharHediffs
} }
else else
{ {
IntVec3 intVec2; // 修改物品直接添加到pawn的物品栏中
if (!this.TryFindSpawnCell(out intVec2))
{
return false;
}
Thing thing = ThingMaker.MakeThing(this.Props.thingToSpawn, null); Thing thing = ThingMaker.MakeThing(this.Props.thingToSpawn, null);
if (thing == null) if (thing == null)
{ {
return false; return false;
} }
thing.stackCount = this.calculatedQuantity; thing.stackCount = this.calculatedQuantity;
// 检查pawn是否有物品栏
if (pawn.inventory == null)
{
Tools.Warn($"Pawn {pawn.Label} does not have an inventory to receive spawned items", this.myDebug);
return false;
}
// 尝试将物品添加到pawn的物品栏
if (pawn.inventory.innerContainer.TryAdd(thing))
{
if (PawnUtility.ShouldSendNotificationAbout(pawn))
{
Messages.Message(this.Props.spawnVerb.Translate(pawn.Named("PAWN"), thing.Named("THING")), pawn, MessageTypeDefOf.PositiveEvent, true);
}
return true;
}
else
{
// 如果物品栏添加失败,回退到原来的地面生成方式
Tools.Warn($"Failed to add {thing.Label} to {pawn.Label}'s inventory, falling back to ground spawn", this.myDebug);
IntVec3 intVec2;
if (!this.TryFindSpawnCell(out intVec2))
{
return false;
}
if (this.Props.spawnForbidden) if (this.Props.spawnForbidden)
{ {
thing.SetForbidden(true, true); thing.SetForbidden(true, true);
} }
GenPlace.TryPlaceThing(thing, intVec2, pawn.Map, ThingPlaceMode.Direct, null, null, default(Rot4)); GenPlace.TryPlaceThing(thing, intVec2, pawn.Map, ThingPlaceMode.Direct, null, null, default(Rot4));
if (PawnUtility.ShouldSendNotificationAbout(pawn)) if (PawnUtility.ShouldSendNotificationAbout(pawn))
{ {
Messages.Message(this.Props.spawnVerb.Translate(pawn.Named("PAWN"), thing.Named("THING")), thing, MessageTypeDefOf.PositiveEvent, true); Messages.Message(this.Props.spawnVerb.Translate(pawn.Named("PAWN"), thing.Named("THING")), thing, MessageTypeDefOf.PositiveEvent, true);
@@ -424,6 +453,7 @@ namespace ArachnaeSwarm.MoharHediffs
return true; return true;
} }
} }
}
private bool TryFindSpawnCell(out IntVec3 result) private bool TryFindSpawnCell(out IntVec3 result)
{ {
@@ -442,19 +472,19 @@ namespace ArachnaeSwarm.MoharHediffs
} }
else else
{ {
// 修改这里将半径从5减少到2让生成位置更靠近pawn // 修改这里将半径从5减少到2让生成位置更靠近pawn
int searchRadius = 2; int searchRadius = 2;
// 首先尝试在pawn的相邻单元格生成半径为1 // 首先尝试在pawn的相邻单元格生成半径为1
result = CellFinder.RandomClosewalkCellNear(this.pawn.Position, map, 1, null); result = CellFinder.RandomClosewalkCellNear(this.pawn.Position, map, 1, null);
// 如果相邻单元格找不到合适位置再尝试稍远一点半径为2 // 如果相邻单元格找不到合适位置再尝试稍远一点半径为2
if (!result.IsValid) if (!result.IsValid)
{ {
result = CellFinder.RandomClosewalkCellNear(this.pawn.Position, map, searchRadius, null); result = CellFinder.RandomClosewalkCellNear(this.pawn.Position, map, searchRadius, null);
} }
// 如果还是找不到尝试pawn当前位置作为最后手段 // 如果还是找不到尝试pawn当前位置作为最后手段
if (!result.IsValid && this.pawn.Position.IsValid && this.pawn.Position.Walkable(map)) if (!result.IsValid && this.pawn.Position.IsValid && this.pawn.Position.Walkable(map))
{ {
result = this.pawn.Position; result = this.pawn.Position;