using System;
using ColdMint.scripts.character;
using ColdMint.scripts.pickable;
using Godot;
namespace ColdMint.scripts.weapon;
///
/// WeaponTemplate
/// 武器模板
///
public abstract partial class WeaponTemplate : PickAbleTemplate
{
private float _gravity = ProjectSettings.GetSetting("physics/2d/default_gravity").AsSingle();
///
/// Fire audio playback component
/// 开火音效播放组件
///
private AudioStreamPlayer2D? _audioStreamPlayer2D;
public override void _Ready()
{
base._Ready();
_audioStreamPlayer2D = GetNodeOrNull("Marker2D/AudioStreamPlayer2D");
}
public override void Use(Node2D? owner, Vector2 targetGlobalPosition)
{
Fire(owner, targetGlobalPosition);
}
private DateTime? _lastFiringTime;
///
/// Firing interval
/// 开火间隔
///
private TimeSpan _firingInterval;
private long _firingIntervalAsMillisecond = 100;
[Export] protected long FiringIntervalAsMillisecond
{
get => _firingIntervalAsMillisecond;
set
{
_firingIntervalAsMillisecond = value;
_firingInterval = TimeSpan.FromMilliseconds(_firingIntervalAsMillisecond);
}
}
///
/// 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方向是自动推断的。
///
[Export] private Vector2 _recoil;
///
/// Discharge of the weapon
/// 武器开火
///
///
///
///owner
///武器所有者
///
///
///enemyGlobalPosition
///敌人所在位置
///
///
public void Fire(Node2D? owner, Vector2 enemyGlobalPosition)
{
var nowTime = DateTime.Now;
//If the present time minus the time of the last fire is less than the interval between fires, it means that the fire cannot be fired yet.
//如果现在时间减去上次开火时间小于开火间隔,说明还不能开火。
if (_lastFiringTime != null && nowTime - _lastFiringTime < _firingInterval)
{
return;
}
if (owner is CharacterTemplate characterTemplate)
{
//We check the recoil of the weapon before each firing.
//我们在每次开火之前,检查武器的后坐力。
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);
}
}
_audioStreamPlayer2D?.Play();
DoFire(owner, enemyGlobalPosition);
_lastFiringTime = nowTime;
}
///
/// Execute fire
/// 执行开火
///
protected abstract void DoFire(Node2D? owner, Vector2 enemyGlobalPosition);
}