From e732f372586de8827d2afdd2805f97a8f8a5423c Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 26 Mar 2023 22:34:37 +0100 Subject: [PATCH] levelheader_t: `relevantskin` property - On level load for GT_TUTORIAL: - Forces to requested skin (or Eggman if not specified). - Named `relevantskin` and not `tutorialskin` in case it's useful to use the same apparatus later for Adventure. - Also sets default skincolor and disables follower. --- src/deh_soc.c | 5 +++++ src/doomstat.h | 1 + src/p_setup.c | 31 +++++++++++++++++++++++++++++++ src/r_skins.c | 6 ++++++ 4 files changed, 43 insertions(+) diff --git a/src/deh_soc.c b/src/deh_soc.c index ad3d46145..190001f80 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -1122,6 +1122,11 @@ void readlevelheader(MYFILE *f, char * name) deh_strlcpy(mapheaderinfo[num]->zonttl, word2, sizeof(mapheaderinfo[num]->zonttl), va("Level header %d: zonetitle", num)); } + else if (fastcmp(word, "RELEVANTSKIN")) + { + deh_strlcpy(mapheaderinfo[num]->relevantskin, word2, + sizeof(mapheaderinfo[num]->relevantskin), va("Level header %d: relevantskin", num)); + } else if (fastcmp(word, "SCRIPTNAME")) { deh_strlcpy(mapheaderinfo[num]->scriptname, word2, diff --git a/src/doomstat.h b/src/doomstat.h index 6a31180a9..01f584dd4 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -427,6 +427,7 @@ struct mapheader_t UINT32 typeoflevel; ///< Combination of typeoflevel flags. UINT8 numlaps; ///< Number of laps in circuit mode, unless overridden. fixed_t gravity; ///< Map-wide gravity. + char relevantskin[SKINNAMESIZE+1]; ///< Skin to use for tutorial (if not provided, uses Eggman.) // Music information char musname[MAXMUSNAMES][7]; ///< Music tracks to play. First dimension is the track number, second is the music string. "" for no music. diff --git a/src/p_setup.c b/src/p_setup.c index 9082c2796..0ca14594b 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -389,6 +389,7 @@ static void P_ClearSingleMapHeaderInfo(INT16 num) mapheaderinfo[num]->typeoflevel = 0; mapheaderinfo[num]->gravity = DEFAULT_GRAVITY; mapheaderinfo[num]->keywords[0] = '\0'; + mapheaderinfo[num]->relevantskin[0] = '\0'; mapheaderinfo[num]->musname[0][0] = 0; mapheaderinfo[num]->musname_size = 0; mapheaderinfo[num]->positionmus[0] = '\0'; @@ -7392,6 +7393,27 @@ static void P_InitCamera(void) static void P_InitPlayers(void) { UINT8 i; + INT32 skin = -1; + + // Are we forcing a character? + if (gametype == GT_TUTORIAL) + { + // Get skin from name. + if (mapheaderinfo[gamemap-1] && mapheaderinfo[gamemap-1]->relevantskin[0]) + { + skin = R_SkinAvailable(mapheaderinfo[gamemap-1]->relevantskin); + } + else + { + skin = R_SkinAvailable(DEFAULTSKIN); + } + + // Handle invalid case. + if (skin == -1) + { + skin = 0; + } + } for (i = 0; i < MAXPLAYERS; i++) { @@ -7400,6 +7422,15 @@ static void P_InitPlayers(void) players[i].mo = NULL; + // If we're forcing a character, do it now. + if (skin != -1) + { + players[i].skin = skin; + players[i].skincolor = skins[skin].prefcolor; + players[i].followerskin = -1; + // followercolor can be left alone for hopefully obvious reasons + } + if (!(gametyperules & GTR_CIRCUIT) && K_PodiumSequence() == false) { G_DoReborn(i); diff --git a/src/r_skins.c b/src/r_skins.c index 212256c21..9a9df4f88 100644 --- a/src/r_skins.c +++ b/src/r_skins.c @@ -236,6 +236,12 @@ boolean R_SkinUsable(INT32 playernum, INT32 skinnum, boolean demoskins) return true; } + if (gametype == GT_TUTORIAL) + { + // Being forced to play as this character by the tutorial + return true; + } + // Determine if this character is supposed to be unlockable or not if (useplayerstruct && demo.playback) {