diff --git a/data/itemRegs/magics.yaml b/data/itemRegs/magics.yaml
index 092267b..c2e0253 100644
--- a/data/itemRegs/magics.yaml
+++ b/data/itemRegs/magics.yaml
@@ -19,4 +19,8 @@
- id: magic_missile
scene_path: res://prefab/magics/magicMissile.tscn
icon_path: res://sprites/projectile/magicMissile.png
+ max_stack_value: 1
+- id: tracking_spell
+ scene_path: res://prefab/magics/trackingSpell.tscn
+ icon_path: res://sprites/projectile/trackingSpell.png
max_stack_value: 1
\ No newline at end of file
diff --git a/locals/Item.csv b/locals/Item.csv
index c4d7511..29a170c 100644
--- a/locals/Item.csv
+++ b/locals/Item.csv
@@ -16,4 +16,6 @@ item_curse_desc,杀死敌人后在生成死灵敌人。,Spawn Undead enemies aft
item_beginner_staff,初学者法杖,Beginner's staff,初心者用の杖です
item_beginner_staff_desc,送给初来乍到的冒险家。,For new adventurers.,初心者の冒険家に贈ります。
item_magic_missile,魔法飞弹,Magic missile,魔法のミサイルです
-item_magic_missile_desc,魔法飞弹,Magic missile,魔法のミサイルです
\ No newline at end of file
+item_magic_missile_desc,轻快的法术。,A light spell.,軽快な術です。
+item_tracking_spell,追踪法术,Tracking spell,追跡術です
+item_tracking_spell_desc,使发射的子弹追踪敌人,Let the fired bullets track the enemy,発射した弾丸で敵を追跡させます
\ No newline at end of file
diff --git a/prefab/magics/trackingSpell.tscn b/prefab/magics/trackingSpell.tscn
new file mode 100644
index 0000000..43503b8
--- /dev/null
+++ b/prefab/magics/trackingSpell.tscn
@@ -0,0 +1,36 @@
+[gd_scene load_steps=5 format=3 uid="uid://cg75t3fw5c6er"]
+
+[ext_resource type="Script" path="res://scripts/spell/TrackingSpell.cs" id="1_vhnwx"]
+[ext_resource type="AudioStream" uid="uid://cak6chjjsu7wo" path="res://sounds/fire.wav" id="2_3fbv3"]
+[ext_resource type="Texture2D" uid="uid://dhgbij2ifphar" path="res://sprites/projectile/trackingSpell.png" id="2_i33g0"]
+
+[sub_resource type="RectangleShape2D" id="RectangleShape2D_i3lbq"]
+size = Vector2(30, 31)
+
+[node name="trackingSpell" type="RigidBody2D"]
+collision_layer = 8
+collision_mask = 34
+angular_damp = -1.0
+script = ExtResource("1_vhnwx")
+
+[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
+position = Vector2(0, -0.5)
+shape = SubResource("RectangleShape2D_i3lbq")
+
+[node name="Marker2D" type="Marker2D" parent="."]
+position = Vector2(65, 0)
+
+[node name="AudioStreamPlayer2D" type="AudioStreamPlayer2D" parent="Marker2D"]
+stream = ExtResource("2_3fbv3")
+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="."]
+
+[node name="TrackingSpell" type="Sprite2D" parent="."]
+texture = ExtResource("2_i33g0")
diff --git a/prefab/magics/x3.tscn b/prefab/magics/x3.tscn
index bba5057..0904635 100644
--- a/prefab/magics/x3.tscn
+++ b/prefab/magics/x3.tscn
@@ -14,7 +14,6 @@ angular_damp = -1.0
script = ExtResource("1_cnhod")
RandomAngle = true
UnitRadian = 0.07
-_projectilePath = null
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
position = Vector2(0, -0.5)
diff --git a/prefab/projectile/curseOfTheUndead.tscn b/prefab/projectile/curseOfTheUndead.tscn
index f008090..9e60274 100644
--- a/prefab/projectile/curseOfTheUndead.tscn
+++ b/prefab/projectile/curseOfTheUndead.tscn
@@ -14,11 +14,7 @@ _durability = 1.0
_maxDamage = 7
_minDamage = 3
_damageType = 2
-Speed = 500.0
-_enableBounce = null
-_ignoreWall = null
-_enableTracking = null
-_targetDiesDestroyProjectile = true
+Speed = 10.0
_repelStrength = 2.5
[node name="CurseOfTheUndead" type="Sprite2D" parent="."]
diff --git a/prefab/projectile/magicMissile.tscn b/prefab/projectile/magicMissile.tscn
index 8430a51..6debafc 100644
--- a/prefab/projectile/magicMissile.tscn
+++ b/prefab/projectile/magicMissile.tscn
@@ -15,8 +15,7 @@ _durability = 1.0
_maxDamage = 7
_minDamage = 3
_damageType = 2
-Speed = 500.0
-_targetDiesDestroyProjectile = true
+Speed = 15.0
_repelStrength = 2.5
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
diff --git a/prefab/roomTemplates/tutorials/spellEditor.tscn b/prefab/roomTemplates/tutorials/spellEditor.tscn
index ce8c422..6516578 100644
--- a/prefab/roomTemplates/tutorials/spellEditor.tscn
+++ b/prefab/roomTemplates/tutorials/spellEditor.tscn
@@ -90,15 +90,23 @@ texture = ExtResource("6_dbg76")
[node name="RigidBody2D" parent="." instance=ExtResource("5_0kep0")]
position = Vector2(227, 283)
+_initialDurability = 0
+_maxDurability = 0
[node name="WoodenBox" parent="." instance=ExtResource("7_jybe6")]
position = Vector2(715, 244)
+_initialDurability = 0
+_furnitureName = ""
[node name="WoodenBox2" parent="." instance=ExtResource("7_jybe6")]
position = Vector2(715, 200)
+_initialDurability = 0
+_furnitureName = ""
[node name="WoodenBox3" parent="." instance=ExtResource("7_jybe6")]
position = Vector2(715, 162)
+_initialDurability = 0
+_furnitureName = ""
[node name="AutoSpawn" type="Node2D" parent="."]
@@ -112,6 +120,11 @@ position = Vector2(100, 250)
script = ExtResource("4_6ihp7")
_itemIdList = PackedStringArray("magic_missile")
+[node name="tracking_spell" type="Marker2D" parent="AutoSpawn"]
+position = Vector2(156, 245)
+script = ExtResource("4_6ihp7")
+_itemIdList = PackedStringArray("tracking_spell")
+
[node name="RoomArea" type="Area2D" parent="."]
[node name="CollisionShape2D" type="CollisionShape2D" parent="RoomArea"]
diff --git a/prefab/weapons/BeginnerStaff.tscn b/prefab/weapons/BeginnerStaff.tscn
index a9b6d04..bd16e97 100644
--- a/prefab/weapons/BeginnerStaff.tscn
+++ b/prefab/weapons/BeginnerStaff.tscn
@@ -13,9 +13,8 @@ collision_layer = 8
collision_mask = 34
script = ExtResource("1_w4b6p")
_numberSlots = 5
-_spellList = null
_fireSequentially = true
-FiringIntervalAsMillisecond = 300
+FiringIntervalAsMillisecond = 280
_recoilStrength = 5
UniqueIcon = ExtResource("2_ip8xd")
diff --git a/prefab/weapons/IronAxe.tscn b/prefab/weapons/IronAxe.tscn
index ad0cb27..9922c3f 100644
--- a/prefab/weapons/IronAxe.tscn
+++ b/prefab/weapons/IronAxe.tscn
@@ -15,10 +15,6 @@ collision_layer = 8
collision_mask = 34
angular_damp = -1.0
script = ExtResource("1_snmy1")
-_maxDamage = null
-_minDamage = null
-FiringIntervalAsMillisecond = null
-_recoilStrength = null
[node name="StaffOfTheUndead2" type="Sprite2D" parent="."]
position = Vector2(30, 0)
diff --git a/prefab/weapons/StaffNecromancy.tscn b/prefab/weapons/StaffNecromancy.tscn
index 35dd763..0ebbe77 100644
--- a/prefab/weapons/StaffNecromancy.tscn
+++ b/prefab/weapons/StaffNecromancy.tscn
@@ -12,10 +12,10 @@ size = Vector2(49, 5.25)
collision_layer = 8
collision_mask = 34
script = ExtResource("1_w8hhv")
-_numberSlots = 5
+_numberSlots = 1
_spellList = PackedStringArray("necromancy")
_fireSequentially = true
-FiringIntervalAsMillisecond = 300
+FiringIntervalAsMillisecond = 350
_recoilStrength = 5
UniqueIcon = ExtResource("3_31iau")
diff --git a/scripts/debug/LogCat.cs b/scripts/debug/LogCat.cs
index dcb6cef..da378a0 100644
--- a/scripts/debug/LogCat.cs
+++ b/scripts/debug/LogCat.cs
@@ -15,6 +15,7 @@ public static class LogCat
/// 默认的日志标签
///
public const string Default = "Default";
+ public const string Debug = "Debug";
///
/// LookForWeaponProcessor
diff --git a/scripts/projectile/Projectile.cs b/scripts/projectile/Projectile.cs
index 5fac312..af40de4 100644
--- a/scripts/projectile/Projectile.cs
+++ b/scripts/projectile/Projectile.cs
@@ -39,7 +39,28 @@ public partial class Projectile : CharacterBody2D
///
private DateTime? _destructionTime;
- [Export] public float Speed;
+ private float _actualSpeed;
+
+ ///
+ /// The speed of the bullet
+ /// 子弹的飞行速度
+ ///
+ ///
+ ///Indicates the number of units moved per second
+ ///表示每秒移动的单位格数
+ ///
+ [Export]
+ public float Speed
+ {
+ get => _actualSpeed / Config.CellSize;
+ private set => _actualSpeed = value * Config.CellSize;
+ }
+
+ ///
+ /// Get actual speed
+ /// 获取实际速度
+ ///
+ public float ActualSpeed => _actualSpeed;
///
/// Whether it bounces back after hitting an enemy or a wall
@@ -57,13 +78,13 @@ public partial class Projectile : CharacterBody2D
/// Enable the tracking of the enemy
/// 启用追踪敌人的功能
///
- [Export] private bool _enableTracking;
+ [Export] public bool EnableTracking;
///
/// The target dies and destroys the projectile at the same time
/// 在目标死亡后销毁抛射体
///
- [Export] private bool _targetDiesDestroyProjectile;
+ [Export] public bool TargetDiesDestroyProjectile;
///
/// The target
@@ -95,6 +116,7 @@ public partial class Projectile : CharacterBody2D
///
public new Node2D? Owner { get; set; }
+
public override void _Ready()
{
if (!_ignoreWall)
@@ -129,7 +151,7 @@ public partial class Projectile : CharacterBody2D
//Clear the trace when the target is destroyed.
//在目标被销毁的时候清空跟踪。
TargetNode = null;
- if (_targetDiesDestroyProjectile)
+ if (TargetDiesDestroyProjectile)
{
OnTimeOut();
}
@@ -265,7 +287,8 @@ public partial class Projectile : CharacterBody2D
pickAbleTemplate.ApplyImpulse(new Vector2(normalized.X * _repelStrength * Config.CellSize,
normalized.Y * _repelStrength * Config.CellSize));
}
- }else if (target is Furniture furniture)
+ }
+ else if (target is Furniture furniture)
{
var damage = new Damage
{
@@ -315,6 +338,7 @@ public partial class Projectile : CharacterBody2D
{
OnTimeOut();
}
+ LookAt(GlobalPosition + Velocity);
}
public override void _PhysicsProcess(double delta)
@@ -324,7 +348,7 @@ public partial class Projectile : CharacterBody2D
{
//No collision.
//没有撞到任何东西。
- if (_enableTracking && TargetNode != null)
+ if (EnableTracking && TargetNode != null)
{
//Track the target
//追踪目标
@@ -340,7 +364,7 @@ public partial class Projectile : CharacterBody2D
}
}
- var actualDesiredVelocity = desiredVelocity.Normalized() * Speed;
+ var actualDesiredVelocity = desiredVelocity.Normalized() * _actualSpeed;
//The weight is smaller, the circle is larger.
//weight越小,子弹绕的圈越大。
Velocity = Velocity.Lerp(actualDesiredVelocity, 0.1f);
diff --git a/scripts/spell/TrackingSpell.cs b/scripts/spell/TrackingSpell.cs
new file mode 100644
index 0000000..8cf246b
--- /dev/null
+++ b/scripts/spell/TrackingSpell.cs
@@ -0,0 +1,13 @@
+using ColdMint.scripts.projectile;
+using Godot;
+
+namespace ColdMint.scripts.spell;
+
+public partial class TrackingSpell : SpellPickAble
+{
+ public override void ModifyProjectile(int index, Projectile projectile, ref Vector2 velocity)
+ {
+ base.ModifyProjectile(index, projectile, ref velocity);
+ projectile.EnableTracking = true;
+ }
+}
\ No newline at end of file
diff --git a/scripts/weapon/ProjectileWeapon.cs b/scripts/weapon/ProjectileWeapon.cs
index 0256643..5ab297e 100644
--- a/scripts/weapon/ProjectileWeapon.cs
+++ b/scripts/weapon/ProjectileWeapon.cs
@@ -263,7 +263,7 @@ public partial class ProjectileWeapon : WeaponTemplate
RestoreWeapon(spellScope);
return false;
}
- var velocity = _marker2D.GlobalPosition.DirectionTo(enemyGlobalPosition) * projectile.Speed;
+ var velocity = _marker2D.GlobalPosition.DirectionTo(enemyGlobalPosition) * projectile.ActualSpeed;
for (var s = spellScope[0]; s <= spellScope[1]; s++)
{
var spell = _spells[s];
diff --git a/sprites/projectile/trackingSpell.png b/sprites/projectile/trackingSpell.png
new file mode 100644
index 0000000..2d25246
Binary files /dev/null and b/sprites/projectile/trackingSpell.png differ
diff --git a/sprites/projectile/trackingSpell.png.import b/sprites/projectile/trackingSpell.png.import
new file mode 100644
index 0000000..d8bf81f
--- /dev/null
+++ b/sprites/projectile/trackingSpell.png.import
@@ -0,0 +1,34 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://dhgbij2ifphar"
+path="res://.godot/imported/trackingSpell.png-69b7e63e484daf64f35dd6da8947c87b.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://sprites/projectile/trackingSpell.png"
+dest_files=["res://.godot/imported/trackingSpell.png-69b7e63e484daf64f35dd6da8947c87b.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1