2261 lines
57 KiB
Python
2261 lines
57 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""
|
||
Generator script to patch casino3d.inc with rich, custom 2.5D graphics,
|
||
fixed audio, authentic palette (00RRGGBBh Little-Endian DIB), and native 2.5D minigames:
|
||
- Coin Flip (Монетка)
|
||
- Grand Craps / Dice (Кости)
|
||
- Gothic Skulls & Cups (Напёрстки)
|
||
- Dead by Daylight Skill Check (Проверка реакции)
|
||
"""
|
||
import shutil
|
||
from pathlib import Path
|
||
|
||
REPO_ROOT = Path(__file__).resolve().parents[2]
|
||
CASINO_INC = REPO_ROOT / 'casino3d.inc'
|
||
BACKUP_INC = REPO_ROOT / 'backups' / 'casino3d_before_full_fix.inc'
|
||
|
||
# 1. Back up casino3d.inc
|
||
BACKUP_INC.parent.mkdir(parents=True, exist_ok=True)
|
||
shutil.copyfile(CASINO_INC, BACKUP_INC)
|
||
print(f"[OK] Backed up casino3d.inc to {BACKUP_INC}")
|
||
|
||
with open(CASINO_INC, 'rb') as f:
|
||
raw_content = f.read()
|
||
|
||
# 2. Add MODE_SKILL equ 9
|
||
if b'MODE_SKILL equ 9' not in raw_content:
|
||
raw_content = raw_content.replace(
|
||
b'MODE_SKULLS equ 8',
|
||
b'MODE_SKULLS equ 8\r\nMODE_SKILL equ 9'
|
||
)
|
||
print("[OK] Added MODE_SKILL equ 9")
|
||
|
||
# 3. Audio block replacement
|
||
old_audio = (
|
||
b'soundClick db "assets\\audio\\b05e1ac8be34248.wav",0'
|
||
)
|
||
if old_audio in raw_content:
|
||
new_audio = (
|
||
b'soundClick db "assets\\audio\\revolverdryfirec.wav",0\r\n'
|
||
b'soundShuffle db "assets\\audio\\moving-stone.wav",0\r\n'
|
||
b'soundLose db "assets\\audio\\\xcf\xf0\xee\xe8\xe3\xf0\xfb\xf8.wav",0\r\n'
|
||
b'soundVictory db "assets\\audio\\victory-tf2.wav",0\r\n'
|
||
b'soundCoinDing db "assets\\audio\\\xc7\xe2\xf3\xea \xec\xee\xed\xe5\xf2\xfb \xe2 \xe8\xe3\xf0\xe5 Ultrakill.wav",0'
|
||
)
|
||
raw_content = raw_content.replace(old_audio, new_audio)
|
||
print("[OK] Replaced audio definitions")
|
||
|
||
# 4. Strings and variables section replacement
|
||
pos_coin_table = raw_content.find(b'coinRxAnimTable db')
|
||
pos_shop_msg = raw_content.find(b'shopMsg db 128 dup(0)')
|
||
assert pos_coin_table != -1 and pos_shop_msg != -1, "Could not locate text strings section"
|
||
|
||
new_strings = """coinRxAnimTable db 26, 22, 16, 6, 16, 22, 26, 22, 16, 6
|
||
|
||
; --- Native 2.5D Coin Flip ---
|
||
coin3d_bet dd 50
|
||
coin3d_choice dd 1 ; 1 = Орёл, 2 = Решка
|
||
coin3d_state dd 0 ; 0 = Idle, 1 = Flipping, 2 = Result
|
||
coin3d_timer dd 0
|
||
coin3d_result dd 1 ; 1 = Орёл, 2 = Решка
|
||
coin3d_streak dd 0
|
||
coin3d_win dd 0
|
||
|
||
textCoinTitle db "* * * З О Л О Т А Я М О Н Е Т А * * *",0
|
||
textCoinHeads db "ОРЁЛ",0
|
||
textCoinTails db "РЕШКА",0
|
||
textCoinSide1 db "[1] ОРЁЛ",0
|
||
textCoinSide2 db "[2] РЕШКА",0
|
||
textCoinFlipping db "МОНЕТА В ПОЛЁТЕ...",0
|
||
textCoinWin db "ПОБЕДА: +$",0
|
||
textCoinLose db "НЕ УГАДАЛИ!",0
|
||
textCoinStreakFmt db "СЕРИЯ ПОБЕД: x",0
|
||
textCoinSelected db "ВЫБРАНО",0
|
||
textCoinKey1 db "[1] ОРЁЛ",0
|
||
textCoinKey2 db "[2] РЕШКА",0
|
||
textCoinKeySpace db "[SPACE] БРОСОК",0
|
||
|
||
; --- Native 2.5D Dice Game ---
|
||
dice3d_bet dd 50
|
||
dice3d_choice dd 1 ; 1 = Чёт, 2 = Нечет
|
||
dice3d_state dd 0 ; 0 = Idle, 1 = Rolling, 2 = Result
|
||
dice3d_timer dd 0
|
||
dice3d_val1 dd 4
|
||
dice3d_val2 dd 6
|
||
dice3d_sum dd 10
|
||
dice3d_win dd 0
|
||
|
||
textDiceTitle db "=== G R A N D C R A P S ===",0
|
||
textDiceEven db "[1] ЧЁТ",0
|
||
textDiceOdd db "[2] НЕЧЕТ",0
|
||
textDiceEvenNums db "2 4 6 8 10 12",0
|
||
textDiceOddNums db "3 5 7 9 11",0
|
||
textDiceSumHdr db "СУММА: ",0
|
||
textDicePlus db " + ",0
|
||
textDiceEqual db " = ",0
|
||
textDiceEvenResult db " (ЧЁТ)",0
|
||
textDiceOddResult db " (НЕЧЕТ)",0
|
||
textDiceRolling db "КОСТИ ЛЕТЯТ ПО СУКНУ...",0
|
||
textDiceWin db "ВЫИГРЫШ: +$",0
|
||
textDiceWinMult db "! (x2)",0
|
||
textDiceLose db "ПРОИГРЫШ!",0
|
||
textDiceKey1 db "[1] ЧЁТ",0
|
||
textDiceKey2 db "[2] НЕЧЕТ",0
|
||
textDiceKeySpace db "[SPACE] БРОСОК",0
|
||
|
||
; --- Native 2.5D Skulls Game ---
|
||
skulls3d_bet dd 50
|
||
skulls3d_state dd 0 ; 0 = Idle, 1 = Show ball, 2 = Shuffle, 3 = Pick, 4 = Reveal
|
||
skulls3d_timer dd 0
|
||
skulls3d_ballPos dd 1 ; 0, 1, 2
|
||
skulls3d_choice dd 1 ; 0, 1, 2
|
||
skulls3d_win dd 0
|
||
skulls3d_swapPair0 dd 0
|
||
skulls3d_swapPair1 dd 1
|
||
skulls3d_swapPair2 dd 2
|
||
|
||
textSkullsTitle db "* * * Н А П Ё Р С Т К И : Ч Е Р Е П А * * *",0
|
||
textSkullsPhase0 db "ДЕЛАЙ СТАВКУ И ЖМИ [ПРОБЕЛ]",0
|
||
textSkullsPhase1 db "СМОТРИ, ГДЕ ЗОЛОТОЙ ШАР...",0
|
||
textSkullsPhase2 db "КРУЧУ, ВЕРЧУ, ЗАПУТАТЬ ХОЧУ...",0
|
||
textSkullsPhase3 db "ГДЕ ШАР? ВЫБИРАЙ: [1], [2] ИЛИ [3]!",0
|
||
textSkullsWin db "ВЫИГРЫШ: +$",0
|
||
textSkullsWinMult db "! (x3) ВЫ УГАДАЛИ!",0
|
||
textSkullsLose db "МИМО! ШАР БЫЛ В ДРУГОМ МЕСТЕ!",0
|
||
textSkullsAgain db "[ПРОБЕЛ] - СЫГРАТЬ ЕЩЁ РАЗ",0
|
||
textSkullsKey1 db "[1]",0
|
||
textSkullsKey2 db "[2]",0
|
||
textSkullsKey3 db "[3]",0
|
||
textSkullsKeySpace db "[SPACE] СТАРТ",0
|
||
|
||
; --- Native 2.5D Skill Check (Dead by Daylight Survivor Check) ---
|
||
skill3d_bet dd 50
|
||
skill3d_state dd 0 ; 0=Ready, 1=Active, 2=Hit Result, 3=Miss Result, 4=Escaped, 5=Defeated
|
||
skill3d_timer dd 0
|
||
skill3d_needle dd 55 ; Needle X (52..268)
|
||
skill3d_speed dd 4
|
||
skill3d_dir dd 1 ; 1=Right, -1=Left
|
||
skill3d_zone_start dd 140
|
||
skill3d_zone_width dd 48
|
||
skill3d_great_start dd 176
|
||
skill3d_great_width dd 12
|
||
skill3d_hits dd 0
|
||
skill3d_misses dd 0
|
||
skill3d_last_result dd 0
|
||
skill3d_win_amount dd 0
|
||
|
||
textSkillTitle db "=== S K I L L C H E C K ===",0
|
||
textSkillHitsHdr db "ХИТ: ",0
|
||
textSkillMissHdr db "ПРОМАХ: ",0
|
||
textSkillReadyMsg db "НАЖМИТЕ [ПРОБЕЛ] ДЛЯ СТАРТА",0
|
||
textSkillPrompt db "НАЖМИТЕ [ПРОБЕЛ] В ЗОНЕ!",0
|
||
textSkillHitMsg db "ХИТ! ТОЧНОЕ ПОПАДАНИЕ!",0
|
||
textSkillGreatMsg db "ОТЛИЧНО! GREAT SKILL CHECK! +БОНУС!",0
|
||
textSkillMissMsg db "ПРОМАХ! ТРЕВОГА!",0
|
||
textSkillEscape db "ПОБЕГ УСПЕШЕН! ВЫИГРЫШ: +$",0
|
||
textSkillLost db "ВЫ ПОЙМАНЫ! ПРОИГРЫШ СТАВКИ!",0
|
||
textSkillKeySpace db "[SPACE] РЕАКЦИЯ",0
|
||
textSkillKeyBet db "[ВВЕРХ/ВНИЗ]",0
|
||
|
||
; --- Shared UI Strings ---
|
||
textKeyEsc db "[ESC]",0
|
||
textBankPrompt db "БАНК: $",0
|
||
textBetPrompt db "СТАВКА: $",0
|
||
textBetHint db " [W/S]",0
|
||
|
||
"""
|
||
|
||
raw_content = raw_content[:pos_coin_table] + new_strings.encode('cp1251') + raw_content[pos_shop_msg:]
|
||
print("[OK] Replaced strings and variables")
|
||
|
||
# 5. Replace minigame procedural drawing & game logic
|
||
pos_games_start = raw_content.find(b'; ==============================================================================\r\n; SHARED RICH UI PROCEDURES')
|
||
if pos_games_start == -1:
|
||
pos_games_start = raw_content.find(b'; SHARED RICH UI PROCEDURES')
|
||
if pos_games_start == -1:
|
||
pos_games_start = raw_content.find(b'; IN-ENGINE 2.5D MINI-GAME: COIN FLIP')
|
||
|
||
pos_player_input = raw_content.find(b'HandlePlayerInput PROC')
|
||
assert pos_games_start != -1 and pos_player_input != -1, "Could not locate games procedures section"
|
||
|
||
new_games_code = r"""; ==============================================================================
|
||
; SHARED RICH UI PROCEDURES
|
||
; ==============================================================================
|
||
DrawKeycap3D PROC uses ebx esi edi, x:DWORD, y:DWORD, strPtr:DWORD, isActive:DWORD
|
||
local keyW:DWORD
|
||
mov esi, strPtr
|
||
xor ecx, ecx
|
||
keycap_len:
|
||
mov al, [esi+ecx]
|
||
test al, al
|
||
jz keycap_len_done
|
||
inc ecx
|
||
jmp keycap_len
|
||
keycap_len_done:
|
||
shl ecx, 3
|
||
add ecx, 8
|
||
mov keyW, ecx
|
||
|
||
; Drop shadow
|
||
mov eax, y
|
||
add eax, 2
|
||
invoke DrawBox, x, eax, keyW, 13, 0008080Ch
|
||
|
||
; Border and Fill
|
||
cmp isActive, 0
|
||
je keycap_inactive
|
||
mov eax, 00FFFF00h ; Bright Yellow active border
|
||
mov edx, 001B4B22h ; Casino Green active fill
|
||
mov ebx, 00FFFF00h ; Bright Yellow active text
|
||
jmp keycap_draw_box
|
||
keycap_inactive:
|
||
mov eax, 00606870h ; Slate inactive border
|
||
mov edx, 001A1C22h ; Charcoal inactive fill
|
||
mov ebx, 00D0D8E0h ; Silver inactive text
|
||
|
||
keycap_draw_box:
|
||
push ebx
|
||
invoke DrawBoxBorder, x, y, keyW, 13, edx, eax, 1
|
||
pop ebx
|
||
|
||
; Text label
|
||
mov eax, x
|
||
add eax, 4
|
||
mov edx, y
|
||
add edx, 3
|
||
invoke DrawString8x8, eax, edx, strPtr, ebx
|
||
|
||
mov eax, keyW
|
||
add eax, 4
|
||
ret
|
||
DrawKeycap3D ENDP
|
||
|
||
DrawChipStack PROC uses ebx esi edi, x:DWORD, y:DWORD, chipCount:DWORD
|
||
mov edi, chipCount
|
||
xor esi, esi
|
||
chip_loop:
|
||
cmp esi, edi
|
||
jge chip_done
|
||
mov eax, esi
|
||
shl eax, 2
|
||
mov edx, y
|
||
sub edx, eax
|
||
|
||
; Shadow
|
||
mov eax, x
|
||
add eax, 2
|
||
mov ecx, edx
|
||
add ecx, 5
|
||
invoke DrawBox, eax, ecx, 20, 2, 00061004h
|
||
|
||
; Red Clay Chip body with white rim
|
||
invoke DrawBoxBorder, x, edx, 24, 6, 00B81515h, 00FFFFFFh, 1
|
||
|
||
; White stripe inlays
|
||
mov eax, x
|
||
add eax, 4
|
||
mov ecx, edx
|
||
add ecx, 1
|
||
invoke DrawBox, eax, ecx, 3, 4, 00FFFFFFh
|
||
|
||
mov eax, x
|
||
add eax, 17
|
||
mov ecx, edx
|
||
add ecx, 1
|
||
invoke DrawBox, eax, ecx, 3, 4, 00FFFFFFh
|
||
|
||
inc esi
|
||
jmp chip_loop
|
||
chip_done:
|
||
ret
|
||
DrawChipStack ENDP
|
||
|
||
DrawDetailedCoin PROC uses ebx esi edi, cxVal:DWORD, cyVal:DWORD, rxVal:DWORD, ryVal:DWORD, outerColor:DWORD, innerColor:DWORD, reliefType:DWORD
|
||
local rxSq:DWORD
|
||
local rySq:DWORD
|
||
local rxRySq:DWORD
|
||
local threshSq:DWORD
|
||
local curDy:DWORD
|
||
local curDx:DWORD
|
||
local curX:DWORD
|
||
local curY:DWORD
|
||
|
||
mov eax, rxVal
|
||
cmp eax, 0
|
||
jle coin_draw_done
|
||
mov eax, ryVal
|
||
cmp eax, 0
|
||
jle coin_draw_done
|
||
|
||
mov eax, rxVal
|
||
imul eax, rxVal
|
||
mov rxSq, eax
|
||
|
||
mov eax, ryVal
|
||
imul eax, ryVal
|
||
mov rySq, eax
|
||
|
||
imul eax, rxSq
|
||
mov rxRySq, eax
|
||
|
||
; 3/4 threshold for rim bevel
|
||
mov ecx, 3
|
||
imul eax, ecx
|
||
shr eax, 2
|
||
mov threshSq, eax
|
||
|
||
; Scan rows
|
||
mov eax, ryVal
|
||
neg eax
|
||
mov curDy, eax
|
||
coin_row_loop:
|
||
mov eax, curDy
|
||
cmp eax, ryVal
|
||
jg coin_relief_check
|
||
|
||
mov edx, cyVal
|
||
add edx, curDy
|
||
mov curY, edx
|
||
|
||
; Scan columns
|
||
mov eax, rxVal
|
||
neg eax
|
||
mov curDx, eax
|
||
coin_col_loop:
|
||
mov eax, curDx
|
||
cmp eax, rxVal
|
||
jg coin_col_next_row
|
||
|
||
mov ecx, cxVal
|
||
add ecx, curDx
|
||
mov curX, ecx
|
||
|
||
; val = dx*dx*rySq + dy*dy*rxSq
|
||
mov eax, curDx
|
||
imul eax, curDx
|
||
imul eax, rySq
|
||
mov ebx, eax
|
||
|
||
mov eax, curDy
|
||
imul eax, curDy
|
||
imul eax, rxSq
|
||
add eax, ebx
|
||
|
||
cmp eax, rxRySq
|
||
ja coin_pixel_outside
|
||
|
||
cmp eax, threshSq
|
||
jb coin_draw_inner
|
||
invoke DrawPixel, curX, curY, outerColor
|
||
jmp coin_pixel_outside
|
||
coin_draw_inner:
|
||
invoke DrawPixel, curX, curY, innerColor
|
||
|
||
coin_pixel_outside:
|
||
inc curDx
|
||
jmp coin_col_loop
|
||
|
||
coin_col_next_row:
|
||
inc curDy
|
||
jmp coin_row_loop
|
||
|
||
coin_relief_check:
|
||
cmp rxVal, 14
|
||
jl coin_draw_done
|
||
|
||
cmp reliefType, 1
|
||
je coin_draw_eagle
|
||
cmp reliefType, 2
|
||
je coin_draw_numeral
|
||
jmp coin_draw_done
|
||
|
||
coin_draw_eagle:
|
||
; Imperial Eagle relief (Dark Gold 009A7A00h / Bright 00FFD700h)
|
||
mov eax, cxVal
|
||
sub eax, 3
|
||
mov edx, cyVal
|
||
sub edx, 14
|
||
invoke DrawBox, eax, edx, 7, 2, 009A7A00h
|
||
|
||
mov eax, cxVal
|
||
sub eax, 4
|
||
mov edx, cyVal
|
||
sub edx, 12
|
||
invoke DrawBox, eax, edx, 9, 2, 009A7A00h
|
||
|
||
mov eax, cxVal
|
||
sub eax, 2
|
||
mov edx, cyVal
|
||
sub edx, 9
|
||
invoke DrawBox, eax, edx, 5, 12, 009A7A00h
|
||
|
||
mov eax, cxVal
|
||
sub eax, 1
|
||
mov edx, cyVal
|
||
sub edx, 8
|
||
invoke DrawBox, eax, edx, 3, 10, 00FFD700h
|
||
|
||
mov eax, cxVal
|
||
sub eax, 10
|
||
mov edx, cyVal
|
||
sub edx, 8
|
||
invoke DrawBox, eax, edx, 7, 3, 009A7A00h
|
||
|
||
mov eax, cxVal
|
||
sub eax, 13
|
||
mov edx, cyVal
|
||
sub edx, 5
|
||
invoke DrawBox, eax, edx, 10, 3, 009A7A00h
|
||
|
||
mov eax, cxVal
|
||
sub eax, 11
|
||
mov edx, cyVal
|
||
sub edx, 2
|
||
invoke DrawBox, eax, edx, 7, 3, 009A7A00h
|
||
|
||
mov eax, cxVal
|
||
add eax, 4
|
||
mov edx, cyVal
|
||
sub edx, 8
|
||
invoke DrawBox, eax, edx, 7, 3, 009A7A00h
|
||
|
||
mov eax, cxVal
|
||
add eax, 4
|
||
mov edx, cyVal
|
||
sub edx, 5
|
||
invoke DrawBox, eax, edx, 10, 3, 009A7A00h
|
||
|
||
mov eax, cxVal
|
||
add eax, 5
|
||
mov edx, cyVal
|
||
sub edx, 2
|
||
invoke DrawBox, eax, edx, 7, 3, 009A7A00h
|
||
|
||
mov eax, cxVal
|
||
sub eax, 4
|
||
mov edx, cyVal
|
||
add edx, 4
|
||
invoke DrawBox, eax, edx, 9, 3, 009A7A00h
|
||
|
||
mov eax, cxVal
|
||
sub eax, 3
|
||
mov edx, cyVal
|
||
add edx, 7
|
||
invoke DrawBox, eax, edx, 7, 3, 009A7A00h
|
||
jmp coin_draw_done
|
||
|
||
coin_draw_numeral:
|
||
; Roman numeral 'I' & laurel
|
||
mov eax, cxVal
|
||
sub eax, 5
|
||
mov edx, cyVal
|
||
sub edx, 10
|
||
invoke DrawBox, eax, edx, 11, 3, 009A7A00h
|
||
|
||
mov eax, cxVal
|
||
sub eax, 2
|
||
mov edx, cyVal
|
||
sub edx, 7
|
||
invoke DrawBox, eax, edx, 5, 14, 009A7A00h
|
||
|
||
mov eax, cxVal
|
||
sub eax, 1
|
||
mov edx, cyVal
|
||
sub edx, 6
|
||
invoke DrawBox, eax, edx, 3, 12, 00FFD700h
|
||
|
||
mov eax, cxVal
|
||
sub eax, 6
|
||
mov edx, cyVal
|
||
add edx, 7
|
||
invoke DrawBox, eax, edx, 13, 3, 009A7A00h
|
||
|
||
; Laurel dots
|
||
mov eax, cxVal
|
||
sub eax, 12
|
||
mov edx, cyVal
|
||
sub edx, 8
|
||
invoke DrawBox, eax, edx, 2, 2, 009A7A00h
|
||
|
||
mov eax, cxVal
|
||
add eax, 11
|
||
mov edx, cyVal
|
||
sub edx, 8
|
||
invoke DrawBox, eax, edx, 2, 2, 009A7A00h
|
||
|
||
mov eax, cxVal
|
||
sub eax, 12
|
||
mov edx, cyVal
|
||
invoke DrawBox, eax, edx, 2, 2, 009A7A00h
|
||
|
||
mov eax, cxVal
|
||
add eax, 11
|
||
mov edx, cyVal
|
||
invoke DrawBox, eax, edx, 2, 2, 009A7A00h
|
||
|
||
mov eax, cxVal
|
||
sub eax, 12
|
||
mov edx, cyVal
|
||
add edx, 8
|
||
invoke DrawBox, eax, edx, 2, 2, 009A7A00h
|
||
|
||
mov eax, cxVal
|
||
add eax, 11
|
||
mov edx, cyVal
|
||
add edx, 8
|
||
invoke DrawBox, eax, edx, 2, 2, 009A7A00h
|
||
|
||
coin_draw_done:
|
||
ret
|
||
DrawDetailedCoin ENDP
|
||
|
||
; ==============================================================================
|
||
; IN-ENGINE 2.5D MINI-GAME: COIN FLIP
|
||
; ==============================================================================
|
||
InitCoinGame PROC
|
||
mov coin3d_state, 0
|
||
mov coin3d_timer, 0
|
||
mov coin3d_streak, 0
|
||
mov coin3d_win, 0
|
||
ret
|
||
InitCoinGame ENDP
|
||
|
||
HandleCoinInput PROC
|
||
cmp coin3d_state, 0
|
||
je coin_handle_idle
|
||
cmp coin3d_state, 1
|
||
je coin_handle_flipping
|
||
cmp coin3d_state, 2
|
||
je coin_handle_result
|
||
ret
|
||
|
||
coin_handle_idle:
|
||
invoke Pressed3D, 26h ; UP
|
||
test eax, eax
|
||
jnz coin_bet_up
|
||
invoke Pressed3D, 57h ; 'W'
|
||
test eax, eax
|
||
jnz coin_bet_up
|
||
invoke Pressed3D, 28h ; DOWN
|
||
test eax, eax
|
||
jnz coin_bet_down
|
||
invoke Pressed3D, 53h ; 'S'
|
||
test eax, eax
|
||
jnz coin_bet_down
|
||
invoke Pressed3D, 31h ; '1'
|
||
test eax, eax
|
||
jnz coin_pick_1
|
||
invoke Pressed3D, 32h ; '2'
|
||
test eax, eax
|
||
jnz coin_pick_2
|
||
invoke Pressed3D, 20h ; SPACE
|
||
test eax, eax
|
||
jnz coin_start_flip
|
||
ret
|
||
|
||
coin_bet_up:
|
||
mov eax, coin3d_bet
|
||
add eax, 50
|
||
cmp eax, bankroll
|
||
jle @F
|
||
mov eax, bankroll
|
||
@@:
|
||
cmp eax, 5000
|
||
jle @F
|
||
mov eax, 5000
|
||
@@:
|
||
mov coin3d_bet, eax
|
||
invoke PlaySoundA, OFFSET soundClick, 0, 1
|
||
ret
|
||
|
||
coin_bet_down:
|
||
mov eax, coin3d_bet
|
||
sub eax, 50
|
||
cmp eax, 50
|
||
jge @F
|
||
mov eax, 50
|
||
@@:
|
||
mov coin3d_bet, eax
|
||
invoke PlaySoundA, OFFSET soundClick, 0, 1
|
||
ret
|
||
|
||
coin_pick_1:
|
||
mov coin3d_choice, 1
|
||
invoke PlaySoundA, OFFSET soundClick, 0, 1
|
||
ret
|
||
|
||
coin_pick_2:
|
||
mov coin3d_choice, 2
|
||
invoke PlaySoundA, OFFSET soundClick, 0, 1
|
||
ret
|
||
|
||
coin_start_flip:
|
||
mov eax, coin3d_bet
|
||
cmp eax, bankroll
|
||
jle @F
|
||
mov eax, bankroll
|
||
mov coin3d_bet, eax
|
||
test eax, eax
|
||
jz coin_done
|
||
@@:
|
||
mov eax, coin3d_bet
|
||
sub bankroll, eax
|
||
mov coin3d_state, 1
|
||
mov coin3d_timer, 40
|
||
invoke PlaySoundA, OFFSET soundCoin, 0, 1
|
||
ret
|
||
|
||
coin_handle_flipping:
|
||
dec coin3d_timer
|
||
cmp coin3d_timer, 0
|
||
jg coin_done
|
||
invoke RandomRange3D, 2
|
||
inc eax
|
||
mov coin3d_result, eax
|
||
mov edx, coin3d_choice
|
||
cmp eax, edx
|
||
jne coin_flip_lost
|
||
|
||
; Won!
|
||
inc coin3d_streak
|
||
mov eax, coin3d_bet
|
||
shl eax, 1
|
||
add bankroll, eax
|
||
mov coin3d_win, eax
|
||
mov coin3d_state, 2
|
||
invoke PlaySoundA, OFFSET soundCoinDing, 0, 1
|
||
ret
|
||
|
||
coin_flip_lost:
|
||
mov coin3d_streak, 0
|
||
mov coin3d_win, 0
|
||
mov coin3d_state, 2
|
||
invoke PlaySoundA, OFFSET soundLose, 0, 1
|
||
ret
|
||
|
||
coin_handle_result:
|
||
invoke Pressed3D, 20h
|
||
test eax, eax
|
||
jz coin_done
|
||
mov coin3d_state, 0
|
||
invoke PlaySoundA, OFFSET soundClick, 0, 1
|
||
coin_done:
|
||
ret
|
||
HandleCoinInput ENDP
|
||
|
||
RenderCoinGame PROC uses ebx esi edi
|
||
local cyVal:DWORD
|
||
local rxVal:DWORD
|
||
local kx:DWORD
|
||
|
||
; Background & Cabinet border
|
||
invoke DrawBox, 0, 0, 320, 240, 00140906h
|
||
invoke DrawBoxBorder, 6, 6, 308, 228, 0022150Fh, 00482E1Bh, 3
|
||
|
||
; Header
|
||
invoke DrawBoxBorder, 20, 12, 280, 26, 001C100Ah, 00FFD700h, 2
|
||
invoke DrawString8x8, 44, 21, OFFSET textCoinTitle, 00FFFF00h
|
||
|
||
; Corner rivets
|
||
invoke DrawBox, 12, 12, 3, 3, 00FFD700h
|
||
invoke DrawBox, 306, 12, 3, 3, 00FFD700h
|
||
invoke DrawBox, 12, 226, 3, 3, 00FFD700h
|
||
invoke DrawBox, 306, 226, 3, 3, 00FFD700h
|
||
|
||
; Status meters
|
||
invoke DrawBoxBorder, 20, 44, 110, 18, 000E1A0Ah, 00224B1Ah, 1
|
||
invoke DrawString8x8, 24, 49, OFFSET textBankPrompt, 003CFF3Ch
|
||
invoke FormatNumber, bankroll, OFFSET hudNumBuffer
|
||
invoke DrawString8x8, 72, 49, OFFSET hudNumBuffer, 003CFF3Ch
|
||
|
||
invoke DrawBoxBorder, 190, 44, 110, 18, 001A100Ah, 003A2814h, 1
|
||
invoke DrawString8x8, 194, 49, OFFSET textBetPrompt, 00FFD700h
|
||
invoke FormatNumber, coin3d_bet, OFFSET hudNumBuffer
|
||
invoke DrawString8x8, 254, 49, OFFSET hudNumBuffer, 00FFD700h
|
||
|
||
; Left: Heads
|
||
cmp coin3d_choice, 1
|
||
jne coin_left_inactive
|
||
invoke DrawBoxBorder, 20, 72, 76, 68, 00101828h, 00FFFF00h, 2
|
||
invoke DrawString8x8, 30, 78, OFFSET textCoinSide1, 00FFFF00h
|
||
invoke DrawDetailedCoin, 58, 106, 14, 14, 00D0A000h, 00FFD700h, 1
|
||
invoke DrawString8x8, 24, 126, OFFSET textCoinSelected, 003CFF3Ch
|
||
jmp coin_right_side
|
||
coin_left_inactive:
|
||
invoke DrawBoxBorder, 20, 72, 76, 68, 000A101Ch, 00404855h, 1
|
||
invoke DrawString8x8, 30, 78, OFFSET textCoinSide1, 00D0D8E0h
|
||
invoke DrawDetailedCoin, 58, 106, 14, 14, 009A7A00h, 00D0A000h, 1
|
||
|
||
coin_right_side:
|
||
; Right: Tails
|
||
cmp coin3d_choice, 2
|
||
jne coin_right_inactive
|
||
invoke DrawBoxBorder, 224, 72, 76, 68, 00101828h, 00FFFF00h, 2
|
||
invoke DrawString8x8, 234, 78, OFFSET textCoinSide2, 00FFFF00h
|
||
invoke DrawDetailedCoin, 262, 106, 14, 14, 00D0A000h, 00FFD700h, 2
|
||
invoke DrawString8x8, 228, 126, OFFSET textCoinSelected, 003CFF3Ch
|
||
jmp coin_center_area
|
||
coin_right_inactive:
|
||
invoke DrawBoxBorder, 224, 72, 76, 68, 000A101Ch, 00404855h, 1
|
||
invoke DrawString8x8, 234, 78, OFFSET textCoinSide2, 00D0D8E0h
|
||
invoke DrawDetailedCoin, 262, 106, 14, 14, 009A7A00h, 00D0A000h, 2
|
||
|
||
coin_center_area:
|
||
; Center spotlight
|
||
invoke DrawCircle, 160, 110, 48, 00121620h
|
||
invoke DrawCircle, 160, 110, 44, 00FFD700h
|
||
invoke DrawCircle, 160, 110, 42, 000E141Eh
|
||
|
||
cmp coin3d_state, 1
|
||
je coin_render_flipping
|
||
cmp coin3d_state, 2
|
||
je coin_render_result
|
||
|
||
; Idle coin
|
||
invoke DrawDetailedCoin, 160, 110, 26, 26, 00D0A000h, 00FFD700h, coin3d_choice
|
||
jmp coin_render_keys
|
||
|
||
coin_render_flipping:
|
||
mov eax, coin3d_timer
|
||
and eax, 7
|
||
movzx eax, byte ptr [coinRxAnimTable + eax]
|
||
mov rxVal, eax
|
||
invoke DrawDetailedCoin, 160, 110, rxVal, 26, 00D0A000h, 00FFD700h, 0
|
||
invoke DrawString8x8, 88, 160, OFFSET textCoinFlipping, 00FFFF00h
|
||
jmp coin_render_keys
|
||
|
||
coin_render_result:
|
||
invoke DrawDetailedCoin, 160, 110, 26, 26, 00D0A000h, 00FFD700h, coin3d_result
|
||
mov eax, coin3d_result
|
||
cmp eax, coin3d_choice
|
||
jne coin_render_loss_msg
|
||
|
||
; Win banner
|
||
invoke DrawBoxBorder, 44, 154, 232, 22, 000E141Eh, 003CFF3Ch, 1
|
||
invoke DrawString8x8, 64, 161, OFFSET textCoinWin, 003CFF3Ch
|
||
invoke FormatNumber, coin3d_win, OFFSET hudNumBuffer
|
||
invoke DrawString8x8, 152, 161, OFFSET hudNumBuffer, 003CFF3Ch
|
||
jmp coin_render_keys
|
||
|
||
coin_render_loss_msg:
|
||
invoke DrawBoxBorder, 44, 154, 232, 22, 000E141Eh, 00C81414h, 1
|
||
invoke DrawString8x8, 114, 161, OFFSET textCoinLose, 00FF6464h
|
||
|
||
coin_render_keys:
|
||
mov kx, 16
|
||
xor eax, eax
|
||
cmp coin3d_choice, 1
|
||
sete al
|
||
invoke DrawKeycap3D, kx, 192, OFFSET textCoinKey1, eax
|
||
add kx, eax
|
||
|
||
xor eax, eax
|
||
cmp coin3d_choice, 2
|
||
sete al
|
||
invoke DrawKeycap3D, kx, 192, OFFSET textCoinKey2, eax
|
||
add kx, eax
|
||
|
||
invoke DrawKeycap3D, kx, 192, OFFSET textCoinKeySpace, 1
|
||
add kx, eax
|
||
|
||
invoke DrawKeycap3D, kx, 192, OFFSET textKeyEsc, 0
|
||
ret
|
||
RenderCoinGame ENDP
|
||
|
||
; ==============================================================================
|
||
; IN-ENGINE 2.5D MINI-GAME: CRAPS / DICE
|
||
; ==============================================================================
|
||
DrawCrapsDie PROC uses ebx esi edi, x:DWORD, y:DWORD, sizeVal:DWORD, valNum:DWORD
|
||
; Drop shadow
|
||
mov eax, x
|
||
add eax, 3
|
||
mov edx, y
|
||
add edx, sizeVal
|
||
invoke DrawBox, eax, edx, sizeVal, 3, 00081403h
|
||
|
||
mov eax, x
|
||
add eax, sizeVal
|
||
mov edx, y
|
||
add edx, 3
|
||
invoke DrawBox, eax, edx, 3, sizeVal, 00081403h
|
||
|
||
; Ivory body & bevel
|
||
invoke DrawBoxBorder, x, y, sizeVal, sizeVal, 00FAF4F0h, 00403535h, 1
|
||
mov eax, x
|
||
inc eax
|
||
mov edx, y
|
||
inc edx
|
||
mov ecx, sizeVal
|
||
sub ecx, 2
|
||
invoke DrawBox, eax, edx, ecx, 1, 00FFFFFFh
|
||
invoke DrawBox, eax, edx, 1, ecx, 00FFFFFFh
|
||
|
||
; Ruby pips (00C81515h)
|
||
mov eax, valNum
|
||
test al, 1
|
||
jz @F
|
||
; Center pip
|
||
mov eax, x
|
||
add eax, 18
|
||
mov edx, y
|
||
add edx, 18
|
||
invoke DrawCircle, eax, edx, 3, 00C81515h
|
||
dec eax
|
||
dec edx
|
||
invoke DrawPixel, eax, edx, 00FFFFFFh
|
||
@@:
|
||
cmp valNum, 2
|
||
jl die_pips_done
|
||
mov eax, x
|
||
add eax, 9
|
||
mov edx, y
|
||
add edx, 9
|
||
invoke DrawCircle, eax, edx, 3, 00C81515h
|
||
mov eax, x
|
||
add eax, 27
|
||
mov edx, y
|
||
add edx, 27
|
||
invoke DrawCircle, eax, edx, 3, 00C81515h
|
||
|
||
cmp valNum, 4
|
||
jl die_pips_done
|
||
mov eax, x
|
||
add eax, 27
|
||
mov edx, y
|
||
add edx, 9
|
||
invoke DrawCircle, eax, edx, 3, 00C81515h
|
||
mov eax, x
|
||
add eax, 9
|
||
mov edx, y
|
||
add edx, 27
|
||
invoke DrawCircle, eax, edx, 3, 00C81515h
|
||
|
||
cmp valNum, 6
|
||
jl die_pips_done
|
||
mov eax, x
|
||
add eax, 9
|
||
mov edx, y
|
||
add edx, 18
|
||
invoke DrawCircle, eax, edx, 3, 00C81515h
|
||
mov eax, x
|
||
add eax, 27
|
||
mov edx, y
|
||
add edx, 18
|
||
invoke DrawCircle, eax, edx, 3, 00C81515h
|
||
|
||
die_pips_done:
|
||
ret
|
||
DrawCrapsDie ENDP
|
||
|
||
InitDiceGame PROC
|
||
mov dice3d_state, 0
|
||
mov dice3d_timer, 0
|
||
mov dice3d_win, 0
|
||
ret
|
||
InitDiceGame ENDP
|
||
|
||
HandleDiceInput PROC
|
||
cmp dice3d_state, 0
|
||
je dice_handle_idle
|
||
cmp dice3d_state, 1
|
||
je dice_handle_rolling
|
||
cmp dice3d_state, 2
|
||
je dice_handle_result
|
||
ret
|
||
|
||
dice_handle_idle:
|
||
invoke Pressed3D, 26h ; UP
|
||
test eax, eax
|
||
jnz dice_bet_up
|
||
invoke Pressed3D, 57h ; 'W'
|
||
test eax, eax
|
||
jnz dice_bet_up
|
||
invoke Pressed3D, 28h ; DOWN
|
||
test eax, eax
|
||
jnz dice_bet_down
|
||
invoke Pressed3D, 53h ; 'S'
|
||
test eax, eax
|
||
jnz dice_bet_down
|
||
invoke Pressed3D, 31h ; '1'
|
||
test eax, eax
|
||
jnz dice_pick_1
|
||
invoke Pressed3D, 32h ; '2'
|
||
test eax, eax
|
||
jnz dice_pick_2
|
||
invoke Pressed3D, 20h ; SPACE
|
||
test eax, eax
|
||
jnz dice_start_roll
|
||
ret
|
||
|
||
dice_bet_up:
|
||
mov eax, dice3d_bet
|
||
add eax, 50
|
||
cmp eax, bankroll
|
||
jle @F
|
||
mov eax, bankroll
|
||
@@:
|
||
cmp eax, 5000
|
||
jle @F
|
||
mov eax, 5000
|
||
@@:
|
||
mov dice3d_bet, eax
|
||
invoke PlaySoundA, OFFSET soundClick, 0, 1
|
||
ret
|
||
|
||
dice_bet_down:
|
||
mov eax, dice3d_bet
|
||
sub eax, 50
|
||
cmp eax, 50
|
||
jge @F
|
||
mov eax, 50
|
||
@@:
|
||
mov dice3d_bet, eax
|
||
invoke PlaySoundA, OFFSET soundClick, 0, 1
|
||
ret
|
||
|
||
dice_pick_1:
|
||
mov dice3d_choice, 1
|
||
invoke PlaySoundA, OFFSET soundClick, 0, 1
|
||
ret
|
||
|
||
dice_pick_2:
|
||
mov dice3d_choice, 2
|
||
invoke PlaySoundA, OFFSET soundClick, 0, 1
|
||
ret
|
||
|
||
dice_start_roll:
|
||
mov eax, dice3d_bet
|
||
cmp eax, bankroll
|
||
jle @F
|
||
mov eax, bankroll
|
||
mov dice3d_bet, eax
|
||
test eax, eax
|
||
jz dice_done
|
||
@@:
|
||
mov eax, dice3d_bet
|
||
sub bankroll, eax
|
||
mov dice3d_state, 1
|
||
mov dice3d_timer, 35
|
||
invoke PlaySoundA, OFFSET soundCards, 0, 1
|
||
ret
|
||
|
||
dice_handle_rolling:
|
||
dec dice3d_timer
|
||
cmp dice3d_timer, 0
|
||
jg dice_randomize_tumble
|
||
|
||
; Roll finished!
|
||
invoke RandomRange3D, 6
|
||
inc eax
|
||
mov dice3d_val1, eax
|
||
invoke RandomRange3D, 6
|
||
inc eax
|
||
mov dice3d_val2, eax
|
||
|
||
mov edx, dice3d_val1
|
||
add edx, eax
|
||
mov dice3d_sum, edx
|
||
|
||
; Parity check
|
||
mov eax, edx
|
||
and eax, 1
|
||
jnz dice_sum_is_odd
|
||
; Even
|
||
mov eax, 1
|
||
jmp dice_check_win
|
||
dice_sum_is_odd:
|
||
mov eax, 2
|
||
|
||
dice_check_win:
|
||
cmp eax, dice3d_choice
|
||
jne dice_roll_lost
|
||
|
||
; Won!
|
||
mov eax, dice3d_bet
|
||
shl eax, 1
|
||
add bankroll, eax
|
||
mov dice3d_win, eax
|
||
mov dice3d_state, 2
|
||
invoke PlaySoundA, OFFSET soundVictory, 0, 1
|
||
ret
|
||
|
||
dice_roll_lost:
|
||
mov dice3d_win, 0
|
||
mov dice3d_state, 2
|
||
invoke PlaySoundA, OFFSET soundLose, 0, 1
|
||
ret
|
||
|
||
dice_randomize_tumble:
|
||
invoke RandomRange3D, 6
|
||
inc eax
|
||
mov dice3d_val1, eax
|
||
invoke RandomRange3D, 6
|
||
inc eax
|
||
mov dice3d_val2, eax
|
||
ret
|
||
|
||
dice_handle_result:
|
||
invoke Pressed3D, 20h
|
||
test eax, eax
|
||
jz dice_done
|
||
mov dice3d_state, 0
|
||
invoke PlaySoundA, OFFSET soundClick, 0, 1
|
||
dice_done:
|
||
ret
|
||
HandleDiceInput ENDP
|
||
|
||
RenderDiceGame PROC uses ebx esi edi
|
||
local kx:DWORD
|
||
|
||
; Mahogany frame & Deep Felt Green table
|
||
invoke DrawBox, 0, 0, 320, 240, 00140906h
|
||
invoke DrawBoxBorder, 6, 6, 308, 228, 000A3816h, 00FFD700h, 2
|
||
|
||
; Header
|
||
invoke DrawBoxBorder, 20, 12, 280, 26, 00072E13h, 00FFD700h, 2
|
||
invoke DrawString8x8, 48, 21, OFFSET textDiceTitle, 00FFFF00h
|
||
|
||
; Status
|
||
invoke DrawBoxBorder, 20, 44, 110, 18, 00072E13h, 001B4B22h, 1
|
||
invoke DrawString8x8, 24, 49, OFFSET textBankPrompt, 003CFF3Ch
|
||
invoke FormatNumber, bankroll, OFFSET hudNumBuffer
|
||
invoke DrawString8x8, 72, 49, OFFSET hudNumBuffer, 003CFF3Ch
|
||
|
||
invoke DrawBoxBorder, 190, 44, 110, 18, 00072E13h, 001B4B22h, 1
|
||
invoke DrawString8x8, 194, 49, OFFSET textBetPrompt, 00FFD700h
|
||
invoke FormatNumber, dice3d_bet, OFFSET hudNumBuffer
|
||
invoke DrawString8x8, 254, 49, OFFSET hudNumBuffer, 00FFD700h
|
||
|
||
; [1] ЧЁТ
|
||
cmp dice3d_choice, 1
|
||
jne dice_even_inactive
|
||
invoke DrawBoxBorder, 16, 70, 88, 48, 00072E13h, 00FFFF00h, 2
|
||
invoke DrawString8x8, 30, 76, OFFSET textDiceEven, 00FFFF00h
|
||
invoke DrawString8x8, 22, 90, OFFSET textDiceEvenNums, 00FFD700h
|
||
invoke DrawString8x8, 26, 104, OFFSET textCoinSelected, 003CFF3Ch
|
||
jmp dice_odd_side
|
||
dice_even_inactive:
|
||
invoke DrawBoxBorder, 16, 70, 88, 48, 00072E13h, 001B4B22h, 1
|
||
invoke DrawString8x8, 30, 76, OFFSET textDiceEven, 00D0D8E0h
|
||
invoke DrawString8x8, 22, 90, OFFSET textDiceEvenNums, 0080B090h
|
||
|
||
dice_odd_side:
|
||
; [2] НЕЧЕТ
|
||
cmp dice3d_choice, 2
|
||
jne dice_odd_inactive
|
||
invoke DrawBoxBorder, 216, 70, 88, 48, 00072E13h, 00FFFF00h, 2
|
||
invoke DrawString8x8, 226, 76, OFFSET textDiceOdd, 00FFFF00h
|
||
invoke DrawString8x8, 224, 90, OFFSET textDiceOddNums, 00FFD700h
|
||
invoke DrawString8x8, 226, 104, OFFSET textCoinSelected, 003CFF3Ch
|
||
jmp dice_center_cubes
|
||
dice_odd_inactive:
|
||
invoke DrawBoxBorder, 216, 70, 88, 48, 00072E13h, 001B4B22h, 1
|
||
invoke DrawString8x8, 226, 76, OFFSET textDiceOdd, 00D0D8E0h
|
||
invoke DrawString8x8, 224, 90, OFFSET textDiceOddNums, 0080B090h
|
||
|
||
dice_center_cubes:
|
||
; 2 Dice in center
|
||
invoke DrawCrapsDie, 116, 76, 36, dice3d_val1
|
||
invoke DrawCrapsDie, 168, 76, 36, dice3d_val2
|
||
|
||
cmp dice3d_state, 1
|
||
je dice_render_rolling
|
||
cmp dice3d_state, 2
|
||
je dice_render_result
|
||
jmp dice_render_keys
|
||
|
||
dice_render_rolling:
|
||
invoke DrawString8x8, 76, 138, OFFSET textDiceRolling, 00FFFF00h
|
||
jmp dice_render_keys
|
||
|
||
dice_render_result:
|
||
invoke DrawBoxBorder, 36, 130, 248, 36, 00072E13h, 00FFD700h, 1
|
||
invoke DrawString8x8, 44, 135, OFFSET textDiceSumHdr, 00FFD700h
|
||
invoke FormatNumber, dice3d_val1, OFFSET hudNumBuffer
|
||
invoke DrawString8x8, 92, 135, OFFSET hudNumBuffer, 00FFFF00h
|
||
invoke DrawString8x8, 110, 135, OFFSET textDicePlus, 00FFD700h
|
||
invoke FormatNumber, dice3d_val2, OFFSET hudNumBuffer
|
||
invoke DrawString8x8, 126, 135, OFFSET hudNumBuffer, 00FFFF00h
|
||
invoke DrawString8x8, 144, 135, OFFSET textDiceEqual, 00FFD700h
|
||
invoke FormatNumber, dice3d_sum, OFFSET hudNumBuffer
|
||
invoke DrawString8x8, 168, 135, OFFSET hudNumBuffer, 00FFFF00h
|
||
|
||
mov eax, dice3d_sum
|
||
and eax, 1
|
||
jnz dice_render_odd_res
|
||
invoke DrawString8x8, 186, 135, OFFSET textDiceEvenResult, 003CFF3Ch
|
||
jmp dice_render_outcome
|
||
dice_render_odd_res:
|
||
invoke DrawString8x8, 186, 135, OFFSET textDiceOddResult, 003CFF3Ch
|
||
|
||
dice_render_outcome:
|
||
mov eax, dice3d_win
|
||
test eax, eax
|
||
jz dice_render_loss_outcome
|
||
invoke DrawString8x8, 68, 150, OFFSET textDiceWin, 003CFF3Ch
|
||
invoke FormatNumber, dice3d_win, OFFSET hudNumBuffer
|
||
invoke DrawString8x8, 156, 150, OFFSET hudNumBuffer, 003CFF3Ch
|
||
invoke DrawString8x8, 188, 150, OFFSET textDiceWinMult, 003CFF3Ch
|
||
jmp dice_render_keys
|
||
|
||
dice_render_loss_outcome:
|
||
invoke DrawString8x8, 116, 150, OFFSET textDiceLose, 00FF6464h
|
||
|
||
dice_render_keys:
|
||
mov kx, 16
|
||
xor eax, eax
|
||
cmp dice3d_choice, 1
|
||
sete al
|
||
invoke DrawKeycap3D, kx, 192, OFFSET textDiceKey1, eax
|
||
add kx, eax
|
||
|
||
xor eax, eax
|
||
cmp dice3d_choice, 2
|
||
sete al
|
||
invoke DrawKeycap3D, kx, 192, OFFSET textDiceKey2, eax
|
||
add kx, eax
|
||
|
||
invoke DrawKeycap3D, kx, 192, OFFSET textDiceKeySpace, 1
|
||
add kx, eax
|
||
|
||
invoke DrawKeycap3D, kx, 192, OFFSET textKeyEsc, 0
|
||
ret
|
||
RenderDiceGame ENDP
|
||
|
||
; ==============================================================================
|
||
; IN-ENGINE 2.5D MINI-GAME: SKULLS & CUPS (НАПЁРСТКИ)
|
||
; ==============================================================================
|
||
DrawGlowingOrb PROC uses ebx esi edi, cxVal:DWORD, cyVal:DWORD
|
||
invoke DrawCircle, cxVal, cyVal, 14, 002E1E08h
|
||
invoke DrawCircle, cxVal, cyVal, 11, 00583A10h
|
||
invoke DrawCircle, cxVal, cyVal, 8, 008A581Ah
|
||
invoke DrawCircle, cxVal, cyVal, 6, 00D0B000h
|
||
invoke DrawCircle, cxVal, cyVal, 4, 00FFE000h
|
||
mov eax, cxVal
|
||
dec eax
|
||
mov edx, cyVal
|
||
dec edx
|
||
invoke DrawCircle, eax, edx, 2, 00FFFF80h
|
||
dec eax
|
||
dec edx
|
||
invoke DrawPixel, eax, edx, 00FFFFFFh
|
||
ret
|
||
DrawGlowingOrb ENDP
|
||
|
||
DrawGothicCup PROC uses ebx esi edi, x:DWORD, y:DWORD, cupId:DWORD, isLifted:DWORD, hasBall:DWORD
|
||
local liftY:DWORD
|
||
|
||
mov eax, y
|
||
cmp isLifted, 0
|
||
je @F
|
||
sub eax, 36
|
||
@@:
|
||
mov liftY, eax
|
||
|
||
; Drop shadow
|
||
cmp isLifted, 0
|
||
jne cup_shadow_lifted
|
||
mov eax, x
|
||
add eax, 6
|
||
mov edx, y
|
||
add edx, 42
|
||
invoke DrawBox, eax, edx, 36, 4, 0010040Ah
|
||
jmp cup_ball_check
|
||
cup_shadow_lifted:
|
||
mov eax, x
|
||
add eax, 10
|
||
mov edx, y
|
||
add edx, 42
|
||
invoke DrawBox, eax, edx, 28, 2, 001A0612h
|
||
|
||
cup_ball_check:
|
||
cmp isLifted, 0
|
||
je cup_body_draw
|
||
cmp hasBall, 0
|
||
je cup_body_draw
|
||
mov eax, x
|
||
add eax, 24
|
||
mov edx, y
|
||
add edx, 26
|
||
invoke DrawGlowingOrb, eax, edx
|
||
|
||
cup_body_draw:
|
||
; Base pedestal
|
||
mov eax, x
|
||
add eax, 6
|
||
mov edx, liftY
|
||
add edx, 36
|
||
invoke DrawBoxBorder, eax, edx, 36, 6, 00301A22h, 00D0B000h, 1
|
||
|
||
; Stem
|
||
mov eax, x
|
||
add eax, 18
|
||
mov edx, liftY
|
||
add edx, 28
|
||
invoke DrawBox, eax, edx, 12, 8, 00452533h
|
||
mov eax, x
|
||
add eax, 22
|
||
invoke DrawBox, eax, edx, 4, 8, 006E4055h
|
||
|
||
; Goblet Bowl
|
||
mov eax, x
|
||
add eax, 8
|
||
mov edx, liftY
|
||
add edx, 8
|
||
invoke DrawBoxBorder, eax, edx, 32, 20, 00401E2Dh, 00FFD700h, 1
|
||
|
||
mov eax, x
|
||
add eax, 14
|
||
mov edx, liftY
|
||
add edx, 10
|
||
invoke DrawBox, eax, edx, 6, 16, 00703550h
|
||
mov eax, x
|
||
add eax, 17
|
||
invoke DrawBox, eax, edx, 3, 16, 00A05078h
|
||
|
||
; Golden Rim
|
||
mov eax, x
|
||
add eax, 4
|
||
mov edx, liftY
|
||
add edx, 2
|
||
invoke DrawBoxBorder, eax, edx, 40, 7, 00200A15h, 00FFFF00h, 1
|
||
mov eax, x
|
||
add eax, 12
|
||
mov edx, liftY
|
||
add edx, 4
|
||
invoke DrawBox, eax, edx, 16, 2, 00FFFF00h
|
||
|
||
; Skull face emblem
|
||
mov eax, x
|
||
add eax, 21
|
||
mov edx, liftY
|
||
add edx, 12
|
||
invoke DrawBox, eax, edx, 6, 5, 00FFD700h
|
||
mov eax, x
|
||
add eax, 22
|
||
mov edx, liftY
|
||
add edx, 17
|
||
invoke DrawBox, eax, edx, 4, 3, 00FFD700h
|
||
mov eax, x
|
||
add eax, 22
|
||
mov edx, liftY
|
||
add edx, 14
|
||
invoke DrawPixel, eax, edx, 00200A15h
|
||
mov eax, x
|
||
add eax, 24
|
||
invoke DrawPixel, eax, edx, 00200A15h
|
||
|
||
; Cup number label
|
||
mov eax, x
|
||
add eax, 21
|
||
mov edx, liftY
|
||
add edx, 24
|
||
mov ecx, cupId
|
||
add ecx, '1'
|
||
invoke DrawChar8x8, eax, edx, ecx, 00FFFF00h
|
||
ret
|
||
DrawGothicCup ENDP
|
||
|
||
InitSkullsGame PROC
|
||
mov skulls3d_state, 0
|
||
mov skulls3d_timer, 0
|
||
mov skulls3d_win, 0
|
||
mov skulls3d_choice, 1
|
||
mov skulls3d_cup0, 0
|
||
mov skulls3d_cup1, 1
|
||
mov skulls3d_cup2, 2
|
||
invoke RandomRange3D, 3
|
||
mov skulls3d_ballPos, eax
|
||
ret
|
||
InitSkullsGame ENDP
|
||
|
||
FinalizeSkullsGuess PROC uses ebx
|
||
mov eax, skulls3d_choice
|
||
cmp eax, skulls3d_ballPos
|
||
jne skulls_guess_wrong
|
||
|
||
; Correct! 3x payout
|
||
mov eax, skulls3d_bet
|
||
imul eax, 3
|
||
add bankroll, eax
|
||
mov skulls3d_win, eax
|
||
mov skulls3d_state, 4
|
||
invoke PlaySoundA, OFFSET soundJackpot, 0, 1
|
||
ret
|
||
|
||
skulls_guess_wrong:
|
||
mov skulls3d_win, 0
|
||
mov skulls3d_state, 4
|
||
invoke PlaySoundA, OFFSET soundLose, 0, 1
|
||
ret
|
||
FinalizeSkullsGuess ENDP
|
||
|
||
HandleSkullsInput PROC
|
||
cmp skulls3d_state, 0
|
||
je skulls_handle_idle
|
||
cmp skulls3d_state, 1
|
||
je skulls_handle_show
|
||
cmp skulls3d_state, 2
|
||
je skulls_handle_shuffle
|
||
cmp skulls3d_state, 3
|
||
je skulls_handle_pick
|
||
cmp skulls3d_state, 4
|
||
je skulls_handle_reveal
|
||
ret
|
||
|
||
skulls_handle_idle:
|
||
invoke Pressed3D, 26h ; UP
|
||
test eax, eax
|
||
jnz skulls_bet_up
|
||
invoke Pressed3D, 57h ; 'W'
|
||
test eax, eax
|
||
jnz skulls_bet_up
|
||
invoke Pressed3D, 28h ; DOWN
|
||
test eax, eax
|
||
jnz skulls_bet_down
|
||
invoke Pressed3D, 53h ; 'S'
|
||
test eax, eax
|
||
jnz skulls_bet_down
|
||
invoke Pressed3D, 20h ; SPACE
|
||
test eax, eax
|
||
jnz skulls_start_game
|
||
ret
|
||
|
||
skulls_bet_up:
|
||
mov eax, skulls3d_bet
|
||
add eax, 50
|
||
cmp eax, bankroll
|
||
jle @F
|
||
mov eax, bankroll
|
||
@@:
|
||
cmp eax, 5000
|
||
jle @F
|
||
mov eax, 5000
|
||
@@:
|
||
mov skulls3d_bet, eax
|
||
invoke PlaySoundA, OFFSET soundClick, 0, 1
|
||
ret
|
||
|
||
skulls_bet_down:
|
||
mov eax, skulls3d_bet
|
||
sub eax, 50
|
||
cmp eax, 50
|
||
jge @F
|
||
mov eax, 50
|
||
@@:
|
||
mov skulls3d_bet, eax
|
||
invoke PlaySoundA, OFFSET soundClick, 0, 1
|
||
ret
|
||
|
||
skulls_start_game:
|
||
mov eax, skulls3d_bet
|
||
cmp eax, bankroll
|
||
jle @F
|
||
mov eax, bankroll
|
||
mov skulls3d_bet, eax
|
||
test eax, eax
|
||
jz skulls_input_done
|
||
@@:
|
||
mov eax, skulls3d_bet
|
||
sub bankroll, eax
|
||
invoke RandomRange3D, 3
|
||
mov skulls3d_ballPos, eax
|
||
mov skulls3d_cup0, 0
|
||
mov skulls3d_cup1, 1
|
||
mov skulls3d_cup2, 2
|
||
|
||
; Pre-generate 3 dynamic swap pairs
|
||
invoke RandomRange3D, 3
|
||
mov skulls3d_swapPair0, eax
|
||
invoke RandomRange3D, 3
|
||
mov skulls3d_swapPair1, eax
|
||
invoke RandomRange3D, 3
|
||
mov skulls3d_swapPair2, eax
|
||
|
||
mov skulls3d_state, 1
|
||
mov skulls3d_timer, 0
|
||
invoke PlaySoundA, OFFSET soundClick, 0, 1
|
||
ret
|
||
|
||
skulls_handle_show:
|
||
inc skulls3d_timer
|
||
cmp skulls3d_timer, 45
|
||
jl skulls_input_done
|
||
; Transition to Phase 2: Active Shuffle Animation
|
||
mov skulls3d_state, 2
|
||
mov skulls3d_timer, 0
|
||
invoke PlaySoundA, OFFSET soundShuffle, 0, 1
|
||
ret
|
||
|
||
skulls_handle_shuffle:
|
||
inc skulls3d_timer
|
||
cmp skulls3d_timer, 60
|
||
jl skulls_input_done
|
||
; Transition to Phase 3: Pick cup
|
||
mov skulls3d_state, 3
|
||
mov skulls3d_timer, 0
|
||
ret
|
||
|
||
skulls_handle_pick:
|
||
invoke Pressed3D, 31h ; '1'
|
||
test eax, eax
|
||
jnz skulls_pick_1
|
||
invoke Pressed3D, 32h ; '2'
|
||
test eax, eax
|
||
jnz skulls_pick_2
|
||
invoke Pressed3D, 33h ; '3'
|
||
test eax, eax
|
||
jnz skulls_pick_3
|
||
ret
|
||
|
||
skulls_pick_1:
|
||
mov skulls3d_choice, 0
|
||
call FinalizeSkullsGuess
|
||
ret
|
||
|
||
skulls_pick_2:
|
||
mov skulls3d_choice, 1
|
||
call FinalizeSkullsGuess
|
||
ret
|
||
|
||
skulls_pick_3:
|
||
mov skulls3d_choice, 2
|
||
call FinalizeSkullsGuess
|
||
ret
|
||
|
||
skulls_handle_reveal:
|
||
invoke Pressed3D, 20h
|
||
test eax, eax
|
||
jz skulls_input_done
|
||
mov skulls3d_state, 0
|
||
invoke PlaySoundA, OFFSET soundClick, 0, 1
|
||
skulls_input_done:
|
||
ret
|
||
HandleSkullsInput ENDP
|
||
|
||
RenderSkullsGame PROC uses ebx esi edi
|
||
local kx:DWORD
|
||
local passTick:DWORD, curPair:DWORD, swapSlotA:DWORD, swapSlotB:DWORD
|
||
local xA:DWORD, xB:DWORD, curXA:DWORD, curXB:DWORD, curYA:DWORD, curYB:DWORD
|
||
local distX:DWORD, dxVal:DWORD, archY:DWORD
|
||
|
||
; Mahogany & Gothic Purple table
|
||
invoke DrawBox, 0, 0, 320, 240, 00140906h
|
||
invoke DrawBoxBorder, 6, 6, 308, 228, 00300F22h, 00FFD700h, 2
|
||
|
||
; Header
|
||
invoke DrawBoxBorder, 20, 12, 280, 26, 001A0812h, 00FFD700h, 2
|
||
invoke DrawString8x8, 44, 21, OFFSET textSkullsTitle, 00FFFF00h
|
||
|
||
; Status
|
||
invoke DrawBoxBorder, 20, 44, 110, 18, 001A0812h, 00452033h, 1
|
||
invoke DrawString8x8, 24, 49, OFFSET textBankPrompt, 003CFF3Ch
|
||
invoke FormatNumber, bankroll, OFFSET hudNumBuffer
|
||
invoke DrawString8x8, 72, 49, OFFSET hudNumBuffer, 003CFF3Ch
|
||
|
||
invoke DrawBoxBorder, 190, 44, 110, 18, 001A0812h, 00452033h, 1
|
||
invoke DrawString8x8, 194, 49, OFFSET textBetPrompt, 00FFD700h
|
||
invoke FormatNumber, skulls3d_bet, OFFSET hudNumBuffer
|
||
invoke DrawString8x8, 254, 49, OFFSET hudNumBuffer, 00FFD700h
|
||
|
||
; Phase Prompts
|
||
cmp skulls3d_state, 0
|
||
jne @F
|
||
invoke DrawString8x8, 56, 62, OFFSET textSkullsPhase0, 00FFD700h
|
||
jmp skulls_draw_idle_cups
|
||
@@:
|
||
cmp skulls3d_state, 1
|
||
jne @F
|
||
invoke DrawString8x8, 56, 62, OFFSET textSkullsPhase1, 00FFFF00h
|
||
jmp skulls_draw_phase1_cups
|
||
@@:
|
||
cmp skulls3d_state, 2
|
||
jne @F
|
||
invoke DrawString8x8, 44, 62, OFFSET textSkullsPhase2, 00FFFF00h
|
||
jmp skulls_draw_animated_cups
|
||
@@:
|
||
cmp skulls3d_state, 3
|
||
jne @F
|
||
invoke DrawString8x8, 28, 62, OFFSET textSkullsPhase3, 00FFFF00h
|
||
jmp skulls_draw_idle_cups
|
||
@@:
|
||
; Phase 4: Reveal outcome
|
||
mov eax, skulls3d_win
|
||
test eax, eax
|
||
jz skulls_reveal_loss_text
|
||
invoke DrawString8x8, 40, 62, OFFSET textSkullsWin, 003CFF3Ch
|
||
invoke FormatNumber, skulls3d_win, OFFSET hudNumBuffer
|
||
invoke DrawString8x8, 136, 62, OFFSET hudNumBuffer, 003CFF3Ch
|
||
invoke DrawString8x8, 168, 62, OFFSET textSkullsWinMult, 003CFF3Ch
|
||
jmp skulls_draw_reveal_cups
|
||
|
||
skulls_reveal_loss_text:
|
||
invoke DrawString8x8, 40, 62, OFFSET textSkullsLose, 00FF6464h
|
||
jmp skulls_draw_reveal_cups
|
||
|
||
skulls_draw_idle_cups:
|
||
; Draw resting cups at static slots: Slot 0 (X=36), Slot 1 (X=136), Slot 2 (X=236)
|
||
invoke DrawGothicCup, 36, 114, skulls3d_cup0, 0, 0
|
||
invoke DrawGothicCup, 136, 114, skulls3d_cup1, 0, 0
|
||
invoke DrawGothicCup, 236, 114, skulls3d_cup2, 0, 0
|
||
jmp skulls_render_controls
|
||
|
||
skulls_draw_phase1_cups:
|
||
; Draw with golden ball showing under starting cup
|
||
mov ebx, 0
|
||
mov edx, 0
|
||
cmp skulls3d_ballPos, 0
|
||
jne @F
|
||
mov ebx, 1
|
||
mov edx, 1
|
||
@@:
|
||
invoke DrawGothicCup, 36, 114, skulls3d_cup0, ebx, edx
|
||
|
||
mov ebx, 0
|
||
mov edx, 0
|
||
cmp skulls3d_ballPos, 1
|
||
jne @F
|
||
mov ebx, 1
|
||
mov edx, 1
|
||
@@:
|
||
invoke DrawGothicCup, 136, 114, skulls3d_cup1, ebx, edx
|
||
|
||
mov ebx, 0
|
||
mov edx, 0
|
||
cmp skulls3d_ballPos, 2
|
||
jne @F
|
||
mov ebx, 1
|
||
mov edx, 1
|
||
@@:
|
||
invoke DrawGothicCup, 236, 114, skulls3d_cup2, ebx, edx
|
||
jmp skulls_render_controls
|
||
|
||
skulls_draw_animated_cups:
|
||
; 60 frames = 3 passes of 20 frames
|
||
mov eax, skulls3d_timer
|
||
cmp eax, 20
|
||
jbe pass_0
|
||
cmp eax, 40
|
||
jbe pass_1
|
||
sub eax, 41
|
||
mov passTick, eax
|
||
mov eax, skulls3d_swapPair2
|
||
mov curPair, eax
|
||
jmp setup_pass
|
||
|
||
pass_0:
|
||
dec eax
|
||
mov passTick, eax
|
||
mov eax, skulls3d_swapPair0
|
||
mov curPair, eax
|
||
jmp setup_pass
|
||
|
||
pass_1:
|
||
sub eax, 21
|
||
mov passTick, eax
|
||
mov eax, skulls3d_swapPair1
|
||
mov curPair, eax
|
||
|
||
setup_pass:
|
||
; curPair determines swap pair:
|
||
; 0: swap slot 0 (X=36) and slot 1 (X=136)
|
||
; 1: swap slot 1 (X=136) and slot 2 (X=236)
|
||
; 2: swap slot 0 (X=36) and slot 2 (X=236)
|
||
cmp curPair, 1
|
||
je pair_1
|
||
cmp curPair, 2
|
||
je pair_2
|
||
mov swapSlotA, 0
|
||
mov swapSlotB, 1
|
||
mov xA, 36
|
||
mov xB, 136
|
||
jmp calc_coords
|
||
pair_1:
|
||
mov swapSlotA, 1
|
||
mov swapSlotB, 2
|
||
mov xA, 136
|
||
mov xB, 236
|
||
jmp calc_coords
|
||
pair_2:
|
||
mov swapSlotA, 0
|
||
mov swapSlotB, 2
|
||
mov xA, 36
|
||
mov xB, 236
|
||
|
||
calc_coords:
|
||
; distX = xB - xA
|
||
mov eax, xB
|
||
sub eax, xA
|
||
mov distX, eax
|
||
|
||
; dxVal = (distX * passTick) / 20
|
||
mov eax, distX
|
||
imul eax, passTick
|
||
xor edx, edx
|
||
mov ecx, 20
|
||
div ecx
|
||
mov dxVal, eax
|
||
|
||
; curXA = xA + dxVal
|
||
mov eax, xA
|
||
add eax, dxVal
|
||
mov curXA, eax
|
||
|
||
; curXB = xB - dxVal
|
||
mov eax, xB
|
||
sub eax, dxVal
|
||
mov curXB, eax
|
||
|
||
; archY = (passTick * (20 - passTick)) / 10
|
||
mov eax, passTick
|
||
mov ecx, 20
|
||
sub ecx, eax
|
||
imul eax, ecx
|
||
xor edx, edx
|
||
mov ecx, 10
|
||
div ecx
|
||
mov archY, eax
|
||
|
||
; Cup A hops UP: 114 - archY
|
||
mov eax, 114
|
||
sub eax, archY
|
||
mov curYA, eax
|
||
|
||
; Cup B hops DOWN: 114 + archY
|
||
mov eax, 114
|
||
add eax, archY
|
||
mov curYB, eax
|
||
|
||
; Check if pass ended (frame 19): swap ball position and cups
|
||
cmp passTick, 19
|
||
jne draw_active_shuffle
|
||
|
||
; Swap ball position if involved
|
||
mov eax, skulls3d_ballPos
|
||
cmp eax, swapSlotA
|
||
jne check_ball_b
|
||
mov edx, swapSlotB
|
||
mov skulls3d_ballPos, edx
|
||
jmp swap_slot_identities
|
||
check_ball_b:
|
||
cmp eax, swapSlotB
|
||
jne swap_slot_identities
|
||
mov edx, swapSlotA
|
||
mov skulls3d_ballPos, edx
|
||
|
||
swap_slot_identities:
|
||
cmp curPair, 1
|
||
je swap_ids_1_2
|
||
cmp curPair, 2
|
||
je swap_ids_0_2
|
||
; swap 0 and 1
|
||
mov eax, skulls3d_cup0
|
||
xchg eax, skulls3d_cup1
|
||
mov skulls3d_cup0, eax
|
||
jmp swap_sound_tick
|
||
swap_ids_1_2:
|
||
mov eax, skulls3d_cup1
|
||
xchg eax, skulls3d_cup2
|
||
mov skulls3d_cup1, eax
|
||
jmp swap_sound_tick
|
||
swap_ids_0_2:
|
||
mov eax, skulls3d_cup0
|
||
xchg eax, skulls3d_cup2
|
||
mov skulls3d_cup0, eax
|
||
|
||
swap_sound_tick:
|
||
invoke PlaySoundA, OFFSET soundShuffle, 0, 1
|
||
|
||
draw_active_shuffle:
|
||
; Draw stationary cup
|
||
cmp curPair, 1
|
||
je draw_stat_cup0
|
||
cmp curPair, 2
|
||
je draw_stat_cup1
|
||
; Stationary cup is slot 2 (X=236)
|
||
invoke DrawGothicCup, 236, 114, skulls3d_cup2, 0, 0
|
||
jmp draw_moving_cups
|
||
draw_stat_cup0:
|
||
; Stationary cup is slot 0 (X=36)
|
||
invoke DrawGothicCup, 36, 114, skulls3d_cup0, 0, 0
|
||
jmp draw_moving_cups
|
||
draw_stat_cup1:
|
||
; Stationary cup is slot 1 (X=136)
|
||
invoke DrawGothicCup, 136, 114, skulls3d_cup1, 0, 0
|
||
|
||
draw_moving_cups:
|
||
; Moving Cup A and Moving Cup B
|
||
cmp curPair, 1
|
||
je ids_pair_1
|
||
cmp curPair, 2
|
||
je ids_pair_2
|
||
mov eax, skulls3d_cup0
|
||
mov ebx, skulls3d_cup1
|
||
jmp draw_the_pair
|
||
ids_pair_1:
|
||
mov eax, skulls3d_cup1
|
||
mov ebx, skulls3d_cup2
|
||
jmp draw_the_pair
|
||
ids_pair_2:
|
||
mov eax, skulls3d_cup0
|
||
mov ebx, skulls3d_cup2
|
||
|
||
draw_the_pair:
|
||
push ebx
|
||
invoke DrawGothicCup, curXA, curYA, eax, 0, 0
|
||
pop ebx
|
||
invoke DrawGothicCup, curXB, curYB, ebx, 0, 0
|
||
jmp skulls_render_controls
|
||
|
||
skulls_draw_reveal_cups:
|
||
; Reveal Phase: lift chosen cup and lift actual ball cup if different
|
||
; Slot 0
|
||
mov ebx, 0
|
||
mov edx, 0
|
||
cmp skulls3d_choice, 0
|
||
je slot0_is_lifted
|
||
cmp skulls3d_ballPos, 0
|
||
jne @F
|
||
slot0_is_lifted:
|
||
mov ebx, 1
|
||
cmp skulls3d_ballPos, 0
|
||
sete dl
|
||
@@:
|
||
invoke DrawGothicCup, 36, 114, skulls3d_cup0, ebx, edx
|
||
|
||
; Slot 1
|
||
mov ebx, 0
|
||
mov edx, 0
|
||
cmp skulls3d_choice, 1
|
||
je slot1_is_lifted
|
||
cmp skulls3d_ballPos, 1
|
||
jne @F
|
||
slot1_is_lifted:
|
||
mov ebx, 1
|
||
cmp skulls3d_ballPos, 1
|
||
sete dl
|
||
@@:
|
||
invoke DrawGothicCup, 136, 114, skulls3d_cup1, ebx, edx
|
||
|
||
; Slot 2
|
||
mov ebx, 0
|
||
mov edx, 0
|
||
cmp skulls3d_choice, 2
|
||
je slot2_is_lifted
|
||
cmp skulls3d_ballPos, 2
|
||
jne @F
|
||
slot2_is_lifted:
|
||
mov ebx, 1
|
||
cmp skulls3d_ballPos, 2
|
||
sete dl
|
||
@@:
|
||
invoke DrawGothicCup, 236, 114, skulls3d_cup2, ebx, edx
|
||
|
||
skulls_render_controls:
|
||
; Cup selection slot labels [1], [2], [3]
|
||
invoke DrawString8x8, 54, 168, OFFSET textSkullsKey1, 00D0D8E0h
|
||
invoke DrawString8x8, 150, 168, OFFSET textSkullsKey2, 00D0D8E0h
|
||
invoke DrawString8x8, 250, 168, OFFSET textSkullsKey3, 00D0D8E0h
|
||
|
||
; Keycaps
|
||
mov kx, 16
|
||
xor eax, eax
|
||
cmp skulls3d_state, 3
|
||
je key1_active
|
||
cmp skulls3d_choice, 0
|
||
sete al
|
||
jmp draw_key1
|
||
key1_active:
|
||
mov eax, 1
|
||
draw_key1:
|
||
invoke DrawKeycap3D, kx, 192, OFFSET textSkullsKey1, eax
|
||
add kx, eax
|
||
|
||
xor eax, eax
|
||
cmp skulls3d_state, 3
|
||
je key2_active
|
||
cmp skulls3d_choice, 1
|
||
sete al
|
||
jmp draw_key2
|
||
key2_active:
|
||
mov eax, 1
|
||
draw_key2:
|
||
invoke DrawKeycap3D, kx, 192, OFFSET textSkullsKey2, eax
|
||
add kx, eax
|
||
|
||
xor eax, eax
|
||
cmp skulls3d_state, 3
|
||
je key3_active
|
||
cmp skulls3d_choice, 2
|
||
sete al
|
||
jmp draw_key3
|
||
key3_active:
|
||
mov eax, 1
|
||
draw_key3:
|
||
invoke DrawKeycap3D, kx, 192, OFFSET textSkullsKey3, eax
|
||
add kx, eax
|
||
|
||
xor eax, eax
|
||
cmp skulls3d_state, 0
|
||
je start_active
|
||
cmp skulls3d_state, 4
|
||
je start_active
|
||
jmp draw_start_key
|
||
start_active:
|
||
mov eax, 1
|
||
draw_start_key:
|
||
invoke DrawKeycap3D, kx, 192, OFFSET textSkullsKeySpace, eax
|
||
add kx, eax
|
||
|
||
invoke DrawKeycap3D, kx, 192, OFFSET textKeyEsc, 0
|
||
ret
|
||
RenderSkullsGame ENDP
|
||
|
||
InitSkillGame PROC
|
||
mov skill3d_state, 0
|
||
mov skill3d_timer, 0
|
||
mov skill3d_hits, 0
|
||
mov skill3d_misses, 0
|
||
mov skill3d_needle, 55
|
||
mov skill3d_speed, 4
|
||
mov skill3d_dir, 1
|
||
mov skill3d_last_result, 0
|
||
mov skill3d_win_amount, 0
|
||
|
||
; Randomize initial zone: 80 + RandomRange(90) -> 80..170
|
||
invoke RandomRange3D, 90
|
||
add eax, 80
|
||
mov skill3d_zone_start, eax
|
||
|
||
; Great zone: start + 20 + RandomRange(12)
|
||
invoke RandomRange3D, 12
|
||
add eax, skill3d_zone_start
|
||
add eax, 20
|
||
mov skill3d_great_start, eax
|
||
ret
|
||
InitSkillGame ENDP
|
||
|
||
HandleSkillInput PROC uses ebx esi
|
||
mov eax, skill3d_state
|
||
cmp eax, 0
|
||
je skill_handle_ready
|
||
cmp eax, 1
|
||
je skill_handle_active
|
||
cmp eax, 2
|
||
je skill_handle_round_wait
|
||
cmp eax, 3
|
||
je skill_handle_round_wait
|
||
cmp eax, 4
|
||
je skill_handle_end_wait
|
||
cmp eax, 5
|
||
je skill_handle_end_wait
|
||
ret
|
||
|
||
skill_handle_ready:
|
||
invoke Pressed3D, 26h ; UP
|
||
test eax, eax
|
||
jnz skill_bet_up
|
||
invoke Pressed3D, 57h ; 'W'
|
||
test eax, eax
|
||
jnz skill_bet_up
|
||
invoke Pressed3D, 28h ; DOWN
|
||
test eax, eax
|
||
jnz skill_bet_down
|
||
invoke Pressed3D, 53h ; 'S'
|
||
test eax, eax
|
||
jnz skill_bet_down
|
||
jmp skill_check_start
|
||
|
||
skill_bet_up:
|
||
mov eax, skill3d_bet
|
||
add eax, 50
|
||
cmp eax, bankroll
|
||
jle @F
|
||
mov eax, bankroll
|
||
@@:
|
||
cmp eax, 5000
|
||
jle @F
|
||
mov eax, 5000
|
||
@@:
|
||
mov skill3d_bet, eax
|
||
invoke PlaySoundA, OFFSET soundClick, 0, 1
|
||
ret
|
||
|
||
skill_bet_down:
|
||
mov eax, skill3d_bet
|
||
sub eax, 50
|
||
cmp eax, 50
|
||
jge @F
|
||
mov eax, 50
|
||
@@:
|
||
mov skill3d_bet, eax
|
||
invoke PlaySoundA, OFFSET soundClick, 0, 1
|
||
ret
|
||
|
||
skill_check_start:
|
||
invoke Pressed3D, 20h ; SPACE
|
||
test eax, eax
|
||
jz skill_input_done
|
||
|
||
; Deduct bet on game start if beginning of run
|
||
mov eax, skill3d_hits
|
||
or eax, skill3d_misses
|
||
jnz @F
|
||
mov eax, skill3d_bet
|
||
cmp eax, bankroll
|
||
jle skill_has_funds
|
||
mov eax, bankroll
|
||
mov skill3d_bet, eax
|
||
test eax, eax
|
||
jz skill_input_done
|
||
skill_has_funds:
|
||
mov eax, skill3d_bet
|
||
sub bankroll, eax
|
||
@@:
|
||
mov skill3d_state, 1
|
||
mov skill3d_needle, 55
|
||
mov skill3d_dir, 1
|
||
invoke PlaySoundA, OFFSET soundClick, 0, 1
|
||
ret
|
||
|
||
skill_handle_active:
|
||
; Move needle smoothly
|
||
mov eax, skill3d_needle
|
||
mov edx, skill3d_speed
|
||
cmp skill3d_dir, 1
|
||
je skill_move_right
|
||
sub eax, edx
|
||
cmp eax, 52
|
||
jge skill_update_needle
|
||
mov eax, 52
|
||
mov skill3d_dir, 1
|
||
jmp skill_update_needle
|
||
skill_move_right:
|
||
add eax, edx
|
||
cmp eax, 268
|
||
jle skill_update_needle
|
||
mov eax, 268
|
||
mov skill3d_dir, -1
|
||
skill_update_needle:
|
||
mov skill3d_needle, eax
|
||
|
||
; Check SPACE pressed (Reaction Hit Attempt!)
|
||
invoke Pressed3D, 20h
|
||
test eax, eax
|
||
jz skill_input_done
|
||
|
||
; Is needle in Great Sweet Spot?
|
||
mov eax, skill3d_needle
|
||
mov edx, skill3d_great_start
|
||
cmp eax, edx
|
||
jl check_success_zone
|
||
add edx, skill3d_great_width
|
||
cmp eax, edx
|
||
jg check_success_zone
|
||
|
||
; GREAT HIT!
|
||
mov skill3d_last_result, 2
|
||
add skill3d_hits, 2
|
||
mov skill3d_state, 2
|
||
mov skill3d_timer, 40
|
||
invoke PlaySoundA, OFFSET soundCoinDing, 0, 1
|
||
jmp skill_check_finish_round
|
||
|
||
check_success_zone:
|
||
mov eax, skill3d_needle
|
||
mov edx, skill3d_zone_start
|
||
cmp eax, edx
|
||
jl skill_was_miss
|
||
add edx, skill3d_zone_width
|
||
cmp eax, edx
|
||
jg skill_was_miss
|
||
|
||
; NORMAL HIT!
|
||
mov skill3d_last_result, 1
|
||
inc skill3d_hits
|
||
mov skill3d_state, 2
|
||
mov skill3d_timer, 40
|
||
invoke PlaySoundA, OFFSET soundVictory, 0, 1
|
||
jmp skill_check_finish_round
|
||
|
||
skill_was_miss:
|
||
; MISS!
|
||
mov skill3d_last_result, 0
|
||
inc skill3d_misses
|
||
mov skill3d_state, 3
|
||
mov skill3d_timer, 45
|
||
invoke PlaySoundA, OFFSET soundLose, 0, 1
|
||
|
||
skill_check_finish_round:
|
||
cmp skill3d_hits, 5
|
||
jge skill_game_escaped
|
||
cmp skill3d_misses, 3
|
||
jge skill_game_lost
|
||
ret
|
||
|
||
skill_game_escaped:
|
||
mov skill3d_state, 4
|
||
mov skill3d_timer, 0
|
||
; Payout: 3x total return (+$2x bet profit)
|
||
mov eax, skill3d_bet
|
||
imul eax, 3
|
||
add bankroll, eax
|
||
mov eax, skill3d_bet
|
||
shl eax, 1
|
||
mov skill3d_win_amount, eax
|
||
invoke PlaySoundA, OFFSET soundJackpot, 0, 1
|
||
ret
|
||
|
||
skill_game_lost:
|
||
mov skill3d_state, 5
|
||
mov skill3d_timer, 0
|
||
invoke PlaySoundA, OFFSET soundLose, 0, 1
|
||
ret
|
||
|
||
skill_handle_round_wait:
|
||
dec skill3d_timer
|
||
cmp skill3d_timer, 0
|
||
jg skill_input_done
|
||
|
||
; Next round setup
|
||
invoke RandomRange3D, 90
|
||
add eax, 80
|
||
mov skill3d_zone_start, eax
|
||
|
||
invoke RandomRange3D, 12
|
||
add eax, skill3d_zone_start
|
||
add eax, 20
|
||
mov skill3d_great_start, eax
|
||
|
||
mov eax, skill3d_hits
|
||
shr eax, 1
|
||
add eax, 4
|
||
mov skill3d_speed, eax
|
||
mov skill3d_state, 1
|
||
ret
|
||
|
||
skill_handle_end_wait:
|
||
invoke Pressed3D, 20h
|
||
test eax, eax
|
||
jz skill_input_done
|
||
call InitSkillGame
|
||
ret
|
||
|
||
skill_input_done:
|
||
ret
|
||
HandleSkillInput ENDP
|
||
|
||
RenderSkillGame PROC uses ebx esi edi
|
||
local kx:DWORD
|
||
local tx:DWORD
|
||
|
||
; Industrial Steel bezel
|
||
invoke DrawBox, 0, 0, 320, 240, 00121416h
|
||
invoke DrawBoxBorder, 6, 6, 308, 228, 001A1D20h, 00FFD700h, 2
|
||
|
||
; Header
|
||
invoke DrawBoxBorder, 20, 12, 280, 26, 00121418h, 00FFD700h, 2
|
||
invoke DrawString8x8, 40, 21, OFFSET textSkillTitle, 00FFFF00h
|
||
|
||
; Status
|
||
invoke DrawBoxBorder, 20, 44, 110, 18, 00121418h, 002A3540h, 1
|
||
invoke DrawString8x8, 24, 49, OFFSET textBankPrompt, 003CFF3Ch
|
||
invoke FormatNumber, bankroll, OFFSET hudNumBuffer
|
||
invoke DrawString8x8, 72, 49, OFFSET hudNumBuffer, 003CFF3Ch
|
||
|
||
invoke DrawBoxBorder, 190, 44, 110, 18, 00121418h, 002A3540h, 1
|
||
invoke DrawString8x8, 194, 49, OFFSET textBetPrompt, 00FFD700h
|
||
invoke FormatNumber, skill3d_bet, OFFSET hudNumBuffer
|
||
invoke DrawString8x8, 254, 49, OFFSET hudNumBuffer, 00FFD700h
|
||
|
||
; Survivor Progress
|
||
invoke DrawString8x8, 24, 70, OFFSET textSkillHitsHdr, 003CFF3Ch
|
||
invoke FormatNumber, skill3d_hits, OFFSET hudNumBuffer
|
||
invoke DrawString8x8, 64, 70, OFFSET hudNumBuffer, 003CFF3Ch
|
||
|
||
invoke DrawString8x8, 180, 70, OFFSET textSkillMissHdr, 00FF6464h
|
||
invoke FormatNumber, skill3d_misses, OFFSET hudNumBuffer
|
||
invoke DrawString8x8, 240, 70, OFFSET hudNumBuffer, 00FF6464h
|
||
|
||
; Dial Frame (Track: X=50..270, Y=102..134)
|
||
invoke DrawBoxBorder, 50, 102, 220, 32, 000F1114h, 00404855h, 2
|
||
|
||
; Calibrated ticks
|
||
mov tx, 60
|
||
skill_ticks_loop:
|
||
cmp tx, 260
|
||
jge skill_draw_zones
|
||
invoke DrawBox, tx, 104, 1, 6, 00303845h
|
||
invoke DrawBox, tx, 126, 1, 6, 00303845h
|
||
add tx, 12
|
||
jmp skill_ticks_loop
|
||
|
||
skill_draw_zones:
|
||
; Normal Success Zone (Green)
|
||
invoke DrawBoxBorder, skill3d_zone_start, 106, skill3d_zone_width, 24, 00155020h, 003CFF3Ch, 1
|
||
|
||
; Great Zone (Gold)
|
||
invoke DrawBoxBorder, skill3d_great_start, 106, skill3d_great_width, 24, 00FFD700h, 00FFFF00h, 1
|
||
|
||
; Pointer / Needle at skill3d_needle
|
||
mov eax, skill3d_needle
|
||
dec eax
|
||
invoke DrawBox, eax, 98, 3, 40, 00FFFFFFh
|
||
mov eax, skill3d_needle
|
||
sub eax, 2
|
||
invoke DrawBox, eax, 96, 5, 2, 00FF3030h
|
||
invoke DrawBox, eax, 138, 5, 2, 00FF3030h
|
||
|
||
; Center prompts / outcome
|
||
cmp skill3d_state, 0
|
||
jne @F
|
||
invoke DrawString8x8, 52, 150, OFFSET textSkillReadyMsg, 00FFD700h
|
||
invoke DrawString8x8, 76, 166, OFFSET textSkillPrompt, 00D0D8E0h
|
||
jmp skill_render_keys
|
||
@@:
|
||
cmp skill3d_state, 1
|
||
jne @F
|
||
invoke DrawString8x8, 76, 150, OFFSET textSkillPrompt, 00FFFF00h
|
||
jmp skill_render_keys
|
||
@@:
|
||
cmp skill3d_state, 2
|
||
jne @F
|
||
cmp skill3d_last_result, 2
|
||
jne skill_normal_hit_text
|
||
invoke DrawString8x8, 36, 150, OFFSET textSkillGreatMsg, 00FFFF00h
|
||
jmp skill_render_keys
|
||
skill_normal_hit_text:
|
||
invoke DrawString8x8, 64, 150, OFFSET textSkillHitMsg, 003CFF3Ch
|
||
jmp skill_render_keys
|
||
@@:
|
||
cmp skill3d_state, 3
|
||
jne @F
|
||
invoke DrawString8x8, 88, 150, OFFSET textSkillMissMsg, 00FF6464h
|
||
jmp skill_render_keys
|
||
@@:
|
||
cmp skill3d_state, 4
|
||
jne @F
|
||
invoke DrawString8x8, 48, 150, OFFSET textSkillEscape, 003CFF3Ch
|
||
invoke FormatNumber, skill3d_win_amount, OFFSET hudNumBuffer
|
||
invoke DrawString8x8, 240, 150, OFFSET hudNumBuffer, 003CFF3Ch
|
||
invoke DrawString8x8, 64, 166, OFFSET textSkullsAgain, 00FFD700h
|
||
jmp skill_render_keys
|
||
@@:
|
||
invoke DrawString8x8, 44, 150, OFFSET textSkillLost, 00FF6464h
|
||
invoke DrawString8x8, 64, 166, OFFSET textSkullsAgain, 00FFD700h
|
||
|
||
skill_render_keys:
|
||
mov kx, 16
|
||
invoke DrawKeycap3D, kx, 192, OFFSET textSkillKeySpace, 1
|
||
add kx, eax
|
||
|
||
invoke DrawKeycap3D, kx, 192, OFFSET textSkillKeyBet, 0
|
||
add kx, eax
|
||
|
||
invoke DrawKeycap3D, kx, 192, OFFSET textKeyEsc, 0
|
||
ret
|
||
RenderSkillGame ENDP
|
||
|
||
"""
|
||
|
||
raw_content = raw_content[:pos_games_start] + new_games_code.encode('cp1251') + raw_content[pos_player_input:]
|
||
print("[OK] Replaced procedural drawing and games code")
|
||
|
||
# 6. Update Trigger3DInteraction for INTERACT_SKILL_CHECK
|
||
old_skill_trigger = b"""check_target_skill:
|
||
cmp eax, INTERACT_SKILL_CHECK
|
||
jne check_target_buckshot
|
||
invoke LaunchClassicGame, OFFSET GameSkillCheck, 11, OFFSET szTitleSkillCheck
|
||
ret"""
|
||
|
||
new_skill_trigger = b"""check_target_skill:
|
||
cmp eax, INTERACT_SKILL_CHECK
|
||
jne check_target_buckshot
|
||
call InitSkillGame
|
||
mov engineMode, MODE_SKILL
|
||
ret"""
|
||
|
||
if old_skill_trigger in raw_content:
|
||
raw_content = raw_content.replace(old_skill_trigger, new_skill_trigger)
|
||
print("[OK] Updated Trigger3DInteraction for INTERACT_SKILL_CHECK")
|
||
else:
|
||
print("[WARN] old_skill_trigger pattern not found verbatim")
|
||
|
||
# 7. Update leave_table: for MODE_SKILL
|
||
old_leave = b""" cmp skulls3d_state, 1
|
||
je engine_tick
|
||
cmp skulls3d_state, 2
|
||
je engine_tick
|
||
mov engineMode, MODE_WALK"""
|
||
|
||
new_leave = b""" cmp skulls3d_state, 1
|
||
je engine_tick
|
||
cmp skulls3d_state, 2
|
||
je engine_tick
|
||
cmp engineMode, MODE_SKILL
|
||
jne @F
|
||
cmp skill3d_state, 1
|
||
je engine_tick
|
||
@@:
|
||
mov engineMode, MODE_WALK"""
|
||
|
||
if old_leave in raw_content:
|
||
raw_content = raw_content.replace(old_leave, new_leave)
|
||
print("[OK] Updated leave_table: for MODE_SKILL")
|
||
else:
|
||
print("[WARN] old_leave pattern not found verbatim")
|
||
|
||
# 8. Update engine_loop dispatch for MODE_SKILL
|
||
old_dispatch = b"""check_skulls_mode:
|
||
cmp engineMode, MODE_SKULLS
|
||
jne present_frame
|
||
call HandleSkullsInput
|
||
call RenderSkullsGame
|
||
jmp present_frame"""
|
||
|
||
new_dispatch = b"""check_skulls_mode:
|
||
cmp engineMode, MODE_SKULLS
|
||
jne check_skill_mode
|
||
call HandleSkullsInput
|
||
call RenderSkullsGame
|
||
jmp present_frame
|
||
check_skill_mode:
|
||
cmp engineMode, MODE_SKILL
|
||
jne present_frame
|
||
call HandleSkillInput
|
||
call RenderSkillGame
|
||
jmp present_frame"""
|
||
|
||
if old_dispatch in raw_content:
|
||
raw_content = raw_content.replace(old_dispatch, new_dispatch)
|
||
print("[OK] Updated engine_loop dispatch for MODE_SKILL")
|
||
else:
|
||
print("[WARN] old_dispatch pattern not found verbatim")
|
||
|
||
# 9. Global replacement of reversed cyan color constants to proper 00RRGGBBh
|
||
color_replacements = [
|
||
(b'0000FFFFh', b'00FFFF00h'), # Cyan -> Pure Yellow
|
||
(b'0000D7FFh', b'00FFD700h'), # Sky Blue -> Pure Gold
|
||
(b'0000A0D0h', b'00D0A000h'), # Amber Gold
|
||
(b'0000E0FFh', b'00FFE000h'), # Bright Amber
|
||
(b'00007A9Ah', b'009A7A00h'), # Bronze / Dark Gold
|
||
(b'000080A0h', b'00A08000h'),
|
||
(b'0000B0D0h', b'00D0B000h'),
|
||
(b'0000B0E0h', b'00E0B000h'),
|
||
(b'000000FFh', b'00FF2020h'), # Pure Blue -> Bright Ruby Red
|
||
(b'008080FFh', b'00FF6464h'), # Light Periwinkle -> Soft Coral Red
|
||
(b'001515B8h', b'00B81515h'), # Blue chip -> Red Clay Casino Chip
|
||
(b'001515C8h', b'00C81515h'), # Blue pips -> Ruby Red Dice Pips
|
||
]
|
||
|
||
for old_c, new_c in color_replacements:
|
||
count = raw_content.count(old_c)
|
||
if count > 0:
|
||
raw_content = raw_content.replace(old_c, new_c)
|
||
print(f"[OK] Replaced {old_c.decode('ascii')} -> {new_c.decode('ascii')} ({count} occurrences)")
|
||
|
||
# Write back to casino3d.inc
|
||
with open(CASINO_INC, 'wb') as f:
|
||
f.write(raw_content)
|
||
|
||
print(f"[SUCCESS] casino3d.inc successfully patched! ({len(raw_content)} bytes)")
|