Compare commits
255
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2800685cfc | ||
|
|
c479d9d706 | ||
|
|
338fbfbeaf | ||
|
|
5ca12bb421 | ||
|
|
6c94e0c9bf | ||
|
|
83d0f6bb50 | ||
|
|
7e06fc986f | ||
|
|
3f5328371a | ||
|
|
148fcc8dab | ||
|
|
72a67d306f | ||
|
|
0dcdcc3da1 | ||
|
|
729c60c9b0 | ||
|
|
1b418caf6b | ||
|
|
d275db9bb4 | ||
|
|
21cfd7c361 | ||
|
|
5a44afcd9f | ||
|
|
3c282b5022 | ||
|
|
f4d40bd55f | ||
|
|
5d8bb3223f | ||
|
|
5e1f943a38 | ||
|
|
612431c1f1 | ||
|
|
fca7b4a837 | ||
|
|
d2bab80b29 | ||
|
|
465fea8bb3 | ||
|
|
78ab90c1a6 | ||
|
|
102e944fd5 | ||
|
|
04385d9700 | ||
|
|
d47e20b54e | ||
|
|
7ef2da5922 | ||
|
|
5638709670 | ||
|
|
9bd4a933cf | ||
|
|
e233635783 | ||
|
|
da24ba20c7 | ||
|
|
74bdabc636 | ||
|
|
4b129314d3 | ||
|
|
3a55972997 | ||
|
|
6e04e4171e | ||
|
|
4e9f9b7e0e | ||
|
|
9650139470 | ||
|
|
054a40a4b2 | ||
|
|
db67176eca | ||
|
|
0b7a4ff4e0 | ||
|
|
972ee5cf76 | ||
|
|
aef02cb347 | ||
|
|
36e485b2a3 | ||
|
|
d23c51e707 | ||
|
|
0db437aadd | ||
|
|
e351c1e62a | ||
|
|
b541de4f8c | ||
|
|
604bc40021 | ||
|
|
be8ddebd80 | ||
|
|
02feb3ad5c | ||
|
|
49f13d2a59 | ||
|
|
b2a36850cb | ||
|
|
8353c1efdd | ||
|
|
d19a2e0912 | ||
|
|
07432c0381 | ||
|
|
4fb3b63152 | ||
|
|
85b736620a | ||
|
|
9f770993d4 | ||
|
|
4bd02ad325 | ||
|
|
6e7b45d15c | ||
|
|
99ebca51d5 | ||
|
|
24eb888af3 | ||
|
|
09ce33abb9 | ||
|
|
044ff158a1 | ||
|
|
36c68d055c | ||
|
|
ddf7d7cdcb | ||
|
|
38950d580f | ||
|
|
707701f317 | ||
|
|
09507d635b | ||
|
|
ab85d6a693 | ||
|
|
5011b17f88 | ||
|
|
7bef45f701 | ||
|
|
40cbce8f9f | ||
|
|
70a70084c9 | ||
|
|
b6da6359d3 | ||
|
|
97075ca5c5 | ||
|
|
e94737945a | ||
|
|
57f15e0213 | ||
|
|
2eae9b197c | ||
|
|
68c7620349 | ||
|
|
7a3faf34e7 | ||
|
|
d401644447 | ||
|
|
dfc349b230 | ||
|
|
687d2bd894 | ||
|
|
78b642cf2d | ||
|
|
cb3b6ca34b | ||
|
|
ad15bf0ea3 | ||
|
|
56021ed999 | ||
|
|
3d22a5906f | ||
|
|
b6d771b48f | ||
|
|
ab30fb2e5e | ||
|
|
618d9e4cdf | ||
|
|
bf78ad9c75 | ||
|
|
918a4e8cd9 | ||
|
|
e90c84c9ac | ||
|
|
a9209a4887 | ||
|
|
0a3e7ba09f | ||
|
|
eb132b08c0 | ||
|
|
82407c3560 | ||
|
|
f1a8210663 | ||
|
|
1d722be4bc | ||
|
|
62a660bfe1 | ||
|
|
2984795175 | ||
|
|
da706d89a5 | ||
|
|
a8005d5cec | ||
|
|
793ccff6e6 | ||
|
|
e7db9bf1fd | ||
|
|
88d62c93a1 | ||
|
|
d73532d019 | ||
|
|
84d3d23936 | ||
|
|
717947843b | ||
|
|
968584a316 | ||
|
|
ccd67f621a | ||
|
|
80b301dbbe | ||
|
|
001e61d39d | ||
|
|
19c98a436a | ||
|
|
8dd6d7cfdd | ||
|
|
7456b6e02c | ||
|
|
5e8096f74c | ||
|
|
6af77afc44 | ||
|
|
42eeb7bdf5 | ||
|
|
6f4b1e5125 | ||
|
|
22e65cdda8 | ||
|
|
9d342d0f3d | ||
|
|
9583bed718 | ||
|
|
b69ce75712 | ||
|
|
a1cd19b023 | ||
|
|
6e50710b25 | ||
|
|
989a971d27 | ||
|
|
24ee56ce7a | ||
|
|
52f99dd9c1 | ||
|
|
6374fda570 | ||
|
|
cdd2d6323e | ||
|
|
c508a7ea78 | ||
|
|
1380a394c7 | ||
|
|
2c937099d4 | ||
|
|
0a936b3bba | ||
|
|
0a31e0a65e | ||
|
|
8627a18452 | ||
|
|
be528adea5 | ||
|
|
5eb4ed8391 | ||
|
|
9a00d30c0c | ||
|
|
71237c5e11 | ||
|
|
9c6e32a1ab | ||
|
|
1bc18801c8 | ||
|
|
221f2a956e | ||
|
|
b450abdf4d | ||
|
|
d36eed3c09 | ||
|
|
43ee791d4a | ||
|
|
c921945922 | ||
|
|
5f8c77e752 | ||
|
|
064db977aa | ||
|
|
5868cd9777 | ||
|
|
b0ddde996a | ||
|
|
e03c3766f0 | ||
|
|
953c0d7451 | ||
|
|
97b303c362 | ||
|
|
2ffe736a20 | ||
|
|
21f2032f34 | ||
|
|
2f66207205 | ||
|
|
5a14b09c1f | ||
|
|
7e9da92dbe | ||
|
|
a27550b95b | ||
|
|
556883487d | ||
|
|
96f8533479 | ||
|
|
f3cca27448 | ||
|
|
252563725d | ||
|
|
9a934a55e2 | ||
|
|
f07d5d381e | ||
|
|
3faab66ef4 | ||
|
|
2a023246be | ||
|
|
006e7fe8f8 | ||
|
|
1a7ff21a04 | ||
|
|
98cb0fdcb2 | ||
|
|
1fd7e9cdac | ||
|
|
0a2eac4d3a | ||
|
|
9ac6fffd4d | ||
|
|
da20f4a087 | ||
|
|
dbf822ced9 | ||
|
|
095842f4aa | ||
|
|
8c290d7597 | ||
|
|
8a6f4db9af | ||
|
|
99186a86db | ||
|
|
c67bf97f7b | ||
|
|
33a1540fcd | ||
|
|
529b0d643a | ||
|
|
4576efbe5c | ||
|
|
185375ece1 | ||
|
|
d11521954e | ||
|
|
41c4300ec2 | ||
|
|
51d5023f29 | ||
|
|
d2878f8834 | ||
|
|
7808159d23 | ||
|
|
e759431948 | ||
|
|
268ccce955 | ||
|
|
f2d3432bf5 | ||
|
|
2da89f1946 | ||
|
|
6153733df4 | ||
|
|
d280b39f9f | ||
|
|
236e7b8d45 | ||
|
|
dcccf672c9 | ||
|
|
03f81bed16 | ||
|
|
fc51c1ba88 | ||
|
|
d50c1ab6d7 | ||
|
|
984c2ff8d6 | ||
|
|
74646acdca | ||
|
|
45ffe87ba6 | ||
|
|
37eb8cfa57 | ||
|
|
a0f903f162 | ||
|
|
8fb1775606 | ||
|
|
fab7635373 | ||
|
|
b29ca13916 | ||
|
|
f1f0782256 | ||
|
|
0e9a825f63 | ||
|
|
e13ba89f1a | ||
|
|
68ae880979 | ||
|
|
5c53a90eea | ||
|
|
55c6ba6d12 | ||
|
|
d8b2134aef | ||
|
|
c168832f8e | ||
|
|
448a603a56 | ||
|
|
2a95201c6d | ||
|
|
a73de55f96 | ||
|
|
e4a4496be6 | ||
|
|
a8f3a8dfb0 | ||
|
|
e19b9d1c60 | ||
|
|
e28ec4e7cb | ||
|
|
d0f09b467b | ||
|
|
6617382f54 | ||
|
|
dd499a410f | ||
|
|
c04ba992a7 | ||
|
|
27c053cd48 | ||
|
|
7d68c0598c | ||
|
|
201c725dc7 | ||
|
|
57b2316c42 | ||
|
|
fe682a8071 | ||
|
|
bf44a054a1 | ||
|
|
eca9c60d9b | ||
|
|
cf42c35b9f | ||
|
|
a364068abb | ||
|
|
e88093d9cf | ||
|
|
5e532a76cf | ||
|
|
fb9c459269 | ||
|
|
359befd857 | ||
|
|
a6898bd1cd | ||
|
|
ff474d18ee | ||
|
|
279dfcafc4 | ||
|
|
f15d3be263 | ||
|
|
19e5366c5b | ||
|
|
346dee019c | ||
|
|
18914f22f2 | ||
|
|
1219ecf818 | ||
|
|
b6923d0d0d |
No files matched your search
+31
@@ -161,6 +161,37 @@ Duration is in milliseconds and is optional to set, default value is 84ms.
|
||||
Exactly same as P_CheckSight but uses cheaper algorithm, useful for things like nametags. Doesn't work exactly
|
||||
like P_CheckSight so don't use it for anything gameplay-related.
|
||||
|
||||
## musicdef_t
|
||||
|
||||
Userdata structure representing a musicdef. Fields:
|
||||
|
||||
`musicdef.name` - song identifier ("kmap01" for example).
|
||||
|
||||
`musicdef.usage`, `musicdef.source` - fields from vanilla MUSICDEFS lump.
|
||||
|
||||
`musicdef.filename` - unused for now.
|
||||
|
||||
`musicdef.title`, `musicdef.alttitle`, `musicdef.authors` - fields from MUSCINFO lump.
|
||||
|
||||
`#musicdef` - returns integer id for musicdef (which can be used as index in `musicdefs`).
|
||||
|
||||
All fields are read-only.
|
||||
|
||||
## S_FindMusicCredit(name)
|
||||
|
||||
Returns musicdef corresponding to music with given identifier. For example, `S_FindMusicCredit("kmap01")` will return
|
||||
musicdef for green hills music.
|
||||
|
||||
## musicdefs
|
||||
|
||||
Global table for all musicdefs, similar to mobjinfo, states, etc. Can take either integer indices,
|
||||
from `0` to `#musicdefs-1`, or string indices (which is equal to calling `S_FindMusicCredit`).
|
||||
|
||||
## addHook("MusicCredit", function(musicdef))
|
||||
|
||||
Hook is called whenever `S_ShowMusicCredit` (either from game or mod) is called. Takes musicdef as only argument, returning true
|
||||
will overwrite vanilla behavior (not show music credit), can be used to implement custom music credit pop-ups.
|
||||
|
||||
# Other changes
|
||||
|
||||
## P_PlayRinglossSound(source, damager)
|
||||
|
||||
+7
-19
@@ -181,7 +181,8 @@ objdir:=$(makedir)/objs
|
||||
|
||||
# very sophisticated dependency
|
||||
sources+=\
|
||||
$(call List,Sourcefile)
|
||||
$(call List,Sourcefile)\
|
||||
$(call List,core/Sourcefile)
|
||||
|
||||
sources+=\
|
||||
$(call List,blua/Sourcefile)
|
||||
@@ -262,12 +263,10 @@ opts+=$(debug_opts)
|
||||
opts+=$(foreach v,$(passthru_opts),$(if $($(v)),-D$(v)))
|
||||
|
||||
opts+=$(WFLAGS) $(CPPFLAGS) $(CFLAGS)
|
||||
libs+=$(LDFLAGS) -lstdc++
|
||||
asflags:=$(ASFLAGS) -x assembler-with-cpp
|
||||
cxxopts:=$(opts) $(CXXFLAGS) -std=c++17
|
||||
|
||||
cxxopts:=$(opts)
|
||||
cxxopts+=-std=c++17
|
||||
cxxopts+=$(CXXFLAGS)
|
||||
libs+=$(LDFLAGS) -lstdc++ -lpthread
|
||||
asflags:=$(ASFLAGS) -x assembler-with-cpp
|
||||
|
||||
cc=$(CC)
|
||||
cxx=$(CXX)
|
||||
@@ -288,6 +287,7 @@ ifndef SILENT
|
||||
ifndef MAKE_RESTARTS
|
||||
ifndef destructive
|
||||
$(shell $(CC) -v)
|
||||
#$(shell $(CXX) -v)
|
||||
define flags =
|
||||
|
||||
SHELL ..... $(SHELL)
|
||||
@@ -315,6 +315,7 @@ endif
|
||||
|
||||
LD:=$(CC)
|
||||
cc:=$(cc) $(opts)
|
||||
cxx:=$(cxx) $(cxxopts)
|
||||
ifdef UPX
|
||||
upx=$(UPX) $(UPX_OPTS)
|
||||
endif
|
||||
@@ -377,19 +378,6 @@ endif
|
||||
$(.)$(cc) -MM -MF $$@ -MT $(objdir)/$$*.o $(2) $$<
|
||||
endef
|
||||
|
||||
# dependency recipe template (C++)
|
||||
# 1: source file suffix
|
||||
# 2: extra flags to gcc
|
||||
define _recipecxx =
|
||||
$(depdir)/%.d : %.$(1) | $$$$(@D)/
|
||||
ifndef WINDOWSHELL
|
||||
ifdef Echo_name
|
||||
@printf '%-20.20s\r' $$<
|
||||
endif
|
||||
endif
|
||||
$(.)$(cxx) -MM -MF $$@ -MT $(objdir)/$$*.o $(2) $$<
|
||||
endef
|
||||
|
||||
$(eval $(call _recipe,c))
|
||||
$(eval $(call _recipe,cpp))
|
||||
$(eval $(call _recipe,s,$(asflags)))
|
||||
|
||||
@@ -4,8 +4,6 @@ sources+=$(call List,dedicated/Sourcefile)
|
||||
|
||||
opts+=-DDEDICATED
|
||||
|
||||
libs+=-lpthread
|
||||
|
||||
ifdef MINGW
|
||||
libs+=-mconsole
|
||||
endif
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
|
||||
makedir:=$(makedir)/SDL
|
||||
|
||||
sources+=$(call List,sdl/Sourcefile)
|
||||
opts+=-DDIRECTFULLSCREEN -DHAVE_SDL
|
||||
sources+=$(call List,sdl/Sourcefile)
|
||||
|
||||
NOUPNP=1
|
||||
|
||||
|
||||
@@ -16,6 +16,9 @@ $(foreach v,$(join $(wordlist 2,$(_n),- $(gcc_versions)),\
|
||||
$(and $(findstring =,$(v)),\
|
||||
$(eval $(call _predecessor,$(subst =, ,$(v))))))
|
||||
|
||||
# aggregate returns seem to happen alot in c++ so just supress em lel
|
||||
CXXFLAGS+= -Wno-aggregate-return
|
||||
|
||||
# -W -Wno-unused
|
||||
|
||||
ifdef GCC150
|
||||
|
||||
+8
-4
@@ -13,6 +13,7 @@ f_finale.c
|
||||
f_wipe.c
|
||||
filesrch.c
|
||||
g_game.c
|
||||
g_demo.c
|
||||
g_input.c
|
||||
hu_stuff.c
|
||||
i_tcp.c
|
||||
@@ -28,6 +29,7 @@ m_cond.c
|
||||
m_fixed.c
|
||||
m_menu.c
|
||||
m_textinput.c
|
||||
m_emotes.cpp
|
||||
m_misc.c
|
||||
m_perfstats.c
|
||||
m_queue.c
|
||||
@@ -49,14 +51,15 @@ r_bsp.c
|
||||
r_data.c
|
||||
r_draw.c
|
||||
r_fps.c
|
||||
r_main.c
|
||||
r_main.cpp
|
||||
r_patch.c
|
||||
r_patchrotation.c
|
||||
r_plane.c
|
||||
r_segs.c
|
||||
r_plane.cpp
|
||||
r_segs.cpp
|
||||
r_skins.c
|
||||
r_sky.c
|
||||
r_splats.c
|
||||
r_things.c
|
||||
r_things.cpp
|
||||
r_portal.c
|
||||
p_ceilng.c
|
||||
p_enemy.c
|
||||
@@ -77,6 +80,7 @@ p_tick.c
|
||||
p_user.c
|
||||
k_director.c
|
||||
k_kart.c
|
||||
k_hud.c
|
||||
k_stats.c
|
||||
lua_baselib.c
|
||||
lua_blockmaplib.c
|
||||
|
||||
+8
-4
@@ -197,7 +197,7 @@ static fixed_t scale_mtof = (fixed_t)INITSCALEMTOF;
|
||||
// used by FTOM to scale from frame-buffer-to-map coords (=1/scale_mtof)
|
||||
static fixed_t scale_ftom;
|
||||
|
||||
static player_t *plr; // the player represented by an arrow
|
||||
static player_t *plr = NULL; // the player represented by an arrow
|
||||
|
||||
static boolean followplayer = true; // specifies whether to follow the player around
|
||||
|
||||
@@ -237,7 +237,7 @@ static inline void AM_restoreScaleAndLoc(void)
|
||||
m_x = old_m_x;
|
||||
m_y = old_m_y;
|
||||
}
|
||||
else
|
||||
else if (plr && plr->mo)
|
||||
{
|
||||
m_x = (plr->mo->x >> FRACTOMAPBITS) - m_w/2;
|
||||
m_y = (plr->mo->y >> FRACTOMAPBITS) - m_h/2;
|
||||
@@ -318,7 +318,8 @@ static void AM_initVariables(void)
|
||||
break;
|
||||
|
||||
plr = &players[pnum];
|
||||
if (plr != NULL && plr->mo != NULL)
|
||||
|
||||
if (plr && plr->mo)
|
||||
{
|
||||
m_x = (plr->mo->x >> FRACTOMAPBITS) - m_w/2;
|
||||
m_y = (plr->mo->y >> FRACTOMAPBITS) - m_h/2;
|
||||
@@ -340,7 +341,7 @@ static void AM_FrameBufferInit(void)
|
||||
f_x = f_y = 0;
|
||||
f_w = vid.width;
|
||||
f_h = vid.height;
|
||||
am_buf = screens[0];
|
||||
am_buf = vid.screens[0];
|
||||
}
|
||||
|
||||
//
|
||||
@@ -597,6 +598,9 @@ static inline void AM_changeWindowScale(void)
|
||||
|
||||
static inline void AM_doFollowPlayer(void)
|
||||
{
|
||||
if (!plr || !plr->mo)
|
||||
return;
|
||||
|
||||
if (f_oldloc.x != plr->mo->x || f_oldloc.y != plr->mo->y)
|
||||
{
|
||||
m_x = FTOM(MTOF(plr->mo->x >> FRACTOMAPBITS)) - m_w/2;
|
||||
|
||||
@@ -46,7 +46,6 @@ INT32 VID_SetMode(INT32 modenum)
|
||||
vid.modenum = 0;
|
||||
vid.width = 320;
|
||||
vid.height = 240;
|
||||
vid.bpp = 1;
|
||||
vid.buffer = android_surface;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#define WRITEUINT8(p,b) do { UINT8 *p_tmp = (void *)p; const UINT8 tv = ( UINT8)(b); memcpy(p, &tv, sizeof( UINT8)); p_tmp++; p = (void *)p_tmp; } while (0)
|
||||
#define WRITESINT8(p,b) do { SINT8 *p_tmp = (void *)p; const SINT8 tv = ( UINT8)(b); memcpy(p, &tv, sizeof( UINT8)); p_tmp++; p = (void *)p_tmp; } while (0)
|
||||
#define WRITEINT16(p,b) do { INT16 *p_tmp = (void *)p; const INT16 tv = ( INT16)(b); memcpy(p, &tv, sizeof( INT16)); p_tmp++; p = (void *)p_tmp; } while (0)
|
||||
#define WRITEINT16_2(p,b) do { INT16 *p_tmp = ( INT16 *)p; const INT16 tv = ( INT16)(b); memcpy(p, &tv, sizeof( INT16)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0) // dumb hack for mumble
|
||||
#define WRITEUINT16(p,b) do { UINT16 *p_tmp = (void *)p; const UINT16 tv = ( UINT16)(b); memcpy(p, &tv, sizeof( UINT16)); p_tmp++; p = (void *)p_tmp; } while (0)
|
||||
#define WRITEINT32(p,b) do { INT32 *p_tmp = (void *)p; const INT32 tv = ( INT32)(b); memcpy(p, &tv, sizeof( INT32)); p_tmp++; p = (void *)p_tmp; } while (0)
|
||||
#define WRITEUINT32(p,b) do { UINT32 *p_tmp = (void *)p; const UINT32 tv = ( UINT32)(b); memcpy(p, &tv, sizeof( UINT32)); p_tmp++; p = (void *)p_tmp; } while (0)
|
||||
@@ -38,6 +39,7 @@
|
||||
#define WRITEUINT8(p,b) do { UINT8 *p_tmp = ( UINT8 *)p; *p_tmp = ( UINT8)(b); p_tmp++; p = (void *)p_tmp; } while (0)
|
||||
#define WRITESINT8(p,b) do { SINT8 *p_tmp = ( SINT8 *)p; *p_tmp = ( SINT8)(b); p_tmp++; p = (void *)p_tmp; } while (0)
|
||||
#define WRITEINT16(p,b) do { INT16 *p_tmp = ( INT16 *)p; *p_tmp = ( INT16)(b); p_tmp++; p = (void *)p_tmp; } while (0)
|
||||
#define WRITEINT16_2(p,b) do { INT16 *p_tmp = ( INT16 *)p; *p_tmp = ( INT16)(b); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0) // dumb hack for mumble
|
||||
#define WRITEUINT16(p,b) do { UINT16 *p_tmp = ( UINT16 *)p; *p_tmp = ( UINT16)(b); p_tmp++; p = (void *)p_tmp; } while (0)
|
||||
#define WRITEINT32(p,b) do { INT32 *p_tmp = ( INT32 *)p; *p_tmp = ( INT32)(b); p_tmp++; p = (void *)p_tmp; } while (0)
|
||||
#define WRITEUINT32(p,b) do { UINT32 *p_tmp = ( UINT32 *)p; *p_tmp = ( UINT32)(b); p_tmp++; p = (void *)p_tmp; } while (0)
|
||||
|
||||
+35
-15
@@ -240,7 +240,6 @@ void COM_ImmedExecute(const char *ptext)
|
||||
|
||||
while (i < strlen(ptext))
|
||||
{
|
||||
|
||||
quotes = 0;
|
||||
for (j = 0; i < strlen(ptext); i++,j++)
|
||||
{
|
||||
@@ -817,12 +816,17 @@ static void COM_Help_f(void)
|
||||
cvar = CV_FindVar(help);
|
||||
if (cvar)
|
||||
{
|
||||
boolean floatmode = false;
|
||||
const char *cvalue = NULL;
|
||||
CONS_Printf("\x82""Variable %s:\n", cvar->name);
|
||||
CONS_Printf(M_GetText(" flags: "));
|
||||
if (cvar->flags & CV_SAVE)
|
||||
CONS_Printf("AUTOSAVE ");
|
||||
if (cvar->flags & CV_FLOAT)
|
||||
{
|
||||
CONS_Printf("FLOAT ");
|
||||
floatmode = true;
|
||||
}
|
||||
if (cvar->flags & CV_NETVAR)
|
||||
CONS_Printf("NETVAR ");
|
||||
if (cvar->flags & CV_CALL)
|
||||
@@ -832,30 +836,43 @@ static void COM_Help_f(void)
|
||||
CONS_Printf("\n");
|
||||
if (cvar->PossibleValue)
|
||||
{
|
||||
if (!stricmp(cvar->PossibleValue[0].strvalue, "MIN") && !stricmp(cvar->PossibleValue[1].strvalue, "MAX"))
|
||||
{
|
||||
CONS_Printf(" range from %d to %d\n", cvar->PossibleValue[0].value,
|
||||
cvar->PossibleValue[1].value);
|
||||
i = 2;
|
||||
}
|
||||
if (!stricmp(cvar->PossibleValue[0].strvalue, "MIN") && !stricmp(cvar->PossibleValue[1].strvalue, "MAX"))
|
||||
{
|
||||
if (floatmode)
|
||||
{
|
||||
float fu = FIXED_TO_FLOAT(cvar->PossibleValue[0].value);
|
||||
float ck = FIXED_TO_FLOAT(cvar->PossibleValue[1].value);
|
||||
CONS_Printf(" range from %ld%s to %ld%s\n",
|
||||
(long)fu, M_Ftrim(fu),
|
||||
(long)ck, M_Ftrim(ck));
|
||||
}
|
||||
else
|
||||
CONS_Printf(" range from %d to %d\n", cvar->PossibleValue[0].value,
|
||||
cvar->PossibleValue[1].value);
|
||||
i = 2;
|
||||
}
|
||||
|
||||
{
|
||||
const char *cvalue = NULL;
|
||||
//CONS_Printf(M_GetText(" possible value : %s\n"), cvar->name);
|
||||
while (cvar->PossibleValue[i].strvalue)
|
||||
{
|
||||
CONS_Printf(" %-2d : %s\n", cvar->PossibleValue[i].value,
|
||||
cvar->PossibleValue[i].strvalue);
|
||||
if (floatmode)
|
||||
CONS_Printf(" %-2f : %s\n", FIXED_TO_FLOAT(cvar->PossibleValue[i].value),
|
||||
cvar->PossibleValue[i].strvalue);
|
||||
else
|
||||
CONS_Printf(" %-2d : %s\n", cvar->PossibleValue[i].value,
|
||||
cvar->PossibleValue[i].strvalue);
|
||||
if (cvar->PossibleValue[i].value == cvar->value)
|
||||
cvalue = cvar->PossibleValue[i].strvalue;
|
||||
i++;
|
||||
}
|
||||
if (cvalue)
|
||||
CONS_Printf(" Current value: %s\n", cvalue);
|
||||
else
|
||||
CONS_Printf(" Current value: %d\n", cvar->value);
|
||||
}
|
||||
}
|
||||
|
||||
if (cvalue)
|
||||
CONS_Printf(" Current value: %s\n", cvalue);
|
||||
else if (cvar->string)
|
||||
CONS_Printf(" Current value: %s\n", cvar->string);
|
||||
else
|
||||
CONS_Printf(" Current value: %d\n", cvar->value);
|
||||
}
|
||||
@@ -1026,7 +1043,10 @@ static void COM_Add_f(void)
|
||||
}
|
||||
|
||||
if (( cvar->flags & CV_FLOAT ))
|
||||
CV_Set(cvar, va("%f", FIXED_TO_FLOAT (cvar->value) + atof(COM_Argv(2))));
|
||||
{
|
||||
float n =FIXED_TO_FLOAT (cvar->value) + atof(COM_Argv(2));
|
||||
CV_Set(cvar, va("%ld%s", (long)n, M_Ftrim(n)));
|
||||
}
|
||||
else
|
||||
CV_AddValue(cvar, atoi(COM_Argv(2)));
|
||||
}
|
||||
|
||||
@@ -13,6 +13,10 @@
|
||||
#ifndef __COMMAND_H__
|
||||
#define __COMMAND_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include "doomdef.h"
|
||||
|
||||
@@ -189,4 +193,8 @@ UINT8 CV_CheatsEnabled(void);
|
||||
// Returns cvar by name. Exposed here for Lua.
|
||||
consvar_t *CV_FindVar(const char *name);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // __COMMAND_H__
|
||||
@@ -1321,13 +1321,6 @@ void CONS_Debug(INT32 debugflags, const char *fmt, ...)
|
||||
//
|
||||
void CONS_Error(const char *msg)
|
||||
{
|
||||
#ifdef RPC_NO_WINDOWS_H
|
||||
if (!graphics_started)
|
||||
{
|
||||
MessageBoxA(vid.WndParent, msg, "SRB2Kart Warning", MB_OK);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
CONS_Printf("\x82%s", msg); // write error msg in different colour
|
||||
CONS_Printf(M_GetText("Press ENTER to continue\n"));
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
target_sourcefile(cpp)
|
||||
@@ -0,0 +1,2 @@
|
||||
memory.cpp
|
||||
thread_pool.cpp
|
||||
@@ -0,0 +1,71 @@
|
||||
// BLANKART
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2024 by Ronald "Eidolon" Kinard
|
||||
// Copyright (C) 2024 by Kart Krew
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "memory.h"
|
||||
|
||||
#include <array>
|
||||
#include <new>
|
||||
|
||||
#include "../z_zone.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
class LinearMemory
|
||||
{
|
||||
size_t size_;
|
||||
size_t height_;
|
||||
void* memory_;
|
||||
|
||||
public:
|
||||
constexpr explicit LinearMemory(size_t size) noexcept;
|
||||
|
||||
void* allocate(size_t size);
|
||||
void reset() noexcept;
|
||||
};
|
||||
|
||||
constexpr LinearMemory::LinearMemory(size_t size) noexcept : size_(size), height_{0}, memory_{nullptr} {}
|
||||
|
||||
void* LinearMemory::allocate(size_t size)
|
||||
{
|
||||
size_t aligned_size = (size + 15) & ~15;
|
||||
if (height_ + aligned_size > size_)
|
||||
{
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
|
||||
if (memory_ == nullptr)
|
||||
{
|
||||
memory_ = Z_Malloc(size_, PU_STATIC, nullptr);
|
||||
}
|
||||
|
||||
void* ptr = (void*)((uintptr_t)(memory_) + height_);
|
||||
height_ += aligned_size;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void LinearMemory::reset() noexcept
|
||||
{
|
||||
height_ = 0;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
static LinearMemory g_frame_memory {4 * 1024 * 1024};
|
||||
|
||||
void* Z_Frame_Alloc(size_t size)
|
||||
{
|
||||
return g_frame_memory.allocate(size);
|
||||
}
|
||||
|
||||
void Z_Frame_Reset()
|
||||
{
|
||||
g_frame_memory.reset();
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
// BLANKART
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2024 by Ronald "Eidolon" Kinard
|
||||
// Copyright (C) 2024 by Kart Krew
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __SRB2_CORE_MEMORY_H__
|
||||
#define __SRB2_CORE_MEMORY_H__
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cpluspplus
|
||||
|
||||
/// @brief Allocate a block of memory with a lifespan of the current main-thread frame.
|
||||
/// This function is NOT thread-safe, but the allocated memory may be used across threads.
|
||||
/// @return a pointer to a block of memory aligned with libc malloc alignment, or null if allocation fails
|
||||
void* Z_Frame_Alloc(size_t size);
|
||||
|
||||
/// @brief Resets per-frame memory. Not thread safe.
|
||||
void Z_Frame_Reset(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // __SRB2_CORE_MEMORY_H__
|
||||
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
// This class is derived from Conor Williams' implementation of a concurrent deque
|
||||
// https://github.com/ConorWilliams/ConcurrentDeque
|
||||
// Copyright (C) 2021 Conor Williams
|
||||
|
||||
// The original version was for C++23. This one has been shrunk slightly and adapted to our conventions.
|
||||
|
||||
#ifndef __SRB2_CORE_SPMC_QUEUE_HPP__
|
||||
#define __SRB2_CORE_SPMC_QUEUE_HPP__
|
||||
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
//#include <tracy/tracy/Tracy.hpp>
|
||||
|
||||
#include "../cxxutil.hpp"
|
||||
|
||||
namespace srb2
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
class SpMcQueue
|
||||
{
|
||||
struct RingBuff {
|
||||
public:
|
||||
explicit RingBuff(int64_t cap) : _cap{cap}, _mask{cap - 1}
|
||||
{
|
||||
SRB2_ASSERT(cap && (!(cap & (cap - 1))) && "Capacity must be buf power of 2!");
|
||||
_buff = std::unique_ptr<T[]>(new T[_cap]);
|
||||
}
|
||||
|
||||
std::int64_t capacity() const noexcept { return _cap; }
|
||||
|
||||
// Store (copy) at modulo index
|
||||
void store(int64_t i, T&& x) noexcept
|
||||
{
|
||||
_buff[i & _mask] = std::move(x);
|
||||
}
|
||||
|
||||
// Load (copy) at modulo index
|
||||
T load(int64_t i) const noexcept
|
||||
{
|
||||
return _buff[i & _mask];
|
||||
}
|
||||
|
||||
// Allocates and returns a new ring buffer, copies elements in range [b, t) into the new buffer.
|
||||
RingBuff* resize(std::int64_t b, std::int64_t t) const
|
||||
{
|
||||
//ZoneScoped;
|
||||
RingBuff* ptr = new RingBuff{2 * _cap};
|
||||
for (std::int64_t i = t; i != b; ++i) {
|
||||
ptr->store(i, load(i));
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
private:
|
||||
int64_t _cap; // Capacity of the buffer
|
||||
int64_t _mask; // Bit mask to perform modulo capacity operations
|
||||
|
||||
std::unique_ptr<T[]> _buff;
|
||||
};
|
||||
|
||||
alignas(64) std::atomic<int64_t> bottom_;
|
||||
alignas(64) std::atomic<int64_t> top_;
|
||||
alignas(64) std::atomic<RingBuff*> buffer_;
|
||||
|
||||
std::vector<std::unique_ptr<RingBuff>> garbage_;
|
||||
|
||||
public:
|
||||
SpMcQueue(size_t capacity) : bottom_(0), top_(0), buffer_(new RingBuff(capacity))
|
||||
{
|
||||
garbage_.reserve(32);
|
||||
}
|
||||
~SpMcQueue() noexcept
|
||||
{
|
||||
delete buffer_.load(std::memory_order_relaxed);
|
||||
};
|
||||
|
||||
size_t size() const noexcept
|
||||
{
|
||||
int64_t bottom = bottom_.load(std::memory_order_relaxed);
|
||||
int64_t top = top_.load(std::memory_order_relaxed);
|
||||
return static_cast<size_t>(bottom >= top ? bottom - top : 0);
|
||||
}
|
||||
|
||||
bool empty() const noexcept
|
||||
{
|
||||
return size() == 0;
|
||||
}
|
||||
|
||||
void push(T&& v) noexcept
|
||||
{
|
||||
int64_t bottom = bottom_.load(std::memory_order_relaxed);
|
||||
int64_t top = top_.load(std::memory_order_acquire);
|
||||
RingBuff* buf = buffer_.load(std::memory_order_relaxed);
|
||||
|
||||
if (buf->capacity() < (bottom - top) + 1)
|
||||
{
|
||||
// Queue is full, build a new one
|
||||
RingBuff* newbuf = buf->resize(bottom, top);
|
||||
garbage_.emplace_back(buf);
|
||||
buffer_.store(newbuf, std::memory_order_relaxed);
|
||||
buf = newbuf;
|
||||
}
|
||||
|
||||
// Construct new object, this does not have to be atomic as no one can steal this item until after we
|
||||
// store the new value of bottom, ordering is maintained by surrounding atomics.
|
||||
buf->store(bottom, std::move(v));
|
||||
|
||||
std::atomic_thread_fence(std::memory_order_release);
|
||||
bottom_.store(bottom + 1, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
std::optional<T> pop() noexcept
|
||||
{
|
||||
int64_t bottom = bottom_.load(std::memory_order_relaxed) - 1;
|
||||
RingBuff* buf = buffer_.load(std::memory_order_relaxed);
|
||||
|
||||
bottom_.store(bottom, std::memory_order_relaxed); // Stealers can no longer steal
|
||||
|
||||
std::atomic_thread_fence(std::memory_order_seq_cst);
|
||||
int64_t top = top_.load(std::memory_order_relaxed);
|
||||
|
||||
if (top <= bottom)
|
||||
{
|
||||
// Non-empty deque
|
||||
if (top == bottom)
|
||||
{
|
||||
// The last item could get stolen, by a stealer that loaded bottom before our write above
|
||||
if (!top_.compare_exchange_strong(top, top + 1, std::memory_order_seq_cst, std::memory_order_relaxed))
|
||||
{
|
||||
// Failed race, thief got the last item.
|
||||
bottom_.store(bottom + 1, std::memory_order_relaxed);
|
||||
return std::nullopt;
|
||||
}
|
||||
bottom_.store(bottom + 1, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
// Can delay load until after acquiring slot as only this thread can push(), this load is not
|
||||
// required to be atomic as we are the exclusive writer.
|
||||
return buf->load(bottom);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
bottom_.store(bottom + 1, std::memory_order_relaxed);
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<T> steal() noexcept
|
||||
{
|
||||
int64_t top = top_.load(std::memory_order_acquire);
|
||||
std::atomic_thread_fence(std::memory_order_seq_cst);
|
||||
int64_t bottom = bottom_.load(std::memory_order_acquire);
|
||||
|
||||
if (top < bottom)
|
||||
{
|
||||
// Must load *before* acquiring the slot as slot may be overwritten immediately after acquiring.
|
||||
// This load is NOT required to be atomic even-though it may race with an overrite as we only
|
||||
// return the value if we win the race below garanteeing we had no race during our read. If we
|
||||
// loose the race then 'x' could be corrupt due to read-during-write race but as T is trivially
|
||||
// destructible this does not matter.
|
||||
T x = buffer_.load(std::memory_order_consume)->load(top);
|
||||
|
||||
if (!top_.compare_exchange_strong(top, top + 1, std::memory_order_seq_cst, std::memory_order_relaxed))
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return x;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace srb2
|
||||
|
||||
#endif // __SRB2_CORE_SPMC_QUEUE_HPP__
|
||||
@@ -0,0 +1,255 @@
|
||||
// BLANKART
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2024 by Ronald "Eidolon" Kinard
|
||||
// Copyright (C) 2024 by Kart Krew
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __SRB2_CORE_STATIC_VEC_HPP__
|
||||
#define __SRB2_CORE_STATIC_VEC_HPP__
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <initializer_list>
|
||||
#include <iterator>
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
|
||||
#include "../cxxutil.hpp"
|
||||
|
||||
namespace srb2
|
||||
{
|
||||
|
||||
template <typename T, size_t Limit>
|
||||
class StaticVec;
|
||||
|
||||
template <typename T, size_t Limit>
|
||||
class StaticVec
|
||||
{
|
||||
std::array<T, Limit> arr_ {{}};
|
||||
size_t size_ = 0;
|
||||
|
||||
public:
|
||||
using value_type = T;
|
||||
|
||||
constexpr StaticVec() {}
|
||||
|
||||
StaticVec(const StaticVec& rhs)
|
||||
{
|
||||
for (size_t i = size_; i > 0; i--)
|
||||
{
|
||||
arr_[i] = T();
|
||||
}
|
||||
size_ = rhs.size();
|
||||
for (size_t i = 0; i < size_; i++)
|
||||
{
|
||||
arr_[i] = rhs.arr_[i];
|
||||
}
|
||||
}
|
||||
|
||||
StaticVec(StaticVec&& rhs) noexcept(std::is_nothrow_move_assignable_v<T>)
|
||||
{
|
||||
for (size_t i = size_; i > 0; i--)
|
||||
{
|
||||
arr_[i] = T();
|
||||
}
|
||||
size_ = rhs.size();
|
||||
for (size_t i = 0; i < size_; i++)
|
||||
{
|
||||
arr_[i] = std::move(rhs.arr_[i]);
|
||||
}
|
||||
while (rhs.size() > 0)
|
||||
{
|
||||
rhs.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
constexpr StaticVec(std::initializer_list<T> list) noexcept(std::is_nothrow_move_assignable_v<T>)
|
||||
{
|
||||
size_ = list.size();
|
||||
size_t i = 0;
|
||||
for (auto itr = list.begin(); itr != list.end(); itr++)
|
||||
{
|
||||
arr_[i] = *itr;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
~StaticVec() = default;
|
||||
|
||||
StaticVec& operator=(const StaticVec& rhs)
|
||||
{
|
||||
for (size_t i = size_; i > 0; i--)
|
||||
{
|
||||
arr_[i] = T();
|
||||
}
|
||||
size_ = rhs.size();
|
||||
for (size_t i = 0; i < size_; i++)
|
||||
{
|
||||
arr_[i] = rhs.arr_[i];
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
StaticVec& operator=(StaticVec&& rhs) noexcept(std::is_nothrow_move_constructible_v<T>)
|
||||
{
|
||||
for (size_t i = size_; i > 0; i--)
|
||||
{
|
||||
arr_[i] = T();
|
||||
}
|
||||
size_ = rhs.size();
|
||||
for (size_t i = 0; i < size_; i++)
|
||||
{
|
||||
arr_[i] = std::move(rhs.arr_[i]);
|
||||
}
|
||||
while (rhs.size() > 0)
|
||||
{
|
||||
rhs.pop_back();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void push_back(const T& value) { arr_[size_++] = value; }
|
||||
|
||||
void pop_back() { arr_[--size_] = T(); }
|
||||
|
||||
void resize(size_t size, T value = T())
|
||||
{
|
||||
if (size >= Limit)
|
||||
{
|
||||
throw std::length_error("new size >= Capacity");
|
||||
}
|
||||
|
||||
if (size == size_)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (size < size_)
|
||||
{
|
||||
while (size_ > size)
|
||||
{
|
||||
pop_back();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (size_ < size)
|
||||
{
|
||||
push_back(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
arr_ = {{}};
|
||||
size_ = 0;
|
||||
}
|
||||
|
||||
using iterator = typename std::array<T, Limit>::iterator;
|
||||
using const_iterator = typename std::array<T, Limit>::const_iterator;
|
||||
|
||||
constexpr iterator begin() noexcept { return arr_.begin(); }
|
||||
|
||||
constexpr const_iterator begin() const noexcept { return arr_.cbegin(); }
|
||||
|
||||
constexpr const_iterator cbegin() const noexcept { return arr_.cbegin(); }
|
||||
|
||||
constexpr iterator end() noexcept { return std::next(arr_.begin(), size_); }
|
||||
|
||||
constexpr const_iterator end() const noexcept { return cend(); }
|
||||
|
||||
constexpr const_iterator cend() const noexcept { return std::next(arr_.cbegin(), size_); }
|
||||
|
||||
constexpr std::reverse_iterator<iterator> rbegin() noexcept { return std::reverse_iterator(this->end()); }
|
||||
|
||||
constexpr std::reverse_iterator<const_iterator> crbegin() const noexcept { return std::reverse_iterator(this->cend()); }
|
||||
|
||||
constexpr std::reverse_iterator<iterator> rend() noexcept { return std::reverse_iterator(this->begin()); }
|
||||
|
||||
constexpr std::reverse_iterator<const_iterator> crend() const noexcept { return std::reverse_iterator(this->cbegin()); }
|
||||
|
||||
constexpr bool empty() const noexcept { return size_ == 0; }
|
||||
|
||||
constexpr size_t size() const noexcept { return size_; }
|
||||
|
||||
constexpr size_t capacity() const noexcept { return Limit; }
|
||||
|
||||
constexpr size_t max_size() const noexcept { return Limit; }
|
||||
|
||||
constexpr T& operator[](size_t index) noexcept { return arr_[index]; }
|
||||
|
||||
T& at(size_t index)
|
||||
{
|
||||
if (index >= size_)
|
||||
{
|
||||
throw std::out_of_range("index >= size");
|
||||
}
|
||||
return this[index];
|
||||
}
|
||||
|
||||
constexpr const T& operator[](size_t index) const noexcept { return arr_[index]; }
|
||||
|
||||
const T& at(size_t index) const
|
||||
{
|
||||
if (index >= size_)
|
||||
{
|
||||
throw std::out_of_range("index >= size");
|
||||
}
|
||||
return this[index];
|
||||
}
|
||||
|
||||
T& front() { return *arr_[0]; }
|
||||
|
||||
T& back() { return *arr_[size_ - 1]; }
|
||||
};
|
||||
|
||||
} // namespace srb2
|
||||
|
||||
template <typename T, size_t L1, size_t L2>
|
||||
bool operator==(const srb2::StaticVec<T, L1>& lhs, const srb2::StaticVec<T, L2>& rhs)
|
||||
{
|
||||
const size_t size = lhs.size();
|
||||
if (size != rhs.size())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (size_t i = 0; i < lhs; i++)
|
||||
{
|
||||
if (rhs[i] != lhs[i])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T, size_t L1, size_t L2>
|
||||
bool operator!=(const srb2::StaticVec<T, L1>& lhs, const srb2::StaticVec<T, L2>& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
template <typename T, size_t Limit>
|
||||
struct std::hash<srb2::StaticVec<T, Limit>>
|
||||
{
|
||||
size_t operator()(const srb2::StaticVec<T, Limit>& input) const
|
||||
{
|
||||
constexpr size_t prime = sizeof(size_t) == 8 ? 0x00000100000001B3 : 0x01000193;
|
||||
constexpr size_t basis = sizeof(size_t) == 8 ? 0xcbf29ce484222325 : 0x811c9dc5;
|
||||
|
||||
size_t ret = basis;
|
||||
for (auto itr = input.begin(); itr != input.end(); itr++)
|
||||
{
|
||||
ret = (ret * prime) ^ std::hash<T>(*itr);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // __SRB2_CORE_STATIC_VEC_HPP__
|
||||
@@ -0,0 +1,346 @@
|
||||
// BLANKART
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2024 by Ronald "Eidolon" Kinard
|
||||
// Copyright (C) 2024 by Kart Krew
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "thread_pool.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <condition_variable>
|
||||
#include <exception>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <system_error>
|
||||
|
||||
//#include <fmt/format.h>
|
||||
//#include <tracy/tracy/Tracy.hpp>
|
||||
|
||||
#include "../cxxutil.hpp"
|
||||
#include "../m_argv.h"
|
||||
|
||||
using namespace srb2;
|
||||
|
||||
static void do_work(ThreadPool::Task& work)
|
||||
{
|
||||
try
|
||||
{
|
||||
//ZoneScoped;
|
||||
(work.thunk)(work.raw.data());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// can't do anything
|
||||
}
|
||||
|
||||
(work.deleter)(work.raw.data());
|
||||
if (work.pseudosema)
|
||||
{
|
||||
work.pseudosema->fetch_sub(1, std::memory_order_relaxed);
|
||||
}
|
||||
}
|
||||
|
||||
static void pool_executor(
|
||||
//int thread_index,
|
||||
std::shared_ptr<std::atomic<bool>> pool_alive,
|
||||
std::shared_ptr<std::mutex> worker_ready_mutex,
|
||||
std::shared_ptr<std::condition_variable> worker_ready_condvar,
|
||||
std::shared_ptr<ThreadPool::Queue> my_wq,
|
||||
std::vector<std::shared_ptr<ThreadPool::Queue>> other_wqs
|
||||
)
|
||||
{
|
||||
{
|
||||
//std::string thread_name = fmt::format("Thread Pool Thread {}", thread_index);
|
||||
//tracy::SetThreadName(thread_name.c_str());
|
||||
}
|
||||
|
||||
int spins = 0;
|
||||
while (true)
|
||||
{
|
||||
std::optional<ThreadPool::Task> work = my_wq->steal();
|
||||
bool did_work = false;
|
||||
if (work)
|
||||
{
|
||||
do_work(*work);
|
||||
|
||||
did_work = true;
|
||||
spins = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (auto& q : other_wqs)
|
||||
{
|
||||
work = q->steal();
|
||||
if (work)
|
||||
{
|
||||
do_work(*work);
|
||||
|
||||
did_work = true;
|
||||
spins = 0;
|
||||
|
||||
// We only want to steal one work item at a time, to prioritize our own queue
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!did_work)
|
||||
{
|
||||
// Spin a few loops to avoid yielding, then wait for the ready lock
|
||||
spins += 1;
|
||||
if (spins > 100)
|
||||
{
|
||||
std::unique_lock<std::mutex> ready_lock {*worker_ready_mutex};
|
||||
while (my_wq->empty() && pool_alive->load())
|
||||
{
|
||||
worker_ready_condvar->wait(ready_lock);
|
||||
}
|
||||
|
||||
if (!pool_alive->load())
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ThreadPool::ThreadPool()
|
||||
{
|
||||
immediate_mode_ = true;
|
||||
}
|
||||
|
||||
ThreadPool::ThreadPool(size_t threads)
|
||||
{
|
||||
next_queue_index_ = 0;
|
||||
pool_alive_ = std::make_shared<std::atomic<bool>>(true);
|
||||
|
||||
for (size_t i = 0; i < threads; i++)
|
||||
{
|
||||
std::shared_ptr<Queue> wsq = std::make_shared<Queue>(2048);
|
||||
work_queues_.push_back(wsq);
|
||||
|
||||
std::shared_ptr<std::mutex> mutex = std::make_shared<std::mutex>();
|
||||
worker_ready_mutexes_.push_back(std::move(mutex));
|
||||
std::shared_ptr<std::condition_variable> condvar = std::make_shared<std::condition_variable>();
|
||||
worker_ready_condvars_.push_back(std::move(condvar));
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < threads; i++)
|
||||
{
|
||||
std::shared_ptr<Queue> my_queue = work_queues_[i];
|
||||
std::vector<std::shared_ptr<Queue>> other_queues;
|
||||
for (size_t j = 0; j < threads; j++)
|
||||
{
|
||||
// Order the other queues starting from the next adjacent worker
|
||||
// i.e. if this is worker 2 of 8, then other queues is 3, 4, 5, 6, 7, 0, 1
|
||||
// This tries to balance out work stealing behavior
|
||||
|
||||
size_t other_index = j + i;
|
||||
if (other_index >= threads)
|
||||
{
|
||||
other_index -= threads;
|
||||
}
|
||||
|
||||
if (other_index != i)
|
||||
{
|
||||
other_queues.push_back(work_queues_[other_index]);
|
||||
}
|
||||
}
|
||||
|
||||
std::thread thread;
|
||||
try
|
||||
{
|
||||
thread = std::thread
|
||||
{
|
||||
pool_executor,
|
||||
//i,
|
||||
pool_alive_,
|
||||
worker_ready_mutexes_[i],
|
||||
worker_ready_condvars_[i],
|
||||
my_queue,
|
||||
other_queues
|
||||
};
|
||||
}
|
||||
catch (const std::system_error& error)
|
||||
{
|
||||
// Safe shutdown and rethrow
|
||||
pool_alive_->store(false);
|
||||
for (auto& t : threads_)
|
||||
{
|
||||
t.join();
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
|
||||
threads_.push_back(std::move(thread));
|
||||
}
|
||||
}
|
||||
|
||||
ThreadPool::ThreadPool(ThreadPool&&) = default;
|
||||
ThreadPool::~ThreadPool() = default;
|
||||
|
||||
ThreadPool& ThreadPool::operator=(ThreadPool&&) = default;
|
||||
|
||||
void ThreadPool::begin_sema()
|
||||
{
|
||||
sema_begun_ = true;
|
||||
}
|
||||
|
||||
ThreadPool::Sema ThreadPool::end_sema()
|
||||
{
|
||||
Sema ret = Sema(std::move(cur_sema_));
|
||||
cur_sema_ = nullptr;
|
||||
sema_begun_ = false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ThreadPool::notify()
|
||||
{
|
||||
for (size_t i = 0; i < work_queues_.size(); i++)
|
||||
{
|
||||
auto& q = work_queues_[i];
|
||||
size_t count = q->size();
|
||||
if (count > 0)
|
||||
{
|
||||
worker_ready_condvars_[i]->notify_one();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ThreadPool::notify_sema(const ThreadPool::Sema& sema)
|
||||
{
|
||||
if (!sema.pseudosema_)
|
||||
{
|
||||
return;
|
||||
}
|
||||
notify();
|
||||
}
|
||||
|
||||
void ThreadPool::wait_idle()
|
||||
{
|
||||
if (immediate_mode_)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//ZoneScoped;
|
||||
|
||||
for (size_t i = 0; i < work_queues_.size(); i++)
|
||||
{
|
||||
auto& q = work_queues_[i];
|
||||
|
||||
std::optional<Task> work;
|
||||
while ((work = q->pop()).has_value())
|
||||
{
|
||||
do_work(*work);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ThreadPool::wait_sema(const Sema& sema)
|
||||
{
|
||||
if (!sema.pseudosema_)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//ZoneScoped;
|
||||
|
||||
while (sema.pseudosema_->load(std::memory_order_seq_cst) > 0)
|
||||
{
|
||||
// spin to win
|
||||
for (size_t i = 0; i < work_queues_.size(); i++)
|
||||
{
|
||||
auto& q = work_queues_[i];
|
||||
|
||||
std::optional<Task> work;
|
||||
if ((work = q->pop()).has_value())
|
||||
{
|
||||
do_work(*work);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sema.pseudosema_->load(std::memory_order_seq_cst) != 0)
|
||||
{
|
||||
throw std::exception();
|
||||
}
|
||||
}
|
||||
|
||||
void ThreadPool::shutdown()
|
||||
{
|
||||
if (immediate_mode_)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
wait_idle();
|
||||
|
||||
pool_alive_->store(false);
|
||||
|
||||
for (auto& condvar : worker_ready_condvars_)
|
||||
{
|
||||
condvar->notify_all();
|
||||
}
|
||||
for (auto& t : threads_)
|
||||
{
|
||||
t.join();
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<ThreadPool> srb2::g_main_threadpool;
|
||||
|
||||
void I_ThreadPoolInit(void)
|
||||
{
|
||||
SRB2_ASSERT(g_main_threadpool == nullptr);
|
||||
size_t thread_count = std::min(static_cast<unsigned int>(9), std::thread::hardware_concurrency());
|
||||
if (thread_count > 1)
|
||||
{
|
||||
// The main thread will act as a worker when waiting for pool idle
|
||||
// Make one less worker thread to avoid unnecessary context switching
|
||||
thread_count -= 1;
|
||||
}
|
||||
|
||||
if (M_CheckParm("-singlethreaded"))
|
||||
{
|
||||
g_main_threadpool = std::make_unique<ThreadPool>();
|
||||
}
|
||||
else
|
||||
{
|
||||
g_main_threadpool = std::make_unique<ThreadPool>(thread_count);
|
||||
}
|
||||
}
|
||||
|
||||
void I_ThreadPoolShutdown(void)
|
||||
{
|
||||
if (!g_main_threadpool)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
g_main_threadpool->shutdown();
|
||||
g_main_threadpool = nullptr;
|
||||
}
|
||||
|
||||
void I_ThreadPoolSubmit(srb2cthunk_t thunk, void* data)
|
||||
{
|
||||
SRB2_ASSERT(g_main_threadpool != nullptr);
|
||||
|
||||
g_main_threadpool->schedule([=]() {
|
||||
(thunk)(data);
|
||||
});
|
||||
g_main_threadpool->notify();
|
||||
}
|
||||
|
||||
void I_ThreadPoolWaitIdle(void)
|
||||
{
|
||||
SRB2_ASSERT(g_main_threadpool != nullptr);
|
||||
|
||||
g_main_threadpool->wait_idle();
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
// BLANKART
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2024 by Ronald "Eidolon" Kinard
|
||||
// Copyright (C) 2024 by Kart Krew
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __SRB2_CORE_THREAD_POOL_H__
|
||||
#define __SRB2_CORE_THREAD_POOL_H__
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include <condition_variable>
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "spmc_queue.hpp"
|
||||
|
||||
namespace srb2
|
||||
{
|
||||
|
||||
class ThreadPool
|
||||
{
|
||||
public:
|
||||
struct Task
|
||||
{
|
||||
void (*thunk)(void*);
|
||||
void (*deleter)(void*);
|
||||
std::shared_ptr<std::atomic<uint32_t>> pseudosema;
|
||||
std::array<std::byte, 512 - sizeof(void(*)(void*)) * 2 - sizeof(std::shared_ptr<std::atomic<uint32_t>>)> raw;
|
||||
};
|
||||
|
||||
using Queue = SpMcQueue<Task>;
|
||||
|
||||
class Sema
|
||||
{
|
||||
std::shared_ptr<std::atomic<uint32_t>> pseudosema_;
|
||||
|
||||
explicit Sema(std::shared_ptr<std::atomic<uint32_t>> sema) : pseudosema_(sema) {}
|
||||
|
||||
friend class ThreadPool;
|
||||
public:
|
||||
Sema() = default;
|
||||
};
|
||||
|
||||
private:
|
||||
std::shared_ptr<std::atomic<bool>> pool_alive_;
|
||||
std::vector<std::shared_ptr<std::mutex>> worker_ready_mutexes_;
|
||||
std::vector<std::shared_ptr<std::condition_variable>> worker_ready_condvars_;
|
||||
std::vector<std::shared_ptr<Queue>> work_queues_;
|
||||
std::vector<std::thread> threads_;
|
||||
size_t next_queue_index_ = 0;
|
||||
std::shared_ptr<std::atomic<uint32_t>> cur_sema_;
|
||||
|
||||
bool immediate_mode_ = false;
|
||||
bool sema_begun_ = false;
|
||||
|
||||
public:
|
||||
ThreadPool();
|
||||
explicit ThreadPool(size_t threads);
|
||||
ThreadPool(const ThreadPool&) = delete;
|
||||
ThreadPool(ThreadPool&&);
|
||||
~ThreadPool();
|
||||
|
||||
ThreadPool& operator=(const ThreadPool&) = delete;
|
||||
ThreadPool& operator=(ThreadPool&&);
|
||||
|
||||
void begin_sema();
|
||||
ThreadPool::Sema end_sema();
|
||||
|
||||
/// Enqueue but don't notify
|
||||
template <typename T> void schedule(T&& thunk);
|
||||
/// Notify threads after several schedules
|
||||
void notify();
|
||||
void notify_sema(const Sema& sema);
|
||||
void wait_idle();
|
||||
void wait_sema(const Sema& sema);
|
||||
void shutdown();
|
||||
};
|
||||
|
||||
extern std::unique_ptr<ThreadPool> g_main_threadpool;
|
||||
|
||||
template <typename F>
|
||||
void callable_caller(F* f)
|
||||
{
|
||||
(*f)();
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
void callable_destroyer(F* f)
|
||||
{
|
||||
f->~F();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void ThreadPool::schedule(T&& thunk)
|
||||
{
|
||||
static_assert(sizeof(T) <= sizeof(std::declval<Task>().raw));
|
||||
|
||||
if (immediate_mode_)
|
||||
{
|
||||
(thunk)();
|
||||
return;
|
||||
}
|
||||
|
||||
if (sema_begun_)
|
||||
{
|
||||
if (cur_sema_ == nullptr)
|
||||
{
|
||||
cur_sema_ = std::make_shared<std::atomic<uint32_t>>(0);
|
||||
}
|
||||
cur_sema_->fetch_add(1, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
size_t qi = next_queue_index_;
|
||||
|
||||
{
|
||||
std::shared_ptr<Queue> q = work_queues_[qi];
|
||||
Task task;
|
||||
task.thunk = reinterpret_cast<void(*)(void*)>(callable_caller<T>);
|
||||
task.deleter = reinterpret_cast<void(*)(void*)>(callable_destroyer<T>);
|
||||
task.pseudosema = cur_sema_;
|
||||
new (reinterpret_cast<T*>(task.raw.data())) T(std::move(thunk));
|
||||
|
||||
q->push(std::move(task));
|
||||
}
|
||||
// worker_ready_condvars_[qi]->notify_one();
|
||||
|
||||
next_queue_index_ += 1;
|
||||
if (next_queue_index_ >= threads_.size())
|
||||
{
|
||||
next_queue_index_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace srb2
|
||||
|
||||
extern "C" {
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
typedef void (*srb2cthunk_t)(void*);
|
||||
|
||||
void I_ThreadPoolInit(void);
|
||||
void I_ThreadPoolShutdown(void);
|
||||
void I_ThreadPoolSubmit(srb2cthunk_t thunk, void* data);
|
||||
void I_ThreadPoolWaitIdle(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // __SRB2_CORE_THREAD_POOL_H__
|
||||
+152
@@ -0,0 +1,152 @@
|
||||
#ifndef __SRB2_CXXUTIL_HPP__
|
||||
#define __SRB2_CXXUTIL_HPP__
|
||||
|
||||
#include <cstdlib>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "doomdef.h"
|
||||
|
||||
namespace srb2 {
|
||||
|
||||
template <class F>
|
||||
class Finally {
|
||||
public:
|
||||
explicit Finally(const F& f) noexcept : f_(f) {}
|
||||
explicit Finally(F&& f) noexcept : f_(f) {}
|
||||
|
||||
Finally(Finally&& from) noexcept : f_(std::move(from.f_)), call_(std::exchange(from.call_, false)) {}
|
||||
|
||||
Finally(const Finally& from) = delete;
|
||||
void operator=(const Finally& from) = delete;
|
||||
void operator=(Finally&& from) = delete;
|
||||
|
||||
~Finally() noexcept {
|
||||
if (call_)
|
||||
f_();
|
||||
}
|
||||
|
||||
private:
|
||||
F f_;
|
||||
bool call_ = true;
|
||||
};
|
||||
|
||||
template <class F>
|
||||
Finally<std::decay_t<F>> finally(F&& f) noexcept {
|
||||
return Finally {std::forward<F>(f)};
|
||||
}
|
||||
|
||||
struct SourceLocation {
|
||||
const char* file_name;
|
||||
unsigned int line_number;
|
||||
};
|
||||
|
||||
#define SRB2_SOURCE_LOCATION \
|
||||
srb2::SourceLocation { __FILE__, __LINE__ }
|
||||
|
||||
#ifndef SRB2_ASSERT_HANDLER
|
||||
#define SRB2_ASSERT_HANDLER srb2::IErrorAssertHandler
|
||||
#endif
|
||||
|
||||
#if !defined(NDEBUG) || defined(PARANOIA)
|
||||
// An assertion level of 2 will activate all invocations of the SRB2_ASSERT macro
|
||||
#define SRB2_ASSERTION_LEVEL 2
|
||||
#else
|
||||
// The minimum assertion level is 1
|
||||
#define SRB2_ASSERTION_LEVEL 1
|
||||
#endif
|
||||
|
||||
/// Assert a precondition expression in debug builds.
|
||||
#define SRB2_ASSERT(expr) srb2::do_assert<2, SRB2_ASSERT_HANDLER>([&] { return (expr); }, SRB2_SOURCE_LOCATION, #expr)
|
||||
|
||||
class IErrorAssertHandler {
|
||||
public:
|
||||
static void handle(const SourceLocation& source_location, const char* expression) {
|
||||
I_Error("Assertion failed at %s:%u: %s != true",
|
||||
source_location.file_name,
|
||||
source_location.line_number,
|
||||
expression);
|
||||
}
|
||||
};
|
||||
|
||||
class NoOpAssertHandler {
|
||||
public:
|
||||
static void handle(const SourceLocation& source_location, const char* expression) {(void)source_location; (void)expression;}
|
||||
};
|
||||
|
||||
/// @brief Assert a precondition expression, aborting the application if it fails.
|
||||
/// @tparam Expr
|
||||
/// @tparam Level the level of this assertion; if it is less than or equal to SRB2_ASSERTION_LEVEL, this overload will
|
||||
/// activate.
|
||||
/// @param expr a callable which returns a bool
|
||||
/// @param source_location a struct containing the source location of the assertion, e.g. SRB2_SOURCE_LOCATION
|
||||
/// @param expression the expression evaluated in the expression callable
|
||||
/// @param message an optional message to display for the assertion
|
||||
template <unsigned int Level, class Handler, class Expr>
|
||||
std::enable_if_t<(Level <= SRB2_ASSERTION_LEVEL), void>
|
||||
do_assert(const Expr& expr, const SourceLocation& source_location, const char* expression = "") noexcept {
|
||||
static_assert(Level > 0, "level of an assertion must not be 0");
|
||||
if (!expr()) {
|
||||
Handler::handle(source_location, expression);
|
||||
std::abort();
|
||||
}
|
||||
}
|
||||
|
||||
template <unsigned int Level, class, class Expr>
|
||||
std::enable_if_t<(Level > SRB2_ASSERTION_LEVEL), void>
|
||||
do_assert(const Expr&, const SourceLocation&, const char* = "") noexcept {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
class NotNull final {
|
||||
T ptr_;
|
||||
|
||||
public:
|
||||
static_assert(std::is_convertible_v<decltype(std::declval<T>() != nullptr), bool>,
|
||||
"T is not comparable with nullptr_t");
|
||||
|
||||
/// @brief Move-construct from the pointer value U, asserting that it is not null. Allows construction of a
|
||||
/// NotNull<T> from any compatible pointer U, for example with polymorphic classes.
|
||||
template <typename U, typename = std::enable_if_t<std::is_convertible_v<U, T>>>
|
||||
constexpr NotNull(U&& rhs) : ptr_(std::forward<U>(rhs)) {
|
||||
SRB2_ASSERT(ptr_ != nullptr);
|
||||
}
|
||||
|
||||
/// @brief Wrap the pointer type T, asserting that the pointer is not null.
|
||||
template <typename = std::enable_if_t<!std::is_same_v<std::nullptr_t, T>>>
|
||||
constexpr NotNull(T rhs) : ptr_(std::move(rhs)) {
|
||||
SRB2_ASSERT(ptr_ != nullptr);
|
||||
}
|
||||
|
||||
/// @brief Copy construction from NotNull of convertible type U. Only if the incoming pointer is NotNull already.
|
||||
template <typename U, typename = std::enable_if_t<std::is_convertible_v<U, T>>>
|
||||
constexpr NotNull(const NotNull<U>& rhs) : NotNull(rhs.get()) {
|
||||
// Value is guaranteed to be not null by construction; no assertion necessary
|
||||
}
|
||||
|
||||
NotNull(const NotNull& rhs) = default;
|
||||
NotNull& operator=(const NotNull& rhs) = default;
|
||||
|
||||
/// @brief Get the stored pointer.
|
||||
constexpr T get() const { return ptr_; }
|
||||
|
||||
/// @brief Convert to T (the pointer type).
|
||||
constexpr operator T() const { return get(); }
|
||||
|
||||
/// @brief Arrow-dereference to *T (the actual value pointed to).
|
||||
constexpr decltype(auto) operator->() const { return get(); }
|
||||
|
||||
/// @brief Dereference to *T (the actual value pointed to).
|
||||
constexpr decltype(auto) operator*() const { return *get(); }
|
||||
|
||||
// It is not allowed to construct NotNull<T> with nullptr regardless of T.
|
||||
NotNull(std::nullptr_t) = delete;
|
||||
NotNull& operator=(std::nullptr_t) = delete;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
NotNull(T) -> NotNull<T>;
|
||||
|
||||
} // namespace srb2
|
||||
|
||||
#endif // __SRB2_CXXUTIL_HPP__
|
||||
+158
-35
@@ -87,6 +87,9 @@ boolean serverrunning = false;
|
||||
INT32 serverplayer = 0;
|
||||
char motd[254], server_context[8]; // Message of the Day, Unique Context (even without Mumble support)
|
||||
|
||||
plrinfo playerinfo[MAXPLAYERS];
|
||||
SINT8 joinnode = 0; // used for CL_VIEWSERVER
|
||||
|
||||
// Server specific vars
|
||||
UINT8 playernode[MAXPLAYERS];
|
||||
|
||||
@@ -95,7 +98,7 @@ UINT8 playernode[MAXPLAYERS];
|
||||
tic_t jointimeout = (3*TICRATE);
|
||||
static boolean sendingsavegame[MAXNETNODES]; // Are we sending the savegame?
|
||||
#ifdef SATURNPAK
|
||||
static boolean resendingsavegame[MAXNETNODES]; // Are we resending the savegame?
|
||||
static tic_t resendingsavegame[MAXNETNODES]; // Are we resending the savegame?
|
||||
static tic_t savegameresendcooldown[MAXNETNODES]; // How long before we can resend again?
|
||||
#endif
|
||||
static tic_t freezetimeout[MAXNETNODES]; // Until when can this node freeze the server before getting a timeout?
|
||||
@@ -1068,6 +1071,7 @@ static void SV_RequireResynch(INT32 node)
|
||||
|
||||
// Initial setup
|
||||
memset(resynch_sent[node], 0, MAXPLAYERS);
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; ++i)
|
||||
{
|
||||
if (!playeringame[i]) // Player not in game so just drop it from required synch
|
||||
@@ -1184,6 +1188,7 @@ typedef enum
|
||||
#endif
|
||||
CL_CONNECTED,
|
||||
CL_ABORTED,
|
||||
CL_VIEWSERVER,
|
||||
CL_ASKFULLFILELIST,
|
||||
CL_CONFIRMCONNECT,
|
||||
#ifdef HAVE_CURL
|
||||
@@ -1247,7 +1252,7 @@ static inline void CL_DrawConnectionStatus(void)
|
||||
if (!menuactive) // menu already draws its own fade
|
||||
V_DrawFadeScreen(0xFF00, 16); // force default
|
||||
|
||||
if (cl_mode != CL_DOWNLOADFILES && cl_mode != CL_LOADFILES && cl_mode != CL_CHECKFILES
|
||||
if (cl_mode != CL_DOWNLOADFILES && cl_mode != CL_LOADFILES && cl_mode != CL_CHECKFILES && cl_mode != CL_VIEWSERVER
|
||||
#ifdef HAVE_CURL
|
||||
&& cl_mode != CL_DOWNLOADHTTPFILES
|
||||
#endif
|
||||
@@ -1367,6 +1372,78 @@ static inline void CL_DrawConnectionStatus(void)
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24, V_20TRANS|V_MONOSPACE|MENUCAPS,
|
||||
va(" %2u/%2u Files",loadcompletednum,fileneedednum));
|
||||
}
|
||||
else if (cl_mode == CL_VIEWSERVER)
|
||||
{
|
||||
V_DrawFill(8, 16, BASEVIDWIDTH - 16, 54, 239);
|
||||
|
||||
V_DrawThinString(12 + 80, 18, V_ALLOWLOWERCASE, va("%s", serverlist[joinnode].info.servername));
|
||||
|
||||
const char *map = va("%sP", serverlist[joinnode].info.mapname);
|
||||
patch_t *current_map = W_LumpExists(map) ? W_CachePatchName(map, PU_CACHE) : W_CachePatchName("BLANKLVL", PU_CACHE);
|
||||
V_DrawSmallScaledPatch(10, 18, 0, current_map);
|
||||
|
||||
V_DrawThinString(12 + 80, 38, V_ALLOWLOWERCASE, va("%s", serverlist[joinnode].info.maptitle));
|
||||
V_DrawThinString(12 + 80, 48, V_ALLOWLOWERCASE, va("%s", Gametype_Names[serverlist[joinnode].info.gametype]));
|
||||
|
||||
if (fileneedednum > 0)
|
||||
{
|
||||
V_DrawThinString(12 + 80, 58, V_ALLOWLOWERCASE|V_ORANGEMAP, va("%i Addons", fileneedednum));
|
||||
}
|
||||
else
|
||||
{
|
||||
V_DrawThinString(12 + 80, 58, V_ALLOWLOWERCASE|V_YELLOWMAP, "Vanilla");
|
||||
}
|
||||
|
||||
if (serverlist[joinnode].info.cheatsenabled)
|
||||
{
|
||||
V_DrawRightAlignedThinString(BASEVIDWIDTH - 12, 58, V_ALLOWLOWERCASE|V_GREENMAP, "Cheats");
|
||||
}
|
||||
|
||||
V_DrawFill(8, 72, BASEVIDWIDTH - 16, 112, 239);
|
||||
|
||||
V_DrawString(12, 74, V_ALLOWLOWERCASE|V_YELLOWMAP, "Players");
|
||||
V_DrawRightAlignedString(BASEVIDWIDTH - 12, 74, V_ALLOWLOWERCASE|V_YELLOWMAP, va("%i / %i", serverlist[joinnode].info.numberofplayer, serverlist[joinnode].info.maxplayer));
|
||||
|
||||
INT32 i;
|
||||
INT32 count = 0;
|
||||
INT32 x = 14;
|
||||
INT32 y = 84;
|
||||
INT32 statuscolor = 1;
|
||||
char player_name[MAXPLAYERNAME+1];
|
||||
if (serverlist[joinnode].info.numberofplayer > 0)
|
||||
{
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (playerinfo[i].node < 255)
|
||||
{
|
||||
strncpy(player_name, playerinfo[i].name, MAXPLAYERNAME);
|
||||
V_DrawThinString(x + 10, y, V_ALLOWLOWERCASE|V_6WIDTHSPACE, player_name);
|
||||
|
||||
if (playerinfo[i].team == 0) { statuscolor = 184; } // playing
|
||||
if (playerinfo[i].data & 0x20) { statuscolor = 86; } // tag IT
|
||||
if (playerinfo[i].team == 1) { statuscolor = 128; } // ctf red team
|
||||
if (playerinfo[i].team == 2) { statuscolor = 232; } // ctf blue team
|
||||
if (playerinfo[i].team == 255) { statuscolor = 16; } // spectator or non-team
|
||||
|
||||
V_DrawFill(x, y, 7, 7, 31);
|
||||
V_DrawFill(x, y, 6, 6, statuscolor);
|
||||
|
||||
y += 9;
|
||||
count++;
|
||||
if ((count == 11) || (count == 22))
|
||||
{
|
||||
x += 104;
|
||||
y = 84;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Buttons
|
||||
V_DrawFill(8, BASEVIDHEIGHT - 14, BASEVIDWIDTH - 16, 12, 239);
|
||||
V_DrawThinString(16, BASEVIDHEIGHT - 12, V_ALLOWLOWERCASE, va("[%sESC%s] = Abort", "\x82", "\x80"));
|
||||
V_DrawRightAlignedThinString(BASEVIDWIDTH - 12, BASEVIDHEIGHT - 12, V_ALLOWLOWERCASE, va("[%sENTER%s] = Join", "\x82", "\x80"));
|
||||
}
|
||||
else if (filedownload.current != -1)
|
||||
{
|
||||
INT32 dldlength;
|
||||
@@ -1687,13 +1764,7 @@ static void SV_SendPlayerInfo(INT32 node)
|
||||
|
||||
for (i = 0; i < MSCOMPAT_MAXPLAYERS; i++)
|
||||
{
|
||||
if (i >= MAXPLAYERS)
|
||||
{
|
||||
netbuffer->u.playerinfo[i].node = 255;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (playeringame[i] == UINT8_MAX || !playeringame[i])
|
||||
if ((i >= MAXPLAYERS) || !playeringame[i])
|
||||
{
|
||||
netbuffer->u.playerinfo[i].node = 255; // This slot is empty.
|
||||
continue;
|
||||
@@ -1778,8 +1849,6 @@ static boolean SV_SendServerConfig(INT32 node)
|
||||
memset(netbuffer->u.servercfg.playerskins, 0xFF, sizeof(netbuffer->u.servercfg.playerskins));
|
||||
memset(netbuffer->u.servercfg.playercolor, 0xFF, sizeof(netbuffer->u.servercfg.playercolor));
|
||||
|
||||
memset(netbuffer->u.servercfg.adminplayers, -1, sizeof(netbuffer->u.servercfg.adminplayers));
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
netbuffer->u.servercfg.adminplayers[i] = (SINT8)adminplayers[i];
|
||||
@@ -2476,6 +2545,7 @@ static boolean CL_ServerConnectionSearchTicker(tic_t *asksent)
|
||||
if (i < 0)
|
||||
return true;
|
||||
}
|
||||
joinnode = i;
|
||||
|
||||
// Quit here rather than downloading files and being refused later.
|
||||
if (serverlist[i].info.numberofplayer >= serverlist[i].info.maxplayer)
|
||||
@@ -2502,7 +2572,7 @@ static boolean CL_ServerConnectionSearchTicker(tic_t *asksent)
|
||||
return true;
|
||||
}
|
||||
|
||||
cl_mode = CL_CHECKFILES;
|
||||
cl_mode = (cv_serverinfoscreen.value) ? CL_VIEWSERVER : CL_CHECKFILES;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2556,7 +2626,7 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
|
||||
|
||||
case CL_ASKFULLFILELIST:
|
||||
if (cl_lastcheckedfilecount == UINT16_MAX) // All files retrieved
|
||||
cl_mode = CL_CHECKFILES;
|
||||
cl_mode = (cv_serverinfoscreen.value) ? CL_VIEWSERVER : CL_CHECKFILES;
|
||||
else if (fileneedednum != cl_lastcheckedfilecount || I_GetTime() >= *asksent)
|
||||
{
|
||||
if (CL_AskFileList(fileneedednum))
|
||||
@@ -2722,6 +2792,15 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
|
||||
D_ProcessEvents(); //needed for menu system to receive inputs
|
||||
|
||||
key = I_GetKey();
|
||||
|
||||
if (cl_mode == CL_VIEWSERVER)
|
||||
{
|
||||
if (key == KEY_ENTER || key == KEY_JOY1)
|
||||
cl_mode = CL_CHECKFILES;
|
||||
else if (key == KEY_ESCAPE || key == KEY_JOY1+1)
|
||||
cl_mode = CL_ABORTED;
|
||||
}
|
||||
|
||||
// Only ESC and non-keyboard keys abort connection
|
||||
if (!modeattacking && (key == KEY_ESCAPE || key == KEY_JOY1+1 || cl_mode == CL_ABORTED))
|
||||
{
|
||||
@@ -3275,7 +3354,7 @@ void CL_ClearPlayer(INT32 playernum)
|
||||
P_RemoveMobj(players[playernum].mo);
|
||||
}
|
||||
|
||||
memset(&players[playernum], 0, sizeof (player_t));
|
||||
memset(&players[playernum], 0, sizeof(player_t));
|
||||
}
|
||||
|
||||
//
|
||||
@@ -4149,6 +4228,8 @@ consvar_t cv_downloadspeed = {"downloadspeed", "300", CV_SAVE, downloadspeed_con
|
||||
static CV_PossibleValue_t connectawaittime_cons_t[] = {{1, "MIN"}, {60, "MAX"}, {0, "Inf"}, {0, NULL}};
|
||||
consvar_t cv_connectawaittime = {"connectawaittime", "5", CV_SAVE, connectawaittime_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
consvar_t cv_serverinfoscreen = {"serverinfoscreen", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
static void Got_AddPlayer(UINT8 **p, INT32 playernum);
|
||||
static void Got_RemovePlayer(UINT8 **p, INT32 playernum);
|
||||
|
||||
@@ -4251,7 +4332,7 @@ static void ResetNode(INT32 node)
|
||||
// SATURN
|
||||
#ifdef SATURNPAK
|
||||
is_client_saturn[node] = false;
|
||||
resendingsavegame[node] = false;
|
||||
resendingsavegame[node] = 0;
|
||||
savegameresendcooldown[node] = 0;
|
||||
gamestate_resend_counter[node] = 0;
|
||||
#endif
|
||||
@@ -4284,14 +4365,14 @@ void SV_ResetServer(void)
|
||||
sprintf(player_names[i], "Player %d", i + 1);
|
||||
}
|
||||
|
||||
memset(player_name_changes, 0, sizeof player_name_changes);
|
||||
memset(player_name_changes, 0, sizeof(player_name_changes));
|
||||
|
||||
memset(playeringame, false, sizeof playeringame);
|
||||
memset(playernode, UINT8_MAX, sizeof playernode);
|
||||
memset(playeringame, false, sizeof(playeringame));
|
||||
memset(playernode, UINT8_MAX, sizeof(playernode));
|
||||
|
||||
pingmeasurecount = 1;
|
||||
memset(realpingtable, 0, sizeof realpingtable);
|
||||
memset(playerpingtable, 0, sizeof playerpingtable);
|
||||
memset(realpingtable, 0, sizeof(realpingtable));
|
||||
memset(playerpingtable, 0, sizeof(playerpingtable));
|
||||
|
||||
ClearAdminPlayers();
|
||||
|
||||
@@ -4916,6 +4997,16 @@ static void HandleServerInfo(SINT8 node)
|
||||
if (client && cl_mode > CL_SEARCHING && node == servernode)
|
||||
memcpy(connectedservername, netbuffer->u.serverinfo.servername, MAXSERVERNAME);
|
||||
}
|
||||
|
||||
|
||||
static void HandlePlayerInfo(SINT8 node)
|
||||
{
|
||||
(void)node;
|
||||
|
||||
INT32 i;
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
playerinfo[i] = netbuffer->u.playerinfo[i];
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SATURNPAK
|
||||
@@ -4952,7 +5043,7 @@ static void PT_CanReceiveGamestate(SINT8 node)
|
||||
CONS_Printf(M_GetText("Resending game state to %s...\n"), player_names[nodetoplayer[node]]);
|
||||
|
||||
SV_SendSaveGame(node, true); // Resend a complete game state
|
||||
resendingsavegame[node] = true;
|
||||
resendingsavegame[node] = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -5204,6 +5295,10 @@ static void HandlePacketFromAwayNode(SINT8 node)
|
||||
|
||||
case PT_CLIENTCMD:
|
||||
break; // This is not an "unknown packet"
|
||||
|
||||
case PT_PLAYERINFO:
|
||||
HandlePlayerInfo(node);
|
||||
break;
|
||||
|
||||
case PT_SERVERTICS:
|
||||
// Do not remove my own server (we have just get a out of order packet)
|
||||
@@ -5324,18 +5419,18 @@ static void HandlePacketFromPlayer(SINT8 node)
|
||||
/// \todo Use a separate cvar for that kind of timeout?
|
||||
freezetimeout[node] = I_GetTime() + connectiontimeout;
|
||||
|
||||
// If we've alredy received a ticcmd for this tic, just submit it for the next one.
|
||||
tic_t faketic = maketic;
|
||||
if ((!!(netcmds[maketic % TICQUEUE][netconsole].angleturn & TICCMD_RECEIVED))
|
||||
&& (maketic - firstticstosend < TICQUEUE - 1))
|
||||
faketic++;
|
||||
|
||||
// Don't do anything for packets of type NODEKEEPALIVE?
|
||||
// Sryder 2018/07/01: Update the freezetimeout still!
|
||||
if (netbuffer->packettype == PT_NODEKEEPALIVE
|
||||
|| netbuffer->packettype == PT_NODEKEEPALIVEMIS)
|
||||
break;
|
||||
|
||||
// If we've alredy received a ticcmd for this tic, just submit it for the next one.
|
||||
tic_t faketic = maketic;
|
||||
if ((!!(netcmds[maketic % TICQUEUE][netconsole].angleturn & TICCMD_RECEIVED))
|
||||
&& (maketic - firstticstosend < TICQUEUE - 1))
|
||||
faketic++;
|
||||
|
||||
// Copy ticcmd
|
||||
G_MoveTiccmd(&netcmds[faketic%TICQUEUE][netconsole], &netbuffer->u.clientpak.cmd, 1);
|
||||
|
||||
@@ -5395,11 +5490,11 @@ static void HandlePacketFromPlayer(SINT8 node)
|
||||
|
||||
// Check player consistancy during the level
|
||||
if (gamestate == GS_LEVEL
|
||||
&& (realstart > gametic - TICQUEUE+1 && realstart <= gametic)
|
||||
&& (realstart <= gametic && realstart + TICQUEUE - 1 > gametic)
|
||||
&& consistancy[realstart%TICQUEUE] != SHORT(netbuffer->u.clientpak.consistancy)
|
||||
&& (!UseSaturnSynch(node) || (!resendingsavegame[node] && savegameresendcooldown[node] <= I_GetTime() && !SV_ResendingSavegameToAnyone())))
|
||||
{
|
||||
resendingsavegame[node] = false; // reset this before just in case
|
||||
resendingsavegame[node] = 0; // reset this before just in case
|
||||
|
||||
// Check if a client is saturn before sending ANYTHING!
|
||||
// this way we only send stuff to clients we know can use the gamestate resend
|
||||
@@ -5409,7 +5504,7 @@ static void HandlePacketFromPlayer(SINT8 node)
|
||||
// Tell the client we are about to resend them the gamestate
|
||||
netbuffer->packettype = PT_WILLRESENDGAMESTATE;
|
||||
HSendPacket(node, true, 0, 0);
|
||||
resendingsavegame[node] = true;
|
||||
resendingsavegame[node] = 1;
|
||||
}
|
||||
else if (UseVanillaSynch(node))
|
||||
{
|
||||
@@ -5425,10 +5520,13 @@ static void HandlePacketFromPlayer(SINT8 node)
|
||||
}
|
||||
|
||||
if (cv_blamecfail.value)
|
||||
{
|
||||
CONS_Printf(M_GetText("Synch failure for player %d (%s); expected %hd, got %hd\n"),
|
||||
netconsole+1, player_names[netconsole],
|
||||
consistancy[realstart%TICQUEUE],
|
||||
SHORT(netbuffer->u.clientpak.consistancy));
|
||||
}
|
||||
|
||||
DEBFILE(va("Restoring player %d (synch failure) [%update] %d!=%d\n",
|
||||
netconsole, realstart, consistancy[realstart%TICQUEUE],
|
||||
SHORT(netbuffer->u.clientpak.consistancy)));
|
||||
@@ -5700,7 +5798,7 @@ static void HandlePacketFromPlayer(SINT8 node)
|
||||
break;
|
||||
}
|
||||
|
||||
//Update client ping table from the server.
|
||||
// Update client ping table from the server.
|
||||
if (client)
|
||||
{
|
||||
UINT8 i;
|
||||
@@ -5736,7 +5834,7 @@ static void HandlePacketFromPlayer(SINT8 node)
|
||||
break;
|
||||
case PT_RECEIVEDGAMESTATE:
|
||||
sendingsavegame[node] = false;
|
||||
resendingsavegame[node] = false;
|
||||
resendingsavegame[node] = 0;
|
||||
savegameresendcooldown[node] = I_GetTime() + cv_resynchcooldown.value * TICRATE; // I_GetTime() + 5 * TICRATE;
|
||||
break;
|
||||
case PT_WILLRESENDGAMESTATE:
|
||||
@@ -5796,8 +5894,9 @@ static void GetPackets(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (netbuffer->packettype == PT_PLAYERINFO)
|
||||
continue; // We do nothing with PLAYERINFO, that's for the MS browser.
|
||||
/*if (netbuffer->packettype == PT_PLAYERINFO)
|
||||
continue; // We do nothing with PLAYERINFO, that's for the MS browser. Not quite true anymore :p*/
|
||||
|
||||
|
||||
// We also count unknown packets, hence "<="
|
||||
if (netbuffer->packettype <= NUMPACKETTYPE)
|
||||
@@ -6366,10 +6465,35 @@ static void SV_Maketic(void)
|
||||
maketic++;
|
||||
}
|
||||
|
||||
#ifdef SATURNPAK
|
||||
static void SV_UpdateResendGamestateTimeout(void)
|
||||
{
|
||||
for (INT32 i = 0; i < MAXNETNODES; ++i)
|
||||
{
|
||||
if (!resendingsavegame[i])
|
||||
continue;
|
||||
|
||||
resendingsavegame[i]++;
|
||||
|
||||
// Resending savegame took too long
|
||||
if (resendingsavegame[i] > (tic_t)TICRATE*cv_pingtimeout.value)
|
||||
{
|
||||
resendingsavegame[i] = 0;
|
||||
SendKick(i, KICK_MSG_CON_FAIL);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
boolean TryRunTics(tic_t realtics)
|
||||
{
|
||||
boolean ticking;
|
||||
|
||||
#ifdef SATURNPAK
|
||||
if (server)
|
||||
SV_UpdateResendGamestateTimeout();
|
||||
#endif
|
||||
|
||||
// the machine has lagged but it is not so bad
|
||||
if (realtics > TICRATE/7) // FIXME: consistency failure!!
|
||||
{
|
||||
@@ -6510,7 +6634,6 @@ static inline void PingUpdate(void)
|
||||
if (pingtimeout[i] > 0)
|
||||
pingtimeout[i]--;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//kick lagging players... unless everyone but the server's ping sucks.
|
||||
|
||||
@@ -13,6 +13,10 @@
|
||||
#ifndef __D_CLISRV__
|
||||
#define __D_CLISRV__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "d_ticcmd.h"
|
||||
#include "d_net.h"
|
||||
#include "d_netcmd.h"
|
||||
@@ -577,6 +581,9 @@ extern boolean acceptnewnode;
|
||||
extern SINT8 servernode;
|
||||
extern char connectedservername[MAXSERVERNAME+1];
|
||||
|
||||
extern plrinfo playerinfo[MAXPLAYERS];
|
||||
extern SINT8 joinnode;
|
||||
|
||||
void Command_Ping_f(void);
|
||||
extern tic_t connectiontimeout;
|
||||
extern tic_t jointimeout;
|
||||
@@ -608,6 +615,8 @@ extern consvar_t cv_connectawaittime;
|
||||
|
||||
extern consvar_t cv_discordinvites;
|
||||
|
||||
extern consvar_t cv_serverinfoscreen;
|
||||
|
||||
// Used in d_net, the only dependence
|
||||
//tic_t ExpandTics(INT32 low, tic_t basetic);
|
||||
void D_ClientServerInit(void);
|
||||
@@ -689,4 +698,9 @@ typedef struct rewind_s {
|
||||
void CL_ClearRewinds(void);
|
||||
rewind_t *CL_SaveRewindPoint(size_t demopos);
|
||||
rewind_t *CL_RewindToTime(tic_t time);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+180
-147
@@ -40,6 +40,7 @@
|
||||
#include "g_game.h"
|
||||
#include "g_input.h"
|
||||
#include "hu_stuff.h"
|
||||
#include "m_emotes.h"
|
||||
#include "i_sound.h"
|
||||
#include "i_system.h"
|
||||
#include "i_time.h"
|
||||
@@ -72,6 +73,9 @@
|
||||
#include "d_protocol.h"
|
||||
#include "m_perfstats.h"
|
||||
#include "k_kart.h"
|
||||
#include "k_hud.h"
|
||||
|
||||
#include "core/memory.h"
|
||||
|
||||
#include "lua_script.h"
|
||||
|
||||
@@ -197,12 +201,10 @@ static void D_PadMenuScrollInput(UINT8 input)
|
||||
// and pass it to the eventlist
|
||||
static void D_GamePadMenuScrollTicker(void)
|
||||
{
|
||||
UINT8 i;
|
||||
static UINT8 menuInputDelayTimer = 0;
|
||||
|
||||
if (dedicated)
|
||||
return;
|
||||
|
||||
for (UINT8 i = 0; i < 4; i++)
|
||||
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
|
||||
{
|
||||
if (dpadscrollstate[i])
|
||||
{
|
||||
@@ -222,10 +224,10 @@ static void D_GamePadMenuScrollTicker(void)
|
||||
static void D_DeviceLEDTick(void)
|
||||
{
|
||||
UINT8 i;
|
||||
static UINT16 color[MAXSPLITSCREENPLAYERS] = {0, 0, 0, 0};
|
||||
static UINT16 curcolor[MAXSPLITSCREENPLAYERS] = {0, 0, 0, 0};
|
||||
static UINT16 color[MAXSPLITSCREENPLAYERS] = {0};
|
||||
static UINT16 curcolor[MAXSPLITSCREENPLAYERS] = {0};
|
||||
|
||||
if (dedicated || numcontrollers == 0)
|
||||
if (numcontrollers == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -252,7 +254,6 @@ static void D_DeviceLEDTick(void)
|
||||
void D_ProcessEvents(void)
|
||||
{
|
||||
event_t *ev;
|
||||
|
||||
boolean eaten;
|
||||
|
||||
for (; eventtail != eventhead; eventtail = (eventtail+1) & (MAXEVENTS-1))
|
||||
@@ -291,8 +292,10 @@ void D_ProcessEvents(void)
|
||||
|
||||
// Demo input:
|
||||
if (demo.playback)
|
||||
{
|
||||
if (M_DemoResponder(ev))
|
||||
continue; // demo ate the event
|
||||
}
|
||||
|
||||
// console input
|
||||
#ifdef HAVE_THREADS
|
||||
@@ -317,6 +320,110 @@ void D_ProcessEvents(void)
|
||||
// draw current display, possibly wiping it from the previous
|
||||
//
|
||||
|
||||
static void D_Renderview(void)
|
||||
{
|
||||
UINT8 i;
|
||||
|
||||
if (automapactive)
|
||||
return;
|
||||
|
||||
R_ApplyLevelInterpolators(rendertimefrac);
|
||||
|
||||
if (rendermode == render_soft)
|
||||
{
|
||||
// if this is display player 1
|
||||
if (cv_homremoval.value)
|
||||
{
|
||||
if (cv_homremoval.value == 1)
|
||||
{
|
||||
// Clear the software screen buffer to remove HOM
|
||||
memset(vid.screens[0], 31, vid.width * vid.height);
|
||||
}
|
||||
else if (cv_homremoval.value == 2)
|
||||
{
|
||||
//'development' HOM removal -- makes it blindingly obvious if HOM is spotted.
|
||||
memset(vid.screens[0], 32+(timeinmap&15), vid.width * vid.height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Draw over the fourth screen so you don't have to stare at a HOM :V
|
||||
if (splitscreen == 2)
|
||||
{
|
||||
// V_DrawPatchFill, but for the fourth screen only
|
||||
patch_t *pat = W_CachePatchName("SRB2BACK", PU_CACHE);
|
||||
INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy);
|
||||
INT32 x, y, pw = SHORT(pat->width) * dupz, ph = SHORT(pat->height) * dupz;
|
||||
|
||||
for (x = vid.width>>1; x < vid.width; x += pw)
|
||||
{
|
||||
for (y = vid.height>>1; y < vid.height; y += ph)
|
||||
V_DrawScaledPatch(x, y, V_NOSCALESTART, pat);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i <= splitscreen; i++)
|
||||
{
|
||||
const boolean issplitscreen = (i > 0);
|
||||
|
||||
if (!P_MobjWasRemoved(players[displayplayers[i]].mo) || players[displayplayers[i]].playerstate == PST_DEAD)
|
||||
{
|
||||
viewssnum = i;
|
||||
|
||||
if (!issplitscreen) // Initialize for P1
|
||||
{
|
||||
viewwindowy = viewwindowx = 0;
|
||||
objectsdrawn = 0;
|
||||
}
|
||||
|
||||
#ifdef HWRENDER
|
||||
if (rendermode == render_opengl)
|
||||
{
|
||||
HWR_RenderPlayerView();
|
||||
R_RestoreLevelInterpolators();
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
if (issplitscreen) // Splitscreen-specific
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (splitscreen > 1)
|
||||
{
|
||||
viewwindowx = viewwidth;
|
||||
viewwindowy = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
viewwindowx = 0;
|
||||
viewwindowy = viewheight;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
viewwindowx = 0;
|
||||
viewwindowy = viewheight;
|
||||
break;
|
||||
case 3:
|
||||
viewwindowx = viewwidth;
|
||||
viewwindowy = viewheight;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
R_RenderPlayerView(&players[displayplayers[i]]);
|
||||
}
|
||||
|
||||
if (!issplitscreen)
|
||||
R_ApplyViewMorph();
|
||||
|
||||
V_DoPostProcessor(i, postimgparam[i]);
|
||||
}
|
||||
|
||||
R_RestoreLevelInterpolators();
|
||||
}
|
||||
|
||||
// wipegamestate can be set to -1 to force a wipe on the next draw
|
||||
// added comment : there is a wipe eatch change of the gamestate
|
||||
gamestate_t wipegamestate = GS_LEVEL;
|
||||
@@ -327,7 +434,6 @@ static boolean D_Display(void)
|
||||
boolean forcerefresh = false;
|
||||
static boolean wipe = false;
|
||||
INT32 wipedefindex = 0;
|
||||
UINT8 i;
|
||||
|
||||
if (!dedicated)
|
||||
{
|
||||
@@ -366,6 +472,7 @@ static boolean D_Display(void)
|
||||
{
|
||||
// set for all later
|
||||
wipedefindex = gamestate; // wipe_xxx_toblack
|
||||
|
||||
if (gamestate == GS_TITLESCREEN && wipegamestate != GS_INTRO)
|
||||
wipedefindex = wipe_timeattack_toblack;
|
||||
else if (gamestate == GS_INTERMISSION)
|
||||
@@ -378,26 +485,28 @@ static boolean D_Display(void)
|
||||
|
||||
if (!dedicated)
|
||||
{
|
||||
// Fade to black first
|
||||
if (gamestate != GS_LEVEL // fades to black on its own timing, always
|
||||
&& wipedefs[wipedefindex] != UINT8_MAX)
|
||||
if (gamestate != GS_LEVEL)
|
||||
{
|
||||
F_WipeStartScreen();
|
||||
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
|
||||
F_WipeEndScreen();
|
||||
F_RunWipe(wipedefs[wipedefindex], gamestate != GS_TIMEATTACK);
|
||||
ranwipe = true;
|
||||
}
|
||||
// Fade to black first
|
||||
if (wipedefs[wipedefindex] != UINT8_MAX) // fades to black on its own timing, always
|
||||
{
|
||||
F_WipeStartScreen();
|
||||
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
|
||||
F_WipeEndScreen();
|
||||
F_RunWipe(wipedefs[wipedefindex], gamestate != GS_TIMEATTACK);
|
||||
ranwipe = true;
|
||||
}
|
||||
|
||||
if (gamestate != GS_LEVEL && rendermode != render_none)
|
||||
{
|
||||
V_SetPaletteLump("PLAYPAL"); // Reset the palette
|
||||
R_ReInitColormaps(0, LUMPERROR);
|
||||
if (rendermode != render_none)
|
||||
{
|
||||
V_SetPaletteLump("PLAYPAL"); // Reset the palette
|
||||
R_ReInitColormaps(0, LUMPERROR);
|
||||
}
|
||||
}
|
||||
|
||||
F_WipeStartScreen();
|
||||
}
|
||||
else //dedicated servers
|
||||
else // dedicated servers
|
||||
{
|
||||
F_RunWipe(wipedefs[wipedefindex], gamestate != GS_TIMEATTACK);
|
||||
ranwipe = true;
|
||||
@@ -405,7 +514,7 @@ static boolean D_Display(void)
|
||||
}
|
||||
}
|
||||
|
||||
if (dedicated) //bail out after wipe logic
|
||||
if (dedicated) // bail out after wipe logic
|
||||
return false;
|
||||
|
||||
// do buffered drawing
|
||||
@@ -430,9 +539,6 @@ static boolean D_Display(void)
|
||||
HU_Drawer();
|
||||
break;
|
||||
|
||||
case GS_TIMEATTACK:
|
||||
break;
|
||||
|
||||
case GS_INTRO:
|
||||
F_IntroDrawer();
|
||||
if (wipegamestate == (gamestate_t)-1)
|
||||
@@ -484,6 +590,7 @@ static boolean D_Display(void)
|
||||
HU_Erase();
|
||||
HU_Drawer();
|
||||
}
|
||||
case GS_TIMEATTACK:
|
||||
case GS_DEDICATEDSERVER:
|
||||
case GS_NULL:
|
||||
break;
|
||||
@@ -492,89 +599,10 @@ static boolean D_Display(void)
|
||||
if (gamestate == GS_LEVEL)
|
||||
{
|
||||
// draw the view directly
|
||||
if (cv_renderview.value && !automapactive)
|
||||
if (cv_renderview.value)
|
||||
{
|
||||
PS_START_TIMING(ps_rendercalltime);
|
||||
|
||||
R_ApplyLevelInterpolators(rendertimefrac);
|
||||
|
||||
for (i = 0; i <= splitscreen; i++)
|
||||
{
|
||||
if (!P_MobjWasRemoved(players[displayplayers[i]].mo) || players[displayplayers[i]].playerstate == PST_DEAD)
|
||||
{
|
||||
viewssnum = i;
|
||||
|
||||
if (i == 0) // Initialize for P1
|
||||
{
|
||||
viewwindowy = 0;
|
||||
viewwindowx = 0;
|
||||
|
||||
topleft = screens[0] + viewwindowy*vid.width + viewwindowx;
|
||||
objectsdrawn = 0;
|
||||
}
|
||||
|
||||
#ifdef HWRENDER
|
||||
if (rendermode == render_opengl)
|
||||
HWR_RenderPlayerView();
|
||||
else
|
||||
#endif
|
||||
if (rendermode != render_none)
|
||||
{
|
||||
if (i > 0) // Splitscreen-specific
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
if (splitscreen > 1)
|
||||
{
|
||||
viewwindowx = viewwidth;
|
||||
viewwindowy = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
viewwindowx = 0;
|
||||
viewwindowy = viewheight;
|
||||
}
|
||||
M_Memcpy(ylookup, ylookup2, viewheight*sizeof (ylookup[0]));
|
||||
break;
|
||||
case 2:
|
||||
viewwindowx = 0;
|
||||
viewwindowy = viewheight;
|
||||
M_Memcpy(ylookup, ylookup3, viewheight*sizeof (ylookup[0]));
|
||||
break;
|
||||
case 3:
|
||||
viewwindowx = viewwidth;
|
||||
viewwindowy = viewheight;
|
||||
M_Memcpy(ylookup, ylookup4, viewheight*sizeof (ylookup[0]));
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
topleft = screens[0] + viewwindowy*vid.width + viewwindowx;
|
||||
}
|
||||
|
||||
R_RenderPlayerView(&players[displayplayers[i]]);
|
||||
|
||||
if (i > 0)
|
||||
M_Memcpy(ylookup, ylookup1, viewheight*sizeof (ylookup[0]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (rendermode == render_soft)
|
||||
{
|
||||
if (!splitscreen)
|
||||
R_ApplyViewMorph();
|
||||
|
||||
for (i = 0; i <= splitscreen; i++)
|
||||
{
|
||||
V_DoPostProcessor(i, postimgparam[i]);
|
||||
}
|
||||
}
|
||||
|
||||
R_RestoreLevelInterpolators();
|
||||
|
||||
D_Renderview();
|
||||
PS_STOP_TIMING(ps_rendercalltime);
|
||||
}
|
||||
|
||||
@@ -582,8 +610,9 @@ static boolean D_Display(void)
|
||||
{
|
||||
if (rendermode == render_soft)
|
||||
{
|
||||
VID_BlitLinearScreen(screens[0], screens[1], vid.width*vid.bpp, vid.height, vid.width*vid.bpp, vid.rowbytes);
|
||||
VID_BlitLinearScreen(vid.screens[0], vid.screens[1], vid.width, vid.height, vid.width, vid.rowbytes);
|
||||
}
|
||||
|
||||
lastdraw = false;
|
||||
}
|
||||
|
||||
@@ -606,13 +635,8 @@ static boolean D_Display(void)
|
||||
// draw pause pic
|
||||
if (paused && cv_showhud.value && !demo.playback)
|
||||
{
|
||||
INT32 py;
|
||||
patch_t *patch;
|
||||
if (automapactive)
|
||||
py = 4;
|
||||
else
|
||||
py = viewwindowy + 4;
|
||||
patch = W_CachePatchName("M_PAUSE", PU_PATCH);
|
||||
INT32 py = (automapactive) ? 4 : (viewwindowy + 4);
|
||||
patch_t *patch = W_CachePatchName("M_PAUSE", PU_PATCH);
|
||||
V_DrawScaledPatch(viewwindowx + (BASEVIDWIDTH - patch->width)/2, py, V_SNAPTOTOP, patch);
|
||||
}
|
||||
|
||||
@@ -620,7 +644,7 @@ static boolean D_Display(void)
|
||||
V_DrawFadeScreen(TC_RAINBOW, (leveltime & 0x20) ? SKINCOLOR_PASTEL : SKINCOLOR_MOONSLAM);
|
||||
|
||||
// vid size change is now finished if it was on...
|
||||
vid.recalc = 0;
|
||||
vid.recalc = false;
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
I_lock_mutex(&m_menu_mutex);
|
||||
@@ -752,9 +776,11 @@ void D_SRB2Loop(void)
|
||||
precise_t enterprecise = I_GetPreciseTime();
|
||||
precise_t finishprecise = enterprecise;
|
||||
|
||||
Z_Frame_Reset();
|
||||
|
||||
// Casting the return value of a function is bad practice (apparently)
|
||||
double budget = ((R_GetFramerateCap() == 0) ? 0.0 : round((1.0 / R_GetFramerateCap()) * I_GetPrecisePrecision()));
|
||||
capbudget = (precise_t) budget;
|
||||
capbudget = (precise_t)budget;
|
||||
|
||||
boolean ranwipe = false;
|
||||
|
||||
@@ -824,12 +850,15 @@ void D_SRB2Loop(void)
|
||||
doDisplay = true;
|
||||
}
|
||||
|
||||
if (menuactive)
|
||||
if (!dedicated)
|
||||
{
|
||||
D_GamePadMenuScrollTicker();
|
||||
}
|
||||
if (menuactive)
|
||||
{
|
||||
D_GamePadMenuScrollTicker();
|
||||
}
|
||||
|
||||
D_DeviceLEDTick();
|
||||
D_DeviceLEDTick();
|
||||
}
|
||||
}
|
||||
|
||||
if (interp)
|
||||
@@ -841,7 +870,9 @@ void D_SRB2Loop(void)
|
||||
ps_interp_frac.value.p = (precise_t)((FIXED_TO_FLOAT(g_time.timefrac)) * 1000.0f);
|
||||
ps_interp_lag.value.p = (precise_t)((deltasecs) * 1000.0f);
|
||||
|
||||
if (!(paused || P_AutoPause()) && deltatics < 1.0 && !hu_stopped)
|
||||
const boolean lagging = ((deltatics >= 1.0) || hu_stopped);
|
||||
|
||||
if (!(paused || P_AutoPause()) && !lagging)
|
||||
{
|
||||
rendertimefrac = g_time.timefrac;
|
||||
}
|
||||
@@ -850,7 +881,7 @@ void D_SRB2Loop(void)
|
||||
rendertimefrac = FRACUNIT;
|
||||
}
|
||||
|
||||
if ((deltatics < 1.0) && !hu_stopped)
|
||||
if (!lagging)
|
||||
{
|
||||
rendertimefrac_unpaused = g_time.timefrac;
|
||||
}
|
||||
@@ -923,7 +954,7 @@ void D_SRB2Loop(void)
|
||||
|
||||
if ((elapsed > 0) && ((INT64)capbudget > elapsed) && !vsync_with_match_refresh)
|
||||
{
|
||||
I_SleepDuration(capbudget - (finishprecise - enterprecise));
|
||||
I_SleepDuration(capbudget - elapsed);
|
||||
}
|
||||
}
|
||||
// Capture the time once more to get the real delta time.
|
||||
@@ -1213,32 +1244,32 @@ static boolean AddIWAD(void)
|
||||
}
|
||||
|
||||
// extra graphic patches for saturn specific thingies
|
||||
boolean found_extra_kart = false;
|
||||
boolean found_extra_kart = false;
|
||||
boolean found_extra2_kart = false;
|
||||
boolean found_extra3_kart = false;
|
||||
|
||||
boolean xtra_speedo = false; // extra speedometer check
|
||||
boolean xtra_speedo_clr = false; // extra speedometer colour check
|
||||
boolean xtra_speedo3 = false; // 80x 11 extra speedometer check
|
||||
boolean xtra_speedo_clr3 = false; // 80x 11 extra speedometer colour check
|
||||
boolean achi_speedo = false; // achiiro speedometer check
|
||||
boolean achi_speedo_clr = false; // extra speedometer colour check
|
||||
boolean dial_speedo = false; // dial speedometer check
|
||||
boolean dial_speedo_clr = false; // dial speedometer colour check
|
||||
boolean kartz_speedo = false; // kartZ speedo
|
||||
boolean xtra_speedo = false; // extra speedometer check
|
||||
boolean xtra_speedo_clr = false; // extra speedometer colour check
|
||||
boolean xtra_speedo3 = false; // 80x 11 extra speedometer check
|
||||
boolean xtra_speedo_clr3 = false; // 80x 11 extra speedometer colour check
|
||||
boolean achi_speedo = false; // achiiro speedometer check
|
||||
boolean achi_speedo_clr = false; // extra speedometer colour check
|
||||
boolean dial_speedo = false; // dial speedometer check
|
||||
boolean dial_speedo_clr = false; // dial speedometer colour check
|
||||
boolean kartz_speedo = false; // kartZ speedo
|
||||
boolean kartz_speedo_smol = false; // kartZ speedo but smol
|
||||
|
||||
boolean clr_hud = false; // colour hud check
|
||||
boolean clr_hud = false; // colour hud check
|
||||
boolean driftgaugegfx_clr = false; // driftgauge colour check
|
||||
boolean big_lap = false; // bigger lap counter
|
||||
boolean big_lap_color = false; // bigger lap counter but colour
|
||||
boolean statdp = false; // stat display for extended player setup
|
||||
boolean nametaggfx = false; // Nametag stuffs
|
||||
boolean driftgaugegfx = false; // Driftgauge stuffs
|
||||
boolean multiitem_icon = false; // Extra icons for Sneakers, Banana and Jawz
|
||||
boolean joystickicon = false; // Extra icons for the joystick input display
|
||||
boolean minidoticon = false; // Dot graphic for minimap player angle display
|
||||
boolean minilighticon = false; // mkwii-style minimap headlight
|
||||
boolean big_lap = false; // bigger lap counter
|
||||
boolean big_lap_color = false; // bigger lap counter but colour
|
||||
boolean statdp = false; // stat display for extended player setup
|
||||
boolean nametaggfx = false; // Nametag stuffs
|
||||
boolean driftgaugegfx = false; // Driftgauge stuffs
|
||||
boolean multiitem_icon = false; // Extra icons for Sneakers, Banana and Jawz
|
||||
boolean joystickicon = false; // Extra icons for the joystick input display
|
||||
boolean minidoticon = false; // Dot graphic for minimap player angle display
|
||||
boolean minilighticon = false; // mkwii-style minimap headlight
|
||||
//
|
||||
|
||||
static void IdentifyVersion(void)
|
||||
@@ -1811,7 +1842,7 @@ void D_SRB2Main(void)
|
||||
{
|
||||
name = lumpinfo->name;
|
||||
|
||||
if (name[0] == 'M' && name[1] == 'A' && name[2] == 'P') // Ignore the headers
|
||||
if (memcmp(name, "MAP", 3) == 0) // Ignore the headers
|
||||
{
|
||||
INT16 num;
|
||||
if (name[5] != '\0')
|
||||
@@ -1841,7 +1872,7 @@ void D_SRB2Main(void)
|
||||
{
|
||||
name = lumpinfo->name;
|
||||
|
||||
if (name[0] == 'M' && name[1] == 'A' && name[2] == 'P') // Ignore the headers
|
||||
if (memcmp(name, "MAP", 3) == 0) // Ignore the headers
|
||||
{
|
||||
INT16 num;
|
||||
if (name[5] != '\0')
|
||||
@@ -1994,6 +2025,8 @@ void D_SRB2Main(void)
|
||||
|
||||
S_InitMusicDefs();
|
||||
|
||||
M_InitEmotes();
|
||||
|
||||
CONS_Printf("ST_Init(): Init status bar.\n");
|
||||
ST_Init();
|
||||
|
||||
|
||||
@@ -14,6 +14,10 @@
|
||||
#ifndef __D_MAIN__
|
||||
#define __D_MAIN__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "d_event.h"
|
||||
#include "w_wad.h" // for MAX_WADFILES
|
||||
|
||||
@@ -90,4 +94,8 @@ const char *D_Home(void);
|
||||
//
|
||||
void D_StartTitle(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif //__D_MAIN__
|
||||
+8
-2
@@ -18,6 +18,10 @@
|
||||
#ifndef __D_NET__
|
||||
#define __D_NET__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Max computers in a game
|
||||
// 127 is probably as high as this can go, because
|
||||
// SINT8 is used for nodes sometimes >:(
|
||||
@@ -43,8 +47,6 @@ extern SINT8 nodetoplayer4[MAXNETNODES]; // Say the numplayer for this node if a
|
||||
extern UINT8 playerpernode[MAXNETNODES]; // Used specially for splitscreen
|
||||
extern boolean nodeingame[MAXNETNODES]; // Set false as nodes leave game
|
||||
|
||||
extern boolean serverrunning;
|
||||
|
||||
void Net_AckTicker(void);
|
||||
|
||||
// If reliable return true if packet sent, 0 else
|
||||
@@ -65,4 +67,8 @@ void Net_SendAcks(INT32 node);
|
||||
void Net_WaitAllAckReceived(UINT32 timeout);
|
||||
const char *Net_GetPacketName(UINT8 packettype);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+17
-12
@@ -21,6 +21,7 @@
|
||||
#include "i_system.h"
|
||||
#include "g_game.h"
|
||||
#include "hu_stuff.h"
|
||||
#include "m_emotes.h"
|
||||
#include "g_input.h"
|
||||
#include "m_menu.h"
|
||||
#include "r_local.h"
|
||||
@@ -204,11 +205,6 @@ static void Command_Archivetest_f(void);
|
||||
// CLIENT VARIABLES
|
||||
// =========================================================================
|
||||
|
||||
void SendWeaponPref(void);
|
||||
void SendWeaponPref2(void);
|
||||
void SendWeaponPref3(void);
|
||||
void SendWeaponPref4(void);
|
||||
|
||||
static CV_PossibleValue_t usemouse_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "Force"}, {0, NULL}};
|
||||
|
||||
static CV_PossibleValue_t autobalance_cons_t[] = {{0, "MIN"}, {4, "MAX"}, {0, NULL}};
|
||||
@@ -216,11 +212,8 @@ static CV_PossibleValue_t teamscramble_cons_t[] = {{0, "Off"}, {1, "Random"}, {2
|
||||
|
||||
static CV_PossibleValue_t startingliveslimit_cons_t[] = {{1, "MIN"}, {99, "MAX"}, {0, NULL}};
|
||||
static CV_PossibleValue_t sleeping_cons_t[] = {{0, "MIN"}, {1000/TICRATE, "MAX"}, {0, NULL}};
|
||||
static CV_PossibleValue_t competitionboxes_cons_t[] = {{0, "Normal"}, {1, "Random"}, {2, "Teleports"},
|
||||
{3, "None"}, {0, NULL}};
|
||||
|
||||
static CV_PossibleValue_t matchboxes_cons_t[] = {{0, "Normal"}, {1, "Random"}, {2, "Non-Random"},
|
||||
{3, "None"}, {0, NULL}};
|
||||
static CV_PossibleValue_t competitionboxes_cons_t[] = {{0, "Normal"}, {1, "Random"}, {2, "Teleports"}, {3, "None"}, {0, NULL}};
|
||||
static CV_PossibleValue_t matchboxes_cons_t[] = {{0, "Normal"}, {1, "Random"}, {2, "Non-Random"}, {3, "None"}, {0, NULL}};
|
||||
|
||||
//static CV_PossibleValue_t chances_cons_t[] = {{0, "MIN"}, {9, "MAX"}, {0, NULL}};
|
||||
static CV_PossibleValue_t match_scoring_cons_t[] = {{0, "Normal"}, {1, "Classic"}, {0, NULL}};
|
||||
@@ -903,6 +896,7 @@ void D_RegisterClientCommands(void)
|
||||
CV_RegisterVar(&cv_netticbuffer);
|
||||
CV_RegisterVar(&cv_mindelay);
|
||||
CV_RegisterVar(&cv_gentlemens);
|
||||
CV_RegisterVar(&cv_serverinfoscreen);
|
||||
|
||||
#ifdef NETGAME_DEVMODE
|
||||
CV_RegisterVar(&cv_fishcake);
|
||||
@@ -919,6 +913,8 @@ void D_RegisterClientCommands(void)
|
||||
|
||||
CV_RegisterVar(&cv_keyboardlayout);
|
||||
|
||||
CV_RegisterVar(&cv_emotes);
|
||||
|
||||
// time attack ghost options are also saved to config
|
||||
CV_RegisterVar(&cv_ghost_besttime);
|
||||
CV_RegisterVar(&cv_ghost_bestlap);
|
||||
@@ -1032,6 +1028,8 @@ void D_RegisterClientCommands(void)
|
||||
CV_RegisterVar(&cv_scr_width);
|
||||
CV_RegisterVar(&cv_scr_height);
|
||||
|
||||
CV_RegisterVar(&cv_parallelsoftware);
|
||||
|
||||
CV_RegisterVar(&cv_soundtest);
|
||||
|
||||
CV_RegisterVar(&cv_perfstats);
|
||||
@@ -1053,7 +1051,9 @@ void D_RegisterClientCommands(void)
|
||||
CV_RegisterVar(&cv_verticallook[i]);
|
||||
}
|
||||
|
||||
CV_RegisterVar(&cv_resyncdemo);
|
||||
CV_RegisterVar(&cv_demodateformat);
|
||||
|
||||
CV_RegisterVar(&cv_showspecstuff);
|
||||
|
||||
// ingame object placing
|
||||
@@ -2775,7 +2775,7 @@ static void Command_Map_f(void)
|
||||
// G_TOLFlag handles both multiplayer gametype and ignores it for !multiplayer
|
||||
else
|
||||
{
|
||||
if (!mapheaderinfo[newmapnum-1] || mapheaderinfo[newmapnum-1] == NULL)
|
||||
if (!mapheaderinfo[newmapnum-1])
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Invalid mapheaderinfo for Course %s (%s)\n"), realmapname, G_BuildMapName(newmapnum));
|
||||
Z_Free(realmapname);
|
||||
@@ -3029,9 +3029,14 @@ static void Command_ReplayMarker(void)
|
||||
adjustedleveltime = 0;
|
||||
|
||||
char *title = G_BuildMapTitle(gamemap);
|
||||
snprintf(demo.titlename, 64, "%s [%i:%02d/%.5s]", title, G_TicsToMinutes(adjustedleveltime, false), G_TicsToSeconds(adjustedleveltime), modeattacking ? "Record Attack" : connectedservername);
|
||||
|
||||
if (title)
|
||||
{
|
||||
snprintf(demo.titlename, 64, "%s [%i:%02d/%.5s]", title, G_TicsToMinutes(adjustedleveltime, false), G_TicsToSeconds(adjustedleveltime), modeattacking ? "Record Attack" : connectedservername);
|
||||
Z_Free(title);
|
||||
}
|
||||
else
|
||||
snprintf(demo.titlename, 64, "[%i:%02d/%.5s]", G_TicsToMinutes(adjustedleveltime, false), G_TicsToSeconds(adjustedleveltime), modeattacking ? "Record Attack" : connectedservername);
|
||||
|
||||
CONS_Printf("Replay will be saved!\n");
|
||||
}
|
||||
|
||||
@@ -15,8 +15,17 @@
|
||||
#ifndef __D_NETCMD__
|
||||
#define __D_NETCMD__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "command.h"
|
||||
|
||||
void SendWeaponPref(void);
|
||||
void SendWeaponPref2(void);
|
||||
void SendWeaponPref3(void);
|
||||
void SendWeaponPref4(void);
|
||||
|
||||
// console vars
|
||||
extern consvar_t cv_playername;
|
||||
extern consvar_t cv_playercolor;
|
||||
@@ -318,4 +327,8 @@ void D_SetPassword(const char *pw);
|
||||
// used for the player setup menu
|
||||
UINT8 CanChangeSkin(INT32 playernum);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -111,7 +111,9 @@ static fileused_t transferFiles[UINT8_MAX + 1];
|
||||
// Receiver structure
|
||||
INT32 fileneedednum; // Number of files needed to join the server
|
||||
fileneeded_t fileneeded[MAX_WADFILES]; // List of needed files
|
||||
#ifdef HAVE_THREADS
|
||||
static I_mutex downloadmutex;
|
||||
#endif
|
||||
char downloaddir[512] = "DOWNLOAD";
|
||||
|
||||
file_download_t filedownload;
|
||||
@@ -1351,14 +1353,18 @@ void CURLAbortFile(void)
|
||||
{
|
||||
filedownload.http_running = false;
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
// lock and unlock to wait for the download thread to exit
|
||||
I_lock_mutex(&downloadmutex);
|
||||
I_unlock_mutex(downloadmutex);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CURLGetFile(void)
|
||||
{
|
||||
#ifdef HAVE_THREADS
|
||||
I_lock_mutex(&downloadmutex);
|
||||
#endif
|
||||
CURLMcode mc; /* return code used by curl_multi_wait() */
|
||||
CURLcode easyres; /* Return from easy interface */
|
||||
CURLMsg *m; /* for picking up messages with the transfer status */
|
||||
@@ -1453,7 +1459,9 @@ void CURLGetFile(void)
|
||||
}
|
||||
|
||||
filedownload.http_running = false;
|
||||
#ifdef HAVE_THREADS
|
||||
I_unlock_mutex(downloadmutex);
|
||||
#endif
|
||||
}
|
||||
|
||||
HTTP_login *
|
||||
|
||||
@@ -13,6 +13,10 @@
|
||||
#ifndef __D_NETFIL__
|
||||
#define __D_NETFIL__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "d_clisrv.h"
|
||||
#include "w_wad.h"
|
||||
|
||||
@@ -125,4 +129,8 @@ HTTP_login * CURLGetLogin (const char *url, HTTP_login ***return_prev_next);
|
||||
size_t curlwrite_data(void *ptr, size_t size, size_t nmemb, FILE *stream);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // __D_NETFIL__
|
||||
+10
-4
@@ -388,7 +388,7 @@ static void DRPC_GotServerIP(UINT32 address)
|
||||
--------------------------------------------------*/
|
||||
static const char *DRPC_GetServerIP(void)
|
||||
{
|
||||
const char *address;
|
||||
const char *address;
|
||||
|
||||
// If you're connected
|
||||
if (I_GetNodeAddress && (address = I_GetNodeAddress(servernode)) != NULL)
|
||||
@@ -489,7 +489,7 @@ void DRPC_UpdatePresence(void)
|
||||
{
|
||||
#endif
|
||||
discordPresence.state = "Private";
|
||||
#ifdef MASTERSERVER
|
||||
#ifdef MASTERSERVER
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -571,9 +571,15 @@ void DRPC_UpdatePresence(void)
|
||||
{
|
||||
// Map name on tool tip
|
||||
char *title = G_BuildMapTitle(gamemap);
|
||||
snprintf(mapname, 48, "Map: %s", title);
|
||||
if (title)
|
||||
{
|
||||
snprintf(mapname, 48, "Map: %s", title);
|
||||
Z_Free(title);
|
||||
}
|
||||
else
|
||||
snprintf(mapname, 48, "Map: UNKNOWN");
|
||||
|
||||
discordPresence.largeImageText = mapname;
|
||||
Z_Free(title);
|
||||
}
|
||||
|
||||
if (gamestate == GS_LEVEL && Playing())
|
||||
|
||||
@@ -58,6 +58,9 @@
|
||||
// warning C4152: nonstandard extension, function/data pointer conversion in expression
|
||||
// warning C4213: nonstandard extension used : cast on l-value
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "doomtype.h"
|
||||
|
||||
@@ -524,12 +527,15 @@ UINT32 quickncasehash (const char *p, size_t n)
|
||||
return x;
|
||||
}
|
||||
|
||||
#ifndef __cplusplus
|
||||
#ifndef min // Double-Check with WATTCP-32's cdefs.h
|
||||
#define min(x, y) (((x) < (y)) ? (x) : (y))
|
||||
#endif
|
||||
#ifndef max // Double-Check with WATTCP-32's cdefs.h
|
||||
#define max(x, y) (((x) > (y)) ? (x) : (y))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef CLAMP
|
||||
#define CLAMP(x, y, z) ((x) < (y) ? (y) : ((x) > (z) ? (z) : (x)))
|
||||
#endif
|
||||
@@ -560,6 +566,14 @@ UINT32 quickncasehash (const char *p, size_t n)
|
||||
#define UNLIKELY(x) (x)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if defined(__GNUC__) || defined(__clang__) || defined(_MSC_VER)
|
||||
#define restrict __restrict
|
||||
#else
|
||||
#define restrict
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// An assert-type mechanism.
|
||||
#ifdef PARANOIA
|
||||
#define I_Assert(e) ((e) ? (void)0 : I_Error("assert failed: %s, file %s, line %d", #e, __FILE__, __LINE__))
|
||||
@@ -657,4 +671,8 @@ extern const char *compdate, *comptime, *comprevision, *compbranch;
|
||||
#undef UPDATE_ALERT
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // __DOOMDEF__
|
||||
+1
-1
@@ -125,7 +125,7 @@ extern boolean lastdraw;
|
||||
extern INT32 postimgparam[MAXSPLITSCREENPLAYERS];
|
||||
|
||||
extern INT32 viewwindowx, viewwindowy;
|
||||
extern INT32 viewwidth, scaledviewwidth;
|
||||
extern INT32 viewwidth;
|
||||
|
||||
extern boolean gamedataloaded;
|
||||
|
||||
|
||||
+23
-16
@@ -17,6 +17,10 @@
|
||||
#ifndef __DOOMTYPE__
|
||||
#define __DOOMTYPE__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined (_WIN32)
|
||||
//#define WIN32_LEAN_AND_MEAN
|
||||
#define RPC_NO_WINDOWS_H
|
||||
@@ -100,8 +104,10 @@ typedef long ssize_t;
|
||||
#define strnicmp(x,y,n) strncasecmp(x,y,n)
|
||||
#endif
|
||||
|
||||
#ifndef __cplusplus
|
||||
char *strcasestr(const char *in, const char *what);
|
||||
#define stristr strcasestr
|
||||
#endif
|
||||
|
||||
#if defined (macintosh) //|| defined (__APPLE__) //skip all boolean/Boolean crap
|
||||
#define true 1
|
||||
@@ -156,22 +162,19 @@ size_t strlcpy(char *dst, const char *src, size_t siz);
|
||||
|
||||
/* Boolean type definition */
|
||||
|
||||
// \note __BYTEBOOL__ used to be set above if "macintosh" was defined,
|
||||
// if macintosh's version of boolean type isn't needed anymore, then isn't this macro pointless now?
|
||||
#ifndef __BYTEBOOL__
|
||||
#define __BYTEBOOL__
|
||||
|
||||
//faB: clean that up !!
|
||||
#if defined( _MSC_VER) && (_MSC_VER >= 1800) // MSVC 2013 and forward
|
||||
#include "stdbool.h"
|
||||
#elif defined (_WIN32)
|
||||
#define false FALSE // use windows types
|
||||
#define true TRUE
|
||||
#define boolean BOOL
|
||||
#else
|
||||
typedef enum {false, true} boolean;
|
||||
#endif
|
||||
#endif // __BYTEBOOL__
|
||||
#ifndef _WIN32
|
||||
#include <stdbool.h>
|
||||
// dont use stdbools _BOOL type
|
||||
// its smaller (1 byte) than the old interger bool (4 bytes)
|
||||
// which results in packed struct sizes being mismatched between vanilla and this
|
||||
// however we gotta still include stdbool cause since c23 true and false are keywords
|
||||
// which we cant use as enumeration constants
|
||||
typedef int32_t boolean;
|
||||
#else
|
||||
#define false FALSE
|
||||
#define true TRUE
|
||||
#define boolean BOOL
|
||||
#endif
|
||||
|
||||
/* 7.18.2.1 Limits of exact-width integer types */
|
||||
#ifndef INT8_MIN
|
||||
@@ -385,4 +388,8 @@ unset_bit_array (bitarray_t * const array, const int value)
|
||||
|
||||
typedef UINT64 precise_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif //__DOOMTYPE__
|
||||
+3
-2
@@ -531,8 +531,8 @@ static const char *credits[] = {
|
||||
"\"Xyzzy\"",
|
||||
"\"Chearii\"",
|
||||
" ",
|
||||
"\"Sunflower\" aka \"AnimeSonic\"",
|
||||
"\"Yuz\" aka \"Yuzler\"",
|
||||
"\"Sunflower\"",
|
||||
"\"Yuz\"",
|
||||
"\"Democrab\"",
|
||||
"\"EXpand\"",
|
||||
"\"Nexit\"",
|
||||
@@ -543,6 +543,7 @@ static const char *credits[] = {
|
||||
"\"Achii\"",
|
||||
"\"Anonimus\"",
|
||||
"\"scizor300\"",
|
||||
"\"Lugent\"",
|
||||
"",
|
||||
"\1Special Thanks",
|
||||
"SEGA",
|
||||
|
||||
+3
-3
@@ -313,7 +313,7 @@ void F_WipeStartScreen(void)
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
wipe_scr_start = screens[3];
|
||||
wipe_scr_start = vid.screens[3];
|
||||
I_ReadScreen(wipe_scr_start);
|
||||
#endif
|
||||
}
|
||||
@@ -330,7 +330,7 @@ void F_WipeEndScreen(void)
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
wipe_scr_end = screens[4];
|
||||
wipe_scr_end = vid.screens[4];
|
||||
I_ReadScreen(wipe_scr_end);
|
||||
V_DrawBlock(0, 0, 0, vid.width, vid.height, wipe_scr_start);
|
||||
#endif
|
||||
@@ -353,7 +353,7 @@ void F_RunWipe(UINT8 wipetype, boolean drawMenu)
|
||||
|
||||
// Init the wipe
|
||||
WipeInAction = true;
|
||||
wipe_scr = screens[0];
|
||||
wipe_scr = vid.screens[0];
|
||||
|
||||
// lastwipetic should either be 0 or the tic we last wiped
|
||||
// on for fade-to-black
|
||||
|
||||
@@ -4,6 +4,10 @@
|
||||
#ifndef __FILESRCH_H__
|
||||
#define __FILESRCH_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "d_netfil.h"
|
||||
#include "m_menu.h" // MAXSTRINGLENGTH
|
||||
@@ -96,4 +100,8 @@ void closefilemenu(boolean validsize);
|
||||
void searchfilemenu(char *tempname);
|
||||
boolean preparefilemenu(boolean samedepth, boolean replayhut);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // __FILESRCH_H__
|
||||
+4070
File diff suppressed because it is too large.
Load diff
+191
@@ -0,0 +1,191 @@
|
||||
// SONIC ROBO BLAST 2 KART
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
||||
// Copyright (C) 1999-2020 by Sonic Team Junior.
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \file g_demo.h
|
||||
/// \brief Demo recording and playback
|
||||
|
||||
#ifndef __G_DEMO__
|
||||
#define __G_DEMO__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "doomstat.h"
|
||||
#include "d_event.h"
|
||||
#include "p_saveg.h"
|
||||
#include "m_textinput.h"
|
||||
|
||||
extern savebuffer_t demobuf;
|
||||
|
||||
// demoplaying back and demo recording
|
||||
extern consvar_t cv_recordmultiplayerdemos, cv_netdemosyncquality, cv_maxdemosize, cv_demochangemap;
|
||||
extern consvar_t cv_demodateformat;
|
||||
extern consvar_t cv_resyncdemo;
|
||||
|
||||
// Publicly-accessible demo vars
|
||||
struct demovars_s {
|
||||
char titlename[65];
|
||||
textinput_t titlenameinput;
|
||||
boolean recording, playback, timing;
|
||||
UINT16 version; // Current file format of the demo being played
|
||||
boolean title; // Title Screen demo can be cancelled by any key
|
||||
boolean rewinding; // Rewind in progress
|
||||
|
||||
boolean loadfiles, ignorefiles; // Demo file loading options
|
||||
boolean fromtitle; // SRB2Kart: Don't stop the music
|
||||
boolean inreplayhut; // Go back to replayhut after demos
|
||||
boolean quitafterplaying; // quit after playing a demo from cmdline
|
||||
boolean deferstart; // don't start playing demo right away
|
||||
|
||||
tic_t savebutton; // Used to determine when the local player can choose to save the replay while the race is still going
|
||||
enum {
|
||||
DSM_NOTSAVING,
|
||||
DSM_WILLAUTOSAVE,
|
||||
DSM_TITLEENTRY,
|
||||
DSM_WILLSAVE,
|
||||
DSM_SAVED
|
||||
} savemode;
|
||||
};
|
||||
|
||||
extern struct demovars_s demo;
|
||||
|
||||
typedef enum {
|
||||
MD_NOTLOADED,
|
||||
MD_LOADED,
|
||||
MD_SUBDIR,
|
||||
MD_OUTDATED,
|
||||
MD_INVALID
|
||||
} menudemotype_e;
|
||||
|
||||
typedef struct menudemo_s {
|
||||
char filepath[256];
|
||||
menudemotype_e type;
|
||||
|
||||
char title[65]; // Null-terminated for string prints
|
||||
char date[11]; // date when replay was recorded
|
||||
char version[12]; // combined version and subversion
|
||||
UINT16 map;
|
||||
UINT8 addonstatus; // What do we need to do addon-wise to play this demo?
|
||||
UINT8 gametype;
|
||||
UINT8 kartspeed; // Add OR DF_ENCORE for encore mode, idk
|
||||
UINT8 numlaps;
|
||||
|
||||
struct {
|
||||
UINT8 ranking;
|
||||
char name[17];
|
||||
UINT8 skin, color;
|
||||
UINT32 timeorscore;
|
||||
} standings[MAXPLAYERS];
|
||||
} menudemo_t;
|
||||
|
||||
extern mobj_t *metalplayback;
|
||||
|
||||
// Only called by startup code.
|
||||
void G_RecordDemo(const char *name);
|
||||
void G_RecordMetal(void);
|
||||
void G_BeginRecording(void);
|
||||
void G_BeginMetal(void);
|
||||
|
||||
// Only called by shutdown code.
|
||||
void G_WriteStanding(UINT8 ranking, char *name, INT32 skinnum, UINT8 color, UINT32 val);
|
||||
void G_SetDemoTime(UINT32 ptime, UINT32 plap);
|
||||
UINT8 G_CmpDemoTime(char *oldname, char *newname);
|
||||
|
||||
void G_LoadDemoInfo(menudemo_t *pdemo);
|
||||
void G_LoadDemoTitle(menudemo_t *pdemo); // For use in replay search feature
|
||||
void G_DeferedPlayDemo(const char *demo);
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GHC_NORMAL = 0,
|
||||
GHC_SUPER,
|
||||
GHC_FIREFLOWER,
|
||||
GHC_INVINCIBLE
|
||||
} ghostcolor_t;
|
||||
|
||||
extern UINT8 demo_extradata[MAXPLAYERS];
|
||||
extern UINT8 demo_writerng;
|
||||
#define DXD_RESPAWN 0x01 // "respawn" command in console
|
||||
#define DXD_SKIN 0x02 // skin changed
|
||||
#define DXD_NAME 0x04 // name changed
|
||||
#define DXD_COLOR 0x08 // color changed
|
||||
#define DXD_PLAYSTATE 0x10 // state changed between playing, spectating, or not in-game
|
||||
|
||||
#define DXD_PST_PLAYING 0x01
|
||||
#define DXD_PST_SPECTATING 0x02
|
||||
#define DXD_PST_LEFT 0x03
|
||||
|
||||
// Record/playback tics
|
||||
void G_ReadDemoExtraData(void);
|
||||
void G_WriteDemoExtraData(void);
|
||||
void G_ReadDemoTiccmd(ticcmd_t *cmd, INT32 playernum);
|
||||
void G_WriteDemoTiccmd(ticcmd_t *cmd, INT32 playernum);
|
||||
void G_GhostAddThok(INT32 playernum);
|
||||
void G_GhostAddSpin(INT32 playernum);
|
||||
void G_GhostAddRev(INT32 playernum);
|
||||
void G_GhostAddColor(INT32 playernum, ghostcolor_t color);
|
||||
void G_GhostAddFlip(INT32 playernum);
|
||||
void G_GhostAddScale(INT32 playernum, fixed_t scale);
|
||||
void G_GhostAddHit(INT32 playernum, mobj_t *victim);
|
||||
void G_WriteAllGhostTics(void);
|
||||
void G_WriteGhostTic(mobj_t *ghost, INT32 playernum);
|
||||
void G_ConsAllGhostTics(void);
|
||||
void G_ConsGhostTic(INT32 playernum);
|
||||
void G_GhostTicker(void);
|
||||
|
||||
void G_InitDemoRewind(void);
|
||||
void G_StoreRewindInfo(void);
|
||||
void G_PreviewRewind(tic_t previewtime);
|
||||
void G_ConfirmRewind(tic_t rewindtime);
|
||||
|
||||
void G_ReadMetalTic(mobj_t *metal);
|
||||
void G_WriteMetalTic(mobj_t *metal);
|
||||
void G_SaveMetal(UINT8 **buffer);
|
||||
void G_LoadMetal(UINT8 **buffer);
|
||||
|
||||
// Your naming conventions are stupid and useless.
|
||||
// There is no conflict here.
|
||||
typedef struct demoghost {
|
||||
UINT8 checksum[16];
|
||||
UINT8 *buffer, *p, color;
|
||||
UINT16 version;
|
||||
mobj_t oldmo, *mo;
|
||||
struct demoghost *next;
|
||||
} demoghost;
|
||||
extern demoghost *ghosts;
|
||||
|
||||
// G_CheckDemoExtraFiles: checks if our loaded WAD list matches the demo's.
|
||||
#define DFILE_ERROR_NOTLOADED 0x01 // Files are not loaded, but can be without a restart.
|
||||
#define DFILE_ERROR_OUTOFORDER 0x02 // Files are loaded, but out of order.
|
||||
#define DFILE_ERROR_INCOMPLETEOUTOFORDER 0x03 // Some files are loaded out of order, but others are not.
|
||||
#define DFILE_ERROR_CANNOTLOAD 0x04 // Files are missing and cannot be loaded.
|
||||
#define DFILE_ERROR_EXTRAFILES 0x05 // Extra files outside of the replay's file list are loaded.
|
||||
|
||||
void G_ResetDemoRecording(void);
|
||||
void G_DoPlayDemo(char *defdemoname);
|
||||
void G_TimeDemo(const char *name);
|
||||
void G_AddGhost(char *defdemoname);
|
||||
void G_UpdateStaffGhostName(lumpnum_t l);
|
||||
void G_DoPlayMetal(void);
|
||||
void G_DoneLevelLoad(void);
|
||||
void G_StopMetalDemo(void);
|
||||
ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(void);
|
||||
void G_StopDemo(void);
|
||||
boolean G_CheckDemoStatus(void);
|
||||
void G_SaveDemo(void);
|
||||
boolean G_DemoTitleResponder(event_t *ev);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // __G_DEMO__
|
||||
+7
-4003
File diff suppressed because it is too large.
Load diff
+9
-164
@@ -14,9 +14,14 @@
|
||||
#ifndef __G_GAME__
|
||||
#define __G_GAME__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "doomstat.h"
|
||||
#include "d_event.h"
|
||||
#include "g_demo.h"
|
||||
#include "p_saveg.h"
|
||||
#include "m_textinput.h"
|
||||
|
||||
@@ -34,75 +39,6 @@ extern INT32 player_name_changes[MAXPLAYERS];
|
||||
extern player_t players[MAXPLAYERS];
|
||||
extern boolean playeringame[MAXPLAYERS];
|
||||
|
||||
extern savebuffer_t demobuf;
|
||||
|
||||
// ======================================
|
||||
// DEMO playback/recording related stuff.
|
||||
// ======================================
|
||||
|
||||
// demoplaying back and demo recording
|
||||
extern consvar_t cv_recordmultiplayerdemos, cv_netdemosyncquality, cv_maxdemosize, cv_demochangemap;
|
||||
extern consvar_t cv_demodateformat;
|
||||
|
||||
// Publicly-accessible demo vars
|
||||
struct demovars_s {
|
||||
char titlename[65];
|
||||
textinput_t titlenameinput;
|
||||
boolean recording, playback, timing;
|
||||
UINT16 version; // Current file format of the demo being played
|
||||
boolean title; // Title Screen demo can be cancelled by any key
|
||||
boolean rewinding; // Rewind in progress
|
||||
|
||||
boolean loadfiles, ignorefiles; // Demo file loading options
|
||||
boolean fromtitle; // SRB2Kart: Don't stop the music
|
||||
boolean inreplayhut; // Go back to replayhut after demos
|
||||
boolean quitafterplaying; // quit after playing a demo from cmdline
|
||||
boolean deferstart; // don't start playing demo right away
|
||||
|
||||
tic_t savebutton; // Used to determine when the local player can choose to save the replay while the race is still going
|
||||
enum {
|
||||
DSM_NOTSAVING,
|
||||
DSM_WILLAUTOSAVE,
|
||||
DSM_TITLEENTRY,
|
||||
DSM_WILLSAVE,
|
||||
DSM_SAVED
|
||||
} savemode;
|
||||
};
|
||||
|
||||
extern struct demovars_s demo;
|
||||
|
||||
typedef enum {
|
||||
MD_NOTLOADED,
|
||||
MD_LOADED,
|
||||
MD_SUBDIR,
|
||||
MD_OUTDATED,
|
||||
MD_INVALID
|
||||
} menudemotype_e;
|
||||
|
||||
typedef struct menudemo_s {
|
||||
char filepath[256];
|
||||
menudemotype_e type;
|
||||
|
||||
char title[65]; // Null-terminated for string prints
|
||||
char date[11]; // date when replay was recorded
|
||||
char version[12]; // combined version and subversion
|
||||
UINT16 map;
|
||||
UINT8 addonstatus; // What do we need to do addon-wise to play this demo?
|
||||
UINT8 gametype;
|
||||
UINT8 kartspeed; // Add OR DF_ENCORE for encore mode, idk
|
||||
UINT8 numlaps;
|
||||
|
||||
struct {
|
||||
UINT8 ranking;
|
||||
char name[17];
|
||||
UINT8 skin, color;
|
||||
UINT32 timeorscore;
|
||||
} standings[MAXPLAYERS];
|
||||
} menudemo_t;
|
||||
|
||||
|
||||
extern mobj_t *metalplayback;
|
||||
|
||||
// gametic at level start
|
||||
extern tic_t levelstarttic;
|
||||
|
||||
@@ -286,10 +222,6 @@ void G_SpawnPlayer(INT32 playernum, boolean starpost);
|
||||
void G_DeferedInitNew(boolean pencoremode, const char *mapname, INT32 pickedchar,
|
||||
UINT8 ssplayers, boolean FLS);
|
||||
|
||||
void G_LoadDemoInfo(menudemo_t *pdemo);
|
||||
void G_LoadDemoTitle(menudemo_t *pdemo); // For use in replay search feature
|
||||
void G_DeferedPlayDemo(const char *demo);
|
||||
|
||||
// Can be called by the startup code or M_Responder, calls P_SetupLevel.
|
||||
void G_LoadGame(UINT32 slot, INT16 mapoverride);
|
||||
|
||||
@@ -297,97 +229,6 @@ void G_SaveGameData(boolean force);
|
||||
|
||||
void G_SaveGame(UINT32 slot);
|
||||
|
||||
// Only called by startup code.
|
||||
void G_RecordDemo(const char *name);
|
||||
void G_RecordMetal(void);
|
||||
void G_BeginRecording(void);
|
||||
void G_BeginMetal(void);
|
||||
|
||||
// Only called by shutdown code.
|
||||
void G_WriteStanding(UINT8 ranking, char *name, INT32 skinnum, UINT8 color, UINT32 val);
|
||||
void G_SetDemoTime(UINT32 ptime, UINT32 plap);
|
||||
UINT8 G_CmpDemoTime(char *oldname, char *newname);
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GHC_NORMAL = 0,
|
||||
GHC_SUPER,
|
||||
GHC_FIREFLOWER,
|
||||
GHC_INVINCIBLE
|
||||
} ghostcolor_t;
|
||||
|
||||
extern UINT8 demo_extradata[MAXPLAYERS];
|
||||
extern UINT8 demo_writerng;
|
||||
#define DXD_RESPAWN 0x01 // "respawn" command in console
|
||||
#define DXD_SKIN 0x02 // skin changed
|
||||
#define DXD_NAME 0x04 // name changed
|
||||
#define DXD_COLOR 0x08 // color changed
|
||||
#define DXD_PLAYSTATE 0x10 // state changed between playing, spectating, or not in-game
|
||||
|
||||
#define DXD_PST_PLAYING 0x01
|
||||
#define DXD_PST_SPECTATING 0x02
|
||||
#define DXD_PST_LEFT 0x03
|
||||
|
||||
// Record/playback tics
|
||||
void G_ReadDemoExtraData(void);
|
||||
void G_WriteDemoExtraData(void);
|
||||
void G_ReadDemoTiccmd(ticcmd_t *cmd, INT32 playernum);
|
||||
void G_WriteDemoTiccmd(ticcmd_t *cmd, INT32 playernum);
|
||||
void G_GhostAddThok(INT32 playernum);
|
||||
void G_GhostAddSpin(INT32 playernum);
|
||||
void G_GhostAddRev(INT32 playernum);
|
||||
void G_GhostAddColor(INT32 playernum, ghostcolor_t color);
|
||||
void G_GhostAddFlip(INT32 playernum);
|
||||
void G_GhostAddScale(INT32 playernum, fixed_t scale);
|
||||
void G_GhostAddHit(INT32 playernum, mobj_t *victim);
|
||||
void G_WriteAllGhostTics(void);
|
||||
void G_WriteGhostTic(mobj_t *ghost, INT32 playernum);
|
||||
void G_ConsAllGhostTics(void);
|
||||
void G_ConsGhostTic(INT32 playernum);
|
||||
void G_GhostTicker(void);
|
||||
|
||||
void G_InitDemoRewind(void);
|
||||
void G_StoreRewindInfo(void);
|
||||
void G_PreviewRewind(tic_t previewtime);
|
||||
void G_ConfirmRewind(tic_t rewindtime);
|
||||
|
||||
void G_ReadMetalTic(mobj_t *metal);
|
||||
void G_WriteMetalTic(mobj_t *metal);
|
||||
void G_SaveMetal(UINT8 **buffer);
|
||||
void G_LoadMetal(UINT8 **buffer);
|
||||
|
||||
// Your naming conventions are stupid and useless.
|
||||
// There is no conflict here.
|
||||
typedef struct demoghost {
|
||||
UINT8 checksum[16];
|
||||
UINT8 *buffer, *p, color;
|
||||
UINT16 version;
|
||||
mobj_t oldmo, *mo;
|
||||
struct demoghost *next;
|
||||
} demoghost;
|
||||
extern demoghost *ghosts;
|
||||
|
||||
// G_CheckDemoExtraFiles: checks if our loaded WAD list matches the demo's.
|
||||
#define DFILE_ERROR_NOTLOADED 0x01 // Files are not loaded, but can be without a restart.
|
||||
#define DFILE_ERROR_OUTOFORDER 0x02 // Files are loaded, but out of order.
|
||||
#define DFILE_ERROR_INCOMPLETEOUTOFORDER 0x03 // Some files are loaded out of order, but others are not.
|
||||
#define DFILE_ERROR_CANNOTLOAD 0x04 // Files are missing and cannot be loaded.
|
||||
#define DFILE_ERROR_EXTRAFILES 0x05 // Extra files outside of the replay's file list are loaded.
|
||||
|
||||
void G_ResetDemoRecording(void);
|
||||
void G_DoPlayDemo(char *defdemoname);
|
||||
void G_TimeDemo(const char *name);
|
||||
void G_AddGhost(char *defdemoname);
|
||||
void G_UpdateStaffGhostName(lumpnum_t l);
|
||||
void G_DoPlayMetal(void);
|
||||
void G_DoneLevelLoad(void);
|
||||
void G_StopMetalDemo(void);
|
||||
ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(void);
|
||||
void G_StopDemo(void);
|
||||
boolean G_CheckDemoStatus(void);
|
||||
void G_SaveDemo(void);
|
||||
boolean G_DemoTitleResponder(event_t *ev);
|
||||
|
||||
#define G_GametypeHasTeams() (G_IsGameType(GT_TEAMMATCH) || G_IsGameType(GT_CTF))
|
||||
#define G_BattleGametype() (G_IsGameType(GT_MATCH))
|
||||
#define G_RaceGametype() (G_IsGameType(GT_RACE))
|
||||
@@ -484,4 +325,8 @@ void G_AddMapToBuffer(INT16 map);
|
||||
|
||||
void G_FixCamera(UINT8 view);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+1
-1
@@ -1030,7 +1030,7 @@ INT32 G_KeyStringtoNum(const char *keystr)
|
||||
if (!keystr[0])
|
||||
return 0;
|
||||
|
||||
if (!keystr[0] || (!keystr[1] && keystr[0] > ' ' && keystr[0] <= 'z'))
|
||||
if (!keystr[1] && keystr[0] > ' ' && keystr[0] <= 'z')
|
||||
return keystr[0];
|
||||
|
||||
if (!strncmp(keystr, "KEY", 3) && keystr[3] >= '0' && keystr[3] <= '9')
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
hw_bsp.c
|
||||
hw_draw.c
|
||||
hw_main.c
|
||||
hw_main.cpp
|
||||
hw_clip.c
|
||||
hw_md2.c
|
||||
hw_cache.c
|
||||
|
||||
+63
-81
@@ -25,22 +25,23 @@ GLMipmap_t *current_texture = NULL;
|
||||
|
||||
boolean currently_batching = false;
|
||||
|
||||
FOutVector* finalVertexArray = NULL;// contains subset of sorted vertices and texture coordinates to be sent to gpu
|
||||
FOutVector* finalVertexArray = NULL;// contains subset of sorted vertices and texture coordinates to be sent to gpu
|
||||
UINT32* finalVertexIndexArray = NULL;// contains indexes for glDrawElements, taking into account fan->triangles conversion
|
||||
// NOTE have this alloced as 3x finalVertexArray size
|
||||
int finalVertexArrayAllocSize = 65536;
|
||||
|
||||
//GLubyte* colorArray = NULL;// contains color data to be sent to gpu, if needed
|
||||
//int colorArrayAllocSize = 65536;
|
||||
// not gonna use this for now, just sort by color and change state when it changes
|
||||
// later maybe when using vertex attributes if it's needed
|
||||
|
||||
PolygonArrayEntry* polygonArray = NULL;// contains the polygon data from DrawPolygon, waiting to be processed
|
||||
int polygonArraySize = 0;
|
||||
PolygonArrayEntry **polygonArraySorted = NULL;// contains sorted pointers to polygonArray
|
||||
PolygonArrayEntry* polygonArray = NULL ;// contains the polygon data from DrawPolygon, waiting to be processed
|
||||
PolygonArrayEntry **polygonArraySorted = NULL; // contains sorted pointers to polygonArray
|
||||
int polygonArraySize = 0;
|
||||
int polygonArrayAllocSize = 65536;
|
||||
|
||||
FOutVector* unsortedVertexArray = NULL;// contains unsorted vertices and texture coordinates from DrawPolygon
|
||||
int unsortedVertexArraySize = 0;
|
||||
FOutVector* unsortedVertexArray = NULL; // contains unsorted vertices and texture coordinates from DrawPolygon
|
||||
int unsortedVertexArraySize = 0;
|
||||
int unsortedVertexArrayAllocSize = 65536;
|
||||
|
||||
// Enables batching mode. HWR_ProcessPolygon will collect polygons instead of passing them directly to the rendering backend.
|
||||
@@ -55,11 +56,11 @@ void HWR_StartBatching(void)
|
||||
// init arrays if that has not been done yet
|
||||
if (!finalVertexArray)
|
||||
{
|
||||
finalVertexArray = malloc(finalVertexArrayAllocSize * sizeof(FOutVector));
|
||||
finalVertexArray = malloc(finalVertexArrayAllocSize * sizeof(FOutVector));
|
||||
finalVertexIndexArray = malloc(finalVertexArrayAllocSize * 3 * sizeof(UINT32));
|
||||
polygonArray = malloc(polygonArrayAllocSize * sizeof(PolygonArrayEntry));
|
||||
polygonArraySorted = malloc(polygonArrayAllocSize * sizeof(PolygonArrayEntry *));
|
||||
unsortedVertexArray = malloc(unsortedVertexArrayAllocSize * sizeof(FOutVector));
|
||||
polygonArray = malloc(polygonArrayAllocSize * sizeof(PolygonArrayEntry));
|
||||
polygonArraySorted = malloc(polygonArrayAllocSize * sizeof(PolygonArrayEntry *));
|
||||
unsortedVertexArray = malloc(unsortedVertexArrayAllocSize * sizeof(FOutVector));
|
||||
}
|
||||
|
||||
currently_batching = true;
|
||||
@@ -89,32 +90,23 @@ void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPt
|
||||
{
|
||||
if (!pSurf)
|
||||
{
|
||||
I_Error("Got a null FSurfaceInfo in batching");// nulls should not come in the stuff that batching currently applies to
|
||||
I_Error("Got a null FSurfaceInfo in batching"); // nulls should not come in the stuff that batching currently applies to
|
||||
}
|
||||
|
||||
if (polygonArraySize == polygonArrayAllocSize)
|
||||
{
|
||||
PolygonArrayEntry* new_array;
|
||||
// ran out of space, make new array double the size
|
||||
// ran out of space, double the array size
|
||||
polygonArrayAllocSize *= 2;
|
||||
new_array = malloc(polygonArrayAllocSize * sizeof(PolygonArrayEntry));
|
||||
memcpy(new_array, polygonArray, polygonArraySize * sizeof(PolygonArrayEntry));
|
||||
free(polygonArray);
|
||||
polygonArray = new_array;
|
||||
polygonArray = realloc(polygonArray, polygonArrayAllocSize * sizeof(PolygonArrayEntry));
|
||||
// also need to redo the index array, dont need to copy it though
|
||||
free(polygonArraySorted);
|
||||
polygonArraySorted = malloc(polygonArrayAllocSize * sizeof(PolygonArrayEntry *));
|
||||
polygonArraySorted = realloc(polygonArraySorted, polygonArrayAllocSize * sizeof(PolygonArrayEntry*));
|
||||
}
|
||||
|
||||
while (unsortedVertexArraySize + (int)iNumPts > unsortedVertexArrayAllocSize)
|
||||
{
|
||||
FOutVector* new_array;
|
||||
// need more space for vertices in unsortedVertexArray
|
||||
unsortedVertexArrayAllocSize *= 2;
|
||||
new_array = malloc(unsortedVertexArrayAllocSize * sizeof(FOutVector));
|
||||
memcpy(new_array, unsortedVertexArray, unsortedVertexArraySize * sizeof(FOutVector));
|
||||
free(unsortedVertexArray);
|
||||
unsortedVertexArray = new_array;
|
||||
unsortedVertexArray = realloc(unsortedVertexArray, unsortedVertexArrayAllocSize * sizeof(FOutVector));
|
||||
}
|
||||
|
||||
// add the polygon data to the arrays
|
||||
@@ -124,7 +116,7 @@ void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPt
|
||||
polygonArray[polygonArraySize].numVerts = iNumPts;
|
||||
polygonArray[polygonArraySize].polyFlags = PolyFlags;
|
||||
polygonArray[polygonArraySize].texture = current_texture;
|
||||
polygonArray[polygonArraySize].shader = (shader_target != -1) ? HWR_GetShaderFromTarget(shader_target) : shader_target;
|
||||
polygonArray[polygonArraySize].shader = (shader_target != SHADER_NONE) ? HWR_GetShaderFromTarget(shader_target) : shader_target;
|
||||
polygonArray[polygonArraySize].horizonSpecial = horizonSpecial;
|
||||
polygonArraySize++;
|
||||
|
||||
@@ -140,13 +132,13 @@ void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPt
|
||||
|
||||
static int comparePolygons(const void *p1, const void *p2)
|
||||
{
|
||||
PolygonArrayEntry *poly1 = *(PolygonArrayEntry *const *)p1;
|
||||
PolygonArrayEntry *poly2 = *(PolygonArrayEntry *const *)p2;
|
||||
int diff;
|
||||
INT64 diff64;
|
||||
const PolygonArrayEntry *poly1 = *(PolygonArrayEntry *const *)p1;
|
||||
const PolygonArrayEntry *poly2 = *(PolygonArrayEntry *const *)p2;
|
||||
|
||||
int shader1 = (poly1->polyFlags & PF_NoTexture || poly1->horizonSpecial) ? -1 : poly1->shader;
|
||||
int shader2 = (poly2->polyFlags & PF_NoTexture || poly2->horizonSpecial) ? -1 : poly2->shader;
|
||||
const int shader1 = (poly1->polyFlags & PF_NoTexture || poly1->horizonSpecial) ? -1 : poly1->shader;
|
||||
const int shader2 = (poly2->polyFlags & PF_NoTexture || poly2->horizonSpecial) ? -1 : poly2->shader;
|
||||
|
||||
// skywalls and horizon lines must retain their order for horizon lines to work
|
||||
if (shader1 == -1 && shader2 == -1)
|
||||
@@ -177,20 +169,18 @@ static int comparePolygons(const void *p1, const void *p2)
|
||||
diff = poly1->surf.LightInfo.fade_end - poly2->surf.LightInfo.fade_end;
|
||||
if (diff != 0) return diff;
|
||||
|
||||
diff = poly1->surf.LightInfo.directional - poly2->surf.LightInfo.directional;
|
||||
|
||||
return diff;
|
||||
return poly1->surf.LightInfo.directional - poly2->surf.LightInfo.directional;
|
||||
}
|
||||
|
||||
static int comparePolygonsNoShaders(const void *p1, const void *p2)
|
||||
{
|
||||
PolygonArrayEntry *poly1 = *(PolygonArrayEntry *const *)p1;
|
||||
PolygonArrayEntry *poly2 = *(PolygonArrayEntry *const *)p2;
|
||||
int diff;
|
||||
INT64 diff64;
|
||||
const PolygonArrayEntry *poly1 = *(PolygonArrayEntry *const *)p1;
|
||||
const PolygonArrayEntry *poly2 = *(PolygonArrayEntry *const *)p2;
|
||||
|
||||
GLMipmap_t *texture1 = (poly1->polyFlags & PF_NoTexture || poly1->horizonSpecial) ? NULL : poly1->texture;
|
||||
GLMipmap_t *texture2 = (poly2->polyFlags & PF_NoTexture || poly2->horizonSpecial) ? NULL : poly2->texture;
|
||||
const GLMipmap_t *texture1 = (poly1->polyFlags & PF_NoTexture || poly1->horizonSpecial) ? NULL : poly1->texture;
|
||||
const GLMipmap_t *texture2 = (poly2->polyFlags & PF_NoTexture || poly2->horizonSpecial) ? NULL : poly2->texture;
|
||||
|
||||
// skywalls and horizon lines must retain their order for horizon lines to work
|
||||
if (!texture1 && !texture2)
|
||||
@@ -214,17 +204,16 @@ static int comparePolygonsNoShaders(const void *p1, const void *p2)
|
||||
// the rendering backend to draw them.
|
||||
void HWR_RenderBatches(void)
|
||||
{
|
||||
int finalVertexWritePos = 0;// position in finalVertexArray
|
||||
int finalIndexWritePos = 0;// position in finalVertexIndexArray
|
||||
|
||||
int polygonReadPos = 0;// position in polygonArraySorted
|
||||
int finalVertexWritePos = 0; // position in finalVertexArray
|
||||
int finalIndexWritePos = 0; // position in finalVertexIndexArray
|
||||
int polygonReadPos = 0; // position in polygonArraySorted
|
||||
|
||||
int currentShader;
|
||||
int nextShader = 0;
|
||||
GLMipmap_t *currentTexture = NULL;
|
||||
GLMipmap_t *nextTexture = NULL;
|
||||
FBITFIELD currentPolyFlags = 0;
|
||||
FBITFIELD nextPolyFlags = 0;
|
||||
GLMipmap_t *currentTexture = NULL;
|
||||
GLMipmap_t *nextTexture = NULL;
|
||||
FBITFIELD currentPolyFlags = 0;
|
||||
FBITFIELD nextPolyFlags = 0;
|
||||
FSurfaceInfo currentSurfaceInfo;
|
||||
FSurfaceInfo nextSurfaceInfo;
|
||||
|
||||
@@ -235,8 +224,8 @@ void HWR_RenderBatches(void)
|
||||
I_Error("HWR_RenderBatches called without starting batching");
|
||||
}
|
||||
|
||||
nextSurfaceInfo.LightInfo.fade_end = 0;
|
||||
nextSurfaceInfo.LightInfo.fade_start = 0;
|
||||
nextSurfaceInfo.LightInfo.fade_end = 0;
|
||||
nextSurfaceInfo.LightInfo.fade_start = 0;
|
||||
nextSurfaceInfo.LightInfo.light_level = 0;
|
||||
nextSurfaceInfo.LightInfo.directional = false;
|
||||
|
||||
@@ -254,7 +243,7 @@ void HWR_RenderBatches(void)
|
||||
ps_hw_numpolys.value.i = polygonArraySize;
|
||||
ps_hw_numcalls.value.i = ps_hw_numverts.value.i = 0;
|
||||
ps_hw_numshaders.value.i = ps_hw_numtextures.value.i
|
||||
= ps_hw_numpolyflags.value.i = ps_hw_numcolors.value.i = 1;
|
||||
= ps_hw_numpolyflags.value.i = ps_hw_numcolors.value.i = 1;
|
||||
|
||||
// init polygonArraySorted
|
||||
for (i = 0; i < polygonArraySize; i++)
|
||||
@@ -264,10 +253,7 @@ void HWR_RenderBatches(void)
|
||||
|
||||
// sort polygons
|
||||
PS_START_TIMING(ps_hw_batchsorttime);
|
||||
if (cv_glshaders.value && gl_shadersavailable)
|
||||
qs22j(polygonArraySorted, polygonArraySize, sizeof(PolygonArrayEntry *), comparePolygons);
|
||||
else
|
||||
qs22j(polygonArraySorted, polygonArraySize, sizeof(PolygonArrayEntry *), comparePolygonsNoShaders);
|
||||
qs22j(polygonArraySorted, polygonArraySize, sizeof(PolygonArrayEntry *), (HWR_UseShader() ? comparePolygons : comparePolygonsNoShaders));
|
||||
PS_STOP_TIMING(ps_hw_batchsorttime);
|
||||
|
||||
// sort order
|
||||
@@ -279,16 +265,16 @@ void HWR_RenderBatches(void)
|
||||
|
||||
PS_START_TIMING(ps_hw_batchdrawtime);
|
||||
|
||||
currentShader = polygonArraySorted[0]->shader;
|
||||
currentTexture = polygonArraySorted[0]->texture;
|
||||
currentPolyFlags = polygonArraySorted[0]->polyFlags;
|
||||
currentShader = polygonArraySorted[0]->shader;
|
||||
currentTexture = polygonArraySorted[0]->texture;
|
||||
currentPolyFlags = polygonArraySorted[0]->polyFlags;
|
||||
currentSurfaceInfo = polygonArraySorted[0]->surf;
|
||||
// For now, will sort and track the colors. Vertex attributes could be used instead of uniforms
|
||||
// and a color array could replace the color calls.
|
||||
|
||||
// set state for first batch
|
||||
|
||||
if (cv_glshaders.value && gl_shadersavailable)
|
||||
if (HWR_UseShader())
|
||||
{
|
||||
GL_SetShader(currentShader);
|
||||
}
|
||||
@@ -313,42 +299,37 @@ void HWR_RenderBatches(void)
|
||||
// steps:
|
||||
// write vertices
|
||||
// check for changes or end, otherwise go back to writing
|
||||
// changes will affect the next vars and the change bools
|
||||
// end could set flag for stopping
|
||||
// changes will affect the next vars and the change bools
|
||||
// end could set flag for stopping
|
||||
// execute draw call
|
||||
// could check ending flag here
|
||||
// change states according to next vars and change bools, updating the current vars and reseting the bools
|
||||
// reset write pos
|
||||
// repeat loop
|
||||
|
||||
PolygonArrayEntry *entry = polygonArraySorted[polygonReadPos++];
|
||||
int numVerts = entry->numVerts;
|
||||
const PolygonArrayEntry *entry = polygonArraySorted[polygonReadPos++];
|
||||
const int numVerts = entry->numVerts;
|
||||
|
||||
// before writing, check if there is enough room
|
||||
// using 'while' instead of 'if' here makes sure that there will *always* be enough room.
|
||||
// probably never will this loop run more than once though
|
||||
while (finalVertexWritePos + numVerts > finalVertexArrayAllocSize)
|
||||
{
|
||||
FOutVector* new_array;
|
||||
unsigned int* new_index_array;
|
||||
finalVertexArrayAllocSize *= 2;
|
||||
new_array = malloc(finalVertexArrayAllocSize * sizeof(FOutVector));
|
||||
memcpy(new_array, finalVertexArray, finalVertexWritePos * sizeof(FOutVector));
|
||||
free(finalVertexArray);
|
||||
finalVertexArray = new_array;
|
||||
finalVertexArray = realloc(finalVertexArray, finalVertexArrayAllocSize * sizeof(FOutVector));
|
||||
// also increase size of index array, 3x of vertex array since
|
||||
// going from fans to triangles increases vertex count to 3x
|
||||
new_index_array = malloc(finalVertexArrayAllocSize * 3 * sizeof(UINT32));
|
||||
memcpy(new_index_array, finalVertexIndexArray, finalIndexWritePos * sizeof(UINT32));
|
||||
free(finalVertexIndexArray);
|
||||
finalVertexIndexArray = new_index_array;
|
||||
finalVertexIndexArray = realloc(finalVertexIndexArray, finalVertexArrayAllocSize * 3 * sizeof(UINT32));
|
||||
}
|
||||
|
||||
// write the vertices of the polygon
|
||||
memcpy(&finalVertexArray[finalVertexWritePos], &unsortedVertexArray[entry->vertsIndex],
|
||||
numVerts * sizeof(FOutVector));
|
||||
memcpy(&finalVertexArray[finalVertexWritePos], &unsortedVertexArray[entry->vertsIndex], numVerts * sizeof(FOutVector));
|
||||
|
||||
// write the indexes, pointing to the fan vertexes but in triangles format
|
||||
firstIndex = finalVertexWritePos;
|
||||
lastIndex = finalVertexWritePos + numVerts;
|
||||
finalVertexWritePos += 2;
|
||||
|
||||
while (finalVertexWritePos < lastIndex)
|
||||
{
|
||||
finalVertexIndexArray[finalIndexWritePos++] = firstIndex;
|
||||
@@ -363,16 +344,16 @@ void HWR_RenderBatches(void)
|
||||
else
|
||||
{
|
||||
// check if a state change is required, set the change bools and next vars
|
||||
PolygonArrayEntry *nextEntry = polygonArraySorted[polygonReadPos];
|
||||
nextShader = nextEntry->shader;
|
||||
nextTexture = nextEntry->texture;
|
||||
nextPolyFlags = nextEntry->polyFlags;
|
||||
const PolygonArrayEntry *nextEntry = polygonArraySorted[polygonReadPos];
|
||||
nextShader = nextEntry->shader;
|
||||
nextTexture = nextEntry->texture;
|
||||
nextPolyFlags = nextEntry->polyFlags;
|
||||
nextSurfaceInfo = nextEntry->surf;
|
||||
|
||||
if (nextPolyFlags & PF_NoTexture)
|
||||
nextTexture = 0;
|
||||
|
||||
if (currentShader != nextShader && cv_glshaders.value && gl_shadersavailable)
|
||||
if (currentShader != nextShader && HWR_UseShader())
|
||||
{
|
||||
changeState = true;
|
||||
changeShader = true;
|
||||
@@ -390,14 +371,14 @@ void HWR_RenderBatches(void)
|
||||
changePolyFlags = true;
|
||||
}
|
||||
|
||||
if (cv_glshaders.value && gl_shadersavailable)
|
||||
if (HWR_UseShader())
|
||||
{
|
||||
if (currentSurfaceInfo.PolyColor.rgba != nextSurfaceInfo.PolyColor.rgba ||
|
||||
currentSurfaceInfo.TintColor.rgba != nextSurfaceInfo.TintColor.rgba ||
|
||||
currentSurfaceInfo.FadeColor.rgba != nextSurfaceInfo.FadeColor.rgba ||
|
||||
currentSurfaceInfo.LightInfo.light_level != nextSurfaceInfo.LightInfo.light_level ||
|
||||
currentSurfaceInfo.LightInfo.fade_start != nextSurfaceInfo.LightInfo.fade_start ||
|
||||
currentSurfaceInfo.LightInfo.fade_end != nextSurfaceInfo.LightInfo.fade_end ||
|
||||
currentSurfaceInfo.LightInfo.fade_start != nextSurfaceInfo.LightInfo.fade_start ||
|
||||
currentSurfaceInfo.LightInfo.fade_end != nextSurfaceInfo.LightInfo.fade_end ||
|
||||
currentSurfaceInfo.LightInfo.directional != nextSurfaceInfo.LightInfo.directional)
|
||||
{
|
||||
changeState = true;
|
||||
@@ -423,7 +404,7 @@ void HWR_RenderBatches(void)
|
||||
ps_hw_numverts.value.i += finalIndexWritePos;
|
||||
// reset write positions
|
||||
finalVertexWritePos = 0;
|
||||
finalIndexWritePos = 0;
|
||||
finalIndexWritePos = 0;
|
||||
}
|
||||
else
|
||||
continue;
|
||||
@@ -469,9 +450,10 @@ void HWR_RenderBatches(void)
|
||||
|
||||
ps_hw_numcolors.value.i++;
|
||||
}
|
||||
// and that should be it?
|
||||
}
|
||||
// and that should be it?
|
||||
}
|
||||
|
||||
// reset the arrays (set sizes to 0)
|
||||
polygonArraySize = 0;
|
||||
unsortedVertexArraySize = 0;
|
||||
|
||||
@@ -13,6 +13,10 @@
|
||||
#ifndef __HWR_BATCHING_H__
|
||||
#define __HWR_BATCHING_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "hw_defs.h"
|
||||
#include "hw_data.h"
|
||||
#include "hw_gl.h"
|
||||
@@ -36,4 +40,8 @@ void HWR_SetCurrentTexture(GLMipmap_t *texture);
|
||||
void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, int shader, boolean horizonSpecial);
|
||||
void HWR_RenderBatches(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -371,12 +371,13 @@ static poly_t *CutOutSubsecPoly(seg_t *lseg, INT32 count, poly_t *poly)
|
||||
line_t *line = lseg->linedef;
|
||||
|
||||
// portal check
|
||||
if (!gl_maphasportals && line->special == 40 && lseg->side == 0)
|
||||
if (!gl_maphasportals && line->special == PORTALSPECIAL && lseg->side == 0)
|
||||
{
|
||||
// Find the other side!
|
||||
INT32 line2 = P_FindSpecialLineFromTag(40, line->tag, -1);
|
||||
INT32 line2 = P_FindSpecialLineFromTag(PORTALSPECIAL, line->tag, -1);
|
||||
|
||||
if (line == &lines[line2])
|
||||
line2 = P_FindSpecialLineFromTag(40, line->tag, line2);
|
||||
line2 = P_FindSpecialLineFromTag(PORTALSPECIAL, line->tag, line2);
|
||||
if (line2 >= 0) // found it!
|
||||
gl_maphasportals = 1;
|
||||
}
|
||||
|
||||
+14
-9
@@ -46,12 +46,16 @@ RGBA_t *HWR_GetTexturePalette(void)
|
||||
|
||||
static INT32 format2bpp(GLTextureFormat_t format)
|
||||
{
|
||||
if (format == GL_TEXFMT_RGBA)
|
||||
return 4;
|
||||
else if (format == GL_TEXFMT_ALPHA_INTENSITY_88 || format == GL_TEXFMT_AP_88)
|
||||
return 2;
|
||||
else
|
||||
return 1;
|
||||
switch (format)
|
||||
{
|
||||
case GL_TEXFMT_RGBA:
|
||||
return 4;
|
||||
case GL_TEXFMT_ALPHA_INTENSITY_88:
|
||||
case GL_TEXFMT_AP_88:
|
||||
return 2;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// This code was originally placed directly in HWR_DrawPatchInCache.
|
||||
@@ -221,8 +225,6 @@ static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap,
|
||||
if (texture->width <= 0 || texture->height <= 0)
|
||||
return;
|
||||
|
||||
palette = HWR_GetTexturePalette();
|
||||
|
||||
x1 = patch->originx;
|
||||
width = SHORT(realpatch->width);
|
||||
height = SHORT(realpatch->height);
|
||||
@@ -234,6 +236,8 @@ static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap,
|
||||
if (patch->originy > texture->height || (patch->originy + height) < 0)
|
||||
return; // patch not located within texture's y bounds, ignore
|
||||
|
||||
palette = HWR_GetTexturePalette();
|
||||
|
||||
// patch is actually inside the texture!
|
||||
// now check if texture is partly off-screen and adjust accordingly
|
||||
|
||||
@@ -323,7 +327,6 @@ static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *gltex, boolean noe
|
||||
boolean skyspecial = false; // poor hack for Legacy large skies..
|
||||
|
||||
RGBA_t *palette;
|
||||
palette = HWR_GetTexturePalette();
|
||||
|
||||
texture = textures[texnum];
|
||||
|
||||
@@ -361,6 +364,8 @@ static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *gltex, boolean noe
|
||||
INT32 j;
|
||||
RGBA_t col;
|
||||
|
||||
palette = HWR_GetTexturePalette();
|
||||
|
||||
col = palette[HWR_CHROMAKEY_EQUIVALENTCOLORINDEX];
|
||||
|
||||
for (idx = 0, j = 0; j < blockheight; j++)
|
||||
|
||||
@@ -7,6 +7,10 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// OpenGL BSP clipping
|
||||
#include "../doomdef.h"
|
||||
#include "../tables.h"
|
||||
@@ -22,3 +26,7 @@ angle_t gld_FrustumAngle(angle_t tiltangle);
|
||||
void gld_FrustumSetup(void);
|
||||
boolean gld_SphereInFrustum(float x, float y, float z, float radius);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
@@ -318,6 +318,8 @@ enum hwdsetspecialstate
|
||||
HWD_SET_TEXTUREFILTERMODE,
|
||||
HWD_SET_TEXTUREANISOTROPICMODE,
|
||||
|
||||
HWD_SET_WIREFRAME,
|
||||
|
||||
HWD_SET_MSAA,
|
||||
|
||||
HWD_SET_SCREEN_TEXTURES,
|
||||
|
||||
+34
-25
@@ -96,12 +96,12 @@ void HWR_DrawPatch(patch_t *gpatch, INT32 x, INT32 y, INT32 option)
|
||||
pdupx = pdupy = 2.0f;
|
||||
break;
|
||||
case V_SMALLSCALEPATCH:
|
||||
pdupx = 2.0f * FIXED_TO_FLOAT(vid.fsmalldupx);
|
||||
pdupy = 2.0f * FIXED_TO_FLOAT(vid.fsmalldupy);
|
||||
pdupx = 2.0f * FIXED_TO_FLOAT(vid.smalldupx*FRACUNIT);
|
||||
pdupy = 2.0f * FIXED_TO_FLOAT(vid.smalldupy*FRACUNIT);
|
||||
break;
|
||||
case V_MEDSCALEPATCH:
|
||||
pdupx = 2.0f * FIXED_TO_FLOAT(vid.fmeddupx);
|
||||
pdupy = 2.0f * FIXED_TO_FLOAT(vid.fmeddupy);
|
||||
pdupx = 2.0f * FIXED_TO_FLOAT(vid.meddupx*FRACUNIT);
|
||||
pdupy = 2.0f * FIXED_TO_FLOAT(vid.meddupx*FRACUNIT);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -241,16 +241,16 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p
|
||||
if (option & V_SNAPTORIGHT)
|
||||
cx += (fvw - (FLOATBASEVIDWIDTH * dupx));
|
||||
else if (!(option & V_SNAPTOLEFT))
|
||||
cx += (fvw - (FLOATBASEVIDWIDTH * dupx))/2;
|
||||
cx += (fvw - (FLOATBASEVIDWIDTH * dupx))/2.0f;
|
||||
}
|
||||
if (fabsf(fvh - FLOATBASEVIDHEIGHT * dupy) > 1.0E-36f)
|
||||
{
|
||||
if ((option & (V_SPLITSCREEN|V_SNAPTOTOP)) == (V_SPLITSCREEN|V_SNAPTOTOP))
|
||||
cy += (fvh/2 - (FLOATBASEVIDHEIGHT/2 * dupy));
|
||||
cy += (fvh/2.0f - (FLOATBASEVIDHEIGHT/2.0f * dupy));
|
||||
else if (option & V_SNAPTOBOTTOM)
|
||||
cy += (fvh - (FLOATBASEVIDHEIGHT * dupy));
|
||||
else if (!(option & V_SNAPTOTOP))
|
||||
cy += (fvh - (FLOATBASEVIDHEIGHT * dupy))/2;
|
||||
cy += (fvh - (FLOATBASEVIDHEIGHT * dupy))/2.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -305,10 +305,13 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p
|
||||
FSurfaceInfo Surf;
|
||||
Surf.PolyColor.s.red = Surf.PolyColor.s.green = Surf.PolyColor.s.blue = 0xff;
|
||||
|
||||
if (alphalevel == 13) Surf.PolyColor.s.alpha = softwaretranstogl_lo[hudtrans];
|
||||
else if (alphalevel == 14) Surf.PolyColor.s.alpha = softwaretranstogl[hudtrans];
|
||||
else if (alphalevel == 15) Surf.PolyColor.s.alpha = softwaretranstogl_hi[hudtrans];
|
||||
else Surf.PolyColor.s.alpha = softwaretranstogl[10-alphalevel];
|
||||
switch (alphalevel)
|
||||
{
|
||||
case 13: Surf.PolyColor.s.alpha = softwaretranstogl_lo[hudtrans]; break;
|
||||
case 14: Surf.PolyColor.s.alpha = softwaretranstogl[hudtrans]; break;
|
||||
case 15: Surf.PolyColor.s.alpha = softwaretranstogl_hi[hudtrans]; break;
|
||||
default: Surf.PolyColor.s.alpha = softwaretranstogl[10-alphalevel]; break;
|
||||
}
|
||||
|
||||
flags |= PF_Modulated;
|
||||
GL_DrawPolygon(&Surf, v, 4, flags);
|
||||
@@ -392,16 +395,16 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale,
|
||||
if (option & V_SNAPTORIGHT)
|
||||
cx += (fvw - (FLOATBASEVIDWIDTH * dupx));
|
||||
else if (!(option & V_SNAPTOLEFT))
|
||||
cx += (fvw - (FLOATBASEVIDWIDTH * dupx))/2;
|
||||
cx += (fvw - (FLOATBASEVIDWIDTH * dupx))/2.0f;
|
||||
}
|
||||
if (fabsf(fvh - FLOATBASEVIDHEIGHT * dupy) > 1.0E-36f)
|
||||
{
|
||||
if ((option & (V_SPLITSCREEN|V_SNAPTOTOP)) == (V_SPLITSCREEN|V_SNAPTOTOP))
|
||||
cy += (fvh/2 - (FLOATBASEVIDHEIGHT/2 * dupy));
|
||||
cy += (fvh/2.0f - (FLOATBASEVIDHEIGHT/2.0f * dupy));
|
||||
else if (option & V_SNAPTOBOTTOM)
|
||||
cy += (fvh - (FLOATBASEVIDHEIGHT * dupy));
|
||||
else if (!(option & V_SNAPTOTOP))
|
||||
cy += (fvh - (FLOATBASEVIDHEIGHT * dupy))/2;
|
||||
cy += (fvh - (FLOATBASEVIDHEIGHT * dupy))/2.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -467,10 +470,13 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale,
|
||||
FSurfaceInfo Surf;
|
||||
Surf.PolyColor.s.red = Surf.PolyColor.s.green = Surf.PolyColor.s.blue = 0xff;
|
||||
|
||||
if (alphalevel == 13) Surf.PolyColor.s.alpha = softwaretranstogl_lo[cv_translucenthud.value];
|
||||
else if (alphalevel == 14) Surf.PolyColor.s.alpha = softwaretranstogl[cv_translucenthud.value];
|
||||
else if (alphalevel == 15) Surf.PolyColor.s.alpha = softwaretranstogl_hi[cv_translucenthud.value];
|
||||
else Surf.PolyColor.s.alpha = softwaretranstogl[10-alphalevel];
|
||||
switch (alphalevel)
|
||||
{
|
||||
case 13: Surf.PolyColor.s.alpha = softwaretranstogl_lo[cv_translucenthud.value]; break;
|
||||
case 14: Surf.PolyColor.s.alpha = softwaretranstogl[cv_translucenthud.value]; break;
|
||||
case 15: Surf.PolyColor.s.alpha = softwaretranstogl_hi[cv_translucenthud.value]; break;
|
||||
default: Surf.PolyColor.s.alpha = softwaretranstogl[10-alphalevel]; break;
|
||||
}
|
||||
|
||||
flags |= PF_Modulated;
|
||||
GL_DrawPolygon(&Surf, v, 4, flags);
|
||||
@@ -487,7 +493,7 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale,
|
||||
// --------------------------------------------------------------------------
|
||||
// Fills a box of pixels using a flat texture as a pattern
|
||||
// --------------------------------------------------------------------------
|
||||
void HWR_DrawFlatFill (INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatlumpnum)
|
||||
void HWR_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatlumpnum)
|
||||
{
|
||||
FOutVector v[4];
|
||||
double dflatsize;
|
||||
@@ -840,7 +846,7 @@ void HWR_DrawDiag(INT32 x, INT32 y, INT32 wh, INT32 color)
|
||||
if (color & V_SNAPTORIGHT)
|
||||
fx += (fvw - (FLOATBASEVIDWIDTH * dupx));
|
||||
else if (!(color & V_SNAPTOLEFT))
|
||||
fx += (fvw - (FLOATBASEVIDWIDTH * dupx)) / 2;
|
||||
fx += (fvw - (FLOATBASEVIDWIDTH * dupx)) / 2.0f;
|
||||
}
|
||||
if (fabsf(fvh - (FLOATBASEVIDHEIGHT * dupy)) > 1.0E-36f)
|
||||
{
|
||||
@@ -848,7 +854,7 @@ void HWR_DrawDiag(INT32 x, INT32 y, INT32 wh, INT32 color)
|
||||
if (color & V_SNAPTOBOTTOM)
|
||||
fy += (fvh - (FLOATBASEVIDHEIGHT * dupy));
|
||||
else if (!(color & V_SNAPTOTOP))
|
||||
fy += (fvh - (FLOATBASEVIDHEIGHT * dupy)) / 2;
|
||||
fy += (fvh - (FLOATBASEVIDHEIGHT * dupy)) / 2.0f;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1122,10 +1128,13 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color)
|
||||
|
||||
if (alphalevel)
|
||||
{
|
||||
if (alphalevel == 13) Surf.PolyColor.s.alpha = softwaretranstogl_lo[hudtrans];
|
||||
else if (alphalevel == 14) Surf.PolyColor.s.alpha = softwaretranstogl[hudtrans];
|
||||
else if (alphalevel == 15) Surf.PolyColor.s.alpha = softwaretranstogl_hi[hudtrans];
|
||||
else Surf.PolyColor.s.alpha = softwaretranstogl[10-alphalevel];
|
||||
switch (alphalevel)
|
||||
{
|
||||
case 13: Surf.PolyColor.s.alpha = softwaretranstogl_lo[hudtrans]; break;
|
||||
case 14: Surf.PolyColor.s.alpha = softwaretranstogl[hudtrans]; break;
|
||||
case 15: Surf.PolyColor.s.alpha = softwaretranstogl_hi[hudtrans]; break;
|
||||
default: Surf.PolyColor.s.alpha = softwaretranstogl[10-alphalevel]; break;
|
||||
}
|
||||
}
|
||||
|
||||
GL_DrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest);
|
||||
|
||||
@@ -13,6 +13,10 @@
|
||||
#ifndef __HWR_GL_H__
|
||||
#define __HWR_GL_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "../screen.h"
|
||||
|
||||
#include "hw_data.h"
|
||||
@@ -76,4 +80,8 @@ UINT32 GL_CreateLightTable(RGBA_t *hw_lighttable);
|
||||
void GL_ClearLightTables(void);
|
||||
void GL_SetScreenPalette(RGBA_t *palette);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // __HWR_GL_H__
|
||||
@@ -14,6 +14,10 @@
|
||||
#ifndef _HWR_GLOB_H_
|
||||
#define _HWR_GLOB_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "hw_defs.h"
|
||||
#include "../m_misc.h"
|
||||
#include "../r_defs.h"
|
||||
@@ -109,4 +113,8 @@ const char *HWR_GetShaderName(INT32 shader);
|
||||
|
||||
extern customshaderxlat_t shaderxlat[];
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif //_HW_GLOB_
|
||||
File diff suppressed because it is too large.
Load diff
+12
-1
@@ -20,6 +20,10 @@
|
||||
#ifndef __HWR_MAIN_H__
|
||||
#define __HWR_MAIN_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "hw_gl.h"
|
||||
#include "hw_glob.h"
|
||||
#include "hw_data.h"
|
||||
@@ -106,6 +110,7 @@ void HWR_AddCommands(void);
|
||||
|
||||
void HWR_RenderPlayerView(void);
|
||||
void HWR_RenderViewpoint(gl_portal_t *rootportal, const float fpov, player_t *player, int stencil_level, boolean allow_portals);
|
||||
void HWR_RenderPortalViewpoint(gl_portal_t *rootportal, const float fpov, player_t *player, int stencil_level, boolean allow_portals);
|
||||
|
||||
void HWR_ClearSkyDome(void);
|
||||
void HWR_BuildSkyDome(void);
|
||||
@@ -202,6 +207,8 @@ extern consvar_t cv_glsolvetjoin;
|
||||
|
||||
extern consvar_t cv_glbatching;
|
||||
|
||||
extern consvar_t cv_glwireframe;
|
||||
|
||||
extern consvar_t cv_glrenderdistance;
|
||||
|
||||
extern consvar_t cv_glhorizonlines;
|
||||
@@ -223,7 +230,11 @@ FUNCINLINE static ATTRINLINE boolean HWR_ShouldUsePaletteRendering(void)
|
||||
|
||||
FUNCINLINE static ATTRINLINE boolean HWR_PalRenderFlashpal(void)
|
||||
{
|
||||
return (HWR_ShouldUsePaletteRendering() && cv_glflashpal.value);
|
||||
return (cv_glflashpal.value && HWR_ShouldUsePaletteRendering());
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}// extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1187,7 +1187,7 @@ void HWR_DrawMD2(gl_vissprite_t *spr)
|
||||
spriteinfo_t *sprinfo;
|
||||
interpmobjstate_t interp;
|
||||
|
||||
if (R_UsingFrameInterpolation() && !paused && (!cv_maxinterpdist.value || R_QuickCamDist(spr->mobj->x, spr->mobj->y) < cv_maxinterpdist.value))
|
||||
if (R_UsingFrameInterpolation() && !paused && R_CheckInterpDist(spr->mobj))
|
||||
{
|
||||
R_InterpolateMobjState(spr->mobj, rendertimefrac, &interp);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,10 @@
|
||||
#ifndef _HW_MD2_H_
|
||||
#define _HW_MD2_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "hw_glob.h"
|
||||
#include "hw_model.h"
|
||||
|
||||
@@ -46,4 +50,8 @@ void HWR_DrawMD2(gl_vissprite_t *spr);
|
||||
void HWR_AddPlayerMD2(INT32 skin, boolean local);
|
||||
void HWR_AddSpriteMD2(size_t spritenum);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // _HW_MD2_H_
|
||||
@@ -66,6 +66,7 @@ void HWR_FreePortalList(gl_portallist_t freelist)
|
||||
|
||||
// free memory from portal list allocated by calls to Add2Lines
|
||||
gl_portal_t *gl_portal_temp = freelist.base;
|
||||
|
||||
while (gl_portal_temp)
|
||||
{
|
||||
gl_portal_t *nextportal = gl_portal_temp->next;
|
||||
@@ -125,8 +126,7 @@ void HWR_PortalFrame(gl_portal_t* portal)
|
||||
if (portal->clipline != -1)
|
||||
{
|
||||
portalclipline = &lines[portal->clipline];
|
||||
portalcullsector = portalclipline->frontsector;
|
||||
viewsector = portalclipline->frontsector;
|
||||
portalcullsector = viewsector = portalclipline->frontsector;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -169,7 +169,7 @@ void HWR_RenderPortal(gl_portal_t* portal, gl_portal_t* rootportal, const float
|
||||
// go to portal frame lmao
|
||||
HWR_PortalFrame(portal);
|
||||
// call HWR_RenderViewpoint
|
||||
HWR_RenderViewpoint(portal, fpov, player, stencil_level + 1, true);
|
||||
HWR_RenderPortalViewpoint(portal, fpov, player, stencil_level + 1, true);
|
||||
// return to current frame
|
||||
if (rootportal)
|
||||
HWR_PortalFrame(rootportal);
|
||||
|
||||
@@ -14,6 +14,10 @@
|
||||
#ifndef __HW_PORTAL__
|
||||
#define __HW_PORTAL__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef HWRENDER
|
||||
|
||||
#include "../doomstat.h"
|
||||
@@ -77,5 +81,9 @@ void HWR_FreePortalList(gl_portallist_t portallist);
|
||||
boolean HWR_PortalCheckPointSide(fixed_t x, fixed_t y);
|
||||
boolean HWR_PortalCheckBBox(const fixed_t *bspcoord);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}// extern "C"
|
||||
#endif
|
||||
#endif
|
||||
+183
-138
@@ -350,6 +350,8 @@ typedef void (APIENTRY * PFNglDisable) (GLenum cap);
|
||||
static PFNglDisable pglDisable;
|
||||
typedef void (APIENTRY * PFNglGetFloatv) (GLenum pname, GLfloat *params);
|
||||
static PFNglGetFloatv pglGetFloatv;
|
||||
typedef void (APIENTRY * PFNglPolygonMode) (GLenum, GLenum);
|
||||
static PFNglPolygonMode pglPolygonMode;
|
||||
|
||||
/* Depth Buffer */
|
||||
typedef void (APIENTRY * PFNglClearDepth) (GLclampd depth);
|
||||
@@ -549,6 +551,7 @@ boolean SetupGLfunc(void)
|
||||
GETOPENGLFUNC(pglGetFloatv, glGetFloatv)
|
||||
GETOPENGLFUNC(pglGetIntegerv, glGetIntegerv)
|
||||
GETOPENGLFUNC(pglGetString, glGetString)
|
||||
GETOPENGLFUNC(pglPolygonMode, glPolygonMode)
|
||||
|
||||
GETOPENGLFUNC(pglClearDepth, glClearDepth)
|
||||
GETOPENGLFUNC(pglDepthFunc, glDepthFunc)
|
||||
@@ -734,69 +737,78 @@ static boolean GLFramebuffer_CheckExt(void)
|
||||
return false;
|
||||
|
||||
// check if all needed gl extensions are available
|
||||
return (GL_isExtAvailable("GL_ARB_framebuffer_no_attachments", gl_extensions) && GL_isExtAvailable("GL_ARB_framebuffer_object", gl_extensions) && GL_isExtAvailable("GL_ARB_framebuffer_sRGB", gl_extensions));
|
||||
return (GL_isExtAvailable("GL_ARB_framebuffer_no_attachments", gl_extensions)
|
||||
&& GL_isExtAvailable("GL_ARB_framebuffer_object", gl_extensions)
|
||||
&& GL_isExtAvailable("GL_ARB_framebuffer_sRGB", gl_extensions));
|
||||
}
|
||||
#endif
|
||||
|
||||
void SetupGLFunc4(void)
|
||||
{
|
||||
#define GetGLfunc(func) \
|
||||
p##func = GetGLFunc(#func); \
|
||||
if (!p##func) \
|
||||
{ \
|
||||
GL_MSG_Warning("failed to get OpenGL function: %s", #func); \
|
||||
} \
|
||||
|
||||
/* 1.2 funcs */
|
||||
pglTexImage3D = GetGLFunc("glTexImage3D");
|
||||
GetGLfunc(glTexImage3D);
|
||||
/* 1.3 funcs */
|
||||
pglActiveTexture = GetGLFunc("glActiveTexture");
|
||||
pglMultiTexCoord2f = GetGLFunc("glMultiTexCoord2f");
|
||||
pglClientActiveTexture = GetGLFunc("glClientActiveTexture");
|
||||
pglMultiTexCoord2fv = GetGLFunc("glMultiTexCoord2fv");
|
||||
GetGLfunc(glActiveTexture);
|
||||
GetGLfunc(glMultiTexCoord2f);
|
||||
GetGLfunc(glClientActiveTexture);
|
||||
GetGLfunc(glMultiTexCoord2fv);
|
||||
|
||||
/* 1.5 funcs */
|
||||
pglGenBuffers = GetGLFunc("glGenBuffers");
|
||||
pglBindBuffer = GetGLFunc("glBindBuffer");
|
||||
pglBufferData = GetGLFunc("glBufferData");
|
||||
pglDeleteBuffers = GetGLFunc("glDeleteBuffers");
|
||||
pglColorPointer = GetGLFunc("glColorPointer");
|
||||
GetGLfunc(glGenBuffers);
|
||||
GetGLfunc(glBindBuffer);
|
||||
GetGLfunc(glBufferData);
|
||||
GetGLfunc(glDeleteBuffers);
|
||||
GetGLfunc(glColorPointer);
|
||||
|
||||
/* 2.0 funcs */
|
||||
pglBlendEquation = GetGLFunc("glBlendEquation");
|
||||
GetGLfunc(glBlendEquation);
|
||||
|
||||
pglStencilFuncSeparate = GetGLFunc("glStencilFuncSeparate");
|
||||
pglStencilOpSeparate = GetGLFunc("glStencilOpSeparate");
|
||||
GetGLfunc(glStencilFuncSeparate);
|
||||
GetGLfunc(glStencilOpSeparate);
|
||||
|
||||
pglCreateShader = GetGLFunc("glCreateShader");
|
||||
pglShaderSource = GetGLFunc("glShaderSource");
|
||||
pglCompileShader = GetGLFunc("glCompileShader");
|
||||
pglGetShaderiv = GetGLFunc("glGetShaderiv");
|
||||
pglGetShaderInfoLog = GetGLFunc("glGetShaderInfoLog");
|
||||
pglDeleteShader = GetGLFunc("glDeleteShader");
|
||||
pglCreateProgram = GetGLFunc("glCreateProgram");
|
||||
pglDeleteProgram = GetGLFunc("glDeleteProgram");
|
||||
pglAttachShader = GetGLFunc("glAttachShader");
|
||||
pglLinkProgram = GetGLFunc("glLinkProgram");
|
||||
pglGetProgramiv = GetGLFunc("glGetProgramiv");
|
||||
pglGetProgramInfoLog = GetGLFunc("glGetProgramInfoLog");
|
||||
pglUseProgram = GetGLFunc("glUseProgram");
|
||||
pglUniform1i = GetGLFunc("glUniform1i");
|
||||
pglUniform1f = GetGLFunc("glUniform1f");
|
||||
pglUniform2f = GetGLFunc("glUniform2f");
|
||||
pglUniform3f = GetGLFunc("glUniform3f");
|
||||
pglUniform4f = GetGLFunc("glUniform4f");
|
||||
pglUniform1fv = GetGLFunc("glUniform1fv");
|
||||
pglUniform2fv = GetGLFunc("glUniform2fv");
|
||||
pglUniform3fv = GetGLFunc("glUniform3fv");
|
||||
pglGetUniformLocation = GetGLFunc("glGetUniformLocation");
|
||||
GetGLfunc(glCreateShader);
|
||||
GetGLfunc(glShaderSource);
|
||||
GetGLfunc(glCompileShader);
|
||||
GetGLfunc(glGetShaderiv);
|
||||
GetGLfunc(glGetShaderInfoLog);
|
||||
GetGLfunc(glDeleteShader);
|
||||
GetGLfunc(glCreateProgram);
|
||||
GetGLfunc(glDeleteProgram);
|
||||
GetGLfunc(glAttachShader);
|
||||
GetGLfunc(glLinkProgram);
|
||||
GetGLfunc(glGetProgramiv);
|
||||
GetGLfunc(glGetProgramInfoLog);
|
||||
GetGLfunc(glUseProgram);
|
||||
GetGLfunc(glUniform1i);
|
||||
GetGLfunc(glUniform1f);
|
||||
GetGLfunc(glUniform2f);
|
||||
GetGLfunc(glUniform3f);
|
||||
GetGLfunc(glUniform4f);
|
||||
GetGLfunc(glUniform1fv);
|
||||
GetGLfunc(glUniform2fv);
|
||||
GetGLfunc(glUniform3fv);
|
||||
GetGLfunc(glGetUniformLocation);
|
||||
|
||||
#ifdef USE_FBO_OGL
|
||||
if (GLFramebuffer_CheckExt())
|
||||
{
|
||||
pglGenFramebuffers = GetGLFunc("glGenFramebuffers");
|
||||
pglBindFramebuffer = GetGLFunc("glBindFramebuffer");
|
||||
pglDeleteFramebuffers = GetGLFunc("glDeleteFramebuffers");
|
||||
pglFramebufferTexture2D = GetGLFunc("glFramebufferTexture2D");
|
||||
pglCheckFramebufferStatus = GetGLFunc("glCheckFramebufferStatus");
|
||||
pglGenRenderbuffers = GetGLFunc("glGenRenderbuffers");
|
||||
pglBindRenderbuffer = GetGLFunc("glBindRenderbuffer");
|
||||
pglDeleteRenderbuffers = GetGLFunc("glDeleteRenderbuffers");
|
||||
pglRenderbufferStorage = GetGLFunc("glRenderbufferStorage");
|
||||
pglFramebufferRenderbuffer = GetGLFunc("glFramebufferRenderbuffer");
|
||||
GetGLfunc(glGenFramebuffers);
|
||||
GetGLfunc(glBindFramebuffer);
|
||||
GetGLfunc(glDeleteFramebuffers);
|
||||
GetGLfunc(glFramebufferTexture2D);
|
||||
GetGLfunc(glCheckFramebufferStatus);
|
||||
GetGLfunc(glGenRenderbuffers);
|
||||
GetGLfunc(glBindRenderbuffer);
|
||||
GetGLfunc(glDeleteRenderbuffers);
|
||||
GetGLfunc(glRenderbufferStorage);
|
||||
GetGLfunc(glFramebufferRenderbuffer);
|
||||
|
||||
// check if ALL functions are availible
|
||||
if (pglGenFramebuffers && pglBindFramebuffer &&
|
||||
@@ -807,6 +819,7 @@ void SetupGLFunc4(void)
|
||||
supportFBO = true;
|
||||
}
|
||||
#endif
|
||||
#undef GetGLfunc
|
||||
}
|
||||
|
||||
boolean GL_InitShaders(void)
|
||||
@@ -956,6 +969,7 @@ static void GL_SetNoTexture(void)
|
||||
{
|
||||
if (NOTEXTURE_NUM == 0)
|
||||
pglGenTextures(1, &NOTEXTURE_NUM);
|
||||
|
||||
pglBindTexture(GL_TEXTURE_2D, NOTEXTURE_NUM);
|
||||
tex_downloaded = NOTEXTURE_NUM;
|
||||
}
|
||||
@@ -1105,10 +1119,12 @@ void GL_DeleteTexture(GLMipmap_t *pTexInfo)
|
||||
head->next->prev = head->prev;
|
||||
else // no next -> tail is being deleted -> update TexCacheTail
|
||||
TexCacheTail = head->prev;
|
||||
|
||||
if (head->prev)
|
||||
head->prev->next = head->next;
|
||||
else // no prev -> head is being deleted -> update TexCacheHead
|
||||
TexCacheHead = head->next;
|
||||
|
||||
free(head);
|
||||
break;
|
||||
}
|
||||
@@ -1129,7 +1145,7 @@ static void GL_Framebuffer_GenerateAttachments(void)
|
||||
pglBindFramebuffer(GL_FRAMEBUFFER, FramebufferObject);
|
||||
|
||||
// Generate the framebuffer texture
|
||||
if (FramebufferTexture == 0)
|
||||
if (!FramebufferTexture)
|
||||
{
|
||||
pglGenTextures(1, &FramebufferTexture);
|
||||
pglBindTexture(GL_TEXTURE_2D, FramebufferTexture);
|
||||
@@ -1143,7 +1159,7 @@ static void GL_Framebuffer_GenerateAttachments(void)
|
||||
}
|
||||
|
||||
// Generate the renderbuffer
|
||||
if (RenderbufferObject == 0)
|
||||
if (!RenderbufferObject)
|
||||
{
|
||||
pglGenRenderbuffers(1, &RenderbufferObject);
|
||||
|
||||
@@ -1165,10 +1181,10 @@ static void GL_Framebuffer_GenerateAttachments(void)
|
||||
|
||||
static void GL_Framebuffer_DeleteAttachments(void)
|
||||
{
|
||||
if (!supportFBO || fboinit == false)
|
||||
if (!supportFBO || !fboinit)
|
||||
return;
|
||||
|
||||
if (FramebufferObject == 0 && RenderbufferObject == 0 && FramebufferTexture == 0)
|
||||
if (!FramebufferObject && !RenderbufferObject && !FramebufferTexture)
|
||||
return;
|
||||
|
||||
// Unbind the framebuffer
|
||||
@@ -1192,7 +1208,7 @@ static void GL_Framebuffer_Generate(void)
|
||||
return;
|
||||
|
||||
// Generate the framebuffer
|
||||
if (FramebufferObject == 0)
|
||||
if (!FramebufferObject)
|
||||
pglGenFramebuffers(1, &FramebufferObject);
|
||||
|
||||
if (pglCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE)
|
||||
@@ -1201,7 +1217,7 @@ static void GL_Framebuffer_Generate(void)
|
||||
|
||||
static void GL_Framebuffer_Delete(void)
|
||||
{
|
||||
if (!supportFBO || fboinit == false)
|
||||
if (!supportFBO || !fboinit)
|
||||
return;
|
||||
|
||||
if (FramebufferObject)
|
||||
@@ -1213,10 +1229,10 @@ static void GL_Framebuffer_Delete(void)
|
||||
|
||||
void GL_Framebuffer_Unbind(void)
|
||||
{
|
||||
if (!supportFBO || fboinit == false)
|
||||
if (!supportFBO || !fboinit)
|
||||
return;
|
||||
|
||||
if (FramebufferObject == 0 && RenderbufferObject == 0)
|
||||
if (!FramebufferObject && !RenderbufferObject)
|
||||
return;
|
||||
|
||||
pglBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
@@ -1230,7 +1246,7 @@ void GL_Framebuffer_Enable(void)
|
||||
|
||||
if (FramebufferObject == 0)
|
||||
GL_Framebuffer_Generate();
|
||||
else if (FramebufferTexture == 0 || RenderbufferObject == 0)
|
||||
else if (!FramebufferTexture || !RenderbufferObject)
|
||||
GL_Framebuffer_GenerateAttachments();
|
||||
|
||||
pglBindFramebuffer(GL_FRAMEBUFFER, FramebufferObject);
|
||||
@@ -1239,10 +1255,10 @@ void GL_Framebuffer_Enable(void)
|
||||
|
||||
void GL_Framebuffer_Disable(void)
|
||||
{
|
||||
if (!supportFBO || fboinit == false)
|
||||
if (!supportFBO || !fboinit)
|
||||
return;
|
||||
|
||||
if (FramebufferObject == 0 && RenderbufferObject == 0)
|
||||
if (!FramebufferObject && !RenderbufferObject)
|
||||
return;
|
||||
|
||||
pglBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
@@ -1292,20 +1308,29 @@ INT32 GL_isExtAvailable(const char *extension, const GLubyte *start)
|
||||
{
|
||||
GLubyte *where, *terminator;
|
||||
|
||||
if (!extension || !start) return 0;
|
||||
if (!extension || !start)
|
||||
return 0;
|
||||
|
||||
where = (GLubyte *) strchr(extension, ' ');
|
||||
|
||||
if (where || *extension == '\0')
|
||||
return 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
where = (GLubyte *) strstr((const char *) start, extension);
|
||||
|
||||
if (!where)
|
||||
break;
|
||||
|
||||
terminator = where + strlen(extension);
|
||||
|
||||
if (where == start || *(where - 1) == ' ')
|
||||
{
|
||||
if (*terminator == ' ' || *terminator == '\0')
|
||||
return 1;
|
||||
}
|
||||
|
||||
start = terminator;
|
||||
}
|
||||
return 0;
|
||||
@@ -1337,23 +1362,33 @@ void GL_ReadScreenTexture(int tex, UINT16 *dst_data)
|
||||
{
|
||||
INT32 i;
|
||||
int dst_stride = screen_width * 3; // stride between rows of image data
|
||||
GLubyte*top = (GLvoid*)dst_data, *bottom = top + dst_stride * (screen_height - 1);
|
||||
GLubyte *top, *bottom;
|
||||
GLubyte *row;
|
||||
|
||||
row = malloc(dst_stride);
|
||||
if (!row) return;
|
||||
|
||||
if (!row)
|
||||
return;
|
||||
|
||||
top = (GLvoid*)dst_data;
|
||||
bottom = top + dst_stride * (screen_height - 1);
|
||||
|
||||
// at the time this function is called, generic2 can be found drawn on the framebuffer
|
||||
// if some other screen texture is needed, draw it to the framebuffer
|
||||
// and draw generic2 back after reading the framebuffer.
|
||||
// this hack is for some reason **much** faster than the simple solution of using glGetTexImage.
|
||||
if (tex != HWD_SCREENTEXTURE_GENERIC2)
|
||||
GL_DrawScreenTexture(tex, NULL, 0);
|
||||
|
||||
pglPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||
pglReadPixels(0, 0, screen_width, screen_height, GL_RGB, GL_UNSIGNED_BYTE, dst_data);
|
||||
|
||||
if (tex != HWD_SCREENTEXTURE_GENERIC2)
|
||||
GL_DrawScreenTexture(HWD_SCREENTEXTURE_GENERIC2, NULL, 0);
|
||||
|
||||
// Flip image upside down.
|
||||
// In other words, convert OpenGL's "bottom->top" row order into "top->bottom".
|
||||
for(i = 0; i < screen_height/2; i++)
|
||||
for (i = 0; i < screen_height/2; i++)
|
||||
{
|
||||
memcpy(row, top, dst_stride);
|
||||
memcpy(top, bottom, dst_stride);
|
||||
@@ -1361,6 +1396,7 @@ void GL_ReadScreenTexture(int tex, UINT16 *dst_data)
|
||||
top += dst_stride;
|
||||
bottom -= dst_stride;
|
||||
}
|
||||
|
||||
free(row);
|
||||
}
|
||||
|
||||
@@ -1413,10 +1449,8 @@ void GL_ClearBuffer(FBOOLEAN ColorMask, FBOOLEAN DepthMask, FBOOLEAN StencilMask
|
||||
if (ColorMask)
|
||||
{
|
||||
if (ClearColor)
|
||||
pglClearColor(ClearColor->red,
|
||||
ClearColor->green,
|
||||
ClearColor->blue,
|
||||
ClearColor->alpha);
|
||||
pglClearColor(ClearColor->red, ClearColor->green, ClearColor->blue, ClearColor->alpha);
|
||||
|
||||
ClearMask |= GL_COLOR_BUFFER_BIT;
|
||||
}
|
||||
if (DepthMask)
|
||||
@@ -1431,6 +1465,7 @@ void GL_ClearBuffer(FBOOLEAN ColorMask, FBOOLEAN DepthMask, FBOOLEAN StencilMask
|
||||
|
||||
if (StencilMask)
|
||||
ClearMask |= GL_STENCIL_BUFFER_BIT;// looks like sometimes stencil buffer needs clearing? had a problem with random black screens
|
||||
|
||||
pglClear(ClearMask);
|
||||
pglEnableClientState(GL_VERTEX_ARRAY); // We always use this one
|
||||
pglEnableClientState(GL_TEXTURE_COORD_ARRAY); // And mostly this one, too
|
||||
@@ -2055,7 +2090,7 @@ static boolean GL_Shader_CompileProgram(gl_shader_t *shader, GLint i)
|
||||
pglGetShaderiv(gl_fragShader, GL_COMPILE_STATUS, &result);
|
||||
if (result == GL_FALSE)
|
||||
{
|
||||
pglGetShaderInfoLog(gl_fragShader, 512, NULL, info_log);
|
||||
pglGetShaderInfoLog(gl_fragShader, 512, NULL, info_log);
|
||||
|
||||
GL_MSG_Error("Error compiling fragment shader: %s\n", info_log);
|
||||
pglDeleteShader(gl_vertShader);
|
||||
@@ -2093,25 +2128,25 @@ static boolean GL_Shader_CompileProgram(gl_shader_t *shader, GLint i)
|
||||
#define GETUNI(uniform) pglGetUniformLocation(shader->program, uniform);
|
||||
|
||||
// lighting
|
||||
shader->uniforms[gluniform_poly_color] = GETUNI("poly_color");
|
||||
shader->uniforms[gluniform_tint_color] = GETUNI("tint_color");
|
||||
shader->uniforms[gluniform_fade_color] = GETUNI("fade_color");
|
||||
shader->uniforms[gluniform_lighting] = GETUNI("lighting");
|
||||
shader->uniforms[gluniform_fade_start] = GETUNI("fade_start");
|
||||
shader->uniforms[gluniform_fade_end] = GETUNI("fade_end");
|
||||
shader->uniforms[gluniform_light_dir] = GETUNI("light_dir");
|
||||
shader->uniforms[gluniform_light_contrast] = GETUNI("light_contrast");
|
||||
shader->uniforms[gluniform_light_backlight] = GETUNI("light_backlight");
|
||||
shader->uniforms[gluniform_poly_color] = GETUNI("poly_color");
|
||||
shader->uniforms[gluniform_tint_color] = GETUNI("tint_color");
|
||||
shader->uniforms[gluniform_fade_color] = GETUNI("fade_color");
|
||||
shader->uniforms[gluniform_lighting] = GETUNI("lighting");
|
||||
shader->uniforms[gluniform_fade_start] = GETUNI("fade_start");
|
||||
shader->uniforms[gluniform_fade_end] = GETUNI("fade_end");
|
||||
shader->uniforms[gluniform_light_dir] = GETUNI("light_dir");
|
||||
shader->uniforms[gluniform_light_contrast] = GETUNI("light_contrast");
|
||||
shader->uniforms[gluniform_light_backlight] = GETUNI("light_backlight");
|
||||
|
||||
// palette rendering
|
||||
shader->uniforms[gluniform_palette_tex] = GETUNI("palette_tex");
|
||||
shader->uniforms[gluniform_palette_lookup_tex] = GETUNI("palette_lookup_tex");
|
||||
shader->uniforms[gluniform_lighttable_tex] = GETUNI("lighttable_tex");
|
||||
shader->uniforms[gluniform_palette_tex] = GETUNI("palette_tex");
|
||||
shader->uniforms[gluniform_palette_lookup_tex] = GETUNI("palette_lookup_tex");
|
||||
shader->uniforms[gluniform_lighttable_tex] = GETUNI("lighttable_tex");
|
||||
|
||||
shader->uniforms[gluniform_scr_resolution] = GETUNI("scr_resolution");
|
||||
shader->uniforms[gluniform_scr_resolution] = GETUNI("scr_resolution");
|
||||
|
||||
// misc.
|
||||
shader->uniforms[gluniform_leveltime] = GETUNI("leveltime");
|
||||
shader->uniforms[gluniform_leveltime] = GETUNI("leveltime");
|
||||
#undef GETUNI
|
||||
|
||||
// set permanent uniform values
|
||||
@@ -2319,49 +2354,54 @@ void GL_SetSpecialState(hwdspecialstate_t IdState, INT32 Value)
|
||||
gl_allowshaders = Value;
|
||||
break;
|
||||
case HWD_SET_TEXTUREFILTERMODE:
|
||||
|
||||
switch (Value)
|
||||
{
|
||||
case HWD_SET_TEXTUREFILTER_TRILINEAR:
|
||||
min_filter = GL_LINEAR_MIPMAP_LINEAR;
|
||||
mag_filter = GL_LINEAR;
|
||||
MipMap = GL_TRUE;
|
||||
break;
|
||||
case HWD_SET_TEXTUREFILTER_BILINEAR:
|
||||
min_filter = mag_filter = GL_LINEAR;
|
||||
switch (Value)
|
||||
{
|
||||
case HWD_SET_TEXTUREFILTER_TRILINEAR:
|
||||
min_filter = GL_LINEAR_MIPMAP_LINEAR;
|
||||
mag_filter = GL_LINEAR;
|
||||
MipMap = GL_TRUE;
|
||||
break;
|
||||
case HWD_SET_TEXTUREFILTER_BILINEAR:
|
||||
min_filter = mag_filter = GL_LINEAR;
|
||||
MipMap = GL_FALSE;
|
||||
break;
|
||||
case HWD_SET_TEXTUREFILTER_POINTSAMPLED:
|
||||
min_filter = mag_filter = GL_NEAREST;
|
||||
MipMap = GL_FALSE;
|
||||
break;
|
||||
case HWD_SET_TEXTUREFILTER_MIXED1:
|
||||
min_filter = GL_NEAREST;
|
||||
mag_filter = GL_LINEAR;
|
||||
MipMap = GL_FALSE;
|
||||
break;
|
||||
case HWD_SET_TEXTUREFILTER_MIXED2:
|
||||
min_filter = GL_LINEAR;
|
||||
mag_filter = GL_NEAREST;
|
||||
MipMap = GL_FALSE;
|
||||
break;
|
||||
case HWD_SET_TEXTUREFILTER_MIXED3:
|
||||
min_filter = GL_LINEAR_MIPMAP_LINEAR;
|
||||
mag_filter = GL_NEAREST;
|
||||
MipMap = GL_TRUE;
|
||||
break;
|
||||
default:
|
||||
min_filter = GL_NEAREST;
|
||||
mag_filter = GL_LINEAR;
|
||||
}
|
||||
|
||||
if (!supportMipMap)
|
||||
{
|
||||
MipMap = GL_FALSE;
|
||||
break;
|
||||
case HWD_SET_TEXTUREFILTER_POINTSAMPLED:
|
||||
min_filter = mag_filter = GL_NEAREST;
|
||||
MipMap = GL_FALSE;
|
||||
break;
|
||||
case HWD_SET_TEXTUREFILTER_MIXED1:
|
||||
min_filter = GL_NEAREST;
|
||||
mag_filter = GL_LINEAR;
|
||||
MipMap = GL_FALSE;
|
||||
break;
|
||||
case HWD_SET_TEXTUREFILTER_MIXED2:
|
||||
min_filter = GL_LINEAR;
|
||||
mag_filter = GL_NEAREST;
|
||||
MipMap = GL_FALSE;
|
||||
break;
|
||||
case HWD_SET_TEXTUREFILTER_MIXED3:
|
||||
min_filter = GL_LINEAR_MIPMAP_LINEAR;
|
||||
mag_filter = GL_NEAREST;
|
||||
MipMap = GL_TRUE;
|
||||
break;
|
||||
default:
|
||||
min_filter = GL_NEAREST;
|
||||
mag_filter = GL_LINEAR;
|
||||
}
|
||||
}
|
||||
|
||||
if (!supportMipMap)
|
||||
{
|
||||
MipMap = GL_FALSE;
|
||||
min_filter = GL_LINEAR;
|
||||
GL_Flush(); //??? if we want to change filter mode by texture, remove this
|
||||
}
|
||||
break;
|
||||
|
||||
GL_Flush(); //??? if we want to change filter mode by texture, remove this
|
||||
case HWD_SET_WIREFRAME:
|
||||
pglPolygonMode(GL_FRONT_AND_BACK, Value ? GL_LINE : GL_FILL);
|
||||
break;
|
||||
|
||||
case HWD_SET_TEXTURE_FORMAT:
|
||||
@@ -2699,7 +2739,7 @@ void GL_DrawModelEx(model_t *model, INT32 frameIndex, float duration, float tics
|
||||
|
||||
pglColor4ubv((GLubyte*)&Surface->PolyColor.s);
|
||||
|
||||
GL_SetBlend((poly.alpha < 1 ? Surface->PolyFlags : (PF_Masked|PF_Occlude))|PF_Modulated);
|
||||
GL_SetBlend(((poly.alpha < 1) ? Surface->PolyFlags : (PF_Masked|PF_Occlude))|PF_Modulated);
|
||||
|
||||
tint.red = byte2float[Surface->TintColor.s.red];
|
||||
tint.green = byte2float[Surface->TintColor.s.green];
|
||||
@@ -2743,9 +2783,9 @@ void GL_DrawModelEx(model_t *model, INT32 frameIndex, float duration, float tics
|
||||
if (hflipped)
|
||||
scalez = -scalez;
|
||||
|
||||
pglRotatef(pos->anglez, 0.0f, 0.0f, -1.0f);
|
||||
pglRotatef(pos->anglex, 1.0f, 0.0f, 0.0f);
|
||||
pglRotatef(pos->angley, 0.0f, -1.0f, 0.0f);
|
||||
pglRotatef(pos->anglez, 0.0f, 0.0f, -1.0f);
|
||||
pglRotatef(pos->anglex, 1.0f, 0.0f, 0.0f);
|
||||
pglRotatef(pos->angley, 0.0f, -1.0f, 0.0f);
|
||||
|
||||
if (pos->roll)
|
||||
{
|
||||
@@ -2916,8 +2956,10 @@ void GL_SetTransform(FTransform *stransform)
|
||||
if (shearing)
|
||||
{
|
||||
float dy = stransform->viewaiming * 2;
|
||||
|
||||
if (stransform->fliptype == TRANSFORM_FLIP || stransform->fliptype == TRANSFORM_MIRRORFLIP)
|
||||
dy *= -1.0f;
|
||||
|
||||
pglTranslatef(0.0f, -dy/BASEVIDHEIGHT, 0.0f);
|
||||
}
|
||||
|
||||
@@ -2969,9 +3011,9 @@ void GL_PostImgRedraw(float points[SCREENVERTS][SCREENVERTS][2])
|
||||
const float blackBack[16] =
|
||||
{
|
||||
-16.0f, -16.0f, 6.0f,
|
||||
-16.0f, 16.0f, 6.0f,
|
||||
16.0f, 16.0f, 6.0f,
|
||||
16.0f, -16.0f, 6.0f
|
||||
-16.0f, 16.0f, 6.0f,
|
||||
16.0f, 16.0f, 6.0f,
|
||||
16.0f, -16.0f, 6.0f
|
||||
};
|
||||
|
||||
if (gl_enable_screen_textures != 2)
|
||||
@@ -2993,9 +3035,9 @@ void GL_PostImgRedraw(float points[SCREENVERTS][SCREENVERTS][2])
|
||||
pglDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
pglEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
for(x = 0; x < SCREENVERTS-1;x ++)
|
||||
for (x = 0; x < (SCREENVERTS-1); x ++)
|
||||
{
|
||||
for(y = 0; y < SCREENVERTS-1; y++)
|
||||
for (y = 0; y < (SCREENVERTS-1); y++)
|
||||
{
|
||||
float stCoords[8];
|
||||
float vertCoords[12];
|
||||
@@ -3047,23 +3089,22 @@ void GL_PostImgRedraw(float points[SCREENVERTS][SCREENVERTS][2])
|
||||
void GL_FlushScreenTextures(void)
|
||||
{
|
||||
pglDeleteTextures(NUMSCREENTEXTURES, screenTextures);
|
||||
memset(screenTextures, 0 , sizeof(screenTextures));
|
||||
memset(screenTextures, 0, sizeof(screenTextures));
|
||||
}
|
||||
|
||||
void GL_DrawScreenTexture(int tex, FSurfaceInfo *surf, FBITFIELD polyflags)
|
||||
{
|
||||
float fix[8];
|
||||
float xfix, yfix;
|
||||
|
||||
const float screenVerts[12] =
|
||||
{
|
||||
-1.0f, -1.0f, 1.0f,
|
||||
-1.0f, 1.0f, 1.0f,
|
||||
1.0f, 1.0f, 1.0f,
|
||||
1.0f, -1.0f, 1.0f
|
||||
-1.0f, 1.0f, 1.0f,
|
||||
1.0f, 1.0f, 1.0f,
|
||||
1.0f, -1.0f, 1.0f
|
||||
};
|
||||
|
||||
float fix[8];
|
||||
|
||||
if (gl_enable_screen_textures != 2)
|
||||
return;
|
||||
|
||||
@@ -3108,9 +3149,9 @@ void GL_DoScreenWipe(int wipeStart, int wipeEnd)
|
||||
const float screenVerts[12] =
|
||||
{
|
||||
-1.0f, -1.0f, 1.0f,
|
||||
-1.0f, 1.0f, 1.0f,
|
||||
1.0f, 1.0f, 1.0f,
|
||||
1.0f, -1.0f, 1.0f
|
||||
-1.0f, 1.0f, 1.0f,
|
||||
1.0f, 1.0f, 1.0f,
|
||||
1.0f, -1.0f, 1.0f
|
||||
};
|
||||
|
||||
float fix[8];
|
||||
@@ -3194,9 +3235,9 @@ void GL_RenderVhsEffect(fixed_t upbary, fixed_t downbary, UINT8 updistort, UINT8
|
||||
float screenVerts[12] =
|
||||
{
|
||||
-1.0f, -1.0f, 1.0f,
|
||||
-1.0f, 1.0f, 1.0f,
|
||||
1.0f, 1.0f, 1.0f,
|
||||
1.0f, -1.0f, 1.0f
|
||||
-1.0f, 1.0f, 1.0f,
|
||||
1.0f, 1.0f, 1.0f,
|
||||
1.0f, -1.0f, 1.0f
|
||||
};
|
||||
|
||||
if (gl_enable_screen_textures != 2)
|
||||
@@ -3295,6 +3336,7 @@ void GL_MakeScreenTexture(int tex)
|
||||
// Create screen texture
|
||||
if (firstTime)
|
||||
pglGenTextures(1, &screenTextures[tex]);
|
||||
|
||||
pglBindTexture(GL_TEXTURE_2D, screenTextures[tex]);
|
||||
|
||||
if (firstTime)
|
||||
@@ -3329,6 +3371,7 @@ void GL_DrawScreenFinalTexture(int tex, INT32 width, INT32 height, boolean usesh
|
||||
|
||||
origaspect = (float)screen_width / screen_height;
|
||||
newaspect = (float)width / height;
|
||||
|
||||
if (origaspect < newaspect)
|
||||
{
|
||||
xoff = origaspect / newaspect;
|
||||
@@ -3464,8 +3507,10 @@ void GL_SetScreenPalette(RGBA_t *palette)
|
||||
if (memcmp(screenPalette, palette, sizeof(screenPalette)))
|
||||
{
|
||||
memcpy(screenPalette, palette, sizeof(screenPalette));
|
||||
|
||||
if (!screenPaletteTex)
|
||||
pglGenTextures(1, &screenPaletteTex);
|
||||
|
||||
pglActiveTexture(GL_TEXTURE2);
|
||||
pglBindTexture(GL_TEXTURE_1D, screenPaletteTex);
|
||||
pglTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
|
||||
@@ -20,6 +20,10 @@
|
||||
#ifndef _R_OPENGL_H_
|
||||
#define _R_OPENGL_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SDL
|
||||
#define _MATH_DEFINES_DEFINED
|
||||
|
||||
@@ -143,4 +147,8 @@ typedef enum
|
||||
GLF_NOTEXENV = 0x02,
|
||||
} oglflags_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+4
-4
@@ -220,9 +220,9 @@ HMS_connect (const char *format, ...)
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url);
|
||||
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
|
||||
curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
|
||||
curl_easy_setopt(curl, CURLOPT_IPRESOLVE, (long)CURL_IPRESOLVE_V4);
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT, cv_masterserver_timeout.value);
|
||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT, (long)cv_masterserver_timeout.value);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, HMS_on_read);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, buffer);
|
||||
|
||||
@@ -339,8 +339,8 @@ HMS_unlist (void)
|
||||
if (! hms)
|
||||
return 0;
|
||||
|
||||
curl_easy_setopt(hms->curl, CURLOPT_POST, 1);
|
||||
curl_easy_setopt(hms->curl, CURLOPT_POSTFIELDSIZE, 0);
|
||||
curl_easy_setopt(hms->curl, CURLOPT_POST, (long)1);
|
||||
curl_easy_setopt(hms->curl, CURLOPT_POSTFIELDSIZE, (long)0);
|
||||
|
||||
okay = HMS_do(hms);
|
||||
HMS_end(hms);
|
||||
|
||||
+166
-22
@@ -17,6 +17,7 @@
|
||||
|
||||
#include "m_menu.h" // gametype_cons_t
|
||||
#include "m_cond.h" // emblems
|
||||
#include "m_emotes.h"
|
||||
|
||||
#include "d_clisrv.h"
|
||||
|
||||
@@ -49,6 +50,7 @@
|
||||
|
||||
#include "s_sound.h" // song credits
|
||||
#include "k_kart.h"
|
||||
#include "k_hud.h"
|
||||
|
||||
#include "m_textinput.h"
|
||||
|
||||
@@ -93,6 +95,9 @@ static textinput_t w_chat;
|
||||
static boolean headsupactive = false;
|
||||
boolean hu_showscores; // draw rankings
|
||||
static char hu_tick;
|
||||
static tic_t hu_emoteanim = 0;
|
||||
#define MAXEMOTESUGGESTIONS 8
|
||||
static emote_t *emote_suggestions[MAXEMOTESUGGESTIONS] = {0};
|
||||
|
||||
static huddrawlist_h luahuddrawlist_scores;
|
||||
|
||||
@@ -259,8 +264,6 @@ INT32 HU_FallBackFrSpecialLetter(INT32 key)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static char cechotext[1024];
|
||||
static tic_t cechotimer = 0;
|
||||
static tic_t cechoduration = 5*TICRATE;
|
||||
@@ -1104,6 +1107,7 @@ void HU_Ticker(void)
|
||||
return;
|
||||
|
||||
hu_tick++;
|
||||
hu_emoteanim++;
|
||||
hu_tick &= 7; // currently only to blink chat input cursor
|
||||
|
||||
if (PLAYER1INPUTDOWN(gc_scores))
|
||||
@@ -1368,7 +1372,7 @@ boolean HU_Responder(event_t *ev)
|
||||
&& ev->data1 != gamecontrol[0][gc_talkkey][1]))
|
||||
return false;
|
||||
|
||||
M_TextInputHandle(&w_chat, c);
|
||||
M_TextInputHandleEmotes(&w_chat, c, emote_suggestions, MAXEMOTESUGGESTIONS);
|
||||
|
||||
if (c == KEY_ENTER)
|
||||
{
|
||||
@@ -1408,6 +1412,8 @@ boolean HU_Responder(event_t *ev)
|
||||
|
||||
#ifndef NONET
|
||||
|
||||
#define HU_DrawEmote(x, y, emote, flags) M_DrawEmote((x), (y), (emote), hu_emoteanim, (flags))
|
||||
|
||||
// Precompile a wordwrapped string to any given width.
|
||||
// This is a muuuch better method than V_WORDWRAP.
|
||||
// again stolen and modified a bit from video.c, don't mind me, will need to rearrange this one day.
|
||||
@@ -1419,6 +1425,8 @@ static char *CHAT_WordWrap(INT32 x, INT32 w, INT32 option, const char *string)
|
||||
size_t slen;
|
||||
char *newstring = Z_StrDup(string);
|
||||
INT32 spacewidth = (vid.width < 640) ? 8 : 4, charwidth = (vid.width < 640) ? 8 : 4;
|
||||
emote_t *emote = NULL;
|
||||
int emotelen = 0;
|
||||
|
||||
slen = strlen(string);
|
||||
x = 0;
|
||||
@@ -1440,7 +1448,12 @@ static char *CHAT_WordWrap(INT32 x, INT32 w, INT32 option, const char *string)
|
||||
c = toupper(c);
|
||||
c -= HU_FONTSTART;
|
||||
|
||||
if (c < 0 || c >= HU_FONTSIZE || !hu_font[c])
|
||||
if ((emote = M_VerifyEmote(string+i, &emotelen)))
|
||||
{
|
||||
chw = EMOTEWIDTH;
|
||||
i += emotelen-1; // Will be incremented on next loop iteration, hence -1
|
||||
}
|
||||
else if (c < 0 || c >= HU_FONTSIZE || !hu_font[c])
|
||||
{
|
||||
chw = spacewidth;
|
||||
lastusablespace = i;
|
||||
@@ -1462,7 +1475,6 @@ static char *CHAT_WordWrap(INT32 x, INT32 w, INT32 option, const char *string)
|
||||
return newstring;
|
||||
}
|
||||
|
||||
|
||||
// 30/7/18: chaty is now the distance at which the lowest point of the chat will be drawn if that makes any sense.
|
||||
|
||||
INT16 chatx = 13, chaty = 169; // let's use this as our coordinates, shh
|
||||
@@ -1495,6 +1507,8 @@ static void HU_drawMiniChat(void)
|
||||
char *msg = CHAT_WordWrap(x+2, boxw-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_mini[i-1]);
|
||||
size_t j = 0;
|
||||
INT32 linescount = 0;
|
||||
emote_t *emote = NULL;
|
||||
int emotelen = 0;
|
||||
|
||||
while(msg[j]) // iterate through msg
|
||||
{
|
||||
@@ -1519,6 +1533,11 @@ static void HU_drawMiniChat(void)
|
||||
|
||||
++j;
|
||||
}
|
||||
else if ((emote = M_VerifyEmote(msg+j, &emotelen)))
|
||||
{
|
||||
dx += EMOTEWIDTH - charwidth;
|
||||
j += emotelen;
|
||||
}
|
||||
else
|
||||
{
|
||||
j++;
|
||||
@@ -1564,6 +1583,8 @@ static void HU_drawMiniChat(void)
|
||||
size_t j = 0;
|
||||
char *msg = CHAT_WordWrap(x+2, boxw-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_mini[i]); // get the current message, and word wrap it.
|
||||
UINT8 *colormap = NULL;
|
||||
emote_t *emote = NULL;
|
||||
int emotelen = 0;
|
||||
|
||||
while(msg[j]) // iterate through msg
|
||||
{
|
||||
@@ -1590,6 +1611,16 @@ static void HU_drawMiniChat(void)
|
||||
|
||||
++j;
|
||||
}
|
||||
else if ((emote = M_VerifyEmote(msg+j, &emotelen)))
|
||||
{
|
||||
if (cv_chatbacktint.value) // on request of wolfy
|
||||
V_DrawFillConsoleMap(x + dx + 2, y+dy, EMOTEWIDTH, charheight, 239|V_SNAPTOBOTTOM|V_SNAPTOLEFT);
|
||||
|
||||
HU_DrawEmote(x+dx+2, y+dy, emote, V_SNAPTOBOTTOM|V_SNAPTOLEFT|transflag);
|
||||
dx += EMOTEWIDTH - charwidth;
|
||||
|
||||
j += emotelen;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cv_chatbacktint.value) // on request of wolfy
|
||||
@@ -1667,6 +1698,9 @@ static void HU_drawChatLog(INT32 offset)
|
||||
INT32 j = 0;
|
||||
char *msg = CHAT_WordWrap(x+2, boxw-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_log[i]); // get the current message, and word wrap it.
|
||||
UINT8 *colormap = NULL;
|
||||
emote_t *emote = NULL;
|
||||
int emotelen = 0;
|
||||
|
||||
while(msg[j]) // iterate through msg
|
||||
{
|
||||
if (msg[j] < HU_FONTSTART) // don't draw
|
||||
@@ -1688,6 +1722,15 @@ static void HU_drawChatLog(INT32 offset)
|
||||
|
||||
++j;
|
||||
}
|
||||
else if ((emote = M_VerifyEmote(msg+j, &emotelen)))
|
||||
{
|
||||
if ((y+dy+2 >= chat_topy) && (y+dy < (chat_bottomy)))
|
||||
{
|
||||
HU_DrawEmote(x+dx+2, y+dy, emote, V_SNAPTOBOTTOM|V_SNAPTOLEFT);
|
||||
dx += EMOTEWIDTH - charwidth;
|
||||
}
|
||||
j += emotelen;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((y+dy+2 >= chat_topy) && (y+dy < (chat_bottomy)))
|
||||
@@ -1813,7 +1856,7 @@ static void HU_DrawChat(void)
|
||||
typelines = 1;
|
||||
|
||||
if ((w_chat.cursor == 0 || w_chat.length == 0) && hu_tick < 4)
|
||||
V_DrawChatCharacter(chatx+2+c+charwidth*w_chat.cursor, y+1, '_'|V_SNAPTOBOTTOM|V_SNAPTOLEFT|t, !cv_allcaps.value, NULL);
|
||||
V_DrawChatCharacter(chatx+2+c, y+1, '_'|V_SNAPTOBOTTOM|V_SNAPTOLEFT|t, !cv_allcaps.value, NULL);
|
||||
|
||||
if (w_chat.select != w_chat.cursor)
|
||||
{
|
||||
@@ -1824,30 +1867,40 @@ static void HU_DrawChat(void)
|
||||
while (w_chat_buf[i])
|
||||
{
|
||||
boolean skippedline = false;
|
||||
if (w_chat.cursor == (i+1))
|
||||
emote_t *emote = NULL;
|
||||
int emotelen = 0;
|
||||
int drawwidth = charwidth; // if we've drawn emote, selection needs to account for that
|
||||
|
||||
if ((emote = M_VerifyEmote(w_chat_buf+i, &emotelen)))
|
||||
{
|
||||
HU_DrawEmote(chatx + c + 2, y-1, emote, V_SNAPTOBOTTOM|V_SNAPTOLEFT|t);
|
||||
c += EMOTEWIDTH - charwidth;
|
||||
i += emotelen-1;
|
||||
drawwidth = EMOTEWIDTH;
|
||||
}
|
||||
else if (w_chat_buf[i] >= HU_FONTSTART) //Hurdler: isn't it better like that?
|
||||
V_DrawChatCharacter(chatx + c + 2, y, w_chat_buf[i] | V_SNAPTOBOTTOM|V_SNAPTOLEFT | t, !cv_allcaps.value, NULL);
|
||||
|
||||
// Draw selection
|
||||
if (i >= select_start && i < select_end)
|
||||
V_DrawFill(chatx + c + 2 - (drawwidth-charwidth), y-1, drawwidth, charheight, 103|V_TRANSLUCENT|V_SNAPTOBOTTOM|V_SNAPTOLEFT|t);
|
||||
|
||||
++i;
|
||||
|
||||
if (w_chat.cursor == i)
|
||||
{
|
||||
INT32 cursorx = (c+charwidth < boxw-charwidth) ? (chatx + 2 + c+charwidth) : (chatx+1); // we may have to go down.
|
||||
INT32 cursory = (cursorx != chatx+1) ? (y) : (y+charheight);
|
||||
if (hu_tick < 4)
|
||||
V_DrawChatCharacter(cursorx, cursory+1, '_' |V_SNAPTOBOTTOM|V_SNAPTOLEFT|t, !cv_allcaps.value, NULL);
|
||||
|
||||
if (cursorx == chatx+1 && saylen == i) // a weirdo hack
|
||||
if (cursorx == chatx+1 && saylen == i-1) // a weirdo hack
|
||||
{
|
||||
typelines += 1;
|
||||
skippedline = true;
|
||||
}
|
||||
}
|
||||
|
||||
//Hurdler: isn't it better like that?
|
||||
if (w_chat_buf[i] >= HU_FONTSTART)
|
||||
V_DrawChatCharacter(chatx + c + 2, y, w_chat_buf[i] | V_SNAPTOBOTTOM|V_SNAPTOLEFT | t, !cv_allcaps.value, NULL);
|
||||
|
||||
// Draw selection
|
||||
if (i >= select_start && i < select_end)
|
||||
V_DrawFill(chatx + c + 2, y-1, charwidth, charheight, 103|V_TRANSLUCENT|V_SNAPTOBOTTOM|V_SNAPTOLEFT|t);
|
||||
|
||||
++i;
|
||||
|
||||
c += charwidth;
|
||||
if (c > boxw-(charwidth*2) && !skippedline)
|
||||
{
|
||||
@@ -1857,6 +1910,36 @@ static void HU_DrawChat(void)
|
||||
}
|
||||
}
|
||||
|
||||
if (emote_suggestions[0])
|
||||
{
|
||||
// A bit of copy-paste from /pm code :p
|
||||
INT32 suggesty = chaty - charheight - 1;
|
||||
size_t longest_suggestion_length = 0;
|
||||
|
||||
for (i = 0; i < MAXEMOTESUGGESTIONS && emote_suggestions[i]; ++i)
|
||||
{
|
||||
longest_suggestion_length = max(longest_suggestion_length, strlen(emote_suggestions[i]->name));
|
||||
}
|
||||
|
||||
#ifdef NETSPLITSCREEN
|
||||
if (splitscreen)
|
||||
{
|
||||
suggesty -= BASEVIDHEIGHT/2;
|
||||
if (splitscreen > 1)
|
||||
suggesty += 16;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
suggesty -= (cv_kartspeedometer.value ? 16 : 0);
|
||||
|
||||
for (i = 0; i < MAXEMOTESUGGESTIONS && emote_suggestions[i]; ++i)
|
||||
{
|
||||
V_DrawFillConsoleMap(chatx + boxw + 2, suggesty - (7*i), (longest_suggestion_length+2)*4 + EMOTEWIDTH, 6, 239|V_SNAPTOBOTTOM|V_SNAPTOLEFT);
|
||||
V_DrawSmallString(chatx + boxw + 4 + EMOTEWIDTH, suggesty - (7*i), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, va(":%s:", emote_suggestions[i]->name));
|
||||
HU_DrawEmote(chatx + boxw + 2, suggesty - i*7, emote_suggestions[i], V_SNAPTOBOTTOM|V_SNAPTOLEFT);
|
||||
}
|
||||
}
|
||||
|
||||
// handle /pm list. It's messy, horrible and I don't care.
|
||||
if (strnicmp(w_chat_buf, "/pm", 3) == 0 && vid.width >= 400 && !teamtalk) // 320x200 unsupported kthxbai
|
||||
{
|
||||
@@ -2133,7 +2216,7 @@ void HU_TickSongCredits(void)
|
||||
}
|
||||
}
|
||||
|
||||
void HU_DrawSongCredits(void)
|
||||
static void HU_DrawSongCreditsVanilla(void)
|
||||
{
|
||||
char *str;
|
||||
INT32 len;
|
||||
@@ -2141,9 +2224,6 @@ void HU_DrawSongCredits(void)
|
||||
INT32 y = (splitscreen ? (BASEVIDHEIGHT/2)-4 : 32);
|
||||
INT32 bgt;
|
||||
|
||||
if (!cursongcredit.def) // No def
|
||||
return;
|
||||
|
||||
str = va("\x1F"" %s", cursongcredit.def->source);
|
||||
len = V_ThinStringWidth(str, V_ALLOWLOWERCASE|V_6WIDTHSPACE);
|
||||
destx = (len + 7) * FRACUNIT;
|
||||
@@ -2173,6 +2253,70 @@ void HU_DrawSongCredits(void)
|
||||
V_DrawRightAlignedThinString(cursongcredit.x / FRACUNIT, y, V_ALLOWLOWERCASE|V_6WIDTHSPACE|V_SNAPTOLEFT|(cursongcredit.trans<<V_ALPHASHIFT), str);
|
||||
}
|
||||
|
||||
#define BOXCREDITSLIDEIN (5*TICRATE-TICRATE/2)
|
||||
#define BOXCREDITSLIDEOUT (TICRATE/2)
|
||||
#define BOXCREDITHEIGHT 8
|
||||
static void HU_DrawSongCreditsBox(void)
|
||||
{
|
||||
char *str = cursongcredit.def->source;
|
||||
INT32 strwidth = V_SmallStringWidth(str, V_ALLOWLOWERCASE) + 4;
|
||||
|
||||
// dup dup dup dup
|
||||
INT32 dup = min(vid.dupx, vid.dupy);
|
||||
|
||||
// Center it
|
||||
INT32 x = (BASEVIDWIDTH/2 - strwidth/2)*dup + ((vid.width - (BASEVIDWIDTH * vid.dupx)) / 2);
|
||||
INT32 y = 0;
|
||||
|
||||
INT32 flags = V_SNAPTOTOP|V_NOSCALESTART;
|
||||
INT32 t = cursongcredit.anim;
|
||||
INT32 bgt;
|
||||
|
||||
fixed_t interpoffset = FixedMul(BOXCREDITHEIGHT*dup*FRACUNIT/(TICRATE/2), R_GetHudUncap());
|
||||
|
||||
if (t > BOXCREDITSLIDEIN)
|
||||
{
|
||||
// Sliding in
|
||||
t = TICRATE/2 - (t - BOXCREDITSLIDEIN);
|
||||
y = -BOXCREDITHEIGHT*dup + (FixedMul(BOXCREDITHEIGHT*FRACUNIT, FixedDiv(t*FRACUNIT, TICRATE*FRACUNIT/2))*dup + interpoffset)/FRACUNIT;
|
||||
}
|
||||
else if (t < TICRATE/2)
|
||||
{
|
||||
// Sliding out
|
||||
y = -BOXCREDITHEIGHT*dup + (FixedMul(BOXCREDITHEIGHT*FRACUNIT, FixedDiv(t*FRACUNIT, TICRATE*FRACUNIT/2))*dup - interpoffset)/FRACUNIT;
|
||||
}
|
||||
|
||||
bgt = (NUMTRANSMAPS/2) + (cursongcredit.trans/2);
|
||||
|
||||
if (bgt < NUMTRANSMAPS)
|
||||
{
|
||||
V_DrawFill(x, y, strwidth*dup, BOXCREDITHEIGHT*dup, 28|flags|(bgt<<V_ALPHASHIFT));
|
||||
V_DrawFill(x+dup, y+dup, (strwidth-2)*dup, (BOXCREDITHEIGHT-2)*dup, 30|flags|(bgt<<V_ALPHASHIFT));
|
||||
}
|
||||
if (cursongcredit.trans < NUMTRANSMAPS)
|
||||
{
|
||||
V_DrawSmallString(x+2*dup, y+2*dup, V_ALLOWLOWERCASE|flags|(cursongcredit.trans<<V_ALPHASHIFT), str);
|
||||
}
|
||||
}
|
||||
|
||||
void HU_DrawSongCredits(void)
|
||||
{
|
||||
if (!cursongcredit.def) // No def
|
||||
return;
|
||||
|
||||
switch (cv_songcredits.value)
|
||||
{
|
||||
case 1:
|
||||
HU_DrawSongCreditsVanilla();
|
||||
break;
|
||||
case 2:
|
||||
HU_DrawSongCreditsBox();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Heads up displays drawer, call each frame
|
||||
//
|
||||
|
||||
@@ -13,6 +13,10 @@
|
||||
#ifndef __I_JOY_H__
|
||||
#define __I_JOY_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "g_input.h"
|
||||
|
||||
/*!
|
||||
@@ -55,4 +59,8 @@ typedef struct JoyType_s JoyType_t;
|
||||
|
||||
extern JoyType_t Joystick[MAXSPLITSCREENPLAYERS];
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // __I_JOY_H__
|
||||
@@ -14,6 +14,10 @@
|
||||
#ifndef __I_NET__
|
||||
#define __I_NET__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface
|
||||
#endif
|
||||
@@ -180,4 +184,8 @@ extern bannednode_t *bannednode;
|
||||
/// \brief Called by D_SRB2Main to be defined by extern network driver
|
||||
boolean I_InitNetwork(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -13,6 +13,10 @@
|
||||
#ifndef __I_SOUND__
|
||||
#define __I_SOUND__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "sounds.h"
|
||||
#include "command.h"
|
||||
@@ -241,4 +245,8 @@ boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void));
|
||||
boolean I_FadeOutStopSong(UINT32 ms);
|
||||
boolean I_FadeInPlaySong(UINT32 ms, boolean looping);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -14,6 +14,10 @@
|
||||
#ifndef __I_SYSTEM__
|
||||
#define __I_SYSTEM__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "d_ticcmd.h"
|
||||
#include "d_event.h"
|
||||
|
||||
@@ -256,4 +260,8 @@ const char *I_ClipboardPaste(void);
|
||||
|
||||
void I_RegisterSysCommands(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -14,6 +14,10 @@
|
||||
#ifndef I_THREADS_H
|
||||
#define I_THREADS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void (*I_thread_fn)(void *userdata);
|
||||
|
||||
typedef void * I_mutex;
|
||||
@@ -35,5 +39,9 @@ void I_hold_cond (I_cond *, I_mutex);
|
||||
void I_wake_one_cond (I_cond *);
|
||||
void I_wake_all_cond (I_cond *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif/*I_THREADS_H*/
|
||||
#endif/*HAVE_THREADS*/
|
||||
+10
-8
@@ -37,18 +37,20 @@ tic_t I_GetTime(void)
|
||||
|
||||
void I_InitializeTime(void)
|
||||
{
|
||||
g_time.time = 0;
|
||||
g_time.timefrac = 0;
|
||||
|
||||
enterprecise = 0;
|
||||
oldenterprecise = 0;
|
||||
tictimer = 0.0;
|
||||
|
||||
CV_RegisterVar(&cv_timescale);
|
||||
|
||||
// I_StartupTimer is preserved for potential subsystems that need to setup
|
||||
// timing information for I_GetPreciseTime and sleeping
|
||||
I_StartupTimer();
|
||||
|
||||
g_time.time = 0;
|
||||
g_time.timefrac = 0;
|
||||
|
||||
enterprecise = I_GetPreciseTime();
|
||||
oldenterprecise = enterprecise;
|
||||
entertic = 0;
|
||||
oldentertics = 0;
|
||||
tictimer = 0.0;
|
||||
}
|
||||
|
||||
void I_UpdateTime(fixed_t timescale)
|
||||
@@ -61,7 +63,7 @@ void I_UpdateTime(fixed_t timescale)
|
||||
ticratescaled = (double)TICRATE * FixedToFloat(timescale);
|
||||
|
||||
enterprecise = I_GetPreciseTime();
|
||||
elapsedseconds = (double)((INT64)enterprecise - oldenterprecise) / I_GetPrecisePrecision();
|
||||
elapsedseconds = (double)(enterprecise - oldenterprecise) / I_GetPrecisePrecision();
|
||||
tictimer += elapsedseconds;
|
||||
while (tictimer > 1.0/ticratescaled)
|
||||
{
|
||||
|
||||
@@ -14,6 +14,10 @@
|
||||
#ifndef __I_VIDEO__
|
||||
#define __I_VIDEO__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "doomtype.h"
|
||||
|
||||
#ifdef __GNUG__
|
||||
@@ -149,4 +153,8 @@ boolean UseScreenFBO(void);
|
||||
extern boolean downsample;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+4788
File diff suppressed because it is too large.
Load diff
+81
@@ -0,0 +1,81 @@
|
||||
// SONIC ROBO BLAST 2 KART
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2018-2020 by Kart Krew
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \file k_hud.h
|
||||
/// \brief HUD drawing functions exclusive to Kart
|
||||
|
||||
#ifndef __K_HUD__
|
||||
#define __K_HUD__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "d_player.h" // Need for player_t
|
||||
#include "command.h"
|
||||
#include "r_defs.h"
|
||||
|
||||
UINT8 K_GetHudColor(void);
|
||||
boolean K_UseColorHud(void);
|
||||
boolean K_UseHighResPortraits(void);
|
||||
patch_t *K_GetFacePrefix(player_t *player, INT32 skinnum);
|
||||
|
||||
void K_RegisterKartHudStuff(void);
|
||||
|
||||
extern consvar_t cv_colorizedhud,
|
||||
cv_colorizeditembox,
|
||||
cv_colorizedhudcolor;
|
||||
|
||||
extern consvar_t cv_darkitembox;
|
||||
extern consvar_t cv_biglaps;
|
||||
extern consvar_t cv_highresportrait;
|
||||
extern consvar_t cv_stat_xoffset, cv_stat_yoffset;
|
||||
extern consvar_t cv_showstats;
|
||||
extern consvar_t cv_fancyroulette;
|
||||
extern consvar_t cv_showlaptimes;
|
||||
extern consvar_t cv_battlespeedo;
|
||||
extern consvar_t cv_multiitemicon;
|
||||
extern consvar_t cv_huditemamount;
|
||||
|
||||
#define NUMSPEEDOSTUFF 8
|
||||
extern CV_PossibleValue_t speedo_cons_t[NUMSPEEDOSTUFF];
|
||||
#define NUMDGAUGESTUFF 6
|
||||
extern CV_PossibleValue_t driftgaugestyle_cons_t[NUMDGAUGESTUFF];
|
||||
#define NUMINPUTDISPLAYSTUFF 5
|
||||
extern CV_PossibleValue_t inputdisplay_cons_t[NUMINPUTDISPLAYSTUFF];
|
||||
#define NUMMINIMAPDOTSTUFF 5
|
||||
extern CV_PossibleValue_t minimapdot_cons_t[NUMMINIMAPDOTSTUFF];
|
||||
|
||||
const char *K_GetItemPatch(UINT8 item, boolean tiny);
|
||||
INT32 K_calcSplitFlags(INT32 snapflags);
|
||||
void K_LoadKartHUDGraphics(void);
|
||||
void K_drawKartHUD(void);
|
||||
void K_drawKartFreePlay(UINT32 flashtime);
|
||||
void K_drawKartTimestamp(tic_t drawtime, INT32 TX, INT32 TY, INT16 emblemmap, UINT8 mode);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
INT32 x;
|
||||
INT32 y;
|
||||
INT32 flags;
|
||||
} drawinfo_t;
|
||||
|
||||
patch_t *K_getItemBoxPatch(boolean small, boolean dark);
|
||||
patch_t *K_getItemMulPatch(boolean small);
|
||||
void K_getItemBoxDrawinfo(drawinfo_t *out);
|
||||
INT32 K_getMinimapTrans(void);
|
||||
void K_getLapsDrawinfo(drawinfo_t *out);
|
||||
void K_getMinimapDrawinfo(drawinfo_t *out);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
// =========================================================================
|
||||
#endif // __K_HUD__
|
||||
+33
-4757
File diff suppressed because it is too large.
Load diff
+9
-44
@@ -6,6 +6,10 @@
|
||||
#ifndef __K_KART__
|
||||
#define __K_KART__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "d_player.h" // Need for player_t
|
||||
|
||||
@@ -18,9 +22,6 @@ extern const UINT8 KartColor_Opposite[MAXSKINCOLORS*2];
|
||||
void K_RainbowColormap(UINT8 *dest_colormap, UINT8 skincolor);
|
||||
void K_GenerateKartColormap(UINT8 *dest_colormap, INT32 skinnum, UINT8 color, boolean local);
|
||||
UINT8 K_GetKartColorByName(const char *name);
|
||||
UINT8 K_GetHudColor(void);
|
||||
boolean K_UseColorHud(void);
|
||||
boolean K_UseHighResPortraits(void);
|
||||
|
||||
void K_RegisterServerKartStuff(void);
|
||||
void K_RegisterClientKartStuff(void);
|
||||
@@ -29,30 +30,11 @@ extern consvar_t cv_coloredspeedlines, cv_coloredsneakertrail;
|
||||
extern consvar_t cv_bananajitter;
|
||||
extern consvar_t cv_bananthrowroll;
|
||||
extern consvar_t cv_airsparks;
|
||||
extern consvar_t cv_colorizedhud, cv_colorizeditembox, cv_colorizedhudcolor;
|
||||
extern consvar_t cv_darkitembox;
|
||||
extern consvar_t cv_biglaps;
|
||||
extern consvar_t cv_highresportrait;
|
||||
extern consvar_t cv_stat_xoffset, cv_stat_yoffset;
|
||||
extern consvar_t cv_showstats;
|
||||
extern consvar_t cv_fancyroulette;
|
||||
extern consvar_t cv_showlaptimes;
|
||||
extern consvar_t cv_battlespeedo;
|
||||
extern consvar_t cv_multiitemicon;
|
||||
extern consvar_t cv_huditemamount;
|
||||
|
||||
#define NUMSPEEDOSTUFF 8
|
||||
extern CV_PossibleValue_t speedo_cons_t[NUMSPEEDOSTUFF];
|
||||
#define NUMDGAUGESTUFF 6
|
||||
extern CV_PossibleValue_t driftgaugestyle_cons_t[NUMDGAUGESTUFF];
|
||||
#define NUMINPUTDISPLAYSTUFF 5
|
||||
extern CV_PossibleValue_t inputdisplay_cons_t[NUMINPUTDISPLAYSTUFF];
|
||||
#define NUMMINIMAPDOTSTUFF 5
|
||||
extern CV_PossibleValue_t minimapdot_cons_t[NUMMINIMAPDOTSTUFF];
|
||||
|
||||
|
||||
boolean K_IsPlayerLosing(player_t *player);
|
||||
boolean K_IsPlayerWanted(player_t *player);
|
||||
INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed, boolean spbrush);
|
||||
INT32 K_FindUseodds(player_t *player, fixed_t mashed, INT32 pingame, INT32 bestbumper, boolean spbrush, boolean dontforcespb);
|
||||
void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid);
|
||||
void K_FlipFromObject(mobj_t *mo, mobj_t *master);
|
||||
void K_MatchGenericExtraFlags(mobj_t *mo, mobj_t *master);
|
||||
@@ -111,26 +93,9 @@ void K_PlayOvertakeSound(mobj_t *source);
|
||||
void K_PlayHitEmSound(mobj_t *source, mobj_t *victim);
|
||||
void K_PlayPowerGloatSound(mobj_t *source);
|
||||
|
||||
const char *K_GetItemPatch(UINT8 item, boolean tiny);
|
||||
INT32 K_calcSplitFlags(INT32 snapflags);
|
||||
void K_LoadKartHUDGraphics(void);
|
||||
void K_drawKartHUD(void);
|
||||
void K_drawKartFreePlay(UINT32 flashtime);
|
||||
void K_drawKartTimestamp(tic_t drawtime, INT32 TX, INT32 TY, INT16 emblemmap, UINT8 mode);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
INT32 x;
|
||||
INT32 y;
|
||||
INT32 flags;
|
||||
} drawinfo_t;
|
||||
|
||||
patch_t *K_getItemBoxPatch(boolean small, boolean dark);
|
||||
patch_t *K_getItemMulPatch(boolean small);
|
||||
void K_getItemBoxDrawinfo(drawinfo_t *out);
|
||||
INT32 K_getMinimapTrans(void);
|
||||
void K_getLapsDrawinfo(drawinfo_t *out);
|
||||
void K_getMinimapDrawinfo(drawinfo_t *out);
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
// =========================================================================
|
||||
#endif // __K_KART__
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "p_slopes.h" // P_GetZAt
|
||||
#include "z_zone.h"
|
||||
#include "r_main.h"
|
||||
#include "r_skins.h"
|
||||
#include "r_things.h"
|
||||
#include "m_random.h"
|
||||
#include "s_sound.h"
|
||||
@@ -24,6 +25,7 @@
|
||||
#include "hu_stuff.h" // HU_AddChatText
|
||||
#include "console.h"
|
||||
#include "k_kart.h" // SRB2Kart
|
||||
#include "k_hud.h" // SRB2Kart
|
||||
#include "d_netcmd.h" // IsPlayerAdmin
|
||||
#include "d_main.h"
|
||||
|
||||
|
||||
@@ -55,6 +55,7 @@
|
||||
X (PlayerQuit),\
|
||||
X (PlayerThink),/* P_PlayerThink */\
|
||||
X (MusicChange),\
|
||||
X (MusicCredit),\
|
||||
X (ShouldSpin),/*SRB2KART*/\
|
||||
X (ShouldExplode),/*SRB2KART*/\
|
||||
X (ShouldSquish),/*SRB2KART*/\
|
||||
@@ -130,6 +131,7 @@ int LUA_HookPlayerCanDamage(player_t *, mobj_t *);
|
||||
void LUA_HookPlayerQuit(player_t *, int);
|
||||
int LUA_HookPlayerCmd(player_t *, ticcmd_t *);
|
||||
int LUA_HookMusicChange(const char *oldname, struct MusicChange *);
|
||||
int LUA_HookMusicCredit(musicdef_t *musicdef);
|
||||
|
||||
int LUA_HookShouldSpin(player_t *player, mobj_t *inflictor, mobj_t *source); // SRB2KART: Should player be spun out?
|
||||
int LUA_HookShouldExplode(player_t *player, mobj_t *inflictor, mobj_t *source); // SRB2KART: Should player be exploded?
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "doomstat.h"
|
||||
#include "p_mobj.h"
|
||||
#include "g_game.h"
|
||||
#include "r_skins.h"
|
||||
#include "r_things.h"
|
||||
#include "b_bot.h"
|
||||
#include "z_zone.h"
|
||||
@@ -1065,6 +1066,18 @@ int LUA_HookMusicChange(const char *oldname, struct MusicChange *param)
|
||||
return hook.status;
|
||||
}
|
||||
|
||||
int LUA_HookMusicCredit(musicdef_t *musicdef)
|
||||
{
|
||||
Hook_State hook;
|
||||
if (prepare_hook(&hook, 0, HOOK(MusicCredit)))
|
||||
{
|
||||
LUA_PushUserdata(gL, musicdef, META_MUSICDEF);
|
||||
call_hooks(&hook, 1, res_true);
|
||||
}
|
||||
|
||||
return hook.status;
|
||||
}
|
||||
|
||||
static int kartdamage_hook
|
||||
(
|
||||
player_t *player,
|
||||
|
||||
+5
-16
@@ -24,6 +24,7 @@
|
||||
#include "w_wad.h"
|
||||
#include "z_zone.h"
|
||||
#include "k_kart.h"
|
||||
#include "k_hud.h" // SRB2kart
|
||||
|
||||
#include "lua_script.h"
|
||||
#include "lua_libs.h"
|
||||
@@ -1260,15 +1261,10 @@ extern int lib_hudadd(lua_State *L);
|
||||
|
||||
static int lib_hudsetvotebackground(lua_State *L)
|
||||
{
|
||||
memset(VoteScreen.luaPrefix, 0, sizeof(VoteScreen.luaPrefix));
|
||||
|
||||
if (lua_isnoneornil(L, 1))
|
||||
{
|
||||
if (luaVoteScreen)
|
||||
{
|
||||
free(luaVoteScreen);
|
||||
}
|
||||
|
||||
luaVoteScreen = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1279,15 +1275,8 @@ static int lib_hudsetvotebackground(lua_State *L)
|
||||
return luaL_argerror(L, 1, "prefix should 4 characters wide");
|
||||
}
|
||||
|
||||
if (!luaVoteScreen)
|
||||
{
|
||||
luaVoteScreen = (char*)malloc(5);
|
||||
luaVoteScreen[4] = 0;
|
||||
}
|
||||
|
||||
strncpy(luaVoteScreen, prefix, 4);
|
||||
|
||||
strupr(luaVoteScreen);
|
||||
strncpy(VoteScreen.luaPrefix, prefix, 4);
|
||||
strupr(VoteScreen.luaPrefix);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "dehacked.h"
|
||||
#include "p_mobj.h"
|
||||
#include "p_local.h"
|
||||
#include "s_sound.h"
|
||||
#include "z_zone.h"
|
||||
|
||||
#include "lua_script.h"
|
||||
@@ -1072,6 +1073,109 @@ static int sfxinfo_num(lua_State *L)
|
||||
return 1;
|
||||
}
|
||||
|
||||
enum musicdef_e {
|
||||
musicdef_name = 0,
|
||||
musicdef_usage,
|
||||
musicdef_source,
|
||||
musicdef_filename,
|
||||
musicdef_title,
|
||||
musicdef_alttitle,
|
||||
musicdef_authors,
|
||||
};
|
||||
|
||||
const char *const musicdef_opt[] = {
|
||||
"name",
|
||||
"usage",
|
||||
"source",
|
||||
"filename",
|
||||
"title",
|
||||
"alttitle",
|
||||
"authors",
|
||||
NULL
|
||||
};
|
||||
|
||||
static int musicdef_fields_ref = LUA_NOREF;
|
||||
|
||||
static int lib_sFindMusicCredit(lua_State *L)
|
||||
{
|
||||
const char *name = luaL_checkstring(L, 1);
|
||||
LUA_PushUserdata(L, S_FindMusicCredit(name), META_MUSICDEF);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lib_getMusicDef(lua_State *L)
|
||||
{
|
||||
musicdef_t *def = NULL;
|
||||
|
||||
if (lua_isnumber(L, 2))
|
||||
def = S_GetMusicCredit(lua_tonumber(L, 2));
|
||||
else if (lua_isstring(L, 2))
|
||||
def = S_FindMusicCredit(lua_tostring(L, 2));
|
||||
else
|
||||
return luaL_error(L, "musicdefs index must be number or string (got %s)", luaL_typename(L, 2));
|
||||
|
||||
LUA_PushUserdata(L, def, META_MUSICDEF);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lib_setMusicDef(lua_State *L)
|
||||
{
|
||||
return luaL_error(L, "musicdefs is read only");
|
||||
}
|
||||
|
||||
static int lib_musicdefslen(lua_State *L)
|
||||
{
|
||||
lua_pushinteger(L, nummusicdefs);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int musicdef_get(lua_State *L)
|
||||
{
|
||||
musicdef_t *musicdef = *((musicdef_t **)luaL_checkudata(L, 1, META_MUSICDEF));
|
||||
enum musicdef_e field = Lua_optoption(L, 2, -1, musicdef_fields_ref);
|
||||
|
||||
I_Assert(musicdef != NULL);
|
||||
|
||||
switch (field)
|
||||
{
|
||||
case musicdef_name:
|
||||
lua_pushstring(L, musicdef->name);
|
||||
return 1;
|
||||
case musicdef_usage:
|
||||
lua_pushstring(L, musicdef->usage);
|
||||
return 1;
|
||||
case musicdef_source:
|
||||
lua_pushstring(L, musicdef->source);
|
||||
return 1;
|
||||
case musicdef_filename:
|
||||
lua_pushstring(L, musicdef->filename);
|
||||
return 1;
|
||||
case musicdef_title:
|
||||
lua_pushstring(L, musicdef->title);
|
||||
return 1;
|
||||
case musicdef_alttitle:
|
||||
lua_pushstring(L, musicdef->alttitle);
|
||||
return 1;
|
||||
case musicdef_authors:
|
||||
lua_pushstring(L, musicdef->authors);
|
||||
return 1;
|
||||
default:
|
||||
return luaL_error(L, LUA_QL("musicdef_t") " has no field named " LUA_QS, lua_tostring(L, 2));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int musicdef_num(lua_State *L)
|
||||
{
|
||||
musicdef_t *musicdef = *((musicdef_t **)luaL_checkudata(L, 1, META_MUSICDEF));
|
||||
|
||||
I_Assert(musicdef != NULL);
|
||||
|
||||
lua_pushinteger(L, musicdef->num);
|
||||
return 1;
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
//
|
||||
// Now push all these functions into the Lua state!
|
||||
@@ -1126,6 +1230,18 @@ int LUA_InfoLib(lua_State *L)
|
||||
|
||||
sfxinfo_fields_ref = Lua_CreateFieldTable(L, sfxinfo_opt);
|
||||
|
||||
luaL_newmetatable(L, META_MUSICDEF);
|
||||
lua_pushcfunction(L, musicdef_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, musicdef_num);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_pop(L, 1);
|
||||
|
||||
musicdef_fields_ref = Lua_CreateFieldTable(L, musicdef_opt);
|
||||
|
||||
lua_register(L, "S_FindMusicCredit", lib_sFindMusicCredit);
|
||||
|
||||
lua_newuserdata(L, 0);
|
||||
lua_createtable(L, 0, 2);
|
||||
lua_pushcfunction(L, lib_getSprname);
|
||||
@@ -1176,5 +1292,19 @@ int LUA_InfoLib(lua_State *L)
|
||||
lua_pushvalue(L, -1);
|
||||
lua_setglobal(L, "S_sfx");
|
||||
lua_setglobal(L, "sfxinfo");
|
||||
|
||||
lua_newuserdata(L, 0);
|
||||
lua_createtable(L, 0, 2);
|
||||
lua_pushcfunction(L, lib_getMusicDef);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, lib_setMusicDef);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
|
||||
lua_pushcfunction(L, lib_musicdefslen);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_setmetatable(L, -2);
|
||||
lua_setglobal(L, "musicdefs");
|
||||
|
||||
return 0;
|
||||
}
|
||||
+5
-1
@@ -10,6 +10,9 @@
|
||||
/// \file lua_libs.h
|
||||
/// \brief libraries for Lua scripting
|
||||
|
||||
#include "doomtype.h"
|
||||
#include "blua/lua.h"
|
||||
|
||||
extern lua_State *gL;
|
||||
|
||||
#define LREG_VALID "VALID_USERDATA"
|
||||
@@ -20,6 +23,7 @@ extern lua_State *gL;
|
||||
#define META_STATE "STATE_T*"
|
||||
#define META_MOBJINFO "MOBJINFO_T*"
|
||||
#define META_SFXINFO "SFXINFO_T*"
|
||||
#define META_MUSICDEF "MUSICDEF_T*"
|
||||
|
||||
#define META_MOBJ "MOBJ_T*"
|
||||
#define META_MAPTHING "MAPTHING_T*"
|
||||
@@ -68,4 +72,4 @@ int LUA_SkinLib(lua_State *L);
|
||||
int LUA_ThinkerLib(lua_State *L);
|
||||
int LUA_MapLib(lua_State *L);
|
||||
int LUA_BlockmapLib(lua_State *L);
|
||||
int LUA_HudLib(lua_State *L);
|
||||
int LUA_HudLib(lua_State *L);
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "doomdef.h"
|
||||
#include "fastcmp.h"
|
||||
#include "r_things.h"
|
||||
#include "r_skins.h"
|
||||
#include "r_main.h"
|
||||
#include "p_local.h"
|
||||
#include "g_game.h"
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "doomdef.h"
|
||||
#include "fastcmp.h"
|
||||
#include "r_main.h"
|
||||
#include "r_skins.h"
|
||||
#include "r_things.h"
|
||||
#include "p_mobj.h"
|
||||
#include "d_player.h"
|
||||
|
||||
+2
-1
@@ -12,6 +12,7 @@
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "fastcmp.h"
|
||||
#include "r_skins.h"
|
||||
#include "r_things.h"
|
||||
#include "sounds.h"
|
||||
|
||||
@@ -277,4 +278,4 @@ int LUA_SkinLib(lua_State *L)
|
||||
lua_setglobal(L, "skins");
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
+4
-4
@@ -495,7 +495,7 @@ static void GIF_rgbconvert(UINT8 *linear, UINT8 *scr)
|
||||
static void GIF_framewrite(void)
|
||||
{
|
||||
UINT8 *p;
|
||||
UINT8 *movie_screen = screens[2];
|
||||
UINT8 *movie_screen = vid.screens[2];
|
||||
INT32 blitx, blity, blitw, blith;
|
||||
|
||||
if (!gifframe_data)
|
||||
@@ -509,7 +509,7 @@ static void GIF_framewrite(void)
|
||||
if (gif_optimize && gif_frames > 0)
|
||||
{
|
||||
// before blit movie_screen points to last frame, cur_screen points to this frame
|
||||
UINT8 *cur_screen = screens[0];
|
||||
UINT8 *cur_screen = vid.screens[0];
|
||||
GIF_optimizeregion(cur_screen, movie_screen, &blitx, &blity, &blitw, &blith);
|
||||
|
||||
// blit to temp screen
|
||||
@@ -535,7 +535,7 @@ static void GIF_framewrite(void)
|
||||
if (rendermode == render_opengl)
|
||||
{
|
||||
UINT8 *linear = HWR_GetScreenshot();
|
||||
GIF_rgbconvert(linear, screens[0]);
|
||||
GIF_rgbconvert(linear, vid.screens[0]);
|
||||
//free(linear); // Allocated 'statically', no need to free now
|
||||
}
|
||||
#endif
|
||||
@@ -545,7 +545,7 @@ static void GIF_framewrite(void)
|
||||
if (gif_frames == 0 && rendermode == render_soft)
|
||||
I_ReadScreen(movie_screen);
|
||||
|
||||
movie_screen = screens[0];
|
||||
movie_screen = vid.screens[0];
|
||||
}
|
||||
|
||||
// screen regions are handled in GIF_lzw
|
||||
|
||||
@@ -14,6 +14,10 @@
|
||||
#ifndef __M_ARGV__
|
||||
#define __M_ARGV__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//
|
||||
// MISC
|
||||
//
|
||||
@@ -42,4 +46,8 @@ const char *M_GetNextParm(void);
|
||||
// Finds and loads a response file (@moreargs.txt)
|
||||
void M_FindResponseFile(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif //__M_ARGV__
|
||||
@@ -0,0 +1,262 @@
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <cstring>
|
||||
|
||||
#include "m_emotes.h"
|
||||
|
||||
extern "C" {
|
||||
#include "w_wad.h"
|
||||
#include "z_zone.h"
|
||||
#include "hu_stuff.h"
|
||||
#include "v_video.h"
|
||||
}
|
||||
|
||||
consvar_t cv_emotes = {"emotes", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};;
|
||||
|
||||
static std::map<std::string, emote_t> emotes;
|
||||
|
||||
// TODO - Would be really nice to generalize soc-like file parsing and not reimplement it 100 times :)))))
|
||||
void M_LoadEmotes(UINT16 wadnum)
|
||||
{
|
||||
UINT16 lumpnum = W_CheckNumForNamePwad("EMOTES", wadnum, 0);
|
||||
|
||||
if (lumpnum == INT16_MAX)
|
||||
return;
|
||||
|
||||
char *lump = static_cast<char*>(W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE));
|
||||
size_t size = W_LumpLengthPwad(wadnum, lumpnum);
|
||||
|
||||
std::istringstream file(std::string(lump, size));
|
||||
std::string line;
|
||||
|
||||
emote_t *emote = nullptr;
|
||||
std::string emote_name;
|
||||
|
||||
// Just smol lambda to remove all the trailing chars we might not want
|
||||
auto trim = [](std::string &str) {
|
||||
str.erase(0, str.find_first_not_of(" \t\n\r\f\v"));
|
||||
str.erase(str.find_last_not_of(" \t\n\r\f\v")+1);
|
||||
};
|
||||
|
||||
int numemotes = 0;
|
||||
int linenum = 0;
|
||||
|
||||
while (std::getline(file, line))
|
||||
{
|
||||
++linenum;
|
||||
|
||||
trim(line);
|
||||
|
||||
if (line.empty())
|
||||
continue;
|
||||
|
||||
size_t split = line.find('=');
|
||||
|
||||
// Didn't find the =, means we're about to parse `Emote <name>`
|
||||
if (split == line.npos)
|
||||
{
|
||||
split = line.find(' ');
|
||||
|
||||
if (split == line.npos)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, "EMOTES: Unrecognized line. (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strnicmp(line.c_str(), "emote", 5))
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, "EMOTES: 'Emote' expected. (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum);
|
||||
continue;
|
||||
}
|
||||
|
||||
emote_name = line.substr(split+1);
|
||||
|
||||
if (emote_name.find_first_of(" \t\n\r\f\v:") != emote_name.npos)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, "EMOTES: Emote name cannot contain spaces or ':' symbols. (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (emote_name.size() > MAXEMOTENAME)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, "EMOTES: Emote name is too long, truncating. (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum);
|
||||
emote_name = emote_name.substr(0, MAXEMOTENAME);
|
||||
}
|
||||
|
||||
emote = &emotes[emote_name];
|
||||
strlcpy(emote->name, emote_name.c_str(), MAXEMOTENAME);
|
||||
|
||||
emote->timeperframe = 1;
|
||||
emote->numframes = 0;
|
||||
std::memset(emote->frames, 0, sizeof(emote->frames));
|
||||
|
||||
++numemotes;
|
||||
}
|
||||
else if (emote)
|
||||
{
|
||||
std::string field = line.substr(0, split);
|
||||
std::string value = line.substr(split+1);
|
||||
|
||||
trim(field);
|
||||
trim(value);
|
||||
|
||||
if (stricmp(field.c_str(), "frames") == 0)
|
||||
{
|
||||
UINT8 numframes = 0;
|
||||
|
||||
auto copy_frame = [&] {
|
||||
if (numframes == MAXEMOTEFRAMES)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, "EMOTES: Too many frames. (file %s, line %d)", wadfiles[wadnum]->filename, linenum);
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t list_split = value.find(',');
|
||||
std::string framelumpname = value.substr(0, list_split);
|
||||
trim(framelumpname);
|
||||
|
||||
if (list_split == value.npos)
|
||||
value = "";
|
||||
else
|
||||
value = value.substr(list_split+1, value.npos);
|
||||
|
||||
// End of list of frames
|
||||
if (framelumpname.size() == 0)
|
||||
return false;
|
||||
|
||||
if (framelumpname.size() > 8)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, "EMOTES: Frame %d name is too long. (file %s, line %d)", numframes, wadfiles[wadnum]->filename, linenum);
|
||||
framelumpname = framelumpname.substr(0, 8);
|
||||
}
|
||||
|
||||
std::strncpy(emote->frames[numframes], framelumpname.c_str(), framelumpname.size()+1);
|
||||
|
||||
++numframes;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
while (copy_frame()) {}
|
||||
|
||||
if (numframes == 0)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, "EMOTES: Expected list of frames. (file %s, line %d)", wadfiles[wadnum]->filename, linenum);
|
||||
}
|
||||
|
||||
emote->numframes = numframes;
|
||||
}
|
||||
else if (stricmp(field.c_str(), "timeperframe") == 0)
|
||||
{
|
||||
emote->timeperframe = std::stoi(value);
|
||||
|
||||
if (emote->timeperframe <= 0)
|
||||
{
|
||||
emote->timeperframe = 1;
|
||||
CONS_Alert(CONS_WARNING, "EMOTES: Bad value for 'timeperframe'. (file %s, line %d)", wadfiles[wadnum]->filename, linenum);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, "EMOTES: Unrecognized field '%s'. (file %s, line %d)", field.c_str(), wadfiles[wadnum]->filename, linenum);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, "EMOTES: Unrecognized line. (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum);
|
||||
}
|
||||
}
|
||||
|
||||
CONS_Printf("Added %d emotes\n", numemotes);
|
||||
}
|
||||
|
||||
void M_InitEmotes(void)
|
||||
{
|
||||
UINT16 i;
|
||||
for (i = 0; i < numwadfiles; i++)
|
||||
M_LoadEmotes(i);
|
||||
}
|
||||
|
||||
emote_t *M_FindEmote(const char *name, int len, int skip)
|
||||
{
|
||||
if (!cv_emotes.value)
|
||||
return nullptr;
|
||||
|
||||
char query[MAXEMOTENAME+1] = {0};
|
||||
std::strncpy(query, name, std::min(len, MAXEMOTENAME));
|
||||
|
||||
for (auto &pair: emotes)
|
||||
{
|
||||
if (pair.first.rfind(query, 0, std::min(len, MAXEMOTENAME)) != 0)
|
||||
continue;
|
||||
|
||||
if (skip > 0)
|
||||
{
|
||||
--skip;
|
||||
continue;
|
||||
}
|
||||
|
||||
return &pair.second;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
emote_t *M_VerifyEmote(const char *name, int *emotelen)
|
||||
{
|
||||
if (*name != ':')
|
||||
return nullptr;
|
||||
|
||||
if (!cv_emotes.value)
|
||||
return nullptr;
|
||||
|
||||
const char *p = name+1; // skip ':'
|
||||
emote_t *match = nullptr;
|
||||
|
||||
while (*p && (p - name) < MAXEMOTENAME)
|
||||
{
|
||||
if (*p == ':')
|
||||
{
|
||||
std::string checkname = std::string(name+1, (p-name)-1);
|
||||
auto it = emotes.find(checkname);
|
||||
|
||||
if (it != emotes.end())
|
||||
match = &it->second;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
++p;
|
||||
}
|
||||
|
||||
if (match && emotelen)
|
||||
*emotelen = p-name+1;
|
||||
|
||||
return match;
|
||||
}
|
||||
|
||||
void M_DrawEmote(INT32 x, INT32 y, emote_t *emote, tic_t anim, INT32 flags)
|
||||
{
|
||||
if (emote->numframes == 0)
|
||||
return;
|
||||
|
||||
const char *lumpname = emote->frames[(anim/emote->timeperframe) % emote->numframes];
|
||||
patch_t *emotepatch = (patch_t*)W_CachePatchName(lumpname, PU_CACHE);
|
||||
|
||||
const int CHARHEIGHT = 6;
|
||||
|
||||
fixed_t scale = FRACUNIT;
|
||||
|
||||
x *= FRACUNIT;
|
||||
y *= FRACUNIT;
|
||||
|
||||
if (emotepatch->width > EMOTEWIDTH)
|
||||
scale = (FRACUNIT/emotepatch->width)*EMOTEWIDTH;
|
||||
else if (emotepatch->width < EMOTEWIDTH)
|
||||
x += (EMOTEWIDTH-emotepatch->width)*FRACUNIT/2;
|
||||
|
||||
y -= (scale*emotepatch->height-CHARHEIGHT*FRACUNIT)/2;
|
||||
|
||||
V_DrawFixedPatch(x, y, scale, flags, emotepatch, NULL);
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
#ifndef __M_EMOTES__
|
||||
#define __M_EMOTES__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "command.h"
|
||||
|
||||
extern consvar_t cv_emotes;
|
||||
|
||||
#define MAXEMOTENAME 32
|
||||
#define MAXEMOTEFRAMES 32
|
||||
#define EMOTEWIDTH 6
|
||||
|
||||
typedef struct emote_s {
|
||||
char name[MAXEMOTENAME+1];
|
||||
char frames[MAXEMOTEFRAMES][9];
|
||||
UINT8 numframes;
|
||||
tic_t timeperframe;
|
||||
} emote_t;
|
||||
|
||||
// Reads and adds emotes from EMOTES lump, with syntax similar to soc
|
||||
void M_LoadEmotes(UINT16 wadnum);
|
||||
|
||||
// Load emotes from all base wads
|
||||
void M_InitEmotes(void);
|
||||
|
||||
// Finds first matching emote, ignoring first few matches
|
||||
emote_t *M_FindEmote(const char *name, int len, int skips);
|
||||
|
||||
// If first character is not ':', instantly returns null
|
||||
// Starts from ':' character, goes until it finds ':' or end of string
|
||||
// If end of string is found, or closing ':' is found but resulting emote name doesn't exist,
|
||||
// it returns null, otherwise it returns emote and stores into *emotelen how much characters
|
||||
// needs to be skipped to get past emote name
|
||||
emote_t *M_VerifyEmote(const char *name, int *emotelen);
|
||||
|
||||
// Draw the emote, anim should be some kind of timer ticking every game tic
|
||||
// for animated emotes
|
||||
void M_DrawEmote(INT32 x, INT32 y, emote_t *emote, tic_t anim, INT32 flags);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // __M_EMOTES__
|
||||
@@ -15,6 +15,10 @@
|
||||
#ifndef __M_FIXED__
|
||||
#define __M_FIXED__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "doomtype.h"
|
||||
#ifdef __GNUC__
|
||||
#include <stdlib.h>
|
||||
@@ -49,6 +53,20 @@ FUNCMATH FUNCINLINE static ATTRINLINE fixed_t FloatToFixed(float f)
|
||||
return (fixed_t)(f * FRACUNIT);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief convert fixed_t into double-precision floating number
|
||||
*/
|
||||
|
||||
FUNCMATH FUNCINLINE static ATTRINLINE double FixedToDouble(fixed_t x)
|
||||
{
|
||||
return x / (double)FRACUNIT;
|
||||
}
|
||||
|
||||
FUNCMATH FUNCINLINE static ATTRINLINE fixed_t DoubleToFixed(double f)
|
||||
{
|
||||
return (fixed_t)(f * FRACUNIT);
|
||||
}
|
||||
|
||||
// for backwards compat
|
||||
#define FIXED_TO_FLOAT(x) FixedToFloat(x) // (((float)(x)) / ((float)FRACUNIT))
|
||||
#define FLOAT_TO_FIXED(f) FloatToFixed(f) // (fixed_t)((f) * ((float)FRACUNIT))
|
||||
@@ -356,4 +374,8 @@ void FM_MultMatrix(matrix_t *dest, const matrix_t *multme);
|
||||
void FM_Translate(matrix_t *dest, fixed_t x, fixed_t y, fixed_t z);
|
||||
void FM_Scale(matrix_t *dest, fixed_t x, fixed_t y, fixed_t z);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif //m_fixed.h
|
||||
+127
-105
@@ -70,6 +70,7 @@
|
||||
#include "st_stuff.h"
|
||||
#include "i_sound.h"
|
||||
#include "k_kart.h" // SRB2kart
|
||||
#include "k_hud.h" // SRB2kart
|
||||
#include "k_stats.h" // SRB2kart
|
||||
#include "d_player.h" // KITEM_ constants
|
||||
|
||||
@@ -2188,29 +2189,30 @@ static menuitem_t OP_SaturnMenu[] =
|
||||
|
||||
{IT_STRING | IT_CVAR, NULL, "Minimum Input Delay", &cv_mindelay, 20},
|
||||
{IT_STRING | IT_CVAR, NULL, "Gentlemens Ping", &cv_gentlemens, 25},
|
||||
{IT_STRING | IT_CVAR, NULL, "Server Info Screen", &cv_serverinfoscreen, 30},
|
||||
|
||||
{IT_STRING | IT_CVAR, NULL, "Skin Select Spinning Speed", &cv_skinselectspin, 35},
|
||||
{IT_STRING | IT_CVAR, NULL, "Skin Select Spinning Speed", &cv_skinselectspin, 40},
|
||||
|
||||
{IT_STRING | IT_CVAR, NULL, "Colorized Speedlines", &cv_coloredspeedlines, 45},
|
||||
{IT_STRING | IT_CVAR, NULL, "Colorized Sneakertrails", &cv_coloredsneakertrail, 50},
|
||||
{IT_STRING | IT_CVAR, NULL, "Colorized Speedlines", &cv_coloredspeedlines, 50},
|
||||
{IT_STRING | IT_CVAR, NULL, "Colorized Sneakertrails", &cv_coloredsneakertrail, 55},
|
||||
|
||||
{IT_STRING | IT_CVAR, NULL, "Player Blendeffects", &cv_playerblendeffects, 60},
|
||||
{IT_STRING | IT_CVAR, NULL, "Player Blendeffects", &cv_playerblendeffects, 65},
|
||||
|
||||
{IT_STRING | IT_CVAR, NULL, "Bananadrag Jitter", &cv_bananajitter, 70},
|
||||
{IT_STRING | IT_CVAR, NULL, "Bananadrag Jitter", &cv_bananajitter, 75},
|
||||
|
||||
{IT_STRING | IT_CVAR, NULL, "Midair Driftsparks", &cv_airsparks, 80},
|
||||
{IT_STRING | IT_CVAR, NULL, "Midair Driftsparks", &cv_airsparks, 85},
|
||||
|
||||
{IT_STRING | IT_CVAR, NULL, "Show Localskin Menus", &cv_showlocalskinmenus, 90},
|
||||
{IT_STRING | IT_CVAR, NULL, "Show Localskin Menus", &cv_showlocalskinmenus, 95},
|
||||
|
||||
{IT_STRING | IT_CVAR, NULL, "Uppercase Menu", &cv_menucaps, 100},
|
||||
{IT_STRING | IT_CVAR, NULL, "Uppercase Menu", &cv_menucaps, 105},
|
||||
|
||||
{IT_STRING | IT_CVAR, NULL, "Keyboard Layout", &cv_keyboardlayout, 110},
|
||||
{IT_STRING | IT_CVAR, NULL, "Keyboard Layout", &cv_keyboardlayout, 115},
|
||||
|
||||
{IT_STRING | IT_CVAR, NULL, "Less Midnight Channel Flicker", &cv_lessflicker, 120},
|
||||
{IT_STRING | IT_CVAR, NULL, "Less Midnight Channel Flicker", &cv_lessflicker, 125},
|
||||
|
||||
{IT_SUBMENU|IT_STRING, NULL, "Saturn Hud...", &OP_SaturnHudDef, 130},
|
||||
{IT_SUBMENU|IT_STRING, NULL, "Sprite Distortion...", &OP_PlayerDistortDef, 135},
|
||||
{IT_SUBMENU|IT_STRING, NULL, "Saturn Credits", &OP_SaturnCreditsDef, 140}, // uwu
|
||||
{IT_SUBMENU|IT_STRING, NULL, "Saturn Hud...", &OP_SaturnHudDef, 135},
|
||||
{IT_SUBMENU|IT_STRING, NULL, "Sprite Distortion...", &OP_PlayerDistortDef, 140},
|
||||
{IT_SUBMENU|IT_STRING, NULL, "Saturn Credits", &OP_SaturnCreditsDef, 145}, // uwu
|
||||
};
|
||||
|
||||
static const char* OP_SaturnTooltips[] =
|
||||
@@ -2219,6 +2221,7 @@ static const char* OP_SaturnTooltips[] =
|
||||
"How long can the game wait before it kicks you out from the server\nconnecting screen.",
|
||||
"Practice for online play! 0 = instant response.",
|
||||
"Simulate online input delay when hosting a server.\nValue choosen by Player with the lowest ping",
|
||||
"Show a screen before joining a server displaying important information about it",
|
||||
"How much speen do you want?",
|
||||
"Colourize the speedlines in your skincolor if you go fast enough!",
|
||||
"Colourize the sneaker flame trails in your skincolor!",
|
||||
@@ -2321,44 +2324,46 @@ static menuitem_t OP_SaturnHudMenu[] =
|
||||
{
|
||||
{IT_HEADER, NULL, "Saturn Hud Options", NULL, 0},
|
||||
|
||||
{IT_STRING | IT_CVAR, NULL, "Speedometer Style", &cv_newspeedometer, 10},
|
||||
{IT_STRING | IT_CVAR, NULL, "Battle Speedometer", &cv_battlespeedo, 15},
|
||||
{IT_STRING|IT_CVAR, NULL, "Speedometer Style", &cv_newspeedometer, 10},
|
||||
{IT_STRING|IT_CVAR, NULL, "Battle Speedometer", &cv_battlespeedo, 15},
|
||||
|
||||
{IT_STRING | IT_CVAR, NULL, "Colourized HUD", &cv_colorizedhud, 25},
|
||||
{IT_STRING | IT_CVAR, NULL, "Colourized Itembox", &cv_colorizeditembox, 30},
|
||||
{IT_STRING | IT_CVAR, NULL, "Colourized HUD Color", &cv_colorizedhudcolor, 35},
|
||||
{IT_STRING|IT_CVAR, NULL, "Colourized HUD", &cv_colorizedhud, 25},
|
||||
{IT_STRING|IT_CVAR, NULL, "Colourized Itembox", &cv_colorizeditembox, 30},
|
||||
{IT_STRING|IT_CVAR, NULL, "Colourized HUD Color", &cv_colorizedhudcolor, 35},
|
||||
|
||||
{IT_STRING | IT_CVAR, NULL, "Input Display", &cv_showinput, 45},
|
||||
{IT_STRING|IT_CVAR, NULL, "Input Display", &cv_showinput, 45},
|
||||
|
||||
{IT_STRING | IT_CVAR, NULL, "Stat Display", &cv_showstats, 55},
|
||||
{IT_STRING|IT_CVAR, NULL, "Stat Display", &cv_showstats, 55},
|
||||
|
||||
{IT_STRING | IT_CVAR, NULL, "Higher Resolution Portraits", &cv_highresportrait, 65},
|
||||
{IT_STRING|IT_CVAR, NULL, "Higher Resolution Portraits", &cv_highresportrait, 65},
|
||||
|
||||
{IT_STRING | IT_CVAR, NULL, "Small Positionnumber", &cv_smallposnum, 75},
|
||||
{IT_STRING | IT_CVAR, NULL, "Positionnumber Animation", &cv_posanim, 80},
|
||||
{IT_STRING|IT_CVAR, NULL, "Small Positionnumber", &cv_smallposnum, 75},
|
||||
{IT_STRING|IT_CVAR, NULL, "Positionnumber Animation", &cv_posanim, 80},
|
||||
|
||||
{IT_STRING | IT_CVAR, NULL, "Flash Lap Times", &cv_showlaptimes, 90},
|
||||
{IT_STRING|IT_CVAR, NULL, "Flash Lap Times", &cv_showlaptimes, 90},
|
||||
|
||||
{IT_STRING | IT_CVAR, NULL, "Multi-Item icons", &cv_multiitemicon, 100},
|
||||
{IT_STRING | IT_CVAR, NULL, "Item Amount Number", &cv_huditemamount, 105},
|
||||
{IT_STRING | IT_CVAR, NULL, "Animated Roulette", &cv_fancyroulette, 110},
|
||||
{IT_STRING|IT_CVAR, NULL, "Multi-Item icons", &cv_multiitemicon, 100},
|
||||
{IT_STRING|IT_CVAR, NULL, "Item Amount Number", &cv_huditemamount, 105},
|
||||
{IT_STRING|IT_CVAR, NULL, "Animated Roulette", &cv_fancyroulette, 110},
|
||||
|
||||
{IT_STRING | IT_CVAR, NULL, "Show Lap Emblem", &cv_showlapemblem, 120},
|
||||
{IT_STRING | IT_CVAR, NULL, "Show Cecho Messages", &cv_cechotoggle, 125},
|
||||
{IT_STRING|IT_CVAR, NULL, "Show Lap Emblem", &cv_showlapemblem, 120},
|
||||
{IT_STRING|IT_CVAR, NULL, "Show Cecho Messages", &cv_cechotoggle, 125},
|
||||
|
||||
{IT_STRING | IT_CVAR, NULL, "Show Names on Minimap", &cv_showminimapnames, 135},
|
||||
{IT_STRING | IT_CVAR, NULL, "Small Minimap Players", &cv_minihead, 140},
|
||||
{IT_STRING | IT_CVAR, NULL, "Spin Minimap Icons", &cv_spinoutroll, 145},
|
||||
{IT_STRING | IT_CVAR, NULL, "Player Angle Visual", &cv_showminimapangle, 150},
|
||||
{IT_STRING|IT_CVAR, NULL, "Show Names on Minimap", &cv_showminimapnames, 135},
|
||||
{IT_STRING|IT_CVAR, NULL, "Small Minimap Players", &cv_minihead, 140},
|
||||
{IT_STRING|IT_CVAR, NULL, "Spin Minimap Icons", &cv_spinoutroll, 145},
|
||||
{IT_STRING|IT_CVAR, NULL, "Player Angle Visual", &cv_showminimapangle, 150},
|
||||
|
||||
{IT_STRING | IT_CVAR, NULL, "Beta Intermissionscreen", &cv_betainterscreen, 160},
|
||||
{IT_STRING|IT_CVAR, NULL, "Music Credits", &cv_songcredits, 160},
|
||||
|
||||
{IT_STRING | IT_CVAR, NULL, "Show Director Prompt", &cv_showdirectorhud, 170},
|
||||
{IT_STRING|IT_CVAR, NULL, "Beta Intermissionscreen", &cv_betainterscreen, 170},
|
||||
|
||||
{IT_STRING | IT_SUBMENU, NULL, "Nametags...", &OP_NametagDef, 180},
|
||||
{IT_STRING | IT_SUBMENU, NULL, "Driftgauge...", &OP_DriftGaugeDef, 185},
|
||||
{IT_STRING|IT_CVAR, NULL, "Show Director Prompt", &cv_showdirectorhud, 180},
|
||||
|
||||
{IT_SUBMENU|IT_STRING, NULL, "Hud Offsets...", &OP_HudOffsetDef, 195},
|
||||
{IT_STRING|IT_SUBMENU, NULL, "Nametags...", &OP_NametagDef, 190},
|
||||
{IT_STRING|IT_SUBMENU, NULL, "Driftgauge...", &OP_DriftGaugeDef, 195},
|
||||
|
||||
{IT_SUBMENU|IT_STRING, NULL, "Hud Offsets...", &OP_HudOffsetDef, 205},
|
||||
};
|
||||
|
||||
static const char* OP_SaturnHudTooltips[] =
|
||||
@@ -2384,6 +2389,7 @@ static const char* OP_SaturnHudTooltips[] =
|
||||
"Minimize the player icons on the minimap.",
|
||||
"Erratically rotate player icons during spinouts.",
|
||||
"Visualize the player facing angle.",
|
||||
"Show the Music Credits and which style.",
|
||||
"Make the Intermission screen look like in beta versions of Kart!\nEither with background or just the rest.",
|
||||
"Show the Director Toggle prompt when spectating.",
|
||||
"Nametag Options.",
|
||||
@@ -2414,6 +2420,7 @@ enum
|
||||
sh_smallmap,
|
||||
sh_iconspinout,
|
||||
sh_minidot,
|
||||
sh_songcred,
|
||||
sh_betainter,
|
||||
sh_directorhud,
|
||||
sh_nametagmen,
|
||||
@@ -2466,39 +2473,38 @@ static menuitem_t OP_HudOffsetMenu[] =
|
||||
|
||||
static menuitem_t OP_SaturnCreditsMenu[] =
|
||||
{
|
||||
{IT_HEADER, NULL, "Saturn Credits", NULL, 0},
|
||||
{IT_HEADER, NULL, "Thanks to all contributers <3", NULL, 0},
|
||||
|
||||
{IT_HEADER, NULL, "Thanks to all contributers <3", NULL, 7},
|
||||
{IT_STRING2+IT_SPACE, NULL, "Alug", NULL, 10},
|
||||
{IT_STRING2+IT_SPACE, NULL, "Indev", NULL, 20},
|
||||
{IT_STRING2+IT_SPACE, NULL, "Haya", NULL, 30},
|
||||
{IT_STRING2+IT_SPACE, NULL, "Nepdisk", NULL, 40},
|
||||
{IT_STRING2+IT_SPACE, NULL, "GenericHeroGuy", NULL, 50},
|
||||
{IT_STRING2+IT_SPACE, NULL, "xyzzy", NULL, 60},
|
||||
{IT_STRING2+IT_SPACE, NULL, "Chearii", NULL, 70},
|
||||
|
||||
{IT_STRING2+IT_SPACE, NULL, "Alug", NULL, 17},
|
||||
{IT_STRING2+IT_SPACE, NULL, "Indev", NULL, 27},
|
||||
{IT_STRING2+IT_SPACE, NULL, "Haya", NULL, 37},
|
||||
{IT_STRING2+IT_SPACE, NULL, "Nepdisk", NULL, 47},
|
||||
{IT_STRING2+IT_SPACE, NULL, "GenericHeroGuy", NULL, 57},
|
||||
{IT_STRING2+IT_SPACE, NULL, "xyzzy", NULL, 67},
|
||||
{IT_STRING2+IT_SPACE, NULL, "Chearii", NULL, 77},
|
||||
{IT_STRING2+IT_SPACE, NULL, "Sunflower", NULL, 80},
|
||||
{IT_STRING2+IT_SPACE, NULL, "Yuz", NULL, 90},
|
||||
{IT_STRING2+IT_SPACE, NULL, "Democrab", NULL, 100},
|
||||
{IT_STRING2+IT_SPACE, NULL, "EXpand", NULL, 110},
|
||||
{IT_STRING2+IT_SPACE, NULL, "Nexit", NULL, 120},
|
||||
{IT_STRING2+IT_SPACE, NULL, "Spee", NULL, 130},
|
||||
{IT_STRING2+IT_SPACE, NULL, "jin", NULL, 140},
|
||||
{IT_STRING2+IT_SPACE, NULL, "riomccloud", NULL, 150},
|
||||
{IT_STRING2+IT_SPACE, NULL, "chromaticpipe", NULL, 160},
|
||||
{IT_STRING2+IT_SPACE, NULL, "Achii", NULL, 170},
|
||||
{IT_STRING2+IT_SPACE, NULL, "Anonimus", NULL, 180},
|
||||
{IT_STRING2+IT_SPACE, NULL, "scizor300", NULL, 190},
|
||||
{IT_STRING2+IT_SPACE, NULL, "Lugent", NULL, 200},
|
||||
|
||||
{IT_STRING2+IT_SPACE, NULL, "Sunflower aka AnimeSonic", NULL, 87},
|
||||
{IT_STRING2+IT_SPACE, NULL, "Yuz aka Yuzler", NULL, 97},
|
||||
{IT_STRING2+IT_SPACE, NULL, "Democrab", NULL, 107},
|
||||
{IT_STRING2+IT_SPACE, NULL, "EXpand", NULL, 117},
|
||||
{IT_STRING2+IT_SPACE, NULL, "Nexit", NULL, 127},
|
||||
{IT_STRING2+IT_SPACE, NULL, "Spee", NULL, 137},
|
||||
{IT_STRING2+IT_SPACE, NULL, "jin", NULL, 147},
|
||||
{IT_STRING2+IT_SPACE, NULL, "riomccloud", NULL, 157},
|
||||
{IT_STRING2+IT_SPACE, NULL, "chromaticpipe", NULL, 167},
|
||||
{IT_STRING2+IT_SPACE, NULL, "Achii", NULL, 177},
|
||||
{IT_STRING2+IT_SPACE, NULL, "Anonimus", NULL, 187},
|
||||
{IT_STRING2+IT_SPACE, NULL, "scizor300", NULL, 197},
|
||||
{IT_HEADER, NULL, "Special Thanks <3", NULL, 168},
|
||||
|
||||
{IT_HEADER, NULL, "Special Thanks <3", NULL, 167},
|
||||
{IT_STRING2+IT_SPACE, NULL, "All of Sunflower's Garden", NULL, 178},
|
||||
{IT_STRING2+IT_SPACE, NULL, "The Moe Mansion and Birdhouse Team", NULL, 188},
|
||||
{IT_STRING2+IT_SPACE, NULL, "Galactice for Galaxy", NULL, 198},
|
||||
|
||||
{IT_STRING2+IT_SPACE, NULL, "All of Sunflower's Garden", NULL, 177},
|
||||
{IT_STRING2+IT_SPACE, NULL, "The Moe Mansion and Birdhouse Team", NULL, 187},
|
||||
{IT_STRING2+IT_SPACE, NULL, "Galactice for Galaxy", NULL, 197},
|
||||
|
||||
{IT_STRING+IT_SPACE, NULL, "", NULL, 207}, // dummy text I
|
||||
{IT_STRING, NULL, "", NULL, 267}, // dummy text II
|
||||
{IT_STRING+IT_SPACE, NULL, "", NULL, 198}, // dummy text I
|
||||
{IT_STRING, NULL, "", NULL, 258}, // dummy text II
|
||||
};
|
||||
|
||||
// sry we dont have space for this anymore :/
|
||||
@@ -3600,8 +3606,8 @@ static void M_ChangeCvar(INT32 choice)
|
||||
char s[20];
|
||||
float increment;
|
||||
|
||||
increment = (currentMenu->menuitems[itemOn].status & IT_CV_BIGFLOAT) ? 0.5f : (1.0f/16.0f);
|
||||
sprintf(s, "%f",FIXED_TO_FLOAT(cv->value)+(choice)*increment);
|
||||
increment = FIXED_TO_FLOAT(cv->value)+(choice)*((currentMenu->menuitems[itemOn].status & IT_CV_BIGFLOAT) ? 0.5f : (1.0f/16.0f));
|
||||
sprintf(s,"%ld%s",(long)increment,M_Ftrim(increment));
|
||||
CV_Set(cv, s);
|
||||
}
|
||||
else
|
||||
@@ -7167,8 +7173,11 @@ static void DrawReplayHutReplayInfo(void)
|
||||
if (mapheaderinfo[demolist[dir_on[menudepthleft]].map-1])
|
||||
{
|
||||
char *title = G_BuildMapTitle(demolist[dir_on[menudepthleft]].map);
|
||||
V_DrawString(x, y, V_SNAPTOTOP|MENUCAPS, title);
|
||||
Z_Free(title);
|
||||
if (title)
|
||||
{
|
||||
V_DrawString(x, y, V_SNAPTOTOP|MENUCAPS, title);
|
||||
Z_Free(title);
|
||||
}
|
||||
}
|
||||
else
|
||||
V_DrawString(x, y, V_SNAPTOTOP|V_ALLOWLOWERCASE|V_TRANSLUCENT, "Level is not loaded.");
|
||||
@@ -8120,6 +8129,9 @@ UINT8 skyRoomMenuTranslations[MAXUNLOCKABLES];
|
||||
|
||||
static char *M_GetConditionString(condition_t cond)
|
||||
{
|
||||
char *title = NULL;
|
||||
char *response = NULL;
|
||||
|
||||
switch(cond.type)
|
||||
{
|
||||
case UC_PLAYTIME:
|
||||
@@ -8146,33 +8158,45 @@ static char *M_GetConditionString(condition_t cond)
|
||||
G_TicsToSeconds(cond.requirement));
|
||||
case UC_MAPVISITED:
|
||||
{
|
||||
char *title = G_BuildMapTitle(cond.requirement-1);
|
||||
char *response = va("Visit %s", title);
|
||||
Z_Free(title);
|
||||
title = G_BuildMapTitle(cond.requirement-1);
|
||||
if (title)
|
||||
{
|
||||
response = va("Visit %s", title);
|
||||
Z_Free(title);
|
||||
}
|
||||
return response;
|
||||
}
|
||||
case UC_MAPBEATEN:
|
||||
{
|
||||
char *title = G_BuildMapTitle(cond.requirement-1);
|
||||
char *response = va("Beat %s", title);
|
||||
Z_Free(title);
|
||||
title = G_BuildMapTitle(cond.requirement-1);
|
||||
if (title)
|
||||
{
|
||||
response = va("Beat %s", title);
|
||||
Z_Free(title);
|
||||
}
|
||||
return response;
|
||||
}
|
||||
case UC_MAPALLEMERALDS:
|
||||
{
|
||||
char *title = G_BuildMapTitle(cond.requirement-1);
|
||||
char *response = va("Beat %s w/ all emeralds", title);
|
||||
Z_Free(title);
|
||||
title = G_BuildMapTitle(cond.requirement-1);
|
||||
if (title)
|
||||
{
|
||||
response = va("Beat %s w/ all emeralds", title);
|
||||
Z_Free(title);
|
||||
}
|
||||
return response;
|
||||
}
|
||||
case UC_MAPTIME:
|
||||
{
|
||||
char *title = G_BuildMapTitle(cond.extrainfo1-1);
|
||||
char *response = va("Beat %s in %i:%02i.%02i", title,
|
||||
G_TicsToMinutes(cond.requirement, true),
|
||||
G_TicsToSeconds(cond.requirement),
|
||||
G_TicsToCentiseconds(cond.requirement));
|
||||
Z_Free(title);
|
||||
title = G_BuildMapTitle(cond.extrainfo1-1);
|
||||
if (title)
|
||||
{
|
||||
response = va("Beat %s in %i:%02i.%02i", title,
|
||||
G_TicsToMinutes(cond.requirement, true),
|
||||
G_TicsToSeconds(cond.requirement),
|
||||
G_TicsToCentiseconds(cond.requirement));
|
||||
Z_Free(title);
|
||||
}
|
||||
return response;
|
||||
}
|
||||
case UC_TOTALEMBLEMS:
|
||||
@@ -8458,7 +8482,7 @@ static void M_MusicTest(INT32 choice)
|
||||
{
|
||||
(void)choice;
|
||||
|
||||
if (!S_PrepareSoundTest())
|
||||
if (!nummusicdefs)
|
||||
{
|
||||
M_StartMessage(M_GetText("No selectable tracks found.\n"),NULL,MM_NOTHING);
|
||||
return;
|
||||
@@ -8537,33 +8561,33 @@ static void M_DrawMusicTest(void)
|
||||
{
|
||||
INT32 t, b, q, m = 128;
|
||||
|
||||
if (numsoundtestdefs <= 8)
|
||||
if (nummusicdefs <= 8)
|
||||
{
|
||||
t = 0;
|
||||
b = numsoundtestdefs - 1;
|
||||
b = nummusicdefs - 1;
|
||||
i = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
q = m;
|
||||
m = (5*m)/numsoundtestdefs;
|
||||
m = (5*m)/nummusicdefs;
|
||||
if (st_sel < 3)
|
||||
{
|
||||
t = 0;
|
||||
b = 7;
|
||||
i = 0;
|
||||
}
|
||||
else if (st_sel >= numsoundtestdefs-4)
|
||||
else if (st_sel >= nummusicdefs-4)
|
||||
{
|
||||
t = numsoundtestdefs - 8;
|
||||
b = numsoundtestdefs - 1;
|
||||
t = nummusicdefs - 8;
|
||||
b = nummusicdefs - 1;
|
||||
i = q-m;
|
||||
}
|
||||
else
|
||||
{
|
||||
t = st_sel - 3;
|
||||
b = st_sel + 4;
|
||||
i = (t * (q-m))/(numsoundtestdefs - 8);
|
||||
i = (t * (q-m))/(nummusicdefs - 8);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8572,7 +8596,7 @@ static void M_DrawMusicTest(void)
|
||||
if (t != 0)
|
||||
V_DrawString(20+280+4, 60+4 - (skullAnimCounter/5), V_YELLOWMAP, "\x1A");
|
||||
|
||||
if (b != numsoundtestdefs - 1)
|
||||
if (b != nummusicdefs - 1)
|
||||
V_DrawString(20+280+4, 60+128-12 + (skullAnimCounter/5), V_YELLOWMAP, "\x1B");
|
||||
|
||||
x = 24;
|
||||
@@ -8586,8 +8610,9 @@ static void M_DrawMusicTest(void)
|
||||
V_DrawFill(20, y-4, 280-1, 16, 237);
|
||||
|
||||
{
|
||||
const musicdef_t *def = S_GetMusicCredit(t);
|
||||
const size_t MAXLENGTH = 34;
|
||||
const char *songname = soundtestdefs[t]->title[0] ? soundtestdefs[t]->title : soundtestdefs[t]->source;
|
||||
const char *songname = def->title[0] ? def->title : def->source;
|
||||
|
||||
size_t namelength = strlen(songname);
|
||||
|
||||
@@ -8600,7 +8625,7 @@ static void M_DrawMusicTest(void)
|
||||
buf[MAXLENGTH] = 0;
|
||||
|
||||
V_DrawString(x, y, (t == st_sel ? V_YELLOWMAP : 0)|V_ALLOWLOWERCASE|V_MONOSPACE, buf);
|
||||
if (curplaying == soundtestdefs[t])
|
||||
if (curplaying == def)
|
||||
{
|
||||
V_DrawFill(20+280-9, y-4, 8, 16, 230);
|
||||
}
|
||||
@@ -8618,7 +8643,7 @@ static void M_HandleMusicTest(INT32 choice)
|
||||
switch (choice)
|
||||
{
|
||||
case KEY_DOWNARROW:
|
||||
if (st_sel++ >= numsoundtestdefs-1)
|
||||
if (st_sel++ >= nummusicdefs-1)
|
||||
st_sel = 0;
|
||||
{
|
||||
S_StartSound(NULL, sfx_menu1);
|
||||
@@ -8627,18 +8652,18 @@ static void M_HandleMusicTest(INT32 choice)
|
||||
break;
|
||||
case KEY_UPARROW:
|
||||
if (!st_sel--)
|
||||
st_sel = numsoundtestdefs-1;
|
||||
st_sel = nummusicdefs-1;
|
||||
{
|
||||
S_StartSound(NULL, sfx_menu1);
|
||||
}
|
||||
st_musictime = 0;
|
||||
break;
|
||||
case KEY_PGDN:
|
||||
if (st_sel < numsoundtestdefs-1)
|
||||
if (st_sel < nummusicdefs-1)
|
||||
{
|
||||
st_sel += 3;
|
||||
if (st_sel >= numsoundtestdefs-1)
|
||||
st_sel = numsoundtestdefs-1;
|
||||
if (st_sel >= nummusicdefs-1)
|
||||
st_sel = nummusicdefs-1;
|
||||
S_StartSound(NULL, sfx_menu1);
|
||||
}
|
||||
st_musictime = 0;
|
||||
@@ -8672,7 +8697,7 @@ static void M_HandleMusicTest(INT32 choice)
|
||||
case KEY_ENTER:
|
||||
S_StopSounds();
|
||||
S_StopMusic();
|
||||
curplaying = soundtestdefs[st_sel];
|
||||
curplaying = S_GetMusicCredit(st_sel);
|
||||
S_ChangeMusicInternal(curplaying->name, true);
|
||||
break;
|
||||
|
||||
@@ -8681,9 +8706,6 @@ static void M_HandleMusicTest(INT32 choice)
|
||||
}
|
||||
if (exitmenu)
|
||||
{
|
||||
Z_Free(soundtestdefs);
|
||||
soundtestdefs = NULL;
|
||||
|
||||
if (currentMenu->prevMenu)
|
||||
M_SetupNextMenu(currentMenu->prevMenu);
|
||||
else
|
||||
|
||||
@@ -15,6 +15,11 @@
|
||||
#ifndef __X_MENU__
|
||||
#define __X_MENU__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "r_skins.h"
|
||||
#include "d_event.h"
|
||||
#include "command.h"
|
||||
#include "i_threads.h"
|
||||
@@ -433,4 +438,8 @@ if (currentMenu == &menu)\
|
||||
}\
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif //__X_MENU__
|
||||
+32
-4
@@ -14,6 +14,10 @@
|
||||
|
||||
#ifdef __GNUC__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)
|
||||
// Ignore "argument might be clobbered by longjmp" warning in GCC
|
||||
// (if libpng is compiled with setjmp error handling)
|
||||
@@ -1060,7 +1064,7 @@ static boolean M_SetupaPNG(png_const_charp filename, png_bytep pal)
|
||||
png_init_io(apng_ptr, apng_FILE);
|
||||
|
||||
#ifdef PNG_SET_USER_LIMITS_SUPPORTED
|
||||
png_set_user_limits(apng_ptr, MAXPNGWIDTH, MAXPNGHEIGHT);
|
||||
png_set_user_limits(apng_ptr, MAXVIDWIDTH, MAXVIDHEIGHT);
|
||||
#endif
|
||||
|
||||
//png_set_filter(apng_ptr, 0, PNG_ALL_FILTERS);
|
||||
@@ -1237,7 +1241,7 @@ void M_SaveFrame(void)
|
||||
if (rendermode == render_soft)
|
||||
{
|
||||
// munge planar buffer to linear
|
||||
linear = screens[2];
|
||||
linear = vid.screens[2];
|
||||
I_ReadScreen(linear);
|
||||
}
|
||||
#ifdef HWRENDER
|
||||
@@ -1375,7 +1379,7 @@ boolean M_SavePNG(const char *filename, void *data, int width, int height, const
|
||||
png_init_io(png_ptr, png_FILE);
|
||||
|
||||
#ifdef PNG_SET_USER_LIMITS_SUPPORTED
|
||||
png_set_user_limits(png_ptr, MAXPNGWIDTH, MAXPNGHEIGHT);
|
||||
png_set_user_limits(png_ptr, MAXVIDWIDTH, MAXVIDHEIGHT);
|
||||
#endif
|
||||
|
||||
//png_set_filter(png_ptr, 0, PNG_ALL_FILTERS);
|
||||
@@ -1539,7 +1543,7 @@ void M_DoScreenShot(void)
|
||||
if (rendermode == render_soft)
|
||||
{
|
||||
// munge planar buffer to linear
|
||||
linear = screens[2];
|
||||
linear = vid.screens[2];
|
||||
I_ReadScreen(linear);
|
||||
}
|
||||
|
||||
@@ -1966,6 +1970,25 @@ char *M_GetToken(const char *inputString)
|
||||
return texturesToken;
|
||||
}
|
||||
|
||||
|
||||
const char * M_Ftrim (double f)
|
||||
{
|
||||
static char dig[9];/* "0." + 6 digits (6 is printf's default) */
|
||||
int i;
|
||||
/* I know I said it's the default, but just in case... */
|
||||
sprintf(dig, "%.6f", fabs(modf(f, &f)));
|
||||
/* trim trailing zeroes */
|
||||
for (i = strlen(dig)-1; dig[i] == '0'; --i)
|
||||
;
|
||||
if (dig[i] == '.')/* :NOTHING: */
|
||||
return "";
|
||||
else
|
||||
{
|
||||
dig[i + 1] = '\0';
|
||||
return &dig[1];/* skip the 0 */
|
||||
}
|
||||
}
|
||||
|
||||
/** Count bits in a number.
|
||||
*/
|
||||
UINT8 M_CountBits(UINT32 num, UINT8 size)
|
||||
@@ -2191,3 +2214,8 @@ void M_MkdirEach(const char *path, int start, int mode)
|
||||
{
|
||||
M_MkdirEachUntil(path, start, -1, mode);
|
||||
}
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
@@ -15,6 +15,10 @@
|
||||
#ifndef __M_MISC__
|
||||
#define __M_MISC__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "doomtype.h"
|
||||
#include "tables.h"
|
||||
|
||||
@@ -104,10 +108,20 @@ boolean M_IsPathAbsolute (const char *path);
|
||||
void M_MkdirEach (const char *path, int start, int mode);
|
||||
void M_MkdirEachUntil (const char *path, int start, int end, int mode);
|
||||
|
||||
/*
|
||||
Return dot and then the fractional part of a float, without
|
||||
trailing zeros, or "" if the fractional part is zero.
|
||||
*/
|
||||
const char * M_Ftrim (double);
|
||||
|
||||
// counting bits, for weapon ammo code, usually
|
||||
FUNCMATH UINT8 M_CountBits(UINT32 num, UINT8 size);
|
||||
|
||||
#include "w_wad.h"
|
||||
extern char configfile[MAX_WADPATH];
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+169
-5
@@ -130,6 +130,82 @@ static void M_TextInputPaste(textinput_t *input)
|
||||
M_TextInputAddString(input, paste);
|
||||
}
|
||||
|
||||
static void M_TextInputLeft(textinput_t *input, boolean emotes)
|
||||
{
|
||||
// Just do it simple way if possible
|
||||
if (!emotes || input->cursor < 2 || input->buffer[input->cursor-1] != ':')
|
||||
{
|
||||
if (input->cursor != 0)
|
||||
--input->cursor;
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise we need to check if we have to skip emote
|
||||
size_t start = input->cursor-2;
|
||||
|
||||
while (input->buffer[start] != ':')
|
||||
{
|
||||
// We reached start of string and didn't find ':' symbol, thats definitely not an emote
|
||||
// so just do it simple way
|
||||
if (start == 0)
|
||||
{
|
||||
M_TextInputLeft(input, false);
|
||||
return;
|
||||
}
|
||||
|
||||
--start;
|
||||
}
|
||||
|
||||
int emotelen = 0;
|
||||
if (M_VerifyEmote(input->buffer+start, &emotelen))
|
||||
input->cursor -= emotelen; // also skip the :
|
||||
else
|
||||
M_TextInputLeft(input, false); // Not a valid emote, do the simple thing
|
||||
}
|
||||
|
||||
static void M_TextInputRight(textinput_t *input, boolean emotes)
|
||||
{
|
||||
// Just do it simple way if possible
|
||||
if (!emotes || input->cursor == input->length || input->buffer[input->cursor] != ':')
|
||||
{
|
||||
if (input->cursor < input->length)
|
||||
++input->cursor;
|
||||
return;
|
||||
}
|
||||
|
||||
int emotelen = 0;
|
||||
if (M_VerifyEmote(input->buffer+input->cursor, &emotelen))
|
||||
input->cursor += emotelen; // Also skip the :
|
||||
else
|
||||
M_TextInputRight(input, false); // Not a valid emote, do the simple thing
|
||||
}
|
||||
|
||||
// Check if we're inside a valid emote
|
||||
static boolean M_TextInputCheckEmote(textinput_t *input)
|
||||
{
|
||||
int start = input->cursor;
|
||||
|
||||
// Definitely not an emote
|
||||
if (start == 0)
|
||||
return false;
|
||||
|
||||
// Might be closing :, need to skip it just in case
|
||||
if (input->buffer[start] == ':')
|
||||
--start;
|
||||
|
||||
while (input->buffer[start] != ':')
|
||||
{
|
||||
// No ':' found, definitely not inside emote
|
||||
if (start == 0)
|
||||
return false;
|
||||
|
||||
--start;
|
||||
}
|
||||
|
||||
// Found what may be emote start, now we can check
|
||||
return M_VerifyEmote(input->buffer+start, NULL) != NULL;
|
||||
}
|
||||
|
||||
void M_TextInputInit(textinput_t *input, char *buffer, size_t buffer_size)
|
||||
{
|
||||
input->buffer = buffer;
|
||||
@@ -156,7 +232,7 @@ void M_TextInputSetString(textinput_t *input, const char *c)
|
||||
input->cursor = input->select = input->length = strlen(c);
|
||||
}
|
||||
|
||||
boolean M_TextInputHandle(textinput_t *input, INT32 key)
|
||||
static boolean M_TextInputHandleBase(textinput_t *input, INT32 key, boolean emotes)
|
||||
{
|
||||
if (key == KEY_LSHIFT || key == KEY_RSHIFT
|
||||
|| key == KEY_LCTRL || key == KEY_RCTRL
|
||||
@@ -241,16 +317,14 @@ boolean M_TextInputHandle(textinput_t *input, INT32 key)
|
||||
|
||||
if (key == KEY_LEFTARROW)
|
||||
{
|
||||
if (input->cursor != 0)
|
||||
--input->cursor;
|
||||
M_TextInputLeft(input, emotes);
|
||||
if (!shiftdown)
|
||||
input->select = input->cursor;
|
||||
return true;
|
||||
}
|
||||
else if (key == KEY_RIGHTARROW)
|
||||
{
|
||||
if (input->cursor < input->length)
|
||||
++input->cursor;
|
||||
M_TextInputRight(input, emotes);
|
||||
if (!shiftdown)
|
||||
input->select = input->cursor;
|
||||
return true;
|
||||
@@ -320,6 +394,96 @@ boolean M_TextInputHandle(textinput_t *input, INT32 key)
|
||||
return true;
|
||||
}
|
||||
|
||||
// Just an alias, more or less
|
||||
boolean M_TextInputHandle(textinput_t *input, INT32 key)
|
||||
{
|
||||
return M_TextInputHandleBase(input, key, false);
|
||||
}
|
||||
|
||||
boolean M_TextInputHandleEmotes(textinput_t *input, INT32 key, emote_t *suggestions[], int maxsuggestions)
|
||||
{
|
||||
boolean ret = M_TextInputHandleBase(input, key, true);
|
||||
|
||||
// After this handled key we ended up inside an emote, lets fix that
|
||||
if (M_TextInputCheckEmote(input))
|
||||
M_TextInputToWordEnd(input, !shiftdown);
|
||||
|
||||
// Always clear the first entry
|
||||
suggestions[0] = NULL;
|
||||
|
||||
// For autocomplete
|
||||
int emotestart = 0;
|
||||
|
||||
// Try find suggestions for emote names
|
||||
for (int i = input->cursor-1; i >= 0 && input->cursor-i <= MAXEMOTENAME; --i)
|
||||
{
|
||||
// Space can't be part of emote name
|
||||
if (isspace(input->buffer[i]))
|
||||
break;
|
||||
|
||||
// Found a :, try suggest emotes
|
||||
if (input->buffer[i] == ':')
|
||||
{
|
||||
emotestart = i+1;
|
||||
// ...But only if we typed at least something
|
||||
if ((int)input->cursor-(i-1) < 3)
|
||||
break;
|
||||
|
||||
for (int skip = 0; skip < maxsuggestions; ++skip)
|
||||
{
|
||||
suggestions[skip] = M_FindEmote(input->buffer+i+1, input->cursor-i-1, skip);
|
||||
|
||||
// No more suggestions
|
||||
if (!suggestions[skip])
|
||||
break;
|
||||
}
|
||||
|
||||
// In any case, we found what we wanted, can exit the loop now
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If we suggest emotes, try autocomplete
|
||||
if (key == '\t' && suggestions[0])
|
||||
{
|
||||
int pos = (input->cursor-emotestart);
|
||||
boolean autocomplete = true;
|
||||
|
||||
while (autocomplete)
|
||||
{
|
||||
// Check if current character matches for all suggestions
|
||||
char c = suggestions[0]->name[pos];
|
||||
|
||||
// End of string reached
|
||||
if (!c)
|
||||
break;
|
||||
|
||||
for (int i = 1; i < maxsuggestions && suggestions[i]; ++i)
|
||||
{
|
||||
if (suggestions[i]->name[pos] != c)
|
||||
{
|
||||
autocomplete = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
++pos;
|
||||
|
||||
if (autocomplete)
|
||||
M_TextInputAddChar(input, c);
|
||||
}
|
||||
|
||||
// This was the only suggestion, finish autocomplete with a ':' and clear suggestions
|
||||
if (maxsuggestions == 1 || !suggestions[1])
|
||||
{
|
||||
M_TextInputAddChar(input, ':');
|
||||
suggestions[0] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void M_DrawTextInputScroll(INT32 x, INT32 y, textinput_t *input, INT32 flags, INT32 MAXINPUTWIDTH)
|
||||
{
|
||||
if (renderisnewtic)
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define __M_TEXTINPUT__
|
||||
|
||||
#include "doomtype.h"
|
||||
#include "m_emotes.h" // M_VerifyEmote, M_FindEmote
|
||||
|
||||
typedef struct textinput_s {
|
||||
size_t cursor;
|
||||
@@ -22,6 +23,10 @@ void M_TextInputSetString(textinput_t *input, const char *c);
|
||||
|
||||
boolean M_TextInputHandle(textinput_t *input, INT32 key);
|
||||
|
||||
// Does everything same as M_TextInputHandle, but also handles emotes in input string
|
||||
// If currently typing something that looks like an existing emote, return suggestions for it
|
||||
boolean M_TextInputHandleEmotes(textinput_t *input, INT32 key, emote_t *suggestions[], int maxsuggestions);
|
||||
|
||||
#define M_DrawTextInput(x, y, input, flags) M_DrawTextInputScroll((x), (y), (input), (flags), ((input)->buffer_size-1)*8)
|
||||
void M_DrawTextInputScroll(INT32 x, INT32 y, textinput_t *input, INT32 flags, INT32 MAXINPUTWIDTH);
|
||||
|
||||
|
||||
@@ -26,12 +26,6 @@
|
||||
|
||||
#if defined (STDC_HEADERS) || defined (_LIBC)
|
||||
#include <stdlib.h>
|
||||
#else
|
||||
#ifndef HAVE_MEMCPY
|
||||
#if !(defined (_WIN32) && !defined (__CYGWIN__)) && !defined (__APPLE__)
|
||||
#define memcpy(d, s, n) bcopy ((s), (d), (n))
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "md5.h"
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "g_game.h"
|
||||
#include "p_local.h"
|
||||
#include "r_main.h"
|
||||
#include "r_skins.h"
|
||||
#include "r_state.h"
|
||||
#include "s_sound.h"
|
||||
#include "m_random.h"
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "p_setup.h"
|
||||
#include "r_fps.h"
|
||||
#include "r_main.h"
|
||||
#include "r_skins.h"
|
||||
#include "r_things.h"
|
||||
#include "r_sky.h"
|
||||
#include "r_splats.h"
|
||||
|
||||
@@ -14,6 +14,10 @@
|
||||
#ifndef __P_MOBJ__
|
||||
#define __P_MOBJ__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Basics.
|
||||
#include "tables.h"
|
||||
#include "m_fixed.h"
|
||||
@@ -536,4 +540,9 @@ extern mapthing_t *huntemeralds[MAXHUNTEMERALDS];
|
||||
extern INT32 numhuntemeralds;
|
||||
extern boolean runemeraldmanager;
|
||||
extern INT32 numstarposts;
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "r_fps.h"
|
||||
#include "r_things.h"
|
||||
#include "r_state.h"
|
||||
#include "r_skins.h"
|
||||
#include "w_wad.h"
|
||||
#include "y_inter.h"
|
||||
#include "z_zone.h"
|
||||
|
||||
+176
-116
@@ -34,6 +34,7 @@
|
||||
#include "r_fps.h" // R_ResetViewInterpolation in level load
|
||||
|
||||
#include "s_sound.h"
|
||||
#include "m_emotes.h"
|
||||
#include "st_stuff.h"
|
||||
#include "w_wad.h"
|
||||
#include "z_zone.h"
|
||||
@@ -67,6 +68,8 @@
|
||||
#include "lua_script.h"
|
||||
#include "lua_hook.h"
|
||||
|
||||
#include "y_inter.h"
|
||||
|
||||
#if !defined (UNDER_CE)
|
||||
#include <time.h>
|
||||
#endif
|
||||
@@ -580,9 +583,6 @@ static void P_LoadRawSegs(UINT8 *data)
|
||||
else
|
||||
li->backsector = 0;
|
||||
|
||||
li->numlights = 0;
|
||||
li->rlights = NULL;
|
||||
|
||||
P_UpdateSegLightOffset(li);
|
||||
}
|
||||
}
|
||||
@@ -675,6 +675,21 @@ INT32 P_AddLevelFlat(const char *flatname, levelflat_t *levelflat)
|
||||
levelflat->lumpnum = R_GetFlatNumForName(flatname);
|
||||
levelflat->baselumpnum = LUMPERROR;
|
||||
|
||||
// check if our flat contains cyan pixels
|
||||
// not sure if this is the best way to do it but it works
|
||||
{
|
||||
const UINT8 *flat = (UINT8 *)W_CacheLumpNum(levelflat->lumpnum, PU_LEVEL);
|
||||
size_t size = W_LumpLength(levelflat->lumpnum);
|
||||
for (size_t steppy = 0; steppy < size; steppy++)
|
||||
{
|
||||
if (flat[steppy] == TRANSPARENTPIXEL)
|
||||
{
|
||||
levelflat->cyan = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef ZDEBUG
|
||||
CONS_Debug(DBG_SETUP, "flat #%03d: %s\n", atoi(sizeu1(numlevelflats)), levelflat->name);
|
||||
#endif
|
||||
@@ -720,6 +735,21 @@ INT32 P_AddLevelFlatRuntime(const char *flatname)
|
||||
levelflat->lumpnum = R_GetFlatNumForName(flatname);
|
||||
levelflat->baselumpnum = LUMPERROR;
|
||||
|
||||
// check if our flat contains cyan pixels
|
||||
// not sure if this is the best way to do it but it works
|
||||
{
|
||||
const UINT8 *flat = (UINT8 *)W_CacheLumpNum(levelflat->lumpnum, PU_LEVEL);
|
||||
size_t size = W_LumpLength(levelflat->lumpnum);
|
||||
for (size_t steppy = 0; steppy < size; steppy++)
|
||||
{
|
||||
if (flat[steppy] == TRANSPARENTPIXEL)
|
||||
{
|
||||
levelflat->cyan = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef ZDEBUG
|
||||
CONS_Debug(DBG_SETUP, "flat #%03d: %s\n", atoi(sizeu1(numlevelflats)), levelflat->name);
|
||||
#endif
|
||||
@@ -2747,8 +2777,6 @@ static void P_SetupPlayer(void)
|
||||
I_mkdir(va("%s"PATHSEP"replay", srb2home), 0755);
|
||||
I_mkdir(va("%s"PATHSEP"replay"PATHSEP"online", srb2home), 0755);
|
||||
G_RecordDemo(buf);
|
||||
if (dedicated)
|
||||
G_BeginRecording(); //this has to move here, since dedicated servers dont run got_mapcmd
|
||||
}
|
||||
|
||||
wantedcalcdelay = wantedfrequency*2;
|
||||
@@ -2868,12 +2896,9 @@ boolean P_SetupLevel(boolean fromnetsave, boolean reloadinggamestate)
|
||||
F_WipeStartScreen();
|
||||
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, levelfadecol);
|
||||
F_WipeEndScreen();
|
||||
F_RunWipe(wipedefs[(encoremode ? wipe_level_final : wipe_level_toblack)], false);
|
||||
}
|
||||
else //dedicated servers
|
||||
{
|
||||
F_RunWipe(wipedefs[(encoremode ? wipe_level_final : wipe_level_toblack)], false);
|
||||
}
|
||||
|
||||
F_RunWipe(wipedefs[(encoremode ? wipe_level_final : wipe_level_toblack)], false);
|
||||
}
|
||||
|
||||
// Reset the palette now all fades have been done
|
||||
@@ -3109,11 +3134,128 @@ boolean P_AddWadFile(const char *wadfilename, boolean local)
|
||||
return true;
|
||||
}
|
||||
|
||||
// check for replacement votescreen backgrounds
|
||||
boolean wideracereplaced = false;
|
||||
boolean racereplaced = false;
|
||||
boolean widebattlereplaced = false;
|
||||
boolean battlereplaced = false;
|
||||
static size_t sreplaces = 0, mreplaces = 0, digmreplaces = 0;
|
||||
|
||||
//
|
||||
// search for sound replacements
|
||||
//
|
||||
static boolean P_CheckSoundReplacements(UINT16 wadnum, char *name, size_t i)
|
||||
{
|
||||
size_t j;
|
||||
lumpnum_t lumpnum = (i|(wadnum<<16));
|
||||
|
||||
if (name[0] == 'D')
|
||||
{
|
||||
if (name[1] == 'S')
|
||||
{
|
||||
for (j = 1; j < NUMSFX; j++)
|
||||
{
|
||||
if (S_sfx[j].name && !strnicmp(S_sfx[j].name, name + 2, 6)
|
||||
&& (S_sfx[j].lumpnum != lumpnum) && (S_sfx[j].lumpnum != LUMPERROR))
|
||||
{
|
||||
// the sound will be reloaded when needed,
|
||||
// since sfx->data will be NULL
|
||||
CONS_Debug(DBG_SETUP, "Sound %.8s replaced\n", name);
|
||||
|
||||
I_FreeSfx(&S_sfx[j]);
|
||||
|
||||
// Re-cache it
|
||||
if (S_PrecacheSound())
|
||||
S_sfx[j].data = I_GetSfx(&S_sfx[j]);
|
||||
|
||||
sreplaces++;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (name[1] == '_')
|
||||
{
|
||||
CONS_Debug(DBG_SETUP, "Music %.8s ignored\n", name);
|
||||
mreplaces++;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (name[0] == 'O' && name[1] == '_')
|
||||
{
|
||||
CONS_Debug(DBG_SETUP, "Music %.8s replaced\n", name);
|
||||
digmreplaces++;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// search for maps
|
||||
//
|
||||
static boolean P_CheckMapReplacements(char *name)
|
||||
{
|
||||
if (memcmp(name, "MAP", 3) == 0) // Ignore the headers
|
||||
{
|
||||
INT16 num;
|
||||
|
||||
if (name[5] != '\0')
|
||||
return false;
|
||||
|
||||
num = (INT16)M_MapNumber(name[3], name[4]);
|
||||
|
||||
// we want to record whether this map exists. if it doesn't have a header, we can assume it's not relephant
|
||||
if (num <= NUMMAPS && mapheaderinfo[num-1])
|
||||
{
|
||||
if (mapheaderinfo[num-1]->menuflags & LF2_EXISTSHACK)
|
||||
G_SetGameModified(multiplayer, true); // oops, double-defined - no record attack privileges for you
|
||||
mapheaderinfo[num-1]->menuflags |= LF2_EXISTSHACK;
|
||||
}
|
||||
|
||||
if (num == gamemap)
|
||||
partadd_replacescurrentmap = true;
|
||||
|
||||
CONS_Printf("%s\n", name);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// check for non Lua votescreen replacements
|
||||
//
|
||||
static boolean P_CheckVoteReplacements(char *name)
|
||||
{
|
||||
// widescreen patch Race
|
||||
if (!VoteScreen.replaced.widerace && !memcmp(name, "INTERSCW", 8))
|
||||
{
|
||||
VoteScreen.replaced.widerace = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!VoteScreen.replaced.race && !memcmp(name, "INTERSCR", 8))
|
||||
{
|
||||
VoteScreen.replaced.race = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// widescreen patch Battle
|
||||
if (!VoteScreen.replaced.widebattle && !memcmp(name, "BATTLSCW", 8))
|
||||
{
|
||||
VoteScreen.replaced.widebattle = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!VoteScreen.replaced.battle && !memcmp(name, "BATTLSCR", 8))
|
||||
{
|
||||
VoteScreen.replaced.battle = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (VoteScreen.replaced.widerace && VoteScreen.replaced.race
|
||||
&& VoteScreen.replaced.widebattle && VoteScreen.replaced.battle)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// Add a WAD file and do the per-WAD setup stages.
|
||||
@@ -3121,12 +3263,15 @@ boolean battlereplaced = false;
|
||||
//
|
||||
UINT16 P_PartialAddWadFile(const char *wadfilename, boolean local)
|
||||
{
|
||||
size_t i, j, sreplaces = 0, mreplaces = 0, digmreplaces = 0;
|
||||
size_t i;
|
||||
UINT16 numlumps, wadnum;
|
||||
char *name;
|
||||
boolean mapsadded = false;
|
||||
static boolean allvotereplaced = false;
|
||||
lumpinfo_t *lumpinfo;
|
||||
|
||||
sreplaces = mreplaces = digmreplaces = 0;
|
||||
|
||||
if ((numlumps = W_InitFile(wadfilename, local)) == INT16_MAX)
|
||||
{
|
||||
refreshdirmenu |= REFRESHDIR_NOTLOADED;
|
||||
@@ -3141,46 +3286,24 @@ UINT16 P_PartialAddWadFile(const char *wadfilename, boolean local)
|
||||
|
||||
wadfiles[wadnum]->localfile = local;
|
||||
|
||||
//
|
||||
// search for sound replacements
|
||||
//
|
||||
lumpinfo = wadfiles[wadnum]->lumpinfo;
|
||||
for (i = 0; i < numlumps; i++, lumpinfo++)
|
||||
{
|
||||
name = lumpinfo->name;
|
||||
lumpnum_t lumpnum = i|(wadnum<<16);
|
||||
|
||||
if (name[0] == 'D')
|
||||
if (P_CheckSoundReplacements(wadnum, name, i))
|
||||
continue;
|
||||
|
||||
if (P_CheckMapReplacements(name))
|
||||
{
|
||||
if (name[1] == 'S') for (j = 1; j < NUMSFX; j++)
|
||||
{
|
||||
if (S_sfx[j].name && !strnicmp(S_sfx[j].name, name + 2, 6) && S_sfx[j].lumpnum != lumpnum && S_sfx[j].lumpnum != LUMPERROR)
|
||||
{
|
||||
// the sound will be reloaded when needed,
|
||||
// since sfx->data will be NULL
|
||||
CONS_Debug(DBG_SETUP, "Sound %.8s replaced\n", name);
|
||||
|
||||
I_FreeSfx(&S_sfx[j]);
|
||||
|
||||
// Re-cache it
|
||||
if (S_PrecacheSound())
|
||||
S_sfx[j].data = I_GetSfx(&S_sfx[j]);
|
||||
|
||||
sreplaces++;
|
||||
}
|
||||
}
|
||||
else if (name[1] == '_')
|
||||
{
|
||||
CONS_Debug(DBG_SETUP, "Music %.8s ignored\n", name);
|
||||
mreplaces++;
|
||||
}
|
||||
}
|
||||
else if (name[0] == 'O' && name[1] == '_')
|
||||
{
|
||||
CONS_Debug(DBG_SETUP, "Music %.8s replaced\n", name);
|
||||
digmreplaces++;
|
||||
mapsadded = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!allvotereplaced && P_CheckVoteReplacements(name))
|
||||
allvotereplaced = true;
|
||||
}
|
||||
|
||||
if (!devparm && sreplaces)
|
||||
CONS_Printf(M_GetText("%s sounds replaced\n"), sizeu1(sreplaces));
|
||||
if (!devparm && mreplaces)
|
||||
@@ -3188,6 +3311,9 @@ UINT16 P_PartialAddWadFile(const char *wadfilename, boolean local)
|
||||
if (!devparm && digmreplaces)
|
||||
CONS_Printf(M_GetText("%s digital musics replaced\n"), sizeu1(digmreplaces));
|
||||
|
||||
if (!mapsadded)
|
||||
CONS_Printf(M_GetText("No maps added\n"));
|
||||
|
||||
//
|
||||
// search for sprite replacements
|
||||
//
|
||||
@@ -3213,79 +3339,13 @@ UINT16 P_PartialAddWadFile(const char *wadfilename, boolean local)
|
||||
S_LoadMusicDefs(wadnum);
|
||||
|
||||
//
|
||||
// search for maps
|
||||
// look for emotes
|
||||
//
|
||||
lumpinfo = wadfiles[wadnum]->lumpinfo;
|
||||
for (i = 0; i < numlumps; i++, lumpinfo++)
|
||||
{
|
||||
name = lumpinfo->name;
|
||||
|
||||
if (name[0] == 'M' && name[1] == 'A' && name[2] == 'P') // Ignore the headers
|
||||
{
|
||||
INT16 num;
|
||||
if (name[5]!='\0')
|
||||
continue;
|
||||
num = (INT16)M_MapNumber(name[3], name[4]);
|
||||
|
||||
// we want to record whether this map exists. if it doesn't have a header, we can assume it's not relephant
|
||||
if (num <= NUMMAPS && mapheaderinfo[num-1])
|
||||
{
|
||||
if (mapheaderinfo[num-1]->menuflags & LF2_EXISTSHACK)
|
||||
G_SetGameModified(multiplayer, true); // oops, double-defined - no record attack privileges for you
|
||||
mapheaderinfo[num-1]->menuflags |= LF2_EXISTSHACK;
|
||||
}
|
||||
|
||||
if (num == gamemap)
|
||||
partadd_replacescurrentmap = true;
|
||||
|
||||
CONS_Printf("%s\n", name);
|
||||
mapsadded = true;
|
||||
}
|
||||
}
|
||||
if (!mapsadded)
|
||||
CONS_Printf(M_GetText("No maps added\n"));
|
||||
M_LoadEmotes(wadnum);
|
||||
|
||||
// TODO: Experimental SPRTINFO support, test first
|
||||
R_LoadSpriteInfoLumps(wadnum, wadfiles[wadnum]->numlumps);
|
||||
|
||||
//
|
||||
// check for votescreen replacements
|
||||
//
|
||||
if (!wideracereplaced && !racereplaced && !widebattlereplaced && !battlereplaced)
|
||||
{
|
||||
lumpinfo = wadfiles[wadnum]->lumpinfo;
|
||||
for (i = 0; i < numlumps; i++, lumpinfo++)
|
||||
{
|
||||
name = lumpinfo->name;
|
||||
|
||||
// widescreen patch Race
|
||||
if (!wideracereplaced && !strncmp(name, "INTERSCW", 8))
|
||||
{
|
||||
wideracereplaced = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!racereplaced && !strncmp(name, "INTERSCR", 8))
|
||||
{
|
||||
racereplaced = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
// widescreen patch Battle
|
||||
if (!widebattlereplaced && !strncmp(name, "BATTLSCW", 8))
|
||||
{
|
||||
widebattlereplaced = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!battlereplaced && !strncmp(name, "BATTLSCR", 8))
|
||||
{
|
||||
battlereplaced = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
refreshdirmenu &= ~REFRESHDIR_GAMEDATA; // Under usual circumstances we'd wait for REFRESHDIR_GAMEDATA to disappear the next frame, but it's a bit too dangerous for that...
|
||||
partadd_stage = 0;
|
||||
return wadnum;
|
||||
|
||||
+9
-5
@@ -14,6 +14,10 @@
|
||||
#ifndef __P_SETUP__
|
||||
#define __P_SETUP__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "doomdata.h"
|
||||
#include "doomstat.h"
|
||||
#include "r_defs.h"
|
||||
@@ -48,6 +52,7 @@ typedef struct
|
||||
INT32 animseq; // start pos. in the anim sequence
|
||||
INT32 numpics;
|
||||
INT32 speed;
|
||||
boolean cyan;
|
||||
} levelflat_t;
|
||||
|
||||
extern size_t numlevelflats;
|
||||
@@ -68,11 +73,6 @@ void HWR_LoadLevel(boolean reloadinggamestate);
|
||||
|
||||
boolean P_AddWadFile(const char *wadfilename, boolean local);
|
||||
|
||||
extern boolean wideracereplaced;
|
||||
extern boolean racereplaced;
|
||||
extern boolean widebattlereplaced;
|
||||
extern boolean battlereplaced;
|
||||
|
||||
// WARNING: The following functions should be grouped as follows:
|
||||
// any amount of PartialAdds followed by MultiSetups until returned true,
|
||||
// as soon as possible.
|
||||
@@ -116,4 +116,8 @@ UINT8 P_GetGrade(UINT32 pscore, INT16 map, UINT8 mare);
|
||||
UINT8 P_HasGrades(INT16 map, UINT8 mare);
|
||||
UINT32 P_GetScoreForGrade(INT16 map, UINT8 mare, UINT8 grade);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Loaded 100 of 155 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user