Add early battle backgrounds and unit class seals
This commit is contained in:
BIN
art/backgrounds/puyang_raid_camp.png
Normal file
BIN
art/backgrounds/puyang_raid_camp.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.5 MiB |
BIN
art/backgrounds/qingzhou_village_road.png
Normal file
BIN
art/backgrounds/qingzhou_village_road.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.9 MiB |
BIN
art/backgrounds/xingyang_forest_ambush.png
Normal file
BIN
art/backgrounds/xingyang_forest_ambush.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.6 MiB |
BIN
art/items/imperial_seal.png
Normal file
BIN
art/items/imperial_seal.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.2 MiB |
BIN
art/items/war_drum.png
Normal file
BIN
art/items/war_drum.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.4 MiB |
@@ -97,6 +97,7 @@
|
||||
"war_drum": {
|
||||
"name": "War Drum",
|
||||
"kind": "accessory",
|
||||
"icon": "res://art/items/war_drum.png",
|
||||
"accessory_type": "accessory",
|
||||
"bonuses": { "atk": 1, "agi": 1 },
|
||||
"effects": [],
|
||||
@@ -105,6 +106,7 @@
|
||||
"imperial_seal": {
|
||||
"name": "Imperial Seal",
|
||||
"kind": "accessory",
|
||||
"icon": "res://art/items/imperial_seal.png",
|
||||
"accessory_type": "accessory",
|
||||
"bonuses": { "mp": 4, "int": 1 },
|
||||
"effects": [],
|
||||
|
||||
@@ -142,6 +142,7 @@
|
||||
"map": {
|
||||
"width": 12,
|
||||
"height": 9,
|
||||
"background": "res://art/backgrounds/xingyang_forest_ambush.png",
|
||||
"terrain": [
|
||||
"GGGFFRRGGGGG",
|
||||
"GGGFFRRGHHGG",
|
||||
|
||||
@@ -122,6 +122,7 @@
|
||||
"map": {
|
||||
"width": 14,
|
||||
"height": 10,
|
||||
"background": "res://art/backgrounds/qingzhou_village_road.png",
|
||||
"terrain": [
|
||||
"GGGGGGGGGGGGGG",
|
||||
"GGGFFFGGGHHGGG",
|
||||
|
||||
@@ -117,6 +117,7 @@
|
||||
"map": {
|
||||
"width": 14,
|
||||
"height": 10,
|
||||
"background": "res://art/backgrounds/puyang_raid_camp.png",
|
||||
"terrain": [
|
||||
"GGGGGHHGGGGGGG",
|
||||
"GGGFFHHGGGFFGG",
|
||||
|
||||
@@ -2604,6 +2604,7 @@ func _draw_units() -> void:
|
||||
draw_arc(center, 28, 0.0, TAU, 64, Color(0.03, 0.035, 0.04), 3.0)
|
||||
draw_arc(center, 28, -PI * 0.65, PI * 0.35, 36, team_color.lightened(0.18), 3.0)
|
||||
_draw_unit_identity_marks(rect, center, unit, team_color)
|
||||
_draw_unit_class_emblem(rect, center, unit, team_color)
|
||||
_draw_unit_class_badge(rect, unit, team_color)
|
||||
|
||||
var label := _short_name(String(unit["name"]))
|
||||
@@ -2768,24 +2769,94 @@ func _is_generic_enemy_unit(unit: Dictionary) -> bool:
|
||||
|
||||
|
||||
func _draw_unit_class_badge(rect: Rect2, unit: Dictionary, team_color: Color) -> void:
|
||||
var badge_rect := Rect2(rect.position + Vector2(5, 5), Vector2(28, 13))
|
||||
draw_rect(badge_rect, Color(0.02, 0.022, 0.026, 0.82))
|
||||
draw_rect(badge_rect, team_color.lightened(0.18), false, 1.2)
|
||||
var badge_rect := Rect2(rect.position + Vector2(4, 4), Vector2(20, 20))
|
||||
var class_color := _unit_class_badge_color(unit, team_color)
|
||||
draw_rect(badge_rect, Color(0.035, 0.018, 0.012, 0.88))
|
||||
draw_rect(badge_rect.grow(-2.0), Color(class_color.r, class_color.g, class_color.b, 0.78))
|
||||
draw_rect(badge_rect, UI_OLD_BRONZE, false, 1.3)
|
||||
var font := _draw_ui_font(true)
|
||||
draw_string(font, badge_rect.position + Vector2(1, 11), _unit_class_abbrev(unit), HORIZONTAL_ALIGNMENT_CENTER, badge_rect.size.x - 2, 8, Color.WHITE)
|
||||
draw_string(font, badge_rect.position + Vector2(0, 15), _unit_class_abbrev(unit), HORIZONTAL_ALIGNMENT_CENTER, badge_rect.size.x, 13, UI_PARCHMENT_TEXT)
|
||||
|
||||
|
||||
func _draw_unit_class_emblem(rect: Rect2, center: Vector2, unit: Dictionary, team_color: Color) -> void:
|
||||
var family := _unit_class_family(unit)
|
||||
var class_color := _unit_class_badge_color(unit, team_color)
|
||||
var emblem := class_color.lightened(0.36)
|
||||
emblem.a = 0.72
|
||||
var shadow := Color(0.02, 0.016, 0.012, 0.72)
|
||||
if family == "cavalry":
|
||||
var pole_start := center + Vector2(16, -24)
|
||||
var pole_end := center + Vector2(16, 16)
|
||||
draw_line(pole_start + Vector2(1, 1), pole_end + Vector2(1, 1), shadow, 2.2)
|
||||
draw_line(pole_start, pole_end, emblem, 2.0)
|
||||
var pennant := PackedVector2Array([
|
||||
pole_start,
|
||||
pole_start + Vector2(22, 7),
|
||||
pole_start + Vector2(5, 16)
|
||||
])
|
||||
draw_colored_polygon(pennant, Color(class_color.r, class_color.g, class_color.b, 0.50))
|
||||
draw_polyline(PackedVector2Array([pennant[0], pennant[1], pennant[2], pennant[0]]), emblem, 1.2)
|
||||
elif family == "ranged":
|
||||
var bow_center := center + Vector2(-17, -5)
|
||||
draw_arc(bow_center + Vector2(1, 1), 17.0, -PI * 0.55, PI * 0.55, 24, shadow, 2.4)
|
||||
draw_arc(bow_center, 17.0, -PI * 0.55, PI * 0.55, 24, emblem, 2.2)
|
||||
draw_line(bow_center + Vector2(6, -14), bow_center + Vector2(6, 14), Color(0.92, 0.82, 0.56, 0.58), 1.2)
|
||||
draw_line(center + Vector2(-14, -5), center + Vector2(8, -5), emblem, 1.6)
|
||||
elif family == "tactic":
|
||||
draw_arc(center + Vector2(0, -3), 20.0, 0.0, TAU, 40, Color(emblem.r, emblem.g, emblem.b, 0.42), 1.8)
|
||||
draw_arc(center + Vector2(0, -3), 12.0, -PI * 0.25, PI * 1.25, 30, emblem, 1.6)
|
||||
draw_line(center + Vector2(-11, -3), center + Vector2(11, -3), Color(1.0, 0.88, 0.38, 0.42), 1.2)
|
||||
draw_line(center + Vector2(0, -14), center + Vector2(0, 8), Color(1.0, 0.88, 0.38, 0.32), 1.2)
|
||||
elif family == "heavy":
|
||||
draw_line(center + Vector2(-19, -16), center + Vector2(17, 18), shadow, 4.4)
|
||||
draw_line(center + Vector2(-19, -16), center + Vector2(17, 18), emblem, 3.0)
|
||||
draw_line(center + Vector2(14, -17), center + Vector2(-16, 16), Color(1.0, 0.82, 0.32, 0.48), 2.4)
|
||||
draw_circle(center + Vector2(15, 18), 4.5, Color(class_color.r, class_color.g, class_color.b, 0.42))
|
||||
else:
|
||||
var shield := Rect2(center + Vector2(-13, -17), Vector2(26, 28))
|
||||
draw_rect(Rect2(shield.position + Vector2(1, 1), shield.size), shadow)
|
||||
draw_rect(shield, Color(class_color.r, class_color.g, class_color.b, 0.38))
|
||||
draw_rect(shield.grow(-4.0), Color(0.82, 0.76, 0.58, 0.28), false, 1.4)
|
||||
draw_line(shield.position + Vector2(shield.size.x * 0.5, 3), shield.position + Vector2(shield.size.x * 0.5, shield.size.y - 3), emblem, 1.6)
|
||||
|
||||
|
||||
func _unit_class_abbrev(unit: Dictionary) -> String:
|
||||
var family := _unit_class_family(unit)
|
||||
if family == "cavalry":
|
||||
return "騎"
|
||||
if family == "ranged":
|
||||
return "弓"
|
||||
if family == "tactic":
|
||||
return "策"
|
||||
if family == "heavy":
|
||||
return "武"
|
||||
return "步"
|
||||
|
||||
|
||||
func _unit_class_family(unit: Dictionary) -> String:
|
||||
var class_id := str(unit.get("class_id", ""))
|
||||
if class_id.contains("cavalry"):
|
||||
return "CAV"
|
||||
return "cavalry"
|
||||
if class_id.contains("archer") or class_id.contains("marksman"):
|
||||
return "ARC"
|
||||
return "ranged"
|
||||
if class_id.contains("strategist") or class_id.contains("advisor") or class_id.contains("hero") or class_id.contains("commander"):
|
||||
return "TAC"
|
||||
return "tactic"
|
||||
if class_id.contains("warrior") or class_id.contains("champion") or class_id.contains("bandit"):
|
||||
return "WAR"
|
||||
return "INF"
|
||||
return "heavy"
|
||||
return "infantry"
|
||||
|
||||
|
||||
func _unit_class_badge_color(unit: Dictionary, team_color: Color) -> Color:
|
||||
var family := _unit_class_family(unit)
|
||||
if family == "cavalry":
|
||||
return Color(0.78, 0.34, 0.16, 1.0)
|
||||
if family == "ranged":
|
||||
return Color(0.16, 0.42, 0.26, 1.0)
|
||||
if family == "tactic":
|
||||
return Color(0.32, 0.26, 0.62, 1.0)
|
||||
if family == "heavy":
|
||||
return Color(0.62, 0.16, 0.12, 1.0)
|
||||
return team_color.darkened(0.10)
|
||||
|
||||
|
||||
func _unit_hp_color(hp_ratio: float) -> Color:
|
||||
|
||||
@@ -15,6 +15,21 @@ const SCENARIO_BACKGROUNDS := [
|
||||
"background_path": "res://art/backgrounds/sishui_gate_pass.png",
|
||||
"label": "002 Sishui Gate background"
|
||||
},
|
||||
{
|
||||
"scenario_path": "res://data/scenarios/003_xingyang_ambush.json",
|
||||
"background_path": "res://art/backgrounds/xingyang_forest_ambush.png",
|
||||
"label": "003 Xingyang forest ambush background"
|
||||
},
|
||||
{
|
||||
"scenario_path": "res://data/scenarios/004_qingzhou_campaign.json",
|
||||
"background_path": "res://art/backgrounds/qingzhou_village_road.png",
|
||||
"label": "004 Qingzhou village road background"
|
||||
},
|
||||
{
|
||||
"scenario_path": "res://data/scenarios/005_puyang_raid.json",
|
||||
"background_path": "res://art/backgrounds/puyang_raid_camp.png",
|
||||
"label": "005 Puyang raid camp background"
|
||||
},
|
||||
{
|
||||
"scenario_path": "res://data/scenarios/008_wan_castle_escape.json",
|
||||
"background_path": "res://art/backgrounds/wan_castle_escape.png",
|
||||
@@ -2464,7 +2479,7 @@ func _check_battle_visual_data(failures: Array[String]) -> void:
|
||||
).is_empty():
|
||||
failures.append("035 old Counterstroke setup flags should not expose doubt rations")
|
||||
|
||||
for item_id in ["bronze_sword", "training_spear", "short_bow", "hand_axe", "iron_armor", "panacea"]:
|
||||
for item_id in ["bronze_sword", "training_spear", "short_bow", "hand_axe", "iron_armor", "war_drum", "imperial_seal", "panacea"]:
|
||||
var item := state.get_item_def(item_id)
|
||||
if item.is_empty():
|
||||
failures.append("missing expected item: %s" % item_id)
|
||||
@@ -2625,9 +2640,30 @@ func _check_hud_focus_text(failures: Array[String]) -> void:
|
||||
failures.append("Enemy archer HUD focus should describe enemy control: %s" % archer_text)
|
||||
if not scene._unit_current_terrain_text(archer).contains("평지"):
|
||||
failures.append("Archer terrain text should reflect its current plain tile")
|
||||
_check_unit_class_mark(failures, scene, "cao_cao", "tactic", "策")
|
||||
_check_unit_class_mark(failures, scene, "xiahou_dun", "cavalry", "騎")
|
||||
_check_unit_class_mark(failures, scene, "yellow_turban_2", "infantry", "步")
|
||||
_check_unit_class_mark(failures, scene, "yellow_turban_3", "ranged", "弓")
|
||||
_check_unit_class_mark(failures, scene, "yellow_turban_1", "heavy", "武")
|
||||
scene.free()
|
||||
|
||||
|
||||
func _check_unit_class_mark(failures: Array[String], scene, unit_id: String, expected_family: String, expected_mark: String) -> void:
|
||||
var unit: Dictionary = scene.state.get_unit(unit_id)
|
||||
if unit.is_empty():
|
||||
failures.append("missing unit for class mark check: %s" % unit_id)
|
||||
return
|
||||
var family := str(scene._unit_class_family(unit))
|
||||
var mark := str(scene._unit_class_abbrev(unit))
|
||||
if family != expected_family:
|
||||
failures.append("%s class family should be %s, got %s" % [unit_id, expected_family, family])
|
||||
if mark != expected_mark:
|
||||
failures.append("%s class mark should be %s, got %s" % [unit_id, expected_mark, mark])
|
||||
var color: Color = scene._unit_class_badge_color(unit, Color(0.20, 0.42, 0.82))
|
||||
if color.a <= 0.0:
|
||||
failures.append("%s class badge color should be visible" % unit_id)
|
||||
|
||||
|
||||
func _check_ancient_ui_theme(failures: Array[String]) -> void:
|
||||
var scene = BattleSceneScript.new()
|
||||
scene._create_hud()
|
||||
|
||||
Reference in New Issue
Block a user