This commit is contained in:
2025-12-02 11:15:13 +08:00
parent 86d2428271
commit e3676e9908
12 changed files with 998 additions and 38 deletions

View File

@@ -0,0 +1,197 @@
using System.Collections.Generic;
using System.Linq;
using RimWorld;
using UnityEngine;
using Verse;
namespace WulaFallenEmpire
{
public class Designator_CallSkyfallerInArea : Designator
{
private readonly new Texture2D icon;
// 记录已经处理过的建筑(避免重复)
private HashSet<Thing> processedBuildings = new HashSet<Thing>();
public Designator_CallSkyfallerInArea()
{
defaultLabel = "WULA_Designator_CallSkyfallerInArea".Translate();
defaultDesc = "WULA_Designator_CallSkyfallerInAreaDesc".Translate();
icon = ContentFinder<Texture2D>.Get("Wula/UI/Designators/WULA_AreaSkyfaller");
soundDragSustain = SoundDefOf.Designate_DragStandard;
soundDragChanged = SoundDefOf.Designate_DragStandard_Changed;
useMouseIcon = true;
soundSucceeded = SoundDefOf.Designate_Claim;
hotKey = KeyBindingDefOf.Misc12;
tutorTag = "CallSkyfallerInArea";
}
public override AcceptanceReport CanDesignateCell(IntVec3 c)
{
if (!c.InBounds(Map))
return false;
// 允许在迷雾格上选择(就像拆除和索赔设计器一样)
if (c.Fogged(Map))
return false;
// 只要单元格内有玩家建筑,就允许选择
var things = Map.thingGrid.ThingsListAt(c);
foreach (var thing in things)
{
if (thing.def.category == ThingCategory.Building &&
thing.Faction == Faction.OfPlayer &&
thing.TryGetComp<CompSkyfallerCaller>() != null)
{
return true;
}
}
// 即使单元格内没有符合条件的建筑,也允许选择(这样用户可以拖动区域)
// 但返回一个友好的提示
return "WULA_NoCallableBuildingsInCell".Translate();
}
public override void DesignateSingleCell(IntVec3 c)
{
// 处理单个单元格内的所有建筑
ProcessCell(c);
}
public override void DesignateMultiCell(IEnumerable<IntVec3> cells)
{
// 清除已处理的建筑记录
processedBuildings.Clear();
int totalBuildings = 0;
// 处理所有选中的单元格
foreach (var cell in cells)
{
if (cell.InBounds(Map))
{
// 统计该单元格处理的建筑数量
int cellCount = processedBuildings.Count;
ProcessCell(cell);
int newBuildings = processedBuildings.Count - cellCount;
totalBuildings += newBuildings;
}
}
// 计算成功和失败的数量
// 这里需要跟踪每个建筑的调用结果
// 由于我们直接调用CallSkyfaller需要知道哪些失败了
// 简化处理在ProcessCell中统计
// 显示简单的结果消息
if (totalBuildings > 0)
{
Messages.Message("WULA_AreaCallInitiated".Translate(totalBuildings),
MessageTypeDefOf.PositiveEvent);
}
else
{
Messages.Message("WULA_NoCallableBuildingsInArea".Translate(),
MessageTypeDefOf.NeutralEvent);
}
}
private void ProcessCell(IntVec3 cell)
{
var things = Map.thingGrid.ThingsListAt(cell);
foreach (var thing in things)
{
// 跳过非建筑
if (thing.def.category != ThingCategory.Building)
continue;
// 跳过非玩家建筑
if (thing.Faction != Faction.OfPlayer)
continue;
// 检查是否已经处理过(避免重复处理同一个建筑)
if (processedBuildings.Contains(thing))
continue;
// 获取空投组件
var comp = thing.TryGetComp<CompSkyfallerCaller>();
if (comp == null)
continue;
// 尝试呼叫空投
if (comp.CanCallSkyfaller)
{
comp.CallSkyfaller(false);
processedBuildings.Add(thing);
}
// 即使不能呼叫,也添加到已处理列表,避免重复尝试
else
{
processedBuildings.Add(thing);
}
}
}
public override AcceptanceReport CanDesignateThing(Thing t)
{
// 这里提供单个建筑的反向设计器支持(右键菜单)
if (t.def.category != ThingCategory.Building)
return false;
if (t.Faction != Faction.OfPlayer)
return false;
var comp = t.TryGetComp<CompSkyfallerCaller>();
if (comp == null)
return false;
if (!comp.CanCallSkyfaller)
return GetFailureReason(t, comp);
return true;
}
private string GetFailureReason(Thing building, CompSkyfallerCaller comp)
{
if (!comp.HasRequiredFlyOver && comp.Props.requireFlyOver)
return "WULA_NoBuildingDropperFlyOver".Translate();
if (!comp.CheckRoofConditions)
{
var roof = building.Position.GetRoof(building.Map);
if (roof?.isThickRoof == true)
return "WULA_ThickRoofBlocking".Translate();
else
return "WULA_RoofBlocking".Translate();
}
if (!comp.HasEnoughMaterials())
return "WULA_InsufficientMaterials".Translate();
if (comp.used)
return "WULA_AlreadyUsed".Translate();
if (comp.calling)
return "WULA_AlreadyCalling".Translate();
return "WULA_CannotCallSkyfaller".Translate();
}
public override void DesignateThing(Thing t)
{
// 用于反向设计器(右键菜单)
var comp = t.TryGetComp<CompSkyfallerCaller>();
if (comp != null && comp.CanCallSkyfaller)
{
comp.CallSkyfaller(false);
}
}
public override void SelectedUpdate()
{
// 参考Designator_Deconstruct只绘制鼠标悬停方框
GenUI.RenderMouseoverBracket();
}
}
}