diff --git a/1.6/1.6/Assemblies/ArachnaeSwarm.dll b/1.6/1.6/Assemblies/ArachnaeSwarm.dll
index f9a4ea8..d9a6d41 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/AbilityDefs/ARA_Abilities.xml b/1.6/1.6/Defs/AbilityDefs/ARA_Abilities.xml
index 6555cf4..2def29c 100644
--- a/1.6/1.6/Defs/AbilityDefs/ARA_Abilities.xml
+++ b/1.6/1.6/Defs/AbilityDefs/ARA_Abilities.xml
@@ -31,6 +31,46 @@
+
+ ARA_TrapSpew
+
+ 发射一排阿拉克涅休眠茧,其中装有阿拉克涅酸爆种,这些危险的虫族被唤醒后就会开始寻仇,匆匆了结自己的生命.
+ UI/Commands/EggSpew
+ 5000
+ true
+ 300
+ true
+ false
+ AcidSpray_Warmup
+
+ Verb_CastAbility
+ 14.9
+ 0.25
+ AcidSpray_Resolve
+
+ true
+
+
+
+
+ ARA_Proj_StrongSludgeSpray
+ 8
+ AcidSpray_Directional
+
+
+ ARA_Proj_Trap
+ 3
+
+
+
+
+
+ ARA_Proj_Trap
+
+
+ Arachnae_Trap_ReleaseRandom
+
+
ARA_TumorSpew
diff --git a/1.6/1.6/Defs/ThingDef_Races/ARA_RaceDroneSwarm.xml b/1.6/1.6/Defs/ThingDef_Races/ARA_RaceDroneSwarm.xml
index f6ea89c..03a781d 100644
--- a/1.6/1.6/Defs/ThingDef_Races/ARA_RaceDroneSwarm.xml
+++ b/1.6/1.6/Defs/ThingDef_Races/ARA_RaceDroneSwarm.xml
@@ -131,6 +131,60 @@
+
+ ArachnaeBase_Race_Acidling
+
+ 阿拉克涅辅虫之一,智力低下,一般被作为自杀式无人机打出,靠近敌人后就会引爆酸囊产生危险的酸性雾气。
+
+ HunterDroneConstant
+ 0.5
+
+ BeetleLikeWithClaw
+
+
+ EusocialInsectAdult
+ 0
+ Pawn_Spelopede_Pain
+ Pawn_Spelopede_Death
+ Pawn_Spelopede_Call
+ Pawn_Spelopede_Angry
+
+
+
+
+ 6
+
+
+
+ 4400
+ 寿命
+ 这种特殊的阿拉克涅辅虫从出生起就走在死亡的道路上了——它们的寿命就是如此短暂。
+ true
+
+
+ 6
+ ARA_AcidBurn
+ 40
+ 0.5
+ Explosion_Smoke
+ ARA_AcidGasCloud
+ 1
+ 1
+
+
+
+
+
+
+ ARA_AcidCut
+
+ 6
+ 2.6
+ HeadAttackTool
+ true
+
+
+
ARA_AcidCut
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 1e6577a..c624340 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
@@ -40,4 +40,32 @@
+
+
+ ARA_AcidGasCloud
+
+
+ Things/Gas/Puff
+ 2.6
+ (0.56, 1, 0.03,0.5)
+
+
+
+ 30
+ 50
+
+
+ 20
+
+ ArachnaeSwarm.OPToxicGas
+
+
+ ARA_AcidCoverd
+ 0.1
+ 240
+
+
+
+
\ No newline at end of file
diff --git a/1.6/1.6/Defs/Thing_building/ARA_ThingDefs_TrapReleaseRandom.xml b/1.6/1.6/Defs/Thing_building/ARA_ThingDefs_TrapReleaseRandom.xml
new file mode 100644
index 0000000..5f22f6f
--- /dev/null
+++ b/1.6/1.6/Defs/Thing_building/ARA_ThingDefs_TrapReleaseRandom.xml
@@ -0,0 +1,52 @@
+
+
+
+ Arachnae_Trap_ReleaseRandom
+
+ 一种阿拉克涅休眠茧,内藏有休眠中的阿拉克涅虫族。如果靠太近则会唤醒其中的虫族。
+ ArachnaeSwarm.Building_TrapReleaseRandom
+
+ (1,1)
+ Building
+ PassThroughOnly
+ true
+ 0.20
+ false
+ false
+ Normal
+ EatVegetarian
+ Filth_Slime
+ Buildings
+
+ 20
+
+
+ 10
+ 4
+ 1.0
+ 50
+
+
+ ArachnaeSwarm/Building/ARA_Tumor
+ Graphic_Single
+ 1.2
+
+ (0.3, 0.6, 0.3)
+ (0,0,-0.1)
+
+
+
+ 3
+
+ ArachnaeBase_Race_Acidling
+ ArachnaeBase_Race_Acid
+
+
+
+
+ 3
+ (220,210,171,0)
+
+
+
+
diff --git a/1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/ArachnaeSwarm_Keys.xml b/1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/ArachnaeSwarm_Keys.xml
index c1cb40f..d324416 100644
--- a/1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/ArachnaeSwarm_Keys.xml
+++ b/1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/ArachnaeSwarm_Keys.xml
@@ -22,4 +22,8 @@
控制的虫族:
尚未绑定任何虫族。
+
+ {TRAP} 被 {PAWN} 触发!
+ {TRAP} 被触发!
+
\ No newline at end of file
diff --git a/Source/ArachnaeSwarm/ArachnaeSwarm.csproj b/Source/ArachnaeSwarm/ArachnaeSwarm.csproj
index 9b9f81d..a443725 100644
--- a/Source/ArachnaeSwarm/ArachnaeSwarm.csproj
+++ b/Source/ArachnaeSwarm/ArachnaeSwarm.csproj
@@ -1,5 +1,6 @@
-
+
Debug
@@ -161,6 +162,7 @@
+
@@ -192,6 +194,8 @@
+
+
diff --git a/Source/ArachnaeSwarm/Building_TrapReleaseRandom.cs b/Source/ArachnaeSwarm/Building_TrapReleaseRandom.cs
new file mode 100644
index 0000000..89ae517
--- /dev/null
+++ b/Source/ArachnaeSwarm/Building_TrapReleaseRandom.cs
@@ -0,0 +1,85 @@
+using System.Collections.Generic;
+using Verse;
+using Verse.Sound;
+using RimWorld;
+
+namespace ArachnaeSwarm;
+
+public class Building_TrapReleaseRandom : Building_TrapReleaseEntity
+{
+ // XML-assignable: number of pawns to spawn
+ public int countToSpawn = 1;
+
+ // XML-assignable: list of PawnKindDefs to choose from randomly when spawning
+ public List pawnKinds = new List();
+
+ protected override int CountToSpawn => countToSpawn;
+
+ protected override PawnKindDef PawnToSpawn => (pawnKinds == null || pawnKinds.Count == 0) ? PawnKindDefOf.Drone_Hunter : pawnKinds.RandomElement();
+
+ // Ensure spawned pawns use the building's faction when possible; otherwise spawn as wild (null faction)
+ protected override void SpringSub(Pawn p)
+ {
+ if (base.Spawned)
+ {
+ SoundStarter.PlayOneShot(SoundDefOf.DroneTrapSpring, new TargetInfo(base.Position, base.Map));
+ if (base.Faction != Faction.OfPlayer)
+ {
+ // Show a localized message including the trap name and, if available, the pawn who triggered it.
+ if (p != null)
+ {
+ Messages.Message("MessageTrapSprung".Translate(this.Named("TRAP"), p.Named("PAWN")), new LookTargets(base.Position, base.Map), MessageTypeDefOf.NegativeEvent);
+ }
+ else
+ {
+ Messages.Message("MessageTrapSprung_NoInstigator".Translate(this.Named("TRAP")), new LookTargets(base.Position, base.Map), MessageTypeDefOf.NegativeEvent);
+ }
+ }
+
+ for (int i = 0; i < CountToSpawn; i++)
+ {
+ PawnKindDef pawnToSpawn = PawnToSpawn;
+
+ // Prefer the building's faction (usually the faction that built it). If none, pass null to produce a wild pawn.
+ Faction spawnFaction = this.Faction;
+
+ float? fixedBiologicalAge = 0f;
+ float? fixedChronologicalAge = 0f;
+ Pawn pawn = PawnGenerator.GeneratePawn(new PawnGenerationRequest(
+ pawnToSpawn,
+ spawnFaction,
+ PawnGenerationContext.NonPlayer,
+ null,
+ forceGenerateNewPawn: false,
+ allowDead: false,
+ allowDowned: false,
+ canGeneratePawnRelations: true,
+ mustBeCapableOfViolence: false,
+ 1f,
+ forceAddFreeWarmLayerIfNeeded: false,
+ allowGay: true,
+ allowPregnant: false,
+ allowFood: true,
+ allowAddictions: true,
+ inhabitant: false,
+ certainlyBeenInCryptosleep: false,
+ forceRedressWorldPawnIfFormerColonist: false,
+ worldPawnFactionDoesntMatter: false,
+ 0f,
+ 0f,
+ null,
+ 1f,
+ null,
+ null,
+ null,
+ null,
+ null,
+ fixedBiologicalAge,
+ fixedChronologicalAge));
+
+ pawn.mindState.enemyTarget = p;
+ GenSpawn.Spawn(pawn, base.Position, base.Map);
+ }
+ }
+ }
+}
diff --git a/Source/ArachnaeSwarm/CompHunterExplosion.cs b/Source/ArachnaeSwarm/CompHunterExplosion.cs
new file mode 100644
index 0000000..504d5f7
--- /dev/null
+++ b/Source/ArachnaeSwarm/CompHunterExplosion.cs
@@ -0,0 +1,123 @@
+using Verse;
+using Verse.Sound;
+using System.Collections.Generic;
+using RimWorld;
+
+namespace ArachnaeSwarm;
+
+public class CompHunterExplosion : ThingComp
+{
+ private bool wickStarted;
+
+ private int wickTicks;
+
+ [Unsaved(false)]
+ private Sustainer wickSoundSustainer;
+
+ [Unsaved(false)]
+ private OverlayHandle? overlayBurningWick;
+
+ private CompProperties_HunterExplosion Props => (CompProperties_HunterExplosion)props;
+
+ public override void PostExposeData()
+ {
+ base.PostExposeData();
+ Scribe_Values.Look(ref wickStarted, "wickStarted", defaultValue: false);
+ Scribe_Values.Look(ref wickTicks, "wickTicks", 0);
+ }
+
+ public override void CompTickInterval(int delta)
+ {
+ if (!wickStarted && parent.IsHashIntervalTick(30, delta) && parent is Pawn { Spawned: not false, Downed: false } pawn && PawnUtility.EnemiesAreNearby(pawn, 9, passDoors: true, 1.5f))
+ {
+ StartWick();
+ }
+ }
+
+ public override void CompTick()
+ {
+ if (wickStarted)
+ {
+ wickSoundSustainer.Maintain();
+ wickTicks--;
+ if (wickTicks <= 0)
+ {
+ Detonate();
+ }
+ }
+ }
+
+ private void StartWick()
+ {
+ if (!wickStarted)
+ {
+ wickStarted = true;
+ overlayBurningWick = parent.Map.overlayDrawer.Enable(parent, OverlayTypes.BurningWick);
+ wickSoundSustainer = SoundDefOf.HissSmall.TrySpawnSustainer(SoundInfo.InMap(parent, MaintenanceType.PerTick));
+ wickTicks = 120;
+ }
+ }
+
+ public override void Notify_Killed(Map prevMap, DamageInfo? dinfo = null)
+ {
+ if (dinfo.HasValue)
+ {
+ Detonate(prevMap);
+ }
+ }
+
+ private void Detonate(Map map = null)
+ {
+ IntVec3 position = parent.Position;
+ if (map == null)
+ {
+ map = parent.Map;
+ }
+ if (!parent.Destroyed)
+ {
+ parent.Destroy();
+ }
+ GenExplosion.DoExplosion(
+ center: position,
+ map: map,
+ radius: Props.explosionRadius,
+ damType: Props.explosionDamageType,
+ instigator: parent,
+ damAmount: Props.explosionDamageAmount,
+ armorPenetration: Props.armorPenetration,
+ explosionSound: Props.explosionSound,
+ weapon: Props.weapon,
+ projectile: Props.projectile,
+ intendedTarget: Props.intendedTarget,
+ postExplosionSpawnThingDef: Props.postExplosionSpawnThingDef,
+ postExplosionSpawnChance: Props.postExplosionSpawnChance,
+ postExplosionSpawnThingCount: Props.postExplosionSpawnThingCount,
+ postExplosionGasType: Props.postExplosionGasType,
+ postExplosionGasRadiusOverride: Props.postExplosionGasRadiusOverride,
+ postExplosionGasAmount: Props.postExplosionGasAmount,
+ applyDamageToExplosionCellsNeighbors: Props.applyDamageToExplosionCellsNeighbors,
+ preExplosionSpawnThingDef: Props.preExplosionSpawnThingDef,
+ preExplosionSpawnChance: Props.preExplosionSpawnChance,
+ preExplosionSpawnThingCount: Props.preExplosionSpawnThingCount,
+ chanceToStartFire: Props.chanceToStartFire,
+ damageFalloff: Props.damageFalloff,
+ direction: Props.direction,
+ ignoredThings: Props.ignoredThings,
+ affectedAngle: Props.affectedAngle,
+ doVisualEffects: Props.doVisualEffects,
+ propagationSpeed: Props.propagationSpeed,
+ excludeRadius: Props.excludeRadius,
+ doSoundEffects: Props.doSoundEffects,
+ postExplosionSpawnThingDefWater: Props.postExplosionSpawnThingDefWater,
+ screenShakeFactor: Props.screenShakeFactor,
+ flammabilityChanceCurve: Props.flammabilityChanceCurve,
+ overrideCells: Props.overrideCells,
+ postExplosionSpawnSingleThingDef: Props.postExplosionSpawnSingleThingDef,
+ preExplosionSpawnSingleThingDef: Props.preExplosionSpawnSingleThingDef
+ );
+ if (base.ParentHolder is Corpse corpse)
+ {
+ corpse.Destroy();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Source/ArachnaeSwarm/CompProperties_HunterExplosion.cs b/Source/ArachnaeSwarm/CompProperties_HunterExplosion.cs
new file mode 100644
index 0000000..d4a03b4
--- /dev/null
+++ b/Source/ArachnaeSwarm/CompProperties_HunterExplosion.cs
@@ -0,0 +1,56 @@
+using System.Collections.Generic;
+using RimWorld;
+using Verse;
+
+namespace ArachnaeSwarm;
+
+public class CompProperties_HunterExplosion : CompProperties
+{
+ public float explosionRadius = 1.9f;
+ public DamageDef explosionDamageType;
+ public int explosionDamageAmount = 50;
+ public float armorPenetration = -1f;
+ public SoundDef explosionSound;
+ public ThingDef weapon;
+ public ThingDef projectile;
+ public Thing intendedTarget;
+ public ThingDef postExplosionSpawnThingDef;
+ public float postExplosionSpawnChance;
+ public int postExplosionSpawnThingCount = 1;
+ public GasType? postExplosionGasType;
+ public float? postExplosionGasRadiusOverride;
+ public int postExplosionGasAmount = 255;
+ public bool applyDamageToExplosionCellsNeighbors;
+ public ThingDef preExplosionSpawnThingDef;
+ public float preExplosionSpawnChance;
+ public int preExplosionSpawnThingCount = 1;
+ public float chanceToStartFire;
+ public bool damageFalloff;
+ public float? direction;
+ public List ignoredThings;
+ public FloatRange? affectedAngle;
+ public bool doVisualEffects = true;
+ public float propagationSpeed = 1f;
+ public float excludeRadius;
+ public bool doSoundEffects = true;
+ public ThingDef postExplosionSpawnThingDefWater;
+ public float screenShakeFactor = 1f;
+ public SimpleCurve flammabilityChanceCurve;
+ public List overrideCells;
+ public ThingDef postExplosionSpawnSingleThingDef;
+ public ThingDef preExplosionSpawnSingleThingDef;
+
+ public CompProperties_HunterExplosion()
+ {
+ compClass = typeof(CompHunterExplosion);
+ }
+
+ public override void ResolveReferences(ThingDef parentDef)
+ {
+ base.ResolveReferences(parentDef);
+ if (explosionDamageType == null)
+ {
+ explosionDamageType = DamageDefOf.Bomb;
+ }
+ }
+}
\ No newline at end of file