Can throw enemies from safe zone

This commit is contained in:
Jason Durand 01 2022-04-02 17:20:01 -04:00
parent 29711ae0e3
commit c07aa285c8
11 changed files with 177 additions and 112 deletions

View File

@ -1756,12 +1756,18 @@ MonoBehaviour:
m_EditorClassIdentifier:
gameFlowManager: {fileID: 1359990806}
spawners:
- {x: -10, y: 10, z: 0}
- {x: 10, y: 10, z: 0}
- {x: -17.75, y: 0, z: 0}
- {x: 17.75, y: 0, z: 0}
- {x: -10, y: -10, z: 0}
- {x: 10, y: -10, z: 0}
- position: {x: -10, y: 10}
direction: {x: 0, y: -1}
- position: {x: 10, y: 10}
direction: {x: 0, y: -1}
- position: {x: -17.75, y: 0}
direction: {x: 1, y: 0}
- position: {x: 17.75, y: 0}
direction: {x: -1, y: 0}
- position: {x: -10, y: -10}
direction: {x: 0, y: 1}
- position: {x: 10, y: -10}
direction: {x: 0, y: 1}
stats: {fileID: 11400000, guid: fe319ad8c9a37b84e8b45268c913d54c, type: 2}
entityPrefab: {fileID: 197677485360569561, guid: b25a487d193f24049b6a791adf592b2e, type: 3}
--- !u!114 &1359990806
@ -1776,4 +1782,5 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: e3fecdc4a8b2cb4419ef9d03180d130d, type: 3}
m_Name:
m_EditorClassIdentifier:
gameTimer: {fileID: 0}
<Paused>k__BackingField: 1

View File

@ -222,10 +222,10 @@ PrefabInstance:
m_Modification:
m_TransformParent: {fileID: 0}
m_Modifications:
- target: {fileID: -7596782781093632548, guid: 581322f036f3ff1448d4d2ec70f295a4, type: 3}
propertyPath: gameFlowManager
- target: {fileID: 1359990806, guid: 581322f036f3ff1448d4d2ec70f295a4, type: 3}
propertyPath: gameTimer
value:
objectReference: {fileID: 1359990806}
objectReference: {fileID: 344214379}
- target: {fileID: 4164153230343464235, guid: 581322f036f3ff1448d4d2ec70f295a4, type: 3}
propertyPath: globalCamera
value:
@ -280,25 +280,17 @@ PrefabInstance:
objectReference: {fileID: 0}
m_RemovedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: 581322f036f3ff1448d4d2ec70f295a4, type: 3}
--- !u!1 &1359990805 stripped
GameObject:
m_CorrespondingSourceObject: {fileID: 9196727425507610131, guid: 581322f036f3ff1448d4d2ec70f295a4, type: 3}
--- !u!114 &1359990809 stripped
MonoBehaviour:
m_CorrespondingSourceObject: {fileID: 1359990806, guid: 581322f036f3ff1448d4d2ec70f295a4, type: 3}
m_PrefabInstance: {fileID: 1359990804}
m_PrefabAsset: {fileID: 0}
--- !u!114 &1359990806
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1359990805}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: e3fecdc4a8b2cb4419ef9d03180d130d, type: 3}
m_Name:
m_EditorClassIdentifier:
gameTimer: {fileID: 344214379}
<Paused>k__BackingField: 1
--- !u!114 &1464970062 stripped
MonoBehaviour:
m_CorrespondingSourceObject: {fileID: 1878107874314509256, guid: e1dac4f28fe75a547b919b7aa8240fed, type: 3}
@ -513,11 +505,11 @@ PrefabInstance:
- target: {fileID: 1214567908930553477, guid: 3e0aae8cda56aef44af9598dc5471020, type: 3}
propertyPath: m_ActionEvents.Array.data[14].m_PersistentCalls.m_Calls.Array.data[0].m_Target
value:
objectReference: {fileID: 1359990806}
objectReference: {fileID: 1359990809}
- target: {fileID: 1214567908930553477, guid: 3e0aae8cda56aef44af9598dc5471020, type: 3}
propertyPath: m_ActionEvents.Array.data[15].m_PersistentCalls.m_Calls.Array.data[0].m_Target
value:
objectReference: {fileID: 1359990806}
objectReference: {fileID: 1359990809}
- target: {fileID: 1214567908930553477, guid: 3e0aae8cda56aef44af9598dc5471020, type: 3}
propertyPath: m_ActionEvents.Array.data[16].m_PersistentCalls.m_Calls.Array.data[0].m_Target
value:
@ -589,7 +581,7 @@ PrefabInstance:
- target: {fileID: 1214567908930553592, guid: 3e0aae8cda56aef44af9598dc5471020, type: 3}
propertyPath: gameFlowManager
value:
objectReference: {fileID: 1359990806}
objectReference: {fileID: 1359990809}
- target: {fileID: 1214567908930553593, guid: 3e0aae8cda56aef44af9598dc5471020, type: 3}
propertyPath: m_Name
value: Vampire
@ -642,6 +634,10 @@ PrefabInstance:
propertyPath: m_SortingOrder
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1967503440015794769, guid: 3e0aae8cda56aef44af9598dc5471020, type: 3}
propertyPath: gameFlowManager
value:
objectReference: {fileID: 1359990809}
- target: {fileID: 3126145803593047825, guid: 3e0aae8cda56aef44af9598dc5471020, type: 3}
propertyPath: healthBar
value:
@ -653,7 +649,7 @@ PrefabInstance:
- target: {fileID: 3126145803593047825, guid: 3e0aae8cda56aef44af9598dc5471020, type: 3}
propertyPath: gameFlowManager
value:
objectReference: {fileID: 1359990806}
objectReference: {fileID: 1359990809}
- target: {fileID: 3126145803593047825, guid: 3e0aae8cda56aef44af9598dc5471020, type: 3}
propertyPath: <Health>k__BackingField
value: 100

