From 081872aa857cb57bf87670807597ee98b3009e91 Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 15 Jan 2019 19:01:55 +0000 Subject: [PATCH] First steps at implementing a mechanism that allows you to load non-cheaty good-faith mods such as custom characters with no Lua scripting, and play record attack with them. Features a few bad hacks and a few more areas of improvement; I'll try to iron them out before they hit `next` or `master`. --- src/d_main.c | 1 + src/d_netcmd.c | 7 +++++-- src/dehacked.c | 28 +++++++++++++++++++++++++++- src/doomstat.h | 3 +++ src/g_game.c | 44 ++++++++++++++++++++++++++++++++------------ src/lua_script.c | 3 +++ src/m_cheat.c | 1 + src/m_cond.c | 2 +- src/m_menu.c | 4 ++-- src/p_setup.c | 14 +++++++++++--- src/r_things.c | 5 +++-- src/r_things.h | 2 +- src/y_inter.c | 2 +- 13 files changed, 91 insertions(+), 25 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index 29a91686..f3539df7 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -1253,6 +1253,7 @@ void D_SRB2Main(void) #endif //ifndef DEVELOP mainwadstally = packetsizetally; + majormods = false; cht_Init(); diff --git a/src/d_netcmd.c b/src/d_netcmd.c index e15ed9aa..d6e78c91 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -2214,10 +2214,13 @@ static void Command_Map_f(void) return; } - if (!(netgame || multiplayer) && (!modifiedgame || savemoddata)) + if (!(netgame || multiplayer) && (!majormods || savemoddata)) { if (COM_CheckParm("-force")) + { G_SetGameModified(false); + majormods = true; + } else { CONS_Printf(M_GetText("Sorry, level change disabled in single player.\n")); @@ -4915,7 +4918,7 @@ static void Command_Isgamemodified_f(void) { if (savemoddata) CONS_Printf(M_GetText("modifiedgame is true, but you can save medal and record data in this mod.\n")); - else if (modifiedgame) + else if (/*modifiedgame*/ majormods) CONS_Printf(M_GetText("modifiedgame is true, extras will not be unlocked\n")); else CONS_Printf(M_GetText("modifiedgame is false, you can unlock extras\n")); diff --git a/src/dehacked.c b/src/dehacked.c index e7e1ae69..49d9d107 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -3417,18 +3417,21 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad) if (fastcmp(word, "FREESLOT")) { readfreeslots(f); + majormods = true; continue; } else if (fastcmp(word, "MAINCFG")) { readmaincfg(f); DEH_WriteUndoline(word, "", UNDO_HEADER); + majormods = true; continue; } else if (fastcmp(word, "WIPES")) { readwipes(f); DEH_WriteUndoline(word, "", UNDO_HEADER); + //majormods = true; continue; } word2 = strtok(NULL, " "); @@ -3449,6 +3452,7 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad) ignorelines(f); } DEH_WriteUndoline(word, word2, UNDO_HEADER); + //majormods = true; continue; } if (word2) @@ -3462,12 +3466,14 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad) // Read texture from spec file. readtexture(f, word2); DEH_WriteUndoline(word, word2, UNDO_HEADER); + //majormods = true; } else if (fastcmp(word, "PATCH")) { // Read patch from spec file. readpatch(f, word2, wad); DEH_WriteUndoline(word, word2, UNDO_HEADER); + //majormods = true; } else if (fastcmp(word, "THING") || fastcmp(word, "MOBJ") || fastcmp(word, "OBJECT")) { @@ -3481,10 +3487,12 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad) ignorelines(f); } DEH_WriteUndoline(word, word2, UNDO_HEADER); + majormods = true; } /* else if (fastcmp(word, "ANIMTEX")) { readAnimTex(f, i); + //majormods = true; }*/ else if (fastcmp(word, "LIGHT")) { @@ -3498,6 +3506,7 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad) ignorelines(f); } DEH_WriteUndoline(word, word2, UNDO_HEADER); + //majormods = true; #endif } else if (fastcmp(word, "SPRITE")) @@ -3513,6 +3522,7 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad) ignorelines(f); } DEH_WriteUndoline(word, word2, UNDO_HEADER); + //majormods = true; #endif } else if (fastcmp(word, "LEVEL")) @@ -3525,7 +3535,11 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad) i = M_MapNumber(word2[0], word2[1]); if (i > 0 && i <= NUMMAPS) + { + if (mapheaderinfo[i]) + majormods = true; // only mark as a major mod if it replaces an already-existing mapheaderinfo readlevelheader(f, i); + } else { deh_warning("Level number %d out of range (1 - %d)", i, NUMMAPS); @@ -3543,6 +3557,7 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad) ignorelines(f); } DEH_WriteUndoline(word, word2, UNDO_HEADER); + //majormods = true; -- might have to reconsider in a future update } else if (fastcmp(word, "FRAME") || fastcmp(word, "STATE")) { @@ -3556,6 +3571,7 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad) ignorelines(f); } DEH_WriteUndoline(word, word2, UNDO_HEADER); + majormods = true; } // Added translations to this just in case its re-enabled /* else if (fastcmp(word, "POINTER")) @@ -3578,6 +3594,7 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad) } else deh_warning("pointer (Frame %d) : missing ')'", i); + majormods = true; }*/ else if (fastcmp(word, "SOUND")) { @@ -3591,6 +3608,7 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad) ignorelines(f); } DEH_WriteUndoline(word, word2, UNDO_HEADER); + //majormods = true; -- ...this won't bite me in the ass later, will it? } /* else if (fastcmp(word, "SPRITE")) { @@ -3611,6 +3629,7 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad) } else deh_warning("Sprite %d doesn't exist",i); + //majormods = true; }*/ else if (fastcmp(word, "HUDITEM")) { @@ -3624,6 +3643,7 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad) ignorelines(f); } DEH_WriteUndoline(word, word2, UNDO_HEADER); + //majormods = true; } else if (fastcmp(word, "EMBLEM")) { @@ -3644,6 +3664,7 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad) ignorelines(f); } DEH_WriteUndoline(word, word2, UNDO_HEADER); + majormods = true; } else if (fastcmp(word, "EXTRAEMBLEM")) { @@ -3664,6 +3685,7 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad) ignorelines(f); } DEH_WriteUndoline(word, word2, UNDO_HEADER); + majormods = true; } else if (fastcmp(word, "UNLOCKABLE")) { @@ -3680,6 +3702,7 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad) ignorelines(f); } DEH_WriteUndoline(word, word2, UNDO_HEADER); + majormods = true; } else if (fastcmp(word, "CONDITIONSET")) { @@ -3697,6 +3720,7 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad) } // no undo support for this insanity yet //DEH_WriteUndoline(word, word2, UNDO_HEADER); + majormods = true; } else if (fastcmp(word, "SRB2KART")) { @@ -3743,6 +3767,8 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad) if (clearall || fastcmp(word2, "LEVELS")) clear_levels(); + + majormods = true; } else deh_warning("Unknown word: %s", word); @@ -9737,7 +9763,7 @@ static inline int lib_getenum(lua_State *L) lua_pushboolean(L, devparm); return 1; } else if (fastcmp(word,"modifiedgame")) { - lua_pushboolean(L, modifiedgame && !savemoddata); + lua_pushboolean(L, /*modifiedgame*/ majormods && !savemoddata); return 1; } else if (fastcmp(word,"menuactive")) { lua_pushboolean(L, menuactive); diff --git a/src/doomstat.h b/src/doomstat.h index 6d710e28..9ae2726d 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -54,6 +54,7 @@ extern boolean gamecomplete; // Set if homebrew PWAD stuff has been added. extern boolean modifiedgame; +extern boolean majormods; extern UINT16 mainwads; extern boolean savemoddata; // This mod saves time/emblem data. extern boolean disableSpeedAdjust; // Don't alter the duration of player states if true @@ -280,6 +281,8 @@ typedef struct #define LF2_NIGHTSATTACK 8 ///< Show this map in NiGHTS mode menu #define LF2_NOVISITNEEDED 16 ///< Available in time attack/nights mode without visiting the level +#define LF2_EXISTSHACK 128 ///< Map lump exists; as noted, a single-bit hack that can be freely movable to other variables without concern. + // Save override #define SAVE_NEVER -1 #define SAVE_DEFAULT 0 diff --git a/src/g_game.c b/src/g_game.c index 1e0c7e46..28171e75 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -86,7 +86,8 @@ INT16 lastmapsaved = 0; // Last map we auto-saved at boolean gamecomplete = false; UINT16 mainwads = 0; -boolean modifiedgame; // Set if homebrew PWAD stuff has been added. +boolean modifiedgame = false; // Set if homebrew PWAD stuff has been added. +boolean majormods = false; // Set if Lua/Gameplay SOC/replacement map has been added. boolean savemoddata = false; UINT8 paused; UINT8 modeattacking = ATTACKING_NONE; @@ -5918,6 +5919,19 @@ void G_DoPlayDemo(char *defdemoname) return; } + // Skin not loaded? + if (!SetPlayerSkin(0, skin)) + { + snprintf(msg, 1024, M_GetText("%s features a character that is not loaded.\n"), pdemoname); + CONS_Alert(CONS_ERROR, "%s", msg); + M_StartMessage(msg, NULL, MM_NOTHING); + Z_Free(pdemoname); + Z_Free(demobuffer); + demoplayback = false; + titledemo = false; + return; + } + Z_Free(pdemoname); memset(&oldcmd,0,sizeof(oldcmd)); @@ -5949,9 +5963,6 @@ void G_DoPlayDemo(char *defdemoname) P_SetRandSeed(randseed); G_InitNew(false, G_BuildMapName(gamemap), true, true); // Doesn't matter whether you reset or not here, given changes to resetplayer. - // Set skin - SetPlayerSkin(0, skin); - // Set color for (i = 0; i < MAXSKINCOLORS; i++) if (!stricmp(KartColor_Names[i],color)) // SRB2kart @@ -6146,6 +6157,22 @@ void G_AddGhost(char *defdemoname) return; } + gh->oldmo->skin = &skins[0]; + for (i = 0; i < numskins; i++) + if (!stricmp(skins[i].name,skin)) + { + gh->oldmo->skin = &skins[i]; + break; + } + + if (i == numskins) + { + CONS_Alert(CONS_NOTICE, M_GetText("Failed to add ghost %s: Invalid character.\n"), pdemoname); + Z_Free(pdemoname); + Z_Free(buffer); + return; + } + gh = Z_Calloc(sizeof(demoghost), PU_LEVEL, NULL); gh->next = ghosts; gh->buffer = buffer; @@ -6191,14 +6218,7 @@ void G_AddGhost(char *defdemoname) gh->oldmo.z = gh->mo->z; // Set skin - gh->mo->skin = &skins[0]; - for (i = 0; i < numskins; i++) - if (!stricmp(skins[i].name,skin)) - { - gh->mo->skin = &skins[i]; - break; - } - gh->oldmo.skin = gh->mo->skin; + gh->mo.skin = gh->oldmo->skin; // Set color gh->mo->color = ((skin_t*)gh->mo->skin)->prefcolor; diff --git a/src/lua_script.c b/src/lua_script.c index 34a26052..d7c4a160 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -212,6 +212,9 @@ void LUA_LoadLump(UINT16 wad, UINT16 lump) LUA_LoadFile(&f, name); // actually load file! + // Okay, we've modified the game beyond the point of no return. + majormods = true; + free(name); Z_Free(f.data); } diff --git a/src/m_cheat.c b/src/m_cheat.c index 9c53f901..499dac28 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -1268,6 +1268,7 @@ void Command_ObjectPlace_f(void) REQUIRE_NOULTIMATE; G_SetGameModified(multiplayer); + majormods = true; // Entering objectplace? if (!objectplacing) diff --git a/src/m_cond.c b/src/m_cond.c index 35eccd1c..b0e49a68 100644 --- a/src/m_cond.c +++ b/src/m_cond.c @@ -385,7 +385,7 @@ UINT8 M_UpdateUnlockablesAndExtraEmblems(boolean force) char cechoText[992] = ""; UINT8 cechoLines = 0; - if (modifiedgame && !savemoddata + if (/*modifiedgame*/ majormods && !savemoddata && !force) // SRB2Kart: for enabling unlocks online in modified servers return false; diff --git a/src/m_menu.c b/src/m_menu.c index 8c0e6079..03cc8002 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -2773,10 +2773,10 @@ boolean M_Responder(event_t *ev) || (currentMenu->menuitems[itemOn].status & IT_TYPE)==IT_SUBMENU) && (currentMenu->menuitems[itemOn].status & IT_CALLTYPE)) { - if (((currentMenu->menuitems[itemOn].status & IT_CALLTYPE) & IT_CALL_NOTMODIFIED) && modifiedgame && !savemoddata) + if (((currentMenu->menuitems[itemOn].status & IT_CALLTYPE) & IT_CALL_NOTMODIFIED) && /*modifiedgame*/ majormods && !savemoddata) { S_StartSound(NULL, sfx_menu1); - M_StartMessage(M_GetText("This cannot be done with add-ons\nor in a cheated game.\n\n(Press a key)\n"), NULL, MM_NOTHING); + M_StartMessage(M_GetText("This cannot be done with complex add-ons\nor in a cheated game.\n\n(Press a key)\n"), NULL, MM_NOTHING); return true; } } diff --git a/src/p_setup.c b/src/p_setup.c index 49b22184..0a59a2a9 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -234,7 +234,7 @@ static void P_ClearSingleMapHeaderInfo(INT16 i) DEH_WriteUndoline("LEVELFLAGS", va("%d", mapheaderinfo[num]->levelflags), UNDO_NONE); mapheaderinfo[num]->levelflags = 0; DEH_WriteUndoline("MENUFLAGS", va("%d", mapheaderinfo[num]->menuflags), UNDO_NONE); - mapheaderinfo[num]->menuflags = 0; + mapheaderinfo[num]->menuflags = (mainwads ? 0 : LF2_EXISTSHACK); // see p_setup.c - prevents replacing maps in addons with easier versions // TODO grades support for delfile (pfft yeah right) P_DeleteGrades(num); // SRB2Kart @@ -1120,7 +1120,7 @@ static inline void P_SpawnEmblems(void) static void P_SpawnSecretItems(boolean loademblems) { // Now let's spawn those funky emblem things! Tails 12-08-2002 - if (netgame || multiplayer || (modifiedgame && !savemoddata)) // No cheating!! + if (netgame || multiplayer || (/*modifiedgame*/ majormods && !savemoddata)) // No cheating!! return; if (loademblems) @@ -3272,7 +3272,7 @@ boolean P_SetupLevel(boolean skipprecip) nextmapoverride = 0; skipstats = false; - if (!(netgame || multiplayer) && (!modifiedgame || savemoddata)) + if (!(netgame || multiplayer) && (/*!modifiedgame*/ !majormods || savemoddata)) mapvisited[gamemap-1] |= MV_VISITED; levelloading = false; @@ -3455,6 +3455,14 @@ boolean P_AddWadFile(const char *wadfilename) continue; num = (INT16)M_MapNumber(name[3], name[4]); + // we want to record whether this map exists. if it doesn't have a header, we can assume it's not relephant + if (num <= NUMMAPS && mapheaderinfo[num-1]) + { + if (mapheaderinfo[num-1]->menuflags & LF2_EXISTSHACK) + majormods = true; // oops, double-defined - no record attack privileges for you + mapheaderinfo[num-1]->menuflags |= LF2_EXISTSHACK; + } + //If you replaced the map you're on, end the level when done. if (num == gamemap) replacedcurrentmap = true; diff --git a/src/r_things.c b/src/r_things.c index 1825d2d9..a4720063 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -2635,7 +2635,7 @@ INT32 R_SkinAvailable(const char *name) } // network code calls this when a 'skin change' is received -void SetPlayerSkin(INT32 playernum, const char *skinname) +boolean SetPlayerSkin(INT32 playernum, const char *skinname) { INT32 i; player_t *player = &players[playernum]; @@ -2646,7 +2646,7 @@ void SetPlayerSkin(INT32 playernum, const char *skinname) if (stricmp(skins[i].name, skinname) == 0) { SetPlayerSkinByNum(playernum, i); - return; + return true; } } @@ -2656,6 +2656,7 @@ void SetPlayerSkin(INT32 playernum, const char *skinname) CONS_Alert(CONS_WARNING, M_GetText("Player %d (%s) skin '%s' not found\n"), playernum, player_names[playernum], skinname); SetPlayerSkinByNum(playernum, 0); + return false; } // Same as SetPlayerSkin, but uses the skin #. diff --git a/src/r_things.h b/src/r_things.h index a8635034..bc51f711 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -194,7 +194,7 @@ typedef struct drawnode_s extern INT32 numskins; extern skin_t skins[MAXSKINS + 1]; -void SetPlayerSkin(INT32 playernum,const char *skinname); +boolean SetPlayerSkin(INT32 playernum,const char *skinname); void SetPlayerSkinByNum(INT32 playernum,INT32 skinnum); // Tails 03-16-2002 INT32 R_SkinAvailable(const char *name); void R_AddSkins(UINT16 wadnum); diff --git a/src/y_inter.c b/src/y_inter.c index 021519e3..046d6d6d 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -786,7 +786,7 @@ void Y_StartIntermission(void) } case int_race: // (time-only race) { - if ((!modifiedgame || savemoddata) && !multiplayer && !demoplayback) // remove this once we have a proper time attack screen + if ((/*!modifiedgame*/ !majormods || savemoddata) && !multiplayer && !demoplayback) // remove this once we have a proper time attack screen { // Update visitation flags mapvisited[gamemap-1] |= MV_BEATEN;