From 8b14e36031a610d34dfc0da7d4872b6cb6b0960a 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: Sat, 9 May 2026 19:43:44 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E6=88=98=E6=96=97=E7=B3=BB=E7=BB=9F):=20?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=86=85=E4=BC=A4=E6=9C=BA=E5=88=B6=E5=92=8C?= =?UTF-8?q?=E7=88=86=E7=82=B8=E7=B1=BB=E5=9E=8B=E5=AD=90=E5=BC=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 为子弹系统添加新的爆炸类型(MotionType.EXPLOSION) 实现内伤机制,包括内伤子弹和相关逻辑 修改多个子弹场景以使用爆炸类型 调整格挡系统,增加内伤效果 更新武器描述和角色配置 --- components/Bullets/Bengbeng.tscn | 2 +- components/Bullets/InternalDamage.tscn | 30 ++++++ components/Bullets/MagicMissle.tscn | 1 + components/Bullets/NuclearBomb.tscn | 2 +- components/Bullets/QKSword.tscn | 1 + components/Bullets/RedCrystal.tscn | 7 +- components/Characters/MuyangDog.tscn | 16 +++- components/Weapons/DaoStatue.tscn | 10 +- components/Weapons/Tree.tscn | 1 - scripts/Contents/Bullets/InternalDamage.gd | 13 +++ .../Contents/Bullets/InternalDamage.gd.uid | 1 + scripts/Contents/Bullets/Parrier.gd | 94 +++++++++++-------- scripts/Contents/Characters/EnergyBlock.gd | 10 +- scripts/Statemachine/BulletBase.gd | 1 + scripts/Statemachine/CycleTimer.gd | 4 +- scripts/Statemachine/EntityBase.gd | 2 +- 16 files changed, 138 insertions(+), 57 deletions(-) create mode 100644 components/Bullets/InternalDamage.tscn create mode 100644 scripts/Contents/Bullets/InternalDamage.gd create mode 100644 scripts/Contents/Bullets/InternalDamage.gd.uid diff --git a/components/Bullets/Bengbeng.tscn b/components/Bullets/Bengbeng.tscn index 685e669..1a120b0 100644 --- a/components/Bullets/Bengbeng.tscn +++ b/components/Bullets/Bengbeng.tscn @@ -84,7 +84,7 @@ script = ExtResource("2_165xl") displayName = "蹦蹦炸弹" speed = 4.0 baseDamage = 30.0 -motionType = 3 +motionType = 7 lifeTime = 10000.0 autoLoopAnimation = true diff --git a/components/Bullets/InternalDamage.tscn b/components/Bullets/InternalDamage.tscn new file mode 100644 index 0000000..a864664 --- /dev/null +++ b/components/Bullets/InternalDamage.tscn @@ -0,0 +1,30 @@ +[gd_scene format=3 uid="uid://dnjct3fifocnb"] + +[ext_resource type="PackedScene" uid="uid://crtdkysmnkith" path="res://components/Abstracts/BulletBase.tscn" id="1_xwju0"] +[ext_resource type="Texture2D" uid="uid://mo0gjwh5amev" path="res://resources/effects/danger/Effect_Boss_YiGung_Upper1206.png" id="2_0na4i"] +[ext_resource type="Script" uid="uid://d3m2bjkxg82a2" path="res://scripts/Contents/Bullets/InternalDamage.gd" id="2_nsbh7"] + +[sub_resource type="SpriteFrames" id="SpriteFrames_nsbh7"] +animations = [{ +"frames": [{ +"duration": 1.0, +"texture": ExtResource("2_0na4i") +}], +"loop": true, +"name": &"default", +"speed": 5.0 +}] + +[sub_resource type="CircleShape2D" id="CircleShape2D_0na4i"] +radius = 150.0 + +[node name="InternalDamage" unique_id=5571707 instance=ExtResource("1_xwju0")] +script = ExtResource("2_nsbh7") + +[node name="texture" parent="." index="0" unique_id=162977358] +scale = Vector2(0.25103292, 0.25103292) +sprite_frames = SubResource("SpriteFrames_nsbh7") + +[node name="hitbox" parent="." index="1" unique_id=175349408] +shape = SubResource("CircleShape2D_0na4i") +disabled = true diff --git a/components/Bullets/MagicMissle.tscn b/components/Bullets/MagicMissle.tscn index 82f1efb..fdadcfa 100644 --- a/components/Bullets/MagicMissle.tscn +++ b/components/Bullets/MagicMissle.tscn @@ -97,6 +97,7 @@ alpha_curve = SubResource("CurveTexture_3jny5") [node name="MagicMissle" unique_id=5571707 instance=ExtResource("1_4sjx4")] script = ExtResource("2_lrw10") +motionType = 7 penerate = 1.0 penerateDamageReduction = 0.1 diff --git a/components/Bullets/NuclearBomb.tscn b/components/Bullets/NuclearBomb.tscn index 48a704b..bfaa557 100644 --- a/components/Bullets/NuclearBomb.tscn +++ b/components/Bullets/NuclearBomb.tscn @@ -41,7 +41,7 @@ radius = 1000.0 [node name="NuclearBomb" unique_id=432957691 instance=ExtResource("1_dpea6")] script = ExtResource("2_f85ek") displayName = "核弹" -motionType = 3 +motionType = 7 canDamageSelf = true autoDestroyOnHitMap = false diff --git a/components/Bullets/QKSword.tscn b/components/Bullets/QKSword.tscn index 5fe3a5e..05d128a 100644 --- a/components/Bullets/QKSword.tscn +++ b/components/Bullets/QKSword.tscn @@ -124,6 +124,7 @@ script = ExtResource("2_x26jp") displayName = "乾坤剑" speed = 20.0 baseDamage = 25.0 +motionType = 7 penerate = 1.0 penerateDamageReduction = 0.2 lifeTime = 3000.0 diff --git a/components/Bullets/RedCrystal.tscn b/components/Bullets/RedCrystal.tscn index 3a3e6e0..5fd3afd 100644 --- a/components/Bullets/RedCrystal.tscn +++ b/components/Bullets/RedCrystal.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=5 format=3 uid="uid://c0oc8aqfef0tt"] +[gd_scene format=3 uid="uid://c0oc8aqfef0tt"] [ext_resource type="PackedScene" uid="uid://crtdkysmnkith" path="res://components/Abstracts/BulletBase.tscn" id="1_k4d80"] [ext_resource type="Script" uid="uid://bv848wj2ko0y0" path="res://scripts/Contents/Bullets/RedCrystal.gd" id="2_llvlo"] @@ -15,13 +15,14 @@ animations = [{ "speed": 5.0 }] -[node name="RedCrystal" instance=ExtResource("1_k4d80")] +[node name="RedCrystal" unique_id=1424825822 instance=ExtResource("1_k4d80")] script = ExtResource("2_llvlo") displayName = "红水晶" speed = 8.0 +motionType = 7 lifeTime = 3000.0 metadata/_edit_vertical_guides_ = [150.0] -[node name="texture" parent="." index="0"] +[node name="texture" parent="." index="0" unique_id=162977358] modulate = Color(1.2892731, 0.44830602, 0.44830602, 1) sprite_frames = SubResource("SpriteFrames_ns31y") diff --git a/components/Characters/MuyangDog.tscn b/components/Characters/MuyangDog.tscn index 13edfd5..af3703e 100644 --- a/components/Characters/MuyangDog.tscn +++ b/components/Characters/MuyangDog.tscn @@ -2,14 +2,26 @@ [ext_resource type="PackedScene" uid="uid://bs863g2s8r770" path="res://components/Abstracts/PlayerBase.tscn" id="1_y3l4w"] [ext_resource type="Script" uid="uid://bbmb572iba42l" path="res://scripts/Contents/Characters/MuyangDog.gd" id="2_mr6nm"] +[ext_resource type="PackedScene" uid="uid://dt8w2w816tsj0" path="res://components/Weapons/RedCrystal.tscn" id="3_6avmi"] [ext_resource type="PackedScene" uid="uid://u0djqwuuysp8" path="res://components/Weapons/Volcano.tscn" id="3_e236u"] +[ext_resource type="PackedScene" uid="uid://bbrllsqjmx0ie" path="res://components/Weapons/DaoStatue.tscn" id="3_nco02"] [ext_resource type="PackedScene" uid="uid://cx7nogfnv7s8t" path="res://components/Weapons/Tree.tscn" id="4_im5m5"] [node name="MuyangDog" unique_id=1711205167 instance=ExtResource("1_y3l4w")] script = ExtResource("2_mr6nm") displayName = "牧羊犬" -[node name="Volcano" parent="weaponStore" index="0" unique_id=204992396 instance=ExtResource("3_e236u")] +[node name="DaoStatue" parent="weaponStore" index="0" unique_id=265403254 instance=ExtResource("3_nco02")] +offset_right = 352.0 +offset_bottom = 624.0 +debugRebuild = false [node name="Tree" parent="weaponStore" index="1" unique_id=185228402 instance=ExtResource("4_im5m5")] -debugRebuild = false +offset_right = 352.0 +offset_bottom = 1416.0 + +[node name="RedCrystal" parent="weaponStore" index="2" unique_id=1209955095 instance=ExtResource("3_6avmi")] +offset_right = 352.0 +offset_bottom = 452.0 + +[node name="Volcano" parent="weaponStore" index="3" unique_id=204992396 instance=ExtResource("3_e236u")] diff --git a/components/Weapons/DaoStatue.tscn b/components/Weapons/DaoStatue.tscn index ce4c6ec..e650cdf 100644 --- a/components/Weapons/DaoStatue.tscn +++ b/components/Weapons/DaoStatue.tscn @@ -28,7 +28,9 @@ descriptionTemplate = "消耗[color=yellow]3[/color]层气力,挥出[b]无为 每失去[color=yellow]1[/color]点生命值,伤害+$rate1; 无量反击可化解路径上的一切伤害, -每化解[color=yellow]1[/color]点伤害,基础伤害*$rate2。" +每化解[color=yellow]1[/color]点伤害: + 斩击的伤害*$rate2, + 敌人产生[color=yellow]1[/color]点内伤。" sources = Array[String](["Nine Sols"]) tease = "天机不可泄露" needEnergy = 40.0 @@ -55,13 +57,15 @@ typeTopic = 1 text = "Nine Sols" [node name="description" parent="container" parent_id_path=PackedInt32Array(575698869) index="2" unique_id=566230682] -text = "[center]消耗[color=yellow]3[/color]层气力,挥出[b]无为之剑[/b], +text = "消耗[color=yellow]3[/color]层气力,挥出[b]无为之剑[/b], 蓄力一段时间后,发动[b]无量反击[/b], 造成[color=cyan]20[/color]点基础伤害。 每失去[color=yellow]1[/color]点生命值,伤害+[color=cyan]5.0%[/color]; 无量反击可化解路径上的一切伤害, -每化解[color=yellow]1[/color]点伤害,基础伤害*[color=cyan]105.0%[/color]。[/center]" +每化解[color=yellow]1[/color]点伤害: + 斩击的伤害*[color=cyan]105.0%[/color], + 敌人产生[color=yellow]1[/color]点内伤。" [node name="tease" parent="container" parent_id_path=PackedInt32Array(575698869) index="3" unique_id=689277044] visible = true diff --git a/components/Weapons/Tree.tscn b/components/Weapons/Tree.tscn index 3060e19..a3a6dad 100644 --- a/components/Weapons/Tree.tscn +++ b/components/Weapons/Tree.tscn @@ -68,7 +68,6 @@ descriptionTemplate = "进行[b]格挡[/b],化解敌人的攻击。 sources = Array[String](["Nine Sols", "Terraria"]) tease = "卸劲反伤" cooldown = 250.0 -debugRebuild = true [node name="avatar" parent="container/info" parent_id_path=PackedInt32Array(1625294072) index="0" unique_id=1021985889] texture = ExtResource("3_nwamk") diff --git a/scripts/Contents/Bullets/InternalDamage.gd b/scripts/Contents/Bullets/InternalDamage.gd new file mode 100644 index 0000000..4dd7bed --- /dev/null +++ b/scripts/Contents/Bullets/InternalDamage.gd @@ -0,0 +1,13 @@ +extends BulletBase +class_name InternalDamageBullet + +var hoster: EntityBase + +func spawn(): + if is_instance_valid(hoster): + hoster.died.connect(tryDestroy) + hoster.hit.connect( + func(_damage, bullet: BulletBase, _crit): + if bullet.motionType == BulletBase.MotionType.EXPLOSION: + hitbox.set_deferred("disabled", false) + ) diff --git a/scripts/Contents/Bullets/InternalDamage.gd.uid b/scripts/Contents/Bullets/InternalDamage.gd.uid new file mode 100644 index 0000000..4e22c08 --- /dev/null +++ b/scripts/Contents/Bullets/InternalDamage.gd.uid @@ -0,0 +1 @@ +uid://d3m2bjkxg82a2 diff --git a/scripts/Contents/Bullets/Parrier.gd b/scripts/Contents/Bullets/Parrier.gd index 98bc6f8..7bbd571 100644 --- a/scripts/Contents/Bullets/Parrier.gd +++ b/scripts/Contents/Bullets/Parrier.gd @@ -33,6 +33,18 @@ func generateParryBall(bDamage: float): ): if b is ParryBallBullet: b.atk = atk * bDamage +func generateInternalDamage(by: EntityBase, who: EntityBase): + var internalDamages = who.getOrCreateCycleTimer("internalDamages", 3000, 150) + for bullet in BulletBase.generate( + ComponentManager.getBullet("InternalDamage"), + by, + Vector2.ZERO, + 0 + ): + if bullet is InternalDamageBullet: + bullet.baseDamage = atk + bullet.hoster = who + internalDamages.host(bullet) func spawn(): var varians = randi_range(0, 1) @@ -51,45 +63,51 @@ func succeedToHit(_dmg: float, entity: EntityBase): func hitBullet(bullet: BulletBase): # 当前子弹与其他子弹相撞 if !is_instance_valid(launcher): return if BulletTool.canDamage(bullet, launcher): # 其他子弹可以使当前子弹的发射者受伤吗? - if parryiedTimes < maxParryTimes && MathTool.rate(parryRate): # 一个刀光最多格挡多少个敌方子弹? - # 可以格挡 挥舞运动(近战攻击)、射弹运动(远程攻击)和猛冲运动 的子弹,射弹如果被弹反则不会产生气力 - # 魔法运动和召唤运动的子弹虽不能格挡,但是可以储能,吐息运动的子弹会对发射者产生击退 - if bullet.motionType == BulletBase.MotionType.PROJECTILE: - # 无论如何都要生成格挡特效 - parryEffect(bullet) - # 弹反 还是 格挡? - if MathTool.rate(reflectRate): - bullet.look_at(bullet.launcher.getTrackingAnchor()) - bullet.launcher = launcher - bullet.baseDamage = reflectRate * atk - bullet.lifeTime *= 2 - if bullet.freeAfterSpawn && bullet.autoSpawnAnimation: - bullet.animator.speed_scale *= 0.5 - else: - bullet.tryDestroy() + if parryiedTimes < maxParryTimes: + if MathTool.rate(parryRate): # 一个刀光最多格挡多少个敌方子弹? + # 可以格挡 挥舞运动(近战攻击)、射弹运动(远程攻击)和猛冲运动 的子弹,射弹如果被弹反则不会产生气力 + # 魔法运动和召唤运动的子弹虽不能格挡,但是可以储能,吐息运动的子弹会对发射者产生击退 + if bullet.motionType == BulletBase.MotionType.PROJECTILE: + # 无论如何都要生成格挡特效 + parryEffect(bullet) + # 弹反 还是 格挡? + if MathTool.rate(reflectRate): + bullet.look_at(bullet.launcher.getTrackingAnchor()) + bullet.launcher = launcher + bullet.baseDamage = reflectRate * atk + bullet.lifeTime *= 2 + if bullet.freeAfterSpawn && bullet.autoSpawnAnimation: + bullet.animator.speed_scale *= 0.5 + else: + bullet.tryDestroy() + generateParryBall(bullet.baseDamage) + elif bullet.motionType == BulletBase.MotionType.SWING: + parryEffect(bullet) + bullet.hitbox.set_deferred("disabled", true) generateParryBall(bullet.baseDamage) - elif bullet.motionType == BulletBase.MotionType.SWING: - parryEffect(bullet) - bullet.hitbox.set_deferred("disabled", true) - generateParryBall(bullet.baseDamage) - elif bullet.motionType == BulletBase.MotionType.STAB: - parryEffect(bullet) - penerateEffect(bullet.launcher, bullet.launcher.position * 1.01) - bullet.hitbox.set_deferred("disabled", true) - bullet.launcher.takeDamage(atk * reflectRate * bullet.getDamage()) - bullet.launcher.impluse(Vector2.from_angle(bullet.rotation) * -2000) - generateParryBall(bullet.baseDamage) - elif bullet.motionType == BulletBase.MotionType.SPRINT: - parryEffect(bullet) - bullet.tryDestroy() - bullet.launcher.velocity *= -0.1 - generateParryBall(bullet.baseDamage) - elif bullet.motionType == BulletBase.MotionType.BREATH: - penerateEffect(bullet.launcher, launcher.position) - bullet.launcher.impluse(Vector2.from_angle(bullet.rotation) * -500) - elif bullet.motionType == BulletBase.MotionType.SUMMON || bullet.motionType == BulletBase.MotionType.MAGIC: - penerateEffect(bullet.launcher, launcher.position) - launcher.storeEnergy(sqrt(bullet.baseDamage)) + generateInternalDamage(launcher, bullet.launcher) + elif bullet.motionType == BulletBase.MotionType.STAB: + parryEffect(bullet) + penerateEffect(bullet.launcher, bullet.launcher.position * 1.01) + bullet.hitbox.set_deferred("disabled", true) + bullet.launcher.takeDamage(atk * reflectRate * bullet.getDamage()) + bullet.launcher.impluse(Vector2.from_angle(bullet.rotation) * -2000) + generateParryBall(bullet.baseDamage) + generateInternalDamage(launcher, bullet.launcher) + elif bullet.motionType == BulletBase.MotionType.SPRINT: + parryEffect(bullet) + bullet.tryDestroy() + bullet.launcher.velocity *= 0 + generateParryBall(bullet.baseDamage) + generateInternalDamage(launcher, bullet.launcher) + elif bullet.motionType == BulletBase.MotionType.BREATH: + penerateEffect(bullet.launcher, launcher.position) + bullet.launcher.impluse(Vector2.from_angle(bullet.rotation) * -500) + elif bullet.motionType == BulletBase.MotionType.SUMMON || bullet.motionType == BulletBase.MotionType.MAGIC: + penerateEffect(bullet.launcher, launcher.position) + launcher.storeEnergy(sqrt(bullet.baseDamage)) + else: + generateInternalDamage(bullet.launcher, launcher) func refract(_newBullet: BulletBase, _entity: EntityBase, _index: int, _total: int, _lastBullet: float): return null diff --git a/scripts/Contents/Characters/EnergyBlock.gd b/scripts/Contents/Characters/EnergyBlock.gd index cb07ed9..efab7eb 100644 --- a/scripts/Contents/Characters/EnergyBlock.gd +++ b/scripts/Contents/Characters/EnergyBlock.gd @@ -17,11 +17,11 @@ func register(): sprintMultiplier = 30 func ai(): PresetEntityAI.distanceAttack(self , currentFocusedBoss, 0, 300, 0) - # PresetEntityAI.distanceAttack(self , currentFocusedBoss, 500, 1000, 1) - # for i in 5: - # tryAttack(i + 2, [3, 4]) - # if 1 not in attackingStates: - # PresetEntityAI.follow(self , currentFocusedBoss, 200) + PresetEntityAI.distanceAttack(self , currentFocusedBoss, 500, 1000, 1) + for i in 5: + tryAttack(i + 2, [3, 4]) + if 1 not in attackingStates: + PresetEntityAI.follow(self , currentFocusedBoss, 200) func attack(type: int): if type == 0: for bullet in BulletBase.generate(ComponentManager.getBullet("SwingSword"), self , getTrackingAnchor(), getTrackingAnchor().angle_to_point(currentFocusedPosition)): diff --git a/scripts/Statemachine/BulletBase.gd b/scripts/Statemachine/BulletBase.gd index bc9f662..97601f2 100644 --- a/scripts/Statemachine/BulletBase.gd +++ b/scripts/Statemachine/BulletBase.gd @@ -9,6 +9,7 @@ enum MotionType { SPRINT, # 冲撞 BREATH, # 吐息 STAB, # 近战戳刺 + EXPLOSION, # 爆炸 } signal destroied(becauseMap: bool) diff --git a/scripts/Statemachine/CycleTimer.gd b/scripts/Statemachine/CycleTimer.gd index 14f43d8..a44008d 100644 --- a/scripts/Statemachine/CycleTimer.gd +++ b/scripts/Statemachine/CycleTimer.gd @@ -16,7 +16,7 @@ func getStateAngle(index: int): return lifetime() / period * deg_to_rad(360) - deg_to_rad(360.0 * index / len(bullets)) func forceFilter(): bullets = bullets.filter(is_instance_valid) -func apply(): +func apply(where: Vector2): forceFilter() for index in len(bullets): var bullet = bullets[index] @@ -24,7 +24,7 @@ func apply(): var offset = Vector2.from_angle(newStateAngle) bullet.cycleStateAngle = newStateAngle offset.y *= 0.25 - bullet.position = bullet.launcher.position + offset * distance + bullet.position = where + offset * distance bullet.scale = Vector2.ONE * (1 + offset.y) func host(bullet: BulletBase): bullets.append(bullet) diff --git a/scripts/Statemachine/EntityBase.gd b/scripts/Statemachine/EntityBase.gd index 5bd3598..905b5c6 100644 --- a/scripts/Statemachine/EntityBase.gd +++ b/scripts/Statemachine/EntityBase.gd @@ -214,7 +214,7 @@ func _physics_process(_delta: float) -> void: trailParticle.emitting = trailing for cycler in cycleTimers.values(): if cycler is CycleTimer: - cycler.apply() + cycler.apply(position) # 通用方法 func impluse(force: Vector2):