312 lines
17 KiB
GDScript
312 lines
17 KiB
GDScript
extends Node
|
||
## Central registry for all runtime-tunable parameters.
|
||
## Add a new param with one _reg_f() call in _register_all() — the menu picks it up automatically.
|
||
## Access: DP.f("key") • Persist: DP.save() / DP.load_saved() • Reset: DP.reset_all()
|
||
|
||
signal any_changed(key: String, value: Variant)
|
||
|
||
const SAVE_PATH := "user://debug_params.cfg"
|
||
|
||
# _params holds the full metadata (min/max/step/default/section/type) and is the
|
||
# authority the debug menu reads. _values is a flat key→value mirror so the hot
|
||
# f()/b() reads — called dozens of times per matador per physics frame — cost a
|
||
# single hash lookup instead of a nested dict access. Every write updates both.
|
||
var _params: Dictionary = {}
|
||
var _values: Dictionary = {}
|
||
|
||
|
||
func _ready() -> void:
|
||
_register_all()
|
||
load_saved()
|
||
|
||
|
||
func _register_all() -> void:
|
||
# ── Movement ──────────────────────────────────────────────────────────────
|
||
_reg_f("Movement", "thrust_impulse", 18.0, 1.0, 200.0)
|
||
_reg_f("Movement", "thrust_vertical", 2.0, 0.0, 20.0)
|
||
_reg_f("Movement", "thrust_min_angle", 15.0, 0.0, 90.0, 1.0)
|
||
_reg_f("Movement", "thrust_max_angle", 90.0, 0.0, 180.0, 1.0)
|
||
_reg_f("Movement", "thrust_charge_time", 0.5, 0.05, 2.0, 0.05)
|
||
_reg_f("Movement", "max_speed", 50.0, 2.0, 1000.0)
|
||
_reg_f("Movement", "roll_damping", 0.15, 0.01, 0.99, 0.01)
|
||
_reg_f("Movement", "jump_velocity", 4.5, 1.0, 200.0)
|
||
_reg_f("Movement", "visual_turn_speed", 12.0, 1.0, 200.0)
|
||
_reg_f("Movement", "bounce_restitution", 0.55, 0.0, 2.0, 0.05)
|
||
_reg_f("Movement", "bounce_min_impact", 1.0, 0.0, 20.0)
|
||
_reg_f("Movement", "wall_bounce_restitution", 0.6, 0.0, 1.5, 0.05)
|
||
_reg_f("Movement", "wall_min_bounce_speed", 6.0, 0.0, 30.0)
|
||
_reg_f("Movement", "kick_impulse", 8.0, 1.0, 50.0)
|
||
_reg_f("Movement", "kick_interval", 0.25, 0.05, 1.0, 0.01)
|
||
_reg_f("Movement", "kick_vertical", 0.0, 0.0, 15.0)
|
||
_reg_f("Movement", "kick_force_var", 0.2, 0.0, 1.0, 0.01)
|
||
_reg_f("Movement", "kick_spread", 10.0, 0.0, 45.0, 1.0)
|
||
_reg_f("Movement", "charge_kick_mult", 2.0, 1.0, 5.0)
|
||
# ── Dust speed thresholds ─────────────────────────────────────────────────
|
||
_reg_f("Dust", "dust_walk_spd", 1.5, 0.1, 10.0)
|
||
_reg_f("Dust", "dust_charge_spd", 7.0, 1.0, 20.0)
|
||
# ── Dust ──────────────────────────────────────────────────────────────────
|
||
_reg_f("Dust", "dust_lifetime", 0.9, 0.1, 4.0)
|
||
_reg_f("Dust", "dust_explosiveness", 0.35, 0.0, 1.0)
|
||
_reg_f("Dust", "dust_spread", 45.0, 5.0, 90.0)
|
||
_reg_f("Dust", "dust_gravity_y", -1.5,-15.0, 0.0)
|
||
_reg_f("Dust", "walk_scale_min", 0.35, 0.05, 3.0)
|
||
_reg_f("Dust", "walk_scale_max", 0.65, 0.05, 3.0)
|
||
_reg_f("Dust", "walk_vel_min", 0.8, 0.1, 12.0)
|
||
_reg_f("Dust", "walk_vel_max", 1.8, 0.1, 12.0)
|
||
_reg_f("Dust", "charge_scale_min", 1.0, 0.05, 6.0)
|
||
_reg_f("Dust", "charge_scale_max", 2.2, 0.05, 6.0)
|
||
_reg_f("Dust", "charge_vel_min", 2.8, 0.1, 20.0)
|
||
_reg_f("Dust", "charge_vel_max", 5.5, 0.1, 20.0)
|
||
# ── Tail ──────────────────────────────────────────────────────────────────
|
||
_reg_f("Tail", "tail_gravity", 9.8, 0.0, 30.0)
|
||
_reg_f("Tail", "tail_damping", 0.08, 0.0, 0.5, 0.01)
|
||
_reg_f("Tail", "tail_body_radius", 0.35, 0.05, 2.0, 0.05)
|
||
_reg_f("Tail", "tail_wag_freq", 4.0, 0.5, 15.0)
|
||
_reg_f("Tail", "tail_wag_idle", 0.3, 0.0, 2.0, 0.05)
|
||
# ── Charge (both mouse buttons) ──────────────────────────────────────────
|
||
_reg_f("Charge", "bull_charge_accel", 80.0, 1.0, 400.0)
|
||
_reg_f("Charge", "bull_charge_max_speed", 76.0, 5.0, 200.0)
|
||
_reg_f("Charge", "charge_ramp_time", 0.75, 0.1, 5.0, 0.05)
|
||
_reg_f("Charge", "charge_head_pitch", 0.3, 0.0, 1.2, 0.01)
|
||
_reg_f("Charge", "charge_head_speed", 5.0, 0.5, 20.0)
|
||
# ── Body ──────────────────────────────────────────────────────────────────
|
||
_reg_f("Body", "body_tilt_fwd", 0.015, 0.0, 0.1, 0.001)
|
||
_reg_f("Body", "body_tilt_side", 0.01, 0.0, 0.1, 0.001)
|
||
_reg_f("Body", "aerial_pitch_scale", 0.6, 0.0, 2.0)
|
||
_reg_f("Body", "aerial_pitch_speed", 5.0, 0.5, 20.0)
|
||
# ── Legs ──────────────────────────────────────────────────────────────────
|
||
_reg_f("Legs", "leg_step_threshold", 0.15, 0.01, 1.0, 0.01)
|
||
_reg_f("Legs", "leg_step_duration", 0.12, 0.02, 0.5, 0.01)
|
||
_reg_f("Legs", "leg_step_height", 0.15, 0.0, 0.5)
|
||
_reg_f("Legs", "leg_step_overshoot", 0.3, 0.0, 1.0)
|
||
_reg_f("Legs", "gait_freq", 1.5, 0.1, 5.0)
|
||
_reg_f("Legs", "launch_hold_time", 0.15, 0.0, 1.0, 0.01)
|
||
_reg_f("Legs", "ragdoll_wobble_amp", 0.15, 0.0, 1.0)
|
||
_reg_f("Legs", "tuck_apex_threshold", 0.5, -5.0, 5.0)
|
||
_reg_f("Legs", "jump_tuck_speed", 8.0, 1.0, 30.0)
|
||
_reg_f("Legs", "jump_tuck_up", 0.2, 0.0, 1.0)
|
||
_reg_f("Legs", "jump_tuck_fwd", -0.1, -0.5, 0.5)
|
||
_reg_f("Legs", "jump_land_threshold", 1.5, 0.5, 5.0)
|
||
# ── Camera ────────────────────────────────────────────────────────────────
|
||
_reg_f("Camera", "charge_zoom_factor", 0.65, 0.3, 1.0, 0.05)
|
||
_reg_f("Camera", "cam_lerp_power", 6.0, 0.5, 30.0)
|
||
_reg_f("Camera", "cam_sensitivity", 0.005, 0.001, 0.05, 0.001)
|
||
_reg_f("Camera", "cam_min_zoom", 3.5, 0.5, 20.0)
|
||
_reg_f("Camera", "cam_max_zoom", 40.0, 2.0, 80.0)
|
||
_reg_f("Camera", "cam_spring_length", 7.0, 1.0, 30.0)
|
||
_reg_f("Camera", "cam_min_vert_angle", -60.0, -90.0, 0.0, 1.0)
|
||
_reg_f("Camera", "cam_max_vert_angle", 45.0, 0.0, 90.0, 1.0)
|
||
# ── Matador ───────────────────────────────────────────────────────────────
|
||
_reg_f("Matador", "mat_spawn_count", 1.0, 1.0, 30.0, 1.0)
|
||
_reg_f("Matador", "mat_walk_speed", 4.0, 0.5, 10.0)
|
||
_reg_f("Matador", "mat_wander_radius", 22.0, 5.0, 50.0)
|
||
_reg_f("Matador", "mat_idle_min", 0.5, 0.0, 5.0, 0.1)
|
||
_reg_f("Matador", "mat_idle_max", 2.5, 0.5, 10.0, 0.1)
|
||
_reg_f("Matador", "mat_hit_threshold", 4.0, 1.0, 30.0)
|
||
_reg_f("Matador", "mat_ragdoll_impulse", 6.0, 0.5, 20.0)
|
||
# Ragdoll joint limits — lower swing/twist = stiffer corpse that keeps its
|
||
# shape; higher angular damp settles the flail instead of flopping flat.
|
||
_reg_f("Matador", "mat_joint_swing", 35.0, 0.0, 180.0, 1.0)
|
||
_reg_f("Matador", "mat_joint_twist", 40.0, 0.0, 180.0, 1.0)
|
||
_reg_f("Matador", "mat_ragdoll_damp", 1.5, 0.0, 10.0, 0.1)
|
||
_reg_f("Matador", "mat_flee_range", 3.5, 2.0, 40.0)
|
||
_reg_f("Matador", "mat_flee_speed", 5.5, 0.5, 12.0)
|
||
_reg_f("Matador", "mat_charge_speed", 10.0, 1.0, 30.0)
|
||
_reg_f("Matador", "mat_brace_range", 5.0, 2.0, 20.0)
|
||
_reg_f("Matador", "mat_brace_duration", 0.7, 0.05, 1.5, 0.05)
|
||
_reg_f("Matador", "mat_commit_dist", 2.5, 0.5, 6.0, 0.1)
|
||
_reg_f("Matador", "mat_step_speed", 3.5, 2.0, 20.0)
|
||
_reg_f("Matador", "mat_step_duration", 0.35, 0.1, 1.0, 0.05)
|
||
# How strongly the sidestep biases toward the bull so the blade sweeps through
|
||
# its path during the pass (0 = pure lateral dodge, 1 = straight at the bull).
|
||
_reg_f("Matador", "mat_pass_lunge", 0.35, 0.0, 1.0, 0.05)
|
||
_reg_f("Matador", "mat_dodge_cooldown", 2.5, 0.5, 12.0, 0.25)
|
||
_reg_f("Matador", "mat_dodge_chance", 0.55, 0.0, 1.0, 0.05)
|
||
_reg_f("Matador", "mat_attack_range", 8.0, 2.0, 20.0)
|
||
_reg_f("Matador", "mat_attack_speed", 5.5, 1.0, 12.0)
|
||
_reg_f("Matador", "mat_attack_duration", 1.8, 0.5, 5.0, 0.1)
|
||
_reg_f("Matador", "mat_attack_min_dist", 3.0, 0.5, 6.0, 0.1)
|
||
# Forward drive during the opening of a melee swing — turns the stationary stab
|
||
# into an estocada lunge so the blade covers ground toward the bull.
|
||
_reg_f("Matador", "mat_lunge_speed", 9.0, 0.0, 20.0)
|
||
_reg_f("Matador", "mat_lunge_time", 0.18, 0.0, 0.6, 0.01)
|
||
_reg_f("Matador", "mat_roll_chance", 0.35, 0.0, 1.0, 0.05)
|
||
_reg_f("Matador", "mat_roll_duration", 0.45, 0.1, 1.5, 0.05)
|
||
# Playback rate of the Draw_weapon clip used for both drawing and sheathing —
|
||
# higher = snappier unholster/holster.
|
||
_reg_f("Matador", "mat_draw_speed", 1.25, 0.25, 3.0, 0.05)
|
||
# Cross-fade between matador animation clips — smooths Run/Attack/Taunt cuts.
|
||
_reg_f("Matador", "mat_anim_blend", 0.12, 0.0, 0.5, 0.01)
|
||
# ── Sword ─────────────────────────────────────────────────────────────────
|
||
# Local seating of the sword in the right hand (drawn / fighting).
|
||
# Defaults are identity — the bone is oriented in Blender to seat the sword
|
||
# directly; these exist to fine-tune in-game without re-exporting.
|
||
_reg_f("Sword", "sword_pos_x", 0.0, -1.0, 1.0, 0.01)
|
||
_reg_f("Sword", "sword_pos_y", 0.0, -1.0, 1.0, 0.01)
|
||
_reg_f("Sword", "sword_pos_z", 0.0, -1.0, 1.0, 0.01)
|
||
_reg_f("Sword", "sword_rot_x", 0.0, -180.0, 180.0, 1.0)
|
||
_reg_f("Sword", "sword_rot_y", 0.0, -180.0, 180.0, 1.0)
|
||
_reg_f("Sword", "sword_rot_z", 0.0, -180.0, 180.0, 1.0)
|
||
# Local seating of the sword in the hip holster (sheathed / wandering).
|
||
# Independent of the hand grip so each pose can be tuned without affecting the
|
||
# other. Defaults angle the blade down along the matador's side.
|
||
_reg_f("Sword", "sword_rest_pos_x", 0.0, -1.0, 1.0, 0.01)
|
||
_reg_f("Sword", "sword_rest_pos_y", 0.0, -1.0, 1.0, 0.01)
|
||
_reg_f("Sword", "sword_rest_pos_z", 0.0, -1.0, 1.0, 0.01)
|
||
_reg_f("Sword", "sword_rest_rot_x", -120.0, -180.0, 180.0, 1.0)
|
||
_reg_f("Sword", "sword_rest_rot_y", 0.0, -180.0, 180.0, 1.0)
|
||
_reg_f("Sword", "sword_rest_rot_z", 0.0, -180.0, 180.0, 1.0)
|
||
# ── Sword throw (matador ranged attack) ──────────────────────────────────
|
||
# Probability of committing to a throw each time the matador becomes eligible;
|
||
# kept low so they favour closing in for a melee Attack over throwing.
|
||
_reg_f("Sword", "mat_throw_chance", 0.15, 0.0, 1.0, 0.05)
|
||
# Delay before a fresh sword appears in the holster after one is thrown.
|
||
_reg_f("Sword", "mat_resword_delay", 2.0, 0.0, 10.0, 0.5)
|
||
_reg_f("Sword", "mat_throw_range", 18.0, 5.0, 40.0)
|
||
_reg_f("Sword", "mat_throw_min_dist", 5.0, 2.0, 15.0, 0.1)
|
||
_reg_f("Sword", "mat_throw_windup", 0.7, 0.2, 2.0, 0.05)
|
||
_reg_f("Sword", "mat_throw_release", 0.55, 0.1, 0.95, 0.01)
|
||
_reg_f("Sword", "mat_throw_speed", 18.0, 5.0, 60.0)
|
||
_reg_f("Sword", "mat_throw_spin", 14.0, 0.0, 40.0)
|
||
_reg_f("Sword", "mat_throw_arm_cock", 70.0,-180.0, 180.0, 1.0)
|
||
_reg_f("Sword", "mat_throw_arm_release", -90.0,-180.0, 180.0, 1.0)
|
||
_reg_f("Sword", "mat_throw_elbow", 80.0,-180.0, 180.0, 1.0)
|
||
# ── Abilities ─────────────────────────────────────────────────────────────
|
||
_reg_f("Abilities", "kick_cooldown", 1.5, 0.2, 10.0, 0.1)
|
||
_reg_f("Abilities", "kick_range", 3.5, 0.5, 8.0, 0.1)
|
||
_reg_f("Abilities", "kick_strength", 12.0, 1.0, 30.0)
|
||
_reg_f("Abilities", "slam_cooldown", 4.0, 0.5, 15.0, 0.1)
|
||
_reg_f("Abilities", "slam_jump_velocity", 7.0, 2.0, 20.0)
|
||
# Descent gravity multiplier — higher = faster crash, less airtime.
|
||
_reg_f("Abilities", "slam_fall_mult", 3.0, 1.0, 8.0, 0.5)
|
||
# Upward launch velocity (m/s) given to a slammed matador's ragdoll — pops them
|
||
# skyward. ~7 ≈ a 2.5 m hop; 0 disables the launch.
|
||
_reg_f("Abilities", "slam_launch_up", 7.0, 0.0, 15.0, 0.5)
|
||
_reg_f("Abilities", "slam_range", 4.0, 1.0, 10.0, 0.1)
|
||
_reg_f("Abilities", "slam_strength", 14.0, 1.0, 30.0)
|
||
_reg_f("Abilities", "dash_cooldown", 2.0, 0.5, 10.0, 0.1)
|
||
_reg_f("Abilities", "dash_speed", 66.0, 5.0, 200.0)
|
||
# ── Roll (boulder charge) ─────────────────────────────────────────────────
|
||
# A held-momentum roll: inherits your current charge, ramps toward roll_max_speed,
|
||
# and RICOCHETS off walls with a speed boost (bank shots build ludicrous speed).
|
||
_reg_f("Roll", "roll_cooldown", 3.0, 0.5, 15.0, 0.1)
|
||
_reg_f("Roll", "roll_duration", 2.5, 0.5, 6.0, 0.1)
|
||
_reg_f("Roll", "roll_min_speed", 30.0, 5.0, 120.0) # launch floor (combines charge)
|
||
_reg_f("Roll", "roll_max_speed", 95.0, 10.0, 200.0) # natural top from acceleration
|
||
_reg_f("Roll", "roll_accel", 55.0, 0.0, 300.0)
|
||
# Per-second speed retained above roll_max_speed — low friction so wall-boosted
|
||
# momentum bleeds off slowly rather than snapping back to the cruise speed.
|
||
_reg_f("Roll", "roll_momentum", 0.9, 0.1, 0.99, 0.01)
|
||
_reg_f("Roll", "roll_turn", 3.5, 0.2, 20.0) # steer rate (sluggish = momentum feel)
|
||
_reg_f("Roll", "roll_wall_boost", 1.25, 1.0, 2.0, 0.05) # speed × on each ricochet
|
||
_reg_f("Roll", "roll_wall_cap", 150.0, 10.0, 300.0) # ceiling reachable via boosts
|
||
_reg_f("Roll", "roll_hit_radius", 2.4, 0.5, 6.0, 0.1)
|
||
_reg_f("Roll", "roll_hit_strength", 22.0, 1.0, 40.0)
|
||
_reg_f("Roll", "roll_hit_up", 4.5, 0.0, 15.0)
|
||
# ── Debug overlays (see debug_draw.gd) ───────────────────────────────────
|
||
_reg_b("Debug", "show_collisions", false)
|
||
_reg_b("Debug", "show_hitboxes", false)
|
||
_reg_b("Debug", "show_bones", false)
|
||
_reg_b("Debug", "show_raycasts", false)
|
||
_reg_b("Debug", "show_tail", false)
|
||
_reg_b("Debug", "show_stats", false)
|
||
_reg_b("Debug", "show_states", false)
|
||
_reg_b("Debug", "show_animation_name", false)
|
||
_reg_b("Debug", "show_wireframe", false)
|
||
_reg_b("Debug", "show_grid", false)
|
||
_reg_b("Debug", "show_axes", false)
|
||
|
||
|
||
func _reg_f(section: String, key: String, default: float,
|
||
min_val: float, max_val: float, step: float = 0.05) -> void:
|
||
_params[key] = {
|
||
"value": default,
|
||
"default": default,
|
||
"section": section,
|
||
"type": TYPE_FLOAT,
|
||
"min": min_val,
|
||
"max": max_val,
|
||
"step": step,
|
||
}
|
||
_values[key] = default
|
||
|
||
|
||
func _reg_b(section: String, key: String, default: bool) -> void:
|
||
_params[key] = {
|
||
"value": default,
|
||
"default": default,
|
||
"section": section,
|
||
"type": TYPE_BOOL,
|
||
}
|
||
_values[key] = default
|
||
|
||
|
||
## Read a float param. Panics on unknown key — intentional: typos should be loud.
|
||
func f(key: String) -> float:
|
||
return _values[key] as float
|
||
|
||
|
||
## Read a bool param.
|
||
func b(key: String) -> bool:
|
||
return _values[key] as bool
|
||
|
||
|
||
func set_value(key: String, value: Variant) -> void:
|
||
if not _params.has(key):
|
||
return
|
||
_params[key]["value"] = value
|
||
_values[key] = value
|
||
any_changed.emit(key, value)
|
||
|
||
|
||
## Returns the full metadata dict — used by Console to build UI.
|
||
func get_all() -> Dictionary:
|
||
return _params
|
||
|
||
|
||
func save() -> void:
|
||
var cfg := ConfigFile.new()
|
||
for key: String in _params:
|
||
var p: Dictionary = _params[key]
|
||
cfg.set_value(p["section"], key, p["value"])
|
||
cfg.save(SAVE_PATH)
|
||
|
||
|
||
func load_saved() -> void:
|
||
var cfg := ConfigFile.new()
|
||
if cfg.load(SAVE_PATH) != OK:
|
||
return
|
||
for section: String in cfg.get_sections():
|
||
for key: String in cfg.get_section_keys(section):
|
||
if not _params.has(key):
|
||
continue
|
||
var p: Dictionary = _params[key]
|
||
var val: Variant = cfg.get_value(section, key)
|
||
if p["type"] == TYPE_FLOAT:
|
||
val = clampf(val as float, p["min"] as float, p["max"] as float)
|
||
_params[key]["value"] = val
|
||
_values[key] = val
|
||
|
||
|
||
func reset_all() -> void:
|
||
for key: String in _params:
|
||
var default: Variant = _params[key]["default"]
|
||
_params[key]["value"] = default
|
||
_values[key] = default
|
||
any_changed.emit("__all__", null)
|
||
|
||
|
||
## Reset a single param to its default. No-op on unknown key.
|
||
func reset(key: String) -> void:
|
||
if not _params.has(key):
|
||
return
|
||
var default: Variant = _params[key]["default"]
|
||
_params[key]["value"] = default
|
||
_values[key] = default
|
||
any_changed.emit(key, default)
|
||
|
||
|
||
## True when the param currently differs from its registered default.
|
||
func is_modified(key: String) -> bool:
|
||
return _params.has(key) and _params[key]["value"] != _params[key]["default"]
|