mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2024-12-14 06:41:03 +00:00
Merge branch 'next' into oglshaderport
This commit is contained in:
commit
dcc7426d1d
14 changed files with 6905 additions and 344 deletions
6521
extras/conf/SRB2-22.cfg
Normal file
6521
extras/conf/SRB2-22.cfg
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1462,7 +1462,7 @@ void D_SRB2Main(void)
|
||||||
{
|
{
|
||||||
levelstarttic = gametic;
|
levelstarttic = gametic;
|
||||||
G_SetGamestate(GS_LEVEL);
|
G_SetGamestate(GS_LEVEL);
|
||||||
if (!P_SetupLevel(false))
|
if (!P_LoadLevel(false))
|
||||||
I_Quit(); // fail so reset game stuff
|
I_Quit(); // fail so reset game stuff
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1847,7 +1847,7 @@ void G_DoLoadLevel(boolean resetplayer)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup the level.
|
// Setup the level.
|
||||||
if (!P_SetupLevel(false)) // this never returns false?
|
if (!P_LoadLevel(false)) // this never returns false?
|
||||||
{
|
{
|
||||||
// fail so reset game stuff
|
// fail so reset game stuff
|
||||||
Command_ExitGame_f();
|
Command_ExitGame_f();
|
||||||
|
|
|
@ -4492,7 +4492,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
||||||
0, // mass
|
0, // mass
|
||||||
0, // damage
|
0, // damage
|
||||||
sfx_None, // activesound
|
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
|
S_NULL // raisestate
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -6273,7 +6273,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
||||||
0, // mass
|
0, // mass
|
||||||
0, // damage
|
0, // damage
|
||||||
sfx_None, // activesound
|
sfx_None, // activesound
|
||||||
MF_NOGRAVITY|MF_NOBLOCKMAP|MF_NOTHINK, // flags
|
MF_NOGRAVITY|MF_NOBLOCKMAP|MF_SCENERY, // flags
|
||||||
S_NULL // raisestate
|
S_NULL // raisestate
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -11992,7 +11992,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
||||||
100, // mass
|
100, // mass
|
||||||
0, // damage
|
0, // damage
|
||||||
sfx_None, // activesound
|
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
|
S_NULL // raisestate
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -12019,7 +12019,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
||||||
100, // mass
|
100, // mass
|
||||||
0, // damage
|
0, // damage
|
||||||
sfx_None, // activesound
|
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
|
S_NULL // raisestate
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -2474,6 +2474,8 @@ int M_PathParts(const char *path)
|
||||||
int n;
|
int n;
|
||||||
const char *p;
|
const char *p;
|
||||||
const char *t;
|
const char *t;
|
||||||
|
if (path == NULL)
|
||||||
|
return 0;
|
||||||
for (n = 0, p = path ;; ++n)
|
for (n = 0, p = path ;; ++n)
|
||||||
{
|
{
|
||||||
t = p;
|
t = p;
|
||||||
|
|
|
@ -2261,7 +2261,7 @@ void A_CrushclawLaunch(mobj_t *actor)
|
||||||
while (chain)
|
while (chain)
|
||||||
{
|
{
|
||||||
P_TeleportMove(chain, actor->target->x + idx, actor->target->y + idy, actor->target->z + idz);
|
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;
|
idx += dx;
|
||||||
idy += dy;
|
idy += dy;
|
||||||
idz += dz;
|
idz += dz;
|
||||||
|
|
|
@ -9434,7 +9434,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
|
||||||
SINT8 sign = ((mobj->tics & 1) ? mobj->tics : -(SINT8)(mobj->tics));
|
SINT8 sign = ((mobj->tics & 1) ? mobj->tics : -(SINT8)(mobj->tics));
|
||||||
while (chain)
|
while (chain)
|
||||||
{
|
{
|
||||||
chain->z = chain->watertop + sign*mobj->scale;
|
chain->z = chain->movefactor + sign*mobj->scale;
|
||||||
sign = -sign;
|
sign = -sign;
|
||||||
chain = chain->target;
|
chain = chain->target;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4064,7 +4064,7 @@ static inline boolean P_NetUnArchiveMisc(void)
|
||||||
|
|
||||||
tokenlist = READUINT32(save_p);
|
tokenlist = READUINT32(save_p);
|
||||||
|
|
||||||
if (!P_SetupLevel(true))
|
if (!P_LoadLevel(true))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// get the time
|
// get the time
|
||||||
|
|
753
src/p_setup.c
753
src/p_setup.c
|
@ -971,7 +971,7 @@ static void P_SpawnEmeraldHunt(void)
|
||||||
mobjinfo[MT_EMERHUNT].spawnstate+2);
|
mobjinfo[MT_EMERHUNT].spawnstate+2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void P_LoadThings(boolean loademblems)
|
static void P_SpawnMapThings(boolean spawnemblems)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
mapthing_t *mt;
|
mapthing_t *mt;
|
||||||
|
@ -1001,7 +1001,7 @@ static void P_LoadThings(boolean loademblems)
|
||||||
|| mt->type == 1702) // MT_AXISTRANSFERLINE
|
|| mt->type == 1702) // MT_AXISTRANSFERLINE
|
||||||
continue; // These were already spawned
|
continue; // These were already spawned
|
||||||
|
|
||||||
if (!loademblems && mt->type == mobjinfo[MT_EMBLEM].doomednum)
|
if (!spawnemblems && mt->type == mobjinfo[MT_EMBLEM].doomednum)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
mt->mobj = NULL;
|
mt->mobj = NULL;
|
||||||
|
@ -2016,6 +2016,75 @@ static void P_LoadMapData(const virtres_t* virt)
|
||||||
memcpy(spawnsides, sides, numsides * sizeof (*sides));
|
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
|
#if 0
|
||||||
static char *levellumps[] =
|
static char *levellumps[] =
|
||||||
{
|
{
|
||||||
|
@ -2084,7 +2153,7 @@ lumpnum_t lastloadedmaplumpnum; // for comparative savegame
|
||||||
//
|
//
|
||||||
// Some player initialization for map start.
|
// Some player initialization for map start.
|
||||||
//
|
//
|
||||||
static void P_LevelInitStuff(void)
|
static void P_InitLevelSettings(void)
|
||||||
{
|
{
|
||||||
INT32 i;
|
INT32 i;
|
||||||
boolean canresetlives = true;
|
boolean canresetlives = true;
|
||||||
|
@ -2209,68 +2278,15 @@ void P_LoadThingsOnly(void)
|
||||||
P_RemoveMobj((mobj_t *)think);
|
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
|
// restore skybox viewpoint/centerpoint if necessary, set them to defaults if we can't do that
|
||||||
skyboxmo[0] = skyboxviewpnts[(viewid >= 0) ? viewid : 0];
|
skyboxmo[0] = skyboxviewpnts[(viewid >= 0) ? viewid : 0];
|
||||||
skyboxmo[1] = skyboxcenterpnts[(centerid >= 0) ? centerid : 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)
|
static void P_RunLevelScript(const char *scriptname)
|
||||||
{
|
{
|
||||||
if (!(mapheaderinfo[gamemap-1]->levelflags & LF_SCRIPTISFILE))
|
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)
|
static void P_LoadRecordGhosts(void)
|
||||||
{
|
{
|
||||||
const size_t glen = strlen(srb2home)+1+strlen("replay")+1+strlen(timeattackfolder)+1+strlen("MAPXX")+1;
|
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);
|
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)
|
static void P_SetupCamera(void)
|
||||||
{
|
{
|
||||||
if (players[displayplayer].mo && (server || addedtogame))
|
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)
|
static boolean CanSaveLevel(INT32 mapnum)
|
||||||
{
|
{
|
||||||
if (ultimatemode) // never save in ultimate (probably redundant with cursaveslot also being checked)
|
if (ultimatemode) // never save in ultimate (probably redundant with cursaveslot also being checked)
|
||||||
|
@ -2486,90 +2607,8 @@ static boolean CanSaveLevel(INT32 mapnum)
|
||||||
return (mapheaderinfo[mapnum-1]->levelflags & LF_SAVEGAME || gamecomplete || !lastmaploaded);
|
return (mapheaderinfo[mapnum-1]->levelflags & LF_SAVEGAME || gamecomplete || !lastmaploaded);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Loads a level from a lump or external wad.
|
static void P_RunSpecialStageWipe(void)
|
||||||
*
|
|
||||||
* \param skipprecip If true, don't spawn precipitation.
|
|
||||||
* \todo Clean up, refactor, split up; get rid of the bloat.
|
|
||||||
*/
|
|
||||||
boolean P_SetupLevel(boolean skipprecip)
|
|
||||||
{
|
{
|
||||||
// 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;
|
|
||||||
sector_t *ss;
|
|
||||||
boolean chase;
|
|
||||||
levelloading = true;
|
|
||||||
|
|
||||||
// This is needed. Don't touch.
|
|
||||||
maptol = mapheaderinfo[gamemap-1]->typeoflevel;
|
|
||||||
|
|
||||||
CON_Drawer(); // let the user know what we are going to do
|
|
||||||
I_FinishUpdate(); // page flip or blit buffer
|
|
||||||
|
|
||||||
// Reset the palette
|
|
||||||
if (rendermode != render_none)
|
|
||||||
V_SetPaletteLump("PLAYPAL");
|
|
||||||
|
|
||||||
// Initialize sector node list.
|
|
||||||
P_Initsecnode();
|
|
||||||
|
|
||||||
if (netgame || multiplayer)
|
|
||||||
cv_debug = botskin = 0;
|
|
||||||
|
|
||||||
if (metalplayback)
|
|
||||||
G_StopMetalDemo();
|
|
||||||
|
|
||||||
// Clear CECHO messages
|
|
||||||
HU_ClearCEcho();
|
|
||||||
|
|
||||||
if (mapheaderinfo[gamemap-1]->runsoc[0] != '#')
|
|
||||||
P_RunSOC(mapheaderinfo[gamemap-1]->runsoc);
|
|
||||||
|
|
||||||
if (cv_runscripts.value && mapheaderinfo[gamemap-1]->scriptname[0] != '#')
|
|
||||||
P_RunLevelScript(mapheaderinfo[gamemap-1]->scriptname);
|
|
||||||
|
|
||||||
P_LevelInitStuff();
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
// Salt: CV_ClearChangedFlags() messes with your settings :(
|
|
||||||
/*if (!cv_cam_speed.changed)
|
|
||||||
CV_Set(&cv_cam_speed, cv_cam_speed.defaultvalue);*/
|
|
||||||
|
|
||||||
if (!cv_chasecam.changed)
|
|
||||||
CV_SetValue(&cv_chasecam, chase);
|
|
||||||
|
|
||||||
// same for second player
|
|
||||||
if (!cv_chasecam2.changed)
|
|
||||||
CV_SetValue(&cv_chasecam2, chase);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initial height of PointOfView
|
|
||||||
// will be set by player think.
|
|
||||||
players[consoleplayer].viewz = 1;
|
|
||||||
|
|
||||||
// Cancel all d_main.c fadeouts (keep fade in though).
|
|
||||||
wipegamestate = FORCEWIPEOFF;
|
|
||||||
wipestyleflags = 0;
|
|
||||||
|
|
||||||
// Special stage fade to white
|
|
||||||
// This is handled BEFORE sounds are stopped.
|
|
||||||
if (modeattacking && !demoplayback && (pausedelay == INT32_MIN))
|
|
||||||
ranspecialwipe = 2;
|
|
||||||
else if (rendermode != render_none && G_IsSpecialStage(gamemap))
|
|
||||||
{
|
|
||||||
tic_t starttime = I_GetTime();
|
tic_t starttime = I_GetTime();
|
||||||
tic_t endtime = starttime + (3*TICRATE)/2;
|
tic_t endtime = starttime + (3*TICRATE)/2;
|
||||||
tic_t nowtime;
|
tic_t nowtime;
|
||||||
|
@ -2579,7 +2618,7 @@ boolean P_SetupLevel(boolean skipprecip)
|
||||||
// Fade music! Time it to S3KAF: 0.25 seconds is snappy.
|
// Fade music! Time it to S3KAF: 0.25 seconds is snappy.
|
||||||
if (RESETMUSIC ||
|
if (RESETMUSIC ||
|
||||||
strnicmp(S_MusicName(),
|
strnicmp(S_MusicName(),
|
||||||
(mapmusflags & MUSIC_RELOADRESET) ? mapheaderinfo[gamemap-1]->musname : mapmusname, 7))
|
(mapmusflags & MUSIC_RELOADRESET) ? mapheaderinfo[gamemap - 1]->musname : mapmusname, 7))
|
||||||
S_FadeOutStopMusic(MUSICRATE/4); //FixedMul(FixedDiv(F_GetWipeLength(wipedefs[wipe_speclevel_towhite])*NEWTICRATERATIO, NEWTICRATE), MUSICRATE)
|
S_FadeOutStopMusic(MUSICRATE/4); //FixedMul(FixedDiv(F_GetWipeLength(wipedefs[wipe_speclevel_towhite])*NEWTICRATERATIO, NEWTICRATE), MUSICRATE)
|
||||||
|
|
||||||
F_WipeStartScreen();
|
F_WipeStartScreen();
|
||||||
|
@ -2611,7 +2650,213 @@ boolean P_SetupLevel(boolean skipprecip)
|
||||||
if (moviemode) // make sure we save frames for the white hold too
|
if (moviemode) // make sure we save frames for the white hold too
|
||||||
M_SaveFrame();
|
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 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_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, ranspecialwipe = 0;
|
||||||
|
sector_t *ss;
|
||||||
|
levelloading = true;
|
||||||
|
|
||||||
|
// This is needed. Don't touch.
|
||||||
|
maptol = mapheaderinfo[gamemap-1]->typeoflevel;
|
||||||
|
|
||||||
|
CON_Drawer(); // let the user know what we are going to do
|
||||||
|
I_FinishUpdate(); // page flip or blit buffer
|
||||||
|
|
||||||
|
// Reset the palette
|
||||||
|
if (rendermode != render_none)
|
||||||
|
V_SetPaletteLump("PLAYPAL");
|
||||||
|
|
||||||
|
// Initialize sector node list.
|
||||||
|
P_Initsecnode();
|
||||||
|
|
||||||
|
if (netgame || multiplayer)
|
||||||
|
cv_debug = botskin = 0;
|
||||||
|
|
||||||
|
if (metalplayback)
|
||||||
|
G_StopMetalDemo();
|
||||||
|
|
||||||
|
// Clear CECHO messages
|
||||||
|
HU_ClearCEcho();
|
||||||
|
|
||||||
|
if (mapheaderinfo[gamemap-1]->runsoc[0] != '#')
|
||||||
|
P_RunSOC(mapheaderinfo[gamemap-1]->runsoc);
|
||||||
|
|
||||||
|
if (cv_runscripts.value && mapheaderinfo[gamemap-1]->scriptname[0] != '#')
|
||||||
|
P_RunLevelScript(mapheaderinfo[gamemap-1]->scriptname);
|
||||||
|
|
||||||
|
P_InitLevelSettings();
|
||||||
|
|
||||||
|
postimgtype = postimgtype2 = postimg_none;
|
||||||
|
|
||||||
|
if (mapheaderinfo[gamemap-1]->forcecharacter[0] != '\0')
|
||||||
|
P_ForceCharacter(mapheaderinfo[gamemap-1]->forcecharacter);
|
||||||
|
|
||||||
|
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);*/
|
||||||
|
|
||||||
|
if (!cv_chasecam.changed)
|
||||||
|
CV_SetValue(&cv_chasecam, chase);
|
||||||
|
|
||||||
|
// same for second player
|
||||||
|
if (!cv_chasecam2.changed)
|
||||||
|
CV_SetValue(&cv_chasecam2, chase);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initial height of PointOfView
|
||||||
|
// will be set by player think.
|
||||||
|
players[consoleplayer].viewz = 1;
|
||||||
|
|
||||||
|
// Cancel all d_main.c fadeouts (keep fade in though).
|
||||||
|
wipegamestate = FORCEWIPEOFF;
|
||||||
|
wipestyleflags = 0;
|
||||||
|
|
||||||
|
// Special stage fade to white
|
||||||
|
// This is handled BEFORE sounds are stopped.
|
||||||
|
if (modeattacking && !demoplayback && (pausedelay == INT32_MIN))
|
||||||
|
ranspecialwipe = 2;
|
||||||
|
else if (rendermode != render_none && G_IsSpecialStage(gamemap))
|
||||||
|
{
|
||||||
|
P_RunSpecialStageWipe();
|
||||||
ranspecialwipe = 1;
|
ranspecialwipe = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2637,25 +2882,7 @@ boolean P_SetupLevel(boolean skipprecip)
|
||||||
// Let's fade to black here
|
// Let's fade to black here
|
||||||
// But only if we didn't do the special stage wipe
|
// But only if we didn't do the special stage wipe
|
||||||
if (rendermode != render_none && !ranspecialwipe)
|
if (rendermode != render_none && !ranspecialwipe)
|
||||||
{
|
P_RunLevelWipe();
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!titlemapinaction)
|
if (!titlemapinaction)
|
||||||
{
|
{
|
||||||
|
@ -2713,14 +2940,7 @@ boolean P_SetupLevel(boolean skipprecip)
|
||||||
P_InitThinkers();
|
P_InitThinkers();
|
||||||
P_InitCachedActions();
|
P_InitCachedActions();
|
||||||
|
|
||||||
/// \note for not spawning precipitation, etc. when loading netgame snapshots
|
if (!fromnetsave && savedata.lives > 0)
|
||||||
if (skipprecip)
|
|
||||||
{
|
|
||||||
fromnetsave = 1;
|
|
||||||
loadprecip = 0;
|
|
||||||
loademblems = 0;
|
|
||||||
}
|
|
||||||
else if (savedata.lives > 0)
|
|
||||||
{
|
{
|
||||||
numgameovers = savedata.numgameovers;
|
numgameovers = savedata.numgameovers;
|
||||||
players[consoleplayer].continues = savedata.continues;
|
players[consoleplayer].continues = savedata.continues;
|
||||||
|
@ -2734,9 +2954,7 @@ boolean P_SetupLevel(boolean skipprecip)
|
||||||
|
|
||||||
// internal game map
|
// internal game map
|
||||||
maplumpname = G_BuildMapName(gamemap);
|
maplumpname = G_BuildMapName(gamemap);
|
||||||
//lastloadedmaplumpnum = LUMPERROR;
|
|
||||||
lastloadedmaplumpnum = W_CheckNumForName(maplumpname);
|
lastloadedmaplumpnum = W_CheckNumForName(maplumpname);
|
||||||
|
|
||||||
if (lastloadedmaplumpnum == INT16_MAX)
|
if (lastloadedmaplumpnum == INT16_MAX)
|
||||||
I_Error("Map %s not found.\n", maplumpname);
|
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.
|
// SRB2 determines the sky texture to be used depending on the map header.
|
||||||
P_SetupLevelSky(mapheaderinfo[gamemap-1]->skynum, true);
|
P_SetupLevelSky(mapheaderinfo[gamemap-1]->skynum, true);
|
||||||
|
|
||||||
numdmstarts = numredctfstarts = numbluectfstarts = 0;
|
P_ResetSpawnpoints();
|
||||||
|
|
||||||
// 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_MapStart();
|
P_MapStart();
|
||||||
|
|
||||||
if (lastloadedmaplumpnum)
|
if (lastloadedmaplumpnum)
|
||||||
{
|
P_LoadMapFromFile();
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
// init gravity, tag lists,
|
// init gravity, tag lists,
|
||||||
// anything that P_ResetDynamicSlopes/P_LoadThings needs to know
|
// anything that P_ResetDynamicSlopes/P_LoadThings needs to know
|
||||||
|
@ -2787,7 +2979,7 @@ boolean P_SetupLevel(boolean skipprecip)
|
||||||
P_ResetDynamicSlopes(fromnetsave);
|
P_ResetDynamicSlopes(fromnetsave);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
P_LoadThings(loademblems);
|
P_SpawnMapThings(!fromnetsave);
|
||||||
skyboxmo[0] = skyboxviewpnts[0];
|
skyboxmo[0] = skyboxviewpnts[0];
|
||||||
skyboxmo[1] = skyboxcenterpnts[0];
|
skyboxmo[1] = skyboxcenterpnts[0];
|
||||||
|
|
||||||
|
@ -2798,7 +2990,7 @@ boolean P_SetupLevel(boolean skipprecip)
|
||||||
// set up world state
|
// set up world state
|
||||||
P_SpawnSpecials(fromnetsave);
|
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();
|
P_SpawnPrecipitation();
|
||||||
|
|
||||||
#ifdef HWRENDER // not win32 only 19990829 by Kin
|
#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
|
// 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
|
// a netgame save is being loaded, and could actively be harmful by messing with
|
||||||
// the client's view of the data.)
|
// the client's view of the data.)
|
||||||
if (fromnetsave)
|
if (!fromnetsave)
|
||||||
goto netgameskip;
|
P_InitGametype();
|
||||||
// ==========
|
|
||||||
|
|
||||||
for (i = 0; i < MAXPLAYERS; i++)
|
P_InitCamera();
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
// clear special respawning que
|
// clear special respawning que
|
||||||
iquehead = iquetail = 0;
|
iquehead = iquetail = 0;
|
||||||
|
@ -3015,7 +3056,7 @@ boolean P_SetupLevel(boolean skipprecip)
|
||||||
|
|
||||||
lastmaploaded = gamemap; // HAS to be set after saving!!
|
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.
|
{ // to make a newly loaded level start on the second frame.
|
||||||
INT32 buf = gametic % BACKUPTICS;
|
INT32 buf = gametic % BACKUPTICS;
|
||||||
for (i = 0; i < MAXPLAYERS; i++)
|
for (i = 0; i < MAXPLAYERS; i++)
|
||||||
|
|
|
@ -97,7 +97,7 @@ void P_SetupLevelSky(INT32 skynum, boolean global);
|
||||||
void P_ScanThings(INT16 mapnum, INT16 wadnum, INT16 lumpnum);
|
void P_ScanThings(INT16 mapnum, INT16 wadnum, INT16 lumpnum);
|
||||||
#endif
|
#endif
|
||||||
void P_LoadThingsOnly(void);
|
void P_LoadThingsOnly(void);
|
||||||
boolean P_SetupLevel(boolean skipprecip);
|
boolean P_LoadLevel(boolean fromnetsave);
|
||||||
boolean P_AddWadFile(const char *wadfilename);
|
boolean P_AddWadFile(const char *wadfilename);
|
||||||
boolean P_RunSOC(const char *socfilename);
|
boolean P_RunSOC(const char *socfilename);
|
||||||
void P_LoadSoundsRange(UINT16 wadnum, UINT16 first, UINT16 num);
|
void P_LoadSoundsRange(UINT16 wadnum, UINT16 first, UINT16 num);
|
||||||
|
|
|
@ -553,11 +553,8 @@ pslope_t *P_SlopeById(UINT16 id)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reset slopes and read them from special lines.
|
/// Reset slopes and read them from special lines.
|
||||||
void P_ResetDynamicSlopes(const UINT32 fromsave) {
|
void P_ResetDynamicSlopes(const boolean fromsave) {
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
boolean spawnthinkers = !(boolean)fromsave;
|
|
||||||
|
|
||||||
slopelist = NULL;
|
slopelist = NULL;
|
||||||
slopecount = 0;
|
slopecount = 0;
|
||||||
|
|
||||||
|
@ -574,14 +571,14 @@ void P_ResetDynamicSlopes(const UINT32 fromsave) {
|
||||||
case 711:
|
case 711:
|
||||||
case 712:
|
case 712:
|
||||||
case 713:
|
case 713:
|
||||||
line_SpawnViaLine(i, spawnthinkers);
|
line_SpawnViaLine(i, !fromsave);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 704:
|
case 704:
|
||||||
case 705:
|
case 705:
|
||||||
case 714:
|
case 714:
|
||||||
case 715:
|
case 715:
|
||||||
line_SpawnViaVertexes(i, spawnthinkers);
|
line_SpawnViaVertexes(i, !fromsave);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -23,7 +23,7 @@ extern UINT16 slopecount;
|
||||||
void P_LinkSlopeThinkers (void);
|
void P_LinkSlopeThinkers (void);
|
||||||
|
|
||||||
void P_CalculateSlopeNormal(pslope_t *slope);
|
void P_CalculateSlopeNormal(pslope_t *slope);
|
||||||
void P_ResetDynamicSlopes(const UINT32 fromsave);
|
void P_ResetDynamicSlopes(const boolean fromsave);
|
||||||
|
|
||||||
//
|
//
|
||||||
// P_CopySectorSlope
|
// P_CopySectorSlope
|
||||||
|
|
|
@ -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.
|
* as they'll just be erased by UnArchiveThinkers.
|
||||||
* \sa P_SpawnPrecipitation, P_SpawnFriction, P_SpawnPushers, P_SpawnScrollers
|
* \sa P_SpawnPrecipitation, P_SpawnFriction, P_SpawnPushers, P_SpawnScrollers
|
||||||
*/
|
*/
|
||||||
void P_SpawnSpecials(INT32 fromnetsave)
|
void P_SpawnSpecials(boolean fromnetsave)
|
||||||
{
|
{
|
||||||
sector_t *sector;
|
sector_t *sector;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
|
@ -35,7 +35,7 @@ void P_SetupLevelFlatAnims(void);
|
||||||
|
|
||||||
// at map load
|
// at map load
|
||||||
void P_InitSpecials(void);
|
void P_InitSpecials(void);
|
||||||
void P_SpawnSpecials(INT32 fromnetsave);
|
void P_SpawnSpecials(boolean fromnetsave);
|
||||||
|
|
||||||
// every tic
|
// every tic
|
||||||
void P_UpdateSpecials(void);
|
void P_UpdateSpecials(void);
|
||||||
|
|
Loading…
Reference in a new issue