Refactoring ahoy

* Instead of doing constant G_MapNumbers when finding the relationship between maps and cups...
    * Add a cache of level IDs to cups, to go with the strings.
    * Add a cache of the cup pointer to maps, so we don't have to search through all cups to find our map. (done in P_InitMapData)
    * Pre-emptive work: G_IsSpecialStage and P_GetNextEmerald now reference cup data instead of a hardcoded ID set.
* Remove a bunch of old stuff from mapheaderinfo_t/associated, and reorder what stays
    * Countdowntimer? 💥
    * Startrings? 💥
    * sstimer/ssspheres? 💥
    * forcecharacter? 💥 (distinct from forceskin)
    * interscreen? 💥
    * sstage_start/end and smpstage_start/end? 💥💥💥💥
    * You've been blocked
* G_MapNumber now returns a special NEXTMAP_INVALID if not found, for more consistent reference.
* Incorporate a good chunk of the `edit-headers` branch. Can't clear maps individually because of the new restrictions on sequential mapheaders, but we can add a "disable in vote screen, not even for map hell/archive" flag to a map at some future juncture for equivalent functionality...
This commit is contained in:
toaster 2022-09-22 17:14:41 +01:00
parent 077b23929b
commit 48e9138dda
15 changed files with 168 additions and 289 deletions

View file

@ -1394,7 +1394,7 @@ UINT8 CanChangeSkin(INT32 playernum)
return true;
// Force skin in effect.
if ((cv_forceskin.value != -1) || (mapheaderinfo[gamemap-1] && mapheaderinfo[gamemap-1]->forcecharacter[0] != '\0'))
if (cv_forceskin.value != -1)
return false;
// Can change skin in intermission and whatnot.

View file

