From 7805a6317429088149aa8ec25abcfd919717b87c Mon Sep 17 00:00:00 2001 From: Cold-Mint Date: Tue, 11 Jun 2024 22:16:10 +0800 Subject: [PATCH] =?UTF-8?q?Fixed=20an=20issue=20where=20items=20on=20the?= =?UTF-8?q?=20ground=20still=20carry=20collision=20damage.=20=E8=A7=A3?= =?UTF-8?q?=E5=86=B3=E7=89=A9=E5=93=81=E5=9C=A8=E5=9C=B0=E9=9D=A2=E4=B8=8A?= =?UTF-8?q?=EF=BC=8C=E4=BB=8D=E7=84=B6=E5=B8=A6=E6=9C=89=E7=A2=B0=E6=92=9E?= =?UTF-8?q?=E4=BC=A4=E5=AE=B3=E7=9A=84=E9=97=AE=E9=A2=98=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- prefab/weapons/staffOfTheUndead.tscn | 11 +- scripts/Config.cs | 6 + scripts/character/CharacterTemplate.cs | 14 ++- scripts/projectile/ProjectileTemplate.cs | 89 +++++++++----- scripts/weapon/WeaponTemplate.cs | 143 +++++++++++++---------- 5 files changed, 160 insertions(+), 103 deletions(-) diff --git a/prefab/weapons/staffOfTheUndead.tscn b/prefab/weapons/staffOfTheUndead.tscn index 955820c..91488d1 100644 --- a/prefab/weapons/staffOfTheUndead.tscn +++ b/prefab/weapons/staffOfTheUndead.tscn @@ -22,11 +22,11 @@ metadata/ID = "StaffOfTheUndead" metadata/MaxStackQuantity = 1 metadata/Description = "staff_of_the_undead_desc" -[node name="Area2D" type="Area2D" parent="."] +[node name="DamageArea2D" type="Area2D" parent="."] collision_layer = 8 -collision_mask = 68 +collision_mask = 71 -[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2D"] +[node name="CollisionShape2D" type="CollisionShape2D" parent="DamageArea2D"] position = Vector2(25.5, 0.5) shape = SubResource("RectangleShape2D_obcq2") @@ -40,8 +40,3 @@ shape = SubResource("RectangleShape2D_14m1g") [node name="Marker2D" type="Marker2D" parent="."] position = Vector2(65, 0) - -[node name="RayCast2D" type="RayCast2D" parent="."] -position = Vector2(26, -8) -target_position = Vector2(0, 20) -collision_mask = 34 diff --git a/scripts/Config.cs b/scripts/Config.cs index 8e8d35e..5263cc5 100644 --- a/scripts/Config.cs +++ b/scripts/Config.cs @@ -85,6 +85,12 @@ public static class Config public const string Aborigines = "Aborigines"; } + /// + /// The percentage of speed reduced after a thrown item hits an enemy + /// 抛出的物品击中敌人后减少的速度百分比 + /// + public const float ThrownItemsHitEnemiesReduceSpeedByPercentage = 0.5f; + /// /// How much blood does a heart represent /// 一颗心代表多少血量 diff --git a/scripts/character/CharacterTemplate.cs b/scripts/character/CharacterTemplate.cs index 135df43..b1930d4 100644 --- a/scripts/character/CharacterTemplate.cs +++ b/scripts/character/CharacterTemplate.cs @@ -318,6 +318,7 @@ public partial class CharacterTemplate : CharacterBody2D if (pickAbleItem is WeaponTemplate weaponTemplate) { weaponTemplate.Owner = this; + weaponTemplate.Picked = true; weaponTemplate.SetCollisionMaskValue(Config.LayerNumber.Platform, false); weaponTemplate.SetCollisionMaskValue(Config.LayerNumber.Ground, false); weaponTemplate.EnableContactInjury = false; @@ -479,7 +480,7 @@ public partial class CharacterTemplate : CharacterBody2D var finalGlobalPosition = GlobalPosition; - CallDeferred("GenerateLootObjects", this,lootDataArray, finalGlobalPosition); + CallDeferred("GenerateLootObjects", this, lootDataArray, finalGlobalPosition); } /// @@ -669,6 +670,7 @@ public partial class CharacterTemplate : CharacterBody2D return; } + weaponTemplate.Picked = false; CallDeferred("WeaponTemplateReparent", weaponTemplate); var timer = new Timer(); weaponTemplate.AddChild(timer); @@ -770,5 +772,15 @@ public partial class CharacterTemplate : CharacterBody2D protected virtual void HookPhysicsProcess(ref Vector2 velocity, double delta) { + //The cost of applying force in the X direction. + //对X方向施加力消耗。 + if ((int)velocity.X == 0) + { + velocity.X = 0; + } + else + { + velocity.X *= 0.95f; + } } } \ No newline at end of file diff --git a/scripts/projectile/ProjectileTemplate.cs b/scripts/projectile/ProjectileTemplate.cs index 0d9a8f9..8d8b4f5 100644 --- a/scripts/projectile/ProjectileTemplate.cs +++ b/scripts/projectile/ProjectileTemplate.cs @@ -2,6 +2,7 @@ using System; using ColdMint.scripts.camp; using ColdMint.scripts.character; using ColdMint.scripts.damage; +using ColdMint.scripts.weapon; using Godot; namespace ColdMint.scripts.projectile; @@ -105,8 +106,15 @@ public partial class ProjectileTemplate : CharacterBody2D if (target is TileMap) { - //When we hit the tile, we return true in order to place the bullet through the tile. - //撞击到瓦片时,我们返回true,是为了放置子弹穿透瓦片。 + //When we hit the tile, we return true to prevent the bullet from penetrating the tile. + //撞击到瓦片时,我们返回true,是为了防止子弹穿透瓦片。 + return true; + } + + if (target is WeaponTemplate) + { + //Bullets are allowed to strike objects. + //允许子弹撞击物品。 return true; } @@ -130,39 +138,56 @@ public partial class ProjectileTemplate : CharacterBody2D /// private void DoDamage(Node2D? owner, Node2D target) { - if (target is not CharacterTemplate characterTemplate) + if (target is CharacterTemplate characterTemplate) { - return; - } - - //Allow damage to be caused - //允许造成伤害 - var damage = new Damage - { - Attacker = owner, - MaxDamage = MaxDamage, - 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) + //Allow damage to be caused + //允许造成伤害 + var damage = new Damage { - //Beat back to port - //向左击退 - forceX = -forceX; - } + Attacker = owner, + MaxDamage = MaxDamage, + 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); + force.X = forceX * Config.CellSize; + force.Y = KnockbackForce.Y * Config.CellSize; + characterTemplate.AddForce(force); + } + }else if (target is WeaponTemplate weaponTemplate) + { + 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; + weaponTemplate.ApplyImpulse(force); + } } } diff --git a/scripts/weapon/WeaponTemplate.cs b/scripts/weapon/WeaponTemplate.cs index c3c27be..0a713fa 100644 --- a/scripts/weapon/WeaponTemplate.cs +++ b/scripts/weapon/WeaponTemplate.cs @@ -2,6 +2,7 @@ using System; using ColdMint.scripts.camp; using ColdMint.scripts.character; using ColdMint.scripts.damage; +using ColdMint.scripts.debug; using ColdMint.scripts.inventory; using Godot; @@ -24,6 +25,13 @@ public partial class WeaponTemplate : RigidBody2D, IItem public Action? OnUse { get; set; } public Func? OnInstantiation { get; set; } + + /// + /// Whether the weapon is currently picked up + /// 当前武器是否被捡起了 + /// + public bool Picked { get; set; } + /// /// Owner /// 主人 @@ -63,16 +71,20 @@ public partial class WeaponTemplate : RigidBody2D, IItem /// This area represents the collision range of the weapon, and when other nodes enter this area, they will deal damage. /// 这个区域表示武器的碰撞范围,当其他节点进入此区域时,会造成伤害。 /// - private Area2D? _area2D; + private Area2D? _damageArea2D; - protected RayCast2D? RayCast2D; + /// + /// The number of tile maps in contact with this weapon + /// 与此武器接触的瓦片地图数量 + /// + private int _tileMapNumber; public override void _Ready() { - RayCast2D = GetNode("RayCast2D"); - _area2D = GetNode("Area2D"); - _area2D.BodyEntered += OnBodyEnter; + _damageArea2D = GetNode("DamageArea2D"); + _damageArea2D.BodyEntered += OnBodyEnter; + _damageArea2D.BodyExited += OnBodyExited; Id = GetMeta("ID", "1").AsString(); Quantity = GetMeta("Quantity", "1").AsInt32(); MaxStackQuantity = GetMeta("MaxStackQuantity", Config.MaxStackQuantity).AsInt32(); @@ -85,6 +97,27 @@ public partial class WeaponTemplate : RigidBody2D, IItem _recoil = GetMeta("Recoil", Vector2.Zero).AsVector2(); } + private void OnBodyExited(Node node) + { + if (Picked) + { + return; + } + + //If it leaves the ground or walls. + //如果离开了地面或墙壁。 + if (node is TileMap tileMap) + { + _tileMapNumber--; + if (_tileMapNumber == 0) + { + //No longer in contact with any shingles can cause injury + //不再与任何瓦片接触后,可以造成伤害 + EnableContactInjury = true; + SetCollisionMaskValue(Config.LayerNumber.Player, false); + } + } + } /// /// Use weapons against the enemy @@ -93,50 +126,57 @@ public partial class WeaponTemplate : RigidBody2D, IItem /// private void OnBodyEnter(Node node) { - if (!EnableContactInjury) + if (Picked) { return; } - if (Owner == null) + if (node is TileMap tileMap) { - return; + _tileMapNumber++; + EnableContactInjury = false; + //Items can be pushed by the player when they are on the ground + //当物品在地面上时,可被玩家推动 + SetCollisionMaskValue(Config.LayerNumber.Player, true); } - - if (Owner is not CharacterTemplate ownerCharacterTemplate) + else if (node is CharacterTemplate characterTemplate) { - return; + if (!EnableContactInjury) + { + return; + } + + + if (Owner is not CharacterTemplate ownerCharacterTemplate) + { + return; + } + + //Determine if your side can cause damage + //判断所属的阵营是否可以造成伤害 + var canCauseHarm = CampManager.CanCauseHarm(CampManager.GetCamp(ownerCharacterTemplate.CampId), + CampManager.GetCamp(characterTemplate.CampId)); + if (!canCauseHarm) + { + return; + } + + //If allowed to cause harm + //如果允许造成伤害 + var damage = new Damage + { + MaxDamage = Math.Abs(_maxContactInjury), + MinDamage = Math.Abs(_minContactInjury), + Attacker = ownerCharacterTemplate + }; + damage.CreateDamage(); + damage.MoveLeft = LinearVelocity.X < 0; + damage.Type = Config.DamageType.Physical; + characterTemplate.Damage(damage); + //Reduce speed after hitting enemies. + //击中敌人后减少速度。 + LinearVelocity *= 1 - Config.ThrownItemsHitEnemiesReduceSpeedByPercentage; } - - if (node is not CharacterTemplate characterTemplate) - { - return; - } - - //Determine if your side can cause damage - //判断所属的阵营是否可以造成伤害 - var canCauseHarm = CampManager.CanCauseHarm(CampManager.GetCamp(ownerCharacterTemplate.CampId), - CampManager.GetCamp(characterTemplate.CampId)); - if (!canCauseHarm) - { - return; - } - - //If allowed to cause harm - //如果允许造成伤害 - var damage = new Damage - { - MaxDamage = Math.Abs(_maxContactInjury), - MinDamage = Math.Abs(_minContactInjury), - Attacker = ownerCharacterTemplate - }; - damage.CreateDamage(); - damage.MoveLeft = LinearVelocity.X < 0; - damage.Type = Config.DamageType.Physical; - characterTemplate.Damage(damage); - //Can only cause one collision damage. - //仅能造成一次碰撞伤害。 - EnableContactInjury = false; } /// @@ -147,27 +187,6 @@ public partial class WeaponTemplate : RigidBody2D, IItem { } - public override void _PhysicsProcess(double delta) - { - base._PhysicsProcess(delta); - if (RayCast2D != null) - { - if (RayCast2D.IsColliding()) - { - //If the weapon hits the ground, we disable physical damage. - //如果武器落到地面了,我们禁用物理伤害。 - EnableContactInjury = false; - //Items can be pushed by the player when they are on the ground - //当物品在地面上时,可被玩家推动 - SetCollisionMaskValue(Config.LayerNumber.Player, true); - } - else - { - SetCollisionMaskValue(Config.LayerNumber.Player, false); - } - } - } - /// /// Discharge of the weapon