diff --git a/1.6/1.6/Assemblies/WulaFallenEmpire.dll b/1.6/1.6/Assemblies/WulaFallenEmpire.dll
index 15fffd0b..4c9b51c4 100644
Binary files a/1.6/1.6/Assemblies/WulaFallenEmpire.dll and b/1.6/1.6/Assemblies/WulaFallenEmpire.dll differ
diff --git a/1.6/1.6/Defs/AbilityDefs/WULA_Flyover_Ability.xml b/1.6/1.6/Defs/AbilityDefs/WULA_Flyover_Ability.xml
index 85eaf6f1..4233a8cc 100644
--- a/1.6/1.6/Defs/AbilityDefs/WULA_Flyover_Ability.xml
+++ b/1.6/1.6/Defs/AbilityDefs/WULA_Flyover_Ability.xml
@@ -217,6 +217,56 @@
+
+ WULA_Spawn_BattleShip_Artillery
+
+ 申请沿指定航道发起全域封锁,一整只乌拉帝国舰队将在大量战机编队的掩护下沿着航道行进,并使用所有的可用武器进行轰炸,以彻底粉碎一切抵抗。
+ Wula/UI/Abilities/WULA_Spawn_Fighter_Drone_Laser
+ 1
+ Misc12
+ false
+
+ Verb_CastAbility
+ false
+ false
+ 0
+ 120
+ true
+
+ false
+ true
+
+
+
+
+
+
+ WULA_MotherShip_Planet_Interdiction
+ GroundStrafing
+ 0.005
+ 20
+ true
+ Perpendicular
+
+
+ true
+
+
+ false
+
+
+ true
+ (0.3,0.7,1.0,0.3)
+
+
+
+
WULA_Spawn_Fighter_Drone_Laser
diff --git a/1.6/1.6/Defs/EventDefs/EventDef_Wula/Wula_MainEvent.xml b/1.6/1.6/Defs/EventDefs/EventDef_Wula/Wula_MainEvent.xml
index 28342a2f..deabc91d 100644
--- a/1.6/1.6/Defs/EventDefs/EventDef_Wula/Wula_MainEvent.xml
+++ b/1.6/1.6/Defs/EventDefs/EventDef_Wula/Wula_MainEvent.xml
@@ -13,7 +13,7 @@
-
+
true
(255,255,255,255)
(157,201,185,195)
@@ -23,6 +23,24 @@
+
+ 陆行舰正在逼近
+ 艾妮西娅按照要求,吸引了一艘乌拉帝国的陆行舰机械体攻击我们的殖民地!
+ 100
+ Mechanoid
+ ImmediateAttack
+ EdgeWalkIn
+ Combat
+
+
+ Combat
+ 100
+
+ 100
+
+
+
+
diff --git a/1.6/1.6/Defs/HediffDefs/WULA_FM_Hediffs.xml b/1.6/1.6/Defs/HediffDefs/WULA_FM_Hediffs.xml
index 9aef23a2..9c358982 100644
--- a/1.6/1.6/Defs/HediffDefs/WULA_FM_Hediffs.xml
+++ b/1.6/1.6/Defs/HediffDefs/WULA_FM_Hediffs.xml
@@ -105,6 +105,7 @@
WULA_CallAircraftCarrier
WULA_CallConstructionShip
WULA_ClearFlightPath
+ WULA_Spawn_BattleShip_Artillery
diff --git a/1.6/1.6/Defs/StoryTellers/WULA_Storytellers.xml b/1.6/1.6/Defs/StoryTellers/WULA_Storytellers.xml
index e27f8ab8..388414f8 100644
--- a/1.6/1.6/Defs/StoryTellers/WULA_Storytellers.xml
+++ b/1.6/1.6/Defs/StoryTellers/WULA_Storytellers.xml
@@ -181,17 +181,22 @@
1
-
-
+
+
1
- WULA_GiveQuest_Intro_Spy
- WULA_Intro_Spy
+ WULA_GiveQuest_Intro_Spy
+ WULA_Intro_Spy
+ true
+ Allow
+
+ WULA_Awakened_Synth
+
+
Map_PlayerHome
-
- Ludeon.RimWorld.Odyssey
-
diff --git a/1.6/1.6/Defs/ThingDefs_Buildings/WULA_Turret_Buildings.xml b/1.6/1.6/Defs/ThingDefs_Buildings/WULA_Turret_Buildings.xml
index f6ad8e3c..75899fcc 100644
--- a/1.6/1.6/Defs/ThingDefs_Buildings/WULA_Turret_Buildings.xml
+++ b/1.6/1.6/Defs/ThingDefs_Buildings/WULA_Turret_Buildings.xml
@@ -750,7 +750,7 @@
true
52
- 32
+ 99999
1
WULA_RW_Handle_Cannon_Burn
1
diff --git a/1.6/1.6/Defs/ThingDefs_Misc/WULA_Flyover_Item.xml b/1.6/1.6/Defs/ThingDefs_Misc/WULA_Flyover_Item.xml
index 5b285193..92672aa3 100644
--- a/1.6/1.6/Defs/ThingDefs_Misc/WULA_Flyover_Item.xml
+++ b/1.6/1.6/Defs/ThingDefs_Misc/WULA_Flyover_Item.xml
@@ -673,6 +673,549 @@
+
+
+ WULA_MotherShip_Planet_Interdiction
+
+ WulaFallenEmpire.FlyOver
+ Normal
+ RealtimeOnly
+
+ Wula/FlyoverThing/WULA_MotherShip_Shadow
+ Graphic_Single
+ TransparentPostLight
+ (100,250)
+ (195,195,195,45)
+
+
+ Wula/Weapon/WULA_Weapon_Empty
+ (0, 0)
+ 0
+ FlyOver/Flying
+
+
+
+
+ Wula/Weapon/WULA_Weapon_Empty
+ true
+ 0.8
+ 0
+ 0
+ 0
+ 0
+
+
+ false
+ false
+ false
+ true
+ 1
+ 50
+
+
+ true
+ false
+ false
+ false
+ MetaOverlays
+
+
+ 300
+ 30
+ 65
+ WULA_Firepower_Primary_Cannon_Strafe_Skyfaller
+ 3
+
+
+ true
+ true
+
+
+
+ 60
+ 全域封锁
+ 全域封锁舰队已抵达,请自行寻找掩护!
+ PositiveEvent
+ true
+ true
+ false
+
+
+
+ WULA_MotherShip_Planet_Interdiction_Escort
+
+
+ 3000
+ 2
+ 1
+
+
+ 0
+ 40
+ 5
+ true
+ 10
+ 70
+
+
+ 1
+ 10
+ false
+
+
+ true
+ false
+ true
+
+
+ true
+
+
+
+ 0.3
+ 0.5
+
+
+
+ true
+
+ 0.6
+ 0.8
+
+ (0.7,0.85,1.0,1.0)
+ 1.3
+
+
+ WULA_BattleShip_Planet_Interdiction
+
+
+ 4000
+ 5
+ 1
+
+
+ 0
+ 70
+ 5
+ true
+ 10
+ 70
+
+
+ 1
+ 10
+ false
+
+
+ true
+ false
+ true
+
+
+ true
+
+
+
+ 0.3
+ 0.5
+
+
+
+ true
+
+ 0.6
+ 0.8
+
+ (0.7,0.85,1.0,1.0)
+ 1.3
+
+
+ WULA_Striker_Escort
+
+
+ 1000
+ 20
+ 1
+
+
+ 0
+ 100
+ 5
+ true
+ 10
+ 70
+
+
+ 8
+ 10
+ false
+
+
+ true
+ false
+ true
+
+
+ true
+
+
+
+ 0.3
+ 0.6
+
+
+
+ true
+
+ 0.6
+ 0.8
+
+ (0.7,0.85,1.0,1.0)
+ 1.3
+
+
+ WULA_Bomber_Escort
+
+
+ 1350
+ 10
+ 1
+
+
+ 0
+ 130
+ 5
+ true
+ 10
+ 70
+
+
+ 5
+ 10
+ false
+
+
+ true
+ false
+ true
+
+
+ true
+
+
+
+ 0.3
+ 0.6
+
+
+
+ true
+
+ 0.6
+ 0.8
+
+ (0.7,0.85,1.0,1.0)
+ 1.3
+
+
+
+
+ WULA_MotherShip_Planet_Interdiction_Escort
+
+ WulaFallenEmpire.FlyOver
+ Normal
+ RealtimeOnly
+
+ Wula/FlyoverThing/WULA_MotherShip_Shadow
+ Graphic_Single
+ TransparentPostLight
+ (100,250)
+ (195,195,195,45)
+
+
+ Wula/Weapon/WULA_Weapon_Empty
+ (0, 0)
+ 0
+ FlyOver/Flying
+
+
+
+
+ Wula/Weapon/WULA_Weapon_Empty
+ true
+ 0.8
+ 0
+ 0
+ 0
+ 0
+
+
+ false
+ false
+ false
+ true
+ 1
+ 50
+
+
+ true
+ false
+ false
+ false
+ MetaOverlays
+
+
+ 300
+ 300
+ 65
+ WULA_Firepower_Cannon_Salvo_Skyfaller
+ 12
+
+
+ true
+ true
+
+
+
+ WULA_Striker_Escort
+
+
+ 1000
+ 20
+ 1
+
+
+ 0
+ 100
+ 5
+ true
+ 10
+ 70
+
+
+ 8
+ 10
+ false
+
+
+ true
+ false
+ true
+
+
+ true
+
+
+
+ 0.3
+ 0.6
+
+
+
+ true
+
+ 0.6
+ 0.8
+
+ (0.7,0.85,1.0,1.0)
+ 1.3
+
+
+ WULA_Bomber_Escort
+
+
+ 1350
+ 10
+ 1
+
+
+ 0
+ 130
+ 5
+ true
+ 10
+ 70
+
+
+ 5
+ 10
+ false
+
+
+ true
+ false
+ true
+
+
+ true
+
+
+
+ 0.3
+ 0.6
+
+
+
+ true
+
+ 0.6
+ 0.8
+
+ (0.7,0.85,1.0,1.0)
+ 1.3
+
+
+
+
+ WULA_BattleShip_Planet_Interdiction
+
+ WulaFallenEmpire.FlyOver
+ Normal
+ RealtimeOnly
+
+ Wula/FlyoverThing/WULA_BattleShip_Shadow
+ Graphic_Single
+ TransparentPostLight
+ (70,100)
+ (195,195,195,45)
+
+
+ Wula/Weapon/WULA_Weapon_Empty
+ (0, 0)
+ 0
+ FlyOver/Flying
+
+
+
+
+ Wula/Weapon/WULA_Weapon_Empty
+ true
+ 0.8
+ 0
+ 0
+ 0
+ 0
+
+
+ false
+ false
+ false
+ true
+ 1
+ 50
+
+
+ true
+ false
+ false
+ false
+ MetaOverlays
+
+
+ 300
+ 30
+ 25
+ WULA_Planet_Interdiction_EnergyLance_Skyfaller
+ 1
+
+
+ true
+ true
+
+
+
+
+ WULA_Planet_Interdiction_EnergyLance_Skyfaller
+
+ (1,1)
+
+ Wula/Weapon/WULA_Weapon_Empty
+ Graphic_Single
+ TransparentPostLight
+ (1,1)
+ (255,255,255,150)
+
+ false
+
+
+
+ Decelerate
+ Things/Skyfaller/SkyfallerShadowDropPod
+ (0, 0)
+ DropPod_Fall
+ 100
+
+ 0.05
+ 0
+ 0
+
+
+ (0,0)
+ (1, 1)
+
+
+ WULA_Firepower_EnergyLance_Surveillance_Beacon
+
+
+
+ WULA_Planet_Interdiction_EnergyLance_Beacon
+
+ 一枚标定监视区的轰炸信标,进入此处的敌对势力都会被乌拉帝国舰队的舰炮狠狠打击。
+ Wula/Building/WULA_WeaponArmor_Productor
+ Normal
+ false
+ false
+ (1,1)
+
+ Wula/Weapon/WULA_Weapon_Empty
+ Graphic_Single
+ TransparentPostLight
+ (72,72)
+ (255,255,255,150)
+
+ false
+
+
+ Building
+ Standable
+ false
+ 0.5
+ false
+ 0
+ false
+ false
+
+ 1
+ 0
+ 0
+
+ 0
+
+ false
+ BuildingDestroyed_Metal_Small
+
+
+
+ WULA_EnergyLance_Surveillance
+ 600
+ 25
+ 36
+ 30
+ 20
+ 45
+ 180
+
+
+
+ true
+ false
+
+
+ 600
+
+
+
+
WulaFallenEmpire.FlyOver
diff --git a/Source/WulaFallenEmpire/Flyover/WULA_DestroyFlyOverByFacilities/CompProperties_DestroyFlyOverByFacilities.cs b/Source/WulaFallenEmpire/Flyover/WULA_DestroyFlyOverByFacilities/CompProperties_DestroyFlyOverByFacilities.cs
index 3063c5d8..745a8c87 100644
--- a/Source/WulaFallenEmpire/Flyover/WULA_DestroyFlyOverByFacilities/CompProperties_DestroyFlyOverByFacilities.cs
+++ b/Source/WulaFallenEmpire/Flyover/WULA_DestroyFlyOverByFacilities/CompProperties_DestroyFlyOverByFacilities.cs
@@ -24,33 +24,110 @@ namespace WulaFallenEmpire
if (parent.pawn?.Map == null) return;
- // 销毁所有 FlyOver 物体
- DestroyAllFlyOvers();
+ // 只销毁带有 CompFlyOverFacilities 的 FlyOver
+ DestroyFlyOversWithFacilities();
}
- // 销毁所有 FlyOver
- private void DestroyAllFlyOvers()
+ // 只销毁带有设施的 FlyOver
+ private void DestroyFlyOversWithFacilities()
{
- List flyOvers = new List();
+ List flyOversWithFacilities = new List();
- // 获取地图上所有的 FlyOver
- foreach (Thing thing in parent.pawn.Map.listerThings.AllThings)
+ // 使用 CompFlyOverFacilities 的静态方法来获取所有带有设施的 FlyOver
+ var allFlyOvers = CompFlyOverFacilities.GetAllFlyOversWithFacilities(parent.pawn.Map);
+
+ if (allFlyOvers.Count > 0)
{
- if (thing is FlyOver flyOver)
+ foreach (var flyOver in allFlyOvers)
{
- flyOvers.Add(flyOver);
+ if (flyOver != null && !flyOver.Destroyed)
+ {
+ flyOversWithFacilities.Add(flyOver);
+ }
}
}
- // 销毁找到的 FlyOver
- foreach (FlyOver flyOver in flyOvers)
+ // 销毁找到的带有设施的 FlyOver
+ foreach (FlyOver flyOver in flyOversWithFacilities)
{
flyOver.EmergencyDestroy();
+ Log.Message($"[DestroyFlyOverByFacilities] Destroyed FlyOver with facilities at {flyOver.Position}");
}
- if (flyOvers.Count > 0)
+ if (flyOversWithFacilities.Count > 0)
{
- Messages.Message($"WULA_DestroyFlyOver".Translate(), parent.pawn, MessageTypeDefOf.PositiveEvent);
+ Messages.Message($"WULA_DestroyFlyOver".Translate(flyOversWithFacilities.Count), parent.pawn, MessageTypeDefOf.PositiveEvent);
+ }
+ else
+ {
+ Messages.Message("WULA_NoFlyOverWithFacilities".Translate(), parent.pawn, MessageTypeDefOf.NeutralEvent);
+ }
+ }
+
+ // 添加验证方法,确保只在有相关 FlyOver 时可用
+ public override bool Valid(LocalTargetInfo target, bool throwMessages = false)
+ {
+ if (!base.Valid(target, throwMessages))
+ return false;
+
+ // 检查是否有带有设施的 FlyOver
+ if (parent.pawn?.Map == null)
+ return false;
+
+ var flyOversWithFacilities = CompFlyOverFacilities.GetAllFlyOversWithFacilities(parent.pawn.Map);
+
+ if (flyOversWithFacilities.Count == 0)
+ {
+ if (throwMessages)
+ {
+ Messages.Message("WULA_NoFlyOverWithFacilities".Translate(), parent.pawn, MessageTypeDefOf.RejectInput);
+ }
+ return false;
+ }
+
+ return true;
+ }
+
+ public override bool GizmoDisabled(out string reason)
+ {
+ if (parent.pawn?.Map == null)
+ {
+ reason = "Cannot use outside of map";
+ return true;
+ }
+
+ // 检查是否有带有设施的 FlyOver
+ var flyOversWithFacilities = CompFlyOverFacilities.GetAllFlyOversWithFacilities(parent.pawn.Map);
+
+ if (flyOversWithFacilities.Count == 0)
+ {
+ reason = "No FlyOver with facilities found";
+ return true;
+ }
+
+ return base.GizmoDisabled(out reason);
+ }
+
+ public override string ExtraLabelMouseAttachment(LocalTargetInfo target)
+ {
+ try
+ {
+ if (parent.pawn?.Map == null)
+ return "Cannot use outside of map";
+
+ var flyOversWithFacilities = CompFlyOverFacilities.GetAllFlyOversWithFacilities(parent.pawn.Map);
+
+ if (flyOversWithFacilities.Count > 0)
+ {
+ return $"Will destroy {flyOversWithFacilities.Count} FlyOver(s) with facilities";
+ }
+
+ return "No FlyOver with facilities found";
+ }
+ catch (System.Exception ex)
+ {
+ Log.Error($"[DestroyFlyOverByFacilities] Error in ExtraLabelMouseAttachment: {ex}");
+ return "Error checking FlyOver status";
}
}
}
diff --git a/Source/WulaFallenEmpire/Flyover/WULA_ShipArtillery/CompProperties_ShipArtillery.cs b/Source/WulaFallenEmpire/Flyover/WULA_ShipArtillery/CompProperties_ShipArtillery.cs
index 7963c01c..328dd556 100644
--- a/Source/WulaFallenEmpire/Flyover/WULA_ShipArtillery/CompProperties_ShipArtillery.cs
+++ b/Source/WulaFallenEmpire/Flyover/WULA_ShipArtillery/CompProperties_ShipArtillery.cs
@@ -42,11 +42,16 @@ namespace WulaFallenEmpire
public bool avoidHittingFlyOver = true;
// 信件通知
- public bool sendAttackLetter = true; // 是否发送攻击信件
+ public bool sendAttackLetter = false; // 是否发送攻击信件
public string customLetterLabel; // 自定义信件标题
public string customLetterText; // 自定义信件内容
public LetterDef letterDef = LetterDefOf.ThreatBig; // 信件类型
+ // 新增:派系甄别系统
+ public bool useFactionDiscrimination = false; // 是否使用派系甄别
+ public FactionDef targetFaction; // 目标派系(友军派系)
+ public bool useMicroTracking = false; // 是否启用微追踪
+
public CompProperties_ShipArtillery()
{
compClass = typeof(CompShipArtillery);
diff --git a/Source/WulaFallenEmpire/Flyover/WULA_ShipArtillery/CompShipArtillery.cs b/Source/WulaFallenEmpire/Flyover/WULA_ShipArtillery/CompShipArtillery.cs
index 82f5a275..309e052f 100644
--- a/Source/WulaFallenEmpire/Flyover/WULA_ShipArtillery/CompShipArtillery.cs
+++ b/Source/WulaFallenEmpire/Flyover/WULA_ShipArtillery/CompShipArtillery.cs
@@ -24,6 +24,16 @@ namespace WulaFallenEmpire
// 目标跟踪
private List previousTargets = new List();
+ // 新增:微追踪目标列表
+ private List microTrackingTargets = new List();
+ private List microTrackingWeights = new List(); // 新增:权重列表
+
+ // 新增:目标类型权重配置
+ private const float PAWN_WEIGHT = 5.0f; // Pawn权重:5倍
+ private const float OWNED_BUILDING_WEIGHT = 1.0f; // 有主建筑权重:1倍
+ private const float UNOWNED_BUILDING_WEIGHT = 0.01f; // 无主建筑权重:0.01倍
+ private const float OTHER_WEIGHT = 1.0f; // 其他目标权重:1倍
+
public override void Initialize(CompProperties props)
{
base.Initialize(props);
@@ -31,6 +41,7 @@ namespace WulaFallenEmpire
ticksUntilNextAttack = Props.ticksBetweenAttacks;
Log.Message($"Ship Artillery initialized: {Props.ticksBetweenAttacks} ticks between attacks, {Props.attackRadius} radius");
+ Log.Message($"Faction Discrimination: {Props.useFactionDiscrimination}, Target Faction: {Props.targetFaction?.defName ?? "None"}, Micro Tracking: {Props.useMicroTracking}");
}
public override void CompTick()
@@ -40,6 +51,12 @@ namespace WulaFallenEmpire
if (parent is not FlyOver flyOver || !flyOver.Spawned || flyOver.Map == null)
return;
+ // 更新微追踪目标列表(如果需要)
+ if (Props.useMicroTracking && Props.useFactionDiscrimination)
+ {
+ UpdateMicroTrackingTargets(flyOver);
+ }
+
// 更新预热状态
if (isWarmingUp)
{
@@ -65,6 +82,173 @@ namespace WulaFallenEmpire
}
}
+ // 新增:更新微追踪目标列表
+ private void UpdateMicroTrackingTargets(FlyOver flyOver)
+ {
+ microTrackingTargets.Clear();
+ microTrackingWeights.Clear();
+
+ Faction targetFaction = GetTargetFaction(flyOver);
+ if (targetFaction == null) return;
+
+ // 获取飞越物体当前位置
+ IntVec3 center = GetFlyOverPosition(flyOver);
+
+ // 搜索范围内的所有潜在目标
+ foreach (IntVec3 cell in GenRadial.RadialCellsAround(center, Props.attackRadius, true))
+ {
+ if (!cell.InBounds(flyOver.Map)) continue;
+
+ // 检查建筑
+ Building building = cell.GetEdifice(flyOver.Map);
+ if (building != null && IsValidMicroTrackingTarget(building, targetFaction))
+ {
+ microTrackingTargets.Add(new LocalTargetInfo(building));
+ float weight = GetTargetWeight(building);
+ microTrackingWeights.Add(weight);
+ }
+
+ // 检查生物
+ List thingList = cell.GetThingList(flyOver.Map);
+ foreach (Thing thing in thingList)
+ {
+ if (thing is Pawn pawn && IsValidMicroTrackingTarget(pawn, targetFaction))
+ {
+ microTrackingTargets.Add(new LocalTargetInfo(pawn));
+ float weight = GetTargetWeight(pawn);
+ microTrackingWeights.Add(weight);
+ }
+ }
+ }
+
+ // 移除重复目标(基于位置)
+ for (int i = microTrackingTargets.Count - 1; i >= 0; i--)
+ {
+ for (int j = 0; j < i; j++)
+ {
+ if (microTrackingTargets[i].Cell == microTrackingTargets[j].Cell)
+ {
+ microTrackingTargets.RemoveAt(i);
+ microTrackingWeights.RemoveAt(i);
+ break;
+ }
+ }
+ }
+
+ if (DebugSettings.godMode)
+ {
+ Log.Message($"MicroTracking: Found {microTrackingTargets.Count} targets for faction {targetFaction.def.defName}");
+ // 输出目标统计信息
+ var targetStats = GetTargetStatistics();
+ Log.Message($"Target Statistics - Pawns: {targetStats.pawnCount}, Owned Buildings: {targetStats.ownedBuildingCount}, Unowned Buildings: {targetStats.unownedBuildingCount}, Others: {targetStats.otherCount}");
+ }
+ }
+
+ // 新增:获取目标权重
+ private float GetTargetWeight(Thing thing)
+ {
+ if (thing is Pawn)
+ {
+ return PAWN_WEIGHT;
+ }
+ else if (thing is Building building)
+ {
+ if (building.Faction == null)
+ {
+ return UNOWNED_BUILDING_WEIGHT;
+ }
+ else
+ {
+ return OWNED_BUILDING_WEIGHT;
+ }
+ }
+ else
+ {
+ return OTHER_WEIGHT;
+ }
+ }
+
+ // 新增:获取目标统计信息
+ private (int pawnCount, int ownedBuildingCount, int unownedBuildingCount, int otherCount) GetTargetStatistics()
+ {
+ int pawnCount = 0;
+ int ownedBuildingCount = 0;
+ int unownedBuildingCount = 0;
+ int otherCount = 0;
+
+ for (int i = 0; i < microTrackingTargets.Count; i++)
+ {
+ Thing thing = microTrackingTargets[i].Thing;
+ if (thing == null) continue;
+
+ if (thing is Pawn)
+ {
+ pawnCount++;
+ }
+ else if (thing is Building building)
+ {
+ if (building.Faction == null)
+ {
+ unownedBuildingCount++;
+ }
+ else
+ {
+ ownedBuildingCount++;
+ }
+ }
+ else
+ {
+ otherCount++;
+ }
+ }
+
+ return (pawnCount, ownedBuildingCount, unownedBuildingCount, otherCount);
+ }
+
+ // 新增:检查是否为有效的微追踪目标
+ private bool IsValidMicroTrackingTarget(Thing thing, Faction targetFaction)
+ {
+ if (thing == null || thing.Destroyed) return false;
+
+ // 检查派系关系:目标派系的友军不应该被攻击
+ if (thing.Faction != null)
+ {
+ if (thing.Faction == targetFaction) return false;
+ if (thing.Faction.RelationKindWith(targetFaction) == FactionRelationKind.Ally) return false;
+ }
+
+ // 检查是否在保护范围内
+ if (Props.avoidPlayerAssets && IsNearPlayerAssets(thing.Position, thing.Map))
+ {
+ return false;
+ }
+
+ // 避免击中飞越物体本身
+ if (Props.avoidHittingFlyOver && thing.Position.DistanceTo(parent.Position) < 10f)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ // 新增:获取目标派系
+ private Faction GetTargetFaction(FlyOver flyOver)
+ {
+ if (!Props.useFactionDiscrimination)
+ return null;
+
+ // 如果指定了目标派系,使用指定的派系
+ if (Props.targetFaction != null)
+ {
+ Faction faction = Find.FactionManager.FirstFactionOfDef(Props.targetFaction);
+ if (faction != null) return faction;
+ }
+
+ // 否则使用玩家当前派系
+ return Faction.OfPlayer;
+ }
+
private void StartAttack(FlyOver flyOver)
{
if (!CanAttack(flyOver))
@@ -195,8 +379,16 @@ namespace WulaFallenEmpire
return;
}
- // 直接选择随机目标
- IntVec3 shellTarget = SelectRandomTarget(flyOver);
+ // 选择目标
+ IntVec3 shellTarget;
+ if (Props.useMicroTracking && Props.useFactionDiscrimination && microTrackingTargets.Count > 0)
+ {
+ shellTarget = SelectMicroTrackingTarget(flyOver);
+ }
+ else
+ {
+ shellTarget = SelectRandomTarget(flyOver);
+ }
// 关键修复:使用 SkyfallerMaker 创建并立即生成 Skyfaller
SkyfallerMaker.SpawnSkyfaller(shellDef, shellTarget, flyOver.Map);
@@ -216,6 +408,79 @@ namespace WulaFallenEmpire
}
}
+ // 修改:微追踪目标选择 - 现在使用权重系统
+ private IntVec3 SelectMicroTrackingTarget(FlyOver flyOver)
+ {
+ if (microTrackingTargets.Count == 0)
+ {
+ Log.Warning("MicroTracking: No targets available, falling back to random target");
+ return SelectRandomTarget(flyOver);
+ }
+
+ // 使用权重系统选择目标
+ LocalTargetInfo selectedTarget = SelectTargetByWeight();
+ IntVec3 targetCell = selectedTarget.Cell;
+
+ // 在目标周围添加随机偏移,避免过于精确
+ float offsetDistance = Rand.Range(0f, 2f);
+ float angle = Rand.Range(0f, 360f);
+
+ IntVec3 offsetTarget = targetCell;
+ offsetTarget.x += Mathf.RoundToInt(Mathf.Cos(angle * Mathf.Deg2Rad) * offsetDistance);
+ offsetTarget.z += Mathf.RoundToInt(Mathf.Sin(angle * Mathf.Deg2Rad) * offsetDistance);
+
+ // 确保目标在地图内
+ if (!offsetTarget.InBounds(flyOver.Map))
+ {
+ offsetTarget = targetCell;
+ }
+
+ if (DebugSettings.godMode)
+ {
+ Thing selectedThing = selectedTarget.Thing;
+ string targetType = selectedThing is Pawn ? "Pawn" :
+ selectedThing is Building building ?
+ (building.Faction == null ? "Unowned Building" : "Owned Building") : "Other";
+
+ Log.Message($"MicroTracking: Targeting {selectedThing?.Label ?? "unknown"} ({targetType}) at {targetCell}, final target: {offsetTarget}");
+ }
+
+ return offsetTarget;
+ }
+
+ // 新增:基于权重的目标选择
+ private LocalTargetInfo SelectTargetByWeight()
+ {
+ if (microTrackingTargets.Count == 0)
+ return LocalTargetInfo.Invalid;
+
+ if (microTrackingTargets.Count == 1)
+ return microTrackingTargets[0];
+
+ // 计算总权重
+ float totalWeight = 0f;
+ foreach (float weight in microTrackingWeights)
+ {
+ totalWeight += weight;
+ }
+
+ // 随机选择
+ float randomValue = Rand.Range(0f, totalWeight);
+ float currentSum = 0f;
+
+ for (int i = 0; i < microTrackingTargets.Count; i++)
+ {
+ currentSum += microTrackingWeights[i];
+ if (randomValue <= currentSum)
+ {
+ return microTrackingTargets[i];
+ }
+ }
+
+ // 回退到最后一个目标
+ return microTrackingTargets[microTrackingTargets.Count - 1];
+ }
+
private ThingDef SelectShellDef()
{
if (Props.skyfallerDefs != null && Props.skyfallerDefs.Count > 0)
@@ -352,6 +617,45 @@ namespace WulaFallenEmpire
if (!Props.avoidPlayerAssets)
return false;
+ // 如果启用了派系甄别,检查目标派系
+ if (Props.useFactionDiscrimination)
+ {
+ Faction targetFaction = GetTargetFaction(parent as FlyOver);
+ if (targetFaction != null)
+ {
+ foreach (IntVec3 checkCell in GenRadial.RadialCellsAround(cell, Props.playerAssetAvoidanceRadius, true))
+ {
+ if (!checkCell.InBounds(map))
+ continue;
+
+ // 检查目标派系建筑
+ var building = checkCell.GetEdifice(map);
+ if (building != null && building.Faction == targetFaction)
+ return true;
+
+ // 检查目标派系殖民者
+ var pawn = map.thingGrid.ThingAt(checkCell);
+ if (pawn != null && pawn.Faction == targetFaction && pawn.RaceProps.Humanlike)
+ return true;
+
+ // 检查目标派系动物
+ var animal = map.thingGrid.ThingAt(checkCell);
+ if (animal != null && animal.Faction == targetFaction && animal.RaceProps.Animal)
+ return true;
+
+ // 检查目标派系物品
+ var items = checkCell.GetThingList(map);
+ foreach (var item in items)
+ {
+ if (item.Faction == targetFaction && item.def.category == ThingCategory.Item)
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+
+ // 默认行为:检查玩家资产
foreach (IntVec3 checkCell in GenRadial.RadialCellsAround(cell, Props.playerAssetAvoidanceRadius, true))
{
if (!checkCell.InBounds(map))
@@ -470,6 +774,8 @@ namespace WulaFallenEmpire
Scribe_Values.Look(ref isWarmingUp, "isWarmingUp", false);
Scribe_Values.Look(ref currentTarget, "currentTarget");
Scribe_Collections.Look(ref previousTargets, "previousTargets", LookMode.Value);
+ Scribe_Collections.Look(ref microTrackingTargets, "microTrackingTargets", LookMode.LocalTargetInfo);
+ Scribe_Collections.Look(ref microTrackingWeights, "microTrackingWeights", LookMode.Value);
}
public override IEnumerable CompGetGizmosExtra()
@@ -504,9 +810,44 @@ namespace WulaFallenEmpire
IntVec3 flyOverPos = GetFlyOverPosition(flyOver);
Log.Message($"FlyOver - DrawPos: {flyOver.DrawPos}, Position: {flyOver.Position}, Calculated: {flyOverPos}");
Log.Message($"Current Target: {currentTarget}, Distance: {flyOverPos.DistanceTo(currentTarget):F1}");
+
+ // 显示派系甄别信息
+ Faction targetFaction = GetTargetFaction(flyOver);
+ Log.Message($"Faction Discrimination: {Props.useFactionDiscrimination}, Target Faction: {targetFaction?.def.defName ?? "None"}");
+ Log.Message($"Micro Tracking: {Props.useMicroTracking}, Targets Found: {microTrackingTargets.Count}");
+
+ // 显示目标统计
+ var stats = GetTargetStatistics();
+ Log.Message($"Target Stats - Pawns: {stats.pawnCount}, Owned Buildings: {stats.ownedBuildingCount}, Unowned Buildings: {stats.unownedBuildingCount}, Others: {stats.otherCount}");
}
}
};
+
+ // 显示微追踪目标信息
+ if (Props.useMicroTracking && Props.useFactionDiscrimination)
+ {
+ yield return new Command_Action
+ {
+ defaultLabel = $"Dev: Show Micro Targets ({microTrackingTargets.Count})",
+ action = () =>
+ {
+ if (parent is FlyOver flyOver)
+ {
+ for (int i = 0; i < microTrackingTargets.Count; i++)
+ {
+ var target = microTrackingTargets[i];
+ float weight = microTrackingWeights[i];
+ Thing thing = target.Thing;
+ string type = thing is Pawn ? "Pawn" :
+ thing is Building building ?
+ (building.Faction == null ? "Unowned Building" : "Owned Building") : "Other";
+
+ Log.Message($"Micro Target: {thing?.Label ?? "Unknown"} ({type}) at {target.Cell}, Weight: {weight:F2}");
+ }
+ }
+ }
+ };
+ }
}
}
diff --git a/Source/WulaFallenEmpire/Storyteller/StorytellerCompProperties_ImportantQuestWithFactionFilter.cs b/Source/WulaFallenEmpire/Storyteller/StorytellerCompProperties_ImportantQuestWithFactionFilter.cs
new file mode 100644
index 00000000..8617a331
--- /dev/null
+++ b/Source/WulaFallenEmpire/Storyteller/StorytellerCompProperties_ImportantQuestWithFactionFilter.cs
@@ -0,0 +1,33 @@
+using RimWorld;
+using System.Collections.Generic;
+using Verse;
+
+namespace WulaFallenEmpire
+{
+ public class StorytellerCompProperties_ImportantQuestWithFactionFilter : StorytellerCompProperties_ImportantQuest
+ {
+ // 派系类型白名单 - 只有这些派系类型的殖民地会触发任务
+ public List factionTypeWhitelist;
+
+ // 派系类型黑名单 - 这些派系类型的殖民地不会触发任务
+ public List factionTypeBlacklist;
+
+ // 是否启用派系过滤
+ public bool useFactionFilter = false;
+
+ // 默认行为(当派系不在白名单中时的处理方式)
+ public FactionFilterDefaultBehavior defaultBehavior = FactionFilterDefaultBehavior.Allow;
+
+ public StorytellerCompProperties_ImportantQuestWithFactionFilter()
+ {
+ compClass = typeof(StorytellerComp_ImportantQuestWithFactionFilter);
+ }
+ }
+
+ // 派系过滤的默认行为枚举
+ public enum FactionFilterDefaultBehavior
+ {
+ Allow, // 允许不在列表中的派系
+ Deny // 拒绝不在列表中的派系
+ }
+}
diff --git a/Source/WulaFallenEmpire/Storyteller/StorytellerComp_ImportantQuestWithFactionFilter.cs b/Source/WulaFallenEmpire/Storyteller/StorytellerComp_ImportantQuestWithFactionFilter.cs
new file mode 100644
index 00000000..001a29aa
--- /dev/null
+++ b/Source/WulaFallenEmpire/Storyteller/StorytellerComp_ImportantQuestWithFactionFilter.cs
@@ -0,0 +1,175 @@
+using RimWorld;
+using System.Collections.Generic;
+using Verse;
+using System.Text;
+using System.Linq;
+using RimWorld.Planet;
+
+namespace WulaFallenEmpire
+{
+ public class StorytellerComp_ImportantQuestWithFactionFilter : StorytellerComp
+ {
+ private StorytellerCompProperties_ImportantQuestWithFactionFilter FilterProps =>
+ (StorytellerCompProperties_ImportantQuestWithFactionFilter)props;
+
+ // 重新实现基类的私有属性
+ private static int IntervalsPassed => Find.TickManager.TicksGame / 1000;
+
+ private bool BeenGivenQuest => Find.QuestManager.QuestsListForReading.Any((Quest q) => q.root == FilterProps.questDef);
+
+ public override IEnumerable MakeIntervalIncidents(IIncidentTarget target)
+ {
+ // 先检查基础条件(天数、是否已给任务等)
+ if (IntervalsPassed <= FilterProps.fireAfterDaysPassed * 60 || BeenGivenQuest)
+ yield break;
+
+ // 检查派系过滤条件
+ if (!PassesFactionFilter(target))
+ yield break;
+
+ IncidentDef questIncident = FilterProps.questIncident;
+ if (questIncident.TargetAllowed(target))
+ {
+ yield return new FiringIncident(questIncident, this, GenerateParms(questIncident.category, target));
+ }
+ }
+
+ ///
+ /// 检查目标是否符合派系过滤条件
+ ///
+ private bool PassesFactionFilter(IIncidentTarget target)
+ {
+ // 如果不启用派系过滤,直接通过
+ if (!FilterProps.useFactionFilter)
+ return true;
+
+ // 获取目标的派系
+ Faction faction = GetTargetFaction(target);
+ if (faction == null)
+ return false;
+
+ // 检查黑名单
+ if (FilterProps.factionTypeBlacklist != null &&
+ FilterProps.factionTypeBlacklist.Contains(faction.def))
+ {
+ Log.Message($"[FactionFilter] Quest blocked: {faction.def.defName} is in blacklist");
+ return false;
+ }
+
+ // 检查白名单
+ if (FilterProps.factionTypeWhitelist != null &&
+ FilterProps.factionTypeWhitelist.Count > 0)
+ {
+ bool inWhitelist = FilterProps.factionTypeWhitelist.Contains(faction.def);
+
+ switch (FilterProps.defaultBehavior)
+ {
+ case FactionFilterDefaultBehavior.Allow:
+ // 白名单模式:在白名单中或默认允许
+ if (!inWhitelist)
+ {
+ Log.Message($"[FactionFilter] Quest allowed: {faction.def.defName} not in whitelist, but default behavior is Allow");
+ }
+ return true;
+
+ case FactionFilterDefaultBehavior.Deny:
+ // 白名单模式:只有在白名单中才允许
+ if (inWhitelist)
+ {
+ Log.Message($"[FactionFilter] Quest allowed: {faction.def.defName} is in whitelist");
+ return true;
+ }
+ else
+ {
+ Log.Message($"[FactionFilter] Quest blocked: {faction.def.defName} not in whitelist and default behavior is Deny");
+ return false;
+ }
+ }
+ }
+
+ // 如果没有设置白名单,根据默认行为决定
+ switch (FilterProps.defaultBehavior)
+ {
+ case FactionFilterDefaultBehavior.Allow:
+ Log.Message($"[FactionFilter] Quest allowed: No whitelist, default behavior is Allow");
+ return true;
+ case FactionFilterDefaultBehavior.Deny:
+ Log.Message($"[FactionFilter] Quest blocked: No whitelist, default behavior is Deny");
+ return false;
+ default:
+ return true;
+ }
+ }
+
+ ///
+ /// 获取目标的派系
+ ///
+ private Faction GetTargetFaction(IIncidentTarget target)
+ {
+ if (target is Map map)
+ {
+ return map.ParentFaction ?? Faction.OfPlayer;
+ }
+ else if (target is World world)
+ {
+ return Faction.OfPlayer;
+ }
+ else if (target is Caravan caravan)
+ {
+ return caravan.Faction;
+ }
+
+ return Faction.OfPlayer;
+ }
+
+ ///
+ /// 调试方法:显示当前过滤状态
+ ///
+ public string GetFactionFilterStatus(IIncidentTarget target)
+ {
+ if (!FilterProps.useFactionFilter)
+ return "Faction filter: DISABLED";
+
+ Faction faction = GetTargetFaction(target);
+ if (faction == null)
+ return "Faction filter: NO FACTION";
+
+ StringBuilder status = new StringBuilder();
+ status.AppendLine($"Faction filter: {faction.def.defName}");
+
+ // 黑名单检查
+ if (FilterProps.factionTypeBlacklist != null &&
+ FilterProps.factionTypeBlacklist.Contains(faction.def))
+ {
+ status.AppendLine("❌ BLACKLISTED");
+ return status.ToString();
+ }
+
+ // 白名单检查
+ if (FilterProps.factionTypeWhitelist != null &&
+ FilterProps.factionTypeWhitelist.Count > 0)
+ {
+ bool inWhitelist = FilterProps.factionTypeWhitelist.Contains(faction.def);
+
+ if (inWhitelist)
+ {
+ status.AppendLine("✅ WHITELISTED");
+ }
+ else
+ {
+ status.AppendLine(FilterProps.defaultBehavior == FactionFilterDefaultBehavior.Allow ?
+ "⚠️ NOT IN WHITELIST (Allowed by default)" :
+ "❌ NOT IN WHITELIST (Denied by default)");
+ }
+ }
+ else
+ {
+ status.AppendLine(FilterProps.defaultBehavior == FactionFilterDefaultBehavior.Allow ?
+ "✅ NO WHITELIST (Allowed by default)" :
+ "❌ NO WHITELIST (Denied by default)");
+ }
+
+ return status.ToString();
+ }
+ }
+}
diff --git a/Source/WulaFallenEmpire/Storyteller/StorytellerComp_SingleOnceFixed_FactionFilter.cs b/Source/WulaFallenEmpire/Storyteller/StorytellerComp_SingleOnceFixed_FactionFilter.cs
deleted file mode 100644
index 685fe4d9..00000000
--- a/Source/WulaFallenEmpire/Storyteller/StorytellerComp_SingleOnceFixed_FactionFilter.cs
+++ /dev/null
@@ -1,63 +0,0 @@
-using System.Collections.Generic;
-using RimWorld;
-using Verse;
-
-namespace WulaFallenEmpire
-{
- public class StorytellerComp_SingleOnceFixed_FactionFilter : StorytellerComp_SingleOnceFixed
- {
- private StorytellerCompProperties_SingleOnceFixed_FactionFilter PropsFilter => (StorytellerCompProperties_SingleOnceFixed_FactionFilter)props;
-
- public override IEnumerable MakeIntervalIncidents(IIncidentTarget target)
- {
- // 检查派系过滤条件
- if (!CheckFactionFilter())
- {
- yield break;
- }
-
- // 调用父类的逻辑
- foreach (var incident in base.MakeIntervalIncidents(target))
- {
- yield return incident;
- }
- }
-
- private bool CheckFactionFilter()
- {
- if (Faction.OfPlayer == null)
- return false;
-
- var playerFactionDef = Faction.OfPlayer.def;
-
- // 优先检查白名单:如果白名单有内容,只有白名单内的派系才能触发
- if (PropsFilter.allowedFactionTypes != null && PropsFilter.allowedFactionTypes.Count > 0)
- {
- return PropsFilter.allowedFactionTypes.Contains(playerFactionDef);
- }
-
- // 然后检查黑名单:如果黑名单有内容,黑名单内的派系不能触发
- if (PropsFilter.excludedFactionTypes != null && PropsFilter.excludedFactionTypes.Count > 0)
- {
- return !PropsFilter.excludedFactionTypes.Contains(playerFactionDef);
- }
-
- // 如果既没有白名单也没有黑名单,所有派系都能触发
- return true;
- }
- }
-
- public class StorytellerCompProperties_SingleOnceFixed_FactionFilter : StorytellerCompProperties_SingleOnceFixed
- {
- // 黑名单:这些派系类型不会触发事件
- public List excludedFactionTypes;
-
- // 白名单:只有这些派系类型会触发事件(优先级高于黑名单)
- public List allowedFactionTypes;
-
- public StorytellerCompProperties_SingleOnceFixed_FactionFilter()
- {
- compClass = typeof(StorytellerComp_SingleOnceFixed_FactionFilter);
- }
- }
-}
diff --git a/Source/WulaFallenEmpire/WulaFallenEmpire.csproj b/Source/WulaFallenEmpire/WulaFallenEmpire.csproj
index 149827e0..37906a23 100644
--- a/Source/WulaFallenEmpire/WulaFallenEmpire.csproj
+++ b/Source/WulaFallenEmpire/WulaFallenEmpire.csproj
@@ -208,7 +208,8 @@
-
+
+