Voice cvars
This commit is contained in:
parent
4b9f9999cd
commit
69cb50b379
4 changed files with 317 additions and 4 deletions
203
src/d_netcmd.c
203
src/d_netcmd.c
|
|
@ -142,6 +142,11 @@ static void Followercolor2_OnChange(void);
|
|||
static void Followercolor3_OnChange(void);
|
||||
static void Followercolor4_OnChange(void);
|
||||
|
||||
static void Voice_OnChange(void);
|
||||
static void Voice2_OnChange(void);
|
||||
static void Voice3_OnChange(void);
|
||||
static void Voice4_OnChange(void);
|
||||
|
||||
static void Color_OnChange(void);
|
||||
static void Color2_OnChange(void);
|
||||
static void Color3_OnChange(void);
|
||||
|
|
@ -344,6 +349,15 @@ consvar_t cv_followercolor[MAXSPLITSCREENPLAYERS] = {
|
|||
CVAR_INIT ("followercolor4", "Default", CV_SAVE|CV_CALL|CV_NOINIT, Followercolor_cons_t, Followercolor4_OnChange)
|
||||
};
|
||||
|
||||
// player's voices...also, uh, saved.
|
||||
consvar_t cv_voice[MAXSPLITSCREENPLAYERS] = {
|
||||
CVAR_INIT ("voice", "None", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Voice_OnChange),
|
||||
CVAR_INIT ("voice2", "None", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Voice2_OnChange),
|
||||
CVAR_INIT ("voice3", "None", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Voice3_OnChange),
|
||||
CVAR_INIT ("voice4", "None", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Voice4_OnChange)
|
||||
};
|
||||
|
||||
|
||||
consvar_t cv_skipmapcheck = CVAR_INIT ("skipmapcheck", "Off", CV_SAVE, CV_OnOff, NULL);
|
||||
|
||||
consvar_t cv_usemouse = CVAR_INIT ("use_mouse", "Off", CV_SAVE|CV_CALL,usemouse_cons_t, I_StartupMouse);
|
||||
|
|
@ -1384,6 +1398,80 @@ static void Skin_FindRealNameSkin(consvar_t *cvar)
|
|||
}
|
||||
}
|
||||
|
||||
static void Skin_FindValidDub(consvar_t *cvar, UINT16 skin_id, kartvoice_t *voice, boolean forceme)
|
||||
{
|
||||
// Not the best way to implements this but it will do.
|
||||
|
||||
int i;
|
||||
const char *value = cvar->string;
|
||||
kartvoice_t *myvoice = voice;
|
||||
|
||||
if (!myvoice)
|
||||
{
|
||||
myvoice = skins[skin_id].voice;
|
||||
|
||||
if (!myvoice)
|
||||
{
|
||||
// ...how?!
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// First, check for freeslotted voices, should they exist at all.
|
||||
if (numfreeslotvoices)
|
||||
{
|
||||
for (i = 0; i < numfreeslotvoices; i++)
|
||||
{
|
||||
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);
|
||||
}
|
||||
else
|
||||
{
|
||||
// This isn't a valid voice for this skin, so don't assign shit.
|
||||
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);
|
||||
|
||||
// *Reassign* the voice to whatever the current voice is, at least.
|
||||
CV_StealthSet(cvar, myvoice->name);
|
||||
}
|
||||
|
||||
// Return regardless, as we've found the voice we were looking for.
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
else
|
||||
{
|
||||
// This isn't a valid voice for this skin, so don't assign shit.
|
||||
CONS_Alert(CONS_NOTICE, M_GetText("Voice \"%s\" doesn't belong to this skin (%s).\n"), skinvoices[i].name, skins[skin_id].name);
|
||||
|
||||
// *Reassign* the voice cvar to whatever the current voice is, at least.
|
||||
CV_StealthSet(cvar, myvoice->name);
|
||||
}
|
||||
|
||||
// Return regardless, as we've found the voice we were looking for.
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Checks if a name (as received from another player) is okay.
|
||||
* A name is okay if it is no fewer than 1 and no more than ::MAXPLAYERNAME
|
||||
* chars long (not including NUL), it does not begin or end with a space,
|
||||
|
|
@ -1733,12 +1821,16 @@ VaguePartyDescription (int playernum, int size, int default_color)
|
|||
static INT32 snacpending[MAXSPLITSCREENPLAYERS] = {0,0,0,0};
|
||||
static INT32 chmappending = 0;
|
||||
|
||||
// name, color, or skin has changed
|
||||
// name, color, skin, or voice has changed
|
||||
//
|
||||
static void SendNameAndColor(UINT8 n)
|
||||
{
|
||||
const INT32 playernum = g_localplayers[n];
|
||||
player_t *player = &players[playernum];
|
||||
kartvoice_t *voice;
|
||||
|
||||
// We have no voice, but don't want to topple the house of cards.
|
||||
boolean permamute = false;
|
||||
|
||||
char buf[MAXPLAYERNAME+12];
|
||||
char *p;
|
||||
|
|
@ -1775,11 +1867,26 @@ static void SendNameAndColor(UINT8 n)
|
|||
if (cv_follower[n].value >= numfollowers || cv_follower[n].value < -1)
|
||||
CV_StealthSet(&cv_follower[n], "-1");
|
||||
|
||||
// Check the player's acoustics.
|
||||
voice = P_GetMobjVoice(player->mo);
|
||||
|
||||
if (!voice)
|
||||
{
|
||||
voice = skins[player->skin].voice;
|
||||
|
||||
if (!voice)
|
||||
{
|
||||
// ...how?!
|
||||
permamute = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!strcmp(cv_playername[n].string, player_names[playernum])
|
||||
&& cv_playercolor[n].value == player->skincolor
|
||||
&& !strcmp(cv_skin[n].string, skins[player->skin].name)
|
||||
&& cv_follower[n].value == player->followerskin
|
||||
&& cv_followercolor[n].value == player->followercolor)
|
||||
&& cv_followercolor[n].value == player->followercolor
|
||||
&& (!permamute && !strcmp(cv_voice[n].string, voice->name)))
|
||||
return;
|
||||
|
||||
player->availabilities = R_GetSkinAvailabilities();
|
||||
|
|
@ -1825,6 +1932,26 @@ static void SendNameAndColor(UINT8 n)
|
|||
SetPlayerSkin(playernum, cv_skin[n].string);
|
||||
}
|
||||
|
||||
// Need to update voices after the fact.
|
||||
if (!cv_voice[n].string)
|
||||
CV_StealthSet(&cv_voice[n], skins[player->skin].voice->name);
|
||||
|
||||
SetPlayerVoice(playernum, cv_voice[n].string);
|
||||
|
||||
const kartvoice_t *valuevoice = P_GetMobjVoice(player->mo);
|
||||
|
||||
if (valuevoice)
|
||||
{
|
||||
CV_StealthSet(&cv_voice[n], valuevoice->name);
|
||||
cv_voice[n].value = (UINT16)valuevoice->id;
|
||||
}
|
||||
else
|
||||
{
|
||||
// ...this is my paranoia speaking.
|
||||
CV_StealthSet(&cv_voice[n], "sonic_voice");
|
||||
cv_voice[n].value = 0;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1852,6 +1979,9 @@ static void SendNameAndColor(UINT8 n)
|
|||
{
|
||||
CV_StealthSet(&cv_skin[n], DEFAULTSKIN);
|
||||
cv_skin[n].value = 0;
|
||||
|
||||
CV_StealthSet(&cv_voice[n], "sonic_voice");
|
||||
cv_voice[n].value = 0;
|
||||
}
|
||||
|
||||
// Finally write out the complete packet and send it off.
|
||||
|
|
@ -1861,6 +1991,7 @@ static void SendNameAndColor(UINT8 n)
|
|||
WRITEUINT16(p, (UINT16)cv_skin[n].value);
|
||||
WRITESINT8(p, (SINT8)cv_follower[n].value);
|
||||
WRITEUINT16(p, (UINT16)cv_followercolor[n].value);
|
||||
WRITEUINT16(p, (UINT16)cv_voice[n].value);
|
||||
|
||||
SendNetXCmdForPlayer(n, XD_NAMEANDCOLOR, buf, p - buf);
|
||||
}
|
||||
|
|
@ -1870,7 +2001,7 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum)
|
|||
player_t *p = &players[playernum];
|
||||
char name[MAXPLAYERNAME+1];
|
||||
UINT16 color, followercolor;
|
||||
UINT16 skin;
|
||||
UINT16 skin, voice;
|
||||
SINT8 follower;
|
||||
SINT8 localplayer = -1;
|
||||
UINT16 i;
|
||||
|
|
@ -1902,6 +2033,7 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum)
|
|||
skin = READUINT16(*cp);
|
||||
follower = READSINT8(*cp);
|
||||
followercolor = READUINT16(*cp);
|
||||
voice = READUINT16(*cp);
|
||||
|
||||
// set name
|
||||
if (player_name_changes[playernum] < MAXNAMECHANGES)
|
||||
|
|
@ -1981,6 +2113,9 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum)
|
|||
else
|
||||
SetPlayerSkinByNum(playernum, skin);
|
||||
|
||||
// set voice
|
||||
SetPlayerVoiceByNum(playernum, voice);
|
||||
|
||||
// set follower colour:
|
||||
// Don't bother doing garbage and kicking if we receive None,
|
||||
// this is both silly and a waste of time,
|
||||
|
|
@ -7218,6 +7353,68 @@ static void Color4_OnChange(void)
|
|||
lastgoodcolor[3] = cv_playercolor[3].value;
|
||||
}
|
||||
|
||||
static void __voice_cvar_func(INT32 pid, UINT8 pnum)
|
||||
{
|
||||
kartvoice_t *myvoice = P_GetMobjVoice(players[pid].mo);
|
||||
|
||||
if (!myvoice)
|
||||
{
|
||||
myvoice = skins[players[pid].skin].voice;
|
||||
|
||||
if (!myvoice)
|
||||
{
|
||||
// ...how?!
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Skin_FindValidDub(&cv_voice[pnum], players[pid].skin, myvoice, false);
|
||||
|
||||
if (!Playing())
|
||||
return; // do whatever you want
|
||||
|
||||
if (pnum > 0 && !splitscreen)
|
||||
return; // do whatever you want
|
||||
|
||||
if (pnum < 1)
|
||||
{
|
||||
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);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!P_PlayerMoving(pid))
|
||||
SendNameAndColor(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);
|
||||
}
|
||||
}
|
||||
|
||||
static void Voice_OnChange(void)
|
||||
{
|
||||
__voice_cvar_func(consoleplayer, 0);
|
||||
}
|
||||
|
||||
static void Voice2_OnChange(void)
|
||||
{
|
||||
__voice_cvar_func(g_localplayers[1], 1);
|
||||
}
|
||||
|
||||
static void Voice3_OnChange(void)
|
||||
{
|
||||
__voice_cvar_func(g_localplayers[2], 2);
|
||||
}
|
||||
|
||||
static void Voice4_OnChange(void)
|
||||
{
|
||||
__voice_cvar_func(g_localplayers[3], 3);
|
||||
}
|
||||
|
||||
/** Displays the result of the chat being muted or unmuted.
|
||||
* The server or remote admin should already know and be able to talk
|
||||
* regardless, so this is only displayed to clients.
|
||||
|
|
|
|||
|
|
@ -14951,6 +14951,12 @@ fixed_t P_GetMobjZMovement(mobj_t *mo)
|
|||
|
||||
kartvoice_t *P_GetMobjVoice(const mobj_t *mo)
|
||||
{
|
||||
if (P_MobjWasRemoved(mo))
|
||||
{
|
||||
// Nonexistent or NULL object.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (mo->voice)
|
||||
{
|
||||
return mo->voice;
|
||||
|
|
|
|||
108
src/r_skins.c
108
src/r_skins.c
|
|
@ -640,6 +640,57 @@ void SetPlayerSkin(INT32 playernum, const char *skinname)
|
|||
SetPlayerSkinByNum(playernum, 0);
|
||||
}
|
||||
|
||||
// network code calls this when a 'voice change' is received
|
||||
void SetPlayerVoice(INT32 playernum, const char *voicename)
|
||||
{
|
||||
player_t *player = &players[playernum];
|
||||
INT32 i;
|
||||
|
||||
if (P_MobjWasRemoved(player->mo))
|
||||
{
|
||||
// No object to give a voice to.
|
||||
return;
|
||||
}
|
||||
|
||||
const kartvoice_t *myvoice = P_GetMobjVoice(player->mo);
|
||||
|
||||
if (!strncmp(voicename, myvoice->name, sizeof myvoice->name))
|
||||
{
|
||||
// Hey... this voice is the same as before!
|
||||
return;
|
||||
}
|
||||
|
||||
// We've done the precautions to check for disallowed dubs in the cvar, just do a blind-read for the needed name.
|
||||
// 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.
|
||||
player->mo->voice = &skinvoices[i + KSKVC_FIRSTFREESLOT];
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Freeslotted voices don't exist or found nothing; check skin voices.
|
||||
for (i = 0; i < numskinvoices; i++)
|
||||
{
|
||||
// Whatever. Go, my code duplication!
|
||||
if (strncmp(voicename, skinvoices[i].name, sizeof skinvoices[i].name) == 0)
|
||||
{
|
||||
// Found a voice.
|
||||
player->mo->voice = &skinvoices[i];
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Couldn't find a voice. Default to the skin's.
|
||||
player->mo->voice = NULL;
|
||||
}
|
||||
|
||||
// Same as SetPlayerSkin, but uses the skin #.
|
||||
// network code calls this when a 'skin change' is received
|
||||
void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum)
|
||||
|
|
@ -685,6 +736,12 @@ void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum)
|
|||
if (player->mo)
|
||||
{
|
||||
player->mo->skin = 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
|
||||
}
|
||||
|
|
@ -708,6 +765,57 @@ void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum)
|
|||
SetPlayerSkinByNum(playernum, 0); // not found, put in the default skin
|
||||
}
|
||||
|
||||
// network code calls this when a 'voice change' is received
|
||||
void SetPlayerVoiceByNum(INT32 playernum, UINT16 voicenum)
|
||||
{
|
||||
player_t *player = &players[playernum];
|
||||
INT32 i;
|
||||
|
||||
if (P_MobjWasRemoved(player->mo))
|
||||
{
|
||||
// No object to give a voice to.
|
||||
return;
|
||||
}
|
||||
|
||||
const kartvoice_t *myvoice = P_GetMobjVoice(player->mo);
|
||||
|
||||
if (myvoice->id == voicenum)
|
||||
{
|
||||
// Hey... this voice is the same as before!
|
||||
return;
|
||||
}
|
||||
|
||||
// We've done the precautions to check for disallowed dubs in the cvar, just do a blind-read for the needed name.
|
||||
// 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.
|
||||
player->mo->voice = &skinvoices[i + KSKVC_FIRSTFREESLOT];
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Freeslotted voices don't exist or found nothing; check skin voices.
|
||||
for (i = 0; i < numskinvoices; i++)
|
||||
{
|
||||
// Whatever. Go, my code duplication!
|
||||
if (skinvoices[i].id == voicenum)
|
||||
{
|
||||
// Found a voice.
|
||||
player->mo->voice = &skinvoices[i];
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Couldn't find a voice. Default to the skin's.
|
||||
player->mo->voice = NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// Add skins from a pwad, each skin preceded by 'S_SKIN' marker
|
||||
//
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ extern consvar_t cv_skinselectstyle, cv_skinselectsort;
|
|||
typedef enum
|
||||
{
|
||||
KSKVC_MAXVANILLA = MAXSKINS,
|
||||
KSKVC_FIRSTFREESLOT,
|
||||
KSKVC_FIRSTFREESLOT = KSKVC_MAXVANILLA,
|
||||
KSKVC_LASTFREESLOT = 65535,
|
||||
MAXSKINVOICES
|
||||
} kartvoicetype_e;
|
||||
|
|
@ -153,6 +153,8 @@ 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);
|
||||
|
||||
void SetPlayerVoice(INT32 playernum, const char *voicename);
|
||||
void SetPlayerVoiceByNum(INT32 playernum, UINT16 voicenum);
|
||||
sfxenum_t P_GetVoiceSFX(kartvoice_t *voice, INT32 skinsound);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
|||
Loading…
Reference in a new issue