# test_metin_socket_parity.gd —— 验证方向 2:魔石镶嵌、碎石残渣与打孔清除 40250 1:1 对齐 extends SceneTree const MetinSocketSystem = preload("res://metin_socket_system.gd") var _passed := 0 var _failed := 0 func _assert(cond: bool, msg: String) -> void: if cond: _passed += 1 print(" [PASS] %s" % msg) else: _failed += 1 printerr(" [FAIL] %s" % msg) func _init() -> void: print("\n=== Running test_metin_socket_parity (Direction 2: Metin Socketing & Cleaning 1:1) ===") test_metin_vnum_identification() test_equipment_target_rules() test_socket_metin_success_and_broken() test_duplicate_metin_prevention() test_clean_broken_sockets_parity() print("\n=== SUMMARY: %d passed, %d failed ===" % [_passed, _failed]) if _failed > 0: printerr("TEST FAILED!") quit(1) else: print("ALL TESTS PASSED!") quit(0) func test_metin_vnum_identification() -> void: print("\n--- Test 1: Metin Stone & Scroll Identification ---") _assert(MetinSocketSystem.is_metin_stone(28430), "28430 (Stone of Penetration+4) is a Metin Stone") _assert(MetinSocketSystem.is_metin_stone(28442), "28442 (Stone of Defense+4) is a Metin Stone") _assert(MetinSocketSystem.is_metin_stone(28033), "28033 (Stone of Warrior+0) is a Metin Stone") _assert(not MetinSocketSystem.is_metin_stone(10), "Sword 10 is not a Metin Stone") _assert(not MetinSocketSystem.is_metin_stone(28960), "Broken stone 28960 is not a Metin stone to socket") _assert(MetinSocketSystem.is_clean_socket_scroll(71006), "71006 is Clean Socket Scroll") _assert(not MetinSocketSystem.is_clean_socket_scroll(71085), "71085 is not clean socket scroll") func test_equipment_target_rules() -> void: print("\n--- Test 2: Target Equipment Restrictions (Body Armor / Weapon vs Shield/Arrow) ---") var body_armor := {"type": MetinSocketSystem.ITEM_TYPE_ARMOR, "sub_type": 0} # ARMOR_BODY var helmet := {"type": MetinSocketSystem.ITEM_TYPE_ARMOR, "sub_type": 1} # ARMOR_HEAD var weapon := {"type": MetinSocketSystem.ITEM_TYPE_WEAPON, "sub_type": 0} # WEAPON_SWORD var arrow := {"type": MetinSocketSystem.ITEM_TYPE_WEAPON, "sub_type": 5} # WEAPON_ARROW var stone_proto := {"type": MetinSocketSystem.ITEM_TYPE_METIN} var r_body := MetinSocketSystem.can_attach_metin(28442, stone_proto, body_armor) _assert(r_body.ok, "Can attach metin stone to body armor") var r_helmet := MetinSocketSystem.can_attach_metin(28442, stone_proto, helmet) _assert(not r_helmet.ok and r_helmet.code == "ARMOR_NOT_BODY", "Cannot attach metin stone to helmet (must be body)") var r_weapon := MetinSocketSystem.can_attach_metin(28430, stone_proto, weapon) _assert(r_weapon.ok, "Can attach metin stone to weapon") var r_arrow := MetinSocketSystem.can_attach_metin(28430, stone_proto, arrow) _assert(not r_arrow.ok and r_arrow.code == "WEAPON_ARROW", "Cannot attach metin stone to arrows") func test_socket_metin_success_and_broken() -> void: print("\n--- Test 3: 40250 Socketing Success vs Broken Fragment (28960) ---") var weapon_proto := {"type": MetinSocketSystem.ITEM_TYPE_WEAPON, "sub_type": 0} var stone_proto := {"type": MetinSocketSystem.ITEM_TYPE_METIN} # Sword with 3 open sockets: [1, 1, 1] var sword := {"vnum": 10, "sockets": [1, 1, 1]} # 1st stone: force success (28430 Penetration+4) var res1 := MetinSocketSystem.socket_metin_stone(28430, stone_proto, sword, weapon_proto, true, false) _assert(res1.ok and res1.code == "SUCCESS", "1st metin stone socketed successfully") _assert(sword.sockets[0] == 28430, "Socket 0 contains 28430") _assert(sword.sockets[1] == 1 and sword.sockets[2] == 1, "Socket 1 and 2 remain open (1)") # 2nd stone: force failure -> creates broken metin stone 28960 var res2 := MetinSocketSystem.socket_metin_stone(28431, stone_proto, sword, weapon_proto, false, true) _assert(not res2.ok and res2.code == "BROKEN_METIN", "2nd metin stone broke on failure") _assert(sword.sockets[1] == MetinSocketSystem.ITEM_BROKEN_METIN_VNUM, "Socket 1 is now blocked by broken fragment 28960") _assert(sword.sockets[2] == 1, "Socket 2 remains open (1)") # 3rd stone: force success (28437 Monster+4) into remaining slot 2 var res3 := MetinSocketSystem.socket_metin_stone(28437, stone_proto, sword, weapon_proto, true, false) _assert(res3.ok and res3.code == "SUCCESS", "3rd metin stone socketed into remaining slot 2") _assert(sword.sockets[2] == 28437, "Socket 2 contains 28437") # 4th stone: no available sockets var res4 := MetinSocketSystem.socket_metin_stone(28432, stone_proto, sword, weapon_proto, true, false) _assert(not res4.ok and res4.code == "NO_AVAILABLE_SOCKET", "No available sockets rejected properly") func test_duplicate_metin_prevention() -> void: print("\n--- Test 4: Prevention of Duplicate Stone Groups ---") var weapon_proto := {"type": MetinSocketSystem.ITEM_TYPE_WEAPON, "sub_type": 0} var stone_proto := {"type": MetinSocketSystem.ITEM_TYPE_METIN} var sword := {"vnum": 10, "sockets": [28430, 1, 1]} # Already has Penetration+4 (28430) # Trying to socket Penetration+3 (28330) or another Penetration stone var res_dup := MetinSocketSystem.socket_metin_stone(28330, stone_proto, sword, weapon_proto, true, false) _assert(not res_dup.ok and res_dup.code == "DUPLICATE_METIN", "Duplicate metin group (Penetration) prevented from socketing") func test_clean_broken_sockets_parity() -> void: print("\n--- Test 5: 40250 USE_CLEAN_SOCKET (71006) Fragment Cleaning ---") # Equipment has: [28430 (valid), 28960 (broken), 28437 (valid)] var item_with_broken := { "vnum": 10, "sockets": [28430, MetinSocketSystem.ITEM_BROKEN_METIN_VNUM, 28437] } var res_clean := MetinSocketSystem.clean_broken_sockets(item_with_broken) _assert(res_clean.ok and res_clean.code == "SUCCESS", "Clean scroll removed broken stone fragments") _assert(item_with_broken.sockets[0] == 28430, "Socket 0 still has valid stone 28430") _assert(item_with_broken.sockets[1] == 28437, "Valid stone 28437 compacted forward to socket 1") _assert(item_with_broken.sockets[2] == 1, "Socket 2 restored back to open state 1") # Using clean scroll on an item with no broken stones must fail (40250 char_item.cpp:4523) var res_clean_no_op := MetinSocketSystem.clean_broken_sockets(item_with_broken) _assert(not res_clean_no_op.ok and res_clean_no_op.code == "NO_BROKEN_STONE", "Clean scroll rejected on item without broken stones")