ludumdare50/Assets/Scripts/AIEntity.cs
2022-04-02 15:50:30 -04:00

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;
}
}
}