-
Notifications
You must be signed in to change notification settings - Fork 0
/
DashAttackAction.cs
117 lines (97 loc) · 4.64 KB
/
DashAttackAction.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
using System;
using Unity.BossRoom.Gameplay.GameplayObjects;
using Unity.BossRoom.Gameplay.GameplayObjects.Character;
using UnityEngine;
namespace Unity.BossRoom.Gameplay.Actions
{
/// <summary>
/// Causes the attacker to teleport near a target spot, then perform a melee attack. The client
/// visualization moves the character locally beforehand, making the character appear to dash to the
/// destination spot.
///
/// After the ExecTime has elapsed, the character is immune to damage until the action ends.
///
/// Since the "Range" field means "range when we can teleport to our target", we need another
/// field to mean "range of our melee attack after dashing". We'll use the "Radius" field of the
/// ActionDescription for that.
/// </summary>
/// <remarks>
/// See MeleeAction for relevant discussion about targeting; we use the same concept here: preferring
/// the chosen target, but using whatever is actually within striking distance at time of attack.
/// </remarks>
[CreateAssetMenu(menuName = "BossRoom/Actions/Dash Attack Action")]
public class DashAttackAction : Action
{
private Vector3 m_TargetSpot;
private bool m_Dashed;
public override bool OnStart(ServerCharacter serverCharacter)
{
// remember the exact spot we'll stop.
m_TargetSpot = ActionUtils.GetDashDestination(serverCharacter.physicsWrapper.Transform, Data.Position, true, Config.Range, Config.Range);
// snap to face our destination. This ensures the client visualization faces the right way while "pretending" to dash
serverCharacter.physicsWrapper.Transform.LookAt(m_TargetSpot);
serverCharacter.serverAnimationHandler.NetworkAnimator.SetTrigger(Config.Anim);
// tell clients to visualize this action
serverCharacter.clientCharacter.RecvDoActionClientRPC(Data);
return ActionConclusion.Continue;
}
public override void Reset()
{
base.Reset();
m_TargetSpot = default;
m_Dashed = false;
}
public override bool OnUpdate(ServerCharacter clientCharacter)
{
return ActionConclusion.Continue;
}
public override void End(ServerCharacter serverCharacter)
{
// Anim2 contains the name of the end-loop-sequence trigger
if (!string.IsNullOrEmpty(Config.Anim2))
{
serverCharacter.serverAnimationHandler.NetworkAnimator.SetTrigger(Config.Anim2);
}
// we're done, time to teleport!
serverCharacter.Movement.Teleport(m_TargetSpot);
// and then swing!
PerformMeleeAttack(serverCharacter);
}
public override void Cancel(ServerCharacter serverCharacter)
{
// OtherAnimatorVariable contains the name of the cancellation trigger
if (!string.IsNullOrEmpty(Config.OtherAnimatorVariable))
{
serverCharacter.serverAnimationHandler.NetworkAnimator.SetTrigger(Config.OtherAnimatorVariable);
}
// because the client-side visualization of the action moves the character visualization around,
// we need to explicitly end the client-side visuals when we abort
serverCharacter.clientCharacter.RecvCancelActionsByPrototypeIDClientRpc(ActionID);
}
public override void BuffValue(BuffableValue buffType, ref float buffedValue)
{
if (TimeRunning >= Config.ExecTimeSeconds && buffType == BuffableValue.PercentDamageReceived)
{
// we suffer no damage during the "dash" (client-side pretend movement)
buffedValue = 0;
}
}
private void PerformMeleeAttack(ServerCharacter parent)
{
// perform a typical melee-hit. But note that we are using the Radius field for range, not the Range field!
IDamageable foe = MeleeAction.GetIdealMeleeFoe(Config.IsFriendly ^ parent.IsNpc,
parent.physicsWrapper.DamageCollider,
Config.Radius,
(Data.TargetIds != null && Data.TargetIds.Length > 0 ? Data.TargetIds[0] : 0));
if (foe != null)
{
foe.ReceiveHP(parent, -Config.Amount);
}
}
public override bool OnUpdateClient(ClientCharacter clientCharacter)
{
if (m_Dashed) { return ActionConclusion.Stop; } // we're done!
return ActionConclusion.Continue;
}
}
}