118 lines
3.8 KiB
C#
118 lines
3.8 KiB
C#
using System;
|
||
using ColdMint.scripts.character;
|
||
using ColdMint.scripts.pickable;
|
||
using Godot;
|
||
|
||
namespace ColdMint.scripts.weapon;
|
||
|
||
/// <summary>
|
||
/// <para>WeaponTemplate</para>
|
||
/// <para>武器模板</para>
|
||
/// </summary>
|
||
public abstract partial class WeaponTemplate : PickAbleTemplate
|
||
{
|
||
private float _gravity = ProjectSettings.GetSetting("physics/2d/default_gravity").AsSingle();
|
||
|
||
/// <summary>
|
||
/// <para>Fire audio playback component</para>
|
||
/// <para>开火音效播放组件</para>
|
||
/// </summary>
|
||
private AudioStreamPlayer2D? _audioStreamPlayer2D;
|
||
|
||
public override void _Ready()
|
||
{
|
||
base._Ready();
|
||
_audioStreamPlayer2D = GetNodeOrNull<AudioStreamPlayer2D>("Marker2D/AudioStreamPlayer2D");
|
||
}
|
||
|
||
public override void Use(Node2D? owner, Vector2 targetGlobalPosition)
|
||
{
|
||
Fire(owner, targetGlobalPosition);
|
||
}
|
||
|
||
|
||
private DateTime? _lastFiringTime;
|
||
|
||
/// <summary>
|
||
/// <para>Firing interval</para>
|
||
/// <para>开火间隔</para>
|
||
/// </summary>
|
||
private TimeSpan _firingInterval;
|
||
private long _firingIntervalAsMillisecond = 100;
|
||
[Export] protected long FiringIntervalAsMillisecond
|
||
{
|
||
get => _firingIntervalAsMillisecond;
|
||
set
|
||
{
|
||
_firingIntervalAsMillisecond = value;
|
||
_firingInterval = TimeSpan.FromMilliseconds(_firingIntervalAsMillisecond);
|
||
}
|
||
}
|
||
|
||
|
||
/// <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>
|
||
[Export] private Vector2 _recoil;
|
||
|
||
/// <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>
|
||
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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// <para>Execute fire</para>
|
||
/// <para>执行开火</para>
|
||
/// </summary>
|
||
protected abstract void DoFire(Node2D? owner, Vector2 enemyGlobalPosition);
|
||
} |