2024-04-28 13:55:19 +00:00
using System ;
using ColdMint.scripts.character ;
2024-06-16 07:28:16 +00:00
using ColdMint.scripts.pickable ;
2024-04-28 13:55:19 +00:00
using Godot ;
2024-06-22 11:21:06 +00:00
namespace ColdMint.scripts.weapon ;
2024-04-28 13:55:19 +00:00
/// <summary>
/// <para>WeaponTemplate</para>
/// <para>武器模板</para>
/// </summary>
2024-06-16 07:28:16 +00:00
public abstract partial class WeaponTemplate : PickAbleTemplate
2024-04-28 13:55:19 +00:00
{
2024-06-05 13:38:45 +00:00
private float _gravity = ProjectSettings . GetSetting ( "physics/2d/default_gravity" ) . AsSingle ( ) ;
2024-06-16 10:35:00 +00:00
2024-07-28 09:53:54 +00:00
/// <summary>
/// <para>Fire audio playback component</para>
/// <para>开火音效播放组件</para>
/// </summary>
private AudioStreamPlayer2D ? _audioStreamPlayer2D ;
2024-09-01 14:25:20 +00:00
2024-07-28 09:53:54 +00:00
public override void _Ready ( )
{
base . _Ready ( ) ;
_audioStreamPlayer2D = GetNodeOrNull < AudioStreamPlayer2D > ( "Marker2D/AudioStreamPlayer2D" ) ;
}
2024-06-16 07:28:16 +00:00
public override void Use ( Node2D ? owner , Vector2 targetGlobalPosition )
2024-06-11 17:57:55 +00:00
{
Fire ( owner , targetGlobalPosition ) ;
}
2024-04-28 13:55:19 +00:00
private DateTime ? _lastFiringTime ;
2024-06-05 13:38:45 +00:00
/// <summary>
/// <para>Firing interval</para>
/// <para>开火间隔</para>
/// </summary>
2024-04-28 13:55:19 +00:00
private TimeSpan _firingInterval ;
2024-09-01 14:25:20 +00:00
2024-06-15 09:16:41 +00:00
private long _firingIntervalAsMillisecond = 100 ;
2024-09-01 14:25:20 +00:00
[Export]
protected long FiringIntervalAsMillisecond
2024-06-15 09:16:41 +00:00
{
get = > _firingIntervalAsMillisecond ;
set
{
_firingIntervalAsMillisecond = value ;
_firingInterval = TimeSpan . FromMilliseconds ( _firingIntervalAsMillisecond ) ;
}
}
2024-04-29 15:25:03 +00:00
2024-04-28 13:55:19 +00:00
/// <summary>
/// <para>The recoil of the weapon</para>
/// <para>武器的后坐力</para>
/// </summary>
/// <remarks>
///<para>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.</para>
///<para>武器开火, 要对使用者施加多大的后坐力, 单位: 格数, 力的X方向是自动推断的。</para>
/// </remarks>
2024-09-01 14:25:20 +00:00
[Export] private long _recoilStrength ;
2024-04-28 13:55:19 +00:00
/// <summary>
/// <para>Discharge of the weapon</para>
/// <para>武器开火</para>
/// </summary>
/// <remarks>
///<param name="owner">
///<para>owner</para>
///<para>武器所有者</para>
/// </param>
/// <param name="enemyGlobalPosition">
///<para>enemyGlobalPosition</para>
///<para>敌人所在位置</para>
/// </param>
/// </remarks>
2024-05-08 10:22:04 +00:00
public void Fire ( Node2D ? owner , Vector2 enemyGlobalPosition )
2024-04-28 13:55:19 +00:00
{
var nowTime = DateTime . Now ;
2024-06-04 14:23:06 +00:00
//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 )
2024-04-28 13:55:19 +00:00
{
2024-06-04 14:23:06 +00:00
return ;
}
2024-10-05 02:53:07 +00:00
var result = DoFire ( owner , enemyGlobalPosition ) ;
if ( result )
2024-06-04 14:23:06 +00:00
{
2024-10-05 02:53:07 +00:00
if ( owner is CharacterTemplate characterTemplate )
2024-04-28 13:55:19 +00:00
{
2024-10-05 02:53:07 +00:00
if ( _recoilStrength ! = 0 )
{
characterTemplate . AddForce ( enemyGlobalPosition . DirectionTo ( characterTemplate . GlobalPosition ) * _recoilStrength * Config . CellSize ) ;
}
2024-06-04 14:23:06 +00:00
}
2024-10-05 02:53:07 +00:00
_audioStreamPlayer2D ? . Play ( ) ;
}
2024-06-04 14:23:06 +00:00
_lastFiringTime = nowTime ;
2024-04-28 13:55:19 +00:00
}
/// <summary>
/// <para>Execute fire</para>
/// <para>执行开火</para>
/// </summary>
2024-10-05 02:53:07 +00:00
/// <returns>
///<para>Return Is the fire successful?</para>
///<para>返回是否成功开火?</para>
/// </returns>
protected abstract bool DoFire ( Node2D ? owner , Vector2 enemyGlobalPosition ) ;
2024-04-28 13:55:19 +00:00
}