-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathNpcBase.cs
154 lines (135 loc) · 5.25 KB
/
NpcBase.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
using System;
using System.Collections;
using System.Collections.Generic;
using Unity.IO.LowLevel.Unsafe;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.UI;
public class NpcBase : MonoBehaviour
{
[HideInInspector] public PlayerBase HostileTarget;
[HideInInspector] public NpcBaseState CurrentState;
[HideInInspector] public Vector3 TargetLastKnownLocation;
[HideInInspector] public bool TurnTowardsTarget;
[SerializeField] public List<GameObject> NpcSkins;
public GameObject SkinSelected { get; private set; }
public NetworkScene NetworkScene { get; private set; }
public NpcStateManager StateManager { get; private set; }
public NavMeshPath NavMeshPath { get; private set; }
public NpcHealth NpcHealth { get; private set; }
public Rigidbody Rb { get; private set; }
public Animator Animator { get; private set; }
public NavMeshAgent Agent { get; private set; }
public int NpcSceneId;
public Vector3 HeadPos { get; private set; } = new Vector3(0, 3, 0);
public float WalkSpeed { get; private set; } = 3f;
public float RunSpeed { get; private set; } = 8f;
public float TurningRunSpeed { get; private set; } = 360f;
public float TurningWalkSpeed { get; private set; } = 200f;
public float AttackDmg { get; private set; } = 10f;
public float CutoffSight { get; private set; } = 45f;
public float Radius { get; private set; } = 20f;
public GameObject WeaponObj;
public GameObject QuestionMarkAlert;
public Action<PlayerBase> Alarm;
void Awake()
{
Rb = GetComponent<Rigidbody>();
Agent = GetComponent<NavMeshAgent>();
NpcHealth = GetComponent<NpcHealth>();
Animator = GetComponentInChildren<Animator>();
NetworkScene = FindObjectOfType<NetworkScene>();
StateManager = FindObjectOfType<NpcStateManager>();
NavMeshPath = new NavMeshPath();
}
void Start()
{
Alarm += OnAlarm;
NpcHealth.Death += OnDeath;
NpcHealth.HitWhileIdle += AlarmOthers;
StateManager.SwitchState(StateManager.IdleState, this);
SkinSelected = NpcSkins[UnityEngine.Random.Range(0, NpcSkins.Count)];
SkinSelected.SetActive(true);
}
private void FixedUpdate()
{
if (TurnTowardsTarget) RotateTowards(HostileTarget.transform);
}
public void OnAlarm(PlayerBase player)
{
if (CurrentState != StateManager.DeadState)
{
HostileTarget = player;
StateManager.SwitchState(StateManager.ChasingState, this);
}
}
public void AlarmOthers(PlayerBase player)
{
foreach (NpcBase npc in FindObjectsOfType<NpcBase>())
{
if (npc == this) continue;
float distance = (npc.transform.position - this.transform.position).magnitude;
if (distance < Radius && npc.Alarm?.GetInvocationList() != null) npc.Alarm.Invoke(player);
}
}
public void AlarmOthersInSight(PlayerBase player)
{
foreach (NpcBase npc in FindObjectsOfType<NpcBase>())
{
if (npc == this) continue;
float distance = (npc.transform.position - this.transform.position).magnitude;
if (distance < Radius)
{
bool isInSight = HelperMethods.CheckInRangeAndSight(this.transform.position, npc.transform, Radius, CutoffSight);
if (isInSight && !npc.NpcHealth.IsDead) npc.Alarm.Invoke(player);
}
}
}
public IEnumerator AlarmRoutine()
{
var players = GameObject.FindGameObjectsWithTag("Player");
float delay = 0.2f;
WaitForSeconds wait = new WaitForSeconds(delay);
while (!NpcHealth.IsDead)
{
foreach(var player in players)
{
if (HelperMethods.CheckInRangeAndSight(player.transform.position, transform, Radius, CutoffSight))
Alarm.Invoke(player.GetComponent<PlayerBase>());
}
yield return wait;
}
}
public IEnumerator AlertRoutine()
{
var players = GameObject.FindGameObjectsWithTag("Player");
float delay = 0.2f;
WaitForSeconds wait = new WaitForSeconds(delay);
while (!NpcHealth.IsDead)
{
yield return wait;
foreach(var player in players)
{
if (HelperMethods.CheckInRange(player.transform.position, transform.position, Radius))
{
PlayerMovement playerMovement = player.GetComponent<PlayerMovement>();
if (!playerMovement.crouching && playerMovement.move != Vector2.zero) StateManager.SwitchState(StateManager.AlertState, this);
}
}
}
}
private void OnDeath()
{
AlarmOthersInSight(HostileTarget);
StateManager.SwitchState(StateManager.DeadState, this);
Alarm -= OnAlarm;
NpcHealth.Death -= OnDeath;
NpcHealth.HitWhileIdle -= AlarmOthers;
}
public void RotateTowards(Transform target)
{
Vector3 direction = (target.position - transform.position).normalized;
Quaternion lookRotation = Quaternion.LookRotation(direction);
transform.rotation = Quaternion.Slerp(transform.rotation, lookRotation, Time.deltaTime * 10);
}
}