641 lines
19 KiB
C#
641 lines
19 KiB
C#
using System;
|
|
using UnityEngine;
|
|
using static AffectingForcesManager;
|
|
using ShipHandling;
|
|
using Managers;
|
|
using Unity.Mathematics;
|
|
using FishNet.Object;
|
|
using FORGE3D;
|
|
using PrimeTween;
|
|
using log4net;
|
|
using System.Reflection;
|
|
using UnityEngine.Rendering.PostProcessing;
|
|
using FishNet.Object.Prediction;
|
|
using GameKit.Dependencies.Utilities;
|
|
using log4net.Filter;
|
|
using FishNet.Transporting;
|
|
|
|
public class PredictedShip : NetworkBehaviour, IHUDOwner
|
|
{
|
|
private static ILog Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
|
|
|
public event Action<float> BoostUpdated;
|
|
public event Action<float> LifeUpdated;
|
|
|
|
public int InstanceID { get; private set; }
|
|
public ShipProperties props;
|
|
public ShipState state;
|
|
public ShipInput input;
|
|
public BoostCapacityUI BoostUI { get; set; }
|
|
// Private variables
|
|
public CameraOperator cameraOperator;
|
|
public ParticleSystem boostEffect;
|
|
public ParticleSystem gravityEffect;
|
|
public ParticleSystem jetFlameEffect;
|
|
public ParticleSystem smokeTrailEffect;
|
|
|
|
public F3DFXController fireController;
|
|
public MeshRenderer bodyMeshRenderer;
|
|
|
|
private AffectingForcesManager forceManager;
|
|
// Saves the current input value for thrust
|
|
private bool canBoost = true;
|
|
private HitDetection[] tackleDetectors;
|
|
private bool isCriticalTackle = false;
|
|
private bool isTackled = false;
|
|
private float tackledTime = 0f;
|
|
private Tween tackleIgnoreTween = new();
|
|
private bool isFiring = false;
|
|
// Current Zone the player occupies
|
|
private Zone zone = Zone.NimbleZone;
|
|
// Upcoming zone change
|
|
private Zone newZone = Zone.NimbleZone;
|
|
|
|
private ManageableAudio ThrusterSound;
|
|
private ManageableAudio BoosterSound;
|
|
private ManageableAudio LeaveZoneSound;
|
|
private ManageableAudio EnterZoneSound;
|
|
private ManageableAudio TackleOpponentSound;
|
|
private ManageableAudio CriticalTackleOpponentSound;
|
|
private ManageableAudio BeingTackledSound;
|
|
private ManageableAudio BeingCriticallyTackledSound;
|
|
private ManageableAudio CrashOutOfBoundsSound;
|
|
|
|
public PredictionRigidbody PredictionRigidbody;
|
|
public GameObject smoothedRepresentation;
|
|
private Rigidbody body;
|
|
|
|
|
|
void Awake()
|
|
{
|
|
if (forceManager == null)
|
|
{
|
|
forceManager = GameObject.FindGameObjectWithTag("ForceManager").
|
|
GetComponent<AffectingForcesManager>();
|
|
}
|
|
|
|
|
|
ThrusterSound = AudioManager.G.GetLocalSound("thruster", 1, gameObject.transform);
|
|
BoosterSound = AudioManager.G.GetLocalSound("booster", 1, gameObject.transform);
|
|
BeingTackledSound = AudioManager.G.GetLocalSound("normal_tackle", 1, gameObject.transform);
|
|
BeingCriticallyTackledSound = AudioManager.G.GetLocalSound("critical_tackle", 1, gameObject.transform);
|
|
LeaveZoneSound = AudioManager.G.GetLocalSound("zone_change_out", 1, gameObject.transform);
|
|
EnterZoneSound = AudioManager.G.GetLocalSound("zone_change_in", 1, gameObject.transform);
|
|
|
|
PredictionRigidbody = ObjectCaches<PredictionRigidbody>.Retrieve();
|
|
PredictionRigidbody.Initialize(GetComponent<Rigidbody>());
|
|
body = GetComponent<Rigidbody>();
|
|
}
|
|
|
|
// Start is called before the first frame update
|
|
void Start()
|
|
{
|
|
InstanceID = gameObject.GetInstanceID();
|
|
state.BoostCapacity = props.MaxBoostCapacity;
|
|
// boostUI.SetMinBoostRatio(props.minBoostCapacity / props.maxBoostCapacity);
|
|
// GameManager.GM.RegisterPlayer(this);
|
|
cameraOperator.AddCharacter(smoothedRepresentation);
|
|
|
|
tackleDetectors = GetComponentsInChildren<HitDetection>();
|
|
foreach (HitDetection td in tackleDetectors)
|
|
{
|
|
td.TackledResponse += TackledResponse;
|
|
td.TacklingResponse += TacklingResponse;
|
|
}
|
|
}
|
|
|
|
public override void OnStartNetwork()
|
|
{
|
|
base.TimeManager.OnTick += TimeManager_OnTick;
|
|
base.TimeManager.OnPostTick += TimeManager_OnPostTick;
|
|
}
|
|
|
|
public override void OnStopNetwork()
|
|
{
|
|
base.TimeManager.OnTick -= TimeManager_OnTick;
|
|
base.TimeManager.OnPostTick -= TimeManager_OnPostTick;
|
|
}
|
|
|
|
void OnDestroy()
|
|
{
|
|
ObjectCaches<PredictionRigidbody>.StoreAndDefault(ref PredictionRigidbody);
|
|
foreach (HitDetection td in tackleDetectors)
|
|
{
|
|
td.TackledResponse = null;
|
|
td.TacklingResponse = null;
|
|
}
|
|
LifeUpdated = null;
|
|
BoostUpdated = null;
|
|
}
|
|
|
|
private void TimeManager_OnTick()
|
|
{
|
|
RunInputs(CreateReplicateData());
|
|
}
|
|
|
|
private ReplicateData CreateReplicateData()
|
|
{
|
|
//if (!base.IsOwner)
|
|
//return default;
|
|
ReplicateData rd = new ReplicateData(input.thrustInput, input.steerInput, input.boostInput);
|
|
return rd;
|
|
}
|
|
|
|
[Replicate]
|
|
private void RunInputs(ReplicateData rd, ReplicateState rstate = ReplicateState.Invalid,
|
|
Channel channel = Channel.Reliable)
|
|
{
|
|
//Debug.Log("inupdatemove " + currentThrustInput);
|
|
// Player rotation is always possible and same speed
|
|
transform.Rotate(0, 0, (float)(-props.SteerVelocity * rd.Steer * 2 * TimeManager.TickDelta));
|
|
//PredictionRigidbody.AddTorque(new Vector3(0, 0, -props.steerVelocity * rd.Steer * Time.deltaTime));
|
|
|
|
// // Get and apply the current Gravity
|
|
Transform gravitySource = forceManager.GetGravitySourceForInstance(InstanceID);
|
|
state.CurrentGravity = forceManager.GetGravityForInstance(InstanceID)(gravitySource, transform);
|
|
PredictionRigidbody.AddForce(state.CurrentGravity, ForceMode.Acceleration);
|
|
|
|
float stunFactor = isCriticalTackle ? props.StunLooseControlFactor : 1f;
|
|
|
|
float thrust = IsBoosting(rd.Boost) ? 1f : rd.Thrust;
|
|
Vector3 acceleration = props.ThrustAcceleration * thrust * (float)TimeManager.TickDelta
|
|
* transform.up * stunFactor * 2;
|
|
|
|
Vector3 currentVelocity = body.velocity;
|
|
|
|
Vector3 boostedAcceleration = BoostAcceleration(acceleration, state.CurrentGravity);
|
|
|
|
if (!isCriticalTackle)
|
|
{
|
|
// Add drag
|
|
if (zone == Zone.NimbleZone)
|
|
{
|
|
Vector3 dragDecceleration = DragDecceleration(currentVelocity, zone);
|
|
PredictionRigidbody.AddForce(dragDecceleration, ForceMode.Acceleration);
|
|
|
|
if (!isTackled)
|
|
{
|
|
// Add anti drift acceleration
|
|
Vector3 driftDampeningAcceleration =
|
|
DriftDampeningAcceleration(currentVelocity, zone);
|
|
PredictionRigidbody.AddForce(driftDampeningAcceleration, ForceMode.Acceleration);
|
|
}
|
|
}
|
|
|
|
if (currentVelocity.magnitude <= props.NormalMaxVelocity || IsBoosting(rd.Boost)
|
|
|| zone != Zone.NimbleZone)
|
|
{
|
|
PredictionRigidbody.AddForce(boostedAcceleration, ForceMode.Acceleration);
|
|
|
|
}
|
|
if (currentVelocity.magnitude >= props.AbsolutMaxVelocity && zone == Zone.NimbleZone)
|
|
{
|
|
body.velocity = body.velocity.normalized * props.AbsolutMaxVelocity;
|
|
}
|
|
}
|
|
|
|
// Default torque drag
|
|
PredictionRigidbody.AddRelativeTorque(body.angularVelocity * -props.TorqueDrag, ForceMode.Acceleration);
|
|
|
|
// Debug.DrawRay(transform.position, transform.up * (currentVelocity.magnitude + 3) * 0.5f,
|
|
// Color.black);
|
|
|
|
// Fix the ship to the virtual 2D plane of the game
|
|
transform.localEulerAngles = new Vector3(0, 0, transform.localEulerAngles.z);
|
|
body.transform.localPosition -= new Vector3(0, 0, transform.localPosition.z);
|
|
PredictionRigidbody.Simulate();
|
|
}
|
|
|
|
private void TimeManager_OnPostTick()
|
|
{
|
|
CreateReconcile();
|
|
}
|
|
|
|
public override void CreateReconcile()
|
|
{
|
|
ReconcileData md = new ReconcileData(PredictionRigidbody);
|
|
ReconcileState(md);
|
|
}
|
|
|
|
[Reconcile]
|
|
private void ReconcileState(ReconcileData rst, Channel channel = Channel.Unreliable)
|
|
{
|
|
PredictionRigidbody.Reconcile(rst.PredictionRigidbody);
|
|
}
|
|
|
|
// Update is called once per frame
|
|
void FixedUpdate()
|
|
{
|
|
// TODO: This belongs in the state object
|
|
newZone = forceManager.GetZoneOfInstance(InstanceID);
|
|
// TODO: This could be more elegant maybe?
|
|
if (MatchManager.G.matchState != MatchState.Match || state.IsFrozen)
|
|
{
|
|
body.constraints = RigidbodyConstraints.FreezeAll;
|
|
UpdateSounds();
|
|
zone = newZone;
|
|
return;
|
|
}
|
|
body.constraints = RigidbodyConstraints.None;
|
|
UpdateSounds();
|
|
if (zone != newZone)
|
|
{
|
|
zone = newZone;
|
|
}
|
|
//UpdateMovement();
|
|
BoostStateUpdate(Time.deltaTime);
|
|
UpdateTackleResponse(isCriticalTackle);
|
|
if (!isFiring && input.shootInput == 1)
|
|
{
|
|
isFiring = true;
|
|
fireController.Fire();
|
|
}
|
|
|
|
// Stop firing
|
|
if (isFiring && input.shootInput < 1)
|
|
{
|
|
isFiring = false;
|
|
fireController.Stop();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Movement logic and simulation of the ship.
|
|
/// </summary>
|
|
void UpdateMovement()
|
|
{
|
|
|
|
//Debug.Log("inupdatemove " + currentThrustInput);
|
|
// Player rotation is always possible and same speed
|
|
transform.Rotate(0, 0, -props.SteerVelocity * input.steerInput * Time.deltaTime);
|
|
|
|
// Get and apply the current Gravity
|
|
Transform gravitySource = forceManager.GetGravitySourceForInstance(InstanceID);
|
|
state.CurrentGravity = forceManager.GetGravityForInstance(InstanceID)(gravitySource, transform);
|
|
body.AddForce(state.CurrentGravity, ForceMode.Acceleration);
|
|
|
|
float stunFactor = isCriticalTackle ? props.StunLooseControlFactor : 1f;
|
|
|
|
float thrust = IsBoosting(input.boostInput) ? 1f : input.thrustInput;
|
|
Vector3 acceleration = props.ThrustAcceleration * thrust * Time.deltaTime
|
|
* transform.up * stunFactor;
|
|
|
|
Vector3 currentVelocity = body.velocity;
|
|
|
|
Vector3 boostedAcceleration = BoostAcceleration(acceleration, state.CurrentGravity);
|
|
|
|
if (!isCriticalTackle)
|
|
{
|
|
// Add drag
|
|
if (zone == Zone.NimbleZone)
|
|
{
|
|
Vector3 dragDecceleration = DragDecceleration(currentVelocity, zone);
|
|
body.AddForce(dragDecceleration, ForceMode.Acceleration);
|
|
|
|
if (!isTackled)
|
|
{
|
|
// Add anti drift acceleration
|
|
Vector3 driftDampeningAcceleration =
|
|
DriftDampeningAcceleration(currentVelocity, zone);
|
|
body.AddForce(driftDampeningAcceleration, ForceMode.Acceleration);
|
|
}
|
|
}
|
|
|
|
if (currentVelocity.magnitude <= props.NormalMaxVelocity || IsBoosting(input.boostInput)
|
|
|| zone != Zone.NimbleZone)
|
|
{
|
|
body.AddForce(boostedAcceleration, ForceMode.Acceleration);
|
|
|
|
}
|
|
if (currentVelocity.magnitude >= props.AbsolutMaxVelocity && zone == Zone.NimbleZone)
|
|
{
|
|
body.velocity = body.velocity.normalized * props.AbsolutMaxVelocity;
|
|
}
|
|
}
|
|
|
|
// Default torque drag
|
|
body.AddRelativeTorque(body.angularVelocity * -props.TorqueDrag, ForceMode.Acceleration);
|
|
|
|
Debug.DrawRay(transform.position, transform.up * (currentVelocity.magnitude + 3) * 0.5f,
|
|
Color.black);
|
|
|
|
// Fix the ship to the virtual 2D plane of the game
|
|
transform.localEulerAngles = new Vector3(0, 0, transform.localEulerAngles.z);
|
|
body.transform.localPosition -= new Vector3(0, 0, transform.localPosition.z);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Calculates a vector to mitigate the ship drifting when it's changing direction.
|
|
/// </summary>
|
|
/// <param name="currentVelocity">Current velocity of the ship</param>
|
|
/// <param name="zone">Zone which the ship is in</param>
|
|
/// <returns></returns>
|
|
Vector3 DriftDampeningAcceleration(Vector3 currentVelocity, Zone zone)
|
|
{
|
|
Vector3 antiDriftVelocity;
|
|
float antiDriftFactor;
|
|
// Cancel out inertia/drifting
|
|
Vector3 up = transform.up;
|
|
Vector3 driftVelocity = currentVelocity - Vector3.Project(currentVelocity, up);
|
|
if (driftVelocity.magnitude < 0.1)
|
|
{
|
|
return Vector3.zero;
|
|
}
|
|
|
|
antiDriftVelocity = Vector3.Reflect(-driftVelocity, up) - driftVelocity;
|
|
antiDriftFactor = Mathf.InverseLerp(props.AbsolutMaxVelocity, props.NormalMaxVelocity,
|
|
currentVelocity.magnitude);
|
|
|
|
antiDriftFactor = Mathf.Max(antiDriftFactor, props.MinAntiDriftFactor);
|
|
|
|
Debug.DrawRay(transform.position, currentVelocity.normalized * currentVelocity.magnitude * 2, Color.cyan);
|
|
Debug.DrawRay(transform.position, driftVelocity.normalized * 5, Color.red);
|
|
Debug.DrawRay(transform.position, antiDriftVelocity.normalized * 5, Color.green);
|
|
|
|
return antiDriftVelocity * props.AntiDriftAmount * antiDriftFactor;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Calculates drag on the ship depending on it's velocity and inhabited zone.
|
|
/// </summary>
|
|
/// <param name="currentVelocity">Velocity of the ship</param>
|
|
/// <param name="zone">Zone which the ship is in</param>
|
|
/// <returns></returns>
|
|
Vector3 DragDecceleration(Vector3 currentVelocity, Zone zone)
|
|
{
|
|
Vector3 drag = new Vector3();
|
|
float minDragFactor = Mathf.InverseLerp(props.AbsolutMaxVelocity, props.NormalMaxVelocity,
|
|
currentVelocity.magnitude);
|
|
|
|
float normalDragFactor = Mathf.InverseLerp(props.NormalMaxVelocity, 0,
|
|
currentVelocity.magnitude);
|
|
|
|
if (!IsBoosting(input.boostInput) && zone == Zone.NimbleZone)
|
|
{
|
|
drag -= currentVelocity.normalized * props.NormalDrag;
|
|
}
|
|
if (currentVelocity.magnitude >= props.NormalMaxVelocity && zone == Zone.NimbleZone)
|
|
{
|
|
drag -= currentVelocity.normalized * props.MaximumDrag;
|
|
}
|
|
return drag;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Is the boost input pressed and boosting possible?
|
|
/// </summary>
|
|
/// <returns>Boosting state</returns>
|
|
bool IsBoosting(float input)
|
|
{
|
|
return input > 0 && canBoost;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Applies boost to an acceleration vector.
|
|
/// This includes increasing acceleration and mitigating
|
|
/// the gravity.
|
|
/// </summary>
|
|
/// <param name="acceleration">Current acceleration vector</param>
|
|
/// <param name="currentGravity">Gravity vector which is in force</param>
|
|
/// <returns></returns>
|
|
Vector3 BoostAcceleration(Vector3 acceleration, Vector3 currentGravity)
|
|
{
|
|
if (IsBoosting(input.boostInput))
|
|
{
|
|
acceleration *= props.BoostMagnitude;
|
|
acceleration -= currentGravity * props.BoostAntiGravityFactor;
|
|
}
|
|
return acceleration;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Logic which depletes boost capacity when boost conditions are met.
|
|
/// </summary>
|
|
/// <param name="deltaTime">Time delta of the current frame</param>
|
|
void BoostStateUpdate(float deltaTime)
|
|
{
|
|
BoostUI.UpdateFill(Math.Min(state.BoostCapacity / props.MaxBoostCapacity, 1));
|
|
if (IsBoosting(input.boostInput))
|
|
{
|
|
state.BoostCapacity -= deltaTime;
|
|
}
|
|
if (canBoost && zone == Zone.OutsideZone)
|
|
{
|
|
state.BoostCapacity -= deltaTime * props.OutsideBoostRate;
|
|
}
|
|
if (state.BoostCapacity <= 0)
|
|
{
|
|
canBoost = false;
|
|
}
|
|
|
|
if ((input.boostInput <= 0 || !canBoost)
|
|
&& zone == Zone.NimbleZone
|
|
&& state.BoostCapacity <= props.MaxBoostCapacity)
|
|
{
|
|
state.BoostCapacity += deltaTime;
|
|
}
|
|
// When your boost capacity is still critical, you can't start boosting immediately again.
|
|
// TODO: This is not tested well enough with players.
|
|
if (canBoost == false && state.BoostCapacity >= props.MinBoostCapacity)
|
|
{
|
|
canBoost = true;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Logic which sets the tackled member variables and
|
|
/// updates them over time.
|
|
/// State logic depends on these variables and is responsible
|
|
/// for certain tackle behavior.
|
|
/// </summary>
|
|
/// <param name="gotTackled">Use true to process a tackle hit</param>
|
|
void UpdateTackleResponse(bool gotTackled = false)
|
|
{
|
|
if (gotTackled && !isTackled)
|
|
{
|
|
isTackled = true;
|
|
tackledTime = isCriticalTackle ? props.TackledCriticalStunTime :
|
|
props.TackledBodyStunTime;
|
|
return;
|
|
}
|
|
tackledTime -= Time.deltaTime;
|
|
if (tackledTime <= 0)
|
|
{
|
|
isTackled = false;
|
|
isCriticalTackle = false;
|
|
tackledTime = 0;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Disable tackle responeses for a given time
|
|
/// </summary>
|
|
async void TemporarilyIgnoreTackles(float duration)
|
|
{
|
|
if (tackleIgnoreTween.isAlive)
|
|
return;
|
|
tackleIgnoreTween = Tween.Delay(duration);
|
|
await tackleIgnoreTween;
|
|
}
|
|
|
|
private bool IgnoreTackle()
|
|
{
|
|
return tackleIgnoreTween.isAlive;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Response logic if the ship is tackling an opponend.
|
|
/// </summary>
|
|
void TacklingResponse()
|
|
{
|
|
if (IgnoreTackle())
|
|
return;
|
|
Log.Debug($"{props.ShipName} is tackling.");
|
|
TemporarilyIgnoreTackles(props.TacklingGraceTime);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called by the collision regions of the ship being tackled by an opponent.
|
|
/// Adds resulting forces to the ship and intiates the tackle response.
|
|
/// </summary>
|
|
/// <param name="tackleKind">Kind of the tackle. Depends on collision region.</param>
|
|
/// <param name="collider">Object which has collided with the collision region.</param>
|
|
void TackledResponse(TackleKind tackleKind, Collider collider)
|
|
{
|
|
if (IgnoreTackle())
|
|
return;
|
|
TemporarilyIgnoreTackles(props.TackledGraceTime);
|
|
|
|
float tacklePowerFactor = props.CriticalTacklePowerFactor;
|
|
if (tackleKind == TackleKind.IncomingCritical)
|
|
{
|
|
isCriticalTackle = true;
|
|
Log.Debug($"{props.ShipName} has been tackled critically.");
|
|
}
|
|
else if (tackleKind == TackleKind.IncomingNormal)
|
|
{
|
|
isCriticalTackle = false;
|
|
tacklePowerFactor = props.NormalTacklePowerFactor;
|
|
Log.Debug($"{props.ShipName} has been tackled.");
|
|
}
|
|
Vector3 colliderVelocity = collider.attachedRigidbody.velocity;
|
|
//Log.Debug("velocity " + colliderVelocity);
|
|
|
|
|
|
//Log.Debug("angle " + angle);
|
|
|
|
//Log.Debug("outvector " + outVector);
|
|
Vector3 force = colliderVelocity * tacklePowerFactor;
|
|
Vector3 resultForce = force / Math.Max(force.magnitude / 4000, 1);
|
|
|
|
resultForce = resultForce / Math.Max(0.001f, Math.Min(resultForce.magnitude / 500, 1));
|
|
Log.Debug(resultForce.magnitude);
|
|
|
|
|
|
body.AddForce(resultForce,
|
|
ForceMode.Acceleration);
|
|
UpdateTackleResponse(true);
|
|
}
|
|
|
|
void UpdateSounds()
|
|
{
|
|
if (MatchManager.G.matchState != MatchState.Match || state.IsFrozen)
|
|
{
|
|
|
|
if (newZone != zone
|
|
&& newZone == Zone.NimbleZone)
|
|
{
|
|
AudioManager.G.BroadcastAudioEffect(AudioEffects.LowPass, transform, false);
|
|
}
|
|
ThrusterSound.StopAudio();
|
|
gravityEffect.Clear();
|
|
gravityEffect.Stop();
|
|
return;
|
|
}
|
|
float velocityFactor = math.smoothstep(0, props.AbsolutMaxVelocity, body.velocity.magnitude);
|
|
if (math.abs(input.thrustInput) > 0 || IsBoosting(input.boostInput))
|
|
{
|
|
ThrusterSound.PlayAudio(true);
|
|
|
|
ThrusterSound.ChangePitch(velocityFactor);
|
|
if (!jetFlameEffect.isPlaying)
|
|
jetFlameEffect.Play();
|
|
}
|
|
else
|
|
{
|
|
ThrusterSound.FadeOutAudio(0.3f);
|
|
jetFlameEffect.Stop();
|
|
}
|
|
if (IsBoosting(input.boostInput))
|
|
{
|
|
if (!boostEffect.isPlaying)
|
|
boostEffect.Play();
|
|
if (!smokeTrailEffect.isPlaying)
|
|
smokeTrailEffect.Play();
|
|
if (jetFlameEffect.isPlaying)
|
|
jetFlameEffect.transform.localScale = new Vector3(1.3f, 2, 1);
|
|
BoosterSound.PlayAudio(false, 0.1f, true);
|
|
}
|
|
else
|
|
{
|
|
BoosterSound.ResetOneShot();
|
|
smokeTrailEffect.Stop();
|
|
jetFlameEffect.transform.localScale = new Vector3(1.3f, 1, 1);
|
|
}
|
|
if (isTackled && !isCriticalTackle)
|
|
{
|
|
BeingTackledSound.PlayAudio(false, 0, true);
|
|
cameraOperator.ShakeCam(0.2f);
|
|
}
|
|
if (isCriticalTackle)
|
|
{
|
|
BeingCriticallyTackledSound.PlayAudio(false, 0, true);
|
|
cameraOperator.ShakeCam(0.4f);
|
|
}
|
|
if (!isTackled)
|
|
{
|
|
BeingCriticallyTackledSound.ResetOneShot();
|
|
BeingTackledSound.ResetOneShot();
|
|
}
|
|
if (newZone != zone
|
|
&& zone != Zone.UninitializedZone
|
|
&& newZone != Zone.UninitializedZone)
|
|
{
|
|
if (newZone != Zone.NimbleZone)
|
|
{
|
|
LeaveZoneSound.ChangePitch(velocityFactor);
|
|
LeaveZoneSound.PlayAudio(false);
|
|
AudioManager.G.BroadcastAudioEffect(AudioEffects.LowPass, transform, true);
|
|
}
|
|
else
|
|
{
|
|
EnterZoneSound.ChangePitch(velocityFactor);
|
|
EnterZoneSound.PlayAudio(false);
|
|
AudioManager.G.BroadcastAudioEffect(AudioEffects.LowPass, transform, false);
|
|
}
|
|
}
|
|
|
|
if (gravityEffect == null)
|
|
{
|
|
return;
|
|
}
|
|
if (!gravityEffect.isPlaying && state.CurrentGravity != Vector3.zero)
|
|
{
|
|
gravityEffect.Play();
|
|
}
|
|
else if (state.CurrentGravity == Vector3.zero)
|
|
{
|
|
gravityEffect.Stop();
|
|
}
|
|
if (gravityEffect.isPlaying)
|
|
{
|
|
float gravityAngle =
|
|
Vector3.SignedAngle(transform.parent.up, state.CurrentGravity, transform.forward);
|
|
gravityEffect.gameObject.transform.localEulerAngles =
|
|
new Vector3(0, 0, gravityAngle - transform.localEulerAngles.z);
|
|
|
|
}
|
|
}
|
|
|
|
}
|