传送器
This commit is contained in:
Binary file not shown.
@@ -1031,9 +1031,9 @@
|
||||
|
||||
<!-- 支援 -->
|
||||
<AbilityDef>
|
||||
<defName>WULA_Support_Shield_Projection</defName>
|
||||
<label>护盾投射</label>
|
||||
<description>以启动拒止舰的止戈立场,在指定地点投射一面球形护盾,阻挡并反射所有的外来射弹。</description>
|
||||
<defName>WULA_Support_Holographic_Flag</defName>
|
||||
<label>空投旗帜</label>
|
||||
<description>从拒止舰队上扔一面全息旗帜到指定地点,激励附近的乌拉星人更英勇地战斗。</description>
|
||||
<iconPath>Wula/UI/Abilities/WULA_Firepower_Minigun_Strafe</iconPath>
|
||||
<cooldownTicksRange>1</cooldownTicksRange>
|
||||
<hotKey>Misc12</hotKey>
|
||||
@@ -1051,10 +1051,42 @@
|
||||
</targetParams>
|
||||
</verbProperties>
|
||||
<comps>
|
||||
<li Class="WulaFallenEmpire.CompProperties_GlobalFlyOverCooldown">
|
||||
<globalCooldownTicks>1000</globalCooldownTicks>
|
||||
<requiredFacility>BombardmentFacility</requiredFacility>
|
||||
<li Class="WulaFallenEmpire.CompProperties_AbilityCallSkyfaller">
|
||||
<delayTicks>0</delayTicks>
|
||||
<skyfallerDef>WULA_Holographic_Flag_Building_Skyfaller</skyfallerDef>
|
||||
<previewRadius>15</previewRadius>
|
||||
<previewColor>(1,1,1,0.5)</previewColor>
|
||||
</li>
|
||||
<li Class="WulaFallenEmpire.CompProperties_RequireFlyOverFacility">
|
||||
<requiredFacility>FactoryFacility</requiredFacility>
|
||||
<facilityNotFoundMessage>需要拥有<color=#BD2F31><i>支援设施</i></color>设施的战舰在地图上才能进行轨道炮击支援</facilityNotFoundMessage>
|
||||
</li>
|
||||
<!-- <li Class="WulaFallenEmpire.CompProperties_AbilityResearchPrereq">
|
||||
<requiredResearch>WULA_Firepower_Minigun_Technology</requiredResearch>
|
||||
</li> -->
|
||||
</comps>
|
||||
</AbilityDef>
|
||||
<AbilityDef>
|
||||
<defName>WULA_Support_Shield_Projection</defName>
|
||||
<label>护盾投射</label>
|
||||
<description>从拒止舰队上扔一面附拒止护盾的全息旗帜到指定地点,激励附近的乌拉星人更英勇地战斗。拒止护盾可以反射所有的敌方射弹,己方的开火不受影响。\n\n在工作一段时间后,该系统将自行烧毁。</description>
|
||||
<iconPath>Wula/UI/Abilities/WULA_Firepower_Minigun_Strafe</iconPath>
|
||||
<cooldownTicksRange>1</cooldownTicksRange>
|
||||
<hotKey>Misc12</hotKey>
|
||||
<casterMustBeCapableOfViolence>false</casterMustBeCapableOfViolence>
|
||||
<verbProperties>
|
||||
<verbClass>Verb_CastAbility</verbClass>
|
||||
<drawAimPie>false</drawAimPie>
|
||||
<requireLineOfSight>false</requireLineOfSight>
|
||||
<warmupTime>1</warmupTime>
|
||||
<range>120</range>
|
||||
<targetable>true</targetable>
|
||||
<targetParams>
|
||||
<canTargetSelf>false</canTargetSelf>
|
||||
<canTargetLocations>true</canTargetLocations>
|
||||
</targetParams>
|
||||
</verbProperties>
|
||||
<comps>
|
||||
<li Class="WulaFallenEmpire.CompProperties_AbilityCallSkyfaller">
|
||||
<delayTicks>0</delayTicks>
|
||||
<skyfallerDef>WULA_Support_Shield_Projection_Skyfaller</skyfallerDef>
|
||||
@@ -1071,4 +1103,41 @@
|
||||
</li> -->
|
||||
</comps>
|
||||
</AbilityDef>
|
||||
<AbilityDef>
|
||||
<defName>WULA_Support_AreaTeleporter</defName>
|
||||
<label>区域传送器</label>
|
||||
<description>从拒止舰队上扔一面附拒止护盾的全息旗帜到指定地点,激励附近的乌拉星人更英勇地战斗。拒止护盾可以反射所有的敌方射弹,己方的开火不受影响。\n\n在工作一段时间后,该系统将自行烧毁。</description>
|
||||
<iconPath>Wula/UI/Abilities/WULA_Firepower_Minigun_Strafe</iconPath>
|
||||
<cooldownTicksRange>1</cooldownTicksRange>
|
||||
<hotKey>Misc12</hotKey>
|
||||
<casterMustBeCapableOfViolence>false</casterMustBeCapableOfViolence>
|
||||
<verbProperties>
|
||||
<verbClass>Verb_CastAbility</verbClass>
|
||||
<drawAimPie>false</drawAimPie>
|
||||
<requireLineOfSight>false</requireLineOfSight>
|
||||
<warmupTime>1</warmupTime>
|
||||
<range>120</range>
|
||||
<targetable>true</targetable>
|
||||
<targetParams>
|
||||
<canTargetSelf>false</canTargetSelf>
|
||||
<canTargetLocations>true</canTargetLocations>
|
||||
</targetParams>
|
||||
</verbProperties>
|
||||
<comps>
|
||||
<li Class="WulaFallenEmpire.CompProperties_AbilityCallSkyfaller">
|
||||
<delayTicks>0</delayTicks>
|
||||
<skyfallerDef>WULA_Support_AreaTeleporter_Skyfaller</skyfallerDef>
|
||||
<previewRadius>20</previewRadius>
|
||||
<previewColor>(0.6,0.8,0.8,0.5)</previewColor>
|
||||
</li>
|
||||
<li Class="WulaFallenEmpire.CompProperties_RequireFlyOverFacility">
|
||||
<!-- <flyOverDef></flyOverDef> -->
|
||||
<requiredFacility>FactoryFacility</requiredFacility>
|
||||
<facilityNotFoundMessage>需要拥有<color=#BD2F31><i>支援设施</i></color>设施的战舰在地图上才能进行轨道炮击支援</facilityNotFoundMessage>
|
||||
</li>
|
||||
<!-- <li Class="WulaFallenEmpire.CompProperties_AbilityResearchPrereq">
|
||||
<requiredResearch>WULA_Firepower_Minigun_Technology</requiredResearch>
|
||||
</li> -->
|
||||
</comps>
|
||||
</AbilityDef>
|
||||
</Defs>
|
||||
@@ -167,7 +167,9 @@
|
||||
<li>WULA_CallMotherShip</li>
|
||||
<li>WULA_CallConstructionShip</li>
|
||||
<li>WULA_ClearFlightPath</li>
|
||||
<li>WULA_Support_Holographic_Flag</li>
|
||||
<li>WULA_Support_Shield_Projection</li>
|
||||
<li>WULA_Support_AreaTeleporter</li>
|
||||
</abilityDefs>
|
||||
</li>
|
||||
</comps>
|
||||
|
||||
@@ -300,7 +300,7 @@
|
||||
<defaultLabelColor>(0.52, 1, 0.95)</defaultLabelColor>
|
||||
<comps>
|
||||
<li Class="HediffCompProperties_Disappears">
|
||||
<disappearsAfterTicks>120</disappearsAfterTicks>
|
||||
<disappearsAfterTicks>125</disappearsAfterTicks>
|
||||
<showRemainingTime>false</showRemainingTime>
|
||||
</li>
|
||||
<li Class="HediffCompProperties_DisappearsOnDeath"/>
|
||||
@@ -309,11 +309,12 @@
|
||||
<li>
|
||||
<minSeverity>0</minSeverity>
|
||||
<statOffsets>
|
||||
<MentalBreakThreshold>-0.01</MentalBreakThreshold>
|
||||
<MentalBreakThreshold>-0.1</MentalBreakThreshold>
|
||||
<MoveSpeed>0.5</MoveSpeed>
|
||||
</statOffsets>
|
||||
<statFactors>
|
||||
<AimingDelayFactor>0.9</AimingDelayFactor>
|
||||
<ShootingAccuracyPawn>1</ShootingAccuracyPawn>
|
||||
<ShootingAccuracyPawn>1.25</ShootingAccuracyPawn>
|
||||
<MeleeDamageFactor>1.1</MeleeDamageFactor>
|
||||
<MeleeCooldownFactor>0.9</MeleeCooldownFactor>
|
||||
</statFactors>
|
||||
|
||||
@@ -2297,6 +2297,7 @@
|
||||
<initialSeverity>0.5</initialSeverity>
|
||||
<onlyPawnsInSameFaction>true</onlyPawnsInSameFaction>
|
||||
<checkIntervalTicks>120</checkIntervalTicks>
|
||||
<hediffDurationTicks>125</hediffDurationTicks>
|
||||
<allowedRaces>
|
||||
<li>WulaSpecies</li>
|
||||
</allowedRaces>
|
||||
@@ -2359,4 +2360,43 @@
|
||||
</li>
|
||||
</comps>
|
||||
</ThingDef>
|
||||
<ThingDef ParentName="WULA_Holographic_Flag_Skyfaller">
|
||||
<defName>WULA_Support_AreaTeleporter_Skyfaller</defName>
|
||||
<label>P.I.A全息旗帜附区域传送器(落地中)</label>
|
||||
<skyfaller>
|
||||
<spawnThing>WULA_Support_AreaTeleporter</spawnThing>
|
||||
</skyfaller>
|
||||
</ThingDef>
|
||||
<ThingDef ParentName="WULA_Holographic_Flag_Building">
|
||||
<defName>WULA_Support_AreaTeleporter</defName>
|
||||
<label>P.I.A全息旗帜附区域传送器</label>
|
||||
<description>乌拉帝国行星封锁机关的全息旗帜,除了宣誓主权外,也能激励附近的乌拉星人更加凶狠地战斗。这面旗帜的底座附带了一个区域传送器,可以使得机械乌拉在旗帜区域内传送。\n\n在工作一段时间后,该系统将自行烧毁。</description>
|
||||
<comps>
|
||||
<li Class="WulaFallenEmpire.CompProperties_CustomRadius">
|
||||
<radius>20</radius> <!-- 半径大小 -->
|
||||
<color>(1, 1, 1)</color> <!-- 绿色圆圈 -->
|
||||
<radiusOffset>0</radiusOffset> <!-- 半径偏移 -->
|
||||
<showInGUI>true</showInGUI>
|
||||
<label>传送范围</label>
|
||||
<description>区域传送器提供的传送范围</description>
|
||||
<defaultVisible>true</defaultVisible>
|
||||
</li>
|
||||
<li Class="CompProperties_Lifespan">
|
||||
<lifespanTicks>3600</lifespanTicks>
|
||||
</li>
|
||||
<li Class="WulaFallenEmpire.CompProperties_AreaTeleporter">
|
||||
<teleportRadius>20</teleportRadius>
|
||||
<stunTicks>60</stunTicks>
|
||||
|
||||
<allowedRaces>
|
||||
<li>WulaSpecies</li>
|
||||
</allowedRaces>
|
||||
<onlyPawnsInSameFaction>true</onlyPawnsInSameFaction>
|
||||
|
||||
<entryEffecter>Skip_Entry</entryEffecter>
|
||||
<exitEffecter>Skip_Exit</exitEffecter>
|
||||
<teleportSound>Psycast_Skip_Entry</teleportSound>
|
||||
</li>
|
||||
</comps>
|
||||
</ThingDef>
|
||||
</Defs>
|
||||
@@ -107,7 +107,6 @@ namespace WulaFallenEmpire
|
||||
var facilitiesComp = flyOver.GetComp<CompFlyOverFacilities>();
|
||||
if (facilitiesComp == null)
|
||||
{
|
||||
Log.Warning($"[RequireFlyOverFacility] FlyOver at {flyOver.Position} has no CompFlyOverFacilities");
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
using RimWorld;
|
||||
using Verse;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace WulaFallenEmpire
|
||||
{
|
||||
public class CompProperties_AreaTeleporter : CompProperties
|
||||
{
|
||||
public float teleportRadius = 15f;
|
||||
|
||||
// 种族筛选
|
||||
public List<ThingDef> allowedRaces;
|
||||
public List<ThingDef> excludedRaces;
|
||||
public bool requireHumanlike = false;
|
||||
public bool requireAnimal = false;
|
||||
public bool requireMechanoid = false;
|
||||
|
||||
// 派系控制
|
||||
public bool onlyPawnsInSameFaction = true;
|
||||
public bool affectAllies = true;
|
||||
public bool affectEnemies = true;
|
||||
public bool affectNeutrals = true;
|
||||
public bool affectPrisoners = false;
|
||||
public bool affectSlaves = false;
|
||||
|
||||
// 传送设置 - 移除冷却时间
|
||||
public int checkIntervalTicks = 30; // 检查间隔
|
||||
public int stunTicks = 30; // 传送后眩晕时间
|
||||
public int maxPositionAdjustRadius = 5; // 最大位置调整半径
|
||||
|
||||
// 效果设置
|
||||
public EffecterDef entryEffecter;
|
||||
public EffecterDef exitEffecter;
|
||||
public EffecterDef enterRangeEffecter;
|
||||
public EffecterDef leaveRangeEffecter;
|
||||
public SoundDef teleportSound;
|
||||
|
||||
// 到达时的喧嚣效果
|
||||
public ClamorDef destClamorType;
|
||||
public float destClamorRadius = 2f;
|
||||
|
||||
public CompProperties_AreaTeleporter()
|
||||
{
|
||||
compClass = typeof(ThingComp_AreaTeleporter);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
using HarmonyLib;
|
||||
using RimWorld;
|
||||
using Verse;
|
||||
using Verse.AI;
|
||||
|
||||
namespace WulaFallenEmpire
|
||||
{
|
||||
[HarmonyPatch(typeof(Pawn_JobTracker), "StartJob")]
|
||||
public static class Patch_Pawn_JobTracker_StartJob
|
||||
{
|
||||
[HarmonyPostfix]
|
||||
public static void Postfix(Pawn_JobTracker __instance, Pawn ___pawn)
|
||||
{
|
||||
// 检查是否是移动相关的任务
|
||||
if (___pawn?.Map == null || ___pawn.Dead || ___pawn.Downed)
|
||||
return;
|
||||
|
||||
if (__instance.curJob == null)
|
||||
return;
|
||||
|
||||
// 只处理移动任务
|
||||
if (__instance.curJob.def == JobDefOf.Goto ||
|
||||
__instance.curJob.def == JobDefOf.GotoWander ||
|
||||
__instance.curJob.def == JobDefOf.Follow)
|
||||
{
|
||||
// 通知区域传送器检查这个Pawn
|
||||
NotifyAreaTeleporters(___pawn);
|
||||
}
|
||||
}
|
||||
|
||||
private static void NotifyAreaTeleporters(Pawn pawn)
|
||||
{
|
||||
if (pawn.Map == null)
|
||||
return;
|
||||
|
||||
// 查找范围内的所有区域传送器
|
||||
foreach (var thing in pawn.Map.listerThings.ThingsOfDef(ThingDef.Named("WULA_Support_AreaTeleporter")))
|
||||
{
|
||||
var comp = thing.TryGetComp<ThingComp_AreaTeleporter>();
|
||||
if (comp != null && pawn.Position.DistanceTo(thing.Position) <= comp.Props.teleportRadius)
|
||||
{
|
||||
// 强制立即检查这个Pawn
|
||||
comp.ForceCheckPawn(pawn);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 为ThingComp_AreaTeleporter添加强制检查方法
|
||||
public partial class ThingComp_AreaTeleporter
|
||||
{
|
||||
public void ForceCheckPawn(Pawn pawn)
|
||||
{
|
||||
if (parent == null || !parent.Spawned || parent.Map == null)
|
||||
return;
|
||||
|
||||
if (pawn.Position.DistanceTo(parent.Position) > Props.teleportRadius)
|
||||
return;
|
||||
|
||||
if (!ShouldAffectPawn(pawn))
|
||||
return;
|
||||
|
||||
TryTeleportPawn(pawn);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,548 @@
|
||||
using RimWorld;
|
||||
using Verse;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using HarmonyLib;
|
||||
using Verse.AI;
|
||||
using Verse.Sound;
|
||||
|
||||
namespace WulaFallenEmpire
|
||||
{
|
||||
public partial class ThingComp_AreaTeleporter : ThingComp
|
||||
{
|
||||
public CompProperties_AreaTeleporter Props => (CompProperties_AreaTeleporter)props;
|
||||
|
||||
// 跟踪范围内的Pawn
|
||||
private HashSet<Pawn> pawnsInRange = new HashSet<Pawn>();
|
||||
|
||||
// 效果器缓存
|
||||
private Dictionary<Pawn, Effecter> effecters = new Dictionary<Pawn, Effecter>();
|
||||
|
||||
// 网络相关:存储同一地图上的所有传送器
|
||||
private static Dictionary<Map, HashSet<ThingComp_AreaTeleporter>> teleporterNetworks =
|
||||
new Dictionary<Map, HashSet<ThingComp_AreaTeleporter>>();
|
||||
|
||||
// 硬编码的工作排除表
|
||||
private static readonly HashSet<JobDef> ExcludedJobs = new HashSet<JobDef>
|
||||
{
|
||||
JobDefOf.GotoWander // 排除闲逛工作
|
||||
};
|
||||
|
||||
public override void Initialize(CompProperties props)
|
||||
{
|
||||
base.Initialize(props);
|
||||
RegisterToNetwork();
|
||||
}
|
||||
|
||||
public override void PostSpawnSetup(bool respawningAfterLoad)
|
||||
{
|
||||
base.PostSpawnSetup(respawningAfterLoad);
|
||||
RegisterToNetwork();
|
||||
}
|
||||
|
||||
public override void PostDeSpawn(Map map, DestroyMode mode = DestroyMode.Vanish)
|
||||
{
|
||||
base.PostDeSpawn(map);
|
||||
UnregisterFromNetwork();
|
||||
}
|
||||
|
||||
public override void PostDestroy(DestroyMode mode, Map previousMap)
|
||||
{
|
||||
base.PostDestroy(mode, previousMap);
|
||||
UnregisterFromNetwork();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 注册到网络
|
||||
/// </summary>
|
||||
private void RegisterToNetwork()
|
||||
{
|
||||
if (parent?.Map == null) return;
|
||||
|
||||
var map = parent.Map;
|
||||
if (!teleporterNetworks.ContainsKey(map))
|
||||
{
|
||||
teleporterNetworks[map] = new HashSet<ThingComp_AreaTeleporter>();
|
||||
}
|
||||
|
||||
teleporterNetworks[map].Add(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从网络注销
|
||||
/// </summary>
|
||||
private void UnregisterFromNetwork()
|
||||
{
|
||||
if (parent?.Map == null) return;
|
||||
|
||||
var map = parent.Map;
|
||||
if (teleporterNetworks.ContainsKey(map))
|
||||
{
|
||||
teleporterNetworks[map].Remove(this);
|
||||
if (teleporterNetworks[map].Count == 0)
|
||||
{
|
||||
teleporterNetworks.Remove(map);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取同一地图上的所有传送器
|
||||
/// </summary>
|
||||
private HashSet<ThingComp_AreaTeleporter> GetNetworkTeleporters()
|
||||
{
|
||||
if (parent?.Map == null) return new HashSet<ThingComp_AreaTeleporter>();
|
||||
|
||||
if (teleporterNetworks.TryGetValue(parent.Map, out var network))
|
||||
{
|
||||
return network;
|
||||
}
|
||||
return new HashSet<ThingComp_AreaTeleporter>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查位置是否在传送网络的范围内
|
||||
/// </summary>
|
||||
private bool IsPositionInNetworkRange(IntVec3 position)
|
||||
{
|
||||
if (parent?.Map == null) return false;
|
||||
|
||||
foreach (var teleporter in GetNetworkTeleporters())
|
||||
{
|
||||
if (teleporter.parent?.Spawned == true &&
|
||||
position.DistanceTo(teleporter.parent.Position) <= teleporter.Props.teleportRadius)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在传送网络范围内寻找安全的传送位置
|
||||
/// </summary>
|
||||
private IntVec3 FindSafePositionInNetwork(IntVec3 preferredPosition, Pawn pawn)
|
||||
{
|
||||
if (parent?.Map == null) return IntVec3.Invalid;
|
||||
|
||||
var map = parent.Map;
|
||||
|
||||
// 首先检查首选位置
|
||||
if (preferredPosition.InBounds(map) && CanTeleportTo(preferredPosition, map))
|
||||
return preferredPosition;
|
||||
|
||||
// 在首选位置周围搜索
|
||||
for (int radius = 1; radius <= Props.maxPositionAdjustRadius; radius++)
|
||||
{
|
||||
foreach (var cell in GenRadial.RadialCellsAround(preferredPosition, radius, true))
|
||||
{
|
||||
if (cell.InBounds(map) && CanTeleportTo(cell, map) && IsPositionInNetworkRange(cell))
|
||||
{
|
||||
return cell;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 在整个网络范围内搜索安全位置
|
||||
foreach (var teleporter in GetNetworkTeleporters())
|
||||
{
|
||||
if (teleporter.parent?.Spawned != true) continue;
|
||||
|
||||
var teleporterPos = teleporter.parent.Position;
|
||||
var searchRadius = teleporter.Props.teleportRadius;
|
||||
|
||||
// 在传送器周围搜索
|
||||
for (int radius = 0; radius <= searchRadius; radius++)
|
||||
{
|
||||
foreach (var cell in GenRadial.RadialCellsAround(teleporterPos, radius, true))
|
||||
{
|
||||
if (cell.InBounds(map) && CanTeleportTo(cell, map))
|
||||
{
|
||||
return cell;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return IntVec3.Invalid;
|
||||
}
|
||||
|
||||
public override void CompTick()
|
||||
{
|
||||
base.CompTick();
|
||||
|
||||
if (parent == null || !parent.Spawned || parent.Map == null)
|
||||
return;
|
||||
|
||||
// 使用间隔检查优化性能
|
||||
if (Find.TickManager.TicksGame % Props.checkIntervalTicks != 0)
|
||||
return;
|
||||
|
||||
UpdatePawnsInRange();
|
||||
ProcessPawnMovements();
|
||||
}
|
||||
|
||||
private void UpdatePawnsInRange()
|
||||
{
|
||||
var newPawnsInRange = new HashSet<Pawn>();
|
||||
|
||||
// 获取范围内的所有pawn
|
||||
foreach (var thing in parent.Map.listerThings.ThingsInGroup(ThingRequestGroup.Pawn))
|
||||
{
|
||||
if (thing is Pawn pawn &&
|
||||
pawn.Position.DistanceTo(parent.Position) <= Props.teleportRadius &&
|
||||
pawn.Spawned && !pawn.Dead && !pawn.Downed)
|
||||
{
|
||||
newPawnsInRange.Add(pawn);
|
||||
}
|
||||
}
|
||||
|
||||
// 处理新进入范围的pawn
|
||||
foreach (var pawn in newPawnsInRange)
|
||||
{
|
||||
if (!pawnsInRange.Contains(pawn) && ShouldAffectPawn(pawn))
|
||||
{
|
||||
OnPawnEnterRange(pawn);
|
||||
}
|
||||
}
|
||||
|
||||
// 处理离开范围的pawn
|
||||
var pawnsToRemove = new List<Pawn>();
|
||||
foreach (var pawn in pawnsInRange)
|
||||
{
|
||||
if (!newPawnsInRange.Contains(pawn))
|
||||
{
|
||||
pawnsToRemove.Add(pawn);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var pawn in pawnsToRemove)
|
||||
{
|
||||
OnPawnLeaveRange(pawn);
|
||||
}
|
||||
|
||||
pawnsInRange = newPawnsInRange;
|
||||
}
|
||||
|
||||
private void ProcessPawnMovements()
|
||||
{
|
||||
foreach (var pawn in pawnsInRange)
|
||||
{
|
||||
if (!ShouldAffectPawn(pawn))
|
||||
continue;
|
||||
|
||||
if (IsPawnMoving(pawn))
|
||||
{
|
||||
TryTeleportPawn(pawn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查pawn是否应该受到传送效果影响
|
||||
/// </summary>
|
||||
private bool ShouldAffectPawn(Pawn pawn)
|
||||
{
|
||||
if (pawn == null || pawn.Dead || pawn.Destroyed)
|
||||
return false;
|
||||
|
||||
// 种族类型检查 - 只允许人类和机械体
|
||||
if (!pawn.RaceProps.Humanlike && !pawn.RaceProps.IsMechanoid)
|
||||
return false;
|
||||
|
||||
// 特定种族检查
|
||||
if (Props.allowedRaces != null && Props.allowedRaces.Count > 0)
|
||||
{
|
||||
if (!Props.allowedRaces.Contains(pawn.def))
|
||||
return false;
|
||||
}
|
||||
|
||||
// 排除种族检查
|
||||
if (Props.excludedRaces != null && Props.excludedRaces.Count > 0)
|
||||
{
|
||||
if (Props.excludedRaces.Contains(pawn.def))
|
||||
return false;
|
||||
}
|
||||
|
||||
// 派系关系检查 - 简化版,只检查是否同派系
|
||||
if (Props.onlyPawnsInSameFaction && parent.Faction != null && pawn.Faction != null)
|
||||
{
|
||||
if (parent.Faction != pawn.Faction)
|
||||
return false;
|
||||
}
|
||||
|
||||
// 囚犯和奴隶检查
|
||||
if (!Props.affectPrisoners && pawn.IsPrisoner)
|
||||
return false;
|
||||
if (!Props.affectSlaves && pawn.IsSlave)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查Pawn是否正在移动
|
||||
/// </summary>
|
||||
private bool IsPawnMoving(Pawn pawn)
|
||||
{
|
||||
if (pawn == null || pawn.jobs == null || pawn.jobs.curJob == null)
|
||||
return false;
|
||||
|
||||
// 检查工作是否在排除表中
|
||||
if (IsJobExcluded(pawn.jobs.curJob.def))
|
||||
return false;
|
||||
|
||||
// 检查是否正在执行移动任务
|
||||
if (pawn.jobs.curJob.def == JobDefOf.Goto ||
|
||||
pawn.jobs.curJob.def == JobDefOf.GotoWander ||
|
||||
pawn.jobs.curJob.def == JobDefOf.Follow)
|
||||
{
|
||||
return pawn.pather.Moving;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查工作是否在排除表中
|
||||
/// </summary>
|
||||
private bool IsJobExcluded(JobDef jobDef)
|
||||
{
|
||||
return ExcludedJobs.Contains(jobDef);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 尝试传送Pawn
|
||||
/// </summary>
|
||||
private void TryTeleportPawn(Pawn pawn)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (pawn == null || pawn.Map == null || pawn.Destroyed)
|
||||
return;
|
||||
|
||||
// 检查当前工作是否在排除表中
|
||||
if (pawn.jobs?.curJob != null && IsJobExcluded(pawn.jobs.curJob.def))
|
||||
return;
|
||||
|
||||
// 获取Pawn的目标位置
|
||||
LocalTargetInfo target = GetPawnMoveTarget(pawn);
|
||||
if (!target.IsValid)
|
||||
return;
|
||||
|
||||
// 检查目标位置是否在传送网络范围内
|
||||
if (!IsPositionInNetworkRange(target.Cell))
|
||||
return;
|
||||
|
||||
// 在网络范围内寻找安全的传送位置
|
||||
IntVec3 safeTarget = FindSafePositionInNetwork(target.Cell, pawn);
|
||||
if (!safeTarget.IsValid)
|
||||
return;
|
||||
|
||||
// 执行传送
|
||||
PerformTeleport(pawn, safeTarget);
|
||||
|
||||
// 记录日志
|
||||
Log.Message($"[AreaTeleporter] 传送 {pawn.LabelShort} 从 {pawn.Position} 到 {safeTarget} (网络传送)");
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Log.Warning($"传送Pawn时出错: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取Pawn的移动目标
|
||||
/// </summary>
|
||||
private LocalTargetInfo GetPawnMoveTarget(Pawn pawn)
|
||||
{
|
||||
if (pawn.jobs?.curJob == null)
|
||||
return LocalTargetInfo.Invalid;
|
||||
|
||||
// 检查工作是否在排除表中
|
||||
if (IsJobExcluded(pawn.jobs.curJob.def))
|
||||
return LocalTargetInfo.Invalid;
|
||||
|
||||
// 尝试从当前工作中获取目标位置
|
||||
var job = pawn.jobs.curJob;
|
||||
|
||||
// 对于Goto任务,目标通常是targetA
|
||||
if (job.targetA.IsValid)
|
||||
return job.targetA;
|
||||
|
||||
// 对于其他移动任务,可能需要不同的逻辑
|
||||
if (job.def == JobDefOf.Follow && job.targetB.IsValid)
|
||||
return job.targetB;
|
||||
|
||||
return LocalTargetInfo.Invalid;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查是否可以传送到指定位置
|
||||
/// </summary>
|
||||
private bool CanTeleportTo(IntVec3 cell, Map map)
|
||||
{
|
||||
if (!cell.InBounds(map))
|
||||
return false;
|
||||
|
||||
// 检查是否可站立
|
||||
if (!cell.Standable(map))
|
||||
return false;
|
||||
|
||||
// 检查是否有建筑阻挡
|
||||
Building edifice = cell.GetEdifice(map);
|
||||
if (edifice != null && edifice.def.surfaceType != SurfaceType.Item &&
|
||||
edifice.def.surfaceType != SurfaceType.Eat && !(edifice is Building_Door { Open: not false }))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查是否有物品阻挡
|
||||
List<Thing> thingList = cell.GetThingList(map);
|
||||
for (int i = 0; i < thingList.Count; i++)
|
||||
{
|
||||
if (thingList[i].def.category == ThingCategory.Item)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 执行传送
|
||||
/// </summary>
|
||||
private void PerformTeleport(Pawn pawn, IntVec3 targetCell)
|
||||
{
|
||||
Map map = pawn.Map;
|
||||
|
||||
// 创建入口特效
|
||||
if (Props.entryEffecter != null)
|
||||
{
|
||||
Effecter entryEffect = Props.entryEffecter.Spawn();
|
||||
entryEffect.Trigger(new TargetInfo(pawn.Position, map), new TargetInfo(pawn.Position, map));
|
||||
entryEffect.Cleanup();
|
||||
}
|
||||
|
||||
// 创建出口特效
|
||||
if (Props.exitEffecter != null)
|
||||
{
|
||||
Effecter exitEffect = Props.exitEffecter.Spawn();
|
||||
exitEffect.Trigger(new TargetInfo(targetCell, map), new TargetInfo(targetCell, map));
|
||||
exitEffect.Cleanup();
|
||||
}
|
||||
|
||||
// 播放音效
|
||||
if (Props.teleportSound != null)
|
||||
{
|
||||
Props.teleportSound.PlayOneShot(new TargetInfo(targetCell, map));
|
||||
}
|
||||
|
||||
// 执行传送
|
||||
pawn.Position = targetCell;
|
||||
pawn.Notify_Teleported();
|
||||
pawn.jobs.StopAll();
|
||||
|
||||
// 如果是玩家阵营,解除战争迷雾
|
||||
if ((pawn.Faction == Faction.OfPlayer || pawn.IsPlayerControlled) && pawn.Position.Fogged(map))
|
||||
{
|
||||
FloodFillerFog.FloodUnfog(pawn.Position, map);
|
||||
}
|
||||
|
||||
// 传送后眩晕
|
||||
if (Props.stunTicks > 0)
|
||||
{
|
||||
pawn.stances.stunner.StunFor(Props.stunTicks, pawn, addBattleLog: false, showMote: false);
|
||||
}
|
||||
|
||||
// 播放到达时的喧嚣效果
|
||||
if (Props.destClamorType != null)
|
||||
{
|
||||
GenClamor.DoClamor(pawn, targetCell, Props.destClamorRadius, Props.destClamorType);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPawnEnterRange(Pawn pawn)
|
||||
{
|
||||
// Pawn进入范围时的处理
|
||||
if (Props.enterRangeEffecter != null)
|
||||
{
|
||||
Effecter effect = Props.enterRangeEffecter.Spawn();
|
||||
effect.Trigger(new TargetInfo(pawn.Position, pawn.Map), new TargetInfo(pawn.Position, pawn.Map));
|
||||
effect.Cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPawnLeaveRange(Pawn pawn)
|
||||
{
|
||||
// Pawn离开范围时的处理
|
||||
if (Props.leaveRangeEffecter != null)
|
||||
{
|
||||
Effecter effect = Props.leaveRangeEffecter.Spawn();
|
||||
effect.Trigger(new TargetInfo(pawn.Position, pawn.Map), new TargetInfo(pawn.Position, pawn.Map));
|
||||
effect.Cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清理所有效果
|
||||
/// </summary>
|
||||
private void CleanupAllEffects()
|
||||
{
|
||||
pawnsInRange.Clear();
|
||||
|
||||
foreach (var effecter in effecters.Values)
|
||||
{
|
||||
effecter.Cleanup();
|
||||
}
|
||||
effecters.Clear();
|
||||
}
|
||||
|
||||
// 调试方法:显示传送范围
|
||||
public override void PostDraw()
|
||||
{
|
||||
base.PostDraw();
|
||||
|
||||
if (Find.Selector.IsSelected(parent))
|
||||
{
|
||||
try
|
||||
{
|
||||
// 绘制当前传送器范围
|
||||
GenDraw.DrawRadiusRing(parent.Position, Props.teleportRadius, Color.blue);
|
||||
|
||||
// 绘制网络范围(所有传送器的范围)
|
||||
foreach (var teleporter in GetNetworkTeleporters())
|
||||
{
|
||||
if (teleporter != this && teleporter.parent.Spawned)
|
||||
{
|
||||
GenDraw.DrawRadiusRing(teleporter.parent.Position, teleporter.Props.teleportRadius, new Color(0, 0, 1, 0.3f));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Log.Warning($"绘制传送范围环时出错: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 获取当前范围内的pawn数量(用于显示)
|
||||
public int GetPawnsInRangeCount()
|
||||
{
|
||||
return pawnsInRange.Count;
|
||||
}
|
||||
|
||||
// 获取范围内的pawn列表(用于调试)
|
||||
public IEnumerable<Pawn> GetPawnsInRange()
|
||||
{
|
||||
return pawnsInRange;
|
||||
}
|
||||
|
||||
// 获取网络中的传送器数量
|
||||
public int GetNetworkTeleporterCount()
|
||||
{
|
||||
return GetNetworkTeleporters().Count;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -197,13 +197,14 @@ namespace WulaFallenEmpire
|
||||
Hediff newHediff = HediffMaker.MakeHediff(Props.hediff, pawn);
|
||||
newHediff.Severity = Props.initialSeverity;
|
||||
|
||||
// 设置持续时间(如果有)
|
||||
// 正确设置持续时间
|
||||
if (Props.hediffDurationTicks > 0)
|
||||
{
|
||||
var comp = newHediff.TryGetComp<HediffComp_Disappears>();
|
||||
if (comp != null)
|
||||
var disappearComp = newHediff.TryGetComp<HediffComp_Disappears>();
|
||||
if (disappearComp != null)
|
||||
{
|
||||
comp.ticksToDisappear = Props.hediffDurationTicks;
|
||||
// 使用 SetDuration 方法正确设置持续时间
|
||||
disappearComp.SetDuration(Props.hediffDurationTicks);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -250,11 +251,11 @@ namespace WulaFallenEmpire
|
||||
{
|
||||
if (Props.hediffDurationTicks > 0)
|
||||
{
|
||||
var comp = hediff.TryGetComp<HediffComp_Disappears>();
|
||||
if (comp != null)
|
||||
var disappearComp = hediff.TryGetComp<HediffComp_Disappears>();
|
||||
if (disappearComp != null)
|
||||
{
|
||||
// 重置持续时间,让效果持续
|
||||
comp.ticksToDisappear = Props.hediffDurationTicks;
|
||||
// 使用 SetDuration 方法重置持续时间,让效果持续
|
||||
disappearComp.SetDuration(Props.hediffDurationTicks);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -259,6 +259,9 @@
|
||||
<Compile Include="ThingComp\WULA_AreaShield\Gizmo_AreaShieldStatus.cs" />
|
||||
<Compile Include="ThingComp\WULA_AreaShield\Harmony_AreaShieldInterceptor.cs" />
|
||||
<Compile Include="ThingComp\WULA_AreaShield\ThingComp_AreaShield.cs" />
|
||||
<Compile Include="ThingComp\WULA_AreaTeleporter\CompProperties_AreaTeleporter.cs" />
|
||||
<Compile Include="ThingComp\WULA_AreaTeleporter\Patch_Pawn_JobTracker_StartJob.cs" />
|
||||
<Compile Include="ThingComp\WULA_AreaTeleporter\ThingComp_AreaTeleporter.cs" />
|
||||
<Compile Include="ThingComp\WULA_CustomUniqueWeapon\CompCustomUniqueWeapon.cs" />
|
||||
<Compile Include="ThingComp\WULA_CustomUniqueWeapon\CompProperties_CustomUniqueWeapon.cs" />
|
||||
<Compile Include="ThingComp\WULA_GiveHediffsInRange\CompGiveHediffsInRange.cs" />
|
||||
|
||||
Reference in New Issue
Block a user