256 lines
5.7 KiB
C#
256 lines
5.7 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using TMPro;
|
|
using UnityEngine;
|
|
using UnityEngine.AI;
|
|
using UnityEngine.VFX;
|
|
using DG.Tweening;
|
|
|
|
public class NPC : MonoBehaviour
|
|
{
|
|
|
|
public event Action OnDead;
|
|
public void Dead() => OnDead?.Invoke();
|
|
|
|
private void Awake()
|
|
{
|
|
npcAssistant = new NPCAssistant(this);
|
|
|
|
entityManager = Client.Instance.gameObject.GetComponent<NPCManager>();
|
|
|
|
//projectile origin is normally the RIGHT hand. LEFT hand for troll / NPC's with bows.
|
|
Transform[] children = GetComponentsInChildren<Transform>();
|
|
foreach (Transform transforms in children)
|
|
{
|
|
if (transforms.name == "projectileOrigin")
|
|
{
|
|
projectileOrigin = transforms.gameObject;
|
|
}
|
|
if (transforms.CompareTag("Head"))
|
|
{
|
|
headTransform = transforms;
|
|
}
|
|
if (transforms.TryGetComponent(out SkinnedMeshRenderer skinnedMesh))
|
|
{
|
|
//Debug.LogError($"SkinnedMesh Found: {skinnedMesh.name}");
|
|
this.skinnedMesh = skinnedMesh;
|
|
}
|
|
|
|
if (transforms.TryGetComponent(out Collider collider))
|
|
{
|
|
npcColliders.Add(collider);
|
|
}
|
|
}
|
|
|
|
weaponRandomizer = GetComponent<NPCWeaponRandomizer>();
|
|
sampleMesh = GetComponent<SkinnedMeshToMesh>();
|
|
healthBarComponent = GetComponent<NPCHealthBar>();
|
|
|
|
healthBarComponent.HeadTransform = headTransform;
|
|
|
|
}
|
|
|
|
private void Start()
|
|
{
|
|
if (localPathfinding())
|
|
{
|
|
l = new LocalNPC(this);
|
|
l.Start();
|
|
}
|
|
|
|
|
|
|
|
animator = GetComponent<Animator>();
|
|
|
|
targetPosition = transform.position;
|
|
previousPosition = transform.position;
|
|
|
|
lastUpdate = Time.time;
|
|
forcePositionUpdate = false;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void Update()
|
|
{
|
|
if (Time.time - lastUpdate > 7.0f)
|
|
{
|
|
entityManager.RemoveNPC(this);
|
|
return;
|
|
}
|
|
|
|
//force update position
|
|
if (forcePositionUpdate)
|
|
{
|
|
transform.position = targetPosition;
|
|
forcePositionUpdate = false;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
private void FixedUpdate()
|
|
{
|
|
if (localPathfinding())
|
|
{
|
|
l.FixedUpdate();
|
|
return;
|
|
}
|
|
|
|
if (isDead) { return; }
|
|
|
|
getNA().InterpolateEntity();
|
|
getNA().BindEntityToTerrain();
|
|
|
|
|
|
showMesh();
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void processUpdateMessage(int id, float x, float z, int deltaMultiplier, float face, float normalizedHealth)
|
|
{
|
|
lastUpdate = Time.time;
|
|
|
|
if (localPathfinding())
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (deltaMultiplier == -1)
|
|
this.forcePositionUpdate = true;
|
|
else
|
|
this.deltaMultiplier = deltaMultiplier;
|
|
|
|
targetPosition = new Vector3(x + (getNA().getSize(this.type) / 2.0f), transform.position.y, z + (getNA().getSize(this.type) / 2.0f));
|
|
transform.rotation = Quaternion.Euler(0, face, 0);
|
|
if (healthBarComponent.healthBar != null)
|
|
healthBarComponent.healthBar.SetHealth(normalizedHealth);
|
|
|
|
if (normalizedHealth <= 0.0f)
|
|
{
|
|
Destroy(GetComponent<AudioSource>());
|
|
isDead = true;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
public void PlayAnimation(string anim)
|
|
{
|
|
if (anim.ToLower().Equals("death"))
|
|
{
|
|
Destroy(GetComponent<AudioSource>());
|
|
isDead = true;
|
|
getNA().ToggleColliders(false);
|
|
StartCoroutine(getNA().DeathFadePosition());
|
|
StartCoroutine(getNA().WaitToSpawnDeathSoul());
|
|
getNA().FadeHealthCanvas();
|
|
OnDead?.Invoke();
|
|
}
|
|
|
|
//print("trying to play animation: " + anim);
|
|
|
|
animator?.Play(anim);
|
|
}
|
|
|
|
|
|
public void showMesh()
|
|
{
|
|
if (Time.time - lastDistanceCheck < 3.0f) { return; }
|
|
//if distance to player > 80
|
|
if (Vector3.Distance(transform.position, Client.Instance.mainPlayer.transform.position) > 80)
|
|
{
|
|
skinnedMesh.enabled = false;
|
|
}
|
|
else
|
|
{
|
|
skinnedMesh.enabled = true;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
public int GetID()
|
|
{
|
|
return id;
|
|
}
|
|
|
|
public void SetID(int id)
|
|
{
|
|
this.id = id;
|
|
}
|
|
|
|
public void SetHitPoints(int hp)
|
|
{
|
|
hitPoints = hp;
|
|
}
|
|
public int GetHitPoints()
|
|
{
|
|
return hitPoints;
|
|
}
|
|
|
|
public NPCAssistant getNA()
|
|
{
|
|
return npcAssistant;
|
|
}
|
|
|
|
public bool localPathfinding()
|
|
{
|
|
return Misc.checkBit(flags, 0);
|
|
}
|
|
|
|
public Projectile Instantiate2(Projectile g)
|
|
{
|
|
return Instantiate(g);
|
|
}
|
|
|
|
private int id;//uuid
|
|
public int flags;
|
|
|
|
public Vector3 targetPosition;
|
|
public float lastUpdate;
|
|
public bool forcePositionUpdate;
|
|
public int hitPoints;
|
|
private NPCManager entityManager;
|
|
public GameObject projectileOrigin;
|
|
[System.NonSerialized] public Animator animator;
|
|
[System.NonSerialized] public int type;
|
|
//when dead, stop interpolation
|
|
[System.NonSerialized] public bool isDead = false;
|
|
|
|
public float damping = 10.0f;
|
|
public Vector3 previousPosition;
|
|
|
|
public Transform headTransform;
|
|
|
|
public SkinnedMeshRenderer skinnedMesh = null;
|
|
public SkinnedMeshToMesh sampleMesh = null;
|
|
public NPCWeaponRandomizer weaponRandomizer = null;
|
|
public NPCHealthBar healthBarComponent;
|
|
public int deltaMultiplier;
|
|
|
|
private float lastDistanceCheck = 0.0f;
|
|
|
|
public List<Collider> npcColliders = new List<Collider>();
|
|
|
|
|
|
public NPCAssistant npcAssistant;
|
|
//only used for npcs where pathfinding and AI is done locally
|
|
public LocalNPC l;
|
|
}
|