diff --git a/data/itemRegs/magics.yaml b/data/itemRegs/magics.yaml index 7b53fa5..c2c25eb 100644 --- a/data/itemRegs/magics.yaml +++ b/data/itemRegs/magics.yaml @@ -7,4 +7,8 @@ - id: necromancy scene_path: res://prefab/magics/curseOfTheUndead.tscn icon_path: res://sprites/projectile/curseOfTheUndead.png + max_stack_value: 1 +- id: x3 + scene_path: res://prefab/magics/x3.tscn + icon_path: res://sprites/projectile/x3.png max_stack_value: 1 \ No newline at end of file diff --git a/locals/Item.csv b/locals/Item.csv index ecdd158..2edbad0 100644 --- a/locals/Item.csv +++ b/locals/Item.csv @@ -4,4 +4,6 @@ item_staff_necromancy_desc,发射诅咒,可将敌人转化为邪恶的怪物 item_portable_backpacks,便携式背包,PortableBackpacks,ポータブルバックパック 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 +item_necromancy_desc,法术的实体化弹丸。,The materialized projectile of a spell.,術の実体化した弾丸です。 +item_x3,三重射击法术,Triple shot spell,三重射撃術です +item_x3_desc,使发射器一次射出三颗弹丸。,Make the launcher shoot three pellets at a time.,発射機から一度に三つの弾丸を発射させます。 \ No newline at end of file diff --git a/prefab/magics/x3.tscn b/prefab/magics/x3.tscn new file mode 100644 index 0000000..2a136dd --- /dev/null +++ b/prefab/magics/x3.tscn @@ -0,0 +1,46 @@ +[gd_scene load_steps=6 format=3 uid="uid://cg75t3fw5c6er"] + +[ext_resource type="Script" path="res://scripts/spell/MultipleFireSpell.cs" id="1_cnhod"] +[ext_resource type="Texture2D" uid="uid://mb5yijtw7sw5" path="res://sprites/projectile/x3.png" id="3_b3s8h"] +[ext_resource type="AudioStream" uid="uid://cak6chjjsu7wo" path="res://sounds/fire.wav" id="4_ffr2k"] + +[sub_resource type="RectangleShape2D" id="RectangleShape2D_3eq4k"] +size = Vector2(30, 30) + +[sub_resource type="RectangleShape2D" id="RectangleShape2D_i3lbq"] +size = Vector2(30, 31) + +[node name="x3" type="RigidBody2D"] +collision_layer = 8 +collision_mask = 34 +angular_damp = -1.0 +script = ExtResource("1_cnhod") + +[node name="DamageArea2D" type="Area2D" parent="."] +collision_layer = 8 +collision_mask = 102 + +[node name="CollisionShape2D" type="CollisionShape2D" parent="DamageArea2D"] +shape = SubResource("RectangleShape2D_3eq4k") + +[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("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="."] + +[node name="X3" type="Sprite2D" parent="."] +texture = ExtResource("3_b3s8h") diff --git a/prefab/roomTemplates/dungeon/initialRoom.tscn b/prefab/roomTemplates/dungeon/initialRoom.tscn index e44b0cf..c809ed2 100644 --- a/prefab/roomTemplates/dungeon/initialRoom.tscn +++ b/prefab/roomTemplates/dungeon/initialRoom.tscn @@ -45,6 +45,16 @@ position = Vector2(142, 84) script = ExtResource("3_v1tlc") ItemId = "staff_necromancy" +[node name="ItemMarker2D3" type="Marker2D" parent="."] +position = Vector2(214, 83) +script = ExtResource("3_v1tlc") +ItemId = "x3" + +[node name="ItemMarker2D4" type="Marker2D" parent="."] +position = Vector2(366, 90) +script = ExtResource("3_v1tlc") +ItemId = "necromancy" + [node name="ItemMarker2D2" type="Marker2D" parent="."] position = Vector2(321, 118) script = ExtResource("3_v1tlc") diff --git a/prefab/weapons/StaffNecromancy.tscn b/prefab/weapons/StaffNecromancy.tscn index 044f4d2..1397579 100644 --- a/prefab/weapons/StaffNecromancy.tscn +++ b/prefab/weapons/StaffNecromancy.tscn @@ -17,6 +17,7 @@ collision_mask = 34 angular_damp = -1.0 script = ExtResource("1_w8hhv") _numberSlots = 5 +_fireSequentially = true FiringIntervalAsMillisecond = 300 _recoilStrength = 5 UniqueIcon = ExtResource("3_31iau") diff --git a/scripts/projectile/ISpell.cs b/scripts/projectile/ISpell.cs index 87b4186..dc00581 100644 --- a/scripts/projectile/ISpell.cs +++ b/scripts/projectile/ISpell.cs @@ -33,12 +33,23 @@ public interface ISpell /// /// void RestoreWeapon(ProjectileWeapon projectileWeapon); - + /// /// Modify the projectile /// 修改抛射体 /// - /// - void ModifyProjectile(Projectile projectile); + /// + ///What is the current projectile? For example, a weapon can fire three projectiles at once, with indexes 0,1,2 + ///当前抛射体是第几个?例如:武器可一下发射3个抛射体,索引为0,1,2 + /// + /// + ///Projectile object + ///抛射体对象 + /// + /// + ///The velocity of the projectile + ///抛射体的飞行速度 + /// + void ModifyProjectile(int index,Projectile projectile, ref Vector2 velocity); } \ No newline at end of file diff --git a/scripts/spell/MultipleFireSpell.cs b/scripts/spell/MultipleFireSpell.cs new file mode 100644 index 0000000..3d3dd4c --- /dev/null +++ b/scripts/spell/MultipleFireSpell.cs @@ -0,0 +1,82 @@ +using ColdMint.scripts.projectile; +using ColdMint.scripts.utils; +using ColdMint.scripts.weapon; +using Godot; + +namespace ColdMint.scripts.spell; + +/// +/// MultipleFireSpell +/// 多重射击法术 +/// +/// +///Use this spell to create shotgun effects +///通过此法术打造霰弹枪的效果 +/// +public partial class MultipleFireSpell : SpellPickAble +{ + /// + /// How many projectiles are generated per fire + /// 每次开火生成多少个抛射体 + /// + [Export] + public int NumberOfProjectiles { get; set; } = 3; + + /// + /// RandomAngle + /// 随机角度 + /// + [Export] + public bool RandomAngle { get; set; } + + /// + /// Unit radian + /// 单位弧度 + /// + /// + ///Unit radian of correction for the projectile Angle.Suppose there are three bullets fired at once, and this is the arc between the two bullets. + ///对抛射体角度修正的单位弧度。假定有三颗子弹一次发射,这是两颗子弹之间的弧度。 + /// + [Export] + public float UnitRadian { get; set; } = 0.069813f; + + /// + /// initial Radian + /// 起始弧度 + /// + /// + ///The Angle of the first bullet, and subsequent bullets will be offset in unit radians. + ///第一颗子弹的角度,随后的子弹会以单位弧度偏移。 + /// + private float _initialRadian; + private float _maxRadian; + private int _oldNumberOfProjectiles; + public override void ModifyWeapon(ProjectileWeapon projectileWeapon) + { + base.ModifyWeapon(projectileWeapon); + _oldNumberOfProjectiles = projectileWeapon.NumberOfProjectiles; + projectileWeapon.NumberOfProjectiles = NumberOfProjectiles; + _initialRadian = -(NumberOfProjectiles / 2f * UnitRadian); + _maxRadian = NumberOfProjectiles * UnitRadian; + } + + public override void RestoreWeapon(ProjectileWeapon projectileWeapon) + { + base.RestoreWeapon(projectileWeapon); + projectileWeapon.NumberOfProjectiles = _oldNumberOfProjectiles; + } + + public override void ModifyProjectile(int index, Projectile projectile, ref Vector2 velocity) + { + base.ModifyProjectile(index, projectile, ref velocity); + if (RandomAngle) + { + velocity = velocity.Rotated(_initialRadian + _maxRadian * RandomUtils.Instance.NextSingle()); + } + else + { + velocity = velocity.Rotated(_initialRadian + UnitRadian * index); + } + } + +} \ No newline at end of file diff --git a/scripts/spell/SpellPickAble.cs b/scripts/spell/SpellPickAble.cs index 683407d..441d199 100644 --- a/scripts/spell/SpellPickAble.cs +++ b/scripts/spell/SpellPickAble.cs @@ -38,17 +38,17 @@ public partial class SpellPickAble : PickAbleTemplate, ISpell return _projectileScene; } - public void ModifyWeapon(ProjectileWeapon projectileWeapon) + public virtual void ModifyWeapon(ProjectileWeapon projectileWeapon) { } - public void RestoreWeapon(ProjectileWeapon projectileWeapon) + public virtual void RestoreWeapon(ProjectileWeapon projectileWeapon) { } - public void ModifyProjectile(Projectile projectile) + public virtual void ModifyProjectile(int index, Projectile projectile, ref Vector2 velocity) { } diff --git a/scripts/weapon/ProjectileWeapon.cs b/scripts/weapon/ProjectileWeapon.cs index 35d13ab..5e0775c 100644 --- a/scripts/weapon/ProjectileWeapon.cs +++ b/scripts/weapon/ProjectileWeapon.cs @@ -216,36 +216,57 @@ public partial class ProjectileWeapon : WeaponTemplate LogCat.LogError("projectile_scene_is_null"); return false; } - for (var i = spellScope[0]; i <= spellScope[1]; i++) - { - var spell = _spells[i]; - spell.ModifyWeapon(this); - } + ModifyWeapon(spellScope); for (var i = 0; i < NumberOfProjectiles; i++) { var projectile = NodeUtils.InstantiatePackedScene(packedScene); if (projectile == null) { LogCat.LogError("projectile_is_null"); + RestoreWeapon(spellScope); return false; } + var velocity = _marker2D.GlobalPosition.DirectionTo(enemyGlobalPosition) * projectile.Speed; for (var s = spellScope[0]; s <= spellScope[1]; s++) { var spell = _spells[s]; - spell.ModifyProjectile(projectile); + spell.ModifyProjectile(i, projectile, ref velocity); } NodeUtils.CallDeferredAddChild(GameSceneDepend.ProjectileContainer, projectile); projectile.Owner = owner; projectile.TargetNode = GameSceneDepend.TemporaryTargetNode; - projectile.Velocity = - _marker2D.GlobalPosition.DirectionTo(enemyGlobalPosition) * projectile.Speed; + projectile.Velocity = velocity; projectile.Position = _marker2D.GlobalPosition; } + RestoreWeapon(spellScope); + return true; + } + + /// + /// Modify weapon attributes + /// 修改武器属性 + /// + /// + private void ModifyWeapon(int[] spellScope) + { + for (var i = spellScope[0]; i <= spellScope[1]; i++) + { + var spell = _spells[i]; + spell.ModifyWeapon(this); + } + } + + /// + /// Restores modifications to weapons + /// 恢复对武器的修改 + /// + /// + private void RestoreWeapon(int[] spellScope) + { for (var i = spellScope[0]; i <= spellScope[1]; i++) { var spell = _spells[i]; spell.RestoreWeapon(this); } - return true; } } \ No newline at end of file diff --git a/sprites/projectile/x3.png b/sprites/projectile/x3.png new file mode 100644 index 0000000..cc78f71 Binary files /dev/null and b/sprites/projectile/x3.png differ diff --git a/sprites/projectile/x3.png.import b/sprites/projectile/x3.png.import new file mode 100644 index 0000000..9af0540 --- /dev/null +++ b/sprites/projectile/x3.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://mb5yijtw7sw5" +path="res://.godot/imported/x3.png-096b2fc27f9da2412a5f72aad28677de.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://sprites/projectile/x3.png" +dest_files=["res://.godot/imported/x3.png-096b2fc27f9da2412a5f72aad28677de.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