using System.Collections.Generic;
using ColdMint.scripts.camp;
using ColdMint.scripts.stateMachine;
using Godot;
namespace ColdMint.scripts.character;
///
/// The role played by computers
/// 由电脑扮演的角色
///
public sealed partial class AiCharacter : CharacterTemplate
{
//Used to detect rays on walls
//用于检测墙壁的射线
private RayCast2D? _wallDetection;
public RayCast2D? WallDetection => _wallDetection;
private Vector2 _wallDetectionOrigin;
private Area2D? _attackArea;
///
/// All enemies within striking distance
/// 在攻击范围内的所有敌人
///
private List? _enemyInTheAttackRange;
///
/// Obstacle detection ray during attack
/// 攻击时的障碍物检测射线
///
///
///
///检测与目标点直接是否间隔墙壁
///
private RayCast2D? _attackObstacleDetection;
///
/// Navigation agent
/// 导航代理
///
public NavigationAgent2D? NavigationAgent2D { get; set; }
public IStateMachine? StateMachine { get; set; }
public RayCast2D? AttackObstacleDetection => _attackObstacleDetection;
public override void _Ready()
{
base._Ready();
_enemyInTheAttackRange = new List();
_wallDetection = GetNode("WallDetection");
_attackArea = GetNode("AttackArea2D");
NavigationAgent2D = GetNode("NavigationAgent2D");
if (ItemMarker2D != null)
{
_attackObstacleDetection = ItemMarker2D.GetNode("AttackObstacleDetection");
}
if (_attackArea != null)
{
//If true, the zone will detect objects or areas entering and leaving the zone.
//如果为true,该区域将检测进出该区域的物体或区域。
_attackArea.Monitoring = true;
//Other areas can't detect our attack zone
//其他区域不能检测到我们的攻击区域
_attackArea.Monitorable = false;
_attackArea.BodyEntered += EnterTheAttackArea;
_attackArea.BodyExited += ExitTheAttackArea;
}
_wallDetectionOrigin = _wallDetection.TargetPosition;
StateMachine = new PatrolStateMachine();
StateMachine.Context = new StateContext
{
CurrentState = State.Patrol,
Owner = this
};
if (StateMachine != null)
{
StateMachine.Start();
}
}
///
/// EnemyDetected
/// 是否发现敌人
///
///
///Have you spotted the enemy?
///是否发现敌人
///
public bool EnemyDetected()
{
if (_enemyInTheAttackRange == null)
{
return false;
}
return _enemyInTheAttackRange.Count > 0;
}
///
/// Get the first enemy to enter range
/// 获取第一个进入范围的敌人
///
///
public CharacterTemplate? GetFirstEnemy()
{
if (_enemyInTheAttackRange == null || _enemyInTheAttackRange.Count == 0)
{
return null;
}
return _enemyInTheAttackRange[0];
}
protected override void HookPhysicsProcess(ref Vector2 velocity, double delta)
{
StateMachine?.Execute();
if (NavigationAgent2D != null && IsOnFloor())
{
var nextPathPosition = NavigationAgent2D.GetNextPathPosition();
var direction = (nextPathPosition - GlobalPosition).Normalized();
velocity = direction * Config.CellSize * Speed;
}
}
private void EnterTheAttackArea(Node node)
{
if (node == this)
{
//The target can't be yourself.
//攻击目标不能是自己。
return;
}
if (node is CharacterTemplate characterTemplate)
{
//Determine if damage can be done between factions
//判断阵营间是否可造成伤害
var camp = CampManager.GetCamp(CampId);
var enemyCamp = CampManager.GetCamp(characterTemplate.CampId);
if (enemyCamp != null && camp != null)
{
var canCause = CampManager.CanCauseHarm(camp, enemyCamp);
if (canCause)
{
_enemyInTheAttackRange?.Add(characterTemplate);
}
}
}
}
private void ExitTheAttackArea(Node node)
{
if (node == this)
{
return;
}
if (node is CharacterTemplate characterTemplate)
{
_enemyInTheAttackRange?.Remove(characterTemplate);
}
}
///
/// Set target location
/// 设置目标位置
///
///
public void SetTargetPosition(Vector2 targetPosition)
{
if (NavigationAgent2D == null)
{
return;
}
NavigationAgent2D.TargetPosition = targetPosition;
}
public override void _ExitTree()
{
base._ExitTree();
if (_attackArea != null)
{
_attackArea.BodyEntered -= EnterTheAttackArea;
_attackArea.BodyExited -= ExitTheAttackArea;
}
if (StateMachine != null)
{
StateMachine.Stop();
}
}
}