@ -158,6 +158,8 @@ void clear_levels(void)
P_DeleteFlickies(nummapheaders);
Z_Free(mapheaderinfo[nummapheaders]->mainrecord);
Patch_Free(mapheaderinfo[nummapheaders]->thumbnailPic);
Patch_Free(mapheaderinfo[nummapheaders]->minimapPic);
@ -167,7 +169,22 @@ void clear_levels(void)
mapheaderinfo[nummapheaders] = NULL;
}
// Realloc the one for the current gamemap as a safeguard
// Clear out the cache
{
cupheader_t *cup = kartcupheaders;
UINT8 i;
while (cup)
{
for (i = 0; i < CUPCACHE_MAX; i++)
{
cup->cachedlevels[i] = NEXTMAP_INVALID;
}
cup = cup->next;
}
}
// Exit the current gamemap as a safeguard
if (Playing())
COM_BufAddText("exitgame"); // Command_ExitGame_f() but delayed
}
@ -1093,17 +1110,18 @@ void readlevelheader(MYFILE *f, char * name)
char *tmp;
INT32 i;
const INT32 num = G_MapNumber(name);
INT32 num = G_MapNumber(name);
if (f->wad > mainwads && num < nummapheaders)
if (num >= nummapheaders)
{
P_AllocMapHeader((INT16)(num = nummapheaders));
}
else if (f->wad > mainwads)
{
// only mark as a major mod if it replaces an already-existing mapheaderinfo
G_SetGameModified(multiplayer, true);
}
// Reset all previous map header information
P_AllocMapHeader((INT16)(num));
if (mapheaderinfo[num]->lumpname == NULL)
{
mapheaderinfo[num]->lumpname = Z_StrDup(name);
@ -1336,11 +1354,6 @@ void readlevelheader(MYFILE *f, char * name)
mapheaderinfo[num]->mustrack = ((UINT16)i - 1);
else if (fastcmp(word, "MUSICPOS"))
mapheaderinfo[num]->muspos = (UINT32)get_number(word2);
else if (fastcmp(word, "FORCECHARACTER"))
{
strlcpy(mapheaderinfo[num]->forcecharacter, word2, SKINNAMESIZE+1);
strlwr(mapheaderinfo[num]->forcecharacter); // skin names are lowercase
}
else if (fastcmp(word, "WEATHER"))
mapheaderinfo[num]->weather = get_precip(word2);
else if (fastcmp(word, "SKYTEXTURE"))
@ -2860,24 +2873,6 @@ void readmaincfg(MYFILE *f)
if (maptmp <= nummapheaders)
spmarathon_start = maptmp;
}
else if (fastcmp(word, "SSTAGE_START"))
{
INT16 maptmp = G_MapNumber(word2)+1;
if (maptmp <= nummapheaders)
{
sstage_start = maptmp;
sstage_end = (sstage_start+13); // 14 special stages
}
}
else if (fastcmp(word, "SMPSTAGE_START"))
{
INT16 maptmp = G_MapNumber(word2)+1;
if (maptmp <= nummapheaders)
{
smpstage_start = maptmp;
smpstage_end = (smpstage_start+13); // 14 special stages
}
}
else if (fastcmp(word, "REDTEAM"))
{
skincolor_redteam = (UINT16)get_number(word2);
@ -3323,16 +3318,17 @@ void readcupheader(MYFILE *f, cupheader_t *cup)
}
cup->levellist[cup->numlevels] = Z_StrDup(tmp);
cup->cachedlevels[cup->numlevels] = NEXTMAP_INVALID;
cup->numlevels++;
} while((tmp = strtok(NULL,",")) != NULL);
}
else if (fastcmp(word, "BONUSGAME"))
{
cup->bonusgame = Z_StrDup(word2);
cup->levellist[CUPCACHE_BONUS] = Z_StrDup(word2);
}
else if (fastcmp(word, "SPECIALSTAGE"))
{
cup->specialstage = Z_StrDup(word2);
cup->levellist[CUPCACHE_SPECIAL] = Z_StrDup(word2);
}
else if (fastcmp(word, "EMERALDNUM"))
{

View file

@ -207,7 +207,6 @@ extern boolean splitscreen_partied[MAXPLAYERS];
// Maps of special importance
extern INT16 spstage_start, spmarathon_start;
extern INT16 sstage_start, sstage_end, smpstage_start, smpstage_end;
extern char * titlemap;
extern boolean hidetitlepics;
@ -221,8 +220,6 @@ extern boolean looptitle;
// CTF colors.
extern UINT16 skincolor_redteam, skincolor_blueteam, skincolor_redring, skincolor_bluering;
extern tic_t countdowntimer;
extern boolean countdowntimeup;
extern boolean exitfadestarted;
typedef struct
@ -313,8 +310,6 @@ extern textprompt_t *textprompts[MAX_PROMPTS];
extern INT16 nextmapoverride;
extern UINT8 skipstats;
extern UINT32 ssspheres; // Total # of spheres in a level
// Fun extra stuff
extern INT16 lastmap; // Last level you were at (returning from special stages).
extern mobj_t *redflag, *blueflag; // Pointers to physical flags
@ -340,91 +335,108 @@ extern struct quake
} quake;
// Custom Lua values
// (This is not ifdeffed so the map header structure can stay identical, just in case.)
typedef struct
{
char option[32]; // 31 usable characters
char value[256]; // 255 usable characters. If this seriously isn't enough then wtf.
} customoption_t;
// This could support more, but is that a good idea?
// Keep in mind that it may encourage people making overly long cups just because they "can", and would be a waste of memory.
#define MAXLEVELLIST 5
#define CUPCACHE_BONUS MAXLEVELLIST
#define CUPCACHE_SPECIAL MAXLEVELLIST+1
#define CUPCACHE_MAX CUPCACHE_SPECIAL+1
typedef struct cupheader_s
{
UINT16 id; ///< Cup ID
char name[15]; ///< Cup title (14 chars)
char icon[9]; ///< Name of the icon patch
char *levellist[CUPCACHE_MAX]; ///< List of levels that belong to this cup
INT16 cachedlevels[CUPCACHE_MAX]; ///< IDs in levellist, bonusgame, and specialstage
UINT8 numlevels; ///< Number of levels defined in levellist
UINT8 emeraldnum; ///< ID of Emerald to use for special stage (1-7 for Chaos Emeralds, 8-14 for Super Emeralds, 0 for no emerald)
SINT8 unlockrequired; ///< An unlockable is required to select this cup. -1 for no unlocking required.
struct cupheader_s *next; ///< Next cup in linked list
} cupheader_t;
extern cupheader_t *kartcupheaders; // Start of cup linked list
extern UINT16 numkartcupheaders;
/** Map header information.
*/
typedef struct
{
char * lumpname; ///< Lump name can be really long
lumpnum_t lumpnum; ///< Lump number for the map, used by vres_GetMap
// Core game information, not user-modifiable directly
char *lumpname; ///< Lump name can be really long
lumpnum_t lumpnum; ///< Lump number for the map, used by vres_GetMap
void * thumbnailPic; ///< Lump data for the level select thumbnail.
void * minimapPic; ///< Lump data for the minimap graphic.
void * encoreLump; ///< Lump data for the Encore Mode remap.
void * tweakLump; ///< Lump data for the palette tweak remap.
void *thumbnailPic; ///< Lump data for the level select thumbnail.
void *minimapPic; ///< Lump data for the minimap graphic.
void *encoreLump; ///< Lump data for the Encore Mode remap.
void *tweakLump; ///< Lump data for the palette tweak remap.
UINT8 mapvisited; ///< A set of flags that says what we've done in the map.
recorddata_t *mainrecord; ///< Stores best time attack data
cupheader_t *cup; ///< Cached cup
// Titlecard information
char lvlttl[22]; ///< Level name without "Zone". (21 character limit instead of 32, 21 characters can display on screen max anyway)
char subttl[33]; ///< Subtitle for level
char zonttl[22]; ///< "ZONE" replacement name
UINT8 actnum; ///< Act number or 0 for none.
UINT32 typeoflevel; ///< Combination of typeoflevel flags.
// Selection metadata
char keywords[33]; ///< Keywords separated by space to search for. 32 characters.
SINT8 unlockrequired; ///< Is an unlockable required to play this level? -1 if no.
UINT8 levelselect; ///< Is this map available in the level select? If so, which map list is it available in?
UINT16 menuflags; ///< LF2_flags: options that affect record attack menus
// Operational metadata
UINT16 levelflags; ///< LF_flags: merged booleans into one UINT16 for space, see below
UINT32 typeoflevel; ///< Combination of typeoflevel flags.
UINT8 numlaps; ///< Number of laps in circuit mode, unless overridden.
fixed_t gravity; ///< Map-wide gravity.
// Music information
char musname[7]; ///< Music track to play. "" for no music.
UINT16 mustrack; ///< Subsong to play. Only really relevant for music modules and specific formats supported by GME. 0 to ignore.
UINT32 muspos; ///< Music position to jump to.
char forcecharacter[17]; ///< (SKINNAMESIZE+1) Skin to switch to or "" to disable.
UINT8 weather; ///< 0 = sunny day, 1 = storm, 2 = snow, 3 = rain, 4 = blank, 5 = thunder w/o rain, 6 = rain w/o lightning, 7 = heat wave.
// Sky information
UINT8 weather; ///< See preciptype_t
char skytexture[9]; ///< Sky texture to use.
INT16 skybox_scalex; ///< Skybox X axis scale. (0 = no movement, 1 = 1:1 movement, 16 = 16:1 slow movement, -4 = 1:4 fast movement, etc.)
INT16 skybox_scaley; ///< Skybox Y axis scale.
INT16 skybox_scalez; ///< Skybox Z axis scale.
// Extra information.
char interscreen[8]; ///< 320x200 patch to display at intermission.
char runsoc[33]; ///< SOC to execute at start of level (32 character limit instead of 63)
char scriptname[33]; ///< Script to use when the map is switched to. (32 character limit instead of 191)
UINT8 precutscenenum; ///< Cutscene number to play BEFORE a level starts.
UINT8 cutscenenum; ///< Cutscene number to use, 0 for none.
INT16 countdown; ///< Countdown until level end?
// Distance information
fixed_t mobj_scale; ///< Defines the size all object calculations are relative to
fixed_t default_waypoint_radius; ///< 0 is a special value for DEFAULT_WAYPOINT_RADIUS, but scaled with mobjscale
// Visual information
UINT16 palette; ///< PAL lump to use on this map
UINT16 encorepal; ///< PAL for encore mode
UINT8 light_contrast; ///< Range of wall lighting. 0 is no lighting.
boolean use_light_angle; ///< When false, wall lighting is evenly distributed. When true, wall lighting is directional.
angle_t light_angle; ///< Angle of directional wall lighting.
UINT8 numlaps; ///< Number of laps in circuit mode, unless overridden.
SINT8 unlockrequired; ///< Is an unlockable required to play this level? -1 if no.
UINT8 levelselect; ///< Is this map available in the level select? If so, which map list is it available in?
UINT16 levelflags; ///< LF_flags: merged booleans into one UINT16 for space, see below
UINT16 menuflags; ///< LF2_flags: options that affect record attack / nights mode menus
UINT16 startrings; ///< Number of rings players start with.
INT32 sstimer; ///< Timer for special stages.
UINT32 ssspheres; ///< Sphere requirement in special stages.
fixed_t gravity; ///< Map-wide gravity.
// Freed animals stuff.
// Freed animal information
UINT8 numFlickies; ///< Internal. For freed flicky support.
mobjtype_t *flickies; ///< List of freeable flickies in this level. Allocated dynamically for space reasons. Be careful.
UINT8 light_contrast; ///< Range of wall lighting. 0 is no lighting.
boolean use_light_angle; ///< When false, wall lighting is evenly distributed. When true, wall lighting is directional.
angle_t light_angle; ///< Angle of directional wall lighting.
// Script information
char runsoc[33]; ///< SOC to execute at start of level (32 character limit instead of 63)
char scriptname[33]; ///< Script to use when the map is switched to. (32 character limit instead of 191)
// SRB2kart
fixed_t mobj_scale; ///< Replacement for TOL_ERZ3
fixed_t default_waypoint_radius; ///< 0 is a special value for DEFAULT_WAYPOINT_RADIUS, but scaled with mobjscale
// Cutscene information
UINT8 precutscenenum; ///< Cutscene number to play BEFORE a level starts.
UINT8 cutscenenum; ///< Cutscene number to use, 0 for none.
// Record data (modified liberally, saved to gamedata)
UINT8 mapvisited; ///< A set of flags that says what we've done in the map.
recorddata_t *mainrecord; ///< Stores best time attack data
// Lua stuff.
// (This is not ifdeffed so the map header structure can stay identical, just in case.)
// Lua information
UINT8 numCustomOptions; ///< Internal. For Lua custom value support.
customoption_t *customopts; ///< Custom options. Allocated dynamically for space reasons. Be careful.
} mapheader_t;
@ -443,27 +455,6 @@ typedef struct
extern mapheader_t** mapheaderinfo;
extern INT32 nummapheaders, mapallocsize;
// This could support more, but is that a good idea?
// Keep in mind that it may encourage people making overly long cups just because they "can", and would be a waste of memory.
#define MAXLEVELLIST 5
typedef struct cupheader_s
{
UINT16 id; ///< Cup ID
char name[15]; ///< Cup title (14 chars)
char icon[9]; ///< Name of the icon patch
char *levellist[MAXLEVELLIST]; ///< List of levels that belong to this cup
UINT8 numlevels; ///< Number of levels defined in levellist
char *bonusgame; ///< Map name to use for bonus game
char *specialstage; ///< Map name to use for special stage
UINT8 emeraldnum; ///< ID of Emerald to use for special stage (1-7 for Chaos Emeralds, 8-14 for Super Emeralds, 0 for no emerald)
SINT8 unlockrequired; ///< An unlockable is required to select this cup. -1 for no unlocking required.
struct cupheader_s *next; ///< Next cup in linked list
} cupheader_t;
extern cupheader_t *kartcupheaders; // Start of cup linked list
extern UINT16 numkartcupheaders;
// Gametypes
#define NUMGAMETYPEFREESLOTS 128
@ -588,7 +579,6 @@ extern UINT32 token; ///< Number of tokens collected in a level
extern UINT32 tokenlist; ///< List of tokens collected
extern boolean gottoken; ///< Did you get a token? Used for end of act
extern INT32 tokenbits; ///< Used for setting token bits
extern INT32 sstimer; ///< Time allotted in the special stage
extern UINT32 bluescore; ///< Blue Team Scores
extern UINT32 redscore; ///< Red Team Scores

