Unveränderter Ausgangsstand inklusive Masterprompt und Konzeptbildern unter assets/. .godot/ und docs/screenshots/ bleiben laut .gitignore unversioniert; letztere sind unter ../backups gesichert. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
89 lines
3.3 KiB
GDScript
89 lines
3.3 KiB
GDScript
extends Node3D
|
|
## Rigid stone joints: meshes shared across units, transforms owned per instance.
|
|
|
|
var asset_id: String = ""
|
|
var parts: Dictionary = {}
|
|
var rest_bounds: AABB
|
|
var _walk: float = 0.0
|
|
var _hit_material: StandardMaterial3D
|
|
var _core_health: float = 1.0
|
|
var _core_damage: float = 0.0
|
|
var _core_activate: float = 0.0
|
|
|
|
func setup(id: String, groups: Dictionary, bounds: AABB) -> void:
|
|
asset_id = id
|
|
rest_bounds = bounds
|
|
name = "Animated_" + id
|
|
_hit_material = StandardMaterial3D.new()
|
|
_hit_material.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED
|
|
_hit_material.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA
|
|
_hit_material.albedo_color = Color(1.0, .83, .49, 0.0)
|
|
for key: String in groups:
|
|
var instance := MeshInstance3D.new()
|
|
instance.name = key
|
|
instance.mesh = groups[key].mesh
|
|
instance.position = groups[key].pivot
|
|
instance.set_meta("rest", instance.position)
|
|
instance.material_overlay = _hit_material
|
|
add_child(instance)
|
|
parts[key] = instance
|
|
|
|
func set_core_health(ratio: float) -> void:
|
|
var next: float = clampf(ratio, 0.0, 1.0)
|
|
if next < _core_health - .002:
|
|
_core_damage = 1.0
|
|
_core_health = next
|
|
|
|
func trigger_activate() -> void:
|
|
_core_activate = 1.0
|
|
|
|
func pose(time: float, moving: bool, attack: float, ability: float, hit: float, delta: float = 0.0) -> void:
|
|
_walk = move_toward(_walk, 1.0 if moving else 0.0, .12)
|
|
var stride: float = sin(time * 8.0) * _walk
|
|
var strike: float = sin(clampf(attack / .28, 0.0, 1.0) * PI)
|
|
_core_damage = maxf(0.0, _core_damage - delta * 1.8)
|
|
_core_activate = maxf(0.0, _core_activate - delta * .55)
|
|
_hit_material.albedo_color.a = clampf(maxf(hit * 2.4, _core_damage * .45), 0.0, .5)
|
|
for key: String in parts:
|
|
var part: MeshInstance3D = parts[key]
|
|
part.position = part.get_meta("rest")
|
|
part.rotation = Vector3.ZERO
|
|
part.scale = Vector3.ONE
|
|
if key.begins_with("Leg"):
|
|
var side: float = 1.0 if key.begins_with("LegL") else -1.0
|
|
if key.right(1).is_valid_int() and int(key.right(1)) % 2 == 1:
|
|
side *= -1.0
|
|
part.rotation.x = stride * side * .30
|
|
part.position.y += maxf(0, stride * side) * .05
|
|
continue
|
|
match key:
|
|
"ArmL", "ArmR":
|
|
var side: float = 1.0 if key == "ArmL" else -1.0
|
|
part.rotation.x = -stride * side * .16 - strike * (.52 if asset_id in ["g01","g02","g03","g04","e05","e08"] else .12)
|
|
part.rotation.z = strike * side * .08
|
|
"Weapon":
|
|
part.position.z -= strike * (.22 if asset_id == "g06" else .10)
|
|
if asset_id == "g05":
|
|
part.rotation.y = strike * .22
|
|
"Mortar":
|
|
part.rotation.x = -strike * .16
|
|
part.position.y -= strike * .07
|
|
"Flame":
|
|
part.scale.y = 1.0 + sin(time * 11.0) * .09 + ability * .45
|
|
"Crystal":
|
|
# Activation flare, calm float, then a readable shudder when hurt.
|
|
var distress: float = 1.0 - _core_health
|
|
var pulse: float = sin(time * (1.5 + distress * 2.2))
|
|
part.position.y += pulse * (.045 + distress * .018) + _core_activate * .14
|
|
part.rotation.y = sin(time * .35) * .08 + _core_damage * .16 * sin(time * 36.0)
|
|
part.scale = Vector3.ONE * (1.0 + _core_activate * .18 + _core_damage * .07)
|
|
"Body":
|
|
part.rotation.z = stride * .025
|
|
if asset_id in ["e03","e06","e09"]:
|
|
part.position.y += sin(time*2.4)*.06
|
|
if asset_id == "e10":
|
|
part.rotation.x = -strike*.15
|
|
part.position.z -= strike*.10
|
|
|
|
func get_aabb() -> AABB:
|
|
return rest_bounds
|