View File

@ -26,3 +26,28 @@ MonoBehaviour:
- {x: 14, y: 0, z: 0}
- {x: 14, y: 0, z: 0}
- {x: 14, y: 0, z: 0}
<ThrownCurve>k__BackingField:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: 2.4414444
outSlope: 2.4414444
tangentMode: 0
weightedMode: 0
inWeight: 0
outWeight: 0.036708858
- serializedVersion: 3
time: 1
value: 1
inSlope: -0.042344622
outSlope: -0.042344622
tangentMode: 0
weightedMode: 0
inWeight: 0.05569625
outWeight: 0
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
<ThrownDurationPerMeter>k__BackingField: 0.15

View File

@ -6,16 +6,14 @@ using UnityEngine.Serialization;
public class AIEntity : Entity
{
[FormerlySerializedAs("stats")] [SerializeField] AIStats AIStats = null!;
[FormerlySerializedAs("stats")] [SerializeField]
public AIStats AIStats = null!;
BaseState currentState = null!;
public string[] enemies {get; protected set; }
override protected void Awake(){
base.Awake();
currentState = new FindTargetState(this);
}
override protected void Start(){
base.Start();
currentState = CreateInitialState();
currentState.EnterState();
}
@ -37,6 +35,8 @@ public class AIEntity : Entity
newState.EnterState();
}
protected virtual BaseState CreateInitialState() => new FindTargetState(this);
//Looks into enemy name list to see if the other is targetable
virtual protected bool IsTargetable(Entity other){
foreach (string name in enemies){
@ -48,75 +48,14 @@ public class AIEntity : Entity
return false;
}
abstract class BaseStateAI : BaseState{
protected abstract class BaseStateAI : BaseState{
protected AIEntity entity;
public BaseStateAI(AIEntity entity){
this.entity = entity;
}
}
/*//Basically a copy of JumpingMovementState
class NonPhysicThrownState : BaseStateAI {
readonly Vector3 target;
Vector3 startPosition;
float duration;
float startTime;
public NonPhysicThrownState(AIEntity entity, Vector3 target) : base(entity) {
this.target = target;
}
public override void EnterState() {
base.EnterState();
duration = entity.AIStats.ThrownDurationPerMeter * Vector3.Distance(entity.transform.position, target);
startPosition = entity.transform.position;
startTime = Time.time;
entity.rb.SetEnabled(false);
}
public override void LeaveState() {
base.LeaveState();
entity.rb.SetEnabled(true);
}
public override BaseState? FixedUpdateState() {
float currentTime = Time.time - startTime;
if (currentTime >= duration)
return new FindTargetState(entity);
entity.rb.MovePosition(Vector3.Lerp(
startPosition,
target,
entity.AIStats.ThrownCurve.Evaluate(currentTime / duration)
));
return null;
}
}*/
class ThrownState : BaseStateAI {
public ThrownState(AIEntity entity) : base(entity) {}
public override void EnterState() {
base.EnterState();
entity.rb.SetEnabled(false);
}
public override void LeaveState() {
base.LeaveState();
entity.rb.SetEnabled(true);
}
public override BaseState? FixedUpdateState()
=> entity.rb.velocity.magnitude < entity.stats.MinVelocityWhenThrown
? new FindTargetState(entity)
: null;
}
class SeekState : BaseStateAI{
protected class SeekState : BaseStateAI{
public SeekState(AIEntity entity) : base(entity){
}
@ -152,7 +91,7 @@ public class AIEntity : Entity
}
}
class FindTargetState : BaseStateAI{
protected class FindTargetState : BaseStateAI{
float closeEnough;
Vector3 roamPosition;
public FindTargetState(AIEntity entity) : base(entity){
@ -199,7 +138,7 @@ public class AIEntity : Entity
}
class AttackState : BaseStateAI{
protected class AttackState : BaseStateAI{
public AttackState(AIEntity entity) : base(entity){
}
@ -234,7 +173,7 @@ public class AIEntity : Entity
}
}
class DeadState : BaseStateAI{
protected class DeadState : BaseStateAI{
public DeadState(AIEntity entity) : base(entity){
Debug.Log("Dead!");
}

View File

@ -12,8 +12,8 @@ public class AIStats : ScriptableObject {
}
[field: SerializeField]
public AnimationCurve ThrownCurve { get; }
public AnimationCurve ThrownCurve { get; private set; }
[field: SerializeField]
public float ThrownDurationPerMeter { get; }
public float ThrownDurationPerMeter { get; private set; }
}

View File

@ -12,4 +12,4 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 8de175900b604adb984b49af64538a07, type: 3}
m_Name: Arena Stats
m_EditorClassIdentifier:
secondsBetweenSpawners: 3
secondsBetweenSpawners: 8

View File

@ -1,16 +1,24 @@
#nullable enable
using System;
using System.Collections;
using NaughtyAttributes;
using UnityEngine;
using Random = UnityEngine.Random;
public class Arena : MonoBehaviour {
[Serializable]
struct GladiatorEntrance {
public Vector2 position;
public Vector2 direction;
}
[SerializeField] [Required]
GameFlowManager gameFlowManager = null!;
//TODO probably add initial direction too
//TODO Add some kind of "MinLength(1)" attribute
[SerializeField]
Vector3[] spawners = null!;
GladiatorEntrance[] spawners = null!;
[SerializeField] [Required]
ArenaStats stats = null!;
[SerializeField] [Required]
@ -26,8 +34,9 @@ public class Arena : MonoBehaviour {
if (gameFlowManager.Paused)
return;
var entity = Instantiate(entityPrefab, spawners[spawnerIndex], Quaternion.identity).GetComponent<Entity>();
entity.gameFlowManager = (gameFlowManager);
var entity = Instantiate(entityPrefab, spawners[spawnerIndex].position, Quaternion.identity).GetComponent<Entity>();
entity.direction = spawners[spawnerIndex].direction;
entity.gameFlowManager = gameFlowManager;
}
IEnumerator SpawnEnemies() {
@ -45,8 +54,10 @@ public class Arena : MonoBehaviour {
#if UNITY_EDITOR
void OnDrawGizmosSelected() {
Gizmos.color = Color.blue;
foreach (Vector3 spawner in spawners)
Gizmos.DrawWireCube(spawner, Vector3.one);
foreach (GladiatorEntrance entrance in spawners) {
Gizmos.DrawWireCube(entrance.position, Vector3.one);
Gizmos.DrawLine(entrance.position, entrance.position + entrance.direction);
}
}
#endif
}

View File

@ -11,7 +11,7 @@ public class Entity : MonoBehaviour {
[field: SerializeField]
[field: Required]
protected EntityStats stats { get; private set; }
public EntityStats stats { get; private set; }
[field: SerializeField] public float Health { get; private set; }
[Min(10f)]
protected float initialHealth;
@ -36,7 +36,9 @@ public class Entity : MonoBehaviour {
virtual protected void Awake() => rb = GetComponent<Rigidbody2D>();
protected virtual void Start() {
direction = new Vector3(1, 0, 0);
if (direction == Vector3.zero && !(this is VampireEntity))
Debug.LogWarning("Entity had null direction.");
attackTimer = attackCooldown;
initialHealth = Health;
if (halo != null) {

View File

@ -1,9 +1,13 @@
#nullable enable
using System.Collections;
using System.Collections.Generic;
using NaughtyAttributes;
using UnityEngine;
using UnityEngine.InputSystem;
public class MinionThrower : MonoBehaviour {
[SerializeField] [Required]
GameFlowManager gameFlowManager = null!;
public Entity[] minionPrefabs;
public GameObject aimArrow;
@ -12,11 +16,13 @@ public class MinionThrower : MonoBehaviour {
Vector2 throwDirection = Vector2.right;
MinionBar minionBar;
VampireEntity vampireEntity;
PlayerMovement movement;
float currentCooldownTimer;
float currentInitialCooldown;
void Awake() {
vampireEntity = GetComponent<VampireEntity>();
movement = GetComponent<PlayerMovement>();
minionBar = FindObjectOfType<MinionBar>();
aimArrow.SetActive(false);
}
@ -35,6 +41,9 @@ public class MinionThrower : MonoBehaviour {
}
public void ToggleThrowMode(InputAction.CallbackContext context) {
if (gameFlowManager.Paused)
return;
if (context.performed) {
isInThrowMode = true;
aimArrow.SetActive(true);
@ -65,9 +74,15 @@ public class MinionThrower : MonoBehaviour {
currentCooldownTimer = currentInitialCooldown;
minionBar.UpdateReload(currentCooldownTimer / currentInitialCooldown);
Entity newMinion = Instantiate(minionBar.GetCurrentMinion().gameObject, transform.position + new Vector3(throwDirection.x, throwDirection.y, 0f) * 1f, Quaternion.identity).GetComponent<Entity>();
var newMinion = Instantiate(minionBar.GetCurrentMinion().gameObject, transform.position + new Vector3(throwDirection.x, throwDirection.y, 0f) * 1f, Quaternion.identity)
.GetComponent<Monster>();
if (movement.GetSafeZone() is {} safeZone) {
newMinion.thrownFromSafeZone = true;
newMinion.thrownTargetPosition = safeZone.GetOutsidePosition(throwDirection);
}
newMinion.direction = throwDirection;
newMinion.gameFlowManager = vampireEntity.gameFlowManager;
// Apply throw force
}
}

View File

@ -1,9 +1,10 @@
using System.Collections;
using System.Collections.Generic;
#nullable enable
using UnityEngine;
public class Monster : AIEntity
{
public class Monster : AIEntity {
public bool thrownFromSafeZone;
public Vector3 thrownTargetPosition;
// Start is called before the first frame update
override protected void Start()
{
@ -12,4 +13,69 @@ public class Monster : AIEntity
base.enemies = new string[]{"Gladiator"};
}
protected override BaseState CreateInitialState()
=> thrownFromSafeZone
? (BaseStateAI)new NonPhysicThrownState(this, thrownTargetPosition)
: new ThrownState(this);
//Basically a copy of JumpingMovementState
protected class NonPhysicThrownState : BaseStateAI {
readonly Vector3 target;
Vector3 startPosition;
float duration;
float startTime;
public NonPhysicThrownState(AIEntity entity, Vector3 target) : base(entity) {
this.target = target;
}
public override void EnterState() {
base.EnterState();
duration = entity.AIStats.ThrownDurationPerMeter * Vector3.Distance(entity.transform.position, target);
startPosition = entity.transform.position;
startTime = Time.time;
entity.rb.SetEnabled(false);
}
public override void LeaveState() {
base.LeaveState();
entity.rb.SetEnabled(true);
}
public override BaseState? FixedUpdateState() {
float currentTime = Time.time - startTime;
if (currentTime >= duration)
return new FindTargetState(entity);
entity.rb.MovePosition(Vector3.Lerp(
startPosition,
target,
entity.AIStats.ThrownCurve.Evaluate(currentTime / duration)
));
return null;
}
}
protected class ThrownState : BaseStateAI {
public ThrownState(AIEntity entity) : base(entity) {}
public override void EnterState() {
base.EnterState();
entity.rb.SetEnabled(false);
}
public override void LeaveState() {
base.LeaveState();
entity.rb.SetEnabled(true);
}
public override BaseState? FixedUpdateState()
=> entity.rb.velocity.magnitude < entity.stats.MinVelocityWhenThrown
? new FindTargetState(entity)
: null;
}
}

View File

@ -49,6 +49,10 @@ public class PlayerMovement : MonoBehaviour {
#endregion
public SafeZone? GetSafeZone() {
return safeZone;
}
#region Inputs
public void OnMove(InputAction.CallbackContext ctx) {