UCRP_MAPDESTROYOBJECTS

You have to destroy all objects of a certain list of types.
UNLIKE OTHER CHALLENGES, this is dependent on a mapheader parameter!!
The author of this commit just didn't want to create too laggy a condition check.
- `Condition1 = MapDestroyObjects RR_ESPRESSOLANE tables & chairs
- Map RR_ESPRESSOLANE
    - DestroyObjectsForChallenges = MT_ESPTABLE,MT_ESPCHAIR
This commit is contained in:
toaster 2023-10-19 17:27:33 +01:00
parent 5680e00deb
commit de79dfe983
8 changed files with 108 additions and 14 deletions

View file

@ -1383,6 +1383,28 @@ void readlevelheader(MYFILE *f, char * name)
}
else if (fastcmp(word, "GRAVITY"))
mapheaderinfo[num]->gravity = FLOAT_TO_FIXED(atof(word2));
else if (fastcmp(word, "DESTROYOBJECTSFORCHALLENGES"))
{
if (fastcmp(word2, "NONE"))
{
mapheaderinfo[num]->destroyforchallenge_size = 0;
}
else
{
UINT8 j = 0; // i was declared elsewhere
tmp = strtok(word2, ",");
do {
if (j >= MAXDESTRUCTIBLES)
break;
mapheaderinfo[num]->destroyforchallenge[j] = get_mobjtype(word2);
j++;
} while ((tmp = strtok(NULL,",")) != NULL);
if (tmp != NULL)
deh_warning("Level header %d: additional destructibles past %d discarded", num, MAXDESTRUCTIBLES);
mapheaderinfo[num]->destroyforchallenge_size = j;
}
}
else
deh_warning("Level header %d: unknown word '%s'", num, word);
}
@ -2500,7 +2522,6 @@ static void readcondition(UINT16 set, UINT32 id, char *word2)
ty = UC_PASSWORD;
stringvar = Z_StrDup(spos);
re = -1;
}
if (ty != UC_NONE)
@ -2531,6 +2552,15 @@ static void readcondition(UINT16 set, UINT32 id, char *word2)
if (spos && *spos)
stringvar = Z_StrDup(spos);
}
else if (fastcmp(params[0], "MAPDESTROYOBJECTS"))
{
PARAMCHECK(1);
EXTENDEDPARAMCHECK(spos, 2);
ty = UCRP_MAPDESTROYOBJECTS;
re = G_MapNumber(params[1]);
stringvar = Z_StrDup(spos);
}
if (ty != UC_NONE)
goto setcondition;

View file

@ -440,6 +440,7 @@ struct staffbrief_t
};
#define MAXMUSNAMES 3 // maximum definable music tracks per level
#define MAXDESTRUCTIBLES 3
#define MAXHEADERFOLLOWERS 32
struct mapheader_lighting_t
@ -537,6 +538,9 @@ struct mapheader_t
UINT8 precutscenenum; ///< Cutscene number to play BEFORE a level starts.
UINT8 cutscenenum; ///< Cutscene number to use, 0 for none.
mobjtype_t destroyforchallenge[MAXDESTRUCTIBLES]; ///< Assistive for UCRP_MAPDESTROYOBJECTS
UINT8 destroyforchallenge_size; ///< Number for above
UINT32 _saveid; ///< Purely assistive in gamedata save processes
UINT16 cache_spraycan; ///< Cached Spraycan ID
UINT16 cache_maplock; ///< Cached Unlockable ID
@ -722,6 +726,7 @@ extern INT32 luabanks[NUM_LUABANKS];
extern INT32 nummaprings; //keep track of spawned rings/coins
extern UINT8 nummapspraycans;
extern UINT16 numchallengedestructibles;
extern UINT32 bluescore; ///< Blue Team Scores
extern UINT32 redscore; ///< Red Team Scores

View file

@ -222,6 +222,7 @@ UINT32 bluescore, redscore; // CTF and Team Match team scores
INT32 nummaprings = 0;
UINT8 nummapspraycans = 0;
UINT16 numchallengedestructibles = 0;
// Elminates unnecessary searching.
boolean CheckForBustableBlocks;

View file

@ -1523,6 +1523,11 @@ boolean M_CheckCondition(condition_t *cn, player_t *player)
// But the game already has this handy-dandy SPB signal for us...
// It's only MAYBE invalid in modded context. And mods can already cheat...
return ((player->pflags & PF_RINGLOCK) == PF_RINGLOCK);
case UCRP_MAPDESTROYOBJECTS:
return (
gamemap == cn->requirement+1
&& numchallengedestructibles == UINT16_MAX
);
case UCRP_MAKERETIRE:
{
@ -2363,6 +2368,16 @@ static const char *M_GetConditionString(condition_t *cn)
return "smash the UFO Catcher";
case UCRP_CHASEDBYSPB:
return "while chased by a Self-Propelled Bomb";
case UCRP_MAPDESTROYOBJECTS:
{
if (cn->stringvar == NULL)
return va("INVALID DESTROY CONDITION \"%d\"", cn->type);
title = M_BuildConditionTitle(cn->requirement);
work = va("%s: destroy all the %s", title, cn->stringvar);
Z_Free(title);
return work;
}
case UCRP_MAKERETIRE:
{

View file

@ -101,6 +101,7 @@ typedef enum
UCRP_SMASHUFO, // Smash the UFO Catcher
UCRP_CHASEDBYSPB, // Chased by SPB
UCRP_MAPDESTROYOBJECTS, // LEVELNAME: Destroy all [object names] -- CAUTION: You have to add to the level's header too to get them successfully tracked!
UCRP_MAKERETIRE, // Make another player of [skin] No Contest

View file

@ -11606,18 +11606,40 @@ void P_RemoveMobj(mobj_t *mobj)
mobj->thinker.function.acp1 = (actionf_p1)P_MobjThinker; // needed for P_UnsetThingPosition, etc. to work.
// Rings only, please!
if (mobj->spawnpoint &&
(mobj->type == MT_RING
|| mobj->type == MT_BLUESPHERE)
&& !(mobj->flags2 & MF2_DONTRESPAWN))
if (mobj->spawnpoint == NULL)
;
else
{
//CONS_Printf("added to queue at tic %d\n", leveltime);
itemrespawnque[iquehead] = mobj->spawnpoint;
itemrespawntime[iquehead] = leveltime;
iquehead = (iquehead+1)&(ITEMQUESIZE-1);
// lose one off the end?
if (iquehead == iquetail)
iquetail = (iquetail+1)&(ITEMQUESIZE-1);
if ((mobj->type == MT_RING
|| mobj->type == MT_BLUESPHERE)
&& !(mobj->flags2 & MF2_DONTRESPAWN))
{
//CONS_Printf("added to queue at tic %d\n", leveltime);
itemrespawnque[iquehead] = mobj->spawnpoint;
itemrespawntime[iquehead] = leveltime;
iquehead = (iquehead+1)&(ITEMQUESIZE-1);
// lose one off the end?
if (iquehead == iquetail)
iquetail = (iquetail+1)&(ITEMQUESIZE-1);
}
if (numchallengedestructibles && numchallengedestructibles != UINT16_MAX)
{
UINT8 i;
for (i = 0; i < mapheaderinfo[gamemap-1]->destroyforchallenge_size; i++)
{
if (mobj->type != mapheaderinfo[gamemap-1]->destroyforchallenge[i])
continue;
if ((--numchallengedestructibles) == 0)
{
numchallengedestructibles = UINT16_MAX;
gamedata->deferredconditioncheck = true;
}
break;
}
}
}
if (P_IsTrackerType(mobj->type))
@ -14148,12 +14170,12 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj)
return true;
}
static mobj_t *P_SpawnMobjFromMapThing(mapthing_t *mthing, fixed_t x, fixed_t y, fixed_t z, mobjtype_t i)
static mobj_t *P_SpawnMobjFromMapThing(mapthing_t *mthing, fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
{
mobj_t *mobj = NULL;
size_t arg = SIZE_MAX;
mobj = P_SpawnMobj(x, y, z, i);
mobj = P_SpawnMobj(x, y, z, type);
mobj->spawnpoint = mthing;
mobj->angle = FixedAngle(mthing->angle << FRACBITS);
@ -14237,6 +14259,19 @@ static mobj_t *P_SpawnMobjFromMapThing(mapthing_t *mthing, fixed_t x, fixed_t y,
mobj->flags2 |= MF2_OBJECTFLIP;
}
if (mapheaderinfo[gamemap-1]->destroyforchallenge_size && numchallengedestructibles != UINT16_MAX)
{
UINT8 i;
for (i = 0; i < mapheaderinfo[gamemap-1]->destroyforchallenge_size; i++)
{
if (type != mapheaderinfo[gamemap-1]->destroyforchallenge[i])
continue;
numchallengedestructibles++;
break;
}
}
return mobj;
}

View file

@ -6064,6 +6064,8 @@ static void P_NetArchiveMisc(savebuffer_t *save, boolean resending)
WRITEUINT32(save->p, darktimer);
WRITEFIXED(save->p, darkness);
WRITEUINT16(save->p, numchallengedestructibles);
// Is it paused?
if (paused)
WRITEUINT8(save->p, 0x2f);
@ -6246,6 +6248,8 @@ static boolean P_NetUnArchiveMisc(savebuffer_t *save, boolean reloading)
darktimer = READUINT32(save->p);
darkness = READFIXED(save->p);
numchallengedestructibles = READUINT16(save->p);
// Is it paused?
if (READUINT8(save->p) == 0x2f)
paused = true;

View file

@ -463,6 +463,8 @@ static void P_ClearSingleMapHeaderInfo(INT16 num)
mapheaderinfo[num]->justPlayed = 0;
mapheaderinfo[num]->anger = 0;
mapheaderinfo[num]->destroyforchallenge_size = 0;
mapheaderinfo[num]->cache_spraycan = UINT16_MAX;
mapheaderinfo[num]->cache_maplock = MAXUNLOCKABLES;
@ -7553,6 +7555,7 @@ static void P_InitLevelSettings(void)
battleprisons = false;
nummapspraycans = 0;
numchallengedestructibles = 0;
// circuit, race and competition stuff
numcheatchecks = 0;