Merge branch 'next' of https://git.magicalgirl.moe/STJr/SRB2 into playerthink-hook

This commit is contained in:
Zachary McAlpin 2019-12-28 22:29:10 -06:00
commit ef9a7b01f5
14 changed files with 6905 additions and 344 deletions

6521
extras/conf/SRB2-22.cfg Normal file

File diff suppressed because it is too large Load diff

View file

@ -1462,7 +1462,7 @@ void D_SRB2Main(void)
{
levelstarttic = gametic;
G_SetGamestate(GS_LEVEL);
if (!P_SetupLevel(false))
if (!P_LoadLevel(false))
I_Quit(); // fail so reset game stuff
}
}

View file

@ -1847,7 +1847,7 @@ void G_DoLoadLevel(boolean resetplayer)
}
// Setup the level.
if (!P_SetupLevel(false)) // this never returns false?
if (!P_LoadLevel(false)) // this never returns false?
{
// fail so reset game stuff
Command_ExitGame_f();

View file

@ -4492,7 +4492,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
0, // mass
0, // damage
sfx_None, // activesound
MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY, // flags
MF_SCENERY|MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY, // flags
S_NULL // raisestate
},
@ -6273,7 +6273,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
0, // mass
0, // damage
sfx_None, // activesound
MF_NOGRAVITY|MF_NOBLOCKMAP|MF_NOTHINK, // flags
MF_NOGRAVITY|MF_NOBLOCKMAP|MF_SCENERY, // flags
S_NULL // raisestate
},
@ -11992,7 +11992,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
100, // mass
0, // damage
sfx_None, // activesound
MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY, // flags
MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY, // flags
S_NULL // raisestate
},
@ -12019,7 +12019,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
100, // mass
0, // damage
sfx_None, // activesound
MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY, // flags
MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY, // flags
S_NULL // raisestate
},

View file

