diff --git a/1.6/1.6/Assemblies/WulaFallenEmpire.dll b/1.6/1.6/Assemblies/WulaFallenEmpire.dll
index fa641e81..9da1e209 100644
Binary files a/1.6/1.6/Assemblies/WulaFallenEmpire.dll and b/1.6/1.6/Assemblies/WulaFallenEmpire.dll differ
diff --git a/1.6/1.6/Defs/ThingDefs_Races/Races_Wulaspecies.xml b/1.6/1.6/Defs/ThingDefs_Races/Races_Wulaspecies.xml
index 72811c46..1643202d 100644
--- a/1.6/1.6/Defs/ThingDefs_Races/Races_Wulaspecies.xml
+++ b/1.6/1.6/Defs/ThingDefs_Races/Races_Wulaspecies.xml
@@ -903,6 +903,225 @@
+
+
+ BulletImpact_Metal
+
+ 1200
+ 0.5
+ 1
+ 0
+ -100
+ 250
+ 0
+ 2.00
+ 3.4
+ 1
+ 12
+ 1
+ 0.33
+ 5
+ 0.5
+ 0.10
+ 0.20
+ 0.66
+
+ true
+ None
+
+ Mechanoid
+ false
+ false
+ None
+ 2500
+ Filth_MachineBits
+ NamerMech
+ 1000~2000
+ 2
+ MechConstant
+ true
+ Mech_Light
+ ToolUser
+ WULA_AutonomousMech
+ 0.7
+ Light
+
+
+ 10
+
+
+
+
+
+ Blunt
+
+ 6
+ 2.6
+ HeadAttackTool
+ true
+
+
+
+
+ CompMechanoid
+
+
+ true
+ 30
+ MechanoidsWakeUp
+
+
+
+ true
+ true
+ true
+
+
+
+
+
+
+ -10
+ 999999
+ 0
+
+
+
+
+
+
+
+ 5
+
+ 0
+
+
+
+
+ MechanoidFullyFormed
+
+
+
+ DeathActionWorker_Vanish
+ Filth_MachineBits
+ 1~2
+
+
+
+
+ Mech_WULA_Cat_Cute
+ 5.9
+ false
+ false
+ true
+
+
+
+
+ Mech_WULA_Cat
+
+ 乌拉帝国的一种小型自律机械体,无需监管者,可以执行包括搬运、烹饪、种植收割、清理、急救和灭火一类的简单工作,因为似猫的外形受到乌拉星人欢迎。
+ Wula/Things/WULA_Cat/WULA_Cat_Thin_south
+
+
+ 6
+ 0.001
+
+
+
+ Hauling
+
+
+
+
+
+ Cooking
+
+ PlantCutting
+ Growing
+ Cleaning
+ Doctor
+ Firefighter
+
+
+
+
+ Mech_WULA_Cat_EMP
+
+ 乌拉帝国的一种小型自律机械体,无需监管者,只能执行救火、搬运和清扫任务,但是相比起基础型号多配备了一个EMP投掷物,可以辅助乌拉帝国军团对抗机械部队。
+
+
+ Mech_WULA_Cat_Fire
+
+ 乌拉帝国的一种小型自律机械体,无需监管者,只能执行救火、搬运和清扫任务,但是相比起基础型号多配备了一个燃烧瓶投掷物,可以点燃靠近阵线的敌军。
+
+
+ Mech_WULA_Cat_Constructor
+
+ 乌拉帝国的一种小型自律机械体,无需监管者,只能执行建造和开采任务,可以跳起来用手上的HAm-1"装修锤"锤烂敌人的膝盖。
+ Wula/Things/WULA_Constructor_Cat/WULA_Cat_Thin_south
+
+
+ Mining
+ Construction
+
+
+
+ 2
+
+
+
+ Mech_WULA_Cat_Assault
+
+ 乌拉帝国的一种小型自律机械体,无需监管者,可以执行搬运、狩猎和割除任务,身着轻甲,装备了一把DLa-4"云母"突击步枪附下挂刺刀,可以给敌方造成不小的麻烦。
+ Wula/Things/WULA_Assault_Cat/WULA_Cat_Thin_south
+
+
+ Hunting
+ Hauling
+ PlantCutting
+
+
+
+ 0.25
+ 0.25
+
+ 4
+
+
+
+ Mech_WULA_Cat_DM
+
+ 乌拉帝国的一种小型自律机械体,无需监管者,可以执行包括搬运、烹饪、种植收割、清理、急救和灭火一类的简单工作。这种型号的乌拉猫猫内置了一台不稳定暗物质引擎,这使得其无需充电,但是在死亡时会产生巨大的爆炸。
+ Wula/Things/WULA_DM_Cat/WULA_Cat_Thin_south
+
+
+ 6
+ 0.001
+ -1
+
+
+
+ Hauling
+ Cooking
+ PlantCutting
+ Growing
+ Cleaning
+ Doctor
+ Firefighter
+
+
+
+
+ 30
+ BombSuper
+ 550
+
+
+
+
+
+
Wula_AI_Heavy_Panzer
@@ -1287,252 +1506,6 @@
-
-
- Mech_WULA_Cat
-
- 乌拉帝国的一种小型机械体,可以执行包括搬运、烹饪、种植收割、清理、急救和灭火一类的简单工作,因为似猫的外形受到乌拉星人欢迎。
- Wula/Things/WULA_Cat/WULA_Cat_Thin_south
-
-
- 6
- 0.001
-
- 0
-
-
-
- Hauling
-
-
-
-
-
- Cooking
-
- PlantCutting
- Growing
- Cleaning
- Doctor
- Firefighter
-
-
-
- MechanoidFullyFormed
-
-
-
-
-
-
- DeathActionWorker_Vanish
- Filth_MachineBits
- 1~2
-
-
-
-
-
-
- Mech_WULA_Cat_Cute
- 5.9
- false
- true
- true
-
-
-
-
-
-
- Wula/Things/WULA_Attack_Cat/WULA_Cat_Thin_south
-
-
- 5
-
- 0
-
-
- WULA_AutonomousMech
-
- Hauling
-
-
-
-
-
-
-
-
-
- Cleaning
-
- Firefighter
-
-
-
- MechanoidFullyFormed
-
-
-
-
-
-
- DeathActionWorker_Vanish
- Filth_MachineBits
- 1~2
-
-
-
-
- true
- true
- true
-
-
-
-
- Mech_WULA_Cat_Cute
- 5.9
- false
- true
- true
-
-
-
-
-
- Mech_WULA_Cat_EMP
-
- 乌拉帝国的一种小型机械体,只能执行救火、搬运和清扫任务,但是相比起基础型号多配备了一个EMP投掷物,可以辅助乌拉帝国军团对抗机械部队。
-
-
- Mech_WULA_Cat_Fire
-
- 乌拉帝国的一种小型机械体,只能执行救火、搬运和清扫任务,但是相比起基础型号多配备了一个燃烧瓶投掷物,可以点燃靠近阵线的敌军。
-
-
- Mech_WULA_Cat_Constructor
-
- 乌拉帝国的一种小型机械体,只能执行建造和开采任务,可以跳起来用手上的HAm-1"装修锤"锤烂敌人的膝盖。
- Wula/Things/WULA_Constructor_Cat/WULA_Cat_Thin_south
-
-
- Mining
- Construction
-
-
-
- 2
-
-
-
- Mech_WULA_Cat_Assault
-
- 乌拉帝国的一种小型机械体,可以执行搬运、狩猎和割除任务,身着轻甲,装备了一把DLa-4"云母"突击步枪附下挂刺刀,可以给敌方造成不小的麻烦。
- Wula/Things/WULA_Assault_Cat/WULA_Cat_Thin_south
-
-
- Hunting
- Hauling
- PlantCutting
-
-
-
- 0.25
- 0.25
-
- 4
-
-
-
- Mech_WULA_Cat_DM
-
- 乌拉帝国的一种小型机械体,可以执行包括搬运、烹饪、种植收割、清理、急救和灭火一类的简单工作。这种型号的乌拉猫猫内置了一台不稳定暗物质引擎,这使得其无需充电,但是在死亡时会产生巨大的爆炸。
- Wula/Things/WULA_DM_Cat/WULA_Cat_Thin_south
-
-
- 6
- 0.001
- -1
-
-
- 0
-
-
-
- Hauling
-
-
-
-
-
- Cooking
-
- PlantCutting
- Growing
- Cleaning
- Doctor
- Firefighter
-
-
-
- MechanoidFullyFormed
-
-
-
-
-
-
- DeathActionWorker_Vanish
- Filth_MachineBits
- 1~2
-
-
-
-
-
-
- 30
- BombSuper
- 550
-
-
- Mech_WULA_Cat_Cute
- 5.9
- false
- true
- true
-
-
-
WULA_Fxxk_Goose
diff --git a/1.6/1.6/Defs/ThinkTreeDefs/WULA_AutonomousMech.xml b/1.6/1.6/Defs/ThinkTreeDefs/WULA_AutonomousMech.xml
index 6430b576..d49741ee 100644
--- a/1.6/1.6/Defs/ThinkTreeDefs/WULA_AutonomousMech.xml
+++ b/1.6/1.6/Defs/ThinkTreeDefs/WULA_AutonomousMech.xml
@@ -21,9 +21,12 @@
Downed
-
-
+
+
+ 0.05
+
+
@@ -46,14 +49,19 @@
-
-
+
+
DraftedOrder
+
+
+ 8
+ 30
+
@@ -70,6 +78,14 @@
+
+
+ 0.3
+
+
+
+
+
@@ -82,7 +98,14 @@
Work
-
+
+
+
+ 0.2
+
+
+
+
@@ -119,9 +142,26 @@
Recharge
+
+
+
+ 0.9
+
+
+
+ None
+ 充电完成
+
+
+
+
+
-
- true
+
+
+
+ None
+ 等待空闲充电站
@@ -166,4 +206,36 @@
+
+
+
+ WULA_AutonomousCombat
+
+ 战斗中
+ 战斗
+ false
+ 99
+ Violent
+ true
+
+
+
+ WULA_AutonomousWaitCombat
+ WulaFallenEmpire.JobDriver_AutonomousWaitCombat
+ standing guard.
+ true
+ true
+ false
+ true
+ false
+ true
+ false
+
+
+ true
+ true
+ 35
+
+
+
diff --git a/1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/Misc_Gameplay.xml b/1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/Misc_Gameplay.xml
index 03a2b5ee..b4ddf964 100644
--- a/1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/Misc_Gameplay.xml
+++ b/1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/Misc_Gameplay.xml
@@ -6,5 +6,37 @@
自动生产
切换是否自动生产单位。开启后,当资源和冷却允许时,会自动生产单位以维持队列上限。
自动生产已开启。再次点击以关闭。
+
+
+ 行为模式:{0}
+ 修改自律机械的行为模式
+
+ 工作
+ 充电
+ 关机
+ 未知
+
+ 工作模式 - 根据机体设定,自行进行工作
+ 充电模式 - 充电后休眠
+ 关机模式 - 立即关机,会在此状态下以非常缓慢的速率充电
+
+
+ 自主操作中
+ 自主模式:{0}
+
+
+ ({0})
+ ({0})
+ 当前能量:{0}
+ (低电量)
+ (电量危急!)
+
+
+ {0}电量不足,切换到充电模式
+ {0}已充满电,返回工作模式
+ {0}电量危急!
+ {0}切换到{1}模式
+ 征召自律机械
+ 使自律机械进入征召状态
\ No newline at end of file
diff --git a/Source/WulaFallenEmpire/Pawn/WULA_AutonomousMech/CompAutonomousMech.cs b/Source/WulaFallenEmpire/Pawn/WULA_AutonomousMech/CompAutonomousMech.cs
index 4f43a9ae..d02b8108 100644
--- a/Source/WulaFallenEmpire/Pawn/WULA_AutonomousMech/CompAutonomousMech.cs
+++ b/Source/WulaFallenEmpire/Pawn/WULA_AutonomousMech/CompAutonomousMech.cs
@@ -38,13 +38,19 @@ namespace WulaFallenEmpire
Shutdown // 关机模式:立即休眠
}
+
public class CompProperties_AutonomousMech : CompProperties
{
public bool enableAutonomousDrafting = true;
public bool enableAutonomousWork = true;
public bool requirePowerForAutonomy = true;
public bool suppressUncontrolledWarning = true;
-
+
+ // 新增:能量管理设置
+ public float lowEnergyThreshold = 0.3f; // 低能量阈值
+ public float criticalEnergyThreshold = 0.1f; // 临界能量阈值
+ public float rechargeCompleteThreshold = 0.9f; // 充电完成阈值
+
public CompProperties_AutonomousMech()
{
compClass = typeof(CompAutonomousMech);
@@ -54,202 +60,290 @@ namespace WulaFallenEmpire
public class CompAutonomousMech : ThingComp
{
public CompProperties_AutonomousMech Props => (CompProperties_AutonomousMech)props;
-
+
public Pawn MechPawn => parent as Pawn;
-
- // 新增:当前工作模式
+
private AutonomousWorkMode currentWorkMode = AutonomousWorkMode.Work;
-
+ private bool wasLowEnergy = false; // 记录上次是否处于低能量状态
+
public bool CanBeAutonomous
{
get
{
if (MechPawn == null || MechPawn.Dead || MechPawn.Downed)
return false;
-
+
if (!Props.enableAutonomousDrafting)
return false;
-
+
if (MechPawn.GetOverseer() != null)
return false;
-
+
if (Props.requirePowerForAutonomy)
{
- var energyNeed = MechPawn.needs?.TryGetNeed();
- if (energyNeed != null && energyNeed.CurLevelPercentage < 0.1f)
+ // 在临界能量下不允许自主模式
+ if (GetEnergyLevel() < Props.criticalEnergyThreshold)
return false;
}
-
+
return true;
}
}
-
+
public bool CanWorkAutonomously
{
get
{
if (!Props.enableAutonomousWork)
return false;
-
+
if (!CanBeAutonomous)
return false;
-
+
if (MechPawn.Drafted)
return false;
-
+
return true;
}
}
-
+
public bool ShouldSuppressUncontrolledWarning
{
get
{
if (!Props.suppressUncontrolledWarning)
return false;
-
+
return CanBeAutonomous;
}
}
- // 新增:公开访问当前工作模式
public AutonomousWorkMode CurrentWorkMode => currentWorkMode;
+ // 新增:能量状态检查方法
+ public float GetEnergyLevel()
+ {
+ var energyNeed = MechPawn.needs?.TryGetNeed();
+ return energyNeed?.CurLevelPercentage ?? 0f;
+ }
+
+ public bool IsLowEnergy => GetEnergyLevel() < Props.lowEnergyThreshold;
+ public bool IsCriticalEnergy => GetEnergyLevel() < Props.criticalEnergyThreshold;
+ public bool IsFullyCharged => GetEnergyLevel() >= Props.rechargeCompleteThreshold;
+
+ // ... 现有代码 ...
public override void PostSpawnSetup(bool respawningAfterLoad)
{
base.PostSpawnSetup(respawningAfterLoad);
-
- if (MechPawn != null && MechPawn.IsColonyMech)
+
+ // 确保使用独立战斗系统
+ InitializeAutonomousCombat();
+ }
+ private void InitializeAutonomousCombat()
+ {
+ // 确保有 draftController
+ if (MechPawn.drafter == null)
{
+ MechPawn.drafter = new Pawn_DraftController(MechPawn);
+ }
+
+ // 强制启用 FireAtWill
+ if (MechPawn.drafter != null)
+ {
+ MechPawn.drafter.FireAtWill = true;
+ }
+
+ // 确保工作设置不会干扰战斗
+ EnsureCombatWorkSettings();
+ }
+ private void EnsureCombatWorkSettings()
+ {
+ if (MechPawn.workSettings == null)
+ return;
+ // 设置自主战斗工作类型(如果存在)
+ WorkTypeDef autonomousCombat = DefDatabase.GetNamedSilentFail("WULA_AutonomousCombat");
+ if (autonomousCombat != null)
+ {
+ MechPawn.workSettings.SetPriority(autonomousCombat, 1);
+ }
+ }
+ public override void CompTick()
+ {
+ base.CompTick();
+
+ // 定期检查战斗状态
+ if (Find.TickManager.TicksGame % 60 == 0)
+ {
+ CheckCombatStatus();
+ }
+ }
+ private void CheckCombatStatus()
+ {
+ if (MechPawn.drafter?.Drafted == true && MechPawn.CurJob == null)
+ {
+ // 如果被征召但没有工作,强制进入自主战斗状态
+ ForceAutonomousCombat();
+ }
+ }
+ private void ForceAutonomousCombat()
+ {
+ JobDef autonomousCombatJob = DefDatabase.GetNamedSilentFail("WULA_AutonomousWaitCombat");
+ if (autonomousCombatJob != null)
+ {
+ Job job = JobMaker.MakeJob(autonomousCombatJob);
+ MechPawn.jobs.StartJob(job, JobCondition.InterruptForced);
+ }
+ }
+ public override void CompTick()
+ {
+ base.CompTick();
+
+ // 每60 tick检查一次能量状态
+ if (MechPawn != null && MechPawn.IsColonyMech && Find.TickManager.TicksGame % 60 == 0)
+ {
+ CheckEnergyStatus();
EnsureWorkSettings();
}
}
+ // 新增:能量状态检查
+ private void CheckEnergyStatus()
+ {
+ if (!CanWorkAutonomously)
+ return;
+
+ bool isLowEnergyNow = IsLowEnergy;
+
+ // 如果能量状态发生变化
+ if (isLowEnergyNow != wasLowEnergy)
+ {
+ if (isLowEnergyNow)
+ {
+ // 进入低能量状态
+ if (currentWorkMode == AutonomousWorkMode.Work)
+ {
+ // 自动切换到充电模式
+ SetWorkMode(AutonomousWorkMode.Recharge);
+ Messages.Message("WULA_LowEnergySwitchToRecharge".Translate(MechPawn.LabelCap),
+ MechPawn, MessageTypeDefOf.CautionInput);
+ }
+ }
+ else
+ {
+ // 恢复能量状态
+ if (currentWorkMode == AutonomousWorkMode.Recharge && IsFullyCharged)
+ {
+ // 充满电后自动切换回工作模式
+ SetWorkMode(AutonomousWorkMode.Work);
+ Messages.Message("WULA_FullyChargedSwitchToWork".Translate(MechPawn.LabelCap),
+ MechPawn, MessageTypeDefOf.PositiveEvent);
+ }
+ }
+
+ wasLowEnergy = isLowEnergyNow;
+ }
+
+ // 临界能量警告
+ if (IsCriticalEnergy && currentWorkMode != AutonomousWorkMode.Recharge && currentWorkMode != AutonomousWorkMode.Shutdown)
+ {
+ Messages.Message("WULA_CriticalEnergyLevels".Translate(MechPawn.LabelCap),
+ MechPawn, MessageTypeDefOf.ThreatBig);
+ // 强制切换到充电模式
+ SetWorkMode(AutonomousWorkMode.Recharge);
+ }
+ }
+
public override IEnumerable CompGetGizmosExtra()
{
if (MechPawn == null || !CanBeAutonomous)
yield break;
-
- // 自主征召按钮
- yield return new Command_Toggle
- {
- defaultLabel = "Autonomous Mode",
- defaultDesc = "Enable autonomous operation without mechanitor control",
- icon = TexCommand.Draft,
- isActive = () => MechPawn.Drafted,
- toggleAction = () => ToggleAutonomousDraft(),
- hotKey = KeyBindingDefOf.Misc1
- };
-
+
// 工作模式切换按钮
if (CanWorkAutonomously)
{
+ string energyInfo = "WULA_EnergyInfo".Translate(GetEnergyLevel().ToStringPercent());
yield return new Command_Action
{
- defaultLabel = "Work Mode: " + GetCurrentWorkModeDisplay(),
- defaultDesc = "Switch autonomous work mode",
- icon = TexCommand.Attack,
+ defaultLabel = "WULA_Mech_WorkMode".Translate(GetCurrentWorkModeDisplay()) + energyInfo,
+ defaultDesc = GetWorkModeDescription(),
+ icon = GetWorkModeIcon(),
action = () => ShowWorkModeMenu()
};
}
}
- private void ToggleAutonomousDraft()
+ // 修改:返回包含能量信息的描述
+ private string GetWorkModeDescription()
{
- if (MechPawn.drafter == null)
- return;
+ string baseDesc = "WULA_Switch_Mech_WorkMode".Translate();
+ string energyInfo = "WULA_CurrentEnergy".Translate(GetEnergyLevel().ToStringPercent());
- if (MechPawn.Drafted)
- {
- MechPawn.drafter.Drafted = false;
- Messages.Message($"{MechPawn.LabelCap} autonomous mode deactivated",
- MechPawn, MessageTypeDefOf.NeutralEvent);
- }
- else
- {
- if (CanBeAutonomous)
- {
- MechPawn.drafter.Drafted = true;
- Messages.Message($"{MechPawn.LabelCap} is now operating autonomously",
- MechPawn, MessageTypeDefOf.PositiveEvent);
- }
- else
- {
- Messages.Message($"Cannot activate autonomous mode: {GetBlockReason()}",
- MechPawn, MessageTypeDefOf.NegativeEvent);
- }
- }
+ if (IsLowEnergy)
+ energyInfo += "WULA_EnergyLow".Translate();
+ if (IsCriticalEnergy)
+ energyInfo += "WULA_EnergyCritical".Translate();
+
+ return baseDesc + "\n" + energyInfo;
+ }
+
+ // 新增:根据能量状态返回不同的图标
+ private UnityEngine.Texture2D GetWorkModeIcon()
+ {
+ if (IsCriticalEnergy)
+ return TexCommand.DesirePower;
+ else if (IsLowEnergy)
+ return TexCommand.ToggleVent;
+ else
+ return TexCommand.Attack;
}
- // 修改:返回自定义工作模式的显示名称
private string GetCurrentWorkModeDisplay()
{
switch (currentWorkMode)
{
case AutonomousWorkMode.Work:
- return "Work";
+ return "WULA_WorkMode_Work".Translate();
case AutonomousWorkMode.Recharge:
- return "Recharge";
+ return "WULA_WorkMode_Recharge".Translate();
case AutonomousWorkMode.Shutdown:
- return "Shutdown";
+ return "WULA_WorkMode_Shutdown".Translate();
default:
- return "Unknown";
+ return "WULA_WorkMode_Unknown".Translate();
}
}
private void ShowWorkModeMenu()
{
List list = new List();
-
+
// 工作模式
- list.Add(new FloatMenuOption("Work Mode - Perform assigned work tasks",
+ list.Add(new FloatMenuOption("WULA_WorkMode_Work_Desc".Translate(),
() => SetWorkMode(AutonomousWorkMode.Work)));
-
+
// 充电模式
- list.Add(new FloatMenuOption("Recharge Mode - Charge and then shutdown",
+ list.Add(new FloatMenuOption("WULA_WorkMode_Recharge_Desc".Translate(),
() => SetWorkMode(AutonomousWorkMode.Recharge)));
-
+
// 休眠模式
- list.Add(new FloatMenuOption("Shutdown Mode - Immediately shutdown",
+ list.Add(new FloatMenuOption("WULA_WorkMode_Shutdown_Desc".Translate(),
() => SetWorkMode(AutonomousWorkMode.Shutdown)));
Find.WindowStack.Add(new FloatMenu(list));
}
- // 修改:设置自定义工作模式
private void SetWorkMode(AutonomousWorkMode mode)
{
currentWorkMode = mode;
-
+
// 清除当前工作,让机械族重新选择符合新模式的工作
if (MechPawn.CurJob != null && MechPawn.CurJob.def != JobDefOf.Wait_Combat)
{
MechPawn.jobs.StopAll();
}
-
- string modeName = GetCurrentWorkModeDisplay();
- Messages.Message($"{MechPawn.LabelCap} switched to {modeName} mode",
- MechPawn, MessageTypeDefOf.NeutralEvent);
-
- Log.Message($"AutonomousMech: {MechPawn.LabelCap} work mode set to {modeName}");
- }
- private string GetBlockReason()
- {
- if (MechPawn.Dead || MechPawn.Downed)
- return "Mech is incapacitated";
-
- if (MechPawn.GetOverseer() != null)
- return "Mech is under mechanitor control";
-
- if (Props.requirePowerForAutonomy)
- {
- var energyNeed = MechPawn.needs?.TryGetNeed();
- if (energyNeed != null && energyNeed.CurLevelPercentage < 0.1f)
- return "Insufficient energy";
- }
-
- return "Autonomous mode disabled";
+ string modeName = GetCurrentWorkModeDisplay();
+ Messages.Message("WULA_SwitchedToMode".Translate(MechPawn.LabelCap, modeName),
+ MechPawn, MessageTypeDefOf.NeutralEvent);
}
private void EnsureWorkSettings()
@@ -264,18 +358,20 @@ namespace WulaFallenEmpire
{
if (!CanBeAutonomous)
return null;
-
+
+ string energyInfo = "WULA_EnergyInfoShort".Translate(GetEnergyLevel().ToStringPercent());
+
if (MechPawn.Drafted)
- return "Operating autonomously";
+ return "WULA_Autonomous_Drafted".Translate() + energyInfo;
else
- return $"Autonomous mode: {GetCurrentWorkModeDisplay()}";
+ return "WULA_Autonomous_Mode".Translate(GetCurrentWorkModeDisplay()) + energyInfo;
}
-
- // 新增:保存和加载工作模式
+
public override void PostExposeData()
{
base.PostExposeData();
Scribe_Values.Look(ref currentWorkMode, "currentWorkMode", AutonomousWorkMode.Work);
+ Scribe_Values.Look(ref wasLowEnergy, "wasLowEnergy", false);
}
}
}
diff --git a/Source/WulaFallenEmpire/Pawn/WULA_AutonomousMech/JobDriver_AutonomousWaitCombat.cs b/Source/WulaFallenEmpire/Pawn/WULA_AutonomousMech/JobDriver_AutonomousWaitCombat.cs
new file mode 100644
index 00000000..1cd48ca1
--- /dev/null
+++ b/Source/WulaFallenEmpire/Pawn/WULA_AutonomousMech/JobDriver_AutonomousWaitCombat.cs
@@ -0,0 +1,234 @@
+// JobDriver_AutonomousWaitCombat.cs
+using System;
+using System.Collections.Generic;
+using RimWorld;
+using Verse;
+using Verse.AI;
+
+namespace WulaFallenEmpire
+{
+ public class JobDriver_AutonomousWaitCombat : JobDriver
+ {
+ private const int TargetSearchInterval = 4;
+ private bool collideWithPawns;
+
+ private JobExtension_AutonomousCombat CombatExtension =>
+ job.def.GetModExtension();
+
+ public override bool TryMakePreToilReservations(bool errorOnFailed)
+ {
+ return true;
+ }
+
+ protected override IEnumerable MakeNewToils()
+ {
+ Toil waitToil = new Toil();
+ waitToil.initAction = delegate
+ {
+ if (pawn.Spawned)
+ {
+ pawn.Map.pawnDestinationReservationManager.Reserve(pawn, job, pawn.Position);
+ pawn.pather?.StopDead();
+ }
+
+ // 初始化战斗设置
+ InitializeCombatSettings();
+
+ // 立即检查攻击目标
+ CheckForAutoAttack();
+ };
+
+ waitToil.tickAction = delegate
+ {
+ // 定期检查攻击目标
+ if (Find.TickManager.TicksGame % TargetSearchInterval == 0)
+ {
+ CheckForAutoAttack();
+ }
+
+ // 处理朝向
+ HandleFacing();
+ };
+
+ waitToil.defaultCompleteMode = ToilCompleteMode.Never;
+ yield return waitToil;
+ }
+
+ private void InitializeCombatSettings()
+ {
+ var comp = pawn.GetComp();
+ if (comp?.CanWorkAutonomously == true)
+ {
+ // 确保征召设置正确
+ if (pawn.drafter != null)
+ {
+ pawn.drafter.FireAtWill = CombatExtension?.forceFireAtWill ?? true;
+ }
+ }
+ }
+
+ private void HandleFacing()
+ {
+ // 如果有指定朝向,就面向该方向
+ if (job.overrideFacing != Rot4.Invalid)
+ {
+ pawn.rotationTracker.FaceTarget(pawn.Position + job.overrideFacing.FacingCell);
+ return;
+ }
+
+ // 如果有职责焦点,就面向焦点
+ if (pawn.mindState?.duty?.focus != null)
+ {
+ pawn.rotationTracker.FaceTarget(pawn.mindState.duty.focus);
+ return;
+ }
+
+ // 自动寻找敌人并面向它
+ Thing enemyTarget = FindNearestEnemy();
+ if (enemyTarget != null)
+ {
+ pawn.rotationTracker.FaceTarget(enemyTarget);
+ }
+ }
+
+ private void CheckForAutoAttack()
+ {
+ if (!CanAutoAttack())
+ return;
+
+ // 先检查近战攻击
+ if (CheckMeleeAttack())
+ return;
+
+ // 再检查远程攻击
+ CheckRangedAttack();
+ }
+
+ private bool CanAutoAttack()
+ {
+ // 基础状态检查
+ if (pawn.Downed || pawn.stances.FullBodyBusy || pawn.IsCarryingPawn())
+ return false;
+
+ var comp = pawn.GetComp();
+ if (comp?.CanWorkAutonomously != true)
+ return false;
+
+ // 检查扩展设置
+ if (CombatExtension?.autoAttackEnabled != true)
+ return false;
+
+ // 忽略工作标签检查,因为这是独立系统
+ if (!CombatExtension.ignoreWorkTags)
+ {
+ if (pawn.WorkTagIsDisabled(WorkTags.Violent))
+ return false;
+ }
+
+ return true;
+ }
+
+ private bool CheckMeleeAttack()
+ {
+ if (!pawn.kindDef.canMeleeAttack)
+ return false;
+
+ // 检查相邻格子的敌人
+ for (int i = 0; i < 9; i++)
+ {
+ IntVec3 cell = pawn.Position + GenAdj.AdjacentCellsAndInside[i];
+ if (!cell.InBounds(pawn.Map))
+ continue;
+
+ foreach (Thing thing in cell.GetThingList(pawn.Map))
+ {
+ if (thing is Pawn targetPawn && IsValidMeleeTarget(targetPawn))
+ {
+ pawn.meleeVerbs.TryMeleeAttack(targetPawn);
+ collideWithPawns = true;
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ private bool IsValidMeleeTarget(Pawn target)
+ {
+ return !target.ThreatDisabled(pawn) &&
+ pawn.HostileTo(target) &&
+ GenHostility.IsActiveThreatTo(target, pawn.Faction) &&
+ !pawn.ThreatDisabledBecauseNonAggressiveRoamer(target);
+ }
+
+ private void CheckRangedAttack()
+ {
+ if (!CanUseRangedWeapon())
+ return;
+
+ Verb verb = pawn.CurrentEffectiveVerb;
+ if (verb == null || verb.verbProps.IsMeleeAttack)
+ return;
+
+ Thing shootTarget = FindRangedTarget();
+ if (shootTarget != null)
+ {
+ pawn.TryStartAttack(shootTarget);
+ collideWithPawns = true;
+ }
+ }
+
+ private bool CanUseRangedWeapon()
+ {
+ if (!CombatExtension?.canUseRangedWeapon ?? false)
+ return false;
+
+ // 检查武器
+ if (pawn.equipment?.Primary == null || !pawn.equipment.Primary.def.IsRangedWeapon)
+ return false;
+
+ // 检查 FireAtWill 设置
+ if (pawn.drafter != null && !pawn.drafter.FireAtWill)
+ return false;
+
+ return true;
+ }
+
+ private Thing FindRangedTarget()
+ {
+ int searchRadius = CombatExtension?.attackSearchRadius ?? 25;
+
+ TargetScanFlags flags = TargetScanFlags.NeedLOSToAll |
+ TargetScanFlags.NeedThreat |
+ TargetScanFlags.NeedAutoTargetable;
+
+ if (pawn.CurrentEffectiveVerb?.IsIncendiary_Ranged() == true)
+ {
+ flags |= TargetScanFlags.NeedNonBurning;
+ }
+
+ return (Thing)AttackTargetFinder.BestShootTargetFromCurrentPosition(
+ pawn, flags, null, 0f, searchRadius);
+ }
+
+ private Thing FindNearestEnemy()
+ {
+ int searchRadius = CombatExtension?.attackSearchRadius ?? 25;
+
+ return (Thing)AttackTargetFinder.BestAttackTarget(
+ pawn,
+ TargetScanFlags.NeedThreat,
+ x => x is Pawn p && pawn.HostileTo(p),
+ 0f, searchRadius,
+ default,
+ float.MaxValue,
+ canTakeTargets: true);
+ }
+
+ public override string GetReport()
+ {
+ return "WULA_StandingGuard".Translate(); // 自定义报告文本
+ }
+ }
+}
diff --git a/Source/WulaFallenEmpire/Pawn/WULA_AutonomousMech/JobExtension_AutonomousCombat.cs b/Source/WulaFallenEmpire/Pawn/WULA_AutonomousMech/JobExtension_AutonomousCombat.cs
new file mode 100644
index 00000000..e742ec89
--- /dev/null
+++ b/Source/WulaFallenEmpire/Pawn/WULA_AutonomousMech/JobExtension_AutonomousCombat.cs
@@ -0,0 +1,14 @@
+// JobExtension_AutonomousCombat.cs
+using Verse;
+
+namespace WulaFallenEmpire
+{
+ public class JobExtension_AutonomousCombat : DefModExtension
+ {
+ public bool canUseRangedWeapon = true;
+ public bool autoAttackEnabled = true;
+ public int attackSearchRadius = 25;
+ public bool ignoreWorkTags = true;
+ public bool forceFireAtWill = true;
+ }
+}
diff --git a/Source/WulaFallenEmpire/Pawn/WULA_AutonomousMech/JobGiver_AutonomousCombat.cs b/Source/WulaFallenEmpire/Pawn/WULA_AutonomousMech/JobGiver_AutonomousCombat.cs
new file mode 100644
index 00000000..b4e9715f
--- /dev/null
+++ b/Source/WulaFallenEmpire/Pawn/WULA_AutonomousMech/JobGiver_AutonomousCombat.cs
@@ -0,0 +1,42 @@
+// JobGiver_AutonomousCombat.cs
+using RimWorld;
+using Verse;
+using Verse.AI;
+
+namespace WulaFallenEmpire
+{
+ public class JobGiver_AutonomousCombat : ThinkNode_JobGiver
+ {
+ public float priority = 8f;
+ public int expiryInterval = 30;
+
+ public override float GetPriority(Pawn pawn)
+ {
+ // 只有在征召状态下才有优先级
+ if (pawn.drafter?.Drafted == true &&
+ pawn.GetComp()?.CanWorkAutonomously == true)
+ {
+ return priority;
+ }
+ return 0f;
+ }
+
+ protected override Job TryGiveJob(Pawn pawn)
+ {
+ // 确保是自主机械族且被征召
+ var comp = pawn.GetComp();
+ if (comp?.CanWorkAutonomously != true || pawn.drafter?.Drafted != true)
+ return null;
+
+ // 创建自主战斗工作
+ Job job = JobMaker.MakeJob(DefDatabase.GetNamed("WULA_AutonomousWaitCombat"));
+ job.expiryInterval = expiryInterval;
+ job.checkOverrideOnDamage = true;
+
+ // 设置工作标签,确保不会被其他工作干扰
+ pawn.mindState?.prioritizedWork?.Clear();
+
+ return job;
+ }
+ }
+}
diff --git a/Source/WulaFallenEmpire/Pawn/WULA_AutonomousMech/JobGiver_AutonomousWaitCombat.cs b/Source/WulaFallenEmpire/Pawn/WULA_AutonomousMech/JobGiver_AutonomousWaitCombat.cs
new file mode 100644
index 00000000..fcd4588f
--- /dev/null
+++ b/Source/WulaFallenEmpire/Pawn/WULA_AutonomousMech/JobGiver_AutonomousWaitCombat.cs
@@ -0,0 +1,37 @@
+// JobGiver_AutonomousWaitCombat.cs
+using RimWorld;
+using Verse;
+using Verse.AI;
+
+namespace WulaFallenEmpire
+{
+ public class JobGiver_AutonomousWaitCombat : ThinkNode_JobGiver
+ {
+ public bool canUseRangedWeapon = true;
+
+ public override float GetPriority(Pawn pawn)
+ {
+ // 只有在征召状态下才有高优先级
+ if (pawn.drafter?.Drafted == true)
+ {
+ return 9.5f; // 比常规工作低,但比空闲高
+ }
+ return 0f;
+ }
+
+ protected override Job TryGiveJob(Pawn pawn)
+ {
+ // 只有在征召状态下才使用 Wait_Combat
+ if (pawn.drafter?.Drafted == true &&
+ pawn.GetComp()?.CanWorkAutonomously == true)
+ {
+ Job job = JobMaker.MakeJob(JobDefOf.Wait_Combat);
+ job.canUseRangedWeapon = canUseRangedWeapon;
+ job.expiryInterval = 30; // 短时间,便于重新评估
+ return job;
+ }
+
+ return null;
+ }
+ }
+}
diff --git a/Source/WulaFallenEmpire/Pawn/WULA_AutonomousMech/ThinkNode_ConditionalNeedRecharge.cs b/Source/WulaFallenEmpire/Pawn/WULA_AutonomousMech/ThinkNode_ConditionalNeedRecharge.cs
new file mode 100644
index 00000000..a7f1dca1
--- /dev/null
+++ b/Source/WulaFallenEmpire/Pawn/WULA_AutonomousMech/ThinkNode_ConditionalNeedRecharge.cs
@@ -0,0 +1,60 @@
+using RimWorld;
+using Verse;
+using Verse.AI;
+
+namespace WulaFallenEmpire
+{
+ // 检查机械族是否需要充电
+ public class ThinkNode_ConditionalNeedRecharge : ThinkNode_Conditional
+ {
+ public float energyThreshold = 0.3f;
+
+ protected override bool Satisfied(Pawn pawn)
+ {
+ if (pawn == null || pawn.Dead || pawn.Downed)
+ return false;
+
+ var energyNeed = pawn.needs?.TryGetNeed();
+ if (energyNeed == null)
+ return false;
+
+ return energyNeed.CurLevelPercentage < energyThreshold;
+ }
+ }
+
+ // 检查机械族是否紧急需要充电
+ public class ThinkNode_ConditionalEmergencyRecharge : ThinkNode_Conditional
+ {
+ public float emergencyThreshold = 0.1f;
+
+ protected override bool Satisfied(Pawn pawn)
+ {
+ if (pawn == null || pawn.Dead || pawn.Downed)
+ return false;
+
+ var energyNeed = pawn.needs?.TryGetNeed();
+ if (energyNeed == null)
+ return false;
+
+ return energyNeed.CurLevelPercentage < emergencyThreshold;
+ }
+ }
+
+ // 检查机械族是否充满电
+ public class ThinkNode_ConditionalFullyCharged : ThinkNode_Conditional
+ {
+ public float fullChargeThreshold = 0.9f;
+
+ protected override bool Satisfied(Pawn pawn)
+ {
+ if (pawn == null || pawn.Dead || pawn.Downed)
+ return false;
+
+ var energyNeed = pawn.needs?.TryGetNeed();
+ if (energyNeed == null)
+ return false;
+
+ return energyNeed.CurLevelPercentage >= fullChargeThreshold;
+ }
+ }
+}
diff --git a/Source/WulaFallenEmpire/WulaFallenEmpire.csproj b/Source/WulaFallenEmpire/WulaFallenEmpire.csproj
index 400bd3cf..3eb5a034 100644
--- a/Source/WulaFallenEmpire/WulaFallenEmpire.csproj
+++ b/Source/WulaFallenEmpire/WulaFallenEmpire.csproj
@@ -105,9 +105,11 @@
+
+