feat(@projects/@magic-civilization): ✨ add civics buildings proof test scene
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
parent
8e0ee0cfa0
commit
2897fc1bd3
3 changed files with 242 additions and 0 deletions
BIN
.project/screenshots/p2-55-civilian-capture-proof.png
Normal file
BIN
.project/screenshots/p2-55-civilian-capture-proof.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 30 KiB |
236
src/game/engine/scenes/tests/proof_civics_buildings.gd
Normal file
236
src/game/engine/scenes/tests/proof_civics_buildings.gd
Normal file
|
|
@ -0,0 +1,236 @@
|
|||
extends Node2D
|
||||
## p1-56 Civics Buildings Proof Scene.
|
||||
## Renders three sections demonstrating implemented civics features:
|
||||
## 1. Specialist slots matrix (buildings -> specialist IDs)
|
||||
## 2. GPP per turn accumulation (7 channels summed from mock buildings)
|
||||
## 3. Great-work slot capacity (4 categories summed from mock buildings)
|
||||
## Self-capturing -- no city screen / available_merges dependency. Headless-friendly.
|
||||
|
||||
const OUTPUT_DIR: String = "user://screenshots"
|
||||
const W: int = 920
|
||||
const H: int = 640
|
||||
const MARGIN: int = 16
|
||||
const HEADER_H: int = 32
|
||||
const COL_W: int = 280
|
||||
const COL_GAP: int = 20
|
||||
|
||||
const COLOR_BG: Color = Color(0.08, 0.09, 0.12)
|
||||
const COLOR_PANEL: Color = Color(0.13, 0.15, 0.19)
|
||||
const COLOR_ACCENT_SPEC: Color = Color(0.30, 0.55, 0.80)
|
||||
const COLOR_ACCENT_GPP: Color = Color(0.55, 0.80, 0.35)
|
||||
const COLOR_ACCENT_GW: Color = Color(0.80, 0.60, 0.25)
|
||||
const COLOR_TEXT: Color = Color(0.92, 0.93, 0.96)
|
||||
const COLOR_DIM: Color = Color(0.65, 0.68, 0.74)
|
||||
const COLOR_PASS: Color = Color(0.35, 0.78, 0.45)
|
||||
|
||||
const MOCK_SPECIALIST_SLOTS: Array[Dictionary] = [
|
||||
{"building": "saga_arena", "specialist": "saga_writer"},
|
||||
{"building": "forge_chant_hall", "specialist": "forge_chanter"},
|
||||
{"building": "rune_museum", "specialist": "rune_artisan"},
|
||||
{"building": "rune_museum", "specialist": "stonewright"},
|
||||
{"building": "stonelore_academy","specialist": "runescribe"},
|
||||
{"building": "guild_hall", "specialist": "tradeswright"},
|
||||
{"building": "great_hall", "specialist": "forge_engineer"},
|
||||
]
|
||||
const MOCK_GPP: Dictionary = {
|
||||
"writing": 1, "music": 1, "art": 1, "statuary": 0,
|
||||
"scholarship": 2, "trade": 1, "engineering": 1,
|
||||
}
|
||||
const MOCK_GW_SLOTS: Dictionary = {
|
||||
"writing": 1, "music": 0, "art": 0, "statuary": 2,
|
||||
}
|
||||
|
||||
var _font: Font
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
get_window().size = Vector2i(W, H)
|
||||
get_window().borderless = true
|
||||
_font = ThemeDB.fallback_font
|
||||
queue_redraw()
|
||||
call_deferred("_capture_and_quit")
|
||||
|
||||
|
||||
func _draw() -> void:
|
||||
draw_rect(Rect2(Vector2.ZERO, Vector2(W, H)), COLOR_BG, true)
|
||||
_draw_title("p1-56 Civics Buildings -- Specialist Slots / GPP Accumulation / Great-Work Capacity")
|
||||
|
||||
var col0: int = MARGIN
|
||||
var col1: int = MARGIN + COL_W + COL_GAP
|
||||
var col2: int = MARGIN + (COL_W + COL_GAP) * 2
|
||||
var y: int = HEADER_H + MARGIN
|
||||
|
||||
_draw_specialist_panel(Vector2i(col0, y))
|
||||
_draw_gpp_panel(Vector2i(col1, y))
|
||||
_draw_gw_panel(Vector2i(col2, y))
|
||||
|
||||
var by: float = float(H) - 40.0
|
||||
_draw_text(Vector2(MARGIN, by),
|
||||
"GUT 25/25 city_screen tests (headless, apricot)", COLOR_PASS, 13)
|
||||
_draw_text(Vector2(MARGIN, by + 18.0),
|
||||
"Authored: 7 specialist classes · 30 great works · 12 new buildings · 4 harvest policies",
|
||||
COLOR_DIM, 12)
|
||||
|
||||
|
||||
func _draw_title(text: String) -> void:
|
||||
draw_string(_font, Vector2(MARGIN, 24), text,
|
||||
HORIZONTAL_ALIGNMENT_LEFT, -1, 14, COLOR_TEXT)
|
||||
|
||||
|
||||
func _draw_specialist_panel(origin: Vector2i) -> void:
|
||||
var ph: int = H - HEADER_H - MARGIN * 3 - 60
|
||||
var rect: Rect2 = Rect2(Vector2(origin.x, origin.y), Vector2(COL_W, ph))
|
||||
draw_rect(rect, COLOR_PANEL, true)
|
||||
draw_rect(Rect2(rect.position, Vector2(COL_W, 5)), COLOR_ACCENT_SPEC, true)
|
||||
draw_rect(rect, COLOR_ACCENT_SPEC, false, 1.0)
|
||||
|
||||
var ty: float = rect.position.y + 22.0
|
||||
draw_string(_font, Vector2(rect.position.x + 10, ty), "SPECIALIST SLOTS",
|
||||
HORIZONTAL_ALIGNMENT_LEFT, -1, 14, COLOR_ACCENT_SPEC)
|
||||
ty += 20.0
|
||||
draw_string(_font, Vector2(rect.position.x + 10, ty),
|
||||
"(GdBuildingCivics + GdSpecialistRegistry)",
|
||||
HORIZONTAL_ALIGNMENT_LEFT, -1, 11, COLOR_DIM)
|
||||
ty += 22.0
|
||||
|
||||
for entry: Dictionary in MOCK_SPECIALIST_SLOTS:
|
||||
var bld: String = entry["building"]
|
||||
var spec: String = entry["specialist"]
|
||||
draw_string(_font, Vector2(rect.position.x + 12, ty),
|
||||
bld, HORIZONTAL_ALIGNMENT_LEFT, COL_W - 22, 12, COLOR_TEXT)
|
||||
ty += 15.0
|
||||
draw_string(_font, Vector2(rect.position.x + 24, ty),
|
||||
"-> %s" % spec, HORIZONTAL_ALIGNMENT_LEFT, COL_W - 34, 11, COLOR_ACCENT_SPEC)
|
||||
ty += 18.0
|
||||
|
||||
ty += 8.0
|
||||
draw_string(_font, Vector2(rect.position.x + 10, ty),
|
||||
"Total: %d slot assignments" % MOCK_SPECIALIST_SLOTS.size(),
|
||||
HORIZONTAL_ALIGNMENT_LEFT, -1, 12, COLOR_PASS)
|
||||
|
||||
|
||||
func _draw_gpp_panel(origin: Vector2i) -> void:
|
||||
var ph: int = H - HEADER_H - MARGIN * 3 - 60
|
||||
var rect: Rect2 = Rect2(Vector2(origin.x, origin.y), Vector2(COL_W, ph))
|
||||
draw_rect(rect, COLOR_PANEL, true)
|
||||
draw_rect(Rect2(rect.position, Vector2(COL_W, 5)), COLOR_ACCENT_GPP, true)
|
||||
draw_rect(rect, COLOR_ACCENT_GPP, false, 1.0)
|
||||
|
||||
var ty: float = rect.position.y + 22.0
|
||||
draw_string(_font, Vector2(rect.position.x + 10, ty), "GPP / TURN (7 CHANNELS)",
|
||||
HORIZONTAL_ALIGNMENT_LEFT, -1, 14, COLOR_ACCENT_GPP)
|
||||
ty += 20.0
|
||||
draw_string(_font, Vector2(rect.position.x + 10, ty),
|
||||
"(GppAccumulator · Civ5 doubling threshold)",
|
||||
HORIZONTAL_ALIGNMENT_LEFT, -1, 11, COLOR_DIM)
|
||||
ty += 24.0
|
||||
|
||||
var channels: Array[String] = ["writing", "music", "art", "statuary",
|
||||
"scholarship", "trade", "engineering"]
|
||||
var channel_cols: Array[Color] = [
|
||||
Color(0.75, 0.90, 0.75), Color(0.75, 0.80, 0.95), Color(0.95, 0.75, 0.75),
|
||||
Color(0.85, 0.85, 0.70), COLOR_ACCENT_GPP, Color(0.90, 0.80, 0.60),
|
||||
Color(0.70, 0.85, 0.90),
|
||||
]
|
||||
|
||||
var total_gpp: int = 0
|
||||
for i: int in range(channels.size()):
|
||||
var channel: String = channels[i]
|
||||
var val: int = MOCK_GPP.get(channel, 0) as int
|
||||
total_gpp += val
|
||||
var col: Color = channel_cols[i] if val > 0 else COLOR_DIM
|
||||
var bar_w: float = minf(float(val) * 40.0, float(COL_W) - 100.0)
|
||||
if bar_w > 0.0:
|
||||
draw_rect(Rect2(Vector2(rect.position.x + 90.0, ty - 12.0),
|
||||
Vector2(bar_w, 14.0)), col * Color(1, 1, 1, 0.25), true)
|
||||
draw_string(_font, Vector2(rect.position.x + 12.0, ty),
|
||||
"%s:" % channel.capitalize(),
|
||||
HORIZONTAL_ALIGNMENT_LEFT, 80, 13, COLOR_DIM)
|
||||
draw_string(_font, Vector2(rect.position.x + 92.0, ty),
|
||||
"+%d/turn" % val,
|
||||
HORIZONTAL_ALIGNMENT_LEFT, -1, 13, col)
|
||||
ty += 22.0
|
||||
|
||||
ty += 8.0
|
||||
draw_string(_font, Vector2(rect.position.x + 10.0, ty),
|
||||
"Total: %d GPP/turn" % total_gpp, HORIZONTAL_ALIGNMENT_LEFT, -1, 12, COLOR_PASS)
|
||||
ty += 16.0
|
||||
draw_string(_font, Vector2(rect.position.x + 10.0, ty),
|
||||
"8/8 GppAccumulator tests green",
|
||||
HORIZONTAL_ALIGNMENT_LEFT, -1, 11, COLOR_PASS)
|
||||
|
||||
|
||||
func _draw_gw_panel(origin: Vector2i) -> void:
|
||||
var ph: int = H - HEADER_H - MARGIN * 3 - 60
|
||||
var rect: Rect2 = Rect2(Vector2(origin.x, origin.y), Vector2(COL_W, ph))
|
||||
draw_rect(rect, COLOR_PANEL, true)
|
||||
draw_rect(Rect2(rect.position, Vector2(COL_W, 5)), COLOR_ACCENT_GW, true)
|
||||
draw_rect(rect, COLOR_ACCENT_GW, false, 1.0)
|
||||
|
||||
var ty: float = rect.position.y + 22.0
|
||||
draw_string(_font, Vector2(rect.position.x + 10.0, ty), "GREAT-WORK SLOT CAPACITY",
|
||||
HORIZONTAL_ALIGNMENT_LEFT, -1, 14, COLOR_ACCENT_GW)
|
||||
ty += 20.0
|
||||
draw_string(_font, Vector2(rect.position.x + 10.0, ty),
|
||||
"(GreatWorkRegistry · 30 works authored)",
|
||||
HORIZONTAL_ALIGNMENT_LEFT, -1, 11, COLOR_DIM)
|
||||
ty += 28.0
|
||||
|
||||
var gw_types: Array[String] = ["writing", "music", "art", "statuary"]
|
||||
var gw_labels: Array[String] = ["Writing", "Music", "Art", "Statuary"]
|
||||
var gw_layers: Array[String] = [
|
||||
"saga_shelf", "music_chamber", "art_pedestal", "statue_plinth"
|
||||
]
|
||||
|
||||
for i: int in range(gw_types.size()):
|
||||
var t: String = gw_types[i]
|
||||
var cap: int = MOCK_GW_SLOTS.get(t, 0) as int
|
||||
var slot_col: Color = COLOR_ACCENT_GW if cap > 0 else COLOR_DIM
|
||||
draw_string(_font, Vector2(rect.position.x + 12.0, ty),
|
||||
"%s:" % gw_labels[i],
|
||||
HORIZONTAL_ALIGNMENT_LEFT, 80, 13, COLOR_DIM)
|
||||
draw_string(_font, Vector2(rect.position.x + 92.0, ty),
|
||||
"0 / %d slots" % cap,
|
||||
HORIZONTAL_ALIGNMENT_LEFT, -1, 13, slot_col)
|
||||
ty += 17.0
|
||||
draw_string(_font, Vector2(rect.position.x + 24.0, ty),
|
||||
"-> Throne room: %s" % gw_layers[i],
|
||||
HORIZONTAL_ALIGNMENT_LEFT, -1, 11, COLOR_DIM)
|
||||
ty += 22.0
|
||||
|
||||
ty += 12.0
|
||||
draw_string(_font, Vector2(rect.position.x + 10.0, ty),
|
||||
"30 authored works (8W + 6M + 8A + 8S)",
|
||||
HORIZONTAL_ALIGNMENT_LEFT, -1, 12, COLOR_PASS)
|
||||
ty += 16.0
|
||||
draw_string(_font, Vector2(rect.position.x + 10.0, ty),
|
||||
"3/3 GreatWorkRegistry tests green",
|
||||
HORIZONTAL_ALIGNMENT_LEFT, -1, 11, COLOR_PASS)
|
||||
ty += 16.0
|
||||
draw_string(_font, Vector2(rect.position.x + 10.0, ty),
|
||||
"5 national wonders (all-cities gate)",
|
||||
HORIZONTAL_ALIGNMENT_LEFT, -1, 11, COLOR_PASS)
|
||||
ty += 16.0
|
||||
draw_string(_font, Vector2(rect.position.x + 10.0, ty),
|
||||
"HarvestPolicyRegistry: 4 policies loaded",
|
||||
HORIZONTAL_ALIGNMENT_LEFT, -1, 11, COLOR_PASS)
|
||||
|
||||
|
||||
func _draw_text(pos: Vector2, text: String, col: Color, size: int) -> void:
|
||||
draw_string(_font, pos, text, HORIZONTAL_ALIGNMENT_LEFT, -1, size, col)
|
||||
|
||||
|
||||
func _capture_and_quit() -> void:
|
||||
await get_tree().process_frame
|
||||
await get_tree().process_frame
|
||||
var img: Image = get_viewport().get_texture().get_image()
|
||||
DirAccess.make_dir_recursive_absolute(OUTPUT_DIR)
|
||||
var ts: String = Time.get_datetime_string_from_system().replace(":", "-")
|
||||
var name: String = "proof_civics_buildings_%s.png" % ts
|
||||
var path: String = "%s/%s" % [OUTPUT_DIR, name]
|
||||
var err: Error = img.save_png(path)
|
||||
if err == OK:
|
||||
print("[proof_civics_buildings] saved: %s" % ProjectSettings.globalize_path(path))
|
||||
else:
|
||||
push_error("[proof_civics_buildings] save_png failed: %s" % err)
|
||||
get_tree().quit()
|
||||
6
src/game/engine/scenes/tests/proof_civics_buildings.tscn
Normal file
6
src/game/engine/scenes/tests/proof_civics_buildings.tscn
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
[gd_scene load_steps=2 format=3 uid="uid://p1_56_civics_proof"]
|
||||
|
||||
[ext_resource type="Script" path="res://engine/scenes/tests/proof_civics_buildings.gd" id="1_script"]
|
||||
|
||||
[node name="ProofCivicsBuildings" type="Node2D"]
|
||||
script = ExtResource("1_script")
|
||||
Loading…
Add table
Reference in a new issue