Reorganize the codebase into role-based folders (snake_case)
Move the 40-odd root-level scripts and scenes into a tree that groups by role,
per the approved roadmap (WS2/WS3): actors/{player,matador,bear}, systems/{combat,
fx,input,debug,render,crowd,config}, ui/, props/ (was tscn_s/). Rename the shell
scene.tscn -> levels/game_shell.tscn and every PascalCase scene to snake_case
(Player.tscn -> player.tscn, MainMenu.tscn -> main_menu.tscn, etc.) so the
case-insensitive web/macOS filesystems can't alias two files together.
Done as a scripted move: each file travels with its .uid; every quoted res:// path
across scenes, scripts, .tres, and project.godot's 9 autoloads is rewritten; the
.godot uid/class cache is rebuilt from scratch. Scenes still resolve by uid, so the
rewrite is belt-and-suspenders. Lint globs (run_tests.sh + both CI workflows) now
walk the new dirs; an orphan animation_tree.gd.uid and 7 pre-existing trailing-
whitespace lints (barrel/torch, never covered by the old root-only glob) are cleaned.
Full suite green on both sides. Asset consolidation (Assets/Animations/fonts ->
art/) is deferred — moving imported .glb/.png/.ttf is safer done in the editor.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017KoYBYQgRyY1zDHXMsXY3V
This commit is contained in:
@@ -0,0 +1,295 @@
|
||||
extends Node
|
||||
## Body wobble and tail simulation. Legs stay in rest pose (no IK, no ragdoll).
|
||||
## Created at runtime by player.gd; call setup() before the first _process tick.
|
||||
|
||||
var _player: CharacterBody3D
|
||||
var _bull: Node3D
|
||||
var _skeleton: Skeleton3D
|
||||
|
||||
# Body wobble
|
||||
var _prev_vel: Vector3 = Vector3.ZERO
|
||||
var _tilt_x: float = 0.0
|
||||
var _tilt_z: float = 0.0
|
||||
var _aerial_pitch: float = 0.0
|
||||
|
||||
var charge_pitch_target: float = 0.0
|
||||
var _charge_pitch_curr: float = 0.0
|
||||
|
||||
# When true, another system (the roll's ball-tumble) owns the bull's full
|
||||
# orientation — skip writing body wobble so we don't fight it.
|
||||
var external_rotation: bool = false
|
||||
|
||||
# Tail — Verlet chain simulation
|
||||
const TAIL_BONES: Array = [
|
||||
&"tail_1", &"tail_2", &"tail_3", &"tail_4",
|
||||
&"tail_5", &"tail_6",
|
||||
&"tail_tip_1", &"tail_tip_2", &"tail_tip_2_end",
|
||||
]
|
||||
var _tail_idx: Array[int] = []
|
||||
var _tail_world: Array[Vector3] = []
|
||||
var _tail_prev: Array[Vector3] = []
|
||||
var _tail_lengths: Array[float] = []
|
||||
var _tail_rest_dir: Array[Vector3] = []
|
||||
var _tail_parent_idx: int = -1
|
||||
|
||||
var tail_ragdoll: bool = false
|
||||
var _prev_on_floor: bool = true
|
||||
|
||||
var _dbg_on: bool = false
|
||||
var _dbg_nodes: Array[MeshInstance3D] = []
|
||||
|
||||
|
||||
func setup(player: CharacterBody3D, bull: Node3D) -> void:
|
||||
_player = player
|
||||
_bull = bull
|
||||
_skeleton = _find_skeleton(bull)
|
||||
if not _skeleton:
|
||||
push_error("BullLegs: Skeleton3D not found under bull")
|
||||
return
|
||||
|
||||
# Disable any physical bone simulator
|
||||
var phys_sim := _find_physical_bones(_skeleton)
|
||||
if phys_sim:
|
||||
phys_sim.active = false
|
||||
|
||||
_setup_tail()
|
||||
|
||||
|
||||
func _setup_tail() -> void:
|
||||
for bone_name: StringName in TAIL_BONES:
|
||||
var idx: int = _skeleton.find_bone(bone_name)
|
||||
if idx == -1:
|
||||
push_warning("BullLegs: tail bone '%s' not found" % bone_name)
|
||||
continue
|
||||
_tail_idx.append(idx)
|
||||
|
||||
if _tail_idx.size() < 2:
|
||||
push_error("BullLegs: not enough tail bones found")
|
||||
return
|
||||
|
||||
for idx: int in _tail_idx:
|
||||
var world: Vector3 = _skeleton.to_global(_skeleton.get_bone_global_rest(idx).origin)
|
||||
_tail_world.append(world)
|
||||
_tail_prev.append(world)
|
||||
|
||||
var max_sep: float = 0.0
|
||||
for i in range(_tail_world.size() - 1):
|
||||
max_sep = maxf(max_sep, _tail_world[i].distance_to(_tail_world[i + 1]))
|
||||
if max_sep < 0.01:
|
||||
push_warning("BullLegs: tail bones have zero separation in rest pose, distributing along spine")
|
||||
var root: Vector3 = _tail_world[0]
|
||||
var back: Vector3 = (_skeleton.global_transform.basis.z + Vector3.DOWN * 0.3).normalized()
|
||||
for i in range(_tail_world.size()):
|
||||
_tail_world[i] = root + back * (i * 0.09)
|
||||
_tail_prev[i] = _tail_world[i]
|
||||
|
||||
const MIN_SEG: float = 0.06
|
||||
for i in range(_tail_world.size() - 1):
|
||||
var seg_len: float = _tail_world[i].distance_to(_tail_world[i + 1])
|
||||
_tail_lengths.append(maxf(seg_len, MIN_SEG))
|
||||
|
||||
for i in range(_tail_world.size() - 1):
|
||||
var p1_skel: Vector3 = _skeleton.to_local(_tail_world[i])
|
||||
var p2_skel: Vector3 = _skeleton.to_local(_tail_world[i + 1])
|
||||
var seg_skel: Vector3 = p2_skel - p1_skel
|
||||
_tail_rest_dir.append(seg_skel.normalized() if seg_skel.length() > 0.001 else Vector3(0, 0, 1))
|
||||
_tail_rest_dir.append(_tail_rest_dir[-1])
|
||||
|
||||
_tail_parent_idx = _skeleton.get_bone_parent(_tail_idx[0])
|
||||
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
if not _skeleton:
|
||||
return
|
||||
_wobble_body(delta)
|
||||
_update_tail(delta)
|
||||
_apply_tail()
|
||||
if DP.b("show_tail") != _dbg_on:
|
||||
_dbg_toggle()
|
||||
if _dbg_on:
|
||||
_dbg_update()
|
||||
|
||||
|
||||
# ── Body Wobble ───────────────────────────────────────────────────────────────
|
||||
|
||||
func _wobble_body(delta: float) -> void:
|
||||
var vel: Vector3 = _player.velocity
|
||||
var accel: Vector3 = (vel - _prev_vel) / maxf(delta, 0.001)
|
||||
_prev_vel = vel
|
||||
|
||||
var la: Vector3 = _bull.global_transform.basis.inverse() * accel
|
||||
|
||||
var tx := clampf(-la.z * DP.f("body_tilt_fwd"), -0.35, 0.35)
|
||||
var tz := clampf(-la.x * DP.f("body_tilt_side"), -0.25, 0.25)
|
||||
|
||||
_tilt_x = lerpf(_tilt_x, tx, delta * 10.0)
|
||||
_tilt_z = lerpf(_tilt_z, tz, delta * 10.0)
|
||||
|
||||
var flat_spd: float = Vector2(vel.x, vel.z).length()
|
||||
var target_pitch: float = 0.0
|
||||
if not _player.is_on_floor() and flat_spd > 0.5:
|
||||
target_pitch = clampf(-atan2(vel.y, flat_spd) * DP.f("aerial_pitch_scale"), -1.4, 1.4)
|
||||
_aerial_pitch = lerpf(_aerial_pitch, target_pitch, delta * DP.f("aerial_pitch_speed"))
|
||||
|
||||
_charge_pitch_curr = lerpf(_charge_pitch_curr, charge_pitch_target, delta * DP.f("charge_head_speed"))
|
||||
if external_rotation:
|
||||
return
|
||||
_bull.rotation.x = _tilt_x + _aerial_pitch + _charge_pitch_curr
|
||||
_bull.rotation.z = _tilt_z
|
||||
|
||||
|
||||
# ── Tail ──────────────────────────────────────────────────────────────────────
|
||||
|
||||
func _update_tail(delta: float) -> void:
|
||||
if _tail_world.is_empty():
|
||||
return
|
||||
|
||||
var gravity := Vector3(0.0, -DP.f("tail_gravity"), 0.0)
|
||||
var damping := 1.0 - clampf(DP.f("tail_damping"), 0.0, 0.99)
|
||||
|
||||
var anchor: Vector3
|
||||
if _tail_parent_idx >= 0:
|
||||
var parent_t := _skeleton.get_bone_global_pose(_tail_parent_idx)
|
||||
anchor = _skeleton.to_global((parent_t * _skeleton.get_bone_rest(_tail_idx[0])).origin)
|
||||
else:
|
||||
anchor = _skeleton.to_global(_skeleton.get_bone_global_rest(_tail_idx[0]).origin)
|
||||
_tail_world[0] = anchor
|
||||
_tail_prev[0] = anchor
|
||||
|
||||
var on_floor := _player.is_on_floor()
|
||||
if not on_floor and _prev_on_floor:
|
||||
# Bull just left the ground — push all tail particles upward with it
|
||||
for i: int in range(1, _tail_world.size()):
|
||||
_tail_prev[i] = _tail_world[i] - _player.velocity * delta
|
||||
_prev_on_floor = on_floor
|
||||
|
||||
var gravity_mult: float
|
||||
if tail_ragdoll:
|
||||
gravity_mult = 2.5
|
||||
elif not on_floor:
|
||||
gravity_mult = 0.15
|
||||
else:
|
||||
gravity_mult = 1.0
|
||||
gravity *= gravity_mult
|
||||
|
||||
var flat_speed: float = Vector2(_player.velocity.x, _player.velocity.z).length()
|
||||
var wag_strength: float = lerpf(DP.f("tail_wag_idle"), 0.0, clampf(flat_speed / 3.0, 0.0, 1.0))
|
||||
var wag_freq: float = DP.f("tail_wag_freq")
|
||||
var time: float = Time.get_ticks_msec() / 1000.0
|
||||
var basis_x: Vector3 = _bull.global_transform.basis.x
|
||||
|
||||
for i in range(1, _tail_world.size()):
|
||||
var vel: Vector3 = (_tail_world[i] - _tail_prev[i]) * damping
|
||||
_tail_prev[i] = _tail_world[i]
|
||||
var wag := Vector3.ZERO if tail_ragdoll \
|
||||
else basis_x * sin(time * wag_freq + i * 0.5) * wag_strength
|
||||
_tail_world[i] = _tail_world[i] + vel + gravity * (delta * delta) + wag * delta
|
||||
|
||||
for i in range(1, _tail_world.size()):
|
||||
var dir: Vector3 = _tail_world[i] - _tail_world[i - 1]
|
||||
var len: float = dir.length()
|
||||
var target_len: float = _tail_lengths[i - 1]
|
||||
if len > 0.0001:
|
||||
_tail_world[i] = _tail_world[i - 1] + dir * (target_len / len)
|
||||
else:
|
||||
_tail_world[i] = _tail_world[i - 1] + Vector3(0.0, -target_len, 0.0)
|
||||
|
||||
var body_radius: float = DP.f("tail_body_radius")
|
||||
for i in range(1, _tail_world.size()):
|
||||
var p := _bull.to_local(_tail_world[i])
|
||||
var closest := Vector3(0.0, 0.0, clampf(p.z, -0.3, 0.5))
|
||||
var diff := p - closest
|
||||
var dist := diff.length()
|
||||
if dist < body_radius and dist > 0.001:
|
||||
p = closest + diff.normalized() * body_radius
|
||||
_tail_world[i] = _bull.to_global(p)
|
||||
|
||||
|
||||
func _apply_tail() -> void:
|
||||
if _tail_world.is_empty():
|
||||
return
|
||||
|
||||
var n := _tail_world.size()
|
||||
var local_pos: Array[Vector3] = []
|
||||
local_pos.resize(n)
|
||||
for i in n:
|
||||
local_pos[i] = _skeleton.to_local(_tail_world[i])
|
||||
|
||||
for i in n:
|
||||
var idx: int = _tail_idx[i]
|
||||
var pos_skel: Vector3 = local_pos[i]
|
||||
|
||||
var point_dir_skel: Vector3
|
||||
if i < n - 1:
|
||||
point_dir_skel = (local_pos[i + 1] - pos_skel).normalized()
|
||||
else:
|
||||
point_dir_skel = (pos_skel - local_pos[i - 1]).normalized()
|
||||
|
||||
var rest_dir: Vector3 = _tail_rest_dir[i]
|
||||
var rest_t: Transform3D = _skeleton.get_bone_global_rest(idx)
|
||||
var new_basis: Basis
|
||||
if rest_dir.length_squared() > 0.0001 and point_dir_skel.length_squared() > 0.0001:
|
||||
new_basis = Basis(Quaternion(rest_dir, point_dir_skel)) * rest_t.basis
|
||||
else:
|
||||
new_basis = rest_t.basis
|
||||
|
||||
_skeleton.set_bone_global_pose_override(idx, Transform3D(new_basis, pos_skel), 1.0, false)
|
||||
|
||||
|
||||
# ── Debug Visualization ───────────────────────────────────────────────────────
|
||||
|
||||
func _dbg_toggle() -> void:
|
||||
if _dbg_on:
|
||||
for n: MeshInstance3D in _dbg_nodes:
|
||||
if is_instance_valid(n):
|
||||
n.queue_free()
|
||||
_dbg_nodes.clear()
|
||||
_dbg_on = false
|
||||
else:
|
||||
_dbg_build()
|
||||
_dbg_on = true
|
||||
|
||||
|
||||
func _dbg_build() -> void:
|
||||
var root: Node = _player.get_parent()
|
||||
var n: int = _tail_world.size()
|
||||
for i: int in n:
|
||||
var mat := StandardMaterial3D.new()
|
||||
mat.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED
|
||||
mat.render_priority = 1
|
||||
mat.albedo_color = Color.RED if i == 0 \
|
||||
else Color(1.0 - float(i) / n, 0.4 + 0.6 * float(i) / n, 0.0)
|
||||
var sm := SphereMesh.new()
|
||||
sm.radius = 0.10 if i == 0 else 0.06
|
||||
sm.height = sm.radius * 2.0
|
||||
sm.radial_segments = 6
|
||||
sm.rings = 3
|
||||
sm.material = mat
|
||||
var mi := MeshInstance3D.new()
|
||||
mi.mesh = sm
|
||||
root.add_child(mi)
|
||||
_dbg_nodes.append(mi)
|
||||
|
||||
|
||||
func _dbg_update() -> void:
|
||||
for i: int in _dbg_nodes.size():
|
||||
_dbg_nodes[i].global_position = _tail_world[i]
|
||||
|
||||
|
||||
# ── Utility ───────────────────────────────────────────────────────────────────
|
||||
|
||||
func _find_skeleton(node: Node) -> Skeleton3D:
|
||||
if node is Skeleton3D:
|
||||
return node as Skeleton3D
|
||||
for child in node.get_children():
|
||||
var r := _find_skeleton(child)
|
||||
if r:
|
||||
return r
|
||||
return null
|
||||
|
||||
|
||||
func _find_physical_bones(node: Node) -> PhysicalBoneSimulator3D:
|
||||
for child in node.get_children():
|
||||
if child is PhysicalBoneSimulator3D:
|
||||
return child as PhysicalBoneSimulator3D
|
||||
return null
|
||||
@@ -0,0 +1 @@
|
||||
uid://bvtw8s41wrrx
|
||||
@@ -0,0 +1,140 @@
|
||||
class_name IsoCamera
|
||||
extends Camera3D
|
||||
|
||||
@export var height: float = 25.0
|
||||
@export var horizontal_distance: float = 25.0
|
||||
@export var horizontal_angle_deg: float = 45.0
|
||||
|
||||
# Perspective zoom (FOV)
|
||||
@export var fov_min: float = 20.0
|
||||
@export var fov_max: float = 75.0
|
||||
@export var default_fov: float = 30.0
|
||||
|
||||
@export var focus_slice_thickness: float = 6.0
|
||||
@export var blur_transition: float = 15.0
|
||||
|
||||
var _shake_amount: float = 0.0
|
||||
var _shake_decay: float = 0.0
|
||||
var _user_fov: float = 0.0
|
||||
|
||||
# Per-level framing multiplier: 1.0 = the designer's base shot, >1 dollies the camera
|
||||
# back for a wider view (the lobby uses this). Set by game_shell when a level loads;
|
||||
# kept separate from the scroll-wheel FOV zoom so the two don't fight.
|
||||
var _framing_scale: float = 1.0
|
||||
|
||||
# Trailing-camera state: _focus is the smoothed point the camera frames (it lags
|
||||
# the bull), _drag_offset is the velocity-driven trail that slides it behind.
|
||||
var _focus: Vector3 = Vector3.ZERO
|
||||
var _drag_offset: Vector3 = Vector3.ZERO
|
||||
var _focus_init: bool = false
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
set_as_top_level(true)
|
||||
|
||||
projection = Camera3D.PROJECTION_PERSPECTIVE
|
||||
fov = default_fov
|
||||
_user_fov = default_fov
|
||||
|
||||
near = 0.1
|
||||
far = 150.0
|
||||
|
||||
|
||||
func _unhandled_input(event: InputEvent) -> void:
|
||||
if event.is_action_pressed("zoom_in"):
|
||||
_user_fov = clamp(_user_fov / 1.1, fov_min, fov_max)
|
||||
|
||||
if event.is_action_pressed("zoom_out"):
|
||||
_user_fov = clamp(_user_fov * 1.1, fov_min, fov_max)
|
||||
|
||||
|
||||
# Pinch-to-zoom hook for the touch UI. `ratio` is the two-finger spread this frame over
|
||||
# last frame: >1 (fingers parting) narrows the FOV to zoom in, <1 widens it to pull back,
|
||||
# mirroring the scroll-wheel zoom_in/zoom_out feel.
|
||||
func adjust_zoom(ratio: float) -> void:
|
||||
if ratio <= 0.0:
|
||||
return
|
||||
_user_fov = clampf(_user_fov / ratio, fov_min, fov_max)
|
||||
|
||||
|
||||
## Dolly the camera in/out for the level being loaded. 1.0 is the base framing; >1 pulls
|
||||
## back for a wider shot (the lobby hub uses this). Independent of the scroll-wheel zoom.
|
||||
func set_framing_scale(scale: float) -> void:
|
||||
_framing_scale = maxf(scale, 0.1)
|
||||
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
fov = lerpf(fov, _user_fov, delta * 8.0)
|
||||
|
||||
var angle_rad := deg_to_rad(horizontal_angle_deg)
|
||||
|
||||
var offset := Vector3(
|
||||
sin(angle_rad) * horizontal_distance * _framing_scale,
|
||||
height * _framing_scale,
|
||||
cos(angle_rad) * horizontal_distance * _framing_scale
|
||||
)
|
||||
|
||||
var target := get_parent() as Node3D
|
||||
var focus := _drag_focus(target, delta)
|
||||
|
||||
global_position = focus + offset
|
||||
look_at(focus, Vector3.UP)
|
||||
|
||||
_update_dof(focus)
|
||||
|
||||
if _shake_amount > 0.005:
|
||||
global_position += Vector3(
|
||||
randf_range(-_shake_amount, _shake_amount),
|
||||
randf_range(-_shake_amount * 0.25, _shake_amount * 0.25),
|
||||
randf_range(-_shake_amount, _shake_amount)
|
||||
)
|
||||
|
||||
_shake_amount = move_toward(_shake_amount, 0.0, _shake_decay * delta)
|
||||
|
||||
|
||||
# Smoothed follow point that drags behind the bull. The target trail sits opposite
|
||||
# the bull's flat velocity (cam_drag metres per m/s); the offset and the focus both
|
||||
# ease toward their targets so the camera lags and settles rather than snapping.
|
||||
func _drag_focus(target: Node3D, delta: float) -> Vector3:
|
||||
var pos := target.global_position
|
||||
if not _focus_init:
|
||||
_focus = pos
|
||||
_focus_init = true
|
||||
|
||||
var vel := Vector3.ZERO
|
||||
if target is CharacterBody3D:
|
||||
vel = (target as CharacterBody3D).velocity
|
||||
vel.y = 0.0
|
||||
|
||||
var drag_target := -vel * DP.f("cam_drag")
|
||||
_drag_offset = _drag_offset.lerp(drag_target, clampf(DP.f("cam_drag_speed") * delta, 0.0, 1.0))
|
||||
_focus = _focus.lerp(pos + _drag_offset, clampf(DP.f("cam_follow_lerp") * delta, 0.0, 1.0))
|
||||
return _focus
|
||||
|
||||
|
||||
func trigger_hit(strength: float) -> void:
|
||||
if not Settings.screen_shake:
|
||||
return
|
||||
_shake_amount = strength * 0.5
|
||||
_shake_decay = _shake_amount / 0.4
|
||||
|
||||
|
||||
func _update_dof(target_pos: Vector3) -> void:
|
||||
var cam_attr: CameraAttributesPractical = null
|
||||
|
||||
if attributes is CameraAttributesPractical:
|
||||
cam_attr = attributes
|
||||
|
||||
if cam_attr == null:
|
||||
return
|
||||
|
||||
var distance := global_position.distance_to(target_pos)
|
||||
|
||||
cam_attr.dof_blur_near_distance = max(distance - focus_slice_thickness * 0.5, near + 0.1)
|
||||
cam_attr.dof_blur_far_distance = distance + focus_slice_thickness * 0.5
|
||||
|
||||
cam_attr.dof_blur_near_transition = blur_transition
|
||||
cam_attr.dof_blur_far_transition = blur_transition
|
||||
|
||||
cam_attr.dof_blur_near_enabled = false
|
||||
cam_attr.dof_blur_far_enabled = false
|
||||
@@ -0,0 +1 @@
|
||||
uid://cpyq2r5cq653g
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1 @@
|
||||
uid://bn777gguclud5
|
||||
@@ -0,0 +1,52 @@
|
||||
[gd_scene format=3 uid="uid://crtm0xtiql3r8"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://bn777gguclud5" path="res://actors/player/player.gd" id="1_xhfnw"]
|
||||
[ext_resource type="Script" uid="uid://cpyq2r5cq653g" path="res://actors/player/camera_iso.gd" id="2_camera_iso"]
|
||||
[ext_resource type="PackedScene" uid="uid://bun14xmk20pcj" path="res://Assets/bull.fbx" id="4_e80uo"]
|
||||
|
||||
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_kne1u"]
|
||||
radius = 0.7495117
|
||||
height = 1.845398
|
||||
|
||||
[node name="Player" type="CharacterBody3D" unique_id=165510044]
|
||||
collision_layer = 2
|
||||
collision_mask = 9
|
||||
script = ExtResource("1_xhfnw")
|
||||
|
||||
[node name="CollisionBull" type="CollisionShape3D" parent="." unique_id=571780801]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.29183745, 0.3197594)
|
||||
shape = SubResource("CapsuleShape3D_kne1u")
|
||||
|
||||
[node name="Camera3D" type="Camera3D" parent="." unique_id=1120161087]
|
||||
script = ExtResource("2_camera_iso")
|
||||
|
||||
[node name="bull" parent="." unique_id=1386495166 instance=ExtResource("4_e80uo")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.655, 0.23)
|
||||
|
||||
[node name="Skeleton3D" parent="bull/Armature" parent_id_path=PackedInt32Array(1386495166, 1942410469) index="0" unique_id=550138996]
|
||||
bones/0/position = Vector3(0, 0, 0.009963839)
|
||||
bones/0/rotation = Quaternion(0.7071068, 0, 0, 0.7071067)
|
||||
bones/0/scale = Vector3(1, 1, 1)
|
||||
bones/1/position = Vector3(0.003526625, -0.0043296535, 0.0040827994)
|
||||
bones/1/rotation = Quaternion(-0.00038647873, 0.06909673, 0.9868542, -0.14609687)
|
||||
bones/2/rotation = Quaternion(-0.06929122, 3.2175163e-07, -0.112670615, 0.99121344)
|
||||
bones/4/position = Vector3(0.0045358227, -0.002137695, -0.004238624)
|
||||
bones/4/rotation = Quaternion(-0.24948503, 0.19590352, 0.9416978, -0.11217985)
|
||||
bones/4/scale = Vector3(1.0000001, 0.9999999, 1.0000001)
|
||||
bones/5/rotation = Quaternion(-0.58943665, -0.3660725, -0.22564478, 0.683842)
|
||||
bones/5/scale = Vector3(1, 1.0000001, 0.99999994)
|
||||
bones/6/rotation = Quaternion(0.52910197, 0.15997827, 0.120245, 0.8246207)
|
||||
bones/6/scale = Vector3(1, 1, 1.0000001)
|
||||
bones/17/position = Vector3(0, 0.0009373814, 0.007552617)
|
||||
bones/17/rotation = Quaternion(-9.4156974e-08, 0.7071068, 0.7071067, -9.4156974e-08)
|
||||
bones/19/position = Vector3(-0.003526625, -0.0043296535, 0.0040827994)
|
||||
bones/19/rotation = Quaternion(0.00038647873, 0.06909673, 0.9868542, 0.14609687)
|
||||
bones/20/rotation = Quaternion(-0.06929122, -3.2227587e-07, 0.11267061, 0.99121344)
|
||||
bones/22/position = Vector3(-0.0045358227, -0.002137695, -0.004238624)
|
||||
bones/22/rotation = Quaternion(0.24948503, 0.19590352, 0.9416978, 0.11217985)
|
||||
bones/23/rotation = Quaternion(-0.58943665, 0.3660725, 0.22564478, 0.683842)
|
||||
bones/23/scale = Vector3(1, 1.0000001, 1)
|
||||
bones/24/rotation = Quaternion(0.529102, -0.15997836, -0.120245025, 0.82462066)
|
||||
bones/24/scale = Vector3(1, 1.0000001, 1)
|
||||
|
||||
[editable path="bull"]
|
||||
Reference in New Issue
Block a user