using System; using ColdMint.scripts.camp; using ColdMint.scripts.character; using ColdMint.scripts.damage; using Godot; namespace ColdMint.scripts.projectile; /// /// Projectile template /// 抛射体模板 /// public partial class ProjectileTemplate : CharacterBody2D { protected Timer? Timer; protected double Life; //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 //当抛射体撞击到物体时,会减少耐久度,当耐久度小于等于0时,销毁抛射体 protected double Durability; protected int MaxDamage; protected int MinDamage; protected int DamageType; //We use the Time node to specify when to destroy the projectile //我们用Time节点来指定何时销毁抛射体 private Timer? _timer; /// /// The impact area of the bullet /// 子弹的碰撞区域 /// protected Area2D? Area2D; /// /// knockback /// 击退 /// /// ///How much force does it have when hitting the character? Unit: Number of cells,The X direction of the force is inferred automatically. ///当击中角色时带有多大的力?单位:格数,力的X方向是自动推断的。 /// protected Vector2 KnockbackForce; public float Speed { get => GetMeta("Speed", "15").AsSingle(); } /// /// The master of the weapon /// 武器的主人 /// public new Node2D? Owner { get; set; } public override void _Ready() { //子弹的碰撞检测区域 Area2D = GetNode("CollisionDetectionArea"); Area2D.Monitoring = true; Area2D.BodyEntered += OnBodyEnter; Area2D.BodyExited += OnBodyExited; Durability = GetMeta("Durability", "1").AsDouble(); MaxDamage = GetMeta("MaxDamage", "7").AsInt32(); MinDamage = GetMeta("MinDamage", "5").AsInt32(); DamageType = GetMeta("DamageType", Config.DamageType.Physical).AsInt32(); KnockbackForce = GetMeta("Knockback", Vector2.Zero).AsVector2(); //子弹的存在时间 Life = GetMeta("Life", "10").AsDouble(); //如果存在时间小于等于0,那么设置为存在10秒,禁止无限期存在的抛射体 if (Life <= 0) { Life = 10; } Timer = new Timer(); AddChild(Timer); Timer.WaitTime = Life; Timer.OneShot = true; Timer.Start(); Timer.Timeout += OnTimeOut; } /// /// Detect whether harm is allowed /// 检测是否允许造成伤害 /// /// /// /// private bool CanCauseHarm(Node2D? owner, Node2D target) { //We must know who the owner of the bullet is in order to determine whether it should cause damage or not //我们必须知道子弹的主人是谁,才能判断是否应该造成伤害 if (owner == null) { return false; } if (owner is not CharacterTemplate ownerCharacterTemplate) { return false; } if (target is TileMap) { //When we hit the tile, we return true in order to place the bullet through the tile. //撞击到瓦片时,我们返回true,是为了放置子弹穿透瓦片。 return true; } if (target is not CharacterTemplate characterTemplate) { return false; } //First get the owner's camp and compare it with the target camp //先获取主人的阵营与目标阵营进行比较 var canCauseHarm = CampManager.CanCauseHarm(CampManager.GetCamp(ownerCharacterTemplate.CampId), CampManager.GetCamp(characterTemplate.CampId)); return canCauseHarm; } /// /// Executive injury treatment /// 执行伤害处理 /// /// /// private void DoDamage(Node2D? owner, Node2D target) { if (target is not CharacterTemplate characterTemplate) { return; } //Allow damage to be caused //允许造成伤害 var damage = new Damage(); damage.Attacker = owner; damage.MaxDamage = MaxDamage; damage.MinDamage = MinDamage; damage.CreateDamage(); damage.MoveLeft = Velocity.X < 0; damage.Type = DamageType; characterTemplate.Damage(damage); if (KnockbackForce != Vector2.Zero) { //If we set the attack force, then apply the force to the object //如果我们设置了攻退力,那么将力应用到对象上 var force = new Vector2(); var forceX = Math.Abs(KnockbackForce.X); if (Velocity.X < 0) { //Beat back to port //向左击退 forceX = -forceX; } force.X = forceX * Config.CellSize; force.Y = KnockbackForce.Y * Config.CellSize; characterTemplate.AddForce(force); } } /// /// When the bullet is in contact with the node /// 当子弹与节点接触时 /// /// protected virtual void OnBodyEnter(Node2D node) { //Here we test whether harm is allowed, notice that for TileMap, we directly allow harm. //这里我们检测是否允许造成伤害,注意对于TileMap,我们直接允许造成伤害。 var canCauseHarm = CanCauseHarm(Owner, node); if (!canCauseHarm) { return; } DoDamage(Owner, node); //Please specify in the Mask who the bullet will collide with //请在Mask内配置子弹会和谁碰撞 //When a bullet hits an object, its durability decreases //子弹撞击到物体时,耐久度减少 Durability--; if (Durability <= 0) { //When the durability is less than or equal to 0, destroy the bullet //当耐久度小于等于0时,销毁子弹 QueueFree(); } } /// /// When the bullet leaves the node /// 当子弹离开节点时 /// /// protected virtual void OnBodyExited(Node2D node) { } /// /// When beyond the time of existence /// 当超过存在时间 /// private void OnTimeOut() { QueueFree(); } public override void _PhysicsProcess(double delta) { MoveAndSlide(); } }