1
1
mirror of https://github.com/Rundll86/Dog-Lynx-And-HCN.git synced 2026-05-28 06:51:54 +08:00

feat(子弹系统): 重构伤害计算并添加音效

将子弹的伤害属性从`damage`重命名为`baseDamage`,并引入`damageMultipliers`数组支持多段伤害
为火山武器添加三段攻击音效并调整伤害倍率
更新相关武器和子弹脚本以适配新的伤害系统
This commit is contained in:
2025-11-22 08:42:51 +08:00
parent b263122a52
commit 46ea2fc775
28 changed files with 145 additions and 31 deletions
+53 -1
View File
@@ -1,8 +1,11 @@
[gd_scene load_steps=20 format=3 uid="uid://8uepi7uql314"] [gd_scene load_steps=23 format=3 uid="uid://8uepi7uql314"]
[ext_resource type="PackedScene" uid="uid://crtdkysmnkith" path="res://components/Abstracts/BulletBase.tscn" id="1_gd3m7"] [ext_resource type="PackedScene" uid="uid://crtdkysmnkith" path="res://components/Abstracts/BulletBase.tscn" id="1_gd3m7"]
[ext_resource type="Script" uid="uid://ci5hswfhck5as" path="res://scripts/Contents/Bullets/Volcano.gd" id="2_w1utg"] [ext_resource type="Script" uid="uid://ci5hswfhck5as" path="res://scripts/Contents/Bullets/Volcano.gd" id="2_w1utg"]
[ext_resource type="Texture2D" uid="uid://ctmxadaowx5ps" path="res://resources/weapons/Volcano.webp" id="2_wwxm2"] [ext_resource type="Texture2D" uid="uid://ctmxadaowx5ps" path="res://resources/weapons/Volcano.webp" id="2_wwxm2"]
[ext_resource type="AudioStream" uid="uid://cer3lxbxqw5pq" path="res://resources/sounds/effect/sword1.mp3" id="3_6sp0s"]
[ext_resource type="AudioStream" uid="uid://cfwu55dfgs4bl" path="res://resources/sounds/effect/sword2.mp3" id="4_1sgli"]
[ext_resource type="AudioStream" uid="uid://bm2o8hu7nyqh1" path="res://resources/sounds/effect/sword3.mp3" id="5_b5nxd"]
[sub_resource type="Animation" id="Animation_w1utg"] [sub_resource type="Animation" id="Animation_w1utg"]
length = 0.001 length = 0.001
@@ -97,6 +100,18 @@ tracks/7/keys = {
"points": PackedFloat32Array(1, -0.25, 0, 0.25, 0), "points": PackedFloat32Array(1, -0.25, 0, 0.25, 0),
"times": PackedFloat32Array(0) "times": PackedFloat32Array(0)
} }
tracks/8/type = "value"
tracks/8/imported = false
tracks/8/enabled = true
tracks/8/path = NodePath("%texture/..:usingDamageMultiplier")
tracks/8/interp = 1
tracks/8/loop_wrap = true
tracks/8/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [0]
}
[sub_resource type="Animation" id="Animation_oinqg"] [sub_resource type="Animation" id="Animation_oinqg"]
resource_name = "destroy" resource_name = "destroy"
@@ -218,6 +233,41 @@ tracks/8/keys = {
"method": &"generateShadow" "method": &"generateShadow"
}] }]
} }
tracks/9/type = "value"
tracks/9/imported = false
tracks/9/enabled = true
tracks/9/path = NodePath("%texture/..:usingDamageMultiplier")
tracks/9/interp = 1
tracks/9/loop_wrap = true
tracks/9/keys = {
"times": PackedFloat32Array(0, 0.6, 1.2),
"transitions": PackedFloat32Array(1, 1, 1),
"update": 1,
"values": [0, 1, 2]
}
tracks/10/type = "audio"
tracks/10/imported = false
tracks/10/enabled = true
tracks/10/path = NodePath("%textureSword/audio")
tracks/10/interp = 1
tracks/10/loop_wrap = true
tracks/10/keys = {
"clips": [{
"end_offset": 0.0,
"start_offset": 0.0,
"stream": ExtResource("3_6sp0s")
}, {
"end_offset": 0.0,
"start_offset": 0.0,
"stream": ExtResource("4_1sgli")
}, {
"end_offset": 0.0,
"start_offset": 0.0,
"stream": ExtResource("5_b5nxd")
}],
"times": PackedFloat32Array(0, 0.6, 1.2)
}
tracks/10/use_blend = true
[sub_resource type="AnimationLibrary" id="AnimationLibrary_w1utg"] [sub_resource type="AnimationLibrary" id="AnimationLibrary_w1utg"]
_data = { _data = {
@@ -308,6 +358,8 @@ scale = Vector2(0.9999999, 0.9999999)
amount = 200 amount = 200
process_material = SubResource("ParticleProcessMaterial_xrrxo") process_material = SubResource("ParticleProcessMaterial_xrrxo")
[node name="audio" type="AudioStreamPlayer2D" parent="texture/anchor/textureSword" index="1"]
[node name="hitbox" parent="." index="1"] [node name="hitbox" parent="." index="1"]
position = Vector2(245.25, 0) position = Vector2(245.25, 0)
shape = SubResource("RectangleShape2D_w1utg") shape = SubResource("RectangleShape2D_w1utg")
+4 -4
View File
@@ -15,9 +15,9 @@ costBeachball = 300
store = { store = {
"atk": 15.0, "atk": 15.0,
"dmg1": 1.0, "dmg1": 1.0,
"dmg2": 0.5, "dmg2": 0.75,
"dmg3": 2.0, "dmg3": 3.0,
"rotate": 0.1 "rotate": 0.05
} }
storeType = { storeType = {
"atk": 1, "atk": 1,
@@ -45,4 +45,4 @@ quality = 4
typeTopic = 2 typeTopic = 2
[node name="description" parent="container" index="2"] [node name="description" parent="container" index="2"]
text = "[center]召唤1支[b]火山[/b],以[color=cyan]10%[/color]的效率跟随鼠标指向,进行3段攻击。基础接触伤害为[color=cyan]15[/color],三段造成的伤害分别为[color=cyan]100%[/color][color=cyan]50%[/color][color=cyan]200%[/color]。[/center]" text = "[center]召唤1支[b]火山[/b],以[color=cyan]5%[/color]的效率跟随鼠标指向,进行3段攻击。基础接触伤害为[color=cyan]15[/color],三段造成的伤害分别为[color=cyan]100%[/color][color=cyan]75%[/color][color=cyan]300%[/color]。[/center]"
Binary file not shown.
+19
View File
@@ -0,0 +1,19 @@
[remap]
importer="mp3"
type="AudioStreamMP3"
uid="uid://cer3lxbxqw5pq"
path="res://.godot/imported/sword1.mp3-348dbff4d27421d2476a13d63c45effb.mp3str"
[deps]
source_file="res://resources/sounds/effect/sword1.mp3"
dest_files=["res://.godot/imported/sword1.mp3-348dbff4d27421d2476a13d63c45effb.mp3str"]
[params]
loop=false
loop_offset=0
bpm=0
beat_count=0
bar_beats=4
Binary file not shown.
+19
View File
@@ -0,0 +1,19 @@
[remap]
importer="mp3"
type="AudioStreamMP3"
uid="uid://cfwu55dfgs4bl"
path="res://.godot/imported/sword2.mp3-768d8bd5124ad729116b92c691ace04c.mp3str"
[deps]
source_file="res://resources/sounds/effect/sword2.mp3"
dest_files=["res://.godot/imported/sword2.mp3-768d8bd5124ad729116b92c691ace04c.mp3str"]
[params]
loop=false
loop_offset=0
bpm=0
beat_count=0
bar_beats=4
Binary file not shown.
+19
View File
@@ -0,0 +1,19 @@
[remap]
importer="mp3"
type="AudioStreamMP3"
uid="uid://bm2o8hu7nyqh1"
path="res://.godot/imported/sword3.mp3-9a333562648f03db1b1227875cf2428b.mp3str"
[deps]
source_file="res://resources/sounds/effect/sword3.mp3"
dest_files=["res://.godot/imported/sword3.mp3-9a333562648f03db1b1227875cf2428b.mp3str"]
[params]
loop=false
loop_offset=0
bpm=0
beat_count=0
bar_beats=4
+1 -1
View File
@@ -18,7 +18,7 @@ func ai():
trail.emitting = true trail.emitting = true
hitbox.disabled = false hitbox.disabled = false
speed = (1 - lifeDistancePercent()) * initialSpeed speed = (1 - lifeDistancePercent()) * initialSpeed
damage = speed * atk baseDamage = speed * atk
PresetBulletAI.forward(self, rotation) PresetBulletAI.forward(self, rotation)
if speed < 1: if speed < 1:
tryDestroy() tryDestroy()
+1 -1
View File
@@ -9,7 +9,7 @@ func register():
func spawn(): func spawn():
CameraManager.shake(5000, 100) # 激光会运行5秒(5000毫秒),期间震屏超高强度 CameraManager.shake(5000, 100) # 激光会运行5秒(5000毫秒),期间震屏超高强度
CameraManager.playAnimation("bigLaser") CameraManager.playAnimation("bigLaser")
damage *= launcher.fields[FieldStore.Entity.ATTACK_SPEED] baseDamage *= launcher.fields[FieldStore.Entity.ATTACK_SPEED]
func ai(): func ai():
rotation = lerp_angle(rotation, ((get_global_mouse_position() - position).angle()), 0.1) rotation = lerp_angle(rotation, ((get_global_mouse_position() - position).angle()), 0.1)
position = launcher.texture.global_position position = launcher.texture.global_position
@@ -13,7 +13,7 @@ var forwarded: bool = false
func register(): func register():
speed = 1 speed = 1
damage = 1 baseDamage = 1
func spawn(): func spawn():
myColor = allColor.gradient.sample(randf()) myColor = allColor.gradient.sample(randf())
superlight.material = superlight.material.duplicate() superlight.material = superlight.material.duplicate()
@@ -5,7 +5,7 @@ extends BulletBase
var myColor: Color var myColor: Color
func register(): func register():
damage = 1 baseDamage = 1
penerate = 1 penerate = 1
func spawn(): func spawn():
myColor = allColor.gradient.sample(randf()) myColor = allColor.gradient.sample(randf())
@@ -10,7 +10,7 @@ extends BulletBase
var myColor: Color var myColor: Color
func register(): func register():
speed = 1 speed = 1
damage = 1 baseDamage = 1
penerate = 1 penerate = 1
func spawn(): func spawn():
myColor = allColor.gradient.sample(randf()) myColor = allColor.gradient.sample(randf())
@@ -11,7 +11,7 @@ var myColor: Color
func register(): func register():
speed = 0 speed = 0
damage = 1 baseDamage = 1
penerate = 1 penerate = 1
func spawn(): func spawn():
myColor = allColor.gradient.sample(randf()) myColor = allColor.gradient.sample(randf())
@@ -15,5 +15,5 @@ func ai():
track.visible = false track.visible = false
hitbox.disabled = false hitbox.disabled = false
PresetBulletAI.forward(self, rotation) PresetBulletAI.forward(self, rotation)
damage = speed / 5 baseDamage = speed / 5
speed *= 1.15 speed *= 1.15
+1 -1
View File
@@ -8,7 +8,7 @@ var splits: float = 10.0
func spawn(): func spawn():
for j in count: for j in count:
for i in BulletBase.generate(ComponentManager.getBullet("PurpleCrystalSmall"), launcher, anchor.global_position, rotation): for i in BulletBase.generate(ComponentManager.getBullet("PurpleCrystalSmall"), launcher, anchor.global_position, rotation):
i.damage = damage i.damage = baseDamage
var dir = Vector2.from_angle(i.rotation).rotated(deg_to_rad(-90)) var dir = Vector2.from_angle(i.rotation).rotated(deg_to_rad(-90))
i.global_position += dir * (count - j * 2) * splits / 2 i.global_position += dir * (count - j * 2) * splits / 2
func ai(): func ai():
+1 -1
View File
@@ -7,7 +7,7 @@ func register():
speed = 0 speed = 0
penerate = 1 penerate = 1
func ai(): func ai():
damage = launcher.velocity.length() / 500 * atk baseDamage = launcher.velocity.length() / 500 * atk
PresetBulletAI.lockLauncher(self, launcher, true) PresetBulletAI.lockLauncher(self, launcher, true)
if !launcher.sprinting: if !launcher.sprinting:
tryDestroy() tryDestroy()
+1 -1
View File
@@ -4,7 +4,7 @@ class_name Diamond
const traceTime = 1500 const traceTime = 1500
func register(): func register():
damage = 2 baseDamage = 2
func ai(): func ai():
PresetBulletAI.forward(self, rotation) PresetBulletAI.forward(self, rotation)
if timeLived() < traceTime: if timeLived() < traceTime:
+1 -1
View File
@@ -2,7 +2,7 @@ extends BulletBase
class_name Pencil class_name Pencil
func register(): func register():
damage = 20 baseDamage = 20
func spawn(): func spawn():
await TickTool.millseconds(1000) await TickTool.millseconds(1000)
hitbox.disabled = false hitbox.disabled = false
+1 -1
View File
@@ -20,7 +20,7 @@ func register():
func(area): func(area):
var bullet = BulletTool.fromArea(area) var bullet = BulletTool.fromArea(area)
if bullet and BulletTool.canDamage(bullet, launcher): if bullet and BulletTool.canDamage(bullet, launcher):
launcher.storeEnergy(damage * 2) launcher.storeEnergy(baseDamage * 2)
) )
func spawn(): func spawn():
modulate = Color(colors[index % colors.size()]) modulate = Color(colors[index % colors.size()])
+1 -1
View File
@@ -2,6 +2,6 @@ extends BulletBase
class_name Star class_name Star
func register(): func register():
damage = 1 baseDamage = 1
func ai(): func ai():
PresetBulletAI.forward(self, rotation) PresetBulletAI.forward(self, rotation)
+1 -1
View File
@@ -25,4 +25,4 @@ func generateShadow():
false, false, true, true false, false, true, true
): ):
if i is VolcanoShadow: if i is VolcanoShadow:
i.damage = damage i.baseDamage = baseDamage
+1 -1
View File
@@ -11,5 +11,5 @@ func attack(entity: EntityBase):
for bullet in BulletBase.generate(ComponentManager.getBullet("BigLaser"), entity, weaponPos, (get_global_mouse_position() - weaponPos).angle()): for bullet in BulletBase.generate(ComponentManager.getBullet("BigLaser"), entity, weaponPos, (get_global_mouse_position() - weaponPos).angle()):
var bigLaser: BigLaser = bullet var bigLaser: BigLaser = bullet
bigLaser.dotTime = readStore("time") * 1000 bigLaser.dotTime = readStore("time") * 1000
bigLaser.damage = readStore("atk") bigLaser.baseDamage = readStore("atk")
return true return true
+1 -1
View File
@@ -10,7 +10,7 @@ func attack(entity: EntityBase):
var weaponPos = entity.findWeaponAnchor("normal") var weaponPos = entity.findWeaponAnchor("normal")
for j in BulletBase.generate(ComponentManager.getBullet("MushroomPickaxe"), entity, entity.texture.global_position, weaponPos.angle_to_point(get_global_mouse_position())): for j in BulletBase.generate(ComponentManager.getBullet("MushroomPickaxe"), entity, entity.texture.global_position, weaponPos.angle_to_point(get_global_mouse_position())):
var bullet: MushroomPickaxe = j var bullet: MushroomPickaxe = j
bullet.damage = readStore("atk") bullet.baseDamage = readStore("atk")
bullet.rate = readStore("rate") bullet.rate = readStore("rate")
bullet.count = readStore("count") bullet.count = readStore("count")
return true return true
+1 -1
View File
@@ -9,6 +9,6 @@ func attack(entity: EntityBase):
var weaponPos = entity.findWeaponAnchor("normal") var weaponPos = entity.findWeaponAnchor("normal")
for j in BulletBase.generate(ComponentManager.getBullet("NuclearBomb"), entity, weaponPos, weaponPos.angle_to_point(get_global_mouse_position())): for j in BulletBase.generate(ComponentManager.getBullet("NuclearBomb"), entity, weaponPos, weaponPos.angle_to_point(get_global_mouse_position())):
var bullet: NuclearBomb = j var bullet: NuclearBomb = j
bullet.damage = readStore("atk") bullet.baseDamage = readStore("atk")
bullet.radius = readStore("radius") bullet.radius = readStore("radius")
return true return true
+1 -1
View File
@@ -13,7 +13,7 @@ func attack(entity: EntityBase):
for i in range(int(randi_range(readStore("mincount"), readStore("maxcount")))): for i in range(int(randi_range(readStore("mincount"), readStore("maxcount")))):
for j in BulletBase.generate(ComponentManager.getBullet("VectorStar"), entity, weaponPos, deg_to_rad(randf_range(0, 360))): for j in BulletBase.generate(ComponentManager.getBullet("VectorStar"), entity, weaponPos, deg_to_rad(randf_range(0, 360))):
var bullet: VectorStar = j var bullet: VectorStar = j
bullet.damage = readStore("atk") bullet.baseDamage = readStore("atk")
bullet.tracer = EntityTool.findClosetEntity(get_global_mouse_position(), get_tree(), !entity.isPlayer(), entity.isPlayer()) bullet.tracer = EntityTool.findClosetEntity(get_global_mouse_position(), get_tree(), !entity.isPlayer(), entity.isPlayer())
bullet.forwardTime = readStore("forwardtime") * 1000 bullet.forwardTime = readStore("forwardtime") * 1000
return true return true
+7 -2
View File
@@ -2,7 +2,11 @@
extends Weapon extends Weapon
func update(to: int, origin: Dictionary, _entity: EntityBase): func update(to: int, origin: Dictionary, _entity: EntityBase):
origin["rotate"] += 0.015 * to * soulLevel origin["rotate"] += 0.005 * to * soulLevel
origin["dmg1"] += 0.03 * to * soulLevel
origin["dmg2"] += 0.03 * to * soulLevel
origin["dmg3"] += 0.03 * to * soulLevel
origin["atk"] += 1 * to * soulLevel
return origin return origin
func attack(entity: EntityBase): func attack(entity: EntityBase):
for j in BulletBase.generate( for j in BulletBase.generate(
@@ -12,5 +16,6 @@ func attack(entity: EntityBase):
entity.position.angle_to_point(entity.get_global_mouse_position()), false, false, true, true entity.position.angle_to_point(entity.get_global_mouse_position()), false, false, true, true
): ):
var bullet: Volcano = j var bullet: Volcano = j
bullet.damage = readStore("atk") bullet.baseDamage = readStore("atk")
bullet.rotates = readStore("rotate") bullet.rotates = readStore("rotate")
bullet.damageMultipliers = [readStore("dmg1"), readStore("dmg2"), readStore("dmg3")]
+6 -6
View File
@@ -3,7 +3,9 @@ class_name BulletBase
@export var displayName: String = "未知子弹" @export var displayName: String = "未知子弹"
@export var speed: float = 10.0 @export var speed: float = 10.0
@export var damage: float = 10.0 @export var baseDamage: float = 10.0
@export var damageMultipliers: Array[float] = [1.0]
@export var usingDamageMultiplier: int = 0
@export var penerate: float = 0.0 @export var penerate: float = 0.0
@export var penerateDamageReduction: float = 0.0 @export var penerateDamageReduction: float = 0.0
@export var lifeDistance: float = -1 # -1表示无限距离 @export var lifeDistance: float = -1 # -1表示无限距离
@@ -31,12 +33,10 @@ var isChildSplit: bool = false
var isChildRefract: bool = false var isChildRefract: bool = false
var initialSpeed: float = 0 var initialSpeed: float = 0
var originalDamage: float = 0 var originalDamage: float = 0
var damageMultiplier: Array[float] = [1.0]
var usingDamageMultiplier: int = 0
func _ready(): func _ready():
initialSpeed = speed initialSpeed = speed
originalDamage = damage originalDamage = baseDamage
if launcher.isSummon(): if launcher.isSummon():
launcherSummoned = launcher launcherSummoned = launcher
launcher = launcher.myMaster launcher = launcher.myMaster
@@ -87,7 +87,7 @@ func _physics_process(_delta: float) -> void:
tryDestroy() tryDestroy()
func getDamage(): func getDamage():
return originalDamage * damageMultiplier[usingDamageMultiplier] return originalDamage * damageMultipliers[usingDamageMultiplier]
func hit(target: Node): func hit(target: Node):
var entity: EntityBase = EntityTool.fromHurtbox(target) var entity: EntityBase = EntityTool.fromHurtbox(target)
if !entity || !launcher: return if !entity || !launcher: return
@@ -96,7 +96,7 @@ func hit(target: Node):
succeedToHit(resultDamage, entity) succeedToHit(resultDamage, entity)
if MathTool.rate(fullPenerate()): if MathTool.rate(fullPenerate()):
penerate -= entity.fields[FieldStore.Entity.PENARATION_RESISTANCE] penerate -= entity.fields[FieldStore.Entity.PENARATION_RESISTANCE]
damage *= 1.0 - penerateDamageReduction baseDamage *= 1.0 - penerateDamageReduction
else: else:
tryDestroy() tryDestroy()
func forward(direction: Vector2): func forward(direction: Vector2):