2024-04-28 13:55:19 +00:00
|
|
|
using ColdMint.scripts.debug;
|
|
|
|
using ColdMint.scripts.projectile;
|
2024-08-03 16:32:49 +00:00
|
|
|
using ColdMint.scripts.projectile.decorator;
|
2024-06-10 13:05:18 +00:00
|
|
|
using ColdMint.scripts.utils;
|
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
|
|
|
|
2024-06-05 13:38:45 +00:00
|
|
|
/// <summary>
|
|
|
|
/// <para>Projectile weapons</para>
|
|
|
|
/// <para>抛射体武器</para>
|
|
|
|
/// </summary>
|
|
|
|
/// <remarks>
|
|
|
|
///<para>These weapons can fire projectiles to attack the enemy.For example: guns and scepters.Generate a bullet to attack the enemy.</para>
|
|
|
|
///<para>这类武器可发射抛射体,攻击敌人。例如:枪支和法杖。生成一个子弹攻击敌人。</para>
|
|
|
|
/// </remarks>
|
2024-04-28 13:55:19 +00:00
|
|
|
public partial class ProjectileWeapon : WeaponTemplate
|
|
|
|
{
|
2024-06-05 13:38:45 +00:00
|
|
|
/// <summary>
|
|
|
|
/// <para>The formation position of the projectile</para>
|
|
|
|
/// <para>抛射体的生成位置</para>
|
|
|
|
/// </summary>
|
2024-05-08 10:22:04 +00:00
|
|
|
private Marker2D? _marker2D;
|
2024-06-10 13:05:18 +00:00
|
|
|
|
2024-08-13 15:07:05 +00:00
|
|
|
/// <summary>
|
|
|
|
/// <para>Scattering radians</para>
|
|
|
|
/// <para>散射弧度</para>
|
|
|
|
/// </summary>
|
|
|
|
[Export] protected float OffsetAngle;
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// <para>The number of projectiles fired at once</para>
|
|
|
|
/// <para>一次可以发射多少个子弹</para>
|
|
|
|
/// </summary>
|
|
|
|
[Export] protected float NumberOfProjectiles = 1;
|
|
|
|
|
2024-06-13 03:14:24 +00:00
|
|
|
[Export] protected PackedScene[] ProjectileScenes { get; set; } = [];
|
2024-06-10 13:05:18 +00:00
|
|
|
|
2024-08-11 15:29:23 +00:00
|
|
|
/// <summary>
|
|
|
|
/// <para>Whether to launch in the order of the projectile list</para>
|
|
|
|
/// <para>是否按照抛射体列表的循序发射</para>
|
|
|
|
/// </summary>
|
|
|
|
[Export]
|
|
|
|
protected bool Sequentially { get; set; }
|
|
|
|
|
|
|
|
private int _projectileIndex;
|
|
|
|
|
2024-05-08 10:22:04 +00:00
|
|
|
public override void _Ready()
|
|
|
|
{
|
|
|
|
base._Ready();
|
|
|
|
_marker2D = GetNode<Marker2D>("Marker2D");
|
|
|
|
}
|
|
|
|
|
2024-08-11 15:29:23 +00:00
|
|
|
/// <summary>
|
|
|
|
/// <para>GetNextProjectileScene</para>
|
|
|
|
/// <para>获取下一个抛射体</para>
|
|
|
|
/// </summary>
|
|
|
|
/// <returns></returns>
|
|
|
|
private PackedScene GetNextProjectileScene()
|
|
|
|
{
|
|
|
|
if (Sequentially)
|
|
|
|
{
|
|
|
|
_projectileIndex = (_projectileIndex + 1) % ProjectileScenes.Length;
|
|
|
|
return ProjectileScenes[_projectileIndex];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return ProjectileScenes[RandomUtils.Instance.Next(ProjectileScenes.Length)];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-13 15:07:05 +00:00
|
|
|
/// <summary>
|
|
|
|
/// <para>GetRandomAngle</para>
|
|
|
|
/// <para>获取随机的偏移弧度</para>
|
|
|
|
/// </summary>
|
|
|
|
/// <returns></returns>
|
|
|
|
private float GetRandomAngle()
|
|
|
|
{
|
|
|
|
if (OffsetAngle == 0)
|
|
|
|
{
|
|
|
|
//If the offset angle is 0, then return 0
|
|
|
|
//弧度为0,不用偏移。
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
var min = -OffsetAngle / 2;
|
|
|
|
return min + RandomUtils.Instance.NextSingle() * OffsetAngle;
|
|
|
|
}
|
|
|
|
|
2024-05-08 10:22:04 +00:00
|
|
|
|
|
|
|
protected override void DoFire(Node2D? owner, Vector2 enemyGlobalPosition)
|
|
|
|
{
|
2024-07-24 13:03:24 +00:00
|
|
|
if (owner == null)
|
|
|
|
{
|
|
|
|
LogCat.LogError("owner_is_null");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_marker2D == null)
|
|
|
|
{
|
|
|
|
LogCat.LogError("marker2d_is_null");
|
|
|
|
return;
|
|
|
|
}
|
2024-06-10 13:05:18 +00:00
|
|
|
|
2024-07-24 13:03:24 +00:00
|
|
|
if (GameSceneNodeHolder.ProjectileContainer == null)
|
|
|
|
{
|
|
|
|
LogCat.LogError("projectile_container_is_null");
|
|
|
|
return;
|
|
|
|
}
|
2024-08-11 15:29:23 +00:00
|
|
|
|
2024-07-24 13:03:24 +00:00
|
|
|
//Empty list check
|
2024-06-13 03:14:24 +00:00
|
|
|
//空列表检查
|
|
|
|
if (ProjectileScenes is [])
|
2024-05-08 10:22:04 +00:00
|
|
|
{
|
2024-06-05 13:38:45 +00:00
|
|
|
LogCat.LogError("projectiles_is_empty");
|
2024-05-08 10:22:04 +00:00
|
|
|
return;
|
|
|
|
}
|
2024-06-10 13:05:18 +00:00
|
|
|
|
2024-05-08 10:22:04 +00:00
|
|
|
//Get the first projectile
|
2024-06-05 13:38:45 +00:00
|
|
|
//获取第一个抛射体
|
2024-08-11 15:29:23 +00:00
|
|
|
var projectileScene = GetNextProjectileScene();
|
2024-08-13 15:07:05 +00:00
|
|
|
for (int i = 0; i < NumberOfProjectiles; i++)
|
2024-08-03 16:32:49 +00:00
|
|
|
{
|
2024-08-13 15:07:05 +00:00
|
|
|
var projectile = NodeUtils.InstantiatePackedScene<Projectile>(projectileScene);
|
|
|
|
if (projectile == null) return;
|
|
|
|
if (Config.IsDebug())
|
2024-08-03 16:32:49 +00:00
|
|
|
{
|
2024-08-13 15:07:05 +00:00
|
|
|
var nodeSpawnOnKillCharacterDecorator = new NodeSpawnOnKillCharacterDecorator
|
|
|
|
{
|
|
|
|
DefaultParentNode = this,
|
|
|
|
PackedScenePath = "res://prefab/entitys/BlackenedAboriginalWarrior.tscn"
|
|
|
|
};
|
|
|
|
projectile.AddProjectileDecorator(nodeSpawnOnKillCharacterDecorator);
|
|
|
|
}
|
2024-08-11 15:29:23 +00:00
|
|
|
|
2024-08-13 15:07:05 +00:00
|
|
|
NodeUtils.CallDeferredAddChild(GameSceneNodeHolder.ProjectileContainer, projectile);
|
|
|
|
projectile.Owner = owner;
|
|
|
|
projectile.Velocity =
|
|
|
|
((enemyGlobalPosition - _marker2D.GlobalPosition).Normalized() * projectile.Speed).Rotated(GetRandomAngle());
|
|
|
|
projectile.Position = _marker2D.GlobalPosition;
|
|
|
|
}
|
2024-05-08 10:22:04 +00:00
|
|
|
}
|
|
|
|
}
|