UPF/Assets/Game/Scripts/Minigame/SpaceshipController.cs
2022-12-14 01:49:10 +05:30

897 lines
28 KiB
C#

using System.Collections.Generic;
using UnityEngine;
using Mirror;
using System.Linq;
using UnityEngine.UI;
using System.Collections;
using CustomExtensions;
public class SpaceshipController : NetworkBehaviour
{
[SyncVar]
public bool ready;
public SpriteRenderer playerImg;
public SkinsData skins;
[SyncVar(hook = nameof(OnSkinChanged))]
public string skinName = null;
[SyncVar(hook = nameof(OnPnameChanged))]
public string pname;
[SyncVar(hook = nameof(OnScoresChanged))]
public int Scores;
[SyncVar(hook = nameof(OnKillsChanged))]
public int Kills;
[SyncVar(hook = nameof(OnTrailTimeChanged))]
public float trailTime;
public float minTrailTime;
public float maxTrailTime;
[SyncVar]
public int moonsCollected;
public float trailIncrementRate = 0.5f;
[SyncVar]
public bool dead;
[SyncVar]
public float speed;
[SyncVar]
public float speedMultiplier;
[SyncVar]
public float boostConsumption;
[SyncVar]
public float energyGain;
public float _scaleMultiplier = 1;
public Text pnameTxt;
public Transform body;
public TrailMgr trailMgr;
public float movingSpeed = 0.1f;
public float turningSmoothFactor = 0.1f;
public Joystick joystick;
[SyncVar]
public bool boosting;
[Header("Client Prediction")]
private Vector2 input;
[SyncVar]
public Vector2 m_Input;
[SerializeField]private float rubberbandSmoothness = 0.3f;
private float timer;
private int currentTick;
private float minTimeBetweenTicks;
private const float SERVER_TICK_RATE = 30f;
private const int BUFFER_SIZE = 2048;
private float ERROR_THRESHOLD =0.25f;
private int MIN_ERROR_COUNT = 10;
public bool showDebugHUD = false;
private double clientNetworkRTT;
public InputState[] clientInputBuffer;
public InputState[] serverInputBuffer;
public PlayerState[] clientStateBuffer;
public PlayerState[] serverStateBuffer;
[SerializeField]private int ErrorInputCount;
[SerializeField]private int ErrorStateCount;
[SerializeField]private int RubberBandsCount;
public GameObject DeathEffect;
public GameObject debrisEffect;
// public GameObject boostStartEffect;
public ParticleSystem[] boostStartEffect;
public ParticleSystem[] boostEffects;
// public GameObject PickupEffect;
public float distanceFromCenter = 0;
RocketLevel rocketStats;
[Header("AudioFX")]
public AudioSource engineAudio;
public float normalPitch,boostedPitch;
public void SetReady(bool value)
{
if (isServer)
{
ready = value;
}
else
{
CmdSetReady(value);
}
}
[Command]
void CmdSetReady(bool value)
{
ready = value;
}
[Command]
void CmdSetPname(string value)
{
pname = value;
}
void OnPnameChanged(string oldName, string newName)
{
pnameTxt.text = newName;
Debug.Log(pname + " Joined the game");
}
[Command]
void CmdSetSkin(string newSkin)
{
skinName = newSkin;
}
[Command]
void CmdSetStats(float _speed, float _energy, float _boost)
{
speedMultiplier = _speed;
energyGain = _energy;
boostConsumption = _boost;
}
void OnSkinChanged(string oldSkin, string newSkin)
{
ChangeSkin(newSkin);
}
void ChangeSkin(string name)
{
Sprite newSprite = SkinManagerHelper.getSkinSprite(name, skins);
playerImg.sprite = newSprite;
}
void OnScoresChanged(int oldScores, int newScores)
{
Debug.Log($"Add scores {newScores - oldScores}, (total: {newScores})");
}
bool isBoostAvailable {get{ return trailTime > minTrailTime;}}
void OnTrailTimeChanged(float oldValue, float newValue)
{
trailMgr.trail.time = newValue;
if (isLocalPlayer)
{
// SceneData.holder.boostBtn.gameObject.SetActive(isBoostAvailable);
SceneData.holder.boostBtn.transform.GetChild(0).gameObject.SetActive(isBoostAvailable);
SceneData.holder.boostBtn.transform.GetChild(0).GetChild(0).gameObject.SetActive(trailTime > maxTrailTime/2f);
SceneData.holder.boostBtn.transform.GetChild(0).GetChild(1).gameObject.SetActive(trailTime > maxTrailTime* 0.8f);
SceneData.holder.boostBtn.transform.GetChild(0).GetChild(2).gameObject.SetActive(trailTime >= maxTrailTime);
SceneData.holder.boostBtn.transform.GetChild(0).Find("Slider").GetComponent<Image>().fillAmount = Mathf.Clamp(0.73f - ((trailTime /maxTrailTime)*0.73f),0f,0.73f);
if (!isBoostAvailable && boosting)
{
CmdSetBoosting(false);
}
}
}
void OnBoostDown()
{
if(!isBoostAvailable){return; }
if (isLocalPlayer)
{
AudioManager.instnace.Boost();
if (isServer)
{
boosting = true;
}
else
{
CmdSetBoosting(true);
}
CameraFollower.instance.ShakeBoost();
// GameObject fx = EffectPool.Spawn(boostStartEffect, transform.position);
foreach(ParticleSystem particle in boostStartEffect){
particle.Play();
}
}
}
void OnBoostUp()
{
if (isLocalPlayer)
{
if (isServer)
{
boosting = false;
}
else
{
CmdSetBoosting(false);
}
}
}
[Command]
void CmdSetBoosting(bool value)
{
boosting = value;
}
[SyncVar]
double startedTime = 0;
void ResetStats()
{
startedXp = DBmanager.Xp;
startedMetal = DBmanager.Metal;
}
void Start()
{
clientInputBuffer = new InputState[BUFFER_SIZE];
serverInputBuffer = new InputState[BUFFER_SIZE];
clientStateBuffer = new PlayerState[BUFFER_SIZE];
serverStateBuffer = new PlayerState[BUFFER_SIZE];
NetworkTime.PingFrequency = SERVER_TICK_RATE;
minTimeBetweenTicks = 1f / SERVER_TICK_RATE;
string[] args = System.Environment.GetCommandLineArgs();
for (int i = 0; i < args.Length; i++)
{
// Debug.Log("ARG " + i + ": " + args[i]);
if (args[i] == "-et")
{
ERROR_THRESHOLD =float.Parse(args[i+1]);
}
if(args[i] == "-grace"){
MIN_ERROR_COUNT = int.Parse(args[i+1]);
}
}
if (isLocalPlayer)
{
ResetStats();
if (MinigameManager.instance.isRanked)
{
DBmanager.SetMetal(DBmanager.Metal + DBmanager.CurrentRank.energyReward);
DBmanager.SetMetal(DBmanager.Metal - DBmanager.CurrentRank.entryFee);
}
if (joystick == null) { joystick = FindObjectOfType<Joystick>(); }
FindObjectOfType<CameraFollower>().SetTarget(transform);
string myName = PlayerPrefs.GetString("username");
SceneData.localPlayer = gameObject;
SceneData.OnBoostDown.AddListener(OnBoostDown);
SceneData.OnBoostUp.AddListener(OnBoostUp);
//Set username
if (isServer) { pname = myName; }
else
{
CmdSetPname(myName);
}
//Set Skin
if (DBmanager.GetSkinIdByName(SkinShopManager.GetEquipedSkin()) < 0)
{
//False skin purchase
}
else
{
string skin = SkinShopManager.GetEquipedSkin();
SkinType rarity = SkinShopManager.GetRarityFromName(skin);
PurchasedSkin purchasedSkin = DBmanager.GetSkinByName(skin);
float m_speed = SkinShopManager.GetStatsForRarity(rarity)[purchasedSkin.speedLevel].speedMultiplier;
float m_energy = SkinShopManager.GetStatsForRarity(rarity)[purchasedSkin.energyLevel].moonMultiplier;
float m_boost = SkinShopManager.GetStatsForRarity(rarity)[purchasedSkin.boostLevel].boostConsumption;
if (isServer)
{
skinName = skin;
speedMultiplier = m_speed;
energyGain = m_energy;
boostConsumption = m_boost;
}
else
{
CmdSetSkin(skin);
CmdSetStats(m_speed, m_energy, m_boost);
}
}
pnameTxt.text = myName;
pnameTxt.gameObject.SetActive(false);
}
if (isServer)
{
startedTime = NetworkTime.time;
trailTime = 0;
DecreaseTrail(0);
}else{
if(AudioManager.SFX_enabled){
engineAudio.volume = 1;
}else{
engineAudio.volume= 0;
}
}
}
// Update is called once per frame
int timeInMillis => (int)(NetworkTime.time * 1000);
int roundedTime => Mathf.FloorToInt((float)timeInMillis / 100f) * 100;
int lastClientUpdateTime = 0;
Vector3 lineCorrection;
float scale => Mathf.Clamp(1 + (trailTime * _scaleMultiplier), 1, 10);
void Update()
{
if (MinigameManager.instance.isRanked && !MinigameManager.instance.RankedGameStarted) { return; }
distanceFromCenter = Vector3.Distance(transform.position, Vector3.zero);
pnameTxt.rectTransform.rotation = Quaternion.Euler(Vector3.zero);
//Update size of trail and spaceship
transform.localScale = Vector3.Lerp(transform.localScale, new Vector3(scale, scale, scale), 0.1f);
trailMgr.trail.startWidth = Mathf.Lerp(trailMgr.trail.startWidth, scale, 0.1f);
if (dead) { return; }
if(isLocalPlayer){
input = joystick.input;
if (Input.GetKeyDown(KeyCode.F))
{
CmdCheatKills();
}
if(Input.GetKeyDown(KeyCode.Space)){
OnBoostDown();
}
if(Input.GetKeyUp(KeyCode.Space)){
OnBoostUp();
}
// Debug.Log(startedTime-NetworkTime.time);
double survivalTime = (startedTime == 0) ? 0 : NetworkTime.time - ((MinigameManager.instance.isRanked) ? MinigameManager.instance.startedTime : startedTime);
if (DBmanager.MostTime < (int)survivalTime)
{
DBmanager.SetMostTime((int)survivalTime);
}
SceneData.SetTimerTxt(survivalTime);
}
timer += Time.deltaTime;
while(timer >= minTimeBetweenTicks){
timer -= minTimeBetweenTicks;
HandleTick();
currentTick++;
}
}
Vector3 serverPosition => serverStateBuffer[bufferIndex].Position;
Vector3 clientPosition => clientStateBuffer[bufferIndex].Position;
int curBufferIndex;
int errorCounter = 0;
int bufferIndex => currentTick % BUFFER_SIZE;
int ticksGap => (int)(clientNetworkRTT * SERVER_TICK_RATE);
int latencyBufferIndex {
get{
int val =(int)(bufferIndex - (clientNetworkRTT * SERVER_TICK_RATE));
if(val < 0){
val = BUFFER_SIZE - val;
}
if(val >= BUFFER_SIZE || val < 0){
Debug.LogError(val + " is bigger than buffer size, latency: " + clientNetworkRTT);
val = BUFFER_SIZE-1;
}
return val;
}
}
public float MovementSmoothnessFactor = 0.1f;
void HandleTick(){
curBufferIndex = bufferIndex;
if(isLocalPlayer){
// HandleInput(input);
InputState curInputState = new InputState(){Tick=currentTick, Input = input};
PlayerState curState = new PlayerState(){Tick=currentTick, Position= transform.position, Rotation = transform.rotation};
clientInputBuffer[bufferIndex] = curInputState;
clientStateBuffer[bufferIndex] = curState;
// transform.Translate(transform.forward * input.y);
// transform.Rotate(transform.up * input.x);
UpdateStates(currentTick, NetworkTime.rtt, input, curState.Position, curState.Rotation);
body.position = targetState.Position;
body.rotation = targetState.Rotation;
// body.position = Vector3.Lerp(body.position,targetState.Position,MovementSmoothnessFactor * movingSpeed);
// body.rotation = Quaternion.Lerp(body.rotation, targetState.Rotation,MovementSmoothnessFactor*movingSpeed);
}else if (isServer){
HandleInput(m_Input);
RpcUpdateOnClient(body.position, body.rotation, m_Input);
}else{
//client but not localPlayer
body.position = targetState.Position;
body.rotation = targetState.Rotation;
// for(int i = 0; i < ticksGap; i++){
// HandleInput(m_Input);
// }
}
if(isLocalPlayer){CameraFollower.UpdateFrame();}
float stateError = clientStateBuffer[bufferIndex].Difference(serverStateBuffer[latencyBufferIndex]);
foreach(ParticleSystem boostEffect in boostEffects){
if(boostEffect.isEmitting && !boosting){
boostEffect.Stop();
}else if(!boostEffect.isEmitting && boosting){
boostEffect.Play();
}
}
if(isServer){
InputState curServerInputState = new InputState(){Tick=currentTick, Input = m_Input};
PlayerState curServerState = new PlayerState(){Tick=currentTick, Position = transform.position, Rotation = transform.rotation};
serverInputBuffer[bufferIndex] = curServerInputState;
serverStateBuffer[bufferIndex] = curServerState;
if(!clientInputBuffer[bufferIndex].CloseEnough(serverInputBuffer[latencyBufferIndex],ERROR_THRESHOLD)){
ErrorInputCount++;
}
// if(!clientStateBuffer[bufferIndex].CloseEnough(serverStateBuffer[latencyBufferIndex],ERROR_THRESHOLD)){
if(stateError > ERROR_THRESHOLD){
ErrorStateCount++;
errorCounter++;
if(errorCounter> MIN_ERROR_COUNT){RpcRubberband(transform.position, transform.rotation); errorCounter=0;}
}else{
errorCounter = 0;
}
//boost check
if (boosting && scale > 1)
{
speed = movingSpeed * 2 * speedMultiplier;
DecreaseTrail(Time.deltaTime * boostConsumption * 0.5f);
// scaleMultiplier -= Time.deltaTime;
// if (scaleMultiplier < 1) { scaleMultiplier = 1; } //Clamp in case gets lower
}
else
{
speed = movingSpeed * speedMultiplier;
}
}else{ // not server
engineAudio.pitch = Mathf.Lerp(engineAudio.pitch, (boosting) ? boostedPitch : normalPitch, 0.1f);
}
}
void HandleInput(Vector2 _input){
// transform.Translate(transform.forward * _input.y);
// transform.Rotate(transform.up * _input.x);
body.Translate(new Vector3(0, speed), body);
Turn(_input);
}
void UpdateStates(int tick,double rtt,Vector2 m_input, Vector3 m_position, Quaternion m_rotation){
if(isServer){
m_updateInput(tick,rtt,m_input, m_position, m_rotation);
}else{
CmdUpdateInput(tick,rtt,m_input, m_position, m_rotation);
}
}
[Command]
void CmdUpdateInput(int tick,double rtt, Vector2 m_input, Vector3 m_position, Quaternion m_rotation){
m_updateInput(tick,rtt,m_input, m_position, m_rotation);
}
private void m_updateInput(int tick,double rtt, Vector2 m_input, Vector3 m_position, Quaternion m_rotation){
clientNetworkRTT = rtt;
m_Input = m_input;
clientInputBuffer[bufferIndex] = new InputState(){Tick=tick, Input=m_input};
clientStateBuffer[bufferIndex] = new PlayerState(){Tick=tick, Position=m_position, Rotation=m_rotation};
}
[ClientRpc]
void RpcRubberband(Vector3 m_position, Quaternion m_rotation){
PlayerState serverState = new PlayerState(){Tick=0, Position = m_position, Rotation = m_rotation};
PlayerState clientState = new PlayerState(){Tick=0, Position = transform.position, Rotation = transform.rotation};
float diff = serverState.Difference(clientState);
Debug.Log("Rubber banded, Strength -> " + diff);
if(diff < 0.3f){
transform.position = Vector3.Lerp(transform.position, m_position, rubberbandSmoothness);
// transform.rotation = Quaternion.Lerp(transform.rotation, m_rotation,rubberbandSmoothness);
transform.rotation = m_rotation;
return;
}
transform.position = m_position;
transform.rotation = m_rotation;
RubberBandsCount++;
}
PlayerState targetState;
[ClientRpc]
void RpcUpdateOnClient(Vector3 m_position, Quaternion m_rotation, Vector2 _input){
if(isLocalPlayer){
// return;
}
targetState = new PlayerState(){Position = m_position, Rotation = m_rotation};
}
void Turn(Vector2 input)
{
body.rotation = Quaternion.Lerp(body.rotation, getTurnAngle(input), turningSmoothFactor * input.magnitude);
}
Quaternion getTurnAngle(Vector2 input)
{
var angle1 = Mathf.Atan2(-input.y, -input.x) * Mathf.Rad2Deg;
return Quaternion.AngleAxis(angle1 + 90, Vector3.forward);
}
[ClientRpc]
void RpcUpdateTrail(Vector3[] positions)
{
//trailMgr.trail.SetPositions(positions);
}
void OnGUI()
{
if (!isLocalPlayer) { return; }
if (showDebugHUD)
{
Vector3 bodyOnScreen = Camera.main.WorldToScreenPoint(body.position);
// Vector3 DetourOnScreen = Camera.main.WorldToScreenPoint(body.position + Detour);
Vector3 bodyUpOnScreen = Camera.main.WorldToScreenPoint(body.position + body.up);
Vector3 bodyRightOnScreen = Camera.main.WorldToScreenPoint(body.position + body.right);
// GUI.Label(new Rect(DetourOnScreen.x,DetourOnScreen.y, 100, 20), Detour.ToString());
// GUI.Label(new Rect(bodyUpOnScreen.x,bodyUpOnScreen.y, 100, 20), body.up.ToString());
// GUI.Label(new Rect(bodyRightOnScreen.x, bodyRightOnScreen.y, 100, 20), body.right.ToString());
GUI.Label(new Rect(Screen.width - 120, 10, 100, 20), transform.position.ToString());
GUI.Label(new Rect(Screen.width - 120, 30, 100, 20), timeInMillis.ToString());
GUI.Label(new Rect(Screen.width - 100, Screen.height - 30, 50, 20), (NetworkTime.rtt * 1000).ToString() + " ms");
}
}
public float Angle(Vector2 vector2)
{
return 360 - (Mathf.Atan2(vector2.x, vector2.y) * Mathf.Rad2Deg * Mathf.Sign(vector2.x));
}
//Auto assign default variables [Editor only]
void OnValidate()
{
if (body == null)
{
body = transform;
}
if (trailMgr == null)
{
trailMgr = GetComponent<TrailMgr>();
}
}
public void TrailCollided(Collider2D hit)
{
if (!isServer)
{
Debug.Log("Got hit : " + hit.name);
// Debug.Log("This cannot run on client, That's illegal!"); // <-- What this log says
return;
}
SpaceshipController deadPlayer = hit.GetComponent<SpaceshipController>();
Debug.Log("got hit by player? : " + (deadPlayer != null));
if (deadPlayer != null && !deadPlayer.dead && (NetworkTime.time - deadPlayer.startedTime) > 5)
{ // <-- okay we killed someone | KILLCODE
// deadPlayer.RpcShowDeathEffect(deadPlayer.transform.position);
deadPlayer.Die(pname);
Debug.Log($"{pname} killed {deadPlayer.pname}");
OnKill();
}
}
public void ShowDeathEffect(Vector2 position){
if(isServer){
// MinigameManager.instance.ShowDeathEffect(position);
EffectPool.Spawn(DeathEffect, position);
RpcShowDeathEffect(position);
}else{
CmdShowDeathEffect(position);
}
}
[Command]
void CmdShowDeathEffect(Vector2 position){
EffectPool.Spawn(DeathEffect, position);
RpcShowDeathEffect(position);
}
[ClientRpc]
void RpcShowDeathEffect(Vector2 position){
EffectPool.Spawn(DeathEffect, position);
EffectPool.Spawn(debrisEffect, position).GetComponent<DebrisEffect>().Play();
}
void OnKill()
{
Kills++;
// Scores += 10; //TODO: Need to change Scores on kills?
// scaleMultiplier += 0.05f;
// OnScaleChanged(scaleMultiplier, scaleMultiplier);
IncreaseTrail(trailIncrementRate);
RpcOnKill();
}
[ClientRpc]
void RpcOnKill()
{
}
void OnKillsChanged(int oldVal, int newVal)
{
if (isLocalPlayer)
{
Debug.Log("Show kills for " + newVal);
KillText.Show(newVal);
}
}
void IncreaseTrail(float rate)
{
trailTime = Mathf.Clamp(trailMgr.trail.time + rate, minTrailTime, maxTrailTime);
trailMgr.trail.time = trailTime;
// Debug.Log("Increasing trail of" + pname);
}
public void DecreaseTrail(float rate)
{
trailTime = Mathf.Clamp(trailMgr.trail.time - rate, minTrailTime, maxTrailTime);
trailMgr.trail.time = trailTime;
// Debug.Log("Decreasing trail of" + pname);
}
[Command]
void CmdCheatKills()
{
OnKill();
}
public void CollectPickup(PickupItem.PickupType type)
{
if (!isServer) { Debug.Log("Server function ran on client. That's illegal!"); } // <-- What this log says
if(type == PickupItem.PickupType.Moon1 || type == PickupItem.PickupType.Moon2|| type == PickupItem.PickupType.Moon3|| type == PickupItem.PickupType.Moon4|| type == PickupItem.PickupType.Moon5){
//Moon!
IncreaseTrail(trailIncrementRate);
// scaleMultiplier += 0.05f;
moonsCollected++;
Scores += 2;
}else {
IncreaseTrail(trailIncrementRate / 2f);
Scores += 1;
}
RpcCollectPickup(type);
}
[ClientRpc]
void RpcCollectPickup(PickupItem.PickupType type)
{
if (isLocalPlayer)
{
if (type == PickupItem.PickupType.Twep)
{
DBmanager.SetTweps(DBmanager.Tweps + 1);
}
else
{
int gainedEnergy = (int)(energyGain * type.GetEnergy());
MinigameManager.instance.GainMetals(gainedEnergy);
}
AudioManager.instnace.CollectMoon(trailTime,maxTrailTime);
}
}
public void Die(string killer)
{
MinigameManager.instance.SpawnLeftoverPickups(transform.position, (int)((float)Scores / 4f));
RpcShowDeathEffect(transform.position);
Debug.Log($"Sending death signal to {pname} by {killer}");
//Handle Respawning
// OnScaleChanged(scaleMultiplier, 1);
// scaleMultiplier = 1;
dead = true;
Scores = 0;
Kills = 0;
startedTime = NetworkTime.time;
DecreaseTrail(trailTime);
trailMgr.trail.time = trailTime;
RpcDie(killer);
gameObject.SetActive(false);
//MinigameManager.instance.SetRespawn(gameObject);
}
private int startedXp;
private int startedMetal;
bool RewardedRankedMetal = false;
[ClientRpc]
public void RpcDie(string killer)
{
Debug.Log($"{killer} killed {pname} : isItMe? -> {isLocalPlayer}");
KillfeedMgr.instance.AddNewEntry($"<b>{pname}</b> was killed by <b>{killer}</b>");
gameObject.SetActive(false);
if (isLocalPlayer)
{
//TODO: Death message goes here
SceneData.holder.ShowDeadscreen(DBmanager.Xp - startedXp, DBmanager.Metal - startedMetal, NetworkTime.time - startedTime);
if (MinigameManager.instance.isRanked)
{
// MinigameManager.instance.rankedSummary.ShowLoss();
// StartCoroutine(ShowRankedResults());
if (MinigameManager.instance.winnerId <= 0)
{
Debug.LogError("Winner ID not synced yet");
}
if (MinigameManager.instance.winnerId != netId)
{
//LOSER!
MinigameManager.instance.rankedSummary.ShowLoss();
AudioManager.instnace.MinigameLost();
}
else
{
MinigameManager.instance.rankedSummary.ShowWin();
AudioManager.instnace.MinigameWon();
}
}
}
}
IEnumerator ShowRankedResults()
{
while (MinigameManager.instance.winnerId <= 0)
{
yield return new WaitForFixedUpdate();
}
}
public void Respawn(Vector3 respawnPoint)
{
Debug.Log("Respawning " + pname);
if (isServer)
{
respawn(respawnPoint);
}
else
{
CmdRespawn(respawnPoint);
}
}
[Command]
void CmdRespawn(Vector3 respawnPoint)
{
respawn(respawnPoint);
}
public void respawn(Vector3 respawnPoint)
{
dead = false;
trailMgr.trail.emitting = false;
trailMgr.trail.Clear();
RpcRespawn(respawnPoint);
transform.position = respawnPoint;
trailMgr.trail.emitting = true;
gameObject.SetActive(true);
}
[ClientRpc]
public void RpcRespawn(Vector3 respawnPoint)
{
GetComponent<NetworkTrail>().enableValidation = false;
trailMgr.trail.Clear();
trailMgr.positions = new Vector3[0];
trailMgr.trail.emitting = false;
transform.position = respawnPoint;
trailMgr.trail.emitting = true;
GetComponent<NetworkTrail>().enableValidation = true;
gameObject.SetActive(true);
if (isLocalPlayer)
{
SceneData.holder.deadScreen.SetActive(false);
ResetStats();
}
}
[Command]
public void CmdWonRanked()
{
WonRanked();
}
[Command]
public void CmdLostRanked()
{
LostRanked();
}
public void WonRanked()
{
if (!isServer)
{
return;
}
RpcWonRanked();
Die("server");
}
[ClientRpc]
void RpcWonRanked()
{
if (isLocalPlayer)
{
DBmanager.SetMetal(DBmanager.Metal + 500);
MinigameManager.instance.rankedSummary.ShowWin();
//Add trophies
DBmanager.SetTrophies(DBmanager.Trophies + 30);
}
}
public void LostRanked()
{
if (!isServer)
{
return;
}
RpcLostRanked();
Die("server");
}
void RpcLostRanked()
{
if (isLocalPlayer)
{
DBmanager.SetMetal(DBmanager.Metal + 250);
MinigameManager.instance.rankedSummary.ShowLoss();
// DBmanager.SetTrophies(Mathf.Clamp(DBmanager.Trophies - 15, 0, int.MaxValue));
DBmanager.SetTrophies(Mathf.Clamp(DBmanager.Trophies - DBmanager.CurrentRank.trophieLoss, 0, int.MaxValue));
}
}
}
public class StatePayload
{
public int Time;
public Vector3 Position;
public Quaternion Rotation;
public Vector2 Input;
public StatePayload(int time, Vector3 position, Quaternion rotation, Vector2 input)
{
Time = time;
Position = position;
Rotation = rotation;
Input = input;
}
}