Now supports spawning spell items.

支持生成法术物品了。
This commit is contained in:
Cold-Mint 2024-10-04 20:53:34 +08:00
parent 124c6ce0ba
commit 8a7a9bcf5d
Signed by: Cold-Mint
GPG Key ID: C5A9BF8A98E0CE99
15 changed files with 211 additions and 34 deletions

10
data/itemRegs/magics.yaml Normal file
View File

@ -0,0 +1,10 @@
#Register spells used by the projectile here.
#在这里注册抛射体使用的法术。
#Note: The id must be the same as the item id in the scene. Otherwise, an ArgumentException will be thrown.
#备注id必须和场景内的物品id保持一致。否则会抛出ArgumentException。
#After you declare the id of the item, add the corresponding localized text to the csv file in the locals' folder. For example, if the id is a corresponding name is item_a and the corresponding description is item_a_desc.
#当您声明物品的id后请在locals文件夹中的csv文件中添加相应的本地化文本。例如id为a则对应的名称为item_a对应的描述为item_a_desc。
- id: necromancy
scene_path: res://prefab/magics/curseOfTheUndead.tscn
icon_path: res://sprites/projectile/curseOfTheUndead.png
max_stack_value: 1

View File

@ -2,4 +2,6 @@ id,zh,en,ja
item_staff_necromancy,死灵法杖,staffNecromancy,ネクロポリスの杖です
item_staff_necromancy_desc,发射诅咒,可将敌人转化为邪恶的怪物。,Cast a curse that transforms enemies into evil monsters.,呪いを発射して、敵を邪悪な怪物に変えることができます。
item_portable_backpacks,便携式背包,PortableBackpacks,ポータブルバックパック
item_portable_backpacks_desc,为玩家提供9个物品槽。,Provides 9 item slots for the player.,プレイヤーに9つのアイテムスロットを提供します。
item_portable_backpacks_desc,为玩家提供9个物品槽。,Provides 9 item slots for the player.,プレイヤーに9つのアイテムスロットを提供します。
item_necromancy,死灵法术,necromancy,ネクロマンシー
item_necromancy_desc,法术的实体化弹丸。,The materialized projectile of a spell.,術の実体化した弾丸です。
1 id zh en ja
2 item_staff_necromancy 死灵法杖 staffNecromancy ネクロポリスの杖です
3 item_staff_necromancy_desc 发射诅咒,可将敌人转化为邪恶的怪物。 Cast a curse that transforms enemies into evil monsters. 呪いを発射して、敵を邪悪な怪物に変えることができます。
4 item_portable_backpacks 便携式背包 PortableBackpacks ポータブルバックパック
5 item_portable_backpacks_desc 为玩家提供9个物品槽。 Provides 9 item slots for the player. プレイヤーに9つのアイテムスロットを提供します。
6 item_necromancy 死灵法术 necromancy ネクロマンシー
7 item_necromancy_desc 法术的实体化弹丸。 The materialized projectile of a spell. 術の実体化した弾丸です。

View File

@ -111,4 +111,6 @@ log_hide_all_node,隐藏{0}个节点。,Hide {0} nodes.,{0}ノードを非表示
log_show_all_node,显示{0}个节点。,Show {0} nodes.,{0}ノードが表示されます。
log_enter_the_screen,进入屏幕。,Enter 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_magics_is_null,法术列表是空的。,The spell list is empty.,スペルリストは空です。
1 id zh en ja
111 log_show_all_node 显示{0}个节点。 Show {0} nodes. {0}ノードが表示されます。
112 log_enter_the_screen 进入屏幕。 Enter screen 画面に移動。
113 log_exit_the_screen 退出屏幕。 Exit screen 画面を終了します。
114 log_failed_to_create_room_preview 创建{0}的房间预览图失败。 Failed to create a room preview of the {0}. {0}の部屋のプレビューを作成できませんでした。
115 log_generated_item_is_empty 生成的物品{0}是空的吗{1}。 Generated item {0} is empty {1}. 生成したアイテム{0}は空ですか{1}。
116 log_magics_is_null 法术列表是空的。 The spell list is empty. スペルリストは空です。

