extends RefCounted ## Original rift creatures for the six enemy types used in the eight-wave slice. ## Generated once, then batched by material. They have no Phase 3 icon reference. static var _cache: Dictionary = {} static func create(data: Dictionary) -> Node3D: var id: String = data.get("id", "") if not id in ["e01", "e02", "e03", "e04", "e07", "e08"]: return null if not _cache.has(id): var root := Node3D.new() _build(root, id) _cache[id] = AssetLibrary.bake_mesh(root) root.free() var result := MeshInstance3D.new() result.name = "Rift_" + id result.mesh = _cache[id] return result static func _mat(hex: String, glow: bool = false) -> StandardMaterial3D: var mat := StandardMaterial3D.new() mat.albedo_color = Color(hex) mat.roughness = 0.85 mat.emission_enabled = glow mat.emission = Color(hex) mat.emission_energy_multiplier = 0.35 return mat static func _piece(root: Node3D, at: Vector3, size: Vector3, mat: Material, box: bool = false) -> MeshInstance3D: var instance := MeshInstance3D.new() if box: var mesh := BoxMesh.new() mesh.size = size instance.mesh = mesh else: var mesh := SphereMesh.new() mesh.radius = 0.5 mesh.height = 1.0 mesh.radial_segments = 6 mesh.rings = 2 instance.mesh = mesh instance.scale = size instance.material_override = mat instance.position = at root.add_child(instance) return instance static func _limb(root: Node3D, start: Vector3, end: Vector3, radius: float, mat: Material, tapered: bool = false) -> void: var mesh := CylinderMesh.new() mesh.height = start.distance_to(end) mesh.bottom_radius = radius mesh.top_radius = 0.0 if tapered else radius * 0.7 mesh.radial_segments = 5 var instance := MeshInstance3D.new() instance.mesh = mesh instance.material_override = mat instance.position = (start + end) * 0.5 instance.quaternion = Quaternion(Vector3.UP, (end - start).normalized()) root.add_child(instance) static func _build(root: Node3D, id: String) -> void: var dark := _mat("323e50") var shell := _mat("869aa6") var pale := _mat("d6dedc") var rift := _mat("d27b94", true) if id in ["e01", "e02"]: var heavy: bool = id == "e02" _piece(root, Vector3(0, .62, -.10), Vector3(1.12, .75 if heavy else .48, 1.15), dark) _piece(root, Vector3(0, .91 if heavy else .74, -.18), Vector3(1.08, .68 if heavy else .35, 1.1), shell) _piece(root, Vector3(0, .60, .54), Vector3(.60, .42, .48), dark) for side: float in [-1.0, 1.0]: for index: int in range(3): var z: float = -.50 + index * .40 var knee := Vector3(side * .73, .47, z + .10) _limb(root, Vector3(side * .30, .62, z), knee, .12 if heavy else .07, shell) _limb(root, knee, Vector3(side * .83, .04, z + .22), .075, dark, true) _piece(root, Vector3(side * .16, .69, .74), Vector3(.11, .10, .08), rift) _limb(root, Vector3(side * .22, .43, .65), Vector3(side * .40, .55, .92), .07, pale, true) if heavy: for z: float in [-.45, -.10, .25]: _limb(root, Vector3(0, 1.00, z), Vector3(0, 1.42, z -.10), .14, pale, true) elif id == "e03": _piece(root, Vector3(0, 1.14, 0), Vector3(.60, .75, .48), dark) _piece(root, Vector3(0, 1.58, .09), Vector3(.42, .59, .24), pale) for side: float in [-1.0, 1.0]: _piece(root, Vector3(side * .11, 1.61, .21), Vector3(.08, .15, .07), rift) _limb(root, Vector3(side*.23,1.25,0), Vector3(side*.57,.95,.17), .12,shell) _limb(root, Vector3(side*.57,.95,.17), Vector3(side*.68,1.29,.27), .09,pale,true) for index: int in range(3): var x: float = (index-1)*.22 _limb(root,Vector3(x,1.0,0),Vector3(x-.12,.43,.04),.15,dark) _limb(root,Vector3(x-.12,.43,.04),Vector3(x+.13,.05,.14),.09,shell,true) elif id == "e04": _piece(root, Vector3(0, 1.02, 0), Vector3(.42, .65, .35), dark) _piece(root, Vector3(0, 1.54, .05), Vector3(.38, .43, .31), pale) _piece(root, Vector3(0, 1.55, .23), Vector3(.23, .055, .05), rift, true) for side: float in [-1.0,1.0]: _limb(root,Vector3(side*.17,.88,0),Vector3(side*.28,.46,-.06),.10,shell) _limb(root,Vector3(side*.28,.46,-.06),Vector3(side*.32,.03,.22),.07,dark) _limb(root,Vector3(side*.20,1.23,0),Vector3(side*.46,1.07,.34),.07,shell) _limb(root,Vector3(0,1.12,.45),Vector3(side*.61,1.15,.65),.06,pale) _limb(root,Vector3(0,1.12,.20),Vector3(0,1.12,.94),.065,rift,true) elif id == "e07": _piece(root, Vector3(0, 1.03, -.22), Vector3(.90, .88, 1.37), dark) _piece(root, Vector3(0, 1.61, .39), Vector3(.66, .85, .71), shell) _piece(root, Vector3(0, 1.62, .82), Vector3(.38, .31, .51), pale) for side: float in [-1.0,1.0]: for z: float in [-.65,.35]: _limb(root,Vector3(side*.29,.91,z),Vector3(side*.42,.09,z+.08),.14,dark) _piece(root,Vector3(side*.42,.09,z+.13),Vector3(.27,.17,.31),pale,true) _piece(root,Vector3(side*.25,1.78,.67),Vector3(.10,.10,.14),rift) _limb(root,Vector3(side*.22,1.89,.40),Vector3(side*.64,2.46,.10),.11,pale,true) _limb(root,Vector3(side*.45,2.17,.24),Vector3(side*.89,2.39,.40),.08,pale,true) _limb(root,Vector3(side*.54,2.29,.17),Vector3(side*.52,2.61,.40),.06,pale,true) else: _piece(root,Vector3(0,1.07,0),Vector3(1.03,1.32,.66),dark,true) _piece(root,Vector3(0,1.23,.37),Vector3(.69,.91,.17),shell,true) _piece(root,Vector3(0,1.26,.48),Vector3(.11,.70,.06),rift,true) _piece(root,Vector3(0,1.98,.08),Vector3(.52,.44,.46),pale,true) _piece(root,Vector3(0,1.99,.32),Vector3(.35,.08,.05),rift,true) for side: float in [-1.0,1.0]: _piece(root,Vector3(side*.38,.29,0),Vector3(.40,.59,.49),shell,true) _piece(root,Vector3(side*.39,.09,.20),Vector3(.48,.17,.64),dark,true) _piece(root,Vector3(side*.78,1.22,.03),Vector3(.42,1.13,.55),shell,true) for index: int in range(2): _piece(root,Vector3(side*.78,1.89,-.14+index*.34),Vector3(.42,.24,.16),pale,true) _limb(root,Vector3(side*.76,.99,.34),Vector3(side*.80,.90,.97),.13,dark)