-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPlayerAimedShot.cs
161 lines (147 loc) · 6.53 KB
/
PlayerAimedShot.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
154
155
156
157
158
159
160
161
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/*
* Changelog
* TODO display to indicate when character is in "locked" state and can't move/shoot
*/
public class PlayerAimedShot : MonoBehaviour {
[Tooltip("Animation created when the shot fires")]
public GameObject onShot;
[Tooltip("Gameobject rendered when the aimedshot is active")]
public GameObject aimIndicator;
[Tooltip("Line of sight origin")]
public Transform lineOfSightOrigin;
[Tooltip("True if the player is attempting an aimed shot right now")]
public bool aimedShotActive = false;
[Tooltip("If used, shows the range of the aimed shot when engaged")]
public GameObject debugSphere;
[Tooltip("Closest target to the screen point being aimed")]
private GameObject target;
private PlayerCharacterController playerCharacterController;
private int layerMask;
private int aimTick = 0;
private int disengageTick = 0;
private enum ShotState {
Aiming,
Firing,
Disengaging,
Inactive
}
private ShotState state = ShotState.Inactive;
private PlayerSettings playerSettings;
void Start() {
playerSettings = PlayerSettings.getInstance();
playerCharacterController = GetComponent<PlayerCharacterController>();
layerMask = LayerMask.GetMask("Enemy");
aimTick = playerSettings.TicksToLockOn;
disengageTick = playerSettings.TicksToDisengage;
aimIndicator.SetActive(false);
StartCoroutine("handleAimedShot");
}
void Update() {
// Debug.Log("look indicator: " + playerCharacterController.lookTargetPoint.transform.position);
}
public void initiateShot() {
if(state == ShotState.Inactive) {
state = ShotState.Aiming;
aimedShotActive = true;
}
//Debug.Log("Shot initiate!");
}
public void disengageShot() {
if(state != ShotState.Inactive) {
state = ShotState.Disengaging;
}
//Debug.Log("Shot disengage!");
}
public GameObject findNearestViableTarget() {
Vector3 targetPoint = playerCharacterController.lookTargetPoint.transform.position;
Collider[] hits = Physics.OverlapSphere(
targetPoint,
playerSettings.AimedShotDetectionRange,
layerMask);
if (debugSphere != null) {
debugSphere.transform.position = targetPoint;
// Debug.Log("look indicator: " + playerCharacterController.lookTargetPoint.transform.position);
debugSphere.transform.localScale = new Vector3(playerSettings.AimedShotDetectionRange*2, playerSettings.AimedShotDetectionRange*2, playerSettings.AimedShotDetectionRange*2);
}
if (hits.Length < 1) {
return null;
}
float closestDistance = Mathf.Infinity;
GameObject closest = null;
foreach (Collider hit in hits) {
HealthManager health = hit.transform.root.gameObject.GetComponent<HealthManager>();
if(health==null || health.dead) {
continue;
}
//TODO check line of sight
float distance = Vector3.Distance(targetPoint, hit.transform.position);
if (distance < closestDistance) {
closestDistance = distance;
closest = hit.transform.root.gameObject;
}
}
return closest;
}
IEnumerator handleAimedShot() {
while (true) {
yield return new WaitForSeconds(playerSettings.aimedShotTickRate);
// Debug.Log("State: " + state);
if (aimedShotActive) {
switch (state) {
case ShotState.Aiming:
//TODO play disengage animation, inform animator to begin aiming
if (target == null) {
GameObject newTarget = findNearestViableTarget();
target = newTarget;
aimTick = playerSettings.TicksToLockOn;
} else {
//TODO pick a new target if the lock target dies
aimedShotActive = true;
aimIndicator.SetActive(true);
aimIndicator.transform.position = new Vector3(target.transform.position.x, -0.5f, target.transform.position.z);
if (aimTick > 0) {
//TODO check line of sight is intact
aimTick--;
} else {
aimTick = playerSettings.TicksToLockOn;
state = ShotState.Firing;
}
}
break;
case ShotState.Firing:
GameObject shot = Instantiate(onShot, transform.position, Quaternion.identity);
LineRenderer line = shot.GetComponent<LineRenderer>();
line.SetPositions(new Vector3[] {transform.position, target.transform.position});
HealthManager health = target.GetComponent<HealthManager>();
Vector3 direction = (transform.position - target.transform.position).normalized;
if (health != null) {
health.TakeDamage(target.transform.position, direction, playerSettings.AimedShotDamage);
}
state = ShotState.Disengaging;
break;
case ShotState.Disengaging:
//TODO play disengage animation, inform animator to stand
aimIndicator.SetActive(false);
target = null;
if (disengageTick > 0) {
disengageTick--;
} else {
disengageTick = playerSettings.TicksToDisengage;
state = ShotState.Inactive;
}
break;
case ShotState.Inactive:
aimIndicator.SetActive(false);
aimedShotActive = false;
//do nothing
break;
default:
break;
}
}
}
}
}