diff --git a/data/itemRegs/magics.yaml b/data/itemRegs/magics.yaml
new file mode 100644
index 0000000..7b53fa5
--- /dev/null
+++ b/data/itemRegs/magics.yaml
@@ -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
\ No newline at end of file
diff --git a/locals/Item.csv b/locals/Item.csv
index 78af003..ecdd158 100644
--- a/locals/Item.csv
+++ b/locals/Item.csv
@@ -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つのアイテムスロットを提供します。
\ No newline at end of file
+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.,術の実体化した弾丸です。
\ No newline at end of file
diff --git a/locals/Log.csv b/locals/Log.csv
index ca1cd8d..a23920f 100644
--- a/locals/Log.csv
+++ b/locals/Log.csv
@@ -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}の部屋のプレビューを作成できませんでした。
\ No newline at end of file
+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.,スペルリストは空です。
\ No newline at end of file
diff --git a/prefab/magics/curseOfTheUndead.tscn b/prefab/magics/curseOfTheUndead.tscn
new file mode 100644
index 0000000..11e4248
--- /dev/null
+++ b/prefab/magics/curseOfTheUndead.tscn
@@ -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")
diff --git a/prefab/roomTemplates/dungeon/initialRoom.tscn b/prefab/roomTemplates/dungeon/initialRoom.tscn
index ca37f5c..e44b0cf 100644
--- a/prefab/roomTemplates/dungeon/initialRoom.tscn
+++ b/prefab/roomTemplates/dungeon/initialRoom.tscn
@@ -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)
diff --git a/scenes/game.tscn b/scenes/game.tscn
index fe5936c..d6bda67 100644
--- a/scenes/game.tscn
+++ b/scenes/game.tscn
@@ -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="."]
diff --git a/scripts/GameSceneDepend.cs b/scripts/GameSceneDepend.cs
index 64e3efa..3821978 100644
--- a/scripts/GameSceneDepend.cs
+++ b/scripts/GameSceneDepend.cs
@@ -48,6 +48,12 @@ public static class GameSceneDepend
/// 抛射体容器
///
public static Node2D? ProjectileContainer { get; set; }
+
+ ///
+ /// MagicContainer
+ /// 法术容器
+ ///
+ public static Node2D? MagicContainer { get; set; }
///
/// WeaponContainer
diff --git a/scripts/debug/LogCat.cs b/scripts/debug/LogCat.cs
index 0a85c53..5907d05 100644
--- a/scripts/debug/LogCat.cs
+++ b/scripts/debug/LogCat.cs
@@ -88,6 +88,12 @@ public static class LogCat
/// 房间
///
public const string Room = "Room";
+
+ ///
+ /// ItemSpawn
+ /// 物品生成器
+ ///
+ public const string ItemSpawn = "ItemSpawn";
}
diff --git a/scripts/inventory/ItemTypeManager.cs b/scripts/inventory/ItemTypeManager.cs
index 29b759b..6dce398 100644
--- a/scripts/inventory/ItemTypeManager.cs
+++ b/scripts/inventory/ItemTypeManager.cs
@@ -97,16 +97,4 @@ public static class ItemTypeManager
Registry.TryGetValue(id, out var itemType)
? itemType.Icon ?? DefaultTexture
: DefaultTexture;
-
- ///
- /// Gets the maximum number of stacks for an item
- /// 获取某个物品的最大堆叠数量
- ///
- ///
- ///id
- ///物品ID
- ///
- ///
- public static int MaxStackQuantityOf(string id) =>
- Registry.TryGetValue(id, out var itemType) ? itemType.MaxStackQuantity : 0;
}
\ No newline at end of file
diff --git a/scripts/loader/sceneLoader/GameSceneLoader.cs b/scripts/loader/sceneLoader/GameSceneLoader.cs
index e39855d..bf56c32 100644
--- a/scripts/loader/sceneLoader/GameSceneLoader.cs
+++ b/scripts/loader/sceneLoader/GameSceneLoader.cs
@@ -45,6 +45,10 @@ public partial class GameSceneLoader : SceneLoaderTemplate
//加载抛射体容器
var projectileContainer = GetNode("ProjectileContainer");
GameSceneDepend.ProjectileContainer = projectileContainer;
+ //Load magic container
+ //加载魔术容器
+ var magicContainer = GetNode("MagicContainer");
+ GameSceneDepend.MagicContainer = magicContainer;
//Load Packsack container
//加载背包容器
var packsackContainer = GetNode("PacksackContainer");
diff --git a/scripts/map/ItemSpawn.cs b/scripts/map/ItemSpawn.cs
index 2276d18..15c6495 100644
--- a/scripts/map/ItemSpawn.cs
+++ b/scripts/map/ItemSpawn.cs
@@ -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;
diff --git a/scripts/pickable/MagicPickAble.cs b/scripts/pickable/MagicPickAble.cs
index 6c92a8a..6e547cd 100644
--- a/scripts/pickable/MagicPickAble.cs
+++ b/scripts/pickable/MagicPickAble.cs
@@ -1,15 +1,53 @@
+using ColdMint.scripts.projectile;
+using ColdMint.scripts.weapon;
+using Godot;
+
namespace ColdMint.scripts.pickable;
///
+/// magic
/// 法术
///
///
+///For projectile weapons
///用于抛射体武器
///
-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(_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)
+ {
+
+ }
}
\ No newline at end of file
diff --git a/scripts/projectile/IMagic.cs b/scripts/projectile/IMagic.cs
index 2b9351e..d984f71 100644
--- a/scripts/projectile/IMagic.cs
+++ b/scripts/projectile/IMagic.cs
@@ -1,3 +1,6 @@
+using ColdMint.scripts.weapon;
+using Godot;
+
namespace ColdMint.scripts.projectile;
///
@@ -10,5 +13,32 @@ namespace ColdMint.scripts.projectile;
///
public interface IMagic
{
+ ///
+ /// GetProjectile
+ /// 获取抛射体
+ ///
+ ///
+ PackedScene? GetProjectile();
+
+ ///
+ /// Modify Weapon
+ /// 修改武器
+ ///
+ ///
+ void ModifyWeapon(ProjectileWeapon projectileWeapon);
+
+ ///
+ /// Restores the modified weapon properties
+ /// 还原修改的武器属性
+ ///
+ ///
+ void RestoreWeapon(ProjectileWeapon projectileWeapon);
+ ///
+ /// Modify the projectile
+ /// 修改抛射体
+ ///
+ ///
+ void ModifyProjectile(Projectile projectile);
+
}
\ No newline at end of file
diff --git a/scripts/utils/NodeUtils.cs b/scripts/utils/NodeUtils.cs
index 4761ab2..89a7e34 100644
--- a/scripts/utils/NodeUtils.cs
+++ b/scripts/utils/NodeUtils.cs
@@ -225,16 +225,21 @@ public static class NodeUtils
///
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;
diff --git a/scripts/weapon/ProjectileWeapon.cs b/scripts/weapon/ProjectileWeapon.cs
index 5c982be..04e21ff 100644
--- a/scripts/weapon/ProjectileWeapon.cs
+++ b/scripts/weapon/ProjectileWeapon.cs
@@ -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
/// 抛射体的生成位置
///
private Marker2D? _marker2D;
-
- private int _projectileIndex;
-
+
///
/// Number of slots for ranged weapons
/// 远程武器的槽位数量
///
[Export] public int NumberSlots { get; set; }
+ private readonly List _magics = new();
+
public override int ItemType
{
get => Config.ItemType.ProjectileWeapon;
}
-
+
public override void _Ready()
{
base._Ready();
_marker2D = GetNode("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;
+ }
}
}
\ No newline at end of file