You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

389 lines
14 KiB

using System.Collections.Generic;
using CoreGame;
using GAS.Runtime;
using UnityEngine;
using xFrame;
namespace CoreGame.Render
{
public struct TexiaoShowParam
{
public int effectId; // 静态配置
public int element;
public Vector2 offset;
public Quaternion rotation;
public Vector3 scale;
public override string ToString()
{
var tbRenderEffect = RenderEffectDescMgr.Instance.GetConfig(effectId);
return "effectId: " + effectId + " name: " + tbRenderEffect?.name;
}
}
public class TxShowProcessParam : ISptPool
{
public int effectId;
public Vector2 offset;
public Quaternion rotation;
public Vector3 scale;
public Vector2 ghostPos; // 若eid的实体已回收,使用此位置播放
public bool isAttach;
public bool useHitPos;
public ReuseGoData reuseGoData;
public int eid;
public void Awake(ref TexiaoShowParam param)
{
effectId = param.effectId;
offset = param.offset;
rotation = param.rotation;
scale = param.scale;
}
public void Reset()
{
effectId = 0;
offset = Vector2.zero;
rotation = Quaternion.identity;
scale = Vector3.one;
ghostPos = Vector2.zero;
isAttach = false;
useHitPos = false;
reuseGoData = null;
eid = 0;
}
}
[Combat]
public class EffectShowProxy : ProxyBase
{
private readonly Dictionary<int, TxShowProcessParam> effectListDict = new();
private readonly List<SpriteRenderer> m_CacheRenderers = new();
private readonly List<Material> m_CacheMaterials = new();
private int m_IsMatPushed = 0;
public float effectScale = 1.0f;
protected override void Initialize(GameObject obj, CombatEntity ent)
{
}
public void ShowCastEffect(int effectId, List<int> seqList = null)
{
TexiaoShowParam param = default;
param.effectId = effectId;
param.scale = Vector3.one;
param.rotation = Quaternion.identity;
param.offset = Vector2.zero;
GA_ShowCastEffect(ref param, null, seqList);
}
public void ShowCastEffect(ref TexiaoShowParam param, in GameplayCueParameters cueData,
List<int> seqList = null)
{
if (cueData.sourceGaSpec != null)
{
GA_ShowCastEffect(ref param, cueData.sourceGaSpec.ctx, seqList);
return;
}
GE_ShowCastEffect(ref param, cueData.sourceGeSpec, seqList);
}
public void GE_ShowCastEffect(ref TexiaoShowParam param, GameplayEffectSpec spec, List<int> seqList = null)
{
Vector2 targetDir = Vector2.right;
if (spec.Source != null && spec.Source.owner.IsValid())
{
targetDir = spec.Owner.owner.transformProxy.position - spec.Source.owner.transformProxy.position;
}
var isShowSelf = IsShowSelf(ref param, seqList, out var path, out var isAttach, targetDir);
if (isShowSelf == false)
{
XLog.LogWarning($"GESpec {spec.GameplayEffect.GameplayEffectName} -> {param}: 只能显示Owner特效");
return;
}
}
public void GA_ShowCastEffect(ref TexiaoShowParam param, GameAbilityContext ctx, List<int> seqList = null)
{
var targetDir = Vector2.zero;
if (ctx != null)
{
var tbRenderEffect = RenderEffectDescMgr.Instance.GetConfig(param.effectId);
if (tbRenderEffect.isLookAtTarget == VFXLookType.PointSelect && ctx.castPos.Count > 0)
{
targetDir = ctx.castPos[0].ToVector2() - ctx.ownerEnt.transformProxy.position;
}
else if (tbRenderEffect.isLookAtTarget == VFXLookType.CatchTarget && ctx.geCatchTargets.Count > 0)
{
for (int i = 0; i < ctx.geCatchTargets.Count; i++)
{
if (ctx.geCatchTargets[i].IsValid() && ctx.geCatchTargets[i].hasTransformProxy)
{
targetDir = ctx.geCatchTargets[i].transformProxy.position -
ctx.ownerEnt.transformProxy.position;
break;
}
}
}
}
if (IsShowSelf(ref param, seqList, out var path, out var isAttach, targetDir)) return;
if (ctx == null || ctx.geCatchTargets.Count == 0)
{
BattleLogger.LogInfo("ShowCastEffect: geCatchTargets is empty");
return;
}
for (var i = 0; i < ctx.geCatchTargets.Count; i++)
{
var useHitData = false;
if (isAttach == false)
useHitData = NormalParma(ref param, ctx.geCatchTargets[i].creationIndex, ctx);
ShowSingleTargetEffect(ctx.geCatchTargets[i], path, useHitData, isAttach, ref param, seqList);
}
}
private bool IsShowSelf(ref TexiaoShowParam param, List<int> seqList, out string path, out bool isAttach,
Vector2 targetDir)
{
seqList?.Clear();
var tbRenderEffect = RenderEffectDescMgr.Instance.GetConfig(param.effectId);
if (tbRenderEffect == null)
{
BattleLogger.LogInfo($"ShowCastEffect: effectId {param.effectId} is not exist");
path = null;
isAttach = false;
return true;
}
if (tbRenderEffect.isScale != 0) // 需要乘上实体的缩放
param.scale *= effectScale;
path = tbRenderEffect.prefab;
if (param.element == (int)ElementType.Fire && !string.IsNullOrEmpty(tbRenderEffect.firePrefab))
path = tbRenderEffect.firePrefab;
else if (param.element == (int)ElementType.Toxic && !string.IsNullOrEmpty(tbRenderEffect.toxicPrefab))
path = tbRenderEffect.toxicPrefab;
else if (param.element == (int)ElementType.Thunder && !string.IsNullOrEmpty(tbRenderEffect.thunderPrefab))
path = tbRenderEffect.thunderPrefab;
isAttach = tbRenderEffect.effectSpawn == EffectSpawn.Target;
var isTargetSelf = tbRenderEffect.effectTarget == EffectTarget.Owner;
if (isTargetSelf)
{
if (tbRenderEffect.isLookAtTarget != VFXLookType.None &&
tbRenderEffect.isLookAtTarget != VFXLookType.Default)
{
var rotation = Quaternion.LookRotation(Vector3.forward, targetDir.normalized);
param.rotation = rotation;
}
ShowSingleTargetEffect(ent, path, false, isAttach, ref param, seqList);
return true;
}
return false;
}
private bool NormalParma(ref TexiaoShowParam param, int targetEid, GameAbilityContext ctx)
{
if (ctx == null)
return false;
if (ctx.hitDatas.TryGetValue(targetEid, out var hitData))
{
param.offset = hitData.hitPos;
param.rotation = Quaternion.LookRotation(Vector3.forward, hitData.hitDir);
return true;
}
return false;
}
private void ShowSingleTargetEffect(CombatEntity entity, string path, bool useHitData, bool isAttach,
ref TexiaoShowParam param, List<int> seqList = null)
{
if (entity == null || entity.isEnabled == false)
{
BattleLogger.LogInfo($"{entity} is null or not enabled");
return;
}
var txShowProcessParam = SptPool<TxShowProcessParam>.Malloc();
txShowProcessParam.Awake(ref param);
txShowProcessParam.isAttach = isAttach;
txShowProcessParam.eid = entity.creationIndex;
txShowProcessParam.useHitPos = useHitData;
txShowProcessParam.ghostPos = entity.transformProxy.position;
var pool = GoPoolDic.GetPool(path);
var reuseGoData = pool.GetNewGo(ShowSingleTargetEffect, txShowProcessParam);
txShowProcessParam.reuseGoData = reuseGoData;
var seq = reuseGoData.GetSeq();
if (seqList != null)
{
seqList.Add(seq);
}
else
{
Contexts.Combat.renderTimerEntity?.renderTimer?.AddTimer(1.3f, seq, DestroyEffect);
}
effectListDict.Add(seq, txShowProcessParam);
}
private static void ShowSingleTargetEffect(ReuseGoData reuseGoData)
{
if (reuseGoData == null)
return;
var param = (TxShowProcessParam)reuseGoData.param;
reuseGoData.param = null; // 只能被池管理
var effectObj = reuseGoData.go;
var entity = Contexts.Combat.GetEntity(param.eid);
// 此函数为回调函数,go一定有
if (param.isAttach && entity.IsValid())
{
var tbRenderEffect = RenderEffectDescMgr.Instance.GetConfig(param.effectId);
Transform bindPoint = entity.transformProxy.value;
if (entity.bindPointProxy?.TryGetBindPointOrDefault(tbRenderEffect.effectPoint,
out var point) == true)
{
bindPoint = point;
}
if (bindPoint == null)
{
XLog.LogDebug($"ShowSingleTargetEffect: bindPoint {tbRenderEffect.effectPoint} is invalid, effectId: {param.effectId}");
return;
}
effectObj.transform.SetParent(bindPoint);
effectObj.transform.SetLocalTransform(param.offset, param.rotation, param.scale);
}
else if (param.useHitPos)
{
effectObj.transform.SetTransform(param.offset, param.rotation, param.scale);
}
else
{
// todo : 有问题,但应该不会出问题,需要矩阵转换
// 不要拿transform,可能没同步
var position = entity.IsValid() ? entity.transformProxy.position : param.ghostPos;
effectObj.transform.SetTransform(
new Vector3(position.x, position.y) + new Vector3(param.offset.x, param.offset.y), param.rotation,
param.scale);
}
effectObj.SetActiveWrap(true);
}
public void ActivateEffect(List<int> seqs)
{
for (int i = 0; i < seqs.Count; i++)
{
if (effectListDict.TryGetValue(seqs[i], out var tp))
{
// 不能用warp
if (!tp.reuseGoData.go) continue;
tp.reuseGoData.go.SetActive(true);
}
}
}
public void DeactivateEffect(List<int> seqs)
{
for (int i = 0; i < seqs.Count; i++)
{
if (effectListDict.TryGetValue(seqs[i], out var tp))
{
if (!tp.reuseGoData.go) continue;
tp.reuseGoData.go.SetActive(false);
}
}
}
public void DestroyEffect(List<int> seqs)
{
for (var i = 0; i < seqs.Count; i++)
{
var seq = seqs[i];
if (effectListDict.TryGetValue(seq, out var tp))
{
GoPoolDic.GetPool(tp.reuseGoData.path).ReleaseGo(tp.reuseGoData);
SptPool<TxShowProcessParam>.Free(ref tp);
effectListDict.Remove(seq);
}
else
{
BattleLogger.LogInfo($"{ent} : DestroyEffect: seq {seq} is not exist");
}
}
}
public void DestroyEffect(object sq)
{
var seq = (int)sq;
if (effectListDict.TryGetValue(seq, out var tp))
{
GoPoolDic.GetPool(tp.reuseGoData.path).ReleaseGo(tp.reuseGoData);
SptPool<TxShowProcessParam>.Free(ref tp);
effectListDict.Remove(seq);
}
}
#region Mat
// 只能一次修改
public void PushMat(Material mat)
{
if (m_IsMatPushed < 0)
m_IsMatPushed++;
if (m_IsMatPushed > 0)
return;
m_IsMatPushed++;
go.GetComponentsInChildren(m_CacheRenderers);
for (var i = m_CacheRenderers.Count - 1; i >= 0; i--)
{
if (m_CacheRenderers[i].GetComponentInParent<NotChangeMatByCue>() != null)
{
m_CacheRenderers.RemoveAt(i);
continue;
}
m_CacheMaterials.Add(m_CacheRenderers[i].sharedMaterial);
m_CacheRenderers[i].sharedMaterial = mat;
}
}
public List<SpriteRenderer> OpMats()
{
return m_CacheRenderers;
}
public void PopMat()
{
m_IsMatPushed--;
for (var i = 0; i < m_CacheRenderers.Count; i++)
{
if (m_CacheRenderers[i])
{
m_CacheRenderers[i].sharedMaterial = m_CacheMaterials[i];
}
}
m_CacheRenderers.Clear();
}
#endregion
protected override void OnReset()
{
effectScale = 1;
}
}
}