Mapheader Followers system

Replaces Flicky List system from 2.2.
Specify a list of comma-seperated Followers.
Not used by any systems in this commit, but important to store the data for later.
This commit is contained in:
toaster 2023-04-20 23:01:13 +01:00
parent 9eacdb4be4
commit 5f15736626
7 changed files with 70 additions and 112 deletions

View file

@ -187,7 +187,7 @@ void clear_levels(void)
// (no need to set num to 0, we're freeing the entire header shortly) // (no need to set num to 0, we're freeing the entire header shortly)
Z_Free(mapheaderinfo[nummapheaders]->customopts); Z_Free(mapheaderinfo[nummapheaders]->customopts);
P_DeleteFlickies(nummapheaders); P_DeleteHeaderFollowers(nummapheaders);
Z_Free(mapheaderinfo[nummapheaders]->mainrecord); Z_Free(mapheaderinfo[nummapheaders]->mainrecord);
@ -1042,77 +1042,47 @@ void readlevelheader(MYFILE *f, char * name)
// Now go to uppercase // Now go to uppercase
strupr(word2); strupr(word2);
// List of flickies that are be freed in this map // List of followers that are be freed in this map
if (fastcmp(word, "FLICKYLIST") || fastcmp(word, "ANIMALLIST")) if (fastcmp(word, "FOLLOWERS"))
{ {
if (fastcmp(word2, "NONE")) if (fastcmp(word2, "NONE"))
P_DeleteFlickies(num); P_DeleteHeaderFollowers(num);
else if (fastcmp(word2, "DEMO")) else if (fastcmp(word2, "DEFAULT"))
P_SetDemoFlickies(num); P_SetDefaultHeaderFollowers(num);
else if (fastcmp(word2, "ALL"))
{
mobjtype_t tmpflickies[MAXFLICKIES];
for (mapheaderinfo[num]->numFlickies = 0;
((mapheaderinfo[num]->numFlickies < MAXFLICKIES) && FLICKYTYPES[mapheaderinfo[num]->numFlickies].type);
mapheaderinfo[num]->numFlickies++)
tmpflickies[mapheaderinfo[num]->numFlickies] = FLICKYTYPES[mapheaderinfo[num]->numFlickies].type;
if (mapheaderinfo[num]->numFlickies) // just in case...
{
size_t newsize = sizeof(mobjtype_t) * mapheaderinfo[num]->numFlickies;
mapheaderinfo[num]->flickies = Z_Realloc(mapheaderinfo[num]->flickies, newsize, PU_STATIC, NULL);
M_Memcpy(mapheaderinfo[num]->flickies, tmpflickies, newsize);
}
}
else else
{ {
mobjtype_t tmpflickies[MAXFLICKIES]; INT16 tmpfollowers[MAXHEADERFOLLOWERS];
mapheaderinfo[num]->numFlickies = 0; mapheaderinfo[num]->numFollowers = 0;
tmp = strtok(word2,","); tmp = strtok(word2,",");
// get up to the first MAXFLICKIES flickies // get up to the first MAXHEADERFOLLOWERS followers
do { do {
if (mapheaderinfo[num]->numFlickies == MAXFLICKIES) // never going to get above that number if (mapheaderinfo[num]->numFollowers == MAXHEADERFOLLOWERS) // never going to get above that number
{ {
deh_warning("Level header %d: too many flickies\n", num); deh_warning("Level header %d: too many followers\n", num);
break; break;
} }
if (fastncmp(tmp, "MT_", 3)) // support for specified mobjtypes...
{ {
i = get_mobjtype(tmp); i = K_FollowerAvailable(tmp);
if (!i) if (i == -1)
{ {
//deh_warning("Level header %d: unknown flicky mobj type %s\n", num, tmp); -- no need for this line as get_mobjtype complains too deh_warning("Level header %d: unknown follower selection %s\n", num, tmp);
continue; continue;
} }
tmpflickies[mapheaderinfo[num]->numFlickies] = i; tmpfollowers[mapheaderinfo[num]->numFollowers] = i;
mapheaderinfo[num]->numFollowers++;
} }
else // ...or a quick, limited selection of default flickies!
{
for (i = 0; FLICKYTYPES[i].name; i++)
if (fastcmp(tmp, FLICKYTYPES[i].name))
break;
if (!FLICKYTYPES[i].name)
{
deh_warning("Level header %d: unknown flicky selection %s\n", num, tmp);
continue;
}
tmpflickies[mapheaderinfo[num]->numFlickies] = FLICKYTYPES[i].type;
}
mapheaderinfo[num]->numFlickies++;
} while ((tmp = strtok(NULL,",")) != NULL); } while ((tmp = strtok(NULL,",")) != NULL);
if (mapheaderinfo[num]->numFlickies) if (mapheaderinfo[num]->numFollowers)
{ {
size_t newsize = sizeof(mobjtype_t) * mapheaderinfo[num]->numFlickies; size_t newsize = sizeof(UINT16) * mapheaderinfo[num]->numFollowers;
mapheaderinfo[num]->flickies = Z_Realloc(mapheaderinfo[num]->flickies, newsize, PU_STATIC, NULL); mapheaderinfo[num]->followers = Z_Realloc(mapheaderinfo[num]->followers, newsize, PU_STATIC, NULL);
// now we add them to the list! // now we add them to the list!
M_Memcpy(mapheaderinfo[num]->flickies, tmpflickies, newsize); M_Memcpy(mapheaderinfo[num]->followers, tmpfollowers, newsize);
} }
else else
deh_warning("Level header %d: no valid flicky types found\n", num); deh_warning("Level header %d: no valid follower types found\n", num);
} }
} }

