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.
162 lines
4.2 KiB
C#
162 lines
4.2 KiB
C#
using System;
|
|
using Unity.BossRoom.Gameplay.GameplayObjects.Character;
|
|
using Unity.Netcode;
|
|
using UnityEngine;
|
|
using UnityEngine.Events;
|
|
|
|
namespace Unity.BossRoom.Gameplay.GameplayObjects
|
|
{
|
|
public class TossedItem : NetworkBehaviour
|
|
{
|
|
[Header("Server")]
|
|
|
|
[SerializeField]
|
|
int m_DamagePoints;
|
|
|
|
[SerializeField]
|
|
float m_HitRadius = 5f;
|
|
|
|
[SerializeField]
|
|
float m_KnockbackSpeed;
|
|
|
|
[SerializeField]
|
|
float m_KnockbackDuration;
|
|
|
|
[SerializeField]
|
|
LayerMask m_LayerMask;
|
|
|
|
bool m_Started;
|
|
|
|
const int k_MaxCollisions = 16;
|
|
|
|
Collider[] m_CollisionCache = new Collider[k_MaxCollisions];
|
|
|
|
[SerializeField]
|
|
float m_DetonateAfterSeconds = 5f;
|
|
|
|
float m_DetonateTimer;
|
|
|
|
[SerializeField]
|
|
float m_DestroyAfterSeconds = 6f;
|
|
|
|
float m_DestroyTimer;
|
|
|
|
bool m_Detonated;
|
|
|
|
public UnityEvent detonatedCallback;
|
|
|
|
[Header("Client")]
|
|
|
|
[SerializeField]
|
|
Transform m_TossedItemVisualTransform;
|
|
|
|
const float k_DisplayHeight = 0.1f;
|
|
|
|
readonly Quaternion k_TossAttackRadiusDisplayRotation = Quaternion.Euler(90f, 0f, 0f);
|
|
|
|
[SerializeField]
|
|
GameObject m_TossedObjectGraphics;
|
|
|
|
[SerializeField]
|
|
AudioSource m_FallingSound;
|
|
|
|
public override void OnNetworkSpawn()
|
|
{
|
|
if (IsServer)
|
|
{
|
|
m_Started = true;
|
|
m_Detonated = false;
|
|
|
|
m_DetonateTimer = Time.fixedTime + m_DetonateAfterSeconds;
|
|
m_DestroyTimer = Time.fixedTime + m_DestroyAfterSeconds;
|
|
}
|
|
|
|
if (IsClient)
|
|
{
|
|
m_TossedItemVisualTransform.gameObject.SetActive(true);
|
|
m_TossedObjectGraphics.SetActive(true);
|
|
m_FallingSound.Play();
|
|
}
|
|
}
|
|
|
|
public override void OnNetworkDespawn()
|
|
{
|
|
if (IsServer)
|
|
{
|
|
m_Started = false;
|
|
m_Detonated = false;
|
|
}
|
|
|
|
if (IsClient)
|
|
{
|
|
m_TossedItemVisualTransform.gameObject.SetActive(false);
|
|
}
|
|
|
|
}
|
|
|
|
void Detonate()
|
|
{
|
|
var hits = Physics.OverlapSphereNonAlloc(transform.position, m_HitRadius, m_CollisionCache, m_LayerMask);
|
|
|
|
for (int i = 0; i < hits; i++)
|
|
{
|
|
if (m_CollisionCache[i].gameObject.TryGetComponent(out IDamageable damageReceiver))
|
|
{
|
|
damageReceiver.ReceiveHP(null, -m_DamagePoints);
|
|
|
|
var serverCharacter = m_CollisionCache[i].gameObject.GetComponentInParent<ServerCharacter>();
|
|
if (serverCharacter)
|
|
{
|
|
serverCharacter.Movement.StartKnockback(transform.position, m_KnockbackSpeed, m_KnockbackDuration);
|
|
}
|
|
}
|
|
}
|
|
|
|
// send client RPC to detonate on clients
|
|
ClientDetonateRpc();
|
|
|
|
m_Detonated = true;
|
|
}
|
|
|
|
[Rpc(SendTo.ClientsAndHost)]
|
|
void ClientDetonateRpc()
|
|
{
|
|
detonatedCallback?.Invoke();
|
|
}
|
|
|
|
void FixedUpdate()
|
|
{
|
|
if (IsServer)
|
|
{
|
|
if (!m_Started)
|
|
{
|
|
return; //don't do anything before OnNetworkSpawn has run.
|
|
}
|
|
|
|
if (!m_Detonated && m_DetonateTimer < Time.fixedTime)
|
|
{
|
|
Detonate();
|
|
}
|
|
|
|
if (m_Detonated && m_DestroyTimer < Time.fixedTime)
|
|
{
|
|
// despawn after sending detonate RPC
|
|
var networkObject = gameObject.GetComponent<NetworkObject>();
|
|
networkObject.Despawn();
|
|
}
|
|
}
|
|
}
|
|
|
|
void LateUpdate()
|
|
{
|
|
if (IsClient)
|
|
{
|
|
var tossedItemPosition = transform.position;
|
|
m_TossedItemVisualTransform.SetPositionAndRotation(
|
|
new Vector3(tossedItemPosition.x, k_DisplayHeight, tossedItemPosition.z),
|
|
k_TossAttackRadiusDisplayRotation);
|
|
}
|
|
}
|
|
}
|
|
}
|