extends Node3D class_name Buff @onready var character: Character = (get_owner() as Character) @onready var status: Status = (%Status as Status) @onready var effect: Effect = (%Effect as Effect) @onready var battle: Battle = (%Battle as Battle) class BuffInfo: var name: String var duration_max: float var duration: float var ignore_pause: bool var buff_map: Dictionary = {} # buff信息 var buff_tick_frame_max = 1 var buff_tick_frame = 0 var delta_cache: float = 0 func _ready(): buff_tick_frame_max = 1 func _process(delta): delta_cache += delta buff_tick_frame += 1 if buff_tick_frame < buff_tick_frame_max: return tick(delta_cache) buff_tick_frame = 0 buff_tick_frame = 0 func tick(delta) -> void: for buff_name in buff_map: var buff_info = buff_map[buff_name] if has_buff("pause") and buff_name != "pause" and !buff_info.ignore_pause: continue if buff_info.duration_max == -1: trigger_buff_effect(buff_info, "update") else: if buff_info.duration == 0: trigger_buff_effect(buff_info, "second") buff_info.duration += delta if buff_info.duration >= buff_info.duration_max: buff_info.duration = buff_info.duration_max trigger_buff_effect(buff_info, "update") remove_buff(buff_name) else: trigger_buff_effect(buff_info, "update") func trigger_buff_effect(buff: BuffInfo, trigger_name: String): var buff_name: String = buff.name var function_name: String = "on_%s_%s" % [trigger_name, buff_name] if has_method(function_name): var rate: float = buff.duration / buff.duration_max call(function_name, rate) func has_buff(buff_name: String) -> bool: return buff_name in buff_map func add_buff(buff_name: String, duration: float, ignore_pause: bool = false): var buff: BuffInfo if buff_name in buff_map: buff = buff_map[buff_name] else: buff = BuffInfo.new() buff.name = buff_name buff_map[buff_name] = buff buff.duration_max = duration buff.duration = 0 buff.ignore_pause = ignore_pause trigger_buff_effect(buff, "start") func remove_buff(buff_name: String): if buff_name in buff_map: var buff = buff_map[buff_name] trigger_buff_effect(buff, "end") buff_map.erase(buff_name) #==具体实现== #位移 func on_end_hit_back(_rate) -> void: status.set_status("hit_back_speed", 0) func on_end_hit_up(_rate) -> void: status.set_status("hit_up_speed", 0) func on_start_jumping(_rate) -> void: status.set_status("is_jumping", true) func on_end_jumping(_rate) -> void: status.set_status("is_jumping", false) func on_start_rising(_rate) -> void: status.set_status("is_rising", true) func on_end_rising(_rate) -> void: status.set_status("is_rising", false) func on_start_floating(_rate) -> void: status.set_status("is_floating", true) add_buff("rising", 0.1) func on_update_floating(_rate) -> void: if not status.is_on_floor or status.is_rising: return remove_buff("floating") add_buff("stagger", 3) func on_end_floating(_rate) -> void: status.set_status("is_floating", false) #战斗状态 func on_start_die(_rate) -> void: status.set_status("is_dead", true) SignalManager.character_die.emit(status.id) func on_end_die(_rate) -> void: add_buff("die2", -1) func on_update_die2(_rate) -> void: if status.is_on_floor and not status.is_rising: remove_buff("die2") func on_end_die2(_rate) -> void: effect.cast_corpse() Global.character_mgr.destroy_character(status.id) func on_start_stagger(_rate) -> void: status.set_status("is_stagger", true) status.set_skill_break_level_add(-1) func on_end_stagger(_rate) -> void: status.set_status("is_stagger", false) status.set_skill_break_level_add(0) func on_end_shield_recover_cd(_rate) -> void: add_buff("shield_recover", -1) func on_update_shield_recover(_rate) -> void: var shield_add: float = get_process_delta_time() * status.cfg.shield.recover_speed shield_add = min(status.shield_max - status.shield, shield_add) if shield_add == status.shield_max - status.shield: remove_buff("shield_recover") character.set_shield(status.shield + shield_add) func on_end_mp_recover_cd(_rate) -> void: add_buff("mp_recover", 0.1) func on_update_mp_recover(_rate) -> void: var mp_add: float = get_process_delta_time() * status.cfg.mp.recover_speed character.add_mp_sub(mp_add, false) func on_update_charging(_rate) -> void: var mp_add: float = get_process_delta_time() * status.cfg.mp.charging_speed character.add_mp_sub(mp_add, true) func on_end_stun_recover_break_cd(_rate) -> void: add_buff("stun_recover_break", -1) func on_update_stun_recover_break(_rate) -> void: var stun_sub: float = get_process_delta_time() * status.cfg.stun.recover_break_speed stun_sub = min(status.stun, stun_sub) status.set_status("stun", status.stun - stun_sub) if status.stun == 0: remove_buff("stun_recover_break") status.set_status("is_stun", false) func on_end_stun_recover_cd(_rate) -> void: add_buff("stun_recover", -1) func on_update_stun_recover(_rate) -> void: var stun_sub: float = get_process_delta_time() * status.cfg.stun.recover_speed stun_sub = min(status.stun, stun_sub) status.set_status("stun", status.stun - stun_sub) if status.stun == 0: remove_buff("stun_recover") func on_update_weapon_index_change(rate) -> void: status.set_status("weapon_index_change_rate", rate) func on_end_weapon_index_change(_rate) -> void: var weapon_index: int = status.weapon_index + status.weapon_index_change_dir var weapon_len: int = len(status.weapon_list) weapon_index = (weapon_index % weapon_len + weapon_len) % weapon_len status.set_status("weapon_index", weapon_index) status.set_status("weapon_index_change_dir", 0) #表现 func on_start_freeze(_rate) -> void: status.set_status("is_pause", true) func on_end_freeze(_rate) -> void: status.set_status("is_pause", false) func on_second_pause(_rate) -> void: status.set_status("is_pause", true) func on_end_pause(_rate) -> void: status.set_status("is_pause", false) func on_start_flash_white(_rate) -> void: status.set_status("flash_white_rate", 1) func on_update_flash_white(rate) -> void: status.set_status("flash_white_rate", 1 - rate) func on_end_flash_white(_rate) -> void: status.set_status("flash_white_rate", 0) func on_update_shake_x(rate) -> void: var shake_rate: float = 0.5 * status.pause_time status.set_status("shake_offset", Vector3((sin(rate * PI * 6) - 0.5) * shake_rate, 0, 0)) func on_end_shake_x(_rate) -> void: status.set_status("shake_offset", Vector3.ZERO) func on_start_deformation(_rate) -> void: status.set_status("deformation_rate", 1) func on_update_deformation(rate) -> void: status.set_status("deformation_rate", 1 - rate) func on_end_deformation(_rate) -> void: status.set_status("deformation_rate", 0)