From 7838c2311f2fd250be342d1ea2177e410674da09 Mon Sep 17 00:00:00 2001 From: yamamama Date: Sun, 30 Nov 2025 19:57:55 -0500 Subject: [PATCH] Fix up some bugs introduced --- src/d_netcmd.c | 27 +++++++++++++++++++++++---- src/g_demo.c | 21 +++++++-------------- src/lua_mobjlib.c | 4 +++- src/p_mobj.c | 10 +++++++++- src/p_saveg.c | 2 +- src/r_skins.c | 28 ++++++++++++++++++++++------ src/r_skins.h | 2 ++ 7 files changed, 67 insertions(+), 27 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 039864f98..ab842f5e7 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -2001,10 +2001,10 @@ static void SendNameAndColor(UINT8 n) // Need to update voices after the fact. if (!cv_voice[n].string) { - CV_StealthSet(&cv_voice[n], skins[player->skin].voices[0].name); + CV_StealthSet(&cv_voice[n], skins[cv_skin[n].value].voices[0].name); } - if (R_FindIDForVoice(&skins[player->skin], cv_voice[n].string) == MAXSKINVOICES) + if (R_FindIDForVoice(&skins[cv_skin[n].value], cv_voice[n].string) == MAXSKINVOICES) { // In the chance our current voice isn't valid, // rescan our current voice and send that over the network. @@ -2018,7 +2018,7 @@ static void SendNameAndColor(UINT8 n) { // Get the voice from our ID. // No need to compare parents. - valuevoice = &skins[player->skin].voices[player->voice_id]; + valuevoice = &skins[cv_skin[n].value].voices[player->voice_id]; if (valuevoice) { @@ -2027,11 +2027,24 @@ static void SendNameAndColor(UINT8 n) else { // ...still nothing? - CV_StealthSet(&cv_voice[n], skins[player->skin].voices[0].name); + CV_StealthSet(&cv_voice[n], skins[cv_skin[n].value].voices[0].name); } } } + // After EVERYTHING, do one last check on our voice so we can set the value. + INT32 cvar_voxid = R_FindIDForVoice(&skins[cv_skin[n].value], cv_voice[n].string); + + if (cvar_voxid == MAXSKINVOICES) + { + // ...huh?! Reset to the default. + cv_voice[n].value = 0; + } + else + { + cv_voice[n].value = cvar_voxid; + } + // Finally write out the complete packet and send it off. WRITESTRINGN(p, cv_playername[n].zstring, MAXPLAYERNAME); WRITEUINT32(p, (UINT32)player->availabilities); @@ -7416,6 +7429,12 @@ static void Color4_OnChange(void) static void __voice_cvar_func(INT32 pid, UINT8 pnum) { + if (!numskins) + { + // There aren't even any skins yet! + return; + } + kartvoice_t *myvoice = P_GetMobjVoice(players[pid].mo); if (!myvoice) diff --git a/src/g_demo.c b/src/g_demo.c index 5a98929d9..c0ce6774a 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -1279,17 +1279,9 @@ void G_ReadDemoExtraData(void) players[p].voice_id = (UINT16)vce; } - if (skins[players[p].skin].voices[players[p].voice_id].id == 0) + if (!P_MobjWasRemoved(players[p].mo)) { - // Default voice for this skin. Just strip the object of its voice. - players[p].mo->voice = NULL; - } - else if (skins[players[p].skin].voices[players[p].voice_id].id != - skins[players[p].skin].voices[0].id && - !P_MobjWasRemoved(players[p].mo)) - { - // This player's mobj exists, and their voice is valid, and isn't - // the default. So, attach the voice to the mobj! + // This player's mobj exists. So, attach the voice to the mobj! players[p].mo->voice = &skins[players[p].skin].voices[players[p].voice_id]; } @@ -2105,7 +2097,7 @@ void G_GhostTicker(void) { default: case GHC_RETURNSKIN: - g->mo->skin = g->oldmo.skin; + R_ApplySkin(g->mo, g->oldmo.skin); /* FALLTHRU */ case GHC_NORMAL: // Go back to skin color g->mo->color = g->oldmo.color; @@ -2166,7 +2158,7 @@ void G_GhostTicker(void) fmo->colorized = true; if (zt.followflags & FZT_SKIN) - fmo->skin = &skins[zt.follow.skin]; + R_ApplySkin(fmo, &skins[zt.follow.skin]); } if (fmo) { @@ -2569,7 +2561,7 @@ void G_ReadMetalTic(mobj_t *metal) follow->colorized = true; if (followtic & FZT_SKIN) - follow->skin = &skins[READUINT8(metal_p)]; + R_ApplySkin(follow, &skins[READUINT8(metal_p)]); } if (follow) { @@ -4124,7 +4116,8 @@ void G_AddGhost(char *defdemoname) gh->mo->tics = -1; // Set skin - gh->mo->skin = gh->oldmo.skin = ghskin; + R_ApplySkin(&gh->oldmo, ghskin); + R_ApplySkin(gh->mo, gh->oldmo.skin); // Set color gh->mo->color = ((skin_t*)gh->mo->skin)->prefcolor; diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index 3c7d03c71..ec47bcfba 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -894,7 +894,9 @@ static int mobj_set(lua_State *L) if (fastcmp(skins[i].name, skin)) { if (!mo->player || R_SkinUsable(mo->player-players, i)) - mo->skin = &skins[i]; + { + R_ApplySkin(mo, &skins[i]); + } return 0; } return luaL_error(L, "mobj.skin '%s' not found!", skin); diff --git a/src/p_mobj.c b/src/p_mobj.c index d71f3cfa4..c7c226b14 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -12378,7 +12378,7 @@ void P_SpawnPlayer(INT32 playernum) // set 'spritedef' override in mobj for player skins.. (see ProjectSprite) // (usefulness: when body mobj is detached from player (who respawns), // the dead body mobj retains the skin through the 'spritedef' override). - mobj->skin = &skins[p->skin]; + R_ApplySkin(mobj, &skins[p->skin]); P_SetupStateAnimation(mobj, mobj->state); if (p->voice_id) @@ -14979,12 +14979,20 @@ kartvoice_t *P_GetMobjVoice(const mobj_t *mo) { return mo->voice; } +#ifdef PARANOIA + else + { + I_Error("P_GetMobjVoice: This object has no voice!"); + return NULL; + } +#else else if (mo->skin) { return &((skin_t *)mo->skin)->voices[0]; } return NULL; +#endif } // diff --git a/src/p_saveg.c b/src/p_saveg.c index 7874caebd..a9dade76e 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -2224,7 +2224,7 @@ static thinker_t *SyncMobjThinker(savebuffer_t *save, actionf_p1 thinker, thinke if (save->write) WRITEUINT16(save->p, (UINT16)((skin_t *)mobj->skin - skins)); else - mobj->skin = &skins[READUINT16(save->p)]; + R_ApplySkin(mobj, &skins[READUINT16(save->p)]); } SYNCF(MD2_COLOR, mobj->color); SYNCF(MD2_EXTVAL1, mobj->extravalue1); diff --git a/src/r_skins.c b/src/r_skins.c index 98d07057b..e3c6bc183 100644 --- a/src/r_skins.c +++ b/src/r_skins.c @@ -675,13 +675,8 @@ void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum) if (player->mo) { - player->mo->skin = skin; + R_ApplySkin(player->mo, skin); - if (player->mo->voice) - { - // Clear out the voice pointer, so we can fall back to using skin voices. - player->mo->voice = NULL; - } P_SetScale(player->mo, player->mo->scale); P_SetPlayerMobjState(player->mo, player->mo->state-states); // Prevent visual errors when switching between skins with differing number of frames } @@ -772,6 +767,27 @@ void SetPlayerVoiceByNum(INT32 playernum, UINT16 voicenum) demo_extradata[playernum] |= DXD_SKIN; } +/** \brief Applies the skin and its default voice. + + \param mo (mobj_t) the given object the skin and voice are being assigned to + \param skin (skin_t) the skin to attach to the object. The voice is sourced from this skin +*/ +void R_ApplySkin(mobj_t *mo, skin_t *skin) +{ + mo->skin = skin; + mo->voice = &((skin_t *)mo->skin)->voices[0]; +} + +/** \brief Applies only the skin. + + \param mo (mobj_t) the given object the skin is being assigned to + \param skin (skin_t) the skin to attach to the object +*/ +void R_ApplySkinOnly(mobj_t *mo, skin_t *skin) +{ + mo->skin = skin; +} + // // Add skins from a pwad, each skin preceded by 'S_SKIN' marker // diff --git a/src/r_skins.h b/src/r_skins.h index f7d9a323c..9c4bc2d47 100644 --- a/src/r_skins.h +++ b/src/r_skins.h @@ -144,6 +144,8 @@ UINT32 R_GetSkinAvailabilities(void); INT32 R_SkinAvailable(const char *name); void R_PatchSkins(UINT16 wadnum); void R_AddSkins(UINT16 wadnum); +void R_ApplySkin(mobj_t *mo, skin_t *skin); +void R_ApplySkinOnly(mobj_t *mo, skin_t *skin); UINT8 P_GetSkinSprite2(skin_t *skin, UINT8 spr2, player_t *player); UINT8 P_KartFrameToSprite2(skin_t *skin, UINT8 inframe, UINT8 *outframe);