Join the status processor of the AI escape.
加入AI逃跑的状态处理器。
This commit is contained in:
parent
7812d9c570
commit
9401913779
|
@ -28,9 +28,7 @@ log_loot_list_has_no_entries,ID为{0}的战利品表,没有指定条目。,"Lo
|
||||||
log_not_within_the_loot_spawn_range,给定的数值{0}没有在战利品{1}的生成范围{2}内。,The given value {0} is not within the spawn range {2} of loot {1}.,与えられた数値{0}は戦利品{1}の生成範囲{2}内にありません。
|
log_not_within_the_loot_spawn_range,给定的数值{0}没有在战利品{1}的生成范围{2}内。,The given value {0} is not within the spawn range {2} of loot {1}.,与えられた数値{0}は戦利品{1}の生成範囲{2}内にありません。
|
||||||
log_loot_data_quantity,有{0}个战利品数据被返回。,{0} loot data was returned.,{0}個の戦利品データが返されます。
|
log_loot_data_quantity,有{0}个战利品数据被返回。,{0} loot data was returned.,{0}個の戦利品データが返されます。
|
||||||
log_loot_data_add,生成战利品{0},Add loot {0},戦利品{0}を生成する
|
log_loot_data_add,生成战利品{0},Add loot {0},戦利品{0}を生成する
|
||||||
|
|
||||||
log_warning_node_cannot_cast_to,创建的物品{0}无法被转型为类型{1},Created items {0} cannot be cast into type {1},作成されたアイテム {0} をタイプ {1} にキャストすることはできません。
|
log_warning_node_cannot_cast_to,创建的物品{0}无法被转型为类型{1},Created items {0} cannot be cast into type {1},作成されたアイテム {0} をタイプ {1} にキャストすることはできません。
|
||||||
|
|
||||||
log_start_item_register_from_file,开始从文件注册物品信息,Start registering item information from files,アイテム情報をファイルから登録開始
|
log_start_item_register_from_file,开始从文件注册物品信息,Start registering item information from files,アイテム情報をファイルから登録開始
|
||||||
log_found_files,找到{0}个文件,Found {0} files,{0}ファイルが見つかりました
|
log_found_files,找到{0}个文件,Found {0} files,{0}ファイルが見つかりました
|
||||||
log_found_item_types,从文件中找到{0}个物品类型,Found {0} item types in files,ファイルから{0}個のアイテム・タイプが見つかった
|
log_found_item_types,从文件中找到{0}个物品类型,Found {0} item types in files,ファイルから{0}個のアイテム・タイプが見つかった
|
||||||
|
@ -84,3 +82,8 @@ log_no_weapon_detected,没有检测到武器。,No weapon detected.,武器が検
|
||||||
log_weapon_lost,武器丢失。,Weapon lost.,武器が失われました。
|
log_weapon_lost,武器丢失。,Weapon lost.,武器が失われました。
|
||||||
log_nearest_node_is_null,最近的节点为空。,The nearest node is null.,最も近いノードが空です。
|
log_nearest_node_is_null,最近的节点为空。,The nearest node is null.,最も近いノードが空です。
|
||||||
log_node_is_not_WeaponTemplate,节点不是WeaponTemplate。,The node is not a WeaponTemplate.,ノードはWeaponTemplateではありません。
|
log_node_is_not_WeaponTemplate,节点不是WeaponTemplate。,The node is not a WeaponTemplate.,ノードはWeaponTemplateではありません。
|
||||||
|
log_weapon_not_in_pickup_range,武器不在拾取范围内。,The weapon is not within the pickup range.,武器は拾い取り範囲内にありません。
|
||||||
|
log_weapon_picked_up,武器被拾取。,Weapon picked up.,武器が拾い取られました。
|
||||||
|
log_weapon_pickup_failed,武器拾取失败。,Weapon pickup failed.,武器の拾い取りに失敗しました。
|
||||||
|
log_enter_the_picking_range_body,进入拾取范围。,Enter the picking range.,拾い取り範囲に入ります。
|
||||||
|
log_search_for_weapon_timeout,搜索武器超时。,Search for weapon timeout.,武器の検索がタイムアウトしました。
|
|
|
@ -26,7 +26,6 @@ animations = [{
|
||||||
collision_layer = 4
|
collision_layer = 4
|
||||||
collision_mask = 34
|
collision_mask = 34
|
||||||
script = ExtResource("1_1dlls")
|
script = ExtResource("1_1dlls")
|
||||||
LootListId = null
|
|
||||||
metadata/CampId = "Default"
|
metadata/CampId = "Default"
|
||||||
metadata/MaxHp = 32
|
metadata/MaxHp = 32
|
||||||
|
|
||||||
|
|
|
@ -10,8 +10,8 @@
|
||||||
radius = 20.0
|
radius = 20.0
|
||||||
height = 52.0
|
height = 52.0
|
||||||
|
|
||||||
[sub_resource type="CircleShape2D" id="CircleShape2D_vmqbt"]
|
[sub_resource type="RectangleShape2D" id="RectangleShape2D_a3myh"]
|
||||||
radius = 34.5398
|
size = Vector2(46, 65)
|
||||||
|
|
||||||
[sub_resource type="SpriteFrames" id="SpriteFrames_qumby"]
|
[sub_resource type="SpriteFrames" id="SpriteFrames_qumby"]
|
||||||
animations = [{
|
animations = [{
|
||||||
|
@ -25,10 +25,10 @@ animations = [{
|
||||||
}]
|
}]
|
||||||
|
|
||||||
[sub_resource type="CircleShape2D" id="CircleShape2D_c61vr"]
|
[sub_resource type="CircleShape2D" id="CircleShape2D_c61vr"]
|
||||||
radius = 185.132
|
radius = 153.0
|
||||||
|
|
||||||
[sub_resource type="CircleShape2D" id="CircleShape2D_fowd5"]
|
[sub_resource type="CircleShape2D" id="CircleShape2D_fowd5"]
|
||||||
radius = 233.808
|
radius = 172.29
|
||||||
|
|
||||||
[node name="DelivererOfDarkMagic" type="CharacterBody2D"]
|
[node name="DelivererOfDarkMagic" type="CharacterBody2D"]
|
||||||
collision_layer = 64
|
collision_layer = 64
|
||||||
|
@ -48,7 +48,8 @@ collision_layer = 0
|
||||||
collision_mask = 8
|
collision_mask = 8
|
||||||
|
|
||||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2DPickingArea"]
|
[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2DPickingArea"]
|
||||||
shape = SubResource("CircleShape2D_vmqbt")
|
position = Vector2(0, 5.5)
|
||||||
|
shape = SubResource("RectangleShape2D_a3myh")
|
||||||
|
|
||||||
[node name="AnimatedSprite2D" type="AnimatedSprite2D" parent="."]
|
[node name="AnimatedSprite2D" type="AnimatedSprite2D" parent="."]
|
||||||
sprite_frames = SubResource("SpriteFrames_qumby")
|
sprite_frames = SubResource("SpriteFrames_qumby")
|
||||||
|
|
|
@ -8,19 +8,6 @@ namespace ColdMint.scripts;
|
||||||
|
|
||||||
public static class Config
|
public static class Config
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// <para>ID of the behavior tree</para>
|
|
||||||
/// <para>行为树的ID</para>
|
|
||||||
/// </summary>
|
|
||||||
public static class BehaviorTreeId
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// <para>巡逻</para>
|
|
||||||
/// <para>Patrol</para>
|
|
||||||
/// </summary>
|
|
||||||
public const string Patrol = "Patrol";
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <para>Loot table ID</para>
|
/// <para>Loot table ID</para>
|
||||||
/// <para>战利品表ID</para>
|
/// <para>战利品表ID</para>
|
||||||
|
@ -34,31 +21,6 @@ public static class Config
|
||||||
public const string Test = "test";
|
public const string Test = "test";
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>BehaviorTreeResult</para>
|
|
||||||
/// <para>行为树的结果</para>
|
|
||||||
/// </summary>
|
|
||||||
public static class BehaviorTreeResult
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// <para>Running</para>
|
|
||||||
/// <para>运行中</para>
|
|
||||||
/// </summary>
|
|
||||||
public const int Running = 0;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>Success</para>
|
|
||||||
/// <para>成功</para>
|
|
||||||
/// </summary>
|
|
||||||
public const int Success = 1;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>Failure</para>
|
|
||||||
/// <para>失败</para>
|
|
||||||
/// </summary>
|
|
||||||
public const int Failure = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <para>Camp ID</para>
|
/// <para>Camp ID</para>
|
||||||
|
|
|
@ -347,9 +347,12 @@ public sealed partial class AiCharacter : CharacterTemplate
|
||||||
private void EnterTheScoutArea(Node node)
|
private void EnterTheScoutArea(Node node)
|
||||||
{
|
{
|
||||||
if (node is WeaponTemplate weaponTemplate)
|
if (node is WeaponTemplate weaponTemplate)
|
||||||
|
{
|
||||||
|
if (CanPickItem(weaponTemplate))
|
||||||
{
|
{
|
||||||
_weaponInTheScoutRange?.Add(weaponTemplate);
|
_weaponInTheScoutRange?.Add(weaponTemplate);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CanCauseHarmNode(node, (canCause, characterTemplate) =>
|
CanCauseHarmNode(node, (canCause, characterTemplate) =>
|
||||||
{
|
{
|
||||||
|
|
|
@ -240,14 +240,12 @@ public partial class CharacterTemplate : CharacterBody2D
|
||||||
foreach (var pickingRangeBody in PickingRangeBodies)
|
foreach (var pickingRangeBody in PickingRangeBodies)
|
||||||
{
|
{
|
||||||
if (pickingRangeBody is not WeaponTemplate weaponTemplate) continue;
|
if (pickingRangeBody is not WeaponTemplate weaponTemplate) continue;
|
||||||
if (weaponTemplate.Owner != null)
|
if (weaponTemplate.Picked)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
weaponTemplates.Add(weaponTemplate);
|
weaponTemplates.Add(weaponTemplate);
|
||||||
}
|
}
|
||||||
|
|
||||||
return weaponTemplates.ToArray();
|
return weaponTemplates.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -308,7 +306,7 @@ public partial class CharacterTemplate : CharacterBody2D
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="node"></param>
|
/// <param name="node"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private bool CanPickItem(Node node)
|
protected bool CanPickItem(Node node)
|
||||||
{
|
{
|
||||||
if (_currentItem != null && node == _currentItem)
|
if (_currentItem != null && node == _currentItem)
|
||||||
{
|
{
|
||||||
|
@ -336,7 +334,7 @@ public partial class CharacterTemplate : CharacterBody2D
|
||||||
///<para>Whether successfully picked up</para>
|
///<para>Whether successfully picked up</para>
|
||||||
///<para>是否成功拾起</para>
|
///<para>是否成功拾起</para>
|
||||||
/// </returns>
|
/// </returns>
|
||||||
protected bool PickItem(Node2D? pickAbleItemNode2D)
|
public bool PickItem(Node2D? pickAbleItemNode2D)
|
||||||
{
|
{
|
||||||
//Empty reference checking is implicitly performed here.
|
//Empty reference checking is implicitly performed here.
|
||||||
//此处隐式的执行了空引用检查。
|
//此处隐式的执行了空引用检查。
|
||||||
|
@ -612,6 +610,7 @@ public partial class CharacterTemplate : CharacterBody2D
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LogCat.Log("enter_the_picking_range_body");
|
||||||
PickingRangeBodiesList?.Add(node);
|
PickingRangeBodiesList?.Add(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,17 +14,17 @@ namespace ColdMint.scripts.projectile;
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public partial class ProjectileTemplate : CharacterBody2D
|
public partial class ProjectileTemplate : CharacterBody2D
|
||||||
{
|
{
|
||||||
protected long Life;
|
private long _life;
|
||||||
|
|
||||||
//The durability of the projectile
|
//The durability of the projectile
|
||||||
//抛射体的耐久度
|
//抛射体的耐久度
|
||||||
//When the projectile hits the object, the durability will be reduced, and when the durability is less than or equal to 0, the projectile will be destroyed
|
//When the projectile hits the object, the durability will be reduced, and when the durability is less than or equal to 0, the projectile will be destroyed
|
||||||
//当抛射体撞击到物体时,会减少耐久度,当耐久度小于等于0时,销毁抛射体
|
//当抛射体撞击到物体时,会减少耐久度,当耐久度小于等于0时,销毁抛射体
|
||||||
protected double Durability;
|
private double _durability;
|
||||||
|
|
||||||
protected int MaxDamage;
|
private int _maxDamage;
|
||||||
protected int MinDamage;
|
private int _minDamage;
|
||||||
protected int DamageType;
|
private int _damageType;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <para>After this time destroy the projectile</para>
|
/// <para>After this time destroy the projectile</para>
|
||||||
|
@ -37,7 +37,7 @@ public partial class ProjectileTemplate : CharacterBody2D
|
||||||
/// <para>The impact area of the bullet</para>
|
/// <para>The impact area of the bullet</para>
|
||||||
/// <para>子弹的碰撞区域</para>
|
/// <para>子弹的碰撞区域</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected Area2D? Area2D;
|
private Area2D? _area2D;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <para>knockback</para>
|
/// <para>knockback</para>
|
||||||
|
@ -47,7 +47,7 @@ public partial class ProjectileTemplate : CharacterBody2D
|
||||||
///<para>How much force does it have when hitting the character? Unit: Number of cells,The X direction of the force is inferred automatically.</para>
|
///<para>How much force does it have when hitting the character? Unit: Number of cells,The X direction of the force is inferred automatically.</para>
|
||||||
///<para>当击中角色时带有多大的力?单位:格数,力的X方向是自动推断的。</para>
|
///<para>当击中角色时带有多大的力?单位:格数,力的X方向是自动推断的。</para>
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
protected Vector2 KnockbackForce;
|
private Vector2 _knockbackForce;
|
||||||
|
|
||||||
public float Speed => GetMeta("Speed", "15").AsSingle();
|
public float Speed => GetMeta("Speed", "15").AsSingle();
|
||||||
|
|
||||||
|
@ -61,26 +61,26 @@ public partial class ProjectileTemplate : CharacterBody2D
|
||||||
{
|
{
|
||||||
//The bullet's impact detection area
|
//The bullet's impact detection area
|
||||||
//子弹的碰撞检测区域
|
//子弹的碰撞检测区域
|
||||||
Area2D = GetNode<Area2D>("CollisionDetectionArea");
|
_area2D = GetNode<Area2D>("CollisionDetectionArea");
|
||||||
Area2D.Monitoring = true;
|
_area2D.Monitoring = true;
|
||||||
Area2D.BodyEntered += OnBodyEnter;
|
_area2D.BodyEntered += OnBodyEnter;
|
||||||
Area2D.BodyExited += OnBodyExited;
|
_area2D.BodyExited += OnBodyExited;
|
||||||
Durability = GetMeta("Durability", "1").AsDouble();
|
_durability = GetMeta("Durability", "1").AsDouble();
|
||||||
MaxDamage = GetMeta("MaxDamage", "7").AsInt32();
|
_maxDamage = GetMeta("MaxDamage", "7").AsInt32();
|
||||||
MinDamage = GetMeta("MinDamage", "5").AsInt32();
|
_minDamage = GetMeta("MinDamage", "5").AsInt32();
|
||||||
DamageType = GetMeta("DamageType", Config.DamageType.Physical).AsInt32();
|
_damageType = GetMeta("DamageType", Config.DamageType.Physical).AsInt32();
|
||||||
KnockbackForce = GetMeta("Knockback", Vector2.Zero).AsVector2();
|
_knockbackForce = GetMeta("Knockback", Vector2.Zero).AsVector2();
|
||||||
//life(ms)
|
//life(ms)
|
||||||
//子弹的存在时间(毫秒)
|
//子弹的存在时间(毫秒)
|
||||||
Life = GetMeta("Life", "10000").AsInt64();
|
_life = GetMeta("Life", "10000").AsInt64();
|
||||||
//If the existence time is less than or equal to 0, then it is set to exist for 10 seconds, and projectiles that exist indefinitely are prohibited
|
//If the existence time is less than or equal to 0, then it is set to exist for 10 seconds, and projectiles that exist indefinitely are prohibited
|
||||||
//如果存在时间小于等于0,那么设置为存在10秒,禁止无限期存在的抛射体
|
//如果存在时间小于等于0,那么设置为存在10秒,禁止无限期存在的抛射体
|
||||||
if (Life <= 0)
|
if (_life <= 0)
|
||||||
{
|
{
|
||||||
Life = 10000;
|
_life = 10000;
|
||||||
}
|
}
|
||||||
|
|
||||||
_destructionTime = DateTime.Now.AddMilliseconds(Life);
|
_destructionTime = DateTime.Now.AddMilliseconds(_life);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -148,19 +148,19 @@ public partial class ProjectileTemplate : CharacterBody2D
|
||||||
var damage = new Damage
|
var damage = new Damage
|
||||||
{
|
{
|
||||||
Attacker = owner,
|
Attacker = owner,
|
||||||
MaxDamage = MaxDamage,
|
MaxDamage = _maxDamage,
|
||||||
MinDamage = MinDamage
|
MinDamage = _minDamage
|
||||||
};
|
};
|
||||||
damage.CreateDamage();
|
damage.CreateDamage();
|
||||||
damage.MoveLeft = Velocity.X < 0;
|
damage.MoveLeft = Velocity.X < 0;
|
||||||
damage.Type = DamageType;
|
damage.Type = _damageType;
|
||||||
characterTemplate.Damage(damage);
|
characterTemplate.Damage(damage);
|
||||||
if (KnockbackForce != Vector2.Zero)
|
if (_knockbackForce != Vector2.Zero)
|
||||||
{
|
{
|
||||||
//If we set the attack force, then apply the force to the object
|
//If we set the attack force, then apply the force to the object
|
||||||
//如果我们设置了攻退力,那么将力应用到对象上
|
//如果我们设置了攻退力,那么将力应用到对象上
|
||||||
var force = new Vector2();
|
var force = new Vector2();
|
||||||
var forceX = Math.Abs(KnockbackForce.X);
|
var forceX = Math.Abs(_knockbackForce.X);
|
||||||
if (Velocity.X < 0)
|
if (Velocity.X < 0)
|
||||||
{
|
{
|
||||||
//Beat back to port
|
//Beat back to port
|
||||||
|
@ -169,18 +169,18 @@ public partial class ProjectileTemplate : CharacterBody2D
|
||||||
}
|
}
|
||||||
|
|
||||||
force.X = forceX * Config.CellSize;
|
force.X = forceX * Config.CellSize;
|
||||||
force.Y = KnockbackForce.Y * Config.CellSize;
|
force.Y = _knockbackForce.Y * Config.CellSize;
|
||||||
characterTemplate.AddForce(force);
|
characterTemplate.AddForce(force);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (target is PickAbleTemplate pickAbleTemplate)
|
else if (target is PickAbleTemplate pickAbleTemplate)
|
||||||
{
|
{
|
||||||
if (KnockbackForce != Vector2.Zero)
|
if (_knockbackForce != Vector2.Zero)
|
||||||
{
|
{
|
||||||
//If we set the attack force, then apply the force to the object
|
//If we set the attack force, then apply the force to the object
|
||||||
//如果我们设置了攻退力,那么将力应用到对象上
|
//如果我们设置了攻退力,那么将力应用到对象上
|
||||||
var force = new Vector2();
|
var force = new Vector2();
|
||||||
var forceX = Math.Abs(KnockbackForce.X);
|
var forceX = Math.Abs(_knockbackForce.X);
|
||||||
if (Velocity.X < 0)
|
if (Velocity.X < 0)
|
||||||
{
|
{
|
||||||
//Beat back to port
|
//Beat back to port
|
||||||
|
@ -189,7 +189,7 @@ public partial class ProjectileTemplate : CharacterBody2D
|
||||||
}
|
}
|
||||||
|
|
||||||
force.X = forceX * Config.CellSize;
|
force.X = forceX * Config.CellSize;
|
||||||
force.Y = KnockbackForce.Y * Config.CellSize;
|
force.Y = _knockbackForce.Y * Config.CellSize;
|
||||||
pickAbleTemplate.ApplyImpulse(force);
|
pickAbleTemplate.ApplyImpulse(force);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -215,8 +215,8 @@ public partial class ProjectileTemplate : CharacterBody2D
|
||||||
//请在Mask内配置子弹会和谁碰撞
|
//请在Mask内配置子弹会和谁碰撞
|
||||||
//When a bullet hits an object, its durability decreases
|
//When a bullet hits an object, its durability decreases
|
||||||
//子弹撞击到物体时,耐久度减少
|
//子弹撞击到物体时,耐久度减少
|
||||||
Durability--;
|
_durability--;
|
||||||
if (Durability <= 0)
|
if (_durability <= 0)
|
||||||
{
|
{
|
||||||
//When the durability is less than or equal to 0, destroy the bullet
|
//When the durability is less than or equal to 0, destroy the bullet
|
||||||
//当耐久度小于等于0时,销毁子弹
|
//当耐久度小于等于0时,销毁子弹
|
||||||
|
|
|
@ -26,5 +26,7 @@ public class PatrolStateMachine : StateMachineTemplate
|
||||||
RegisterProcessor(chaseStateProcessor);
|
RegisterProcessor(chaseStateProcessor);
|
||||||
var lookForWeaponProcessor = new LookForWeaponProcessor();
|
var lookForWeaponProcessor = new LookForWeaponProcessor();
|
||||||
RegisterProcessor(lookForWeaponProcessor);
|
RegisterProcessor(lookForWeaponProcessor);
|
||||||
|
var fleeProcessor = new FleeProcessor();
|
||||||
|
RegisterProcessor(fleeProcessor);
|
||||||
}
|
}
|
||||||
}
|
}
|
63
scripts/stateMachine/StateProcessor/FleeProcessor.cs
Normal file
63
scripts/stateMachine/StateProcessor/FleeProcessor.cs
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
using System;
|
||||||
|
using ColdMint.scripts.character;
|
||||||
|
using Godot;
|
||||||
|
|
||||||
|
namespace ColdMint.scripts.stateMachine.StateProcessor;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Escape state processor</para>
|
||||||
|
/// <para>逃跑状态处理器</para>
|
||||||
|
/// </summary>
|
||||||
|
public class FleeProcessor : StateProcessorTemplate
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// <para>When to return to enemy free status</para>
|
||||||
|
/// <para>何时恢复到没有敌人的状态</para>
|
||||||
|
/// </summary>
|
||||||
|
private DateTime? _endTime;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>When away from the enemy, how long to return to normal state</para>
|
||||||
|
/// <para>当远离敌人后,多长时间恢复到正常状态</para>
|
||||||
|
/// </summary>
|
||||||
|
public TimeSpan RecoveryTimeSpan { get; set; } = TimeSpan.FromMilliseconds(300);
|
||||||
|
|
||||||
|
protected override void OnExecute(StateContext context, Node owner)
|
||||||
|
{
|
||||||
|
if (owner is not AiCharacter aiCharacter)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var enemy = aiCharacter.GetFirstEnemyInScoutArea();
|
||||||
|
if (enemy == null)
|
||||||
|
{
|
||||||
|
//There are no enemies left.
|
||||||
|
//没有敌人了
|
||||||
|
if (_endTime == null)
|
||||||
|
{
|
||||||
|
_endTime = DateTime.Now + RecoveryTimeSpan;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DateTime.Now > _endTime)
|
||||||
|
{
|
||||||
|
//Recovery time, end status.
|
||||||
|
//恢复时间,结束状态。
|
||||||
|
context.CurrentState = State.Patrol;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Enemies
|
||||||
|
//有敌人
|
||||||
|
//To calculate the escape direction, the vector of the enemy pointing to the character is the escape direction.
|
||||||
|
//计算逃跑方向,敌人指向角色的向量为逃跑方向。
|
||||||
|
_endTime = null;
|
||||||
|
var direction = aiCharacter.GlobalPosition - enemy.GlobalPosition;
|
||||||
|
aiCharacter.SetTargetPosition(aiCharacter.GlobalPosition + direction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override State State => State.Flee;
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
using System.Collections.Generic;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using ColdMint.scripts.character;
|
using ColdMint.scripts.character;
|
||||||
using ColdMint.scripts.debug;
|
using ColdMint.scripts.debug;
|
||||||
using ColdMint.scripts.utils;
|
using ColdMint.scripts.utils;
|
||||||
|
@ -13,7 +14,37 @@ namespace ColdMint.scripts.stateMachine.StateProcessor;
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class LookForWeaponProcessor : StateProcessorTemplate
|
public class LookForWeaponProcessor : StateProcessorTemplate
|
||||||
{
|
{
|
||||||
protected WeaponTemplate? TargetWeapon;
|
private WeaponTemplate? _targetWeapon;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///<para></para>
|
||||||
|
///<para>停止寻找武器的时间</para>
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>If you don't find a weapon in a while, give up looking</para>
|
||||||
|
/// <para>如果在一段时间内没找到武器,那么放弃寻找</para>
|
||||||
|
/// </remarks>
|
||||||
|
private DateTime _endTime;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>When no weapon was found, how long did they give up looking</para>
|
||||||
|
/// <para>当没有找到武器,多长时间放弃寻找</para>
|
||||||
|
/// </summary>
|
||||||
|
public TimeSpan RecoveryTimeSpan { get; set; } = TimeSpan.FromMilliseconds(150);
|
||||||
|
|
||||||
|
public override void Enter(StateContext context)
|
||||||
|
{
|
||||||
|
UpdateEndTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Update end time</para>
|
||||||
|
/// <para>更新结束时间</para>
|
||||||
|
/// </summary>
|
||||||
|
private void UpdateEndTime()
|
||||||
|
{
|
||||||
|
_endTime = DateTime.Now + RecoveryTimeSpan;
|
||||||
|
}
|
||||||
|
|
||||||
protected override void OnExecute(StateContext context, Node owner)
|
protected override void OnExecute(StateContext context, Node owner)
|
||||||
{
|
{
|
||||||
|
@ -23,11 +54,77 @@ public class LookForWeaponProcessor : StateProcessorTemplate
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TargetWeapon != null)
|
if (_targetWeapon == null)
|
||||||
{
|
{
|
||||||
|
if (DateTime.Now > _endTime)
|
||||||
|
{
|
||||||
|
//The search for the weapon ran out of time
|
||||||
|
//寻找武器时超时
|
||||||
|
LogCat.Log("search_for_weapon_timeout", LogCat.LogLabel.LookForWeaponProcessor);
|
||||||
|
context.CurrentState = State.Flee;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (_targetWeapon.Picked)
|
||||||
|
{
|
||||||
|
//If the weapon we're looking for gets picked up, we find a new one.
|
||||||
|
//如果我们要拿的武器被别人捡了,那么重新找新的武器。
|
||||||
|
_targetWeapon = null;
|
||||||
|
UpdateEndTime();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
//If the nearest weapon is found, move the character to the weapon.
|
//If the nearest weapon is found, move the character to the weapon.
|
||||||
//如果有最近的武器被找到了,那么将角色移动到武器旁边。
|
//如果有最近的武器被找到了,那么将角色移动到武器旁边。
|
||||||
aiCharacter.SetTargetPosition(TargetWeapon.GlobalPosition);
|
var weaponTemplates = aiCharacter.GetCanPickedWeapon();
|
||||||
|
//Weapons are not in the range of the pickup.
|
||||||
|
//武器没在拾捡范围内。
|
||||||
|
if (weaponTemplates.Length == 0)
|
||||||
|
{
|
||||||
|
LogCat.Log("weapon_not_in_pickup_range", LogCat.LogLabel.LookForWeaponProcessor);
|
||||||
|
aiCharacter.SetTargetPosition(_targetWeapon.GlobalPosition);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var haveWeapon = false;
|
||||||
|
foreach (var weaponTemplate in weaponTemplates)
|
||||||
|
{
|
||||||
|
if (weaponTemplate == _targetWeapon)
|
||||||
|
{
|
||||||
|
haveWeapon = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (haveWeapon)
|
||||||
|
{
|
||||||
|
var pickResult = aiCharacter.PickItem(_targetWeapon);
|
||||||
|
if (pickResult)
|
||||||
|
{
|
||||||
|
context.CurrentState = context.PreviousState;
|
||||||
|
//Successfully picked up the weapon.
|
||||||
|
//成功拾起武器。
|
||||||
|
LogCat.Log("weapon_picked_up", LogCat.LogLabel.LookForWeaponProcessor);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_targetWeapon = null;
|
||||||
|
UpdateEndTime();
|
||||||
|
//Weapon failed to pick up.
|
||||||
|
//武器捡起时失败。
|
||||||
|
LogCat.Log("weapon_pickup_failed", LogCat.LogLabel.LookForWeaponProcessor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//No weapons are included in the pickup area.
|
||||||
|
//拾捡范围内不包含武器。
|
||||||
|
LogCat.Log("weapon_not_in_pickup_range", LogCat.LogLabel.LookForWeaponProcessor);
|
||||||
|
aiCharacter.SetTargetPosition(_targetWeapon.GlobalPosition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,7 +164,7 @@ public class LookForWeaponProcessor : StateProcessorTemplate
|
||||||
|
|
||||||
if (node is WeaponTemplate weaponTemplate)
|
if (node is WeaponTemplate weaponTemplate)
|
||||||
{
|
{
|
||||||
TargetWeapon = weaponTemplate;
|
_targetWeapon = weaponTemplate;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue
Block a user