Compiling reaches g_demo.c again after the merge

This commit is contained in:
Sally Coolatta 2020-08-12 22:40:15 -04:00
parent 1c9284fbad
commit 5319ef434e
7 changed files with 125 additions and 130 deletions

View file

@ -158,6 +158,7 @@ extern CV_PossibleValue_t CV_Natural[];
#define KARTSPEED_EASY 0
#define KARTSPEED_NORMAL 1
#define KARTSPEED_HARD 2
#define KARTGP_MASTER 3 // Not a speed setting, gives the hardest speed with maxed out bots
extern CV_PossibleValue_t kartspeed_cons_t[];
extern consvar_t cv_execversion;

View file

@ -1817,12 +1817,11 @@ void D_SRB2Main(void)
INT16 newskill = -1;
const char *sskill = M_GetNextParm();
const UINT8 master = KARTSPEED_HARD+1;
const char *masterstr = "Master";
if (!strcasecmp(masterstr, sskill))
{
newskill = master;
newskill = KARTGP_MASTER;
}
else
{
@ -1838,14 +1837,14 @@ void D_SRB2Main(void)
if (!kartspeed_cons_t[j].strvalue) // reached end of the list with no match
{
j = atoi(sskill); // assume they gave us a skill number, which is okay too
if (j >= KARTSPEED_EASY && j <= master)
if (j >= KARTSPEED_EASY && j <= KARTGP_MASTER)
newskill = (INT16)j;
}
}
if (grandprixinfo.gp == true)
{
if (newskill == master)
if (newskill == KARTGP_MASTER)
{
grandprixinfo.masterbots = true;
newskill = KARTSPEED_HARD;
@ -1853,9 +1852,8 @@ void D_SRB2Main(void)
grandprixinfo.gamespeed = newskill;
}
else if (newskill == master)
else if (newskill == KARTGP_MASTER)
{
grandprixinfo.masterbots = true;
newskill = KARTSPEED_HARD;
}

View file

@ -283,16 +283,20 @@ consvar_t cv_skin[MAXSPLITSCREENPLAYERS] = {
};
// player's followers. Also saved.
consvar_t cv_follower = {"follower", "-1", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Follower_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_follower2 = {"follower2", "-1", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Follower2_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_follower3 = {"follower3", "-1", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Follower3_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_follower4 = {"follower4", "-1", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Follower4_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_follower[MAXSPLITSCREENPLAYERS] = {
{"follower", "-1", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Follower_OnChange, 0, NULL, NULL, 0, 0, NULL},
{"follower2", "-1", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Follower2_OnChange, 0, NULL, NULL, 0, 0, NULL},
{"follower3", "-1", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Follower3_OnChange, 0, NULL, NULL, 0, 0, NULL},
{"follower4", "-1", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Follower4_OnChange, 0, NULL, NULL, 0, 0, NULL}
};
// player's follower colors... Also saved...
consvar_t cv_followercolor = {"followercolor", "Match", CV_SAVE|CV_CALL|CV_NOINIT, Followercolor_cons_t, Followercolor_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_followercolor2 = {"followercolor2", "Match", CV_SAVE|CV_CALL|CV_NOINIT, Followercolor_cons_t, Followercolor2_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_followercolor3 = {"followercolor3", "Match", CV_SAVE|CV_CALL|CV_NOINIT, Followercolor_cons_t, Followercolor3_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_followercolor4 = {"followercolor4", "Match", CV_SAVE|CV_CALL|CV_NOINIT, Followercolor_cons_t, Followercolor4_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_followercolor[MAXSPLITSCREENPLAYERS] = {
{"followercolor", "Match", CV_SAVE|CV_CALL|CV_NOINIT, Followercolor_cons_t, Followercolor_OnChange, 0, NULL, NULL, 0, 0, NULL},
{"followercolor2", "Match", CV_SAVE|CV_CALL|CV_NOINIT, Followercolor_cons_t, Followercolor2_OnChange, 0, NULL, NULL, 0, 0, NULL},
{"followercolor3", "Match", CV_SAVE|CV_CALL|CV_NOINIT, Followercolor_cons_t, Followercolor3_OnChange, 0, NULL, NULL, 0, 0, NULL},
{"followercolor4", "Match", CV_SAVE|CV_CALL|CV_NOINIT, Followercolor_cons_t, Followercolor4_OnChange, 0, NULL, NULL, 0, 0, NULL}
};
// Follower toggle
@ -2503,6 +2507,7 @@ static void Command_Map_f(void)
size_t option_force;
size_t option_gametype;
size_t option_encore;
size_t option_skill;
const char *gametypename;
boolean newresetplayers;
@ -2515,6 +2520,7 @@ static void Command_Map_f(void)
INT32 newgametype = gametype;
boolean newencoremode = (cv_kartencore.value == 1);
boolean startgp = false;
INT32 d;
@ -2527,6 +2533,7 @@ static void Command_Map_f(void)
option_force = COM_CheckPartialParm("-f");
option_gametype = COM_CheckPartialParm("-g");
option_encore = COM_CheckPartialParm("-e");
option_skill = COM_CheckPartialParm("-s");
newresetplayers = ! COM_CheckParm("-noresetplayers");
mustmodifygame = !(netgame || multiplayer) && !majormods;
@ -2645,22 +2652,19 @@ static void Command_Map_f(void)
if (startgp)
{
i = COM_CheckParm("-skill");
grandprixinfo.gamespeed = (cv_kartspeed.value == KARTSPEED_AUTO ? KARTSPEED_NORMAL : cv_kartspeed.value);
grandprixinfo.masterbots = false;
if (i)
if (option_skill)
{
const UINT8 master = KARTSPEED_HARD+1;
const char *masterstr = "Master";
const char *skillname = COM_Argv(i+1);
const char *skillname = COM_Argv(option_skill + 1);
INT32 newskill = -1;
INT32 j;
if (!strcasecmp(masterstr, skillname))
{
newskill = master;
newskill = KARTGP_MASTER;
}
else
{
@ -2675,15 +2679,15 @@ static void Command_Map_f(void)
if (!kartspeed_cons_t[j].strvalue) // reached end of the list with no match
{
j = atoi(COM_Argv(i+1)); // assume they gave us a skill number, which is okay too
if (j >= KARTSPEED_EASY && j <= master)
newskill = (INT16)j;
INT32 num = atoi(COM_Argv(option_skill + 1)); // assume they gave us a skill number, which is okay too
if (num >= KARTSPEED_EASY && num <= KARTGP_MASTER)
newskill = (INT16)num;
}
}
if (newskill != -1)
{
if (newskill == master)
if (newskill == KARTGP_MASTER)
{
grandprixinfo.gamespeed = KARTSPEED_HARD;
grandprixinfo.masterbots = true;
@ -5035,19 +5039,19 @@ static void Follower_OnChange(void)
// there is a slight chance that we will actually use a string instead so...
// let's investigate the string...
strcpy(str, cv_follower.string);
strcpy(cpy, cv_follower.string);
strcpy(str, cv_follower[0].string);
strcpy(cpy, cv_follower[0].string);
strlwr(str);
if (stricmp(cpy,"0") !=0 && !atoi(cpy)) // yep, that's a string alright...
{
if (stricmp(cpy, "None") == 0)
{
CV_StealthSet(&cv_follower, "-1");
CV_StealthSet(&cv_follower[0], "-1");
if (!Playing())
return; // don't send anything there.
SendNameAndColor();
SendNameAndColor(0);
return;
}
@ -5057,26 +5061,25 @@ static void Follower_OnChange(void)
CONS_Alert(CONS_WARNING, M_GetText("Follower '%s' not found\n"), str);
sprintf(set, "%d", num);
CV_StealthSet(&cv_follower, set); // set it to a number. It's easier for us to send later :)
CV_StealthSet(&cv_follower[0], set); // set it to a number. It's easier for us to send later :)
}
if (!Playing())
return; // don't send anything there.
SendNameAndColor();
SendNameAndColor(0);
}
// About the same as Color_OnChange but for followers.
static void Followercolor_OnChange(void)
{
if (!Playing())
return; // do whatever you want if you aren't in the game or don't have a follower.
if (!P_PlayerMoving(consoleplayer))
{
// Color change menu scrolling fix is no longer necessary
SendNameAndColor();
SendNameAndColor(0);
}
}
@ -5085,136 +5088,153 @@ static void Followercolor_OnChange(void)
static void Follower2_OnChange(void)
{
char str[SKINNAMESIZE+1], cpy[SKINNAMESIZE+1];
if (!Playing() || !splitscreen)
return; // do whatever you want
INT32 num;
char set[10]; // This isn't Lua and mixed declarations in the middle of code make caveman compilers scream.
strcpy(str, cv_follower2.string);
strcpy(cpy, cv_follower2.string);
// there is a slight chance that we will actually use a string instead so...
// let's investigate the string...
strcpy(str, cv_follower[1].string);
strcpy(cpy, cv_follower[1].string);
strlwr(str);
if (stricmp(cpy,"0") !=0 && !atoi(cpy)) // yep, that's a string alright...
{
if (stricmp(cpy, "None") == 0)
{
CV_StealthSet(&cv_follower2, "-1");
SendNameAndColor2();
CV_StealthSet(&cv_follower[1], "-1");
if (!Playing())
return; // don't send anything there.
SendNameAndColor(1);
return;
}
num = R_FollowerAvailable(str);
{
INT32 num = R_FollowerAvailable(str);
char set[10];
if (num == -1) // that's an error.
CONS_Alert(CONS_WARNING, M_GetText("Follower '%s' not found\n"), str);
if (num == -1) // that's an error.
CONS_Alert(CONS_WARNING, M_GetText("Follower '%s' not found\n"), str);
sprintf(set, "%d", num);
CV_StealthSet(&cv_follower2, set); // set it to a number. It's easier for us to send later :)
}
sprintf(set, "%d", num);
CV_StealthSet(&cv_follower[1], set); // set it to a number. It's easier for us to send later :)
}
SendNameAndColor2();
if (!Playing())
return; // don't send anything there.
SendNameAndColor(1);
}
static void Followercolor2_OnChange(void)
{
if (!Playing())
return; // do whatever you want if you aren't in the game or don't have a follower.
if (!P_PlayerMoving(g_localplayers[1]))
{
// Color change menu scrolling fix is no longer necessary
SendNameAndColor2();
SendNameAndColor(1);
}
}
static void Follower3_OnChange(void)
{
char str[SKINNAMESIZE+1], cpy[SKINNAMESIZE+1];
if (!Playing() || !splitscreen)
return; // do whatever you want
INT32 num;
char set[10]; // This isn't Lua and mixed declarations in the middle of code make caveman compilers scream.
strcpy(str, cv_follower3.string);
strcpy(cpy, cv_follower3.string);
// there is a slight chance that we will actually use a string instead so...
// let's investigate the string...
strcpy(str, cv_follower[2].string);
strcpy(cpy, cv_follower[2].string);
strlwr(str);
if (stricmp(cpy,"0") !=0 && !atoi(cpy)) // yep, that's a string alright...
{
if (stricmp(cpy, "None") == 0)
{
CV_StealthSet(&cv_follower3, "-1");
SendNameAndColor3();
CV_StealthSet(&cv_follower[2], "-1");
if (!Playing())
return; // don't send anything there.
SendNameAndColor(2);
return;
}
{
INT32 num = R_FollowerAvailable(str);
char set[10];
if (num == -1) // that's an error.
CONS_Alert(CONS_WARNING, M_GetText("Follower '%s' not found\n"), str);
num = R_FollowerAvailable(str);
sprintf(set, "%d", num);
CV_StealthSet(&cv_follower3, set); // set it to a number. It's easier for us to send later :)
}
if (num == -1) // that's an error.
CONS_Alert(CONS_WARNING, M_GetText("Follower '%s' not found\n"), str);
sprintf(set, "%d", num);
CV_StealthSet(&cv_follower[2], set); // set it to a number. It's easier for us to send later :)
}
SendNameAndColor3();
if (!Playing())
return; // don't send anything there.
SendNameAndColor(2);
}
static void Followercolor3_OnChange(void)
{
if (!Playing())
return; // do whatever you want if you aren't in the game or don't have a follower.
if (!P_PlayerMoving(g_localplayers[2]))
{
// Color change menu scrolling fix is no longer necessary
SendNameAndColor3();
SendNameAndColor(2);
}
}
static void Follower4_OnChange(void)
{
char str[SKINNAMESIZE+1], cpy[SKINNAMESIZE+1];
if (!Playing() || !splitscreen)
return; // do whatever you want
INT32 num;
char set[10]; // This isn't Lua and mixed declarations in the middle of code make caveman compilers scream.
strcpy(str, cv_follower4.string);
strcpy(cpy, cv_follower4.string);
// there is a slight chance that we will actually use a string instead so...
// let's investigate the string...
strcpy(str, cv_follower[3].string);
strcpy(cpy, cv_follower[3].string);
strlwr(str);
if (stricmp(cpy,"0") !=0 && !atoi(cpy)) // yep, that's a string alright...
{
if (stricmp(cpy, "None") == 0)
{
CV_StealthSet(&cv_follower4, "-1");
SendNameAndColor4();
CV_StealthSet(&cv_follower[3], "-1");
if (!Playing())
return; // don't send anything there.
SendNameAndColor(3);
return;
}
{
INT32 num = R_FollowerAvailable(str);
char set[10];
if (num == -1) // that's an error.
CONS_Alert(CONS_WARNING, M_GetText("Follower '%s' not found\n"), str);
num = R_FollowerAvailable(str);
sprintf(set, "%d", num);
CV_StealthSet(&cv_follower4, set); // set it to a number. It's easier for us to send later :)
}
if (num == -1) // that's an error.
CONS_Alert(CONS_WARNING, M_GetText("Follower '%s' not found\n"), str);
sprintf(set, "%d", num);
CV_StealthSet(&cv_follower[3], set); // set it to a number. It's easier for us to send later :)
}
SendNameAndColor4();
if (!Playing())
return; // don't send anything there.
SendNameAndColor(3);
}
static void Followercolor4_OnChange(void)
{
if (!Playing())
return; // do whatever you want if you aren't in the game or don't have a follower.
if (!P_PlayerMoving(g_localplayers[3]))
{
// Color change menu scrolling fix is no longer necessary
SendNameAndColor4();
SendNameAndColor(3);
}
}

View file

@ -670,7 +670,7 @@ static void readfollower(MYFILE *f)
followers[numfollowers].bobspeed = TICRATE*2;
followers[numfollowers].bobamp = 4;
followers[numfollowers].hitconfirmtime = TICRATE;
followers[numfollowers].defaultcolor = 1;
followers[numfollowers].defaultcolor = SKINCOLOR_GREEN;
do
{
@ -701,71 +701,58 @@ static void readfollower(MYFILE *f)
if (fastcmp(word, "NAME"))
{
DEH_WriteUndoline(word, va("%s", followers[numfollowers].name), UNDO_NONE);
strcpy(followers[numfollowers].name, word2);
nameset = true;
}
else if (fastcmp(word, "DEFAULTCOLOR"))
{
DEH_WriteUndoline(word, va("%d", followers[numfollowers].defaultcolor), UNDO_NONE);
followers[numfollowers].defaultcolor = (UINT8)get_number(word2);
followers[numfollowers].defaultcolor = (UINT16)get_number(word2);
}
else if (fastcmp(word, "SCALE"))
{
DEH_WriteUndoline(word, va("%d", followers[numfollowers].scale), UNDO_NONE);
followers[numfollowers].scale = get_number(word2);
}
else if (fastcmp(word, "BUBBLESCALE"))
{
DEH_WriteUndoline(word, va("%d", followers[numfollowers].bubblescale), UNDO_NONE);
followers[numfollowers].bubblescale = get_number(word2);
}
else if (fastcmp(word, "ATANGLE"))
{
DEH_WriteUndoline(word, va("%d", followers[numfollowers].atangle), UNDO_NONE);
followers[numfollowers].atangle = (INT32)atoi(word2);
}
else if (fastcmp(word, "HORZLAG"))
{
DEH_WriteUndoline(word, va("%d", followers[numfollowers].horzlag), UNDO_NONE);
followers[numfollowers].horzlag = (INT32)atoi(word2);
}
else if (fastcmp(word, "VERTLAG"))
{
DEH_WriteUndoline(word, va("%d", followers[numfollowers].vertlag), UNDO_NONE);
followers[numfollowers].vertlag = (INT32)atoi(word2);
}
else if (fastcmp(word, "BOBSPEED"))
{
DEH_WriteUndoline(word, va("%d", followers[numfollowers].bobspeed), UNDO_NONE);
followers[numfollowers].bobspeed = (INT32)atoi(word2);
}
else if (fastcmp(word, "BOBAMP"))
{
DEH_WriteUndoline(word, va("%d", followers[numfollowers].bobamp), UNDO_NONE);
followers[numfollowers].bobamp = (INT32)atoi(word2);
}
else if (fastcmp(word, "ZOFFSET") || (fastcmp(word, "ZOFFS")))
{
DEH_WriteUndoline(word, va("%d", followers[numfollowers].zoffs), UNDO_NONE);
followers[numfollowers].zoffs = (INT32)atoi(word2);
}
else if (fastcmp(word, "DISTANCE") || (fastcmp(word, "DIST")))
{
DEH_WriteUndoline(word, va("%d", followers[numfollowers].dist), UNDO_NONE);
followers[numfollowers].dist = (INT32)atoi(word2);
}
else if (fastcmp(word, "HEIGHT"))
{
DEH_WriteUndoline(word, va("%d", followers[numfollowers].height), UNDO_NONE);
followers[numfollowers].height = (INT32)atoi(word2);
}
else if (fastcmp(word, "IDLESTATE"))
{
if (word2)
strupr(word2);
DEH_WriteUndoline(word, va("%d", followers[numfollowers].idlestate), UNDO_NONE);
followers[numfollowers].idlestate = get_number(word2);
fallbackstate = followers[numfollowers].idlestate;
}
@ -773,40 +760,34 @@ static void readfollower(MYFILE *f)
{
if (word2)
strupr(word2);
DEH_WriteUndoline(word, va("%d", followers[numfollowers].followstate), UNDO_NONE);
followers[numfollowers].followstate = get_number(word2);
}
else if (fastcmp(word, "HURTSTATE"))
{
if (word2)
strupr(word2);
DEH_WriteUndoline(word, va("%d", followers[numfollowers].hurtstate), UNDO_NONE);
followers[numfollowers].hurtstate = get_number(word2);
}
else if (fastcmp(word, "LOSESTATE"))
{
if (word2)
strupr(word2);
DEH_WriteUndoline(word, va("%d", followers[numfollowers].losestate), UNDO_NONE);
followers[numfollowers].losestate = get_number(word2);
}
else if (fastcmp(word, "WINSTATE"))
{
if (word2)
strupr(word2);
DEH_WriteUndoline(word, va("%d", followers[numfollowers].winstate), UNDO_NONE);
followers[numfollowers].winstate = get_number(word2);
}
else if (fastcmp(word, "HITSTATE") || (fastcmp(word, "HITCONFIRMSTATE")))
{
if (word2)
strupr(word2);
DEH_WriteUndoline(word, va("%d", followers[numfollowers].hitconfirmstate), UNDO_NONE);
followers[numfollowers].hitconfirmstate = get_number(word2);
}
else if (fastcmp(word, "HITTIME") || (fastcmp(word, "HITCONFIRMTIME")))
{
DEH_WriteUndoline(word, va("%d", followers[numfollowers].hitconfirmtime), UNDO_NONE);
followers[numfollowers].hitconfirmtime = (INT32)atoi(word2);
}
else
@ -868,10 +849,10 @@ if (followers[numfollowers].field < threshold) \
FALLBACK(bubblescale, "BUBBLESCALE", 0, 0); // No negative scale
// Special case for color I suppose
if (followers[numfollowers].defaultcolor > MAXSKINCOLORS-1)
if (followers[numfollowers].defaultcolor > numskincolors-1)
{
followers[numfollowers].defaultcolor = 1;
deh_warning("Follower \'%s\': Value for 'color' should be between 1 and %d.\n", dname, MAXSKINCOLORS-1);
followers[numfollowers].defaultcolor = SKINCOLOR_GREEN;
deh_warning("Follower \'%s\': Value for 'color' should be between 1 and %d.\n", dname, numskincolors-1);
}
#undef FALLBACK
@ -4860,7 +4841,6 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile)
else if (fastcmp(word, "FOLLOWER"))
{
readfollower(f); // at the same time this will be our only way to ADD followers for now. Yikes.
DEH_WriteUndoline(word, "", UNDO_HEADER);
// This is not a major mod either.
continue; // continue so that we don't error.
}
@ -5096,7 +5076,6 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile)
}
readcupheader(f, cup);
DEH_WriteUndoline(word, word2, UNDO_HEADER);
}
else if (fastcmp(word, "CUTSCENE"))
{

View file

@ -1003,9 +1003,8 @@ typedef enum sprite
SPR_WTRL, // Water Trail
SPR_FBUB, // follower bubble
SPR_GCHA, // follower: generic chao
SPR_CHEZ, // follower: cheese
SPR_GCHA, // follower: generic chao
SPR_CHEZ, // follower: cheese
// First person view sprites; this is a sprite so that it can be replaced by a specialized MD2 draw later
SPR_VIEW,

View file

@ -7664,21 +7664,19 @@ static void M_StartGrandPrix(INT32 choice)
switch (cv_dummygpdifficulty.value)
{
case 0:
grandprixinfo.gamespeed = KARTSPEED_EASY;
case KARTSPEED_EASY:
case KARTSPEED_NORMAL:
case KARTSPEED_HARD:
grandprixinfo.gamespeed = cv_dummygpdifficulty.value;
break;
case 1:
default:
grandprixinfo.gamespeed = KARTSPEED_NORMAL;
break;
case 2:
grandprixinfo.gamespeed = KARTSPEED_HARD;
break;
case 3:
case KARTGP_MASTER:
grandprixinfo.gamespeed = KARTSPEED_HARD;
grandprixinfo.masterbots = true;
break;
default:
CONS_Alert(CONS_WARNING, "Invalid GP difficulty\n");
grandprixinfo.gamespeed = KARTSPEED_NORMAL;
break;
}
grandprixinfo.encore = (boolean)(cv_dummygpencore.value);

View file

@ -93,7 +93,7 @@ typedef struct follower_s
char skinname[SKINNAMESIZE+1]; // Skin Name. This is what to refer to when asking the commands anything.
char name[SKINNAMESIZE+1]; // Name. This is used for the menus. We'll just follow the same rules as skins for this.
UINT8 defaultcolor; // default color for menus.
UINT16 defaultcolor; // default color for menus.
fixed_t scale; // Scale relative to the player's.
fixed_t bubblescale; // Bubble scale relative to the player scale. If not set, no bubble will spawn (default)
@ -106,8 +106,8 @@ typedef struct follower_s
// movement options
INT32 horzlag; // Lag for X/Y displacement. Default is 2. Must be > 0 because we divide by this number.
INT32 vertlag; // not Vert from Neptunia lagging, this is for Z displacement lag Default is 6. Must be > 0 because we divide by this number.
UINT32 horzlag; // Lag for X/Y displacement. Default is 2. Must be > 0 because we divide by this number.
UINT32 vertlag; // not Vert from Neptunia lagging, this is for Z displacement lag Default is 6. Must be > 0 because we divide by this number.
INT32 bobamp; // Bob amplitude. Default is 4.
INT32 bobspeed; // Arbitrary modifier for bobbing speed, default is TICRATE*2 (70).
@ -120,7 +120,7 @@ typedef struct follower_s
INT32 winstate; // state when the player has won
INT32 losestate; // state when the player has lost
INT32 hitconfirmstate; // state for hit confirm
INT32 hitconfirmtime; // time to keep the above playing for
UINT32 hitconfirmtime; // time to keep the above playing for
} follower_t;
extern INT32 numfollowers;