diff --git a/1.6/1.6/Defs/AnimationDefs/ARA_Animations.xml b/1.6/1.6/Defs/AnimationDefs/ARA_Animations.xml index 47dbd28..e9a9b7a 100644 --- a/1.6/1.6/Defs/AnimationDefs/ARA_Animations.xml +++ b/1.6/1.6/Defs/AnimationDefs/ARA_Animations.xml @@ -17,7 +17,7 @@
  • 240 - 3 + 2
  • 540 @@ -25,7 +25,7 @@
  • 780 - -3 + -2
  • 1080 diff --git a/1.6/1.6/Defs/DamageDefs/ARA_Damage_Freeze.xml b/1.6/1.6/Defs/DamageDefs/ARA_Damage_Freeze.xml new file mode 100644 index 0000000..6562cf6 --- /dev/null +++ b/1.6/1.6/Defs/DamageDefs/ARA_Damage_Freeze.xml @@ -0,0 +1,165 @@ + + + + + ARA_Hediff_FrostCoverd_after + + 此人被一片冰霜之云所覆盖。 + (1, 1, 0.8) + HediffWithComps + +
  • + -4 +
  • +
  • + ARA_Damage_Freeze + Explosion_Stun + 3 + true + 5 + 0.10 + 60~120 + ARA_FrostGasCloud + 1 + 1 +
  • +
  • + + + + + + + ARA_CryoShock + + 此人正处于低温休克状态。 + (1, 1, 0.8) + ArachnaeSwarm.HediffCurseFlame + +
  • + -6 +
  • + + +
  • + Stun + 1~2 + 80 +
  • +
    + + 0.02 + + +
  • + + true +
  • +
  • + + 0.2 + + 40 + + +
  • + Consciousness + -0.10 +
  • + + +
  • + + 0.35 + + 80 + + +
  • + Consciousness + -0.20 +
  • + + +
  • + + 0.5 + + 120 + + +
  • + Consciousness + -0.20 +
  • + + +
  • + + 0.65 + + 160 + + +
  • + Consciousness + -0.30 +
  • + + +
  • + + 0.85 + + 200 + + +
  • + Consciousness + -0.30 +
  • + + +
    + + + + + ARA_Damage_Freeze + + DamageWorker_Frostbite + true + {0}的身体在极寒中化为了冰雕,随后碎裂四散。 + Frostbite + false + Heat + 0 + 3 + 0 + 0 + 0 + -15 + ARA_BlastFrost + (0.52, 0.7, 0.95,0.5) + (0.52, 1, 0.95,0.5) + Explosion_Stun + + + + + ARA_Damage_Freeze_ex + +
  • + ARA_CryoShock + 0.01 +
  • +
  • + ARA_Hediff_FrostCoverd_after + 0.01 + true + true +
  • +
    +
    + + \ No newline at end of file diff --git a/1.6/1.6/Defs/Effects/ARA_Flecks.xml b/1.6/1.6/Defs/Effects/ARA_Flecks.xml index 9031799..a1bcae3 100644 --- a/1.6/1.6/Defs/Effects/ARA_Flecks.xml +++ b/1.6/1.6/Defs/Effects/ARA_Flecks.xml @@ -12,4 +12,16 @@ MoteGlow + + + ARA_BlastFrost + + ArachnaeSwarm/Mote/BlastFrost + TransparentPostLight + true + + MoteOverhead + 0 + 0.2 + \ No newline at end of file diff --git a/1.6/1.6/Defs/HediffDefs/ARA_PowerArmor_Hediffs.xml b/1.6/1.6/Defs/HediffDefs/ARA_PowerArmor_Hediffs.xml index 29f2558..70f21ac 100644 --- a/1.6/1.6/Defs/HediffDefs/ARA_PowerArmor_Hediffs.xml +++ b/1.6/1.6/Defs/HediffDefs/ARA_PowerArmor_Hediffs.xml @@ -14,7 +14,7 @@
  • Moving - -0.4 + -0.5
  • diff --git a/1.6/1.6/Defs/Thing_Misc/ARA_Things_Gas.xml b/1.6/1.6/Defs/Thing_Misc/ARA_Things_Gas.xml index 6cb81c8..433afbf 100644 --- a/1.6/1.6/Defs/Thing_Misc/ARA_Things_Gas.xml +++ b/1.6/1.6/Defs/Thing_Misc/ARA_Things_Gas.xml @@ -41,31 +41,86 @@ - - ARA_AcidGasCloud - - - Things/Gas/Puff - 2.6 - (0.56, 1, 0.03,0.5) - - - - 30 - 50 - - - 20 - - ArachnaeSwarm.OPToxicGas - -
  • - ARA_AcidCoverd - 0.1 - 240 -
  • -
    -
    + 20 + + ArachnaeSwarm.OPToxicGas + +
  • + ARA_AcidCoverd + 0.1 + 240 +
  • +
    + + + + + ARA_FrostGasCloud_Ex + + + Things/Gas/Puff + 2.6 + (0.52, 1, 0.95,0.5) + + + + 5 + 10 + + + 5 + + ArachnaeSwarm.OPToxicGas + +
  • + ARA_Hediff_FrostCoverd_after + 0.1 + 240 +
  • +
    +
    + + + ARA_FrostGasCloud + + + Things/Gas/Puff + 2.6 + (0.52, 1, 0.95,0.5) + + + + 5 + 10 + + + 5 + + ArachnaeSwarm.OPToxicGas + +
  • + ARA_CryoShock + 0.1 + 240 +
  • +
    +
    \ No newline at end of file diff --git a/1.6/1.6/Defs/Thing_Misc/ARA_PowerArmor_Defs.xml b/1.6/1.6/Defs/Thing_Misc/Apparels/ARA_PowerArmor.xml similarity index 90% rename from 1.6/1.6/Defs/Thing_Misc/ARA_PowerArmor_Defs.xml rename to 1.6/1.6/Defs/Thing_Misc/Apparels/ARA_PowerArmor.xml index cbf1f62..dcafeb8 100644 --- a/1.6/1.6/Defs/Thing_Misc/ARA_PowerArmor_Defs.xml +++ b/1.6/1.6/Defs/Thing_Misc/Apparels/ARA_PowerArmor.xml @@ -37,13 +37,13 @@ ARA_SpiderOne_PowerArmor
  • - 10.0 + 100.0 - -
  • FoodMeals
  • -
  • FoodRaw
  • - + +
  • ARA_InsectJelly
  • +
    + 虫蜜 1 0.5 true @@ -66,6 +66,7 @@ ARA_Building_SpiderOne ARA_PowerArmor_NoFuel 0.5 + ARA_RW_Icez_Mortar_Turretgun @@ -110,13 +111,14 @@
  • - 10.0 + true + 100.0 - -
  • FoodMeals
  • -
  • FoodRaw
  • - + +
  • ARA_InsectJelly
  • +
    + 虫蜜 1 0.5 true diff --git a/1.6/1.6/Defs/Thing_Misc/Weapons/ARA_Weapon.xml b/1.6/1.6/Defs/Thing_Misc/Weapons/ARA_Weapon.xml index d597f05..7d99a6d 100644 --- a/1.6/1.6/Defs/Thing_Misc/Weapons/ARA_Weapon.xml +++ b/1.6/1.6/Defs/Thing_Misc/Weapons/ARA_Weapon.xml @@ -1103,7 +1103,7 @@ true false 5 - 120 + 80 1 SpitterSpit diff --git a/1.6/1.6/Defs/Thing_Misc/Weapons/ARA_Weapon_Icez.xml b/1.6/1.6/Defs/Thing_Misc/Weapons/ARA_Weapon_Icez.xml new file mode 100644 index 0000000..c408bb2 --- /dev/null +++ b/1.6/1.6/Defs/Thing_Misc/Weapons/ARA_Weapon_Icez.xml @@ -0,0 +1,127 @@ + + + + ARA_RW_Icez_Mortar + + 阿拉克涅虫群督虫使用大型远程武装器官,可以发射极度冰冷的霜冻气团,被接触到的敌人会产生霜冻爆炸,一旦被冻结不会立即致死,但随之而来的任何外来伤害都会立刻摧毁脆弱的冰雕。 + Normal + Animal + + ARA_Cocoon_Weapon_2Stage + + + ArachnaeSwarm/Weapon/ARA_RW_Acid_Mortar + Graphic_Single + 1.5 + + 0.75 + SpitterSpawn + + + ARA_Technology_9VXI + UnfinishedWeapon + + + 2500 + 1300 + + 3.5 + 0.3 + 0.3 + 0.25 + 0.1 + 3.5 + 450 + 15 + + +
  • + Verb_Shoot + true + false + 1.5 + 3 + Bullet_ARA_RW_Icez_Mortar + false + false + 5 + 49 + 1 + SpitterSpit + + true + +
  • +
    + + 50 + + +
  • ARA_Armed_Organ
  • +
  • ARA_Armed_Organ_Ranged
  • +
  • ARA_Armed_Organ_T2
  • +
    + 0 + None + + +
  • + +
  • ARA_Cocoon_Weapon_2Stage
  • +
  • ARA_BioforgeIncubator_Thing
  • + + +
  • + +
  • ARA_Huge_Weapon
  • +
  • ARA_Weapon_Damage_FrostExplode
  • + + + 2 + 2 + + +
    +
    + + Bullet_ARA_RW_Icez_Mortar + + + Graphic_Single_AgeSecs + Things/Projectile/WaterSplash + (.75, .75) + MoteGlow + + 0.8 + Projectile_Explosive + + True + 1 + ARA_Damage_Freeze_ex + 25 + 75 + 1 + 3.5 + + ARA_FrostGasCloud_Ex + 1 + 1 + Explosion_Stun + + + + + + + + ARA_RW_Icez_Mortar_Turretgun + true + + + +
    \ No newline at end of file diff --git a/1.6/1.6/Defs/WeaponTraitDefs/ARA_WeaponTraitDefs.xml b/1.6/1.6/Defs/WeaponTraitDefs/ARA_WeaponTraitDefs.xml index fd444dd..70b74d1 100644 --- a/1.6/1.6/Defs/WeaponTraitDefs/ARA_WeaponTraitDefs.xml +++ b/1.6/1.6/Defs/WeaponTraitDefs/ARA_WeaponTraitDefs.xml @@ -77,4 +77,15 @@ + + ARA_Weapon_Damage_FrostExplode + + 这种武装器官发射的霜冻气雾能够沾染敌人,被沾染的敌人会再次爆炸。 + 1 + ARA_Weapon_Damage_Category + + + + + \ No newline at end of file diff --git a/1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/PowerArmor_Keys.xml b/1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/PowerArmor_Keys.xml new file mode 100644 index 0000000..2756cc2 --- /dev/null +++ b/1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/PowerArmor_Keys.xml @@ -0,0 +1,12 @@ + + + + + 进入 {0} + 无法进入外骨骼 + {0} 已经被损毁! + + + 结构点 + + \ 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 deleted file mode 100644 index 3257089..0000000 --- a/1.6/Languages/English/Keyed/PowerArmor_Keys.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - Enter {0} - Cannot enter power armor - {0} has been broken! - - - Structure - - \ No newline at end of file diff --git a/Content/Textures/ArachnaeSwarm/Mote/BlastFrost.png b/Content/Textures/ArachnaeSwarm/Mote/BlastFrost.png new file mode 100644 index 0000000..a6ae06a Binary files /dev/null and b/Content/Textures/ArachnaeSwarm/Mote/BlastFrost.png differ diff --git a/Source/ArachnaeSwarm/ARA_HediffDefOf.cs b/Source/ArachnaeSwarm/ARA_HediffDefOf.cs index 611ee5c..b3ffd3a 100644 --- a/Source/ArachnaeSwarm/ARA_HediffDefOf.cs +++ b/Source/ArachnaeSwarm/ARA_HediffDefOf.cs @@ -1,19 +1,18 @@ using RimWorld; using Verse; -using Verse.Sound; namespace ArachnaeSwarm { [DefOf] public static class ARA_HediffDefOf { - public static HediffDef ARA_AcidCoverd; public static HediffDef ARA_HiveMindMaster; public static HediffDef ARA_HiveMindDrone; - public static HediffDef ARA_HiveMindWorker; + public static HediffDef ARA_HiveMindWorker; // 如果存在这个Def + static ARA_HediffDefOf() { - DefOfHelper.EnsureInitializedInCtor(typeof(HediffDefOf)); + DefOfHelper.EnsureInitializedInCtor(typeof(ARA_HediffDefOf)); } } } \ No newline at end of file diff --git a/Source/ArachnaeSwarm/ArachnaeSwarm.csproj b/Source/ArachnaeSwarm/ArachnaeSwarm.csproj index 8c85906..ee5f244 100644 --- a/Source/ArachnaeSwarm/ArachnaeSwarm.csproj +++ b/Source/ArachnaeSwarm/ArachnaeSwarm.csproj @@ -193,6 +193,7 @@ + @@ -278,7 +279,6 @@ - diff --git a/Source/ArachnaeSwarm/Building_Comps/CompRefuelableNutrition.cs b/Source/ArachnaeSwarm/Building_Comps/CompRefuelableNutrition.cs index e9e153f..87de355 100644 --- a/Source/ArachnaeSwarm/Building_Comps/CompRefuelableNutrition.cs +++ b/Source/ArachnaeSwarm/Building_Comps/CompRefuelableNutrition.cs @@ -7,13 +7,27 @@ namespace ArachnaeSwarm { public class CompProperties_RefuelableNutrition : CompProperties_Refuelable { + public bool silent = false; + public CompProperties_RefuelableNutrition() { compClass = typeof(CompRefuelableNutrition); - // 默认启用这些Gizmo,除非在XML中明确设置为false this.targetFuelLevelConfigurable = true; this.showAllowAutoRefuelToggle = true; } + + public override IEnumerable SpecialDisplayStats(StatRequest req) + { + if (silent) + { + yield break; // If silent, return nothing. + } + + foreach (var stat in base.SpecialDisplayStats(req)) + { + yield return stat; + } + } } [StaticConstructorOnStartup] diff --git a/Source/ArachnaeSwarm/HediffComp_TimedExplosion.cs b/Source/ArachnaeSwarm/HediffComp_TimedExplosion.cs new file mode 100644 index 0000000..450399e --- /dev/null +++ b/Source/ArachnaeSwarm/HediffComp_TimedExplosion.cs @@ -0,0 +1,244 @@ +using RimWorld; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; +using Verse; +using Verse.Noise; + +namespace ArachnaeSwarm // 修正命名空间 +{ + public class HediffComp_TimedExplosion : HediffComp + { + // 倒计时相关字段 + public int ticksToDisappear; + public int disappearsAfterTicks; + public int seed; + + // 配置属性快捷访问 + public HediffCompProperties_TimedExplosion Props => + (HediffCompProperties_TimedExplosion)props; + + // 消失判定属性 + public override bool CompShouldRemove + { + get + { + if (ticksToDisappear > 0) return false; + if (Props.requiredMentalState != null) + { + return parent.pawn.MentalStateDef != Props.requiredMentalState; + } + return true; + } + } + + // 进度计算 + public float Progress => + 1f - (float)ticksToDisappear / Mathf.Max(1, disappearsAfterTicks); + + public int EffectiveTicksToDisappear => ticksToDisappear / TicksLostPerTick; + + public float NoisyProgress => AddNoiseToProgress(Progress, seed); + + public virtual int TicksLostPerTick => 1; + + public override string CompLabelInBracketsExtra + { + get + { + if (Props.showRemainingTime) + { + if (EffectiveTicksToDisappear < 2500) + { + return EffectiveTicksToDisappear.ToStringSecondsFromTicks("F0"); + } + return EffectiveTicksToDisappear.ToStringTicksToPeriod(allowSeconds: true, shortForm: true, canUseDecimals: true, allowYears: true, Props.canUseDecimalsShortForm); + } + return base.CompLabelInBracketsExtra; + } + } + + private static float AddNoiseToProgress(float progress, int seed) + { + float num = (float)Perlin.GetValue(progress, 0.0, 0.0, 9.0, seed); + float num2 = 0.25f * (1f - progress); + return Mathf.Clamp01(progress + num2 * num); + } + + // 初始化 + public override void CompPostMake() + { + base.CompPostMake(); + disappearsAfterTicks = Props.disappearsAfterTicks.RandomInRange; + seed = Rand.Int; + ticksToDisappear = disappearsAfterTicks; + } + + // 每帧更新 + public override void CompPostTick(ref float severityAdjustment) + { + ticksToDisappear--; + if (CompShouldRemove) + { + parent.pawn.health.RemoveHediff(parent); + } + } + + // 移除后处理 + public override void CompPostPostRemoved() + { + base.CompPostPostRemoved(); + + // 处理新鲜伤口状态 + if (!Props.leaveFreshWounds && parent.Part != null) + { + foreach (BodyPartRecord part in parent.Part.GetPartAndAllChildParts()) + { + Hediff_MissingPart hediff = parent.pawn.health.hediffSet.GetMissingPartFor(part) as Hediff_MissingPart; + if (hediff != null) + { + hediff.IsFresh = false; + } + } + } + + // 触发爆炸逻辑 + if (ShouldTriggerExplosion()) + { + TriggerExplosion(); + DestroyGearIfNeeded(); + } + + // 发送消息通知 + if (!Props.messageOnDisappear.NullOrEmpty() && PawnUtility.ShouldSendNotificationAbout(parent.pawn)) + { + Messages.Message( + Props.messageOnDisappear.Formatted(parent.pawn.Named("PAWN")), + parent.pawn, + MessageTypeDefOf.NeutralEvent + ); + } + + // 发送信件通知 + if (!Props.letterTextOnDisappear.NullOrEmpty() && + !Props.letterLabelOnDisappear.NullOrEmpty() && + PawnUtility.ShouldSendNotificationAbout(parent.pawn)) + { + Find.LetterStack.ReceiveLetter( + Props.letterLabelOnDisappear.Formatted(parent.pawn.Named("PAWN")), + Props.letterTextOnDisappear.Formatted(parent.pawn.Named("PAWN")), + LetterDefOf.NegativeEvent, + parent.pawn + ); + } + } + + // 爆炸条件检查 + private bool ShouldTriggerExplosion() + { + return parent.pawn.Spawned && + Props.explosionRadius > 0.01f && + Props.damageDef != null && + parent.pawn.Map != null; + } + + // 执行爆炸 + private void TriggerExplosion() + { + GenExplosion.DoExplosion( + center: parent.pawn.Position, + map: parent.pawn.Map, + radius: Props.explosionRadius, + damType: Props.damageDef, + instigator: parent.pawn, + damAmount: Props.damageAmount, + armorPenetration: Props.armorPenetration, + explosionSound: Props.soundDef, + weapon: null, + projectile: null, + intendedTarget: null, + postExplosionSpawnThingDef: Props.postExplosionSpawnThingDef, + postExplosionSpawnChance: Props.postExplosionSpawnChance, + postExplosionSpawnThingCount: Props.postExplosionSpawnThingCount, + postExplosionGasType: null, + applyDamageToExplosionCellsNeighbors: false, + chanceToStartFire: Props.chanceToStartFire, + damageFalloff: Props.damageFalloff, + direction: null, + ignoredThings: new List { parent.pawn } + ); + } + + // 装备销毁 + private void DestroyGearIfNeeded() + { + if (!Props.destroyGear) return; + + if (parent.pawn.equipment != null) + { + parent.pawn.equipment.DestroyAllEquipment(DestroyMode.Vanish); + } + if (parent.pawn.apparel != null) + { + parent.pawn.apparel.DestroyAll(DestroyMode.Vanish); + } + } + + // 数据持久化 + public override void CompExposeData() + { + Scribe_Values.Look(ref ticksToDisappear, "ticksToDisappear", 0); + Scribe_Values.Look(ref disappearsAfterTicks, "disappearsAfterTicks", 0); + Scribe_Values.Look(ref seed, "seed", 0); + } + + // 调试信息 + public override string CompDebugString() + { + return $"倒计时: {ticksToDisappear}\n爆炸半径: {Props.explosionRadius}"; + } + } + + public class HediffCompProperties_TimedExplosion : HediffCompProperties + { + [Header("消失设置")] + public IntRange disappearsAfterTicks = new IntRange(600, 1200); + public bool showRemainingTime = true; + public bool canUseDecimalsShortForm; + public MentalStateDef requiredMentalState; + public bool leaveFreshWounds = true; + + [Header("爆炸设置")] + public float explosionRadius = 3f; + public DamageDef damageDef; + public int damageAmount = 20; + public float armorPenetration; + public SoundDef soundDef; + public float chanceToStartFire; + public bool damageFalloff = true; + + [Header("后续效果")] + public bool destroyGear; + public GasType gasType; + public ThingDef postExplosionSpawnThingDef; + public float postExplosionSpawnChance; + public int postExplosionSpawnThingCount = 1; + + [Header("通知设置")] + [MustTranslate] + public string messageOnDisappear; + [MustTranslate] + public string letterLabelOnDisappear; + [MustTranslate] + public string letterTextOnDisappear; + public bool sendLetterOnDisappearIfDead = true; + + public HediffCompProperties_TimedExplosion() + { + compClass = typeof(HediffComp_TimedExplosion); + } + } +} \ No newline at end of file diff --git a/Source/ArachnaeSwarm/PowerArmor/ARA_PowerArmor.cs b/Source/ArachnaeSwarm/PowerArmor/ARA_PowerArmor.cs index 646af0a..5061875 100644 --- a/Source/ArachnaeSwarm/PowerArmor/ARA_PowerArmor.cs +++ b/Source/ArachnaeSwarm/PowerArmor/ARA_PowerArmor.cs @@ -19,6 +19,7 @@ namespace ArachnaeSwarm public float structurePointsMax = 500f; public HediffDef hediffOnEmptyFuel; public float fuelConsumptionRate = 0.5f; // Nutrition per day + public ThingDef powerArmorWeapon; } [StaticConstructorOnStartup] @@ -51,6 +52,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 + + public void SetOriginalWeapon(ThingWithComps weapon) + { + originalWeapon = weapon; + } + + public void SetCurrentPowerArmorWeapon(ThingWithComps weapon) + { + currentPowerArmorWeapon = weapon; + } #endregion #region Ticker @@ -110,6 +123,8 @@ namespace ArachnaeSwarm 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 } #endregion @@ -137,12 +152,49 @@ 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. @@ -171,6 +223,12 @@ namespace ArachnaeSwarm buildingFuelComp.ReceiveFuel(apparelFuelComp.Fuel); } + // Sync quality back to building + if (this.TryGetComp() is CompQuality apparelQuality && building.TryGetComp() 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 diff --git a/Source/ArachnaeSwarm/PowerArmor/CompPowerArmorStation.cs b/Source/ArachnaeSwarm/PowerArmor/CompPowerArmorStation.cs index 7515614..f4d4d52 100644 --- a/Source/ArachnaeSwarm/PowerArmor/CompPowerArmorStation.cs +++ b/Source/ArachnaeSwarm/PowerArmor/CompPowerArmorStation.cs @@ -1,5 +1,8 @@ using RimWorld; using Verse; +using System.Collections.Generic; +using Verse.AI; // For PathEndMode and Danger +using UnityEngine; // For Texture2D namespace ArachnaeSwarm { @@ -16,5 +19,45 @@ namespace ArachnaeSwarm public class CompPowerArmorStation : ThingComp { public CompProperties_PowerArmorStation Props => (CompProperties_PowerArmorStation)props; + + public override void CompTick() + { + base.CompTick(); + var fuelComp = parent.GetComp(); + if (fuelComp != null) + { + // Set consumption rate to 0 when in building form + fuelComp.currentConsumptionRate = 0f; + } + } + + public override IEnumerable CompFloatMenuOptions(Pawn selPawn) + { + foreach (FloatMenuOption option in base.CompFloatMenuOptions(selPawn)) + { + yield return option; + } + + // Check if there's an apparelDef defined + if (Props.apparelDef == null) + { + yield break; // No apparel to wear + } + + // Check if the pawn can interact with the building + if (!selPawn.CanReserveAndReach(parent, PathEndMode.InteractionCell, Danger.Deadly)) + { + yield return new FloatMenuOption("CannotEnterPowerArmor".Translate() + ": " + "CannotReach".Translate(), null); + } + else + { + void enterAction() + { + Job job = JobMaker.MakeJob(DefDatabase.GetNamed("ARA_EnterPowerArmor"), parent); + selPawn.jobs.TryTakeOrderedJob(job, JobTag.Misc); + } + yield return new FloatMenuOption("EnterPowerArmor".Translate(parent.Label), enterAction); + } + } } } \ No newline at end of file diff --git a/Source/ArachnaeSwarm/PowerArmor/Harmony_ThingWithComps_GetFloatMenuOptions.cs b/Source/ArachnaeSwarm/PowerArmor/Harmony_ThingWithComps_GetFloatMenuOptions.cs deleted file mode 100644 index 0ec7543..0000000 --- a/Source/ArachnaeSwarm/PowerArmor/Harmony_ThingWithComps_GetFloatMenuOptions.cs +++ /dev/null @@ -1,59 +0,0 @@ -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 index 29bc532..7ff93df 100644 --- a/Source/ArachnaeSwarm/PowerArmor/JobDriver_EnterPowerArmor.cs +++ b/Source/ArachnaeSwarm/PowerArmor/JobDriver_EnterPowerArmor.cs @@ -50,11 +50,40 @@ namespace ArachnaeSwarm apparelFuelComp.ReceiveFuel(buildingFuelComp.Fuel); } + // Sync quality + if (building.TryGetComp() is CompQuality buildingQuality && apparel.TryGetComp() is CompQuality apparelQuality) + { + apparelQuality.SetQuality(buildingQuality.Quality, ArtGenerationContext.Colony); + } + // 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) + { + 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() is CompQuality existingApparelQuality && weapon.TryGetComp() 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); + } + // Despawn the building building.DeSpawn(); }