KAZIK/src_graphics/hell_fps_render.inc
Игорь Федосеев ce5121debd feat: add native hell expedition
Add a painting entrance, Freedoom combat and Doom-style HUD.

Persist the one-time clear reward in signed saves without changing file sizes. Include native regression checks and synchronized game/launcher builds.
2026-11-01 22:29:09 +03:00

348 lines
8.5 KiB
PHP

; World sprites share casino depth testing. HUD uses native 640x480 pixels.
HFText PROC uses esi edi ebx x:DWORD,y:DWORD,text:DWORD,color:DWORD
local row:DWORD,column:DWORD,cursor:DWORD,bits:DWORD
mov esi,text
mov eax,x
mov cursor,eax
hf_text_char:
movzx eax,BYTE PTR [esi]
test eax,eax
jz hf_text_done
lea edi,font8x8[eax*8]
mov row,0
hf_text_row:
mov eax,row
movzx eax,BYTE PTR [edi+eax]
mov bits,eax
mov column,0
hf_text_pixel:
test bits,80h
jz hf_text_next_pixel
mov eax,y
add eax,row
cmp eax,480
jae hf_text_next_pixel
mov ebx,cursor
add ebx,column
cmp ebx,640
jae hf_text_next_pixel
imul eax,640
add eax,ebx
mov ebx,color
mov screenBuffer[eax*4],ebx
hf_text_next_pixel:
shl bits,1
inc column
cmp column,8
jb hf_text_pixel
inc row
cmp row,8
jb hf_text_row
add cursor,8
inc esi
jmp hf_text_char
hf_text_done:
ret
HFText ENDP
HFNumber PROC x:DWORD,y:DWORD,value:DWORD
invoke FormatNumber,value,OFFSET hfNumber
invoke HFText,x,y,OFFSET hfNumber,00FFE0A0h
ret
HFNumber ENDP
HFLargeNumber PROC uses ebx edi rightEdge:DWORD,y:DWORD,value:DWORD,percent:DWORD
mov ebx,value
mov edi,rightEdge
cmp percent,0
je hf_large_digit
sub edi,28
invoke DrawAnimSprite3D,OFFSET hfDigitsArt,10,edi,y,32,32
hf_large_digit:
mov eax,ebx
xor edx,edx
mov ecx,10
div ecx
mov ebx,eax
sub edi,28
invoke DrawAnimSprite3D,OFFSET hfDigitsArt,edx,edi,y,32,32
test ebx,ebx
jnz hf_large_digit
ret
HFLargeNumber ENDP
HFRenderStatus PROC uses ebx
invoke DrawAnimSprite3D,OFFSET hfHUDArt,0,0,416,640,64
mov eax,hfBullets
cmp hfWeapon,0
je @F
mov eax,hfShells
@@:
invoke HFLargeNumber,86,422,eax,0
invoke HFLargeNumber,208,422,hfHealth,1
invoke HFLargeNumber,466,422,hfArmor,1
; Replace multiplayer FRAGS field with the owned weapon slots.
invoke DrawBox,108,209,35,31,003C3B36h
invoke HFText,228,460,OFFSET hfArmsText,00B0ACA0h
mov eax,00777770h
cmp hfWeapon,0
jne @F
mov eax,00FFE070h
@@:
invoke HFText,230,434,OFFSET hfSlot1Text,eax
cmp hfHasShotgun,0
je hf_status_face
mov eax,00777770h
cmp hfWeapon,1
jne @F
mov eax,00FFE070h
@@:
invoke HFText,258,434,OFFSET hfSlot2Text,eax
hf_status_face:
mov eax,100
sub eax,hfHealth
xor edx,edx
mov ecx,20
div ecx
cmp eax,4
jbe @F
mov eax,4
@@:
shl eax,2
mov ebx,eax
cmp hfHurt,0
je hf_face_idle
add ebx,3
jmp hf_face_draw
hf_face_idle:
mov eax,hfTicks
shr eax,5
xor edx,edx
mov ecx,3
div ecx
add ebx,edx
hf_face_draw:
cmp hfState,1
jne @F
mov ebx,20
@@:
invoke DrawAnimSprite3D,OFFSET hfFacesArt,ebx,296,416,48,64
cmp hfKey,0
je @F
invoke DrawAnimSprite3D,OFFSET hfItemsArt,5,476,420,28,28
@@:
; Clear original ammo glyphs, then draw live reserve counts.
invoke DrawBox,257,209,62,30,002E302Ch
invoke HFText,518,420,OFFSET hfAmmoTypesText,00B0ACA0h
invoke HFNumber,558,420,hfBullets
invoke HFText,590,420,OFFSET hfMaxBulletsText,008E8C80h
invoke HFText,518,434,OFFSET hfShellTypeText,00B0ACA0h
invoke HFNumber,558,434,hfShells
invoke HFText,590,434,OFFSET hfMaxShellsText,008E8C80h
invoke HFText,518,448,OFFSET hfEmptyAmmoText,008E8C80h
invoke HFText,518,462,OFFSET hfEmptyCellText,008E8C80h
ret
HFRenderStatus ENDP
RenderHellPortal3D PROC
cmp hallLevel3D,0
jne hf_portal_done
invoke LoadAnimPack3D,OFFSET hfPaintingArt,OFFSET hfPaintingPath
cmp hfPaintingArt.pixels,0
je hf_portal_done
; Gilt landscape hung flat on the south wall opposite the bar.
invoke DrawCityVertical3D,1,HF_PORTAL_Y,3*FP_1,9*FP_1,FP_1*35/100,FP_1*235/100,HF_PAINTING_MATERIAL
hf_portal_done:
ret
RenderHellPortal3D ENDP
RenderHellFPS3D PROC uses esi edi ebx
call UpdateCamera3D
call RenderCeilingAndFloor
call RenderWalls
call PrepareCityDepth3D
; Animated lava patch, same bounds as HFTick damage.
mov eax,hfTicks
shr eax,3
and eax,3
add eax,HF_LAVA
invoke DrawCityHorizontal3D,16*FP_1,18*FP_1,17*FP_1,20*FP_1,128,eax
mov esi,OFFSET hfEnemies
mov edi,HF_ENEMIES
hf_render_enemy:
mov eax,[esi].HFEnemy.x
mov hfObject.posX,eax
mov eax,[esi].HFEnemy.y
mov hfObject.posY,eax
mov eax,[esi].HFEnemy.kind
mov eax,hfMonsterPacks[eax*4]
mov hfObject.asset,eax
mov eax,[esi].HFEnemy.pose
mov hfObject.frame,eax
mov hfObject.worldW,FP_1*6/5
mov hfObject.worldH,FP_1*3/2
mov hfObject.groundZ,0
cmp [esi].HFEnemy.kind,3
jne @F
mov hfObject.worldW,FP_1*9/5
mov hfObject.worldH,FP_1*22/10
@@:
invoke DrawCityObject3D,OFFSET hfObject,0
add esi,SIZEOF HFEnemy
dec edi
jnz hf_render_enemy
mov hfObject.asset,OFFSET hfItemsArt
mov hfObject.worldW,FP_1/2
mov hfObject.worldH,FP_1/2
mov hfObject.groundZ,0
xor edi,edi
mov esi,OFFSET hfItemSeeds
hf_render_item:
cmp hfItemTaken[edi*4],0
jne hf_render_item_next
mov eax,[esi]
mov hfObject.posX,eax
mov eax,[esi+4]
mov hfObject.posY,eax
mov eax,[esi+8]
mov hfObject.frame,eax
invoke DrawCityObject3D,OFFSET hfObject,0
hf_render_item_next:
add esi,12
inc edi
cmp edi,HF_ITEMS
jb hf_render_item
mov hfObject.asset,OFFSET hfFireArt
mov hfObject.worldW,FP_1/3
mov hfObject.worldH,FP_1/3
mov hfObject.groundZ,FP_1*3/4
mov eax,hfTicks
shr eax,2
and eax,1
mov hfObject.frame,eax
mov esi,OFFSET hfBolts
mov edi,32
hf_render_bolt:
cmp [esi].HFBolt.life,0
je hf_render_bolt_next
mov eax,[esi].HFBolt.x
mov hfObject.posX,eax
mov eax,[esi].HFBolt.y
mov hfObject.posY,eax
invoke DrawCityObject3D,OFFSET hfObject,0
hf_render_bolt_next:
add esi,SIZEOF HFBolt
dec edi
jnz hf_render_bolt
mov hfObject.asset,OFFSET hfImpactsArt
mov hfObject.worldW,FP_1/3
mov hfObject.worldH,FP_1/3
mov hfObject.groundZ,FP_1*5/6
mov esi,OFFSET hfImpacts
mov edi,HF_SHOT_PELLETS
hf_render_impact:
cmp [esi].HFImpact.life,0
je hf_render_impact_next
mov eax,[esi].HFImpact.x
mov hfObject.posX,eax
mov eax,[esi].HFImpact.y
mov hfObject.posY,eax
mov eax,8
sub eax,[esi].HFImpact.life
shr eax,1
mov hfObject.frame,eax
invoke DrawCityObject3D,OFFSET hfObject,0
hf_render_impact_next:
add esi,SIZEOF HFImpact
dec edi
jnz hf_render_impact
mov hfObject.asset,OFFSET hfPortalArt
mov hfObject.posX,28*FP_1
mov hfObject.posY,29*FP_1
mov hfObject.worldW,FP_1*3/2
mov hfObject.worldH,2*FP_1
mov hfObject.groundZ,0
mov eax,hfTicks
shr eax,2
and eax,7
mov hfObject.frame,eax
invoke DrawCityObject3D,OFFSET hfObject,0
cmp hfState,0
jne hf_render_hud
mov esi,OFFSET hfPistol
mov edi,0
cmp hfWeapon,1
jne hf_weapon_pose
mov esi,OFFSET hfShotgun
hf_weapon_pose:
cmp hfCooldown,0
je hf_weapon_draw
cmp hfWeapon,0
jne hf_shotgun_pose
; Four recovery poses over the nine-tick pistol cycle.
mov eax,9
sub eax,hfCooldown
shr eax,1
inc eax
cmp eax,4
jbe @F
mov eax,4
@@:
mov edi,eax
jmp hf_weapon_draw
hf_shotgun_pose:
mov edi,3
cmp hfCooldown,10
jbe hf_weapon_draw
mov edi,2
cmp hfCooldown,18
jbe hf_weapon_draw
mov edi,1
hf_weapon_draw:
invoke DrawAnimSprite3D,esi,edi,176,176,288,240
cmp hfFlash,0
je @F
invoke DrawAnimSprite3D,OFFSET hfFireArt,0,296,202,48,48
@@:
invoke DrawBox,159,117,2,7,00D0C0A0h
invoke DrawBox,156,120,8,1,00D0C0A0h
hf_render_hud:
cmp hfHurt,0
je @F
invoke DrawBox,0,0,320,3,00902010h
invoke DrawBox,0,0,3,210,00902010h
invoke DrawBox,317,0,3,210,00902010h
@@:
call HFRenderStatus
cmp hfMessageTime,0
je @F
invoke HFText,12,34,hfMessage,00FFD090h
@@:
cmp hfState,0
je hf_render_done
invoke DrawBox,24,80,272,65,00181010h
mov eax,OFFSET hfDeadText
cmp hfState,1
je @F
mov eax,OFFSET hfWinText
@@:
invoke HFText,64,176,eax,00FFB070h
invoke HFText,64,208,OFFSET hfStatsText,00C0A080h
mov eax,hfTicks
xor edx,edx
mov ecx,35
div ecx
invoke HFNumber,80,226,eax
invoke HFNumber,232,226,hfKills
invoke HFNumber,392,226,hfSecrets
cmp hfState,2
jne hf_render_done
mov eax,OFFSET hfRepeatText
cmp hfAwarded,0
je @F
mov eax,OFFSET hfRewardText
@@:
invoke HFText,144,258,eax,00FFE0A0h
hf_render_done:
ret
RenderHellFPS3D ENDP