feat: update shop

This commit is contained in:
2026-04-17 00:17:37 +08:00
parent f10d777c90
commit ff0a2e0f41
5 changed files with 914 additions and 130 deletions
+75 -3
View File
@@ -521,21 +521,93 @@ func _apply_outline_recursive(node: Node):
for child in node.get_children():
_apply_outline_recursive(child)
const COSMETIC_MAPPING = {
"head_hat1": {
"hide": ["helm_default", "helm1", "helm2", "helm3"],
"show": ["head_hat1"],
"materials": {}
},
"head_crown": {
"hide": ["helm_default", "helm1", "helm2", "helm3"],
"show": ["head_crown"],
"materials": {}
},
"costume_red": {
"hide": [],
"show": [],
"materials": {
"body": "res://assets/materials/body_red.tres",
"arm": "res://assets/materials/body_red.tres"
}
},
"costume_gold": {
"hide": [],
"show": [],
"materials": {
"body": "res://assets/materials/body_gold.tres",
"arm": "res://assets/materials/body_gold.tres"
}
},
"glove_leather": {
"hide": ["hands", "glove_default"],
"show": ["glove_leather"],
"materials": {}
},
"acc_glasses": {
"hide": [],
"show": ["acc_glasses"],
"materials": {}
}
}
func apply_loadout(character_node: Node3D) -> void:
"""Apply equipped cosmetics from UserProfileManager.loadout onto the active character model.
Items are expected as child nodes named matching the item ID (e.g. 'head_hat1', 'acc_glasses').
All nodes in the cosmetic category groups are hidden first, then the equipped one is shown."""
It uses COSMETIC_MAPPING to dynamically swap visibility and materials of internal meshes."""
if not has_node("/root/UserProfileManager"):
return
var loadout: Dictionary = UserProfileManager.loadout
var all_meshes = _get_all_mesh_instances(character_node)
for category in ["head", "costume", "glove", "accessory"]:
var equipped: String = loadout.get(category, "")
# Fallback basic logic for direct children
for child in character_node.get_children():
# Only manage nodes that start with the category prefix
if child.name.begins_with(category):
child.visible = (child.name == equipped)
# Advanced mapping logic for deep node part swapping and materials
if equipped and COSMETIC_MAPPING.has(equipped):
var mapping = COSMETIC_MAPPING[equipped]
# Visibility overrides
var to_hide = mapping.get("hide", [])
var to_show = mapping.get("show", [])
for mesh in all_meshes:
if mesh.name in to_hide:
mesh.visible = false
if mesh.name in to_show:
mesh.visible = true
# Material overrides
var mats = mapping.get("materials", {})
for mesh_name in mats:
var mat_path = mats[mesh_name]
for mesh in all_meshes:
if mesh.name == mesh_name:
if ResourceLoader.exists(mat_path):
var new_mat = load(mat_path)
mesh.material_override = new_mat
func _get_all_mesh_instances(node: Node) -> Array:
var result = []
if node is MeshInstance3D or node.get_class() == "SkinnedMeshInstance3D":
result.append(node)
for child in node.get_children():
result.append_array(_get_all_mesh_instances(child))
return result
@rpc("any_peer", "call_local", "reliable")
func sync_character(character_name: String) -> void: