1
This commit is contained in:
Binary file not shown.
@@ -69,6 +69,18 @@
|
||||
<suspendable>false</suspendable>
|
||||
</JobDef>
|
||||
|
||||
<JobDef>
|
||||
<defName>WULA_TransformPawn</defName>
|
||||
<driverClass>WulaFallenEmpire.JobDriver_TransformPawn</driverClass>
|
||||
<reportString>变更装备中。</reportString>
|
||||
<abilityCasting>true</abilityCasting>
|
||||
<alwaysShowWeapon>true</alwaysShowWeapon>
|
||||
<playerInterruptible>true</playerInterruptible>
|
||||
<casualInterruptible>false</casualInterruptible>
|
||||
<checkOverrideOnDamage>Always</checkOverrideOnDamage>
|
||||
<suspendable>false</suspendable>
|
||||
</JobDef>
|
||||
|
||||
|
||||
<JobDef>
|
||||
<defName>WULA_EnterMech</defName>
|
||||
|
||||
@@ -265,7 +265,7 @@
|
||||
<ThingDef ParentName="BuildingBase">
|
||||
<defName>WULA_Cat_Bunker_Cleanzone</defName>
|
||||
<label>乌拉猫猫地堡</label>
|
||||
<description>清理出一块场地并准备好资源,使得乌拉帝国可以向此处投放建筑。\n\n乌拉猫猫地堡是集生产和防御为一体的坚实建筑,3只乌拉猫猫自律机械体会和地堡一起空降。地堡可供乌拉猫猫更换工作类型,并允许乌拉猫猫进驻使用内部武器击败来犯敌军。</description>
|
||||
<description>清理出一块场地并准备好资源,使得乌拉帝国可以向此处投放建筑。\n\n乌拉猫猫地堡是集生产和防御为一体的坚实建筑,3只乌拉猫猫自律机械体会和地堡一起空降。地堡可供乌拉猫猫更换工作类型,并拥有内部武器用于击败来犯敌军。</description>
|
||||
<uiIconPath>Wula/Building/WULA_Cat_Bunker_south</uiIconPath>
|
||||
<minifiedDef>MinifiedThing</minifiedDef>
|
||||
<tickerType>Normal</tickerType>
|
||||
@@ -385,9 +385,9 @@
|
||||
<ThingDef ParentName="BuildingBase">
|
||||
<defName>WULA_Cat_Bunker</defName>
|
||||
<label>乌拉猫猫地堡</label>
|
||||
<description>这是一个从乌拉帝国母舰上空投下来的地堡,它拥有一些预制件,可以供乌拉猫猫更换其工作类型。此外,当敌人袭击时,可将乌拉猫猫召回至地堡内,它们将在地堡里对外射击以击退来犯者。</description>
|
||||
<thingClass>WulaFallenEmpire.Building_MechanoidRecycler</thingClass>
|
||||
<description>这是一个从乌拉帝国母舰上空投下来的地堡,它拥有一些预制件,可以供乌拉猫猫更换其工作类型。此外,当敌人袭击时,地堡的自动机枪会对外射击以击退来犯者。</description>
|
||||
<tickerType>Normal</tickerType>
|
||||
<thingClass>Building_TurretGun</thingClass>
|
||||
<descriptionHyperlinks>
|
||||
<ThingDef>WULA_Cat_Bunker_TurretGun</ThingDef>
|
||||
<ThingDef>Mech_WULA_Cat</ThingDef>
|
||||
@@ -407,10 +407,8 @@
|
||||
</shadowData>
|
||||
</graphicData>
|
||||
<altitudeLayer>Building</altitudeLayer>
|
||||
<passability>Impassable</passability>
|
||||
<blockWind>true</blockWind>
|
||||
<fillPercent>1</fillPercent>
|
||||
<blockLight>false</blockLight>
|
||||
<passability>PassThroughOnly</passability>
|
||||
<fillPercent>0.9</fillPercent>
|
||||
<castEdgeShadows>false</castEdgeShadows>
|
||||
<canOverlapZones>false</canOverlapZones>
|
||||
<hasInteractionCell>false</hasInteractionCell>
|
||||
@@ -444,101 +442,28 @@
|
||||
<usePlayerFactionIfNull>true</usePlayerFactionIfNull>
|
||||
<overrideExistingFaction>false</overrideExistingFaction>
|
||||
</li>
|
||||
<li Class="WulaFallenEmpire.CompProperties_MechanoidRecycler">
|
||||
<maxStorageCapacity>6</maxStorageCapacity>
|
||||
|
||||
<!-- 可回收的机械族种族 -->
|
||||
<recyclableRaces>
|
||||
<li>Mech_WULA_Cat</li>
|
||||
<li>Mech_WULA_Cat_Constructor</li>
|
||||
<li>Mech_WULA_Cat_Assault</li>
|
||||
</recyclableRaces>
|
||||
<recycleJobDef>WULA_RecycleMechanoid</recycleJobDef>
|
||||
<recycleRange>5</recycleRange>
|
||||
|
||||
<!-- 可生成的机械族种类 -->
|
||||
<spawnablePawnKinds>
|
||||
<li>Mech_WULA_Cat</li>
|
||||
<li>Mech_WULA_Cat_Constructor</li>
|
||||
<li>Mech_WULA_Cat_Assault</li>
|
||||
</spawnablePawnKinds>
|
||||
|
||||
<!-- 新增初始单位配置 -->
|
||||
<initialUnits>
|
||||
<li>
|
||||
<pawnKindDef>Mech_WULA_Cat</pawnKindDef>
|
||||
<count>1</count>
|
||||
</li>
|
||||
<li>
|
||||
<pawnKindDef>Mech_WULA_Cat_Constructor</pawnKindDef>
|
||||
<count>1</count>
|
||||
</li>
|
||||
<li>
|
||||
<pawnKindDef>Mech_WULA_Cat_Assault</pawnKindDef>
|
||||
<count>1</count>
|
||||
</li>
|
||||
</initialUnits>
|
||||
|
||||
<!-- <ownershipFaction>Player</ownershipFaction> -->
|
||||
<li Class="WulaFallenEmpire.CompProperties_BuildToPawn">
|
||||
<pawnKindDef>Mech_WULA_Cat_Assault</pawnKindDef>
|
||||
<spawnCount>3</spawnCount>
|
||||
<inheritFaction>true</inheritFaction>
|
||||
<destroyBuilding>false</destroyBuilding>
|
||||
<initDrafted>true</initDrafted>
|
||||
</li>
|
||||
<li Class="WulaFallenEmpire.CompProperties_Gather">
|
||||
<gatherRange>500</gatherRange>
|
||||
<!-- <gatherSound></gatherSound> -->
|
||||
<cooldownTicks>60</cooldownTicks>
|
||||
</li>
|
||||
|
||||
<li Class="WulaFallenEmpire.CompProperties_PathCostUpdater">
|
||||
<adaptiveExpansion>true</adaptiveExpansion>
|
||||
</li>
|
||||
|
||||
<li Class="WulaFallenEmpire.CompProperties_StorageMultiTurretGun">
|
||||
<ID>1</ID>
|
||||
<turretDef>WULA_Cat_Bunker_TurretGun</turretDef>
|
||||
<angleOffset>0</angleOffset>
|
||||
<autoAttack>true</autoAttack>
|
||||
<requiredMechanoids>1</requiredMechanoids>
|
||||
<autoActivate>true</autoActivate>
|
||||
</li>
|
||||
<li Class="WulaFallenEmpire.CompProperties_StorageMultiTurretGun">
|
||||
<ID>2</ID>
|
||||
<turretDef>WULA_Cat_Bunker_TurretGun</turretDef>
|
||||
<angleOffset>0</angleOffset>
|
||||
<autoAttack>true</autoAttack>
|
||||
<requiredMechanoids>2</requiredMechanoids>
|
||||
<autoActivate>true</autoActivate>
|
||||
</li>
|
||||
<li Class="WulaFallenEmpire.CompProperties_StorageMultiTurretGun">
|
||||
<ID>3</ID>
|
||||
<turretDef>WULA_Cat_Bunker_TurretGun</turretDef>
|
||||
<angleOffset>0</angleOffset>
|
||||
<autoAttack>true</autoAttack>
|
||||
<requiredMechanoids>3</requiredMechanoids>
|
||||
<autoActivate>true</autoActivate>
|
||||
</li>
|
||||
<li Class="WulaFallenEmpire.CompProperties_StorageMultiTurretGun">
|
||||
<ID>4</ID>
|
||||
<turretDef>WULA_Cat_Bunker_TurretGun</turretDef>
|
||||
<angleOffset>0</angleOffset>
|
||||
<autoAttack>true</autoAttack>
|
||||
<requiredMechanoids>4</requiredMechanoids>
|
||||
<autoActivate>true</autoActivate>
|
||||
</li>
|
||||
<li Class="WulaFallenEmpire.CompProperties_StorageMultiTurretGun">
|
||||
<ID>5</ID>
|
||||
<turretDef>WULA_Cat_Bunker_TurretGun</turretDef>
|
||||
<angleOffset>0</angleOffset>
|
||||
<autoAttack>true</autoAttack>
|
||||
<requiredMechanoids>5</requiredMechanoids>
|
||||
<autoActivate>true</autoActivate>
|
||||
</li>
|
||||
<li Class="WulaFallenEmpire.CompProperties_StorageMultiTurretGun">
|
||||
<ID>6</ID>
|
||||
<turretDef>WULA_Cat_Bunker_TurretGun</turretDef>
|
||||
<angleOffset>0</angleOffset>
|
||||
<autoAttack>true</autoAttack>
|
||||
<requiredMechanoids>6</requiredMechanoids>
|
||||
<autoActivate>true</autoActivate>
|
||||
</li>
|
||||
</comps>
|
||||
</ThingDef>
|
||||
<ThingDef ParentName="BaseWeaponTurret">
|
||||
<defName>WULA_Cat_Bunker_TurretGun</defName>
|
||||
<label>地堡炮塔</label>
|
||||
<description>由进入地堡的乌拉猫猫操纵的炮塔——说那么多干什么,扣扳机就完了,殖民地会报销弹药的。</description>
|
||||
<description>由驻守地堡的乌拉猫猫操纵的炮塔——说那么多干什么,扣扳机就完了,殖民地会报销弹药的。</description>
|
||||
<graphicData>
|
||||
<texPath>Wula/Weapon/WULA_Weapon_Empty</texPath>
|
||||
<graphicClass>Graphic_Single</graphicClass>
|
||||
@@ -558,7 +483,7 @@
|
||||
<defaultProjectile>Bullet_WULA_RW_Base_AR</defaultProjectile>
|
||||
<range>28</range>
|
||||
<ticksBetweenBurstShots>5</ticksBetweenBurstShots>
|
||||
<burstShotCount>12</burstShotCount>
|
||||
<burstShotCount>24</burstShotCount>
|
||||
<soundCast>Shot_AssaultRifle</soundCast>
|
||||
<soundCastTail>GunTail_Medium</soundCastTail>
|
||||
<muzzleFlashScale>9</muzzleFlashScale>
|
||||
|
||||
@@ -951,6 +951,16 @@
|
||||
<li>Firefighter</li>
|
||||
</mechEnabledWorkTypes>
|
||||
</race>
|
||||
<comps>
|
||||
<li Class="WulaFallenEmpire.CompProperties_AutonomousCat">
|
||||
<autoDraftOnGather>true</autoDraftOnGather>
|
||||
<transformablePawnKinds>
|
||||
<li>Mech_WULA_Cat</li>
|
||||
<li>Mech_WULA_Cat_Constructor</li>
|
||||
<li>Mech_WULA_Cat_Assault</li>
|
||||
</transformablePawnKinds>
|
||||
</li>
|
||||
</comps>
|
||||
</AlienRace.ThingDef_AlienRace>
|
||||
<AlienRace.ThingDef_AlienRace ParentName="Mech_WULA_Cat_Base">
|
||||
<defName>Mech_WULA_Cat_Constructor</defName>
|
||||
@@ -975,6 +985,16 @@
|
||||
<statBases>
|
||||
<WorkSpeedGlobal>2</WorkSpeedGlobal>
|
||||
</statBases>
|
||||
<comps>
|
||||
<li Class="WulaFallenEmpire.CompProperties_AutonomousCat">
|
||||
<autoDraftOnGather>true</autoDraftOnGather>
|
||||
<transformablePawnKinds>
|
||||
<li>Mech_WULA_Cat</li>
|
||||
<li>Mech_WULA_Cat_Constructor</li>
|
||||
<li>Mech_WULA_Cat_Assault</li>
|
||||
</transformablePawnKinds>
|
||||
</li>
|
||||
</comps>
|
||||
</AlienRace.ThingDef_AlienRace>
|
||||
<AlienRace.ThingDef_AlienRace ParentName="Mech_WULA_Cat_Base">
|
||||
<defName>Mech_WULA_Cat_Assault</defName>
|
||||
@@ -1003,6 +1023,16 @@
|
||||
<!-- <WorkSpeedGlobal>2</WorkSpeedGlobal> -->
|
||||
<MoveSpeed>4</MoveSpeed>
|
||||
</statBases>
|
||||
<comps>
|
||||
<li Class="WulaFallenEmpire.CompProperties_AutonomousCat">
|
||||
<autoDraftOnGather>true</autoDraftOnGather>
|
||||
<transformablePawnKinds>
|
||||
<li>Mech_WULA_Cat</li>
|
||||
<li>Mech_WULA_Cat_Constructor</li>
|
||||
<li>Mech_WULA_Cat_Assault</li>
|
||||
</transformablePawnKinds>
|
||||
</li>
|
||||
</comps>
|
||||
</AlienRace.ThingDef_AlienRace>
|
||||
<AlienRace.ThingDef_AlienRace ParentName="Mech_WULA_Cat_Base">
|
||||
<defName>Mech_WULA_Cat_Cloak_Sniper</defName>
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
// CompBuildToPawn_SimpleDelay.cs
|
||||
using RimWorld;
|
||||
using System.Collections.Generic;
|
||||
using Verse;
|
||||
|
||||
namespace WulaFallenEmpire
|
||||
{
|
||||
public class CompBuildToPawn : ThingComp
|
||||
{
|
||||
public CompProperties_BuildToPawn Props => (CompProperties_BuildToPawn)props;
|
||||
|
||||
private bool shouldSpawn = false;
|
||||
private int delayCounter = 0;
|
||||
|
||||
public override void PostSpawnSetup(bool respawningAfterLoad)
|
||||
{
|
||||
base.PostSpawnSetup(respawningAfterLoad);
|
||||
|
||||
// 跳过存档加载和蓝图/框架
|
||||
if (respawningAfterLoad || parent.def.IsBlueprint || parent.def.IsFrame)
|
||||
return;
|
||||
|
||||
// 延迟一帧
|
||||
shouldSpawn = true;
|
||||
delayCounter = 0;
|
||||
}
|
||||
|
||||
public override void CompTick()
|
||||
{
|
||||
base.CompTick();
|
||||
|
||||
if (shouldSpawn && delayCounter >= 1) // 延迟一帧后执行
|
||||
{
|
||||
if (Props.pawnKindDef != null && parent != null && !parent.Destroyed && parent.Map != null)
|
||||
{
|
||||
// 生成Pawn
|
||||
for (int i = 0; i < Props.spawnCount; i++)
|
||||
{
|
||||
Pawn pawn = PawnGenerator.GeneratePawn(Props.pawnKindDef);
|
||||
if (Props.inheritFaction)
|
||||
pawn.SetFaction(parent.Faction, null);
|
||||
|
||||
GenSpawn.Spawn(pawn, parent.Position, parent.Map, WipeMode.Vanish);
|
||||
|
||||
if (Props.initDrafted && pawn.drafter!=null)
|
||||
pawn.drafter.Drafted = true;
|
||||
}
|
||||
|
||||
if (Props.destroyBuilding)
|
||||
// 摧毁建筑
|
||||
parent.Destroy();
|
||||
}
|
||||
|
||||
shouldSpawn = false;
|
||||
}
|
||||
else if (shouldSpawn)
|
||||
{
|
||||
delayCounter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
// CompProperties_BuildToPawn.cs
|
||||
using RimWorld;
|
||||
using Verse;
|
||||
|
||||
namespace WulaFallenEmpire
|
||||
{
|
||||
public class CompProperties_BuildToPawn : CompProperties
|
||||
{
|
||||
public PawnKindDef pawnKindDef; // 要生成的Pawn种类
|
||||
public int spawnCount = 1; // 生成数量,默认为1
|
||||
public bool inheritFaction = true; // 是否继承建筑的派系
|
||||
public bool destroyBuilding = false; // 是否销毁建筑
|
||||
public bool initDrafted = false; // 是否生成时直接设为征召
|
||||
|
||||
public CompProperties_BuildToPawn()
|
||||
{
|
||||
this.compClass = typeof(CompBuildToPawn);
|
||||
}
|
||||
}
|
||||
}
|
||||
400
Source/WulaFallenEmpire/BuildingComp/WULA_Gather/CompGather.cs
Normal file
400
Source/WulaFallenEmpire/BuildingComp/WULA_Gather/CompGather.cs
Normal file
@@ -0,0 +1,400 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Verse;
|
||||
using Verse.AI;
|
||||
using RimWorld;
|
||||
using UnityEngine;
|
||||
|
||||
namespace WulaFallenEmpire
|
||||
{
|
||||
// 召集组件属性
|
||||
public class CompProperties_Gather : CompProperties
|
||||
{
|
||||
public float gatherRange = 100f; // 召集范围(单元格)
|
||||
public SoundDef gatherSound; // 召集音效
|
||||
public int cooldownTicks = 1200; // 召集冷却时间(tick,默认20秒)
|
||||
|
||||
// 转化相关
|
||||
public bool canTransformPawns = true; // 是否允许转化Pawn
|
||||
public IntVec3 spawnOffset = IntVec3.Zero; // 新Pawn生成位置偏移
|
||||
|
||||
public CompProperties_Gather()
|
||||
{
|
||||
compClass = typeof(Comp_Gather);
|
||||
}
|
||||
}
|
||||
|
||||
// 召集组件实现
|
||||
public class Comp_Gather : ThingComp
|
||||
{
|
||||
private int lastGatherTick = -1000; // 上一次召集的tick
|
||||
private bool gatheringActive = false; // 召集是否正在进行
|
||||
private int gatherDurationLeft = 0; // 召集持续时间剩余
|
||||
|
||||
// Gizmo缓存
|
||||
private Command_Action cachedGizmo;
|
||||
|
||||
// 属性
|
||||
public CompProperties_Gather Props => (CompProperties_Gather)props;
|
||||
|
||||
public bool CanGatherNow
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!parent.Spawned || parent.Destroyed)
|
||||
return false;
|
||||
|
||||
// 检查冷却时间
|
||||
int currentTick = Find.TickManager.TicksGame;
|
||||
if (currentTick - lastGatherTick < Props.cooldownTicks)
|
||||
return false;
|
||||
|
||||
// 检查建筑是否可用
|
||||
if (parent is Building building)
|
||||
{
|
||||
if (building.IsBrokenDown() || building.IsForbidden(Faction.OfPlayer))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsGatheringActive => gatheringActive;
|
||||
|
||||
// 公开方法:检查是否可以进行转化
|
||||
public bool CanTransformPawn(Pawn pawn)
|
||||
{
|
||||
if (!Props.canTransformPawns)
|
||||
return false;
|
||||
|
||||
if (!parent.Spawned || parent.Destroyed)
|
||||
return false;
|
||||
|
||||
// 检查Pawn是否拥有AutonomousCat组件
|
||||
if (pawn.TryGetComp<Comp_AutonomousCat>() == null)
|
||||
return false;
|
||||
|
||||
// 检查建筑是否可用
|
||||
if (parent is Building building)
|
||||
{
|
||||
if (building.IsBrokenDown() || building.IsForbidden(Faction.OfPlayer))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// 获取生成位置
|
||||
public IntVec3 GetSpawnPosition()
|
||||
{
|
||||
if (parent.Spawned)
|
||||
{
|
||||
return parent.Position + Props.spawnOffset;
|
||||
}
|
||||
return parent.Position;
|
||||
}
|
||||
|
||||
// 公开方法:执行转化
|
||||
public void TransformPawn(Pawn originalPawn, PawnKindDef targetPawnKind)
|
||||
{
|
||||
if (!CanTransformPawn(originalPawn))
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
// 记录原始信息
|
||||
Map map = originalPawn.Map;
|
||||
IntVec3 position = GetSpawnPosition();
|
||||
Faction faction = originalPawn.Faction;
|
||||
|
||||
// 检查位置是否可用
|
||||
if (!position.Walkable(map) || position.Fogged(map))
|
||||
{
|
||||
// 尝试在周围寻找可用位置
|
||||
if (!CellFinder.TryFindRandomCellNear(position, map, 3,
|
||||
(c) => c.Walkable(map) && !c.Fogged(map), out position))
|
||||
{
|
||||
Messages.Message("Wula_NoSpawnSpace".Translate(), MessageTypeDefOf.RejectInput);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 创建新的Pawn
|
||||
Pawn newPawn = PawnGenerator.GeneratePawn(targetPawnKind, faction);
|
||||
|
||||
// 复制一些重要信息
|
||||
if (originalPawn.Name != null)
|
||||
{
|
||||
newPawn.Name = originalPawn.Name;
|
||||
}
|
||||
newPawn.gender = originalPawn.gender;
|
||||
|
||||
// 销毁原始Pawn
|
||||
originalPawn.Destroy(DestroyMode.Vanish);
|
||||
|
||||
// 生成新的Pawn
|
||||
GenSpawn.Spawn(newPawn, position, map);
|
||||
|
||||
// 为新Pawn添加AutonomousCat组件(如果还没有)
|
||||
EnsureAutonomousCatComponent(newPawn);
|
||||
|
||||
// 显示消息
|
||||
Messages.Message(
|
||||
"Wula_TransformComplete".Translate(originalPawn.LabelShort, newPawn.LabelShort),
|
||||
MessageTypeDefOf.PositiveEvent
|
||||
);
|
||||
|
||||
// 记录日志
|
||||
if (Prefs.DevMode)
|
||||
{
|
||||
Log.Message($"[CompGather] Transformation complete: {originalPawn.LabelShort} -> {newPawn.LabelShort}");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error($"Error completing transformation: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
// 确保新Pawn有AutonomousCat组件
|
||||
private void EnsureAutonomousCatComponent(Pawn newPawn)
|
||||
{
|
||||
// 检查是否已经有AutonomousCat组件
|
||||
if (newPawn.TryGetComp<Comp_AutonomousCat>() != null)
|
||||
return;
|
||||
|
||||
// 检查Pawn的定义中是否有AutonomousCat组件
|
||||
var compProps = newPawn.def.comps?.Find(c => c.compClass == typeof(Comp_AutonomousCat)) as CompProperties_AutonomousCat;
|
||||
if (compProps == null)
|
||||
{
|
||||
// 如果没有,添加一个默认的AutonomousCat组件
|
||||
newPawn.AllComps.Add(new Comp_AutonomousCat()
|
||||
{
|
||||
parent = newPawn,
|
||||
props = new CompProperties_AutonomousCat()
|
||||
{
|
||||
autoDraftOnGather = true
|
||||
}
|
||||
});
|
||||
|
||||
if (Prefs.DevMode)
|
||||
{
|
||||
Log.Message($"[CompGather] Added AutonomousCat component to {newPawn.LabelShort}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Gizmo显示
|
||||
public override IEnumerable<Gizmo> CompGetGizmosExtra()
|
||||
{
|
||||
foreach (Gizmo gizmo in base.CompGetGizmosExtra())
|
||||
{
|
||||
yield return gizmo;
|
||||
}
|
||||
|
||||
// 只对玩家派系显示
|
||||
if (parent.Faction == Faction.OfPlayer)
|
||||
{
|
||||
if (cachedGizmo == null)
|
||||
{
|
||||
InitializeGizmo();
|
||||
}
|
||||
|
||||
yield return cachedGizmo;
|
||||
}
|
||||
}
|
||||
|
||||
private void InitializeGizmo()
|
||||
{
|
||||
cachedGizmo = new Command_Action();
|
||||
cachedGizmo.defaultLabel = "Wula_GatherCats".Translate();
|
||||
cachedGizmo.defaultDesc = "Wula_GatherCatsDesc".Translate();
|
||||
cachedGizmo.icon = ContentFinder<Texture2D>.Get("UI/Gizmos/GatherCats", false) ?? BaseContent.BadTex;
|
||||
cachedGizmo.action = StartGathering;
|
||||
|
||||
// 添加冷却时间显示
|
||||
cachedGizmo.disabledReason = GetDisabledReason();
|
||||
|
||||
// 热键
|
||||
cachedGizmo.hotKey = KeyBindingDefOf.Misc2;
|
||||
}
|
||||
|
||||
private string GetDisabledReason()
|
||||
{
|
||||
if (!parent.Spawned || parent.Destroyed)
|
||||
return "Building destroyed or not spawned";
|
||||
|
||||
int currentTick = Find.TickManager.TicksGame;
|
||||
int ticksSinceLastGather = currentTick - lastGatherTick;
|
||||
|
||||
if (ticksSinceLastGather < Props.cooldownTicks)
|
||||
{
|
||||
int remainingTicks = Props.cooldownTicks - ticksSinceLastGather;
|
||||
return "Wula_GatherCooldown".Translate(remainingTicks.ToStringTicksToPeriod());
|
||||
}
|
||||
|
||||
if (parent is Building building && building.IsBrokenDown())
|
||||
return "Wula_BuildingBroken".Translate();
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// 开始召集
|
||||
private void StartGathering()
|
||||
{
|
||||
if (!CanGatherNow)
|
||||
return;
|
||||
|
||||
// 记录召集时间
|
||||
lastGatherTick = Find.TickManager.TicksGame;
|
||||
|
||||
// 设置召集状态
|
||||
gatheringActive = true;
|
||||
gatherDurationLeft = 60; // 持续1秒
|
||||
|
||||
// 查找并命令范围内的 Autonomous Cats
|
||||
GatherAutonomousCats();
|
||||
|
||||
// 显示消息
|
||||
Messages.Message("Wula_GatheringStarted".Translate(), MessageTypeDefOf.PositiveEvent);
|
||||
|
||||
// 刷新Gizmo状态
|
||||
cachedGizmo.disabledReason = GetDisabledReason();
|
||||
}
|
||||
|
||||
// 查找并命令 Autonomous Cats
|
||||
private void GatherAutonomousCats()
|
||||
{
|
||||
if (parent.Map == null)
|
||||
return;
|
||||
|
||||
// 查找范围内的所有 Autonomous Cats
|
||||
List<Pawn> autonomousCats = new List<Pawn>();
|
||||
foreach (Pawn pawn in parent.Map.mapPawns.AllPawnsSpawned)
|
||||
{
|
||||
// 检查是否拥有 AutonomousCat 组件
|
||||
var comp = pawn.TryGetComp<Comp_AutonomousCat>();
|
||||
if (comp != null)
|
||||
{
|
||||
// 检查是否有待处理的转化,如果有则不响应召集
|
||||
if (comp.PendingTransformTarget != null)
|
||||
continue;
|
||||
|
||||
// 检查距离
|
||||
float distance = pawn.Position.DistanceTo(parent.Position);
|
||||
if (distance <= Props.gatherRange)
|
||||
{
|
||||
autonomousCats.Add(pawn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 命令每个 Autonomous Cat
|
||||
foreach (Pawn cat in autonomousCats)
|
||||
{
|
||||
CommandCatToGather(cat);
|
||||
}
|
||||
|
||||
// 报告召集数量
|
||||
if (autonomousCats.Count > 0)
|
||||
{
|
||||
Messages.Message(
|
||||
"Wula_CatsGathered".Translate(autonomousCats.Count),
|
||||
MessageTypeDefOf.NeutralEvent
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 命令单个 Autonomous Cat
|
||||
private void CommandCatToGather(Pawn cat)
|
||||
{
|
||||
if (cat == null || !cat.Spawned || cat.Dead)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
// 获取 AutonomousCat 组件
|
||||
var comp = cat.TryGetComp<Comp_AutonomousCat>();
|
||||
if (comp != null)
|
||||
{
|
||||
// 使用组件的响应方法
|
||||
comp.RespondToGather(parent);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 如果没有组件,使用默认行为
|
||||
if (cat.drafter != null)
|
||||
{
|
||||
cat.drafter.Drafted = true;
|
||||
}
|
||||
|
||||
Job job = new Job(JobDefOf.Goto, parent.Position);
|
||||
job.expiryInterval = 30000;
|
||||
job.checkOverrideOnExpire = true;
|
||||
|
||||
if (cat.CurJob != null)
|
||||
{
|
||||
cat.jobs.EndCurrentJob(JobCondition.InterruptForced);
|
||||
}
|
||||
|
||||
cat.jobs.StartJob(job, JobCondition.InterruptForced);
|
||||
}
|
||||
|
||||
// 记录日志
|
||||
if (Prefs.DevMode)
|
||||
{
|
||||
Log.Message($"[CompGather] Cat {cat.LabelShort} commanded to gather at {parent.Position}");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error($"Error commanding cat to gather: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
// 每帧更新
|
||||
public override void CompTick()
|
||||
{
|
||||
base.CompTick();
|
||||
|
||||
if (gatheringActive)
|
||||
{
|
||||
gatherDurationLeft--;
|
||||
if (gatherDurationLeft <= 0)
|
||||
{
|
||||
gatheringActive = false;
|
||||
}
|
||||
}
|
||||
|
||||
// 每30tick更新一次Gizmo状态
|
||||
if (parent.IsHashIntervalTick(30) && cachedGizmo != null)
|
||||
{
|
||||
cachedGizmo.disabledReason = GetDisabledReason();
|
||||
}
|
||||
}
|
||||
|
||||
// 保存/加载数据
|
||||
public override void PostExposeData()
|
||||
{
|
||||
base.PostExposeData();
|
||||
Scribe_Values.Look(ref lastGatherTick, "lastGatherTick", -1000);
|
||||
Scribe_Values.Look(ref gatheringActive, "gatheringActive", false);
|
||||
Scribe_Values.Look(ref gatherDurationLeft, "gatherDurationLeft", 0);
|
||||
}
|
||||
|
||||
// 绘制效果(可选)
|
||||
public override void PostDraw()
|
||||
{
|
||||
base.PostDraw();
|
||||
|
||||
// 如果正在召集,绘制一个光环效果
|
||||
if (gatheringActive)
|
||||
{
|
||||
float pulse = Mathf.Sin(Find.TickManager.TicksGame * 0.1f) * 0.5f + 0.5f;
|
||||
GenDraw.DrawRadiusRing(parent.Position, Props.gatherRange, Color.Lerp(Color.cyan, Color.white, pulse),
|
||||
(c) => (c.x + c.y + Find.TickManager.TicksGame) % 10 < 5);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,398 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Verse;
|
||||
using Verse.AI;
|
||||
using RimWorld;
|
||||
using UnityEngine;
|
||||
|
||||
namespace WulaFallenEmpire
|
||||
{
|
||||
// AutonomousCat组件属性
|
||||
public class CompProperties_AutonomousCat : CompProperties
|
||||
{
|
||||
public bool autoDraftOnGather = true; // 被召集时自动征召
|
||||
|
||||
// 转化功能
|
||||
public List<PawnKindDef> transformablePawnKinds; // 可转化的Pawn种类列表
|
||||
public float transformTime = 3f; // 转化所需时间(秒)
|
||||
public SoundDef transformSound; // 转化音效
|
||||
public EffecterDef transformEffect; // 转化特效
|
||||
|
||||
// 外观设置
|
||||
public Color gatherLineColor = new Color(0.2f, 0.8f, 0.2f, 0.8f); // 召集线颜色
|
||||
public float gatherLineWidth = 0.2f; // 召集线宽度
|
||||
|
||||
public CompProperties_AutonomousCat()
|
||||
{
|
||||
compClass = typeof(Comp_AutonomousCat);
|
||||
}
|
||||
}
|
||||
|
||||
// AutonomousCat组件实现
|
||||
public class Comp_AutonomousCat : ThingComp
|
||||
{
|
||||
// 状态跟踪
|
||||
private bool isRespondingToGather = false;
|
||||
private Thing gatherTarget = null;
|
||||
private int gatherResponseEndTick = 0;
|
||||
|
||||
// 转化目标
|
||||
private PawnKindDef pendingTransformTarget = null;
|
||||
|
||||
// Gizmo缓存
|
||||
private Command_Action cachedTransformGizmo;
|
||||
private bool gizmoInitialized = false;
|
||||
|
||||
// 属性
|
||||
public CompProperties_AutonomousCat Props => (CompProperties_AutonomousCat)props;
|
||||
|
||||
// 公开属性
|
||||
public bool IsRespondingToGather => isRespondingToGather;
|
||||
public Thing GatherTarget => gatherTarget;
|
||||
public PawnKindDef PendingTransformTarget => pendingTransformTarget;
|
||||
|
||||
public override void Initialize(CompProperties props)
|
||||
{
|
||||
base.Initialize(props);
|
||||
}
|
||||
|
||||
// 响应召集命令
|
||||
public void RespondToGather(Thing target)
|
||||
{
|
||||
if (parent is Pawn pawn && !pawn.Dead && pawn.Spawned)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 如果有待处理的转化,不响应召集
|
||||
if (pendingTransformTarget != null)
|
||||
return;
|
||||
|
||||
// 设置目标
|
||||
gatherTarget = target;
|
||||
isRespondingToGather = true;
|
||||
gatherResponseEndTick = Find.TickManager.TicksGame + 6000; // 100秒后超时
|
||||
|
||||
// 自动征召
|
||||
if (Props.autoDraftOnGather && pawn.drafter != null)
|
||||
{
|
||||
pawn.drafter.Drafted = true;
|
||||
}
|
||||
|
||||
// 创建移动到目标的Job
|
||||
if (target != null && target.Spawned)
|
||||
{
|
||||
CreateGatherJob(pawn, target);
|
||||
}
|
||||
|
||||
// 记录日志
|
||||
if (Prefs.DevMode)
|
||||
{
|
||||
Log.Message($"[CompAutonomousCat] {pawn.LabelShort} responding to gather call from {target?.LabelShort ?? "unknown"}");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error($"Error in RespondToGather for {parent.LabelShort}: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 创建召集任务
|
||||
private void CreateGatherJob(Pawn pawn, Thing target)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 清除当前任务
|
||||
if (pawn.CurJob != null)
|
||||
{
|
||||
pawn.jobs.EndCurrentJob(JobCondition.InterruptForced);
|
||||
}
|
||||
|
||||
// 创建移动到目标的Job
|
||||
Job job = new Job(JobDefOf.Goto, target.Position);
|
||||
|
||||
// 设置任务优先级和参数
|
||||
job.expiryInterval = 30000; // 长时间有效
|
||||
job.checkOverrideOnExpire = true;
|
||||
|
||||
// 开始任务
|
||||
pawn.jobs.StartJob(job, JobCondition.InterruptForced);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error($"Error creating gather job for {pawn.LabelShort}: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
// 开始转化流程
|
||||
public void StartTransformation(PawnKindDef targetPawnKind)
|
||||
{
|
||||
if (parent is Pawn pawn && !pawn.Dead && pawn.Spawned)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 查找最近的Comp_Gather建筑
|
||||
Thing closestGatherBuilding = FindClosestGatherBuilding();
|
||||
|
||||
if (closestGatherBuilding == null)
|
||||
{
|
||||
Messages.Message(
|
||||
"Wula_NoGatherBuilding".Translate(),
|
||||
MessageTypeDefOf.RejectInput
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// 存储转化目标
|
||||
pendingTransformTarget = targetPawnKind;
|
||||
|
||||
// 创建转化Job
|
||||
Job job = JobMaker.MakeJob(Wula_JobDefOf.WULA_TransformPawn, closestGatherBuilding);
|
||||
|
||||
// 清除当前任务并开始新任务
|
||||
pawn.jobs.StopAll();
|
||||
pawn.jobs.StartJob(job, JobCondition.InterruptForced);
|
||||
|
||||
// 显示消息
|
||||
Messages.Message(
|
||||
"Wula_TransformStarted".Translate(pawn.LabelShort, targetPawnKind.label),
|
||||
MessageTypeDefOf.NeutralEvent
|
||||
);
|
||||
|
||||
// 记录日志
|
||||
if (Prefs.DevMode)
|
||||
{
|
||||
Log.Message($"[CompAutonomousCat] {pawn.LabelShort} starting transformation to {targetPawnKind.label}");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error($"Error starting transformation for {parent.LabelShort}: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 清除转化目标(由JobDriver调用)
|
||||
public void ClearTransformTarget()
|
||||
{
|
||||
pendingTransformTarget = null;
|
||||
}
|
||||
|
||||
// 查找最近的Comp_Gather建筑
|
||||
private Thing FindClosestGatherBuilding()
|
||||
{
|
||||
if (parent.Map == null)
|
||||
return null;
|
||||
|
||||
Thing closestBuilding = null;
|
||||
float closestDistance = float.MaxValue;
|
||||
|
||||
// 查找所有Comp_Gather建筑
|
||||
foreach (Thing thing in parent.Map.listerThings.AllThings)
|
||||
{
|
||||
if (thing.TryGetComp<Comp_Gather>() != null &&
|
||||
thing.Spawned &&
|
||||
!thing.Destroyed &&
|
||||
thing.Faction == parent.Faction)
|
||||
{
|
||||
float distance = thing.Position.DistanceTo(parent.Position);
|
||||
if (distance < closestDistance)
|
||||
{
|
||||
closestDistance = distance;
|
||||
closestBuilding = thing;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return closestBuilding;
|
||||
}
|
||||
|
||||
// 每帧更新
|
||||
public override void CompTick()
|
||||
{
|
||||
base.CompTick();
|
||||
|
||||
// 处理召集响应
|
||||
if (isRespondingToGather)
|
||||
{
|
||||
UpdateGatherResponse();
|
||||
}
|
||||
}
|
||||
|
||||
// 更新召集响应
|
||||
private void UpdateGatherResponse()
|
||||
{
|
||||
// 检查是否超时
|
||||
if (Find.TickManager.TicksGame > gatherResponseEndTick)
|
||||
{
|
||||
EndGatherResponse();
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查目标是否仍然有效
|
||||
if (gatherTarget == null || !gatherTarget.Spawned || gatherTarget.Destroyed)
|
||||
{
|
||||
EndGatherResponse();
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查Pawn是否已经死亡或无法行动
|
||||
if (parent is Pawn pawn && (pawn.Dead || pawn.Downed || !pawn.Spawned))
|
||||
{
|
||||
EndGatherResponse();
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查是否已经到达目标附近
|
||||
if (parent is Pawn movingPawn && movingPawn.Position.DistanceTo(gatherTarget.Position) < 5f)
|
||||
{
|
||||
// 到达目标,结束召集响应
|
||||
EndGatherResponse();
|
||||
|
||||
// 可选:到达后执行其他动作
|
||||
if (movingPawn.CurJobDef == JobDefOf.Goto)
|
||||
{
|
||||
// 切换到等待或警戒状态
|
||||
movingPawn.jobs.EndCurrentJob(JobCondition.Succeeded);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 结束召集响应
|
||||
private void EndGatherResponse()
|
||||
{
|
||||
isRespondingToGather = false;
|
||||
gatherTarget = null;
|
||||
}
|
||||
|
||||
// 绘制效果
|
||||
public override void PostDraw()
|
||||
{
|
||||
base.PostDraw();
|
||||
|
||||
// 如果正在响应召集,绘制连接线
|
||||
if (isRespondingToGather && gatherTarget != null && parent.Spawned)
|
||||
{
|
||||
DrawGatherLine();
|
||||
}
|
||||
}
|
||||
|
||||
// 绘制召集线
|
||||
private void DrawGatherLine()
|
||||
{
|
||||
Vector3 startPos = parent.DrawPos;
|
||||
Vector3 endPos = gatherTarget.DrawPos;
|
||||
|
||||
// 提升到覆盖层高度
|
||||
startPos.y = AltitudeLayer.MetaOverlays.AltitudeFor();
|
||||
endPos.y = AltitudeLayer.MetaOverlays.AltitudeFor();
|
||||
|
||||
// 绘制连接线
|
||||
GenDraw.DrawLineBetween(
|
||||
startPos,
|
||||
endPos
|
||||
);
|
||||
}
|
||||
|
||||
// Gizmo显示
|
||||
public override IEnumerable<Gizmo> CompGetGizmosExtra()
|
||||
{
|
||||
foreach (Gizmo gizmo in base.CompGetGizmosExtra())
|
||||
{
|
||||
yield return gizmo;
|
||||
}
|
||||
|
||||
// 只对玩家派系显示
|
||||
if (parent.Faction == Faction.OfPlayer && parent is Pawn pawn && !pawn.Dead)
|
||||
{
|
||||
// 延迟初始化Gizmo
|
||||
if (!gizmoInitialized)
|
||||
{
|
||||
InitializeGizmo();
|
||||
gizmoInitialized = true;
|
||||
}
|
||||
|
||||
if (cachedTransformGizmo != null)
|
||||
{
|
||||
// 如果已有待处理的转化,显示不同图标或状态
|
||||
if (pendingTransformTarget != null)
|
||||
{
|
||||
cachedTransformGizmo.disabledReason = "Wula_TransformPending".Translate(pendingTransformTarget.label);
|
||||
}
|
||||
|
||||
yield return cachedTransformGizmo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化Gizmo
|
||||
private void InitializeGizmo()
|
||||
{
|
||||
if (Props.transformablePawnKinds != null && Props.transformablePawnKinds.Count > 0)
|
||||
{
|
||||
cachedTransformGizmo = new Command_Action();
|
||||
cachedTransformGizmo.defaultLabel = "Wula_Transform".Translate();
|
||||
cachedTransformGizmo.defaultDesc = "Wula_TransformDesc".Translate();
|
||||
cachedTransformGizmo.icon = ContentFinder<Texture2D>.Get("UI/Gizmos/Transform", false) ?? BaseContent.BadTex;
|
||||
cachedTransformGizmo.action = () => ShowTransformMenu();
|
||||
|
||||
// 设置热键
|
||||
cachedTransformGizmo.hotKey = KeyBindingDefOf.Misc3;
|
||||
}
|
||||
}
|
||||
|
||||
// 显示转化菜单
|
||||
private void ShowTransformMenu()
|
||||
{
|
||||
if (Props.transformablePawnKinds == null || Props.transformablePawnKinds.Count == 0)
|
||||
return;
|
||||
|
||||
List<FloatMenuOption> options = new List<FloatMenuOption>();
|
||||
|
||||
foreach (PawnKindDef pawnKind in Props.transformablePawnKinds)
|
||||
{
|
||||
options.Add(new FloatMenuOption(
|
||||
pawnKind.LabelCap,
|
||||
() => StartTransformation(pawnKind),
|
||||
pawnKind.race.uiIcon,
|
||||
Color.white
|
||||
));
|
||||
}
|
||||
|
||||
// 添加取消选项
|
||||
options.Add(new FloatMenuOption(
|
||||
"Cancel".Translate(),
|
||||
null,
|
||||
MenuOptionPriority.Default
|
||||
));
|
||||
|
||||
Find.WindowStack.Add(new FloatMenu(options));
|
||||
}
|
||||
|
||||
// 保存/加载数据
|
||||
public override void PostExposeData()
|
||||
{
|
||||
base.PostExposeData();
|
||||
|
||||
Scribe_Values.Look(ref isRespondingToGather, "isRespondingToGather", false);
|
||||
Scribe_References.Look(ref gatherTarget, "gatherTarget");
|
||||
Scribe_Values.Look(ref gatherResponseEndTick, "gatherResponseEndTick", 0);
|
||||
|
||||
// 保存/加载转化目标
|
||||
Scribe_Defs.Look(ref pendingTransformTarget, "pendingTransformTarget");
|
||||
|
||||
if (Scribe.mode == LoadSaveMode.PostLoadInit)
|
||||
{
|
||||
// 重置不正确的状态
|
||||
if (isRespondingToGather && (gatherTarget == null || !gatherTarget.Spawned))
|
||||
{
|
||||
isRespondingToGather = false;
|
||||
}
|
||||
|
||||
// 重置Gizmo缓存
|
||||
gizmoInitialized = false;
|
||||
cachedTransformGizmo = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
using System.Collections.Generic;
|
||||
using Verse;
|
||||
using Verse.AI;
|
||||
using RimWorld;
|
||||
using UnityEngine;
|
||||
|
||||
namespace WulaFallenEmpire
|
||||
{
|
||||
public class JobDriver_TransformPawn : JobDriver
|
||||
{
|
||||
private const TargetIndex GatherBuildingIndex = TargetIndex.A;
|
||||
|
||||
private Comp_Gather GatherComp => job.targetA.Thing?.TryGetComp<Comp_Gather>();
|
||||
private Comp_AutonomousCat PawnComp => pawn.TryGetComp<Comp_AutonomousCat>();
|
||||
|
||||
public override bool TryMakePreToilReservations(bool errorOnFailed)
|
||||
{
|
||||
// 预留目标建筑
|
||||
if (!pawn.Reserve(job.targetA, job, 1, -1, null, errorOnFailed))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override IEnumerable<Toil> MakeNewToils()
|
||||
{
|
||||
// 第1步:移动到目标建筑
|
||||
yield return Toils_Goto.GotoCell(GatherBuildingIndex, PathEndMode.InteractionCell);
|
||||
|
||||
// 第2步:进行转化工作
|
||||
Toil transformToil = new Toil();
|
||||
transformToil.initAction = () =>
|
||||
{
|
||||
// 获取目标建筑
|
||||
Thing gatherBuilding = job.targetA.Thing;
|
||||
if (gatherBuilding == null || gatherBuilding.Destroyed)
|
||||
{
|
||||
ReadyForNextToil();
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取Comp_Gather
|
||||
var gatherComp = gatherBuilding.TryGetComp<Comp_Gather>();
|
||||
if (gatherComp == null)
|
||||
{
|
||||
ReadyForNextToil();
|
||||
return;
|
||||
}
|
||||
|
||||
// 确保可以转化
|
||||
if (!gatherComp.CanTransformPawn(pawn))
|
||||
{
|
||||
Messages.Message("Wula_CannotTransformHere".Translate(), MessageTypeDefOf.RejectInput);
|
||||
ReadyForNextToil();
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
transformToil.tickAction = () =>
|
||||
{
|
||||
// 确保目标建筑仍然有效
|
||||
Thing gatherBuilding = job.targetA.Thing;
|
||||
if (gatherBuilding == null || gatherBuilding.Destroyed ||
|
||||
gatherBuilding.Map != pawn.Map ||
|
||||
pawn.Position.DistanceTo(gatherBuilding.Position) > 3f)
|
||||
{
|
||||
// 中断转化,清除转化目标
|
||||
PawnComp?.ClearTransformTarget();
|
||||
EndJobWith(JobCondition.Incompletable);
|
||||
return;
|
||||
}
|
||||
|
||||
// 面向建筑
|
||||
pawn.rotationTracker.FaceCell(gatherBuilding.Position);
|
||||
|
||||
// 播放转化效果
|
||||
if (Find.TickManager.TicksGame % 20 == 0)
|
||||
{
|
||||
PlayTransformEffects();
|
||||
}
|
||||
};
|
||||
|
||||
// 从Comp_AutonomousCat获取转化时间
|
||||
var compProps = PawnComp?.Props as CompProperties_AutonomousCat;
|
||||
int transformDuration = compProps != null ?
|
||||
Mathf.RoundToInt(compProps.transformTime * 60f) : 180; // 默认3秒
|
||||
|
||||
transformToil.defaultCompleteMode = ToilCompleteMode.Delay;
|
||||
transformToil.defaultDuration = transformDuration;
|
||||
yield return transformToil;
|
||||
|
||||
// 第3步:完成转化
|
||||
yield return new Toil
|
||||
{
|
||||
initAction = () =>
|
||||
{
|
||||
// 获取目标建筑
|
||||
Thing gatherBuilding = job.targetA.Thing;
|
||||
if (gatherBuilding == null || gatherBuilding.Destroyed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取Comp_Gather
|
||||
var gatherComp = gatherBuilding.TryGetComp<Comp_Gather>();
|
||||
if (gatherComp == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取要转化的PawnKindDef(从Comp_AutonomousCat中)
|
||||
var targetPawnKind = PawnComp?.PendingTransformTarget;
|
||||
if (targetPawnKind == null)
|
||||
{
|
||||
Messages.Message("Wula_NoTransformTarget".Translate(), MessageTypeDefOf.RejectInput);
|
||||
return;
|
||||
}
|
||||
|
||||
// 调用Comp_Gather的转化方法
|
||||
gatherComp.TransformPawn(pawn, targetPawnKind);
|
||||
|
||||
// 清除转化目标
|
||||
PawnComp?.ClearTransformTarget();
|
||||
},
|
||||
defaultCompleteMode = ToilCompleteMode.Instant
|
||||
};
|
||||
}
|
||||
|
||||
// 播放转化效果
|
||||
private void PlayTransformEffects()
|
||||
{
|
||||
// 播放音效
|
||||
var compProps = PawnComp?.Props as CompProperties_AutonomousCat;
|
||||
|
||||
// 播放特效
|
||||
if (compProps?.transformEffect != null)
|
||||
{
|
||||
compProps.transformEffect.Spawn(pawn.Position, pawn.Map).Cleanup();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,7 @@ namespace WulaFallenEmpire
|
||||
public static JobDef WULA_RepairMech;
|
||||
public static JobDef WULA_ForceEjectPilot;
|
||||
public static JobDef WULA_CarryToMech;
|
||||
public static JobDef WULA_TransformPawn;
|
||||
|
||||
static Wula_JobDefOf()
|
||||
{
|
||||
|
||||
@@ -85,6 +85,9 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<!-- 第一部分:基础类和组件 -->
|
||||
<Compile Include="BuildingComp\WULA_BuildToPawn\CompBuildToPawn.cs" />
|
||||
<Compile Include="BuildingComp\WULA_BuildToPawn\CompProperties_BuildToPawn.cs" />
|
||||
<Compile Include="BuildingComp\WULA_Gather\CompGather.cs" />
|
||||
<Compile Include="HarmonyPatches\WULA_MechUnit\Patch_Pawn_RotationTracker_UpdateRotation.cs" />
|
||||
<Compile Include="HediffComp\WULA_DamageResponse\HediffComp_DamageResponse.cs" />
|
||||
<Compile Include="HediffComp\WULA_DisappearWithEffect\HediffCompProperties_DisappearWithEffect.cs" />
|
||||
@@ -97,6 +100,8 @@
|
||||
<Compile Include="HediffComp\WULA_TimedExplosion\HediffComp_TimedExplosion.cs" />
|
||||
<Compile Include="ITab\ITab_MechSkills.cs" />
|
||||
<Compile Include="MentalState\MentalState_MechNoPilot.cs" />
|
||||
<Compile Include="Pawn_Comps\AutonomousCat\CompAutonomousCat.cs" />
|
||||
<Compile Include="Pawn_Comps\AutonomousCat\JobDriver_TransformPawn.cs" />
|
||||
<Compile Include="Pawn_Comps\PawnRenderExtra\Comp_PawnRenderExtra.cs" />
|
||||
<Compile Include="Pawn_Comps\HighSpeedCollision\CompHighSpeedCollision.cs" />
|
||||
<Compile Include="Work\EnterMech\FloatMenuOptionProvider_EnterMech.cs" />
|
||||
|
||||
Reference in New Issue
Block a user