Fixed an issue where items on the ground still carry collision damage.

解决物品在地面上,仍然带有碰撞伤害的问题。
This commit is contained in:
Cold-Mint 2024-06-11 22:16:10 +08:00
parent 63a56cbb2c
commit 7805a63174
Signed by: Cold-Mint
GPG Key ID: C5A9BF8A98E0CE99
5 changed files with 160 additions and 103 deletions

View File

@ -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

View File

@ -85,6 +85,12 @@ public static class Config
public const string Aborigines = "Aborigines";
}
/// <summary>
/// <para>The percentage of speed reduced after a thrown item hits an enemy</para>
/// <para>抛出的物品击中敌人后减少的速度百分比</para>
/// </summary>
public const float ThrownItemsHitEnemiesReduceSpeedByPercentage = 0.5f;
/// <summary>
/// <para>How much blood does a heart represent</para>
/// <para>一颗心代表多少血量</para>

View File

@ -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);
}
/// <summary>
@ -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;
}
}
}

View File

@ -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
/// <param name="target"></param>
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);
}
}
}

View File

@ -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<IItem>? OnUse { get; set; }
public Func<IItem, Node>? OnInstantiation { get; set; }
/// <summary>
/// <para>Whether the weapon is currently picked up</para>
/// <para>当前武器是否被捡起了</para>
/// </summary>
public bool Picked { get; set; }
/// <summary>
/// <para>Owner</para>
/// <para>主人</para>
@ -63,16 +71,20 @@ public partial class WeaponTemplate : RigidBody2D, IItem
/// <para>This area represents the collision range of the weapon, and when other nodes enter this area, they will deal damage.</para>
/// <para>这个区域表示武器的碰撞范围,当其他节点进入此区域时,会造成伤害。</para>
/// </summary>
private Area2D? _area2D;
private Area2D? _damageArea2D;
protected RayCast2D? RayCast2D;
/// <summary>
/// <para>The number of tile maps in contact with this weapon</para>
/// <para>与此武器接触的瓦片地图数量</para>
/// </summary>
private int _tileMapNumber;
public override void _Ready()
{
RayCast2D = GetNode<RayCast2D>("RayCast2D");
_area2D = GetNode<Area2D>("Area2D");
_area2D.BodyEntered += OnBodyEnter;
_damageArea2D = GetNode<Area2D>("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);
}
}
}
/// <summary>
/// <para>Use weapons against the enemy</para>
@ -93,50 +126,57 @@ public partial class WeaponTemplate : RigidBody2D, IItem
/// <param name="node"></param>
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;
}
/// <summary>
@ -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);
}
}
}
/// <summary>
/// <para>Discharge of the weapon</para>