From 4990a3e300b3116a5cf94aced365fc206ffadc20 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=99=A8=E8=90=BD=E5=9F=BA=E5=9B=B4=E8=99=BE?=
<3161880837@qq.com>
Date: Wed, 28 Jan 2026 20:20:55 +0800
Subject: [PATCH] =?UTF-8?q?feat(=E8=A7=92=E8=89=B2):=20=E6=B7=BB=E5=8A=A0G?=
=?UTF-8?q?obo=E8=A7=92=E8=89=B2=E5=8F=8A=E7=9B=B8=E5=85=B3=E8=B5=84?=
=?UTF-8?q?=E6=BA=90?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
添加Gobo角色,包括武器、召唤物和治疗导弹功能
- 新增Gobo角色模型和动画资源
- 实现Gobo武器系统,可召唤Gobo单位
- 添加治疗导弹功能,Gobo受伤时会发射治疗友军
- 优化实体基础类,添加生命值初始化方法
- 修改子弹伤害判定逻辑,支持友军伤害设置
---
components/Bullets/HealingMissle.tscn | 27 ++++++++++
components/Characters/Rooster.tscn | 10 ++--
components/Summons/Gobo.tscn | 46 ++++++++++++++++++
components/Weapons/Gobo.tscn | 39 +++++++++++++++
resources/characters/gobo/gobo-a.svg | 19 ++++++++
resources/characters/gobo/gobo-a.svg.import | 43 ++++++++++++++++
resources/characters/gobo/gobo-b.svg | 19 ++++++++
resources/characters/gobo/gobo-b.svg.import | 43 ++++++++++++++++
resources/characters/gobo/gobo-c.svg | 19 ++++++++
resources/characters/gobo/gobo-c.svg.import | 43 ++++++++++++++++
resources/items/apple-white.png | Bin 0 -> 2441 bytes
resources/items/apple-white.png.import | 40 +++++++++++++++
scripts/Contents/Bullets/HealingMissle.gd | 5 ++
scripts/Contents/Bullets/HealingMissle.gd.uid | 1 +
scripts/Contents/Summons/Gobo.gd | 32 ++++++++++++
scripts/Contents/Summons/Gobo.gd.uid | 1 +
scripts/Contents/Weapons/Gobo.gd | 13 +++++
scripts/Contents/Weapons/Gobo.gd.uid | 1 +
scripts/Contents/Weapons/Shield.gd | 5 +-
scripts/Statemachine/BulletBase.gd | 2 +-
scripts/Statemachine/EntityBase.gd | 4 ++
scripts/Tools/BulletTool.gd | 7 ++-
22 files changed, 410 insertions(+), 9 deletions(-)
create mode 100644 components/Bullets/HealingMissle.tscn
create mode 100644 components/Summons/Gobo.tscn
create mode 100644 components/Weapons/Gobo.tscn
create mode 100644 resources/characters/gobo/gobo-a.svg
create mode 100644 resources/characters/gobo/gobo-a.svg.import
create mode 100644 resources/characters/gobo/gobo-b.svg
create mode 100644 resources/characters/gobo/gobo-b.svg.import
create mode 100644 resources/characters/gobo/gobo-c.svg
create mode 100644 resources/characters/gobo/gobo-c.svg.import
create mode 100644 resources/items/apple-white.png
create mode 100644 resources/items/apple-white.png.import
create mode 100644 scripts/Contents/Bullets/HealingMissle.gd
create mode 100644 scripts/Contents/Bullets/HealingMissle.gd.uid
create mode 100644 scripts/Contents/Summons/Gobo.gd
create mode 100644 scripts/Contents/Summons/Gobo.gd.uid
create mode 100644 scripts/Contents/Weapons/Gobo.gd
create mode 100644 scripts/Contents/Weapons/Gobo.gd.uid
diff --git a/components/Bullets/HealingMissle.tscn b/components/Bullets/HealingMissle.tscn
new file mode 100644
index 0000000..9fc1bd5
--- /dev/null
+++ b/components/Bullets/HealingMissle.tscn
@@ -0,0 +1,27 @@
+[gd_scene load_steps=5 format=3 uid="uid://ds6yxgj6r8f4v"]
+
+[ext_resource type="PackedScene" uid="uid://crtdkysmnkith" path="res://components/Abstracts/BulletBase.tscn" id="1_1wl5l"]
+[ext_resource type="Texture2D" uid="uid://dpvk6pja35rdb" path="res://resources/items/apple-white.png" id="2_0jb7f"]
+[ext_resource type="Script" uid="uid://d2ubbdwexom6t" path="res://scripts/Contents/Bullets/HealingMissle.gd" id="2_nxr84"]
+
+[sub_resource type="SpriteFrames" id="SpriteFrames_nxr84"]
+animations = [{
+"frames": [{
+"duration": 1.0,
+"texture": ExtResource("2_0jb7f")
+}],
+"loop": true,
+"name": &"default",
+"speed": 5.0
+}]
+
+[node name="HealingMissle" instance=ExtResource("1_1wl5l")]
+script = ExtResource("2_nxr84")
+speed = 1.0
+lifeTime = 5000.0
+allowFriendlyDamage = true
+
+[node name="texture" parent="." index="0"]
+modulate = Color(0.0068707466, 1, 0, 1)
+scale = Vector2(0.44360867, 0.44360867)
+sprite_frames = SubResource("SpriteFrames_nxr84")
diff --git a/components/Characters/Rooster.tscn b/components/Characters/Rooster.tscn
index 61dea8f..6cf793e 100644
--- a/components/Characters/Rooster.tscn
+++ b/components/Characters/Rooster.tscn
@@ -1,8 +1,9 @@
-[gd_scene load_steps=14 format=3 uid="uid://dky8574uqc18r"]
+[gd_scene load_steps=15 format=3 uid="uid://dky8574uqc18r"]
[ext_resource type="PackedScene" uid="uid://cvogxi7mktumf" path="res://components/Abstracts/EntityBase.tscn" id="1_e5pl8"]
[ext_resource type="Script" uid="uid://cthtupc6dtbav" path="res://scripts/Contents/Characters/Rooster.gd" id="2_oqdqd"]
[ext_resource type="PackedScene" uid="uid://dldnbpubu2jgm" path="res://components/Weapons/GrassWall.tscn" id="3_0omr3"]
+[ext_resource type="PackedScene" uid="uid://blwoev5sencdh" path="res://components/Weapons/Gobo.tscn" id="3_jluqw"]
[ext_resource type="PackedScene" uid="uid://c0n3igy4hucrg" path="res://components/Weapons/PurpleCrystal.tscn" id="3_joj4g"]
[ext_resource type="AudioStream" uid="uid://cdrevrq7n6yqa" path="res://resources/sounds/effect/Boing.mp3" id="4_66s6c"]
[ext_resource type="AudioStream" uid="uid://benyec5bqni0b" path="res://resources/sounds/effect/Chomp.wav" id="4_k0yme"]
@@ -59,10 +60,13 @@ metadata/_edit_vertical_guides_ = [71.0]
[node name="weaponStore" parent="." index="1"]
process_mode = 4
-[node name="PurpleCrystal" parent="weaponStore" index="0" instance=ExtResource("3_joj4g")]
+[node name="Gobo" parent="weaponStore" index="0" instance=ExtResource("3_jluqw")]
+offset_bottom = 446.0
+
+[node name="PurpleCrystal" parent="weaponStore" index="1" instance=ExtResource("3_joj4g")]
offset_bottom = 350.0
-[node name="GrassWall" parent="weaponStore" index="1" instance=ExtResource("3_0omr3")]
+[node name="GrassWall" parent="weaponStore" index="2" instance=ExtResource("3_0omr3")]
[node name="sprint" parent="sounds" index="0"]
stream = ExtResource("4_66s6c")
diff --git a/components/Summons/Gobo.tscn b/components/Summons/Gobo.tscn
new file mode 100644
index 0000000..c313bae
--- /dev/null
+++ b/components/Summons/Gobo.tscn
@@ -0,0 +1,46 @@
+[gd_scene load_steps=7 format=3 uid="uid://b2ilo4ag801m2"]
+
+[ext_resource type="PackedScene" uid="uid://cvogxi7mktumf" path="res://components/Abstracts/EntityBase.tscn" id="1_hgynr"]
+[ext_resource type="Texture2D" uid="uid://xen2edbhf052" path="res://resources/characters/gobo/gobo-a.svg" id="2_e0tdx"]
+[ext_resource type="Script" uid="uid://cqax27sw0wlme" path="res://scripts/Contents/Summons/Gobo.gd" id="2_ftr65"]
+[ext_resource type="Texture2D" uid="uid://s12imwmfics6" path="res://resources/characters/gobo/gobo-b.svg" id="3_ftr65"]
+[ext_resource type="Texture2D" uid="uid://d38bjxoowbg7t" path="res://resources/characters/gobo/gobo-c.svg" id="4_w2qsx"]
+
+[sub_resource type="SpriteFrames" id="SpriteFrames_0xeeo"]
+animations = [{
+"frames": [{
+"duration": 1.0,
+"texture": ExtResource("2_e0tdx")
+}],
+"loop": true,
+"name": &"idle",
+"speed": 5.0
+}, {
+"frames": [{
+"duration": 1.0,
+"texture": ExtResource("2_e0tdx")
+}, {
+"duration": 1.0,
+"texture": ExtResource("3_ftr65")
+}, {
+"duration": 1.0,
+"texture": ExtResource("4_w2qsx")
+}],
+"loop": true,
+"name": &"walk",
+"speed": 5.0
+}]
+
+[node name="Gobo" instance=ExtResource("1_hgynr")]
+script = ExtResource("2_ftr65")
+attraction = 0.0
+displayName = "Gobo"
+
+[node name="texture" parent="." index="3"]
+sprite_frames = SubResource("SpriteFrames_0xeeo")
+animation = &"walk"
+frame = 2
+frame_progress = 0.92641157
+
+[node name="statebar" parent="." index="4"]
+position = Vector2(0, -122)
diff --git a/components/Weapons/Gobo.tscn b/components/Weapons/Gobo.tscn
new file mode 100644
index 0000000..db5c642
--- /dev/null
+++ b/components/Weapons/Gobo.tscn
@@ -0,0 +1,39 @@
+[gd_scene load_steps=4 format=3 uid="uid://blwoev5sencdh"]
+
+[ext_resource type="PackedScene" uid="uid://ckq2cq6m23hq3" path="res://components/Abstracts/WeaponCardBase.tscn" id="1_0udcw"]
+[ext_resource type="Script" uid="uid://cbg3xkg1giv35" path="res://scripts/Contents/Weapons/Gobo.gd" id="2_7yxbe"]
+[ext_resource type="Texture2D" uid="uid://xen2edbhf052" path="res://resources/characters/gobo/gobo-a.svg" id="2_tw58e"]
+
+[node name="Gobo" instance=ExtResource("1_0udcw")]
+script = ExtResource("2_7yxbe")
+avatarTexture = ExtResource("2_tw58e")
+displayName = "Gobo"
+quality = 4
+typeTopic = 4
+store = {
+"atk": 50,
+"health": 200,
+"percent": 0.1
+}
+storeType = {
+"atk": 1,
+"health": 1,
+"percent": 2
+}
+descriptionTemplate = "召唤[b]Gobo[/b],Gobo会自主行动,每受到$atk点伤害后会发射一枚[b]疗愈导弹[/b]。
+[b]疗愈导弹[/b]命中障碍物或友军时对其产生Gobo剩余生命值×$percent点的治疗。
+Gobo初始拥有$health点生命值。"
+cooldown = 1000.0
+
+[node name="avatar" parent="container/info" index="0"]
+texture = ExtResource("2_tw58e")
+
+[node name="name" parent="container/info" index="2"]
+displayName = "Gobo"
+quality = 4
+typeTopic = 4
+
+[node name="description" parent="container" index="2"]
+text = "[center]召唤[b]Gobo[/b],Gobo会自主行动,每受到[color=cyan]50[/color]点伤害后会发射一枚[b]疗愈导弹[/b]。
+[b]疗愈导弹[/b]命中障碍物或友军时对其产生Gobo剩余生命值×[color=cyan]10.0%[/color]点的治疗。
+Gobo初始拥有[color=cyan]200[/color]点生命值。[/center]"
diff --git a/resources/characters/gobo/gobo-a.svg b/resources/characters/gobo/gobo-a.svg
new file mode 100644
index 0000000..a117c67
--- /dev/null
+++ b/resources/characters/gobo/gobo-a.svg
@@ -0,0 +1,19 @@
+
\ No newline at end of file
diff --git a/resources/characters/gobo/gobo-a.svg.import b/resources/characters/gobo/gobo-a.svg.import
new file mode 100644
index 0000000..56073bf
--- /dev/null
+++ b/resources/characters/gobo/gobo-a.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://xen2edbhf052"
+path="res://.godot/imported/gobo-a.svg-324026b3e192456adada726ade96da2d.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://resources/characters/gobo/gobo-a.svg"
+dest_files=["res://.godot/imported/gobo-a.svg-324026b3e192456adada726ade96da2d.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+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/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+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
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/resources/characters/gobo/gobo-b.svg b/resources/characters/gobo/gobo-b.svg
new file mode 100644
index 0000000..1622b6b
--- /dev/null
+++ b/resources/characters/gobo/gobo-b.svg
@@ -0,0 +1,19 @@
+
\ No newline at end of file
diff --git a/resources/characters/gobo/gobo-b.svg.import b/resources/characters/gobo/gobo-b.svg.import
new file mode 100644
index 0000000..ef7baf1
--- /dev/null
+++ b/resources/characters/gobo/gobo-b.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://s12imwmfics6"
+path="res://.godot/imported/gobo-b.svg-075dcd98d32f1272ba543e817534f6fc.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://resources/characters/gobo/gobo-b.svg"
+dest_files=["res://.godot/imported/gobo-b.svg-075dcd98d32f1272ba543e817534f6fc.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+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/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+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
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/resources/characters/gobo/gobo-c.svg b/resources/characters/gobo/gobo-c.svg
new file mode 100644
index 0000000..fe18434
--- /dev/null
+++ b/resources/characters/gobo/gobo-c.svg
@@ -0,0 +1,19 @@
+
\ No newline at end of file
diff --git a/resources/characters/gobo/gobo-c.svg.import b/resources/characters/gobo/gobo-c.svg.import
new file mode 100644
index 0000000..510d403
--- /dev/null
+++ b/resources/characters/gobo/gobo-c.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://d38bjxoowbg7t"
+path="res://.godot/imported/gobo-c.svg-7d92174bbaa3236d452fc842786da9f3.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://resources/characters/gobo/gobo-c.svg"
+dest_files=["res://.godot/imported/gobo-c.svg-7d92174bbaa3236d452fc842786da9f3.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+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/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+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
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/resources/items/apple-white.png b/resources/items/apple-white.png
new file mode 100644
index 0000000000000000000000000000000000000000..ee4bef797586e58a10a7487514684f9fb7ea3972
GIT binary patch
literal 2441
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
Hu0mjfEof*X
literal 0
HcmV?d00001
diff --git a/resources/items/apple-white.png.import b/resources/items/apple-white.png.import
new file mode 100644
index 0000000..32e61bd
--- /dev/null
+++ b/resources/items/apple-white.png.import
@@ -0,0 +1,40 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://dpvk6pja35rdb"
+path="res://.godot/imported/apple-white.png-d39950409511c2e490d5c9c504fbd06c.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://resources/items/apple-white.png"
+dest_files=["res://.godot/imported/apple-white.png-d39950409511c2e490d5c9c504fbd06c.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+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/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+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
diff --git a/scripts/Contents/Bullets/HealingMissle.gd b/scripts/Contents/Bullets/HealingMissle.gd
new file mode 100644
index 0000000..7bdc218
--- /dev/null
+++ b/scripts/Contents/Bullets/HealingMissle.gd
@@ -0,0 +1,5 @@
+extends BulletBase
+class_name HealingMissleBullet
+
+func ai():
+ PresetBulletAI.forward(self, rotation)
diff --git a/scripts/Contents/Bullets/HealingMissle.gd.uid b/scripts/Contents/Bullets/HealingMissle.gd.uid
new file mode 100644
index 0000000..4561a5b
--- /dev/null
+++ b/scripts/Contents/Bullets/HealingMissle.gd.uid
@@ -0,0 +1 @@
+uid://d2ubbdwexom6t
diff --git a/scripts/Contents/Summons/Gobo.gd b/scripts/Contents/Summons/Gobo.gd
new file mode 100644
index 0000000..2953bb8
--- /dev/null
+++ b/scripts/Contents/Summons/Gobo.gd
@@ -0,0 +1,32 @@
+extends SummonBase
+class_name GoboSummon
+
+var percent: float = 0.0
+var healthSinceLastLaunch: float = 0
+
+func initHealth(maxHealth: float):
+ super.initHealth(maxHealth)
+ healthSinceLastLaunch = maxHealth
+
+func register():
+ fields[FieldStore.Entity.MOVEMENT_SPEED] = 1.5
+ healthChanged.connect(
+ func(newHealth):
+ if healthSinceLastLaunch - newHealth >= 1:
+ launch()
+ healthSinceLastLaunch = newHealth
+ )
+func ai():
+ var target = BulletTool.findClosetBulletCanDamage(position, get_tree(), self)
+ if is_instance_valid(target):
+ move(target.position - position)
+
+func launch():
+ for bullet in BulletBase.generate(
+ ComponentManager.getBullet("HealingMissle"),
+ self,
+ position,
+ position.angle_to_point(EntityTool.findClosetEntity(myMaster.position, get_tree(), isPlayer(), !isPlayer(), [self]).position)
+ ):
+ if bullet is HealingMissleBullet:
+ bullet.baseDamage = health * percent * -1
diff --git a/scripts/Contents/Summons/Gobo.gd.uid b/scripts/Contents/Summons/Gobo.gd.uid
new file mode 100644
index 0000000..ec06fc2
--- /dev/null
+++ b/scripts/Contents/Summons/Gobo.gd.uid
@@ -0,0 +1 @@
+uid://cqax27sw0wlme
diff --git a/scripts/Contents/Weapons/Gobo.gd b/scripts/Contents/Weapons/Gobo.gd
new file mode 100644
index 0000000..8d96fe7
--- /dev/null
+++ b/scripts/Contents/Weapons/Gobo.gd
@@ -0,0 +1,13 @@
+@tool
+extends Weapon
+
+func update(to: int, origin: Dictionary, _entity: EntityBase):
+ origin["health"] += 5 * to * soulLevel
+ origin["percent"] += 0.02 * to * soulLevel
+ return origin
+func attack(entity: EntityBase):
+ var gobo = entity.summon(ComponentManager.getSummon("Gobo"))
+ if gobo is GoboSummon:
+ gobo.percent = readStore("percent")
+ gobo.initHealth(readStore("health"))
+ return true
diff --git a/scripts/Contents/Weapons/Gobo.gd.uid b/scripts/Contents/Weapons/Gobo.gd.uid
new file mode 100644
index 0000000..a7aa8fb
--- /dev/null
+++ b/scripts/Contents/Weapons/Gobo.gd.uid
@@ -0,0 +1 @@
+uid://cbg3xkg1giv35
diff --git a/scripts/Contents/Weapons/Shield.gd b/scripts/Contents/Weapons/Shield.gd
index 35f14ad..53cbdca 100644
--- a/scripts/Contents/Weapons/Shield.gd
+++ b/scripts/Contents/Weapons/Shield.gd
@@ -7,7 +7,6 @@ func update(to: int, origin: Dictionary, _entity: EntityBase):
return origin
func attack(entity: EntityBase):
var summon = entity.summon(ComponentManager.getSummon("Shield"))
- if !summon: return true
- summon.fields[FieldStore.Entity.MAX_HEALTH] = readStore("atk")
- summon.health = summon.fields[FieldStore.Entity.MAX_HEALTH]
+ if summon:
+ summon.initHealth(readStore("atk"))
return true
diff --git a/scripts/Statemachine/BulletBase.gd b/scripts/Statemachine/BulletBase.gd
index 2495bcb..faa21b9 100644
--- a/scripts/Statemachine/BulletBase.gd
+++ b/scripts/Statemachine/BulletBase.gd
@@ -10,7 +10,7 @@ class_name BulletBase
@export var penerateDamageReduction: float = 0.0
@export var lifeDistance: float = -1 # -1表示无限距离
@export var lifeTime: float = -1 # -1表示无限时间
-@export var indisDamage: bool = false # 是否无差别伤害(不区分敌我)
+@export var allowFriendlyDamage: bool = false # 是否无差别伤害(不区分敌我)
@export var canDamageSelf: bool = false # 是否可以伤害发射者
@export var autoSpawnAnimation: bool = false
@export var autoLoopAnimation: bool = false
diff --git a/scripts/Statemachine/EntityBase.gd b/scripts/Statemachine/EntityBase.gd
index 9f9172d..f600f1e 100644
--- a/scripts/Statemachine/EntityBase.gd
+++ b/scripts/Statemachine/EntityBase.gd
@@ -200,6 +200,10 @@ func _physics_process(_delta: float) -> void:
trailParticle.emitting = trailing
# 通用方法
+func initHealth(maxHealth: float):
+ fields[FieldStore.Entity.MAX_HEALTH] = maxHealth
+ health = maxHealth
+ statebar.forceSync()
func rebuildWeaponIcons():
if isPlayer():
for i in UIState.skillIconContainer.get_children():
diff --git a/scripts/Tools/BulletTool.gd b/scripts/Tools/BulletTool.gd
index 1bfaa25..4fa0c13 100644
--- a/scripts/Tools/BulletTool.gd
+++ b/scripts/Tools/BulletTool.gd
@@ -8,9 +8,12 @@ static func fromArea(area: Area2D) -> BulletBase:
static func canDamage(bullet: BulletBase, target: EntityBase) -> bool:
if !bullet or !target or !bullet.launcher: return false
if target.currentInvinsible: return false
- if !bullet.canDamageSelf && target == bullet.launcher: return false
if !GameRule.allowFriendlyFire:
- if target.isPlayer() == bullet.launcher.isPlayer() and bullet.launcher.currentFocusedBoss != target: return false
+ if target.isPlayer() == bullet.launcher.isPlayer() and bullet.launcher.currentFocusedBoss != target and !bullet.allowFriendlyDamage:
+ return false
+ if !bullet.canDamageSelf:
+ if target == bullet.launcher:
+ return false
return true
static func findClosetBullet(to: Vector2, fromTree: SceneTree) -> BulletBase:
var result: BulletBase = null