Allows players to reload projectiles on their weapons.
允许玩家对武器装填抛射体了。
This commit is contained in:
parent
8a7a9bcf5d
commit
839d60b62a
|
@ -113,4 +113,4 @@ log_enter_the_screen,进入屏幕。,Enter screen,画面に移動。
|
||||||
log_exit_the_screen,退出屏幕。,Exit screen,画面を終了します。
|
log_exit_the_screen,退出屏幕。,Exit screen,画面を終了します。
|
||||||
log_failed_to_create_room_preview,创建{0}的房间预览图失败。,Failed to create a room preview of the {0}.,{0}の部屋のプレビューを作成できませんでした。
|
log_failed_to_create_room_preview,创建{0}的房间预览图失败。,Failed to create a room preview of the {0}.,{0}の部屋のプレビューを作成できませんでした。
|
||||||
log_generated_item_is_empty,生成的物品{0}是空的吗{1}。,Generated item {0} is empty {1}.,生成したアイテム{0}は空ですか{1}。
|
log_generated_item_is_empty,生成的物品{0}是空的吗{1}。,Generated item {0} is empty {1}.,生成したアイテム{0}は空ですか{1}。
|
||||||
log_magics_is_null,法术列表是空的。,The spell list is empty.,スペルリストは空です。
|
log_projectile_generate_magic_is_null,没有装填可提供抛射体的法术。,There is no reload spell that provides projectiles.,射出体を提供するスペルを装填していません。
|
|
|
@ -1,6 +1,6 @@
|
||||||
[gd_scene load_steps=6 format=3 uid="uid://crthy8a50a4t"]
|
[gd_scene load_steps=6 format=3 uid="uid://crthy8a50a4t"]
|
||||||
|
|
||||||
[ext_resource type="Script" path="res://scripts/pickable/MagicPickAble.cs" id="1_5mane"]
|
[ext_resource type="Script" path="res://scripts/spell/SpellPickAble.cs" id="1_v0grp"]
|
||||||
[ext_resource type="AudioStream" uid="uid://cak6chjjsu7wo" path="res://sounds/fire.wav" id="4_ffr2k"]
|
[ext_resource type="AudioStream" uid="uid://cak6chjjsu7wo" path="res://sounds/fire.wav" id="4_ffr2k"]
|
||||||
[ext_resource type="Texture2D" uid="uid://bbcjkyrsx88av" path="res://sprites/projectile/curseOfTheUndead.png" id="4_y6nkf"]
|
[ext_resource type="Texture2D" uid="uid://bbcjkyrsx88av" path="res://sprites/projectile/curseOfTheUndead.png" id="4_y6nkf"]
|
||||||
|
|
||||||
|
@ -14,8 +14,8 @@ size = Vector2(20, 20.75)
|
||||||
collision_layer = 8
|
collision_layer = 8
|
||||||
collision_mask = 34
|
collision_mask = 34
|
||||||
angular_damp = -1.0
|
angular_damp = -1.0
|
||||||
script = ExtResource("1_5mane")
|
script = ExtResource("1_v0grp")
|
||||||
UniqueIcon = ExtResource("4_y6nkf")
|
_projectilePath = "res://prefab/projectile/curseOfTheUndead.tscn"
|
||||||
|
|
||||||
[node name="DamageArea2D" type="Area2D" parent="."]
|
[node name="DamageArea2D" type="Area2D" parent="."]
|
||||||
collision_layer = 8
|
collision_layer = 8
|
||||||
|
|
|
@ -16,7 +16,7 @@ collision_layer = 8
|
||||||
collision_mask = 34
|
collision_mask = 34
|
||||||
angular_damp = -1.0
|
angular_damp = -1.0
|
||||||
script = ExtResource("1_w8hhv")
|
script = ExtResource("1_w8hhv")
|
||||||
NumberSlots = 5
|
_numberSlots = 5
|
||||||
FiringIntervalAsMillisecond = 300
|
FiringIntervalAsMillisecond = 300
|
||||||
_recoilStrength = 5
|
_recoilStrength = 5
|
||||||
UniqueIcon = ExtResource("3_31iau")
|
UniqueIcon = ExtResource("3_31iau")
|
||||||
|
|
|
@ -118,7 +118,7 @@ visible = false
|
||||||
|
|
||||||
[node name="WeaponContainer" type="Node2D" parent="."]
|
[node name="WeaponContainer" type="Node2D" parent="."]
|
||||||
|
|
||||||
[node name="MagicContainer" type="Node2D" parent="."]
|
[node name="SpellContainer" type="Node2D" parent="."]
|
||||||
|
|
||||||
[node name="PlayerContainer" type="Node2D" parent="."]
|
[node name="PlayerContainer" type="Node2D" parent="."]
|
||||||
|
|
||||||
|
|
|
@ -227,14 +227,14 @@ public static class Config
|
||||||
public const int ProjectileWeapon = 3;
|
public const int ProjectileWeapon = 3;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <para>Magic</para>
|
/// <para>Spell</para>
|
||||||
/// <para>法术</para>
|
/// <para>法术</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
///<para>Type of special item used in Projectile weapons</para>
|
///<para>Type of special item used in Projectile weapons</para>
|
||||||
///<para>用于远程武器内的特殊物品类型</para>
|
///<para>用于远程武器内的特殊物品类型</para>
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public const int Magic = 4;
|
public const int Spell = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -50,10 +50,10 @@ public static class GameSceneDepend
|
||||||
public static Node2D? ProjectileContainer { get; set; }
|
public static Node2D? ProjectileContainer { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <para>MagicContainer</para>
|
/// <para>SpellContainer</para>
|
||||||
/// <para>法术容器</para>
|
/// <para>法术容器</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static Node2D? MagicContainer { get; set; }
|
public static Node2D? SpellContainer { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <para>WeaponContainer</para>
|
/// <para>WeaponContainer</para>
|
||||||
|
|
|
@ -47,8 +47,8 @@ public partial class GameSceneLoader : SceneLoaderTemplate
|
||||||
GameSceneDepend.ProjectileContainer = projectileContainer;
|
GameSceneDepend.ProjectileContainer = projectileContainer;
|
||||||
//Load magic container
|
//Load magic container
|
||||||
//加载魔术容器
|
//加载魔术容器
|
||||||
var magicContainer = GetNode<Node2D>("MagicContainer");
|
var magicContainer = GetNode<Node2D>("SpellContainer");
|
||||||
GameSceneDepend.MagicContainer = magicContainer;
|
GameSceneDepend.SpellContainer = magicContainer;
|
||||||
//Load Packsack container
|
//Load Packsack container
|
||||||
//加载背包容器
|
//加载背包容器
|
||||||
var packsackContainer = GetNode<Node2D>("PacksackContainer");
|
var packsackContainer = GetNode<Node2D>("PacksackContainer");
|
||||||
|
|
|
@ -4,14 +4,14 @@ using Godot;
|
||||||
namespace ColdMint.scripts.projectile;
|
namespace ColdMint.scripts.projectile;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <para>Magic</para>
|
/// <para>Spell</para>
|
||||||
/// <para>法术</para>
|
/// <para>法术</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
///<para>For projectile weapons</para>
|
///<para>For projectile weapons</para>
|
||||||
///<para>用于抛射体武器</para>
|
///<para>用于抛射体武器</para>
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public interface IMagic
|
public interface ISpell
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <para>GetProjectile</para>
|
/// <para>GetProjectile</para>
|
|
@ -1,8 +1,9 @@
|
||||||
|
using ColdMint.scripts.pickable;
|
||||||
using ColdMint.scripts.projectile;
|
using ColdMint.scripts.projectile;
|
||||||
using ColdMint.scripts.weapon;
|
using ColdMint.scripts.weapon;
|
||||||
using Godot;
|
using Godot;
|
||||||
|
|
||||||
namespace ColdMint.scripts.pickable;
|
namespace ColdMint.scripts.spell;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <para>magic</para>
|
/// <para>magic</para>
|
||||||
|
@ -12,8 +13,9 @@ namespace ColdMint.scripts.pickable;
|
||||||
///<para>For projectile weapons</para>
|
///<para>For projectile weapons</para>
|
||||||
///<para>用于抛射体武器</para>
|
///<para>用于抛射体武器</para>
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public partial class MagicPickAble : PickAbleTemplate, IMagic
|
public partial class SpellPickAble : PickAbleTemplate, ISpell
|
||||||
{
|
{
|
||||||
|
[Export]
|
||||||
private string? _projectilePath;
|
private string? _projectilePath;
|
||||||
|
|
||||||
private PackedScene? _projectileScene;
|
private PackedScene? _projectileScene;
|
||||||
|
@ -28,7 +30,7 @@ public partial class MagicPickAble : PickAbleTemplate, IMagic
|
||||||
|
|
||||||
public override int ItemType
|
public override int ItemType
|
||||||
{
|
{
|
||||||
get => Config.ItemType.Magic;
|
get => Config.ItemType.Spell;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PackedScene? GetProjectile()
|
public PackedScene? GetProjectile()
|
|
@ -235,9 +235,9 @@ public static class NodeUtils
|
||||||
return GameSceneDepend.ProjectileContainer;
|
return GameSceneDepend.ProjectileContainer;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GameSceneDepend.MagicContainer != null && childNode is IMagic)
|
if (GameSceneDepend.SpellContainer != null && childNode is ISpell)
|
||||||
{
|
{
|
||||||
return GameSceneDepend.MagicContainer;
|
return GameSceneDepend.SpellContainer;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GameSceneDepend.WeaponContainer != null && childNode is WeaponTemplate)
|
if (GameSceneDepend.WeaponContainer != null && childNode is WeaponTemplate)
|
||||||
|
|
|
@ -3,6 +3,7 @@ using ColdMint.scripts.debug;
|
||||||
using ColdMint.scripts.inventory;
|
using ColdMint.scripts.inventory;
|
||||||
using ColdMint.scripts.map.events;
|
using ColdMint.scripts.map.events;
|
||||||
using ColdMint.scripts.projectile;
|
using ColdMint.scripts.projectile;
|
||||||
|
using ColdMint.scripts.utils;
|
||||||
using Godot;
|
using Godot;
|
||||||
|
|
||||||
namespace ColdMint.scripts.weapon;
|
namespace ColdMint.scripts.weapon;
|
||||||
|
@ -27,9 +28,81 @@ public partial class ProjectileWeapon : WeaponTemplate
|
||||||
/// <para>Number of slots for ranged weapons</para>
|
/// <para>Number of slots for ranged weapons</para>
|
||||||
/// <para>远程武器的槽位数量</para>
|
/// <para>远程武器的槽位数量</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Export] public int NumberSlots { get; set; }
|
[Export]
|
||||||
|
private int _numberSlots;
|
||||||
|
|
||||||
private readonly List<IMagic> _magics = new();
|
/// <summary>
|
||||||
|
/// <para>How many projectiles are generated per fire</para>
|
||||||
|
/// <para>每次开火生成多少个抛射体</para>
|
||||||
|
/// </summary>
|
||||||
|
public int NumberOfProjectiles { get; set; } = 1;
|
||||||
|
|
||||||
|
private readonly List<ISpell> _spells = new();
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Saves the position of a spell with projectile generation</para>
|
||||||
|
/// <para>保存具有抛射体生成能力的法术位置</para>
|
||||||
|
/// </summary>
|
||||||
|
private readonly List<int> _spellProjectileIndexes = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Whether to fire spells in sequence</para>
|
||||||
|
/// <para>是否按顺序发射法术</para>
|
||||||
|
/// </summary>
|
||||||
|
[Export]
|
||||||
|
private bool _fireSequentially;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>The index used the last time a spell was cast</para>
|
||||||
|
/// <para>上次发射法术时采用的索引</para>
|
||||||
|
/// </summary>
|
||||||
|
private int _lastUsedProjectileMagicIndex;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Get next index</para>
|
||||||
|
/// <para>获取下次索引</para>
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
private int GetNextProjectileMagicIndex()
|
||||||
|
{
|
||||||
|
if (_fireSequentially)
|
||||||
|
{
|
||||||
|
_lastUsedProjectileMagicIndex++;
|
||||||
|
if (_lastUsedProjectileMagicIndex >= _spellProjectileIndexes.Count)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return _lastUsedProjectileMagicIndex;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return RandomUtils.Instance.Next(0, _spellProjectileIndexes.Count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Gets the loading range of the spell</para>
|
||||||
|
/// <para>获取法术的加载范围</para>
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
private int[] GetSpellScope()
|
||||||
|
{
|
||||||
|
var index = GetNextProjectileMagicIndex();
|
||||||
|
var endIndex = _spellProjectileIndexes[index];
|
||||||
|
if (index > 0)
|
||||||
|
{
|
||||||
|
//And the previous index can set the starting position.(The starting position is increased by 1 to avoid using spells with projectile generation as starting points.)
|
||||||
|
//还有前面的索引可设定起始位置。(这里起始位置加1是为了避免 具有抛射体生成能力的法术 作为起点。)
|
||||||
|
var startIndex = _spellProjectileIndexes[index - 1] + 1;
|
||||||
|
return [startIndex, endIndex];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return
|
||||||
|
[
|
||||||
|
0, endIndex
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override int ItemType
|
public override int ItemType
|
||||||
{
|
{
|
||||||
|
@ -40,9 +113,8 @@ public partial class ProjectileWeapon : WeaponTemplate
|
||||||
{
|
{
|
||||||
base._Ready();
|
base._Ready();
|
||||||
_marker2D = GetNode<Marker2D>("Marker2D");
|
_marker2D = GetNode<Marker2D>("Marker2D");
|
||||||
SelfItemContainer = new UniversalItemContainer(NumberSlots);
|
SelfItemContainer = new UniversalItemContainer(_numberSlots);
|
||||||
SelfItemContainer.AllowAddingItemByType(Config.ItemType.Magic);
|
SelfItemContainer.AllowAddingItemByType(Config.ItemType.Spell);
|
||||||
SelfItemContainer.ItemDataChangeEvent += OnItemDataChangeEvent;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnItemDataChangeEvent(ItemDataChangeEvent itemDataChangeEvent)
|
private void OnItemDataChangeEvent(ItemDataChangeEvent itemDataChangeEvent)
|
||||||
|
@ -51,7 +123,8 @@ public partial class ProjectileWeapon : WeaponTemplate
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_magics.Clear();
|
_spells.Clear();
|
||||||
|
_spellProjectileIndexes.Clear();
|
||||||
var totalCapacity = SelfItemContainer.GetTotalCapacity();
|
var totalCapacity = SelfItemContainer.GetTotalCapacity();
|
||||||
for (var i = 0; i < totalCapacity; i++)
|
for (var i = 0; i < totalCapacity; i++)
|
||||||
{
|
{
|
||||||
|
@ -60,11 +133,27 @@ public partial class ProjectileWeapon : WeaponTemplate
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (item is not IMagic magic)
|
if (item is not ISpell spell)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
_magics.Add(magic);
|
_spells.Add(spell);
|
||||||
|
var packedScene = spell.GetProjectile();
|
||||||
|
if (packedScene != null)
|
||||||
|
{
|
||||||
|
//Has the ability to generate projectiles.
|
||||||
|
//拥有抛射体生成能力。
|
||||||
|
_spellProjectileIndexes.Add(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void _EnterTree()
|
||||||
|
{
|
||||||
|
base._EnterTree();
|
||||||
|
if (SelfItemContainer != null)
|
||||||
|
{
|
||||||
|
SelfItemContainer.ItemDataChangeEvent += OnItemDataChangeEvent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,10 +185,45 @@ public partial class ProjectileWeapon : WeaponTemplate
|
||||||
LogCat.LogError("projectile_container_is_null");
|
LogCat.LogError("projectile_container_is_null");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (_magics.Count == 0)
|
if (_spellProjectileIndexes.Count == 0)
|
||||||
{
|
{
|
||||||
LogCat.LogError("magics_is_null");
|
LogCat.LogError("projectile_generate_magic_is_null");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
var spellScope = GetSpellScope();
|
||||||
|
//The final spell is a projectile generator.
|
||||||
|
//最后的法术是拥有抛射体生成能力的。
|
||||||
|
var spellProjectile = _spells[spellScope[1]];
|
||||||
|
var packedScene = spellProjectile.GetProjectile();
|
||||||
|
if (packedScene == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (var i = spellScope[0]; i <= spellScope[1]; i++)
|
||||||
|
{
|
||||||
|
var spell = _spells[i];
|
||||||
|
spell.ModifyWeapon(this);
|
||||||
|
}
|
||||||
|
for (var i = 0; i < NumberOfProjectiles; i++)
|
||||||
|
{
|
||||||
|
var projectile = NodeUtils.InstantiatePackedScene<Projectile>(packedScene);
|
||||||
|
if (projectile == null) return;
|
||||||
|
for (var s = spellScope[0]; s <= spellScope[1]; s++)
|
||||||
|
{
|
||||||
|
var spell = _spells[s];
|
||||||
|
spell.ModifyProjectile(projectile);
|
||||||
|
}
|
||||||
|
NodeUtils.CallDeferredAddChild(GameSceneDepend.ProjectileContainer, projectile);
|
||||||
|
projectile.Owner = owner;
|
||||||
|
projectile.TargetNode = GameSceneDepend.TemporaryTargetNode;
|
||||||
|
projectile.Velocity =
|
||||||
|
_marker2D.GlobalPosition.DirectionTo(enemyGlobalPosition) * projectile.Speed;
|
||||||
|
projectile.Position = _marker2D.GlobalPosition;
|
||||||
|
}
|
||||||
|
for (var i = spellScope[0]; i <= spellScope[1]; i++)
|
||||||
|
{
|
||||||
|
var spell = _spells[i];
|
||||||
|
spell.RestoreWeapon(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user