I needed to commit here so I could switch branches to fix magnet hand xd

This commit is contained in:
Latapostrophe 2019-02-13 10:06:52 +01:00
parent 16004e5ba9
commit fe3852f005
8 changed files with 483 additions and 40 deletions

View file

@ -103,6 +103,10 @@ static void Skin_OnChange(void);
static void Skin2_OnChange(void); static void Skin2_OnChange(void);
static void Skin3_OnChange(void); static void Skin3_OnChange(void);
static void Skin4_OnChange(void); static void Skin4_OnChange(void);
static void Follower_OnChange(void);
static void Follower2_OnChange(void);
static void Follower3_OnChange(void);
static void Follower4_OnChange(void);
static void Color_OnChange(void); static void Color_OnChange(void);
static void Color2_OnChange(void); static void Color2_OnChange(void);
static void Color3_OnChange(void); static void Color3_OnChange(void);
@ -268,6 +272,12 @@ consvar_t cv_skin2 = {"skin2", DEFAULTSKIN2, CV_SAVE|CV_CALL|CV_NOINIT, NULL, Sk
consvar_t cv_skin3 = {"skin3", DEFAULTSKIN3, CV_SAVE|CV_CALL|CV_NOINIT, NULL, Skin3_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_skin3 = {"skin3", DEFAULTSKIN3, CV_SAVE|CV_CALL|CV_NOINIT, NULL, Skin3_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_skin4 = {"skin4", DEFAULTSKIN4, CV_SAVE|CV_CALL|CV_NOINIT, NULL, Skin4_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_skin4 = {"skin4", DEFAULTSKIN4, CV_SAVE|CV_CALL|CV_NOINIT, NULL, Skin4_OnChange, 0, NULL, NULL, 0, 0, NULL};
// 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_skipmapcheck = {"skipmapcheck", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_skipmapcheck = {"skipmapcheck", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
INT32 cv_debug; INT32 cv_debug;
@ -747,18 +757,22 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_playername); CV_RegisterVar(&cv_playername);
CV_RegisterVar(&cv_playercolor); CV_RegisterVar(&cv_playercolor);
CV_RegisterVar(&cv_skin); // r_things.c (skin NAME) CV_RegisterVar(&cv_skin); // r_things.c (skin NAME)
CV_RegisterVar(&cv_follower);
// secondary player (splitscreen) // secondary player (splitscreen)
CV_RegisterVar(&cv_playername2); CV_RegisterVar(&cv_playername2);
CV_RegisterVar(&cv_playercolor2); CV_RegisterVar(&cv_playercolor2);
CV_RegisterVar(&cv_skin2); CV_RegisterVar(&cv_skin2);
CV_RegisterVar(&cv_follower2);
// third player // third player
CV_RegisterVar(&cv_playername3); CV_RegisterVar(&cv_playername3);
CV_RegisterVar(&cv_playercolor3); CV_RegisterVar(&cv_playercolor3);
CV_RegisterVar(&cv_skin3); CV_RegisterVar(&cv_skin3);
CV_RegisterVar(&cv_follower3);
// fourth player // fourth player
CV_RegisterVar(&cv_playername4); CV_RegisterVar(&cv_playername4);
CV_RegisterVar(&cv_playercolor4); CV_RegisterVar(&cv_playercolor4);
CV_RegisterVar(&cv_skin4); CV_RegisterVar(&cv_skin4);
CV_RegisterVar(&cv_follower4);
// preferred number of players // preferred number of players
CV_RegisterVar(&cv_splitplayers); CV_RegisterVar(&cv_splitplayers);
@ -1241,7 +1255,7 @@ static INT32 snacpending = 0, snac2pending = 0, snac3pending = 0, snac4pending =
// //
static void SendNameAndColor(void) static void SendNameAndColor(void)
{ {
XBOXSTATIC char buf[MAXPLAYERNAME+2]; XBOXSTATIC char buf[MAXPLAYERNAME+3];
char *p; char *p;
p = buf; p = buf;
@ -1268,7 +1282,8 @@ static void SendNameAndColor(void)
if (!strcmp(cv_playername.string, player_names[consoleplayer]) if (!strcmp(cv_playername.string, player_names[consoleplayer])
&& cv_playercolor.value == players[consoleplayer].skincolor && cv_playercolor.value == players[consoleplayer].skincolor
&& !strcmp(cv_skin.string, skins[players[consoleplayer].skin].name)) && !strcmp(cv_skin.string, skins[players[consoleplayer].skin].name)
&& cv_follower.value == players[consoleplayer].followerskin)
return; return;
// We'll handle it later if we're not playing. // We'll handle it later if we're not playing.
@ -1351,6 +1366,7 @@ static void SendNameAndColor(void)
WRITESTRINGN(p, cv_playername.zstring, MAXPLAYERNAME); WRITESTRINGN(p, cv_playername.zstring, MAXPLAYERNAME);
WRITEUINT8(p, (UINT8)cv_playercolor.value); WRITEUINT8(p, (UINT8)cv_playercolor.value);
WRITEUINT8(p, (UINT8)cv_skin.value); WRITEUINT8(p, (UINT8)cv_skin.value);
WRITESINT8(p, (UINT8)cv_follower.value);
SendNetXCmd(XD_NAMEANDCOLOR, buf, p - buf); SendNetXCmd(XD_NAMEANDCOLOR, buf, p - buf);
} }
@ -1358,7 +1374,7 @@ static void SendNameAndColor(void)
static void SendNameAndColor2(void) static void SendNameAndColor2(void)
{ {
INT32 secondplaya = -1; INT32 secondplaya = -1;
XBOXSTATIC char buf[MAXPLAYERNAME+2]; XBOXSTATIC char buf[MAXPLAYERNAME+3];
char *p; char *p;
if (splitscreen < 1 && !botingame) if (splitscreen < 1 && !botingame)
@ -1475,13 +1491,14 @@ static void SendNameAndColor2(void)
WRITESTRINGN(p, cv_playername2.zstring, MAXPLAYERNAME); WRITESTRINGN(p, cv_playername2.zstring, MAXPLAYERNAME);
WRITEUINT8(p, (UINT8)cv_playercolor2.value); WRITEUINT8(p, (UINT8)cv_playercolor2.value);
WRITEUINT8(p, (UINT8)cv_skin2.value); WRITEUINT8(p, (UINT8)cv_skin2.value);
WRITESINT8(p, (UINT8)cv_follower2.value);
SendNetXCmd2(XD_NAMEANDCOLOR, buf, p - buf); SendNetXCmd2(XD_NAMEANDCOLOR, buf, p - buf);
} }
static void SendNameAndColor3(void) static void SendNameAndColor3(void)
{ {
INT32 thirdplaya = -1; INT32 thirdplaya = -1;
XBOXSTATIC char buf[MAXPLAYERNAME+2]; XBOXSTATIC char buf[MAXPLAYERNAME+3];
char *p; char *p;
if (splitscreen < 2) if (splitscreen < 2)
@ -1590,13 +1607,14 @@ static void SendNameAndColor3(void)
WRITESTRINGN(p, cv_playername3.zstring, MAXPLAYERNAME); WRITESTRINGN(p, cv_playername3.zstring, MAXPLAYERNAME);
WRITEUINT8(p, (UINT8)cv_playercolor3.value); WRITEUINT8(p, (UINT8)cv_playercolor3.value);
WRITEUINT8(p, (UINT8)cv_skin3.value); WRITEUINT8(p, (UINT8)cv_skin3.value);
WRITESINT8(p, (UINT8)cv_follower3.value);
SendNetXCmd3(XD_NAMEANDCOLOR, buf, p - buf); SendNetXCmd3(XD_NAMEANDCOLOR, buf, p - buf);
} }
static void SendNameAndColor4(void) static void SendNameAndColor4(void)
{ {
INT32 fourthplaya = -1; INT32 fourthplaya = -1;
XBOXSTATIC char buf[MAXPLAYERNAME+2]; XBOXSTATIC char buf[MAXPLAYERNAME+3];
char *p; char *p;
if (splitscreen < 3) if (splitscreen < 3)
@ -1713,6 +1731,7 @@ static void SendNameAndColor4(void)
WRITESTRINGN(p, cv_playername4.zstring, MAXPLAYERNAME); WRITESTRINGN(p, cv_playername4.zstring, MAXPLAYERNAME);
WRITEUINT8(p, (UINT8)cv_playercolor4.value); WRITEUINT8(p, (UINT8)cv_playercolor4.value);
WRITEUINT8(p, (UINT8)cv_skin4.value); WRITEUINT8(p, (UINT8)cv_skin4.value);
WRITESINT8(p, (UINT8)cv_follower4.value);
SendNetXCmd4(XD_NAMEANDCOLOR, buf, p - buf); SendNetXCmd4(XD_NAMEANDCOLOR, buf, p - buf);
} }
@ -1721,6 +1740,7 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum)
player_t *p = &players[playernum]; player_t *p = &players[playernum];
char name[MAXPLAYERNAME+1]; char name[MAXPLAYERNAME+1];
UINT8 color, skin; UINT8 color, skin;
SINT8 follower;
#ifdef PARANOIA #ifdef PARANOIA
if (playernum < 0 || playernum > MAXPLAYERS) if (playernum < 0 || playernum > MAXPLAYERS)
@ -1744,6 +1764,7 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum)
READSTRINGN(*cp, name, MAXPLAYERNAME); READSTRINGN(*cp, name, MAXPLAYERNAME);
color = READUINT8(*cp); color = READUINT8(*cp);
skin = READUINT8(*cp); skin = READUINT8(*cp);
follower = READSINT8(*cp);
// set name // set name
if (strcasecmp(player_names[playernum], name) != 0) if (strcasecmp(player_names[playernum], name) != 0)
@ -1802,6 +1823,9 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum)
} }
else else
SetPlayerSkinByNum(playernum, skin); SetPlayerSkinByNum(playernum, skin);
// set follower:
SetFollower(playernum, follower);
} }
void SendWeaponPref(void) void SendWeaponPref(void)
@ -5090,6 +5114,97 @@ static void Name4_OnChange(void)
SendNameAndColor4(); SendNameAndColor4();
} }
// sends the follower change for players
static void Follower_OnChange(void)
{
if (!Playing())
return; // do whatever you want
// there is a slight chance that we will actually use a string instead so...
// let's investigate the string...
char str[SKINNAMESIZE+1], cpy[SKINNAMESIZE+1];
strcpy(str, cv_follower.string);
strcpy(cpy, cv_follower.string);
strlwr(str);
if (!atoi(cpy)) // yep, that's a string alright...
{
INT32 num = R_FollowerAvailable(str);
if (num == -1) // that's an error.
CONS_Alert(CONS_WARNING, M_GetText("Follower '%s' not found\n"), str);
char set[10];
sprintf(set, "%d", num);
CV_StealthSet(&cv_follower, set); // set it to a number. It's easier for us to send later :)
}
SendNameAndColor();
}
static void Follower2_OnChange(void)
{
if (!Playing() || !splitscreen)
return; // do whatever you want
char str[SKINNAMESIZE+1], cpy[SKINNAMESIZE+1];
strcpy(str, cv_follower2.string);
strcpy(cpy, cv_follower2.string);
strlwr(str);
if (!atoi(cpy)) // yep, that's a string alright...
{
INT32 num = R_FollowerAvailable(str);
if (num == -1) // that's an error.
CONS_Alert(CONS_WARNING, M_GetText("Follower '%s' not found\n"), str);
char set[10];
sprintf(set, "%d", num);
CV_StealthSet(&cv_follower2, set); // set it to a number. It's easier for us to send later :)
}
SendNameAndColor2();
}
static void Follower3_OnChange(void)
{
if (!Playing() || !splitscreen)
return; // do whatever you want
char str[SKINNAMESIZE+1], cpy[SKINNAMESIZE+1];
strcpy(str, cv_follower3.string);
strcpy(cpy, cv_follower3.string);
strlwr(str);
if (!atoi(cpy)) // yep, that's a string alright...
{
INT32 num = R_FollowerAvailable(str);
if (num == -1) // that's an error.
CONS_Alert(CONS_WARNING, M_GetText("Follower '%s' not found\n"), str);
char set[10];
sprintf(set, "%d", num);
CV_StealthSet(&cv_follower3, set); // set it to a number. It's easier for us to send later :)
}
SendNameAndColor3();
}
static void Follower4_OnChange(void)
{
if (!Playing() || !splitscreen)
return; // do whatever you want
char str[SKINNAMESIZE+1], cpy[SKINNAMESIZE+1];
strcpy(str, cv_follower4.string);
strcpy(cpy, cv_follower4.string);
strlwr(str);
if (!atoi(cpy)) // yep, that's a string alright...
{
INT32 num = R_FollowerAvailable(str);
if (num == -1) // that's an error.
CONS_Alert(CONS_WARNING, M_GetText("Follower '%s' not found\n"), str);
char set[10];
sprintf(set, "%d", num);
CV_StealthSet(&cv_follower4, set); // set it to a number. It's easier for us to send later :)
}
SendNameAndColor4();
}
/** Sends a skin change for the console player, unless that player is moving. /** Sends a skin change for the console player, unless that player is moving.
* \sa cv_skin, Skin2_OnChange, Color_OnChange * \sa cv_skin, Skin2_OnChange, Color_OnChange
* \author Graue <graue@oceanbase.org> * \author Graue <graue@oceanbase.org>

View file

@ -21,18 +21,22 @@
extern consvar_t cv_playername; extern consvar_t cv_playername;
extern consvar_t cv_playercolor; extern consvar_t cv_playercolor;
extern consvar_t cv_skin; extern consvar_t cv_skin;
extern consvar_t cv_follower;
// secondary splitscreen player // secondary splitscreen player
extern consvar_t cv_playername2; extern consvar_t cv_playername2;
extern consvar_t cv_playercolor2; extern consvar_t cv_playercolor2;
extern consvar_t cv_skin2; extern consvar_t cv_skin2;
extern consvar_t cv_follower2;
// third splitscreen player // third splitscreen player
extern consvar_t cv_playername3; extern consvar_t cv_playername3;
extern consvar_t cv_playercolor3; extern consvar_t cv_playercolor3;
extern consvar_t cv_skin3; extern consvar_t cv_skin3;
extern consvar_t cv_follower3;
// fourth splitscreen player // fourth splitscreen player
extern consvar_t cv_playername4; extern consvar_t cv_playername4;
extern consvar_t cv_playercolor4; extern consvar_t cv_playercolor4;
extern consvar_t cv_skin4; extern consvar_t cv_skin4;
extern consvar_t cv_follower4;
// preferred number of players // preferred number of players
extern consvar_t cv_splitplayers; extern consvar_t cv_splitplayers;

View file

@ -445,6 +445,7 @@ typedef struct player_s
UINT8 kartspeed; // Kart speed stat between 1 and 9 UINT8 kartspeed; // Kart speed stat between 1 and 9
UINT8 kartweight; // Kart weight stat between 1 and 9 UINT8 kartweight; // Kart weight stat between 1 and 9
INT32 followerskin; // Kart: This player's follower "skin"
mobj_t *follower; // Kart: This is the follower object we have. (If any) mobj_t *follower; // Kart: This is the follower object we have. (If any)
// //

View file

@ -702,15 +702,18 @@ static void readfollower(MYFILE *f)
if (numfollowers > MAXSKINS) if (numfollowers > MAXSKINS)
{ {
CONS_Printf("Error: Too many followers, cannot add anymore.\n"); deh_warning("Error: Too many followers, cannot add anymore.\n");
return; return;
} }
char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL); char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL);
char *word, *word2; char *word, *word2, *dname = malloc(SKINNAMESIZE+1);
char *tmp; char *tmp;
CONS_Printf("Adding follower, please bear with me...\n"); boolean nameset;
INT32 fallbackstate = 0;
CONS_Printf("Adding follower...\n");
do do
{ {
@ -732,14 +735,20 @@ static void readfollower(MYFILE *f)
break; break;
word2 = strtok(NULL, " = "); word2 = strtok(NULL, " = ");
if (word2)
strupr(word2); if (!word2)
else
break; break;
if (word2[strlen(word2)-1] == '\n') if (word2[strlen(word2)-1] == '\n')
word2[strlen(word2)-1] = '\0'; word2[strlen(word2)-1] = '\0';
if (fastcmp(word, "ATANGLE")) 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, "ATANGLE"))
{ {
DEH_WriteUndoline(word, va("%d", followers[numfollowers].atangle), UNDO_NONE); DEH_WriteUndoline(word, va("%d", followers[numfollowers].atangle), UNDO_NONE);
followers[numfollowers].atangle = (INT32)atoi(word2); followers[numfollowers].atangle = (INT32)atoi(word2);
@ -749,13 +758,103 @@ static void readfollower(MYFILE *f)
DEH_WriteUndoline(word, va("%d", followers[numfollowers].zoffs), UNDO_NONE); DEH_WriteUndoline(word, va("%d", followers[numfollowers].zoffs), UNDO_NONE);
followers[numfollowers].zoffs = (INT32)atoi(word2); followers[numfollowers].zoffs = (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;
}
else if (fastcmp(word, "FOLLOWSTATE"))
{
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 else
deh_warning("Follower %d: unknown word '%s'", numfollowers, word); deh_warning("Follower %d: unknown word '%s'", numfollowers, word);
} }
} while (!myfeof(f)); // finish when the line is empty } while (!myfeof(f)); // finish when the line is empty
CONS_Printf("We are done adding the follower.\n"); if (!nameset) // well this is problematic.
numfollowers++; {
strcpy(followers[numfollowers].name, va("Follower%d", numfollowers)); // this is lazy, so what
}
// set skin name (this is just the follower's name in lowercases):
// but before we do, let's... actually check if another follower isn't doing the same shit...
char testname[SKINNAMESIZE];
strcpy(testname, followers[numfollowers].name);
// lower testname for skin checks...
strlwr(testname);
INT32 res = R_FollowerAvailable(testname);
if (res > -1) // yikes, someone else has stolen our name already
{
deh_warning("There was already a follower with the same name. (%s)", testname);
INT32 startlen = strlen(testname);
char cpy[2];
sprintf(cpy, "%d", numfollowers);
memcpy(&testname[startlen], cpy, 2);
// in that case, we'll be very lazy and copy numfollowers to the end of our skin name.
}
strcpy(followers[numfollowers].skinname, testname);
// get ready to print the name...
strcpy(dname, followers[numfollowers].skinname);
// check for atangle and zoffs. But don't error if they aren't set, just give them logical values.
if (!followers[numfollowers].atangle && followers[numfollowers].atangle != 0)
followers[numfollowers].atangle = 300;
if ((!followers[numfollowers].zoffs || followers[numfollowers].zoffs < 0) && followers[numfollowers].zoffs != 0) // yikes, no offset or negative offset
followers[numfollowers].zoffs = 64;
// also check if we forgot states :V
#define NOSTATE(field, field2) \
if (!followers[numfollowers].field) \
{ \
followers[numfollowers].field = fallbackstate ? fallbackstate : S_INVISIBLE; \
if (!fallbackstate) \
deh_warning("Follower %s is missing state definition for %s, no idlestate fallback was found", dname, field2); \
} \
NOSTATE(idlestate, "idlestate");
NOSTATE(followstate, "followstate");
NOSTATE(hurtstate, "hurtstate");
NOSTATE(losestate, "losestate");
NOSTATE(winstate, "winstate");
#undef NOSTATE
CONS_Printf("Added follower '%s'\n", dname);
numfollowers++; // add 1 follower
free(dname); // free name memory
Z_Free(s); Z_Free(s);
} }
@ -3508,6 +3607,13 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
// This is not a major mod. // This is not a major mod.
continue; continue;
} }
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.
}
word2 = strtok(NULL, " "); word2 = strtok(NULL, " ");
if (fastcmp(word, "CHARACTER")) if (fastcmp(word, "CHARACTER"))
{ {
@ -3549,11 +3655,6 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
DEH_WriteUndoline(word, word2, UNDO_HEADER); DEH_WriteUndoline(word, word2, UNDO_HEADER);
// This is not a major mod. // This is not a major mod.
} }
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, word2, UNDO_HEADER);
}
else if (fastcmp(word, "THING") || fastcmp(word, "MOBJ") || fastcmp(word, "OBJECT")) else if (fastcmp(word, "THING") || fastcmp(word, "MOBJ") || fastcmp(word, "OBJECT"))
{ {
if (i == 0 && word2[0] != '0') // If word2 isn't a number if (i == 0 && word2[0] != '0') // If word2 isn't a number

View file

@ -140,7 +140,7 @@
extern FILE *logstream; extern FILE *logstream;
#endif #endif
#define DEVELOP // Disable this for release builds to remove excessive cheat commands and enable MD5 checking and stuff, all in one go. :3 //#define DEVELOP // Disable this for release builds to remove excessive cheat commands and enable MD5 checking and stuff, all in one go. :3
#ifdef DEVELOP #ifdef DEVELOP
#define VERSION 0 // Game version #define VERSION 0 // Game version
#define SUBVERSION 0 // more precise version number #define SUBVERSION 0 // more precise version number

View file

@ -184,6 +184,7 @@ INT16 startmap; // Mario, NiGHTS, or just a plain old normal game?
static INT16 itemOn = 1; // menu item skull is on, Hack by Tails 09-18-2002 static INT16 itemOn = 1; // menu item skull is on, Hack by Tails 09-18-2002
static INT16 skullAnimCounter = 10; // skull animation counter static INT16 skullAnimCounter = 10; // skull animation counter
static tic_t followertimer = 0; // Used for smooth follower floating
static UINT8 setupcontrolplayer; static UINT8 setupcontrolplayer;
static INT32 (*setupcontrols)[2]; // pointer to the gamecontrols of the player being edited static INT32 (*setupcontrols)[2]; // pointer to the gamecontrols of the player being edited
@ -973,6 +974,7 @@ static menuitem_t MP_PlayerSetupMenu[] =
{ {
{IT_KEYHANDLER | IT_STRING, NULL, "Name", M_HandleSetupMultiPlayer, 0}, {IT_KEYHANDLER | IT_STRING, NULL, "Name", M_HandleSetupMultiPlayer, 0},
{IT_KEYHANDLER | IT_STRING, NULL, "Character", M_HandleSetupMultiPlayer, 16}, // Tails 01-18-2001 {IT_KEYHANDLER | IT_STRING, NULL, "Character", M_HandleSetupMultiPlayer, 16}, // Tails 01-18-2001
{IT_KEYHANDLER | IT_STRING, NULL, "Follower", M_HandleSetupMultiPlayer, 26},
{IT_KEYHANDLER | IT_STRING, NULL, "Color", M_HandleSetupMultiPlayer, 152}, {IT_KEYHANDLER | IT_STRING, NULL, "Color", M_HandleSetupMultiPlayer, 152},
}; };
@ -3139,6 +3141,8 @@ void M_Ticker(void)
if (--skullAnimCounter <= 0) if (--skullAnimCounter <= 0)
skullAnimCounter = 8; skullAnimCounter = 8;
followertimer++;
//added : 30-01-98 : test mode for five seconds //added : 30-01-98 : test mode for five seconds
if (vidm_testingmode > 0) if (vidm_testingmode > 0)
{ {
@ -8027,9 +8031,15 @@ static void M_HandleConnectIP(INT32 choice)
// ======================== // ========================
// Tails 03-02-2002 // Tails 03-02-2002
// used for skin display on player setup menu
static INT32 multi_tics; static INT32 multi_tics;
static state_t *multi_state; static state_t *multi_state;
// used for follower display on player setup menu
static INT32 follower_tics;
static INT32 follower_frame; // used for FF_ANIMATE garbo
static state_t *follower_state;
// this is set before entering the MultiPlayer setup menu, // this is set before entering the MultiPlayer setup menu,
// for either player 1 or 2 // for either player 1 or 2
static char setupm_name[MAXPLAYERNAME+1]; static char setupm_name[MAXPLAYERNAME+1];
@ -8037,8 +8047,10 @@ static player_t *setupm_player;
static consvar_t *setupm_cvskin; static consvar_t *setupm_cvskin;
static consvar_t *setupm_cvcolor; static consvar_t *setupm_cvcolor;
static consvar_t *setupm_cvname; static consvar_t *setupm_cvname;
static consvar_t *setupm_cvfollower;
static INT32 setupm_fakeskin; static INT32 setupm_fakeskin;
static INT32 setupm_fakecolor; static INT32 setupm_fakecolor;
static INT32 setupm_fakefollower; // -1 is for none, our followers start at 0
static void M_DrawSetupMultiPlayerMenu(void) static void M_DrawSetupMultiPlayerMenu(void)
{ {
@ -8087,11 +8099,31 @@ static void M_DrawSetupMultiPlayerMenu(void)
'\x1D' | highlightflags, false); // right arrow '\x1D' | highlightflags, false); // right arrow
} }
// draw follower string
char *fname = malloc(SKINNAMESIZE+1);
if (setupm_fakefollower == -1)
strcpy(fname, "None");
else
strcpy(fname, followers[setupm_fakefollower].name);
st = V_StringWidth(fname, 0);
V_DrawString(BASEVIDWIDTH - mx - st, my + 26,
((MP_PlayerSetupMenu[2].status & IT_TYPE) == IT_SPACE ? V_TRANSLUCENT : 0)|highlightflags|V_ALLOWLOWERCASE,
fname);
if (itemOn == 2)
{
V_DrawCharacter(BASEVIDWIDTH - mx - 10 - st - (skullAnimCounter/5), my + 26,
'\x1C' | highlightflags, false); // left arrow
V_DrawCharacter(BASEVIDWIDTH - mx + 2 + (skullAnimCounter/5), my + 26,
'\x1D' | highlightflags, false); // right arrow
}
// draw the name of the color you have chosen // draw the name of the color you have chosen
// Just so people don't go thinking that "Default" is Green. // Just so people don't go thinking that "Default" is Green.
st = V_StringWidth(KartColor_Names[setupm_fakecolor], 0); st = V_StringWidth(KartColor_Names[setupm_fakecolor], 0);
V_DrawString(BASEVIDWIDTH - mx - st, my + 152, highlightflags|V_ALLOWLOWERCASE, KartColor_Names[setupm_fakecolor]); // SRB2kart V_DrawString(BASEVIDWIDTH - mx - st, my + 152, highlightflags|V_ALLOWLOWERCASE, KartColor_Names[setupm_fakecolor]); // SRB2kart
if (itemOn == 2) if (itemOn == 3)
{ {
V_DrawCharacter(BASEVIDWIDTH - mx - 10 - st - (skullAnimCounter/5), my + 152, V_DrawCharacter(BASEVIDWIDTH - mx - 10 - st - (skullAnimCounter/5), my + 152,
'\x1C' | highlightflags, false); // left arrow '\x1C' | highlightflags, false); // left arrow
@ -8262,9 +8294,84 @@ static void M_DrawSetupMultiPlayerMenu(void)
Z_Free(colormap); Z_Free(colormap);
} }
// draw their follower if there is one
if (setupm_fakefollower > -1 && setupm_fakefollower < numfollowers)
{
// animate the follower
if (--follower_tics <= 0)
{
// FF_ANIMATE; cycle through FRAMES and get back afterwards. This will be prominent amongst followers hence why it's being supported here.
if (follower_state->frame & FF_ANIMATE)
{
follower_frame++;
follower_tics = follower_state->var2;
if (follower_frame > (follower_state->frame & FF_FRAMEMASK) + follower_state->var1) // that's how it works, right?
follower_frame = follower_state->frame & FF_FRAMEMASK;
}
else
{
st = follower_state->nextstate;
if (st != S_NULL)
follower_state = &states[st];
follower_tics = follower_state->tics;
if (follower_tics == -1)
follower_tics = 15; // er, what?
// get spritedef:
follower_frame = follower_state->frame & FF_FRAMEMASK;
}
}
sprdef = &sprites[follower_state->sprite];
// draw the follower
if (follower_frame >= sprdef->numframes)
follower_frame = 0; // frame doesn't exist, we went beyond it... what?
sprframe = &sprdef->spriteframes[follower_frame];
patch = W_CachePatchNum(sprframe->lumppat[1], PU_CACHE);
if (sprframe->flip & 1) // Only for first sprite
flags |= V_FLIP; // This sprite is left/right flipped!
// draw player sprite
if (setupm_fakecolor) // inverse should never happen
{
// smooth floating, totally not stolen from rocket sneakers.
const fixed_t pi = (22<<FRACBITS) / 7; // loose approximation, this doesn't need to be incredibly precise
fixed_t sine = 8 * FINESINE((((4*pi*(TICRATE)) * followertimer)>>ANGLETOFINESHIFT) & FINEMASK);
UINT8 *colormap = R_GetTranslationColormap(-1, setupm_fakecolor, 0);
V_DrawMappedPatch(mx+65, my+90+(sine/FRACUNIT), flags, patch, colormap);
Z_Free(colormap);
}
}
#undef charw #undef charw
} }
// follower state update. This is its own function so that it's at least somewhat clean
static void M_GetFollowerState(void)
{
if (setupm_fakefollower == -1 || setupm_fakefollower > numfollowers-1) // yikes, there's none!
return;
// ^ we don't actually need to set anything since it won't be displayed anyway.
//followertimer = 0; // reset timer. not like it'll overflow anytime soon but whatever.
// set follower state
follower_state = &states[followers[setupm_fakefollower].followstate];
if (follower_state->frame & FF_ANIMATE)
follower_tics = follower_state->var2; // support for FF_ANIMATE
else
follower_tics = follower_state->tics;
follower_frame = follower_state->frame & FF_FRAMEMASK;
}
// Handle 1P/2P MP Setup // Handle 1P/2P MP Setup
static void M_HandleSetupMultiPlayer(INT32 choice) static void M_HandleSetupMultiPlayer(INT32 choice)
{ {
@ -8289,7 +8396,13 @@ static void M_HandleSetupMultiPlayer(INT32 choice)
S_StartSound(NULL,sfx_menu1); // Tails S_StartSound(NULL,sfx_menu1); // Tails
setupm_fakeskin--; setupm_fakeskin--;
} }
else if (itemOn == 2) // player color else if (itemOn == 2) // follower
{
S_StartSound(NULL,sfx_menu1);
setupm_fakefollower--;
M_GetFollowerState(); // update follower state
}
else if (itemOn == 3) // player color
{ {
S_StartSound(NULL,sfx_menu1); // Tails S_StartSound(NULL,sfx_menu1); // Tails
setupm_fakecolor--; setupm_fakecolor--;
@ -8301,8 +8414,15 @@ static void M_HandleSetupMultiPlayer(INT32 choice)
{ {
S_StartSound(NULL,sfx_menu1); // Tails S_StartSound(NULL,sfx_menu1); // Tails
setupm_fakeskin++; setupm_fakeskin++;
M_GetFollowerState(); // update follower state
} }
else if (itemOn == 2) // player color else if (itemOn == 2) // follower
{
S_StartSound(NULL,sfx_menu1);
setupm_fakefollower++;
M_GetFollowerState();
}
else if (itemOn == 3) // player color
{ {
S_StartSound(NULL,sfx_menu1); // Tails S_StartSound(NULL,sfx_menu1); // Tails
setupm_fakecolor++; setupm_fakecolor++;
@ -8322,7 +8442,12 @@ static void M_HandleSetupMultiPlayer(INT32 choice)
setupm_name[l-1] =0; setupm_name[l-1] =0;
} }
} }
else if (itemOn == 2) else if (itemOn == 2) // follower
{
S_StartSound(NULL,sfx_menu1);
setupm_fakefollower = -1;
}
else if (itemOn == 3)
{ {
UINT8 col = skins[setupm_fakeskin].prefcolor; UINT8 col = skins[setupm_fakeskin].prefcolor;
if (setupm_fakecolor != col) if (setupm_fakecolor != col)
@ -8360,6 +8485,18 @@ static void M_HandleSetupMultiPlayer(INT32 choice)
if (setupm_fakeskin > numskins-1) if (setupm_fakeskin > numskins-1)
setupm_fakeskin = 0; setupm_fakeskin = 0;
// check followers:
if (setupm_fakefollower < -1)
{
setupm_fakefollower = numfollowers-1;
M_GetFollowerState(); // update follower state
}
if (setupm_fakefollower > numfollowers-1)
{
setupm_fakefollower = -1;
M_GetFollowerState(); // update follower state
}
// check color // check color
if (setupm_fakecolor < 1) if (setupm_fakecolor < 1)
setupm_fakecolor = MAXSKINCOLORS-1; setupm_fakecolor = MAXSKINCOLORS-1;
@ -8382,6 +8519,7 @@ static void M_SetupMultiPlayer(INT32 choice)
multi_state = &states[mobjinfo[MT_PLAYER].seestate]; multi_state = &states[mobjinfo[MT_PLAYER].seestate];
multi_tics = multi_state->tics; multi_tics = multi_state->tics;
strcpy(setupm_name, cv_playername.string); strcpy(setupm_name, cv_playername.string);
// set for player 1 // set for player 1
@ -8389,6 +8527,10 @@ static void M_SetupMultiPlayer(INT32 choice)
setupm_cvskin = &cv_skin; setupm_cvskin = &cv_skin;
setupm_cvcolor = &cv_playercolor; setupm_cvcolor = &cv_playercolor;
setupm_cvname = &cv_playername; setupm_cvname = &cv_playername;
setupm_cvfollower = &cv_follower;
setupm_fakefollower = atoi(setupm_cvfollower->string); // update fake follower value
M_GetFollowerState(); // update follower state
// For whatever reason this doesn't work right if you just use ->value // For whatever reason this doesn't work right if you just use ->value
setupm_fakeskin = R_SkinAvailable(setupm_cvskin->string); setupm_fakeskin = R_SkinAvailable(setupm_cvskin->string);
@ -8420,6 +8562,10 @@ static void M_SetupMultiPlayer2(INT32 choice)
setupm_cvskin = &cv_skin2; setupm_cvskin = &cv_skin2;
setupm_cvcolor = &cv_playercolor2; setupm_cvcolor = &cv_playercolor2;
setupm_cvname = &cv_playername2; setupm_cvname = &cv_playername2;
setupm_cvfollower = &cv_follower;
setupm_fakefollower = atoi(setupm_cvfollower->string); // update fake follower value
M_GetFollowerState(); // update follower state
// For whatever reason this doesn't work right if you just use ->value // For whatever reason this doesn't work right if you just use ->value
setupm_fakeskin = R_SkinAvailable(setupm_cvskin->string); setupm_fakeskin = R_SkinAvailable(setupm_cvskin->string);
@ -8451,6 +8597,10 @@ static void M_SetupMultiPlayer3(INT32 choice)
setupm_cvskin = &cv_skin3; setupm_cvskin = &cv_skin3;
setupm_cvcolor = &cv_playercolor3; setupm_cvcolor = &cv_playercolor3;
setupm_cvname = &cv_playername3; setupm_cvname = &cv_playername3;
setupm_cvfollower = &cv_follower;
setupm_fakefollower = atoi(setupm_cvfollower->string); // update fake follower value
M_GetFollowerState(); // update follower state
// For whatever reason this doesn't work right if you just use ->value // For whatever reason this doesn't work right if you just use ->value
setupm_fakeskin = R_SkinAvailable(setupm_cvskin->string); setupm_fakeskin = R_SkinAvailable(setupm_cvskin->string);
@ -8482,6 +8632,10 @@ static void M_SetupMultiPlayer4(INT32 choice)
setupm_cvskin = &cv_skin4; setupm_cvskin = &cv_skin4;
setupm_cvcolor = &cv_playercolor4; setupm_cvcolor = &cv_playercolor4;
setupm_cvname = &cv_playername4; setupm_cvname = &cv_playername4;
setupm_cvfollower = &cv_follower;
setupm_fakefollower = atoi(setupm_cvfollower->string); // update fake follower value
M_GetFollowerState(); // update follower state
// For whatever reason this doesn't work right if you just use ->value // For whatever reason this doesn't work right if you just use ->value
setupm_fakeskin = R_SkinAvailable(setupm_cvskin->string); setupm_fakeskin = R_SkinAvailable(setupm_cvskin->string);
@ -8514,6 +8668,7 @@ static boolean M_QuitMultiPlayerMenu(void)
// you know what? always putting these in the buffer won't hurt anything. // you know what? always putting these in the buffer won't hurt anything.
COM_BufAddText (va("%s \"%s\"\n",setupm_cvskin->name,skins[setupm_fakeskin].name)); COM_BufAddText (va("%s \"%s\"\n",setupm_cvskin->name,skins[setupm_fakeskin].name));
COM_BufAddText (va("%s %d\n",setupm_cvcolor->name,setupm_fakecolor)); COM_BufAddText (va("%s %d\n",setupm_cvcolor->name,setupm_fakecolor));
COM_BufAddText (va("%s %d\n",setupm_cvfollower->name,setupm_fakefollower));
return true; return true;
} }

View file

@ -2637,6 +2637,19 @@ INT32 R_SkinAvailable(const char *name)
return -1; return -1;
} }
// same thing but for followers:
INT32 R_FollowerAvailable(const char *name)
{
INT32 i;
for (i = 0; i < numfollowers; i++)
{
if (stricmp(followers[i].skinname,name)==0)
return i;
}
return -1;
}
// network code calls this when a 'skin change' is received // network code calls this when a 'skin change' is received
boolean SetPlayerSkin(INT32 playernum, const char *skinname) boolean SetPlayerSkin(INT32 playernum, const char *skinname)
{ {
@ -2662,13 +2675,38 @@ boolean SetPlayerSkin(INT32 playernum, const char *skinname)
return false; return false;
} }
// Again, same thing but for followers;
boolean SetPlayerFollower(INT32 playernum, const char *skinname)
{
INT32 i;
player_t *player = &players[playernum];
for (i = 0; i < numfollowers; i++)
{
// search in the skin list
if (stricmp(followers[i].skinname, skinname) == 0)
{
SetFollower(playernum, i);
return true;
}
}
if (P_IsLocalPlayer(player))
CONS_Alert(CONS_WARNING, M_GetText("Follower '%s' not found.\n"), skinname);
else if(server || IsPlayerAdmin(consoleplayer))
CONS_Alert(CONS_WARNING, M_GetText("Player %d (%s) follower '%s' not found\n"), playernum, player_names[playernum], skinname);
SetFollower(playernum, -1); // reminder that -1 is nothing
return false;
}
// Same as SetPlayerSkin, but uses the skin #. // Same as SetPlayerSkin, but uses the skin #.
// network code calls this when a 'skin change' is received // network code calls this when a 'skin change' is received
void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum) void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum)
{ {
player_t *player = &players[playernum]; player_t *player = &players[playernum];
skin_t *skin = &skins[skinnum]; skin_t *skin = &skins[skinnum];
CONS_Printf("skin\n");
if (skinnum >= 0 && skinnum < numskins) // Make sure it exists! if (skinnum >= 0 && skinnum < numskins) // Make sure it exists!
{ {
player->skin = skinnum; player->skin = skinnum;
@ -2727,6 +2765,30 @@ void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum)
SetPlayerSkinByNum(playernum, 0); // not found put the sonic skin SetPlayerSkinByNum(playernum, 0); // not found put the sonic skin
} }
// you get the drill, now we do the same for followers:
void SetFollower(INT32 playernum, INT32 skinnum)
{
player_t *player = &players[playernum];
if (skinnum >= -1 && skinnum <= numfollowers) // Make sure it exists!
{
player->followerskin = skinnum;
CONS_Printf("Updated player follower num\n");
/*
We don't actually set anything there, becasuse we need to be sure that a proper player->mo is available to spawn the follower.
Moreover, the follower will self-handle itself the rest of the time, hence, its skinnum stored to the player is all we need right now.
*/
return;
}
if (P_IsLocalPlayer(player))
CONS_Alert(CONS_WARNING, M_GetText("Follower %d not found\n"), skinnum);
else if(server || IsPlayerAdmin(consoleplayer))
CONS_Alert(CONS_WARNING, "Player %d (%s) follower %d not found\n", playernum, player_names[playernum], skinnum);
SetFollower(playernum, -1); // Not found, then set -1 (nothing) as our follower.
}
// //
// Add skins from a pwad, each skin preceded by 'S_SKIN' marker // Add skins from a pwad, each skin preceded by 'S_SKIN' marker
// //

View file

@ -122,6 +122,7 @@ typedef struct
// //
typedef struct follower_s 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. char name[SKINNAMESIZE+1]; // Name. This is used for the menus. We'll just follow the same rules as skins for this.
// some position shenanigans: // some position shenanigans:
@ -225,6 +226,10 @@ void SetPlayerSkinByNum(INT32 playernum,INT32 skinnum); // Tails 03-16-2002
INT32 R_SkinAvailable(const char *name); INT32 R_SkinAvailable(const char *name);
void R_AddSkins(UINT16 wadnum); void R_AddSkins(UINT16 wadnum);
INT32 R_FollowerAvailable(const char *name);
boolean SetPlayerFollower(INT32 playernum,const char *skinname);
void SetFollower(INT32 playernum,INT32 skinnum);
#ifdef DELFILE #ifdef DELFILE
void R_DelSkins(UINT16 wadnum); void R_DelSkins(UINT16 wadnum);
#endif #endif