1
This commit is contained in:
@@ -0,0 +1,129 @@
|
||||
using System.Collections.Generic;
|
||||
using Verse;
|
||||
using RimWorld;
|
||||
using UnityEngine;
|
||||
|
||||
namespace WulaFallenEmpire
|
||||
{
|
||||
public class Effect_CallSkyfaller : EffectBase
|
||||
{
|
||||
public ThingDef skyfallerDef;
|
||||
public int delayTicks = 120;
|
||||
public bool checkClearance = true;
|
||||
public int clearanceRadius = 3;
|
||||
public string letterLabel;
|
||||
public string letterText;
|
||||
public LetterDef letterDef;
|
||||
|
||||
public override void Execute(Window dialog = null)
|
||||
{
|
||||
Map currentMap = Find.CurrentMap;
|
||||
if (currentMap == null)
|
||||
{
|
||||
Log.Error("[WulaFallenEmpire] Effect_CallSkyfaller cannot execute without a current map.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (skyfallerDef == null)
|
||||
{
|
||||
Log.Error("[WulaFallenEmpire] Effect_CallSkyfaller has a null skyfallerDef.");
|
||||
return;
|
||||
}
|
||||
|
||||
// 寻找合适的掉落点
|
||||
IntVec3 dropCenter;
|
||||
if (checkClearance)
|
||||
{
|
||||
dropCenter = FindDropSpotWithClearance(currentMap, clearanceRadius);
|
||||
}
|
||||
else
|
||||
{
|
||||
dropCenter = DropCellFinder.RandomDropSpot(currentMap);
|
||||
}
|
||||
|
||||
if (!dropCenter.IsValid)
|
||||
{
|
||||
Log.Error("[WulaFallenEmpire] Effect_CallSkyfaller could not find a valid drop spot.");
|
||||
return;
|
||||
}
|
||||
|
||||
// 创建延时召唤
|
||||
CallSkyfallerDelayed(dropCenter, currentMap);
|
||||
|
||||
// 发送通知信件
|
||||
if (!string.IsNullOrEmpty(letterLabel) && !string.IsNullOrEmpty(letterText))
|
||||
{
|
||||
Find.LetterStack.ReceiveLetter(letterLabel, letterText, letterDef ?? LetterDefOf.NeutralEvent);
|
||||
}
|
||||
|
||||
Log.Message($"[WulaFallenEmpire] Scheduled skyfaller '{skyfallerDef.defName}' at {dropCenter} with {delayTicks} ticks delay");
|
||||
}
|
||||
|
||||
private IntVec3 FindDropSpotWithClearance(Map map, int radius)
|
||||
{
|
||||
// 优先在殖民地附近寻找
|
||||
IntVec3 result;
|
||||
if (RCellFinder.TryFindRandomCellNearTheCenterOfTheMapWith(
|
||||
(IntVec3 c) => IsValidDropSpotWithClearance(c, map, radius) && map.reachability.CanReachColony(c),
|
||||
map, out result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
// 如果找不到,放宽条件
|
||||
if (CellFinder.TryFindRandomCellNear(map.Center, map, Mathf.Max(map.Size.x / 4, 10),
|
||||
(IntVec3 c) => IsValidDropSpotWithClearance(c, map, radius), out result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
// 最后尝试任何有效位置
|
||||
if (CellFinder.TryFindRandomCellNear(map.Center, map, map.Size.x / 2,
|
||||
(IntVec3 c) => IsValidDropSpotWithClearance(c, map, radius), out result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
return IntVec3.Invalid;
|
||||
}
|
||||
|
||||
private bool IsValidDropSpotWithClearance(IntVec3 center, Map map, int radius)
|
||||
{
|
||||
// 检查中心点是否有效
|
||||
if (!center.IsValid || !center.InBounds(map) || !center.Standable(map) || center.Fogged(map))
|
||||
return false;
|
||||
|
||||
// 检查指定半径内的所有单元格
|
||||
foreach (IntVec3 cell in GenRadial.RadialCellsAround(center, radius, true))
|
||||
{
|
||||
if (!cell.InBounds(map) || !cell.Walkable(map) || cell.Fogged(map))
|
||||
return false;
|
||||
|
||||
// 检查是否有建筑物阻挡
|
||||
Building building = cell.GetEdifice(map);
|
||||
if (building != null && building.def.passability == Traversability.Impassable)
|
||||
return false;
|
||||
|
||||
// 检查是否有屋顶(可选,根据需求调整)
|
||||
if (cell.Roofed(map))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void CallSkyfallerDelayed(IntVec3 targetCell, Map map)
|
||||
{
|
||||
// 获取或创建延时组件
|
||||
var delayedComponent = map.GetComponent<MapComponent_SkyfallerDelayed>();
|
||||
if (delayedComponent == null)
|
||||
{
|
||||
delayedComponent = new MapComponent_SkyfallerDelayed(map);
|
||||
map.components.Add(delayedComponent);
|
||||
}
|
||||
|
||||
// 安排延时召唤
|
||||
delayedComponent.ScheduleSkyfaller(skyfallerDef, targetCell, delayTicks);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
using RimWorld;
|
||||
using RimWorld.QuestGen;
|
||||
using System;
|
||||
using Verse;
|
||||
|
||||
namespace WulaFallenEmpire
|
||||
{
|
||||
public class QuestNode_EventLetter : QuestNode
|
||||
{
|
||||
[NoTranslate]
|
||||
public SlateRef<string> inSignal;
|
||||
|
||||
public SlateRef<string> eventDefName;
|
||||
|
||||
protected override bool TestRunInt(Slate slate)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void RunInt()
|
||||
{
|
||||
Slate slate = QuestGen.slate;
|
||||
string signal = inSignal.GetValue(slate);
|
||||
string defName = eventDefName.GetValue(slate);
|
||||
|
||||
if (defName.NullOrEmpty())
|
||||
{
|
||||
Log.Error("[WulaFallenEmpire] QuestNode_EventLetter: eventDefName is not specified.");
|
||||
return;
|
||||
}
|
||||
|
||||
// 关键:使用 HardcodedSignalWithQuestID 处理信号
|
||||
string processedSignal = QuestGenUtility.HardcodedSignalWithQuestID(signal) ?? slate.Get<string>("inSignal");
|
||||
|
||||
QuestPart_EventLetter questPart = new QuestPart_EventLetter();
|
||||
questPart.inSignal = processedSignal;
|
||||
questPart.eventDefName = defName;
|
||||
|
||||
QuestGen.quest.AddPart(questPart);
|
||||
}
|
||||
}
|
||||
|
||||
public class QuestPart_EventLetter : QuestPart
|
||||
{
|
||||
public string inSignal;
|
||||
public string eventDefName;
|
||||
|
||||
public override void Notify_QuestSignalReceived(Signal signal)
|
||||
{
|
||||
base.Notify_QuestSignalReceived(signal);
|
||||
|
||||
Log.Message($"[WulaFallenEmpire] QuestPart_EventLetter received signal: '{signal.tag}', waiting for: '{inSignal}'");
|
||||
|
||||
if (signal.tag == inSignal)
|
||||
{
|
||||
Log.Message($"[WulaFallenEmpire] Signal matched! Opening EventDef: {eventDefName}");
|
||||
OpenEventDefWindow(eventDefName);
|
||||
}
|
||||
}
|
||||
|
||||
private void OpenEventDefWindow(string defName)
|
||||
{
|
||||
try
|
||||
{
|
||||
EventDef eventDef = DefDatabase<EventDef>.GetNamed(defName, false);
|
||||
if (eventDef == null)
|
||||
{
|
||||
Log.Error($"[WulaFallenEmpire] EventDef '{defName}' not found in DefDatabase.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (eventDef.windowType == null)
|
||||
{
|
||||
Log.Error($"[WulaFallenEmpire] EventDef '{defName}' has null windowType.");
|
||||
return;
|
||||
}
|
||||
|
||||
Log.Message($"[WulaFallenEmpire] Creating window instance for {defName} with type {eventDef.windowType}");
|
||||
Window window = (Window)Activator.CreateInstance(eventDef.windowType, eventDef);
|
||||
|
||||
Log.Message($"[WulaFallenEmpire] Adding window to WindowStack");
|
||||
Find.WindowStack.Add(window);
|
||||
Log.Message($"[WulaFallenEmpire] Successfully opened EventDef window: {defName}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error($"[WulaFallenEmpire] Error opening EventDef window '{defName}': {ex}");
|
||||
}
|
||||
}
|
||||
|
||||
public override void ExposeData()
|
||||
{
|
||||
base.ExposeData();
|
||||
Scribe_Values.Look(ref inSignal, "inSignal");
|
||||
Scribe_Values.Look(ref eventDefName, "eventDefName");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user