EBLAN_ENGINE/include/engine_combat.inc

303 lines
7.5 KiB
PHP

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