From e6d855924fb8bf68f80a7d2871cc6b8f7743a504 Mon Sep 17 00:00:00 2001 From: "ProjectKoi-Kalo\\Kalo" Date: Mon, 1 Sep 2025 20:39:33 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9A=82=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 1.6/1.6/Assemblies/ArachnaeSwarm.dll | Bin 24576 -> 30720 bytes .../AbilityDefs/ARA_Abilities_HiveMind.xml | 35 ++++++ .../Defs/BackstoryDefs/ARA_BackstoryDef.xml | 9 +- .../Defs/HediffDefs/ARA_Hediffs_HiveMind.xml | 14 ++- 1.6/1.6/Defs/PawnKindDef/ARA_PawnKinds.xml | 1 + Source/ArachnaeSwarm/ArachnaeSwarm.csproj | 6 + .../CompAbilityEffect_BindDrone.cs | 108 ++++++++++++++++++ .../CompProperties_AbilityBindDrone.cs | 13 +++ .../HediffCompProperties_HiveMindDrone.cs | 14 +++ .../ArachnaeSwarm/HediffComp_HiveMindDrone.cs | 57 +++++++++ Source/ArachnaeSwarm/Hediff_HiveMindDrone.cs | 73 ++++++++++++ Source/ArachnaeSwarm/Hediff_HiveMindMaster.cs | 86 ++++++++++++++ 12 files changed, 409 insertions(+), 7 deletions(-) create mode 100644 1.6/1.6/Defs/AbilityDefs/ARA_Abilities_HiveMind.xml rename 1.6/{ => 1.6}/Defs/HediffDefs/ARA_Hediffs_HiveMind.xml (79%) create mode 100644 Source/ArachnaeSwarm/CompAbilityEffect_BindDrone.cs create mode 100644 Source/ArachnaeSwarm/CompProperties_AbilityBindDrone.cs create mode 100644 Source/ArachnaeSwarm/HediffCompProperties_HiveMindDrone.cs create mode 100644 Source/ArachnaeSwarm/HediffComp_HiveMindDrone.cs create mode 100644 Source/ArachnaeSwarm/Hediff_HiveMindDrone.cs create mode 100644 Source/ArachnaeSwarm/Hediff_HiveMindMaster.cs diff --git a/1.6/1.6/Assemblies/ArachnaeSwarm.dll b/1.6/1.6/Assemblies/ArachnaeSwarm.dll index 29adbd54ed77b42e8842e3bfcec4658a5f14ed6e..712070020822c4f9bb82027d4a19699c4d091f27 100644 GIT binary patch delta 13894 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 diff --git a/1.6/1.6/Defs/AbilityDefs/ARA_Abilities_HiveMind.xml b/1.6/1.6/Defs/AbilityDefs/ARA_Abilities_HiveMind.xml new file mode 100644 index 0000000..abad623 --- /dev/null +++ b/1.6/1.6/Defs/AbilityDefs/ARA_Abilities_HiveMind.xml @@ -0,0 +1,35 @@ + + + + + ARA_BindDrone + + Allows the hive mind master to bind with an unlinked drone, bringing it under direct psychic control. + UI/Commands/EggSpew + + CastAbilityOnThing + true + 60 + + + Verb_CastAbility + 0.5 + 99 + + true + false + true + false + false + false + + + + +
  • + +
  • +
    +
    + +
    \ No newline at end of file diff --git a/1.6/1.6/Defs/BackstoryDefs/ARA_BackstoryDef.xml b/1.6/1.6/Defs/BackstoryDefs/ARA_BackstoryDef.xml index 1b755ad..c63cee7 100644 --- a/1.6/1.6/Defs/BackstoryDefs/ARA_BackstoryDef.xml +++ b/1.6/1.6/Defs/BackstoryDefs/ARA_BackstoryDef.xml @@ -15,6 +15,9 @@ 2 2 + +
  • ARA_HiveMindMaster
  • +
  • ArachnaeQueen_spawnCategoriesA
  • @@ -53,9 +56,13 @@
  • ArachnaeNode_spawnCategoriesA
  • + +
  • ARA_HiveMindDrone
  • +
    + true - + Arachnae_Node_BS_Adult_1 阿拉克涅督虫种 diff --git a/1.6/Defs/HediffDefs/ARA_Hediffs_HiveMind.xml b/1.6/1.6/Defs/HediffDefs/ARA_Hediffs_HiveMind.xml similarity index 79% rename from 1.6/Defs/HediffDefs/ARA_Hediffs_HiveMind.xml rename to 1.6/1.6/Defs/HediffDefs/ARA_Hediffs_HiveMind.xml index 02f3fac..421cc2a 100644 --- a/1.6/Defs/HediffDefs/ARA_Hediffs_HiveMind.xml +++ b/1.6/1.6/Defs/HediffDefs/ARA_Hediffs_HiveMind.xml @@ -3,7 +3,7 @@ ARA_HiveMindMaster - + The central node of a hive mind, connected to multiple drone beings. ArachnaeSwarm.Hediff_HiveMindMaster (0.8, 0.3, 0.8) @@ -19,18 +19,20 @@ - + ARA_HiveMindDrone - + A drone being, psychically linked to a master node. If the master dies, this unit will cease to function. ArachnaeSwarm.Hediff_HiveMindDrone (0.6, 0.4, 0.8) false true - -
  • - + +
  • + 6400
  • + +
    diff --git a/1.6/1.6/Defs/PawnKindDef/ARA_PawnKinds.xml b/1.6/1.6/Defs/PawnKindDef/ARA_PawnKinds.xml index 9388dba..ddc159f 100644 --- a/1.6/1.6/Defs/PawnKindDef/ARA_PawnKinds.xml +++ b/1.6/1.6/Defs/PawnKindDef/ARA_PawnKinds.xml @@ -16,6 +16,7 @@
  • ARA_EggSpew
  • ARA_AcidSprayBurst
  • +
  • ARA_BindDrone
  • diff --git a/Source/ArachnaeSwarm/ArachnaeSwarm.csproj b/Source/ArachnaeSwarm/ArachnaeSwarm.csproj index 115002f..73f91ed 100644 --- a/Source/ArachnaeSwarm/ArachnaeSwarm.csproj +++ b/Source/ArachnaeSwarm/ArachnaeSwarm.csproj @@ -77,6 +77,12 @@ + + + + + + diff --git a/Source/ArachnaeSwarm/CompAbilityEffect_BindDrone.cs b/Source/ArachnaeSwarm/CompAbilityEffect_BindDrone.cs new file mode 100644 index 0000000..c206b95 --- /dev/null +++ b/Source/ArachnaeSwarm/CompAbilityEffect_BindDrone.cs @@ -0,0 +1,108 @@ +using RimWorld; +using Verse; +using System.Linq; // For LINQ operations + +namespace ArachnaeSwarm +{ + public class CompAbilityEffect_BindDrone : CompAbilityEffect + { + public override void Apply(LocalTargetInfo target, LocalTargetInfo dest) + { + base.Apply(target, dest); + + Pawn dronePawn = target.Pawn; + Pawn masterPawn = parent.pawn; // The pawn casting the ability + + if (masterPawn != null && dronePawn != null) + { + Hediff_HiveMindMaster masterHediff = masterPawn.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("ARA_HiveMindMaster")) as Hediff_HiveMindMaster; + if (masterHediff != null) + { + if (masterHediff.TryBindDrone(dronePawn)) + { + Messages.Message($"Successfully bound {dronePawn.LabelShort} to {masterPawn.LabelShort}'s hive mind.", MessageTypeDefOf.PositiveEvent, historical: false); + } + else + { + Messages.Message($"Failed to bind {dronePawn.LabelShort} to {masterPawn.LabelShort}'s hive mind. Check logs for details.", MessageTypeDefOf.NegativeEvent, historical: false); + } + } + else + { + Log.Error($"[ArachnaeSwarm] Master {masterPawn.LabelShort} tried to bind a drone but does not have Hediff_HiveMindMaster."); + } + } + } + + public override bool Valid(LocalTargetInfo target, bool throwMessages = false) + { + if (!base.Valid(target, throwMessages)) + { + return false; + } + + Pawn dronePawn = target.Pawn; + Pawn masterPawn = parent.pawn; + + // Target must be a pawn + if (dronePawn == null) + { + if (throwMessages) + { + Messages.Message("MustTargetPawn".Translate(parent.def.label), MessageTypeDefOf.RejectInput, historical: false); + } + return false; + } + + // Target must be on the same map as the caster + if (dronePawn.Map != masterPawn.Map) + { + if (throwMessages) + { + Messages.Message("CannotTargetDifferentMap".Translate(), MessageTypeDefOf.RejectInput, historical: false); + } + return false; + } + + // Target must have ARA_HiveMindDrone hediff + Hediff_HiveMindDrone droneHediff = dronePawn.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("ARA_HiveMindDrone")) as Hediff_HiveMindDrone; + if (droneHediff == null) + { + if (throwMessages) + { + Messages.Message($"Target {dronePawn.LabelShort} does not have the 'ARA_HiveMindDrone' hediff.", MessageTypeDefOf.RejectInput, historical: false); + } + return false; + } + + // Target must not be already bound to another master + if (droneHediff.target != null && droneHediff.target != masterPawn) + { + if (throwMessages) + { + Messages.Message($"Target {dronePawn.LabelShort} is already bound to {droneHediff.target.LabelShort}.", MessageTypeDefOf.RejectInput, historical: false); + } + return false; + } + + // Caster must have ARA_HiveMindMaster hediff + Hediff_HiveMindMaster masterHediff = masterPawn.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("ARA_HiveMindMaster")) as Hediff_HiveMindMaster; + if (masterHediff == null) + { + if (throwMessages) + { + Messages.Message($"Caster {masterPawn.LabelShort} does not have the 'ARA_HiveMindMaster' hediff.", MessageTypeDefOf.RejectInput, historical: false); + } + return false; + } + + // All checks passed + return true; + } + + public override bool CanApplyOn(LocalTargetInfo target, LocalTargetInfo dest) + { + return Valid(target); + } + } +} \ No newline at end of file diff --git a/Source/ArachnaeSwarm/CompProperties_AbilityBindDrone.cs b/Source/ArachnaeSwarm/CompProperties_AbilityBindDrone.cs new file mode 100644 index 0000000..959f8d2 --- /dev/null +++ b/Source/ArachnaeSwarm/CompProperties_AbilityBindDrone.cs @@ -0,0 +1,13 @@ +using Verse; +using RimWorld; + +namespace ArachnaeSwarm +{ + public class CompProperties_AbilityBindDrone : CompProperties_AbilityEffect + { + public CompProperties_AbilityBindDrone() + { + this.compClass = typeof(CompAbilityEffect_BindDrone); + } + } +} \ No newline at end of file diff --git a/Source/ArachnaeSwarm/HediffCompProperties_HiveMindDrone.cs b/Source/ArachnaeSwarm/HediffCompProperties_HiveMindDrone.cs new file mode 100644 index 0000000..921f2ea --- /dev/null +++ b/Source/ArachnaeSwarm/HediffCompProperties_HiveMindDrone.cs @@ -0,0 +1,14 @@ +using Verse; + +namespace ArachnaeSwarm +{ + public class HediffCompProperties_HiveMindDrone : HediffCompProperties + { + public int unlinkedDieDelayTicks = 1800; // Default to 30 seconds + + public HediffCompProperties_HiveMindDrone() + { + this.compClass = typeof(HediffComp_HiveMindDrone); // Reference the Comp class + } + } +} \ No newline at end of file diff --git a/Source/ArachnaeSwarm/HediffComp_HiveMindDrone.cs b/Source/ArachnaeSwarm/HediffComp_HiveMindDrone.cs new file mode 100644 index 0000000..09302cd --- /dev/null +++ b/Source/ArachnaeSwarm/HediffComp_HiveMindDrone.cs @@ -0,0 +1,57 @@ +using Verse; +using RimWorld; + +namespace ArachnaeSwarm +{ + public class HediffComp_HiveMindDrone : HediffComp + { + public HediffCompProperties_HiveMindDrone Props => (HediffCompProperties_HiveMindDrone)this.props; + + public int TicksUnlinked => ticksUnlinked; // Expose as public property + private int ticksUnlinked = 0; + + public override void CompExposeData() + { + base.CompExposeData(); + Scribe_Values.Look(ref ticksUnlinked, "ticksUnlinked", 0); + } + + public override void CompPostTick(ref float severityAdjustment) + { + base.CompPostTick(ref severityAdjustment); + + // Only check if pawn is spawned and on a map + if (parent.pawn.Spawned && parent.pawn.Map != null) + { + // We use parent.pawn.IsHashIntervalTick(60) for performance + if (!parent.pawn.IsHashIntervalTick(60)) + return; + + Hediff_HiveMindDrone droneHediff = parent as Hediff_HiveMindDrone; + if (droneHediff == null) return; // Should not happen + + Pawn masterPawn = droneHediff.target as Pawn; + + if (masterPawn == null || masterPawn.Destroyed || masterPawn.Dead || !masterPawn.health.hediffSet.HasHediff(HediffDef.Named("ARA_HiveMindMaster"))) + { + // Master is invalid or unlinked, start/continue unlinked timer + ticksUnlinked += 60; // Increment by 60 because we check every 60 ticks + if (ticksUnlinked >= Props.unlinkedDieDelayTicks) + { + Log.Message($"[ArachnaeSwarm] Drone {parent.pawn.LabelShort} was unlinked from master for too long and will die. Forcing death."); + // Ensure the pawn is killed only once and prevent further ticks + if (!parent.pawn.Dead && !parent.pawn.Destroyed) + { + parent.pawn.Kill(null, parent); + } + } + } + else + { + // Master is valid, reset unlinked timer + ticksUnlinked = 0; + } + } + } + } +} \ No newline at end of file diff --git a/Source/ArachnaeSwarm/Hediff_HiveMindDrone.cs b/Source/ArachnaeSwarm/Hediff_HiveMindDrone.cs new file mode 100644 index 0000000..87760f0 --- /dev/null +++ b/Source/ArachnaeSwarm/Hediff_HiveMindDrone.cs @@ -0,0 +1,73 @@ +using System.Linq; +using RimWorld; +using Verse; + +namespace ArachnaeSwarm +{ + public class Hediff_HiveMindDrone : HediffWithTarget + { + public override string LabelBase + { + get + { + string baseLabel = base.LabelBase + " (" + (target != null ? target.LabelShortCap : "未连接") + ")"; + + // Get the HediffComp_HiveMindDrone to access ticksUnlinked + HediffComp_HiveMindDrone comp = this.TryGetComp(); + if (comp != null) + { + // Safely cast target to Pawn for Dead and health checks + Pawn masterPawn = target as Pawn; + + if (masterPawn == null || masterPawn.Destroyed || masterPawn.Dead || !masterPawn.health.hediffSet.HasHediff(HediffDef.Named("ARA_HiveMindMaster"))) + { + float timeLeftSecs = (comp.Props.unlinkedDieDelayTicks - comp.TicksUnlinked) / 60f; + if (timeLeftSecs > 0) + { + return baseLabel + " (死亡倒计时: " + timeLeftSecs.ToString("F1") + "s)"; + } + } + } + return baseLabel; + } + } + + public override void PostAdd(DamageInfo? dinfo) + { + base.PostAdd(dinfo); + // No direct linking in PostAdd, master will link manually + } + + public override bool ShouldRemove + { + get + { + // Only remove if base ShouldRemove is true, OR if pawn is dead + // We do NOT want to remove it just because target is invalid, as the Comp will handle delayed death + if (base.ShouldRemove && pawn.Dead) + { + return true; + } + // Also remove if pawn is no longer spawned or on a map + if (!pawn.Spawned || pawn.Map == null) + { + return true; + } + return false; // Let the Comp handle the unlinked death + } + } + + public override void PostRemoved() + { + base.PostRemoved(); + // Deregister from the master when this hediff is removed + // Ensure target is a Pawn and not dead before attempting to deregister + if (this.target is Pawn master && master != null && !master.Destroyed && !master.Dead) + { + var masterHediff = master.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("ARA_HiveMindMaster")) as Hediff_HiveMindMaster; + masterHediff?.DeregisterDrone(this.pawn); + } + } + // PostTick logic moved to HediffComp_HiveMindDrone + } +} \ No newline at end of file diff --git a/Source/ArachnaeSwarm/Hediff_HiveMindMaster.cs b/Source/ArachnaeSwarm/Hediff_HiveMindMaster.cs new file mode 100644 index 0000000..2558b1e --- /dev/null +++ b/Source/ArachnaeSwarm/Hediff_HiveMindMaster.cs @@ -0,0 +1,86 @@ +using System.Collections.Generic; +using System.Linq; +using RimWorld; +using Verse; + +namespace ArachnaeSwarm +{ + public class Hediff_HiveMindMaster : Hediff + { + private List drones = new List(); + + public override string LabelInBrackets => drones.Count.ToString(); + + public override void ExposeData() + { + base.ExposeData(); + Scribe_Collections.Look(ref drones, "drones", LookMode.Reference); + if (drones == null) + { + drones = new List(); + } + } + + public bool TryBindDrone(Pawn drone) + { + if (drone == null || drone.Dead || !drone.Spawned || drone.Map != this.pawn.Map) + { + Log.Message($"[ArachnaeSwarm] Cannot bind drone {drone?.LabelShort ?? "null"}: Invalid pawn state."); + return false; + } + + Hediff_HiveMindDrone droneHediff = drone.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("ARA_HiveMindDrone")) as Hediff_HiveMindDrone; + if (droneHediff == null) + { + Log.Message($"[ArachnaeSwarm] Cannot bind drone {drone.LabelShort}: Does not have ARA_HiveMindDrone hediff."); + return false; + } + + if (droneHediff.target != null && droneHediff.target != this.pawn) + { + Log.Message($"[ArachnaeSwarm] Cannot bind drone {drone.LabelShort}: Already bound to another master ({droneHediff.target.LabelShort})."); + return false; + } + + if (drones.Contains(drone)) + { + Log.Message($"[ArachnaeSwarm] Drone {drone.LabelShort} is already bound to this master."); + return false; + } + + droneHediff.target = this.pawn; // Set the drone's target to this master + drones.Add(drone); + UpdateSeverity(); + Log.Message($"[ArachnaeSwarm] Master {this.pawn.LabelShort} successfully bound drone {drone.LabelShort}."); + return true; + } + + public void DeregisterDrone(Pawn drone) + { + if (drones.Contains(drone)) + { + drones.Remove(drone); + UpdateSeverity(); + } + } + + private void UpdateSeverity() + { + this.Severity = drones.Count; + } + + public override void PostRemoved() + { + base.PostRemoved(); + // Kill all drones when the master hediff is removed (e.g., master dies) + foreach (var drone in drones.ToList()) // ToList() to avoid collection modification issues + { + if (drone != null && !drone.Dead) + { + Log.Message($"[ArachnaeSwarm] Master {pawn.LabelShort} died, killing drone {drone.LabelShort}."); + drone.Kill(null, this); + } + } + } + } +} \ No newline at end of file