299 lines
10 KiB
C#
299 lines
10 KiB
C#
using ArachnaeSwarm;
|
||
using RimWorld;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using UnityEngine;
|
||
using Verse;
|
||
|
||
namespace ArachnaeSwarmVerse
|
||
{
|
||
/// <summary>
|
||
/// 近战伤害反射组件的属性
|
||
/// </summary>
|
||
public class HediffCompProperties_ReflectMeleeDamage : HediffCompProperties
|
||
{
|
||
public float reflectMultiplier = 3.0f; // 反射倍数,默认300%
|
||
public bool showReflectionEffect = true; // 是否显示反射效果
|
||
public bool reflectOnlyMelee = true; // 是否只反射近战伤害
|
||
public bool includeToolBasedRanged = false; // 是否包含使用工具的远程伤害
|
||
public float minDamageToReflect = 0.1f; // 最小反射伤害阈值
|
||
|
||
public HediffCompProperties_ReflectMeleeDamage()
|
||
{
|
||
this.compClass = typeof(HediffComp_ReflectMeleeDamage);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 近战伤害反射组件
|
||
/// 当Pawn受到近战伤害时,将300%的伤害反射给攻击者
|
||
/// </summary>
|
||
public class HediffComp_ReflectMeleeDamage : HediffComp
|
||
{
|
||
private bool isProcessingReflection = false; // 防止递归调用
|
||
private int lastReflectionTick = -100; // 上次反射的tick
|
||
private const int MIN_TICKS_BETWEEN_REFLECTIONS = 2; // 最小反射间隔
|
||
|
||
public HediffCompProperties_ReflectMeleeDamage Props => (HediffCompProperties_ReflectMeleeDamage)props;
|
||
|
||
/// <summary>
|
||
/// 获取反射倍率
|
||
/// </summary>
|
||
public float ReflectMultiplier => Props.reflectMultiplier;
|
||
|
||
/// <summary>
|
||
/// 检查是否为近战伤害
|
||
/// 根据题目要求:所有damageinfo有tool的,视为近战伤害
|
||
/// </summary>
|
||
private bool IsMeleeDamage(DamageInfo dinfo)
|
||
{
|
||
// 如果有Tool,视为近战伤害
|
||
if (dinfo.Tool != null)
|
||
{
|
||
return true;
|
||
}
|
||
|
||
// 如果没有Tool,进一步检查武器类型
|
||
if (dinfo.Weapon != null)
|
||
{
|
||
// 检查是否为近战武器
|
||
if (dinfo.Weapon.IsMeleeWeapon)
|
||
{
|
||
return true;
|
||
}
|
||
|
||
// 如果设置为包含使用工具的远程伤害,且武器有工具定义
|
||
if (Props.includeToolBasedRanged && dinfo.Weapon.tools != null && dinfo.Weapon.tools.Count > 0)
|
||
{
|
||
return true;
|
||
}
|
||
}
|
||
|
||
// 默认情况下,不视为近战伤害
|
||
return false;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 检查是否应该反射此伤害
|
||
/// </summary>
|
||
private bool ShouldReflectDamage(DamageInfo dinfo, Pawn pawn)
|
||
{
|
||
// 防止递归调用
|
||
if (isProcessingReflection)
|
||
{
|
||
return false;
|
||
}
|
||
|
||
// 检查最小伤害阈值
|
||
if (dinfo.Amount < Props.minDamageToReflect)
|
||
{
|
||
return false;
|
||
}
|
||
|
||
// 检查是否只反射近战伤害
|
||
if (Props.reflectOnlyMelee && !IsMeleeDamage(dinfo))
|
||
{
|
||
return false;
|
||
}
|
||
|
||
// 检查伤害来源
|
||
if (dinfo.Instigator == null || dinfo.Instigator == pawn)
|
||
{
|
||
return false;
|
||
}
|
||
|
||
// 检查最小反射间隔
|
||
if (Find.TickManager.TicksGame - lastReflectionTick < MIN_TICKS_BETWEEN_REFLECTIONS)
|
||
{
|
||
return false;
|
||
}
|
||
|
||
// 检查攻击者是否有效
|
||
Pawn attacker = dinfo.Instigator as Pawn;
|
||
if (attacker != null && (attacker.Dead || attacker.Destroyed))
|
||
{
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 反射伤害给攻击者
|
||
/// </summary>
|
||
private void ReflectDamageToAttacker(DamageInfo originalDinfo, Pawn pawn)
|
||
{
|
||
try
|
||
{
|
||
isProcessingReflection = true;
|
||
lastReflectionTick = Find.TickManager.TicksGame;
|
||
|
||
// 计算反射伤害
|
||
float reflectedAmount = originalDinfo.Amount * ReflectMultiplier;
|
||
|
||
// 确保有最小伤害
|
||
if (reflectedAmount < 1f)
|
||
{
|
||
reflectedAmount = 1f;
|
||
}
|
||
|
||
// 获取攻击者
|
||
Thing attacker = originalDinfo.Instigator;
|
||
if (attacker == null || attacker.Destroyed)
|
||
{
|
||
return;
|
||
}
|
||
|
||
// 创建反射伤害信息
|
||
DamageInfo reflectedDinfo = new DamageInfo(
|
||
def: originalDinfo.Def,
|
||
amount: reflectedAmount,
|
||
armorPenetration: originalDinfo.ArmorPenetrationInt,
|
||
angle: Rand.Range(0, 359),
|
||
instigator: pawn, // 反射者作为伤害来源
|
||
hitPart: null,
|
||
weapon: originalDinfo.Weapon,
|
||
category: DamageInfo.SourceCategory.ThingOrUnknown,
|
||
intendedTarget: attacker
|
||
);
|
||
|
||
// 设置反射伤害的特殊属性
|
||
reflectedDinfo.SetAllowDamagePropagation(true);
|
||
reflectedDinfo.SetIgnoreArmor(false);
|
||
|
||
// 如果有Tool,传递Tool信息(但标记为反射伤害)
|
||
if (originalDinfo.Tool != null)
|
||
{
|
||
reflectedDinfo.SetTool(originalDinfo.Tool);
|
||
}
|
||
|
||
// 记录日志
|
||
if (Prefs.DevMode)
|
||
{
|
||
Log.Message($"[ReflectMeleeDamage] {pawn.LabelShortCap} reflected {reflectedAmount:F1} damage " +
|
||
$"({originalDinfo.Amount:F1} × {ReflectMultiplier:F1}) to {attacker.LabelShortCap}");
|
||
}
|
||
|
||
// 对攻击者造成伤害
|
||
attacker.TakeDamage(reflectedDinfo);
|
||
|
||
// 显示反射效果
|
||
if (Props.showReflectionEffect)
|
||
{
|
||
ShowReflectionEffect(pawn, attacker);
|
||
}
|
||
|
||
// 发送消息
|
||
if (pawn.Faction == Faction.OfPlayer && attacker.Faction != Faction.OfPlayer)
|
||
{
|
||
Messages.Message(
|
||
"ASV_ReflectDamageMessage".Translate(
|
||
pawn.LabelShort,
|
||
attacker.LabelShort,
|
||
reflectedAmount.ToString("F0")
|
||
),
|
||
pawn,
|
||
MessageTypeDefOf.NeutralEvent
|
||
);
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log.Error($"[ReflectMeleeDamage] Error reflecting damage: {ex}");
|
||
}
|
||
finally
|
||
{
|
||
isProcessingReflection = false;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 显示反射效果
|
||
/// </summary>
|
||
private void ShowReflectionEffect(Pawn pawn, Thing attacker)
|
||
{
|
||
try
|
||
{
|
||
// 显示反弹粒子
|
||
if (pawn.Spawned && attacker.Spawned && pawn.Map == attacker.Map)
|
||
{
|
||
Vector3 startPos = pawn.DrawPos;
|
||
Vector3 endPos = attacker.DrawPos;
|
||
|
||
// 创建一个从反射者到攻击者的弹道效果
|
||
for (int i = 0; i < 3; i++)
|
||
{
|
||
MoteThrown mote = (MoteThrown)ThingMaker.MakeThing(ARA_ThingDefOf.Mote_SparkSimple, null);
|
||
mote.Scale = Rand.Range(0.5f, 0.8f);
|
||
mote.exactPosition = startPos + new Vector3(
|
||
Rand.Range(-0.3f, 0.3f),
|
||
0f,
|
||
Rand.Range(-0.3f, 0.3f)
|
||
);
|
||
mote.SetVelocity(
|
||
(endPos - startPos).normalized.x * Rand.Range(15f, 25f),
|
||
0f
|
||
);
|
||
GenSpawn.Spawn(mote, pawn.Position, pawn.Map);
|
||
}
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log.Error($"[ReflectMeleeDamage] Error showing reflection effect: {ex}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 在Pawn受到伤害后调用
|
||
/// </summary>
|
||
public override void Notify_PawnPostApplyDamage(DamageInfo dinfo, float totalDamageDealt)
|
||
{
|
||
base.Notify_PawnPostApplyDamage(dinfo, totalDamageDealt);
|
||
|
||
Pawn pawn = this.Pawn;
|
||
if (pawn == null || pawn.Dead || pawn.Destroyed)
|
||
{
|
||
return;
|
||
}
|
||
|
||
// 检查是否应该反射伤害
|
||
if (ShouldReflectDamage(dinfo, pawn))
|
||
{
|
||
// 反射伤害给攻击者
|
||
ReflectDamageToAttacker(dinfo, pawn);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取组件描述
|
||
/// </summary>
|
||
public override string CompTipStringExtra
|
||
{
|
||
get
|
||
{
|
||
string tip = "ASV_ReflectMeleeDamage_Tip".Translate(ReflectMultiplier.ToStringPercent());
|
||
|
||
if (Props.includeToolBasedRanged)
|
||
{
|
||
tip += "\n" + "ASV_ReflectIncludesToolRanged".Translate();
|
||
}
|
||
|
||
return tip;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取调试信息
|
||
/// </summary>
|
||
public override string CompDebugString()
|
||
{
|
||
return $"Reflect multiplier: {ReflectMultiplier:F1}x\n" +
|
||
$"Last reflection tick: {lastReflectionTick}\n" +
|
||
$"Min damage to reflect: {Props.minDamageToReflect}\n" +
|
||
$"Reflects only melee: {Props.reflectOnlyMelee}\n" +
|
||
$"Includes tool-based ranged: {Props.includeToolBasedRanged}";
|
||
}
|
||
}
|
||
}
|