This commit is contained in:
2025-11-27 17:14:53 +08:00
parent 58249fb306
commit 0cca8b0516
30 changed files with 924 additions and 682 deletions

View File

@@ -2,6 +2,7 @@ using RimWorld;
using System.Collections.Generic;
using UnityEngine;
using Verse;
using System.Text;
namespace WulaFallenEmpire
{
@@ -14,6 +15,11 @@ namespace WulaFallenEmpire
private ThingDef restoreBuildingDef;
private int restoreMechanoidCount;
// 缓存校验结果
private bool? lastValidationResult = null;
private string lastValidationReason = null;
private int lastValidationTick = 0;
public override void Initialize(CompProperties props)
{
base.Initialize(props);
@@ -46,9 +52,12 @@ namespace WulaFallenEmpire
};
// 检查是否可以转换
if (!CanTransformNow())
string failReason;
bool canTransform = CanTransformNow(out failReason);
if (!canTransform)
{
command.Disable("无法在当前位置转换");
command.Disable(failReason);
}
yield return command;
@@ -57,12 +66,38 @@ namespace WulaFallenEmpire
private string GetGizmoDescription()
{
string desc = Props.gizmoDesc;
StringBuilder sb = new StringBuilder();
sb.Append(Props.gizmoDesc);
if (restoreBuildingDef != null)
{
desc += $"\n\n将恢复为: {restoreBuildingDef.LabelCap}";
sb.AppendLine();
sb.AppendLine();
sb.Append($"将恢复为: {restoreBuildingDef.LabelCap}");
if (restoreMechanoidCount > 0)
{
sb.AppendLine();
sb.Append($"恢复机械族储存: {restoreMechanoidCount}");
}
}
return desc;
// 添加空间校验信息
string failReason;
bool isValid = CanTransformNow(out failReason);
sb.AppendLine();
sb.AppendLine();
if (isValid)
{
sb.Append("<color=green>✓ 当前位置可以放置建筑</color>");
}
else
{
sb.Append($"<color=red>✗ {failReason}</color>");
}
return sb.ToString();
}
private Texture2D GetGizmoIcon()
@@ -74,25 +109,84 @@ namespace WulaFallenEmpire
return TexCommand.Install;
}
private bool CanTransformNow()
/// <summary>
/// 检查是否可以转换(带详细失败原因)
/// </summary>
private bool CanTransformNow(out string failReason)
{
if (parent == null || !parent.Spawned)
return false;
failReason = null;
// 检查空间是否足够
if (parent == null || !parent.Spawned)
{
failReason = "单位未生成或已销毁";
return false;
}
// 确定要生成的建筑类型
ThingDef buildingDef = restoreBuildingDef ?? Props.targetBuildingDef;
if (buildingDef == null)
return false;
foreach (IntVec3 cell in GenAdj.CellsOccupiedBy(Pawn.Position, Rot4.North, buildingDef.Size))
{
if (!cell.InBounds(Pawn.Map) || !cell.Walkable(Pawn.Map) || cell.GetEdifice(Pawn.Map) != null)
failReason = "无法确定目标建筑类型";
return false;
}
// 使用缓存优化性能每60 tick检查一次
if (lastValidationResult.HasValue && Find.TickManager.TicksGame - lastValidationTick < 60)
{
failReason = lastValidationReason;
return lastValidationResult.Value;
}
// 执行完整的空间校验排除被转换的Pawn本身
bool isValid = TransformValidationUtility.CanPlaceBuildingAt(
buildingDef,
Pawn.Position,
Pawn.Map,
Pawn.Faction,
Pawn, // 排除被转换的Pawn本身
out failReason
);
// 更新缓存
lastValidationResult = isValid;
lastValidationReason = failReason;
lastValidationTick = Find.TickManager.TicksGame;
return isValid;
}
/// <summary>
/// 查找最近的可用位置
/// </summary>
private bool TryFindNearbyValidPosition(out IntVec3 validPosition, out string failReason)
{
validPosition = IntVec3.Invalid;
failReason = null;
ThingDef buildingDef = restoreBuildingDef ?? Props.targetBuildingDef;
if (buildingDef == null)
{
failReason = "无法确定目标建筑类型";
return false;
}
// 在周围搜索可用位置
for (int radius = 1; radius <= 5; radius++)
{
foreach (IntVec3 cell in GenRadial.RadialPatternInRadius(radius))
{
return false;
IntVec3 checkPos = Pawn.Position + cell;
if (TransformValidationUtility.CanPlaceBuildingAt(buildingDef, checkPos, Pawn.Map, Pawn.Faction, Pawn, out failReason))
{
validPosition = checkPos;
return true;
}
}
}
return true;
failReason = "周围没有找到合适的放置位置";
return false;
}
public void TransformToBuilding()
@@ -101,7 +195,7 @@ namespace WulaFallenEmpire
return;
Map map = Pawn.Map;
IntVec3 position = Pawn.Position;
IntVec3 desiredPosition = Pawn.Position;
Faction faction = Pawn.Faction;
// 确定要生成的建筑类型
@@ -112,11 +206,29 @@ namespace WulaFallenEmpire
return;
}
// 最终校验排除被转换的Pawn本身
string failReason;
if (!TransformValidationUtility.CanPlaceBuildingAt(buildingDef, desiredPosition, map, faction, Pawn, out failReason))
{
// 尝试寻找附近的位置
IntVec3 alternativePosition;
if (TryFindNearbyValidPosition(out alternativePosition, out failReason))
{
desiredPosition = alternativePosition;
Messages.Message($"将在附近位置 {desiredPosition} 部署建筑", MessageTypeDefOf.NeutralEvent);
}
else
{
Messages.Message($"无法部署建筑: {failReason}", MessageTypeDefOf.RejectInput);
return;
}
}
// 移除Pawn
Pawn.DeSpawn(DestroyMode.Vanish);
// 生成建筑
Building newBuilding = (Building)GenSpawn.Spawn(buildingDef, position, map, WipeMode.Vanish);
Building newBuilding = (Building)GenSpawn.Spawn(buildingDef, desiredPosition, map, WipeMode.Vanish);
newBuilding.SetFaction(faction);
// 恢复机械族计数
@@ -151,20 +263,33 @@ namespace WulaFallenEmpire
Messages.Message($"{Pawn.LabelCap} 已部署为 {newBuilding.Label}", MessageTypeDefOf.PositiveEvent);
// 播放转换效果
PlayTransformEffects(position, map);
PlayTransformEffects(desiredPosition, map);
// 清除缓存
lastValidationResult = null;
lastValidationReason = null;
}
private void PlayTransformEffects(IntVec3 position, Map map)
{
//// 播放转换视觉效果
// 播放转换视觉效果
//for (int i = 0; i < 3; i++)
//{
// MoteMaker.ThrowSmoke(position.ToVector3Shifted() + new Vector3(0, 0, 0.5f), map, 1.5f);
// MoteMaker.ThrowMicroSparks(position.ToVector3Shifted(), map);
//}
}
// 每tick更新校验状态用于实时反馈
public override void CompTick()
{
base.CompTick();
//// 播放音效
//SoundDefOf.MechClusterDefeated.PlayOneShot(new TargetInfo(position, map));
// 每60 tick清除一次缓存确保校验结果实时更新
if (Find.TickManager.TicksGame % 60 == 0)
{
lastValidationResult = null;
}
}
}
}