暂存
This commit is contained in:
290
Source/WulaFallenEmpire/DRMDamageShield.cs
Normal file
290
Source/WulaFallenEmpire/DRMDamageShield.cs
Normal file
@@ -0,0 +1,290 @@
|
||||
using RimWorld;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using Verse;
|
||||
using Verse.Sound;
|
||||
using HarmonyLib; // For AccessTools
|
||||
|
||||
namespace WulaFallenEmpire
|
||||
{
|
||||
// 自定义 CompProperties_Shield 变体
|
||||
public class DRMCompShieldProp : CompProperties
|
||||
{
|
||||
public int startingTicksToReset = 3200;
|
||||
public float minDrawSize = 1.2f;
|
||||
public float maxDrawSize = 1.55f;
|
||||
public float energyLossPerDamage = 0.033f;
|
||||
public float energyOnReset = 0.2f;
|
||||
public bool blocksRangedWeapons = true;
|
||||
|
||||
public DRMCompShieldProp()
|
||||
{
|
||||
compClass = typeof(DRMDamageShield);
|
||||
}
|
||||
}
|
||||
|
||||
[StaticConstructorOnStartup] // 确保在游戏启动时加载
|
||||
public class DRMDamageShield : ThingComp
|
||||
{
|
||||
// 从 Hediff_DamageShield 获取层数作为能量
|
||||
public float Energy
|
||||
{
|
||||
get
|
||||
{
|
||||
Hediff_DamageShield hediff = PawnOwner?.health?.hediffSet.GetFirstHediff<Hediff_DamageShield>();
|
||||
return hediff?.ShieldCharges ?? 0;
|
||||
}
|
||||
set
|
||||
{
|
||||
Hediff_DamageShield hediff = PawnOwner?.health?.hediffSet.GetFirstHediff<Hediff_DamageShield>();
|
||||
if (hediff != null)
|
||||
{
|
||||
hediff.ShieldCharges = (int)value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public float MaxEnergy
|
||||
{
|
||||
get
|
||||
{
|
||||
Hediff_DamageShield hediff = PawnOwner?.health?.hediffSet.GetFirstHediff<Hediff_DamageShield>();
|
||||
return hediff?.def.maxSeverity ?? 0;
|
||||
}
|
||||
set
|
||||
{
|
||||
// MaxEnergy 由 HediffDef 控制,这里不需要设置
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsActive = false; // 控制护盾是否激活,由 Hediff_DamageShield 管理
|
||||
|
||||
// 复制自 CompShield
|
||||
protected int ticksToReset = -1;
|
||||
protected int lastKeepDisplayTick = -9999;
|
||||
private Vector3 impactAngleVect;
|
||||
private int lastAbsorbDamageTick = -9999;
|
||||
|
||||
private const float MaxDamagedJitterDist = 0.05f;
|
||||
private const int JitterDurationTicks = 8;
|
||||
private int KeepDisplayingTicks = 1000;
|
||||
|
||||
// 获取原版 CompShield 的 BubbleMat
|
||||
private static readonly Material BubbleMat;
|
||||
|
||||
static DRMDamageShield()
|
||||
{
|
||||
// 使用 Harmony AccessTools 获取 CompShield 的私有静态字段 BubbleMat
|
||||
BubbleMat = (Material)AccessTools.Field(typeof(CompShield), "BubbleMat").GetValue(null);
|
||||
}
|
||||
|
||||
public DRMCompShieldProp Props => (DRMCompShieldProp)props;
|
||||
|
||||
public ShieldState ShieldState
|
||||
{
|
||||
get
|
||||
{
|
||||
if (PawnOwner == null || !IsActive || Energy <= 0)
|
||||
{
|
||||
return ShieldState.Disabled;
|
||||
}
|
||||
if (ticksToReset <= 0)
|
||||
{
|
||||
return ShieldState.Active;
|
||||
}
|
||||
return ShieldState.Resetting;
|
||||
}
|
||||
}
|
||||
|
||||
protected bool ShouldDisplay
|
||||
{
|
||||
get
|
||||
{
|
||||
Pawn pawnOwner = PawnOwner;
|
||||
if (pawnOwner == null || !pawnOwner.Spawned || pawnOwner.Dead || pawnOwner.Downed)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (pawnOwner.InAggroMentalState)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (pawnOwner.Drafted)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (pawnOwner.Faction.HostileTo(Faction.OfPlayer) && !pawnOwner.IsPrisoner)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (Find.TickManager.TicksGame < lastKeepDisplayTick + KeepDisplayingTicks)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected Pawn PawnOwner
|
||||
{
|
||||
get
|
||||
{
|
||||
return parent as Pawn;
|
||||
}
|
||||
}
|
||||
|
||||
public override void PostExposeData()
|
||||
{
|
||||
base.PostExposeData();
|
||||
Scribe_Values.Look(ref ticksToReset, "ticksToReset", -1);
|
||||
Scribe_Values.Look(ref lastKeepDisplayTick, "lastKeepDisplayTick", 0);
|
||||
Scribe_Values.Look(ref IsActive, "isActive", false);
|
||||
}
|
||||
|
||||
public override void CompTick()
|
||||
{
|
||||
base.CompTick();
|
||||
if (PawnOwner == null || !IsActive)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (ShieldState == ShieldState.Resetting)
|
||||
{
|
||||
ticksToReset--;
|
||||
if (ticksToReset <= 0)
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
}
|
||||
else if (ShieldState == ShieldState.Active)
|
||||
{
|
||||
// 护盾能量(层数)通过 Hediff_DamageShield 的 Tick 方法管理,这里不需要额外回复
|
||||
// 如果需要自动回复层数,可以在这里实现
|
||||
}
|
||||
}
|
||||
|
||||
public override void PostPreApplyDamage(ref DamageInfo dinfo, out bool absorbed)
|
||||
{
|
||||
absorbed = false;
|
||||
// 获取 Hediff_DamageShield 实例
|
||||
Hediff_DamageShield damageShield = PawnOwner?.health?.hediffSet.GetFirstHediff<Hediff_DamageShield>();
|
||||
|
||||
if (ShieldState != ShieldState.Active || !IsActive || damageShield == null || damageShield.ShieldCharges <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果是 EMP 伤害,且护盾没有 EMP 抗性(这里假设我们的护盾没有),则直接击穿
|
||||
// 为了简化,我们假设我们的次数盾没有 EMP 抗性,任何 EMP 伤害都会直接击穿
|
||||
if (dinfo.Def == DamageDefOf.EMP)
|
||||
{
|
||||
Energy = 0; // 能量归零
|
||||
Notify_ShieldBreak(); // 触发护盾击穿效果
|
||||
absorbed = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果是远程或爆炸伤害,且护盾阻挡这些类型
|
||||
if (Props.blocksRangedWeapons && (dinfo.Def.isRanged || dinfo.Def.isExplosive))
|
||||
{
|
||||
// 消耗一层护盾
|
||||
damageShield.ShieldCharges--;
|
||||
|
||||
// 触发护盾吸收效果
|
||||
Notify_DamageAbsorbed(dinfo);
|
||||
|
||||
// 护盾抖动效果
|
||||
PawnOwner.Drawer.renderer.wiggler.SetToCustomRotation(Rand.Range(-0.05f, 0.05f));
|
||||
// 移除文字提示
|
||||
// 移除粒子效果
|
||||
|
||||
absorbed = true; // 伤害被吸收
|
||||
|
||||
// 如果护盾层数归零,触发护盾击穿效果
|
||||
if (damageShield.ShieldCharges <= 0)
|
||||
{
|
||||
Notify_ShieldBreak();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Notify_DamageAbsorbed(DamageInfo dinfo)
|
||||
{
|
||||
// 复制自 CompShield.AbsorbedDamage
|
||||
SoundDefOf.EnergyShield_AbsorbDamage.PlayOneShot(new TargetInfo(PawnOwner.Position, PawnOwner.Map));
|
||||
impactAngleVect = Vector3Utility.HorizontalVectorFromAngle(dinfo.Angle);
|
||||
// 移除 FleckMaker.Static 和 FleckMaker.ThrowDustPuff
|
||||
lastAbsorbDamageTick = Find.TickManager.TicksGame;
|
||||
KeepDisplaying();
|
||||
}
|
||||
|
||||
public void Notify_ShieldBreak()
|
||||
{
|
||||
// 复制自 CompShield.Break
|
||||
if (parent.Spawned)
|
||||
{
|
||||
float scale = Mathf.Lerp(Props.minDrawSize, Props.maxDrawSize, Energy / MaxEnergy); // 根据当前能量比例调整大小
|
||||
EffecterDefOf.Shield_Break.SpawnAttached(parent, parent.MapHeld, scale);
|
||||
// 移除 FleckMaker.Static 和 FleckMaker.ThrowDustPuff
|
||||
}
|
||||
ticksToReset = Props.startingTicksToReset;
|
||||
// 护盾层数归零将由 Hediff_DamageShield 负责移除 Hediff
|
||||
}
|
||||
|
||||
private void Reset()
|
||||
{
|
||||
// 复制自 CompShield.Reset
|
||||
if (PawnOwner.Spawned)
|
||||
{
|
||||
SoundDefOf.EnergyShield_Reset.PlayOneShot(new TargetInfo(PawnOwner.Position, PawnOwner.Map));
|
||||
// 移除 FleckMaker.ThrowLightningGlow
|
||||
}
|
||||
ticksToReset = -1;
|
||||
// 能量恢复由 Hediff_DamageShield 负责,这里不需要设置 Energy
|
||||
// 这里可以添加逻辑,让 Hediff_DamageShield 恢复层数
|
||||
Hediff_DamageShield hediff = PawnOwner?.health?.hediffSet.GetFirstHediff<Hediff_DamageShield>();
|
||||
if (hediff != null)
|
||||
{
|
||||
hediff.ShieldCharges = (int)hediff.def.initialSeverity; // 重置时恢复到初始层数
|
||||
}
|
||||
}
|
||||
|
||||
public void KeepDisplaying()
|
||||
{
|
||||
lastKeepDisplayTick = Find.TickManager.TicksGame;
|
||||
}
|
||||
|
||||
public override void PostDraw()
|
||||
{
|
||||
base.PostDraw();
|
||||
Draw();
|
||||
}
|
||||
|
||||
private void Draw()
|
||||
{
|
||||
if (ShieldState == ShieldState.Active && ShouldDisplay)
|
||||
{
|
||||
float num = Mathf.Lerp(Props.minDrawSize, Props.maxDrawSize, Energy / MaxEnergy); // 根据当前能量比例调整大小
|
||||
Vector3 drawPos = PawnOwner.Drawer.DrawPos;
|
||||
drawPos.y = AltitudeLayer.MoteOverhead.AltitudeFor();
|
||||
int num2 = Find.TickManager.TicksGame - lastAbsorbDamageTick;
|
||||
if (num2 < JitterDurationTicks) // 使用 JitterDurationTicks
|
||||
{
|
||||
float num3 = (float)(JitterDurationTicks - num2) / JitterDurationTicks * MaxDamagedJitterDist; // 使用 MaxDamagedJitterDist
|
||||
drawPos += impactAngleVect * num3;
|
||||
num -= num3;
|
||||
}
|
||||
float angle = Rand.Range(0, 360);
|
||||
Vector3 s = new Vector3(num, 1f, num);
|
||||
Matrix4x4 matrix = default(Matrix4x4);
|
||||
matrix.SetTRS(drawPos, Quaternion.AngleAxis(angle, Vector3.up), s);
|
||||
Graphics.DrawMesh(MeshPool.plane10, matrix, BubbleMat, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
using HarmonyLib;
|
||||
using Verse;
|
||||
using System.Reflection;
|
||||
using UnityEngine; // Add UnityEngine for MoteMaker and Color
|
||||
|
||||
namespace WulaFallenEmpire.HarmonyPatches
|
||||
{
|
||||
[HarmonyPatch(typeof(Pawn_HealthTracker), "PreApplyDamage")]
|
||||
public static class DamageShieldPatch
|
||||
{
|
||||
// 使用 Harmony 的 AccessTools.Field 来获取私有的 pawn 字段
|
||||
private static readonly FieldInfo PawnField = AccessTools.Field(typeof(Pawn_HealthTracker), "pawn");
|
||||
|
||||
public static bool Prefix(Pawn_HealthTracker __instance, ref DamageInfo dinfo, out bool absorbed)
|
||||
{
|
||||
// 获取 Pawn 实例
|
||||
Pawn pawn = (Pawn)PawnField.GetValue(__instance);
|
||||
|
||||
// 查找 Pawn 身上是否有 Hediff_DamageShield
|
||||
Hediff_DamageShield damageShield = pawn.health.hediffSet.GetFirstHediff<Hediff_DamageShield>();
|
||||
|
||||
if (damageShield != null && damageShield.ShieldCharges > 0)
|
||||
{
|
||||
// 如果有护盾层数,则消耗一层并抵挡伤害
|
||||
damageShield.ShieldCharges--;
|
||||
// MoteMaker.ThrowText(pawn.DrawPos, pawn.Map, "伤害被护盾抵挡!", Color.cyan, 1.2f); // 视觉反馈,明确指定 Verse.MoteMaker,此行将被删除
|
||||
|
||||
// 设置 absorbed 为 true,表示伤害被完全吸收
|
||||
absorbed = true;
|
||||
|
||||
// 返回 false,阻止原始方法执行,即伤害不会被应用
|
||||
return false;
|
||||
}
|
||||
|
||||
// 如果没有护盾 Hediff 或者层数用尽,则正常处理伤害
|
||||
absorbed = false;
|
||||
return true; // 继续执行原始方法
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,20 +1,40 @@
|
||||
using Verse;
|
||||
using System; // Add for Activator
|
||||
using System.Text;
|
||||
using RimWorld;
|
||||
using UnityEngine;
|
||||
using HarmonyLib; // Needed for AccessTools if you use it here directly
|
||||
|
||||
namespace WulaFallenEmpire
|
||||
{
|
||||
public class Hediff_DamageShield : HediffWithComps
|
||||
{
|
||||
// 伤害抵挡层数
|
||||
// 直接将 severityInt 作为 ShieldCharges,这样外部对 severity 的修改会直接影响 ShieldCharges
|
||||
public int ShieldCharges
|
||||
{
|
||||
get => (int)severityInt;
|
||||
set => severityInt = value;
|
||||
}
|
||||
|
||||
// 获取或创建 DRMDamageShield 组件
|
||||
public DRMDamageShield ShieldComp
|
||||
{
|
||||
get
|
||||
{
|
||||
DRMDamageShield comp = pawn.GetComp<DRMDamageShield>();
|
||||
if (comp == null)
|
||||
{
|
||||
comp = (DRMDamageShield)Activator.CreateInstance(typeof(DRMDamageShield));
|
||||
comp.parent = pawn;
|
||||
comp.props = new DRMCompShieldProp(); // 确保有属性,即使是默认的
|
||||
pawn.AllComps.Add(comp);
|
||||
comp.Initialize(comp.props);
|
||||
}
|
||||
return comp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public override string LabelInBrackets
|
||||
{
|
||||
get
|
||||
@@ -54,10 +74,25 @@ namespace WulaFallenEmpire
|
||||
public override void PostAdd(DamageInfo? dinfo)
|
||||
{
|
||||
base.PostAdd(dinfo);
|
||||
// 初始层数由 XML 中的 initialSeverity 控制
|
||||
// 如果需要一个固定的初始值,可以在这里设置
|
||||
// 例如:如果 hediffDef.initialSeverity 设为 0,这里可以强制给一个默认值
|
||||
// 如果 initialSeverity 在 XML 中已经设置为 10,这里就不需要额外处理
|
||||
// 确保 Pawn 拥有 DRMCompShield 组件
|
||||
DRMDamageShield comp = ShieldComp; // 访问属性以确保组件被添加
|
||||
if (comp != null)
|
||||
{
|
||||
comp.IsActive = true; // 激活护盾组件
|
||||
// 能量同步将在 Tick() 中完成
|
||||
}
|
||||
}
|
||||
|
||||
public override void PostRemoved()
|
||||
{
|
||||
base.PostRemoved();
|
||||
// 当 Hediff 被移除时,移除对应的 DRMDamageShield 组件
|
||||
DRMDamageShield comp = pawn.GetComp<DRMDamageShield>();
|
||||
if (comp != null)
|
||||
{
|
||||
pawn.AllComps.Remove(comp);
|
||||
comp.IsActive = false; // 确保禁用
|
||||
}
|
||||
}
|
||||
|
||||
public override void Tick()
|
||||
@@ -68,6 +103,13 @@ namespace WulaFallenEmpire
|
||||
{
|
||||
pawn.health.RemoveHediff(this);
|
||||
}
|
||||
// 同步能量到 ShieldComp
|
||||
DRMDamageShield comp = pawn.GetComp<DRMDamageShield>(); // 每次 Tick 获取,确保是最新的
|
||||
if (comp != null && comp.IsActive)
|
||||
{
|
||||
comp.Energy = ShieldCharges;
|
||||
comp.MaxEnergy = (int)def.maxSeverity;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -183,7 +183,7 @@
|
||||
<Compile Include="Verb\Verb_ShootWeaponStealBeam.cs" />
|
||||
<Compile Include="Verb\Verb_ShootMeltBeam.cs" />
|
||||
<Compile Include="Hediff_DamageShield.cs" />
|
||||
<Compile Include="HarmonyPatches\DamageShieldPatch.cs" />
|
||||
<Compile Include="DRMDamageShield.cs" />
|
||||
<Compile Include="CompUseEffect_AddDamageShieldCharges.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
|
||||
Reference in New Issue
Block a user