11
This commit is contained in:
Binary file not shown.
@@ -3,13 +3,41 @@
|
||||
"WorkspaceRootPath": "E:\\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\\building_comps\\compnutritiontofuelconverter.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:building_comps\\compnutritiontofuelconverter.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\\powerarmor\\ara_powerarmor.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:powerarmor\\ara_powerarmor.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\\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\\powerarmor\\jobdriver_enterpowerarmor.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:powerarmor\\jobdriver_enterpowerarmor.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\\powerarmor\\comppowerarmorstation.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:powerarmor\\comppowerarmorstation.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\\powerarmor\\gizmo_structurepanel.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:powerarmor\\gizmo_structurepanel.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\\abilities\\ara_huggingface\\compabilityeffect_possess.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:abilities\\ara_huggingface\\compabilityeffect_possess.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\\building_comps\\ara_nutrientvat\\building_nutrientvat.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:building_comps\\ara_nutrientvat\\building_nutrientvat.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\\building_comps\\ara_building_refuelingvat\\building_refuelingvat.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:building_comps\\ara_building_refuelingvat\\building_refuelingvat.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\\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\\building_comps\\compnutritiontofuelconverter.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:building_comps\\compnutritiontofuelconverter.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\\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}"
|
||||
@@ -22,28 +50,114 @@
|
||||
"DocumentGroups": [
|
||||
{
|
||||
"DockedWidth": 200,
|
||||
"SelectedChildIndex": 1,
|
||||
"SelectedChildIndex": 4,
|
||||
"Children": [
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:0:0:{1c4feeaa-4718-4aa9-859d-94ce25d182ba}"
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 2,
|
||||
"Title": "CompPowerArmorStation.cs",
|
||||
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\PowerArmor\\CompPowerArmorStation.cs",
|
||||
"RelativeDocumentMoniker": "PowerArmor\\CompPowerArmorStation.cs",
|
||||
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\PowerArmor\\CompPowerArmorStation.cs",
|
||||
"RelativeToolTip": "PowerArmor\\CompPowerArmorStation.cs",
|
||||
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAwAAAAmAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2025-10-18T16:40:43.953Z",
|
||||
"EditorCaption": ""
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 1,
|
||||
"Title": "JobDriver_EnterPowerArmor.cs",
|
||||
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\PowerArmor\\JobDriver_EnterPowerArmor.cs",
|
||||
"RelativeDocumentMoniker": "PowerArmor\\JobDriver_EnterPowerArmor.cs",
|
||||
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\PowerArmor\\JobDriver_EnterPowerArmor.cs",
|
||||
"RelativeToolTip": "PowerArmor\\JobDriver_EnterPowerArmor.cs",
|
||||
"ViewState": "AgIAAGUAAAAAAAAAAAAAAIwAAAAAAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2025-10-18T16:33:18.657Z",
|
||||
"EditorCaption": ""
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 3,
|
||||
"Title": "Gizmo_StructurePanel.cs",
|
||||
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\PowerArmor\\Gizmo_StructurePanel.cs",
|
||||
"RelativeDocumentMoniker": "PowerArmor\\Gizmo_StructurePanel.cs",
|
||||
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\PowerArmor\\Gizmo_StructurePanel.cs",
|
||||
"RelativeToolTip": "PowerArmor\\Gizmo_StructurePanel.cs",
|
||||
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2025-10-18T16:32:53.277Z"
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 0,
|
||||
"Title": "ARA_PowerArmor.cs",
|
||||
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\PowerArmor\\ARA_PowerArmor.cs",
|
||||
"RelativeDocumentMoniker": "PowerArmor\\ARA_PowerArmor.cs",
|
||||
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\PowerArmor\\ARA_PowerArmor.cs",
|
||||
"RelativeToolTip": "PowerArmor\\ARA_PowerArmor.cs",
|
||||
"ViewState": "AgIAAAAAAAAAAAAAAAAAACQAAAAAAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2025-10-18T16:30:55.497Z",
|
||||
"EditorCaption": ""
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 4,
|
||||
"Title": "CompAbilityEffect_Possess.cs",
|
||||
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_HuggingFace\\CompAbilityEffect_Possess.cs",
|
||||
"RelativeDocumentMoniker": "Abilities\\ARA_HuggingFace\\CompAbilityEffect_Possess.cs",
|
||||
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_HuggingFace\\CompAbilityEffect_Possess.cs",
|
||||
"RelativeToolTip": "Abilities\\ARA_HuggingFace\\CompAbilityEffect_Possess.cs",
|
||||
"ViewState": "AgIAACwAAAAAAAAAAAAkwDsAAAAtAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2025-10-18T13:31:46.288Z"
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 5,
|
||||
"Title": "Building_NutrientVat.cs",
|
||||
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\ARA_NutrientVat\\Building_NutrientVat.cs",
|
||||
"RelativeDocumentMoniker": "Building_Comps\\ARA_NutrientVat\\Building_NutrientVat.cs",
|
||||
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\ARA_NutrientVat\\Building_NutrientVat.cs",
|
||||
"RelativeToolTip": "Building_Comps\\ARA_NutrientVat\\Building_NutrientVat.cs",
|
||||
"ViewState": "AgIAAAgAAAAAAAAAAAAQwBAAAAAIAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2025-10-18T11:56:31.022Z"
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 6,
|
||||
"Title": "Building_RefuelingVat.cs",
|
||||
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\ARA_Building_RefuelingVat\\Building_RefuelingVat.cs",
|
||||
"RelativeDocumentMoniker": "Building_Comps\\ARA_Building_RefuelingVat\\Building_RefuelingVat.cs",
|
||||
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\ARA_Building_RefuelingVat\\Building_RefuelingVat.cs",
|
||||
"RelativeToolTip": "Building_Comps\\ARA_Building_RefuelingVat\\Building_RefuelingVat.cs",
|
||||
"ViewState": "AgIAAGcAAAAAAAAAAAAAAI4AAAAgAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2025-10-18T11:56:12.333Z"
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 8,
|
||||
"Title": "CompNutritionToFuelConverter.cs",
|
||||
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\CompNutritionToFuelConverter.cs",
|
||||
"RelativeDocumentMoniker": "Building_Comps\\CompNutritionToFuelConverter.cs",
|
||||
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\CompNutritionToFuelConverter.cs",
|
||||
"RelativeToolTip": "Building_Comps\\CompNutritionToFuelConverter.cs",
|
||||
"ViewState": "AgIAAAAAAAAAAAAAAAAAAKEAAAAcAAAAAAAAAA==",
|
||||
"ViewState": "AgIAAGEAAAAAAAAAAAAQwHYAAAAJAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2025-10-17T11:32:00.484Z",
|
||||
"EditorCaption": ""
|
||||
"WhenOpened": "2025-10-17T11:32:00.484Z"
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 2,
|
||||
"DocumentIndex": 9,
|
||||
"Title": "CompResearchProducer.cs",
|
||||
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\ARA_CompInteractiveProducer\\CompResearchProducer.cs",
|
||||
"RelativeDocumentMoniker": "Building_Comps\\ARA_CompInteractiveProducer\\CompResearchProducer.cs",
|
||||
@@ -55,16 +169,15 @@
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 1,
|
||||
"DocumentIndex": 7,
|
||||
"Title": "CompInteractiveProducer.cs",
|
||||
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\ARA_CompInteractiveProducer\\CompInteractiveProducer.cs",
|
||||
"RelativeDocumentMoniker": "Building_Comps\\ARA_CompInteractiveProducer\\CompInteractiveProducer.cs",
|
||||
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\ARA_CompInteractiveProducer\\CompInteractiveProducer.cs",
|
||||
"RelativeToolTip": "Building_Comps\\ARA_CompInteractiveProducer\\CompInteractiveProducer.cs",
|
||||
"ViewState": "AgIAAJYBAAAAAAAAAAAUwKoBAAAAAAAAAAAAAA==",
|
||||
"ViewState": "AgIAAAwAAAAAAAAAAAAgwGYAAABWAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2025-10-17T09:00:51.526Z",
|
||||
"EditorCaption": ""
|
||||
"WhenOpened": "2025-10-17T09:00:51.526Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -40,9 +40,77 @@ namespace ArachnaeSwarm
|
||||
public override void Apply(LocalTargetInfo target, LocalTargetInfo dest)
|
||||
{
|
||||
base.Apply(target, dest);
|
||||
DoPossession(this.parent.pawn, target.Pawn);
|
||||
|
||||
// 新增:检查目标是否无法行动(倒地)
|
||||
if (target.Pawn != null && IsTargetImmobilized(target.Pawn))
|
||||
{
|
||||
Log.Message($"[夺舍] 目标 {target.Pawn.LabelShort} 无法行动,直接执行夺舍");
|
||||
DoPossession(this.parent.pawn, target.Pawn);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Message($"[夺舍] 目标可以行动,执行标准夺舍流程");
|
||||
DoPossession(this.parent.pawn, target.Pawn);
|
||||
}
|
||||
}
|
||||
|
||||
// 新增:检查目标是否无法行动
|
||||
private bool IsTargetImmobilized(Pawn target)
|
||||
{
|
||||
if (target == null) return false;
|
||||
|
||||
// 检查是否倒地
|
||||
if (target.Downed)
|
||||
{
|
||||
Log.Message($"[夺舍] 目标 {target.LabelShort} 处于倒地状态");
|
||||
return true;
|
||||
}
|
||||
|
||||
// 检查是否无法移动
|
||||
if (!target.health.capacities.CapableOf(PawnCapacityDefOf.Moving))
|
||||
{
|
||||
Log.Message($"[夺舍] 目标 {target.LabelShort} 无法移动");
|
||||
return true;
|
||||
}
|
||||
|
||||
// 检查是否有严重的移动障碍
|
||||
if (target.health.hediffSet.HasHediff(HediffDefOf.Anesthetic) ||
|
||||
target.health.hediffSet.HasHediff(HediffDefOf.CryptosleepSickness) ||
|
||||
target.health.hediffSet.HasHediff(HediffDefOf.FoodPoisoning))
|
||||
{
|
||||
Log.Message($"[夺舍] 目标 {target.LabelShort} 有严重的移动障碍");
|
||||
return true;
|
||||
}
|
||||
|
||||
// 检查是否被束缚或囚禁
|
||||
if (target.IsPrisoner || target.HostFaction != null)
|
||||
{
|
||||
Log.Message($"[夺舍] 目标 {target.LabelShort} 被囚禁或束缚");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// 新增:计算寄生成功率
|
||||
private float CalculateSuccessChance(Pawn targetPawn, float damageDealt = 0f)
|
||||
{
|
||||
// 如果目标无法行动,100%成功率
|
||||
if (IsTargetImmobilized(targetPawn))
|
||||
{
|
||||
Log.Message($"[夺舍] 目标 {targetPawn.LabelShort} 无法行动,寄生成功率: 100%");
|
||||
return 1f;
|
||||
}
|
||||
|
||||
// 正常计算成功率
|
||||
float baseChance = Props.successChance.RandomInRange;
|
||||
float bonusFromDamage = damageDealt * Props.successChanceBonusPerDamage;
|
||||
float finalChance = Mathf.Clamp01(baseChance + bonusFromDamage);
|
||||
|
||||
Log.Message($"[夺舍] 目标 {targetPawn.LabelShort} 可以行动,寄生成功率: {finalChance:P0} (基础: {baseChance:P0}, 伤害加成: {bonusFromDamage:P0})");
|
||||
return finalChance;
|
||||
}
|
||||
|
||||
private void DoPossession(Pawn caster, Pawn targetPawn)
|
||||
{
|
||||
if (targetPawn == null || caster == null) return;
|
||||
@@ -146,10 +214,10 @@ namespace ArachnaeSwarm
|
||||
|
||||
if (damageResult.totalDamageDealt > 0)
|
||||
{
|
||||
float baseChance = Props.successChance.RandomInRange;
|
||||
float bonusFromDamage = damageResult.totalDamageDealt * Props.successChanceBonusPerDamage;
|
||||
float finalChance = Mathf.Clamp01(baseChance + bonusFromDamage);
|
||||
Log.Message($"[Possess] Base chance: {baseChance}, Bonus: {bonusFromDamage}, Final chance: {finalChance}");
|
||||
// 修改:使用新的成功率计算方法
|
||||
float finalChance = CalculateSuccessChance(targetPawn, damageResult.totalDamageDealt);
|
||||
|
||||
Log.Message($"[Possess] Final chance: {finalChance:P0}");
|
||||
|
||||
if (Rand.Chance(finalChance))
|
||||
{
|
||||
@@ -163,4 +231,4 @@ namespace ArachnaeSwarm
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ namespace ArachnaeSwarm
|
||||
|
||||
DamageInfo acidDamage = new DamageInfo(
|
||||
acidDamageDef,
|
||||
0.1f, // 每次0.1点伤害
|
||||
1.5f, // 每次1.5点伤害
|
||||
2f, // 护甲穿透
|
||||
-1f, // 随机角度
|
||||
instigator: null,
|
||||
|
||||
@@ -38,6 +38,11 @@ namespace ArachnaeSwarm
|
||||
private int spawnTick = -1; // 新增:记录生成时间
|
||||
private const int COOLDOWN_TICKS = 120; // 新增:120 tick冷却时间
|
||||
|
||||
// 新增:修复负时间相关字段
|
||||
private int lastNegativeTimeCheckTick = -1;
|
||||
private const int NEGATIVE_TIME_CHECK_INTERVAL = 60; // 每60ticks检查一次
|
||||
private bool hasFixedNegativeTime = false; // 标记是否已经修复过负时间问题
|
||||
|
||||
private CompRefuelableNutrition _fuelComp;
|
||||
private static readonly Texture2D CancelIcon = ContentFinder<Texture2D>.Get("UI/Designators/Cancel");
|
||||
|
||||
@@ -79,6 +84,83 @@ namespace ArachnaeSwarm
|
||||
}
|
||||
}
|
||||
|
||||
// 新增:获取剩余生产时间(ticks)
|
||||
public int RemainingProductionTicks
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!InProduction || productionUntilTick <= 0) return 0;
|
||||
return Mathf.Max(0, productionUntilTick - Find.TickManager.TicksGame);
|
||||
}
|
||||
}
|
||||
|
||||
// 新增:检查是否存在负时间问题
|
||||
private bool HasNegativeTimeProblem
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!InProduction || productionUntilTick <= 0) return false;
|
||||
int remainingTicks = productionUntilTick - Find.TickManager.TicksGame;
|
||||
return remainingTicks < -10; // 小于-10ticks认为有问题
|
||||
}
|
||||
}
|
||||
|
||||
// 新增:修复负时间问题
|
||||
private void FixNegativeTimeProblem()
|
||||
{
|
||||
if (!InProduction || _selectedProcess == null)
|
||||
{
|
||||
Log.Warning($"Attempted to fix negative time but no process is selected. Resetting production.");
|
||||
ResetProduction();
|
||||
return;
|
||||
}
|
||||
|
||||
int currentTicks = Find.TickManager.TicksGame;
|
||||
int remainingTicks = productionUntilTick - currentTicks;
|
||||
|
||||
Log.Warning($"Detected negative production time for {parent.Label}. " +
|
||||
$"Current: {currentTicks}, Target: {productionUntilTick}, Remaining: {remainingTicks}. " +
|
||||
$"Process: {_selectedProcess.thingDef?.defName ?? "Unknown"}, Expected Duration: {_selectedProcess.productionTicks}");
|
||||
|
||||
// 计算应该设置的正确结束时间
|
||||
int correctEndTick = currentTicks + _selectedProcess.productionTicks;
|
||||
|
||||
// 如果偏差太大,直接完成生产
|
||||
if (remainingTicks < -_selectedProcess.productionTicks)
|
||||
{
|
||||
Log.Warning($"Negative time too large ({remainingTicks} ticks). Forcing production completion.");
|
||||
FinishProduction();
|
||||
return;
|
||||
}
|
||||
|
||||
// 否则重置为正确的剩余时间
|
||||
productionUntilTick = correctEndTick;
|
||||
hasFixedNegativeTime = true;
|
||||
|
||||
Log.Message($"Fixed negative production time for {parent.Label}. " +
|
||||
$"New target: {productionUntilTick}, New remaining: {_selectedProcess.productionTicks} ticks");
|
||||
|
||||
// 发送消息通知(开发模式)
|
||||
if (Prefs.DevMode)
|
||||
{
|
||||
Messages.Message($"Fixed negative production time for {parent.Label}. Remaining: {_selectedProcess.productionTicks.ToStringTicksToPeriod()}",
|
||||
MessageTypeDefOf.SilentInput);
|
||||
}
|
||||
}
|
||||
|
||||
// 新增:定期检查负时间问题
|
||||
private void CheckForNegativeTime()
|
||||
{
|
||||
if (Find.TickManager.TicksGame > lastNegativeTimeCheckTick + NEGATIVE_TIME_CHECK_INTERVAL)
|
||||
{
|
||||
if (HasNegativeTimeProblem && !hasFixedNegativeTime)
|
||||
{
|
||||
FixNegativeTimeProblem();
|
||||
}
|
||||
lastNegativeTimeCheckTick = Find.TickManager.TicksGame;
|
||||
}
|
||||
}
|
||||
|
||||
public override void PostSpawnSetup(bool respawningAfterLoad)
|
||||
{
|
||||
base.PostSpawnSetup(respawningAfterLoad);
|
||||
@@ -90,6 +172,17 @@ namespace ArachnaeSwarm
|
||||
{
|
||||
spawnTick = Find.TickManager.TicksGame;
|
||||
}
|
||||
|
||||
// 新增:初始化负时间检查
|
||||
lastNegativeTimeCheckTick = Find.TickManager.TicksGame;
|
||||
hasFixedNegativeTime = false;
|
||||
|
||||
// 新增:立即检查一次负时间问题
|
||||
if (InProduction && HasNegativeTimeProblem)
|
||||
{
|
||||
Log.Warning($"Detected negative production time on spawn for {parent.Label}");
|
||||
FixNegativeTimeProblem();
|
||||
}
|
||||
}
|
||||
|
||||
public override void PostExposeData()
|
||||
@@ -104,6 +197,8 @@ namespace ArachnaeSwarm
|
||||
Scribe_Values.Look(ref ticksUnderOptimalConditions, "ticksUnderOptimalConditions", 0);
|
||||
Scribe_Values.Look(ref temperaturePenaltyPercent, "temperaturePenaltyPercent", 0f);
|
||||
Scribe_Values.Look(ref spawnTick, "spawnTick", -1); // 新增:序列化生成时间
|
||||
Scribe_Values.Look(ref lastNegativeTimeCheckTick, "lastNegativeTimeCheckTick", -1);
|
||||
Scribe_Values.Look(ref hasFixedNegativeTime, "hasFixedNegativeTime", false);
|
||||
|
||||
// 加载时重建 selectedProcess
|
||||
if (Scribe.mode == LoadSaveMode.LoadingVars && selectedProcessThingDef != null)
|
||||
@@ -138,6 +233,12 @@ namespace ArachnaeSwarm
|
||||
Log.Warning($"Abnormal production time detected for {selectedProcessThingDef.defName}. Recalculating.");
|
||||
productionUntilTick = Find.TickManager.TicksGame + _selectedProcess.productionTicks;
|
||||
}
|
||||
// 新增:检查负时间问题
|
||||
else if (HasNegativeTimeProblem)
|
||||
{
|
||||
Log.Warning($"Negative production time detected on load for {selectedProcessThingDef.defName}. Fixing.");
|
||||
FixNegativeTimeProblem();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -241,6 +342,10 @@ namespace ArachnaeSwarm
|
||||
public override void CompTick()
|
||||
{
|
||||
base.CompTick();
|
||||
|
||||
// 新增:定期检查负时间问题
|
||||
CheckForNegativeTime();
|
||||
|
||||
if (InProduction && productionUntilTick > 0)
|
||||
{
|
||||
// 关键修复:添加时间戳有效性检查
|
||||
@@ -251,6 +356,13 @@ namespace ArachnaeSwarm
|
||||
return;
|
||||
}
|
||||
|
||||
// 新增:再次检查负时间问题(在每次tick时)
|
||||
if (HasNegativeTimeProblem && !hasFixedNegativeTime)
|
||||
{
|
||||
FixNegativeTimeProblem();
|
||||
return; // 修复后跳过本次tick的逻辑
|
||||
}
|
||||
|
||||
if (FuelComp == null) return;
|
||||
|
||||
bool hasFuel = FuelComp.HasFuel;
|
||||
@@ -341,6 +453,9 @@ namespace ArachnaeSwarm
|
||||
temperaturePenaltyPercent = 0f;
|
||||
float nutritionPerDay = (_selectedProcess.totalNutritionNeeded / _selectedProcess.productionTicks) * 60000f;
|
||||
FuelComp.currentConsumptionRate = nutritionPerDay;
|
||||
|
||||
// 新增:重置负时间修复标记
|
||||
hasFixedNegativeTime = false;
|
||||
}
|
||||
|
||||
public (QualityCategory quality, float baseScore, float penalty) GetEstimatedQualityDetails()
|
||||
@@ -495,6 +610,7 @@ namespace ArachnaeSwarm
|
||||
productionUntilTick = -1;
|
||||
ticksUnderOptimalConditions = 0;
|
||||
temperaturePenaltyPercent = 0f;
|
||||
hasFixedNegativeTime = false; // 新增:重置修复标记
|
||||
}
|
||||
|
||||
// 新增:绘制进度条的方法
|
||||
@@ -570,6 +686,13 @@ namespace ArachnaeSwarm
|
||||
// 生产进度条
|
||||
float progress = ProductionProgress;
|
||||
int remainingTicks = productionUntilTick - Find.TickManager.TicksGame;
|
||||
|
||||
// 新增:显示负时间警告
|
||||
if (remainingTicks < -10)
|
||||
{
|
||||
sb.AppendLine("<color=red>WARNING: Negative production time detected! Auto-fixing...</color>");
|
||||
}
|
||||
|
||||
sb.AppendLine("Progress".Translate() + ": " + GetProgressBar(progress) + " " + progress.ToStringPercent("F0"));
|
||||
sb.AppendLine("TimeLeft".Translate() + ": " + remainingTicks.ToStringTicksToPeriod());
|
||||
|
||||
@@ -624,12 +747,16 @@ namespace ArachnaeSwarm
|
||||
drawPos.y += 0.15f; // 稍微抬高一点
|
||||
|
||||
float progress = ProductionProgress;
|
||||
|
||||
// 新增:负时间警告颜色(红色)
|
||||
Color barColor = HasNegativeTimeProblem ? Color.red : Color.green;
|
||||
|
||||
GenDraw.DrawFillableBar(new GenDraw.FillableBarRequest
|
||||
{
|
||||
center = drawPos,
|
||||
size = new Vector2(1f, 0.15f),
|
||||
fillPercent = progress,
|
||||
filledMat = SolidColorMaterials.SimpleSolidColorMaterial(Color.green),
|
||||
filledMat = SolidColorMaterials.SimpleSolidColorMaterial(barColor),
|
||||
unfilledMat = SolidColorMaterials.SimpleSolidColorMaterial(Color.gray),
|
||||
margin = 0.1f,
|
||||
rotation = Rot4.North
|
||||
@@ -690,8 +817,53 @@ namespace ArachnaeSwarm
|
||||
{
|
||||
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);
|
||||
int remainingTicks = productionUntilTick - Find.TickManager.TicksGame;
|
||||
|
||||
string message = $"Progress: {progress:P0}\n" +
|
||||
$"Base Score: {qualityDetails.baseScore:P0}\n" +
|
||||
$"Penalty: {qualityDetails.penalty:P0}\n" +
|
||||
$"Final: {qualityDetails.quality}\n" +
|
||||
$"Remaining Ticks: {remainingTicks}\n" +
|
||||
$"Has Negative Time: {HasNegativeTimeProblem}\n" +
|
||||
$"Fixed Before: {hasFixedNegativeTime}";
|
||||
Messages.Message(message, MessageTypeDefOf.SilentInput);
|
||||
}
|
||||
};
|
||||
|
||||
// 新增:调试命令手动触发负时间修复
|
||||
yield return new Command_Action
|
||||
{
|
||||
defaultLabel = "Debug: Fix Negative Time",
|
||||
action = () =>
|
||||
{
|
||||
if (HasNegativeTimeProblem)
|
||||
{
|
||||
FixNegativeTimeProblem();
|
||||
Messages.Message("Manually triggered negative time fix", MessageTypeDefOf.SilentInput);
|
||||
}
|
||||
else
|
||||
{
|
||||
Messages.Message("No negative time problem detected", MessageTypeDefOf.SilentInput);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 新增:调试命令模拟负时间问题
|
||||
yield return new Command_Action
|
||||
{
|
||||
defaultLabel = "Debug: Simulate Negative Time",
|
||||
action = () =>
|
||||
{
|
||||
if (InProduction)
|
||||
{
|
||||
productionUntilTick = Find.TickManager.TicksGame - 1000; // 设置为1000ticks前
|
||||
hasFixedNegativeTime = false;
|
||||
Messages.Message("Simulated negative time problem (-1000 ticks)", MessageTypeDefOf.SilentInput);
|
||||
}
|
||||
else
|
||||
{
|
||||
Messages.Message("Not in production", MessageTypeDefOf.SilentInput);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -36,6 +36,11 @@ namespace ArachnaeSwarm
|
||||
private int spawnTick = -1;
|
||||
private const int COOLDOWN_TICKS = 120;
|
||||
|
||||
// 新增:修复负时间相关字段
|
||||
private int lastNegativeTimeCheckTick = -1;
|
||||
private const int NEGATIVE_TIME_CHECK_INTERVAL = 60; // 每60ticks检查一次
|
||||
private bool hasFixedNegativeTime = false; // 标记是否已经修复过负时间问题
|
||||
|
||||
private CompRefuelableNutrition _fuelComp;
|
||||
private static readonly Texture2D CancelIcon = ContentFinder<Texture2D>.Get("UI/Designators/Cancel");
|
||||
|
||||
@@ -77,6 +82,83 @@ namespace ArachnaeSwarm
|
||||
}
|
||||
}
|
||||
|
||||
// 新增:获取剩余生产时间(ticks)
|
||||
public int RemainingProductionTicks
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!InProduction || productionUntilTick <= 0) return 0;
|
||||
return Mathf.Max(0, productionUntilTick - Find.TickManager.TicksGame);
|
||||
}
|
||||
}
|
||||
|
||||
// 新增:检查是否存在负时间问题
|
||||
private bool HasNegativeTimeProblem
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!InProduction || productionUntilTick <= 0) return false;
|
||||
int remainingTicks = productionUntilTick - Find.TickManager.TicksGame;
|
||||
return remainingTicks < -10; // 小于-10ticks认为有问题
|
||||
}
|
||||
}
|
||||
|
||||
// 新增:修复负时间问题
|
||||
private void FixNegativeTimeProblem()
|
||||
{
|
||||
if (!InProduction || _selectedProcess == null)
|
||||
{
|
||||
Log.Warning($"Attempted to fix negative time but no process is selected. Resetting production.");
|
||||
ResetProduction();
|
||||
return;
|
||||
}
|
||||
|
||||
int currentTicks = Find.TickManager.TicksGame;
|
||||
int remainingTicks = productionUntilTick - currentTicks;
|
||||
|
||||
Log.Warning($"Detected negative research production time for {parent.Label}. " +
|
||||
$"Current: {currentTicks}, Target: {productionUntilTick}, Remaining: {remainingTicks}. " +
|
||||
$"Research: {_selectedProcess.researchDef?.defName ?? "Unknown"}, Expected Duration: {_selectedProcess.productionTicks}");
|
||||
|
||||
// 计算应该设置的正确结束时间
|
||||
int correctEndTick = currentTicks + _selectedProcess.productionTicks;
|
||||
|
||||
// 如果偏差太大,直接完成生产
|
||||
if (remainingTicks < -_selectedProcess.productionTicks)
|
||||
{
|
||||
Log.Warning($"Negative time too large ({remainingTicks} ticks). Forcing production completion.");
|
||||
FinishProduction();
|
||||
return;
|
||||
}
|
||||
|
||||
// 否则重置为正确的剩余时间
|
||||
productionUntilTick = correctEndTick;
|
||||
hasFixedNegativeTime = true;
|
||||
|
||||
Log.Message($"Fixed negative research production time for {parent.Label}. " +
|
||||
$"New target: {productionUntilTick}, New remaining: {_selectedProcess.productionTicks} ticks");
|
||||
|
||||
// 发送消息通知(开发模式)
|
||||
if (Prefs.DevMode)
|
||||
{
|
||||
Messages.Message($"Fixed negative research production time for {parent.Label}. Remaining: {_selectedProcess.productionTicks.ToStringTicksToPeriod()}",
|
||||
MessageTypeDefOf.SilentInput);
|
||||
}
|
||||
}
|
||||
|
||||
// 新增:定期检查负时间问题
|
||||
private void CheckForNegativeTime()
|
||||
{
|
||||
if (Find.TickManager.TicksGame > lastNegativeTimeCheckTick + NEGATIVE_TIME_CHECK_INTERVAL)
|
||||
{
|
||||
if (HasNegativeTimeProblem && !hasFixedNegativeTime)
|
||||
{
|
||||
FixNegativeTimeProblem();
|
||||
}
|
||||
lastNegativeTimeCheckTick = Find.TickManager.TicksGame;
|
||||
}
|
||||
}
|
||||
|
||||
public override void PostSpawnSetup(bool respawningAfterLoad)
|
||||
{
|
||||
base.PostSpawnSetup(respawningAfterLoad);
|
||||
@@ -87,6 +169,17 @@ namespace ArachnaeSwarm
|
||||
{
|
||||
spawnTick = Find.TickManager.TicksGame;
|
||||
}
|
||||
|
||||
// 新增:初始化负时间检查
|
||||
lastNegativeTimeCheckTick = Find.TickManager.TicksGame;
|
||||
hasFixedNegativeTime = false;
|
||||
|
||||
// 新增:立即检查一次负时间问题
|
||||
if (InProduction && HasNegativeTimeProblem)
|
||||
{
|
||||
Log.Warning($"Detected negative research production time on spawn for {parent.Label}");
|
||||
FixNegativeTimeProblem();
|
||||
}
|
||||
}
|
||||
|
||||
public override void PostExposeData()
|
||||
@@ -99,6 +192,8 @@ namespace ArachnaeSwarm
|
||||
|
||||
Scribe_Values.Look(ref productionUntilTick, "productionUntilTick", -1);
|
||||
Scribe_Values.Look(ref spawnTick, "spawnTick", -1);
|
||||
Scribe_Values.Look(ref lastNegativeTimeCheckTick, "lastNegativeTimeCheckTick", -1);
|
||||
Scribe_Values.Look(ref hasFixedNegativeTime, "hasFixedNegativeTime", false);
|
||||
|
||||
// 加载时重建 selectedProcess
|
||||
if (Scribe.mode == LoadSaveMode.LoadingVars && selectedProcessResearchDef != null)
|
||||
@@ -127,6 +222,12 @@ namespace ArachnaeSwarm
|
||||
Log.Warning($"Abnormal production time detected for {selectedProcessResearchDef.defName}. Recalculating.");
|
||||
productionUntilTick = Find.TickManager.TicksGame + _selectedProcess.productionTicks;
|
||||
}
|
||||
// 新增:检查负时间问题
|
||||
else if (HasNegativeTimeProblem)
|
||||
{
|
||||
Log.Warning($"Negative production time detected on load for {selectedProcessResearchDef.defName}. Fixing.");
|
||||
FixNegativeTimeProblem();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -231,6 +332,9 @@ namespace ArachnaeSwarm
|
||||
{
|
||||
base.CompTick();
|
||||
|
||||
// 新增:定期检查负时间问题
|
||||
CheckForNegativeTime();
|
||||
|
||||
if (InProduction && productionUntilTick > 0)
|
||||
{
|
||||
if (productionUntilTick <= 0)
|
||||
@@ -240,6 +344,13 @@ namespace ArachnaeSwarm
|
||||
return;
|
||||
}
|
||||
|
||||
// 新增:再次检查负时间问题(在每次tick时)
|
||||
if (HasNegativeTimeProblem && !hasFixedNegativeTime)
|
||||
{
|
||||
FixNegativeTimeProblem();
|
||||
return; // 修复后跳过本次tick的逻辑
|
||||
}
|
||||
|
||||
if (FuelComp == null) return;
|
||||
|
||||
bool hasFuel = FuelComp.HasFuel;
|
||||
@@ -315,6 +426,9 @@ namespace ArachnaeSwarm
|
||||
|
||||
float nutritionPerDay = (_selectedProcess.totalNutritionNeeded / _selectedProcess.productionTicks) * 60000f;
|
||||
FuelComp.currentConsumptionRate = nutritionPerDay;
|
||||
|
||||
// 新增:重置负时间修复标记
|
||||
hasFixedNegativeTime = false;
|
||||
}
|
||||
|
||||
private void FinishProduction()
|
||||
@@ -417,6 +531,7 @@ namespace ArachnaeSwarm
|
||||
if (FuelComp != null) FuelComp.currentConsumptionRate = 0f;
|
||||
_selectedProcess = null;
|
||||
productionUntilTick = -1;
|
||||
hasFixedNegativeTime = false; // 新增:重置修复标记
|
||||
}
|
||||
|
||||
// 进度条显示
|
||||
@@ -449,6 +564,13 @@ namespace ArachnaeSwarm
|
||||
|
||||
float progress = ProductionProgress;
|
||||
int remainingTicks = productionUntilTick - Find.TickManager.TicksGame;
|
||||
|
||||
// 新增:显示负时间警告
|
||||
if (remainingTicks < -10)
|
||||
{
|
||||
sb.AppendLine("<color=red>WARNING: Negative production time detected! Auto-fixing...</color>");
|
||||
}
|
||||
|
||||
sb.AppendLine("Progress".Translate() + ": " + GetProgressBar(progress) + " " + progress.ToStringPercent("F0"));
|
||||
sb.AppendLine("TimeLeft".Translate() + ": " + remainingTicks.ToStringTicksToPeriod());
|
||||
sb.AppendLine("TechprintsToProduce".Translate() + ": " + _selectedProcess.techprintCount);
|
||||
@@ -487,12 +609,16 @@ namespace ArachnaeSwarm
|
||||
drawPos.y += 0.15f;
|
||||
|
||||
float progress = ProductionProgress;
|
||||
|
||||
// 新增:负时间警告颜色(红色)
|
||||
Color barColor = HasNegativeTimeProblem ? Color.red : Color.green;
|
||||
|
||||
GenDraw.DrawFillableBar(new GenDraw.FillableBarRequest
|
||||
{
|
||||
center = drawPos,
|
||||
size = new Vector2(1f, 0.15f),
|
||||
fillPercent = progress,
|
||||
filledMat = SolidColorMaterials.SimpleSolidColorMaterial(Color.green),
|
||||
filledMat = SolidColorMaterials.SimpleSolidColorMaterial(barColor),
|
||||
unfilledMat = SolidColorMaterials.SimpleSolidColorMaterial(Color.gray),
|
||||
margin = 0.1f,
|
||||
rotation = Rot4.North
|
||||
@@ -522,6 +648,62 @@ namespace ArachnaeSwarm
|
||||
defaultLabel = "Debug: Force Finish",
|
||||
action = () => FinishProduction()
|
||||
};
|
||||
|
||||
// 新增:调试命令显示详细进度信息
|
||||
yield return new Command_Action
|
||||
{
|
||||
defaultLabel = "Debug: Show Progress Info",
|
||||
action = () =>
|
||||
{
|
||||
float progress = ProductionProgress;
|
||||
int remainingTicks = productionUntilTick - Find.TickManager.TicksGame;
|
||||
|
||||
string message = $"Progress: {progress:P0}\n" +
|
||||
$"Remaining Ticks: {remainingTicks}\n" +
|
||||
$"Has Negative Time: {HasNegativeTimeProblem}\n" +
|
||||
$"Fixed Before: {hasFixedNegativeTime}\n" +
|
||||
$"Research: {_selectedProcess.researchDef?.defName ?? "Unknown"}\n" +
|
||||
$"Techprints: {_selectedProcess.techprintCount}";
|
||||
Messages.Message(message, MessageTypeDefOf.SilentInput);
|
||||
}
|
||||
};
|
||||
|
||||
// 新增:调试命令手动触发负时间修复
|
||||
yield return new Command_Action
|
||||
{
|
||||
defaultLabel = "Debug: Fix Negative Time",
|
||||
action = () =>
|
||||
{
|
||||
if (HasNegativeTimeProblem)
|
||||
{
|
||||
FixNegativeTimeProblem();
|
||||
Messages.Message("Manually triggered negative time fix", MessageTypeDefOf.SilentInput);
|
||||
}
|
||||
else
|
||||
{
|
||||
Messages.Message("No negative time problem detected", MessageTypeDefOf.SilentInput);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 新增:调试命令模拟负时间问题
|
||||
yield return new Command_Action
|
||||
{
|
||||
defaultLabel = "Debug: Simulate Negative Time",
|
||||
action = () =>
|
||||
{
|
||||
if (InProduction)
|
||||
{
|
||||
productionUntilTick = Find.TickManager.TicksGame - 1000; // 设置为1000ticks前
|
||||
hasFixedNegativeTime = false;
|
||||
Messages.Message("Simulated negative time problem (-1000 ticks)", MessageTypeDefOf.SilentInput);
|
||||
}
|
||||
else
|
||||
{
|
||||
Messages.Message("Not in production", MessageTypeDefOf.SilentInput);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,8 +123,8 @@ namespace ArachnaeSwarm
|
||||
|
||||
DamageInfo acidDamage = new DamageInfo(
|
||||
acidDamageDef,
|
||||
1f, // 每次1点伤害
|
||||
0.1f, // 轻微护甲穿透
|
||||
3f, // 每次3点伤害
|
||||
2f, // 轻微护甲穿透
|
||||
-1f, // 随机角度
|
||||
instigator: null,
|
||||
hitPart: targetPart
|
||||
|
||||
@@ -80,6 +80,13 @@ namespace ArachnaeSwarm
|
||||
Pawn pawn = parent as Pawn;
|
||||
if (pawn == null) return;
|
||||
|
||||
// 添加:如果有关闭 Hediff,不处理缺失的寿命 Hediff
|
||||
if (HasShutdownHediff)
|
||||
{
|
||||
Log.Message($"Lifespan hediff missing for {pawn.Label}, but shutdown hediff is present. This is expected behavior.");
|
||||
return;
|
||||
}
|
||||
|
||||
Log.Warning($"Lifespan hediff missing for {pawn.Label}. This should not happen. Forcing death.");
|
||||
|
||||
// 立即处死pawn
|
||||
@@ -105,6 +112,20 @@ namespace ArachnaeSwarm
|
||||
Pawn pawn = parent as Pawn;
|
||||
if (pawn == null) return null;
|
||||
|
||||
// 添加:如果有关闭 Hediff,不创建或返回寿命 Hediff
|
||||
if (HasShutdownHediff)
|
||||
{
|
||||
// 如果已经存在寿命 Hediff,可以选择移除它
|
||||
var existingHediff = pawn.health.hediffSet.GetFirstHediffOfDef(Props.lifespanHediff);
|
||||
if (existingHediff != null)
|
||||
{
|
||||
Log.Message($"Shutdown hediff present for {pawn.Label}. Removing lifespan hediff.");
|
||||
pawn.health.RemoveHediff(existingHediff);
|
||||
lifespanHediff = null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// 首先尝试查找现有的寿命Hediff
|
||||
if (lifespanHediff == null || lifespanHediff.pawn != pawn)
|
||||
{
|
||||
@@ -132,6 +153,19 @@ namespace ArachnaeSwarm
|
||||
Pawn pawn = parent as Pawn;
|
||||
if (pawn == null) return;
|
||||
|
||||
// 添加:如果有关闭 Hediff,不进行同步
|
||||
if (HasShutdownHediff)
|
||||
{
|
||||
// 确保移除可能存在的寿命 Hediff
|
||||
var existingHediff = pawn.health.hediffSet.GetFirstHediffOfDef(Props.lifespanHediff);
|
||||
if (existingHediff != null)
|
||||
{
|
||||
pawn.health.RemoveHediff(existingHediff);
|
||||
lifespanHediff = null;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var hediff = GetOrCreateLifespanHediff();
|
||||
if (hediff == null)
|
||||
{
|
||||
@@ -167,6 +201,13 @@ namespace ArachnaeSwarm
|
||||
Pawn pawn = parent as Pawn;
|
||||
if (pawn == null) return;
|
||||
|
||||
// 添加:如果有关闭 Hediff,不写入数据
|
||||
if (HasShutdownHediff)
|
||||
{
|
||||
Log.Message($"Cannot write comp data to hediff: Shutdown hediff is present for {pawn.Label}");
|
||||
return;
|
||||
}
|
||||
|
||||
var hediff = GetOrCreateLifespanHediff();
|
||||
if (hediff == null)
|
||||
{
|
||||
@@ -185,6 +226,20 @@ namespace ArachnaeSwarm
|
||||
Pawn pawn = parent as Pawn;
|
||||
if (pawn == null) return;
|
||||
|
||||
// 添加:如果有关闭 Hediff,不进行 Hediff 校验
|
||||
if (HasShutdownHediff)
|
||||
{
|
||||
// 确保移除可能存在的寿命 Hediff
|
||||
var existingHediff = pawn.health.hediffSet.GetFirstHediffOfDef(Props.lifespanHediff);
|
||||
if (existingHediff != null)
|
||||
{
|
||||
pawn.health.RemoveHediff(existingHediff);
|
||||
lifespanHediff = null;
|
||||
Log.Message($"Removed lifespan hediff for {pawn.Label} due to shutdown hediff presence");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查寿命Hediff是否存在
|
||||
var currentHediff = pawn.health.hediffSet.GetFirstHediffOfDef(Props.lifespanHediff);
|
||||
|
||||
@@ -201,6 +256,19 @@ namespace ArachnaeSwarm
|
||||
}
|
||||
}
|
||||
|
||||
// 新增:检查是否需要创建寿命 Hediff
|
||||
private bool ShouldCreateLifespanHediff()
|
||||
{
|
||||
// 如果有关闭 Hediff,不应该创建寿命 Hediff
|
||||
if (HasShutdownHediff)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// 其他创建条件...
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void PostSpawnSetup(bool respawningAfterLoad)
|
||||
{
|
||||
if (!ModLister.CheckBiotechOrAnomalyOrOdyssey("Node swarm lifetime"))
|
||||
@@ -222,11 +290,19 @@ namespace ArachnaeSwarm
|
||||
lastHediffSyncTick = Find.TickManager.TicksGame;
|
||||
lastHediffMissingCheckTick = Find.TickManager.TicksGame;
|
||||
|
||||
// 确保寿命Hediff存在
|
||||
GetOrCreateLifespanHediff();
|
||||
|
||||
// 初始同步
|
||||
SyncLifespanWithHediff();
|
||||
// 添加:检查是否需要创建寿命 Hediff
|
||||
if (ShouldCreateLifespanHediff())
|
||||
{
|
||||
// 确保寿命Hediff存在
|
||||
GetOrCreateLifespanHediff();
|
||||
|
||||
// 初始同步
|
||||
SyncLifespanWithHediff();
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Message($"Skipping lifespan hediff creation for {parent.Label} due to shutdown hediff");
|
||||
}
|
||||
}
|
||||
|
||||
public override IEnumerable<Gizmo> CompGetGizmosExtra()
|
||||
@@ -254,12 +330,38 @@ namespace ArachnaeSwarm
|
||||
}
|
||||
if (DebugSettings.ShowDevGizmos)
|
||||
{
|
||||
// 新增:显示关闭 Hediff 状态
|
||||
yield return new Command_Action
|
||||
{
|
||||
defaultLabel = "DEV: 显示关闭Hediff状态",
|
||||
action = delegate
|
||||
{
|
||||
Pawn pawn = parent as Pawn;
|
||||
if (pawn != null)
|
||||
{
|
||||
string message = $"关闭Hediff状态:\n" +
|
||||
$"HasShutdownHediff: {HasShutdownHediff}\n" +
|
||||
$"Shutdown Hediff Def: {Props.immuteHediff?.defName ?? "None"}\n" +
|
||||
$"实际存在: {(Props.immuteHediff != null ? pawn.health.hediffSet.HasHediff(Props.immuteHediff).ToString() : "N/A")}";
|
||||
Messages.Message(message, MessageTypeDefOf.SilentInput);
|
||||
Log.Message(message);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 新增:补满寿命调试命令
|
||||
yield return new Command_Action
|
||||
{
|
||||
defaultLabel = "DEV: 补满寿命",
|
||||
action = delegate
|
||||
{
|
||||
// 添加:检查关闭 Hediff
|
||||
if (HasShutdownHediff)
|
||||
{
|
||||
Messages.Message("无法补满寿命:存在关闭系统的 Hediff", MessageTypeDefOf.RejectInput);
|
||||
return;
|
||||
}
|
||||
|
||||
powerTicksLeft = (int)(Props.lifetimeDays * 60000);
|
||||
WriteCompDataToHediff(); // 使用新的写入方法
|
||||
Log.Message($"已补满寿命: {parent.Label} 剩余 {DaysLeft:F1} 天");
|
||||
@@ -273,6 +375,13 @@ namespace ArachnaeSwarm
|
||||
defaultLabel = "DEV: 剩余0.01%寿命",
|
||||
action = delegate
|
||||
{
|
||||
// 添加:检查关闭 Hediff
|
||||
if (HasShutdownHediff)
|
||||
{
|
||||
Messages.Message("无法设置寿命:存在关闭系统的 Hediff", MessageTypeDefOf.RejectInput);
|
||||
return;
|
||||
}
|
||||
|
||||
int totalTicks = (int)(Props.lifetimeDays * 60000);
|
||||
powerTicksLeft = (int)(totalTicks * 0.0001f); // 0.01%
|
||||
WriteCompDataToHediff(); // 使用新的写入方法
|
||||
@@ -288,6 +397,13 @@ namespace ArachnaeSwarm
|
||||
defaultLabel = "DEV: 归零寿命",
|
||||
action = delegate
|
||||
{
|
||||
// 添加:检查关闭 Hediff
|
||||
if (HasShutdownHediff)
|
||||
{
|
||||
Messages.Message("无法归零寿命:存在关闭系统的 Hediff", MessageTypeDefOf.RejectInput);
|
||||
return;
|
||||
}
|
||||
|
||||
powerTicksLeft = 0;
|
||||
WriteCompDataToHediff(); // 使用新的写入方法
|
||||
Log.Message($"已归零寿命: {parent.Label} 将立即死亡");
|
||||
@@ -320,13 +436,16 @@ namespace ArachnaeSwarm
|
||||
$"剩余天数: {DaysLeft:F4}\n" +
|
||||
$"总天数: {TotalDays:F1}\n" +
|
||||
$"百分比: {PercentFull:P4}\n" +
|
||||
$"已耗尽: {depleted}";
|
||||
$"已耗尽: {depleted}\n" +
|
||||
$"关闭Hediff存在: {HasShutdownHediff}";
|
||||
Messages.Message(message, MessageTypeDefOf.SilentInput);
|
||||
Log.Message(message);
|
||||
}
|
||||
else
|
||||
{
|
||||
Messages.Message("未找到寿命hediff", MessageTypeDefOf.SilentInput);
|
||||
string message = $"未找到寿命hediff\n" +
|
||||
$"关闭Hediff存在: {HasShutdownHediff}";
|
||||
Messages.Message(message, MessageTypeDefOf.SilentInput);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -362,6 +481,13 @@ namespace ArachnaeSwarm
|
||||
defaultLabel = "DEV: 强制同步",
|
||||
action = delegate
|
||||
{
|
||||
// 添加:检查关闭 Hediff
|
||||
if (HasShutdownHediff)
|
||||
{
|
||||
Messages.Message("无法同步:存在关闭系统的 Hediff", MessageTypeDefOf.RejectInput);
|
||||
return;
|
||||
}
|
||||
|
||||
SyncLifespanWithHediff();
|
||||
var hediff = GetOrCreateLifespanHediff();
|
||||
if (hediff != null)
|
||||
@@ -482,9 +608,17 @@ namespace ArachnaeSwarm
|
||||
// 立即检查hediff是否存在
|
||||
ValidateHediffState();
|
||||
|
||||
// 确保寿命Hediff存在并同步
|
||||
GetOrCreateLifespanHediff();
|
||||
SyncLifespanWithHediff();
|
||||
// 添加:检查是否需要创建寿命 Hediff
|
||||
if (ShouldCreateLifespanHediff())
|
||||
{
|
||||
// 确保寿命Hediff存在并同步
|
||||
GetOrCreateLifespanHediff();
|
||||
SyncLifespanWithHediff();
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Message($"Skipping lifespan hediff creation for {parent.Label} after load due to shutdown hediff");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,31 @@ using RimWorld;
|
||||
using UnityEngine;
|
||||
using Verse;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace ArachnaeSwarm
|
||||
{
|
||||
public static class ARA_Translations
|
||||
{
|
||||
// 武装方案相关
|
||||
public static readonly string UnknownScheme = "ARA_UnknownScheme";
|
||||
public static readonly string SchemeFormat = "ARA_SchemeFormat";
|
||||
|
||||
// 消息提示
|
||||
public static readonly string PowerArmorDamaged = "ARA_PowerArmorDamaged";
|
||||
public static readonly string SwitchedToMode = "ARA_SwitchedToMode";
|
||||
public static readonly string EquipPowerArmorFailed = "ARA_EquipPowerArmorFailed";
|
||||
public static readonly string AlreadySelectedScheme = "ARA_AlreadySelectedScheme";
|
||||
|
||||
// Gizmo 按钮文本
|
||||
public static readonly string SwitchWeapon = "ARA_SwitchWeapon";
|
||||
public static readonly string SwitchWeaponDesc = "ARA_SwitchWeaponDesc";
|
||||
public static readonly string SwitchToScheme = "ARA_SwitchToScheme";
|
||||
|
||||
// 默认值
|
||||
public static readonly string Default = "ARA_Default";
|
||||
}
|
||||
|
||||
public interface IStructurePoints
|
||||
{
|
||||
float StructurePoints { get; }
|
||||
@@ -13,13 +35,28 @@ namespace ArachnaeSwarm
|
||||
string Label { get; }
|
||||
}
|
||||
|
||||
public class PowerArmorWeaponSet
|
||||
{
|
||||
public string label; // 方案名称,显示在UI上
|
||||
public string description; // 方案描述,显示在按钮的desc上
|
||||
public ThingDef weapon; // 武器定义
|
||||
public List<HediffDef> hediffsToAdd; // 切换到此方案时添加的Hediff
|
||||
public List<HediffDef> hediffsToRemove; // 切换到此方案时移除的Hediff
|
||||
public string iconPath; // 可选的图标路径
|
||||
}
|
||||
|
||||
public class PowerArmorExtension : DefModExtension
|
||||
{
|
||||
public ThingDef buildingDef;
|
||||
public float structurePointsMax = 500f;
|
||||
public HediffDef hediffOnEmptyFuel;
|
||||
public float fuelConsumptionRate = 0.5f; // Nutrition per day
|
||||
public ThingDef powerArmorWeapon;
|
||||
|
||||
// 废弃原来的单个武器,改用列表
|
||||
public List<PowerArmorWeaponSet> weaponSets = new List<PowerArmorWeaponSet>();
|
||||
|
||||
// 默认武装方案索引
|
||||
public int defaultWeaponSetIndex = 0;
|
||||
}
|
||||
|
||||
[StaticConstructorOnStartup]
|
||||
@@ -52,8 +89,18 @@ namespace ArachnaeSwarm
|
||||
public float StructurePointsPercent => StructurePoints / StructurePointsMax;
|
||||
|
||||
public Building sourceBuilding;
|
||||
private ThingWithComps originalWeapon; // Still needed to store pawn's original weapon
|
||||
private ThingWithComps currentPowerArmorWeapon; // Track the currently equipped power armor weapon
|
||||
private ThingWithComps originalWeapon;
|
||||
private ThingWithComps currentPowerArmorWeapon;
|
||||
|
||||
// 新增字段:武装方案管理
|
||||
private int currentWeaponSetIndex = 0;
|
||||
private List<Hediff> activeHediffs = new List<Hediff>();
|
||||
|
||||
public int CurrentWeaponSetIndex => currentWeaponSetIndex;
|
||||
public PowerArmorWeaponSet CurrentWeaponSet =>
|
||||
Ext?.weaponSets != null && Ext.weaponSets.Count > currentWeaponSetIndex ?
|
||||
Ext.weaponSets[currentWeaponSetIndex] : null;
|
||||
public int WeaponSetCount => Ext?.weaponSets?.Count ?? 0;
|
||||
|
||||
public void SetOriginalWeapon(ThingWithComps weapon)
|
||||
{
|
||||
@@ -66,6 +113,280 @@ namespace ArachnaeSwarm
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 装备/卸下处理
|
||||
public override void Notify_Equipped(Pawn pawn)
|
||||
{
|
||||
base.Notify_Equipped(pawn);
|
||||
|
||||
// 设置默认武装方案
|
||||
currentWeaponSetIndex = Ext?.defaultWeaponSetIndex ?? 0;
|
||||
|
||||
// 应用初始武装方案
|
||||
ApplyWeaponSet(pawn, CurrentWeaponSet);
|
||||
|
||||
Log.Message($"[PA_Debug] 装备动力装甲,应用武装方案: {CurrentWeaponSet?.label ?? "无方案"}");
|
||||
}
|
||||
|
||||
public override void Notify_Unequipped(Pawn pawn)
|
||||
{
|
||||
// 清除所有激活的Hediff
|
||||
foreach (var hediff in activeHediffs)
|
||||
{
|
||||
if (pawn.health.hediffSet.hediffs.Contains(hediff))
|
||||
{
|
||||
pawn.health.RemoveHediff(hediff);
|
||||
}
|
||||
}
|
||||
activeHediffs.Clear();
|
||||
|
||||
base.Notify_Unequipped(pawn);
|
||||
|
||||
// 原有卸下逻辑保持不变...
|
||||
if (Ext?.weaponSets != null && Ext.weaponSets.Count > 0)
|
||||
{
|
||||
// 销毁当前动力装甲武器
|
||||
if (currentPowerArmorWeapon != null)
|
||||
{
|
||||
if (pawn?.equipment != null && pawn.equipment.Contains(currentPowerArmorWeapon))
|
||||
{
|
||||
pawn.equipment.Remove(currentPowerArmorWeapon);
|
||||
}
|
||||
else if (pawn?.inventory?.innerContainer != null && pawn.inventory.innerContainer.Contains(currentPowerArmorWeapon))
|
||||
{
|
||||
pawn.inventory.innerContainer.Remove(currentPowerArmorWeapon);
|
||||
}
|
||||
else if (currentPowerArmorWeapon.Spawned)
|
||||
{
|
||||
currentPowerArmorWeapon.DeSpawn();
|
||||
}
|
||||
string destroyedWeaponLabel = currentPowerArmorWeapon.Label;
|
||||
currentPowerArmorWeapon.Destroy();
|
||||
Log.Message($"[PA_Debug] Notify_Unequipped: 销毁动力装甲武器 {destroyedWeaponLabel}.");
|
||||
currentPowerArmorWeapon = null;
|
||||
}
|
||||
|
||||
// 恢复原始武器
|
||||
if (originalWeapon != null && pawn?.equipment != null)
|
||||
{
|
||||
string originalWeaponLabel = originalWeapon.Label;
|
||||
pawn.equipment.MakeRoomFor(originalWeapon);
|
||||
pawn.equipment.AddEquipment(originalWeapon);
|
||||
Log.Message($"[PA_Debug] Notify_Unequipped: 恢复原始武器 {originalWeaponLabel}.");
|
||||
originalWeapon = null;
|
||||
}
|
||||
}
|
||||
|
||||
Building building = sourceBuilding;
|
||||
|
||||
// 如果源建筑引用丢失,创建新建筑作为回退
|
||||
if (building == null)
|
||||
{
|
||||
ThingDef buildingDef = Ext?.buildingDef;
|
||||
if (buildingDef == null)
|
||||
{
|
||||
Log.Error($"[ArachnaeSwarm] 动力装甲 {this.def.defName} 卸下,但在其PowerArmorExtension中未定义buildingDef且源建筑引用丢失。");
|
||||
this.Destroy(DestroyMode.Vanish);
|
||||
return;
|
||||
}
|
||||
building = (Building)ThingMaker.MakeThing(buildingDef);
|
||||
}
|
||||
|
||||
// 同步健康值回建筑
|
||||
building.HitPoints = Mathf.Max(1, Mathf.RoundToInt(this.StructurePoints));
|
||||
|
||||
// 同步燃料回建筑
|
||||
var apparelFuelComp = this.GetComp<CompRefuelableNutrition>();
|
||||
var buildingFuelComp = building.GetComp<CompRefuelableNutrition>();
|
||||
if (apparelFuelComp != null && buildingFuelComp != null)
|
||||
{
|
||||
buildingFuelComp.ConsumeFuel(buildingFuelComp.Fuel);
|
||||
buildingFuelComp.ReceiveFuel(apparelFuelComp.Fuel);
|
||||
}
|
||||
|
||||
// 同步质量回建筑
|
||||
if (this.TryGetComp<CompQuality>() is CompQuality apparelQuality && building.TryGetComp<CompQuality>() is CompQuality buildingQuality)
|
||||
{
|
||||
buildingQuality.SetQuality(apparelQuality.Quality, ArtGenerationContext.Colony);
|
||||
}
|
||||
|
||||
Log.Message($"[PA_Debug] Notify_Unequipped: 生成建筑前 (ID: {building.thingIDNumber}) - HitPoints: {building.HitPoints}, StackCount: {building.stackCount}");
|
||||
|
||||
// 确保建筑堆叠数至少为1
|
||||
if (building.stackCount <= 0)
|
||||
{
|
||||
building.stackCount = 1;
|
||||
Log.Warning($"[PA_Debug] Notify_Unequipped: 修正建筑 (ID: {building.thingIDNumber}) 堆叠数为1,因为原为0。");
|
||||
}
|
||||
|
||||
// 设置派系
|
||||
building.SetFaction(pawn.Faction);
|
||||
|
||||
// 重新生成原始建筑实例
|
||||
GenPlace.TryPlaceThing(building, pawn.Position, pawn.Map, ThingPlaceMode.Near);
|
||||
Log.Message($"[PA_Debug] Notify_Unequipped: 生成建筑后 (ID: {building.thingIDNumber}) - HitPoints: {building.HitPoints}, StackCount: {building.stackCount}");
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 武装方案管理
|
||||
/// <summary>
|
||||
/// 切换到下一个武装方案
|
||||
/// </summary>
|
||||
public void CycleToNextWeaponSet()
|
||||
{
|
||||
if (WeaponSetCount <= 1) return;
|
||||
|
||||
var oldSet = CurrentWeaponSet;
|
||||
currentWeaponSetIndex = (currentWeaponSetIndex + 1) % WeaponSetCount;
|
||||
var newSet = CurrentWeaponSet;
|
||||
|
||||
Log.Message($"[PA_Debug] 切换武装方案: {oldSet?.label ?? "无"} -> {newSet?.label ?? "无"}");
|
||||
|
||||
ApplyWeaponSet(Wearer, newSet, oldSet);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 切换到指定索引的武装方案
|
||||
/// </summary>
|
||||
public void SwitchToWeaponSet(int index)
|
||||
{
|
||||
if (index < 0 || index >= WeaponSetCount) return;
|
||||
|
||||
var oldSet = CurrentWeaponSet;
|
||||
currentWeaponSetIndex = index;
|
||||
var newSet = CurrentWeaponSet;
|
||||
|
||||
Log.Message($"[PA_Debug] 切换到武装方案: {oldSet?.label ?? "无"} -> {newSet?.label ?? "无"}");
|
||||
|
||||
ApplyWeaponSet(Wearer, newSet, oldSet);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 应用指定的武装方案
|
||||
/// </summary>
|
||||
private void ApplyWeaponSet(Pawn pawn, PowerArmorWeaponSet newSet, PowerArmorWeaponSet oldSet = null)
|
||||
{
|
||||
if (pawn == null) return;
|
||||
|
||||
// 移除旧方案的Hediff
|
||||
if (oldSet?.hediffsToRemove != null)
|
||||
{
|
||||
foreach (var hediffDef in oldSet.hediffsToRemove)
|
||||
{
|
||||
var hediff = pawn.health.hediffSet.GetFirstHediffOfDef(hediffDef);
|
||||
if (hediff != null)
|
||||
{
|
||||
pawn.health.RemoveHediff(hediff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 清除当前激活的Hediff
|
||||
foreach (var hediff in activeHediffs.ToList())
|
||||
{
|
||||
if (pawn.health.hediffSet.hediffs.Contains(hediff))
|
||||
{
|
||||
pawn.health.RemoveHediff(hediff);
|
||||
}
|
||||
}
|
||||
activeHediffs.Clear();
|
||||
|
||||
// 添加新方案的Hediff
|
||||
if (newSet?.hediffsToAdd != null)
|
||||
{
|
||||
foreach (var hediffDef in newSet.hediffsToAdd)
|
||||
{
|
||||
var hediff = pawn.health.GetOrAddHediff(hediffDef);
|
||||
activeHediffs.Add(hediff);
|
||||
Log.Message($"[PA_Debug] 添加Hediff: {hediffDef.defName}");
|
||||
}
|
||||
}
|
||||
|
||||
// 处理武器切换
|
||||
HandleWeaponSwitch(pawn, newSet);
|
||||
|
||||
// 显示切换消息
|
||||
if (newSet != null)
|
||||
{
|
||||
Messages.Message(ARA_Translations.SwitchedToMode.Translate(newSet.label), pawn, MessageTypeDefOf.NeutralEvent);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理武器切换逻辑
|
||||
/// </summary>
|
||||
private void HandleWeaponSwitch(Pawn pawn, PowerArmorWeaponSet newSet)
|
||||
{
|
||||
if (pawn?.equipment == null) return;
|
||||
|
||||
// 销毁当前动力装甲武器
|
||||
if (currentPowerArmorWeapon != null)
|
||||
{
|
||||
if (pawn.equipment.Contains(currentPowerArmorWeapon))
|
||||
{
|
||||
pawn.equipment.Remove(currentPowerArmorWeapon);
|
||||
}
|
||||
currentPowerArmorWeapon.Destroy();
|
||||
currentPowerArmorWeapon = null;
|
||||
Log.Message($"[PA_Debug] 销毁当前动力装甲武器");
|
||||
}
|
||||
|
||||
// 如果新方案有武器,装备新武器
|
||||
if (newSet?.weapon != null)
|
||||
{
|
||||
ThingWithComps weapon = (ThingWithComps)ThingMaker.MakeThing(newSet.weapon);
|
||||
|
||||
// 同步武器质量
|
||||
if (this.TryGetComp<CompQuality>() is CompQuality apparelQuality &&
|
||||
weapon.TryGetComp<CompQuality>() is CompQuality weaponQuality)
|
||||
{
|
||||
weaponQuality.SetQuality(apparelQuality.Quality, ArtGenerationContext.Colony);
|
||||
}
|
||||
|
||||
pawn.equipment.MakeRoomFor(weapon);
|
||||
pawn.equipment.AddEquipment(weapon);
|
||||
SetCurrentPowerArmorWeapon(weapon);
|
||||
|
||||
Log.Message($"[PA_Debug] 装备新武器: {weapon.Label}");
|
||||
}
|
||||
// 如果没有武器,恢复原始武器
|
||||
else if (originalWeapon != null)
|
||||
{
|
||||
pawn.equipment.MakeRoomFor(originalWeapon);
|
||||
pawn.equipment.AddEquipment(originalWeapon);
|
||||
Log.Message($"[PA_Debug] 恢复原始武器: {originalWeapon.Label}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取武装方案显示名称
|
||||
/// </summary>
|
||||
public string GetWeaponSetDisplayName(int index)
|
||||
{
|
||||
if (index < 0 || index >= WeaponSetCount) return ARA_Translations.UnknownScheme.Translate();
|
||||
var set = Ext.weaponSets[index];
|
||||
return set.label ?? ARA_Translations.SchemeFormat.Translate(index + 1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取武装方案描述
|
||||
/// </summary>
|
||||
public string GetWeaponSetDescription(int index)
|
||||
{
|
||||
if (index < 0 || index >= WeaponSetCount) return string.Empty;
|
||||
var set = Ext.weaponSets[index];
|
||||
|
||||
// 如果设置了自定义描述,使用自定义描述
|
||||
if (!string.IsNullOrEmpty(set.description))
|
||||
{
|
||||
return set.description;
|
||||
}
|
||||
|
||||
// 否则使用默认的翻译文本
|
||||
return ARA_Translations.SwitchToScheme.Translate(
|
||||
set.label ?? ARA_Translations.SchemeFormat.Translate(index + 1));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Ticker
|
||||
protected override void Tick()
|
||||
{
|
||||
@@ -82,15 +403,11 @@ namespace ArachnaeSwarm
|
||||
var fuelComp = this.GetComp<CompRefuelableNutrition>();
|
||||
if (fuelComp != null)
|
||||
{
|
||||
// Set the consumption rate on every tick. This value is then used by CompRefuelableNutrition's CompTick.
|
||||
// We use the value from our PowerArmorExtension, ensuring it's always active.
|
||||
// 设置消耗率
|
||||
fuelComp.currentConsumptionRate = Ext?.fuelConsumptionRate ?? 0f;
|
||||
|
||||
// We must explicitly call the component's Tick, as Apparel's base Tick does not.
|
||||
// This will trigger the consumption logic inside CompRefuelableNutrition.
|
||||
fuelComp.CompTick();
|
||||
|
||||
// Handle hediff for empty fuel, checked frequently for responsiveness.
|
||||
// 处理空燃料Hediff
|
||||
if (this.Wearer.IsHashIntervalTick(60))
|
||||
{
|
||||
var hediffDef = Ext?.hediffOnEmptyFuel;
|
||||
@@ -117,31 +434,72 @@ namespace ArachnaeSwarm
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Data
|
||||
#region 数据保存
|
||||
public override void ExposeData()
|
||||
{
|
||||
base.ExposeData();
|
||||
Scribe_Values.Look(ref structurePoints, "structurePoints", -1f);
|
||||
Scribe_References.Look(ref sourceBuilding, "sourceBuilding");
|
||||
Scribe_References.Look(ref originalWeapon, "originalWeapon");
|
||||
Scribe_References.Look(ref currentPowerArmorWeapon, "currentPowerArmorWeapon"); // Save/load current power armor weapon
|
||||
Scribe_References.Look(ref currentPowerArmorWeapon, "currentPowerArmorWeapon");
|
||||
Scribe_Values.Look(ref currentWeaponSetIndex, "currentWeaponSetIndex", 0);
|
||||
|
||||
// 注意:Hediff不需要保存,因为会在加载时重新应用
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Gizmo
|
||||
public override IEnumerable<Gizmo> GetWornGizmos()
|
||||
{
|
||||
// Always yield base gizmos first.
|
||||
// 基础Gizmo
|
||||
foreach (var gizmo in base.GetWornGizmos())
|
||||
{
|
||||
yield return gizmo;
|
||||
}
|
||||
|
||||
// Yield our custom structure points gizmo.
|
||||
// 结构点面板
|
||||
yield return new Gizmo_StructurePanel(this);
|
||||
|
||||
// Yield the default gizmos from the CompRefuelable component.
|
||||
// This will provide the standard RimWorld fuel gizmo.
|
||||
// 武装方案切换按钮(只有在有多个方案时显示)
|
||||
if (WeaponSetCount > 1)
|
||||
{
|
||||
// 主切换按钮(已注释,但保留翻译)
|
||||
/*
|
||||
yield return new Command_Action
|
||||
{
|
||||
defaultLabel = ARA_Translations.SwitchWeapon.Translate(CurrentWeaponSet?.label ?? ARA_Translations.Default.Translate()),
|
||||
defaultDesc = ARA_Translations.SwitchWeaponDesc.Translate(
|
||||
CurrentWeaponSet?.label ?? ARA_Translations.Default.Translate(),
|
||||
WeaponSetCount),
|
||||
icon = ContentFinder<Texture2D>.Get("UI/Commands/Attack") ?? BaseContent.BadTex,
|
||||
action = CycleToNextWeaponSet
|
||||
};
|
||||
*/
|
||||
|
||||
// 为每个武装方案提供单独的切换按钮
|
||||
for (int i = 0; i < WeaponSetCount; i++)
|
||||
{
|
||||
int currentIndex = i; // 创建局部变量捕获当前索引
|
||||
var set = Ext.weaponSets[currentIndex];
|
||||
var command = new Command_Action
|
||||
{
|
||||
defaultLabel = set.label ?? ARA_Translations.SchemeFormat.Translate(currentIndex + 1),
|
||||
defaultDesc = GetWeaponSetDescription(currentIndex), // 使用新的描述获取方法
|
||||
icon = set.iconPath != null ? ContentFinder<Texture2D>.Get(set.iconPath) : ContentFinder<Texture2D>.Get("UI/Commands/Attack"),
|
||||
action = () => SwitchToWeaponSet(currentIndex) // 使用局部变量
|
||||
};
|
||||
|
||||
// 正确禁用当前已选择的方案按钮
|
||||
if (currentIndex == currentWeaponSetIndex)
|
||||
{
|
||||
command.Disable(ARA_Translations.AlreadySelectedScheme.Translate());
|
||||
}
|
||||
|
||||
yield return command;
|
||||
}
|
||||
}
|
||||
|
||||
// 燃料组件Gizmo
|
||||
var fuelComp = this.GetComp<CompRefuelableNutrition>();
|
||||
if (fuelComp != null)
|
||||
{
|
||||
@@ -152,105 +510,8 @@ namespace ArachnaeSwarm
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region State-Switching
|
||||
public override void Notify_Unequipped(Pawn pawn)
|
||||
{
|
||||
base.Notify_Unequipped(pawn);
|
||||
|
||||
// Handle power armor weapon destruction and original weapon restoration
|
||||
if (Ext?.powerArmorWeapon != null)
|
||||
{
|
||||
// Destroy the power armor weapon, wherever it might be.
|
||||
// We track it with currentPowerArmorWeapon, so we don't rely on pawn.equipment.Primary.
|
||||
if (currentPowerArmorWeapon != null)
|
||||
{
|
||||
if (pawn?.equipment != null && pawn.equipment.Contains(currentPowerArmorWeapon))
|
||||
{
|
||||
pawn.equipment.Remove(currentPowerArmorWeapon);
|
||||
}
|
||||
else if (pawn?.inventory?.innerContainer != null && pawn.inventory.innerContainer.Contains(currentPowerArmorWeapon))
|
||||
{
|
||||
pawn.inventory.innerContainer.Remove(currentPowerArmorWeapon);
|
||||
}
|
||||
// If it's on the map, destroy it there.
|
||||
else if (currentPowerArmorWeapon.Spawned)
|
||||
{
|
||||
currentPowerArmorWeapon.DeSpawn();
|
||||
}
|
||||
string destroyedWeaponLabel = currentPowerArmorWeapon.Label;
|
||||
currentPowerArmorWeapon.Destroy();
|
||||
Log.Message($"[PA_Debug] Notify_Unequipped: Destroyed power armor weapon {destroyedWeaponLabel}.");
|
||||
currentPowerArmorWeapon = null;
|
||||
}
|
||||
|
||||
// Restore original weapon if saved
|
||||
if (originalWeapon != null && pawn?.equipment != null)
|
||||
{
|
||||
string originalWeaponLabel = originalWeapon.Label;
|
||||
pawn.equipment.MakeRoomFor(originalWeapon);
|
||||
pawn.equipment.AddEquipment(originalWeapon);
|
||||
Log.Message($"[PA_Debug] Notify_Unequipped: Restored original weapon {originalWeaponLabel}.");
|
||||
originalWeapon = null;
|
||||
}
|
||||
}
|
||||
|
||||
Building building = sourceBuilding;
|
||||
|
||||
// If the source building reference is lost, create a new one as a fallback.
|
||||
if (building == null)
|
||||
{
|
||||
ThingDef buildingDef = Ext?.buildingDef;
|
||||
if (buildingDef == null)
|
||||
{
|
||||
Log.Error($"[ArachnaeSwarm] Power Armor {this.def.defName} unequipped, but has no buildingDef defined in its PowerArmorExtension and the source building reference was lost.");
|
||||
this.Destroy(DestroyMode.Vanish);
|
||||
return;
|
||||
}
|
||||
building = (Building)ThingMaker.MakeThing(buildingDef);
|
||||
}
|
||||
|
||||
// Sync health back to the building, ensuring it's at least 1 to prevent it from being destroyed instantly.
|
||||
building.HitPoints = Mathf.Max(1, Mathf.RoundToInt(this.StructurePoints));
|
||||
|
||||
// Sync fuel back to the building
|
||||
var apparelFuelComp = this.GetComp<CompRefuelableNutrition>();
|
||||
var buildingFuelComp = building.GetComp<CompRefuelableNutrition>();
|
||||
if (apparelFuelComp != null && buildingFuelComp != null)
|
||||
{
|
||||
// Reset building fuel and then set it to the apparel's current fuel to avoid overflow.
|
||||
buildingFuelComp.ConsumeFuel(buildingFuelComp.Fuel);
|
||||
buildingFuelComp.ReceiveFuel(apparelFuelComp.Fuel);
|
||||
}
|
||||
|
||||
// Sync quality back to building
|
||||
if (this.TryGetComp<CompQuality>() is CompQuality apparelQuality && building.TryGetComp<CompQuality>() is CompQuality buildingQuality)
|
||||
{
|
||||
buildingQuality.SetQuality(apparelQuality.Quality, ArtGenerationContext.Colony);
|
||||
}
|
||||
|
||||
Log.Message($"[PA_Debug] Notify_Unequipped: Before spawning building (ID: {building.thingIDNumber}) - HitPoints: {building.HitPoints}, StackCount: {building.stackCount}");
|
||||
|
||||
// Ensure stackCount is at least 1 for buildings, as 0 stackCount causes errors during spawning
|
||||
if (building.stackCount <= 0)
|
||||
{
|
||||
building.stackCount = 1;
|
||||
Log.Warning($"[PA_Debug] Notify_Unequipped: Corrected building (ID: {building.thingIDNumber}) stackCount to 1 as it was 0.");
|
||||
}
|
||||
|
||||
// Set the faction to the pawn's faction before spawning
|
||||
building.SetFaction(pawn.Faction);
|
||||
|
||||
// Re-spawn the original building instance
|
||||
GenPlace.TryPlaceThing(building, pawn.Position, pawn.Map, ThingPlaceMode.Near);
|
||||
Log.Message($"[PA_Debug] Notify_Unequipped: After spawning building (ID: {building.thingIDNumber}) - HitPoints: {building.HitPoints}, StackCount: {building.stackCount}");
|
||||
|
||||
// The destruction is now handled by the Tick() method when it detects Wearer is null.
|
||||
// This is the safest way to implement delayed self-destruction.
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Damage Handling - THE FINAL, CORRECT IMPLEMENTATION
|
||||
#region 伤害处理
|
||||
public override bool CheckPreAbsorbDamage(DamageInfo dinfo)
|
||||
{
|
||||
if (this.Wearer == null || !dinfo.Def.harmsHealth || dinfo.Amount <= 0.001f)
|
||||
@@ -267,7 +528,7 @@ namespace ArachnaeSwarm
|
||||
|
||||
if (this.StructurePoints <= 0)
|
||||
{
|
||||
Messages.Message("PowerArmorBroken".Translate(this.Label, this.Wearer.LabelShort), this, MessageTypeDefOf.NegativeEvent);
|
||||
Messages.Message(ARA_Translations.PowerArmorDamaged.Translate(this.Label, this.Wearer.LabelShort), this, MessageTypeDefOf.NegativeEvent);
|
||||
this.Destroy(DestroyMode.KillFinalize);
|
||||
}
|
||||
}
|
||||
@@ -276,7 +537,7 @@ namespace ArachnaeSwarm
|
||||
EffecterDefOf.Deflect_Metal_Bullet.SpawnAttached(this.Wearer, this.Wearer.Map, 1f);
|
||||
}
|
||||
|
||||
// By returning true, we tell the game the damage has been fully handled and should not proceed to the pawn.
|
||||
// 返回true表示伤害已被完全处理,不应继续传递给pawn
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -310,4 +571,4 @@ namespace ArachnaeSwarm
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,80 +20,167 @@ namespace ArachnaeSwarm
|
||||
this.FailOnDespawnedNullOrForbidden(BuildingInd);
|
||||
this.FailOnSomeonePhysicallyInteracting(BuildingInd);
|
||||
|
||||
// 第一步:移动到动力装甲站
|
||||
yield return Toils_Goto.GotoThing(BuildingInd, PathEndMode.InteractionCell);
|
||||
|
||||
// 第二步:等待装备过程(120 ticks = 2秒)
|
||||
yield return Toils_General.Wait(120, BuildingInd).WithProgressBarToilDelay(BuildingInd);
|
||||
|
||||
// 第三步:执行装备动力装甲
|
||||
Toil enter = new Toil();
|
||||
enter.initAction = () =>
|
||||
{
|
||||
Pawn actor = enter.actor;
|
||||
var building = (Building)actor.CurJob.GetTarget(BuildingInd).Thing;
|
||||
|
||||
// Get the CompProperties from the building's new component
|
||||
// 获取动力装甲站的组件属性
|
||||
var compProps = building.GetComp<CompPowerArmorStation>()?.Props;
|
||||
if (compProps != null && compProps.apparelDef != null)
|
||||
{
|
||||
// Create the apparel
|
||||
// 创建动力装甲装备
|
||||
ARA_PowerArmor apparel = (ARA_PowerArmor)ThingMaker.MakeThing(compProps.apparelDef);
|
||||
|
||||
// CRITICAL STEP: Link the apparel back to the building
|
||||
// 关键步骤:将装备链接回建筑
|
||||
apparel.sourceBuilding = building;
|
||||
|
||||
// Sync health from building to apparel
|
||||
// 从建筑同步健康值到装备
|
||||
apparel.StructurePoints = building.HitPoints;
|
||||
|
||||
// Sync fuel from building to apparel
|
||||
// 从建筑同步燃料到装备
|
||||
var buildingFuelComp = building.GetComp<CompRefuelableNutrition>();
|
||||
var apparelFuelComp = apparel.GetComp<CompRefuelableNutrition>();
|
||||
if (buildingFuelComp != null && apparelFuelComp != null)
|
||||
{
|
||||
// 重置装备燃料并同步建筑燃料
|
||||
apparelFuelComp.ConsumeFuel(apparelFuelComp.Fuel); // 先清空
|
||||
apparelFuelComp.ReceiveFuel(buildingFuelComp.Fuel);
|
||||
Log.Message($"[PA_Debug] 同步燃料: 建筑 {buildingFuelComp.Fuel} -> 装备 {apparelFuelComp.Fuel}");
|
||||
}
|
||||
|
||||
// Sync quality
|
||||
if (building.TryGetComp<CompQuality>() is CompQuality buildingQuality && apparel.TryGetComp<CompQuality>() is CompQuality apparelQuality)
|
||||
// 同步质量
|
||||
if (building.TryGetComp<CompQuality>() is CompQuality buildingQuality &&
|
||||
apparel.TryGetComp<CompQuality>() is CompQuality apparelQuality)
|
||||
{
|
||||
apparelQuality.SetQuality(buildingQuality.Quality, ArtGenerationContext.Colony);
|
||||
Log.Message($"[PA_Debug] 同步质量: {buildingQuality.Quality}");
|
||||
}
|
||||
|
||||
// Wear the apparel. The second argument 'false' is lockWhileWorn.
|
||||
// The third argument 'false' is playerForced, which is CRITICAL.
|
||||
// If playerForced is true, the game automatically locks the apparel.
|
||||
actor.apparel.Wear(apparel, false, false);
|
||||
|
||||
// Handle weapon switching
|
||||
if (apparel.Ext.powerArmorWeapon != null)
|
||||
// 保存原始武器(如果有)
|
||||
ThingWithComps originalWeapon = actor.equipment?.Primary;
|
||||
if (originalWeapon != null)
|
||||
{
|
||||
if (actor.equipment.Primary != null)
|
||||
{
|
||||
apparel.SetOriginalWeapon(actor.equipment.Primary);
|
||||
actor.equipment.TryDropEquipment(actor.equipment.Primary, out _, actor.Position, false);
|
||||
}
|
||||
|
||||
ThingWithComps weapon = (ThingWithComps)ThingMaker.MakeThing(apparel.Ext.powerArmorWeapon);
|
||||
|
||||
// Sync weapon quality with armor quality
|
||||
if (apparel.TryGetComp<CompQuality>() is CompQuality existingApparelQuality && weapon.TryGetComp<CompQuality>() is CompQuality weaponQuality)
|
||||
{
|
||||
weaponQuality.SetQuality(existingApparelQuality.Quality, ArtGenerationContext.Colony);
|
||||
}
|
||||
|
||||
actor.equipment.MakeRoomFor(weapon);
|
||||
actor.equipment.AddEquipment(weapon);
|
||||
// Track the power armor weapon so it can be destroyed later
|
||||
apparel.SetCurrentPowerArmorWeapon(weapon);
|
||||
apparel.SetOriginalWeapon(originalWeapon);
|
||||
Log.Message($"[PA_Debug] 保存原始武器: {originalWeapon.Label}");
|
||||
}
|
||||
|
||||
// Despawn the building
|
||||
// 获取动力装甲扩展和默认武装方案
|
||||
var powerArmorExt = apparel.Ext;
|
||||
PowerArmorWeaponSet defaultSet = null;
|
||||
|
||||
// 确定要使用的武装方案
|
||||
if (powerArmorExt?.weaponSets != null && powerArmorExt.weaponSets.Count > 0)
|
||||
{
|
||||
// 使用默认方案索引,确保在有效范围内
|
||||
int defaultIndex = powerArmorExt.defaultWeaponSetIndex;
|
||||
if (defaultIndex < 0 || defaultIndex >= powerArmorExt.weaponSets.Count)
|
||||
{
|
||||
defaultIndex = 0; // 回退到第一个方案
|
||||
}
|
||||
|
||||
defaultSet = powerArmorExt.weaponSets[defaultIndex];
|
||||
Log.Message($"[PA_Debug] 使用武装方案: {defaultSet?.label ?? "无方案"} (索引: {defaultIndex})");
|
||||
|
||||
// 如果默认方案有武器,需要卸下原始武器
|
||||
if (defaultSet?.weapon != null && originalWeapon != null)
|
||||
{
|
||||
// 卸下原始武器,为动力装甲武器腾出位置
|
||||
if (actor.equipment.Contains(originalWeapon))
|
||||
{
|
||||
actor.equipment.Remove(originalWeapon);
|
||||
Log.Message($"[PA_Debug] 卸下原始武器: {originalWeapon.Label}");
|
||||
}
|
||||
|
||||
// 创建并装备动力装甲武器
|
||||
ThingWithComps powerArmorWeapon = (ThingWithComps)ThingMaker.MakeThing(defaultSet.weapon);
|
||||
|
||||
// 同步武器质量与装甲质量
|
||||
if (apparel.TryGetComp<CompQuality>() is CompQuality existingApparelQuality &&
|
||||
powerArmorWeapon.TryGetComp<CompQuality>() is CompQuality weaponQuality)
|
||||
{
|
||||
weaponQuality.SetQuality(existingApparelQuality.Quality, ArtGenerationContext.Colony);
|
||||
}
|
||||
|
||||
// 装备动力装甲武器
|
||||
actor.equipment.MakeRoomFor(powerArmorWeapon);
|
||||
actor.equipment.AddEquipment(powerArmorWeapon);
|
||||
apparel.SetCurrentPowerArmorWeapon(powerArmorWeapon);
|
||||
|
||||
Log.Message($"[PA_Debug] 装备动力装甲武器: {powerArmorWeapon.Label}");
|
||||
}
|
||||
// 如果默认方案没有武器,但原始武器存在,保留原始武器
|
||||
else if (originalWeapon != null)
|
||||
{
|
||||
Log.Message($"[PA_Debug] 默认方案无武器,保留原始武器: {originalWeapon.Label}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Message($"[PA_Debug] 无武装方案配置,使用原有逻辑");
|
||||
|
||||
// 如果没有武装方案配置,就不进行武器切换
|
||||
// 保留殖民者的原始武器
|
||||
if (originalWeapon != null)
|
||||
{
|
||||
Log.Message($"[PA_Debug] 无武装方案,保留原始武器: {originalWeapon.Label}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Message($"[PA_Debug] 无武装方案,且无原始武器");
|
||||
}
|
||||
}
|
||||
|
||||
// 穿戴装备
|
||||
// 第三个参数 'false' 是 playerForced,这很关键
|
||||
// 如果 playerForced 为 true,游戏会自动锁定装备
|
||||
actor.apparel.Wear(apparel, false, false);
|
||||
Log.Message($"[PA_Debug] 成功穿戴动力装甲: {apparel.Label}");
|
||||
|
||||
// 销毁建筑
|
||||
building.DeSpawn();
|
||||
Log.Message($"[PA_Debug] 销毁动力装甲站建筑");
|
||||
|
||||
// 显示成功消息
|
||||
Messages.Message($"{actor.LabelShort} 已装备{apparel.Label}", actor, MessageTypeDefOf.PositiveEvent);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Error($"[ArachnaeSwarm] Power Armor Building {building.def.defName} is missing CompProperties_PowerArmorStation or apparelDef.");
|
||||
Log.Error($"[ArachnaeSwarm] 动力装甲建筑 {building.def.defName} 缺少 CompProperties_PowerArmorStation 或 apparelDef。");
|
||||
|
||||
// 显示错误消息
|
||||
Messages.Message("装备动力装甲失败:配置错误", actor, MessageTypeDefOf.NegativeEvent);
|
||||
}
|
||||
};
|
||||
|
||||
enter.defaultCompleteMode = ToilCompleteMode.Instant;
|
||||
yield return enter;
|
||||
}
|
||||
|
||||
// 添加失败处理
|
||||
public override string GetReport()
|
||||
{
|
||||
return "正在装备动力装甲...";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 可选的:为动力装甲站添加工作定义
|
||||
[DefOf]
|
||||
public static class JobDefOf_ARA
|
||||
{
|
||||
public static JobDef ARA_EnterPowerArmor;
|
||||
|
||||
static JobDefOf_ARA()
|
||||
{
|
||||
DefOfHelper.EnsureInitializedInCtor(typeof(JobDefOf_ARA));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,4 +79,24 @@ namespace ArachnaeSwarm
|
||||
disappearsComp?.ResetElapsedTicks();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 新增补丁:为 Verb_ShootBeamExplosive 添加支持
|
||||
[HarmonyPatch(typeof(Verb_ShootBeamExplosive), "TryCastShot")]
|
||||
public static class Patch_Verb_ShootBeamExplosive_TryCastShot
|
||||
{
|
||||
public static void Postfix(Verb_ShootBeamExplosive __instance, bool __result)
|
||||
{
|
||||
if (!__result) return;
|
||||
if (__instance.CasterPawn == null || __instance.EquipmentSource == null) return;
|
||||
|
||||
CompGiveHediffOnShot comp = __instance.EquipmentSource.GetComp<CompGiveHediffOnShot>();
|
||||
if (comp == null || comp.Props.hediffDef == null) return;
|
||||
|
||||
Hediff hediff = __instance.CasterPawn.health.GetOrAddHediff(comp.Props.hediffDef);
|
||||
hediff.Severity += comp.Props.severityToAdd;
|
||||
|
||||
var disappearsComp = hediff.TryGetComp<HediffComp_Disappears>();
|
||||
disappearsComp?.ResetElapsedTicks();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user