mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-24 21:11:52 +00:00
- sync 3D floor branch with trunk.
SVN r3094 (3dfloors2)
This commit is contained in:
parent
652558577c
commit
f511e29278
65 changed files with 3577 additions and 924 deletions
|
@ -658,6 +658,7 @@ add_executable( zdoom WIN32
|
||||||
m_misc.cpp
|
m_misc.cpp
|
||||||
m_png.cpp
|
m_png.cpp
|
||||||
m_random.cpp
|
m_random.cpp
|
||||||
|
memarena.cpp
|
||||||
md5.cpp
|
md5.cpp
|
||||||
name.cpp
|
name.cpp
|
||||||
nodebuild.cpp
|
nodebuild.cpp
|
||||||
|
|
|
@ -28,6 +28,9 @@
|
||||||
%define setupmvlineasm _setupmvlineasm
|
%define setupmvlineasm _setupmvlineasm
|
||||||
%define mvlineasm1 _mvlineasm1
|
%define mvlineasm1 _mvlineasm1
|
||||||
%define mvlineasm4 _mvlineasm4
|
%define mvlineasm4 _mvlineasm4
|
||||||
|
|
||||||
|
%define R_SetupDrawSlab _R_SetupDrawSlab
|
||||||
|
%define R_DrawSlab _R_DrawSlab
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
EXTERN ylookup ; near
|
EXTERN ylookup ; near
|
||||||
|
@ -44,9 +47,6 @@ EXTERN dc_dest
|
||||||
EXTERN dc_source
|
EXTERN dc_source
|
||||||
EXTERN dc_texturefrac
|
EXTERN dc_texturefrac
|
||||||
|
|
||||||
mvlineasm4_counter:
|
|
||||||
dd 0
|
|
||||||
|
|
||||||
SECTION .text
|
SECTION .text
|
||||||
|
|
||||||
ALIGN 16
|
ALIGN 16
|
||||||
|
@ -59,8 +59,45 @@ setvlinebpl_:
|
||||||
mov [fixchain2ma+2], eax
|
mov [fixchain2ma+2], eax
|
||||||
mov [fixchain2mb+2], eax
|
mov [fixchain2mb+2], eax
|
||||||
selfmod fixchain1a, fixchain2mb+6
|
selfmod fixchain1a, fixchain2mb+6
|
||||||
|
|
||||||
|
setdrawslabbpl:
|
||||||
|
mov dword [voxbpl1+2], eax
|
||||||
|
mov dword [voxbpl2+2], eax
|
||||||
|
mov dword [voxbpl3+2], eax
|
||||||
|
mov dword [voxbpl4+2], eax
|
||||||
|
mov dword [voxbpl5+2], eax
|
||||||
|
mov dword [voxbpl6+2], eax
|
||||||
|
mov dword [voxbpl7+2], eax
|
||||||
|
mov dword [voxbpl8+2], eax
|
||||||
|
selfmod voxbpl1, voxpl8+6
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
SECTION .data
|
||||||
|
|
||||||
|
lastslabcolormap:
|
||||||
|
dd 4
|
||||||
|
|
||||||
|
SECTION .text
|
||||||
|
|
||||||
|
GLOBAL R_SetupDrawSlab
|
||||||
|
GLOBAL @R_SetupDrawSlab@4
|
||||||
|
R_SetupDrawSlab:
|
||||||
|
mov ecx, [esp+4]
|
||||||
|
@R_SetupDrawSlab@4:
|
||||||
|
cmp [lastslabcolormap], ecx
|
||||||
|
je .done
|
||||||
|
mov [lastslabcolormap], ecx
|
||||||
|
mov dword [voxpal1+2], ecx
|
||||||
|
mov dword [voxpal2+2], ecx
|
||||||
|
mov dword [voxpal3+2], ecx
|
||||||
|
mov dword [voxpal4+2], ecx
|
||||||
|
mov dword [voxpal5+2], ecx
|
||||||
|
mov dword [voxpal6+2], ecx
|
||||||
|
mov dword [voxpal7+2], ecx
|
||||||
|
mov dword [voxpal8+2], ecx
|
||||||
|
.done ret
|
||||||
|
|
||||||
|
|
||||||
; pass it log2(texheight)
|
; pass it log2(texheight)
|
||||||
|
|
||||||
ALIGN 16
|
ALIGN 16
|
||||||
|
@ -549,6 +586,226 @@ mvcase0: jmp beginmvlineasm4
|
||||||
|
|
||||||
align 16
|
align 16
|
||||||
|
|
||||||
|
|
||||||
|
;*************************************************************************
|
||||||
|
;***************************** Voxel Slabs *******************************
|
||||||
|
;*************************************************************************
|
||||||
|
|
||||||
|
GLOBAL R_DrawSlab
|
||||||
|
R_DrawSlab:
|
||||||
|
push ebx
|
||||||
|
push ebp
|
||||||
|
push esi
|
||||||
|
push edi
|
||||||
|
|
||||||
|
mov eax, [esp+5*4+0]
|
||||||
|
mov ebx, [esp+5*4+4]
|
||||||
|
mov ecx, [esp+5*4+8]
|
||||||
|
mov edx, [esp+5*4+12]
|
||||||
|
mov esi, [esp+5*4+16]
|
||||||
|
mov edi, [esp+5*4+20]
|
||||||
|
|
||||||
|
cmp eax, 2
|
||||||
|
je voxbegdraw2
|
||||||
|
ja voxskip2
|
||||||
|
xor eax, eax
|
||||||
|
voxbegdraw1:
|
||||||
|
mov ebp, ebx
|
||||||
|
shr ebp, 16
|
||||||
|
add ebx, edx
|
||||||
|
dec ecx
|
||||||
|
mov al, byte [esi+ebp]
|
||||||
|
voxpal1: mov al, byte [eax+88888888h]
|
||||||
|
mov byte [edi], al
|
||||||
|
voxbpl1: lea edi, [edi+88888888h]
|
||||||
|
jnz voxbegdraw1
|
||||||
|
jmp voxskipslab5
|
||||||
|
|
||||||
|
voxbegdraw2:
|
||||||
|
mov ebp, ebx
|
||||||
|
shr ebp, 16
|
||||||
|
add ebx, edx
|
||||||
|
xor eax, eax
|
||||||
|
dec ecx
|
||||||
|
mov al, byte [esi+ebp]
|
||||||
|
voxpal2: mov al, byte [eax+88888888h]
|
||||||
|
mov ah, al
|
||||||
|
mov word [edi], ax
|
||||||
|
voxbpl2: lea edi, [edi+88888888h]
|
||||||
|
jnz voxbegdraw2
|
||||||
|
jmp voxskipslab5
|
||||||
|
|
||||||
|
voxskip2:
|
||||||
|
cmp eax, 4
|
||||||
|
jne voxskip4
|
||||||
|
xor eax, eax
|
||||||
|
voxbegdraw4:
|
||||||
|
mov ebp, ebx
|
||||||
|
add ebx, edx
|
||||||
|
shr ebp, 16
|
||||||
|
xor eax, eax
|
||||||
|
mov al, byte [esi+ebp]
|
||||||
|
voxpal3: mov al, byte [eax+88888888h]
|
||||||
|
mov ah, al
|
||||||
|
shl eax, 8
|
||||||
|
mov al, ah
|
||||||
|
shl eax, 8
|
||||||
|
mov al, ah
|
||||||
|
mov dword [edi], eax
|
||||||
|
voxbpl3: add edi, 88888888h
|
||||||
|
dec ecx
|
||||||
|
jnz voxbegdraw4
|
||||||
|
jmp voxskipslab5
|
||||||
|
|
||||||
|
voxskip4:
|
||||||
|
add eax, edi
|
||||||
|
|
||||||
|
test edi, 1
|
||||||
|
jz voxskipslab1
|
||||||
|
cmp edi, eax
|
||||||
|
je voxskipslab1
|
||||||
|
|
||||||
|
push eax
|
||||||
|
push ebx
|
||||||
|
push ecx
|
||||||
|
push edi
|
||||||
|
voxbegslab1:
|
||||||
|
mov ebp, ebx
|
||||||
|
add ebx, edx
|
||||||
|
shr ebp, 16
|
||||||
|
xor eax, eax
|
||||||
|
mov al, byte [esi+ebp]
|
||||||
|
voxpal4: mov al, byte [eax+88888888h]
|
||||||
|
mov byte [edi], al
|
||||||
|
voxbpl4: add edi, 88888888h
|
||||||
|
dec ecx
|
||||||
|
jnz voxbegslab1
|
||||||
|
pop edi
|
||||||
|
pop ecx
|
||||||
|
pop ebx
|
||||||
|
pop eax
|
||||||
|
inc edi
|
||||||
|
|
||||||
|
voxskipslab1:
|
||||||
|
push eax
|
||||||
|
test edi, 2
|
||||||
|
jz voxskipslab2
|
||||||
|
dec eax
|
||||||
|
cmp edi, eax
|
||||||
|
jge voxskipslab2
|
||||||
|
|
||||||
|
push ebx
|
||||||
|
push ecx
|
||||||
|
push edi
|
||||||
|
voxbegslab2:
|
||||||
|
mov ebp, ebx
|
||||||
|
add ebx, edx
|
||||||
|
shr ebp, 16
|
||||||
|
xor eax, eax
|
||||||
|
mov al, byte [esi+ebp]
|
||||||
|
voxpal5: mov al, byte [eax+88888888h]
|
||||||
|
mov ah, al
|
||||||
|
mov word [edi], ax
|
||||||
|
voxbpl5: add edi, 88888888h
|
||||||
|
dec ecx
|
||||||
|
jnz voxbegslab2
|
||||||
|
pop edi
|
||||||
|
pop ecx
|
||||||
|
pop ebx
|
||||||
|
add edi, 2
|
||||||
|
|
||||||
|
voxskipslab2:
|
||||||
|
mov eax, [esp]
|
||||||
|
|
||||||
|
sub eax, 3
|
||||||
|
cmp edi, eax
|
||||||
|
jge voxskipslab3
|
||||||
|
|
||||||
|
voxprebegslab3:
|
||||||
|
push ebx
|
||||||
|
push ecx
|
||||||
|
push edi
|
||||||
|
voxbegslab3:
|
||||||
|
mov ebp, ebx
|
||||||
|
add ebx, edx
|
||||||
|
shr ebp, 16
|
||||||
|
xor eax, eax
|
||||||
|
mov al, byte [esi+ebp]
|
||||||
|
voxpal6: mov al, byte [eax+88888888h]
|
||||||
|
mov ah, al
|
||||||
|
shl eax, 8
|
||||||
|
mov al, ah
|
||||||
|
shl eax, 8
|
||||||
|
mov al, ah
|
||||||
|
mov dword [edi], eax
|
||||||
|
voxbpl6: add edi, 88888888h
|
||||||
|
dec ecx
|
||||||
|
jnz voxbegslab3
|
||||||
|
pop edi
|
||||||
|
pop ecx
|
||||||
|
pop ebx
|
||||||
|
add edi, 4
|
||||||
|
|
||||||
|
mov eax, [esp]
|
||||||
|
|
||||||
|
sub eax, 3
|
||||||
|
cmp edi, eax
|
||||||
|
jl voxprebegslab3
|
||||||
|
|
||||||
|
voxskipslab3:
|
||||||
|
mov eax, [esp]
|
||||||
|
|
||||||
|
dec eax
|
||||||
|
cmp edi, eax
|
||||||
|
jge voxskipslab4
|
||||||
|
|
||||||
|
push ebx
|
||||||
|
push ecx
|
||||||
|
push edi
|
||||||
|
voxbegslab4:
|
||||||
|
mov ebp, ebx
|
||||||
|
add ebx, edx
|
||||||
|
shr ebp, 16
|
||||||
|
xor eax, eax
|
||||||
|
mov al, byte [esi+ebp]
|
||||||
|
voxpal7: mov al, byte [eax+88888888h]
|
||||||
|
mov ah, al
|
||||||
|
mov word [edi], ax
|
||||||
|
voxbpl7: add edi, 88888888h
|
||||||
|
dec ecx
|
||||||
|
jnz voxbegslab4
|
||||||
|
pop edi
|
||||||
|
pop ecx
|
||||||
|
pop ebx
|
||||||
|
add edi, 2
|
||||||
|
|
||||||
|
voxskipslab4:
|
||||||
|
pop eax
|
||||||
|
|
||||||
|
cmp edi, eax
|
||||||
|
je voxskipslab5
|
||||||
|
|
||||||
|
voxbegslab5:
|
||||||
|
mov ebp, ebx
|
||||||
|
add ebx, edx
|
||||||
|
shr ebp, 16
|
||||||
|
xor eax, eax
|
||||||
|
mov al, byte [esi+ebp]
|
||||||
|
voxpal8: mov al, byte [eax+88888888h]
|
||||||
|
mov byte [edi], al
|
||||||
|
voxbpl8: add edi, 88888888h
|
||||||
|
dec ecx
|
||||||
|
jnz voxbegslab5
|
||||||
|
|
||||||
|
voxskipslab5:
|
||||||
|
pop edi
|
||||||
|
pop esi
|
||||||
|
pop ebp
|
||||||
|
pop ebx
|
||||||
|
ret
|
||||||
|
|
||||||
|
align 16
|
||||||
|
|
||||||
%ifdef M_TARGET_MACHO
|
%ifdef M_TARGET_MACHO
|
||||||
GLOBAL _rtext_a_end
|
GLOBAL _rtext_a_end
|
||||||
_rtext_a_end:
|
_rtext_a_end:
|
||||||
|
|
|
@ -342,13 +342,13 @@ dsy3: shr ebp,26
|
||||||
mov edx,[ds_ystep]
|
mov edx,[ds_ystep]
|
||||||
mov ecx,[ds_xfrac]
|
mov ecx,[ds_xfrac]
|
||||||
dsy4: shr ecx,26
|
dsy4: shr ecx,26
|
||||||
dsm8: and edx,0xffffffc0
|
dsm8: and edx,strict dword 0xffffffc0
|
||||||
or ebp,edx
|
or ebp,edx
|
||||||
mov [esp+4],ebp
|
mov [esp+4],ebp
|
||||||
mov ebp,[ds_yfrac]
|
mov ebp,[ds_yfrac]
|
||||||
mov edx,[ds_xfrac]
|
mov edx,[ds_xfrac]
|
||||||
dsy2: shl edx,6
|
dsy2: shl edx,6
|
||||||
dsm9: and ebp,0xffffffc0
|
dsm9: and ebp,strict dword 0xffffffc0
|
||||||
or ecx,ebp
|
or ecx,ebp
|
||||||
shr esi,1
|
shr esi,1
|
||||||
jnc dseven1
|
jnc dseven1
|
||||||
|
@ -485,13 +485,13 @@ dmsy3: shr ebp,26
|
||||||
mov edx,[ds_ystep]
|
mov edx,[ds_ystep]
|
||||||
mov ecx,[ds_xfrac]
|
mov ecx,[ds_xfrac]
|
||||||
dmsy4: shr ecx,26
|
dmsy4: shr ecx,26
|
||||||
dmsm8: and edx,0xffffffc0
|
dmsm8: and edx,strict dword 0xffffffc0
|
||||||
or ebp,edx
|
or ebp,edx
|
||||||
mov [esp+4],ebp
|
mov [esp+4],ebp
|
||||||
mov ebp,[ds_yfrac]
|
mov ebp,[ds_yfrac]
|
||||||
mov edx,[ds_xfrac]
|
mov edx,[ds_xfrac]
|
||||||
dmsy2: shl edx,6
|
dmsy2: shl edx,6
|
||||||
dmsm9: and ebp,0xffffffc0
|
dmsm9: and ebp,strict dword 0xffffffc0
|
||||||
or ecx,ebp
|
or ecx,ebp
|
||||||
shr esi,1
|
shr esi,1
|
||||||
jnc dmseven1
|
jnc dmseven1
|
||||||
|
@ -850,8 +850,8 @@ GLOBAL R_DrawColumnHorizP_ASM
|
||||||
align 16
|
align 16
|
||||||
|
|
||||||
@R_DrawColumnHorizP_ASM@0:
|
@R_DrawColumnHorizP_ASM@0:
|
||||||
R_DrawColumnHorizP_ASM:
|
|
||||||
_R_DrawColumnHorizP_ASM:
|
_R_DrawColumnHorizP_ASM:
|
||||||
|
R_DrawColumnHorizP_ASM:
|
||||||
|
|
||||||
; count = dc_yh - dc_yl;
|
; count = dc_yh - dc_yl;
|
||||||
|
|
||||||
|
@ -870,8 +870,10 @@ _R_DrawColumnHorizP_ASM:
|
||||||
inc eax ; make 0 count mean 0 pixels
|
inc eax ; make 0 count mean 0 pixels
|
||||||
and edx,3
|
and edx,3
|
||||||
push eax
|
push eax
|
||||||
mov esi,[dc_ctspan+edx*4]
|
mov eax,[dc_temp]
|
||||||
lea eax,[dc_temp+ecx*4+edx] ; eax = top of column in buffer
|
mov esi,[dc_ctspan+edx*4]
|
||||||
|
add eax,edx
|
||||||
|
lea eax,[eax+ecx*4] ; eax = top of column in buffer
|
||||||
mov ebp,[dc_yh]
|
mov ebp,[dc_yh]
|
||||||
mov [esi],ecx
|
mov [esi],ecx
|
||||||
mov [esi+4],ebp
|
mov [esi+4],ebp
|
||||||
|
@ -1102,8 +1104,9 @@ _rt_copy1col_asm:
|
||||||
lea esi,[eax*4]
|
lea esi,[eax*4]
|
||||||
inc ebx ; ebx = count
|
inc ebx ; ebx = count
|
||||||
mov eax,edx
|
mov eax,edx
|
||||||
lea ecx,[dc_temp+ecx+esi] ; ecx = source
|
add ecx,esi
|
||||||
mov edi,[ylookup+esi]
|
mov edi,[ylookup+esi]
|
||||||
|
add ecx,[dc_temp] ; ecx = source
|
||||||
mov esi,[dc_pitch] ; esi = pitch
|
mov esi,[dc_pitch] ; esi = pitch
|
||||||
add eax,edi ; eax = dest
|
add eax,edi ; eax = dest
|
||||||
add eax,[dc_destorg]
|
add eax,[dc_destorg]
|
||||||
|
@ -1169,10 +1172,11 @@ _rt_copy4cols_asm:
|
||||||
inc ebx ; ebx = count
|
inc ebx ; ebx = count
|
||||||
mov eax,ecx
|
mov eax,ecx
|
||||||
mov esi,[ylookup+edx*4]
|
mov esi,[ylookup+edx*4]
|
||||||
lea ecx,[dc_temp+edx*4] ; ecx = source
|
mov ecx,[dc_temp]
|
||||||
mov edx,[dc_pitch] ; edx = pitch
|
|
||||||
add eax,esi ; eax = dest
|
add eax,esi ; eax = dest
|
||||||
add eax,[dc_destorg]
|
add eax,[dc_destorg]
|
||||||
|
lea ecx,[ecx+edx*4] ; ecx = source
|
||||||
|
mov edx,[dc_pitch] ; edx = pitch
|
||||||
|
|
||||||
shr ebx,1
|
shr ebx,1
|
||||||
jnc .even
|
jnc .even
|
||||||
|
@ -1241,7 +1245,8 @@ _rt_map1col_asm:
|
||||||
mov esi,[dc_colormap] ; esi = colormap
|
mov esi,[dc_colormap] ; esi = colormap
|
||||||
inc ebx ; ebx = count
|
inc ebx ; ebx = count
|
||||||
mov eax,edx
|
mov eax,edx
|
||||||
lea ebp,[dc_temp+ecx+edi] ; ebp = source
|
lea ebp,[ecx+edi] ; ebp = source
|
||||||
|
add ebp,[dc_temp]
|
||||||
mov ecx,[ylookup+edi]
|
mov ecx,[ylookup+edi]
|
||||||
mov edi,[dc_pitch] ; edi = pitch
|
mov edi,[dc_pitch] ; edi = pitch
|
||||||
add eax,ecx ; eax = dest
|
add eax,ecx ; eax = dest
|
||||||
|
@ -1320,7 +1325,8 @@ _rt_map4cols_asm1:
|
||||||
mov eax,ecx
|
mov eax,ecx
|
||||||
inc ebx ; ebx = count
|
inc ebx ; ebx = count
|
||||||
mov edi,[ylookup+edx]
|
mov edi,[ylookup+edx]
|
||||||
lea ebp,[dc_temp+edx] ; ebp = source
|
mov ebp,[dc_temp]
|
||||||
|
add ebp,edx ; ebp = source
|
||||||
add eax,edi ; eax = dest
|
add eax,edi ; eax = dest
|
||||||
mov edi,[dc_pitch] ; edi = pitch
|
mov edi,[dc_pitch] ; edi = pitch
|
||||||
add eax,[dc_destorg]
|
add eax,[dc_destorg]
|
||||||
|
@ -1414,7 +1420,8 @@ _rt_map4cols_asm2:
|
||||||
mov eax,ecx
|
mov eax,ecx
|
||||||
inc ebx ; ebx = count
|
inc ebx ; ebx = count
|
||||||
mov edi,[ylookup+edx]
|
mov edi,[ylookup+edx]
|
||||||
lea ebp,[dc_temp+edx] ; ebp = source
|
mov ebp,[dc_temp]
|
||||||
|
add ebp,edx ; ebp = source
|
||||||
add eax,edi ; eax = dest
|
add eax,edi ; eax = dest
|
||||||
mov edi,[dc_pitch] ; edi = pitch
|
mov edi,[dc_pitch] ; edi = pitch
|
||||||
add eax,[dc_destorg]
|
add eax,[dc_destorg]
|
||||||
|
@ -1493,10 +1500,11 @@ _rt_shaded4cols_asm:
|
||||||
add eax,[dc_destorg] ; eax = destination
|
add eax,[dc_destorg] ; eax = destination
|
||||||
push ebx
|
push ebx
|
||||||
push esi
|
push esi
|
||||||
|
mov esi,[dc_temp]
|
||||||
inc ebp ; ebp = count
|
inc ebp ; ebp = count
|
||||||
add eax,[esp+16]
|
add eax,[esp+16]
|
||||||
push edi
|
push edi
|
||||||
lea esi,[dc_temp+ecx*4] ; esi = source
|
lea esi,[esi+ecx*4] ; esi = source
|
||||||
|
|
||||||
align 16
|
align 16
|
||||||
|
|
||||||
|
@ -1580,10 +1588,11 @@ _rt_add4cols_asm:
|
||||||
add eax,[dc_destorg]
|
add eax,[dc_destorg]
|
||||||
push ebx
|
push ebx
|
||||||
push esi
|
push esi
|
||||||
|
mov esi,[dc_temp]
|
||||||
push ebp
|
push ebp
|
||||||
inc edi
|
inc edi
|
||||||
add eax,[esp+20]
|
add eax,[esp+20]
|
||||||
lea esi,[dc_temp+ecx*4]
|
lea esi,[esi+ecx*4]
|
||||||
|
|
||||||
align 16
|
align 16
|
||||||
a4loop:
|
a4loop:
|
||||||
|
@ -1659,10 +1668,11 @@ _rt_addclamp4cols_asm:
|
||||||
add eax,[dc_destorg]
|
add eax,[dc_destorg]
|
||||||
push ebx
|
push ebx
|
||||||
push esi
|
push esi
|
||||||
|
mov esi,[dc_temp]
|
||||||
push ebp
|
push ebp
|
||||||
inc edi
|
inc edi
|
||||||
add eax,[esp+20]
|
add eax,[esp+20]
|
||||||
lea esi,[dc_temp+ecx*4]
|
lea esi,[esi+ecx*4]
|
||||||
push edi
|
push edi
|
||||||
|
|
||||||
align 16
|
align 16
|
||||||
|
|
|
@ -453,7 +453,7 @@ CCMD (puke)
|
||||||
|
|
||||||
if (argc < 2 || argc > 5)
|
if (argc < 2 || argc > 5)
|
||||||
{
|
{
|
||||||
Printf (" puke <script> [arg1] [arg2] [arg3]\n");
|
Printf ("Usage: puke <script> [arg1] [arg2] [arg3]\n");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -489,6 +489,52 @@ CCMD (puke)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CCMD (special)
|
||||||
|
{
|
||||||
|
int argc = argv.argc();
|
||||||
|
|
||||||
|
if (argc < 2 || argc > 7)
|
||||||
|
{
|
||||||
|
Printf("Usage: special <special-name> [arg1] [arg2] [arg3] [arg4] [arg5]\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int specnum;
|
||||||
|
|
||||||
|
if (argv[1][0] >= '0' && argv[1][0] <= '9')
|
||||||
|
{
|
||||||
|
specnum = atoi(argv[1]);
|
||||||
|
if (specnum < 0 || specnum > 255)
|
||||||
|
{
|
||||||
|
Printf("Bad special number\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int min_args;
|
||||||
|
specnum = P_FindLineSpecial(argv[1], &min_args);
|
||||||
|
if (specnum == 0 || min_args < 0)
|
||||||
|
{
|
||||||
|
Printf("Unknown special\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (argc < 2 + min_args)
|
||||||
|
{
|
||||||
|
Printf("%s needs at least %d argument%s\n", argv[1], min_args, min_args == 1 ? "" : "s");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Net_WriteByte(DEM_RUNSPECIAL);
|
||||||
|
Net_WriteByte(specnum);
|
||||||
|
Net_WriteByte(argc - 2);
|
||||||
|
for (int i = 2; i < argc; ++i)
|
||||||
|
{
|
||||||
|
Net_WriteLong(atoi(argv[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CCMD (error)
|
CCMD (error)
|
||||||
{
|
{
|
||||||
if (argv.argc() > 1)
|
if (argv.argc() > 1)
|
||||||
|
|
|
@ -221,7 +221,16 @@ int FBaseCVar::ToInt (UCVarValue value, ECVarType type)
|
||||||
#else
|
#else
|
||||||
case CVAR_Float: res = (int)value.Float; break;
|
case CVAR_Float: res = (int)value.Float; break;
|
||||||
#endif
|
#endif
|
||||||
case CVAR_String: res = strtol (value.String, NULL, 0); break;
|
case CVAR_String:
|
||||||
|
{
|
||||||
|
if (stricmp (value.String, "true") == 0)
|
||||||
|
res = 1;
|
||||||
|
else if (stricmp (value.String, "false") == 0)
|
||||||
|
res = 0;
|
||||||
|
else
|
||||||
|
res = strtol (value.String, NULL, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case CVAR_GUID: res = 0; break;
|
case CVAR_GUID: res = 0; break;
|
||||||
default: res = 0; break;
|
default: res = 0; break;
|
||||||
}
|
}
|
||||||
|
@ -444,7 +453,12 @@ UCVarValue FBaseCVar::FromString (const char *value, ECVarType type)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CVAR_Int:
|
case CVAR_Int:
|
||||||
ret.Int = strtol (value, NULL, 0);
|
if (stricmp (value, "true") == 0)
|
||||||
|
ret.Int = 1;
|
||||||
|
else if (stricmp (value, "false") == 0)
|
||||||
|
ret.Int = 0;
|
||||||
|
else
|
||||||
|
ret.Int = strtol (value, NULL, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CVAR_Float:
|
case CVAR_Float:
|
||||||
|
|
|
@ -166,5 +166,6 @@ void ResetButtonStates (); // Same as above, but also clear bDown
|
||||||
|
|
||||||
extern unsigned int MakeKey (const char *s);
|
extern unsigned int MakeKey (const char *s);
|
||||||
extern unsigned int MakeKey (const char *s, size_t len);
|
extern unsigned int MakeKey (const char *s, size_t len);
|
||||||
|
extern unsigned int SuperFastHash (const char *data, size_t len);
|
||||||
|
|
||||||
#endif //__C_DISPATCH_H__
|
#endif //__C_DISPATCH_H__
|
||||||
|
|
|
@ -90,7 +90,6 @@ static FCompatOption Options[] =
|
||||||
{ "resetplayerspeed", 0, BCOMPATF_RESETPLAYERSPEED },
|
{ "resetplayerspeed", 0, BCOMPATF_RESETPLAYERSPEED },
|
||||||
{ "vileghosts", 0, BCOMPATF_VILEGHOSTS },
|
{ "vileghosts", 0, BCOMPATF_VILEGHOSTS },
|
||||||
{ "ignoreteleporttags", 0, BCOMPATF_BADTELEPORTERS },
|
{ "ignoreteleporttags", 0, BCOMPATF_BADTELEPORTERS },
|
||||||
{ "oldportals", 0, BCOMPATF_BADPORTALS },
|
|
||||||
|
|
||||||
// list copied from g_mapinfo.cpp
|
// list copied from g_mapinfo.cpp
|
||||||
{ "shorttex", COMPATF_SHORTTEX, 0 },
|
{ "shorttex", COMPATF_SHORTTEX, 0 },
|
||||||
|
@ -284,12 +283,6 @@ void CheckCompatibility(MapData *map)
|
||||||
ib_compatflags = 0;
|
ib_compatflags = 0;
|
||||||
ii_compatparams = -1;
|
ii_compatparams = -1;
|
||||||
}
|
}
|
||||||
else if (Wads.GetLumpFile(map->lumpnum) == 1 && (gameinfo.flags & GI_COMPATPORTAL))
|
|
||||||
{
|
|
||||||
ii_compatflags = 0;
|
|
||||||
ib_compatflags = BCOMPATF_BADPORTALS;
|
|
||||||
ii_compatparams = -1;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
map->GetChecksum(md5.Bytes);
|
map->GetChecksum(md5.Bytes);
|
||||||
|
|
|
@ -174,7 +174,6 @@ void FIWadManager::ParseIWadInfo(const char *fn, const char *data, int datasize)
|
||||||
else if(sc.Compare("Extended")) iwad->flags |= GI_MENUHACK_EXTENDED;
|
else if(sc.Compare("Extended")) iwad->flags |= GI_MENUHACK_EXTENDED;
|
||||||
else if(sc.Compare("Shorttex")) iwad->flags |= GI_COMPATSHORTTEX;
|
else if(sc.Compare("Shorttex")) iwad->flags |= GI_COMPATSHORTTEX;
|
||||||
else if(sc.Compare("Stairs")) iwad->flags |= GI_COMPATSTAIRS;
|
else if(sc.Compare("Stairs")) iwad->flags |= GI_COMPATSTAIRS;
|
||||||
else if(sc.Compare("Portals")) iwad->flags |= GI_COMPATPORTAL;
|
|
||||||
else sc.ScriptError(NULL);
|
else sc.ScriptError(NULL);
|
||||||
}
|
}
|
||||||
while (sc.CheckString(","));
|
while (sc.CheckString(","));
|
||||||
|
|
|
@ -57,6 +57,7 @@
|
||||||
#include "g_level.h"
|
#include "g_level.h"
|
||||||
#include "d_event.h"
|
#include "d_event.h"
|
||||||
#include "m_argv.h"
|
#include "m_argv.h"
|
||||||
|
#include "p_lnspec.h"
|
||||||
|
|
||||||
int P_StartScript (AActor *who, line_t *where, int script, char *map, bool backSide,
|
int P_StartScript (AActor *who, line_t *where, int script, char *map, bool backSide,
|
||||||
int arg0, int arg1, int arg2, int always, bool wantResultCode, bool net);
|
int arg0, int arg1, int arg2, int always, bool wantResultCode, bool net);
|
||||||
|
@ -2316,13 +2317,38 @@ void Net_DoCommand (int type, BYTE **stream, int player)
|
||||||
|
|
||||||
for (i = 0; i < argn; ++i)
|
for (i = 0; i < argn; ++i)
|
||||||
{
|
{
|
||||||
arg[i] = ReadLong (stream);
|
int argval = ReadLong(stream);
|
||||||
|
if (i < countof(arg))
|
||||||
|
{
|
||||||
|
arg[i] = argval;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
P_StartScript (players[player].mo, NULL, snum, level.mapname, false,
|
P_StartScript (players[player].mo, NULL, snum, level.mapname, false,
|
||||||
arg[0], arg[1], arg[2], type == DEM_RUNSCRIPT2, false, true);
|
arg[0], arg[1], arg[2], type == DEM_RUNSCRIPT2, false, true);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case DEM_RUNSPECIAL:
|
||||||
|
{
|
||||||
|
int snum = ReadByte(stream);
|
||||||
|
int argn = ReadByte(stream);
|
||||||
|
int arg[5] = { 0, 0, 0, 0, 0 };
|
||||||
|
|
||||||
|
for (i = 0; i < argn; ++i)
|
||||||
|
{
|
||||||
|
int argval = ReadLong(stream);
|
||||||
|
if (i < countof(arg))
|
||||||
|
{
|
||||||
|
arg[i] = argval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!CheckCheatmode(player == consoleplayer))
|
||||||
|
{
|
||||||
|
LineSpecials[snum](NULL, players[player].mo, false, arg[0], arg[1], arg[2], arg[3], arg[4]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case DEM_CROUCH:
|
case DEM_CROUCH:
|
||||||
if (gamestate == GS_LEVEL && players[player].mo != NULL &&
|
if (gamestate == GS_LEVEL && players[player].mo != NULL &&
|
||||||
players[player].health > 0 && !(players[player].oldbuttons & BT_JUMP))
|
players[player].health > 0 && !(players[player].oldbuttons & BT_JUMP))
|
||||||
|
@ -2521,6 +2547,10 @@ void Net_SkipCommand (int type, BYTE **stream)
|
||||||
skip = 3 + *(*stream + 2) * 4;
|
skip = 3 + *(*stream + 2) * 4;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case DEM_RUNSPECIAL:
|
||||||
|
skip = 2 + *(*stream + 1) * 4;
|
||||||
|
break;
|
||||||
|
|
||||||
case DEM_CONVREPLY:
|
case DEM_CONVREPLY:
|
||||||
skip = 3;
|
skip = 3;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -137,6 +137,7 @@ public:
|
||||||
int SpawnMask;
|
int SpawnMask;
|
||||||
FNameNoInit MorphWeapon;
|
FNameNoInit MorphWeapon;
|
||||||
fixed_t AttackZOffset; // attack height, relative to player center
|
fixed_t AttackZOffset; // attack height, relative to player center
|
||||||
|
const PClass *FlechetteType;
|
||||||
|
|
||||||
// [CW] Fades for when you are being damaged.
|
// [CW] Fades for when you are being damaged.
|
||||||
PalEntry DamageFade;
|
PalEntry DamageFade;
|
||||||
|
|
|
@ -158,6 +158,7 @@ enum EDemoCommand
|
||||||
DEM_CONVREPLY, // 59 Word: Dialogue node, Byte: Reply number
|
DEM_CONVREPLY, // 59 Word: Dialogue node, Byte: Reply number
|
||||||
DEM_CONVCLOSE, // 60
|
DEM_CONVCLOSE, // 60
|
||||||
DEM_CONVNULL, // 61
|
DEM_CONVNULL, // 61
|
||||||
|
DEM_RUNSPECIAL, // 62 Byte: Special number, Byte: Arg count, Ints: Args
|
||||||
};
|
};
|
||||||
|
|
||||||
// The following are implemented by cht_DoCheat in m_cheat.cpp
|
// The following are implemented by cht_DoCheat in m_cheat.cpp
|
||||||
|
|
|
@ -455,6 +455,8 @@ CCMD (drop)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const PClass *GetFlechetteType(AActor *other);
|
||||||
|
|
||||||
CCMD (useflechette)
|
CCMD (useflechette)
|
||||||
{ // Select from one of arti_poisonbag1-3, whichever the player has
|
{ // Select from one of arti_poisonbag1-3, whichever the player has
|
||||||
static const ENamedName bagnames[3] =
|
static const ENamedName bagnames[3] =
|
||||||
|
@ -463,22 +465,26 @@ CCMD (useflechette)
|
||||||
NAME_ArtiPoisonBag2,
|
NAME_ArtiPoisonBag2,
|
||||||
NAME_ArtiPoisonBag3
|
NAME_ArtiPoisonBag3
|
||||||
};
|
};
|
||||||
int i, j;
|
|
||||||
|
|
||||||
if (who == NULL)
|
if (who == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (who->IsKindOf (PClass::FindClass (NAME_ClericPlayer)))
|
const PClass *type = GetFlechetteType(who);
|
||||||
i = 0;
|
if (type != NULL)
|
||||||
else if (who->IsKindOf (PClass::FindClass (NAME_MagePlayer)))
|
|
||||||
i = 1;
|
|
||||||
else
|
|
||||||
i = 2;
|
|
||||||
|
|
||||||
for (j = 0; j < 3; ++j)
|
|
||||||
{
|
{
|
||||||
AInventory *item;
|
AInventory *item;
|
||||||
if ( (item = who->FindInventory (bagnames[(i+j)%3])) )
|
if ( (item = who->FindInventory (type) ))
|
||||||
|
{
|
||||||
|
SendItemUse = item;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The default flechette could not be found. Try all 3 types then.
|
||||||
|
for (int j = 0; j < 3; ++j)
|
||||||
|
{
|
||||||
|
AInventory *item;
|
||||||
|
if ( (item = who->FindInventory (bagnames[j])) )
|
||||||
{
|
{
|
||||||
SendItemUse = item;
|
SendItemUse = item;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -141,6 +141,27 @@ bool AArtiPoisonBag3::Use (bool pickup)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// GetFlechetteType
|
||||||
|
//
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
const PClass *GetFlechetteType(AActor *other)
|
||||||
|
{
|
||||||
|
const PClass *spawntype = NULL;
|
||||||
|
if (other->IsKindOf(RUNTIME_CLASS(APlayerPawn)))
|
||||||
|
{
|
||||||
|
spawntype = static_cast<APlayerPawn*>(other)->FlechetteType;
|
||||||
|
}
|
||||||
|
if (spawntype == NULL)
|
||||||
|
{
|
||||||
|
// default fallback if nothing valid defined.
|
||||||
|
spawntype = RUNTIME_CLASS(AArtiPoisonBag3);
|
||||||
|
}
|
||||||
|
return spawntype;
|
||||||
|
}
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
//
|
//
|
||||||
// AArtiPoisonBag :: HandlePickup
|
// AArtiPoisonBag :: HandlePickup
|
||||||
|
@ -155,21 +176,7 @@ bool AArtiPoisonBag::HandlePickup (AInventory *item)
|
||||||
return Super::HandlePickup (item);
|
return Super::HandlePickup (item);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool matched;
|
if (GetClass() == GetFlechetteType(Owner))
|
||||||
|
|
||||||
if (Owner->IsKindOf (PClass::FindClass(NAME_ClericPlayer)))
|
|
||||||
{
|
|
||||||
matched = (GetClass() == RUNTIME_CLASS(AArtiPoisonBag1));
|
|
||||||
}
|
|
||||||
else if (Owner->IsKindOf (PClass::FindClass(NAME_MagePlayer)))
|
|
||||||
{
|
|
||||||
matched = (GetClass() == RUNTIME_CLASS(AArtiPoisonBag2));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
matched = (GetClass() == RUNTIME_CLASS(AArtiPoisonBag3));
|
|
||||||
}
|
|
||||||
if (matched)
|
|
||||||
{
|
{
|
||||||
if (Amount < MaxAmount)
|
if (Amount < MaxAmount)
|
||||||
{
|
{
|
||||||
|
@ -204,20 +211,8 @@ AInventory *AArtiPoisonBag::CreateCopy (AActor *other)
|
||||||
}
|
}
|
||||||
|
|
||||||
AInventory *copy;
|
AInventory *copy;
|
||||||
const PClass *spawntype;
|
|
||||||
|
|
||||||
if (other->IsKindOf (PClass::FindClass(NAME_ClericPlayer)))
|
const PClass *spawntype = GetFlechetteType(other);
|
||||||
{
|
|
||||||
spawntype = RUNTIME_CLASS(AArtiPoisonBag1);
|
|
||||||
}
|
|
||||||
else if (other->IsKindOf (PClass::FindClass(NAME_MagePlayer)))
|
|
||||||
{
|
|
||||||
spawntype = RUNTIME_CLASS(AArtiPoisonBag2);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
spawntype = RUNTIME_CLASS(AArtiPoisonBag3);
|
|
||||||
}
|
|
||||||
copy = static_cast<AInventory *>(Spawn (spawntype, 0, 0, 0, NO_REPLACE));
|
copy = static_cast<AInventory *>(Spawn (spawntype, 0, 0, 0, NO_REPLACE));
|
||||||
copy->Amount = Amount;
|
copy->Amount = Amount;
|
||||||
copy->MaxAmount = MaxAmount;
|
copy->MaxAmount = MaxAmount;
|
||||||
|
|
|
@ -36,8 +36,6 @@ static FRandom pr_torch ("Torch");
|
||||||
#define TIMEFREEZE_TICS ( 12 * TICRATE )
|
#define TIMEFREEZE_TICS ( 12 * TICRATE )
|
||||||
*/
|
*/
|
||||||
|
|
||||||
EXTERN_CVAR (Bool, r_drawfuzz);
|
|
||||||
|
|
||||||
IMPLEMENT_CLASS (APowerup)
|
IMPLEMENT_CLASS (APowerup)
|
||||||
|
|
||||||
// Powerup-Giver -------------------------------------------------------------
|
// Powerup-Giver -------------------------------------------------------------
|
||||||
|
|
|
@ -1190,7 +1190,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
if(clearDontDraw)
|
if(clearDontDraw)
|
||||||
screen->Clear(static_cast<int>(MAX<double>(dx, dcx)), static_cast<int>(MAX<double>(dy, dcy)), static_cast<int>(dcr), static_cast<int>(dcb), GPalette.BlackIndex, 0);
|
screen->Clear(static_cast<int>(MAX<double>(dx, dcx)), static_cast<int>(MAX<double>(dy, dcy)), static_cast<int>(MIN<double>(dcr,w+MAX<double>(dx, dcx))), static_cast<int>(MIN<double>(dcb,MAX<double>(dy, dcy)+h)), GPalette.BlackIndex, 0);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(alphaMap)
|
if(alphaMap)
|
||||||
|
|
|
@ -2660,6 +2660,58 @@ class CommandPlayerClass : public SBarInfoCommandFlowControl
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class CommandPlayerType : public SBarInfoCommandFlowControl
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CommandPlayerType(SBarInfo *script) : SBarInfoCommandFlowControl(script)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Parse(FScanner &sc, bool fullScreenOffsets)
|
||||||
|
{
|
||||||
|
sc.MustGetToken(TK_Identifier);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
bool foundClass = false;
|
||||||
|
const PClass *cls = PClass::FindClass(sc.String);
|
||||||
|
if (cls != NULL)
|
||||||
|
{
|
||||||
|
foundClass = true;
|
||||||
|
classes.Push(cls);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
if(!foundClass)
|
||||||
|
sc.ScriptError("Unkown PlayerClass '%s'.", sc.String);
|
||||||
|
*/
|
||||||
|
if(!sc.CheckToken(','))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
while(sc.CheckToken(TK_Identifier));
|
||||||
|
SBarInfoCommandFlowControl::Parse(sc, fullScreenOffsets);
|
||||||
|
}
|
||||||
|
void Tick(const SBarInfoMainBlock *block, const DSBarInfo *statusBar, bool hudChanged)
|
||||||
|
{
|
||||||
|
SBarInfoCommandFlowControl::Tick(block, statusBar, hudChanged);
|
||||||
|
|
||||||
|
if(statusBar->CPlayer->cls == NULL)
|
||||||
|
return; //No class so we can not continue
|
||||||
|
|
||||||
|
for(unsigned int i = 0;i < classes.Size();i++)
|
||||||
|
{
|
||||||
|
if (statusBar->CPlayer->cls->IsDescendantOf(classes[i]))
|
||||||
|
{
|
||||||
|
SetTruth(true, block, statusBar);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SetTruth(false, block, statusBar);
|
||||||
|
}
|
||||||
|
protected:
|
||||||
|
TArray<const PClass *> classes;
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
class CommandHasWeaponPiece : public SBarInfoCommandFlowControl
|
class CommandHasWeaponPiece : public SBarInfoCommandFlowControl
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -3082,7 +3134,7 @@ static const char *SBarInfoCommandNames[] =
|
||||||
"drawmugshot", "drawselectedinventory",
|
"drawmugshot", "drawselectedinventory",
|
||||||
"drawinventorybar", "drawbar", "drawgem",
|
"drawinventorybar", "drawbar", "drawgem",
|
||||||
"drawshader", "drawstring", "drawkeybar",
|
"drawshader", "drawstring", "drawkeybar",
|
||||||
"gamemode", "playerclass", "aspectratio",
|
"gamemode", "playerclass", "playertype", "aspectratio",
|
||||||
"isselected", "usesammo", "usessecondaryammo",
|
"isselected", "usesammo", "usessecondaryammo",
|
||||||
"hasweaponpiece", "inventorybarnotvisible",
|
"hasweaponpiece", "inventorybarnotvisible",
|
||||||
"weaponammo", "ininventory", "alpha",
|
"weaponammo", "ininventory", "alpha",
|
||||||
|
@ -3095,7 +3147,7 @@ enum SBarInfoCommands
|
||||||
SBARINFO_DRAWMUGSHOT, SBARINFO_DRAWSELECTEDINVENTORY,
|
SBARINFO_DRAWMUGSHOT, SBARINFO_DRAWSELECTEDINVENTORY,
|
||||||
SBARINFO_DRAWINVENTORYBAR, SBARINFO_DRAWBAR, SBARINFO_DRAWGEM,
|
SBARINFO_DRAWINVENTORYBAR, SBARINFO_DRAWBAR, SBARINFO_DRAWGEM,
|
||||||
SBARINFO_DRAWSHADER, SBARINFO_DRAWSTRING, SBARINFO_DRAWKEYBAR,
|
SBARINFO_DRAWSHADER, SBARINFO_DRAWSTRING, SBARINFO_DRAWKEYBAR,
|
||||||
SBARINFO_GAMEMODE, SBARINFO_PLAYERCLASS, SBARINFO_ASPECTRATIO,
|
SBARINFO_GAMEMODE, SBARINFO_PLAYERCLASS, SBARINFO_PLAYERTYPE, SBARINFO_ASPECTRATIO,
|
||||||
SBARINFO_ISSELECTED, SBARINFO_USESAMMO, SBARINFO_USESSECONDARYAMMO,
|
SBARINFO_ISSELECTED, SBARINFO_USESAMMO, SBARINFO_USESSECONDARYAMMO,
|
||||||
SBARINFO_HASWEAPONPIECE, SBARINFO_INVENTORYBARNOTVISIBLE,
|
SBARINFO_HASWEAPONPIECE, SBARINFO_INVENTORYBARNOTVISIBLE,
|
||||||
SBARINFO_WEAPONAMMO, SBARINFO_ININVENTORY, SBARINFO_ALPHA,
|
SBARINFO_WEAPONAMMO, SBARINFO_ININVENTORY, SBARINFO_ALPHA,
|
||||||
|
@ -3126,6 +3178,7 @@ SBarInfoCommand *SBarInfoCommandFlowControl::NextCommand(FScanner &sc)
|
||||||
case SBARINFO_ASPECTRATIO: return new CommandAspectRatio(script);
|
case SBARINFO_ASPECTRATIO: return new CommandAspectRatio(script);
|
||||||
case SBARINFO_ISSELECTED: return new CommandIsSelected(script);
|
case SBARINFO_ISSELECTED: return new CommandIsSelected(script);
|
||||||
case SBARINFO_PLAYERCLASS: return new CommandPlayerClass(script);
|
case SBARINFO_PLAYERCLASS: return new CommandPlayerClass(script);
|
||||||
|
case SBARINFO_PLAYERTYPE: return new CommandPlayerType(script);
|
||||||
case SBARINFO_HASWEAPONPIECE: return new CommandHasWeaponPiece(script);
|
case SBARINFO_HASWEAPONPIECE: return new CommandHasWeaponPiece(script);
|
||||||
case SBARINFO_WEAPONAMMO: return new CommandWeaponAmmo(script);
|
case SBARINFO_WEAPONAMMO: return new CommandWeaponAmmo(script);
|
||||||
case SBARINFO_ININVENTORY: return new CommandInInventory(script);
|
case SBARINFO_ININVENTORY: return new CommandInInventory(script);
|
||||||
|
|
1
src/gi.h
1
src/gi.h
|
@ -47,7 +47,6 @@
|
||||||
#define GI_COMPATPOLY1 0x00000040 // Hexen's MAP36 needs old polyobject drawing
|
#define GI_COMPATPOLY1 0x00000040 // Hexen's MAP36 needs old polyobject drawing
|
||||||
#define GI_COMPATPOLY2 0x00000080 // so does HEXDD's MAP47
|
#define GI_COMPATPOLY2 0x00000080 // so does HEXDD's MAP47
|
||||||
#define GI_NOTEXTCOLOR 0x00000100 // Chex Quest 3 would have everything green
|
#define GI_NOTEXTCOLOR 0x00000100 // Chex Quest 3 would have everything green
|
||||||
#define GI_COMPATPORTAL 0x00000200 // Urban Brawl relies on the old portal code
|
|
||||||
|
|
||||||
#include "gametype.h"
|
#include "gametype.h"
|
||||||
|
|
||||||
|
|
|
@ -810,7 +810,8 @@ void F_StartFinale (const char *music, int musicorder, int cdtrack, unsigned int
|
||||||
const char *text, INTBOOL textInLump, INTBOOL finalePic, INTBOOL lookupText,
|
const char *text, INTBOOL textInLump, INTBOOL finalePic, INTBOOL lookupText,
|
||||||
bool ending, FName endsequence)
|
bool ending, FName endsequence)
|
||||||
{
|
{
|
||||||
if (text != NULL && *text != 0)
|
// Hexen's chess ending doesn't have a text screen, even if the cluster has a message defined.
|
||||||
|
if (text != NULL && *text != 0 && endsequence != NAME_Inter_Chess)
|
||||||
{
|
{
|
||||||
FIntermissionActionTextscreen *textscreen = new FIntermissionActionTextscreen;
|
FIntermissionActionTextscreen *textscreen = new FIntermissionActionTextscreen;
|
||||||
if (textInLump)
|
if (textInLump)
|
||||||
|
|
|
@ -141,4 +141,36 @@ inline SDWORD ModDiv (SDWORD num, SDWORD den, SDWORD *dmval)
|
||||||
#define FIXED2FLOAT(f) ((f) / float(65536))
|
#define FIXED2FLOAT(f) ((f) / float(65536))
|
||||||
#define FIXED2DBL(f) ((f) / double(65536))
|
#define FIXED2DBL(f) ((f) / double(65536))
|
||||||
|
|
||||||
|
class Fixed
|
||||||
|
{
|
||||||
|
int v;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Fixed() {}
|
||||||
|
Fixed(int val) { v = val; }
|
||||||
|
Fixed(double val) { v = xs_Fix<16>::ToFix(val); }
|
||||||
|
Fixed &operator = (int val) { v = val; return *this; }
|
||||||
|
Fixed &operator = (double val) { v = xs_Fix<16>::ToFix(val); return *this; }
|
||||||
|
|
||||||
|
Fixed &operator += (Fixed val) { v += val.v; return *this; }
|
||||||
|
Fixed &operator -= (Fixed val) { v -= val.v; return *this; }
|
||||||
|
Fixed &operator *= (Fixed val) { v = FixedMul(v, val.v); return *this; }
|
||||||
|
Fixed &operator /= (Fixed val) { v = FixedDiv(v, val.v); return *this; }
|
||||||
|
Fixed &operator += (double val) { v += xs_Fix<16>::ToFix(val); return *this; }
|
||||||
|
Fixed &operator -= (double val) { v -= xs_Fix<16>::ToFix(val); return *this; }
|
||||||
|
Fixed &operator *= (Fixed val) { v = FixedMul(v, xs_Fix<16>::ToFix(val)); return *this; }
|
||||||
|
Fixed &operator /= (Fixed val) { v = FixedDiv(v, xs_Fix<16>::ToFix(val)); return *this; }
|
||||||
|
|
||||||
|
Fixed operator + (Fixed val) { return v + val.v; }
|
||||||
|
Fixed operator - (Fixed val) { return v - val.v; }
|
||||||
|
Fixed operator * (Fixed val) { return FixedMul(v, val.v); }
|
||||||
|
Fixed operator / (Fixed val) { return FixedDiv(v, val.v); }
|
||||||
|
Fixed operator + (double val) { return v + xs_Fix<16>::ToFix(val); }
|
||||||
|
Fixed operator - (double val) { return v - xs_Fix<16>::ToFix(val); }
|
||||||
|
Fixed operator * (Fixed val) { return FixedMul(v, xs_Fix<16>::ToFix(val)); }
|
||||||
|
Fixed operator / (Fixed val) { return FixedDiv(v, xs_Fix<16>::ToFix(val)); }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
376
src/memarena.cpp
Normal file
376
src/memarena.cpp
Normal file
|
@ -0,0 +1,376 @@
|
||||||
|
/*
|
||||||
|
** memarena.cpp
|
||||||
|
** Implements memory arenas.
|
||||||
|
**
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
** Copyright 2010 Randy Heit
|
||||||
|
** All rights reserved.
|
||||||
|
**
|
||||||
|
** Redistribution and use in source and binary forms, with or without
|
||||||
|
** modification, are permitted provided that the following conditions
|
||||||
|
** are met:
|
||||||
|
**
|
||||||
|
** 1. Redistributions of source code must retain the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer.
|
||||||
|
** 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer in the
|
||||||
|
** documentation and/or other materials provided with the distribution.
|
||||||
|
** 3. The name of the author may not be used to endorse or promote products
|
||||||
|
** derived from this software without specific prior written permission.
|
||||||
|
**
|
||||||
|
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
**
|
||||||
|
** A memory arena is used for efficient allocation of many small objects that
|
||||||
|
** will all be freed at once. Note that since individual destructors are not
|
||||||
|
** called, you must not use an arena to allocate any objects that use a
|
||||||
|
** destructor, either explicitly or implicitly (because they have members
|
||||||
|
** with destructors).
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "doomtype.h"
|
||||||
|
#include "m_alloc.h"
|
||||||
|
#include "memarena.h"
|
||||||
|
#include "c_dispatch.h"
|
||||||
|
#include "zstring.h"
|
||||||
|
|
||||||
|
#define BLOCK_SIZE (10*1024)
|
||||||
|
|
||||||
|
struct FMemArena::Block
|
||||||
|
{
|
||||||
|
Block *NextBlock;
|
||||||
|
void *Limit; // End of this block
|
||||||
|
void *Avail; // Start of free space in this block
|
||||||
|
|
||||||
|
void Reset();
|
||||||
|
void *Alloc(size_t size);
|
||||||
|
};
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// RoundPointer
|
||||||
|
//
|
||||||
|
// Rounds a pointer up to a pointer-sized boundary.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
static inline void *RoundPointer(void *ptr)
|
||||||
|
{
|
||||||
|
return (void *)(((size_t)ptr + sizeof(void*) - 1) & ~(sizeof(void*) - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FMemArena Constructor
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
FMemArena::FMemArena()
|
||||||
|
{
|
||||||
|
TopBlock = NULL;
|
||||||
|
FreeBlocks = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FMemArena Destructor
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
FMemArena::~FMemArena()
|
||||||
|
{
|
||||||
|
FreeAllBlocks();
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FMemArena :: Alloc
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void *FMemArena::Alloc(size_t size)
|
||||||
|
{
|
||||||
|
Block *block;
|
||||||
|
|
||||||
|
for (block = TopBlock; block != NULL; block = block->NextBlock)
|
||||||
|
{
|
||||||
|
void *res = block->Alloc(size);
|
||||||
|
if (res != NULL)
|
||||||
|
{
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
block = AddBlock(size);
|
||||||
|
return block->Alloc(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FMemArena :: FreeAll
|
||||||
|
//
|
||||||
|
// Moves all blocks to the free list. No system-level deallocation occurs.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void FMemArena::FreeAll()
|
||||||
|
{
|
||||||
|
for (Block *next, *block = TopBlock; block != NULL; block = next)
|
||||||
|
{
|
||||||
|
next = block->NextBlock;
|
||||||
|
block->Reset();
|
||||||
|
block->NextBlock = FreeBlocks;
|
||||||
|
FreeBlocks = block;
|
||||||
|
}
|
||||||
|
TopBlock = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FMemArena :: FreeAllBlocks
|
||||||
|
//
|
||||||
|
// Frees all blocks used by this arena.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void FMemArena::FreeAllBlocks()
|
||||||
|
{
|
||||||
|
FreeBlockChain(TopBlock);
|
||||||
|
FreeBlockChain(FreeBlocks);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FMemArena :: FreeBlockChain
|
||||||
|
//
|
||||||
|
// Frees a chain of blocks.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void FMemArena::FreeBlockChain(Block *&top)
|
||||||
|
{
|
||||||
|
for (Block *next, *block = top; block != NULL; block = next)
|
||||||
|
{
|
||||||
|
next = block->NextBlock;
|
||||||
|
M_Free(block);
|
||||||
|
}
|
||||||
|
top = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FMemArena :: AddBlock
|
||||||
|
//
|
||||||
|
// Allocates a block large enough to hold at least <size> bytes and adds it
|
||||||
|
// to the TopBlock chain.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
FMemArena::Block *FMemArena::AddBlock(size_t size)
|
||||||
|
{
|
||||||
|
Block *mem, **last;
|
||||||
|
size += sizeof(Block); // Account for header size
|
||||||
|
|
||||||
|
// Search for a free block to use
|
||||||
|
for (last = &FreeBlocks, mem = FreeBlocks; mem != NULL; last = &mem->NextBlock, mem = mem->NextBlock)
|
||||||
|
{
|
||||||
|
if ((BYTE *)mem->Limit - (BYTE *)mem >= (ptrdiff_t)size)
|
||||||
|
{
|
||||||
|
*last = mem->NextBlock;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mem == NULL)
|
||||||
|
{
|
||||||
|
// Allocate a new block
|
||||||
|
if (size < BLOCK_SIZE)
|
||||||
|
{
|
||||||
|
size = BLOCK_SIZE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // Stick some free space at the end so we can use this block for
|
||||||
|
// other things.
|
||||||
|
size += BLOCK_SIZE/2;
|
||||||
|
}
|
||||||
|
mem = (Block *)M_Malloc(size);
|
||||||
|
mem->Limit = (BYTE *)mem + size;
|
||||||
|
}
|
||||||
|
mem->Reset();
|
||||||
|
mem->NextBlock = TopBlock;
|
||||||
|
TopBlock = mem;
|
||||||
|
return mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FMemArena :: Block :: Reset
|
||||||
|
//
|
||||||
|
// Resets this block's Avail pointer.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void FMemArena::Block::Reset()
|
||||||
|
{
|
||||||
|
Avail = RoundPointer(this + sizeof(*this));
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FMemArena :: Block :: Alloc
|
||||||
|
//
|
||||||
|
// Allocates memory from the block if it has space. Returns NULL if not.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void *FMemArena::Block::Alloc(size_t size)
|
||||||
|
{
|
||||||
|
if ((char *)Avail + size > Limit)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
void *res = Avail;
|
||||||
|
Avail = RoundPointer((char *)Avail + size);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FSharedStringArena Constructor
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
FSharedStringArena::FSharedStringArena()
|
||||||
|
{
|
||||||
|
memset(Buckets, 0, sizeof(Buckets));
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FSharedStringArena Destructor
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
FSharedStringArena::~FSharedStringArena()
|
||||||
|
{
|
||||||
|
FreeAll();
|
||||||
|
// FMemArena destructor will free the blocks.
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FSharedStringArena :: Alloc
|
||||||
|
//
|
||||||
|
// Allocates a new string and initializes it with the passed string. This
|
||||||
|
// version takes an FString as a parameter, so it won't need to allocate any
|
||||||
|
// memory for the string text if it already exists in the arena.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
FString *FSharedStringArena::Alloc(const FString &source)
|
||||||
|
{
|
||||||
|
unsigned int hash;
|
||||||
|
Node *strnode;
|
||||||
|
|
||||||
|
strnode = FindString(source, source.Len(), hash);
|
||||||
|
if (strnode == NULL)
|
||||||
|
{
|
||||||
|
strnode = (Node *)FMemArena::Alloc(sizeof(Node));
|
||||||
|
::new(&strnode->String) FString(source);
|
||||||
|
strnode->Hash = hash;
|
||||||
|
hash %= countof(Buckets);
|
||||||
|
strnode->Next = Buckets[hash];
|
||||||
|
Buckets[hash] = strnode;
|
||||||
|
}
|
||||||
|
return &strnode->String;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FSharedStringArena :: Alloc
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
FString *FSharedStringArena::Alloc(const char *source)
|
||||||
|
{
|
||||||
|
return Alloc(source, strlen(source));
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FSharedStringArena :: Alloc
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
FString *FSharedStringArena::Alloc(const char *source, size_t strlen)
|
||||||
|
{
|
||||||
|
unsigned int hash;
|
||||||
|
Node *strnode;
|
||||||
|
|
||||||
|
strnode = FindString(source, strlen, hash);
|
||||||
|
if (strnode == NULL)
|
||||||
|
{
|
||||||
|
strnode = (Node *)FMemArena::Alloc(sizeof(Node));
|
||||||
|
::new(&strnode->String) FString(source, strlen);
|
||||||
|
strnode->Hash = hash;
|
||||||
|
hash %= countof(Buckets);
|
||||||
|
strnode->Next = Buckets[hash];
|
||||||
|
Buckets[hash] = strnode;
|
||||||
|
}
|
||||||
|
return &strnode->String;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FSharedStringArena :: FindString
|
||||||
|
//
|
||||||
|
// Finds the string if it's already in the arena. Returns NULL if not.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
FSharedStringArena::Node *FSharedStringArena::FindString(const char *str, size_t strlen, unsigned int &hash)
|
||||||
|
{
|
||||||
|
hash = SuperFastHash(str, strlen);
|
||||||
|
|
||||||
|
for (Node *node = Buckets[hash % countof(Buckets)]; node != NULL; node = node->Next)
|
||||||
|
{
|
||||||
|
if (node->Hash == hash && node->String.Len() == strlen && memcmp(&node->String[0], str, strlen) == 0)
|
||||||
|
{
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FSharedStringArena :: FreeAll
|
||||||
|
//
|
||||||
|
// In addition to moving all used blocks onto the free list, all FStrings
|
||||||
|
// they contain will have their destructors called.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void FSharedStringArena::FreeAll()
|
||||||
|
{
|
||||||
|
for (Block *next, *block = TopBlock; block != NULL; block = next)
|
||||||
|
{
|
||||||
|
next = block->NextBlock;
|
||||||
|
void *limit = block->Avail;
|
||||||
|
block->Reset();
|
||||||
|
for (Node *string = (Node *)block->Avail; string < limit; ++string)
|
||||||
|
{
|
||||||
|
string->~Node();
|
||||||
|
}
|
||||||
|
block->NextBlock = FreeBlocks;
|
||||||
|
FreeBlocks = block;
|
||||||
|
}
|
||||||
|
memset(Buckets, 0, sizeof(Buckets));
|
||||||
|
}
|
83
src/memarena.h
Normal file
83
src/memarena.h
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
/*
|
||||||
|
** memarena.h
|
||||||
|
**
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
** Copyright 2010 Randy Heit
|
||||||
|
** All rights reserved.
|
||||||
|
**
|
||||||
|
** Redistribution and use in source and binary forms, with or without
|
||||||
|
** modification, are permitted provided that the following conditions
|
||||||
|
** are met:
|
||||||
|
**
|
||||||
|
** 1. Redistributions of source code must retain the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer.
|
||||||
|
** 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer in the
|
||||||
|
** documentation and/or other materials provided with the distribution.
|
||||||
|
** 3. The name of the author may not be used to endorse or promote products
|
||||||
|
** derived from this software without specific prior written permission.
|
||||||
|
**
|
||||||
|
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "zstring.h"
|
||||||
|
|
||||||
|
// A general purpose arena.
|
||||||
|
class FMemArena
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FMemArena();
|
||||||
|
~FMemArena();
|
||||||
|
|
||||||
|
void *Alloc(size_t size);
|
||||||
|
void FreeAll();
|
||||||
|
void FreeAllBlocks();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
struct Block;
|
||||||
|
|
||||||
|
Block *AddBlock(size_t size);
|
||||||
|
void FreeBlockChain(Block *&top);
|
||||||
|
|
||||||
|
Block *TopBlock;
|
||||||
|
Block *FreeBlocks;
|
||||||
|
};
|
||||||
|
|
||||||
|
// An arena specializing in storage of FStrings. It knows how to free them,
|
||||||
|
// but this means it also should never be used for allocating anything else.
|
||||||
|
// Identical strings all return the same pointer.
|
||||||
|
class FSharedStringArena : public FMemArena
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FSharedStringArena();
|
||||||
|
~FSharedStringArena();
|
||||||
|
void FreeAll();
|
||||||
|
|
||||||
|
class FString *Alloc(const FString &source);
|
||||||
|
class FString *Alloc(const char *source);
|
||||||
|
class FString *Alloc(const char *source, size_t strlen);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
struct Node
|
||||||
|
{
|
||||||
|
Node *Next;
|
||||||
|
FString String;
|
||||||
|
unsigned int Hash;
|
||||||
|
};
|
||||||
|
Node *Buckets[256];
|
||||||
|
|
||||||
|
Node *FindString(const char *str, size_t strlen, unsigned int &hash);
|
||||||
|
private:
|
||||||
|
void *Alloc(size_t size) { return NULL; } // No access to FMemArena::Alloc for outsiders.
|
||||||
|
};
|
|
@ -912,7 +912,7 @@ void DPlayerMenu::ClassChanged (FListMenuItem *li)
|
||||||
players[consoleplayer].userinfo.PlayerClass = sel-1;
|
players[consoleplayer].userinfo.PlayerClass = sel-1;
|
||||||
PickPlayerClass();
|
PickPlayerClass();
|
||||||
|
|
||||||
cvar_set ("playerclass", sel == 0 ? "Random" : PlayerClass->Type->TypeName);
|
cvar_set ("playerclass", sel == 0 ? "Random" : PlayerClass->Type->Meta.GetMetaString (APMETA_DisplayName));
|
||||||
|
|
||||||
UpdateSkins();
|
UpdateSkins();
|
||||||
UpdateColorsets();
|
UpdateColorsets();
|
||||||
|
|
|
@ -529,6 +529,7 @@ xx(res_9)
|
||||||
xx(AlwaysRun)
|
xx(AlwaysRun)
|
||||||
|
|
||||||
// end sequences
|
// end sequences
|
||||||
|
xx(Inter_Chess)
|
||||||
xx(Inter_Strife)
|
xx(Inter_Strife)
|
||||||
xx(Inter_Strife_Good)
|
xx(Inter_Strife_Good)
|
||||||
xx(Inter_Strife_Sad)
|
xx(Inter_Strife_Sad)
|
||||||
|
|
|
@ -2829,6 +2829,9 @@ int DLevelScript::CheckActorProperty (int tid, int property, int value)
|
||||||
case APROP_MasterTID:
|
case APROP_MasterTID:
|
||||||
case APROP_TargetTID:
|
case APROP_TargetTID:
|
||||||
case APROP_TracerTID:
|
case APROP_TracerTID:
|
||||||
|
case APROP_WaterLevel:
|
||||||
|
case APROP_ScaleX:
|
||||||
|
case APROP_ScaleY:
|
||||||
return (GetActorProperty(tid, property) == value);
|
return (GetActorProperty(tid, property) == value);
|
||||||
|
|
||||||
// Boolean values need to compare to a binary version of value
|
// Boolean values need to compare to a binary version of value
|
||||||
|
|
|
@ -30,9 +30,11 @@
|
||||||
#include "r_state.h"
|
#include "r_state.h"
|
||||||
#include "gi.h"
|
#include "gi.h"
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
//
|
//
|
||||||
// CEILINGS
|
// CEILINGS
|
||||||
//
|
//
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
IMPLEMENT_CLASS (DCeiling)
|
IMPLEMENT_CLASS (DCeiling)
|
||||||
|
|
||||||
|
@ -40,6 +42,12 @@ DCeiling::DCeiling ()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
void DCeiling::Serialize (FArchive &arc)
|
void DCeiling::Serialize (FArchive &arc)
|
||||||
{
|
{
|
||||||
Super::Serialize (arc);
|
Super::Serialize (arc);
|
||||||
|
@ -59,6 +67,12 @@ void DCeiling::Serialize (FArchive &arc)
|
||||||
<< m_Hexencrush;
|
<< m_Hexencrush;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
void DCeiling::PlayCeilingSound ()
|
void DCeiling::PlayCeilingSound ()
|
||||||
{
|
{
|
||||||
if (m_Sector->seqType >= 0)
|
if (m_Sector->seqType >= 0)
|
||||||
|
@ -80,9 +94,12 @@ void DCeiling::PlayCeilingSound ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
//
|
//
|
||||||
// T_MoveCeiling
|
// DCeiling :: Tick
|
||||||
//
|
//
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
void DCeiling::Tick ()
|
void DCeiling::Tick ()
|
||||||
{
|
{
|
||||||
EResult res;
|
EResult res;
|
||||||
|
@ -176,6 +193,12 @@ void DCeiling::Tick ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
DCeiling::DCeiling (sector_t *sec)
|
DCeiling::DCeiling (sector_t *sec)
|
||||||
: DMovingCeiling (sec)
|
: DMovingCeiling (sec)
|
||||||
{
|
{
|
||||||
|
@ -191,11 +214,258 @@ DCeiling::DCeiling (sector_t *sec, fixed_t speed1, fixed_t speed2, int silent)
|
||||||
m_Silent = silent;
|
m_Silent = silent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
DCeiling *DCeiling::Create(sector_t *sec, DCeiling::ECeiling type, line_t *line, int tag,
|
||||||
|
fixed_t speed, fixed_t speed2, fixed_t height,
|
||||||
|
int crush, int silent, int change, bool hexencrush)
|
||||||
|
{
|
||||||
|
fixed_t targheight = 0; // Silence, GCC
|
||||||
|
|
||||||
|
// if ceiling already moving, don't start a second function on it
|
||||||
|
if (sec->PlaneMoving(sector_t::ceiling))
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// new door thinker
|
||||||
|
DCeiling *ceiling = new DCeiling (sec, speed, speed2, silent);
|
||||||
|
vertex_t *spot = sec->lines[0]->v1;
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case ceilCrushAndRaise:
|
||||||
|
case ceilCrushRaiseAndStay:
|
||||||
|
ceiling->m_TopHeight = sec->ceilingplane.d;
|
||||||
|
case ceilLowerAndCrush:
|
||||||
|
case ceilLowerAndCrushDist:
|
||||||
|
targheight = sec->FindHighestFloorPoint (&spot);
|
||||||
|
if (type == ceilLowerAndCrush)
|
||||||
|
{
|
||||||
|
targheight += 8*FRACUNIT;
|
||||||
|
}
|
||||||
|
else if (type == ceilLowerAndCrushDist)
|
||||||
|
{
|
||||||
|
targheight += height;
|
||||||
|
}
|
||||||
|
ceiling->m_BottomHeight = sec->ceilingplane.PointToDist (spot, targheight);
|
||||||
|
ceiling->m_Direction = -1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ceilRaiseToHighest:
|
||||||
|
targheight = sec->FindHighestCeilingSurrounding (&spot);
|
||||||
|
ceiling->m_TopHeight = sec->ceilingplane.PointToDist (spot, targheight);
|
||||||
|
ceiling->m_Direction = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ceilLowerByValue:
|
||||||
|
targheight = sec->ceilingplane.ZatPoint (spot) - height;
|
||||||
|
ceiling->m_BottomHeight = sec->ceilingplane.PointToDist (spot, targheight);
|
||||||
|
ceiling->m_Direction = -1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ceilRaiseByValue:
|
||||||
|
targheight = sec->ceilingplane.ZatPoint (spot) + height;
|
||||||
|
ceiling->m_TopHeight = sec->ceilingplane.PointToDist (spot, targheight);
|
||||||
|
ceiling->m_Direction = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ceilMoveToValue:
|
||||||
|
{
|
||||||
|
int diff = height - sec->ceilingplane.ZatPoint (spot);
|
||||||
|
|
||||||
|
targheight = height;
|
||||||
|
if (diff < 0)
|
||||||
|
{
|
||||||
|
ceiling->m_BottomHeight = sec->ceilingplane.PointToDist (spot, height);
|
||||||
|
ceiling->m_Direction = -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ceiling->m_TopHeight = sec->ceilingplane.PointToDist (spot, height);
|
||||||
|
ceiling->m_Direction = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ceilLowerToHighestFloor:
|
||||||
|
targheight = sec->FindHighestFloorSurrounding (&spot);
|
||||||
|
ceiling->m_BottomHeight = sec->ceilingplane.PointToDist (spot, targheight);
|
||||||
|
ceiling->m_Direction = -1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ceilRaiseToHighestFloor:
|
||||||
|
targheight = sec->FindHighestFloorSurrounding (&spot);
|
||||||
|
ceiling->m_TopHeight = sec->ceilingplane.PointToDist (spot, targheight);
|
||||||
|
ceiling->m_Direction = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ceilLowerInstant:
|
||||||
|
targheight = sec->ceilingplane.ZatPoint (spot) - height;
|
||||||
|
ceiling->m_BottomHeight = sec->ceilingplane.PointToDist (spot, targheight);
|
||||||
|
ceiling->m_Direction = -1;
|
||||||
|
ceiling->m_Speed = height;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ceilRaiseInstant:
|
||||||
|
targheight = sec->ceilingplane.ZatPoint (spot) + height;
|
||||||
|
ceiling->m_TopHeight = sec->ceilingplane.PointToDist (spot, targheight);
|
||||||
|
ceiling->m_Direction = 1;
|
||||||
|
ceiling->m_Speed = height;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ceilLowerToNearest:
|
||||||
|
targheight = sec->FindNextLowestCeiling (&spot);
|
||||||
|
ceiling->m_BottomHeight = sec->ceilingplane.PointToDist (spot, targheight);
|
||||||
|
ceiling->m_Direction = -1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ceilRaiseToNearest:
|
||||||
|
targheight = sec->FindNextHighestCeiling (&spot);
|
||||||
|
ceiling->m_TopHeight = sec->ceilingplane.PointToDist (spot, targheight);
|
||||||
|
ceiling->m_Direction = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ceilLowerToLowest:
|
||||||
|
targheight = sec->FindLowestCeilingSurrounding (&spot);
|
||||||
|
ceiling->m_BottomHeight = sec->ceilingplane.PointToDist (spot, targheight);
|
||||||
|
ceiling->m_Direction = -1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ceilRaiseToLowest:
|
||||||
|
targheight = sec->FindLowestCeilingSurrounding (&spot);
|
||||||
|
ceiling->m_TopHeight = sec->ceilingplane.PointToDist (spot, targheight);
|
||||||
|
ceiling->m_Direction = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ceilLowerToFloor:
|
||||||
|
targheight = sec->FindHighestFloorPoint (&spot);
|
||||||
|
ceiling->m_BottomHeight = sec->ceilingplane.PointToDist (spot, targheight);
|
||||||
|
ceiling->m_Direction = -1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ceilRaiseToFloor: // [RH] What's this for?
|
||||||
|
targheight = sec->FindHighestFloorPoint (&spot);
|
||||||
|
ceiling->m_TopHeight = sec->ceilingplane.PointToDist (spot, targheight);
|
||||||
|
ceiling->m_Direction = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ceilLowerToHighest:
|
||||||
|
targheight = sec->FindHighestCeilingSurrounding (&spot);
|
||||||
|
ceiling->m_BottomHeight = sec->ceilingplane.PointToDist (spot, targheight);
|
||||||
|
ceiling->m_Direction = -1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ceilLowerByTexture:
|
||||||
|
targheight = sec->ceilingplane.ZatPoint (spot) - sec->FindShortestUpperAround ();
|
||||||
|
ceiling->m_BottomHeight = sec->ceilingplane.PointToDist (spot, targheight);
|
||||||
|
ceiling->m_Direction = -1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ceilRaiseByTexture:
|
||||||
|
targheight = sec->ceilingplane.ZatPoint (spot) + sec->FindShortestUpperAround ();
|
||||||
|
ceiling->m_TopHeight = sec->ceilingplane.PointToDist (spot, targheight);
|
||||||
|
ceiling->m_Direction = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break; // Silence GCC
|
||||||
|
}
|
||||||
|
|
||||||
|
ceiling->m_Tag = tag;
|
||||||
|
ceiling->m_Type = type;
|
||||||
|
ceiling->m_Crush = crush;
|
||||||
|
ceiling->m_Hexencrush = hexencrush;
|
||||||
|
|
||||||
|
// Do not interpolate instant movement ceilings.
|
||||||
|
// Note for ZDoomGL: Check to make sure that you update the sector
|
||||||
|
// after the ceiling moves, because it hasn't actually moved yet.
|
||||||
|
fixed_t movedist;
|
||||||
|
|
||||||
|
if (ceiling->m_Direction < 0)
|
||||||
|
{
|
||||||
|
movedist = sec->ceilingplane.d - ceiling->m_BottomHeight;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
movedist = ceiling->m_TopHeight - sec->ceilingplane.d;
|
||||||
|
}
|
||||||
|
if (ceiling->m_Speed >= movedist)
|
||||||
|
{
|
||||||
|
ceiling->StopInterpolation();
|
||||||
|
}
|
||||||
|
|
||||||
|
// set texture/type change properties
|
||||||
|
if (change & 3) // if a texture change is indicated
|
||||||
|
{
|
||||||
|
if (change & 4) // if a numeric model change
|
||||||
|
{
|
||||||
|
sector_t *modelsec;
|
||||||
|
|
||||||
|
//jff 5/23/98 find model with floor at target height if target
|
||||||
|
//is a floor type
|
||||||
|
modelsec = (/*type == ceilRaiseToHighest ||*/
|
||||||
|
type == ceilRaiseToFloor ||
|
||||||
|
/*type == ceilLowerToHighest ||*/
|
||||||
|
type == ceilLowerToFloor) ?
|
||||||
|
sec->FindModelFloorSector (targheight) :
|
||||||
|
sec->FindModelCeilingSector (targheight);
|
||||||
|
if (modelsec != NULL)
|
||||||
|
{
|
||||||
|
ceiling->m_Texture = modelsec->GetTexture(sector_t::ceiling);
|
||||||
|
switch (change & 3)
|
||||||
|
{
|
||||||
|
case 1: // type is zeroed
|
||||||
|
ceiling->m_NewSpecial = 0;
|
||||||
|
ceiling->m_Type = genCeilingChg0;
|
||||||
|
break;
|
||||||
|
case 2: // type is copied
|
||||||
|
ceiling->m_NewSpecial = sec->special;
|
||||||
|
ceiling->m_Type = genCeilingChgT;
|
||||||
|
break;
|
||||||
|
case 3: // type is left alone
|
||||||
|
ceiling->m_Type = genCeilingChg;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (line) // else if a trigger model change
|
||||||
|
{
|
||||||
|
ceiling->m_Texture = line->frontsector->GetTexture(sector_t::ceiling);
|
||||||
|
switch (change & 3)
|
||||||
|
{
|
||||||
|
case 1: // type is zeroed
|
||||||
|
ceiling->m_NewSpecial = 0;
|
||||||
|
ceiling->m_Type = genCeilingChg0;
|
||||||
|
break;
|
||||||
|
case 2: // type is copied
|
||||||
|
ceiling->m_NewSpecial = line->frontsector->special;
|
||||||
|
ceiling->m_Type = genCeilingChgT;
|
||||||
|
break;
|
||||||
|
case 3: // type is left alone
|
||||||
|
ceiling->m_Type = genCeilingChg;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ceiling->PlayCeilingSound ();
|
||||||
|
return ceiling;
|
||||||
|
}
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
//
|
//
|
||||||
// EV_DoCeiling
|
// EV_DoCeiling
|
||||||
// Move a ceiling up/down and all around!
|
// Move a ceiling up/down and all around!
|
||||||
//
|
//
|
||||||
// [RH] Added tag, speed, speed2, height, crush, silent, change params
|
// [RH] Added tag, speed, speed2, height, crush, silent, change params
|
||||||
|
//
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
bool EV_DoCeiling (DCeiling::ECeiling type, line_t *line,
|
bool EV_DoCeiling (DCeiling::ECeiling type, line_t *line,
|
||||||
int tag, fixed_t speed, fixed_t speed2, fixed_t height,
|
int tag, fixed_t speed, fixed_t speed2, fixed_t height,
|
||||||
int crush, int silent, int change, bool hexencrush)
|
int crush, int silent, int change, bool hexencrush)
|
||||||
|
@ -203,10 +473,6 @@ bool EV_DoCeiling (DCeiling::ECeiling type, line_t *line,
|
||||||
int secnum;
|
int secnum;
|
||||||
bool rtn;
|
bool rtn;
|
||||||
sector_t* sec;
|
sector_t* sec;
|
||||||
DCeiling* ceiling;
|
|
||||||
bool manual = false;
|
|
||||||
fixed_t targheight = 0; // Silence, GCC
|
|
||||||
vertex_t* spot;
|
|
||||||
|
|
||||||
rtn = false;
|
rtn = false;
|
||||||
|
|
||||||
|
@ -216,11 +482,10 @@ bool EV_DoCeiling (DCeiling::ECeiling type, line_t *line,
|
||||||
if (!line || !(sec = line->backsector))
|
if (!line || !(sec = line->backsector))
|
||||||
return rtn;
|
return rtn;
|
||||||
secnum = (int)(sec-sectors);
|
secnum = (int)(sec-sectors);
|
||||||
manual = true;
|
|
||||||
// [RH] Hack to let manual crushers be retriggerable, too
|
// [RH] Hack to let manual crushers be retriggerable, too
|
||||||
tag ^= secnum | 0x1000000;
|
tag ^= secnum | 0x1000000;
|
||||||
P_ActivateInStasisCeiling (tag);
|
P_ActivateInStasisCeiling (tag);
|
||||||
goto manual_ceiling;
|
return !!DCeiling::Create(sec, type, line, tag, speed, speed2, height, crush, silent, change, hexencrush);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reactivate in-stasis ceilings...for certain types.
|
// Reactivate in-stasis ceilings...for certain types.
|
||||||
|
@ -234,252 +499,19 @@ bool EV_DoCeiling (DCeiling::ECeiling type, line_t *line,
|
||||||
// affects all sectors with the same tag as the linedef
|
// affects all sectors with the same tag as the linedef
|
||||||
while ((secnum = P_FindSectorFromTag (tag, secnum)) >= 0)
|
while ((secnum = P_FindSectorFromTag (tag, secnum)) >= 0)
|
||||||
{
|
{
|
||||||
sec = §ors[secnum];
|
rtn |= !!DCeiling::Create(§ors[secnum], type, line, tag, speed, speed2, height, crush, silent, change, hexencrush);
|
||||||
manual_ceiling:
|
|
||||||
// if ceiling already moving, don't start a second function on it
|
|
||||||
if (sec->PlaneMoving(sector_t::ceiling))
|
|
||||||
{
|
|
||||||
if (!manual)
|
|
||||||
continue;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// new door thinker
|
|
||||||
rtn = 1;
|
|
||||||
ceiling = new DCeiling (sec, speed, speed2, silent);
|
|
||||||
spot = sec->lines[0]->v1;
|
|
||||||
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case DCeiling::ceilCrushAndRaise:
|
|
||||||
case DCeiling::ceilCrushRaiseAndStay:
|
|
||||||
ceiling->m_TopHeight = sec->ceilingplane.d;
|
|
||||||
case DCeiling::ceilLowerAndCrush:
|
|
||||||
case DCeiling::ceilLowerAndCrushDist:
|
|
||||||
targheight = sec->FindHighestFloorPoint (&spot);
|
|
||||||
if (type == DCeiling::ceilLowerAndCrush)
|
|
||||||
{
|
|
||||||
targheight += 8*FRACUNIT;
|
|
||||||
}
|
|
||||||
else if (type == DCeiling::ceilLowerAndCrushDist)
|
|
||||||
{
|
|
||||||
targheight += height;
|
|
||||||
}
|
|
||||||
ceiling->m_BottomHeight = sec->ceilingplane.PointToDist (spot, targheight);
|
|
||||||
ceiling->m_Direction = -1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DCeiling::ceilRaiseToHighest:
|
|
||||||
targheight = sec->FindHighestCeilingSurrounding (&spot);
|
|
||||||
ceiling->m_TopHeight = sec->ceilingplane.PointToDist (spot, targheight);
|
|
||||||
ceiling->m_Direction = 1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DCeiling::ceilLowerByValue:
|
|
||||||
targheight = sec->ceilingplane.ZatPoint (spot) - height;
|
|
||||||
ceiling->m_BottomHeight = sec->ceilingplane.PointToDist (spot, targheight);
|
|
||||||
ceiling->m_Direction = -1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DCeiling::ceilRaiseByValue:
|
|
||||||
targheight = sec->ceilingplane.ZatPoint (spot) + height;
|
|
||||||
ceiling->m_TopHeight = sec->ceilingplane.PointToDist (spot, targheight);
|
|
||||||
ceiling->m_Direction = 1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DCeiling::ceilMoveToValue:
|
|
||||||
{
|
|
||||||
int diff = height - sec->ceilingplane.ZatPoint (spot);
|
|
||||||
|
|
||||||
targheight = height;
|
|
||||||
if (diff < 0)
|
|
||||||
{
|
|
||||||
ceiling->m_BottomHeight = sec->ceilingplane.PointToDist (spot, height);
|
|
||||||
ceiling->m_Direction = -1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ceiling->m_TopHeight = sec->ceilingplane.PointToDist (spot, height);
|
|
||||||
ceiling->m_Direction = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DCeiling::ceilLowerToHighestFloor:
|
|
||||||
targheight = sec->FindHighestFloorSurrounding (&spot);
|
|
||||||
ceiling->m_BottomHeight = sec->ceilingplane.PointToDist (spot, targheight);
|
|
||||||
ceiling->m_Direction = -1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DCeiling::ceilRaiseToHighestFloor:
|
|
||||||
targheight = sec->FindHighestFloorSurrounding (&spot);
|
|
||||||
ceiling->m_TopHeight = sec->ceilingplane.PointToDist (spot, targheight);
|
|
||||||
ceiling->m_Direction = 1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DCeiling::ceilLowerInstant:
|
|
||||||
targheight = sec->ceilingplane.ZatPoint (spot) - height;
|
|
||||||
ceiling->m_BottomHeight = sec->ceilingplane.PointToDist (spot, targheight);
|
|
||||||
ceiling->m_Direction = -1;
|
|
||||||
ceiling->m_Speed = height;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DCeiling::ceilRaiseInstant:
|
|
||||||
targheight = sec->ceilingplane.ZatPoint (spot) + height;
|
|
||||||
ceiling->m_TopHeight = sec->ceilingplane.PointToDist (spot, targheight);
|
|
||||||
ceiling->m_Direction = 1;
|
|
||||||
ceiling->m_Speed = height;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DCeiling::ceilLowerToNearest:
|
|
||||||
targheight = sec->FindNextLowestCeiling (&spot);
|
|
||||||
ceiling->m_BottomHeight = sec->ceilingplane.PointToDist (spot, targheight);
|
|
||||||
ceiling->m_Direction = -1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DCeiling::ceilRaiseToNearest:
|
|
||||||
targheight = sec->FindNextHighestCeiling (&spot);
|
|
||||||
ceiling->m_TopHeight = sec->ceilingplane.PointToDist (spot, targheight);
|
|
||||||
ceiling->m_Direction = 1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DCeiling::ceilLowerToLowest:
|
|
||||||
targheight = sec->FindLowestCeilingSurrounding (&spot);
|
|
||||||
ceiling->m_BottomHeight = sec->ceilingplane.PointToDist (spot, targheight);
|
|
||||||
ceiling->m_Direction = -1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DCeiling::ceilRaiseToLowest:
|
|
||||||
targheight = sec->FindLowestCeilingSurrounding (&spot);
|
|
||||||
ceiling->m_TopHeight = sec->ceilingplane.PointToDist (spot, targheight);
|
|
||||||
ceiling->m_Direction = 1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DCeiling::ceilLowerToFloor:
|
|
||||||
targheight = sec->FindHighestFloorPoint (&spot);
|
|
||||||
ceiling->m_BottomHeight = sec->ceilingplane.PointToDist (spot, targheight);
|
|
||||||
ceiling->m_Direction = -1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DCeiling::ceilRaiseToFloor: // [RH] What's this for?
|
|
||||||
targheight = sec->FindHighestFloorPoint (&spot);
|
|
||||||
ceiling->m_TopHeight = sec->ceilingplane.PointToDist (spot, targheight);
|
|
||||||
ceiling->m_Direction = 1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DCeiling::ceilLowerToHighest:
|
|
||||||
targheight = sec->FindHighestCeilingSurrounding (&spot);
|
|
||||||
ceiling->m_BottomHeight = sec->ceilingplane.PointToDist (spot, targheight);
|
|
||||||
ceiling->m_Direction = -1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DCeiling::ceilLowerByTexture:
|
|
||||||
targheight = sec->ceilingplane.ZatPoint (spot) - sec->FindShortestUpperAround ();
|
|
||||||
ceiling->m_BottomHeight = sec->ceilingplane.PointToDist (spot, targheight);
|
|
||||||
ceiling->m_Direction = -1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DCeiling::ceilRaiseByTexture:
|
|
||||||
targheight = sec->ceilingplane.ZatPoint (spot) + sec->FindShortestUpperAround ();
|
|
||||||
ceiling->m_TopHeight = sec->ceilingplane.PointToDist (spot, targheight);
|
|
||||||
ceiling->m_Direction = 1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break; // Silence GCC
|
|
||||||
}
|
|
||||||
|
|
||||||
ceiling->m_Tag = tag;
|
|
||||||
ceiling->m_Type = type;
|
|
||||||
ceiling->m_Crush = crush;
|
|
||||||
ceiling->m_Hexencrush = hexencrush;
|
|
||||||
|
|
||||||
// Do not interpolate instant movement ceilings.
|
|
||||||
// Note for ZDoomGL: Check to make sure that you update the sector
|
|
||||||
// after the ceiling moves, because it hasn't actually moved yet.
|
|
||||||
fixed_t movedist;
|
|
||||||
|
|
||||||
if (ceiling->m_Direction < 0)
|
|
||||||
{
|
|
||||||
movedist = sec->ceilingplane.d - ceiling->m_BottomHeight;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
movedist = ceiling->m_TopHeight - sec->ceilingplane.d;
|
|
||||||
}
|
|
||||||
if (ceiling->m_Speed >= movedist)
|
|
||||||
{
|
|
||||||
ceiling->StopInterpolation();
|
|
||||||
}
|
|
||||||
|
|
||||||
// set texture/type change properties
|
|
||||||
if (change & 3) // if a texture change is indicated
|
|
||||||
{
|
|
||||||
if (change & 4) // if a numeric model change
|
|
||||||
{
|
|
||||||
sector_t *modelsec;
|
|
||||||
|
|
||||||
//jff 5/23/98 find model with floor at target height if target
|
|
||||||
//is a floor type
|
|
||||||
modelsec = (/*type == DCeiling::ceilRaiseToHighest ||*/
|
|
||||||
type == DCeiling::ceilRaiseToFloor ||
|
|
||||||
/*type == DCeiling::ceilLowerToHighest ||*/
|
|
||||||
type == DCeiling::ceilLowerToFloor) ?
|
|
||||||
sec->FindModelFloorSector (targheight) :
|
|
||||||
sec->FindModelCeilingSector (targheight);
|
|
||||||
if (modelsec != NULL)
|
|
||||||
{
|
|
||||||
ceiling->m_Texture = modelsec->GetTexture(sector_t::ceiling);
|
|
||||||
switch (change & 3)
|
|
||||||
{
|
|
||||||
case 1: // type is zeroed
|
|
||||||
ceiling->m_NewSpecial = 0;
|
|
||||||
ceiling->m_Type = DCeiling::genCeilingChg0;
|
|
||||||
break;
|
|
||||||
case 2: // type is copied
|
|
||||||
ceiling->m_NewSpecial = sec->special;
|
|
||||||
ceiling->m_Type = DCeiling::genCeilingChgT;
|
|
||||||
break;
|
|
||||||
case 3: // type is left alone
|
|
||||||
ceiling->m_Type = DCeiling::genCeilingChg;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (line) // else if a trigger model change
|
|
||||||
{
|
|
||||||
ceiling->m_Texture = line->frontsector->GetTexture(sector_t::ceiling);
|
|
||||||
switch (change & 3)
|
|
||||||
{
|
|
||||||
case 1: // type is zeroed
|
|
||||||
ceiling->m_NewSpecial = 0;
|
|
||||||
ceiling->m_Type = DCeiling::genCeilingChg0;
|
|
||||||
break;
|
|
||||||
case 2: // type is copied
|
|
||||||
ceiling->m_NewSpecial = line->frontsector->special;
|
|
||||||
ceiling->m_Type = DCeiling::genCeilingChgT;
|
|
||||||
break;
|
|
||||||
case 3: // type is left alone
|
|
||||||
ceiling->m_Type = DCeiling::genCeilingChg;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ceiling->PlayCeilingSound ();
|
|
||||||
|
|
||||||
if (manual)
|
|
||||||
return rtn;
|
|
||||||
}
|
}
|
||||||
return rtn;
|
return rtn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
//
|
//
|
||||||
// Restart a ceiling that's in-stasis
|
// Restart a ceiling that's in-stasis
|
||||||
// [RH] Passed a tag instead of a line and rewritten to use a list
|
// [RH] Passed a tag instead of a line and rewritten to use a list
|
||||||
//
|
//
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
void P_ActivateInStasisCeiling (int tag)
|
void P_ActivateInStasisCeiling (int tag)
|
||||||
{
|
{
|
||||||
DCeiling *scan;
|
DCeiling *scan;
|
||||||
|
@ -495,11 +527,14 @@ void P_ActivateInStasisCeiling (int tag)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
//
|
//
|
||||||
// EV_CeilingCrushStop
|
// EV_CeilingCrushStop
|
||||||
// Stop a ceiling from crushing!
|
// Stop a ceiling from crushing!
|
||||||
// [RH] Passed a tag instead of a line and rewritten to use a list
|
// [RH] Passed a tag instead of a line and rewritten to use a list
|
||||||
//
|
//
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
bool EV_CeilingCrushStop (int tag)
|
bool EV_CeilingCrushStop (int tag)
|
||||||
{
|
{
|
||||||
bool rtn = false;
|
bool rtn = false;
|
||||||
|
|
119
src/p_doors.cpp
119
src/p_doors.cpp
|
@ -36,6 +36,12 @@
|
||||||
#include "sc_man.h"
|
#include "sc_man.h"
|
||||||
#include "cmdlib.h"
|
#include "cmdlib.h"
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// VERTICAL DOORS
|
||||||
|
//
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
IMPLEMENT_CLASS (DDoor)
|
IMPLEMENT_CLASS (DDoor)
|
||||||
|
|
||||||
DDoor::DDoor ()
|
DDoor::DDoor ()
|
||||||
|
@ -55,14 +61,12 @@ void DDoor::Serialize (FArchive &arc)
|
||||||
<< m_LightTag;
|
<< m_LightTag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
//
|
|
||||||
// VERTICAL DOORS
|
|
||||||
//
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// T_VerticalDoor
|
// T_VerticalDoor
|
||||||
//
|
//
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
void DDoor::Tick ()
|
void DDoor::Tick ()
|
||||||
{
|
{
|
||||||
EResult res;
|
EResult res;
|
||||||
|
@ -215,7 +219,12 @@ void DDoor::Tick ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
// [RH] DoorSound: Plays door sound depending on direction and speed
|
// [RH] DoorSound: Plays door sound depending on direction and speed
|
||||||
|
//
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
void DDoor::DoorSound (bool raise) const
|
void DDoor::DoorSound (bool raise) const
|
||||||
{
|
{
|
||||||
int choice;
|
int choice;
|
||||||
|
@ -309,10 +318,12 @@ DDoor::DDoor (sector_t *sector)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// [RH] Merged EV_VerticalDoor and EV_DoLockedDoor into EV_DoDoor
|
//============================================================================
|
||||||
// and made them more general to support the new specials.
|
//
|
||||||
|
|
||||||
// [RH] SpawnDoor: Helper function for EV_DoDoor
|
// [RH] SpawnDoor: Helper function for EV_DoDoor
|
||||||
|
//
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
DDoor::DDoor (sector_t *sec, EVlDoor type, fixed_t speed, int delay, int lightTag)
|
DDoor::DDoor (sector_t *sec, EVlDoor type, fixed_t speed, int delay, int lightTag)
|
||||||
: DMovingCeiling (sec),
|
: DMovingCeiling (sec),
|
||||||
m_Type (type), m_Speed (speed), m_TopWait (delay), m_LightTag (lightTag)
|
m_Type (type), m_Speed (speed), m_TopWait (delay), m_LightTag (lightTag)
|
||||||
|
@ -371,6 +382,13 @@ DDoor::DDoor (sector_t *sec, EVlDoor type, fixed_t speed, int delay, int lightTa
|
||||||
m_OldFloorDist = sec->floorplane.d;
|
m_OldFloorDist = sec->floorplane.d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// [RH] Merged EV_VerticalDoor and EV_DoLockedDoor into EV_DoDoor
|
||||||
|
// and made them more general to support the new specials.
|
||||||
|
//
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
bool EV_DoDoor (DDoor::EVlDoor type, line_t *line, AActor *thing,
|
bool EV_DoDoor (DDoor::EVlDoor type, line_t *line, AActor *thing,
|
||||||
int tag, int speed, int delay, int lock, int lightTag)
|
int tag, int speed, int delay, int lock, int lightTag)
|
||||||
{
|
{
|
||||||
|
@ -464,10 +482,12 @@ bool EV_DoDoor (DDoor::EVlDoor type, line_t *line, AActor *thing,
|
||||||
return rtn;
|
return rtn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
//
|
//
|
||||||
// Spawn a door that closes after 30 seconds
|
// Spawn a door that closes after 30 seconds
|
||||||
//
|
//
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
void P_SpawnDoorCloseIn30 (sector_t *sec)
|
void P_SpawnDoorCloseIn30 (sector_t *sec)
|
||||||
{
|
{
|
||||||
fixed_t height;
|
fixed_t height;
|
||||||
|
@ -487,18 +507,56 @@ void P_SpawnDoorCloseIn30 (sector_t *sec)
|
||||||
door->m_LightTag = 0;
|
door->m_LightTag = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
//
|
//
|
||||||
// Spawn a door that opens after 5 minutes
|
// Spawn a door that opens after 5 minutes
|
||||||
//
|
//
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
void P_SpawnDoorRaiseIn5Mins (sector_t *sec)
|
void P_SpawnDoorRaiseIn5Mins (sector_t *sec)
|
||||||
{
|
{
|
||||||
sec->special = 0;
|
sec->special = 0;
|
||||||
new DDoor (sec, DDoor::doorRaiseIn5Mins, 2*FRACUNIT, TICRATE*30/7, 0);
|
new DDoor (sec, DDoor::doorRaiseIn5Mins, 2*FRACUNIT, TICRATE*30/7, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// EV_SlidingDoor : slide a door horizontally
|
|
||||||
// (animate midtexture, then set noblocking line)
|
//============================================================================
|
||||||
//
|
//
|
||||||
|
// animated doors
|
||||||
|
//
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
IMPLEMENT_CLASS (DAnimatedDoor)
|
||||||
|
|
||||||
|
DAnimatedDoor::DAnimatedDoor ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
DAnimatedDoor::DAnimatedDoor (sector_t *sec)
|
||||||
|
: DMovingCeiling (sec)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void DAnimatedDoor::Serialize (FArchive &arc)
|
||||||
|
{
|
||||||
|
Super::Serialize (arc);
|
||||||
|
|
||||||
|
arc << m_Line1 << m_Line2
|
||||||
|
<< m_Frame
|
||||||
|
<< m_Timer
|
||||||
|
<< m_BotDist
|
||||||
|
<< m_Status
|
||||||
|
<< m_Speed
|
||||||
|
<< m_Delay
|
||||||
|
<< m_DoorAnim
|
||||||
|
<< m_SetBlocking1 << m_SetBlocking2;
|
||||||
|
}
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// Starts a closing action on an animated door
|
||||||
|
//
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
bool DAnimatedDoor::StartClosing ()
|
bool DAnimatedDoor::StartClosing ()
|
||||||
{
|
{
|
||||||
|
@ -528,6 +586,12 @@ bool DAnimatedDoor::StartClosing ()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
void DAnimatedDoor::Tick ()
|
void DAnimatedDoor::Tick ()
|
||||||
{
|
{
|
||||||
if (m_DoorAnim == NULL)
|
if (m_DoorAnim == NULL)
|
||||||
|
@ -624,31 +688,11 @@ void DAnimatedDoor::Tick ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IMPLEMENT_CLASS (DAnimatedDoor)
|
//============================================================================
|
||||||
|
//
|
||||||
DAnimatedDoor::DAnimatedDoor ()
|
//
|
||||||
{
|
//
|
||||||
}
|
//============================================================================
|
||||||
|
|
||||||
DAnimatedDoor::DAnimatedDoor (sector_t *sec)
|
|
||||||
: DMovingCeiling (sec)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void DAnimatedDoor::Serialize (FArchive &arc)
|
|
||||||
{
|
|
||||||
Super::Serialize (arc);
|
|
||||||
|
|
||||||
arc << m_Line1 << m_Line2
|
|
||||||
<< m_Frame
|
|
||||||
<< m_Timer
|
|
||||||
<< m_BotDist
|
|
||||||
<< m_Status
|
|
||||||
<< m_Speed
|
|
||||||
<< m_Delay
|
|
||||||
<< m_DoorAnim
|
|
||||||
<< m_SetBlocking1 << m_SetBlocking2;
|
|
||||||
}
|
|
||||||
|
|
||||||
DAnimatedDoor::DAnimatedDoor (sector_t *sec, line_t *line, int speed, int delay, FDoorAnimation *anim)
|
DAnimatedDoor::DAnimatedDoor (sector_t *sec, line_t *line, int speed, int delay, FDoorAnimation *anim)
|
||||||
: DMovingCeiling (sec)
|
: DMovingCeiling (sec)
|
||||||
|
@ -706,7 +750,8 @@ DAnimatedDoor::DAnimatedDoor (sector_t *sec, line_t *line, int speed, int delay,
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
//
|
//
|
||||||
// EV_SlidingDoor
|
// EV_SlidingDoor : slide a door horizontally
|
||||||
|
// (animate midtexture, then set noblocking line)
|
||||||
//
|
//
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
|
|
|
@ -1223,6 +1223,7 @@ static void CreateCachedNodes(MapData *map)
|
||||||
FILE *f = fopen(path, "wb");
|
FILE *f = fopen(path, "wb");
|
||||||
fwrite(compressed, 1, outlen+offset, f);
|
fwrite(compressed, 1, outlen+offset, f);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
delete [] compressed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -81,7 +81,6 @@ static void PlayerLandedOnThing (AActor *mo, AActor *onmobj);
|
||||||
|
|
||||||
extern cycle_t BotSupportCycles;
|
extern cycle_t BotSupportCycles;
|
||||||
extern int BotWTG;
|
extern int BotWTG;
|
||||||
EXTERN_CVAR (Bool, r_drawfuzz);
|
|
||||||
EXTERN_CVAR (Int, cl_rockettrails)
|
EXTERN_CVAR (Int, cl_rockettrails)
|
||||||
|
|
||||||
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
||||||
|
|
|
@ -2519,10 +2519,10 @@ void P_LoadSideDefs2 (MapData * map)
|
||||||
// as possible from its ZDBSP incarnation.
|
// as possible from its ZDBSP incarnation.
|
||||||
//
|
//
|
||||||
|
|
||||||
static unsigned int BlockHash (TArray<WORD> *block)
|
static unsigned int BlockHash (TArray<int> *block)
|
||||||
{
|
{
|
||||||
int hash = 0;
|
int hash = 0;
|
||||||
WORD *ar = &(*block)[0];
|
int *ar = &(*block)[0];
|
||||||
for (size_t i = 0; i < block->Size(); ++i)
|
for (size_t i = 0; i < block->Size(); ++i)
|
||||||
{
|
{
|
||||||
hash = hash * 12235 + ar[i];
|
hash = hash * 12235 + ar[i];
|
||||||
|
@ -2530,7 +2530,7 @@ static unsigned int BlockHash (TArray<WORD> *block)
|
||||||
return hash & 0x7fffffff;
|
return hash & 0x7fffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool BlockCompare (TArray<WORD> *block1, TArray<WORD> *block2)
|
static bool BlockCompare (TArray<int> *block1, TArray<int> *block2)
|
||||||
{
|
{
|
||||||
size_t size = block1->Size();
|
size_t size = block1->Size();
|
||||||
|
|
||||||
|
@ -2542,8 +2542,8 @@ static bool BlockCompare (TArray<WORD> *block1, TArray<WORD> *block2)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
WORD *ar1 = &(*block1)[0];
|
int *ar1 = &(*block1)[0];
|
||||||
WORD *ar2 = &(*block2)[0];
|
int *ar2 = &(*block2)[0];
|
||||||
for (size_t i = 0; i < size; ++i)
|
for (size_t i = 0; i < size; ++i)
|
||||||
{
|
{
|
||||||
if (ar1[i] != ar2[i])
|
if (ar1[i] != ar2[i])
|
||||||
|
@ -2554,20 +2554,20 @@ static bool BlockCompare (TArray<WORD> *block1, TArray<WORD> *block2)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CreatePackedBlockmap (TArray<int> &BlockMap, TArray<WORD> *blocks, int bmapwidth, int bmapheight)
|
static void CreatePackedBlockmap (TArray<int> &BlockMap, TArray<int> *blocks, int bmapwidth, int bmapheight)
|
||||||
{
|
{
|
||||||
int buckets[4096];
|
int buckets[4096];
|
||||||
int *hashes, hashblock;
|
int *hashes, hashblock;
|
||||||
TArray<WORD> *block;
|
TArray<int> *block;
|
||||||
int zero = 0;
|
int zero = 0;
|
||||||
int terminator = -1;
|
int terminator = -1;
|
||||||
WORD *array;
|
int *array;
|
||||||
int i, hash;
|
int i, hash;
|
||||||
int hashed = 0, nothashed = 0;
|
int hashed = 0, nothashed = 0;
|
||||||
|
|
||||||
hashes = new int[bmapwidth * bmapheight];
|
hashes = new int[bmapwidth * bmapheight];
|
||||||
|
|
||||||
memset (hashes, 0xff, sizeof(WORD)*bmapwidth*bmapheight);
|
memset (hashes, 0xff, sizeof(int)*bmapwidth*bmapheight);
|
||||||
memset (buckets, 0xff, sizeof(buckets));
|
memset (buckets, 0xff, sizeof(buckets));
|
||||||
|
|
||||||
for (i = 0; i < bmapwidth * bmapheight; ++i)
|
for (i = 0; i < bmapwidth * bmapheight; ++i)
|
||||||
|
@ -2614,12 +2614,12 @@ static void CreatePackedBlockmap (TArray<int> &BlockMap, TArray<WORD> *blocks, i
|
||||||
|
|
||||||
static void P_CreateBlockMap ()
|
static void P_CreateBlockMap ()
|
||||||
{
|
{
|
||||||
TArray<WORD> *BlockLists, *block, *endblock;
|
TArray<int> *BlockLists, *block, *endblock;
|
||||||
WORD adder;
|
int adder;
|
||||||
int bmapwidth, bmapheight;
|
int bmapwidth, bmapheight;
|
||||||
int minx, maxx, miny, maxy;
|
int minx, maxx, miny, maxy;
|
||||||
int i;
|
int i;
|
||||||
WORD line;
|
int line;
|
||||||
|
|
||||||
if (numvertexes <= 0)
|
if (numvertexes <= 0)
|
||||||
return;
|
return;
|
||||||
|
@ -2651,7 +2651,7 @@ static void P_CreateBlockMap ()
|
||||||
adder = bmapwidth; BlockMap.Push (adder);
|
adder = bmapwidth; BlockMap.Push (adder);
|
||||||
adder = bmapheight; BlockMap.Push (adder);
|
adder = bmapheight; BlockMap.Push (adder);
|
||||||
|
|
||||||
BlockLists = new TArray<WORD>[bmapwidth * bmapheight];
|
BlockLists = new TArray<int>[bmapwidth * bmapheight];
|
||||||
|
|
||||||
for (line = 0; line < numlines; ++line)
|
for (line = 0; line < numlines; ++line)
|
||||||
{
|
{
|
||||||
|
|
|
@ -921,39 +921,6 @@ static bool SpreadCeilingPortal(AStackPoint *pt, fixed_t alpha, sector_t *sector
|
||||||
return fail;
|
return fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool SpreadFloorPortal(AStackPoint *pt, fixed_t alpha, sector_t *sector)
|
|
||||||
{
|
|
||||||
bool fail = false;
|
|
||||||
sector->validcount = validcount;
|
|
||||||
for(int i=0; i<sector->linecount; i++)
|
|
||||||
{
|
|
||||||
line_t *line = sector->lines[i];
|
|
||||||
sector_t *backsector = sector == line->frontsector? line->backsector : line->frontsector;
|
|
||||||
if (line->backsector == line->frontsector) continue;
|
|
||||||
if (backsector == NULL) { fail = true; continue; }
|
|
||||||
if (backsector->validcount == validcount) continue;
|
|
||||||
if (backsector->FloorSkyBox == pt) continue;
|
|
||||||
|
|
||||||
// Check if the backside would map to the same visplane
|
|
||||||
if (backsector->FloorSkyBox != NULL) { fail = true; continue; }
|
|
||||||
if (backsector->floorplane != sector->ceilingplane) { fail = true; continue; }
|
|
||||||
if (backsector->lightlevel != sector->lightlevel) { fail = true; continue; }
|
|
||||||
if (backsector->GetTexture(sector_t::floor) != sector->GetTexture(sector_t::floor)) { fail = true; continue; }
|
|
||||||
if (backsector->GetXOffset(sector_t::floor) != sector->GetXOffset(sector_t::floor)) { fail = true; continue; }
|
|
||||||
if (backsector->GetYOffset(sector_t::floor) != sector->GetYOffset(sector_t::floor)) { fail = true; continue; }
|
|
||||||
if (backsector->GetXScale(sector_t::floor) != sector->GetXScale(sector_t::floor)) { fail = true; continue; }
|
|
||||||
if (backsector->GetYScale(sector_t::floor) != sector->GetYScale(sector_t::floor)) { fail = true; continue; }
|
|
||||||
if (backsector->GetAngle(sector_t::floor) != sector->GetAngle(sector_t::floor)) { fail = true; continue; }
|
|
||||||
if (SpreadFloorPortal(pt, alpha, backsector)) { fail = true; continue; }
|
|
||||||
}
|
|
||||||
if (!fail)
|
|
||||||
{
|
|
||||||
sector->FloorSkyBox = pt;
|
|
||||||
sector->SetAlpha(sector_t::floor, alpha);
|
|
||||||
}
|
|
||||||
return fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
void P_SetupPortals()
|
void P_SetupPortals()
|
||||||
{
|
{
|
||||||
TThinkerIterator<AStackPoint> it;
|
TThinkerIterator<AStackPoint> it;
|
||||||
|
@ -974,51 +941,6 @@ void P_SetupPortals()
|
||||||
pt->special1 = 0;
|
pt->special1 = 0;
|
||||||
points.Push(pt);
|
points.Push(pt);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Maps using undefined portal hacks may not benefit from portal optimizations.
|
|
||||||
if (ib_compatflags & BCOMPATF_BADPORTALS) return;
|
|
||||||
|
|
||||||
for(unsigned i=0;i<points.Size(); i++)
|
|
||||||
{
|
|
||||||
if (points[i]->special1 == 0 && points[i]->Mate != NULL)
|
|
||||||
{
|
|
||||||
for(unsigned j=1;j<points.Size(); j++)
|
|
||||||
{
|
|
||||||
if (points[j]->special1 == 0 && points[j]->Mate != NULL && points[i]->GetClass() == points[j]->GetClass())
|
|
||||||
{
|
|
||||||
fixed_t deltax1 = points[i]->Mate->x - points[i]->x;
|
|
||||||
fixed_t deltay1 = points[i]->Mate->y - points[i]->y;
|
|
||||||
fixed_t deltax2 = points[j]->Mate->x - points[j]->x;
|
|
||||||
fixed_t deltay2 = points[j]->Mate->y - points[j]->y;
|
|
||||||
|
|
||||||
if (deltax1 == deltax2 && deltay1 == deltay2)
|
|
||||||
{
|
|
||||||
if (points[j]->Sector->FloorSkyBox == points[j]->Mate)
|
|
||||||
points[j]->Sector->FloorSkyBox = points[i]->Mate;
|
|
||||||
|
|
||||||
if (points[j]->Sector->CeilingSkyBox == points[j]->Mate)
|
|
||||||
points[j]->Sector->CeilingSkyBox = points[i]->Mate;
|
|
||||||
|
|
||||||
points[j]->special1 = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
validcount++;
|
|
||||||
// Some fudging to preserve an unintended 'portal bleeding' effect caused by incomplete checks in the rendering code.
|
|
||||||
// Due to the addition of linedef-based portals this effect no longer works.
|
|
||||||
for(int i=0;i<numsectors; i++)
|
|
||||||
{
|
|
||||||
if (sectors[i].CeilingSkyBox != NULL && sectors[i].CeilingSkyBox->bAlways && sectors[i].validcount != validcount)
|
|
||||||
{
|
|
||||||
SpreadCeilingPortal(barrier_cast<AStackPoint*>(sectors[i].CeilingSkyBox), sectors[i].GetAlpha(sector_t::ceiling), §ors[i]);
|
|
||||||
}
|
|
||||||
if (sectors[i].FloorSkyBox != NULL && sectors[i].FloorSkyBox->bAlways && sectors[i].validcount != validcount)
|
|
||||||
{
|
|
||||||
SpreadFloorPortal(barrier_cast<AStackPoint*>(sectors[i].FloorSkyBox), sectors[i].GetAlpha(sector_t::floor), §ors[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void SetPortal(sector_t *sector, int plane, AStackPoint *portal, fixed_t alpha)
|
inline void SetPortal(sector_t *sector, int plane, AStackPoint *portal, fixed_t alpha)
|
||||||
|
|
|
@ -677,6 +677,10 @@ public:
|
||||||
void Serialize (FArchive &arc);
|
void Serialize (FArchive &arc);
|
||||||
void Tick ();
|
void Tick ();
|
||||||
|
|
||||||
|
static DCeiling *Create(sector_t *sec, DCeiling::ECeiling type, line_t *line, int tag,
|
||||||
|
fixed_t speed, fixed_t speed2, fixed_t height,
|
||||||
|
int crush, int silent, int change, bool hexencrush);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ECeiling m_Type;
|
ECeiling m_Type;
|
||||||
fixed_t m_BottomHeight;
|
fixed_t m_BottomHeight;
|
||||||
|
@ -702,9 +706,6 @@ protected:
|
||||||
private:
|
private:
|
||||||
DCeiling ();
|
DCeiling ();
|
||||||
|
|
||||||
friend bool EV_DoCeiling (DCeiling::ECeiling type, line_t *line,
|
|
||||||
int tag, fixed_t speed, fixed_t speed2, fixed_t height,
|
|
||||||
int crush, int silent, int change, bool hexencrush);
|
|
||||||
friend bool EV_CeilingCrushStop (int tag);
|
friend bool EV_CeilingCrushStop (int tag);
|
||||||
friend void P_ActivateInStasisCeiling (int tag);
|
friend void P_ActivateInStasisCeiling (int tag);
|
||||||
};
|
};
|
||||||
|
|
|
@ -432,7 +432,8 @@ void APlayerPawn::Serialize (FArchive &arc)
|
||||||
<< InvSel
|
<< InvSel
|
||||||
<< MorphWeapon
|
<< MorphWeapon
|
||||||
<< DamageFade
|
<< DamageFade
|
||||||
<< PlayerFlags;
|
<< PlayerFlags
|
||||||
|
<< FlechetteType;
|
||||||
}
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
|
@ -48,6 +48,7 @@ enum ERenderStyle
|
||||||
STYLE_Add, // Draw additive
|
STYLE_Add, // Draw additive
|
||||||
STYLE_Shaded, // Treat patch data as alpha values for alphacolor
|
STYLE_Shaded, // Treat patch data as alpha values for alphacolor
|
||||||
STYLE_TranslucentStencil,
|
STYLE_TranslucentStencil,
|
||||||
|
STYLE_Shadow,
|
||||||
|
|
||||||
STYLE_Count
|
STYLE_Count
|
||||||
};
|
};
|
||||||
|
@ -63,6 +64,9 @@ enum ERenderOp
|
||||||
STYLEOP_FuzzOrAdd, // Draw fuzzy or add, based on user preference
|
STYLEOP_FuzzOrAdd, // Draw fuzzy or add, based on user preference
|
||||||
STYLEOP_FuzzOrSub, // Draw fuzzy or subtract, based on user preference
|
STYLEOP_FuzzOrSub, // Draw fuzzy or subtract, based on user preference
|
||||||
STYLEOP_FuzzOrRevSub, // Draw fuzzy or reverse subtract, based on user preference
|
STYLEOP_FuzzOrRevSub, // Draw fuzzy or reverse subtract, based on user preference
|
||||||
|
|
||||||
|
// special styles
|
||||||
|
STYLEOP_Shadow,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ERenderAlpha
|
enum ERenderAlpha
|
||||||
|
|
304
src/r_data.cpp
304
src/r_data.cpp
|
@ -355,6 +355,304 @@ const BYTE *R_GetColumn (FTexture *tex, int col)
|
||||||
return tex->GetColumn (col, NULL);
|
return tex->GetColumn (col, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// GetVoxelRemap
|
||||||
|
//
|
||||||
|
// Calculates a remap table for the voxel's palette. Results are cached so
|
||||||
|
// passing the same palette repeatedly will not require repeated
|
||||||
|
// recalculations.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
static BYTE *GetVoxelRemap(const BYTE *pal)
|
||||||
|
{
|
||||||
|
static BYTE remap[256];
|
||||||
|
static BYTE oldpal[768];
|
||||||
|
static bool firsttime = true;
|
||||||
|
|
||||||
|
if (firsttime || memcmp(oldpal, pal, 768) != 0)
|
||||||
|
{ // Not the same palette as last time, so recalculate.
|
||||||
|
firsttime = false;
|
||||||
|
memcpy(oldpal, pal, 768);
|
||||||
|
for (int i = 0; i < 256; ++i)
|
||||||
|
{
|
||||||
|
// The voxel palette uses VGA colors, so we have to expand it
|
||||||
|
// from 6 to 8 bits per component.
|
||||||
|
remap[i] = BestColor((uint32 *)GPalette.BaseColors,
|
||||||
|
(oldpal[i*3 + 0] << 2) | (oldpal[i*3 + 0] >> 4),
|
||||||
|
(oldpal[i*3 + 1] << 2) | (oldpal[i*3 + 1] >> 4),
|
||||||
|
(oldpal[i*3 + 2] << 2) | (oldpal[i*3 + 2] >> 4));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return remap;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// CopyVoxelSlabs
|
||||||
|
//
|
||||||
|
// Copy all the slabs in a block of slabs.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
static bool CopyVoxelSlabs(kvxslab_t *dest, const kvxslab_t *src, int size)
|
||||||
|
{
|
||||||
|
while (size >= 3)
|
||||||
|
{
|
||||||
|
int slabzleng = src->zleng;
|
||||||
|
|
||||||
|
if (3 + slabzleng > size)
|
||||||
|
{ // slab is too tall
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
dest->ztop = src->ztop;
|
||||||
|
dest->zleng = src->zleng;
|
||||||
|
dest->backfacecull = src->backfacecull;
|
||||||
|
|
||||||
|
for (int j = 0; j < slabzleng; ++j)
|
||||||
|
{
|
||||||
|
dest->col[j] = src->col[j];
|
||||||
|
}
|
||||||
|
slabzleng += 3;
|
||||||
|
src = (kvxslab_t *)((BYTE *)src + slabzleng);
|
||||||
|
dest = (kvxslab_t *)((BYTE *)dest + slabzleng);
|
||||||
|
size -= slabzleng;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// RemapVoxelSlabs
|
||||||
|
//
|
||||||
|
// Remaps all the slabs in a block of slabs.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
static void RemapVoxelSlabs(kvxslab_t *dest, int size, const BYTE *remap)
|
||||||
|
{
|
||||||
|
while (size >= 3)
|
||||||
|
{
|
||||||
|
int slabzleng = dest->zleng;
|
||||||
|
|
||||||
|
for (int j = 0; j < slabzleng; ++j)
|
||||||
|
{
|
||||||
|
dest->col[j] = remap[dest->col[j]];
|
||||||
|
}
|
||||||
|
slabzleng += 3;
|
||||||
|
dest = (kvxslab_t *)((BYTE *)dest + slabzleng);
|
||||||
|
size -= slabzleng;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// R_LoadKVX
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
FVoxel *R_LoadKVX(int lumpnum)
|
||||||
|
{
|
||||||
|
const kvxslab_t *slabs[MAXVOXMIPS];
|
||||||
|
FVoxel *voxel = new FVoxel;
|
||||||
|
const BYTE *rawmip;
|
||||||
|
int mip, maxmipsize;
|
||||||
|
int i, j, n;
|
||||||
|
|
||||||
|
FMemLump lump = Wads.ReadLump(lumpnum); // FMemLump adds an extra 0 byte to the end.
|
||||||
|
BYTE *rawvoxel = (BYTE *)lump.GetMem();
|
||||||
|
int voxelsize = (int)(lump.GetSize()-1);
|
||||||
|
|
||||||
|
// Oh, KVX, why couldn't you have a proper header? We'll just go through
|
||||||
|
// and collect each MIP level, doing lots of range checking, and if the
|
||||||
|
// last one doesn't end exactly 768 bytes before the end of the file,
|
||||||
|
// we'll reject it.
|
||||||
|
|
||||||
|
for (mip = 0, rawmip = rawvoxel, maxmipsize = voxelsize - 768 - 4;
|
||||||
|
mip < MAXVOXMIPS;
|
||||||
|
mip++)
|
||||||
|
{
|
||||||
|
int numbytes = GetInt(rawmip);
|
||||||
|
if (numbytes > maxmipsize || numbytes < 24)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
rawmip += 4;
|
||||||
|
|
||||||
|
FVoxelMipLevel *mipl = &voxel->Mips[mip];
|
||||||
|
|
||||||
|
// Load header data.
|
||||||
|
mipl->SizeX = GetInt(rawmip + 0);
|
||||||
|
mipl->SizeY = GetInt(rawmip + 4);
|
||||||
|
mipl->SizeZ = GetInt(rawmip + 8);
|
||||||
|
mipl->PivotX = GetInt(rawmip + 12);
|
||||||
|
mipl->PivotY = GetInt(rawmip + 16);
|
||||||
|
mipl->PivotZ = GetInt(rawmip + 20);
|
||||||
|
|
||||||
|
// How much space do we have for voxdata?
|
||||||
|
int offsetsize = (mipl->SizeX + 1) * 4 + mipl->SizeX * (mipl->SizeY + 1) * 2;
|
||||||
|
int voxdatasize = numbytes - 24 - offsetsize;
|
||||||
|
if (voxdatasize < 0)
|
||||||
|
{ // Clearly, not enough.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (voxdatasize == 0)
|
||||||
|
{ // This mip level is empty.
|
||||||
|
goto nextmip;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate slab data space.
|
||||||
|
mipl->OffsetX = new int[(numbytes - 24 + 3) / 4];
|
||||||
|
mipl->OffsetXY = (short *)(mipl->OffsetX + mipl->SizeX + 1);
|
||||||
|
mipl->SlabData = (BYTE *)(mipl->OffsetXY + mipl->SizeX * (mipl->SizeY + 1));
|
||||||
|
|
||||||
|
// Load x offsets.
|
||||||
|
for (i = 0, n = mipl->SizeX; i <= n; ++i)
|
||||||
|
{
|
||||||
|
// The X offsets stored in the KVX file are relative to the start of the
|
||||||
|
// X offsets array. Make them relative to voxdata instead.
|
||||||
|
mipl->OffsetX[i] = GetInt(rawmip + 24 + i * 4) - offsetsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The first X offset must be 0 (since we subtracted offsetsize), according to the spec:
|
||||||
|
// NOTE: xoffset[0] = (xsiz+1)*4 + xsiz*(ysiz+1)*2 (ALWAYS)
|
||||||
|
if (mipl->OffsetX[0] != 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// And the final X offset must point just past the end of the voxdata.
|
||||||
|
if (mipl->OffsetX[mipl->SizeX] != voxdatasize)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load xy offsets.
|
||||||
|
i = 24 + i * 4;
|
||||||
|
for (j = 0, n *= mipl->SizeY + 1; j < n; ++j)
|
||||||
|
{
|
||||||
|
mipl->OffsetXY[j] = GetShort(rawmip + i + j * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure all offsets are within bounds.
|
||||||
|
for (i = 0; i < mipl->SizeX; ++i)
|
||||||
|
{
|
||||||
|
int xoff = mipl->OffsetX[i];
|
||||||
|
for (j = 0; j < mipl->SizeY; ++j)
|
||||||
|
{
|
||||||
|
int yoff = mipl->OffsetXY[(mipl->SizeY + 1) * i + j];
|
||||||
|
if (unsigned(xoff + yoff) > unsigned(voxdatasize))
|
||||||
|
{
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Record slab location for the end.
|
||||||
|
slabs[mip] = (kvxslab_t *)(rawmip + 24 + offsetsize);
|
||||||
|
|
||||||
|
// Time for the next mip Level.
|
||||||
|
nextmip:
|
||||||
|
rawmip += numbytes;
|
||||||
|
maxmipsize -= numbytes + 4;
|
||||||
|
}
|
||||||
|
// Did we get any mip levels, and if so, does the last one leave just
|
||||||
|
// enough room for the palette after it?
|
||||||
|
if (mip == 0 || rawmip != rawvoxel + voxelsize - 768)
|
||||||
|
{
|
||||||
|
bad: delete voxel;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do not count empty mips at the end.
|
||||||
|
for (; mip > 0; --mip)
|
||||||
|
{
|
||||||
|
if (voxel->Mips[mip - 1].SlabData != NULL)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
voxel->NumMips = mip;
|
||||||
|
|
||||||
|
for (i = 0; i < mip; ++i)
|
||||||
|
{
|
||||||
|
if (!CopyVoxelSlabs((kvxslab_t *)voxel->Mips[i].SlabData, slabs[i], voxel->Mips[i].OffsetX[voxel->Mips[i].SizeX]))
|
||||||
|
{ // Invalid slabs encountered. Reject this voxel.
|
||||||
|
delete voxel;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
voxel->LumpNum = lumpnum;
|
||||||
|
voxel->Palette = new BYTE[768];
|
||||||
|
memcpy(voxel->Palette, rawvoxel + voxelsize - 768, 768);
|
||||||
|
|
||||||
|
return voxel;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FVoxelMipLevel Constructor
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
FVoxelMipLevel::FVoxelMipLevel()
|
||||||
|
{
|
||||||
|
SizeZ = SizeY = SizeX = 0;
|
||||||
|
PivotZ = PivotY = PivotX = 0;
|
||||||
|
OffsetX = NULL;
|
||||||
|
OffsetXY = NULL;
|
||||||
|
SlabData = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FVoxelMipLevel Destructor
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
FVoxelMipLevel::~FVoxelMipLevel()
|
||||||
|
{
|
||||||
|
if (OffsetX != NULL)
|
||||||
|
{
|
||||||
|
delete[] OffsetX;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FVoxel Constructor
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
FVoxel::FVoxel()
|
||||||
|
{
|
||||||
|
Palette = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
FVoxel::~FVoxel()
|
||||||
|
{
|
||||||
|
if (Palette != NULL) delete [] Palette;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// Remap the voxel to the game palette
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void FVoxel::Remap()
|
||||||
|
{
|
||||||
|
if (Palette != NULL)
|
||||||
|
{
|
||||||
|
BYTE *remap = GetVoxelRemap(Palette);
|
||||||
|
for (int i = 0; i < NumMips; ++i)
|
||||||
|
{
|
||||||
|
RemapVoxelSlabs((kvxslab_t *)Mips[i].SlabData, Mips[i].OffsetX[Mips[i].SizeX], remap);
|
||||||
|
}
|
||||||
|
delete [] Palette;
|
||||||
|
Palette = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
|
@ -389,10 +687,4 @@ CCMD (printspans)
|
||||||
Printf ("\n");
|
Printf ("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CCMD (picnum)
|
|
||||||
{
|
|
||||||
//int picnum = TexMan.GetTexture (argv[1], FTexture::TEX_Any);
|
|
||||||
//Printf ("%d: %s - %s\n", picnum, TexMan[picnum]->Name, TexMan(picnum)->Name);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -144,4 +144,6 @@ extern size_t numfakecmaps;
|
||||||
|
|
||||||
int R_FindSkin (const char *name, int pclass); // [RH] Find a skin
|
int R_FindSkin (const char *name, int pclass); // [RH] Find a skin
|
||||||
|
|
||||||
|
FVoxel *R_LoadKVX(int lumpnum);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
95
src/r_defs.h
95
src/r_defs.h
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
#include "doomdef.h"
|
#include "doomdef.h"
|
||||||
#include "templates.h"
|
#include "templates.h"
|
||||||
|
#include "memarena.h"
|
||||||
|
|
||||||
// Some more or less basic data types
|
// Some more or less basic data types
|
||||||
// we depend on.
|
// we depend on.
|
||||||
|
@ -1038,7 +1039,6 @@ struct column_t
|
||||||
|
|
||||||
typedef BYTE lighttable_t; // This could be wider for >8 bit display.
|
typedef BYTE lighttable_t; // This could be wider for >8 bit display.
|
||||||
|
|
||||||
|
|
||||||
// A vissprite_t is a thing
|
// A vissprite_t is a thing
|
||||||
// that will be drawn during a refresh.
|
// that will be drawn during a refresh.
|
||||||
// I.e. a sprite object that is partly visible.
|
// I.e. a sprite object that is partly visible.
|
||||||
|
@ -1046,8 +1046,9 @@ struct vissprite_t
|
||||||
{
|
{
|
||||||
short x1, x2;
|
short x1, x2;
|
||||||
fixed_t cx; // for line side calculation
|
fixed_t cx; // for line side calculation
|
||||||
fixed_t gx, gy; // for drawseg and fake floor clipping
|
fixed_t gx, gy, gz; // origin in world coordinates
|
||||||
fixed_t gz, gzt; // global bottom / top for silhouette clipping
|
angle_t angle;
|
||||||
|
fixed_t gzb, gzt; // global bottom / top for silhouette clipping
|
||||||
fixed_t startfrac; // horizontal position of x1
|
fixed_t startfrac; // horizontal position of x1
|
||||||
fixed_t xscale, yscale;
|
fixed_t xscale, yscale;
|
||||||
fixed_t xiscale; // negative if flipped
|
fixed_t xiscale; // negative if flipped
|
||||||
|
@ -1060,12 +1061,17 @@ struct vissprite_t
|
||||||
sector_t *sector; // [RH] sector this sprite is in
|
sector_t *sector; // [RH] sector this sprite is in
|
||||||
fixed_t alpha;
|
fixed_t alpha;
|
||||||
fixed_t floorclip;
|
fixed_t floorclip;
|
||||||
FTexture *pic;
|
union
|
||||||
|
{
|
||||||
|
FTexture *pic;
|
||||||
|
struct FVoxel *voxel;
|
||||||
|
};
|
||||||
|
BYTE bIsVoxel:1; // [RH] Use voxel instead of pic
|
||||||
|
BYTE bSplitSprite:1; // [RH] Sprite was split by a drawseg
|
||||||
|
BYTE FakeFlatStat; // [RH] which side of fake/floor ceiling sprite is on
|
||||||
short renderflags;
|
short renderflags;
|
||||||
DWORD Translation; // [RH] for color translation
|
DWORD Translation; // [RH] for color translation
|
||||||
FRenderStyle RenderStyle;
|
FRenderStyle RenderStyle;
|
||||||
BYTE FakeFlatStat; // [RH] which side of fake/floor ceiling sprite is on
|
|
||||||
BYTE bSplitSprite; // [RH] Sprite was split by a drawseg
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
|
@ -1087,14 +1093,16 @@ enum
|
||||||
//
|
//
|
||||||
struct spriteframe_t
|
struct spriteframe_t
|
||||||
{
|
{
|
||||||
|
struct FVoxelDef *Voxel;// voxel to use for this frame
|
||||||
FTextureID Texture[16]; // texture to use for view angles 0-15
|
FTextureID Texture[16]; // texture to use for view angles 0-15
|
||||||
WORD Flip; // flip (1 = flip) to use for view angles 0-15.
|
WORD Flip; // flip (1 = flip) to use for view angles 0-15.
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// A sprite definition:
|
// A sprite definition:
|
||||||
// a number of animation frames.
|
// a number of animation frames.
|
||||||
//
|
//
|
||||||
|
|
||||||
struct spritedef_t
|
struct spritedef_t
|
||||||
{
|
{
|
||||||
union
|
union
|
||||||
|
@ -1127,4 +1135,77 @@ public:
|
||||||
int namespc; // namespace for this skin
|
int namespc; // namespace for this skin
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// [RH] Voxels from Build
|
||||||
|
|
||||||
|
#define MAXVOXMIPS 5
|
||||||
|
|
||||||
|
struct kvxslab_t
|
||||||
|
{
|
||||||
|
BYTE ztop; // starting z coordinate of top of slab
|
||||||
|
BYTE zleng; // # of bytes in the color array - slab height
|
||||||
|
BYTE backfacecull; // low 6 bits tell which of 6 faces are exposed
|
||||||
|
BYTE col[1/*zleng*/];// color data from top to bottom
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FVoxelMipLevel
|
||||||
|
{
|
||||||
|
FVoxelMipLevel();
|
||||||
|
~FVoxelMipLevel();
|
||||||
|
|
||||||
|
int SizeX;
|
||||||
|
int SizeY;
|
||||||
|
int SizeZ;
|
||||||
|
fixed_t PivotX; // 24.8 fixed point
|
||||||
|
fixed_t PivotY; // ""
|
||||||
|
fixed_t PivotZ; // ""
|
||||||
|
int *OffsetX;
|
||||||
|
short *OffsetXY;
|
||||||
|
BYTE *SlabData;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FVoxel
|
||||||
|
{
|
||||||
|
int LumpNum;
|
||||||
|
int NumMips;
|
||||||
|
BYTE *Palette;
|
||||||
|
FVoxelMipLevel Mips[MAXVOXMIPS];
|
||||||
|
|
||||||
|
FVoxel();
|
||||||
|
~FVoxel();
|
||||||
|
void Remap();
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FVoxelDef
|
||||||
|
{
|
||||||
|
FVoxel *Voxel;
|
||||||
|
int PlacedSpin; // degrees/sec to spin actors without MF_DROPPED set
|
||||||
|
int DroppedSpin; // degrees/sec to spin actors with MF_DROPPED set
|
||||||
|
fixed_t Scale;
|
||||||
|
angle_t AngleOffset; // added to actor's angle to compensate for wrong-facing voxels
|
||||||
|
};
|
||||||
|
|
||||||
|
// [RH] A c-buffer. Used for keeping track of offscreen voxel spans.
|
||||||
|
|
||||||
|
struct FCoverageBuffer
|
||||||
|
{
|
||||||
|
struct Span
|
||||||
|
{
|
||||||
|
Span *NextSpan;
|
||||||
|
short Start, Stop;
|
||||||
|
};
|
||||||
|
|
||||||
|
FCoverageBuffer(int size);
|
||||||
|
~FCoverageBuffer();
|
||||||
|
|
||||||
|
void Clear();
|
||||||
|
void InsertSpan(int listnum, int start, int stop);
|
||||||
|
Span *AllocSpan();
|
||||||
|
|
||||||
|
FMemArena SpanArena;
|
||||||
|
Span **Spans; // [0..NumLists-1] span lists
|
||||||
|
Span *FreeSpans;
|
||||||
|
unsigned int NumLists;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
140
src/r_draw.cpp
140
src/r_draw.cpp
|
@ -141,6 +141,7 @@ FRenderStyle LegacyRenderStyles[STYLE_Count] =
|
||||||
/* STYLE_Add */ {{ STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_One, 0 }},
|
/* STYLE_Add */ {{ STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_One, 0 }},
|
||||||
/* STYLE_Shaded */ {{ STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_InvSrc, STYLEF_RedIsAlpha | STYLEF_ColorIsFixed }},
|
/* STYLE_Shaded */ {{ STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_InvSrc, STYLEF_RedIsAlpha | STYLEF_ColorIsFixed }},
|
||||||
/* STYLE_TranslucentStencil */{{ STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_InvSrc, STYLEF_ColorIsFixed }},
|
/* STYLE_TranslucentStencil */{{ STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_InvSrc, STYLEF_ColorIsFixed }},
|
||||||
|
/* STYLE_Shadow */{{ STYLEOP_Shadow, 0, 0, 0 }},
|
||||||
};
|
};
|
||||||
#else
|
#else
|
||||||
FRenderStyle LegacyRenderStyles[STYLE_Count];
|
FRenderStyle LegacyRenderStyles[STYLE_Count];
|
||||||
|
@ -157,6 +158,7 @@ static const BYTE Styles[STYLE_Count * 4] =
|
||||||
STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_One, 0,
|
STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_One, 0,
|
||||||
STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_InvSrc, STYLEF_RedIsAlpha | STYLEF_ColorIsFixed,
|
STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_InvSrc, STYLEF_RedIsAlpha | STYLEF_ColorIsFixed,
|
||||||
STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_InvSrc, STYLEF_ColorIsFixed,
|
STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_InvSrc, STYLEF_ColorIsFixed,
|
||||||
|
STYLEOP_Shadow, 0, 0, 0
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct LegacyInit
|
static struct LegacyInit
|
||||||
|
@ -1350,6 +1352,97 @@ void R_FillSpan (void)
|
||||||
memset (ylookup[ds_y] + ds_x1 + dc_destorg, ds_color, ds_x2 - ds_x1 + 1);
|
memset (ylookup[ds_y] + ds_x1 + dc_destorg, ds_color, ds_x2 - ds_x1 + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Draw a voxel slab
|
||||||
|
//
|
||||||
|
// "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman
|
||||||
|
// Ken Silverman's official web site: "http://www.advsys.net/ken"
|
||||||
|
// See the included license file "BUILDLIC.TXT" for license info.
|
||||||
|
|
||||||
|
// Actually, this is just R_DrawColumn with an extra width parameter.
|
||||||
|
|
||||||
|
#ifndef X86_ASM
|
||||||
|
static const BYTE *slabcolormap;
|
||||||
|
|
||||||
|
extern "C" void R_SetupDrawSlab(const BYTE *colormap)
|
||||||
|
{
|
||||||
|
slabcolormap = colormap;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void STACK_ARGS R_DrawSlab(int dx, fixed_t v, int dy, fixed_t vi, const BYTE *vptr, BYTE *p)
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
const BYTE *colormap = slabcolormap;
|
||||||
|
int pitch = dc_pitch;
|
||||||
|
|
||||||
|
assert(dx > 0);
|
||||||
|
|
||||||
|
if (dx == 1)
|
||||||
|
{
|
||||||
|
while (dy > 0)
|
||||||
|
{
|
||||||
|
*p = colormap[vptr[v >> FRACBITS]];
|
||||||
|
p += pitch;
|
||||||
|
v += vi;
|
||||||
|
dy--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (dx == 2)
|
||||||
|
{
|
||||||
|
while (dy > 0)
|
||||||
|
{
|
||||||
|
BYTE color = colormap[vptr[v >> FRACBITS]];
|
||||||
|
p[0] = color;
|
||||||
|
p[1] = color;
|
||||||
|
p += pitch;
|
||||||
|
v += vi;
|
||||||
|
dy--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (dx == 3)
|
||||||
|
{
|
||||||
|
while (dy > 0)
|
||||||
|
{
|
||||||
|
BYTE color = colormap[vptr[v >> FRACBITS]];
|
||||||
|
p[0] = color;
|
||||||
|
p[1] = color;
|
||||||
|
p[2] = color;
|
||||||
|
p += pitch;
|
||||||
|
v += vi;
|
||||||
|
dy--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (dx == 4)
|
||||||
|
{
|
||||||
|
while (dy > 0)
|
||||||
|
{
|
||||||
|
BYTE color = colormap[vptr[v >> FRACBITS]];
|
||||||
|
p[0] = color;
|
||||||
|
p[1] = color;
|
||||||
|
p[2] = color;
|
||||||
|
p[3] = color;
|
||||||
|
p += pitch;
|
||||||
|
v += vi;
|
||||||
|
dy--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else while (dy > 0)
|
||||||
|
{
|
||||||
|
BYTE color = colormap[vptr[v >> FRACBITS]];
|
||||||
|
// The optimizer will probably turn this into a memset call.
|
||||||
|
// Since dx is not likely to be large, I'm not sure that's a good thing,
|
||||||
|
// hence the alternatives above.
|
||||||
|
for (x = 0; x < dx; x++)
|
||||||
|
{
|
||||||
|
p[x] = color;
|
||||||
|
}
|
||||||
|
p += pitch;
|
||||||
|
v += vi;
|
||||||
|
dy--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/****************************************************/
|
/****************************************************/
|
||||||
/****************************************************/
|
/****************************************************/
|
||||||
|
|
||||||
|
@ -2068,7 +2161,7 @@ void R_InitColumnDrawers ()
|
||||||
}
|
}
|
||||||
|
|
||||||
// [RH] Choose column drawers in a single place
|
// [RH] Choose column drawers in a single place
|
||||||
EXTERN_CVAR (Bool, r_drawfuzz)
|
EXTERN_CVAR (Int, r_drawfuzz)
|
||||||
EXTERN_CVAR (Float, transsouls)
|
EXTERN_CVAR (Float, transsouls)
|
||||||
CVAR (Bool, r_drawtrans, true, 0)
|
CVAR (Bool, r_drawtrans, true, 0)
|
||||||
|
|
||||||
|
@ -2235,6 +2328,13 @@ ESPSResult R_SetPatchStyle (FRenderStyle style, fixed_t alpha, int translation,
|
||||||
|
|
||||||
style.CheckFuzz();
|
style.CheckFuzz();
|
||||||
|
|
||||||
|
if (style.BlendOp == STYLEOP_Shadow)
|
||||||
|
{
|
||||||
|
style = LegacyRenderStyles[STYLE_TranslucentStencil];
|
||||||
|
alpha = FRACUNIT*3/10;
|
||||||
|
color = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (style.Flags & STYLEF_TransSoulsAlpha)
|
if (style.Flags & STYLEF_TransSoulsAlpha)
|
||||||
{
|
{
|
||||||
alpha = fixed_t(transsouls * FRACUNIT);
|
alpha = fixed_t(transsouls * FRACUNIT);
|
||||||
|
@ -2390,16 +2490,42 @@ bool FRenderStyle::IsVisible(fixed_t alpha) const throw()
|
||||||
|
|
||||||
void FRenderStyle::CheckFuzz()
|
void FRenderStyle::CheckFuzz()
|
||||||
{
|
{
|
||||||
if (BlendOp == STYLEOP_FuzzOrAdd)
|
switch (BlendOp)
|
||||||
{
|
{
|
||||||
BlendOp = (r_drawfuzz || !r_drawtrans) ? STYLEOP_Fuzz : STYLEOP_Add;
|
default:
|
||||||
|
return;
|
||||||
|
|
||||||
|
case STYLEOP_FuzzOrAdd:
|
||||||
|
if (r_drawtrans && r_drawfuzz == 0)
|
||||||
|
{
|
||||||
|
BlendOp = STYLEOP_Add;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STYLEOP_FuzzOrSub:
|
||||||
|
if (r_drawtrans && r_drawfuzz == 0)
|
||||||
|
{
|
||||||
|
BlendOp = STYLEOP_Sub;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STYLEOP_FuzzOrRevSub:
|
||||||
|
if (r_drawtrans && r_drawfuzz == 0)
|
||||||
|
{
|
||||||
|
BlendOp = STYLEOP_RevSub;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else if (BlendOp == STYLEOP_FuzzOrSub)
|
|
||||||
|
if (r_drawfuzz == 2)
|
||||||
{
|
{
|
||||||
BlendOp = (r_drawfuzz || !r_drawtrans) ? STYLEOP_Fuzz : STYLEOP_Sub;
|
BlendOp = STYLEOP_Shadow;
|
||||||
}
|
}
|
||||||
else if (BlendOp == STYLEOP_FuzzOrRevSub)
|
else
|
||||||
{
|
{
|
||||||
BlendOp = (r_drawfuzz || !r_drawtrans) ? STYLEOP_Fuzz : STYLEOP_RevSub;
|
BlendOp = STYLEOP_Fuzz;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,7 @@ extern "C" BYTE* palookupoffse[4];
|
||||||
extern "C" const BYTE* bufplce[4];
|
extern "C" const BYTE* bufplce[4];
|
||||||
|
|
||||||
// [RH] Temporary buffer for column drawing
|
// [RH] Temporary buffer for column drawing
|
||||||
extern "C" BYTE dc_temp[MAXHEIGHT*4];
|
extern "C" BYTE *dc_temp;
|
||||||
extern "C" unsigned int dc_tspans[4][MAXHEIGHT];
|
extern "C" unsigned int dc_tspans[4][MAXHEIGHT];
|
||||||
extern "C" unsigned int *dc_ctspan[4];
|
extern "C" unsigned int *dc_ctspan[4];
|
||||||
extern "C" unsigned int horizspans[4];
|
extern "C" unsigned int horizspans[4];
|
||||||
|
@ -178,7 +178,7 @@ extern void (STACK_ARGS *rt_map4cols)(int sx, int yl, int yh);
|
||||||
void rt_draw4cols (int sx);
|
void rt_draw4cols (int sx);
|
||||||
|
|
||||||
// [RH] Preps the temporary horizontal buffer.
|
// [RH] Preps the temporary horizontal buffer.
|
||||||
void rt_initcols (void);
|
void rt_initcols (BYTE *buffer=NULL);
|
||||||
|
|
||||||
void R_DrawFogBoundary (int x1, int x2, short *uclip, short *dclip);
|
void R_DrawFogBoundary (int x1, int x2, short *uclip, short *dclip);
|
||||||
|
|
||||||
|
@ -216,6 +216,9 @@ void R_FillColumnP (void);
|
||||||
void R_FillColumnHorizP (void);
|
void R_FillColumnHorizP (void);
|
||||||
void R_FillSpan (void);
|
void R_FillSpan (void);
|
||||||
|
|
||||||
|
extern "C" void R_SetupDrawSlab(const BYTE *colormap);
|
||||||
|
extern "C" void STACK_ARGS R_DrawSlab(int dx, fixed_t v, int dy, fixed_t vi, const BYTE *vptr, BYTE *p);
|
||||||
|
|
||||||
extern "C" int ds_y;
|
extern "C" int ds_y;
|
||||||
extern "C" int ds_x1;
|
extern "C" int ds_x1;
|
||||||
extern "C" int ds_x2;
|
extern "C" int ds_x2;
|
||||||
|
|
|
@ -52,9 +52,13 @@
|
||||||
// dc_temp is the buffer R_DrawColumnHoriz writes into.
|
// dc_temp is the buffer R_DrawColumnHoriz writes into.
|
||||||
// dc_tspans points into it.
|
// dc_tspans points into it.
|
||||||
// dc_ctspan points into dc_tspans.
|
// dc_ctspan points into dc_tspans.
|
||||||
// But what is horizspan, and what is its relation with dc_ctspan?
|
// horizspan also points into dc_tspans.
|
||||||
|
|
||||||
BYTE dc_temp[MAXHEIGHT*4];
|
// dc_ctspan is advanced while drawing into dc_temp.
|
||||||
|
// horizspan is advanced up to dc_ctspan when drawing from dc_temp to the screen.
|
||||||
|
|
||||||
|
BYTE dc_tempbuff[MAXHEIGHT*4];
|
||||||
|
BYTE *dc_temp;
|
||||||
unsigned int dc_tspans[4][MAXHEIGHT];
|
unsigned int dc_tspans[4][MAXHEIGHT];
|
||||||
unsigned int *dc_ctspan[4];
|
unsigned int *dc_ctspan[4];
|
||||||
unsigned int *horizspan[4];
|
unsigned int *horizspan[4];
|
||||||
|
@ -998,10 +1002,11 @@ void rt_draw4cols (int sx)
|
||||||
|
|
||||||
// Before each pass through a rendering loop that uses these routines,
|
// Before each pass through a rendering loop that uses these routines,
|
||||||
// call this function to set up the span pointers.
|
// call this function to set up the span pointers.
|
||||||
void rt_initcols (void)
|
void rt_initcols (BYTE *buff)
|
||||||
{
|
{
|
||||||
int y;
|
int y;
|
||||||
|
|
||||||
|
dc_temp = buff == NULL ? dc_tempbuff : buff;
|
||||||
for (y = 3; y >= 0; y--)
|
for (y = 3; y >= 0; y--)
|
||||||
horizspan[y] = dc_ctspan[y] = &dc_tspans[y][0];
|
horizspan[y] = dc_ctspan[y] = &dc_tspans[y][0];
|
||||||
}
|
}
|
||||||
|
@ -1035,26 +1040,18 @@ void R_DrawColumnHorizP_C (void)
|
||||||
const BYTE *source = dc_source;
|
const BYTE *source = dc_source;
|
||||||
|
|
||||||
if (count & 1) {
|
if (count & 1) {
|
||||||
*dest = source[frac>>FRACBITS];
|
*dest = source[frac>>FRACBITS]; dest += 4; frac += fracstep;
|
||||||
dest += 4;
|
|
||||||
frac += fracstep;
|
|
||||||
}
|
}
|
||||||
if (count & 2) {
|
if (count & 2) {
|
||||||
dest[0] = source[frac>>FRACBITS];
|
dest[0] = source[frac>>FRACBITS]; frac += fracstep;
|
||||||
frac += fracstep;
|
dest[4] = source[frac>>FRACBITS]; frac += fracstep;
|
||||||
dest[4] = source[frac>>FRACBITS];
|
|
||||||
frac += fracstep;
|
|
||||||
dest += 8;
|
dest += 8;
|
||||||
}
|
}
|
||||||
if (count & 4) {
|
if (count & 4) {
|
||||||
dest[0] = source[frac>>FRACBITS];
|
dest[0] = source[frac>>FRACBITS]; frac += fracstep;
|
||||||
frac += fracstep;
|
dest[4] = source[frac>>FRACBITS]; frac += fracstep;
|
||||||
dest[4] = source[frac>>FRACBITS];
|
dest[8] = source[frac>>FRACBITS]; frac += fracstep;
|
||||||
frac += fracstep;
|
dest[12]= source[frac>>FRACBITS]; frac += fracstep;
|
||||||
dest[8] = source[frac>>FRACBITS];
|
|
||||||
frac += fracstep;
|
|
||||||
dest[12] = source[frac>>FRACBITS];
|
|
||||||
frac += fracstep;
|
|
||||||
dest += 16;
|
dest += 16;
|
||||||
}
|
}
|
||||||
count >>= 3;
|
count >>= 3;
|
||||||
|
@ -1062,22 +1059,14 @@ void R_DrawColumnHorizP_C (void)
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
dest[0] = source[frac>>FRACBITS];
|
dest[0] = source[frac>>FRACBITS]; frac += fracstep;
|
||||||
frac += fracstep;
|
dest[4] = source[frac>>FRACBITS]; frac += fracstep;
|
||||||
dest[4] = source[frac>>FRACBITS];
|
dest[8] = source[frac>>FRACBITS]; frac += fracstep;
|
||||||
frac += fracstep;
|
dest[12]= source[frac>>FRACBITS]; frac += fracstep;
|
||||||
dest[8] = source[frac>>FRACBITS];
|
dest[16]= source[frac>>FRACBITS]; frac += fracstep;
|
||||||
frac += fracstep;
|
dest[20]= source[frac>>FRACBITS]; frac += fracstep;
|
||||||
dest[12] = source[frac>>FRACBITS];
|
dest[24]= source[frac>>FRACBITS]; frac += fracstep;
|
||||||
frac += fracstep;
|
dest[28]= source[frac>>FRACBITS]; frac += fracstep;
|
||||||
dest[16] = source[frac>>FRACBITS];
|
|
||||||
frac += fracstep;
|
|
||||||
dest[20] = source[frac>>FRACBITS];
|
|
||||||
frac += fracstep;
|
|
||||||
dest[24] = source[frac>>FRACBITS];
|
|
||||||
frac += fracstep;
|
|
||||||
dest[28] = source[frac>>FRACBITS];
|
|
||||||
frac += fracstep;
|
|
||||||
dest += 32;
|
dest += 32;
|
||||||
} while (--count);
|
} while (--count);
|
||||||
}
|
}
|
||||||
|
@ -1110,8 +1099,7 @@ void R_FillColumnHorizP (void)
|
||||||
if (!(count >>= 1))
|
if (!(count >>= 1))
|
||||||
return;
|
return;
|
||||||
do {
|
do {
|
||||||
dest[0] = color;
|
dest[0] = color; dest[4] = color;
|
||||||
dest[4] = color;
|
|
||||||
dest += 8;
|
dest += 8;
|
||||||
} while (--count);
|
} while (--count);
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,7 +103,6 @@ static fixed_t MaxVisForFloor;
|
||||||
static FRandom pr_torchflicker ("TorchFlicker");
|
static FRandom pr_torchflicker ("TorchFlicker");
|
||||||
static FRandom pr_hom;
|
static FRandom pr_hom;
|
||||||
static TArray<InterpolationViewer> PastViewers;
|
static TArray<InterpolationViewer> PastViewers;
|
||||||
static int centerxwide;
|
|
||||||
static bool polyclipped;
|
static bool polyclipped;
|
||||||
static bool r_showviewer;
|
static bool r_showviewer;
|
||||||
bool r_dontmaplines;
|
bool r_dontmaplines;
|
||||||
|
@ -135,6 +134,7 @@ float LastFOV;
|
||||||
int WidescreenRatio;
|
int WidescreenRatio;
|
||||||
|
|
||||||
fixed_t GlobVis;
|
fixed_t GlobVis;
|
||||||
|
fixed_t viewingrangerecip;
|
||||||
fixed_t FocalTangent;
|
fixed_t FocalTangent;
|
||||||
fixed_t FocalLengthX;
|
fixed_t FocalLengthX;
|
||||||
fixed_t FocalLengthY;
|
fixed_t FocalLengthY;
|
||||||
|
@ -151,6 +151,8 @@ float WallTMapScale2;
|
||||||
extern "C" {
|
extern "C" {
|
||||||
int centerx;
|
int centerx;
|
||||||
int centery;
|
int centery;
|
||||||
|
int centerxwide;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DCanvas *RenderTarget; // [RH] canvas to render to
|
DCanvas *RenderTarget; // [RH] canvas to render to
|
||||||
|
@ -159,6 +161,7 @@ fixed_t globaluclip, globaldclip;
|
||||||
fixed_t centerxfrac;
|
fixed_t centerxfrac;
|
||||||
fixed_t centeryfrac;
|
fixed_t centeryfrac;
|
||||||
fixed_t yaspectmul;
|
fixed_t yaspectmul;
|
||||||
|
fixed_t baseyaspectmul; // yaspectmul without a forced aspect ratio
|
||||||
float iyaspectmulfloat;
|
float iyaspectmulfloat;
|
||||||
fixed_t InvZtoScale;
|
fixed_t InvZtoScale;
|
||||||
|
|
||||||
|
@ -458,6 +461,9 @@ void R_InitTextureMapping ()
|
||||||
FocalLengthY = Scale (centerxfrac, yaspectmul, hitan);
|
FocalLengthY = Scale (centerxfrac, yaspectmul, hitan);
|
||||||
FocalLengthXfloat = (float)FocalLengthX / 65536.f;
|
FocalLengthXfloat = (float)FocalLengthX / 65536.f;
|
||||||
|
|
||||||
|
// This is 1/FocalTangent before the widescreen extension of FOV.
|
||||||
|
viewingrangerecip = DivScale32(1, finetangent[FINEANGLES/4+(FieldOfView/2)]);
|
||||||
|
|
||||||
// Now generate xtoviewangle for sky texture mapping.
|
// Now generate xtoviewangle for sky texture mapping.
|
||||||
// [RH] Do not generate viewangletox, because texture mapping is no
|
// [RH] Do not generate viewangletox, because texture mapping is no
|
||||||
// longer done with trig, so it's not needed.
|
// longer done with trig, so it's not needed.
|
||||||
|
@ -600,7 +606,7 @@ void R_SetViewSize (int blocks)
|
||||||
|
|
||||||
void R_SetWindow (int windowSize, int fullWidth, int fullHeight, int stHeight)
|
void R_SetWindow (int windowSize, int fullWidth, int fullHeight, int stHeight)
|
||||||
{
|
{
|
||||||
int virtheight, virtwidth;
|
int virtheight, virtwidth, trueratio, virtwidth2, virtheight2;
|
||||||
|
|
||||||
if (windowSize >= 11)
|
if (windowSize >= 11)
|
||||||
{
|
{
|
||||||
|
@ -621,7 +627,7 @@ void R_SetWindow (int windowSize, int fullWidth, int fullHeight, int stHeight)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the screen is approximately 16:9 or 16:10, consider it widescreen.
|
// If the screen is approximately 16:9 or 16:10, consider it widescreen.
|
||||||
WidescreenRatio = CheckRatio (fullWidth, fullHeight);
|
WidescreenRatio = CheckRatio (fullWidth, fullHeight, &trueratio);
|
||||||
|
|
||||||
DrawFSHUD = (windowSize == 11);
|
DrawFSHUD = (windowSize == 11);
|
||||||
|
|
||||||
|
@ -644,8 +650,18 @@ void R_SetWindow (int windowSize, int fullWidth, int fullHeight, int stHeight)
|
||||||
centerxfrac = centerx<<FRACBITS;
|
centerxfrac = centerx<<FRACBITS;
|
||||||
centeryfrac = centery<<FRACBITS;
|
centeryfrac = centery<<FRACBITS;
|
||||||
|
|
||||||
virtwidth = fullWidth;
|
virtwidth = virtwidth2 = fullWidth;
|
||||||
virtheight = fullHeight;
|
virtheight = virtheight2 = fullHeight;
|
||||||
|
|
||||||
|
if (trueratio & 4)
|
||||||
|
{
|
||||||
|
virtheight2 = virtheight2 * BaseRatioSizes[trueratio][3] / 48;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
virtwidth2 = virtwidth2 * BaseRatioSizes[trueratio][3] / 48;
|
||||||
|
}
|
||||||
|
|
||||||
if (WidescreenRatio & 4)
|
if (WidescreenRatio & 4)
|
||||||
{
|
{
|
||||||
virtheight = virtheight * BaseRatioSizes[WidescreenRatio][3] / 48;
|
virtheight = virtheight * BaseRatioSizes[WidescreenRatio][3] / 48;
|
||||||
|
@ -657,6 +673,7 @@ void R_SetWindow (int windowSize, int fullWidth, int fullHeight, int stHeight)
|
||||||
centerxwide = centerx * BaseRatioSizes[WidescreenRatio][3] / 48;
|
centerxwide = centerx * BaseRatioSizes[WidescreenRatio][3] / 48;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
baseyaspectmul = Scale(320 << FRACBITS, virtheight2, r_Yaspect * virtwidth2);
|
||||||
yaspectmul = Scale ((320<<FRACBITS), virtheight, r_Yaspect * virtwidth);
|
yaspectmul = Scale ((320<<FRACBITS), virtheight, r_Yaspect * virtwidth);
|
||||||
iyaspectmulfloat = (float)virtwidth * r_Yaspect / 320.f / (float)virtheight;
|
iyaspectmulfloat = (float)virtwidth * r_Yaspect / 320.f / (float)virtheight;
|
||||||
InvZtoScale = yaspectmul * centerx;
|
InvZtoScale = yaspectmul * centerx;
|
||||||
|
|
|
@ -43,6 +43,7 @@ extern fixed_t viewsin;
|
||||||
extern fixed_t viewtancos;
|
extern fixed_t viewtancos;
|
||||||
extern fixed_t viewtansin;
|
extern fixed_t viewtansin;
|
||||||
extern fixed_t FocalTangent;
|
extern fixed_t FocalTangent;
|
||||||
|
extern fixed_t viewingrangerecip;
|
||||||
extern fixed_t FocalLengthX, FocalLengthY;
|
extern fixed_t FocalLengthX, FocalLengthY;
|
||||||
extern float FocalLengthXfloat;
|
extern float FocalLengthXfloat;
|
||||||
extern fixed_t InvZtoScale;
|
extern fixed_t InvZtoScale;
|
||||||
|
@ -62,7 +63,7 @@ extern int viewwindowy;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
extern "C" int centerx;
|
extern "C" int centerx, centerxwide;
|
||||||
extern "C" int centery;
|
extern "C" int centery;
|
||||||
|
|
||||||
extern fixed_t centerxfrac;
|
extern fixed_t centerxfrac;
|
||||||
|
|
|
@ -593,7 +593,7 @@ visplane_t *R_FindPlane (const secplane_t &height, FTextureID picnum, int lightl
|
||||||
check->viewz == stacked_viewz &&
|
check->viewz == stacked_viewz &&
|
||||||
(
|
(
|
||||||
// headache inducing logic... :(
|
// headache inducing logic... :(
|
||||||
(ib_compatflags & BCOMPATF_BADPORTALS) ||
|
(!(skybox->flags & MF_JUSTATTACKED)) ||
|
||||||
(
|
(
|
||||||
check->alpha == alpha &&
|
check->alpha == alpha &&
|
||||||
(alpha == 0 || // if alpha is > 0 everything needs to be checked
|
(alpha == 0 || // if alpha is > 0 everything needs to be checked
|
||||||
|
|
1343
src/r_things.cpp
1343
src/r_things.cpp
File diff suppressed because it is too large
Load diff
|
@ -104,6 +104,14 @@ void R_ClearSprites ();
|
||||||
void R_DrawMasked ();
|
void R_DrawMasked ();
|
||||||
void R_DrawRemainingPlayerSprites ();
|
void R_DrawRemainingPlayerSprites ();
|
||||||
|
|
||||||
|
void R_CheckOffscreenBuffer(int width, int height, bool spansonly);
|
||||||
|
|
||||||
|
enum { DVF_OFFSCREEN = 1, DVF_SPANSONLY = 2 };
|
||||||
|
|
||||||
|
void R_DrawVoxel(fixed_t dasprx, fixed_t daspry, fixed_t dasprz, angle_t dasprang,
|
||||||
|
fixed_t daxscale, fixed_t dayscale, FVoxel *voxobj,
|
||||||
|
lighttable_t *colormap, short *daumost, short *dadmost, int minslabz, int maxslabz, int flags);
|
||||||
|
|
||||||
void R_ClipVisSprite (vissprite_t *vis, int xl, int xh);
|
void R_ClipVisSprite (vissprite_t *vis, int xl, int xh);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -113,6 +113,7 @@ bool FWadFile::Open(bool quiet)
|
||||||
SetNamespace("TX_START", "TX_END", ns_newtextures);
|
SetNamespace("TX_START", "TX_END", ns_newtextures);
|
||||||
SetNamespace("V_START", "V_END", ns_strifevoices);
|
SetNamespace("V_START", "V_END", ns_strifevoices);
|
||||||
SetNamespace("HI_START", "HI_END", ns_hires);
|
SetNamespace("HI_START", "HI_END", ns_hires);
|
||||||
|
SetNamespace("VX_START", "VX_END", ns_voxels);
|
||||||
SkinHack();
|
SkinHack();
|
||||||
}
|
}
|
||||||
delete [] fileinfo;
|
delete [] fileinfo;
|
||||||
|
|
|
@ -116,6 +116,7 @@ void FResourceLump::LumpNameSetup(const char *iname)
|
||||||
!strncmp(iname, "textures/", 9) ? ns_newtextures :
|
!strncmp(iname, "textures/", 9) ? ns_newtextures :
|
||||||
!strncmp(iname, "hires/", 6) ? ns_hires :
|
!strncmp(iname, "hires/", 6) ? ns_hires :
|
||||||
!strncmp(iname, "sprites/", 8) ? ns_sprites :
|
!strncmp(iname, "sprites/", 8) ? ns_sprites :
|
||||||
|
!strncmp(iname, "voxels/", 7) ? ns_voxels :
|
||||||
!strncmp(iname, "colormaps/", 10) ? ns_colormaps :
|
!strncmp(iname, "colormaps/", 10) ? ns_colormaps :
|
||||||
!strncmp(iname, "acs/", 4) ? ns_acslibrary :
|
!strncmp(iname, "acs/", 4) ? ns_acslibrary :
|
||||||
!strncmp(iname, "voices/", 7) ? ns_strifevoices :
|
!strncmp(iname, "voices/", 7) ? ns_strifevoices :
|
||||||
|
@ -137,7 +138,7 @@ void FResourceLump::LumpNameSetup(const char *iname)
|
||||||
// Since '\' can't be used as a file name's part inside a ZIP
|
// Since '\' can't be used as a file name's part inside a ZIP
|
||||||
// we have to work around this for sprites because it is a valid
|
// we have to work around this for sprites because it is a valid
|
||||||
// frame character.
|
// frame character.
|
||||||
else if (Namespace == ns_sprites)
|
else if (Namespace == ns_sprites || Namespace == ns_voxels)
|
||||||
{
|
{
|
||||||
char *c;
|
char *c;
|
||||||
|
|
||||||
|
|
|
@ -4,21 +4,39 @@
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/ucontext.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <sys/ucontext.h>
|
|
||||||
|
|
||||||
// Solaris doesn't have SA_ONESHOT
|
#ifdef __linux__
|
||||||
// According to the Linux header this is the same.
|
#include <sys/prctl.h>
|
||||||
#ifndef SA_ONESHOT
|
#ifndef PR_SET_PTRACER
|
||||||
#define SA_ONESHOT SA_RESETHAND
|
#define PR_SET_PTRACER 0x59616d61
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static const char *cc_logfile = NULL;
|
|
||||||
|
|
||||||
static char respfile[256];
|
static const char crash_switch[] = "--cc-handle-crash";
|
||||||
static char buf[256];
|
|
||||||
static char user_info_buf[1024];
|
static const char fatal_err[] = "\n\n*** Fatal Error ***\n";
|
||||||
|
static const char pipe_err[] = "!!! Failed to create pipe\n";
|
||||||
|
static const char fork_err[] = "!!! Failed to fork debug process\n";
|
||||||
|
static const char exec_err[] = "!!! Failed to exec debug process\n";
|
||||||
|
|
||||||
|
static char argv0[PATH_MAX];
|
||||||
|
|
||||||
|
static char altstack[SIGSTKSZ];
|
||||||
|
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
int signum;
|
||||||
|
pid_t pid;
|
||||||
|
int has_siginfo;
|
||||||
|
siginfo_t siginfo;
|
||||||
|
char buf[1024];
|
||||||
|
} crash_info;
|
||||||
|
|
||||||
|
|
||||||
static const struct {
|
static const struct {
|
||||||
const char *name;
|
const char *name;
|
||||||
|
@ -88,16 +106,19 @@ static const struct {
|
||||||
|
|
||||||
static int (*cc_user_info)(char*, char*);
|
static int (*cc_user_info)(char*, char*);
|
||||||
|
|
||||||
|
|
||||||
static void gdb_info(pid_t pid)
|
static void gdb_info(pid_t pid)
|
||||||
{
|
{
|
||||||
|
char respfile[64];
|
||||||
|
char cmd_buf[128];
|
||||||
FILE *f;
|
FILE *f;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
/* Create a temp file to put gdb commands into */
|
/* Create a temp file to put gdb commands into */
|
||||||
strcpy(respfile, "gdb-respfile-XXXXXX");
|
strcpy(respfile, "gdb-respfile-XXXXXX");
|
||||||
if((fd = mkstemp(respfile)) >= 0 && (f = fdopen(fd, "w")))
|
if((fd=mkstemp(respfile)) >= 0 && (f=fdopen(fd, "w")) != NULL)
|
||||||
{
|
{
|
||||||
fprintf(f, "signal SIGCHLD\n"
|
fprintf(f, "attach %d\n"
|
||||||
"shell echo \"\"\n"
|
"shell echo \"\"\n"
|
||||||
"shell echo \"* Loaded Libraries\"\n"
|
"shell echo \"* Loaded Libraries\"\n"
|
||||||
"info sharedlibrary\n"
|
"info sharedlibrary\n"
|
||||||
|
@ -111,49 +132,18 @@ static void gdb_info(pid_t pid)
|
||||||
"shell echo \"* Registers\"\n"
|
"shell echo \"* Registers\"\n"
|
||||||
"info registers\n"
|
"info registers\n"
|
||||||
"shell echo \"\"\n"
|
"shell echo \"\"\n"
|
||||||
"shell echo \"* Bytes near %%eip:\"\n"
|
|
||||||
"x/x $eip-3\nx/x $eip\n"
|
|
||||||
"shell echo \"\"\n"
|
|
||||||
"shell echo \"* Backtrace\"\n"
|
"shell echo \"* Backtrace\"\n"
|
||||||
"backtrace full\n"
|
"thread apply all backtrace full\n"
|
||||||
#if 0 /* This sorta works to print out the core, but is too slow and skips 0's.. */
|
"detach\n"
|
||||||
"shell echo \"\"\n"
|
"quit\n", pid);
|
||||||
"shell echo \"* Stack\"\n"
|
|
||||||
"set var $_sp = $esp\n"
|
|
||||||
"while $_sp <= $ebp - 12\n"
|
|
||||||
" printf \"%%08x: \", $_sp\n"
|
|
||||||
" set var $_i = $_sp\n"
|
|
||||||
" while $_i < $_sp + 16\n"
|
|
||||||
" printf \"%%08x \", {int} $_i\n"
|
|
||||||
" set $_i += 4\n"
|
|
||||||
" end\n"
|
|
||||||
" set var $_i = $_sp\n"
|
|
||||||
" while $_i < $_sp + 16\n"
|
|
||||||
" printf \"%%c\", {int} $_i\n"
|
|
||||||
" set ++$_i\n"
|
|
||||||
" end\n"
|
|
||||||
" set var $_sp += 16\n"
|
|
||||||
" printf \"\\n\"\n"
|
|
||||||
"end\n"
|
|
||||||
"if $_sp <= $ebp\n"
|
|
||||||
" printf \"%%08x: \", $esp\n"
|
|
||||||
" while $_sp <= $ebp\n"
|
|
||||||
" printf \"%%08x \", {int} $_i\n"
|
|
||||||
" set $_sp += 4\n"
|
|
||||||
" end\n"
|
|
||||||
" printf \"\\n\"\n"
|
|
||||||
"end\n"
|
|
||||||
#endif
|
|
||||||
"kill\n"
|
|
||||||
"quit\n");
|
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
/* Run gdb and print process info. */
|
/* Run gdb and print process info. */
|
||||||
snprintf(buf, sizeof(buf), "gdb --quiet --batch --command=%s --pid=%i", respfile, pid);
|
snprintf(cmd_buf, sizeof(cmd_buf), "gdb --quiet --batch --command=%s", respfile);
|
||||||
printf("Executing: %s\n", buf);
|
printf("Executing: %s\n", cmd_buf);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
system(buf);
|
|
||||||
|
|
||||||
|
system(cmd_buf);
|
||||||
/* Clean up */
|
/* Clean up */
|
||||||
remove(respfile);
|
remove(respfile);
|
||||||
}
|
}
|
||||||
|
@ -165,55 +155,137 @@ static void gdb_info(pid_t pid)
|
||||||
close(fd);
|
close(fd);
|
||||||
remove(respfile);
|
remove(respfile);
|
||||||
}
|
}
|
||||||
printf("Could not create gdb command file\n");
|
printf("!!! Could not create gdb command file\n");
|
||||||
}
|
}
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Generic system info */
|
|
||||||
static void sys_info(void)
|
static void sys_info(void)
|
||||||
{
|
{
|
||||||
#if (defined __unix__)
|
#ifdef __unix__
|
||||||
system("echo \"System: `uname -a`\"");
|
system("echo \"System: `uname -a`\"");
|
||||||
#endif
|
|
||||||
system("echo \"GCC version: `gcc -dumpversion`\"");
|
|
||||||
putchar('\n');
|
putchar('\n');
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static size_t safe_write(int fd, const void *buf, size_t len)
|
||||||
|
{
|
||||||
|
size_t ret = 0;
|
||||||
|
while(ret < len)
|
||||||
|
{
|
||||||
|
ssize_t rem;
|
||||||
|
if((rem=write(fd, (const char*)buf+ret, len-ret)) == -1)
|
||||||
|
{
|
||||||
|
if(errno == EINTR)
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ret += rem;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void crash_catcher(int signum, siginfo_t *siginfo, void *context)
|
static void crash_catcher(int signum, siginfo_t *siginfo, void *context)
|
||||||
{
|
{
|
||||||
ucontext_t *ucontext = (ucontext_t*)context;
|
ucontext_t *ucontext = (ucontext_t*)context;
|
||||||
const char *sigdesc = NULL;
|
pid_t dbg_pid;
|
||||||
pid_t pid, dbg_pid;
|
int fd[2];
|
||||||
struct stat sbuf;
|
|
||||||
#ifndef __FreeBSD__
|
/* Make sure the effective uid is the real uid */
|
||||||
struct rlimit rl;
|
if(getuid() != geteuid())
|
||||||
|
{
|
||||||
|
raise(signum);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
safe_write(STDERR_FILENO, fatal_err, sizeof(fatal_err)-1);
|
||||||
|
if(pipe(fd) == -1)
|
||||||
|
{
|
||||||
|
safe_write(STDERR_FILENO, pipe_err, sizeof(pipe_err)-1);
|
||||||
|
raise(signum);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
crash_info.signum = signum;
|
||||||
|
crash_info.pid = getpid();
|
||||||
|
crash_info.has_siginfo = !!siginfo;
|
||||||
|
if(siginfo)
|
||||||
|
crash_info.siginfo = *siginfo;
|
||||||
|
if(cc_user_info)
|
||||||
|
cc_user_info(crash_info.buf, crash_info.buf+sizeof(crash_info.buf));
|
||||||
|
|
||||||
|
/* Fork off to start a crash handler */
|
||||||
|
switch((dbg_pid=fork()))
|
||||||
|
{
|
||||||
|
/* Error */
|
||||||
|
case -1:
|
||||||
|
safe_write(STDERR_FILENO, fork_err, sizeof(fork_err)-1);
|
||||||
|
raise(signum);
|
||||||
|
return;
|
||||||
|
|
||||||
|
case 0:
|
||||||
|
dup2(fd[0], STDIN_FILENO);
|
||||||
|
close(fd[0]);
|
||||||
|
close(fd[1]);
|
||||||
|
|
||||||
|
execl(argv0, argv0, crash_switch, NULL);
|
||||||
|
|
||||||
|
safe_write(STDERR_FILENO, exec_err, sizeof(exec_err)-1);
|
||||||
|
_exit(1);
|
||||||
|
|
||||||
|
default:
|
||||||
|
#ifdef __linux__
|
||||||
|
prctl(PR_SET_PTRACER, dbg_pid, 0, 0, 0);
|
||||||
#endif
|
#endif
|
||||||
int status, i;
|
safe_write(fd[1], &crash_info, sizeof(crash_info));
|
||||||
FILE *f;
|
close(fd[0]);
|
||||||
|
close(fd[1]);
|
||||||
|
|
||||||
|
/* Wait; we'll be killed when gdb is done */
|
||||||
|
do {
|
||||||
|
int status;
|
||||||
|
if(waitpid(dbg_pid, &status, 0) == dbg_pid &&
|
||||||
|
(WIFEXITED(status) || WIFSIGNALED(status)))
|
||||||
|
{
|
||||||
|
/* The debug process died before it could kill us */
|
||||||
|
raise(signum);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void crash_handler(const char *logfile)
|
||||||
|
{
|
||||||
|
const char *sigdesc = "";
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if(fread(&crash_info, sizeof(crash_info), 1, stdin) != 1)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "!!! Failed to retrieve info from crashed process\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
/* Get the signal description */
|
/* Get the signal description */
|
||||||
if(!siginfo)
|
for(i = 0;signals[i].name;++i)
|
||||||
{
|
{
|
||||||
for(i = 0;signals[i].name;++i)
|
if(signals[i].signum == crash_info.signum)
|
||||||
{
|
{
|
||||||
if(signals[i].signum == signum)
|
sigdesc = signals[i].name;
|
||||||
{
|
break;
|
||||||
sigdesc = signals[i].name;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
if(crash_info.has_siginfo)
|
||||||
{
|
{
|
||||||
switch(signum)
|
switch(crash_info.signum)
|
||||||
{
|
{
|
||||||
case SIGSEGV:
|
case SIGSEGV:
|
||||||
for(i = 0;sigsegv_codes[i].name;++i)
|
for(i = 0;sigsegv_codes[i].name;++i)
|
||||||
{
|
{
|
||||||
if(sigsegv_codes[i].code == siginfo->si_code)
|
if(sigsegv_codes[i].code == crash_info.siginfo.si_code)
|
||||||
{
|
{
|
||||||
sigdesc = sigsegv_codes[i].name;
|
sigdesc = sigsegv_codes[i].name;
|
||||||
break;
|
break;
|
||||||
|
@ -224,7 +296,7 @@ static void crash_catcher(int signum, siginfo_t *siginfo, void *context)
|
||||||
case SIGFPE:
|
case SIGFPE:
|
||||||
for(i = 0;sigfpe_codes[i].name;++i)
|
for(i = 0;sigfpe_codes[i].name;++i)
|
||||||
{
|
{
|
||||||
if(sigfpe_codes[i].code == siginfo->si_code)
|
if(sigfpe_codes[i].code == crash_info.siginfo.si_code)
|
||||||
{
|
{
|
||||||
sigdesc = sigfpe_codes[i].name;
|
sigdesc = sigfpe_codes[i].name;
|
||||||
break;
|
break;
|
||||||
|
@ -235,7 +307,7 @@ static void crash_catcher(int signum, siginfo_t *siginfo, void *context)
|
||||||
case SIGILL:
|
case SIGILL:
|
||||||
for(i = 0;sigill_codes[i].name;++i)
|
for(i = 0;sigill_codes[i].name;++i)
|
||||||
{
|
{
|
||||||
if(sigill_codes[i].code == siginfo->si_code)
|
if(sigill_codes[i].code == crash_info.siginfo.si_code)
|
||||||
{
|
{
|
||||||
sigdesc = sigill_codes[i].name;
|
sigdesc = sigill_codes[i].name;
|
||||||
break;
|
break;
|
||||||
|
@ -246,7 +318,7 @@ static void crash_catcher(int signum, siginfo_t *siginfo, void *context)
|
||||||
case SIGBUS:
|
case SIGBUS:
|
||||||
for(i = 0;sigbus_codes[i].name;++i)
|
for(i = 0;sigbus_codes[i].name;++i)
|
||||||
{
|
{
|
||||||
if(sigbus_codes[i].code == siginfo->si_code)
|
if(sigbus_codes[i].code == crash_info.siginfo.si_code)
|
||||||
{
|
{
|
||||||
sigdesc = sigbus_codes[i].name;
|
sigdesc = sigbus_codes[i].name;
|
||||||
break;
|
break;
|
||||||
|
@ -255,149 +327,91 @@ static void crash_catcher(int signum, siginfo_t *siginfo, void *context)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fprintf(stderr, "%s (signal %i)\n", sigdesc, crash_info.signum);
|
||||||
|
if(crash_info.has_siginfo)
|
||||||
|
fprintf(stderr, "Address: %p\n", crash_info.siginfo.si_addr);
|
||||||
|
fputc('\n', stderr);
|
||||||
|
|
||||||
if(!sigdesc)
|
if(logfile)
|
||||||
{
|
{
|
||||||
/* Unknown signal, let the default handler deal with it */
|
/* Create crash log file and redirect shell output to it */
|
||||||
raise(signum);
|
if(freopen(logfile, "wa", stdout) != stdout)
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0 /* Do we need this? */
|
|
||||||
/* Make sure the effective uid is the real uid */
|
|
||||||
if (getuid() != geteuid())
|
|
||||||
{
|
|
||||||
fprintf(stderr, "%s (signal %i)\ngetuid() does not match geteuid().\n", sigdesc, signum);
|
|
||||||
_exit(-1);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Create crash log file */
|
|
||||||
if(cc_logfile)
|
|
||||||
{
|
|
||||||
f = fopen(cc_logfile, "w");
|
|
||||||
if(!f)
|
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Could not create %s following signal.\n", cc_logfile);
|
fprintf(stderr, "!!! Could not create %s following signal\n", logfile);
|
||||||
raise(signum);
|
exit(1);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
fprintf(stderr, "Generating %s and killing process %d, please wait... ", logfile, crash_info.pid);
|
||||||
else
|
|
||||||
f = stderr;
|
|
||||||
|
|
||||||
/* Get current process id and fork off */
|
printf("*** Fatal Error ***\n"
|
||||||
pid = getpid();
|
"%s (signal %i)\n", sigdesc, crash_info.signum);
|
||||||
switch ((dbg_pid = fork()))
|
if(crash_info.has_siginfo)
|
||||||
|
printf("Address: %p\n", crash_info.siginfo.si_addr);
|
||||||
|
fputc('\n', stdout);
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
sys_info();
|
||||||
|
|
||||||
|
crash_info.buf[sizeof(crash_info.buf)-1] = '\0';
|
||||||
|
printf("%s\n", crash_info.buf);
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
if(crash_info.pid > 0)
|
||||||
{
|
{
|
||||||
/* Error */
|
gdb_info(crash_info.pid);
|
||||||
case -1:
|
kill(crash_info.pid, SIGKILL);
|
||||||
break;
|
|
||||||
|
|
||||||
case 0:
|
|
||||||
fprintf(stderr, "\n\n*** Fatal Error ***\n"
|
|
||||||
"%s (signal %i)\n", sigdesc, signum);
|
|
||||||
|
|
||||||
/* Redirect shell output */
|
|
||||||
close(STDOUT_FILENO);
|
|
||||||
dup2(fileno(f), STDOUT_FILENO);
|
|
||||||
|
|
||||||
if(f != stderr)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "\nGenerating %s and killing process %i, please wait... ", cc_logfile, pid);
|
|
||||||
fprintf(f, "*** Fatal Error ***\n"
|
|
||||||
"%s (signal %i)\n", sigdesc, signum);
|
|
||||||
}
|
|
||||||
if(siginfo)
|
|
||||||
fprintf(f, "Address: %p\n", siginfo->si_addr);
|
|
||||||
fputc('\n', f);
|
|
||||||
fflush(f);
|
|
||||||
|
|
||||||
/* Get info */
|
|
||||||
sys_info();
|
|
||||||
if(cc_user_info)
|
|
||||||
{
|
|
||||||
if(cc_user_info(user_info_buf, user_info_buf+sizeof(user_info_buf)) > 0)
|
|
||||||
{
|
|
||||||
fprintf(f, "%s\n", user_info_buf);
|
|
||||||
fflush(f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
gdb_info(pid);
|
|
||||||
|
|
||||||
#if 0 /* Why won't this work? */
|
|
||||||
if(ucontext)
|
|
||||||
{
|
|
||||||
unsigned char *ptr = ucontext->uc_stack.ss_sp;
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
fprintf(f, "\n* Stack\n");
|
|
||||||
for(len = ucontext->uc_stack.ss_size/4;len > 0; len -= 4)
|
|
||||||
{
|
|
||||||
fprintf(f, "0x%08x:", (int)ptr);
|
|
||||||
for(i = 0;i < ((len < 4) ? len : 4);++i)
|
|
||||||
{
|
|
||||||
fprintf(f, " %02x%02x%02x%02x", ptr[i*4 + 0], ptr[i*4 + 1],
|
|
||||||
ptr[i*4 + 2], ptr[i*4 + 3]);
|
|
||||||
}
|
|
||||||
fputc(' ', f);
|
|
||||||
fflush(f);
|
|
||||||
for(i = 0;i < ((len < 4) ? len : 4);++i)
|
|
||||||
{
|
|
||||||
fprintf(f, "%c", *(ptr++));
|
|
||||||
fprintf(f, "%c", *(ptr++));
|
|
||||||
fprintf(f, "%c", *(ptr++));
|
|
||||||
fprintf(f, "%c", *(ptr++));
|
|
||||||
}
|
|
||||||
fputc('\n', f);
|
|
||||||
fflush(f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if(f != stderr)
|
|
||||||
{
|
|
||||||
fclose(f);
|
|
||||||
#if (defined __unix__)
|
|
||||||
if(cc_logfile)
|
|
||||||
{
|
|
||||||
char buf[256];
|
|
||||||
snprintf(buf, sizeof(buf),
|
|
||||||
"if (which gxmessage > /dev/null 2>&1);"
|
|
||||||
"then gxmessage -buttons \"Damn it:0\" -center -title \"Very Fatal Error\" -file %s;"
|
|
||||||
"elif (which xmessage > /dev/null 2>&1);"
|
|
||||||
"then xmessage -buttons \"Damn it:0\" -center -file %s -geometry 600x400;"
|
|
||||||
"fi", cc_logfile, cc_logfile);
|
|
||||||
system(buf);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
_exit(0);
|
|
||||||
|
|
||||||
default:
|
|
||||||
/* Wait and let the child attach gdb */
|
|
||||||
waitpid(dbg_pid, NULL, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(logfile)
|
||||||
|
{
|
||||||
|
const char *str;
|
||||||
|
char buf[512];
|
||||||
|
|
||||||
|
if((str=getenv("KDE_FULL_SESSION")) && strcmp(str, "true") == 0)
|
||||||
|
snprintf(buf, sizeof(buf), "kdialog --title \"Very Fatal Error\" --textbox \"%s\" 800 600", logfile);
|
||||||
|
else if((str=getenv("GNOME_DESKTOP_SESSION_ID")) && str[0] != '\0')
|
||||||
|
snprintf(buf, sizeof(buf), "gxmessage -buttons \"Okay:0\" -geometry 800x600 -title \"Very Fatal Error\" -center -file \"%s\"", logfile);
|
||||||
|
else
|
||||||
|
snprintf(buf, sizeof(buf), "xmessage -buttons \"Okay:0\" -center -file \"%s\"", logfile);
|
||||||
|
|
||||||
|
system(buf);
|
||||||
|
}
|
||||||
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int cc_install_handlers(int num_signals, int *signals, const char *logfile, int (*user_info)(char*, char*))
|
int cc_install_handlers(int argc, char **argv, int num_signals, int *signals, const char *logfile, int (*user_info)(char*, char*))
|
||||||
{
|
{
|
||||||
int retval = 0;
|
|
||||||
struct sigaction sa;
|
struct sigaction sa;
|
||||||
memset(&sa, 0, sizeof(sa));
|
stack_t altss;
|
||||||
|
int retval;
|
||||||
|
|
||||||
sa.sa_sigaction = crash_catcher;
|
if(argc == 2 && strcmp(argv[1], crash_switch) == 0)
|
||||||
|
crash_handler(logfile);
|
||||||
|
|
||||||
#if !defined(__FreeBSD__) && !defined(__APPLE__)
|
|
||||||
sa.sa_flags = SA_ONESHOT | SA_NODEFER | SA_SIGINFO;
|
|
||||||
#else
|
|
||||||
sa.sa_flags = SA_NODEFER | SA_SIGINFO;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
cc_logfile = logfile;
|
|
||||||
cc_user_info = user_info;
|
cc_user_info = user_info;
|
||||||
|
|
||||||
|
if(argv[0][0] == '/')
|
||||||
|
snprintf(argv0, sizeof(argv0), "%s", argv[0]);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
getcwd(argv0, sizeof(argv0));
|
||||||
|
retval = strlen(argv0);
|
||||||
|
snprintf(argv0+retval, sizeof(argv0)-retval, "/%s", argv[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set an alternate signal stack so SIGSEGVs caused by stack overflows
|
||||||
|
* still run */
|
||||||
|
altss.ss_sp = altstack;
|
||||||
|
altss.ss_flags = 0;
|
||||||
|
altss.ss_size = sizeof(altstack);
|
||||||
|
sigaltstack(&altss, NULL);
|
||||||
|
|
||||||
|
memset(&sa, 0, sizeof(sa));
|
||||||
|
sa.sa_sigaction = crash_catcher;
|
||||||
|
sa.sa_flags = SA_RESETHAND | SA_NODEFER | SA_SIGINFO | SA_ONSTACK;
|
||||||
|
sigemptyset(&sa.sa_mask);
|
||||||
|
|
||||||
|
retval = 0;
|
||||||
while(num_signals--)
|
while(num_signals--)
|
||||||
{
|
{
|
||||||
if((*signals != SIGSEGV && *signals != SIGILL && *signals != SIGFPE &&
|
if((*signals != SIGSEGV && *signals != SIGILL && *signals != SIGFPE &&
|
||||||
|
@ -408,6 +422,5 @@ int cc_install_handlers(int num_signals, int *signals, const char *logfile, int
|
||||||
}
|
}
|
||||||
++signals;
|
++signals;
|
||||||
}
|
}
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,7 +73,7 @@
|
||||||
|
|
||||||
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
||||||
|
|
||||||
extern "C" int cc_install_handlers(int, int*, const char*, int(*)(char*, char*));
|
extern "C" int cc_install_handlers(int, char**, int, int*, const char*, int(*)(char*, char*));
|
||||||
|
|
||||||
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
|
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
|
||||||
|
|
||||||
|
@ -156,13 +156,14 @@ static void STACK_ARGS NewFailure ()
|
||||||
static int DoomSpecificInfo (char *buffer, char *end)
|
static int DoomSpecificInfo (char *buffer, char *end)
|
||||||
{
|
{
|
||||||
const char *arg;
|
const char *arg;
|
||||||
int size = end-buffer;
|
int size = end-buffer-2;
|
||||||
int i, p;
|
int i, p;
|
||||||
|
|
||||||
SDL_Quit();
|
|
||||||
|
|
||||||
p = 0;
|
p = 0;
|
||||||
p += snprintf (buffer+p, size-p, GAMENAME" version " DOTVERSIONSTR " (" __DATE__ ")\n");
|
p += snprintf (buffer+p, size-p, GAMENAME" version " DOTVERSIONSTR " (" __DATE__ ")\n");
|
||||||
|
#ifdef __VERSION__
|
||||||
|
p += snprintf (buffer+p, size-p, "Compiler version: %s\n", __VERSION__);
|
||||||
|
#endif
|
||||||
p += snprintf (buffer+p, size-p, "\nCommand line:");
|
p += snprintf (buffer+p, size-p, "\nCommand line:");
|
||||||
for (i = 0; i < Args->NumArgs(); ++i)
|
for (i = 0; i < Args->NumArgs(); ++i)
|
||||||
{
|
{
|
||||||
|
@ -250,14 +251,14 @@ void I_ShutdownJoysticks();
|
||||||
|
|
||||||
int main (int argc, char **argv)
|
int main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
printf(GAMENAME" v%s - SVN revision %s - SDL version\nCompiled on %s\n\n",
|
|
||||||
DOTVERSIONSTR_NOREV,SVN_REVISION_STRING,__DATE__);
|
|
||||||
|
|
||||||
{
|
{
|
||||||
int s[4] = { SIGSEGV, SIGILL, SIGFPE, SIGBUS };
|
int s[4] = { SIGSEGV, SIGILL, SIGFPE, SIGBUS };
|
||||||
cc_install_handlers(4, s, "zdoom-crash.log", DoomSpecificInfo);
|
cc_install_handlers(argc, argv, 4, s, "zdoom-crash.log", DoomSpecificInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printf(GAMENAME" v%s - SVN revision %s - SDL version\nCompiled on %s\n\n",
|
||||||
|
DOTVERSIONSTR_NOREV,SVN_REVISION_STRING,__DATE__);
|
||||||
|
|
||||||
seteuid (getuid ());
|
seteuid (getuid ());
|
||||||
std::set_new_handler (NewFailure);
|
std::set_new_handler (NewFailure);
|
||||||
|
|
||||||
|
|
|
@ -608,6 +608,57 @@ int I_PickIWad (WadStuff *wads, int numwads, bool showwin, int defaultiwad)
|
||||||
return defaultiwad;
|
return defaultiwad;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !defined(__APPLE__)
|
||||||
|
const char *str;
|
||||||
|
if((str=getenv("KDE_FULL_SESSION")) && strcmp(str, "true") == 0)
|
||||||
|
{
|
||||||
|
FString cmd("kdialog --title \""GAMESIG" "DOTVERSIONSTR": Select an IWAD to use\""
|
||||||
|
" --menu \"ZDoom found more than one IWAD\n"
|
||||||
|
"Select from the list below to determine which one to use:\"");
|
||||||
|
|
||||||
|
for(i = 0; i < numwads; ++i)
|
||||||
|
{
|
||||||
|
const char *filepart = strrchr(wads[i].Path, '/');
|
||||||
|
if(filepart == NULL)
|
||||||
|
filepart = wads[i].Path;
|
||||||
|
else
|
||||||
|
filepart++;
|
||||||
|
// Menu entries are specified in "tag" "item" pairs, where when a
|
||||||
|
// particular item is selected (and the Okay button clicked), its
|
||||||
|
// corresponding tag is printed to stdout for identification.
|
||||||
|
cmd.AppendFormat(" \"%d\" \"%s (%s)\"", i, wads[i].Name.GetChars(), filepart);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(defaultiwad >= 0 && defaultiwad < numwads)
|
||||||
|
{
|
||||||
|
const char *filepart = strrchr(wads[defaultiwad].Path, '/');
|
||||||
|
if(filepart == NULL)
|
||||||
|
filepart = wads[defaultiwad].Path;
|
||||||
|
else
|
||||||
|
filepart++;
|
||||||
|
cmd.AppendFormat(" --default \"%s (%s)\"", wads[defaultiwad].Name.GetChars(), filepart);
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *f = popen(cmd, "r");
|
||||||
|
if(f != NULL)
|
||||||
|
{
|
||||||
|
char gotstr[16];
|
||||||
|
|
||||||
|
if(fgets(gotstr, sizeof(gotstr), f) == NULL ||
|
||||||
|
sscanf(gotstr, "%d", &i) != 1)
|
||||||
|
i = -1;
|
||||||
|
|
||||||
|
// Exit status = 1 means the selection was canceled (either by
|
||||||
|
// Cancel/Esc or the X button), not that there was an error running
|
||||||
|
// the program. In that case, nothing was printed so fgets will
|
||||||
|
// have failed. Other values can indicate an error running the app,
|
||||||
|
// so fall back to whatever else can be used.
|
||||||
|
int status = pclose(f);
|
||||||
|
if(WIFEXITED(status) && (WEXITSTATUS(status) == 0 || WEXITSTATUS(status) == 1))
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#ifndef NO_GTK
|
#ifndef NO_GTK
|
||||||
if (GtkAvailable)
|
if (GtkAvailable)
|
||||||
{
|
{
|
||||||
|
|
|
@ -2555,7 +2555,7 @@ void FMODSoundRenderer::DrawWaveDebug(int mode)
|
||||||
// 16 pixels of padding between each window.
|
// 16 pixels of padding between each window.
|
||||||
window_size = (screen->GetWidth() - 16) / numoutchans - 16;
|
window_size = (screen->GetWidth() - 16) / numoutchans - 16;
|
||||||
|
|
||||||
float *wavearray = (float*)alloca(window_size*sizeof(float));
|
float *wavearray = (float*)alloca(MAX(SPECTRUM_SIZE,window_size)*sizeof(float));
|
||||||
|
|
||||||
y = 16;
|
y = 16;
|
||||||
y = DrawChannelGroupOutput(SfxGroup, wavearray, window_size, window_height, y, mode);
|
y = DrawChannelGroupOutput(SfxGroup, wavearray, window_size, window_height, y, mode);
|
||||||
|
|
|
@ -60,7 +60,7 @@ extern fixed_t finesine[5*FINEANGLES/4];
|
||||||
// (encapsulated in a struct so that we can still use array accesses).
|
// (encapsulated in a struct so that we can still use array accesses).
|
||||||
struct cosine_inline
|
struct cosine_inline
|
||||||
{
|
{
|
||||||
fixed_t operator[] (unsigned int x)
|
fixed_t operator[] (unsigned int x) const
|
||||||
{
|
{
|
||||||
return finesine[x+FINEANGLES/4];
|
return finesine[x+FINEANGLES/4];
|
||||||
}
|
}
|
||||||
|
|
|
@ -234,6 +234,7 @@ void FTextureManager::AddTiles (void *tiles)
|
||||||
rot.Texture[8] =
|
rot.Texture[8] =
|
||||||
rot.Texture[9] = texnum.GetIndex() + 4;
|
rot.Texture[9] = texnum.GetIndex() + 4;
|
||||||
rot.Flip = 0x00FC;
|
rot.Flip = 0x00FC;
|
||||||
|
rot.Voxel = NULL;
|
||||||
tex->Rotations = SpriteFrames.Push (rot);
|
tex->Rotations = SpriteFrames.Push (rot);
|
||||||
}
|
}
|
||||||
else if (rotType == 2)
|
else if (rotType == 2)
|
||||||
|
@ -247,6 +248,7 @@ void FTextureManager::AddTiles (void *tiles)
|
||||||
rot.Texture[17-j*2] = texnum.GetIndex() + j;
|
rot.Texture[17-j*2] = texnum.GetIndex() + j;
|
||||||
}
|
}
|
||||||
rot.Flip = 0;
|
rot.Flip = 0;
|
||||||
|
rot.Voxel = NULL;
|
||||||
tex->Rotations = SpriteFrames.Push (rot);
|
tex->Rotations = SpriteFrames.Push (rot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2070,6 +2070,15 @@ DEFINE_CLASS_PROPERTY_PREFIX(player, morphweapon, S, PlayerPawn)
|
||||||
defaults->MorphWeapon = FName(z);
|
defaults->MorphWeapon = FName(z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
DEFINE_CLASS_PROPERTY_PREFIX(player, flechettetype, S, PlayerPawn)
|
||||||
|
{
|
||||||
|
PROP_STRING_PARM(str, 0);
|
||||||
|
defaults->FlechetteType = FindClassTentative(str, "ArtiPoisonBag");
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
|
@ -1313,6 +1313,21 @@ void DFrameBuffer::RenderView(player_t *player)
|
||||||
FCanvasTextureInfo::UpdateAll ();
|
FCanvasTextureInfo::UpdateAll ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
extern TDeletingArray<FVoxel *> Voxels;
|
||||||
|
|
||||||
|
void DFrameBuffer::RemapVoxels()
|
||||||
|
{
|
||||||
|
for (unsigned i=0; i<Voxels.Size(); i++)
|
||||||
|
{
|
||||||
|
Voxels[i]->Remap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
// Render the view to a savegame picture
|
// Render the view to a savegame picture
|
||||||
|
@ -1689,6 +1704,7 @@ void V_Init2()
|
||||||
Printf ("Resolution: %d x %d\n", SCREENWIDTH, SCREENHEIGHT);
|
Printf ("Resolution: %d x %d\n", SCREENWIDTH, SCREENHEIGHT);
|
||||||
|
|
||||||
screen->SetGamma (gamma);
|
screen->SetGamma (gamma);
|
||||||
|
screen->RemapVoxels();
|
||||||
FBaseCVar::ResetColors ();
|
FBaseCVar::ResetColors ();
|
||||||
C_NewModeAdjust();
|
C_NewModeAdjust();
|
||||||
M_InitVideoModesMenu();
|
M_InitVideoModesMenu();
|
||||||
|
@ -1733,43 +1749,61 @@ CUSTOM_CVAR (Int, vid_aspect, 0, CVAR_GLOBALCONFIG|CVAR_ARCHIVE)
|
||||||
// 1: 16:9
|
// 1: 16:9
|
||||||
// 2: 16:10
|
// 2: 16:10
|
||||||
// 4: 5:4
|
// 4: 5:4
|
||||||
int CheckRatio (int width, int height)
|
int CheckRatio (int width, int height, int *trueratio)
|
||||||
{
|
{
|
||||||
|
int fakeratio = -1;
|
||||||
|
int ratio;
|
||||||
|
|
||||||
if ((vid_aspect >=1) && (vid_aspect <=4))
|
if ((vid_aspect >=1) && (vid_aspect <=4))
|
||||||
{
|
{
|
||||||
// [SP] User wants to force aspect ratio; let them.
|
// [SP] User wants to force aspect ratio; let them.
|
||||||
return vid_aspect == 3? 0: int(vid_aspect);
|
fakeratio = vid_aspect == 3? 0: int(vid_aspect);
|
||||||
}
|
}
|
||||||
if (vid_nowidescreen)
|
if (vid_nowidescreen)
|
||||||
{
|
{
|
||||||
if (!vid_tft)
|
if (!vid_tft)
|
||||||
{
|
{
|
||||||
return 0;
|
fakeratio = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fakeratio = (height * 5/4 == width) ? 4 : 0;
|
||||||
}
|
}
|
||||||
return (height * 5/4 == width) ? 4 : 0;
|
|
||||||
}
|
}
|
||||||
// If the size is approximately 16:9, consider it so.
|
// If the size is approximately 16:9, consider it so.
|
||||||
if (abs (height * 16/9 - width) < 10)
|
if (abs (height * 16/9 - width) < 10)
|
||||||
{
|
{
|
||||||
return 1;
|
ratio = 1;
|
||||||
}
|
}
|
||||||
// 16:10 has more variance in the pixel dimensions. Grr.
|
// 16:10 has more variance in the pixel dimensions. Grr.
|
||||||
if (abs (height * 16/10 - width) < 60)
|
else if (abs (height * 16/10 - width) < 60)
|
||||||
{
|
{
|
||||||
// 320x200 and 640x400 are always 4:3, not 16:10
|
// 320x200 and 640x400 are always 4:3, not 16:10
|
||||||
if ((width == 320 && height == 200) || (width == 640 && height == 400))
|
if ((width == 320 && height == 200) || (width == 640 && height == 400))
|
||||||
{
|
{
|
||||||
return 0;
|
ratio = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ratio = 2;
|
||||||
}
|
}
|
||||||
return 2;
|
|
||||||
}
|
}
|
||||||
// Unless vid_tft is set, 1280x1024 is 4:3, not 5:4.
|
// Unless vid_tft is set, 1280x1024 is 4:3, not 5:4.
|
||||||
if (height * 5/4 == width && vid_tft)
|
else if (height * 5/4 == width && vid_tft)
|
||||||
{
|
{
|
||||||
return 4;
|
ratio = 4;
|
||||||
}
|
}
|
||||||
// Assume anything else is 4:3.
|
// Assume anything else is 4:3.
|
||||||
return 0;
|
else
|
||||||
|
{
|
||||||
|
ratio = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trueratio != NULL)
|
||||||
|
{
|
||||||
|
*trueratio = ratio;
|
||||||
|
}
|
||||||
|
return (fakeratio >= 0) ? fakeratio : ratio;
|
||||||
}
|
}
|
||||||
|
|
||||||
// First column: Base width (unused)
|
// First column: Base width (unused)
|
||||||
|
|
|
@ -364,6 +364,9 @@ public:
|
||||||
// Set the rect defining the area affected by blending.
|
// Set the rect defining the area affected by blending.
|
||||||
virtual void SetBlendingRect (int x1, int y1, int x2, int y2);
|
virtual void SetBlendingRect (int x1, int y1, int x2, int y2);
|
||||||
|
|
||||||
|
// Remap voxel palette
|
||||||
|
virtual void RemapVoxels();
|
||||||
|
|
||||||
// render 3D view
|
// render 3D view
|
||||||
virtual void RenderView(player_t *player);
|
virtual void RenderView(player_t *player);
|
||||||
|
|
||||||
|
@ -500,7 +503,7 @@ void V_DrawFrame (int left, int top, int width, int height);
|
||||||
extern "C" void ASM_PatchPitch (void);
|
extern "C" void ASM_PatchPitch (void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int CheckRatio (int width, int height);
|
int CheckRatio (int width, int height, int *trueratio=NULL);
|
||||||
static inline int CheckRatio (double width, double height) { return CheckRatio(int(width), int(height)); }
|
static inline int CheckRatio (double width, double height) { return CheckRatio(int(width), int(height)); }
|
||||||
extern const int BaseRatioSizes[5][4];
|
extern const int BaseRatioSizes[5][4];
|
||||||
|
|
||||||
|
|
|
@ -64,7 +64,7 @@
|
||||||
// Protocol version used in demos.
|
// Protocol version used in demos.
|
||||||
// Bump it if you change existing DEM_ commands or add new ones.
|
// Bump it if you change existing DEM_ commands or add new ones.
|
||||||
// Otherwise, it should be safe to leave it alone.
|
// Otherwise, it should be safe to leave it alone.
|
||||||
#define DEMOGAMEVERSION 0x213
|
#define DEMOGAMEVERSION 0x214
|
||||||
|
|
||||||
// Minimum demo version we can play.
|
// Minimum demo version we can play.
|
||||||
// Bump it whenever you change or remove existing DEM_ commands.
|
// Bump it whenever you change or remove existing DEM_ commands.
|
||||||
|
@ -75,7 +75,7 @@
|
||||||
// SAVESIG should match SAVEVER.
|
// SAVESIG should match SAVEVER.
|
||||||
|
|
||||||
// MINSAVEVER is the minimum level snapshot version that can be loaded.
|
// MINSAVEVER is the minimum level snapshot version that can be loaded.
|
||||||
#define MINSAVEVER 3030
|
#define MINSAVEVER 3085
|
||||||
|
|
||||||
#if SVN_REVISION_NUMBER < MINSAVEVER
|
#if SVN_REVISION_NUMBER < MINSAVEVER
|
||||||
// If we don't know the current revision write something very high to ensure that
|
// If we don't know the current revision write something very high to ensure that
|
||||||
|
|
|
@ -62,6 +62,7 @@ typedef enum {
|
||||||
ns_bloodmisc,
|
ns_bloodmisc,
|
||||||
ns_strifevoices,
|
ns_strifevoices,
|
||||||
ns_hires,
|
ns_hires,
|
||||||
|
ns_voxels,
|
||||||
|
|
||||||
// These namespaces are only used to mark lumps in special subdirectories
|
// These namespaces are only used to mark lumps in special subdirectories
|
||||||
// so that their contents doesn't interfere with the global namespace.
|
// so that their contents doesn't interfere with the global namespace.
|
||||||
|
|
|
@ -3677,6 +3677,14 @@ bool D3DFB::SetStyle(D3DTex *tex, DrawParms &parms, D3DCOLOR &color0, D3DCOLOR &
|
||||||
alpha = clamp<fixed_t> (parms.alpha, 0, FRACUNIT) / 65536.f;
|
alpha = clamp<fixed_t> (parms.alpha, 0, FRACUNIT) / 65536.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
style.CheckFuzz();
|
||||||
|
if (style.BlendOp == STYLEOP_Shadow)
|
||||||
|
{
|
||||||
|
style = LegacyRenderStyles[STYLE_TranslucentStencil];
|
||||||
|
alpha = 0.3f;
|
||||||
|
parms.fillcolor = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: Fuzz effect is not written
|
// FIXME: Fuzz effect is not written
|
||||||
if (style.BlendOp == STYLEOP_FuzzOrAdd || style.BlendOp == STYLEOP_Fuzz)
|
if (style.BlendOp == STYLEOP_FuzzOrAdd || style.BlendOp == STYLEOP_Fuzz)
|
||||||
{
|
{
|
||||||
|
|
|
@ -28,6 +28,7 @@ ACTOR ClericPlayer : PlayerPawn
|
||||||
Player.WeaponSlot 2, CWeapStaff
|
Player.WeaponSlot 2, CWeapStaff
|
||||||
Player.WeaponSlot 3, CWeapFlame
|
Player.WeaponSlot 3, CWeapFlame
|
||||||
Player.WeaponSlot 4, CWeapWraithverge
|
Player.WeaponSlot 4, CWeapWraithverge
|
||||||
|
Player.FlechetteType "ArtiPoisonBag1"
|
||||||
|
|
||||||
Player.ColorRange 146, 163
|
Player.ColorRange 146, 163
|
||||||
Player.Colorset 0, "Blue", 146, 163, 161
|
Player.Colorset 0, "Blue", 146, 163, 161
|
||||||
|
|
|
@ -30,6 +30,7 @@ ACTOR MagePlayer : PlayerPawn
|
||||||
Player.WeaponSlot 2, MWeapFrost
|
Player.WeaponSlot 2, MWeapFrost
|
||||||
Player.WeaponSlot 3, MWeapLightning
|
Player.WeaponSlot 3, MWeapLightning
|
||||||
Player.WeaponSlot 4, MWeapBloodscourge
|
Player.WeaponSlot 4, MWeapBloodscourge
|
||||||
|
Player.FlechetteType "ArtiPoisonBag2"
|
||||||
|
|
||||||
Player.ColorRange 146, 163
|
Player.ColorRange 146, 163
|
||||||
Player.Colorset 0, "Blue", 146, 163, 161
|
Player.Colorset 0, "Blue", 146, 163, 161
|
||||||
|
|
|
@ -28,6 +28,7 @@ Actor PlayerPawn : Actor native
|
||||||
Player.SoundClass "player"
|
Player.SoundClass "player"
|
||||||
Player.DamageScreenColor "ff 00 00"
|
Player.DamageScreenColor "ff 00 00"
|
||||||
Player.MugShotMaxHealth 0
|
Player.MugShotMaxHealth 0
|
||||||
|
Player.FlechetteType "ArtiPoisonBag3"
|
||||||
}
|
}
|
||||||
|
|
||||||
Actor PlayerChunk : PlayerPawn native
|
Actor PlayerChunk : PlayerPawn native
|
||||||
|
|
|
@ -26,7 +26,6 @@ IWad
|
||||||
Game = "Doom"
|
Game = "Doom"
|
||||||
Config = "UrbanBrawl"
|
Config = "UrbanBrawl"
|
||||||
Mapinfo = "mapinfo/urbanbrawl.txt"
|
Mapinfo = "mapinfo/urbanbrawl.txt"
|
||||||
Compatibility = "Portals"
|
|
||||||
MustContain = "MAP01", "AD2LIB"
|
MustContain = "MAP01", "AD2LIB"
|
||||||
BannerColors = "a8 a8 00", "a8 00 00"
|
BannerColors = "a8 a8 00", "a8 00 00"
|
||||||
}
|
}
|
||||||
|
|
|
@ -640,6 +640,13 @@ OptionValue Contrast
|
||||||
2.0, "Smooth"
|
2.0, "Smooth"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OptionValue Fuzziness
|
||||||
|
{
|
||||||
|
0.0, "Translucent"
|
||||||
|
1.0, "Fuzz"
|
||||||
|
2.0, "Shadow"
|
||||||
|
}
|
||||||
|
|
||||||
OptionMenu "VideoOptions"
|
OptionMenu "VideoOptions"
|
||||||
{
|
{
|
||||||
Title "DISPLAY OPTIONS"
|
Title "DISPLAY OPTIONS"
|
||||||
|
@ -662,7 +669,7 @@ OptionMenu "VideoOptions"
|
||||||
}
|
}
|
||||||
|
|
||||||
Option "Stretch short skies", "r_stretchsky", "OnOff"
|
Option "Stretch short skies", "r_stretchsky", "OnOff"
|
||||||
Option "Use fuzz effect", "r_drawfuzz", "YesNo"
|
Option "Use fuzz effect", "r_drawfuzz", "Fuzziness"
|
||||||
Slider "Lost Soul translucency", "transsouls", 0.25, 1.0, 0.05, 2
|
Slider "Lost Soul translucency", "transsouls", 0.25, 1.0, 0.05, 2
|
||||||
Option "Use fake contrast", "r_fakecontrast", "Contrast"
|
Option "Use fake contrast", "r_fakecontrast", "Contrast"
|
||||||
Option "Rocket Trails", "cl_rockettrails", "RocketTrailTypes"
|
Option "Rocket Trails", "cl_rockettrails", "RocketTrailTypes"
|
||||||
|
|
|
@ -114,29 +114,26 @@ statusbar Normal
|
||||||
drawimage "ARMCLS", 255, 178;
|
drawimage "ARMCLS", 255, 178;
|
||||||
drawnumber 2, HUDFONT_RAVEN, untranslated, armorclass, 275, 176, 1;
|
drawnumber 2, HUDFONT_RAVEN, untranslated, armorclass, 275, 176, 1;
|
||||||
|
|
||||||
playerclass Cleric
|
playertype ClericPlayer
|
||||||
{
|
{
|
||||||
drawimage "WPSLOT1", 190, 162;
|
drawimage "WPSLOT1", 190, 162;
|
||||||
hasweaponpiece CWeapWraithverge, 1
|
ininventory CWeapWraithverge
|
||||||
{
|
{
|
||||||
drawimage "WPIECEC1", 190, 162;
|
drawimage "WPFULL1", 190, 162;
|
||||||
}
|
}
|
||||||
hasweaponpiece CWeapWraithverge, 2
|
else
|
||||||
{
|
|
||||||
drawimage "WPIECEC2", 212, 162;
|
|
||||||
}
|
|
||||||
hasweaponpiece CWeapWraithverge, 3
|
|
||||||
{
|
|
||||||
drawimage "WPIECEC3", 225, 162;
|
|
||||||
}
|
|
||||||
hasweaponpiece CWeapWraithverge, 1
|
|
||||||
{
|
{
|
||||||
|
hasweaponpiece CWeapWraithverge, 1
|
||||||
|
{
|
||||||
|
drawimage "WPIECEC1", 190, 162;
|
||||||
|
}
|
||||||
hasweaponpiece CWeapWraithverge, 2
|
hasweaponpiece CWeapWraithverge, 2
|
||||||
{
|
{
|
||||||
hasweaponpiece CWeapWraithverge, 3
|
drawimage "WPIECEC2", 212, 162;
|
||||||
{
|
}
|
||||||
drawimage "WPFULL1", 190, 162;
|
hasweaponpiece CWeapWraithverge, 3
|
||||||
}
|
{
|
||||||
|
drawimage "WPIECEC3", 225, 162;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,29 +142,26 @@ statusbar Normal
|
||||||
else
|
else
|
||||||
drawgem translatable, interpolate(6), "CHAIN2", "LIFEGMC2", -23, 49, 15, 30, 193;
|
drawgem translatable, interpolate(6), "CHAIN2", "LIFEGMC2", -23, 49, 15, 30, 193;
|
||||||
}
|
}
|
||||||
else playerclass Mage
|
else playertype MagePlayer
|
||||||
{
|
{
|
||||||
drawimage "WPSLOT2", 190, 162;
|
drawimage "WPSLOT2", 190, 162;
|
||||||
hasweaponpiece MWeapBloodscourge, 1
|
ininventory MWeapBloodscourge
|
||||||
{
|
{
|
||||||
drawimage "WPIECEM1", 190, 162;
|
drawimage "WPFULL2", 190, 162;
|
||||||
}
|
}
|
||||||
hasweaponpiece MWeapBloodscourge, 2
|
else
|
||||||
{
|
|
||||||
drawimage "WPIECEM2", 205, 162;
|
|
||||||
}
|
|
||||||
hasweaponpiece MWeapBloodscourge, 3
|
|
||||||
{
|
|
||||||
drawimage "WPIECEM3", 224, 162;
|
|
||||||
}
|
|
||||||
hasweaponpiece MWeapBloodscourge, 1
|
|
||||||
{
|
{
|
||||||
|
hasweaponpiece MWeapBloodscourge, 1
|
||||||
|
{
|
||||||
|
drawimage "WPIECEM1", 190, 162;
|
||||||
|
}
|
||||||
hasweaponpiece MWeapBloodscourge, 2
|
hasweaponpiece MWeapBloodscourge, 2
|
||||||
{
|
{
|
||||||
hasweaponpiece MWeapBloodscourge, 3
|
drawimage "WPIECEM2", 205, 162;
|
||||||
{
|
}
|
||||||
drawimage "WPFULL2", 190, 162;
|
hasweaponpiece MWeapBloodscourge, 3
|
||||||
}
|
{
|
||||||
|
drawimage "WPIECEM3", 224, 162;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,26 +173,23 @@ statusbar Normal
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
drawimage "WPSLOT0", 190, 162;
|
drawimage "WPSLOT0", 190, 162;
|
||||||
hasweaponpiece FWeapQuietus, 1
|
ininventory FWeapQuietus
|
||||||
{
|
{
|
||||||
drawimage "WPIECEF1", 190, 162;
|
drawimage "WPFULL0", 190, 162;
|
||||||
}
|
}
|
||||||
hasweaponpiece FWeapQuietus, 2
|
else
|
||||||
{
|
|
||||||
drawimage "WPIECEF2", 225, 162;
|
|
||||||
}
|
|
||||||
hasweaponpiece FWeapQuietus, 3
|
|
||||||
{
|
|
||||||
drawimage "WPIECEF3", 234, 162;
|
|
||||||
}
|
|
||||||
hasweaponpiece FWeapQuietus, 1
|
|
||||||
{
|
{
|
||||||
|
hasweaponpiece FWeapQuietus, 1
|
||||||
|
{
|
||||||
|
drawimage "WPIECEF1", 190, 162;
|
||||||
|
}
|
||||||
hasweaponpiece FWeapQuietus, 2
|
hasweaponpiece FWeapQuietus, 2
|
||||||
{
|
{
|
||||||
hasweaponpiece FWeapQuietus, 3
|
drawimage "WPIECEF2", 225, 162;
|
||||||
{
|
}
|
||||||
drawimage "WPFULL0", 190, 162;
|
hasweaponpiece FWeapQuietus, 3
|
||||||
}
|
{
|
||||||
|
drawimage "WPIECEF3", 234, 162;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -222,21 +213,21 @@ statusbar Automap
|
||||||
drawimage hexenarmor amulet, "ARMSLOT4", 243, 164;
|
drawimage hexenarmor amulet, "ARMSLOT4", 243, 164;
|
||||||
|
|
||||||
// Also draw the life gem here
|
// Also draw the life gem here
|
||||||
playerclass Fighter
|
playertype FighterPlayer
|
||||||
{
|
{
|
||||||
gamemode singleplayer
|
gamemode singleplayer
|
||||||
drawgem interpolate(6), "CHAIN", "LIFEGMF2", -23, 49, 15, 30, 193;
|
drawgem interpolate(6), "CHAIN", "LIFEGMF2", -23, 49, 15, 30, 193;
|
||||||
else
|
else
|
||||||
drawgem translatable, interpolate(6), "CHAIN", "LIFEGMF2", -23, 49, 15, 30, 193;
|
drawgem translatable, interpolate(6), "CHAIN", "LIFEGMF2", -23, 49, 15, 30, 193;
|
||||||
}
|
}
|
||||||
else playerclass Cleric
|
else playertype ClericPlayer
|
||||||
{
|
{
|
||||||
gamemode singleplayer
|
gamemode singleplayer
|
||||||
drawgem interpolate(6), "CHAIN2", "LIFEGMC2", -23, 49, 15, 30, 193;
|
drawgem interpolate(6), "CHAIN2", "LIFEGMC2", -23, 49, 15, 30, 193;
|
||||||
else
|
else
|
||||||
drawgem translatable, interpolate(6), "CHAIN2", "LIFEGMC2", -23, 49, 15, 30, 193;
|
drawgem translatable, interpolate(6), "CHAIN2", "LIFEGMC2", -23, 49, 15, 30, 193;
|
||||||
}
|
}
|
||||||
else playerclass Mage
|
else playertype MagePlayer
|
||||||
{
|
{
|
||||||
gamemode singleplayer
|
gamemode singleplayer
|
||||||
drawgem interpolate(6), "CHAIN3", "LIFEGMM2", -23, 49, 15, 30, 193;
|
drawgem interpolate(6), "CHAIN3", "LIFEGMM2", -23, 49, 15, 30, 193;
|
||||||
|
|
|
@ -704,6 +704,10 @@
|
||||||
RelativePath=".\src\md5.cpp"
|
RelativePath=".\src\md5.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\src\memarena.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\src\name.cpp"
|
RelativePath=".\src\name.cpp"
|
||||||
>
|
>
|
||||||
|
@ -1353,6 +1357,10 @@
|
||||||
RelativePath=".\src\md5.h"
|
RelativePath=".\src\md5.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\src\memarena.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\src\mscinlines.h"
|
RelativePath=".\src\mscinlines.h"
|
||||||
>
|
>
|
||||||
|
|
Loading…
Reference in a new issue