View file

@ -151,12 +151,10 @@ INT32 g_localplayers[MAXSPLITSCREENPLAYERS];
tic_t gametic;
tic_t levelstarttic; // gametic at level start
UINT32 ssspheres; // old special stage
INT16 lastmap; // last level you were at (returning from special stages)
tic_t timeinmap; // Ticker for time spent in level (used for levelcard display)
INT16 spstage_start, spmarathon_start;
INT16 sstage_start, sstage_end, smpstage_start, smpstage_end;
char * titlemap = NULL;
boolean hidetitlepics = false;
@ -172,8 +170,6 @@ UINT16 skincolor_blueteam = SKINCOLOR_BLUE;
UINT16 skincolor_redring = SKINCOLOR_RASPBERRY;
UINT16 skincolor_bluering = SKINCOLOR_PERIWINKLE;
tic_t countdowntimer = 0;
boolean countdowntimeup = false;
boolean exitfadestarted = false;
cutscene_t *cutscenes[128];
@ -212,9 +208,6 @@ UINT32 tokenlist; // List of tokens collected
boolean gottoken; // Did you get a token? Used for end of act
INT32 tokenbits; // Used for setting token bits
// Old Special Stage
INT32 sstimer; // Time allotted in the special stage
tic_t totalplaytime;
UINT32 matchesplayed; // SRB2Kart
boolean gamedataloaded = false;
@ -673,13 +666,13 @@ INT32 G_MapNumber(const char * name)
for (map = 0; map < nummapheaders; ++map)
{
if (strcasecmp(mapheaderinfo[map]->lumpname, name) == 0)
{
break;
}
if (strcasecmp(mapheaderinfo[map]->lumpname, name) != 0)
continue;
return map;
}
return map;
return NEXTMAP_INVALID;
}
#ifdef NEXTMAPINSOC
@ -3201,18 +3194,15 @@ INT32 G_GetGametypeByName(const char *gametypestr)
//
boolean G_IsSpecialStage(INT32 mapnum)
{
#if 1
(void)mapnum;
#else
if (modeattacking == ATTACKING_TIME)
return false;
if (mapnum >= sstage_start && mapnum <= sstage_end)
return true;
if (mapnum >= smpstage_start && mapnum <= smpstage_end)
return true;
#endif
mapnum--; // gamemap-based to 0 indexed
return false;
if (mapnum > nummapheaders || !mapheaderinfo[mapnum])
return false;
if (!mapheaderinfo[mapnum]->cup || mapheaderinfo[mapnum]->cup->cachedlevels[CUPCACHE_SPECIAL] != mapnum)
return false;
return true;
}
//
@ -3386,11 +3376,11 @@ UINT32 G_TOLFlag(INT32 pgametype)
INT16 G_GetFirstMapOfGametype(UINT8 pgametype)
{
INT16 mapnum = nummapheaders;
INT16 mapnum = NEXTMAP_INVALID;
if ((gametypedefaultrules[pgametype] & GTR_CAMPAIGN) && kartcupheaders)
{
mapnum = G_MapNumber(kartcupheaders->levellist[0]);
mapnum = kartcupheaders->cachedlevels[0];
}
if (mapnum >= nummapheaders)
@ -3699,7 +3689,7 @@ static void G_GetNextMap(void)
else
{
// Proceed to next map
const INT32 cupLevelNum = G_MapNumber(grandprixinfo.cup->levellist[grandprixinfo.roundnum]);
const INT32 cupLevelNum =grandprixinfo.cup->cachedlevels[grandprixinfo.roundnum];
if (cupLevelNum < nummapheaders && mapheaderinfo[cupLevelNum])
{
@ -3725,19 +3715,14 @@ static void G_GetNextMap(void)
if (gametyperules & GTR_CAMPAIGN)
{
register INT16 cm;
cupheader_t *cup = kartcupheaders;
cupheader_t *cup = mapheaderinfo[gamemap-1]->cup;
UINT8 gettingresult = 0;
// While this can't produce an infinite loop IN THE ITERATION, it
// is technically possible for you to keep cycling inside a lousy
// cul-de-sac of the same maps over and over while marathonning
// them all, if the same map is present in the cup list multiple
// times. There is no good solution. Don't dupe maps between cups!
while (cup)
{
for (i = 0; i < cup->numlevels; i++)
{
cm = G_MapNumber(cup->levellist[i]);
cm = cup->cachedlevels[i];
// Not valid?
if (cm >= nummapheaders
@ -3829,9 +3814,7 @@ static void G_GetNextMap(void)
}
// We are committed to this map now.
// We may as well allocate its header if it doesn't exist
// (That is, if it's a real map)
if (nextmap < NEXTMAP_SPECIAL && (nextmap >= nummapheaders || !mapheaderinfo[nextmap] || mapheaderinfo[nextmap]->lumpnum == LUMPERROR))
if (nextmap == NEXTMAP_INVALID || (nextmap < NEXTMAP_SPECIAL && (nextmap >= nummapheaders || !mapheaderinfo[nextmap] || mapheaderinfo[nextmap]->lumpnum == LUMPERROR)))
I_Error("G_GetNextMap: Internal map ID %d not found (nummapheaders = %d)\n", nextmap, nummapheaders);
}
@ -4135,11 +4118,6 @@ void G_LoadGameSettings(void)
{
// defaults
spstage_start = spmarathon_start = 1;
sstage_start = 50;
sstage_end = 56; // 7 special stages in vanilla SRB2
sstage_end++; // plus one weirdo
smpstage_start = 60;
smpstage_end = 66; // 7 multiplayer special stages too
// initialize free sfx slots for skin sounds
S_InitRuntimeSounds();

View file

@ -44,7 +44,8 @@ typedef enum
NEXTMAP_EVALUATION = INT16_MAX-2,
NEXTMAP_CREDITS = INT16_MAX-3,
NEXTMAP_CEREMONY = INT16_MAX-4,
NEXTMAP_SPECIAL = NEXTMAP_CEREMONY
NEXTMAP_INVALID = INT16_MAX-5, // Always last (swap with NEXTMAP_RESERVED when removing that)
NEXTMAP_SPECIAL = NEXTMAP_INVALID
} nextmapspecial_t;
extern INT32 gameovertics;

View file

@ -1846,7 +1846,7 @@ static void M_DrawCupPreview(INT16 y, cupheader_t *cup)
i = (cupgrid.previewanim / 82) % cup->numlevels;
while (x < BASEVIDWIDTH + pad)
{
INT32 cupLevelNum = G_MapNumber(cup->levellist[i]);
INT32 cupLevelNum = cup->cachedlevels[i];
patch_t *PictureOfLevel = NULL;
if (cupLevelNum < nummapheaders && mapheaderinfo[cupLevelNum])

View file

@ -3207,23 +3207,10 @@ boolean M_CanShowLevelInList(INT16 mapnum, UINT8 gt)
if (levellist.timeattack && (mapheaderinfo[mapnum]->menuflags & LF2_NOTIMEATTACK))
return false;
if (gametypedefaultrules[gt] & GTR_CAMPAIGN)
if (gametypedefaultrules[gt] & GTR_CAMPAIGN && levellist.selectedcup)
{
if (levellist.selectedcup && levellist.selectedcup->numlevels)
{
UINT8 i;
for (i = 0; i < levellist.selectedcup->numlevels; i++)
{
const INT32 cupLevelNum = G_MapNumber(levellist.selectedcup->levellist[i]);
if (mapnum == cupLevelNum)
break;
}
if (i == levellist.selectedcup->numlevels)
return false;
}
if (mapheaderinfo[mapnum]->cup != levellist.selectedcup)
return false;
}
// Survived our checks.
@ -3413,7 +3400,9 @@ void M_CupSelectHandler(INT32 choice)
{
M_SetMenuDelay(pid);
if ((!newcup) || (newcup && newcup->unlockrequired != -1 && !unlockables[newcup->unlockrequired].unlocked))
if ((!newcup)
|| (newcup && newcup->unlockrequired != -1 && !unlockables[newcup->unlockrequired].unlocked)
|| (newcup->cachedlevels[0] == NEXTMAP_INVALID))
{
S_StartSound(NULL, sfx_s3kb2);
return;
@ -3465,7 +3454,7 @@ void M_CupSelectHandler(INT32 choice)
netgame = levellist.netgame; // ^ ditto.
}
levelNum = G_MapNumber(grandprixinfo.cup->levellist[0]);
levelNum = grandprixinfo.cup->cachedlevels[0];
D_MapChange(
levelNum + 1,

View file

@ -2116,7 +2116,6 @@ static int mapheaderinfo_get(lua_State *L)
{
mapheader_t *header = *((mapheader_t **)luaL_checkudata(L, 1, META_MAPHEADER));
const char *field = luaL_checkstring(L, 2);
INT16 i;
if (fastcmp(field,"lvlttl"))
lua_pushstring(L, header->lvlttl);
else if (fastcmp(field,"subttl"))
@ -2135,8 +2134,6 @@ static int mapheaderinfo_get(lua_State *L)
lua_pushinteger(L, header->mustrack);
else if (fastcmp(field,"muspos"))
lua_pushinteger(L, header->muspos);
else if (fastcmp(field,"forcecharacter"))
lua_pushstring(L, header->forcecharacter);
else if (fastcmp(field,"weather"))
lua_pushinteger(L, header->weather);
else if (fastcmp(field,"skytexture"))
@ -2147,12 +2144,7 @@ static int mapheaderinfo_get(lua_State *L)
lua_pushinteger(L, header->skybox_scaley);
else if (fastcmp(field,"skybox_scalez"))
lua_pushinteger(L, header->skybox_scalez);
else if (fastcmp(field,"interscreen")) {
for (i = 0; i < 8; i++)
if (!header->interscreen[i])
break;
lua_pushlstring(L, header->interscreen, i);
} else if (fastcmp(field,"runsoc"))
else if (fastcmp(field,"runsoc"))
lua_pushstring(L, header->runsoc);
else if (fastcmp(field,"scriptname"))
lua_pushstring(L, header->scriptname);
@ -2160,8 +2152,6 @@ static int mapheaderinfo_get(lua_State *L)
lua_pushinteger(L, header->precutscenenum);
else if (fastcmp(field,"cutscenenum"))
lua_pushinteger(L, header->cutscenenum);
else if (fastcmp(field,"countdown"))
lua_pushinteger(L, header->countdown);
else if (fastcmp(field,"palette"))
lua_pushinteger(L, header->palette);
else if (fastcmp(field,"numlaps"))
@ -2176,12 +2166,6 @@ static int mapheaderinfo_get(lua_State *L)
lua_pushinteger(L, header->menuflags);
else if (fastcmp(field,"mobj_scale"))
lua_pushfixed(L, header->mobj_scale);
else if (fastcmp(field,"startrings"))
lua_pushinteger(L, header->startrings);
else if (fastcmp(field, "sstimer"))
lua_pushinteger(L, header->sstimer);
else if (fastcmp(field, "ssspheres"))
lua_pushinteger(L, header->ssspheres);
else if (fastcmp(field, "gravity"))
lua_pushfixed(L, header->gravity);
else {

View file

@ -217,18 +217,6 @@ int LUA_PushGlobals(lua_State *L, const char *word)
} else if (fastcmp(word,"spmarathon_start")) {
lua_pushinteger(L, spmarathon_start);
return 1;
} else if (fastcmp(word,"sstage_start")) {
lua_pushinteger(L, sstage_start);
return 1;
} else if (fastcmp(word,"sstage_end")) {
lua_pushinteger(L, sstage_end);
return 1;
} else if (fastcmp(word,"smpstage_start")) {
lua_pushinteger(L, smpstage_start);
return 1;
} else if (fastcmp(word,"smpstage_end")) {
lua_pushinteger(L, smpstage_end);
return 1;
} else if (fastcmp(word,"titlemap")) {
lua_pushstring(L, titlemap);
return 1;

View file

@ -11281,7 +11281,7 @@ void P_SpawnPlayer(INT32 playernum)
else if (p->bot)
{
/*
if (bonusgame || specialstage)
if (bonusgame || specialstage || boss)
{
// Bots should avoid
p->spectator = true;

View file

@ -4476,7 +4476,6 @@ static void P_NetArchiveMisc(boolean resending)
WRITEUINT8(save_p, encoremode);
WRITEUINT32(save_p, leveltime);
WRITEUINT32(save_p, ssspheres);
WRITEINT16(save_p, lastmap);
WRITEUINT16(save_p, bossdisabled);
@ -4502,7 +4501,6 @@ static void P_NetArchiveMisc(boolean resending)
}
WRITEUINT32(save_p, token);
WRITEINT32(save_p, sstimer);
WRITEUINT32(save_p, bluescore);
WRITEUINT32(save_p, redscore);
@ -4531,9 +4529,6 @@ static void P_NetArchiveMisc(boolean resending)
WRITEFIXED(save_p, gravity);
WRITEFIXED(save_p, mapobjectscale);
WRITEUINT32(save_p, countdowntimer);
WRITEUINT8(save_p, countdowntimeup);
// SRB2kart
WRITEINT32(save_p, numgotboxes);
WRITEUINT8(save_p, numtargets);
@ -4642,7 +4637,6 @@ static inline boolean P_NetUnArchiveMisc(boolean reloading)
// get the time
leveltime = READUINT32(save_p);
ssspheres = READUINT32(save_p);
lastmap = READINT16(save_p);
bossdisabled = READUINT16(save_p);
@ -4665,7 +4659,6 @@ static inline boolean P_NetUnArchiveMisc(boolean reloading)
}
token = READUINT32(save_p);
sstimer = READINT32(save_p);
bluescore = READUINT32(save_p);
redscore = READUINT32(save_p);
@ -4694,9 +4687,6 @@ static inline boolean P_NetUnArchiveMisc(boolean reloading)
gravity = READFIXED(save_p);
mapobjectscale = READFIXED(save_p);
countdowntimer = (tic_t)READUINT32(save_p);
countdowntimeup = (boolean)READUINT8(save_p);
// SRB2kart
numgotboxes = READINT32(save_p);
numtargets = READUINT8(save_p);

View file

@ -366,28 +366,22 @@ static void P_ClearSingleMapHeaderInfo(INT16 num)
mapheaderinfo[num]->zonttl[0] = '\0';
mapheaderinfo[num]->actnum = 0;
mapheaderinfo[num]->typeoflevel = 0;
mapheaderinfo[num]->startrings = 0;
mapheaderinfo[num]->sstimer = 90;
mapheaderinfo[num]->ssspheres = 1;
mapheaderinfo[num]->gravity = DEFAULT_GRAVITY;
mapheaderinfo[num]->keywords[0] = '\0';
sprintf(mapheaderinfo[num]->musname, "%.5sM", G_BuildMapName(i));
sprintf(mapheaderinfo[num]->musname, "%.5sM", G_BuildMapName(num));
mapheaderinfo[num]->musname[6] = 0;
mapheaderinfo[num]->mustrack = 0;
mapheaderinfo[num]->muspos = 0;
mapheaderinfo[num]->forcecharacter[0] = '\0';
mapheaderinfo[num]->weather = PRECIP_NONE;
snprintf(mapheaderinfo[num]->skytexture, 5, "SKY1");
mapheaderinfo[num]->skytexture[4] = 0;
mapheaderinfo[num]->skybox_scalex = 16;
mapheaderinfo[num]->skybox_scaley = 16;
mapheaderinfo[num]->skybox_scalez = 16;
mapheaderinfo[num]->interscreen[0] = '#';
mapheaderinfo[num]->runsoc[0] = '#';
mapheaderinfo[num]->scriptname[0] = '#';
mapheaderinfo[num]->precutscenenum = 0;
mapheaderinfo[num]->cutscenenum = 0;
mapheaderinfo[num]->countdown = 0;
mapheaderinfo[num]->palette = UINT16_MAX;
mapheaderinfo[num]->encorepal = UINT16_MAX;
mapheaderinfo[num]->numlaps = NUMLAPS_DEFAULT;
@ -461,8 +455,9 @@ void P_AllocMapHeader(INT16 i)
mapheaderinfo[i]->lumpname = NULL;
mapheaderinfo[i]->thumbnailPic = NULL;
mapheaderinfo[i]->minimapPic = NULL;
mapheaderinfo[i]->flickies = NULL;
mapheaderinfo[i]->cup = NULL;
mapheaderinfo[i]->mainrecord = NULL;
mapheaderinfo[i]->flickies = NULL;
nummapheaders++;
}
P_ClearSingleMapHeaderInfo(i);
@ -3523,15 +3518,6 @@ static void P_InitLevelSettings(void)
// emerald hunt
hunt1 = hunt2 = hunt3 = NULL;
// map time limit
if (mapheaderinfo[gamemap-1]->countdown)
{
countdowntimer = mapheaderinfo[gamemap-1]->countdown * TICRATE;
}
else
countdowntimer = 0;
countdowntimeup = false;
// clear ctf pointers
redflag = blueflag = NULL;
rflagpoint = bflagpoint = NULL;
@ -3539,7 +3525,7 @@ static void P_InitLevelSettings(void)
// circuit, race and competition stuff
circuitmap = false;
numstarposts = 0;
ssspheres = timeinmap = 0;
timeinmap = 0;
// special stage
stagefailed = true; // assume failed unless proven otherwise - P_GiveEmerald or emerald touchspecial
@ -3683,43 +3669,6 @@ static void P_RunLevelScript(const char *scriptname)
COM_BufExecute(); // Run it!
}
static void P_ForceCharacter(const char *forcecharskin)
{
UINT8 i;
if (netgame)
{
char skincmd[33];
for (i = 0; i <= splitscreen; i++)
{
const char *num = "";
if (i > 0)
num = va("%d", i+1);
sprintf(skincmd, "skin%s %s\n", num, forcecharskin);
CV_Set(&cv_skin[i], forcecharskin);
}
COM_BufAddText(skincmd);
}
else
{
for (i = 0; i <= splitscreen; i++)
{
SetPlayerSkin(g_localplayers[i], forcecharskin);
// normal player colors in single player
if ((unsigned)cv_playercolor[i].value != skins[players[g_localplayers[i]].skin].prefcolor && !modeattacking)
{
CV_StealthSetValue(&cv_playercolor[i], skins[players[g_localplayers[i]].skin].prefcolor);
players[g_localplayers[i]].skincolor = skins[players[g_localplayers[i]].skin].prefcolor;
}
}
}
}
static void P_ResetSpawnpoints(void)
{
UINT8 i;
@ -3991,9 +3940,6 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
for (i = 0; i <= r_splitscreen; i++)
postimgtype[i] = postimg_none;
if (mapheaderinfo[gamemap-1]->forcecharacter[0] != '\0')
P_ForceCharacter(mapheaderinfo[gamemap-1]->forcecharacter);
// Initial height of PointOfView
// will be set by player think.
players[consoleplayer].viewz = 1;
@ -4566,6 +4512,37 @@ UINT8 P_InitMapData(INT32 numexistingmapheaders)
}
vres_Free(virtmap);
// Now associate it with a cup cache.
// (The core assumption is that cups < headers.)
if (i >= numexistingmapheaders)
{
cupheader_t *cup = kartcupheaders;
INT32 j;
while (cup)
{
for (j = 0; j < CUPCACHE_MAX; j++)
{
// Already discovered?
if (cup->cachedlevels[j] != NEXTMAP_INVALID)
continue;
if (!cup->levellist[j] || strcasecmp(cup->levellist[j], name) != 0)
continue;
// Only panic about back-reference for non-bonus material.
if (j < MAXLEVELLIST || j == CUPCACHE_SPECIAL)
{
if (mapheaderinfo[i]->cup)
I_Error("P_InitMapData: Map %s cannot appear in cups multiple times! (First in %s, now in %s)", name, mapheaderinfo[i]->cup->name, cup->name);
mapheaderinfo[i]->cup = cup;
}
cup->cachedlevels[j] = i;
}
cup = cup->next;
}
}
}
}

View file

@ -5931,10 +5931,6 @@ void P_InitSpecials(void)
maplighting.directional = mapheaderinfo[gamemap-1]->use_light_angle;
maplighting.angle = mapheaderinfo[gamemap-1]->light_angle;
// Defaults in case levels don't have them set.
sstimer = mapheaderinfo[gamemap-1]->sstimer*TICRATE + 6;
ssspheres = mapheaderinfo[gamemap-1]->ssspheres;
CheckForBustableBlocks = CheckForBouncySector = CheckForQuicksand = CheckForMarioBlocks = CheckForFloatBob = CheckForReverseGravity = false;
// Set weather
@ -6026,11 +6022,6 @@ void P_SpawnSpecials(boolean fromnetsave)
// Process Section 2
switch(GETSECSPECIAL(sector->special, 2))
{
case 10: // Time for special stage
sstimer = (sector->floorheight>>FRACBITS) * TICRATE + 6; // Time to finish
ssspheres = sector->ceilingheight>>FRACBITS; // Ring count for special stage
break;
case 11: // Custom global gravity!
gravity = sector->floorheight/1000;
break;

View file

@ -300,11 +300,15 @@ boolean P_PlayerMoving(INT32 pnum)
//
UINT8 P_GetNextEmerald(void)
{
if (gamemap >= sstage_start && gamemap <= sstage_end)
return (UINT8)(gamemap - sstage_start);
if (gamemap >= smpstage_start || gamemap <= smpstage_end)
return (UINT8)(gamemap - smpstage_start);
return 0;
INT16 mapnum = gamemap-1;
if (mapnum > nummapheaders || !mapheaderinfo[mapnum])
return 0;
if (!mapheaderinfo[mapnum]->cup || mapheaderinfo[mapnum]->cup->cachedlevels[CUPCACHE_SPECIAL] != mapnum)
return 0;
return mapheaderinfo[mapnum]->cup->emeraldnum;
}
//
@ -2144,9 +2148,6 @@ void P_MovePlayer(player_t *player)
fixed_t runspd;
if (countdowntimeup)
return;
cmd = &player->cmd;
runspd = 14*player->mo->scale; //srb2kart

View file

@ -191,12 +191,6 @@ boolean R_SkinUsable(INT32 playernum, INT32 skinnum)
return true;
}
if (Playing() && (R_SkinAvailable(mapheaderinfo[gamemap-1]->forcecharacter) == skinnum))
{
// Being forced to play as this character by the level
return true;
}
if (netgame && (cv_forceskin.value == skinnum))
{
// Being forced to play as this character by the server