Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision

Target

Select target project
  • STJr/SRB2
  • Sryder/SRB2
  • wolfy852/SRB2
  • Alpha2244/SRB2
  • Inuyasha/SRB2
  • yoshibot/SRB2
  • TehRealSalt/SRB2
  • PrisimaTF/SRB2
  • Hatninja/SRB2
  • SteelT/SRB2
  • james/SRB2
  • ShaderWraith/SRB2
  • SinnamonLat/SRB2
  • mazmazz_/SRB2
  • filpAM/SRB2
  • chaoloveicemdboy/SRB2
  • Whooa21/SRB2
  • Machturne/SRB2
  • Golden/SRB2
  • Tatsuru/SRB2
  • Snu/SRB2
  • Zwip-Zwap_Zapony/SRB2
  • fickleheart/SRB2
  • alphaRexJames/SRB2
  • JJK/SRB2
  • diskpoppy/SRB2
  • Hannu_Hanhi/SRB2
  • ZipperQR/SRB2
  • kays/SRB2
  • spherallic/SRB2
  • Zippy_Zolton/SRB2
  • namiishere/SRB2
  • Ors/SRB2
  • SMS_Alfredo/SRB2
  • sonic_edge/SRB2
  • lavla/SRB2
  • ashi/SRB2
  • X.organic/SRB2
  • Fafabis/SRB2
  • Meziu/SRB2
  • v-rob/SRB2
  • tertu/SRB2
  • bitten2up/SRB2
  • flarn2006/SRB2
  • Krabs/SRB2
  • clairebun/SRB2
  • Lactozilla/SRB2
  • thehackstack/SRB2
  • Spice/SRB2
  • win8linux/SRB2
  • JohnFrostFox/SRB2
  • talktoneon726/SRB2
  • Wane/SRB2
  • Lamibe/SRB2
  • spectrumuk2/srb-2
  • nerdyminer18/srb-2
  • 256nil/SRB2
  • ARJr/SRB2
  • Alam/SRB2
  • Zenya/srb-2-marathon-demos
  • Acelite/srb-2-archivedmodifications
  • MIDIMan/SRB2
  • Lach/SRB2
  • Frostiikin/bounce-tweaks
  • Jaden/SRB2
  • Tyron/SRB2
  • Astronight/SRB2
  • Mari0shi06/SRB2
  • aiire/SRB2
  • Galactice/SRB2
  • srb2-ports/srb2-dreamcast
  • sdasdas/SRB2
  • chreas/srb-2-vr
  • StarManiaKG/the-story-of-sinically-rocketing-and-botching-the-2nd
  • LoganAir/SRB2
  • NepDisk/srb-2
  • alufolie91/SRB2
  • Felicia.iso/SRB2
  • twi/SRB2
  • BarrelsOFun/SRB2
  • Speed2411/SRB2
  • Leather_Realms/SRB2
  • Ayemar/SRB2
  • Acelite/SRB2
  • VladDoc/SRB2
  • kaldrum/model-features
  • strawberryfox417/SRB2
  • Lugent/SRB2
  • Jisk/SRB2
  • Rem/SRB2
  • Refrag/SRB2
  • Henry_3230/srb-3230
  • TehPuertoRicanSpartan2/tprs-srb2
  • Leminn/srb-2-marathon-stuff
  • chromaticpipe2/SRB2
  • MiguelGustavo15/SRB2
  • Maru/srb-2-tests
  • SilicDev/SRB2
  • UnmatchedBracket/SRB2
  • HybridDog/SRB2
  • xordspar0/SRB2
  • jsjhbewfhh/SRB2
  • Fancy2209/SRB2
  • Lorsoen/SRB2
  • shindoukin/SRB2
  • GamerOfDays/SRB2
  • Craftyawesome/SRB2
  • tenshi-tensai-tennoji/SRB2
  • Scarfdudebalder/SRB2
  • luigi-budd/srb-2-fix-interplag-lockon
  • mskluesner/SRB2
  • johnpetersa19/SRB2
  • Pheazant/SRB2
  • chromaticpipe2/srb2classic
  • romoney5/SRB2
  • PAS/SRB2Classic
  • BlueStaggo/SRB2
