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.
|
||||
/build/actions/
|
||||
/build/artifacts/
|
||||
/build/hell-tower/
|
||||
/build/test-deps/
|
||||
/build/arrival/
|
||||
/build/billiards/
|
||||
/build/card-ranks/
|
||||
|
|
|
|||
BIN
bin/poker.exe
BIN
bin/poker.exe
Binary file not shown.
|
|
@ -8,7 +8,7 @@ namespace AssemblerCasinoLauncher
|
|||
{
|
||||
static class Program
|
||||
{
|
||||
const string ExpectedPokerSha256 = "755067F511E82184081FE3D06391FCF872EC058AB224CA6ED8C1DB0A2990E1BA";
|
||||
const string ExpectedPokerSha256 = "A3A35CB3C9F21FB0F29F2849B01DFEE914AEA7830ED7540FFEF24C6A8467F44A";
|
||||
|
||||
[STAThread]
|
||||
static void Main()
|
||||
|
|
|
|||
Binary file not shown.
19
casino3d.inc
19
casino3d.inc
|
|
@ -3283,6 +3283,7 @@ dice_check_win:
|
|||
shl eax, 1
|
||||
add bankroll, eax
|
||||
mov dice3d_win, eax
|
||||
invoke TriggerCharmWinBonus,dice3d_bet
|
||||
mov dice3d_state, 2
|
||||
invoke PlayCasinoSound3D, OFFSET soundRoundWin, 0, 1
|
||||
invoke NpcRecordRound3D,8,1
|
||||
|
|
@ -5373,12 +5374,12 @@ check_slots_mode:
|
|||
call RenderJackbox3D
|
||||
jmp present_frame
|
||||
check_jackbox_done:
|
||||
cmp engineMode,MODE_DARTS
|
||||
jne check_darts_done
|
||||
call HandleDarts3D
|
||||
call RenderDarts3D
|
||||
jmp present_frame
|
||||
check_darts_done:
|
||||
cmp engineMode,MODE_DARTS
|
||||
jne check_darts_done
|
||||
call HandleDarts3D
|
||||
call RenderDarts3D
|
||||
jmp present_frame
|
||||
check_darts_done:
|
||||
cmp engineMode,MODE_FORTUNE
|
||||
jne @F
|
||||
call HandleFortuneDialog3D
|
||||
|
|
@ -5659,7 +5660,7 @@ engine_shutdown:
|
|||
call SaveProgress3D
|
||||
invoke PlayCasinoSound3D, 0, 0, 0
|
||||
call FreeRussianAssets3D
|
||||
call FreeDarts3D
|
||||
call FreeDarts3D
|
||||
call FreeStartupAssets3D
|
||||
call FreeCardTableAssets3D
|
||||
call FreeBuckshotAssets3D
|
||||
|
|
@ -5687,3 +5688,7 @@ IFDEF CASINO_ACTION_TEST
|
|||
include tools\tests\casino_actions_test.inc
|
||||
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
|
||||
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,
|
||||
not decorative extra opponents. Native talisman effects, achievements, daily
|
||||
tasks and online tables still require integration with the selected profile.
|
||||
not decorative extra opponents. Native talisman effects were subsequently
|
||||
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 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
|
||||
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
|
||||
classify only positive net results as wins. No claim of completing every legacy
|
||||
Clover feature or its balance is made.
|
||||
|
|
|
|||
|
|
@ -1,13 +1,16 @@
|
|||
# Native scene fixes
|
||||
|
||||
The MASM game stays in one graphical window. Unported CloverPit,
|
||||
online roulette, Umamusume, tower, terminal and observer interactions open a
|
||||
The MASM game stays in one graphical window. Unported
|
||||
online roulette and Umamusume interactions open a
|
||||
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
|
||||
console routine or blocks the window event loop. Legacy console game code
|
||||
is retained for the earlier standalone console mode, not called by these
|
||||
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
|
||||
podkidnoy/perevodnoy rules and exit confirmation. See `native-durak.md`.
|
||||
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
|
||||
graphical games include the three card tables, Russian roulette, Buckshot,
|
||||
multi-bet casino roulette, coin, dice, skulls, skill checks and billiards.
|
||||
777, CloverPit, online play, tower, terminal and observer still show native
|
||||
unavailable panels. Native profile data remains separate from legacy console
|
||||
777, CloverPit, tower, terminal and observer subsequently received native
|
||||
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.
|
||||
|
|
|
|||
60
poker.asm
60
poker.asm
|
|
@ -1,6 +1,8 @@
|
|||
.386
|
||||
.model flat, stdcall
|
||||
option casemap:none
|
||||
ArtifactSaveSignature3D PROTO :DWORD
|
||||
ValidateArtifactSave3D PROTO :DWORD
|
||||
|
||||
includelib kernel32.lib
|
||||
includelib winmm.lib
|
||||
|
|
@ -24,7 +26,9 @@ FILE_ATTRIBUTE_NORMAL equ 80h
|
|||
INVALID_HANDLE_VALUE equ -1
|
||||
SAVE_MAGIC equ 31435653h
|
||||
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
|
||||
ENABLE_VIRTUAL_TERMINAL_PROCESSING equ 0004h
|
||||
COLOR_DEFAULT equ 07h
|
||||
|
|
@ -576,6 +580,7 @@ ReadKey ENDP
|
|||
|
||||
|
||||
ResetProfileDefaults PROC uses ecx edi
|
||||
call ResetArtifacts3D
|
||||
mov bankroll, 10000
|
||||
mov targetBank, 50000
|
||||
mov gamesPlayed, 0
|
||||
|
|
@ -804,6 +809,20 @@ save_stats_played_loop:
|
|||
loop save_stats_played_loop
|
||||
call CalcSaveSignature
|
||||
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
|
||||
invoke CreateFileA, OFFSET saveFullPath, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0
|
||||
cmp eax, INVALID_HANDLE_VALUE
|
||||
|
|
@ -816,6 +835,7 @@ save_done:
|
|||
SaveGame ENDP
|
||||
|
||||
LoadSave PROC uses eax ecx esi edi
|
||||
call ResetArtifacts3D
|
||||
mov dailyDateKey, 0
|
||||
mov dailyRewardMask, 0
|
||||
mov dailyProgressPacked, 0
|
||||
|
|
@ -844,12 +864,29 @@ load_file_opened:
|
|||
mov eax, DWORD PTR [saveBuffer]
|
||||
cmp eax, SAVE_MAGIC
|
||||
jne load_done
|
||||
cmp charsRead, SAVE_FILE_SIZE
|
||||
cmp charsRead, SAVE_LEGACY_SIZE
|
||||
jb load_signature_ok
|
||||
mov edx, DWORD PTR [saveBuffer+SAVE_SIGN_SIZE]
|
||||
call CalcSaveSignature
|
||||
cmp eax, edx
|
||||
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:
|
||||
mov eax, DWORD PTR [saveBuffer+4]
|
||||
mov bankroll, eax
|
||||
|
|
@ -1905,8 +1942,8 @@ CheckDurakEnd ENDP
|
|||
include casino3d.inc
|
||||
|
||||
|
||||
IFDEF CASINO_ACTION_TEST
|
||||
RunCasinoActionsTest3D PROC uses ebx esi edi
|
||||
IFDEF HELL_TOWER_TEST
|
||||
RunHellTowerTest3D PROC uses ebx esi edi
|
||||
local stageLoop:DWORD
|
||||
|
||||
call InitPaths3D
|
||||
|
|
@ -1914,8 +1951,12 @@ RunCasinoActionsTest3D PROC uses ebx esi edi
|
|||
test eax, eax
|
||||
jz test_error_init
|
||||
|
||||
; Test-owned session: no persistence or profile money is loaded.
|
||||
mov arrivalConfirmed3D,0
|
||||
mov bankroll,10000
|
||||
; Enter Hell Tower
|
||||
call InitHellTower3D
|
||||
invoke ChooseTowerRelic3D,0
|
||||
cmp tournamentMode, 1
|
||||
jne test_error_tower_mode
|
||||
|
||||
|
|
@ -1947,6 +1988,7 @@ stage_test_loop:
|
|||
call Present3D
|
||||
|
||||
; Advance to next stage
|
||||
invoke ChooseTowerRelic3D,0
|
||||
inc towerStage
|
||||
mov towerFloorState, TOWER_STATE_BRIEFING
|
||||
mov towerCalloutAnim, 0
|
||||
|
|
@ -1998,10 +2040,18 @@ test_error_exit_mode:
|
|||
test_error_exit_engine:
|
||||
mov eax, 107
|
||||
ret
|
||||
RunCasinoActionsTest3D ENDP
|
||||
RunHellTowerTest3D ENDP
|
||||
ENDIF
|
||||
|
||||
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
|
||||
call RunCasinoActionsTest3D
|
||||
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_known, -1
|
||||
mov bs3d_known[4], -1
|
||||
call UpdateTowerEye3D
|
||||
mov bs3d_messageTime, 1800
|
||||
bs_commit_done:
|
||||
ret
|
||||
|
|
@ -236,6 +237,9 @@ bs_finish_win:
|
|||
jbe @F
|
||||
mov bankroll, 1000000000
|
||||
@@:
|
||||
mov eax,bs3d_bet
|
||||
shl eax,1
|
||||
invoke TriggerCharmWinBonus,eax
|
||||
invoke NpcRecordRound3D,7,1
|
||||
call SaveProgress3D
|
||||
ret
|
||||
|
|
@ -244,6 +248,7 @@ bs_finish_lose:
|
|||
mov bs3d_result, BS_LOSE
|
||||
mov bs3d_victim, 0
|
||||
mov bs3d_timer, 800
|
||||
invoke TriggerCharmLossProtection,bs3d_bet
|
||||
invoke NpcRecordRound3D,7,0
|
||||
call SaveProgress3D
|
||||
bs_finish_done:
|
||||
|
|
@ -866,6 +871,7 @@ ResolveBuckshotPose3D ENDP
|
|||
|
||||
RenderBuckshot3D PROC uses ebx esi edi
|
||||
local handY:DWORD,pose:DWORD,actor:DWORD
|
||||
call UpdateTowerEye3D
|
||||
mov animOpacity3D, 255
|
||||
cmp bs3d_room.pixels, 0
|
||||
je bs_render_error
|
||||
|
|
|
|||
|
|
@ -129,6 +129,11 @@ LeaveCardTable3D PROC
|
|||
card_leave_hall:
|
||||
mov cardExitActive3D, 0
|
||||
mov paused3D, 0
|
||||
cmp tournamentMode,1
|
||||
jne @F
|
||||
call TowerExitToHall
|
||||
ret
|
||||
@@:
|
||||
mov engineMode, MODE_WALK
|
||||
call ClearKeys3D
|
||||
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
|
||||
local curX:DWORD, tempBuf[16]:BYTE
|
||||
|
||||
cmp tournamentMode,0
|
||||
jne hud_done
|
||||
mov eax, charmCloverUses
|
||||
or eax, charmHorseshoeUses
|
||||
or eax, charmSkullUses
|
||||
|
|
@ -135,6 +16,8 @@ DrawCharmsHUD PROC uses ebx esi edi, drawX:DWORD, drawY:DWORD
|
|||
mov curX, eax
|
||||
|
||||
; 1. Clover Badge
|
||||
test charmEnabledMask3D,1
|
||||
jz check_horse_hud
|
||||
cmp charmCloverUses, 0
|
||||
jle check_horse_hud
|
||||
|
||||
|
|
@ -152,6 +35,8 @@ DrawCharmsHUD PROC uses ebx esi edi, drawX:DWORD, drawY:DWORD
|
|||
|
||||
check_horse_hud:
|
||||
; 2. Horseshoe Badge
|
||||
test charmEnabledMask3D,2
|
||||
jz check_skull_hud
|
||||
cmp charmHorseshoeUses, 0
|
||||
jle check_skull_hud
|
||||
|
||||
|
|
@ -169,6 +54,8 @@ check_horse_hud:
|
|||
|
||||
check_skull_hud:
|
||||
; 3. Skull Badge
|
||||
test charmEnabledMask3D,4
|
||||
jz check_devil_hud
|
||||
cmp charmSkullUses, 0
|
||||
jle check_devil_hud
|
||||
|
||||
|
|
@ -186,6 +73,8 @@ check_skull_hud:
|
|||
|
||||
check_devil_hud:
|
||||
; 4. Devil Contract Badge
|
||||
test charmEnabledMask3D,8
|
||||
jz hud_done
|
||||
cmp charmDevilUses, 0
|
||||
jle hud_done
|
||||
|
||||
|
|
|
|||
|
|
@ -1,19 +1,29 @@
|
|||
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_HORSESHOE_PRICE equ 20000
|
||||
CHARM_HORSESHOE_PRICE equ 1800
|
||||
CHARM_HORSESHOE_USES equ 5
|
||||
|
||||
CHARM_SKULL_PRICE equ 35000
|
||||
CHARM_SKULL_PRICE equ 3500
|
||||
CHARM_SKULL_USES equ 1
|
||||
|
||||
CHARM_DEVIL_PRICE equ 50000
|
||||
CHARM_DEVIL_PRICE equ 4000
|
||||
CHARM_DEVIL_USES equ 2
|
||||
|
||||
TriggerCharmLossProtection 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
|
||||
DrawCharmsHUD PROTO :DWORD, :DWORD
|
||||
|
||||
|
|
@ -24,35 +34,57 @@ charmCloverUses dd 0
|
|||
charmHorseshoeUses dd 0
|
||||
charmSkullUses dd 0
|
||||
charmDevilUses dd 0
|
||||
charmEnabledMask3D dd 7
|
||||
artifactBuyArmed3D dd 0
|
||||
artifactNum3D db 16 dup(0)
|
||||
|
||||
; Charm Store Metadata
|
||||
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
|
||||
|
||||
charmNameClover db 'Êëåâåð Óäà÷è',0
|
||||
charmNameHorseshoe db 'Çîëîòàÿ Ïîäêîâà',0
|
||||
charmNameSkull db '×åðåï Áåññìåðòèÿ',0
|
||||
charmNameDevil db 'Êîíòðàêò Äüÿâîëà',0
|
||||
|
||||
charmNames3D dd OFFSET charmNameClover, OFFSET charmNameHorseshoe, OFFSET charmNameSkull, OFFSET charmNameDevil
|
||||
|
||||
charmDescClover db '15% øàíñ ñïàñòè ñòàâêó',0
|
||||
charmDescHorseshoe db '+15% ê âûèãðûøó â ñëîòàõ',0
|
||||
charmDescSkull db '100% ñïàñåíèå îò ïóëè',0
|
||||
charmDescDevil db '50% øàíñ ñïàñòè ñòàâêó',0
|
||||
|
||||
charmDescs3D dd OFFSET charmDescClover, OFFSET charmDescHorseshoe, OFFSET charmDescSkull, OFFSET charmDescDevil
|
||||
|
||||
; HUD Flash Messages
|
||||
msgCharmCloverSave db 'Êëåâåð ñïàñ âàøó ñòàâêó!',0
|
||||
msgCharmDevilSave db 'Äüÿâîë: ñòàâêà âîçâðàùåíà!',0
|
||||
msgCharmHorseshoeWin db 'Ïîäêîâà: +15% ê âûèãðûøó!',0
|
||||
msgCharmSkullSave db '×åðåï: Îñå÷êà! Âû âûæèëè!',0
|
||||
msgCharmTowerSave db 'Òàëèñìàí ñïàñ âàñ îò ïàäåíèÿ ñ Áàøíè!',0
|
||||
|
||||
; Compact HUD Badges
|
||||
badgeCloverPrefix db '[ÊË:',0
|
||||
badgeHorsePrefix db '[ÏÊ:',0
|
||||
badgeSkullPrefix db '[×Ð:',0
|
||||
badgeDevilPrefix db '[ÊÒ:',0
|
||||
badgeCloseBracket db '] ',0
|
||||
charmNameClover db 202,203,197,194,197,208,0
|
||||
charmNameHorseshoe db 207,206,196,202,206,194,192,0
|
||||
charmNameSkull db 215,197,208,197,207,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
|
||||
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
|
||||
charmDescDevil db 211,228,226,238,232,242,32,239,240,232,225,251,235,252,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
|
||||
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
|
||||
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
|
||||
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
|
||||
badgeHorsePrefix db 91,207,196,58,0
|
||||
badgeSkullPrefix db 91,215,208,58,0
|
||||
badgeDevilPrefix db 91,196,202,58,0
|
||||
badgeCloseBracket db 93,32,0
|
||||
artifactShopTitle3D db 192,208,210,197,212,192,202,210,219,32,209,200,196,206,208,206,194,200,215,192,0
|
||||
artifactStock3D db 197,209,210,220,58,0
|
||||
artifactPack3D db 205,192,193,206,208,58,0
|
||||
artifactPrice3D db 214,197,205,192,58,0
|
||||
artifactOn3D db 194,202,203,0
|
||||
artifactOff3D db 194,219,202,203,0
|
||||
artifactToggle3D db 91,69,93,32,194,202,203,32,47,32,194,219,202,203,0
|
||||
artifactBuy3D db 91,69,78,84,69,82,93,32,202,211,207,200,210,220,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
|
||||
cmp DWORD PTR entrySaveData3D[4], 1000000000
|
||||
ja profile_invalid
|
||||
cmp fileBytes, SAVE_FILE_SIZE
|
||||
cmp fileBytes, SAVE_LEGACY_SIZE
|
||||
jb profile_valid
|
||||
mov esi, OFFSET entrySaveData3D
|
||||
mov ecx, SAVE_SIGN_SIZE/4
|
||||
|
|
@ -43,6 +43,13 @@ profile_signature:
|
|||
loop profile_signature
|
||||
cmp eax, DWORD PTR entrySaveData3D[SAVE_SIGN_SIZE]
|
||||
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:
|
||||
mov eax, 1
|
||||
ret
|
||||
|
|
@ -253,6 +260,7 @@ graphic_create_store:
|
|||
invoke CreateDirectoryA, OFFSET runtime3D, 0
|
||||
invoke CreateDirectoryA, nativeProfilesDirPtr3D, 0
|
||||
call ResetProfileDefaults
|
||||
call ResetArtifacts3D
|
||||
invoke CopyCString, OFFSET saveFileName, OFFSET entryDisplayName3D
|
||||
mov nativeProfileActive3D, 1
|
||||
call SyncGraphicBack3D
|
||||
|
|
|
|||
|
|
@ -12,11 +12,13 @@ FreeTowerMinigameAssets ENDP
|
|||
|
||||
InitHellTower3D PROC
|
||||
call FreeTowerMinigameAssets
|
||||
call ResetTowerRelics3D
|
||||
mov tournamentMode, 1
|
||||
mov towerStage, 1
|
||||
mov towerFloorState, TOWER_STATE_BRIEFING
|
||||
mov towerAnimClock, 0
|
||||
mov towerCalloutAnim, 0
|
||||
call PrepareTowerReward3D
|
||||
|
||||
mov eax, towerFloorY[0]
|
||||
mov towerCursorY, eax
|
||||
|
|
@ -33,6 +35,7 @@ InitHellTower3D ENDP
|
|||
TowerExitToHall PROC
|
||||
call StopTowerMusic
|
||||
call FreeTowerMinigameAssets
|
||||
call ResetTowerRelics3D
|
||||
mov tournamentMode, 0
|
||||
mov engineMode, MODE_WALK
|
||||
call ClearKeys3D
|
||||
|
|
@ -40,6 +43,18 @@ TowerExitToHall PROC
|
|||
TowerExitToHall ENDP
|
||||
|
||||
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
|
||||
dec eax
|
||||
cmp eax, 6
|
||||
|
|
@ -79,6 +94,7 @@ launch_valid:
|
|||
@@:
|
||||
cmp edx, MODE_ROULETTE
|
||||
jne @F
|
||||
mov wheelChip3D,100
|
||||
call InitNativeWheel3D
|
||||
mov engineMode, MODE_ROULETTE
|
||||
jmp launch_done
|
||||
|
|
@ -86,16 +102,32 @@ launch_valid:
|
|||
cmp edx, MODE_BUCKSHOT
|
||||
jne launch_done
|
||||
call InitBuckshot3D
|
||||
test eax,eax
|
||||
jnz @F
|
||||
mov towerFloorState,TOWER_STATE_BRIEFING
|
||||
mov engineMode,MODE_HELL_TOWER
|
||||
ret
|
||||
@@:
|
||||
mov engineMode, MODE_BUCKSHOT
|
||||
|
||||
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
|
||||
ret
|
||||
tower_launch_blocked:
|
||||
ret
|
||||
TowerLaunchCurrentFloor ENDP
|
||||
|
||||
TowerReportRoundOutcome PROC uses eax outcome:DWORD
|
||||
cmp tournamentMode, 1
|
||||
jne report_exit
|
||||
cmp towerFloorState,TOWER_STATE_IN_GAME
|
||||
jne report_exit
|
||||
mov eax, outcome
|
||||
cmp eax, 1
|
||||
jne report_loss
|
||||
|
|
@ -105,6 +137,7 @@ TowerReportRoundOutcome PROC uses eax outcome:DWORD
|
|||
jae report_champion
|
||||
|
||||
mov towerFloorState, TOWER_STATE_CLEAR
|
||||
call PrepareTowerReward3D
|
||||
mov towerCalloutAnim, 0
|
||||
mov eax, towerStage
|
||||
dec eax
|
||||
|
|
@ -120,8 +153,8 @@ TowerReportRoundOutcome PROC uses eax outcome:DWORD
|
|||
|
||||
report_champion:
|
||||
mov towerFloorState, TOWER_STATE_CHAMPION
|
||||
mov eax, towerPrizeAmount
|
||||
add bankroll, eax
|
||||
invoke ArtifactCredit3D,towerPrizeAmount
|
||||
call ResetTowerRelics3D
|
||||
invoke PlayCasinoSound3D, OFFSET soundRoundWin, 0, 1
|
||||
call SaveProgress3D
|
||||
mov engineMode, MODE_HELL_TOWER
|
||||
|
|
@ -129,16 +162,39 @@ report_champion:
|
|||
ret
|
||||
|
||||
report_loss:
|
||||
invoke TriggerCharmLossProtection, 0
|
||||
test eax, eax
|
||||
jz @F
|
||||
mov towerFloorState, TOWER_STATE_BRIEFING
|
||||
invoke CopyString3D, OFFSET msgCharmTowerSave, OFFSET flashMessage
|
||||
mov flashTimer, 140
|
||||
mov engineMode, MODE_HELL_TOWER
|
||||
cmp towerPurseUses3D,0
|
||||
je tower_loss_retry
|
||||
mov eax,towerEntryBank3D
|
||||
sub eax,bankroll
|
||||
jbe tower_loss_retry
|
||||
cmp eax,5000
|
||||
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
|
||||
ret
|
||||
@@:
|
||||
tower_loss_final:
|
||||
call ResetTowerRelics3D
|
||||
mov towerFloorState, TOWER_STATE_DEFEAT
|
||||
call StopTowerMusic
|
||||
invoke PlayCasinoSound3D, OFFSET soundRoundLose, 0, 1
|
||||
|
|
@ -151,6 +207,11 @@ report_exit:
|
|||
TowerReportRoundOutcome ENDP
|
||||
|
||||
HandleHellTowerInput PROC
|
||||
cmp towerRewardPending3D,1
|
||||
jne @F
|
||||
call HandleTowerReward3D
|
||||
ret
|
||||
@@:
|
||||
mov eax, towerFloorState
|
||||
cmp eax, TOWER_STATE_BRIEFING
|
||||
je input_briefing
|
||||
|
|
@ -240,6 +301,11 @@ HandleHellTowerInput ENDP
|
|||
RenderHellTower3D PROC uses ebx esi edi
|
||||
local cardX:DWORD, cardY:DWORD, cardW:DWORD, cardH: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
|
||||
cmp hellTowerMenuArt3D.pixels, 0
|
||||
|
|
@ -456,10 +522,18 @@ render_card_briefing:
|
|||
invoke DrawBoxBorder, eax, 134, ecx, 32, 00180303h, 00661111h, 1
|
||||
mov eax, cardX
|
||||
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
|
||||
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)
|
||||
mov eax, cardX
|
||||
|
|
@ -552,6 +626,7 @@ render_card_champion:
|
|||
invoke DrawString8x8, eax, 184, OFFSET towerReturnBtn, 00FFFFFFh
|
||||
|
||||
render_tower_done:
|
||||
call RenderTowerRelicStock3D
|
||||
ret
|
||||
RenderHellTower3D ENDP
|
||||
|
||||
|
|
@ -568,7 +643,10 @@ RenderTowerInGameBadge PROC
|
|||
invoke FormatNumber, towerStage, OFFSET hudNumBuffer
|
||||
invoke DrawString8x8, 64, 8, OFFSET hudNumBuffer, 00FFFFFFh
|
||||
invoke DrawString8x8, 72, 8, OFFSET towerHudOfTen, 00AAAAAAh
|
||||
call RenderTowerRelicStock3D
|
||||
|
||||
badge_done:
|
||||
ret
|
||||
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
|
||||
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 merchantReaction3D, 1280
|
||||
mov merchantMessage3D, 0
|
||||
mov merchantTab3D, 0
|
||||
mov merchantTab3D, 1
|
||||
mov artifactBuyArmed3D,0
|
||||
mov merchantCharmSelected3D, 0
|
||||
mov eax, selectedBack3D
|
||||
cmp eax, 12
|
||||
|
|
@ -48,49 +49,40 @@ merchant_purchase_done:
|
|||
ret
|
||||
BuyMerchantBack3D ENDP
|
||||
|
||||
BuyMerchantCharm3D PROC uses ebx charmIndex:DWORD
|
||||
mov ebx, charmIndex
|
||||
cmp ebx, 3
|
||||
ja charm_purchase_done
|
||||
mov eax, charmPrices3D[ebx*4]
|
||||
cmp bankroll, eax
|
||||
BuyMerchantCharm3D PROC uses ebx esi charmIndex:DWORD
|
||||
mov ebx,charmIndex
|
||||
cmp ebx,CHARM_COUNT
|
||||
jae charm_purchase_done
|
||||
lea esi,charmCloverUses
|
||||
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
|
||||
sub bankroll, eax
|
||||
mov ecx, charmUsesPack3D[ebx*4]
|
||||
cmp ebx, 0
|
||||
jne @F
|
||||
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
|
||||
sub bankroll,eax
|
||||
mov eax,charmUsesPack3D[ebx*4]
|
||||
add [esi+ebx*4],eax
|
||||
mov merchantMessage3D,1
|
||||
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
|
||||
charm_purchase_poor:
|
||||
mov merchantMessage3D, 2
|
||||
mov merchantReaction3D, 0
|
||||
mov merchantReactionKind3D, 1
|
||||
mov merchantMessage3D,2
|
||||
charm_purchase_done:
|
||||
ret
|
||||
BuyMerchantCharm3D ENDP
|
||||
|
||||
HandleMerchant3D PROC uses ebx
|
||||
cmp merchantTab3D,1
|
||||
jne @F
|
||||
call HandleArtifactShop3D
|
||||
ret
|
||||
@@:
|
||||
mov eax, merchantSelected3D
|
||||
cmp eax, merchantPreviousFocus3D
|
||||
je @F
|
||||
|
|
@ -256,6 +248,11 @@ HandleMerchant3D ENDP
|
|||
|
||||
RenderMerchant3D PROC uses ebx esi edi
|
||||
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, 21, 320, 7, 00836638h
|
||||
invoke DrawBox, 0, 151, 320, 63, 003C3024h
|
||||
|
|
@ -451,3 +448,5 @@ merchant_render_footer:
|
|||
invoke DrawString8x8, 8, 229, OFFSET merchantShopKeysWithTabs, 00C5C7B8h
|
||||
ret
|
||||
RenderMerchant3D ENDP
|
||||
|
||||
include src_graphics\artifact_shop.inc
|
||||
|
|
|
|||
|
|
@ -75,6 +75,8 @@ NativeBJSettle3D PROC result:DWORD
|
|||
add eax, edx
|
||||
bj_settle_credit:
|
||||
add bankroll, eax
|
||||
sub eax,cbStake3D
|
||||
invoke TriggerCharmWinBonus,eax
|
||||
invoke PlayCasinoSound3D, OFFSET soundRoundWin, 0, 1
|
||||
jmp bj_settle_save
|
||||
bj_settle_loss:
|
||||
|
|
@ -230,6 +232,9 @@ bj_animate_hit:
|
|||
jne bj_begin_dealer
|
||||
jmp bj_begin_player
|
||||
bj_player_bust:
|
||||
call TryTowerBustSave3D
|
||||
test eax,eax
|
||||
jnz bj_begin_dealer
|
||||
invoke FinishBJPlayer3D, 1
|
||||
ret
|
||||
bj_animate_dealer:
|
||||
|
|
@ -327,6 +332,13 @@ bj_ready_input:
|
|||
jnz bj_tourney_report
|
||||
ret
|
||||
bj_tourney_report:
|
||||
cmp cbOutcome3D,2
|
||||
jne @F
|
||||
mov towerFloorState,TOWER_STATE_BRIEFING
|
||||
mov engineMode,MODE_HELL_TOWER
|
||||
call ClearKeys3D
|
||||
ret
|
||||
@@:
|
||||
cmp cbOutcome3D, 1
|
||||
je bj_tourney_loss
|
||||
invoke TowerReportRoundOutcome, 1
|
||||
|
|
|
|||
|
|
@ -186,10 +186,14 @@ SettleNativeClover3D PROC
|
|||
jmp clp_settle_leave
|
||||
@@:
|
||||
invoke PlayCasinoSound3D,OFFSET soundRoundWin,0,1
|
||||
invoke TriggerCharmWinBonus, clpGross3D
|
||||
mov eax,clpGross3D
|
||||
sub eax,clpStake3D
|
||||
invoke TriggerCharmWinBonus,eax
|
||||
jmp clp_settle_leave
|
||||
clp_settle_loss:
|
||||
invoke TriggerCharmLossProtection, clpStake3D
|
||||
mov eax,clpStake3D
|
||||
sub eax,clpGross3D
|
||||
invoke TriggerCharmLossProtection,eax
|
||||
test eax, eax
|
||||
jnz clp_settle_leave
|
||||
invoke PlayCasinoSound3D,OFFSET soundRoundLose,0,1
|
||||
|
|
|
|||
|
|
@ -58,6 +58,9 @@ CoinEscape3D PROC
|
|||
mov paused3D,0
|
||||
cmp tournamentMode, 1
|
||||
jne @F
|
||||
call CoinSettle3D
|
||||
call CloseCoinDetail3D
|
||||
mov coinExitQueued3D,0
|
||||
call TowerExitToHall
|
||||
ret
|
||||
@@:
|
||||
|
|
@ -96,6 +99,7 @@ CoinSettle3D PROC
|
|||
jbe @F
|
||||
mov bankroll,1000000000
|
||||
@@:
|
||||
invoke TriggerCharmWinBonus,coin3d_bet
|
||||
invoke PlayCasinoSound3D,OFFSET soundCoinDing,0,1
|
||||
jmp coin_settle_save
|
||||
coin_settle_loss:
|
||||
|
|
|
|||
|
|
@ -35,6 +35,11 @@ DiceEscape3D PROC
|
|||
ret
|
||||
dice_escape_now:
|
||||
mov diceExitQueued3D,0
|
||||
cmp tournamentMode,1
|
||||
jne @F
|
||||
call TowerExitToHall
|
||||
ret
|
||||
@@:
|
||||
mov engineMode,MODE_WALK
|
||||
call ClearKeys3D
|
||||
invoke PlayCasinoSound3D,0,0,0
|
||||
|
|
|
|||
|
|
@ -127,6 +127,8 @@ NativeDurakSettle3D PROC result:DWORD
|
|||
shl eax, 1
|
||||
@@:
|
||||
add bankroll, eax
|
||||
sub eax,dkStake3D
|
||||
invoke TriggerCharmWinBonus,eax
|
||||
invoke PlayCasinoSound3D, OFFSET soundRoundWin, 0, 1
|
||||
jmp dk_settle_save
|
||||
dk_settle_loss:
|
||||
|
|
|
|||
|
|
@ -255,6 +255,8 @@ PokerFold3D PROC actor:DWORD
|
|||
je poker_fold_player
|
||||
mov eax, pkPot3D
|
||||
add bankroll, eax
|
||||
sub eax,pkPaid3D[0]
|
||||
invoke TriggerCharmWinBonus,eax
|
||||
mov pkOutcome3D, 0
|
||||
invoke PlayCasinoSound3D, OFFSET soundRoundWin, 0, 1
|
||||
jmp poker_fold_settled
|
||||
|
|
@ -343,6 +345,8 @@ poker_evaluate_player:
|
|||
je poker_showdown_tie
|
||||
mov eax, pkPot3D
|
||||
add bankroll, eax
|
||||
sub eax,pkPaid3D[0]
|
||||
invoke TriggerCharmWinBonus,eax
|
||||
mov pkOutcome3D, 0
|
||||
invoke PlayCasinoSound3D, OFFSET soundRoundWin, 0, 1
|
||||
jmp poker_showdown_settled
|
||||
|
|
|
|||
|
|
@ -173,10 +173,14 @@ slot_settle_stops:
|
|||
jmp slot_settle_exit
|
||||
@@:
|
||||
invoke PlayCasinoSound3D,OFFSET soundRoundWin,0,1
|
||||
invoke TriggerCharmWinBonus, slotWinAmount
|
||||
mov eax,slotWinAmount
|
||||
sub eax,slotStake3D
|
||||
invoke TriggerCharmWinBonus,eax
|
||||
jmp slot_settle_exit
|
||||
slot_settle_loss:
|
||||
invoke TriggerCharmLossProtection, slotStake3D
|
||||
mov eax,slotStake3D
|
||||
sub eax,slotWinAmount
|
||||
invoke TriggerCharmLossProtection,eax
|
||||
test eax, eax
|
||||
jnz slot_settle_exit
|
||||
invoke PlayCasinoSound3D,OFFSET soundRoundLose,0,1
|
||||
|
|
|
|||
|
|
@ -134,12 +134,15 @@ wheel_bank_cap:
|
|||
mov ecx, wheelReturn3D
|
||||
cmp ecx, wheelStake3D
|
||||
ja wheel_win_charm
|
||||
cmp ecx, 0
|
||||
jne wheel_charm_done
|
||||
invoke TriggerCharmLossProtection, wheelStake3D
|
||||
je wheel_charm_done
|
||||
mov eax,wheelStake3D
|
||||
sub eax,wheelReturn3D
|
||||
invoke TriggerCharmLossProtection,eax
|
||||
jmp wheel_charm_done
|
||||
wheel_win_charm:
|
||||
invoke TriggerCharmWinBonus, wheelReturn3D
|
||||
mov eax,wheelReturn3D
|
||||
sub eax,wheelStake3D
|
||||
invoke TriggerCharmWinBonus,eax
|
||||
wheel_charm_done:
|
||||
mov roulState, 2
|
||||
xor eax,eax
|
||||
|
|
@ -519,6 +522,11 @@ WheelEscape3D PROC
|
|||
ret
|
||||
wheel_leave_hall:
|
||||
mov wheelExitQueued3D,0
|
||||
cmp tournamentMode,1
|
||||
jne @F
|
||||
call TowerExitToHall
|
||||
ret
|
||||
@@:
|
||||
mov engineMode,MODE_WALK
|
||||
call ClearKeys3D
|
||||
invoke PlayCasinoSound3D,0,0,0
|
||||
|
|
|
|||
|
|
@ -549,14 +549,26 @@ LoadProgress3D PROC uses ebx
|
|||
mov charmHorseshoeUses, 0
|
||||
mov charmSkullUses, 0
|
||||
mov charmDevilUses, 0
|
||||
mov charmEnabledMask3D,7
|
||||
invoke CreateFileA, OFFSET savePath3D, 80000000h, 1, 0, 3, 80h, 0
|
||||
cmp eax, -1
|
||||
je progress_loaded
|
||||
mov ebx, eax
|
||||
invoke ReadFile, ebx, OFFSET saveData3D, 32, OFFSET saveIo3D, 0
|
||||
invoke ReadFile, ebx, OFFSET saveData3D, 40, OFFSET saveIo3D, 0
|
||||
invoke CloseHandle, ebx
|
||||
cmp saveIo3D, 16
|
||||
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
|
||||
je progress_version_ok
|
||||
cmp saveData3D, 32443343h
|
||||
|
|
@ -607,6 +619,7 @@ progress_version_ok:
|
|||
mov eax, saveData3D[28]
|
||||
mov charmDevilUses, eax
|
||||
progress_loaded:
|
||||
call ClampArtifacts3D
|
||||
ret
|
||||
LoadProgress3D ENDP
|
||||
|
||||
|
|
@ -625,7 +638,7 @@ SaveProgress3D PROC uses ebx
|
|||
ret
|
||||
@@:
|
||||
invoke CreateDirectoryA, OFFSET runtime3D, 0
|
||||
mov saveData3D, 33443343h
|
||||
mov saveData3D, 34443343h
|
||||
mov eax, bankroll
|
||||
mov saveData3D[4], eax
|
||||
mov eax, ownedBacks3D
|
||||
|
|
@ -640,11 +653,15 @@ SaveProgress3D PROC uses ebx
|
|||
mov saveData3D[24], eax
|
||||
mov eax, charmDevilUses
|
||||
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
|
||||
cmp eax, -1
|
||||
je progress_saved
|
||||
mov ebx, eax
|
||||
invoke WriteFile, ebx, OFFSET saveData3D, 32, OFFSET saveIo3D, 0
|
||||
invoke WriteFile, ebx, OFFSET saveData3D, 40, OFFSET saveIo3D, 0
|
||||
invoke CloseHandle, ebx
|
||||
progress_saved:
|
||||
ret
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ displaySettingsPath3D db "runtime\display.cfg",0
|
|||
displaySettingsData3D dd 44535031h,1,0
|
||||
displaySettingsIo3D dd 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
|
||||
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
|
||||
|
|
|
|||
|
|
@ -81,6 +81,8 @@ RRPartyWin3D PROC
|
|||
imul eax,rrPartySize3D
|
||||
mov rr3d_payout,eax
|
||||
add bankroll,eax
|
||||
sub eax,rrPartyStake3D
|
||||
invoke TriggerCharmWinBonus,eax
|
||||
mov rr3d_state,RR_WIN
|
||||
invoke PlayCasinoSound3D,OFFSET soundRoundWin,0,20003h
|
||||
invoke NpcRecordRound3D,6,1
|
||||
|
|
@ -93,6 +95,7 @@ RRPartyLose3D PROC
|
|||
cmp rrPartySettled3D,0
|
||||
jne rr_party_lose_done
|
||||
mov rrPartySettled3D,1
|
||||
invoke TriggerCharmLossProtection,rrPartyStake3D
|
||||
mov rr3d_state,RR_GLITCH
|
||||
invoke NpcRecordRound3D,6,0
|
||||
call SaveProgress3D
|
||||
|
|
|
|||
|
|
@ -185,12 +185,14 @@ rr_live_round:
|
|||
add bankroll, eax
|
||||
mov rr3d_state, RR_WIN
|
||||
mov rrPartySettled3D,1
|
||||
invoke TriggerCharmWinBonus,rr3d_bet
|
||||
invoke PlayCasinoSound3D, OFFSET soundRoundWin, 0, 20003h
|
||||
invoke NpcRecordRound3D,6,1
|
||||
call SaveProgress3D
|
||||
ret
|
||||
rr_player_lost:
|
||||
mov rrPartySettled3D,1
|
||||
invoke TriggerCharmLossProtection,rr3d_bet
|
||||
mov rr3d_state, RR_GLITCH
|
||||
invoke NpcRecordRound3D,6,0
|
||||
call SaveProgress3D
|
||||
|
|
|
|||
|
|
@ -413,12 +413,15 @@ FinishScratch3D PROC
|
|||
mov ecx, scrGross3D
|
||||
cmp ecx, scrStake3D
|
||||
ja scratch_charm_win
|
||||
cmp ecx, 0
|
||||
jne @F
|
||||
invoke TriggerCharmLossProtection, scrStake3D
|
||||
je @F
|
||||
mov eax,scrStake3D
|
||||
sub eax,scrGross3D
|
||||
invoke TriggerCharmLossProtection,eax
|
||||
jmp @F
|
||||
scratch_charm_win:
|
||||
invoke TriggerCharmWinBonus, scrGross3D
|
||||
mov eax,scrGross3D
|
||||
sub eax,scrStake3D
|
||||
invoke TriggerCharmWinBonus,eax
|
||||
@@:
|
||||
call ScratchStartPayout3D
|
||||
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
|
||||
mov bankroll, 35000
|
||||
call BeginMerchant3D
|
||||
mov merchantTab3D,0
|
||||
mov merchantSelected3D, 5
|
||||
mov merchantReaction3D, 1280
|
||||
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_terminals import signature
|
||||
from check_character_cast import check as check_character_cast
|
||||
from check_artifacts import toolchain
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
OUT = ROOT / "build/hall-expansion"
|
||||
|
|
@ -329,11 +330,11 @@ def main():
|
|||
(OUT/(stem+".asm")).write_text(source,encoding="cp1251")
|
||||
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")
|
||||
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.",
|
||||
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]
|
||||
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"/LIBPATH:{sdk}",f"/LIBPATH:{masm/'lib'}",f"/OUT:build/hall-expansion/{stem}.exe",
|
||||
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."""
|
||||
import subprocess
|
||||
import sys
|
||||
"""Smoke-test six real tower scene launches; outcomes injected, not balance measurement."""
|
||||
import hashlib
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
from check_artifacts import toolchain
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
POKER_ASM = ROOT / "poker.asm"
|
||||
OUT = ROOT/'build/hell-tower'
|
||||
|
||||
|
||||
def main():
|
||||
print("[1/4] Preparing test harness in poker.asm...")
|
||||
code = POKER_ASM.read_text(encoding="cp1251")
|
||||
target = "\nIFDEF CASINO_ACTION_TEST\n"
|
||||
if "CASINO_ACTION_TEST equ 1\n" not in code:
|
||||
code = code.replace(target, "\nCASINO_ACTION_TEST equ 1\nIFDEF CASINO_ACTION_TEST\n")
|
||||
POKER_ASM.write_text(code, encoding="cp1251")
|
||||
|
||||
try:
|
||||
print("[2/4] Building poker.exe with test harness...")
|
||||
build_res = subprocess.run(["cmd.exe", "/c", "build.bat"], cwd=ROOT, capture_output=True, text=True)
|
||||
if build_res.returncode != 0:
|
||||
print("[FAIL] Build failed:", build_res.stdout, build_res.stderr)
|
||||
return 1
|
||||
|
||||
print("[3/4] Running Hell Tower 6-floor run-through...")
|
||||
run_res = subprocess.run([str(ROOT / "poker.exe")], cwd=ROOT, capture_output=True, timeout=15)
|
||||
print(f"Hell Tower test completed with exit code: {run_res.returncode}")
|
||||
if run_res.returncode != 0:
|
||||
print(f"[FAIL] Hell Tower run-through failed with code {run_res.returncode}")
|
||||
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
|
||||
OUT.mkdir(parents=True, exist_ok=True)
|
||||
source_hash = hashlib.sha256((ROOT/'poker.asm').read_bytes()).digest()
|
||||
runtime = {p: hashlib.sha256(p.read_bytes()).digest()
|
||||
for p in (ROOT/'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())
|
||||
subprocess.run([str(ml), '/c', '/coff', '/Cp', '/nologo', '/I.', '/DHELL_TOWER_TEST=1',
|
||||
'/Fobuild/hell-tower/test.obj', 'poker.asm'], cwd=ROOT, check=True)
|
||||
subprocess.run([str(link), '/nologo', '/SUBSYSTEM:CONSOLE', '/LIBPATH:'+str(libraries),
|
||||
'/OUT:build/hell-tower/test.exe', 'build/hell-tower/test.obj',
|
||||
'kernel32.lib', 'winmm.lib', 'user32.lib', 'gdi32.lib', 'opengl32.lib'],
|
||||
cwd=ROOT, check=True)
|
||||
subprocess.run([str(OUT/'test.exe')], cwd=ROOT, check=True, timeout=90)
|
||||
assert hashlib.sha256((ROOT/'poker.asm').read_bytes()).digest() == source_hash
|
||||
assert {p: hashlib.sha256(p.read_bytes()).digest()
|
||||
for p in (ROOT/'runtime').rglob('*') if p.is_file()} == runtime
|
||||
print('PASS: six tower scene launches, reward transitions and exit; source/runtime unchanged')
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
.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
|
||||
.code
|
||||
RunUnavailableTest3D PROC uses ebx esi edi
|
||||
|
|
@ -72,7 +74,7 @@ unavailable_test_close:
|
|||
cmp playerAngle,eax
|
||||
jne unavailable_test_fail
|
||||
inc esi
|
||||
cmp esi,5
|
||||
cmp esi,unavailableTestCount3D
|
||||
jb unavailable_test_next
|
||||
mov eax,oldMode
|
||||
mov engineMode,eax
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue