Consolidate voice allocation

Skin voices and freeslot voices are no longer separated, with all voices allocating as skin voices would prior.
Due to this, skin voice allocation has been refactored a bit:
- No longer relies on a name string, instead using Dehacked name info hashes and string offsets
- Name string checks now check the voice's Dehacked name; the skin 'tails' will allocate KVOICE_TAILS, and so on
- Overall refactors to fit this new system
This commit is contained in:
yamamama 2025-11-15 09:34:44 -05:00
parent 0625e92dc1
commit e0d4a8e385
9 changed files with 191 additions and 192 deletions

View file

@ -1406,6 +1406,7 @@ static UINT8 Skin_FindValidDub(consvar_t *cvar, UINT16 skin_id, kartvoice_t *voi
int i;
const char *value = cvar->string;
kartvoice_t *myvoice = voice;
char cvarname[VOICENAMESIZE+1];
if (!Playing())
{
@ -1424,66 +1425,43 @@ static UINT8 Skin_FindValidDub(consvar_t *cvar, UINT16 skin_id, kartvoice_t *voi
}
}
// First, check for freeslotted voices, should they exist at all.
if (numfreeslotvoices)
// Scan through our allocated skin voices for the wanted voice.
strncpy(cvarname, value, VOICENAMESIZE);
strupr(cvarname);
i = DEH_FindVoice(cvarname);
if (i != MAXSKINVOICES)
{
for (i = 0; i < numfreeslotvoices; i++)
// Make sure this voice belongs to the skin we're about to assign it to.
if (skinvoices[i].parent == skin_id || forceme)
{
if (strncmp(value, skinvoices[i + KSKVC_FIRSTFREESLOT].name, sizeof skinvoices[i + KSKVC_FIRSTFREESLOT].name) == 0)
{
// Make sure this voice belongs to the skin we're about to assign it to.
if (skinvoices[i + KSKVC_FIRSTFREESLOT].parent == skin_id || forceme)
{
// Change the cvar to be the value of the name.
CV_StealthSet(cvar, skinvoices[i + KSKVC_FIRSTFREESLOT].name);
cvar->value = skinvoices[i + KSKVC_FIRSTFREESLOT].id;
}
else
{
// This isn't a valid voice for this skin, so don't assign shit.
if (!silent)
CONS_Alert(CONS_NOTICE, M_GetText("Voice \"%s\" doesn't belong to this skin (%s).\n"), skinvoices[i + KSKVC_FIRSTFREESLOT].name, skins[skin_id].name);
// Change the cvar to be the value of the name.
strncpy(cvarname, DEH_VoiceName(i), VOICENAMESIZE);
strlwr(cvarname);
// *Reassign* the voice to whatever the current voice is, at least.
CV_StealthSet(cvar, myvoice->name);
cvar->value = myvoice->id;
return 1;
}
// Return regardless, as we've found the voice we were looking for.
return 0;
}
CV_StealthSet(cvar, cvarname);
cvar->value = skinvoices[i].id;
}
}
// Freeslotted voices don't exist or found nothing; check skin voices.
for (i = 0; i < numskinvoices; i++)
{
// Whatever. Go, my code duplication!
if (strncmp(value, skinvoices[i].name, sizeof skinvoices[i].name) == 0)
else
{
// Make sure this voice belongs to the skin we're about to assign it to.
if (skinvoices[i].parent == skin_id || forceme)
{
// Change the cvar to be the value of the name.
CV_StealthSet(cvar, skinvoices[i].name);
cvar->value = skinvoices[i].id;
}
else
{
// This isn't a valid voice for this skin, so don't assign shit.
if (!silent)
CONS_Alert(CONS_NOTICE, M_GetText("Voice \"%s\" doesn't belong to this skin (%s).\n"), skinvoices[i].name, skins[skin_id].name);
// This isn't a valid voice for this skin, so don't assign shit.
if (!silent)
CONS_Alert(CONS_NOTICE, M_GetText("Voice \"%s\" doesn't belong to this skin (%s).\n"), DEH_VoiceName(i), skins[skin_id].name);
// *Reassign* the voice cvar to whatever the current voice is, at least.
CV_StealthSet(cvar, myvoice->name);
cvar->value = myvoice->id;
return 1;
}
// *Reassign* the voice cvar to whatever the current voice is, at least.
strncpy(cvarname, DEH_VoiceName(myvoice->id), VOICENAMESIZE);
strlwr(cvarname);
// Return regardless, as we've found the voice we were looking for.
return 0;
CV_StealthSet(cvar, cvarname);
cvar->value = myvoice->id;
// Signal to networking that we failed to set a voice.
return 1;
}
// We've found the voice we were looking for!
return 0;
}
// Found diddly-squat, say as much.
@ -1491,8 +1469,13 @@ static UINT8 Skin_FindValidDub(consvar_t *cvar, UINT16 skin_id, kartvoice_t *voi
CONS_Alert(CONS_NOTICE, M_GetText("Voice \"%s\" does not exist.\n"), value);
// Reassign the voice cvar to our current voice.
CV_StealthSet(cvar, myvoice->name);
strncpy(cvarname, DEH_VoiceName(myvoice->id), VOICENAMESIZE);
strlwr(cvarname);
CV_StealthSet(cvar, cvarname);
cvar->value = myvoice->id;
// Signal to networking that we failed to set a voice.
return 1;
}
@ -1859,6 +1842,7 @@ static void SendNameAndColor(UINT8 n)
boolean permamute = false;
char buf[MAXPLAYERNAME+12];
char voicebuf[VOICENAMESIZE+1];
char *p;
if (splitscreen < n)
@ -1912,7 +1896,7 @@ static void SendNameAndColor(UINT8 n)
&& !strcmp(cv_skin[n].string, skins[player->skin].name)
&& cv_follower[n].value == player->followerskin
&& cv_followercolor[n].value == player->followercolor
&& (!permamute && !strcmp(cv_voice[n].string, voice->name)))
&& (!permamute && !stricmp(cv_voice[n].string, DEH_VoiceName(voice->id))))
return;
player->availabilities = R_GetSkinAvailabilities();
@ -1955,7 +1939,10 @@ static void SendNameAndColor(UINT8 n)
// Reset the voice to that of the skin's.
if (prevskin != player->skin && skins[player->skin].voice)
{
CV_StealthSet(&cv_voice[n], skins[player->skin].voice->name);
strncpy(voicebuf, DEH_VoiceName(skins[player->skin].voice->id), VOICENAMESIZE);
strlwr(voicebuf);
CV_StealthSet(&cv_voice[n], voicebuf);
cv_voice[n].value = (UINT16)skins[player->skin].voice->id;
}
}
@ -1971,14 +1958,22 @@ static void SendNameAndColor(UINT8 n)
// Reset the voice to that of the skin's.
if (prevskin != player->skin && skins[player->skin].voice)
{
CV_StealthSet(&cv_voice[n], skins[player->skin].voice->name);
strncpy(voicebuf, DEH_VoiceName(skins[player->skin].voice->id), VOICENAMESIZE);
strlwr(voicebuf);
CV_StealthSet(&cv_voice[n], voicebuf);
cv_voice[n].value = (UINT16)skins[player->skin].voice->id;
}
}
// Need to update voices after the fact.
if (!cv_voice[n].string)
CV_StealthSet(&cv_voice[n], skins[player->skin].voice->name);
{
strncpy(voicebuf, DEH_VoiceName(skins[player->skin].voice->id), VOICENAMESIZE);
strlwr(voicebuf);
CV_StealthSet(&cv_voice[n], voicebuf);
}
SetPlayerVoice(playernum, cv_voice[n].string);
@ -1986,7 +1981,10 @@ static void SendNameAndColor(UINT8 n)
if (valuevoice)
{
CV_StealthSet(&cv_voice[n], valuevoice->name);
strncpy(voicebuf, DEH_VoiceName(valuevoice->id), VOICENAMESIZE);
strlwr(voicebuf);
CV_StealthSet(&cv_voice[n], voicebuf);
cv_voice[n].value = (UINT16)valuevoice->id;
}
else
@ -1996,13 +1994,19 @@ static void SendNameAndColor(UINT8 n)
if (valuevoice)
{
CV_StealthSet(&cv_voice[n], valuevoice->name);
strncpy(voicebuf, DEH_VoiceName(valuevoice->id), VOICENAMESIZE);
strlwr(voicebuf);
CV_StealthSet(&cv_voice[n], voicebuf);
cv_voice[n].value = (UINT16)valuevoice->id;
}
else
{
// ...still nothing?
CV_StealthSet(&cv_voice[n], "sonic_voice");
strncpy(voicebuf, DEH_VoiceName(0), VOICENAMESIZE);
strlwr(voicebuf);
CV_StealthSet(&cv_voice[n], voicebuf);
cv_voice[n].value = 0;
}
}
@ -2031,7 +2035,10 @@ static void SendNameAndColor(UINT8 n)
if (Skin_FindValidDub(&cv_voice[n], cv_skin[n].value, voice, false, true))
{
// Our voice is no longer valid, set it to that of our skin's.
CV_StealthSet(&cv_voice[n], skins[player->skin].voice->name);
strncpy(voicebuf, DEH_VoiceName(skins[player->skin].voice->id), VOICENAMESIZE);
strlwr(voicebuf);
CV_StealthSet(&cv_voice[n], voicebuf);
cv_voice[n].value = skins[player->skin].voice->id;
}
}
@ -2050,7 +2057,12 @@ 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].voice->name);
{
strncpy(voicebuf, DEH_VoiceName(skins[player->skin].voice->id), VOICENAMESIZE);
strlwr(voicebuf);
CV_StealthSet(&cv_voice[n], voicebuf);
}
if (!permamute)
{
@ -2062,7 +2074,10 @@ static void SendNameAndColor(UINT8 n)
if (valuevoice && valuevoice->parent == cv_skin[n].value)
{
CV_StealthSet(&cv_voice[n], valuevoice->name);
strncpy(voicebuf, DEH_VoiceName(valuevoice->id), VOICENAMESIZE);
strlwr(voicebuf);
CV_StealthSet(&cv_voice[n], voicebuf);
cv_voice[n].value = (UINT16)valuevoice->id;
}
else
@ -2072,13 +2087,19 @@ static void SendNameAndColor(UINT8 n)
if (valuevoice)
{
CV_StealthSet(&cv_voice[n], valuevoice->name);
strncpy(voicebuf, DEH_VoiceName(valuevoice->id), VOICENAMESIZE);
strlwr(voicebuf);
CV_StealthSet(&cv_voice[n], voicebuf);
cv_voice[n].value = (UINT16)valuevoice->id;
}
else
{
// ...still nothing?
CV_StealthSet(&cv_voice[n], "sonic_voice");
strncpy(voicebuf, DEH_VoiceName(0), VOICENAMESIZE);
strlwr(voicebuf);
CV_StealthSet(&cv_voice[n], voicebuf);
cv_voice[n].value = 0;
}
}
@ -2101,6 +2122,7 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum)
{
player_t *p = &players[playernum];
char name[MAXPLAYERNAME+1];
char voicename[VOICENAMESIZE+1];
UINT16 color, followercolor;
UINT16 skin, voice;
SINT8 follower;
@ -2212,7 +2234,10 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum)
{
CV_StealthSet(&cv_skin[localplayer], skins[forcedskin].name);
CV_StealthSet(&cv_voice[localplayer], skins[forcedskin].voice->name);
strncpy(voicename, DEH_VoiceName(skins[forcedskin].voice->id), VOICENAMESIZE);
strlwr(voicename);
CV_StealthSet(&cv_voice[localplayer], voicename);
cv_voice[localplayer].value = skins[forcedskin].voice->id;
}
@ -2228,7 +2253,10 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum)
if (localplayer != -1)
{
CV_StealthSet(&cv_voice[localplayer], skinvoices[voice].name);
strncpy(voicename, DEH_VoiceName(voice), VOICENAMESIZE);
strlwr(voicename);
CV_StealthSet(&cv_voice[localplayer], voicename);
cv_voice[localplayer].value = skinvoices[voice].id;
}
}
@ -7472,6 +7500,8 @@ static void Color4_OnChange(void)
static void __voice_cvar_func(INT32 pid, UINT8 pnum)
{
char cvarname[VOICENAMESIZE+1];
kartvoice_t *myvoice = P_GetMobjVoice(players[pid].mo);
if (!myvoice)
@ -7498,7 +7528,11 @@ static void __voice_cvar_func(INT32 pid, UINT8 pnum)
if (!(cht_debug || devparm) && !(multiplayer || netgame) // In single player.
&& (gamestate != GS_WAITINGPLAYERS)) // allows command line -warp x +skin y
{
CV_StealthSet(&cv_voice[pnum], myvoice->name);
strncpy(cvarname, DEH_VoiceName(myvoice->id), VOICENAMESIZE);
strlwr(cvarname);
CV_StealthSet(&cv_voice[pnum], cvarname);
cv_voice[pnum].value = myvoice->id;
return;
}
}
@ -7508,7 +7542,12 @@ static void __voice_cvar_func(INT32 pid, UINT8 pnum)
else
{
CONS_Alert(CONS_NOTICE, M_GetText("You can't change your voice at the moment.\n"));
CV_StealthSet(&cv_voice[pnum], myvoice->name);
strncpy(cvarname, DEH_VoiceName(myvoice->id), VOICENAMESIZE);
strlwr(cvarname);
CV_StealthSet(&cv_voice[pnum], cvarname);
cv_voice[pnum].value = myvoice->id;
}
}

View file

@ -4316,23 +4316,7 @@ void readkartvoice(MYFILE *f, kartvoice_t *voice)
word2 = (tmp += 2);
strupr(word2);
if (fastcmp(word, "NAME"))
{
strlwr(word2);
// Catch any voices with similar names.
for (i = KSKVC_FIRSTFREESLOT; i < MAXSKINVOICES; i++)
{
if (strnicmp(word2, skinvoices[i].name, sizeof skinvoices[i].name) == 0)
{
// Name collision!
// Append the ID to differentiate... poorly.
snprintf(word2, sizeof voice->name, "%u_%s", voice->id, skinvoices[i].name);
}
}
strncpy(voice->name, word2, sizeof voice->name);
CONS_Printf("KartVoice %s: renamed to \"%s\"\n", strbuf_get(voicenames, voice->info.nameofs), voice->name);
}
else if (fastcmp(word, "SKIN"))
if (fastcmp(word, "SKIN"))
{
i = R_SkinAvailable(word2);
@ -4395,6 +4379,9 @@ void readkartvoice(MYFILE *f, kartvoice_t *voice)
}
while (!myfeof(f)); // finish when the line is empty
// Set our ID afterwards.
voice->id = (UINT32)(voice - skinvoices);
Z_Free(s);
}
@ -4587,7 +4574,7 @@ kartvoicetype_e get_kartvoice(const char *word)
if (fastncmp("KVOICE_",word,7))
word += 7; // take off the KVOICE_
i = DEH_FindVoice(word);
if (i == MAXVOICEFREESLOTS)
if (i == MAXSKINVOICES)
deh_warning("Couldn't find voice named 'KVOICE_%s'", word);
return i;
}