View File

@ -0,0 +1,46 @@
[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="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"]
[sub_resource type="RectangleShape2D" id="RectangleShape2D_obcq2"]
size = Vector2(20, 21)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_14m1g"]
size = Vector2(20, 20.75)
[node name="curseOfTheUndead" type="RigidBody2D"]
collision_layer = 8
collision_mask = 34
angular_damp = -1.0
script = ExtResource("1_5mane")
UniqueIcon = ExtResource("4_y6nkf")
[node name="DamageArea2D" type="Area2D" parent="."]
collision_layer = 8
collision_mask = 102
[node name="CollisionShape2D" type="CollisionShape2D" parent="DamageArea2D"]
position = Vector2(0, -0.5)
shape = SubResource("RectangleShape2D_obcq2")
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
position = Vector2(0, -0.625)
shape = SubResource("RectangleShape2D_14m1g")
[node name="Marker2D" type="Marker2D" parent="."]
position = Vector2(65, 0)
[node name="AudioStreamPlayer2D" type="AudioStreamPlayer2D" parent="Marker2D"]
stream = ExtResource("4_ffr2k")
bus = &"SoundEffect"
[node name="TipLabel" type="Label" parent="."]
offset_left = -19.0
offset_top = 23.0
offset_right = 21.0
offset_bottom = 48.0
[node name="CurseOfTheUndead" type="Sprite2D" parent="."]
texture = ExtResource("4_y6nkf")

View File

@ -1,11 +1,10 @@
[gd_scene load_steps=10 format=4 uid="uid://du5ldsp613fei"]
[gd_scene load_steps=9 format=4 uid="uid://du5ldsp613fei"]
[ext_resource type="TileSet" uid="uid://c4wpp12rr44hi" path="res://tileSets/dungeon.tres" id="1_rn2om"]
[ext_resource type="Script" path="res://scripts/map/PlayerSpawn.cs" id="2_6p8mv"]
[ext_resource type="Script" path="res://scripts/map/ItemSpawn.cs" id="3_v1tlc"]
[ext_resource type="Texture2D" uid="uid://drw45jlmfo0su" path="res://sprites/light/White_100.png" id="5_4pssd"]
[ext_resource type="PackedScene" uid="uid://djsh4unystlf0" path="res://prefab/furnitures/SpellEditor.tscn" id="5_7c8bh"]
[ext_resource type="PackedScene" uid="uid://bq5d2w22wnxrf" path="res://prefab/packsacks/PortableBackpacks.tscn" id="6_0iot7"]
[sub_resource type="RectangleShape2D" id="RectangleShape2D_kiih8"]
size = Vector2(507, 251)
@ -46,6 +45,11 @@ position = Vector2(142, 84)
script = ExtResource("3_v1tlc")
ItemId = "staff_necromancy"
[node name="ItemMarker2D2" type="Marker2D" parent="."]
position = Vector2(321, 118)
script = ExtResource("3_v1tlc")
ItemId = "necromancy"
[node name="NavigationRegion2D" type="NavigationRegion2D" parent="."]
navigation_polygon = SubResource("NavigationPolygon_064c7")
@ -81,9 +85,3 @@ texture = ExtResource("5_4pssd")
[node name="RigidBody2D" parent="." instance=ExtResource("5_7c8bh")]
position = Vector2(149, 109)
collision_mask = 0
[node name="RigidBody2D2" parent="." instance=ExtResource("6_0iot7")]
position = Vector2(338, 115)
[node name="RigidBody2D3" parent="." instance=ExtResource("6_0iot7")]
position = Vector2(206, 123)

View File

@ -118,6 +118,8 @@ visible = false
[node name="WeaponContainer" type="Node2D" parent="."]
[node name="MagicContainer" type="Node2D" parent="."]
[node name="PlayerContainer" type="Node2D" parent="."]
[node name="AICharacterContainer" type="Node2D" parent="."]