View file

@ -31,31 +31,6 @@ char *FREE_MOBJS[NUMMOBJFREESLOTS];
char *FREE_SKINCOLORS[NUMCOLORFREESLOTS]; char *FREE_SKINCOLORS[NUMCOLORFREESLOTS];
UINT8 used_spr[(NUMSPRITEFREESLOTS / 8) + 1]; // Bitwise flag for sprite freeslot in use! I would use ceil() here if I could, but it only saves 1 byte of memory anyway. UINT8 used_spr[(NUMSPRITEFREESLOTS / 8) + 1]; // Bitwise flag for sprite freeslot in use! I would use ceil() here if I could, but it only saves 1 byte of memory anyway.
struct flickytypes_s FLICKYTYPES[] = {
{"BLUEBIRD", MT_FLICKY_01}, // Flicky (Flicky)
{"RABBIT", MT_FLICKY_02}, // Pocky (1)
{"CHICKEN", MT_FLICKY_03}, // Cucky (1)
{"SEAL", MT_FLICKY_04}, // Rocky (1)
{"PIG", MT_FLICKY_05}, // Picky (1)
{"CHIPMUNK", MT_FLICKY_06}, // Ricky (1)
{"PENGUIN", MT_FLICKY_07}, // Pecky (1)
{"FISH", MT_FLICKY_08}, // Nicky (CD)
{"RAM", MT_FLICKY_09}, // Flocky (CD)
{"PUFFIN", MT_FLICKY_10}, // Wicky (CD)
{"COW", MT_FLICKY_11}, // Macky (SRB2)
{"RAT", MT_FLICKY_12}, // Micky (2)
{"BEAR", MT_FLICKY_13}, // Becky (2)
{"DOVE", MT_FLICKY_14}, // Docky (CD)
{"CAT", MT_FLICKY_15}, // Nyannyan (Flicky)
{"CANARY", MT_FLICKY_16}, // Lucky (CD)
{"a", 0}, // End of normal flickies - a lower case character so will never fastcmp valid with uppercase tmp
//{"FLICKER", MT_FLICKER}, // Flacky (SRB2)
{"SPIDER", MT_SECRETFLICKY_01}, // Sticky (SRB2)
{"BAT", MT_SECRETFLICKY_02}, // Backy (SRB2)
{"SEED", MT_SEED}, // Seed (CD)
{NULL, 0}
};
// IMPORTANT! // IMPORTANT!
// DO NOT FORGET TO SYNC THIS LIST WITH THE ACTIONNUM ENUM IN INFO.H // DO NOT FORGET TO SYNC THIS LIST WITH THE ACTIONNUM ENUM IN INFO.H
actionpointer_t actionpointers[] = actionpointer_t actionpointers[] =

