# monster_card_system.gd —— Metin2 40250 怪物图鉴与百科全书系统 1:1 # 对照 40250 服务端 monster_card.cpp, uimonstercard.py, char_battle.cpp class_name MonsterCardSystem extends RefCounted signal card_collected(mob_vnum: int, mob_name: String, count: int) signal zone_completed(zone_name: String, bonuses: Dictionary) # 区域图鉴数据库配置 const BESTIARY_DATA: Dictionary = { "village": { "zone_name": "新手原野", "bonus": {"max_hp": 300}, "monsters": { 101: { "name": "野狼", "level": 1, "element": "无", "weakness": "物理", "drops": ["木剑+0", "小红药水"], "card_vnum": 70201 }, 391: { "name": "白灵女将", "level": 25, "element": "风", "weakness": "火", "drops": ["狼剑+9", "红药水(中)"], "card_vnum": 70202 } } }, "desert": { "zone_name": "永壁沙漠", "bonus": {"monster_dmg_pct": 3}, "monsters": { 2108: { "name": "沙漠强盗", "level": 50, "element": "地", "weakness": "风", "drops": ["红药水(大)", "胡萝卜"], "card_vnum": 70203 }, 2191: { "name": "巨型沙漠龟", "level": 67, "element": "地", "weakness": "风", "drops": ["沙漠龟宝箱", "灵魂之石"], "card_vnum": 70204 } } }, "catacomb": { "zone_name": "地下墓穴", "bonus": {"def": 50}, "monsters": { 2597: { "name": "塔耳塔洛斯", "level": 82, "element": "暗", "weakness": "圣", "drops": ["冷酷之石"], "card_vnum": 70205 }, 2598: { "name": "冥王阿兹瑞尔", "level": 91, "element": "暗", "weakness": "圣", "drops": ["阿兹瑞尔宝箱", "泰坦之盾"], "card_vnum": 70206 } } } } var collected_cards: Dictionary = {} # mob_vnum -> count var completed_zones: Dictionary = {} # zone_key -> bool # 使用并收集怪物卡片 func register_card(card_vnum: int) -> Dictionary: # 查找对应怪物 var target_mob_vnum := -1 var target_mob_name := "" var target_zone := "" for z_key in BESTIARY_DATA.keys(): var z_data = BESTIARY_DATA[z_key] for mv in z_data["monsters"].keys(): var minfo = z_data["monsters"][mv] if minfo["card_vnum"] == card_vnum: target_mob_vnum = mv target_mob_name = minfo["name"] target_zone = z_key break if target_mob_vnum != -1: break if target_mob_vnum == -1: return {"ok": false, "reason": "INVALID_CARD", "msg": "这不是有效的怪物图鉴卡片!"} var new_count: int = int(collected_cards.get(target_mob_vnum, 0)) + 1 collected_cards[target_mob_vnum] = new_count card_collected.emit(target_mob_vnum, target_mob_name, new_count) # 检查所属区域是否全部完成收集 var is_newly_completed := false var zone_bonus: Dictionary = {} if not completed_zones.get(target_zone, false): var all_done := true var z_mobs = BESTIARY_DATA[target_zone]["monsters"] for m_id in z_mobs.keys(): if int(collected_cards.get(m_id, 0)) < 1: all_done = false break if all_done: completed_zones[target_zone] = true is_newly_completed = true zone_bonus = BESTIARY_DATA[target_zone]["bonus"] zone_completed.emit(BESTIARY_DATA[target_zone]["zone_name"], zone_bonus) return { "ok": true, "mob_vnum": target_mob_vnum, "mob_name": target_mob_name, "count": new_count, "zone_completed": is_newly_completed, "zone_bonus": zone_bonus, "msg": "已将【%s】录入怪物图鉴!" % target_mob_name } # 查看图鉴词条 (未解锁则模糊显示) func get_monster_entry(mob_vnum: int) -> Dictionary: for z_data in BESTIARY_DATA.values(): if z_data["monsters"].has(mob_vnum): var info: Dictionary = z_data["monsters"][mob_vnum].duplicate(true) var count: int = int(collected_cards.get(mob_vnum, 0)) if count >= 1: info["is_unlocked"] = true info["collected_count"] = count return info else: return { "is_unlocked": false, "name": "???", "level": "??", "element": "??", "weakness": "??", "drops": ["未知"], "collected_count": 0 } return {"is_unlocked": false, "reason": "NOT_FOUND"} # 汇总所有已完成区域图鉴的常驻被动战力加成 func get_active_collection_bonuses() -> Dictionary: var total_bonuses: Dictionary = {} for z_key in completed_zones.keys(): if completed_zones[z_key]: var b = BESTIARY_DATA[z_key]["bonus"] for k in b.keys(): total_bonuses[k] = total_bonuses.get(k, 0) + int(b[k]) return total_bonuses