战斗优化

master
chendian 10 months ago
parent e2f8e9a105
commit 92a17820df

@ -1,6 +1,5 @@
[gd_resource type="Resource" script_class="SkillWeaponCfg" load_steps=8 format=3 uid="uid://5ufjc1dso0y8"] [gd_resource type="Resource" script_class="SkillWeaponCfg" load_steps=7 format=3 uid="uid://5ufjc1dso0y8"]
[ext_resource type="Resource" uid="uid://btg40rn2f36c2" path="res://config/attack/sharp_normal_hit_back.tres" id="1_7ai5j"]
[ext_resource type="Resource" uid="uid://d3mcp8sf6qbmd" path="res://config/attack/sharp_normal_hit.tres" id="1_rgi7a"] [ext_resource type="Resource" uid="uid://d3mcp8sf6qbmd" path="res://config/attack/sharp_normal_hit.tres" id="1_rgi7a"]
[ext_resource type="Script" path="res://script/config/skill_weapon_cfg.gd" id="1_uaib7"] [ext_resource type="Script" path="res://script/config/skill_weapon_cfg.gd" id="1_uaib7"]
[ext_resource type="Resource" uid="uid://cy3wwalxeyro0" path="res://config/weapon/long.tres" id="2_8uqiw"] [ext_resource type="Resource" uid="uid://cy3wwalxeyro0" path="res://config/weapon/long.tres" id="2_8uqiw"]
@ -19,7 +18,7 @@ free_lock = false
ignore_push = false ignore_push = false
attack1 = ExtResource("1_rgi7a") attack1 = ExtResource("1_rgi7a")
attack1_box = ExtResource("2_j0l20") attack1_box = ExtResource("2_j0l20")
attack2 = ExtResource("1_7ai5j") attack2 = ExtResource("1_rgi7a")
attack2_box = ExtResource("2_j0l20") attack2_box = ExtResource("2_j0l20")
stance_from = 2 stance_from = 2
stance_to = 3 stance_to = 3

@ -1,4 +1,4 @@
[gd_scene load_steps=26 format=3 uid="uid://8rcvw1vnjcf7"] [gd_scene load_steps=27 format=3 uid="uid://8rcvw1vnjcf7"]
[ext_resource type="Script" path="res://script/character/character.gd" id="1_tonbs"] [ext_resource type="Script" path="res://script/character/character.gd" id="1_tonbs"]
[ext_resource type="Script" path="res://script/character/hitbox.gd" id="2_6xf87"] [ext_resource type="Script" path="res://script/character/hitbox.gd" id="2_6xf87"]
@ -74,9 +74,16 @@ _data = {
} }
[sub_resource type="Curve" id="Curve_e7j3f"] [sub_resource type="Curve" id="Curve_e7j3f"]
max_value = 6.0 max_value = 4.0
_data = [Vector2(0, 6), 0.0, 0.0, 0, 0, Vector2(1, 0), 0.0, 0.0, 0, 0] _data = [Vector2(0, 4), 0.0, 0.0, 0, 0, Vector2(1, 0), 0.0, 0.0, 0, 0]
point_count = 2 point_count = 2
metadata/_snap_enabled = true
[sub_resource type="Curve" id="Curve_55xfs"]
max_value = 0.3
_data = [Vector2(0, 0), 0.0, 0.0, 0, 0, Vector2(0.5, 0.09), 0.555563, 0.555563, 0, 0, Vector2(1, 0.3), 2.8841e-07, 0.0, 0, 0]
point_count = 3
metadata/_snap_enabled = true
[node name="Character" type="CharacterBody3D"] [node name="Character" type="CharacterBody3D"]
collision_layer = 2 collision_layer = 2
@ -138,6 +145,7 @@ script = ExtResource("9_jlnhy")
unique_name_in_owner = true unique_name_in_owner = true
script = ExtResource("8_w84sf") script = ExtResource("8_w84sf")
hit_back_limit_curve = SubResource("Curve_e7j3f") hit_back_limit_curve = SubResource("Curve_e7j3f")
pause_time_limit_curve = SubResource("Curve_55xfs")
[node name="Effect" type="Node3D" parent="."] [node name="Effect" type="Node3D" parent="."]
unique_name_in_owner = true unique_name_in_owner = true

