Age battle UI toward ancient campaign style
This commit is contained in:
@@ -83,6 +83,9 @@ const UI_BAMBOO_DARK := Color(0.20, 0.11, 0.045, 1.0)
|
||||
const UI_MUTED_JADE := Color(0.16, 0.30, 0.23, 1.0)
|
||||
const UI_PARCHMENT_TEXT := Color(0.95, 0.82, 0.55, 1.0)
|
||||
const UI_DISABLED_TEXT := Color(0.48, 0.40, 0.29, 1.0)
|
||||
const UI_SILK_WASH := Color(0.80, 0.64, 0.37, 1.0)
|
||||
const UI_SILK_FIBER := Color(0.18, 0.10, 0.045, 1.0)
|
||||
const MAP_SCROLL_FRAME_PADDING := 12.0
|
||||
|
||||
var state: BattleState = BattleStateScript.new()
|
||||
var campaign_state: CampaignState = CampaignStateScript.new()
|
||||
@@ -431,6 +434,27 @@ func _make_bamboo_divider(width: float = 0.0, height: float = 4.0) -> HBoxContai
|
||||
return row
|
||||
|
||||
|
||||
func _make_scroll_rod(width: float = 0.0, height: float = 4.0) -> HBoxContainer:
|
||||
var row := HBoxContainer.new()
|
||||
row.custom_minimum_size = Vector2(width, height)
|
||||
row.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
row.add_theme_constant_override("separation", 2)
|
||||
var cap_width: float = maxf(8.0, height * 3.0)
|
||||
for index in range(5):
|
||||
var strip := ColorRect.new()
|
||||
strip.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
strip.custom_minimum_size = Vector2(cap_width if index != 2 else width, height)
|
||||
strip.size_flags_horizontal = Control.SIZE_EXPAND_FILL if index == 2 else Control.SIZE_SHRINK_CENTER
|
||||
if index == 0 or index == 4:
|
||||
strip.color = UI_CINNABAR_DARK
|
||||
elif index == 1 or index == 3:
|
||||
strip.color = UI_OLD_BRONZE
|
||||
else:
|
||||
strip.color = UI_BAMBOO
|
||||
row.add_child(strip)
|
||||
return row
|
||||
|
||||
|
||||
func _make_section_caption(text: String, width: float = 0.0) -> Label:
|
||||
var label := Label.new()
|
||||
label.text = text
|
||||
@@ -558,7 +582,7 @@ func _create_hud() -> void:
|
||||
selected_row.add_child(selected_label)
|
||||
|
||||
mission_title_label = Label.new()
|
||||
mission_title_label.text = "Battle Mandate"
|
||||
mission_title_label.text = "Imperial Mandate"
|
||||
mission_title_label.add_theme_font_size_override("font_size", 14)
|
||||
_apply_label_style(mission_title_label, UI_OLD_BRONZE)
|
||||
side_column.add_child(mission_title_label)
|
||||
@@ -846,8 +870,8 @@ func _create_hud() -> void:
|
||||
_apply_label_style(briefing_location_label, UI_MUTED_JADE, 14)
|
||||
briefing_column.add_child(briefing_location_label)
|
||||
|
||||
briefing_column.add_child(_make_bamboo_divider(680, 4))
|
||||
briefing_column.add_child(_make_section_caption("Bronze War Edict", 680))
|
||||
briefing_column.add_child(_make_scroll_rod(680, 4))
|
||||
briefing_column.add_child(_make_section_caption("Imperial Bronze War Edict", 680))
|
||||
|
||||
briefing_objective_panel = PanelContainer.new()
|
||||
briefing_objective_panel.custom_minimum_size = Vector2(680, 92)
|
||||
@@ -867,7 +891,7 @@ func _create_hud() -> void:
|
||||
_apply_label_style(briefing_objective_label, UI_AGED_INK, 15)
|
||||
briefing_objective_row.add_child(briefing_objective_label)
|
||||
|
||||
briefing_column.add_child(_make_section_caption("Bamboo Map and Camp Ledger", 680))
|
||||
briefing_column.add_child(_make_section_caption("Silk Map and Camp Ledger", 680))
|
||||
|
||||
briefing_camp_overview_row = HBoxContainer.new()
|
||||
briefing_camp_overview_row.custom_minimum_size = Vector2(680, 84)
|
||||
@@ -905,7 +929,7 @@ func _create_hud() -> void:
|
||||
_apply_label_style(briefing_camp_overview_label, UI_AGED_INK, 14)
|
||||
briefing_camp_overview_row.add_child(briefing_camp_overview_label)
|
||||
|
||||
briefing_column.add_child(_make_bamboo_divider(680, 3))
|
||||
briefing_column.add_child(_make_scroll_rod(680, 3))
|
||||
|
||||
var briefing_scroll := ScrollContainer.new()
|
||||
briefing_scroll.custom_minimum_size = Vector2(680, 66)
|
||||
@@ -1116,7 +1140,7 @@ func _create_hud() -> void:
|
||||
save_action_row.add_child(manual_load_button)
|
||||
|
||||
var begin_button := Button.new()
|
||||
begin_button.text = "Enter Field"
|
||||
begin_button.text = "Unroll War Map"
|
||||
begin_button.pressed.connect(_on_begin_battle_pressed)
|
||||
briefing_column.add_child(begin_button)
|
||||
|
||||
@@ -1161,7 +1185,7 @@ func _create_hud() -> void:
|
||||
dialogue_column.add_theme_constant_override("separation", 8)
|
||||
dialogue_row.add_child(dialogue_column)
|
||||
|
||||
dialogue_column.add_child(_make_bamboo_divider(DIALOGUE_TEXT_SIZE.x, 3))
|
||||
dialogue_column.add_child(_make_scroll_rod(DIALOGUE_TEXT_SIZE.x, 3))
|
||||
|
||||
dialogue_speaker_panel = PanelContainer.new()
|
||||
dialogue_speaker_panel.custom_minimum_size = Vector2(DIALOGUE_TEXT_SIZE.x, 32)
|
||||
@@ -1193,7 +1217,7 @@ func _create_hud() -> void:
|
||||
_apply_label_style(dialogue_text_label, UI_AGED_INK, 17)
|
||||
dialogue_text_row.add_child(dialogue_text_label)
|
||||
|
||||
dialogue_column.add_child(_make_bamboo_divider(DIALOGUE_TEXT_SIZE.x, 3))
|
||||
dialogue_column.add_child(_make_scroll_rod(DIALOGUE_TEXT_SIZE.x, 3))
|
||||
|
||||
var dialogue_control_row := HBoxContainer.new()
|
||||
dialogue_control_row.add_theme_constant_override("separation", 8)
|
||||
@@ -1230,6 +1254,8 @@ func _create_hud() -> void:
|
||||
result_column.alignment = BoxContainer.ALIGNMENT_CENTER
|
||||
result_panel.add_child(result_column)
|
||||
|
||||
result_column.add_child(_make_scroll_rod(520, 4))
|
||||
|
||||
result_label = Label.new()
|
||||
result_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_LEFT
|
||||
result_label.vertical_alignment = VERTICAL_ALIGNMENT_TOP
|
||||
@@ -1238,6 +1264,8 @@ func _create_hud() -> void:
|
||||
_apply_label_style(result_label, UI_AGED_INK, 16)
|
||||
result_column.add_child(result_label)
|
||||
|
||||
result_column.add_child(_make_scroll_rod(520, 3))
|
||||
|
||||
result_choice_list = VBoxContainer.new()
|
||||
result_choice_list.add_theme_constant_override("separation", 6)
|
||||
result_column.add_child(result_choice_list)
|
||||
@@ -1759,7 +1787,58 @@ func _draw_map() -> void:
|
||||
_draw_terrain_edge_blend(cell, rect, terrain_key)
|
||||
draw_rect(rect, _map_grid_color(has_background), false, 1.0)
|
||||
|
||||
draw_rect(board_rect, Color(0.02, 0.025, 0.03), false, 3.0)
|
||||
_draw_silk_map_patina(board_rect, has_background)
|
||||
_draw_silk_map_frame(board_rect)
|
||||
|
||||
|
||||
func _draw_silk_map_patina(board_rect: Rect2, has_background: bool) -> void:
|
||||
var wash := UI_SILK_WASH
|
||||
wash.a = 0.08 if has_background else 0.14
|
||||
draw_rect(board_rect, wash)
|
||||
var fiber := UI_SILK_FIBER
|
||||
fiber.a = 0.12 if has_background else 0.18
|
||||
for index in range(7):
|
||||
var y := board_rect.position.y + 18.0 + float(index) * (board_rect.size.y - 36.0) / 6.0
|
||||
var drift := 4.0 + _cell_noise(Vector2i(index, state.map_size.y), 211) * 10.0
|
||||
draw_line(
|
||||
Vector2(board_rect.position.x + 12.0, y),
|
||||
Vector2(board_rect.end.x - 12.0, y + drift),
|
||||
fiber,
|
||||
1.0
|
||||
)
|
||||
for index in range(5):
|
||||
var x := board_rect.position.x + 20.0 + float(index) * (board_rect.size.x - 40.0) / 4.0
|
||||
var drift := 5.0 + _cell_noise(Vector2i(state.map_size.x, index), 227) * 9.0
|
||||
draw_line(
|
||||
Vector2(x, board_rect.position.y + 12.0),
|
||||
Vector2(x + drift, board_rect.end.y - 12.0),
|
||||
Color(fiber.r, fiber.g, fiber.b, fiber.a * 0.65),
|
||||
1.0
|
||||
)
|
||||
var corner_stain := Color(0.12, 0.06, 0.025, 0.12 if has_background else 0.18)
|
||||
draw_circle(board_rect.position + Vector2(20, 18), 26.0, corner_stain)
|
||||
draw_circle(board_rect.end - Vector2(24, 22), 30.0, corner_stain)
|
||||
|
||||
|
||||
func _draw_silk_map_frame(board_rect: Rect2) -> void:
|
||||
var padding := MAP_SCROLL_FRAME_PADDING
|
||||
var top_rod := Rect2(board_rect.position + Vector2(-padding, -padding), Vector2(board_rect.size.x + padding * 2.0, 7.0))
|
||||
var bottom_rod := Rect2(Vector2(board_rect.position.x - padding, board_rect.end.y + padding - 7.0), top_rod.size)
|
||||
var left_rod := Rect2(board_rect.position + Vector2(-padding, -padding), Vector2(7.0, board_rect.size.y + padding * 2.0))
|
||||
var right_rod := Rect2(Vector2(board_rect.end.x + padding - 7.0, board_rect.position.y - padding), left_rod.size)
|
||||
for rod in [top_rod, bottom_rod, left_rod, right_rod]:
|
||||
draw_rect(rod, UI_BAMBOO_DARK)
|
||||
draw_rect(rod, Color(0.62, 0.43, 0.18, 0.80), false, 1.0)
|
||||
for corner in [
|
||||
top_rod.position - Vector2(3, 3),
|
||||
Vector2(top_rod.end.x - 11.0, top_rod.position.y - 3.0),
|
||||
Vector2(bottom_rod.position.x - 3.0, bottom_rod.end.y - 11.0),
|
||||
bottom_rod.end - Vector2(11, 11)
|
||||
]:
|
||||
draw_rect(Rect2(corner, Vector2(14, 14)), UI_CINNABAR_DARK)
|
||||
draw_rect(Rect2(corner + Vector2(2, 2), Vector2(10, 10)), UI_OLD_BRONZE, false, 1.0)
|
||||
draw_rect(board_rect.grow(4.0), UI_LACQUER_EDGE, false, 5.0)
|
||||
draw_rect(board_rect.grow(1.0), UI_OLD_BRONZE, false, 2.0)
|
||||
|
||||
|
||||
func _current_battle_background_texture() -> Texture2D:
|
||||
@@ -2964,8 +3043,8 @@ func _update_hud() -> void:
|
||||
func _format_objective_hud_text() -> String:
|
||||
var text := String(state.objectives.get("victory", "Defeat all enemies."))
|
||||
if text.is_empty():
|
||||
return "Battle Mandate"
|
||||
return "Battle Mandate: %s" % text
|
||||
return "Imperial Mandate"
|
||||
return "Imperial Mandate: %s" % text
|
||||
|
||||
|
||||
func _format_unit_focus_text(unit: Dictionary, prefix: String) -> String:
|
||||
@@ -3135,19 +3214,19 @@ func _format_mission_panel_text() -> String:
|
||||
var lines := []
|
||||
var victory := str(state.objectives.get("victory", ""))
|
||||
if not victory.is_empty():
|
||||
lines.append("Edict: %s" % victory)
|
||||
lines.append("Imperial Edict: %s" % victory)
|
||||
var progress_lines := state.get_objective_progress_lines(false, false)
|
||||
if not progress_lines.is_empty():
|
||||
lines.append("Battle Register:")
|
||||
lines.append("Bamboo Register:")
|
||||
for progress_line in progress_lines:
|
||||
lines.append(" %s" % progress_line)
|
||||
var risk_lines := state.get_defeat_progress_lines()
|
||||
if not risk_lines.is_empty():
|
||||
lines.append("Dire Portents:")
|
||||
lines.append("Ominous Signs:")
|
||||
for risk_line in risk_lines:
|
||||
lines.append(" %s" % risk_line)
|
||||
if lines.is_empty():
|
||||
return "No battle mandate."
|
||||
return "No edict has been sealed."
|
||||
return _join_strings(lines, "\n")
|
||||
|
||||
|
||||
@@ -3542,10 +3621,7 @@ func _update_result_panel() -> void:
|
||||
if result_restart_button != null:
|
||||
result_restart_button.visible = true
|
||||
_update_result_next_button_visibility()
|
||||
result_label.text = "Victory Proclamation\n%s\n%s" % [
|
||||
state.objectives.get("victory", ""),
|
||||
_format_battle_result_summary()
|
||||
]
|
||||
result_label.text = _format_victory_result_text()
|
||||
elif state.battle_status == BattleState.STATUS_DEFEAT:
|
||||
_clear_dialogue()
|
||||
_clear_result_choices()
|
||||
@@ -3554,7 +3630,7 @@ func _update_result_panel() -> void:
|
||||
result_restart_button.visible = true
|
||||
if next_battle_button != null:
|
||||
next_battle_button.visible = false
|
||||
result_label.text = "Defeat Memorial\n%s" % state.objectives.get("defeat", "")
|
||||
result_label.text = _format_defeat_result_text()
|
||||
else:
|
||||
_clear_result_choices()
|
||||
result_panel.visible = false
|
||||
@@ -3564,6 +3640,17 @@ func _update_result_panel() -> void:
|
||||
next_battle_button.visible = false
|
||||
|
||||
|
||||
func _format_victory_result_text() -> String:
|
||||
return "Bronze Victory Proclamation\nMandate Fulfilled: %s\n%s" % [
|
||||
state.objectives.get("victory", ""),
|
||||
_format_battle_result_summary()
|
||||
]
|
||||
|
||||
|
||||
func _format_defeat_result_text() -> String:
|
||||
return "Defeat Memorial Tablet\nOmen Fulfilled: %s" % state.objectives.get("defeat", "")
|
||||
|
||||
|
||||
func _on_state_changed() -> void:
|
||||
if state.get_selected_unit().is_empty():
|
||||
selected_skill_id = ""
|
||||
@@ -3584,18 +3671,18 @@ func _on_log_added(message: String) -> void:
|
||||
|
||||
func _format_log_entry_text(message: String) -> String:
|
||||
if message.begins_with("Objective updated:"):
|
||||
return "Mandate revised:%s" % message.substr("Objective updated:".length())
|
||||
return "Edict amended:%s" % message.substr("Objective updated:".length())
|
||||
if message.begins_with("Defeat condition updated:"):
|
||||
return "Omen revised:%s" % message.substr("Defeat condition updated:".length())
|
||||
return "Omen amended:%s" % message.substr("Defeat condition updated:".length())
|
||||
return message
|
||||
|
||||
|
||||
func _on_objective_updated(victory: String, defeat: String) -> void:
|
||||
var notice_lines := ["New Battle Mandate"]
|
||||
var notice_lines := ["New Sealed Edict"]
|
||||
if not victory.is_empty():
|
||||
notice_lines.append("Mandate: %s" % victory)
|
||||
notice_lines.append("Imperial Mandate: %s" % victory)
|
||||
if not defeat.is_empty():
|
||||
notice_lines.append("Omen: %s" % defeat)
|
||||
notice_lines.append("Defeat Omen: %s" % defeat)
|
||||
if objective_notice_label != null:
|
||||
objective_notice_label.text = "\n".join(notice_lines)
|
||||
if objective_notice_panel != null:
|
||||
@@ -4317,27 +4404,27 @@ func _format_briefing_objectives() -> String:
|
||||
var text := ""
|
||||
var victory := str(state.objectives.get("victory", ""))
|
||||
if not victory.is_empty():
|
||||
text = "Mandate of Victory: %s" % victory
|
||||
text = "Imperial Victory Edict: %s" % victory
|
||||
var defeat := str(state.objectives.get("defeat", ""))
|
||||
if not defeat.is_empty():
|
||||
if not text.is_empty():
|
||||
text += "\n"
|
||||
text += "Omen of Ruin: %s" % defeat
|
||||
text += "Defeat Omen: %s" % defeat
|
||||
var progress_lines := state.get_objective_progress_lines(false, false)
|
||||
if not progress_lines.is_empty():
|
||||
if not text.is_empty():
|
||||
text += "\n"
|
||||
text += "Battle Register: %s" % _join_strings(progress_lines, ", ")
|
||||
text += "Bamboo Battle Register: %s" % _join_strings(progress_lines, ", ")
|
||||
var risk_lines := state.get_defeat_progress_lines()
|
||||
if not risk_lines.is_empty():
|
||||
if not text.is_empty():
|
||||
text += "\n"
|
||||
text += "Dire Portents: %s" % _join_strings(risk_lines, ", ")
|
||||
text += "Ominous Signs: %s" % _join_strings(risk_lines, ", ")
|
||||
var rewards_text := _format_briefing_rewards()
|
||||
if not rewards_text.is_empty():
|
||||
if not text.is_empty():
|
||||
text += "\n"
|
||||
text += "Spoils Ledger: %s" % rewards_text
|
||||
text += "Spoils Seal: %s" % rewards_text
|
||||
return text
|
||||
|
||||
|
||||
@@ -6022,10 +6109,7 @@ func _on_post_battle_choice_pressed(choice: Dictionary) -> void:
|
||||
_rebuild_result_choices()
|
||||
_update_result_next_button_visibility()
|
||||
if result_label != null and state.battle_status == BattleState.STATUS_VICTORY:
|
||||
result_label.text = "Victory Proclamation\n%s\n%s" % [
|
||||
state.objectives.get("victory", ""),
|
||||
_format_battle_result_summary()
|
||||
]
|
||||
result_label.text = _format_victory_result_text()
|
||||
_update_hud()
|
||||
|
||||
|
||||
@@ -6899,8 +6983,8 @@ func _action_phase_block_reason() -> Dictionary:
|
||||
}
|
||||
if not battle_started:
|
||||
return {
|
||||
"label": "Enter Field",
|
||||
"tooltip": "Begin the battle before using combat actions."
|
||||
"label": "Unroll Map",
|
||||
"tooltip": "Unroll the war map before issuing combat orders."
|
||||
}
|
||||
if state.battle_status != BattleState.STATUS_ACTIVE:
|
||||
return {
|
||||
@@ -6954,7 +7038,7 @@ func _update_threat_button() -> void:
|
||||
_set_action_button_blocked(threat_button, "Enemy Lines", "Chronicle Sealed", "The campaign is complete.")
|
||||
return
|
||||
if not battle_started:
|
||||
_set_action_button_blocked(threat_button, "Enemy Lines", "Enter Field", "Begin the battle before reading enemy lines.")
|
||||
_set_action_button_blocked(threat_button, "Enemy Lines", "Unroll Map", "Unroll the war map before reading enemy lines.")
|
||||
return
|
||||
if state.battle_status != BattleState.STATUS_ACTIVE:
|
||||
_set_action_button_blocked(threat_button, "Enemy Lines", "Field Settled", "Enemy lines are only available during active battles.")
|
||||
|
||||
Reference in New Issue
Block a user