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
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);
|
|
}
|
|
}
|
|
}
|