View File

@ -48,6 +48,12 @@ public static class GameSceneDepend
/// <para>抛射体容器</para>
/// </summary>
public static Node2D? ProjectileContainer { get; set; }
/// <summary>
/// <para>MagicContainer</para>
/// <para>法术容器</para>
/// </summary>
public static Node2D? MagicContainer { get; set; }
/// <summary>
/// <para>WeaponContainer</para>

View File

@ -88,6 +88,12 @@ public static class LogCat
/// <para>房间</para>
/// </summary>
public const string Room = "Room";
/// <summary>
/// <para>ItemSpawn</para>
/// <para>物品生成器</para>
/// </summary>
public const string ItemSpawn = "ItemSpawn";
}

View File

@ -97,16 +97,4 @@ public static class ItemTypeManager
Registry.TryGetValue(id, out var itemType)
? itemType.Icon ?? DefaultTexture
: DefaultTexture;
/// <summary>
/// <para>Gets the maximum number of stacks for an item</para>
/// <para>获取某个物品的最大堆叠数量</para>
/// </summary>
/// <param name="id">
///<para>id</para>
///<para>物品ID</para>
/// </param>
/// <returns></returns>
public static int MaxStackQuantityOf(string id) =>
Registry.TryGetValue(id, out var itemType) ? itemType.MaxStackQuantity : 0;
}

View File

@ -45,6 +45,10 @@ public partial class GameSceneLoader : SceneLoaderTemplate
//加载抛射体容器
var projectileContainer = GetNode<Node2D>("ProjectileContainer");
GameSceneDepend.ProjectileContainer = projectileContainer;
//Load magic container
//加载魔术容器
var magicContainer = GetNode<Node2D>("MagicContainer");
GameSceneDepend.MagicContainer = magicContainer;
//Load Packsack container
//加载背包容器
var packsackContainer = GetNode<Node2D>("PacksackContainer");

View File

