fix(hell_tower): calibrate menu to 6 floors, fix UI text overflow, and remove casino prefix
- Align tower progression and cursor coordinates strictly to the 6 floors: Coin, Dice, Cards, Russian Roulette, Roulette, Buckshot - Recalibrate tower cursor Y positions for each tier (205, 174, 143, 112, 81, 50) - Reformat UI text, labels, and action buttons to strictly fit within card and sub-card boundaries without clipping - Remove redundant 'КАЗИНО 3D' prefix from header banner, keeping bold centered 'АДСКАЯ БАШНЯ' - Rebuild shipping binaries and verify complete 6-floor test suite
This commit is contained in:
parent
eef2039c7e
commit
3c8465bdad
8 changed files with 791 additions and 768 deletions
Binary file not shown.
|
|
@ -1935,7 +1935,7 @@ stage_test_loop:
|
||||||
invoke TowerReportRoundOutcome, 1
|
invoke TowerReportRoundOutcome, 1
|
||||||
|
|
||||||
; 4. Check outcome state
|
; 4. Check outcome state
|
||||||
cmp stageLoop, 10
|
cmp stageLoop, 6
|
||||||
jae stage_check_champ
|
jae stage_check_champ
|
||||||
|
|
||||||
cmp towerFloorState, TOWER_STATE_CLEAR
|
cmp towerFloorState, TOWER_STATE_CLEAR
|
||||||
|
|
|
||||||
BIN
poker.exe
BIN
poker.exe
Binary file not shown.
BIN
poker.obj
BIN
poker.obj
Binary file not shown.
File diff suppressed because it is too large
Load diff
|
|
@ -1,94 +1,84 @@
|
||||||
; --- hell_tower_data.inc: Data for Hell Tower 3D ---
|
; --- hell_tower_data.inc: Data for Hell Tower 3D (6 Floors) ---
|
||||||
MODE_HELL_TOWER equ 23
|
MODE_HELL_TOWER equ 23
|
||||||
TOWER_STATE_BRIEFING equ 0
|
TOWER_STATE_BRIEFING equ 0
|
||||||
TOWER_STATE_IN_GAME equ 1
|
TOWER_STATE_IN_GAME equ 1
|
||||||
TOWER_STATE_CLEAR equ 2
|
TOWER_STATE_CLEAR equ 2
|
||||||
TOWER_STATE_DEFEAT equ 3
|
TOWER_STATE_DEFEAT equ 3
|
||||||
TOWER_STATE_CHAMPION equ 4
|
TOWER_STATE_CHAMPION equ 4
|
||||||
|
|
||||||
InitHellTower3D PROTO
|
InitHellTower3D PROTO
|
||||||
TowerExitToHall PROTO
|
TowerExitToHall PROTO
|
||||||
TowerReportRoundOutcome PROTO :DWORD
|
TowerReportRoundOutcome PROTO :DWORD
|
||||||
RenderTowerInGameBadge PROTO
|
RenderTowerInGameBadge PROTO
|
||||||
ResolveHellAssetPath PROTO :DWORD, :DWORD
|
ResolveHellAssetPath PROTO :DWORD, :DWORD
|
||||||
FreeTowerMinigameAssets PROTO
|
FreeTowerMinigameAssets PROTO
|
||||||
|
|
||||||
.data
|
.data
|
||||||
towerStage dd 1
|
towerStage dd 1
|
||||||
towerFloorState dd 0
|
towerFloorState dd 0
|
||||||
towerAnimClock dd 0
|
towerAnimClock dd 0
|
||||||
towerCurrentGame dd 0
|
towerCurrentGame dd 0
|
||||||
towerPrizeAmount dd 66600
|
towerPrizeAmount dd 66600
|
||||||
towerHudText db 91,32,0
|
towerHudText db 91,32,0
|
||||||
|
|
||||||
hellTowerMenuArt3D AnimPack3D <0>
|
hellTowerMenuArt3D AnimPack3D <0>
|
||||||
hellTowerMenuPath3D db "assets\animations\hall\helltower-menu.bin",0
|
hellTowerMenuPath3D db "assets\animations\hall\helltower-menu.bin",0
|
||||||
|
|
||||||
towerFloorY dd 205, 186, 167, 148, 129, 110, 91, 72, 53, 34
|
; 6 floors: 1=205, 2=174, 3=143, 4=112, 5=81, 6=50
|
||||||
towerCursorY dd 205
|
towerFloorY dd 205, 174, 143, 112, 81, 50
|
||||||
towerCursorTargetY dd 205
|
towerCursorY dd 205
|
||||||
towerCalloutAnim dd 0
|
towerCursorTargetY dd 205
|
||||||
|
towerCalloutAnim dd 0
|
||||||
towerPrizePrompt db 202,211,216,58,32,36,0 ; "КУШ: $"
|
|
||||||
|
towerPrizePrompt db 202,211,216,58,32,36,0
|
||||||
towerFloorModes dd MODE_COIN, MODE_DICE, MODE_SKULLS, MODE_BLACKJACK, MODE_POKER, MODE_RUSSIAN, MODE_ROULETTE, MODE_DURAK, MODE_SKILL, MODE_BUCKSHOT
|
|
||||||
|
towerFloorModes dd MODE_COIN, MODE_DICE, MODE_BLACKJACK, MODE_RUSSIAN, MODE_ROULETTE, MODE_BUCKSHOT
|
||||||
towerBoss1 db 193,197,209,32,192,199,192,208,210,192,0
|
|
||||||
towerBoss2 db 196,197,204,206,205,32,202,206,209,210,197,201,0
|
towerBoss1 db 193,229,241,32,192,231,224,240,242,224,0
|
||||||
towerBoss3 db 215,197,208,205,206,202,205,200,198,205,200,202,0
|
towerBoss2 db 196,229,236,238,237,32,202,238,241,242,229,233,0
|
||||||
towerBoss4 db 202,208,211,207,220,197,32,207,208,197,200,209,207,206,196,205,197,201,0
|
towerBoss3 db 202,240,243,239,252,229,32,210,252,236,251,0
|
||||||
towerBoss5 db 196,197,204,206,205,32,193,203,197,212,192,0
|
towerBoss4 db 209,243,228,252,255,32,192,228,224,0
|
||||||
towerBoss6 db 206,193,208,197,215,197,205,205,219,201,32,195,208,197,216,205,200,202,0
|
towerBoss5 db 213,238,231,255,232,237,32,208,243,235,229,242,234,232,0
|
||||||
towerBoss7 db 202,206,203,197,209,206,32,209,211,196,220,193,219,0
|
towerBoss6 db 194,235,224,228,251,234,224,32,193,224,248,237,232,0
|
||||||
towerBoss8 db 202,192,208,210,206,215,205,219,201,32,215,197,208,210,0
|
|
||||||
towerBoss9 db 207,192,203,192,215,32,202,208,222,202,192,0
|
towerBossNames dd OFFSET towerBoss1, OFFSET towerBoss2, OFFSET towerBoss3, OFFSET towerBoss4, OFFSET towerBoss5, OFFSET towerBoss6
|
||||||
towerBoss10 db 194,203,192,196,219,202,192,32,193,192,216,205,200,0
|
|
||||||
|
towerGame1 db 206,240,229,235,32,232,32,240,229,248,234,224,0
|
||||||
towerBossNames dd OFFSET towerBoss1, OFFSET towerBoss2, OFFSET towerBoss3, OFFSET towerBoss4, OFFSET towerBoss5, OFFSET towerBoss6, OFFSET towerBoss7, OFFSET towerBoss8, OFFSET towerBoss9, OFFSET towerBoss10
|
towerGame2 db 202,238,241,242,232,0
|
||||||
|
towerGame3 db 50,49,32,47,32,206,247,234,238,0
|
||||||
towerGame1 db 206,240,229,235,32,232,32,240,229,248,234,224,0
|
towerGame4 db 208,243,241,241,234,224,255,32,240,243,235,229,242,234,224,0
|
||||||
towerGame2 db 202,238,241,242,232,0
|
towerGame5 db 202,224,231,232,237,238,45,240,243,235,229,242,234,224,0
|
||||||
towerGame3 db 215,229,240,229,239,224,32,232,32,248,224,240,232,234,0
|
towerGame6 db 66,117,99,107,115,104,111,116,32,82,111,117,108,101,116,116,101,0
|
||||||
towerGame4 db 50,49,32,47,32,206,247,234,238,0
|
|
||||||
towerGame5 db 207,238,234,229,240,0
|
towerGameNames dd OFFSET towerGame1, OFFSET towerGame2, OFFSET towerGame3, OFFSET towerGame4, OFFSET towerGame5, OFFSET towerGame6
|
||||||
towerGame6 db 208,243,241,241,234,224,255,32,240,243,235,229,242,234,224,0
|
|
||||||
towerGame7 db 202,224,231,232,237,238,45,240,243,235,229,242,234,224,0
|
towerDesc1 db 211,227,224,228,224,233,32,241,242,238,240,238,237,243,32,236,238,237,229,242,251,46,0
|
||||||
towerGame8 db 196,243,240,224,234,0
|
towerDesc2 db 205,224,225,229,240,232,32,225,238,235,252,248,229,32,238,247,234,238,226,46,0
|
||||||
towerGame9 db 202,240,254,234,58,32,83,107,105,108,108,32,67,104,101,99,107,0
|
towerDesc3 db 206,225,251,227,240,224,233,32,234,240,243,239,252,229,32,226,32,50,49,46,0
|
||||||
towerGame10 db 66,117,99,107,115,104,111,116,32,82,111,117,108,101,116,116,101,0
|
towerDesc4 db 49,32,239,224,242,240,238,237,46,32,194,251,230,232,226,232,33,0
|
||||||
|
towerDesc5 db 211,227,224,228,224,233,32,247,232,241,235,238,32,240,243,235,229,242,234,232,46,0
|
||||||
towerGameNames dd OFFSET towerGame1, OFFSET towerGame2, OFFSET towerGame3, OFFSET towerGame4, OFFSET towerGame5, OFFSET towerGame6, OFFSET towerGame7, OFFSET towerGame8, OFFSET towerGame9, OFFSET towerGame10
|
towerDesc6 db 196,243,253,235,252,32,237,224,32,228,240,238,225,238,226,232,234,229,33,0
|
||||||
|
|
||||||
towerDesc1 db 211,227,224,228,224,233,32,241,242,238,240,238,237,243,32,236,238,237,229,242,251,46,0
|
towerDescriptions dd OFFSET towerDesc1, OFFSET towerDesc2, OFFSET towerDesc3, OFFSET towerDesc4, OFFSET towerDesc5, OFFSET towerDesc6
|
||||||
towerDesc2 db 207,229,240,229,225,240,238,241,252,32,228,229,236,238,237,224,32,226,32,241,243,236,236,229,32,234,238,241,242,229,233,46,0
|
|
||||||
towerDesc3 db 205,224,233,228,232,32,228,243,248,243,32,239,238,228,32,247,229,240,229,239,238,236,46,0
|
towerHeader db 192,196,209,202,192,223,32,193,192,216,205,223,0
|
||||||
towerDesc4 db 209,238,225,229,240,232,32,50,49,32,238,247,234,238,32,232,32,239,238,225,229,228,232,32,234,240,243,239,252,229,46,0
|
towerFloorPrefix db 221,210,192,198,32,0
|
||||||
towerDesc5 db 194,241,234,240,238,233,32,234,224,240,242,251,32,232,32,239,238,225,229,228,232,32,226,32,239,238,234,229,240,46,0
|
towerOfTen db 32,47,32,54,0
|
||||||
towerDesc6 db 49,32,239,224,242,240,238,237,32,226,32,225,224,240,224,225,224,237,229,58,32,226,251,230,232,226,232,46,0
|
towerEnemyLabel db 194,208,192,195,58,32,0
|
||||||
towerDesc7 db 209,228,229,235,224,233,32,241,242,224,226,234,243,32,237,224,32,240,243,235,229,242,234,229,46,0
|
towerGameLabel db 200,195,208,192,58,32,0
|
||||||
towerDesc8 db 206,241,242,224,226,252,32,247,184,240,242,224,32,226,32,228,243,240,224,234,224,245,46,0
|
towerRuleText db 54,32,253,242,224,230,229,233,32,225,229,231,32,239,238,240,224,230,229,237,232,233,0
|
||||||
towerDesc9 db 207,238,239,224,228,232,32,226,32,231,238,237,243,32,232,32,241,238,240,226,232,241,252,32,241,32,234,240,254,234,224,46,0
|
towerLossWarning db 207,238,240,224,230,229,237,232,229,32,45,32,226,238,231,226,240,224,242,33,0
|
||||||
towerDesc10 db 196,243,253,235,252,32,237,224,32,228,240,238,225,238,226,232,234,224,245,32,231,224,32,230,232,231,237,252,33,0
|
towerStartBtn db 91,69,78,84,69,82,93,32,193,206,201,0
|
||||||
|
towerEscBtn db 91,69,83,67,93,32,205,192,199,192,196,0
|
||||||
towerDescriptions dd OFFSET towerDesc1, OFFSET towerDesc2, OFFSET towerDesc3, OFFSET towerDesc4, OFFSET towerDesc5, OFFSET towerDesc6, OFFSET towerDesc7, OFFSET towerDesc8, OFFSET towerDesc9, OFFSET towerDesc10
|
towerClearTitle db 221,210,192,198,32,199,192,215,200,217,197,205,33,0
|
||||||
|
towerClearDesc db 194,240,224,227,32,239,238,226,229,240,230,229,237,33,0
|
||||||
towerHeader db 202,192,199,200,205,206,32,51,68,32,45,32,192,196,209,202,192,223,32,193,192,216,205,223,0
|
towerNextBtn db 91,69,78,84,69,82,93,32,196,192,203,220,216,197,0
|
||||||
towerFloorPrefix db 221,210,192,198,32,0
|
towerDefeatTitle db 194,219,32,207,206,195,200,193,203,200,32,194,32,193,192,216,205,197,33,0
|
||||||
towerOfTen db 32,47,32,49,48,0
|
towerDefeatDesc db 196,243,248,224,32,241,227,238,240,229,235,224,32,226,32,192,228,243,46,0
|
||||||
towerEnemyLabel db 194,208,192,195,58,32,0
|
towerReturnBtn db 91,69,83,67,93,32,194,32,213,206,203,203,32,202,192,199,200,205,206,0
|
||||||
towerGameLabel db 200,195,208,192,58,32,0
|
towerChampTitle db 193,192,216,205,223,32,207,206,202,206,208,197,205,192,33,0
|
||||||
towerRuleText db 49,48,32,225,232,242,226,32,239,238,228,240,255,228,32,225,229,231,32,239,240,224,226,224,32,237,224,32,238,248,232,225,234,243,0
|
towerChampSubtitle db 194,251,32,45,32,194,235,224,228,251,234,224,32,193,224,248,237,232,33,0
|
||||||
towerLossWarning db 207,238,240,224,230,229,237,232,229,32,45,32,226,238,231,226,240,224,242,32,226,32,245,238,235,235,32,234,224,231,232,237,238,0
|
towerPrizeText db 202,211,216,58,32,43,36,54,54,44,54,48,48,32,194,32,193,192,205,202,33,0
|
||||||
towerStartBtn db 91,207,208,206,193,197,203,93,32,194,32,193,206,201,0
|
towerHudBadge db 193,192,216,205,223,58,32,0
|
||||||
towerEscBtn db 91,69,83,67,93,32,209,193,197,198,192,210,220,0
|
towerHudOfTen db 47,54,0
|
||||||
towerClearTitle db 221,210,192,198,32,199,192,215,200,217,197,205,33,32,194,208,192,195,32,207,206,194,197,208,198,197,205,33,0
|
|
||||||
towerClearDesc db 194,240,224,227,32,239,238,226,229,240,230,229,237,33,32,194,239,229,240,229,228,232,32,237,238,226,251,233,32,253,242,224,230,46,0
|
|
||||||
towerNextBtn db 91,207,208,206,193,197,203,93,32,196,192,203,220,216,197,0
|
|
||||||
towerDefeatTitle db 194,219,32,207,192,203,200,32,194,32,192,196,209,202,206,201,32,193,192,216,205,197,46,46,46,0
|
|
||||||
towerDefeatDesc db 194,224,248,224,32,228,243,248,224,32,237,224,226,229,234,232,32,241,227,238,240,229,235,224,32,226,32,192,228,243,46,0
|
|
||||||
towerReturnBtn db 91,207,208,206,193,197,203,32,47,32,69,83,67,93,32,194,32,213,206,203,203,32,202,192,199,200,205,206,0
|
|
||||||
towerChampTitle db 210,208,200,211,204,212,33,32,192,196,209,202,192,223,32,193,192,216,205,223,32,207,206,202,206,208,197,205,192,33,0
|
|
||||||
towerChampSubtitle db 194,219,32,45,32,215,197,204,207,200,206,205,32,192,196,209,202,206,201,32,193,192,216,205,200,33,0
|
|
||||||
towerPrizeText db 209,211,207,197,208,207,208,200,199,58,32,43,36,54,54,44,54,48,48,32,194,32,193,192,205,202,208,206,203,203,33,0
|
|
||||||
towerHudBadge db 193,192,216,205,223,58,32,0
|
|
||||||
towerHudOfTen db 47,49,48,0
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
"""Render full simulation of Hell Tower menu at floors 1, 5, 10."""
|
"""Render simulation of Hell Tower with 6 floors and strict boundary checks."""
|
||||||
import struct
|
import struct
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from PIL import Image, ImageDraw, ImageFont
|
from PIL import Image, ImageDraw, ImageFont
|
||||||
|
|
@ -7,109 +7,167 @@ ROOT = Path(__file__).resolve().parents[2]
|
||||||
MENU_BIN = ROOT / "assets/animations/hall/helltower-menu.bin"
|
MENU_BIN = ROOT / "assets/animations/hall/helltower-menu.bin"
|
||||||
ART_DIR = Path(r"C:\Users\IKER\.gemini\antigravity-cli\brain\c2d69e9d-8822-4f06-923a-36a9194468d6")
|
ART_DIR = Path(r"C:\Users\IKER\.gemini\antigravity-cli\brain\c2d69e9d-8822-4f06-923a-36a9194468d6")
|
||||||
|
|
||||||
FLOOR_Y = [205, 186, 167, 148, 129, 110, 91, 72, 53, 34]
|
# 6 Floors Y in logical 320x240 coordinates
|
||||||
|
FLOOR_Y = [205, 174, 143, 112, 81, 50]
|
||||||
|
|
||||||
BOSSES = [
|
BOSSES = [
|
||||||
"БЕС АЗАРТА", "ДЕМОН КОСТЕЙ", "ЧЕРНОКНИЖНИК", "КРУПЬЕ ПРЕИСПОДНЕЙ", "ДЕМОН БЛЕФА",
|
"Бес Азарта",
|
||||||
"ОБРЕЧЕННЫЙ ГРЕШНИК", "КОЛЕСО СУДЬБЫ", "КАРТОЧНЫЙ ЧЕРТ", "ПАЛАЧ КРЮКА", "ВЛАДЫКА БАШНИ"
|
"Демон Костей",
|
||||||
|
"Крупье Тьмы",
|
||||||
|
"Судья Ада",
|
||||||
|
"Хозяин Рулетки",
|
||||||
|
"Владыка Башни"
|
||||||
]
|
]
|
||||||
|
|
||||||
GAMES = [
|
GAMES = [
|
||||||
"Орел и решка", "Кости", "Черепа и шарик", "21 / Очко", "Покер",
|
"Орел и решка",
|
||||||
"Русская рулетка", "Казино-рулетка", "Дурак", "Крюк: Skill Check", "Buckshot Roulette"
|
"Кости",
|
||||||
|
"21 / Очко",
|
||||||
|
"Русская рулетка",
|
||||||
|
"Казино-рулетка",
|
||||||
|
"Buckshot Roulette"
|
||||||
]
|
]
|
||||||
|
|
||||||
DESCS = [
|
DESCS = [
|
||||||
"Угадай сторону монеты.",
|
"Угадай сторону монеты.",
|
||||||
"Перебрось демона в сумме костей.",
|
"Набери больше очков.",
|
||||||
"Найди душу под черепом.",
|
"Обыграй крупье в 21.",
|
||||||
"Собери 21 очко и победи крупье.",
|
"1 патрон. Выживи!",
|
||||||
"Вскрой карты и победи в покер.",
|
"Угадай число рулетки.",
|
||||||
"1 патрон в барабане: выживи.",
|
"Дуэль на дробовике!"
|
||||||
"Сделай ставку на рулетке.",
|
|
||||||
"Оставь чёрта в дураках.",
|
|
||||||
"Попади в зону и сорвись с крюка.",
|
|
||||||
"Дуэль на дробовиках за жизнь!"
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
SUB_NOTES = [
|
||||||
|
"Один бросок решит все.",
|
||||||
|
"Бросай кости против беса.",
|
||||||
|
"Собери больше, но не перебор.",
|
||||||
|
"Крути барабан револьвера.",
|
||||||
|
"Ставь на черное или красное.",
|
||||||
|
"Заряжай картечь и стреляй!"
|
||||||
|
]
|
||||||
|
|
||||||
def render_menu_frame(stage: int, callout_anim: int = 100):
|
def render_menu_frame(stage: int, state: int = 0, callout_anim: int = 100):
|
||||||
# 1. Load background from ANM1 pack
|
# 1. Load background
|
||||||
data = MENU_BIN.read_bytes()
|
data = MENU_BIN.read_bytes()
|
||||||
magic, w, h, frames, b_len = struct.unpack("<4sIIII", data[:20])
|
magic, w, h, frames, b_len = struct.unpack("<4sIIII", data[:20])
|
||||||
raw_bgra = data[20:20 + b_len]
|
raw_bgra = data[20:20 + b_len]
|
||||||
bg = Image.frombytes("RGBA", (w, h), raw_bgra, "raw", "BGRA")
|
bg = Image.frombytes("RGBA", (w, h), raw_bgra, "raw", "BGRA")
|
||||||
|
|
||||||
draw = ImageDraw.Draw(bg)
|
# Scale down to 320x240 logical to replicate exact ASM blit logic
|
||||||
|
canvas = bg.resize((320, 240), Image.Resampling.LANCZOS)
|
||||||
floor_idx = stage - 1
|
draw = ImageDraw.Draw(canvas)
|
||||||
|
|
||||||
|
floor_idx = max(0, min(5, stage - 1))
|
||||||
target_y = FLOOR_Y[floor_idx]
|
target_y = FLOOR_Y[floor_idx]
|
||||||
|
|
||||||
# Calculate sliding card box
|
# Sliding card dimensions
|
||||||
card_h = 208
|
card_h = 208
|
||||||
card_y = 20
|
card_y = 16
|
||||||
card_w = max(10, 206 * callout_anim // 100)
|
card_w = max(10, 206 * callout_anim // 100)
|
||||||
card_x = 214 - card_w
|
card_x = 214 - card_w
|
||||||
|
|
||||||
# Connector line
|
# 1. Indicator line and cursor on tower
|
||||||
draw.line([(214, target_y), (224, target_y)], fill=(255, 68, 68), width=2)
|
draw.line([(214, target_y), (224, target_y)], fill=(255, 68, 68), width=2)
|
||||||
# Cursor chevron/diamond
|
|
||||||
draw.rectangle([224, target_y - 3, 230, target_y + 3], fill=(255, 51, 0), outline=(255, 221, 68))
|
draw.rectangle([224, target_y - 3, 230, target_y + 3], fill=(255, 51, 0), outline=(255, 221, 68))
|
||||||
# Pulsing flame pip
|
|
||||||
draw.rectangle([234, target_y - 2, 238, target_y + 2], fill=(255, 170, 34))
|
draw.rectangle([234, target_y - 2, 238, target_y + 2], fill=(255, 170, 34))
|
||||||
|
|
||||||
# Outer and inner border of card
|
# 2. Card outer/inner borders
|
||||||
draw.rectangle([card_x, card_y, card_x + card_w, card_y + card_h], outline=(204, 34, 34), width=2)
|
draw.rectangle([card_x, card_y, card_x + card_w, card_y + card_h], outline=(204, 34, 34), width=2)
|
||||||
draw.rectangle([card_x + 2, card_y + 2, card_x + card_w - 2, card_y + card_h - 2], outline=(85, 17, 17), width=1)
|
draw.rectangle([card_x + 2, card_y + 2, card_x + card_w - 2, card_y + card_h - 2], outline=(85, 17, 17), width=1)
|
||||||
|
|
||||||
|
inner_w = card_w - 12
|
||||||
|
inner_x = card_x + 6
|
||||||
|
|
||||||
if card_w >= 120:
|
if card_w >= 120:
|
||||||
# Header banner
|
# Header banner: "АДСКАЯ БАШНЯ" (Centered, NO "КАЗИНО 3D")
|
||||||
draw.rectangle([card_x + 6, 26, card_x + card_w - 6, 44], fill=(34, 4, 4), outline=(255, 68, 68))
|
hdr_w = len("АДСКАЯ БАШНЯ") * 8
|
||||||
draw.text((card_x + 12, 29), "КАЗИНО 3D - АДСКАЯ БАШНЯ", fill=(255, 221, 102))
|
hdr_x = inner_x + (inner_w - hdr_w) // 2
|
||||||
|
draw.rectangle([inner_x, 22, inner_x + inner_w, 40], fill=(34, 4, 4), outline=(255, 68, 68))
|
||||||
|
draw.text((hdr_x, 26), "АДСКАЯ БАШНЯ", fill=(255, 221, 102))
|
||||||
|
|
||||||
|
# Floor & Bankroll / Prize indicator
|
||||||
|
draw.text((card_x + 12, 46), f"ЭТАЖ {stage} / 6", fill=(255, 102, 102))
|
||||||
|
draw.text((card_x + 105, 46), "КУШ: $66,600", fill=(255, 221, 68))
|
||||||
|
|
||||||
|
if state == 0: # BRIEFING
|
||||||
|
# Subcard
|
||||||
|
draw.rectangle([inner_x, 60, inner_x + inner_w, 130], fill=(30, 4, 4), outline=(136, 24, 24))
|
||||||
|
draw.text((card_x + 12, 66), f"ВРАГ: {BOSSES[floor_idx]}", fill=(255, 255, 255))
|
||||||
|
draw.text((card_x + 12, 80), f"ИГРА: {GAMES[floor_idx]}", fill=(255, 221, 102))
|
||||||
|
draw.text((card_x + 12, 96), DESCS[floor_idx], fill=(204, 204, 204))
|
||||||
|
draw.text((card_x + 12, 112), SUB_NOTES[floor_idx], fill=(170, 170, 170))
|
||||||
|
|
||||||
|
# Rules & warning box
|
||||||
|
draw.rectangle([inner_x, 134, inner_x + inner_w, 166], fill=(24, 3, 3), outline=(102, 17, 17))
|
||||||
|
draw.text((card_x + 12, 139), "6 этажей без поражений", fill=(255, 170, 51))
|
||||||
|
draw.text((card_x + 12, 151), "Поражение - возврат!", fill=(255, 85, 85))
|
||||||
|
|
||||||
|
# Bank
|
||||||
|
draw.text((card_x + 12, 172), "БАНК: $10,000", fill=(102, 255, 102))
|
||||||
|
draw.text((card_x + 115, 172), "НАГРАДА: +100%", fill=(255, 200, 50))
|
||||||
|
|
||||||
|
# Action Buttons
|
||||||
|
btn_w = 93
|
||||||
|
draw.rectangle([inner_x, 188, inner_x + btn_w, 212], fill=(61, 12, 12), outline=(255, 68, 68))
|
||||||
|
draw.text((inner_x + 12, 196), "[ENTER] БОЙ", fill=(255, 255, 255))
|
||||||
|
|
||||||
|
draw.rectangle([inner_x + 101, 188, inner_x + 101 + btn_w, 212], fill=(34, 6, 6), outline=(136, 34, 34))
|
||||||
|
draw.text((inner_x + 113, 196), "[ESC] НАЗАД", fill=(170, 170, 170))
|
||||||
|
|
||||||
# Floor indicator
|
elif state == 2: # CLEAR
|
||||||
draw.text((card_x + 10, 48), f"ЭТАЖ {stage} / 10", fill=(255, 102, 102))
|
draw.rectangle([inner_x, 62, inner_x + inner_w, 142], fill=(8, 34, 8), outline=(51, 204, 51), width=2)
|
||||||
|
clr_w = len("ЭТАЖ ЗАЧИЩЕН!") * 8
|
||||||
|
draw.text((inner_x + (inner_w - clr_w) // 2, 76), "ЭТАЖ ЗАЧИЩЕН!", fill=(102, 255, 102))
|
||||||
|
sub_w = len("Враг повержен!") * 8
|
||||||
|
draw.text((inner_x + (inner_w - sub_w) // 2, 96), "Враг повержен!", fill=(255, 255, 255))
|
||||||
|
rwd_w = len("Путь наверх открыт!") * 8
|
||||||
|
draw.text((inner_x + (inner_w - rwd_w) // 2, 116), "Путь наверх открыт!", fill=(255, 221, 102))
|
||||||
|
|
||||||
|
draw.rectangle([card_x + 18, 176, card_x + 188, 202], fill=(17, 68, 17), outline=(68, 255, 68))
|
||||||
|
btn_w2 = len("[ENTER] ДАЛЬШЕ") * 8
|
||||||
|
draw.text((card_x + 18 + (170 - btn_w2) // 2, 184), "[ENTER] ДАЛЬШЕ", fill=(255, 255, 255))
|
||||||
|
|
||||||
# Boss & Game sub-card
|
elif state == 3: # DEFEAT
|
||||||
draw.rectangle([card_x + 6, 64, card_x + card_w - 6, 126], fill=(30, 4, 4), outline=(136, 24, 24))
|
draw.rectangle([inner_x, 62, inner_x + inner_w, 142], fill=(42, 4, 4), outline=(255, 34, 34), width=2)
|
||||||
draw.text((card_x + 10, 68), f"ВРАГ: {BOSSES[floor_idx]}", fill=(255, 255, 255))
|
dft_w = len("ВЫ ПОГИБЛИ В БАШНЕ!") * 8
|
||||||
draw.text((card_x + 10, 82), f"ИГРА: {GAMES[floor_idx]}", fill=(255, 221, 102))
|
draw.text((inner_x + (inner_w - dft_w) // 2, 76), "ВЫ ПОГИБЛИ В БАШНЕ!", fill=(255, 68, 68))
|
||||||
draw.text((card_x + 10, 98), DESCS[floor_idx], fill=(204, 204, 204))
|
sub_w = len("Душа сгорела в Аду.") * 8
|
||||||
|
draw.text((inner_x + (inner_w - sub_w) // 2, 98), "Душа сгорела в Аду.", fill=(255, 255, 255))
|
||||||
|
|
||||||
|
draw.rectangle([card_x + 18, 176, card_x + 188, 202], fill=(68, 16, 16), outline=(255, 68, 68))
|
||||||
|
btn_w2 = len("[ESC] В ХОЛЛ КАЗИНО") * 8
|
||||||
|
draw.text((card_x + 18 + (170 - btn_w2) // 2, 184), "[ESC] В ХОЛЛ КАЗИНО", fill=(255, 255, 255))
|
||||||
|
|
||||||
# Rules & warning
|
elif state == 4: # CHAMPION
|
||||||
draw.text((card_x + 10, 132), "10 битв подряд без права на ошибку", fill=(255, 170, 51))
|
draw.rectangle([inner_x, 58, inner_x + inner_w, 150], fill=(51, 34, 0), outline=(255, 215, 0), width=2)
|
||||||
draw.text((card_x + 10, 146), "Поражение - возврат в холл казино", fill=(238, 68, 68))
|
chm_w = len("БАШНЯ ПОКОРЕНА!") * 8
|
||||||
|
draw.text((inner_x + (inner_w - chm_w) // 2, 70), "БАШНЯ ПОКОРЕНА!", fill=(255, 224, 102))
|
||||||
# Bankroll & Prize
|
sub_w = len("Вы - Владыка Башни!") * 8
|
||||||
draw.text((card_x + 10, 162), "БАНК: $10,000", fill=(102, 255, 102))
|
draw.text((inner_x + (inner_w - sub_w) // 2, 90), "Вы - Владыка Башни!", fill=(255, 255, 255))
|
||||||
draw.text((card_x + 110, 162), "КУШ: $66,600", fill=(255, 221, 68))
|
prz_w = len("КУШ: +$66,600 В БАНК!") * 8
|
||||||
|
draw.text((inner_x + (inner_w - prz_w) // 2, 114), "КУШ: +$66,600 В БАНК!", fill=(102, 255, 102))
|
||||||
# Buttons
|
|
||||||
draw.rectangle([card_x + 8, 184, card_x + 100, 206], fill=(61, 12, 12), outline=(255, 68, 68))
|
draw.rectangle([card_x + 18, 176, card_x + 188, 202], fill=(68, 51, 0), outline=(255, 204, 0))
|
||||||
draw.text((card_x + 14, 191), "[ПРОБЕЛ] В БОЙ", fill=(255, 255, 255))
|
btn_w2 = len("[ESC] В ХОЛЛ КАЗИНО") * 8
|
||||||
|
draw.text((card_x + 18 + (170 - btn_w2) // 2, 184), "[ESC] В ХОЛЛ КАЗИНО", fill=(255, 255, 255))
|
||||||
draw.rectangle([card_x + 106, 184, card_x + 198, 206], fill=(34, 6, 6), outline=(136, 34, 34))
|
|
||||||
draw.text((card_x + 114, 191), "[ESC] СБЕЖАТЬ", fill=(170, 170, 170))
|
|
||||||
|
|
||||||
# Scale 2x for high quality artifact preview (640x480)
|
|
||||||
bg_hd = bg.resize((640, 480), Image.Resampling.NEAREST)
|
|
||||||
return bg_hd
|
|
||||||
|
|
||||||
|
# Scale 2x for full HD 640x480 preview
|
||||||
|
return canvas.resize((640, 480), Image.Resampling.NEAREST)
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
ART_DIR.mkdir(parents=True, exist_ok=True)
|
ART_DIR.mkdir(parents=True, exist_ok=True)
|
||||||
f1 = render_menu_frame(1, 100)
|
for st in range(1, 7):
|
||||||
f1.save(ART_DIR / "helltower_rendered_floor1.png")
|
im = render_menu_frame(st, state=0)
|
||||||
print("[OK] Saved helltower_rendered_floor1.png")
|
im.save(ART_DIR / f"helltower_6fl_floor{st}.png")
|
||||||
|
print(f"[OK] Saved helltower_6fl_floor{st}.png")
|
||||||
f5 = render_menu_frame(5, 100)
|
|
||||||
f5.save(ART_DIR / "helltower_rendered_floor5.png")
|
clr = render_menu_frame(1, state=2)
|
||||||
print("[OK] Saved helltower_rendered_floor5.png")
|
clr.save(ART_DIR / "helltower_6fl_clear.png")
|
||||||
|
dft = render_menu_frame(1, state=3)
|
||||||
f10 = render_menu_frame(10, 100)
|
dft.save(ART_DIR / "helltower_6fl_defeat.png")
|
||||||
f10.save(ART_DIR / "helltower_rendered_floor10.png")
|
chp = render_menu_frame(6, state=4)
|
||||||
print("[OK] Saved helltower_rendered_floor10.png")
|
chp.save(ART_DIR / "helltower_6fl_champion.png")
|
||||||
|
print("All previews generated successfully!")
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
"""Automated smoke test for Hell Tower 10-floor run-through."""
|
"""Automated smoke test for Hell Tower 6-floor run-through."""
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
@ -22,13 +22,13 @@ def main():
|
||||||
print("[FAIL] Build failed:", build_res.stdout, build_res.stderr)
|
print("[FAIL] Build failed:", build_res.stdout, build_res.stderr)
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
print("[3/4] Running Hell Tower 10-floor run-through...")
|
print("[3/4] Running Hell Tower 6-floor run-through...")
|
||||||
run_res = subprocess.run([str(ROOT / "poker.exe")], cwd=ROOT, capture_output=True, timeout=15)
|
run_res = subprocess.run([str(ROOT / "poker.exe")], cwd=ROOT, capture_output=True, timeout=15)
|
||||||
print(f"Hell Tower test completed with exit code: {run_res.returncode}")
|
print(f"Hell Tower test completed with exit code: {run_res.returncode}")
|
||||||
if run_res.returncode != 0:
|
if run_res.returncode != 0:
|
||||||
print(f"[FAIL] Hell Tower run-through failed with code {run_res.returncode}")
|
print(f"[FAIL] Hell Tower run-through failed with code {run_res.returncode}")
|
||||||
return run_res.returncode
|
return run_res.returncode
|
||||||
print("[SUCCESS] All 10 floors of Hell Tower completed without errors or crashes!")
|
print("[SUCCESS] All 6 floors of Hell Tower completed without errors or crashes!")
|
||||||
finally:
|
finally:
|
||||||
print("[4/4] Restoring normal poker.asm and rebuilding...")
|
print("[4/4] Restoring normal poker.asm and rebuilding...")
|
||||||
restored = POKER_ASM.read_text(encoding="cp1251")
|
restored = POKER_ASM.read_text(encoding="cp1251")
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue