# SkillFx (P6 收尾) —— 技能 id / 内建特效 id → .mse 文件,接 P5 EffectRegistry。 # # var sfx := preload("res://fx/skill_fx.gd").new() # sfx.setup(effect_registry, skill_table) # sfx.spawn_skill(1, 3, caster_node) # 技能 1(samyeon) grade→_4 挂 caster 播 # sfx.spawn_special(19, node) # GC_SPECIAL_EFFECT type 19 = SE_AUTO_HPUP -> drugup_red # # 技能特效表:skilldesc 的 motion_name(col13)就是特效基名;等级后缀 = 2 + master_type(夹 2..4)。 # effect/pc//effect/_.mse(EffectRegistry 的 basename 扫描能找到散包 / PC / season1) # 少数技能有 _blow / _head / _foot / _yong 子特效;这里只放主特效,缺就跳过。 extends RefCounted # GC_SPECIAL_EFFECT 的 type(ItemData.h / Packet.h 的 SE_* enum,值 = 下标)-> etc 特效基名。 # 不全 —— 只填常见的(真机 GM 号狂刷 19/20 自动喝药)。 const SPECIAL_FX := { 1: "drugup_red", # SE_HPUP_RED 2: "drugup_blue", # SE_SPUP_BLUE 3: "drugup_green", # SE_SPEEDUP_GREEN 4: "drugup_purple", # SE_DXUP_PURPLE 9: "firecracker_1", # SE_CHINA_FIREWORK 11: "firecracker_2", # SE_SUCCESS(凑合) 12: "fail", # SE_FAIL 19: "drugup_red", # SE_AUTO_HPUP 20: "drugup_blue", # SE_AUTO_SPUP } var fxr: RefCounted # EffectRegistry var table: RefCounted # SkillTable # 一个 motion 常见的子特效后缀(有就一起播) const SUB_SUFFIX := ["", "_blow", "_hand", "_head", "_foot", "_yong"] func setup(effect_registry: RefCounted, skill_table: RefCounted) -> void: fxr = effect_registry table = skill_table # skill_id + master_type(0..3) -> 主特效基名(_)。查不到 motion 返回 ""。 func skill_effect_name(skill_id: int, master: int = 0) -> String: if table == null: return "" var mn := String(table.entry(skill_id).get("motion", "")) if mn == "": return "" var n := clampi(2 + master, 2, 4) return "%s_%d" % [mn, n] # 在 host 下播技能特效(主 + 已存在的子特效各一份)。返回播了几个。 func spawn_skill(skill_id: int, master: int, host: Node3D) -> int: if fxr == null or host == null: return 0 var base := skill_effect_name(skill_id, master) if base == "": return 0 var parts := base.rsplit("_", false, 1) # "samyeon_4" -> ["samyeon", "4"] var stem: String = parts[0] var num: String = parts[1] if parts.size() > 1 else "" var played := 0 for suf in SUB_SUFFIX: var name: String = base if suf != "": name = "%s%s_%s" % [stem, suf, num] if num != "" else stem + suf if fxr.resolve(name) != "": fxr.spawn(name, host, true) played += 1 return played # GC_SPECIAL_EFFECT type -> 内建特效。返回是否播了。 func spawn_special(special_id: int, host: Node3D) -> bool: if fxr == null or host == null or not SPECIAL_FX.has(special_id): return false var name: String = SPECIAL_FX[special_id] if fxr.resolve(name) == "": return false fxr.spawn(name, host, true) return true