diff --git a/1.6/1.6/Assemblies/WulaFallenEmpire.dll b/1.6/1.6/Assemblies/WulaFallenEmpire.dll index 7f56cd5c..05819d15 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 2f38d40f..2d3658c4 100644 --- a/Source/WulaFallenEmpire/WulaFallenEmpire.csproj +++ b/Source/WulaFallenEmpire/WulaFallenEmpire.csproj @@ -239,6 +239,8 @@ + +