Localize Sishui gate and battle log tone
This commit is contained in:
@@ -735,12 +735,12 @@ func try_cast_selected_skill(skill_id: String, target_cell: Vector2i) -> bool:
|
||||
if caster.get("acted", false):
|
||||
return false
|
||||
if _unit_has_action_lock(caster, "skill"):
|
||||
_emit_log("%s cannot use tactics while sealed." % caster["name"])
|
||||
_emit_log("%s는 봉인되어 책략을 펼치지 못한다." % caster["name"])
|
||||
return false
|
||||
if not _unit_has_skill(caster, skill_id):
|
||||
return false
|
||||
if int(caster.get("mp", 0)) < int(skill.get("mp_cost", 0)):
|
||||
_emit_log("%s does not have enough MP." % caster["name"])
|
||||
_emit_log("%s의 기력이 모자라다." % caster["name"])
|
||||
return false
|
||||
if not _skill_cells_from(caster, skill).has(target_cell):
|
||||
return false
|
||||
@@ -749,9 +749,9 @@ func try_cast_selected_skill(skill_id: String, target_cell: Vector2i) -> bool:
|
||||
var targets := _skill_targets_for_cast(caster, skill_id, skill, target_cell)
|
||||
if targets.is_empty():
|
||||
if skill_kind == "heal":
|
||||
_emit_log("%s has no injured targets in range." % skill.get("name", "Skill"))
|
||||
_emit_log("%s의 범위 안에 다친 아군이 없다." % skill.get("name", "책략"))
|
||||
else:
|
||||
_emit_log("%s has no valid targets." % skill.get("name", "Skill"))
|
||||
_emit_log("%s의 표적이 없다." % skill.get("name", "책략"))
|
||||
return false
|
||||
if skill_kind == "support" and not _skill_has_support_effects(skill):
|
||||
return false
|
||||
@@ -795,7 +795,7 @@ func try_use_selected_item_on_cell(item_id: String, target_cell: Vector2i) -> bo
|
||||
if user.get("acted", false):
|
||||
return false
|
||||
if int(battle_inventory.get(item_id, 0)) <= 0:
|
||||
_emit_log("No %s remains." % item.get("name", item_id))
|
||||
_emit_log("%s은 이미 다하였다." % _item_display_name(item_id))
|
||||
return false
|
||||
if str(item.get("kind", "")) != "consumable":
|
||||
return false
|
||||
@@ -814,7 +814,7 @@ func try_use_selected_item_on_cell(item_id: String, target_cell: Vector2i) -> bo
|
||||
user["acted"] = true
|
||||
user["moved"] = true
|
||||
selected_unit_id = ""
|
||||
_emit_log("%s uses %s on %s." % [user["name"], item.get("name", item_id), target["name"]])
|
||||
_emit_log("%s 사용: %s -> %s." % [user["name"], _item_display_name(item_id), target["name"]])
|
||||
_check_battle_status()
|
||||
_notify_changed()
|
||||
return true
|
||||
@@ -1126,9 +1126,9 @@ func _resolve_skill_support(caster: Dictionary, target: Dictionary, skill_id: St
|
||||
"remaining_phases": max(1, int(effect.get("duration_turns", 1)))
|
||||
})
|
||||
target["status_effects"] = status_effects
|
||||
_emit_log("%s casts %s on %s. %s" % [
|
||||
_emit_log("%s 시전 %s -> %s. %s" % [
|
||||
caster["name"],
|
||||
skill.get("name", "Skill"),
|
||||
skill.get("name", "책략"),
|
||||
target["name"],
|
||||
_format_support_effects(skill)
|
||||
])
|
||||
@@ -1159,25 +1159,25 @@ func _format_support_effects(skill: Dictionary) -> String:
|
||||
continue
|
||||
var effect_type := str(effect.get("type", ""))
|
||||
var duration: int = maxi(1, int(effect.get("duration_turns", 1)))
|
||||
var duration_text := "next phase" if duration == 1 else "%d phases" % duration
|
||||
var duration_text := _support_duration_text(duration)
|
||||
if effect_type == "stat_bonus":
|
||||
var stat := str(effect.get("stat", ""))
|
||||
var amount := int(effect.get("amount", 0))
|
||||
if not _is_supported_status_stat(stat) or amount == 0:
|
||||
continue
|
||||
var sign := "+" if amount > 0 else ""
|
||||
parts.append("%s %s%d until %s" % [stat.to_upper(), sign, amount, duration_text])
|
||||
parts.append("%s %s%d, %s 지속" % [_status_stat_display_name(stat), sign, amount, duration_text])
|
||||
elif effect_type == "damage_over_time":
|
||||
var damage := int(effect.get("amount", 0))
|
||||
if damage <= 0:
|
||||
continue
|
||||
var status_name := _status_display_name(str(effect.get("status", "poison")))
|
||||
parts.append("%s -%d HP for %s" % [status_name, damage, duration_text])
|
||||
parts.append("%s -%d 병력, %s 지속" % [status_name, damage, duration_text])
|
||||
elif effect_type == "action_lock":
|
||||
var status_name := _status_display_name(str(effect.get("status", "status")))
|
||||
parts.append("%s %s for %s" % [status_name, _action_lock_display_name(str(effect.get("action", ""))), duration_text])
|
||||
parts.append("%s %s, %s 지속" % [status_name, _action_lock_display_name(str(effect.get("action", ""))), duration_text])
|
||||
if parts.is_empty():
|
||||
return "No support effect."
|
||||
return "효험 없음"
|
||||
return _join_strings(parts, ", ")
|
||||
|
||||
|
||||
@@ -1193,15 +1193,15 @@ func _format_support_popup(skill: Dictionary) -> String:
|
||||
if not _is_supported_status_stat(stat) or amount == 0:
|
||||
continue
|
||||
var sign := "+" if amount > 0 else ""
|
||||
parts.append("%s %s%d" % [stat.to_upper(), sign, amount])
|
||||
parts.append("%s %s%d" % [_status_stat_display_name(stat), sign, amount])
|
||||
elif effect_type == "damage_over_time":
|
||||
var damage := int(effect.get("amount", 0))
|
||||
if damage > 0:
|
||||
parts.append(_status_display_name(str(effect.get("status", "poison"))).to_upper())
|
||||
parts.append(_status_display_name(str(effect.get("status", "poison"))))
|
||||
elif effect_type == "action_lock":
|
||||
parts.append(_status_display_name(str(effect.get("status", "status"))).to_upper())
|
||||
parts.append(_status_display_name(str(effect.get("status", "status"))))
|
||||
if parts.is_empty():
|
||||
return "Support"
|
||||
return "지원"
|
||||
return _join_strings(parts, ", ")
|
||||
|
||||
|
||||
@@ -1232,7 +1232,7 @@ func _format_active_status_effects(unit: Dictionary) -> String:
|
||||
var duration_text := _format_status_remaining_phases(effect)
|
||||
if effect_type == "damage_over_time":
|
||||
if amount > 0:
|
||||
parts.append("%s -%d HP %s" % [
|
||||
parts.append("%s -%d 병력 %s" % [
|
||||
_status_display_name(str(effect.get("status", "poison"))),
|
||||
amount,
|
||||
duration_text
|
||||
@@ -1249,23 +1249,53 @@ func _format_active_status_effects(unit: Dictionary) -> String:
|
||||
if not _is_supported_status_stat(stat) or amount == 0:
|
||||
continue
|
||||
var sign := "+" if amount > 0 else ""
|
||||
parts.append("%s %s%d %s" % [stat.to_upper(), sign, amount, duration_text])
|
||||
parts.append("%s %s%d %s" % [_status_stat_display_name(stat), sign, amount, duration_text])
|
||||
return _join_strings(parts, ", ")
|
||||
|
||||
|
||||
func _format_status_remaining_phases(effect: Dictionary) -> String:
|
||||
var remaining: int = maxi(1, int(effect.get("remaining_phases", 1)))
|
||||
var label := "phase" if remaining == 1 else "phases"
|
||||
return "(%d %s)" % [remaining, label]
|
||||
return "(%d회)" % remaining
|
||||
|
||||
|
||||
func _status_display_name(status: String) -> String:
|
||||
var normalized := status.strip_edges()
|
||||
var normalized := status.strip_edges().to_lower()
|
||||
if normalized.is_empty():
|
||||
return "Status"
|
||||
return "상태"
|
||||
if normalized == "poison":
|
||||
return "독"
|
||||
if normalized == "seal":
|
||||
return "봉인"
|
||||
if normalized == "snare":
|
||||
return "발묶임"
|
||||
if normalized == "disarm":
|
||||
return "무장해제"
|
||||
if normalized == "debuff":
|
||||
return "약화"
|
||||
return normalized.replace("_", " ").capitalize()
|
||||
|
||||
|
||||
func _status_stat_display_name(stat: String) -> String:
|
||||
var normalized := stat.strip_edges().to_lower()
|
||||
if normalized == "atk":
|
||||
return "무력"
|
||||
if normalized == "def":
|
||||
return "방비"
|
||||
if normalized == "int":
|
||||
return "지략"
|
||||
if normalized == "agi":
|
||||
return "순발"
|
||||
if normalized == "move":
|
||||
return "행군"
|
||||
return normalized.to_upper()
|
||||
|
||||
|
||||
func _support_duration_text(duration: int) -> String:
|
||||
if duration <= 1:
|
||||
return "다음 차례"
|
||||
return "%d차례" % duration
|
||||
|
||||
|
||||
func _is_supported_status_stat(stat: String) -> bool:
|
||||
return stat == "atk" or stat == "def" or stat == "int" or stat == "agi" or stat == "move"
|
||||
|
||||
@@ -1282,12 +1312,12 @@ func _unit_has_action_lock(unit: Dictionary, action: String) -> bool:
|
||||
|
||||
func _action_lock_display_name(action: String) -> String:
|
||||
if action == "skill":
|
||||
return "no tactics"
|
||||
return "책략 봉인"
|
||||
if action == "move":
|
||||
return "no movement"
|
||||
return "행군 봉인"
|
||||
if action == "attack":
|
||||
return "no attacks"
|
||||
return "no action"
|
||||
return "타격 봉인"
|
||||
return "행동 봉인"
|
||||
|
||||
|
||||
func try_wait_selected() -> bool:
|
||||
@@ -1300,7 +1330,7 @@ func try_wait_selected() -> bool:
|
||||
unit["acted"] = true
|
||||
unit["moved"] = true
|
||||
selected_unit_id = ""
|
||||
_emit_log("%s waits." % unit["name"])
|
||||
_emit_log("%s 대기." % unit["name"])
|
||||
_notify_changed()
|
||||
return true
|
||||
|
||||
@@ -2290,12 +2320,12 @@ func _format_skill_threat_effect_summary(skill: Dictionary) -> String:
|
||||
if not _is_supported_status_stat(stat) or amount == 0:
|
||||
continue
|
||||
var sign := "+" if amount > 0 else ""
|
||||
parts.append("%s %s%d" % [stat.to_upper(), sign, amount])
|
||||
parts.append("%s %s%d" % [_status_stat_display_name(stat), sign, amount])
|
||||
elif effect_type == "damage_over_time":
|
||||
var damage := int(effect.get("amount", 0))
|
||||
if damage <= 0:
|
||||
continue
|
||||
parts.append("%s -%d HP" % [_status_display_name(str(effect.get("status", "poison"))), damage])
|
||||
parts.append("%s -%d 병력" % [_status_display_name(str(effect.get("status", "poison"))), damage])
|
||||
elif effect_type == "action_lock":
|
||||
var status_name := _status_display_name(str(effect.get("status", "status")))
|
||||
parts.append("%s %s" % [status_name, _action_lock_display_name(str(effect.get("action", "")))])
|
||||
@@ -2518,28 +2548,28 @@ func _apply_item_effects(user: Dictionary, target: Dictionary, item: Dictionary)
|
||||
var healed := _apply_item_heal(target, int(effect.get("amount", 0)))
|
||||
if healed > 0:
|
||||
applied = true
|
||||
_emit_log("%s recovers %d HP." % [target["name"], healed])
|
||||
_emit_combat_feedback(target, "+%d HP" % healed, "heal")
|
||||
_emit_log("%s의 병력 %d 회복." % [target["name"], healed])
|
||||
_emit_combat_feedback(target, "+%d 병력" % healed, "heal")
|
||||
elif effect_type == "heal_mp":
|
||||
var restored := _apply_item_mp_heal(target, int(effect.get("amount", 0)))
|
||||
if restored > 0:
|
||||
applied = true
|
||||
_emit_log("%s recovers %d MP." % [target["name"], restored])
|
||||
_emit_combat_feedback(target, "+%d MP" % restored, "mp")
|
||||
_emit_log("%s의 기력 %d 회복." % [target["name"], restored])
|
||||
_emit_combat_feedback(target, "+%d 기력" % restored, "mp")
|
||||
elif effect_type == "cure_status":
|
||||
var cured_statuses := _apply_item_status_cure(target, str(effect.get("status", "")))
|
||||
if not cured_statuses.is_empty():
|
||||
applied = true
|
||||
_emit_log("%s is cured of %s." % [target["name"], _join_strings(cured_statuses, ", ")])
|
||||
_emit_combat_feedback(target, "CURE", "support")
|
||||
_emit_log("%s의 %s 해소." % [target["name"], _join_strings(cured_statuses, ", ")])
|
||||
_emit_combat_feedback(target, "해소", "support")
|
||||
elif effect_type == "cleanse_debuffs":
|
||||
var cleansed_debuffs := _apply_item_debuff_cleanse(target)
|
||||
if not cleansed_debuffs.is_empty():
|
||||
applied = true
|
||||
_emit_log("%s is cleansed of %s." % [target["name"], _join_strings(cleansed_debuffs, ", ")])
|
||||
_emit_combat_feedback(target, "CLEANSE", "support")
|
||||
_emit_log("%s의 약화 해소: %s." % [target["name"], _join_strings(cleansed_debuffs, ", ")])
|
||||
_emit_combat_feedback(target, "정화", "support")
|
||||
if not applied:
|
||||
_emit_log("%s has no effect on %s." % [item.get("name", "Item"), target["name"]])
|
||||
_emit_log("%s은 %s에게 효험이 없었다." % [str(item.get("name", "도구")), target["name"]])
|
||||
return applied
|
||||
|
||||
|
||||
@@ -2670,8 +2700,8 @@ func _is_negative_stat_bonus_effect(effect: Dictionary) -> bool:
|
||||
func _stat_debuff_display_name(effect: Dictionary) -> String:
|
||||
var stat := str(effect.get("stat", "stat"))
|
||||
if not _is_supported_status_stat(stat):
|
||||
return "Debuff"
|
||||
return "%s down" % stat.to_upper()
|
||||
return "약화"
|
||||
return "%s 저하" % _status_stat_display_name(stat)
|
||||
|
||||
|
||||
func _equipment_slot_for_item(item: Dictionary) -> String:
|
||||
@@ -3184,7 +3214,7 @@ func _execute_ai_skill_action(caster: Dictionary, action: Dictionary) -> bool:
|
||||
if _resolve_skill_damage(caster, area_target, skill):
|
||||
defeated_count += 1
|
||||
_grant_experience(caster, EXP_SKILL + defeated_count * EXP_DEFEAT_BONUS)
|
||||
_emit_log("%s spends %d MP." % [caster["name"], int(skill.get("mp_cost", 0))])
|
||||
_emit_log("%s 기력 %d 소모." % [caster["name"], int(skill.get("mp_cost", 0))])
|
||||
return true
|
||||
|
||||
|
||||
@@ -3230,7 +3260,7 @@ func _resolve_combat(attacker: Dictionary, target: Dictionary) -> void:
|
||||
|
||||
func _resolve_attack(attacker: Dictionary, target: Dictionary, is_counter := false) -> Dictionary:
|
||||
var hit_chance := calculate_hit_chance(attacker, target)
|
||||
var verb := "counterattacks" if is_counter else "attacks"
|
||||
var verb := "반격" if is_counter else "공격"
|
||||
unit_action_motion_requested.emit(
|
||||
str(attacker.get("id", "")),
|
||||
attacker.get("pos", Vector2i(-1, -1)),
|
||||
@@ -3238,22 +3268,22 @@ func _resolve_attack(attacker: Dictionary, target: Dictionary, is_counter := fal
|
||||
"counter" if is_counter else "attack"
|
||||
)
|
||||
if rng.randi_range(1, 100) > hit_chance:
|
||||
_emit_log("%s %s %s but misses. Hit %d%%." % [attacker["name"], verb, target["name"], hit_chance])
|
||||
_emit_combat_feedback(target, "MISS", "miss")
|
||||
_emit_log("%s %s %s, 헛쳤다. 명중 %d%%." % [attacker["name"], verb, target["name"], hit_chance])
|
||||
_emit_combat_feedback(target, "헛침", "miss")
|
||||
return {"hit": false, "defeated": false}
|
||||
var damage := calculate_damage(attacker, target)
|
||||
target["hp"] = max(0, int(target["hp"]) - damage)
|
||||
var effective_bonus := _weapon_effectiveness_bonus(attacker, target)
|
||||
var effective_text := ""
|
||||
if effective_bonus > 0:
|
||||
effective_text = " Effective +%d vs %s." % [effective_bonus, _format_move_type(_weapon_effectiveness_target_type(target))]
|
||||
_emit_log("%s %s %s for %d damage. Hit %d%%.%s" % [attacker["name"], verb, target["name"], damage, hit_chance, effective_text])
|
||||
effective_text = " %s 특효 +%d." % [_format_move_type(_weapon_effectiveness_target_type(target)), effective_bonus]
|
||||
_emit_log("%s %s %s, %d 피해. 명중 %d%%.%s" % [attacker["name"], verb, target["name"], damage, hit_chance, effective_text])
|
||||
_emit_combat_feedback(target, "-%d" % damage, "damage")
|
||||
|
||||
if int(target["hp"]) <= 0:
|
||||
target["alive"] = false
|
||||
_emit_log("%s is defeated." % target["name"])
|
||||
_emit_combat_feedback(target, "DOWN", "defeat")
|
||||
_emit_log("%s 퇴각." % target["name"])
|
||||
_emit_combat_feedback(target, "퇴각", "defeat")
|
||||
_handle_unit_defeated(target)
|
||||
return {"hit": true, "defeated": true}
|
||||
return {"hit": true, "defeated": false}
|
||||
@@ -3262,9 +3292,9 @@ func _resolve_attack(attacker: Dictionary, target: Dictionary, is_counter := fal
|
||||
func _resolve_skill_damage(caster: Dictionary, target: Dictionary, skill: Dictionary) -> bool:
|
||||
var damage := calculate_skill_damage(caster, target, skill)
|
||||
target["hp"] = max(0, int(target["hp"]) - damage)
|
||||
_emit_log("%s casts %s on %s for %d damage." % [
|
||||
_emit_log("%s 시전 %s -> %s, %d 피해." % [
|
||||
caster["name"],
|
||||
skill.get("name", "Skill"),
|
||||
skill.get("name", "책략"),
|
||||
target["name"],
|
||||
damage
|
||||
])
|
||||
@@ -3272,8 +3302,8 @@ func _resolve_skill_damage(caster: Dictionary, target: Dictionary, skill: Dictio
|
||||
|
||||
if int(target["hp"]) <= 0:
|
||||
target["alive"] = false
|
||||
_emit_log("%s is defeated." % target["name"])
|
||||
_emit_combat_feedback(target, "DOWN", "defeat")
|
||||
_emit_log("%s 퇴각." % target["name"])
|
||||
_emit_combat_feedback(target, "퇴각", "defeat")
|
||||
_handle_unit_defeated(target)
|
||||
return true
|
||||
return false
|
||||
@@ -3299,13 +3329,13 @@ func _handle_unit_defeated(unit: Dictionary) -> void:
|
||||
func _resolve_skill_heal(caster: Dictionary, target: Dictionary, skill: Dictionary) -> int:
|
||||
var healed := calculate_skill_heal(caster, target, skill)
|
||||
target["hp"] = min(int(target["max_hp"]), int(target["hp"]) + healed)
|
||||
_emit_log("%s casts %s on %s, restoring %d HP." % [
|
||||
_emit_log("%s 시전 %s -> %s, 병력 %d 회복." % [
|
||||
caster["name"],
|
||||
skill.get("name", "Skill"),
|
||||
skill.get("name", "책략"),
|
||||
target["name"],
|
||||
healed
|
||||
])
|
||||
_emit_combat_feedback(target, "+%d HP" % healed, "heal")
|
||||
_emit_combat_feedback(target, "+%d 병력" % healed, "heal")
|
||||
return healed
|
||||
|
||||
|
||||
@@ -3313,7 +3343,7 @@ func _grant_experience(unit: Dictionary, amount: int) -> void:
|
||||
if unit.is_empty() or not unit.get("alive", false) or amount <= 0:
|
||||
return
|
||||
unit["exp"] = int(unit.get("exp", 0)) + amount
|
||||
_emit_log("%s gains %d EXP." % [unit["name"], amount])
|
||||
_emit_log("%s 공적 +%d." % [unit["name"], amount])
|
||||
while int(unit["exp"]) >= EXP_LEVEL:
|
||||
unit["exp"] = int(unit["exp"]) - EXP_LEVEL
|
||||
_level_up(unit)
|
||||
@@ -3330,7 +3360,7 @@ func _level_up(unit: Dictionary) -> void:
|
||||
unit["mp"] = min(int(unit["max_mp"]), int(unit.get("mp", 0)) + mp_gain)
|
||||
for stat in ["atk", "def", "int", "agi"]:
|
||||
unit[stat] = int(unit.get(stat, 0)) + _growth_gain(unit, stat, 1)
|
||||
_emit_log("%s reaches Lv.%d." % [unit["name"], unit["level"]])
|
||||
_emit_log("%s Lv.%d에 이르렀다." % [unit["name"], unit["level"]])
|
||||
_emit_combat_feedback(unit, "Lv.%d" % int(unit["level"]), "progress")
|
||||
if str(unit.get("team", "")) == TEAM_PLAYER:
|
||||
_record_progression_event({
|
||||
@@ -3414,12 +3444,12 @@ func _check_battle_status() -> void:
|
||||
battle_status = STATUS_DEFEAT
|
||||
current_team = TEAM_PLAYER
|
||||
selected_unit_id = ""
|
||||
_emit_log("Defeat condition met.")
|
||||
_emit_log("패전의 조짐이 굳어졌다.")
|
||||
elif _is_condition_group_met(battle_conditions.get("victory", {})):
|
||||
battle_status = STATUS_VICTORY
|
||||
current_team = TEAM_PLAYER
|
||||
selected_unit_id = ""
|
||||
_emit_log("Victory condition met.")
|
||||
_emit_log("승전의 군령이 이루어졌다.")
|
||||
|
||||
|
||||
func _is_condition_group_met(condition_group) -> bool:
|
||||
@@ -4051,9 +4081,9 @@ func _grant_event_item(action: Dictionary, trigger_unit: Dictionary = {}) -> boo
|
||||
return false
|
||||
var count: int = maxi(1, int(action.get("count", 1)))
|
||||
battle_inventory[item_id] = int(battle_inventory.get(item_id, 0)) + count
|
||||
var item_name: String = str(item.get("name", item_id))
|
||||
var item_name: String = _item_display_name(item_id)
|
||||
var count_text: String = "" if count == 1 else " x%d" % count
|
||||
_emit_log("Received %s%s." % [item_name, count_text])
|
||||
_emit_log("전리품: %s%s." % [item_name, count_text])
|
||||
if not trigger_unit.is_empty() and bool(trigger_unit.get("alive", false)):
|
||||
_emit_combat_feedback(trigger_unit, "+%s" % item_name, "item")
|
||||
return true
|
||||
@@ -4067,7 +4097,7 @@ func _grant_event_gold(action: Dictionary, trigger_unit: Dictionary = {}) -> boo
|
||||
battle_gold_reward += amount
|
||||
var text := str(action.get("text", "")).strip_edges()
|
||||
if text.is_empty():
|
||||
text = "Received %d gold." % amount
|
||||
text = "군자금: %dG." % amount
|
||||
_emit_log(text)
|
||||
if not trigger_unit.is_empty() and bool(trigger_unit.get("alive", false)):
|
||||
_emit_combat_feedback(trigger_unit, "+%dG" % amount, "gold")
|
||||
@@ -4230,11 +4260,11 @@ func _withdraw_event_unit(unit_id: String) -> bool:
|
||||
return false
|
||||
if selected_unit_id == normalized_id:
|
||||
selected_unit_id = ""
|
||||
_emit_combat_feedback(unit, "WITHDRAW", "fade")
|
||||
_emit_combat_feedback(unit, "퇴각", "fade")
|
||||
unit["deployed"] = false
|
||||
unit["acted"] = true
|
||||
unit["moved"] = true
|
||||
_emit_log("%s withdraws from the battlefield." % unit.get("name", normalized_id))
|
||||
_emit_log("%s 전장을 물러났다." % unit.get("name", normalized_id))
|
||||
_notify_changed()
|
||||
return true
|
||||
|
||||
@@ -4263,12 +4293,13 @@ func _apply_phase_status_effects_for_team(team: String) -> void:
|
||||
continue
|
||||
unit["hp"] = max(0, int(unit.get("hp", 0)) - damage)
|
||||
var status := str(effect.get("status", "poison"))
|
||||
_emit_log("%s suffers %d %s damage." % [unit["name"], damage, status.replace("_", " ")])
|
||||
var status_name := _status_display_name(status)
|
||||
_emit_log("%s, %s으로 병력 %d 손실." % [unit["name"], status_name, damage])
|
||||
_emit_combat_feedback(unit, "-%d" % damage, status)
|
||||
if int(unit.get("hp", 0)) <= 0:
|
||||
unit["alive"] = false
|
||||
_emit_log("%s is defeated by %s." % [unit["name"], status.replace("_", " ")])
|
||||
_emit_combat_feedback(unit, "DOWN", "defeat")
|
||||
_emit_log("%s, %s으로 퇴각." % [unit["name"], status_name])
|
||||
_emit_combat_feedback(unit, "퇴각", "defeat")
|
||||
_handle_unit_defeated(unit)
|
||||
break
|
||||
|
||||
@@ -4288,13 +4319,13 @@ func _expire_status_effects_for_team(team: String) -> void:
|
||||
kept_effect["remaining_phases"] = next_remaining
|
||||
kept_effects.append(kept_effect)
|
||||
else:
|
||||
var effect_name := str(effect.get("name", "Support"))
|
||||
var effect_name := str(effect.get("name", "지원"))
|
||||
if not expired_names.has(effect_name):
|
||||
expired_names.append(effect_name)
|
||||
unit["status_effects"] = kept_effects
|
||||
for expired_effect_name in expired_names:
|
||||
_emit_log("%s's %s fades." % [unit["name"], expired_effect_name])
|
||||
_emit_combat_feedback(unit, "FADES", "fade")
|
||||
_emit_log("%s의 %s이 사라졌다." % [unit["name"], expired_effect_name])
|
||||
_emit_combat_feedback(unit, "해제", "fade")
|
||||
|
||||
|
||||
func _manhattan(a: Vector2i, b: Vector2i) -> int:
|
||||
@@ -4316,6 +4347,47 @@ func _format_cells(cells: Array[Vector2i]) -> String:
|
||||
return _join_strings(labels, ", ")
|
||||
|
||||
|
||||
func _item_display_name(item_id: String) -> String:
|
||||
match item_id:
|
||||
"bronze_sword":
|
||||
return "청동검"
|
||||
"iron_sword":
|
||||
return "철검"
|
||||
"training_spear":
|
||||
return "연습창"
|
||||
"short_bow":
|
||||
return "단궁"
|
||||
"hand_axe":
|
||||
return "손도끼"
|
||||
"war_axe":
|
||||
return "전부"
|
||||
"war_drum":
|
||||
return "전고"
|
||||
"imperial_seal":
|
||||
return "옥새"
|
||||
"yitian_sword":
|
||||
return "의천검"
|
||||
"dragon_spear":
|
||||
return "용담창"
|
||||
"wind_chaser_bow":
|
||||
return "추풍궁"
|
||||
"black_tortoise_robe":
|
||||
return "현무도포"
|
||||
"bean":
|
||||
return "콩"
|
||||
"antidote":
|
||||
return "해독약"
|
||||
"panacea":
|
||||
return "만능약"
|
||||
"wine":
|
||||
return "술"
|
||||
_:
|
||||
var item := get_item_def(item_id)
|
||||
if item.is_empty():
|
||||
return item_id
|
||||
return str(item.get("name", item_id))
|
||||
|
||||
|
||||
func _join_strings(values: Array, delimiter: String) -> String:
|
||||
var text := ""
|
||||
for value in values:
|
||||
|
||||
@@ -1645,25 +1645,25 @@ func _play_ui_cancel() -> void:
|
||||
|
||||
|
||||
func _play_log_sfx(message: String) -> void:
|
||||
if message.contains(" but misses."):
|
||||
if message.contains(" but misses.") or message.contains("헛쳤다"):
|
||||
_play_sfx("guard_block")
|
||||
elif message.begins_with("Objective updated:") or message.begins_with("Defeat condition updated:"):
|
||||
elif message.begins_with("Objective updated:") or message.begins_with("Defeat condition updated:") or message.begins_with("군령 갱신:") or message.begins_with("패전 군령 갱신:"):
|
||||
_play_ui_confirm()
|
||||
elif message.ends_with(" withdraws from the battlefield."):
|
||||
elif message.ends_with(" withdraws from the battlefield.") or message.ends_with("전장을 물러났다."):
|
||||
_play_ui_confirm()
|
||||
elif message.contains(" attacks ") or message.contains(" counterattacks "):
|
||||
if message.contains(" for "):
|
||||
elif message.contains(" attacks ") or message.contains(" counterattacks ") or message.contains(" 공격 ") or message.contains(" 반격 "):
|
||||
if message.contains(" for ") or message.contains("피해"):
|
||||
_play_sfx("hit_heavy")
|
||||
elif message.contains(" casts "):
|
||||
if message.contains("restoring") or message.contains(" until "):
|
||||
elif message.contains(" casts ") or message.contains(" 시전 "):
|
||||
if message.contains("restoring") or message.contains(" until ") or message.contains("회복") or message.contains("지원"):
|
||||
_play_sfx("skill_cast")
|
||||
else:
|
||||
_play_sfx("fire_skill")
|
||||
elif message.contains(" moved to ") or message.contains(" advances to ") or message.contains(" takes formation at ") or message.contains(" arrives at "):
|
||||
_play_sfx("footstep")
|
||||
elif message.contains(" uses ") or message.contains(" equips ") or message.contains(" 매입:") or message.contains(" 매각:") or message.begins_with("Received "):
|
||||
elif message.contains(" uses ") or message.contains(" equips ") or message.contains(" 사용:") or message.contains(" 장착:") or message.contains(" 매입:") or message.contains(" 매각:") or message.begins_with("Received ") or message.begins_with("전리품:") or message.begins_with("군자금:"):
|
||||
_play_sfx("item_pickup")
|
||||
elif message.contains(" reaches Lv.") or message.contains(" promotes to "):
|
||||
elif message.contains(" reaches Lv.") or message.contains(" promotes to ") or message.contains("공적") or message.contains("승급"):
|
||||
_play_sfx("menu_confirm")
|
||||
|
||||
|
||||
@@ -3056,9 +3056,9 @@ func _skill_target_preview_badge_for_cell(selected: Dictionary, target: Dictiona
|
||||
return _make_target_preview_badge_at("가득", "invalid", cell)
|
||||
if bool(preview.get("has_area", false)):
|
||||
return _make_target_preview_badge_at("+%d x%d" % [total_heal, target_count], "heal", cell)
|
||||
return _make_target_preview_badge_at("+%d HP" % heal, "heal", cell)
|
||||
return _make_target_preview_badge_at("+%d 병력" % heal, "heal", cell)
|
||||
if kind == "support":
|
||||
var effect_text := str(preview.get("effect_text", "Support"))
|
||||
var effect_text := str(preview.get("effect_text", "지원"))
|
||||
var badge_kind := _support_preview_badge_kind(effect_text)
|
||||
if bool(preview.get("has_area", false)):
|
||||
return _make_target_preview_badge_at("%s x%d" % [_compact_support_preview_text(effect_text), target_count], badge_kind, cell)
|
||||
@@ -3099,8 +3099,8 @@ func _item_target_preview_badge_for_cell(selected: Dictionary, target: Dictionar
|
||||
if hp_heal > 0 and mp_heal > 0:
|
||||
return _make_target_preview_badge_at("+%d/%d" % [hp_heal, mp_heal], "heal", cell)
|
||||
if hp_heal > 0:
|
||||
return _make_target_preview_badge_at("+%d HP" % hp_heal, "heal", cell)
|
||||
return _make_target_preview_badge_at("+%d MP" % mp_heal, "mp", cell)
|
||||
return _make_target_preview_badge_at("+%d 병력" % hp_heal, "heal", cell)
|
||||
return _make_target_preview_badge_at("+%d 기력" % mp_heal, "mp", cell)
|
||||
|
||||
|
||||
func _hover_intent_preview_badge(selected: Dictionary, target: Dictionary) -> Dictionary:
|
||||
@@ -3145,7 +3145,10 @@ func _compact_support_preview_text(effect_text: String) -> String:
|
||||
var for_index := part.find(" for ")
|
||||
if for_index >= 0:
|
||||
part = part.substr(0, for_index)
|
||||
if not part.is_empty() and part != "No support effect.":
|
||||
var duration_index := part.find(", ")
|
||||
if duration_index >= 0:
|
||||
part = part.substr(0, duration_index)
|
||||
if not part.is_empty() and part != "No support effect." and part != "효험 없음":
|
||||
parts.append(_compact_support_badge_text(part))
|
||||
if parts.is_empty():
|
||||
return "지원"
|
||||
@@ -3155,27 +3158,27 @@ func _compact_support_preview_text(effect_text: String) -> String:
|
||||
|
||||
|
||||
func _compact_support_badge_text(text: String) -> String:
|
||||
if text.contains("Disarm"):
|
||||
if text.contains("Disarm") or text.contains("무장해제"):
|
||||
return "무장해제"
|
||||
if text.contains("Snare"):
|
||||
if text.contains("Snare") or text.contains("발묶임"):
|
||||
return "속박"
|
||||
if text.contains("Seal"):
|
||||
if text.contains("Seal") or text.contains("봉인"):
|
||||
return "봉인"
|
||||
if text.contains("Poison"):
|
||||
if text.contains("Poison") or text.contains("독"):
|
||||
return "독"
|
||||
if text.contains("Cleanse"):
|
||||
if text.contains("Cleanse") or text.contains("해소"):
|
||||
return "해소"
|
||||
return text
|
||||
|
||||
|
||||
func _support_preview_badge_kind(effect_text: String) -> String:
|
||||
if effect_text.contains("Disarm"):
|
||||
if effect_text.contains("Disarm") or effect_text.contains("무장해제"):
|
||||
return "disarm"
|
||||
if effect_text.contains("Snare"):
|
||||
if effect_text.contains("Snare") or effect_text.contains("발묶임"):
|
||||
return "snare"
|
||||
if effect_text.contains("Seal"):
|
||||
if effect_text.contains("Seal") or effect_text.contains("봉인"):
|
||||
return "seal"
|
||||
if effect_text.contains("Poison"):
|
||||
if effect_text.contains("Poison") or effect_text.contains("독"):
|
||||
return "poison"
|
||||
if effect_text.contains("-"):
|
||||
return "debuff"
|
||||
@@ -3805,7 +3808,7 @@ func _update_skill_forecast(selected: Dictionary) -> void:
|
||||
preview["mp_cost"],
|
||||
mp_text,
|
||||
area_text,
|
||||
preview.get("effect_text", "Support effect"),
|
||||
preview.get("effect_text", "지원"),
|
||||
refresh_text
|
||||
]
|
||||
else:
|
||||
@@ -4617,7 +4620,7 @@ func _load_pending_post_battle_choice() -> void:
|
||||
if briefing_panel != null:
|
||||
briefing_panel.visible = false
|
||||
if log_box != null:
|
||||
log_box.append_text("Campaign choice pending.\n")
|
||||
log_box.append_text("군의 논의가 이어지고 있다.\n")
|
||||
|
||||
|
||||
func _load_scenario(scenario_id: String) -> void:
|
||||
@@ -6426,10 +6429,10 @@ func _on_post_battle_choice_pressed(choice: Dictionary) -> void:
|
||||
_append_result_items(choice.get("items", []))
|
||||
_append_unique_result_values("joined_officers", choice.get("join_officers", []))
|
||||
_append_unique_result_values("left_officers", choice.get("leave_officers", []))
|
||||
_on_log_added("Campaign choice saved: %s." % battle_result_summary["choice_label"])
|
||||
_on_log_added("군령 채택: %s." % battle_result_summary["choice_label"])
|
||||
else:
|
||||
_play_ui_cancel()
|
||||
_on_log_added("Could not save campaign choice.")
|
||||
_on_log_added("군령을 봉하지 못했다.")
|
||||
_rebuild_result_choices()
|
||||
_update_result_next_button_visibility()
|
||||
if result_label != null and state.battle_status == BattleState.STATUS_VICTORY:
|
||||
@@ -6825,7 +6828,7 @@ func _show_campaign_complete() -> void:
|
||||
if briefing_panel != null:
|
||||
briefing_panel.visible = false
|
||||
if log_box != null:
|
||||
log_box.append_text("Campaign complete.\n")
|
||||
log_box.append_text("전기가 여기서 매듭지어졌다.\n")
|
||||
|
||||
|
||||
func _on_new_campaign_pressed() -> void:
|
||||
@@ -7109,7 +7112,7 @@ func _format_post_move_tactic_button_text(skill_id: String, skill: Dictionary, s
|
||||
|
||||
func _format_post_move_item_button_text(item_id: String, item: Dictionary, count: int) -> String:
|
||||
var marker := "> " if selected_item_id == item_id else ""
|
||||
var item_name := str(item.get("name", item_id))
|
||||
var item_name := _item_display_name(item_id)
|
||||
return "%s%s x%d %s" % [marker, item_name, count, _format_post_move_item_effect_text(item)]
|
||||
|
||||
|
||||
@@ -7545,13 +7548,13 @@ func _format_tactic_effect_text(skill: Dictionary) -> String:
|
||||
if amount == 0:
|
||||
continue
|
||||
var sign := "+" if amount > 0 else ""
|
||||
parts.append("%s %s%d" % [str(effect.get("stat", "")).to_upper(), sign, amount])
|
||||
parts.append("%s %s%d" % [_battle_stat_display_name(str(effect.get("stat", ""))), sign, amount])
|
||||
elif effect_type == "damage_over_time" and amount > 0:
|
||||
var status_name := str(effect.get("status", "status")).replace("_", " ").capitalize()
|
||||
var status_name := _battle_status_display_name(str(effect.get("status", "status")))
|
||||
parts.append("%s -%d" % [status_name, amount])
|
||||
elif effect_type == "action_lock":
|
||||
parts.append("%s %s" % [
|
||||
str(effect.get("status", "status")).replace("_", " ").capitalize(),
|
||||
_battle_status_display_name(str(effect.get("status", "status"))),
|
||||
_action_lock_effect_label(str(effect.get("action", "")))
|
||||
])
|
||||
if not parts.is_empty():
|
||||
@@ -7592,6 +7595,42 @@ func _action_lock_effect_label(action: String) -> String:
|
||||
return "군령 봉인"
|
||||
|
||||
|
||||
func _battle_stat_display_name(stat: String) -> String:
|
||||
var normalized := stat.strip_edges().to_lower()
|
||||
if normalized == "hp":
|
||||
return "병력"
|
||||
if normalized == "mp":
|
||||
return "기력"
|
||||
if normalized == "atk":
|
||||
return "무력"
|
||||
if normalized == "def":
|
||||
return "방비"
|
||||
if normalized == "int":
|
||||
return "지략"
|
||||
if normalized == "agi":
|
||||
return "순발"
|
||||
if normalized == "move":
|
||||
return "행군"
|
||||
return _format_identifier_label(stat)
|
||||
|
||||
|
||||
func _battle_status_display_name(status: String) -> String:
|
||||
var normalized := status.strip_edges().to_lower()
|
||||
if normalized == "poison":
|
||||
return "독"
|
||||
if normalized == "seal":
|
||||
return "봉인"
|
||||
if normalized == "snare":
|
||||
return "발묶임"
|
||||
if normalized == "disarm":
|
||||
return "무장해제"
|
||||
if normalized == "debuff":
|
||||
return "약화"
|
||||
if normalized.is_empty():
|
||||
return "상태"
|
||||
return _format_identifier_label(status)
|
||||
|
||||
|
||||
func _skill_kind_text(kind: String) -> String:
|
||||
var normalized := kind.strip_edges().to_lower()
|
||||
if normalized == "damage":
|
||||
@@ -7714,7 +7753,7 @@ func _clear_item_list() -> void:
|
||||
|
||||
func _format_item_button_text(item_id: String, item: Dictionary, count: int) -> String:
|
||||
var marker := "> " if selected_item_id == item_id else ""
|
||||
var item_name := str(item.get("name", item_id))
|
||||
var item_name := _item_display_name(item_id)
|
||||
return "%s%s x%d %s" % [marker, item_name, count, _format_item_effect_text(item)]
|
||||
|
||||
|
||||
@@ -7728,7 +7767,7 @@ func _format_item_effect_text(item: Dictionary) -> String:
|
||||
elif str(effect.get("type", "")) == "heal_mp":
|
||||
parts.append("기력 +%d" % int(effect.get("amount", 0)))
|
||||
elif str(effect.get("type", "")) == "cure_status":
|
||||
parts.append("치료 %s" % str(effect.get("status", "status")).replace("_", " ").capitalize())
|
||||
parts.append("치료 %s" % _battle_status_display_name(str(effect.get("status", "status"))))
|
||||
elif str(effect.get("type", "")) == "cleanse_debuffs":
|
||||
parts.append("약화 해소")
|
||||
if parts.is_empty():
|
||||
@@ -7872,9 +7911,9 @@ func _format_unit_equipment(unit: Dictionary) -> String:
|
||||
for slot in ["weapon", "armor", "accessory"]:
|
||||
var item_id := _equipment_item_id(equipment, slot)
|
||||
if item_id.is_empty():
|
||||
parts.append("%s -" % slot.capitalize())
|
||||
parts.append("%s -" % _equipment_slot_display_name(slot))
|
||||
else:
|
||||
parts.append("%s %s" % [slot.capitalize(), _item_display_name(item_id)])
|
||||
parts.append("%s %s" % [_equipment_slot_display_name(slot), _item_display_name(item_id)])
|
||||
return _join_strings(parts, ", ")
|
||||
|
||||
|
||||
@@ -7911,7 +7950,7 @@ func _format_equipment_option_text(unit: Dictionary, item_id: String, item: Dict
|
||||
|
||||
func _format_equipment_unequip_text(unit: Dictionary, slot: String, item_id: String, item: Dictionary) -> String:
|
||||
var parts := [
|
||||
"%s 해제:" % slot.capitalize(),
|
||||
"%s 해제:" % _equipment_slot_display_name(slot),
|
||||
_item_display_name(item_id)
|
||||
]
|
||||
var change_text := _format_equipment_unequip_change_text(unit, slot, item)
|
||||
@@ -7929,7 +7968,7 @@ func _format_equipment_unequip_change_text(unit: Dictionary, slot: String, item:
|
||||
var delta := -int(current_bonuses.get(stat, 0))
|
||||
if delta == 0:
|
||||
continue
|
||||
parts.append("%s %d" % [stat.to_upper(), delta])
|
||||
parts.append("%s %d" % [_battle_stat_display_name(stat), delta])
|
||||
if slot == "weapon":
|
||||
var current_range := _format_equipment_item_range_text(item)
|
||||
if not current_range.is_empty():
|
||||
@@ -7960,7 +7999,7 @@ func _format_equipment_change_text(unit: Dictionary, item: Dictionary) -> String
|
||||
if delta == 0:
|
||||
continue
|
||||
var sign := "+" if delta > 0 else ""
|
||||
parts.append("%s %s%d" % [stat.to_upper(), sign, delta])
|
||||
parts.append("%s %s%d" % [_battle_stat_display_name(stat), sign, delta])
|
||||
|
||||
var range_text := _format_equipment_range_change_text(current_item, item)
|
||||
if not range_text.is_empty():
|
||||
@@ -7980,6 +8019,17 @@ func _equipment_slot_for_display(item: Dictionary) -> String:
|
||||
return ""
|
||||
|
||||
|
||||
func _equipment_slot_display_name(slot: String) -> String:
|
||||
var normalized := slot.strip_edges().to_lower()
|
||||
if normalized == "weapon":
|
||||
return "병장"
|
||||
if normalized == "armor":
|
||||
return "갑주"
|
||||
if normalized == "accessory":
|
||||
return "보물"
|
||||
return _format_identifier_label(slot)
|
||||
|
||||
|
||||
func _equipment_bonus_map(item: Dictionary) -> Dictionary:
|
||||
if item.is_empty() or typeof(item.get("bonuses", {})) != TYPE_DICTIONARY:
|
||||
return {}
|
||||
@@ -7995,7 +8045,7 @@ func _format_equipment_range_change_text(current_item: Dictionary, candidate_ite
|
||||
return ""
|
||||
if current_range.is_empty():
|
||||
current_range = "-"
|
||||
return "RNG %s->%s" % [current_range, candidate_range]
|
||||
return "사거리 %s->%s" % [current_range, candidate_range]
|
||||
|
||||
|
||||
func _format_equipment_item_range_text(item: Dictionary) -> String:
|
||||
@@ -8021,10 +8071,10 @@ func _format_equipment_effectiveness_change_text(current_item: Dictionary, candi
|
||||
if candidate_text == current_text:
|
||||
return ""
|
||||
if current_text.is_empty():
|
||||
return "Gains %s" % candidate_text
|
||||
return "특효 획득 %s" % candidate_text
|
||||
if candidate_text.is_empty():
|
||||
return "Loses %s" % current_text
|
||||
return "Effect changes"
|
||||
return "특효 상실 %s" % current_text
|
||||
return "특효 변화"
|
||||
|
||||
|
||||
func _format_equipment_bonus_text(item: Dictionary) -> String:
|
||||
@@ -8038,12 +8088,12 @@ func _format_equipment_bonus_text(item: Dictionary) -> String:
|
||||
if amount == 0:
|
||||
continue
|
||||
var sign := "+" if amount > 0 else ""
|
||||
parts.append("%s %s%d" % [stat.to_upper(), sign, amount])
|
||||
parts.append("%s %s%d" % [_battle_stat_display_name(stat), sign, amount])
|
||||
var effective_text := _format_equipment_effectiveness_text(item)
|
||||
if not effective_text.is_empty():
|
||||
parts.append(effective_text)
|
||||
if parts.is_empty():
|
||||
return str(item.get("kind", "equipment")).capitalize()
|
||||
return _item_kind_text(str(item.get("kind", "item")))
|
||||
return _join_strings(parts, ", ")
|
||||
|
||||
|
||||
@@ -8054,7 +8104,7 @@ func _format_equipment_rarity_text(item: Dictionary) -> String:
|
||||
func _format_item_rarity_text(item: Dictionary) -> String:
|
||||
var rarity := str(item.get("rarity", ""))
|
||||
if rarity == "named":
|
||||
return "Named"
|
||||
return "명품"
|
||||
return ""
|
||||
|
||||
|
||||
@@ -8074,7 +8124,7 @@ func _format_equipment_effectiveness_text(item: Dictionary) -> String:
|
||||
labels.append(label)
|
||||
if labels.is_empty():
|
||||
return ""
|
||||
return "Effective +%d vs %s" % [bonus, _join_strings(labels, "/")]
|
||||
return "%s 특효 +%d" % [_join_strings(labels, "/"), bonus]
|
||||
|
||||
|
||||
func _format_move_type(move_type: String) -> String:
|
||||
|
||||
Reference in New Issue
Block a user