; ============================================================================== ; 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