Hands/POV - Cut a real first-person arms rig out of the GODVERSE modular character kit (tools/gen_fps_arms.py): ch01 hands + per-side sleeves on the full 65-bone mixamorig skeleton, so all 20 finger bones per hand are poseable at runtime. Textures shrunk to 1k; 4.2 MB. - ViewModel.gd instances that rig ONCE PER HAND and places each instance so its own hand bone lands on the grip — no IK. Grip orientation is measured off the rig at load (pinky->index knuckle = bore axis, elbow->hand = forearm dir), so it survives re-tuning grip_rest_rot instead of needing new euler angles. - Motion layers: look-sway with spring-back, walk bob scaled by speed and weapon heft, idle breathe, landing dip, weapon lower/raise on swap. - Sleeve material overridden (donor asset is a fantasy leather bracer); hand material forced non-metallic (its spec/gloss maps rendered skin as bronze). Weapons - Weapon.gd replaces MeleeAttack: 6 weapons, 4 swing archetypes, and the weapon-vs-material matrix from the founding chat. - Smashable moves from binary hits_to_break to hp/toughness, giving three outcomes: break, dent, or futile (dead clank, no score, HUD nudge). The box cutter genuinely shreds cardboard and genuinely cannot hurt a filing cabinet. - The hit lands at Weapon.contact THROUGH the swing, not on the click — that delay is most of why the sledge feels different from the cutter. - Slots on 1-6 / wheel / Q; game modes moved to M, HUD cycle to H. HUD - Hud.gd: Arcade, Minimal, Work Order (a corporate destruction docket that fills in line items) and Dev, over one shared data feed. Scoring + combo multipliers. Dev harness (not shipped) - macOS screen-recording perms aren't available to the CLI, so the game records itself: dev/demo.tscn + DemoDriver.gd drive a scripted tour for --write-movie, and dev/probe_*.gd print rig/scale/placement numbers. Fix: tools/gen_viewmodel.py box() scaled by size/2 on top of primitive_cube_add's already-unit side length, halving every box — which detached the bat's blade. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
53 lines
1.8 KiB
GDScript
53 lines
1.8 KiB
GDScript
extends SceneTree
|
|
|
|
## What units does the imported arms rig actually live in? The Blender side reports bone
|
|
## lengths in centimetres but a metre-scale mesh AABB, so measure it in-engine with the
|
|
## scene actually in a tree (skinned AABBs are meaningless before that).
|
|
|
|
func _initialize() -> void:
|
|
var root := Node3D.new()
|
|
get_root().add_child(root)
|
|
var ps := load("res://assets/viewmodel/fps_arms.glb") as PackedScene
|
|
var inst: Node3D = ps.instantiate()
|
|
root.add_child(inst)
|
|
|
|
print("inst.transform = ", inst.transform)
|
|
for c in inst.get_children():
|
|
print(" child ", c.name, " <", c.get_class(), "> xform=", (c as Node3D).transform)
|
|
|
|
var skel := _skel(inst)
|
|
print("skel.transform = ", skel.transform)
|
|
print("skel global (rel inst) = ", inst.global_transform.affine_inverse() * skel.global_transform)
|
|
|
|
for n in ["mixamorig_RightHand", "mixamorig_RightForeArm", "mixamorig_RightHandIndex1"]:
|
|
var i := skel.find_bone(n)
|
|
print("%-30s global_rest.origin = %s" % [n, skel.get_bone_global_rest(i).origin])
|
|
|
|
var hr := skel.find_bone("mixamorig_RightHand")
|
|
var fa := skel.find_bone("mixamorig_RightForeArm")
|
|
var forearm_len: float = (skel.get_bone_global_rest(hr).origin
|
|
- skel.get_bone_global_rest(fa).origin).length()
|
|
print("forearm length (skeleton units) = ", forearm_len)
|
|
|
|
for mi in _meshes(inst):
|
|
var m := mi as MeshInstance3D
|
|
print("mesh %-16s local aabb=%s global aabb size=%s" % [
|
|
m.name, m.get_aabb().size, m.get_global_transform().basis * m.get_aabb().size])
|
|
quit()
|
|
|
|
func _skel(n: Node) -> Skeleton3D:
|
|
if n is Skeleton3D:
|
|
return n
|
|
for c in n.get_children():
|
|
var r := _skel(c)
|
|
if r != null:
|
|
return r
|
|
return null
|
|
|
|
func _meshes(n: Node, acc: Array = []) -> Array:
|
|
if n is MeshInstance3D:
|
|
acc.append(n)
|
|
for c in n.get_children():
|
|
_meshes(c, acc)
|
|
return acc
|