View file

@ -71,7 +71,7 @@ const char *DEH_KartItemName(kartitemtype_e i)
const char *DEH_VoiceName(kartvoicetype_e i)
{
return strbuf_get(voicenames, skinvoices[i + KSKVC_FIRSTFREESLOT].info.nameofs);
return strbuf_get(voicenames, skinvoices[i].info.nameofs);
}
mobjtype_t DEH_FindMobjtype(const char *word)
@ -143,13 +143,13 @@ kartvoicetype_e DEH_FindVoice(const char *word)
{
INT32 i;
UINT32 hash = HASH32(word, strlen(word));
for (i = 0; i < numfreeslotvoices; i++) {
if (hash != skinvoices[i + KSKVC_FIRSTFREESLOT].info.namehash)
for (i = 0; i < numskinvoices; i++) {
if (hash != skinvoices[i].info.namehash)
continue;
if (fastcmp(word, DEH_VoiceName(i)))
return (kartvoicetype_e)i;
}
return MAXVOICEFREESLOTS;
return MAXSKINVOICES;
}
struct flickytypes_s FLICKYTYPES[] = {

View file

@ -393,19 +393,7 @@ INT32 DEH_ReadFreeslot(const char *type, const char *word, INT32 *out)
}
else if (fastcmp(type, "KVOICE"))
{
*out = DEH_FindVoice(word);
if (*out != MAXVOICEFREESLOTS)
return 0; // already allocated
if (numfreeslotvoices == MAXVOICEFREESLOTS) {
CONS_Alert(CONS_WARNING, "Ran out of free voice slots!\n");
return -1;
}
CONS_Printf("Voice KVOICE_%s allocated.\n",word);
DEH_Link(word, &skinvoices[numfreeslotvoices + KSKVC_FIRSTFREESLOT].info, &voicenames);
skinvoices[numfreeslotvoices + KSKVC_FIRSTFREESLOT].id = numfreeslotvoices + KSKVC_FIRSTFREESLOT;
*out = numfreeslotvoices++;
return 0;
return R_AllocVoice(false, word, out);
}
return -2;
@ -806,12 +794,12 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile)
{
if (i == 0 && word2[0] != '0') // If word2 isn't a number
i = get_kartvoice(word2); // find a voice by name
if ((i + 1) >= 1 && i < numfreeslotvoices)
readkartvoice(f, &skinvoices[i + KSKVC_FIRSTFREESLOT]);
if ((i + 1) >= 1 && i < numskinvoices)
readkartvoice(f, &skinvoices[i]);
else
{
// zero-based, but let's start at 1
deh_warning("KartVoice number %d out of range (1 - %d)", i, numfreeslotvoices);
deh_warning("KartVoice number %d out of range (1 - %d)", i, numskinvoices);
ignorelines(f);
}
}

