using System;
using ColdMint.scripts.camp;
using ColdMint.scripts.character;
using ColdMint.scripts.damage;
using ColdMint.scripts.inventory;
using Godot;
namespace ColdMint.scripts.weapon;
///
/// WeaponTemplate
/// 武器模板
///
public partial class WeaponTemplate : RigidBody2D, IItem
{
public float Gravity = ProjectSettings.GetSetting("physics/2d/default_gravity").AsSingle();
public string? Id { get; set; }
public int Quantity { get; set; }
public int MaxStackQuantity { get; set; }
public Texture2D? Icon { get; set; }
public new string? Name { get; set; }
public string? Description { get; set; }
public Action? OnUse { get; set; }
public Func? OnInstantiation { get; set; }
///
/// Owner
/// 主人
///
public new Node2D? Owner { get; set; }
///
/// Enabled contact injury
/// 启用接触伤害
///
public bool EnableContactInjury;
private int _minContactInjury;
private int _maxContactInjury;
private DateTime? _lastFiringTime;
//开火间隔
private TimeSpan _firingInterval;
///
/// The recoil of the weapon
/// 武器的后坐力
///
///
///When the weapon is fired, how much recoil is applied to the user, in units: the number of cells, and the X direction of the force is automatically inferred.
///武器开火,要对使用者施加多大的后坐力,单位:格数,力的X方向是自动推断的。
///
private Vector2 _recoil;
private Area2D? _area2D;
protected RayCast2D? RayCast2D;
public override void _Ready()
{
RayCast2D = GetNode("RayCast2D");
_area2D = GetNode("Area2D");
_area2D.BodyEntered += OnBodyEnter;
Id = GetMeta("ID", "1").AsString();
Quantity = GetMeta("Quantity", "1").AsInt32();
MaxStackQuantity = GetMeta("MaxStackQuantity", Config.MaxStackQuantity).AsInt32();
Icon = GetMeta("Icon", "").As();
Name = GetMeta("Name", "").AsString();
Description = GetMeta("Description", "").AsString();
_firingInterval = TimeSpan.FromMilliseconds(GetMeta("FiringInterval", "100").AsInt64());
_minContactInjury = GetMeta("MinContactInjury", "1").AsInt32();
_maxContactInjury = GetMeta("MaxContactInjury", "2").AsInt32();
_recoil = GetMeta("Recoil", Vector2.Zero).AsVector2();
}
///
/// Use weapons against the enemy
/// 使用武器砸敌人
///
///
private void OnBodyEnter(Node node)
{
if (!EnableContactInjury)
{
return;
}
if (Owner == null)
{
return;
}
if (Owner is not CharacterTemplate ownerCharacterTemplate)
{
return;
}
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
//如果允许造成伤害
Owner = null;
var damage = new Damage
{
MaxDamage = Math.Abs(_maxContactInjury),
MinDamage = Math.Abs(_minContactInjury)
};
damage.Attacker = ownerCharacterTemplate;
damage.CreateDamage();
damage.MoveLeft = LinearVelocity.X < 0;
damage.Type = Config.DamageType.Physical;
characterTemplate.Damage(damage);
}
///
/// 翻转武器
///
///
public void Flip(bool facingLeft)
{
}
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
/// 武器开火
///
///
///
///owner
///武器所有者
///
///
///enemyGlobalPosition
///敌人所在位置
///
///
public void Fire(Node2D? owner, Vector2 enemyGlobalPosition)
{
var nowTime = DateTime.Now;
if (_lastFiringTime == null || nowTime - _lastFiringTime > _firingInterval)
{
if (owner is CharacterTemplate characterTemplate)
{
//我们在每次开火之前,检查武器的后坐力。
if (_recoil != Vector2.Zero)
{
//假设此武器拥有后坐力
var force = new Vector2();
var forceX = Math.Abs(_recoil.X);
if (Math.Abs(RotationDegrees) < 90)
{
//The weapon goes to the right and we apply a recoil to the left
//武器朝向右边我们向左施加后坐力
forceX = -forceX;
}
force.X = forceX * Config.CellSize;
force.Y = _recoil.Y * Config.CellSize;
characterTemplate.AddForce(force);
}
}
//If the time difference is greater than the firing interval, then fire
//如果可以时间差大于开火间隔,那么开火
DoFire(owner, enemyGlobalPosition);
_lastFiringTime = nowTime;
}
}
///
/// Execute fire
/// 执行开火
///
protected virtual void DoFire(Node2D? owner, Vector2 enemyGlobalPosition)
{
}
}