117 results
Select Git revision
Show changes
Commits on Source (16)
......@@ -52,6 +52,7 @@ p_telept.c
p_tick.c
p_user.c
p_slopes.c
p_world.c
tables.c
r_bsp.c
r_data.c
......
......@@ -529,6 +529,10 @@ boolean B_CheckRespawn(player_t *player)
return false;
}
// Not even in the same world?
if (P_GetMobjWorld(sonic) != P_GetMobjWorld(tails))
return true;
// If you can't see Sonic, I guess we should?
if (!P_CheckSight(sonic, tails) && P_AproxDistance(P_AproxDistance(tails->x-sonic->x, tails->y-sonic->y), tails->z-sonic->z) > FixedMul(1024*FRACUNIT, tails->scale))
return true;
......
......@@ -1394,9 +1394,9 @@ static void SV_SendServerInfo(INT32 node, tic_t servertime)
memset(netbuffer->u.serverinfo.maptitle, 0, sizeof netbuffer->u.serverinfo.maptitle);
if (mapheaderinfo[gamemap-1] && *mapheaderinfo[gamemap-1]->lvlttl)
if (worldmapheader && *worldmapheader->lvlttl)
{
char *read = mapheaderinfo[gamemap-1]->lvlttl, *writ = netbuffer->u.serverinfo.maptitle;
char *read = worldmapheader->lvlttl, *writ = netbuffer->u.serverinfo.maptitle;
while (writ < (netbuffer->u.serverinfo.maptitle+32) && *read != '\0')
{
if (!(*read & 0x80))
......@@ -1407,18 +1407,18 @@ static void SV_SendServerInfo(INT32 node, tic_t servertime)
read++;
}
*writ = '\0';
//strncpy(netbuffer->u.serverinfo.maptitle, (char *)mapheaderinfo[gamemap-1]->lvlttl, 33);
//strncpy(netbuffer->u.serverinfo.maptitle, (char *)worldmapheader->lvlttl, 33);
}
else
strncpy(netbuffer->u.serverinfo.maptitle, "UNKNOWN", 32);
if (mapheaderinfo[gamemap-1] && !(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE))
if (worldmapheader && !(worldmapheader->levelflags & LF_NOZONE))
netbuffer->u.serverinfo.iszone = 1;
else
netbuffer->u.serverinfo.iszone = 0;
if (mapheaderinfo[gamemap-1])
netbuffer->u.serverinfo.actnum = mapheaderinfo[gamemap-1]->actnum;
if (worldmapheader)
netbuffer->u.serverinfo.actnum = worldmapheader->actnum;
p = PutFileNeeded(0);
......@@ -1540,7 +1540,7 @@ static boolean SV_SendServerConfig(INT32 node)
}
#ifndef NONET
#define SAVEGAMESIZE (768*1024)
#define SAVEGAMESIZE (8192*1024) // was (768*1024)
static boolean SV_ResendingSavegameToAnyone(void)
{
......@@ -1706,12 +1706,12 @@ static void CL_LoadReceivedSavegame(boolean reloading)
// load a base level
if (P_LoadNetGame(reloading))
{
const UINT8 actnum = mapheaderinfo[gamemap-1]->actnum;
const UINT8 actnum = worldmapheader->actnum;
CONS_Printf(M_GetText("Map is now \"%s"), G_BuildMapName(gamemap));
if (strcmp(mapheaderinfo[gamemap-1]->lvlttl, ""))
if (strcmp(worldmapheader->lvlttl, ""))
{
CONS_Printf(": %s", mapheaderinfo[gamemap-1]->lvlttl);
if (!(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE))
CONS_Printf(": %s", worldmapheader->lvlttl);
if (!(worldmapheader->levelflags & LF_NOZONE))
CONS_Printf(M_GetText(" Zone"));
if (actnum > 0)
CONS_Printf(" %2d", actnum);
......@@ -2885,6 +2885,9 @@ void CL_RemovePlayer(INT32 playernum, kickreason_t reason)
}
}
if (players[playernum].world)
((world_t *)players[playernum].world)->players--;
if (gametyperules & GTR_TEAMFLAGS)
P_PlayerFlagBurst(&players[playernum], false); // Don't take the flag with you!
......
......@@ -342,7 +342,7 @@ typedef struct
extern serverelem_t serverlist[MAXSERVERLIST];
extern UINT32 serverlistcount;
extern INT32 mapchangepending;
extern boolean mapchangepending;
// Points inside doomcom
extern doomdata_t *netbuffer;
......
......@@ -298,6 +298,31 @@ gamestate_t wipegamestate = GS_LEVEL;
INT16 wipetypepre = -1;
INT16 wipetypepost = -1;
static void D_RenderView(UINT32 viewnum)
{
player_t *player = viewnum == 1 ? &players[secondarydisplayplayer] : &players[displayplayer];
R_PrepareViewWorld(player);
if (viewworld == NULL)
return;
R_ApplyLevelInterpolators(viewworld, R_UsingFrameInterpolation() ? rendertimefrac : FRACUNIT);
if (player->mo || player->playerstate == PST_DEAD)
{
R_SetViewNum(viewnum);
#ifdef HWRENDER
if (rendermode != render_soft)
HWR_RenderPlayerView(viewnum, player);
else
#endif
if (rendermode != render_none)
R_RenderPlayerView(player);
}
}
static void D_Display(void)
{
boolean forcerefresh = false;
......@@ -478,41 +503,19 @@ static void D_Display(void)
if (!automapactive && !dedicated && cv_renderview.value)
{
R_ApplyLevelInterpolators(R_UsingFrameInterpolation() ? rendertimefrac : FRACUNIT);
PS_START_TIMING(ps_rendercalltime);
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]));
objectsdrawn = 0;
topleft = screens[0] + viewwindowy*vid.width + viewwindowx;
D_RenderView(0);
R_RenderPlayerView(&players[secondarydisplayplayer]);
// render the second screen
if (splitscreen)
D_RenderView(1);
viewwindowy = 0;
M_Memcpy(ylookup, ylookup1, viewheight*sizeof (ylookup[0]));
}
for (INT32 wi = 0; wi < numworlds; wi++)
{
R_RestoreLevelInterpolators(worldlist[wi]);
worldlist[wi]->interpolated_level_this_frame = false;
}
// Image postprocessing effect
......@@ -527,7 +530,6 @@ static void D_Display(void)
V_DoPostProcessor(1, postimgtype2, postimgparam2);
}
PS_STOP_TIMING(ps_rendercalltime);
R_RestoreLevelInterpolators();
}
if (lastdraw)
......
......@@ -64,7 +64,9 @@
static void Got_NameAndColor(UINT8 **cp, INT32 playernum);
static void Got_WeaponPref(UINT8 **cp, INT32 playernum);
static void Got_Mapcmd(UINT8 **cp, INT32 playernum);
static void Got_Newworld(UINT8 **cp, INT32 playernum);
static void Got_ExitLevelcmd(UINT8 **cp, INT32 playernum);
static void Got_Switchworld(UINT8 **cp, INT32 playernum);
static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum);
static void Got_RequestAddfoldercmd(UINT8 **cp, INT32 playernum);
static void Got_Addfilecmd(UINT8 **cp, INT32 playernum);
......@@ -416,6 +418,7 @@ const char *netxcmdnames[MAXNETXCMD - 1] =
"ADDPLAYER",
"TEAMCHANGE",
"CLEARSCORES",
"SWITCHWORLD",
"VERIFIED",
"RANDOMSEED",
"RUNSOC",
......@@ -452,7 +455,9 @@ void D_RegisterServerCommands(void)
RegisterNetXCmd(XD_NAMEANDCOLOR, Got_NameAndColor);
RegisterNetXCmd(XD_WEAPONPREF, Got_WeaponPref);
RegisterNetXCmd(XD_MAP, Got_Mapcmd);
RegisterNetXCmd(XD_NEWWORLD, Got_Newworld);
RegisterNetXCmd(XD_EXITLEVEL, Got_ExitLevelcmd);
RegisterNetXCmd(XD_SWITCHWORLD, Got_Switchworld);
RegisterNetXCmd(XD_ADDFILE, Got_Addfilecmd);
RegisterNetXCmd(XD_ADDFOLDER, Got_Addfoldercmd);
RegisterNetXCmd(XD_REQADDFILE, Got_RequestAddfilecmd);
......@@ -480,6 +485,8 @@ void D_RegisterServerCommands(void)
RegisterNetXCmd(XD_CLEARSCORES, Got_Clearscores);
COM_AddCommand("clearscores", Command_Clearscores_f, COM_LUA);
COM_AddCommand("map", Command_Map_f, COM_LUA);
COM_AddCommand("switchworld", Command_Switchworld_f, COM_LUA);
COM_AddCommand("listworlds", Command_Listworlds_f, COM_LUA);
COM_AddCommand("exitgame", Command_ExitGame_f, COM_LUA);
COM_AddCommand("retry", Command_Retry_f, COM_LUA);
......@@ -1158,7 +1165,7 @@ UINT8 CanChangeSkin(INT32 playernum)
return true;
// Force skin in effect.
if ((cv_forceskin.value != -1) || (mapheaderinfo[gamemap-1] && mapheaderinfo[gamemap-1]->forcecharacter[0] != '\0'))
if ((cv_forceskin.value != -1) || (worldmapheader && worldmapheader->forcecharacter[0] != '\0'))
return false;
// Can change skin in intermission and whatnot.
......@@ -1728,7 +1735,7 @@ static void Command_StopMovie_f(void)
M_StopMovie();
}
INT32 mapchangepending = 0;
boolean mapchangepending = false;
/** Runs a map change.
* The supplied data are assumed to be good. If provided by a user, they will
......@@ -1812,10 +1819,11 @@ void D_MapChange(INT32 mapnum, INT32 newgametype, boolean pultmode, boolean rese
}
if (delay == 1)
mapchangepending = 1;
mapchangepending = true;
else
{
mapchangepending = 0;
mapchangepending = false;
// spawn the server if needed
// reset players if there is a new one
if (!IsPlayerAdmin(consoleplayer))
......@@ -1833,6 +1841,22 @@ void D_MapChange(INT32 mapnum, INT32 newgametype, boolean pultmode, boolean rese
}
}
// Sends a command to add a new world.
// It's as simple as that.
void D_AddWorld(INT32 mapnum)
{
char buf[MAX_WADPATH+1];
char *buf_p = buf;
CONS_Debug(DBG_GAMELOGIC, "New world: mapnum=%d\n", mapnum);
I_Assert(W_CheckNumForName(mapname) != LUMPERROR);
WRITESTRINGN(buf_p, G_BuildMapName(mapnum), MAX_WADPATH);
SendNetXCmd(XD_NEWWORLD, buf, buf_p - buf);
}
static char *
ConcatCommandArgv (int start, int end)
{
......@@ -1893,7 +1917,9 @@ static void Command_Map_f(void)
INT32 d;
if (client && !IsPlayerAdmin(consoleplayer))
boolean addworld = COM_CheckParm("-addworld");
if (client && !addworld && !IsPlayerAdmin(consoleplayer))
{
CONS_Printf(M_GetText("Only the server or a remote admin can use this.\n"));
return;
......@@ -2058,7 +2084,10 @@ static void Command_Map_f(void)
}
tutorialmode = false; // warping takes us out of tutorial mode
D_MapChange(newmapnum, newgametype, false, newresetplayers, 0, false, fromlevelselect);
if (addworld)
D_AddWorld(newmapnum);
else
D_MapChange(newmapnum, newgametype, false, newresetplayers, 0, false, fromlevelselect);
Z_Free(realmapname);
}
......@@ -2078,6 +2107,8 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum)
UINT8 skipprecutscene, FLS;
INT16 mapnumber;
flags = READUINT8(*cp);
if (playernum != serverplayer && !IsPlayerAdmin(playernum))
{
CONS_Alert(CONS_WARNING, M_GetText("Illegal map change received from %s\n"), player_names[playernum]);
......@@ -2089,8 +2120,6 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum)
if (chmappending)
chmappending--;
flags = READUINT8(*cp);
ultimatemode = ((flags & 1) != 0);
if (netgame || multiplayer)
ultimatemode = false;
......@@ -2141,7 +2170,7 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum)
mapnumber = M_MapNumber(mapname[3], mapname[4]);
LUA_HookInt(mapnumber, HOOK(MapChange));
G_InitNew(ultimatemode, mapname, resetplayer, skipprecutscene, FLS);
G_InitNew(mapname, ultimatemode, resetplayer, skipprecutscene, FLS);
if (demoplayback && !timingdemo)
precache = true;
if (timingdemo)
......@@ -2154,6 +2183,97 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum)
demo_start = true;
}
/** Receives a new world command and creates a new one.
*
* \param cp Data buffer.
* \param playernum Player number responsible for the message.
* \sa D_MapChange
*/
static void Got_Newworld(UINT8 **cp, INT32 playernum)
{
(void)playernum;
char mapname[MAX_WADPATH+1];
READSTRINGN(*cp, mapname, MAX_WADPATH);
DEBFILE(va("Adding world with map %s\n", mapname));
G_LoadWorld(mapname);
}
void SendWorldSwitch(INT32 worldnum, void *location, boolean nodetach)
{
UINT8 buf[sizeof(INT32) + sizeof(UINT8) + (sizeof(fixed_t) * 3) + sizeof(angle_t)];
UINT8 *p = buf;
UINT8 flags = 0;
if (location != NULL)
flags |= 1;
if (nodetach)
flags |= 2;
WRITEINT32(p, worldnum);
WRITEUINT8(p, flags);
if (flags & 1)
{
location_t *loc = (location_t *)location;
WRITEFIXED(p, loc->x);
WRITEFIXED(p, loc->y);
WRITEFIXED(p, loc->z);
WRITEANGLE(p, loc->angle);
}
else
{
WRITEFIXED(p, 0);
WRITEFIXED(p, 0);
WRITEFIXED(p, 0);
WRITEANGLE(p, 0);
}
SendNetXCmd(XD_SWITCHWORLD, buf, sizeof(buf));
}
static void Got_Switchworld(UINT8 **cp, INT32 playernum)
{
player_t *player = &players[playernum];
INT32 worldnum = READINT32(*cp);
UINT8 flags = READUINT8(*cp);
location_t location;
location.x = READFIXED(*cp);
location.y = READFIXED(*cp);
location.z = READFIXED(*cp);
location.angle = READANGLE(*cp);
if (worldnum >= numworlds)
{
CONS_Alert(CONS_WARNING, M_GetText("Illegal world switch command received from %s\n"), player_names[playernum]);
if (server)
SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
return;
}
// Don't detach from the current world, if any
if (flags & 2)
{
world_t *w = player->world;
if (w != NULL)
w->players--;
player->world = NULL;
}
if (flags & 1)
{
P_SwitchWorld(player, worldlist[worldnum], &location);
}
else
{
P_SwitchWorld(player, worldlist[worldnum], NULL);
}
}
static void Command_Pause(void)
{
UINT8 buf[2];
......@@ -4329,7 +4449,8 @@ static void Gravity_OnChange(void)
if (!CV_IsSetToDefault(&cv_gravity))
G_SetUsedCheats(false);
gravity = cv_gravity.value;
if (world)
world->gravity = cv_gravity.value;
}
static void SoundTest_OnChange(void)
......@@ -4522,10 +4643,10 @@ static void Command_Showmap_f(void)
{
if (gamestate == GS_LEVEL)
{
if (mapheaderinfo[gamemap-1]->actnum)
CONS_Printf("%s (%d): %s %d\n", G_BuildMapName(gamemap), gamemap, mapheaderinfo[gamemap-1]->lvlttl, mapheaderinfo[gamemap-1]->actnum);
if (worldmapheader->actnum)
CONS_Printf("%s (%d): %s %d\n", G_BuildMapName(gamemap), gamemap, worldmapheader->lvlttl, worldmapheader->actnum);
else
CONS_Printf("%s (%d): %s\n", G_BuildMapName(gamemap), gamemap, mapheaderinfo[gamemap-1]->lvlttl);
CONS_Printf("%s (%d): %s\n", G_BuildMapName(gamemap), gamemap, worldmapheader->lvlttl);
}
else
CONS_Printf(M_GetText("You must be in a level to use this.\n"));
......
......@@ -130,23 +130,25 @@ typedef enum
XD_SAY, // 5
XD_MAP, // 6
XD_EXITLEVEL, // 7
XD_ADDFILE, // 8
XD_ADDFOLDER, // 9
XD_PAUSE, // 10
XD_ADDPLAYER, // 11
XD_TEAMCHANGE, // 12
XD_CLEARSCORES, // 13
XD_VERIFIED, // 14
XD_RANDOMSEED, // 15
XD_RUNSOC, // 16
XD_REQADDFILE, // 17
XD_REQADDFOLDER,// 18
XD_SETMOTD, // 19
XD_SUICIDE, // 20
XD_DEMOTED, // 21
XD_LUACMD, // 22
XD_LUAVAR, // 23
XD_LUAFILE, // 24
XD_NEWWORLD, // 8
XD_SWITCHWORLD, // 9
XD_ADDFILE, // 10
XD_ADDFOLDER, // 11
XD_PAUSE, // 12
XD_ADDPLAYER, // 13
XD_TEAMCHANGE, // 14
XD_CLEARSCORES, // 15
XD_VERIFIED, // 16
XD_RANDOMSEED, // 17
XD_RUNSOC, // 18
XD_REQADDFILE, // 19
XD_REQADDFOLDER,// 20
XD_SETMOTD, // 21
XD_SUICIDE, // 22
XD_DEMOTED, // 23
XD_LUACMD, // 24
XD_LUAVAR, // 25
XD_LUAFILE, // 26
MAXNETXCMD
} netxcmd_t;
......@@ -202,12 +204,14 @@ void Command_ExitGame_f(void);
void Command_Retry_f(void);
void D_GameTypeChanged(INT32 lastgametype); // not a real _OnChange function anymore
void D_MapChange(INT32 pmapnum, INT32 pgametype, boolean pultmode, boolean presetplayers, INT32 pdelay, boolean pskipprecutscene, boolean pfromlevelselect);
void D_AddWorld(INT32 pmapnum);
boolean IsPlayerAdmin(INT32 playernum);
void SetAdminPlayer(INT32 playernum);
void ClearAdminPlayers(void);
void RemoveAdminPlayer(INT32 playernum);
void ItemFinder_OnChange(void);
void D_SetPassword(const char *pw);
void SendWorldSwitch(INT32 worldnum, void *location, boolean nodetach);
// used for the player setup menu
UINT8 CanChangeSkin(INT32 playernum);
......
......@@ -360,6 +360,9 @@ typedef struct player_s
playerstate_t playerstate;
void *world;
INT32 worldnum; // Lactozilla: for unarchiving purposes only, just like mobjnum
// Determine POV, including viewpoint bobbing during movement.
fixed_t camerascale;
fixed_t shieldscale;
......
......@@ -403,6 +403,10 @@ extern skincolor_t skincolors[MAXSKINCOLORS];
#define PUSHACCEL (2*FRACUNIT) // Acceleration for MF2_SLIDEPUSH items.
// Time interval for item respawning.
// WARNING MUST be a power of 2
#define ITEMQUESIZE 1024
// Special linedef executor tag numbers! Binary map format only (UDMF has other ways of doing these things).
enum {
LE_PINCHPHASE = -2, // A boss entered pinch phase (and, in most cases, is preparing their pinch phase attack!)
......@@ -632,13 +636,6 @@ extern const char *compdate, *comptime, *comprevision, *compbranch;
/// Experimental attempts at preventing MF_PAPERCOLLISION objects from getting stuck in walls.
//#define PAPER_COLLISIONCORRECTION
/// FINALLY some real clipping that doesn't make walls dissappear AND speeds the game up
/// (that was the original comment from SRB2CB, sadly it is a lie and actually slows game down)
/// on the bright side it fixes some weird issues with translucent walls
/// \note SRB2CB port.
/// SRB2CB itself ported this from PrBoom+
#define NEWCLIP
/// OpenGL shaders
#define GL_SHADERS
......
......@@ -40,7 +40,6 @@ extern UINT32 mapmusposition;
// Use other bits if necessary.
extern UINT32 maptol;
extern UINT8 globalweather;
extern INT32 curWeather;
extern INT32 cursaveslot;
//extern INT16 lastmapsaved;
......@@ -389,6 +388,10 @@ typedef struct
extern mapheader_t* mapheaderinfo[NUMMAPS];
extern mapheader_t* curmapheader;
extern mapheader_t* nextmapheader;
extern mapheader_t* worldmapheader;
// Gametypes
#define NUMGAMETYPEFREESLOTS 128
enum GameType
......@@ -549,14 +552,12 @@ extern UINT8 useContinues;
extern UINT8 shareEmblems;
extern mobj_t *hunt1, *hunt2, *hunt3; // Emerald hunt locations
#define NUM_EMERALD_HUNT_LOCATIONS 3
// For racing
extern UINT32 countdown;
extern UINT32 countdown2;
extern fixed_t gravity;
//for CTF balancing
extern INT16 autobalance;
extern INT16 teamscramble;
......@@ -579,16 +580,6 @@ extern tic_t hidetime;
extern tic_t gametic;
#define localgametic leveltime
// Player spawn spots.
extern mapthing_t *playerstarts[MAXPLAYERS]; // Cooperative
extern mapthing_t *bluectfstarts[MAXPLAYERS]; // CTF
extern mapthing_t *redctfstarts[MAXPLAYERS]; // CTF
#define WAYPOINTSEQUENCESIZE 256
#define NUMWAYPOINTSEQUENCES 256
extern mobj_t *waypoints[NUMWAYPOINTSEQUENCES][WAYPOINTSEQUENCESIZE];
extern UINT16 numwaypoints[NUMWAYPOINTSEQUENCES];
void P_AddWaypoint(UINT8 sequence, UINT8 id, mobj_t *waypoint);
mobj_t *P_GetFirstWaypoint(UINT8 sequence);
mobj_t *P_GetLastWaypoint(UINT8 sequence);
......
......@@ -2429,8 +2429,11 @@ void F_StartTitleScreen(void)
if (!mapheaderinfo[gamemap-1])
P_AllocMapHeader(gamemap-1);
maptol = mapheaderinfo[gamemap-1]->typeoflevel;
globalweather = mapheaderinfo[gamemap-1]->weather;
World_UnloadAll();
curmapheader = nextmapheader = mapheaderinfo[gamemap-1];
worldmapheader = curmapheader;
maptol = curmapheader->typeoflevel;
G_DoLoadLevel(true);
if (!titlemap)
......@@ -2439,10 +2442,10 @@ void F_StartTitleScreen(void)
players[displayplayer].playerstate = PST_DEAD; // Don't spawn the player in dummy (I'm still a filthy cheater)
// Set Default Position
if (playerstarts[0])
startpos = playerstarts[0];
else if (deathmatchstarts[0])
startpos = deathmatchstarts[0];
if (world->playerstarts[0])
startpos = world->playerstarts[0];
else if (world->deathmatchstarts[0])
startpos = world->deathmatchstarts[0];
else
startpos = NULL;
......@@ -2476,6 +2479,8 @@ void F_StartTitleScreen(void)
gamemap = 1; // g_game.c
if (!mapheaderinfo[gamemap-1])
P_AllocMapHeader(gamemap-1);
curmapheader = nextmapheader = mapheaderinfo[gamemap-1];
worldmapheader = curmapheader;
CON_ClearHUD();
}
......
......@@ -1868,6 +1868,8 @@ void G_DoPlayDemo(char *defdemoname)
}
demo_p += 4; // "PLAY"
gamemap = READINT16(demo_p);
curmapheader = nextmapheader = mapheaderinfo[gamemap-1];
worldmapheader = curmapheader;
demo_p += 16; // mapmd5
demoflags = READUINT8(demo_p);
......@@ -1983,7 +1985,7 @@ void G_DoPlayDemo(char *defdemoname)
memset(playeringame,0,sizeof(playeringame));
playeringame[0] = true;
P_SetRandSeed(randseed);
G_InitNew(false, G_BuildMapName(gamemap), true, true, false);
G_InitNew(G_BuildMapName(gamemap), false, true, true, false);
// Set color
players[0].skincolor = skins[players[0].skin].prefcolor;
......@@ -2213,7 +2215,7 @@ void G_AddGhost(char *defdemoname)
ghosts = gh;
gh->version = ghostversion;
mthing = playerstarts[0];
mthing = world->playerstarts[0];
I_Assert(mthing);
{ // A bit more complex than P_SpawnPlayer because ghosts aren't solid and won't just push themselves out of the ceiling.
fixed_t z,f,c;
......
......@@ -54,6 +54,7 @@
gameaction_t gameaction;
gamestate_t gamestate = GS_NULL;
UINT8 ultimatemode = false;
boolean roaming = false;
boolean botingame;
UINT8 botskin;
......@@ -80,7 +81,6 @@ UINT32 mapmusposition; // Position to jump to
INT16 gamemap = 1;
UINT32 maptol;
UINT8 globalweather = 0;
INT32 curWeather = PRECIP_NONE;
INT32 cursaveslot = 0; // Auto-save 1p savegame slot
//INT16 lastmapsaved = 0; // Last map we auto-saved at
......@@ -164,11 +164,13 @@ mobj_t *blueflag;
mapthing_t *rflagpoint;
mapthing_t *bflagpoint;
struct quake quake;
// Map Header Information
mapheader_t* mapheaderinfo[NUMMAPS] = {NULL};
mapheader_t* curmapheader = NULL;
mapheader_t* nextmapheader = NULL;
mapheader_t* worldmapheader = NULL;
static boolean exitgame = false;
static boolean retrying = false;
static boolean retryingmodeattack = false;
......@@ -221,15 +223,8 @@ UINT8 introtoplay;
UINT8 creditscutscene;
UINT8 useBlackRock = 1;
// Emerald locations
mobj_t *hunt1;
mobj_t *hunt2;
mobj_t *hunt3;
UINT32 countdown, countdown2; // for racing
fixed_t gravity;
INT16 autobalance; //for CTF team balance
INT16 teamscramble; //for CTF team scramble
INT16 scrambleplayers[MAXPLAYERS]; //for CTF team scramble
......@@ -1788,6 +1783,14 @@ static void AutoBrake2_OnChange(void)
SendWeaponPref2();
}
static void G_ResetCamera(INT32 playernum)
{
if (playernum == consoleplayer && camera.chase)
P_ResetCamera(&players[displayplayer], &camera);
if (playernum == 1 && camera2.chase && splitscreen)
P_ResetCamera(&players[secondarydisplayplayer], &camera2);
}
//
// G_DoLoadLevel
//
......@@ -1831,15 +1834,16 @@ void G_DoLoadLevel(boolean resetplayer)
players[i].playerstate = PST_REBORN;
}
World_UnloadAll();
// Setup the level.
if (!P_LoadLevel(false, false)) // this never returns false?
if (!P_LoadLevel(false, false)) // this never returns false? (yes it can)
{
// fail so reset game stuff
Command_ExitGame_f();
return;
}
P_FindEmerald();
P_FindEmerald(world);
displayplayer = consoleplayer; // view the guy you are playing
if (!splitscreen && !botingame)
......@@ -1850,11 +1854,6 @@ void G_DoLoadLevel(boolean resetplayer)
Z_CheckHeap(-2);
#endif
if (camera.chase)
P_ResetCamera(&players[displayplayer], &camera);
if (camera2.chase && splitscreen)
P_ResetCamera(&players[secondarydisplayplayer], &camera2);
// clear cmd building stuff
memset(gamekeydown, 0, sizeof (gamekeydown));
for (i = 0;i < JOYAXISSET; i++)
......@@ -1865,6 +1864,11 @@ void G_DoLoadLevel(boolean resetplayer)
G_SetMouseDeltas(0, 0, 1);
G_SetMouseDeltas(0, 0, 2);
if (splitscreen)
G_ResetCamera(1);
G_ResetCamera(consoleplayer);
// clear hud messages remains (usually from game startup)
CON_ClearHUD();
}
......@@ -1941,7 +1945,7 @@ boolean G_IsTitleCardAvailable(void)
else if (titlecardforreload)
titleflag = LF_NOTITLECARDRESPAWN;
if (mapheaderinfo[gamemap-1]->levelflags & titleflag)
if (worldmapheader->levelflags & titleflag)
return false;
// The current gametype doesn't have a title card.
......@@ -1949,7 +1953,7 @@ boolean G_IsTitleCardAvailable(void)
return false;
// The current level has no name.
if (!mapheaderinfo[gamemap-1]->lvlttl[0])
if (!worldmapheader->lvlttl[0])
return false;
// The title card is available.
......@@ -2225,6 +2229,61 @@ boolean G_LuaResponder(event_t *ev)
return cancelled;
}
static void G_DoMarathonModeRetry(void)
{
player_t *p = &players[consoleplayer];
marathonmode |= MA_INIT;
marathontime = 0;
numgameovers = tokenlist = token = 0;
countdown = countdown2 = exitfadestarted = 0;
p->playerstate = PST_REBORN;
p->starpostx = p->starposty = p->starpostz = 0;
p->lives = startinglivesbalance[0];
p->continues = 1;
p->score = 0;
// The latter two should clear by themselves, but just in case
p->pflags &= ~(PF_TAGIT|PF_GAMETYPEOVER|PF_FULLSTASIS);
// Clear cheatcodes too, just in case.
p->pflags &= ~(PF_GODMODE|PF_NOCLIP|PF_INVIS);
p->xtralife = 0;
// Reset unlockable triggers
unlocktriggers = 0;
emeralds = 0;
memset(&luabanks, 0, sizeof(luabanks));
}
static void G_DoSingleplayerRetry(void)
{
G_ClearRetryFlag();
if (modeattacking)
{
pausedelay = INT32_MIN;
M_ModeAttackRetry(0);
}
else
{
// Costs a life to retry ... unless the player in question is dead already, or you haven't even touched the first starpost in marathon run.
if (marathonmode && gamemap == spmarathon_start && !players[consoleplayer].starposttime)
G_DoMarathonModeRetry();
else if (G_GametypeUsesLives() && players[consoleplayer].playerstate == PST_LIVE && players[consoleplayer].lives != INFLIVES)
players[consoleplayer].lives -= 1;
P_SetWorld(P_GetPlayerWorld(&players[consoleplayer]));
G_DoReborn(consoleplayer);
}
}
//
// G_Ticker
// Make ticcmd_ts for the players.
......@@ -2261,59 +2320,19 @@ void G_Ticker(boolean run)
{
// Or, alternatively, retry.
if (!(netgame || multiplayer) && G_GetRetryFlag())
{
G_ClearRetryFlag();
if (modeattacking)
{
pausedelay = INT32_MIN;
M_ModeAttackRetry(0);
}
else
{
// Costs a life to retry ... unless the player in question is dead already, or you haven't even touched the first starpost in marathon run.
if (marathonmode && gamemap == spmarathon_start && !players[consoleplayer].starposttime)
{
player_t *p = &players[consoleplayer];
marathonmode |= MA_INIT;
marathontime = 0;
numgameovers = tokenlist = token = 0;
countdown = countdown2 = exitfadestarted = 0;
p->playerstate = PST_REBORN;
p->starpostx = p->starposty = p->starpostz = 0;
p->lives = startinglivesbalance[0];
p->continues = 1;
p->score = 0;
// The latter two should clear by themselves, but just in case
p->pflags &= ~(PF_TAGIT|PF_GAMETYPEOVER|PF_FULLSTASIS);
// Clear cheatcodes too, just in case.
p->pflags &= ~(PF_GODMODE|PF_NOCLIP|PF_INVIS);
p->xtralife = 0;
// Reset unlockable triggers
unlocktriggers = 0;
emeralds = 0;
memset(&luabanks, 0, sizeof(luabanks));
}
else if (G_GametypeUsesLives() && players[consoleplayer].playerstate == PST_LIVE && players[consoleplayer].lives != INFLIVES)
players[consoleplayer].lives -= 1;
G_DoReborn(consoleplayer);
}
}
G_DoSingleplayerRetry();
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].playerstate == PST_REBORN)
{
// We have to actually be in that player's world.
P_SetWorld(P_GetPlayerWorld(&players[i]));
G_DoReborn(i);
}
// Restore the world
if (world != localworld)
P_SetWorld(localworld);
}
P_MapEnd();
......@@ -2482,7 +2501,7 @@ void G_Ticker(boolean run)
// G_PlayerFinishLevel
// Called when a player completes a level.
//
static inline void G_PlayerFinishLevel(INT32 player)
void G_PlayerFinishLevel(INT32 player)
{
player_t *p;
......@@ -2630,7 +2649,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
if (betweenmaps || !G_IsSpecialStage(gamemap))
{
rings = (ultimatemode ? 0 : mapheaderinfo[gamemap-1]->startrings);
rings = (ultimatemode ? 0 : curmapheader->startrings);
spheres = 0;
}
else
......@@ -2642,6 +2661,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
p = &players[player];
memset(p, 0, sizeof (*p));
p->world = world;
p->score = score;
p->lives = lives;
p->continues = continues;
......@@ -2741,23 +2761,23 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
{
if (mapmusflags & MUSIC_RELOADRESET)
{
strncpy(mapmusname, mapheaderinfo[gamemap-1]->musname, 7);
strncpy(mapmusname, worldmapheader->musname, 7);
mapmusname[6] = 0;
mapmusflags = (mapheaderinfo[gamemap-1]->mustrack & MUSIC_TRACKMASK);
mapmusposition = mapheaderinfo[gamemap-1]->muspos;
mapmusflags = (worldmapheader->mustrack & MUSIC_TRACKMASK);
mapmusposition = worldmapheader->muspos;
}
// This is in S_Start, but this was not here previously.
// if (RESETMUSIC)
// if (S_ShouldResetMusic(worldmapheader))
// S_StopMusic();
S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0);
}
if (gametyperules & GTR_EMERALDHUNT)
P_FindEmerald(); // scan for emeralds to hunt for
P_FindEmerald(p->world); // scan for emeralds to hunt for
// If NiGHTS, find lowest mare to start with.
p->mare = P_FindLowestMare();
p->mare = P_FindLowestMare(p->world);
CONS_Debug(DBG_NIGHTS, M_GetText("Current mare is %d\n"), p->mare);
......@@ -2797,10 +2817,11 @@ static boolean G_CheckSpot(INT32 playernum, mapthing_t *mthing)
x = mthing->x << FRACBITS;
y = mthing->y << FRACBITS;
if (!P_CheckPosition(players[playernum].mo, x, y))
return false;
mobj_t *ptmthing = tmthing;
boolean success = P_CheckPosition(players[playernum].mo, x, y);
P_SetTarget(&tmthing, ptmthing);
return true;
return success;
}
//
......@@ -2824,7 +2845,7 @@ void G_MovePlayerToSpawnOrStarpost(INT32 playernum)
if (players[playernum].starposttime)
P_MovePlayerToStarpost(playernum);
else
P_MovePlayerToSpawn(playernum, G_FindMapStart(playernum));
P_MovePlayerToSpawn(playernum, G_FindMapStart(players[playernum].world, playernum));
R_ResetMobjInterpolationState(players[playernum].mo);
......@@ -2837,20 +2858,21 @@ void G_MovePlayerToSpawnOrStarpost(INT32 playernum)
P_ResetCamera(&players[playernum], &camera2);
}
mapthing_t *G_FindCTFStart(INT32 playernum)
mapthing_t *G_FindCTFStart(void *wptr, INT32 playernum)
{
INT32 i,j;
INT32 i, j;
world_t *w = (world_t *)wptr;
if (!numredctfstarts && !numbluectfstarts) //why even bother, eh?
if (!w->numredctfstarts && !w->numbluectfstarts) //why even bother, eh?
{
if ((gametyperules & GTR_TEAMFLAGS) && (playernum == consoleplayer || (splitscreen && playernum == secondarydisplayplayer)))
CONS_Alert(CONS_WARNING, M_GetText("No CTF starts in this map!\n"));
return NULL;
}
if ((!players[playernum].ctfteam && numredctfstarts && (!numbluectfstarts || P_RandomChance(FRACUNIT/2))) || players[playernum].ctfteam == 1) //red
if ((!players[playernum].ctfteam && w->numredctfstarts && (!w->numbluectfstarts || P_RandomChance(FRACUNIT/2))) || players[playernum].ctfteam == 1) //red
{
if (!numredctfstarts)
if (!w->numredctfstarts)
{
if (playernum == consoleplayer || (splitscreen && playernum == secondarydisplayplayer))
CONS_Alert(CONS_WARNING, M_GetText("No Red Team starts in this map!\n"));
......@@ -2859,9 +2881,9 @@ mapthing_t *G_FindCTFStart(INT32 playernum)
for (j = 0; j < 32; j++)
{
i = P_RandomKey(numredctfstarts);
if (G_CheckSpot(playernum, redctfstarts[i]))
return redctfstarts[i];
i = P_RandomKey(w->numredctfstarts);
if (G_CheckSpot(playernum, w->redctfstarts[i]))
return w->redctfstarts[i];
}
if (playernum == consoleplayer || (splitscreen && playernum == secondarydisplayplayer))
......@@ -2870,7 +2892,7 @@ mapthing_t *G_FindCTFStart(INT32 playernum)
}
else if (!players[playernum].ctfteam || players[playernum].ctfteam == 2) //blue
{
if (!numbluectfstarts)
if (!w->numbluectfstarts)
{
if (playernum == consoleplayer || (splitscreen && playernum == secondarydisplayplayer))
CONS_Alert(CONS_WARNING, M_GetText("No Blue Team starts in this map!\n"));
......@@ -2879,9 +2901,9 @@ mapthing_t *G_FindCTFStart(INT32 playernum)
for (j = 0; j < 32; j++)
{
i = P_RandomKey(numbluectfstarts);
if (G_CheckSpot(playernum, bluectfstarts[i]))
return bluectfstarts[i];
i = P_RandomKey(w->numbluectfstarts);
if (G_CheckSpot(playernum, w->bluectfstarts[i]))
return w->bluectfstarts[i];
}
if (playernum == consoleplayer || (splitscreen && playernum == secondarydisplayplayer))
CONS_Alert(CONS_WARNING, M_GetText("Could not spawn at any Blue Team starts!\n"));
......@@ -2891,17 +2913,18 @@ mapthing_t *G_FindCTFStart(INT32 playernum)
return NULL;
}
mapthing_t *G_FindMatchStart(INT32 playernum)
mapthing_t *G_FindMatchStart(void *wptr, INT32 playernum)
{
INT32 i, j;
world_t *w = (world_t *)wptr;
if (numdmstarts)
if (w->numdmstarts)
{
for (j = 0; j < 64; j++)
{
i = P_RandomKey(numdmstarts);
if (G_CheckSpot(playernum, deathmatchstarts[i]))
return deathmatchstarts[i];
i = P_RandomKey(w->numdmstarts);
if (G_CheckSpot(playernum, w->deathmatchstarts[i]))
return w->deathmatchstarts[i];
}
if (playernum == consoleplayer || (splitscreen && playernum == secondarydisplayplayer))
CONS_Alert(CONS_WARNING, M_GetText("Could not spawn at any Deathmatch starts!\n"));
......@@ -2913,17 +2936,19 @@ mapthing_t *G_FindMatchStart(INT32 playernum)
return NULL;
}
mapthing_t *G_FindCoopStart(INT32 playernum)
mapthing_t *G_FindCoopStart(void *wptr, INT32 playernum)
{
if (numcoopstarts)
world_t *w = (world_t *)wptr;
if (w->numcoopstarts)
{
//if there's 6 players in a map with 3 player starts, this spawns them 1/2/3/1/2/3.
if (G_CheckSpot(playernum, playerstarts[playernum % numcoopstarts]))
return playerstarts[playernum % numcoopstarts];
if (G_CheckSpot(playernum, w->playerstarts[playernum % w->numcoopstarts]))
return w->playerstarts[playernum % w->numcoopstarts];
//Don't bother checking to see if the player 1 start is open.
//Just spawn there.
return playerstarts[0];
return w->playerstarts[0];
}
if (playernum == consoleplayer || (splitscreen && playernum == secondarydisplayplayer))
......@@ -2932,32 +2957,30 @@ mapthing_t *G_FindCoopStart(INT32 playernum)
}
// Find a Co-op start, or fallback into other types of starts.
static inline mapthing_t *G_FindCoopStartOrFallback(INT32 playernum)
static mapthing_t *G_FindCoopStartOrFallback(world_t *w, INT32 playernum)
{
mapthing_t *spawnpoint = NULL;
if (!(spawnpoint = G_FindCoopStart(playernum)) // find a Co-op start
&& !(spawnpoint = G_FindMatchStart(playernum))) // find a DM start
spawnpoint = G_FindCTFStart(playernum); // fallback
if (!(spawnpoint = G_FindCoopStart(w, playernum)) // find a Co-op start
&& !(spawnpoint = G_FindMatchStart(w, playernum))) // find a DM start
spawnpoint = G_FindCTFStart(w, playernum); // fallback
return spawnpoint;
}
// Find a Match start, or fallback into other types of starts.
static inline mapthing_t *G_FindMatchStartOrFallback(INT32 playernum)
static mapthing_t *G_FindMatchStartOrFallback(world_t *w, INT32 playernum)
{
mapthing_t *spawnpoint = NULL;
if (!(spawnpoint = G_FindMatchStart(playernum)) // find a DM start
&& !(spawnpoint = G_FindCTFStart(playernum))) // find a CTF start
spawnpoint = G_FindCoopStart(playernum); // fallback
if (!(spawnpoint = G_FindMatchStart(w, playernum)) // find a DM start
&& !(spawnpoint = G_FindCTFStart(w, playernum))) // find a CTF start
spawnpoint = G_FindCoopStart(w, playernum); // fallback
return spawnpoint;
}
mapthing_t *G_FindMapStart(INT32 playernum)
mapthing_t *G_GetMapStartForPlayerNum(void *wptr, INT32 playernum)
{
world_t *w = (world_t *)wptr;
mapthing_t *spawnpoint;
if (!playeringame[playernum])
return NULL;
// -- Spectators --
// Order in platform gametypes: Coop->DM->CTF
// And, with deathmatch starts: DM->CTF->Coop
......@@ -2966,38 +2989,49 @@ mapthing_t *G_FindMapStart(INT32 playernum)
// In platform gametypes, spawn in Co-op starts first
// Overriden by GTR_DEATHMATCHSTARTS.
if (G_PlatformGametype() && !(gametyperules & GTR_DEATHMATCHSTARTS))
spawnpoint = G_FindCoopStartOrFallback(playernum);
spawnpoint = G_FindCoopStartOrFallback(w, playernum);
else
spawnpoint = G_FindMatchStartOrFallback(playernum);
spawnpoint = G_FindMatchStartOrFallback(w, playernum);
}
// -- CTF --
// Order: CTF->DM->Coop
else if ((gametyperules & (GTR_TEAMFLAGS|GTR_TEAMS)) && players[playernum].ctfteam)
{
if (!(spawnpoint = G_FindCTFStart(playernum)) // find a CTF start
&& !(spawnpoint = G_FindMatchStart(playernum))) // find a DM start
spawnpoint = G_FindCoopStart(playernum); // fallback
if (!(spawnpoint = G_FindCTFStart(w, playernum)) // find a CTF start
&& !(spawnpoint = G_FindMatchStart(w, playernum))) // find a DM start
spawnpoint = G_FindCoopStart(w, playernum); // fallback
}
// -- DM/Tag/CTF-spectator/etc --
// Order: DM->CTF->Coop
else if (G_TagGametype() ? (!(players[playernum].pflags & PF_TAGIT)) : (gametyperules & GTR_DEATHMATCHSTARTS))
spawnpoint = G_FindMatchStartOrFallback(playernum);
spawnpoint = G_FindMatchStartOrFallback(w, playernum);
// -- Other game modes --
// Order: Coop->DM->CTF
else
spawnpoint = G_FindCoopStartOrFallback(playernum);
spawnpoint = G_FindCoopStartOrFallback(w, playernum);
return spawnpoint;
}
mapthing_t *G_FindMapStart(void *wptr, INT32 playernum)
{
if (!playeringame[playernum])
return NULL;
world_t *w = (world_t *)wptr;
mapthing_t *spawnpoint = G_GetMapStartForPlayerNum(w, playernum);
//No spawns found. ANYWHERE.
if (!spawnpoint)
{
if (nummapthings)
if (w->nummapthings)
{
if (playernum == consoleplayer || (splitscreen && playernum == secondarydisplayplayer))
CONS_Alert(CONS_ERROR, M_GetText("No player spawns found, spawning at the first mapthing!\n"));
spawnpoint = &mapthings[0];
spawnpoint = &w->mapthings[0];
}
else
{
......@@ -3039,6 +3073,7 @@ void G_ChangePlayerReferences(mobj_t *oldmo, mobj_t *newmo)
//
// G_DoReborn
// This assumes the correct world is set and won't modify it
//
void G_DoReborn(INT32 playernum)
{
......@@ -3174,7 +3209,7 @@ void G_DoReborn(INT32 playernum)
players[i].starpostnum = 0;
}
}
if (!countdowntimeup && (mapheaderinfo[gamemap-1]->levelflags & LF_NORELOAD) && !(marathonmode & MA_INIT))
if (!countdowntimeup && (curmapheader->levelflags & LF_NORELOAD) && !(marathonmode & MA_INIT))
{
P_RespawnThings();
......@@ -3301,6 +3336,12 @@ void G_AddPlayer(INT32 playernum)
}
}
p->world = NULL;
// Let's just place the player in the first world
if (worldlist)
P_SwitchPlayerWorld(p, worldlist[0]);
p->playerstate = PST_REBORN;
p->height = mobjinfo[MT_PLAYER].height;
......@@ -3942,37 +3983,9 @@ static void G_HandleSaveLevel(void)
}
}
//
// G_DoCompleted
//
static void G_DoCompleted(void)
void G_SetNextMap(boolean usespec, boolean inspec)
{
INT32 i;
boolean spec = G_IsSpecialStage(gamemap);
tokenlist = 0; // Reset the list
if (modeattacking && pausedelay)
pausedelay = 0;
gameaction = ga_nothing;
if (metalplayback)
G_StopMetalDemo();
if (metalrecording)
G_StopMetalRecording(false);
G_SetGamestate(GS_NULL);
wipegamestate = GS_NULL;
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i])
G_PlayerFinishLevel(i); // take away cards and stuff
if (automapactive)
AM_Stop();
S_StopSounds();
prevmap = (INT16)(gamemap-1);
......@@ -3980,11 +3993,11 @@ static void G_DoCompleted(void)
// nextmap is 0-based, unlike gamemap
if (nextmapoverride != 0)
nextmap = (INT16)(nextmapoverride-1);
else if (marathonmode && mapheaderinfo[gamemap-1]->marathonnext)
nextmap = (INT16)(mapheaderinfo[gamemap-1]->marathonnext-1);
else if (marathonmode && curmapheader->marathonnext)
nextmap = (INT16)(curmapheader->marathonnext-1);
else
{
nextmap = (INT16)(mapheaderinfo[gamemap-1]->nextlevel-1);
nextmap = (INT16)(curmapheader->nextlevel-1);
if (marathonmode && nextmap == spmarathon_start-1)
nextmap = 1100-1; // No infinite loop for you
}
......@@ -3993,7 +4006,7 @@ static void G_DoCompleted(void)
// a map of the proper gametype -- skip levels that don't support
// the current gametype. (Helps avoid playing boss levels in Race,
// for instance).
if (!spec || nextmapoverride)
if (!inspec || nextmapoverride)
{
if (nextmap >= 0 && nextmap < NUMMAPS)
{
......@@ -4045,11 +4058,11 @@ static void G_DoCompleted(void)
if (nextmap < 0 || (nextmap >= NUMMAPS && nextmap < 1100-1) || nextmap > 1103-1)
I_Error("Followed map %d to invalid map %d\n", prevmap + 1, nextmap + 1);
if (!spec)
if (!inspec)
lastmap = nextmap; // Remember last map for when you come out of the special stage.
}
if ((gottoken = ((gametyperules & GTR_SPECIALSTAGES) && token)))
if ((gottoken = (usespec && token)))
{
token--;
......@@ -4068,8 +4081,42 @@ static void G_DoCompleted(void)
}
}
if (spec && !gottoken && !nextmapoverride)
if (inspec && !gottoken && !nextmapoverride)
nextmap = lastmap; // Exiting from a special stage? Go back to the game. Tails 08-11-2001
}
//
// G_DoCompleted
//
static void G_DoCompleted(void)
{
INT32 i;
boolean spec = G_IsSpecialStage(gamemap);
tokenlist = 0; // Reset the list
if (modeattacking && pausedelay)
pausedelay = 0;
gameaction = ga_nothing;
if (metalplayback)
G_StopMetalDemo();
if (metalrecording)
G_StopMetalRecording(false);
G_SetGamestate(GS_NULL);
wipegamestate = GS_NULL;
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i])
G_PlayerFinishLevel(i); // take away cards and stuff
if (automapactive)
AM_Stop();
S_StopSounds();
G_SetNextMap(gametyperules & GTR_SPECIALSTAGES, spec);
automapactive = false;
......@@ -4124,14 +4171,14 @@ void G_AfterIntermission(void)
HU_ClearCEcho();
if ((gametyperules & GTR_CUTSCENES) && mapheaderinfo[gamemap-1]->cutscenenum
if ((gametyperules & GTR_CUTSCENES) && curmapheader->cutscenenum
&& !modeattacking
&& skipstats <= 1
&& (gamecomplete || !(marathonmode & MA_NOCUTSCENES))
&& stagefailed == false)
{
// Start a custom cutscene.
F_StartCustomCutscene(mapheaderinfo[gamemap-1]->cutscenenum-1, false, false, false);
F_StartCustomCutscene(curmapheader->cutscenenum-1, false, false, false);
}
else
{
......@@ -4934,11 +4981,41 @@ void G_DeferedInitNew(boolean pultmode, const char *mapname, INT32 pickedchar, b
D_MapChange(M_MapNumber(mapname[3], mapname[4]), gametype, pultmode, true, 1, false, FLS);
}
static void G_ResetPlayer(player_t *player, boolean pultmode, boolean FLS)
{
player->playerstate = PST_REBORN;
player->starpostscale = player->starpostangle = player->starpostnum = player->starposttime = 0;
player->starpostx = player->starposty = player->starpostz = 0;
if (netgame || multiplayer)
{
if (!FLS || (player->lives < 1))
player->lives = cv_startinglives.value;
player->continues = 0;
}
else
{
player->lives = (pultmode) ? 1 : startinglivesbalance[0];
player->continues = (pultmode) ? 0 : 1;
}
if (!((netgame || multiplayer) && (FLS)))
player->score = 0;
// The latter two should clear by themselves, but just in case
player->pflags &= ~(PF_TAGIT|PF_GAMETYPEOVER|PF_FULLSTASIS);
// Clear cheatcodes too, just in case.
player->pflags &= ~(PF_GODMODE|PF_NOCLIP|PF_INVIS);
player->xtralife = 0;
}
//
// This is the map command interpretation something like Command_Map_f
//
// called at: map cmd execution, doloadgame, doplaydemo
void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean skipprecutscene, boolean FLS)
void G_InitNew(const char *mapname, UINT8 pultmode, boolean resetplayer, boolean skipprecutscene, boolean FLS)
{
INT32 i;
......@@ -4963,34 +5040,7 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean
countdown = countdown2 = exitfadestarted = 0;
for (i = 0; i < MAXPLAYERS; i++)
{
players[i].playerstate = PST_REBORN;
players[i].starpostscale = players[i].starpostangle = players[i].starpostnum = players[i].starposttime = 0;
players[i].starpostx = players[i].starposty = players[i].starpostz = 0;
if (netgame || multiplayer)
{
if (!FLS || (players[i].lives < 1))
players[i].lives = cv_startinglives.value;
players[i].continues = 0;
}
else
{
players[i].lives = (pultmode) ? 1 : startinglivesbalance[0];
players[i].continues = (pultmode) ? 0 : 1;
}
if (!((netgame || multiplayer) && (FLS)))
players[i].score = 0;
// The latter two should clear by themselves, but just in case
players[i].pflags &= ~(PF_TAGIT|PF_GAMETYPEOVER|PF_FULLSTASIS);
// Clear cheatcodes too, just in case.
players[i].pflags &= ~(PF_GODMODE|PF_NOCLIP|PF_INVIS);
players[i].xtralife = 0;
}
G_ResetPlayer(&players[i], pultmode, FLS);
// Reset unlockable triggers
unlocktriggers = 0;
......@@ -5017,8 +5067,8 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean
if(!mapheaderinfo[gamemap-1])
P_AllocMapHeader(gamemap-1);
maptol = mapheaderinfo[gamemap-1]->typeoflevel;
globalweather = mapheaderinfo[gamemap-1]->weather;
curmapheader = worldmapheader = nextmapheader = mapheaderinfo[gamemap-1];
maptol = nextmapheader->typeoflevel;
// Don't carry over custom music change to another map.
mapmusflags |= MUSIC_RELOADRESET;
......@@ -5027,8 +5077,8 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean
automapactive = false;
imcontinuing = false;
if ((gametyperules & GTR_CUTSCENES) && !skipprecutscene && mapheaderinfo[gamemap-1]->precutscenenum && !modeattacking && !(marathonmode & MA_NOCUTSCENES)) // Start a custom cutscene.
F_StartCustomCutscene(mapheaderinfo[gamemap-1]->precutscenenum-1, true, resetplayer, FLS);
if ((gametyperules & GTR_CUTSCENES) && !skipprecutscene && nextmapheader->precutscenenum && !modeattacking && !(marathonmode & MA_NOCUTSCENES)) // Start a custom cutscene.
F_StartCustomCutscene(nextmapheader->precutscenenum-1, true, resetplayer, FLS);
else
G_DoLoadLevel(resetplayer);
......@@ -5046,6 +5096,45 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean
}
}
boolean G_LoadWorld(const char *mapname)
{
// Check if the map is actually valid.
if (W_CheckNumForName(mapname) == LUMPERROR)
{
CONS_Alert(CONS_ERROR, "G_LoadWorld: Internal game map '%s' not found\n", mapname);
return false;
}
INT16 mapnum = (INT16)M_MapNumber(mapname[3], mapname[4]); // get xx out of MAPxx
// gamemap changed; we assume that its map header is always valid,
// so make it so
if(!mapheaderinfo[mapnum-1])
P_AllocMapHeader(mapnum-1);
LUA_HookInt(mapnum, HOOK(MapChange));
nextmapheader = mapheaderinfo[mapnum-1];
worldmapheader = nextmapheader;
world_t *curworld = world;
if (!P_LoadWorld(mapnum, false))
{
P_SetWorld(curworld); // Change world back to the previous one
CONS_Alert(CONS_ERROR, "G_LoadWorld: Could not load map '%s'\n", mapname);
return false;
}
// Change world back to the previous one
P_SetWorld(curworld);
#ifdef PARANOIA
Z_CheckHeap(-2);
#endif
return true;
}
char *G_BuildMapTitle(INT32 mapnum)
{
......
......@@ -136,8 +136,7 @@ extern INT32 localaiming, localaiming2; // should be an angle_t but signed
void G_ChangePlayerReferences(mobj_t *oldmo, mobj_t *newmo);
void G_DoReborn(INT32 playernum);
void G_PlayerReborn(INT32 player, boolean betweenmaps);
void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer,
boolean skipprecutscene, boolean FLS);
void G_InitNew(const char *mapname, UINT8 pultmode, boolean resetplayer, boolean skipprecutscene, boolean FLS);
char *G_BuildMapTitle(INT32 mapnum);
struct searchdim
......@@ -165,18 +164,21 @@ void G_FreeMapSearch(mapsearchfreq_t *freq, INT32 freqc);
INT32 G_FindMapByNameOrCode(const char *query, char **foundmapnamep);
// XMOD spawning
mapthing_t *G_FindCTFStart(INT32 playernum);
mapthing_t *G_FindMatchStart(INT32 playernum);
mapthing_t *G_FindCoopStart(INT32 playernum);
mapthing_t *G_FindMapStart(INT32 playernum);
mapthing_t *G_FindCTFStart(void *wptr, INT32 playernum);
mapthing_t *G_FindMatchStart(void *wptr, INT32 playernum);
mapthing_t *G_FindCoopStart(void *wptr, INT32 playernum);
mapthing_t *G_FindMapStart(void *wptr, INT32 playernum);
mapthing_t *G_GetMapStartForPlayerNum(void *wptr, INT32 playernum);
void G_MovePlayerToSpawnOrStarpost(INT32 playernum);
void G_SpawnPlayer(INT32 playernum);
// Can be called by the startup code or M_Responder.
// A normal game starts at map 1, but a warp test can start elsewhere
void G_DeferedInitNew(boolean pultmode, const char *mapname, INT32 pickedchar,
boolean SSSG, boolean FLS);
void G_DeferedInitNew(boolean pultmode, const char *mapname, INT32 pickedchar,boolean SSSG, boolean FLS);
void G_DoLoadLevel(boolean resetplayer);
boolean G_LoadWorld(const char *mapname);
void G_StartTitleCard(void);
void G_PreLevelTitleCard(void);
boolean G_IsTitleCardAvailable(void);
......@@ -217,6 +219,8 @@ boolean G_CompetitionGametype(void);
boolean G_EnoughPlayersFinished(void);
void G_ExitLevel(void);
void G_NextLevel(void);
void G_SetNextMap(boolean usespec, boolean inspec);
void G_PlayerFinishLevel(INT32 player);
void G_Continue(void);
void G_UseContinue(void);
void G_AfterIntermission(void);
......
......@@ -54,6 +54,7 @@ typedef enum
extern gamestate_t gamestate;
extern UINT8 titlemapinaction;
extern UINT8 ultimatemode; // was sk_insane
extern boolean roaming;
extern gameaction_t gameaction;
extern boolean botingame;
......
......@@ -23,17 +23,15 @@
#include "../i_video.h"
#include "../w_wad.h"
#include "../p_setup.h" // levelfadecol
#include "../p_world.h"
// --------------------------------------------------------------------------
// This is global data for planes rendering
// --------------------------------------------------------------------------
extrasubsector_t *extrasubsectors = NULL;
// newsubsectors are subsectors without segs, added for the plane polygons
#define NEWSUBSECTORS 50
static size_t totsubsectors;
size_t addsubsector;
typedef struct
{
......@@ -45,121 +43,24 @@ typedef struct
// FLOOR & CEILING CONVEX POLYS GENERATION
// ==========================================================================
//debug counters
static INT32 nobackpoly = 0;
static INT32 skipcut = 0;
static INT32 totalsubsecpolys = 0;
// --------------------------------------------------------------------------
// Polygon fast alloc / free
// --------------------------------------------------------------------------
//hurdler: quick fix for those who wants to play with larger wad
#define ZPLANALLOC
#ifndef ZPLANALLOC
//#define POLYPOOLSIZE 1024000 // may be much over what is needed
/// \todo check out how much is used
static size_t POLYPOOLSIZE = 1024000;
static UINT8 *gl_polypool = NULL;
static UINT8 *gl_ppcurrent;
static size_t gl_ppfree;
#endif
// only between levels, clear poly pool
static void HWR_ClearPolys(void)
{
#ifndef ZPLANALLOC
gl_ppcurrent = gl_polypool;
gl_ppfree = POLYPOOLSIZE;
#endif
}
// allocate pool for fast alloc of polys
void HWR_InitPolyPool(void)
{
#ifndef ZPLANALLOC
INT32 pnum;
//hurdler: quick fix for those who wants to play with larger wad
if ((pnum = M_CheckParm("-polypoolsize")))
POLYPOOLSIZE = atoi(myargv[pnum+1])*1024; // (in kb)
CONS_Debug(DBG_RENDER, "HWR_InitPolyPool(): allocating %d bytes\n", POLYPOOLSIZE);
gl_polypool = malloc(POLYPOOLSIZE);
if (!gl_polypool)
I_Error("HWR_InitPolyPool(): couldn't malloc polypool\n");
HWR_ClearPolys();
#endif
}
void HWR_FreePolyPool(void)
{
#ifndef ZPLANALLOC
if (gl_polypool)
free(gl_polypool);
gl_polypool = NULL;
#endif
}
static poly_t *HWR_AllocPoly(INT32 numpts)
{
poly_t *p;
size_t size = sizeof (poly_t) + sizeof (polyvertex_t) * numpts;
#ifdef ZPLANALLOC
p = Z_Malloc(size, PU_HWRPLANE, NULL);
#else
#ifdef PARANOIA
if (!gl_polypool)
I_Error("Used gl_polypool without init!\n");
if (!gl_ppcurrent)
I_Error("gl_ppcurrent == NULL!\n");
#endif
if (gl_ppfree < size)
I_Error("HWR_AllocPoly(): no more memory %u bytes left, %u bytes needed\n\n%s\n",
gl_ppfree, size, "You can try the param -polypoolsize 2048 (or higher if needed)");
p = (poly_t *)gl_ppcurrent;
gl_ppcurrent += size;
gl_ppfree -= size;
#endif
poly_t *p = Z_Malloc(size, PU_HWRPLANE, NULL);
p->numpts = numpts;
return p;
}
static polyvertex_t *HWR_AllocVertex(void)
{
polyvertex_t *p;
size_t size = sizeof (polyvertex_t);
#ifdef ZPLANALLOC
p = Z_Malloc(size, PU_HWRPLANE, NULL);
#else
if (gl_ppfree < size)
I_Error("HWR_AllocVertex(): no more memory %u bytes left, %u bytes needed\n\n%s\n",
gl_ppfree, size, "You can try the param -polypoolsize 2048 (or higher if needed)");
p = (polyvertex_t *)gl_ppcurrent;
gl_ppcurrent += size;
gl_ppfree -= size;
#endif
return p;
return Z_Malloc(sizeof (polyvertex_t), PU_HWRPLANE, NULL);
}
/// \todo polygons should be freed in reverse order for efficiency,
/// for now don't free because it doesn't free in reverse order
static void HWR_FreePoly(poly_t *poly)
{
#ifdef ZPLANALLOC
Z_Free(poly);
#else
const size_t size = sizeof (poly_t) + sizeof (polyvertex_t) * poly->numpts;
memset(poly, 0x00, size);
//mempoly -= polysize;
#endif
}
// Return interception along bsp line,
// with the polygon segment
//
......@@ -532,9 +433,6 @@ static poly_t *CutOutSubsecPoly(seg_t *lseg, INT32 count, poly_t *poly)
// only when the cut is not needed it seems (when the cut
// line is aligned to one of the borders of the poly, and
// only some times..)
else
skipcut++;
// I_Error("CutOutPoly: only one point for split line (%d %d) %d", ps, pe, debugpos);
}
}
return poly;
......@@ -551,16 +449,15 @@ static inline void HWR_SubsecPoly(INT32 num, poly_t *poly)
subsector_t *sub;
seg_t *lseg;
sub = &subsectors[num];
sub = &world->subsectors[num];
count = sub->numlines;
lseg = &segs[sub->firstline];
lseg = &world->segs[sub->firstline];
if (poly)
{
poly = CutOutSubsecPoly (lseg,count,poly);
totalsubsecpolys++;
//extra data for this subsector
extrasubsectors[num].planepoly = poly;
world->extrasubsectors[num].planepoly = poly;
}
}
......@@ -627,13 +524,13 @@ static void WalkBSPNode(INT32 bspnum, poly_t *poly, UINT16 *leafnode, fixed_t *b
if (poly && poly->numpts > 2)
{
CONS_Debug(DBG_RENDER, "Adding a new subsector\n");
if (addsubsector == numsubsectors + NEWSUBSECTORS)
if (world->numextrasubsectors == numsubsectors + NEWSUBSECTORS)
I_Error("WalkBSPNode: not enough addsubsectors\n");
else if (addsubsector > 0x7fff)
else if (world->numextrasubsectors > 0x7fff)
I_Error("WalkBSPNode: addsubsector > 0x7fff\n");
*leafnode = (UINT16)((UINT16)addsubsector | NF_SUBSECTOR);
extrasubsectors[addsubsector].planepoly = poly;
addsubsector++;
*leafnode = (UINT16)((UINT16)world->numextrasubsectors | NF_SUBSECTOR);
world->extrasubsectors[world->numextrasubsectors].planepoly = poly;
world->numextrasubsectors++;
}
//add subsectors without segs here?
......@@ -653,7 +550,7 @@ static void WalkBSPNode(INT32 bspnum, poly_t *poly, UINT16 *leafnode, fixed_t *b
#endif
}
M_ClearBox(bbox);
poly = extrasubsectors[bspnum & ~NF_SUBSECTOR].planepoly;
poly = world->extrasubsectors[bspnum & ~NF_SUBSECTOR].planepoly;
for (i = 0, pt = poly->pts; i < poly->numpts; i++,pt++)
M_AddToBox(bbox, FLOAT_TO_FIXED(pt->x), FLOAT_TO_FIXED(pt->y));
......@@ -666,10 +563,6 @@ static void WalkBSPNode(INT32 bspnum, poly_t *poly, UINT16 *leafnode, fixed_t *b
SplitPoly(&fdivline, poly, &frontpoly, &backpoly);
poly = NULL;
//debug
if (!backpoly)
nobackpoly++;
// Recursively divide front space.
if (frontpoly)
{
......@@ -696,11 +589,10 @@ static void WalkBSPNode(INT32 bspnum, poly_t *poly, UINT16 *leafnode, fixed_t *b
}
// FIXME: use Z_Malloc() STATIC ?
void HWR_FreeExtraSubsectors(void)
void HWR_FreeExtraSubsectors(extrasubsector_t *sub)
{
if (extrasubsectors)
free(extrasubsectors);
extrasubsectors = NULL;
if (sub)
free(sub);
}
#define MAXDIST 1.5f
......@@ -774,7 +666,7 @@ static void SearchSegInBSP(INT32 bspnum,polyvertex_t *p,poly_t *poly)
if (bspnum != -1)
{
bspnum &= ~NF_SUBSECTOR;
q = extrasubsectors[bspnum].planepoly;
q = world->extrasubsectors[bspnum].planepoly;
if (poly == q || !q)
return;
for (j = 0; j < q->numpts; j++)
......@@ -795,7 +687,7 @@ static void SearchSegInBSP(INT32 bspnum,polyvertex_t *p,poly_t *poly)
for (n = k+1; n < newpoly->numpts; n++)
newpoly->pts[n] = q->pts[n-1];
numsplitpoly++;
extrasubsectors[bspnum].planepoly =
world->extrasubsectors[bspnum].planepoly =
newpoly;
HWR_FreePoly(q);
return;
......@@ -840,9 +732,9 @@ static INT32 SolveTProblem(void)
numsplitpoly = 0;
for (l = 0; l < addsubsector; l++)
for (l = 0; l < world->numextrasubsectors; l++)
{
p = extrasubsectors[l].planepoly;
p = world->extrasubsectors[l].planepoly;
if (p)
for (i = 0; i < p->numpts; i++)
SearchSegInBSP((INT32)numnodes-1, &p->pts[i], p);
......@@ -870,9 +762,9 @@ static void AdjustSegs(void)
for (i = 0; i < numsubsectors; i++)
{
count = subsectors[i].numlines;
lseg = &segs[subsectors[i].firstline];
p = extrasubsectors[i].planepoly;
count = world->subsectors[i].numlines;
lseg = &world->segs[world->subsectors[i].firstline];
p = world->extrasubsectors[i].planepoly;
//if (!p)
//continue;
for (; count--; lseg++)
......@@ -955,40 +847,28 @@ void HWR_CreatePlanePolygons(INT32 bspnum)
{
poly_t *rootp;
polyvertex_t *rootpv;
size_t i;
fixed_t rootbbox[4];
CONS_Debug(DBG_RENDER, "Creating polygons, please wait...\n");
#ifdef HWR_LOADING_SCREEN
ls_count = ls_percent = 0; // reset the loading status
CON_Drawer(); //let the user know what we are doing
I_FinishUpdate(); // page flip or blit buffer
#endif
HWR_ClearPolys();
// find min/max boundaries of map
//CONS_Debug(DBG_RENDER, "Looking for boundaries of map...\n");
M_ClearBox(rootbbox);
for (i = 0;i < numvertexes; i++)
M_AddToBox(rootbbox, vertexes[i].x, vertexes[i].y);
//CONS_Debug(DBG_RENDER, "Generating subsector polygons... %d subsectors\n", numsubsectors);
for (size_t i = 0; i < world->numvertexes; i++)
M_AddToBox(rootbbox, world->vertexes[i].x, world->vertexes[i].y);
HWR_FreeExtraSubsectors();
// allocate extra data for each subsector present in map
totsubsectors = numsubsectors + NEWSUBSECTORS;
extrasubsectors = calloc(totsubsectors, sizeof (*extrasubsectors));
if (extrasubsectors == NULL)
totsubsectors = world->numsubsectors + NEWSUBSECTORS;
world->extrasubsectors = calloc(totsubsectors, sizeof (*world->extrasubsectors));
if (world->extrasubsectors == NULL)
I_Error("couldn't malloc extrasubsectors totsubsectors %s\n", sizeu1(totsubsectors));
// allocate table for back to front drawing of subsectors
/*gl_drawsubsectors = (INT16 *)malloc(sizeof (*gl_drawsubsectors) * totsubsectors);
if (!gl_drawsubsectors)
I_Error("couldn't malloc gl_drawsubsectors\n");*/
// number of the first new subsector that might be added
addsubsector = numsubsectors;
world->numextrasubsectors = world->numsubsectors; // number of the first new subsector that might be added
// construct the initial convex poly that encloses the full map
rootp = HWR_AllocPoly(4);
......@@ -1007,20 +887,10 @@ void HWR_CreatePlanePolygons(INT32 bspnum)
rootpv->y = FIXED_TO_FLOAT(rootbbox[BOXBOTTOM]); //ll
rootpv++;
WalkBSPNode(bspnum, rootp, NULL,rootbbox);
WalkBSPNode(bspnum, rootp, NULL, rootbbox);
i = SolveTProblem();
//CONS_Debug(DBG_RENDER, "%d point divides a polygon line\n",i);
SolveTProblem();
AdjustSegs();
//debug debug..
//if (nobackpoly)
// CONS_Debug(DBG_RENDER, "no back polygon %u times\n",nobackpoly);
//"(should happen only with the deep water trick)"
//if (skipcut)
// CONS_Debug(DBG_RENDER, "%u cuts were skipped because of only one point\n",skipcut);
//CONS_Debug(DBG_RENDER, "done: %u total subsector convex polygons\n", totalsubsecpolys);
}
#endif //HWRENDER
......@@ -28,35 +28,6 @@
// structures
// -----------
// a vertex of a Doom 'plane' polygon
typedef struct
{
float x;
float y;
float z;
} polyvertex_t;
#ifdef _MSC_VER
#pragma warning(disable : 4200)
#endif
// a convex 'plane' polygon, clockwise order
typedef struct
{
INT32 numpts;
polyvertex_t pts[0];
} poly_t;
#ifdef _MSC_VER
#pragma warning(default : 4200)
#endif
// holds extra info for 3D render, for each subsector in subsectors[]
typedef struct
{
poly_t *planepoly; // the generated convex polygon
} extrasubsector_t;
// needed for sprite rendering
// equivalent of the software renderer's vissprites
typedef struct gl_vissprite_s
......@@ -97,13 +68,7 @@ typedef struct gl_vissprite_s
// --------
// hw_bsp.c
// --------
extern extrasubsector_t *extrasubsectors;
extern size_t addsubsector;
void HWR_InitPolyPool(void);
void HWR_FreePolyPool(void);
void HWR_FreeExtraSubsectors(void);
void HWR_FreeExtraSubsectors(extrasubsector_t *sub);
// --------
// hw_cache.c
......
......@@ -24,6 +24,7 @@
#include "../v_video.h"
#include "../p_local.h"
#include "../p_setup.h"
#include "../p_world.h"
#include "../r_fps.h"
#include "../r_local.h"
#include "../r_patch.h"
......@@ -42,14 +43,9 @@
#include "../d_main.h"
#include "../p_slopes.h"
#include "hw_md2.h"
#ifdef NEWCLIP
#include "hw_clip.h"
#endif
#define R_FAKEFLOORS
#define HWPRECIP
//#define POLYSKY
// ==========================================================================
// the hardware driver object
......@@ -73,41 +69,10 @@ void HWR_AddTransparentPolyobjectFloor(levelflat_t *levelflat, polyobj_t *polyse
boolean drawsky = true;
// ==========================================================================
// VIEW GLOBALS
// ==========================================================================
// Fineangles in the SCREENWIDTH wide window.
#define FIELDOFVIEW ANGLE_90
#define ABS(x) ((x) < 0 ? -(x) : (x))
static angle_t gl_clipangle;
// The viewangletox[viewangle + FINEANGLES/4] lookup
// maps the visible view angles to screen X coordinates,
// flattening the arc to a flat projection plane.
// There will be many angles mapped to the same X.
static INT32 gl_viewangletox[FINEANGLES/2];
// The xtoviewangleangle[] table maps a screen pixel
// to the lowest viewangle that maps back to x ranges
// from clipangle to -clipangle.
static angle_t gl_xtoviewangle[MAXVIDWIDTH+1];
// ==========================================================================
// GLOBALS
// ==========================================================================
// uncomment to remove the plane rendering
#define DOPLANES
//#define DOWALLS
// test of drawing sky by polygons like in software with visplane, unfortunately
// this doesn't work since we must have z for pixel and z for texture (not like now with z = oow)
//#define POLYSKY
// test change fov when looking up/down but bsp projection messup :(
//#define NOCRAPPYMLOOK
// base values set at SetViewSize
static float gl_basecentery;
......@@ -167,7 +132,6 @@ ps_metric_t ps_hw_batchsorttime = {0};
ps_metric_t ps_hw_batchdrawtime = {0};
boolean gl_init = false;
boolean gl_maploaded = false;
boolean gl_sessioncommandsadded = false;
boolean gl_shadersavailable = true;
......@@ -353,8 +317,6 @@ static FUINT HWR_CalcSlopeLight(FUINT lightnum, angle_t dir, fixed_t delta)
// FLOOR/CEILING GENERATION FROM SUBSECTORS
// ==========================================================================
#ifdef DOPLANES
// -----------------+
// HWR_RenderPlane : Render a floor or ceiling convex polygon
// -----------------+
......@@ -572,7 +534,7 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool
const float renderdist = 27000.0f; // How far out to properly render the plane
const float farrenderdist = 32768.0f; // From here, raise plane to horizon level to fill in the line with some texture distortion
seg_t *line = &segs[subsector->firstline];
seg_t *line = &viewworld->segs[subsector->firstline];
for (i = 0; i < subsector->numlines; i++, line++)
{
......@@ -639,52 +601,6 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool
#endif
}
#ifdef POLYSKY
// this don't draw anything it only update the z-buffer so there isn't problem with
// wall/things upper that sky (map12)
static void HWR_RenderSkyPlane(extrasubsector_t *xsub, fixed_t fixedheight)
{
polyvertex_t *pv;
float height; //constant y for all points on the convex flat polygon
FOutVector *v3d;
INT32 nrPlaneVerts; //verts original define of convex flat polygon
INT32 i;
// no convex poly were generated for this subsector
if (!xsub->planepoly)
return;
height = FIXED_TO_FLOAT(fixedheight);
pv = xsub->planepoly->pts;
nrPlaneVerts = xsub->planepoly->numpts;
if (nrPlaneVerts < 3) // not even a triangle?
return;
if (nrPlaneVerts > MAXPLANEVERTICES) // FIXME: exceeds plVerts size
{
CONS_Debug(DBG_RENDER, "polygon size of %d exceeds max value of %d vertices\n", nrPlaneVerts, MAXPLANEVERTICES);
return;
}
// transform
v3d = planeVerts;
for (i = 0; i < nrPlaneVerts; i++,v3d++,pv++)
{
v3d->s = 0.0f;
v3d->t = 0.0f;
v3d->x = pv->x;
v3d->y = height;
v3d->z = pv->y;
}
HWD.pfnDrawPolygon(NULL, planeVerts, nrPlaneVerts, PF_Invisible|PF_NoTexture|PF_Occlude);
}
#endif //polysky
#endif //doplanes
FBITFIELD HWR_GetBlendModeFlag(INT32 style)
{
switch (style)
......@@ -781,45 +697,6 @@ static void HWR_ProjectWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIEL
HWR_ProcessPolygon(pSurf, wallVerts, 4, blendmode|PF_Modulated|PF_Occlude, shader, false);
}
// ==========================================================================
// BSP, CULL, ETC..
// ==========================================================================
// return the frac from the interception of the clipping line
// (in fact a clipping plane that has a constant, so can clip with simple 2d)
// with the wall segment
//
#ifndef NEWCLIP
static float HWR_ClipViewSegment(INT32 x, polyvertex_t *v1, polyvertex_t *v2)
{
float num, den;
float v1x, v1y, v1dx, v1dy, v2dx, v2dy;
angle_t pclipangle = gl_xtoviewangle[x];
// a segment of a polygon
v1x = v1->x;
v1y = v1->y;
v1dx = (v2->x - v1->x);
v1dy = (v2->y - v1->y);
// the clipping line
pclipangle = pclipangle + dup_viewangle; //back to normal angle (non-relative)
v2dx = FIXED_TO_FLOAT(FINECOSINE(pclipangle>>ANGLETOFINESHIFT));
v2dy = FIXED_TO_FLOAT(FINESINE(pclipangle>>ANGLETOFINESHIFT));
den = v2dy*v1dx - v2dx*v1dy;
if (den == 0)
return -1; // parallel
// calc the frac along the polygon segment,
//num = (v2x - v1x)*v2dy + (v1y - v2y)*v2dx;
//num = -v1x * v2dy + v1y * v2dx;
num = (gl_viewx - v1x)*v2dy + (v1y - gl_viewy)*v2dx;
return num / den;
}
#endif
// SoM: split up and light walls according to the lightlist.
// This may also include leaving out parts of the wall that can't be seen
static void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum, FSurfaceInfo* Surf, INT32 cutflag, ffloor_t *pfloor, FBITFIELD polyflags)
......@@ -1124,15 +1001,15 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
// hack to allow height changes in outdoor areas
// This is what gets rid of the upper textures if there should be sky
if (gl_frontsector->ceilingpic == skyflatnum
&& gl_backsector->ceilingpic == skyflatnum)
if (gl_frontsector->ceilingpic == viewworld->skyflatnum
&& gl_backsector->ceilingpic == viewworld->skyflatnum)
{
bothceilingssky = true;
}
// likewise, but for floors and upper textures
if (gl_frontsector->floorpic == skyflatnum
&& gl_backsector->floorpic == skyflatnum)
if (gl_frontsector->floorpic == viewworld->skyflatnum
&& gl_backsector->floorpic == viewworld->skyflatnum)
{
bothfloorssky = true;
}
......@@ -1268,12 +1145,12 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
INT32 repeats;
if (gl_linedef->frontsector->heightsec != -1)
front = &sectors[gl_linedef->frontsector->heightsec];
front = &viewworld->sectors[gl_linedef->frontsector->heightsec];
else
front = gl_linedef->frontsector;
if (gl_linedef->backsector->heightsec != -1)
back = &sectors[gl_linedef->backsector->heightsec];
back = &viewworld->sectors[gl_linedef->backsector->heightsec];
else
back = gl_linedef->backsector;
......@@ -1446,8 +1323,8 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
// No longer so much a mess as before!
if (!gl_curline->polyseg) // Don't do it for polyobjects
{
if (gl_frontsector->ceilingpic == skyflatnum
&& gl_backsector->ceilingpic != skyflatnum) // don't cull if back sector is also sky
if (gl_frontsector->ceilingpic == viewworld->skyflatnum
&& gl_backsector->ceilingpic != viewworld->skyflatnum) // don't cull if back sector is also sky
{
wallVerts[2].y = wallVerts[3].y = FIXED_TO_FLOAT(INT32_MAX); // draw to top of map space
wallVerts[0].y = FIXED_TO_FLOAT(worldtop);
......@@ -1455,8 +1332,8 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
HWR_DrawSkyWall(wallVerts, &Surf);
}
if (gl_frontsector->floorpic == skyflatnum
&& gl_backsector->floorpic != skyflatnum) // same thing here
if (gl_frontsector->floorpic == viewworld->skyflatnum
&& gl_backsector->floorpic != viewworld->skyflatnum) // same thing here
{
wallVerts[3].y = FIXED_TO_FLOAT(worldbottom);
wallVerts[2].y = FIXED_TO_FLOAT(worldbottomslope);
......@@ -1522,14 +1399,14 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
if (!gl_curline->polyseg)
{
if (gl_frontsector->ceilingpic == skyflatnum) // It's a single-sided line with sky for its sector
if (gl_frontsector->ceilingpic == viewworld->skyflatnum) // It's a single-sided line with sky for its sector
{
wallVerts[2].y = wallVerts[3].y = FIXED_TO_FLOAT(INT32_MAX); // draw to top of map space
wallVerts[0].y = FIXED_TO_FLOAT(worldtop);
wallVerts[1].y = FIXED_TO_FLOAT(worldtopslope);
HWR_DrawSkyWall(wallVerts, &Surf);
}
if (gl_frontsector->floorpic == skyflatnum)
if (gl_frontsector->floorpic == viewworld->skyflatnum)
{
wallVerts[3].y = FIXED_TO_FLOAT(worldbottom);
wallVerts[2].y = FIXED_TO_FLOAT(worldbottomslope);
......@@ -1584,13 +1461,13 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
if ((high1 < lowcut && highslope1 < lowcutslope) || (low1 > highcut && lowslope1 > highcutslope))
continue;
texnum = R_GetTextureNum(sides[rover->master->sidenum[0]].midtexture);
texnum = R_GetTextureNum(viewworld->sides[rover->master->sidenum[0]].midtexture);
if (rover->master->flags & ML_TFERLINE)
{
size_t linenum = gl_curline->linedef-gl_backsector->lines[0];
newline = rover->master->frontsector->lines[0] + linenum;
texnum = R_GetTextureNum(sides[newline->sidenum[0]].midtexture);
texnum = R_GetTextureNum(viewworld->sides[newline->sidenum[0]].midtexture);
}
h = P_GetFFloorTopZAt (rover, v1x, v1y);
......@@ -1634,13 +1511,13 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
// -- Monster Iestyn 26/06/18
if (newline)
{
texturevpeg = sides[newline->sidenum[0]].rowoffset;
texturevpeg = viewworld->sides[newline->sidenum[0]].rowoffset;
attachtobottom = !!(newline->flags & ML_DONTPEGBOTTOM);
slopeskew = !!(newline->flags & ML_SKEWTD);
}
else
{
texturevpeg = sides[rover->master->sidenum[0]].rowoffset;
texturevpeg = viewworld->sides[rover->master->sidenum[0]].rowoffset;
attachtobottom = !!(gl_linedef->flags & ML_DONTPEGBOTTOM);
slopeskew = !!(rover->master->flags & ML_SKEWTD);
}
......@@ -1741,13 +1618,13 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
if ((high1 < lowcut && highslope1 < lowcutslope) || (low1 > highcut && lowslope1 > highcutslope))
continue;
texnum = R_GetTextureNum(sides[rover->master->sidenum[0]].midtexture);
texnum = R_GetTextureNum(viewworld->sides[rover->master->sidenum[0]].midtexture);
if (rover->master->flags & ML_TFERLINE)
{
size_t linenum = gl_curline->linedef-gl_backsector->lines[0];
newline = rover->master->frontsector->lines[0] + linenum;
texnum = R_GetTextureNum(sides[newline->sidenum[0]].midtexture);
texnum = R_GetTextureNum(viewworld->sides[newline->sidenum[0]].midtexture);
}
h = P_GetFFloorTopZAt (rover, v1x, v1y);
hS = P_GetFFloorTopZAt (rover, v2x, v2y);
......@@ -1785,13 +1662,13 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
if (newline)
{
wallVerts[3].t = wallVerts[2].t = (*rover->topheight - h + sides[newline->sidenum[0]].rowoffset) * grTex->scaleY;
wallVerts[0].t = wallVerts[1].t = (h - l + (*rover->topheight - h + sides[newline->sidenum[0]].rowoffset)) * grTex->scaleY;
wallVerts[3].t = wallVerts[2].t = (*rover->topheight - h + viewworld->sides[newline->sidenum[0]].rowoffset) * grTex->scaleY;
wallVerts[0].t = wallVerts[1].t = (h - l + (*rover->topheight - h + viewworld->sides[newline->sidenum[0]].rowoffset)) * grTex->scaleY;
}
else
{
wallVerts[3].t = wallVerts[2].t = (*rover->topheight - h + sides[rover->master->sidenum[0]].rowoffset) * grTex->scaleY;
wallVerts[0].t = wallVerts[1].t = (h - l + (*rover->topheight - h + sides[rover->master->sidenum[0]].rowoffset)) * grTex->scaleY;
wallVerts[3].t = wallVerts[2].t = (*rover->topheight - h + viewworld->sides[rover->master->sidenum[0]].rowoffset) * grTex->scaleY;
wallVerts[0].t = wallVerts[1].t = (h - l + (*rover->topheight - h + viewworld->sides[rover->master->sidenum[0]].rowoffset)) * grTex->scaleY;
}
wallVerts[0].s = wallVerts[3].s = cliplow * grTex->scaleX;
......@@ -1845,7 +1722,6 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
//
// e6y: Check whether the player can look beyond this line
//
#ifdef NEWCLIP
boolean checkforemptylines = true;
// Don't modify anything here, just check
// Kalaron: Modified for sloped linedefs
......@@ -1855,9 +1731,9 @@ static boolean CheckClip(seg_t * seg, sector_t * afrontsector, sector_t * abacks
fixed_t backf1, backf2, backc1, backc2; // back floor ceiling ends
boolean bothceilingssky = false, bothfloorssky = false;
if (abacksector->ceilingpic == skyflatnum && afrontsector->ceilingpic == skyflatnum)
if (abacksector->ceilingpic == viewworld->skyflatnum && afrontsector->ceilingpic == viewworld->skyflatnum)
bothceilingssky = true;
if (abacksector->floorpic == skyflatnum && afrontsector->floorpic == skyflatnum)
if (abacksector->floorpic == viewworld->skyflatnum && afrontsector->floorpic == viewworld->skyflatnum)
bothfloorssky = true;
// GZDoom method of sloped line clipping
......@@ -1928,295 +1804,6 @@ static boolean CheckClip(seg_t * seg, sector_t * afrontsector, sector_t * abacks
return false;
}
#else
//Hurdler: just like in r_bsp.c
#if 1
#define MAXSEGS MAXVIDWIDTH/2+1
#else
//Alam_GBC: Or not (may cause overflow)
#define MAXSEGS 128
#endif
// hw_newend is one past the last valid seg
static cliprange_t * hw_newend;
static cliprange_t gl_solidsegs[MAXSEGS];
// needs fix: walls are incorrectly clipped one column less
static consvar_t cv_glclipwalls = CVAR_INIT ("gr_clipwalls", "Off", 0, CV_OnOff, NULL);
static void printsolidsegs(void)
{
cliprange_t * start;
if (!hw_newend)
return;
for (start = gl_solidsegs;start != hw_newend;start++)
{
CONS_Debug(DBG_RENDER, "%d-%d|",start->first,start->last);
}
CONS_Debug(DBG_RENDER, "\n\n");
}
//
//
//
static void HWR_ClipSolidWallSegment(INT32 first, INT32 last)
{
cliprange_t *next, *start;
float lowfrac, highfrac;
boolean poorhack = false;
// Find the first range that touches the range
// (adjacent pixels are touching).
start = gl_solidsegs;
while (start->last < first-1)
start++;
if (first < start->first)
{
if (last < start->first-1)
{
// Post is entirely visible (above start),
// so insert a new clippost.
HWR_StoreWallRange(first, last);
next = hw_newend;
hw_newend++;
while (next != start)
{
*next = *(next-1);
next--;
}
next->first = first;
next->last = last;
printsolidsegs();
return;
}
// There is a fragment above *start.
if (!cv_glclipwalls.value)
{
if (!poorhack) HWR_StoreWallRange(first, last);
poorhack = true;
}
else
{
highfrac = HWR_ClipViewSegment(start->first+1, (polyvertex_t *)gl_curline->pv1, (polyvertex_t *)gl_curline->pv2);
HWR_StoreWallRange(0, highfrac);
}
// Now adjust the clip size.
start->first = first;
}
// Bottom contained in start?
if (last <= start->last)
{
printsolidsegs();
return;
}
next = start;
while (last >= (next+1)->first-1)
{
// There is a fragment between two posts.
if (!cv_glclipwalls.value)
{
if (!poorhack) HWR_StoreWallRange(first,last);
poorhack = true;
}
else
{
lowfrac = HWR_ClipViewSegment(next->last-1, (polyvertex_t *)gl_curline->pv1, (polyvertex_t *)gl_curline->pv2);
highfrac = HWR_ClipViewSegment((next+1)->first+1, (polyvertex_t *)gl_curline->pv1, (polyvertex_t *)gl_curline->pv2);
HWR_StoreWallRange(lowfrac, highfrac);
}
next++;
if (last <= next->last)
{
// Bottom is contained in next.
// Adjust the clip size.
start->last = next->last;
goto crunch;
}
}
if (first == next->first+1) // 1 line texture
{
if (!cv_glclipwalls.value)
{
if (!poorhack) HWR_StoreWallRange(first,last);
poorhack = true;
}
else
HWR_StoreWallRange(0, 1);
}
else
{
// There is a fragment after *next.
if (!cv_glclipwalls.value)
{
if (!poorhack) HWR_StoreWallRange(first,last);
poorhack = true;
}
else
{
lowfrac = HWR_ClipViewSegment(next->last-1, (polyvertex_t *)gl_curline->pv1, (polyvertex_t *)gl_curline->pv2);
HWR_StoreWallRange(lowfrac, 1);
}
}
// Adjust the clip size.
start->last = last;
// Remove start+1 to next from the clip list,
// because start now covers their area.
crunch:
if (next == start)
{
printsolidsegs();
// Post just extended past the bottom of one post.
return;
}
while (next++ != hw_newend)
{
// Remove a post.
*++start = *next;
}
hw_newend = start;
printsolidsegs();
}
//
// handle LineDefs with upper and lower texture (windows)
//
static void HWR_ClipPassWallSegment(INT32 first, INT32 last)
{
cliprange_t *start;
float lowfrac, highfrac;
//to allow noclipwalls but still solidseg reject of non-visible walls
boolean poorhack = false;
// Find the first range that touches the range
// (adjacent pixels are touching).
start = gl_solidsegs;
while (start->last < first - 1)
start++;
if (first < start->first)
{
if (last < start->first-1)
{
// Post is entirely visible (above start).
HWR_StoreWallRange(0, 1);
return;
}
// There is a fragment above *start.
if (!cv_glclipwalls.value)
{ //20/08/99: Changed by Hurdler (taken from faB's code)
if (!poorhack) HWR_StoreWallRange(0, 1);
poorhack = true;
}
else
{
highfrac = HWR_ClipViewSegment(min(start->first + 1,
start->last), (polyvertex_t *)gl_curline->pv1,
(polyvertex_t *)gl_curline->pv2);
HWR_StoreWallRange(0, highfrac);
}
}
// Bottom contained in start?
if (last <= start->last)
return;
while (last >= (start+1)->first-1)
{
// There is a fragment between two posts.
if (!cv_glclipwalls.value)
{
if (!poorhack) HWR_StoreWallRange(0, 1);
poorhack = true;
}
else
{
lowfrac = HWR_ClipViewSegment(max(start->last-1,start->first), (polyvertex_t *)gl_curline->pv1, (polyvertex_t *)gl_curline->pv2);
highfrac = HWR_ClipViewSegment(min((start+1)->first+1,(start+1)->last), (polyvertex_t *)gl_curline->pv1, (polyvertex_t *)gl_curline->pv2);
HWR_StoreWallRange(lowfrac, highfrac);
}
start++;
if (last <= start->last)
return;
}
if (first == start->first+1) // 1 line texture
{
if (!cv_glclipwalls.value)
{
if (!poorhack) HWR_StoreWallRange(0, 1);
poorhack = true;
}
else
HWR_StoreWallRange(0, 1);
}
else
{
// There is a fragment after *next.
if (!cv_glclipwalls.value)
{
if (!poorhack) HWR_StoreWallRange(0,1);
poorhack = true;
}
else
{
lowfrac = HWR_ClipViewSegment(max(start->last - 1,
start->first), (polyvertex_t *)gl_curline->pv1,
(polyvertex_t *)gl_curline->pv2);
HWR_StoreWallRange(lowfrac, 1);
}
}
}
// --------------------------------------------------------------------------
// HWR_ClipToSolidSegs check if it is hide by wall (solidsegs)
// --------------------------------------------------------------------------
static boolean HWR_ClipToSolidSegs(INT32 first, INT32 last)
{
cliprange_t * start;
// Find the first range that touches the range
// (adjacent pixels are touching).
start = gl_solidsegs;
while (start->last < first-1)
start++;
if (first < start->first)
return true;
// Bottom contained in start?
if (last <= start->last)
return false;
return true;
}
//
// HWR_ClearClipSegs
//
static void HWR_ClearClipSegs(void)
{
gl_solidsegs[0].first = -0x7fffffff;
gl_solidsegs[0].last = -1;
gl_solidsegs[1].first = vid.width; //viewwidth;
gl_solidsegs[1].last = 0x7fffffff;
hw_newend = gl_solidsegs+2;
}
#endif // NEWCLIP
// -----------------+
// HWR_AddLine : Clips the given segment and adds any visible pieces to the line list.
......@@ -2226,11 +1813,6 @@ static void HWR_ClearClipSegs(void)
static void HWR_AddLine(seg_t * line)
{
angle_t angle1, angle2;
#ifndef NEWCLIP
INT32 x1, x2;
angle_t span, tspan;
boolean bothceilingssky = false, bothfloorssky = false;
#endif
// SoM: Backsector needs to be run through R_FakeFlat
static sector_t tempsec;
......@@ -2250,8 +1832,7 @@ static void HWR_AddLine(seg_t * line)
angle1 = R_PointToAngle64(v1x, v1y);
angle2 = R_PointToAngle64(v2x, v2y);
#ifdef NEWCLIP
// PrBoom: Back side, i.e. backface culling - read: endAngle >= startAngle!
// PrBoom: Back side, i.e. backface culling - read: endAngle >= startAngle!
if (angle2 - angle1 < ANGLE_180)
return;
......@@ -2263,90 +1844,9 @@ static void HWR_AddLine(seg_t * line)
}
checkforemptylines = true;
#else
// Clip to view edges.
span = angle1 - angle2;
// backface culling : span is < ANGLE_180 if ang1 > ang2 : the seg is facing
if (span >= ANGLE_180)
return;
// Global angle needed by segcalc.
//rw_angle1 = angle1;
angle1 -= dup_viewangle;
angle2 -= dup_viewangle;
tspan = angle1 + gl_clipangle;
if (tspan > 2*gl_clipangle)
{
tspan -= 2*gl_clipangle;
// Totally off the left edge?
if (tspan >= span)
return;
angle1 = gl_clipangle;
}
tspan = gl_clipangle - angle2;
if (tspan > 2*gl_clipangle)
{
tspan -= 2*gl_clipangle;
// Totally off the left edge?
if (tspan >= span)
return;
angle2 = (angle_t)-(signed)gl_clipangle;
}
#if 0
{
float fx1,fx2,fy1,fy2;
//BP: test with a better projection than viewangletox[R_PointToAngle(angle)]
// do not enable this at release 4 mul and 2 div
fx1 = ((polyvertex_t *)(line->pv1))->x-gl_viewx;
fy1 = ((polyvertex_t *)(line->pv1))->y-gl_viewy;
fy2 = (fx1 * gl_viewcos + fy1 * gl_viewsin);
if (fy2 < 0)
// the point is back
fx1 = 0;
else
fx1 = gl_windowcenterx + (fx1 * gl_viewsin - fy1 * gl_viewcos) * gl_centerx / fy2;
fx2 = ((polyvertex_t *)(line->pv2))->x-gl_viewx;
fy2 = ((polyvertex_t *)(line->pv2))->y-gl_viewy;
fy1 = (fx2 * gl_viewcos + fy2 * gl_viewsin);
if (fy1 < 0)
// the point is back
fx2 = vid.width;
else
fx2 = gl_windowcenterx + (fx2 * gl_viewsin - fy2 * gl_viewcos) * gl_centerx / fy1;
x1 = fx1+0.5f;
x2 = fx2+0.5f;
}
#else
// The seg is in the view range,
// but not necessarily visible.
angle1 = (angle1+ANGLE_90)>>ANGLETOFINESHIFT;
angle2 = (angle2+ANGLE_90)>>ANGLETOFINESHIFT;
x1 = gl_viewangletox[angle1];
x2 = gl_viewangletox[angle2];
#endif
// Does not cross a pixel?
// if (x1 == x2)
/* {
// BP: HERE IS THE MAIN PROBLEM !
//CONS_Debug(DBG_RENDER, "tineline\n");
return;
}
*/
#endif
gl_backsector = line->backsector;
#ifdef NEWCLIP
if (!line->backsector)
{
gld_clipper_SafeAddClipRange(angle2, angle1);
......@@ -2357,9 +1857,9 @@ static void HWR_AddLine(seg_t * line)
gl_backsector = R_FakeFlat(gl_backsector, &tempsec, NULL, NULL, true);
if (gl_backsector->ceilingpic == skyflatnum && gl_frontsector->ceilingpic == skyflatnum)
if (gl_backsector->ceilingpic == viewworld->skyflatnum && gl_frontsector->ceilingpic == viewworld->skyflatnum)
bothceilingssky = true;
if (gl_backsector->floorpic == skyflatnum && gl_frontsector->floorpic == skyflatnum)
if (gl_backsector->floorpic == viewworld->skyflatnum && gl_frontsector->floorpic == viewworld->skyflatnum)
bothfloorssky = true;
if (bothceilingssky && bothfloorssky) // everything's sky? let's save us a bit of time then
......@@ -2388,115 +1888,6 @@ static void HWR_AddLine(seg_t * line)
}
HWR_ProcessSeg(); // Doesn't need arguments because they're defined globally :D
return;
#else
// Single sided line?
if (!gl_backsector)
goto clipsolid;
gl_backsector = R_FakeFlat(gl_backsector, &tempsec, NULL, NULL, true);
if (gl_backsector->ceilingpic == skyflatnum && gl_frontsector->ceilingpic == skyflatnum)
bothceilingssky = true;
if (gl_backsector->floorpic == skyflatnum && gl_frontsector->floorpic == skyflatnum)
bothfloorssky = true;
if (bothceilingssky && bothfloorssky) // everything's sky? let's save us a bit of time then
{
if (!line->polyseg &&
!line->sidedef->midtexture
&& ((!gl_frontsector->ffloors && !gl_backsector->ffloors)
|| Tag_Compare(&gl_frontsector->tags, &gl_backsector->tags)))
return; // line is empty, don't even bother
goto clippass; // treat like wide open window instead
}
if (gl_frontsector->f_slope || gl_frontsector->c_slope || gl_backsector->f_slope || gl_backsector->c_slope)
{
fixed_t frontf1,frontf2, frontc1, frontc2; // front floor/ceiling ends
fixed_t backf1, backf2, backc1, backc2; // back floor ceiling ends
#define SLOPEPARAMS(slope, end1, end2, normalheight) \
end1 = P_GetZAt(slope, v1x, v1y, normalheight); \
end2 = P_GetZAt(slope, v2x, v2y, normalheight);
SLOPEPARAMS(gl_frontsector->f_slope, frontf1, frontf2, gl_frontsector-> floorheight)
SLOPEPARAMS(gl_frontsector->c_slope, frontc1, frontc2, gl_frontsector->ceilingheight)
SLOPEPARAMS( gl_backsector->f_slope, backf1, backf2, gl_backsector-> floorheight)
SLOPEPARAMS( gl_backsector->c_slope, backc1, backc2, gl_backsector->ceilingheight)
#undef SLOPEPARAMS
// if both ceilings are skies, consider it always "open"
// same for floors
if (!bothceilingssky && !bothfloorssky)
{
// Closed door.
if ((backc1 <= frontf1 && backc2 <= frontf2)
|| (backf1 >= frontc1 && backf2 >= frontc2))
{
goto clipsolid;
}
// Check for automap fix.
if (backc1 <= backf1 && backc2 <= backf2
&& ((backc1 >= frontc1 && backc2 >= frontc2) || gl_curline->sidedef->toptexture)
&& ((backf1 <= frontf1 && backf2 >= frontf2) || gl_curline->sidedef->bottomtexture))
goto clipsolid;
}
// Window.
if (!bothceilingssky) // ceilings are always the "same" when sky
if (backc1 != frontc1 || backc2 != frontc2)
goto clippass;
if (!bothfloorssky) // floors are always the "same" when sky
if (backf1 != frontf1 || backf2 != frontf2)
goto clippass;
}
else
{
// if both ceilings are skies, consider it always "open"
// same for floors
if (!bothceilingssky && !bothfloorssky)
{
// Closed door.
if (gl_backsector->ceilingheight <= gl_frontsector->floorheight ||
gl_backsector->floorheight >= gl_frontsector->ceilingheight)
goto clipsolid;
// Check for automap fix.
if (gl_backsector->ceilingheight <= gl_backsector->floorheight
&& ((gl_backsector->ceilingheight >= gl_frontsector->ceilingheight) || gl_curline->sidedef->toptexture)
&& ((gl_backsector->floorheight <= gl_backsector->floorheight) || gl_curline->sidedef->bottomtexture))
goto clipsolid;
}
// Window.
if (!bothceilingssky) // ceilings are always the "same" when sky
if (gl_backsector->ceilingheight != gl_frontsector->ceilingheight)
goto clippass;
if (!bothfloorssky) // floors are always the "same" when sky
if (gl_backsector->floorheight != gl_frontsector->floorheight)
goto clippass;
}
// Reject empty lines used for triggers and special events.
// Identical floor and ceiling on both sides,
// identical light levels on both sides,
// and no middle texture.
if (R_IsEmptyLine(gl_curline, gl_frontsector, gl_backsector))
return;
clippass:
if (x1 == x2)
{ x2++;x1 -= 2; }
HWR_ClipPassWallSegment(x1, x2-1);
return;
clipsolid:
if (x1 == x2)
goto clippass;
HWR_ClipSolidWallSegment(x1, x2-1);
#endif
}
// HWR_CheckBBox
......@@ -2511,10 +1902,6 @@ static boolean HWR_CheckBBox(fixed_t *bspcoord)
INT32 boxpos;
fixed_t px1, py1, px2, py2;
angle_t angle1, angle2;
#ifndef NEWCLIP
INT32 sx1, sx2;
angle_t span, tspan;
#endif
// Find the corners of the box
// that define the edges from current viewpoint.
......@@ -2540,59 +1927,9 @@ static boolean HWR_CheckBBox(fixed_t *bspcoord)
px2 = bspcoord[checkcoord[boxpos][2]];
py2 = bspcoord[checkcoord[boxpos][3]];
#ifdef NEWCLIP
angle1 = R_PointToAngle64(px1, py1);
angle2 = R_PointToAngle64(px2, py2);
return gld_clipper_SafeCheckRange(angle2, angle1);
#else
// check clip list for an open space
angle1 = R_PointToAngle2(dup_viewx>>1, dup_viewy>>1, px1>>1, py1>>1) - dup_viewangle;
angle2 = R_PointToAngle2(dup_viewx>>1, dup_viewy>>1, px2>>1, py2>>1) - dup_viewangle;
span = angle1 - angle2;
// Sitting on a line?
if (span >= ANGLE_180)
return true;
tspan = angle1 + gl_clipangle;
if (tspan > 2*gl_clipangle)
{
tspan -= 2*gl_clipangle;
// Totally off the left edge?
if (tspan >= span)
return false;
angle1 = gl_clipangle;
}
tspan = gl_clipangle - angle2;
if (tspan > 2*gl_clipangle)
{
tspan -= 2*gl_clipangle;
// Totally off the left edge?
if (tspan >= span)
return false;
angle2 = (angle_t)-(signed)gl_clipangle;
}
// Find the first clippost
// that touches the source post
// (adjacent pixels are touching).
angle1 = (angle1+ANGLE_90)>>ANGLETOFINESHIFT;
angle2 = (angle2+ANGLE_90)>>ANGLETOFINESHIFT;
sx1 = gl_viewangletox[angle1];
sx2 = gl_viewangletox[angle2];
// Does not cross a pixel.
if (sx1 == sx2)
return false;
return HWR_ClipToSolidSegs(sx1, sx2 - 1);
#endif
}
//
......@@ -2836,14 +2173,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], po_ptrs[i], false, polyobjsector->floorheight,
HWR_AddTransparentPolyobjectFloor(&viewworld->flats[polyobjsector->floorpic], po_ptrs[i], false, polyobjsector->floorheight,
(light == -1 ? gl_frontsector->lightlevel : *gl_frontsector->lightlist[light].lightlevel), Surf.PolyColor.s.alpha, polyobjsector, blendmode, (light == -1 ? gl_frontsector->extra_colormap : *gl_frontsector->lightlist[light].extra_colormap));
}
else
{
HWR_GetLevelFlat(&levelflats[polyobjsector->floorpic]);
HWR_GetLevelFlat(&viewworld->flats[polyobjsector->floorpic]);
HWR_RenderPolyObjectPlane(po_ptrs[i], false, polyobjsector->floorheight, PF_Occlude,
(light == -1 ? gl_frontsector->lightlevel : *gl_frontsector->lightlist[light].lightlevel), &levelflats[polyobjsector->floorpic],
(light == -1 ? gl_frontsector->lightlevel : *gl_frontsector->lightlist[light].lightlevel), &viewworld->flats[polyobjsector->floorpic],
polyobjsector, 255, (light == -1 ? gl_frontsector->extra_colormap : *gl_frontsector->lightlist[light].extra_colormap));
}
}
......@@ -2859,14 +2196,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], po_ptrs[i], true, polyobjsector->ceilingheight,
HWR_AddTransparentPolyobjectFloor(&viewworld->flats[polyobjsector->ceilingpic], po_ptrs[i], true, polyobjsector->ceilingheight,
(light == -1 ? gl_frontsector->lightlevel : *gl_frontsector->lightlist[light].lightlevel), Surf.PolyColor.s.alpha, polyobjsector, blendmode, (light == -1 ? gl_frontsector->extra_colormap : *gl_frontsector->lightlist[light].extra_colormap));
}
else
{
HWR_GetLevelFlat(&levelflats[polyobjsector->ceilingpic]);
HWR_GetLevelFlat(&viewworld->flats[polyobjsector->ceilingpic]);
HWR_RenderPolyObjectPlane(po_ptrs[i], true, polyobjsector->ceilingheight, PF_Occlude,
(light == -1 ? gl_frontsector->lightlevel : *gl_frontsector->lightlist[light].lightlevel), &levelflats[polyobjsector->ceilingpic],
(light == -1 ? gl_frontsector->lightlevel : *gl_frontsector->lightlist[light].lightlevel), &viewworld->flats[polyobjsector->ceilingpic],
polyobjsector, 255, (light == -1 ? gl_frontsector->extra_colormap : *gl_frontsector->lightlist[light].extra_colormap));
}
}
......@@ -2902,53 +2239,36 @@ static void HWR_Subsector(size_t num)
ffloor_t *rover;
#ifdef PARANOIA //no risk while developing, enough debugging nights!
if (num >= addsubsector)
if (num >= viewworld->numextrasubsectors)
I_Error("HWR_Subsector: ss %s with numss = %s, addss = %s\n",
sizeu1(num), sizeu2(numsubsectors), sizeu3(addsubsector));
/*if (num >= numsubsectors)
I_Error("HWR_Subsector: ss %i with numss = %i",
num,
numsubsectors);*/
sizeu1(num), sizeu2(numsubsectors), sizeu3(viewworld->numextrasubsectors));
#endif
if (num < numsubsectors)
if (num < viewworld->numsubsectors)
{
// subsector
sub = &subsectors[num];
sub = &viewworld->subsectors[num];
// sector
gl_frontsector = sub->sector;
// how many linedefs
count = sub->numlines;
// first line seg
line = &segs[sub->firstline];
line = &viewworld->segs[sub->firstline];
}
else
{
// there are no segs but only planes
sub = &subsectors[0];
sub = &viewworld->subsectors[0];
gl_frontsector = sub->sector;
count = 0;
line = NULL;
}
//SoM: 4/7/2000: Test to make Boom water work in Hardware mode.
gl_frontsector = R_FakeFlat(gl_frontsector, &tempsec, &floorlightlevel,
&ceilinglightlevel, false);
//FIXME: Use floorlightlevel and ceilinglightlevel insted of lightlevel.
gl_frontsector = R_FakeFlat(gl_frontsector, &tempsec, &floorlightlevel, &ceilinglightlevel, false);
floorcolormap = ceilingcolormap = gl_frontsector->extra_colormap;
// ------------------------------------------------------------------------
// sector lighting, DISABLED because it's done in HWR_StoreWallRange
// ------------------------------------------------------------------------
/// \todo store a RGBA instead of just intensity, allow coloured sector lighting
//light = (FUBYTE)(sub->sector->lightlevel & 0xFF) / 255.0f;
//gl_cursectorlight.red = light;
//gl_cursectorlight.green = light;
//gl_cursectorlight.blue = light;
//gl_cursectorlight.alpha = light;
// ----- end special tricks -----
cullFloorHeight = P_GetSectorFloorZAt (gl_frontsector, viewx, viewy);
cullCeilingHeight = P_GetSectorCeilingZAt(gl_frontsector, viewx, viewy);
......@@ -2963,7 +2283,8 @@ static void HWR_Subsector(size_t num)
{
for (rover = gl_frontsector->ffloors; rover; rover = rover->next)
{
sector_t *controlSec = &sectors[rover->secnum];
sector_t *controlSec = &viewworld->sectors[rover->secnum];
if (controlSec->moved == true)
{
anyMoved = true;
......@@ -2995,59 +2316,34 @@ static void HWR_Subsector(size_t num)
sub->sector->extra_colormap = gl_frontsector->extra_colormap;
// render floor ?
#ifdef DOPLANES
// yeah, easy backface cull! :)
if (cullFloorHeight < dup_viewz)
if (sub->validcount != validcount)
{
if (gl_frontsector->floorpic != skyflatnum)
// yeah, easy backface cull! :)
if (cullFloorHeight < dup_viewz && gl_frontsector->floorpic != viewworld->skyflatnum)
{
if (sub->validcount != validcount)
{
HWR_GetLevelFlat(&levelflats[gl_frontsector->floorpic]);
HWR_RenderPlane(sub, &extrasubsectors[num], false,
// Hack to make things continue to work around slopes.
locFloorHeight == cullFloorHeight ? locFloorHeight : gl_frontsector->floorheight,
// We now return you to your regularly scheduled rendering.
PF_Occlude, floorlightlevel, &levelflats[gl_frontsector->floorpic], NULL, 255, floorcolormap);
}
HWR_GetLevelFlat(&viewworld->flats[gl_frontsector->floorpic]);
HWR_RenderPlane(sub, &viewworld->extrasubsectors[num], false,
// Hack to make things continue to work around slopes.
locFloorHeight == cullFloorHeight ? locFloorHeight : gl_frontsector->floorheight,
// We now return you to your regularly scheduled rendering.
PF_Occlude, floorlightlevel, &viewworld->flats[gl_frontsector->floorpic], NULL, 255, floorcolormap);
}
else
{
#ifdef POLYSKY
HWR_RenderSkyPlane(&extrasubsectors[num], locFloorHeight);
#endif
}
}
if (cullCeilingHeight > dup_viewz)
{
if (gl_frontsector->ceilingpic != skyflatnum)
if (cullCeilingHeight > dup_viewz && gl_frontsector->ceilingpic != viewworld->skyflatnum)
{
if (sub->validcount != validcount)
{
HWR_GetLevelFlat(&levelflats[gl_frontsector->ceilingpic]);
HWR_RenderPlane(sub, &extrasubsectors[num], true,
// Hack to make things continue to work around slopes.
locCeilingHeight == cullCeilingHeight ? locCeilingHeight : gl_frontsector->ceilingheight,
// We now return you to your regularly scheduled rendering.
PF_Occlude, ceilinglightlevel, &levelflats[gl_frontsector->ceilingpic], NULL, 255, ceilingcolormap);
}
}
else
{
#ifdef POLYSKY
HWR_RenderSkyPlane(&extrasubsectors[num], locCeilingHeight);
#endif
HWR_GetLevelFlat(&viewworld->flats[gl_frontsector->ceilingpic]);
HWR_RenderPlane(sub, &viewworld->extrasubsectors[num], true,
// Hack to make things continue to work around slopes.
locCeilingHeight == cullCeilingHeight ? locCeilingHeight : gl_frontsector->ceilingheight,
// We now return you to your regularly scheduled rendering.
PF_Occlude, ceilinglightlevel, &viewworld->flats[gl_frontsector->ceilingpic], NULL, 255, ceilingcolormap);
}
}
#ifndef POLYSKY
// Moved here because before, when above the ceiling and the floor does not have the sky flat, it doesn't draw the sky
if (gl_frontsector->ceilingpic == skyflatnum || gl_frontsector->floorpic == skyflatnum)
if (gl_frontsector->ceilingpic == viewworld->skyflatnum || gl_frontsector->floorpic == viewworld->skyflatnum)
drawsky = true;
#endif
#ifdef R_FAKEFLOORS
if (gl_frontsector->ffloors)
{
/// \todo fix light, xoffs, yoffs, extracolormap ?
......@@ -3077,9 +2373,9 @@ static void HWR_Subsector(size_t num)
light = R_GetPlaneLight(gl_frontsector, centerHeight, dup_viewz < cullHeight ? true : false);
alpha = HWR_FogBlockAlpha(*gl_frontsector->lightlist[light].lightlevel, rover->master->frontsector->extra_colormap);
HWR_AddTransparentFloor(0,
&extrasubsectors[num],
false,
HWR_AddTransparentFloor(NULL,
&viewworld->extrasubsectors[num],
false,
*rover->bottomheight,
*gl_frontsector->lightlist[light].lightlevel,
alpha, rover->master->frontsector, PF_Fog|PF_NoTexture,
......@@ -3089,9 +2385,9 @@ static void HWR_Subsector(size_t num)
{
light = R_GetPlaneLight(gl_frontsector, centerHeight, dup_viewz < cullHeight ? true : false);
HWR_AddTransparentFloor(&levelflats[*rover->bottompic],
&extrasubsectors[num],
false,
HWR_AddTransparentFloor(&viewworld->flats[*rover->bottompic],
&viewworld->extrasubsectors[num],
false,
*rover->bottomheight,
*gl_frontsector->lightlist[light].lightlevel,
rover->alpha-1 > 255 ? 255 : rover->alpha-1, rover->master->frontsector,
......@@ -3100,9 +2396,9 @@ static void HWR_Subsector(size_t num)
}
else
{
HWR_GetLevelFlat(&levelflats[*rover->bottompic]);
HWR_GetLevelFlat(&viewworld->flats[*rover->bottompic]);
light = R_GetPlaneLight(gl_frontsector, centerHeight, dup_viewz < cullHeight ? true : false);
HWR_RenderPlane(sub, &extrasubsectors[num], false, *rover->bottomheight, HWR_RippleBlend(gl_frontsector, rover, false)|PF_Occlude, *gl_frontsector->lightlist[light].lightlevel, &levelflats[*rover->bottompic],
HWR_RenderPlane(sub, &viewworld->extrasubsectors[num], false, *rover->bottomheight, HWR_RippleBlend(gl_frontsector, rover, false)|PF_Occlude, *gl_frontsector->lightlist[light].lightlevel, &viewworld->flats[*rover->bottompic],
rover->master->frontsector, 255, *gl_frontsector->lightlist[light].extra_colormap);
}
}
......@@ -3123,21 +2419,21 @@ static void HWR_Subsector(size_t num)
light = R_GetPlaneLight(gl_frontsector, centerHeight, dup_viewz < cullHeight ? true : false);
alpha = HWR_FogBlockAlpha(*gl_frontsector->lightlist[light].lightlevel, rover->master->frontsector->extra_colormap);
HWR_AddTransparentFloor(0,
&extrasubsectors[num],
true,
HWR_AddTransparentFloor(NULL,
&viewworld->extrasubsectors[num],
true,
*rover->topheight,
*gl_frontsector->lightlist[light].lightlevel,
alpha, rover->master->frontsector, PF_Fog|PF_NoTexture,
true, rover->master->frontsector->extra_colormap);
true, rover->master->frontsector->extra_colormap);
}
else if ((rover->fofflags & FOF_TRANSLUCENT && !(rover->fofflags & FOF_SPLAT)) || rover->blend)
{
light = R_GetPlaneLight(gl_frontsector, centerHeight, dup_viewz < cullHeight ? true : false);
HWR_AddTransparentFloor(&levelflats[*rover->toppic],
&extrasubsectors[num],
true,
HWR_AddTransparentFloor(&viewworld->flats[*rover->toppic],
&viewworld->extrasubsectors[num],
true,
*rover->topheight,
*gl_frontsector->lightlist[light].lightlevel,
rover->alpha-1 > 255 ? 255 : rover->alpha-1, rover->master->frontsector,
......@@ -3146,16 +2442,14 @@ static void HWR_Subsector(size_t num)
}
else
{
HWR_GetLevelFlat(&levelflats[*rover->toppic]);
HWR_GetLevelFlat(&viewworld->flats[*rover->toppic]);
light = R_GetPlaneLight(gl_frontsector, centerHeight, dup_viewz < cullHeight ? true : false);
HWR_RenderPlane(sub, &extrasubsectors[num], true, *rover->topheight, HWR_RippleBlend(gl_frontsector, rover, false)|PF_Occlude, *gl_frontsector->lightlist[light].lightlevel, &levelflats[*rover->toppic],
HWR_RenderPlane(sub, &viewworld->extrasubsectors[num], true, *rover->topheight, HWR_RippleBlend(gl_frontsector, rover, false)|PF_Occlude, *gl_frontsector->lightlist[light].lightlevel, &viewworld->flats[*rover->toppic],
rover->master->frontsector, 255, *gl_frontsector->lightlist[light].extra_colormap);
}
}
}
}
#endif
#endif //doplanes
// Draw all the polyobjects in this subsector
if (sub->polyList)
......@@ -3187,10 +2481,10 @@ static void HWR_Subsector(size_t num)
}
}
// Hurder ici se passe les choses INT32�essantes!
// on vient de tracer le sol et le plafond
// on trace �pr�ent d'abord les sprites et ensuite les murs
// hurdler: faux: on ajoute seulement les sprites, le murs sont trac� d'abord
// Hurder interesting things are happening here!
// we have just drawn the floor and the ceiling
// we now draw the sprites first and then the walls
// hurdler: false: we only add the sprites, the walls are drawn first
if (line)
{
// draw sprites first, coz they are clipped to the solidsegs of
......@@ -3207,7 +2501,6 @@ static void HWR_Subsector(size_t num)
while (count--)
{
if (!line->glseg && !line->polyseg) // ignore segs that belong to polyobjects
HWR_AddLine(line);
line++;
......@@ -3248,34 +2541,7 @@ fixed_t *hwbbox;
static void HWR_RenderBSPNode(INT32 bspnum)
{
/*//GZDoom code
if(bspnum == -1)
{
HWR_Subsector(subsectors);
return;
}
while(!((size_t)bspnum&(~NF_SUBSECTOR))) // Keep going until found a subsector
{
node_t *bsp = &nodes[bspnum];
// Decide which side the view point is on
INT32 side = R_PointOnSide(dup_viewx, dup_viewy, bsp);
// Recursively divide front space (toward the viewer)
HWR_RenderBSPNode(bsp->children[side]);
// Possibly divide back space (away from viewer)
side ^= 1;
if (!HWR_CheckBBox(bsp->bbox[side]))
return;
bspnum = bsp->children[side];
}
HWR_Subsector(bspnum-1);
*/
node_t *bsp = &nodes[bspnum];
node_t *bsp = &viewworld->nodes[bspnum];
// Decide which side the view point is on
INT32 side;
......@@ -3287,12 +2553,10 @@ static void HWR_RenderBSPNode(INT32 bspnum)
{
if (bspnum == -1)
{
//*(gl_drawsubsector_p++) = 0;
HWR_Subsector(0);
}
else
{
//*(gl_drawsubsector_p++) = bspnum&(~NF_SUBSECTOR);
HWR_Subsector(bspnum&(~NF_SUBSECTOR));
}
return;
......@@ -3316,100 +2580,6 @@ static void HWR_RenderBSPNode(INT32 bspnum)
}
}
/*
//
// Clear 'stack' of subsectors to draw
//
static void HWR_ClearDrawSubsectors(void)
{
gl_drawsubsector_p = gl_drawsubsectors;
}
//
// Draw subsectors pushed on the drawsubsectors 'stack', back to front
//
static void HWR_RenderSubsectors(void)
{
while (gl_drawsubsector_p > gl_drawsubsectors)
{
HWR_RenderBSPNode(
lastsubsec->nextsubsec = bspnum & (~NF_SUBSECTOR);
}
}
*/
// ==========================================================================
// FROM R_MAIN.C
// ==========================================================================
//BP : exactely the same as R_InitTextureMapping
void HWR_InitTextureMapping(void)
{
angle_t i;
INT32 x;
INT32 t;
fixed_t focallength;
fixed_t grcenterx;
fixed_t grcenterxfrac;
INT32 grviewwidth;
#define clipanglefov (FIELDOFVIEW>>ANGLETOFINESHIFT)
grviewwidth = vid.width;
grcenterx = grviewwidth/2;
grcenterxfrac = grcenterx<<FRACBITS;
// Use tangent table to generate viewangletox:
// viewangletox will give the next greatest x
// after the view angle.
//
// Calc focallength
// so FIELDOFVIEW angles covers SCREENWIDTH.
focallength = FixedDiv(grcenterxfrac,
FINETANGENT(FINEANGLES/4+clipanglefov/2));
for (i = 0; i < FINEANGLES/2; i++)
{
if (FINETANGENT(i) > FRACUNIT*2)
t = -1;
else if (FINETANGENT(i) < -FRACUNIT*2)
t = grviewwidth+1;
else
{
t = FixedMul(FINETANGENT(i), focallength);
t = (grcenterxfrac - t+FRACUNIT-1)>>FRACBITS;
if (t < -1)
t = -1;
else if (t > grviewwidth+1)
t = grviewwidth+1;
}
gl_viewangletox[i] = t;
}
// Scan viewangletox[] to generate xtoviewangle[]:
// xtoviewangle will give the smallest view angle
// that maps to x.
for (x = 0; x <= grviewwidth; x++)
{
i = 0;
while (gl_viewangletox[i]>x)
i++;
gl_xtoviewangle[x] = (i<<ANGLETOFINESHIFT) - ANGLE_90;
}
// Take out the fencepost cases from viewangletox.
for (i = 0; i < FINEANGLES/2; i++)
{
if (gl_viewangletox[i] == -1)
gl_viewangletox[i] = 0;
else if (gl_viewangletox[i] == grviewwidth+1)
gl_viewangletox[i] = grviewwidth;
}
gl_clipangle = gl_xtoviewangle[0];
}
// ==========================================================================
// gl_things.c
// ==========================================================================
......@@ -4713,7 +3883,7 @@ static int CompareDrawNodePlanes(const void *p1, const void *p2)
size_t n2 = *(const size_t*)p2;
if (!sortnode[n1].plane) I_Error("CompareDrawNodePlanes: Uh.. This isn't a plane! (n1)");
if (!sortnode[n2].plane) I_Error("CompareDrawNodePlanes: Uh.. This isn't a plane! (n2)");
return ABS(sortnode[n2].plane->fixedheight - viewz) - ABS(sortnode[n1].plane->fixedheight - viewz);
return abs(sortnode[n2].plane->fixedheight - viewz) - abs(sortnode[n1].plane->fixedheight - viewz);
}
//
......@@ -5610,9 +4780,6 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing)
// ==========================================================================
// Sky dome rendering, ported from PrBoom+
// ==========================================================================
static gl_sky_t gl_sky;
static void HWR_SkyDomeVertex(gl_sky_t *sky, gl_skyvertex_t *vbo, int r, int c, signed char yflip, float delta, boolean foglayer)
{
const float radians = (float)(M_PIl / 180.0f);
......@@ -5654,10 +4821,25 @@ static void HWR_SkyDomeVertex(gl_sky_t *sky, gl_skyvertex_t *vbo, int r, int c,
vbo->z = z;
}
// Clears the sky dome.
void HWR_ClearSkyDome(void)
void HWR_FreeSkyDome(void *skydome)
{
gl_sky_t *sky = &gl_sky;
gl_sky_t *sky = (gl_sky_t *)skydome;
if (sky == NULL)
return;
if (sky->loops)
free(sky->loops);
if (sky->data)
free(sky->data);
Z_Free(sky);
}
static void HWR_ClearSkyDome(world_t *w)
{
gl_sky_t *sky = (gl_sky_t *)w->sky_dome;
if (sky == NULL)
return;
if (sky->loops)
free(sky->loops);
......@@ -5678,7 +4860,7 @@ void HWR_ClearSkyDome(void)
sky->rebuild = true;
}
void HWR_BuildSkyDome(void)
static void HWR_BuildSkyDome(world_t *w)
{
int c, r;
signed char yflip;
......@@ -5686,15 +4868,22 @@ void HWR_BuildSkyDome(void)
int col_count = 4;
float delta;
gl_sky_t *sky = &gl_sky;
gl_sky_t *sky = (gl_sky_t *)w->sky_dome;
gl_skyvertex_t *vertex_p;
texture_t *texture = textures[texturetranslation[skytexture]];
INT32 skytexture = texturetranslation[w->skytexture];
texture_t *texture = textures[skytexture];
if (sky == NULL)
{
sky = Z_Calloc(sizeof(gl_sky_t), PU_STATIC, NULL);
w->sky_dome = sky;
}
sky->detail = 16;
col_count *= sky->detail;
if ((sky->columns != col_count) || (sky->rows != row_count))
HWR_ClearSkyDome();
HWR_ClearSkyDome(w);
sky->columns = col_count;
sky->rows = row_count;
......@@ -5707,7 +4896,7 @@ void HWR_BuildSkyDome(void)
if (!sky->data)
sky->data = malloc(sky->vertex_count * sizeof(sky->data[0]));
sky->texture = texturetranslation[skytexture];
sky->texture = skytexture;
sky->width = texture->width;
sky->height = texture->height;
......@@ -5793,17 +4982,23 @@ static void HWR_DrawSkyBackground(player_t *player)
}
dometransform.splitscreen = splitscreen;
HWR_GetTexture(texturetranslation[skytexture]);
HWR_GetTexture(texturetranslation[viewworld->skytexture]);
if (gl_sky.texture != texturetranslation[skytexture])
gl_sky_t *gl_sky = (gl_sky_t *)viewworld->sky_dome;
if (gl_sky == NULL)
{
HWR_ClearSkyDome();
HWR_BuildSkyDome();
HWR_BuildSkyDome(viewworld);
gl_sky = (gl_sky_t *)viewworld->sky_dome;
}
else if (gl_sky->texture != texturetranslation[viewworld->skytexture])
{
HWR_ClearSkyDome(viewworld);
HWR_BuildSkyDome(viewworld);
}
HWD.pfnSetShader(SHADER_SKY); // sky shader
HWD.pfnSetTransform(&dometransform);
HWD.pfnRenderSkyDome(&gl_sky);
HWD.pfnRenderSkyDome(gl_sky);
}
else
{
......@@ -5813,7 +5008,7 @@ static void HWR_DrawSkyBackground(player_t *player)
float aspectratio;
float angleturn;
HWR_GetTexture(texturetranslation[skytexture]);
HWR_GetTexture(texturetranslation[viewworld->skytexture]);
aspectratio = (float)vid.width/(float)vid.height;
//Hurdler: the sky is the only texture who need 4.0f instead of 1.0
......@@ -5838,9 +5033,9 @@ static void HWR_DrawSkyBackground(player_t *player)
// software doesn't draw any further than 1024 for skies anyway, but this doesn't overlap properly
// The only time this will probably be an issue is when a sky wider than 1024 is used as a sky AND a regular wall texture
angle = (dup_viewangle + gl_xtoviewangle[0]);
angle = (dup_viewangle + xtoviewangle[0]);
dimensionmultiply = ((float)textures[texturetranslation[skytexture]]->width/256.0f);
dimensionmultiply = ((float)textures[texturetranslation[viewworld->skytexture]]->width/256.0f);
v[0].s = v[3].s = (-1.0f * angle) / (((float)ANGLE_90-1.0f)*dimensionmultiply); // left
v[2].s = v[1].s = v[0].s + (1.0f/dimensionmultiply); // right (or left + 1.0f)
......@@ -5848,7 +5043,7 @@ static void HWR_DrawSkyBackground(player_t *player)
// Y
angle = aimingangle;
dimensionmultiply = ((float)textures[texturetranslation[skytexture]]->height/(128.0f*aspectratio));
dimensionmultiply = ((float)textures[texturetranslation[viewworld->skytexture]]->height/(128.0f*aspectratio));
if (splitscreen)
{
......@@ -6086,7 +5281,6 @@ void HWR_RenderSkyboxView(INT32 viewnumber, player_t *player)
drawcount = 0;
#ifdef NEWCLIP
if (rendermode == render_opengl)
{
angle_t a1 = gld_FrustumAngle(gl_aimingangle);
......@@ -6096,9 +5290,6 @@ void HWR_RenderSkyboxView(INT32 viewnumber, player_t *player)
gld_FrustrumSetup();
#endif
}
#else
HWR_ClearClipSegs();
#endif
//04/01/2000: Hurdler: added for T&L
// Actually it only works on Walls and Planes
......@@ -6112,36 +5303,7 @@ void HWR_RenderSkyboxView(INT32 viewnumber, player_t *player)
if (cv_glbatching.value)
HWR_StartBatching();
HWR_RenderBSPNode((INT32)numnodes-1);
#ifndef NEWCLIP
// Make a viewangle int so we can render things based on mouselook
if (player == &players[consoleplayer])
viewangle = localaiming;
else if (splitscreen && player == &players[secondarydisplayplayer])
viewangle = localaiming2;
// Handle stuff when you are looking farther up or down.
if ((gl_aimingangle || cv_fov.value+player->fovadd > 90*FRACUNIT))
{
dup_viewangle += ANGLE_90;
HWR_ClearClipSegs();
HWR_RenderBSPNode((INT32)numnodes-1); //left
dup_viewangle += ANGLE_90;
if (((INT32)gl_aimingangle > ANGLE_45 || (INT32)gl_aimingangle<-ANGLE_45))
{
HWR_ClearClipSegs();
HWR_RenderBSPNode((INT32)numnodes-1); //back
}
dup_viewangle += ANGLE_90;
HWR_ClearClipSegs();
HWR_RenderBSPNode((INT32)numnodes-1); //right
dup_viewangle += ANGLE_90;
}
#endif
HWR_RenderBSPNode((INT32)viewworld->numnodes-1);
if (cv_glbatching.value)
HWR_RenderBatches();
......@@ -6188,7 +5350,7 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player)
const float fpov = FIXED_TO_FLOAT(cv_fov.value+player->fovadd);
postimg_t *type;
const boolean skybox = (skyboxmo[0] && cv_skybox.value); // True if there's a skybox object and skyboxes are on
const boolean skybox = viewworld->skyboxmo[0] && cv_skybox.value; // True if there's a skybox object and skyboxes are on
FRGBAFloat ClearColor;
......@@ -6208,6 +5370,14 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player)
if (viewnumber == 0) // Only do it if it's the first screen being rendered
HWD.pfnClearBuffer(true, false, &ClearColor); // Clear the Color Buffer, stops HOMs. Also seems to fix the skybox issue on Intel GPUs.
// Uh, double check? I don't know, I'm not paid for this.
if (viewworld->extrasubsectors == NULL)
HWR_CreatePlanePolygons((INT32)viewworld->numnodes - 1);
// Same
if (viewworld->sky_dome == NULL)
HWR_BuildSkyDome(viewworld);
PS_START_TIMING(ps_hw_skyboxtime);
if (skybox && drawsky) // If there's a skybox and we should be drawing the sky, draw the skybox
HWR_RenderSkyboxView(viewnumber, player); // This is drawn before everything else so it is placed behind
......@@ -6300,7 +5470,6 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player)
drawcount = 0;
#ifdef NEWCLIP
if (rendermode == render_opengl)
{
angle_t a1 = gld_FrustumAngle(gl_aimingangle);
......@@ -6310,9 +5479,6 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player)
gld_FrustrumSetup();
#endif
}
#else
HWR_ClearClipSegs();
#endif
//04/01/2000: Hurdler: added for T&L
// Actually it only works on Walls and Planes
......@@ -6330,36 +5496,7 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player)
if (cv_glbatching.value)
HWR_StartBatching();
HWR_RenderBSPNode((INT32)numnodes-1);
#ifndef NEWCLIP
// Make a viewangle int so we can render things based on mouselook
if (player == &players[consoleplayer])
viewangle = localaiming;
else if (splitscreen && player == &players[secondarydisplayplayer])
viewangle = localaiming2;
// Handle stuff when you are looking farther up or down.
if ((gl_aimingangle || cv_fov.value+player->fovadd > 90*FRACUNIT))
{
dup_viewangle += ANGLE_90;
HWR_ClearClipSegs();
HWR_RenderBSPNode((INT32)numnodes-1); //left
dup_viewangle += ANGLE_90;
if (((INT32)gl_aimingangle > ANGLE_45 || (INT32)gl_aimingangle<-ANGLE_45))
{
HWR_ClearClipSegs();
HWR_RenderBSPNode((INT32)numnodes-1); //back
}
dup_viewangle += ANGLE_90;
HWR_ClearClipSegs();
HWR_RenderBSPNode((INT32)numnodes-1); //right
dup_viewangle += ANGLE_90;
}
#endif
HWR_RenderBSPNode((INT32)viewworld->numnodes-1);
PS_STOP_TIMING(ps_bsptime);
......@@ -6410,22 +5547,6 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player)
HWD.pfnGClipRect(0, 0, vid.width, vid.height, NZCLIP_PLANE);
}
void HWR_LoadLevel(void)
{
#ifdef ALAM_LIGHTING
// BP: reset light between levels (we draw preview frame lights on current frame)
HWR_ResetLights();
#endif
HWR_CreatePlanePolygons((INT32)numnodes - 1);
// Build the sky dome
HWR_ClearSkyDome();
HWR_BuildSkyDome();
gl_maploaded = true;
}
// ==========================================================================
// 3D ENGINE COMMANDS
// ==========================================================================
......@@ -6513,10 +5634,6 @@ void HWR_AddCommands(void)
CV_RegisterVar(&cv_glsolvetjoin);
CV_RegisterVar(&cv_glbatching);
#ifndef NEWCLIP
CV_RegisterVar(&cv_glclipwalls);
#endif
}
void HWR_AddSessionCommands(void)
......@@ -6536,7 +5653,6 @@ void HWR_Startup(void)
{
CONS_Printf("HWR_Startup()...\n");
HWR_InitPolyPool();
HWR_AddSessionCommands();
HWR_InitMapTextures();
HWR_InitModels();
......@@ -6571,13 +5687,6 @@ void HWR_Switch(void)
// Load textures
if (!gl_maptexturesloaded)
HWR_LoadMapTextures(numtextures);
// Create plane polygons
if (!gl_maploaded && (gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction)))
{
HWR_ClearAllTextures();
HWR_LoadLevel();
}
}
// --------------------------------------------------------------------------
......@@ -6586,8 +5695,6 @@ void HWR_Switch(void)
void HWR_Shutdown(void)
{
CONS_Printf("HWR_Shutdown()\n");
HWR_FreeExtraSubsectors();
HWR_FreePolyPool();
HWR_FreeMapTextures();
HWD.pfnFlushScreenTextures();
}
......
......@@ -33,11 +33,9 @@ void HWR_DrawConsoleBack(UINT32 color, INT32 height);
void HWR_DrawTutorialBack(UINT32 color, INT32 boxheight);
void HWR_RenderSkyboxView(INT32 viewnumber, player_t *player);
void HWR_RenderPlayerView(INT32 viewnumber, player_t *player);
void HWR_ClearSkyDome(void);
void HWR_BuildSkyDome(void);
void HWR_FreeSkyDome(void *skydome);
void HWR_DrawViewBorder(INT32 clearlines);
void HWR_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatlumpnum);
void HWR_InitTextureMapping(void);
void HWR_SetViewSize(void);
void HWR_DrawPatch(patch_t *gpatch, INT32 x, INT32 y, INT32 option);
void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap);
......
......@@ -2404,7 +2404,7 @@ static int lib_pSwitchWeather(lua_State *L)
if (!lua_isnone(L, 2) && lua_isuserdata(L, 2)) // if a player, setup weather for only the player, otherwise setup weather for all players
user = *((player_t **)luaL_checkudata(L, 2, META_PLAYER));
if (!user) // global
globalweather = weathernum;
world->weather = weathernum;
if (!user || P_IsLocalPlayer(user))
P_SwitchWeather(weathernum);
return 0;
......@@ -2520,7 +2520,7 @@ static int lib_pSetSkyboxMobj(lua_State *L)
return luaL_error(L, "skybox mobj index %d is out of range for P_SetSkyboxMobj argument #2 (expected 0 or 1)", w);
if (!user || P_IsLocalPlayer(user))
skyboxmo[w] = mo;
world->skyboxmo[w] = mo;
return 0;
}
......@@ -2577,15 +2577,15 @@ static int lib_pStartQuake(lua_State *L)
q_epicenter.z = 0;
lua_pop(L, 1);
quake.epicenter = &q_epicenter;
world->quake.epicenter = &q_epicenter;
}
else
quake.epicenter = NULL;
quake.radius = luaL_optinteger(L, 4, 512*FRACUNIT);
world->quake.epicenter = NULL;
world->quake.radius = luaL_optinteger(L, 4, 512*FRACUNIT);
// These things are actually used in 2.1.
quake.intensity = q_intensity;
quake.time = q_time;
world->quake.intensity = q_intensity;
world->quake.time = q_time;
return 0;
}
......