EBLAN_ENGINE/include/engine_gameplay.inc
Игорь Федосеев 527d92411d chore: integrate main before stage 2
Preserve stage-1 stability fixes alongside v5 lighting, IPC v2, weapons and studio updates. Fix barrel AOE pointer corruption and extend modal gameplay gating.

Verify 137 editor checks, 191 ASM checks, lighting bake and preview parity. Document stage-2 scope without implementing it.
2026-10-31 22:10:07 +03:00

342 lines
9.6 KiB
PHP

; ==============================================================================
; EBLAN ENGINE - Gameplay Events, Scripting Hooks, HUD Toasts & Dialog Modals
; ==============================================================================
.code
DrawPixel PROTO :DWORD, :DWORD, :DWORD
DrawRect PROTO :DWORD, :DWORD, :DWORD, :DWORD, :DWORD
DrawRectOutline PROTO :DWORD, :DWORD, :DWORD, :DWORD, :DWORD
DrawString8x8 PROTO :DWORD, :DWORD, :DWORD, :DWORD
DrawNumber8x8 PROTO :DWORD, :DWORD, :DWORD, :DWORD
PlaySoundA PROTO :DWORD, :DWORD, :DWORD
; ------------------------------------------------------------------------------
; ShowGameToast: Displays a floating toast notification banner on screen
; ------------------------------------------------------------------------------
ShowGameToast PROC uses esi edi ecx eax, pszText:DWORD, duration:DWORD, textColor:DWORD
mov esi, pszText
test esi, esi
jz toast_skip_copy
mov edi, OFFSET gameToastText
mov ecx, 63
toast_copy_loop:
lodsb
stosb
test al, al
jz toast_copy_done
dec ecx
jnz toast_copy_loop
xor al, al
stosb
toast_copy_done:
toast_skip_copy:
mov eax, duration
mov gameToastTimer, eax
mov eax, textColor
mov gameToastColor, eax
ret
ShowGameToast ENDP
; ------------------------------------------------------------------------------
; RenderGameToast: Draws active toast notification at top center of screen
; ------------------------------------------------------------------------------
RenderGameToast PROC uses ebx ecx edx esi edi
cmp gameToastTimer, 0
jle rt_done
dec gameToastTimer
; 1. Calculate text character length
mov esi, OFFSET gameToastText
xor ecx, ecx
count_len:
mov al, [esi+ecx]
test al, al
jz count_done
inc ecx
cmp ecx, 63
jb count_len
count_done:
test ecx, ecx
jz rt_done
; Width in pixels = length * 8
mov eax, ecx
shl eax, 3
mov edx, eax
; Center X = (SCREEN_W - width) / 2
mov ebx, SCREEN_W
sub ebx, edx
sar ebx, 1
; Box coordinates: X = ebx - 6, Y = 16, W = edx + 12, H = 14
mov eax, ebx
sub eax, 6
mov esi, edx
add esi, 12
invoke DrawRect, eax, 16, esi, 14, 00101010h
invoke DrawRectOutline, eax, 16, esi, 14, gameToastColor
invoke DrawString8x8, ebx, 19, OFFSET gameToastText, gameToastColor
rt_done:
ret
RenderGameToast ENDP
; ------------------------------------------------------------------------------
; ShowGameDialog: Opens an interactive retro dialogue modal with speaker and text
; ------------------------------------------------------------------------------
ShowGameDialog PROC uses esi edi ecx eax, pszSpeaker:DWORD, pszText:DWORD
mov esi, pszSpeaker
mov edi, OFFSET gameDialogSpeaker
mov ecx, 31
test esi, esi
jz no_speaker
copy_spk:
lodsb
stosb
test al, al
jz spk_done
dec ecx
jnz copy_spk
xor al, al
stosb
spk_done:
jmp setup_dlg_text
no_speaker:
mov BYTE PTR [edi], 0
setup_dlg_text:
mov esi, pszText
mov edi, OFFSET gameDialogText
mov ecx, 127
test esi, esi
jz no_text
copy_txt:
lodsb
stosb
test al, al
jz txt_done
dec ecx
jnz copy_txt
xor al, al
stosb
txt_done:
jmp activate_dlg
no_text:
mov BYTE PTR [edi], 0
activate_dlg:
mov gameDialogActive, 1
ret
ShowGameDialog ENDP
; ------------------------------------------------------------------------------
; CloseGameDialog: Closes active dialogue box
; ------------------------------------------------------------------------------
CloseGameDialog PROC
mov gameDialogActive, 0
ret
CloseGameDialog ENDP
; ------------------------------------------------------------------------------
; RenderGameDialog: Draws active dialogue box at bottom of screen
; ------------------------------------------------------------------------------
RenderGameDialog PROC uses ebx ecx edx esi edi
cmp gameDialogActive, 0
je rd_done
; Dialog Box background: X = 16, Y = 170, W = 288, H = 42
invoke DrawRect, 16, 170, 288, 42, 00121212h
invoke DrawRectOutline, 16, 170, 288, 42, COLOR_CYAN
; Speaker name (if not empty)
cmp BYTE PTR [gameDialogSpeaker], 0
je draw_dlg_body
invoke DrawString8x8, 24, 174, OFFSET gameDialogSpeaker, COLOR_YELLOW
draw_dlg_body:
; Text
invoke DrawString8x8, 24, 186, OFFSET gameDialogText, COLOR_WHITE
; Close hint in bottom-right
invoke DrawString8x8, 140, 200, OFFSET szDialogCloseHint, COLOR_GRAY
; Check if player pressed Action key or Attack to dismiss
cmp keyAction, 0
jne do_dismiss
cmp keyAttack, 0
jne do_dismiss
jmp rd_done
do_dismiss:
mov keyAction, 0
mov keyAttack, 0
mov gameDialogActive, 0
rd_done:
ret
RenderGameDialog ENDP
; ------------------------------------------------------------------------------
; PlayGameSFX: Asynchronously plays a sound effect via WinMM PlaySoundA
; ------------------------------------------------------------------------------
PlayGameSFX PROC uses eax, pszRelativePath:DWORD
cmp isCutsceneActive, 0
jne sfx_done
mov eax, pszRelativePath
test eax, eax
jz sfx_done
cmp BYTE PTR [eax], 0
jz sfx_done
invoke PlaySoundA, eax, 0, 9 ; SND_FILENAME (1) | SND_ASYNC (8) = 9
sfx_done:
ret
PlayGameSFX ENDP
; ------------------------------------------------------------------------------
; Game_OnTick: Hook called every 60 Hz frame during active gameplay
; ------------------------------------------------------------------------------
Game_OnTick PROC uses eax ebx ecx edx
; Extensible hook for custom game logic (quests, timers, zones)
ret
Game_OnTick ENDP
; ------------------------------------------------------------------------------
; Game_OnPlayerInteract: Hook called when player presses [E] in range of an entity
; Returns: EAX = 1 if handled by custom script, 0 if default engine behavior
; ------------------------------------------------------------------------------
Game_OnPlayerInteract PROC uses ebx ecx edx esi edi, entityIdx:DWORD, entityTypeVal:DWORD
; Extensible hook for custom interactions
xor eax, eax
ret
Game_OnPlayerInteract ENDP
; ------------------------------------------------------------------------------
; Game_OnEntityKilled: Hook called when enemy guard or barrel is destroyed
; ------------------------------------------------------------------------------
Game_OnEntityKilled PROC uses eax ebx ecx edx, entityIdx:DWORD, entityTypeVal:DWORD
; Extensible hook for boss fights, doors opening on kill, score multipliers
ret
Game_OnEntityKilled ENDP
; ------------------------------------------------------------------------------
; Game_OnCustomHUD: Hook called during HUD rendering
; ------------------------------------------------------------------------------
Game_OnCustomHUD PROC uses eax ebx ecx edx
; Extensible hook for custom UI bars, quest markers, mini-dialogues
ret
Game_OnCustomHUD ENDP
; ------------------------------------------------------------------------------
; RenderGameHUDOverlays: Renders active toast banner, dialogue modal, and custom HUD
; ------------------------------------------------------------------------------
RenderGameHUDOverlays PROC
call RenderGameToast
call RenderGameDialog
call Game_OnCustomHUD
ret
RenderGameHUDOverlays ENDP
; ------------------------------------------------------------------------------
; CheckCmdFlag: Case-insensitive substring search (EAX = 1 if found, 0 if not)
; ------------------------------------------------------------------------------
CheckCmdFlag PROC uses esi edi ecx, pszCmd:DWORD, pszFlag:DWORD
mov esi, pszCmd
test esi, esi
jz flag_not_found
check_next_char:
cmp byte ptr [esi], 0
je flag_not_found
mov edi, pszFlag
mov ecx, esi
compare_loop:
mov al, byte ptr [edi]
test al, al
jz flag_found
mov ah, byte ptr [ecx]
cmp al, 'A'
jl @F
cmp al, 'Z'
jg @F
add al, 32
@@:
cmp ah, 'A'
jl @F
cmp ah, 'Z'
jg @F
add ah, 32
@@:
cmp al, ah
jne mismatch
inc edi
inc ecx
jmp compare_loop
mismatch:
inc esi
jmp check_next_char
flag_found:
mov eax, 1
ret
flag_not_found:
xor eax, eax
ret
CheckCmdFlag ENDP
; ------------------------------------------------------------------------------
; LoadProjectSettings: Reads project.eblanproj if present in working directory
; ------------------------------------------------------------------------------
LoadProjectSettings PROC uses ebx ecx edx esi edi
LOCAL hFile:DWORD, bytesRead:DWORD
LOCAL projBuf[1024]:BYTE
invoke CreateFileA, OFFSET szProjectFile, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0
cmp eax, INVALID_HANDLE_VALUE
je proj_done
mov hFile, eax
lea edx, projBuf
invoke ReadFile, hFile, edx, 1023, ADDR bytesRead, 0
invoke CloseHandle, hFile
cmp bytesRead, 0
jle proj_done
mov eax, bytesRead
mov byte ptr [projBuf + eax], 0
lea edx, projBuf
invoke CheckCmdFlag, edx, OFFSET szProjGameMode0
test eax, eax
jnz set_adv_mode
lea edx, projBuf
invoke CheckCmdFlag, edx, OFFSET szProjShowWeapons0
test eax, eax
jnz set_adv_mode
lea edx, projBuf
invoke CheckCmdFlag, edx, OFFSET szProjGameMode1
test eax, eax
jnz set_act_mode
jmp proj_done
set_adv_mode:
mov gameMode, GAME_MODE_ADVENTURE
mov enableWeapons, 0
mov playerWeapon, WEAPON_NONE
mov showCrosshair, 0
jmp proj_done
set_act_mode:
mov gameMode, GAME_MODE_ACTION
mov enableWeapons, 1
mov playerWeapon, WEAPON_PISTOL
mov showCrosshair, 1
proj_done:
ret
LoadProjectSettings ENDP