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.
 
 
 
 
 
 

213 lines
6.8 KiB

using GAS.Runtime;
using Sog;
using UnityEngine.Profiling;
namespace CoreGame.Render
{
public class GaDeathSpec : AbilitySpec, ISptPool
{
protected TimelineAbilityPlayer player;
private CallbackWrapper m_CallbackWrapper = null;
public override void Awake(GameplayAbility ability, GameAbilityContext gaCtx)
{
base.Awake(ability, gaCtx);
player = new TimelineAbilityPlayer();
player.Awake(this);
gaCtx.asc.RegisterGameplayTagEvent(GTagLib.Event_Dying, EGameplayTagEventType.NewOrRemoved, OnWillDeath);
}
public override void GrantAbility()
{
m_CallbackWrapper = CallbackWrapper.New(OnHpChange, this);
ctx.ownerEnt.AddEventCallBack(ClientEvent.OnEntityBeKill, m_CallbackWrapper);
}
public override void UnGrantAbility()
{
ctx.ownerEnt.RemoveCallback(ClientEvent.OnEntityBeKill, ref m_CallbackWrapper);
}
public void OnHpChange(object self, int eventId, object value)
{
var spec = (GaDeathSpec)self;
spec.OnWillDeath(default, 1);
}
public void OnWillDeath(GameplayTag tag, int count)
{
if (count == 0) // 代表移除
return;
if (ctx.ownerEnt.abilitySystem == null)
return;
// 触发死亡前能力
var b = ctx.ownerEnt.abilitySystem.TryActivateAbilities_WithTag(GTagLib.Event_BeforeDyingGA);
if (!b)
{
// 直接死亡
OnDeath(tag, count);
}
else
{
// 等待死亡前能力结束
ctx.asc.RegisterGameplayTagEvent(GTagLib.Event_BeforeDyingGA, EGameplayTagEventType.NewOrRemoved,
OnDeath);
}
}
public void OnDeath(GameplayTag tag, int count)
{
if (count == 0)
return;
ctx.ownerEnt.abilitySystem.TryActivateAbilities_WithTag(GTagLib.Event_Dying);
}
private void DisableCmpts()
{
var ent = ctx.ownerEnt;
ent.isDead = true;
if (ent.hasCollider2DProxy)
{
var colliderProxy = ent.collider2DProxy;
foreach (var collider in colliderProxy.cs)
{
ColliderSrv.DisableCollider(collider);
}
}
}
private void DestroyLifeBindChildren()
{
var lifeBindMe = ctx.ownerEnt.lifeBindMe;
if (lifeBindMe != null)
{
for (int i = 0; i < lifeBindMe.children.Count; i++)
{
var childEid = lifeBindMe.children[i];
var childEnt = Contexts.Combat.GetEntity(childEid);
if (childEnt != null)
{
childEnt.isDead = true;
childEnt.isDestroyEnt = true;
}
}
lifeBindMe.children.Clear();
}
}
private void PushBattleData()
{
var levelWaveEnt = Contexts.Combat.LevelWave;
if (levelWaveEnt == null)
return;
var levelWave = levelWaveEnt.levelWave;
if (ctx.ownerEnt.hasMonster)
{
if (!ctx.ownerEnt.hasSummon)
{
var battleWaveData = SptPool<BattleWaveData>.Malloc();
battleWaveData.MonsterKilledCount = 1;
battleWaveData.StageId = levelWave.curStageId;
CoreUIBridge.CoreGamePushBattleWaveData(battleWaveData);
SptPool<BattleWaveData>.Free(ref battleWaveData);
}
}
else if (ctx.ownerEnt.isLocalPlayer)
{
var isBossContinueBattleRedNameWave = BattleModule.Instance.worldType == WorldType.BossContinueBattle &&
CoreUIBridge.s_BossBattleParams.waveIsRedName;
if (!isBossContinueBattleRedNameWave)
{
CoreUIBridge.CoreGamePushBattleEndData(levelWave.battleId, CoreUIBridge.BattleEndType.LoseHeroDead);
}
}
}
private void MakeLocalPlayerCannotBeHurt()
{
const int normalBattleParam = 1;
const int bossContinueBattleParam = 2;
if (ctx.ownerEnt.hasMonster && !ctx.ownerEnt.hasSummon)
{
var worldType = BattleModule.Instance.worldType;
var monsterType = ctx.ownerEnt.monster.monsterType;
if (worldType != WorldType.BossContinueBattle)
{
if (monsterType == MonsterType.Boss)
{
Contexts.Combat.LocalPlayer.DispatchEvent(ClientEvent.MakeEntityCannotBeHurt,
normalBattleParam);
}
}
else
{
if (monsterType == MonsterType.Boss || monsterType == MonsterType.Intruder)
{
Contexts.Combat.LocalPlayer.DispatchEvent(ClientEvent.MakeEntityCannotBeHurt,
bossContinueBattleParam);
}
}
}
}
public override void ActivateAbility()
{
MakeLocalPlayerCannotBeHurt();
player.Stop();
player.Play();
DisableCmpts();
}
public override void CancelAbility()
{
player.Stop();
}
public override void EndAbility()
{
player.Stop();
DestroyLifeBindChildren();
PushBattleData();
}
protected override void AbilityTick(Fixed64 dt)
{
Profiler.BeginSample("GaDeathSpec<T>::AbilityTick()");
player.Tick(dt);
Profiler.EndSample();
}
public void Reset()
{
player = null;
}
}
public class GADeath : GameplayAbility
{
public GADeath(AbilityAsset abilityAsset) : base(abilityAsset)
{
}
public override AbilitySpec CreateSpec(AbilitySystemComponent owner, GameAbilityContext ctx)
{
var deathAbilitySpec = SptPool<GaDeathSpec>.Malloc();
deathAbilitySpec.Awake(this, ctx);
return deathAbilitySpec;
}
public override void FreeSpec(ref AbilitySpec spec)
{
if (!(spec is GaDeathSpec deathAbilitySpec))
{
BattleLogger.LogInfo("DeathAbilitySpec.FreeSpec: spec is not DeathAbilitySpec");
return;
}
SptPool<GaDeathSpec>.Free(ref deathAbilitySpec);
}
}
}