2026-04-24 18:22:21 +08:00

160 lines
6.7 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* @Author: 白哉
* @Description:
* @Date: 2025年04月23日 星期三 21:04:18
* @Modify:
*/
using System.Collections.Generic;
using RuntimeData;
using System;
using Logic.CrashSight;
using Logic.Pool;
using TH1_Logic.Core;
using TH1_Anim.Fragments;
using TH1_Core.Managers;
using TH1_Renderer;
using TH1Renderer;
using UnityEngine;
using MemoryPack;
namespace Logic.Skill
{
public partial class SplashSkill : SkillBase
{
public SplashSkill()
{
IsPermanent = true;
TurnsLimit = 0;
Score = 4;
}
public override SkillType GetSkillType()
{
return SkillType.SPLASH;
}
public override void OnDamageOther(MapData mapData, SettlementInfo info)
{
if (info == null) return;
if (info.DamageType != DamageType.ActiveAttack) return;
if (info.DamageOrigin == null )return;//|| info.DamageTarget == null) return;
if (!mapData.GetPlayerDataByUnitId(info.DamageOrigin.Id, out var player)) return;
using var pooledSelfUnitList = THCollectionPool.GetHashSetHandle<UnitData>(out var selfUnitList);
mapData.GetUnitDataListByPlayerId(player.Id, selfUnitList);
if (info.DamageTargetGrid == null)
{
LogSystem.LogError($"SplashSkill info.DamageTarget is null");
return;
}
// 收集需要延迟刷新的单位。注意Renderer 必须在 DamageSettlement 前缓存,
// 否则死亡后 ROUnitMap 若被其他路径清理将无法再查到。
using var pooledUnitsToRefresh = THCollectionPool.GetListHandle<(UnitData unit, GridData grid, UnitRenderer renderer, int damage, bool wasKilled)>(out var unitsToRefresh);
var aroundBuf = RentAroundBuf();
mapData.GridMap.GetAroundGridData(1, 1, info.DamageTargetGrid, aroundBuf);
foreach (var grid in aroundBuf)
{
if (!grid.RealUnit(mapData, out var unit)) continue;
if (unit == info.DamageTarget) continue;
if (selfUnitList.Contains(unit)) continue;
if (mapData.IsLeagueOrJustBreakByUnit(unit.Id, info.DamageOrigin.Id)) continue;
// 计算攻击伤害
var damage = Table.Instance.CalcDamage(mapData, info.DamageOrigin, unit, damagePara:0.5f);
var targetRenderer = unit.Renderer(mapData);
Main.UnitLogic.DamageSettlement(mapData, info.DamageOrigin, unit, damage, DamageType.Splash);
bool wasKilled = !unit.IsAlive();
unitsToRefresh.Add((unit, grid, targetRenderer, damage, wasKilled));
}
ReturnAroundBuf();
// 视觉更新:延迟刷新所有溅射目标单位的显示
if (mapData != Main.MapData) return;
int phase = AnimPhase.AttackImpact + 50;
float projectileTime = Table.Instance.ProjectileTypeDataAssets.GetProjectileTypeInfo(ProjectileType.Bomb, out var pinfo)
? pinfo.AnimTime
: 0.5f;
var scope = PresentationManager.CurrentScope;
if (scope != null)
{
// 在攻击流程中:延迟注入到攻击 Fragment。Duration=0 让所有溅射目标在 Phase 250
// 同一帧并发触发受伤/死亡动画,不阻塞后续 phase。视觉动作本身是 fire-and-forget。
foreach (var (unit, grid, renderer, dmg, wasKilled) in unitsToRefresh)
{
if (MapRenderer.Instance == null) continue;
var g = grid;
var r = renderer;
var d = dmg;
var killed = wasKilled;
scope.Add(new FragmentStep
{
Phase = phase,
Duration = 0f,
Execute = () =>
{
if (!g.InMainSight()) return;
if (killed)
{
r?.Die();
g.Renderer(mapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Hurt));
g.Renderer(mapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Die));
g.Renderer(mapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Damage, d));
g.Renderer(mapData)?.InstantUpdateGrid();
}
else
{
r?.InstantUpdateUnit(false);
g.Renderer(mapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Hurt));
g.Renderer(mapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Damage, d));
g.Renderer(mapData)?.InstantUpdateGrid();
g.Renderer(mapData)?.SetBounceAnim(NeedRandomWait:true);
}
}
});
}
}
else
{
// 不在攻击流程中:使用原有 Timer 逻辑
foreach (var (unit, grid, renderer, dmg, wasKilled) in unitsToRefresh)
{
if (!grid.InMainSight()) continue;
var g = grid;
var r = renderer;
var d = dmg;
var killed = wasKilled;
Timer.Instance.TimerRegister(this, () =>
{
if (killed)
{
r?.Die();
g.Renderer(mapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Hurt));
g.Renderer(mapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Die));
g.Renderer(mapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Damage, d));
g.Renderer(mapData)?.InstantUpdateGrid();
}
else
{
r?.InstantUpdateUnit(false);
g.Renderer(mapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Hurt));
g.Renderer(mapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Damage, d));
g.Renderer(mapData)?.InstantUpdateGrid();
g.Renderer(mapData)?.SetBounceAnim(NeedRandomWait:true);
}
}, projectileTime, "SPLASHANIM TMP");
}
}
}
}
}