diff --git a/1.6/1.6/Assemblies/WulaFallenEmpire.dll b/1.6/1.6/Assemblies/WulaFallenEmpire.dll index 2f4562ac..e4d77621 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/DamageDefs/Damages_Wula.xml b/1.6/1.6/Defs/DamageDefs/Damages_Wula.xml index ab4647a2..5c041dab 100644 --- a/1.6/1.6/Defs/DamageDefs/Damages_Wula.xml +++ b/1.6/1.6/Defs/DamageDefs/Damages_Wula.xml @@ -419,6 +419,69 @@ 15 + + + WULA_Combat_Excavator_Shoke_Damage + + + WulaFallenEmpire.DamageWorker_ExplosionWithTerrain + 10 + 10 + 2 + + WULA_Disturber_Turret_Bomb_Shockwave + + +
  • + LavaShallow +
  • + +
    +
    + + WULA_Combat_Excavator_Shoke_S_Damage + + + WulaFallenEmpire.DamageWorker_ExplosionWithTerrain + 10 + 10 + 2 + + WULA_Disturber_Turret_Bomb_Shockwave + + +
  • + CooledLava +
  • + +
    +
    WULA_DarkMatterBomb 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 3d60d825..dafccd7a 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 @@ -1068,4 +1068,138 @@ + + + + WULA_Combat_Excavator + + 乌拉帝国用于发起游击战的隧道挖掘机,在指定地点部署后,钻机将通过高速旋转的刀片引发若干次地震冲击波,随后将单位一股脑放出。 + WulaFallenEmpire.Building_ExtraGraphics + true + Building + 50 + true + PassThroughOnly + 1 + (1,1) + true + None + (0.56, 0.62, 0.9) + Wula/Building/Flag/WULA_Flag_Building_A + WULA_Buildings + false + + Wula/Building/Flag/WULA_Flag_Building_Mount + Graphic_Single + (1,1) + + + 4 + + + 99999 + 0 + 1000 + 5 + + Normal + true + false + North + true + Light + BulletImpact_Metal + true + RealtimeOnly + ConstructMetal + true + + + false + BuildingDestroyed_Metal_Big + true + true + + +
  • + 0 + 0 + + +
  • + Wula/Building/Flag/WULA_Flag_Building_A + MoteGlow + (1,1) + 0 + (0,1,2) + RotateY + 360 + 360 + 0 +
  • +
  • + Wula/Building/Flag/WULA_Flag_Building_Mount + Transparent + (1,1) + 1 + (0,1,0) + 0 + 0 + 0 +
  • + + +
    + +
  • + Wula_Progressive_Faction + true + false +
  • +
  • + 3 + (120,240,252,0) +
  • +
  • + 240 + 180 + + +
  • + WULA_Combat_Excavator_Shoke_S_Damage + 6 + 2 + 5 +
  • +
  • + WULA_Combat_Excavator_Shoke_S_Damage + 9 + 2 + 5 +
  • +
  • + WULA_Combat_Excavator_Shoke_Damage + 9 + 2 + 5 +
  • +
  • + Smoke + 12 + BlindSmoke + 2 + 0 +
  • + + + +
  • Mech_WULA_Cat_Constructor
  • +
  • Mech_WULA_Cat_Assault
  • +
    + + 3 + 180 + +
    +
    \ No newline at end of file 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 09cae253..8e90b7c8 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 @@ -1663,6 +1663,7 @@ false + Building Standable false @@ -1862,6 +1863,7 @@ false false (1,1) + Wula/Building/WULA_Surveillance_Building Graphic_Single @@ -2097,6 +2099,7 @@ 0 false false + 1 0 diff --git a/Source/WulaFallenEmpire/BuildingComp/Building_ExtraGraphics.cs b/Source/WulaFallenEmpire/BuildingComp/Building_ExtraGraphics.cs index 6f769b2c..78421863 100644 --- a/Source/WulaFallenEmpire/BuildingComp/Building_ExtraGraphics.cs +++ b/Source/WulaFallenEmpire/BuildingComp/Building_ExtraGraphics.cs @@ -153,7 +153,7 @@ namespace WulaFallenEmpire } } - // 绘制单个图形层 - 现在支持旋转动画 + // 绘制单个图形层 - 现在支持三种旋转动画 private void DrawGraphicLayer(Vector3 baseDrawPos, bool flip, GraphicLayerData layer) { if (string.IsNullOrEmpty(layer.texturePath)) @@ -183,7 +183,9 @@ namespace WulaFallenEmpire } break; - case AnimationType.Rotate: + case AnimationType.RotateZ: + case AnimationType.RotateY: + case AnimationType.RotateX: if (layer.enableAnimation && layerRotationAngles.ContainsKey(layerIndex)) { rotationAngle = layerRotationAngles[layerIndex]; @@ -194,9 +196,13 @@ namespace WulaFallenEmpire // 最终绘制位置 = 基础位置 + 图层偏移 + 动画偏移 Vector3 drawPos = baseDrawPos + layer.offset + animationOffset; - // 如果启用了旋转动画,使用矩阵变换绘制 - if (layer.animationType == AnimationType.Rotate && layer.enableAnimation && rotationAngle != 0f) + // 如果启用了旋转动画,使用特殊方法绘制 + if ((layer.animationType == AnimationType.RotateZ || + layer.animationType == AnimationType.RotateY || + layer.animationType == AnimationType.RotateX) && + layer.enableAnimation) { + // 使用自定义旋转绘制方法 DrawWithRotation(graphic, drawPos, flip, rotationAngle, layer); } else @@ -206,7 +212,7 @@ namespace WulaFallenEmpire } } - // 使用矩阵变换绘制旋转图形 + // 使用矩阵变换绘制旋转图形 - 支持三种旋转轴 private void DrawWithRotation(Graphic graphic, Vector3 drawPos, bool flip, float rotationAngle, GraphicLayerData layer) { try @@ -221,26 +227,48 @@ namespace WulaFallenEmpire return; } - // 创建旋转矩阵 - Quaternion rotation = Quaternion.Euler(0f, 0f, rotationAngle); + // 根据旋转类型创建不同的旋转矩阵 + Quaternion rotation = Quaternion.identity; + + switch (layer.animationType) + { + case AnimationType.RotateZ: + // 绕Z轴旋转(2D平面旋转) + rotation = Quaternion.Euler(0f, 0f, rotationAngle); + break; + + case AnimationType.RotateY: + // 绕Y轴旋转(3D旋转,类似旋转门) + rotation = Quaternion.Euler(0f, rotationAngle, 0f); + break; + + case AnimationType.RotateX: + // 绕X轴旋转(3D旋转,类似翻跟斗) + rotation = Quaternion.Euler(rotationAngle, 0f, 0f); + break; + } // 如果图层有旋转中心偏移,需要调整位置 - Vector3 pivotOffset = new Vector3(layer.pivotOffset.x, layer.pivotOffset.y, 0f); + Vector3 pivotOffset = new Vector3(layer.pivotOffset.x, 0, layer.pivotOffset.y); - // 计算最终矩阵 + // 最终绘制位置 = 基础位置 + 图层偏移 + 旋转中心偏移 + Vector3 finalDrawPos = drawPos + pivotOffset; + + // 创建变换矩阵 + // 注意:Graphic已经应用了缩放,所以这里使用Vector3.one Matrix4x4 matrix = Matrix4x4.TRS( - drawPos + pivotOffset, // 位置 - rotation, // 旋转 - new Vector3(layer.scale.x, layer.scale.y, 1f) // 缩放 + finalDrawPos, // 位置 + rotation, // 旋转 + Vector3.one // 缩放(已由Graphic处理) ); - // 绘制网格 - Graphics.DrawMesh(mesh, matrix, mat, 0); + // 使用RimWorld的绘制方法 + GenDraw.DrawMeshNowOrLater(mesh, matrix, mat, false); - // 如果需要,绘制第二面(双面渲染) + // 如果需要双面渲染,再绘制一次 if (layer.doubleSided) { - Graphics.DrawMesh(mesh, matrix, mat, 0, null, 0, null, UnityEngine.Rendering.ShadowCastingMode.Off, true); + GenDraw.DrawMeshNowOrLater(mesh, matrix, mat, false); } } catch (Exception ex) @@ -268,6 +296,13 @@ namespace WulaFallenEmpire if (!layerAnimationTimes.ContainsKey(i)) { layerAnimationTimes[i] = layer.animationStartTime; + // 为旋转动画初始化旋转角度 + if (layer.animationType == AnimationType.RotateZ || + layer.animationType == AnimationType.RotateY || + layer.animationType == AnimationType.RotateX) + { + layerRotationAngles[i] = 0f; + } } // 更新动画时间 @@ -285,22 +320,35 @@ namespace WulaFallenEmpire layerHoverOffsets[i] = hoverOffset; break; - case AnimationType.Rotate: + case AnimationType.RotateZ: + case AnimationType.RotateY: + case AnimationType.RotateX: // 计算该图层的旋转角度 float rotateSpeed = layer.animationSpeed > 0 ? layer.animationSpeed : ModExtension.globalAnimationSpeed; - float maxAngle = layer.animationIntensity > 0 ? layer.animationIntensity : ModExtension.globalAnimationIntensity; - // 旋转角度(循环) - float rotationAngle = (layerAnimationTimes[i] * rotateSpeed * 360f) % 360f; + // 旋转角度计算:动画时间 × 旋转速度(度/秒) + float rotationAngle = layerAnimationTimes[i] * rotateSpeed; - // 限制旋转角度范围(如果设置了最大角度) - if (maxAngle > 0 && maxAngle < 360f) + // 如果设置了动画强度且小于360,则限制旋转范围 + if (layer.animationIntensity > 0 && layer.animationIntensity < 360f) { - // 使用正弦波限制旋转角度范围 - rotationAngle = Mathf.Sin(layerAnimationTimes[i] * rotateSpeed) * maxAngle; + // 使用正弦波创建来回旋转效果 + rotationAngle = Mathf.Sin(layerAnimationTimes[i] * rotateSpeed * Mathf.Deg2Rad) * layer.animationIntensity; + } + else if (layer.animationIntensity >= 360f) + { + // 完整旋转:取模确保在0-360度之间 + rotationAngle %= 360f; } layerRotationAngles[i] = rotationAngle; + + // 调试输出 + if (DebugSettings.godMode && i == 0 && Find.TickManager.TicksGame % 60 == 0) + { + // 只在开发模式下,每60帧输出一次第一条图层的旋转信息 + Log.Message($"{layer.animationType} 图层 {i}: 角度={rotationAngle:F1}°, 时间={layerAnimationTimes[i]:F2}s, 速度={rotateSpeed}°/s"); + } break; } } @@ -315,14 +363,32 @@ namespace WulaFallenEmpire base.ExposeData(); // 保存自定义状态(如果需要) } + + // 调试方法:手动触发旋转测试 + public void TestRotation() + { + for (int i = 0; i < ModExtension.graphicLayers.Count; i++) + { + var layer = ModExtension.graphicLayers[i]; + if (layer.animationType == AnimationType.RotateZ || + layer.animationType == AnimationType.RotateY || + layer.animationType == AnimationType.RotateX) + { + layerRotationAngles[i] = 45f; // 设置为45度测试 + break; + } + } + } } - // 动画类型枚举 + // 动画类型枚举 - 现在有五种动画类型 public enum AnimationType { None, // 无动画 Hover, // 上下浮动 - Rotate // 自旋转 + RotateZ, // 绕Z轴旋转(2D平面旋转)- 原来的Rotate + RotateY, // 绕Y轴旋转(3D旋转,类似旋转门)- 新增 + RotateX // 绕X轴旋转(3D旋转,类似翻跟斗)- 新增 } // 主要的 ModExtension 定义 @@ -404,5 +470,19 @@ namespace WulaFallenEmpire get => animationPhase; set => animationPhase = value; } + + // 向后兼容:Rotate应该映射到RotateZ + [Obsolete("Use animationType instead")] + public AnimationType animationTypeCompat + { + get => animationType; + set + { + animationType = value; + // 如果旧值是Rotate,映射到RotateZ + if (animationType == AnimationType.RotateZ) + animationType = AnimationType.RotateZ; + } + } } } diff --git a/Source/WulaFallenEmpire/BuildingComp/WULA_PhaseCombatTower/CompPhaseCombatTower.cs b/Source/WulaFallenEmpire/BuildingComp/WULA_PhaseCombatTower/CompPhaseCombatTower.cs new file mode 100644 index 00000000..2b4b72b7 --- /dev/null +++ b/Source/WulaFallenEmpire/BuildingComp/WULA_PhaseCombatTower/CompPhaseCombatTower.cs @@ -0,0 +1,361 @@ +using System; +using System.Collections.Generic; +using RimWorld; +using UnityEngine; +using Verse; +using Verse.AI; +using Verse.Sound; +using System.Linq; + +namespace WulaFallenEmpire +{ + public class CompPhaseCombatTower : ThingComp + { + // 组件状态枚举 + public enum TowerState + { + Idle, // 空闲(未激活) + Warmup, // 启动期 + Exploding, // 爆炸阶段 + SpawningPawns, // 生成Pawn阶段 + Finished // 完成 + } + + private CompProperties_PhaseCombatTower Props => (CompProperties_PhaseCombatTower)props; + + // 状态变量 + private TowerState currentState = TowerState.Idle; + private int ticksInCurrentState = 0; + private int currentExplosionIndex = 0; + private int pawnsSpawned = 0; + private int nextSpawnTick = 0; + + // 缓存 + private List cachedPawnKindDefs = null; + + public override void PostSpawnSetup(bool respawningAfterLoad) + { + base.PostSpawnSetup(respawningAfterLoad); + + if (!respawningAfterLoad) + { + // 初次生成时开始启动期 + StartWarmup(); + } + } + + // 开始启动期 + private void StartWarmup() + { + currentState = TowerState.Warmup; + ticksInCurrentState = 0; + currentExplosionIndex = 0; + pawnsSpawned = 0; + } + + // 开始爆炸阶段 + private void StartExplosionPhase() + { + currentState = TowerState.Exploding; + ticksInCurrentState = 0; + currentExplosionIndex = 0; + + if (Props.explosions.Count == 0) + { + StartSpawningPhase(); + } + } + + // 开始生成Pawn阶段 + private void StartSpawningPhase() + { + currentState = TowerState.SpawningPawns; + ticksInCurrentState = 0; + pawnsSpawned = 0; + + // 初始化Pawn种类缓存 + if (cachedPawnKindDefs == null) + { + cachedPawnKindDefs = new List(); + foreach (string pawnKindName in Props.pawnKindDefs) + { + PawnKindDef pawnKindDef = DefDatabase.GetNamedSilentFail(pawnKindName); + if (pawnKindDef != null) + { + cachedPawnKindDefs.Add(pawnKindDef); + } + else + { + Log.Error($"PhaseCombatTower: 找不到PawnKindDef '{pawnKindName}'"); + } + } + } + + if (cachedPawnKindDefs.Count > 0 && Props.spawnCount > 0) + { + nextSpawnTick = Find.TickManager.TicksGame + Props.spawnIntervalTicks; + } + else + { + currentState = TowerState.Finished; + } + } + + public override void CompTick() + { + base.CompTick(); + + if (parent.Map == null || parent.Destroyed) + return; + + switch (currentState) + { + case TowerState.Warmup: + TickWarmup(); + break; + case TowerState.Exploding: + TickExploding(); + break; + case TowerState.SpawningPawns: + TickSpawningPawns(); + break; + } + } + + private void TickWarmup() + { + ticksInCurrentState++; + + // 启动期结束 + if (ticksInCurrentState >= Props.warmupTicks) + { + StartExplosionPhase(); + } + } + + private void TickExploding() + { + ticksInCurrentState++; + + // 检查是否需要执行下一次爆炸 + if (currentExplosionIndex < Props.explosions.Count) + { + // 第一次爆炸或冷却期已过 + if (currentExplosionIndex == 0 || + ticksInCurrentState >= Props.explosionCooldownTicks * currentExplosionIndex) + { + ExecuteExplosion(currentExplosionIndex); + currentExplosionIndex++; + + // 如果这是最后一次爆炸,开始生成Pawn阶段 + if (currentExplosionIndex >= Props.explosions.Count) + { + StartSpawningPhase(); + } + } + } + } + + private void TickSpawningPawns() + { + if (Find.TickManager.TicksGame >= nextSpawnTick && pawnsSpawned < Props.spawnCount) + { + SpawnPawn(); + pawnsSpawned++; + + if (pawnsSpawned >= Props.spawnCount) + { + currentState = TowerState.Finished; + } + else + { + nextSpawnTick = Find.TickManager.TicksGame + Props.spawnIntervalTicks; + } + } + } + + // 执行爆炸 - 使用标准爆炸方法,支持气体释放 + private void ExecuteExplosion(int explosionIndex) + { + if (explosionIndex < 0 || explosionIndex >= Props.explosions.Count) + return; + + var explosionData = Props.explosions[explosionIndex]; + + // 使用RimWorld标准爆炸方法 + if (parent.Map != null) + { + // 调用GenExplosion.DoExplosion方法,包含气体参数 + GenExplosion.DoExplosion( + center: parent.Position, // 爆炸中心 + map: parent.Map, // 地图 + radius: explosionData.radius, // 爆炸半径 + damType: explosionData.damageDef ?? DamageDefOf.Bomb, // 伤害类型 + instigator: parent, // 爆炸者 + damAmount: explosionData.damageAmount, // 伤害值 + armorPenetration: explosionData.armorPenetration, // 穿甲系数 + explosionSound: explosionData.explosionSound, // 爆炸声音 + weapon: null, // 武器(可选) + projectile: null, // 抛射物(可选) + intendedTarget: null, // 预定目标(可选) + + // 爆炸前生成物 + preExplosionSpawnThingDef: explosionData.preExplosionSpawnThingDef, + preExplosionSpawnChance: explosionData.preExplosionSpawnChance, + preExplosionSpawnThingCount: explosionData.preExplosionSpawnThingCount, + + // 爆炸后生成物 + postExplosionSpawnThingDef: explosionData.postExplosionSpawnThingDef, + postExplosionSpawnChance: explosionData.postExplosionSpawnChance, + postExplosionSpawnThingCount: explosionData.postExplosionSpawnThingCount, + + // 气体释放参数 + postExplosionGasType: explosionData.postExplosionGasType, // 气体类型 + postExplosionGasRadiusOverride: explosionData.postExplosionGasRadiusOverride, // 气体半径 + postExplosionGasAmount: explosionData.postExplosionGasAmount, // 气体数量 + + // 其他参数 + applyDamageToExplosionCellsNeighbors: explosionData.applyDamageToExplosionCellsNeighbors, + chanceToStartFire: explosionData.chanceToStartFire, + damageFalloff: explosionData.damageFalloff, + direction: explosionData.direction, + ignoredThings: null, + affectedAngle: explosionData.affectedAngle, + doVisualEffects: true, // 总是显示视觉效果 + propagationSpeed: explosionData.propagationSpeed, + excludeRadius: explosionData.excludeRadius, + doSoundEffects: explosionData.explosionSound != null, + screenShakeFactor: explosionData.screenShakeFactor + ); + } + } + + // 生成Pawn + private void SpawnPawn() + { + if (cachedPawnKindDefs == null || cachedPawnKindDefs.Count == 0) + return; + + // 随机选择Pawn种类 + PawnKindDef pawnKindDef = cachedPawnKindDefs.RandomElement(); + + // 寻找合适的生成位置 + IntVec3 spawnPosition = FindSpawnPosition(); + if (!spawnPosition.IsValid) + return; + + // 生成Pawn + PawnGenerationRequest request = new PawnGenerationRequest( + pawnKindDef, + faction: parent.Faction, + forceGenerateNewPawn: true, + canGeneratePawnRelations: false, + fixedBiologicalAge: 0, + fixedChronologicalAge: 0 + ); + + Pawn pawn = PawnGenerator.GeneratePawn(request); + + // 生成Pawn到地图 + GenSpawn.Spawn(pawn, spawnPosition, parent.Map); + + // 添加生成效果 + FleckMaker.ThrowDustPuff(spawnPosition, parent.Map, 2f); + } + + // 寻找生成位置 + private IntVec3 FindSpawnPosition() + { + Map map = parent.Map; + + // 尝试在建筑周围寻找合适的空单元格 + for (int radius = 1; radius <= 5; radius++) + { + CellRect rect = CellRect.CenteredOn(parent.Position, radius); + List validCells = new List(); + + foreach (IntVec3 cell in rect) + { + if (cell.InBounds(map) && + cell.Walkable(map) && + !cell.Fogged(map) && + map.thingGrid.ThingsAt(cell).Count() == 0) + { + validCells.Add(cell); + } + } + + if (validCells.Count > 0) + { + return validCells.RandomElement(); + } + } + + // 如果找不到合适位置,使用建筑位置(可能会重叠) + return parent.Position; + } + + // 获取当前状态描述(用于UI显示) + public string GetStatusDescription() + { + switch (currentState) + { + case TowerState.Warmup: + float progress = (float)ticksInCurrentState / Props.warmupTicks; + return $"启动中: {Mathf.RoundToInt(progress * 100)}%"; + + case TowerState.Exploding: + return $"爆炸阶段: {currentExplosionIndex + 1}/{Props.explosions.Count}"; + + case TowerState.SpawningPawns: + return $"生成单位: {pawnsSpawned}/{Props.spawnCount}"; + + case TowerState.Finished: + return "已完成"; + + default: + return "待机"; + } + } + + // 保存和加载状态 + public override void PostExposeData() + { + base.PostExposeData(); + + Scribe_Values.Look(ref currentState, "currentState", TowerState.Idle); + Scribe_Values.Look(ref ticksInCurrentState, "ticksInCurrentState", 0); + Scribe_Values.Look(ref currentExplosionIndex, "currentExplosionIndex", 0); + Scribe_Values.Look(ref pawnsSpawned, "pawnsSpawned", 0); + Scribe_Values.Look(ref nextSpawnTick, "nextSpawnTick", 0); + } + + public override IEnumerable CompGetGizmosExtra() + { + // 添加调试Gizmo(开发模式下) + if (DebugSettings.godMode) + { + yield return new Command_Action + { + defaultLabel = "强制启动", + action = () => StartWarmup(), + icon = TexCommand.ForbidOff + }; + + yield return new Command_Action + { + defaultLabel = "跳至爆炸阶段", + action = () => StartExplosionPhase(), + icon = TexCommand.Attack + }; + + yield return new Command_Action + { + defaultLabel = "跳至生成阶段", + action = () => StartSpawningPhase(), + icon = TexCommand.Attack + }; + } + } + } +} diff --git a/Source/WulaFallenEmpire/BuildingComp/WULA_PhaseCombatTower/CompProperties_PhaseCombatTower.cs b/Source/WulaFallenEmpire/BuildingComp/WULA_PhaseCombatTower/CompProperties_PhaseCombatTower.cs new file mode 100644 index 00000000..11c3eb1e --- /dev/null +++ b/Source/WulaFallenEmpire/BuildingComp/WULA_PhaseCombatTower/CompProperties_PhaseCombatTower.cs @@ -0,0 +1,62 @@ +using System.Collections.Generic; +using RimWorld; +using Verse; + +namespace WulaFallenEmpire +{ + public class CompProperties_PhaseCombatTower : CompProperties + { + // 阶段1: 启动期 + public int warmupTicks = 180; // 启动期帧数 (3秒) + + // 阶段2: 爆炸阶段 + public List explosions = new List(); + + // 阶段3: 生成Pawn阶段 + public List pawnKindDefs = new List(); // Pawn种类列表 + public int spawnCount = 5; // 需要生成的Pawn数量 (Y) + public int spawnIntervalTicks = 120; // 生成间隔帧数 (Z) + + // 爆炸冷却期 + public int explosionCooldownTicks = 60; // 爆炸之间的冷却时间 (默认1秒) + + public CompProperties_PhaseCombatTower() + { + compClass = typeof(CompPhaseCombatTower); + } + } + + // 爆炸数据定义 + public class ExplosionData + { + public DamageDef damageDef; // 伤害类型 + public float radius = 3f; // 爆炸范围 + public float armorPenetration = 0f; // 穿甲系数 + public int damageAmount = 30; // 伤害值 + public SoundDef explosionSound = null; // 爆炸声音 + public float chanceToStartFire = 0f; // 起火概率 + public bool damageFalloff = true; // 伤害是否随距离衰减 + + // 气体释放参数 + public GasType? postExplosionGasType = null; // 爆炸后生成的气体类型 + public float? postExplosionGasRadiusOverride = null; // 气体半径覆盖(如果为null,则使用爆炸半径) + public int postExplosionGasAmount = 255; // 气体数量(0-255) + + // 爆炸前/后生成物体 + public ThingDef preExplosionSpawnThingDef = null; // 爆炸前生成物 + public float preExplosionSpawnChance = 0f; // 爆炸前生成几率 + public int preExplosionSpawnThingCount = 1; // 爆炸前生成数量 + + public ThingDef postExplosionSpawnThingDef = null; // 爆炸后生成物 + public float postExplosionSpawnChance = 0f; // 爆炸后生成几率 + public int postExplosionSpawnThingCount = 1; // 爆炸后生成数量 + + // 高级参数 + public bool applyDamageToExplosionCellsNeighbors = false; // 是否对爆炸单元格邻居造成伤害 + public float? direction = null; // 爆炸方向(角度,0-360) + public FloatRange? affectedAngle = null; // 受影响角度范围 + public float propagationSpeed = 1f; // 爆炸传播速度 + public float excludeRadius = 0f; // 排除半径(中心区域不受伤害) + public float screenShakeFactor = 1f; // 屏幕震动因子 + } +} diff --git a/Source/WulaFallenEmpire/WulaFallenEmpire.csproj b/Source/WulaFallenEmpire/WulaFallenEmpire.csproj index 25862d8d..87e01a73 100644 --- a/Source/WulaFallenEmpire/WulaFallenEmpire.csproj +++ b/Source/WulaFallenEmpire/WulaFallenEmpire.csproj @@ -114,6 +114,8 @@ + +