@ -2474,6 +2474,8 @@ int M_PathParts(const char *path)
int n;
const char *p;
const char *t;
if (path == NULL)
return 0;
for (n = 0, p = path ;; ++n)
{
t = p;

View file

@ -2261,7 +2261,7 @@ void A_CrushclawLaunch(mobj_t *actor)
while (chain)
{
P_TeleportMove(chain, actor->target->x + idx, actor->target->y + idy, actor->target->z + idz);
chain->watertop = chain->z;
chain->movefactor = chain->z;
idx += dx;
idy += dy;
idz += dz;

View file

@ -9434,7 +9434,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
SINT8 sign = ((mobj->tics & 1) ? mobj->tics : -(SINT8)(mobj->tics));
while (chain)
{
chain->z = chain->watertop + sign*mobj->scale;
chain->z = chain->movefactor + sign*mobj->scale;
sign = -sign;
chain = chain->target;
}

View file

@ -4064,7 +4064,7 @@ static inline boolean P_NetUnArchiveMisc(void)
tokenlist = READUINT32(save_p);
if (!P_SetupLevel(true))
if (!P_LoadLevel(true))
return false;
// get the time

View file

@ -971,7 +971,7 @@ static void P_SpawnEmeraldHunt(void)
mobjinfo[MT_EMERHUNT].spawnstate+2);
}
static void P_LoadThings(boolean loademblems)
static void P_SpawnMapThings(boolean spawnemblems)
{
size_t i;
mapthing_t *mt;
@ -1001,7 +1001,7 @@ static void P_LoadThings(boolean loademblems)
|| mt->type == 1702) // MT_AXISTRANSFERLINE
continue; // These were already spawned
if (!loademblems && mt->type == mobjinfo[MT_EMBLEM].doomednum)
if (!spawnemblems && mt->type == mobjinfo[MT_EMBLEM].doomednum)
continue;
mt->mobj = NULL;
@ -2016,6 +2016,75 @@ static void P_LoadMapData(const virtres_t* virt)
memcpy(spawnsides, sides, numsides * sizeof (*sides));
}
/** Compute MD5 message digest for bytes read from memory source
*
* The resulting message digest number will be written into the 16 bytes
* beginning at RESBLOCK.
*
* \param filename path of file
* \param resblock resulting MD5 checksum
* \return 0 if MD5 checksum was made, and is at resblock, 1 if error was found
*/
static INT32 P_MakeBufferMD5(const char* buffer, size_t len, void* resblock)
{
#ifdef NOMD5
(void)buffer;
(void)len;
memset(resblock, 0x00, 16);
return 1;
#else
tic_t t = I_GetTime();
CONS_Debug(DBG_SETUP, "Making MD5\n");
if (md5_buffer(buffer, len, resblock) == NULL)
return 1;
CONS_Debug(DBG_SETUP, "MD5 calc took %f seconds\n", (float)(I_GetTime() - t)/NEWTICRATE);
return 0;
#endif
}
static void P_MakeMapMD5(virtres_t* virt, void* dest)
{
unsigned char linemd5[16];
unsigned char sectormd5[16];
unsigned char thingmd5[16];
unsigned char sidedefmd5[16];
unsigned char resmd5[16];
UINT8 i;
// Create a hash for the current map
// get the actual lumps!
virtlump_t *virtlines = vres_Find(virt, "LINEDEFS");
virtlump_t *virtsectors = vres_Find(virt, "SECTORS");
virtlump_t *virtmthings = vres_Find(virt, "THINGS");
virtlump_t *virtsides = vres_Find(virt, "SIDEDEFS");
P_MakeBufferMD5((char*)virtlines->data, virtlines->size, linemd5);
P_MakeBufferMD5((char*)virtsectors->data, virtsectors->size, sectormd5);
P_MakeBufferMD5((char*)virtmthings->data, virtmthings->size, thingmd5);
P_MakeBufferMD5((char*)virtsides->data, virtsides->size, sidedefmd5);
for (i = 0; i < 16; i++)
resmd5[i] = (linemd5[i] + sectormd5[i] + thingmd5[i] + sidedefmd5[i]) & 0xFF;
M_Memcpy(dest, &resmd5, 16);
}
static void P_LoadMapFromFile(void)
{
virtres_t *virt = vres_GetMap(lastloadedmaplumpnum);
P_LoadMapData(virt);
P_LoadMapBSP(virt);
P_LoadMapLUT(virt);
P_LoadLineDefs2();
P_GroupLines();
P_MakeMapMD5(virt, &mapmd5);
vres_Free(virt);
}
#if 0
static char *levellumps[] =
{
@ -2084,7 +2153,7 @@ lumpnum_t lastloadedmaplumpnum; // for comparative savegame
//
// Some player initialization for map start.
//
static void P_LevelInitStuff(void)
static void P_InitLevelSettings(void)
{
INT32 i;
boolean canresetlives = true;
@ -2209,68 +2278,15 @@ void P_LoadThingsOnly(void)
P_RemoveMobj((mobj_t *)think);
}
P_LevelInitStuff();
P_InitLevelSettings();
P_LoadThings(true);
P_SpawnMapThings(true);
// restore skybox viewpoint/centerpoint if necessary, set them to defaults if we can't do that
skyboxmo[0] = skyboxviewpnts[(viewid >= 0) ? viewid : 0];
skyboxmo[1] = skyboxcenterpnts[(centerid >= 0) ? centerid : 0];
}
/** Compute MD5 message digest for bytes read from memory source
*
* The resulting message digest number will be written into the 16 bytes
* beginning at RESBLOCK.
*
* \param filename path of file
* \param resblock resulting MD5 checksum
* \return 0 if MD5 checksum was made, and is at resblock, 1 if error was found
*/
static INT32 P_MakeBufferMD5(const char *buffer, size_t len, void *resblock)
{
#ifdef NOMD5
(void)buffer;
(void)len;
memset(resblock, 0x00, 16);
return 1;
#else
tic_t t = I_GetTime();
CONS_Debug(DBG_SETUP, "Making MD5\n");
if (md5_buffer(buffer, len, resblock) == NULL)
return 1;
CONS_Debug(DBG_SETUP, "MD5 calc took %f seconds\n", (float)(I_GetTime() - t)/NEWTICRATE);
return 0;
#endif
}
static void P_MakeMapMD5(virtres_t* virt, void *dest)
{
unsigned char linemd5[16];
unsigned char sectormd5[16];
unsigned char thingmd5[16];
unsigned char sidedefmd5[16];
unsigned char resmd5[16];
UINT8 i;
// Create a hash for the current map
// get the actual lumps!
virtlump_t* virtlines = vres_Find(virt, "LINEDEFS");
virtlump_t* virtsectors = vres_Find(virt, "SECTORS");
virtlump_t* virtmthings = vres_Find(virt, "THINGS");
virtlump_t* virtsides = vres_Find(virt, "SIDEDEFS");
P_MakeBufferMD5((char*)virtlines->data, virtlines->size, linemd5);
P_MakeBufferMD5((char*)virtsectors->data, virtsectors->size, sectormd5);
P_MakeBufferMD5((char*)virtmthings->data, virtmthings->size, thingmd5);
P_MakeBufferMD5((char*)virtsides->data, virtsides->size, sidedefmd5);
for (i = 0; i < 16; i++)
resmd5[i] = (linemd5[i] + sectormd5[i] + thingmd5[i] + sidedefmd5[i]) & 0xFF;
M_Memcpy(dest, &resmd5, 16);
}
static void P_RunLevelScript(const char *scriptname)
{
if (!(mapheaderinfo[gamemap-1]->levelflags & LF_SCRIPTISFILE))
@ -2335,6 +2351,26 @@ static void P_ForceCharacter(const char *forcecharskin)
}
}
static void P_ResetSpawnpoints(void)
{
UINT8 i;
numdmstarts = numredctfstarts = numbluectfstarts = 0;
// reset the player starts
for (i = 0; i < MAXPLAYERS; i++)
playerstarts[i] = bluectfstarts[i] = redctfstarts[i] = NULL;
for (i = 0; i < MAX_DM_STARTS; i++)
deathmatchstarts[i] = NULL;
for (i = 0; i < 2; i++)
skyboxmo[i] = NULL;
for (i = 0; i < 16; i++)
skyboxviewpnts[i] = skyboxcenterpnts[i] = NULL;
}
static void P_LoadRecordGhosts(void)
{
const size_t glen = strlen(srb2home)+1+strlen("replay")+1+strlen(timeattackfolder)+1+strlen("MAPXX")+1;
@ -2434,6 +2470,45 @@ static void P_LoadNightsGhosts(void)
free(gpath);
}
static void P_InitTagGametype(void)
{
UINT8 i;
INT32 realnumplayers = 0;
INT32 playersactive[MAXPLAYERS];
//I just realized how problematic this code can be.
//D_NumPlayers() will not always cover the scope of the netgame.
//What if one player is node 0 and the other node 31?
//The solution? Make a temp array of all players that are currently playing and pick from them.
//Future todo? When a player leaves, shift all nodes down so D_NumPlayers() can be used as intended?
//Also, you'd never have to loop through all 32 players slots to find anything ever again.
for (i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i] && !players[i].spectator)
{
playersactive[realnumplayers] = i; //stores the player's node in the array.
realnumplayers++;
}
}
if (!realnumplayers) //this should also fix the dedicated crash bug. You only pick a player if one exists to be picked.
{
CONS_Printf(M_GetText("No player currently available to become IT. Awaiting available players.\n"));
return;
}
i = P_RandomKey(realnumplayers);
players[playersactive[i]].pflags |= PF_TAGIT; //choose our initial tagger before map starts.
// Taken and modified from G_DoReborn()
// Remove the player so he can respawn elsewhere.
// first disassociate the corpse
if (players[playersactive[i]].mo)
P_RemoveMobj(players[playersactive[i]].mo);
G_SpawnPlayer(playersactive[i], false); //respawn the lucky player in his dedicated spawn location.
}
static void P_SetupCamera(void)
{
if (players[displayplayer].mo && (server || addedtogame))
@ -2471,6 +2546,52 @@ static void P_SetupCamera(void)
}
}
static void P_InitCamera(void)
{
if (!dedicated)
{
P_SetupCamera();
// Salt: CV_ClearChangedFlags() messes with your settings :(
/*if (!cv_cam_height.changed)
CV_Set(&cv_cam_height, cv_cam_height.defaultvalue);
if (!cv_cam2_height.changed)
CV_Set(&cv_cam2_height, cv_cam2_height.defaultvalue);
if (!cv_cam_dist.changed)
CV_Set(&cv_cam_dist, cv_cam_dist.defaultvalue);
if (!cv_cam2_dist.changed)
CV_Set(&cv_cam2_dist, cv_cam2_dist.defaultvalue);*/
// Though, I don't think anyone would care about cam_rotate being reset back to the only value that makes sense :P
if (!cv_cam_rotate.changed)
CV_Set(&cv_cam_rotate, cv_cam_rotate.defaultvalue);
if (!cv_cam2_rotate.changed)
CV_Set(&cv_cam2_rotate, cv_cam2_rotate.defaultvalue);
if (!cv_analog.changed)
CV_SetValue(&cv_analog, 0);
if (!cv_analog2.changed)
CV_SetValue(&cv_analog2, 0);
displayplayer = consoleplayer; // Start with your OWN view, please!
}
if (twodlevel)
{
CV_SetValue(&cv_analog, false);
CV_SetValue(&cv_analog2, false);
}
else
{
if (cv_useranalog.value)
CV_SetValue(&cv_analog, true);
if ((splitscreen && cv_useranalog2.value) || botingame)
CV_SetValue(&cv_analog2, true);
}
}
static boolean CanSaveLevel(INT32 mapnum)
{
if (ultimatemode) // never save in ultimate (probably redundant with cursaveslot also being checked)
@ -2486,21 +2607,187 @@ static boolean CanSaveLevel(INT32 mapnum)
return (mapheaderinfo[mapnum-1]->levelflags & LF_SAVEGAME || gamecomplete || !lastmaploaded);
}
static void P_RunSpecialStageWipe(void)
{
tic_t starttime = I_GetTime();
tic_t endtime = starttime + (3*TICRATE)/2;
tic_t nowtime;
S_StartSound(NULL, sfx_s3kaf);
// Fade music! Time it to S3KAF: 0.25 seconds is snappy.
if (RESETMUSIC ||
strnicmp(S_MusicName(),
(mapmusflags & MUSIC_RELOADRESET) ? mapheaderinfo[gamemap - 1]->musname : mapmusname, 7))
S_FadeOutStopMusic(MUSICRATE/4); //FixedMul(FixedDiv(F_GetWipeLength(wipedefs[wipe_speclevel_towhite])*NEWTICRATERATIO, NEWTICRATE), MUSICRATE)
F_WipeStartScreen();
wipestyleflags |= (WSF_FADEOUT|WSF_TOWHITE);
#ifdef HWRENDER
// uh..........
if (rendermode == render_opengl)
F_WipeColorFill(0);
#endif
F_WipeEndScreen();
F_RunWipe(wipedefs[wipe_speclevel_towhite], false);
I_OsPolling();
I_FinishUpdate(); // page flip or blit buffer
if (moviemode)
M_SaveFrame();
nowtime = lastwipetic;
// Hold on white for extra effect.
while (nowtime < endtime)
{
// wait loop
while (!((nowtime = I_GetTime()) - lastwipetic))
I_Sleep();
lastwipetic = nowtime;
if (moviemode) // make sure we save frames for the white hold too
M_SaveFrame();
}
}
static void P_RunLevelWipe(void)
{
F_WipeStartScreen();
wipestyleflags |= WSF_FADEOUT;
#ifdef HWRENDER
// uh..........
if (rendermode == render_opengl)
F_WipeColorFill(31);
#endif
F_WipeEndScreen();
// for titlemap: run a specific wipe if specified
// needed for exiting time attack
if (wipetypepre != INT16_MAX)
F_RunWipe(
(wipetypepre >= 0 && F_WipeExists(wipetypepre)) ? wipetypepre : wipedefs[wipe_level_toblack],
false);
wipetypepre = -1;
}
static void P_InitPlayers(void)
{
UINT8 i;
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i])
continue;
// Start players with pity shields if possible
players[i].pity = -1;
players[i].mo = NULL;
if (!G_PlatformGametype())
G_DoReborn(i);
else // gametype is GT_COOP or GT_RACE
{
G_SpawnPlayer(i, players[i].starposttime);
if (players[i].starposttime)
P_ClearStarPost(players[i].starpostnum);
}
}
}
static void P_WriteLetter(void)
{
char *buf, *b;
if (!unlockables[27].unlocked) // pandora's box
return;
if (modeattacking)
return;
#ifndef DEVELOP
if (modifiedgame)
return;
#endif
if (netgame || multiplayer)
return;
if (gamemap != 0x1d35 - 016464)
return;
P_SpawnMobj(0640370000, 0x11000000, 0x3180000, MT_LETTER)->angle = ANGLE_90;
if (textprompts[199]->page[1].backcolor == 259)
return;
buf = W_CacheLumpName("WATERMAP", PU_STATIC);
b = buf;
while ((*b != 65) && (b - buf < 256))
{
*b = (*b - 65) & 255;
b++;
}
*b = '\0';
Z_Free(textprompts[199]->page[1].text);
textprompts[199]->page[1].text = Z_StrDup(buf);
textprompts[199]->page[1].lines = 4;
textprompts[199]->page[1].backcolor = 259;
Z_Free(buf);
}
static void P_InitGametype(void)
{
UINT8 i;
P_InitPlayers();
// restore time in netgame (see also g_game.c)
if ((netgame || multiplayer) && gametype == GT_COOP && cv_coopstarposts.value == 2)
{
// is this a hack? maybe
tic_t maxstarposttime = 0;
for (i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i] && players[i].starposttime > maxstarposttime)
maxstarposttime = players[i].starposttime;
}
leveltime = maxstarposttime;
}
P_WriteLetter();
if (modeattacking == ATTACKING_RECORD && !demoplayback)
P_LoadRecordGhosts();
else if (modeattacking == ATTACKING_NIGHTS && !demoplayback)
P_LoadNightsGhosts();
if (G_TagGametype())
P_InitTagGametype();
else if (gametype == GT_RACE && server)
CV_StealthSetValue(&cv_numlaps,
(cv_basenumlaps.value)
? cv_basenumlaps.value
: mapheaderinfo[gamemap - 1]->numlaps);
}
/** Loads a level from a lump or external wad.
*
* \param skipprecip If true, don't spawn precipitation.
* \param fromnetsave If true, skip some stuff because we're loading a netgame snapshot.
* \todo Clean up, refactor, split up; get rid of the bloat.
*/
boolean P_SetupLevel(boolean skipprecip)
boolean P_LoadLevel(boolean fromnetsave)
{
// use gamemap to get map number.
// 99% of the things already did, so.
// Map header should always be in place at this point
INT32 i, loadprecip = 1, ranspecialwipe = 0;
INT32 loademblems = 1;
INT32 fromnetsave = 0;
INT32 i, ranspecialwipe = 0;
sector_t *ss;
boolean chase;
levelloading = true;
// This is needed. Don't touch.
@ -2531,19 +2818,18 @@ boolean P_SetupLevel(boolean skipprecip)
if (cv_runscripts.value && mapheaderinfo[gamemap-1]->scriptname[0] != '#')
P_RunLevelScript(mapheaderinfo[gamemap-1]->scriptname);
P_LevelInitStuff();
P_InitLevelSettings();
postimgtype = postimgtype2 = postimg_none;
if (mapheaderinfo[gamemap-1]->forcecharacter[0] != '\0')
P_ForceCharacter(mapheaderinfo[gamemap-1]->forcecharacter);
// chasecam on in chaos, race, coop
// chasecam off in match, tag, capture the flag
chase = (!(gametyperules & GTR_FIRSTPERSON)) || (maptol & TOL_2D);
if (!dedicated)
{
// chasecam on in first-person gametypes and 2D
boolean chase = (!(gametyperules & GTR_FIRSTPERSON)) || (maptol & TOL_2D);
// Salt: CV_ClearChangedFlags() messes with your settings :(
/*if (!cv_cam_speed.changed)
CV_Set(&cv_cam_speed, cv_cam_speed.defaultvalue);*/
@ -2570,48 +2856,7 @@ boolean P_SetupLevel(boolean skipprecip)
ranspecialwipe = 2;
else if (rendermode != render_none && G_IsSpecialStage(gamemap))
{
tic_t starttime = I_GetTime();
tic_t endtime = starttime + (3*TICRATE)/2;
tic_t nowtime;
S_StartSound(NULL, sfx_s3kaf);
// Fade music! Time it to S3KAF: 0.25 seconds is snappy.
if (RESETMUSIC ||
strnicmp(S_MusicName(),
(mapmusflags & MUSIC_RELOADRESET) ? mapheaderinfo[gamemap-1]->musname : mapmusname, 7))
S_FadeOutStopMusic(MUSICRATE/4); //FixedMul(FixedDiv(F_GetWipeLength(wipedefs[wipe_speclevel_towhite])*NEWTICRATERATIO, NEWTICRATE), MUSICRATE)
F_WipeStartScreen();
wipestyleflags |= (WSF_FADEOUT|WSF_TOWHITE);
#ifdef HWRENDER
// uh..........
if (rendermode == render_opengl)
F_WipeColorFill(0);
#endif
F_WipeEndScreen();
F_RunWipe(wipedefs[wipe_speclevel_towhite], false);
I_OsPolling();
I_FinishUpdate(); // page flip or blit buffer
if (moviemode)
M_SaveFrame();
nowtime = lastwipetic;
// Hold on white for extra effect.
while (nowtime < endtime)
{
// wait loop
while (!((nowtime = I_GetTime()) - lastwipetic))
I_Sleep();
lastwipetic = nowtime;
if (moviemode) // make sure we save frames for the white hold too
M_SaveFrame();
}
P_RunSpecialStageWipe();
ranspecialwipe = 1;
}
@ -2637,25 +2882,7 @@ boolean P_SetupLevel(boolean skipprecip)
// Let's fade to black here
// But only if we didn't do the special stage wipe
if (rendermode != render_none && !ranspecialwipe)
{
F_WipeStartScreen();
wipestyleflags |= WSF_FADEOUT;
#ifdef HWRENDER
// uh..........
if (rendermode == render_opengl)
F_WipeColorFill(31);
#endif
F_WipeEndScreen();
// for titlemap: run a specific wipe if specified
// needed for exiting time attack
if (wipetypepre != INT16_MAX)
F_RunWipe(
(wipetypepre >= 0 && F_WipeExists(wipetypepre)) ? wipetypepre : wipedefs[wipe_level_toblack],
false);
wipetypepre = -1;
}
P_RunLevelWipe();
if (!titlemapinaction)
{
@ -2713,14 +2940,7 @@ boolean P_SetupLevel(boolean skipprecip)
P_InitThinkers();
P_InitCachedActions();
/// \note for not spawning precipitation, etc. when loading netgame snapshots
if (skipprecip)
{
fromnetsave = 1;
loadprecip = 0;
loademblems = 0;
}
else if (savedata.lives > 0)
if (!fromnetsave && savedata.lives > 0)
{
numgameovers = savedata.numgameovers;
players[consoleplayer].continues = savedata.continues;
@ -2734,9 +2954,7 @@ boolean P_SetupLevel(boolean skipprecip)
// internal game map
maplumpname = G_BuildMapName(gamemap);
//lastloadedmaplumpnum = LUMPERROR;
lastloadedmaplumpnum = W_CheckNumForName(maplumpname);
if (lastloadedmaplumpnum == INT16_MAX)
I_Error("Map %s not found.\n", maplumpname);
@ -2746,38 +2964,12 @@ boolean P_SetupLevel(boolean skipprecip)
// SRB2 determines the sky texture to be used depending on the map header.
P_SetupLevelSky(mapheaderinfo[gamemap-1]->skynum, true);
numdmstarts = numredctfstarts = numbluectfstarts = 0;
// reset the player starts
for (i = 0; i < MAXPLAYERS; i++)
playerstarts[i] = bluectfstarts[i] = redctfstarts[i] = NULL;
for (i = 0; i < MAX_DM_STARTS; i++)
deathmatchstarts[i] = NULL;
for (i = 0; i < 2; i++)
skyboxmo[i] = NULL;
for (i = 0; i < 16; i++)
skyboxviewpnts[i] = skyboxcenterpnts[i] = NULL;
P_ResetSpawnpoints();
P_MapStart();
if (lastloadedmaplumpnum)
{
virtres_t* virt = vres_GetMap(lastloadedmaplumpnum);
P_LoadMapData(virt);
P_LoadMapBSP(virt);
P_LoadMapLUT(virt);
P_LoadLineDefs2();
P_GroupLines();
P_MakeMapMD5(virt, &mapmd5);
vres_Free(virt);
}
P_LoadMapFromFile();
// init gravity, tag lists,
// anything that P_ResetDynamicSlopes/P_LoadThings needs to know
@ -2787,7 +2979,7 @@ boolean P_SetupLevel(boolean skipprecip)
P_ResetDynamicSlopes(fromnetsave);
#endif
P_LoadThings(loademblems);
P_SpawnMapThings(!fromnetsave);
skyboxmo[0] = skyboxviewpnts[0];
skyboxmo[1] = skyboxcenterpnts[0];
@ -2798,7 +2990,7 @@ boolean P_SetupLevel(boolean skipprecip)
// set up world state
P_SpawnSpecials(fromnetsave);
if (loadprecip) // ugly hack for P_NetUnArchiveMisc (and P_LoadNetGame)
if (!fromnetsave) // ugly hack for P_NetUnArchiveMisc (and P_LoadNetGame)
P_SpawnPrecipitation();
#ifdef HWRENDER // not win32 only 19990829 by Kin
@ -2826,161 +3018,10 @@ boolean P_SetupLevel(boolean skipprecip)
// none of this needs to be done because it's not the beginning of the map when
// a netgame save is being loaded, and could actively be harmful by messing with
// the client's view of the data.)
if (fromnetsave)
goto netgameskip;
// ==========
if (!fromnetsave)
P_InitGametype();
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i])
{
// Start players with pity shields if possible
players[i].pity = -1;
if (!G_PlatformGametype())
{
players[i].mo = NULL;
G_DoReborn(i);
}
else // gametype is GT_COOP or GT_RACE
{
players[i].mo = NULL;
if (players[i].starposttime)
{
G_SpawnPlayer(i, true);
P_ClearStarPost(players[i].starpostnum);
}
else
G_SpawnPlayer(i, false);
}
}
// restore time in netgame (see also g_game.c)
if ((netgame || multiplayer) && gametype == GT_COOP && cv_coopstarposts.value == 2)
{
// is this a hack? maybe
tic_t maxstarposttime = 0;
for (i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i] && players[i].starposttime > maxstarposttime)
maxstarposttime = players[i].starposttime;
}
leveltime = maxstarposttime;
}
if (unlockables[27].unlocked && !modeattacking // pandora's box
#ifndef DEVELOP
&& !modifiedgame
#endif
&& !(netgame || multiplayer) && gamemap == 0x1d35-016464)
{
P_SpawnMobj(0640370000, 0x11000000, 0x3180000, MT_LETTER)->angle = ANGLE_90;
if (textprompts[199]->page[1].backcolor != 259)
{
char *buf = W_CacheLumpName("WATERMAP", PU_STATIC), *b = buf;
while ((*b != 65) && (b-buf < 256)) { *b = (*b - 65)&255; b++; } *b = '\0';
Z_Free(textprompts[199]->page[1].text);
textprompts[199]->page[1].text = Z_StrDup(buf);
textprompts[199]->page[1].lines = 4;
textprompts[199]->page[1].backcolor = 259;
Z_Free(buf);
}
}
if (modeattacking == ATTACKING_RECORD && !demoplayback)
P_LoadRecordGhosts();
else if (modeattacking == ATTACKING_NIGHTS && !demoplayback)
P_LoadNightsGhosts();
if (G_TagGametype())
{
INT32 realnumplayers = 0;
INT32 playersactive[MAXPLAYERS];
//I just realized how problematic this code can be.
//D_NumPlayers() will not always cover the scope of the netgame.
//What if one player is node 0 and the other node 31?
//The solution? Make a temp array of all players that are currently playing and pick from them.
//Future todo? When a player leaves, shift all nodes down so D_NumPlayers() can be used as intended?
//Also, you'd never have to loop through all 32 players slots to find anything ever again.
for (i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i] && !players[i].spectator)
{
playersactive[realnumplayers] = i; //stores the player's node in the array.
realnumplayers++;
}
}
if (realnumplayers) //this should also fix the dedicated crash bug. You only pick a player if one exists to be picked.
{
i = P_RandomKey(realnumplayers);
players[playersactive[i]].pflags |= PF_TAGIT; //choose our initial tagger before map starts.
// Taken and modified from G_DoReborn()
// Remove the player so he can respawn elsewhere.
// first dissasociate the corpse
if (players[playersactive[i]].mo)
P_RemoveMobj(players[playersactive[i]].mo);
G_SpawnPlayer(playersactive[i], false); //respawn the lucky player in his dedicated spawn location.
}
else
CONS_Printf(M_GetText("No player currently available to become IT. Awaiting available players.\n"));
}
else if (gametype == GT_RACE && server)
CV_StealthSetValue(&cv_numlaps,
(cv_basenumlaps.value)
? cv_basenumlaps.value
: mapheaderinfo[gamemap - 1]->numlaps);
// ===========
// landing point for netgames.
netgameskip:
if (!dedicated)
{
P_SetupCamera();
// Salt: CV_ClearChangedFlags() messes with your settings :(
/*if (!cv_cam_height.changed)
CV_Set(&cv_cam_height, cv_cam_height.defaultvalue);
if (!cv_cam2_height.changed)
CV_Set(&cv_cam2_height, cv_cam2_height.defaultvalue);
if (!cv_cam_dist.changed)
CV_Set(&cv_cam_dist, cv_cam_dist.defaultvalue);
if (!cv_cam2_dist.changed)
CV_Set(&cv_cam2_dist, cv_cam2_dist.defaultvalue);*/
// Though, I don't think anyone would care about cam_rotate being reset back to the only value that makes sense :P
if (!cv_cam_rotate.changed)
CV_Set(&cv_cam_rotate, cv_cam_rotate.defaultvalue);
if (!cv_cam2_rotate.changed)
CV_Set(&cv_cam2_rotate, cv_cam2_rotate.defaultvalue);
if (!cv_analog.changed)
CV_SetValue(&cv_analog, 0);
if (!cv_analog2.changed)
CV_SetValue(&cv_analog2, 0);
displayplayer = consoleplayer; // Start with your OWN view, please!
}
if (cv_useranalog.value)
CV_SetValue(&cv_analog, true);
if (splitscreen && cv_useranalog2.value)
CV_SetValue(&cv_analog2, true);
else if (botingame)
CV_SetValue(&cv_analog2, true);
if (twodlevel)
{
CV_SetValue(&cv_analog2, false);
CV_SetValue(&cv_analog, false);
}
P_InitCamera();
// clear special respawning que
iquehead = iquetail = 0;
@ -3015,7 +3056,7 @@ boolean P_SetupLevel(boolean skipprecip)
lastmaploaded = gamemap; // HAS to be set after saving!!
if (loadprecip) // uglier hack
if (!fromnetsave) // uglier hack
{ // to make a newly loaded level start on the second frame.
INT32 buf = gametic % BACKUPTICS;
for (i = 0; i < MAXPLAYERS; i++)

View file

@ -97,7 +97,7 @@ void P_SetupLevelSky(INT32 skynum, boolean global);
void P_ScanThings(INT16 mapnum, INT16 wadnum, INT16 lumpnum);
#endif
void P_LoadThingsOnly(void);
boolean P_SetupLevel(boolean skipprecip);
boolean P_LoadLevel(boolean fromnetsave);
boolean P_AddWadFile(const char *wadfilename);
boolean P_RunSOC(const char *socfilename);
void P_LoadSoundsRange(UINT16 wadnum, UINT16 first, UINT16 num);

View file

@ -553,11 +553,8 @@ pslope_t *P_SlopeById(UINT16 id)
}
/// Reset slopes and read them from special lines.
void P_ResetDynamicSlopes(const UINT32 fromsave) {
void P_ResetDynamicSlopes(const boolean fromsave) {
size_t i;
boolean spawnthinkers = !(boolean)fromsave;
slopelist = NULL;
slopecount = 0;
@ -574,14 +571,14 @@ void P_ResetDynamicSlopes(const UINT32 fromsave) {
case 711:
case 712:
case 713:
line_SpawnViaLine(i, spawnthinkers);
line_SpawnViaLine(i, !fromsave);
break;
case 704:
case 705:
case 714:
case 715:
line_SpawnViaVertexes(i, spawnthinkers);
line_SpawnViaVertexes(i, !fromsave);
break;
default:

View file

@ -23,7 +23,7 @@ extern UINT16 slopecount;
void P_LinkSlopeThinkers (void);
void P_CalculateSlopeNormal(pslope_t *slope);
void P_ResetDynamicSlopes(const UINT32 fromsave);
void P_ResetDynamicSlopes(const boolean fromsave);
//
// P_CopySectorSlope

View file

@ -6426,7 +6426,7 @@ static void P_ApplyFlatAlignment(line_t *master, sector_t *sector, angle_t flata
* as they'll just be erased by UnArchiveThinkers.
* \sa P_SpawnPrecipitation, P_SpawnFriction, P_SpawnPushers, P_SpawnScrollers
*/
void P_SpawnSpecials(INT32 fromnetsave)
void P_SpawnSpecials(boolean fromnetsave)
{
sector_t *sector;
size_t i;

View file

@ -35,7 +35,7 @@ void P_SetupLevelFlatAnims(void);
// at map load
void P_InitSpecials(void);
void P_SpawnSpecials(INT32 fromnetsave);
void P_SpawnSpecials(boolean fromnetsave);
// every tic
void P_UpdateSpecials(void);