343 lines
9.6 KiB
PHP
343 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
|
|
|