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.
154 lines
3.9 KiB
C#
154 lines
3.9 KiB
C#
using System;
|
|
using Fusion;
|
|
using UnityEngine;
|
|
|
|
namespace Projectiles
|
|
{
|
|
/// <summary>
|
|
/// Weapon component that fires a laser beam that damages targets on hit.
|
|
/// </summary>
|
|
[DefaultExecutionOrder(15)]
|
|
public class WeaponBeam : WeaponComponent
|
|
{
|
|
// PRIVATE MEMBERS
|
|
|
|
[SerializeField]
|
|
private float _damage = 10f;
|
|
[SerializeField]
|
|
private EHitType _hitType = EHitType.Projectile;
|
|
[SerializeField]
|
|
private LayerMask _hitMask;
|
|
[SerializeField]
|
|
private float _maxDistance = 50f;
|
|
[SerializeField]
|
|
private float _beamRadius = 0.2f;
|
|
[SerializeField, Tooltip("Number of raycast rays fired. First is always in center, other are spread around in the radius distance.")]
|
|
private int _raycastAmount = 5;
|
|
[SerializeField]
|
|
private WeaponTrigger _weaponTrigger;
|
|
|
|
[Header("Beam Visuals")]
|
|
[SerializeField]
|
|
private GameObject _beamStart;
|
|
[SerializeField]
|
|
private GameObject _beamEnd;
|
|
[SerializeField]
|
|
private LineRenderer _beam;
|
|
[SerializeField]
|
|
private float _beamEndOffset = 0.5f;
|
|
[SerializeField]
|
|
private bool _updateBeamMaterial;
|
|
[SerializeField]
|
|
private float _textureScale = 3f;
|
|
[SerializeField]
|
|
private float _textureScrollSpeed = -8f;
|
|
|
|
[Header("Camera Effect")]
|
|
[SerializeField]
|
|
private ShakeSetup _cameraShakePosition;
|
|
[SerializeField]
|
|
private ShakeSetup _cameraShakeRotation;
|
|
|
|
[Networked]
|
|
private float _beamDistance { get; set; }
|
|
|
|
// WeaponComponent INTERFACE
|
|
|
|
public override void Fire()
|
|
{
|
|
var hit = ProcessBeamHit();
|
|
if (hit.Distance > 0f)
|
|
{
|
|
HitUtility.ProcessHit(Object.InputAuthority, FireTransform.forward, hit, _damage, _hitType);
|
|
}
|
|
}
|
|
|
|
// NetworkBehaviour INTERFACE
|
|
|
|
public override void FixedUpdateNetwork()
|
|
{
|
|
// Update beam distance only when trigger is firing
|
|
if (_weaponTrigger.IsBusy == true)
|
|
{
|
|
ProcessBeamHit();
|
|
}
|
|
else
|
|
{
|
|
_beamDistance = -1f;
|
|
}
|
|
}
|
|
|
|
private void LateUpdate()
|
|
{
|
|
if (Object == null || Object.IsValid == false)
|
|
return;
|
|
|
|
// Beam needs to be updated after camera pivot change
|
|
// - after PlayerAgent.LateUpdate
|
|
UpdateBeam();
|
|
|
|
if (_beamDistance > 0f && HasInputAuthority == true)
|
|
{
|
|
var cameraShake = Context.Camera.ShakeEffect;
|
|
cameraShake.Play(_cameraShakePosition, EShakeForce.ReplaceSame);
|
|
cameraShake.Play(_cameraShakeRotation, EShakeForce.ReplaceSame);
|
|
}
|
|
}
|
|
|
|
// PRIVATE MEMBERS
|
|
|
|
private LagCompensatedHit ProcessBeamHit()
|
|
{
|
|
_beamDistance = _maxDistance;
|
|
|
|
if (ProjectileUtility.CircleCast(Runner, Object.InputAuthority, FireTransform.position, FireTransform.forward, _maxDistance, _beamRadius, _raycastAmount, _hitMask, out LagCompensatedHit hit) == true)
|
|
{
|
|
_beamDistance = hit.Distance;
|
|
return hit;
|
|
}
|
|
|
|
return default;
|
|
}
|
|
|
|
private void UpdateBeam()
|
|
{
|
|
bool beamActive = _beamDistance > 0f;
|
|
|
|
_beamStart.SetActiveSafe(beamActive);
|
|
_beamEnd.SetActiveSafe(beamActive);
|
|
_beam.gameObject.SetActiveSafe(beamActive);
|
|
|
|
if (beamActive == false)
|
|
return;
|
|
|
|
var startPosition = _beamStart.transform.position;
|
|
var targetPosition = FireTransform.position + FireTransform.forward * _beamDistance;
|
|
|
|
var visualDirection = targetPosition - startPosition;
|
|
float visualDistance = visualDirection.magnitude;
|
|
|
|
visualDirection /= visualDistance; // Normalize
|
|
|
|
if (_beamEndOffset > 0f)
|
|
{
|
|
// Adjust target position
|
|
visualDistance = visualDistance > _beamEndOffset ? visualDistance - _beamEndOffset : 0f;
|
|
targetPosition = startPosition + visualDirection * visualDistance;
|
|
}
|
|
|
|
_beamEnd.transform.SetPositionAndRotation(targetPosition, Quaternion.LookRotation(-visualDirection));
|
|
|
|
_beam.SetPosition(0, startPosition);
|
|
_beam.SetPosition(1, targetPosition);
|
|
|
|
if (_updateBeamMaterial == true)
|
|
{
|
|
var beamMaterial = _beam.material;
|
|
|
|
beamMaterial.mainTextureScale = new Vector2(visualDistance / _textureScale, 1f);
|
|
beamMaterial.mainTextureOffset += new Vector2(Time.deltaTime * _textureScrollSpeed, 0f);
|
|
}
|
|
}
|
|
}
|
|
}
|