diff --git a/.snow/handoff_drop_pod_intercept.md b/.snow/handoff_drop_pod_intercept.md
new file mode 100644
index 0000000..2004b12
--- /dev/null
+++ b/.snow/handoff_drop_pod_intercept.md
@@ -0,0 +1,112 @@
+# 落地交付文档:天巫集群掠食 - 空投拦截系统
+
+## 1. 目标与结论
+- 目标:实现“敌方空投袭击可被天巫种拦截”的完整闭环(开关控制、拦截逻辑、视觉反馈、通知、持久化)。
+- 结论:核心功能已完成并通过编译,已具备交由 planer 进行方案审阅与验收测试的条件。
+
+## 2. 实现范围(按 plan.md 对齐)
+
+### 2.1 GameComponent 全局状态与拦截逻辑
+- 新增文件:`Source/ArachnaeSwarm/Flyover/GameComponent_DropPodInterceptor.cs`
+- 已实现:
+ - `bool interceptEnabled` 持久化(`ExposeData` + `Scribe_Values.Look`)。
+ - `ToggleIntercept()` 开关切换与日志。
+ - `HasAirborneTianwu()` 检查 `WorldComponent_AircraftManager.GetAvailableAircraftCount(...) > 0`。
+ - `TryInterceptDropPods(...)`:
+ - 前置检查:开关、敌对派系、可用天巫、至少保留 1 名袭击者。
+ - 随机拦截 1-3 名(上限由 `pawns.Count - 1` 约束)。
+ - 拦截对象执行 `Pawn.Kill(DamageInfo)`,收集 `Corpse`。
+ - 用 `DropPodUtility.DropThingsNear(...)` 以空投仓形式落尸。
+ - 触发 FlyOver(复用 `ARA_HiveCorvette_Fake`)与信件通知。
+
+### 2.2 Harmony 补丁
+- 新增文件:`Source/ArachnaeSwarm/HarmonyPatches/Patch_DropPodIntercept.cs`
+- 已实现:
+ - Prefix 挂钩:
+ - `PawnsArrivalModeWorker_EdgeDrop.Arrive`
+ - `PawnsArrivalModeWorker_CenterDrop.Arrive`
+ - 两个入口共用 `InterceptPrefix(...)`。
+ - **不跳过原方法**(`return true`),原方法继续处理剩余 `pawns`。
+
+### 2.3 引航种能力(开关)
+- 新增文件:`Source/ArachnaeSwarm/Abilities/CompAbilityEffect_ToggleDropPodIntercept.cs`
+- 已实现:
+ - `CompProperties_ToggleDropPodIntercept`
+ - `CompAbilityEffect_ToggleDropPodIntercept`
+ - `Apply`:切换全局开关 + 消息提示。
+ - `Valid`:无可用天巫时拒绝施放并提示。
+ - `ExtraLabelMouseAttachment`:显示“开启/关闭”状态文本。
+
+### 2.4 Ability Def
+- 新增文件:`1.6/1.6/Defs/AbilityDefs/Ability_DropPodIntercept.xml`
+- 已实现:
+ - 新能力 `ARA_ToggleDropPodIntercept`
+ - 自施放、`targetRequired=false`、`targetable=false`、无冷却切换。
+
+### 2.5 挂载到 Skyraider
+- 修改文件:`1.6/1.6/Defs/PawnKindDef/ARA_PawnKinds.xml`
+- 已实现:
+ - 在 `ArachnaeNode_Race_Skyraider` 的 `abilities` 中追加:`ARA_ToggleDropPodIntercept`
+
+### 2.6 本地化
+- 修改文件:`1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/AirStrike_Keys.xml`
+- 已实现 key:
+ - `ARA_ToggleDropPodIntercept_Label`
+ - `ARA_ToggleDropPodIntercept_Desc`
+ - `ARA_InterceptDropPod_Enabled`
+ - `ARA_InterceptDropPod_Disabled`
+ - `ARA_InterceptDropPod_NoAircraft`
+ - `ARA_InterceptDropPod_Status`
+ - `ARA_InterceptDropPod_StatusOn`
+ - `ARA_InterceptDropPod_StatusOff`
+ - `ARA_InterceptDropPod_LetterLabel`
+ - `ARA_InterceptDropPod_LetterText`
+
+### 2.7 工程文件同步
+- 修改文件:`Source/ArachnaeSwarm/ArachnaeSwarm.csproj`
+- 已实现:新增 3 个 C# 文件的 ``。
+
+## 3. 与 plan.md 的差异说明(供 planer 决策)
+- FlyOver Def:按 plan 的“优先复用”策略,当前复用 `ARA_HiveCorvette_Fake`,**未新增** `ARA_HiveCorvette_Intercept` ThingDef。
+- `CompAbilityEffect_ToggleDropPodIntercept.Valid` 使用单目标签名(与现项目其他 Ability 风格一致),未采用数组签名版本。
+- 能力 label/description 当前写在 AbilityDef 内,key 已补全;若需严格 DefInjected 化,可由 planer 决定是否二次整理。
+
+## 4. 构建与验证
+- 构建命令(已执行):
+ - `MSBuild ArachnaeSwarm.csproj -p:Configuration=Release -verbosity:minimal`
+- 结果:通过。
+- 输出:
+ - `1.6/1.6/Assemblies/ArachnaeSwarm.dll`
+ - `1.6/1.6/Assemblies/ArachnaeSwarm.pdb`
+
+## 5. 建议的审阅清单(给 planer)
+- 逻辑正确性:
+ - 是否接受“至少保留 1 名袭击者”的平衡策略。
+ - 是否接受“仅敌对派系 + EdgeDrop/CenterDrop 生效”的作用域。
+- 体验反馈:
+ - FlyOver 速度、出现时机、信件文案是否符合预期。
+- 兼容性:
+ - 与其他修改袭击到场逻辑的 Harmony 补丁是否可能冲突。
+- 本地化策略:
+ - 是否要求将 AbilityDef `label/description` 进一步改为 DefInjected。
+
+## 6. 建议测试用例(未在本轮自动化执行)
+- Dev 触发 `Raid (EdgeDrop)`:验证拦截 1-3,尸体空投、FlyOver、信件。
+- Dev 触发 `Raid (CenterDrop)`:同上。
+- 关闭拦截后再触发空投:验证不拦截。
+- 触发 `EdgeWalkIn`:验证不拦截。
+- 触发友军空投:验证不拦截。
+- 存档/读档:验证 `interceptEnabled` 状态持久化。
+
+## 7. 当前改动文件清单
+- `Source/ArachnaeSwarm/Flyover/GameComponent_DropPodInterceptor.cs`(新增)
+- `Source/ArachnaeSwarm/HarmonyPatches/Patch_DropPodIntercept.cs`(新增)
+- `Source/ArachnaeSwarm/Abilities/CompAbilityEffect_ToggleDropPodIntercept.cs`(新增)
+- `1.6/1.6/Defs/AbilityDefs/Ability_DropPodIntercept.xml`(新增)
+- `1.6/1.6/Defs/PawnKindDef/ARA_PawnKinds.xml`(修改)
+- `1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/AirStrike_Keys.xml`(修改)
+- `Source/ArachnaeSwarm/ArachnaeSwarm.csproj`(修改)
+
+---
+
+如需我继续,可下一步直接输出“planer审阅意见处理版”补丁(按审阅结论二改)。
diff --git a/.snow/plan.md b/.snow/plan.md
new file mode 100644
index 0000000..835be26
--- /dev/null
+++ b/.snow/plan.md
@@ -0,0 +1,134 @@
+# Plan: 天巫集群掠食 — 空投拦截系统
+
+**TL;DR**:通过 Harmony Prefix 补丁拦截原版 `EdgeDrop` 和 `CenterDrop` 的 `Arrive()` 方法,在敌方空投仓落地前由天巫种拦截 1-3 个运输仓。击杀后尸体仍以运输仓形式落地。使用 `GameComponent` 全局管理开关状态,引航种 Pawn 通过自释放 `AbilityDef` 切换开关。拦截时生成天巫种 FlyOver 作为视觉反馈。
+
+## 架构概览
+
+```
+[敌方袭击触发]
+IncidentWorker_RaidEnemy → Arrive(pawns, parms)
+ ↓ Harmony Prefix
+[新增] Patch_DropPodIntercept
+ → GameComponent_DropPodInterceptor.TryIntercept()
+ ├── 检查 interceptEnabled (引航种toggle)
+ ├── 检查 WorldComponent_AircraftManager 有可用天巫
+ ├── 验证 parms.faction.HostileTo(Player)
+ ├── 随机选取 1-3 pawns → Kill → 获取 Corpse
+ ├── 用 DropPodUtility.DropThingsNear 投掷尸体
+ ├── FlyOver.MakeFlyOver() 生成拦截飞越视觉
+ └── ReceiveLetter 通知玩家
+ → 原 Arrive 继续执行(剩余 pawn 正常空投)
+
+[引航种能力]
+ArachnaeNode_Race_Skyraider → AbilityDef: ARA_ToggleDropPodIntercept
+ → CompAbilityEffect_ToggleDropPodIntercept.Apply()
+ → GameComponent_DropPodInterceptor.ToggleIntercept()
+```
+
+---
+
+## Steps
+
+### 1. 创建全局状态管理 `GameComponent_DropPodInterceptor`
+
+新文件:`Source/ArachnaeSwarm/Flyover/GameComponent_DropPodInterceptor.cs`
+
+- 继承 `GameComponent`,序列化字段 `bool interceptEnabled`
+- 属性 `IsInterceptEnabled` — 外部查询开关状态
+- 方法 `ToggleIntercept()` — 翻转开关 + `ArachnaeLog.Debug`
+- 方法 `HasAirborneTianwu()` — 查询 `WorldComponent_AircraftManager`:检查 `GetAvailableAircraftCount(ThingDef ARA_HiveCorvette_Entity, Faction.OfPlayer) > 0`(非全部冷却中即可,不消耗资源)
+- 核心方法 `TryInterceptDropPods(List pawns, IncidentParms parms, out List interceptedPawns)` — 完整拦截逻辑:
+ - 前置条件检查(`interceptEnabled` && `HasAirborneTianwu()` && `parms.faction.HostileTo(Faction.OfPlayer)`)
+ - 从 `pawns` 中随机移除 `Rand.RangeInclusive(1, Mathf.Min(3, pawns.Count - 1))` 个 Pawn(至少保留 1 个 pawn 正常空投,避免完全吞掉袭击)
+ - 对每个被拦截的 Pawn:调用 `pawn.Kill(new DamageInfo(DamageDefOf.Bomb, 9999f))`,收集 `pawn.Corpse` 到尸体列表
+ - 将尸体通过 `DropPodUtility.DropThingsNear(parms.spawnCenter, map, corpses, leaveSlag: true)` 投掷到同一空投区域
+ - 调用 `SpawnInterceptionFlyOver(map, parms.spawnCenter)` 生成天巫飞越视觉
+ - 调用 `SendInterceptionLetter(map, interceptedCount, parms.spawnCenter)` 发送信件
+- 方法 `SpawnInterceptionFlyOver(Map, IntVec3)` — 调用 `FlyOver.MakeFlyOver()` 生成 `ARA_HiveCorvette_Fake`(复用现有视觉 FlyOver ThingDef),起点从地图边缘到空投中心飞越
+- 方法 `SendInterceptionLetter(Map, int count, IntVec3)` — 发送自定义 `LetterDefOf.PositiveEvent` 信件,告知玩家拦截了多少运输仓
+- `ExposeData()` — `Scribe_Values.Look(ref interceptEnabled, "interceptEnabled", false)`
+
+### 2. 创建 Harmony 补丁 `Patch_DropPodIntercept`
+
+新文件:`Source/ArachnaeSwarm/HarmonyPatches/Patch_DropPodIntercept.cs`
+
+- `[HarmonyPatch(typeof(PawnsArrivalModeWorker_EdgeDrop), "Arrive")]` — Prefix
+- `[HarmonyPatch(typeof(PawnsArrivalModeWorker_CenterDrop), "Arrive")]` — Prefix
+- 两个 Prefix 共用同一个静态方法 `InterceptPrefix(List pawns, IncidentParms parms)`
+- Prefix 逻辑:获取 `Current.Game.GetComponent()`,调用 `TryInterceptDropPods(pawns, parms)`
+- **不 skip 原方法**(`return true`),原方法继续用被修改过的 `pawns` 列表正常空投剩余敌人
+
+### 3. 创建引航种切换能力 `CompAbilityEffect_ToggleDropPodIntercept`
+
+新文件:`Source/ArachnaeSwarm/Abilities/CompAbilityEffect_ToggleDropPodIntercept.cs`
+
+- `CompProperties_ToggleDropPodIntercept` 继承 `CompProperties_AbilityEffect`,包含字段:
+ - `string enabledMessage` / `disabledMessage` — 开启/关闭时的消息文本 key
+ - `ThingDef requiredAircraftType` — 需要检查的战机类型(`ARA_HiveCorvette_Entity`)
+- `CompAbilityEffect_ToggleDropPodIntercept` 继承 `CompAbilityEffect`:
+ - `Apply(LocalTargetInfo, LocalTargetInfo)` — 获取 `GameComponent_DropPodInterceptor`,调用 `ToggleIntercept()`,发送 `Messages.Message` 通知当前状态
+ - `Valid(LocalTargetInfo[], bool)` — 检查 `WorldComponent_AircraftManager.HasAvailableAircraft` 是否有天巫升空;无天巫时禁用能力并显示 "无可用天巫种" 提示
+ - `ExtraLabelMouseAttachment(LocalTargetInfo)` — 返回当前状态文本("掠食巡航: 开启/关闭")
+
+### 4. 创建拦截 FlyOver 视觉 ThingDef
+
+修改现有文件 `1.6/1.6/Defs/Thing_Misc/ARA_Flyover_Item.xml`,新增 `ARA_HiveCorvette_Intercept` ThingDef:
+
+- 以 `ARA_HiveCorvette_Fake` 为模板(纯视觉 FlyOver,无攻击 Comp)
+- `thingClass="ArachnaeSwarm.FlyOver"`
+- 设置较快的 `flightSpeed`(拦截应该是快速掠过)
+- 可选添加 `CompProperties_SendLetterAfterTicks` 以在飞越后发出完成通知
+- 或直接复用 `ARA_HiveCorvette_Fake` defName,不新建 ThingDef
+
+### 5. 创建能力 XML 定义
+
+新文件:`1.6/1.6/Defs/AbilityDefs/Ability_DropPodIntercept.xml`
+
+- `AbilityDef` defName: `ARA_ToggleDropPodIntercept`
+- `label`: 掠食巡航(或类似命名)
+- `targetRequired: false`(自释放,无需目标)
+- `cooldownTicksRange: 0`(无冷却,即时切换)
+- `comps`:
+ - `CompProperties_ToggleDropPodIntercept`(`requiredAircraftType: ARA_HiveCorvette_Entity`)
+
+### 6. 将能力添加到引航种
+
+查找并修改引航种 `ArachnaeNode_Race_Skyraider` 的能力列表定义(可能在 `1.6/1.6/Defs/PawnKindDef/ARA_PawnKinds.xml` 或 Race ThingDef 中),在 `abilities` 列表中添加 `ARA_ToggleDropPodIntercept`
+
+### 7. 添加本地化文本
+
+修改 `1.6/1.6/Languages/ChineseSimplified/Keyed/` 下的翻译文件,添加:
+
+- `ARA_ToggleDropPodIntercept_Label` — "掠食巡航"
+- `ARA_ToggleDropPodIntercept_Desc` — 能力描述
+- `ARA_InterceptDropPod_Enabled` — "掠食巡航已启动"
+- `ARA_InterceptDropPod_Disabled` — "掠食巡航已关闭"
+- `ARA_InterceptDropPod_LetterLabel` — "天巫种拦截空投"
+- `ARA_InterceptDropPod_LetterText` — "天巫种在空中拦截了{0}个敌方运输仓…"
+- `ARA_InterceptDropPod_NoAircraft` — "没有可用的天巫种兽虫"
+
+---
+
+## Verification
+
+1. MSBuild 编译:`cd "ArachnaeSwarm\Source\ArachnaeSwarm" && MSBuild ArachnaeSwarm.csproj -p:Configuration=Release`
+2. 游戏内测试流程:
+ - 建造天巫种机库 → 起飞(注册战机到 WorldComponent_AircraftManager)
+ - 使用引航种能力开启"掠食巡航"
+ - 使用 dev console 触发 `Raid (EdgeDrop)` → 验证 1-3 个运输仓被拦截(尸体掉落 + FlyOver 视觉 + 信件)
+ - 使用 dev console 触发 `Raid (CenterDrop)` → 同上
+ - 关闭"掠食巡航" → 再次触发空投 → 验证不拦截
+ - 触发非空投袭击(EdgeWalkIn) → 验证不触发拦截
+ - 触发友方空投 → 验证不拦截(HostileTo 检查)
+3. 存档/读档测试:验证 `interceptEnabled` 状态持久化
+
+---
+
+## Decisions
+
+- **Harmony 挂钩点**:选 `PawnsArrivalModeWorker_EdgeDrop.Arrive` + `CenterDrop.Arrive` 而非底层 `DropPodUtility`,因为只需响应这两种袭击到场模式,不影响其他空投场景(贸易、任务奖励等)
+- **GameComponent vs MapComponent**:选 `GameComponent`(全局,跨地图),因为用户明确说"全局管理"
+- **不消耗战机资源**:只检查 `HasAvailableAircraft` 判断天巫是否升空,不调用 `TryUseAircraft`
+- **至少保留 1 个 pawn**:`Mathf.Min(3, pawns.Count - 1)` 确保不会完全吞掉袭击,玩家仍需应战
+- **Kill + Corpse 方案**:调用 `Pawn.Kill(DamageInfo)` 后获取 `Corpse`,再通过 `DropPodUtility.DropThingsNear` 以运输仓形式投掷尸体,既有"被击杀"的反馈感,又能剥削敌方装备
+- **复用 `ARA_HiveCorvette_Fake`**:优先复用现有纯视觉 FlyOver,避免新增无意义 ThingDef;若需要不同飞行参数再另建
diff --git a/1.6/1.6/Assemblies/ArachnaeSwarm.dll b/1.6/1.6/Assemblies/ArachnaeSwarm.dll
index b4ef638..417599b 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/Assemblies/ArachnaeSwarm.pdb b/1.6/1.6/Assemblies/ArachnaeSwarm.pdb
index 39f8378..98059d8 100644
Binary files a/1.6/1.6/Assemblies/ArachnaeSwarm.pdb and b/1.6/1.6/Assemblies/ArachnaeSwarm.pdb differ
diff --git a/1.6/1.6/Defs/AbilityDefs/Ability_DropPodIntercept.xml b/1.6/1.6/Defs/AbilityDefs/Ability_DropPodIntercept.xml
new file mode 100644
index 0000000..1689770
--- /dev/null
+++ b/1.6/1.6/Defs/AbilityDefs/Ability_DropPodIntercept.xml
@@ -0,0 +1,31 @@
+
+
+
+ ARA_ToggleDropPodIntercept
+
+ 切换天巫种对敌方空投袭击的拦截模式。开启后,敌方空投到达前会被随机拦截一部分运输仓。
+ ArachnaeSwarm/UI/Abilities/ARA_Spawn_ARA_HiveCorvette_Strike
+ 0
+ false
+ false
+
+ Verb_CastAbility
+ false
+ false
+ true
+ 0
+ false
+
+ True
+
+
+
+
+ ARA_InterceptDropPod_Enabled
+ ARA_InterceptDropPod_Disabled
+ ARA_InterceptDropPod_NoAircraft
+ ARA_HiveCorvette_Entity
+
+
+
+
diff --git a/1.6/1.6/Defs/PawnKindDef/ARA_PawnKinds.xml b/1.6/1.6/Defs/PawnKindDef/ARA_PawnKinds.xml
index 23af037..78664ef 100644
--- a/1.6/1.6/Defs/PawnKindDef/ARA_PawnKinds.xml
+++ b/1.6/1.6/Defs/PawnKindDef/ARA_PawnKinds.xml
@@ -356,6 +356,7 @@
ARA_Skyraider_jump
+ ARA_ToggleDropPodIntercept
@@ -699,4 +700,4 @@
ARA_Ability_SlayerCharge
-
\ No newline at end of file
+
diff --git a/1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/AirStrike_Keys.xml b/1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/AirStrike_Keys.xml
index ff5d420..dfe7ad7 100644
--- a/1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/AirStrike_Keys.xml
+++ b/1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/AirStrike_Keys.xml
@@ -50,4 +50,16 @@
{0} 准备好再次进行打击
没有可用的兽虫
{0}:{1}/{2}(冷却中:{3})
-
\ No newline at end of file
+
+
+ 掠食巡航
+ 切换天巫种对敌方空投袭击的拦截模式。
+ 掠食巡航已启动
+ 掠食巡航已关闭
+ 没有可用的天巫种兽虫
+ 掠食巡航:{0}
+ 开启
+ 关闭
+ 天巫种拦截空投
+ 天巫种在空中拦截了 {0} 个敌方运输仓,目标已坠毁并以空投舱形式落地。
+
diff --git a/Source/ArachnaeSwarm/Abilities/CompAbilityEffect_ToggleDropPodIntercept.cs b/Source/ArachnaeSwarm/Abilities/CompAbilityEffect_ToggleDropPodIntercept.cs
new file mode 100644
index 0000000..10242ce
--- /dev/null
+++ b/Source/ArachnaeSwarm/Abilities/CompAbilityEffect_ToggleDropPodIntercept.cs
@@ -0,0 +1,79 @@
+using RimWorld;
+using Verse;
+
+namespace ArachnaeSwarm
+{
+ public class CompProperties_ToggleDropPodIntercept : CompProperties_AbilityEffect
+ {
+ public string enabledMessage = "ARA_InterceptDropPod_Enabled";
+ public string disabledMessage = "ARA_InterceptDropPod_Disabled";
+ public string noAircraftMessage = "ARA_InterceptDropPod_NoAircraft";
+ public ThingDef requiredAircraftType;
+
+ public CompProperties_ToggleDropPodIntercept()
+ {
+ compClass = typeof(CompAbilityEffect_ToggleDropPodIntercept);
+ }
+ }
+
+ public class CompAbilityEffect_ToggleDropPodIntercept : CompAbilityEffect
+ {
+ public new CompProperties_ToggleDropPodIntercept Props => (CompProperties_ToggleDropPodIntercept)props;
+
+ public override void Apply(LocalTargetInfo target, LocalTargetInfo dest)
+ {
+ base.Apply(target, dest);
+
+ GameComponent_DropPodInterceptor interceptor = Current.Game?.GetComponent();
+ if (interceptor == null)
+ {
+ return;
+ }
+
+ bool enabled = interceptor.ToggleIntercept();
+ string messageKey = enabled ? Props.enabledMessage : Props.disabledMessage;
+ Messages.Message(messageKey.Translate(), parent.pawn, MessageTypeDefOf.PositiveEvent);
+ }
+
+ public override bool Valid(LocalTargetInfo target, bool throwMessages = false)
+ {
+ if (!base.Valid(target, throwMessages))
+ {
+ return false;
+ }
+
+ GameComponent_DropPodInterceptor interceptor = Current.Game?.GetComponent();
+ if (interceptor == null)
+ {
+ return false;
+ }
+
+ if (!interceptor.HasAirborneTianwu(Props.requiredAircraftType))
+ {
+ if (throwMessages)
+ {
+ Messages.Message(Props.noAircraftMessage.Translate(), parent.pawn, MessageTypeDefOf.RejectInput);
+ }
+
+ return false;
+ }
+
+ return true;
+ }
+
+ public override string ExtraLabelMouseAttachment(LocalTargetInfo target)
+ {
+ GameComponent_DropPodInterceptor interceptor = Current.Game?.GetComponent();
+ if (interceptor == null)
+ {
+ return base.ExtraLabelMouseAttachment(target);
+ }
+
+ string status = interceptor.IsInterceptEnabled
+ ? "ARA_InterceptDropPod_StatusOn".Translate()
+ : "ARA_InterceptDropPod_StatusOff".Translate();
+
+ return "ARA_InterceptDropPod_Status".Translate(status);
+ }
+ }
+}
diff --git a/Source/ArachnaeSwarm/ArachnaeSwarm.csproj b/Source/ArachnaeSwarm/ArachnaeSwarm.csproj
index 7137873..ad4f9f9 100644
--- a/Source/ArachnaeSwarm/ArachnaeSwarm.csproj
+++ b/Source/ArachnaeSwarm/ArachnaeSwarm.csproj
@@ -137,6 +137,7 @@
+
@@ -269,10 +270,12 @@
+
+
@@ -467,4 +470,4 @@
-
\ No newline at end of file
+
diff --git a/Source/ArachnaeSwarm/Flyover/GameComponent_DropPodInterceptor.cs b/Source/ArachnaeSwarm/Flyover/GameComponent_DropPodInterceptor.cs
new file mode 100644
index 0000000..8633eb4
--- /dev/null
+++ b/Source/ArachnaeSwarm/Flyover/GameComponent_DropPodInterceptor.cs
@@ -0,0 +1,177 @@
+using RimWorld;
+using System.Collections.Generic;
+using System.Linq;
+using UnityEngine;
+using Verse;
+
+namespace ArachnaeSwarm
+{
+ public class GameComponent_DropPodInterceptor : GameComponent
+ {
+ private const string DefaultAircraftDefName = "ARA_HiveCorvette_Entity";
+ private const string DefaultInterceptFlyOverDefName = "ARA_HiveCorvette_Fake";
+
+ private bool interceptEnabled;
+
+ public bool IsInterceptEnabled => interceptEnabled;
+
+ public GameComponent_DropPodInterceptor(Game game)
+ {
+ }
+
+ public bool ToggleIntercept()
+ {
+ interceptEnabled = !interceptEnabled;
+ ArachnaeLog.Debug($"DropPodInterceptor toggled: {interceptEnabled}");
+ return interceptEnabled;
+ }
+
+ public bool HasAirborneTianwu(ThingDef requiredAircraftDef = null)
+ {
+ WorldComponent_AircraftManager manager = Find.World?.GetComponent();
+ if (manager == null || Faction.OfPlayer == null)
+ {
+ return false;
+ }
+
+ ThingDef aircraftDef = requiredAircraftDef ?? DefDatabase.GetNamedSilentFail(DefaultAircraftDefName);
+ if (aircraftDef == null)
+ {
+ ArachnaeLog.Debug($"DropPodInterceptor: missing aircraft def {DefaultAircraftDefName}");
+ return false;
+ }
+
+ return manager.GetAvailableAircraftCount(aircraftDef, Faction.OfPlayer) > 0;
+ }
+
+ public bool TryInterceptDropPods(List pawns, IncidentParms parms, out List interceptedPawns)
+ {
+ interceptedPawns = new List();
+
+ if (pawns == null || pawns.Count <= 1 || !interceptEnabled)
+ {
+ return false;
+ }
+
+ if (parms == null || parms.faction == null || Faction.OfPlayer == null || !parms.faction.HostileTo(Faction.OfPlayer))
+ {
+ return false;
+ }
+
+ if (!HasAirborneTianwu())
+ {
+ return false;
+ }
+
+ Map map = parms.target as Map;
+ if (map == null)
+ {
+ ArachnaeLog.Debug("DropPodInterceptor: target map missing.");
+ return false;
+ }
+
+ int validPawnCount = pawns.Count(p => p != null);
+ if (validPawnCount <= 1)
+ {
+ return false;
+ }
+
+ int maxInterceptCount = Mathf.Min(3, validPawnCount - 1);
+ int interceptCount = Rand.RangeInclusive(1, maxInterceptCount);
+
+ List selected = pawns.Where(p => p != null).InRandomOrder().Take(interceptCount).ToList();
+ if (selected.Count == 0)
+ {
+ return false;
+ }
+
+ List corpses = new List();
+ foreach (Pawn pawn in selected)
+ {
+ if (!pawns.Remove(pawn))
+ {
+ continue;
+ }
+
+ interceptedPawns.Add(pawn);
+
+ if (!pawn.Dead)
+ {
+ pawn.Kill(new DamageInfo(DamageDefOf.Bite, 9999f));
+ }
+
+ Corpse corpse = pawn.Corpse;
+ if (corpse != null && !corpse.Spawned && !corpse.Destroyed)
+ {
+ corpses.Add(corpse);
+ }
+ }
+
+ if (interceptedPawns.Count == 0)
+ {
+ return false;
+ }
+
+ IntVec3 dropCenter = parms.spawnCenter.IsValid ? parms.spawnCenter : map.Center;
+ if (corpses.Count > 0)
+ {
+ DropPodUtility.DropThingsNear(dropCenter, map, corpses, leaveSlag: true);
+ }
+
+ SpawnInterceptionFlyOver(map, dropCenter);
+ SendInterceptionLetter(map, interceptedPawns.Count, dropCenter);
+
+ ArachnaeLog.Debug($"DropPodInterceptor: intercepted {interceptedPawns.Count} raid pawns.");
+ return true;
+ }
+
+ private void SpawnInterceptionFlyOver(Map map, IntVec3 dropCenter)
+ {
+ ThingDef flyOverDef = DefDatabase.GetNamedSilentFail(DefaultInterceptFlyOverDefName);
+ if (flyOverDef == null)
+ {
+ ArachnaeLog.Debug($"DropPodInterceptor: missing fly over def {DefaultInterceptFlyOverDefName}.");
+ return;
+ }
+
+ IntVec3 start = GetRandomMapEdgeCell(map);
+ IntVec3 end = dropCenter.IsValid && dropCenter.InBounds(map) ? dropCenter : map.Center;
+
+ FlyOver.MakeFlyOver(flyOverDef, start, end, map, speed: 5f, height: 12f);
+ }
+
+ private static IntVec3 GetRandomMapEdgeCell(Map map)
+ {
+ int edge = Rand.RangeInclusive(0, 3);
+ switch (edge)
+ {
+ case 0:
+ return new IntVec3(Rand.RangeInclusive(0, map.Size.x - 1), 0, 0);
+ case 1:
+ return new IntVec3(map.Size.x - 1, 0, Rand.RangeInclusive(0, map.Size.z - 1));
+ case 2:
+ return new IntVec3(Rand.RangeInclusive(0, map.Size.x - 1), 0, map.Size.z - 1);
+ default:
+ return new IntVec3(0, 0, Rand.RangeInclusive(0, map.Size.z - 1));
+ }
+ }
+
+ private void SendInterceptionLetter(Map map, int interceptedCount, IntVec3 dropCenter)
+ {
+ string label = "ARA_InterceptDropPod_LetterLabel".Translate();
+ string text = "ARA_InterceptDropPod_LetterText".Translate(interceptedCount);
+
+ Find.LetterStack.ReceiveLetter(
+ label,
+ text,
+ LetterDefOf.PositiveEvent,
+ new TargetInfo(dropCenter, map));
+ }
+
+ public override void ExposeData()
+ {
+ base.ExposeData();
+ Scribe_Values.Look(ref interceptEnabled, "interceptEnabled", false);
+ }
+ }
+}
diff --git a/Source/ArachnaeSwarm/HarmonyPatches/Patch_DropPodIntercept.cs b/Source/ArachnaeSwarm/HarmonyPatches/Patch_DropPodIntercept.cs
new file mode 100644
index 0000000..904dab5
--- /dev/null
+++ b/Source/ArachnaeSwarm/HarmonyPatches/Patch_DropPodIntercept.cs
@@ -0,0 +1,46 @@
+using HarmonyLib;
+using RimWorld;
+using System;
+using System.Collections.Generic;
+using Verse;
+
+namespace ArachnaeSwarm
+{
+ [HarmonyPatch(typeof(PawnsArrivalModeWorker_EdgeDrop), nameof(PawnsArrivalModeWorker_EdgeDrop.Arrive))]
+ public static class Patch_DropPodIntercept_EdgeDrop
+ {
+ [HarmonyPrefix]
+ public static bool Prefix(List pawns, IncidentParms parms)
+ {
+ return Patch_DropPodIntercept.InterceptPrefix(pawns, parms);
+ }
+ }
+
+ [HarmonyPatch(typeof(PawnsArrivalModeWorker_CenterDrop), nameof(PawnsArrivalModeWorker_CenterDrop.Arrive))]
+ public static class Patch_DropPodIntercept_CenterDrop
+ {
+ [HarmonyPrefix]
+ public static bool Prefix(List pawns, IncidentParms parms)
+ {
+ return Patch_DropPodIntercept.InterceptPrefix(pawns, parms);
+ }
+ }
+
+ public static class Patch_DropPodIntercept
+ {
+ public static bool InterceptPrefix(List pawns, IncidentParms parms)
+ {
+ try
+ {
+ GameComponent_DropPodInterceptor interceptor = Current.Game?.GetComponent();
+ interceptor?.TryInterceptDropPods(pawns, parms, out _);
+ }
+ catch (Exception ex)
+ {
+ ArachnaeLog.Debug($"DropPodInterceptor prefix exception: {ex}");
+ }
+
+ return true;
+ }
+ }
+}