# monarch_empire_treasury_system.gd —— Metin2 40250 官方君主国王特权与王国国库祈愿系统 1:1 # 100% 对照 40250 服务端 monarch.cpp, monarch.h, quest/monarch.quest, tables.h class_name MonarchEmpireTreasurySystem extends RefCounted signal monarch_healed_empire(empire: int, cost: int, restored_citizens_count: int) signal monarch_power_up_activated(empire: int, cost: int, duration: float) signal monarch_defense_up_activated(empire: int, cost: int, duration: float) signal treasury_tax_collected(empire: int, amount: int, new_balance: int) signal monarch_appointed(empire: int, player_id: int, player_name: String) signal monarch_error(reason: String) # 40250 官方三大帝国常数 const EMPIRE_NONE := 0 const EMPIRE_SHINSOO := 1 # 辛秀帝国 (红国) const EMPIRE_CHUNJO := 2 # 春祖帝国 (黄国) const EMPIRE_JINNO := 3 # 镇奴帝国 (蓝国) const EMPIRE_NAMES: Dictionary = { EMPIRE_SHINSOO: "辛秀帝国 (Shinsoo - 红国)", EMPIRE_CHUNJO: "春祖帝国 (Chunjo - 黄国)", EMPIRE_JINNO: "镇奴帝国 (Jinno - 蓝国)" } # 国库金币上限 (40250 monarch.cpp: 20亿上限) const MAX_TREASURY_GOLD := 2000000000 # 技能费用与冷却 const COST_HEAL_EMPIRE := 100000 # 恩泽圣愈国库消耗 100,000 金币 const COST_POWER_UP := 500000 # 帝国狂暴国库消耗 500,000 金币 const COST_DEFENSE_UP := 500000 # 铁壁光环国库消耗 500,000 金币 const COOLDOWN_HEAL_EMPIRE := 600.0 # 恩泽圣愈冷却 10 分钟 (600 秒) const COOLDOWN_POWER_UP := 600.0 # 战力觉醒冷却 10 分钟 const COOLDOWN_DEFENSE_UP := 600.0 # 铁壁守护冷却 10 分钟 const DURATION_POWER_UP := 1800.0 # 战力狂暴持续 30 分钟 (1800 秒) const DURATION_DEFENSE_UP := 1800.0 # 铁壁守护持续 30 分钟 # 数据存储 var _monarch_pids: Dictionary = {1: 0, 2: 0, 3: 0} # empire -> player_id var _monarch_names: Dictionary = {1: "", 2: "", 3: ""} var _treasury: Dictionary = {1: 0, 2: 0, 3: 0} # empire -> gold var _heal_cooldown: Dictionary = {1: 0.0, 2: 0.0, 3: 0.0} var _power_up_cooldown: Dictionary = {1: 0.0, 2: 0.0, 3: 0.0} var _defense_up_cooldown: Dictionary = {1: 0.0, 2: 0.0, 3: 0.0} var _power_up_active: Dictionary = {1: false, 2: false, 3: false} var _defense_up_active: Dictionary = {1: false, 2: false, 3: false} var _power_up_timer: Dictionary = {1: 0.0, 2: 0.0, 3: 0.0} var _defense_up_timer: Dictionary = {1: 0.0, 2: 0.0, 3: 0.0} # ========================================== # 1. 国王任命与身份核验 (monarch.cpp: IsMonarch) # ========================================== func appoint_monarch(empire: int, player_id: int, player_name: String) -> bool: if not _is_valid_empire(empire): monarch_error.emit("INVALID_EMPIRE") return false _monarch_pids[empire] = player_id _monarch_names[empire] = player_name monarch_appointed.emit(empire, player_id, player_name) return true func is_monarch(player_id: int, empire: int) -> bool: if not _is_valid_empire(empire): return false return int(_monarch_pids.get(empire, 0)) == player_id func get_monarch_info(empire: int) -> Dictionary: if not _is_valid_empire(empire): return {} return { "empire": empire, "empire_name": EMPIRE_NAMES[empire], "player_id": _monarch_pids.get(empire, 0), "player_name": _monarch_names.get(empire, ""), "treasury_gold": _treasury.get(empire, 0) } # ========================================== # 2. 国库金币与税赋 (monarch.cpp: AddMoney, DecMoney) # ========================================== func get_treasury_gold(empire: int) -> int: if not _is_valid_empire(empire): return 0 return int(_treasury.get(empire, 0)) func add_treasury_gold(empire: int, amount: int) -> bool: if not _is_valid_empire(empire) or amount <= 0: return false var current = int(_treasury.get(empire, 0)) var new_val = min(current + amount, MAX_TREASURY_GOLD) _treasury[empire] = new_val return true func collect_monster_tax(empire: int, monster_gold_drop: int, tax_rate: float = 0.02) -> int: if not _is_valid_empire(empire) or monster_gold_drop <= 0: return 0 var tax = int(floor(monster_gold_drop * tax_rate)) if tax > 0: add_treasury_gold(empire, tax) treasury_tax_collected.emit(empire, tax, _treasury[empire]) return tax func dec_treasury_gold(empire: int, amount: int) -> bool: if not _is_valid_empire(empire) or amount <= 0: return false var current = int(_treasury.get(empire, 0)) if current < amount: return false _treasury[empire] = current - amount return true # ========================================== # 3. 君主全境治国神技 (monarch.cpp: HealMyEmpire, PowerUp, DefenseUp) # ========================================== # 恩泽圣愈:全境国民 HP/SP 瞬间全满 (FHealMyEmpire) func heal_my_empire( player_id: int, empire: int, online_citizens: Array[Dictionary] ) -> Dictionary: if not is_monarch(player_id, empire): monarch_error.emit("NOT_MONARCH") return {"ok": false, "reason": "NOT_MONARCH", "msg": "你并非本帝国加冕的君主,无权调动国库施加恩泽!"} if float(_heal_cooldown.get(empire, 0.0)) > 0.0: monarch_error.emit("COOLDOWN_ACTIVE") return { "ok": false, "reason": "COOLDOWN_ACTIVE", "msg": "恩泽圣愈冷却中!还需等待 %d 秒。" % int(_heal_cooldown[empire]) } if get_treasury_gold(empire) < COST_HEAL_EMPIRE: monarch_error.emit("NOT_ENOUGH_TREASURY") return { "ok": false, "reason": "NOT_ENOUGH_TREASURY", "msg": "国库资金匮乏!施展恩泽圣愈需要 %d 国库金币,当前只有 %d 金币。" % [COST_HEAL_EMPIRE, get_treasury_gold(empire)] } # 扣除国库金币 dec_treasury_gold(empire, COST_HEAL_EMPIRE) _heal_cooldown[empire] = COOLDOWN_HEAL_EMPIRE # 治愈同帝国所有国民 (40250 ch->PointChange(POINT_HP, max - hp)) var healed_count := 0 for citizen in online_citizens: if int(citizen.get("empire", 0)) == empire: citizen["hp"] = citizen.get("max_hp", 1000) citizen["sp"] = citizen.get("max_sp", 500) healed_count += 1 monarch_healed_empire.emit(empire, COST_HEAL_EMPIRE, healed_count) return { "ok": true, "healed_count": healed_count, "remaining_treasury": get_treasury_gold(empire), "msg": "君主高举天子权杖,浩荡圣光普照四野!全境 %d 位国民生命法力全部盈满!" % healed_count } # 帝国战力狂暴 (PowerUp: 攻击力 +10%) func activate_power_up(player_id: int, empire: int) -> Dictionary: if not is_monarch(player_id, empire): monarch_error.emit("NOT_MONARCH") return {"ok": false, "reason": "NOT_MONARCH", "msg": "只有君主方可激发帝国战力觉醒!"} if float(_power_up_cooldown.get(empire, 0.0)) > 0.0: monarch_error.emit("COOLDOWN_ACTIVE") return { "ok": false, "reason": "COOLDOWN_ACTIVE", "msg": "帝国狂暴冷却中!还需等待 %d 秒。" % int(_power_up_cooldown[empire]) } if get_treasury_gold(empire) < COST_POWER_UP: monarch_error.emit("NOT_ENOUGH_TREASURY") return {"ok": false, "reason": "NOT_ENOUGH_TREASURY", "msg": "国库资金不足 %d 金币!" % COST_POWER_UP} dec_treasury_gold(empire, COST_POWER_UP) _power_up_cooldown[empire] = COOLDOWN_POWER_UP _power_up_active[empire] = true _power_up_timer[empire] = DURATION_POWER_UP monarch_power_up_activated.emit(empire, COST_POWER_UP, DURATION_POWER_UP) return { "ok": true, "duration": DURATION_POWER_UP, "att_grade_bonus": 0.10, "remaining_treasury": get_treasury_gold(empire), "msg": "战神咆哮!君主调动帝国龙脉之力,全体国民攻击力提升 10%,持续 30 分钟!" } # 帝国铁壁守护 (DefenseUp: 防御力 +10%) func activate_defense_up(player_id: int, empire: int) -> Dictionary: if not is_monarch(player_id, empire): monarch_error.emit("NOT_MONARCH") return {"ok": false, "reason": "NOT_MONARCH", "msg": "只有君主方可激发帝国铁壁守护!"} if float(_defense_up_cooldown.get(empire, 0.0)) > 0.0: monarch_error.emit("COOLDOWN_ACTIVE") return { "ok": false, "reason": "COOLDOWN_ACTIVE", "msg": "铁壁守护冷却中!还需等待 %d 秒。" % int(_defense_up_cooldown[empire]) } if get_treasury_gold(empire) < COST_DEFENSE_UP: monarch_error.emit("NOT_ENOUGH_TREASURY") return {"ok": false, "reason": "NOT_ENOUGH_TREASURY", "msg": "国库资金不足 %d 金币!" % COST_DEFENSE_UP} dec_treasury_gold(empire, COST_DEFENSE_UP) _defense_up_cooldown[empire] = COOLDOWN_DEFENSE_UP _defense_up_active[empire] = true _defense_up_timer[empire] = DURATION_DEFENSE_UP monarch_defense_up_activated.emit(empire, COST_DEFENSE_UP, DURATION_DEFENSE_UP) return { "ok": true, "duration": DURATION_DEFENSE_UP, "def_grade_bonus": 0.10, "remaining_treasury": get_treasury_gold(empire), "msg": "坚不可摧!君主召唤玄龟金钟大阵,全体国民防御力提升 10%,持续 30 分钟!" } # 查询帝国国民当前享受的光环加成 func get_citizen_empire_buffs(empire: int) -> Dictionary: if not _is_valid_empire(empire): return {"att_bonus": 0.0, "def_bonus": 0.0} return { "att_bonus": 0.10 if bool(_power_up_active.get(empire, false)) else 0.0, "def_bonus": 0.10 if bool(_defense_up_active.get(empire, false)) else 0.0, "power_up_time_left": float(_power_up_timer.get(empire, 0.0)), "defense_up_time_left": float(_defense_up_timer.get(empire, 0.0)) } # 定时器时间步进 func update(delta: float) -> void: for emp in [1, 2, 3]: # 冷却倒计时 if _heal_cooldown[emp] > 0.0: _heal_cooldown[emp] = max(_heal_cooldown[emp] - delta, 0.0) if _power_up_cooldown[emp] > 0.0: _power_up_cooldown[emp] = max(_power_up_cooldown[emp] - delta, 0.0) if _defense_up_cooldown[emp] > 0.0: _defense_up_cooldown[emp] = max(_defense_up_cooldown[emp] - delta, 0.0) # 增益持续倒计时 if _power_up_active[emp]: _power_up_timer[emp] -= delta if _power_up_timer[emp] <= 0.0: _power_up_timer[emp] = 0.0 _power_up_active[emp] = false if _defense_up_active[emp]: _defense_up_timer[emp] -= delta if _defense_up_timer[emp] <= 0.0: _defense_up_timer[emp] = 0.0 _defense_up_active[emp] = false func _is_valid_empire(empire: int) -> bool: return empire == EMPIRE_SHINSOO or empire == EMPIRE_CHUNJO or empire == EMPIRE_JINNO # 序列化与反序列化 func serialize() -> Dictionary: return { "monarch_pids": _monarch_pids.duplicate(), "monarch_names": _monarch_names.duplicate(), "treasury": _treasury.duplicate(), "heal_cooldown": _heal_cooldown.duplicate(), "power_up_cooldown": _power_up_cooldown.duplicate(), "defense_up_cooldown": _defense_up_cooldown.duplicate(), "power_up_active": _power_up_active.duplicate(), "defense_up_active": _defense_up_active.duplicate(), "power_up_timer": _power_up_timer.duplicate(), "defense_up_timer": _defense_up_timer.duplicate() } func deserialize(data: Dictionary) -> void: _monarch_pids = data.get("monarch_pids", {1: 0, 2: 0, 3: 0}).duplicate() _monarch_names = data.get("monarch_names", {1: "", 2: "", 3: ""}).duplicate() _treasury = data.get("treasury", {1: 0, 2: 0, 3: 0}).duplicate() _heal_cooldown = data.get("heal_cooldown", {1: 0.0, 2: 0.0, 3: 0.0}).duplicate() _power_up_cooldown = data.get("power_up_cooldown", {1: 0.0, 2: 0.0, 3: 0.0}).duplicate() _defense_up_cooldown = data.get("defense_up_cooldown", {1: 0.0, 2: 0.0, 3: 0.0}).duplicate() _power_up_active = data.get("power_up_active", {1: false, 2: false, 3: false}).duplicate() _defense_up_active = data.get("defense_up_active", {1: false, 2: false, 3: false}).duplicate() _power_up_timer = data.get("power_up_timer", {1: 0.0, 2: 0.0, 3: 0.0}).duplicate() _defense_up_timer = data.get("defense_up_timer", {1: 0.0, 2: 0.0, 3: 0.0}).duplicate()