metahunt/Assets/Scripts/PlayerNetwork.cs
2024-02-11 13:53:18 +05:30

485 lines
16 KiB
C#

using DamageNumbersPro;
using Photon.Pun;
using Photon.Realtime;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.Animations.Rigging;
using static UnityEngine.EventSystems.EventTrigger;
public class PlayerNetwork : MonoBehaviourPunCallbacks, IPunObservable
{
public string username;
public string partyname;
public string partyId;
public Rig weaponRig;
public Rig aimRig;
public Animator anim;
public RuntimeAnimatorController defaultAnim;
public Transform lookAtTarget;
public List<PlayerWeaponEntry> weapons;
public List<LootObjectEntry> nades;
public int selectedWeaponIndex = -1;
public int selectedNadeIndex=-1;
[Range(0,100f)]
public float health = 100;
[Range(0,100f)]
public float shield = 100;
public int kills;
public int deaths;
public int assists;
PlayerFX playerFX;
public AnimationCurve DistanceDamageCurve;
public float BulletEffectiveRange;
List<HitBox> hitboxes = new List<HitBox>();
public void RegisterHitbox(HitBox hitBox){
if(hitboxes == null){hitboxes = new List<HitBox>();}
hitboxes.Add(hitBox);
}
void Awake()
{
playerController = GetComponent<PlayerController>();
playerFX = GetComponent<PlayerFX>();
}
void Start()
{
if (photonView.IsMine)
{
photonView.RPC("RpcSyncName", RpcTarget.AllBuffered ,string.IsNullOrEmpty(LoginManager.username) ? "Dev0" : LoginManager.username);
UIManager.SetHealth(health,shield);
UIManager.SetUsername( username);
//
partyId = GameManager.partyId;
List<string> availablePartyNames = Helpers.battleTeamNames.ToList<string>();
string partyName = Helpers.RandomTeamName;
PlayerNetwork[] players = FindObjectsOfType<PlayerNetwork>();
bool foundMyParty = false;
foreach(PlayerNetwork player in players){
if(player == this){continue;}
if(player.partyId == partyId){
//Found my party!
partyName = player.partyname;
foundMyParty = true;
Debug.Log("Found my party! Its called " + player.partyname);
break;
}else{
if(availablePartyNames.Contains(player.partyname)){
availablePartyNames.Remove(player.partyname);
}
}
}
if(!foundMyParty){
partyName = availablePartyNames[UnityEngine.Random.Range(0, availablePartyNames.Count)];
Debug.Log("Got a new party name! : " + partyName);
}
partyname = partyName;
}
GetComponent<CharacterController>().detectCollisions=false;
}
public void SetActiveWeapon(LootItemScriptableObject data)
{
int _selectedIndex = -1;
int _selectedNadeIndex =-1;
if(data == null){
selectedNadeIndex = _selectedNadeIndex;
selectedWeaponIndex = _selectedIndex;
return;
}
if(data.isThrowable){
_selectedIndex=-1;
for(int i=0;i < nades.Count; i++){
if(nades[i].data == data){
_selectedNadeIndex=i;
break;
}
}
}else{
_selectedNadeIndex=-1;
for(int i=0; i < weapons.Count; i++)
{
if (weapons[i].data == data)
{
_selectedIndex = i;
UpdatePlayerFX(weapons[i]);
break;
}
}
}
selectedNadeIndex =_selectedNadeIndex;
selectedWeaponIndex = _selectedIndex;
}
[PunRPC]
void RpcSyncName(string name)
{
username = name;
}
[PunRPC]
void RpcSyncPartyName(string name,string id){
partyname = name;
partyId = id;
}
void IPunObservable.OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
{
if (stream.IsWriting)
{
stream.SendNext(lookAtTarget.position);
stream.SendNext(weaponRig.weight);
stream.SendNext(aimRig.weight);
stream.SendNext(weaponRig.weight);
stream.SendNext(selectedWeaponIndex);
stream.SendNext(selectedNadeIndex);
stream.SendNext(health);
stream.SendNext(shield);
stream.SendNext(kills);
stream.SendNext(deaths);
stream.SendNext(assists);
stream.SendNext(partyId);
stream.SendNext(partyname);
}
else
{
lookAtTarget.position = Vector3.Lerp(lookAtTarget.position, (Vector3)stream.ReceiveNext(),0.5f);
weaponRig.weight = (float)stream.ReceiveNext();
aimRig.weight= (float)stream.ReceiveNext();
weaponRig.weight= (float)stream.ReceiveNext();
selectedWeaponIndex =((int)stream.ReceiveNext());
selectedNadeIndex = ((int)stream.ReceiveNext());
health = (float)stream.ReceiveNext();
shield = (float)stream.ReceiveNext();
kills = (int)stream.ReceiveNext();
deaths = (int)stream.ReceiveNext();
assists = (int)stream.ReceiveNext();
partyId = (string)stream.ReceiveNext();
partyname = (string)stream.ReceiveNext();
if(prevActiveWeapon != selectedWeaponIndex || prevActiveNade != selectedNadeIndex){
UpdateActiveWeapon();
}
prevActiveWeapon = selectedWeaponIndex;
prevActiveNade = selectedNadeIndex;
}
}
float prevActiveWeapon =0;
float prevActiveNade=0;
void UpdateActiveWeapon()
{
for(int i=0; i < weapons.Count; i++)
{
weapons[i].obj.SetActive(i == selectedWeaponIndex);
weapons[i].muzzleFlash.SetActive(false);
if(selectedWeaponIndex == i)
{
UpdatePlayerFX(weapons[i]);
}
}
for(int i=0; i < nades.Count; i++){
nades[i].obj.SetActive(i==selectedNadeIndex);
}
}
public LootItemScriptableObject CurrentWeaponData;
void UpdatePlayerFX(PlayerWeaponEntry data)
{
playerFX.MuzzleFlash = data.muzzleFlash;
playerFX.FireSFXs = data.FireSFX;
// playerFX.fireSFX = data.FireSFX;
if(!photonView.IsMine){
if(data.data.overrideController == null){
anim.runtimeAnimatorController = defaultAnim;
}else{
anim.runtimeAnimatorController = data.data.overrideController;
}
}
}
public void OnNadeThrow(){
photonView.RPC("RpcOnNadeThrow", RpcTarget.All);
}
[PunRPC]
void RpcOnNadeThrow(){
if(!photonView.IsMine){
anim.SetTrigger("Throw");
}
}
PlayerController playerController;
public void OnHit(int id, HitBoxType type, Vector3 point, float dist)
{
float damage = PlayerControllerHelper.GetDamageForHitboxType(type) *GetDamageMultiplier(dist);
photonView.RPC("RpcOnHit", RpcTarget.All, id, damage,point);
}
public void OnHit(int id, float damage,Vector3 point,float dist)
{
photonView.RPC("RpcOnHit", RpcTarget.All, id, damage * GetDamageMultiplier(dist), point);
}
public float GetDamageMultiplier(float dist){
if(!GameManager.isInit){return 0;}
return DistanceDamageCurve.Evaluate(Mathf.Clamp01(dist/BulletEffectiveRange));
}
[PunRPC]
void RpcOnHit(int id, float damage, Vector3 point)
{
Debug.Log($"{username} ({photonView.ViewID}) Got hit by user ID {id})");
float newShield = shield;
float newHealth = health;
if(shield > 0){
newShield = Mathf.Clamp(shield - damage,0,100);
}else{
newHealth = health-damage;
}
if (photonView.IsMine)
{
playerController.OnHit(damage);
UIManager.instance.OnScreenDamageFx.color = new Color(1, 1, 1, UIManager.instance.OnScreenDamageFx.color.a + (damage / 100f));
GameObject enemy = PhotonView.Find(id).gameObject;
if(newHealth <= 0 && health >0)
{
//Death
bool shouldSpawnLoot = GameManager.desiredGameMode != GameModes.Deathmatch.ToString();
//Spawn loots
if(shouldSpawnLoot){
float a= 0;
foreach(KeyValuePair<LootItemScriptableObject,int> item in InventoryManager.instance.Stock){
a += Mathf.PI * 0.2f;
float x = Mathf.Sin(a);
float y = Mathf.Cos(a);
GameManager.instance.SpawnPickup(item.Key.spawnableName, transform.position + new Vector3(x,0,y), count: item.Value);
}
if(InventoryManager.instance.FirstWeapon != null){
a += Mathf.PI * 0.2f;
float x = Mathf.Sin(a);
float y = Mathf.Cos(a);
GameManager.instance.SpawnPickup(InventoryManager.instance.FirstWeapon.spawnableName,point: transform.position + new Vector3(x,0,y));
}
if(InventoryManager.instance.SecondWeapon != null){
a += Mathf.PI * 0.2f;
float x = Mathf.Sin(a);
float y = Mathf.Cos(a);
GameManager.instance.SpawnPickup(InventoryManager.instance.SecondWeapon.spawnableName,point: transform.position + new Vector3(x,0,y));
}
if(InventoryManager.instance.PrimaryWeapon != null){
a += Mathf.PI * 0.2f;
float x = Mathf.Sin(a);
float y = Mathf.Cos(a);
GameManager.instance.SpawnPickup(InventoryManager.instance.PrimaryWeapon.spawnableName,point: transform.position + new Vector3(x,0,y));
}
}
InventoryManager.ResetStocks();
CameraFollow.Pause();
enemy.GetComponent<PlayerNetwork>().GainedKill();
//Destroy(GetComponent<PlayerController>());
playerController.OnDeath();
UIManager.OnDeath();
deaths++;
if(GameManager.desiredGameMode == GameModes.Deathmatch.ToString()){
StartCoroutine(CoroutineRespawner());
}
UserDataManager.instance.AddDeath();
// PhotonNetwork.Destroy(gameObject);
}
UIManager.SetHealth(newHealth,newShield);
Vector3 toPosition = (enemy.transform.position - Camera.main.transform.position).normalized;
float angle = Vector3.SignedAngle(Camera.main.transform.forward, toPosition, Vector3.up);
UIManager.SetDamageDirection(angle);
}else{
}
if(newHealth <=0){
//Dead general
anim.SetBool("dead",true);
}
health=newHealth;
shield= newShield;
if(GameManager.localPlayer.photonView.ViewID == id && health >0)
{
Debug.Log("Show damage number");
//I HIT THIS GUY!
playerFX.ShowDamageNumber(point, damage);
}
}
IEnumerator CoroutineRespawner(){
int seconds = 0;
while(seconds < 4){
yield return new WaitForSeconds(1);
seconds++;
//TODO: Update timer text here
}
Respawn();
}
public void Respawn(){
if(photonView.IsMine){
respawn();
}else{
photonView.RPC("RpcRespawn",RpcTarget.All);
}
}
[PunRPC]
void RpcRespawn(){
respawn();
}
void respawn(){
Transform newSpawnPoint = GameManager.instance.GetRandomSpawnPoint();
transform.position = newSpawnPoint.position;
anim.SetBool("dead",false);
health = 100;
shield= 100;
UIManager.SetHealth(health,shield);
CameraFollow.Resume();
playerController.isActive=true;
UIManager.OnRespawn();
if(GameManager.desiredGameMode == GameModes.Deathmatch.ToString()){
InventoryManager.instance.GiveDefaultLoots(GameManager.instance.DeathmatchDefaultInventory);
}
UIManager.UpdateInventory(InventoryManager.instance);
}
public void GainedKill(){
if(photonView.IsMine){
gainedKill();
}else{
photonView.RPC("RpcGainKill", RpcTarget.All);
}
}
[PunRPC]
void RpcGainKill(){
if(photonView.IsMine){ gainedKill();}
}
void gainedKill(){
Debug.Log("Got a new kill");
UserDataManager.instance.AddKill();
kills++;
}
public void StartBomb(int pid, GameObject nade, LootItemScriptableObject data)
{
StartCoroutine(TickBomb(pid,nade, data));
}
IEnumerator TickBomb(int pid, GameObject nade, LootItemScriptableObject data)
{
yield return new WaitForSeconds(data.throwableTimer);
photonView.RPC("RpcBlastEffect", RpcTarget.All, photonView.ViewID, nade.transform.position, data.spawnableName);
//Handle Nade damage
PlayerNetwork[] players = FindObjectsOfType<PlayerNetwork>();
foreach(PlayerNetwork player in players){
player.photonView.RPC("RpcHandleNadeDamage", RpcTarget.All, nade.transform.position, photonView.ViewID, data.throwableDamage, data.throwableDamageRange);
}
PhotonNetwork.Destroy(nade);
}
[PunRPC]
void RpcBlastEffect(int thrower, Vector3 blastPosition, string lootSpawnableName){
LootItemScriptableObject data = GameManager.GetLootByName(lootSpawnableName);
ObjectsPool.instance.Spawn(data.throwableBlastEffect, blastPosition, Quaternion.identity, effect: true);
float distToBomb = Vector3.Distance(transform.position, blastPosition);
Debug.Log($"{username}({photonView.ViewID}) was {distToBomb} away from grenade thrown by {thrower}");
}
[PunRPC]
void RpcHandleNadeDamage(Vector3 blastPosition, int thrower, float damage, float range){
float distToBomb = Vector3.Distance(transform.position, blastPosition);
Debug.Log($"{username}({photonView.ViewID}) was {distToBomb} away from grenade thrown by {thrower}");
if(photonView.IsMine){
if(distToBomb < range){
float intensity = (range - distToBomb) * damage;
OnHit(thrower, intensity, transform.position,0);
CameraFollow.Shake(intensity * 0.01f);
}else{
Debug.Log($"Bomb was {distToBomb} far away");
}
}
}
//Testing Damage Direction
/* float a;
void Update()
{
a += Time.deltaTime;
float x = Mathf.Sin(a) * 100;
float y = Mathf.Cos(a) * 100;
Vector3 newPos = transform.position + new Vector3(x, 0, y);
Debug.DrawLine(transform.position, newPos);
Vector3 toPosition = (newPos - Camera.main.transform.position).normalized;
float angle = Vector3.SignedAngle(Camera.main.transform.forward, toPosition, Vector3.up);
Debug.Log(angle);
UIManager.SetDamageDirection(angle);
}*/
}
[Serializable]
public struct PlayerWeaponEntry
{
public LootItemScriptableObject data;
public GameObject obj;
public GameObject muzzleFlash;
public AudioClip[] FireSFX;
public Transform leftHandIk;
}
[Serializable]
public struct LootObjectEntry{
public LootItemScriptableObject data;
public GameObject obj;
}