View file

@ -41,6 +41,7 @@
#include "lua_hook.h"
#include "p_saveg.h" // savebuffer_t
#include "g_party.h"
#include "deh_tables.h"
// SRB2Kart
#include "d_netfil.h" // nameonly
@ -54,7 +55,7 @@
#include "k_color.h"
#include "k_follower.h"
#include "k_grandprix.h"
#include "strbuf.h"
//#include "strbuf.h"
static CV_PossibleValue_t recordmultiplayerdemos_cons_t[] = {{0, "Disabled"}, {1, "Manual Save"}, {2, "Auto Save"}, {0, NULL}};
consvar_t cv_recordmultiplayerdemos = CVAR_INIT ("netdemo_record", "Manual Save", CV_SAVE, recordmultiplayerdemos_cons_t, NULL);
@ -1395,7 +1396,7 @@ void G_WriteDemoExtraData(void)
WRITESTRINGL(demobuf.p, skins[players[i].skin].name, 16+1);
// Voice
WRITESTRINGL(demobuf.p, skinvoices[players[i].voice_id].name, 32+1);
WRITESTRINGL(demobuf.p, DEH_VoiceName(players[i].voice_id), 32+1);
// Stats
WRITEUINT8(demobuf.p, skins[players[i].skin].kartspeed);
@ -2982,7 +2983,7 @@ void G_BeginRecording(void)
WRITESTRINGL(demobuf.p, skincolors[player->skincolor].name, 16+1);
// Voice
WRITESTRINGL(demobuf.p, skinvoices[player->voice_id].name, 32+1);
WRITESTRINGL(demobuf.p, DEH_VoiceName(player->voice_id), 32+1);
// Save follower's skin name
// PS: We must check for 'follower' to determine if the followerskin is valid. It's going to be 0 if we don't have a follower, but 0 is also absolutely a valid follower!

