diff --git a/1.6/1.6/Assemblies/WulaFallenEmpire.dll b/1.6/1.6/Assemblies/WulaFallenEmpire.dll
index 2b39e9c9..d7b32934 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_Misc_Ability.xml b/1.6/1.6/Defs/AbilityDefs/WULA_Misc_Ability.xml
index 60b46850..5c4c928b 100644
--- a/1.6/1.6/Defs/AbilityDefs/WULA_Misc_Ability.xml
+++ b/1.6/1.6/Defs/AbilityDefs/WULA_Misc_Ability.xml
@@ -246,7 +246,7 @@
WULA_Psi_Skip
- 使用灵能撕开一个连接自身、虚境和目的地的单向通道,随后以极短的时间穿过整个通道,以瞬间移动到目标地点
+ 使用灵能撕开一个连接自身、虚境和目的地的单向通道,随后以极短的时间穿过整个通道,以瞬间移动到目标地点。
UI/Abilities/Skip
True
False
@@ -401,7 +401,6 @@
600
HoraxianSpellLight_Warmup
- 8
600
@@ -414,9 +413,10 @@
-
+
WULA_Black_Hole_Entity
false
+ false
@@ -444,9 +444,8 @@
true
0.5
5
- false
- true
- true
+ true
+ true
diff --git a/1.6/1.6/Defs/ThingDefs_Buildings/WULA_Misc_Buildings.xml b/1.6/1.6/Defs/ThingDefs_Buildings/WULA_Misc_Buildings.xml
index 9a5f6185..d412bf87 100644
--- a/1.6/1.6/Defs/ThingDefs_Buildings/WULA_Misc_Buildings.xml
+++ b/1.6/1.6/Defs/ThingDefs_Buildings/WULA_Misc_Buildings.xml
@@ -748,4 +748,64 @@
Placeworker_AttachedToWall
+
+
+ WULA_BroadshieldProjector
+
+ A man-portable low-angle shield projector. Bullets can go out, but not in. Its compact power source burns out after a few seconds of use.
+ BuildingOnTop
+ MapMeshAndRealTime
+ 0
+ Standable
+ 0.35
+
+ Things/Building/Security/BroadshieldProjector
+ Graphic_Single
+ 0.7
+
+ (0.3, 0.2, 0.3)
+ (0,0,-0.1)
+
+
+ (0.2,0.2,0.6,0.6)
+
+
+
+ 250
+ 0.5
+
+ Normal
+
+ false
+ true
+ Light
+ BulletImpact_Metal
+ ConstructMetal
+ 0
+
+ false
+ BuildingDestroyed_Metal_Small
+ false
+ false
+ Broadshield_Burnout
+
+
+
+ SolarFlare
+ 1
+ 0.01
+
+
+ 4.9
+ true
+ true
+ false
+ (0.6, 0.6, 0.8)
+ 3
+ 0.05
+ 600
+ Broadshield_Ambience
+
+
+
\ No newline at end of file
diff --git a/1.6/1.6/Defs/ThingDefs_Races/Races_Wulaspecies.xml b/1.6/1.6/Defs/ThingDefs_Races/Races_Wulaspecies.xml
index 374b625f..ef6e01f1 100644
--- a/1.6/1.6/Defs/ThingDefs_Races/Races_Wulaspecies.xml
+++ b/1.6/1.6/Defs/ThingDefs_Races/Races_Wulaspecies.xml
@@ -1352,6 +1352,17 @@
WULA_Hover_FlyEast
WULA_Hover_FlySouth
+
+ 3.5
+ 30
+ Crush
+ 4
+ false
+ false
+ false
+ true
+ true
+
diff --git a/Source/WulaFallenEmpire/Flyover/WULA_FlyOverEscort/CompFlyOverEscort.cs b/Source/WulaFallenEmpire/Flyover/WULA_FlyOverEscort/CompFlyOverEscort.cs
index d8877cf8..81e9a1bf 100644
--- a/Source/WulaFallenEmpire/Flyover/WULA_FlyOverEscort/CompFlyOverEscort.cs
+++ b/Source/WulaFallenEmpire/Flyover/WULA_FlyOverEscort/CompFlyOverEscort.cs
@@ -34,9 +34,6 @@ namespace WulaFallenEmpire
{
ticksUntilNextSpawn = Props.spawnIntervalTicks;
}
-
- Log.Message($"FlyOver Escort initialized: {Props.spawnIntervalTicks} ticks interval, max {Props.maxEscorts} escorts");
- Log.Message($"Safe distances - From Main: {Props.minSafeDistanceFromMain}, Between Escorts: {Props.minSafeDistanceBetweenEscorts}");
}
public override void CompTick()
@@ -50,7 +47,6 @@ namespace WulaFallenEmpire
if (!hasInitialized && mainFlyOver.hasStarted)
{
hasInitialized = true;
- Log.Message($"FlyOver Escort: Main FlyOver started at {mainFlyOver.startPosition}");
}
// 清理已销毁的伴飞
@@ -136,14 +132,11 @@ namespace WulaFallenEmpire
escortDataByID[escortID] = visualData;
successfulSpawns++;
-
- Log.Message($"Spawned escort #{successfulSpawns} for FlyOver at {mainFlyOver.DrawPos}, scale: {visualData.scale:F2}, maskAlpha: {visualData.heightMaskAlpha:F2}");
}
else
{
// 不安全,销毁这个伴飞
escort.Destroy();
- Log.Message($"Escort spawn attempt {attempt + 1}: Position too close to existing escort, trying again");
}
}
@@ -169,7 +162,6 @@ namespace WulaFallenEmpire
float distToMain = Vector3.Distance(newPos, mainFlyOver.DrawPos);
if (distToMain < Props.minSafeDistanceFromMain)
{
- Log.Message($"Escort too close to main FlyOver: {distToMain:F1} < {Props.minSafeDistanceFromMain}");
return false;
}
}
@@ -185,7 +177,6 @@ namespace WulaFallenEmpire
float distToEscort = Vector3.Distance(newPos, existingEscort.DrawPos);
if (distToEscort < Props.minSafeDistanceBetweenEscorts)
{
- Log.Message($"Escort too close to existing escort: {distToEscort:F1} < {Props.minSafeDistanceBetweenEscorts}");
return false;
}
}
@@ -252,8 +243,6 @@ namespace WulaFallenEmpire
// 设置伴飞属性 - 现在传入 visualData
SetupEscortProperties(escort, mainFlyOver, visualData);
- Log.Message($"Created escort: {escortStart} -> {escortEnd}, speed: {escortSpeed}, altitude: {escortAltitude}");
-
return escort;
}
catch (System.Exception ex)
@@ -371,8 +360,6 @@ namespace WulaFallenEmpire
{
escort.playFlyOverSound = false;
}
-
- Log.Message($"Set escort properties: scale={visualData.scale:F2}, isEscort={escort.isEscort}");
}
private void UpdateEscortPositions(FlyOver mainFlyOver)
@@ -532,8 +519,6 @@ namespace WulaFallenEmpire
escortDataByID[escortIDs[i]] = escortDataList[i];
}
}
-
- Log.Message($"Loaded escort visual data: {escortDataByID.Count} entries");
}
else if (Scribe.mode == LoadSaveMode.PostLoadInit)
{
@@ -560,8 +545,6 @@ namespace WulaFallenEmpire
// 重新设置伴飞的缩放
escort.escortScale = visualData.scale;
-
- Log.Message($"Rebuilt visual data for escort {escortID}: scale={visualData.scale:F2}");
}
else
{
@@ -569,13 +552,9 @@ namespace WulaFallenEmpire
var newVisualData = GenerateEscortVisualData();
escortVisualData[escort] = newVisualData;
escort.escortScale = newVisualData.scale;
-
- Log.Message($"Regenerated visual data for escort {escortID}: scale={newVisualData.scale:F2}");
}
}
}
-
- Log.Message($"Rebuilt escort visual data: {escortVisualData.Count} escorts");
}
// 公共方法:强制生成伴飞
diff --git a/Source/WulaFallenEmpire/ThingComp/WULA_AreaDamage/CompAreaDamage.cs b/Source/WulaFallenEmpire/ThingComp/WULA_AreaDamage/CompAreaDamage.cs
index e2676595..958031bd 100644
--- a/Source/WulaFallenEmpire/ThingComp/WULA_AreaDamage/CompAreaDamage.cs
+++ b/Source/WulaFallenEmpire/ThingComp/WULA_AreaDamage/CompAreaDamage.cs
@@ -64,45 +64,74 @@ namespace WulaFallenEmpire
private bool IsValidTarget(Thing thing)
{
- // 检查是否有生命值
- if (thing.def.useHitPoints == false || thing.HitPoints <= 0)
- return false;
-
- // 检查物体类型过滤
- if (thing is Building && !Props.affectBuildings)
- return false;
- if (thing is Pawn && !Props.affectPawns)
- return false;
- if (thing is Plant && !Props.affectPlants)
- return false;
-
- // 检查阵营关系(如果是生物)
+ // 检查是否为 Pawn(Pawn 有独立的健康系统)
if (thing is Pawn pawn)
{
Faction targetFaction = pawn.Faction;
Faction parentFaction = parent.Faction;
+
+ if (pawn.Dead || pawn.Downed)
+ return false;
- if (targetFaction == null)
+ // 检查是否影响生物
+ if (!Props.affectPawns)
+ return false;
+
+ // 如果父物体没有派系,则只检查目标派系
+ if (parentFaction == null)
{
- if (!Props.affectNeutral)
+ if (targetFaction == null && !Props.affectNeutral)
return false;
- }
- else if (targetFaction == parentFaction)
- {
- if (!Props.affectFriendly)
+ if (targetFaction != null && targetFaction.IsPlayer && !Props.affectFriendly)
return false;
- }
- else if (targetFaction.HostileTo(parentFaction))
- {
- if (!Props.affectHostile)
+ if (targetFaction != null && !targetFaction.IsPlayer && !Props.affectHostile)
return false;
}
else
{
- if (!Props.affectNeutral)
- return false;
+ // 正常阵营关系检查
+ if (targetFaction == null)
+ {
+ if (!Props.affectNeutral)
+ return false;
+ }
+ else if (targetFaction == parentFaction)
+ {
+ if (!Props.affectFriendly)
+ return false;
+ }
+ else if (targetFaction.HostileTo(parentFaction))
+ {
+ if (!Props.affectHostile)
+ return false;
+ }
+ else
+ {
+ if (!Props.affectNeutral)
+ return false;
+ }
}
}
+ else
+ {
+ // 对于非 Pawn 物体,检查生命值系统
+ if (thing.def.useHitPoints == false || thing.HitPoints <= 0)
+ return false;
+
+ // 检查物体类型过滤
+ if (thing is Building && !Props.affectBuildings)
+ return false;
+ if (thing is Plant && !Props.affectPlants)
+ return false;
+ }
+
+ // 如果设置为影响所有物体,跳过后续检查
+ if (Props.affectEverything)
+ return true;
+
+ // 如果忽略阵营关系,跳过阵营检查
+ if (Props.ignoreFactionRelations)
+ return true;
return true;
}
@@ -119,7 +148,7 @@ namespace WulaFallenEmpire
DamageInfo damageInfo = new DamageInfo(
Props.damageDef,
finalDamageAmount,
- armorPenetration: 0f,
+ armorPenetration: Props.armorPenetration,
instigator: parent,
hitPart: null,
weapon: null,
@@ -128,6 +157,9 @@ namespace WulaFallenEmpire
// 应用伤害
target.TakeDamage(damageInfo);
+
+ // 特殊效果处理
+ HandleSpecialEffects(target, damageInfo);
}
///
@@ -172,35 +204,29 @@ namespace WulaFallenEmpire
}
// 返回心灵敏感度作为伤害倍率
- // 例如:敏感度0.5 = 0.5倍伤害,敏感度1.5 = 1.5倍伤害
return psychicSensitivity;
}
+ ///
+ /// 处理特殊效果(如伤害类型特定的效果)
+ ///
+ private void HandleSpecialEffects(Thing target, DamageInfo damageInfo)
+ {
+ // 如果是 Pawn,可以添加额外的效果
+ if (target is Pawn pawn)
+ {
+ // 显示伤害数值(调试用)
+ if (Props.showDamageNumbers)
+ {
+ MoteMaker.ThrowText(target.DrawPos, target.Map, damageInfo.Amount.ToString());
+ }
+ }
+ }
+
public override void PostExposeData()
{
base.PostExposeData();
Scribe_Values.Look(ref ticksUntilNextDamage, "ticksUntilNextDamage", Props.damageIntervalTicks);
}
-
- ///
- /// 调试方法:显示伤害计算信息
- ///
- public string GetDamageDebugInfo(Thing target)
- {
- if (target is Pawn pawn)
- {
- float psychicSensitivity = pawn.GetStatValue(StatDefOf.PsychicSensitivity);
- float damageFactor = CalculatePsychicSensitivityFactor(pawn);
- int finalDamage = CalculateFinalDamage(target);
-
- return $"目标: {pawn.Label}\n" +
- $"心灵敏感度: {psychicSensitivity:F2}\n" +
- $"伤害倍率: {damageFactor:F2}\n" +
- $"基础伤害: {Props.damageAmount}\n" +
- $"最终伤害: {finalDamage}";
- }
-
- return $"目标: {target.Label}\n基础伤害: {Props.damageAmount}";
- }
}
}
diff --git a/Source/WulaFallenEmpire/ThingComp/WULA_AreaDamage/CompProperties_AreaDamage.cs b/Source/WulaFallenEmpire/ThingComp/WULA_AreaDamage/CompProperties_AreaDamage.cs
index 76c53201..5e0343ef 100644
--- a/Source/WulaFallenEmpire/ThingComp/WULA_AreaDamage/CompProperties_AreaDamage.cs
+++ b/Source/WulaFallenEmpire/ThingComp/WULA_AreaDamage/CompProperties_AreaDamage.cs
@@ -9,6 +9,7 @@ namespace WulaFallenEmpire
public int damageIntervalTicks = 60; // B: 伤害间隔(帧数)
public DamageDef damageDef; // C: 伤害类型
public int damageAmount = 10; // 基础伤害量
+ public float armorPenetration = 0f; // 护甲穿透
// 伤害缩放设置
public bool scaleWithPsychicSensitivity = false; // 是否随心灵敏感度缩放
@@ -24,6 +25,13 @@ namespace WulaFallenEmpire
public bool affectBuildings = true; // 是否影响建筑
public bool affectPawns = true; // 是否影响生物
public bool affectPlants = false; // 是否影响植物
+
+ // 特殊设置
+ public bool ignoreFactionRelations = false; // 忽略所有阵营关系检查(用于无派系实体)
+ public bool affectEverything = false; // 影响范围内所有有生命值的物体
+
+ // 特殊效果
+ public bool showDamageNumbers = false; // 显示伤害数值(调试用)
public CompProperties_AreaDamage()
{
diff --git a/Source/WulaFallenEmpire/ThingComp/WULA_PeriodicGameCondition/CompPeriodicGameCondition.cs b/Source/WulaFallenEmpire/ThingComp/WULA_PeriodicGameCondition/CompPeriodicGameCondition.cs
new file mode 100644
index 00000000..07545510
--- /dev/null
+++ b/Source/WulaFallenEmpire/ThingComp/WULA_PeriodicGameCondition/CompPeriodicGameCondition.cs
@@ -0,0 +1,162 @@
+using RimWorld;
+using UnityEngine;
+using Verse;
+
+namespace WulaFallenEmpire
+{
+ public class CompPeriodicGameCondition : ThingComp
+ {
+ private int ticksUntilNextCondition;
+
+ public CompProperties_PeriodicGameCondition Props => (CompProperties_PeriodicGameCondition)props;
+
+ public override void Initialize(CompProperties props)
+ {
+ base.Initialize(props);
+ ticksUntilNextCondition = GetIntervalTicks();
+ }
+
+ public override void CompTick()
+ {
+ base.CompTick();
+
+ if (!parent.Spawned || parent.Map == null)
+ return;
+
+ ticksUntilNextCondition--;
+ if (ticksUntilNextCondition <= 0)
+ {
+ TryMakeGameCondition();
+ ticksUntilNextCondition = GetIntervalTicks();
+ }
+ }
+
+ private int GetIntervalTicks()
+ {
+ return Mathf.RoundToInt(Props.intervalDays * 60000f); // 1天 = 60000 ticks
+ }
+
+ private int GetDurationTicks()
+ {
+ return Mathf.RoundToInt(Props.durationDays * 60000f);
+ }
+
+ private void TryMakeGameCondition()
+ {
+ Map map = parent.Map;
+ if (map == null)
+ return;
+
+ // 检查是否可以触发
+ if (!CanMakeGameCondition(map))
+ return;
+
+ // 创建游戏条件
+ GameCondition condition = GameConditionMaker.MakeCondition(Props.gameConditionDef, GetDurationTicks());
+ map.gameConditionManager.RegisterCondition(condition);
+
+ // 发送通知
+ if (Props.sendLetter)
+ {
+ TrySendLetter(map, condition);
+ }
+ }
+
+ private bool CanMakeGameCondition(Map map)
+ {
+ if (Props.gameConditionDef == null)
+ return false;
+
+ GameConditionManager conditionManager = map.gameConditionManager;
+ if (conditionManager == null)
+ return false;
+
+ // 检查是否被其他条件阻止
+ if (Props.checkPreventIncidents)
+ {
+ foreach (GameCondition activeCondition in conditionManager.ActiveConditions)
+ {
+ if (activeCondition.def.preventIncidents)
+ {
+ return false;
+ }
+ }
+ }
+
+ // 检查是否已存在相同条件
+ if (Props.checkAlreadyActive && conditionManager.ConditionIsActive(Props.gameConditionDef))
+ {
+ return false;
+ }
+
+ // 检查是否可以共存
+ if (Props.checkCanCoexist)
+ {
+ foreach (GameCondition activeCondition in conditionManager.ActiveConditions)
+ {
+ if (!Props.gameConditionDef.CanCoexistWith(activeCondition.def))
+ {
+ return false;
+ }
+ }
+ }
+
+ // 特殊条件:检查水域是否有鱼
+ if (Props.requireFish && ModsConfig.OdysseyActive)
+ {
+ if (map.waterBodyTracker == null || !map.waterBodyTracker.AnyBodyContainsFish)
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private void TrySendLetter(Map map, GameCondition condition)
+ {
+ if (condition.HiddenByOtherCondition(map))
+ return;
+
+ // 检查是否有地图会受到这个条件影响
+ bool anyMapAffected = false;
+ foreach (Map currentMap in Find.Maps)
+ {
+ if (condition.CanApplyOnMap(currentMap))
+ {
+ anyMapAffected = true;
+ break;
+ }
+ }
+
+ if (!anyMapAffected)
+ return;
+ }
+
+ public override void PostExposeData()
+ {
+ base.PostExposeData();
+ Scribe_Values.Look(ref ticksUntilNextCondition, "ticksUntilNextCondition", GetIntervalTicks());
+ }
+
+ ///
+ /// 手动触发一次游戏条件(用于调试或特殊事件)
+ ///
+ public void TriggerNow()
+ {
+ ticksUntilNextCondition = 0;
+ }
+
+ ///
+ /// 获取下一次触发的时间信息
+ ///
+ public string GetNextTriggerInfo()
+ {
+ if (!parent.Spawned)
+ return "Not spawned";
+
+ float daysUntilNext = ticksUntilNextCondition / 60000f;
+ return $"Next trigger in: {daysUntilNext:F1} days";
+ }
+ }
+}
diff --git a/Source/WulaFallenEmpire/ThingComp/WULA_PeriodicGameCondition/CompProperties_PeriodicGameCondition.cs b/Source/WulaFallenEmpire/ThingComp/WULA_PeriodicGameCondition/CompProperties_PeriodicGameCondition.cs
new file mode 100644
index 00000000..ea237f78
--- /dev/null
+++ b/Source/WulaFallenEmpire/ThingComp/WULA_PeriodicGameCondition/CompProperties_PeriodicGameCondition.cs
@@ -0,0 +1,30 @@
+using RimWorld;
+using Verse;
+
+namespace WulaFallenEmpire
+{
+ public class CompProperties_PeriodicGameCondition : CompProperties
+ {
+ public GameConditionDef gameConditionDef; // 要创建的游戏条件
+ public float intervalDays = 1f; // 触发间隔(天)
+ public float durationDays = 1f; // 游戏条件持续时间(天)
+
+ // 条件检查设置
+ public bool checkCanCoexist = true; // 检查是否与其他条件共存
+ public bool checkAlreadyActive = true; // 检查是否已存在相同条件
+ public bool checkPreventIncidents = true; // 检查是否被其他条件阻止
+
+ // 通知设置
+ public bool sendLetter = true; // 是否发送信件通知
+ public string letterLabel; // 信件标题(如为空则使用游戏条件的默认标题)
+ public LetterDef letterDef; // 信件类型
+
+ // 特殊条件
+ public bool requireFish = false; // 是否需要水域有鱼(仅限Odyssey DLC)
+
+ public CompProperties_PeriodicGameCondition()
+ {
+ compClass = typeof(CompPeriodicGameCondition);
+ }
+ }
+}
diff --git a/Source/WulaFallenEmpire/WulaFallenEmpire.csproj b/Source/WulaFallenEmpire/WulaFallenEmpire.csproj
index 3e5ddb49..b8792d7b 100644
--- a/Source/WulaFallenEmpire/WulaFallenEmpire.csproj
+++ b/Source/WulaFallenEmpire/WulaFallenEmpire.csproj
@@ -239,6 +239,8 @@
+
+