mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
Merge branch 'other-progression' into 'master'
Other Progression Closes #561 See merge request KartKrew/Kart!1606
This commit is contained in:
commit
47a01d0699
44 changed files with 609 additions and 135 deletions
|
|
@ -350,10 +350,13 @@ ACSVM::Word Environment::callSpecImpl
|
|||
|
||||
activator_t *activator = static_cast<activator_t *>(Z_Calloc(sizeof(activator_t), PU_LEVEL, nullptr));
|
||||
auto __ = srb2::finally(
|
||||
[activator]()
|
||||
[info, activator]()
|
||||
{
|
||||
P_SetTarget(&activator->mo, NULL);
|
||||
Z_Free(activator);
|
||||
if (info->thread_era == thinker_era)
|
||||
{
|
||||
P_SetTarget(&activator->mo, NULL);
|
||||
Z_Free(activator);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -70,6 +70,28 @@ void ACS_Shutdown(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
void ACS_InvalidateMapScope(size_t mapID)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
void ACS_InvalidateMapScope(void)
|
||||
{
|
||||
Environment *env = &ACSEnv;
|
||||
|
||||
ACSVM::GlobalScope *const global = env->getGlobalScope(0);
|
||||
ACSVM::HubScope *hub = NULL;
|
||||
ACSVM::MapScope *map = NULL;
|
||||
|
||||
// Conclude hub scope, even if we are not using it.
|
||||
hub = global->getHubScope(0);
|
||||
hub->reset();
|
||||
|
||||
// Conclude current map scope.
|
||||
map = hub->getMapScope(0); // This is where you'd put in mapID if you add hub support.
|
||||
map->reset();
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
void ACS_LoadLevelScripts(size_t mapID)
|
||||
|
||||
|
|
@ -103,14 +125,20 @@ void ACS_LoadLevelScripts(size_t mapID)
|
|||
// hubs are to be implemented, this logic would need
|
||||
// to be far more sophisticated.
|
||||
|
||||
// Reset hub scope, even if we are not using it.
|
||||
// Extra note regarding the commented out ->reset()'s:
|
||||
// This is too late! That needs to be done before
|
||||
// PU_LEVEL is purged. Call ACS_InvalidateMapScope
|
||||
// to take care of that. Those lines are left in
|
||||
// only as a warning to future code spelunkers.
|
||||
|
||||
// Restart hub scope, even if we are not using it.
|
||||
hub = global->getHubScope(0);
|
||||
hub->reset();
|
||||
//hub->reset();
|
||||
hub->active = true;
|
||||
|
||||
// Start up new map scope.
|
||||
map = hub->getMapScope(0); // This is where you'd put in mapID if you add hub support.
|
||||
map->reset();
|
||||
//map->reset();
|
||||
map->active = true;
|
||||
|
||||
// Insert BEHAVIOR lump into the list.
|
||||
|
|
|
|||
|
|
@ -44,6 +44,23 @@ void ACS_Init(void);
|
|||
void ACS_Shutdown(void);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
void ACS_InvalidateMapScope(size_t mapID);
|
||||
|
||||
Resets the ACS hub and map scopes to remove
|
||||
existing running scripts, without starting
|
||||
any new scripts.
|
||||
|
||||
Input Arguments:-
|
||||
None
|
||||
|
||||
Return:-
|
||||
None
|
||||
--------------------------------------------------*/
|
||||
|
||||
void ACS_InvalidateMapScope(void);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
void ACS_LoadLevelScripts(size_t mapID);
|
||||
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ enum acs_tagType_e
|
|||
class ThreadInfo : public ACSVM::ThreadInfo
|
||||
{
|
||||
public:
|
||||
UINT32 thread_era; // If equal to thinker_era, mobj pointers are safe.
|
||||
mobj_t *mo; // Object that activated this thread.
|
||||
line_t *line; // Linedef that activated this thread.
|
||||
UINT8 side; // Front / back side of said linedef.
|
||||
|
|
@ -67,6 +68,7 @@ public:
|
|||
bool fromLineSpecial; // Called from P_ProcessLineSpecial.
|
||||
|
||||
ThreadInfo() :
|
||||
thread_era { thinker_era },
|
||||
mo{ nullptr },
|
||||
line{ nullptr },
|
||||
side{ 0 },
|
||||
|
|
@ -77,6 +79,7 @@ public:
|
|||
}
|
||||
|
||||
ThreadInfo(const ThreadInfo &info) :
|
||||
thread_era { thinker_era },
|
||||
mo{ nullptr },
|
||||
line{ info.line },
|
||||
side{ info.side },
|
||||
|
|
@ -88,6 +91,7 @@ public:
|
|||
}
|
||||
|
||||
ThreadInfo(const activator_t *activator) :
|
||||
thread_era { thinker_era },
|
||||
mo{ nullptr },
|
||||
line{ activator->line },
|
||||
side{ activator->side },
|
||||
|
|
@ -100,11 +104,15 @@ public:
|
|||
|
||||
~ThreadInfo()
|
||||
{
|
||||
P_SetTarget(&mo, nullptr);
|
||||
if (thread_era == thinker_era)
|
||||
{
|
||||
P_SetTarget(&mo, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
ThreadInfo &operator = (const ThreadInfo &info)
|
||||
{
|
||||
thread_era = thinker_era;
|
||||
P_SetTarget(&mo, info.mo);
|
||||
line = info.line;
|
||||
side = info.side;
|
||||
|
|
|
|||
|
|
@ -1110,7 +1110,7 @@ static void SV_SendServerInfo(INT32 node, tic_t servertime)
|
|||
|
||||
M_Memcpy(netbuffer->u.serverinfo.mapmd5, mapmd5, 16);
|
||||
|
||||
if (!(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE) && !(mapheaderinfo[prevmap]->zonttl[0]))
|
||||
if (!(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE) && !(mapheaderinfo[gamemap-1]->zonttl[0]))
|
||||
netbuffer->u.serverinfo.iszone = 1;
|
||||
else
|
||||
netbuffer->u.serverinfo.iszone = 0;
|
||||
|
|
@ -1443,6 +1443,7 @@ static void CL_LoadReceivedSavegame(boolean reloading)
|
|||
demo.playback = false;
|
||||
demo.title = false;
|
||||
titlemapinaction = false;
|
||||
tutorialchallenge = TUTORIALSKIP_NONE;
|
||||
automapactive = false;
|
||||
|
||||
// load a base level
|
||||
|
|
@ -3992,7 +3993,9 @@ void SV_StopServer(void)
|
|||
Y_EndIntermission();
|
||||
if (gamestate == GS_VOTING)
|
||||
Y_EndVote();
|
||||
gamestate = wipegamestate = GS_NULL;
|
||||
|
||||
G_SetGamestate(GS_NULL);
|
||||
wipegamestate = GS_NULL;
|
||||
|
||||
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
|
||||
((UINT16*)localtextcmd[i])[0] = 0;
|
||||
|
|
|
|||
|
|
@ -1062,8 +1062,11 @@ void D_ClearState(void)
|
|||
memset(&grandprixinfo, 0, sizeof(struct grandprixinfo));
|
||||
memset(&roundqueue, 0, sizeof(struct roundqueue));
|
||||
|
||||
// empty maptol so mario/etc sounds don't play in sound test when they shouldn't
|
||||
// empty some other semi-important state
|
||||
maptol = 0;
|
||||
nextmapoverride = 0;
|
||||
skipstats = 0;
|
||||
tutorialchallenge = TUTORIALSKIP_NONE;
|
||||
|
||||
gameaction = ga_nothing;
|
||||
memset(displayplayers, 0, sizeof(displayplayers));
|
||||
|
|
|
|||
|
|
@ -2587,7 +2587,7 @@ static void Command_Map_f(void)
|
|||
SplitScreen_OnChange();
|
||||
}
|
||||
|
||||
if (!newnetgame && option_match == 0)
|
||||
if (!newnetgame && (newgametype != GT_TUTORIAL) && option_match == 0)
|
||||
{
|
||||
grandprixinfo.gp = true;
|
||||
grandprixinfo.initalize = true;
|
||||
|
|
@ -3022,7 +3022,7 @@ static void Command_QueueMap_f(void)
|
|||
return;
|
||||
}
|
||||
|
||||
if ((/*newmapnum != 1 &&*/ M_MapLocked(newmapnum)))
|
||||
if (/*newmapnum != 1 &&*/ M_MapLocked(newmapnum))
|
||||
{
|
||||
ischeating = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -355,6 +355,7 @@ struct respawnvars_t
|
|||
fixed_t pointx; // Respawn position coords to go towards
|
||||
fixed_t pointy;
|
||||
fixed_t pointz;
|
||||
angle_t pointangle; // Only used when wp is NULL
|
||||
boolean flip; // Flip upside down or not
|
||||
tic_t timer; // Time left on respawn animation once you're there
|
||||
tic_t airtimer; // Time spent in the air before respawning
|
||||
|
|
|
|||
|
|
@ -2791,7 +2791,8 @@ static void readcondition(UINT16 set, UINT32 id, char *word2)
|
|||
else if ((offset=0) || fastcmp(params[0], "ADDON")
|
||||
|| (++offset && fastcmp(params[0], "CREDITS"))
|
||||
|| (++offset && fastcmp(params[0], "REPLAY"))
|
||||
|| (++offset && fastcmp(params[0], "CRASH")))
|
||||
|| (++offset && fastcmp(params[0], "CRASH"))
|
||||
|| (++offset && fastcmp(params[0], "TUTORIALSKIP")))
|
||||
{
|
||||
//PARAMCHECK(1);
|
||||
ty = UC_ADDON + offset;
|
||||
|
|
@ -3469,6 +3470,11 @@ void readmaincfg(MYFILE *f, boolean mainfile)
|
|||
titlemap = Z_StrDup(word2);
|
||||
titlechanged = true;
|
||||
}
|
||||
else if (fastcmp(word, "TUTORIALCHALLENGEMAP"))
|
||||
{
|
||||
Z_Free(tutorialchallengemap);
|
||||
tutorialchallengemap = Z_StrDup(word2);
|
||||
}
|
||||
else if (fastcmp(word, "HIDETITLEPICS") || fastcmp(word, "TITLEPICSHIDE"))
|
||||
{
|
||||
hidetitlepics = (boolean)(value != 0 || word2[0] == 'T' || word2[0] == 'Y');
|
||||
|
|
|
|||
|
|
@ -246,11 +246,16 @@ extern INT32 g_localplayers[MAXSPLITSCREENPLAYERS];
|
|||
|
||||
extern char * titlemap;
|
||||
extern boolean hidetitlepics;
|
||||
extern char * bootmap; //bootmap for loading a map on startup
|
||||
extern boolean looptitle;
|
||||
|
||||
extern char * bootmap; //bootmap for loading a map on startup
|
||||
extern char * podiummap; // map to load for podium
|
||||
|
||||
extern boolean looptitle;
|
||||
extern char * tutorialchallengemap; // map to load for tutorial skip
|
||||
extern UINT8 tutorialchallenge;
|
||||
#define TUTORIALSKIP_NONE 0
|
||||
#define TUTORIALSKIP_FAILED 1
|
||||
#define TUTORIALSKIP_INPROGRESS 2
|
||||
|
||||
// CTF colors.
|
||||
extern UINT16 skincolor_redteam, skincolor_blueteam, skincolor_redring, skincolor_bluering;
|
||||
|
|
|
|||
155
src/g_game.c
155
src/g_game.c
|
|
@ -83,7 +83,7 @@
|
|||
|
||||
gameaction_t gameaction;
|
||||
gamestate_t gamestate = GS_NULL;
|
||||
UINT8 ultimatemode = false;
|
||||
boolean ultimatemode = false;
|
||||
|
||||
JoyType_t Joystick[MAXSPLITSCREENPLAYERS];
|
||||
|
||||
|
|
@ -170,11 +170,13 @@ tic_t timeinmap; // Ticker for time spent in level (used for levelcard display)
|
|||
|
||||
char * titlemap = NULL;
|
||||
boolean hidetitlepics = false;
|
||||
char * bootmap = NULL; //bootmap for loading a map on startup
|
||||
boolean looptitle = true;
|
||||
|
||||
char * bootmap = NULL; //bootmap for loading a map on startup
|
||||
char * podiummap = NULL; // map to load for podium
|
||||
|
||||
boolean looptitle = true;
|
||||
char * tutorialchallengemap = NULL; // map to load for tutorial skip
|
||||
UINT8 tutorialchallenge = TUTORIALSKIP_NONE;
|
||||
|
||||
UINT16 skincolor_redteam = SKINCOLOR_RED;
|
||||
UINT16 skincolor_blueteam = SKINCOLOR_BLUE;
|
||||
|
|
@ -717,14 +719,18 @@ INT32 G_MapNumber(const char * name)
|
|||
|
||||
name += 8;
|
||||
|
||||
if (strcasecmp("TITLE", name) == 0)
|
||||
return NEXTMAP_TITLE;
|
||||
if (strcasecmp("EVALUATION", name) == 0)
|
||||
return NEXTMAP_EVALUATION;
|
||||
if (strcasecmp("CREDITS", name) == 0)
|
||||
return NEXTMAP_CREDITS;
|
||||
if (strcasecmp("CEREMONY", name) == 0)
|
||||
return NEXTMAP_CEREMONY;
|
||||
if (strcasecmp("TITLE", name) == 0)
|
||||
return NEXTMAP_TITLE;
|
||||
if (strcasecmp("VOTING", name) == 0)
|
||||
return NEXTMAP_VOTING;
|
||||
if (strcasecmp("TUTORIALCHALLENGE", name) == 0)
|
||||
return NEXTMAP_TUTORIALCHALLENGE;
|
||||
|
||||
return NEXTMAP_INVALID;
|
||||
}
|
||||
|
|
@ -2499,8 +2505,7 @@ void G_MovePlayerToSpawnOrCheatcheck(INT32 playernum)
|
|||
rsp->pointx = pos.x;
|
||||
rsp->pointy = pos.y;
|
||||
rsp->pointz = pos.z;
|
||||
|
||||
players[playernum].mo->angle = Obj_GetCheckpointRespawnAngle(checkpoint);
|
||||
rsp->pointangle = Obj_GetCheckpointRespawnAngle(checkpoint);
|
||||
|
||||
Obj_ActivateCheckpointInstantly(checkpoint);
|
||||
|
||||
|
|
@ -3354,7 +3359,7 @@ UINT32 G_TOLFlag(INT32 pgametype)
|
|||
return 0;
|
||||
}
|
||||
|
||||
UINT16 G_GetFirstMapOfGametype(UINT8 pgametype)
|
||||
UINT16 G_GetFirstMapOfGametype(UINT16 pgametype)
|
||||
{
|
||||
UINT8 i = 0;
|
||||
UINT16 mapnum = NEXTMAP_INVALID;
|
||||
|
|
@ -3364,7 +3369,7 @@ UINT16 G_GetFirstMapOfGametype(UINT8 pgametype)
|
|||
templevelsearch.typeoflevel = G_TOLFlag(pgametype);
|
||||
templevelsearch.cupmode = (!(gametypes[pgametype]->rules & GTR_NOCUPSELECT));
|
||||
templevelsearch.timeattack = false;
|
||||
templevelsearch.tutorial = false;
|
||||
templevelsearch.tutorial = (pgametype == GT_TUTORIAL);
|
||||
templevelsearch.checklocked = true;
|
||||
|
||||
if (templevelsearch.cupmode)
|
||||
|
|
@ -3618,6 +3623,14 @@ void G_UpdateVisited(void)
|
|||
if (demo.playback)
|
||||
return;
|
||||
|
||||
// For some reason, we don't want to update visitation flags.
|
||||
if (prevmap != gamemap-1)
|
||||
return;
|
||||
|
||||
// Neither for tutorial skip material
|
||||
if (nextmapoverride == NEXTMAP_TUTORIALCHALLENGE+1 || tutorialchallenge != TUTORIALSKIP_NONE)
|
||||
return;
|
||||
|
||||
// Check if every local player wiped out.
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
|
|
@ -3627,7 +3640,7 @@ void G_UpdateVisited(void)
|
|||
if (!P_IsLocalPlayer(&players[i])) // Not local.
|
||||
continue;
|
||||
|
||||
if (players[i].spectator) // Not playing.
|
||||
if (players[i].spectator == true) // Not playing.
|
||||
continue;
|
||||
|
||||
if (players[i].pflags & PF_NOCONTEST) // Sonic after not surviving.
|
||||
|
|
@ -3658,7 +3671,7 @@ void G_UpdateVisited(void)
|
|||
CONS_Printf(M_GetText("\x82" "Earned %hu emblem%s for level completion.\n"), (UINT16)earnedEmblems, earnedEmblems > 1 ? "s" : "");
|
||||
|
||||
M_UpdateUnlockablesAndExtraEmblems(true, true);
|
||||
G_SaveGameData();
|
||||
gamedata->deferredsave = true;
|
||||
}
|
||||
|
||||
void G_HandleSaveLevel(boolean removecondition)
|
||||
|
|
@ -4148,11 +4161,6 @@ static void G_DoCompleted(void)
|
|||
gamedata->deferredsave = true;
|
||||
}
|
||||
|
||||
// This isn't in the above block because other
|
||||
// mechanisms can queue up a gamedata save.
|
||||
if (gamedata->deferredsave)
|
||||
G_SaveGameData();
|
||||
|
||||
// Then, update some important game state.
|
||||
{
|
||||
legitimateexit = false;
|
||||
|
|
@ -4172,14 +4180,18 @@ static void G_DoCompleted(void)
|
|||
|
||||
G_SetGamestate(GS_NULL);
|
||||
wipegamestate = GS_NULL;
|
||||
|
||||
prevmap = (INT16)(gamemap-1);
|
||||
}
|
||||
|
||||
// Finally, if you're not exiting, guarantee NO CONTEST.
|
||||
// We do this seperately from the loop above Challenges,
|
||||
// so NOCONTEST-related Challenges don't fire on exitlevel.
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
if (gametype == GT_TUTORIAL)
|
||||
{
|
||||
// Maybe one day there'll be another context in which
|
||||
// there's no way to progress other than ACS, but for
|
||||
// now, Tutorial is a hardcoded exception.
|
||||
}
|
||||
else for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (playeringame[i] == false)
|
||||
{
|
||||
|
|
@ -4195,6 +4207,40 @@ static void G_DoCompleted(void)
|
|||
}
|
||||
|
||||
// And lastly, everything in anticipation for Intermission/level change.
|
||||
|
||||
if (tutorialchallenge == TUTORIALSKIP_INPROGRESS)
|
||||
{
|
||||
if (
|
||||
!legitimateexit
|
||||
|| !players[consoleplayer].exiting
|
||||
|| K_IsPlayerLosing(&players[consoleplayer])
|
||||
)
|
||||
{
|
||||
// Return to whence you came with your tail between your legs
|
||||
tutorialchallenge = TUTORIALSKIP_FAILED;
|
||||
G_SetGametype(GT_TUTORIAL);
|
||||
nextmapoverride = prevmap+1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Proceed.
|
||||
nextmapoverride = NEXTMAP_TITLE+1;
|
||||
|
||||
gamedata->finishedtutorialchallenge = true;
|
||||
|
||||
M_UpdateUnlockablesAndExtraEmblems(true, true);
|
||||
gamedata->deferredsave = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// The "else" might not be strictly needed, but I don't
|
||||
// want the "challenge" map to be considered visited before it's your time.
|
||||
// ~toast 161123 (5 years of srb2kart, woooouuuu)
|
||||
prevmap = gamemap-1;
|
||||
tutorialchallenge = TUTORIALSKIP_NONE;
|
||||
}
|
||||
|
||||
if (!demo.playback)
|
||||
{
|
||||
// Set up power level gametype scrambles
|
||||
|
|
@ -4219,6 +4265,11 @@ static void G_DoCompleted(void)
|
|||
Y_StartIntermission();
|
||||
G_UpdateVisited();
|
||||
}
|
||||
|
||||
// This isn't in the above blocks because many
|
||||
// mechanisms can queue up a gamedata save.
|
||||
if (gamedata->deferredsave)
|
||||
G_SaveGameData();
|
||||
}
|
||||
|
||||
// See also F_EndCutscene, the only other place which handles intra-map/ending transitions
|
||||
|
|
@ -4265,6 +4316,27 @@ void G_AfterIntermission(void)
|
|||
//
|
||||
void G_NextLevel(void)
|
||||
{
|
||||
if (
|
||||
gametype == GT_TUTORIAL
|
||||
&& nextmap == NEXTMAP_TUTORIALCHALLENGE
|
||||
&& !(gamedata && gamedata->enteredtutorialchallenge)
|
||||
)
|
||||
{
|
||||
nextmap = G_MapNumber(tutorialchallengemap);
|
||||
if (
|
||||
nextmap < nummapheaders
|
||||
&& mapheaderinfo[nextmap] != NULL
|
||||
&& mapheaderinfo[nextmap]->typeoflevel != 0
|
||||
)
|
||||
{
|
||||
tutorialchallenge = TUTORIALSKIP_INPROGRESS;
|
||||
G_SetGametype(G_GuessGametypeByTOL(mapheaderinfo[nextmap]->typeoflevel));
|
||||
|
||||
gamedata->enteredtutorialchallenge = true;
|
||||
// A gamedata save will happen on successful level enter
|
||||
}
|
||||
}
|
||||
|
||||
if (nextmap >= NEXTMAP_SPECIAL)
|
||||
{
|
||||
G_EndGame();
|
||||
|
|
@ -4467,6 +4539,8 @@ typedef enum
|
|||
GDEVER_SPECIAL = 1<<3,
|
||||
GDEVER_KEYTUTORIAL = 1<<4,
|
||||
GDEVER_KEYMAJORSKIP = 1<<5,
|
||||
GDEVER_TUTORIALSKIP = 1<<6,
|
||||
GDEVER_ENTERTUTSKIP = 1<<7,
|
||||
} gdeverdone_t;
|
||||
|
||||
static const char *G_GameDataFolder(void)
|
||||
|
|
@ -4606,6 +4680,8 @@ void G_LoadGameData(void)
|
|||
gamedata->everseenspecial = !!(everflags & GDEVER_SPECIAL);
|
||||
gamedata->chaokeytutorial = !!(everflags & GDEVER_KEYTUTORIAL);
|
||||
gamedata->majorkeyskipattempted = !!(everflags & GDEVER_KEYMAJORSKIP);
|
||||
gamedata->finishedtutorialchallenge = !!(everflags & GDEVER_TUTORIALSKIP);
|
||||
gamedata->enteredtutorialchallenge = !!(everflags & GDEVER_ENTERTUTSKIP);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -5297,6 +5373,10 @@ void G_SaveGameData(void)
|
|||
everflags |= GDEVER_KEYTUTORIAL;
|
||||
if (gamedata->majorkeyskipattempted)
|
||||
everflags |= GDEVER_KEYMAJORSKIP;
|
||||
if (gamedata->finishedtutorialchallenge)
|
||||
everflags |= GDEVER_TUTORIALSKIP;
|
||||
if (gamedata->enteredtutorialchallenge)
|
||||
everflags |= GDEVER_ENTERTUTSKIP;
|
||||
|
||||
WRITEUINT32(save.p, everflags); // 4
|
||||
}
|
||||
|
|
@ -5990,7 +6070,9 @@ INT32 G_FindMap(const char *mapname, char **foundmapnamep,
|
|||
aprop = realmapname;
|
||||
|
||||
/* Now that we found a perfect match no need to fucking guess. */
|
||||
if (strnicmp(realmapname, mapname, mapnamelen) == 0)
|
||||
if (strnicmp(realmapname, mapname, mapnamelen) == 0
|
||||
|| (mapheaderinfo[i]->menuttl[0]
|
||||
&& strnicmp(mapheaderinfo[i]->menuttl, mapname, mapnamelen) == 0))
|
||||
{
|
||||
if (wanttable)
|
||||
{
|
||||
|
|
@ -6024,15 +6106,42 @@ INT32 G_FindMap(const char *mapname, char **foundmapnamep,
|
|||
realmapname = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (mapheaderinfo[i]->menuttl[0] && ( aprop = strcasestr(mapheaderinfo[i]->menuttl, mapname) ))
|
||||
{
|
||||
if (wanttable)
|
||||
{
|
||||
writesimplefreq(freq, &freqc,
|
||||
mapnum, aprop - mapheaderinfo[i]->menuttl, mapnamelen);
|
||||
}
|
||||
if (apromapnum == 0)
|
||||
{
|
||||
apromapnum = mapnum;
|
||||
apromapname = realmapname;
|
||||
realmapname = 0;
|
||||
}
|
||||
}
|
||||
else/* ...match individual keywords */
|
||||
{
|
||||
freq[freqc].mapnum = mapnum;
|
||||
measurekeywords(&freq[freqc],
|
||||
&freq[freqc].matchd, &freq[freqc].matchc,
|
||||
realmapname, mapname, wanttable);
|
||||
measurekeywords(&freq[freqc],
|
||||
&freq[freqc].keywhd, &freq[freqc].keywhc,
|
||||
mapheaderinfo[i]->keywords, mapname, wanttable);
|
||||
|
||||
if (mapheaderinfo[i]->menuttl[0])
|
||||
{
|
||||
measurekeywords(&freq[freqc],
|
||||
&freq[freqc].keywhd, &freq[freqc].keywhc,
|
||||
mapheaderinfo[i]->menuttl, mapname, wanttable);
|
||||
}
|
||||
|
||||
if (mapheaderinfo[i]->keywords[0])
|
||||
{
|
||||
measurekeywords(&freq[freqc],
|
||||
&freq[freqc].keywhd, &freq[freqc].keywhc,
|
||||
mapheaderinfo[i]->keywords, mapname, wanttable);
|
||||
}
|
||||
|
||||
if (freq[freqc].total)
|
||||
freqc++;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,7 +49,8 @@ typedef enum
|
|||
NEXTMAP_CREDITS = INT16_MAX-3,
|
||||
NEXTMAP_CEREMONY = INT16_MAX-4,
|
||||
NEXTMAP_VOTING = INT16_MAX-5,
|
||||
NEXTMAP_INVALID = INT16_MAX-6, // Always last
|
||||
NEXTMAP_TUTORIALCHALLENGE = INT16_MAX-6,
|
||||
NEXTMAP_INVALID = INT16_MAX-7, // Always last
|
||||
NEXTMAP_SPECIAL = NEXTMAP_INVALID
|
||||
} nextmapspecial_t;
|
||||
|
||||
|
|
@ -279,7 +280,7 @@ FUNCMATH INT32 G_TicsToMilliseconds(tic_t tics);
|
|||
|
||||
// Don't split up TOL handling
|
||||
UINT32 G_TOLFlag(INT32 pgametype);
|
||||
UINT16 G_GetFirstMapOfGametype(UINT8 pgametype);
|
||||
UINT16 G_GetFirstMapOfGametype(UINT16 pgametype);
|
||||
|
||||
UINT16 G_RandMap(UINT32 tolflags, UINT16 pprevmap, boolean ignoreBuffers, boolean callAgainSoon, UINT16 *extBuffer);
|
||||
void G_AddMapToBuffer(UINT16 map);
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ typedef enum
|
|||
|
||||
extern gamestate_t gamestate;
|
||||
extern boolean titlemapinaction;
|
||||
extern UINT8 ultimatemode; // was sk_insane
|
||||
extern boolean ultimatemode; // was sk_insane
|
||||
extern gameaction_t gameaction;
|
||||
|
||||
void G_SetGamestate(gamestate_t newstate);
|
||||
|
|
|
|||
|
|
@ -39,6 +39,9 @@ UINT8 numtargets = 0; // Capsules busted
|
|||
|
||||
INT32 K_StartingBumperCount(void)
|
||||
{
|
||||
if (tutorialchallenge == TUTORIALSKIP_INPROGRESS)
|
||||
return 0;
|
||||
|
||||
if (battleprisons || K_CheckBossIntro())
|
||||
{
|
||||
if (grandprixinfo.gp)
|
||||
|
|
|
|||
|
|
@ -71,8 +71,50 @@ void K_SetBot(UINT8 newplayernum, UINT8 skinnum, UINT8 difficulty, botStyle_e st
|
|||
// For each subsequent round of GP, K_UpdateGrandPrixBots will handle this.
|
||||
players[newplayernum].spectator = grandprixinfo.gp && grandprixinfo.initalize && K_BotDefaultSpectator();
|
||||
|
||||
players[newplayernum].skincolor = skins[skinnum].prefcolor;
|
||||
sprintf(player_names[newplayernum], "%s", skins[skinnum].realname);
|
||||
skincolornum_t color = static_cast<skincolornum_t>(skins[skinnum].prefcolor);
|
||||
const char *realname = skins[skinnum].realname;
|
||||
if (tutorialchallenge == TUTORIALSKIP_INPROGRESS)
|
||||
{
|
||||
// The ROYGBIV Rangers
|
||||
switch (newplayernum)
|
||||
{
|
||||
case 1:
|
||||
color = SKINCOLOR_RED;
|
||||
realname = "Champ";
|
||||
break;
|
||||
case 2:
|
||||
color = SKINCOLOR_ORANGE;
|
||||
realname = "Pharaoh";
|
||||
break;
|
||||
case 3:
|
||||
color = SKINCOLOR_YELLOW;
|
||||
realname = "Caesar";
|
||||
break;
|
||||
case 4:
|
||||
color = SKINCOLOR_GREEN;
|
||||
realname = "General";
|
||||
break;
|
||||
case 5:
|
||||
color = SKINCOLOR_CYAN; // blue (lighter than _BLUE)
|
||||
realname = "Shogun";
|
||||
break;
|
||||
case 6:
|
||||
color = SKINCOLOR_BLUEBERRY; // indigo
|
||||
realname = "Emperor";
|
||||
break;
|
||||
case 7:
|
||||
color = SKINCOLOR_VIOLET;
|
||||
realname = "King";
|
||||
break;
|
||||
default:
|
||||
color = SKINCOLOR_BLACK;
|
||||
realname = "Vizier"; // working in the shadows
|
||||
break;
|
||||
}
|
||||
}
|
||||
players[newplayernum].skincolor = color;
|
||||
sprintf(player_names[newplayernum], "%s", realname);
|
||||
|
||||
SetPlayerSkinByNum(newplayernum, skinnum);
|
||||
|
||||
playerconsole[newplayernum] = newplayernum;
|
||||
|
|
@ -128,8 +170,8 @@ boolean K_AddBot(UINT8 skin, UINT8 difficulty, botStyle_e style, UINT8 *p)
|
|||
void K_UpdateMatchRaceBots(void)
|
||||
{
|
||||
const UINT8 defaultbotskin = R_BotDefaultSkin();
|
||||
const UINT8 difficulty = cv_kartbot.value;
|
||||
UINT8 pmax = std::min<UINT8>((dedicated ? MAXPLAYERS-1 : MAXPLAYERS), static_cast<UINT8>(cv_maxconnections.value));
|
||||
UINT8 difficulty;
|
||||
UINT8 pmax = (dedicated ? MAXPLAYERS-1 : MAXPLAYERS);
|
||||
UINT8 numplayers = 0;
|
||||
UINT8 numbots = 0;
|
||||
UINT8 numwaiting = 0;
|
||||
|
|
@ -145,9 +187,27 @@ void K_UpdateMatchRaceBots(void)
|
|||
}
|
||||
grabskins[usableskins] = MAXSKINS;
|
||||
|
||||
if (cv_maxplayers.value > 0)
|
||||
if ((gametyperules & GTR_BOTS) == 0)
|
||||
{
|
||||
pmax = std::min<UINT8>(pmax, static_cast<UINT8>(cv_maxplayers.value));
|
||||
difficulty = 0;
|
||||
}
|
||||
else if (tutorialchallenge == TUTORIALSKIP_INPROGRESS)
|
||||
{
|
||||
pmax = 8; // can you believe this is a nerf
|
||||
difficulty = MAXBOTDIFFICULTY;
|
||||
}
|
||||
else if (K_CanChangeRules(true) == false)
|
||||
{
|
||||
difficulty = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
difficulty = cv_kartbot.value;
|
||||
pmax = std::min<UINT8>(pmax, static_cast<UINT8>(cv_maxconnections.value));
|
||||
if (cv_maxplayers.value > 0)
|
||||
{
|
||||
pmax = std::min<UINT8>(pmax, static_cast<UINT8>(cv_maxplayers.value));
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
|
|
@ -180,9 +240,7 @@ void K_UpdateMatchRaceBots(void)
|
|||
}
|
||||
}
|
||||
|
||||
if (K_CanChangeRules(true) == false
|
||||
|| (gametyperules & GTR_BOTS) == 0
|
||||
|| difficulty == 0)
|
||||
if (difficulty == 0)
|
||||
{
|
||||
// Remove bots if there are any.
|
||||
wantedbots = 0;
|
||||
|
|
@ -209,7 +267,11 @@ void K_UpdateMatchRaceBots(void)
|
|||
}
|
||||
|
||||
// Rearrange usable bot skins list to prevent gaps for randomised selection
|
||||
for (i = 0; i < usableskins; i++)
|
||||
if (tutorialchallenge == TUTORIALSKIP_INPROGRESS)
|
||||
{
|
||||
usableskins = 0; // force a crack team of Eggrobo
|
||||
}
|
||||
else for (i = 0; i < usableskins; i++)
|
||||
{
|
||||
if (!(grabskins[i] == MAXSKINS || !R_SkinUsable(-1, grabskins[i], true)))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -831,7 +831,7 @@ boolean K_CanChangeRules(boolean allowdemos)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (gametype == GT_TUTORIAL)
|
||||
if (gametype == GT_TUTORIAL || tutorialchallenge == TUTORIALSKIP_INPROGRESS)
|
||||
{
|
||||
// Tutorials are locked down.
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -2352,6 +2352,8 @@ static boolean K_drawKartPositionFaces(void)
|
|||
|
||||
if ((gametyperules & GTR_BUMPERS) && (players[rankplayer[i]].pflags & PF_ELIMINATED))
|
||||
V_DrawScaledPatch(FACE_X-4, Y-3, V_HUDTRANS|V_SLIDEIN|V_SNAPTOLEFT, kp_ranknobumpers);
|
||||
else if (K_Cooperative())
|
||||
;
|
||||
else if (gametyperules & GTR_CIRCUIT)
|
||||
{
|
||||
INT32 pos = players[rankplayer[i]].position;
|
||||
|
|
@ -2360,7 +2362,7 @@ static boolean K_drawKartPositionFaces(void)
|
|||
// Draws the little number over the face
|
||||
V_DrawScaledPatch(FACE_X-5, Y+10, V_HUDTRANS|V_SLIDEIN|V_SNAPTOLEFT, kp_facenum[pos]);
|
||||
}
|
||||
else
|
||||
else if (gametyperules & GTR_POINTLIMIT)
|
||||
{
|
||||
INT32 flags = V_HUDTRANS | V_SLIDEIN | V_SNAPTOLEFT;
|
||||
|
||||
|
|
@ -5526,7 +5528,7 @@ void K_drawKartHUD(void)
|
|||
if (!battleprisons)
|
||||
K_drawKartEmeralds();
|
||||
}
|
||||
else if (!islonesome)
|
||||
else if (!islonesome && !K_Cooperative())
|
||||
K_DrawKartPositionNum(stplyr->position);
|
||||
}
|
||||
|
||||
|
|
|
|||
18
src/k_kart.c
18
src/k_kart.c
|
|
@ -396,6 +396,9 @@ boolean K_IsPlayerLosing(player_t *player)
|
|||
if (specialstageinfo.valid == true)
|
||||
return false; // anything short of DNF is COOL
|
||||
|
||||
if (tutorialchallenge == TUTORIALSKIP_INPROGRESS)
|
||||
return true; // anything short of perfect is SUCK
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i] || players[i].spectator)
|
||||
|
|
@ -582,6 +585,15 @@ boolean K_TimeAttackRules(void)
|
|||
return true;
|
||||
}
|
||||
|
||||
if (gametype == GT_TUTORIAL)
|
||||
{
|
||||
// Tutorials are special. By default only one
|
||||
// player will be playing... but sometimes bots
|
||||
// can be spawned! So we still guarantee the
|
||||
// changed behaviour for consistency.
|
||||
return true;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (playeringame[i] == false || players[i].spectator == true)
|
||||
|
|
@ -13076,6 +13088,12 @@ boolean K_Cooperative(void)
|
|||
return true;
|
||||
}
|
||||
|
||||
if (gametype == GT_TUTORIAL)
|
||||
{
|
||||
// Maybe this should be a rule. Eventually?
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -451,6 +451,8 @@ typedef enum
|
|||
#endif
|
||||
mpause_admin,
|
||||
mpause_callvote,
|
||||
|
||||
mpause_giveup,
|
||||
mpause_restartmap,
|
||||
mpause_tryagain,
|
||||
|
||||
|
|
@ -1104,6 +1106,7 @@ extern consvar_t cv_dummyspectator;
|
|||
// Bunch of funny functions for the pause menu...~
|
||||
void M_RestartMap(INT32 choice); // Restart level (MP)
|
||||
void M_TryAgain(INT32 choice); // Try again (SP)
|
||||
void M_GiveUp(INT32 choice); // Give up (SP)
|
||||
void M_ConfirmSpectate(INT32 choice); // Spectate confirm when you're alone
|
||||
void M_ConfirmEnterGame(INT32 choice); // Enter game confirm when you're alone
|
||||
void M_ConfirmSpectateChange(INT32 choice); // Splitscreen spectate/play menu func
|
||||
|
|
@ -1133,7 +1136,9 @@ char *M_AddonsHeaderPath(void);
|
|||
extern consvar_t cv_dummyaddonsearch;
|
||||
extern consvar_t cv_dummyextraspassword;
|
||||
|
||||
#ifdef TODONEWMANUAL
|
||||
void M_Manual(INT32 choice);
|
||||
#endif
|
||||
void M_HandleImageDef(INT32 choice);
|
||||
|
||||
// K_MENUDRAW.C
|
||||
|
|
|
|||
|
|
@ -775,6 +775,7 @@ void M_Drawer(void)
|
|||
if (menuwipe)
|
||||
F_WipeStartScreen();
|
||||
|
||||
// background layer
|
||||
if (menuactive)
|
||||
{
|
||||
if (gamestate == GS_MENU)
|
||||
|
|
@ -785,7 +786,17 @@ void M_Drawer(void)
|
|||
{
|
||||
V_DrawFadeScreen(122, 3);
|
||||
}
|
||||
}
|
||||
|
||||
// draw pause pic
|
||||
if (paused && !demo.playback && (menuactive || cv_showhud.value))
|
||||
{
|
||||
M_DrawPausedText(0);
|
||||
}
|
||||
|
||||
// foreground layer
|
||||
if (menuactive)
|
||||
{
|
||||
if (currentMenu->drawroutine)
|
||||
currentMenu->drawroutine(); // call current menu Draw routine
|
||||
|
||||
|
|
@ -813,18 +824,6 @@ void M_Drawer(void)
|
|||
menuwipe = false;
|
||||
}
|
||||
|
||||
// draw pause pic
|
||||
if (paused && !demo.playback && (menuactive || cv_showhud.value))
|
||||
{
|
||||
// Don't cover the Stereo player!
|
||||
boolean stereo_open = menuactive && currentMenu == &MISC_SoundTestDef;
|
||||
|
||||
if (stereo_open == false)
|
||||
{
|
||||
M_DrawPausedText(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (netgame && Playing())
|
||||
{
|
||||
boolean mainpause_open = menuactive && currentMenu == &PAUSE_MainDef;
|
||||
|
|
@ -2909,7 +2908,7 @@ static void M_DrawHighLowLevelTitle(INT16 x, INT16 y, INT16 map)
|
|||
V_DrawLSTitleLowString(x2, y+28, 0, word2);
|
||||
}
|
||||
|
||||
static void M_DrawLevelSelectBlock(INT16 x, INT16 y, INT16 map, boolean redblink, boolean greyscale)
|
||||
static void M_DrawLevelSelectBlock(INT16 x, INT16 y, UINT16 map, boolean redblink, boolean greyscale)
|
||||
{
|
||||
UINT8 *colormap = NULL;
|
||||
|
||||
|
|
@ -2928,6 +2927,20 @@ static void M_DrawLevelSelectBlock(INT16 x, INT16 y, INT16 map, boolean redblink
|
|||
map,
|
||||
colormap);
|
||||
M_DrawHighLowLevelTitle(98+x, y+8, map);
|
||||
|
||||
if (levellist.levelsearch.tutorial && !(mapheaderinfo[map]->records.mapvisited & MV_BEATEN))
|
||||
{
|
||||
V_DrawScaledPatch(
|
||||
x + 80 + 3, y + 50, 0,
|
||||
W_CachePatchName(
|
||||
va(
|
||||
"CUPBKUP%c",
|
||||
(greyscale ? '1' : '2')
|
||||
),
|
||||
PU_CACHE
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void M_DrawLevelSelect(void)
|
||||
|
|
|
|||
|
|
@ -980,9 +980,11 @@ void K_FinishCeremony(void)
|
|||
|
||||
g_podiumData.ranking = true;
|
||||
|
||||
// Play the noise now (via G_UpdateVisited's concluding gamedata save)
|
||||
// Play the noise now (via G_UpdateVisited's concluding challenge check)
|
||||
prevmap = gamemap-1;
|
||||
G_UpdateVisited();
|
||||
if (gamedata->deferredsave)
|
||||
G_SaveGameData();
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
#include "d_player.h"
|
||||
#include "k_kart.h"
|
||||
#include "k_battle.h"
|
||||
#include "k_objects.h" // Obj_FindCheckpoint, etc
|
||||
#include "g_game.h"
|
||||
#include "p_local.h"
|
||||
#include "p_tick.h"
|
||||
|
|
@ -163,6 +164,9 @@ void K_DoIngameRespawn(player_t *player)
|
|||
K_TumbleInterrupt(player);
|
||||
P_ResetPlayer(player);
|
||||
|
||||
mobj_t *checkpoint;
|
||||
vector3_t pos;
|
||||
|
||||
// Set up respawn position if invalid
|
||||
if (player->respawn.manual == true)
|
||||
{
|
||||
|
|
@ -194,6 +198,21 @@ void K_DoIngameRespawn(player_t *player)
|
|||
K_RespawnAtWaypoint(player, player->respawn.wp);
|
||||
}
|
||||
}
|
||||
else if ((gametyperules & GTR_CHECKPOINTS)
|
||||
&& player->checkpointId
|
||||
&& (checkpoint = Obj_FindCheckpoint(player->checkpointId))
|
||||
&& Obj_GetCheckpointRespawnPosition(checkpoint, &pos))
|
||||
{
|
||||
player->respawn.wp = NULL;
|
||||
player->respawn.flip = (checkpoint->flags2 & MF2_OBJECTFLIP) ? true : false; // K_RespawnOffset wants a boolean!
|
||||
player->respawn.pointx = pos.x;
|
||||
player->respawn.pointy = pos.y;
|
||||
player->respawn.pointz = pos.z + K_RespawnOffset(player, player->respawn.flip);
|
||||
|
||||
player->respawn.pointangle = Obj_GetCheckpointRespawnAngle(checkpoint);
|
||||
|
||||
player->respawn.distanceleft = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
UINT32 bestdist = UINT32_MAX;
|
||||
|
|
@ -244,6 +263,7 @@ void K_DoIngameRespawn(player_t *player)
|
|||
player->respawn.pointx = 0;
|
||||
player->respawn.pointy = 0;
|
||||
player->respawn.pointz = 0;
|
||||
player->respawn.pointangle = 0;
|
||||
player->respawn.flip = false;
|
||||
}
|
||||
else
|
||||
|
|
@ -254,7 +274,7 @@ void K_DoIngameRespawn(player_t *player)
|
|||
player->respawn.pointx = beststart->x << FRACBITS;
|
||||
player->respawn.pointy = beststart->y << FRACBITS;
|
||||
|
||||
player->mo->angle = ( beststart->angle * ANG1 );
|
||||
player->respawn.pointangle = ( beststart->angle * ANG1 );
|
||||
|
||||
s = R_PointInSubsector(beststart->x << FRACBITS, beststart->y << FRACBITS)->sector;
|
||||
|
||||
|
|
@ -476,6 +496,11 @@ static void K_MovePlayerToRespawnPoint(player_t *player)
|
|||
else
|
||||
{
|
||||
// We can now drop!
|
||||
if (gametyperules & GTR_CHECKPOINTS)
|
||||
{
|
||||
// Of course, in gametypes where there's a clear and intended progression, set our direction.
|
||||
P_SetPlayerAngle(player, (player->drawangle = player->respawn.pointangle));
|
||||
}
|
||||
player->respawn.state = RESPAWNST_DROP;
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -183,7 +183,7 @@ static kartitems_t K_KartItemReelSpecialEnd[] =
|
|||
KITEM_NONE
|
||||
};
|
||||
|
||||
static kartitems_t K_KartItemReelTimeAttack[] =
|
||||
static kartitems_t K_KartItemReelRingSneaker[] =
|
||||
{
|
||||
KITEM_SNEAKER,
|
||||
KITEM_SUPERRING,
|
||||
|
|
@ -1228,7 +1228,7 @@ static void K_CalculateRouletteSpeed(itemroulette_t *const roulette)
|
|||
fixed_t progress = 0;
|
||||
fixed_t total = 0;
|
||||
|
||||
if (bossinfo.valid == true)
|
||||
if (K_CheckBossIntro() == true)
|
||||
{
|
||||
// Boss in action, use a speed controlled by boss health
|
||||
total = FixedDiv(bossinfo.healthbar, BOSSHEALTHBARLEN);
|
||||
|
|
@ -1345,7 +1345,7 @@ void K_FillItemRouletteData(const player_t *player, itemroulette_t *const roulet
|
|||
return;
|
||||
}
|
||||
}
|
||||
else if (gametyperules & GTR_BOSS)
|
||||
else if (K_CheckBossIntro() == true)
|
||||
{
|
||||
for (i = 0; K_KartItemReelBoss[i] != KITEM_NONE; i++)
|
||||
{
|
||||
|
|
@ -1356,10 +1356,10 @@ void K_FillItemRouletteData(const player_t *player, itemroulette_t *const roulet
|
|||
}
|
||||
else if (K_TimeAttackRules() == true)
|
||||
{
|
||||
kartitems_t *presetlist = K_KartItemReelTimeAttack;
|
||||
kartitems_t *presetlist = K_KartItemReelRingSneaker;
|
||||
|
||||
// If the objective is not to go fast, it's to cause serious damage.
|
||||
if (gametyperules & GTR_PRISONS)
|
||||
if (battleprisons == true)
|
||||
{
|
||||
presetlist = K_KartItemReelBreakTheCapsules;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -291,7 +291,11 @@ void level_tally_t::Init(player_t *player)
|
|||
owner = player;
|
||||
gt = gametype;
|
||||
|
||||
const boolean game_over = ((player->pflags & PF_LOSTLIFE) == PF_LOSTLIFE);
|
||||
const boolean game_over = (
|
||||
G_GametypeUsesLives()
|
||||
? ((player->pflags & PF_LOSTLIFE) == PF_LOSTLIFE)
|
||||
: (tutorialchallenge == TUTORIALSKIP_INPROGRESS && K_IsPlayerLosing(player))
|
||||
);
|
||||
|
||||
time = std::min(static_cast<INT32>(player->realtime), (100 * 60 * TICRATE) - 1);
|
||||
ringPool = player->totalring;
|
||||
|
|
@ -384,7 +388,14 @@ void level_tally_t::Init(player_t *player)
|
|||
{
|
||||
if (game_over == true)
|
||||
{
|
||||
if (player->lives <= 0)
|
||||
if (tutorialchallenge == TUTORIALSKIP_INPROGRESS)
|
||||
{
|
||||
snprintf(
|
||||
header, sizeof header,
|
||||
"NICE TRY"
|
||||
);
|
||||
}
|
||||
else if (G_GametypeUsesLives() && player->lives <= 0)
|
||||
{
|
||||
snprintf(
|
||||
header, sizeof header,
|
||||
|
|
@ -991,7 +1002,7 @@ void level_tally_t::Draw(void)
|
|||
|| state == TALLY_ST_GAMEOVER_LIVES
|
||||
|| state == TALLY_ST_GAMEOVER_DONE)
|
||||
{
|
||||
if (owner->lives > 0)
|
||||
if (G_GametypeUsesLives() && owner->lives > 0)
|
||||
{
|
||||
srb2::Draw lives_drawer = drawer
|
||||
.xy(
|
||||
|
|
|
|||
|
|
@ -219,6 +219,9 @@ int LUA_PushGlobals(lua_State *L, const char *word)
|
|||
} else if (fastcmp(word,"podiummap")) {
|
||||
lua_pushstring(L, podiummap);
|
||||
return 1;
|
||||
} else if (fastcmp(word,"tutorialchallengemap")) {
|
||||
lua_pushstring(L, tutorialchallengemap);
|
||||
return 1;
|
||||
// end map vars
|
||||
// begin CTF colors
|
||||
} else if (fastcmp(word,"skincolor_redteam")) {
|
||||
|
|
|
|||
|
|
@ -661,6 +661,8 @@ void M_ClearStats(void)
|
|||
gamedata->evercrashed = false;
|
||||
gamedata->chaokeytutorial = false;
|
||||
gamedata->majorkeyskipattempted = false;
|
||||
gamedata->enteredtutorialchallenge = false;
|
||||
gamedata->finishedtutorialchallenge = false;
|
||||
gamedata->musicstate = GDMUSIC_NONE;
|
||||
|
||||
gamedata->importprofilewins = false;
|
||||
|
|
@ -1499,6 +1501,8 @@ boolean M_CheckCondition(condition_t *cn, player_t *player)
|
|||
return true;
|
||||
}
|
||||
return false;
|
||||
case UC_TUTORIALSKIP:
|
||||
return (gamedata->finishedtutorialchallenge == true);
|
||||
case UC_PASSWORD:
|
||||
return (cn->stringvar == NULL);
|
||||
|
||||
|
|
@ -2307,6 +2311,8 @@ static const char *M_GetConditionString(condition_t *cn)
|
|||
if (gamedata->evercrashed)
|
||||
return "launch \"Dr. Robotnik's Ring Racers\" again after a game crash";
|
||||
return NULL;
|
||||
case UC_TUTORIALSKIP:
|
||||
return "successfully skip the Tutorial";
|
||||
case UC_PASSWORD:
|
||||
return "enter a secret password";
|
||||
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ typedef enum
|
|||
UC_CREDITS, // Finish watching the credits
|
||||
UC_REPLAY, // Save a replay
|
||||
UC_CRASH, // Hee ho !
|
||||
UC_TUTORIALSKIP, // Complete the Tutorial Challenge
|
||||
|
||||
UC_PASSWORD, // Type in something funny
|
||||
|
||||
|
|
@ -363,6 +364,8 @@ struct gamedata_t
|
|||
boolean evercrashed;
|
||||
boolean chaokeytutorial;
|
||||
boolean majorkeyskipattempted;
|
||||
boolean enteredtutorialchallenge;
|
||||
boolean finishedtutorialchallenge;
|
||||
gdmusic_t musicstate;
|
||||
|
||||
// BACKWARDS COMPAT ASSIST
|
||||
|
|
|
|||
|
|
@ -90,18 +90,7 @@ void M_InitExtras(INT32 choice)
|
|||
|
||||
// Tutorial
|
||||
{
|
||||
levelsearch_t templevelsearch;
|
||||
UINT8 i = 0;
|
||||
INT16 map;
|
||||
|
||||
templevelsearch.cup = NULL;
|
||||
templevelsearch.typeoflevel = G_TOLFlag(GT_TUTORIAL);
|
||||
templevelsearch.cupmode = false;
|
||||
templevelsearch.timeattack = false;
|
||||
templevelsearch.tutorial = true;
|
||||
templevelsearch.checklocked = true;
|
||||
|
||||
map = M_GetFirstLevelInList(&i, &templevelsearch);
|
||||
UINT16 map = G_GetFirstMapOfGametype(GT_TUTORIAL);
|
||||
|
||||
EXTRAS_Main[extras_tutorial].status = (IT_STRING |
|
||||
((map == NEXTMAP_INVALID) ? IT_TRANSTEXT : IT_CALL));
|
||||
|
|
|
|||
|
|
@ -80,7 +80,11 @@ static void M_StatisticsMaps(void)
|
|||
headerexists = false;
|
||||
for (i = 0; i < nummapheaders; i++)
|
||||
{
|
||||
M_StatisticsAddMap(i, NULL, &headerexists, true);
|
||||
if (M_StatisticsAddMap(i, NULL, &headerexists, true))
|
||||
{
|
||||
if (!(mapheaderinfo[i]->records.mapvisited & MV_BEATEN))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((i = statisticsmenu.numextramedals) != 0)
|
||||
|
|
|
|||
|
|
@ -31,8 +31,10 @@ menuitem_t OPTIONS_Main[] =
|
|||
{IT_STRING | IT_SUBMENU, "Data Options", "Miscellaneous data options such as the screenshot format.",
|
||||
NULL, {.submenu = &OPTIONS_DataDef}, 0, 0},
|
||||
|
||||
#ifdef TODONEWMANUAL
|
||||
{IT_STRING | IT_CALL, "Tricks & Secrets", "Those who bother reading a game manual always get the edge over those who don't!",
|
||||
NULL, {.routine = M_Manual}, 0, 0},
|
||||
#endif
|
||||
};
|
||||
|
||||
// For options menu, the 'extra1' field will determine the background colour to use for... the background! (What a concept!)
|
||||
|
|
|
|||
|
|
@ -110,7 +110,6 @@ void M_MPSetupNetgameMapSelect(INT32 choice)
|
|||
levellist.netgame = true;
|
||||
// Make sure we reset those
|
||||
levellist.levelsearch.timeattack = false;
|
||||
levellist.levelsearch.tutorial = false;
|
||||
levellist.levelsearch.checklocked = true;
|
||||
cupgrid.grandprix = false;
|
||||
|
||||
|
|
|
|||
|
|
@ -125,9 +125,25 @@ UINT16 M_CountLevelsToShowInList(levelsearch_t *levelsearch)
|
|||
}
|
||||
|
||||
for (i = 0; i < nummapheaders; i++)
|
||||
{
|
||||
if (M_CanShowLevelInList(i, levelsearch))
|
||||
{
|
||||
count++;
|
||||
|
||||
// Tutorial will only show what you've made your way to
|
||||
if (!levelsearch->checklocked)
|
||||
continue;
|
||||
if (!levelsearch->tutorial)
|
||||
continue;
|
||||
if (i >= basenummapheaders)
|
||||
continue;
|
||||
if (mapheaderinfo[i]->records.mapvisited & MV_BEATEN)
|
||||
continue;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
|
@ -188,6 +204,13 @@ UINT16 M_GetNextLevelInList(UINT16 mapnum, UINT8 *i, levelsearch_t *levelsearch)
|
|||
}
|
||||
else
|
||||
{
|
||||
// Tutorial will only show what you've made your way to
|
||||
if (levelsearch->checklocked
|
||||
&& levelsearch->tutorial
|
||||
&& mapnum < basenummapheaders
|
||||
&& !(mapheaderinfo[mapnum]->records.mapvisited & MV_BEATEN))
|
||||
return NEXTMAP_INVALID;
|
||||
|
||||
mapnum++;
|
||||
while (!M_CanShowLevelInList(mapnum, levelsearch) && mapnum < nummapheaders)
|
||||
mapnum++;
|
||||
|
|
@ -215,6 +238,7 @@ boolean M_LevelListFromGametype(INT16 gt)
|
|||
{
|
||||
static boolean first = true;
|
||||
UINT8 temp = 0;
|
||||
boolean invalidatedcursor = false;
|
||||
|
||||
if (gt != -1)
|
||||
{
|
||||
|
|
@ -244,6 +268,15 @@ boolean M_LevelListFromGametype(INT16 gt)
|
|||
}
|
||||
|
||||
levellist.levelsearch.cupmode = (!(gametypes[gt]->rules & GTR_NOCUPSELECT));
|
||||
if (!levellist.levelsearch.cupmode)
|
||||
{
|
||||
invalidatedcursor = (
|
||||
levellist.levelsearch.cup != NULL
|
||||
|| levellist.levelsearch.tutorial != (gt == GT_TUTORIAL)
|
||||
);
|
||||
}
|
||||
|
||||
levellist.levelsearch.tutorial = (gt == GT_TUTORIAL);
|
||||
|
||||
CV_SetValue(&cv_dummyspbattack, 0);
|
||||
}
|
||||
|
|
@ -412,19 +445,36 @@ boolean M_LevelListFromGametype(INT16 gt)
|
|||
|
||||
// Okay, just a list of maps then.
|
||||
|
||||
if (M_GetFirstLevelInList(&temp, &levellist.levelsearch) == NEXTMAP_INVALID)
|
||||
levellist.levelsearch.cup = NULL;
|
||||
|
||||
UINT16 test = M_GetFirstLevelInList(&temp, &levellist.levelsearch);
|
||||
|
||||
if (test == NEXTMAP_INVALID)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Reset position properly if you go back & forth between gametypes
|
||||
if (levellist.levelsearch.cup)
|
||||
levellist.mapcount = M_CountLevelsToShowInList(&levellist.levelsearch);
|
||||
|
||||
if (levellist.levelsearch.tutorial && levellist.levelsearch.checklocked)
|
||||
{
|
||||
// Find the first level we haven't played.
|
||||
UINT16 possiblecursor = 0;
|
||||
while (test < nummapheaders && (mapheaderinfo[test]->records.mapvisited & MV_BEATEN))
|
||||
{
|
||||
test = M_GetNextLevelInList(test, &temp, &levellist.levelsearch);
|
||||
possiblecursor++;
|
||||
}
|
||||
|
||||
if (test != NEXTMAP_INVALID)
|
||||
levellist.cursor = possiblecursor;
|
||||
}
|
||||
else if (invalidatedcursor)
|
||||
{
|
||||
levellist.cursor = 0;
|
||||
levellist.levelsearch.cup = NULL;
|
||||
}
|
||||
|
||||
levellist.mapcount = M_CountLevelsToShowInList(&levellist.levelsearch);
|
||||
M_LevelSelectScrollDest();
|
||||
levellist.y = levellist.dest;
|
||||
|
||||
|
|
@ -450,7 +500,6 @@ void M_LevelSelectInit(INT32 choice)
|
|||
// Make sure this is reset as we'll only be using this function for offline games!
|
||||
levellist.netgame = false;
|
||||
levellist.levelsearch.checklocked = true;
|
||||
levellist.levelsearch.tutorial = (gt == GT_TUTORIAL);
|
||||
|
||||
switch (currentMenu->menuitems[itemOn].mvar1)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ void M_HandleImageDef(INT32 choice)
|
|||
}
|
||||
|
||||
// Opening manual
|
||||
#ifdef TODONEWMANUAL
|
||||
void M_Manual(INT32 choice)
|
||||
{
|
||||
(void)choice;
|
||||
|
|
@ -71,3 +72,4 @@ void M_Manual(INT32 choice)
|
|||
MISC_ManualDef.prevMenu = (choice == INT32_MAX ? NULL : currentMenu);
|
||||
M_SetupNextMenu(&MISC_ManualDef, true);
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -40,6 +40,9 @@ menuitem_t PAUSE_Main[] =
|
|||
{IT_STRING | IT_ARROWS, "CALL VOTE", "M_ICOVOT",
|
||||
NULL, {.routine = M_HandlePauseMenuCallVote}, 0, 0},
|
||||
|
||||
{IT_STRING | IT_CALL, "GIVE UP", "M_ICOGUP",
|
||||
NULL, {.routine = M_GiveUp}, 0, 0},
|
||||
|
||||
{IT_STRING | IT_CALL, "RESTART MAP", "M_ICORE",
|
||||
NULL, {.routine = M_RestartMap}, 0, 0},
|
||||
|
||||
|
|
@ -130,6 +133,8 @@ void M_OpenPauseMenu(void)
|
|||
#ifdef HAVE_DISCORDRPC
|
||||
PAUSE_Main[mpause_discordrequests].status = IT_DISABLED;
|
||||
#endif
|
||||
|
||||
PAUSE_Main[mpause_giveup].status = IT_DISABLED;
|
||||
PAUSE_Main[mpause_restartmap].status = IT_DISABLED;
|
||||
PAUSE_Main[mpause_tryagain].status = IT_DISABLED;
|
||||
|
||||
|
|
@ -172,19 +177,33 @@ void M_OpenPauseMenu(void)
|
|||
}
|
||||
else if (!netgame && !demo.playback)
|
||||
{
|
||||
boolean retryallowed = (modeattacking != ATTACKING_NONE || gametype == GT_TUTORIAL);
|
||||
if (
|
||||
retryallowed == false
|
||||
&& gamestate == GS_LEVEL
|
||||
&& G_GametypeUsesLives()
|
||||
)
|
||||
boolean retryallowed = (modeattacking != ATTACKING_NONE);
|
||||
boolean giveup = (
|
||||
grandprixinfo.gp == true
|
||||
&& grandprixinfo.eventmode != GPEVENT_NONE
|
||||
&& roundqueue.size != 0
|
||||
);
|
||||
|
||||
if (tutorialchallenge == TUTORIALSKIP_INPROGRESS)
|
||||
{
|
||||
for (i = 0; i <= splitscreen; i++)
|
||||
// NO RETRY, ONLY GIVE UP
|
||||
giveup = true;
|
||||
}
|
||||
else if (gamestate == GS_LEVEL && !retryallowed)
|
||||
{
|
||||
if (gametype == GT_TUTORIAL)
|
||||
{
|
||||
if (players[g_localplayers[i]].lives <= 1)
|
||||
continue;
|
||||
retryallowed = true;
|
||||
break;
|
||||
}
|
||||
else if (G_GametypeUsesLives())
|
||||
{
|
||||
for (i = 0; i <= splitscreen; i++)
|
||||
{
|
||||
if (players[g_localplayers[i]].lives <= 1)
|
||||
continue;
|
||||
retryallowed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -192,6 +211,11 @@ void M_OpenPauseMenu(void)
|
|||
{
|
||||
PAUSE_Main[mpause_tryagain].status = IT_STRING | IT_CALL;
|
||||
}
|
||||
|
||||
if (giveup)
|
||||
{
|
||||
PAUSE_Main[mpause_giveup].status = IT_STRING | IT_CALL;
|
||||
}
|
||||
}
|
||||
|
||||
if (netgame) // && (PAUSE_Main[mpause_admin].status == IT_DISABLED))
|
||||
|
|
@ -398,6 +422,35 @@ void M_TryAgain(INT32 choice)
|
|||
}
|
||||
}
|
||||
|
||||
static void M_GiveUpResponse(INT32 ch)
|
||||
{
|
||||
if (ch != MA_YES)
|
||||
return;
|
||||
|
||||
if (exitcountdown != 1)
|
||||
{
|
||||
G_BeginLevelExit();
|
||||
exitcountdown = 1;
|
||||
|
||||
if (server)
|
||||
SendNetXCmd(XD_EXITLEVEL, NULL, 0);
|
||||
}
|
||||
|
||||
M_ClearMenus(false);
|
||||
}
|
||||
|
||||
void M_GiveUp(INT32 choice)
|
||||
{
|
||||
(void)choice;
|
||||
if (demo.playback)
|
||||
return;
|
||||
|
||||
if (!Playing())
|
||||
return;
|
||||
|
||||
M_StartMessage("Give up", M_GetText("Are you sure you want to\ngive up on this challenge?\n"), &M_GiveUpResponse, MM_YESNO, NULL, NULL);
|
||||
}
|
||||
|
||||
// Pause spectate / join functions
|
||||
void M_ConfirmSpectate(INT32 choice)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1913,7 +1913,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
|
|||
// spectating. Because in Free Play, this player
|
||||
// can enter the game again, and these flags would
|
||||
// make them intangible.
|
||||
if (K_Cooperative() && !target->player->spectator)
|
||||
if (!(gametyperules & GTR_CHECKPOINTS) && K_Cooperative() && !target->player->spectator)
|
||||
{
|
||||
target->player->pflags |= PF_ELIMINATED;
|
||||
|
||||
|
|
@ -2570,7 +2570,7 @@ static boolean P_KillPlayer(player_t *player, mobj_t *inflictor, mobj_t *source,
|
|||
player->roundconditions.checkthisframe = true;
|
||||
}
|
||||
|
||||
if (gametyperules & GTR_BUMPERS)
|
||||
if (gametyperules & (GTR_BUMPERS|GTR_CHECKPOINTS))
|
||||
{
|
||||
player->mo->health--;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,6 +80,7 @@ extern thinker_t thlist[];
|
|||
extern mobj_t *mobjcache;
|
||||
|
||||
void P_InitThinkers(void);
|
||||
void P_InvalidateThinkersWithoutInit(void);
|
||||
void P_AddThinker(const thinklistnum_t n, thinker_t *thinker);
|
||||
void P_RemoveThinker(thinker_t *thinker);
|
||||
void P_UnlinkThinker(thinker_t *thinker);
|
||||
|
|
|
|||
10
src/p_mobj.c
10
src/p_mobj.c
|
|
@ -12812,7 +12812,7 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing)
|
|||
else if (mobj->z == mobj->floorz)
|
||||
mobj->eflags |= MFE_ONGROUND;
|
||||
|
||||
mobj->angle = angle;
|
||||
mobj->angle = p->drawangle = angle;
|
||||
|
||||
// FAULT
|
||||
if (gamestate == GS_LEVEL && leveltime > introtime && !p->spectator)
|
||||
|
|
@ -12827,6 +12827,7 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing)
|
|||
p->respawn.pointx = x;
|
||||
p->respawn.pointy = y;
|
||||
p->respawn.pointz = z;
|
||||
p->respawn.pointangle = angle;
|
||||
}
|
||||
|
||||
P_AfterPlayerSpawn(playernum);
|
||||
|
|
@ -12881,7 +12882,7 @@ void P_MovePlayerToCheatcheck(INT32 playernum)
|
|||
}
|
||||
}
|
||||
else
|
||||
p->drawangle = mobj->angle; // default to the camera angle
|
||||
p->drawangle = mobj->angle = p->respawn.pointangle;
|
||||
|
||||
K_DoIngameRespawn(p);
|
||||
p->respawn.truedeath = true;
|
||||
|
|
@ -13055,6 +13056,9 @@ static boolean P_SetupEmblem(mapthing_t *mthing, mobj_t *mobj)
|
|||
skincolornum_t emcolor;
|
||||
INT16 tagnum = mthing->tid;
|
||||
|
||||
if (tutorialchallenge == TUTORIALSKIP_INPROGRESS)
|
||||
return false; // No out-of-sequence goodies
|
||||
|
||||
while (emblem)
|
||||
{
|
||||
if (emblem->type == ET_GLOBAL && emblem->tag == tagnum)
|
||||
|
|
@ -13622,7 +13626,7 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj)
|
|||
}
|
||||
case MT_SPRAYCAN:
|
||||
{
|
||||
if (nummapspraycans == UINT8_MAX)
|
||||
if (nummapspraycans == UINT8_MAX || tutorialchallenge == TUTORIALSKIP_INPROGRESS)
|
||||
{
|
||||
P_RemoveMobj(mobj);
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -7609,7 +7609,10 @@ static void P_InitLevelSettings(void)
|
|||
gamespeed = grandprixinfo.gamespeed;
|
||||
}
|
||||
}
|
||||
else if (modeattacking)
|
||||
else if (
|
||||
modeattacking != ATTACKING_NONE
|
||||
|| tutorialchallenge == TUTORIALSKIP_INPROGRESS
|
||||
)
|
||||
{
|
||||
if (gametyperules & GTR_CIRCUIT)
|
||||
{
|
||||
|
|
@ -8286,7 +8289,14 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
|
|||
}
|
||||
}
|
||||
|
||||
if (K_PodiumHasEmerald())
|
||||
// Default
|
||||
levelfadecol = 31;
|
||||
|
||||
if (gamestate == GS_TITLESCREEN)
|
||||
{
|
||||
;
|
||||
}
|
||||
else if (K_PodiumHasEmerald())
|
||||
{
|
||||
// Special Stage out
|
||||
if (ranspecialwipe != 2)
|
||||
|
|
@ -8316,11 +8326,6 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
|
|||
levelfadecol = 0;
|
||||
wipetype = wipe_encore_towhite;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Default
|
||||
levelfadecol = 31;
|
||||
}
|
||||
|
||||
if (rendermode != render_none)
|
||||
{
|
||||
|
|
@ -8343,6 +8348,8 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
|
|||
|
||||
K_UnsetDialogue();
|
||||
|
||||
ACS_InvalidateMapScope();
|
||||
|
||||
LUA_InvalidateLevel();
|
||||
|
||||
for (ss = sectors; sectors+numsectors != ss; ss++)
|
||||
|
|
|
|||
|
|
@ -4132,14 +4132,17 @@ boolean P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, cha
|
|||
}
|
||||
else
|
||||
{
|
||||
// args[2]: cap rings to -20 instead of 0
|
||||
SINT8 baseline = (args[2] ? -20 : 0);
|
||||
|
||||
// Don't push you below baseline
|
||||
if (mo->player->rings <= 0)
|
||||
if (mo->player->rings <= baseline)
|
||||
return false;
|
||||
|
||||
rings = -(rings);
|
||||
|
||||
if (rings > mo->player->rings)
|
||||
rings = mo->player->rings;
|
||||
if (rings > (mo->player->rings - baseline))
|
||||
rings = (mo->player->rings - baseline);
|
||||
|
||||
mo->player->rings -= rings;
|
||||
S_StartSound(mo, sfx_antiri);
|
||||
|
|
|
|||
40
src/p_tick.c
40
src/p_tick.c
|
|
@ -55,6 +55,8 @@
|
|||
tic_t leveltime;
|
||||
boolean thinkersCompleted;
|
||||
|
||||
UINT32 thinker_era = 0;
|
||||
|
||||
static boolean g_freezeCheat;
|
||||
static boolean g_freezeLevel;
|
||||
|
||||
|
|
@ -278,6 +280,8 @@ void P_InitThinkers(void)
|
|||
{
|
||||
UINT8 i;
|
||||
|
||||
P_InvalidateThinkersWithoutInit();
|
||||
|
||||
for (i = 0; i < NUM_THINKERLISTS; i++)
|
||||
{
|
||||
thlist[i].prev = thlist[i].next = &thlist[i];
|
||||
|
|
@ -299,6 +303,15 @@ void P_InitThinkers(void)
|
|||
Obj_ResetCheckpoints();
|
||||
}
|
||||
|
||||
//
|
||||
// P_InvalidateThinkersWithoutInit
|
||||
//
|
||||
|
||||
void P_InvalidateThinkersWithoutInit(void)
|
||||
{
|
||||
thinker_era++;
|
||||
}
|
||||
|
||||
// Adds a new thinker at the end of the list.
|
||||
void P_AddThinker(const thinklistnum_t n, thinker_t *thinker)
|
||||
{
|
||||
|
|
@ -855,15 +868,22 @@ void P_Ticker(boolean run)
|
|||
|
||||
ps_playerthink_time = I_GetPreciseTime() - ps_playerthink_time;
|
||||
|
||||
// TODO would this be laggy with more conditions in play...
|
||||
if (((!demo.playback && leveltime > introtime && M_UpdateUnlockablesAndExtraEmblems(true, false))
|
||||
|| (gamedata && gamedata->deferredsave)))
|
||||
G_SaveGameData();
|
||||
}
|
||||
if (gamedata && gamestate == GS_LEVEL && !demo.playback)
|
||||
{
|
||||
// Keep track of how long they've been playing!
|
||||
gamedata->totalplaytime++;
|
||||
|
||||
// Keep track of how long they've been playing!
|
||||
if (!demo.playback) // Don't increment if a demo is playing.
|
||||
gamedata->totalplaytime++;
|
||||
// TODO would this be laggy with more conditions in play...
|
||||
if (
|
||||
(leveltime > introtime
|
||||
&& M_UpdateUnlockablesAndExtraEmblems(true, false))
|
||||
|| gamedata->deferredsave
|
||||
)
|
||||
{
|
||||
G_SaveGameData();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (run)
|
||||
{
|
||||
|
|
@ -1049,7 +1069,7 @@ void P_Ticker(boolean run)
|
|||
}
|
||||
|
||||
player_t *player = &players[i];
|
||||
if (K_PlayerTallyActive(player) == true && player->tally.done == false)
|
||||
if (player->spectator == false && K_PlayerTallyActive(player) == true && player->tally.done == false)
|
||||
{
|
||||
run_exit_countdown = false;
|
||||
break;
|
||||
|
|
@ -1153,7 +1173,7 @@ void P_Ticker(boolean run)
|
|||
P_RunChaseCameras();
|
||||
}
|
||||
|
||||
if (run)
|
||||
if (run && !levelloading && leveltime)
|
||||
{
|
||||
K_TickDialogue();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,6 +43,8 @@ void P_PreTicker(INT32 frames);
|
|||
void P_DoTeamscrambling(void);
|
||||
void P_RemoveThinkerDelayed(thinker_t *thinker); //killed
|
||||
|
||||
extern UINT32 thinker_era;
|
||||
|
||||
mobj_t *P_SetTarget2(mobj_t **mo, mobj_t *target
|
||||
#ifdef PARANOIA
|
||||
, const char *source_file, int source_line
|
||||
|
|
|
|||
|
|
@ -2824,7 +2824,7 @@ static void P_DeathThink(player_t *player)
|
|||
}
|
||||
}
|
||||
|
||||
if ((player->pflags & PF_ELIMINATED) && (gametyperules & GTR_BUMPERS))
|
||||
if ((player->pflags & PF_ELIMINATED) /*&& (gametyperules & GTR_BUMPERS)*/)
|
||||
{
|
||||
playerGone = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1250,8 +1250,6 @@ static void ST_overlayDrawer(void)
|
|||
}
|
||||
|
||||
K_DrawMidVote();
|
||||
|
||||
K_DrawDialogue();
|
||||
}
|
||||
|
||||
void ST_DrawDemoTitleEntry(void)
|
||||
|
|
@ -1558,6 +1556,8 @@ void ST_Drawer(void)
|
|||
if (stagetitle)
|
||||
ST_drawTitleCard();
|
||||
|
||||
K_DrawDialogue();
|
||||
|
||||
// Replay manual-save stuff
|
||||
if (demo.recording && multiplayer && demo.savebutton && demo.savebutton + 3*TICRATE < leveltime)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1905,7 +1905,9 @@ void Y_DetermineIntermissionType(void)
|
|||
// or for failing in time attack mode
|
||||
|| (modeattacking && (players[consoleplayer].pflags & PF_NOCONTEST))
|
||||
// or for explicit requested skip (outside of modeattacking)
|
||||
|| (modeattacking == ATTACKING_NONE && skipstats != 0))
|
||||
|| (modeattacking == ATTACKING_NONE && skipstats != 0)
|
||||
// or tutorial skip material
|
||||
|| (nextmapoverride == NEXTMAP_TUTORIALCHALLENGE+1 || tutorialchallenge != TUTORIALSKIP_NONE))
|
||||
{
|
||||
intertype = int_none;
|
||||
return;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue