492 lines
30 KiB
GDScript
492 lines
30 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()
|
||
|
||
|
||
func _register_all() -> void:
|
||
# ── Movement ──────────────────────────────────────────────────────────────
|
||
# WASD/arrows drive the bull: move_accel ramps flat velocity toward max_speed in
|
||
# the input direction; move_friction bleeds it off when no direction is held.
|
||
_reg_f("Movement", "max_speed", 10.0, 2.0, 1000.0)
|
||
_reg_f("Movement", "move_accel", 120.0, 5.0, 600.0)
|
||
_reg_f("Movement", "move_friction", 90.0, 5.0, 600.0)
|
||
_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)
|
||
# ── Bull health ───────────────────────────────────────────────────────────
|
||
# The bull soaks bull_max_hp clean hits before it dies; each hit grants
|
||
# bull_hit_iframes seconds of invulnerability so a single pass can't drain it.
|
||
_reg_f("Bull", "bull_max_hp", 10.0, 1.0, 100.0, 1.0)
|
||
_reg_f("Bull", "bull_hit_iframes", 0.8, 0.0, 3.0, 0.1)
|
||
# ── 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.20, 0.05, 3.0)
|
||
_reg_f("Dust", "walk_scale_max", 0.40, 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", 0.35, 0.05, 6.0)
|
||
_reg_f("Dust", "charge_scale_max", 0.70, 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 pose (horns-down lean during dash / roll) ─────────────────────
|
||
_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)
|
||
# Trailing "drag" camera: the focus point lags the bull and slides opposite to
|
||
# its velocity, so the camera visibly drags behind during a fast charge.
|
||
# cam_drag = metres of trail per m/s of bull speed (0 = rigid follow)
|
||
# cam_drag_speed = how fast the trail offset eases toward its target
|
||
# cam_follow_lerp = how tightly the focus point chases the bull (higher = snappier)
|
||
_reg_f("Camera", "cam_drag", 0.12, 0.0, 1.0, 0.01)
|
||
_reg_f("Camera", "cam_drag_speed", 3.5, 0.5, 20.0)
|
||
_reg_f("Camera", "cam_follow_lerp", 10.0, 1.0, 40.0)
|
||
# ── Matador ───────────────────────────────────────────────────────────────
|
||
# Wave system: matadors enter the arena in escalating waves (1 → 2 → … → N where N
|
||
# is the number of placed spawn points). mat_spawn_stagger is the delay between each
|
||
# matador leaping in within a wave; mat_wave_pause is the breather after a wave clears.
|
||
_reg_f("Matador", "mat_spawn_stagger", 0.4, 0.0, 3.0, 0.05)
|
||
_reg_f("Matador", "mat_wave_pause", 2.0, 0.0, 8.0, 0.25)
|
||
_reg_f("Matador", "mat_walk_speed", 5.5, 0.5, 10.0)
|
||
_reg_f("Matador", "mat_wander_radius", 22.0, 5.0, 50.0)
|
||
# Radius of the inner fighting floor: bull + matadors spawn on this ring (so
|
||
# they stay off the benches). Tune in the console to hug the bench edge.
|
||
_reg_f("Matador", "arena_spawn_radius", 10.0, 2.0, 22.0, 0.5)
|
||
_reg_f("Matador", "mat_idle_min", 1.2, 0.0, 5.0, 0.1)
|
||
_reg_f("Matador", "mat_idle_max", 4.0, 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", 7.0, 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", 6.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.72, 0.0, 1.0, 0.05)
|
||
_reg_f("Matador", "mat_attack_range", 8.0, 2.0, 20.0)
|
||
_reg_f("Matador", "mat_attack_speed", 7.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.2, 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", 13.0, 0.0, 20.0)
|
||
_reg_f("Matador", "mat_lunge_time", 0.22, 0.0, 0.6, 0.01)
|
||
# Reach of the reach-based stab (the reliable melee hit) and its re-strike gap.
|
||
# The bull dies if it comes inside mat_stab_reach of a matador that's attacking,
|
||
# bracing, or passing with a drawn blade — closing in is genuinely deadly.
|
||
_reg_f("Matador", "mat_stab_reach", 1.7, 0.5, 4.0, 0.1)
|
||
_reg_f("Matador", "mat_stab_cooldown", 0.6, 0.1, 3.0, 0.1)
|
||
# Half-angle (deg) the matador must be facing the bull within for a stab to land.
|
||
# Stops "sword's off to the side but I still died" — you're only gored when the
|
||
# blade is actually presented at you.
|
||
_reg_f("Matador", "mat_stab_arc", 55.0, 5.0, 180.0, 5.0)
|
||
_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.9, 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)
|
||
# ── Matador heuristics (utility AI) ───────────────────────────────────────
|
||
# Every mat_decide_interval seconds the matador scores its options — dodge the
|
||
# pass, close for a strike, retreat, throw the blade, or strut/taunt — and picks
|
||
# the highest. These weights bias the personality: crank aggression for a reckless
|
||
# bullfighter, caution for a slippery one. mat_w_commit is a stickiness bonus for
|
||
# the current choice so it doesn't dither between two near-tied options.
|
||
_reg_f("Matador", "mat_decide_interval", 0.2, 0.05, 1.0, 0.05)
|
||
_reg_f("Matador", "mat_w_aggression", 1.1, 0.0, 3.0, 0.05)
|
||
_reg_f("Matador", "mat_w_caution", 1.0, 0.0, 3.0, 0.05)
|
||
_reg_f("Matador", "mat_w_flee", 0.8, 0.0, 3.0, 0.05)
|
||
# Showmanship (strut, circle the bull, taunt) — the supporting matadors lean on
|
||
# this to spread out and give the lead room, so a whole crowd reads as a bullring,
|
||
# not a swarm. Crank it for more posturing, drop it for a relentless mob.
|
||
_reg_f("Matador", "mat_w_showmanship", 1.6, 0.0, 3.0, 0.05)
|
||
# Weight on hurling the blade. Kept low — a thrown sword is an occasional flourish,
|
||
# not a barrage; raising this brings back the pelting.
|
||
_reg_f("Matador", "mat_w_throw", 0.35, 0.0, 3.0, 0.05)
|
||
# How many matadors press the bull at once. The nearest this-many engage (close,
|
||
# throw); everyone else keeps their distance and taunts, taking turns as the bull
|
||
# moves. 1 = strict one-on-one, higher = a bolder pack.
|
||
_reg_f("Matador", "mat_engage_slots", 2.0, 1.0, 8.0, 1.0)
|
||
# Preferred distance (m) a taunting matador circles the bull at while waiting its
|
||
# turn — the showmanship ring the crowd spreads out onto.
|
||
_reg_f("Matador", "mat_taunt_ring", 7.0, 3.0, 15.0, 0.5)
|
||
# How long (s) a matador safely out of the action holds a taunt before drifting to
|
||
# a new spot — much longer than the between-passes idle, so bystanders mostly pose
|
||
# for the crowd instead of milling about. Actual hold is randomised ±30%.
|
||
_reg_f("Matador", "mat_taunt_hold", 8.0, 1.0, 20.0, 0.5)
|
||
# Small so it smooths dithering without locking the matador into idling.
|
||
_reg_f("Matador", "mat_w_commit", 0.15, 0.0, 2.0, 0.05)
|
||
# ── Bear (boss) ─────────────────────────────────────────────────────────────
|
||
# A Dark-Souls-style boss with a learnable moveset. It soaks bear_max_hp clean hits
|
||
# (ram or ability), staggering on each, and only topples when worn down. From NEUTRAL
|
||
# it weighs its options by the range band to the bull and commits to one telegraphed
|
||
# routine (wind-up → active → recovery); each routine plays to the end (the recovery
|
||
# is the player's punish window). Below bear_enrage_frac HP it enters phase 2: faster
|
||
# tells and recovery (× bear_enrage_scale) and longer combo chains.
|
||
_reg_f("Bear", "bear_max_hp", 50.0, 1.0, 100.0, 1.0)
|
||
# HP fraction at which phase 2 ("Fury") triggers, and how much it multiplies every
|
||
# wind-up / recovery timer (lower = snappier, more dangerous).
|
||
_reg_f("Bear", "bear_enrage_frac", 0.4, 0.0, 1.0, 0.05)
|
||
_reg_f("Bear", "bear_enrage_scale", 0.7, 0.3, 1.0, 0.05)
|
||
# Range bands (m) that pick the moveset: ≤close it strikes (swipe / smash), ≤mid it
|
||
# walks in to close the gap (stalk) or leaps, beyond it lopes in (prowl) or leaps.
|
||
# close is deliberately generous — the bear commits to melee "from a bit further" and
|
||
# steps in during the swing (see bear_lunge_speed) rather than needing to be on top.
|
||
_reg_f("Bear", "bear_close_range", 5.0, 1.0, 12.0, 0.1)
|
||
_reg_f("Bear", "bear_mid_range", 9.0, 3.0, 20.0, 0.5)
|
||
# Beat spent in NEUTRAL sizing up the bull between routines — kept short so the bear
|
||
# flows straight from one action into the next instead of pausing (raise for a more
|
||
# hesitant, readable boss; near-0 for relentless pressure). Shrinks again in phase 2.
|
||
_reg_f("Bear", "bear_think_time", 0.06, 0.0, 1.0, 0.01)
|
||
# Locomotion: the all-fours prowl (close a big gap), the menacing 2-leg walk-in
|
||
# (stalk), the facing rate while positioning/winding up, and the softer tracking rate
|
||
# a swing keeps on the bull mid-attack so it's harder to just walk out of.
|
||
_reg_f("Bear", "bear_run_speed", 11.0, 1.0, 20.0, 0.1)
|
||
_reg_f("Bear", "bear_stalk_speed", 5.5, 0.5, 12.0, 0.1)
|
||
_reg_f("Bear", "bear_turn_rate", 7.0, 1.0, 20.0, 0.5)
|
||
_reg_f("Bear", "bear_track_active", 3.5, 0.0, 12.0, 0.1)
|
||
# Forward step-in during a swing so a strike lands even when the bull is a touch out of
|
||
# reach (also carries the tracking); 0 = a purely stationary swing.
|
||
_reg_f("Bear", "bear_lunge_speed", 7.0, 0.0, 16.0, 0.5)
|
||
# Playback multiplier for the swipe/smash clips — >1 makes the punches snappier.
|
||
_reg_f("Bear", "bear_attack_anim_speed", 1.35, 0.5, 3.0, 0.05)
|
||
# Half-arc (deg) the bear must be facing the bull within for a directional swing to
|
||
# connect; slams use their own radius instead of an arc.
|
||
_reg_f("Bear", "bear_hit_arc", 70.0, 5.0, 180.0, 5.0)
|
||
# Double Swipe (ONE_TWO_HIT) — bread-and-butter close combo, two quick hits.
|
||
_reg_f("Bear", "bear_swipe_windup", 0.3, 0.05, 2.0, 0.05)
|
||
_reg_f("Bear", "bear_swipe_recover", 0.35, 0.05, 3.0, 0.05)
|
||
_reg_f("Bear", "bear_swipe_reach", 4.2, 1.0, 8.0, 0.1)
|
||
# Overhead Smash (SMASH_HIT) — slower tell, biggest punish window, AoE on impact.
|
||
_reg_f("Bear", "bear_smash_windup", 0.6, 0.1, 3.0, 0.05)
|
||
_reg_f("Bear", "bear_smash_recover", 0.75, 0.1, 4.0, 0.05)
|
||
_reg_f("Bear", "bear_smash_radius", 4.2, 1.0, 8.0, 0.1)
|
||
# Leap Slam (JUMP_SMASH, 47 frames @30fps) — timed to the clip by FRAME: it plays the
|
||
# crouch grounded, springs at the takeoff frame, and the arc is solved so the paws hit
|
||
# ground exactly on the impact frame (25), leaving the tail frames to settle on the
|
||
# ground — no finishing the anim in mid-air. The arc uses its own gravity so peak height
|
||
# and airtime are independent: bear_leap_height is the peak reached in that fixed airtime.
|
||
_reg_f("Bear", "bear_leap_takeoff_frame", 6.0, 0.0, 46.0, 1.0)
|
||
_reg_f("Bear", "bear_leap_impact_frame", 25.0, 1.0, 47.0, 1.0)
|
||
_reg_f("Bear", "bear_leap_height", 2.6, 0.5, 8.0, 0.1)
|
||
_reg_f("Bear", "bear_leap_recover", 0.35, 0.0, 4.0, 0.05)
|
||
_reg_f("Bear", "bear_leap_speed", 14.0, 4.0, 30.0, 0.5)
|
||
_reg_f("Bear", "bear_slam_radius", 4.0, 1.0, 8.0, 0.1)
|
||
# Stalk (WALK_ON2LEGS) — how long it will keep walking the bull down before re-deciding.
|
||
_reg_f("Bear", "bear_stalk_time", 2.5, 0.0, 6.0, 0.1)
|
||
# Odds a close combo chains a follow-up smash after the swipe (phase 2 always chains).
|
||
_reg_f("Bear", "bear_combo_chance", 0.7, 0.0, 1.0, 0.05)
|
||
# Minimum bull speed (ram) that counts as a hit on the bear — a gentle nudge is
|
||
# shrugged off, only a real charge or an ability wounds it. (The bear itself never
|
||
# damages the bull by colliding — only its swings and slams hurt.)
|
||
_reg_f("Bear", "bear_hit_threshold", 6.0, 1.0, 30.0, 0.5)
|
||
# How long (s) the bear is rocked back and can't act after taking a hit.
|
||
_reg_f("Bear", "bear_stagger_time", 0.5, 0.0, 2.0, 0.05)
|
||
# Poise: after a stagger the bear shrugs off staggers for this long (hits still wound
|
||
# it), so it can't be perma-stunlocked — it gets a window to commit an attack that then
|
||
# rides its hyper-armour. 0 = no poise (stun-locks under sustained fire).
|
||
_reg_f("Bear", "bear_stagger_cd", 1.0, 0.0, 4.0, 0.05)
|
||
# ── 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)
|
||
# ── Spear throw (matador ranged attack) ──────────────────────────────────
|
||
# Local seating of the spear in the throwing hand during the wind-up. Tune to
|
||
# seat the shaft in the grip without re-exporting; flight orientation is derived
|
||
# from the aim direction at release, not from this pose.
|
||
_reg_f("Sword", "spear_pos_x", 0.0, -1.0, 1.0, 0.01)
|
||
_reg_f("Sword", "spear_pos_y", 0.0, -1.0, 1.0, 0.01)
|
||
_reg_f("Sword", "spear_pos_z", 0.0, -1.0, 1.0, 0.01)
|
||
_reg_f("Sword", "spear_rot_x", 0.0, -180.0, 180.0, 1.0)
|
||
_reg_f("Sword", "spear_rot_y", 0.0, -180.0, 180.0, 1.0)
|
||
_reg_f("Sword", "spear_rot_z", 0.0, -180.0, 180.0, 1.0)
|
||
# Delay before a fresh sword reappears in the holster if one is ever lost.
|
||
_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.5, 0.2, 2.0, 0.05)
|
||
_reg_f("Sword", "mat_throw_release", 0.55, 0.1, 0.95, 0.01)
|
||
# Horizontal speed of the thrown spear; the vertical launch is solved from this
|
||
# and the gravity below so the arc lands on the bull. Lower = a higher, slower lob.
|
||
_reg_f("Sword", "mat_throw_speed", 11.0, 5.0, 60.0)
|
||
# Gravity scale on the spear (higher = a more pronounced arc) and the vertical aim
|
||
# offset from the bull origin down onto its low collision body.
|
||
_reg_f("Sword", "mat_throw_gravity", 1.0, 0.1, 3.0, 0.05)
|
||
_reg_f("Sword", "mat_throw_aim_y", -0.45,-1.5, 0.5, 0.05)
|
||
# Aim scatter (± degrees) so thrown blades can be read and dodged on the move.
|
||
_reg_f("Sword", "mat_throw_spread", 11.0, 0.0, 30.0, 0.5)
|
||
_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", 2, 0.2, 600, 0.1)
|
||
_reg_f("Abilities", "kick_range", 6.0, 0.5, 8.0, 0.1)
|
||
_reg_f("Abilities", "kick_strength", 12.0, 1.0, 30.0)
|
||
_reg_f("Abilities", "slam_cooldown", 12, 0.5, 600, 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", 3, 0.1, 600.0, 0.1)
|
||
_reg_f("Abilities", "dash_speed", 66.0, 5.0, 200.0)
|
||
# Exponential rate the dash bleeds from dash_speed back to cruise (max_speed).
|
||
# Higher = a snappier bullet that dies off quicker; lower = a longer glide.
|
||
_reg_f("Abilities", "dash_decel", 7.0, 0.5, 30.0, 0.5)
|
||
# ── Roll (homing chain ball) ──────────────────────────────────────────────
|
||
# The bull curls into a ball and ACCELERATES the longer it rolls, from
|
||
# roll_base_speed up to roll_max_speed over roll_rampup_time. It HOMES on the
|
||
# closest matador; on slamming one the ball POPS it (launched skyward via
|
||
# roll_knockup) then CHAINS to the next closest, up to roll_chain_count times.
|
||
# roll_turn is the homing turn rate. When no chain targets remain, the roll ends.
|
||
_reg_f("Roll", "roll_cooldown", 20, 0.5, 600, 0.1)
|
||
_reg_f("Roll", "roll_duration", 2.5, 0.5, 6.0, 0.1) # max roll time
|
||
_reg_f("Roll", "roll_chain_count", 2.0, 0.0, 8.0, 1.0) # extra matadors chained after the first
|
||
_reg_f("Roll", "roll_base_speed", 28.0, 5.0, 120.0) # speed at the start of the roll
|
||
_reg_f("Roll", "roll_max_speed", 95.0, 10.0, 200.0) # top speed once fully ramped
|
||
_reg_f("Roll", "roll_rampup_time", 2.0, 0.2, 6.0, 0.1) # time to reach top speed
|
||
_reg_f("Roll", "roll_turn", 7.0, 0.2, 20.0) # homing turn rate (higher = tighter tracking)
|
||
_reg_f("Roll", "roll_spin_radius", 1.4, 0.3, 4.0, 0.1) # ball radius for tumble spin (smaller = faster)
|
||
_reg_f("Roll", "roll_hit_radius", 2.4, 0.5, 6.0, 0.1) # contact radius that pops the ball
|
||
_reg_f("Roll", "roll_hit_strength", 22.0, 1.0, 40.0) # horizontal launch on the pop
|
||
_reg_f("Roll", "roll_knockup", 11.0, 0.0, 25.0) # vertical knock-up on the pop
|
||
# ── Debug overlays (see debug_draw.gd) ───────────────────────────────────
|
||
_reg_b("Debug", "show_collisions", false)
|
||
# PS1 post-process filter (see ps1_filter.gd on the fullscreen ColorRect):
|
||
# screen-covering CRT/PS1 shader — pixelation, colour-banding + dither, and a
|
||
# rolling scanline. Keys map 1:1 onto the shader uniforms; show_ps1 toggles the
|
||
# whole overlay. Ranges mirror the shader's hint_range so the console can't push
|
||
# a uniform out of bounds.
|
||
_reg_b("PS1", "show_ps1", true)
|
||
_reg_f("PS1", "ps1_pixel_scale", 4.0, 1.0, 8.0, 1.0)
|
||
_reg_f("PS1", "ps1_color_depth", 4.5, 2.0, 8.0, 1.0)
|
||
_reg_f("PS1", "ps1_dither_strength", 1, 0.0, 2.0, 0.05)
|
||
_reg_f("PS1", "ps1_scanline_strength", 0.2, 0.0, 1.0, 0.05)
|
||
_reg_f("PS1", "ps1_roll_speed", 3.0, 0.0, 10.0, 0.1)
|
||
_reg_f("PS1", "ps1_roll_strength", 1.0, 0.0, 1.0, 0.05)
|
||
_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)
|
||
# Force the on-screen touch controls (joystick + ability buttons) on even on a
|
||
# desktop build — otherwise they appear only when a touchscreen is detected.
|
||
_reg_b("Touch", "force_touch_controls", false)
|
||
# On-screen readout of live touch state (event count, last position, active zone) so
|
||
# touch problems can be diagnosed on the actual device, where no console is reachable.
|
||
_reg_b("Touch", "touch_debug", 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 path := "res://debug_params.gd"
|
||
var file := FileAccess.open(path, FileAccess.READ)
|
||
if file == null:
|
||
push_error("DP.save: cannot open " + path)
|
||
return
|
||
var src := file.get_as_text()
|
||
file.close()
|
||
|
||
for key: String in _params:
|
||
var p: Dictionary = _params[key]
|
||
if p["value"] == p["default"]:
|
||
continue
|
||
var re := RegEx.new()
|
||
if p["type"] == TYPE_FLOAT:
|
||
re.compile('(_reg_f\\("[^"]+",\\s*"%s",\\s*)([-\\d.e]+)' % key)
|
||
src = re.sub(src, "$1" + _fmt_float(p["value"] as float))
|
||
else:
|
||
re.compile('(_reg_b\\("[^"]+",\\s*"%s",\\s*)(true|false)' % key)
|
||
src = re.sub(src, "$1" + ("true" if bool(p["value"]) else "false"))
|
||
p["default"] = p["value"]
|
||
|
||
var wfile := FileAccess.open(path, FileAccess.WRITE)
|
||
if wfile == null:
|
||
push_error("DP.save: cannot write " + path)
|
||
return
|
||
wfile.store_string(src)
|
||
wfile.close()
|
||
|
||
|
||
func _fmt_float(v: float) -> String:
|
||
var s := "%.6g" % v
|
||
if not ("." in s or "e" in s):
|
||
s += ".0"
|
||
return s
|
||
|
||
|
||
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"]
|