mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
Merge branch 'discord-rp-update' into 'master'
Update Discord Rich Presence for Ring Racers See merge request KartKrew/Kart!2155
This commit is contained in:
commit
20d6dcda88
11 changed files with 538 additions and 166 deletions
|
|
@ -1243,11 +1243,6 @@ static void Got_NameAndColor(const UINT8 **cp, INT32 playernum)
|
|||
|
||||
// set follower
|
||||
K_SetFollowerByNum(playernum, follower);
|
||||
|
||||
#ifdef HAVE_DISCORDRPC
|
||||
if (playernum == consoleplayer)
|
||||
DRPC_UpdatePresence();
|
||||
#endif
|
||||
}
|
||||
|
||||
enum {
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@
|
|||
#include "filesrch.h" // refreshdirmenu
|
||||
#include "k_follower.h"
|
||||
#include "doomstat.h" // MAXMUSNAMES
|
||||
#include "discord.h"
|
||||
|
||||
// Loops through every constant and operation in word and performs its calculations, returning the final value.
|
||||
fixed_t get_number(const char *word)
|
||||
|
|
@ -787,6 +788,7 @@ void readgametype(MYFILE *f, char *gtname)
|
|||
INT32 newgtpointlimit = 0;
|
||||
INT32 newgttimelimit = 0;
|
||||
UINT8 newgtinttype = 0;
|
||||
SINT8 newgtspeed = KARTSPEED_AUTO; // KARTSPEED_EASY
|
||||
char gtconst[MAXLINELEN];
|
||||
char gppic[9];
|
||||
char gppicmini[9];
|
||||
|
|
@ -853,6 +855,29 @@ void readgametype(MYFILE *f, char *gtname)
|
|||
// Case sensitive
|
||||
newgtinttype = (int)get_number(word2lwr);
|
||||
}
|
||||
else if (fastcmp(word, "GAMESPEED"))
|
||||
{
|
||||
if (fasticmp(word2, "EASY"))
|
||||
{
|
||||
newgtspeed = KARTSPEED_EASY;
|
||||
}
|
||||
else if (fasticmp(word2, "NORMAL"))
|
||||
{
|
||||
newgtspeed = KARTSPEED_NORMAL;
|
||||
}
|
||||
else if (fasticmp(word2, "HARD"))
|
||||
{
|
||||
newgtspeed = KARTSPEED_HARD;
|
||||
}
|
||||
else if (fasticmp(word2, "ANY"))
|
||||
{
|
||||
newgtspeed = KARTSPEED_AUTO;
|
||||
}
|
||||
else
|
||||
{
|
||||
deh_warning("readgametype %s: unknown gamespeed name %s\n", gtname, word2);
|
||||
}
|
||||
}
|
||||
// Type of level
|
||||
else if (fastcmp(word, "TYPEOFLEVEL"))
|
||||
{
|
||||
|
|
@ -945,6 +970,7 @@ void readgametype(MYFILE *f, char *gtname)
|
|||
newgametype->intermission = newgtinttype;
|
||||
newgametype->pointlimit = newgtpointlimit;
|
||||
newgametype->timelimit = newgttimelimit;
|
||||
newgametype->speed = newgtspeed;
|
||||
|
||||
gametypes[numgametypes++] = newgametype;
|
||||
|
||||
|
|
|
|||
602
src/discord.c
602
src/discord.c
|
|
@ -28,6 +28,9 @@
|
|||
#include "byteptr.h"
|
||||
#include "stun.h"
|
||||
#include "i_tcp.h" // current_port
|
||||
#include "k_grandprix.h"
|
||||
#include "k_battle.h"
|
||||
#include "m_cond.h" // M_GameTrulyStarted
|
||||
|
||||
#include "discord.h"
|
||||
#include "doomdef.h"
|
||||
|
|
@ -35,6 +38,10 @@
|
|||
// Feel free to provide your own, if you care enough to create another Discord app for this :P
|
||||
#define DISCORD_APPID "977470696852684833"
|
||||
|
||||
#ifdef DEVELOP
|
||||
#define DISCORD_SECRETIVE
|
||||
#endif
|
||||
|
||||
// length of IP strings
|
||||
#define IP_SIZE 21
|
||||
|
||||
|
|
@ -42,8 +49,31 @@ struct discordInfo_s discordInfo;
|
|||
|
||||
discordRequest_t *discordRequestList = NULL;
|
||||
|
||||
size_t g_discord_skins = 0;
|
||||
|
||||
static char self_ip[IP_SIZE];
|
||||
|
||||
/*--------------------------------------------------
|
||||
const char *DRPC_HideUsername(const char *input)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
const char *DRPC_HideUsername(const char *input)
|
||||
{
|
||||
static char buffer[5];
|
||||
int i;
|
||||
|
||||
buffer[0] = input[0];
|
||||
|
||||
for (i = 1; i < 4; ++i)
|
||||
{
|
||||
buffer[i] = '.';
|
||||
}
|
||||
|
||||
buffer[4] = '\0';
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static char *DRPC_XORIPString(const char *input)
|
||||
|
||||
|
|
@ -94,11 +124,11 @@ static void DRPC_HandleReady(const DiscordUser *user)
|
|||
{
|
||||
if (cv_discordstreamer.value)
|
||||
{
|
||||
CONS_Printf("Discord: connected to %s\n", user->username);
|
||||
CONS_Printf("Discord: connected to %s\n", DRPC_HideUsername(user->username));
|
||||
}
|
||||
else
|
||||
{
|
||||
CONS_Printf("Discord: connected to %s#%s (%s)\n", user->username, user->discriminator, user->userId);
|
||||
CONS_Printf("Discord: connected to %s (%s)\n", user->username, user->userId);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -234,8 +264,10 @@ static void DRPC_HandleJoinRequest(const DiscordUser *requestUser)
|
|||
newRequest->username = Z_Calloc(344, PU_STATIC, NULL);
|
||||
snprintf(newRequest->username, 344, "%s", requestUser->username);
|
||||
|
||||
#if 0
|
||||
newRequest->discriminator = Z_Calloc(8, PU_STATIC, NULL);
|
||||
snprintf(newRequest->discriminator, 8, "%s", requestUser->discriminator);
|
||||
#endif
|
||||
|
||||
newRequest->userID = Z_Calloc(32, PU_STATIC, NULL);
|
||||
snprintf(newRequest->userID, 32, "%s", requestUser->userId);
|
||||
|
|
@ -301,7 +333,9 @@ void DRPC_RemoveRequest(discordRequest_t *removeRequest)
|
|||
}
|
||||
|
||||
Z_Free(removeRequest->username);
|
||||
#if 0
|
||||
Z_Free(removeRequest->discriminator);
|
||||
#endif
|
||||
Z_Free(removeRequest->userID);
|
||||
Z_Free(removeRequest);
|
||||
}
|
||||
|
|
@ -394,6 +428,68 @@ static void DRPC_EmptyRequests(void)
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef DISCORD_SECRETIVE
|
||||
/*--------------------------------------------------
|
||||
static boolean DRPC_DisplayGonerSetup(void)
|
||||
|
||||
Returns true if we're in the initial
|
||||
tutorial game state.
|
||||
--------------------------------------------------*/
|
||||
static boolean DRPC_DisplayGonerSetup(void)
|
||||
{
|
||||
if (M_GameTrulyStarted())
|
||||
{
|
||||
// We're past all that tutorial stuff.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Playing())
|
||||
{
|
||||
// Need to check a bunch of stuff manually,
|
||||
// since with command line and/or console you
|
||||
// can play a bit of the game without fully
|
||||
// fully starting the game.
|
||||
|
||||
if (netgame)
|
||||
{
|
||||
// We smuggled into a netgame early,
|
||||
// show the netgame's info.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (tutorialchallenge == TUTORIALSKIP_INPROGRESS)
|
||||
{
|
||||
// Attempting the Dirty Bubble Challenge
|
||||
return true;
|
||||
}
|
||||
|
||||
// If it's not GT_TUTORIAL, it's directly
|
||||
// command line into a specific map.
|
||||
return (gametype == GT_TUTORIAL);
|
||||
}
|
||||
|
||||
// If we're in a menu, and the game hasn't started,
|
||||
// then we're definitely in goner setup.
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
enum {
|
||||
DISCORD_GS_UNKNOWN,
|
||||
DISCORD_GS_CUSTOM,
|
||||
DISCORD_GS_RACE,
|
||||
DISCORD_GS_BATTLE,
|
||||
DISCORD_GS_TUTORIAL,
|
||||
DISCORD_GS_TIMEATTACK,
|
||||
DISCORD_GS_GRANDPRIX,
|
||||
DISCORD_GS_VOTING,
|
||||
DISCORD_GS_MENU,
|
||||
DISCORD_GS_REPLAY,
|
||||
DISCORD_GS_TITLE,
|
||||
DISCORD_GS_CREDITS,
|
||||
DISCORD_GS_GONER
|
||||
};
|
||||
|
||||
/*--------------------------------------------------
|
||||
void DRPC_UpdatePresence(void)
|
||||
|
||||
|
|
@ -401,17 +497,6 @@ static void DRPC_EmptyRequests(void)
|
|||
--------------------------------------------------*/
|
||||
void DRPC_UpdatePresence(void)
|
||||
{
|
||||
#ifdef USEMAPIMG
|
||||
char mapimg[8+1];
|
||||
#endif
|
||||
#ifndef DEVELOP
|
||||
char detailstr[48+1];
|
||||
char mapname[5+21+21+2+1];
|
||||
|
||||
char charimg[4+SKINNAMESIZE+1];
|
||||
char charname[11+SKINNAMESIZE+1];
|
||||
#endif
|
||||
|
||||
boolean joinSecretSet = false;
|
||||
char *clientJoinSecret = NULL;
|
||||
|
||||
|
|
@ -432,14 +517,12 @@ void DRPC_UpdatePresence(void)
|
|||
return;
|
||||
}
|
||||
|
||||
#ifdef DEVELOP
|
||||
#ifdef DISCORD_SECRETIVE
|
||||
// This way, we can use the invite feature in-dev, but not have snoopers seeing any potential secrets! :P
|
||||
discordPresence.largeImageKey = "miscdevelop";
|
||||
discordPresence.largeImageKey = "misc_develop";
|
||||
discordPresence.largeImageText = "No peeking!";
|
||||
discordPresence.state = "Development EXE";
|
||||
#endif // DEVELOP
|
||||
|
||||
// Server info
|
||||
if (netgame)
|
||||
{
|
||||
if (DRPC_InvitesAreAllowed() == true)
|
||||
|
|
@ -459,7 +542,170 @@ void DRPC_UpdatePresence(void)
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef DEVELOP
|
||||
discordPresence.partyId = server_context; // Thanks, whoever gave us Mumble support, for implementing the EXACT thing Discord wanted for this field!
|
||||
discordPresence.partySize = D_NumPlayers(); // Players in server
|
||||
discordPresence.partyMax = discordInfo.maxPlayers; // Max players
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reset discord info if you're not in a place that uses it!
|
||||
// Important for if you join a server that compiled without HAVE_DISCORDRPC,
|
||||
// so that you don't ever end up using bad information from another server.
|
||||
memset(&discordInfo, 0, sizeof(discordInfo));
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
char detailstr[128];
|
||||
char localstr[128];
|
||||
|
||||
char charimg[32];
|
||||
char charname[128];
|
||||
|
||||
char gtname[128];
|
||||
|
||||
UINT8 gs = DISCORD_GS_UNKNOWN;
|
||||
if (DRPC_DisplayGonerSetup())
|
||||
{
|
||||
gs = DISCORD_GS_GONER;
|
||||
}
|
||||
else if (demo.playback)
|
||||
{
|
||||
switch (demo.attract)
|
||||
{
|
||||
case DEMO_ATTRACT_TITLE:
|
||||
{
|
||||
gs = DISCORD_GS_TITLE;
|
||||
break;
|
||||
}
|
||||
case DEMO_ATTRACT_CREDITS:
|
||||
{
|
||||
gs = DISCORD_GS_CREDITS;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
gs = DISCORD_GS_REPLAY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (gamestate)
|
||||
{
|
||||
case GS_LEVEL:
|
||||
case GS_INTERMISSION:
|
||||
{
|
||||
if (grandprixinfo.gp == true)
|
||||
{
|
||||
gs = DISCORD_GS_GRANDPRIX;
|
||||
}
|
||||
else if (modeattacking)
|
||||
{
|
||||
gs = DISCORD_GS_TIMEATTACK;
|
||||
}
|
||||
else if (gametype >= GT_FIRSTFREESLOT)
|
||||
{
|
||||
gs = DISCORD_GS_CUSTOM;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (gametype)
|
||||
{
|
||||
case GT_RACE:
|
||||
{
|
||||
gs = DISCORD_GS_RACE;
|
||||
break;
|
||||
}
|
||||
case GT_BATTLE:
|
||||
{
|
||||
gs = DISCORD_GS_BATTLE;
|
||||
break;
|
||||
}
|
||||
case GT_TUTORIAL:
|
||||
{
|
||||
gs = DISCORD_GS_TUTORIAL;
|
||||
break;
|
||||
}
|
||||
case GT_SPECIAL:
|
||||
case GT_VERSUS:
|
||||
{
|
||||
// You're using command line.
|
||||
// Just patch over this for now.
|
||||
gs = DISCORD_GS_GRANDPRIX;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break; // leave as UNKNOWN...
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GS_CEREMONY:
|
||||
{
|
||||
gs = DISCORD_GS_GRANDPRIX;
|
||||
break;
|
||||
}
|
||||
case GS_VOTING:
|
||||
{
|
||||
gs = DISCORD_GS_VOTING;
|
||||
break;
|
||||
}
|
||||
case GS_TITLESCREEN:
|
||||
{
|
||||
gs = DISCORD_GS_TITLE;
|
||||
break;
|
||||
}
|
||||
case GS_CREDITS:
|
||||
{
|
||||
gs = DISCORD_GS_CREDITS;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
gs = DISCORD_GS_MENU;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Server info
|
||||
if (gs == DISCORD_GS_GONER)
|
||||
{
|
||||
if (Playing())
|
||||
{
|
||||
discordPresence.state = "TRAINING DATA";
|
||||
}
|
||||
else if (gamedata->gonerlevel >= GDGONER_OUTRO)
|
||||
{
|
||||
discordPresence.state = "EVALUATION";
|
||||
}
|
||||
else
|
||||
{
|
||||
discordPresence.state = "MISSING DATA";
|
||||
}
|
||||
}
|
||||
else if (netgame)
|
||||
{
|
||||
if (DRPC_InvitesAreAllowed() == true)
|
||||
{
|
||||
const char *join;
|
||||
|
||||
// Grab the host's IP for joining.
|
||||
if ((join = DRPC_GetServerIP()) != NULL)
|
||||
{
|
||||
discordPresence.joinSecret = DRPC_XORIPString(join);
|
||||
joinSecretSet = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (cv_advertise.value)
|
||||
{
|
||||
discordPresence.state = "Public";
|
||||
|
|
@ -468,7 +714,6 @@ void DRPC_UpdatePresence(void)
|
|||
{
|
||||
discordPresence.state = "Private";
|
||||
}
|
||||
#endif // DEVELOP
|
||||
|
||||
discordPresence.partyId = server_context; // Thanks, whoever gave us Mumble support, for implementing the EXACT thing Discord wanted for this field!
|
||||
discordPresence.partySize = D_NumPlayers(); // Players in server
|
||||
|
|
@ -481,71 +726,115 @@ void DRPC_UpdatePresence(void)
|
|||
// so that you don't ever end up using bad information from another server.
|
||||
memset(&discordInfo, 0, sizeof(discordInfo));
|
||||
|
||||
#ifndef DEVELOP
|
||||
// Offline info
|
||||
if (Playing())
|
||||
discordPresence.state = "Offline";
|
||||
else if (demo.playback && !demo.attract)
|
||||
discordPresence.state = "Watching Replay";
|
||||
else
|
||||
discordPresence.state = "Menu";
|
||||
#endif // DEVELOP
|
||||
}
|
||||
|
||||
#ifndef DEVELOP
|
||||
// Gametype info
|
||||
if ((gamestate == GS_LEVEL || gamestate == GS_INTERMISSION || gamestate == GS_VOTING) && Playing())
|
||||
{
|
||||
if (modeattacking)
|
||||
discordPresence.details = "Time Attack";
|
||||
{
|
||||
snprintf(localstr, 128, "Local (%dP)", splitscreen + 1);
|
||||
discordPresence.state = localstr;
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(detailstr, 48, "%s%s%s",
|
||||
gametypes[gametype]->name,
|
||||
(gametyperules & GTR_CIRCUIT) ? va(" | %s", kartspeed_cons_t[gamespeed].strvalue) : "",
|
||||
(encoremode == true) ? " | Encore" : ""
|
||||
);
|
||||
discordPresence.details = detailstr;
|
||||
switch (gs)
|
||||
{
|
||||
case DISCORD_GS_REPLAY:
|
||||
{
|
||||
discordPresence.state = "Watching Replay";
|
||||
break;
|
||||
}
|
||||
case DISCORD_GS_TITLE:
|
||||
{
|
||||
discordPresence.state = "Title Screen";
|
||||
break;
|
||||
}
|
||||
case DISCORD_GS_CREDITS:
|
||||
{
|
||||
discordPresence.state = "Watching Credits";
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
discordPresence.state = "Menu";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((gamestate == GS_LEVEL || gamestate == GS_INTERMISSION) // Map info
|
||||
&& !(demo.playback && demo.attract))
|
||||
if (gs == DISCORD_GS_GONER)
|
||||
{
|
||||
#ifdef USEMAPIMG
|
||||
if ((gamemap >= 1 && gamemap <= 60) // supported race maps
|
||||
|| (gamemap >= 136 && gamemap <= 164)) // supported battle maps
|
||||
{
|
||||
//FIXME
|
||||
//snprintf(mapimg, 8, "%s", G_BuildMapName(gamemap));
|
||||
strlwr(mapimg);
|
||||
discordPresence.largeImageKey = mapimg; // Map image
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (mapheaderinfo[gamemap-1]->menuflags & LF2_HIDEINMENU)
|
||||
{
|
||||
// Hell map, use the method that got you here :P
|
||||
discordPresence.largeImageKey = "miscdice";
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is probably a custom map!
|
||||
discordPresence.largeImageKey = "mapcustom";
|
||||
}
|
||||
// Gametype info
|
||||
discordPresence.details = "Setup";
|
||||
|
||||
if (mapheaderinfo[gamemap-1]->menuflags & LF2_HIDEINMENU)
|
||||
discordPresence.largeImageKey = "gs_goner";
|
||||
discordPresence.largeImageText = "NO SIGNAL";
|
||||
}
|
||||
else
|
||||
{
|
||||
// Gametype info
|
||||
if ((gamestate == GS_LEVEL || gamestate == GS_INTERMISSION || gamestate == GS_VOTING || gamestate == GS_CEREMONY) && Playing())
|
||||
{
|
||||
// Hell map, hide the name
|
||||
discordPresence.largeImageText = "Map: ???";
|
||||
}
|
||||
else
|
||||
{
|
||||
// Map name on tool tip
|
||||
char *title = G_BuildMapTitle(gamemap);
|
||||
snprintf(mapname, 48, "Map: %s", title);
|
||||
Z_Free(title);
|
||||
discordPresence.largeImageText = mapname;
|
||||
if (grandprixinfo.gp)
|
||||
{
|
||||
char roundstr[32];
|
||||
|
||||
if (gamestate == GS_CEREMONY)
|
||||
{
|
||||
snprintf(roundstr, 32, " | Ceremony");
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (grandprixinfo.eventmode)
|
||||
{
|
||||
case GPEVENT_BONUS:
|
||||
{
|
||||
snprintf(roundstr, 32, " | Bonus");
|
||||
break;
|
||||
}
|
||||
case GPEVENT_SPECIAL:
|
||||
{
|
||||
snprintf(roundstr, 32, " | Special");
|
||||
break;
|
||||
}
|
||||
case GPEVENT_NONE:
|
||||
{
|
||||
if (roundqueue.position > 0 && roundqueue.position <= roundqueue.size)
|
||||
{
|
||||
snprintf(roundstr, 32, " | Round %d", roundqueue.position);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
snprintf(detailstr, 128, "Grand Prix%s | %s",
|
||||
roundstr,
|
||||
grandprixinfo.masterbots ? "Master" : kartspeed_cons_t[grandprixinfo.gamespeed + 1].strvalue
|
||||
);
|
||||
discordPresence.details = detailstr;
|
||||
}
|
||||
else if (battleprisons == true)
|
||||
{
|
||||
discordPresence.details = "Prison Break";
|
||||
}
|
||||
else if (modeattacking)
|
||||
{
|
||||
if (modeattacking & ATTACKING_SPB)
|
||||
{
|
||||
discordPresence.details = "SPB Attack";
|
||||
}
|
||||
else
|
||||
{
|
||||
discordPresence.details = "Time Attack";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(detailstr, 128, "%s%s%s",
|
||||
gametypes[gametype]->name,
|
||||
(gametypes[gametype]->speed == KARTSPEED_AUTO) ? va(" | %s", kartspeed_cons_t[gamespeed + 1].strvalue) : "",
|
||||
(encoremode == true) ? " | Encore" : ""
|
||||
);
|
||||
discordPresence.details = detailstr;
|
||||
}
|
||||
}
|
||||
|
||||
if (gamestate == GS_LEVEL && Playing())
|
||||
|
|
@ -561,90 +850,105 @@ void DRPC_UpdatePresence(void)
|
|||
discordPresence.endTimestamp = mapTimeEnd;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (gamestate == GS_VOTING)
|
||||
{
|
||||
discordPresence.largeImageKey = ((gametype == GT_BATTLE) ? "miscredplanet" : "miscblueplanet");
|
||||
discordPresence.largeImageText = "Voting";
|
||||
}
|
||||
else
|
||||
{
|
||||
discordPresence.largeImageKey = "misctitle";
|
||||
discordPresence.largeImageText = "Title Screen";
|
||||
}
|
||||
|
||||
// Character info
|
||||
if (Playing() && playeringame[consoleplayer] && !players[consoleplayer].spectator)
|
||||
{
|
||||
// Supported skin names
|
||||
static const char *supportedSkins[] = {
|
||||
// base game
|
||||
"sonic",
|
||||
"tails",
|
||||
"knuckles",
|
||||
"eggman",
|
||||
"metalsonic",
|
||||
// bonus chars
|
||||
"flicky",
|
||||
"motobug",
|
||||
"amy",
|
||||
"mighty",
|
||||
"ray",
|
||||
"espio",
|
||||
"vector",
|
||||
"chao",
|
||||
"gamma",
|
||||
"chaos",
|
||||
"shadow",
|
||||
"rouge",
|
||||
"herochao",
|
||||
"darkchao",
|
||||
"cream",
|
||||
"omega",
|
||||
"blaze",
|
||||
"silver",
|
||||
"wonderboy",
|
||||
"arle",
|
||||
"nights",
|
||||
"sakura",
|
||||
"ulala",
|
||||
"beat",
|
||||
"vyse",
|
||||
"aiai",
|
||||
"kiryu",
|
||||
"aigis",
|
||||
"miku",
|
||||
"doom",
|
||||
NULL
|
||||
};
|
||||
|
||||
boolean customChar = true;
|
||||
UINT8 checkSkin = 0;
|
||||
|
||||
// Character image
|
||||
while (supportedSkins[checkSkin] != NULL)
|
||||
// Gametype image
|
||||
switch (gs)
|
||||
{
|
||||
if (!strcmp(skins[players[consoleplayer].skin].name, supportedSkins[checkSkin]))
|
||||
case DISCORD_GS_CUSTOM:
|
||||
{
|
||||
snprintf(charimg, 21, "char%s", supportedSkins[checkSkin]);
|
||||
discordPresence.smallImageKey = charimg;
|
||||
customChar = false;
|
||||
discordPresence.largeImageKey = "custom_gs";
|
||||
snprintf(gtname, 128, "%s", gametypes[gametype]->name);
|
||||
discordPresence.largeImageText = gtname;
|
||||
break;
|
||||
}
|
||||
case DISCORD_GS_RACE:
|
||||
{
|
||||
discordPresence.largeImageKey = "gs_race";
|
||||
discordPresence.largeImageText = "Race";
|
||||
break;
|
||||
}
|
||||
case DISCORD_GS_BATTLE:
|
||||
{
|
||||
discordPresence.largeImageKey = "gs_battle";
|
||||
discordPresence.largeImageText = "Battle";
|
||||
break;
|
||||
}
|
||||
case DISCORD_GS_TUTORIAL:
|
||||
{
|
||||
discordPresence.largeImageKey = "gs_tutorial";
|
||||
discordPresence.largeImageText = "Tutorial";
|
||||
break;
|
||||
}
|
||||
case DISCORD_GS_TIMEATTACK:
|
||||
{
|
||||
discordPresence.largeImageKey = "gs_timeattack";
|
||||
discordPresence.largeImageText = "Time Attack";
|
||||
break;
|
||||
}
|
||||
case DISCORD_GS_GRANDPRIX:
|
||||
{
|
||||
discordPresence.largeImageKey = "gs_grandprix";
|
||||
discordPresence.largeImageText = "Grand Prix";
|
||||
break;
|
||||
}
|
||||
case DISCORD_GS_VOTING:
|
||||
{
|
||||
discordPresence.largeImageKey = "gs_voting";
|
||||
discordPresence.largeImageText = "Voting";
|
||||
break;
|
||||
}
|
||||
case DISCORD_GS_MENU:
|
||||
{
|
||||
discordPresence.largeImageKey = "gs_menu";
|
||||
discordPresence.largeImageText = "Menu";
|
||||
break;
|
||||
}
|
||||
case DISCORD_GS_REPLAY:
|
||||
{
|
||||
discordPresence.largeImageKey = "gs_replay";
|
||||
discordPresence.largeImageText = "Watching Replay";
|
||||
break;
|
||||
}
|
||||
case DISCORD_GS_TITLE:
|
||||
{
|
||||
discordPresence.largeImageKey = "gs_title";
|
||||
discordPresence.largeImageText = "Title Screen";
|
||||
break;
|
||||
}
|
||||
case DISCORD_GS_CREDITS:
|
||||
{
|
||||
discordPresence.largeImageKey = "gs_credits";
|
||||
discordPresence.largeImageText = "Credits";
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
discordPresence.largeImageKey = "misc_develop";
|
||||
discordPresence.largeImageText = "Invalid DRPC state?";
|
||||
break;
|
||||
}
|
||||
|
||||
checkSkin++;
|
||||
}
|
||||
|
||||
if (customChar == true)
|
||||
// Character info
|
||||
if (Playing() && playeringame[consoleplayer] && !players[consoleplayer].spectator)
|
||||
{
|
||||
// Use the custom character icon!
|
||||
discordPresence.smallImageKey = "charcustom";
|
||||
}
|
||||
// Character image
|
||||
if ((unsigned)players[consoleplayer].skin < g_discord_skins) // Supported skins
|
||||
{
|
||||
snprintf(charimg, 32, "char_%s", skins[ players[consoleplayer].skin ].name);
|
||||
discordPresence.smallImageKey = charimg;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use the custom character icon!
|
||||
discordPresence.smallImageKey = "custom_char";
|
||||
}
|
||||
|
||||
snprintf(charname, 28, "Character: %s", skins[players[consoleplayer].skin].realname);
|
||||
discordPresence.smallImageText = charname; // Character name
|
||||
snprintf(charname, 128, "Character: %s", skins[players[consoleplayer].skin].realname);
|
||||
discordPresence.smallImageText = charname; // Character name
|
||||
}
|
||||
}
|
||||
#endif // DEVELOP
|
||||
#endif // DISCORD_SECRETIVE
|
||||
|
||||
if (joinSecretSet == false)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -33,7 +33,9 @@ extern struct discordInfo_s {
|
|||
|
||||
struct discordRequest_t {
|
||||
char *username; // Discord user name.
|
||||
#if 0 // Good night, sweet prince...
|
||||
char *discriminator; // Discord discriminator (The little hashtag thing after the username). Separated for a "hide discriminators" cvar.
|
||||
#endif
|
||||
char *userID; // The ID of the Discord user, gets used with Discord_Respond()
|
||||
|
||||
// HAHAHA, no.
|
||||
|
|
@ -48,6 +50,18 @@ struct discordRequest_t {
|
|||
|
||||
extern discordRequest_t *discordRequestList;
|
||||
|
||||
extern size_t g_discord_skins;
|
||||
|
||||
/*--------------------------------------------------
|
||||
const char *DRPC_HideUsername(const char *input);
|
||||
|
||||
Handle usernames while cv_discordstreamer is activated.
|
||||
(The loss of discriminators is still a dumbass regression
|
||||
that I will never forgive the Discord developers for.)
|
||||
--------------------------------------------------*/
|
||||
|
||||
const char *DRPC_HideUsername(const char *input);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
void DRPC_RemoveRequest(void);
|
||||
|
|
|
|||
|
|
@ -624,6 +624,7 @@ struct gametype_t
|
|||
UINT32 rules;
|
||||
UINT32 tol;
|
||||
UINT8 intermission;
|
||||
SINT8 speed;
|
||||
INT32 pointlimit;
|
||||
INT32 timelimit;
|
||||
char gppic[9];
|
||||
|
|
|
|||
|
|
@ -3181,6 +3181,7 @@ static gametype_t defaultgametypes[] =
|
|||
GTR_CIRCUIT|GTR_BOTS|GTR_ENCORE,
|
||||
TOL_RACE,
|
||||
int_time,
|
||||
KARTSPEED_AUTO,
|
||||
0,
|
||||
0,
|
||||
"",
|
||||
|
|
@ -3194,6 +3195,7 @@ static gametype_t defaultgametypes[] =
|
|||
GTR_SPHERES|GTR_BUMPERS|GTR_PAPERITEMS|GTR_POWERSTONES|GTR_KARMA|GTR_ITEMARROWS|GTR_PRISONS|GTR_BATTLESTARTS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_OVERTIME|GTR_CLOSERPLAYERS,
|
||||
TOL_BATTLE,
|
||||
int_scoreortimeattack,
|
||||
KARTSPEED_EASY,
|
||||
0,
|
||||
3,
|
||||
"TT_RNDB",
|
||||
|
|
@ -3207,6 +3209,7 @@ static gametype_t defaultgametypes[] =
|
|||
GTR_CATCHER|GTR_SPECIALSTART|GTR_ROLLINGSTART|GTR_CIRCUIT|GTR_NOPOSITION,
|
||||
TOL_SPECIAL,
|
||||
int_time,
|
||||
KARTSPEED_AUTO,
|
||||
0,
|
||||
0,
|
||||
"TT_RNDSS",
|
||||
|
|
@ -3220,6 +3223,7 @@ static gametype_t defaultgametypes[] =
|
|||
GTR_BOSS|GTR_SPHERES|GTR_BUMPERS|GTR_POINTLIMIT|GTR_CLOSERPLAYERS|GTR_NOCUPSELECT|GTR_ENCORE,
|
||||
TOL_VERSUS,
|
||||
int_scoreortimeattack,
|
||||
KARTSPEED_EASY,
|
||||
0,
|
||||
0,
|
||||
"",
|
||||
|
|
@ -3233,6 +3237,7 @@ static gametype_t defaultgametypes[] =
|
|||
GTR_CHECKPOINTS|GTR_NOMP|GTR_NOCUPSELECT|GTR_NOPOSITION,
|
||||
TOL_TUTORIAL,
|
||||
int_none,
|
||||
KARTSPEED_EASY,
|
||||
0,
|
||||
0,
|
||||
"",
|
||||
|
|
|
|||
|
|
@ -2513,7 +2513,7 @@ static void HU_DrawRankings(void)
|
|||
V_DrawCenteredString(256, 8, 0, "POINT LIMIT");
|
||||
V_DrawCenteredString(256, 16, hilicol, va("%d", g_pointlimit));
|
||||
}
|
||||
else if (gametyperules & GTR_CIRCUIT)
|
||||
else if (gametypes[gametype]->speed == KARTSPEED_AUTO)
|
||||
{
|
||||
V_DrawCenteredString(256, 8, 0, "GAME SPEED");
|
||||
V_DrawCenteredString(256, 16, hilicol, (cv_4thgear.value) ? va("4th Gear") : kartspeed_cons_t[1+gamespeed].strvalue);
|
||||
|
|
|
|||
|
|
@ -2567,6 +2567,7 @@ static int lib_gAddGametype(lua_State *L)
|
|||
INT32 newgtpointlimit = 0;
|
||||
INT32 newgttimelimit = 0;
|
||||
UINT8 newgtinttype = 0;
|
||||
SINT8 newgtspeed = KARTSPEED_AUTO;
|
||||
INT16 j;
|
||||
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
|
|
@ -2632,6 +2633,14 @@ static int lib_gAddGametype(lua_State *L)
|
|||
if (!lua_isstring(L, 3))
|
||||
TYPEERROR("gppicmini", LUA_TSTRING)
|
||||
gppicmini = lua_tostring(L, 3);
|
||||
} else if (i == 10 || (k && fasticmp(k, "speed"))) {
|
||||
if (!lua_isnumber(L, 3))
|
||||
TYPEERROR("speed", LUA_TNUMBER)
|
||||
newgtspeed = (UINT32)lua_tointeger(L, 3);
|
||||
if (newgtspeed < KARTSPEED_AUTO || newgtspeed > KARTSPEED_HARD)
|
||||
{
|
||||
newgtspeed = KARTSPEED_AUTO;
|
||||
}
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
|
@ -2672,6 +2681,7 @@ static int lib_gAddGametype(lua_State *L)
|
|||
newgametype->intermission = newgtinttype;
|
||||
newgametype->pointlimit = newgtpointlimit;
|
||||
newgametype->timelimit = newgttimelimit;
|
||||
newgametype->speed = newgtspeed;
|
||||
|
||||
if (gppic != NULL)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -107,9 +107,9 @@ const char *M_GetDiscordName(discordRequest_t *r)
|
|||
return "";
|
||||
|
||||
if (cv_discordstreamer.value)
|
||||
return r->username;
|
||||
return DRPC_HideUsername(r->username);
|
||||
|
||||
return va("%s#%s", r->username, r->discriminator);
|
||||
return r->username;
|
||||
}
|
||||
|
||||
#endif // HAVE_DISCORDRPC
|
||||
|
|
|
|||
|
|
@ -7679,7 +7679,8 @@ static void P_InitLevelSettings(void)
|
|||
g_exit.retry = false;
|
||||
|
||||
// Gamespeed and frantic items
|
||||
gamespeed = KARTSPEED_EASY;
|
||||
const boolean multi_speed = (gametypes[gametype]->speed == KARTSPEED_AUTO);
|
||||
gamespeed = multi_speed ? KARTSPEED_EASY : gametypes[gametype]->speed;
|
||||
franticitems = false;
|
||||
|
||||
if (K_PodiumSequence() == true)
|
||||
|
|
@ -7694,7 +7695,7 @@ static void P_InitLevelSettings(void)
|
|||
}
|
||||
else if (grandprixinfo.gp == true)
|
||||
{
|
||||
if (gametyperules & GTR_CIRCUIT)
|
||||
if (multi_speed)
|
||||
{
|
||||
gamespeed = grandprixinfo.gamespeed;
|
||||
}
|
||||
|
|
@ -7704,18 +7705,21 @@ static void P_InitLevelSettings(void)
|
|||
|| tutorialchallenge == TUTORIALSKIP_INPROGRESS
|
||||
)
|
||||
{
|
||||
if ((gametyperules & GTR_CATCHER) && encoremode == false)
|
||||
if (multi_speed)
|
||||
{
|
||||
gamespeed = KARTSPEED_NORMAL;
|
||||
}
|
||||
else if (gametyperules & GTR_CIRCUIT)
|
||||
{
|
||||
gamespeed = KARTSPEED_HARD;
|
||||
if ((gametyperules & GTR_CATCHER) && encoremode == false)
|
||||
{
|
||||
gamespeed = KARTSPEED_NORMAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
gamespeed = KARTSPEED_HARD;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gametyperules & GTR_CIRCUIT)
|
||||
if (multi_speed)
|
||||
{
|
||||
if (cv_kartspeed.value == KARTSPEED_AUTO)
|
||||
gamespeed = ((speedscramble == -1) ? KARTSPEED_NORMAL : (UINT8)speedscramble);
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
#include "k_kart.h" // K_KartResetPlayerColor
|
||||
#endif
|
||||
#include "k_grandprix.h" // K_CanChangeRules
|
||||
#include "discord.h"
|
||||
#ifdef HWRENDER
|
||||
#include "hardware/hw_md2.h"
|
||||
#endif
|
||||
|
|
@ -184,6 +185,13 @@ void R_InitSkins(void)
|
|||
R_AddSkins((UINT16)i, true);
|
||||
R_PatchSkins((UINT16)i, true);
|
||||
R_LoadSpriteInfoLumps(i, wadfiles[i]->numlumps);
|
||||
|
||||
#ifdef HAVE_DISCORDRPC
|
||||
if (i == mainwads)
|
||||
{
|
||||
g_discord_skins = numskins;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
ST_ReloadSkinFaceGraphics();
|
||||
M_UpdateConditionSetsPending();
|
||||
|
|
@ -430,6 +438,11 @@ static void SetSkin(player_t *player, INT32 skinnum)
|
|||
|
||||
// for replays: We have changed our skin mid-game; let the game know so it can do the same in the replay!
|
||||
demo_extradata[(player-players)] |= DXD_SKIN;
|
||||
|
||||
#ifdef HAVE_DISCORDRPC
|
||||
if (player - players == consoleplayer)
|
||||
DRPC_UpdatePresence();
|
||||
#endif
|
||||
}
|
||||
|
||||
// Gets the player to the first usuable skin in the game.
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue