using System; using System.Collections.Generic; using ColdMint.scripts.debug; 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; /// /// Nodes in the attack range /// 在攻击范围内的节点 /// private List? _nodesInTheAttackRange; /// /// All nodes in the attack range /// 在攻击范围内的全部节点 /// public Node[] NodesInTheAttackRange => _nodesInTheAttackRange?.ToArray() ?? Array.Empty(); /// /// 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(); _nodesInTheAttackRange = 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(); } } 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) { _nodesInTheAttackRange?.Add(node); } private void ExitTheAttackArea(Node node) { _nodesInTheAttackRange?.Remove(node); } /// /// 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(); } } }