feat: rework artifacts and tower relics
Extend profiles from 280 to 312 bytes with legacy compatibility. Keep tower relics run-local and share the profile bankroll.
This commit is contained in:
parent
2aa6c4cff4
commit
eaac8b861e
47 changed files with 1946 additions and 278 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -17,6 +17,9 @@ __pycache__/
|
||||||
|
|
||||||
# Generated build/test output; keep packaging source and shipping exe files.
|
# Generated build/test output; keep packaging source and shipping exe files.
|
||||||
/build/actions/
|
/build/actions/
|
||||||
|
/build/artifacts/
|
||||||
|
/build/hell-tower/
|
||||||
|
/build/test-deps/
|
||||||
/build/arrival/
|
/build/arrival/
|
||||||
/build/billiards/
|
/build/billiards/
|
||||||
/build/card-ranks/
|
/build/card-ranks/
|
||||||
|
|
|
||||||
BIN
bin/poker.exe
BIN
bin/poker.exe
Binary file not shown.
|
|
@ -8,7 +8,7 @@ namespace AssemblerCasinoLauncher
|
||||||
{
|
{
|
||||||
static class Program
|
static class Program
|
||||||
{
|
{
|
||||||
const string ExpectedPokerSha256 = "755067F511E82184081FE3D06391FCF872EC058AB224CA6ED8C1DB0A2990E1BA";
|
const string ExpectedPokerSha256 = "A3A35CB3C9F21FB0F29F2849B01DFEE914AEA7830ED7540FFEF24C6A8467F44A";
|
||||||
|
|
||||||
[STAThread]
|
[STAThread]
|
||||||
static void Main()
|
static void Main()
|
||||||
|
|
|
||||||
Binary file not shown.
19
casino3d.inc
19
casino3d.inc
|
|
@ -3283,6 +3283,7 @@ dice_check_win:
|
||||||
shl eax, 1
|
shl eax, 1
|
||||||
add bankroll, eax
|
add bankroll, eax
|
||||||
mov dice3d_win, eax
|
mov dice3d_win, eax
|
||||||
|
invoke TriggerCharmWinBonus,dice3d_bet
|
||||||
mov dice3d_state, 2
|
mov dice3d_state, 2
|
||||||
invoke PlayCasinoSound3D, OFFSET soundRoundWin, 0, 1
|
invoke PlayCasinoSound3D, OFFSET soundRoundWin, 0, 1
|
||||||
invoke NpcRecordRound3D,8,1
|
invoke NpcRecordRound3D,8,1
|
||||||
|
|
@ -5373,12 +5374,12 @@ check_slots_mode:
|
||||||
call RenderJackbox3D
|
call RenderJackbox3D
|
||||||
jmp present_frame
|
jmp present_frame
|
||||||
check_jackbox_done:
|
check_jackbox_done:
|
||||||
cmp engineMode,MODE_DARTS
|
cmp engineMode,MODE_DARTS
|
||||||
jne check_darts_done
|
jne check_darts_done
|
||||||
call HandleDarts3D
|
call HandleDarts3D
|
||||||
call RenderDarts3D
|
call RenderDarts3D
|
||||||
jmp present_frame
|
jmp present_frame
|
||||||
check_darts_done:
|
check_darts_done:
|
||||||
cmp engineMode,MODE_FORTUNE
|
cmp engineMode,MODE_FORTUNE
|
||||||
jne @F
|
jne @F
|
||||||
call HandleFortuneDialog3D
|
call HandleFortuneDialog3D
|
||||||
|
|
@ -5659,7 +5660,7 @@ engine_shutdown:
|
||||||
call SaveProgress3D
|
call SaveProgress3D
|
||||||
invoke PlayCasinoSound3D, 0, 0, 0
|
invoke PlayCasinoSound3D, 0, 0, 0
|
||||||
call FreeRussianAssets3D
|
call FreeRussianAssets3D
|
||||||
call FreeDarts3D
|
call FreeDarts3D
|
||||||
call FreeStartupAssets3D
|
call FreeStartupAssets3D
|
||||||
call FreeCardTableAssets3D
|
call FreeCardTableAssets3D
|
||||||
call FreeBuckshotAssets3D
|
call FreeBuckshotAssets3D
|
||||||
|
|
@ -5687,3 +5688,7 @@ IFDEF CASINO_ACTION_TEST
|
||||||
include tools\tests\casino_actions_test.inc
|
include tools\tests\casino_actions_test.inc
|
||||||
ENDIF
|
ENDIF
|
||||||
|
|
||||||
|
|
||||||
|
IFDEF ARTIFACT_TEST
|
||||||
|
include tools\tests\artifacts_test.inc
|
||||||
|
ENDIF
|
||||||
|
|
|
||||||
BIN
dist/Assembler Casino.exe
vendored
BIN
dist/Assembler Casino.exe
vendored
Binary file not shown.
97
docs/ARTIFACTS_AND_TOWER.md
Normal file
97
docs/ARTIFACTS_AND_TOWER.md
Normal file
|
|
@ -0,0 +1,97 @@
|
||||||
|
# Артефакты и Адская башня
|
||||||
|
|
||||||
|
## Магазин Сидоровича
|
||||||
|
|
||||||
|
Магазин открывается на вкладке артефактов. Стрелки вверх/вниз выбирают предмет,
|
||||||
|
`E` включает или выключает эффект. Покупка требует двух нажатий `Enter`:
|
||||||
|
первое запрашивает подтверждение, второе оплачивает набор. Смена выбранного
|
||||||
|
предмета отменяет подтверждение. Поддерживается мышь. `Tab` возвращает рубашки,
|
||||||
|
`Esc` — холл.
|
||||||
|
|
||||||
|
| Артефакт | Цена набора | Зарядов | Эффект |
|
||||||
|
|---|---:|---:|---|
|
||||||
|
| Клевер | 900 | 3 | Возвращает 50% фактической потери раунда, округляя вверх; максимум 10000 |
|
||||||
|
| Подкова | 1800 | 5 | Добавляет 35% чистой прибыли; максимум 5000, минимум 1 при положительной прибыли |
|
||||||
|
| Череп | 3500 | 1 | Отменяет смертельный выстрел в русской рулетке или Buckshot |
|
||||||
|
| Контракт | 4000 | 2 | Добавляет 100% чистой прибыли, максимум 10000; проигрыш тоже расходует заряд |
|
||||||
|
|
||||||
|
Лимит — 99 зарядов каждого вида. При недостатке денег или превышении лимита
|
||||||
|
набор не покупается даже частично. Заряды не имеют срока действия.
|
||||||
|
Выключенный эффект не расходуется. Контракт несовместим с клевером и подковой:
|
||||||
|
его включение выключает оба эффекта. Череп может работать вместе с контрактом.
|
||||||
|
|
||||||
|
Возвращённая ставка не считается прибылью. Частичный проигрыш страхуется только
|
||||||
|
на сумму потери. Ничья не расходует денежные эффекты. Клевер и подкова расходуют
|
||||||
|
заряд только при фактическом зачислении. Банк ограничен 1000000000.
|
||||||
|
Режим наблюдателя не расходует инвентарь и не начисляет личные бонусы.
|
||||||
|
|
||||||
|
## Адская башня
|
||||||
|
|
||||||
|
**Банк общий с профилем.** Ставки, проигрыши и выплаты меняют обычный банк;
|
||||||
|
выход не восстанавливает прежнюю сумму. Денежный приз за шестой этаж — 66600,
|
||||||
|
однократно, с общим ограничением банка.
|
||||||
|
|
||||||
|
Обычные артефакты внутри башни не работают и не расходуются. Вместо них перед
|
||||||
|
стартом и после каждого из первых пяти этажей выбирается одна из трёх временных
|
||||||
|
реликвий. `1`/`2`/`3` берут соответствующую карточку; стрелки влево/вправо и
|
||||||
|
`Enter` выбирают выделенную. Также можно нажать карточку мышью.
|
||||||
|
|
||||||
|
| Реликвия | Действие |
|
||||||
|
|---|---|
|
||||||
|
| Сердце | Один повтор любого проигранного этажа |
|
||||||
|
| Часы | Два повтора предстоящего этажа; остаток сгорает при переходе дальше |
|
||||||
|
| Патрон | Две отмены смертельного выстрела |
|
||||||
|
| Печать | Дважды удаляет последнюю карту, вызвавшую перебор в блэкджеке; затем ходит крупье |
|
||||||
|
| Око палача | Показывает игроку следующий патрон Buckshot на протяжении забега |
|
||||||
|
| Кошель | Дважды возвращает потерю проигранного этажа, максимум 5000 за возврат |
|
||||||
|
|
||||||
|
Кошель не даёт дополнительную попытку. При поражении сначала возвращаются деньги,
|
||||||
|
затем расходуются часы соответствующего этажа, затем сердце. Если повторов нет,
|
||||||
|
забег завершается. Ничья в блэкджеке позволяет переиграть без расхода повтора.
|
||||||
|
|
||||||
|
Предложения: сердце, кошель и ситуационная реликвия. Перед блэкджеком доступна
|
||||||
|
печать, перед русской рулеткой — патрон, перед Buckshot — око, иначе — часы.
|
||||||
|
Заряды остальных реликвий складываются. Выбор нельзя получить повторным нажатием.
|
||||||
|
|
||||||
|
Все реликвии сбрасываются при победе, окончательном поражении, выходе в холл
|
||||||
|
и начале нового забега. В сохранение они не записываются. Выход во время
|
||||||
|
оплаченного раунда соблюдает правила соответствующей игры: например, монета
|
||||||
|
доигрывает результат, а карточный стол считает незавершённую руку проигранной.
|
||||||
|
|
||||||
|
Счётчики `СЕР`, `ЧАС`, `ПАТ`, `ПЕЧ`, `ОКО`, `КОШ` показывают остаток реликвий.
|
||||||
|
Внутри игры они находятся сверху, между этажами — снизу.
|
||||||
|
|
||||||
|
## Сохранения
|
||||||
|
|
||||||
|
Именованный профиль: 312 байт. Первые 280 байт сохраняют старый формат и подпись;
|
||||||
|
расширение `ARF2` хранит четыре счётчика, маску включения, версию и контрольную
|
||||||
|
сумму. Старый профиль загружается с пустым новым инвентарём.
|
||||||
|
При смене или создании профиля инвентарь сбрасывается перед загрузкой.
|
||||||
|
Preview-сохранение: 40 байт, версия `C3D4`, маска эффектов и контрольная сумма;
|
||||||
|
старые preview-версии по-прежнему читаются.
|
||||||
|
|
||||||
|
Контрольные суммы обнаруживают случайное повреждение; это не криптографическая
|
||||||
|
защита от редактирования владельцем компьютера.
|
||||||
|
|
||||||
|
## Проверки и ограничения
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
python -B tools/tests/check_artifacts.py
|
||||||
|
python -B tools/tests/test_hell_tower_runthrough.py
|
||||||
|
python -B tools/tests/check_casino_actions.py
|
||||||
|
python -B tools/tests/check_hall_expansion.py
|
||||||
|
```
|
||||||
|
|
||||||
|
Для общих тестов нужны Pillow, treys и capstone. Это офлайн-зависимости тестов,
|
||||||
|
не зависимости игры. Игра и все перечисленные эффекты реализованы на MASM x86.
|
||||||
|
|
||||||
|
Тест артефактов исполняет настоящие процедуры игры, проверяет покупки, лимиты,
|
||||||
|
отключение, чистую прибыль Buckshot, повторные выплаты, реликвии, выходы,
|
||||||
|
сохранения и их повреждение. Снимки UI и отчёт — `build/artifacts/`.
|
||||||
|
Проверяются длины строк карточек и очистка предыдущего кадра.
|
||||||
|
|
||||||
|
Шестиступенчатый smoke-тест действительно открывает игровые сцены, но подставляет
|
||||||
|
победные исходы. Он **не измеряет вероятность прохождения**. Целевые 40–60%
|
||||||
|
прохождений освоившим правила игроком пока не подтверждены статистикой;
|
||||||
|
полноценная оценка требует серий забегов с указанной стратегией на каждом этаже.
|
||||||
|
Эта переработка добавляет страховку и повторы, но не подменяет случайные исходы.
|
||||||
|
|
@ -97,8 +97,9 @@ and reads before publishing the pixels. Packs are loaded once and reused.
|
||||||
First-person roulette actions need approved, consistent hand/gun animation
|
First-person roulette actions need approved, consistent hand/gun animation
|
||||||
sequences. The requested replacement sheet failed generation and is not shipped.
|
sequences. The requested replacement sheet failed generation and is not shipped.
|
||||||
Multiway poker requires actual 3/4-player betting, side pots and AI seat state,
|
Multiway poker requires actual 3/4-player betting, side pots and AI seat state,
|
||||||
not decorative extra opponents. Native talisman effects, achievements, daily
|
not decorative extra opponents. Native talisman effects were subsequently
|
||||||
tasks and online tables still require integration with the selected profile.
|
integrated with selected profiles; see `ARTIFACTS_AND_TOWER.md`. Achievements,
|
||||||
|
daily tasks and online tables have separate integration work.
|
||||||
The old installer has not been repackaged with this work.
|
The old installer has not been repackaged with this work.
|
||||||
|
|
||||||
The classic 777 cabinet is now playable natively: generated cabinet/symbol art,
|
The classic 777 cabinet is now playable natively: generated cabinet/symbol art,
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,8 @@ idempotent payout, bank cap, missing funds and six framebuffer captures.
|
||||||
`check_clover.py --parity` checks assets, real framebuffer clipping, all fifteen
|
`check_clover.py --parity` checks assets, real framebuffer clipping, all fifteen
|
||||||
complete cells, selected paid-mask changes and tested/shipping assembly code.
|
complete cells, selected paid-mask changes and tested/shipping assembly code.
|
||||||
|
|
||||||
Native talisman modifiers and legacy console achievement/dance side effects
|
Native talisman modifiers were subsequently integrated; see
|
||||||
|
`ARTIFACTS_AND_TOWER.md`. Legacy console achievement/dance side effects
|
||||||
are not ported by this change. NPC challenges count native slot rounds and
|
are not ported by this change. NPC challenges count native slot rounds and
|
||||||
classify only positive net results as wins. No claim of completing every legacy
|
classify only positive net results as wins. No claim of completing every legacy
|
||||||
Clover feature or its balance is made.
|
Clover feature or its balance is made.
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,16 @@
|
||||||
# Native scene fixes
|
# Native scene fixes
|
||||||
|
|
||||||
The MASM game stays in one graphical window. Unported CloverPit,
|
The MASM game stays in one graphical window. Unported
|
||||||
online roulette, Umamusume, tower, terminal and observer interactions open a
|
online roulette and Umamusume interactions open a
|
||||||
native "not implemented yet" panel. Escape, E, Enter, Space or its close button
|
native "not implemented yet" panel. Escape, E, Enter, Space or its close button
|
||||||
return to the same position. Opening/closing never charges a stake, runs a
|
return to the same position. Opening/closing never charges a stake, runs a
|
||||||
console routine or blocks the window event loop. Legacy console game code
|
console routine or blocks the window event loop. Legacy console game code
|
||||||
is retained for the earlier standalone console mode, not called by these
|
is retained for the earlier standalone console mode, not called by these
|
||||||
graphical interactions.
|
graphical interactions.
|
||||||
|
|
||||||
|
CloverPit, tower, terminal and observer subsequently received native scenes.
|
||||||
|
See `ARTIFACTS_AND_TOWER.md` for current artifact and tower rules.
|
||||||
|
|
||||||
Durak now has a native animated table instead of that panel, including
|
Durak now has a native animated table instead of that panel, including
|
||||||
podkidnoy/perevodnoy rules and exit confirmation. See `native-durak.md`.
|
podkidnoy/perevodnoy rules and exit confirmation. See `native-durak.md`.
|
||||||
777 now has an animated native cabinet, paytable and safely queued exit.
|
777 now has an animated native cabinet, paytable and safely queued exit.
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,8 @@ Existing fullscreen, startup, audio, dice and 2000 roulette-round checks remain.
|
||||||
This is not a completed migration of the whole casino. The implemented
|
This is not a completed migration of the whole casino. The implemented
|
||||||
graphical games include the three card tables, Russian roulette, Buckshot,
|
graphical games include the three card tables, Russian roulette, Buckshot,
|
||||||
multi-bet casino roulette, coin, dice, skulls, skill checks and billiards.
|
multi-bet casino roulette, coin, dice, skulls, skill checks and billiards.
|
||||||
777, CloverPit, online play, tower, terminal and observer still show native
|
777, CloverPit, tower, terminal and observer subsequently received native
|
||||||
unavailable panels. Native profile data remains separate from legacy console
|
implementations. Only online roulette and Umamusume still show unavailable
|
||||||
|
panels. See `ARTIFACTS_AND_TOWER.md` for artifact and tower rules.
|
||||||
|
Native profile data remains separate from legacy console
|
||||||
account saves. The old installer is not refreshed by this change.
|
account saves. The old installer is not refreshed by this change.
|
||||||
|
|
|
||||||
60
poker.asm
60
poker.asm
|
|
@ -1,6 +1,8 @@
|
||||||
.386
|
.386
|
||||||
.model flat, stdcall
|
.model flat, stdcall
|
||||||
option casemap:none
|
option casemap:none
|
||||||
|
ArtifactSaveSignature3D PROTO :DWORD
|
||||||
|
ValidateArtifactSave3D PROTO :DWORD
|
||||||
|
|
||||||
includelib kernel32.lib
|
includelib kernel32.lib
|
||||||
includelib winmm.lib
|
includelib winmm.lib
|
||||||
|
|
@ -24,7 +26,9 @@ FILE_ATTRIBUTE_NORMAL equ 80h
|
||||||
INVALID_HANDLE_VALUE equ -1
|
INVALID_HANDLE_VALUE equ -1
|
||||||
SAVE_MAGIC equ 31435653h
|
SAVE_MAGIC equ 31435653h
|
||||||
SAVE_SIGN_SIZE equ 276
|
SAVE_SIGN_SIZE equ 276
|
||||||
SAVE_FILE_SIZE equ 280
|
SAVE_FILE_SIZE equ 312
|
||||||
|
SAVE_LEGACY_SIZE equ 280
|
||||||
|
SAVE_ARTIFACT_SIGN_SIZE equ 308
|
||||||
SAVE_SALT equ 0A57C0DEh
|
SAVE_SALT equ 0A57C0DEh
|
||||||
ENABLE_VIRTUAL_TERMINAL_PROCESSING equ 0004h
|
ENABLE_VIRTUAL_TERMINAL_PROCESSING equ 0004h
|
||||||
COLOR_DEFAULT equ 07h
|
COLOR_DEFAULT equ 07h
|
||||||
|
|
@ -576,6 +580,7 @@ ReadKey ENDP
|
||||||
|
|
||||||
|
|
||||||
ResetProfileDefaults PROC uses ecx edi
|
ResetProfileDefaults PROC uses ecx edi
|
||||||
|
call ResetArtifacts3D
|
||||||
mov bankroll, 10000
|
mov bankroll, 10000
|
||||||
mov targetBank, 50000
|
mov targetBank, 50000
|
||||||
mov gamesPlayed, 0
|
mov gamesPlayed, 0
|
||||||
|
|
@ -804,6 +809,20 @@ save_stats_played_loop:
|
||||||
loop save_stats_played_loop
|
loop save_stats_played_loop
|
||||||
call CalcSaveSignature
|
call CalcSaveSignature
|
||||||
mov DWORD PTR [saveBuffer+SAVE_SIGN_SIZE], eax
|
mov DWORD PTR [saveBuffer+SAVE_SIGN_SIZE], eax
|
||||||
|
mov DWORD PTR [saveBuffer+280],32465241h ; ARF2
|
||||||
|
mov eax,charmCloverUses
|
||||||
|
mov DWORD PTR [saveBuffer+284],eax
|
||||||
|
mov eax,charmHorseshoeUses
|
||||||
|
mov DWORD PTR [saveBuffer+288],eax
|
||||||
|
mov eax,charmSkullUses
|
||||||
|
mov DWORD PTR [saveBuffer+292],eax
|
||||||
|
mov eax,charmDevilUses
|
||||||
|
mov DWORD PTR [saveBuffer+296],eax
|
||||||
|
mov eax,charmEnabledMask3D
|
||||||
|
mov DWORD PTR [saveBuffer+300],eax
|
||||||
|
mov DWORD PTR [saveBuffer+304],2
|
||||||
|
invoke ArtifactSaveSignature3D,OFFSET saveBuffer
|
||||||
|
mov DWORD PTR [saveBuffer+308],eax
|
||||||
call BuildSaveFullPath
|
call BuildSaveFullPath
|
||||||
invoke CreateFileA, OFFSET saveFullPath, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0
|
invoke CreateFileA, OFFSET saveFullPath, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0
|
||||||
cmp eax, INVALID_HANDLE_VALUE
|
cmp eax, INVALID_HANDLE_VALUE
|
||||||
|
|
@ -816,6 +835,7 @@ save_done:
|
||||||
SaveGame ENDP
|
SaveGame ENDP
|
||||||
|
|
||||||
LoadSave PROC uses eax ecx esi edi
|
LoadSave PROC uses eax ecx esi edi
|
||||||
|
call ResetArtifacts3D
|
||||||
mov dailyDateKey, 0
|
mov dailyDateKey, 0
|
||||||
mov dailyRewardMask, 0
|
mov dailyRewardMask, 0
|
||||||
mov dailyProgressPacked, 0
|
mov dailyProgressPacked, 0
|
||||||
|
|
@ -844,12 +864,29 @@ load_file_opened:
|
||||||
mov eax, DWORD PTR [saveBuffer]
|
mov eax, DWORD PTR [saveBuffer]
|
||||||
cmp eax, SAVE_MAGIC
|
cmp eax, SAVE_MAGIC
|
||||||
jne load_done
|
jne load_done
|
||||||
cmp charsRead, SAVE_FILE_SIZE
|
cmp charsRead, SAVE_LEGACY_SIZE
|
||||||
jb load_signature_ok
|
jb load_signature_ok
|
||||||
mov edx, DWORD PTR [saveBuffer+SAVE_SIGN_SIZE]
|
mov edx, DWORD PTR [saveBuffer+SAVE_SIGN_SIZE]
|
||||||
call CalcSaveSignature
|
call CalcSaveSignature
|
||||||
cmp eax, edx
|
cmp eax, edx
|
||||||
jne load_tampered
|
jne load_tampered
|
||||||
|
cmp charsRead,SAVE_LEGACY_SIZE
|
||||||
|
je load_signature_ok
|
||||||
|
cmp charsRead,SAVE_FILE_SIZE
|
||||||
|
jne load_tampered
|
||||||
|
invoke ValidateArtifactSave3D,OFFSET saveBuffer
|
||||||
|
test eax,eax
|
||||||
|
jz load_tampered
|
||||||
|
mov eax,DWORD PTR [saveBuffer+284]
|
||||||
|
mov charmCloverUses,eax
|
||||||
|
mov eax,DWORD PTR [saveBuffer+288]
|
||||||
|
mov charmHorseshoeUses,eax
|
||||||
|
mov eax,DWORD PTR [saveBuffer+292]
|
||||||
|
mov charmSkullUses,eax
|
||||||
|
mov eax,DWORD PTR [saveBuffer+296]
|
||||||
|
mov charmDevilUses,eax
|
||||||
|
mov eax,DWORD PTR [saveBuffer+300]
|
||||||
|
mov charmEnabledMask3D,eax
|
||||||
load_signature_ok:
|
load_signature_ok:
|
||||||
mov eax, DWORD PTR [saveBuffer+4]
|
mov eax, DWORD PTR [saveBuffer+4]
|
||||||
mov bankroll, eax
|
mov bankroll, eax
|
||||||
|
|
@ -1905,8 +1942,8 @@ CheckDurakEnd ENDP
|
||||||
include casino3d.inc
|
include casino3d.inc
|
||||||
|
|
||||||
|
|
||||||
IFDEF CASINO_ACTION_TEST
|
IFDEF HELL_TOWER_TEST
|
||||||
RunCasinoActionsTest3D PROC uses ebx esi edi
|
RunHellTowerTest3D PROC uses ebx esi edi
|
||||||
local stageLoop:DWORD
|
local stageLoop:DWORD
|
||||||
|
|
||||||
call InitPaths3D
|
call InitPaths3D
|
||||||
|
|
@ -1914,8 +1951,12 @@ RunCasinoActionsTest3D PROC uses ebx esi edi
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz test_error_init
|
jz test_error_init
|
||||||
|
|
||||||
|
; Test-owned session: no persistence or profile money is loaded.
|
||||||
|
mov arrivalConfirmed3D,0
|
||||||
|
mov bankroll,10000
|
||||||
; Enter Hell Tower
|
; Enter Hell Tower
|
||||||
call InitHellTower3D
|
call InitHellTower3D
|
||||||
|
invoke ChooseTowerRelic3D,0
|
||||||
cmp tournamentMode, 1
|
cmp tournamentMode, 1
|
||||||
jne test_error_tower_mode
|
jne test_error_tower_mode
|
||||||
|
|
||||||
|
|
@ -1947,6 +1988,7 @@ stage_test_loop:
|
||||||
call Present3D
|
call Present3D
|
||||||
|
|
||||||
; Advance to next stage
|
; Advance to next stage
|
||||||
|
invoke ChooseTowerRelic3D,0
|
||||||
inc towerStage
|
inc towerStage
|
||||||
mov towerFloorState, TOWER_STATE_BRIEFING
|
mov towerFloorState, TOWER_STATE_BRIEFING
|
||||||
mov towerCalloutAnim, 0
|
mov towerCalloutAnim, 0
|
||||||
|
|
@ -1998,10 +2040,18 @@ test_error_exit_mode:
|
||||||
test_error_exit_engine:
|
test_error_exit_engine:
|
||||||
mov eax, 107
|
mov eax, 107
|
||||||
ret
|
ret
|
||||||
RunCasinoActionsTest3D ENDP
|
RunHellTowerTest3D ENDP
|
||||||
ENDIF
|
ENDIF
|
||||||
|
|
||||||
main PROC
|
main PROC
|
||||||
|
IFDEF HELL_TOWER_TEST
|
||||||
|
call RunHellTowerTest3D
|
||||||
|
invoke ExitProcess,eax
|
||||||
|
ENDIF
|
||||||
|
IFDEF ARTIFACT_TEST
|
||||||
|
call RunArtifactTest3D
|
||||||
|
invoke ExitProcess,eax
|
||||||
|
ENDIF
|
||||||
IFDEF CASINO_ACTION_TEST
|
IFDEF CASINO_ACTION_TEST
|
||||||
call RunCasinoActionsTest3D
|
call RunCasinoActionsTest3D
|
||||||
invoke ExitProcess, eax
|
invoke ExitProcess, eax
|
||||||
|
|
|
||||||
BIN
poker.exe
BIN
poker.exe
Binary file not shown.
BIN
poker.obj
BIN
poker.obj
Binary file not shown.
180
src_graphics/artifact_shop.inc
Normal file
180
src_graphics/artifact_shop.inc
Normal file
|
|
@ -0,0 +1,180 @@
|
||||||
|
HandleArtifactShop3D PROC uses ebx
|
||||||
|
invoke Pressed3D,09h
|
||||||
|
test eax,eax
|
||||||
|
jz @F
|
||||||
|
mov merchantTab3D,0
|
||||||
|
mov artifactBuyArmed3D,0
|
||||||
|
ret
|
||||||
|
@@:
|
||||||
|
invoke Pressed3D,26h
|
||||||
|
test eax,eax
|
||||||
|
jz @F
|
||||||
|
cmp merchantCharmSelected3D,0
|
||||||
|
je @F
|
||||||
|
dec merchantCharmSelected3D
|
||||||
|
mov artifactBuyArmed3D,0
|
||||||
|
mov merchantMessage3D,0
|
||||||
|
@@:
|
||||||
|
invoke Pressed3D,28h
|
||||||
|
test eax,eax
|
||||||
|
jz @F
|
||||||
|
cmp merchantCharmSelected3D,3
|
||||||
|
jae @F
|
||||||
|
inc merchantCharmSelected3D
|
||||||
|
mov artifactBuyArmed3D,0
|
||||||
|
mov merchantMessage3D,0
|
||||||
|
@@:
|
||||||
|
invoke Pressed3D,45h
|
||||||
|
test eax,eax
|
||||||
|
jz artifact_shop_mouse
|
||||||
|
invoke ToggleArtifact3D,merchantCharmSelected3D
|
||||||
|
mov artifactBuyArmed3D,0
|
||||||
|
artifact_shop_mouse:
|
||||||
|
cmp mouseClick3D,0
|
||||||
|
je artifact_shop_enter
|
||||||
|
mov mouseClick3D,0
|
||||||
|
cmp mouseY3D,27
|
||||||
|
jb artifact_shop_enter
|
||||||
|
cmp mouseY3D,45
|
||||||
|
jae artifact_shop_rows
|
||||||
|
cmp mouseX3D,96
|
||||||
|
jae artifact_shop_enter
|
||||||
|
mov merchantTab3D,0
|
||||||
|
ret
|
||||||
|
artifact_shop_rows:
|
||||||
|
cmp mouseX3D,8
|
||||||
|
jb artifact_shop_enter
|
||||||
|
cmp mouseX3D,108
|
||||||
|
jae artifact_shop_actions
|
||||||
|
mov eax,mouseY3D
|
||||||
|
sub eax,52
|
||||||
|
js artifact_shop_enter
|
||||||
|
xor edx,edx
|
||||||
|
mov ecx,34
|
||||||
|
div ecx
|
||||||
|
cmp eax,3
|
||||||
|
ja artifact_shop_enter
|
||||||
|
mov merchantCharmSelected3D,eax
|
||||||
|
mov artifactBuyArmed3D,0
|
||||||
|
mov merchantMessage3D,0
|
||||||
|
ret
|
||||||
|
artifact_shop_actions:
|
||||||
|
cmp mouseX3D,116
|
||||||
|
jb artifact_shop_enter
|
||||||
|
cmp mouseX3D,311
|
||||||
|
jae artifact_shop_enter
|
||||||
|
cmp mouseY3D,169
|
||||||
|
jb artifact_shop_enter
|
||||||
|
cmp mouseY3D,185
|
||||||
|
jae artifact_shop_buy_mouse
|
||||||
|
invoke ToggleArtifact3D,merchantCharmSelected3D
|
||||||
|
mov artifactBuyArmed3D,0
|
||||||
|
ret
|
||||||
|
artifact_shop_buy_mouse:
|
||||||
|
cmp mouseY3D,190
|
||||||
|
jb artifact_shop_enter
|
||||||
|
cmp mouseY3D,210
|
||||||
|
jae artifact_shop_enter
|
||||||
|
jmp artifact_shop_confirm
|
||||||
|
artifact_shop_enter:
|
||||||
|
invoke Pressed3D,0Dh
|
||||||
|
test eax,eax
|
||||||
|
jz artifact_shop_done
|
||||||
|
artifact_shop_confirm:
|
||||||
|
cmp artifactBuyArmed3D,0
|
||||||
|
jne artifact_shop_purchase
|
||||||
|
mov artifactBuyArmed3D,1
|
||||||
|
mov merchantMessage3D,0
|
||||||
|
ret
|
||||||
|
artifact_shop_purchase:
|
||||||
|
mov artifactBuyArmed3D,0
|
||||||
|
invoke BuyMerchantCharm3D,merchantCharmSelected3D
|
||||||
|
artifact_shop_done:
|
||||||
|
ret
|
||||||
|
HandleArtifactShop3D ENDP
|
||||||
|
|
||||||
|
RenderArtifactShop3D PROC uses ebx esi edi
|
||||||
|
local y:DWORD,x:DWORD,ink:DWORD
|
||||||
|
invoke DrawBox,0,0,320,240,0015191Bh
|
||||||
|
invoke DrawBox,0,0,320,24,002B302Ah
|
||||||
|
invoke DrawString8x8,8,7,OFFSET artifactShopTitle3D,00EED5A0h
|
||||||
|
invoke FormatNumber,bankroll,OFFSET artifactNum3D
|
||||||
|
invoke DrawString8x8,232,7,OFFSET artifactNum3D,00AAEEAAh
|
||||||
|
invoke DrawBoxBorder,8,28,88,17,002B302Ah,00667766h,1
|
||||||
|
invoke DrawString8x8,14,33,OFFSET merchantStock3D,00BBBBBBh
|
||||||
|
invoke DrawBoxBorder,100,28,212,17,003D4939h,00C8AE70h,1
|
||||||
|
invoke DrawString8x8,122,33,OFFSET merchantTabCharmsLabel,00FFE0A0h
|
||||||
|
xor ebx,ebx
|
||||||
|
mov y,52
|
||||||
|
artifact_shop_card:
|
||||||
|
mov ink,00465450h
|
||||||
|
cmp ebx,merchantCharmSelected3D
|
||||||
|
jne @F
|
||||||
|
mov ink,00D8B878h
|
||||||
|
@@:
|
||||||
|
invoke DrawBoxBorder,8,y,100,31,00232A2Bh,ink,1
|
||||||
|
mov eax,y
|
||||||
|
add eax,5
|
||||||
|
invoke DrawString8x8,13,eax,charmNames3D[ebx*4],artifactColors3D[ebx*4]
|
||||||
|
mov ecx,ebx
|
||||||
|
bt charmEnabledMask3D,ecx
|
||||||
|
mov esi,OFFSET artifactOff3D
|
||||||
|
jnc @F
|
||||||
|
mov esi,OFFSET artifactOn3D
|
||||||
|
@@:
|
||||||
|
mov eax,y
|
||||||
|
add eax,18
|
||||||
|
invoke DrawString8x8,13,eax,esi,00AAAAAAh
|
||||||
|
lea edi,charmCloverUses
|
||||||
|
invoke FormatNumber,[edi+ebx*4],OFFSET artifactNum3D
|
||||||
|
mov eax,y
|
||||||
|
add eax,18
|
||||||
|
invoke DrawString8x8,76,eax,OFFSET artifactNum3D,00FFFFFFh
|
||||||
|
add y,34
|
||||||
|
inc ebx
|
||||||
|
cmp ebx,4
|
||||||
|
jb artifact_shop_card
|
||||||
|
mov ebx,merchantCharmSelected3D
|
||||||
|
invoke DrawBoxBorder,114,52,198,115,001D2425h,00647770h,1
|
||||||
|
invoke DrawString8x8,120,59,charmNames3D[ebx*4],artifactColors3D[ebx*4]
|
||||||
|
invoke DrawString8x8,120,77,charmDescs3D[ebx*4],00FFFFFFh
|
||||||
|
; Detail descriptions use full width below cards to avoid clipped text.
|
||||||
|
invoke DrawString8x8,8,216,artifactRules3D[ebx*4],00DDCDAAh
|
||||||
|
invoke DrawString8x8,8,228,OFFSET artifactHelp3D,0099AAA5h
|
||||||
|
invoke DrawString8x8,120,96,OFFSET artifactPack3D,0099AAA5h
|
||||||
|
invoke FormatNumber,charmUsesPack3D[ebx*4],OFFSET artifactNum3D
|
||||||
|
invoke DrawString8x8,280,96,OFFSET artifactNum3D,00FFFFFFh
|
||||||
|
invoke DrawString8x8,120,112,OFFSET artifactStock3D,0099AAA5h
|
||||||
|
lea edi,charmCloverUses
|
||||||
|
invoke FormatNumber,[edi+ebx*4],OFFSET artifactNum3D
|
||||||
|
invoke DrawString8x8,280,112,OFFSET artifactNum3D,00FFFFFFh
|
||||||
|
invoke DrawString8x8,120,128,OFFSET artifactPrice3D,0099AAA5h
|
||||||
|
invoke FormatNumber,charmPrices3D[ebx*4],OFFSET artifactNum3D
|
||||||
|
invoke DrawString8x8,264,128,OFFSET artifactNum3D,00FFD080h
|
||||||
|
invoke DrawString8x8,120,150,artifactUseRules3D[ebx*4],00BBCCC0h
|
||||||
|
mov esi,OFFSET artifactTowerNote3D
|
||||||
|
cmp merchantMessage3D,1
|
||||||
|
jne @F
|
||||||
|
mov esi,OFFSET artifactBought3D
|
||||||
|
@@:
|
||||||
|
cmp merchantMessage3D,2
|
||||||
|
jne @F
|
||||||
|
mov esi,OFFSET merchantPoor3D
|
||||||
|
@@:
|
||||||
|
cmp merchantMessage3D,3
|
||||||
|
jne @F
|
||||||
|
mov esi,OFFSET artifactLimit3D
|
||||||
|
@@:
|
||||||
|
; Long status uses a full-width strip, not the detail card.
|
||||||
|
invoke DrawString8x8,8,202,esi,00E0B580h
|
||||||
|
invoke DrawBoxBorder,116,170,194,15,00303E37h,006F9982h,1
|
||||||
|
invoke DrawString8x8,128,174,OFFSET artifactToggle3D,00BBDDCCh
|
||||||
|
mov esi,OFFSET artifactBuy3D
|
||||||
|
cmp artifactBuyArmed3D,0
|
||||||
|
je @F
|
||||||
|
mov esi,OFFSET artifactConfirm3D
|
||||||
|
@@:
|
||||||
|
invoke DrawBoxBorder,116,188,194,13,0043372Ah,00CCAA66h,1
|
||||||
|
invoke DrawString8x8,120,191,esi,00FFE0A0h
|
||||||
|
ret
|
||||||
|
RenderArtifactShop3D ENDP
|
||||||
239
src_graphics/artifact_system.inc
Normal file
239
src_graphics/artifact_system.inc
Normal file
|
|
@ -0,0 +1,239 @@
|
||||||
|
; Artifact settlement owns caps, inventory and observer/tower isolation.
|
||||||
|
PreviewArtifactSignature3D PROC uses esi ecx source:DWORD
|
||||||
|
mov esi,source
|
||||||
|
mov ecx,9
|
||||||
|
mov eax,0A57C0DEh
|
||||||
|
preview_artifact_sign:
|
||||||
|
rol eax,5
|
||||||
|
xor eax,[esi]
|
||||||
|
add eax,9E3779B9h
|
||||||
|
add esi,4
|
||||||
|
loop preview_artifact_sign
|
||||||
|
ret
|
||||||
|
PreviewArtifactSignature3D ENDP
|
||||||
|
|
||||||
|
ArtifactSaveSignature3D PROC uses esi ecx edx source:DWORD
|
||||||
|
mov esi,source
|
||||||
|
mov ecx,SAVE_ARTIFACT_SIGN_SIZE/4
|
||||||
|
mov eax,0A57C0DEh
|
||||||
|
artifact_sign_word:
|
||||||
|
rol eax,5
|
||||||
|
xor eax,[esi]
|
||||||
|
mov edx,eax
|
||||||
|
shr edx,16
|
||||||
|
xor eax,edx
|
||||||
|
add eax,9E3779B9h
|
||||||
|
add esi,4
|
||||||
|
loop artifact_sign_word
|
||||||
|
ret
|
||||||
|
ArtifactSaveSignature3D ENDP
|
||||||
|
|
||||||
|
ValidateArtifactSave3D PROC uses esi edi source:DWORD
|
||||||
|
mov esi,source
|
||||||
|
cmp DWORD PTR [esi+280],32465241h
|
||||||
|
jne artifact_save_invalid
|
||||||
|
cmp DWORD PTR [esi+304],2
|
||||||
|
jne artifact_save_invalid
|
||||||
|
invoke ArtifactSaveSignature3D,esi
|
||||||
|
cmp eax,[esi+308]
|
||||||
|
jne artifact_save_invalid
|
||||||
|
mov edi,284
|
||||||
|
@@:
|
||||||
|
cmp DWORD PTR [esi+edi],99
|
||||||
|
ja artifact_save_invalid
|
||||||
|
add edi,4
|
||||||
|
cmp edi,300
|
||||||
|
jb @B
|
||||||
|
cmp DWORD PTR [esi+300],15
|
||||||
|
ja artifact_save_invalid
|
||||||
|
mov eax,1
|
||||||
|
ret
|
||||||
|
artifact_save_invalid:
|
||||||
|
xor eax,eax
|
||||||
|
ret
|
||||||
|
ValidateArtifactSave3D ENDP
|
||||||
|
|
||||||
|
ArtifactCredit3D PROC amount:DWORD
|
||||||
|
mov eax,1000000000
|
||||||
|
sub eax,bankroll
|
||||||
|
cmp eax,amount
|
||||||
|
jbe @F
|
||||||
|
mov eax,amount
|
||||||
|
@@:
|
||||||
|
add bankroll,eax
|
||||||
|
ret
|
||||||
|
ArtifactCredit3D ENDP
|
||||||
|
|
||||||
|
ResetArtifacts3D PROC
|
||||||
|
mov charmCloverUses,0
|
||||||
|
mov charmHorseshoeUses,0
|
||||||
|
mov charmSkullUses,0
|
||||||
|
mov charmDevilUses,0
|
||||||
|
mov charmEnabledMask3D,7
|
||||||
|
ret
|
||||||
|
ResetArtifacts3D ENDP
|
||||||
|
|
||||||
|
ClampArtifacts3D PROC uses esi ecx
|
||||||
|
lea esi,charmCloverUses
|
||||||
|
mov ecx,4
|
||||||
|
@@:
|
||||||
|
cmp DWORD PTR [esi],CHARM_MAX_USES
|
||||||
|
jbe artifact_clamp_next
|
||||||
|
mov DWORD PTR [esi],CHARM_MAX_USES
|
||||||
|
artifact_clamp_next:
|
||||||
|
add esi,4
|
||||||
|
loop @B
|
||||||
|
and charmEnabledMask3D,15
|
||||||
|
test charmEnabledMask3D,8
|
||||||
|
jz @F
|
||||||
|
and charmEnabledMask3D,12
|
||||||
|
@@:
|
||||||
|
ret
|
||||||
|
ClampArtifacts3D ENDP
|
||||||
|
|
||||||
|
ToggleArtifact3D PROC index:DWORD
|
||||||
|
mov ecx,index
|
||||||
|
cmp ecx,3
|
||||||
|
ja artifact_toggle_done
|
||||||
|
btc charmEnabledMask3D,ecx
|
||||||
|
cmp ecx,3
|
||||||
|
jne @F
|
||||||
|
test charmEnabledMask3D,8
|
||||||
|
jz artifact_toggle_save
|
||||||
|
and charmEnabledMask3D,12
|
||||||
|
jmp artifact_toggle_save
|
||||||
|
@@:
|
||||||
|
cmp ecx,2
|
||||||
|
je artifact_toggle_save
|
||||||
|
and charmEnabledMask3D,7
|
||||||
|
artifact_toggle_save:
|
||||||
|
call SaveProgress3D
|
||||||
|
artifact_toggle_done:
|
||||||
|
ret
|
||||||
|
ToggleArtifact3D ENDP
|
||||||
|
|
||||||
|
TriggerCharmLossProtection PROC uses ebx ecx edx betAmount:DWORD
|
||||||
|
cmp obsActive3D,0
|
||||||
|
jne artifact_loss_none
|
||||||
|
cmp tournamentMode,0
|
||||||
|
jne artifact_loss_none
|
||||||
|
cmp betAmount,0
|
||||||
|
je artifact_loss_none
|
||||||
|
test charmEnabledMask3D,8
|
||||||
|
jz artifact_loss_clover
|
||||||
|
cmp charmDevilUses,0
|
||||||
|
je artifact_loss_none
|
||||||
|
dec charmDevilUses
|
||||||
|
call SaveProgress3D
|
||||||
|
jmp artifact_loss_none
|
||||||
|
artifact_loss_clover:
|
||||||
|
test charmEnabledMask3D,1
|
||||||
|
jz artifact_loss_none
|
||||||
|
cmp charmCloverUses,0
|
||||||
|
je artifact_loss_none
|
||||||
|
mov eax,betAmount
|
||||||
|
inc eax
|
||||||
|
shr eax,1
|
||||||
|
cmp eax,10000
|
||||||
|
jbe @F
|
||||||
|
mov eax,10000
|
||||||
|
@@:
|
||||||
|
invoke ArtifactCredit3D,eax
|
||||||
|
test eax,eax
|
||||||
|
jz artifact_loss_none
|
||||||
|
dec charmCloverUses
|
||||||
|
invoke CopyString3D,OFFSET msgCharmCloverSave,OFFSET flashMessage
|
||||||
|
mov flashTimer,140
|
||||||
|
call SaveProgress3D
|
||||||
|
mov eax,1
|
||||||
|
ret
|
||||||
|
artifact_loss_none:
|
||||||
|
xor eax,eax
|
||||||
|
ret
|
||||||
|
TriggerCharmLossProtection ENDP
|
||||||
|
|
||||||
|
; Input is NET profit, never gross payout or returned stake.
|
||||||
|
TriggerCharmWinBonus PROC uses ebx ecx edx winAmount:DWORD
|
||||||
|
cmp obsActive3D,0
|
||||||
|
jne artifact_bonus_none
|
||||||
|
cmp tournamentMode,0
|
||||||
|
jne artifact_bonus_none
|
||||||
|
cmp winAmount,0
|
||||||
|
je artifact_bonus_none
|
||||||
|
test charmEnabledMask3D,8
|
||||||
|
jz artifact_bonus_horse
|
||||||
|
cmp charmDevilUses,0
|
||||||
|
je artifact_bonus_none
|
||||||
|
mov eax,winAmount
|
||||||
|
cmp eax,10000
|
||||||
|
jbe @F
|
||||||
|
mov eax,10000
|
||||||
|
@@:
|
||||||
|
invoke ArtifactCredit3D,eax
|
||||||
|
test eax,eax
|
||||||
|
jz artifact_bonus_none
|
||||||
|
dec charmDevilUses
|
||||||
|
mov ebx,eax
|
||||||
|
invoke CopyString3D,OFFSET msgCharmDevilSave,OFFSET flashMessage
|
||||||
|
jmp artifact_bonus_save
|
||||||
|
artifact_bonus_horse:
|
||||||
|
test charmEnabledMask3D,2
|
||||||
|
jz artifact_bonus_none
|
||||||
|
cmp charmHorseshoeUses,0
|
||||||
|
je artifact_bonus_none
|
||||||
|
mov eax,winAmount
|
||||||
|
mov ecx,35
|
||||||
|
mul ecx
|
||||||
|
mov ecx,100
|
||||||
|
div ecx
|
||||||
|
test eax,eax
|
||||||
|
jnz @F
|
||||||
|
inc eax
|
||||||
|
@@:
|
||||||
|
cmp eax,5000
|
||||||
|
jbe @F
|
||||||
|
mov eax,5000
|
||||||
|
@@:
|
||||||
|
invoke ArtifactCredit3D,eax
|
||||||
|
test eax,eax
|
||||||
|
jz artifact_bonus_none
|
||||||
|
dec charmHorseshoeUses
|
||||||
|
mov ebx,eax
|
||||||
|
invoke CopyString3D,OFFSET msgCharmHorseshoeWin,OFFSET flashMessage
|
||||||
|
artifact_bonus_save:
|
||||||
|
mov flashTimer,140
|
||||||
|
call SaveProgress3D
|
||||||
|
mov eax,ebx
|
||||||
|
ret
|
||||||
|
artifact_bonus_none:
|
||||||
|
xor eax,eax
|
||||||
|
ret
|
||||||
|
TriggerCharmWinBonus ENDP
|
||||||
|
|
||||||
|
TriggerCharmBulletProtection PROC
|
||||||
|
cmp obsActive3D,0
|
||||||
|
jne artifact_bullet_none
|
||||||
|
cmp tournamentMode,0
|
||||||
|
je artifact_bullet_normal
|
||||||
|
cmp towerBulletUses3D,0
|
||||||
|
je artifact_bullet_none
|
||||||
|
dec towerBulletUses3D
|
||||||
|
invoke CopyString3D,OFFSET towerBulletMessage3D,OFFSET flashMessage
|
||||||
|
mov flashTimer,140
|
||||||
|
mov eax,1
|
||||||
|
ret
|
||||||
|
artifact_bullet_normal:
|
||||||
|
test charmEnabledMask3D,4
|
||||||
|
jz artifact_bullet_none
|
||||||
|
cmp charmSkullUses,0
|
||||||
|
je artifact_bullet_none
|
||||||
|
dec charmSkullUses
|
||||||
|
invoke CopyString3D,OFFSET msgCharmSkullSave,OFFSET flashMessage
|
||||||
|
mov flashTimer,140
|
||||||
|
call SaveProgress3D
|
||||||
|
mov eax,1
|
||||||
|
ret
|
||||||
|
artifact_bullet_none:
|
||||||
|
xor eax,eax
|
||||||
|
ret
|
||||||
|
TriggerCharmBulletProtection ENDP
|
||||||
|
|
@ -193,6 +193,7 @@ bs_commit_cleanup:
|
||||||
mov bs3d_damage[edi*4], 1
|
mov bs3d_damage[edi*4], 1
|
||||||
mov bs3d_known, -1
|
mov bs3d_known, -1
|
||||||
mov bs3d_known[4], -1
|
mov bs3d_known[4], -1
|
||||||
|
call UpdateTowerEye3D
|
||||||
mov bs3d_messageTime, 1800
|
mov bs3d_messageTime, 1800
|
||||||
bs_commit_done:
|
bs_commit_done:
|
||||||
ret
|
ret
|
||||||
|
|
@ -236,6 +237,9 @@ bs_finish_win:
|
||||||
jbe @F
|
jbe @F
|
||||||
mov bankroll, 1000000000
|
mov bankroll, 1000000000
|
||||||
@@:
|
@@:
|
||||||
|
mov eax,bs3d_bet
|
||||||
|
shl eax,1
|
||||||
|
invoke TriggerCharmWinBonus,eax
|
||||||
invoke NpcRecordRound3D,7,1
|
invoke NpcRecordRound3D,7,1
|
||||||
call SaveProgress3D
|
call SaveProgress3D
|
||||||
ret
|
ret
|
||||||
|
|
@ -244,6 +248,7 @@ bs_finish_lose:
|
||||||
mov bs3d_result, BS_LOSE
|
mov bs3d_result, BS_LOSE
|
||||||
mov bs3d_victim, 0
|
mov bs3d_victim, 0
|
||||||
mov bs3d_timer, 800
|
mov bs3d_timer, 800
|
||||||
|
invoke TriggerCharmLossProtection,bs3d_bet
|
||||||
invoke NpcRecordRound3D,7,0
|
invoke NpcRecordRound3D,7,0
|
||||||
call SaveProgress3D
|
call SaveProgress3D
|
||||||
bs_finish_done:
|
bs_finish_done:
|
||||||
|
|
@ -866,6 +871,7 @@ ResolveBuckshotPose3D ENDP
|
||||||
|
|
||||||
RenderBuckshot3D PROC uses ebx esi edi
|
RenderBuckshot3D PROC uses ebx esi edi
|
||||||
local handY:DWORD,pose:DWORD,actor:DWORD
|
local handY:DWORD,pose:DWORD,actor:DWORD
|
||||||
|
call UpdateTowerEye3D
|
||||||
mov animOpacity3D, 255
|
mov animOpacity3D, 255
|
||||||
cmp bs3d_room.pixels, 0
|
cmp bs3d_room.pixels, 0
|
||||||
je bs_render_error
|
je bs_render_error
|
||||||
|
|
|
||||||
|
|
@ -129,6 +129,11 @@ LeaveCardTable3D PROC
|
||||||
card_leave_hall:
|
card_leave_hall:
|
||||||
mov cardExitActive3D, 0
|
mov cardExitActive3D, 0
|
||||||
mov paused3D, 0
|
mov paused3D, 0
|
||||||
|
cmp tournamentMode,1
|
||||||
|
jne @F
|
||||||
|
call TowerExitToHall
|
||||||
|
ret
|
||||||
|
@@:
|
||||||
mov engineMode, MODE_WALK
|
mov engineMode, MODE_WALK
|
||||||
call ClearKeys3D
|
call ClearKeys3D
|
||||||
invoke PlayCasinoSound3D, 0, 0, 0
|
invoke PlayCasinoSound3D, 0, 0, 0
|
||||||
|
|
|
||||||
|
|
@ -1,129 +1,10 @@
|
||||||
|
include src_graphics\artifact_system.inc
|
||||||
|
|
||||||
.code
|
|
||||||
|
|
||||||
; ------------------------------------------------------------------------------
|
|
||||||
; TriggerCharmLossProtection: Checks Devil's Contract and Clover to save bet
|
|
||||||
; Input: betAmount (DWORD)
|
|
||||||
; Output: eax = 1 if saved (bet refunded to bankroll), 0 if not saved
|
|
||||||
; ------------------------------------------------------------------------------
|
|
||||||
TriggerCharmLossProtection PROC uses ebx ecx edx, betAmount:DWORD
|
|
||||||
cmp obsActive3D,0
|
|
||||||
jne protection_none
|
|
||||||
; 1. Check Devil's Contract (50% chance to refund full bet)
|
|
||||||
cmp charmDevilUses, 0
|
|
||||||
jle check_clover
|
|
||||||
|
|
||||||
invoke RandomRange, 100
|
|
||||||
cmp eax, 50
|
|
||||||
jge check_clover
|
|
||||||
|
|
||||||
; Devil Contract Triggered!
|
|
||||||
dec charmDevilUses
|
|
||||||
mov eax, betAmount
|
|
||||||
test eax, eax
|
|
||||||
jz @F
|
|
||||||
add bankroll, eax
|
|
||||||
@@:
|
|
||||||
invoke CopyString3D, OFFSET msgCharmDevilSave, OFFSET flashMessage
|
|
||||||
mov flashTimer, 120
|
|
||||||
invoke PlayCasinoSound3D, OFFSET soundJackpot, 0, 1
|
|
||||||
call SaveProgress3D
|
|
||||||
mov eax, 1
|
|
||||||
ret
|
|
||||||
|
|
||||||
check_clover:
|
|
||||||
; 2. Check Clover of Luck (15% chance to refund bet)
|
|
||||||
cmp charmCloverUses, 0
|
|
||||||
jle protection_none
|
|
||||||
|
|
||||||
invoke RandomRange, 100
|
|
||||||
cmp eax, 15
|
|
||||||
jge protection_none
|
|
||||||
|
|
||||||
; Clover Triggered!
|
|
||||||
dec charmCloverUses
|
|
||||||
mov eax, betAmount
|
|
||||||
test eax, eax
|
|
||||||
jz @F
|
|
||||||
add bankroll, eax
|
|
||||||
@@:
|
|
||||||
invoke CopyString3D, OFFSET msgCharmCloverSave, OFFSET flashMessage
|
|
||||||
mov flashTimer, 120
|
|
||||||
invoke PlayCasinoSound3D, OFFSET soundJackpot, 0, 1
|
|
||||||
call SaveProgress3D
|
|
||||||
mov eax, 1
|
|
||||||
ret
|
|
||||||
|
|
||||||
protection_none:
|
|
||||||
xor eax, eax
|
|
||||||
ret
|
|
||||||
TriggerCharmLossProtection ENDP
|
|
||||||
|
|
||||||
; ------------------------------------------------------------------------------
|
|
||||||
; TriggerCharmWinBonus: Grants +15% extra payout on slot / roulette win
|
|
||||||
; Input: winAmount (DWORD)
|
|
||||||
; Output: eax = bonus amount added to bankroll, 0 if no horseshoe active
|
|
||||||
; ------------------------------------------------------------------------------
|
|
||||||
TriggerCharmWinBonus PROC uses ebx ecx edx, winAmount:DWORD
|
|
||||||
cmp charmHorseshoeUses, 0
|
|
||||||
jle bonus_none
|
|
||||||
|
|
||||||
mov eax, winAmount
|
|
||||||
test eax, eax
|
|
||||||
jle bonus_none
|
|
||||||
|
|
||||||
; Calculate 15% bonus: (winAmount * 15) / 100
|
|
||||||
imul eax, 15
|
|
||||||
xor edx, edx
|
|
||||||
mov ecx, 100
|
|
||||||
div ecx
|
|
||||||
cmp eax, 1
|
|
||||||
jge @F
|
|
||||||
mov eax, 1
|
|
||||||
@@:
|
|
||||||
mov ebx, eax
|
|
||||||
add bankroll, ebx
|
|
||||||
dec charmHorseshoeUses
|
|
||||||
invoke CopyString3D, OFFSET msgCharmHorseshoeWin, OFFSET flashMessage
|
|
||||||
mov flashTimer, 120
|
|
||||||
invoke PlayCasinoSound3D, OFFSET soundCoin, 0, 1
|
|
||||||
call SaveProgress3D
|
|
||||||
mov eax, ebx
|
|
||||||
ret
|
|
||||||
|
|
||||||
bonus_none:
|
|
||||||
xor eax, eax
|
|
||||||
ret
|
|
||||||
TriggerCharmWinBonus ENDP
|
|
||||||
|
|
||||||
; ------------------------------------------------------------------------------
|
|
||||||
; TriggerCharmBulletProtection: Protects player from fatal gunshot
|
|
||||||
; Output: eax = 1 if saved (bullet misfired), 0 if no skull active
|
|
||||||
; ------------------------------------------------------------------------------
|
|
||||||
TriggerCharmBulletProtection PROC uses ebx ecx edx
|
|
||||||
cmp charmSkullUses, 0
|
|
||||||
jle bullet_none
|
|
||||||
|
|
||||||
dec charmSkullUses
|
|
||||||
invoke CopyString3D, OFFSET msgCharmSkullSave, OFFSET flashMessage
|
|
||||||
mov flashTimer, 140
|
|
||||||
invoke PlayCasinoSound3D, OFFSET rrDrySound3D, 0, 1
|
|
||||||
call SaveProgress3D
|
|
||||||
mov eax, 1
|
|
||||||
ret
|
|
||||||
|
|
||||||
bullet_none:
|
|
||||||
xor eax, eax
|
|
||||||
ret
|
|
||||||
TriggerCharmBulletProtection ENDP
|
|
||||||
|
|
||||||
; ------------------------------------------------------------------------------
|
|
||||||
; DrawCharmsHUD: Draws active charm badges with remaining charges
|
|
||||||
; Input: drawX, drawY (screen coordinates)
|
|
||||||
; ------------------------------------------------------------------------------
|
|
||||||
DrawCharmsHUD PROC uses ebx esi edi, drawX:DWORD, drawY:DWORD
|
DrawCharmsHUD PROC uses ebx esi edi, drawX:DWORD, drawY:DWORD
|
||||||
local curX:DWORD, tempBuf[16]:BYTE
|
local curX:DWORD, tempBuf[16]:BYTE
|
||||||
|
|
||||||
|
cmp tournamentMode,0
|
||||||
|
jne hud_done
|
||||||
mov eax, charmCloverUses
|
mov eax, charmCloverUses
|
||||||
or eax, charmHorseshoeUses
|
or eax, charmHorseshoeUses
|
||||||
or eax, charmSkullUses
|
or eax, charmSkullUses
|
||||||
|
|
@ -135,6 +16,8 @@ DrawCharmsHUD PROC uses ebx esi edi, drawX:DWORD, drawY:DWORD
|
||||||
mov curX, eax
|
mov curX, eax
|
||||||
|
|
||||||
; 1. Clover Badge
|
; 1. Clover Badge
|
||||||
|
test charmEnabledMask3D,1
|
||||||
|
jz check_horse_hud
|
||||||
cmp charmCloverUses, 0
|
cmp charmCloverUses, 0
|
||||||
jle check_horse_hud
|
jle check_horse_hud
|
||||||
|
|
||||||
|
|
@ -152,6 +35,8 @@ DrawCharmsHUD PROC uses ebx esi edi, drawX:DWORD, drawY:DWORD
|
||||||
|
|
||||||
check_horse_hud:
|
check_horse_hud:
|
||||||
; 2. Horseshoe Badge
|
; 2. Horseshoe Badge
|
||||||
|
test charmEnabledMask3D,2
|
||||||
|
jz check_skull_hud
|
||||||
cmp charmHorseshoeUses, 0
|
cmp charmHorseshoeUses, 0
|
||||||
jle check_skull_hud
|
jle check_skull_hud
|
||||||
|
|
||||||
|
|
@ -169,6 +54,8 @@ check_horse_hud:
|
||||||
|
|
||||||
check_skull_hud:
|
check_skull_hud:
|
||||||
; 3. Skull Badge
|
; 3. Skull Badge
|
||||||
|
test charmEnabledMask3D,4
|
||||||
|
jz check_devil_hud
|
||||||
cmp charmSkullUses, 0
|
cmp charmSkullUses, 0
|
||||||
jle check_devil_hud
|
jle check_devil_hud
|
||||||
|
|
||||||
|
|
@ -186,6 +73,8 @@ check_skull_hud:
|
||||||
|
|
||||||
check_devil_hud:
|
check_devil_hud:
|
||||||
; 4. Devil Contract Badge
|
; 4. Devil Contract Badge
|
||||||
|
test charmEnabledMask3D,8
|
||||||
|
jz hud_done
|
||||||
cmp charmDevilUses, 0
|
cmp charmDevilUses, 0
|
||||||
jle hud_done
|
jle hud_done
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,29 @@
|
||||||
CHARM_COUNT equ 4
|
CHARM_COUNT equ 4
|
||||||
|
CHARM_MAX_USES equ 99
|
||||||
|
|
||||||
CHARM_CLOVER_PRICE equ 12000
|
CHARM_CLOVER_PRICE equ 900
|
||||||
CHARM_CLOVER_USES equ 3
|
CHARM_CLOVER_USES equ 3
|
||||||
|
|
||||||
CHARM_HORSESHOE_PRICE equ 20000
|
CHARM_HORSESHOE_PRICE equ 1800
|
||||||
CHARM_HORSESHOE_USES equ 5
|
CHARM_HORSESHOE_USES equ 5
|
||||||
|
|
||||||
CHARM_SKULL_PRICE equ 35000
|
CHARM_SKULL_PRICE equ 3500
|
||||||
CHARM_SKULL_USES equ 1
|
CHARM_SKULL_USES equ 1
|
||||||
|
|
||||||
CHARM_DEVIL_PRICE equ 50000
|
CHARM_DEVIL_PRICE equ 4000
|
||||||
CHARM_DEVIL_USES equ 2
|
CHARM_DEVIL_USES equ 2
|
||||||
|
|
||||||
TriggerCharmLossProtection PROTO :DWORD
|
TriggerCharmLossProtection PROTO :DWORD
|
||||||
TriggerCharmWinBonus PROTO :DWORD
|
TriggerCharmWinBonus PROTO :DWORD
|
||||||
|
PreviewArtifactSignature3D PROTO :DWORD
|
||||||
|
ArtifactSaveSignature3D PROTO :DWORD
|
||||||
|
ValidateArtifactSave3D PROTO :DWORD
|
||||||
|
ArtifactCredit3D PROTO :DWORD
|
||||||
|
ResetArtifacts3D PROTO
|
||||||
|
ClampArtifacts3D PROTO
|
||||||
|
ToggleArtifact3D PROTO :DWORD
|
||||||
|
RenderArtifactShop3D PROTO
|
||||||
|
HandleArtifactShop3D PROTO
|
||||||
TriggerCharmBulletProtection PROTO
|
TriggerCharmBulletProtection PROTO
|
||||||
DrawCharmsHUD PROTO :DWORD, :DWORD
|
DrawCharmsHUD PROTO :DWORD, :DWORD
|
||||||
|
|
||||||
|
|
@ -24,35 +34,57 @@ charmCloverUses dd 0
|
||||||
charmHorseshoeUses dd 0
|
charmHorseshoeUses dd 0
|
||||||
charmSkullUses dd 0
|
charmSkullUses dd 0
|
||||||
charmDevilUses dd 0
|
charmDevilUses dd 0
|
||||||
|
charmEnabledMask3D dd 7
|
||||||
|
artifactBuyArmed3D dd 0
|
||||||
|
artifactNum3D db 16 dup(0)
|
||||||
|
|
||||||
; Charm Store Metadata
|
; Charm Store Metadata
|
||||||
charmPrices3D dd CHARM_CLOVER_PRICE, CHARM_HORSESHOE_PRICE, CHARM_SKULL_PRICE, CHARM_DEVIL_PRICE
|
charmPrices3D dd CHARM_CLOVER_PRICE, CHARM_HORSESHOE_PRICE, CHARM_SKULL_PRICE, CHARM_DEVIL_PRICE
|
||||||
charmUsesPack3D dd CHARM_CLOVER_USES, CHARM_HORSESHOE_USES, CHARM_SKULL_USES, CHARM_DEVIL_USES
|
charmUsesPack3D dd CHARM_CLOVER_USES, CHARM_HORSESHOE_USES, CHARM_SKULL_USES, CHARM_DEVIL_USES
|
||||||
|
|
||||||
charmNameClover db 'Êëåâåð Óäà÷è',0
|
charmNameClover db 202,203,197,194,197,208,0
|
||||||
charmNameHorseshoe db 'Çîëîòàÿ Ïîäêîâà',0
|
charmNameHorseshoe db 207,206,196,202,206,194,192,0
|
||||||
charmNameSkull db '×åðåï Áåññìåðòèÿ',0
|
charmNameSkull db 215,197,208,197,207,0
|
||||||
charmNameDevil db 'Êîíòðàêò Äüÿâîëà',0
|
charmNameDevil db 202,206,205,210,208,192,202,210,0
|
||||||
|
charmDescClover db 194,229,240,237,184,242,32,53,48,37,32,239,238,242,229,240,232,0
|
||||||
charmNames3D dd OFFSET charmNameClover, OFFSET charmNameHorseshoe, OFFSET charmNameSkull, OFFSET charmNameDevil
|
charmDescHorseshoe db 43,51,53,37,32,247,232,241,242,238,233,32,239,240,232,225,251,235,232,0
|
||||||
|
charmDescSkull db 209,239,224,241,184,242,32,238,242,32,241,236,229,240,242,232,0
|
||||||
charmDescClover db '15% øàíñ ñïàñòè ñòàâêó',0
|
charmDescDevil db 211,228,226,238,232,242,32,239,240,232,225,251,235,252,0
|
||||||
charmDescHorseshoe db '+15% ê âûèãðûøó â ñëîòàõ',0
|
msgCharmCloverSave db 202,235,229,226,229,240,58,32,53,48,37,32,239,238,242,229,240,232,32,226,238,231,226,240,224,249,229,237,238,33,0
|
||||||
charmDescSkull db '100% ñïàñåíèå îò ïóëè',0
|
msgCharmDevilSave db 202,238,237,242,240,224,234,242,58,32,225,238,237,243,241,32,234,32,239,240,232,225,251,235,232,33,0
|
||||||
charmDescDevil db '50% øàíñ ñïàñòè ñòàâêó',0
|
msgCharmHorseshoeWin db 207,238,228,234,238,226,224,58,32,43,51,53,37,32,247,232,241,242,238,233,32,239,240,232,225,251,235,232,33,0
|
||||||
|
msgCharmSkullSave db 215,229,240,229,239,32,239,240,232,237,255,235,32,241,236,229,240,242,229,235,252,237,251,233,32,226,251,241,242,240,229,235,33,0
|
||||||
charmDescs3D dd OFFSET charmDescClover, OFFSET charmDescHorseshoe, OFFSET charmDescSkull, OFFSET charmDescDevil
|
msgCharmTowerSave db 208,229,235,232,234,226,232,255,58,32,229,249,184,32,238,228,237,224,32,239,238,239,251,242,234,224,33,0
|
||||||
|
badgeCloverPrefix db 91,202,203,58,0
|
||||||
; HUD Flash Messages
|
badgeHorsePrefix db 91,207,196,58,0
|
||||||
msgCharmCloverSave db 'Êëåâåð ñïàñ âàøó ñòàâêó!',0
|
badgeSkullPrefix db 91,215,208,58,0
|
||||||
msgCharmDevilSave db 'Äüÿâîë: ñòàâêà âîçâðàùåíà!',0
|
badgeDevilPrefix db 91,196,202,58,0
|
||||||
msgCharmHorseshoeWin db 'Ïîäêîâà: +15% ê âûèãðûøó!',0
|
badgeCloseBracket db 93,32,0
|
||||||
msgCharmSkullSave db '×åðåï: Îñå÷êà! Âû âûæèëè!',0
|
artifactShopTitle3D db 192,208,210,197,212,192,202,210,219,32,209,200,196,206,208,206,194,200,215,192,0
|
||||||
msgCharmTowerSave db 'Òàëèñìàí ñïàñ âàñ îò ïàäåíèÿ ñ Áàøíè!',0
|
artifactStock3D db 197,209,210,220,58,0
|
||||||
|
artifactPack3D db 205,192,193,206,208,58,0
|
||||||
; Compact HUD Badges
|
artifactPrice3D db 214,197,205,192,58,0
|
||||||
badgeCloverPrefix db '[ÊË:',0
|
artifactOn3D db 194,202,203,0
|
||||||
badgeHorsePrefix db '[ÏÊ:',0
|
artifactOff3D db 194,219,202,203,0
|
||||||
badgeSkullPrefix db '[×Ð:',0
|
artifactToggle3D db 91,69,93,32,194,202,203,32,47,32,194,219,202,203,0
|
||||||
badgeDevilPrefix db '[ÊÒ:',0
|
artifactBuy3D db 91,69,78,84,69,82,93,32,202,211,207,200,210,220,0
|
||||||
badgeCloseBracket db '] ',0
|
artifactConfirm3D db 91,69,78,84,69,82,93,32,207,206,196,210,194,197,208,196,200,210,220,0
|
||||||
|
artifactBought3D db 205,192,193,206,208,32,202,211,207,203,197,205,0
|
||||||
|
artifactLimit3D db 203,200,204,200,210,58,32,57,57,32,199,192,208,223,196,206,194,0
|
||||||
|
artifactHelp3D db 84,65,66,58,32,208,211,193,192,216,202,200,32,32,69,58,32,221,212,212,197,202,210,32,32,69,83,67,58,32,213,206,203,203,0
|
||||||
|
artifactTowerNote3D db 194,32,193,192,216,205,197,32,208,192,193,206,210,192,222,210,32,210,206,203,220,202,206,32,197,168,32,208,197,203,200,202,194,200,200,0
|
||||||
|
artifactMode3D db 221,212,212,197,202,210,32,192,194,210,206,204,192,210,200,215,197,209,202,200,201,44,32,207,206,202,192,32,194,202,203,222,215,168,205,0
|
||||||
|
artifactCloverRule3D db 196,238,32,49,48,48,48,48,32,231,224,32,239,240,238,232,227,240,224,237,237,251,233,32,240,224,243,237,228,0
|
||||||
|
artifactHorseRule3D db 196,238,32,53,48,48,48,32,231,224,32,239,240,232,225,251,235,252,237,251,233,32,240,224,243,237,228,0
|
||||||
|
artifactSkullRule3D db 208,243,241,241,234,224,255,32,240,243,235,229,242,234,224,32,232,32,66,117,99,107,115,104,111,116,0
|
||||||
|
artifactDevilRule3D db 196,238,32,49,48,48,48,48,59,32,239,240,238,232,227,240,251,248,32,242,240,224,242,232,242,32,231,224,240,255,228,0
|
||||||
|
artifactCloverUse3D db 199,224,240,255,228,32,231,224,32,226,238,231,226,240,224,242,0
|
||||||
|
artifactHorseUse3D db 199,224,240,255,228,32,231,224,32,225,238,237,243,241,0
|
||||||
|
artifactSkullUse3D db 199,224,240,255,228,32,231,224,32,241,239,224,241,229,237,232,229,0
|
||||||
|
artifactDevilUse3D db 193,229,231,32,234,235,229,226,229,240,224,32,232,32,239,238,228,234,238,226,251,0
|
||||||
|
charmNames3D dd OFFSET charmNameClover,OFFSET charmNameHorseshoe,OFFSET charmNameSkull,OFFSET charmNameDevil
|
||||||
|
charmDescs3D dd OFFSET charmDescClover,OFFSET charmDescHorseshoe,OFFSET charmDescSkull,OFFSET charmDescDevil
|
||||||
|
artifactRules3D dd OFFSET artifactCloverRule3D,OFFSET artifactHorseRule3D,OFFSET artifactSkullRule3D,OFFSET artifactDevilRule3D
|
||||||
|
artifactUseRules3D dd OFFSET artifactCloverUse3D,OFFSET artifactHorseUse3D,OFFSET artifactSkullUse3D,OFFSET artifactDevilUse3D
|
||||||
|
artifactColors3D dd 0088DD88h,00FFD070h,00CCDDEEh,00FF7777h
|
||||||
|
.code
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ ValidateGraphicProfile3D PROC uses ebx esi edi path:DWORD
|
||||||
jne profile_invalid
|
jne profile_invalid
|
||||||
cmp DWORD PTR entrySaveData3D[4], 1000000000
|
cmp DWORD PTR entrySaveData3D[4], 1000000000
|
||||||
ja profile_invalid
|
ja profile_invalid
|
||||||
cmp fileBytes, SAVE_FILE_SIZE
|
cmp fileBytes, SAVE_LEGACY_SIZE
|
||||||
jb profile_valid
|
jb profile_valid
|
||||||
mov esi, OFFSET entrySaveData3D
|
mov esi, OFFSET entrySaveData3D
|
||||||
mov ecx, SAVE_SIGN_SIZE/4
|
mov ecx, SAVE_SIGN_SIZE/4
|
||||||
|
|
@ -43,6 +43,13 @@ profile_signature:
|
||||||
loop profile_signature
|
loop profile_signature
|
||||||
cmp eax, DWORD PTR entrySaveData3D[SAVE_SIGN_SIZE]
|
cmp eax, DWORD PTR entrySaveData3D[SAVE_SIGN_SIZE]
|
||||||
jne profile_invalid
|
jne profile_invalid
|
||||||
|
cmp fileBytes,SAVE_LEGACY_SIZE
|
||||||
|
je profile_valid
|
||||||
|
cmp fileBytes,SAVE_FILE_SIZE
|
||||||
|
jne profile_invalid
|
||||||
|
invoke ValidateArtifactSave3D,OFFSET entrySaveData3D
|
||||||
|
test eax,eax
|
||||||
|
jz profile_invalid
|
||||||
profile_valid:
|
profile_valid:
|
||||||
mov eax, 1
|
mov eax, 1
|
||||||
ret
|
ret
|
||||||
|
|
@ -253,6 +260,7 @@ graphic_create_store:
|
||||||
invoke CreateDirectoryA, OFFSET runtime3D, 0
|
invoke CreateDirectoryA, OFFSET runtime3D, 0
|
||||||
invoke CreateDirectoryA, nativeProfilesDirPtr3D, 0
|
invoke CreateDirectoryA, nativeProfilesDirPtr3D, 0
|
||||||
call ResetProfileDefaults
|
call ResetProfileDefaults
|
||||||
|
call ResetArtifacts3D
|
||||||
invoke CopyCString, OFFSET saveFileName, OFFSET entryDisplayName3D
|
invoke CopyCString, OFFSET saveFileName, OFFSET entryDisplayName3D
|
||||||
mov nativeProfileActive3D, 1
|
mov nativeProfileActive3D, 1
|
||||||
call SyncGraphicBack3D
|
call SyncGraphicBack3D
|
||||||
|
|
|
||||||
|
|
@ -12,11 +12,13 @@ FreeTowerMinigameAssets ENDP
|
||||||
|
|
||||||
InitHellTower3D PROC
|
InitHellTower3D PROC
|
||||||
call FreeTowerMinigameAssets
|
call FreeTowerMinigameAssets
|
||||||
|
call ResetTowerRelics3D
|
||||||
mov tournamentMode, 1
|
mov tournamentMode, 1
|
||||||
mov towerStage, 1
|
mov towerStage, 1
|
||||||
mov towerFloorState, TOWER_STATE_BRIEFING
|
mov towerFloorState, TOWER_STATE_BRIEFING
|
||||||
mov towerAnimClock, 0
|
mov towerAnimClock, 0
|
||||||
mov towerCalloutAnim, 0
|
mov towerCalloutAnim, 0
|
||||||
|
call PrepareTowerReward3D
|
||||||
|
|
||||||
mov eax, towerFloorY[0]
|
mov eax, towerFloorY[0]
|
||||||
mov towerCursorY, eax
|
mov towerCursorY, eax
|
||||||
|
|
@ -33,6 +35,7 @@ InitHellTower3D ENDP
|
||||||
TowerExitToHall PROC
|
TowerExitToHall PROC
|
||||||
call StopTowerMusic
|
call StopTowerMusic
|
||||||
call FreeTowerMinigameAssets
|
call FreeTowerMinigameAssets
|
||||||
|
call ResetTowerRelics3D
|
||||||
mov tournamentMode, 0
|
mov tournamentMode, 0
|
||||||
mov engineMode, MODE_WALK
|
mov engineMode, MODE_WALK
|
||||||
call ClearKeys3D
|
call ClearKeys3D
|
||||||
|
|
@ -40,6 +43,18 @@ TowerExitToHall PROC
|
||||||
TowerExitToHall ENDP
|
TowerExitToHall ENDP
|
||||||
|
|
||||||
TowerLaunchCurrentFloor PROC uses ebx esi edi
|
TowerLaunchCurrentFloor PROC uses ebx esi edi
|
||||||
|
cmp towerRewardPending3D,0
|
||||||
|
jne tower_launch_blocked
|
||||||
|
cmp towerFloorState,TOWER_STATE_BRIEFING
|
||||||
|
jne tower_launch_blocked
|
||||||
|
cmp bankroll,100
|
||||||
|
jae @F
|
||||||
|
invoke CopyString3D,OFFSET towerFundsLabel3D,OFFSET flashMessage
|
||||||
|
mov flashTimer,140
|
||||||
|
ret
|
||||||
|
@@:
|
||||||
|
mov eax,bankroll
|
||||||
|
mov towerEntryBank3D,eax
|
||||||
mov eax, towerStage
|
mov eax, towerStage
|
||||||
dec eax
|
dec eax
|
||||||
cmp eax, 6
|
cmp eax, 6
|
||||||
|
|
@ -79,6 +94,7 @@ launch_valid:
|
||||||
@@:
|
@@:
|
||||||
cmp edx, MODE_ROULETTE
|
cmp edx, MODE_ROULETTE
|
||||||
jne @F
|
jne @F
|
||||||
|
mov wheelChip3D,100
|
||||||
call InitNativeWheel3D
|
call InitNativeWheel3D
|
||||||
mov engineMode, MODE_ROULETTE
|
mov engineMode, MODE_ROULETTE
|
||||||
jmp launch_done
|
jmp launch_done
|
||||||
|
|
@ -86,16 +102,32 @@ launch_valid:
|
||||||
cmp edx, MODE_BUCKSHOT
|
cmp edx, MODE_BUCKSHOT
|
||||||
jne launch_done
|
jne launch_done
|
||||||
call InitBuckshot3D
|
call InitBuckshot3D
|
||||||
|
test eax,eax
|
||||||
|
jnz @F
|
||||||
|
mov towerFloorState,TOWER_STATE_BRIEFING
|
||||||
|
mov engineMode,MODE_HELL_TOWER
|
||||||
|
ret
|
||||||
|
@@:
|
||||||
mov engineMode, MODE_BUCKSHOT
|
mov engineMode, MODE_BUCKSHOT
|
||||||
|
|
||||||
launch_done:
|
launch_done:
|
||||||
|
; Predictable entry stakes; all money remains in the shared profile bank.
|
||||||
|
mov coin3d_bet,50
|
||||||
|
mov dice3d_bet,100
|
||||||
|
mov cbBet3D,100
|
||||||
|
mov rr3d_bet,100
|
||||||
|
mov bs3d_bet,100
|
||||||
call ClearKeys3D
|
call ClearKeys3D
|
||||||
ret
|
ret
|
||||||
|
tower_launch_blocked:
|
||||||
|
ret
|
||||||
TowerLaunchCurrentFloor ENDP
|
TowerLaunchCurrentFloor ENDP
|
||||||
|
|
||||||
TowerReportRoundOutcome PROC uses eax outcome:DWORD
|
TowerReportRoundOutcome PROC uses eax outcome:DWORD
|
||||||
cmp tournamentMode, 1
|
cmp tournamentMode, 1
|
||||||
jne report_exit
|
jne report_exit
|
||||||
|
cmp towerFloorState,TOWER_STATE_IN_GAME
|
||||||
|
jne report_exit
|
||||||
mov eax, outcome
|
mov eax, outcome
|
||||||
cmp eax, 1
|
cmp eax, 1
|
||||||
jne report_loss
|
jne report_loss
|
||||||
|
|
@ -105,6 +137,7 @@ TowerReportRoundOutcome PROC uses eax outcome:DWORD
|
||||||
jae report_champion
|
jae report_champion
|
||||||
|
|
||||||
mov towerFloorState, TOWER_STATE_CLEAR
|
mov towerFloorState, TOWER_STATE_CLEAR
|
||||||
|
call PrepareTowerReward3D
|
||||||
mov towerCalloutAnim, 0
|
mov towerCalloutAnim, 0
|
||||||
mov eax, towerStage
|
mov eax, towerStage
|
||||||
dec eax
|
dec eax
|
||||||
|
|
@ -120,8 +153,8 @@ TowerReportRoundOutcome PROC uses eax outcome:DWORD
|
||||||
|
|
||||||
report_champion:
|
report_champion:
|
||||||
mov towerFloorState, TOWER_STATE_CHAMPION
|
mov towerFloorState, TOWER_STATE_CHAMPION
|
||||||
mov eax, towerPrizeAmount
|
invoke ArtifactCredit3D,towerPrizeAmount
|
||||||
add bankroll, eax
|
call ResetTowerRelics3D
|
||||||
invoke PlayCasinoSound3D, OFFSET soundRoundWin, 0, 1
|
invoke PlayCasinoSound3D, OFFSET soundRoundWin, 0, 1
|
||||||
call SaveProgress3D
|
call SaveProgress3D
|
||||||
mov engineMode, MODE_HELL_TOWER
|
mov engineMode, MODE_HELL_TOWER
|
||||||
|
|
@ -129,16 +162,39 @@ report_champion:
|
||||||
ret
|
ret
|
||||||
|
|
||||||
report_loss:
|
report_loss:
|
||||||
invoke TriggerCharmLossProtection, 0
|
cmp towerPurseUses3D,0
|
||||||
test eax, eax
|
je tower_loss_retry
|
||||||
jz @F
|
mov eax,towerEntryBank3D
|
||||||
mov towerFloorState, TOWER_STATE_BRIEFING
|
sub eax,bankroll
|
||||||
invoke CopyString3D, OFFSET msgCharmTowerSave, OFFSET flashMessage
|
jbe tower_loss_retry
|
||||||
mov flashTimer, 140
|
cmp eax,5000
|
||||||
mov engineMode, MODE_HELL_TOWER
|
jbe @F
|
||||||
|
mov eax,5000
|
||||||
|
@@:
|
||||||
|
invoke ArtifactCredit3D,eax
|
||||||
|
dec towerPurseUses3D
|
||||||
|
call SaveProgress3D
|
||||||
|
tower_loss_retry:
|
||||||
|
mov eax,towerStage
|
||||||
|
cmp eax,towerSealStage3D
|
||||||
|
jne tower_loss_heart
|
||||||
|
cmp towerSealUses3D,0
|
||||||
|
je tower_loss_heart
|
||||||
|
dec towerSealUses3D
|
||||||
|
jmp tower_loss_saved
|
||||||
|
tower_loss_heart:
|
||||||
|
cmp towerHeartUses3D,0
|
||||||
|
je tower_loss_final
|
||||||
|
dec towerHeartUses3D
|
||||||
|
tower_loss_saved:
|
||||||
|
mov towerFloorState,TOWER_STATE_BRIEFING
|
||||||
|
invoke CopyString3D,OFFSET towerRetryMessage3D,OFFSET flashMessage
|
||||||
|
mov flashTimer,140
|
||||||
|
mov engineMode,MODE_HELL_TOWER
|
||||||
call ClearKeys3D
|
call ClearKeys3D
|
||||||
ret
|
ret
|
||||||
@@:
|
tower_loss_final:
|
||||||
|
call ResetTowerRelics3D
|
||||||
mov towerFloorState, TOWER_STATE_DEFEAT
|
mov towerFloorState, TOWER_STATE_DEFEAT
|
||||||
call StopTowerMusic
|
call StopTowerMusic
|
||||||
invoke PlayCasinoSound3D, OFFSET soundRoundLose, 0, 1
|
invoke PlayCasinoSound3D, OFFSET soundRoundLose, 0, 1
|
||||||
|
|
@ -151,6 +207,11 @@ report_exit:
|
||||||
TowerReportRoundOutcome ENDP
|
TowerReportRoundOutcome ENDP
|
||||||
|
|
||||||
HandleHellTowerInput PROC
|
HandleHellTowerInput PROC
|
||||||
|
cmp towerRewardPending3D,1
|
||||||
|
jne @F
|
||||||
|
call HandleTowerReward3D
|
||||||
|
ret
|
||||||
|
@@:
|
||||||
mov eax, towerFloorState
|
mov eax, towerFloorState
|
||||||
cmp eax, TOWER_STATE_BRIEFING
|
cmp eax, TOWER_STATE_BRIEFING
|
||||||
je input_briefing
|
je input_briefing
|
||||||
|
|
@ -240,6 +301,11 @@ HandleHellTowerInput ENDP
|
||||||
RenderHellTower3D PROC uses ebx esi edi
|
RenderHellTower3D PROC uses ebx esi edi
|
||||||
local cardX:DWORD, cardY:DWORD, cardW:DWORD, cardH:DWORD
|
local cardX:DWORD, cardY:DWORD, cardW:DWORD, cardH:DWORD
|
||||||
local currY:DWORD, tgtY:DWORD
|
local currY:DWORD, tgtY:DWORD
|
||||||
|
cmp towerRewardPending3D,1
|
||||||
|
jne @F
|
||||||
|
call RenderTowerReward3D
|
||||||
|
ret
|
||||||
|
@@:
|
||||||
|
|
||||||
; 1. Background: draw HellTower menu art if loaded, else fallback to maroon
|
; 1. Background: draw HellTower menu art if loaded, else fallback to maroon
|
||||||
cmp hellTowerMenuArt3D.pixels, 0
|
cmp hellTowerMenuArt3D.pixels, 0
|
||||||
|
|
@ -456,10 +522,18 @@ render_card_briefing:
|
||||||
invoke DrawBoxBorder, eax, 134, ecx, 32, 00180303h, 00661111h, 1
|
invoke DrawBoxBorder, eax, 134, ecx, 32, 00180303h, 00661111h, 1
|
||||||
mov eax, cardX
|
mov eax, cardX
|
||||||
add eax, 12
|
add eax, 12
|
||||||
invoke DrawString8x8, eax, 139, OFFSET towerRuleText, 00FFAA33h
|
invoke DrawString8x8,eax,139,OFFSET towerHeartLabel3D,00FFAA33h
|
||||||
|
invoke FormatNumber,towerHeartUses3D,OFFSET towerRelicNum3D
|
||||||
|
mov eax,cardX
|
||||||
|
add eax,78
|
||||||
|
invoke DrawString8x8,eax,139,OFFSET towerRelicNum3D,00FFFFFFh
|
||||||
mov eax, cardX
|
mov eax, cardX
|
||||||
add eax, 12
|
add eax, 12
|
||||||
invoke DrawString8x8, eax, 151, OFFSET towerLossWarning, 00FF5555h
|
invoke DrawString8x8,eax,151,OFFSET towerSealLabel3D,00FFAA33h
|
||||||
|
invoke FormatNumber,towerSealUses3D,OFFSET towerRelicNum3D
|
||||||
|
mov eax,cardX
|
||||||
|
add eax,78
|
||||||
|
invoke DrawString8x8,eax,151,OFFSET towerRelicNum3D,00FFFFFFh
|
||||||
|
|
||||||
; Bankroll & Prize (Y = 172)
|
; Bankroll & Prize (Y = 172)
|
||||||
mov eax, cardX
|
mov eax, cardX
|
||||||
|
|
@ -552,6 +626,7 @@ render_card_champion:
|
||||||
invoke DrawString8x8, eax, 184, OFFSET towerReturnBtn, 00FFFFFFh
|
invoke DrawString8x8, eax, 184, OFFSET towerReturnBtn, 00FFFFFFh
|
||||||
|
|
||||||
render_tower_done:
|
render_tower_done:
|
||||||
|
call RenderTowerRelicStock3D
|
||||||
ret
|
ret
|
||||||
RenderHellTower3D ENDP
|
RenderHellTower3D ENDP
|
||||||
|
|
||||||
|
|
@ -568,7 +643,10 @@ RenderTowerInGameBadge PROC
|
||||||
invoke FormatNumber, towerStage, OFFSET hudNumBuffer
|
invoke FormatNumber, towerStage, OFFSET hudNumBuffer
|
||||||
invoke DrawString8x8, 64, 8, OFFSET hudNumBuffer, 00FFFFFFh
|
invoke DrawString8x8, 64, 8, OFFSET hudNumBuffer, 00FFFFFFh
|
||||||
invoke DrawString8x8, 72, 8, OFFSET towerHudOfTen, 00AAAAAAh
|
invoke DrawString8x8, 72, 8, OFFSET towerHudOfTen, 00AAAAAAh
|
||||||
|
call RenderTowerRelicStock3D
|
||||||
|
|
||||||
badge_done:
|
badge_done:
|
||||||
ret
|
ret
|
||||||
RenderTowerInGameBadge ENDP
|
RenderTowerInGameBadge ENDP
|
||||||
|
|
||||||
|
include src_graphics\tower_relics.inc
|
||||||
|
|
|
||||||
|
|
@ -82,3 +82,74 @@ towerPrizeText db 202,211,216,58,32,43,36,54,54,44,54,48,48,32,194,32,193,192,20
|
||||||
towerHudBadge db 193,192,216,205,223,58,32,0
|
towerHudBadge db 193,192,216,205,223,58,32,0
|
||||||
towerHudOfTen db 47,54,0
|
towerHudOfTen db 47,54,0
|
||||||
|
|
||||||
|
|
||||||
|
RenderTowerRelicStock3D PROTO
|
||||||
|
ResetTowerRelics3D PROTO
|
||||||
|
PrepareTowerReward3D PROTO
|
||||||
|
ChooseTowerRelic3D PROTO :DWORD
|
||||||
|
HandleTowerReward3D PROTO
|
||||||
|
RenderTowerReward3D PROTO
|
||||||
|
TryTowerBustSave3D PROTO
|
||||||
|
UpdateTowerEye3D PROTO
|
||||||
|
.data
|
||||||
|
towerHeartUses3D dd 0
|
||||||
|
towerSealUses3D dd 0
|
||||||
|
towerSealStage3D dd 0
|
||||||
|
towerBulletUses3D dd 0
|
||||||
|
towerBustUses3D dd 0
|
||||||
|
towerEye3D dd 0
|
||||||
|
towerPurseUses3D dd 0
|
||||||
|
towerRewardPending3D dd 0
|
||||||
|
towerRewardSelection3D dd 0
|
||||||
|
towerEntryBank3D dd 0
|
||||||
|
towerRewardOffers3D dd 0,1,5
|
||||||
|
towerRelicNum3D db 16 dup(0)
|
||||||
|
towerRewardTitle3D db 194,219,193,197,208,200,32,208,197,203,200,202,194,200,222,0
|
||||||
|
towerRewardHint3D db 193,192,205,202,32,206,193,217,200,201,46,32,208,197,203,200,202,194,200,200,32,205,192,32,206,196,200,205,32,199,192,193,197,195,46,0
|
||||||
|
towerRewardKeys3D db 49,32,47,32,50,32,47,32,51,58,32,194,219,193,206,208,32,32,32,69,78,84,69,82,58,32,194,199,223,210,220,0
|
||||||
|
towerRunOnly3D db 205,192,32,199,192,193,197,195,0
|
||||||
|
towerBulletMessage3D db 204,184,240,242,226,251,233,32,239,224,242,240,238,237,32,238,242,236,229,237,232,235,32,241,236,229,240,242,229,235,252,237,251,233,32,226,251,241,242,240,229,235,33,0
|
||||||
|
towerBustMessage3D db 207,229,247,224,242,252,58,32,239,238,241,235,229,228,237,255,255,32,234,224,240,242,224,32,239,229,240,229,225,238,240,224,32,238,242,236,229,237,229,237,224,33,0
|
||||||
|
towerRetryMessage3D db 208,229,235,232,234,226,232,255,32,241,239,224,241,235,224,32,231,224,225,229,227,46,32,207,238,226,242,238,240,232,32,253,242,224,230,33,0
|
||||||
|
towerHeartLabel3D db 209,197,208,196,214,192,58,0
|
||||||
|
towerSealLabel3D db 207,206,194,210,206,208,58,0
|
||||||
|
towerBulletLabel3D db 199,192,217,200,210,192,58,0
|
||||||
|
towerFundsLabel3D db 205,197,32,213,194,192,210,192,197,210,32,196,197,205,197,195,32,196,203,223,32,221,210,192,198,192,0
|
||||||
|
towerRelicName0 db 209,197,208,196,214,197,0
|
||||||
|
towerRelicDesc0 db 43,49,32,239,238,226,242,238,240,0
|
||||||
|
db 239,240,232,32,239,240,238,226,224,235,229,0
|
||||||
|
db 235,254,225,238,233,32,253,242,224,230,0
|
||||||
|
towerRelicName1 db 215,192,209,219,0
|
||||||
|
towerRelicDesc1 db 50,32,239,238,226,242,238,240,224,0
|
||||||
|
db 239,240,232,32,239,240,238,226,224,235,229,0
|
||||||
|
db 241,235,229,228,46,32,253,242,224,230,224,0
|
||||||
|
towerRelicName2 db 207,192,210,208,206,205,0
|
||||||
|
towerRelicDesc2 db 50,32,241,239,224,241,229,237,232,255,0
|
||||||
|
db 238,242,32,241,236,229,240,242,232,0
|
||||||
|
db 238,242,32,226,251,241,242,240,229,235,224,0
|
||||||
|
towerRelicName3 db 207,197,215,192,210,220,0
|
||||||
|
towerRelicDesc3 db 50,32,238,242,236,229,237,251,0
|
||||||
|
db 239,238,241,235,229,228,237,229,233,0
|
||||||
|
db 234,224,240,242,251,32,62,50,49,0
|
||||||
|
towerRelicName4 db 206,202,206,32,207,192,203,192,215,192,0
|
||||||
|
towerRelicDesc4 db 194,32,66,117,99,107,115,104,111,116,0
|
||||||
|
db 226,232,228,229,237,32,241,235,229,228,46,0
|
||||||
|
db 239,224,242,240,238,237,0
|
||||||
|
towerRelicName5 db 202,206,216,197,203,220,0
|
||||||
|
towerRelicDesc5 db 50,32,226,238,231,226,240,224,242,224,0
|
||||||
|
db 231,224,32,239,240,238,226,224,235,0
|
||||||
|
db 228,238,32,53,48,48,48,0
|
||||||
|
towerRelicNames3D dd OFFSET towerRelicName0,OFFSET towerRelicName1,OFFSET towerRelicName2,OFFSET towerRelicName3,OFFSET towerRelicName4,OFFSET towerRelicName5
|
||||||
|
towerRelicDescriptions3D dd OFFSET towerRelicDesc0,OFFSET towerRelicDesc1,OFFSET towerRelicDesc2,OFFSET towerRelicDesc3,OFFSET towerRelicDesc4,OFFSET towerRelicDesc5
|
||||||
|
.code
|
||||||
|
|
||||||
|
.data
|
||||||
|
towerStockLabel0 db 209,197,208,0
|
||||||
|
towerStockLabel1 db 215,192,209,0
|
||||||
|
towerStockLabel2 db 207,192,210,0
|
||||||
|
towerStockLabel3 db 207,197,215,0
|
||||||
|
towerStockLabel4 db 206,202,206,0
|
||||||
|
towerStockLabel5 db 202,206,216,0
|
||||||
|
towerStockLabels3D dd OFFSET towerStockLabel0,OFFSET towerStockLabel1,OFFSET towerStockLabel2,OFFSET towerStockLabel3,OFFSET towerStockLabel4,OFFSET towerStockLabel5
|
||||||
|
towerStockValues3D dd OFFSET towerHeartUses3D,OFFSET towerSealUses3D,OFFSET towerBulletUses3D,OFFSET towerBustUses3D,OFFSET towerEye3D,OFFSET towerPurseUses3D
|
||||||
|
.code
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,8 @@ BeginMerchant3D PROC
|
||||||
mov merchantTime3D, 0
|
mov merchantTime3D, 0
|
||||||
mov merchantReaction3D, 1280
|
mov merchantReaction3D, 1280
|
||||||
mov merchantMessage3D, 0
|
mov merchantMessage3D, 0
|
||||||
mov merchantTab3D, 0
|
mov merchantTab3D, 1
|
||||||
|
mov artifactBuyArmed3D,0
|
||||||
mov merchantCharmSelected3D, 0
|
mov merchantCharmSelected3D, 0
|
||||||
mov eax, selectedBack3D
|
mov eax, selectedBack3D
|
||||||
cmp eax, 12
|
cmp eax, 12
|
||||||
|
|
@ -48,49 +49,40 @@ merchant_purchase_done:
|
||||||
ret
|
ret
|
||||||
BuyMerchantBack3D ENDP
|
BuyMerchantBack3D ENDP
|
||||||
|
|
||||||
BuyMerchantCharm3D PROC uses ebx charmIndex:DWORD
|
BuyMerchantCharm3D PROC uses ebx esi charmIndex:DWORD
|
||||||
mov ebx, charmIndex
|
mov ebx,charmIndex
|
||||||
cmp ebx, 3
|
cmp ebx,CHARM_COUNT
|
||||||
ja charm_purchase_done
|
jae charm_purchase_done
|
||||||
mov eax, charmPrices3D[ebx*4]
|
lea esi,charmCloverUses
|
||||||
cmp bankroll, eax
|
mov eax,[esi+ebx*4]
|
||||||
|
add eax,charmUsesPack3D[ebx*4]
|
||||||
|
cmp eax,CHARM_MAX_USES
|
||||||
|
ja charm_purchase_limit
|
||||||
|
mov eax,charmPrices3D[ebx*4]
|
||||||
|
cmp bankroll,eax
|
||||||
jb charm_purchase_poor
|
jb charm_purchase_poor
|
||||||
sub bankroll, eax
|
sub bankroll,eax
|
||||||
mov ecx, charmUsesPack3D[ebx*4]
|
mov eax,charmUsesPack3D[ebx*4]
|
||||||
cmp ebx, 0
|
add [esi+ebx*4],eax
|
||||||
jne @F
|
mov merchantMessage3D,1
|
||||||
add charmCloverUses, ecx
|
|
||||||
jmp charm_bought
|
|
||||||
@@:
|
|
||||||
cmp ebx, 1
|
|
||||||
jne @F
|
|
||||||
add charmHorseshoeUses, ecx
|
|
||||||
jmp charm_bought
|
|
||||||
@@:
|
|
||||||
cmp ebx, 2
|
|
||||||
jne @F
|
|
||||||
add charmSkullUses, ecx
|
|
||||||
jmp charm_bought
|
|
||||||
@@:
|
|
||||||
cmp ebx, 3
|
|
||||||
jne charm_bought
|
|
||||||
add charmDevilUses, ecx
|
|
||||||
charm_bought:
|
|
||||||
mov merchantMessage3D, 1
|
|
||||||
mov merchantReaction3D, 0
|
|
||||||
mov merchantReactionKind3D, 2
|
|
||||||
call SaveProgress3D
|
call SaveProgress3D
|
||||||
invoke PlayCasinoSound3D, OFFSET soundCoin, 0, 1
|
invoke PlayCasinoSound3D,OFFSET soundCoin,0,1
|
||||||
|
jmp charm_purchase_done
|
||||||
|
charm_purchase_limit:
|
||||||
|
mov merchantMessage3D,3
|
||||||
ret
|
ret
|
||||||
charm_purchase_poor:
|
charm_purchase_poor:
|
||||||
mov merchantMessage3D, 2
|
mov merchantMessage3D,2
|
||||||
mov merchantReaction3D, 0
|
|
||||||
mov merchantReactionKind3D, 1
|
|
||||||
charm_purchase_done:
|
charm_purchase_done:
|
||||||
ret
|
ret
|
||||||
BuyMerchantCharm3D ENDP
|
BuyMerchantCharm3D ENDP
|
||||||
|
|
||||||
HandleMerchant3D PROC uses ebx
|
HandleMerchant3D PROC uses ebx
|
||||||
|
cmp merchantTab3D,1
|
||||||
|
jne @F
|
||||||
|
call HandleArtifactShop3D
|
||||||
|
ret
|
||||||
|
@@:
|
||||||
mov eax, merchantSelected3D
|
mov eax, merchantSelected3D
|
||||||
cmp eax, merchantPreviousFocus3D
|
cmp eax, merchantPreviousFocus3D
|
||||||
je @F
|
je @F
|
||||||
|
|
@ -256,6 +248,11 @@ HandleMerchant3D ENDP
|
||||||
|
|
||||||
RenderMerchant3D PROC uses ebx esi edi
|
RenderMerchant3D PROC uses ebx esi edi
|
||||||
local rowY:DWORD,start:DWORD,frame:DWORD,ink:DWORD
|
local rowY:DWORD,start:DWORD,frame:DWORD,ink:DWORD
|
||||||
|
cmp merchantTab3D,1
|
||||||
|
jne @F
|
||||||
|
call RenderArtifactShop3D
|
||||||
|
ret
|
||||||
|
@@:
|
||||||
invoke DrawBox, 0, 0, 320, 240, 00252B24h
|
invoke DrawBox, 0, 0, 320, 240, 00252B24h
|
||||||
invoke DrawBox, 0, 21, 320, 7, 00836638h
|
invoke DrawBox, 0, 21, 320, 7, 00836638h
|
||||||
invoke DrawBox, 0, 151, 320, 63, 003C3024h
|
invoke DrawBox, 0, 151, 320, 63, 003C3024h
|
||||||
|
|
@ -451,3 +448,5 @@ merchant_render_footer:
|
||||||
invoke DrawString8x8, 8, 229, OFFSET merchantShopKeysWithTabs, 00C5C7B8h
|
invoke DrawString8x8, 8, 229, OFFSET merchantShopKeysWithTabs, 00C5C7B8h
|
||||||
ret
|
ret
|
||||||
RenderMerchant3D ENDP
|
RenderMerchant3D ENDP
|
||||||
|
|
||||||
|
include src_graphics\artifact_shop.inc
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,8 @@ NativeBJSettle3D PROC result:DWORD
|
||||||
add eax, edx
|
add eax, edx
|
||||||
bj_settle_credit:
|
bj_settle_credit:
|
||||||
add bankroll, eax
|
add bankroll, eax
|
||||||
|
sub eax,cbStake3D
|
||||||
|
invoke TriggerCharmWinBonus,eax
|
||||||
invoke PlayCasinoSound3D, OFFSET soundRoundWin, 0, 1
|
invoke PlayCasinoSound3D, OFFSET soundRoundWin, 0, 1
|
||||||
jmp bj_settle_save
|
jmp bj_settle_save
|
||||||
bj_settle_loss:
|
bj_settle_loss:
|
||||||
|
|
@ -230,6 +232,9 @@ bj_animate_hit:
|
||||||
jne bj_begin_dealer
|
jne bj_begin_dealer
|
||||||
jmp bj_begin_player
|
jmp bj_begin_player
|
||||||
bj_player_bust:
|
bj_player_bust:
|
||||||
|
call TryTowerBustSave3D
|
||||||
|
test eax,eax
|
||||||
|
jnz bj_begin_dealer
|
||||||
invoke FinishBJPlayer3D, 1
|
invoke FinishBJPlayer3D, 1
|
||||||
ret
|
ret
|
||||||
bj_animate_dealer:
|
bj_animate_dealer:
|
||||||
|
|
@ -327,6 +332,13 @@ bj_ready_input:
|
||||||
jnz bj_tourney_report
|
jnz bj_tourney_report
|
||||||
ret
|
ret
|
||||||
bj_tourney_report:
|
bj_tourney_report:
|
||||||
|
cmp cbOutcome3D,2
|
||||||
|
jne @F
|
||||||
|
mov towerFloorState,TOWER_STATE_BRIEFING
|
||||||
|
mov engineMode,MODE_HELL_TOWER
|
||||||
|
call ClearKeys3D
|
||||||
|
ret
|
||||||
|
@@:
|
||||||
cmp cbOutcome3D, 1
|
cmp cbOutcome3D, 1
|
||||||
je bj_tourney_loss
|
je bj_tourney_loss
|
||||||
invoke TowerReportRoundOutcome, 1
|
invoke TowerReportRoundOutcome, 1
|
||||||
|
|
|
||||||
|
|
@ -186,10 +186,14 @@ SettleNativeClover3D PROC
|
||||||
jmp clp_settle_leave
|
jmp clp_settle_leave
|
||||||
@@:
|
@@:
|
||||||
invoke PlayCasinoSound3D,OFFSET soundRoundWin,0,1
|
invoke PlayCasinoSound3D,OFFSET soundRoundWin,0,1
|
||||||
invoke TriggerCharmWinBonus, clpGross3D
|
mov eax,clpGross3D
|
||||||
|
sub eax,clpStake3D
|
||||||
|
invoke TriggerCharmWinBonus,eax
|
||||||
jmp clp_settle_leave
|
jmp clp_settle_leave
|
||||||
clp_settle_loss:
|
clp_settle_loss:
|
||||||
invoke TriggerCharmLossProtection, clpStake3D
|
mov eax,clpStake3D
|
||||||
|
sub eax,clpGross3D
|
||||||
|
invoke TriggerCharmLossProtection,eax
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jnz clp_settle_leave
|
jnz clp_settle_leave
|
||||||
invoke PlayCasinoSound3D,OFFSET soundRoundLose,0,1
|
invoke PlayCasinoSound3D,OFFSET soundRoundLose,0,1
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,9 @@ CoinEscape3D PROC
|
||||||
mov paused3D,0
|
mov paused3D,0
|
||||||
cmp tournamentMode, 1
|
cmp tournamentMode, 1
|
||||||
jne @F
|
jne @F
|
||||||
|
call CoinSettle3D
|
||||||
|
call CloseCoinDetail3D
|
||||||
|
mov coinExitQueued3D,0
|
||||||
call TowerExitToHall
|
call TowerExitToHall
|
||||||
ret
|
ret
|
||||||
@@:
|
@@:
|
||||||
|
|
@ -96,6 +99,7 @@ CoinSettle3D PROC
|
||||||
jbe @F
|
jbe @F
|
||||||
mov bankroll,1000000000
|
mov bankroll,1000000000
|
||||||
@@:
|
@@:
|
||||||
|
invoke TriggerCharmWinBonus,coin3d_bet
|
||||||
invoke PlayCasinoSound3D,OFFSET soundCoinDing,0,1
|
invoke PlayCasinoSound3D,OFFSET soundCoinDing,0,1
|
||||||
jmp coin_settle_save
|
jmp coin_settle_save
|
||||||
coin_settle_loss:
|
coin_settle_loss:
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,11 @@ DiceEscape3D PROC
|
||||||
ret
|
ret
|
||||||
dice_escape_now:
|
dice_escape_now:
|
||||||
mov diceExitQueued3D,0
|
mov diceExitQueued3D,0
|
||||||
|
cmp tournamentMode,1
|
||||||
|
jne @F
|
||||||
|
call TowerExitToHall
|
||||||
|
ret
|
||||||
|
@@:
|
||||||
mov engineMode,MODE_WALK
|
mov engineMode,MODE_WALK
|
||||||
call ClearKeys3D
|
call ClearKeys3D
|
||||||
invoke PlayCasinoSound3D,0,0,0
|
invoke PlayCasinoSound3D,0,0,0
|
||||||
|
|
|
||||||
|
|
@ -127,6 +127,8 @@ NativeDurakSettle3D PROC result:DWORD
|
||||||
shl eax, 1
|
shl eax, 1
|
||||||
@@:
|
@@:
|
||||||
add bankroll, eax
|
add bankroll, eax
|
||||||
|
sub eax,dkStake3D
|
||||||
|
invoke TriggerCharmWinBonus,eax
|
||||||
invoke PlayCasinoSound3D, OFFSET soundRoundWin, 0, 1
|
invoke PlayCasinoSound3D, OFFSET soundRoundWin, 0, 1
|
||||||
jmp dk_settle_save
|
jmp dk_settle_save
|
||||||
dk_settle_loss:
|
dk_settle_loss:
|
||||||
|
|
|
||||||
|
|
@ -255,6 +255,8 @@ PokerFold3D PROC actor:DWORD
|
||||||
je poker_fold_player
|
je poker_fold_player
|
||||||
mov eax, pkPot3D
|
mov eax, pkPot3D
|
||||||
add bankroll, eax
|
add bankroll, eax
|
||||||
|
sub eax,pkPaid3D[0]
|
||||||
|
invoke TriggerCharmWinBonus,eax
|
||||||
mov pkOutcome3D, 0
|
mov pkOutcome3D, 0
|
||||||
invoke PlayCasinoSound3D, OFFSET soundRoundWin, 0, 1
|
invoke PlayCasinoSound3D, OFFSET soundRoundWin, 0, 1
|
||||||
jmp poker_fold_settled
|
jmp poker_fold_settled
|
||||||
|
|
@ -343,6 +345,8 @@ poker_evaluate_player:
|
||||||
je poker_showdown_tie
|
je poker_showdown_tie
|
||||||
mov eax, pkPot3D
|
mov eax, pkPot3D
|
||||||
add bankroll, eax
|
add bankroll, eax
|
||||||
|
sub eax,pkPaid3D[0]
|
||||||
|
invoke TriggerCharmWinBonus,eax
|
||||||
mov pkOutcome3D, 0
|
mov pkOutcome3D, 0
|
||||||
invoke PlayCasinoSound3D, OFFSET soundRoundWin, 0, 1
|
invoke PlayCasinoSound3D, OFFSET soundRoundWin, 0, 1
|
||||||
jmp poker_showdown_settled
|
jmp poker_showdown_settled
|
||||||
|
|
|
||||||
|
|
@ -173,10 +173,14 @@ slot_settle_stops:
|
||||||
jmp slot_settle_exit
|
jmp slot_settle_exit
|
||||||
@@:
|
@@:
|
||||||
invoke PlayCasinoSound3D,OFFSET soundRoundWin,0,1
|
invoke PlayCasinoSound3D,OFFSET soundRoundWin,0,1
|
||||||
invoke TriggerCharmWinBonus, slotWinAmount
|
mov eax,slotWinAmount
|
||||||
|
sub eax,slotStake3D
|
||||||
|
invoke TriggerCharmWinBonus,eax
|
||||||
jmp slot_settle_exit
|
jmp slot_settle_exit
|
||||||
slot_settle_loss:
|
slot_settle_loss:
|
||||||
invoke TriggerCharmLossProtection, slotStake3D
|
mov eax,slotStake3D
|
||||||
|
sub eax,slotWinAmount
|
||||||
|
invoke TriggerCharmLossProtection,eax
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jnz slot_settle_exit
|
jnz slot_settle_exit
|
||||||
invoke PlayCasinoSound3D,OFFSET soundRoundLose,0,1
|
invoke PlayCasinoSound3D,OFFSET soundRoundLose,0,1
|
||||||
|
|
|
||||||
|
|
@ -134,12 +134,15 @@ wheel_bank_cap:
|
||||||
mov ecx, wheelReturn3D
|
mov ecx, wheelReturn3D
|
||||||
cmp ecx, wheelStake3D
|
cmp ecx, wheelStake3D
|
||||||
ja wheel_win_charm
|
ja wheel_win_charm
|
||||||
cmp ecx, 0
|
je wheel_charm_done
|
||||||
jne wheel_charm_done
|
mov eax,wheelStake3D
|
||||||
invoke TriggerCharmLossProtection, wheelStake3D
|
sub eax,wheelReturn3D
|
||||||
|
invoke TriggerCharmLossProtection,eax
|
||||||
jmp wheel_charm_done
|
jmp wheel_charm_done
|
||||||
wheel_win_charm:
|
wheel_win_charm:
|
||||||
invoke TriggerCharmWinBonus, wheelReturn3D
|
mov eax,wheelReturn3D
|
||||||
|
sub eax,wheelStake3D
|
||||||
|
invoke TriggerCharmWinBonus,eax
|
||||||
wheel_charm_done:
|
wheel_charm_done:
|
||||||
mov roulState, 2
|
mov roulState, 2
|
||||||
xor eax,eax
|
xor eax,eax
|
||||||
|
|
@ -519,6 +522,11 @@ WheelEscape3D PROC
|
||||||
ret
|
ret
|
||||||
wheel_leave_hall:
|
wheel_leave_hall:
|
||||||
mov wheelExitQueued3D,0
|
mov wheelExitQueued3D,0
|
||||||
|
cmp tournamentMode,1
|
||||||
|
jne @F
|
||||||
|
call TowerExitToHall
|
||||||
|
ret
|
||||||
|
@@:
|
||||||
mov engineMode,MODE_WALK
|
mov engineMode,MODE_WALK
|
||||||
call ClearKeys3D
|
call ClearKeys3D
|
||||||
invoke PlayCasinoSound3D,0,0,0
|
invoke PlayCasinoSound3D,0,0,0
|
||||||
|
|
|
||||||
|
|
@ -549,14 +549,26 @@ LoadProgress3D PROC uses ebx
|
||||||
mov charmHorseshoeUses, 0
|
mov charmHorseshoeUses, 0
|
||||||
mov charmSkullUses, 0
|
mov charmSkullUses, 0
|
||||||
mov charmDevilUses, 0
|
mov charmDevilUses, 0
|
||||||
|
mov charmEnabledMask3D,7
|
||||||
invoke CreateFileA, OFFSET savePath3D, 80000000h, 1, 0, 3, 80h, 0
|
invoke CreateFileA, OFFSET savePath3D, 80000000h, 1, 0, 3, 80h, 0
|
||||||
cmp eax, -1
|
cmp eax, -1
|
||||||
je progress_loaded
|
je progress_loaded
|
||||||
mov ebx, eax
|
mov ebx, eax
|
||||||
invoke ReadFile, ebx, OFFSET saveData3D, 32, OFFSET saveIo3D, 0
|
invoke ReadFile, ebx, OFFSET saveData3D, 40, OFFSET saveIo3D, 0
|
||||||
invoke CloseHandle, ebx
|
invoke CloseHandle, ebx
|
||||||
cmp saveIo3D, 16
|
cmp saveIo3D, 16
|
||||||
jb progress_loaded
|
jb progress_loaded
|
||||||
|
cmp saveData3D,34443343h
|
||||||
|
jne progress_legacy_version
|
||||||
|
cmp saveIo3D,40
|
||||||
|
jne progress_loaded
|
||||||
|
invoke PreviewArtifactSignature3D,OFFSET saveData3D
|
||||||
|
cmp eax,saveData3D[36]
|
||||||
|
jne progress_loaded
|
||||||
|
mov eax,saveData3D[32]
|
||||||
|
mov charmEnabledMask3D,eax
|
||||||
|
jmp progress_version_ok
|
||||||
|
progress_legacy_version:
|
||||||
cmp saveData3D, 33443343h
|
cmp saveData3D, 33443343h
|
||||||
je progress_version_ok
|
je progress_version_ok
|
||||||
cmp saveData3D, 32443343h
|
cmp saveData3D, 32443343h
|
||||||
|
|
@ -607,6 +619,7 @@ progress_version_ok:
|
||||||
mov eax, saveData3D[28]
|
mov eax, saveData3D[28]
|
||||||
mov charmDevilUses, eax
|
mov charmDevilUses, eax
|
||||||
progress_loaded:
|
progress_loaded:
|
||||||
|
call ClampArtifacts3D
|
||||||
ret
|
ret
|
||||||
LoadProgress3D ENDP
|
LoadProgress3D ENDP
|
||||||
|
|
||||||
|
|
@ -625,7 +638,7 @@ SaveProgress3D PROC uses ebx
|
||||||
ret
|
ret
|
||||||
@@:
|
@@:
|
||||||
invoke CreateDirectoryA, OFFSET runtime3D, 0
|
invoke CreateDirectoryA, OFFSET runtime3D, 0
|
||||||
mov saveData3D, 33443343h
|
mov saveData3D, 34443343h
|
||||||
mov eax, bankroll
|
mov eax, bankroll
|
||||||
mov saveData3D[4], eax
|
mov saveData3D[4], eax
|
||||||
mov eax, ownedBacks3D
|
mov eax, ownedBacks3D
|
||||||
|
|
@ -640,11 +653,15 @@ SaveProgress3D PROC uses ebx
|
||||||
mov saveData3D[24], eax
|
mov saveData3D[24], eax
|
||||||
mov eax, charmDevilUses
|
mov eax, charmDevilUses
|
||||||
mov saveData3D[28], eax
|
mov saveData3D[28], eax
|
||||||
|
mov eax,charmEnabledMask3D
|
||||||
|
mov saveData3D[32],eax
|
||||||
|
invoke PreviewArtifactSignature3D,OFFSET saveData3D
|
||||||
|
mov saveData3D[36],eax
|
||||||
invoke CreateFileA, OFFSET savePath3D, 40000000h, 0, 0, 2, 80h, 0
|
invoke CreateFileA, OFFSET savePath3D, 40000000h, 0, 0, 2, 80h, 0
|
||||||
cmp eax, -1
|
cmp eax, -1
|
||||||
je progress_saved
|
je progress_saved
|
||||||
mov ebx, eax
|
mov ebx, eax
|
||||||
invoke WriteFile, ebx, OFFSET saveData3D, 32, OFFSET saveIo3D, 0
|
invoke WriteFile, ebx, OFFSET saveData3D, 40, OFFSET saveIo3D, 0
|
||||||
invoke CloseHandle, ebx
|
invoke CloseHandle, ebx
|
||||||
progress_saved:
|
progress_saved:
|
||||||
ret
|
ret
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@ displaySettingsPath3D db "runtime\display.cfg",0
|
||||||
displaySettingsData3D dd 44535031h,1,0
|
displaySettingsData3D dd 44535031h,1,0
|
||||||
displaySettingsIo3D dd 0
|
displaySettingsIo3D dd 0
|
||||||
savePath3D db "runtime\casino3d-progress.dat",0
|
savePath3D db "runtime\casino3d-progress.dat",0
|
||||||
saveData3D dd 32443343h, 10000, 0, 0, 0, 0, 0, 0
|
saveData3D dd 32443343h,10000,0,0,0,0,0,0,7,0
|
||||||
saveIo3D dd 0
|
saveIo3D dd 0
|
||||||
previewBackMap3D dd 0,3,5,2
|
previewBackMap3D dd 0,3,5,2
|
||||||
textPause3D db 202,192,199,200,205,206,32,47,32,205,192,209,210,208,206,201,202,200,0
|
textPause3D db 202,192,199,200,205,206,32,47,32,205,192,209,210,208,206,201,202,200,0
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,8 @@ RRPartyWin3D PROC
|
||||||
imul eax,rrPartySize3D
|
imul eax,rrPartySize3D
|
||||||
mov rr3d_payout,eax
|
mov rr3d_payout,eax
|
||||||
add bankroll,eax
|
add bankroll,eax
|
||||||
|
sub eax,rrPartyStake3D
|
||||||
|
invoke TriggerCharmWinBonus,eax
|
||||||
mov rr3d_state,RR_WIN
|
mov rr3d_state,RR_WIN
|
||||||
invoke PlayCasinoSound3D,OFFSET soundRoundWin,0,20003h
|
invoke PlayCasinoSound3D,OFFSET soundRoundWin,0,20003h
|
||||||
invoke NpcRecordRound3D,6,1
|
invoke NpcRecordRound3D,6,1
|
||||||
|
|
@ -93,6 +95,7 @@ RRPartyLose3D PROC
|
||||||
cmp rrPartySettled3D,0
|
cmp rrPartySettled3D,0
|
||||||
jne rr_party_lose_done
|
jne rr_party_lose_done
|
||||||
mov rrPartySettled3D,1
|
mov rrPartySettled3D,1
|
||||||
|
invoke TriggerCharmLossProtection,rrPartyStake3D
|
||||||
mov rr3d_state,RR_GLITCH
|
mov rr3d_state,RR_GLITCH
|
||||||
invoke NpcRecordRound3D,6,0
|
invoke NpcRecordRound3D,6,0
|
||||||
call SaveProgress3D
|
call SaveProgress3D
|
||||||
|
|
|
||||||
|
|
@ -185,12 +185,14 @@ rr_live_round:
|
||||||
add bankroll, eax
|
add bankroll, eax
|
||||||
mov rr3d_state, RR_WIN
|
mov rr3d_state, RR_WIN
|
||||||
mov rrPartySettled3D,1
|
mov rrPartySettled3D,1
|
||||||
|
invoke TriggerCharmWinBonus,rr3d_bet
|
||||||
invoke PlayCasinoSound3D, OFFSET soundRoundWin, 0, 20003h
|
invoke PlayCasinoSound3D, OFFSET soundRoundWin, 0, 20003h
|
||||||
invoke NpcRecordRound3D,6,1
|
invoke NpcRecordRound3D,6,1
|
||||||
call SaveProgress3D
|
call SaveProgress3D
|
||||||
ret
|
ret
|
||||||
rr_player_lost:
|
rr_player_lost:
|
||||||
mov rrPartySettled3D,1
|
mov rrPartySettled3D,1
|
||||||
|
invoke TriggerCharmLossProtection,rr3d_bet
|
||||||
mov rr3d_state, RR_GLITCH
|
mov rr3d_state, RR_GLITCH
|
||||||
invoke NpcRecordRound3D,6,0
|
invoke NpcRecordRound3D,6,0
|
||||||
call SaveProgress3D
|
call SaveProgress3D
|
||||||
|
|
|
||||||
|
|
@ -413,12 +413,15 @@ FinishScratch3D PROC
|
||||||
mov ecx, scrGross3D
|
mov ecx, scrGross3D
|
||||||
cmp ecx, scrStake3D
|
cmp ecx, scrStake3D
|
||||||
ja scratch_charm_win
|
ja scratch_charm_win
|
||||||
cmp ecx, 0
|
je @F
|
||||||
jne @F
|
mov eax,scrStake3D
|
||||||
invoke TriggerCharmLossProtection, scrStake3D
|
sub eax,scrGross3D
|
||||||
|
invoke TriggerCharmLossProtection,eax
|
||||||
jmp @F
|
jmp @F
|
||||||
scratch_charm_win:
|
scratch_charm_win:
|
||||||
invoke TriggerCharmWinBonus, scrGross3D
|
mov eax,scrGross3D
|
||||||
|
sub eax,scrStake3D
|
||||||
|
invoke TriggerCharmWinBonus,eax
|
||||||
@@:
|
@@:
|
||||||
call ScratchStartPayout3D
|
call ScratchStartPayout3D
|
||||||
call SaveProgress3D
|
call SaveProgress3D
|
||||||
|
|
|
||||||
278
src_graphics/tower_relics.inc
Normal file
278
src_graphics/tower_relics.inc
Normal file
|
|
@ -0,0 +1,278 @@
|
||||||
|
; Run-local relics. Never serialized; all stakes still use the profile bankroll.
|
||||||
|
ResetTowerRelics3D PROC
|
||||||
|
mov towerHeartUses3D,0
|
||||||
|
mov towerSealUses3D,0
|
||||||
|
mov towerSealStage3D,0
|
||||||
|
mov towerBulletUses3D,0
|
||||||
|
mov towerBustUses3D,0
|
||||||
|
mov towerEye3D,0
|
||||||
|
mov towerPurseUses3D,0
|
||||||
|
mov towerRewardPending3D,0
|
||||||
|
mov towerRewardSelection3D,0
|
||||||
|
mov towerEntryBank3D,0
|
||||||
|
mov towerRewardOffers3D,0
|
||||||
|
mov towerRewardOffers3D[4],0
|
||||||
|
mov towerRewardOffers3D[8],0
|
||||||
|
ret
|
||||||
|
ResetTowerRelics3D ENDP
|
||||||
|
|
||||||
|
PrepareTowerReward3D PROC
|
||||||
|
mov towerRewardPending3D,1
|
||||||
|
mov towerRewardSelection3D,0
|
||||||
|
mov towerRewardOffers3D,0
|
||||||
|
mov towerRewardOffers3D[8],5
|
||||||
|
mov eax,towerStage
|
||||||
|
cmp towerFloorState,TOWER_STATE_CLEAR
|
||||||
|
jne @F
|
||||||
|
inc eax
|
||||||
|
@@:
|
||||||
|
mov towerSealStage3D,eax
|
||||||
|
mov towerSealUses3D,0
|
||||||
|
mov ecx,1
|
||||||
|
cmp eax,3
|
||||||
|
jne @F
|
||||||
|
mov ecx,3
|
||||||
|
@@:
|
||||||
|
cmp eax,4
|
||||||
|
jne @F
|
||||||
|
mov ecx,2
|
||||||
|
@@:
|
||||||
|
cmp eax,6
|
||||||
|
jne @F
|
||||||
|
mov ecx,4
|
||||||
|
@@:
|
||||||
|
mov towerRewardOffers3D[4],ecx
|
||||||
|
call ClearKeys3D
|
||||||
|
mov mouseClick3D,0
|
||||||
|
ret
|
||||||
|
PrepareTowerReward3D ENDP
|
||||||
|
|
||||||
|
ChooseTowerRelic3D PROC index:DWORD
|
||||||
|
cmp towerRewardPending3D,1
|
||||||
|
jne tower_choose_done
|
||||||
|
mov ecx,index
|
||||||
|
cmp ecx,2
|
||||||
|
ja tower_choose_done
|
||||||
|
mov eax,towerRewardOffers3D[ecx*4]
|
||||||
|
cmp eax,0
|
||||||
|
jne @F
|
||||||
|
inc towerHeartUses3D
|
||||||
|
@@:
|
||||||
|
cmp eax,1
|
||||||
|
jne @F
|
||||||
|
mov towerSealUses3D,2
|
||||||
|
@@:
|
||||||
|
cmp eax,2
|
||||||
|
jne @F
|
||||||
|
add towerBulletUses3D,2
|
||||||
|
@@:
|
||||||
|
cmp eax,3
|
||||||
|
jne @F
|
||||||
|
add towerBustUses3D,2
|
||||||
|
@@:
|
||||||
|
cmp eax,4
|
||||||
|
jne @F
|
||||||
|
mov towerEye3D,1
|
||||||
|
@@:
|
||||||
|
cmp eax,5
|
||||||
|
jne @F
|
||||||
|
add towerPurseUses3D,2
|
||||||
|
@@:
|
||||||
|
mov towerRewardPending3D,0
|
||||||
|
call ClearKeys3D
|
||||||
|
mov mouseClick3D,0
|
||||||
|
tower_choose_done:
|
||||||
|
ret
|
||||||
|
ChooseTowerRelic3D ENDP
|
||||||
|
|
||||||
|
HandleTowerReward3D PROC
|
||||||
|
invoke Pressed3D,1Bh
|
||||||
|
test eax,eax
|
||||||
|
jz @F
|
||||||
|
call TowerExitToHall
|
||||||
|
ret
|
||||||
|
@@:
|
||||||
|
invoke Pressed3D,25h
|
||||||
|
test eax,eax
|
||||||
|
jz @F
|
||||||
|
cmp towerRewardSelection3D,0
|
||||||
|
je @F
|
||||||
|
dec towerRewardSelection3D
|
||||||
|
@@:
|
||||||
|
invoke Pressed3D,27h
|
||||||
|
test eax,eax
|
||||||
|
jz @F
|
||||||
|
cmp towerRewardSelection3D,2
|
||||||
|
jae @F
|
||||||
|
inc towerRewardSelection3D
|
||||||
|
@@:
|
||||||
|
cmp mouseClick3D,0
|
||||||
|
je tower_reward_keys
|
||||||
|
mov mouseClick3D,0
|
||||||
|
cmp mouseY3D,73
|
||||||
|
jb tower_reward_keys
|
||||||
|
cmp mouseY3D,183
|
||||||
|
jae tower_reward_keys
|
||||||
|
mov eax,mouseX3D
|
||||||
|
sub eax,8
|
||||||
|
js tower_reward_keys
|
||||||
|
xor edx,edx
|
||||||
|
mov ecx,102
|
||||||
|
div ecx
|
||||||
|
cmp eax,2
|
||||||
|
ja tower_reward_keys
|
||||||
|
mov towerRewardSelection3D,eax
|
||||||
|
invoke ChooseTowerRelic3D,eax
|
||||||
|
ret
|
||||||
|
tower_reward_keys:
|
||||||
|
invoke Pressed3D,31h
|
||||||
|
test eax,eax
|
||||||
|
jz @F
|
||||||
|
invoke ChooseTowerRelic3D,0
|
||||||
|
ret
|
||||||
|
@@:
|
||||||
|
invoke Pressed3D,32h
|
||||||
|
test eax,eax
|
||||||
|
jz @F
|
||||||
|
invoke ChooseTowerRelic3D,1
|
||||||
|
ret
|
||||||
|
@@:
|
||||||
|
invoke Pressed3D,33h
|
||||||
|
test eax,eax
|
||||||
|
jz @F
|
||||||
|
invoke ChooseTowerRelic3D,2
|
||||||
|
ret
|
||||||
|
@@:
|
||||||
|
invoke Pressed3D,0Dh
|
||||||
|
test eax,eax
|
||||||
|
jnz tower_reward_confirm
|
||||||
|
invoke Pressed3D,20h
|
||||||
|
test eax,eax
|
||||||
|
jz tower_reward_done
|
||||||
|
tower_reward_confirm:
|
||||||
|
invoke ChooseTowerRelic3D,towerRewardSelection3D
|
||||||
|
tower_reward_done:
|
||||||
|
ret
|
||||||
|
HandleTowerReward3D ENDP
|
||||||
|
|
||||||
|
RenderTowerReward3D PROC uses ebx esi edi
|
||||||
|
local x:DWORD,y:DWORD
|
||||||
|
invoke DrawBox,0,0,320,240,000C080Bh
|
||||||
|
invoke DrawBoxBorder,4,24,312,192,0014090Dh,00D08030h,2
|
||||||
|
invoke DrawString8x8,16,32,OFFSET towerRewardTitle3D,00FFD080h
|
||||||
|
invoke DrawString8x8,16,47,OFFSET towerRewardHint3D,00CCCCBBh
|
||||||
|
xor ebx,ebx
|
||||||
|
mov x,8
|
||||||
|
tower_reward_card:
|
||||||
|
mov edx,00604430h
|
||||||
|
cmp ebx,towerRewardSelection3D
|
||||||
|
jne @F
|
||||||
|
mov edx,00FFCC66h
|
||||||
|
@@:
|
||||||
|
invoke DrawBoxBorder,x,73,100,110,002A1717h,edx,2
|
||||||
|
mov esi,towerRewardOffers3D[ebx*4]
|
||||||
|
mov eax,x
|
||||||
|
add eax,4
|
||||||
|
invoke DrawString8x8,eax,83,towerRelicNames3D[esi*4],00FFDD88h
|
||||||
|
mov edi,towerRelicDescriptions3D[esi*4]
|
||||||
|
mov y,105
|
||||||
|
push ebx
|
||||||
|
mov ebx,3
|
||||||
|
@@:
|
||||||
|
mov eax,x
|
||||||
|
add eax,4
|
||||||
|
invoke DrawString8x8,eax,y,edi,00DDD3CCh
|
||||||
|
tower_reward_text_end:
|
||||||
|
cmp BYTE PTR [edi],0
|
||||||
|
je tower_reward_text_next
|
||||||
|
inc edi
|
||||||
|
jmp tower_reward_text_end
|
||||||
|
tower_reward_text_next:
|
||||||
|
inc edi
|
||||||
|
add y,13
|
||||||
|
dec ebx
|
||||||
|
jnz @B
|
||||||
|
pop ebx
|
||||||
|
mov eax,x
|
||||||
|
add eax,4
|
||||||
|
invoke DrawString8x8,eax,161,OFFSET towerRunOnly3D,00AA9999h
|
||||||
|
add x,102
|
||||||
|
inc ebx
|
||||||
|
cmp ebx,3
|
||||||
|
jb tower_reward_card
|
||||||
|
invoke DrawString8x8,16,195,OFFSET towerRewardKeys3D,00FFDD88h
|
||||||
|
call RenderTowerRelicStock3D
|
||||||
|
ret
|
||||||
|
RenderTowerReward3D ENDP
|
||||||
|
|
||||||
|
; Six compact counters remain visible between floors and during play.
|
||||||
|
RenderTowerRelicStock3D PROC uses ebx esi
|
||||||
|
local x:DWORD,y:DWORD,stepX:DWORD
|
||||||
|
mov x,4
|
||||||
|
mov y,229
|
||||||
|
mov stepX,52
|
||||||
|
cmp engineMode,MODE_HELL_TOWER
|
||||||
|
je tower_stock_menu
|
||||||
|
; Keep table action buttons at the bottom unobscured.
|
||||||
|
invoke DrawBox,100,4,216,26,0014090Dh
|
||||||
|
mov x,104
|
||||||
|
mov y,7
|
||||||
|
mov stepX,70
|
||||||
|
jmp tower_stock_start
|
||||||
|
tower_stock_menu:
|
||||||
|
invoke DrawBox,0,226,320,14,0014090Dh
|
||||||
|
tower_stock_start:
|
||||||
|
xor ebx,ebx
|
||||||
|
tower_stock_counter:
|
||||||
|
invoke DrawString8x8,x,y,towerStockLabels3D[ebx*4],00CCAA88h
|
||||||
|
mov esi,towerStockValues3D[ebx*4]
|
||||||
|
invoke FormatNumber,DWORD PTR [esi],OFFSET towerRelicNum3D
|
||||||
|
mov eax,x
|
||||||
|
add eax,26
|
||||||
|
invoke DrawString8x8,eax,y,OFFSET towerRelicNum3D,00FFFFFFh
|
||||||
|
mov eax,stepX
|
||||||
|
add x,eax
|
||||||
|
inc ebx
|
||||||
|
cmp ebx,3
|
||||||
|
jne @F
|
||||||
|
cmp engineMode,MODE_HELL_TOWER
|
||||||
|
je @F
|
||||||
|
mov x,104
|
||||||
|
add y,12
|
||||||
|
@@:
|
||||||
|
cmp ebx,6
|
||||||
|
jb tower_stock_counter
|
||||||
|
ret
|
||||||
|
RenderTowerRelicStock3D ENDP
|
||||||
|
|
||||||
|
TryTowerBustSave3D PROC
|
||||||
|
cmp tournamentMode,1
|
||||||
|
jne tower_bust_none
|
||||||
|
cmp towerBustUses3D,0
|
||||||
|
je tower_bust_none
|
||||||
|
dec towerBustUses3D
|
||||||
|
dec cbPlayerCount3D
|
||||||
|
invoke NativeBJScore3D,OFFSET cbPlayer3D,cbPlayerCount3D
|
||||||
|
mov cbPlayerScore3D,eax
|
||||||
|
invoke CopyString3D,OFFSET towerBustMessage3D,OFFSET flashMessage
|
||||||
|
mov flashTimer,140
|
||||||
|
mov eax,1
|
||||||
|
ret
|
||||||
|
tower_bust_none:
|
||||||
|
xor eax,eax
|
||||||
|
ret
|
||||||
|
TryTowerBustSave3D ENDP
|
||||||
|
|
||||||
|
UpdateTowerEye3D PROC
|
||||||
|
cmp tournamentMode,1
|
||||||
|
jne tower_eye_done
|
||||||
|
cmp towerEye3D,1
|
||||||
|
jne tower_eye_done
|
||||||
|
mov eax,bs3d_shellIndex
|
||||||
|
cmp eax,bs3d_shellCount
|
||||||
|
jae tower_eye_done
|
||||||
|
mov eax,bs3d_shells[eax*4]
|
||||||
|
mov bs3d_known,eax
|
||||||
|
tower_eye_done:
|
||||||
|
ret
|
||||||
|
UpdateTowerEye3D ENDP
|
||||||
|
|
@ -640,6 +640,7 @@ arrival_admit_sequence:
|
||||||
jne arrival_test_fail
|
jne arrival_test_fail
|
||||||
mov bankroll, 35000
|
mov bankroll, 35000
|
||||||
call BeginMerchant3D
|
call BeginMerchant3D
|
||||||
|
mov merchantTab3D,0
|
||||||
mov merchantSelected3D, 5
|
mov merchantSelected3D, 5
|
||||||
mov merchantReaction3D, 1280
|
mov merchantReaction3D, 1280
|
||||||
mov eax, bankroll
|
mov eax, bankroll
|
||||||
|
|
|
||||||
502
tools/tests/artifacts_test.inc
Normal file
502
tools/tests/artifacts_test.inc
Normal file
|
|
@ -0,0 +1,502 @@
|
||||||
|
; Native regression: real production procedures, isolated output paths.
|
||||||
|
.data
|
||||||
|
artifactTestPath3D db "build\artifacts\profile.dat",0
|
||||||
|
artifactTestDir3D db "build\artifacts",0
|
||||||
|
artifactTestPreview3D db "build\artifacts\preview.dat",0
|
||||||
|
artifactTestLegacy3D db "build\artifacts\legacy.dat",0
|
||||||
|
artifactTestProfileName3D db "profile.dat",0
|
||||||
|
artifactTestLegacyName3D db "legacy.dat",0
|
||||||
|
artifactTestBmp3D db "build\artifacts\shop.bmp",0
|
||||||
|
artifactTestRewardBmp3D db "build\artifacts\rewards.bmp",0
|
||||||
|
artifactTestHeader3D db 42h,4Dh
|
||||||
|
dd 1228854
|
||||||
|
dw 0,0
|
||||||
|
dd 54,40,640,-480
|
||||||
|
dw 1,32
|
||||||
|
dd 0,1228800,0,0,0,0
|
||||||
|
.code
|
||||||
|
ArtifactTestCapture3D PROC uses ebx path:DWORD
|
||||||
|
local io:DWORD
|
||||||
|
invoke CreateFileA,path,40000000h,0,0,2,80h,0
|
||||||
|
mov ebx,eax
|
||||||
|
invoke WriteFile,ebx,OFFSET artifactTestHeader3D,54,ADDR io,0
|
||||||
|
invoke WriteFile,ebx,OFFSET screenBuffer,SCREEN_SIZE*4,ADDR io,0
|
||||||
|
invoke CloseHandle,ebx
|
||||||
|
ret
|
||||||
|
ArtifactTestCapture3D ENDP
|
||||||
|
|
||||||
|
RunArtifactTest3D PROC uses ebx esi edi
|
||||||
|
local savedBank:DWORD,oldPath[260]:BYTE,io:DWORD
|
||||||
|
mov obsActive3D,0
|
||||||
|
mov tournamentMode,0
|
||||||
|
mov nativeProfileActive3D,0
|
||||||
|
mov arrivalConfirmed3D,0
|
||||||
|
call ResetArtifacts3D
|
||||||
|
mov bankroll,10000
|
||||||
|
invoke BuyMerchantCharm3D,0
|
||||||
|
cmp bankroll,9100
|
||||||
|
jne artifact_fail_1
|
||||||
|
cmp charmCloverUses,3
|
||||||
|
jne artifact_fail_1
|
||||||
|
invoke TriggerCharmLossProtection,100
|
||||||
|
cmp bankroll,9150
|
||||||
|
jne artifact_fail_1
|
||||||
|
cmp charmCloverUses,2
|
||||||
|
jne artifact_fail_1
|
||||||
|
invoke TriggerCharmLossProtection,0
|
||||||
|
cmp charmCloverUses,2
|
||||||
|
jne artifact_fail_1
|
||||||
|
mov charmHorseshoeUses,5
|
||||||
|
invoke TriggerCharmWinBonus,1000
|
||||||
|
cmp eax,350
|
||||||
|
jne artifact_fail_2
|
||||||
|
cmp bankroll,9500
|
||||||
|
jne artifact_fail_2
|
||||||
|
mov charmDevilUses,2
|
||||||
|
invoke ToggleArtifact3D,3
|
||||||
|
cmp charmEnabledMask3D,12
|
||||||
|
jne artifact_fail_2
|
||||||
|
invoke TriggerCharmWinBonus,100
|
||||||
|
cmp eax,100
|
||||||
|
jne artifact_fail_2
|
||||||
|
cmp charmDevilUses,1
|
||||||
|
jne artifact_fail_2
|
||||||
|
invoke TriggerCharmLossProtection,100
|
||||||
|
cmp eax,0
|
||||||
|
jne artifact_fail_2
|
||||||
|
cmp charmDevilUses,0
|
||||||
|
jne artifact_fail_2
|
||||||
|
mov charmEnabledMask3D,7
|
||||||
|
mov bankroll,999999999
|
||||||
|
invoke TriggerCharmWinBonus,1000000000
|
||||||
|
cmp eax,1
|
||||||
|
jne artifact_fail_3
|
||||||
|
cmp bankroll,1000000000
|
||||||
|
jne artifact_fail_3
|
||||||
|
mov eax,charmHorseshoeUses
|
||||||
|
mov ebx,eax
|
||||||
|
invoke TriggerCharmWinBonus,100
|
||||||
|
cmp charmHorseshoeUses,ebx
|
||||||
|
jne artifact_fail_3
|
||||||
|
mov charmSkullUses,1
|
||||||
|
mov obsActive3D,1
|
||||||
|
invoke TriggerCharmBulletProtection
|
||||||
|
test eax,eax
|
||||||
|
jnz artifact_fail_4
|
||||||
|
cmp charmSkullUses,1
|
||||||
|
jne artifact_fail_4
|
||||||
|
mov obsActive3D,0
|
||||||
|
mov tournamentMode,1
|
||||||
|
invoke TriggerCharmLossProtection,100
|
||||||
|
test eax,eax
|
||||||
|
jnz artifact_fail_4
|
||||||
|
invoke TriggerCharmBulletProtection
|
||||||
|
test eax,eax
|
||||||
|
jnz artifact_fail_4
|
||||||
|
mov towerBulletUses3D,1
|
||||||
|
invoke TriggerCharmBulletProtection
|
||||||
|
cmp eax,1
|
||||||
|
jne artifact_fail_4
|
||||||
|
cmp charmSkullUses,1
|
||||||
|
jne artifact_fail_4
|
||||||
|
cmp towerBulletUses3D,0
|
||||||
|
jne artifact_fail_4
|
||||||
|
mov tournamentMode,0
|
||||||
|
mov charmCloverUses,98
|
||||||
|
mov bankroll,10000
|
||||||
|
invoke BuyMerchantCharm3D,0
|
||||||
|
cmp bankroll,10000
|
||||||
|
jne artifact_fail_5
|
||||||
|
cmp charmCloverUses,98
|
||||||
|
jne artifact_fail_5
|
||||||
|
mov charmCloverUses,0
|
||||||
|
mov bankroll,0
|
||||||
|
invoke BuyMerchantCharm3D,0
|
||||||
|
cmp charmCloverUses,0
|
||||||
|
jne artifact_fail_5
|
||||||
|
|
||||||
|
; Reward cannot be claimed twice; reset starts a fresh run without touching bank.
|
||||||
|
mov bankroll,10000
|
||||||
|
mov towerStage,1
|
||||||
|
mov towerFloorState,TOWER_STATE_BRIEFING
|
||||||
|
call ResetTowerRelics3D
|
||||||
|
call PrepareTowerReward3D
|
||||||
|
invoke ChooseTowerRelic3D,0
|
||||||
|
invoke ChooseTowerRelic3D,0
|
||||||
|
cmp towerHeartUses3D,1
|
||||||
|
jne artifact_fail_6
|
||||||
|
mov tournamentMode,1
|
||||||
|
mov towerFloorState,TOWER_STATE_IN_GAME
|
||||||
|
invoke TowerReportRoundOutcome,2
|
||||||
|
cmp towerFloorState,TOWER_STATE_BRIEFING
|
||||||
|
jne artifact_fail_6
|
||||||
|
cmp towerHeartUses3D,0
|
||||||
|
jne artifact_fail_6
|
||||||
|
; Duplicate report cannot kill a saved attempt.
|
||||||
|
invoke TowerReportRoundOutcome,2
|
||||||
|
cmp towerFloorState,TOWER_STATE_BRIEFING
|
||||||
|
jne artifact_fail_6
|
||||||
|
mov towerFloorState,TOWER_STATE_IN_GAME
|
||||||
|
invoke TowerReportRoundOutcome,1
|
||||||
|
cmp towerRewardPending3D,1
|
||||||
|
jne artifact_fail_6
|
||||||
|
invoke ChooseTowerRelic3D,1
|
||||||
|
cmp towerSealStage3D,2
|
||||||
|
jne artifact_fail_6
|
||||||
|
cmp towerSealUses3D,2
|
||||||
|
jne artifact_fail_6
|
||||||
|
mov towerStage,2
|
||||||
|
mov towerFloorState,TOWER_STATE_IN_GAME
|
||||||
|
invoke TowerReportRoundOutcome,2
|
||||||
|
cmp towerSealUses3D,1
|
||||||
|
jne artifact_fail_6
|
||||||
|
cmp towerFloorState,TOWER_STATE_BRIEFING
|
||||||
|
jne artifact_fail_6
|
||||||
|
call ResetTowerRelics3D
|
||||||
|
cmp towerSealUses3D,0
|
||||||
|
jne artifact_fail_6
|
||||||
|
cmp bankroll,10000
|
||||||
|
jne artifact_fail_6
|
||||||
|
; Exact net loss refunded, not arbitrary prize or a second stake payout.
|
||||||
|
mov towerPurseUses3D,1
|
||||||
|
mov towerHeartUses3D,1
|
||||||
|
mov towerEntryBank3D,10000
|
||||||
|
mov bankroll,9900
|
||||||
|
mov towerFloorState,TOWER_STATE_IN_GAME
|
||||||
|
invoke TowerReportRoundOutcome,2
|
||||||
|
cmp bankroll,10000
|
||||||
|
jne artifact_fail_6
|
||||||
|
cmp towerPurseUses3D,0
|
||||||
|
jne artifact_fail_6
|
||||||
|
mov towerStage,6
|
||||||
|
mov towerFloorState,TOWER_STATE_IN_GAME
|
||||||
|
invoke TowerReportRoundOutcome,1
|
||||||
|
mov eax,bankroll
|
||||||
|
mov savedBank,eax
|
||||||
|
invoke TowerReportRoundOutcome,1
|
||||||
|
mov eax,savedBank
|
||||||
|
cmp bankroll,eax
|
||||||
|
jne artifact_fail_6
|
||||||
|
cmp towerHeartUses3D,0
|
||||||
|
jne artifact_fail_6
|
||||||
|
|
||||||
|
; Bust protection removes the real last card, without drawing a replacement.
|
||||||
|
mov towerBustUses3D,1
|
||||||
|
mov cbPlayerCount3D,3
|
||||||
|
mov cbPlayer3D,8
|
||||||
|
mov cbPlayer3D[4],7
|
||||||
|
mov cbPlayer3D[8],6
|
||||||
|
call TryTowerBustSave3D
|
||||||
|
cmp eax,1
|
||||||
|
jne artifact_fail_7
|
||||||
|
cmp cbPlayerCount3D,2
|
||||||
|
jne artifact_fail_7
|
||||||
|
cmp cbPlayerScore3D,19
|
||||||
|
jne artifact_fail_7
|
||||||
|
mov towerEye3D,1
|
||||||
|
mov bs3d_shellIndex,0
|
||||||
|
mov bs3d_shellCount,2
|
||||||
|
mov bs3d_shells,1
|
||||||
|
call UpdateTowerEye3D
|
||||||
|
cmp bs3d_known,1
|
||||||
|
jne artifact_fail_7
|
||||||
|
mov tournamentMode,0
|
||||||
|
call ResetTowerRelics3D
|
||||||
|
|
||||||
|
; Both legacy checksum and versioned extension must validate.
|
||||||
|
mov DWORD PTR [saveBuffer+280],32465241h
|
||||||
|
mov DWORD PTR [saveBuffer+284],3
|
||||||
|
mov DWORD PTR [saveBuffer+288],5
|
||||||
|
mov DWORD PTR [saveBuffer+292],1
|
||||||
|
mov DWORD PTR [saveBuffer+296],2
|
||||||
|
mov DWORD PTR [saveBuffer+300],7
|
||||||
|
mov DWORD PTR [saveBuffer+304],2
|
||||||
|
invoke ArtifactSaveSignature3D,OFFSET saveBuffer
|
||||||
|
mov DWORD PTR [saveBuffer+308],eax
|
||||||
|
invoke ValidateArtifactSave3D,OFFSET saveBuffer
|
||||||
|
cmp eax,1
|
||||||
|
jne artifact_fail_8
|
||||||
|
inc DWORD PTR [saveBuffer+284]
|
||||||
|
invoke ValidateArtifactSave3D,OFFSET saveBuffer
|
||||||
|
test eax,eax
|
||||||
|
jnz artifact_fail_8
|
||||||
|
|
||||||
|
; Real profile write/reload uses test paths, never runtime/profiles.
|
||||||
|
invoke CreateDirectoryA,OFFSET artifactTestDir3D,0
|
||||||
|
mov nativeProfilesDirPtr3D,OFFSET artifactTestDir3D
|
||||||
|
mov nativeProfileActive3D,1
|
||||||
|
invoke CopyCString,OFFSET saveFileName,OFFSET artifactTestProfileName3D
|
||||||
|
mov charmCloverUses,3
|
||||||
|
mov charmHorseshoeUses,5
|
||||||
|
mov charmSkullUses,1
|
||||||
|
mov charmDevilUses,2
|
||||||
|
mov charmEnabledMask3D,7
|
||||||
|
mov bankroll,12345
|
||||||
|
call SaveGraphicProfile3D
|
||||||
|
invoke ValidateGraphicProfile3D,OFFSET artifactTestPath3D
|
||||||
|
cmp eax,1
|
||||||
|
jne artifact_fail_9
|
||||||
|
call ResetArtifacts3D
|
||||||
|
mov bankroll,0
|
||||||
|
call LoadSave
|
||||||
|
cmp bankroll,12345
|
||||||
|
jne artifact_fail_9
|
||||||
|
cmp charmCloverUses,3
|
||||||
|
jne artifact_fail_9
|
||||||
|
cmp charmDevilUses,2
|
||||||
|
jne artifact_fail_9
|
||||||
|
cmp charmEnabledMask3D,7
|
||||||
|
jne artifact_fail_9
|
||||||
|
; A signed 280-byte legacy file imports with an empty artifact inventory.
|
||||||
|
invoke CreateFileA,OFFSET artifactTestLegacy3D,40000000h,0,0,2,80h,0
|
||||||
|
mov ebx,eax
|
||||||
|
invoke WriteFile,ebx,OFFSET saveBuffer,SAVE_LEGACY_SIZE,ADDR io,0
|
||||||
|
invoke CloseHandle,ebx
|
||||||
|
invoke ValidateGraphicProfile3D,OFFSET artifactTestLegacy3D
|
||||||
|
cmp eax,1
|
||||||
|
jne artifact_fail_9
|
||||||
|
invoke CopyCString,OFFSET saveFileName,OFFSET artifactTestLegacyName3D
|
||||||
|
call LoadSave
|
||||||
|
cmp charmCloverUses,0
|
||||||
|
jne artifact_fail_9
|
||||||
|
cmp bankroll,12345
|
||||||
|
jne artifact_fail_9
|
||||||
|
|
||||||
|
; Preview format roundtrip, disabled effects and checksum rejection.
|
||||||
|
mov nativeProfileActive3D,0
|
||||||
|
invoke CopyCString,OFFSET savePath3D,OFFSET artifactTestPreview3D
|
||||||
|
mov arrivalConfirmed3D,1
|
||||||
|
mov bankroll,54321
|
||||||
|
mov charmCloverUses,9
|
||||||
|
mov charmHorseshoeUses,8
|
||||||
|
mov charmSkullUses,7
|
||||||
|
mov charmDevilUses,6
|
||||||
|
mov charmEnabledMask3D,4
|
||||||
|
call SaveProgress3D
|
||||||
|
mov arrivalConfirmed3D,0
|
||||||
|
call ResetArtifacts3D
|
||||||
|
call LoadProgress3D
|
||||||
|
cmp bankroll,54321
|
||||||
|
jne artifact_fail_10
|
||||||
|
cmp charmCloverUses,9
|
||||||
|
jne artifact_fail_10
|
||||||
|
cmp charmDevilUses,6
|
||||||
|
jne artifact_fail_10
|
||||||
|
cmp charmEnabledMask3D,4
|
||||||
|
jne artifact_fail_10
|
||||||
|
invoke TriggerCharmWinBonus,100
|
||||||
|
test eax,eax
|
||||||
|
jnz artifact_fail_10
|
||||||
|
cmp charmHorseshoeUses,8
|
||||||
|
jne artifact_fail_10
|
||||||
|
inc saveData3D[16]
|
||||||
|
invoke CreateFileA,OFFSET artifactTestPreview3D,40000000h,0,0,2,80h,0
|
||||||
|
mov ebx,eax
|
||||||
|
invoke WriteFile,ebx,OFFSET saveData3D,40,ADDR io,0
|
||||||
|
invoke CloseHandle,ebx
|
||||||
|
call LoadProgress3D
|
||||||
|
cmp bankroll,10000
|
||||||
|
jne artifact_fail_10
|
||||||
|
cmp charmCloverUses,0
|
||||||
|
jne artifact_fail_10
|
||||||
|
call ResetProfileDefaults
|
||||||
|
cmp charmSkullUses,0
|
||||||
|
jne artifact_fail_10
|
||||||
|
|
||||||
|
; Production Buckshot settlement pays net-profit bonus and cannot repeat it.
|
||||||
|
mov bankroll,9900
|
||||||
|
mov charmEnabledMask3D,7
|
||||||
|
mov charmHorseshoeUses,2
|
||||||
|
mov bs3d_bet,100
|
||||||
|
mov bs3d_state,BS_SHOT
|
||||||
|
mov bs3d_afterAnim,BS_WIN
|
||||||
|
call FinishBuckshotAction3D
|
||||||
|
cmp bankroll,10270
|
||||||
|
jne artifact_fail_11
|
||||||
|
cmp charmHorseshoeUses,1
|
||||||
|
jne artifact_fail_11
|
||||||
|
call FinishBuckshotAction3D
|
||||||
|
cmp bankroll,10270
|
||||||
|
jne artifact_fail_11
|
||||||
|
mov bankroll,9900
|
||||||
|
mov charmCloverUses,2
|
||||||
|
mov bs3d_state,BS_SHOT
|
||||||
|
mov bs3d_afterAnim,BS_LOSE
|
||||||
|
call FinishBuckshotAction3D
|
||||||
|
cmp bankroll,9950
|
||||||
|
jne artifact_fail_11
|
||||||
|
cmp charmCloverUses,1
|
||||||
|
jne artifact_fail_11
|
||||||
|
|
||||||
|
; Keyboard purchase requires two presses; selection cancels confirmation.
|
||||||
|
mov bankroll,10000
|
||||||
|
call ResetArtifacts3D
|
||||||
|
mov merchantTab3D,1
|
||||||
|
mov merchantCharmSelected3D,0
|
||||||
|
mov artifactBuyArmed3D,0
|
||||||
|
call ClearKeys3D
|
||||||
|
mov pressedKeys3D[0Dh],1
|
||||||
|
call HandleArtifactShop3D
|
||||||
|
cmp bankroll,10000
|
||||||
|
jne artifact_fail_12
|
||||||
|
cmp artifactBuyArmed3D,1
|
||||||
|
jne artifact_fail_12
|
||||||
|
mov pressedKeys3D[0Dh],1
|
||||||
|
call HandleArtifactShop3D
|
||||||
|
cmp bankroll,9100
|
||||||
|
jne artifact_fail_12
|
||||||
|
cmp charmCloverUses,3
|
||||||
|
jne artifact_fail_12
|
||||||
|
mov artifactBuyArmed3D,1
|
||||||
|
mov pressedKeys3D[28h],1
|
||||||
|
call HandleArtifactShop3D
|
||||||
|
cmp artifactBuyArmed3D,0
|
||||||
|
jne artifact_fail_12
|
||||||
|
cmp merchantCharmSelected3D,1
|
||||||
|
jne artifact_fail_12
|
||||||
|
mov pressedKeys3D[09h],1
|
||||||
|
call HandleArtifactShop3D
|
||||||
|
cmp merchantTab3D,0
|
||||||
|
jne artifact_fail_12
|
||||||
|
|
||||||
|
; Fresh run clears every relic, stale offer and entry bankroll.
|
||||||
|
mov towerHeartUses3D,5
|
||||||
|
mov towerSealUses3D,2
|
||||||
|
mov towerSealStage3D,6
|
||||||
|
mov towerBulletUses3D,2
|
||||||
|
mov towerBustUses3D,2
|
||||||
|
mov towerEye3D,1
|
||||||
|
mov towerPurseUses3D,2
|
||||||
|
call ResetTowerRelics3D
|
||||||
|
mov eax,towerHeartUses3D
|
||||||
|
or eax,towerSealUses3D
|
||||||
|
or eax,towerSealStage3D
|
||||||
|
or eax,towerBulletUses3D
|
||||||
|
or eax,towerBustUses3D
|
||||||
|
or eax,towerEye3D
|
||||||
|
or eax,towerPurseUses3D
|
||||||
|
or eax,towerEntryBank3D
|
||||||
|
or eax,towerRewardPending3D
|
||||||
|
test eax,eax
|
||||||
|
jnz artifact_fail_12
|
||||||
|
|
||||||
|
; Leaving each native table must end the run, not leak tournament mode to hall.
|
||||||
|
mov tournamentMode,1
|
||||||
|
mov towerHeartUses3D,1
|
||||||
|
mov dice3d_state,0
|
||||||
|
call DiceEscape3D
|
||||||
|
cmp tournamentMode,0
|
||||||
|
jne artifact_fail_13
|
||||||
|
cmp towerHeartUses3D,0
|
||||||
|
jne artifact_fail_13
|
||||||
|
mov tournamentMode,1
|
||||||
|
mov towerEye3D,1
|
||||||
|
mov roulState,0
|
||||||
|
call WheelEscape3D
|
||||||
|
cmp tournamentMode,0
|
||||||
|
jne artifact_fail_13
|
||||||
|
cmp towerEye3D,0
|
||||||
|
jne artifact_fail_13
|
||||||
|
mov tournamentMode,1
|
||||||
|
mov towerBustUses3D,1
|
||||||
|
mov engineMode,MODE_BLACKJACK
|
||||||
|
mov cbState3D,CB_IDLE
|
||||||
|
call LeaveCardTable3D
|
||||||
|
cmp tournamentMode,0
|
||||||
|
jne artifact_fail_13
|
||||||
|
cmp towerBustUses3D,0
|
||||||
|
jne artifact_fail_13
|
||||||
|
mov tournamentMode,1
|
||||||
|
mov towerPurseUses3D,1
|
||||||
|
mov bankroll,9950
|
||||||
|
mov coin3d_bet,50
|
||||||
|
mov coin3d_state,COIN_TOSS
|
||||||
|
mov coin3d_choice,1
|
||||||
|
mov coin3d_result,1
|
||||||
|
call CoinEscape3D
|
||||||
|
cmp bankroll,10050
|
||||||
|
jne artifact_fail_13
|
||||||
|
cmp tournamentMode,0
|
||||||
|
jne artifact_fail_13
|
||||||
|
cmp towerPurseUses3D,0
|
||||||
|
jne artifact_fail_13
|
||||||
|
call CoinSettle3D
|
||||||
|
cmp bankroll,10050
|
||||||
|
jne artifact_fail_13
|
||||||
|
|
||||||
|
; Situational offers follow the upcoming floor, not the one just cleared.
|
||||||
|
mov towerStage,2
|
||||||
|
mov towerFloorState,TOWER_STATE_CLEAR
|
||||||
|
call PrepareTowerReward3D
|
||||||
|
cmp towerRewardOffers3D[4],3
|
||||||
|
jne artifact_fail_14
|
||||||
|
mov towerStage,3
|
||||||
|
call PrepareTowerReward3D
|
||||||
|
cmp towerRewardOffers3D[4],2
|
||||||
|
jne artifact_fail_14
|
||||||
|
mov towerStage,5
|
||||||
|
call PrepareTowerReward3D
|
||||||
|
cmp towerRewardOffers3D[4],4
|
||||||
|
jne artifact_fail_14
|
||||||
|
invoke ChooseTowerRelic3D,1
|
||||||
|
cmp towerEye3D,1
|
||||||
|
jne artifact_fail_14
|
||||||
|
call ResetTowerRelics3D
|
||||||
|
|
||||||
|
; Render shipping UI; captures inspected by the Python runner.
|
||||||
|
mov merchantTab3D,1
|
||||||
|
mov merchantCharmSelected3D,0
|
||||||
|
mov merchantMessage3D,0
|
||||||
|
call RenderMerchant3D
|
||||||
|
invoke ArtifactTestCapture3D,OFFSET artifactTestBmp3D
|
||||||
|
mov towerStage,3
|
||||||
|
mov engineMode,MODE_HELL_TOWER
|
||||||
|
mov towerFloorState,TOWER_STATE_BRIEFING
|
||||||
|
call PrepareTowerReward3D
|
||||||
|
call RenderHellTower3D
|
||||||
|
invoke ArtifactTestCapture3D,OFFSET artifactTestRewardBmp3D
|
||||||
|
xor eax,eax
|
||||||
|
ret
|
||||||
|
artifact_fail_1:
|
||||||
|
mov eax,101
|
||||||
|
ret
|
||||||
|
artifact_fail_2:
|
||||||
|
mov eax,102
|
||||||
|
ret
|
||||||
|
artifact_fail_3:
|
||||||
|
mov eax,103
|
||||||
|
ret
|
||||||
|
artifact_fail_4:
|
||||||
|
mov eax,104
|
||||||
|
ret
|
||||||
|
artifact_fail_5:
|
||||||
|
mov eax,105
|
||||||
|
ret
|
||||||
|
artifact_fail_6:
|
||||||
|
mov eax,106
|
||||||
|
ret
|
||||||
|
artifact_fail_7:
|
||||||
|
mov eax,107
|
||||||
|
ret
|
||||||
|
artifact_fail_8:
|
||||||
|
mov eax,108
|
||||||
|
ret
|
||||||
|
artifact_fail_9:
|
||||||
|
mov eax,109
|
||||||
|
ret
|
||||||
|
artifact_fail_10:
|
||||||
|
mov eax,110
|
||||||
|
ret
|
||||||
|
artifact_fail_11:
|
||||||
|
mov eax,111
|
||||||
|
ret
|
||||||
|
artifact_fail_12:
|
||||||
|
mov eax,112
|
||||||
|
ret
|
||||||
|
artifact_fail_13:
|
||||||
|
mov eax,113
|
||||||
|
ret
|
||||||
|
artifact_fail_14:
|
||||||
|
mov eax,114
|
||||||
|
ret
|
||||||
|
RunArtifactTest3D ENDP
|
||||||
95
tools/tests/check_artifacts.py
Normal file
95
tools/tests/check_artifacts.py
Normal file
|
|
@ -0,0 +1,95 @@
|
||||||
|
"""Compile shipping ASM procedures with isolated artifact/tower regression entry."""
|
||||||
|
import hashlib
|
||||||
|
import json
|
||||||
|
import re
|
||||||
|
from pathlib import Path
|
||||||
|
import struct
|
||||||
|
import subprocess
|
||||||
|
from PIL import Image
|
||||||
|
|
||||||
|
ROOT = Path(__file__).resolve().parents[2]
|
||||||
|
OUT = ROOT / 'build/artifacts'
|
||||||
|
|
||||||
|
|
||||||
|
def toolchain():
|
||||||
|
for base in (Path('C:/Program Files/Microsoft Visual Studio/18/Community/VC/Tools/MSVC'),
|
||||||
|
Path('C:/Program Files (x86)/Microsoft Visual Studio/18/BuildTools/VC/Tools/MSVC')):
|
||||||
|
if base.exists():
|
||||||
|
for version in sorted(base.iterdir(), reverse=True):
|
||||||
|
binary = version / 'bin/Hostx64/x86'
|
||||||
|
if (binary / 'ml.exe').exists():
|
||||||
|
return binary / 'ml.exe', binary / 'link.exe'
|
||||||
|
for base in (Path('F:/MASM32/masm32'), Path('D:/MASM32/masm32'), Path('C:/masm32')):
|
||||||
|
if (base/'bin/ml.exe').exists():
|
||||||
|
return base/'bin/ml.exe', base/'bin/link.exe'
|
||||||
|
raise RuntimeError('MASM x86 toolchain required')
|
||||||
|
|
||||||
|
|
||||||
|
def run(*args):
|
||||||
|
subprocess.run([str(x) for x in args], cwd=ROOT, check=True, timeout=120)
|
||||||
|
|
||||||
|
|
||||||
|
def check_text_widths():
|
||||||
|
source = (ROOT/'src_graphics/hell_tower_data.inc').read_text(encoding='cp1251')
|
||||||
|
for index in range(6):
|
||||||
|
block = source.split(f'towerRelicName{index} db ', 1)[1].split('\ntowerRelicName', 1)[0]
|
||||||
|
block = block.split('\ntowerRelicNames3D', 1)[0]
|
||||||
|
rows = re.findall(r'(?:^|\bdb )([\d,]+)', block)
|
||||||
|
assert len(rows) == 4, (index, rows)
|
||||||
|
for row in rows:
|
||||||
|
data = bytes(map(int, row.split(','))).rstrip(b'\0')
|
||||||
|
assert len(data) <= 11, (index, data.decode('cp1251'))
|
||||||
|
assert 151 not in data
|
||||||
|
for label, width in [('towerRewardTitle3D', 36), ('towerRewardHint3D', 36),
|
||||||
|
('towerRewardKeys3D', 36), ('towerRunOnly3D', 11)]:
|
||||||
|
row = re.search(rf'^{label} db ([\d,]+)', source, re.M).group(1)
|
||||||
|
data = bytes(map(int, row.split(','))).rstrip(b'\0')
|
||||||
|
assert len(data) <= width and 151 not in data, label
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
check_text_widths()
|
||||||
|
OUT.mkdir(parents=True, exist_ok=True)
|
||||||
|
runtime = ROOT/'runtime'
|
||||||
|
before = {p: hashlib.sha256(p.read_bytes()).digest() for p in runtime.rglob('*') if p.is_file()}
|
||||||
|
ml, link = toolchain()
|
||||||
|
sdk = Path('C:/Program Files (x86)/Windows Kits/10/Lib')
|
||||||
|
libraries = next(p/'um/x86' for p in sorted(sdk.iterdir(), reverse=True)
|
||||||
|
if (p/'um/x86/kernel32.lib').exists())
|
||||||
|
run(ml, '/c', '/coff', '/Cp', '/nologo', '/I.', '/DARTIFACT_TEST=1',
|
||||||
|
'/Fobuild/artifacts/test.obj', 'poker.asm')
|
||||||
|
run(link, '/nologo', '/SUBSYSTEM:CONSOLE', '/LIBPATH:'+str(libraries),
|
||||||
|
'/OUT:build/artifacts/test.exe', 'build/artifacts/test.obj',
|
||||||
|
'kernel32.lib', 'winmm.lib', 'user32.lib', 'gdi32.lib', 'opengl32.lib')
|
||||||
|
run(OUT/'test.exe')
|
||||||
|
assert all(p.exists() and hashlib.sha256(p.read_bytes()).digest() == h for p,h in before.items())
|
||||||
|
assert {p for p in runtime.rglob('*') if p.is_file()} == set(before), 'test wrote player runtime'
|
||||||
|
profile = (OUT/'profile.dat').read_bytes()
|
||||||
|
assert len(profile) == 312
|
||||||
|
assert struct.unpack_from('<4s6I', profile, 280)[:6] == (b'ARF2',3,5,1,2,7)
|
||||||
|
assert len((OUT/'legacy.dat').read_bytes()) == 280
|
||||||
|
for name in ('shop', 'rewards'):
|
||||||
|
image = Image.open(OUT/f'{name}.bmp').convert('RGB')
|
||||||
|
assert image.size == (640,480) and len(image.getcolors(640*480)) > 5
|
||||||
|
image.save(OUT/f'{name}.png')
|
||||||
|
if name == 'rewards':
|
||||||
|
# Reward scene must not retain any pixels from previously rendered shop.
|
||||||
|
assert image.getpixel((0,0)) == (12,8,11)
|
||||||
|
assert image.getpixel((639,449)) == (12,8,11)
|
||||||
|
assert image.getpixel((639,479)) == (20,9,13)
|
||||||
|
report = {'native': 'PASS', 'profile_bytes': len(profile),
|
||||||
|
'player_runtime_unchanged': True,
|
||||||
|
'checks': ['purchases', 'caps', 'toggles', 'observer isolation', 'tower isolation',
|
||||||
|
'retries', 'reward idempotence', 'prize idempotence', 'bust save',
|
||||||
|
'shell reveal', 'checksums', 'profile roundtrip', 'legacy import',
|
||||||
|
'preview roundtrip and tamper rejection', 'disabled effects',
|
||||||
|
'Buckshot net settlement and idempotence', 'purchase confirmation',
|
||||||
|
'selection cancels confirmation', 'fresh run full reset',
|
||||||
|
'native table exits reset tower', 'paid coin exit settles once',
|
||||||
|
'text widths', 'UI captures']}
|
||||||
|
(OUT/'report.json').write_text(json.dumps(report, indent=2), encoding='utf-8')
|
||||||
|
print('PASS: native artifacts, run-local relics, profile migration and UI captures')
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
30
tools/tests/check_casino_actions.py
Normal file
30
tools/tests/check_casino_actions.py
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
"""Build full native action suite without changing production source or executables."""
|
||||||
|
from pathlib import Path
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
from check_artifacts import toolchain
|
||||||
|
|
||||||
|
ROOT = Path(__file__).resolve().parents[2]
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
(ROOT/'build/actions').mkdir(parents=True, exist_ok=True)
|
||||||
|
for fixture in ('prepare_arrival_fixtures.py', 'prepare_clover_fixtures.py',
|
||||||
|
'prepare_poker_fixtures.py'):
|
||||||
|
subprocess.run([sys.executable, '-B', str(ROOT/'tools/tests'/fixture)], check=True, cwd=ROOT)
|
||||||
|
ml, link = toolchain()
|
||||||
|
sdk = Path('C:/Program Files (x86)/Windows Kits/10/Lib')
|
||||||
|
libraries = next(p/'um/x86' for p in sorted(sdk.iterdir(), reverse=True)
|
||||||
|
if (p/'um/x86/kernel32.lib').exists())
|
||||||
|
subprocess.run([str(ml), '/c', '/coff', '/Cp', '/nologo', '/I.', '/DCASINO_ACTION_TEST=1',
|
||||||
|
'/Fobuild/actions/actions-test.obj', 'poker.asm'], cwd=ROOT, check=True)
|
||||||
|
subprocess.run([str(link), '/nologo', '/SUBSYSTEM:CONSOLE', '/LIBPATH:'+str(libraries),
|
||||||
|
'/OUT:build/actions/actions-test.exe', 'build/actions/actions-test.obj',
|
||||||
|
'kernel32.lib', 'winmm.lib', 'user32.lib', 'gdi32.lib', 'opengl32.lib'],
|
||||||
|
cwd=ROOT, check=True)
|
||||||
|
subprocess.run([str(ROOT/'build/actions/actions-test.exe')], cwd=ROOT, check=True, timeout=600)
|
||||||
|
print((ROOT/'build/actions/test-report.txt').read_text(encoding='ascii'))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
|
|
@ -9,6 +9,7 @@ from PIL import Image, ImageStat, ImageChops
|
||||||
from check_card_exit_build import Coff
|
from check_card_exit_build import Coff
|
||||||
from check_terminals import signature
|
from check_terminals import signature
|
||||||
from check_character_cast import check as check_character_cast
|
from check_character_cast import check as check_character_cast
|
||||||
|
from check_artifacts import toolchain
|
||||||
|
|
||||||
ROOT = Path(__file__).resolve().parents[2]
|
ROOT = Path(__file__).resolve().parents[2]
|
||||||
OUT = ROOT / "build/hall-expansion"
|
OUT = ROOT / "build/hall-expansion"
|
||||||
|
|
@ -329,11 +330,11 @@ def main():
|
||||||
(OUT/(stem+".asm")).write_text(source,encoding="cp1251")
|
(OUT/(stem+".asm")).write_text(source,encoding="cp1251")
|
||||||
masm = Path("F:/MASM32/masm32")
|
masm = Path("F:/MASM32/masm32")
|
||||||
modern_ml = Path("C:/Program Files/Microsoft Visual Studio/18/Community/VC/Tools/MSVC/14.51.36231/bin/Hostx64/x86/ml.exe")
|
modern_ml = Path("C:/Program Files/Microsoft Visual Studio/18/Community/VC/Tools/MSVC/14.51.36231/bin/Hostx64/x86/ml.exe")
|
||||||
assembler = modern_ml if modern_ml.is_file() else masm/"bin/ml.exe"
|
assembler, linker = toolchain()
|
||||||
subprocess.run([str(assembler),"/c","/coff","/Cp","/nologo","/I.",
|
subprocess.run([str(assembler),"/c","/coff","/Cp","/nologo","/I.",
|
||||||
f"/Fobuild/hall-expansion/{stem}.obj",f"build/hall-expansion/{stem}.asm"],cwd=ROOT,check=True)
|
f"/Fobuild/hall-expansion/{stem}.obj",f"build/hall-expansion/{stem}.asm"],cwd=ROOT,check=True)
|
||||||
sdk = sorted(Path("C:/Program Files (x86)/Windows Kits/10/Lib").glob("*/um/x86"))[-1]
|
sdk = sorted(Path("C:/Program Files (x86)/Windows Kits/10/Lib").glob("*/um/x86"))[-1]
|
||||||
subprocess.run([str(masm/"bin/link.exe"),"/nologo","/SUBSYSTEM:CONSOLE","/ENTRY:ExpansionTestStart@0",
|
subprocess.run([str(linker),"/nologo","/SUBSYSTEM:CONSOLE","/ENTRY:ExpansionTestStart@0",
|
||||||
f"/MAP:build/hall-expansion/{stem}.map",
|
f"/MAP:build/hall-expansion/{stem}.map",
|
||||||
f"/LIBPATH:{sdk}",f"/LIBPATH:{masm/'lib'}",f"/OUT:build/hall-expansion/{stem}.exe",
|
f"/LIBPATH:{sdk}",f"/LIBPATH:{masm/'lib'}",f"/OUT:build/hall-expansion/{stem}.exe",
|
||||||
f"build/hall-expansion/{stem}.obj","build/hall-expansion/helpers.obj",
|
f"build/hall-expansion/{stem}.obj","build/hall-expansion/helpers.obj",
|
||||||
|
|
|
||||||
30
tools/tests/prepare_poker_fixtures.py
Normal file
30
tools/tests/prepare_poker_fixtures.py
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
"""Generate independent evaluator vectors only; never rewrite shipping assets."""
|
||||||
|
import itertools
|
||||||
|
from pathlib import Path
|
||||||
|
import random
|
||||||
|
import struct
|
||||||
|
import sys
|
||||||
|
|
||||||
|
ROOT = Path(__file__).resolve().parents[2]
|
||||||
|
sys.path.insert(0, str(ROOT/'tools/vendor'))
|
||||||
|
from treys import Card, Evaluator
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
rng = random.Random(77291)
|
||||||
|
hands = [list(hand) for hand in itertools.combinations([8,9,10,11,12,13,25], 5)]
|
||||||
|
hands += [rng.sample(range(52), count) for count in (5,6,7) for _ in range(3000)]
|
||||||
|
evaluator = Evaluator()
|
||||||
|
def native(card):
|
||||||
|
return Card.new('23456789TJQKA'[card%13]+'cdhs'[card//13])
|
||||||
|
vectors = b''.join(struct.pack('<9I', len(hand), *hand, *([0]*(7-len(hand))),
|
||||||
|
evaluator.evaluate([], [native(card) for card in hand]))
|
||||||
|
for hand in hands)
|
||||||
|
target = ROOT/'build/tables/poker-vectors.bin'
|
||||||
|
target.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
target.write_bytes(struct.pack('<I', len(hands))+vectors)
|
||||||
|
print(f'Prepared {len(hands)} independent poker vectors')
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
3
tools/tests/requirements.txt
Normal file
3
tools/tests/requirements.txt
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
Pillow>=10
|
||||||
|
capstone>=5,<6
|
||||||
|
treys==0.1.8
|
||||||
|
|
@ -1,45 +1,34 @@
|
||||||
"""Automated smoke test for Hell Tower 6-floor run-through."""
|
"""Smoke-test six real tower scene launches; outcomes injected, not balance measurement."""
|
||||||
import subprocess
|
import hashlib
|
||||||
import sys
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
import subprocess
|
||||||
|
from check_artifacts import toolchain
|
||||||
|
|
||||||
ROOT = Path(__file__).resolve().parents[2]
|
ROOT = Path(__file__).resolve().parents[2]
|
||||||
POKER_ASM = ROOT / "poker.asm"
|
OUT = ROOT/'build/hell-tower'
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
print("[1/4] Preparing test harness in poker.asm...")
|
OUT.mkdir(parents=True, exist_ok=True)
|
||||||
code = POKER_ASM.read_text(encoding="cp1251")
|
source_hash = hashlib.sha256((ROOT/'poker.asm').read_bytes()).digest()
|
||||||
target = "\nIFDEF CASINO_ACTION_TEST\n"
|
runtime = {p: hashlib.sha256(p.read_bytes()).digest()
|
||||||
if "CASINO_ACTION_TEST equ 1\n" not in code:
|
for p in (ROOT/'runtime').rglob('*') if p.is_file()}
|
||||||
code = code.replace(target, "\nCASINO_ACTION_TEST equ 1\nIFDEF CASINO_ACTION_TEST\n")
|
ml, link = toolchain()
|
||||||
POKER_ASM.write_text(code, encoding="cp1251")
|
sdk = Path('C:/Program Files (x86)/Windows Kits/10/Lib')
|
||||||
|
libraries = next(p/'um/x86' for p in sorted(sdk.iterdir(), reverse=True)
|
||||||
try:
|
if (p/'um/x86/kernel32.lib').exists())
|
||||||
print("[2/4] Building poker.exe with test harness...")
|
subprocess.run([str(ml), '/c', '/coff', '/Cp', '/nologo', '/I.', '/DHELL_TOWER_TEST=1',
|
||||||
build_res = subprocess.run(["cmd.exe", "/c", "build.bat"], cwd=ROOT, capture_output=True, text=True)
|
'/Fobuild/hell-tower/test.obj', 'poker.asm'], cwd=ROOT, check=True)
|
||||||
if build_res.returncode != 0:
|
subprocess.run([str(link), '/nologo', '/SUBSYSTEM:CONSOLE', '/LIBPATH:'+str(libraries),
|
||||||
print("[FAIL] Build failed:", build_res.stdout, build_res.stderr)
|
'/OUT:build/hell-tower/test.exe', 'build/hell-tower/test.obj',
|
||||||
return 1
|
'kernel32.lib', 'winmm.lib', 'user32.lib', 'gdi32.lib', 'opengl32.lib'],
|
||||||
|
cwd=ROOT, check=True)
|
||||||
print("[3/4] Running Hell Tower 6-floor run-through...")
|
subprocess.run([str(OUT/'test.exe')], cwd=ROOT, check=True, timeout=90)
|
||||||
run_res = subprocess.run([str(ROOT / "poker.exe")], cwd=ROOT, capture_output=True, timeout=15)
|
assert hashlib.sha256((ROOT/'poker.asm').read_bytes()).digest() == source_hash
|
||||||
print(f"Hell Tower test completed with exit code: {run_res.returncode}")
|
assert {p: hashlib.sha256(p.read_bytes()).digest()
|
||||||
if run_res.returncode != 0:
|
for p in (ROOT/'runtime').rglob('*') if p.is_file()} == runtime
|
||||||
print(f"[FAIL] Hell Tower run-through failed with code {run_res.returncode}")
|
print('PASS: six tower scene launches, reward transitions and exit; source/runtime unchanged')
|
||||||
return run_res.returncode
|
|
||||||
print("[SUCCESS] All 6 floors of Hell Tower completed without errors or crashes!")
|
|
||||||
finally:
|
|
||||||
print("[4/4] Restoring normal poker.asm and rebuilding...")
|
|
||||||
restored = POKER_ASM.read_text(encoding="cp1251")
|
|
||||||
if "CASINO_ACTION_TEST equ 1\n" in restored:
|
|
||||||
restored = restored.replace("CASINO_ACTION_TEST equ 1\n", "")
|
|
||||||
POKER_ASM.write_text(restored, encoding="cp1251")
|
|
||||||
subprocess.run(["cmd.exe", "/c", "build.bat"], cwd=ROOT, capture_output=True, text=True)
|
|
||||||
print("[OK] Production poker.exe rebuilt cleanly.")
|
|
||||||
|
|
||||||
return 0
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == '__main__':
|
||||||
sys.exit(main())
|
main()
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
.data
|
.data
|
||||||
unavailableTestIds3D dd INTERACT_ONLINE_RR,INTERACT_UMAMUSUME,INTERACT_HELL_TOWER,INTERACT_TERMINAL,INTERACT_OBSERVER
|
; Tower, terminals and observer now have native scenes, not placeholder modals.
|
||||||
|
unavailableTestIds3D dd INTERACT_ONLINE_RR,INTERACT_UMAMUSUME
|
||||||
|
unavailableTestCount3D equ ($-unavailableTestIds3D)/4
|
||||||
unavailableTestPath3D db "build\actions\unavailable.bmp",0
|
unavailableTestPath3D db "build\actions\unavailable.bmp",0
|
||||||
.code
|
.code
|
||||||
RunUnavailableTest3D PROC uses ebx esi edi
|
RunUnavailableTest3D PROC uses ebx esi edi
|
||||||
|
|
@ -72,7 +74,7 @@ unavailable_test_close:
|
||||||
cmp playerAngle,eax
|
cmp playerAngle,eax
|
||||||
jne unavailable_test_fail
|
jne unavailable_test_fail
|
||||||
inc esi
|
inc esi
|
||||||
cmp esi,5
|
cmp esi,unavailableTestCount3D
|
||||||
jb unavailable_test_next
|
jb unavailable_test_next
|
||||||
mov eax,oldMode
|
mov eax,oldMode
|
||||||
mov engineMode,eax
|
mov engineMode,eax
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue