EBLAN_ENGINE/include/engine_combat.inc

617 lines
16 KiB
PHP

; ==============================================================================
; EBLAN ENGINE - Player Combat, Multi-Weapon Arsenal & 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
ShowGameToast PROTO :DWORD, :DWORD, :DWORD
Game_OnEntityKilled PROTO :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
LOCAL weaponDamage:DWORD, maxHitDist:DWORD, hitTolerance: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, game is paused, or in peaceful adventure mode, cannot attack
cmp isPlayerDead, 0
jne combat_done
cmp isGamePaused, 0
jne combat_done
cmp gameMode, GAME_MODE_ADVENTURE
je combat_done
cmp enableWeapons, 0
je combat_done
cmp playerWeapon, WEAPON_NONE
je combat_done
; 2. Check attack input
cmp keyAttack, 0
je combat_done
cmp playerAttackCooldown, 0
jne combat_done
; Set weapon parameters based on playerWeapon
mov weaponDamage, 35
mov maxHitDist, 999999
mov hitTolerance, 22
cmp playerWeapon, WEAPON_KNIFE
je setup_knife
cmp playerWeapon, WEAPON_SHOTGUN
je setup_shotgun
jmp setup_pistol
setup_knife:
; Knife: no ammo needed, close range (within 64 units = 1 cell), fast cooldown
mov weaponDamage, 30
mov maxHitDist, 64
mov hitTolerance, 32
mov playerAttackCooldown, 8
mov playerFlashTimer, 3
jmp fire_hitscan
setup_shotgun:
; Shotgun: needs 2 ammo, high damage (70), wide spread (hitTolerance 40), long cooldown
cmp playerAmmo, 2
jl combat_dry_fire
sub playerAmmo, 2
mov weaponDamage, 70
mov maxHitDist, 999999
mov hitTolerance, 40
mov playerAttackCooldown, 22
mov playerFlashTimer, 7
invoke SpawnMuzzleFlashLight, playerX, playerY
jmp fire_hitscan
setup_pistol:
; Pistol: needs 1 ammo, accurate (hitTolerance 22), medium cooldown (12)
cmp playerAmmo, 1
jl combat_dry_fire
dec playerAmmo
mov weaponDamage, 35
mov maxHitDist, 999999
mov hitTolerance, 22
mov playerAttackCooldown, 12
mov playerFlashTimer, 5
invoke SpawnMuzzleFlashLight, playerX, playerY
fire_hitscan:
; 3. Hitscan check against enemies & destructible barrels in 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]
; Check if Guard or Barrel
cmp eax, ENTITY_TYPE_GUARD
je hitscan_target_valid
cmp eax, ENTITY_TYPE_BARREL
je hitscan_target_valid
; Also check if prop has barrel texture (11)
mov ebx, i
imul ebx, sizeof SpriteStruct
add ebx, OFFSET spriteList
mov eax, [ebx].SpriteStruct.textureId
cmp eax, 11
je hitscan_target_valid
jmp next_hitscan_target
hitscan_target_valid:
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 maximum weapon hit distance
mov eax, transY
cmp eax, maxHitDist
jg 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 check
sub eax, SCREEN_HALF_W
cdq
xor eax, edx
sub eax, edx ; abs(sprScreenX - 160)
cmp eax, hitTolerance
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
mov ecx, closestIdx
mov eax, [entityType + ecx*4]
; Check if hit an explosive barrel!
cmp eax, ENTITY_TYPE_BARREL
je explode_barrel
mov ebx, closestIdx
imul ebx, sizeof SpriteStruct
add ebx, OFFSET spriteList
cmp [ebx].SpriteStruct.textureId, 11
je explode_barrel
; Hit an enemy guard!
mov eax, [entityHealth + ecx*4]
sub eax, weaponDamage
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
invoke Game_OnEntityKilled, closestIdx, ENTITY_TYPE_GUARD
; Drop ammo reward
mov eax, playerAmmo
add eax, 10
cmp eax, playerMaxAmmo
jle @F
mov eax, playerMaxAmmo
@@:
mov playerAmmo, eax
jmp combat_done
explode_barrel:
; Exploding Barrel: Destroy barrel and trigger AOE blast!
mov [entityState + ecx*4], ENTITY_STATE_DEAD
mov ebx, closestIdx
imul ebx, sizeof SpriteStruct
add ebx, OFFSET spriteList
mov [ebx].SpriteStruct.textureId, 0 ; disappear
; Fiery orange-red screen flash
mov playerHitFlash, 8
add playerScore, 200
invoke ShowGameToast, OFFSET szBarrelExplodedToast, 60, 00FFA020h
invoke Game_OnEntityKilled, closestIdx, ENTITY_TYPE_BARREL
; AOE damage to all surrounding guards within 128 units (2 cells)
push esi
push edi
mov esi, [ebx].SpriteStruct.x
mov edi, [ebx].SpriteStruct.y
invoke SpawnExplosionLight, esi, edi
mov i, 0
aoe_loop:
mov eax, i
cmp eax, spriteCount
jge aoe_check_player
mov ecx, i
cmp ecx, closestIdx
je next_aoe
mov eax, [entityType + ecx*4]
cmp eax, ENTITY_TYPE_GUARD
jne next_aoe
cmp [entityState + ecx*4], ENTITY_STATE_DEAD
je next_aoe
mov edx, i
imul edx, sizeof SpriteStruct
add edx, OFFSET spriteList
mov eax, [edx].SpriteStruct.x
sub eax, esi
cdq
xor eax, edx
sub eax, edx
cmp eax, 128
jg next_aoe
mov eax, [edx].SpriteStruct.y
sub eax, edi
cdq
xor eax, edx
sub eax, edx
cmp eax, 128
jg next_aoe
; Within blast: deal 60 blast damage!
mov eax, [entityHealth + ecx*4]
sub eax, 60
jns @F
xor eax, eax
@@:
mov [entityHealth + ecx*4], eax
test eax, eax
jnz next_aoe
mov [entityState + ecx*4], ENTITY_STATE_DEAD
add playerScore, 150
next_aoe:
inc i
jmp aoe_loop
aoe_check_player:
; If player was standing too close to the barrel (< 96 units), player takes blast damage!
mov eax, playerX
sub eax, esi
cdq
xor eax, edx
sub eax, edx
cmp eax, 96
jg aoe_done
mov eax, playerY
sub eax, edi
cdq
xor eax, edx
sub eax, edx
cmp eax, 96
jg aoe_done
; Player blast damage
mov eax, playerHealth
sub eax, 25
jns @F
xor eax, eax
@@:
mov playerHealth, eax
test eax, eax
jnz aoe_done
mov isPlayerDead, 1
aoe_done:
pop edi
pop esi
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
; If in adventure mode, unarmed, or weapons disabled, skip weapon & combat stats
cmp gameMode, GAME_MODE_ADVENTURE
je hud_damage_flash
cmp enableWeapons, 0
je hud_damage_flash
cmp playerWeapon, WEAPON_NONE
je hud_damage_flash
; 1. Center Crosshair (subtle cross at 160, 120)
cmp showCrosshair, 0
je skip_crosshair
invoke DrawRect, 156, 120, 9, 1, 00FFFFFFh
invoke DrawRect, 160, 116, 1, 9, 00FFFFFFh
invoke DrawRect, 160, 120, 1, 1, 0000FF00h
skip_crosshair:
; 2. Render Active Weapon at bottom center
cmp playerWeapon, WEAPON_KNIFE
je render_knife_weapon
cmp playerWeapon, WEAPON_SHOTGUN
je render_shotgun_weapon
jmp render_pistol_weapon
render_knife_weapon:
; Knife Combat Animation: thrusts forward when cooldown active
mov gunY, 190
cmp playerFlashTimer, 0
je draw_knife
sub gunY, 12 ; thrust forward!
draw_knife:
; Silver steel blade
invoke DrawRect, 166, gunY, 6, 26, 00D0D0D0h
invoke DrawRect, 168, gunY, 2, 26, 00FFFFFFh ; shine
invoke DrawRect, 167, gunY - 4, 4, 4, 00B0B0B0h ; blade tip
invoke DrawRect, 168, gunY - 7, 2, 3, 00E0E0E0h
; Brass crossguard
mov eax, gunY
add eax, 26
invoke DrawRect, 160, eax, 18, 5, 00D4AF37h
; Wooden grip
mov eax, gunY
add eax, 31
invoke DrawRect, 164, eax, 10, 22, 00502A10h
jmp hud_stats_draw
render_shotgun_weapon:
; Heavy Pump Shotgun
mov gunY, 188
cmp playerFlashTimer, 0
je draw_shotgun_barrels
add gunY, 4 ; heavy recoil!
; Massive dual blast flash!
invoke DrawRect, 146, 155, 28, 22, 00FFAA00h
invoke DrawRect, 150, 158, 20, 16, 00FFFF00h
invoke DrawRect, 154, 162, 12, 10, 00FFFFFFh
draw_shotgun_barrels:
; Twin heavy steel barrels
invoke DrawRect, 148, gunY, 10, 32, 002B2B2Bh
invoke DrawRect, 150, gunY, 6, 32, 00484848h
invoke DrawRect, 162, gunY, 10, 32, 002B2B2Bh
invoke DrawRect, 164, gunY, 6, 32, 00484848h
; Barrel rib connector
invoke DrawRect, 158, gunY, 4, 32, 00222222h
; Wooden pump forend
mov eax, gunY
add eax, 20
invoke DrawRect, 144, eax, 32, 18, 00603818h
invoke DrawRect, 146, eax, 28, 14, 007A4820h
jmp hud_stats_draw
render_pistol_weapon:
mov gunY, 192
cmp playerFlashTimer, 0
je draw_pistol_barrel
add gunY, 3 ; recoil offset
; 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_pistol_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
hud_stats_draw:
; 3. Health Bar at top-left: X=8, Y=8
invoke DrawString8x8, 8, 8, OFFSET strHpLabel, COLOR_GREEN
invoke DrawNumber8x8, 34, 8, playerHealth, COLOR_WHITE
invoke DrawRect, 66, 8, 50, 8, 00441010h
invoke DrawRectOutline, 66, 8, 50, 8, COLOR_WHITE
mov eax, playerHealth
imul eax, 48
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, 48
jle @F
mov barW, 48
@@:
mov edx, 0000CC33h ; Green
cmp playerHealth, 30
jg @F
mov edx, 00FF2222h ; Red warning
@@:
invoke DrawRect, 67, 9, barW, 6, edx
hud_ammo_draw:
; 4. Ammo Display: X=126, Y=8
invoke DrawString8x8, 126, 8, OFFSET strAmmoLabel, COLOR_YELLOW
invoke DrawNumber8x8, 168, 8, playerAmmo, COLOR_YELLOW
; 5. Keys: X=204, Y=8 (if collected)
cmp playerKeys, 0
jle hud_score_draw
invoke DrawString8x8, 204, 8, OFFSET strKeysLabel, COLOR_MAGENTA
invoke DrawNumber8x8, 238, 8, playerKeys, COLOR_MAGENTA
hud_score_draw:
; 6. Score Display: only in Debug HUD style
cmp hudStyle, HUD_STYLE_CLEAN
je draw_weapon_badge
invoke DrawString8x8, 8, 20, OFFSET strScoreLabel, COLOR_CYAN
invoke DrawNumber8x8, 58, 20, playerScore, COLOR_CYAN
draw_weapon_badge:
; 7. Active Weapon Badge at bottom-right corner: X=228, Y=222
invoke DrawRect, 228, 222, 88, 14, 00141414h
invoke DrawRectOutline, 228, 222, 88, 14, 00444444h
cmp playerWeapon, WEAPON_KNIFE
jne @F
invoke DrawString8x8, 233, 225, OFFSET strWeaponKnife, COLOR_CYAN
jmp draw_weapon_slots
@@:
cmp playerWeapon, WEAPON_SHOTGUN
jne @F
invoke DrawString8x8, 233, 225, OFFSET strWeaponShotgun, 00FFAA00h
jmp draw_weapon_slots
@@:
invoke DrawString8x8, 233, 225, OFFSET strWeaponPistol, COLOR_YELLOW
draw_weapon_slots:
; Draw small weapon slot indicator boxes: [1] [2] [3]
invoke DrawRectOutline, 287, 225, 6, 8, 00555555h
invoke DrawRectOutline, 295, 225, 6, 8, 00555555h
invoke DrawRectOutline, 303, 225, 6, 8, 00555555h
; Highlight active slot
mov eax, playerWeapon
imul eax, 8
add eax, 287
invoke DrawRectOutline, eax, 225, 6, 8, COLOR_YELLOW
hud_damage_flash:
; 8. 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:
; 9. 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
; ------------------------------------------------------------------------------
; RenderPauseMenu: Renders stylish retro pause overlay when isGamePaused != 0
; ------------------------------------------------------------------------------
RenderPauseMenu PROC uses ebx ecx edx
cmp isGamePaused, 0
je pause_menu_done
; Centered semi-transparent panel 220x112 at (50, 64)
invoke DrawRect, 50, 64, 220, 112, 00141416h
invoke DrawRectOutline, 50, 64, 220, 112, COLOR_CYAN
invoke DrawRectOutline, 52, 66, 216, 108, COLOR_WHITE
; Header
invoke DrawString8x8, 112, 72, OFFSET strPauseTitle, COLOR_YELLOW
; Menu Options
invoke DrawString8x8, 64, 88, OFFSET strPauseOpt1, COLOR_GREEN
invoke DrawString8x8, 64, 102, OFFSET strPauseOpt2, COLOR_WHITE
invoke DrawString8x8, 64, 116, OFFSET strPauseOpt3, COLOR_CYAN
invoke DrawString8x8, 64, 130, OFFSET strPauseOpt4, COLOR_YELLOW
invoke DrawString8x8, 64, 146, OFFSET strPauseOpt5, 00FF4444h
pause_menu_done:
ret
RenderPauseMenu ENDP