@ -1,4 +1,5 @@
using ColdMint.scripts.inventory;
using ColdMint.scripts.debug;
using ColdMint.scripts.inventory;
using ColdMint.scripts.map.events;
using Godot;
@ -15,7 +16,6 @@ public partial class ItemSpawn : Marker2D
public override void _Ready()
{
base._Ready();
EventBus.MapGenerationCompleteEvent += MapGenerationCompleteEvent;
}
@ -29,6 +29,7 @@ public partial class ItemSpawn : Marker2D
}
var item = ItemTypeManager.CreateItem(ItemId, this);
LogCat.LogWithFormat("generated_item_is_empty",LogCat.LogLabel.ItemSpawn,true,ItemId,item == null);
if (item is Node2D node2D)
{
node2D.GlobalPosition = GlobalPosition;

View File

@ -1,15 +1,53 @@
using ColdMint.scripts.projectile;
using ColdMint.scripts.weapon;
using Godot;
namespace ColdMint.scripts.pickable;
/// <summary>
/// <para>magic</para>
/// <para>法术</para>
/// </summary>
/// <remarks>
///<para>For projectile weapons</para>
///<para>用于抛射体武器</para>
/// </remarks>
public partial class MagicPickAble : PickAbleTemplate
public partial class MagicPickAble : PickAbleTemplate, IMagic
{
private string? _projectilePath;
private PackedScene? _projectileScene;
public override void _Ready()
{
base._Ready();
if (_projectilePath != null)
{
_projectileScene = GD.Load<PackedScene>(_projectilePath);
}
}
public override int ItemType
{
get => Config.ItemType.Magic;
}
public PackedScene? GetProjectile()
{
return _projectileScene;
}
public void ModifyWeapon(ProjectileWeapon projectileWeapon)
{
}
public void RestoreWeapon(ProjectileWeapon projectileWeapon)
{
}
public void ModifyProjectile(Projectile projectile)
{
}
}

View File

@ -1,3 +1,6 @@
using ColdMint.scripts.weapon;
using Godot;
namespace ColdMint.scripts.projectile;
/// <summary>
@ -10,5 +13,32 @@ namespace ColdMint.scripts.projectile;
/// </remarks>
public interface IMagic
{
/// <summary>
/// <para>GetProjectile</para>
/// <para>获取抛射体</para>
/// </summary>
/// <returns></returns>
PackedScene? GetProjectile();
/// <summary>
/// <para>Modify Weapon</para>
/// <para>修改武器</para>
/// </summary>
/// <param name="projectileWeapon"></param>
void ModifyWeapon(ProjectileWeapon projectileWeapon);
/// <summary>
/// <para>Restores the modified weapon properties</para>
/// <para>还原修改的武器属性</para>
/// </summary>
/// <param name="projectileWeapon"></param>
void RestoreWeapon(ProjectileWeapon projectileWeapon);
/// <summary>
/// <para>Modify the projectile</para>
/// <para>修改抛射体</para>
/// </summary>
/// <param name="projectile"></param>
void ModifyProjectile(Projectile projectile);
}

View File

@ -225,16 +225,21 @@ public static class NodeUtils
/// <returns></returns>
public static Node FindContainerNode(Node childNode, Node defaultParentNode)
{
if (GameSceneDepend.AiCharacterContainer!= null && childNode is AiCharacter)
if (GameSceneDepend.AiCharacterContainer != null && childNode is AiCharacter)
{
return GameSceneDepend.AiCharacterContainer;
}
if (GameSceneDepend.ProjectileContainer != null && childNode is Projectile)
{
return GameSceneDepend.ProjectileContainer;
}
if (GameSceneDepend.MagicContainer != null && childNode is IMagic)
{
return GameSceneDepend.MagicContainer;
}
if (GameSceneDepend.WeaponContainer != null && childNode is WeaponTemplate)
{
return GameSceneDepend.WeaponContainer;

View File

@ -1,5 +1,8 @@
using System.Collections.Generic;
using ColdMint.scripts.debug;
using ColdMint.scripts.inventory;
using ColdMint.scripts.map.events;
using ColdMint.scripts.projectile;
using Godot;
namespace ColdMint.scripts.weapon;
@ -19,28 +22,60 @@ public partial class ProjectileWeapon : WeaponTemplate
/// <para>抛射体的生成位置</para>
/// </summary>
private Marker2D? _marker2D;
private int _projectileIndex;
/// <summary>
/// <para>Number of slots for ranged weapons</para>
/// <para>远程武器的槽位数量</para>
/// </summary>
[Export] public int NumberSlots { get; set; }
private readonly List<IMagic> _magics = new();
public override int ItemType
{
get => Config.ItemType.ProjectileWeapon;
}
public override void _Ready()
{
base._Ready();
_marker2D = GetNode<Marker2D>("Marker2D");
SelfItemContainer = new UniversalItemContainer(NumberSlots);
SelfItemContainer.AllowAddingItemByType(Config.ItemType.Magic);
SelfItemContainer.ItemDataChangeEvent += OnItemDataChangeEvent;
}
private void OnItemDataChangeEvent(ItemDataChangeEvent itemDataChangeEvent)
{
if (SelfItemContainer == null)
{
return;
}
_magics.Clear();
var totalCapacity = SelfItemContainer.GetTotalCapacity();
for (var i = 0; i < totalCapacity; i++)
{
var item = SelfItemContainer.GetItem(i);
if (item == null)
{
continue;
}
if (item is not IMagic magic)
{
continue;
}
_magics.Add(magic);
}
}
public override void _ExitTree()
{
base._ExitTree();
if (SelfItemContainer != null)
{
SelfItemContainer.ItemDataChangeEvent -= OnItemDataChangeEvent;
}
}
protected override void DoFire(Node2D? owner, Vector2 enemyGlobalPosition)
{
@ -61,6 +96,10 @@ public partial class ProjectileWeapon : WeaponTemplate
LogCat.LogError("projectile_container_is_null");
return;
}
if (_magics.Count == 0)
{
LogCat.LogError("magics_is_null");
return;
}
}
}