166 lines
5.0 KiB
C#
166 lines
5.0 KiB
C#
#nullable enable
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEngine.Serialization;
|
|
|
|
public class AIEntity : Entity
|
|
{
|
|
[FormerlySerializedAs("stats")] [SerializeField] AIStats AIStats = null!;
|
|
public string? ennemyName {get; protected set; }
|
|
|
|
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{
|
|
public SeekState(AIEntity entity) : base(entity){
|
|
|
|
}
|
|
|
|
public override BaseState? UpdateState(){
|
|
Entity targetEntity = entity.GetTarget().GetComponent<Entity>();
|
|
if(targetEntity != null){
|
|
if(targetEntity.IsAlive()){//target is alive, keep chasing it
|
|
return null;
|
|
}else{//target is dead, go to findTargetState
|
|
return new FindTargetState(entity);;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public override BaseState? FixedUpdateState(){
|
|
Transform target = entity.GetTarget();
|
|
entity.direction = Vector3.RotateTowards(entity.direction, (target.position - entity.transform.position), entity.rotSpeed*Time.fixedDeltaTime, 0.0f);
|
|
if(!entity.IsInAttackRange()){
|
|
entity.rb.MovePosition(entity.transform.position + entity.direction * entity.movementSpeed * Time.fixedDeltaTime);
|
|
}else{
|
|
return new AttackState(entity);
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
|
|
class FindTargetState : BaseStateAI{
|
|
float closeEnough;
|
|
public FindTargetState(AIEntity entity) : base(entity){
|
|
}
|
|
|
|
public override BaseState? UpdateState(){
|
|
Entity[] entities = FindObjectsOfType<Entity>();
|
|
float lastDist = -1;
|
|
Entity chosenEntity = null!;
|
|
foreach (Entity other in entities){// Find the closest entity
|
|
if(other.name == entity.ennemyName){
|
|
float distance = Vector2.Distance(other.transform.position, entity.transform.position);
|
|
if(distance < lastDist){
|
|
lastDist = distance;
|
|
chosenEntity = other;
|
|
if(lastDist <= entity.AIStats.closeEnough)break;
|
|
}
|
|
}
|
|
}
|
|
if(chosenEntity != null){
|
|
entity.SetTarget(chosenEntity.transform);
|
|
}
|
|
return new SeekState(entity);
|
|
}
|
|
|
|
}
|
|
|
|
class AttackState : BaseStateAI{
|
|
public AttackState(AIEntity entity) : base(entity){
|
|
}
|
|
|
|
public override BaseState? UpdateState(){
|
|
if(entity.IsInAttackRange()){
|
|
if(entity.attackTimer >= entity.attackCooldown){
|
|
entity.attackTimer = 0;
|
|
return Attack();
|
|
}else{
|
|
entity.attackTimer += Time.deltaTime;
|
|
}
|
|
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private BaseState? Attack(){
|
|
Entity targetEntity = entity.GetTarget().GetComponent<Entity>();
|
|
if(targetEntity != null){
|
|
targetEntity.TakeDamage(entity.attackDmg);
|
|
bool isTargetAlive = targetEntity.IsAlive();
|
|
if(!isTargetAlive){
|
|
return new FindTargetState(entity);
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
}
|