; ============================================================================== ; EBLAN ENGINE - Player Combat, Weapon Shooting & Combat HUD ; ============================================================================== .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 ; ------------------------------------------------------------------------------ ; UpdateCombat: Process weapon firing, hitscan raycasting, cooldowns & damage ; ------------------------------------------------------------------------------ UpdateCombat PROC uses ebx ecx edx esi edi LOCAL camCos:DWORD, camSin:DWORD LOCAL i:DWORD, closestIdx:DWORD, closestDist:DWORD LOCAL sprX:DWORD, sprY:DWORD LOCAL transX:DWORD, transY:DWORD LOCAL sprScreenX:DWORD, wallDepth:DWORD ; 1. Decrement cooldowns cmp playerAttackCooldown, 0 je @F dec playerAttackCooldown @@: cmp playerFlashTimer, 0 je @F dec playerFlashTimer @@: cmp playerHitFlash, 0 je @F dec playerHitFlash @@: ; If player is dead, cannot attack cmp isPlayerDead, 0 jne combat_done ; 2. Check attack input cmp keyAttack, 0 je combat_done cmp playerAttackCooldown, 0 jne combat_done ; Check ammo cmp playerAmmo, 0 jle combat_dry_fire ; Fire weapon! dec playerAmmo mov playerAttackCooldown, 10 mov playerFlashTimer, 5 ; 3. Hitscan check against enemies in center crosshair ; Camera basis for -playerAngle mov eax, ANGLE_512 sub eax, playerAngle and eax, ANGLE_MASK mov ecx, [tableCos + eax*4] mov camCos, ecx mov edx, [tableSin + eax*4] mov camSin, edx ; Center wall depth from depthBuffer[160] mov eax, [depthBuffer + SCREEN_HALF_W * 4] mov wallDepth, eax mov closestIdx, -1 mov closestDist, 999999 mov i, 0 hitscan_loop: mov eax, i cmp eax, spriteCount jge hitscan_eval mov ecx, i mov eax, [entityType + ecx*4] cmp eax, ENTITY_TYPE_GUARD jne next_hitscan_target mov eax, [entityState + ecx*4] cmp eax, ENTITY_STATE_DEAD je next_hitscan_target mov ebx, i imul ebx, sizeof SpriteStruct add ebx, OFFSET spriteList mov eax, [ebx].SpriteStruct.textureId test eax, eax jz next_hitscan_target ; Transform to camera space mov eax, [ebx].SpriteStruct.x sub eax, playerX mov sprX, eax mov eax, [ebx].SpriteStruct.y sub eax, playerY mov sprY, eax ; transY = sprX * camCos - sprY * camSin mov eax, sprX imul camCos shrd eax, edx, 16 mov ecx, eax mov eax, sprY imul camSin shrd eax, edx, 16 sub ecx, eax mov transY, ecx ; Must be in front of player cmp transY, 16 jle next_hitscan_target ; Must be closer than the wall at center screen mov eax, transY cmp eax, wallDepth jge next_hitscan_target ; transX = sprX * camSin + sprY * camCos mov eax, sprX imul camSin shrd eax, edx, 16 mov ecx, eax mov eax, sprY imul camCos shrd eax, edx, 16 add ecx, eax mov transX, ecx ; sprScreenX = (transX * PROJ_DIST) / transY + SCREEN_HALF_W mov eax, transX imul eax, PROJ_DIST cdq idiv transY add eax, SCREEN_HALF_W mov sprScreenX, eax ; Crosshair hitbox: within 22 pixels of center (SCREEN_HALF_W = 160) sub eax, SCREEN_HALF_W cdq xor eax, edx sub eax, edx ; abs(sprScreenX - 160) cmp eax, 22 jg next_hitscan_target ; Check if closer than previous target mov eax, transY cmp eax, closestDist jge next_hitscan_target mov closestDist, eax mov eax, i mov closestIdx, eax next_hitscan_target: inc i jmp hitscan_loop hitscan_eval: cmp closestIdx, -1 je combat_done ; Apply damage to hit guard mov ecx, closestIdx mov eax, [entityHealth + ecx*4] sub eax, 35 jns @F xor eax, eax @@: mov [entityHealth + ecx*4], eax test eax, eax jnz combat_done ; Guard died! mov [entityState + ecx*4], ENTITY_STATE_DEAD mov DWORD PTR [entityTimer + ecx*4], 0 add playerScore, 100 ; Drop 10 ammo reward mov eax, playerAmmo add eax, 10 cmp eax, playerMaxAmmo jle @F mov eax, playerMaxAmmo @@: mov playerAmmo, eax jmp combat_done combat_dry_fire: mov playerAttackCooldown, 12 combat_done: ret UpdateCombat ENDP ; ------------------------------------------------------------------------------ ; RenderCombatHUD: Renders health bar, ammo, crosshair, weapon & death screen ; ------------------------------------------------------------------------------ RenderCombatHUD PROC uses ebx ecx edx esi edi LOCAL barW:DWORD, gunY:DWORD ; 1. Center Crosshair (subtle cross at 160, 120) invoke DrawRect, 156, 120, 9, 1, 00FFFFFFh invoke DrawRect, 160, 116, 1, 9, 00FFFFFFh invoke DrawRect, 160, 120, 1, 1, 0000FF00h ; 2. Render Retro Weapon at bottom center mov gunY, 192 cmp playerFlashTimer, 0 je draw_gun_barrel ; Recoil offset add gunY, 3 ; Muzzle Flash Burst (Bright yellow & white star) invoke DrawRect, 157, 165, 7, 18, 00FFFF00h invoke DrawRect, 152, 170, 17, 8, 00FFAA00h invoke DrawRect, 158, 168, 5, 12, 00FFFFFFh draw_gun_barrel: ; Weapon barrel & slide invoke DrawRect, 154, gunY, 13, 28, 003A3A3Ah invoke DrawRect, 156, gunY, 9, 28, 00555555h invoke DrawRect, 158, gunY, 5, 28, 00777777h ; highlight strip ; Gun frame & grip mov eax, gunY add eax, 24 invoke DrawRect, 150, eax, 21, 24, 00252525h mov eax, gunY add eax, 26 invoke DrawRect, 152, eax, 17, 22, 00453020h ; brown wood grip plates ; 3. Health Bar invoke DrawString8x8, 8, 42, OFFSET strHpLabel, COLOR_GREEN invoke DrawNumber8x8, 34, 42, playerHealth, COLOR_WHITE invoke DrawRect, 68, 42, 60, 8, 00441010h invoke DrawRectOutline, 68, 42, 60, 8, COLOR_WHITE mov eax, playerHealth imul eax, 58 xor edx, edx mov ecx, playerMaxHealth test ecx, ecx jnz @F mov ecx, 100 @@: div ecx mov barW, eax cmp barW, 0 jle hud_ammo_draw cmp barW, 58 jle @F mov barW, 58 @@: mov edx, 0000CC33h ; Green cmp playerHealth, 30 jg @F mov edx, 00FF2222h ; Red warning @@: invoke DrawRect, 69, 43, barW, 6, edx hud_ammo_draw: ; 4. Ammo Display invoke DrawString8x8, 140, 42, OFFSET strAmmoLabel, COLOR_YELLOW invoke DrawNumber8x8, 182, 42, playerAmmo, COLOR_YELLOW ; 5. Score Display invoke DrawString8x8, 222, 42, OFFSET strScoreLabel, COLOR_CYAN invoke DrawNumber8x8, 272, 42, playerScore, COLOR_CYAN ; 6. Keys (if collected) cmp playerKeys, 0 jle hud_damage_flash invoke DrawString8x8, 222, 10, OFFSET strKeysLabel, COLOR_MAGENTA invoke DrawNumber8x8, 258, 10, playerKeys, COLOR_MAGENTA hud_damage_flash: ; 7. Damage Screen Flash cmp playerHitFlash, 0 jle hud_death_check ; Red border vignette invoke DrawRect, 0, 0, SCREEN_W, 3, 00FF0000h invoke DrawRect, 0, 237, SCREEN_W, 3, 00FF0000h invoke DrawRect, 0, 0, 3, SCREEN_H, 00FF0000h invoke DrawRect, 317, 0, 3, SCREEN_H, 00FF0000h hud_death_check: ; 8. Death Overlay Screen cmp isPlayerDead, 0 je combat_hud_done invoke DrawRect, 20, 95, 280, 50, 00880000h invoke DrawRectOutline, 20, 95, 280, 50, COLOR_WHITE invoke DrawString8x8, 32, 114, OFFSET strYouDied, COLOR_YELLOW combat_hud_done: ret RenderCombatHUD ENDP