214 lines
5.4 KiB
C#
214 lines
5.4 KiB
C#
using UnityEngine;
|
|
using Fusion;
|
|
using Fusion.Addons.KCC;
|
|
|
|
namespace TPSBR
|
|
{
|
|
public sealed class Airplane : ContextBehaviour
|
|
{
|
|
// PUBLIC MEMBERS
|
|
|
|
[Networked, HideInInspector]
|
|
public Vector3 NextTargetPosition { get; set; }
|
|
|
|
public bool DropEnabled { get { return _state.IsBitSet(0); } set { _state = _state.SetBitNoRef(0, value); } }
|
|
public bool DropFinished { get { return _state.IsBitSet(1); } set { _state = _state.SetBitNoRef(1, value); } }
|
|
public bool IsFlyingAway { get { return _state.IsBitSet(2); } set { _state = _state.SetBitNoRef(2, value); } }
|
|
public bool IsFinished { get { return _state.IsBitSet(3); } set { _state = _state.SetBitNoRef(3, value); } }
|
|
|
|
public Transform AgentPosition => _agentPosition;
|
|
public float OutZoneDistance => _outZoneDistance;
|
|
|
|
// PRIVATE MEMBERS
|
|
|
|
[SerializeField]
|
|
private GameObject _dropEnabledObject;
|
|
[SerializeField]
|
|
private GameObject _dropDisabledObject;
|
|
[SerializeField]
|
|
private Transform _agentPosition;
|
|
[SerializeField]
|
|
private float _maxSpeed = 8f;
|
|
[SerializeField]
|
|
private float _maxAcceleration = 8f;
|
|
[SerializeField]
|
|
private float _tiltSpeed = 8f;
|
|
[SerializeField]
|
|
private float _maxTilt = 60;
|
|
[SerializeField]
|
|
private float _minDistanceToTargetChange = 60f;
|
|
[SerializeField]
|
|
private float _outZoneDistance = 20f;
|
|
[SerializeField]
|
|
private float _inZoneDistance = 10f;
|
|
|
|
[Header("Sounds")]
|
|
[SerializeField]
|
|
private AudioEffect _audioEffect;
|
|
[SerializeField]
|
|
private AudioSetup _playerJumpedSound;
|
|
|
|
[Networked]
|
|
private byte _state { get; set; }
|
|
[Networked]
|
|
private Vector3 _velocity { get; set; }
|
|
[Networked]
|
|
private float _tilt { get; set; }
|
|
|
|
// PUBLIC METHODS
|
|
|
|
public void ActivateDropWindow()
|
|
{
|
|
if (HasStateAuthority == false)
|
|
return;
|
|
|
|
DropEnabled = true;
|
|
NextTargetPosition = Vector3.zero;
|
|
}
|
|
|
|
public void DeactivateDropWindow()
|
|
{
|
|
if (HasStateAuthority == false)
|
|
return;
|
|
|
|
DropEnabled = false;
|
|
DropFinished = true;
|
|
NextTargetPosition = Vector3.zero;
|
|
}
|
|
|
|
public void OnPlayerJumped(PlayerRef playerRef)
|
|
{
|
|
_audioEffect.Play(_playerJumpedSound);
|
|
}
|
|
|
|
// NetworkBehaviour INTERFACE
|
|
|
|
public override void Spawned()
|
|
{
|
|
if (HasStateAuthority == false)
|
|
return;
|
|
|
|
_velocity = transform.rotation * (Vector3.forward * _maxSpeed);
|
|
}
|
|
|
|
public override void FixedUpdateNetwork()
|
|
{
|
|
if (HasStateAuthority == false)
|
|
return;
|
|
|
|
if (IsFinished == true)
|
|
return;
|
|
|
|
if (NeedsNewTarget() == true)
|
|
{
|
|
if (IsFlyingAway == true)
|
|
{
|
|
// Plane is near fly away target, let's despawn
|
|
IsFinished = true;
|
|
return;
|
|
}
|
|
else if (DropEnabled == true)
|
|
{
|
|
NextTargetPosition = FindNewTargetInZone();
|
|
}
|
|
else if (DropFinished == false)
|
|
{
|
|
// Waiting for drop start
|
|
NextTargetPosition = FindNewTargetOutsideZone();
|
|
}
|
|
else
|
|
{
|
|
NextTargetPosition = FindFlyAwayTarget();
|
|
IsFlyingAway = true;
|
|
}
|
|
}
|
|
|
|
UpdatePosition();
|
|
}
|
|
|
|
public override void Render()
|
|
{
|
|
_dropEnabledObject.SetActive(DropEnabled);
|
|
_dropDisabledObject.SetActive(DropEnabled == false);
|
|
}
|
|
|
|
// PRIVATE METHODS
|
|
|
|
private bool NeedsNewTarget()
|
|
{
|
|
if (NextTargetPosition == Vector3.zero)
|
|
return true;
|
|
|
|
return Vector3.SqrMagnitude(transform.position - NextTargetPosition) < _minDistanceToTargetChange * _minDistanceToTargetChange;
|
|
}
|
|
|
|
private Vector3 FindNewTargetInZone()
|
|
{
|
|
var area = Context.GameplayMode.ShrinkingArea;
|
|
|
|
var dirToPlane = (transform.position - area.Center).OnlyXZ().normalized;
|
|
var nextDirection = -dirToPlane + _velocity.OnlyXZ().normalized * 0.3f;
|
|
|
|
if (nextDirection == Vector3.zero)
|
|
{
|
|
nextDirection = -dirToPlane;
|
|
nextDirection.x += 5;
|
|
}
|
|
|
|
var areaPoint = area.Center + nextDirection.normalized * (area.Radius - _inZoneDistance);
|
|
areaPoint.y = transform.position.y;
|
|
|
|
return areaPoint;
|
|
}
|
|
|
|
private Vector3 FindNewTargetOutsideZone()
|
|
{
|
|
var area = Context.GameplayMode.ShrinkingArea;
|
|
var dirOutOfArea = (transform.position + transform.forward * 60f - area.Center).OnlyXZ().normalized;
|
|
|
|
var areaPoint = area.Center + dirOutOfArea * (area.Radius + _outZoneDistance);
|
|
areaPoint.y = transform.position.y;
|
|
|
|
return areaPoint;
|
|
}
|
|
|
|
private Vector3 FindFlyAwayTarget()
|
|
{
|
|
var area = Context.GameplayMode.ShrinkingArea;
|
|
var dirOutOfArea = (transform.position + transform.forward * 60f - area.Center).OnlyXZ().normalized;
|
|
|
|
var areaPoint = area.Center + dirOutOfArea * (area.Radius + 300f);
|
|
areaPoint.y = transform.position.y + 50f;
|
|
|
|
return areaPoint;
|
|
}
|
|
|
|
private void UpdatePosition()
|
|
{
|
|
float deltaTime = Runner.DeltaTime;
|
|
|
|
transform.position = transform.position + _velocity * deltaTime;
|
|
var directionToTarget = NextTargetPosition - transform.position;
|
|
|
|
var lastLeft = -transform.right;
|
|
lastLeft.y = 0f;
|
|
float directionDot = Vector3.Dot(directionToTarget.normalized, lastLeft.normalized);
|
|
float targetTilt = MathUtility.Map(-1f, 1f, -_maxTilt, _maxTilt, directionDot);
|
|
|
|
_tilt = Mathf.Lerp(_tilt, targetTilt, _tiltSpeed * deltaTime);
|
|
|
|
var newRotation = Quaternion.LookRotation(_velocity, Vector3.up).eulerAngles;
|
|
newRotation.z = _tilt;
|
|
transform.rotation = Quaternion.Euler(newRotation);
|
|
|
|
_velocity += directionToTarget.normalized * _maxAcceleration * deltaTime;
|
|
|
|
float speed = _velocity.magnitude;
|
|
if (speed > _maxSpeed)
|
|
{
|
|
_velocity = (_velocity / speed) * _maxSpeed;
|
|
}
|
|
}
|
|
}
|
|
}
|