You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
145 lines
5.5 KiB
C#
145 lines
5.5 KiB
C#
2 weeks ago
|
using System;
|
||
|
using System.Collections.Generic;
|
||
|
using Unity.BossRoom.Gameplay.GameplayObjects.Character;
|
||
|
using Unity.BossRoom.VisualEffects;
|
||
|
using Unity.Netcode;
|
||
|
using UnityEngine;
|
||
|
|
||
|
namespace Unity.BossRoom.Gameplay.Actions
|
||
|
{
|
||
|
public partial class MeleeAction
|
||
|
{
|
||
|
//have we actually played an impact? This won't necessarily happen for all swings. Sometimes you're just swinging at space.
|
||
|
private bool m_ImpactPlayed;
|
||
|
|
||
|
/// <summary>
|
||
|
/// When we detect if our original target is still around, we use a bit of padding on the range check.
|
||
|
/// </summary>
|
||
|
private const float k_RangePadding = 3f;
|
||
|
|
||
|
/// <summary>
|
||
|
/// List of active special graphics playing on the target.
|
||
|
/// </summary>
|
||
|
private List<SpecialFXGraphic> m_SpawnedGraphics = null;
|
||
|
|
||
|
public override bool OnStartClient(ClientCharacter clientCharacter)
|
||
|
{
|
||
|
base.OnStartClient(clientCharacter);
|
||
|
|
||
|
// we can optionally have special particles that should play on the target. If so, add them now.
|
||
|
// (don't wait until impact, because the particles need to start sooner!)
|
||
|
if (Data.TargetIds != null
|
||
|
&& Data.TargetIds.Length > 0
|
||
|
&& NetworkManager.Singleton.SpawnManager.SpawnedObjects.TryGetValue(Data.TargetIds[0], out var targetNetworkObj)
|
||
|
&& targetNetworkObj != null)
|
||
|
{
|
||
|
float padRange = Config.Range + k_RangePadding;
|
||
|
|
||
|
Vector3 targetPosition;
|
||
|
if (PhysicsWrapper.TryGetPhysicsWrapper(Data.TargetIds[0], out var physicsWrapper))
|
||
|
{
|
||
|
targetPosition = physicsWrapper.Transform.position;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
targetPosition = targetNetworkObj.transform.position;
|
||
|
}
|
||
|
|
||
|
if ((clientCharacter.transform.position - targetPosition).sqrMagnitude < (padRange * padRange))
|
||
|
{
|
||
|
// target is in range! Play the graphics
|
||
|
m_SpawnedGraphics = InstantiateSpecialFXGraphics(physicsWrapper ? physicsWrapper.Transform : targetNetworkObj.transform, true);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
public override bool OnUpdateClient(ClientCharacter clientCharacter)
|
||
|
{
|
||
|
return ActionConclusion.Continue;
|
||
|
}
|
||
|
|
||
|
public override void OnAnimEventClient(ClientCharacter clientCharacter, string id)
|
||
|
{
|
||
|
if (id == "impact" && !m_ImpactPlayed)
|
||
|
{
|
||
|
PlayHitReact(clientCharacter);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public override void EndClient(ClientCharacter clientCharacter)
|
||
|
{
|
||
|
//if this didn't already happen, make sure it gets a chance to run. This could have failed to run because
|
||
|
//our animationclip didn't have the "impact" event properly configured (as one possibility).
|
||
|
PlayHitReact(clientCharacter);
|
||
|
base.EndClient(clientCharacter);
|
||
|
}
|
||
|
|
||
|
public override void CancelClient(ClientCharacter clientCharacter)
|
||
|
{
|
||
|
// if we had any special target graphics, tell them we're done
|
||
|
if (m_SpawnedGraphics != null)
|
||
|
{
|
||
|
foreach (var spawnedGraphic in m_SpawnedGraphics)
|
||
|
{
|
||
|
if (spawnedGraphic)
|
||
|
{
|
||
|
spawnedGraphic.Shutdown();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void PlayHitReact(ClientCharacter parent)
|
||
|
{
|
||
|
if (m_ImpactPlayed) { return; }
|
||
|
|
||
|
m_ImpactPlayed = true;
|
||
|
|
||
|
if (NetworkManager.Singleton.IsServer)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//Is my original target still in range? Then definitely get him!
|
||
|
if (Data.TargetIds != null &&
|
||
|
Data.TargetIds.Length > 0 &&
|
||
|
NetworkManager.Singleton.SpawnManager.SpawnedObjects.TryGetValue(Data.TargetIds[0], out var targetNetworkObj)
|
||
|
&& targetNetworkObj != null)
|
||
|
{
|
||
|
float padRange = Config.Range + k_RangePadding;
|
||
|
|
||
|
Vector3 targetPosition;
|
||
|
if (PhysicsWrapper.TryGetPhysicsWrapper(Data.TargetIds[0], out var movementContainer))
|
||
|
{
|
||
|
targetPosition = movementContainer.Transform.position;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
targetPosition = targetNetworkObj.transform.position;
|
||
|
}
|
||
|
|
||
|
if ((parent.transform.position - targetPosition).sqrMagnitude < (padRange * padRange))
|
||
|
{
|
||
|
if (targetNetworkObj.NetworkObjectId != parent.NetworkObjectId)
|
||
|
{
|
||
|
string hitAnim = Config.ReactAnim;
|
||
|
if (string.IsNullOrEmpty(hitAnim)) { hitAnim = k_DefaultHitReact; }
|
||
|
|
||
|
if (targetNetworkObj.TryGetComponent<ServerCharacter>(out var serverCharacter)
|
||
|
&& serverCharacter.clientCharacter != null
|
||
|
&& serverCharacter.clientCharacter.OurAnimator)
|
||
|
{
|
||
|
serverCharacter.clientCharacter.OurAnimator.SetTrigger(hitAnim);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//in the future we may do another physics check to handle the case where a target "ran under our weapon".
|
||
|
//But for now, if the original target is no longer present, then we just don't play our hit react on anything.
|
||
|
}
|
||
|
}
|
||
|
}
|