diff --git a/1.6/1.6/Assemblies/WulaFallenEmpire.dll b/1.6/1.6/Assemblies/WulaFallenEmpire.dll index 05819d15..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/ThingDefs_Buildings/WULA_Mortar_Turret_Buildings.xml b/1.6/1.6/Defs/ThingDefs_Buildings/WULA_Mortar_Turret_Buildings.xml new file mode 100644 index 00000000..62e5e6c5 --- /dev/null +++ b/1.6/1.6/Defs/ThingDefs_Buildings/WULA_Mortar_Turret_Buildings.xml @@ -0,0 +1,294 @@ + + + + + + Wula_Base_Mortar_Turret_Cleanzone + + 清理出一块场地并准备好资源,使得乌拉帝国母舰可以向此处投放建筑。建造好的信标可以收起或移至他处,但是必须要有母舰或者工程舰在上空才能投送建筑。\n\nMTt-8"深渊"迫击炮塔是一种需要通电才能运转的中型防御炮塔,发射高爆迫击炮弹。这种炮台具有高伤害范围攻击能力,适合对付集群敌人和建筑。 + Wula/Building/Wula_Base_Mortar_Turret + MinifiedThing + Normal + + Wula_Base_Mortar_Turret + Wula_Base_Mortar_Turret_Weapon + + +
  • BuildingsMisc
  • +
    + + Wula/Building/WULA_Dropping_Building_Cleanzone + Graphic_Multi + (3,3) + + false + + + Building + PassThroughOnly + 0 + false + 0.5 + false + false + false + +
  • WULA_Turret_Base_Mortar_Technology
  • +
    + + 1 + 1 + 1 + 0 + + (3,3) + 0 + 1 + + 100 + 6 + + + BuildingDestroyed_Metal_Small + + +
  • WulaFallenEmpire.PlaceWorker_CustomRadius
  • +
    + WULA_Buildings + +
  • + 75 + (1, 1, 1) + 0 + true + + 在该建筑空降到指定地点时,其炮台武器的最大射程。 + true +
  • +
  • + Wula_Base_Mortar_Turret_Incoming + true + 1 + true + false +
  • +
    +
    + + + + Wula_Base_Mortar_Turret_Incoming + + (3,3) + + Wula/Building/Wula_Base_ATGun_Turret_Incoming + Graphic_Single + CutoutFlying + (3,3.75) + + + Accelerate + Things/Skyfaller/SkyfallerShadowDropPod + (2, 2) + DropPod_Fall + 100 + Explosion_Vaporize + 0.05 + 1 + 1 + + +
  • (0,0)
  • +
  • (1, 1)
  • +
    +
    + Wula_Base_Mortar_Turret +
    + +
  • + Smoke_Joint +
  • +
    +
    + + + + Wula_Base_Mortar_Turret + + MTt-8"深渊"迫击炮塔是一种需要通电才能运转的中型防御炮塔,发射高爆迫击炮弹。这种炮台具有高伤害范围攻击能力,适合对付集群敌人和建筑。 + WulaFallenEmpire.Building_TurretGunHasSpeed + MapMeshAndRealTime + +
  • + 0.2 +
  • +
    + + Wula/Building/WULA_Turret_Component + Graphic_Single + (3,3) + + + (0.3,0.3,1.4,1.4) + + + (0.5,0.35,0.75) + (0,0,-0.05) + + + true + Wula/Building/Wula_Base_Mortar_Turret + 1.0 + Building + false + false + (3,3) + + 1500 + 0 + 3200 + 80 + 0 + 0.80 + + + 100 + 6 + + false + Normal + PassThroughOnly + 50 + 0.5 + true + + 450 + true + Wula_Base_Mortar_Turret_Weapon + 4 + (-0.04, 0) + 5.0 + + +
  • PlaceWorker_TurretTop
  • +
  • PlaceWorker_ShowTurretRadius
  • +
    + +
  • +
  • +
  • + MechanoidsWakeUp +
  • +
  • + +
  • EMP
  • + + +
  • + MechTurretBig_Call +
  • +
  • + + true + false +
  • +
  • + CompPowerTrader + 200 +
  • +
  • + 6 + (252,240,120,0) +
  • +
  • + + + + + + Wula_Base_Mortar_Turret_Weapon + + 迫击炮塔,可以从远距离上对敌方集群造成巨大伤害。 + None + true + Ultra + + Wula/Building/Wula_Base_ATGun_Turret_Weapon + Graphic_Single + 3 + + 0.33 + + 150 + 0.3 + 0.7 + 0.85 + 0.8 + + +
  • + Verb_Shoot + true + Bullet_WULA_WM_Mortar_Turret + 2.5 + 5 + 10 + 75 + 1 + 1.9 + WULA_MW_Mass_Drivers_Shootingsound + GunTail_Heavy + 18 + + true + +
  • + +
    + + + + Bullet_WULA_WM_Mortar_Turret + + WulaFallenEmpire.Projectile_NorthArcTrail + Normal + True + + Wula/Projectile/WULA_Bullet_ChargeLanceShot_Red + Graphic_Single + TransparentPostLight + 5 + + + Bomb + 220 + 20 + 0.8 + 5.0 + Artillery_HitThickRoof + MortarBomb_Explode + MortarRound_PreImpact + MortarRound_Ambient + 5 + true + 2 + + +
  • + 100 + 1.0 + true +
  • +
  • + WULA_GunTail_Lighting + 3 + 1 + 1~2 + 0.5~1.0 + 0.1~0.3 + -30~30 +
  • +
    +
    + +
    \ No newline at end of file diff --git a/Source/WulaFallenEmpire/Projectiles/NorthArcModExtension.cs b/Source/WulaFallenEmpire/Projectiles/NorthArcModExtension.cs new file mode 100644 index 00000000..1a72a0eb --- /dev/null +++ b/Source/WulaFallenEmpire/Projectiles/NorthArcModExtension.cs @@ -0,0 +1,16 @@ +using Verse; + +namespace WulaFallenEmpire +{ + public class NorthArcModExtension : DefModExtension + { + // 控制向北偏移的高度(格数),值越大弧度越高 + public float northOffsetDistance = 10f; + + // 控制曲线的形状,值越大曲线越陡峭 + public float curveSteepness = 1f; + + // 是否使用弧形轨迹(默认为true,如果为false则使用直线轨迹) + public bool useArcTrajectory = true; + } +} \ No newline at end of file diff --git a/Source/WulaFallenEmpire/Projectiles/Projectile_NorthArcTrail.cs b/Source/WulaFallenEmpire/Projectiles/Projectile_NorthArcTrail.cs new file mode 100644 index 00000000..9fc3e72d --- /dev/null +++ b/Source/WulaFallenEmpire/Projectiles/Projectile_NorthArcTrail.cs @@ -0,0 +1,243 @@ +using System.Collections.Generic; +using RimWorld; +using UnityEngine; +using Verse; + +namespace WulaFallenEmpire +{ + public class Projectile_NorthArcTrail : Projectile_Explosive + { + // --- 弹道部分变量 --- + // 通过ModExtension配置的向北偏移高度 + public float northOffsetDistance = 0f; + + private Vector3 exactPositionInt; // 用于存储我们自己计算的位置 + private float curveSteepness = 1f; + + private Vector3 originPos; + private Vector3 destinationPos; + private Vector3 bezierControlPoint; + private int ticksFlying; + private int totalTicks; + private bool initialized = false; + + // --- 尾迹部分变量 --- + private TrackingBulletDef trackingDefInt; + private int Fleck_MakeFleckTick; + private Vector3 lastTickPosition; // 记录上一帧位置用于计算拖尾方向 + + // 获取 XML 中的扩展数据 + public TrackingBulletDef TrackingDef + { + get + { + if (trackingDefInt == null) + { + trackingDefInt = def.GetModExtension(); + if (trackingDefInt == null) + { + // 如果没配置,给一个空的默认值防止报错,或者只报错一次 + trackingDefInt = new TrackingBulletDef(); + } + } + return trackingDefInt; + } + } + + public override Vector3 ExactPosition => exactPositionInt; // 重写属性,让游戏获取我们计算的位置 + public override Quaternion ExactRotation => Quaternion.LookRotation(GetCurrentDirection()); // 弹头朝向当前移动方向 + + public override void ExposeData() + { + base.ExposeData(); + // 保存弹道数据 + Scribe_Values.Look(ref originPos, "originPos"); + Scribe_Values.Look(ref destinationPos, "destinationPos"); + Scribe_Values.Look(ref bezierControlPoint, "bezierControlPoint"); + Scribe_Values.Look(ref ticksFlying, "ticksFlying", 0); + Scribe_Values.Look(ref totalTicks, "totalTicks", 0); + Scribe_Values.Look(ref initialized, "initialized", false); + Scribe_Values.Look(ref northOffsetDistance, "northOffsetDistance", 0f); + Scribe_Values.Look(ref exactPositionInt, "exactPositionInt", Vector3.zero); + Scribe_Values.Look(ref curveSteepness, "curveSteepness", 1f); + + // 保存尾迹数据 + Scribe_Values.Look(ref Fleck_MakeFleckTick, "Fleck_MakeFleckTick", 0); + Scribe_Values.Look(ref lastTickPosition, "lastTickPosition", Vector3.zero); + } + + public override void Launch(Thing launcher, Vector3 origin, LocalTargetInfo usedTarget, LocalTargetInfo intendedTarget, ProjectileHitFlags hitFlags, bool preventFriendlyFire = false, Thing equipment = null, ThingDef targetCoverDef = null) + { + base.Launch(launcher, origin, usedTarget, intendedTarget, hitFlags, preventFriendlyFire, equipment, targetCoverDef); + + // 获取北向偏移配置 + NorthArcModExtension arcExtension = def.GetModExtension(); + if (arcExtension != null) + { + northOffsetDistance = arcExtension.northOffsetDistance; + curveSteepness = arcExtension.curveSteepness; + } + else + { + // 如果没有配置,则使用默认值,或者从 projectile.arcHeightFactor 获取参考值 + northOffsetDistance = def.projectile.arcHeightFactor * 3; // 将arcHeightFactor转换为北向偏移距离 + } + + // --- 初始化弹道 --- + originPos = origin; + destinationPos = usedTarget.CenterVector3; + + float speed = def.projectile.speed; + if (speed <= 0) speed = 1f; + + // 计算直线距离估算时间 + float distance = (originPos - destinationPos).MagnitudeHorizontal(); + totalTicks = Mathf.CeilToInt(distance / speed * 100f); + if (totalTicks < 1) totalTicks = 1; + + ticksFlying = 0; + + // 贝塞尔曲线计算: + // 中点 + Vector3 midPoint = (originPos + destinationPos) / 2f; + // 顶点 (中点向北偏移 X 格) + Vector3 apexPoint = midPoint + new Vector3(0, 0, northOffsetDistance); + // 控制点 P1 = 2 * 顶点 - 中点 + bezierControlPoint = 2f * apexPoint - midPoint; + + initialized = true; + + // 初始化我们自己的位置 + exactPositionInt = origin; + + // --- 初始化尾迹 --- + lastTickPosition = origin; + } + + protected override void Tick() + { + // 首先调用base.Tick(),让它处理组件更新(比如拖尾特效)和ticksToImpact + base.Tick(); + + // 如果base.Tick()已经处理了撞击,我们就不再继续 + if (this.Destroyed) + { + return; + } + + if (!initialized) + { + base.Tick(); + return; + } + + ticksFlying++; + + // 1. 计算当前帧的新位置 (贝塞尔曲线) + float t = (float)ticksFlying / (float)totalTicks; + if (t > 1f) t = 1f; + + float u = 1 - t; + // 水平位移 (贝塞尔) + Vector3 nextPos = (u * u * originPos) + (2 * u * t * bezierControlPoint) + (t * t * destinationPos); + // 垂直高度 (抛物线) + float arcHeight = def.projectile.arcHeightFactor * GenMath.InverseParabola(t); + nextPos.y = arcHeight; + + // 检查边界 + if (!nextPos.ToIntVec3().InBounds(base.Map)) + { + this.Destroy(); + return; + } + + // 更新我们自己的位置 + exactPositionInt = nextPos; + + // 2. 处理拖尾特效 + // 只有当这一帧移动了,且配置了 DefModExtension 时才生成 + if (TrackingDef != null && TrackingDef.tailFleckDef != null) + { + Fleck_MakeFleckTick++; + // 检查生成间隔 + if (Fleck_MakeFleckTick >= TrackingDef.fleckDelayTicks) + { + // 简单的循环计时重置逻辑 + if (Fleck_MakeFleckTick >= (TrackingDef.fleckDelayTicks + TrackingDef.fleckMakeFleckTickMax)) + { + Fleck_MakeFleckTick = TrackingDef.fleckDelayTicks; + } + + Map map = base.Map; + // 只有当在地图内时才生成 + if (map != null) + { + int count = TrackingDef.fleckMakeFleckNum.RandomInRange; + Vector3 currentPosition = this.ExactPosition; + Vector3 previousPosition = lastTickPosition; + + // 仅当有位移时才计算角度,防止原地鬼畜 + if ((currentPosition - previousPosition).MagnitudeHorizontalSquared() > 0.0001f) + { + float moveAngle = (currentPosition - previousPosition).AngleFlat(); + + for (int i = 0; i < count; i++) + { + // 这里的逻辑完全照搬原来的 BulletWithTrail + float velocityAngle = TrackingDef.fleckAngle.RandomInRange + moveAngle; + + FleckCreationData dataStatic = FleckMaker.GetDataStatic(currentPosition, map, TrackingDef.tailFleckDef, TrackingDef.fleckScale.RandomInRange); + dataStatic.rotation = moveAngle; // 粒子朝向跟随移动方向 + dataStatic.rotationRate = TrackingDef.fleckRotation.RandomInRange; + dataStatic.velocityAngle = velocityAngle; + dataStatic.velocitySpeed = TrackingDef.fleckSpeed.RandomInRange; + map.flecks.CreateFleck(dataStatic); + } + } + } + } + } + + // 3. 更新上一帧位置 + lastTickPosition = nextPos; + + // 4. 判定到达目标或倒计时爆炸 + if (ticksFlying >= totalTicks) + { + Impact(null); + return; + } + } + + // 计算当前位置的切线方向 + private Vector3 GetCurrentDirection() + { + if (!initialized || totalTicks <= 0) + { + return destinationPos - originPos; + } + + float t = (float)ticksFlying / (float)totalTicks; + if (t > 1f) t = 1f; + + // 计算贝塞尔曲线的导数(切线向量) + // 对于二次贝塞尔曲线 B(t) = (1-t)²P₀ + 2(1-t)tP₁ + t²P₂ + // 导数 B'(t) = 2(1-t)(P₁-P₀) + 2t(P₂-P₁) + float u = 1 - t; + Vector3 tangent = 2 * u * (bezierControlPoint - originPos) + 2 * t * (destinationPos - bezierControlPoint); + + // 如果切线向量为零,则使用默认方向 + if (tangent.MagnitudeHorizontalSquared() < 0.0001f) + { + return (destinationPos - originPos).normalized; + } + + return tangent.normalized; + } + + protected override void Impact(Thing hitThing, bool blockedByShield = false) + { + base.Impact(hitThing, blockedByShield); + } + } +} \ No newline at end of file diff --git a/Source/WulaFallenEmpire/WulaFallenEmpire.csproj b/Source/WulaFallenEmpire/WulaFallenEmpire.csproj index 2d3658c4..b8792d7b 100644 --- a/Source/WulaFallenEmpire/WulaFallenEmpire.csproj +++ b/Source/WulaFallenEmpire/WulaFallenEmpire.csproj @@ -296,6 +296,8 @@ + +