diff --git a/debug_draw.gd b/debug_draw.gd index 6ca6b1b..15709ed 100644 --- a/debug_draw.gd +++ b/debug_draw.gd @@ -10,6 +10,7 @@ extends Node ## ## Toggle from the console: ## show_collisions · show_hitboxes · show_bones · show_raycasts (true / false) +## show_hitboxes also surfaces the bull's and bear's body capsules, not just Area3Ds ## show_states — floating AI-state tags + velocity vectors over each matador ## show_animation_name — floating current-clip tag over every AnimationPlayer host ## show_stats — 2D corner readout: fps / frame ms / draw calls / matador tally @@ -421,7 +422,10 @@ func _collect(node: Node, col: bool, hit: bool, bone: bool, anim: bool, wanted: # Ragdoll bone colliders (PhysicalBone3D) are excluded — use show_bones for # the skeleton; otherwise every corpse floods the view with capsules. var is_body := parent is PhysicsBody3D and not (parent is PhysicalBone3D) - if (is_area and hit) or (is_body and col): + # The bull's and bear's body capsules are combat volumes too, so they also + # surface under show_hitboxes (not just show_collisions). + var is_combatant := is_body and (parent.is_in_group(&"player") or parent.is_in_group(&"bear")) + if (is_area and hit) or (is_body and col) or (is_combatant and hit): wanted[cs.get_instance_id()] = [cs, is_area] for child in node.get_children(): _collect(child, col, hit, bone, anim, wanted) diff --git a/debug_params.gd b/debug_params.gd index f0e4ca3..3e46db2 100644 --- a/debug_params.gd +++ b/debug_params.gd @@ -433,12 +433,22 @@ func save() -> void: if p["value"] == p["default"]: continue var re := RegEx.new() + var literal := "" 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)) + literal = _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")) + literal = "true" if bool(p["value"]) else "false" + var m := re.search(src) + if m == null: + push_warning("DP.save: no _reg_ line found for '%s' — skipped" % key) + continue + # Splice the value in by index rather than RegEx.sub(): sub()'s replacement + # string parses "$n" as a backreference, so "$1"+"12.5" becomes "$112.5" + # (group 112 → PCRE2 error → mangled output). Indexed splice inserts the + # literal verbatim, exactly the value the user entered. + src = src.substr(0, m.get_start(2)) + literal + src.substr(m.get_end(2)) p["default"] = p["value"] var wfile := FileAccess.open(path, FileAccess.WRITE) @@ -449,8 +459,12 @@ func save() -> void: wfile.close() +# Godot's String % operator has no "g" conversion — "%.6g" % v slips past the +# compiler (v is not const) but emits the literal "%.6g" at runtime, which would be +# written straight into the source. "%s" gives the shortest round-tripping form, +# matching the value the user entered; the guard keeps it a float literal. func _fmt_float(v: float) -> String: - var s := "%.6g" % v + var s := "%s" % v if not ("." in s or "e" in s): s += ".0" return s