diff --git a/1.6/1.6/Assemblies/WulaFallenEmpire.dll b/1.6/1.6/Assemblies/WulaFallenEmpire.dll index f50252aa..27287dba 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_Races/Races_Wulaspecies.xml b/1.6/1.6/Defs/ThingDefs_Races/Races_Wulaspecies.xml index d4ceae68..560f0f3e 100644 --- a/1.6/1.6/Defs/ThingDefs_Races/Races_Wulaspecies.xml +++ b/1.6/1.6/Defs/ThingDefs_Races/Races_Wulaspecies.xml @@ -970,6 +970,270 @@ + + + Wula_Mech_Mobile_Factory + + 乌拉帝国的大型战争机械,简直就是一座移动堡垒——它不仅装甲厚实、火炮林立,还能在战场上生产大量的辅助战争机械以形成坚实的弹性阵线,生来就是为了粉碎坚固的堡垒和顽强的抵抗。 + + 1 + 1.5 + 5 + + + Mech_Warqueen + 30 + +
  • + MechanoidFullyFormed + 0 + Pawn_Mech_Warqueen_Wounded + Pawn_Mech_Warqueen_Death + Pawn_Mech_Warqueen_Call +
  • +
    + 25 + +
    + +
  • + + +
  • Blunt
  • + + 360 + 8 + Torso + true + +
    + +
  • + 0 + Wula_CR_Mobile_Factory_Turret + + +
  • + PawnRenderNode_TurretGun + PawnRenderNodeWorker_TurretGun + Body + (1, 1) + 20 + Any + + + -90 + (-1, 0, -1.45) + true + -5 + + + 90 + -5 + (2.15, 0, -1) + + + -90 + (1, 0, -1.45) + + + 90 + (-2.15, 0, -1) + + +
  • + + +
  • + 1 + Wula_CR_Mobile_Factory_Turret + + +
  • + PawnRenderNode_TurretGun + PawnRenderNodeWorker_TurretGun + Body + (1, 1) + 20 + Any + + + -90 + (1, 0, -1.45) + -5 + + + -90 + (2.15, 0, -1) + + + -90 + (-1, 0, -1.45) + + + 90 + (-2.15, 0, -1) + -5 + + +
  • + + +
  • + 2 + Wula_MR_Mobile_Factory_Turret + + +
  • + PawnRenderNode_TurretGun + PawnRenderNodeWorker_TurretGun + Body + (1, 1) + 20 + Any + + + -90 + (-1.3, 0, -0.45) + true + -5 + + + 90 + -5 + (1.4, 0, -0.35) + + + -90 + (1.3, 0, -0.45) + + + 90 + (-1.4, 0, -0.35) + + +
  • + + +
  • + 3 + Wula_MR_Mobile_Factory_Turret + + +
  • + PawnRenderNode_TurretGun + PawnRenderNodeWorker_TurretGun + Body + (1, 1) + 20 + Any + + + -90 + (1.3, 0, -0.45) + true + -5 + + + -90 + (1.4, 0, -0.35) + + + -90 + (-1.3, 0, -0.45) + + + 90 + -5 + (-1.4, 0, -0.35) + + +
  • + + +
  • + 4 + Wula_LR_Mobile_Factory_Turret + + +
  • + PawnRenderNode_TurretGun + PawnRenderNodeWorker_TurretGun + Body + (1, 1) + 20 + Any + + + -90 + (1.25, 0, 0.45) + true + -5 + + + 90 + -5 + (0.6, 0, 0.15) + + + -90 + (-1.25, 0, 0.65) + + + 90 + (-0.6, 0, 0.15) + + +
  • + + +
  • + 5 + Wula_LR_Mobile_Factory_Turret + + +
  • + PawnRenderNode_TurretGun + PawnRenderNodeWorker_TurretGun + Body + (1, 1) + 20 + Any + + + -90 + (-1.25, 0, 0.45) + true + -5 + + + -90 + (0.6, 0, 0.15) + + + -90 + (1.25, 0, 0.65) + + + 90 + -5 + (-0.6, 0, 0.15) + + +
  • + + +
  • + 36000 + 8.2 + 8.4 + 0.01 + 4.0 + false +
  • +
    +
    + Wula_AI_Heavy_Panzer @@ -1355,6 +1619,7 @@ + WULA_Fxxk_Goose diff --git a/1.6/1.6/Defs/ThingDefs_Races/Races_Wulaspecies_FE_Materialist.xml b/1.6/1.6/Defs/ThingDefs_Races/Races_Wulaspecies_FE_Materialist.xml index a5f51bdd..60649d75 100644 --- a/1.6/1.6/Defs/ThingDefs_Races/Races_Wulaspecies_FE_Materialist.xml +++ b/1.6/1.6/Defs/ThingDefs_Races/Races_Wulaspecies_FE_Materialist.xml @@ -175,362 +175,6 @@ WULA_Mech_Flyer_Melta_Slow - - Wula_Mech_Mobile_Factory - - 乌拉帝国图书馆的陆行战舰——火力强大,装甲厚重,不仅拥有各种各样的副炮和威力巨大的主炮,还能生产海量的小型机械体掩护行动,是乌拉帝国图书馆战术的典型代表。 - - 14 - 1.5 - 5 - - - Mech_Warqueen - 30 - -
  • - MechanoidFullyFormed - 0 - Pawn_Mech_Warqueen_Wounded - Pawn_Mech_Warqueen_Death - Pawn_Mech_Warqueen_Call -
  • -
    - 25 - -
    - -
  • - - -
  • Blunt
  • - - 360 - 8 - Torso - true - -
    - - -
  • -
  • -
  • - true - 30 - MechanoidsWakeUp -
  • -
  • - Wula_CR_Mobile_Factory_Turret - - -
  • - PawnRenderNode_TurretGun - PawnRenderNodeWorker_TurretGun - Body - (1, 1) - 20 - Any - - - -90 - (-1, 0, -1.45) - true - -5 - - - 90 - -5 - (2.15, 0, -1) - - - -90 - (1, 0, -1.45) - - - 90 - (-2.15, 0, -1) - - -
  • - - -
  • - Wula_CR_Mobile_Factory_Turret - - -
  • - PawnRenderNode_TurretGun - PawnRenderNodeWorker_TurretGun - Body - (1, 1) - 20 - Any - - - -90 - (1, 0, -1.45) - -5 - - - -90 - (2.15, 0, -1) - - - -90 - (-1, 0, -1.45) - - - 90 - (-2.15, 0, -1) - -5 - - -
  • - - -
  • - Wula_MR_Mobile_Factory_Turret - - -
  • - PawnRenderNode_TurretGun - PawnRenderNodeWorker_TurretGun - Body - (1, 1) - 20 - Any - - - -90 - (-1.3, 0, -0.45) - true - -5 - - - 90 - -5 - (1.4, 0, -0.35) - - - -90 - (1.3, 0, -0.45) - - - 90 - (-1.4, 0, -0.35) - - -
  • - - -
  • - Wula_MR_Mobile_Factory_Turret - - -
  • - PawnRenderNode_TurretGun - PawnRenderNodeWorker_TurretGun - Body - (1, 1) - 20 - Any - - - -90 - (1.3, 0, -0.45) - true - -5 - - - -90 - (1.4, 0, -0.35) - - - -90 - (-1.3, 0, -0.45) - - - 90 - -5 - (-1.4, 0, -0.35) - - -
  • - - -
  • - Wula_LR_Mobile_Factory_Turret - - -
  • - PawnRenderNode_TurretGun - PawnRenderNodeWorker_TurretGun - Body - (1, 1) - 20 - Any - - - -90 - (1.25, 0, 0.45) - true - -5 - - - 90 - -5 - (0.6, 0, 0.15) - - - -90 - (-1.25, 0, 0.65) - - - 90 - (-0.6, 0, 0.15) - - -
  • - - -
  • - Wula_LR_Mobile_Factory_Turret - - -
  • - PawnRenderNode_TurretGun - PawnRenderNodeWorker_TurretGun - Body - (1, 1) - 20 - Any - - - -90 - (-1.25, 0, 0.45) - true - -5 - - - -90 - (0.6, 0, 0.15) - - - -90 - (1.25, 0, 0.65) - - - 90 - -5 - (-0.6, 0, 0.15) - - -
  • - - -
  • - 36000 - 4.2 - 4.4 - 0.01 - 4.0 - false -
  • -
  • - true - WULA_MechCarrierSwitchHediff - Steel - 500 - 500 - 999 - 9999 - -
  • - WULA_Mech_Flyer - 1 - 50 -
  • -
  • - WULA_Mech_Flyer_Slow - 4 - 600 -
  • - - WarqueenWarUrchinsSpawned - WarUrchinSpawned - -
  • - true - WULA_MechCarrierSwitchHediff - Steel - 500 - 500 - 999 - 9999 - -
  • - WULA_Mech_Flyer - 1 - 50 -
  • -
  • - WULA_Mech_Flyer_Slow - 4 - 600 -
  • - - WarqueenWarUrchinsSpawned - WarUrchinSpawned - -
  • - true - WULA_MechCarrierSwitchHediff - Steel - 500 - 500 - 999 - 9999 - -
  • - WULA_Mech_Flyer - 1 - 50 -
  • -
  • - WULA_Mech_Flyer_Slow - 4 - 600 -
  • - - WarqueenWarUrchinsSpawned - WarUrchinSpawned - -
  • - true - WULA_MechCarrierSwitchHediff - Steel - 500 - 500 - 999 - 9999 - -
  • - WULA_Mech_Flyer - 1 - 50 -
  • -
  • - WULA_Mech_Flyer_Slow - 4 - 600 -
  • - - WarqueenWarUrchinsSpawned - WarUrchinSpawned - -
    -
    Wula_Mech_Mobile_Factory diff --git a/Source/WulaFallenEmpire/BuildingComp/WULA_FlyOverBeacon/Building_FlyOverBeacon.cs b/Source/WulaFallenEmpire/BuildingComp/WULA_FlyOverBeacon/Building_FlyOverBeacon.cs deleted file mode 100644 index db52a936..00000000 --- a/Source/WulaFallenEmpire/BuildingComp/WULA_FlyOverBeacon/Building_FlyOverBeacon.cs +++ /dev/null @@ -1,480 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using UnityEngine; -using Verse; -using Verse.AI; -using Verse.Sound; -using RimWorld; -using RimWorld.Planet; - -namespace WulaFallenEmpire -{ - [StaticConstructorOnStartup] - public class Building_FlyOverBeacon : Building - { - public GlobalTargetInfo flyOverTarget; - public FlyOverConfig flyOverConfig; - public static readonly Texture2D CallFlyOverTex = ContentFinder.Get("UI/Commands/CallFlyOver", true); - - private CompPowerTrader powerComp; - private CompRefuelable refuelableComp; - private int cooldownTicksLeft; - - public bool IsReady => (powerComp == null || powerComp.PowerOn) && - (refuelableComp == null || refuelableComp.HasFuel) && - cooldownTicksLeft <= 0; - - public override void SpawnSetup(Map map, bool respawningAfterLoad) - { - base.SpawnSetup(map, respawningAfterLoad); - powerComp = this.TryGetComp(); - refuelableComp = this.TryGetComp(); - - if (!respawningAfterLoad) - { - flyOverTarget = GlobalTargetInfo.Invalid; - flyOverConfig = new FlyOverConfig(); - } - } - - public override void ExposeData() - { - base.ExposeData(); - Scribe_TargetInfo.Look(ref flyOverTarget, "flyOverTarget"); - Scribe_Deep.Look(ref flyOverConfig, "flyOverConfig"); - Scribe_Values.Look(ref cooldownTicksLeft, "cooldownTicksLeft", 0); - } - - protected override void Tick() - { - base.Tick(); - - // 冷却计时 - if (cooldownTicksLeft > 0) - cooldownTicksLeft--; - - // 自动执行已设定的飞越任务 - if (flyOverTarget.IsValid && IsReady) - { - ExecuteFlyOverMission(); - } - } - - public override string GetInspectString() - { - StringBuilder sb = new StringBuilder(base.GetInspectString()); - - if (cooldownTicksLeft > 0) - { - if (sb.Length > 0) sb.AppendLine(); - sb.Append("飞越信标冷却中: ".Translate() + cooldownTicksLeft.ToStringTicksToPeriod()); - } - - if (flyOverTarget.IsValid) - { - if (sb.Length > 0) sb.AppendLine(); - sb.Append("已锁定目标: ".Translate() + flyOverTarget.Label); - } - - if (!IsReady) - { - if (sb.Length > 0) sb.AppendLine(); - if (powerComp != null && !powerComp.PowerOn) - sb.Append("需要电力".Translate()); - else if (refuelableComp != null && !refuelableComp.HasFuel) - sb.Append("需要燃料".Translate()); - else if (cooldownTicksLeft > 0) - sb.Append("冷却中".Translate()); - } - - return sb.ToString(); - } - - public override IEnumerable GetGizmos() - { - foreach (var g in base.GetGizmos()) - { - yield return g; - } - - // 召唤飞越命令 - Command_Action callFlyOver = new Command_Action - { - defaultLabel = "召唤跨图飞越", - defaultDesc = "在世界地图上选择目标位置召唤飞越单位", - icon = CallFlyOverTex, - action = StartChoosingFlyOverTarget - }; - - if (!IsReady) - { - callFlyOver.Disable(GetDisabledReason()); - } - yield return callFlyOver; - - // 配置飞越参数命令 - if (flyOverTarget.IsValid) - { - Command_Action configureFlyOver = new Command_Action - { - defaultLabel = "配置飞越参数", - defaultDesc = "调整飞越单位的类型和行为", - icon = ContentFinder.Get("UI/Commands/Configure", true), - action = OpenConfigurationDialog - }; - yield return configureFlyOver; - - // 清除目标命令 - Command_Action clearTarget = new Command_Action - { - defaultLabel = "清除目标", - defaultDesc = "清除已锁定的飞越目标", - icon = ContentFinder.Get("UI/Designators/Cancel", true), - action = () => flyOverTarget = GlobalTargetInfo.Invalid - }; - yield return clearTarget; - } - } - - private string GetDisabledReason() - { - if (powerComp != null && !powerComp.PowerOn) - return "需要电力"; - if (refuelableComp != null && !refuelableComp.HasFuel) - return "需要燃料"; - if (cooldownTicksLeft > 0) - return "冷却中"; - return "无法使用"; - } - - private void StartChoosingFlyOverTarget() - { - CameraJumper.TryJump(CameraJumper.GetWorldTarget(this)); - Find.WorldSelector.ClearSelection(); - - Find.WorldTargeter.BeginTargeting( - ChooseWorldTarget, - canTargetTiles: true, - targeterMouseAttachment: CallFlyOverTex, - extraLabelGetter: GetExtraTargetingLabel - ); - } - - private string GetExtraTargetingLabel(GlobalTargetInfo target) - { - if (target.IsValid) - { - return "召唤飞越至: " + target.Label; - } - return "选择飞越目标位置"; - } - - private bool ChooseWorldTarget(GlobalTargetInfo target) - { - if (!target.IsValid) - { - Messages.Message("无效的目标位置", MessageTypeDefOf.RejectInput); - return false; - } - - if (target.Tile == this.Map.Tile) - { - Messages.Message("无法在同一地图召唤飞越", MessageTypeDefOf.RejectInput); - return false; - } - - // 处理不同类型的目标 - if (target.WorldObject is MapParent mapParent && mapParent.HasMap) - { - // 切换到目标地图选择具体飞越路径 - var originalMap = this.Map; - Action onFinished = () => { - if (Current.Game.CurrentMap != originalMap) - Current.Game.CurrentMap = originalMap; - }; - - Current.Game.CurrentMap = mapParent.Map; - Find.Targeter.BeginTargeting( - new TargetingParameters - { - canTargetLocations = true, - canTargetPawns = false, - canTargetBuildings = false, - mapObjectTargetsMustBeAutoAttackable = false - }, - (LocalTargetInfo localTarget) => - { - // 设置飞越配置 - flyOverTarget = new GlobalTargetInfo(localTarget.Cell, mapParent.Map); - flyOverConfig.targetCell = localTarget.Cell; - flyOverConfig.targetMap = mapParent.Map; - - // 自动计算飞越路径 - CalculateFlyOverPath(mapParent.Map, localTarget.Cell); - }, - null, onFinished, CallFlyOverTex, true); - } - else - { - // 空地目标,生成临时地图 - flyOverTarget = target; - flyOverConfig.targetTile = target.Tile; - CalculateFlyOverPathForTile(target.Tile); - } - - return true; - } - - private void CalculateFlyOverPath(Map targetMap, IntVec3 targetCell) - { - // 计算从地图边缘到目标点的飞越路径 - Vector3 targetPos = targetCell.ToVector3(); - - // 随机选择进入方向 - Vector3[] approachDirections = { - new Vector3(1, 0, 0), // 从右边进入 - new Vector3(-1, 0, 0), // 从左边进入 - new Vector3(0, 0, 1), // 从上边进入 - new Vector3(0, 0, -1) // 从下边进入 - }; - - Vector3 approachDir = approachDirections.RandomElement(); - Vector3 startPos = FindMapEdgePosition(targetMap, approachDir); - Vector3 endPos = FindMapEdgePosition(targetMap, -approachDir); // 从对面飞出 - - flyOverConfig.startPos = startPos.ToIntVec3(); - flyOverConfig.endPos = endPos.ToIntVec3(); - flyOverConfig.approachType = FlyOverApproachType.StraightLine; - - Log.Message($"Calculated flyover path: {flyOverConfig.startPos} -> {targetCell} -> {flyOverConfig.endPos}"); - } - - private void CalculateFlyOverPathForTile(int tile) - { - // 为地图瓦片计算默认飞越路径(穿越地图中心) - Map targetMap = GetOrGenerateMapUtility.GetOrGenerateMap(tile, Find.World.info.initialMapSize, null); - if (targetMap != null) - { - targetMap.fogGrid.ClearAllFog(); // 获得视野 - - IntVec3 center = targetMap.Center; - CalculateFlyOverPath(targetMap, center); - } - } - - private IntVec3 FindMapEdgePosition(Map map, Vector3 direction) - { - // 找到地图边缘位置 - Vector3 center = map.Center.ToVector3(); - Vector3 edgePos = center; - float maxDistance = Mathf.Max(map.Size.x, map.Size.z) * 0.6f; - - for (int i = 1; i <= maxDistance; i++) - { - Vector3 testPos = center + direction.normalized * i; - IntVec3 testCell = new IntVec3((int)testPos.x, 0, (int)testPos.z); - - if (!testCell.InBounds(map)) - { - // 找到最近的边界内单元格 - return FindClosestValidPosition(testCell, map); - } - } - - return map.Center; - } - - private IntVec3 FindClosestValidPosition(IntVec3 invalidPos, Map map) - { - for (int radius = 1; radius <= 10; radius++) - { - foreach (IntVec3 offset in GenRadial.RadialPatternInRadius(radius)) - { - IntVec3 testPos = invalidPos + offset; - if (testPos.InBounds(map)) - return testPos; - } - } - return map.Center; - } - - private void OpenConfigurationDialog() - { - // 打开飞越配置对话框 - List options = new List - { - new FloatMenuOption("标准侦察飞越", () => ConfigureStandardRecon()), - new FloatMenuOption("地面扫射飞越", () => ConfigureGroundStrafing()), - new FloatMenuOption("监视巡逻飞越", () => ConfigureSurveillance()), - new FloatMenuOption("货运投送飞越", () => ConfigureCargoDrop()) - }; - - Find.WindowStack.Add(new FloatMenu(options)); - } - - private void ConfigureStandardRecon() - { - flyOverConfig.flyOverType = FlyOverType.Standard; - flyOverConfig.flyOverDef = DefDatabase.GetNamedSilentFail("ARA_HiveScout"); - flyOverConfig.altitude = 20f; - flyOverConfig.flightSpeed = 1.2f; - Messages.Message("已配置为标准侦察飞越", MessageTypeDefOf.TaskCompletion); - } - - private void ConfigureGroundStrafing() - { - flyOverConfig.flyOverType = FlyOverType.GroundStrafing; - flyOverConfig.flyOverDef = DefDatabase.GetNamedSilentFail("ARA_HiveGunship"); - flyOverConfig.altitude = 10f; - flyOverConfig.flightSpeed = 0.8f; - flyOverConfig.enableStrafing = true; - Messages.Message("已配置为地面扫射飞越", MessageTypeDefOf.TaskCompletion); - } - - private void ConfigureSurveillance() - { - flyOverConfig.flyOverType = FlyOverType.Surveillance; - flyOverConfig.flyOverDef = DefDatabase.GetNamedSilentFail("ARA_HiveObserver"); - flyOverConfig.altitude = 25f; - flyOverConfig.flightSpeed = 0.6f; - flyOverConfig.enableSurveillance = true; - Messages.Message("已配置为监视巡逻飞越", MessageTypeDefOf.TaskCompletion); - } - - private void ConfigureCargoDrop() - { - flyOverConfig.flyOverType = FlyOverType.CargoDrop; - flyOverConfig.flyOverDef = DefDatabase.GetNamedSilentFail("ARA_HiveTransport"); - flyOverConfig.altitude = 15f; - flyOverConfig.flightSpeed = 1.0f; - flyOverConfig.dropContentsOnImpact = true; - Messages.Message("已配置为货运投送飞越", MessageTypeDefOf.TaskCompletion); - } - - public void ExecuteFlyOverMission() - { - if (!IsReady) return; - - try - { - Log.Message($"[FlyOverBeacon] Executing flyover mission to {flyOverTarget.Label}"); - - // 创建世界飞越载体 - WorldObject_FlyOverCarrier carrier = (WorldObject_FlyOverCarrier)WorldObjectMaker.MakeWorldObject( - DefDatabase.GetNamed("FlyOverCarrier") - ); - - carrier.Tile = this.Map.Tile; - carrier.destinationTile = flyOverTarget.Tile; - carrier.flyOverConfig = flyOverConfig.Clone(); - carrier.sourceBeacon = this; - - Find.WorldObjects.Add(carrier); - - // 本地视觉效果 - CreateLocalLaunchEffects(); - - // 资源消耗 - if (refuelableComp != null) - refuelableComp.ConsumeFuel(1); - - // 进入冷却 - cooldownTicksLeft = 6000; // 1分钟冷却 - - Messages.Message($"飞越单位已派遣至 {flyOverTarget.Label}", MessageTypeDefOf.PositiveEvent); - - } - catch (Exception ex) - { - Log.Error($"Error executing flyover mission: {ex}"); - Messages.Message("飞越任务执行失败", MessageTypeDefOf.NegativeEvent); - } - } - - private void CreateLocalLaunchEffects() - { - // 发射视觉效果 - MoteMaker.MakeStaticMote(this.DrawPos, this.Map, ThingDefOf.Mote_ExplosionFlash, 3f); - - for (int i = 0; i < 3; i++) - { - FleckMaker.ThrowSmoke(this.DrawPos, this.Map, 2f); - FleckMaker.ThrowLightningGlow(this.DrawPos, this.Map, 1.5f); - } - - // 发射音效 - SoundDefOf.PsychicPulseGlobal.PlayOneShot(new TargetInfo(this.Position, this.Map)); - } - } - - // 飞越配置类 - public class FlyOverConfig : IExposable - { - public ThingDef flyOverDef; - public FlyOverType flyOverType = FlyOverType.Standard; - public IntVec3 startPos; - public IntVec3 endPos; - public IntVec3 targetCell; - public Map targetMap; - public int targetTile = -1; - public float flightSpeed = 1f; - public float altitude = 15f; - public bool dropContentsOnImpact = false; - public bool enableStrafing = false; - public bool enableSurveillance = false; - public FlyOverApproachType approachType = FlyOverApproachType.StraightLine; - - public void ExposeData() - { - Scribe_Defs.Look(ref flyOverDef, "flyOverDef"); - Scribe_Values.Look(ref flyOverType, "flyOverType", FlyOverType.Standard); - Scribe_Values.Look(ref startPos, "startPos"); - Scribe_Values.Look(ref endPos, "endPos"); - Scribe_Values.Look(ref targetCell, "targetCell"); - Scribe_References.Look(ref targetMap, "targetMap"); - Scribe_Values.Look(ref targetTile, "targetTile", -1); - Scribe_Values.Look(ref flightSpeed, "flightSpeed", 1f); - Scribe_Values.Look(ref altitude, "altitude", 15f); - Scribe_Values.Look(ref dropContentsOnImpact, "dropContentsOnImpact", false); - Scribe_Values.Look(ref enableStrafing, "enableStrafing", false); - Scribe_Values.Look(ref enableSurveillance, "enableSurveillance", false); - Scribe_Values.Look(ref approachType, "approachType", FlyOverApproachType.StraightLine); - } - - public FlyOverConfig Clone() - { - return new FlyOverConfig - { - flyOverDef = this.flyOverDef, - flyOverType = this.flyOverType, - startPos = this.startPos, - endPos = this.endPos, - targetCell = this.targetCell, - targetMap = this.targetMap, - targetTile = this.targetTile, - flightSpeed = this.flightSpeed, - altitude = this.altitude, - dropContentsOnImpact = this.dropContentsOnImpact, - enableStrafing = this.enableStrafing, - enableSurveillance = this.enableSurveillance, - approachType = this.approachType - }; - } - } - - public enum FlyOverType - { - Standard, - GroundStrafing, - Surveillance, - CargoDrop - } - - public enum FlyOverApproachType - { - StraightLine, - CirclePattern, - FigureEight - } -} diff --git a/Source/WulaFallenEmpire/BuildingComp/WULA_FlyOverBeacon/WorldObject_FlyOverCarrier.cs b/Source/WulaFallenEmpire/BuildingComp/WULA_FlyOverBeacon/WorldObject_FlyOverCarrier.cs deleted file mode 100644 index 92a533b6..00000000 --- a/Source/WulaFallenEmpire/BuildingComp/WULA_FlyOverBeacon/WorldObject_FlyOverCarrier.cs +++ /dev/null @@ -1,241 +0,0 @@ -using RimWorld.Planet; -using UnityEngine; -using Verse; -using RimWorld; -using System.Collections.Generic; - -namespace WulaFallenEmpire -{ - public class WorldObject_FlyOverCarrier : WorldObject - { - public int destinationTile = -1; - public FlyOverConfig flyOverConfig; - public Building_FlyOverBeacon sourceBeacon; - - private int initialTile = -1; - private float traveledPct; - private const float TravelSpeed = 0.0001f; // 比导弹慢,适合侦察 - - public override void ExposeData() - { - base.ExposeData(); - Scribe_Values.Look(ref destinationTile, "destinationTile", -1); - Scribe_Deep.Look(ref flyOverConfig, "flyOverConfig"); - Scribe_References.Look(ref sourceBeacon, "sourceBeacon"); - Scribe_Values.Look(ref initialTile, "initialTile", -1); - Scribe_Values.Look(ref traveledPct, "traveledPct", 0f); - } - - public override void PostAdd() - { - base.PostAdd(); - this.initialTile = this.Tile; - Log.Message($"[FlyOverCarrier] Launched from tile {initialTile} to {destinationTile}"); - } - - private Vector3 StartPos => Find.WorldGrid.GetTileCenter(this.initialTile); - private Vector3 EndPos => Find.WorldGrid.GetTileCenter(this.destinationTile); - - public override Vector3 DrawPos => Vector3.Slerp(StartPos, EndPos, traveledPct); - - protected override void Tick() - { - base.Tick(); - - if (this.destinationTile < 0) - { - Log.Error("FlyOverCarrier has invalid destination tile"); - Find.WorldObjects.Remove(this); - return; - } - - float distance = GenMath.SphericalDistance(StartPos.normalized, EndPos.normalized); - if (distance > 0) - { - traveledPct += TravelSpeed / distance; - } - else - { - traveledPct = 1; - } - - // 更新世界图标位置 - if (Find.WorldRenderer != null) - { - Find.WorldRenderer.Notify_WorldObjectPosChanged(this); - } - - if (traveledPct >= 1f) - { - Arrived(); - } - } - - private void Arrived() - { - Log.Message($"[FlyOverCarrier] Arrived at destination tile {destinationTile}"); - - Map targetMap = GetTargetMap(); - if (targetMap != null) - { - CreateFlyOverInTargetMap(targetMap); - } - else - { - Log.Warning($"[FlyOverCarrier] Could not find or generate map for tile {destinationTile}"); - } - - // 通知源信标任务完成 - if (sourceBeacon != null && !sourceBeacon.Destroyed) - { - Messages.Message($"飞越单位已到达 {flyOverConfig.targetMap?.Parent?.Label ?? "目标区域"}", - sourceBeacon, MessageTypeDefOf.PositiveEvent); - } - - Find.WorldObjects.Remove(this); - } - - private Map GetTargetMap() - { - // 优先使用配置中的目标地图 - if (flyOverConfig.targetMap != null && !flyOverConfig.targetMap.Destroyed) - { - return flyOverConfig.targetMap; - } - - // 生成临时地图 - return GetOrGenerateMapUtility.GetOrGenerateMap(destinationTile, Find.World.info.initialMapSize, null); - } - - private void CreateFlyOverInTargetMap(Map targetMap) - { - if (flyOverConfig.flyOverDef == null) - { - Log.Warning("[FlyOverCarrier] No fly over def specified, using default"); - flyOverConfig.flyOverDef = DefDatabase.GetNamedSilentFail("ARA_HiveScout"); - } - - // 确保目标地图有视野 - targetMap.fogGrid.ClearAllFog(); - - // 验证并调整飞越路径 - IntVec3 startPos = ValidateAndAdjustPosition(flyOverConfig.startPos, targetMap); - IntVec3 endPos = ValidateAndAdjustPosition(flyOverConfig.endPos, targetMap); - - Log.Message($"[FlyOverCarrier] Creating flyover: {startPos} -> {endPos} in {targetMap}"); - - // 创建飞越物体 - FlyOver flyOver = FlyOver.MakeFlyOver( - flyOverConfig.flyOverDef, - startPos, - endPos, - targetMap, - flyOverConfig.flightSpeed, - flyOverConfig.altitude, - casterPawn: null - ); - - // 配置飞越属性 - flyOver.spawnContentsOnImpact = flyOverConfig.dropContentsOnImpact; - flyOver.playFlyOverSound = true; - flyOver.faction = sourceBeacon?.Faction; - - // 配置特殊组件 - ConfigureFlyOverComponents(flyOver); - - // 创建到达视觉效果 - CreateArrivalEffects(targetMap, startPos); - } - - private IntVec3 ValidateAndAdjustPosition(IntVec3 pos, Map map) - { - if (pos.IsValid && pos.InBounds(map)) - return pos; - - // 如果位置无效,使用地图边缘位置 - return CellFinder.RandomEdgeCell(Rand.Range(0, 4), map); - } - - private void ConfigureFlyOverComponents(FlyOver flyOver) - { - // 地面扫射配置 - if (flyOverConfig.enableStrafing) - { - CompGroundStrafing strafingComp = flyOver.GetComp(); - if (strafingComp != null) - { - // 计算扫射区域 - Vector3 flightDirection = (flyOverConfig.endPos.ToVector3() - flyOverConfig.startPos.ToVector3()).normalized; - List impactCells = CalculateStrafingImpactCells(flyOverConfig.targetCell, flightDirection); - List confirmedTargets = PreprocessStrafingTargets(impactCells, 0.7f); - - strafingComp.SetConfirmedTargets(confirmedTargets); - } - } - - // 监视功能配置 - if (flyOverConfig.enableSurveillance) - { - // 可以在这里添加监视组件的配置 - Log.Message("[FlyOverCarrier] Surveillance mode configured"); - } - } - - private List CalculateStrafingImpactCells(IntVec3 targetCell, Vector3 flightDirection) - { - // 简化的扫射区域计算 - List cells = new List(); - Map map = Find.CurrentMap; - - if (map != null) - { - Vector3 perpendicular = new Vector3(-flightDirection.z, 0f, flightDirection.x).normalized; - - for (int i = -2; i <= 2; i++) - { - for (int j = -5; j <= 5; j++) - { - Vector3 offset = perpendicular * i + flightDirection * j; - IntVec3 cell = targetCell + new IntVec3((int)offset.x, 0, (int)offset.z); - - if (cell.InBounds(map)) - { - cells.Add(cell); - } - } - } - } - - return cells; - } - - private List PreprocessStrafingTargets(List potentialTargets, float fireChance) - { - List confirmedTargets = new List(); - - foreach (IntVec3 cell in potentialTargets) - { - if (Rand.Value <= fireChance) - { - confirmedTargets.Add(cell); - } - } - - return confirmedTargets; - } - - private void CreateArrivalEffects(Map targetMap, IntVec3 entryPos) - { - // 进入视觉效果 - MoteMaker.MakeStaticMote(entryPos.ToVector3Shifted(), targetMap, ThingDefOf.Mote_PsycastAreaEffect, 2f); - - for (int i = 0; i < 5; i++) - { - FleckMaker.ThrowAirPuffUp(entryPos.ToVector3Shifted(), targetMap); - } - - // 进入音效 - SoundDefOf.PsychicPulse.PlayOneShot(new TargetInfo(entryPos, targetMap)); - } - } -} diff --git a/Source/WulaFallenEmpire/Pawn/Comp_MultiTurretGun.cs b/Source/WulaFallenEmpire/Pawn/Comp_MultiTurretGun.cs new file mode 100644 index 00000000..2ad4d4bf --- /dev/null +++ b/Source/WulaFallenEmpire/Pawn/Comp_MultiTurretGun.cs @@ -0,0 +1,71 @@ +using System; +using System.Collections.Generic; +using Verse; +using Verse.AI; +using RimWorld; +using UnityEngine; + +namespace WulaFallenEmpire +{ + public class CompProperties_MultiTurretGun : CompProperties_TurretGun + { + public int ID; + public CompProperties_MultiTurretGun() + { + compClass = typeof(Comp_MultiTurretGun); + } + } + public class Comp_MultiTurretGun : CompTurretGun + { + private bool fireAtWill = true; + public new CompProperties_MultiTurretGun Props => (CompProperties_MultiTurretGun)props; + public override void CompTick() + { + base.CompTick(); + if (!currentTarget.IsValid && burstCooldownTicksLeft <= 0) + { + // 在其他情况下没有目标且冷却结束时也回正 + curRotation = parent.Rotation.AsAngle + Props.angleOffset; + } + } + private void MakeGun() + { + gun = ThingMaker.MakeThing(Props.turretDef); + UpdateGunVerbs(); + } + private void UpdateGunVerbs() + { + List allVerbs = gun.TryGetComp().AllVerbs; + for (int i = 0; i < allVerbs.Count; i++) + { + Verb verb = allVerbs[i]; + verb.caster = parent; + verb.castCompleteCallback = delegate + { + burstCooldownTicksLeft = AttackVerb.verbProps.defaultCooldownTime.SecondsToTicks(); + }; + } + } + public override void PostExposeData() + { + Scribe_Values.Look(ref burstCooldownTicksLeft, "burstCooldownTicksLeft", 0); + Scribe_Values.Look(ref burstWarmupTicksLeft, "burstWarmupTicksLeft", 0); + Scribe_TargetInfo.Look(ref currentTarget, "currentTarget_" + Props.ID); + Scribe_Deep.Look(ref gun, "gun_" + Props.ID); + Scribe_Values.Look(ref fireAtWill, "fireAtWill", defaultValue: true); + if (Scribe.mode == LoadSaveMode.PostLoadInit) + { + if (gun == null) + { + Log.Error("CompTurrentGun had null gun after loading. Recreating."); + MakeGun(); + } + else + { + UpdateGunVerbs(); + } + } + } + } + +} diff --git a/Source/WulaFallenEmpire/Pawn/Comp_PawnRenderExtra.cs b/Source/WulaFallenEmpire/Pawn/Comp_PawnRenderExtra.cs new file mode 100644 index 00000000..59e9c278 --- /dev/null +++ b/Source/WulaFallenEmpire/Pawn/Comp_PawnRenderExtra.cs @@ -0,0 +1,128 @@ +using System; +using System.Reflection.Emit; +using System.Runtime.Remoting.Messaging; +using RimWorld; +using UnityEngine; +using Verse; + +namespace WulaFallenEmpire +{ + public class CompProperties_PawnRenderExtra : CompProperties + { + public CompProperties_PawnRenderExtra() + { + this.compClass = typeof(Comp_PawnRenderExtra); + } + + public string path; + + public Vector3 size; + + public Color colorAlly; + + public Color colorEnemy; + + public ShaderTypeDef shader; + + public DrawData drawData; + } + [StaticConstructorOnStartup] + public class Comp_PawnRenderExtra : ThingComp + { + public CompProperties_PawnRenderExtra Props + { + get + { + return this.props as CompProperties_PawnRenderExtra; + } + } + + private Pawn ParentPawn + { + get + { + return this.parent as Pawn; + } + } + + public override void PostDraw() + { + base.PostDraw(); + if (!this.ParentPawn.Dead && !this.ParentPawn.Downed && this.ParentPawn.CurJobDef != JobDefOf.MechCharge && this.ParentPawn.CurJobDef != JobDefOf.SelfShutdown) + { + this.DrawPawnRenderExtra(); + } + } + + public void DrawPawnRenderExtra() + { + Vector3 pos = this.ParentPawn.DrawPos; + if (this.ParentPawn.Faction == Faction.OfPlayer || !this.ParentPawn.Faction.HostileTo(Faction.OfPlayer)) + { + this.color = this.Props.colorAlly; + } + else + { + this.color = this.Props.colorEnemy; + } + string graphic = this.GetPawnRenderExtra(); + Vector3 offset = GetOffsetByRot(); + float layer = GetLayerByRot(); + pos.y = AltitudeLayer.Pawn.AltitudeFor(layer); + + Matrix4x4 matrix = default(Matrix4x4); + matrix.SetTRS(pos + offset, Quaternion.AngleAxis(0f, Vector3.up), this.Props.size); + Material material = MaterialPool.MatFrom(graphic, this.Props.shader.Shader, this.color); + Graphics.DrawMesh(MeshPool.plane10, matrix, material, (int)layer); + } + + public Vector3 GetOffsetByRot() + { + Vector3 result; + if (this.Props.drawData != null) + { + result = this.Props.drawData.OffsetForRot(this.ParentPawn.Rotation); + } + else + { + result = Vector3.zero; + } + return result; + } + public float GetLayerByRot() + { + float result; + if (this.Props.drawData != null) + { + result = this.Props.drawData.LayerForRot(this.ParentPawn.Rotation, 0); + } + else + { + result = 0; + } + return result; + } + + public string GetPawnRenderExtra() + { + if (this.ParentPawn.Rotation.AsInt == 0) + { + return this.Props.path + "_north"; + } + if (this.ParentPawn.Rotation.AsInt == 1) + { + return this.Props.path + "_east"; + } + if (this.ParentPawn.Rotation.AsInt == 2) + { + return this.Props.path + "_south"; + } + if (this.ParentPawn.Rotation.AsInt == 3) + { + return this.Props.path + "_west"; + } + return null; + } + public Color color; + } +} diff --git a/Source/WulaFallenEmpire/WulaFallenEmpire.csproj b/Source/WulaFallenEmpire/WulaFallenEmpire.csproj index f4a472f1..7f48a92a 100644 --- a/Source/WulaFallenEmpire/WulaFallenEmpire.csproj +++ b/Source/WulaFallenEmpire/WulaFallenEmpire.csproj @@ -90,8 +90,6 @@ - - @@ -149,6 +147,8 @@ + + @@ -280,7 +280,9 @@ - + + +