TG9six 03a642d635 first push
first push
2025-09-06 17:17:39 +04:00

572 lines
19 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.Networking;
using EZCameraShake;
using UnityEngine.InputSystem;
using UnityEngine.Rendering;
using Weapons.Projectiles;
using Random = UnityEngine.Random;
/**
* A script attached to every player to handle visual effects
*/
public class PlayerEntity : MonoBehaviour
{
[System.NonSerialized] public PlayableCharacterSkin CurrentlyEquippedSkin = null;
internal Volume volumeMain;
internal Volume volumeMashroom;
internal Material skyMain;
internal Material skyMashroom;
public Transform FirstPersonCameraPivot;
[SerializeField] private List<PlayableCharacterSkin> skinList = new List<PlayableCharacterSkin>();
[SerializeField] private GameObject playerRendererBackgroundObjects;
private static RuntimeAnimatorController meleeController;
private static RuntimeAnimatorController gunController;
private static RuntimeAnimatorController pistolController;
private static RuntimeAnimatorController bowController;
private static RuntimeAnimatorController gloveController;
private int playerFlags;
//player looking
private Vector3 currVelocity = Vector3.zero;
private float lookAngleOffset = 20.0f;
private float playerLookAngle;
//animator caching
private static readonly int animator_VerticalLook = Animator.StringToHash("VerticalLook");
private static readonly int animator_xAxis = Animator.StringToHash("xAxis");
private static readonly int animator_zAxis = Animator.StringToHash("zAxis");
private static readonly int animator_Magnitude = Animator.StringToHash("VelocityMagnitude");
//float caching
private const float constSmooth = 10.0f;
//player rotation
private Quaternion playerYRotation;
//player animation floats
private float playerAnimX;
private float playerAnimZ;
private float playerMagnitude;
public string[] playerTextureURLS = new string[1];
private Texture2D playerSkinTexture;
private Transform _Skins;
[HideInInspector] public PlayerEntity SpectatedPlayer;
[System.NonSerialized] public Camera spectatedPlayersThirdPersonCamera;
[System.NonSerialized] public GameObject thirdPersonCameraObject;
[SerializeField] internal List<Transform> listOfManualInitWeaponslot = new List<Transform>();
private void Awake()
{
if (meleeController == null)
meleeController = OnDemandLoader.Load<RuntimeAnimatorController>("Models/Player/Player_MeleeStance_Controller");
if (gunController == null)
gunController = OnDemandLoader.Load<RuntimeAnimatorController>("Models/Player/Player_GunStance_Controller");
if (bowController == null)
bowController = OnDemandLoader.Load<RuntimeAnimatorController>("Models/Player/Player_bowStance_Controller");
if (pistolController == null)
pistolController = OnDemandLoader.Load<RuntimeAnimatorController>("Models/Player/Player_pistolStance_Controller");
if (gloveController == null)
gloveController = OnDemandLoader.Load<RuntimeAnimatorController>("Models/Player/Glove_Controller");
Transform pCanvas = transform.Find("Canvas");
if (pCanvas != null)
{
ChatBubble = pCanvas.Find("CanvasContainer/ChatBubbleContainer/ChatBubble").GetComponent<ChatBubble>();
Transform nameGOTMPro = pCanvas.Find("CanvasContainer/Name");
if (nameGOTMPro != null)
{
PlayerEntityName = nameGOTMPro.GetComponent<TextMeshProUGUI>();
}
}
_Skins = transform.Find("Skins");
}
public void Start()
{
animator = gameObject.GetComponent<Animator>();
targetPosition = transform.position;
lastUpdate = Time.time;
if (GetComponent<Player>() == null)
{
Destroy(GetComponent<FirstPersonController>());
Destroy(GetComponent<CharacterController>());
PlayerInput input = GetComponent<PlayerInput>();
input.DeactivateInput();
if (input != null)
{
Destroy(input);
}
Destroy(GetComponent<InputHandler>());
Destroy(GetComponent<GamePadInputEvents>());
Destroy(transform.Find("FirstPersonCamera_Holder").gameObject);
Destroy(transform.Find("PlayerUICamera").gameObject);
Destroy(GetComponent<ShaderInteractor>());
Destroy(GetComponent<UICameraPositioner>());
Destroy(playerRendererBackgroundObjects);
}
InitWeaponSystems();
thirdPersonCameraObject = transform.Find("ThirdPerson_Camera").gameObject;
thirdPersonCameraObject.SetActive(false);
}
internal void InitWeaponSystems()
{
GameObject weaponSlot = transform.Find("Root/Hips/Spine_01/Spine_02/Spine_03/Clavicle_R/Shoulder_R/Elbow_R/Hand_R/Weapon").gameObject;
foreach (Transform weapon in weaponSlot.transform)
{
thirdPersonWeaponList.Add(weapon.gameObject);
}
foreach (var weapon in listOfManualInitWeaponslot)
{
thirdPersonWeaponList.Add(weapon.gameObject);
}
foreach (GameObject weaponObj in thirdPersonWeaponList)
{
thirdPersonWeaponDictionary[int.Parse(weaponObj.name)] = weaponObj;
}
}
private void Update()
{
//don't do processing for main player here.. do it in player.cs
if (id == -1) { return; }
//remove Entity if last update is over 5 seconds long.
if (Time.time - lastUpdate > 5.0f)
{
PlayerManager.Instance.RemovePlayer(this);
return;
}
InterpolateEntity();
}
private void FixedUpdate()
{
if (id == -1) { return; }
InterpolateAnimation();
terrainHeightFix();
}
public void spectatePlayer(int playerId)
{
PlayerEntity player = PlayerManager.Instance.GetPlayer(playerId).GetComponent<PlayerEntity>();
spectatedPlayersThirdPersonCamera = player.thirdPersonCameraObject.GetComponent<Camera>();
spectatedPlayersThirdPersonCamera.gameObject.SetActive(true);
}
private void InterpolateEntity()
{
InterpolatePosition();
InterpolateRotation();
}
public void ResetJumpTrigger() //used in animation event
{
animator.ResetTrigger("Jump");
}
private void InterpolatePosition()
{
float distance = Vector3.Distance(transform.position, targetPosition);
//Debug.Log($"Player: {gameObject.name} is {distance} units away from where they should be!");
if (distance >= 10f) { transform.position = targetPosition; }
else { transform.position = Vector3.SmoothDamp(transform.position, targetPosition, ref currVelocity, 0.1f); }
}
private void InterpolateRotation()
{
Vector3 euler = transform.eulerAngles;
euler.y = Mathf.LerpAngle(euler.y, playerYRotation.eulerAngles.y, constSmooth * Time.deltaTime);
transform.eulerAngles = euler;
}
private void InterpolateAnimation()
{
animator.SetFloat(animator_VerticalLook, Mathf.Lerp(animator.GetFloat(animator_VerticalLook), playerLookAngle + lookAngleOffset, constSmooth * Time.deltaTime));
animator.SetFloat(animator_xAxis, Mathf.Lerp(animator.GetFloat(animator_xAxis), playerAnimX, constSmooth * Time.deltaTime));
animator.SetFloat(animator_zAxis, Mathf.Lerp(animator.GetFloat(animator_zAxis), playerAnimZ, constSmooth * Time.deltaTime));
animator.SetFloat(animator_Magnitude, Mathf.Lerp(animator.GetFloat(animator_Magnitude), playerMagnitude, constSmooth * Time.deltaTime));
if ((playerFlags & 0x02) == 0x02) { animator.SetTrigger("Jump"); }
animator.SetBool("Aiming", (playerFlags & 0x01) == 0x01);
}
public void ProcessUpdateMessage(int id, float x, float y, float z, float rotationY, float lookAngle, string name, float animX, float animZ, float magnitude, int flags, string forceAnim)
{
if (PlayerEntityName != null)
{
Debug.Log(PlayerEntityName);
PlayerEntityName.text = name;
playerName = name;
}
lastPacketPosition = transform.position;
targetPosition = new Vector3(x, y, z);
velocity = targetPosition - lastPacketPosition;
//playerYRotation is cached rotation and calculated outside of the 10 updates a second step.
playerYRotation = Quaternion.Euler(transform.rotation.eulerAngles.x, rotationY, transform.rotation.eulerAngles.z);
playerLookAngle = lookAngle;
//animation interpolation caching
playerAnimX = animX;
playerAnimZ = animZ;
playerMagnitude = magnitude;
playerFlags = flags;
if (forceAnim.Length > 0)
{
animator.Play(forceAnim);
}
lastUpdate = Time.time;
}
public void setWeapon(int itemId)
{
Weapon.WEAPON_TYPE weaponType = ItemDef.GetInstance().getType(itemId);
lookAngleOffset = 20.0f;
switch (weaponType)
{
case Weapon.WEAPON_TYPE.NONE:
break;
case Weapon.WEAPON_TYPE.GUN:
animator.runtimeAnimatorController = gunController;
break;
case Weapon.WEAPON_TYPE.BOW:
animator.runtimeAnimatorController = bowController;
break;
case Weapon.WEAPON_TYPE.SWORD:
lookAngleOffset = 20f; //animations are angled down more. so decrease the offset.
animator.runtimeAnimatorController = meleeController;
break;
case Weapon.WEAPON_TYPE.PISTOL:
lookAngleOffset = 5f; //animations are angled down more. so decrease the offset.
animator.runtimeAnimatorController = pistolController;
break;
case Weapon.WEAPON_TYPE.MINER:
lookAngleOffset = 5f;
animator.runtimeAnimatorController = meleeController;
break;
case Weapon.WEAPON_TYPE.GLOVE:
animator.runtimeAnimatorController = gloveController;
lookAngleOffset = 5f;
break;
}
this.weaponId = itemId;
this.projectileOrigin = null;
GameObject weaponSlot = transform.Find("Root/Hips/Spine_01/Spine_02/Spine_03/Clavicle_R/Shoulder_R/Elbow_R/Hand_R/Weapon").gameObject;
foreach (Transform child in weaponSlot.transform)
{
child.gameObject.SetActive(false);
}
foreach (var manualSlots in listOfManualInitWeaponslot)
{
manualSlots.gameObject.SetActive(false);
}
Debug.Log($"Activate {itemId}");
if (itemId != -1)
{
if (thirdPersonWeaponDictionary.TryGetValue(itemId, out var valWeapon))
{
valWeapon.SetActive(true);
currentWeapon = valWeapon;
SetLayerRecursively(currentWeapon, "Default");
}
}
}
private void SetLayerRecursively(GameObject obj, string newLayer)
{
if (obj == null)
{
return;
}
obj.layer = LayerMask.NameToLayer(newLayer);
foreach (Transform child in obj.transform)
{
if (child == null)
{
continue;
}
SetLayerRecursively(child.gameObject, newLayer);
}
}
public IEnumerator processWeaponFire(Vector3 direction, string projectile)
{
if (ItemDef.GetInstance().isThrowable(weaponId))
{
animator.Play("3D_ThrowNade");
yield return new WaitForSeconds(0.7f);
fireProjectile(direction, projectile);
}
else
{
fireProjectile(direction, projectile);
animator.Play("3D_Shoot");
}
}
public Vector3 GetProjectileOrigin()
{
if (projectileOrigin)
return projectileOrigin.transform.position;
else
{
return Vector3.zero;;
}
}
public void SetSkin(string skin)
{
//Debug.Log("setting skin " + skin);
PlayableCharacterSkin currentlyEquiptSkin = _Skins.Find(skin).GetComponent<PlayableCharacterSkin>();
CurrentlyEquippedSkin = currentlyEquiptSkin;
for (int i = 0; i < skinList.Count; i++)
{
//Debug.Log($"Searching for {skins[i]}- result: {transform.Find(skins[i])}");
try
{
skinList[i].DeactivateSkin();
}
catch (Exception e)
{
Debug.Log(e.ToString());
}
}
currentlyEquiptSkin.ActivateSkin();
if (GetComponent<Player>() != null && UIManager.Instance.IsGameLobbyCanvasesActive())
{
//client side stats. Rest are server side.
SetSpecialStat(skin);
}
}
private void SetSpecialStat(string skin)
{
PreGameManager.Instance.SetSpecialStat(skin);
}
public IEnumerator GetAndSetPlayerTexture(GameObject mainPlayer)
{
int randTexture = Random.Range(0, 5);
UnityWebRequest www = UnityWebRequestTexture.GetTexture(playerTextureURLS[0]);
yield return www.SendWebRequest();
playerSkinTexture = DownloadHandlerTexture.GetContent(www);
//Debug.Log("Decal successfully Loaded!" + texture);
foreach (SkinnedMeshRenderer playerModel in mainPlayer.GetComponentsInChildren<SkinnedMeshRenderer>())
{
if (!playerModel.enabled || !playerModel.gameObject.name.Contains("Character_")) { continue; }
//Debug.Log($"{playerModel.gameObject.name} did not contain \"Character_\" and enable was {playerModel.enabled}");
playerModel.material.SetTexture("_BaseMap", playerSkinTexture);
}
}
public bool IsFuturisticWeapon()
{
if (weaponId == 0 || weaponId == 4 || weaponId == 5 || weaponId == 6 || weaponId == 12)
{
return true;
}
return false;
}
public void fireProjectile(Vector3 direction, string projectile)
{
if (projectile == null)
return;
if (projectileOrigin == null)
return;
var qTargetRotateProjectile = Quaternion.identity;
var isFlameProjectile = false;
if (projectile == "Level_1_FlameAttack"||
projectile == "Level_2_FlameAttack"||
projectile == "Level_3_FlameAttack"||
projectile == "Level_4_FlameAttack"||
projectile == "Level_5_FlameAttack"||
projectile == "Level_6_FlameAttack"||
projectile == "Level_7_FlameAttack"
)
{
isFlameProjectile = true;
qTargetRotateProjectile = projectileOrigin.transform.rotation;
}
GameObject pooledProjectile = null;
if (!isFlameProjectile)
pooledProjectile = NetworkPooler.Instance.PooledInstantiate(projectile, projectileOrigin.transform.position,qTargetRotateProjectile);
if (projectile != "Grenade" && !isFlameProjectile)
{
pooledProjectile.GetComponent<ProjectileBase>().ApplyForce(direction);
}
else if (isFlameProjectile)
{
var current = thirdPersonWeaponDictionary[weaponId];
projectileOrigin = current.transform.Find("projectileOrigin")?.gameObject;
projectileOrigin.transform.GetComponent<FlameProjectile>().InstantiateOrigin(this, projectileOrigin.transform, projectile);
}
else
{
pooledProjectile.GetComponent<Projectile>().ApplyForce(direction, 10);
}
if (id != -1)
{
//only create muzzleflashes for none-main player. Main player muzzleflash are handled seperately.
if (IsFuturisticWeapon())
{
NetworkPooler.Instance.PooledPlayEffect("FuturisticMuzzleFlash", projectileOrigin.transform.position, projectileOrigin.transform.rotation, 3.0f);
}
else
{
//Debug.Log("Not a futuristic weapon,");
//exclude rocket launcher and grenade from the muzzleflash. We can make it have it if neeed. Remove this if check.
if (weaponId != 14 && weaponId != 23)
{
//Debug.Log("Playing MuzzleFlash!");
NetworkPooler.Instance.PooledPlayEffect("NormalMuzzleFlash", projectileOrigin.transform.position, projectileOrigin.transform.rotation, 3.0f);
}
}
}
//if bullet didnt hit anything. Disable it after 10 seconds.
NetworkPooler.Instance.PooledDestroy(projectile, pooledProjectile, 10.0f);
}
private void terrainHeightFix()
{
Terrain terrain = Misc.GetClosestCurrentTerrain(transform.position);
float height = terrain.SampleHeight(transform.position);
if (transform.position.y < height)
{
transform.position = new Vector3(transform.position.x, height, transform.position.z);
}
}
public int GetID()
{
return id;
}
public void SetID(int id)
{
this.id = id;
}
public string GetVoiceID()
{
return voiceID;
}
public void SetVoiceID(string voiceID)
{
this.voiceID = voiceID;
}
public int GetSkinID()
{
return skinList.IndexOf(CurrentlyEquippedSkin);
}
public void SetLastPositionAfterTeleportation(Vector3 vector3)
{
lastPacketPosition = vector3;
targetPosition = vector3;
}
private void OnTriggerEnter(Collider other)
{
if (other.CompareTag("PPdetector"))
{
if (id == -1)
{
OnDetectPP?.Invoke();
volumeMain.gameObject.SetActive(false);
volumeMashroom.gameObject.SetActive(true);
RenderSettings.skybox = skyMashroom;
}
}
}
private void OnTriggerExit(Collider other)
{
if (other.CompareTag("PPdetector"))
{
if (id == -1)
{
OnDetectClosePP?.Invoke();
volumeMain.gameObject.SetActive(true);
volumeMashroom.gameObject.SetActive(false);
RenderSettings.skybox = skyMain;
}
}
}
public string GetName() => playerName;
public static event Action OnDetectPP;
public static event Action OnDetectClosePP;
[HideInInspector] public GameObject projectileOrigin;
[HideInInspector] public int weaponId;
public ChatBubble ChatBubble { get; internal set; }
private int id = -1;
private string voiceID = "null";
[HideInInspector] public Animator animator;
private float lastUpdate;
private Vector3 lastPacketPosition;
private Vector3 targetPosition;
private Vector3 velocity;
[System.NonSerialized] public TextMeshProUGUI PlayerEntityName;
private string playerName;
[HideInInspector] public GameObject currentWeapon;
private List<GameObject> thirdPersonWeaponList = new List<GameObject>();
private readonly Dictionary<int, GameObject> thirdPersonWeaponDictionary = new Dictionary<int, GameObject>();
}