View file

@ -41,8 +41,6 @@ struct flickytypes_s {
const mobjtype_t type; const mobjtype_t type;
}; };
#define MAXFLICKIES 64
/** Action pointer for reading actions from Dehacked lumps. /** Action pointer for reading actions from Dehacked lumps.
*/ */
struct actionpointer_t struct actionpointer_t

View file

@ -386,6 +386,7 @@ struct staffbrief_t
}; };
#define MAXMUSNAMES 3 // maximum definable music tracks per level #define MAXMUSNAMES 3 // maximum definable music tracks per level
#define MAXHEADERFOLLOWERS 32
/** Map header information. /** Map header information.
*/ */
@ -458,9 +459,9 @@ struct mapheader_t
boolean use_light_angle; ///< When false, wall lighting is evenly distributed. When true, wall lighting is directional. 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. angle_t light_angle; ///< Angle of directional wall lighting.
// Freed animal information // Audience information
UINT8 numFlickies; ///< Internal. For freed flicky support. UINT8 numFollowers; ///< Internal. For audience support.
mobjtype_t *flickies; ///< List of freeable flickies in this level. Allocated dynamically for space reasons. Be careful. UINT16 *followers; ///< List of audience followers in this level. Allocated dynamically for space reasons. Be careful.
// Script information // Script information
char runsoc[33]; ///< SOC to execute at start of level (32 character limit instead of 63) char runsoc[33]; ///< SOC to execute at start of level (32 character limit instead of 63)

View file

