冠军甲
This commit is contained in:
@@ -97,7 +97,7 @@ namespace WulaFallenEmpire
|
||||
// 如果无法找到有效位置,取消传送
|
||||
if (!CanTeleportTo(finalTargetCell, map))
|
||||
{
|
||||
Messages.Message("TeleportFailedNoValidLocation".Translate(), caster, MessageTypeDefOf.RejectInput);
|
||||
Messages.Message("WULA_TeleportFailedNoValidLocation".Translate(), caster, MessageTypeDefOf.RejectInput);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -218,7 +218,7 @@ namespace WulaFallenEmpire
|
||||
{
|
||||
if (showMessages)
|
||||
{
|
||||
Messages.Message("CannotTeleportToLocation".Translate(),
|
||||
Messages.Message("WULA_CannotTeleportToLocation".Translate(),
|
||||
new LookTargets(target.Cell, parent.pawn.Map),
|
||||
MessageTypeDefOf.RejectInput);
|
||||
}
|
||||
@@ -294,7 +294,7 @@ namespace WulaFallenEmpire
|
||||
{
|
||||
if (!CanHitTarget(target))
|
||||
{
|
||||
return "CannotTeleportToLocation".Translate();
|
||||
return "WULA_CannotTeleportToLocation".Translate();
|
||||
}
|
||||
return base.ExtraLabelMouseAttachment(target);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
using RimWorld;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Verse;
|
||||
|
||||
namespace WulaFallenEmpire
|
||||
{
|
||||
public class CompEquippableAbilities : ThingComp
|
||||
{
|
||||
public CompProperties_EquippableAbilities Props => (CompProperties_EquippableAbilities)props;
|
||||
|
||||
private Pawn wearer;
|
||||
private List<Ability> grantedAbilities = new List<Ability>();
|
||||
|
||||
public override void Notify_Equipped(Pawn pawn)
|
||||
{
|
||||
base.Notify_Equipped(pawn);
|
||||
wearer = pawn;
|
||||
GrantAbilities(pawn);
|
||||
}
|
||||
|
||||
public override void Notify_Unequipped(Pawn pawn)
|
||||
{
|
||||
base.Notify_Unequipped(pawn);
|
||||
RemoveAbilities(pawn);
|
||||
wearer = null;
|
||||
}
|
||||
|
||||
private void GrantAbilities(Pawn pawn)
|
||||
{
|
||||
if (pawn.abilities == null || Props.abilityDefs == null)
|
||||
return;
|
||||
|
||||
foreach (AbilityDef abilityDef in Props.abilityDefs)
|
||||
{
|
||||
if (!pawn.abilities.abilities.Any(a => a.def == abilityDef))
|
||||
{
|
||||
Ability ability = new Ability(pawn, abilityDef);
|
||||
pawn.abilities.GainAbility(abilityDef);
|
||||
grantedAbilities.Add(ability);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void RemoveAbilities(Pawn pawn)
|
||||
{
|
||||
if (pawn.abilities == null)
|
||||
return;
|
||||
|
||||
foreach (Ability ability in grantedAbilities)
|
||||
{
|
||||
pawn.abilities.RemoveAbility(ability.def);
|
||||
}
|
||||
grantedAbilities.Clear();
|
||||
}
|
||||
|
||||
public override string CompInspectStringExtra()
|
||||
{
|
||||
if (Props.abilityDefs != null && Props.abilityDefs.Count > 0)
|
||||
{
|
||||
return $"授予技能: {Props.abilityDefs.Count}";
|
||||
}
|
||||
return base.CompInspectStringExtra();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using RimWorld;
|
||||
using System.Collections.Generic;
|
||||
using Verse;
|
||||
|
||||
namespace WulaFallenEmpire
|
||||
{
|
||||
public class CompProperties_EquippableAbilities : CompProperties
|
||||
{
|
||||
public List<AbilityDef> abilityDefs;
|
||||
|
||||
public CompProperties_EquippableAbilities()
|
||||
{
|
||||
compClass = typeof(CompEquippableAbilities);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,439 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using RimWorld;
|
||||
using UnityEngine;
|
||||
using Verse;
|
||||
using Verse.Sound;
|
||||
|
||||
namespace WulaFallenEmpire
|
||||
{
|
||||
public class CompAbilityEffect_PullTarget : CompAbilityEffect
|
||||
{
|
||||
public static string PullUsedSignalTag = "CompAbilityEffect.PullUsed";
|
||||
|
||||
public new CompProperties_AbilityPullTarget Props => (CompProperties_AbilityPullTarget)props;
|
||||
|
||||
public override IEnumerable<PreCastAction> GetPreCastActions()
|
||||
{
|
||||
yield return new PreCastAction
|
||||
{
|
||||
action = delegate(LocalTargetInfo target, LocalTargetInfo dest)
|
||||
{
|
||||
Pawn caster = parent.pawn;
|
||||
Pawn targetPawn = target.Pawn;
|
||||
Map map = caster.Map;
|
||||
|
||||
if (targetPawn == null || !IsValidPullTarget(targetPawn))
|
||||
{
|
||||
Messages.Message("WULA_InvalidPullTarget".Translate(), caster, MessageTypeDefOf.RejectInput);
|
||||
return;
|
||||
}
|
||||
|
||||
// 在目标位置创建入口特效
|
||||
if (Props.customEntryFleck != null)
|
||||
{
|
||||
FleckMaker.Static(targetPawn.Position, map, Props.customEntryFleck);
|
||||
}
|
||||
else
|
||||
{
|
||||
FleckMaker.Static(targetPawn.Position, map, FleckDefOf.PsycastSkipFlashEntry);
|
||||
}
|
||||
|
||||
// 播放拉取音效
|
||||
SoundDefOf.Psycast_Skip_Entry.PlayOneShot(new TargetInfo(targetPawn.Position, map));
|
||||
|
||||
// 计算拉取目的地
|
||||
IntVec3 pullDestination = FindPullDestination(caster, targetPawn, map);
|
||||
|
||||
// 存储拉取目的地
|
||||
this.pullDestination = pullDestination;
|
||||
},
|
||||
ticksAwayFromCast = 5
|
||||
};
|
||||
}
|
||||
|
||||
private IntVec3 pullDestination = IntVec3.Invalid;
|
||||
|
||||
public override void Apply(LocalTargetInfo target, LocalTargetInfo dest)
|
||||
{
|
||||
base.Apply(target, dest);
|
||||
|
||||
Pawn caster = parent.pawn;
|
||||
Pawn targetPawn = target.Pawn;
|
||||
Map map = caster.Map;
|
||||
|
||||
if (targetPawn == null || !IsValidPullTarget(targetPawn))
|
||||
{
|
||||
Messages.Message("WULA_InvalidPullTarget".Translate(), caster, MessageTypeDefOf.RejectInput);
|
||||
return;
|
||||
}
|
||||
|
||||
// 使用存储的拉取目的地或重新计算
|
||||
IntVec3 finalDestination = this.pullDestination.IsValid ? this.pullDestination : FindPullDestination(caster, targetPawn, map);
|
||||
this.pullDestination = IntVec3.Invalid;
|
||||
|
||||
// 验证目的地
|
||||
finalDestination = ValidateAndAdjustDestination(finalDestination, targetPawn, map);
|
||||
|
||||
if (!CanTeleportTo(finalDestination, map))
|
||||
{
|
||||
Messages.Message("WULA_PullFailedNoValidLocation".Translate(), caster, MessageTypeDefOf.RejectInput);
|
||||
return;
|
||||
}
|
||||
|
||||
// 目标位置入口效果器
|
||||
EffecterDef entryEffecter = Props.customEntryEffecter ?? EffecterDefOf.Skip_Entry;
|
||||
Effecter entryEffect = entryEffecter.Spawn(targetPawn, map);
|
||||
parent.AddEffecterToMaintain(entryEffect, targetPawn.Position, 60);
|
||||
|
||||
// 目的地出口效果器
|
||||
EffecterDef exitEffecter = Props.customExitEffecter ?? EffecterDefOf.Skip_Exit;
|
||||
Effecter exitEffect = exitEffecter.Spawn(finalDestination, map);
|
||||
parent.AddEffecterToMaintain(exitEffect, finalDestination, 60);
|
||||
|
||||
// 执行传送(拉取)
|
||||
targetPawn.Position = finalDestination;
|
||||
targetPawn.Notify_Teleported();
|
||||
|
||||
// 如果是玩家阵营,解除战争迷雾
|
||||
if ((targetPawn.Faction == Faction.OfPlayer || targetPawn.IsPlayerControlled) && targetPawn.Position.Fogged(map))
|
||||
{
|
||||
FloodFillerFog.FloodUnfog(targetPawn.Position, map);
|
||||
}
|
||||
|
||||
// 拉取后眩晕目标
|
||||
targetPawn.stances.stunner.StunFor(Props.stunTicks.RandomInRange, caster, addBattleLog: true, showMote: true);
|
||||
|
||||
// 发送拉取信号
|
||||
SendPullUsedSignal(targetPawn.Position, caster);
|
||||
|
||||
// 播放到达时的喧嚣效果
|
||||
if (Props.destClamorType != null)
|
||||
{
|
||||
float adjustedRadius = Props.destClamorRadius * Props.effectScale;
|
||||
GenClamor.DoClamor(caster, finalDestination, adjustedRadius, Props.destClamorType);
|
||||
}
|
||||
|
||||
// 播放拉取成功音效
|
||||
SoundDefOf.Psycast_Skip_Exit.PlayOneShot(new TargetInfo(finalDestination, map));
|
||||
|
||||
// 记录拉取信息
|
||||
if (Prefs.DevMode)
|
||||
{
|
||||
Log.Message($"[PullTarget] {caster.Label} 将 {targetPawn.Label} 拉取到 {finalDestination}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查目标是否可以被拉取
|
||||
/// </summary>
|
||||
private bool IsValidPullTarget(Pawn target)
|
||||
{
|
||||
// 检查目标是否为Pawn
|
||||
if (target == null)
|
||||
return false;
|
||||
|
||||
// 检查体型限制
|
||||
if (target.BodySize > Props.maxTargetBodySize)
|
||||
{
|
||||
Messages.Message("WULA_TargetTooLarge".Translate(target.LabelShort, Props.maxTargetBodySize),
|
||||
parent.pawn, MessageTypeDefOf.RejectInput);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查目标是否死亡或倒下
|
||||
if (target.Dead || target.Downed)
|
||||
return false;
|
||||
|
||||
// 检查目标是否可被影响(根据派系关系)
|
||||
if (!Props.canPullHostile && target.HostileTo(parent.pawn.Faction))
|
||||
return false;
|
||||
|
||||
if (!Props.canPullNeutral && target.Faction != null && !target.HostileTo(parent.pawn.Faction) && target.Faction != parent.pawn.Faction)
|
||||
return false;
|
||||
|
||||
if (!Props.canPullFriendly && target.Faction == parent.pawn.Faction)
|
||||
return false;
|
||||
|
||||
// 检查特殊免疫状态
|
||||
if (target.GetComp<CompImmuneToPull>() != null)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 寻找拉取目的地(施法者附近的合适位置)
|
||||
/// </summary>
|
||||
private IntVec3 FindPullDestination(Pawn caster, Pawn target, Map map)
|
||||
{
|
||||
// 在施法者周围寻找合适的拉取位置
|
||||
IntVec3 center = caster.Position;
|
||||
int searchRadius = Props.pullDestinationSearchRadius;
|
||||
|
||||
// 优先选择施法者周围的空位
|
||||
for (int radius = 1; radius <= searchRadius; radius++)
|
||||
{
|
||||
foreach (IntVec3 cell in GenRadial.RadialCellsAround(center, radius, true))
|
||||
{
|
||||
if (cell.InBounds(map) &&
|
||||
CanTeleportTo(cell, map) &&
|
||||
cell != caster.Position && // 避免和目标重叠
|
||||
cell != target.Position)
|
||||
{
|
||||
// 检查该位置是否在施法者视线内(可选)
|
||||
if (!Props.requireLineOfSightToDestination || GenSight.LineOfSight(center, cell, map))
|
||||
{
|
||||
return cell;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 如果找不到合适位置,返回施法者位置(作为备选)
|
||||
return center;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证并调整拉取目的地
|
||||
/// </summary>
|
||||
private IntVec3 ValidateAndAdjustDestination(IntVec3 destination, Pawn target, Map map)
|
||||
{
|
||||
// 如果目的地不可传送,寻找替代位置
|
||||
if (!CanTeleportTo(destination, map))
|
||||
{
|
||||
IntVec3 adjustedCell = FindNearestValidTeleportPosition(destination, target, map, Props.maxPositionAdjustRadius);
|
||||
if (adjustedCell.IsValid)
|
||||
{
|
||||
return adjustedCell;
|
||||
}
|
||||
}
|
||||
|
||||
return destination;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 寻找最近的可行传送位置
|
||||
/// </summary>
|
||||
private IntVec3 FindNearestValidTeleportPosition(IntVec3 center, Pawn pawn, Map map, int maxRadius = 15)
|
||||
{
|
||||
// 首先检查中心点本身
|
||||
if (CanTeleportTo(center, map))
|
||||
return center;
|
||||
|
||||
// 在逐渐增大的半径内搜索
|
||||
for (int radius = 1; radius <= maxRadius; radius++)
|
||||
{
|
||||
int numCells = GenRadial.NumCellsInRadius(radius);
|
||||
for (int i = 0; i < numCells; i++)
|
||||
{
|
||||
IntVec3 cell = center + GenRadial.RadialPattern[i];
|
||||
if (cell.InBounds(map) && CanTeleportTo(cell, map))
|
||||
{
|
||||
return cell;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return IntVec3.Invalid;
|
||||
}
|
||||
|
||||
public override bool Valid(LocalTargetInfo target, bool showMessages = true)
|
||||
{
|
||||
Pawn targetPawn = target.Pawn;
|
||||
|
||||
if (targetPawn == null)
|
||||
{
|
||||
if (showMessages)
|
||||
{
|
||||
Messages.Message("WULA_MustTargetPawn".Translate(),
|
||||
new LookTargets(parent.pawn),
|
||||
MessageTypeDefOf.RejectInput);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IsValidPullTarget(targetPawn))
|
||||
{
|
||||
if (showMessages)
|
||||
{
|
||||
// 错误消息已经在IsValidPullTarget中显示
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查最小距离 - 新增:不允许对身边一格的单位释放
|
||||
float distance = target.Cell.DistanceTo(parent.pawn.Position);
|
||||
if (distance <= Props.minRange)
|
||||
{
|
||||
if (showMessages)
|
||||
{
|
||||
Messages.Message("WULA_TargetTooClose".Translate(Props.minRange),
|
||||
new LookTargets(parent.pawn),
|
||||
MessageTypeDefOf.RejectInput);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查最大距离
|
||||
if (distance > Props.range)
|
||||
{
|
||||
if (showMessages)
|
||||
{
|
||||
Messages.Message("WULA_TargetOutOfRange".Translate(Props.range),
|
||||
new LookTargets(parent.pawn),
|
||||
MessageTypeDefOf.RejectInput);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查视线(如果需要)
|
||||
if (Props.requireLineOfSight && !GenSight.LineOfSight(parent.pawn.Position, target.Cell, parent.pawn.Map))
|
||||
{
|
||||
if (showMessages)
|
||||
{
|
||||
Messages.Message("WULA_NoLineOfSight".Translate(),
|
||||
new LookTargets(parent.pawn),
|
||||
MessageTypeDefOf.RejectInput);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return base.Valid(target, showMessages);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查是否可以命中目标
|
||||
/// </summary>
|
||||
public bool CanHitTarget(LocalTargetInfo target)
|
||||
{
|
||||
Pawn targetPawn = target.Pawn;
|
||||
|
||||
if (targetPawn == null)
|
||||
return false;
|
||||
|
||||
// 检查距离
|
||||
float distance = target.Cell.DistanceTo(parent.pawn.Position);
|
||||
|
||||
// 新增:检查最小距离
|
||||
if (distance <= Props.minRange)
|
||||
return false;
|
||||
|
||||
if (Props.range > 0f && distance > Props.range)
|
||||
return false;
|
||||
|
||||
// 检查视线(如果需要)
|
||||
if (Props.requireLineOfSight && !GenSight.LineOfSight(parent.pawn.Position, target.Cell, parent.pawn.Map))
|
||||
return false;
|
||||
|
||||
// 检查目标有效性
|
||||
return IsValidPullTarget(targetPawn);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查是否可以传送到指定位置
|
||||
/// </summary>
|
||||
private bool CanTeleportTo(IntVec3 cell, Map map)
|
||||
{
|
||||
if (!cell.InBounds(map))
|
||||
return false;
|
||||
|
||||
// 检查战争迷雾
|
||||
if (!Props.canTeleportToFogged && cell.Fogged(map))
|
||||
return false;
|
||||
|
||||
// 检查屋顶
|
||||
if (!Props.canTeleportToRoofed && map.roofGrid.Roofed(cell))
|
||||
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;
|
||||
}
|
||||
|
||||
public override string ExtraLabelMouseAttachment(LocalTargetInfo target)
|
||||
{
|
||||
if (!CanHitTarget(target))
|
||||
{
|
||||
// 检查具体原因以提供更精确的错误信息
|
||||
Pawn targetPawn = target.Pawn;
|
||||
float distance = target.Cell.DistanceTo(parent.pawn.Position);
|
||||
|
||||
if (targetPawn == null)
|
||||
return "WULA_MustTargetPawn".Translate();
|
||||
|
||||
if (distance <= Props.minRange)
|
||||
return "WULA_TargetTooClose".Translate(Props.minRange);
|
||||
|
||||
if (Props.range > 0f && distance > Props.range)
|
||||
return "WULA_TargetOutOfRange".Translate(Props.range);
|
||||
|
||||
if (Props.requireLineOfSight && !GenSight.LineOfSight(parent.pawn.Position, target.Cell, parent.pawn.Map))
|
||||
return "WULA_NoLineOfSight".Translate();
|
||||
|
||||
return "WULA_CannotPullTarget".Translate();
|
||||
}
|
||||
return base.ExtraLabelMouseAttachment(target);
|
||||
}
|
||||
|
||||
public override void DrawEffectPreview(LocalTargetInfo target)
|
||||
{
|
||||
// 绘制目标高亮
|
||||
GenDraw.DrawTargetHighlight(target);
|
||||
|
||||
// 绘制拉取范围
|
||||
if (Props.range > 0)
|
||||
{
|
||||
GenDraw.DrawRadiusRing(parent.pawn.Position, Props.range);
|
||||
}
|
||||
|
||||
// 绘制最小范围环 - 新增:显示不允许释放的区域
|
||||
if (Props.minRange > 0)
|
||||
{
|
||||
GenDraw.DrawRadiusRing(parent.pawn.Position, Props.minRange, Color.red);
|
||||
}
|
||||
|
||||
// 预览拉取目的地(如果可能)
|
||||
Pawn targetPawn = target.Pawn;
|
||||
if (targetPawn != null && IsValidPullTarget(targetPawn))
|
||||
{
|
||||
IntVec3 destination = FindPullDestination(parent.pawn, targetPawn, parent.pawn.Map);
|
||||
if (destination.IsValid)
|
||||
{
|
||||
GenDraw.DrawCircleOutline(destination.ToVector3Shifted(), 1f, SimpleColor.Green);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void SendPullUsedSignal(LocalTargetInfo target, Thing initiator)
|
||||
{
|
||||
Find.SignalManager.SendSignal(new Signal(PullUsedSignalTag, target.Named("POSITION"), initiator.Named("SUBJECT")));
|
||||
}
|
||||
}
|
||||
|
||||
// 可选的免疫组件
|
||||
public class CompImmuneToPull : ThingComp
|
||||
{
|
||||
// 简单的标记组件,表示该单位免疫拉取效果
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
using RimWorld;
|
||||
using Verse;
|
||||
|
||||
namespace WulaFallenEmpire
|
||||
{
|
||||
public class CompProperties_AbilityPullTarget : CompProperties_AbilityEffect
|
||||
{
|
||||
public float range = 12f;
|
||||
public float minRange = 1f; // 新增:最小拉取距离,默认为1格
|
||||
public IntRange stunTicks = new IntRange(30, 60);
|
||||
public float maxTargetBodySize = 2f; // 最大可拉取目标的体型
|
||||
|
||||
// 拉取目的地设置
|
||||
public int pullDestinationSearchRadius = 3; // 在施法者周围搜索拉取目的地的半径
|
||||
public bool requireLineOfSightToDestination = false; // 是否需要视线到拉取目的地
|
||||
|
||||
// 到达时的喧嚣效果
|
||||
public ClamorDef destClamorType;
|
||||
public float destClamorRadius = 2f;
|
||||
|
||||
// 拉取限制
|
||||
public bool requireLineOfSight = true;
|
||||
public bool canTeleportToFogged = true;
|
||||
public bool canTeleportToRoofed = true;
|
||||
|
||||
// 派系关系限制
|
||||
public bool canPullHostile = true;
|
||||
public bool canPullNeutral = true;
|
||||
public bool canPullFriendly = false; // 默认不拉取友军
|
||||
|
||||
// 自定义效果器
|
||||
public EffecterDef customEntryEffecter;
|
||||
public EffecterDef customExitEffecter;
|
||||
public FleckDef customEntryFleck;
|
||||
public FleckDef customExitFleck;
|
||||
public float effectScale = 1.0f; // 效果缩放比例
|
||||
|
||||
// 位置调整设置
|
||||
public int maxPositionAdjustRadius = 15; // 最大位置调整半径
|
||||
public bool allowPositionAdjustment = true; // 是否允许自动调整位置
|
||||
|
||||
public CompProperties_AbilityPullTarget()
|
||||
{
|
||||
compClass = typeof(CompAbilityEffect_PullTarget);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -53,14 +53,14 @@ namespace WulaFallenEmpire
|
||||
{
|
||||
if (storedMechanoidCount >= Props.maxStorageCapacity)
|
||||
{
|
||||
Messages.Message("回收器已满", MessageTypeDefOf.RejectInput);
|
||||
Messages.Message("WULA_RecyclerFull".Translate(), MessageTypeDefOf.RejectInput);
|
||||
return;
|
||||
}
|
||||
|
||||
storedMechanoidCount++;
|
||||
mech.Destroy(); // 直接销毁,不存储实例
|
||||
|
||||
Messages.Message($"机械族 {mech.LabelCap} 已回收 (当前: {storedMechanoidCount}/{Props.maxStorageCapacity})",
|
||||
Messages.Message("WULA_MechRecycled".Translate(mech.LabelCap, storedMechanoidCount, Props.maxStorageCapacity),
|
||||
MessageTypeDefOf.PositiveEvent);
|
||||
|
||||
// 通知转换组件存储更新
|
||||
@@ -100,7 +100,7 @@ namespace WulaFallenEmpire
|
||||
{
|
||||
if (storedMechanoidCount == 0)
|
||||
{
|
||||
Messages.Message("没有可用的机械族进行转换", MessageTypeDefOf.RejectInput);
|
||||
Messages.Message("WULA_NoMechsToConvert".Translate(), MessageTypeDefOf.RejectInput);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -121,7 +121,7 @@ namespace WulaFallenEmpire
|
||||
{
|
||||
if (!ConsumeMechanoids(count))
|
||||
{
|
||||
Messages.Message("机械族数量不足", MessageTypeDefOf.RejectInput);
|
||||
Messages.Message("WULA_NotEnoughMechs".Translate(), MessageTypeDefOf.RejectInput);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -143,7 +143,7 @@ namespace WulaFallenEmpire
|
||||
}
|
||||
|
||||
TrySpawnFromQueue();
|
||||
Messages.Message($"正在转换 {count} 个机械族为 {kindDef.LabelCap}", MessageTypeDefOf.PositiveEvent);
|
||||
Messages.Message("WULA_ConvertingMechs".Translate(count, kindDef.LabelCap), MessageTypeDefOf.PositiveEvent);
|
||||
}
|
||||
|
||||
private void TrySpawnFromQueue()
|
||||
@@ -194,15 +194,15 @@ namespace WulaFallenEmpire
|
||||
// 回收附近机械族按钮
|
||||
Command_Action recycleCommand = new Command_Action
|
||||
{
|
||||
defaultLabel = "回收附近机械族",
|
||||
defaultDesc = $"命令附近 {Props.recycleRange} 格内的机械族前来回收",
|
||||
defaultLabel = "WULA_RecycleNearbyMechs".Translate(),
|
||||
defaultDesc = "WULA_RecycleNearbyMechsDesc".Translate(Props.recycleRange),
|
||||
icon = ContentFinder<Texture2D>.Get("Wula/UI/Commands/WULA_RecycleNearbyMechanoids"),
|
||||
action = RecycleNearbyMechanoids
|
||||
};
|
||||
|
||||
if (storedMechanoidCount >= Props.maxStorageCapacity)
|
||||
{
|
||||
recycleCommand.Disable("储存器已满");
|
||||
recycleCommand.Disable("WULA_StorageFull".Translate());
|
||||
}
|
||||
|
||||
yield return recycleCommand;
|
||||
@@ -210,15 +210,15 @@ namespace WulaFallenEmpire
|
||||
// 生成机械族按钮
|
||||
Command_Action spawnCommand = new Command_Action
|
||||
{
|
||||
defaultLabel = "转换机械族",
|
||||
defaultDesc = $"将储存的机械族转换为其他单位 (当前: {storedMechanoidCount}/{Props.maxStorageCapacity})",
|
||||
defaultLabel = "WULA_ConvertMechs".Translate(),
|
||||
defaultDesc = "WULA_ConvertMechsDesc".Translate(storedMechanoidCount, Props.maxStorageCapacity),
|
||||
icon = ContentFinder<Texture2D>.Get("Wula/UI/Commands/WULA_ConvertMechanoids"),
|
||||
action = OpenSpawnInterface
|
||||
};
|
||||
|
||||
if (storedMechanoidCount == 0)
|
||||
{
|
||||
spawnCommand.Disable("没有可用的机械族");
|
||||
spawnCommand.Disable("WULA_NoAvailableMechs".Translate());
|
||||
}
|
||||
|
||||
yield return spawnCommand;
|
||||
@@ -229,7 +229,7 @@ namespace WulaFallenEmpire
|
||||
{
|
||||
if (storedMechanoidCount >= Props.maxStorageCapacity)
|
||||
{
|
||||
Messages.Message("储存器已满", MessageTypeDefOf.RejectInput);
|
||||
Messages.Message("WULA_StorageFull".Translate(), MessageTypeDefOf.RejectInput);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -237,7 +237,7 @@ namespace WulaFallenEmpire
|
||||
|
||||
if (nearbyMechs.Count == 0)
|
||||
{
|
||||
Messages.Message("附近没有可回收的机械族", MessageTypeDefOf.RejectInput);
|
||||
Messages.Message("WULA_NoNearbyRecyclableMechs".Translate(), MessageTypeDefOf.RejectInput);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -250,7 +250,7 @@ namespace WulaFallenEmpire
|
||||
}
|
||||
}
|
||||
|
||||
Messages.Message($"已命令 {assignedCount} 个机械族前来回收", MessageTypeDefOf.PositiveEvent);
|
||||
Messages.Message("WULA_MechsOrderedToRecycle".Translate(assignedCount), MessageTypeDefOf.PositiveEvent);
|
||||
}
|
||||
|
||||
private List<Pawn> FindNearbyRecyclableMechanoids()
|
||||
@@ -312,7 +312,7 @@ namespace WulaFallenEmpire
|
||||
stringBuilder.Append(baseString);
|
||||
}
|
||||
|
||||
string storedInfo = $"储存机械族: {storedMechanoidCount}/{Props.maxStorageCapacity}";
|
||||
string storedInfo = "WULA_StoredMechs".Translate(storedMechanoidCount, Props.maxStorageCapacity);
|
||||
|
||||
if (stringBuilder.Length > 0)
|
||||
stringBuilder.AppendLine();
|
||||
@@ -322,7 +322,7 @@ namespace WulaFallenEmpire
|
||||
if (IsCooldownActive)
|
||||
{
|
||||
stringBuilder.AppendLine();
|
||||
stringBuilder.Append($"转换冷却: {GetRemainingCooldownHours():F1} 小时");
|
||||
stringBuilder.Append("WULA_TransformCooldown".Translate(GetRemainingCooldownHours().ToString("F1")));
|
||||
}
|
||||
|
||||
return stringBuilder.ToString();
|
||||
|
||||
@@ -9,8 +9,7 @@ namespace WulaFallenEmpire
|
||||
{
|
||||
private CompProperties_TransformAtFullCapacity Props => (CompProperties_TransformAtFullCapacity)props;
|
||||
|
||||
// 存储转换前的计数,用于恢复
|
||||
private int storedCountAtTransform = 0;
|
||||
// 移除存储计数的字段,不再进行数量传递
|
||||
|
||||
public Building_MechanoidRecycler Recycler => parent as Building_MechanoidRecycler;
|
||||
public bool IsCooldownActive => Recycler?.IsCooldownActive ?? false;
|
||||
@@ -24,7 +23,7 @@ namespace WulaFallenEmpire
|
||||
public override void PostExposeData()
|
||||
{
|
||||
base.PostExposeData();
|
||||
Scribe_Values.Look(ref storedCountAtTransform, "storedCountAtTransform", 0);
|
||||
// 移除存储计数的保存
|
||||
}
|
||||
|
||||
public override IEnumerable<Gizmo> CompGetGizmosExtra()
|
||||
@@ -33,7 +32,7 @@ namespace WulaFallenEmpire
|
||||
{
|
||||
Command_Action command = new Command_Action
|
||||
{
|
||||
defaultLabel = Props.gizmoLabel,
|
||||
defaultLabel = Props.gizmoLabel.Translate(),
|
||||
defaultDesc = GetGizmoDescription(),
|
||||
icon = GetGizmoIcon(),
|
||||
action = TransformToPawn
|
||||
@@ -42,11 +41,11 @@ namespace WulaFallenEmpire
|
||||
// 禁用条件
|
||||
if (IsCooldownActive)
|
||||
{
|
||||
command.Disable($"建筑刚部署,需要等待 {Recycler.GetRemainingCooldownHours():F1} 小时后才能转换");
|
||||
command.Disable("WULA_BuildingCooldown".Translate(Recycler.GetRemainingCooldownHours().ToString("F1")));
|
||||
}
|
||||
else if (!IsAtFullCapacity)
|
||||
{
|
||||
command.Disable($"需要储存 {Props.requiredCapacity} 个机械族,当前: {Recycler.StoredCount}/{Props.requiredCapacity}");
|
||||
command.Disable("WULA_NeedMoreMechs".Translate(Props.requiredCapacity, Recycler.StoredCount, Props.requiredCapacity));
|
||||
}
|
||||
|
||||
yield return command;
|
||||
@@ -55,12 +54,13 @@ namespace WulaFallenEmpire
|
||||
|
||||
private string GetGizmoDescription()
|
||||
{
|
||||
string desc = Props.gizmoDesc;
|
||||
string desc = Props.gizmoDesc.Translate();
|
||||
if (IsCooldownActive)
|
||||
{
|
||||
desc += $"\n\n冷却时间剩余: {Recycler.GetRemainingCooldownHours():F1} 小时";
|
||||
desc += "\n\n" + "WULA_CooldownRemaining".Translate(Recycler.GetRemainingCooldownHours().ToString("F1"));
|
||||
}
|
||||
desc += $"\n目标单位: {Props.targetPawnKind.LabelCap}";
|
||||
desc += "\n" + "WULA_TargetUnit".Translate(Props.targetPawnKind.LabelCap);
|
||||
desc += "\n" + "WULA_MechsRequired".Translate(Props.requiredCapacity);
|
||||
return desc;
|
||||
}
|
||||
|
||||
@@ -92,13 +92,10 @@ namespace WulaFallenEmpire
|
||||
IntVec3 position = parent.Position;
|
||||
Faction faction = parent.Faction;
|
||||
|
||||
// 存储当前的机械族计数(用于恢复)
|
||||
storedCountAtTransform = Recycler.StoredCount;
|
||||
|
||||
// 消耗存储的机械族
|
||||
if (!Recycler.ConsumeMechanoids(Props.requiredCapacity))
|
||||
{
|
||||
Messages.Message("机械族数量不足", MessageTypeDefOf.RejectInput);
|
||||
Messages.Message("WULA_NotEnoughMechs".Translate(), MessageTypeDefOf.RejectInput);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -117,11 +114,12 @@ namespace WulaFallenEmpire
|
||||
|
||||
Pawn newPawn = PawnGenerator.GeneratePawn(request);
|
||||
|
||||
// 添加转换组件并设置恢复数据
|
||||
// 添加转换组件,只传递建筑定义,不传递数量
|
||||
var transformComp = newPawn.GetComp<CompTransformIntoBuilding>();
|
||||
if (transformComp != null)
|
||||
{
|
||||
transformComp.SetRestoreData(parent.def, storedCountAtTransform);
|
||||
// 只设置建筑定义,不设置恢复数量
|
||||
transformComp.SetRestoreData(parent.def);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -135,7 +133,8 @@ namespace WulaFallenEmpire
|
||||
transformComp.props = compProps;
|
||||
newPawn.AllComps.Add(transformComp);
|
||||
transformComp.Initialize(compProps);
|
||||
transformComp.SetRestoreData(parent.def, storedCountAtTransform);
|
||||
// 只设置建筑定义,不设置恢复数量
|
||||
transformComp.SetRestoreData(parent.def);
|
||||
}
|
||||
|
||||
// 移除建筑
|
||||
@@ -150,7 +149,7 @@ namespace WulaFallenEmpire
|
||||
Find.Selector.Select(newPawn);
|
||||
}
|
||||
|
||||
Messages.Message($"{parent.Label} 已转换为 {newPawn.LabelCap}", MessageTypeDefOf.PositiveEvent);
|
||||
Messages.Message("WULA_BuildingTransformedToPawn".Translate(parent.Label, newPawn.LabelCap), MessageTypeDefOf.PositiveEvent);
|
||||
|
||||
// 播放转换效果
|
||||
PlayTransformEffects(position, map);
|
||||
|
||||
@@ -11,9 +11,8 @@ namespace WulaFallenEmpire
|
||||
private CompProperties_TransformIntoBuilding Props => (CompProperties_TransformIntoBuilding)props;
|
||||
private Pawn Pawn => (Pawn)parent;
|
||||
|
||||
// 恢复数据
|
||||
// 恢复数据 - 只存储建筑定义,不存储数量
|
||||
private ThingDef restoreBuildingDef;
|
||||
private int restoreMechanoidCount;
|
||||
|
||||
// 缓存校验结果
|
||||
private bool? lastValidationResult = null;
|
||||
@@ -29,14 +28,13 @@ namespace WulaFallenEmpire
|
||||
{
|
||||
base.PostExposeData();
|
||||
Scribe_Defs.Look(ref restoreBuildingDef, "restoreBuildingDef");
|
||||
Scribe_Values.Look(ref restoreMechanoidCount, "restoreMechanoidCount", 0);
|
||||
// 移除存储数量的保存
|
||||
}
|
||||
|
||||
// 设置恢复数据
|
||||
public void SetRestoreData(ThingDef buildingDef, int mechanoidCount)
|
||||
// 设置恢复数据 - 只设置建筑定义
|
||||
public void SetRestoreData(ThingDef buildingDef)
|
||||
{
|
||||
restoreBuildingDef = buildingDef;
|
||||
restoreMechanoidCount = mechanoidCount;
|
||||
}
|
||||
|
||||
public override IEnumerable<Gizmo> CompGetGizmosExtra()
|
||||
@@ -45,7 +43,7 @@ namespace WulaFallenEmpire
|
||||
{
|
||||
Command_Action command = new Command_Action
|
||||
{
|
||||
defaultLabel = Props.gizmoLabel,
|
||||
defaultLabel = Props.gizmoLabel.Translate(),
|
||||
defaultDesc = GetGizmoDescription(),
|
||||
icon = GetGizmoIcon(),
|
||||
action = TransformToBuilding
|
||||
@@ -67,18 +65,20 @@ namespace WulaFallenEmpire
|
||||
private string GetGizmoDescription()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.Append(Props.gizmoDesc);
|
||||
sb.Append(Props.gizmoDesc.Translate());
|
||||
|
||||
if (restoreBuildingDef != null)
|
||||
{
|
||||
sb.AppendLine();
|
||||
sb.AppendLine();
|
||||
sb.Append($"将恢复为: {restoreBuildingDef.LabelCap}");
|
||||
sb.Append("WULA_WillRestoreTo".Translate(restoreBuildingDef.LabelCap));
|
||||
|
||||
if (restoreMechanoidCount > 0)
|
||||
// 显示目标建筑的最大存储容量
|
||||
var recyclerProps = restoreBuildingDef.GetCompProperties<CompProperties_MechanoidRecycler>();
|
||||
if (recyclerProps != null)
|
||||
{
|
||||
sb.AppendLine();
|
||||
sb.Append($"恢复机械族储存: {restoreMechanoidCount}");
|
||||
sb.Append("WULA_MaxStorageCapacity".Translate(recyclerProps.maxStorageCapacity));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,11 +90,11 @@ namespace WulaFallenEmpire
|
||||
sb.AppendLine();
|
||||
if (isValid)
|
||||
{
|
||||
sb.Append("<color=green>✓ 当前位置可以放置建筑</color>");
|
||||
sb.Append("WULA_PositionValid".Translate());
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append($"<color=red>✗ {failReason}</color>");
|
||||
sb.Append("WULA_PositionInvalid".Translate(failReason));
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
@@ -118,7 +118,7 @@ namespace WulaFallenEmpire
|
||||
|
||||
if (parent == null || !parent.Spawned)
|
||||
{
|
||||
failReason = "单位未生成或已销毁";
|
||||
failReason = "WULA_UnitNotSpawned".Translate();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -126,7 +126,7 @@ namespace WulaFallenEmpire
|
||||
ThingDef buildingDef = restoreBuildingDef ?? Props.targetBuildingDef;
|
||||
if (buildingDef == null)
|
||||
{
|
||||
failReason = "无法确定目标建筑类型";
|
||||
failReason = "WULA_CannotDetermineBuildingType".Translate();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -166,7 +166,7 @@ namespace WulaFallenEmpire
|
||||
ThingDef buildingDef = restoreBuildingDef ?? Props.targetBuildingDef;
|
||||
if (buildingDef == null)
|
||||
{
|
||||
failReason = "无法确定目标建筑类型";
|
||||
failReason = "WULA_CannotDetermineBuildingType".Translate();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -185,7 +185,7 @@ namespace WulaFallenEmpire
|
||||
}
|
||||
}
|
||||
|
||||
failReason = "周围没有找到合适的放置位置";
|
||||
failReason = "WULA_NoSuitablePositionFound".Translate();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -202,7 +202,7 @@ namespace WulaFallenEmpire
|
||||
ThingDef buildingDef = restoreBuildingDef ?? Props.targetBuildingDef;
|
||||
if (buildingDef == null)
|
||||
{
|
||||
Messages.Message("无法确定目标建筑类型", MessageTypeDefOf.RejectInput);
|
||||
Messages.Message("WULA_CannotDetermineBuildingType".Translate(), MessageTypeDefOf.RejectInput);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -215,11 +215,11 @@ namespace WulaFallenEmpire
|
||||
if (TryFindNearbyValidPosition(out alternativePosition, out failReason))
|
||||
{
|
||||
desiredPosition = alternativePosition;
|
||||
Messages.Message($"将在附近位置 {desiredPosition} 部署建筑", MessageTypeDefOf.NeutralEvent);
|
||||
Messages.Message("WULA_DeployingAtNearbyPosition".Translate(desiredPosition), MessageTypeDefOf.NeutralEvent);
|
||||
}
|
||||
else
|
||||
{
|
||||
Messages.Message($"无法部署建筑: {failReason}", MessageTypeDefOf.RejectInput);
|
||||
Messages.Message("WULA_CannotDeployBuilding".Translate(failReason), MessageTypeDefOf.RejectInput);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -231,12 +231,8 @@ namespace WulaFallenEmpire
|
||||
Building newBuilding = (Building)GenSpawn.Spawn(buildingDef, desiredPosition, map, WipeMode.Vanish);
|
||||
newBuilding.SetFaction(faction);
|
||||
|
||||
// 恢复机械族计数
|
||||
var recycler = newBuilding as Building_MechanoidRecycler;
|
||||
if (recycler != null && restoreMechanoidCount > 0)
|
||||
{
|
||||
recycler.SetMechanoidCount(restoreMechanoidCount);
|
||||
}
|
||||
// 不再恢复机械族计数,新建筑为空状态
|
||||
// 如果需要,可以在这里设置初始状态,但不再传递之前的数量
|
||||
|
||||
// 添加建筑转换组件
|
||||
var transformComp = newBuilding.TryGetComp<CompTransformAtFullCapacity>();
|
||||
@@ -260,7 +256,7 @@ namespace WulaFallenEmpire
|
||||
Find.Selector.Select(newBuilding);
|
||||
}
|
||||
|
||||
Messages.Message($"{Pawn.LabelCap} 已部署为 {newBuilding.Label}", MessageTypeDefOf.PositiveEvent);
|
||||
Messages.Message("WULA_PawnDeployedAsBuilding".Translate(Pawn.LabelCap, newBuilding.Label), MessageTypeDefOf.PositiveEvent);
|
||||
|
||||
// 播放转换效果
|
||||
PlayTransformEffects(desiredPosition, map);
|
||||
|
||||
@@ -94,6 +94,10 @@
|
||||
<Compile Include="Ability\WULA_AbilityTeleportSelf\CompProperties_AbilityTeleportSelf.cs" />
|
||||
<Compile Include="Ability\WULA_AbilityStunKnockback\CompAbilityEffect_StunKnockback.cs" />
|
||||
<Compile Include="Ability\WULA_AbilityStunKnockback\CompProperties_StunKnockback.cs" />
|
||||
<Compile Include="Ability\WULA_EquippableAbilities\CompEquippableAbilities.cs" />
|
||||
<Compile Include="Ability\WULA_EquippableAbilities\CompProperties_EquippableAbilities.cs" />
|
||||
<Compile Include="Ability\WULA_PullTarget\CompAbilityEffect_PullTarget.cs" />
|
||||
<Compile Include="Ability\WULA_PullTarget\CompProperties_AbilityPullTarget.cs" />
|
||||
<Compile Include="BuildingComp\Building_ExtraGraphics.cs" />
|
||||
<Compile Include="BuildingComp\Building_MapObserver.cs" />
|
||||
<Compile Include="BuildingComp\WULA_BuildingBombardment\CompBuildingBombardment.cs" />
|
||||
|
||||
Reference in New Issue
Block a user