@ -2,6 +2,7 @@ extends Node3D
class_name Battle class_name Battle
@export var hit_back_limit_curve: Curve @export var hit_back_limit_curve: Curve
@export var pause_time_limit_curve: Curve
@onready var character: Character = (get_owner() as Character) @onready var character: Character = (get_owner() as Character)
@onready var status: Status = (%Status as Status) @onready var status: Status = (%Status as Status)
@ -64,9 +65,16 @@ func add_attack(attack: AttackCfg, attack_box: AttackBoxCfg, hit_self: bool = fa
var offset: Vector3 = Vector3(offset_xz.x, offset_y, offset_xz.y) var offset: Vector3 = Vector3(offset_xz.x, offset_y, offset_xz.y)
var shape: Shape3D = attack_box.shape var shape: Shape3D = attack_box.shape
if not shape: if not shape:
print("无效形状:",attack_box.get_res_name()) print("无效形状:", attack_box.get_res_name())
_debug_draw_attack_box(shape, offset) _debug_draw_attack_box(shape, offset)
result = Util.raycast_character(shape, pos+offset, attack_dir) result = Util.raycast_character(shape, pos+offset, attack_dir)
#result按break_level_def排序 确保硬直最高的最后结算
result.sort_custom(
func(a: Character, b: Character):
if a == null: return true
if b == null: return false
return a.get_break_level_def() < b.get_break_level_def()
)
var is_hit: bool = false var is_hit: bool = false
for target: Character in result: for target: Character in result:
if target == null: if target == null:
@ -105,14 +113,18 @@ func settle(from: int, to: int, dir: Vector2, attack: AttackCfg) -> HitResult:
var cfg_from: CharacterCfg = character_from.cfg() var cfg_from: CharacterCfg = character_from.cfg()
var cfg_to: CharacterCfg = character_to.cfg() var cfg_to: CharacterCfg = character_to.cfg()
var is_dead = character_to.get_status("is_dead") var is_dead = character_to.get_status("is_dead")
var is_stun = character_to.get_status("is_stun") var is_stun = character_to.get_status("is_stun")
var hp = character_to.get_status("hp") var hp = character_to.get_status("hp")
var shield = character_to.get_status("shield") var shield = character_to.get_status("shield")
var has_shield = shield > 0 var has_shield: bool = shield > 0
var is_stagger: bool = character_to.has_buff("stagger")
var is_on_floor: bool = character_to.get_status("is_on_floor")
var is_self_on_floor: bool = character_from.get_status("is_on_floor")
var is_floating: bool = attack.is_floating or not character_to.get_status("is_on_floor") var is_floating: bool = attack.is_floating or not is_on_floor
var is_rebound: bool = attack.is_rebound and (character_from == character_to) var is_rebound: bool = attack.is_rebound and (character_from == character_to)
var is_bullet: bool = int(character_from.cfg().type) == Enum.ECharacterType.Bullet
var is_break_shield: bool = false var is_break_shield: bool = false
var is_break_stun: bool = false var is_break_stun: bool = false
@ -120,18 +132,15 @@ func settle(from: int, to: int, dir: Vector2, attack: AttackCfg) -> HitResult:
var is_kill: bool = false var is_kill: bool = false
var is_break_skill: bool = false var is_break_skill: bool = false
var is_break_skill_real: bool = false var is_break_skill_real: bool = false
var pause_time: float = attack.pause_time
var is_bullet: bool = int(character_from.cfg().type) == Enum.ECharacterType.Bullet
#基本伤害 #基本伤害
var damage: float = attack.damage_rate * cfg_from.attack var damage: float = attack.damage_rate * cfg_from.attack
#硬直等级 #硬直等级
var break_level_def: int = cfg_to.shield.break_level_on if has_shield else cfg_to.shield.break_level_off var break_level_def: int = character_to.get_break_level_def()
break_level_def += character_to.get_status("skill_break_level_add")
var break_level_sub: int = clampi(attack.break_level - break_level_def, -1, 3) var break_level_sub: int = clampi(attack.break_level - break_level_def, -1, 3)
is_break_skill_real = break_level_sub > 0 is_break_skill_real = break_level_sub > 0
is_break_skill = is_break_skill_real or not character_to.get_status("is_on_floor") is_break_skill = is_break_skill_real or not is_on_floor
#硬直等级伤害修正 #硬直等级伤害修正
if break_level_sub == -1: if break_level_sub == -1:
damage = 0 damage = 0
@ -139,6 +148,7 @@ func settle(from: int, to: int, dir: Vector2, attack: AttackCfg) -> HitResult:
damage *= 0.5 damage *= 0.5
is_floating = is_break_skill and is_floating is_floating = is_break_skill and is_floating
is_block = not is_break_skill
#造成伤害 #造成伤害
if has_shield: if has_shield:
@ -159,13 +169,21 @@ func settle(from: int, to: int, dir: Vector2, attack: AttackCfg) -> HitResult:
if is_kill: if is_kill:
character_to.add_buff("die", 1) character_to.add_buff("die", 1)
#破盾、格挡、击杀修正 #卡帧时间计算
if break_level_sub < 0: var pause_time: float
pause_time = 0.1 if is_break_skill:
break_level_sub = 0 var break_level_sum_rate: float
elif break_level_sub == 0: if is_stagger:
break_level_sum_rate = attack.break_level / 4.0
else:
break_level_sum_rate = (attack.break_level + break_level_def) / 4.0
pause_time = pause_time_limit_curve.sample(break_level_sum_rate)
#格挡 破盾以及击杀具有固定值
if is_block:
pause_time = 0.05 pause_time = 0.05
if is_break_shield: break_level_sub = 0
elif is_break_shield:
pause_time = 0.2 pause_time = 0.2
break_level_sub = 2 break_level_sub = 2
elif is_kill: elif is_kill:
@ -213,6 +231,12 @@ func settle(from: int, to: int, dir: Vector2, attack: AttackCfg) -> HitResult:
character_to.set_status("is_be_throw", false) character_to.set_status("is_be_throw", false)
status.throw_target = 0 status.throw_target = 0
#碰撞距离计算
var character_dir: Vector2 = character_to.pos2D() - character_from.pos2D()
var dist: float = character_dir.length()
var radius_sum: float = character_from.radius() + character_to.radius()
var dist_rate: float = clamp(dist / radius_sum, 0, 1)
if is_break_skill: if is_break_skill:
#取消技能 #取消技能
if character_to.get_status("is_skill_running"): if character_to.get_status("is_skill_running"):
@ -231,9 +255,10 @@ func settle(from: int, to: int, dir: Vector2, attack: AttackCfg) -> HitResult:
elif break_level_sub == 1: trigger_hit="hit" elif break_level_sub == 1: trigger_hit="hit"
character_to.set_view_trigger(trigger_hit) character_to.set_view_trigger(trigger_hit)
#浮空 击落 强制位移
var hit_up_speed: float = attack.hit_up_speed var hit_up_speed: float = attack.hit_up_speed
var hit_back_speed: float = attack.hit_back_speed var hit_back_speed: float = attack.hit_back_speed
#浮空 击落 强制位移
if is_floating: if is_floating:
character_to.add_buff("stagger", -1) character_to.add_buff("stagger", -1)
character_to.add_buff("floating", -1) character_to.add_buff("floating", -1)
@ -246,9 +271,7 @@ func settle(from: int, to: int, dir: Vector2, attack: AttackCfg) -> HitResult:
3: character_to.add_buff("stagger", 0.9) 3: character_to.add_buff("stagger", 0.9)
hit_up_speed = 0 hit_up_speed = 0
if hit_back_limit_curve: if hit_back_limit_curve:
var character_dir: Vector2 = character_from.pos2D() - character_to.pos2D() hit_back_speed = max(hit_back_limit_curve.sample(dist_rate), hit_back_speed)
var dist = clamp(character_dir.length(), 0, 1)
hit_back_speed = max(hit_back_limit_curve.sample(dist), hit_back_speed)
if not is_break_skill_real: if not is_break_skill_real:
hit_up_speed *= 0.75 hit_up_speed *= 0.75
@ -261,6 +284,15 @@ func settle(from: int, to: int, dir: Vector2, attack: AttackCfg) -> HitResult:
character_from.move_stop() character_from.move_stop()
character_from.set_status("skill_move_stop", true) character_from.set_status("skill_move_stop", true)
#攻击到不可移动的物体 造成自身后退
var is_against_wall: bool = character_to.move_tick(pause_time)
if is_self_on_floor and not is_bullet and (is_against_wall or not is_break_skill):
var self_hit_back_speed = max(hit_back_limit_curve.sample(dist_rate), 2)
character_from.move_stop()
character_from.set_status("skill_move_stop", true)
character_from.set_hit_move(-dir, self_hit_back_speed, 0)
character_from.add_buff("hit_back", attack.hit_up_duration)
#受击pt掉落 #受击pt掉落
if damage>0: if damage>0:
if is_kill || is_break_shield: if is_kill || is_break_shield:
@ -300,17 +332,18 @@ func settle(from: int, to: int, dir: Vector2, attack: AttackCfg) -> HitResult:
_: pass _: pass
#抖动 #抖动
character_to.add_buff("shake_x", 0.2, true) if is_block:
character_from.add_buff("shake_x", 0.2, true)
else:
character_to.add_buff("shake_x", 0.2, true)
#闪白 #闪白
character_to.add_buff("flash_white", 0.04) character_to.add_buff("flash_white", 0.04)
#卡帧 #卡帧
pause_time *= 0.6
if not is_bullet: if not is_bullet:
character_from.set_pause_time(pause_time) character_from.set_pause_time(pause_time)
character_to.set_pause_time(pause_time) character_to.set_pause_time(pause_time)
character_to.move_tick(pause_time)
#全局特效 #全局特效
var has_global_effect: bool = character_from.is_player() or character_to.is_player() var has_global_effect: bool = character_from.is_player() or character_to.is_player()
@ -375,11 +408,13 @@ func cost_mp(value: int):
character.remove_buff("mp_recover") character.remove_buff("mp_recover")
character.add_buff("mp_recover_cd", status.cfg.mp.recover_cd) character.add_buff("mp_recover_cd", status.cfg.mp.recover_cd)
func cost_mp_sub(): func cost_mp_sub():
character.set_status("mp_sub", 0) character.set_status("mp_sub", 0)
character.remove_buff("mp_recover") character.remove_buff("mp_recover")
character.add_buff("mp_recover_cd", status.cfg.mp.recover_cd) character.add_buff("mp_recover_cd", status.cfg.mp.recover_cd)
func check_ground(): skill.on_check_ground(0) func check_ground(): skill.on_check_ground(0)
@ -403,6 +438,7 @@ func cast_sub_character(): skill.on_cast_sub_character()
func hold(): skill.on_hold() func hold(): skill.on_hold()
func stop(): func stop():
move.stop() move.stop()

@ -138,8 +138,8 @@ func move_stop():
set_status("move_dir", Vector2.ZERO) set_status("move_dir", Vector2.ZERO)
move.stop() move.stop()
func move_tick(delta): func move_tick(delta) -> bool:
move.move_tick(delta) return move.move_tick(delta)
func get_face_dir() -> Vector2: func get_face_dir() -> Vector2:
if status.move_dir == Vector2.ZERO: if status.move_dir == Vector2.ZERO:
@ -202,6 +202,11 @@ func cost_mp(value: int):
func cost_mp_sub(): func cost_mp_sub():
battle.cost_mp_sub() battle.cost_mp_sub()
func get_break_level_def() -> int:
var shield: float = get_status("shield")
var break_level_def: int = cfg().shield.break_level_on if shield > 0 else cfg().shield.break_level_off
break_level_def += get_status("skill_break_level_add")
return break_level_def
func set_effect_lock(value: bool): func set_effect_lock(value: bool):
effect.set_effect_lock(value) effect.set_effect_lock(value)

@ -23,11 +23,11 @@ func _process(delta) -> void:
return return
func move_tick(delta) -> void: func move_tick(delta) -> bool:
var is_hit_floor: bool = update_on_floor(delta) var is_hit_floor: bool = update_on_floor(delta)
update_move(delta) update_move(delta)
update_speed_y(delta) update_speed_y(delta)
update_move_check(delta) var is_against_wall: bool = update_move_check(delta)
status.velocity_change = character.velocity.abs() - velocity_cache status.velocity_change = character.velocity.abs() - velocity_cache
velocity_cache = character.velocity.abs() velocity_cache = character.velocity.abs()
if character.velocity: if character.velocity:
@ -38,7 +38,7 @@ func move_tick(delta) -> void:
SignalManager.character_hit_floor.emit(character.id(), character.pos()) SignalManager.character_hit_floor.emit(character.id(), character.pos())
update_deformation(delta) update_deformation(delta)
update_move_effect(delta) update_move_effect(delta)
return return is_against_wall
func update_on_floor(delta) -> bool: func update_on_floor(delta) -> bool:
@ -116,7 +116,7 @@ func update_move_effect(delta):
Global.effect_mgr.cast_particle(ResourceManager.particle_move_dash, character.view_pos(), character.velocity.normalized()) Global.effect_mgr.cast_particle(ResourceManager.particle_move_dash, character.view_pos(), character.velocity.normalized())
func update_move_check(delta): func update_move_check(delta) -> bool:
var velocity: Vector3 = character.velocity var velocity: Vector3 = character.velocity
character.move_and_slide() character.move_and_slide()
if status.is_stagger: if status.is_stagger:
@ -140,6 +140,9 @@ func update_move_check(delta):
Global.effect_mgr.cast_particle(ResourceManager.particle_hit_ground_normal, character.pos(), normal) Global.effect_mgr.cast_particle(ResourceManager.particle_hit_ground_normal, character.pos(), normal)
character.velocity = velocity - normal * normal_speed * 1.5 character.velocity = velocity - normal * normal_speed * 1.5
character.add_buff("floating", -1) character.add_buff("floating", -1)
if normal.y == 0:
return true
return false
func jump(): func jump():

@ -18,5 +18,4 @@ class_name AttackCfg
@export var hit_back_duration: float = 0.05 #击退持续时间 @export var hit_back_duration: float = 0.05 #击退持续时间
@export var hit_up_duration: float = 0.05 #击飞持续时间 @export var hit_up_duration: float = 0.05 #击飞持续时间
@export_group("卡帧") @export_group("卡帧")
@export var pause_time: float #卡帧时间
@export var is_force_pause: bool #是否强制卡帧 @export var is_force_pause: bool #是否强制卡帧

Loading…
Cancel
Save