diff --git a/1.6/1.6/Defs/HediffDefs/ARA_PowerArmor_Hediffs.xml b/1.6/1.6/Defs/HediffDefs/ARA_PowerArmor_Hediffs.xml new file mode 100644 index 0000000..29f2558 --- /dev/null +++ b/1.6/1.6/Defs/HediffDefs/ARA_PowerArmor_Hediffs.xml @@ -0,0 +1,24 @@ + + + + + ARA_PowerArmor_NoFuel + + 生物外骨骼因缺少养分而营养不良,这会对宿主造成不良影响. + HediffWithComps + (0.6, 0.6, 0.6) + true + false + +
  • + +
  • + Moving + -0.4 +
  • + + +
    +
    + +
    \ No newline at end of file diff --git a/1.6/1.6/Defs/JobDefs/ARA_Jobs.xml b/1.6/1.6/Defs/JobDefs/ARA_Jobs.xml index 2083d1a..76740e7 100644 --- a/1.6/1.6/Defs/JobDefs/ARA_Jobs.xml +++ b/1.6/1.6/Defs/JobDefs/ARA_Jobs.xml @@ -12,4 +12,11 @@ 将 TargetA 带到 TargetB. false + + + ARA_EnterPowerArmor + ArachnaeSwarm.JobDriver_EnterPowerArmor + entering TargetA. + true + \ No newline at end of file diff --git a/1.6/1.6/Defs/ThingDef_Races/ARA_RaceNodeSwarm.xml b/1.6/1.6/Defs/ThingDef_Races/ARA_RaceNodeSwarm.xml index 1a92a1a..ea45ed8 100644 --- a/1.6/1.6/Defs/ThingDef_Races/ARA_RaceNodeSwarm.xml +++ b/1.6/1.6/Defs/ThingDef_Races/ARA_RaceNodeSwarm.xml @@ -349,6 +349,7 @@
  • ARA_Latex_Catsuit
  • ARA_Pantyhose_Black
  • ARA_Pantyhose_White
  • +
  • ARA_SpiderOne_PowerArmor
  • Apparel_AdvancedHelmet
  • diff --git a/1.6/1.6/Defs/Thing_Misc/ARA_PowerArmor_Defs.xml b/1.6/1.6/Defs/Thing_Misc/ARA_PowerArmor_Defs.xml new file mode 100644 index 0000000..7d26e4d --- /dev/null +++ b/1.6/1.6/Defs/Thing_Misc/ARA_PowerArmor_Defs.xml @@ -0,0 +1,127 @@ + + + + + + ARA_Building_SpiderOne + + 阿拉克涅动力装甲 + + Graphic_Multi + (1,1) + ArachnaeSwarm/Apparel/ARA_Bunny_Girl_Uniform + + Building + Building + PassThroughOnly + 70 + true + 0.5 + false + (1,1) + Misc + true + true + Normal + MapMeshAndRealTime + true + (0,0,-1) + + 500 + 2000 + 50 + 0.5 + + +
  • + ARA_SpiderOne_PowerArmor +
  • +
  • + 10.0 + + +
  • FoodMeals
  • +
  • FoodRaw
  • + + + 1 + 0.5 + true + +
    +
    + + + ARA_SpiderOne_PowerArmor + + 阿拉克涅动力装甲 + + ARA_Cocoon_Cloth_1Stage + + ArachnaeSwarm.ARA_PowerArmor + +
  • + 500 + ARA_Building_SpiderOne + ARA_PowerArmor_NoFuel + 0.5 +
  • +
    + + + ARA_Technology_6DIL + UnfinishedArmor + + + 25 + + + ArachnaeSwarm/Apparel/ARA_Bunny_Girl_Uniform + + + +
  • Torso
  • +
  • Shoulders
  • +
  • Arms
  • +
  • Legs
  • +
    + + +
  • Middle
  • +
    + ArachnaeSwarm/Apparel/ARA_Bunny_Girl_Uniform +
    + + 120 + 2.5 + + + + 0 + +
  • + ARA_TerrainMoveSpeedHediff +
  • +
  • + +
  • ARA_Cocoon_Cloth_1Stage
  • +
  • ARA_BioforgeIncubator_Thing
  • + + +
  • + 10.0 + + +
  • FoodMeals
  • +
  • FoodRaw
  • + + + 1 + 0.5 + true + true + +
    +
    + +
    \ No newline at end of file diff --git a/1.6/Defs/Thing_Misc/ARA_PowerArmor_Defs.xml b/1.6/Defs/Thing_Misc/ARA_PowerArmor_Defs.xml new file mode 100644 index 0000000..cac9984 --- /dev/null +++ b/1.6/Defs/Thing_Misc/ARA_PowerArmor_Defs.xml @@ -0,0 +1,133 @@ + + + + + + Building + + Graphic_Multi + (3,3) + + Building + PassThroughOnly + 70 + true + 0.5 + false + (2,2) + Misc + true + true + Never + MapMeshAndRealTime + + 250 + 2000 + 50 + 0.5 + + + + + + ArachnaeSwarm.ARA_PowerArmor + + 2 + + + 250 + 30 + 0 + 0.85 + 0.80 + 0.90 + 40 + 20 + + + -0.5 + + + +
  • Torso
  • +
  • Neck
  • +
  • Shoulders
  • +
  • Arms
  • +
  • Legs
  • +
    + +
  • Shell
  • +
  • Middle
  • +
    + false +
    +
    + + + + + + ARA_Apparel_SpiderOne + + A prototype power armor with an arachnid design. + + Things/Pawn/Humanlike/Apparel/SpiderArmor/SpiderArmor + + +
  • + ARA_Building_SpiderOne + 625 + ARA_PowerArmor_NoFuel + 0.5 +
  • +
    + +
  • + 10.0 + + +
  • Meat_Human
  • + + +
  • FoodMeals
  • +
  • FoodRaw
  • +
    + + 1 + 0.5 + true + true + +
    +
    + + + ARA_Building_SpiderOne + + A stationary housing for the Spider-I Power Armor. + + Things/Building/PowerArmorStation + + +
  • + ARA_Apparel_SpiderOne +
  • +
  • + 10.0 + + +
  • Meat_Human
  • + + +
  • FoodMeals
  • +
  • FoodRaw
  • +
    + + 1 + 0.5 + true + +
    +
    + +
    \ No newline at end of file diff --git a/1.6/Languages/English/Keyed/PowerArmor_Keys.xml b/1.6/Languages/English/Keyed/PowerArmor_Keys.xml new file mode 100644 index 0000000..3257089 --- /dev/null +++ b/1.6/Languages/English/Keyed/PowerArmor_Keys.xml @@ -0,0 +1,12 @@ + + + + + Enter {0} + Cannot enter power armor + {0} has been broken! + + + Structure + + \ No newline at end of file diff --git a/Languages/ChineseSimplified/Keyed/PowerArmor_Keys.xml b/Languages/ChineseSimplified/Keyed/PowerArmor_Keys.xml new file mode 100644 index 0000000..73a35af --- /dev/null +++ b/Languages/ChineseSimplified/Keyed/PowerArmor_Keys.xml @@ -0,0 +1,13 @@ + + + + + 进入动力甲 + + + 结构点 + + + {0} 已被摧毁!驾驶员 {1} 被暴露在外。 + + \ No newline at end of file diff --git a/Source/ArachnaeSwarm/ArachnaeSwarm.csproj b/Source/ArachnaeSwarm/ArachnaeSwarm.csproj index 2702294..c5701ac 100644 --- a/Source/ArachnaeSwarm/ArachnaeSwarm.csproj +++ b/Source/ArachnaeSwarm/ArachnaeSwarm.csproj @@ -267,6 +267,12 @@ + + + + + + diff --git a/Source/ArachnaeSwarm/PowerArmor/ARA_PowerArmor.cs b/Source/ArachnaeSwarm/PowerArmor/ARA_PowerArmor.cs new file mode 100644 index 0000000..f30f95b --- /dev/null +++ b/Source/ArachnaeSwarm/PowerArmor/ARA_PowerArmor.cs @@ -0,0 +1,252 @@ +using RimWorld; +using UnityEngine; +using Verse; +using System.Collections.Generic; + +namespace ArachnaeSwarm +{ + public interface IStructurePoints + { + float StructurePoints { get; } + float StructurePointsMax { get; } + float StructurePointsPercent { get; } + string Label { get; } + } + + public class PowerArmorExtension : DefModExtension + { + public ThingDef buildingDef; + public float structurePointsMax = 500f; + public HediffDef hediffOnEmptyFuel; + public float fuelConsumptionRate = 0.5f; // Nutrition per day + } + + [StaticConstructorOnStartup] + public class ARA_PowerArmor : Apparel, IStructurePoints + { + #region Properties + private PowerArmorExtension ext; + public PowerArmorExtension Ext => ext ??= def.GetModExtension(); + public override string Label => base.Label; + + private float structurePoints = -1f; + public float StructurePointsMax => Ext?.structurePointsMax ?? 500f; + + public float StructurePoints + { + get + { + if (structurePoints < 0) + { + structurePoints = StructurePointsMax; + } + return structurePoints; + } + set + { + structurePoints = Mathf.Clamp(value, 0, StructurePointsMax); + } + } + + public float StructurePointsPercent => StructurePoints / StructurePointsMax; + + public Building sourceBuilding; + #endregion + + #region Ticker + protected override void Tick() + { + base.Tick(); // Call Apparel's Tick + + if (this.Wearer == null) return; // Only tick if worn + + var fuelComp = this.GetComp(); + if (fuelComp != null) + { + // Explicitly call the component's Tick method to ensure fuel consumption logic is executed. + // This is needed because Apparel's base Tick does not automatically call component Ticks. + // First, update consumption rate and hediffs + if (this.Wearer.IsHashIntervalTick(60)) // Check every second + { + if (this.Wearer.pather != null && this.Wearer.pather.MovingNow) + { + fuelComp.currentConsumptionRate = Ext?.fuelConsumptionRate ?? 0.5f; + } + else + { + fuelComp.currentConsumptionRate = 0f; + } + + // Handle hediff for empty fuel + var hediffDef = Ext?.hediffOnEmptyFuel; + if (hediffDef != null) + { + var hediff = this.Wearer.health.hediffSet.GetFirstHediffOfDef(hediffDef); + if (!fuelComp.HasFuel) + { + if (hediff == null) + { + this.Wearer.health.AddHediff(hediffDef); + } + } + else + { + if (hediff != null) + { + this.Wearer.health.RemoveHediff(hediff); + } + } + } + } + // Then, explicitly call the component's Tick method to ensure fuel consumption logic is executed with the UPDATED rate. + fuelComp.CompTick(); + } + } // Correctly close the Tick method + #endregion + + #region Data + public override void ExposeData() + { + base.ExposeData(); + Scribe_Values.Look(ref structurePoints, "structurePoints", -1f); + Scribe_References.Look(ref sourceBuilding, "sourceBuilding"); + } + #endregion + + #region Gizmo + public override IEnumerable GetWornGizmos() + { + // Always yield base gizmos first. + foreach (var gizmo in base.GetWornGizmos()) + { + yield return gizmo; + } + + // Yield our custom structure points gizmo. + yield return new Gizmo_StructurePanel(this); + + // Yield our custom fuel panel gizmo. + var fuelComp = this.GetComp(); + if (fuelComp != null) + { + yield return new Gizmo_FuelPanel(fuelComp); + } + } + #endregion + + #region State-Switching + public override void Notify_Unequipped(Pawn pawn) + { + base.Notify_Unequipped(pawn); + + 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(); + var buildingFuelComp = building.GetComp(); + 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); + } + + 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}"); + + // Destroy the apparel to prevent duplication + this.Destroy(DestroyMode.Vanish); + Log.Message($"[PA_Debug] Notify_Unequipped: Apparel {this.Label} (ID: {this.thingIDNumber}) destroyed."); + } + #endregion + + #region Damage Handling - THE FINAL, CORRECT IMPLEMENTATION + public override bool CheckPreAbsorbDamage(DamageInfo dinfo) + { + if (this.Wearer == null || !dinfo.Def.harmsHealth || dinfo.Amount <= 0.001f) + { + return false; + } + + float finalDamage = GetPostArmorDamage(ref dinfo); + + if (finalDamage > 0) + { + this.StructurePoints -= finalDamage; + EffecterDefOf.DamageDiminished_Metal.SpawnAttached(this.Wearer, this.Wearer.Map, 1f); + + if (this.StructurePoints <= 0) + { + Messages.Message("PowerArmorBroken".Translate(this.Label, this.Wearer.LabelShort), this, MessageTypeDefOf.NegativeEvent); + this.Destroy(DestroyMode.KillFinalize); + } + } + else + { + 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. + return true; + } + + private float GetPostArmorDamage(ref DamageInfo dinfo) + { + float amount = dinfo.Amount; + if (dinfo.Def.armorCategory != null) + { + StatDef armorRatingStat = dinfo.Def.armorCategory.armorRatingStat; + float armorRating = this.GetStatValue(armorRatingStat); + + float armorPenetration = dinfo.ArmorPenetrationInt; + float num = Mathf.Max(armorRating - armorPenetration, 0f); + float value = Rand.Value; + float num2 = num * 0.5f; + float num3 = num; + if (value < num2) + { + amount = 0f; + } + else if (value < num3) + { + amount = GenMath.RoundRandom(amount / 2f); + if (dinfo.Def.armorCategory == DamageArmorCategoryDefOf.Sharp) + { + dinfo.Def = DamageDefOf.Blunt; + } + } + } + return amount; + } + #endregion + } +} \ No newline at end of file diff --git a/Source/ArachnaeSwarm/PowerArmor/CompPowerArmorStation.cs b/Source/ArachnaeSwarm/PowerArmor/CompPowerArmorStation.cs new file mode 100644 index 0000000..7515614 --- /dev/null +++ b/Source/ArachnaeSwarm/PowerArmor/CompPowerArmorStation.cs @@ -0,0 +1,20 @@ +using RimWorld; +using Verse; + +namespace ArachnaeSwarm +{ + public class CompProperties_PowerArmorStation : CompProperties + { + public ThingDef apparelDef; + + public CompProperties_PowerArmorStation() + { + compClass = typeof(CompPowerArmorStation); + } + } + + public class CompPowerArmorStation : ThingComp + { + public CompProperties_PowerArmorStation Props => (CompProperties_PowerArmorStation)props; + } +} \ No newline at end of file diff --git a/Source/ArachnaeSwarm/PowerArmor/Gizmo_FuelPanel.cs b/Source/ArachnaeSwarm/PowerArmor/Gizmo_FuelPanel.cs new file mode 100644 index 0000000..ef84748 --- /dev/null +++ b/Source/ArachnaeSwarm/PowerArmor/Gizmo_FuelPanel.cs @@ -0,0 +1,55 @@ +using UnityEngine; +using Verse; +using RimWorld; // For SolidColorMaterials + +namespace ArachnaeSwarm +{ + [StaticConstructorOnStartup] + public class Gizmo_FuelPanel : Gizmo + { + private static readonly Texture2D FullBarTex = SolidColorMaterials.NewSolidColorTexture(new Color(0.9f, 0.7f, 0.2f)); // Orange for fuel + private static readonly Texture2D EmptyBarTex = SolidColorMaterials.NewSolidColorTexture(new Color(0.1f, 0.1f, 0.1f)); + + private CompRefuelableNutrition fuelComp; + + public Gizmo_FuelPanel(CompRefuelableNutrition fuelComp) + { + this.fuelComp = fuelComp; + this.Order = -90f; // Slightly higher order than structure panel + } + + public override float GetWidth(float maxWidth) + { + return 140f; + } + + public override GizmoResult GizmoOnGUI(Vector2 topLeft, float maxWidth, GizmoRenderParms parms) + { + Rect overRect = new Rect(topLeft.x, topLeft.y, GetWidth(maxWidth), 75f); + Find.WindowStack.ImmediateWindow(984989, overRect, WindowLayer.GameUI, delegate + { + Rect rect = overRect.AtZero().ContractedBy(6f); + + // Draw label + Rect labelRect = rect; + labelRect.height = overRect.height / 2f; + Text.Font = GameFont.Tiny; + Widgets.Label(labelRect, "Fuel".Translate()); // Use "Fuel" or custom text + + // Draw bar + Rect barRect = rect; + barRect.yMin = overRect.height / 2f; + float fillPercent = fuelComp.FuelPercentOfMax; + + Widgets.FillableBar(barRect, fillPercent, FullBarTex, EmptyBarTex, false); + + // Draw text on bar + Text.Font = GameFont.Small; + Text.Anchor = TextAnchor.MiddleCenter; + Widgets.Label(barRect, $"{fuelComp.Fuel:F0} / {fuelComp.Props.fuelCapacity:F0}"); + Text.Anchor = TextAnchor.UpperLeft; + }); + return new GizmoResult(GizmoState.Clear); + } + } +} \ No newline at end of file diff --git a/Source/ArachnaeSwarm/PowerArmor/Gizmo_StructurePanel.cs b/Source/ArachnaeSwarm/PowerArmor/Gizmo_StructurePanel.cs new file mode 100644 index 0000000..fc5f566 --- /dev/null +++ b/Source/ArachnaeSwarm/PowerArmor/Gizmo_StructurePanel.cs @@ -0,0 +1,55 @@ +using UnityEngine; +using Verse; + +namespace ArachnaeSwarm +{ + [StaticConstructorOnStartup] + public class Gizmo_StructurePanel : Gizmo + { + private static readonly Texture2D FullBarTex = SolidColorMaterials.NewSolidColorTexture(new Color(0.2f, 0.8f, 0.2f)); + private static readonly Texture2D EmptyBarTex = SolidColorMaterials.NewSolidColorTexture(new Color(0.1f, 0.1f, 0.1f)); + private static readonly Texture2D UnderflowBarTex = SolidColorMaterials.NewSolidColorTexture(new Color(0.9f, 0.1f, 0.1f)); + + private IStructurePoints armor; + + public Gizmo_StructurePanel(IStructurePoints armor) + { + this.armor = armor; + this.Order = -100f; // Correctly use the 'Order' property + } + + public override float GetWidth(float maxWidth) + { + return 140f; + } + + public override GizmoResult GizmoOnGUI(Vector2 topLeft, float maxWidth, GizmoRenderParms parms) + { + Rect overRect = new Rect(topLeft.x, topLeft.y, GetWidth(maxWidth), 75f); + Find.WindowStack.ImmediateWindow(984988, overRect, WindowLayer.GameUI, delegate + { + Rect rect = overRect.AtZero().ContractedBy(6f); + + // Draw label + Rect labelRect = rect; + labelRect.height = overRect.height / 2f; + Text.Font = GameFont.Tiny; + Widgets.Label(labelRect, armor.Label); + + // Draw bar + Rect barRect = rect; + barRect.yMin = overRect.height / 2f; + float fillPercent = armor.StructurePointsPercent; + + Widgets.FillableBar(barRect, fillPercent, FullBarTex, EmptyBarTex, false); + + // Draw text on bar + Text.Font = GameFont.Small; + Text.Anchor = TextAnchor.MiddleCenter; + Widgets.Label(barRect, $"{armor.StructurePoints:F0} / {armor.StructurePointsMax:F0}"); + Text.Anchor = TextAnchor.UpperLeft; + }); + return new GizmoResult(GizmoState.Clear); + } + } +} \ No newline at end of file diff --git a/Source/ArachnaeSwarm/PowerArmor/Harmony_ThingWithComps_GetFloatMenuOptions.cs b/Source/ArachnaeSwarm/PowerArmor/Harmony_ThingWithComps_GetFloatMenuOptions.cs new file mode 100644 index 0000000..0ec7543 --- /dev/null +++ b/Source/ArachnaeSwarm/PowerArmor/Harmony_ThingWithComps_GetFloatMenuOptions.cs @@ -0,0 +1,59 @@ +using HarmonyLib; +using RimWorld; +using System.Collections.Generic; +using Verse; +using Verse.AI; + +namespace ArachnaeSwarm +{ + [HarmonyPatch(typeof(ThingWithComps), "GetFloatMenuOptions")] + public static class Harmony_ThingWithComps_GetFloatMenuOptions + { + [HarmonyPostfix] + public static IEnumerable Postfix(IEnumerable values, ThingWithComps __instance, Pawn selPawn) + { + // First, return all original options + foreach (var value in values) + { + yield return value; + } + + // --- DEBUG LOGGING --- + // Use a more specific check to avoid log spam + if (__instance.def.defName != null && __instance.def.defName.StartsWith("ARA_")) + { + Log.Message($"[PA_Debug] GetFloatMenuOptions Postfix triggered for: {__instance.def.defName}"); + } + + // Check if the thing is our power armor building + var comp = __instance.GetComp(); + + if (comp == null && __instance.def.defName != null && __instance.def.defName.StartsWith("ARA_")) + { + Log.Message($"[PA_Debug] CompPowerArmorStation is NULL for {__instance.def.defName}"); + } + + if (comp != null) + { + Log.Message($"[PA_Debug] CompPowerArmorStation FOUND for {__instance.def.defName}. Checking reachability."); + + // Check if the pawn can interact + if (!selPawn.CanReserveAndReach(__instance, PathEndMode.InteractionCell, Danger.Deadly)) + { + yield return new FloatMenuOption("CannotEnterPowerArmor".Translate() + ": " + "CannotReach".Translate(), null); + } + else + { + // Action to give the job + void enterAction() + { + Job job = JobMaker.MakeJob(DefDatabase.GetNamed("ARA_EnterPowerArmor"), __instance); + selPawn.jobs.TryTakeOrderedJob(job, JobTag.Misc); + } + + yield return new FloatMenuOption("EnterPowerArmor".Translate(__instance.Label), enterAction); + } + } + } + } +} \ No newline at end of file diff --git a/Source/ArachnaeSwarm/PowerArmor/JobDriver_EnterPowerArmor.cs b/Source/ArachnaeSwarm/PowerArmor/JobDriver_EnterPowerArmor.cs new file mode 100644 index 0000000..383fe59 --- /dev/null +++ b/Source/ArachnaeSwarm/PowerArmor/JobDriver_EnterPowerArmor.cs @@ -0,0 +1,68 @@ +using RimWorld; +using System.Collections.Generic; +using Verse; +using Verse.AI; + +namespace ArachnaeSwarm +{ + public class JobDriver_EnterPowerArmor : JobDriver + { + private const TargetIndex BuildingInd = TargetIndex.A; + private Building PowerArmorBuilding => (Building)job.GetTarget(BuildingInd).Thing; + + public override bool TryMakePreToilReservations(bool errorOnFailed) + { + return pawn.Reserve(PowerArmorBuilding, job, 1, -1, null, errorOnFailed); + } + + protected override IEnumerable MakeNewToils() + { + this.FailOnDespawnedNullOrForbidden(BuildingInd); + this.FailOnSomeonePhysicallyInteracting(BuildingInd); + + yield return Toils_Goto.GotoThing(BuildingInd, PathEndMode.InteractionCell); + 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()?.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(); + var apparelFuelComp = apparel.GetComp(); + if (buildingFuelComp != null && apparelFuelComp != null) + { + apparelFuelComp.ReceiveFuel(buildingFuelComp.Fuel); + } + + // Wear the apparel + actor.apparel.Wear(apparel, true, true); + + // Despawn the building + building.DeSpawn(); + } + else + { + Log.Error($"[ArachnaeSwarm] Power Armor Building {building.def.defName} is missing CompProperties_PowerArmorStation or apparelDef."); + } + }; + enter.defaultCompleteMode = ToilCompleteMode.Instant; + yield return enter; + } + } +} \ No newline at end of file