View file

@ -262,12 +262,12 @@ void P_ResetData(INT32 flags)
// voices
if (init)
{
for (i = KSKVC_FIRSTFREESLOT; i < MAXSKINVOICES; i++)
for (i = 0; i < MAXSKINVOICES; i++)
{
R_ClearVoice(i);
}
numfreeslotvoices = 0;
numskinvoices = 0;
if (voicenames)
Z_Free(voicenames);

View file

@ -16,6 +16,7 @@
#include "fastcmp.h"
#include "r_skins.h"
#include "sounds.h"
#include "deh_tables.h"
#include "lua_script.h"
#include "lua_libs.h"
@ -23,7 +24,7 @@
enum voicevars
{
voicevars_id = 0,
voicevars_name,
voicevars_name, // Not actually in kartvoice_t; returns the name of the voice
voicevars_parent,
voicevars_parentname, // Not actually in kartvoice_t; returns the name of the parent skin
voicevars_win,
@ -70,7 +71,7 @@ static int voice_get(lua_State* L)
lua_pushinteger(L, voice->id);
break;
case voicevars_name:
lua_pushstring(L, voice->name);
lua_pushstring(L, DEH_VoiceName((kartvoicetype_e)(voice - skinvoices)));
break;
case voicevars_parent:
lua_pushinteger(L, voice->parent);
@ -170,16 +171,7 @@ static int lib_iterateVoices(lua_State* L)
i = 0;
// voices are always valid, only added, never removed
if (i >= KSKVC_MAXVANILLA)
{
// Check freeslotted voices.
if ((i - KSKVC_MAXVANILLA) < numfreeslotvoices)
{
LUA_PushUserdata(L, &skinvoices[i], META_VOICE);
return 1;
}
}
else if (i < numskinvoices)
if (i < numskinvoices)
{
LUA_PushUserdata(L, &skinvoices[i], META_VOICE);
return 1;
@ -202,14 +194,6 @@ static int lib_getVoice(lua_State* L)
return luaL_error(
L, "skinvoices[] index %d out of range (0 - %d)", i, MAXSKINVOICES - 1);
}
if (i >= KSKVC_MAXVANILLA)
{
// Check freeslotted voices.
if ((i - KSKVC_MAXVANILLA) >= numfreeslotvoices)
{
return 0;
}
}
else if (i >= numskinvoices)
{
return 0;
@ -228,19 +212,6 @@ static int lib_getVoice(lua_State* L)
return 1;
}
// Special functions for getting voice counts per individual table.
if (fastcmp(field, "basevoices"))
{
lua_pushinteger(L, numskinvoices);
return 1;
}
if (fastcmp(field, "freeslotvoices"))
{
lua_pushinteger(L, numfreeslotvoices);
return 1;
}
// find voice by name
// Glad I made a function for this...
i = R_FindIDForVoice(field);
@ -258,7 +229,7 @@ static int lib_getVoice(lua_State* L)
// In this case: returns TOTAL voices, and not individual table counts.
static int lib_numVoices(lua_State* L)
{
lua_pushinteger(L, numskinvoices + numfreeslotvoices);
lua_pushinteger(L, numskinvoices);
return 1;
}

View file

@ -28,6 +28,7 @@
#include "dehacked.h" // get_number (for thok)
#include "m_cond.h"
#include "d_main.h" // MAINWAD_CHARS
#include "deh_tables.h" // Voice freeslotting
#if 0
#include "k_kart.h" // K_KartResetPlayerColor
#endif
@ -40,7 +41,6 @@
INT32 numskins = 0;
INT32 numskinvoices = 0;
INT32 numfreeslotvoices = 0;
skin_t skins[MAXSKINS];
INT32 skinsorted[MAXSKINS];
kartvoice_t skinvoices[MAXSKINVOICES];
@ -344,10 +344,6 @@ static void Sk_SetDefaultValue(skin_t *skin, kartvoice_t *skin_voice)
}
// TODO: Make this hexadecimal
snprintf(skin_voice->name,
sizeof skin_voice->name, "voice %u", (UINT32)(skin_voice-skinvoices));
skin_voice->name[sizeof skin_voice->name - 1] = '\0';
skin_voice->parent = (UINT16)(skin - skins);
skin_voice->id = skin_voice-skinvoices;
@ -725,27 +721,14 @@ void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum)
kartvoicetype_e R_FindIDForVoice(const char* voicename)
{
INT32 i;
const char *checkvoicename;
// First, check for freeslotted voices, should they exist at all.
if (numfreeslotvoices)
{
for (i = 0; i < numfreeslotvoices; i++)
{
if (strncmp(voicename,
skinvoices[i + KSKVC_FIRSTFREESLOT].name,
sizeof skinvoices[i + KSKVC_FIRSTFREESLOT].name) == 0)
{
// Found a voice.
return (kartvoicetype_e)(i + KSKVC_FIRSTFREESLOT);
}
}
}
// Freeslotted voices don't exist, or we've found nothing; check skin voices.
// Scan through our allocated skin voices for the wanted voice.
for (i = 0; i < numskinvoices; i++)
{
// Whatever. Go, my code duplication!
if (strncmp(voicename, skinvoices[i].name, sizeof skinvoices[i].name) == 0)
checkvoicename = DEH_VoiceName(i);
if (strnicmp(voicename, checkvoicename, VOICENAMESIZE) == 0)
{
// Found a voice.
return (kartvoicetype_e)i;
@ -760,20 +743,7 @@ static kartvoicetype_e R_FindIDForVoiceNum(UINT16 voicenum)
{
INT32 i;
// First, check for freeslotted voices, should they exist at all.
if (numfreeslotvoices)
{
for (i = 0; i < numfreeslotvoices; i++)
{
if (skinvoices[i + KSKVC_FIRSTFREESLOT].id == voicenum)
{
// Found a voice.
return (kartvoicetype_e)(i + KSKVC_FIRSTFREESLOT);
}
}
}
// Freeslotted voices don't exist, or we've found nothing; check skin voices.
// Scan through our allocated skin voices for the wanted voice.
for (i = 0; i < numskinvoices; i++)
{
// Whatever. Go, my code duplication!
@ -815,7 +785,8 @@ void SetPlayerVoice(INT32 playernum, const char* voicename)
const kartvoice_t* myvoice = P_GetMobjVoice(player->mo);
if (!strncmp(voicename, myvoice->name, sizeof myvoice->name))
const char* myvoicename = DEH_VoiceName(myvoice->id);
if (!strnicmp(voicename, myvoicename, VOICENAMESIZE))
{
// Hey... this voice is the same as before!
// WAIT! Before we go, reset the player's voice ID!
@ -1109,10 +1080,16 @@ static void R_IHateThatHedgehog(UINT16 wadnum)
Sk_SetDefaultValue(skin, skin_voice);
skin->wadnum = wadnum;
strcpy(skin->name, "sonic");
strcpy(skin->voice->name, "sonic_voice");
skin->voice->parent = 0;
// Add voice
INT32 dummy;
if (R_AllocVoice(true, skin->name, &dummy) < 0)
{
// Hey guy, take care!
I_Error("Failed to allocate initial skin voice\n");
}
#ifdef SKINVALUES
skin_cons_t[0].value = 0;
skin_cons_t[0].strvalue = skin->name;
@ -1288,6 +1265,33 @@ static boolean R_ProcessPatchableFields(skin_t *skin, char *stoken, char *value)
return true;
}
//
// Allocates a voice onto the dehacked list, and iterates the provided output pointer
// (should it exist).
//
INT32 R_AllocVoice(boolean skinalloc, const char* name, INT32 *out)
{
char voxname_upper[VOICENAMESIZE];
strncpy(voxname_upper, name, VOICENAMESIZE);
strupr(voxname_upper);
*out = DEH_FindVoice(voxname_upper);
if (*out != MAXSKINVOICES)
return skinalloc ? -1 : 0; // already allocated
if (numskinvoices == MAXSKINVOICES - 1) {
CONS_Alert(CONS_WARNING, "Ran out of free voice slots!\n");
return -1;
}
CONS_Printf("Voice KVOICE_%s allocated.\n",voxname_upper);
DEH_Link(voxname_upper, &skinvoices[numskinvoices].info, &voicenames);
*out = numskinvoices++;
return 0;
}
//
// Find skin sprites, sounds & optional status bar face, & add them
//
@ -1330,7 +1334,7 @@ void R_AddSkins(UINT16 wadnum)
// set defaults
skin = &skins[numskins];
skin_voice = &skinvoices[numskins];
skin_voice = &skinvoices[numskinvoices];
Sk_SetDefaultValue(skin, skin_voice);
skin->wadnum = wadnum;
realname = false;
@ -1360,7 +1364,6 @@ void R_AddSkins(UINT16 wadnum)
if (skinnum == -1)
{
STRBUFCPY(skin->name, value);
STRBUFCPY(skin->voice->name, va("%s_voice", value));
skin->voice->parent = (UINT16)(skin - skins);
}
// the skin name must uniquely identify a single skin
@ -1379,7 +1382,6 @@ void R_AddSkins(UINT16 wadnum)
// I'm lazy so if NEW name is already used I leave the 'skin x'
// default skin name set in Sk_SetDefaultValue
STRBUFCPY(skin->name, value2);
STRBUFCPY(skin->voice->name, va("%s_voice", value2));
skin->voice->parent = (UINT16)(skin - skins);
}
Z_Free(value2);
@ -1405,6 +1407,18 @@ void R_AddSkins(UINT16 wadnum)
}
free(buf2);
// Add voice
INT32 dummy;
if (R_AllocVoice(true, skin->name, &dummy) < 0)
{
// We couldn't allocate our own skin's voice?!
I_Error("Failed to allocate voice for skin %s\n", skin->name);
}
else
{
CONS_Printf(M_GetText("%d voices allocated.\n"), numskinvoices);
}
// Add sprites
R_LoadSkinSprites(wadnum, &lump, &lastlump, skin);
//ST_LoadFaceGraphics(numskins); -- nah let's do this elsewhere
@ -1431,7 +1445,6 @@ void R_AddSkins(UINT16 wadnum)
skinsorted[numskins] = numskins;
numskins++;
numskinvoices++;
}
SortSkins();
return;

View file

@ -52,10 +52,9 @@ struct kartvoice_t
{
UINT32 id;
// Dehacked info for the voice's name (hash and pointer within the voicenames array).
dehinfo_t info;
char name[VOICENAMESIZE+1]; // INT16 descriptive name of the voice.
// UINT16 ID of the parent skin this voice belongs to.
// Checked when the voice is assigned to prevent erroneous dubs.
UINT16 parent;
@ -131,7 +130,7 @@ enum skinmenusortoption
};
/// Externs
extern INT32 numskins, numskinvoices, numfreeslotvoices;
extern INT32 numskins, numskinvoices;
extern skin_t skins[MAXSKINS];
extern INT32 skinsorted[MAXSKINS];
extern kartvoice_t skinvoices[MAXSKINVOICES];
@ -156,6 +155,7 @@ void R_AddSkins(UINT16 wadnum);
UINT8 P_GetSkinSprite2(skin_t *skin, UINT8 spr2, player_t *player);
UINT8 P_KartFrameToSprite2(skin_t *skin, UINT8 inframe, UINT8 *outframe);
INT32 R_AllocVoice(boolean skinalloc, const char* name, INT32 *out);
void R_ClearVoice(kartvoicetype_e voicetype);
void Sk_SetSkinVoiceValue(kartvoice_t *voice, INT32 skinsound, INT32 writesound);