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

@ -3,3 +3,5 @@ item_staff_necromancy,死灵法杖,staffNecromancy,ネクロポリスの杖で
item_staff_necromancy_desc,发射诅咒,可将敌人转化为邪恶的怪物。,Cast a curse that transforms enemies into evil monsters.,呪いを発射して、敵を邪悪な怪物に変えることができます。 item_staff_necromancy_desc,发射诅咒,可将敌人转化为邪恶的怪物。,Cast a curse that transforms enemies into evil monsters.,呪いを発射して、敵を邪悪な怪物に変えることができます。
item_portable_backpacks,便携式背包,PortableBackpacks,ポータブルバックパック 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
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

@ -112,3 +112,5 @@ log_show_all_node,显示{0}个节点。,Show {0} nodes.,{0}ノードが表示さ
log_enter_the_screen,进入屏幕。,Enter screen,画面に移動。 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_magics_is_null,法术列表是空的。,The spell list is empty.,スペルリストは空です。
1 id zh en ja
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="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/PlayerSpawn.cs" id="2_6p8mv"]
[ext_resource type="Script" path="res://scripts/map/ItemSpawn.cs" id="3_v1tlc"] [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="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://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"] [sub_resource type="RectangleShape2D" id="RectangleShape2D_kiih8"]
size = Vector2(507, 251) size = Vector2(507, 251)
@ -46,6 +45,11 @@ position = Vector2(142, 84)
script = ExtResource("3_v1tlc") script = ExtResource("3_v1tlc")
ItemId = "staff_necromancy" 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="."] [node name="NavigationRegion2D" type="NavigationRegion2D" parent="."]
navigation_polygon = SubResource("NavigationPolygon_064c7") navigation_polygon = SubResource("NavigationPolygon_064c7")
@ -81,9 +85,3 @@ texture = ExtResource("5_4pssd")
[node name="RigidBody2D" parent="." instance=ExtResource("5_7c8bh")] [node name="RigidBody2D" parent="." instance=ExtResource("5_7c8bh")]
position = Vector2(149, 109) position = Vector2(149, 109)
collision_mask = 0 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="WeaponContainer" type="Node2D" parent="."]
[node name="MagicContainer" type="Node2D" parent="."]
[node name="PlayerContainer" type="Node2D" parent="."] [node name="PlayerContainer" type="Node2D" parent="."]
[node name="AICharacterContainer" type="Node2D" parent="."] [node name="AICharacterContainer" type="Node2D" parent="."]

View File

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

View File

@ -88,6 +88,12 @@ public static class LogCat
/// <para>房间</para> /// <para>房间</para>
/// </summary> /// </summary>
public const string Room = "Room"; 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) Registry.TryGetValue(id, out var itemType)
? itemType.Icon ?? DefaultTexture ? itemType.Icon ?? DefaultTexture
: 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"); var projectileContainer = GetNode<Node2D>("ProjectileContainer");
GameSceneDepend.ProjectileContainer = projectileContainer; GameSceneDepend.ProjectileContainer = projectileContainer;
//Load magic container
//加载魔术容器
var magicContainer = GetNode<Node2D>("MagicContainer");
GameSceneDepend.MagicContainer = magicContainer;
//Load Packsack container //Load Packsack container
//加载背包容器 //加载背包容器
var packsackContainer = GetNode<Node2D>("PacksackContainer"); 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 ColdMint.scripts.map.events;
using Godot; using Godot;
@ -15,7 +16,6 @@ public partial class ItemSpawn : Marker2D
public override void _Ready() public override void _Ready()
{ {
base._Ready(); base._Ready();
EventBus.MapGenerationCompleteEvent += MapGenerationCompleteEvent; EventBus.MapGenerationCompleteEvent += MapGenerationCompleteEvent;
} }
@ -29,6 +29,7 @@ public partial class ItemSpawn : Marker2D
} }
var item = ItemTypeManager.CreateItem(ItemId, this); var item = ItemTypeManager.CreateItem(ItemId, this);
LogCat.LogWithFormat("generated_item_is_empty",LogCat.LogLabel.ItemSpawn,true,ItemId,item == null);
if (item is Node2D node2D) if (item is Node2D node2D)
{ {
node2D.GlobalPosition = GlobalPosition; node2D.GlobalPosition = GlobalPosition;

View File

@ -1,15 +1,53 @@
using ColdMint.scripts.projectile;
using ColdMint.scripts.weapon;
using Godot;
namespace ColdMint.scripts.pickable; namespace ColdMint.scripts.pickable;
/// <summary> /// <summary>
/// <para>magic</para>
/// <para>法术</para> /// <para>法术</para>
/// </summary> /// </summary>
/// <remarks> /// <remarks>
///<para>For projectile weapons</para>
///<para>用于抛射体武器</para> ///<para>用于抛射体武器</para>
/// </remarks> /// </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 public override int ItemType
{ {
get => Config.ItemType.Magic; 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; namespace ColdMint.scripts.projectile;
/// <summary> /// <summary>
@ -10,5 +13,32 @@ namespace ColdMint.scripts.projectile;
/// </remarks> /// </remarks>
public interface IMagic 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,7 +225,7 @@ public static class NodeUtils
/// <returns></returns> /// <returns></returns>
public static Node FindContainerNode(Node childNode, Node defaultParentNode) 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; return GameSceneDepend.AiCharacterContainer;
} }
@ -235,6 +235,11 @@ public static class NodeUtils
return GameSceneDepend.ProjectileContainer; return GameSceneDepend.ProjectileContainer;
} }
if (GameSceneDepend.MagicContainer != null && childNode is IMagic)
{
return GameSceneDepend.MagicContainer;
}
if (GameSceneDepend.WeaponContainer != null && childNode is WeaponTemplate) if (GameSceneDepend.WeaponContainer != null && childNode is WeaponTemplate)
{ {
return GameSceneDepend.WeaponContainer; return GameSceneDepend.WeaponContainer;

View File

@ -1,5 +1,8 @@
using System.Collections.Generic;
using ColdMint.scripts.debug; using ColdMint.scripts.debug;
using ColdMint.scripts.inventory; using ColdMint.scripts.inventory;
using ColdMint.scripts.map.events;
using ColdMint.scripts.projectile;
using Godot; using Godot;
namespace ColdMint.scripts.weapon; namespace ColdMint.scripts.weapon;
@ -20,14 +23,14 @@ public partial class ProjectileWeapon : WeaponTemplate
/// </summary> /// </summary>
private Marker2D? _marker2D; private Marker2D? _marker2D;
private int _projectileIndex;
/// <summary> /// <summary>
/// <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] public int NumberSlots { get; set; }
private readonly List<IMagic> _magics = new();
public override int ItemType public override int ItemType
{ {
get => Config.ItemType.ProjectileWeapon; get => Config.ItemType.ProjectileWeapon;
@ -39,8 +42,40 @@ public partial class ProjectileWeapon : WeaponTemplate
_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.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) protected override void DoFire(Node2D? owner, Vector2 enemyGlobalPosition)
{ {
@ -61,6 +96,10 @@ public partial class ProjectileWeapon : WeaponTemplate
LogCat.LogError("projectile_container_is_null"); LogCat.LogError("projectile_container_is_null");
return; return;
} }
if (_magics.Count == 0)
{
LogCat.LogError("magics_is_null");
return;
}
} }
} }