@ -10234,13 +10234,8 @@ mobj_t *P_InternalFlickySpawn(mobj_t *actor, mobjtype_t flickytype, fixed_t momz
if (!flickytype) if (!flickytype)
{ {
if (!mapheaderinfo[gamemap-1] || !mapheaderinfo[gamemap-1]->numFlickies) // No mapheader, no shoes, no service. // The flicky list system has been removed, so no backups are possible.
return NULL; return NULL;
else
{
INT32 prandom = P_RandomKey(PR_UNDEFINED, mapheaderinfo[gamemap-1]->numFlickies);
flickytype = mapheaderinfo[gamemap-1]->flickies[prandom];
}
} }
if (moveforward) if (moveforward)

View file

@ -347,31 +347,50 @@ FUNCNORETURN static ATTRNORETURN void CorruptMapError(const char *msg)
I_Error("Invalid or corrupt map.\nLook in log file or text console for technical details."); I_Error("Invalid or corrupt map.\nLook in log file or text console for technical details.");
} }
/** Sets a header's flickies to be equivalent to the original Freed Animals /** Sets a header's followers to the default list
* *
* \param i The header to set flickies for * \param i The header to set followers for
*/ */
void P_SetDemoFlickies(INT16 i) void P_SetDefaultHeaderFollowers(UINT16 i)
{ {
mapheaderinfo[i]->numFlickies = 5; static INT16 defaultfollowers[MAXHEADERFOLLOWERS];
mapheaderinfo[i]->flickies = Z_Realloc(mapheaderinfo[i]->flickies, 5*sizeof(mobjtype_t), PU_STATIC, NULL); static UINT8 validdefaultfollowers = 0;
mapheaderinfo[i]->flickies[0] = MT_FLICKY_02/*MT_BUNNY*/;
mapheaderinfo[i]->flickies[1] = MT_FLICKY_01/*MT_BIRD*/; if (validdefaultfollowers == 0)
mapheaderinfo[i]->flickies[2] = MT_FLICKY_12/*MT_MOUSE*/; {
mapheaderinfo[i]->flickies[3] = MT_FLICKY_11/*MT_COW*/; const char *defaultfollowernames[] =
mapheaderinfo[i]->flickies[4] = MT_FLICKY_03/*MT_CHICKEN*/; {
"Flicky",
"Chao",
NULL
};
for (validdefaultfollowers = 0; defaultfollowernames[validdefaultfollowers]; validdefaultfollowers++)
{
defaultfollowers[validdefaultfollowers] = K_FollowerAvailable(defaultfollowernames[validdefaultfollowers]);
} }
/** Clears a header's flickies I_Assert(validdefaultfollowers != 0);
* }
* \param i The header to clear flickies for
*/ mapheaderinfo[i]->followers = Z_Realloc(mapheaderinfo[i]->followers, sizeof(UINT16) * validdefaultfollowers, PU_STATIC, NULL);
void P_DeleteFlickies(INT16 i)
for (mapheaderinfo[i]->numFollowers = 0; mapheaderinfo[i]->numFollowers < validdefaultfollowers; mapheaderinfo[i]->numFollowers++)
{ {
if (mapheaderinfo[i]->flickies) mapheaderinfo[i]->followers[mapheaderinfo[i]->numFollowers] = defaultfollowers[mapheaderinfo[i]->numFollowers];
Z_Free(mapheaderinfo[i]->flickies); }
mapheaderinfo[i]->flickies = NULL; }
mapheaderinfo[i]->numFlickies = 0;
/** Clears a header's followers
*
* \param i The header to clear followers for
*/
void P_DeleteHeaderFollowers(UINT16 i)
{
if (mapheaderinfo[i]->followers)
Z_Free(mapheaderinfo[i]->followers);
mapheaderinfo[i]->followers = NULL;
mapheaderinfo[i]->numFollowers = 0;
} }
#define NUMLAPS_DEFAULT 3 #define NUMLAPS_DEFAULT 3
@ -419,10 +438,10 @@ static void P_ClearSingleMapHeaderInfo(INT16 num)
mapheaderinfo[num]->light_contrast = 16; mapheaderinfo[num]->light_contrast = 16;
mapheaderinfo[num]->use_light_angle = false; mapheaderinfo[num]->use_light_angle = false;
mapheaderinfo[num]->light_angle = 0; mapheaderinfo[num]->light_angle = 0;
#if 1 // equivalent to "FlickyList = DEMO" #if 1 // equivalent to "Followers = DEFAULT"
P_SetDemoFlickies(num); P_SetDefaultHeaderFollowers(num);
#else // equivalent to "FlickyList = NONE" #else
P_DeleteFlickies(num); P_DeleteHeaderFollowers(num);
#endif #endif
mapheaderinfo[num]->mapvisited = 0; mapheaderinfo[num]->mapvisited = 0;
@ -486,7 +505,7 @@ void P_AllocMapHeader(INT16 i)
mapheaderinfo[i]->ghostCount = 0; mapheaderinfo[i]->ghostCount = 0;
mapheaderinfo[i]->cup = NULL; mapheaderinfo[i]->cup = NULL;
mapheaderinfo[i]->mainrecord = NULL; mapheaderinfo[i]->mainrecord = NULL;
mapheaderinfo[i]->flickies = NULL; mapheaderinfo[i]->followers = NULL;
nummapheaders++; nummapheaders++;
} }
P_ClearSingleMapHeaderInfo(i); P_ClearSingleMapHeaderInfo(i);

View file

@ -144,8 +144,8 @@ boolean P_ApplyLightOffsetFine(UINT8 baselightlevel);
size_t P_PrecacheLevelFlats(void); size_t P_PrecacheLevelFlats(void);
void P_AllocMapHeader(INT16 i); void P_AllocMapHeader(INT16 i);
void P_SetDemoFlickies(INT16 i); void P_SetDefaultHeaderFollowers(UINT16 i);
void P_DeleteFlickies(INT16 i); void P_DeleteHeaderFollowers(UINT16 i);
// Needed for NiGHTS // Needed for NiGHTS
void P_ReloadRings(void); void P_ReloadRings(void);