897 lines
28 KiB
C#
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;
|
|
}
|
|
} |