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 LoadResource()
{
base.LoadResource();
_audioStreamPlayer2D = GetNode("Marker2D/AudioStreamPlayer2D");
}
public override bool Use(Node2D? owner, Vector2 targetGlobalPosition)
{
return 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 long _recoilStrength;
///
/// Discharge of the weapon
/// 武器开火
///
///
///
///owner
///武器所有者
///
///
///enemyGlobalPosition
///敌人所在位置
///
///
public bool 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 false;
}
_lastFiringTime = nowTime;
var result = DoFire(owner, enemyGlobalPosition);
if (result)
{
if (owner is CharacterTemplate characterTemplate)
{
if (_recoilStrength != 0)
{
characterTemplate.AddForce(enemyGlobalPosition.DirectionTo(characterTemplate.GlobalPosition) * _recoilStrength * Config.CellSize);
}
}
_audioStreamPlayer2D?.Play();
}
return result;
}
///
/// Execute fire
/// 执行开火
///
///
///Return Is the fire successful?
///返回是否成功开火?
///
protected abstract bool DoFire(Node2D? owner, Vector2 enemyGlobalPosition);
}