Merge remote-tracking branch 'origin/master' into rotsprite_i

This commit is contained in:
Jaime Passos 2019-11-12 21:38:02 -03:00
commit 245881ec55
67 changed files with 5103 additions and 2329 deletions

View file

@ -3542,7 +3542,7 @@ thingtypes
}
124
{
title = "AquaBuzz";
title = "Buggle";
sprite = "BBUZA1";
width = 20;
height = 24;
@ -5673,8 +5673,8 @@ thingtypes
{
arrow = 1;
blocking = 2;
title = "Trapgoyle";
sprite = "GARGA1";
title = "Glaregoyle";
sprite = "BGARA1";
width = 16;
height = 40;
flags4text = "[4] Slides when pushed";
@ -5684,8 +5684,8 @@ thingtypes
{
arrow = 1;
blocking = 2;
title = "Trapgoyle (Up)";
sprite = "GARGA1";
title = "Glaregoyle (Up)";
sprite = "BGARA1";
width = 16;
height = 40;
flags4text = "[4] Slides when pushed";
@ -5695,8 +5695,8 @@ thingtypes
{
arrow = 1;
blocking = 2;
title = "Trapgoyle (Down)";
sprite = "GARGA1";
title = "Glaregoyle (Down)";
sprite = "BGARA1";
width = 16;
height = 40;
flags4text = "[4] Slides when pushed";
@ -5706,8 +5706,8 @@ thingtypes
{
arrow = 1;
blocking = 2;
title = "Trapgoyle (Long)";
sprite = "GARGA1";
title = "Glaregoyle (Long)";
sprite = "BGARA1";
width = 16;
height = 40;
flags4text = "[4] Slides when pushed";

View file

@ -425,7 +425,11 @@ if(${SRB2_CONFIG_HWRENDER})
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_light.c
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_main.c
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_md2.c
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_md2load.c
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_md3load.c
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_model.c
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_trick.c
${CMAKE_CURRENT_SOURCE_DIR}/hardware/u_list.c
)
set (SRB2_HWRENDER_HEADERS
@ -439,6 +443,10 @@ if(${SRB2_CONFIG_HWRENDER})
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_light.h
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_main.h
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_md2.h
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_md2load.h
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_md3load.h
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_model.h
${CMAKE_CURRENT_SOURCE_DIR}/hardware/u_list.h
)
set(SRB2_R_OPENGL_SOURCES

View file

@ -226,7 +226,8 @@ else
#OPTS+=-DUSE_PALETTED_TEXTURE
OPTS+=-DHWRENDER
OBJS+=$(OBJDIR)/hw_bsp.o $(OBJDIR)/hw_draw.o $(OBJDIR)/hw_light.o \
$(OBJDIR)/hw_main.o $(OBJDIR)/hw_clip.o $(OBJDIR)/hw_md2.o $(OBJDIR)/hw_cache.o $(OBJDIR)/hw_trick.o
$(OBJDIR)/hw_main.o $(OBJDIR)/hw_clip.o $(OBJDIR)/hw_md2.o $(OBJDIR)/hw_cache.o $(OBJDIR)/hw_trick.o \
$(OBJDIR)/hw_md2load.o $(OBJDIR)/hw_md3load.o $(OBJDIR)/hw_model.o $(OBJDIR)/u_list.o
endif
ifdef NOHS
@ -647,16 +648,18 @@ ifdef MINGW
$(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h \
doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \
command.h hardware/hw_data.h hardware/hw_glide.h hardware/hw_defs.h \
hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h am_map.h \
d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h \
hardware/hw_md2load.h hardware/hw_md3load.h hardware/hw_model.h hardware/u_list.h \
am_map.h d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h
$(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@
else
$(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h \
doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \
command.h hardware/hw_data.h hardware/hw_glide.h hardware/hw_defs.h \
hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h am_map.h \
d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h \
hardware/hw_md2load.h hardware/hw_md3load.h hardware/hw_model.h hardware/u_list.h \
am_map.h d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h
$(CC) $(CFLAGS) $(WFLAGS) -I/usr/X11R6/include -c $< -o $@
endif
@ -734,16 +737,18 @@ ifndef NOHW
$(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h \
doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \
command.h hardware/hw_data.h hardware/hw_glide.h hardware/hw_defs.h \
hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h am_map.h \
d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h \
hardware/hw_md2load.h hardware/hw_md3load.h hardware/hw_model.h hardware/u_list.h \
am_map.h d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h
$(CC) $(CFLAGS) $(WFLAGS) -D_WINDOWS -mwindows -c $< -o $@
$(OBJDIR)/ogl_win.o: hardware/r_opengl/ogl_win.c hardware/r_opengl/r_opengl.h \
doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \
command.h hardware/hw_data.h hardware/hw_glide.h hardware/hw_defs.h \
hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h am_map.h \
d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h \
hardware/hw_md2load.h hardware/hw_md3load.h hardware/hw_model.h hardware/u_list.h \
am_map.h d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h
$(CC) $(CFLAGS) $(WFLAGS) -D_WINDOWS -mwindows -c $< -o $@
endif

View file

@ -2491,7 +2491,7 @@ static void CL_RemovePlayer(INT32 playernum, INT32 reason)
void CL_Reset(void)
{
if (metalrecording)
G_StopMetalRecording();
G_StopMetalRecording(false);
if (metalplayback)
G_StopMetalDemo();
if (demorecording)
@ -4708,7 +4708,12 @@ void TryRunTics(tic_t realtics)
if (neededtic > gametic && !resynch_local_inprogress)
{
if (advancedemo)
D_StartTitle();
{
if (timedemo_quit)
COM_ImmedExecute("quit");
else
D_StartTitle();
}
else
// run the count * tics
while (neededtic > gametic)

View file

@ -291,11 +291,8 @@ static void D_Display(void)
switch (gamestate)
{
case GS_TITLESCREEN:
if (!titlemapinaction || !curbghide) {
F_TitleScreenDrawer();
break;
}
/* FALLTHRU */
F_TitleScreenDrawer();
break;
case GS_LEVEL:
if (!gametic)
break;
@ -366,56 +363,11 @@ static void D_Display(void)
// clean up border stuff
// see if the border needs to be initially drawn
if (gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction && curbghide && (!hidetitlemap)))
if (gamestate == GS_LEVEL)
{
// draw the view directly
if (!automapactive && !dedicated && cv_renderview.value)
{
if (players[displayplayer].mo || players[displayplayer].playerstate == PST_DEAD)
{
topleft = screens[0] + viewwindowy*vid.width + viewwindowx;
objectsdrawn = 0;
#ifdef HWRENDER
if (rendermode != render_soft)
HWR_RenderPlayerView(0, &players[displayplayer]);
else
#endif
if (rendermode != render_none)
R_RenderPlayerView(&players[displayplayer]);
}
// render the second screen
if (splitscreen && players[secondarydisplayplayer].mo)
{
#ifdef HWRENDER
if (rendermode != render_soft)
HWR_RenderPlayerView(1, &players[secondarydisplayplayer]);
else
#endif
if (rendermode != render_none)
{
viewwindowy = vid.height / 2;
M_Memcpy(ylookup, ylookup2, viewheight*sizeof (ylookup[0]));
topleft = screens[0] + viewwindowy*vid.width + viewwindowx;
R_RenderPlayerView(&players[secondarydisplayplayer]);
viewwindowy = 0;
M_Memcpy(ylookup, ylookup1, viewheight*sizeof (ylookup[0]));
}
}
// Image postprocessing effect
if (rendermode == render_soft)
{
if (postimgtype)
V_DoPostProcessor(0, postimgtype, postimgparam);
if (postimgtype2)
V_DoPostProcessor(1, postimgtype2, postimgparam2);
}
}
D_Render();
if (lastdraw)
{
@ -428,14 +380,9 @@ static void D_Display(void)
lastdraw = false;
}
if (gamestate == GS_LEVEL)
{
ST_Drawer();
F_TextPromptDrawer();
HU_Drawer();
}
else
F_TitleScreenDrawer();
ST_Drawer();
F_TextPromptDrawer();
HU_Drawer();
}
}
@ -491,6 +438,13 @@ static void D_Display(void)
F_RunWipe(wipetypepost, gamestate != GS_TIMEATTACK && gamestate != GS_TITLESCREEN);
}
// reset counters so timedemo doesn't count the wipe duration
if (timingdemo)
{
framecount = 0;
demostarttime = I_GetTime();
}
wipetypepost = -1;
}
else
@ -531,6 +485,56 @@ static void D_Display(void)
}
}
void D_Render(void)
{
if (!automapactive && !dedicated && cv_renderview.value)
{
if (players[displayplayer].mo || players[displayplayer].playerstate == PST_DEAD)
{
topleft = screens[0] + viewwindowy*vid.width + viewwindowx;
objectsdrawn = 0;
#ifdef HWRENDER
if (rendermode != render_soft)
HWR_RenderPlayerView(0, &players[displayplayer]);
else
#endif
if (rendermode != render_none)
R_RenderPlayerView(&players[displayplayer]);
}
// render the second screen
if (splitscreen && players[secondarydisplayplayer].mo)
{
#ifdef HWRENDER
if (rendermode != render_soft)
HWR_RenderPlayerView(1, &players[secondarydisplayplayer]);
else
#endif
if (rendermode != render_none)
{
viewwindowy = vid.height / 2;
M_Memcpy(ylookup, ylookup2, viewheight*sizeof (ylookup[0]));
topleft = screens[0] + viewwindowy*vid.width + viewwindowx;
R_RenderPlayerView(&players[secondarydisplayplayer]);
viewwindowy = 0;
M_Memcpy(ylookup, ylookup1, viewheight*sizeof (ylookup[0]));
}
}
// Image postprocessing effect
if (rendermode == render_soft)
{
if (postimgtype)
V_DoPostProcessor(0, postimgtype, postimgparam);
if (postimgtype2)
V_DoPostProcessor(1, postimgtype2, postimgparam2);
}
}
}
// =========================================================================
// D_SRB2Loop
// =========================================================================
@ -544,9 +548,6 @@ void D_SRB2Loop(void)
if (dedicated)
server = true;
if (M_CheckParm("-voodoo")) // 256x256 Texture Limiter
COM_BufAddText("gr_voodoocompatibility on\n");
// Pushing of + parameters is now done back in D_SRB2Main, not here.
CONS_Printf("I_StartupKeyboard()...\n");

View file

@ -54,4 +54,7 @@ const char *D_Home(void);
void D_AdvanceDemo(void);
void D_StartTitle(void);
/* Here for title maps */
void D_Render(void);
#endif //__D_MAIN__

View file

@ -365,6 +365,11 @@ consvar_t cv_mute = {"mute", "Off", CV_NETVAR|CV_CALL, CV_OnOff, Mute_OnChange,
consvar_t cv_sleep = {"cpusleep", "1", CV_SAVE, sleeping_cons_t, NULL, -1, NULL, NULL, 0, 0, NULL};
char timedemo_name[256];
boolean timedemo_csv;
char timedemo_csv_id[256];
boolean timedemo_quit;
INT16 gametype = GT_COOP;
boolean splitscreen = false;
boolean circuitmap = false;
@ -1206,9 +1211,9 @@ static void SendNameAndColor(void)
players[consoleplayer].mo->color = players[consoleplayer].skincolor;
if (metalrecording)
{ // Metal Sonic is Sonic, obviously.
SetPlayerSkinByNum(consoleplayer, 0);
CV_StealthSet(&cv_skin, skins[0].name);
{ // Starring Metal Sonic as themselves, obviously.
SetPlayerSkinByNum(consoleplayer, 5);
CV_StealthSet(&cv_skin, skins[5].name);
}
else if ((foundskin = R_SkinAvailable(cv_skin.string)) != -1 && R_SkinUsable(consoleplayer, foundskin))
{
@ -1569,11 +1574,11 @@ static void Command_Playdemo_f(void)
static void Command_Timedemo_f(void)
{
char name[256];
size_t i = 0;
if (COM_Argc() != 2)
if (COM_Argc() < 2)
{
CONS_Printf(M_GetText("timedemo <demoname>: time a demo\n"));
CONS_Printf(M_GetText("timedemo <demoname> [-csv [<trialid>]] [-quit]: time a demo\n"));
return;
}
@ -1590,12 +1595,23 @@ static void Command_Timedemo_f(void)
G_StopMetalDemo();
// open the demo file
strcpy (name, COM_Argv(1));
strcpy (timedemo_name, COM_Argv(1));
// dont add .lmp so internal game demos can be played
CONS_Printf(M_GetText("Timing demo '%s'.\n"), name);
// print timedemo results as CSV?
i = COM_CheckParm("-csv");
timedemo_csv = (i > 0);
if (COM_CheckParm("-quit") != i + 1)
strcpy(timedemo_csv_id, COM_Argv(i + 1)); // user-defined string to identify row
else
timedemo_csv_id[0] = 0;
G_TimeDemo(name);
// exit after the timedemo?
timedemo_quit = (COM_CheckParm("-quit") > 0);
CONS_Printf(M_GetText("Timing demo '%s'.\n"), timedemo_name);
G_TimeDemo(timedemo_name);
}
// stop current demo
@ -1646,7 +1662,31 @@ void D_MapChange(INT32 mapnum, INT32 newgametype, boolean pultmode, boolean rese
// The supplied data are assumed to be good.
I_Assert(delay >= 0 && delay <= 2);
if (mapnum != -1)
{
CV_SetValue(&cv_nextmap, mapnum);
// Kick bot from special stages
if (botskin)
{
if (G_IsSpecialStage(mapnum) || (mapheaderinfo[mapnum-1] && (mapheaderinfo[mapnum-1]->typeoflevel & TOL_NIGHTS)))
{
if (botingame)
{
//CL_RemoveSplitscreenPlayer();
botingame = false;
playeringame[1] = false;
}
}
else if (!botingame)
{
//CL_AddSplitscreenPlayer();
botingame = true;
secondarydisplayplayer = 1;
playeringame[1] = true;
players[1].bot = 1;
SendNameAndColor2();
}
}
}
CONS_Debug(DBG_GAMELOGIC, "Map change: mapnum=%d gametype=%d ultmode=%d resetplayers=%d delay=%d skipprecutscene=%d\n",
mapnum, newgametype, pultmode, resetplayers, delay, skipprecutscene);
if ((netgame || multiplayer) && !((gametype == newgametype) && (newgametype == GT_COOP)))
@ -1689,29 +1729,6 @@ void D_MapChange(INT32 mapnum, INT32 newgametype, boolean pultmode, boolean rese
return;
}
// Kick bot from special stages
if (botskin)
{
if (G_IsSpecialStage(mapnum) || (mapheaderinfo[mapnum-1] && (mapheaderinfo[mapnum-1]->typeoflevel & TOL_NIGHTS)))
{
if (botingame)
{
//CL_RemoveSplitscreenPlayer();
botingame = false;
playeringame[1] = false;
}
}
else if (!botingame)
{
//CL_AddSplitscreenPlayer();
botingame = true;
secondarydisplayplayer = 1;
playeringame[1] = true;
players[1].bot = 1;
SendNameAndColor2();
}
}
chmappending++;
if (netgame)
WRITEUINT32(buf_p, M_RandomizedSeed()); // random seed

View file

@ -113,6 +113,11 @@ extern consvar_t cv_skipmapcheck;
extern consvar_t cv_sleep;
extern char timedemo_name[256];
extern boolean timedemo_csv;
extern char timedemo_csv_id[256];
extern boolean timedemo_quit;
typedef enum
{
XD_NAMEANDCOLOR = 1,

View file

@ -5583,25 +5583,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_CYBRAKDEMONVILEEXPLOSION3",
// Metal Sonic (Race)
// S_PLAY_STND
"S_METALSONIC_STAND",
// S_PLAY_TAP1
"S_METALSONIC_WAIT1",
"S_METALSONIC_WAIT2",
// S_PLAY_WALK
"S_METALSONIC_WALK1",
"S_METALSONIC_WALK2",
"S_METALSONIC_WALK3",
"S_METALSONIC_WALK4",
"S_METALSONIC_WALK5",
"S_METALSONIC_WALK6",
"S_METALSONIC_WALK7",
"S_METALSONIC_WALK8",
// S_PLAY_SPD1
"S_METALSONIC_RUN1",
"S_METALSONIC_RUN2",
"S_METALSONIC_RUN3",
"S_METALSONIC_RUN4",
"S_METALSONIC_RACE",
// Metal Sonic (Battle)
"S_METALSONIC_FLOAT",
"S_METALSONIC_VECTOR",
@ -5944,7 +5926,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_ARROW",
"S_ARROWBONK",
// Trapgoyle Demon fire
// Glaregoyle Demon fire
"S_DEMONFIRE",
// GFZ flowers
@ -6312,29 +6294,35 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_WALLVINE_LONG",
"S_WALLVINE_SHORT",
// Trapgoyles
"S_TRAPGOYLE",
"S_TRAPGOYLE_CHECK",
"S_TRAPGOYLE_FIRE1",
"S_TRAPGOYLE_FIRE2",
"S_TRAPGOYLE_FIRE3",
"S_TRAPGOYLEUP",
"S_TRAPGOYLEUP_CHECK",
"S_TRAPGOYLEUP_FIRE1",
"S_TRAPGOYLEUP_FIRE2",
"S_TRAPGOYLEUP_FIRE3",
"S_TRAPGOYLEDOWN",
"S_TRAPGOYLEDOWN_CHECK",
"S_TRAPGOYLEDOWN_FIRE1",
"S_TRAPGOYLEDOWN_FIRE2",
"S_TRAPGOYLEDOWN_FIRE3",
"S_TRAPGOYLELONG",
"S_TRAPGOYLELONG_CHECK",
"S_TRAPGOYLELONG_FIRE1",
"S_TRAPGOYLELONG_FIRE2",
"S_TRAPGOYLELONG_FIRE3",
"S_TRAPGOYLELONG_FIRE4",
"S_TRAPGOYLELONG_FIRE5",
// Glaregoyles
"S_GLAREGOYLE",
"S_GLAREGOYLE_CHARGE",
"S_GLAREGOYLE_BLINK",
"S_GLAREGOYLE_HOLD",
"S_GLAREGOYLE_FIRE",
"S_GLAREGOYLE_LOOP",
"S_GLAREGOYLE_COOLDOWN",
"S_GLAREGOYLEUP",
"S_GLAREGOYLEUP_CHARGE",
"S_GLAREGOYLEUP_BLINK",
"S_GLAREGOYLEUP_HOLD",
"S_GLAREGOYLEUP_FIRE",
"S_GLAREGOYLEUP_LOOP",
"S_GLAREGOYLEUP_COOLDOWN",
"S_GLAREGOYLEDOWN",
"S_GLAREGOYLEDOWN_CHARGE",
"S_GLAREGOYLEDOWN_BLINK",
"S_GLAREGOYLEDOWN_HOLD",
"S_GLAREGOYLEDOWN_FIRE",
"S_GLAREGOYLEDOWN_LOOP",
"S_GLAREGOYLEDOWN_COOLDOWN",
"S_GLAREGOYLELONG",
"S_GLAREGOYLELONG_CHARGE",
"S_GLAREGOYLELONG_BLINK",
"S_GLAREGOYLELONG_HOLD",
"S_GLAREGOYLELONG_FIRE",
"S_GLAREGOYLELONG_LOOP",
"S_GLAREGOYLELONG_COOLDOWN",
// ATZ's Red Crystal/Target
"S_TARGET_IDLE",
@ -6346,6 +6334,9 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
// ATZ's green flame
"S_GREENFLAME",
// ATZ Blue Gargoyle
"S_BLUEGARGOYLE",
// Stalagmites
"S_STG0",
"S_STG1",
@ -7535,8 +7526,8 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_BUMBLEBORE_STUCK2",
"S_BUMBLEBORE_DIE",
"S_BBUZZFLY1",
"S_BBUZZFLY2",
"S_BUGGLEIDLE",
"S_BUGGLEFLY",
"S_SMASHSPIKE_FLOAT",
"S_SMASHSPIKE_EASE1",
@ -7932,7 +7923,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_CANNONBALL", // Cannonball
"MT_CANNONBALLDECOR", // Decorative/still cannonball
"MT_ARROW", // Arrow
"MT_DEMONFIRE", // Trapgoyle fire
"MT_DEMONFIRE", // Glaregoyle fire
// Greenflower Scenery
"MT_GFZFLOWER1",
@ -8095,12 +8086,13 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
// Egg Rock Scenery
// Azure Temple Scenery
"MT_TRAPGOYLE",
"MT_TRAPGOYLEUP",
"MT_TRAPGOYLEDOWN",
"MT_TRAPGOYLELONG",
"MT_GLAREGOYLE",
"MT_GLAREGOYLEUP",
"MT_GLAREGOYLEDOWN",
"MT_GLAREGOYLELONG",
"MT_TARGET",
"MT_GREENFLAME",
"MT_BLUEGARGOYLE",
// Stalagmites
"MT_STALAGMITE0",
@ -8375,7 +8367,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_HIVEELEMENTAL",
"MT_BUMBLEBORE",
"MT_BUBBLEBUZZ",
"MT_BUGGLE",
"MT_SMASHINGSPIKEBALL",
"MT_CACOLANTERN",

View file

@ -326,16 +326,18 @@ size_t strlcpy(char *dst, const char *src, size_t siz);
/* Miscellaneous types that don't fit anywhere else (Can this be changed?) */
typedef struct
{
UINT8 red;
UINT8 green;
UINT8 blue;
UINT8 alpha;
} byteColor_t;
union FColorRGBA
{
UINT32 rgba;
struct
{
UINT8 red;
UINT8 green;
UINT8 blue;
UINT8 alpha;
} s;
byteColor_t s;
} ATTRPACK;
typedef union FColorRGBA RGBA_t;

View file

@ -2580,7 +2580,9 @@ void F_TitleScreenDrawer(void)
// Draw that sky!
if (curbgcolor >= 0)
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, curbgcolor);
else if (!curbghide || !titlemapinaction || gamestate == GS_WAITINGPLAYERS)
else if (titlemapinaction && curbghide && ! hidetitlemap)
D_Render();
else
F_SkyScroll(curbgxspeed, curbgyspeed, curbgname);
// Don't draw outside of the title screen, or if the patch isn't there.
@ -3312,10 +3314,6 @@ void F_TitleScreenTicker(boolean run)
if (run)
finalecount++;
// don't trigger if doing anything besides idling on title
if (gameaction != ga_nothing || gamestate != GS_TITLESCREEN)
return;
// Execute the titlemap camera settings
if (titlemapinaction)
{
@ -3362,6 +3360,10 @@ void F_TitleScreenTicker(boolean run)
}
}
// don't trigger if doing anything besides idling on title
if (gameaction != ga_nothing || gamestate != GS_TITLESCREEN)
return;
// no demos to play? or, are they disabled?
if (!cv_rollingdemos.value || !numDemos)
return;

View file

@ -104,7 +104,7 @@ UINT32 demoIdleTime = 3*TICRATE;
boolean timingdemo; // if true, exit with report on completion
boolean nodrawers; // for comparative timing purposes
boolean noblit; // for comparative timing purposes
static tic_t demostarttime; // for comparative timing purposes
tic_t demostarttime; // for comparative timing purposes
boolean netgame; // only true if packets are broadcast
boolean multiplayer;
@ -289,7 +289,7 @@ static struct {
// There is no conflict here.
typedef struct demoghost {
UINT8 checksum[16];
UINT8 *buffer, *p, color;
UINT8 *buffer, *p, color, fadein;
UINT16 version;
mobj_t oldmo, *mo;
struct demoghost *next;
@ -2755,6 +2755,8 @@ void G_DoReborn(INT32 playernum)
LUAh_MapChange(gamemap);
#endif
G_DoLoadLevel(true);
if (metalrecording)
G_BeginMetal();
return;
}
}
@ -2922,7 +2924,7 @@ boolean G_GametypeUsesLives(void)
{
// Coop, Competitive
if ((gametype == GT_COOP || gametype == GT_COMPETITION)
&& !modeattacking // No lives in Time Attack
&& !(modeattacking || metalrecording) // No lives in Time Attack
//&& !G_IsSpecialStage(gamemap)
&& !(maptol & TOL_NIGHTS)) // No lives in NiGHTS
return true;
@ -3053,7 +3055,7 @@ static void G_DoCompleted(void)
if (metalplayback)
G_StopMetalDemo();
if (metalrecording)
G_StopMetalRecording();
G_StopMetalRecording(false);
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i])
@ -4049,7 +4051,7 @@ char *G_BuildMapTitle(INT32 mapnum)
// DEMO RECORDING
//
#define DEMOVERSION 0x000a
#define DEMOVERSION 0x000c
#define DEMOHEADER "\xF0" "SRB2Replay" "\x0F"
#define DF_GHOST 0x01 // This demo contains ghost data too!
@ -4065,6 +4067,8 @@ char *G_BuildMapTitle(INT32 mapnum)
#define ZT_BUTTONS 0x08
#define ZT_AIMING 0x10
#define DEMOMARKER 0x80 // demoend
#define METALDEATH 0x44
#define METALSNICE 0x69
static ticcmd_t oldcmd;
@ -4073,7 +4077,6 @@ static ticcmd_t oldcmd;
#define GZT_MOMXY 0x02
#define GZT_MOMZ 0x04
#define GZT_ANGLE 0x08
// Not used for Metal Sonic
#define GZT_FRAME 0x10 // Animation frame
#define GZT_SPR2 0x20 // Player animations
#define GZT_EXTRA 0x40
@ -4089,7 +4092,15 @@ static ticcmd_t oldcmd;
#define EZT_SCALE 0x10 // Changed size
#define EZT_HIT 0x20 // Damaged a mobj
#define EZT_SPRITE 0x40 // Changed sprite set completely out of PLAY (NiGHTS, SOCs, whatever)
// spare EZT slot 0x80
#define EZT_HEIGHT 0x80 // Changed height
// GZT_FOLLOW flags
#define FZT_SPAWNED 0x01 // just been spawned
#define FZT_SKIN 0x02 // has skin
#define FZT_LINKDRAW 0x04 // has linkdraw (combine with spawned only)
#define FZT_COLORIZED 0x08 // colorized (ditto)
#define FZT_SCALE 0x10 // different scale to object
// spare FZT slots 0x20 to 0x80
static mobj_t oldmetal, oldghost;
@ -4215,28 +4226,28 @@ void G_WriteDemoTiccmd(ticcmd_t *cmd, INT32 playernum)
void G_GhostAddThok(void)
{
if (!demorecording || !(demoflags & DF_GHOST))
if (!metalrecording && (!demorecording || !(demoflags & DF_GHOST)))
return;
ghostext.flags = (ghostext.flags & ~EZT_THOKMASK) | EZT_THOK;
}
void G_GhostAddSpin(void)
{
if (!demorecording || !(demoflags & DF_GHOST))
if (!metalrecording && (!demorecording || !(demoflags & DF_GHOST)))
return;
ghostext.flags = (ghostext.flags & ~EZT_THOKMASK) | EZT_SPIN;
}
void G_GhostAddRev(void)
{
if (!demorecording || !(demoflags & DF_GHOST))
if (!metalrecording && (!demorecording || !(demoflags & DF_GHOST)))
return;
ghostext.flags = (ghostext.flags & ~EZT_THOKMASK) | EZT_REV;
}
void G_GhostAddFlip(void)
{
if (!demorecording || !(demoflags & DF_GHOST))
if (!metalrecording && (!demorecording || !(demoflags & DF_GHOST)))
return;
ghostext.flags |= EZT_FLIP;
}
@ -4256,7 +4267,7 @@ void G_GhostAddColor(ghostcolor_t color)
void G_GhostAddScale(fixed_t scale)
{
if (!demorecording || !(demoflags & DF_GHOST))
if (!metalrecording && (!demorecording || !(demoflags & DF_GHOST)))
return;
if (ghostext.lastscale == scale)
{
@ -4282,6 +4293,7 @@ void G_WriteGhostTic(mobj_t *ghost)
char ziptic = 0;
UINT8 *ziptic_p;
UINT32 i;
fixed_t height;
if (!demo_p)
return;
@ -4371,6 +4383,12 @@ void G_WriteGhostTic(mobj_t *ghost)
ghostext.flags |= EZT_SPRITE;
}
if ((height = FixedDiv(ghost->height, ghost->scale)) != oldghost.height)
{
oldghost.height = height;
ghostext.flags |= EZT_HEIGHT;
}
if (ghostext.flags)
{
ziptic |= GZT_EXTRA;
@ -4410,26 +4428,60 @@ void G_WriteGhostTic(mobj_t *ghost)
ghostext.hitlist = NULL;
}
if (ghostext.flags & EZT_SPRITE)
WRITEUINT8(demo_p,oldghost.sprite);
WRITEUINT16(demo_p,oldghost.sprite);
if (ghostext.flags & EZT_HEIGHT)
{
height >>= FRACBITS;
WRITEINT16(demo_p, height);
}
ghostext.flags = 0;
}
if (ghost->player && ghost->player->followmobj) // bloats tails runs but what can ya do
if (ghost->player && ghost->player->followmobj && !(ghost->player->followmobj->sprite == SPR_NULL || (ghost->player->followmobj->flags2 & MF2_DONTDRAW))) // bloats tails runs but what can ya do
{
INT16 temp;
UINT8 *followtic_p = demo_p++;
UINT8 followtic = 0;
ziptic |= GZT_FOLLOW;
if (ghost->player->followmobj->skin)
followtic |= FZT_SKIN;
if (!(oldghost.flags2 & MF2_AMBUSH))
{
followtic |= FZT_SPAWNED;
WRITEINT16(demo_p,ghost->player->followmobj->info->height>>FRACBITS);
if (ghost->player->followmobj->flags2 & MF2_LINKDRAW)
followtic |= FZT_LINKDRAW;
if (ghost->player->followmobj->colorized)
followtic |= FZT_COLORIZED;
if (followtic & FZT_SKIN)
WRITEUINT8(demo_p,(UINT8)(((skin_t *)(ghost->player->followmobj->skin))-skins));
oldghost.flags2 |= MF2_AMBUSH;
}
temp = (INT16)((ghost->player->followmobj->x-ghost->x)>>8);
WRITEINT16(demo_p,temp);
temp = (INT16)((ghost->player->followmobj->y-ghost->y)>>8);
WRITEINT16(demo_p,temp);
temp = (INT16)((ghost->player->followmobj->z-ghost->z)>>8);
WRITEINT16(demo_p,temp);
WRITEUINT8(demo_p,ghost->player->followmobj->sprite);
WRITEUINT8(demo_p,ghost->player->followmobj->sprite2);
if (followtic & FZT_SKIN)
WRITEUINT8(demo_p,ghost->player->followmobj->sprite2);
WRITEUINT16(demo_p,ghost->player->followmobj->sprite);
WRITEUINT8(demo_p,(ghost->player->followmobj->frame & FF_FRAMEMASK));
WRITEUINT8(demo_p,ghost->player->followmobj->color);
if (ghost->player->followmobj->scale != ghost->scale)
{
followtic |= FZT_SCALE;
WRITEFIXED(demo_p,ghost->player->followmobj->scale);
}
*followtic_p = followtic;
}
else
oldghost.flags2 &= ~MF2_AMBUSH;
*ziptic_p = ziptic;
@ -4533,15 +4585,28 @@ void G_ConsGhostTic(void)
}
}
if (xziptic & EZT_SPRITE)
demo_p++;
demo_p += sizeof(UINT16);
if (xziptic & EZT_HEIGHT)
demo_p += sizeof(INT16);
}
if (ziptic & GZT_FOLLOW)
{ // Even more...
UINT8 followtic = READUINT8(demo_p);
if (followtic & FZT_SPAWNED)
{
demo_p += sizeof(INT16);
if (followtic & FZT_SKIN)
demo_p++;
}
if (followtic & FZT_SCALE)
demo_p += sizeof(fixed_t);
demo_p += sizeof(INT16);
demo_p += sizeof(INT16);
demo_p += sizeof(INT16);
demo_p++;
if (followtic & FZT_SKIN)
demo_p++;
demo_p += sizeof(UINT16);
demo_p++;
demo_p++;
}
@ -4629,6 +4694,11 @@ void G_GhostTicker(void)
g->mo->z = g->oldmo.z;
P_SetThingPosition(g->mo);
g->mo->frame = g->oldmo.frame | tr_trans30<<FF_TRANSSHIFT;
if (g->fadein)
{
g->mo->frame += (((--g->fadein)/6)<<FF_TRANSSHIFT); // this calc never exceeds 9 unless g->fadein is bad, and it's only set once, so...
g->mo->flags2 &= ~MF2_DONTDRAW;
}
g->mo->sprite2 = g->oldmo.sprite2;
if (ziptic & GZT_EXTRA)
@ -4686,33 +4756,38 @@ void G_GhostTicker(void)
break;
}
}
if (type == MT_GHOST)
if (type != MT_NULL)
{
mobj = P_SpawnGhostMobj(g->mo); // does a large portion of the work for us
mobj->frame = (mobj->frame & ~FF_FRAMEMASK)|tr_trans60<<FF_TRANSSHIFT; // P_SpawnGhostMobj sets trans50, we want trans60
}
else
{
mobj = P_SpawnMobj(g->mo->x, g->mo->y, g->mo->z - FixedDiv(FixedMul(g->mo->info->height, g->mo->scale) - g->mo->height,3*FRACUNIT), MT_THOK);
mobj->sprite = states[mobjinfo[type].spawnstate].sprite;
mobj->frame = (states[mobjinfo[type].spawnstate].frame & FF_FRAMEMASK) | tr_trans60<<FF_TRANSSHIFT;
mobj->tics = -1; // nope.
mobj->color = g->mo->color;
if (g->mo->eflags & MFE_VERTICALFLIP)
if (type == MT_GHOST)
{
mobj->flags2 |= MF2_OBJECTFLIP;
mobj->eflags |= MFE_VERTICALFLIP;
mobj = P_SpawnGhostMobj(g->mo); // does a large portion of the work for us
mobj->frame = (mobj->frame & ~FF_FRAMEMASK)|tr_trans60<<FF_TRANSSHIFT; // P_SpawnGhostMobj sets trans50, we want trans60
}
P_SetScale(mobj, g->mo->scale);
mobj->destscale = g->mo->scale;
else
{
mobj = P_SpawnMobjFromMobj(g->mo, 0, 0, -FixedDiv(FixedMul(g->mo->info->height, g->mo->scale) - g->mo->height,3*FRACUNIT), MT_THOK);
mobj->sprite = states[mobjinfo[type].spawnstate].sprite;
mobj->frame = (states[mobjinfo[type].spawnstate].frame & FF_FRAMEMASK) | tr_trans60<<FF_TRANSSHIFT;
mobj->color = g->mo->color;
mobj->skin = g->mo->skin;
P_SetScale(mobj, (mobj->destscale = g->mo->scale));
if (type == MT_THOK) // spintrail-specific modification for MT_THOK
{
mobj->frame = FF_TRANS80;
mobj->fuse = mobj->tics;
}
mobj->tics = -1; // nope.
}
mobj->floorz = mobj->z;
mobj->ceilingz = mobj->z+mobj->height;
P_UnsetThingPosition(mobj);
mobj->flags = MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY; // make an ATTEMPT to curb crazy SOCs fucking stuff up...
P_SetThingPosition(mobj);
if (!mobj->fuse)
mobj->fuse = 8;
P_SetTarget(&mobj->target, g->mo);
}
mobj->floorz = mobj->z;
mobj->ceilingz = mobj->z+mobj->height;
P_UnsetThingPosition(mobj);
mobj->flags = MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY; // make an ATTEMPT to curb crazy SOCs fucking stuff up...
P_SetThingPosition(mobj);
mobj->fuse = 8;
P_SetTarget(&mobj->target, g->mo);
}
if (xziptic & EZT_HIT)
{ // Spawn hit poofs for killing things!
@ -4742,7 +4817,12 @@ void G_GhostTicker(void)
}
}
if (xziptic & EZT_SPRITE)
g->mo->sprite = READUINT8(g->p);
g->mo->sprite = READUINT16(g->p);
if (xziptic & EZT_HEIGHT)
{
fixed_t temp = READINT16(g->p)<<FRACBITS;
g->mo->height = FixedMul(temp, g->mo->scale);
}
}
// Tick ghost colors (Super and Mario Invincibility flashing)
@ -4768,55 +4848,81 @@ void G_GhostTicker(void)
#define follow g->mo->tracer
if (ziptic & GZT_FOLLOW)
{ // Even more...
if (!follow)
UINT8 followtic = READUINT8(g->p);
fixed_t temp;
if (followtic & FZT_SPAWNED)
{
mobj_t *newmo = P_SpawnMobj(g->mo->x, g->mo->y, g->mo->z, MT_GHOST);
P_SetTarget(&g->mo->tracer, newmo);
P_SetTarget(&newmo->tracer, g->mo);
newmo->skin = g->mo->skin;
newmo->tics = -1;
newmo->flags2 |= MF2_LINKDRAW;
if (follow)
P_RemoveMobj(follow);
P_SetTarget(&follow, P_SpawnMobjFromMobj(g->mo, 0, 0, 0, MT_GHOST));
P_SetTarget(&follow->tracer, g->mo);
follow->tics = -1;
temp = READINT16(g->p)<<FRACBITS;
follow->height = FixedMul(follow->scale, temp);
follow->eflags = (follow->eflags & ~MFE_VERTICALFLIP)|(g->mo->eflags & MFE_VERTICALFLIP);
follow->destscale = g->mo->destscale;
if (followtic & FZT_LINKDRAW)
follow->flags2 |= MF2_LINKDRAW;
if (followtic & FZT_COLORIZED)
follow->colorized = true;
if (followtic & FZT_SKIN)
follow->skin = &skins[READUINT8(g->p)];
}
if (follow)
{
if (followtic & FZT_SCALE)
follow->destscale = READFIXED(g->p);
else
follow->destscale = g->mo->destscale;
if (follow->destscale != follow->scale)
P_SetScale(follow, follow->destscale);
}
else
{
if (xziptic & EZT_FLIP)
g->mo->eflags ^= MFE_VERTICALFLIP;
if (xziptic & EZT_SCALE)
P_UnsetThingPosition(follow);
temp = READINT16(g->p)<<8;
follow->x = g->mo->x + temp;
temp = READINT16(g->p)<<8;
follow->y = g->mo->y + temp;
temp = READINT16(g->p)<<8;
follow->z = g->mo->z + temp;
P_SetThingPosition(follow);
if (followtic & FZT_SKIN)
follow->sprite2 = READUINT8(g->p);
else
follow->sprite2 = 0;
follow->sprite = READUINT16(g->p);
follow->frame = (READUINT8(g->p)) | (g->mo->frame & FF_TRANSMASK);
follow->angle = g->mo->angle;
follow->color = READUINT8(g->p);
if (!(followtic & FZT_SPAWNED))
{
follow->destscale = g->mo->destscale;
if (follow->destscale != follow->scale)
P_SetScale(follow, follow->destscale);
if (xziptic & EZT_FLIP)
{
follow->flags2 ^= MF2_OBJECTFLIP;
follow->eflags ^= MFE_VERTICALFLIP;
}
}
}
P_UnsetThingPosition(follow);
follow->x = g->mo->x + (READINT16(g->p)<<8);
follow->y = g->mo->y + (READINT16(g->p)<<8);
follow->z = g->mo->z + (READINT16(g->p)<<8);
P_SetThingPosition(follow);
follow->sprite = READUINT8(g->p);
follow->sprite2 = READUINT8(g->p);
follow->frame = (READUINT8(g->p)) | tr_trans30<<FF_TRANSSHIFT;
follow->angle = g->mo->angle;
follow->color = g->mo->color;
}
else if (follow)
{
P_RemoveMobj(follow);
P_SetTarget(&follow, NULL);
}
#undef follow
// Demo ends after ghost data.
if (*g->p == DEMOMARKER)
{
g->mo->momx = g->mo->momy = g->mo->momz = 0;
#if 1 // freeze frame (maybe more useful for time attackers)
g->mo->colorized = true;
if (follow)
follow->colorized = true;
#else // dissapearing act
g->mo->fuse = TICRATE;
if (follow)
follow->fuse = TICRATE;
#endif
if (p)
p->next = g->next;
else
@ -4825,17 +4931,41 @@ void G_GhostTicker(void)
continue;
}
p = g;
#undef follow
}
}
void G_ReadMetalTic(mobj_t *metal)
{
UINT8 ziptic;
UINT16 speed;
UINT8 statetype;
UINT8 xziptic = 0;
if (!metal_p)
return;
if (!metal->health)
{
G_StopMetalDemo();
return;
}
switch (*metal_p)
{
case METALSNICE:
break;
case METALDEATH:
if (metal->tracer)
P_RemoveMobj(metal->tracer);
P_KillMobj(metal, NULL, NULL, 0);
/* FALLTHRU */
case DEMOMARKER:
default:
// end of demo data stream
G_StopMetalDemo();
return;
}
metal_p++;
ziptic = READUINT8(metal_p);
// Read changes from the tic
@ -4862,9 +4992,9 @@ void G_ReadMetalTic(mobj_t *metal)
if (ziptic & GZT_ANGLE)
metal->angle = READUINT8(metal_p)<<24;
if (ziptic & GZT_FRAME)
metal_p++; // Currently unused. (Metal Sonic figures out what he's doing his own damn self.)
oldmetal.frame = READUINT32(metal_p);
if (ziptic & GZT_SPR2)
metal_p++;
oldmetal.sprite2 = READUINT8(metal_p);
// Set movement, position, and angle
// oldmetal contains where you're supposed to be.
@ -4876,67 +5006,160 @@ void G_ReadMetalTic(mobj_t *metal)
metal->y = oldmetal.y;
metal->z = oldmetal.z;
P_SetThingPosition(metal);
metal->frame = oldmetal.frame;
metal->sprite2 = oldmetal.sprite2;
if (ziptic & GZT_EXTRA)
{ // But wait, there's more!
ziptic = READUINT8(metal_p);
if (ziptic & EZT_FLIP)
xziptic = READUINT8(metal_p);
if (xziptic & EZT_FLIP)
metal->eflags ^= MFE_VERTICALFLIP;
if (ziptic & EZT_SCALE)
if (xziptic & EZT_SCALE)
{
metal->destscale = READFIXED(metal_p);
if (metal->destscale != metal->scale)
P_SetScale(metal, metal->destscale);
}
}
if (xziptic & EZT_THOKMASK)
{ // Let's only spawn ONE of these per frame, thanks.
mobj_t *mobj;
INT32 type = -1;
if (metal->skin)
{
skin_t *skin = (skin_t *)metal->skin;
switch (xziptic & EZT_THOKMASK)
{
case EZT_THOK:
type = skin->thokitem < 0 ? (UINT32)mobjinfo[MT_PLAYER].painchance : (UINT32)skin->thokitem;
break;
case EZT_SPIN:
type = skin->spinitem < 0 ? (UINT32)mobjinfo[MT_PLAYER].damage : (UINT32)skin->spinitem;
break;
case EZT_REV:
type = skin->revitem < 0 ? (UINT32)mobjinfo[MT_PLAYER].raisestate : (UINT32)skin->revitem;
break;
}
}
if (type != MT_NULL)
{
if (type == MT_GHOST)
{
mobj = P_SpawnGhostMobj(metal); // does a large portion of the work for us
}
else
{
mobj = P_SpawnMobjFromMobj(metal, 0, 0, -FixedDiv(FixedMul(metal->info->height, metal->scale) - metal->height,3*FRACUNIT), MT_THOK);
mobj->sprite = states[mobjinfo[type].spawnstate].sprite;
mobj->frame = states[mobjinfo[type].spawnstate].frame;
mobj->angle = metal->angle;
mobj->color = metal->color;
mobj->skin = metal->skin;
P_SetScale(mobj, (mobj->destscale = metal->scale));
// Calculates player's speed based on distance-of-a-line formula
speed = FixedDiv(P_AproxDistance(oldmetal.momx, oldmetal.momy), metal->scale)>>FRACBITS;
// Use speed to decide an appropriate state
if (speed > 28) // default skin runspeed
statetype = 2;
else if (speed > 1) // stopspeed
statetype = 1;
else
statetype = 0;
// Set state
if (statetype != metal->threshold)
{
switch (statetype)
{
case 2: // run
P_SetMobjState(metal,metal->info->meleestate);
break;
case 1: // walk
P_SetMobjState(metal,metal->info->seestate);
break;
default: // stand
P_SetMobjState(metal,metal->info->spawnstate);
break;
if (type == MT_THOK) // spintrail-specific modification for MT_THOK
{
mobj->frame = FF_TRANS70;
mobj->fuse = mobj->tics;
}
mobj->tics = -1; // nope.
}
mobj->floorz = mobj->z;
mobj->ceilingz = mobj->z+mobj->height;
P_UnsetThingPosition(mobj);
mobj->flags = MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY; // make an ATTEMPT to curb crazy SOCs fucking stuff up...
P_SetThingPosition(mobj);
if (!mobj->fuse)
mobj->fuse = 8;
P_SetTarget(&mobj->target, metal);
}
}
if (xziptic & EZT_SPRITE)
metal->sprite = READUINT16(metal_p);
if (xziptic & EZT_HEIGHT)
{
fixed_t temp = READINT16(metal_p)<<FRACBITS;
metal->height = FixedMul(temp, metal->scale);
}
metal->threshold = statetype;
}
// TODO: Modify state durations based on movement speed, similar to players?
#define follow metal->tracer
if (ziptic & GZT_FOLLOW)
{ // Even more...
UINT8 followtic = READUINT8(metal_p);
fixed_t temp;
if (followtic & FZT_SPAWNED)
{
if (follow)
P_RemoveMobj(follow);
P_SetTarget(&follow, P_SpawnMobjFromMobj(metal, 0, 0, 0, MT_GHOST));
P_SetTarget(&follow->tracer, metal);
follow->tics = -1;
temp = READINT16(metal_p)<<FRACBITS;
follow->height = FixedMul(follow->scale, temp);
if (*metal_p == DEMOMARKER)
{
// end of demo data stream
G_StopMetalDemo();
return;
}
if (followtic & FZT_LINKDRAW)
follow->flags2 |= MF2_LINKDRAW;
if (followtic & FZT_COLORIZED)
follow->colorized = true;
if (followtic & FZT_SKIN)
follow->skin = &skins[READUINT8(metal_p)];
}
if (follow)
{
if (followtic & FZT_SCALE)
follow->destscale = READFIXED(metal_p);
else
follow->destscale = metal->destscale;
if (follow->destscale != follow->scale)
P_SetScale(follow, follow->destscale);
P_UnsetThingPosition(follow);
temp = READINT16(metal_p)<<8;
follow->x = metal->x + temp;
temp = READINT16(metal_p)<<8;
follow->y = metal->y + temp;
temp = READINT16(metal_p)<<8;
follow->z = metal->z + temp;
P_SetThingPosition(follow);
if (followtic & FZT_SKIN)
follow->sprite2 = READUINT8(metal_p);
else
follow->sprite2 = 0;
follow->sprite = READUINT16(metal_p);
follow->frame = READUINT32(metal_p); // NOT & FF_FRAMEMASK here, so 32 bits
follow->angle = metal->angle;
follow->color = READUINT8(metal_p);
if (!(followtic & FZT_SPAWNED))
{
if (xziptic & EZT_FLIP)
{
follow->flags2 ^= MF2_OBJECTFLIP;
follow->eflags ^= MFE_VERTICALFLIP;
}
}
}
}
else if (follow)
{
P_RemoveMobj(follow);
P_SetTarget(&follow, NULL);
}
#undef follow
}
void G_WriteMetalTic(mobj_t *metal)
{
UINT8 ziptic = 0;
UINT8 *ziptic_p;
fixed_t height;
if (!demo_p) // demo_p will be NULL until the race start linedef executor is triggered!
if (!demo_p) // demo_p will be NULL until the race start linedef executor is activated!
return;
WRITEUINT8(demo_p, METALSNICE);
ziptic_p = demo_p++; // the ziptic, written at the end of this function
#define MAXMOM (0xFFFF<<8)
@ -4949,10 +5172,10 @@ void G_WriteMetalTic(mobj_t *metal)
oldmetal.x = metal->x;
oldmetal.y = metal->y;
oldmetal.z = metal->z;
ziptic |= GZT_XYZ;
WRITEFIXED(demo_p,oldmetal.x);
WRITEFIXED(demo_p,oldmetal.y);
WRITEFIXED(demo_p,oldmetal.z);
ziptic |= GZT_XYZ;
}
else
{
@ -4965,16 +5188,16 @@ void G_WriteMetalTic(mobj_t *metal)
{
oldmetal.momx = momx;
oldmetal.momy = momy;
ziptic |= GZT_MOMXY;
WRITEINT16(demo_p,momx);
WRITEINT16(demo_p,momy);
ziptic |= GZT_MOMXY;
}
momx = (INT16)((metal->z-oldmetal.z)>>8);
if (momx != oldmetal.momz)
{
oldmetal.momz = momx;
WRITEINT16(demo_p,momx);
ziptic |= GZT_MOMZ;
WRITEINT16(demo_p,momx);
}
// This SHOULD set oldmetal.x/y/z to match metal->x/y/z
@ -4997,41 +5220,112 @@ void G_WriteMetalTic(mobj_t *metal)
WRITEUINT8(demo_p,oldmetal.angle);
}
// Metal Sonic does not need our state changes.
// ... currently.
// Store the sprite frame.
if ((metal->frame & FF_FRAMEMASK) != oldmetal.frame)
{
UINT8 *exttic_p = NULL;
UINT8 exttic = 0;
if ((metal->eflags & MFE_VERTICALFLIP) != (oldmetal.eflags & MFE_VERTICALFLIP))
{
if (!exttic_p)
exttic_p = demo_p++;
exttic |= EZT_FLIP;
oldmetal.eflags ^= MFE_VERTICALFLIP;
}
if (metal->scale != oldmetal.scale)
{
if (!exttic_p)
exttic_p = demo_p++;
exttic |= EZT_SCALE;
WRITEFIXED(demo_p,metal->scale);
oldmetal.scale = metal->scale;
}
if (exttic_p)
{
*exttic_p = exttic;
ziptic |= GZT_EXTRA;
}
oldmetal.frame = metal->frame; // NOT & FF_FRAMEMASK here, so 32 bits
ziptic |= GZT_FRAME;
WRITEUINT32(demo_p,oldmetal.frame);
}
if (metal->sprite == SPR_PLAY
&& metal->sprite2 != oldmetal.sprite2)
{
oldmetal.sprite2 = metal->sprite2;
ziptic |= GZT_SPR2;
WRITEUINT8(demo_p,oldmetal.sprite2);
}
// Check for sprite set changes
if (metal->sprite != oldmetal.sprite)
{
oldmetal.sprite = metal->sprite;
ghostext.flags |= EZT_SPRITE;
}
if ((height = FixedDiv(metal->height, metal->scale)) != oldmetal.height)
{
oldmetal.height = height;
ghostext.flags |= EZT_HEIGHT;
}
if (ghostext.flags & ~(EZT_COLOR|EZT_HIT)) // these two aren't handled by metal ever
{
ziptic |= GZT_EXTRA;
if (ghostext.scale == ghostext.lastscale)
ghostext.flags &= ~EZT_SCALE;
WRITEUINT8(demo_p,ghostext.flags);
if (ghostext.flags & EZT_SCALE)
{
WRITEFIXED(demo_p,ghostext.scale);
ghostext.lastscale = ghostext.scale;
}
if (ghostext.flags & EZT_SPRITE)
WRITEUINT16(demo_p,oldmetal.sprite);
if (ghostext.flags & EZT_HEIGHT)
{
height >>= FRACBITS;
WRITEINT16(demo_p, height);
}
ghostext.flags = 0;
}
if (metal->player && metal->player->followmobj && !(metal->player->followmobj->sprite == SPR_NULL || (metal->player->followmobj->flags2 & MF2_DONTDRAW)))
{
INT16 temp;
UINT8 *followtic_p = demo_p++;
UINT8 followtic = 0;
ziptic |= GZT_FOLLOW;
if (metal->player->followmobj->skin)
followtic |= FZT_SKIN;
if (!(oldmetal.flags2 & MF2_AMBUSH))
{
followtic |= FZT_SPAWNED;
WRITEINT16(demo_p,metal->player->followmobj->info->height>>FRACBITS);
if (metal->player->followmobj->flags2 & MF2_LINKDRAW)
followtic |= FZT_LINKDRAW;
if (metal->player->followmobj->colorized)
followtic |= FZT_COLORIZED;
if (followtic & FZT_SKIN)
WRITEUINT8(demo_p,(UINT8)(((skin_t *)(metal->player->followmobj->skin))-skins));
oldmetal.flags2 |= MF2_AMBUSH;
}
if (metal->player->followmobj->scale != metal->scale)
{
followtic |= FZT_SCALE;
WRITEFIXED(demo_p,metal->player->followmobj->scale);
}
temp = (INT16)((metal->player->followmobj->x-metal->x)>>8);
WRITEINT16(demo_p,temp);
temp = (INT16)((metal->player->followmobj->y-metal->y)>>8);
WRITEINT16(demo_p,temp);
temp = (INT16)((metal->player->followmobj->z-metal->z)>>8);
WRITEINT16(demo_p,temp);
if (followtic & FZT_SKIN)
WRITEUINT8(demo_p,metal->player->followmobj->sprite2);
WRITEUINT16(demo_p,metal->player->followmobj->sprite);
WRITEUINT32(demo_p,metal->player->followmobj->frame); // NOT & FF_FRAMEMASK here, so 32 bits
WRITEUINT8(demo_p,metal->player->followmobj->color);
*followtic_p = followtic;
}
else
oldmetal.flags2 &= ~MF2_AMBUSH;
*ziptic_p = ziptic;
// attention here for the ticcmd size!
// latest demos with mouse aiming byte in ticcmd
if (demo_p >= demoend - 32)
{
G_StopMetalRecording(); // no more space
G_StopMetalRecording(false); // no more space
return;
}
}
@ -5165,22 +5459,36 @@ void G_BeginRecording(void)
// And mobjtype_t is best with UINT32 too...
WRITEUINT32(demo_p, player->followitem);
// Save pflag data
// Save pflag data - see SendWeaponPref()
{
UINT8 buf = 0;
if (player->pflags & PF_FLIPCAM)
pflags_t pflags = 0;
if (cv_flipcam.value)
{
buf |= 0x01;
if (player->pflags & PF_ANALOGMODE)
pflags |= PF_FLIPCAM;
}
if (cv_analog.value)
{
buf |= 0x02;
if (player->pflags & PF_DIRECTIONCHAR)
pflags |= PF_ANALOGMODE;
}
if (cv_directionchar.value)
{
buf |= 0x04;
if (player->pflags & PF_AUTOBRAKE)
pflags |= PF_DIRECTIONCHAR;
}
if (cv_autobrake.value)
{
buf |= 0x08;
pflags |= PF_AUTOBRAKE;
}
if (cv_usejoystick.value)
buf |= 0x10;
CV_SetValue(&cv_showinputjoy, !!(cv_usejoystick.value));
WRITEUINT8(demo_p,buf);
player->pflags = pflags;
}
// Save netvar data
@ -5209,8 +5517,10 @@ void G_BeginMetal(void)
{
mobj_t *mo = players[consoleplayer].mo;
#if 0
if (demo_p)
return;
#endif
demo_p = demobuffer;
@ -5225,6 +5535,9 @@ void G_BeginMetal(void)
M_Memcpy(demo_p, "METL", 4); demo_p += 4;
memset(&ghostext,0,sizeof(ghostext));
ghostext.lastscale = ghostext.scale = FRACUNIT;
// Set up our memory.
memset(&oldmetal,0,sizeof(oldmetal));
oldmetal.x = mo->x;
@ -5873,7 +6186,9 @@ void G_AddGhost(char *defdemoname)
gh->mo->state = states+S_PLAY_STND;
gh->mo->sprite = gh->mo->state->sprite;
gh->mo->sprite2 = (gh->mo->state->frame & FF_FRAMEMASK);
gh->mo->frame = tr_trans20<<FF_TRANSSHIFT;
//gh->mo->frame = tr_trans30<<FF_TRANSSHIFT;
gh->mo->flags2 |= MF2_DONTDRAW;
gh->fadein = (9-3)*6; // fade from invisible to trans30 over as close to 35 tics as possible
gh->mo->tics = -1;
CONS_Printf(M_GetText("Added ghost %s from %s\n"), name, pdemoname);
@ -5994,19 +6309,23 @@ void G_StopMetalDemo(void)
}
// Stops metal sonic recording.
ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(void)
ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(boolean kill)
{
boolean saved = false;
if (demo_p)
{
UINT8 *p = demobuffer+16; // checksum position
if (kill)
WRITEUINT8(demo_p, METALDEATH); // add the metal death marker
else
WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker
#ifdef NOMD5
UINT8 i;
WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker
for (i = 0; i < 16; i++, p++)
*p = P_RandomByte(); // This MD5 was chosen by fair dice roll and most likely < 50% correct.
{
UINT8 i;
for (i = 0; i < 16; i++, p++)
*p = P_RandomByte(); // This MD5 was chosen by fair dice roll and most likely < 50% correct.
}
#else
WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker
md5_buffer((char *)p+16, demo_p - (p+16), (void *)p); // make a checksum of everything after the checksum in the file.
#endif
saved = FIL_WriteFile(va("%sMS.LMP", G_BuildMapName(gamemap)), demobuffer, demo_p - demobuffer); // finally output the file.
@ -6064,7 +6383,46 @@ boolean G_CheckDemoStatus(void)
timingdemo = false;
f1 = (double)demotime;
f2 = (double)framecount*TICRATE;
CONS_Printf(M_GetText("timed %u gametics in %d realtics\n%f seconds, %f avg fps\n"), leveltime,demotime,f1/TICRATE,f2/f1);
CONS_Printf(M_GetText("timed %u gametics in %d realtics - %u frames\n%f seconds, %f avg fps\n"),
leveltime,demotime,(UINT32)framecount,f1/TICRATE,f2/f1);
// CSV-readable timedemo results, for external parsing
if (timedemo_csv)
{
FILE *f;
const char *csvpath = va("%s"PATHSEP"%s", srb2home, "timedemo.csv");
const char *header = "id,demoname,seconds,avgfps,leveltime,demotime,framecount,ticrate,rendermode,vidmode,vidwidth,vidheight,procbits\n";
const char *rowformat = "\"%s\",\"%s\",%f,%f,%u,%d,%u,%u,%u,%u,%u,%u,%u\n";
boolean headerrow = !FIL_FileExists(csvpath);
UINT8 procbits = 0;
// Bitness
if (sizeof(void*) == 4)
procbits = 32;
else if (sizeof(void*) == 8)
procbits = 64;
f = fopen(csvpath, "a+");
if (f)
{
if (headerrow)
fputs(header, f);
fprintf(f, rowformat,
timedemo_csv_id,timedemo_name,f1/TICRATE,f2/f1,leveltime,demotime,(UINT32)framecount,TICRATE,rendermode,vid.modenum,vid.width,vid.height,procbits);
fclose(f);
CONS_Printf("Timedemo results saved to '%s'\n", csvpath);
}
else
{
// Just print the CSV output to console
CON_LogMessage(header);
CONS_Printf(rowformat,
timedemo_csv_id,timedemo_name,f1/TICRATE,f2/f1,leveltime,demotime,(UINT32)framecount,TICRATE,rendermode,vid.modenum,vid.width,vid.height,procbits);
}
}
if (restorecv_vidwait != cv_vidwait.value)
CV_SetValue(&cv_vidwait, restorecv_vidwait);
D_AdvanceDemo();

View file

@ -37,6 +37,7 @@ extern boolean playeringame[MAXPLAYERS];
// demoplaying back and demo recording
extern boolean demoplayback, titledemo, demorecording, timingdemo;
extern tic_t demostarttime;
// Quit after playing a demo from cmdline.
extern boolean singledemo;
@ -174,7 +175,7 @@ void G_AddGhost(char *defdemoname);
void G_DoPlayMetal(void);
void G_DoneLevelLoad(void);
void G_StopMetalDemo(void);
ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(void);
ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(boolean kill);
void G_StopDemo(void);
boolean G_CheckDemoStatus(void);

View file

@ -506,43 +506,6 @@ static void HWR_ResizeBlock(INT32 originalwidth, INT32 originalheight,
if (blockheight < 1)
I_Error("3D GenerateTexture : too small");
}
else if (cv_voodoocompatibility.value)
{
if (originalwidth > 256 || originalheight > 256)
{
blockwidth = 256;
while (originalwidth < blockwidth)
blockwidth >>= 1;
if (blockwidth < 1)
I_Error("3D GenerateTexture : too small");
blockheight = 256;
while (originalheight < blockheight)
blockheight >>= 1;
if (blockheight < 1)
I_Error("3D GenerateTexture : too small");
}
else
{
//size up to nearest power of 2
blockwidth = 1;
while (blockwidth < originalwidth)
blockwidth <<= 1;
// scale down the original graphics to fit in 256
if (blockwidth > 256)
blockwidth = 256;
//I_Error("3D GenerateTexture : too big");
//size up to nearest power of 2
blockheight = 1;
while (blockheight < originalheight)
blockheight <<= 1;
// scale down the original graphics to fit in 256
if (blockheight > 256)
blockheight = 255;
//I_Error("3D GenerateTexture : too big");
}
}
else
{
#ifdef GLIDE_API_COMPATIBILITY
@ -771,18 +734,6 @@ void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipm
newwidth = blockwidth;
newheight = blockheight;
}
else if (cv_voodoocompatibility.value) // Only scales down textures that exceed 256x256.
{
// no rounddown, do not size up patches, so they don't look 'scaled'
newwidth = min(grPatch->width, blockwidth);
newheight = min(grPatch->height, blockheight);
if (newwidth > 256 || newheight > 256)
{
newwidth = blockwidth;
newheight = blockheight;
}
}
else
{
// no rounddown, do not size up patches, so they don't look 'scaled'
@ -925,29 +876,6 @@ GLTexture_t *HWR_GetTexture(INT32 tex)
return grtex;
}
// HWR_RenderPlane and HWR_RenderPolyObjectPlane need this to get the flat dimensions from a patch.
lumpnum_t gr_patchflat;
static void HWR_LoadPatchFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum)
{
UINT8 *flat;
patch_t *patch = (patch_t *)W_CacheLumpNum(flatlumpnum, PU_STATIC);
#ifndef NO_PNG_LUMPS
size_t lumplength = W_LumpLength(flatlumpnum);
if (R_IsLumpPNG((UINT8 *)patch, lumplength))
patch = R_PNGToPatch((UINT8 *)patch, lumplength, NULL, false);
#endif
grMipmap->width = (UINT16)SHORT(patch->width);
grMipmap->height = (UINT16)SHORT(patch->height);
flat = Z_Malloc(grMipmap->width * grMipmap->height, PU_HWRCACHE, &grMipmap->grInfo.data);
memset(flat, TRANSPARENTPIXEL, grMipmap->width * grMipmap->height);
R_PatchToFlat(patch, flat);
}
static void HWR_CacheFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum)
{
size_t size, pflatsize;
@ -988,40 +916,15 @@ static void HWR_CacheFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum)
break;
}
if (R_CheckIfPatch(flatlumpnum))
HWR_LoadPatchFlat(grMipmap, flatlumpnum);
else
{
grMipmap->width = (UINT16)pflatsize;
grMipmap->height = (UINT16)pflatsize;
grMipmap->width = (UINT16)pflatsize;
grMipmap->height = (UINT16)pflatsize;
// the flat raw data needn't be converted with palettized textures
W_ReadLump(flatlumpnum, Z_Malloc(W_LumpLength(flatlumpnum),
PU_HWRCACHE, &grMipmap->grInfo.data));
}
// the flat raw data needn't be converted with palettized textures
W_ReadLump(flatlumpnum, Z_Malloc(W_LumpLength(flatlumpnum),
PU_HWRCACHE, &grMipmap->grInfo.data));
}
// Download a Doom 'flat' to the hardware cache and make it ready for use
void HWR_GetFlat(lumpnum_t flatlumpnum)
{
GLMipmap_t *grmip;
grmip = HWR_GetCachedGLPatch(flatlumpnum)->mipmap;
if (!grmip->downloaded && !grmip->grInfo.data)
HWR_CacheFlat(grmip, flatlumpnum);
HWD.pfnSetTexture(grmip);
// The system-memory data can be purged now.
Z_ChangeTag(grmip->grInfo.data, PU_HWRCACHE_UNLOCKED);
gr_patchflat = 0;
if (R_CheckIfPatch(flatlumpnum))
gr_patchflat = flatlumpnum;
}
static void HWR_LoadTextureFlat(GLMipmap_t *grMipmap, INT32 texturenum)
static void HWR_CacheTextureAsFlat(GLMipmap_t *grMipmap, INT32 texturenum)
{
UINT8 *flat;
@ -1043,24 +946,53 @@ static void HWR_LoadTextureFlat(GLMipmap_t *grMipmap, INT32 texturenum)
R_TextureToFlat(texturenum, flat);
}
void HWR_GetTextureFlat(INT32 texturenum)
// Download a Doom 'flat' to the hardware cache and make it ready for use
void HWR_LiterallyGetFlat(lumpnum_t flatlumpnum)
{
GLTexture_t *grtex;
#ifdef PARANOIA
if ((unsigned)texturenum >= gr_numtextures)
I_Error("HWR_GetTextureFlat: texturenum >= numtextures\n");
#endif
if (texturenum == 0 || texturenum == -1)
GLMipmap_t *grmip;
if (flatlumpnum == LUMPERROR)
return;
grtex = &gr_textures2[texturenum];
if (!grtex->mipmap.grInfo.data && !grtex->mipmap.downloaded)
HWR_LoadTextureFlat(&grtex->mipmap, texturenum);
grmip = HWR_GetCachedGLPatch(flatlumpnum)->mipmap;
if (!grmip->downloaded && !grmip->grInfo.data)
HWR_CacheFlat(grmip, flatlumpnum);
HWD.pfnSetTexture(&grtex->mipmap);
HWD.pfnSetTexture(grmip);
// The system-memory data can be purged now.
Z_ChangeTag(grtex->mipmap.grInfo.data, PU_HWRCACHE_UNLOCKED);
Z_ChangeTag(grmip->grInfo.data, PU_HWRCACHE_UNLOCKED);
}
void HWR_GetLevelFlat(levelflat_t *levelflat)
{
// Who knows?
if (levelflat == NULL)
return;
if (levelflat->type == LEVELFLAT_FLAT)
HWR_LiterallyGetFlat(levelflat->u.flat.lumpnum);
else if (levelflat->type == LEVELFLAT_TEXTURE)
{
GLTexture_t *grtex;
INT32 texturenum = levelflat->u.texture.num;
#ifdef PARANOIA
if ((unsigned)texturenum >= gr_numtextures)
I_Error("HWR_GetLevelFlat: texturenum >= numtextures\n");
#endif
if (texturenum == 0 || texturenum == -1)
return;
grtex = &gr_textures2[texturenum];
if (!grtex->mipmap.grInfo.data && !grtex->mipmap.downloaded)
HWR_CacheTextureAsFlat(&grtex->mipmap, texturenum);
HWD.pfnSetTexture(&grtex->mipmap);
// The system-memory data can be purged now.
Z_ChangeTag(grtex->mipmap.grInfo.data, PU_HWRCACHE_UNLOCKED);
}
else // set no texture
HWD.pfnSetTexture(NULL);
}
//
@ -1286,18 +1218,6 @@ GLPatch_t *HWR_GetPic(lumpnum_t lumpnum)
newwidth = blockwidth;
newheight = blockheight;
}
else if (cv_voodoocompatibility.value) // Only scales down textures that exceed 256x256.
{
// no rounddown, do not size up patches, so they don't look 'scaled'
newwidth = min(SHORT(pic->width),blockwidth);
newheight = min(SHORT(pic->height),blockheight);
if (newwidth > 256 || newheight > 256)
{
newwidth = blockwidth;
newheight = blockheight;
}
}
else
{
// no rounddown, do not size up patches, so they don't look 'scaled'

View file

@ -77,8 +77,8 @@
#include "r_opengl/r_opengl.h"
#ifdef HAVE_SPHEREFRUSTRUM
static GLdouble viewMatrix[16];
static GLdouble projMatrix[16];
static GLfloat viewMatrix[16];
static GLfloat projMatrix[16];
float frustum[6][4];
#endif
@ -380,8 +380,8 @@ void gld_FrustrumSetup(void)
float t;
float clip[16];
pglGetDoublev(GL_PROJECTION_MATRIX, projMatrix);
pglGetDoublev(GL_MODELVIEW_MATRIX, viewMatrix);
pglGeFloatv(GL_PROJECTION_MATRIX, projMatrix);
pglGetFloatv(GL_MODELVIEW_MATRIX, viewMatrix);
clip[0] = CALCMATRIX(0, 0, 1, 4, 2, 8, 3, 12);
clip[1] = CALCMATRIX(0, 1, 1, 5, 2, 9, 3, 13);

View file

@ -95,18 +95,34 @@ typedef struct
//Hurdler: Transform (coords + angles)
//BP: transform order : scale(rotation_x(rotation_y(translation(v))))
// Kart features
//#define USE_FTRANSFORM_ANGLEZ
//#define USE_FTRANSFORM_MIRROR
// Vanilla features
#define USE_MODEL_NEXTFRAME
typedef struct
{
FLOAT x,y,z; // position
#ifdef USE_FTRANSFORM_ANGLEZ
FLOAT anglex,angley,anglez; // aimingangle / viewangle
#else
FLOAT anglex,angley; // aimingangle / viewangle
#endif
FLOAT scalex,scaley,scalez;
FLOAT fovxangle, fovyangle;
INT32 splitscreen;
UINT8 splitscreen;
boolean flip; // screenflip
#ifdef ROTSPRITE
// rotsprite
boolean roll;
FLOAT centerx,centery;
SINT8 nightsroll;
FLOAT rollangle; // done to not override USE_FTRANSFORM_ANGLEZ
FLOAT centerx, centery;
#endif
#ifdef USE_FTRANSFORM_MIRROR
boolean mirror; // SRB2Kart: Encore Mode
#endif
} FTransform;
@ -150,7 +166,7 @@ enum EPolyFlags
// When set, pass the color constant into the FSurfaceInfo -> FlatColor
PF_NoTexture = 0x00002000, // Use the small white texture
PF_Corona = 0x00004000, // Tell the rendrer we are drawing a corona
PF_MD2 = 0x00008000, // Tell the rendrer we are drawing an MD2
PF_Unused = 0x00008000, // Unused
PF_RemoveYWrap = 0x00010000, // Force clamp texture on Y
PF_ForceWrapX = 0x00020000, // Force repeat texture on X
PF_ForceWrapY = 0x00040000, // Force repeat texture on Y
@ -208,8 +224,6 @@ enum hwdsetspecialstate
HWD_SET_FOG_COLOR,
HWD_SET_FOG_DENSITY,
HWD_SET_FOV,
HWD_SET_POLYGON_SMOOTH,
HWD_SET_PALETTECOLOR,
HWD_SET_TEXTUREFILTERMODE,
HWD_SET_TEXTUREANISOTROPICMODE,
HWD_NUMSTATE

View file

@ -647,7 +647,7 @@ void HWR_DrawFlatFill (INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatlumpnum
v[0].tow = v[1].tow = (float)((y & flatflag)/dflatsize);
v[2].tow = v[3].tow = (float)(v[0].tow + h/dflatsize);
HWR_GetFlat(flatlumpnum);
HWR_LiterallyGetFlat(flatlumpnum);
//Hurdler: Boris, the same comment as above... but maybe for pics
// it not a problem since they don't have any transparent pixel

View file

@ -59,20 +59,18 @@ EXPORT void HWRAPI(ClearMipMapCache) (void);
EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value);
//Hurdler: added for new development
EXPORT void HWRAPI(DrawMD2) (INT32 *gl_cmd_buffer, md2_frame_t *frame, FTransform *pos, float scale);
EXPORT void HWRAPI(DrawMD2i) (INT32 *gl_cmd_buffer, md2_frame_t *frame, INT32 duration, INT32 tics, md2_frame_t *nextframe, FTransform *pos, float scale, UINT8 flipped, UINT8 *color);
EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, UINT8 *color);
EXPORT void HWRAPI(CreateModelVBOs) (model_t *model);
EXPORT void HWRAPI(SetTransform) (FTransform *ptransform);
EXPORT INT32 HWRAPI(GetTextureUsed) (void);
EXPORT INT32 HWRAPI(GetRenderVersion) (void);
#ifdef SHUFFLE
#define SCREENVERTS 10
EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]);
#endif
EXPORT void HWRAPI(FlushScreenTextures) (void);
EXPORT void HWRAPI(StartScreenWipe) (void);
EXPORT void HWRAPI(EndScreenWipe) (void);
EXPORT void HWRAPI(DoScreenWipe) (float alpha);
EXPORT void HWRAPI(DoScreenWipe) (void);
EXPORT void HWRAPI(DrawIntermissionBG) (void);
EXPORT void HWRAPI(MakeScreenTexture) (void);
EXPORT void HWRAPI(MakeScreenFinalTexture) (void);
@ -98,8 +96,8 @@ struct hwdriver_s
GClipRect pfnGClipRect;
ClearMipMapCache pfnClearMipMapCache;
SetSpecialState pfnSetSpecialState;//Hurdler: added for backward compatibility
DrawMD2 pfnDrawMD2;
DrawMD2i pfnDrawMD2i;
DrawModel pfnDrawModel;
CreateModelVBOs pfnCreateModelVBOs;
SetTransform pfnSetTransform;
GetTextureUsed pfnGetTextureUsed;
GetRenderVersion pfnGetRenderVersion;
@ -109,9 +107,7 @@ struct hwdriver_s
#ifndef HAVE_SDL
Shutdown pfnShutdown;
#endif
#ifdef SHUFFLE
PostImgRedraw pfnPostImgRedraw;
#endif
FlushScreenTextures pfnFlushScreenTextures;
StartScreenWipe pfnStartScreenWipe;
EndScreenWipe pfnEndScreenWipe;

View file

@ -23,6 +23,7 @@
#include "hw_defs.h"
#include "hw_main.h"
#include "../m_misc.h"
#include "../p_setup.h"
// the original aspect ratio of Doom graphics isn't square
#define ORIGINAL_ASPECT (320.0f/200.0f)
@ -101,8 +102,8 @@ void HWR_InitTextureCache(void);
void HWR_FreeTextureCache(void);
void HWR_FreeExtraSubsectors(void);
void HWR_GetFlat(lumpnum_t flatlumpnum);
void HWR_GetTextureFlat(INT32 texturenum);
void HWR_GetLevelFlat(levelflat_t *levelflat);
void HWR_LiterallyGetFlat(lumpnum_t flatlumpnum);
GLTexture_t *HWR_GetTexture(INT32 tex);
void HWR_GetPatch(GLPatch_t *gpatch);
void HWR_GetMappedPatch(GLPatch_t *gpatch, const UINT8 *colormap);
@ -119,8 +120,6 @@ void HWR_GetFadeMask(lumpnum_t fademasklumpnum);
// --------
// hw_draw.c
// --------
extern lumpnum_t gr_patchflat;
extern float gr_patch_scalex;
extern float gr_patch_scaley;

View file

@ -71,12 +71,12 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing);
#endif
#ifdef SORTING
void HWR_AddTransparentFloor(lumpnum_t lumpnum, INT32 texturenum, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight,
void HWR_AddTransparentFloor(levelflat_t *levelflat, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight,
INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, extracolormap_t *planecolormap);
void HWR_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, INT32 texturenum, polyobj_t *polysector, boolean isceiling, fixed_t fixedheight,
void HWR_AddTransparentPolyobjectFloor(levelflat_t *levelflat, polyobj_t *polysector, boolean isceiling, fixed_t fixedheight,
INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, extracolormap_t *planecolormap);
#else
static void HWR_Add3DWater(lumpnum_t lumpnum, extrasubsector_t *xsub, fixed_t fixedheight,
static void HWR_Add3DWater(levelflat_t *levelflat, extrasubsector_t *xsub, fixed_t fixedheight,
INT32 lightlevel, INT32 alpha, sector_t *FOFSector);
static void HWR_Render3DWater(void);
static void HWR_RenderTransparentWalls(void);
@ -523,7 +523,7 @@ static UINT8 HWR_FogBlockAlpha(INT32 light, UINT32 color) // Let's see if this c
// HWR_RenderPlane : Render a floor or ceiling convex polygon
// -----------------+
static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight,
FBITFIELD PolyFlags, INT32 lightlevel, lumpnum_t lumpnum, INT32 texturenum, sector_t *FOFsector, UINT8 alpha, boolean fogplane, extracolormap_t *planecolormap)
FBITFIELD PolyFlags, INT32 lightlevel, levelflat_t *levelflat, sector_t *FOFsector, UINT8 alpha, boolean fogplane, extracolormap_t *planecolormap)
{
polyvertex_t * pv;
float height; //constant y for all points on the convex flat polygon
@ -531,9 +531,9 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is
INT32 nrPlaneVerts; //verts original define of convex flat polygon
INT32 i;
float flatxref,flatyref;
float fflatwidth, fflatheight;
INT32 flatflag;
boolean texflat = true;
float fflatwidth = 64.0f, fflatheight = 64.0f;
INT32 flatflag = 63;
boolean texflat = false;
size_t len;
float scrollx = 0.0f, scrolly = 0.0f;
angle_t angle = 0;
@ -542,7 +542,6 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is
#ifdef ESLOPE
pslope_t *slope = NULL;
#endif
patch_t *patch;
static FOutVector *planeVerts = NULL;
static UINT16 numAllocedPlaneVerts = 0;
@ -598,48 +597,49 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is
Z_Malloc(numAllocedPlaneVerts * sizeof (FOutVector), PU_LEVEL, &planeVerts);
}
len = W_LumpLength(lumpnum);
switch (len)
// set texture for polygon
if (levelflat != NULL)
{
case 4194304: // 2048x2048 lump
fflatwidth = fflatheight = 2048.0f;
break;
case 1048576: // 1024x1024 lump
fflatwidth = fflatheight = 1024.0f;
break;
case 262144:// 512x512 lump
fflatwidth = fflatheight = 512.0f;
break;
case 65536: // 256x256 lump
fflatwidth = fflatheight = 256.0f;
break;
case 16384: // 128x128 lump
fflatwidth = fflatheight = 128.0f;
break;
case 1024: // 32x32 lump
fflatwidth = fflatheight = 32.0f;
break;
default: // 64x64 lump
fflatwidth = fflatheight = 64.0f;
break;
}
if (levelflat->type == LEVELFLAT_TEXTURE)
{
fflatwidth = textures[levelflat->u.texture.num]->width;
fflatheight = textures[levelflat->u.texture.num]->height;
texflat = true;
}
else if (levelflat->type == LEVELFLAT_FLAT)
{
len = W_LumpLength(levelflat->u.flat.lumpnum);
flatflag = ((INT32)fflatwidth)-1;
switch (len)
{
case 4194304: // 2048x2048 lump
fflatwidth = fflatheight = 2048.0f;
break;
case 1048576: // 1024x1024 lump
fflatwidth = fflatheight = 1024.0f;
break;
case 262144:// 512x512 lump
fflatwidth = fflatheight = 512.0f;
break;
case 65536: // 256x256 lump
fflatwidth = fflatheight = 256.0f;
break;
case 16384: // 128x128 lump
fflatwidth = fflatheight = 128.0f;
break;
case 1024: // 32x32 lump
fflatwidth = fflatheight = 32.0f;
break;
default: // 64x64 lump
fflatwidth = fflatheight = 64.0f;
break;
}
if (texturenum != 0 && texturenum != -1)
{
fflatwidth = textures[texturenum]->width;
fflatheight = textures[texturenum]->height;
flatflag = ((INT32)fflatwidth)-1;
}
}
else if (gr_patchflat && R_CheckIfPatch(gr_patchflat)) // Just in case?
{
patch = (patch_t *)W_CacheLumpNum(gr_patchflat, PU_STATIC);
fflatwidth = SHORT(patch->width);
fflatheight = SHORT(patch->height);
}
else
texflat = false;
else // set no texture
HWD.pfnSetTexture(NULL);
// reference point for flat texture coord for each vertex around the polygon
flatxref = (float)(((fixed_t)pv->x & (~flatflag)) / fflatwidth);
@ -1973,7 +1973,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
{
// Single sided line... Deal only with the middletexture (if one exists)
gr_midtexture = R_GetTextureNum(gr_sidedef->midtexture);
if (gr_midtexture)
if (gr_midtexture && gr_linedef->special != 41) // Ignore horizon line for OGL
{
{
fixed_t texturevpeg;
@ -3184,23 +3184,22 @@ static inline void HWR_AddPolyObjectSegs(void)
#ifdef POLYOBJECTS_PLANES
static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, fixed_t fixedheight,
FBITFIELD blendmode, UINT8 lightlevel, lumpnum_t lumpnum, INT32 texturenum, sector_t *FOFsector,
FBITFIELD blendmode, UINT8 lightlevel, levelflat_t *levelflat, sector_t *FOFsector,
UINT8 alpha, extracolormap_t *planecolormap)
{
float height; //constant y for all points on the convex flat polygon
FOutVector *v3d;
INT32 i;
float flatxref,flatyref;
float fflatwidth, fflatheight;
INT32 flatflag;
boolean texflat = true;
float fflatwidth = 64.0f, fflatheight = 64.0f;
INT32 flatflag = 63;
boolean texflat = false;
size_t len;
float scrollx = 0.0f, scrolly = 0.0f;
angle_t angle = 0;
FSurfaceInfo Surf;
fixed_t tempxsow, tempytow;
size_t nrPlaneVerts;
patch_t *patch;
static FOutVector *planeVerts = NULL;
static UINT16 numAllocedPlaneVerts = 0;
@ -3226,48 +3225,49 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling,
Z_Malloc(numAllocedPlaneVerts * sizeof (FOutVector), PU_LEVEL, &planeVerts);
}
len = W_LumpLength(lumpnum);
switch (len)
// set texture for polygon
if (levelflat != NULL)
{
case 4194304: // 2048x2048 lump
fflatwidth = fflatheight = 2048.0f;
break;
case 1048576: // 1024x1024 lump
fflatwidth = fflatheight = 1024.0f;
break;
case 262144:// 512x512 lump
fflatwidth = fflatheight = 512.0f;
break;
case 65536: // 256x256 lump
fflatwidth = fflatheight = 256.0f;
break;
case 16384: // 128x128 lump
fflatwidth = fflatheight = 128.0f;
break;
case 1024: // 32x32 lump
fflatwidth = fflatheight = 32.0f;
break;
default: // 64x64 lump
fflatwidth = fflatheight = 64.0f;
break;
}
if (levelflat->type == LEVELFLAT_TEXTURE)
{
fflatwidth = textures[levelflat->u.texture.num]->width;
fflatheight = textures[levelflat->u.texture.num]->height;
texflat = true;
}
else if (levelflat->type == LEVELFLAT_FLAT)
{
len = W_LumpLength(levelflat->u.flat.lumpnum);
flatflag = ((INT32)fflatwidth)-1;
switch (len)
{
case 4194304: // 2048x2048 lump
fflatwidth = fflatheight = 2048.0f;
break;
case 1048576: // 1024x1024 lump
fflatwidth = fflatheight = 1024.0f;
break;
case 262144:// 512x512 lump
fflatwidth = fflatheight = 512.0f;
break;
case 65536: // 256x256 lump
fflatwidth = fflatheight = 256.0f;
break;
case 16384: // 128x128 lump
fflatwidth = fflatheight = 128.0f;
break;
case 1024: // 32x32 lump
fflatwidth = fflatheight = 32.0f;
break;
default: // 64x64 lump
fflatwidth = fflatheight = 64.0f;
break;
}
if (texturenum != 0 && texturenum != -1)
{
fflatwidth = textures[texturenum]->width;
fflatheight = textures[texturenum]->height;
flatflag = ((INT32)fflatwidth)-1;
}
}
else if (gr_patchflat && R_CheckIfPatch(gr_patchflat)) // Just in case?
{
patch = (patch_t *)W_CacheLumpNum(gr_patchflat, PU_STATIC);
fflatwidth = SHORT(patch->width);
fflatheight = SHORT(patch->height);
}
else
texflat = false;
else // set no texture
HWD.pfnSetTexture(NULL);
// reference point for flat texture coord for each vertex around the polygon
flatxref = (float)((polysector->origVerts[0].x & (~flatflag)) / fflatwidth);
@ -3401,15 +3401,14 @@ static void HWR_AddPolyObjectPlanes(void)
FBITFIELD blendmode;
memset(&Surf, 0x00, sizeof(Surf));
blendmode = HWR_TranstableToAlpha(po_ptrs[i]->translucency, &Surf);
HWR_AddTransparentPolyobjectFloor(levelflats[polyobjsector->floorpic].lumpnum, levelflats[polyobjsector->floorpic].texturenum, po_ptrs[i], false, polyobjsector->floorheight,
HWR_AddTransparentPolyobjectFloor(&levelflats[polyobjsector->floorpic], po_ptrs[i], false, polyobjsector->floorheight,
(light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), Surf.FlatColor.s.alpha, polyobjsector, blendmode, (light == -1 ? gr_frontsector->extra_colormap : *gr_frontsector->lightlist[light].extra_colormap));
}
else
{
HWR_GetFlat(levelflats[polyobjsector->floorpic].lumpnum);
HWR_GetTextureFlat(levelflats[polyobjsector->floorpic].texturenum);
HWR_GetLevelFlat(&levelflats[polyobjsector->floorpic]);
HWR_RenderPolyObjectPlane(po_ptrs[i], false, polyobjsector->floorheight, PF_Occlude,
(light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), levelflats[polyobjsector->floorpic].lumpnum, levelflats[polyobjsector->floorpic].texturenum,
(light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), &levelflats[polyobjsector->floorpic],
polyobjsector, 255, (light == -1 ? gr_frontsector->extra_colormap : *gr_frontsector->lightlist[light].extra_colormap));
}
}
@ -3425,15 +3424,14 @@ static void HWR_AddPolyObjectPlanes(void)
FBITFIELD blendmode;
memset(&Surf, 0x00, sizeof(Surf));
blendmode = HWR_TranstableToAlpha(po_ptrs[i]->translucency, &Surf);
HWR_AddTransparentPolyobjectFloor(levelflats[polyobjsector->ceilingpic].lumpnum, levelflats[polyobjsector->floorpic].texturenum, po_ptrs[i], true, polyobjsector->ceilingheight,
HWR_AddTransparentPolyobjectFloor(&levelflats[polyobjsector->ceilingpic], po_ptrs[i], true, polyobjsector->ceilingheight,
(light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), Surf.FlatColor.s.alpha, polyobjsector, blendmode, (light == -1 ? gr_frontsector->extra_colormap : *gr_frontsector->lightlist[light].extra_colormap));
}
else
{
HWR_GetFlat(levelflats[polyobjsector->ceilingpic].lumpnum);
HWR_GetTextureFlat(levelflats[polyobjsector->ceilingpic].texturenum);
HWR_GetLevelFlat(&levelflats[polyobjsector->ceilingpic]);
HWR_RenderPolyObjectPlane(po_ptrs[i], true, polyobjsector->ceilingheight, PF_Occlude,
(light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), levelflats[polyobjsector->floorpic].lumpnum, levelflats[polyobjsector->floorpic].texturenum,
(light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), &levelflats[polyobjsector->floorpic],
polyobjsector, 255, (light == -1 ? gr_frontsector->extra_colormap : *gr_frontsector->lightlist[light].extra_colormap));
}
}
@ -3584,13 +3582,12 @@ static void HWR_Subsector(size_t num)
{
if (sub->validcount != validcount)
{
HWR_GetFlat(levelflats[gr_frontsector->floorpic].lumpnum);
HWR_GetTextureFlat(levelflats[gr_frontsector->floorpic].texturenum);
HWR_GetLevelFlat(&levelflats[gr_frontsector->floorpic]);
HWR_RenderPlane(gr_frontsector, &extrasubsectors[num], false,
// Hack to make things continue to work around slopes.
locFloorHeight == cullFloorHeight ? locFloorHeight : gr_frontsector->floorheight,
// We now return you to your regularly scheduled rendering.
PF_Occlude, floorlightlevel, levelflats[gr_frontsector->floorpic].lumpnum, levelflats[gr_frontsector->floorpic].texturenum, NULL, 255, false, floorcolormap);
PF_Occlude, floorlightlevel, &levelflats[gr_frontsector->floorpic], NULL, 255, false, floorcolormap);
}
}
else
@ -3607,13 +3604,12 @@ static void HWR_Subsector(size_t num)
{
if (sub->validcount != validcount)
{
HWR_GetFlat(levelflats[gr_frontsector->ceilingpic].lumpnum);
HWR_GetTextureFlat(levelflats[gr_frontsector->ceilingpic].texturenum);
HWR_GetLevelFlat(&levelflats[gr_frontsector->ceilingpic]);
HWR_RenderPlane(NULL, &extrasubsectors[num], true,
// Hack to make things continue to work around slopes.
locCeilingHeight == cullCeilingHeight ? locCeilingHeight : gr_frontsector->ceilingheight,
// We now return you to your regularly scheduled rendering.
PF_Occlude, ceilinglightlevel, levelflats[gr_frontsector->ceilingpic].lumpnum, levelflats[gr_frontsector->ceilingpic].texturenum, NULL, 255, false, ceilingcolormap);
PF_Occlude, ceilinglightlevel, &levelflats[gr_frontsector->ceilingpic], NULL, 255, false, ceilingcolormap);
}
}
else
@ -3672,7 +3668,7 @@ static void HWR_Subsector(size_t num)
else
alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, NORMALFOG);
HWR_AddTransparentFloor(0, 0,
HWR_AddTransparentFloor(NULL,
&extrasubsectors[num],
false,
*rover->bottomheight,
@ -3684,14 +3680,13 @@ static void HWR_Subsector(size_t num)
{
light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false);
#ifndef SORTING
HWR_Add3DWater(levelflats[*rover->bottompic].lumpnum,
HWR_Add3DWater(&levelflats[*rover->bottompic],
&extrasubsectors[num],
*rover->bottomheight,
*gr_frontsector->lightlist[light].lightlevel,
rover->alpha-1, rover->master->frontsector);
#else
HWR_AddTransparentFloor(levelflats[*rover->bottompic].lumpnum,
levelflats[*rover->bottompic].texturenum,
HWR_AddTransparentFloor(&levelflats[*rover->bottompic],
&extrasubsectors[num],
false,
*rover->bottomheight,
@ -3702,10 +3697,9 @@ static void HWR_Subsector(size_t num)
}
else
{
HWR_GetFlat(levelflats[*rover->bottompic].lumpnum);
HWR_GetTextureFlat(levelflats[*rover->bottompic].texturenum);
HWR_GetLevelFlat(&levelflats[*rover->bottompic]);
light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false);
HWR_RenderPlane(NULL, &extrasubsectors[num], false, *rover->bottomheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->bottompic].lumpnum, levelflats[*rover->bottompic].texturenum,
HWR_RenderPlane(NULL, &extrasubsectors[num], false, *rover->bottomheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, &levelflats[*rover->bottompic],
rover->master->frontsector, 255, false, *gr_frontsector->lightlist[light].extra_colormap);
}
}
@ -3737,7 +3731,7 @@ static void HWR_Subsector(size_t num)
else
alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, NORMALFOG);
HWR_AddTransparentFloor(0, 0,
HWR_AddTransparentFloor(NULL,
&extrasubsectors[num],
true,
*rover->topheight,
@ -3749,14 +3743,13 @@ static void HWR_Subsector(size_t num)
{
light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false);
#ifndef SORTING
HWR_Add3DWater(levelflats[*rover->toppic].lumpnum,
HWR_Add3DWater(&levelflats[*rover->toppic],
&extrasubsectors[num],
*rover->topheight,
*gr_frontsector->lightlist[light].lightlevel,
rover->alpha-1, rover->master->frontsector);
#else
HWR_AddTransparentFloor(levelflats[*rover->toppic].lumpnum,
levelflats[*rover->bottompic].texturenum,
HWR_AddTransparentFloor(&levelflats[*rover->toppic],
&extrasubsectors[num],
true,
*rover->topheight,
@ -3768,10 +3761,9 @@ static void HWR_Subsector(size_t num)
}
else
{
HWR_GetFlat(levelflats[*rover->toppic].lumpnum);
HWR_GetTextureFlat(levelflats[*rover->toppic].texturenum);
HWR_GetLevelFlat(&levelflats[*rover->toppic]);
light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false);
HWR_RenderPlane(NULL, &extrasubsectors[num], true, *rover->topheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->toppic].lumpnum, levelflats[*rover->toppic].texturenum,
HWR_RenderPlane(NULL, &extrasubsectors[num], true, *rover->topheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, &levelflats[*rover->toppic],
rover->master->frontsector, 255, false, *gr_frontsector->lightlist[light].extra_colormap);
}
}
@ -5099,8 +5091,7 @@ typedef struct
boolean isceiling;
fixed_t fixedheight;
INT32 lightlevel;
lumpnum_t lumpnum;
INT32 texturenum;
levelflat_t *levelflat;
INT32 alpha;
sector_t *FOFSector;
FBITFIELD blend;
@ -5118,8 +5109,7 @@ typedef struct
boolean isceiling;
fixed_t fixedheight;
INT32 lightlevel;
lumpnum_t lumpnum;
INT32 texturenum;
levelflat_t *levelflat;
INT32 alpha;
sector_t *FOFSector;
FBITFIELD blend;
@ -5150,7 +5140,7 @@ static INT32 drawcount = 0;
#define MAX_TRANSPARENTFLOOR 512
// This will likely turn into a copy of HWR_Add3DWater and replace it.
void HWR_AddTransparentFloor(lumpnum_t lumpnum, INT32 texturenum, extrasubsector_t *xsub, boolean isceiling,
void HWR_AddTransparentFloor(levelflat_t *levelflat, extrasubsector_t *xsub, boolean isceiling,
fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, extracolormap_t *planecolormap)
{
static size_t allocedplanes = 0;
@ -5168,8 +5158,7 @@ void HWR_AddTransparentFloor(lumpnum_t lumpnum, INT32 texturenum, extrasubsector
planeinfo[numplanes].isceiling = isceiling;
planeinfo[numplanes].fixedheight = fixedheight;
planeinfo[numplanes].lightlevel = lightlevel;
planeinfo[numplanes].lumpnum = lumpnum;
planeinfo[numplanes].texturenum = texturenum;
planeinfo[numplanes].levelflat = levelflat;
planeinfo[numplanes].xsub = xsub;
planeinfo[numplanes].alpha = alpha;
planeinfo[numplanes].FOFSector = FOFSector;
@ -5183,7 +5172,7 @@ void HWR_AddTransparentFloor(lumpnum_t lumpnum, INT32 texturenum, extrasubsector
// Adding this for now until I can create extrasubsector info for polyobjects
// When that happens it'll just be done through HWR_AddTransparentFloor and HWR_RenderPlane
void HWR_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, INT32 texturenum, polyobj_t *polysector, boolean isceiling,
void HWR_AddTransparentPolyobjectFloor(levelflat_t *levelflat, polyobj_t *polysector, boolean isceiling,
fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, extracolormap_t *planecolormap)
{
static size_t allocedpolyplanes = 0;
@ -5201,8 +5190,7 @@ void HWR_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, INT32 texturenum, poly
polyplaneinfo[numpolyplanes].isceiling = isceiling;
polyplaneinfo[numpolyplanes].fixedheight = fixedheight;
polyplaneinfo[numpolyplanes].lightlevel = lightlevel;
polyplaneinfo[numpolyplanes].lumpnum = lumpnum;
polyplaneinfo[numpolyplanes].texturenum = texturenum;
polyplaneinfo[numpolyplanes].levelflat = levelflat;
polyplaneinfo[numpolyplanes].polysector = polysector;
polyplaneinfo[numpolyplanes].alpha = alpha;
polyplaneinfo[numpolyplanes].FOFSector = FOFSector;
@ -5364,12 +5352,9 @@ static void HWR_CreateDrawNodes(void)
gr_frontsector = NULL;
if (!(sortnode[sortindex[i]].plane->blend & PF_NoTexture))
{
HWR_GetFlat(sortnode[sortindex[i]].plane->lumpnum);
HWR_GetTextureFlat(sortnode[sortindex[i]].plane->texturenum);
}
HWR_GetLevelFlat(sortnode[sortindex[i]].plane->levelflat);
HWR_RenderPlane(NULL, sortnode[sortindex[i]].plane->xsub, sortnode[sortindex[i]].plane->isceiling, sortnode[sortindex[i]].plane->fixedheight, sortnode[sortindex[i]].plane->blend, sortnode[sortindex[i]].plane->lightlevel,
sortnode[sortindex[i]].plane->lumpnum, sortnode[sortindex[i]].plane->texturenum, sortnode[sortindex[i]].plane->FOFSector, sortnode[sortindex[i]].plane->alpha, sortnode[sortindex[i]].plane->fogplane, sortnode[sortindex[i]].plane->planecolormap);
sortnode[sortindex[i]].plane->levelflat, sortnode[sortindex[i]].plane->FOFSector, sortnode[sortindex[i]].plane->alpha, sortnode[sortindex[i]].plane->fogplane, sortnode[sortindex[i]].plane->planecolormap);
}
else if (sortnode[sortindex[i]].polyplane)
{
@ -5377,12 +5362,9 @@ static void HWR_CreateDrawNodes(void)
gr_frontsector = NULL;
if (!(sortnode[sortindex[i]].polyplane->blend & PF_NoTexture))
{
HWR_GetFlat(sortnode[sortindex[i]].polyplane->lumpnum);
HWR_GetTextureFlat(sortnode[sortindex[i]].polyplane->texturenum);
}
HWR_GetLevelFlat(sortnode[sortindex[i]].polyplane->levelflat);
HWR_RenderPolyObjectPlane(sortnode[sortindex[i]].polyplane->polysector, sortnode[sortindex[i]].polyplane->isceiling, sortnode[sortindex[i]].polyplane->fixedheight, sortnode[sortindex[i]].polyplane->blend, sortnode[sortindex[i]].polyplane->lightlevel,
sortnode[sortindex[i]].polyplane->lumpnum, sortnode[sortindex[i]].polyplane->texturenum, sortnode[sortindex[i]].polyplane->FOFSector, sortnode[sortindex[i]].polyplane->alpha, sortnode[sortindex[i]].polyplane->planecolormap);
sortnode[sortindex[i]].polyplane->levelflat, sortnode[sortindex[i]].polyplane->FOFSector, sortnode[sortindex[i]].polyplane->alpha, sortnode[sortindex[i]].polyplane->planecolormap);
}
else if (sortnode[sortindex[i]].wall)
{
@ -5427,17 +5409,17 @@ static void HWR_DrawSprites(void)
#endif
if (spr->mobj && spr->mobj->skin && spr->mobj->sprite == SPR_PLAY)
{
if (!cv_grmd2.value || md2_playermodels[(skin_t*)spr->mobj->skin-skins].notfound || md2_playermodels[(skin_t*)spr->mobj->skin-skins].scale < 0.0f)
if (!cv_grmodels.value || md2_playermodels[(skin_t*)spr->mobj->skin-skins].notfound || md2_playermodels[(skin_t*)spr->mobj->skin-skins].scale < 0.0f)
HWR_DrawSprite(spr);
else
HWR_DrawMD2(spr);
HWR_DrawModel(spr);
}
else
{
if (!cv_grmd2.value || md2_models[spr->mobj->sprite].notfound || md2_models[spr->mobj->sprite].scale < 0.0f)
if (!cv_grmodels.value || md2_models[spr->mobj->sprite].notfound || md2_models[spr->mobj->sprite].scale < 0.0f)
HWR_DrawSprite(spr);
else
HWR_DrawMD2(spr);
HWR_DrawModel(spr);
}
}
}
@ -5578,7 +5560,7 @@ static void HWR_ProjectSprite(mobj_t *thing)
tz = (tr_x * gr_viewcos) + (tr_y * gr_viewsin);
// thing is behind view plane?
if (tz < ZCLIP_PLANE && !papersprite && (!cv_grmd2.value || md2_models[thing->sprite].notfound == true)) //Yellow: Only MD2's dont disappear
if (tz < ZCLIP_PLANE && !papersprite && (!cv_grmodels.value || md2_models[thing->sprite].notfound == true)) //Yellow: Only MD2's dont disappear
return;
// The above can stay as it works for cutting sprites that are too close
@ -5806,6 +5788,15 @@ static void HWR_ProjectSprite(mobj_t *thing)
// New colormap stuff for skins Tails 06-07-2002
if (thing->colorized)
vis->colormap = R_GetTranslationColormap(TC_RAINBOW, thing->color, GTC_CACHE);
else if (thing->player && thing->player->dashmode >= DASHMODE_THRESHOLD
&& (thing->player->charflags & SF_DASHMODE)
&& ((leveltime/2) & 1))
{
if (thing->player->charflags & SF_MACHINE)
vis->colormap = R_GetTranslationColormap(TC_DASHMODE, 0, GTC_CACHE);
else
vis->colormap = R_GetTranslationColormap(TC_RAINBOW, thing->color, GTC_CACHE);
}
else if (thing->skin && thing->sprite == SPR_PLAY) // This thing is a player!
{
size_t skinnum = (skin_t*)thing->skin-skins;
@ -6359,6 +6350,7 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player)
// note: sets viewangle, viewx, viewy, viewz
R_SetupFrame(player);
framecount++; // timedemo
// copy view cam position for local use
dup_viewx = viewx;
@ -6655,13 +6647,13 @@ void HWR_Startup(void)
// do this once
if (!startupdone)
{
CONS_Printf("HWR_Startup()\n");
CONS_Printf("HWR_Startup()...\n");
HWR_InitPolyPool();
// add console cmds & vars
HWR_AddEngineCommands();
HWR_InitTextureCache();
HWR_InitMD2();
HWR_InitModels();
#ifdef ALAM_LIGHTING
HWR_InitLight();
@ -6712,10 +6704,11 @@ void transform(float *cx, float *cy, float *cz)
//Hurdler: 3D Water stuff
#ifndef SORTING
#define MAX_3DWATER 512
#ifndef SORTING
static void HWR_Add3DWater(lumpnum_t lumpnum, extrasubsector_t *xsub,
static void HWR_Add3DWater(levelflat_t *levelflat, extrasubsector_t *xsub,
fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector)
{
static size_t allocedplanes = 0;
@ -6731,17 +6724,15 @@ static void HWR_Add3DWater(lumpnum_t lumpnum, extrasubsector_t *xsub,
}
planeinfo[numfloors].fixedheight = fixedheight;
planeinfo[numfloors].lightlevel = lightlevel;
planeinfo[numfloors].lumpnum = lumpnum;
planeinfo[numfloors].levelflat = levelflat;
planeinfo[numfloors].xsub = xsub;
planeinfo[numfloors].alpha = alpha;
planeinfo[numfloors].FOFSector = FOFSector;
numfloors++;
}
#endif
#define DIST_PLANE(i) ABS(planeinfo[(i)].fixedheight-dup_viewz)
#if 0
static void HWR_QuickSortPlane(INT32 start, INT32 finish)
{
INT32 left = start;
@ -6771,9 +6762,7 @@ static void HWR_QuickSortPlane(INT32 start, INT32 finish)
if (start < right) HWR_QuickSortPlane(start, right);
if (left < finish) HWR_QuickSortPlane(left, finish);
}
#endif
#ifndef SORTING
static void HWR_Render3DWater(void)
{
size_t i;
@ -6804,8 +6793,8 @@ static void HWR_Render3DWater(void)
gr_frontsector = NULL; //Hurdler: gr_fronsector is no longer valid
for (i = 0; i < numfloors; i++)
{
HWR_GetFlat(planeinfo[i].lumpnum);
HWR_RenderPlane(NULL, planeinfo[i].xsub, planeinfo[i].isceiling, planeinfo[i].fixedheight, PF_Translucent, planeinfo[i].lightlevel, planeinfo[i].lumpnum,
HWR_GetLevelFlat(planeinfo[i].levelflat);
HWR_RenderPlane(NULL, planeinfo[i].xsub, planeinfo[i].isceiling, planeinfo[i].fixedheight, PF_Translucent, planeinfo[i].lightlevel, planeinfo[i].levelflat,
planeinfo[i].FOFSector, planeinfo[i].alpha, planeinfo[i].fogplane, planeinfo[i].planecolormap);
}
numfloors = 0;
@ -6838,6 +6827,7 @@ static void HWR_AddTransparentWall(wallVert3D *wallVerts, FSurfaceInfo *pSurf, I
wallinfo[numwalls].wallcolormap = wallcolormap;
numwalls++;
}
#ifndef SORTING
static void HWR_RenderTransparentWalls(void)
{
@ -6870,6 +6860,7 @@ static void HWR_RenderTransparentWalls(void)
numwalls = 0;
}
#endif
static void HWR_RenderWall(wallVert3D *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend, boolean fogwall, INT32 lightlevel, extracolormap_t *wallcolormap)
{
FOutVector trVerts[4];
@ -6928,11 +6919,6 @@ static void HWR_RenderWall(wallVert3D *wallVerts, FSurfaceInfo *pSurf, FBITFIE
#endif
}
void HWR_SetPaletteColor(INT32 palcolor)
{
HWD.pfnSetSpecialState(HWD_SET_PALETTECOLOR, palcolor);
}
INT32 HWR_GetTextureUsed(void)
{
return HWD.pfnGetTextureUsed();
@ -6979,7 +6965,6 @@ void HWR_DoPostProcessor(player_t *player)
if (splitscreen) // Not supported in splitscreen - someone want to add support?
return;
#ifdef SHUFFLE
// Drunken vision! WooOOooo~
if (*type == postimg_water || *type == postimg_heat)
{
@ -7022,7 +7007,6 @@ void HWR_DoPostProcessor(player_t *player)
HWD.pfnMakeScreenTexture();
}
// Flipping of the screen isn't done here anymore
#endif // SHUFFLE
}
void HWR_StartScreenWipe(void)
@ -7069,7 +7053,7 @@ void HWR_DoWipe(UINT8 wipenum, UINT8 scrnnum)
HWR_GetFadeMask(lumpnum);
HWD.pfnDoScreenWipe(HWRWipeCounter); // Still send in wipecounter since old stuff might not support multitexturing
HWD.pfnDoScreenWipe();
HWRWipeCounter += 0.05f; // increase opacity of end screen

View file

@ -60,7 +60,6 @@ void HWR_AddCommands(void);
void HWR_CorrectSWTricks(void);
void transform(float *cx, float *cy, float *cz);
FBITFIELD HWR_TranstableToAlpha(INT32 transtablenum, FSurfaceInfo *pSurf);
void HWR_SetPaletteColor(INT32 palcolor);
INT32 HWR_GetTextureUsed(void);
void HWR_DoPostProcessor(player_t *player);
void HWR_StartScreenWipe(void);
@ -83,7 +82,8 @@ extern consvar_t cv_grcoronas;
extern consvar_t cv_grcoronasize;
#endif
extern consvar_t cv_grfov;
extern consvar_t cv_grmd2;
extern consvar_t cv_grmodels;
extern consvar_t cv_grmodelinterpolation;
extern consvar_t cv_grfog;
extern consvar_t cv_grfogcolor;
extern consvar_t cv_grfogdensity;
@ -94,7 +94,6 @@ extern consvar_t cv_grgammablue;
extern consvar_t cv_grfiltermode;
extern consvar_t cv_granisotropicmode;
extern consvar_t cv_grcorrecttricks;
extern consvar_t cv_voodoocompatibility;
extern consvar_t cv_grfovchange;
extern consvar_t cv_grsolvetjoin;
extern consvar_t cv_grspritebillboarding;

View file

@ -35,6 +35,7 @@
#include "hw_drv.h"
#include "hw_light.h"
#include "hw_md2.h"
#include "../d_main.h"
#include "../r_bsp.h"
#include "../r_main.h"
#include "../m_misc.h"
@ -43,6 +44,7 @@
#include "../r_things.h"
#include "../r_draw.h"
#include "../p_tick.h"
#include "hw_model.h"
#include "hw_main.h"
#include "../v_video.h"
@ -75,172 +77,6 @@
#include "errno.h"
#endif
#define NUMVERTEXNORMALS 162
float avertexnormals[NUMVERTEXNORMALS][3] = {
{-0.525731f, 0.000000f, 0.850651f},
{-0.442863f, 0.238856f, 0.864188f},
{-0.295242f, 0.000000f, 0.955423f},
{-0.309017f, 0.500000f, 0.809017f},
{-0.162460f, 0.262866f, 0.951056f},
{0.000000f, 0.000000f, 1.000000f},
{0.000000f, 0.850651f, 0.525731f},
{-0.147621f, 0.716567f, 0.681718f},
{0.147621f, 0.716567f, 0.681718f},
{0.000000f, 0.525731f, 0.850651f},
{0.309017f, 0.500000f, 0.809017f},
{0.525731f, 0.000000f, 0.850651f},
{0.295242f, 0.000000f, 0.955423f},
{0.442863f, 0.238856f, 0.864188f},
{0.162460f, 0.262866f, 0.951056f},
{-0.681718f, 0.147621f, 0.716567f},
{-0.809017f, 0.309017f, 0.500000f},
{-0.587785f, 0.425325f, 0.688191f},
{-0.850651f, 0.525731f, 0.000000f},
{-0.864188f, 0.442863f, 0.238856f},
{-0.716567f, 0.681718f, 0.147621f},
{-0.688191f, 0.587785f, 0.425325f},
{-0.500000f, 0.809017f, 0.309017f},
{-0.238856f, 0.864188f, 0.442863f},
{-0.425325f, 0.688191f, 0.587785f},
{-0.716567f, 0.681718f, -0.147621f},
{-0.500000f, 0.809017f, -0.309017f},
{-0.525731f, 0.850651f, 0.000000f},
{0.000000f, 0.850651f, -0.525731f},
{-0.238856f, 0.864188f, -0.442863f},
{0.000000f, 0.955423f, -0.295242f},
{-0.262866f, 0.951056f, -0.162460f},
{0.000000f, 1.000000f, 0.000000f},
{0.000000f, 0.955423f, 0.295242f},
{-0.262866f, 0.951056f, 0.162460f},
{0.238856f, 0.864188f, 0.442863f},
{0.262866f, 0.951056f, 0.162460f},
{0.500000f, 0.809017f, 0.309017f},
{0.238856f, 0.864188f, -0.442863f},
{0.262866f, 0.951056f, -0.162460f},
{0.500000f, 0.809017f, -0.309017f},
{0.850651f, 0.525731f, 0.000000f},
{0.716567f, 0.681718f, 0.147621f},
{0.716567f, 0.681718f, -0.147621f},
{0.525731f, 0.850651f, 0.000000f},
{0.425325f, 0.688191f, 0.587785f},
{0.864188f, 0.442863f, 0.238856f},
{0.688191f, 0.587785f, 0.425325f},
{0.809017f, 0.309017f, 0.500000f},
{0.681718f, 0.147621f, 0.716567f},
{0.587785f, 0.425325f, 0.688191f},
{0.955423f, 0.295242f, 0.000000f},
{1.000000f, 0.000000f, 0.000000f},
{0.951056f, 0.162460f, 0.262866f},
{0.850651f, -0.525731f, 0.000000f},
{0.955423f, -0.295242f, 0.000000f},
{0.864188f, -0.442863f, 0.238856f},
{0.951056f, -0.162460f, 0.262866f},
{0.809017f, -0.309017f, 0.500000f},
{0.681718f, -0.147621f, 0.716567f},
{0.850651f, 0.000000f, 0.525731f},
{0.864188f, 0.442863f, -0.238856f},
{0.809017f, 0.309017f, -0.500000f},
{0.951056f, 0.162460f, -0.262866f},
{0.525731f, 0.000000f, -0.850651f},
{0.681718f, 0.147621f, -0.716567f},
{0.681718f, -0.147621f, -0.716567f},
{0.850651f, 0.000000f, -0.525731f},
{0.809017f, -0.309017f, -0.500000f},
{0.864188f, -0.442863f, -0.238856f},
{0.951056f, -0.162460f, -0.262866f},
{0.147621f, 0.716567f, -0.681718f},
{0.309017f, 0.500000f, -0.809017f},
{0.425325f, 0.688191f, -0.587785f},
{0.442863f, 0.238856f, -0.864188f},
{0.587785f, 0.425325f, -0.688191f},
{0.688191f, 0.587785f, -0.425325f},
{-0.147621f, 0.716567f, -0.681718f},
{-0.309017f, 0.500000f, -0.809017f},
{0.000000f, 0.525731f, -0.850651f},
{-0.525731f, 0.000000f, -0.850651f},
{-0.442863f, 0.238856f, -0.864188f},
{-0.295242f, 0.000000f, -0.955423f},
{-0.162460f, 0.262866f, -0.951056f},
{0.000000f, 0.000000f, -1.000000f},
{0.295242f, 0.000000f, -0.955423f},
{0.162460f, 0.262866f, -0.951056f},
{-0.442863f, -0.238856f, -0.864188f},
{-0.309017f, -0.500000f, -0.809017f},
{-0.162460f, -0.262866f, -0.951056f},
{0.000000f, -0.850651f, -0.525731f},
{-0.147621f, -0.716567f, -0.681718f},
{0.147621f, -0.716567f, -0.681718f},
{0.000000f, -0.525731f, -0.850651f},
{0.309017f, -0.500000f, -0.809017f},
{0.442863f, -0.238856f, -0.864188f},
{0.162460f, -0.262866f, -0.951056f},
{0.238856f, -0.864188f, -0.442863f},
{0.500000f, -0.809017f, -0.309017f},
{0.425325f, -0.688191f, -0.587785f},
{0.716567f, -0.681718f, -0.147621f},
{0.688191f, -0.587785f, -0.425325f},
{0.587785f, -0.425325f, -0.688191f},
{0.000000f, -0.955423f, -0.295242f},
{0.000000f, -1.000000f, 0.000000f},
{0.262866f, -0.951056f, -0.162460f},
{0.000000f, -0.850651f, 0.525731f},
{0.000000f, -0.955423f, 0.295242f},
{0.238856f, -0.864188f, 0.442863f},
{0.262866f, -0.951056f, 0.162460f},
{0.500000f, -0.809017f, 0.309017f},
{0.716567f, -0.681718f, 0.147621f},
{0.525731f, -0.850651f, 0.000000f},
{-0.238856f, -0.864188f, -0.442863f},
{-0.500000f, -0.809017f, -0.309017f},
{-0.262866f, -0.951056f, -0.162460f},
{-0.850651f, -0.525731f, 0.000000f},
{-0.716567f, -0.681718f, -0.147621f},
{-0.716567f, -0.681718f, 0.147621f},
{-0.525731f, -0.850651f, 0.000000f},
{-0.500000f, -0.809017f, 0.309017f},
{-0.238856f, -0.864188f, 0.442863f},
{-0.262866f, -0.951056f, 0.162460f},
{-0.864188f, -0.442863f, 0.238856f},
{-0.809017f, -0.309017f, 0.500000f},
{-0.688191f, -0.587785f, 0.425325f},
{-0.681718f, -0.147621f, 0.716567f},
{-0.442863f, -0.238856f, 0.864188f},
{-0.587785f, -0.425325f, 0.688191f},
{-0.309017f, -0.500000f, 0.809017f},
{-0.147621f, -0.716567f, 0.681718f},
{-0.425325f, -0.688191f, 0.587785f},
{-0.162460f, -0.262866f, 0.951056f},
{0.442863f, -0.238856f, 0.864188f},
{0.162460f, -0.262866f, 0.951056f},
{0.309017f, -0.500000f, 0.809017f},
{0.147621f, -0.716567f, 0.681718f},
{0.000000f, -0.525731f, 0.850651f},
{0.425325f, -0.688191f, 0.587785f},
{0.587785f, -0.425325f, 0.688191f},
{0.688191f, -0.587785f, 0.425325f},
{-0.955423f, 0.295242f, 0.000000f},
{-0.951056f, 0.162460f, 0.262866f},
{-1.000000f, 0.000000f, 0.000000f},
{-0.850651f, 0.000000f, 0.525731f},
{-0.955423f, -0.295242f, 0.000000f},
{-0.951056f, -0.162460f, 0.262866f},
{-0.864188f, 0.442863f, -0.238856f},
{-0.951056f, 0.162460f, -0.262866f},
{-0.809017f, 0.309017f, -0.500000f},
{-0.864188f, -0.442863f, -0.238856f},
{-0.951056f, -0.162460f, -0.262866f},
{-0.809017f, -0.309017f, -0.500000f},
{-0.681718f, 0.147621f, -0.716567f},
{-0.681718f, -0.147621f, -0.716567f},
{-0.850651f, 0.000000f, -0.525731f},
{-0.688191f, 0.587785f, -0.425325f},
{-0.587785f, 0.425325f, -0.688191f},
{-0.425325f, 0.688191f, -0.587785f},
{-0.425325f, -0.688191f, -0.587785f},
{-0.587785f, -0.425325f, -0.688191f},
{-0.688191f, -0.587785f, -0.425325f},
};
md2_t md2_models[NUMSPRITES];
md2_t md2_playermodels[MAXSKINS];
@ -248,230 +84,25 @@ md2_t md2_playermodels[MAXSKINS];
/*
* free model
*/
static void md2_freeModel (md2_model_t *model)
#if 0
static void md2_freeModel (model_t *model)
{
if (model)
{
if (model->skins)
free(model->skins);
if (model->texCoords)
free(model->texCoords);
if (model->triangles)
free(model->triangles);
if (model->frames)
{
size_t i;
for (i = 0; i < model->header.numFrames; i++)
{
if (model->frames[i].vertices)
free(model->frames[i].vertices);
}
free(model->frames);
}
if (model->spr2frames)
free(model->spr2frames);
if (model->glCommandBuffer)
free(model->glCommandBuffer);
free(model);
}
UnloadModel(model);
}
#endif
//
// load model
//
// Hurdler: the current path is the Legacy.exe path
static md2_model_t *md2_readModel(const char *filename)
static model_t *md2_readModel(const char *filename)
{
FILE *file;
md2_model_t *model;
UINT8 buffer[MD2_MAX_FRAMESIZE];
size_t i;
model = calloc(1, sizeof (*model));
if (model == NULL)
return 0;
//Filename checking fixed ~Monster Iestyn and Golden
file = fopen(va("%s"PATHSEP"%s", srb2home, filename), "rb");
if (!file)
{
free(model);
return 0;
}
// initialize model and read header
if (fread(&model->header, sizeof (model->header), 1, file) != 1
|| model->header.magic != MD2_IDENT
|| model->header.version != MD2_VERSION)
{
fclose(file);
free(model);
return 0;
}
model->header.numSkins = 1;
#define MD2LIMITCHECK(field, max, msgname) \
if (field > max) \
{ \
CONS_Alert(CONS_ERROR, "md2_readModel: %s has too many " msgname " (# found: %d, maximum: %d)\n", filename, field, max); \
md2_freeModel (model); \
fclose(file); \
return 0; \
}
// Uncomment if these are actually needed
// MD2LIMITCHECK(model->header.numSkins, MD2_MAX_SKINS, "skins")
// MD2LIMITCHECK(model->header.numTexCoords, MD2_MAX_TEXCOORDS, "texture coordinates")
MD2LIMITCHECK(model->header.numTriangles, MD2_MAX_TRIANGLES, "triangles")
MD2LIMITCHECK(model->header.numFrames, MD2_MAX_FRAMES, "frames")
MD2LIMITCHECK(model->header.numVertices, MD2_MAX_VERTICES, "vertices")
#undef MD2LIMITCHECK
// read skins
fseek(file, model->header.offsetSkins, SEEK_SET);
if (model->header.numSkins > 0)
{
model->skins = calloc(sizeof (md2_skin_t), model->header.numSkins);
if (!model->skins || model->header.numSkins !=
fread(model->skins, sizeof (md2_skin_t), model->header.numSkins, file))
{
md2_freeModel (model);
fclose(file);
return 0;
}
}
// read texture coordinates
fseek(file, model->header.offsetTexCoords, SEEK_SET);
if (model->header.numTexCoords > 0)
{
model->texCoords = calloc(sizeof (md2_textureCoordinate_t), model->header.numTexCoords);
if (!model->texCoords || model->header.numTexCoords !=
fread(model->texCoords, sizeof (md2_textureCoordinate_t), model->header.numTexCoords, file))
{
md2_freeModel (model);
fclose(file);
return 0;
}
}
// read triangles
fseek(file, model->header.offsetTriangles, SEEK_SET);
if (model->header.numTriangles > 0)
{
model->triangles = calloc(sizeof (md2_triangle_t), model->header.numTriangles);
if (!model->triangles || model->header.numTriangles !=
fread(model->triangles, sizeof (md2_triangle_t), model->header.numTriangles, file))
{
md2_freeModel (model);
fclose(file);
return 0;
}
}
// read alias frames
fseek(file, model->header.offsetFrames, SEEK_SET);
if (model->header.numFrames > 0)
{
model->frames = calloc(sizeof (md2_frame_t), model->header.numFrames);
if (!model->frames)
{
md2_freeModel (model);
fclose(file);
return 0;
}
for (i = 0; i < model->header.numFrames; i++)
{
md2_alias_frame_t *frame = (md2_alias_frame_t *)(void *)buffer;
size_t j;
model->frames[i].vertices = calloc(sizeof (md2_triangleVertex_t), model->header.numVertices);
if (!model->frames[i].vertices || model->header.frameSize !=
fread(frame, 1, model->header.frameSize, file))
{
md2_freeModel (model);
fclose(file);
return 0;
}
strcpy(model->frames[i].name, frame->name);
if (frame->name[0] == 'S')
{
boolean super;
if ((super = (fastncmp("UPER", frame->name+1, 4))) // SUPER
|| fastncmp("PR2_", frame->name+1, 4)) // SPR2_
{
UINT8 spr2;
for (spr2 = 0; spr2 < free_spr2; spr2++)
if (fastncmp(frame->name+5,spr2names[spr2],3)
&& ((frame->name[8] == spr2names[spr2][3])
|| (frame->name[8] == '.' && spr2names[spr2][3] == '_')))
break;
if (spr2 < free_spr2)
{
if (!model->spr2frames)
{
model->spr2frames = calloc(sizeof (size_t), 2*NUMPLAYERSPRITES*2);
if (!model->spr2frames)
{
md2_freeModel (model);
fclose(file);
return 0;
}
}
if (super)
spr2 |= FF_SPR2SUPER;
if (model->spr2frames[spr2*2 + 1]++ == 0) // numspr2frames
model->spr2frames[spr2*2] = i; // starting frame
CONS_Debug(DBG_RENDER, "frame %s, sprite2 %s - starting frame %s, number of frames %s\n", frame->name, spr2names[spr2 & ~FF_SPR2SUPER], sizeu1(model->spr2frames[spr2*2]), sizeu2(model->spr2frames[spr2*2 + 1]));
}
}
}
for (j = 0; j < model->header.numVertices; j++)
{
model->frames[i].vertices[j].vertex[0] = (float) ((INT32) frame->alias_vertices[j].vertex[0]) * frame->scale[0] + frame->translate[0];
model->frames[i].vertices[j].vertex[2] = -1* ((float) ((INT32) frame->alias_vertices[j].vertex[1]) * frame->scale[1] + frame->translate[1]);
model->frames[i].vertices[j].vertex[1] = (float) ((INT32) frame->alias_vertices[j].vertex[2]) * frame->scale[2] + frame->translate[2];
model->frames[i].vertices[j].normal[0] = avertexnormals[frame->alias_vertices[j].lightNormalIndex][0];
model->frames[i].vertices[j].normal[1] = avertexnormals[frame->alias_vertices[j].lightNormalIndex][1];
model->frames[i].vertices[j].normal[2] = avertexnormals[frame->alias_vertices[j].lightNormalIndex][2];
}
}
}
// read gl commands
fseek(file, model->header.offsetGlCommands, SEEK_SET);
if (model->header.numGlCommands)
{
model->glCommandBuffer = calloc(sizeof (INT32), model->header.numGlCommands);
if (!model->glCommandBuffer || model->header.numGlCommands !=
fread(model->glCommandBuffer, sizeof (INT32), model->header.numGlCommands, file))
{
md2_freeModel (model);
fclose(file);
return 0;
}
}
fclose(file);
return model;
return LoadModel(va("%s"PATHSEP"%s", srb2home, filename), PU_STATIC);
}
static inline void md2_printModelInfo (md2_model_t *model)
static inline void md2_printModelInfo (model_t *model)
{
#if 0
INT32 i;
@ -530,7 +161,7 @@ static GrTextureFormat_t PNG_Load(const char *filename, int *w, int *h, GLPatch_
#endif
png_FILE_p png_FILE;
//Filename checking fixed ~Monster Iestyn and Golden
char *pngfilename = va("%s"PATHSEP"md2"PATHSEP"%s", srb2home, filename);
char *pngfilename = va("%s"PATHSEP"models"PATHSEP"%s", srb2home, filename);
FIL_ForceExtension(pngfilename, ".png");
png_FILE = fopen(pngfilename, "rb");
@ -659,7 +290,7 @@ static GrTextureFormat_t PCX_Load(const char *filename, int *w, int *h,
INT32 ch, rep;
FILE *file;
//Filename checking fixed ~Monster Iestyn and Golden
char *pcxfilename = va("%s"PATHSEP"md2"PATHSEP"%s", srb2home, filename);
char *pcxfilename = va("%s"PATHSEP"models"PATHSEP"%s", srb2home, filename);
FIL_ForceExtension(pcxfilename, ".pcx");
file = fopen(pcxfilename, "rb");
@ -720,7 +351,7 @@ static GrTextureFormat_t PCX_Load(const char *filename, int *w, int *h,
}
// -----------------+
// md2_loadTexture : Download a pcx or png texture for MD2 models
// md2_loadTexture : Download a pcx or png texture for models
// -----------------+
static void md2_loadTexture(md2_t *model)
{
@ -830,7 +461,7 @@ static void md2_loadBlendTexture(md2_t *model)
// Don't spam the console, or the OS with fopen requests!
static boolean nomd2s = false;
void HWR_InitMD2(void)
void HWR_InitModels(void)
{
size_t i;
INT32 s;
@ -838,7 +469,7 @@ void HWR_InitMD2(void)
char name[18], filename[32];
float scale, offset;
CONS_Printf("InitMD2()...\n");
CONS_Printf("HWR_InitModels()...\n");
for (s = 0; s < MAXSKINS; s++)
{
md2_playermodels[s].scale = -1.0f;
@ -858,13 +489,13 @@ void HWR_InitMD2(void)
md2_models[i].error = false;
}
// read the md2.dat file
// read the models.dat file
//Filename checking fixed ~Monster Iestyn and Golden
f = fopen(va("%s"PATHSEP"%s", srb2home, "md2.dat"), "rt");
f = fopen(va("%s"PATHSEP"%s", srb2home, "models.dat"), "rt");
if (!f)
{
CONS_Printf("%s %s\n", M_GetText("Error while loading md2.dat:"), strerror(errno));
CONS_Printf("%s %s\n", M_GetText("Error while loading models.dat:"), strerror(errno));
nomd2s = true;
return;
}
@ -872,7 +503,7 @@ void HWR_InitMD2(void)
{
if (stricmp(name, "PLAY") == 0)
{
CONS_Printf("MD2 for sprite PLAY detected in md2.dat, use a player skin instead!\n");
CONS_Printf("Model for sprite PLAY detected in models.dat, use a player skin instead!\n");
continue;
}
@ -906,7 +537,7 @@ void HWR_InitMD2(void)
}
}
// no sprite/player skin name found?!?
CONS_Printf("Unknown sprite/player skin %s detected in md2.dat\n", name);
//CONS_Printf("Unknown sprite/player skin %s detected in models.dat\n", name);
md2found:
// move on to next line...
continue;
@ -914,7 +545,7 @@ md2found:
fclose(f);
}
void HWR_AddPlayerMD2(int skin) // For MD2's that were added after startup
void HWR_AddPlayerModel(int skin) // For skins that were added after startup
{
FILE *f;
char name[18], filename[32];
@ -923,20 +554,20 @@ void HWR_AddPlayerMD2(int skin) // For MD2's that were added after startup
if (nomd2s)
return;
CONS_Printf("AddPlayerMD2()...\n");
//CONS_Printf("HWR_AddPlayerModel()...\n");
// read the md2.dat file
// read the models.dat file
//Filename checking fixed ~Monster Iestyn and Golden
f = fopen(va("%s"PATHSEP"%s", srb2home, "md2.dat"), "rt");
f = fopen(va("%s"PATHSEP"%s", srb2home, "models.dat"), "rt");
if (!f)
{
CONS_Printf("Error while loading md2.dat\n");
CONS_Printf("Error while loading models.dat\n");
nomd2s = true;
return;
}
// Check for any MD2s that match the names of player skins!
// Check for any model that match the names of player skins!
while (fscanf(f, "%19s %31s %f %f", name, filename, &scale, &offset) == 4)
{
if (stricmp(name, skins[skin].name) == 0)
@ -950,17 +581,16 @@ void HWR_AddPlayerMD2(int skin) // For MD2's that were added after startup
}
}
//CONS_Printf("MD2 for player skin %s not found\n", skins[skin].name);
//CONS_Printf("Model for player skin %s not found\n", skins[skin].name);
md2_playermodels[skin].notfound = true;
playermd2found:
fclose(f);
}
void HWR_AddSpriteMD2(size_t spritenum) // For MD2s that were added after startup
void HWR_AddSpriteModel(size_t spritenum) // For sprites that were added after startup
{
FILE *f;
// name[18] is used to check for names in the md2.dat file that match with sprites or player skins
// name[18] is used to check for names in the models.dat file that match with sprites or player skins
// sprite names are always 4 characters long, and names is for player skins can be up to 19 characters long
char name[18], filename[32];
float scale, offset;
@ -971,18 +601,18 @@ void HWR_AddSpriteMD2(size_t spritenum) // For MD2s that were added after startu
if (spritenum == SPR_PLAY) // Handled already NEWMD2: Per sprite, per-skin check
return;
// Read the md2.dat file
// Read the models.dat file
//Filename checking fixed ~Monster Iestyn and Golden
f = fopen(va("%s"PATHSEP"%s", srb2home, "md2.dat"), "rt");
f = fopen(va("%s"PATHSEP"%s", srb2home, "models.dat"), "rt");
if (!f)
{
CONS_Printf("Error while loading md2.dat\n");
CONS_Printf("Error while loading models.dat\n");
nomd2s = true;
return;
}
// Check for any MD2s that match the names of player skins!
// Check for any MD2s that match the names of sprite names!
while (fscanf(f, "%19s %31s %f %f", name, filename, &scale, &offset) == 4)
{
if (stricmp(name, sprnames[spritenum]) == 0)
@ -1006,7 +636,6 @@ spritemd2found:
// 0.2126 to red
// 0.7152 to green
// 0.0722 to blue
// (See this same define in k_kart.c!)
#define SETBRIGHTNESS(brightness,r,g,b) \
brightness = (UINT8)(((1063*((UINT16)r)/5000) + (3576*((UINT16)g)/5000) + (361*((UINT16)b)/5000)) / 3)
@ -1190,39 +819,40 @@ static void HWR_GetBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, INT
Z_ChangeTag(newmip->grInfo.data, PU_HWRCACHE_UNLOCKED);
}
#define NORMALFOG 0x00000000
#define FADEFOG 0x19000000
static boolean HWR_CanInterpolateModel(mobj_t *mobj, model_t *model)
{
if (cv_grmodelinterpolation.value == 2) // Always interpolate
return true;
return model->interpolate[(mobj->frame & FF_FRAMEMASK)];
}
// -----------------+
// HWR_DrawMD2 : Draw MD2
// : (monsters, bonuses, weapons, lights, ...)
// Returns :
// -----------------+
/*
wait/stand
death
pain
walk
shoot/fire
static boolean HWR_CanInterpolateSprite2(modelspr2frames_t *spr2frame)
{
if (cv_grmodelinterpolation.value == 2) // Always interpolate
return true;
return spr2frame->interpolate;
}
die?
atka?
atkb?
attacka/b/c/d?
res?
run?
*/
//
// HWR_GetModelSprite2 (see P_GetSkinSprite2)
// For non-super players, tries each sprite2's immediate predecessor until it finds one with a number of frames or ends up at standing.
// For super players, does the same as above - but tries the super equivalent for each sprite2 before the non-super version.
//
static UINT8 P_GetModelSprite2(md2_t *md2, skin_t *skin, UINT8 spr2, player_t *player)
static UINT8 HWR_GetModelSprite2(md2_t *md2, skin_t *skin, UINT8 spr2, player_t *player)
{
UINT8 super = 0, i = 0;
if (!md2 || !skin)
if (!md2 || !md2->model || !md2->model->spr2frames || !skin)
return 0;
if ((playersprite_t)(spr2 & ~FF_SPR2SUPER) >= free_spr2)
return 0;
while (!(md2->model->spr2frames[spr2*2 + 1])
while (!md2->model->spr2frames[spr2].numframes
&& spr2 != SPR2_STND
&& ++i != 32) // recursion limiter
{
@ -1263,19 +893,23 @@ static UINT8 P_GetModelSprite2(md2_t *md2, skin_t *skin, UINT8 spr2, player_t *p
return spr2;
}
#define NORMALFOG 0x00000000
#define FADEFOG 0x19000000
void HWR_DrawMD2(gr_vissprite_t *spr)
//
// HWR_DrawModel
//
void HWR_DrawModel(gr_vissprite_t *spr)
{
FSurfaceInfo Surf;
char filename[64];
INT32 frame;
INT32 frame = 0;
INT32 nextFrame = -1;
UINT8 spr2 = 0;
FTransform p;
md2_t *md2;
UINT8 color[4];
if (!cv_grmd2.value)
if (!cv_grmodels.value)
return;
if (spr->precip)
@ -1321,13 +955,13 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
// Look at HWR_ProjectSprite for more
{
GLPatch_t *gpatch;
INT32 *buff;
INT32 durs = spr->mobj->state->tics;
INT32 tics = spr->mobj->tics;
md2_frame_t *curr, *next = NULL;
//mdlframe_t *next = NULL;
const UINT8 flip = (UINT8)(!(spr->mobj->eflags & MFE_VERTICALFLIP) != !(spr->mobj->frame & FF_VERTICALFLIP));
spritedef_t *sprdef;
spriteframe_t *sprframe;
INT32 mod;
float finalscale;
// Apparently people don't like jump frames like that, so back it goes
@ -1358,13 +992,14 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
return; // we already failed loading this before :(
if (!md2->model)
{
//CONS_Debug(DBG_RENDER, "Loading MD2... (%s)", sprnames[spr->mobj->sprite]);
sprintf(filename, "md2/%s", md2->filename);
//CONS_Debug(DBG_RENDER, "Loading model... (%s)", sprnames[spr->mobj->sprite]);
sprintf(filename, "models/%s", md2->filename);
md2->model = md2_readModel(filename);
if (md2->model)
{
md2_printModelInfo(md2->model);
HWD.pfnCreateModelVBOs(md2->model);
}
else
{
@ -1403,16 +1038,21 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
}
else if (spr->mobj->color)
{
if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY)
if (spr->mobj->colorized)
skinnum = TC_RAINBOW;
else if (spr->mobj->player && spr->mobj->player->dashmode >= DASHMODE_THRESHOLD
&& (spr->mobj->player->charflags & SF_DASHMODE)
&& ((leveltime/2) & 1))
{
if (spr->mobj->colorized)
skinnum = TC_RAINBOW;
if (spr->mobj->player->charflags & SF_MACHINE)
skinnum = TC_DASHMODE;
else
{
skinnum = (INT32)((skin_t*)spr->mobj->skin-skins);
}
skinnum = TC_RAINBOW;
}
else skinnum = TC_DEFAULT;
else if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY)
skinnum = (INT32)((skin_t*)spr->mobj->skin-skins);
else
skinnum = TC_DEFAULT;
}
HWR_GetBlendedTexture(gpatch, (GLPatch_t *)md2->blendgrpatch, skinnum, spr->colormap, (skincolors_t)spr->mobj->color);
}
@ -1436,70 +1076,69 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
tics = spr->mobj->anim_duration;
}
#define INTERPOLERATION_LIMIT TICRATE/4
frame = (spr->mobj->frame & FF_FRAMEMASK);
if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY && md2->model->spr2frames)
{
UINT8 spr2 = P_GetModelSprite2(md2, spr->mobj->skin, spr->mobj->sprite2, spr->mobj->player);
UINT8 mod = md2->model->spr2frames[spr2*2 + 1] ? md2->model->spr2frames[spr2*2 + 1] : md2->model->header.numFrames;
if (mod > ((skin_t *)spr->mobj->skin)->sprites[spr2].numframes)
spr2 = HWR_GetModelSprite2(md2, spr->mobj->skin, spr->mobj->sprite2, spr->mobj->player);
mod = md2->model->spr2frames[spr2].numframes;
#ifndef DONTHIDEDIFFANIMLENGTH // by default, different anim length is masked by the mod
if (mod > (INT32)((skin_t *)spr->mobj->skin)->sprites[spr2].numframes)
mod = ((skin_t *)spr->mobj->skin)->sprites[spr2].numframes;
//FIXME: this is not yet correct
frame = (spr->mobj->frame & FF_FRAMEMASK);
if (frame >= mod)
frame = 0;
buff = md2->model->glCommandBuffer;
curr = &md2->model->frames[md2->model->spr2frames[spr2*2] + frame];
if (cv_grmd2.value == 1 && tics <= durs && tics <= INTERPOLERATION_LIMIT)
{
if (durs > INTERPOLERATION_LIMIT)
durs = INTERPOLERATION_LIMIT;
if (spr->mobj->frame & FF_ANIMATE
|| (spr->mobj->state->nextstate != S_NULL
&& states[spr->mobj->state->nextstate].sprite == spr->mobj->sprite
&& (states[spr->mobj->state->nextstate].frame & FF_FRAMEMASK) == spr->mobj->sprite2))
{
if (++frame >= mod)
frame = 0;
if (frame || !(spr->mobj->state->frame & FF_SPR2ENDSTATE))
next = &md2->model->frames[md2->model->spr2frames[spr2*2] + frame];
}
}
#endif
if (!mod)
mod = 1;
frame = md2->model->spr2frames[spr2].frames[frame%mod];
}
else
{
//FIXME: this is not yet correct
frame = (spr->mobj->frame & FF_FRAMEMASK) % md2->model->header.numFrames;
buff = md2->model->glCommandBuffer;
curr = &md2->model->frames[frame];
if (cv_grmd2.value == 1 && tics <= durs && tics <= INTERPOLERATION_LIMIT)
{
if (durs > INTERPOLERATION_LIMIT)
durs = INTERPOLERATION_LIMIT;
mod = md2->model->meshes[0].numFrames;
if (!mod)
mod = 1;
}
#ifdef USE_MODEL_NEXTFRAME
#define INTERPOLERATION_LIMIT TICRATE/4
if (cv_grmodelinterpolation.value && tics <= durs && tics <= INTERPOLERATION_LIMIT)
{
if (durs > INTERPOLERATION_LIMIT)
durs = INTERPOLERATION_LIMIT;
if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY && md2->model->spr2frames)
{
if (HWR_CanInterpolateSprite2(&md2->model->spr2frames[spr2])
&& (spr->mobj->frame & FF_ANIMATE
|| (spr->mobj->state->nextstate != S_NULL
&& states[spr->mobj->state->nextstate].sprite == SPR_PLAY
&& ((P_GetSkinSprite2(spr->mobj->skin, (((spr->mobj->player && spr->mobj->player->powers[pw_super]) ? FF_SPR2SUPER : 0)|states[spr->mobj->state->nextstate].frame) & FF_FRAMEMASK, spr->mobj->player) == spr->mobj->sprite2)))))
{
nextFrame = (spr->mobj->frame & FF_FRAMEMASK) + 1;
if (nextFrame >= mod)
nextFrame = 0;
if (frame || !(spr->mobj->state->frame & FF_SPR2ENDSTATE))
nextFrame = md2->model->spr2frames[spr2].frames[nextFrame];
else
nextFrame = -1;
}
}
else if (HWR_CanInterpolateModel(spr->mobj, md2->model))
{
// frames are handled differently for states with FF_ANIMATE, so get the next frame differently for the interpolation
if (spr->mobj->frame & FF_ANIMATE)
{
UINT32 nextframe = (spr->mobj->frame & FF_FRAMEMASK) + 1;
if (nextframe >= (UINT32)spr->mobj->state->var1)
nextframe = (spr->mobj->state->frame & FF_FRAMEMASK);
nextframe %= md2->model->header.numFrames;
next = &md2->model->frames[nextframe];
nextFrame = (spr->mobj->frame & FF_FRAMEMASK) + 1;
if (nextFrame >= (INT32)(spr->mobj->state->var1 + (spr->mobj->state->frame & FF_FRAMEMASK)))
nextFrame = (spr->mobj->state->frame & FF_FRAMEMASK) % mod;
}
else
{
if (spr->mobj->state->nextstate != S_NULL
&& states[spr->mobj->state->nextstate].sprite == spr->mobj->sprite)
{
const UINT32 nextframe = (states[spr->mobj->state->nextstate].frame & FF_FRAMEMASK) % md2->model->header.numFrames;
next = &md2->model->frames[nextframe];
}
if (spr->mobj->state->nextstate != S_NULL && states[spr->mobj->state->nextstate].sprite != SPR_NULL
&& !(spr->mobj->player && (spr->mobj->state->nextstate == S_PLAY_WAIT) && spr->mobj->state == &states[S_PLAY_STND]))
nextFrame = (states[spr->mobj->state->nextstate].frame & FF_FRAMEMASK) % mod;
}
}
}
#undef INTERPOLERATION_LIMIT
#endif
//Hurdler: it seems there is still a small problem with mobj angle
p.x = FIXED_TO_FLOAT(spr->mobj->x);
@ -1519,7 +1158,13 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
if (sprframe->rotate)
{
const fixed_t anglef = AngleFixed((spr->mobj->player ? spr->mobj->player->drawangle : spr->mobj->angle));
fixed_t anglef = AngleFixed(spr->mobj->angle);
if (spr->mobj->player)
anglef = AngleFixed(spr->mobj->player->drawangle);
else
anglef = AngleFixed(spr->mobj->angle);
p.angley = FIXED_TO_FLOAT(anglef);
}
else
@ -1528,21 +1173,50 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
p.angley = FIXED_TO_FLOAT(anglef);
}
// rotsprite
#ifdef ROTSPRITE
p.rollangle = 0.0f;
p.nightsroll = 0;
if (spr->mobj->rollangle)
{
// do i have to support ROTANGLES here??????
fixed_t anglef = AngleFixed(spr->mobj->rollangle);
p.anglex = FIXED_TO_FLOAT(anglef);
p.rollangle = FIXED_TO_FLOAT(anglef);
// pivot
p.centerx = FIXED_TO_FLOAT(spr->mobj->radius/2);
p.centery = FIXED_TO_FLOAT(spr->mobj->height/2);
p.roll = true;
// NiGHTS-specific conditional
//if (spr->mobj->player)
{
statenum_t state = spr->mobj->state-states;
if ((state == S_PLAY_NIGHTS_FLY0) || (state == S_PLAY_NIGHTS_DRILL0))
{
angle_t ang = R_PointToAngle (spr->mobj->x, spr->mobj->y) - (spr->mobj->player ? spr->mobj->player->drawangle : spr->mobj->angle);
if ((sprframe->rotate & SRF_RIGHT) && (ang < ANGLE_180)) // See from right
p.nightsroll = 1;
else if ((sprframe->rotate & SRF_LEFT) && (ang >= ANGLE_180)) // See from left
p.nightsroll = -1;
}
}
}
#endif
p.anglex = 0.0f;
#ifdef USE_FTRANSFORM_ANGLEZ
// Slope rotation from Kart
p.anglez = 0.0f;
if (spr->mobj->standingslope)
{
fixed_t tempz = spr->mobj->standingslope->normal.z;
fixed_t tempy = spr->mobj->standingslope->normal.y;
fixed_t tempx = spr->mobj->standingslope->normal.x;
fixed_t tempangle = AngleFixed(R_PointToAngle2(0, 0, FixedSqrt(FixedMul(tempy, tempy) + FixedMul(tempz, tempz)), tempx));
p.anglez = FIXED_TO_FLOAT(tempangle);
tempangle = -AngleFixed(R_PointToAngle2(0, 0, tempz, tempy));
p.anglex = FIXED_TO_FLOAT(tempangle);
}
else
#endif
p.anglex = 0.0f;
color[0] = Surf.FlatColor.s.red;
color[1] = Surf.FlatColor.s.green;
@ -1553,8 +1227,11 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
finalscale *= FIXED_TO_FLOAT(spr->mobj->scale);
p.flip = atransform.flip;
#ifdef USE_FTRANSFORM_MIRROR
p.mirror = atransform.mirror; // from Kart
#endif
HWD.pfnDrawMD2i(buff, curr, durs, tics, next, &p, finalscale, flip, color);
HWD.pfnDrawModel(md2->model, frame, durs, tics, nextFrame, &p, finalscale, flip, color);
}
}

View file

@ -22,104 +22,7 @@
#define _HW_MD2_H_
#include "hw_glob.h"
#include "../info.h"
// magic number "IDP2" or 844121161
#define MD2_IDENT (INT32)(('2' << 24) + ('P' << 16) + ('D' << 8) + 'I')
// model version
#define MD2_VERSION 8
// magic number "IDP2" or 844121161
#define MD2_IDENT (INT32)(('2' << 24) + ('P' << 16) + ('D' << 8) + 'I')
// model version
#define MD2_VERSION 8
#define MD2_MAX_TRIANGLES 8192
#define MD2_MAX_VERTICES 4096
#define MD2_MAX_TEXCOORDS 4096
#define MD2_MAX_FRAMES 512
#define MD2_MAX_SKINS 32
#define MD2_MAX_FRAMESIZE (MD2_MAX_VERTICES * 4 + 128)
#if defined(_MSC_VER)
#pragma pack(1)
#endif
typedef struct
{
UINT32 magic;
UINT32 version;
UINT32 skinWidth;
UINT32 skinHeight;
UINT32 frameSize;
UINT32 numSkins;
UINT32 numVertices;
UINT32 numTexCoords;
UINT32 numTriangles;
UINT32 numGlCommands;
UINT32 numFrames;
UINT32 offsetSkins;
UINT32 offsetTexCoords;
UINT32 offsetTriangles;
UINT32 offsetFrames;
UINT32 offsetGlCommands;
UINT32 offsetEnd;
} ATTRPACK md2_header_t; //NOTE: each of md2_header's members are 4 unsigned bytes
typedef struct
{
UINT8 vertex[3];
UINT8 lightNormalIndex;
} ATTRPACK md2_alias_triangleVertex_t;
typedef struct
{
float vertex[3];
float normal[3];
} ATTRPACK md2_triangleVertex_t;
typedef struct
{
INT16 vertexIndices[3];
INT16 textureIndices[3];
} ATTRPACK md2_triangle_t;
typedef struct
{
INT16 s, t;
} ATTRPACK md2_textureCoordinate_t;
typedef struct
{
float scale[3];
float translate[3];
char name[16];
md2_alias_triangleVertex_t alias_vertices[1];
} ATTRPACK md2_alias_frame_t;
typedef struct
{
char name[16];
md2_triangleVertex_t *vertices;
} ATTRPACK md2_frame_t;
typedef char md2_skin_t[64];
typedef struct
{
float s, t;
INT32 vertexIndex;
} ATTRPACK md2_glCommandVertex_t;
typedef struct
{
md2_header_t header;
md2_skin_t *skins;
md2_textureCoordinate_t *texCoords;
md2_triangle_t *triangles;
md2_frame_t *frames;
size_t *spr2frames; // size_t spr2frames[2*NUMPLAYERSPRITES][2];
INT32 *glCommandBuffer;
} ATTRPACK md2_model_t;
#include "hw_model.h"
#if defined(_MSC_VER)
#pragma pack()
@ -130,7 +33,7 @@ typedef struct
char filename[32];
float scale;
float offset;
md2_model_t *model;
model_t *model;
void *grpatch;
void *blendgrpatch;
boolean notfound;
@ -141,9 +44,9 @@ typedef struct
extern md2_t md2_models[NUMSPRITES];
extern md2_t md2_playermodels[MAXSKINS];
void HWR_InitMD2(void);
void HWR_DrawMD2(gr_vissprite_t *spr);
void HWR_AddPlayerMD2(INT32 skin);
void HWR_AddSpriteMD2(size_t spritenum);
void HWR_InitModels(void);
void HWR_DrawModel(gr_vissprite_t *spr);
void HWR_AddPlayerModel(INT32 skin);
void HWR_AddSpriteModel(size_t spritenum);
#endif // _HW_MD2_H_

576
src/hardware/hw_md2load.c Normal file
View file

@ -0,0 +1,576 @@
/*
From the 'Wizard2' engine by Spaddlewit Inc. ( http://www.spaddlewit.com )
An experimental work-in-progress.
Donated to Sonic Team Junior and adapted to work with
Sonic Robo Blast 2. The license of this code matches whatever
the licensing is for Sonic Robo Blast 2.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "../doomdef.h"
#include "hw_md2load.h"
#include "hw_model.h"
#include "../z_zone.h"
#define NUMVERTEXNORMALS 162
// Quake 2 normals are indexed. Use avertexnormals[normalindex][x/y/z] and
// you'll have your normals.
float avertexnormals[NUMVERTEXNORMALS][3] = {
{-0.525731f, 0.000000f, 0.850651f},
{-0.442863f, 0.238856f, 0.864188f},
{-0.295242f, 0.000000f, 0.955423f},
{-0.309017f, 0.500000f, 0.809017f},
{-0.162460f, 0.262866f, 0.951056f},
{0.000000f, 0.000000f, 1.000000f},
{0.000000f, 0.850651f, 0.525731f},
{-0.147621f, 0.716567f, 0.681718f},
{0.147621f, 0.716567f, 0.681718f},
{0.000000f, 0.525731f, 0.850651f},
{0.309017f, 0.500000f, 0.809017f},
{0.525731f, 0.000000f, 0.850651f},
{0.295242f, 0.000000f, 0.955423f},
{0.442863f, 0.238856f, 0.864188f},
{0.162460f, 0.262866f, 0.951056f},
{-0.681718f, 0.147621f, 0.716567f},
{-0.809017f, 0.309017f, 0.500000f},
{-0.587785f, 0.425325f, 0.688191f},
{-0.850651f, 0.525731f, 0.000000f},
{-0.864188f, 0.442863f, 0.238856f},
{-0.716567f, 0.681718f, 0.147621f},
{-0.688191f, 0.587785f, 0.425325f},
{-0.500000f, 0.809017f, 0.309017f},
{-0.238856f, 0.864188f, 0.442863f},
{-0.425325f, 0.688191f, 0.587785f},
{-0.716567f, 0.681718f, -0.147621f},
{-0.500000f, 0.809017f, -0.309017f},
{-0.525731f, 0.850651f, 0.000000f},
{0.000000f, 0.850651f, -0.525731f},
{-0.238856f, 0.864188f, -0.442863f},
{0.000000f, 0.955423f, -0.295242f},
{-0.262866f, 0.951056f, -0.162460f},
{0.000000f, 1.000000f, 0.000000f},
{0.000000f, 0.955423f, 0.295242f},
{-0.262866f, 0.951056f, 0.162460f},
{0.238856f, 0.864188f, 0.442863f},
{0.262866f, 0.951056f, 0.162460f},
{0.500000f, 0.809017f, 0.309017f},
{0.238856f, 0.864188f, -0.442863f},
{0.262866f, 0.951056f, -0.162460f},
{0.500000f, 0.809017f, -0.309017f},
{0.850651f, 0.525731f, 0.000000f},
{0.716567f, 0.681718f, 0.147621f},
{0.716567f, 0.681718f, -0.147621f},
{0.525731f, 0.850651f, 0.000000f},
{0.425325f, 0.688191f, 0.587785f},
{0.864188f, 0.442863f, 0.238856f},
{0.688191f, 0.587785f, 0.425325f},
{0.809017f, 0.309017f, 0.500000f},
{0.681718f, 0.147621f, 0.716567f},
{0.587785f, 0.425325f, 0.688191f},
{0.955423f, 0.295242f, 0.000000f},
{1.000000f, 0.000000f, 0.000000f},
{0.951056f, 0.162460f, 0.262866f},
{0.850651f, -0.525731f, 0.000000f},
{0.955423f, -0.295242f, 0.000000f},
{0.864188f, -0.442863f, 0.238856f},
{0.951056f, -0.162460f, 0.262866f},
{0.809017f, -0.309017f, 0.500000f},
{0.681718f, -0.147621f, 0.716567f},
{0.850651f, 0.000000f, 0.525731f},
{0.864188f, 0.442863f, -0.238856f},
{0.809017f, 0.309017f, -0.500000f},
{0.951056f, 0.162460f, -0.262866f},
{0.525731f, 0.000000f, -0.850651f},
{0.681718f, 0.147621f, -0.716567f},
{0.681718f, -0.147621f, -0.716567f},
{0.850651f, 0.000000f, -0.525731f},
{0.809017f, -0.309017f, -0.500000f},
{0.864188f, -0.442863f, -0.238856f},
{0.951056f, -0.162460f, -0.262866f},
{0.147621f, 0.716567f, -0.681718f},
{0.309017f, 0.500000f, -0.809017f},
{0.425325f, 0.688191f, -0.587785f},
{0.442863f, 0.238856f, -0.864188f},
{0.587785f, 0.425325f, -0.688191f},
{0.688191f, 0.587785f, -0.425325f},
{-0.147621f, 0.716567f, -0.681718f},
{-0.309017f, 0.500000f, -0.809017f},
{0.000000f, 0.525731f, -0.850651f},
{-0.525731f, 0.000000f, -0.850651f},
{-0.442863f, 0.238856f, -0.864188f},
{-0.295242f, 0.000000f, -0.955423f},
{-0.162460f, 0.262866f, -0.951056f},
{0.000000f, 0.000000f, -1.000000f},
{0.295242f, 0.000000f, -0.955423f},
{0.162460f, 0.262866f, -0.951056f},
{-0.442863f, -0.238856f, -0.864188f},
{-0.309017f, -0.500000f, -0.809017f},
{-0.162460f, -0.262866f, -0.951056f},
{0.000000f, -0.850651f, -0.525731f},
{-0.147621f, -0.716567f, -0.681718f},
{0.147621f, -0.716567f, -0.681718f},
{0.000000f, -0.525731f, -0.850651f},
{0.309017f, -0.500000f, -0.809017f},
{0.442863f, -0.238856f, -0.864188f},
{0.162460f, -0.262866f, -0.951056f},
{0.238856f, -0.864188f, -0.442863f},
{0.500000f, -0.809017f, -0.309017f},
{0.425325f, -0.688191f, -0.587785f},
{0.716567f, -0.681718f, -0.147621f},
{0.688191f, -0.587785f, -0.425325f},
{0.587785f, -0.425325f, -0.688191f},
{0.000000f, -0.955423f, -0.295242f},
{0.000000f, -1.000000f, 0.000000f},
{0.262866f, -0.951056f, -0.162460f},
{0.000000f, -0.850651f, 0.525731f},
{0.000000f, -0.955423f, 0.295242f},
{0.238856f, -0.864188f, 0.442863f},
{0.262866f, -0.951056f, 0.162460f},
{0.500000f, -0.809017f, 0.309017f},
{0.716567f, -0.681718f, 0.147621f},
{0.525731f, -0.850651f, 0.000000f},
{-0.238856f, -0.864188f, -0.442863f},
{-0.500000f, -0.809017f, -0.309017f},
{-0.262866f, -0.951056f, -0.162460f},
{-0.850651f, -0.525731f, 0.000000f},
{-0.716567f, -0.681718f, -0.147621f},
{-0.716567f, -0.681718f, 0.147621f},
{-0.525731f, -0.850651f, 0.000000f},
{-0.500000f, -0.809017f, 0.309017f},
{-0.238856f, -0.864188f, 0.442863f},
{-0.262866f, -0.951056f, 0.162460f},
{-0.864188f, -0.442863f, 0.238856f},
{-0.809017f, -0.309017f, 0.500000f},
{-0.688191f, -0.587785f, 0.425325f},
{-0.681718f, -0.147621f, 0.716567f},
{-0.442863f, -0.238856f, 0.864188f},
{-0.587785f, -0.425325f, 0.688191f},
{-0.309017f, -0.500000f, 0.809017f},
{-0.147621f, -0.716567f, 0.681718f},
{-0.425325f, -0.688191f, 0.587785f},
{-0.162460f, -0.262866f, 0.951056f},
{0.442863f, -0.238856f, 0.864188f},
{0.162460f, -0.262866f, 0.951056f},
{0.309017f, -0.500000f, 0.809017f},
{0.147621f, -0.716567f, 0.681718f},
{0.000000f, -0.525731f, 0.850651f},
{0.425325f, -0.688191f, 0.587785f},
{0.587785f, -0.425325f, 0.688191f},
{0.688191f, -0.587785f, 0.425325f},
{-0.955423f, 0.295242f, 0.000000f},
{-0.951056f, 0.162460f, 0.262866f},
{-1.000000f, 0.000000f, 0.000000f},
{-0.850651f, 0.000000f, 0.525731f},
{-0.955423f, -0.295242f, 0.000000f},
{-0.951056f, -0.162460f, 0.262866f},
{-0.864188f, 0.442863f, -0.238856f},
{-0.951056f, 0.162460f, -0.262866f},
{-0.809017f, 0.309017f, -0.500000f},
{-0.864188f, -0.442863f, -0.238856f},
{-0.951056f, -0.162460f, -0.262866f},
{-0.809017f, -0.309017f, -0.500000f},
{-0.681718f, 0.147621f, -0.716567f},
{-0.681718f, -0.147621f, -0.716567f},
{-0.850651f, 0.000000f, -0.525731f},
{-0.688191f, 0.587785f, -0.425325f},
{-0.587785f, 0.425325f, -0.688191f},
{-0.425325f, 0.688191f, -0.587785f},
{-0.425325f, -0.688191f, -0.587785f},
{-0.587785f, -0.425325f, -0.688191f},
{-0.688191f, -0.587785f, -0.425325f},
};
typedef struct
{
int ident; // A "magic number" that's used to identify the .md2 file
int version; // The version of the file, always 8
int skinwidth; // Width of the skin(s) in pixels
int skinheight; // Height of the skin(s) in pixels
int framesize; // Size of each frame in bytes
int numSkins; // Number of skins with the model
int numXYZ; // Number of vertices in each frame
int numST; // Number of texture coordinates in each frame.
int numTris; // Number of triangles in each frame
int numGLcmds; // Number of dwords (4 bytes) in the gl command list.
int numFrames; // Number of frames
int offsetSkins; // Offset, in bytes from the start of the file, to the list of skin names.
int offsetST; // Offset, in bytes from the start of the file, to the list of texture coordinates
int offsetTris; // Offset, in bytes from the start of the file, to the list of triangles
int offsetFrames; // Offset, in bytes from the start of the file, to the list of frames
int offsetGLcmds; // Offset, in bytes from the start of the file, to the list of gl commands
int offsetEnd; // Offset, in bytes from the start of the file, to the end of the file (filesize)
} md2header_t;
typedef struct
{
unsigned short meshIndex[3]; // indices into the array of vertices in each frames
unsigned short stIndex[3]; // indices into the array of texture coordinates
} md2triangle_t;
typedef struct
{
short s;
short t;
} md2texcoord_t;
typedef struct
{
unsigned char v[3]; // Scaled vertices. You'll need to multiply them with scale[x] to make them normal.
unsigned char lightNormalIndex; // Index to the array of normals
} md2vertex_t;
typedef struct
{
float scale[3]; // Used by the v member in the md2framePoint structure
float translate[3]; // Used by the v member in the md2framePoint structure
char name[16]; // Name of the frame
} md2frame_t;
// Load the model
model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat)
{
FILE *f;
model_t *retModel = NULL;
md2header_t *header;
size_t fileLen;
int i, j;
size_t namelen;
char *texturefilename;
const char *texPos;
char *buffer;
const float WUNITS = 1.0f;
float dataScale = WUNITS;
md2triangle_t *tris;
md2texcoord_t *texcoords;
md2frame_t *frames;
char *fname = NULL;
int foffset = 0;
int t;
// MD2 currently does not work with tinyframes, so force useFloat = true
//
// <SSNTails>
// the UV coordinates in MD2 are not compatible with glDrawElements like MD3 is. So they need to be loaded as full float.
//
// MD2 is intended to be draw in triangle strips and fans
// not very compatible with a modern GL implementation, either
// so the idea would be to full float expand it, and put it in a vertex buffer object
// I'm sure there's a way to convert the UVs to 'tinyframes', but maybe that's a job for someone else.
// You'd have to decompress the model, then recompress, reindexing the triangles and weeding out duplicate coordinates
// I already have the decompression work done
useFloat = true;
f = fopen(fileName, "rb");
if (!f)
return NULL;
retModel = (model_t*)Z_Calloc(sizeof(model_t), ztag, 0);
//size_t fileLen;
//int i, j;
//size_t namelen;
//char *texturefilename;
texPos = strchr(fileName, '/');
if (texPos)
{
texPos++;
namelen = strlen(texPos) + 1;
texturefilename = (char*)Z_Malloc(namelen, PU_CACHE, 0);
strcpy(texturefilename, texPos);
}
else
{
namelen = strlen(fileName) + 1;
texturefilename = (char*)Z_Malloc(namelen, PU_CACHE, 0);
strcpy(texturefilename, fileName);
}
texturefilename[namelen - 2] = 'z';
texturefilename[namelen - 3] = 'u';
texturefilename[namelen - 4] = 'b';
// find length of file
fseek(f, 0, SEEK_END);
fileLen = ftell(f);
fseek(f, 0, SEEK_SET);
// read in file
buffer = malloc(fileLen);
if (fread(buffer, fileLen, 1, f)) { } // squash ignored fread error
fclose(f);
// get pointer to file header
header = (md2header_t*)buffer;
retModel->numMeshes = 1; // MD2 only has one mesh
retModel->meshes = (mesh_t*)Z_Calloc(sizeof(mesh_t) * retModel->numMeshes, ztag, 0);
retModel->meshes[0].numFrames = header->numFrames;
// const float WUNITS = 1.0f;
// float dataScale = WUNITS;
// Tris and ST are simple structures that can be straight-copied
tris = (md2triangle_t*)&buffer[header->offsetTris];
texcoords = (md2texcoord_t*)&buffer[header->offsetST];
frames = (md2frame_t*)&buffer[header->offsetFrames];
retModel->framenames = (char*)Z_Calloc(header->numFrames*16, ztag, 0);
fname = retModel->framenames;
for (i = 0; i < header->numFrames; i++)
{
md2frame_t *fr = (md2frame_t*)&buffer[header->offsetFrames + foffset];
memcpy(fname, fr->name, 16);
foffset += sizeof(md2frame_t) + (sizeof(md2vertex_t) * header->numXYZ);
fname += 16;
}
// Read in textures
retModel->numMaterials = header->numSkins;
if (retModel->numMaterials <= 0) // Always at least one skin, duh
retModel->numMaterials = 1;
retModel->materials = (material_t*)Z_Calloc(sizeof(material_t)*retModel->numMaterials, ztag, 0);
// int t;
for (t = 0; t < retModel->numMaterials; t++)
{
retModel->materials[t].ambient[0] = 0.8f;
retModel->materials[t].ambient[1] = 0.8f;
retModel->materials[t].ambient[2] = 0.8f;
retModel->materials[t].ambient[3] = 1.0f;
retModel->materials[t].diffuse[0] = 0.8f;
retModel->materials[t].diffuse[1] = 0.8f;
retModel->materials[t].diffuse[2] = 0.8f;
retModel->materials[t].diffuse[3] = 1.0f;
retModel->materials[t].emissive[0] = 0.0f;
retModel->materials[t].emissive[1] = 0.0f;
retModel->materials[t].emissive[2] = 0.0f;
retModel->materials[t].emissive[3] = 1.0f;
retModel->materials[t].specular[0] = 0.0f;
retModel->materials[t].specular[1] = 0.0f;
retModel->materials[t].specular[2] = 0.0f;
retModel->materials[t].specular[3] = 1.0f;
retModel->materials[t].shininess = 0.0f;
retModel->materials[t].spheremap = false;
/* retModel->materials[t].texture = Texture::ReadTexture((char*)texturefilename, ZT_TEXTURE);
if (!systemSucks)
{
// Check for a normal map...??
char openfilename[1024];
char normalMapName[1024];
strcpy(normalMapName, texturefilename);
size_t len = strlen(normalMapName);
char *ptr = &normalMapName[len];
ptr--; // z
ptr--; // u
ptr--; // b
ptr--; // .
*ptr++ = '_';
*ptr++ = 'n';
*ptr++ = '.';
*ptr++ = 'b';
*ptr++ = 'u';
*ptr++ = 'z';
*ptr++ = '\0';
sprintf(openfilename, "%s/%s", "textures", normalMapName);
// Convert backslashes to forward slashes
for (int k = 0; k < 1024; k++)
{
if (openfilename[k] == '\0')
break;
if (openfilename[k] == '\\')
openfilename[k] = '/';
}
Resource::resource_t *res = Resource::Open(openfilename);
if (res)
{
Resource::Close(res);
retModel->materials[t].lightmap = Texture::ReadTexture(normalMapName, ZT_TEXTURE);
}
}*/
}
retModel->meshes[0].numTriangles = header->numTris;
if (!useFloat) // Decompress to MD3 'tinyframe' space
{
char *ptr;
md2triangle_t *trisPtr;
unsigned short *indexptr;
float *uvptr;
dataScale = 0.015624f; // 1 / 64.0f
retModel->meshes[0].tinyframes = (tinyframe_t*)Z_Calloc(sizeof(tinyframe_t)*header->numFrames, ztag, 0);
retModel->meshes[0].numVertices = header->numXYZ;
retModel->meshes[0].uvs = (float*)Z_Malloc(sizeof(float) * 2 * retModel->meshes[0].numVertices, ztag, 0);
ptr = (char*)frames;
for (i = 0; i < header->numFrames; i++, ptr += header->framesize)
{
short *vertptr;
char *normptr;
// char *tanptr;
md2vertex_t *vertex;
md2frame_t *framePtr = (md2frame_t*)ptr;
retModel->meshes[0].tinyframes[i].vertices = (short*)Z_Malloc(sizeof(short) * 3 * header->numXYZ, ztag, 0);
retModel->meshes[0].tinyframes[i].normals = (char*)Z_Malloc(sizeof(char) * 3 * header->numXYZ, ztag, 0);
// if (retModel->materials[0].lightmap)
// retModel->meshes[0].tinyframes[i].tangents = (char*)malloc(sizeof(char));//(char*)Z_Malloc(sizeof(char)*3*header->numVerts, ztag);
retModel->meshes[0].indices = (unsigned short*)Z_Malloc(sizeof(unsigned short) * 3 * header->numTris, ztag, 0);
vertptr = retModel->meshes[0].tinyframes[i].vertices;
normptr = retModel->meshes[0].tinyframes[i].normals;
// tanptr = retModel->meshes[0].tinyframes[i].tangents;
retModel->meshes[0].tinyframes[i].material = &retModel->materials[0];
framePtr++; // Advance to vertex list
vertex = (md2vertex_t*)framePtr;
framePtr--;
for (j = 0; j < header->numXYZ; j++, vertex++)
{
*vertptr = (short)(((vertex->v[0] * framePtr->scale[0]) + framePtr->translate[0]) / dataScale);
vertptr++;
*vertptr = (short)(((vertex->v[2] * framePtr->scale[2]) + framePtr->translate[2]) / dataScale);
vertptr++;
*vertptr = -1.0f * (short)(((vertex->v[1] * framePtr->scale[1]) + framePtr->translate[1]) / dataScale);
vertptr++;
// Normal
*normptr++ = (char)(avertexnormals[vertex->lightNormalIndex][0] * 127);
*normptr++ = (char)(avertexnormals[vertex->lightNormalIndex][2] * 127);
*normptr++ = (char)(avertexnormals[vertex->lightNormalIndex][1] * 127);
}
}
// This doesn't need to be done every frame!
trisPtr = tris;
indexptr = retModel->meshes[0].indices;
uvptr = (float*)retModel->meshes[0].uvs;
for (j = 0; j < header->numTris; j++, trisPtr++)
{
*indexptr = trisPtr->meshIndex[0];
indexptr++;
*indexptr = trisPtr->meshIndex[1];
indexptr++;
*indexptr = trisPtr->meshIndex[2];
indexptr++;
uvptr[trisPtr->meshIndex[0] * 2] = texcoords[trisPtr->stIndex[0]].s / (float)header->skinwidth;
uvptr[trisPtr->meshIndex[0] * 2 + 1] = (texcoords[trisPtr->stIndex[0]].t / (float)header->skinheight);
uvptr[trisPtr->meshIndex[1] * 2] = texcoords[trisPtr->stIndex[1]].s / (float)header->skinwidth;
uvptr[trisPtr->meshIndex[1] * 2 + 1] = (texcoords[trisPtr->stIndex[1]].t / (float)header->skinheight);
uvptr[trisPtr->meshIndex[2] * 2] = texcoords[trisPtr->stIndex[2]].s / (float)header->skinwidth;
uvptr[trisPtr->meshIndex[2] * 2 + 1] = (texcoords[trisPtr->stIndex[2]].t / (float)header->skinheight);
}
}
else // Full float loading method
{
md2triangle_t *trisPtr;
float *uvptr;
char *ptr;
retModel->meshes[0].numVertices = header->numTris * 3;
retModel->meshes[0].frames = (mdlframe_t*)Z_Calloc(sizeof(mdlframe_t)*header->numFrames, ztag, 0);
retModel->meshes[0].uvs = (float*)Z_Malloc(sizeof(float) * 2 * retModel->meshes[0].numVertices, ztag, 0);
trisPtr = tris;
uvptr = retModel->meshes[0].uvs;
for (i = 0; i < retModel->meshes[0].numTriangles; i++, trisPtr++)
{
*uvptr++ = texcoords[trisPtr->stIndex[0]].s / (float)header->skinwidth;
*uvptr++ = (texcoords[trisPtr->stIndex[0]].t / (float)header->skinheight);
*uvptr++ = texcoords[trisPtr->stIndex[1]].s / (float)header->skinwidth;
*uvptr++ = (texcoords[trisPtr->stIndex[1]].t / (float)header->skinheight);
*uvptr++ = texcoords[trisPtr->stIndex[2]].s / (float)header->skinwidth;
*uvptr++ = (texcoords[trisPtr->stIndex[2]].t / (float)header->skinheight);
}
ptr = (char*)frames;
for (i = 0; i < header->numFrames; i++, ptr += header->framesize)
{
float *vertptr, *normptr;
md2vertex_t *vertex;
md2frame_t *framePtr = (md2frame_t*)ptr;
retModel->meshes[0].frames[i].normals = (float*)Z_Malloc(sizeof(float) * 3 * header->numTris * 3, ztag, 0);
retModel->meshes[0].frames[i].vertices = (float*)Z_Malloc(sizeof(float) * 3 * header->numTris * 3, ztag, 0);
// if (retModel->materials[0].lightmap)
// retModel->meshes[0].frames[i].tangents = (float*)malloc(sizeof(float));//(float*)Z_Malloc(sizeof(float)*3*header->numTris*3, ztag);
//float *vertptr, *normptr;
normptr = (float*)retModel->meshes[0].frames[i].normals;
vertptr = (float*)retModel->meshes[0].frames[i].vertices;
trisPtr = tris;
retModel->meshes[0].frames[i].material = &retModel->materials[0];
framePtr++; // Advance to vertex list
vertex = (md2vertex_t*)framePtr;
framePtr--;
for (j = 0; j < header->numTris; j++, trisPtr++)
{
*vertptr = ((vertex[trisPtr->meshIndex[0]].v[0] * framePtr->scale[0]) + framePtr->translate[0]) * WUNITS;
vertptr++;
*vertptr = ((vertex[trisPtr->meshIndex[0]].v[2] * framePtr->scale[2]) + framePtr->translate[2]) * WUNITS;
vertptr++;
*vertptr = -1.0f * ((vertex[trisPtr->meshIndex[0]].v[1] * framePtr->scale[1]) + framePtr->translate[1]) * WUNITS;
vertptr++;
*vertptr = ((vertex[trisPtr->meshIndex[1]].v[0] * framePtr->scale[0]) + framePtr->translate[0]) * WUNITS;
vertptr++;
*vertptr = ((vertex[trisPtr->meshIndex[1]].v[2] * framePtr->scale[2]) + framePtr->translate[2]) * WUNITS;
vertptr++;
*vertptr = -1.0f * ((vertex[trisPtr->meshIndex[1]].v[1] * framePtr->scale[1]) + framePtr->translate[1]) * WUNITS;
vertptr++;
*vertptr = ((vertex[trisPtr->meshIndex[2]].v[0] * framePtr->scale[0]) + framePtr->translate[0]) * WUNITS;
vertptr++;
*vertptr = ((vertex[trisPtr->meshIndex[2]].v[2] * framePtr->scale[2]) + framePtr->translate[2]) * WUNITS;
vertptr++;
*vertptr = -1.0f * ((vertex[trisPtr->meshIndex[2]].v[1] * framePtr->scale[1]) + framePtr->translate[1]) * WUNITS;
vertptr++;
*normptr++ = avertexnormals[vertex[trisPtr->meshIndex[0]].lightNormalIndex][0];
*normptr++ = avertexnormals[vertex[trisPtr->meshIndex[0]].lightNormalIndex][2];
*normptr++ = avertexnormals[vertex[trisPtr->meshIndex[0]].lightNormalIndex][1];
*normptr++ = avertexnormals[vertex[trisPtr->meshIndex[1]].lightNormalIndex][0];
*normptr++ = avertexnormals[vertex[trisPtr->meshIndex[1]].lightNormalIndex][2];
*normptr++ = avertexnormals[vertex[trisPtr->meshIndex[1]].lightNormalIndex][1];
*normptr++ = avertexnormals[vertex[trisPtr->meshIndex[2]].lightNormalIndex][0];
*normptr++ = avertexnormals[vertex[trisPtr->meshIndex[2]].lightNormalIndex][2];
*normptr++ = avertexnormals[vertex[trisPtr->meshIndex[2]].lightNormalIndex][1];
}
}
}
free(buffer);
return retModel;
}

19
src/hardware/hw_md2load.h Normal file
View file

@ -0,0 +1,19 @@
/*
From the 'Wizard2' engine by Spaddlewit Inc. ( http://www.spaddlewit.com )
An experimental work-in-progress.
Donated to Sonic Team Junior and adapted to work with
Sonic Robo Blast 2. The license of this code matches whatever
the licensing is for Sonic Robo Blast 2.
*/
#ifndef _HW_MD2LOAD_H_
#define _HW_MD2LOAD_H_
#include "hw_model.h"
#include "../doomtype.h"
// Load the Model
model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat);
#endif

522
src/hardware/hw_md3load.c Normal file
View file

@ -0,0 +1,522 @@
/*
From the 'Wizard2' engine by Spaddlewit Inc. ( http://www.spaddlewit.com )
An experimental work-in-progress.
Donated to Sonic Team Junior and adapted to work with
Sonic Robo Blast 2. The license of this code matches whatever
the licensing is for Sonic Robo Blast 2.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "../doomdef.h"
#include "hw_md3load.h"
#include "hw_model.h"
#include "../z_zone.h"
typedef struct
{
int ident; // A "magic number" that's used to identify the .md3 file
int version; // The version of the file, always 15
char name[64];
int flags;
int numFrames; // Number of frames
int numTags;
int numSurfaces;
int numSkins; // Number of skins with the model
int offsetFrames;
int offsetTags;
int offsetSurfaces;
int offsetEnd; // Offset, in bytes from the start of the file, to the end of the file (filesize)
} md3modelHeader;
typedef struct
{
float minBounds[3]; // First corner of the bounding box
float maxBounds[3]; // Second corner of the bounding box
float localOrigin[3]; // Local origin, usually (0, 0, 0)
float radius; // Radius of bounding sphere
char name[16]; // Name of frame
} md3Frame;
typedef struct
{
char name[64]; // Name of tag
float origin[3]; // Coordinates of tag
float axis[9]; // Orientation of tag object
} md3Tag;
typedef struct
{
int ident;
char name[64]; // Name of this surface
int flags;
int numFrames; // # of keyframes
int numShaders; // # of shaders
int numVerts; // # of vertices
int numTriangles; // # of triangles
int offsetTriangles; // Relative offset from start of this struct to where the list of Triangles start
int offsetShaders; // Relative offset from start of this struct to where the list of Shaders start
int offsetST; // Relative offset from start of this struct to where the list of tex coords start
int offsetXYZNormal; // Relative offset from start of this struct to where the list of vertices start
int offsetEnd; // Relative offset from start of this struct to where this surface ends
} md3Surface;
typedef struct
{
char name[64]; // Name of this shader
int shaderIndex; // Shader index number
} md3Shader;
typedef struct
{
int index[3]; // List of offset values into the list of Vertex objects that constitute the corners of the Triangle object.
} md3Triangle;
typedef struct
{
float st[2];
} md3TexCoord;
typedef struct
{
short x, y, z, n;
} md3Vertex;
static float latlnglookup[256][256][3];
static void GetNormalFromLatLong(short latlng, float *out)
{
float *lookup = latlnglookup[(unsigned char)(latlng >> 8)][(unsigned char)(latlng & 255)];
out[0] = *lookup++;
out[1] = *lookup++;
out[2] = *lookup++;
}
#if 0
static void NormalToLatLng(float *n, short *out)
{
// Special cases
if (0.0f == n[0] && 0.0f == n[1])
{
if (n[2] > 0.0f)
*out = 0;
else
*out = 128;
}
else
{
char x, y;
x = (char)(57.2957795f * (atan2(n[1], n[0])) * (255.0f / 360.0f));
y = (char)(57.2957795f * (acos(n[2])) * (255.0f / 360.0f));
*out = (x << 8) + y;
}
}
#endif
static inline void LatLngToNormal(short n, float *out)
{
const float PI = (3.1415926535897932384626433832795f);
float lat = (float)(n >> 8);
float lng = (float)(n & 255);
lat *= PI / 128.0f;
lng *= PI / 128.0f;
out[0] = cosf(lat) * sinf(lng);
out[1] = sinf(lat) * sinf(lng);
out[2] = cosf(lng);
}
static void LatLngInit(void)
{
int i, j;
for (i = 0; i < 256; i++)
{
for (j = 0; j < 256; j++)
LatLngToNormal((short)((i << 8) + j), latlnglookup[i][j]);
}
}
static boolean latlnginit = false;
model_t *MD3_LoadModel(const char *fileName, int ztag, boolean useFloat)
{
const float WUNITS = 1.0f;
model_t *retModel = NULL;
md3Frame *frames = NULL;
char *fname = NULL;
md3modelHeader *mdh;
long fileLen;
long fileReadLen;
char *buffer;
int surfEnd;
int i, t;
int matCount;
FILE *f;
if (!latlnginit)
{
LatLngInit();
latlnginit = true;
}
f = fopen(fileName, "rb");
if (!f)
return NULL;
retModel = (model_t*)Z_Calloc(sizeof(model_t), ztag, 0);
// find length of file
fseek(f, 0, SEEK_END);
fileLen = ftell(f);
fseek(f, 0, SEEK_SET);
// read in file
buffer = malloc(fileLen);
fileReadLen = fread(buffer, fileLen, 1, f);
fclose(f);
(void)fileReadLen; // intentionally ignore return value, per buildbot
// get pointer to file header
mdh = (md3modelHeader*)buffer;
retModel->numMeshes = mdh->numSurfaces;
retModel->numMaterials = 0;
surfEnd = 0;
for (i = 0; i < mdh->numSurfaces; i++)
{
md3Surface *mdS = (md3Surface*)&buffer[mdh->offsetSurfaces];
surfEnd += mdS->offsetEnd;
retModel->numMaterials += mdS->numShaders;
}
// Initialize materials
if (retModel->numMaterials <= 0) // Always at least one skin, duh
retModel->numMaterials = 1;
retModel->materials = (material_t*)Z_Calloc(sizeof(material_t)*retModel->numMaterials, ztag, 0);
for (t = 0; t < retModel->numMaterials; t++)
{
retModel->materials[t].ambient[0] = 0.3686f;
retModel->materials[t].ambient[1] = 0.3684f;
retModel->materials[t].ambient[2] = 0.3684f;
retModel->materials[t].ambient[3] = 1.0f;
retModel->materials[t].diffuse[0] = 0.8863f;
retModel->materials[t].diffuse[1] = 0.8850f;
retModel->materials[t].diffuse[2] = 0.8850f;
retModel->materials[t].diffuse[3] = 1.0f;
retModel->materials[t].emissive[0] = 0.0f;
retModel->materials[t].emissive[1] = 0.0f;
retModel->materials[t].emissive[2] = 0.0f;
retModel->materials[t].emissive[3] = 1.0f;
retModel->materials[t].specular[0] = 0.4902f;
retModel->materials[t].specular[1] = 0.4887f;
retModel->materials[t].specular[2] = 0.4887f;
retModel->materials[t].specular[3] = 1.0f;
retModel->materials[t].shininess = 25.0f;
retModel->materials[t].spheremap = false;
}
retModel->meshes = (mesh_t*)Z_Calloc(sizeof(mesh_t)*retModel->numMeshes, ztag, 0);
frames = (md3Frame*)&buffer[mdh->offsetFrames];
retModel->framenames = (char*)Z_Calloc(mdh->numFrames*16, ztag, 0);
fname = retModel->framenames;
for (i = 0; i < mdh->numFrames; i++)
{
memcpy(fname, frames->name, 16);
fname += 16;
frames++;
}
matCount = 0;
for (i = 0, surfEnd = 0; i < mdh->numSurfaces; i++)
{
int j;
md3Shader *mdShader;
md3Surface *mdS = (md3Surface*)&buffer[mdh->offsetSurfaces + surfEnd];
surfEnd += mdS->offsetEnd;
mdShader = (md3Shader*)((char*)mdS + mdS->offsetShaders);
for (j = 0; j < mdS->numShaders; j++, matCount++)
{
size_t len = strlen(mdShader[j].name);
mdShader[j].name[len-1] = 'z';
mdShader[j].name[len-2] = 'u';
mdShader[j].name[len-3] = 'b';
// Load material
/* retModel->materials[matCount].texture = Texture::ReadTexture(mdShader[j].name, ZT_TEXTURE);
if (!systemSucks)
{
// Check for a normal map...??
char openfilename[1024];
char normalMapName[1024];
strcpy(normalMapName, mdShader[j].name);
len = strlen(normalMapName);
char *ptr = &normalMapName[len];
ptr--; // z
ptr--; // u
ptr--; // b
ptr--; // .
*ptr++ = '_';
*ptr++ = 'n';
*ptr++ = '.';
*ptr++ = 'b';
*ptr++ = 'u';
*ptr++ = 'z';
*ptr++ = '\0';
sprintf(openfilename, "%s/%s", "textures", normalMapName);
// Convert backslashes to forward slashes
for (int k = 0; k < 1024; k++)
{
if (openfilename[k] == '\0')
break;
if (openfilename[k] == '\\')
openfilename[k] = '/';
}
Resource::resource_t *res = Resource::Open(openfilename);
if (res)
{
Resource::Close(res);
retModel->materials[matCount].lightmap = Texture::ReadTexture(normalMapName, ZT_TEXTURE);
}
}*/
}
retModel->meshes[i].numFrames = mdS->numFrames;
retModel->meshes[i].numTriangles = mdS->numTriangles;
if (!useFloat) // 'tinyframe' mode with indices
{
float tempNormal[3];
float *uvptr;
md3TexCoord *mdST;
unsigned short *indexptr;
md3Triangle *mdT;
retModel->meshes[i].tinyframes = (tinyframe_t*)Z_Calloc(sizeof(tinyframe_t)*mdS->numFrames, ztag, 0);
retModel->meshes[i].numVertices = mdS->numVerts;
retModel->meshes[i].uvs = (float*)Z_Malloc(sizeof(float)*2*mdS->numVerts, ztag, 0);
for (j = 0; j < mdS->numFrames; j++)
{
short *vertptr;
char *normptr;
// char *tanptr;
int k;
md3Vertex *mdV = (md3Vertex*)((char*)mdS + mdS->offsetXYZNormal + (mdS->numVerts*j*sizeof(md3Vertex)));
retModel->meshes[i].tinyframes[j].vertices = (short*)Z_Malloc(sizeof(short)*3*mdS->numVerts, ztag, 0);
retModel->meshes[i].tinyframes[j].normals = (char*)Z_Malloc(sizeof(char)*3*mdS->numVerts, ztag, 0);
// if (retModel->materials[0].lightmap)
// retModel->meshes[i].tinyframes[j].tangents = (char*)malloc(sizeof(char));//(char*)Z_Malloc(sizeof(char)*3*mdS->numVerts, ztag);
retModel->meshes[i].indices = (unsigned short*)Z_Malloc(sizeof(unsigned short) * 3 * mdS->numTriangles, ztag, 0);
vertptr = retModel->meshes[i].tinyframes[j].vertices;
normptr = retModel->meshes[i].tinyframes[j].normals;
// tanptr = retModel->meshes[i].tinyframes[j].tangents;
retModel->meshes[i].tinyframes[j].material = &retModel->materials[i];
for (k = 0; k < mdS->numVerts; k++)
{
// Vertex
*vertptr = mdV[k].x;
vertptr++;
*vertptr = mdV[k].z;
vertptr++;
*vertptr = 1.0f - mdV[k].y;
vertptr++;
// Normal
GetNormalFromLatLong(mdV[k].n, tempNormal);
*normptr = (char)(tempNormal[0] * 127);
normptr++;
*normptr = (char)(tempNormal[2] * 127);
normptr++;
*normptr = (char)(tempNormal[1] * 127);
normptr++;
}
}
uvptr = (float*)retModel->meshes[i].uvs;
mdST = (md3TexCoord*)((char*)mdS + mdS->offsetST);
for (j = 0; j < mdS->numVerts; j++)
{
*uvptr = mdST[j].st[0];
uvptr++;
*uvptr = mdST[j].st[1];
uvptr++;
}
indexptr = retModel->meshes[i].indices;
mdT = (md3Triangle*)((char*)mdS + mdS->offsetTriangles);
for (j = 0; j < mdS->numTriangles; j++, mdT++)
{
// Indices
*indexptr = (unsigned short)mdT->index[0];
indexptr++;
*indexptr = (unsigned short)mdT->index[1];
indexptr++;
*indexptr = (unsigned short)mdT->index[2];
indexptr++;
}
}
else // Traditional full-float loading method
{
float dataScale = 0.015624f * WUNITS;
float tempNormal[3];
md3TexCoord *mdST;
md3Triangle *mdT;
float *uvptr;
int k;
retModel->meshes[i].numVertices = mdS->numTriangles * 3;//mdS->numVerts;
retModel->meshes[i].frames = (mdlframe_t*)Z_Calloc(sizeof(mdlframe_t)*mdS->numFrames, ztag, 0);
retModel->meshes[i].uvs = (float*)Z_Malloc(sizeof(float)*2*mdS->numTriangles*3, ztag, 0);
for (j = 0; j < mdS->numFrames; j++)
{
float *vertptr;
float *normptr;
md3Vertex *mdV = (md3Vertex*)((char*)mdS + mdS->offsetXYZNormal + (mdS->numVerts*j*sizeof(md3Vertex)));
retModel->meshes[i].frames[j].vertices = (float*)Z_Malloc(sizeof(float)*3*mdS->numTriangles*3, ztag, 0);
retModel->meshes[i].frames[j].normals = (float*)Z_Malloc(sizeof(float)*3*mdS->numTriangles*3, ztag, 0);
// if (retModel->materials[i].lightmap)
// retModel->meshes[i].frames[j].tangents = (float*)malloc(sizeof(float));//(float*)Z_Malloc(sizeof(float)*3*mdS->numTriangles*3, ztag);
vertptr = retModel->meshes[i].frames[j].vertices;
normptr = retModel->meshes[i].frames[j].normals;
retModel->meshes[i].frames[j].material = &retModel->materials[i];
mdT = (md3Triangle*)((char*)mdS + mdS->offsetTriangles);
for (k = 0; k < mdS->numTriangles; k++)
{
// Vertex 1
*vertptr = mdV[mdT->index[0]].x * dataScale;
vertptr++;
*vertptr = mdV[mdT->index[0]].z * dataScale;
vertptr++;
*vertptr = 1.0f - mdV[mdT->index[0]].y * dataScale;
vertptr++;
GetNormalFromLatLong(mdV[mdT->index[0]].n, tempNormal);
*normptr = tempNormal[0];
normptr++;
*normptr = tempNormal[2];
normptr++;
*normptr = tempNormal[1];
normptr++;
// Vertex 2
*vertptr = mdV[mdT->index[1]].x * dataScale;
vertptr++;
*vertptr = mdV[mdT->index[1]].z * dataScale;
vertptr++;
*vertptr = 1.0f - mdV[mdT->index[1]].y * dataScale;
vertptr++;
GetNormalFromLatLong(mdV[mdT->index[1]].n, tempNormal);
*normptr = tempNormal[0];
normptr++;
*normptr = tempNormal[2];
normptr++;
*normptr = tempNormal[1];
normptr++;
// Vertex 3
*vertptr = mdV[mdT->index[2]].x * dataScale;
vertptr++;
*vertptr = mdV[mdT->index[2]].z * dataScale;
vertptr++;
*vertptr = 1.0f - mdV[mdT->index[2]].y * dataScale;
vertptr++;
GetNormalFromLatLong(mdV[mdT->index[2]].n, tempNormal);
*normptr = tempNormal[0];
normptr++;
*normptr = tempNormal[2];
normptr++;
*normptr = tempNormal[1];
normptr++;
mdT++; // Advance to next triangle
}
}
mdST = (md3TexCoord*)((char*)mdS + mdS->offsetST);
uvptr = (float*)retModel->meshes[i].uvs;
mdT = (md3Triangle*)((char*)mdS + mdS->offsetTriangles);
for (k = 0; k < mdS->numTriangles; k++)
{
*uvptr = mdST[mdT->index[0]].st[0];
uvptr++;
*uvptr = mdST[mdT->index[0]].st[1];
uvptr++;
*uvptr = mdST[mdT->index[1]].st[0];
uvptr++;
*uvptr = mdST[mdT->index[1]].st[1];
uvptr++;
*uvptr = mdST[mdT->index[2]].st[0];
uvptr++;
*uvptr = mdST[mdT->index[2]].st[1];
uvptr++;
mdT++; // Advance to next triangle
}
}
}
/*
// Tags?
retModel->numTags = mdh->numTags;
retModel->maxNumFrames = mdh->numFrames;
retModel->tags = (tag_t*)Z_Calloc(sizeof(tag_t) * retModel->numTags * mdh->numFrames, ztag);
md3Tag *mdTag = (md3Tag*)&buffer[mdh->offsetTags];
tag_t *curTag = retModel->tags;
for (i = 0; i < mdh->numFrames; i++)
{
int j;
for (j = 0; j < retModel->numTags; j++, mdTag++)
{
strcpys(curTag->name, mdTag->name, sizeof(curTag->name) / sizeof(char));
curTag->transform.m[0][0] = mdTag->axis[0];
curTag->transform.m[0][1] = mdTag->axis[1];
curTag->transform.m[0][2] = mdTag->axis[2];
curTag->transform.m[1][0] = mdTag->axis[3];
curTag->transform.m[1][1] = mdTag->axis[4];
curTag->transform.m[1][2] = mdTag->axis[5];
curTag->transform.m[2][0] = mdTag->axis[6];
curTag->transform.m[2][1] = mdTag->axis[7];
curTag->transform.m[2][2] = mdTag->axis[8];
curTag->transform.m[3][0] = mdTag->origin[0] * WUNITS;
curTag->transform.m[3][1] = mdTag->origin[1] * WUNITS;
curTag->transform.m[3][2] = mdTag->origin[2] * WUNITS;
curTag->transform.m[3][3] = 1.0f;
Matrix::Rotate(&curTag->transform, 90.0f, &Vector::Xaxis);
curTag++;
}
}*/
free(buffer);
return retModel;
}

19
src/hardware/hw_md3load.h Normal file
View file

@ -0,0 +1,19 @@
/*
From the 'Wizard2' engine by Spaddlewit Inc. ( http://www.spaddlewit.com )
An experimental work-in-progress.
Donated to Sonic Team Junior and adapted to work with
Sonic Robo Blast 2. The license of this code matches whatever
the licensing is for Sonic Robo Blast 2.
*/
#ifndef _HW_MD3LOAD_H_
#define _HW_MD3LOAD_H_
#include "hw_model.h"
#include "../doomtype.h"
// Load the Model
model_t *MD3_LoadModel(const char *fileName, int ztag, boolean useFloat);
#endif

737
src/hardware/hw_model.c Normal file
View file

@ -0,0 +1,737 @@
/*
From the 'Wizard2' engine by Spaddlewit Inc. ( http://www.spaddlewit.com )
An experimental work-in-progress.
Donated to Sonic Team Junior and adapted to work with
Sonic Robo Blast 2. The license of this code matches whatever
the licensing is for Sonic Robo Blast 2.
*/
#include "../doomdef.h"
#include "../doomtype.h"
#include "../info.h"
#include "../z_zone.h"
#include "hw_model.h"
#include "hw_md2load.h"
#include "hw_md3load.h"
#include "hw_md2.h"
#include "u_list.h"
#include <string.h>
static float PI = (3.1415926535897932384626433832795f);
static float U_Deg2Rad(float deg)
{
return deg * ((float)PI / 180.0f);
}
vector_t vectorXaxis = { 1.0f, 0.0f, 0.0f };
vector_t vectorYaxis = { 0.0f, 1.0f, 0.0f };
vector_t vectorZaxis = { 0.0f, 0.0f, 1.0f };
void VectorRotate(vector_t *rotVec, const vector_t *axisVec, float angle)
{
float ux, uy, uz, vx, vy, vz, wx, wy, wz, sa, ca;
angle = U_Deg2Rad(angle);
// Rotate the point (x,y,z) around the vector (u,v,w)
ux = axisVec->x * rotVec->x;
uy = axisVec->x * rotVec->y;
uz = axisVec->x * rotVec->z;
vx = axisVec->y * rotVec->x;
vy = axisVec->y * rotVec->y;
vz = axisVec->y * rotVec->z;
wx = axisVec->z * rotVec->x;
wy = axisVec->z * rotVec->y;
wz = axisVec->z * rotVec->z;
sa = sinf(angle);
ca = cosf(angle);
rotVec->x = axisVec->x*(ux + vy + wz) + (rotVec->x*(axisVec->y*axisVec->y + axisVec->z*axisVec->z) - axisVec->x*(vy + wz))*ca + (-wy + vz)*sa;
rotVec->y = axisVec->y*(ux + vy + wz) + (rotVec->y*(axisVec->x*axisVec->x + axisVec->z*axisVec->z) - axisVec->y*(ux + wz))*ca + (wx - uz)*sa;
rotVec->z = axisVec->z*(ux + vy + wz) + (rotVec->z*(axisVec->x*axisVec->x + axisVec->y*axisVec->y) - axisVec->z*(ux + vy))*ca + (-vx + uy)*sa;
}
void UnloadModel(model_t *model)
{
// Wouldn't it be great if C just had destructors?
int i;
for (i = 0; i < model->numMeshes; i++)
{
mesh_t *mesh = &model->meshes[i];
if (mesh->frames)
{
int j;
for (j = 0; j < mesh->numFrames; j++)
{
if (mesh->frames[j].normals)
Z_Free(mesh->frames[j].normals);
if (mesh->frames[j].tangents)
Z_Free(mesh->frames[j].tangents);
if (mesh->frames[j].vertices)
Z_Free(mesh->frames[j].vertices);
if (mesh->frames[j].colors)
Z_Free(mesh->frames[j].colors);
}
Z_Free(mesh->frames);
}
else if (mesh->tinyframes)
{
int j;
for (j = 0; j < mesh->numFrames; j++)
{
if (mesh->tinyframes[j].normals)
Z_Free(mesh->tinyframes[j].normals);
if (mesh->tinyframes[j].tangents)
Z_Free(mesh->tinyframes[j].tangents);
if (mesh->tinyframes[j].vertices)
Z_Free(mesh->tinyframes[j].vertices);
}
if (mesh->indices)
Z_Free(mesh->indices);
Z_Free(mesh->tinyframes);
}
if (mesh->uvs)
Z_Free(mesh->uvs);
if (mesh->lightuvs)
Z_Free(mesh->lightuvs);
}
if (model->meshes)
Z_Free(model->meshes);
if (model->tags)
Z_Free(model->tags);
if (model->materials)
Z_Free(model->materials);
DeleteVBOs(model);
Z_Free(model);
}
tag_t *GetTagByName(model_t *model, char *name, int frame)
{
if (frame < model->maxNumFrames)
{
tag_t *iterator = &model->tags[frame * model->numTags];
int i;
for (i = 0; i < model->numTags; i++)
{
if (!stricmp(iterator[i].name, name))
return &iterator[i];
}
}
return NULL;
}
//
// LoadModel
//
// Load a model and
// convert it to the
// internal format.
//
model_t *LoadModel(const char *filename, int ztag)
{
model_t *model;
// What type of file?
const char *extension = NULL;
int i;
for (i = (int)strlen(filename)-1; i >= 0; i--)
{
if (filename[i] != '.')
continue;
extension = &filename[i];
break;
}
if (!extension)
{
CONS_Printf("Model %s is lacking a file extension, unable to determine type!\n", filename);
return NULL;
}
if (!strcmp(extension, ".md3"))
{
if (!(model = MD3_LoadModel(filename, ztag, false)))
return NULL;
}
else if (!strcmp(extension, ".md3s")) // MD3 that will be converted in memory to use full floats
{
if (!(model = MD3_LoadModel(filename, ztag, true)))
return NULL;
}
else if (!strcmp(extension, ".md2"))
{
if (!(model = MD2_LoadModel(filename, ztag, false)))
return NULL;
}
else if (!strcmp(extension, ".md2s"))
{
if (!(model = MD2_LoadModel(filename, ztag, true)))
return NULL;
}
else
{
CONS_Printf("Unknown model format: %s\n", extension);
return NULL;
}
model->mdlFilename = (char*)Z_Malloc(strlen(filename)+1, ztag, 0);
strcpy(model->mdlFilename, filename);
Optimize(model);
GeneratePolygonNormals(model, ztag);
LoadModelSprite2(model);
if (!model->spr2frames)
LoadModelInterpolationSettings(model);
// Default material properties
for (i = 0 ; i < model->numMaterials; i++)
{
material_t *material = &model->materials[i];
material->ambient[0] = 0.7686f;
material->ambient[1] = 0.7686f;
material->ambient[2] = 0.7686f;
material->ambient[3] = 1.0f;
material->diffuse[0] = 0.5863f;
material->diffuse[1] = 0.5863f;
material->diffuse[2] = 0.5863f;
material->diffuse[3] = 1.0f;
material->specular[0] = 0.4902f;
material->specular[1] = 0.4902f;
material->specular[2] = 0.4902f;
material->specular[3] = 1.0f;
material->shininess = 25.0f;
}
return model;
}
void HWR_ReloadModels(void)
{
size_t i;
INT32 s;
for (s = 0; s < MAXSKINS; s++)
{
if (md2_playermodels[s].model)
LoadModelSprite2(md2_playermodels[s].model);
}
for (i = 0; i < NUMSPRITES; i++)
{
if (md2_models[i].model)
LoadModelInterpolationSettings(md2_models[i].model);
}
}
void LoadModelInterpolationSettings(model_t *model)
{
INT32 i;
INT32 numframes = model->meshes[0].numFrames;
char *framename = model->framenames;
if (!framename)
return;
#define GET_OFFSET \
memcpy(&interpolation_flag, framename + offset, 2); \
model->interpolate[i] = (!memcmp(interpolation_flag, MODEL_INTERPOLATION_FLAG, 2));
for (i = 0; i < numframes; i++)
{
int offset = (strlen(framename) - 4);
char interpolation_flag[3];
memset(&interpolation_flag, 0x00, 3);
// find the +i on the frame name
// ANIM+i00
// so the offset is (frame name length - 4)
GET_OFFSET;
// maybe the frame had three digits?
// ANIM+i000
// so the offset is (frame name length - 5)
if (!model->interpolate[i])
{
offset--;
GET_OFFSET;
}
framename += 16;
}
#undef GET_OFFSET
}
void LoadModelSprite2(model_t *model)
{
INT32 i;
modelspr2frames_t *spr2frames = NULL;
INT32 numframes = model->meshes[0].numFrames;
char *framename = model->framenames;
if (!framename)
return;
for (i = 0; i < numframes; i++)
{
char prefix[6];
char name[5];
char interpolation_flag[3];
char framechars[4];
UINT8 frame = 0;
UINT8 spr2idx;
boolean interpolate = false;
memset(&prefix, 0x00, 6);
memset(&name, 0x00, 5);
memset(&interpolation_flag, 0x00, 3);
memset(&framechars, 0x00, 4);
if (strlen(framename) >= 9)
{
boolean super;
char *modelframename = framename;
memcpy(&prefix, modelframename, 5);
modelframename += 5;
memcpy(&name, modelframename, 4);
modelframename += 4;
// Oh look
memcpy(&interpolation_flag, modelframename, 2);
if (!memcmp(interpolation_flag, MODEL_INTERPOLATION_FLAG, 2))
{
interpolate = true;
modelframename += 2;
}
memcpy(&framechars, modelframename, 3);
if ((super = (!memcmp(prefix, "SUPER", 5))) || (!memcmp(prefix, "SPR2_", 5)))
{
spr2idx = 0;
while (spr2idx < free_spr2)
{
if (!memcmp(spr2names[spr2idx], name, 4))
{
if (!spr2frames)
spr2frames = (modelspr2frames_t*)Z_Calloc(sizeof(modelspr2frames_t)*NUMPLAYERSPRITES*2, PU_STATIC, NULL);
if (super)
spr2idx |= FF_SPR2SUPER;
if (framechars[0])
{
frame = atoi(framechars);
if (spr2frames[spr2idx].numframes < frame+1)
spr2frames[spr2idx].numframes = frame+1;
}
else
{
frame = spr2frames[spr2idx].numframes;
spr2frames[spr2idx].numframes++;
}
spr2frames[spr2idx].frames[frame] = i;
spr2frames[spr2idx].interpolate = interpolate;
break;
}
spr2idx++;
}
}
}
framename += 16;
}
if (model->spr2frames)
Z_Free(model->spr2frames);
model->spr2frames = spr2frames;
}
//
// GenerateVertexNormals
//
// Creates a new normal for a vertex using the average of all of the polygons it belongs to.
//
void GenerateVertexNormals(model_t *model)
{
int i;
for (i = 0; i < model->numMeshes; i++)
{
int j;
mesh_t *mesh = &model->meshes[i];
if (!mesh->frames)
continue;
for (j = 0; j < mesh->numFrames; j++)
{
mdlframe_t *frame = &mesh->frames[j];
int memTag = PU_STATIC;
float *newNormals = (float*)Z_Malloc(sizeof(float)*3*mesh->numTriangles*3, memTag, 0);
int k;
float *vertPtr = frame->vertices;
float *oldNormals;
M_Memcpy(newNormals, frame->normals, sizeof(float)*3*mesh->numTriangles*3);
/* if (!systemSucks)
{
memTag = Z_GetTag(frame->tangents);
float *newTangents = (float*)Z_Malloc(sizeof(float)*3*mesh->numTriangles*3, memTag);
M_Memcpy(newTangents, frame->tangents, sizeof(float)*3*mesh->numTriangles*3);
}*/
for (k = 0; k < mesh->numVertices; k++)
{
float x, y, z;
int vCount = 0;
vector_t normal;
int l;
float *testPtr = frame->vertices;
x = *vertPtr++;
y = *vertPtr++;
z = *vertPtr++;
normal.x = normal.y = normal.z = 0;
for (l = 0; l < mesh->numVertices; l++)
{
float testX, testY, testZ;
testX = *testPtr++;
testY = *testPtr++;
testZ = *testPtr++;
if (fabsf(x - testX) > FLT_EPSILON
|| fabsf(y - testY) > FLT_EPSILON
|| fabsf(z - testZ) > FLT_EPSILON)
continue;
// Found a vertex match! Add it...
normal.x += frame->normals[3 * l + 0];
normal.y += frame->normals[3 * l + 1];
normal.z += frame->normals[3 * l + 2];
vCount++;
}
if (vCount > 1)
{
// Vector::Normalize(&normal);
newNormals[3 * k + 0] = (float)normal.x;
newNormals[3 * k + 1] = (float)normal.y;
newNormals[3 * k + 2] = (float)normal.z;
/* if (!systemSucks)
{
Vector::vector_t tangent;
Vector::Tangent(&normal, &tangent);
newTangents[3 * k + 0] = tangent.x;
newTangents[3 * k + 1] = tangent.y;
newTangents[3 * k + 2] = tangent.z;
}*/
}
}
oldNormals = frame->normals;
frame->normals = newNormals;
Z_Free(oldNormals);
/* if (!systemSucks)
{
float *oldTangents = frame->tangents;
frame->tangents = newTangents;
Z_Free(oldTangents);
}*/
}
}
}
typedef struct materiallist_s
{
struct materiallist_s *next;
struct materiallist_s *prev;
material_t *material;
} materiallist_t;
static boolean AddMaterialToList(materiallist_t **head, material_t *material)
{
materiallist_t *node, *newMatNode;
for (node = *head; node; node = node->next)
{
if (node->material == material)
return false;
}
// Didn't find it, so add to the list
newMatNode = (materiallist_t*)Z_Malloc(sizeof(materiallist_t), PU_CACHE, 0);
newMatNode->material = material;
ListAdd(newMatNode, (listitem_t**)head);
return true;
}
//
// Optimize
//
// Groups triangles from meshes in the model
// Only works for models with 1 frame
//
void Optimize(model_t *model)
{
int numMeshes = 0;
int i;
materiallist_t *matListHead = NULL;
int memTag;
mesh_t *newMeshes;
materiallist_t *node;
if (model->numMeshes <= 1)
return; // No need
for (i = 0; i < model->numMeshes; i++)
{
mesh_t *curMesh = &model->meshes[i];
if (curMesh->numFrames > 1)
return; // Can't optimize models with > 1 frame
if (!curMesh->frames)
return; // Don't optimize tinyframe models (no need)
// We are condensing to 1 mesh per material, so
// the # of materials we use will be the new
// # of meshes
if (AddMaterialToList(&matListHead, curMesh->frames[0].material))
numMeshes++;
}
memTag = PU_STATIC;
newMeshes = (mesh_t*)Z_Calloc(sizeof(mesh_t) * numMeshes, memTag, 0);
i = 0;
for (node = matListHead; node; node = node->next)
{
material_t *curMat = node->material;
mesh_t *newMesh = &newMeshes[i];
mdlframe_t *curFrame;
int uvCount;
int vertCount;
int colorCount;
// Find all triangles with this material and count them
int numTriangles = 0;
int j;
for (j = 0; j < model->numMeshes; j++)
{
mesh_t *curMesh = &model->meshes[j];
if (curMesh->frames[0].material == curMat)
numTriangles += curMesh->numTriangles;
}
newMesh->numFrames = 1;
newMesh->numTriangles = numTriangles;
newMesh->numVertices = numTriangles * 3;
newMesh->uvs = (float*)Z_Malloc(sizeof(float)*2*numTriangles*3, memTag, 0);
// if (node->material->lightmap)
// newMesh->lightuvs = (float*)Z_Malloc(sizeof(float)*2*numTriangles*3, memTag, 0);
newMesh->frames = (mdlframe_t*)Z_Calloc(sizeof(mdlframe_t), memTag, 0);
curFrame = &newMesh->frames[0];
curFrame->material = curMat;
curFrame->normals = (float*)Z_Malloc(sizeof(float)*3*numTriangles*3, memTag, 0);
// if (!systemSucks)
// curFrame->tangents = (float*)Z_Malloc(sizeof(float)*3*numTriangles*3, memTag, 0);
curFrame->vertices = (float*)Z_Malloc(sizeof(float)*3*numTriangles*3, memTag, 0);
curFrame->colors = (char*)Z_Malloc(sizeof(char)*4*numTriangles*3, memTag, 0);
// Now traverse the meshes of the model, adding in
// vertices/normals/uvs that match the current material
uvCount = 0;
vertCount = 0;
colorCount = 0;
for (j = 0; j < model->numMeshes; j++)
{
mesh_t *curMesh = &model->meshes[j];
if (curMesh->frames[0].material == curMat)
{
float *dest;
float *src;
char *destByte;
char *srcByte;
M_Memcpy(&newMesh->uvs[uvCount],
curMesh->uvs,
sizeof(float)*2*curMesh->numTriangles*3);
/* if (node->material->lightmap)
{
M_Memcpy(&newMesh->lightuvs[uvCount],
curMesh->lightuvs,
sizeof(float)*2*curMesh->numTriangles*3);
}*/
uvCount += 2*curMesh->numTriangles*3;
dest = (float*)newMesh->frames[0].vertices;
src = (float*)curMesh->frames[0].vertices;
M_Memcpy(&dest[vertCount],
src,
sizeof(float)*3*curMesh->numTriangles*3);
dest = (float*)newMesh->frames[0].normals;
src = (float*)curMesh->frames[0].normals;
M_Memcpy(&dest[vertCount],
src,
sizeof(float)*3*curMesh->numTriangles*3);
/* if (!systemSucks)
{
dest = (float*)newMesh->frames[0].tangents;
src = (float*)curMesh->frames[0].tangents;
M_Memcpy(&dest[vertCount],
src,
sizeof(float)*3*curMesh->numTriangles*3);
}*/
vertCount += 3 * curMesh->numTriangles * 3;
destByte = (char*)newMesh->frames[0].colors;
srcByte = (char*)curMesh->frames[0].colors;
if (srcByte)
{
M_Memcpy(&destByte[colorCount],
srcByte,
sizeof(char)*4*curMesh->numTriangles*3);
}
else
{
memset(&destByte[colorCount],
255,
sizeof(char)*4*curMesh->numTriangles*3);
}
colorCount += 4 * curMesh->numTriangles * 3;
}
}
i++;
}
CONS_Printf("Model::Optimize(): Model reduced from %d to %d meshes.\n", model->numMeshes, numMeshes);
model->meshes = newMeshes;
model->numMeshes = numMeshes;
}
void GeneratePolygonNormals(model_t *model, int ztag)
{
int i;
for (i = 0; i < model->numMeshes; i++)
{
int j;
mesh_t *mesh = &model->meshes[i];
if (!mesh->frames)
continue;
for (j = 0; j < mesh->numFrames; j++)
{
int k;
mdlframe_t *frame = &mesh->frames[j];
const float *vertices = frame->vertices;
vector_t *polyNormals;
frame->polyNormals = (vector_t*)Z_Malloc(sizeof(vector_t) * mesh->numTriangles, ztag, 0);
polyNormals = frame->polyNormals;
for (k = 0; k < mesh->numTriangles; k++)
{
// Vector::Normal(vertices, polyNormals);
vertices += 3 * 3;
polyNormals++;
}
}
}
}
//
// Reload
//
// Reload VBOs
//
#if 0
static void Reload(void)
{
/* model_t *node;
for (node = modelHead; node; node = node->next)
{
int i;
for (i = 0; i < node->numMeshes; i++)
{
mesh_t *mesh = &node->meshes[i];
if (mesh->frames)
{
int j;
for (j = 0; j < mesh->numFrames; j++)
CreateVBO(mesh, &mesh->frames[j]);
}
else if (mesh->tinyframes)
{
int j;
for (j = 0; j < mesh->numFrames; j++)
CreateVBO(mesh, &mesh->tinyframes[j]);
}
}
}*/
}
#endif
void DeleteVBOs(model_t *model)
{
(void)model;
/* for (int i = 0; i < model->numMeshes; i++)
{
mesh_t *mesh = &model->meshes[i];
if (mesh->frames)
{
for (int j = 0; j < mesh->numFrames; j++)
{
mdlframe_t *frame = &mesh->frames[j];
if (!frame->vboID)
continue;
bglDeleteBuffers(1, &frame->vboID);
frame->vboID = 0;
}
}
else if (mesh->tinyframes)
{
for (int j = 0; j < mesh->numFrames; j++)
{
tinyframe_t *frame = &mesh->tinyframes[j];
if (!frame->vboID)
continue;
bglDeleteBuffers(1, &frame->vboID);
frame->vboID = 0;
}
}
}*/
}

121
src/hardware/hw_model.h Normal file
View file

@ -0,0 +1,121 @@
/*
From the 'Wizard2' engine by Spaddlewit Inc. ( http://www.spaddlewit.com )
An experimental work-in-progress.
Donated to Sonic Team Junior and adapted to work with
Sonic Robo Blast 2. The license of this code matches whatever
the licensing is for Sonic Robo Blast 2.
*/
#ifndef _HW_MODEL_H_
#define _HW_MODEL_H_
#include "../doomtype.h"
typedef struct
{
float x, y, z;
} vector_t;
extern vector_t vectorXaxis;
extern vector_t vectorYaxis;
extern vector_t vectorZaxis;
void VectorRotate(vector_t *rotVec, const vector_t *axisVec, float angle);
typedef struct
{
float ambient[4], diffuse[4], specular[4], emissive[4];
float shininess;
boolean spheremap;
// Texture::texture_t *texture;
// Texture::texture_t *lightmap;
} material_t;
typedef struct
{
material_t *material; // Pointer to the allocated 'materials' list in model_t
float *vertices;
float *normals;
float *tangents;
char *colors;
unsigned int vboID;
vector_t *polyNormals;
} mdlframe_t;
typedef struct
{
material_t *material;
short *vertices;
char *normals;
char *tangents;
unsigned int vboID;
} tinyframe_t;
// Equivalent to MD3's many 'surfaces'
typedef struct mesh_s
{
int numVertices;
int numTriangles;
float *uvs;
float *lightuvs;
int numFrames;
mdlframe_t *frames;
tinyframe_t *tinyframes;
unsigned short *indices;
} mesh_t;
typedef struct tag_s
{
char name[64];
// matrix_t transform;
} tag_t;
#define MODEL_INTERPOLATION_FLAG "+i"
typedef struct
{
INT32 frames[256];
UINT8 numframes;
boolean interpolate;
} modelspr2frames_t;
typedef struct model_s
{
int maxNumFrames;
int numMaterials;
material_t *materials;
int numMeshes;
mesh_t *meshes;
int numTags;
tag_t *tags;
char *mdlFilename;
boolean unloaded;
char *framenames;
boolean interpolate[256];
modelspr2frames_t *spr2frames;
} model_t;
extern int numModels;
extern model_t *modelHead;
void HWR_ReloadModels(void);
tag_t *GetTagByName(model_t *model, char *name, int frame);
model_t *LoadModel(const char *filename, int ztag);
void UnloadModel(model_t *model);
void Optimize(model_t *model);
void LoadModelInterpolationSettings(model_t *model);
void LoadModelSprite2(model_t *model);
void GenerateVertexNormals(model_t *model);
void GeneratePolygonNormals(model_t *model, int ztag);
void CreateVBOTiny(mesh_t *mesh, tinyframe_t *frame);
void CreateVBO(mesh_t *mesh, mdlframe_t *frame);
void DeleteVBOs(model_t *model);
#endif

View file

@ -347,13 +347,6 @@ static INT32 WINAPI SetRes(viddef_t *lvid, vmode_t *pcurrentmode)
if (strstr(renderer, "810")) oglflags |= GLF_NOZBUFREAD;
DBG_Printf("oglflags : 0x%X\n", oglflags);
#ifdef USE_PALETTED_TEXTURE
if (isExtAvailable("GL_EXT_paletted_texture",gl_extensions))
glColorTableEXT = GetGLFunc("glColorTableEXT");
else
glColorTableEXT = NULL;
#endif
#ifdef USE_WGL_SWAP
if (isExtAvailable("WGL_EXT_swap_control",gl_extensions))
wglSwapIntervalEXT = GetGLFunc("wglSwapIntervalEXT");
@ -582,19 +575,8 @@ EXPORT void HWRAPI(SetPalette) (RGBA_t *pal, RGBA_t *gamma)
myPaletteData[i].s.blue = (UINT8)MIN((pal[i].s.blue*gamma->s.blue)/127, 255);
myPaletteData[i].s.alpha = pal[i].s.alpha;
}
#ifdef USE_PALETTED_TEXTURE
if (glColorTableEXT)
{
for (i = 0; i < 256; i++)
{
palette_tex[3*i+0] = pal[i].s.red;
palette_tex[3*i+1] = pal[i].s.green;
palette_tex[3*i+2] = pal[i].s.blue;
}
glColorTableEXT(GL_TEXTURE_2D, GL_RGB8, 256, GL_RGB, GL_UNSIGNED_BYTE, palette_tex);
}
#endif
// on a chang<6E> de palette, il faut recharger toutes les textures
// on a palette change, you have to reload all of the textures
Flush();
}

File diff suppressed because it is too large Load diff

View file

@ -71,7 +71,6 @@ extern FILE *gllogstream;
#endif
#ifndef DRIVER_STRING
// #define USE_PALETTED_TEXTURE
#define DRIVER_STRING "HWRAPI Init(): SRB2 OpenGL renderer" // Tails
#endif
@ -89,10 +88,6 @@ int SetupPixelFormat(INT32 WantColorBits, INT32 WantStencilBits, INT32 WantDepth
void SetModelView(GLint w, GLint h);
void SetStates(void);
FUNCMATH float byteasfloat(UINT8 fbyte);
#ifdef USE_PALETTED_TEXTURE
extern PFNGLCOLORTABLEEXTPROC glColorTableEXT;
extern GLubyte palette_tex[256*3];
#endif
#ifndef GL_EXT_texture_filter_anisotropic
#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
@ -118,6 +113,10 @@ typedef void (APIENTRY * PFNglGetIntegerv) (GLenum pname, GLint *params);
extern PFNglGetIntegerv pglGetIntegerv;
typedef const GLubyte* (APIENTRY * PFNglGetString) (GLenum name);
extern PFNglGetString pglGetString;
#if 0
typedef void (APIENTRY * PFNglEnableClientState) (GLenum cap); // redefined in r_opengl.c
static PFNglEnableClientState pglEnableClientState;
#endif
#endif
// ==========================================================================

View file

@ -0,0 +1,52 @@
/*
From the 'Wizard2' engine by Spaddlewit Inc. ( http://www.spaddlewit.com )
An experimental work-in-progress.
Donated to Sonic Team Junior and adapted to work with
Sonic Robo Blast 2. The license of this code matches whatever
the licensing is for Sonic Robo Blast 2.
*/
#ifndef _R_VBO_H_
#define _R_VBO_H_
typedef struct
{
float x, y, z; // Vertex
float nx, ny, nz; // Normal
float s0, t0; // Texcoord0
} vbo32_t;
typedef struct
{
float x, y, z; // Vertex
float s0, t0; // Texcoord0
unsigned char r, g, b, a; // Color
float pad[2]; // Pad
} vbo2d32_t;
typedef struct
{
float x, y; // Vertex
float s0, t0; // Texcoord0
} vbofont_t;
typedef struct
{
short x, y, z; // Vertex
char nx, ny, nz; // Normal
char tanx, tany, tanz; // Tangent
float s0, t0; // Texcoord0
} vbotiny_t;
typedef struct
{
float x, y, z; // Vertex
float nx, ny, nz; // Normal
float s0, t0; // Texcoord0
float s1, t1; // Texcoord1
float s2, t2; // Texcoord2
float tan0, tan1, tan2; // Tangent
unsigned char r, g, b, a; // Color
} vbo64_t;
#endif

230
src/hardware/u_list.c Normal file
View file

@ -0,0 +1,230 @@
/*
From the 'Wizard2' engine by Spaddlewit Inc. ( http://www.spaddlewit.com )
An experimental work-in-progress.
Donated to Sonic Team Junior and adapted to work with
Sonic Robo Blast 2. The license of this code matches whatever
the licensing is for Sonic Robo Blast 2.
*/
#include "u_list.h"
#include "../z_zone.h"
// Utility for managing
// structures in a linked
// list.
//
// Struct must have "next" and "prev" pointers
// as its first two variables.
//
//
// ListAdd
//
// Adds an item to the list
//
void ListAdd(void *pItem, listitem_t **itemHead)
{
listitem_t *item = (listitem_t*)pItem;
if (*itemHead == NULL)
{
*itemHead = item;
(*itemHead)->prev = (*itemHead)->next = NULL;
}
else
{
listitem_t *tail;
tail = *itemHead;
while (tail->next != NULL)
tail = tail->next;
tail->next = item;
tail->next->prev = tail;
item->next = NULL;
}
}
//
// ListAddFront
//
// Adds an item to the front of the list
// (This is much faster)
//
void ListAddFront(void *pItem, listitem_t **itemHead)
{
listitem_t *item = (listitem_t*)pItem;
if (*itemHead == NULL)
{
*itemHead = item;
(*itemHead)->prev = (*itemHead)->next = NULL;
}
else
{
(*itemHead)->prev = item;
item->next = (*itemHead);
item->prev = NULL;
*itemHead = item;
}
}
//
// ListAddBefore
//
// Adds an item before the item specified in the list
//
void ListAddBefore(void *pItem, void *pSpot, listitem_t **itemHead)
{
listitem_t *item = (listitem_t*)pItem;
listitem_t *spot = (listitem_t*)pSpot;
listitem_t *prev = spot->prev;
if (!prev)
ListAddFront(pItem, itemHead);
else
{
item->next = spot;
spot->prev = item;
item->prev = prev;
prev->next = item;
}
}
//
// ListAddAfter
//
// Adds an item after the item specified in the list
//
void ListAddAfter(void *pItem, void *pSpot, listitem_t **itemHead)
{
listitem_t *item = (listitem_t*)pItem;
listitem_t *spot = (listitem_t*)pSpot;
listitem_t *next = spot->next;
if (!next)
ListAdd(pItem, itemHead);
else
{
item->prev = spot;
spot->next = item;
item->next = next;
next->prev = item;
}
}
//
// ListRemove
//
// Take an item out of the list and free its memory.
//
void ListRemove(void *pItem, listitem_t **itemHead)
{
listitem_t *item = (listitem_t*)pItem;
if (item == *itemHead) // Start of list
{
*itemHead = item->next;
if (*itemHead)
(*itemHead)->prev = NULL;
}
else if (item->next == NULL) // end of list
{
item->prev->next = NULL;
}
else // Somewhere in between
{
item->prev->next = item->next;
item->next->prev = item->prev;
}
Z_Free (item);
}
//
// ListRemoveAll
//
// Removes all items from the list, freeing their memory.
//
void ListRemoveAll(listitem_t **itemHead)
{
listitem_t *item;
listitem_t *next;
for (item = *itemHead; item; item = next)
{
next = item->next;
ListRemove(item, itemHead);
}
}
//
// ListRemoveNoFree
//
// Take an item out of the list, but don't free its memory.
//
void ListRemoveNoFree(void *pItem, listitem_t **itemHead)
{
listitem_t *item = (listitem_t*)pItem;
if (item == *itemHead) // Start of list
{
*itemHead = item->next;
if (*itemHead)
(*itemHead)->prev = NULL;
}
else if (item->next == NULL) // end of list
{
item->prev->next = NULL;
}
else // Somewhere in between
{
item->prev->next = item->next;
item->next->prev = item->prev;
}
}
//
// ListGetCount
//
// Counts the # of items in a list
// Should not be used in performance-minded code
//
unsigned int ListGetCount(void *itemHead)
{
listitem_t *item = (listitem_t*)itemHead;
unsigned int count = 0;
for (; item; item = item->next)
count++;
return count;
}
//
// ListGetByIndex
//
// Gets an item in the list by its index
// Should not be used in performance-minded code
//
listitem_t *ListGetByIndex(void *itemHead, unsigned int index)
{
listitem_t *head = (listitem_t*)itemHead;
unsigned int count = 0;
listitem_t *node;
for (node = head; node; node = node->next)
{
if (count == index)
return node;
count++;
}
return NULL;
}

29
src/hardware/u_list.h Normal file
View file

@ -0,0 +1,29 @@
/*
From the 'Wizard2' engine by Spaddlewit Inc. ( http://www.spaddlewit.com )
An experimental work-in-progress.
Donated to Sonic Team Junior and adapted to work with
Sonic Robo Blast 2. The license of this code matches whatever
the licensing is for Sonic Robo Blast 2.
*/
#ifndef _U_LIST_H_
#define _U_LIST_H_
typedef struct listitem_s
{
struct listitem_s *next;
struct listitem_s *prev;
} listitem_t;
void ListAdd(void *pItem, listitem_t **itemHead);
void ListAddFront(void *pItem, listitem_t **itemHead);
void ListAddBefore(void *pItem, void *pSpot, listitem_t **itemHead);
void ListAddAfter(void *pItem, void *pSpot, listitem_t **itemHead);
void ListRemove(void *pItem, listitem_t **itemHead);
void ListRemoveAll(listitem_t **itemHead);
void ListRemoveNoFree(void *pItem, listitem_t **itemHead);
unsigned int ListGetCount(void *itemHead);
listitem_t *ListGetByIndex(void *itemHead, unsigned int index);
#endif

View file

@ -1800,38 +1800,24 @@ state_t states[NUMSTATES] =
{SPR_NULL, 0, 1, {A_BossScream}, 0, 0, S_CYBRAKDEMONVILEEXPLOSION1}, //S_CYBRAKDEMONVILEEXPLOSION3,
// Metal Sonic
{SPR_METL, 0, 35, {NULL}, 0, 0, S_METALSONIC_WAIT1}, // S_METALSONIC_STAND
{SPR_METL, 1, 8, {NULL}, 0, 0, S_METALSONIC_WAIT2}, // S_METALSONIC_WAIT1
{SPR_METL, 2, 8, {NULL}, 0, 0, S_METALSONIC_WAIT1}, // S_METALSONIC_WAIT2
{SPR_METL, 3, 4, {NULL}, 0, 0, S_METALSONIC_WALK2}, // S_METALSONIC_WALK1
{SPR_METL, 4, 4, {NULL}, 0, 0, S_METALSONIC_WALK3}, // S_METALSONIC_WALK2
{SPR_METL, 5, 4, {NULL}, 0, 0, S_METALSONIC_WALK4}, // S_METALSONIC_WALK3
{SPR_METL, 6, 4, {NULL}, 0, 0, S_METALSONIC_WALK5}, // S_METALSONIC_WALK4
{SPR_METL, 7, 4, {NULL}, 0, 0, S_METALSONIC_WALK6}, // S_METALSONIC_WALK5
{SPR_METL, 6, 4, {NULL}, 0, 0, S_METALSONIC_WALK7}, // S_METALSONIC_WALK6
{SPR_METL, 5, 4, {NULL}, 0, 0, S_METALSONIC_WALK8}, // S_METALSONIC_WALK7
{SPR_METL, 4, 4, {NULL}, 0, 0, S_METALSONIC_WALK1}, // S_METALSONIC_WALK8
{SPR_METL, 8, 2, {NULL}, 0, 0, S_METALSONIC_RUN2}, // S_METALSONIC_RUN1
{SPR_METL, 9, 2, {NULL}, 0, 0, S_METALSONIC_RUN3}, // S_METALSONIC_RUN2
{SPR_METL, 10, 2, {NULL}, 0, 0, S_METALSONIC_RUN4}, // S_METALSONIC_RUN3
{SPR_METL, 9, 2, {NULL}, 0, 0, S_METALSONIC_RUN1}, // S_METALSONIC_RUN4
{SPR_PLAY, SPR2_STND, -1, {NULL}, 0, 0, S_METALSONIC_RACE}, // S_METALSONIC_RACE
{SPR_METL, 4, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_FLOAT
{SPR_METL, 12|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_METALSONIC_STUN}, // S_METALSONIC_VECTOR
{SPR_METL, 11, -1, {NULL}, 0, 0, S_METALSONIC_FLOAT}, // S_METALSONIC_STUN
{SPR_METL, 13, 20, {NULL}, 0, 0, S_METALSONIC_GATHER},// S_METALSONIC_RAISE
{SPR_METL, 14, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_GATHER
{SPR_METL, 15, -1, {NULL}, 0, 0, S_METALSONIC_BOUNCE},// S_METALSONIC_DASH
{SPR_METL, 14, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_BOUNCE
{SPR_METL, 16, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_BADBOUNCE
{SPR_METL, 13, -1, {NULL}, 0, 0, S_METALSONIC_GATHER},// S_METALSONIC_SHOOT
{SPR_METL, 11, 40, {A_Pain}, 0, 0, S_METALSONIC_FLOAT}, // S_METALSONIC_PAIN
{SPR_METL, 13, 2, {A_Fall}, 0, 0, S_METALSONIC_DEATH2},// S_METALSONIC_DEATH1
{SPR_METL, 13, 4, {A_BossScream}, 0, 0, S_METALSONIC_DEATH3},// S_METALSONIC_DEATH2
{SPR_METL, 13, 0, {A_Repeat}, 17, S_METALSONIC_DEATH2, S_METALSONIC_DEATH4}, // S_METALSONIC_DEATH3
{SPR_METL, 13, -1, {A_BossDeath}, 0, 0, S_NULL}, // S_METALSONIC_DEATH4
{SPR_METL, 11, 1, {A_BossScream}, 0, 0, S_METALSONIC_FLEE2}, // S_METALSONIC_FLEE1
{SPR_METL, 11, 7, {NULL}, 0, 0, S_METALSONIC_FLEE1}, // S_METALSONIC_FLEE2
{SPR_METL, 16|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_METALSONIC_STUN}, // S_METALSONIC_VECTOR
{SPR_METL, 15, -1, {NULL}, 0, 0, S_METALSONIC_FLOAT}, // S_METALSONIC_STUN
{SPR_METL, 17, 20, {NULL}, 0, 0, S_METALSONIC_GATHER},// S_METALSONIC_RAISE
{SPR_METL, 18, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_GATHER
{SPR_METL, 6|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 1, 2, S_METALSONIC_BOUNCE},// S_METALSONIC_DASH
{SPR_METL, 18|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 1, 2, S_NULL}, // S_METALSONIC_BOUNCE
{SPR_METL, 14, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_BADBOUNCE
{SPR_METL, 17, -1, {NULL}, 0, 0, S_METALSONIC_GATHER},// S_METALSONIC_SHOOT
{SPR_METL, 15, 40, {A_Pain}, 0, 0, S_METALSONIC_FLOAT}, // S_METALSONIC_PAIN
{SPR_METL, 17, 2, {A_Fall}, 0, 0, S_METALSONIC_DEATH2},// S_METALSONIC_DEATH1
{SPR_METL, 17, 4, {A_BossScream}, 0, 0, S_METALSONIC_DEATH3},// S_METALSONIC_DEATH2
{SPR_METL, 17, 0, {A_Repeat}, 17, S_METALSONIC_DEATH2, S_METALSONIC_DEATH4}, // S_METALSONIC_DEATH3
{SPR_METL, 17, -1, {A_BossDeath}, 0, 0, S_NULL}, // S_METALSONIC_DEATH4
{SPR_METL, 15, 1, {A_BossScream}, 0, 0, S_METALSONIC_FLEE2}, // S_METALSONIC_FLEE1
{SPR_METL, 15, 7, {NULL}, 0, 0, S_METALSONIC_FLEE1}, // S_METALSONIC_FLEE2
{SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30|FF_ANIMATE, -1, {NULL}, 11, 1, S_NULL}, // S_MSSHIELD_F1
{SPR_MSCF, FF_FULLBRIGHT|FF_ANIMATE|12, -1, {NULL}, 8, 2, S_NULL}, // S_MSSHIELD_F2
@ -2542,32 +2528,38 @@ state_t states[NUMSTATES] =
{SPR_WVIN, FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_WALLVINE_LONG
{SPR_WVIN, 1|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_WALLVINE_SHORT
// Trapgoyles
{SPR_BGAR, 0, 67, {NULL}, 0, 0, S_TRAPGOYLE_CHECK}, // S_TRAPGOYLE
{SPR_BGAR, 0, 3, {NULL}, 0, 0, S_TRAPGOYLE_FIRE1}, // S_TRAPGOYLE_CHECK
{SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16), S_TRAPGOYLE_FIRE2}, // S_TRAPGOYLE_FIRE1
{SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16), S_TRAPGOYLE_FIRE3}, // S_TRAPGOYLE_FIRE2
{SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16), S_TRAPGOYLE}, // S_TRAPGOYLE_FIRE3
// Glaregoyles
{SPR_BGAR, 0, 22, {NULL}, 0, 0, S_GLAREGOYLE_CHARGE}, // S_GLAREGOYLE
{SPR_BGAR, 2, 6, {NULL}, 0, 0, S_GLAREGOYLE_BLINK}, // S_GLAREGOYLE_CHARGE
{SPR_BGAR, FF_ANIMATE|1, 18, {NULL}, 1, 3, S_GLAREGOYLE_HOLD}, // S_GLAREGOYLE_BLINK
{SPR_BGAR, 1, 9, {NULL}, 0, 0, S_GLAREGOYLE_FIRE}, // S_GLAREGOYLE_HOLD
{SPR_BGAR, 1, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16), S_GLAREGOYLE_LOOP}, // S_GLAREGOYLE_FIRE
{SPR_BGAR, 1, 0, {A_Repeat}, 3, S_GLAREGOYLE_FIRE, S_GLAREGOYLE_COOLDOWN}, // S_GLAREGOYLE_LOOP
{SPR_BGAR, FF_ANIMATE|1, 15, {NULL}, 1, 9, S_GLAREGOYLE}, // S_GLAREGOYLE_COOLDOWN
{SPR_BGAR, 0, 67, {NULL}, 0, 0, S_TRAPGOYLEUP_CHECK}, // S_TRAPGOYLEUP
{SPR_BGAR, 0, 3, {NULL}, 0, 0, S_TRAPGOYLEUP_FIRE1}, // S_TRAPGOYLEUP_CHECK
{SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16)+45, S_TRAPGOYLEUP_FIRE2}, // S_TRAPGOYLEUP_FIRE1
{SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16)+45, S_TRAPGOYLEUP_FIRE3}, // S_TRAPGOYLEUP_FIRE2
{SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16)+45, S_TRAPGOYLEUP}, // S_TRAPGOYLEUP_FIRE3
{SPR_BGAR, 0, 22, {NULL}, 0, 0, S_GLAREGOYLEUP_CHARGE}, // S_GLAREGOYLEUP
{SPR_BGAR, 2, 6, {NULL}, 0, 0, S_GLAREGOYLEUP_BLINK}, // S_GLAREGOYLEUP_CHARGE
{SPR_BGAR, FF_ANIMATE|1, 18, {NULL}, 1, 3, S_GLAREGOYLEUP_HOLD}, // S_GLAREGOYLEUP_BLINK
{SPR_BGAR, 1, 9, {NULL}, 0, 0, S_GLAREGOYLEUP_FIRE}, // S_GLAREGOYLEUP_HOLD
{SPR_BGAR, 1, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16)+45, S_GLAREGOYLEUP_LOOP}, // S_GLAREGOYLEUP_FIRE
{SPR_BGAR, 1, 0, {A_Repeat}, 3, S_GLAREGOYLEUP_FIRE, S_GLAREGOYLEUP_COOLDOWN}, // S_GLAREGOYLEUP_LOOP
{SPR_BGAR, FF_ANIMATE|1, 15, {NULL}, 1, 9, S_GLAREGOYLEUP}, // S_GLAREGOYLEUP_COOLDOWN
{SPR_BGAR, 0, 67, {NULL}, 0, 0, S_TRAPGOYLEDOWN_CHECK}, // S_TRAPGOYLEDOWN
{SPR_BGAR, 0, 3, {NULL}, 0, 0, S_TRAPGOYLEDOWN_FIRE1}, // S_TRAPGOYLEDOWN_CHECK
{SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16)+315, S_TRAPGOYLEDOWN_FIRE2}, // S_TRAPGOYLEDOWN_FIRE1
{SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16)+315, S_TRAPGOYLEDOWN_FIRE3}, // S_TRAPGOYLEDOWN_FIRE2
{SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16)+315, S_TRAPGOYLEDOWN}, // S_TRAPGOYLEDOWN_FIRE3
{SPR_BGAR, 0, 22, {NULL}, 0, 0, S_GLAREGOYLEDOWN_CHARGE}, // S_GLAREGOYLEDOWN
{SPR_BGAR, 2, 6, {NULL}, 0, 0, S_GLAREGOYLEDOWN_BLINK}, // S_GLAREGOYLEDOWN_CHARGE
{SPR_BGAR, FF_ANIMATE|1, 18, {NULL}, 1, 3, S_GLAREGOYLEDOWN_HOLD}, // S_GLAREGOYLEDOWN_BLINK
{SPR_BGAR, 1, 9, {NULL}, 0, 0, S_GLAREGOYLEDOWN_FIRE}, // S_GLAREGOYLEDOWN_HOLD
{SPR_BGAR, 1, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16)+315, S_GLAREGOYLEDOWN_LOOP}, // S_GLAREGOYLEDOWN_FIRE
{SPR_BGAR, 1, 0, {A_Repeat}, 3, S_GLAREGOYLEDOWN_FIRE, S_GLAREGOYLEDOWN_COOLDOWN}, // S_GLAREGOYLEDOWN_LOOP
{SPR_BGAR, FF_ANIMATE|1, 15, {NULL}, 1, 9, S_GLAREGOYLEDOWN}, // S_GLAREGOYLEDOWN_COOLDOWN
{SPR_BGAR, 0, 135, {NULL}, 0, 0, S_TRAPGOYLELONG_CHECK}, // S_TRAPGOYLELONG
{SPR_BGAR, 0, 3, {NULL}, 0, 0, S_TRAPGOYLELONG_FIRE1}, // S_TRAPGOYLELONG_CHECK
{SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16), S_TRAPGOYLELONG_FIRE2}, // S_TRAPGOYLELONG_FIRE1
{SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16), S_TRAPGOYLELONG_FIRE3}, // S_TRAPGOYLELONG_FIRE2
{SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16), S_TRAPGOYLELONG_FIRE4}, // S_TRAPGOYLELONG_FIRE3
{SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16), S_TRAPGOYLELONG_FIRE5}, // S_TRAPGOYLELONG_FIRE4
{SPR_BGAR, 0, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16), S_TRAPGOYLELONG}, // S_TRAPGOYLELONG_FIRE5
{SPR_BGAR, 0, 90, {NULL}, 0, 0, S_GLAREGOYLELONG_CHARGE}, // S_GLAREGOYLELONG
{SPR_BGAR, 2, 6, {NULL}, 0, 0, S_GLAREGOYLELONG_BLINK}, // S_GLAREGOYLELONG_CHARGE
{SPR_BGAR, FF_ANIMATE|1, 18, {NULL}, 1, 3, S_GLAREGOYLELONG_HOLD}, // S_GLAREGOYLELONG_BLINK
{SPR_BGAR, 1, 9, {NULL}, 0, 0, S_GLAREGOYLELONG_FIRE}, // S_GLAREGOYLELONG_HOLD
{SPR_BGAR, 1, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16), S_GLAREGOYLELONG_LOOP}, // S_GLAREGOYLELONG_FIRE
{SPR_BGAR, 1, 0, {A_Repeat}, 5, S_GLAREGOYLELONG_FIRE, S_GLAREGOYLELONG_COOLDOWN}, // S_GLAREGOYLELONG_LOOP
{SPR_BGAR, FF_ANIMATE|1, 15, {NULL}, 1, 9, S_GLAREGOYLELONG}, // S_GLAREGOYLELONG_COOLDOWN
// Target/Red Crystal
{SPR_RCRY, 0, -1, {NULL}, 0, 0, S_TARGET_IDLE}, // S_TARGET_IDLE
@ -2579,6 +2571,9 @@ state_t states[NUMSTATES] =
// Green flame
{SPR_CFLM, FF_FULLBRIGHT|FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 7, 3, S_GREENFLAME}, // S_GREENFLAME
// ATZ Blue Gargoyle
{SPR_BGAR, 3, -1, {NULL}, 0, 0, S_NULL}, // S_BLUEGARGOYLE
// Stalagmites
{SPR_STLG, 0, -1, {NULL}, 0, 0, S_NULL}, // S_STG0
{SPR_STLG, 1, -1, {NULL}, 0, 0, S_NULL}, // S_STG1
@ -3826,8 +3821,8 @@ state_t states[NUMSTATES] =
{SPR_BUMB, 5, 120, {NULL}, 0, 0, S_BUMBLEBORE_DIE}, // S_BUMBLEBORE_STUCK2
{SPR_BUMB, 5, 0, {A_CryingToMomma}, 0, 0, S_XPLD1}, // S_BUMBLEBORE_DIE
{SPR_BBUZ, 0, 2, {NULL}, 0, 0, S_BBUZZFLY2}, // S_BBUZZFLY1
{SPR_BBUZ, 1, 2, {NULL}, 0, 0, S_BBUZZFLY1}, // S_BBUZZFLY2
{SPR_BBUZ, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BUGGLEIDLE
{SPR_BBUZ, FF_ANIMATE, -1, {NULL}, 1, 2, S_NULL}, // S_BUGGLEFLY
{SPR_FMCE, 0, 20, {NULL}, 0, 0, S_SMASHSPIKE_EASE1}, // S_SMASHSPIKE_FLOAT
{SPR_FMCE, 0, 4, {A_ZThrust}, 4, (1<<16)|1, S_SMASHSPIKE_EASE2}, // S_SMASHSPIKE_EASE1
@ -6640,18 +6635,18 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
{ // MT_METALSONIC_RACE
207, // doomednum
S_METALSONIC_STAND, // spawnstate
S_METALSONIC_RACE, // spawnstate
8, // spawnhealth
S_METALSONIC_WALK1, // seestate
S_NULL, // seestate
sfx_None, // seesound
0, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_METALSONIC_RUN1, // meleestate
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_PLAY_DEAD, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
0, // speed
@ -6661,7 +6656,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
0, // mass
0, // damage
sfx_None, // activesound
MF_SCENERY|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags
MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate
},
@ -6711,7 +6706,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
0, // speed
32*FRACUNIT, // radius
52*FRACUNIT, // height
0, // display offset
1, // display offset
0, // mass
0, // damage
sfx_None, // activesound
@ -13544,9 +13539,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
{ // MT_TRAPGOYLE
{ // MT_GLAREGOYLE
1500, // doomednum
S_TRAPGOYLE, // spawnstate
S_GLAREGOYLE, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
@ -13571,9 +13566,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
{ // MT_TRAPGOYLEUP
{ // MT_GLAREGOYLEUP
1501, // doomednum
S_TRAPGOYLEUP, // spawnstate
S_GLAREGOYLEUP, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
@ -13598,9 +13593,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
{ // MT_TRAPGOYLEDOWN
{ // MT_GLAREGOYLEDOWN
1502, // doomednum
S_TRAPGOYLEDOWN,// spawnstate
S_GLAREGOYLEDOWN,// spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
@ -13625,9 +13620,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
{ // MT_TRAPGOYLELONG
{ // MT_GLAREGOYLELONG
1503, // doomednum
S_TRAPGOYLELONG,// spawnstate
S_GLAREGOYLELONG,// spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
@ -13706,6 +13701,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
{ // MT_BLUEGARGOYLE
1506, // doomednum
S_BLUEGARGOYLE, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
21*FRACUNIT, // speed
16*FRACUNIT, // radius
40*FRACUNIT, // height
0, // display offset
100, // mass
1, // damage
sfx_statu2, // activesound
MF_SLIDEME|MF_SOLID|MF_PUSHABLE, // flags
S_NULL // raisestate
},
{ // MT_STALAGMITE0
1900, // doomednum
S_STG0, // spawnstate
@ -20091,11 +20113,11 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
{ // MT_BUBBLEBUZZ
{ // MT_BUGGLE
124, // doomednum
S_BBUZZFLY1, // spawnstate
S_BUGGLEIDLE, // spawnstate
1, // spawnhealth
S_BBUZZFLY1, // seestate
S_BUGGLEFLY, // seestate
sfx_None, // seesound
2, // reactiontime
sfx_None, // attacksound

View file

@ -1939,25 +1939,7 @@ typedef enum state
S_CYBRAKDEMONVILEEXPLOSION3,
// Metal Sonic (Race)
// S_PLAY_STND
S_METALSONIC_STAND,
// S_PLAY_TAP1
S_METALSONIC_WAIT1,
S_METALSONIC_WAIT2,
// S_PLAY_WALK
S_METALSONIC_WALK1,
S_METALSONIC_WALK2,
S_METALSONIC_WALK3,
S_METALSONIC_WALK4,
S_METALSONIC_WALK5,
S_METALSONIC_WALK6,
S_METALSONIC_WALK7,
S_METALSONIC_WALK8,
// S_PLAY_SPD1
S_METALSONIC_RUN1,
S_METALSONIC_RUN2,
S_METALSONIC_RUN3,
S_METALSONIC_RUN4,
S_METALSONIC_RACE,
// Metal Sonic (Battle)
S_METALSONIC_FLOAT,
S_METALSONIC_VECTOR,
@ -2300,7 +2282,7 @@ typedef enum state
S_ARROW,
S_ARROWBONK,
// Trapgoyle Demon fire
// Glaregoyle Demon fire
S_DEMONFIRE,
// GFZ flowers
@ -2668,29 +2650,35 @@ typedef enum state
S_WALLVINE_LONG,
S_WALLVINE_SHORT,
// Trapgoyles
S_TRAPGOYLE,
S_TRAPGOYLE_CHECK,
S_TRAPGOYLE_FIRE1,
S_TRAPGOYLE_FIRE2,
S_TRAPGOYLE_FIRE3,
S_TRAPGOYLEUP,
S_TRAPGOYLEUP_CHECK,
S_TRAPGOYLEUP_FIRE1,
S_TRAPGOYLEUP_FIRE2,
S_TRAPGOYLEUP_FIRE3,
S_TRAPGOYLEDOWN,
S_TRAPGOYLEDOWN_CHECK,
S_TRAPGOYLEDOWN_FIRE1,
S_TRAPGOYLEDOWN_FIRE2,
S_TRAPGOYLEDOWN_FIRE3,
S_TRAPGOYLELONG,
S_TRAPGOYLELONG_CHECK,
S_TRAPGOYLELONG_FIRE1,
S_TRAPGOYLELONG_FIRE2,
S_TRAPGOYLELONG_FIRE3,
S_TRAPGOYLELONG_FIRE4,
S_TRAPGOYLELONG_FIRE5,
// Glaregoyles
S_GLAREGOYLE,
S_GLAREGOYLE_CHARGE,
S_GLAREGOYLE_BLINK,
S_GLAREGOYLE_HOLD,
S_GLAREGOYLE_FIRE,
S_GLAREGOYLE_LOOP,
S_GLAREGOYLE_COOLDOWN,
S_GLAREGOYLEUP,
S_GLAREGOYLEUP_CHARGE,
S_GLAREGOYLEUP_BLINK,
S_GLAREGOYLEUP_HOLD,
S_GLAREGOYLEUP_FIRE,
S_GLAREGOYLEUP_LOOP,
S_GLAREGOYLEUP_COOLDOWN,
S_GLAREGOYLEDOWN,
S_GLAREGOYLEDOWN_CHARGE,
S_GLAREGOYLEDOWN_BLINK,
S_GLAREGOYLEDOWN_HOLD,
S_GLAREGOYLEDOWN_FIRE,
S_GLAREGOYLEDOWN_LOOP,
S_GLAREGOYLEDOWN_COOLDOWN,
S_GLAREGOYLELONG,
S_GLAREGOYLELONG_CHARGE,
S_GLAREGOYLELONG_BLINK,
S_GLAREGOYLELONG_HOLD,
S_GLAREGOYLELONG_FIRE,
S_GLAREGOYLELONG_LOOP,
S_GLAREGOYLELONG_COOLDOWN,
// ATZ's Red Crystal/Target
S_TARGET_IDLE,
@ -2702,6 +2690,9 @@ typedef enum state
// ATZ's green flame
S_GREENFLAME,
// ATZ Blue Gargoyle
S_BLUEGARGOYLE,
// Stalagmites
S_STG0,
S_STG1,
@ -3892,8 +3883,8 @@ typedef enum state
S_BUMBLEBORE_STUCK2,
S_BUMBLEBORE_DIE,
S_BBUZZFLY1,
S_BBUZZFLY2,
S_BUGGLEIDLE,
S_BUGGLEFLY,
S_SMASHSPIKE_FLOAT,
S_SMASHSPIKE_EASE1,
@ -4311,7 +4302,7 @@ typedef enum mobj_type
MT_CANNONBALL, // Cannonball
MT_CANNONBALLDECOR, // Decorative/still cannonball
MT_ARROW, // Arrow
MT_DEMONFIRE, // Trapgoyle fire
MT_DEMONFIRE, // Glaregoyle fire
// Greenflower Scenery
MT_GFZFLOWER1,
@ -4474,12 +4465,13 @@ typedef enum mobj_type
// Egg Rock Scenery
// Azure Temple Scenery
MT_TRAPGOYLE,
MT_TRAPGOYLEUP,
MT_TRAPGOYLEDOWN,
MT_TRAPGOYLELONG,
MT_GLAREGOYLE,
MT_GLAREGOYLEUP,
MT_GLAREGOYLEDOWN,
MT_GLAREGOYLELONG,
MT_TARGET, // AKA Red Crystal
MT_GREENFLAME,
MT_BLUEGARGOYLE,
// Stalagmites
MT_STALAGMITE0,
@ -4754,7 +4746,7 @@ typedef enum mobj_type
MT_HIVEELEMENTAL,
MT_BUMBLEBORE,
MT_BUBBLEBUZZ,
MT_BUGGLE,
MT_SMASHINGSPIKEBALL,
MT_CACOLANTERN,

View file

@ -56,7 +56,7 @@ fixed_t FixedDiv2(fixed_t a, fixed_t b)
if (b == 0)
I_Error("FixedDiv: divide by zero");
ret = (((INT64)a * FRACUNIT) ) / b;
ret = (((INT64)a * FRACUNIT)) / b;
if ((ret > INT32_MAX) || (ret < INT32_MIN))
I_Error("FixedDiv: divide by zero");
@ -117,7 +117,7 @@ fixed_t FixedHypot(fixed_t x, fixed_t y)
yx = FixedDiv(y, x); // (x/y)
}
yx2 = FixedMul(yx, yx); // (x/y)^2
yx1 = FixedSqrt(1*FRACUNIT + yx2); // (1 + (x/y)^2)^1/2
yx1 = FixedSqrt(1 * FRACUNIT + yx2); // (1 + (x/y)^2)^1/2
return FixedMul(ax, yx1); // |x|*((1 + (x/y)^2)^1/2)
}
@ -191,8 +191,8 @@ vector2_t *FV2_Divide(vector2_t *a_i, fixed_t a_c)
// Vector Complex Math
vector2_t *FV2_Midpoint(const vector2_t *a_1, const vector2_t *a_2, vector2_t *a_o)
{
a_o->x = FixedDiv(a_2->x - a_1->x, 2*FRACUNIT);
a_o->y = FixedDiv(a_2->y - a_1->y, 2*FRACUNIT);
a_o->x = FixedDiv(a_2->x - a_1->x, 2 * FRACUNIT);
a_o->y = FixedDiv(a_2->y - a_1->y, 2 * FRACUNIT);
a_o->x = a_1->x + a_o->x;
a_o->y = a_1->y + a_o->y;
return a_o;
@ -200,16 +200,16 @@ vector2_t *FV2_Midpoint(const vector2_t *a_1, const vector2_t *a_2, vector2_t *a
fixed_t FV2_Distance(const vector2_t *p1, const vector2_t *p2)
{
fixed_t xs = FixedMul(p2->x-p1->x,p2->x-p1->x);
fixed_t ys = FixedMul(p2->y-p1->y,p2->y-p1->y);
return FixedSqrt(xs+ys);
fixed_t xs = FixedMul(p2->x - p1->x, p2->x - p1->x);
fixed_t ys = FixedMul(p2->y - p1->y, p2->y - p1->y);
return FixedSqrt(xs + ys);
}
fixed_t FV2_Magnitude(const vector2_t *a_normal)
{
fixed_t xs = FixedMul(a_normal->x,a_normal->x);
fixed_t ys = FixedMul(a_normal->y,a_normal->y);
return FixedSqrt(xs+ys);
fixed_t xs = FixedMul(a_normal->x, a_normal->x);
fixed_t ys = FixedMul(a_normal->y, a_normal->y);
return FixedSqrt(xs + ys);
}
// Also returns the magnitude
@ -240,7 +240,7 @@ vector2_t *FV2_Negate(vector2_t *a_1)
boolean FV2_Equal(const vector2_t *a_1, const vector2_t *a_2)
{
fixed_t Epsilon = FRACUNIT/FRACUNIT;
fixed_t Epsilon = FRACUNIT / FRACUNIT;
if ((abs(a_2->x - a_1->x) > Epsilon) ||
(abs(a_2->y - a_1->y) > Epsilon))
@ -261,7 +261,7 @@ fixed_t FV2_Dot(const vector2_t *a_1, const vector2_t *a_2)
//
// Given two points, create a vector between them.
//
vector2_t *FV2_Point2Vec (const vector2_t *point1, const vector2_t *point2, vector2_t *a_o)
vector2_t *FV2_Point2Vec(const vector2_t *point1, const vector2_t *point2, vector2_t *a_o)
{
a_o->x = point1->x - point2->x;
a_o->y = point1->y - point2->y;
@ -344,9 +344,9 @@ vector3_t *FV3_Divide(vector3_t *a_i, fixed_t a_c)
// Vector Complex Math
vector3_t *FV3_Midpoint(const vector3_t *a_1, const vector3_t *a_2, vector3_t *a_o)
{
a_o->x = FixedDiv(a_2->x - a_1->x, 2*FRACUNIT);
a_o->y = FixedDiv(a_2->y - a_1->y, 2*FRACUNIT);
a_o->z = FixedDiv(a_2->z - a_1->z, 2*FRACUNIT);
a_o->x = FixedDiv(a_2->x - a_1->x, 2 * FRACUNIT);
a_o->y = FixedDiv(a_2->y - a_1->y, 2 * FRACUNIT);
a_o->z = FixedDiv(a_2->z - a_1->z, 2 * FRACUNIT);
a_o->x = a_1->x + a_o->x;
a_o->y = a_1->y + a_o->y;
a_o->z = a_1->z + a_o->z;
@ -355,18 +355,18 @@ vector3_t *FV3_Midpoint(const vector3_t *a_1, const vector3_t *a_2, vector3_t *a
fixed_t FV3_Distance(const vector3_t *p1, const vector3_t *p2)
{
fixed_t xs = FixedMul(p2->x-p1->x,p2->x-p1->x);
fixed_t ys = FixedMul(p2->y-p1->y,p2->y-p1->y);
fixed_t zs = FixedMul(p2->z-p1->z,p2->z-p1->z);
return FixedSqrt(xs+ys+zs);
fixed_t xs = FixedMul(p2->x - p1->x, p2->x - p1->x);
fixed_t ys = FixedMul(p2->y - p1->y, p2->y - p1->y);
fixed_t zs = FixedMul(p2->z - p1->z, p2->z - p1->z);
return FixedSqrt(xs + ys + zs);
}
fixed_t FV3_Magnitude(const vector3_t *a_normal)
{
fixed_t xs = FixedMul(a_normal->x,a_normal->x);
fixed_t ys = FixedMul(a_normal->y,a_normal->y);
fixed_t zs = FixedMul(a_normal->z,a_normal->z);
return FixedSqrt(xs+ys+zs);
fixed_t xs = FixedMul(a_normal->x, a_normal->x);
fixed_t ys = FixedMul(a_normal->y, a_normal->y);
fixed_t zs = FixedMul(a_normal->z, a_normal->z);
return FixedSqrt(xs + ys + zs);
}
// Also returns the magnitude
@ -399,7 +399,7 @@ vector3_t *FV3_Negate(vector3_t *a_1)
boolean FV3_Equal(const vector3_t *a_1, const vector3_t *a_2)
{
fixed_t Epsilon = FRACUNIT/FRACUNIT;
fixed_t Epsilon = FRACUNIT / FRACUNIT;
if ((abs(a_2->x - a_1->x) > Epsilon) ||
(abs(a_2->y - a_1->y) > Epsilon) ||
@ -458,6 +458,20 @@ vector3_t *FV3_ClosestPointOnLine(const vector3_t *Line, const vector3_t *p, vec
return FV3_AddEx(&Line[0], &V, out);
}
//
// ClosestPointOnVector
//
// Similar to ClosestPointOnLine, but uses a vector instead of two points.
//
void FV3_ClosestPointOnVector(const vector3_t *dir, const vector3_t *p, vector3_t *out)
{
fixed_t t = FV3_Dot(dir, p);
// Return the point on the line closest
FV3_MulEx(dir, t, out);
return;
}
//
// ClosestPointOnTriangle
//
@ -465,7 +479,7 @@ vector3_t *FV3_ClosestPointOnLine(const vector3_t *Line, const vector3_t *p, vec
// the closest point on the edge of
// the triangle is returned.
//
void FV3_ClosestPointOnTriangle (const vector3_t *tri, const vector3_t *point, vector3_t *result)
void FV3_ClosestPointOnTriangle(const vector3_t *tri, const vector3_t *point, vector3_t *result)
{
UINT8 i;
fixed_t dist, closestdist;
@ -506,7 +520,7 @@ void FV3_ClosestPointOnTriangle (const vector3_t *tri, const vector3_t *point, v
//
// Given two points, create a vector between them.
//
vector3_t *FV3_Point2Vec (const vector3_t *point1, const vector3_t *point2, vector3_t *a_o)
vector3_t *FV3_Point2Vec(const vector3_t *point1, const vector3_t *point2, vector3_t *a_o)
{
a_o->x = point1->x - point2->x;
a_o->y = point1->y - point2->y;
@ -519,7 +533,7 @@ vector3_t *FV3_Point2Vec (const vector3_t *point1, const vector3_t *point2, vect
//
// Calculates the normal of a polygon.
//
void FV3_Normal (const vector3_t *a_triangle, vector3_t *a_normal)
fixed_t FV3_Normal(const vector3_t *a_triangle, vector3_t *a_normal)
{
vector3_t a_1;
vector3_t a_2;
@ -529,7 +543,28 @@ void FV3_Normal (const vector3_t *a_triangle, vector3_t *a_normal)
FV3_Cross(&a_1, &a_2, a_normal);
FV3_NormalizeEx(a_normal, a_normal);
return FV3_NormalizeEx(a_normal, a_normal);
}
//
// Strength
//
// Measures the 'strength' of a vector in a particular direction.
//
fixed_t FV3_Strength(const vector3_t *a_1, const vector3_t *dir)
{
vector3_t normal;
fixed_t dist = FV3_NormalizeEx(a_1, &normal);
fixed_t dot = FV3_Dot(&normal, dir);
FV3_ClosestPointOnVector(dir, a_1, &normal);
dist = FV3_Magnitude(&normal);
if (dot < 0) // Not facing same direction, so negate result.
dist = -dist;
return dist;
}
//
@ -550,11 +585,11 @@ boolean FV3_IntersectedPlane(const vector3_t *a_triangle, const vector3_t *a_lin
*originDistance = FV3_PlaneDistance(a_normal, &a_triangle[0]);
distance1 = (FixedMul(a_normal->x, a_line[0].x) + FixedMul(a_normal->y, a_line[0].y)
+ FixedMul(a_normal->z, a_line[0].z)) + *originDistance;
distance1 = (FixedMul(a_normal->x, a_line[0].x) + FixedMul(a_normal->y, a_line[0].y)
+ FixedMul(a_normal->z, a_line[0].z)) + *originDistance;
distance2 = (FixedMul(a_normal->x, a_line[1].x) + FixedMul(a_normal->y, a_line[1].y)
+ FixedMul(a_normal->z, a_line[1].z)) + *originDistance;
distance2 = (FixedMul(a_normal->x, a_line[1].x) + FixedMul(a_normal->y, a_line[1].y)
+ FixedMul(a_normal->z, a_line[1].z)) + *originDistance;
// Positive or zero number means no intersection
if (FixedMul(distance1, distance2) >= 0)
@ -575,8 +610,8 @@ boolean FV3_IntersectedPlane(const vector3_t *a_triangle, const vector3_t *a_lin
fixed_t FV3_PlaneIntersection(const vector3_t *pOrigin, const vector3_t *pNormal, const vector3_t *rOrigin, const vector3_t *rVector)
{
fixed_t d = -(FV3_Dot(pNormal, pOrigin));
fixed_t number = FV3_Dot(pNormal,rOrigin) + d;
fixed_t denom = FV3_Dot(pNormal,rVector);
fixed_t number = FV3_Dot(pNormal, rOrigin) + d;
fixed_t denom = FV3_Dot(pNormal, rVector);
return -FixedDiv(number, denom);
}
@ -597,11 +632,11 @@ fixed_t FV3_IntersectRaySphere(const vector3_t *rO, const vector3_t *rV, const v
c = FV3_Magnitude(&Q);
v = FV3_Dot(&Q, rV);
d = FixedMul(sR, sR) - (FixedMul(c,c) - FixedMul(v,v));
d = FixedMul(sR, sR) - (FixedMul(c, c) - FixedMul(v, v));
// If there was no intersection, return -1
if (d < 0*FRACUNIT)
return (-1*FRACUNIT);
if (d < 0 * FRACUNIT)
return (-1 * FRACUNIT);
// Return the distance to the [first] intersecting point
return (v - FixedSqrt(d));
@ -629,9 +664,9 @@ vector3_t *FV3_IntersectionPoint(const vector3_t *vNormal, const vector3_t *vLin
// Here I just chose a arbitrary point as the point to find that distance. You notice we negate that
// distance. We negate the distance because we want to eventually go BACKWARDS from our point to the plane.
// By doing this is will basically bring us back to the plane to find our intersection point.
Numerator = - (FixedMul(vNormal->x, vLine[0].x) + // Use the plane equation with the normal and the line
FixedMul(vNormal->y, vLine[0].y) +
FixedMul(vNormal->z, vLine[0].z) + distance);
Numerator = -(FixedMul(vNormal->x, vLine[0].x) + // Use the plane equation with the normal and the line
FixedMul(vNormal->y, vLine[0].y) +
FixedMul(vNormal->z, vLine[0].z) + distance);
// 3) If we take the dot product between our line vector and the normal of the polygon,
// this will give us the cosine of the angle between the 2 (since they are both normalized - length 1).
@ -643,7 +678,7 @@ vector3_t *FV3_IntersectionPoint(const vector3_t *vNormal, const vector3_t *vLin
// on the plane (the normal is perpendicular to the line - (Normal.Vector = 0)).
// In this case, we should just return any point on the line.
if( Denominator == 0*FRACUNIT) // Check so we don't divide by zero
if (Denominator == 0 * FRACUNIT) // Check so we don't divide by zero
{
ReturnVec->x = vLine[0].x;
ReturnVec->y = vLine[0].y;
@ -686,8 +721,8 @@ vector3_t *FV3_IntersectionPoint(const vector3_t *vNormal, const vector3_t *vLin
//
UINT8 FV3_PointOnLineSide(const vector3_t *point, const vector3_t *line)
{
fixed_t s1 = FixedMul((point->y - line[0].y),(line[1].x - line[0].x));
fixed_t s2 = FixedMul((point->x - line[0].x),(line[1].y - line[0].y));
fixed_t s1 = FixedMul((point->y - line[0].y), (line[1].x - line[0].x));
fixed_t s2 = FixedMul((point->x - line[0].x), (line[1].y - line[0].y));
return (UINT8)(s1 - s2 < 0);
}
@ -752,7 +787,7 @@ void FM_CreateObjectMatrix(matrix_t *matrix, fixed_t x, fixed_t y, fixed_t z, fi
matrix->m[0] = upcross.x;
matrix->m[1] = upcross.y;
matrix->m[2] = upcross.z;
matrix->m[3] = 0*FRACUNIT;
matrix->m[3] = 0 * FRACUNIT;
matrix->m[4] = upx;
matrix->m[5] = upy;
@ -764,9 +799,9 @@ void FM_CreateObjectMatrix(matrix_t *matrix, fixed_t x, fixed_t y, fixed_t z, fi
matrix->m[10] = anglez;
matrix->m[11] = 0;
matrix->m[12] = x - FixedMul(upx,radius);
matrix->m[13] = y - FixedMul(upy,radius);
matrix->m[14] = z - FixedMul(upz,radius);
matrix->m[12] = x - FixedMul(upx, radius);
matrix->m[13] = y - FixedMul(upy, radius);
matrix->m[14] = z - FixedMul(upz, radius);
matrix->m[15] = FRACUNIT;
}
@ -778,20 +813,20 @@ void FM_CreateObjectMatrix(matrix_t *matrix, fixed_t x, fixed_t y, fixed_t z, fi
void FM_MultMatrixVec3(const matrix_t *matrix, const vector3_t *vec, vector3_t *out)
{
#define M(row,col) matrix->m[col * 4 + row]
out->x = FixedMul(vec->x,M(0, 0))
+ FixedMul(vec->y,M(0, 1))
+ FixedMul(vec->z,M(0, 2))
+ M(0, 3);
out->x = FixedMul(vec->x, M(0, 0))
+ FixedMul(vec->y, M(0, 1))
+ FixedMul(vec->z, M(0, 2))
+ M(0, 3);
out->y = FixedMul(vec->x,M(1, 0))
+ FixedMul(vec->y,M(1, 1))
+ FixedMul(vec->z,M(1, 2))
+ M(1, 3);
out->y = FixedMul(vec->x, M(1, 0))
+ FixedMul(vec->y, M(1, 1))
+ FixedMul(vec->z, M(1, 2))
+ M(1, 3);
out->z = FixedMul(vec->x,M(2, 0))
+ FixedMul(vec->y,M(2, 1))
+ FixedMul(vec->z,M(2, 2))
+ M(2, 3);
out->z = FixedMul(vec->x, M(2, 0))
+ FixedMul(vec->y, M(2, 1))
+ FixedMul(vec->z, M(2, 2))
+ M(2, 3);
#undef M
}
@ -811,7 +846,7 @@ void FM_MultMatrix(matrix_t *dest, const matrix_t *multme)
for (i = 0; i < 4; i++)
{
for (j = 0; j < 4; j++)
R(i, j) = FixedMul(D(i, 0),M(0, j)) + FixedMul(D(i, 1),M(1, j)) + FixedMul(D(i, 2),M(2, j)) + FixedMul(D(i, 3),M(3, j));
R(i, j) = FixedMul(D(i, 0), M(0, j)) + FixedMul(D(i, 1), M(1, j)) + FixedMul(D(i, 2), M(2, j)) + FixedMul(D(i, 3), M(3, j));
}
M_Memcpy(dest, &result, sizeof(matrix_t));
@ -869,8 +904,8 @@ void FM_Scale(matrix_t *dest, fixed_t x, fixed_t y, fixed_t z)
static inline void M_print(INT64 a)
{
const fixed_t w = (a>>FRACBITS);
fixed_t f = a%FRACUNIT;
const fixed_t w = (a >> FRACBITS);
fixed_t f = a % FRACUNIT;
fixed_t d = FRACUNIT;
if (f == 0)
@ -878,7 +913,7 @@ static inline void M_print(INT64 a)
printf("%d", (fixed_t)w);
return;
}
else while (f != 1 && f/2 == f>>1)
else while (f != 1 && f / 2 == f >> 1)
{
d /= 2;
f /= 2;
@ -892,7 +927,7 @@ static inline void M_print(INT64 a)
FUNCMATH FUNCINLINE static inline fixed_t FixedMulC(fixed_t a, fixed_t b)
{
return (fixed_t)((((INT64)a * b) ) / FRACUNIT);
return (fixed_t)((((INT64)a * b)) / FRACUNIT);
}
FUNCMATH FUNCINLINE static inline fixed_t FixedDivC2(fixed_t a, fixed_t b)
@ -902,7 +937,7 @@ FUNCMATH FUNCINLINE static inline fixed_t FixedDivC2(fixed_t a, fixed_t b)
if (b == 0)
I_Error("FixedDiv: divide by zero");
ret = (((INT64)a * FRACUNIT) ) / b;
ret = (((INT64)a * FRACUNIT)) / b;
if ((ret > INT32_MAX) || (ret < INT32_MIN))
I_Error("FixedDiv: divide by zero");
@ -911,7 +946,7 @@ FUNCMATH FUNCINLINE static inline fixed_t FixedDivC2(fixed_t a, fixed_t b)
FUNCMATH FUNCINLINE static inline fixed_t FixedDivC(fixed_t a, fixed_t b)
{
if ((abs(a) >> (FRACBITS-2)) >= abs(b))
if ((abs(a) >> (FRACBITS - 2)) >= abs(b))
return (a^b) < 0 ? INT32_MIN : INT32_MAX;
return FixedDivC2(a, b);
@ -938,43 +973,43 @@ int main(int argc, char** argv)
#ifdef MULDIV_TEST
for (a = 1; a <= INT32_MAX; a += FRACUNIT)
for (b = 0; b <= INT32_MAX; b += FRACUNIT)
{
c = FixedMul(a, b);
d = FixedMulC(a, b);
if (c != d)
for (b = 0; b <= INT32_MAX; b += FRACUNIT)
{
printf("(");
M_print(a);
printf(") * (");
M_print(b);
printf(") = (");
M_print(c);
printf(") != (");
M_print(d);
printf(") \n");
n--;
printf("%d != %d\n", c, d);
c = FixedMul(a, b);
d = FixedMulC(a, b);
if (c != d)
{
printf("(");
M_print(a);
printf(") * (");
M_print(b);
printf(") = (");
M_print(c);
printf(") != (");
M_print(d);
printf(") \n");
n--;
printf("%d != %d\n", c, d);
}
c = FixedDiv(a, b);
d = FixedDivC(a, b);
if (c != d)
{
printf("(");
M_print(a);
printf(") / (");
M_print(b);
printf(") = (");
M_print(c);
printf(") != (");
M_print(d);
printf(")\n");
n--;
printf("%d != %d\n", c, d);
}
if (n <= 0)
exit(-1);
}
c = FixedDiv(a, b);
d = FixedDivC(a, b);
if (c != d)
{
printf("(");
M_print(a);
printf(") / (");
M_print(b);
printf(") = (");
M_print(c);
printf(") != (");
M_print(d);
printf(")\n");
n--;
printf("%d != %d\n", c, d);
}
if (n <= 0)
exit(-1);
}
#endif
#ifdef SQRT_TEST
@ -982,7 +1017,7 @@ int main(int argc, char** argv)
{
c = FixedSqrt(a);
d = FixedSqrtC(a);
b = abs(c-d);
b = abs(c - d);
if (b > 1)
{
printf("sqrt(");

View file

@ -389,9 +389,11 @@ boolean FV3_Equal(const vector3_t *a_1, const vector3_t *a_2);
fixed_t FV3_Dot(const vector3_t *a_1, const vector3_t *a_2);
vector3_t *FV3_Cross(const vector3_t *a_1, const vector3_t *a_2, vector3_t *a_o);
vector3_t *FV3_ClosestPointOnLine(const vector3_t *Line, const vector3_t *p, vector3_t *out);
void FV3_ClosestPointOnVector(const vector3_t *dir, const vector3_t *p, vector3_t *out);
void FV3_ClosestPointOnTriangle(const vector3_t *tri, const vector3_t *point, vector3_t *result);
vector3_t *FV3_Point2Vec(const vector3_t *point1, const vector3_t *point2, vector3_t *a_o);
void FV3_Normal(const vector3_t *a_triangle, vector3_t *a_normal);
fixed_t FV3_Normal(const vector3_t *a_triangle, vector3_t *a_normal);
fixed_t FV3_Strength(const vector3_t *a_1, const vector3_t *dir);
fixed_t FV3_PlaneDistance(const vector3_t *a_normal, const vector3_t *a_point);
boolean FV3_IntersectedPlane(const vector3_t *a_triangle, const vector3_t *a_line, vector3_t *a_normal, fixed_t *originDistance);
fixed_t FV3_PlaneIntersection(const vector3_t *pOrigin, const vector3_t *pNormal, const vector3_t *rOrigin, const vector3_t *rVector);

View file

@ -1295,18 +1295,21 @@ static menuitem_t OP_ColorOptionsMenu[] =
#ifdef HWRENDER
static menuitem_t OP_OpenGLOptionsMenu[] =
{
{IT_STRING|IT_CVAR, NULL, "Field of view", &cv_grfov, 10},
{IT_STRING|IT_CVAR, NULL, "Quality", &cv_scr_depth, 20},
{IT_STRING|IT_CVAR, NULL, "Texture Filter", &cv_grfiltermode, 30},
{IT_STRING|IT_CVAR, NULL, "Anisotropic", &cv_granisotropicmode,40},
{IT_STRING|IT_CVAR, NULL, "Models", &cv_grmodels, 10},
{IT_STRING|IT_CVAR, NULL, "Model interpolation", &cv_grmodelinterpolation, 20},
{IT_STRING|IT_CVAR, NULL, "Field of view", &cv_grfov, 40},
{IT_STRING|IT_CVAR, NULL, "Quality", &cv_scr_depth, 50},
{IT_STRING|IT_CVAR, NULL, "Texture Filter", &cv_grfiltermode, 60},
{IT_STRING|IT_CVAR, NULL, "Anisotropic", &cv_granisotropicmode,70},
#if defined (_WINDOWS) && (!((defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL)))
{IT_STRING|IT_CVAR, NULL, "Fullscreen", &cv_fullscreen, 50},
{IT_STRING|IT_CVAR, NULL, "Fullscreen", &cv_fullscreen, 80},
#endif
#ifdef ALAM_LIGHTING
{IT_SUBMENU|IT_STRING, NULL, "Lighting...", &OP_OpenGLLightingDef, 70},
{IT_SUBMENU|IT_STRING, NULL, "Lighting...", &OP_OpenGLLightingDef, 100},
#endif
{IT_SUBMENU|IT_STRING, NULL, "Fog...", &OP_OpenGLFogDef, 80},
{IT_SUBMENU|IT_STRING, NULL, "Gamma...", &OP_OpenGLColorDef, 90},
{IT_SUBMENU|IT_STRING, NULL, "Fog...", &OP_OpenGLFogDef, 110},
{IT_SUBMENU|IT_STRING, NULL, "Gamma...", &OP_OpenGLColorDef, 120},
};
#ifdef ALAM_LIGHTING
@ -6560,7 +6563,7 @@ static void M_LevelSelectWarp(INT32 choice)
if (W_CheckNumForName(G_BuildMapName(cv_nextmap.value)) == LUMPERROR)
{
// CONS_Alert(CONS_WARNING, "Internal game map '%s' not found\n", G_BuildMapName(cv_nextmap.value));
CONS_Alert(CONS_WARNING, "Internal game map '%s' not found\n", G_BuildMapName(cv_nextmap.value));
return;
}
@ -7977,81 +7980,80 @@ static void M_SetupChoosePlayer(INT32 choice)
char *and;
(void)choice;
SP_PlayerMenu[0].status &= ~IT_DYBIGSPACE; // Correcting a hack that may be made below.
for (i = 0; i < 32; i++) // Handle charsels, availability, and unlocks.
if (!(mapheaderinfo[startmap-1]
&& (mapheaderinfo[startmap-1]->forcecharacter[0] != '\0'
|| (mapheaderinfo[startmap-1]->typeoflevel & TOL_NIGHTS)) // remove this later when everyone gets their own nights sprites, maybe
))
{
if (description[i].used) // If the character's disabled through SOC, there's nothing we can do for it.
for (i = 0; i < 32; i++) // Handle charsels, availability, and unlocks.
{
and = strchr(description[i].skinname, '&');
if (and)
if (description[i].used) // If the character's disabled through SOC, there's nothing we can do for it.
{
char firstskin[SKINNAMESIZE+1];
strncpy(firstskin, description[i].skinname, (and - description[i].skinname));
firstskin[(and - description[i].skinname)] = '\0';
description[i].skinnum[0] = R_SkinAvailable(firstskin);
description[i].skinnum[1] = R_SkinAvailable(and+1);
}
else
{
description[i].skinnum[0] = R_SkinAvailable(description[i].skinname);
description[i].skinnum[1] = -1;
}
skinnum = description[i].skinnum[0];
if ((skinnum != -1) && (R_SkinUsable(-1, skinnum)))
{
// Handling order.
if (firstvalid == 255)
firstvalid = i;
and = strchr(description[i].skinname, '&');
if (and)
{
char firstskin[SKINNAMESIZE+1];
strncpy(firstskin, description[i].skinname, (and - description[i].skinname));
firstskin[(and - description[i].skinname)] = '\0';
description[i].skinnum[0] = R_SkinAvailable(firstskin);
description[i].skinnum[1] = R_SkinAvailable(and+1);
}
else
{
description[i].prev = lastvalid;
description[lastvalid].next = i;
description[i].skinnum[0] = R_SkinAvailable(description[i].skinname);
description[i].skinnum[1] = -1;
}
lastvalid = i;
if (i == char_on)
allowed = true;
if (!(description[i].picname[0]))
skinnum = description[i].skinnum[0];
if ((skinnum != -1) && (R_SkinUsable(-1, skinnum)))
{
if (skins[skinnum].sprites[SPR2_XTRA].numframes >= XTRA_CHARSEL+1)
// Handling order.
if (firstvalid == 255)
firstvalid = i;
else
{
spritedef_t *sprdef = &skins[skinnum].sprites[SPR2_XTRA];
spriteframe_t *sprframe = &sprdef->spriteframes[XTRA_CHARSEL];
description[i].charpic = W_CachePatchNum(sprframe->lumppat[0], PU_CACHE);
description[i].prev = lastvalid;
description[lastvalid].next = i;
}
lastvalid = i;
if (i == char_on)
allowed = true;
if (!(description[i].picname[0]))
{
if (skins[skinnum].sprites[SPR2_XTRA].numframes >= XTRA_CHARSEL+1)
{
spritedef_t *sprdef = &skins[skinnum].sprites[SPR2_XTRA];
spriteframe_t *sprframe = &sprdef->spriteframes[XTRA_CHARSEL];
description[i].charpic = W_CachePatchNum(sprframe->lumppat[0], PU_CACHE);
}
else
description[i].charpic = W_CachePatchName("MISSING", PU_CACHE);
}
else
description[i].charpic = W_CachePatchName("MISSING", PU_CACHE);
}
else
description[i].charpic = W_CachePatchName(description[i].picname, PU_CACHE);
description[i].charpic = W_CachePatchName(description[i].picname, PU_CACHE);
if (description[i].nametag[0])
{
const char *nametag = description[i].nametag;
description[i].namepic = NULL;
if (W_LumpExists(nametag))
description[i].namepic = W_CachePatchName(nametag, PU_CACHE);
if (description[i].nametag[0])
{
const char *nametag = description[i].nametag;
description[i].namepic = NULL;
if (W_LumpExists(nametag))
description[i].namepic = W_CachePatchName(nametag, PU_CACHE);
}
}
// else -- Technically, character select icons without corresponding skins get bundled away behind this too. Sucks to be them.
}
// else -- Technically, character select icons without corresponding skins get bundled away behind this too. Sucks to be them.
}
}
if ((firstvalid != 255)
&& !(mapheaderinfo[startmap-1]
&& (mapheaderinfo[startmap-1]->forcecharacter[0] != '\0')
)
)
if (firstvalid != 255)
{ // One last bit of order we can't do in the iteration above.
description[firstvalid].prev = lastvalid;
description[lastvalid].next = firstvalid;
}
else // We're being forced into a specific character, so might as well.
else // We're being forced into a specific character, so might as well just skip it.
{
SP_PlayerMenu[0].status |= IT_DYBIGSPACE; // This is a dummy flag hack to make a non-IT_CALL character in slot 0 not softlock the game.
M_ChoosePlayer(0);
M_ChoosePlayer(-1);
return;
}
@ -8378,38 +8380,42 @@ static void M_DrawSetupChoosePlayerMenu(void)
static void M_ChoosePlayer(INT32 choice)
{
boolean ultmode = (ultimate_selectable && SP_PlayerDef.prevMenu == &SP_LoadDef && saveSlotSelected == NOSAVESLOT);
UINT8 skinnum;
// skip this if forcecharacter or no characters available
if (!(SP_PlayerMenu[0].status & IT_DYBIGSPACE))
if (choice == -1)
{
skinnum = botskin = 0;
botingame = false;
}
// M_SetupChoosePlayer didn't call us directly, that means we've been properly set up.
else
{
// M_SetupChoosePlayer didn't call us directly, that means we've been properly set up.
char_scroll = 0; // finish scrolling the menu
M_DrawSetupChoosePlayerMenu(); // draw the finally selected character one last time for the fadeout
// Is this a hack?
charseltimer = 0;
}
M_ClearMenus(true);
if (description[choice].skinnum[1] != -1) {
// this character has a second skin
botingame = true;
botskin = (UINT8)(description[choice].skinnum[1]+1);
botcolor = skins[description[choice].skinnum[1]].prefcolor;
}
else
{
botingame = false;
botskin = 0;
botcolor = 0;
skinnum = description[choice].skinnum[0];
if ((botingame = (description[choice].skinnum[1] != -1))) {
// this character has a second skin
botskin = (UINT8)(description[choice].skinnum[1]+1);
botcolor = skins[description[choice].skinnum[1]].prefcolor;
}
else
botskin = botcolor = 0;
}
M_ClearMenus(true);
if (startmap != spstage_start)
cursaveslot = 0;
//lastmapsaved = 0;
gamecomplete = false;
G_DeferedInitNew(ultmode, G_BuildMapName(startmap), (UINT8)description[choice].skinnum[0], false, fromlevelselect);
G_DeferedInitNew(ultmode, G_BuildMapName(startmap), skinnum, false, fromlevelselect);
COM_BufAddText("dummyconsvar 1\n"); // G_DeferedInitNew doesn't do this
if (levelselect.rows)

View file

@ -3327,7 +3327,8 @@ void A_SkullAttack(mobj_t *actor)
fixed_t oldradius = mobjinfo[MT_NULL].radius;
fixed_t oldheight = mobjinfo[MT_NULL].height;
mobj_t *check;
INT32 i, j, k;
INT32 i, j;
static INT32 k;/* static for (at least) GCC 9.1 weirdness */
boolean allow;
angle_t testang;
@ -3936,11 +3937,15 @@ void A_BossDeath(mobj_t *mo)
{
// Touching the egg trap button calls P_DoPlayerExit, which calls P_RestoreMusic.
// So just park ourselves in the mapmus variables.
boolean changed = strnicmp(mapheaderinfo[gamemap-1]->musname, mapmusname, 7);
strncpy(mapmusname, mapheaderinfo[gamemap-1]->muspostbossname, 7);
mapmusname[6] = 0;
mapmusflags = (mapheaderinfo[gamemap-1]->muspostbosstrack & MUSIC_TRACKMASK) | MUSIC_RELOADRESET;
mapmusposition = mapheaderinfo[gamemap-1]->muspostbosspos;
// But don't change the mapmus variables if they were modified from their level header values (e.g., TUNES).
boolean changed = strnicmp(mapheaderinfo[gamemap-1]->musname, S_MusicName(), 7);
if (!strnicmp(mapheaderinfo[gamemap-1]->musname, mapmusname, 7))
{
strncpy(mapmusname, mapheaderinfo[gamemap-1]->muspostbossname, 7);
mapmusname[6] = 0;
mapmusflags = (mapheaderinfo[gamemap-1]->muspostbosstrack & MUSIC_TRACKMASK) | MUSIC_RELOADRESET;
mapmusposition = mapheaderinfo[gamemap-1]->muspostbosspos;
}
// don't change if we're in another tune
// but in case we're in jingle, use our parked mapmus variables so the correct track restores
@ -9207,10 +9212,11 @@ void A_BossJetFume(mobj_t *actor)
P_SetTarget(&filler->target, actor);
filler->fuse = 59;
P_SetTarget(&actor->tracer, filler);
filler->destscale = actor->scale/3;
P_SetScale(filler, filler->destscale);
P_SetScale(filler, (filler->destscale = actor->scale/3));
if (actor->eflags & MFE_VERTICALFLIP)
filler->flags2 |= MF2_OBJECTFLIP;
filler->color = SKINCOLOR_ICY;
filler->colorized = true;
}
else if (locvar1 == 3) // Boss 4 jet flame
{

View file

@ -2372,7 +2372,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
if (target->player && !target->player->spectator)
{
if (metalrecording) // Ack! Metal Sonic shouldn't die! Cut the tape, end recording!
G_StopMetalRecording();
G_StopMetalRecording(true);
if (gametype == GT_MATCH // note, no team match suicide penalty
&& ((target == source) || (source == NULL && inflictor == NULL) || (source && !source->player)))
{ // Suicide penalty
@ -2617,7 +2617,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
target->fuse = target->info->damage;
break;
case MT_BUBBLEBUZZ:
case MT_BUGGLE:
if (inflictor && inflictor->player // did a player kill you? Spawn relative to the player so they're bound to get it
&& P_AproxDistance(inflictor->x - target->x, inflictor->y - target->y) <= inflictor->radius + target->radius + FixedMul(8*FRACUNIT, inflictor->scale) // close enough?
&& inflictor->z <= target->z + target->height + FixedMul(8*FRACUNIT, inflictor->scale)
@ -2763,6 +2763,12 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
}
}
break;
case MT_METALSONIC_RACE:
target->fuse = TICRATE*3;
target->momx = target->momy = target->momz = 0;
P_SetObjectMomZ(target, 14*FRACUNIT, false);
target->flags = (target->flags & ~MF_NOGRAVITY)|(MF_NOCLIP|MF_NOCLIPTHING);
break;
default:
break;
}
@ -3617,11 +3623,12 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
}
else if (inflictor && inflictor->flags & MF_MISSILE)
return false; // Metal Sonic walk through flame !!
else
else if (!player->powers[pw_flashing])
{ // Oh no! Metal Sonic is hit !!
P_ShieldDamage(player, inflictor, source, damage, damagetype);
return true;
}
return false;
}
else if (player->powers[pw_invulnerability] || player->powers[pw_flashing] || player->powers[pw_super]) // ignore bouncing & such in invulnerability
{

View file

@ -2563,19 +2563,30 @@ static boolean P_ZMovement(mobj_t *mo)
if (!mo->player && P_CheckDeathPitCollide(mo))
{
if (mo->flags & MF_ENEMY || mo->flags & MF_BOSS || mo->type == MT_MINECART)
switch (mo->type)
{
// Kill enemies, bosses and minecarts that fall into death pits.
if (mo->health)
{
P_KillMobj(mo, NULL, NULL, 0);
return false;
}
}
else
{
P_RemoveMobj(mo);
return false;
case MT_GHOST:
case MT_METALSONIC_RACE:
case MT_EXPLODE:
case MT_BOSSEXPLODE:
case MT_SONIC3KBOSSEXPLODE:
break;
default:
if (mo->flags & MF_ENEMY || mo->flags & MF_BOSS || mo->type == MT_MINECART)
{
// Kill enemies, bosses and minecarts that fall into death pits.
if (mo->health)
{
P_KillMobj(mo, NULL, NULL, 0);
}
return false;
}
else
{
P_RemoveMobj(mo);
return false;
}
break;
}
}
@ -5567,9 +5578,9 @@ static void P_Boss9Thinker(mobj_t *mobj)
P_InstaThrust(mobj, mobj->angle, -4*FRACUNIT);
P_TryMove(mobj, mobj->x+mobj->momx, mobj->y+mobj->momy, true);
mobj->momz -= gravity;
if (mobj->z < mobj->watertop)
if (mobj->z < mobj->watertop || mobj->z < (mobj->floorz + 16*FRACUNIT))
{
mobj->watertop = mobj->target->floorz + 32*FRACUNIT;
mobj->watertop = mobj->floorz + 32*FRACUNIT;
P_SetMobjState(mobj, mobj->info->spawnstate);
}
return;
@ -5577,16 +5588,22 @@ static void P_Boss9Thinker(mobj_t *mobj)
if ((!mobj->target || !(mobj->target->flags & MF_SHOOTABLE)))
{
if (mobj->tracer)
P_RemoveMobj(mobj->tracer);
if (mobj->hprev)
{
P_RemoveMobj(mobj->hprev);
P_SetTarget(&mobj->hprev, NULL);
}
P_BossTargetPlayer(mobj, false);
if (mobj->target && (!P_IsObjectOnGround(mobj->target) || mobj->target->player->pflags & PF_SPINNING))
P_SetTarget(&mobj->target, NULL); // Wait for them to hit the ground first
if (!mobj->target) // Still no target, aww.
{
// Reset the boss.
if (mobj->tracer)
P_RemoveMobj(mobj->tracer);
if (mobj->hprev)
{
P_RemoveMobj(mobj->hprev);
P_SetTarget(&mobj->hprev, NULL);
}
P_SetMobjState(mobj, mobj->info->spawnstate);
mobj->fuse = 0;
mobj->momx = FixedDiv(mobj->momx, FRACUNIT + (FRACUNIT>>2));
@ -5600,7 +5617,7 @@ static void P_Boss9Thinker(mobj_t *mobj)
return;
}
else if (!mobj->fuse)
mobj->fuse = 10*TICRATE;
mobj->fuse = 8*TICRATE;
}
// AI goes here.
@ -5627,16 +5644,18 @@ static void P_Boss9Thinker(mobj_t *mobj)
mobj->angle -= InvAngle(angle)/8;
// Alter your energy bubble's size/position
if (mobj->health > 3)
if (mobj->health > mobj->info->damage)
{
mobj->tracer->destscale = FRACUNIT + (4*TICRATE - mobj->fuse)*(FRACUNIT/2)/TICRATE + FixedMul(FINECOSINE(angle>>ANGLETOFINESHIFT),FRACUNIT/2);
P_SetScale(mobj->tracer, mobj->tracer->destscale);
}
if (mobj->hprev)
{
mobj->hprev->destscale = FRACUNIT + (2*TICRATE - mobj->fuse)*(FRACUNIT/2)/TICRATE + FixedMul(FINECOSINE(angle>>ANGLETOFINESHIFT),FRACUNIT/2);
P_SetScale(mobj->hprev, mobj->hprev->destscale);
P_TeleportMove(mobj->tracer, mobj->x, mobj->y, mobj->z + mobj->height/2 - mobj->tracer->height/2);
mobj->tracer->momx = mobj->momx;
mobj->tracer->momy = mobj->momy;
mobj->tracer->momz = mobj->momz;
P_TeleportMove(mobj->hprev, mobj->x, mobj->y, mobj->z + mobj->height/2 - mobj->hprev->height/2);
mobj->hprev->momx = mobj->momx;
mobj->hprev->momy = mobj->momy;
mobj->hprev->momz = mobj->momz;
}
// Firin' mah lazors - INDICATOR
if (mobj->fuse > TICRATE/2)
@ -5724,6 +5743,7 @@ static void P_Boss9Thinker(mobj_t *mobj)
S_StartSound(mobj, sfx_s3kb3);
}
}
}
// up...
mobj->z += mobj->height/2;
@ -5750,12 +5770,12 @@ static void P_Boss9Thinker(mobj_t *mobj)
if (mobj->health > mobj->info->damage)
{
P_SetScale(missile, FRACUNIT/3);
missile->color = SKINCOLOR_GOLD; // sonic cd electric power
missile->color = SKINCOLOR_MAGENTA; // sonic OVA/4 purple power
}
else
{
P_SetScale(missile, FRACUNIT/5);
missile->color = SKINCOLOR_MAGENTA; // sonic OVA/4 purple power
missile->color = SKINCOLOR_SUNSET; // sonic cd electric power
}
missile->destscale = missile->scale*2;
missile->scalespeed = abs(missile->scale - missile->destscale)/missile->fuse;
@ -5774,8 +5794,10 @@ static void P_Boss9Thinker(mobj_t *mobj)
if (mobj->movedir == 0 || mobj->movedir == 2) { // Pausing between bounces in the pinball phase
if (mobj->target->player->powers[pw_tailsfly]) // Trying to escape, eh?
mobj->watertop = mobj->target->z + mobj->target->momz*6; // Readjust your aim. >:3
else
else if (mobj->target->floorz > mobj->floorz)
mobj->watertop = mobj->target->floorz + 16*FRACUNIT;
else
mobj->watertop = mobj->floorz + 16*FRACUNIT;
if (!(mobj->threshold%4)) {
mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x + mobj->target->momx*4, mobj->target->y + mobj->target->momy*4);
@ -5867,8 +5889,6 @@ static void P_Boss9Thinker(mobj_t *mobj)
return;
}
P_SpawnGhostMobj(mobj);
// Pinball attack!
if (mobj->movecount == 3 && (mobj->movedir == 0 || mobj->movedir == 2))
{
@ -5883,20 +5903,20 @@ static void P_Boss9Thinker(mobj_t *mobj)
if (!P_TryMove(mobj, mobj->x+mobj->momx, mobj->y+mobj->momy, true))
{ // Hit a wall? Find a direction to bounce
mobj->threshold--;
P_SetMobjState(mobj, mobj->state->nextstate);
if (!mobj->threshold) { // failed bounce!
S_StartSound(mobj, sfx_mspogo);
P_BounceMove(mobj);
mobj->angle = R_PointToAngle2(mobj->momx, mobj->momy,0,0);
mobj->momz = 4*FRACUNIT;
mobj->flags &= ~MF_PAIN;
mobj->fuse = 10*TICRATE;
mobj->fuse = 8*TICRATE;
mobj->movecount = 0;
P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_CYBRAKDEMON_VILE_EXPLOSION);
P_SetMobjState(mobj, mobj->info->meleestate);
}
else if (!(mobj->threshold%4))
{ // We've decided to lock onto the player this bounce.
P_SetMobjState(mobj, mobj->state->nextstate);
S_StartSound(mobj, sfx_s3k5a);
mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x + mobj->target->momx*4, mobj->target->y + mobj->target->momy*4);
mobj->reactiontime = TICRATE - 5*(mobj->info->damage - mobj->health); // targetting time
@ -5913,6 +5933,8 @@ static void P_Boss9Thinker(mobj_t *mobj)
return;
}
P_SpawnGhostMobj(mobj)->colorized = false;
// Vector form dodge!
mobj->angle += mobj->movedir;
P_InstaThrust(mobj, mobj->angle, -speed);
@ -6009,7 +6031,7 @@ static void P_Boss9Thinker(mobj_t *mobj)
if (mobj->health > mobj->info->damage)
{ // No more bubble if we're broken (pinch phase)
mobj_t *shield = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_MSSHIELD_FRONT);
P_SetTarget(&mobj->tracer, shield);
P_SetTarget(&mobj->hprev, shield);
P_SetTarget(&shield->target, mobj);
// Attack 2: Energy shot!
@ -6040,14 +6062,15 @@ static void P_Boss9Thinker(mobj_t *mobj)
}
else
{
mobj_t *shield = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_MSSHIELD_FRONT);
/*mobj_t *shield = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_MSSHIELD_FRONT);
P_SetTarget(&mobj->tracer, shield);
P_SetTarget(&shield->target, mobj);
shield->height -= 20*FRACUNIT; // different offset...
P_SetMobjState(shield, S_MSSHIELD_F2);
P_SetMobjState(shield, S_MSSHIELD_F2);*/
P_SetMobjState(mobj, S_METALSONIC_BOUNCE);
//P_LinedefExecute(LE_PINCHPHASE, mobj, NULL); -- why does this happen twice? see case 2...
}
mobj->fuse = 4*TICRATE;
mobj->fuse = 3*TICRATE;
mobj->flags |= MF_PAIN;
if (mobj->info->attacksound)
S_StartSound(mobj, mobj->info->attacksound);
@ -6058,14 +6081,14 @@ static void P_Boss9Thinker(mobj_t *mobj)
case 2:
{
// We're all charged and ready now! Unleash the fury!!
mobj_t *removemobj = mobj->tracer;
S_StopSound(mobj);
P_SetTarget(&mobj->tracer, mobj->hnext);
P_RemoveMobj(removemobj);
if (mobj->hprev)
{
P_RemoveMobj(mobj->hprev);
P_SetTarget(&mobj->hprev, NULL);
}
if (mobj->health <= mobj->info->damage)
{
mobj_t *whoosh;
// Attack 1: Pinball dash!
if (mobj->health == 1)
mobj->movedir = 0;
@ -6078,9 +6101,13 @@ static void P_Boss9Thinker(mobj_t *mobj)
mobj->threshold = 12; // bounce 12 times
else
mobj->threshold = 24; // bounce 24 times
mobj->watertop = mobj->target->floorz + 16*FRACUNIT;
if (mobj->floorz >= mobj->target->floorz)
mobj->watertop = mobj->floorz + 16*FRACUNIT;
else
mobj->watertop = mobj->target->floorz + 16*FRACUNIT;
P_LinedefExecute(LE_PINCHPHASE, mobj, NULL);
#if 0
whoosh = P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_GHOST); // done here so the offset is correct
whoosh->frame = FF_FULLBRIGHT;
whoosh->sprite = SPR_ARMA;
@ -6088,9 +6115,13 @@ static void P_Boss9Thinker(mobj_t *mobj)
whoosh->scalespeed = FixedMul(whoosh->scalespeed, whoosh->scale);
whoosh->height = 38*whoosh->scale;
whoosh->fuse = 10;
whoosh->color = SKINCOLOR_MAGENTA;
whoosh->color = SKINCOLOR_SUNSET;
whoosh->colorized = true;
whoosh->flags |= MF_NOCLIPHEIGHT;
#endif
P_SetMobjState(mobj->tracer, S_JETFUMEFLASH);
P_SetScale(mobj->tracer, mobj->scale << 1);
}
else
{
@ -6102,10 +6133,13 @@ static void P_Boss9Thinker(mobj_t *mobj)
}
case 3:
// Return to idle.
mobj->watertop = mobj->target->floorz + 32*FRACUNIT;
if (mobj->floorz >= mobj->target->floorz)
mobj->watertop = mobj->floorz + 32*FRACUNIT;
else
mobj->watertop = mobj->target->floorz + 32*FRACUNIT;
P_SetMobjState(mobj, mobj->info->spawnstate);
mobj->flags &= ~MF_PAIN;
mobj->fuse = 10*TICRATE;
mobj->fuse = 8*TICRATE;
break;
}
mobj->movecount++;
@ -8264,6 +8298,20 @@ void P_MobjThinker(mobj_t *mobj)
P_SetObjectMomZ(mobj, -2 * FRACUNIT / 3, true);
}
break;
case MT_METALSONIC_RACE:
{
if (!(mobj->fuse % 8))
{
fixed_t r = mobj->radius >> FRACBITS;
mobj_t *explosion = P_SpawnMobj(
mobj->x + (P_RandomRange(r, -r) << FRACBITS),
mobj->y + (P_RandomRange(r, -r) << FRACBITS),
mobj->z + (P_RandomKey(mobj->height >> FRACBITS) << FRACBITS),
MT_SONIC3KBOSSEXPLODE);
S_StartSound(explosion, sfx_s3kb4);
}
P_SetObjectMomZ(mobj, -2 * FRACUNIT / 3, true);
}
default:
break;
}
@ -8399,7 +8447,7 @@ void P_MobjThinker(mobj_t *mobj)
}
}
break;
case MT_BUBBLEBUZZ:
case MT_BUGGLE:
mobj->eflags |= MFE_UNDERWATER; //P_MobjCheckWater(mobj); // solely for MFE_UNDERWATER for A_FlickySpawn
{
if (mobj->tracer && mobj->tracer->player && mobj->tracer->health > 0
@ -8413,6 +8461,9 @@ void P_MobjThinker(mobj_t *mobj)
if (leveltime % mobj->info->painchance == 0)
S_StartSound(mobj, mobj->info->activesound);
if ((statenum_t)(mobj->state-states) != mobj->info->seestate)
P_SetMobjState(mobj, mobj->info->seestate);
}
else
{
@ -8421,6 +8472,8 @@ void P_MobjThinker(mobj_t *mobj)
mobj->momx >>= 1;
mobj->momy >>= 1;
mobj->momz >>= 1;
if ((statenum_t)(mobj->state-states) != mobj->info->spawnstate)
P_SetMobjState(mobj, mobj->info->spawnstate);
}
}
break;
@ -8706,11 +8759,17 @@ void P_MobjThinker(mobj_t *mobj)
}
else if (mobj->fuse == 59)
{
boolean dashmod = ((mobj->target->flags & MF_PAIN) && (mobj->target->health <= mobj->target->info->damage));
jetx = mobj->target->x + P_ReturnThrustX(mobj->target, mobj->target->angle, -mobj->target->radius);
jety = mobj->target->y + P_ReturnThrustY(mobj->target, mobj->target->angle, -mobj->target->radius);
P_UnsetThingPosition(mobj);
mobj->x = jetx;
mobj->y = jety;
mobj->destscale = mobj->target->scale;
if (!(dashmod && mobj->target->state == states+S_METALSONIC_BOUNCE))
{
mobj->destscale = (mobj->destscale + FixedDiv(R_PointToDist2(0, 0, mobj->target->momx, mobj->target->momy), 36*mobj->target->scale))/3;
}
if (mobj->target->eflags & MFE_VERTICALFLIP)
mobj->z = mobj->target->z + mobj->target->height/2 + mobj->height/2;
else
@ -8718,6 +8777,14 @@ void P_MobjThinker(mobj_t *mobj)
mobj->floorz = mobj->z;
mobj->ceilingz = mobj->z+mobj->height;
P_SetThingPosition(mobj);
if (dashmod)
{
mobj->color = SKINCOLOR_SUNSET;
if (mobj->target->movecount == 3 && !mobj->target->reactiontime && (mobj->target->movedir == 0 || mobj->target->movedir == 2))
P_SpawnGhostMobj(mobj);
}
else
mobj->color = SKINCOLOR_ICY;
}
mobj->fuse++;
}
@ -10402,8 +10469,11 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
if (nummaprings >= 0)
nummaprings++;
break;
case MT_METALSONIC_BATTLE:
case MT_METALSONIC_RACE:
mobj->skin = &skins[5];
/* FALLTHRU */
case MT_METALSONIC_BATTLE:
mobj->color = skins[5].prefcolor;
sc = 5;
break;
case MT_FANG:
@ -10474,6 +10544,12 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
if (!(mobj->flags & MF_NOTHINK))
P_AddThinker(THINK_MOBJ, &mobj->thinker);
if (mobj->skin) // correct inadequecies above.
{
mobj->sprite2 = P_GetSkinSprite2(mobj->skin, (mobj->frame & FF_FRAMEMASK), NULL);
mobj->frame &= ~FF_FRAMEMASK;
}
// Call action functions when the state is set
if (st->action.acp1 && (mobj->flags & MF_RUNSPAWNFUNC))
{
@ -11256,6 +11332,8 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing)
}
if (mthing->options & MTF_AMBUSH)
P_SetPlayerMobjState(mobj, S_PLAY_FALL);
else if (metalrecording)
P_SetPlayerMobjState(mobj, S_PLAY_WAIT);
}
else
z = floor;
@ -12444,10 +12522,10 @@ ML_EFFECT5 : Don't stop thinking when too far away
if (mthing->extrainfo)
mobj->extravalue1 = mthing->extrainfo;
break;
case MT_TRAPGOYLE:
case MT_TRAPGOYLEUP:
case MT_TRAPGOYLEDOWN:
case MT_TRAPGOYLELONG:
case MT_GLAREGOYLE:
case MT_GLAREGOYLEUP:
case MT_GLAREGOYLEDOWN:
case MT_GLAREGOYLELONG:
if (mthing->angle >= 360)
mobj->tics += 7*(mthing->angle / 360) + 1; // starting delay
break;

View file

@ -76,6 +76,7 @@
#ifdef HWRENDER
#include "hardware/hw_main.h"
#include "hardware/hw_light.h"
#include "hardware/hw_model.h"
#endif
#ifdef ESLOPE
@ -548,52 +549,118 @@ size_t P_PrecacheLevelFlats(void)
flatmemory = 0;
for (i = 0; i < numlevelflats; i++)
{
lump = levelflats[i].lumpnum;
if (devparm)
flatmemory += W_LumpLength(lump);
R_GetFlat(lump);
if (levelflats[i].type == LEVELFLAT_FLAT)
{
lump = levelflats[i].u.flat.lumpnum;
if (devparm)
flatmemory += W_LumpLength(lump);
R_GetFlat(lump);
}
}
return flatmemory;
}
/*
levelflat refers to an array of level flats,
or NULL if we want to allocate it now.
*/
static INT32
Ploadflat (levelflat_t *levelflat, const char *flatname)
{
UINT8 buffer[8];
lumpnum_t flatnum;
int texturenum;
size_t i;
if (levelflat)
{
// Scan through the already found flats, return if it matches.
for (i = 0; i < numlevelflats; i++)
{
if (strnicmp(levelflat[i].name, flatname, 8) == 0)
return i;
}
}
#ifndef ZDEBUG
CONS_Debug(DBG_SETUP, "flat #%03d: %s\n", atoi(sizeu1(numlevelflats)), levelflat->name);
#endif
if (numlevelflats >= MAXLEVELFLATS)
I_Error("Too many flats in level\n");
if (levelflat)
levelflat += numlevelflats;
else
{
// allocate new flat memory
levelflats = Z_Realloc(levelflats, (numlevelflats + 1) * sizeof(*levelflats), PU_LEVEL, NULL);
levelflat = levelflats + numlevelflats;
}
// Store the name.
strlcpy(levelflat->name, flatname, sizeof (levelflat->name));
strupr(levelflat->name);
/* If we can't find a flat, try looking for a texture! */
if (( flatnum = R_GetFlatNumForName(flatname) ) == LUMPERROR)
{
if (( texturenum = R_CheckTextureNumForName(flatname) ) == -1)
{
// check for REDWALL
if (( texturenum = R_CheckTextureNumForName("REDWALL") ) != -1)
goto texturefound;
// check for REDFLR
else if (( flatnum = R_GetFlatNumForName("REDFLR") ) != LUMPERROR)
goto flatfound;
// nevermind
levelflat->type = LEVELFLAT_NONE;
}
else
{
texturefound:
levelflat->type = LEVELFLAT_TEXTURE;
levelflat->u.texture. num = texturenum;
levelflat->u.texture.lastnum = texturenum;
/* start out unanimated */
levelflat->u.texture.basenum = -1;
}
}
else
{
flatfound:
/* This could be a flat, patch, or PNG. */
if (R_CheckIfPatch(flatnum))
levelflat->type = LEVELFLAT_PATCH;
else
{
#ifndef NO_PNG_LUMPS
/*
Only need eight bytes for PNG headers.
FIXME: Put this elsewhere.
*/
W_ReadLumpHeader(flatnum, buffer, 8, 0);
if (R_IsLumpPNG(buffer, W_LumpLength(flatnum)))
levelflat->type = LEVELFLAT_PNG;
else
#endif/*NO_PNG_LUMPS*/
levelflat->type = LEVELFLAT_FLAT;/* phew */
}
levelflat->u.flat. lumpnum = flatnum;
levelflat->u.flat.baselumpnum = LUMPERROR;
}
return ( numlevelflats++ );
}
// Auxiliary function. Find a flat in the active wad files,
// allocate an id for it, and set the levelflat (to speedup search)
INT32 P_AddLevelFlat(const char *flatname, levelflat_t *levelflat)
{
size_t i;
// Scan through the already found flats, break if it matches.
for (i = 0; i < numlevelflats; i++, levelflat++)
if (strnicmp(levelflat->name, flatname, 8) == 0)
break;
// If there is no match, make room for a new flat.
if (i == numlevelflats)
{
// Store the name.
strlcpy(levelflat->name, flatname, sizeof (levelflat->name));
strupr(levelflat->name);
// store the flat lump number
levelflat->lumpnum = R_GetFlatNumForName(flatname);
levelflat->texturenum = R_CheckTextureNumForName(flatname);
levelflat->lasttexturenum = levelflat->texturenum;
levelflat->baselumpnum = LUMPERROR;
levelflat->basetexturenum = -1;
#ifndef ZDEBUG
CONS_Debug(DBG_SETUP, "flat #%03d: %s\n", atoi(sizeu1(numlevelflats)), levelflat->name);
#endif
numlevelflats++;
if (numlevelflats >= MAXLEVELFLATS)
I_Error("Too many flats in level\n");
}
// level flat id
return (INT32)i;
return Ploadflat(levelflat, flatname);
}
// help function for Lua and $$$.sav reading
@ -602,44 +669,7 @@ INT32 P_AddLevelFlat(const char *flatname, levelflat_t *levelflat)
//
INT32 P_AddLevelFlatRuntime(const char *flatname)
{
size_t i;
levelflat_t *levelflat = levelflats;
//
// first scan through the already found flats
//
for (i = 0; i < numlevelflats; i++, levelflat++)
if (strnicmp(levelflat->name,flatname,8)==0)
break;
// that flat was already found in the level, return the id
if (i == numlevelflats)
{
// allocate new flat memory
levelflats = Z_Realloc(levelflats, (numlevelflats + 1) * sizeof(*levelflats), PU_LEVEL, NULL);
levelflat = levelflats+i;
// store the name
strlcpy(levelflat->name, flatname, sizeof (levelflat->name));
strupr(levelflat->name);
// store the flat lump number
levelflat->lumpnum = R_GetFlatNumForName(flatname);
levelflat->texturenum = R_CheckTextureNumForName(flatname);
levelflat->lasttexturenum = levelflat->texturenum;
levelflat->baselumpnum = LUMPERROR;
levelflat->basetexturenum = -1;
#ifndef ZDEBUG
CONS_Debug(DBG_SETUP, "flat #%03d: %s\n", atoi(sizeu1(numlevelflats)), levelflat->name);
#endif
numlevelflats++;
}
// level flat id
return (INT32)i;
return Ploadflat(0, flatname);
}
// help function for $$$.sav checking
@ -3476,6 +3506,10 @@ boolean P_AddWadFile(const char *wadfilename)
R_LoadSpriteInfoLumps(wadnum, numlumps);
#ifdef HWRENDER
HWR_ReloadModels();
#endif
// reload status bar (warning should have valid player!)
if (gamestate == GS_LEVEL)
ST_Start();

View file

@ -30,20 +30,51 @@ extern boolean levelloading;
extern UINT8 levelfadecol;
extern lumpnum_t lastloadedmaplumpnum; // for comparative savegame
/* for levelflat type */
enum
{
LEVELFLAT_NONE,/* HOM time my friend */
LEVELFLAT_FLAT,
LEVELFLAT_PATCH,
#ifndef NO_PNG_LUMPS
LEVELFLAT_PNG,
#endif
LEVELFLAT_TEXTURE,
};
//
// MAP used flats lookup table
//
typedef struct
{
char name[9]; // resource name from wad
lumpnum_t lumpnum; // lump number of the flat
INT32 texturenum, lasttexturenum; // texture number of the flat
UINT8 type;
union
{
struct
{
lumpnum_t lumpnum; // lump number of the flat
// for flat animation
lumpnum_t baselumpnum;
}
flat;
struct
{
INT32 num;
INT32 lastnum; // texture number of the flat
// for flat animation
INT32 basenum;
}
texture;
}
u;
UINT16 width, height;
fixed_t topoffset, leftoffset;
// for flat animation
lumpnum_t baselumpnum;
INT32 basetexturenum;
INT32 animseq; // start pos. in the anim sequence
INT32 numpics;
INT32 speed;

View file

@ -464,11 +464,11 @@ static inline void P_FindAnimatedFlat(INT32 animnum)
for (i = 0; i < numlevelflats; i++, foundflats++)
{
// is that levelflat from the flat anim sequence ?
if ((anims[animnum].istexture) && (foundflats->texturenum != 0 && foundflats->texturenum != -1)
&& ((UINT16)foundflats->texturenum >= startflatnum && (UINT16)foundflats->texturenum <= endflatnum))
if ((anims[animnum].istexture) && (foundflats->type == LEVELFLAT_TEXTURE)
&& ((UINT16)foundflats->u.texture.num >= startflatnum && (UINT16)foundflats->u.texture.num <= endflatnum))
{
foundflats->basetexturenum = startflatnum;
foundflats->animseq = foundflats->texturenum - startflatnum;
foundflats->u.texture.basenum = startflatnum;
foundflats->animseq = foundflats->u.texture.num - startflatnum;
foundflats->numpics = endflatnum - startflatnum + 1;
foundflats->speed = anims[animnum].speed;
@ -476,10 +476,10 @@ static inline void P_FindAnimatedFlat(INT32 animnum)
atoi(sizeu1(i)), foundflats->name, foundflats->animseq,
foundflats->numpics,foundflats->speed);
}
else if (foundflats->lumpnum >= startflatnum && foundflats->lumpnum <= endflatnum)
else if (foundflats->u.flat.lumpnum >= startflatnum && foundflats->u.flat.lumpnum <= endflatnum)
{
foundflats->baselumpnum = startflatnum;
foundflats->animseq = foundflats->lumpnum - startflatnum;
foundflats->u.flat.baselumpnum = startflatnum;
foundflats->animseq = foundflats->u.flat.lumpnum - startflatnum;
foundflats->numpics = endflatnum - startflatnum + 1;
foundflats->speed = anims[animnum].speed;
@ -5589,11 +5589,11 @@ void P_UpdateSpecials(void)
if (foundflats->speed) // it is an animated flat
{
// update the levelflat texture number
if (foundflats->basetexturenum != -1)
foundflats->texturenum = foundflats->basetexturenum + ((leveltime/foundflats->speed + foundflats->animseq) % foundflats->numpics);
if (foundflats->type == LEVELFLAT_TEXTURE)
foundflats->u.texture.num = foundflats->u.texture.basenum + ((leveltime/foundflats->speed + foundflats->animseq) % foundflats->numpics);
// update the levelflat lump number
else if (foundflats->baselumpnum != LUMPERROR)
foundflats->lumpnum = foundflats->baselumpnum + ((leveltime/foundflats->speed + foundflats->animseq) % foundflats->numpics);
else if ((foundflats->type == LEVELFLAT_FLAT) && (foundflats->u.flat.baselumpnum != LUMPERROR))
foundflats->u.flat.lumpnum = foundflats->u.flat.baselumpnum + ((leveltime/foundflats->speed + foundflats->animseq) % foundflats->numpics);
}
}
}

View file

@ -2050,8 +2050,7 @@ void P_SpawnThokMobj(player_t *player)
mobj->eflags |= (player->mo->eflags & MFE_VERTICALFLIP);
// scale
P_SetScale(mobj, player->mo->scale);
mobj->destscale = player->mo->scale;
P_SetScale(mobj, (mobj->destscale = player->mo->scale));
if (type == MT_THOK) // spintrail-specific modification for MT_THOK
{
@ -2061,8 +2060,7 @@ void P_SpawnThokMobj(player_t *player)
}
P_SetTarget(&mobj->target, player->mo); // the one thing P_SpawnGhostMobj doesn't do
if (demorecording)
G_GhostAddThok();
G_GhostAddThok();
}
//
@ -2265,7 +2263,7 @@ boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff)
else if (!player->skidtime)
player->pflags &= ~PF_GLIDING;
}
else if (player->charability == CA_GLIDEANDCLIMB && player->pflags & PF_THOKKED && (~player->pflags) & PF_SHIELDABILITY)
else if (player->charability == CA_GLIDEANDCLIMB && player->pflags & PF_THOKKED && !(player->pflags & PF_SHIELDABILITY) && player->mo->state-states == S_PLAY_FALL)
{
if (player->mo->state-states != S_PLAY_GLIDE_LANDING)
{
@ -4576,8 +4574,7 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd)
if (player->revitem && !(leveltime % 5)) // Now spawn the color thok circle.
{
P_SpawnSpinMobj(player, player->revitem);
if (demorecording)
G_GhostAddRev();
G_GhostAddRev();
}
}
@ -5305,14 +5302,23 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd)
// Now Knuckles-type abilities are checked.
if (!(player->pflags & PF_THOKKED) || player->charflags & SF_MULTIABILITY)
{
INT32 glidespeed = player->actionspd;
fixed_t glidespeed = FixedMul(player->actionspd, player->mo->scale);
fixed_t playerspeed = player->speed;
if (player->mo->eflags & MFE_UNDERWATER)
{
glidespeed >>= 1;
playerspeed >>= 1;
player->mo->momx = ((player->mo->momx - player->cmomx) >> 1) + player->cmomx;
player->mo->momy = ((player->mo->momy - player->cmomy) >> 1) + player->cmomy;
}
player->pflags |= PF_GLIDING|PF_THOKKED;
player->glidetime = 0;
P_SetPlayerMobjState(player->mo, S_PLAY_GLIDE);
if (player->speed < glidespeed)
P_Thrust(player->mo, player->mo->angle, glidespeed - player->speed);
if (playerspeed < glidespeed)
P_Thrust(player->mo, player->mo->angle, glidespeed - playerspeed);
player->pflags &= ~(PF_SPINNING|PF_STARTDASH);
}
break;
@ -5972,7 +5978,12 @@ static void P_3dMovement(player_t *player)
if (player->climbing)
{
if (cmd->forwardmove)
P_SetObjectMomZ(player->mo, FixedDiv(cmd->forwardmove*FRACUNIT, 15*FRACUNIT>>1), false);
{
if (player->mo->eflags & MFE_UNDERWATER)
P_SetObjectMomZ(player->mo, FixedDiv(cmd->forwardmove*FRACUNIT, 10*FRACUNIT), false);
else
P_SetObjectMomZ(player->mo, FixedDiv(cmd->forwardmove*FRACUNIT, 15*FRACUNIT>>1), false);
}
}
else if (!analogmove
&& cmd->forwardmove != 0 && !(player->pflags & PF_GLIDING || player->exiting
@ -6006,7 +6017,12 @@ static void P_3dMovement(player_t *player)
}
// Sideways movement
if (player->climbing)
P_InstaThrust(player->mo, player->mo->angle-ANGLE_90, FixedDiv(cmd->sidemove*player->mo->scale, 15*FRACUNIT>>1));
{
if (player->mo->eflags & MFE_UNDERWATER)
P_InstaThrust(player->mo, player->mo->angle-ANGLE_90, FixedDiv(cmd->sidemove*player->mo->scale, 10*FRACUNIT));
else
P_InstaThrust(player->mo, player->mo->angle-ANGLE_90, FixedDiv(cmd->sidemove*player->mo->scale, 15*FRACUNIT>>1));
}
// Analog movement control
else if (analogmove)
{
@ -8361,8 +8377,7 @@ static void P_MovePlayer(player_t *player)
if (player->pflags & PF_SPINNING && P_AproxDistance(player->speed, player->mo->momz) > FixedMul(15<<FRACBITS, player->mo->scale) && !(player->pflags & PF_JUMPED))
{
P_SpawnSpinMobj(player, player->spinitem);
if (demorecording)
G_GhostAddSpin();
G_GhostAddSpin();
}
@ -11129,6 +11144,7 @@ static void P_DoMetalJetFume(player_t *player, mobj_t *fume)
}
fume->movecount = dashmode; // keeps track of previous dashmode value so we know whether Metal is entering or leaving it
fume->eflags = (fume->flags2 & ~MF2_OBJECTFLIP) | (mo->flags2 & MF2_OBJECTFLIP); // Make sure to flip in reverse gravity!
fume->eflags = (fume->eflags & ~MFE_VERTICALFLIP) | (mo->eflags & MFE_VERTICALFLIP); // Make sure to flip in reverse gravity!
// Finally, set its position
@ -11137,10 +11153,7 @@ static void P_DoMetalJetFume(player_t *player, mobj_t *fume)
P_UnsetThingPosition(fume);
fume->x = mo->x + P_ReturnThrustX(fume, angle, dist);
fume->y = mo->y + P_ReturnThrustY(fume, angle, dist);
if (fume->eflags & MFE_VERTICALFLIP)
fume->z = mo->z + ((mo->height + fume->height) >> 1);
else
fume->z = mo->z + ((mo->height - fume->height) >> 1);
fume->z = mo->z + ((mo->height - fume->height) >> 1);
P_SetThingPosition(fume);
}
@ -11532,7 +11545,7 @@ void P_PlayerThink(player_t *player)
// deez New User eXperiences.
{
angle_t diff = 0;
angle_t oldang = player->drawangle, diff = 0;
UINT8 factor;
// Directionchar!
// Camera angle stuff.
@ -11546,6 +11559,13 @@ void P_PlayerThink(player_t *player)
player->drawangle = player->mo->angle;
else if (P_PlayerInPain(player))
;
else if (player->powers[pw_justsprung]) // restricted, potentially by lua
{
#ifdef SPRINGSPIN
if (player->powers[pw_justsprung] & (1<<15))
player->drawangle += (player->powers[pw_justsprung] & ~(1<<15))*(ANG2+ANG1);
#endif
}
else if (player->powers[pw_carry] && player->mo->tracer) // carry
{
switch (player->powers[pw_carry])
@ -11583,13 +11603,6 @@ void P_PlayerThink(player_t *player)
break;
}
}
else if (player->powers[pw_justsprung])
{
#ifdef SPRINGSPIN
if (player->powers[pw_justsprung] & (1<<15))
player->drawangle += (player->powers[pw_justsprung] & ~(1<<15))*(ANG2+ANG1);
#endif
}
else if ((player->skidtime > (TICRATE/2 - 2) || ((player->pflags & (PF_SPINNING|PF_STARTDASH)) == PF_SPINNING)) && (abs(player->rmomx) > 5*player->mo->scale || abs(player->rmomy) > 5*player->mo->scale)) // spin/skid force
player->drawangle = R_PointToAngle2(0, 0, player->rmomx, player->rmomy);
else if (((player->charability2 == CA2_GUNSLINGER || player->charability2 == CA2_MELEE) && player->panim == PA_ABILITY2) || player->pflags & PF_STASIS || player->skidtime)
@ -11650,6 +11663,22 @@ void P_PlayerThink(player_t *player)
player->drawangle += diff;
}
// reset from waiting to standing when turning on the spot
if (player->panim == PA_IDLE)
{
diff = player->drawangle - oldang;
if (diff > ANGLE_180)
diff = InvAngle(diff);
if (diff > ANG10/2)
{
statenum_t stat = player->mo->state-states;
if (stat == S_PLAY_WAIT)
P_SetPlayerMobjState(player->mo, S_PLAY_STND);
else if (stat == S_PLAY_STND && player->mo->tics != -1)
player->mo->tics++;
}
}
// Autobrake! check ST_drawInput if you modify this
{
boolean currentlyonground = P_IsObjectOnGround(player->mo);
@ -11888,8 +11917,8 @@ void P_PlayerThink(player_t *player)
player->pflags &= ~PF_SLIDING;
#define dashmode player->dashmode
// Dash mode - thanks be to Iceman404
if ((player->charflags & SF_DASHMODE) && !(player->gotflag) && !(maptol & TOL_NIGHTS)) // woo, dashmode! no nights tho.
// Dash mode - thanks be to VelocitOni
if ((player->charflags & SF_DASHMODE) && !player->gotflag && !player->powers[pw_carry] && !player->exiting && !(maptol & TOL_NIGHTS) && !metalrecording) // woo, dashmode! no nights tho.
{
boolean totallyradical = player->speed >= FixedMul(player->runspeed, player->mo->scale);
boolean floating = (player->secondjump == 1);
@ -11899,12 +11928,16 @@ void P_PlayerThink(player_t *player)
if (dashmode < DASHMODE_MAX)
dashmode++; // Counter. Adds 1 to dash mode per tic in top speed.
if (dashmode == DASHMODE_THRESHOLD) // This isn't in the ">=" equation because it'd cause the sound to play infinitely.
S_StartSound(player->mo, sfx_s3ka2); // If the player enters dashmode, play this sound on the the tic it starts.
S_StartSound(player->mo, (player->charflags & SF_MACHINE) ? sfx_kc4d : sfx_cdfm40); // If the player enters dashmode, play this sound on the the tic it starts.
}
else if ((!totallyradical || !floating) && !(player->pflags & PF_SPINNING))
{
if (dashmode > 3)
{
dashmode -= 3; // Rather than lose it all, it gently counts back down!
if ((dashmode+3) >= DASHMODE_THRESHOLD && dashmode < DASHMODE_THRESHOLD)
S_StartSound(player->mo, sfx_kc65);
}
else
dashmode = 0;
}
@ -11935,6 +11968,7 @@ void P_PlayerThink(player_t *player)
{
player->normalspeed = skins[player->skin].normalspeed;
player->jumpfactor = skins[player->skin].jumpfactor;
S_StartSound(player->mo, sfx_kc65);
}
dashmode = 0;
}

View file

@ -435,6 +435,7 @@ static UINT8 *R_GenerateTexture(size_t texnum)
texture_t *texture;
texpatch_t *patch;
patch_t *realpatch;
boolean dealloc = false;
int x, x1, x2, i, width, height;
size_t blocksize;
column_t *patchcol;
@ -466,10 +467,7 @@ static UINT8 *R_GenerateTexture(size_t texnum)
#ifndef NO_PNG_LUMPS
if (R_IsLumpPNG((UINT8 *)realpatch, lumplength))
{
realpatch = R_PNGToPatch((UINT8 *)realpatch, lumplength, NULL, false);
goto multipatch;
}
#endif
// Check the patch for holes.
@ -558,9 +556,14 @@ static UINT8 *R_GenerateTexture(size_t texnum)
lumpnum = patch->lump;
lumplength = W_LumpLengthPwad(wadnum, lumpnum);
realpatch = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE);
dealloc = false;
#ifndef NO_PNG_LUMPS
if (R_IsLumpPNG((UINT8 *)realpatch, lumplength))
{
realpatch = R_PNGToPatch((UINT8 *)realpatch, lumplength, NULL, false);
dealloc = true;
}
#endif
x1 = patch->originx;
@ -598,6 +601,9 @@ static UINT8 *R_GenerateTexture(size_t texnum)
*(UINT32 *)&colofs[x<<2] = LONG((x * texture->height) + (texture->width*4));
ColumnDrawerPointer(patchcol, block + LONG(*(UINT32 *)&colofs[x<<2]), patch, texture->height, height);
}
if (dealloc)
Z_Free(realpatch);
}
done:
@ -1429,48 +1435,6 @@ lumpnum_t R_GetFlatNumForName(const char *name)
lump = LUMPERROR;
}
// Detect textures
if (lump == LUMPERROR)
{
// Scan wad files backwards so patched textures take preference.
for (i = numwadfiles - 1; i >= 0; i--)
{
switch (wadfiles[i]->type)
{
case RET_WAD:
if ((start = W_CheckNumForNamePwad("TX_START", (UINT16)i, 0)) == INT16_MAX)
continue;
if ((end = W_CheckNumForNamePwad("TX_END", (UINT16)i, start)) == INT16_MAX)
continue;
break;
case RET_PK3:
if ((start = W_CheckNumForFolderStartPK3("Textures/", i, 0)) == INT16_MAX)
continue;
if ((end = W_CheckNumForFolderEndPK3("Textures/", i, start)) == INT16_MAX)
continue;
break;
default:
continue;
}
// Now find lump with specified name in that range.
lump = W_CheckNumForNamePwad(name, (UINT16)i, start);
if (lump < end)
{
lump += (i<<16); // found it, in our constraints
break;
}
lump = LUMPERROR;
}
}
if (lump == LUMPERROR)
{
if (strcmp(name, SKYFLATNAME))
CONS_Debug(DBG_SETUP, "R_GetFlatNumForName: Could not find flat %.8s\n", name);
lump = W_CheckNumForName("REDFLR");
}
return lump;
}

View file

@ -567,8 +567,12 @@ static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, U
else if (skinnum == TC_METALSONIC)
{
for (i = 0; i < 6; i++)
{
dest_colormap[Color_Index[SKINCOLOR_BLUE-1][12-i]] = Color_Index[SKINCOLOR_BLUE-1][i];
}
dest_colormap[159] = dest_colormap[253] = dest_colormap[254] = 0;
for (i = 0; i < 16; i++)
dest_colormap[96+i] = dest_colormap[Color_Index[SKINCOLOR_COBALT-1][i]];
}
else if (skinnum == TC_DASHMODE) // This is a long one, because MotorRoach basically hand-picked the indices
{

View file

@ -1208,7 +1208,6 @@ void R_RegisterEngineStuff(void)
CV_RegisterVar(&cv_grgammared);
CV_RegisterVar(&cv_grfovchange);
CV_RegisterVar(&cv_grfog);
CV_RegisterVar(&cv_voodoocompatibility);
CV_RegisterVar(&cv_grfogcolor);
CV_RegisterVar(&cv_grsoftwarefog);
#ifdef ALAM_LIGHTING
@ -1217,7 +1216,8 @@ void R_RegisterEngineStuff(void)
CV_RegisterVar(&cv_grcoronas);
CV_RegisterVar(&cv_grcoronasize);
#endif
CV_RegisterVar(&cv_grmd2);
CV_RegisterVar(&cv_grmodelinterpolation);
CV_RegisterVar(&cv_grmodels);
CV_RegisterVar(&cv_grspritebillboarding);
CV_RegisterVar(&cv_grskydome);
#endif

View file

@ -756,9 +756,9 @@ static UINT8 *R_GenerateFlat(UINT16 width, UINT16 height)
static UINT8 *R_GetTextureFlat(levelflat_t *levelflat, boolean leveltexture, boolean ispng)
{
UINT8 *flat;
textureflat_t *texflat = &texflats[levelflat->texturenum];
textureflat_t *texflat = &texflats[levelflat->u.texture.num];
patch_t *patch = NULL;
boolean texturechanged = (leveltexture ? (levelflat->texturenum != levelflat->lasttexturenum) : false);
boolean texturechanged = (leveltexture ? (levelflat->u.texture.num != levelflat->u.texture.lastnum) : false);
// Check if the texture changed.
if (leveltexture && (!texturechanged))
@ -780,12 +780,12 @@ static UINT8 *R_GetTextureFlat(levelflat_t *levelflat, boolean leveltexture, boo
// Level texture
if (leveltexture)
{
texture_t *texture = textures[levelflat->texturenum];
texture_t *texture = textures[levelflat->u.texture.num];
texflat->width = ds_flatwidth = texture->width;
texflat->height = ds_flatheight = texture->height;
texflat->flat = R_GenerateFlat(ds_flatwidth, ds_flatheight);
R_TextureToFlat(levelflat->texturenum, texflat->flat);
R_TextureToFlat(levelflat->u.texture.num, texflat->flat);
flat = texflat->flat;
levelflat->flatpatch = flat;
@ -799,7 +799,7 @@ static UINT8 *R_GetTextureFlat(levelflat_t *levelflat, boolean leveltexture, boo
#ifndef NO_PNG_LUMPS
if (ispng)
{
levelflat->flatpatch = R_PNGToFlat(&levelflat->width, &levelflat->height, ds_source, W_LumpLength(levelflat->lumpnum));
levelflat->flatpatch = R_PNGToFlat(&levelflat->width, &levelflat->height, ds_source, W_LumpLength(levelflat->u.flat.lumpnum));
levelflat->topoffset = levelflat->leftoffset = 0;
ds_flatwidth = levelflat->width;
ds_flatheight = levelflat->height;
@ -829,7 +829,7 @@ static UINT8 *R_GetTextureFlat(levelflat_t *levelflat, boolean leveltexture, boo
xoffs += levelflat->leftoffset;
yoffs += levelflat->topoffset;
levelflat->lasttexturenum = levelflat->texturenum;
levelflat->u.texture.lastnum = levelflat->u.texture.num;
return flat;
}
@ -839,10 +839,9 @@ void R_DrawSinglePlane(visplane_t *pl)
INT32 light = 0;
INT32 x;
INT32 stop, angle;
size_t size;
ffloor_t *rover;
levelflat_t *levelflat;
boolean rawflat = false;
int type;
if (!(pl->minx <= pl->maxx))
return;
@ -996,43 +995,45 @@ void R_DrawSinglePlane(visplane_t *pl)
currentplane = pl;
levelflat = &levelflats[pl->picnum];
size = W_LumpLength(levelflat->lumpnum);
ds_source = (UINT8 *)W_CacheLumpNum(levelflat->lumpnum, PU_STATIC); // Stay here until Z_ChangeTag
// Check if the flat is actually a wall texture.
if (levelflat->texturenum != 0 && levelflat->texturenum != -1)
flat = R_GetTextureFlat(levelflat, true, false);
/* :james: */
type = levelflat->type;
switch (type)
{
case LEVELFLAT_NONE:
return;
case LEVELFLAT_FLAT:
ds_source = W_CacheLumpNum(levelflat->u.flat.lumpnum, PU_CACHE);
R_CheckFlatLength(W_LumpLength(levelflat->u.flat.lumpnum));
// Raw flats always have dimensions that are powers-of-two numbers.
ds_powersoftwo = true;
break;
default:
switch (type)
{
case LEVELFLAT_TEXTURE:
/* Textures get cached differently and don't need ds_source */
ds_source = R_GetTextureFlat(levelflat, true, false);
break;
default:
ds_source = W_CacheLumpNum(levelflat->u.flat.lumpnum, PU_STATIC);
flat = R_GetTextureFlat(levelflat, false,
#ifndef NO_PNG_LUMPS
// Maybe it's a PNG?!
else if (R_IsLumpPNG(ds_source, size))
flat = R_GetTextureFlat(levelflat, false, true);
( type == LEVELFLAT_PNG )
#else
false
#endif
// Maybe it's just a patch, then?
else if (R_CheckIfPatch(levelflat->lumpnum))
flat = R_GetTextureFlat(levelflat, false, false);
// It's a raw flat.
else
{
rawflat = true;
R_CheckFlatLength(size);
flat = ds_source;
}
Z_ChangeTag(ds_source, PU_CACHE);
ds_source = flat;
if (ds_source == NULL)
return;
// Raw flats always have dimensions that are powers-of-two numbers.
if (rawflat)
ds_powersoftwo = true;
// Otherwise, check if this texture or patch has such dimensions.
else if (R_CheckPowersOfTwo())
{
R_CheckFlatLength(ds_flatwidth * ds_flatheight);
if (spanfunc == basespanfunc)
spanfunc = mmxspanfunc;
);
Z_ChangeTag(ds_source, PU_CACHE);
ds_source = flat;
}
// Check if this texture or patch has power-of-two dimensions.
if (R_CheckPowersOfTwo())
{
R_CheckFlatLength(ds_flatwidth * ds_flatheight);
if (spanfunc == basespanfunc)
spanfunc = mmxspanfunc;
}
}
if (light >= LIGHTLEVELS)

View file

@ -520,7 +520,7 @@ void R_AddSpriteDefs(UINT16 wadnum)
{
#ifdef HWRENDER
if (rendermode == render_opengl)
HWR_AddSpriteMD2(i);
HWR_AddSpriteModel(i);
#endif
// if a new sprite was added (not just replaced)
addsprites++;
@ -846,10 +846,13 @@ static void R_DrawVisSprite(vissprite_t *vis)
dc_translation = R_GetTranslationColormap(TC_RAINBOW, vis->mobj->color, GTC_CACHE);
else if (!(vis->cut & SC_PRECIP)
&& vis->mobj->player && vis->mobj->player->dashmode >= DASHMODE_THRESHOLD
&& (vis->mobj->player->charflags & (SF_DASHMODE|SF_MACHINE)) == (SF_DASHMODE|SF_MACHINE)
&& (vis->mobj->player->charflags & SF_DASHMODE)
&& ((leveltime/2) & 1))
{
dc_translation = R_GetTranslationColormap(TC_DASHMODE, 0, GTC_CACHE);
if (vis->mobj->player->charflags & SF_MACHINE)
dc_translation = R_GetTranslationColormap(TC_DASHMODE, 0, GTC_CACHE);
else
dc_translation = R_GetTranslationColormap(TC_RAINBOW, vis->mobj->color, GTC_CACHE);
}
else if (!(vis->cut & SC_PRECIP) && vis->mobj->skin && vis->mobj->sprite == SPR_PLAY) // MT_GHOST LOOKS LIKE A PLAYER SO USE THE PLAYER TRANSLATION TABLES. >_>
{
@ -874,10 +877,13 @@ static void R_DrawVisSprite(vissprite_t *vis)
dc_translation = R_GetTranslationColormap(TC_RAINBOW, vis->mobj->color, GTC_CACHE);
else if (!(vis->cut & SC_PRECIP)
&& vis->mobj->player && vis->mobj->player->dashmode >= DASHMODE_THRESHOLD
&& (vis->mobj->player->charflags & (SF_DASHMODE|SF_MACHINE)) == (SF_DASHMODE|SF_MACHINE)
&& (vis->mobj->player->charflags & SF_DASHMODE)
&& ((leveltime/2) & 1))
{
dc_translation = R_GetTranslationColormap(TC_DASHMODE, 0, GTC_CACHE);
if (vis->mobj->player->charflags & SF_MACHINE)
dc_translation = R_GetTranslationColormap(TC_DASHMODE, 0, GTC_CACHE);
else
dc_translation = R_GetTranslationColormap(TC_RAINBOW, vis->mobj->color, GTC_CACHE);
}
else if (!(vis->cut & SC_PRECIP) && vis->mobj->skin && vis->mobj->sprite == SPR_PLAY) // This thing is a player!
{
@ -2686,7 +2692,7 @@ UINT8 P_GetSkinSprite2(skin_t *skin, UINT8 spr2, player_t *player)
if ((playersprite_t)(spr2 & ~FF_SPR2SUPER) >= free_spr2)
return 0;
while (!(skin->sprites[spr2].numframes)
while (!skin->sprites[spr2].numframes
&& spr2 != SPR2_STND
&& ++i < 32) // recursion limiter
{
@ -2827,6 +2833,7 @@ boolean R_SkinUsable(INT32 playernum, INT32 skinnum)
|| (modeattacking) // If you have someone else's run you might as well take a look
|| (Playing() && (R_SkinAvailable(mapheaderinfo[gamemap-1]->forcecharacter) == skinnum)) // Force 1.
|| (netgame && (cv_forceskin.value == skinnum)) // Force 2.
|| (metalrecording && skinnum == 5) // Force 3.
);
}
@ -3315,7 +3322,7 @@ next_token:
#ifdef HWRENDER
if (rendermode == render_opengl)
HWR_AddPlayerMD2(numskins);
HWR_AddPlayerModel(numskins);
#endif
numskins++;

View file

@ -64,6 +64,8 @@ static void ModFilter_OnChange(void);
static lumpnum_t S_GetMusicLumpNum(const char *mname);
static boolean S_CheckQueue(void);
// commands for music and sound servers
#ifdef MUSSERV
consvar_t musserver_cmd = {"musserver_cmd", "musserver", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
@ -1613,13 +1615,14 @@ static void S_AddMusicStackEntry(const char *mname, UINT16 mflags, boolean loopi
if (!music_stacks)
{
music_stacks = Z_Calloc(sizeof (*mst), PU_MUSIC, NULL);
strncpy(music_stacks->musname, (status == JT_MASTER ? mname : mapmusname), 7);
music_stacks->musflags = (status == JT_MASTER ? mflags : mapmusflags);
music_stacks->looping = (status == JT_MASTER ? looping : true);
music_stacks->position = (status == JT_MASTER ? position : S_GetMusicPosition());
strncpy(music_stacks->musname, (status == JT_MASTER ? mname : (S_CheckQueue() ? queue_name : mapmusname)), 7);
music_stacks->musflags = (status == JT_MASTER ? mflags : (S_CheckQueue() ? queue_flags : mapmusflags));
music_stacks->looping = (status == JT_MASTER ? looping : (S_CheckQueue() ? queue_looping : true));
music_stacks->position = (status == JT_MASTER ? position : (S_CheckQueue() ? queue_position : S_GetMusicPosition()));
music_stacks->tic = gametic;
music_stacks->status = JT_MASTER;
music_stacks->mlumpnum = S_GetMusicLumpNum(music_stacks->musname);
music_stacks->noposition = S_CheckQueue();
if (status == JT_MASTER)
return; // we just added the user's entry here
@ -1638,6 +1641,7 @@ static void S_AddMusicStackEntry(const char *mname, UINT16 mflags, boolean loopi
new_mst->tic = gametic;
new_mst->status = status;
new_mst->mlumpnum = S_GetMusicLumpNum(new_mst->musname);
new_mst->noposition = false;
mst->next = new_mst;
new_mst->prev = mst;
@ -1745,11 +1749,23 @@ boolean S_RecallMusic(UINT16 status, boolean fromfirst)
entry->tic = gametic;
entry->status = JT_MASTER;
entry->mlumpnum = S_GetMusicLumpNum(entry->musname);
entry->noposition = false; // don't set this until we do the mapmuschanged check, below. Else, this breaks some resumes.
}
if (entry->status == JT_MASTER)
{
mapmuschanged = strnicmp(entry->musname, mapmusname, 7);
if (mapmuschanged)
{
strncpy(entry->musname, mapmusname, 7);
entry->musflags = mapmusflags;
entry->looping = true;
entry->position = mapmusposition;
entry->tic = gametic;
entry->status = JT_MASTER;
entry->mlumpnum = S_GetMusicLumpNum(entry->musname);
entry->noposition = true;
}
S_ResetMusicStack();
}
else if (!entry->status)
@ -1758,7 +1774,7 @@ boolean S_RecallMusic(UINT16 status, boolean fromfirst)
return false;
}
if (!mapmuschanged && strncmp(entry->musname, S_MusicName(), 7)) // don't restart music if we're already playing it
if (strncmp(entry->musname, S_MusicName(), 7)) // don't restart music if we're already playing it
{
if (music_stack_fadeout)
S_ChangeMusicEx(entry->musname, entry->musflags, entry->looping, 0, music_stack_fadeout, 0);
@ -1766,7 +1782,7 @@ boolean S_RecallMusic(UINT16 status, boolean fromfirst)
{
S_ChangeMusicEx(entry->musname, entry->musflags, entry->looping, 0, 0, music_stack_fadein);
if (!music_stack_noposition) // HACK: Global boolean to toggle position resuming, e.g., de-superize
if (!entry->noposition && !music_stack_noposition) // HACK: Global boolean to toggle position resuming, e.g., de-superize
{
UINT32 poslapse = 0;
@ -1908,6 +1924,11 @@ static void S_QueueMusic(const char *mmusic, UINT16 mflags, boolean looping, UIN
queue_fadeinms = fadeinms;
}
static boolean S_CheckQueue(void)
{
return queue_name[0];
}
static void S_ClearQueue(void)
{
queue_name[0] = queue_flags = queue_looping = queue_position = queue_fadeinms = 0;

View file

@ -220,6 +220,7 @@ typedef struct musicstack_s
tic_t tic;
UINT16 status;
lumpnum_t mlumpnum;
boolean noposition; // force music stack resuming from zero (like music_stack_noposition)
struct musicstack_s *prev;
struct musicstack_s *next;

View file

@ -229,6 +229,10 @@
<ClInclude Include="..\hardware\hw_light.h" />
<ClInclude Include="..\hardware\hw_main.h" />
<ClInclude Include="..\hardware\hw_md2.h" />
<ClInclude Include="..\hardware\hw_md2load.h" />
<ClInclude Include="..\hardware\hw_md3load.h" />
<ClInclude Include="..\hardware\hw_model.h" />
<ClInclude Include="..\hardware\u_list.h" />
<ClInclude Include="..\hu_stuff.h" />
<ClInclude Include="..\info.h" />
<ClInclude Include="..\i_addrinfo.h" />
@ -369,8 +373,12 @@
<ClCompile Include="..\hardware\hw_light.c" />
<ClCompile Include="..\hardware\hw_main.c" />
<ClCompile Include="..\hardware\hw_md2.c" />
<ClCompile Include="..\hardware\hw_md2load.c" />
<ClCompile Include="..\hardware\hw_md3load.c" />
<ClCompile Include="..\hardware\hw_model.c" />
<ClCompile Include="..\hardware\hw_trick.c" />
<ClCompile Include="..\hardware\r_opengl\r_opengl.c" />
<ClCompile Include="..\hardware\u_list.c" />
<ClCompile Include="..\hu_stuff.c" />
<ClCompile Include="..\info.c" />
<ClCompile Include="..\i_addrinfo.c">

View file

@ -246,6 +246,18 @@
<ClInclude Include="..\hardware\hw_md2.h">
<Filter>Hw_Hardware</Filter>
</ClInclude>
<ClInclude Include="..\hardware\hw_md2load.h">
<Filter>Hw_Hardware</Filter>
</ClInclude>
<ClInclude Include="..\hardware\hw_md3load.h">
<Filter>Hw_Hardware</Filter>
</ClInclude>
<ClInclude Include="..\hardware\hw_model.h">
<Filter>Hw_Hardware</Filter>
</ClInclude>
<ClInclude Include="..\hardware\u_list.h">
<Filter>Hw_Hardware</Filter>
</ClInclude>
<ClInclude Include="..\byteptr.h">
<Filter>I_Interface</Filter>
</ClInclude>
@ -633,9 +645,21 @@
<ClCompile Include="..\hardware\hw_md2.c">
<Filter>Hw_Hardware</Filter>
</ClCompile>
<ClCompile Include="..\hardware\hw_md2load.c">
<Filter>Hw_Hardware</Filter>
</ClCompile>
<ClCompile Include="..\hardware\hw_md3load.c">
<Filter>Hw_Hardware</Filter>
</ClCompile>
<ClCompile Include="..\hardware\hw_model.c">
<Filter>Hw_Hardware</Filter>
</ClCompile>
<ClCompile Include="..\hardware\hw_trick.c">
<Filter>Hw_Hardware</Filter>
</ClCompile>
<ClCompile Include="..\hardware\u_list.c">
<Filter>Hw_Hardware</Filter>
</ClCompile>
<ClCompile Include="..\filesrch.c">
<Filter>I_Interface</Filter>
</ClCompile>

View file

@ -88,13 +88,11 @@ void *hwSym(const char *funcName,void *handle)
GETFUNC(ClearMipMapCache);
GETFUNC(SetSpecialState);
GETFUNC(GetTextureUsed);
GETFUNC(DrawMD2);
GETFUNC(DrawMD2i);
GETFUNC(DrawModel);
GETFUNC(CreateModelVBOs);
GETFUNC(SetTransform);
GETFUNC(GetRenderVersion);
#ifdef SHUFFLE
GETFUNC(PostImgRedraw);
#endif //SHUFFLE
GETFUNC(FlushScreenTextures);
GETFUNC(StartScreenWipe);
GETFUNC(EndScreenWipe);

View file

@ -2181,7 +2181,7 @@ void I_Quit(void)
if (demorecording)
G_CheckDemoStatus();
if (metalrecording)
G_StopMetalRecording();
G_StopMetalRecording(false);
D_QuitNetGame();
I_ShutdownMusic();
@ -2299,7 +2299,7 @@ void I_Error(const char *error, ...)
if (demorecording)
G_CheckDemoStatus();
if (metalrecording)
G_StopMetalRecording();
G_StopMetalRecording(false);
D_QuitNetGame();
I_ShutdownMusic();

View file

@ -1654,13 +1654,11 @@ void I_StartupGraphics(void)
HWD.pfnSetSpecialState = hwSym("SetSpecialState",NULL);
HWD.pfnSetPalette = hwSym("SetPalette",NULL);
HWD.pfnGetTextureUsed = hwSym("GetTextureUsed",NULL);
HWD.pfnDrawMD2 = hwSym("DrawMD2",NULL);
HWD.pfnDrawMD2i = hwSym("DrawMD2i",NULL);
HWD.pfnDrawModel = hwSym("DrawModel",NULL);
HWD.pfnCreateModelVBOs = hwSym("CreateModelVBOs",NULL);
HWD.pfnSetTransform = hwSym("SetTransform",NULL);
HWD.pfnGetRenderVersion = hwSym("GetRenderVersion",NULL);
#ifdef SHUFFLE
HWD.pfnPostImgRedraw = hwSym("PostImgRedraw",NULL);
#endif
HWD.pfnFlushScreenTextures=hwSym("FlushScreenTextures",NULL);
HWD.pfnStartScreenWipe = hwSym("StartScreenWipe",NULL);
HWD.pfnEndScreenWipe = hwSym("EndScreenWipe",NULL);

View file

@ -693,7 +693,7 @@ sfxinfo_t S_sfx[NUMSFX] =
{"cdfm37", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"cdfm38", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Drowning"},
{"cdfm39", false, 128, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"cdfm40", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"cdfm40", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Power up"},
{"cdfm41", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"cdfm42", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"cdfm43", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
@ -780,7 +780,7 @@ sfxinfo_t S_sfx[NUMSFX] =
{"kc4a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"kc4b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"kc4c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"kc4d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"kc4d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Power up"},
{"kc4e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"kc4f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"kc50", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
@ -804,7 +804,7 @@ sfxinfo_t S_sfx[NUMSFX] =
{"kc62", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"kc63", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"kc64", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Terrifying rumble"},
{"kc65", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"kc65", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Power down"},
{"kc66", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"kc67", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"kc68", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},

View file

@ -837,7 +837,13 @@ static void ST_drawLivesArea(void)
}
// Lives number
if (G_GametypeUsesLives() || gametype == GT_RACE)
if (metalrecording)
{
if (((2*leveltime)/TICRATE) & 1)
V_DrawRightAlignedString(hudinfo[HUD_LIVES].x+58, hudinfo[HUD_LIVES].y+8,
hudinfo[HUD_LIVES].f|V_PERPLAYER|V_REDMAP|V_HUDTRANS, "REC");
}
else if (G_GametypeUsesLives() || gametype == GT_RACE)
{
// x
V_DrawScaledPatch(hudinfo[HUD_LIVES].x+22, hudinfo[HUD_LIVES].y+10,

View file

@ -89,8 +89,8 @@ static void CV_Gammaxxx_ONChange(void);
// but they won't do anything.
static CV_PossibleValue_t grgamma_cons_t[] = {{1, "MIN"}, {255, "MAX"}, {0, NULL}};
static CV_PossibleValue_t grsoftwarefog_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "LightPlanes"}, {0, NULL}};
static CV_PossibleValue_t grmodelinterpolation_cons_t[] = {{0, "Off"}, {1, "Sometimes"}, {2, "Always"}, {0, NULL}};
consvar_t cv_voodoocompatibility = {"gr_voodoocompatibility", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_grfovchange = {"gr_fovchange", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_grfog = {"gr_fog", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_grfogcolor = {"gr_fogcolor", "AAAAAA", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
@ -108,9 +108,9 @@ consvar_t cv_grcoronas = {"gr_coronas", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL,
consvar_t cv_grcoronasize = {"gr_coronasize", "1", CV_SAVE| CV_FLOAT, 0, NULL, 0, NULL, NULL, 0, 0, NULL};
#endif
static CV_PossibleValue_t CV_MD2[] = {{0, "Off"}, {1, "On"}, {2, "Old"}, {0, NULL}};
// console variables in development
consvar_t cv_grmd2 = {"gr_md2", "Off", CV_SAVE, CV_MD2, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_grmodels = {"gr_models", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_grmodelinterpolation = {"gr_modelinterpolation", "Sometimes", CV_SAVE, grmodelinterpolation_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_grspritebillboarding = {"gr_spritebillboarding", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_grskydome = {"gr_skydome", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
#endif

View file

@ -1665,12 +1665,12 @@ void W_VerifyFileMD5(UINT16 wadfilenum, const char *matchmd5)
{
char actualmd5text[2*MD5_LEN+1];
PrintMD5String(wadfiles[wadfilenum]->md5sum, actualmd5text);
#ifdef _DEBUG
/*#ifdef _DEBUG
CONS_Printf
#else
I_Error
#endif
(M_GetText("File is corrupt or has been modified: %s (found md5: %s, wanted: %s)\n"), wadfiles[wadfilenum]->filename, actualmd5text, matchmd5);
(M_GetText("File is corrupt or has been modified: %s (found md5: %s, wanted: %s)\n"), wadfiles[wadfilenum]->filename, actualmd5text, matchmd5);*/
}
#endif
}

View file

@ -231,7 +231,11 @@
<ClCompile Include="..\hardware\hw_light.c" />
<ClCompile Include="..\hardware\hw_main.c" />
<ClCompile Include="..\hardware\hw_md2.c" />
<ClCompile Include="..\hardware\hw_md2load.c" />
<ClCompile Include="..\hardware\hw_md3load.c" />
<ClCompile Include="..\hardware\hw_model.c" />
<ClCompile Include="..\hardware\hw_trick.c" />
<ClCompile Include="..\hardware\u_list.c" />
<ClCompile Include="..\hu_stuff.c" />
<ClCompile Include="..\info.c" />
<ClCompile Include="..\i_addrinfo.c">
@ -397,6 +401,10 @@
<ClInclude Include="..\hardware\hw_light.h" />
<ClInclude Include="..\hardware\hw_main.h" />
<ClInclude Include="..\hardware\hw_md2.h" />
<ClInclude Include="..\hardware\hw_md2load.h" />
<ClInclude Include="..\hardware\hw_md3load.h" />
<ClInclude Include="..\hardware\hw_model.h" />
<ClInclude Include="..\hardware\u_list.h" />
<ClInclude Include="..\hu_stuff.h" />
<ClInclude Include="..\info.h" />
<ClInclude Include="..\i_addrinfo.h" />

View file

@ -453,6 +453,18 @@
<ClCompile Include="..\string.c">
<Filter>M_Misc</Filter>
</ClCompile>
<ClCompile Include="..\hardware\hw_md2load.c">
<Filter>Hw_Hardware</Filter>
</ClCompile>
<ClCompile Include="..\hardware\hw_md3load.c">
<Filter>Hw_Hardware</Filter>
</ClCompile>
<ClCompile Include="..\hardware\hw_model.c">
<Filter>Hw_Hardware</Filter>
</ClCompile>
<ClCompile Include="..\hardware\u_list.c">
<Filter>Hw_Hardware</Filter>
</ClCompile>
<ClCompile Include="..\hardware\hw_clip.c">
<Filter>Hw_Hardware</Filter>
</ClCompile>
@ -516,6 +528,15 @@
<ClInclude Include="..\hardware\hw_md2.h">
<Filter>Hw_Hardware</Filter>
</ClInclude>
<ClInclude Include="..\hardware\hw_md2load.h">
<Filter>Hw_Hardware</Filter>
</ClInclude>
<ClInclude Include="..\hardware\hw_md3load.h">
<Filter>Hw_Hardware</Filter>
</ClInclude>
<ClInclude Include="..\hardware\hw_model.h">
<Filter>Hw_Hardware</Filter>
</ClInclude>
<ClInclude Include="..\hardware\hw3dsdrv.h">
<Filter>Hw_Hardware</Filter>
</ClInclude>
@ -525,6 +546,9 @@
<ClInclude Include="..\hardware\hws_data.h">
<Filter>Hw_Hardware</Filter>
</ClInclude>
<ClInclude Include="..\hardware\u_list.h">
<Filter>Hw_Hardware</Filter>
</ClInclude>
<ClInclude Include="..\blua\lapi.h">
<Filter>BLUA</Filter>
</ClInclude>

View file

@ -110,8 +110,7 @@ static loadfunc_t hwdFuncTable[] = {
{"GClipRect@20", &hwdriver.pfnGClipRect},
{"ClearMipMapCache@0", &hwdriver.pfnClearMipMapCache},
{"SetSpecialState@8", &hwdriver.pfnSetSpecialState},
{"DrawMD2@16", &hwdriver.pfnDrawMD2},
{"DrawMD2i@36", &hwdriver.pfnDrawMD2i},
{"DrawModel@16", &hwdriver.pfnDrawModel},
{"SetTransform@4", &hwdriver.pfnSetTransform},
{"GetTextureUsed@0", &hwdriver.pfnGetTextureUsed},
{"GetRenderVersion@0", &hwdriver.pfnGetRenderVersion},
@ -142,8 +141,7 @@ static loadfunc_t hwdFuncTable[] = {
{"GClipRect", &hwdriver.pfnGClipRect},
{"ClearMipMapCache", &hwdriver.pfnClearMipMapCache},
{"SetSpecialState", &hwdriver.pfnSetSpecialState},
{"DrawMD2", &hwdriver.pfnDrawMD2},
{"DrawMD2i", &hwdriver.pfnDrawMD2i},
{"DrawModel", &hwdriver.pfnDrawModel},
{"SetTransform", &hwdriver.pfnSetTransform},
{"GetTextureUsed", &hwdriver.pfnGetTextureUsed},
{"GetRenderVersion", &hwdriver.pfnGetRenderVersion},

View file

@ -647,7 +647,7 @@ void I_Error(const char *error, ...)
if (demorecording)
G_CheckDemoStatus();
if (metalrecording)
G_StopMetalRecording();
G_StopMetalRecording(false);
D_QuitNetGame();
@ -733,7 +733,7 @@ void I_Quit(void)
if (demorecording)
G_CheckDemoStatus();
if (metalrecording)
G_StopMetalRecording();
G_StopMetalRecording(false);
M_SaveConfig(NULL); // save game config, cvars..
#ifndef NONET