change: enemy combat/detection state now handled by the spawner
This commit is contained in:
@@ -8,8 +8,13 @@ namespace Reset.Units{
|
||||
|
||||
[Button]
|
||||
public void SetNewTarget(GameObject newTarget){
|
||||
Unit.Graph.SendEvent("New Target Set");
|
||||
Unit.Graph.SendEvent("New Target Detected");
|
||||
target = newTarget;
|
||||
}
|
||||
|
||||
public void DropTarget(){
|
||||
target = null;
|
||||
Unit.Graph.SendEvent("Drop Target");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,22 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Drawing;
|
||||
using Pathfinding;
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
using Random = UnityEngine.Random;
|
||||
|
||||
namespace Reset.Units{
|
||||
public class EnemySpawn : MonoBehaviour{
|
||||
enum SpawnerState{
|
||||
Idle = 0,
|
||||
TargetAcquired,
|
||||
TargetDropped,
|
||||
InCombatUnlocked,
|
||||
InCombatLocked,
|
||||
Cooldown,
|
||||
}
|
||||
|
||||
public float radius = 30f;
|
||||
|
||||
public int minimumEnemies = 1;
|
||||
@@ -19,6 +30,9 @@ namespace Reset.Units{
|
||||
public List<GameObject> enemies;
|
||||
|
||||
public GridGraph relatedGraph;
|
||||
|
||||
private SpawnerState spawnerState;
|
||||
private float timeInState;
|
||||
|
||||
void Start(){
|
||||
CreateAstarGraph();
|
||||
@@ -56,43 +70,154 @@ namespace Reset.Units{
|
||||
}
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update(){
|
||||
Draw.WireCylinder(transform.position, transform.position + Vector3.up * 7f, radius);
|
||||
ProcessStateUpdate();
|
||||
DrawSpawnStateGizmos();
|
||||
}
|
||||
|
||||
// Set the new state of the spawner and also reset the timer for state management
|
||||
void ChangeState(SpawnerState newState){
|
||||
spawnerState = newState;
|
||||
ProcessStateStart();
|
||||
timeInState = 0f;
|
||||
}
|
||||
|
||||
if (PlayerIsInRange()) {
|
||||
SetPlayerAsTarget();
|
||||
|
||||
// Does initial actions on state switch
|
||||
void ProcessStateStart(){
|
||||
switch (spawnerState) {
|
||||
case SpawnerState.TargetDropped:
|
||||
foreach (GameObject thisEnemy in enemies) {
|
||||
thisEnemy.GetComponent<EnemyCombat>().DropTarget();
|
||||
}
|
||||
break;
|
||||
|
||||
case SpawnerState.InCombatUnlocked:
|
||||
foreach (GameObject thisEnemy in enemies) {
|
||||
thisEnemy.GetComponent<Enemy>().Graph.SendEvent("Enter Combat");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
GameObject PlayerIsInRange(){
|
||||
// TODO: Make compatible with all players
|
||||
Vector3 playerPos = PlayerManager.Player.transform.position;
|
||||
// Actively processes the state of the spawner and its assocaited enemies
|
||||
void ProcessStateUpdate(){
|
||||
switch (spawnerState) {
|
||||
// Check if player is in range of this spawner. If so, set them as the new target
|
||||
case SpawnerState.Idle:
|
||||
if (PlayerIsInRange(radius, radius / 2f)) {
|
||||
foreach (GameObject thisEnemy in enemies) {
|
||||
thisEnemy.GetComponent<EnemyCombat>().SetNewTarget(PlayerManager.Player);
|
||||
}
|
||||
ChangeState(SpawnerState.TargetAcquired);
|
||||
}
|
||||
break;
|
||||
|
||||
// After grabbing a player in range, make sure they stay in range. If they aren't in range after 5 seconds, disengage. If they are or get too close, engage.
|
||||
case SpawnerState.TargetAcquired:
|
||||
if (PlayerIsInRange(radius, 8f) && timeInState > 1f) {
|
||||
ChangeState(SpawnerState.InCombatUnlocked);
|
||||
return;
|
||||
}
|
||||
|
||||
if (timeInState > 5f) {
|
||||
if (PlayerIsInRange(radius + 2f, radius * .6f)) {
|
||||
ChangeState(SpawnerState.InCombatUnlocked);
|
||||
return;
|
||||
}
|
||||
|
||||
// Skip checking and return null/false if the player is nowhere near the spawn
|
||||
if (Vector3.Distance(playerPos, transform.position) < radius * 1.5f) {
|
||||
ChangeState(SpawnerState.TargetDropped);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
// Wait a few seconds after dropping the target before doing anything else
|
||||
case SpawnerState.TargetDropped:
|
||||
if (timeInState > 3f) {
|
||||
ChangeState(SpawnerState.Idle);
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
// Set all units to combat. Drop combat if the target gets too far
|
||||
case SpawnerState.InCombatUnlocked:
|
||||
if (!PlayerIsInRange(radius * 1.5f, radius * 1.5f) && timeInState > 5f) {
|
||||
ChangeState(SpawnerState.TargetDropped);
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
// Lock the player to the spawn. Currently unused.
|
||||
case SpawnerState.InCombatLocked:
|
||||
break;
|
||||
|
||||
|
||||
// Long cooldown for after all units have been killed. Currently unused.
|
||||
case SpawnerState.Cooldown:
|
||||
break;
|
||||
}
|
||||
|
||||
// Increment state timer
|
||||
timeInState += 1f * Time.deltaTime;
|
||||
}
|
||||
|
||||
|
||||
|
||||
GameObject PlayerIsInRange(float spawnerRange, float enemyRange){
|
||||
// TODO: Make compatible with all players
|
||||
if (!PlayerManager.Player) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// If they are in range, check if the player is close enough to either an enemy or the spawn center
|
||||
if (Vector3.Distance(playerPos, transform.position) < radius * .33f) {
|
||||
Vector3 playerPos = PlayerManager.Player.transform.position;
|
||||
|
||||
// Skip checking and return null/false if the player is nowhere near the input range
|
||||
if (Vector3.Distance(playerPos, transform.position) > spawnerRange * 2f) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// If they are in range, check if the player is close enough to either an enemy or the input range
|
||||
if (Vector3.Distance(playerPos, transform.position) < spawnerRange) {
|
||||
return PlayerManager.Player;
|
||||
}
|
||||
|
||||
foreach (GameObject thisEnemy in enemies) {
|
||||
if (Vector3.Distance(playerPos, thisEnemy.transform.position) < radius / 2f) {
|
||||
if (Vector3.Distance(playerPos, thisEnemy.transform.position) < enemyRange) {
|
||||
return PlayerManager.Player;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void DrawSpawnStateGizmos(){
|
||||
Color cylinderColor = Color.blue;
|
||||
|
||||
void SetPlayerAsTarget(){
|
||||
foreach (GameObject thisEnemy in enemies) {
|
||||
thisEnemy.GetComponent<EnemyCombat>().SetNewTarget(PlayerManager.Player);
|
||||
switch (spawnerState) {
|
||||
case SpawnerState.Idle:
|
||||
break;
|
||||
case SpawnerState.TargetAcquired:
|
||||
cylinderColor = Color.coral;
|
||||
break;
|
||||
case SpawnerState.TargetDropped:
|
||||
cylinderColor = Color.khaki;
|
||||
break;
|
||||
case SpawnerState.InCombatUnlocked:
|
||||
cylinderColor = Color.red;
|
||||
break;
|
||||
case SpawnerState.InCombatLocked:
|
||||
cylinderColor = Color.violetRed;
|
||||
break;
|
||||
case SpawnerState.Cooldown:
|
||||
cylinderColor = Color.gray;
|
||||
break;
|
||||
}
|
||||
|
||||
Draw.WireCylinder(transform.position, transform.position + Vector3.up * 7f, radius, cylinderColor);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user