diff --git a/1.6/1.6/Assemblies/ArachnaeSwarm.dll b/1.6/1.6/Assemblies/ArachnaeSwarm.dll index 4dc662f..e90b4a1 100644 Binary files a/1.6/1.6/Assemblies/ArachnaeSwarm.dll and b/1.6/1.6/Assemblies/ArachnaeSwarm.dll differ diff --git a/1.6/1.6/Defs/Thing_building/ARA_HiveShip.xml b/1.6/1.6/Defs/Thing_building/ARA_HiveShip.xml index a1c5279..61d6189 100644 --- a/1.6/1.6/Defs/Thing_building/ARA_HiveShip.xml +++ b/1.6/1.6/Defs/Thing_building/ARA_HiveShip.xml @@ -3,15 +3,16 @@ ARA_HiveShip_Heart - 一艘阿拉克涅虫群猎手虫巢舰的心脏。其功能和人类的逆重引擎类似 + 一艘阿拉克涅虫群猎手虫巢舰的心脏,其功能和人类的逆重引擎类似。 ArachnaeSwarm.Building_ArachnaeGravEngine RealtimeOnly Normal MinifiedThing + ArachnaeSwarm/Building/ARA_HiveShip_Heart_Icon Graphic_Single - Things/Building/GravEngine/GravEngine - (3,3) + ArachnaeSwarm/Building/ARA_HiveShip_Heart_Pedestal + (3.25,3.25) true @@ -24,17 +25,15 @@
  • - UI/Commands/ArachnaeInspect - Things/Building/ArachnaeGravEngine/ArachnaeGravEngine_Orb - Things/Building/ArachnaeGravEngine/ArachnaeGravEngine_Cooldown - UI/Icons/ArachnaeSwarm + UI/Commands/Inspect + ArachnaeSwarm/Building/ARA_HiveShip_Heart + ArachnaeSwarm/Building/ARA_HiveShip_Heart
  • (3,3) true 0.6 - PassThroughOnly - 20 + Impassable false true @@ -48,20 +47,18 @@
  • - 18.9 + 30
  • 8 - (0,218,255,0) + (199,136,114,0)
  • -
  • GravFieldExtender
  • -
  • PilotConsole
  • -
  • ChemfuelTank
  • -
  • LargeChemfuelTank
  • -
  • SmallThruster
  • -
  • LargeThruster
  • +
  • GravFieldExtender
  • +
  • PilotConsole
  • +
  • ARA_HiveShip_Stomach
  • +
  • ARA_HiveShip_Tail
  • FuelOptimizer
  • SignalJammer
  • PilotSubpersonaCore
  • @@ -73,4 +70,114 @@
    + + ARA_HiveShip_Stomach + + 阿拉克涅虫群猎手虫巢舰的胃囊,它可以储存供虫巢舰进行移动的生物质。 + + Graphic_Multi + Things/Building/ChemfuelTank/ChemfuelTank + (2, 2) + + + 200 + 30 + 1 + -10 + 2000 + + (2, 2) + + 120 + + +
  • BasicGravtech
  • +
    + +
  • + 250 + true + 250 + + +
  • Chemfuel
  • + + + Chemfuel + Chemfuel + true + 1 + true + false + true + true + false + +
    +
    + + ARA_HiveShip_Tail + + A chemfuel thruster that increases the range of a gravship. Thrusters require an unobstructed area free of large buildings and gravship substructure.\n\nA gravship can support up to four small thrusters. + + Graphic_Multi + Things/Building/SmallThruster/SmallThruster + (1.1, 2.2) + + (1, 1, 2) + + + + 250 + 0 + -10 + 10000 + 20 + + (1, 2) + 4 + + 180 + 4 + + +
  • BasicGravtech
  • +
    + +
  • + + 10 + + Thruster + (1, 0, 5) + (0, 0, -5) + 20 + 4.0 + +
  • (0, 0, 0.5)
  • +
  • (0, 0, 0.5)
  • +
  • (0, 0, 0.5)
  • +
  • (0, 0, 0.5)
  • + + MoteGlow + + <_MainTex>/Things/Mote/SmallThruster_Burn + + false + 4 + 500 + + GravshipThrusterExhaust + 40.0 + 0.0~0.5 + (0.0,0.0,-20.0) + -10.0~10.0 + 0.8~1.2 + -180.0~180.0 + 1.5~3.0 + + +
  • + + \ No newline at end of file diff --git a/Content/Textures/ArachnaeSwarm/Building/ARA_HiveShip_Heart.png b/Content/Textures/ArachnaeSwarm/Building/ARA_HiveShip_Heart.png new file mode 100644 index 0000000..9098272 Binary files /dev/null and b/Content/Textures/ArachnaeSwarm/Building/ARA_HiveShip_Heart.png differ diff --git a/Content/Textures/ArachnaeSwarm/Building/ARA_HiveShip_Heart_Cooldown.png b/Content/Textures/ArachnaeSwarm/Building/ARA_HiveShip_Heart_Cooldown.png new file mode 100644 index 0000000..9098272 Binary files /dev/null and b/Content/Textures/ArachnaeSwarm/Building/ARA_HiveShip_Heart_Cooldown.png differ diff --git a/Content/Textures/ArachnaeSwarm/Building/ARA_HiveShip_Heart_Icon.png b/Content/Textures/ArachnaeSwarm/Building/ARA_HiveShip_Heart_Icon.png new file mode 100644 index 0000000..215ebdb Binary files /dev/null and b/Content/Textures/ArachnaeSwarm/Building/ARA_HiveShip_Heart_Icon.png differ diff --git a/Content/Textures/ArachnaeSwarm/Building/ARA_HiveShip_Heart_Pedestal.png b/Content/Textures/ArachnaeSwarm/Building/ARA_HiveShip_Heart_Pedestal.png new file mode 100644 index 0000000..bdc47e0 Binary files /dev/null and b/Content/Textures/ArachnaeSwarm/Building/ARA_HiveShip_Heart_Pedestal.png differ diff --git a/Source/ArachnaeSwarm/.vs/ArachnaeSwarm/v17/.suo b/Source/ArachnaeSwarm/.vs/ArachnaeSwarm/v17/.suo index 61921df..b0d8646 100644 Binary files a/Source/ArachnaeSwarm/.vs/ArachnaeSwarm/v17/.suo and b/Source/ArachnaeSwarm/.vs/ArachnaeSwarm/v17/.suo differ diff --git a/Source/ArachnaeSwarm/.vs/ArachnaeSwarm/v17/DocumentLayout.json b/Source/ArachnaeSwarm/.vs/ArachnaeSwarm/v17/DocumentLayout.json index f7dbf27..581d4ba 100644 --- a/Source/ArachnaeSwarm/.vs/ArachnaeSwarm/v17/DocumentLayout.json +++ b/Source/ArachnaeSwarm/.vs/ArachnaeSwarm/v17/DocumentLayout.json @@ -1,25 +1,17 @@ { "Version": 1, - "WorkspaceRootPath": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\", + "WorkspaceRootPath": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\", "Documents": [ { - "AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|e:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\buildings\\building_arachnaegravengine.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\\buildings\\building_arachnaegravengine.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", "RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:buildings\\building_arachnaegravengine.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_spawnpawnfromlist\\compspawnpawnfromlist.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", - "RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:building_comps\\ara_spawnpawnfromlist\\compspawnpawnfromlist.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_spawnpawnfromlist\\compproperties_spawnpawnfromlist.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", - "RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:building_comps\\ara_spawnpawnfromlist\\compproperties_spawnpawnfromlist.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" - }, - { - "AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\hediffs\\ara_hediffterrainspawn\\comphediffterrainspawn.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\\ara_hediffterrainspawn\\comphediffterrainspawn.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", "RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:hediffs\\ara_hediffterrainspawn\\comphediffterrainspawn.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\\compabilityeffect_randomhediff.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\\compabilityeffect_randomhediff.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", "RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:abilities\\compabilityeffect_randomhediff.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" } ], @@ -40,59 +32,35 @@ "$type": "Document", "DocumentIndex": 0, "Title": "Building_ArachnaeGravEngine.cs", - "DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Buildings\\Building_ArachnaeGravEngine.cs", + "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Buildings\\Building_ArachnaeGravEngine.cs", "RelativeDocumentMoniker": "Buildings\\Building_ArachnaeGravEngine.cs", - "ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Buildings\\Building_ArachnaeGravEngine.cs", + "ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Buildings\\Building_ArachnaeGravEngine.cs", "RelativeToolTip": "Buildings\\Building_ArachnaeGravEngine.cs", - "ViewState": "AgIAAAAAAAAAAAAAAADwvw0AAAAmAAAAAAAAAA==", + "ViewState": "AgIAAK0AAAAAAAAAAAAUwL4AAAANAAAAAAAAAA==", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", - "WhenOpened": "2025-10-23T12:04:20.765Z", + "WhenOpened": "2025-10-24T02:30:45.288Z", "EditorCaption": "" }, { "$type": "Document", "DocumentIndex": 1, - "Title": "CompSpawnPawnFromList.cs", - "DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\ARA_SpawnPawnFromList\\CompSpawnPawnFromList.cs", - "RelativeDocumentMoniker": "Building_Comps\\ARA_SpawnPawnFromList\\CompSpawnPawnFromList.cs", - "ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\ARA_SpawnPawnFromList\\CompSpawnPawnFromList.cs", - "RelativeToolTip": "Building_Comps\\ARA_SpawnPawnFromList\\CompSpawnPawnFromList.cs", - "ViewState": "AgIAAHQAAAAAAAAAAAAgwKAAAAA/AAAAAAAAAA==", + "Title": "CompHediffTerrainSpawn.cs", + "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Hediffs\\ARA_HediffTerrainSpawn\\CompHediffTerrainSpawn.cs", + "RelativeDocumentMoniker": "Hediffs\\ARA_HediffTerrainSpawn\\CompHediffTerrainSpawn.cs", + "ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Hediffs\\ARA_HediffTerrainSpawn\\CompHediffTerrainSpawn.cs", + "RelativeToolTip": "Hediffs\\ARA_HediffTerrainSpawn\\CompHediffTerrainSpawn.cs", + "ViewState": "AgIAAB0AAAAAAAAAAAAswE0AAABHAAAAAAAAAA==", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", - "WhenOpened": "2025-10-23T10:44:55.813Z", + "WhenOpened": "2025-10-23T08:00:28.236Z", "EditorCaption": "" }, { "$type": "Document", "DocumentIndex": 2, - "Title": "CompProperties_SpawnPawnFromList.cs", - "DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\ARA_SpawnPawnFromList\\CompProperties_SpawnPawnFromList.cs", - "RelativeDocumentMoniker": "Building_Comps\\ARA_SpawnPawnFromList\\CompProperties_SpawnPawnFromList.cs", - "ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\ARA_SpawnPawnFromList\\CompProperties_SpawnPawnFromList.cs", - "RelativeToolTip": "Building_Comps\\ARA_SpawnPawnFromList\\CompProperties_SpawnPawnFromList.cs", - "ViewState": "AgIAAAAAAAAAAAAAAADwvwAAAAAAAAAAAAAAAA==", - "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", - "WhenOpened": "2025-10-23T10:44:53.422Z" - }, - { - "$type": "Document", - "DocumentIndex": 3, - "Title": "CompHediffTerrainSpawn.cs", - "DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Hediffs\\ARA_HediffTerrainSpawn\\CompHediffTerrainSpawn.cs", - "RelativeDocumentMoniker": "Hediffs\\ARA_HediffTerrainSpawn\\CompHediffTerrainSpawn.cs", - "ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Hediffs\\ARA_HediffTerrainSpawn\\CompHediffTerrainSpawn.cs", - "RelativeToolTip": "Hediffs\\ARA_HediffTerrainSpawn\\CompHediffTerrainSpawn.cs", - "ViewState": "AgIAAF4AAAAAAAAAAAAAAG4AAAAAAAAAAAAAAA==", - "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", - "WhenOpened": "2025-10-23T08:00:28.236Z" - }, - { - "$type": "Document", - "DocumentIndex": 4, "Title": "CompAbilityEffect_RandomHediff.cs", - "DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\CompAbilityEffect_RandomHediff.cs", + "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\CompAbilityEffect_RandomHediff.cs", "RelativeDocumentMoniker": "Abilities\\CompAbilityEffect_RandomHediff.cs", - "ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\CompAbilityEffect_RandomHediff.cs", + "ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\CompAbilityEffect_RandomHediff.cs", "RelativeToolTip": "Abilities\\CompAbilityEffect_RandomHediff.cs", "ViewState": "AgIAALoAAAAAAAAAAAAqwNcAAAAZAAAAAAAAAA==", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", diff --git a/Source/ArachnaeSwarm/Building_Comps/ARA_Building_RefuelingVat/Building_RefuelingVat.cs b/Source/ArachnaeSwarm/Building_Comps/ARA_Building_RefuelingVat/Building_RefuelingVat.cs index 110c48f..61bd1e4 100644 --- a/Source/ArachnaeSwarm/Building_Comps/ARA_Building_RefuelingVat/Building_RefuelingVat.cs +++ b/Source/ArachnaeSwarm/Building_Comps/ARA_Building_RefuelingVat/Building_RefuelingVat.cs @@ -114,7 +114,8 @@ namespace ArachnaeSwarm { if (selectedPawn != null && innerContainer.Contains(selectedPawn)) { - Notify_PawnRemoved(); + Log.Warning($"RefuelingVat despawned with pawn inside, forcing ejection."); + Finish(); // 使用修改后的Finish方法 } } base.DeSpawn(mode); @@ -172,6 +173,13 @@ namespace ArachnaeSwarm if (base.Working && selectedPawn != null) { + // 检查俘虏是否死亡 - 增加更严格的检查 + if (selectedPawn.Dead || selectedPawn.Destroyed) + { + Finish(); + return; + } + // 酸蚀伤害逻辑 if (pawnTickCounters.TryGetValue(selectedPawn, out int tickCount)) { @@ -195,13 +203,6 @@ namespace ArachnaeSwarm float fuelToAdd = FuelProductionPerTick; RefuelableComp.Refuel(fuelToAdd); } - - // 检查俘虏是否死亡 - if (selectedPawn.Dead) - { - Finish(); - return; - } } } @@ -254,11 +255,61 @@ namespace ArachnaeSwarm private void Finish() { - if (selectedPawn != null && innerContainer.Contains(selectedPawn)) + if (selectedPawn != null) { - Notify_PawnRemoved(); - innerContainer.TryDrop(selectedPawn, InteractionCell, base.Map, ThingPlaceMode.Near, 1, out var _); - OnStop(); + try + { + Notify_PawnRemoved(); + + bool ejected = false; + string ejectionMethod = "None"; + + // 方法1:标准弹出 - 在交互单元格附近 + if (innerContainer.Contains(selectedPawn)) + { + ejected = innerContainer.TryDrop(selectedPawn, InteractionCell, base.Map, ThingPlaceMode.Near, 1, out var _); + if (ejected) ejectionMethod = "Standard"; + } + + // 方法2:尝试随机相邻单元格 + if (!ejected && innerContainer.Contains(selectedPawn)) + { + var adjacentCells = GenAdj.CellsAdjacent8Way(this).Where(c => c.Walkable(base.Map) && c.InBounds(base.Map)).ToList(); + if (adjacentCells.Count > 0) + { + IntVec3 randomCell = adjacentCells.RandomElement(); + ejected = innerContainer.TryDrop(selectedPawn, randomCell, base.Map, ThingPlaceMode.Direct, 1, out var _); + if (ejected) ejectionMethod = "Adjacent"; + } + } + + // 方法3:强制移除 + if (!ejected && innerContainer.Contains(selectedPawn)) + { + Log.Warning($"Forcing removal of dead pawn {selectedPawn} from RefuelingVat"); + innerContainer.Remove(selectedPawn); + GenPlace.TryPlaceThing(selectedPawn, this.Position, base.Map, ThingPlaceMode.Near); + ejected = true; + ejectionMethod = "Forced"; + } + + if (ejected) + { + Log.Message($"Successfully ejected {selectedPawn} using method: {ejectionMethod}"); + } + else + { + Log.Error($"Failed to eject {selectedPawn} from RefuelingVat"); + } + } + catch (Exception ex) + { + Log.Error($"Error during Finish() for {selectedPawn}: {ex}"); + } + finally + { + OnStop(); + } } } @@ -267,6 +318,13 @@ namespace ArachnaeSwarm if (selectedPawn != null) { pawnTickCounters.Remove(selectedPawn); + + // 确保pawn不在容器中 + if (innerContainer.Contains(selectedPawn)) + { + Log.Warning($"Pawn {selectedPawn} still in container during OnStop, forcing removal."); + innerContainer.Remove(selectedPawn); + } } selectedPawn = null; startTick = -1; diff --git a/Source/ArachnaeSwarm/Building_Comps/ARA_NutrientVat/Building_NutrientVat.cs b/Source/ArachnaeSwarm/Building_Comps/ARA_NutrientVat/Building_NutrientVat.cs index 8e2ef16..b1ba301 100644 --- a/Source/ArachnaeSwarm/Building_Comps/ARA_NutrientVat/Building_NutrientVat.cs +++ b/Source/ArachnaeSwarm/Building_Comps/ARA_NutrientVat/Building_NutrientVat.cs @@ -88,6 +88,10 @@ namespace ArachnaeSwarm } } + // 酸蚀伤害间隔(每6000 tick约1/10天) + private const int AcidDamageInterval = 6000; + private Dictionary pawnTickCounters = new Dictionary(); + public override void SpawnSetup(Map map, bool respawningAfterLoad) { base.SpawnSetup(map, respawningAfterLoad); @@ -100,19 +104,13 @@ namespace ArachnaeSwarm { if (selectedPawn != null && innerContainer.Contains(selectedPawn)) { - Notify_PawnRemoved(); + Log.Warning($"NutrientVat despawned with pawn inside, forcing ejection."); + Finish(); // 使用修改后的Finish方法 } } base.DeSpawn(mode); } - //޸ĵ㣺Աʴ˺ - private Dictionary pawnTickCounters = new Dictionary(); - private BodyPartRecord GetRandomBodyPart(Pawn pawn) - { - var parts = pawn.health.hediffSet.GetNotMissingParts().ToList(); - return parts.Count > 0 ? parts.RandomElement() : pawn.RaceProps.body.corePart; - } private void ApplyAcidDamage(Pawn pawn) { try @@ -123,14 +121,14 @@ namespace ArachnaeSwarm DamageInfo acidDamage = new DamageInfo( acidDamageDef, - 3f, // ÿ3˺ - 2f, // ΢״͸ - -1f, // Ƕ + 3f, // 每次3点伤害 + 2f, // 护甲穿透 + -1f, // 随机角度 instigator: null, hitPart: targetPart ); - // Ӧ˺ + // 应用伤害 pawn.TakeDamage(acidDamage); } catch (Exception ex) @@ -138,9 +136,10 @@ namespace ArachnaeSwarm Log.Error($"Error applying acid damage to {pawn}: {ex.Message}"); } } + private BodyPartRecord GetRandomVulnerablePart(Pawn pawn) { - // ѡⲿ岿λ + // 优先选择外部身体部位 var vulnerableParts = pawn.health.hediffSet.GetNotMissingParts() .Where(part => part.depth == BodyPartDepth.Outside && !part.def.conceptual && @@ -164,24 +163,23 @@ namespace ArachnaeSwarm if (base.Working && selectedPawn != null) { - //޸ĵ㣺Աʴ˺ + // 检查俘虏是否死亡 - 增加更严格的检查 + if (selectedPawn.Dead || selectedPawn.Destroyed) + { + Finish(); + return; + } + + // 酸蚀伤害逻辑 if (pawnTickCounters.TryGetValue(selectedPawn, out int tickCount)) { tickCount++; pawnTickCounters[selectedPawn] = tickCount; - if (tickCount >= 6000) + if (tickCount >= AcidDamageInterval) { - DamageInfo acidDamage = new DamageInfo( - DefDatabase.GetNamed("AcidBurn") ?? DamageDefOf.Burn, - 1f, - 100f, // ȫ״͸ - -1f, - instigator: null, - hitPart: GetRandomBodyPart(selectedPawn) - ); - pawnTickCounters[selectedPawn] = 0; ApplyAcidDamage(selectedPawn); + pawnTickCounters[selectedPawn] = 0; } } else @@ -242,24 +240,26 @@ namespace ArachnaeSwarm { return "PawnBiostarving".Translate(pawn.Named("PAWN")); } - //޸ĵ㣺ֹȺԱ - if (pawn.health.hediffSet.HasHediff(ARA_HediffDefOf.ARA_HiveMindMaster) || pawn.health.hediffSet.HasHediff(ARA_HediffDefOf.ARA_HiveMindDrone) || pawn.health.hediffSet.HasHediff(ARA_HediffDefOf.ARA_HiveMindWorker)) + // 禁止置入虫群成员 + if (pawn.health.hediffSet.HasHediff(ARA_HediffDefOf.ARA_HiveMindMaster) || + pawn.health.hediffSet.HasHediff(ARA_HediffDefOf.ARA_HiveMindDrone) || + pawn.health.hediffSet.HasHediff(ARA_HediffDefOf.ARA_HiveMindWorker)) { return "PawnIsHiveMember".Translate(pawn.Named("PAWN")); } - //޸ĵ㣺ֳߡū + // 允许殖民者、囚犯和奴隶 bool isColonist = pawn.IsColonist; bool isPrisoner = pawn.IsPrisonerOfColony; bool isSlave = pawn.IsSlaveOfColony; - // ֳߡū + // 允许殖民者、囚犯或奴隶,但不能是任务寄宿者 return (isColonist || isPrisoner || isSlave) && !pawn.IsQuestLodger(); } public override void TryAcceptPawn(Pawn pawn) { - if (!CanAcceptPawn(pawn)) + if (!CanAcceptPawn(pawn).Accepted) { return; } @@ -269,6 +269,7 @@ namespace ArachnaeSwarm if (innerContainer.TryAddOrTransfer(pawn)) { startTick = Find.TickManager.TicksGame; + pawnTickCounters[pawn] = 0; // 初始化伤害计数器 } if (deselected) { @@ -278,28 +279,143 @@ namespace ArachnaeSwarm private void Finish() { - if (selectedPawn != null && innerContainer.Contains(selectedPawn)) + if (selectedPawn != null) { - Notify_PawnRemoved(); - innerContainer.TryDrop(selectedPawn, InteractionCell, base.Map, ThingPlaceMode.Near, 1, out var _); - OnStop(); + try + { + Notify_PawnRemoved(); + + bool ejected = false; + string ejectionMethod = "None"; + + // 方法1:标准弹出 - 在交互单元格附近 + if (innerContainer.Contains(selectedPawn)) + { + ejected = innerContainer.TryDrop(selectedPawn, InteractionCell, base.Map, ThingPlaceMode.Near, 1, out var _); + if (ejected) ejectionMethod = "Standard"; + } + + // 方法2:尝试随机相邻单元格 + if (!ejected && innerContainer.Contains(selectedPawn)) + { + var adjacentCells = GenAdj.CellsAdjacent8Way(this).Where(c => c.Walkable(base.Map) && c.InBounds(base.Map)).ToList(); + if (adjacentCells.Count > 0) + { + IntVec3 randomCell = adjacentCells.RandomElement(); + ejected = innerContainer.TryDrop(selectedPawn, randomCell, base.Map, ThingPlaceMode.Direct, 1, out var _); + if (ejected) ejectionMethod = "Adjacent"; + } + } + + // 方法3:强制移除 + if (!ejected && innerContainer.Contains(selectedPawn)) + { + Log.Warning($"Forcing removal of pawn {selectedPawn} from NutrientVat"); + innerContainer.Remove(selectedPawn); + GenPlace.TryPlaceThing(selectedPawn, this.Position, base.Map, ThingPlaceMode.Near); + ejected = true; + ejectionMethod = "Forced"; + } + + if (ejected) + { + Log.Message($"Successfully ejected {selectedPawn} using method: {ejectionMethod}"); + } + else + { + Log.Error($"Failed to eject {selectedPawn} from NutrientVat"); + } + } + catch (Exception ex) + { + Log.Error($"Error during Finish() for {selectedPawn}: {ex}"); + } + finally + { + OnStop(); + } } } private void Fail() { - if (selectedPawn != null && innerContainer.Contains(selectedPawn)) + if (selectedPawn != null) { - Notify_PawnRemoved(); - innerContainer.TryDrop(selectedPawn, InteractionCell, base.Map, ThingPlaceMode.Near, 1, out var _); - Hediff firstHediffOfDef = selectedPawn.health.hediffSet.GetFirstHediffOfDef(HediffDefOf.BioStarvation); - selectedPawn.Kill(null, firstHediffOfDef); + try + { + Notify_PawnRemoved(); + + bool ejected = false; + string ejectionMethod = "None"; + + // 方法1:标准弹出 - 在交互单元格附近 + if (innerContainer.Contains(selectedPawn)) + { + ejected = innerContainer.TryDrop(selectedPawn, InteractionCell, base.Map, ThingPlaceMode.Near, 1, out var _); + if (ejected) ejectionMethod = "Standard"; + } + + // 方法2:尝试随机相邻单元格 + if (!ejected && innerContainer.Contains(selectedPawn)) + { + var adjacentCells = GenAdj.CellsAdjacent8Way(this).Where(c => c.Walkable(base.Map) && c.InBounds(base.Map)).ToList(); + if (adjacentCells.Count > 0) + { + IntVec3 randomCell = adjacentCells.RandomElement(); + ejected = innerContainer.TryDrop(selectedPawn, randomCell, base.Map, ThingPlaceMode.Direct, 1, out var _); + if (ejected) ejectionMethod = "Adjacent"; + } + } + + // 方法3:强制移除 + if (!ejected && innerContainer.Contains(selectedPawn)) + { + Log.Warning($"Forcing removal of failed pawn {selectedPawn} from NutrientVat"); + innerContainer.Remove(selectedPawn); + GenPlace.TryPlaceThing(selectedPawn, this.Position, base.Map, ThingPlaceMode.Near); + ejected = true; + ejectionMethod = "Forced"; + } + + if (ejected) + { + Log.Message($"Successfully ejected failed pawn {selectedPawn} using method: {ejectionMethod}"); + // 在成功弹出后杀死俘虏 + Hediff firstHediffOfDef = selectedPawn.health.hediffSet.GetFirstHediffOfDef(HediffDefOf.BioStarvation); + selectedPawn.Kill(null, firstHediffOfDef); + } + else + { + Log.Error($"Failed to eject failed pawn {selectedPawn} from NutrientVat"); + // 即使弹出失败也要杀死俘虏 + Hediff firstHediffOfDef = selectedPawn.health.hediffSet.GetFirstHediffOfDef(HediffDefOf.BioStarvation); + selectedPawn.Kill(null, firstHediffOfDef); + } + } + catch (Exception ex) + { + Log.Error($"Error during Fail() for {selectedPawn}: {ex}"); + } + finally + { + OnStop(); + } } - OnStop(); } private void OnStop() { + if (selectedPawn != null) + { + pawnTickCounters.Remove(selectedPawn); + + // 确保pawn不在容器中 + if (innerContainer.Contains(selectedPawn)) + { + Log.Warning($"Pawn {selectedPawn} still in container during OnStop, forcing removal."); + innerContainer.Remove(selectedPawn); + } + } selectedPawn = null; startTick = -1; if (RefuelableComp != null) @@ -312,22 +428,22 @@ namespace ArachnaeSwarm { // You can add sound effects here if you want, e.g., SoundDefOf.GrowthVat_Open.PlayOneShot(SoundInfo.InMap(this)); } + public override IEnumerable GetGizmos() { - // ԭеĻGizmos + // 原有的基础Gizmos foreach (Gizmo gizmo in base.GetGizmos()) { yield return gizmo; } - // ޸ĵ㣺ɾ˵ if (base.Working) { - // ԭеĹ״̬µGizmos + // 原有的工作状态下的Gizmos } else { - // ԭеѡֳߵIJ + // 原有的选择殖民者的操作 var command_Action = new Command_Action { defaultLabel = "InsertPerson".Translate() + "...", @@ -338,7 +454,7 @@ namespace ArachnaeSwarm List list = new List(); foreach (Pawn p in base.Map.mapPawns.AllPawnsSpawned) { - if ((bool)CanAcceptPawn(p)) + if (CanAcceptPawn(p).Accepted) { list.Add(new FloatMenuOption(p.LabelCap, () => SelectPawn(p), p, Color.white)); } @@ -356,7 +472,7 @@ namespace ArachnaeSwarm } yield return command_Action; - // ָɰ/ūIJ + // 指派搬运囚犯/奴隶的操作 var command_CarryPrisoner = new Command_Action { defaultLabel = "AssignCarryPrisoner".Translate() + "...", @@ -366,10 +482,10 @@ namespace ArachnaeSwarm { List list = new List(); - // ȡпɽܵū + // 获取所有可接受的囚犯和奴隶 foreach (Pawn p in base.Map.mapPawns.AllPawnsSpawned) { - if ((bool)CanAcceptPawn(p) && (p.IsPrisonerOfColony || p.IsSlaveOfColony)) + if (CanAcceptPawn(p).Accepted && (p.IsPrisonerOfColony || p.IsSlaveOfColony)) { list.Add(new FloatMenuOption( p.LabelCap + " (" + (p.IsPrisonerOfColony ? "Prisoner" : "Slave") + ")", @@ -388,9 +504,9 @@ namespace ArachnaeSwarm } }; - // Ƿпõ/ū + // 检查是否有可用的囚犯/奴隶 bool hasPrisonersOrSlaves = base.Map.mapPawns.AllPawnsSpawned - .Any(p => (bool)CanAcceptPawn(p) && (p.IsPrisonerOfColony || p.IsSlaveOfColony)); + .Any(p => CanAcceptPawn(p).Accepted && (p.IsPrisonerOfColony || p.IsSlaveOfColony)); if (!hasPrisonersOrSlaves) { @@ -416,6 +532,13 @@ namespace ArachnaeSwarm string text = ((BiostarvationDailyOffset >= 0f) ? "+" : string.Empty); stringBuilder.AppendLineIfNotEmpty().Append(string.Format("{0}: {1} ({2})", "Biostarvation".Translate(), biostarvation.Severity.ToStringPercent(), "PerDay".Translate(text + BiostarvationDailyOffset.ToStringPercent()))); } + + // 显示酸蚀伤害信息 + if (pawnTickCounters.TryGetValue(selectedPawn, out int tickCount)) + { + float damageProgress = (float)tickCount / AcidDamageInterval; + stringBuilder.AppendLineIfNotEmpty().Append("AcidDamageProgress".Translate() + ": " + damageProgress.ToStringPercent()); + } } else if (selectedPawn != null) { @@ -466,13 +589,14 @@ namespace ArachnaeSwarm TopGraphic.Draw(DrawPos + Altitudes.AltIncVect * 2f, base.Rotation, this); } } + public Job CreateCarryJobForPrisoner(Pawn prisoner, Pawn carrier) { if (prisoner == null || carrier == null) return null; if (!CanAcceptPawn(prisoner).Accepted) return null; - // ˹ + // 创建搬运工作定义 JobDef carryJobDef = DefDatabase.GetNamed("ARA_CarryPrisonerToNutrientVat"); if (carryJobDef == null) return null; @@ -480,16 +604,17 @@ namespace ArachnaeSwarm job.count = 1; return job; } + public IEnumerable GetAvailableCarriers() { foreach (Pawn pawn in base.Map.mapPawns.AllPawnsSpawned) { - // ǷdzȺԱӵARA_HiveMindDrone + // 检查是否是虫群成员 if (pawn.health.hediffSet.HasHediff(ARA_HediffDefOf.ARA_HiveMindDrone) || pawn.health.hediffSet.HasHediff(ARA_HediffDefOf.ARA_HiveMindWorker) || pawn.health.hediffSet.HasHediff(ARA_HediffDefOf.ARA_HiveMindMaster)) { - // ǷܹҲ + // 检查是否能够工作且不是囚犯 if (pawn.workSettings != null && pawn.workSettings.WorkIsActive(WorkTypeDefOf.Hauling) && !pawn.Downed && !pawn.IsPrisoner && pawn.CanReach(this, PathEndMode.InteractionCell, Danger.Some)) { @@ -498,11 +623,12 @@ namespace ArachnaeSwarm } } } + public void AssignCarrierForPrisoner(Pawn prisoner) { if (prisoner == null) return; - // ȡõİ + // 获取可用的搬运者 var availableCarriers = GetAvailableCarriers().ToList(); if (!availableCarriers.Any()) @@ -510,7 +636,7 @@ namespace ArachnaeSwarm Messages.Message("NoAvailableHiveCarriers".Translate(), MessageTypeDefOf.RejectInput); return; } - // ˵ѡ + // 创建浮动菜单选择搬运者 List options = new List(); foreach (Pawn carrier in availableCarriers) @@ -539,5 +665,12 @@ namespace ArachnaeSwarm Messages.Message("NoAvailableCarriers".Translate(), MessageTypeDefOf.RejectInput); } } + + // 保存和加载数据 + public override void ExposeData() + { + base.ExposeData(); + Scribe_Collections.Look(ref pawnTickCounters, "pawnTickCounters", LookMode.Reference, LookMode.Value); + } } -} \ No newline at end of file +} diff --git a/Source/ArachnaeSwarm/Buildings/Building_ArachnaeGravEngine.cs b/Source/ArachnaeSwarm/Buildings/Building_ArachnaeGravEngine.cs index 0180cba..a5f2776 100644 --- a/Source/ArachnaeSwarm/Buildings/Building_ArachnaeGravEngine.cs +++ b/Source/ArachnaeSwarm/Buildings/Building_ArachnaeGravEngine.cs @@ -174,12 +174,22 @@ namespace ArachnaeSwarm Messages.Message("ArachnaeSwarmActivated".Translate(), this, MessageTypeDefOf.PositiveEvent); } - // 重写 DrawAt 方法以使用自定义材质 + // 重写 DrawAt 方法以完全控制绘制过程 protected override void DrawAt(Vector3 drawLoc, bool flip = false) { - base.DrawAt(drawLoc, flip); + // 不调用 base.DrawAt,而是直接绘制建筑主体 + // 复制父类 Building 的 DrawAt 逻辑,但不包括 orb 的绘制 + if (def.graphicData != null) + { + Graphic graphic = Graphic; + if (graphic != null) + { + graphic.Draw(drawLoc, flip ? base.Rotation.Opposite : base.Rotation, this, 0f); + } + } if (base.Spawned) { + // 应用浮动效果(与父类相同) if (Find.TickManager.TicksGame >= cooldownCompleteTick) { // 使用 Mathf 替代 MathF @@ -187,8 +197,8 @@ namespace ArachnaeSwarm } drawLoc.y += 0.03658537f; Vector3 s = new Vector3(def.graphicData.drawSize.x, 1f, def.graphicData.drawSize.y); - - // 使用自定义的球体材质 + + // 只使用自定义的球体材质,不绘制默认 orb Graphics.DrawMesh(MeshPool.plane10Back, Matrix4x4.TRS(drawLoc, base.Rotation.AsQuat, s), CustomOrbMat.Material, 0, null, 0); } } @@ -217,6 +227,5 @@ namespace ArachnaeSwarm public string inspectCommandTexPath; public string orbTexPath; public string cooldownTexPath; - public string swarmIconPath; } } diff --git a/非公开资源/Content/Textures/Building/ARA_HiveShip_Heart.sai2 b/非公开资源/Content/Textures/Building/ARA_HiveShip_Heart.sai2 index 213bc1b..6d13f5f 100644 Binary files a/非公开资源/Content/Textures/Building/ARA_HiveShip_Heart.sai2 and b/非公开资源/Content/Textures/Building/ARA_HiveShip_Heart.sai2 differ