diff --git a/src/d_clisrv.c b/src/d_clisrv.c index decc2e74b..3878d8795 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -768,8 +768,16 @@ static void resynch_read_player(resynch_pak *rsp) players[i].mo->scalespeed = LONG(rsp->scalespeed); // And finally, SET THE MOBJ SKIN damn it. - players[i].mo->skin = &skins[players[i].skin]; - players[i].mo->color = players[i].skincolor; + if ((players[i].powers[pw_carry] == CR_NIGHTSMODE) && (skins[players[i].skin].sprites[SPR2_NGT0].numframes == 0)) + { + players[i].mo->skin = &skins[DEFAULTNIGHTSSKIN]; + players[i].mo->color = skins[DEFAULTNIGHTSSKIN].prefcolor; // this will be corrected by thinker to super flash + } + else + { + players[i].mo->skin = &skins[players[i].skin]; + players[i].mo->color = players[i].skincolor; // this will be corrected by thinker to super flash/mario star + } P_SetThingPosition(players[i].mo); } @@ -883,6 +891,7 @@ static inline void resynch_write_others(resynchend_pak *rst) UINT8 i; rst->ingame = 0; + rst->outofcoop = 0; for (i = 0; i < MAXPLAYERS; ++i) { @@ -899,6 +908,8 @@ static inline void resynch_write_others(resynchend_pak *rst) if (!players[i].spectator) rst->ingame |= (1<outofcoop |= (1<ctfteam[i] = (INT32)LONG(players[i].ctfteam); rst->score[i] = (UINT32)LONG(players[i].score); rst->numboxes[i] = SHORT(players[i].numboxes); @@ -915,11 +926,13 @@ static inline void resynch_read_others(resynchend_pak *p) { UINT8 i; UINT32 loc_ingame = (UINT32)LONG(p->ingame); + UINT32 loc_outofcoop = (UINT32)LONG(p->outofcoop); for (i = 0; i < MAXPLAYERS; ++i) { // We don't care if they're in the game or not, just write all the data. players[i].spectator = !(loc_ingame & (1<ctfteam[i]); // no, 0 does not mean spectator, at least not in Match players[i].score = (UINT32)LONG(p->score[i]); players[i].numboxes = SHORT(p->numboxes[i]); @@ -1319,7 +1332,7 @@ static void SV_SendPlayerInfo(INT32 node) netbuffer->u.playerinfo[i].skin = (UINT8)players[i].skin; // Extra data - netbuffer->u.playerinfo[i].data = players[i].skincolor; + netbuffer->u.playerinfo[i].data = 0; //players[i].skincolor; if (players[i].pflags & PF_TAGIT) netbuffer->u.playerinfo[i].data |= 0x20; diff --git a/src/d_clisrv.h b/src/d_clisrv.h index da077c682..b9a4eec3e 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -136,6 +136,7 @@ typedef struct fixed_t flagz[2]; UINT32 ingame; // Spectator bit for each player + UINT32 outofcoop; // outofcoop bit for each player INT32 ctfteam[MAXPLAYERS]; // Which team? (can't be 1 bit, since in regular Match there are no teams) // Resynch game scores and the like all at once diff --git a/src/d_main.c b/src/d_main.c index f01bcb84d..27ab71641 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -724,6 +724,14 @@ void D_StartTitle(void) // empty maptol so mario/etc sounds don't play in sound test when they shouldn't maptol = 0; + // reset to default player stuff + COM_BufAddText (va("%s \"%s\"\n",cv_playername.name,cv_defaultplayername.string)); + COM_BufAddText (va("%s \"%s\"\n",cv_skin.name,cv_defaultskin.string)); + COM_BufAddText (va("%s \"%s\"\n",cv_playercolor.name,cv_defaultplayercolor.string)); + COM_BufAddText (va("%s \"%s\"\n",cv_playername2.name,cv_defaultplayername2.string)); + COM_BufAddText (va("%s \"%s\"\n",cv_skin2.name,cv_defaultskin2.string)); + COM_BufAddText (va("%s \"%s\"\n",cv_playercolor2.name,cv_defaultplayercolor2.string)); + gameaction = ga_nothing; displayplayer = consoleplayer = 0; gametype = GT_COOP; diff --git a/src/d_netcmd.c b/src/d_netcmd.c index d7aabe253..4c9ed9625 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -61,9 +61,6 @@ static void Got_WeaponPref(UINT8 **cp, INT32 playernum); static void Got_Mapcmd(UINT8 **cp, INT32 playernum); static void Got_ExitLevelcmd(UINT8 **cp, INT32 playernum); static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum); -#ifdef DELFILE -static void Got_Delfilecmd(UINT8 **cp, INT32 playernum); -#endif static void Got_Addfilecmd(UINT8 **cp, INT32 playernum); static void Got_Pause(UINT8 **cp, INT32 playernum); static void Got_Suicide(UINT8 **cp, INT32 playernum); @@ -85,6 +82,9 @@ static void TeamScramble_OnChange(void); static void NetTimeout_OnChange(void); static void JoinTimeout_OnChange(void); +static void CoopStarposts_OnChange(void); +static void CoopLives_OnChange(void); + static void Ringslinger_OnChange(void); static void Gravity_OnChange(void); static void ForceSkin_OnChange(void); @@ -112,9 +112,6 @@ static void Command_ResetCamera_f(void); static void Command_Addfile(void); static void Command_ListWADS_f(void); -#ifdef DELFILE -static void Command_Delfile(void); -#endif static void Command_RunSOC(void); static void Command_Pause(void); static void Command_Suicide(void); @@ -185,15 +182,14 @@ static CV_PossibleValue_t joyport_cons_t[] = {{1, "/dev/js0"}, {2, "/dev/js1"}, #define usejoystick_cons_t NULL #endif -static CV_PossibleValue_t autobalance_cons_t[] = {{0, "MIN"}, {4, "MAX"}, {0, NULL}}; static CV_PossibleValue_t teamscramble_cons_t[] = {{0, "Off"}, {1, "Random"}, {2, "Points"}, {0, NULL}}; static CV_PossibleValue_t startingliveslimit_cons_t[] = {{1, "MIN"}, {99, "MAX"}, {0, NULL}}; static CV_PossibleValue_t sleeping_cons_t[] = {{-1, "MIN"}, {1000/TICRATE, "MAX"}, {0, NULL}}; -static CV_PossibleValue_t competitionboxes_cons_t[] = {{0, "Normal"}, {1, "Random"}, //{2, "Teleports"}, +static CV_PossibleValue_t competitionboxes_cons_t[] = {{0, "Normal"}, {1, "Mystery"}, //{2, "Teleport"}, {3, "None"}, {0, NULL}}; -static CV_PossibleValue_t matchboxes_cons_t[] = {{0, "Normal"}, {1, "Random"}, {2, "Non-Random"}, +static CV_PossibleValue_t matchboxes_cons_t[] = {{0, "Normal"}, {1, "Mystery"}, {2, "Unchanging"}, {3, "None"}, {0, NULL}}; static CV_PossibleValue_t chances_cons_t[] = {{0, "MIN"}, {9, "MAX"}, {0, NULL}}; @@ -215,7 +211,7 @@ consvar_t cv_startinglives = {"startinglives", "3", CV_NETVAR|CV_CHEAT, starting static CV_PossibleValue_t respawntime_cons_t[] = {{0, "MIN"}, {30, "MAX"}, {0, NULL}}; consvar_t cv_respawntime = {"respawndelay", "3", CV_NETVAR|CV_CHEAT, respawntime_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_competitionboxes = {"competitionboxes", "Random", CV_NETVAR|CV_CHEAT, competitionboxes_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_competitionboxes = {"competitionboxes", "Mystery", CV_NETVAR|CV_CHEAT, competitionboxes_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; #ifdef SEENAMES static CV_PossibleValue_t seenames_cons_t[] = {{0, "Off"}, {1, "Colorless"}, {2, "Team"}, {3, "Ally/Foe"}, {0, NULL}}; @@ -223,9 +219,9 @@ consvar_t cv_seenames = {"seenames", "Ally/Foe", CV_SAVE, seenames_cons_t, 0, 0, consvar_t cv_allowseenames = {"allowseenames", "Yes", CV_NETVAR, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; #endif -// these are just meant to be saved to the config -consvar_t cv_playername = {"name", "Sonic", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Name_OnChange, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_playername2 = {"name2", "Tails", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Name2_OnChange, 0, NULL, NULL, 0, 0, NULL}; +// names +consvar_t cv_playername = {"name", "Sonic", CV_CALL|CV_NOINIT, NULL, Name_OnChange, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_playername2 = {"name2", "Tails", CV_CALL|CV_NOINIT, NULL, Name2_OnChange, 0, NULL, NULL, 0, 0, NULL}; // player colors consvar_t cv_playercolor = {"color", "Blue", CV_CALL|CV_NOINIT, Color_cons_t, Color_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_playercolor2 = {"color2", "Orange", CV_CALL|CV_NOINIT, Color_cons_t, Color2_OnChange, 0, NULL, NULL, 0, 0, NULL}; @@ -233,6 +229,14 @@ consvar_t cv_playercolor2 = {"color2", "Orange", CV_CALL|CV_NOINIT, Color_cons_t consvar_t cv_skin = {"skin", DEFAULTSKIN, CV_CALL|CV_NOINIT, NULL, Skin_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_skin2 = {"skin2", DEFAULTSKIN2, CV_CALL|CV_NOINIT, NULL, Skin2_OnChange, 0, NULL, NULL, 0, 0, NULL}; +// saved versions of the above six +consvar_t cv_defaultplayername = {"defaultname", "Sonic", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_defaultplayername2 = {"defaultname2", "Tails", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_defaultplayercolor = {"defaultcolor", "Blue", CV_SAVE, Color_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_defaultplayercolor2 = {"defaultcolor2", "Orange", CV_SAVE, Color_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_defaultskin = {"defaultskin", DEFAULTSKIN, CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_defaultskin2 = {"defaultskin2", DEFAULTSKIN2, CV_SAVE, NULL, 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; @@ -303,7 +307,7 @@ consvar_t cv_countdowntime = {"countdowntime", "60", CV_NETVAR|CV_CHEAT, minitim consvar_t cv_touchtag = {"touchtag", "Off", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_hidetime = {"hidetime", "30", CV_NETVAR|CV_CALL, minitimelimit_cons_t, Hidetime_OnChange, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_autobalance = {"autobalance", "0", CV_NETVAR|CV_CALL, autobalance_cons_t, AutoBalance_OnChange, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_autobalance = {"autobalance", "Off", CV_NETVAR|CV_CALL, CV_OnOff, AutoBalance_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_teamscramble = {"teamscramble", "Off", CV_NETVAR|CV_CALL|CV_NOINIT, teamscramble_cons_t, TeamScramble_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_scrambleonchange = {"scrambleonchange", "Off", CV_NETVAR, teamscramble_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -348,12 +352,18 @@ consvar_t cv_maxping = {"maxping", "0", CV_SAVE, CV_Unsigned, NULL, 0, NULL, NUL #endif // Intermission time Tails 04-19-2002 static CV_PossibleValue_t inttime_cons_t[] = {{0, "MIN"}, {3600, "MAX"}, {0, NULL}}; -consvar_t cv_inttime = {"inttime", "20", CV_NETVAR, inttime_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_inttime = {"inttime", "10", CV_NETVAR, inttime_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; + +static CV_PossibleValue_t coopstarposts_cons_t[] = {{0, "Per-player"}, {1, "Shared"}, {2, "Teamwork"}, {0, NULL}}; +consvar_t cv_coopstarposts = {"coopstarposts", "Teamwork", CV_NETVAR|CV_CALL|CV_CHEAT, coopstarposts_cons_t, CoopStarposts_OnChange, 0, NULL, NULL, 0, 0, NULL}; + +static CV_PossibleValue_t cooplives_cons_t[] = {{0, "Infinite"}, {1, "Per-player"}, {2, "Avoid Game Over"}, {3, "Single pool"}, {0, NULL}}; +consvar_t cv_cooplives = {"cooplives", "Avoid Game Over", CV_NETVAR|CV_CALL|CV_CHEAT, cooplives_cons_t, CoopLives_OnChange, 0, NULL, NULL, 0, 0, NULL}; static CV_PossibleValue_t advancemap_cons_t[] = {{0, "Off"}, {1, "Next"}, {2, "Random"}, {0, NULL}}; consvar_t cv_advancemap = {"advancemap", "Next", CV_NETVAR, advancemap_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -static CV_PossibleValue_t playersforexit_cons_t[] = {{0, "One"}, {1, "All"}, {0, NULL}}; -consvar_t cv_playersforexit = {"playersforexit", "One", CV_NETVAR, playersforexit_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +static CV_PossibleValue_t playersforexit_cons_t[] = {{0, "One"}, {1, "1/4"}, {2, "Half"}, {3, "3/4"}, {4, "All"}, {0, NULL}}; +consvar_t cv_playersforexit = {"playersforexit", "All", CV_NETVAR, playersforexit_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_runscripts = {"runscripts", "Yes", 0, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -387,7 +397,7 @@ const char *netxcmdnames[MAXNETXCMD - 1] = "RANDOMSEED", "RUNSOC", "REQADDFILE", - "DELFILE", + "DELFILE", // replace next time we add an XD "SETMOTD", "SUICIDE", #ifdef HAVE_BLUA @@ -413,9 +423,6 @@ void D_RegisterServerCommands(void) RegisterNetXCmd(XD_EXITLEVEL, Got_ExitLevelcmd); RegisterNetXCmd(XD_ADDFILE, Got_Addfilecmd); RegisterNetXCmd(XD_REQADDFILE, Got_RequestAddfilecmd); -#ifdef DELFILE - RegisterNetXCmd(XD_DELFILE, Got_Delfilecmd); -#endif RegisterNetXCmd(XD_PAUSE, Got_Pause); RegisterNetXCmd(XD_SUICIDE, Got_Suicide); RegisterNetXCmd(XD_RUNSOC, Got_RunSOCcmd); @@ -449,9 +456,6 @@ void D_RegisterServerCommands(void) COM_AddCommand("addfile", Command_Addfile); COM_AddCommand("listwad", Command_ListWADS_f); -#ifdef DELFILE - COM_AddCommand("delfile", Command_Delfile); -#endif COM_AddCommand("runsoc", Command_RunSOC); COM_AddCommand("pause", Command_Pause); COM_AddCommand("suicide", Command_Suicide); @@ -508,6 +512,9 @@ void D_RegisterServerCommands(void) CV_RegisterVar(&cv_forceskin); CV_RegisterVar(&cv_downloading); + CV_RegisterVar(&cv_coopstarposts); + CV_RegisterVar(&cv_cooplives); + CV_RegisterVar(&cv_specialrings); CV_RegisterVar(&cv_powerstones); CV_RegisterVar(&cv_competitionboxes); @@ -636,7 +643,7 @@ void D_RegisterClientCommands(void) // register these so it is saved to config if ((username = I_GetUserName())) - cv_playername.defaultvalue = username; + cv_playername.defaultvalue = cv_defaultplayername.defaultvalue = username; CV_RegisterVar(&cv_playername); CV_RegisterVar(&cv_playercolor); CV_RegisterVar(&cv_skin); // r_things.c (skin NAME) @@ -644,6 +651,13 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_playername2); CV_RegisterVar(&cv_playercolor2); CV_RegisterVar(&cv_skin2); + // saved versions of the above six + CV_RegisterVar(&cv_defaultplayername); + CV_RegisterVar(&cv_defaultplayercolor); + CV_RegisterVar(&cv_defaultskin); + CV_RegisterVar(&cv_defaultplayername2); + CV_RegisterVar(&cv_defaultplayercolor2); + CV_RegisterVar(&cv_defaultskin2); #ifdef SEENAMES CV_RegisterVar(&cv_seenames); @@ -1173,7 +1187,7 @@ static void SendNameAndColor(void) { CV_StealthSetValue(&cv_playercolor, skins[cv_skin.value].prefcolor); - players[consoleplayer].skincolor = (cv_playercolor.value&0x1F) % MAXSKINCOLORS; + players[consoleplayer].skincolor = cv_playercolor.value % MAXSKINCOLORS; if (players[consoleplayer].mo) players[consoleplayer].mo->color = (UINT8)players[consoleplayer].skincolor; @@ -1300,7 +1314,7 @@ static void SendNameAndColor2(void) { CV_StealthSetValue(&cv_playercolor2, skins[players[secondplaya].skin].prefcolor); - players[secondplaya].skincolor = (cv_playercolor2.value&0x1F) % MAXSKINCOLORS; + players[secondplaya].skincolor = cv_playercolor2.value % MAXSKINCOLORS; if (players[secondplaya].mo) players[secondplaya].mo->color = players[secondplaya].skincolor; @@ -3082,42 +3096,6 @@ static void Command_Addfile(void) SendNetXCmd(XD_ADDFILE, buf, buf_p - buf); } -#ifdef DELFILE -/** removes the last added pwad at runtime. - * Searches for sounds, maps, music and images to remove - */ -static void Command_Delfile(void) -{ - if (gamestate == GS_LEVEL) - { - CONS_Printf(M_GetText("You must NOT be in a level to use this.\n")); - return; - } - - if (netgame && !(server || adminplayer == consoleplayer)) - { - CONS_Printf(M_GetText("Only the server or a remote admin can use this.\n")); - return; - } - - if (numwadfiles <= mainwads) - { - CONS_Printf(M_GetText("No additional WADs are loaded.\n")); - return; - } - - if (!(netgame || multiplayer)) - { - P_DelWadFile(); - if (mainwads == numwadfiles && modifiedgame) - modifiedgame = false; - return; - } - - SendNetXCmd(XD_DELFILE, NULL, 0); -} -#endif - static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum) { char filename[241]; @@ -3192,33 +3170,6 @@ static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum) COM_BufAddText(va("addfile %s\n", filename)); } -#ifdef DELFILE -static void Got_Delfilecmd(UINT8 **cp, INT32 playernum) -{ - if (playernum != serverplayer && playernum != adminplayer) - { - CONS_Alert(CONS_WARNING, M_GetText("Illegal delfile command received from %s\n"), player_names[playernum]); - if (server) - { - XBOXSTATIC UINT8 buf[2]; - - buf[0] = (UINT8)playernum; - buf[1] = KICK_MSG_CON_FAIL; - SendNetXCmd(XD_KICK, &buf, 2); - } - return; - } - (void)cp; - - if (numwadfiles <= mainwads) //sanity - return; - - P_DelWadFile(); - if (mainwads == numwadfiles && modifiedgame) - modifiedgame = false; -} -#endif - static void Got_Addfilecmd(UINT8 **cp, INT32 playernum) { char filename[241]; @@ -3424,6 +3375,102 @@ static void JoinTimeout_OnChange(void) jointimeout = (tic_t)cv_jointimeout.value; } +static void CoopStarposts_OnChange(void) +{ + INT32 i; + + if (!(netgame || multiplayer) || gametype != GT_COOP) + return; + + switch (cv_coopstarposts.value) + { + case 0: + CONS_Printf(M_GetText("Starposts are now per-player.\n")); + break; + case 1: + CONS_Printf(M_GetText("Starposts are now shared between players.\n")); + break; + case 2: + CONS_Printf(M_GetText("Players now only spawn when starposts are hit.\n")); + return; + } + + if (G_IsSpecialStage(gamemap)) + return; + + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; + + if (!players[i].spectator) + continue; + + if (players[i].lives <= 0) + continue; + + break; + } + + if (i == MAXPLAYERS) + return; + + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; + + if (!players[i].spectator) + continue; + + if (players[i].lives <= 0 && (cv_cooplives.value == 1)) + continue; + + P_SpectatorJoinGame(&players[i]); + } +} + +static void CoopLives_OnChange(void) +{ + INT32 i; + + if (!(netgame || multiplayer) || gametype != GT_COOP) + return; + + switch (cv_cooplives.value) + { + case 0: + CONS_Printf(M_GetText("Players can now respawn indefinitely.\n")); + return; + case 1: + CONS_Printf(M_GetText("Lives are now per-player.\n")); + return; + case 2: + CONS_Printf(M_GetText("Players can now steal lives to avoid game over.\n")); + break; + case 3: + CONS_Printf(M_GetText("Lives are now shared between players.\n")); + break; + } + + if (cv_coopstarposts.value == 2) + return; + + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; + + if (!players[i].spectator) + continue; + + if (players[i].lives > 0) + continue; + + P_SpectatorJoinGame(&players[i]); + } +} + UINT32 timelimitintics = 0; /** Deals with a timelimit change by printing the change to the console. @@ -3714,7 +3761,7 @@ retryscramble: { if (red == maxcomposition) newteam = 2; - else if (blue == maxcomposition) + else //if (blue == maxcomposition) newteam = 1; repick = false; @@ -3755,14 +3802,11 @@ retryscramble: newteam = (INT16)((M_RandomByte() % 2) + 1); repick = false; } - else + else if (i != 2) // Mystic's secret sauce - ABBA is better than ABAB, so team B doesn't get worse players all around { // We will only randomly pick the team for the first guy. // Otherwise, just alternate back and forth, distributing players. - if (newteam == 1) - newteam = 2; - else - newteam = 1; + newteam = 3 - newteam; } scrambleteams[i] = newteam; diff --git a/src/d_netcmd.h b/src/d_netcmd.h index 80481c6a5..57e23b0f1 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -25,6 +25,13 @@ extern consvar_t cv_skin; extern consvar_t cv_playername2; extern consvar_t cv_playercolor2; extern consvar_t cv_skin2; +// saved versions of the above six +extern consvar_t cv_defaultplayername; +extern consvar_t cv_defaultplayercolor; +extern consvar_t cv_defaultskin; +extern consvar_t cv_defaultplayername2; +extern consvar_t cv_defaultplayercolor2; +extern consvar_t cv_defaultskin2; #ifdef SEENAMES extern consvar_t cv_seenames, cv_allowseenames; @@ -89,7 +96,7 @@ extern consvar_t cv_recycler; extern consvar_t cv_itemfinder; -extern consvar_t cv_inttime, cv_advancemap, cv_playersforexit; +extern consvar_t cv_inttime, cv_coopstarposts, cv_cooplives, cv_advancemap, cv_playersforexit; extern consvar_t cv_overtime; extern consvar_t cv_startinglives; @@ -129,7 +136,7 @@ typedef enum XD_RANDOMSEED, // 15 XD_RUNSOC, // 16 XD_REQADDFILE, // 17 - XD_DELFILE, // 18 + XD_DELFILE, // 18 - replace next time we add an XD XD_SETMOTD, // 19 XD_SUICIDE, // 20 #ifdef HAVE_BLUA diff --git a/src/d_player.h b/src/d_player.h index f8b38ded9..d578d15ef 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -481,6 +481,7 @@ typedef struct player_s angle_t awayviewaiming; // Used for cut-away view boolean spectator; + boolean outofcoop; UINT8 bot; tic_t jointime; // Timer when player joins game to change skin/color diff --git a/src/dehacked.c b/src/dehacked.c index 6affa302f..719476543 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -78,97 +78,6 @@ static int dbg_line; static boolean gamedataadded = false; -#ifdef DELFILE -typedef struct undehacked_s -{ - char *undata; - struct undehacked_s *next; -} undehacked_t; - -static UINT16 unsocwad; -static undehacked_t *unsocdata[MAX_WADFILES]; -static boolean disableundo = false; - -void DEH_WriteUndoline(const char *value, const char *data, undotype_f flags) -{ - const char *eqstr = " = "; - const char *space = " "; - const char *pader = eqstr; - undehacked_t *newdata; - - if (disableundo || !unsocwad) - return; - - if ((newdata = malloc(sizeof(*newdata))) == NULL) - I_Error("Out of memory for unsoc line"); - - if (flags & UNDO_SPACE) - pader = space; - - if (flags & UNDO_ENDTEXT && !data) - data = space; - - if (value) - { - const size_t plen = strlen(pader); - const char *pound = "#"; - char *undata = NULL; - const size_t elen = strlen(pound); - size_t vlen = strlen(value), dlen = 0, len = 1; - - if (*(value+vlen-1) == '\n') - vlen--; // lnet not copy the ending \n - - if (flags & UNDO_ENDTEXT) - len += elen; // let malloc more space - - if (flags & UNDO_NEWLINE) - len++; // more space for the beginning \n - - if (data) - { - dlen = strlen(data); - if (flags & UNDO_CUTLINE && *(data+dlen-1) == '\n') - dlen--; // let not copy the ending \n - newdata->undata = malloc(vlen+plen+dlen+len); - newdata->undata[vlen+plen+dlen+len-1] = '\0'; - } - else - { - newdata->undata = malloc(vlen+len); - newdata->undata[vlen+len-1] = '\0'; - } - - if (newdata->undata) - { - undata = newdata->undata; - *undata = '\0'; - } - else - { - free(newdata); - I_Error("Out of memory for unsoc data"); - } - - if (flags & UNDO_NEWLINE) // let start with \n - strcat(undata, "\n"); - - strncat(undata, value, vlen); - - if (data) // value+pader+data - strncat(strncat(undata, pader, plen), data, dlen); - - if (flags & UNDO_ENDTEXT) // let end the text - strncat(undata, pound, elen); - } - else - newdata->undata = NULL; - - newdata->next = unsocdata[unsocwad]; - unsocdata[unsocwad] = newdata; -} -#endif - ATTRINLINE static FUNCINLINE char myfget_color(MYFILE *f) { char c = *f->curpos++; @@ -408,8 +317,6 @@ static void readPlayer(MYFILE *f, INT32 num) INT32 i; boolean slotfound = false; - DEH_WriteUndoline("PLAYERTEXT", description[num].notes, UNDO_ENDTEXT); - do { if (myfgets(s, MAXLINELEN, f)) @@ -478,7 +385,6 @@ static void readPlayer(MYFILE *f, INT32 num) { if (!slotfound && (slotfound = findFreeSlot(&num)) == false) goto done; - DEH_WriteUndoline(word, &description[num].picname[0], UNDO_NONE); strncpy(description[num].picname, word2, 8); } @@ -493,7 +399,7 @@ static void readPlayer(MYFILE *f, INT32 num) */ if (i && !slotfound && (slotfound = findFreeSlot(&num)) == false) goto done; - DEH_WriteUndoline(word, va("%d", description[num].used), UNDO_NONE); + description[num].used = (!!i); } else if (fastcmp(word, "SKINNAME")) @@ -501,7 +407,6 @@ static void readPlayer(MYFILE *f, INT32 num) // Send to free slot. if (!slotfound && (slotfound = findFreeSlot(&num)) == false) goto done; - DEH_WriteUndoline(word, description[num].skinname, UNDO_NONE); strlcpy(description[num].skinname, word2, sizeof description[num].skinname); strlwr(description[num].skinname); @@ -511,11 +416,6 @@ static void readPlayer(MYFILE *f, INT32 num) } } while (!myfeof(f)); // finish when the line is empty -#ifdef DELFILE - if (slotfound) - DEH_WriteUndoline("MENUPOSITION", va("%d", num), UNDO_NONE); -#endif - done: Z_Free(s); } @@ -653,122 +553,98 @@ static void readthing(MYFILE *f, INT32 num) if (fastcmp(word, "MAPTHINGNUM") || fastcmp(word, "DOOMEDNUM")) { - DEH_WriteUndoline(word, va("%d", mobjinfo[num].doomednum), UNDO_NONE); mobjinfo[num].doomednum = (INT32)atoi(word2); } else if (fastcmp(word, "SPAWNSTATE")) { - DEH_WriteUndoline(word, va("%d", mobjinfo[num].spawnstate), UNDO_NONE); mobjinfo[num].spawnstate = get_number(word2); } else if (fastcmp(word, "SPAWNHEALTH")) { - DEH_WriteUndoline(word, va("%d", mobjinfo[num].spawnhealth), UNDO_NONE); mobjinfo[num].spawnhealth = (INT32)get_number(word2); } else if (fastcmp(word, "SEESTATE")) { - DEH_WriteUndoline(word, va("%d", mobjinfo[num].seestate), UNDO_NONE); mobjinfo[num].seestate = get_number(word2); } else if (fastcmp(word, "SEESOUND")) { - DEH_WriteUndoline(word, va("%d", mobjinfo[num].seesound), UNDO_NONE); mobjinfo[num].seesound = get_number(word2); } else if (fastcmp(word, "REACTIONTIME")) { - DEH_WriteUndoline(word, va("%d", mobjinfo[num].reactiontime), UNDO_NONE); mobjinfo[num].reactiontime = (INT32)get_number(word2); } else if (fastcmp(word, "ATTACKSOUND")) { - DEH_WriteUndoline(word, va("%d", mobjinfo[num].attacksound), UNDO_NONE); mobjinfo[num].attacksound = get_number(word2); } else if (fastcmp(word, "PAINSTATE")) { - DEH_WriteUndoline(word, va("%d", mobjinfo[num].painstate), UNDO_NONE); mobjinfo[num].painstate = get_number(word2); } else if (fastcmp(word, "PAINCHANCE")) { - DEH_WriteUndoline(word, va("%d", mobjinfo[num].painchance), UNDO_NONE); mobjinfo[num].painchance = (INT32)get_number(word2); } else if (fastcmp(word, "PAINSOUND")) { - DEH_WriteUndoline(word, va("%d", mobjinfo[num].painsound), UNDO_NONE); mobjinfo[num].painsound = get_number(word2); } else if (fastcmp(word, "MELEESTATE")) { - DEH_WriteUndoline(word, va("%d", mobjinfo[num].meleestate), UNDO_NONE); mobjinfo[num].meleestate = get_number(word2); } else if (fastcmp(word, "MISSILESTATE")) { - DEH_WriteUndoline(word, va("%d", mobjinfo[num].missilestate), UNDO_NONE); mobjinfo[num].missilestate = get_number(word2); } else if (fastcmp(word, "DEATHSTATE")) { - DEH_WriteUndoline(word, va("%d", mobjinfo[num].deathstate), UNDO_NONE); mobjinfo[num].deathstate = get_number(word2); } else if (fastcmp(word, "DEATHSOUND")) { - DEH_WriteUndoline(word, va("%d", mobjinfo[num].deathsound), UNDO_NONE); mobjinfo[num].deathsound = get_number(word2); } else if (fastcmp(word, "XDEATHSTATE")) { - DEH_WriteUndoline(word, va("%d", mobjinfo[num].xdeathstate), UNDO_NONE); mobjinfo[num].xdeathstate = get_number(word2); } else if (fastcmp(word, "SPEED")) { - DEH_WriteUndoline(word, va("%d", mobjinfo[num].speed), UNDO_NONE); mobjinfo[num].speed = get_number(word2); } else if (fastcmp(word, "RADIUS")) { - DEH_WriteUndoline(word, va("%d", mobjinfo[num].radius), UNDO_NONE); mobjinfo[num].radius = get_number(word2); } else if (fastcmp(word, "HEIGHT")) { - DEH_WriteUndoline(word, va("%d", mobjinfo[num].height), UNDO_NONE); mobjinfo[num].height = get_number(word2); } else if (fastcmp(word, "DISPOFFSET")) { - DEH_WriteUndoline(word, va("%d", mobjinfo[num].dispoffset), UNDO_NONE); mobjinfo[num].dispoffset = get_number(word2); } else if (fastcmp(word, "MASS")) { - DEH_WriteUndoline(word, va("%d", mobjinfo[num].mass), UNDO_NONE); mobjinfo[num].mass = (INT32)get_number(word2); } else if (fastcmp(word, "DAMAGE")) { - DEH_WriteUndoline(word, va("%d", mobjinfo[num].damage), UNDO_NONE); mobjinfo[num].damage = (INT32)get_number(word2); } else if (fastcmp(word, "ACTIVESOUND")) { - DEH_WriteUndoline(word, va("%d", mobjinfo[num].activesound), UNDO_NONE); mobjinfo[num].activesound = get_number(word2); } else if (fastcmp(word, "FLAGS")) { - DEH_WriteUndoline(word, va("%d", mobjinfo[num].flags), UNDO_NONE); mobjinfo[num].flags = (INT32)get_number(word2); } else if (fastcmp(word, "RAISESTATE")) { - DEH_WriteUndoline(word, va("%d", mobjinfo[num].raisestate), UNDO_NONE); mobjinfo[num].raisestate = get_number(word2); } else @@ -812,37 +688,30 @@ static void readlight(MYFILE *f, INT32 num) if (fastcmp(word, "TYPE")) { - DEH_WriteUndoline(word, va("%d", lspr[num].type), UNDO_NONE); lspr[num].type = (UINT16)value; } else if (fastcmp(word, "OFFSETX")) { - DEH_WriteUndoline(word, va("%f", lspr[num].light_xoffset), UNDO_NONE); lspr[num].light_xoffset = fvalue; } else if (fastcmp(word, "OFFSETY")) { - DEH_WriteUndoline(word, va("%f", lspr[num].light_yoffset), UNDO_NONE); lspr[num].light_yoffset = fvalue; } else if (fastcmp(word, "CORONACOLOR")) { - DEH_WriteUndoline(word, va("%u", lspr[num].corona_color), UNDO_NONE); lspr[num].corona_color = value; } else if (fastcmp(word, "CORONARADIUS")) { - DEH_WriteUndoline(word, va("%f", lspr[num].corona_radius), UNDO_NONE); lspr[num].corona_radius = fvalue; } else if (fastcmp(word, "DYNAMICCOLOR")) { - DEH_WriteUndoline(word, va("%u", lspr[num].dynamic_color), UNDO_NONE); lspr[num].dynamic_color = value; } else if (fastcmp(word, "DYNAMICRADIUS")) { - DEH_WriteUndoline(word, va("%f", lspr[num].dynamic_radius), UNDO_NONE); lspr[num].dynamic_radius = fvalue; /// \note Update the sqrradius! unnecessary? @@ -889,7 +758,6 @@ static void readspritelight(MYFILE *f, INT32 num) INT32 oldvar; for (oldvar = 0; t_lspr[num] != &lspr[oldvar]; oldvar++) ; - DEH_WriteUndoline(word, va("%d", oldvar), UNDO_NONE); t_lspr[num] = &lspr[value]; } else @@ -972,8 +840,6 @@ static void readlevelheader(MYFILE *f, INT32 num) INT32 i; // Reset all previous map header information - // This call automatically saves all previous information when DELFILE is defined. - // We don't need to do it ourselves. P_AllocMapHeader((INT16)(num-1)); do @@ -1399,8 +1265,6 @@ static void readcutscenescene(MYFILE *f, INT32 num, INT32 scenenum) UINT16 usi; UINT8 picid; - DEH_WriteUndoline("SCENETEXT", cutscenes[num]->scene[scenenum].text, UNDO_ENDTEXT); - do { if (myfgets(s, MAXLINELEN, f)) @@ -1477,7 +1341,6 @@ static void readcutscenescene(MYFILE *f, INT32 num, INT32 scenenum) if (fastcmp(word, "NUMBEROFPICS")) { - DEH_WriteUndoline(word, va("%d", cutscenes[num]->scene[scenenum].numpics), UNDO_NONE); cutscenes[num]->scene[scenenum].numpics = (UINT8)i; } else if (fastncmp(word, "PIC", 3)) @@ -1492,27 +1355,22 @@ static void readcutscenescene(MYFILE *f, INT32 num, INT32 scenenum) if (fastcmp(word+4, "NAME")) { - DEH_WriteUndoline(word, cutscenes[num]->scene[scenenum].picname[picid], UNDO_NONE); strncpy(cutscenes[num]->scene[scenenum].picname[picid], word2, 8); } else if (fastcmp(word+4, "HIRES")) { - DEH_WriteUndoline(word, va("%d", cutscenes[num]->scene[scenenum].pichires[picid]), UNDO_NONE); cutscenes[num]->scene[scenenum].pichires[picid] = (UINT8)(i || word2[0] == 'T' || word2[0] == 'Y'); } else if (fastcmp(word+4, "DURATION")) { - DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].picduration[picid]), UNDO_NONE); cutscenes[num]->scene[scenenum].picduration[picid] = usi; } else if (fastcmp(word+4, "XCOORD")) { - DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].xcoord[picid]), UNDO_NONE); cutscenes[num]->scene[scenenum].xcoord[picid] = usi; } else if (fastcmp(word+4, "YCOORD")) { - DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].ycoord[picid]), UNDO_NONE); cutscenes[num]->scene[scenenum].ycoord[picid] = usi; } else @@ -1520,14 +1378,12 @@ static void readcutscenescene(MYFILE *f, INT32 num, INT32 scenenum) } else if (fastcmp(word, "MUSIC")) { - DEH_WriteUndoline(word, cutscenes[num]->scene[scenenum].musswitch, UNDO_NONE); strncpy(cutscenes[num]->scene[scenenum].musswitch, word2, 7); cutscenes[num]->scene[scenenum].musswitch[6] = 0; } #ifdef MUSICSLOT_COMPATIBILITY else if (fastcmp(word, "MUSICSLOT")) { - DEH_WriteUndoline(word, cutscenes[num]->scene[scenenum].musswitch, UNDO_NONE); i = get_mus(word2, true); if (i && i <= 1035) snprintf(cutscenes[num]->scene[scenenum].musswitch, 7, "%sM", G_BuildMapName(i)); @@ -1540,37 +1396,30 @@ static void readcutscenescene(MYFILE *f, INT32 num, INT32 scenenum) #endif else if (fastcmp(word, "MUSICTRACK")) { - DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].musswitchflags), UNDO_NONE); cutscenes[num]->scene[scenenum].musswitchflags = ((UINT16)i) & MUSIC_TRACKMASK; } else if (fastcmp(word, "MUSICLOOP")) { - DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].musicloop), UNDO_NONE); cutscenes[num]->scene[scenenum].musicloop = (UINT8)(i || word2[0] == 'T' || word2[0] == 'Y'); } else if (fastcmp(word, "TEXTXPOS")) { - DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].textxpos), UNDO_NONE); cutscenes[num]->scene[scenenum].textxpos = usi; } else if (fastcmp(word, "TEXTYPOS")) { - DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].textypos), UNDO_NONE); cutscenes[num]->scene[scenenum].textypos = usi; } else if (fastcmp(word, "FADEINID")) { - DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].fadenum), UNDO_NONE); cutscenes[num]->scene[scenenum].fadeinid = (UINT8)i; } else if (fastcmp(word, "FADEOUTID")) { - DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].fadenum), UNDO_NONE); cutscenes[num]->scene[scenenum].fadeoutid = (UINT8)i; } else if (fastcmp(word, "FADECOLOR")) { - DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].fadenum), UNDO_NONE); cutscenes[num]->scene[scenenum].fadecolor = (UINT8)i; } else @@ -1588,9 +1437,6 @@ static void readcutscene(MYFILE *f, INT32 num) char *word2; char *tmp; INT32 value; -#ifdef DELFILE - const INT32 oldnumscenes = cutscenes[num]->numscenes; -#endif // Allocate memory for this cutscene if we don't yet have any if (!cutscenes[num]) @@ -1633,8 +1479,6 @@ static void readcutscene(MYFILE *f, INT32 num) if (1 <= value && value <= 128) { readcutscenescene(f, num, value - 1); - DEH_WriteUndoline(word, word2, UNDO_SPACE|UNDO_CUTLINE); - DEH_WriteUndoline("NUMSCENES", va("%d", oldnumscenes), UNDO_SPACE); } else deh_warning("Scene number %d out of range (1 - 128)", value); @@ -1687,12 +1531,10 @@ static void readhuditem(MYFILE *f, INT32 num) if (fastcmp(word, "X")) { - DEH_WriteUndoline(word, va("%d", hudinfo[num].x), UNDO_NONE); hudinfo[num].x = i; } else if (fastcmp(word, "Y")) { - DEH_WriteUndoline(word, va("%d", hudinfo[num].y), UNDO_NONE); hudinfo[num].y = i; } else @@ -1969,32 +1811,26 @@ static void readframe(MYFILE *f, INT32 num) if (fastcmp(word1, "SPRITENUMBER") || fastcmp(word1, "SPRITENAME")) { - DEH_WriteUndoline(word1, va("%u", states[num].sprite), UNDO_NONE); states[num].sprite = get_sprite(word2); } else if (fastcmp(word1, "SPRITESUBNUMBER") || fastcmp(word1, "SPRITEFRAME")) { - DEH_WriteUndoline(word1, va("%d", states[num].frame), UNDO_NONE); states[num].frame = (INT32)get_number(word2); // So the FF_ flags get calculated } else if (fastcmp(word1, "DURATION")) { - DEH_WriteUndoline(word1, va("%u", states[num].tics), UNDO_NONE); states[num].tics = (INT32)get_number(word2); // So TICRATE can be used } else if (fastcmp(word1, "NEXT")) { - DEH_WriteUndoline(word1, va("%d", states[num].nextstate), UNDO_NONE); states[num].nextstate = get_state(word2); } else if (fastcmp(word1, "VAR1")) { - DEH_WriteUndoline(word1, va("%d", states[num].var1), UNDO_NONE); states[num].var1 = (INT32)get_number(word2); } else if (fastcmp(word1, "VAR2")) { - DEH_WriteUndoline(word1, va("%d", states[num].var2), UNDO_NONE); states[num].var2 = (INT32)get_number(word2); } else if (fastcmp(word1, "ACTION")) @@ -2019,10 +1855,7 @@ static void readframe(MYFILE *f, INT32 num) for (z = 0; actionpointers[z].name; z++) { if (actionpointers[z].action.acv == states[num].action.acv) - { - DEH_WriteUndoline(word1, actionpointers[z].name, UNDO_NONE); break; - } } z = 0; @@ -2092,17 +1925,14 @@ static void readsound(MYFILE *f, INT32 num) if (fastcmp(word, "SINGULAR")) { - DEH_WriteUndoline(word, va("%d", S_sfx[num].singularity), UNDO_NONE); S_sfx[num].singularity = value; } else if (fastcmp(word, "PRIORITY")) { - DEH_WriteUndoline(word, va("%d", S_sfx[num].priority), UNDO_NONE); S_sfx[num].priority = value; } else if (fastcmp(word, "FLAGS")) { - DEH_WriteUndoline(word, va("%d", S_sfx[num].pitch), UNDO_NONE); S_sfx[num].pitch = value; } else if (fastcmp(word, "CAPTION") || fastcmp(word, "DESCRIPTION")) @@ -2146,11 +1976,7 @@ static boolean GoodDataFileName(const char *s) p = s + strlen(s) - strlen(tail); if (p <= s) return false; // too short if (!fasticmp(p, tail)) return false; // doesn't end in .dat -#ifdef DELFILE - if (fasticmp(s, "gamedata.dat") && !disableundo) return false; -#else if (fasticmp(s, "gamedata.dat")) return false; -#endif return true; } @@ -2163,17 +1989,6 @@ static void reademblemdata(MYFILE *f, INT32 num) char *tmp; INT32 value; - // Reset all data initially - DEH_WriteUndoline("TYPE", va("%d", emblemlocations[num-1].type), UNDO_NONE); - DEH_WriteUndoline("X", va("%d", emblemlocations[num-1].x), UNDO_NONE); - DEH_WriteUndoline("Y", va("%d", emblemlocations[num-1].y), UNDO_NONE); - DEH_WriteUndoline("Z", va("%d", emblemlocations[num-1].z), UNDO_NONE); - DEH_WriteUndoline("MAPNUM", va("%d", emblemlocations[num-1].level), UNDO_NONE); - DEH_WriteUndoline("VAR", va("%d", emblemlocations[num-1].var), UNDO_NONE); - DEH_WriteUndoline("SPRITE", va("%d", emblemlocations[num-1].sprite), UNDO_NONE); - DEH_WriteUndoline("COLOR", va("%d", emblemlocations[num-1].color), UNDO_NONE); - DEH_WriteUndoline("HINT", extraemblems[num-1].hint, UNDO_NONE); - memset(&emblemlocations[num-1], 0, sizeof(emblem_t)); do @@ -2309,13 +2124,6 @@ static void readextraemblemdata(MYFILE *f, INT32 num) char *tmp; INT32 value; - // Reset all data initially - DEH_WriteUndoline("NAME", extraemblems[num-1].name, UNDO_NONE); - DEH_WriteUndoline("OBJECTIVE", extraemblems[num-1].description, UNDO_NONE); - DEH_WriteUndoline("CONDITIONSET", va("%d", extraemblems[num-1].conditionset), UNDO_NONE); - DEH_WriteUndoline("SPRITE", va("%d", extraemblems[num-1].sprite), UNDO_NONE); - DEH_WriteUndoline("COLOR", va("%d", extraemblems[num-1].color), UNDO_NONE); - memset(&extraemblems[num-1], 0, sizeof(extraemblem_t)); do @@ -2390,16 +2198,6 @@ static void readunlockable(MYFILE *f, INT32 num) char *tmp; INT32 i; - // Same deal with unlockables, clear all first - DEH_WriteUndoline("NAME", unlockables[num].name, UNDO_NONE); - DEH_WriteUndoline("OBJECTIVE", unlockables[num].objective, UNDO_NONE); - DEH_WriteUndoline("HEIGHT", va("%d", unlockables[num].height), UNDO_NONE); - DEH_WriteUndoline("CONDITIONSET", va("%d", unlockables[num].conditionset), UNDO_NONE); - DEH_WriteUndoline("TYPE", va("%d", unlockables[num].type), UNDO_NONE); - DEH_WriteUndoline("NOCECHO", va("%d", unlockables[num].nocecho), UNDO_NONE); - DEH_WriteUndoline("NOCHECKLIST", va("%d", unlockables[num].nochecklist), UNDO_NONE); - DEH_WriteUndoline("VAR", va("%d", unlockables[num].variable), UNDO_NONE); - memset(&unlockables[num], 0, sizeof(unlockable_t)); unlockables[num].objective[0] = '/'; @@ -2794,7 +2592,6 @@ static void readmaincfg(MYFILE *f) else value = get_number(word2); - DEH_WriteUndoline(word, va("%d", spstage_start), UNDO_NONE); spstage_start = (INT16)value; } else if (fastcmp(word, "SSTAGE_START")) @@ -2808,79 +2605,64 @@ static void readmaincfg(MYFILE *f) else value = get_number(word2); - DEH_WriteUndoline(word, va("%d", sstage_start), UNDO_NONE); sstage_start = (INT16)value; sstage_end = (INT16)(sstage_start+6); // 7 special stages total } else if (fastcmp(word, "USENIGHTSSS")) { - DEH_WriteUndoline(word, va("%d", useNightsSS), UNDO_NONE); useNightsSS = (UINT8)(value || word2[0] == 'T' || word2[0] == 'Y'); } else if (fastcmp(word, "REDTEAM")) { - DEH_WriteUndoline(word, va("%d", skincolor_redteam), UNDO_NONE); skincolor_redteam = (UINT8)get_number(word2); } else if (fastcmp(word, "BLUETEAM")) { - DEH_WriteUndoline(word, va("%d", skincolor_blueteam), UNDO_NONE); skincolor_blueteam = (UINT8)get_number(word2); } else if (fastcmp(word, "REDRING")) { - DEH_WriteUndoline(word, va("%d", skincolor_redring), UNDO_NONE); skincolor_redring = (UINT8)get_number(word2); } else if (fastcmp(word, "BLUERING")) { - DEH_WriteUndoline(word, va("%d", skincolor_bluering), UNDO_NONE); skincolor_bluering = (UINT8)get_number(word2); } else if (fastcmp(word, "INVULNTICS")) { - DEH_WriteUndoline(word, va("%u", invulntics), UNDO_NONE); invulntics = (UINT16)get_number(word2); } else if (fastcmp(word, "SNEAKERTICS")) { - DEH_WriteUndoline(word, va("%u", sneakertics), UNDO_NONE); sneakertics = (UINT16)get_number(word2); } else if (fastcmp(word, "FLASHINGTICS")) { - DEH_WriteUndoline(word, va("%u", flashingtics), UNDO_NONE); flashingtics = (UINT16)get_number(word2); } else if (fastcmp(word, "TAILSFLYTICS")) { - DEH_WriteUndoline(word, va("%u", tailsflytics), UNDO_NONE); tailsflytics = (UINT16)get_number(word2); } else if (fastcmp(word, "UNDERWATERTICS")) { - DEH_WriteUndoline(word, va("%u", underwatertics), UNDO_NONE); underwatertics = (UINT16)get_number(word2); } else if (fastcmp(word, "SPACETIMETICS")) { - DEH_WriteUndoline(word, va("%u", spacetimetics), UNDO_NONE); spacetimetics = (UINT16)get_number(word2); } else if (fastcmp(word, "EXTRALIFETICS")) { - DEH_WriteUndoline(word, va("%u", extralifetics), UNDO_NONE); extralifetics = (UINT16)get_number(word2); } else if (fastcmp(word, "GAMEOVERTICS")) { - DEH_WriteUndoline(word, va("%u", gameovertics), UNDO_NONE); gameovertics = get_number(word2); } else if (fastcmp(word, "INTROTOPLAY")) { - DEH_WriteUndoline(word, va("%d", introtoplay), UNDO_NONE); introtoplay = (UINT8)get_number(word2); // range check, you morons. if (introtoplay > 128) @@ -2888,17 +2670,14 @@ static void readmaincfg(MYFILE *f) } else if (fastcmp(word, "LOOPTITLE")) { - DEH_WriteUndoline(word, va("%d", looptitle), UNDO_NONE); looptitle = (boolean)(value || word2[0] == 'T' || word2[0] == 'Y'); } else if (fastcmp(word, "TITLESCROLLSPEED")) { - DEH_WriteUndoline(word, va("%d", titlescrollspeed), UNDO_NONE); titlescrollspeed = get_number(word2); } else if (fastcmp(word, "CREDITSCUTSCENE")) { - DEH_WriteUndoline(word, va("%d", creditscutscene), UNDO_NONE); creditscutscene = (UINT8)get_number(word2); // range check, you morons. if (creditscutscene > 128) @@ -2906,32 +2685,26 @@ static void readmaincfg(MYFILE *f) } else if (fastcmp(word, "DISABLESPEEDADJUST")) { - DEH_WriteUndoline(word, va("%d", disableSpeedAdjust), UNDO_NONE); disableSpeedAdjust = (UINT8)get_number(word2); } else if (fastcmp(word, "NUMDEMOS")) { - DEH_WriteUndoline(word, va("%d", numDemos), UNDO_NONE); numDemos = (UINT8)get_number(word2); } else if (fastcmp(word, "DEMODELAYTIME")) { - DEH_WriteUndoline(word, va("%d", demoDelayTime), UNDO_NONE); demoDelayTime = get_number(word2); } else if (fastcmp(word, "DEMOIDLETIME")) { - DEH_WriteUndoline(word, va("%d", demoIdleTime), UNDO_NONE); demoIdleTime = get_number(word2); } else if (fastcmp(word, "USE1UPSOUND")) { - DEH_WriteUndoline(word, va("%u", use1upSound), UNDO_NONE); use1upSound = (UINT8)(value || word2[0] == 'T' || word2[0] == 'Y'); } else if (fastcmp(word, "MAXXTRALIFE")) { - DEH_WriteUndoline(word, va("%u", maxXtraLife), UNDO_NONE); maxXtraLife = (UINT8)get_number(word2); } @@ -2945,7 +2718,6 @@ static void readmaincfg(MYFILE *f) I_Error("Maincfg: bad data file name '%s'\n", word2); G_SaveGameData(); - DEH_WriteUndoline(word, gamedatafilename, UNDO_NONE); strlcpy(gamedatafilename, word2, sizeof (gamedatafilename)); strlwr(gamedatafilename); savemoddata = true; @@ -2962,12 +2734,10 @@ static void readmaincfg(MYFILE *f) } else if (fastcmp(word, "RESETDATA")) { - DEH_WriteUndoline(word, "0", UNDO_TODO); /// \todo P_ResetData(value); } else if (fastcmp(word, "CUSTOMVERSION")) { - DEH_WriteUndoline(word, customversionstring, UNDO_NONE); strlcpy(customversionstring, word2, sizeof (customversionstring)); } else @@ -3205,13 +2975,11 @@ static void DEH_LoadDehackedFile(MYFILE *f) else if (fastcmp(word, "MAINCFG")) { readmaincfg(f); - DEH_WriteUndoline(word, "", UNDO_HEADER); continue; } else if (fastcmp(word, "WIPES")) { readwipes(f); - DEH_WriteUndoline(word, "", UNDO_HEADER); continue; } word2 = strtok(NULL, " "); @@ -3231,7 +2999,6 @@ static void DEH_LoadDehackedFile(MYFILE *f) deh_warning("Character %d out of range (0 - 31)", i); ignorelines(f); } - DEH_WriteUndoline(word, word2, UNDO_HEADER); continue; } if (word2) @@ -3240,6 +3007,7 @@ static void DEH_LoadDehackedFile(MYFILE *f) if (word2[strlen(word2)-1] == '\n') word2[strlen(word2)-1] = '\0'; i = atoi(word2); + if (fastcmp(word, "THING") || fastcmp(word, "MOBJ") || fastcmp(word, "OBJECT")) { if (i == 0 && word2[0] != '0') // If word2 isn't a number @@ -3251,7 +3019,6 @@ static void DEH_LoadDehackedFile(MYFILE *f) deh_warning("Thing %d out of range (1 - %d)", i, NUMMOBJTYPES-1); ignorelines(f); } - DEH_WriteUndoline(word, word2, UNDO_HEADER); } else if (fastcmp(word, "LIGHT")) { @@ -3264,7 +3031,6 @@ static void DEH_LoadDehackedFile(MYFILE *f) deh_warning("Light number %d out of range (1 - %d)", i, NUMLIGHTS-1); ignorelines(f); } - DEH_WriteUndoline(word, word2, UNDO_HEADER); #endif } else if (fastcmp(word, "SPRITE")) @@ -3279,7 +3045,6 @@ static void DEH_LoadDehackedFile(MYFILE *f) deh_warning("Sprite number %d out of range (0 - %d)", i, NUMSPRITES-1); ignorelines(f); } - DEH_WriteUndoline(word, word2, UNDO_HEADER); #endif } else if (fastcmp(word, "LEVEL")) @@ -3298,7 +3063,6 @@ static void DEH_LoadDehackedFile(MYFILE *f) deh_warning("Level number %d out of range (1 - %d)", i, NUMMAPS); ignorelines(f); } - DEH_WriteUndoline(word, word2, UNDO_HEADER); } else if (fastcmp(word, "CUTSCENE")) { @@ -3309,7 +3073,6 @@ static void DEH_LoadDehackedFile(MYFILE *f) deh_warning("Cutscene number %d out of range (1 - 128)", i); ignorelines(f); } - DEH_WriteUndoline(word, word2, UNDO_HEADER); } else if (fastcmp(word, "FRAME") || fastcmp(word, "STATE")) { @@ -3322,7 +3085,6 @@ static void DEH_LoadDehackedFile(MYFILE *f) deh_warning("Frame %d out of range (0 - %d)", i, NUMSTATES-1); ignorelines(f); } - DEH_WriteUndoline(word, word2, UNDO_HEADER); } else if (fastcmp(word, "SOUND")) { @@ -3335,7 +3097,6 @@ static void DEH_LoadDehackedFile(MYFILE *f) deh_warning("Sound %d out of range (1 - %d)", i, NUMSFX-1); ignorelines(f); } - DEH_WriteUndoline(word, word2, UNDO_HEADER); } else if (fastcmp(word, "HUDITEM")) { @@ -3348,7 +3109,6 @@ static void DEH_LoadDehackedFile(MYFILE *f) deh_warning("HUD item number %d out of range (0 - %d)", i, NUMHUDITEMS-1); ignorelines(f); } - DEH_WriteUndoline(word, word2, UNDO_HEADER); } else if (fastcmp(word, "EMBLEM")) { @@ -3368,7 +3128,6 @@ static void DEH_LoadDehackedFile(MYFILE *f) deh_warning("Emblem number %d out of range (1 - %d)", i, MAXEMBLEMS); ignorelines(f); } - DEH_WriteUndoline(word, word2, UNDO_HEADER); } else if (fastcmp(word, "EXTRAEMBLEM")) { @@ -3388,7 +3147,6 @@ static void DEH_LoadDehackedFile(MYFILE *f) deh_warning("Extra emblem number %d out of range (1 - %d)", i, MAXEXTRAEMBLEMS); ignorelines(f); } - DEH_WriteUndoline(word, word2, UNDO_HEADER); } else if (fastcmp(word, "UNLOCKABLE")) { @@ -3404,7 +3162,6 @@ static void DEH_LoadDehackedFile(MYFILE *f) deh_warning("Unlockable number %d out of range (1 - %d)", i, MAXUNLOCKABLES); ignorelines(f); } - DEH_WriteUndoline(word, word2, UNDO_HEADER); } else if (fastcmp(word, "CONDITIONSET")) { @@ -3420,8 +3177,6 @@ static void DEH_LoadDehackedFile(MYFILE *f) deh_warning("Condition set number %d out of range (1 - %d)", i, MAXCONDITIONSETS); ignorelines(f); } - // no undo support for this insanity yet - //DEH_WriteUndoline(word, word2, UNDO_HEADER); } // Last I heard this crashes the game if you try to use it // so this is disabled for now @@ -3431,7 +3186,6 @@ static void DEH_LoadDehackedFile(MYFILE *f) INT32 ver = searchvalue(strtok(NULL, "\n")); if (ver != PATCHVERSION) deh_warning("Patch is for SRB2 version %d,\nonly version %d is supported", ver, PATCHVERSION); - //DEH_WriteUndoline(word, va("%d", ver), UNDO_NONE); } // Clear all data in certain locations (mostly for unlocks) // Unless you REALLY want to piss people off, @@ -3502,9 +3256,6 @@ static void DEH_LoadDehackedFile(MYFILE *f) void DEH_LoadDehackedLumpPwad(UINT16 wad, UINT16 lump) { MYFILE f; -#ifdef DELFILE - unsocwad = wad; -#endif f.wad = wad; f.size = W_LumpLengthPwad(wad, lump); f.data = Z_Malloc(f.size + 1, PU_STATIC, NULL); @@ -3512,7 +3263,6 @@ void DEH_LoadDehackedLumpPwad(UINT16 wad, UINT16 lump) f.curpos = f.data; f.data[f.size] = 0; DEH_LoadDehackedFile(&f); - DEH_WriteUndoline(va("# uload for wad: %u, lump: %u", wad, lump), NULL, UNDO_DONE); Z_Free(f.data); } @@ -3521,67 +3271,6 @@ void DEH_LoadDehackedLump(lumpnum_t lumpnum) DEH_LoadDehackedLumpPwad(WADFILENUM(lumpnum),LUMPNUM(lumpnum)); } -#ifdef DELFILE -#define DUMPUNDONE - -// read (un)dehacked lump in wad's memory -void DEH_UnloadDehackedWad(UINT16 wad) -{ - undehacked_t *tmp, *curundo = unsocdata[wad]; - MYFILE f; - size_t len = 0; - char *data; -#ifdef DUMPUNDONE - FILE *UNDO = fopen("undo.soc", "wt"); -#endif - CONS_Printf(M_GetText("Unloading WAD SOC edits\n")); - while (curundo) - { - data = curundo->undata; - curundo = curundo->next; - if (data) - len += strlen(data); - len += 1; -#ifdef DUMPUNDONE - if (UNDO) - { - if (data) - fprintf(UNDO, "%s\n", data); - else - fprintf(UNDO, "\n"); - } -#endif - } -#ifndef DUMPUNDONE - if (UNDO) fclose(UNDO); -#endif - if (!len) return; - f.size = len; - data = f.data = Z_Malloc(f.size + 1, PU_STATIC, NULL); - curundo = unsocdata[wad]; - unsocdata[wad] = NULL; - while (curundo) - { - tmp = curundo; - curundo = curundo->next; - if (tmp->undata) - data += sprintf(data, "%s\n", tmp->undata); - else - data += sprintf(data, "\n"); - if (tmp->undata) free(tmp->undata); - free(tmp); - } - f.wad = wad; - f.curpos = f.data; - f.data[f.size] = 0; - disableundo = true; - DEH_LoadDehackedFile(&f); - disableundo = false; - Z_Free(f.data); -} -#endif //DELFILE - - //////////////////////////////////////////////////////////////////////////////// // CRAZY LIST OF STATE NAMES AND ALL FROM HERE DOWN // TODO: Make this all a seperate file or something, like part of info.c?? @@ -6816,91 +6505,130 @@ static const char *const ML_LIST[16] = { // This DOES differ from r_draw's Color_Names, unfortunately. // Also includes Super colors static const char *COLOR_ENUMS[] = { - "NONE", // SKINCOLOR_NONE - "WHITE", // SKINCOLOR_WHITE - "SILVER", // SKINCOLOR_SILVER - "GREY", // SKINCOLOR_GREY - "BLACK", // SKINCOLOR_BLACK - "BEIGE", // SKINCOLOR_BEIGE - "PEACH", // SKINCOLOR_PEACH - "BROWN", // SKINCOLOR_BROWN - "RED", // SKINCOLOR_RED - "CRIMSON", // SKINCOLOR_CRIMSON - "ORANGE", // SKINCOLOR_ORANGE - "RUST", // SKINCOLOR_RUST - "GOLD", // SKINCOLOR_GOLD - "YELLOW", // SKINCOLOR_YELLOW - "TAN", // SKINCOLOR_TAN - "MOSS", // SKINCOLOR_MOSS - "PERIDOT", // SKINCOLOR_PERIDOT - "GREEN", // SKINCOLOR_GREEN - "EMERALD", // SKINCOLOR_EMERALD - "AQUA", // SKINCOLOR_AQUA - "TEAL", // SKINCOLOR_TEAL - "CYAN", // SKINCOLOR_CYAN - "BLUE", // SKINCOLOR_BLUE - "AZURE", // SKINCOLOR_AZURE - "PASTEL", // SKINCOLOR_PASTEL - "PURPLE", // SKINCOLOR_PURPLE - "LAVENDER", // SKINCOLOR_LAVENDER - "MAGENTA", // SKINCOLOR_MAGENTA - "PINK", // SKINCOLOR_PINK - "ROSY", // SKINCOLOR_ROSY + "NONE", // SKINCOLOR_NONE, + + // Greyscale ranges + "WHITE", // SKINCOLOR_WHITE, + "BONE", // SKINCOLOR_BONE, + "CLOUDY", // SKINCOLOR_CLOUDY, + "GREY", // SKINCOLOR_GREY, + "SILVER", // SKINCOLOR_SILVER, + "CARBON", // SKINCOLOR_CARBON, + "JET", // SKINCOLOR_JET, + "BLACK", // SKINCOLOR_BLACK, + + // Desaturated + "AETHER", // SKINCOLOR_AETHER, + "SLATE", // SKINCOLOR_SLATE, + "PINK", // SKINCOLOR_PINK, + "YOGURT", // SKINCOLOR_YOGURT, + "BROWN", // SKINCOLOR_BROWN, + "TAN", // SKINCOLOR_TAN, + "BEIGE", // SKINCOLOR_BEIGE, + "MOSS", // SKINCOLOR_MOSS, + "AZURE", // SKINCOLOR_AZURE, + "LAVENDER", // SKINCOLOR_LAVENDER, + + // Viv's vivid colours (toast 21/07/17) + "RUBY", // SKINCOLOR_RUBY, + "SALMON", // SKINCOLOR_SALMON, + "RED", // SKINCOLOR_RED, + "CRIMSON", // SKINCOLOR_CRIMSON, + "FLAME", // SKINCOLOR_FLAME, + "PEACHY", // SKINCOLOR_PEACHY, + "QUAIL", // SKINCOLOR_QUAIL, + "SUNSET", // SKINCOLOR_SUNSET, + "APRICOT", // SKINCOLOR_APRICOT, + "ORANGE", // SKINCOLOR_ORANGE, + "RUST", // SKINCOLOR_RUST, + "GOLD", // SKINCOLOR_GOLD, + "SANDY", // SKINCOLOR_SANDY, + "YELLOW", // SKINCOLOR_YELLOW, + "OLIVE", // SKINCOLOR_OLIVE, + "LIME", // SKINCOLOR_LIME, + "PERIDOT", // SKINCOLOR_PERIDOT, + "GREEN", // SKINCOLOR_GREEN, + "FOREST", // SKINCOLOR_FOREST, + "EMERALD", // SKINCOLOR_EMERALD, + "MINT", // SKINCOLOR_MINT, + "SEAFOAM", // SKINCOLOR_SEAFOAM, + "AQUA", // SKINCOLOR_AQUA, + "TEAL", // SKINCOLOR_TEAL, + "WAVE", // SKINCOLOR_WAVE, + "CYAN", // SKINCOLOR_CYAN, + "SKY", // SKINCOLOR_SKY, + "CERULEAN", // SKINCOLOR_CERULEAN, + "ICY", // SKINCOLOR_ICY, + "SAPPHIRE", // SKINCOLOR_SAPPHIRE, + "CORNFLOWER", // SKINCOLOR_CORNFLOWER, + "BLUE", // SKINCOLOR_BLUE, + "COBALT", // SKINCOLOR_COBALT, + "VAPOR", // SKINCOLOR_VAPOR, + "DUSK", // SKINCOLOR_DUSK, + "PASTEL", // SKINCOLOR_PASTEL, + "PURPLE", // SKINCOLOR_PURPLE, + "BUBBLEGUM", // SKINCOLOR_BUBBLEGUM, + "MAGENTA", // SKINCOLOR_MAGENTA, + "NEON", // SKINCOLOR_NEON, + "VIOLET", // SKINCOLOR_VIOLET, + "LILAC", // SKINCOLOR_LILAC, + "PLUM", // SKINCOLOR_PLUM, + "ROSY", // SKINCOLOR_ROSY, // Super special awesome Super flashing colors! - "SUPERSILVER1", // SKINCOLOR_SUPERSILVER1 - "SUPERSILVER2", // SKINCOLOR_SUPERSILVER2, - "SUPERSILVER3", // SKINCOLOR_SUPERSILVER3, - "SUPERSILVER4", // SKINCOLOR_SUPERSILVER4, - "SUPERSILVER5", // SKINCOLOR_SUPERSILVER5, + "SUPERSILVER1", // SKINCOLOR_SUPERSILVER1 + "SUPERSILVER2", // SKINCOLOR_SUPERSILVER2, + "SUPERSILVER3", // SKINCOLOR_SUPERSILVER3, + "SUPERSILVER4", // SKINCOLOR_SUPERSILVER4, + "SUPERSILVER5", // SKINCOLOR_SUPERSILVER5, - "SUPERRED1", // SKINCOLOR_SUPERRED1 - "SUPERRED2", // SKINCOLOR_SUPERRED2, - "SUPERRED3", // SKINCOLOR_SUPERRED3, - "SUPERRED4", // SKINCOLOR_SUPERRED4, - "SUPERRED5", // SKINCOLOR_SUPERRED5, + "SUPERRED1", // SKINCOLOR_SUPERRED1 + "SUPERRED2", // SKINCOLOR_SUPERRED2, + "SUPERRED3", // SKINCOLOR_SUPERRED3, + "SUPERRED4", // SKINCOLOR_SUPERRED4, + "SUPERRED5", // SKINCOLOR_SUPERRED5, - "SUPERORANGE1", // SKINCOLOR_SUPERORANGE1 - "SUPERORANGE2", // SKINCOLOR_SUPERORANGE2, - "SUPERORANGE3", // SKINCOLOR_SUPERORANGE3, - "SUPERORANGE4", // SKINCOLOR_SUPERORANGE4, - "SUPERORANGE5", // SKINCOLOR_SUPERORANGE5, + "SUPERORANGE1", // SKINCOLOR_SUPERORANGE1 + "SUPERORANGE2", // SKINCOLOR_SUPERORANGE2, + "SUPERORANGE3", // SKINCOLOR_SUPERORANGE3, + "SUPERORANGE4", // SKINCOLOR_SUPERORANGE4, + "SUPERORANGE5", // SKINCOLOR_SUPERORANGE5, - "SUPERGOLD1", // SKINCOLOR_SUPERGOLD1 - "SUPERGOLD2", // SKINCOLOR_SUPERGOLD2, - "SUPERGOLD3", // SKINCOLOR_SUPERGOLD3, - "SUPERGOLD4", // SKINCOLOR_SUPERGOLD4, - "SUPERGOLD5", // SKINCOLOR_SUPERGOLD5, + "SUPERGOLD1", // SKINCOLOR_SUPERGOLD1 + "SUPERGOLD2", // SKINCOLOR_SUPERGOLD2, + "SUPERGOLD3", // SKINCOLOR_SUPERGOLD3, + "SUPERGOLD4", // SKINCOLOR_SUPERGOLD4, + "SUPERGOLD5", // SKINCOLOR_SUPERGOLD5, - "SUPERPERIDOT1", // SKINCOLOR_SUPERPERIDOT1 - "SUPERPERIDOT2", // SKINCOLOR_SUPERPERIDOT2, - "SUPERPERIDOT3", // SKINCOLOR_SUPERPERIDOT3, - "SUPERPERIDOT4", // SKINCOLOR_SUPERPERIDOT4, - "SUPERPERIDOT5", // SKINCOLOR_SUPERPERIDOT5, + "SUPERPERIDOT1", // SKINCOLOR_SUPERPERIDOT1 + "SUPERPERIDOT2", // SKINCOLOR_SUPERPERIDOT2, + "SUPERPERIDOT3", // SKINCOLOR_SUPERPERIDOT3, + "SUPERPERIDOT4", // SKINCOLOR_SUPERPERIDOT4, + "SUPERPERIDOT5", // SKINCOLOR_SUPERPERIDOT5, - "SUPERCYAN1", // SKINCOLOR_SUPERCYAN1 - "SUPERCYAN2", // SKINCOLOR_SUPERCYAN2, - "SUPERCYAN3", // SKINCOLOR_SUPERCYAN3, - "SUPERCYAN4", // SKINCOLOR_SUPERCYAN4, - "SUPERCYAN5", // SKINCOLOR_SUPERCYAN5, + "SUPERSKY1", // SKINCOLOR_SUPERSKY1 + "SUPERSKY2", // SKINCOLOR_SUPERSKY2, + "SUPERSKY3", // SKINCOLOR_SUPERSKY3, + "SUPERSKY4", // SKINCOLOR_SUPERSKY4, + "SUPERSKY5", // SKINCOLOR_SUPERSKY5, - "SUPERPURPLE1", // SKINCOLOR_SUPERPURPLE1, - "SUPERPURPLE2", // SKINCOLOR_SUPERPURPLE2, - "SUPERPURPLE3", // SKINCOLOR_SUPERPURPLE3, - "SUPERPURPLE4", // SKINCOLOR_SUPERPURPLE4, - "SUPERPURPLE5", // SKINCOLOR_SUPERPURPLE5, + "SUPERPURPLE1", // SKINCOLOR_SUPERPURPLE1, + "SUPERPURPLE2", // SKINCOLOR_SUPERPURPLE2, + "SUPERPURPLE3", // SKINCOLOR_SUPERPURPLE3, + "SUPERPURPLE4", // SKINCOLOR_SUPERPURPLE4, + "SUPERPURPLE5", // SKINCOLOR_SUPERPURPLE5, - "SUPERRUST1", // SKINCOLOR_SUPERRUST1 - "SUPERRUST2", // SKINCOLOR_SUPERRUST2, - "SUPERRUST3", // SKINCOLOR_SUPERRUST3, - "SUPERRUST4", // SKINCOLOR_SUPERRUST4, - "SUPERRUST5", // SKINCOLOR_SUPERRUST5, + "SUPERRUST1", // SKINCOLOR_SUPERRUST1 + "SUPERRUST2", // SKINCOLOR_SUPERRUST2, + "SUPERRUST3", // SKINCOLOR_SUPERRUST3, + "SUPERRUST4", // SKINCOLOR_SUPERRUST4, + "SUPERRUST5", // SKINCOLOR_SUPERRUST5, - "SUPERTAN1", // SKINCOLOR_SUPERTAN1 - "SUPERTAN2", // SKINCOLOR_SUPERTAN2, - "SUPERTAN3", // SKINCOLOR_SUPERTAN3, - "SUPERTAN4", // SKINCOLOR_SUPERTAN4, - "SUPERTAN5" // SKINCOLOR_SUPERTAN5, + "SUPERTAN1", // SKINCOLOR_SUPERTAN1 + "SUPERTAN2", // SKINCOLOR_SUPERTAN2, + "SUPERTAN3", // SKINCOLOR_SUPERTAN3, + "SUPERTAN4", // SKINCOLOR_SUPERTAN4, + "SUPERTAN5" // SKINCOLOR_SUPERTAN5, }; static const char *const POWERS_LIST[] = { diff --git a/src/dehacked.h b/src/dehacked.h index 8832216b8..dfce996a2 100644 --- a/src/dehacked.h +++ b/src/dehacked.h @@ -27,13 +27,6 @@ typedef enum UNDO_DONE = 0, } undotype_f; -#ifdef DELFILE -void DEH_WriteUndoline(const char *value, const char *data, undotype_f flags); -void DEH_UnloadDehackedWad(UINT16 wad); -#else // null the undo lines -#define DEH_WriteUndoline(a,b,c) -#endif - void DEH_LoadDehackedLump(lumpnum_t lumpnum); void DEH_LoadDehackedLumpPwad(UINT16 wad, UINT16 lump); diff --git a/src/doomdata.h b/src/doomdata.h index 033cc71b3..c0586fd65 100644 --- a/src/doomdata.h +++ b/src/doomdata.h @@ -207,8 +207,9 @@ typedef struct #define ZSHIFT 4 +extern const UINT8 Color_Index[MAXTRANSLATIONS-1][16]; extern const char *Color_Names[MAXSKINCOLORS + NUMSUPERCOLORS]; -extern const UINT8 Color_Opposite[MAXSKINCOLORS*2]; +extern const UINT8 Color_Opposite[(MAXSKINCOLORS - 1)*2]; #define NUMMAPS 1035 diff --git a/src/doomdef.h b/src/doomdef.h index e1e274d08..4d6bf75bb 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -229,39 +229,77 @@ extern FILE *logstream; typedef enum { SKINCOLOR_NONE = 0, + + // Greyscale ranges SKINCOLOR_WHITE, - SKINCOLOR_SILVER, + SKINCOLOR_BONE, + SKINCOLOR_CLOUDY, SKINCOLOR_GREY, + SKINCOLOR_SILVER, + SKINCOLOR_CARBON, + SKINCOLOR_JET, SKINCOLOR_BLACK, - SKINCOLOR_BEIGE, - SKINCOLOR_PEACH, + + // Desaturated + SKINCOLOR_AETHER, + SKINCOLOR_SLATE, + SKINCOLOR_PINK, + SKINCOLOR_YOGURT, SKINCOLOR_BROWN, + SKINCOLOR_TAN, + SKINCOLOR_BEIGE, + SKINCOLOR_MOSS, + SKINCOLOR_AZURE, + SKINCOLOR_LAVENDER, + + // Viv's vivid colours (toast 21/07/17) + SKINCOLOR_RUBY, + SKINCOLOR_SALMON, SKINCOLOR_RED, SKINCOLOR_CRIMSON, + SKINCOLOR_FLAME, + SKINCOLOR_PEACHY, + SKINCOLOR_QUAIL, + SKINCOLOR_SUNSET, + SKINCOLOR_APRICOT, SKINCOLOR_ORANGE, SKINCOLOR_RUST, SKINCOLOR_GOLD, + SKINCOLOR_SANDY, SKINCOLOR_YELLOW, - SKINCOLOR_TAN, - SKINCOLOR_MOSS, + SKINCOLOR_OLIVE, + SKINCOLOR_LIME, SKINCOLOR_PERIDOT, SKINCOLOR_GREEN, + SKINCOLOR_FOREST, SKINCOLOR_EMERALD, + SKINCOLOR_MINT, + SKINCOLOR_SEAFOAM, SKINCOLOR_AQUA, SKINCOLOR_TEAL, + SKINCOLOR_WAVE, SKINCOLOR_CYAN, + SKINCOLOR_SKY, + SKINCOLOR_CERULEAN, + SKINCOLOR_ICY, + SKINCOLOR_SAPPHIRE, // sweet mother, i cannot weave – slender aphrodite has overcome me with longing for a girl + SKINCOLOR_CORNFLOWER, SKINCOLOR_BLUE, - SKINCOLOR_AZURE, + SKINCOLOR_COBALT, + SKINCOLOR_VAPOR, + SKINCOLOR_DUSK, SKINCOLOR_PASTEL, SKINCOLOR_PURPLE, - SKINCOLOR_LAVENDER, + SKINCOLOR_BUBBLEGUM, SKINCOLOR_MAGENTA, - SKINCOLOR_PINK, + SKINCOLOR_NEON, + SKINCOLOR_VIOLET, + SKINCOLOR_LILAC, + SKINCOLOR_PLUM, SKINCOLOR_ROSY, - //SKINCOLOR_? - //SKINCOLOR_? - // Careful! MAXSKINCOLORS cannot be greater than 0x20! Two slots left... + // SKINCOLOR_? - one left before we bump up against 0x39, which isn't a HARD limit anymore but would be excessive + MAXSKINCOLORS, // Super special awesome Super flashing colors! @@ -295,11 +333,11 @@ typedef enum SKINCOLOR_SUPERPERIDOT4, SKINCOLOR_SUPERPERIDOT5, - SKINCOLOR_SUPERCYAN1, - SKINCOLOR_SUPERCYAN2, - SKINCOLOR_SUPERCYAN3, - SKINCOLOR_SUPERCYAN4, - SKINCOLOR_SUPERCYAN5, + SKINCOLOR_SUPERSKY1, + SKINCOLOR_SUPERSKY2, + SKINCOLOR_SUPERSKY3, + SKINCOLOR_SUPERSKY4, + SKINCOLOR_SUPERSKY5, SKINCOLOR_SUPERPURPLE1, SKINCOLOR_SUPERPURPLE2, @@ -483,10 +521,6 @@ extern const char *compdate, *comptime, *comprevision, *compbranch; #define ESLOPE_TYPESHIM #endif -/// Delete file while the game is running. -/// \note EXTREMELY buggy, tends to crash game. -//#define DELFILE - /// Allows the use of devmode in multiplayer. AKA "fishcake" //#define NETGAME_DEVMODE diff --git a/src/g_game.c b/src/g_game.c index 1a2a2aac6..e996938ab 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2091,6 +2091,7 @@ void G_PlayerReborn(INT32 player) UINT32 availabilities; tic_t jointime; boolean spectator; + boolean outofcoop; INT16 bot; SINT8 pity; @@ -2101,6 +2102,7 @@ void G_PlayerReborn(INT32 player) exiting = players[player].exiting; jointime = players[player].jointime; spectator = players[player].spectator; + outofcoop = players[player].outofcoop; pflags = (players[player].pflags & (PF_TIMEOVER|PF_FLIPCAM|PF_TAGIT|PF_TAGGED|PF_ANALOGMODE)); // As long as we're not in multiplayer, carry over cheatcodes from map to map @@ -2155,6 +2157,7 @@ void G_PlayerReborn(INT32 player) p->ctfteam = ctfteam; p->jointime = jointime; p->spectator = spectator; + p->outofcoop = outofcoop; // save player config truth reborn p->skincolor = skincolor; @@ -2206,8 +2209,8 @@ void G_PlayerReborn(INT32 player) p->rings = 0; // 0 rings p->panim = PA_IDLE; // standing animation - if ((netgame || multiplayer) && !p->spectator) - p->powers[pw_flashing] = flashingtics-1; // Babysitting deterrent + //if ((netgame || multiplayer) && !p->spectator) -- moved into P_SpawnPlayer to account for forced changes there + //p->powers[pw_flashing] = flashingtics-1; // Babysitting deterrent if (p-players == consoleplayer) { @@ -2496,7 +2499,8 @@ void G_ChangePlayerReferences(mobj_t *oldmo, mobj_t *newmo) void G_DoReborn(INT32 playernum) { player_t *player = &players[playernum]; - boolean starpost = false; + boolean resetlevel = false; + INT32 i; if (modeattacking) { @@ -2522,35 +2526,98 @@ void G_DoReborn(INT32 playernum) B_RespawnBot(playernum); if (oldmo) G_ChangePlayerReferences(oldmo, players[playernum].mo); + + return; } - else if (countdowntimeup || (!multiplayer && gametype == GT_COOP)) + + if (countdowntimeup || (!(netgame || multiplayer) && gametype == GT_COOP)) + resetlevel = true; + else if (gametype == GT_COOP && (netgame || multiplayer)) + { + boolean notgameover = true; + + if (cv_cooplives.value != 0 && player->lives <= 0) // consider game over first + { + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; + if (players[i].exiting || players[i].lives > 0) + break; + } + + if (i == MAXPLAYERS) + { + notgameover = false; + if (!countdown2) + { + // They're dead, Jim. + //nextmapoverride = spstage_start; + nextmapoverride = gamemap; + countdown2 = TICRATE; + skipstats = true; + + for (i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i]) + players[i].score = 0; + } + + //emeralds = 0; + tokenbits = 0; + tokenlist = 0; + token = 0; + } + } + } + + if (notgameover && cv_coopstarposts.value == 2) + { + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; + + if (players[i].playerstate != PST_DEAD && !players[i].spectator && players[i].mo && players[i].mo->health) + break; + } + if (i == MAXPLAYERS) + resetlevel = true; + } + } + + if (resetlevel) { // reload the level from scratch if (countdowntimeup) { - player->starpostangle = 0; - player->starposttime = 0; - player->starpostx = 0; - player->starposty = 0; - player->starpostz = 0; - player->starpostnum = 0; + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; + players[i].starpostangle = 0; + players[i].starposttime = 0; + players[i].starpostx = 0; + players[i].starposty = 0; + players[i].starpostz = 0; + players[i].starpostnum = 0; + } } if (!countdowntimeup && (mapheaderinfo[gamemap-1]->levelflags & LF_NORELOAD)) { - INT32 i; - - player->playerstate = PST_REBORN; - P_LoadThingsOnly(); - P_ClearStarPost(player->starpostnum); + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; + players[i].playerstate = PST_REBORN; + P_ClearStarPost(players[i].starpostnum); + } // Do a wipe wipegamestate = -1; - if (player->starposttime) - starpost = true; - if (camera.chase) P_ResetCamera(&players[displayplayer], &camera); if (camera2.chase && splitscreen) @@ -2558,7 +2625,7 @@ void G_DoReborn(INT32 playernum) // clear cmd building stuff memset(gamekeydown, 0, sizeof (gamekeydown)); - for (i = 0;i < JOYAXISSET; i++) + for (i = 0; i < JOYAXISSET; i++) { joyxmove[i] = joyymove[i] = 0; joy2xmove[i] = joy2ymove[i] = 0; @@ -2570,31 +2637,45 @@ void G_DoReborn(INT32 playernum) CON_ClearHUD(); // Starpost support - G_SpawnPlayer(playernum, starpost); + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; + G_SpawnPlayer(i, (players[i].starposttime)); + } - if (botingame) - { // Bots respawn next to their master. - players[secondarydisplayplayer].playerstate = PST_REBORN; - G_SpawnPlayer(secondarydisplayplayer, false); + // restore time in netgame (see also p_setup.c) + if ((netgame || multiplayer) && gametype == GT_COOP && cv_coopstarposts.value == 2) + { + // is this a hack? maybe + tic_t maxstarposttime = 0; + for (i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i] && players[i].starposttime > maxstarposttime) + maxstarposttime = players[i].starposttime; + } + leveltime = maxstarposttime; } } else -#ifdef HAVE_BLUA { +#ifdef HAVE_BLUA LUAh_MapChange(); #endif G_DoLoadLevel(true); -#ifdef HAVE_BLUA + return; } -#endif } else { // respawn at the start mobj_t *oldmo = NULL; - if (player->starposttime) - starpost = true; + // Not resetting map, so return to level music + if (!countdown2 + && player->lives <= 0 + && cv_cooplives.value == 1) // not allowed for life steal because no way to come back from zero group lives without addons, which should call this anyways + P_RestoreMultiMusic(player); // first dissasociate the corpse if (player->mo) @@ -2604,7 +2685,7 @@ void G_DoReborn(INT32 playernum) P_RemoveMobj(player->mo); } - G_SpawnPlayer(playernum, starpost); + G_SpawnPlayer(playernum, (player->starposttime)); if (oldmo) G_ChangePlayerReferences(oldmo, players[playernum].mo); } @@ -2612,10 +2693,49 @@ void G_DoReborn(INT32 playernum) void G_AddPlayer(INT32 playernum) { + INT32 countplayers = 0, notexiting = 0; + player_t *p = &players[playernum]; + // Go through the current players and make sure you have the latest starpost set + if (G_PlatformGametype() && (netgame || multiplayer)) + { + INT32 i; + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; + + if (players[i].bot) // ignore dumb, stupid tails + continue; + + countplayers++; + + if (!players->exiting) + notexiting++; + + if (!(cv_coopstarposts.value && (gametype == GT_COOP) && (p->starpostnum < players[i].starpostnum))) + continue; + + p->starposttime = players[i].starposttime; + p->starpostx = players[i].starpostx; + p->starposty = players[i].starposty; + p->starpostz = players[i].starpostz; + p->starpostangle = players[i].starpostangle; + p->starpostnum = players[i].starpostnum; + } + } + p->jointime = 0; p->playerstate = PST_REBORN; + + p->height = mobjinfo[MT_PLAYER].height; + + if (G_GametypeUsesLives() || ((netgame || multiplayer) && gametype == GT_COOP)) + p->lives = cv_startinglives.value; + + if (countplayers && !notexiting) + P_DoPlayerExit(p); } void G_ExitLevel(void) @@ -3613,7 +3733,7 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean if (netgame || multiplayer) { - if (!FLS || (players[i].lives < cv_startinglives.value)) + if (!FLS || (players[i].lives < 1)) players[i].lives = cv_startinglives.value; players[i].continues = 0; } @@ -4415,7 +4535,7 @@ void G_GhostTicker(void) g->mo->color += abs( ( (signed)( (unsigned)leveltime >> 1 ) % 9) - 4); break; case GHC_INVINCIBLE: // Mario invincibility (P_CheckInvincibilityTimer) - g->mo->color = (UINT8)(SKINCOLOR_RED + (leveltime % (MAXSKINCOLORS - SKINCOLOR_RED))); // Passes through all saturated colours + g->mo->color = (UINT8)(SKINCOLOR_RUBY + (leveltime % (MAXSKINCOLORS - SKINCOLOR_RUBY))); // Passes through all saturated colours break; default: break; diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 18fc1bd6d..df2c9f59a 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -945,7 +945,6 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, { UINT16 w = gpatch->width, h = gpatch->height; UINT32 size = w*h; - UINT8 c = 255; RGBA_t *image, *blendimage, *cur, blendcolor; if (grmip->width == 0) @@ -969,59 +968,10 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, image = gpatch->mipmap.grInfo.data; blendimage = blendgpatch->mipmap.grInfo.data; -#define SUPERCOLORBLEND(name, c1, c2, c3, c4, c5) \ - case SKINCOLOR_SUPER ## name ## 1: c = c1; break; \ - case SKINCOLOR_SUPER ## name ## 2: c = c2; break; \ - case SKINCOLOR_SUPER ## name ## 3: c = c3; break; \ - case SKINCOLOR_SUPER ## name ## 4: c = c4; break; \ - case SKINCOLOR_SUPER ## name ## 5: c = c5; break; - - switch (color) - { - case SKINCOLOR_WHITE: c = 3; break; - case SKINCOLOR_SILVER: c = 10; break; - case SKINCOLOR_GREY: c = 15; break; - case SKINCOLOR_BLACK: c = 27; break; - case SKINCOLOR_BEIGE: c = 247; break; - case SKINCOLOR_PEACH: c = 218; break; - case SKINCOLOR_BROWN: c = 234; break; - case SKINCOLOR_RED: c = 38; break; - case SKINCOLOR_CRIMSON: c = 45; break; - case SKINCOLOR_ORANGE: c = 54; break; - case SKINCOLOR_RUST: c = 60; break; - case SKINCOLOR_GOLD: c = 67; break; - case SKINCOLOR_YELLOW: c = 73; break; - case SKINCOLOR_TAN: c = 85; break; - case SKINCOLOR_MOSS: c = 92; break; - case SKINCOLOR_PERIDOT: c = 188; break; - case SKINCOLOR_GREEN: c = 101; break; - case SKINCOLOR_EMERALD: c = 112; break; - case SKINCOLOR_AQUA: c = 122; break; - case SKINCOLOR_TEAL: c = 141; break; - case SKINCOLOR_CYAN: c = 131; break; - case SKINCOLOR_BLUE: c = 152; break; - case SKINCOLOR_AZURE: c = 171; break; - case SKINCOLOR_PASTEL: c = 161; break; - case SKINCOLOR_PURPLE: c = 165; break; - case SKINCOLOR_LAVENDER: c = 195; break; - case SKINCOLOR_MAGENTA: c = 183; break; - case SKINCOLOR_PINK: c = 211; break; - case SKINCOLOR_ROSY: c = 202; break; - - SUPERCOLORBLEND(SILVER, 0, 2, 4, 7, 10) // Super silver - SUPERCOLORBLEND(RED, 208, 210, 32, 33, 35) // Super red - SUPERCOLORBLEND(ORANGE, 208, 48, 50, 54, 58) // Super orange - SUPERCOLORBLEND(GOLD, 80, 83, 73, 64, 67) // Super gold - SUPERCOLORBLEND(PERIDOT, 88, 188, 189, 190, 191) // Super peridot - SUPERCOLORBLEND(CYAN, 128, 131, 133, 134, 136) // Super cyan - SUPERCOLORBLEND(PURPLE, 144, 162, 164, 166, 168) // Super purple - SUPERCOLORBLEND(RUST, 51, 54, 68, 70, 234) // Super rust - SUPERCOLORBLEND(TAN, 80, 82, 84, 87, 247) // Super tan - default: c = 255; break; - } - blendcolor = V_GetColor(c); - -#undef SUPERCOLORBLEND + if (color == SKINCOLOR_NONE || color >= MAXTRANSLATIONS) + blendcolor = V_GetColor(0xff); + else + blendcolor = V_GetColor(Color_Index[color-1][4]); while (size--) { diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 365ea093b..e92b96995 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -92,6 +92,7 @@ patch_t *emeraldpics[7]; patch_t *tinyemeraldpics[7]; static patch_t *emblemicon; patch_t *tokenicon; +static patch_t *exiticon; //------------------------------------------- // misc vars @@ -245,6 +246,7 @@ void HU_LoadGraphics(void) emblemicon = W_CachePatchName("EMBLICON", PU_HUDGFX); tokenicon = W_CachePatchName("TOKNICON", PU_HUDGFX); + exiticon = W_CachePatchName("EXITICON", PU_HUDGFX); emeraldpics[0] = W_CachePatchName("CHAOS1", PU_HUDGFX); emeraldpics[1] = W_CachePatchName("CHAOS2", PU_HUDGFX); @@ -1176,6 +1178,9 @@ void HU_Erase(void) // IN-LEVEL MULTIPLAYER RANKINGS //====================================================================== +#define supercheckdef ((players[tab[i].num].powers[pw_super] && players[tab[i].num].mo && (players[tab[i].num].mo->state < &states[S_PLAY_SUPER_TRANS] || players[tab[i].num].mo->state > &states[S_PLAY_SUPER_TRANS9])) || (players[tab[i].num].powers[pw_carry] == CR_NIGHTSMODE && skins[players[tab[i].num].skin].flags & SF_SUPER)) +#define greycheckdef ((players[tab[i].num].mo && players[tab[i].num].mo->health <= 0) || players[tab[i].num].spectator) + // // HU_DrawTabRankings // @@ -1183,6 +1188,7 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I { INT32 i; const UINT8 *colormap; + boolean greycheck, supercheck; //this function is designed for 9 or less score lines only I_Assert(scorelines <= 9); @@ -1191,12 +1197,15 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I for (i = 0; i < scorelines; i++) { - if (players[tab[i].num].spectator) + if (players[tab[i].num].spectator && gametype != GT_COOP) continue; //ignore them. + greycheck = greycheckdef; + supercheck = supercheckdef; + V_DrawString(x + 20, y, ((tab[i].num == whiteplayer) ? V_YELLOWMAP : 0) - | ((players[tab[i].num].mo && players[tab[i].num].mo->health > 0) ? 0 : V_60TRANS) + | (greycheck ? V_60TRANS : 0) | V_ALLOWLOWERCASE, tab[i].name); // Draw emeralds @@ -1206,7 +1215,7 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I HU_DrawEmeralds(x-12,y+2,tab[i].emeralds); } - if (players[tab[i].num].mo && players[tab[i].num].mo->health <= 0) + if (greycheck) V_DrawSmallTranslucentPatch (x, y-4, V_80TRANS, livesback); else V_DrawSmallScaledPatch (x, y-4, 0, livesback); @@ -1214,11 +1223,11 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I if (tab[i].color == 0) { colormap = colormaps; - if (players[tab[i].num].powers[pw_super]) + if (supercheck) V_DrawSmallScaledPatch(x, y-4, 0, superprefix[players[tab[i].num].skin]); else { - if (players[tab[i].num].mo && players[tab[i].num].mo->health <= 0) + if (greycheck) V_DrawSmallTranslucentPatch(x, y-4, V_80TRANS, faceprefix[players[tab[i].num].skin]); else V_DrawSmallScaledPatch(x, y-4, 0, faceprefix[players[tab[i].num].skin]); @@ -1226,7 +1235,7 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I } else { - if (players[tab[i].num].powers[pw_super] && players[tab[i].num].mo && (players[tab[i].num].mo->state < &states[S_PLAY_SUPER_TRANS] || players[tab[i].num].mo->state > &states[S_PLAY_SUPER_TRANS9])) + if (supercheck) { colormap = R_GetTranslationColormap(players[tab[i].num].skin, players[tab[i].num].mo->color, GTC_CACHE); V_DrawSmallMappedPatch (x, y-4, 0, superprefix[players[tab[i].num].skin], colormap); @@ -1234,23 +1243,26 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I else { colormap = R_GetTranslationColormap(players[tab[i].num].skin, players[tab[i].num].mo ? players[tab[i].num].mo->color : tab[i].color, GTC_CACHE); - if (players[tab[i].num].mo && players[tab[i].num].mo->health <= 0) + if (greycheck) V_DrawSmallTranslucentMappedPatch (x, y-4, V_80TRANS, faceprefix[players[tab[i].num].skin], colormap); else V_DrawSmallMappedPatch (x, y-4, 0, faceprefix[players[tab[i].num].skin], colormap); } } - if (G_GametypeUsesLives()) //show lives - V_DrawRightAlignedString(x, y+4, V_ALLOWLOWERCASE|((players[tab[i].num].mo && players[tab[i].num].mo->health > 0) ? 0 : V_60TRANS), va("%dx", players[tab[i].num].lives)); + if (G_GametypeUsesLives() && !(gametype == GT_COOP && (cv_cooplives.value == 0 || cv_cooplives.value == 3))) //show lives + V_DrawRightAlignedString(x, y+4, V_ALLOWLOWERCASE|(greycheck ? V_60TRANS : 0), va("%dx", players[tab[i].num].lives)); else if (G_TagGametype() && players[tab[i].num].pflags & PF_TAGIT) { - if (players[tab[i].num].mo && players[tab[i].num].mo->health <= 0) + if (greycheck) V_DrawSmallTranslucentPatch(x-32, y-4, V_60TRANS, tagico); else V_DrawSmallScaledPatch(x-32, y-4, 0, tagico); } + if (players[tab[i].num].exiting) + V_DrawSmallScaledPatch(x - SHORT(exiticon->width)/2 - 1, y-3, 0, exiticon); + if (gametype == GT_RACE) { if (circuitmap) @@ -1258,13 +1270,13 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I if (players[tab[i].num].exiting) V_DrawRightAlignedString(x+240, y, 0, va("%i:%02i.%02i", G_TicsToMinutes(players[tab[i].num].realtime,true), G_TicsToSeconds(players[tab[i].num].realtime), G_TicsToCentiseconds(players[tab[i].num].realtime))); else - V_DrawRightAlignedString(x+240, y, ((players[tab[i].num].mo && players[tab[i].num].mo->health > 0) ? 0 : V_60TRANS), va("%u", tab[i].count)); + V_DrawRightAlignedString(x+240, y, (greycheck ? V_60TRANS : 0), va("%u", tab[i].count)); } else - V_DrawRightAlignedString(x+240, y, ((players[tab[i].num].mo && players[tab[i].num].mo->health > 0) ? 0 : V_60TRANS), va("%i:%02i.%02i", G_TicsToMinutes(tab[i].count,true), G_TicsToSeconds(tab[i].count), G_TicsToCentiseconds(tab[i].count))); + V_DrawRightAlignedString(x+240, y, (greycheck ? V_60TRANS : 0), va("%i:%02i.%02i", G_TicsToMinutes(tab[i].count,true), G_TicsToSeconds(tab[i].count), G_TicsToCentiseconds(tab[i].count))); } else - V_DrawRightAlignedString(x+240, y, ((players[tab[i].num].mo && players[tab[i].num].mo->health > 0) ? 0 : V_60TRANS), va("%u", tab[i].count)); + V_DrawRightAlignedString(x+240, y, (greycheck ? V_60TRANS : 0), va("%u", tab[i].count)); y += 16; } @@ -1279,6 +1291,7 @@ void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer) INT32 redplayers = 0, blueplayers = 0; const UINT8 *colormap; char name[MAXPLAYERNAME+1]; + boolean greycheck, supercheck; V_DrawFill(160, 26, 1, 154, 0); //Draw a vertical line to separate the two teams. V_DrawFill(1, 26, 318, 1, 0); //And a horizontal line to make a T. @@ -1306,10 +1319,13 @@ void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer) else //er? not on red or blue, so ignore them continue; + greycheck = greycheckdef; + supercheck = supercheckdef; + strlcpy(name, tab[i].name, 9); V_DrawString(x + 20, y, ((tab[i].num == whiteplayer) ? V_YELLOWMAP : 0) - | ((players[tab[i].num].mo && players[tab[i].num].mo->health > 0) ? 0 : V_TRANSLUCENT) + | (greycheck ? V_TRANSLUCENT : 0) | V_ALLOWLOWERCASE, name); if (gametype == GT_CTF) @@ -1327,7 +1343,7 @@ void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer) HU_DrawEmeralds(x-12,y+2,tab[i].emeralds); } - if (players[tab[i].num].powers[pw_super]) + if (supercheck) { colormap = R_GetTranslationColormap(players[tab[i].num].skin, players[tab[i].num].mo ? players[tab[i].num].mo->color : tab[i].color, GTC_CACHE); V_DrawSmallMappedPatch (x, y-4, 0, superprefix[players[tab[i].num].skin], colormap); @@ -1335,12 +1351,12 @@ void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer) else { colormap = R_GetTranslationColormap(players[tab[i].num].skin, players[tab[i].num].mo ? players[tab[i].num].mo->color : tab[i].color, GTC_CACHE); - if (players[tab[i].num].mo && players[tab[i].num].mo->health <= 0) - V_DrawSmallTranslucentMappedPatch (x, y-4, 0, faceprefix[players[tab[i].num].skin], colormap); + if (greycheck) + V_DrawSmallTranslucentMappedPatch (x, y-4, V_80TRANS, faceprefix[players[tab[i].num].skin], colormap); else V_DrawSmallMappedPatch (x, y-4, 0, faceprefix[players[tab[i].num].skin], colormap); } - V_DrawRightAlignedThinString(x+120, y, ((players[tab[i].num].mo && players[tab[i].num].mo->health > 0) ? 0 : V_TRANSLUCENT), va("%u", tab[i].count)); + V_DrawRightAlignedThinString(x+120, y, (greycheck ? V_TRANSLUCENT : 0), va("%u", tab[i].count)); } } @@ -1352,6 +1368,7 @@ void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scoreline INT32 i; const UINT8 *colormap; char name[MAXPLAYERNAME+1]; + boolean greycheck, supercheck; V_DrawFill(160, 26, 1, 154, 0); //Draw a vertical line to separate the two sides. V_DrawFill(1, 26, 318, 1, 0); //And a horizontal line to make a T. @@ -1359,20 +1376,26 @@ void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scoreline for (i = 0; i < scorelines; i++) { - if (players[tab[i].num].spectator) + if (players[tab[i].num].spectator && gametype != GT_COOP) continue; //ignore them. + greycheck = greycheckdef; + supercheck = supercheckdef; + strlcpy(name, tab[i].name, 9); V_DrawString(x + 20, y, ((tab[i].num == whiteplayer) ? V_YELLOWMAP : 0) - | ((players[tab[i].num].mo && players[tab[i].num].mo->health > 0) ? 0 : V_TRANSLUCENT) + | (greycheck ? V_TRANSLUCENT : 0) | V_ALLOWLOWERCASE, name); - if (G_GametypeUsesLives()) //show lives + if (G_GametypeUsesLives() && !(gametype == GT_COOP && (cv_cooplives.value == 0 || cv_cooplives.value == 3))) //show lives V_DrawRightAlignedString(x, y+4, V_ALLOWLOWERCASE, va("%dx", players[tab[i].num].lives)); else if (G_TagGametype() && players[tab[i].num].pflags & PF_TAGIT) V_DrawSmallScaledPatch(x-28, y-4, 0, tagico); + if (players[tab[i].num].exiting) + V_DrawSmallScaledPatch(x - SHORT(exiticon->width)/2 - 1, y-3, 0, exiticon); + // Draw emeralds if (!players[tab[i].num].powers[pw_super] || ((leveltime/7) & 1)) @@ -1384,19 +1407,19 @@ void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scoreline if (tab[i].color == 0) { colormap = colormaps; - if (players[tab[i].num].powers[pw_super]) + if (supercheck) V_DrawSmallScaledPatch (x, y-4, 0, superprefix[players[tab[i].num].skin]); else { - if (players[tab[i].num].mo && players[tab[i].num].mo->health <= 0) - V_DrawSmallTranslucentPatch (x, y-4, 0, faceprefix[players[tab[i].num].skin]); + if (greycheck) + V_DrawSmallTranslucentPatch (x, y-4, V_80TRANS, faceprefix[players[tab[i].num].skin]); else V_DrawSmallScaledPatch (x, y-4, 0, faceprefix[players[tab[i].num].skin]); } } else { - if (players[tab[i].num].powers[pw_super]) + if (supercheck) { colormap = R_GetTranslationColormap(players[tab[i].num].skin, players[tab[i].num].mo ? players[tab[i].num].mo->color : tab[i].color, GTC_CACHE); V_DrawSmallMappedPatch (x, y-4, 0, superprefix[players[tab[i].num].skin], colormap); @@ -1404,8 +1427,8 @@ void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scoreline else { colormap = R_GetTranslationColormap(players[tab[i].num].skin, players[tab[i].num].mo ? players[tab[i].num].mo->color : tab[i].color, GTC_CACHE); - if (players[tab[i].num].mo && players[tab[i].num].mo->health <= 0) - V_DrawSmallTranslucentMappedPatch (x, y-4, 0, faceprefix[players[tab[i].num].skin], colormap); + if (greycheck) + V_DrawSmallTranslucentMappedPatch (x, y-4, V_80TRANS, faceprefix[players[tab[i].num].skin], colormap); else V_DrawSmallMappedPatch (x, y-4, 0, faceprefix[players[tab[i].num].skin], colormap); } @@ -1419,13 +1442,13 @@ void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scoreline if (players[tab[i].num].exiting) V_DrawRightAlignedThinString(x+156, y, 0, va("%i:%02i.%02i", G_TicsToMinutes(players[tab[i].num].realtime,true), G_TicsToSeconds(players[tab[i].num].realtime), G_TicsToCentiseconds(players[tab[i].num].realtime))); else - V_DrawRightAlignedThinString(x+156, y, ((players[tab[i].num].mo && players[tab[i].num].mo->health > 0) ? 0 : V_TRANSLUCENT), va("%u", tab[i].count)); + V_DrawRightAlignedThinString(x+156, y, (greycheck ? V_TRANSLUCENT : 0), va("%u", tab[i].count)); } else - V_DrawRightAlignedThinString(x+156, y, ((players[tab[i].num].mo && players[tab[i].num].mo->health > 0) ? 0 : V_TRANSLUCENT), va("%i:%02i.%02i", G_TicsToMinutes(tab[i].count,true), G_TicsToSeconds(tab[i].count), G_TicsToCentiseconds(tab[i].count))); + V_DrawRightAlignedThinString(x+156, y, (greycheck ? V_TRANSLUCENT : 0), va("%i:%02i.%02i", G_TicsToMinutes(tab[i].count,true), G_TicsToSeconds(tab[i].count), G_TicsToCentiseconds(tab[i].count))); } else - V_DrawRightAlignedThinString(x+120, y, ((players[tab[i].num].mo && players[tab[i].num].mo->health > 0) ? 0 : V_TRANSLUCENT), va("%u", tab[i].count)); + V_DrawRightAlignedThinString(x+120, y, (greycheck ? V_TRANSLUCENT : 0), va("%u", tab[i].count)); y += 16; if (y > 160) @@ -1622,61 +1645,67 @@ static void HU_DrawRankings(void) for (j = 0; j < MAXPLAYERS; j++) { - if (!playeringame[j] || players[j].spectator) + if (!playeringame[j]) + continue; + + if (gametype != GT_COOP && players[j].spectator) continue; for (i = 0; i < MAXPLAYERS; i++) { - if (playeringame[i] && !players[i].spectator) + if (!playeringame[i]) + continue; + + if (gametype != GT_COOP && players[i].spectator) + continue; + + if (gametype == GT_RACE) { - if (gametype == GT_RACE) + if (circuitmap) { - if (circuitmap) + if ((unsigned)players[i].laps+1 >= tab[scorelines].count && completed[i] == false) { - if ((unsigned)players[i].laps+1 >= tab[scorelines].count && completed[i] == false) - { - tab[scorelines].count = players[i].laps+1; - tab[scorelines].num = i; - tab[scorelines].color = players[i].skincolor; - tab[scorelines].name = player_names[i]; - } - } - else - { - if (players[i].realtime <= tab[scorelines].count && completed[i] == false) - { - tab[scorelines].count = players[i].realtime; - tab[scorelines].num = i; - tab[scorelines].color = players[i].skincolor; - tab[scorelines].name = player_names[i]; - } - } - } - else if (gametype == GT_COMPETITION) - { - // todo put something more fitting for the gametype here, such as current - // number of categories led - if (players[i].score >= tab[scorelines].count && completed[i] == false) - { - tab[scorelines].count = players[i].score; + tab[scorelines].count = players[i].laps+1; tab[scorelines].num = i; tab[scorelines].color = players[i].skincolor; tab[scorelines].name = player_names[i]; - tab[scorelines].emeralds = players[i].powers[pw_emeralds]; } } else { - if (players[i].score >= tab[scorelines].count && completed[i] == false) + if (players[i].realtime <= tab[scorelines].count && completed[i] == false) { - tab[scorelines].count = players[i].score; + tab[scorelines].count = players[i].realtime; tab[scorelines].num = i; tab[scorelines].color = players[i].skincolor; tab[scorelines].name = player_names[i]; - tab[scorelines].emeralds = players[i].powers[pw_emeralds]; } } } + else if (gametype == GT_COMPETITION) + { + // todo put something more fitting for the gametype here, such as current + // number of categories led + if (players[i].score >= tab[scorelines].count && completed[i] == false) + { + tab[scorelines].count = players[i].score; + tab[scorelines].num = i; + tab[scorelines].color = players[i].skincolor; + tab[scorelines].name = player_names[i]; + tab[scorelines].emeralds = players[i].powers[pw_emeralds]; + } + } + else + { + if (players[i].score >= tab[scorelines].count && completed[i] == false) + { + tab[scorelines].count = players[i].score; + tab[scorelines].num = i; + tab[scorelines].color = players[i].skincolor; + tab[scorelines].name = player_names[i]; + tab[scorelines].emeralds = players[i].powers[pw_emeralds]; + } + } } completed[tab[scorelines].num] = true; scorelines++; diff --git a/src/hu_stuff.h b/src/hu_stuff.h index 9bfb42912..e757db85a 100644 --- a/src/hu_stuff.h +++ b/src/hu_stuff.h @@ -21,7 +21,7 @@ //------------------------------------ // heads up font //------------------------------------ -#define HU_FONTSTART '\x19' // the first font character +#define HU_FONTSTART '\x16' // the first font character #define HU_FONTEND '~' #define HU_FONTSIZE (HU_FONTEND - HU_FONTSTART + 1) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index de379cdbb..be1455415 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -978,6 +978,19 @@ static int lib_pGivePlayerLives(lua_State *L) return 0; } +static int lib_pGiveCoopLives(lua_State *L) +{ + player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + INT32 numlives = (INT32)luaL_checkinteger(L, 2); + boolean sound = (boolean)lua_opttrueboolean(L, 3); + NOHUD + INLEVEL + if (!player) + return LUA_ErrInvalid(L, "player_t"); + P_GiveCoopLives(player, numlives, sound); + return 0; +} + static int lib_pResetScore(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); @@ -2440,6 +2453,7 @@ static luaL_Reg lib[] = { {"P_SpawnGhostMobj",lib_pSpawnGhostMobj}, {"P_GivePlayerRings",lib_pGivePlayerRings}, {"P_GivePlayerLives",lib_pGivePlayerLives}, + {"P_GiveCoopLives",lib_pGiveCoopLives}, {"P_ResetScore",lib_pResetScore}, {"P_DoJumpShield",lib_pDoJumpShield}, {"P_DoBubbleBounce",lib_pDoBubbleBounce}, diff --git a/src/lua_consolelib.c b/src/lua_consolelib.c index b688155fb..559c576f0 100644 --- a/src/lua_consolelib.c +++ b/src/lua_consolelib.c @@ -399,12 +399,21 @@ static int lib_cvRegisterVar(lua_State *L) // stack: cvar table, cvar userdata lua_getfield(L, LUA_REGISTRYINDEX, "CV_Vars"); I_Assert(lua_istable(L, 3)); + + lua_getfield(L, 3, cvar->name); + if (lua_type(L, -1) != LUA_TNIL) + return luaL_error(L, M_GetText("Variable %s is already defined\n"), cvar->name); + lua_pop(L, 1); + lua_pushvalue(L, 2); lua_setfield(L, 3, cvar->name); lua_pop(L, 1); // actually time to register it to the console now! Finally! + cvar->flags |= CV_MODIFIED; CV_RegisterVar(cvar); + if (cvar->flags & CV_MODIFIED) + return luaL_error(L, "failed to register cvar (probable conflict with internal variable/command names)"); // return cvar userdata return 1; diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index 29e4970c1..8175f1b9b 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -12,6 +12,7 @@ #include "doomdef.h" #ifdef HAVE_BLUA +#include "fastcmp.h" #include "r_defs.h" #include "r_local.h" #include "st_stuff.h" // hudinfo[] @@ -343,6 +344,158 @@ static int libd_cachePatch(lua_State *L) return 1; } +// v.getSpritePatch(sprite, [frame, [angle]]) +static int libd_getSpritePatch(lua_State *L) +{ + UINT32 i; // sprite prefix + UINT32 frame = 0; // 'A' + UINT8 angle = 0; + spritedef_t *sprdef; + spriteframe_t *sprframe; + HUDONLY + + if (lua_isnumber(L, 1)) // sprite number given, e.g. SPR_THOK + { + i = lua_tonumber(L, 1); + if (i >= NUMSPRITES) + return 0; + } + else if (lua_isstring(L, 1)) // sprite prefix name given, e.g. "THOK" + { + const char *name = lua_tostring(L, 1); + for (i = 0; i < NUMSPRITES; i++) + if (fastcmp(name, sprnames[i])) + break; + if (i >= NUMSPRITES) + return 0; + } + else + return 0; + + if (i == SPR_PLAY) // Use getSprite2Patch instead! + return 0; + + sprdef = &sprites[i]; + + // set frame number + frame = luaL_optinteger(L, 2, 0); + frame &= FF_FRAMEMASK; // ignore any bits that are not the actual frame, just in case + if (frame >= sprdef->numframes) + return 0; + // set angle number + sprframe = &sprdef->spriteframes[frame]; + angle = luaL_optinteger(L, 3, 1); + + // convert WAD editor angle numbers (1-8) to internal angle numbers (0-7) + // keep 0 the same since we'll make it default to angle 1 (which is internally 0) + // in case somebody didn't know that angle 0 really just maps all 8 angles to the same patch + if (angle != 0) + angle--; + + if (angle >= 8) // out of range? + return 0; + + // push both the patch and it's "flip" value + LUA_PushUserdata(L, W_CachePatchNum(sprframe->lumppat[angle], PU_STATIC), META_PATCH); + lua_pushboolean(L, (sprframe->flip & (1<= MAXSKINS) + return luaL_error(L, "skin number %d out of range (0 - %d)", i, MAXSKINS-1); + if (i >= numskins) + return 0; + } + else // find skin by name + { + const char *name = luaL_checkstring(L, 1); + for (i = 0; i < numskins; i++) + if (fastcmp(skins[i].name, name)) + break; + if (i >= numskins) + return 0; + } + + lua_remove(L, 1); // remove skin now + + if (lua_isnumber(L, 1)) // sprite number given, e.g. SPR2_STND + { + j = lua_tonumber(L, 1); + if (j & FF_SPR2SUPER) // e.g. SPR2_STND|FF_SPR2SUPER + { + super = true; + j &= ~FF_SPR2SUPER; // remove flag so the next check doesn't fail + } + if (j >= free_spr2) + return 0; + } + else if (lua_isstring(L, 1)) // sprite prefix name given, e.g. "STND" + { + const char *name = lua_tostring(L, 1); + for (j = 0; j < free_spr2; j++) + if (fastcmp(name, spr2names[j])) + break; + // if you want super flags you'll have to use the optional boolean following this + if (j >= free_spr2) + return 0; + } + else + return 0; + + if (lua_isboolean(L, 2)) // optional boolean for superness + { + super = lua_toboolean(L, 2); // note: this can override FF_SPR2SUPER from sprite number + lua_remove(L, 2); // remove + } + // if it's not boolean then just assume it's the frame number + + if (super) + j |= FF_SPR2SUPER; + + j = P_GetSkinSprite2(&skins[i], j, NULL); // feed skin and current sprite2 through to change sprite2 used if necessary + + sprdef = &skins[i].sprites[j]; + + // set frame number + frame = luaL_optinteger(L, 2, 0); + frame &= FF_FRAMEMASK; // ignore any bits that are not the actual frame, just in case + if (frame >= sprdef->numframes) + return 0; + // set angle number + sprframe = &sprdef->spriteframes[frame]; + angle = luaL_optinteger(L, 3, 1); + + // convert WAD editor angle numbers (1-8) to internal angle numbers (0-7) + // keep 0 the same since we'll make it default to angle 1 (which is internally 0) + // in case somebody didn't know that angle 0 really just maps all 8 angles to the same patch + if (angle != 0) + angle--; + + if (angle >= 8) // out of range? + return 0; + + // push both the patch and it's "flip" value + LUA_PushUserdata(L, W_CachePatchNum(sprframe->lumppat[angle], PU_STATIC), META_PATCH); + lua_pushboolean(L, (sprframe->flip & (1<frame = (UINT32)luaL_checkinteger(L, 3); break; case mobj_sprite2: - mo->sprite2 = P_GetMobjSprite2(mo, (UINT8)luaL_checkinteger(L, 3)); + mo->sprite2 = P_GetSkinSprite2(((skin_t *)mo->skin), (UINT8)luaL_checkinteger(L, 3), mo->player); break; case mobj_anim_duration: mo->anim_duration = (UINT16)luaL_checkinteger(L, 3); diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 622309425..b8a6ea4fd 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -320,6 +320,8 @@ static int player_get(lua_State *L) lua_pushangle(L, plr->awayviewaiming); else if (fastcmp(field,"spectator")) lua_pushboolean(L, plr->spectator); + else if (fastcmp(field,"outofcoop")) + lua_pushboolean(L, plr->outofcoop); else if (fastcmp(field,"bot")) lua_pushinteger(L, plr->bot); else if (fastcmp(field,"jointime")) @@ -597,6 +599,8 @@ static int player_set(lua_State *L) plr->awayviewaiming = luaL_checkangle(L, 3); else if (fastcmp(field,"spectator")) plr->spectator = lua_toboolean(L, 3); + else if (fastcmp(field,"outofcoop")) + plr->outofcoop = lua_toboolean(L, 3); else if (fastcmp(field,"bot")) return NOSET; else if (fastcmp(field,"jointime")) diff --git a/src/m_cond.c b/src/m_cond.c index b7735d4ce..9339c4989 100644 --- a/src/m_cond.c +++ b/src/m_cond.c @@ -499,63 +499,63 @@ emblem_t emblemlocations[MAXEMBLEMS] = // FLORAL FIELD // --- {0, 5394, -996, 160, 50, 'N', SKINCOLOR_RUST, 0, "", 0}, - {ET_NGRADE, 0,0,0, 50, 'Q', SKINCOLOR_TEAL, GRADE_A, "", 0}, + {ET_NGRADE, 0,0,0, 50, 'Q', SKINCOLOR_CYAN, GRADE_A, "", 0}, {ET_NTIME, 0,0,0, 50, 'T', SKINCOLOR_GREY, 40*TICRATE, "", 0}, // TOXIC PLATEAU // --- {0, 780, -1664, 32, 51, 'N', SKINCOLOR_RUST, 0, "", 0}, - {ET_NGRADE, 0,0,0, 51, 'Q', SKINCOLOR_TEAL, GRADE_A, "", 0}, + {ET_NGRADE, 0,0,0, 51, 'Q', SKINCOLOR_CYAN, GRADE_A, "", 0}, {ET_NTIME, 0,0,0, 51, 'T', SKINCOLOR_GREY, 50*TICRATE, "", 0}, // FLOODED COVE // --- {0, 1824, -1888, 2448, 52, 'N', SKINCOLOR_RUST, 0, "", 0}, - {ET_NGRADE, 0,0,0, 52, 'Q', SKINCOLOR_TEAL, GRADE_A, "", 0}, + {ET_NGRADE, 0,0,0, 52, 'Q', SKINCOLOR_CYAN, GRADE_A, "", 0}, {ET_NTIME, 0,0,0, 52, 'T', SKINCOLOR_GREY, 90*TICRATE, "", 0}, // CAVERN FORTRESS // --- {0, -3089, -431, 1328, 53, 'N', SKINCOLOR_RUST, 0, "", 0}, - {ET_NGRADE, 0,0,0, 53, 'Q', SKINCOLOR_TEAL, GRADE_A, "", 0}, + {ET_NGRADE, 0,0,0, 53, 'Q', SKINCOLOR_CYAN, GRADE_A, "", 0}, {ET_NTIME, 0,0,0, 53, 'T', SKINCOLOR_GREY, 75*TICRATE, "", 0}, // DUSTY WASTELAND // --- {0, 957, 924, 2956, 54, 'N', SKINCOLOR_RUST, 0, "", 0}, - {ET_NGRADE, 0,0,0, 54, 'Q', SKINCOLOR_TEAL, GRADE_A, "", 0}, + {ET_NGRADE, 0,0,0, 54, 'Q', SKINCOLOR_CYAN, GRADE_A, "", 0}, {ET_NTIME, 0,0,0, 54, 'T', SKINCOLOR_GREY, 65*TICRATE, "", 0}, // MAGMA CAVES // --- {0, -2752, 3104, 1800, 55, 'N', SKINCOLOR_RUST, 0, "", 0}, - {ET_NGRADE, 0,0,0, 55, 'Q', SKINCOLOR_TEAL, GRADE_A, "", 0}, + {ET_NGRADE, 0,0,0, 55, 'Q', SKINCOLOR_CYAN, GRADE_A, "", 0}, {ET_NTIME, 0,0,0, 55, 'T', SKINCOLOR_GREY, 80*TICRATE, "", 0}, // EGG SATELLITE // --- {0, 5334, -609, 3426, 56, 'N', SKINCOLOR_RUST, 0, "", 0}, - {ET_NGRADE, 0,0,0, 56, 'Q', SKINCOLOR_TEAL, GRADE_A, "", 0}, + {ET_NGRADE, 0,0,0, 56, 'Q', SKINCOLOR_CYAN, GRADE_A, "", 0}, {ET_NTIME, 0,0,0, 56, 'T', SKINCOLOR_GREY, 120*TICRATE, "", 0}, // BLACK HOLE // --- {0, 2108, 3776, 32, 57, 'N', SKINCOLOR_RUST, 0, "", 0}, - {ET_NGRADE, 0,0,0, 57, 'Q', SKINCOLOR_TEAL, GRADE_A, "", 0}, + {ET_NGRADE, 0,0,0, 57, 'Q', SKINCOLOR_CYAN, GRADE_A, "", 0}, {ET_NTIME, 0,0,0, 57, 'T', SKINCOLOR_GREY, 150*TICRATE, "", 0}, // SPRING HILL // --- {0, -1840, -1024, 1644, 58, 'N', SKINCOLOR_RUST, 0, "", 0}, - {ET_NGRADE, 0,0,0, 58, 'Q', SKINCOLOR_TEAL, GRADE_A, "", 0}, + {ET_NGRADE, 0,0,0, 58, 'Q', SKINCOLOR_CYAN, GRADE_A, "", 0}, {ET_NTIME, 0,0,0, 58, 'T', SKINCOLOR_GREY, 60*TICRATE, "", 0}, }; @@ -566,7 +566,7 @@ extraemblem_t extraemblems[MAXEXTRAEMBLEMS] = {"All Emeralds", "Complete 1P Mode with all Emeralds", 11, 'V', SKINCOLOR_GREY, 0}, {"Perfect Bonus", "Perfect Bonus on a non-secret stage", 30, 'P', SKINCOLOR_GOLD, 0}, {"PLACEHOLDER", "PLACEHOLDER", 0, 'O', SKINCOLOR_RUST, 0}, - {"NiGHTS Mastery", "Show your mastery of NiGHTS!", 22, 'W', SKINCOLOR_TEAL, 0}, + {"NiGHTS Mastery", "Show your mastery of NiGHTS!", 22, 'W', SKINCOLOR_CYAN, 0}, }; // Default Unlockables diff --git a/src/m_menu.c b/src/m_menu.c index dc74ae5d2..64255e71a 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -263,7 +263,7 @@ static void M_ConfirmTeamChange(INT32 choice); static void M_SecretsMenu(INT32 choice); static void M_SetupChoosePlayer(INT32 choice); static void M_QuitSRB2(INT32 choice); -menu_t SP_MainDef, MP_MainDef, OP_MainDef; +menu_t SP_MainDef, OP_MainDef; menu_t MISC_ScrambleTeamDef, MISC_ChangeTeamDef; // Single Player @@ -286,21 +286,19 @@ static menu_t SP_TimeAttackDef, SP_ReplayDef, SP_GuestReplayDef, SP_GhostDef; static menu_t SP_NightsAttackDef, SP_NightsReplayDef, SP_NightsGuestReplayDef, SP_NightsGhostDef; // Multiplayer -#ifndef NONET -static void M_StartServerMenu(INT32 choice); -static void M_ConnectMenu(INT32 choice); -static void M_ConnectIPMenu(INT32 choice); -#endif +static void M_SetupMultiPlayer(INT32 choice); +static void M_SetupMultiPlayer2(INT32 choice); static void M_StartSplitServerMenu(INT32 choice); static void M_StartServer(INT32 choice); static void M_ServerOptions(INT32 choice); #ifndef NONET +static void M_StartServerMenu(INT32 choice); +static void M_ConnectMenu(INT32 choice); static void M_Refresh(INT32 choice); static void M_Connect(INT32 choice); static void M_ChooseRoom(INT32 choice); +menu_t MP_MainDef; #endif -static void M_SetupMultiPlayer(INT32 choice); -static void M_SetupMultiPlayer2(INT32 choice); // Options // Split into multiple parts due to size @@ -376,16 +374,13 @@ static void M_OGL_DrawColorMenu(void); #ifndef NONET static void M_DrawScreenshotMenu(void); static void M_DrawConnectMenu(void); -static void M_DrawConnectIPMenu(void); +static void M_DrawMPMainMenu(void); static void M_DrawRoomMenu(void); #endif static void M_DrawJoystick(void); static void M_DrawSetupMultiPlayerMenu(void); // Handling functions -#ifndef NONET -static boolean M_CancelConnect(void); -#endif static boolean M_ExitPandorasBox(void); static boolean M_QuitMultiPlayerMenu(void); static void M_HandleAddons(INT32 choice); @@ -395,6 +390,7 @@ static void M_HandleImageDef(INT32 choice); static void M_HandleLoadSave(INT32 choice); static void M_HandleLevelStats(INT32 choice); #ifndef NONET +static boolean M_CancelConnect(void); static void M_HandleConnectIP(INT32 choice); #endif static void M_HandleSetupMultiPlayer(INT32 choice); @@ -497,12 +493,16 @@ static consvar_t cv_dummymares = {"dummymares", "Overall", CV_HIDEN|CV_CALL, dum // --------- static menuitem_t MainMenu[] = { - {IT_CALL |IT_STRING, NULL, "Secrets", M_SecretsMenu, 76}, - {IT_CALL |IT_STRING, NULL, "1 player", M_SinglePlayerMenu, 84}, - {IT_SUBMENU|IT_STRING, NULL, "multiplayer", &MP_MainDef, 92}, - {IT_CALL |IT_STRING, NULL, "options", M_Options, 100}, - {IT_CALL |IT_STRING, NULL, "addons", M_Addons, 108}, - {IT_CALL |IT_STRING, NULL, "quit game", M_QuitSRB2, 116}, + {IT_STRING|IT_CALL, NULL, "Secrets", M_SecretsMenu, 76}, + {IT_STRING|IT_CALL, NULL, "1 player", M_SinglePlayerMenu, 84}, +#ifndef NONET + {IT_STRING|IT_SUBMENU, NULL, "multiplayer", &MP_MainDef, 92}, +#else + {IT_STRING|IT_CALL, NULL, "multiplayer", M_StartSplitServerMenu, 92}, +#endif + {IT_STRING|IT_CALL, NULL, "options", M_Options, 100}, + {IT_CALL |IT_STRING, NULL, "addons", M_Addons, 108}, + {IT_STRING|IT_CALL, NULL, "quit game", M_QuitSRB2, 116}, }; typedef enum @@ -922,56 +922,56 @@ static menuitem_t SP_PlayerMenu[] = // Multiplayer and all of its submenus // ----------------------------------- // Prefix: MP_ + +// Separated splitscreen and normal servers. +static menuitem_t MP_SplitServerMenu[] = +{ + {IT_STRING|IT_CALL, NULL, "Select Gametype/Level...", M_GameTypeChange, 100}, +#ifdef NONET // In order to keep player setup accessible. + {IT_STRING|IT_CALL, NULL, "Player 1 setup...", M_SetupMultiPlayer, 110}, + {IT_STRING|IT_CALL, NULL, "Player 2 setup...", M_SetupMultiPlayer2, 120}, +#endif + {IT_STRING|IT_CALL, NULL, "More Options...", M_ServerOptions, 130}, + {IT_WHITESTRING|IT_CALL, NULL, "Start", M_StartServer, 140}, +}; + +#ifndef NONET + static menuitem_t MP_MainMenu[] = { -#ifndef NONET - {IT_CALL | IT_STRING, NULL, "HOST GAME", M_StartServerMenu, 10}, - {IT_CALL | IT_STRING, NULL, "JOIN GAME (Search)", M_ConnectMenu, 30}, - {IT_CALL | IT_STRING, NULL, "JOIN GAME (Specify IP)", M_ConnectIPMenu, 40}, -#endif - {IT_CALL | IT_STRING, NULL, "TWO PLAYER GAME", M_StartSplitServerMenu, 60}, - - {IT_CALL | IT_STRING, NULL, "PLAYER 1 SETUP", M_SetupMultiPlayer, 80}, - {IT_CALL | IT_STRING, NULL, "PLAYER 2 SETUP", M_SetupMultiPlayer2, 90}, + {IT_HEADER, NULL, "Host a game", NULL, 0}, + {IT_STRING|IT_CALL, NULL, "Internet/LAN...", M_StartServerMenu, 12}, + {IT_STRING|IT_CALL, NULL, "Splitscreen...", M_StartSplitServerMenu, 22}, + {IT_HEADER, NULL, "Join a game", NULL, 40}, + {IT_STRING|IT_CALL, NULL, "Server browser...", M_ConnectMenu, 52}, + {IT_STRING|IT_KEYHANDLER, NULL, "Specify IPv4 address:", M_HandleConnectIP, 62}, + {IT_HEADER, NULL, "Player setup", NULL, 94}, + {IT_STRING|IT_CALL, NULL, "Player 1...", M_SetupMultiPlayer, 106}, + {IT_STRING|IT_CALL, NULL, "Player 2... ", M_SetupMultiPlayer2, 116}, }; static menuitem_t MP_ServerMenu[] = { - {IT_DISABLED|IT_NOTHING, NULL, "", NULL, 0}, -#ifndef NONET - {IT_STRING|IT_CALL, NULL, "Room...", M_RoomMenu, 10}, - {IT_STRING|IT_CVAR|IT_CV_STRING, NULL, "Server Name", &cv_servername, 20}, - {IT_STRING|IT_CVAR, NULL, "Max Players", &cv_maxplayers, 46}, - {IT_STRING|IT_CVAR, NULL, "Allow WAD Downloading", &cv_downloading, 56}, -#endif - {IT_STRING|IT_CALL, NULL, "Select Gametype/Level...", M_GameTypeChange, 100}, - {IT_STRING|IT_CALL, NULL, "More Options...", M_ServerOptions, 130}, - {IT_WHITESTRING|IT_CALL, NULL, "Start", M_StartServer, 140}, + {IT_STRING|IT_CALL, NULL, "Room...", M_RoomMenu, 10}, + {IT_STRING|IT_CVAR|IT_CV_STRING, NULL, "Server Name", &cv_servername, 20}, + {IT_STRING|IT_CVAR, NULL, "Max Players", &cv_maxplayers, 46}, + {IT_STRING|IT_CVAR, NULL, "Allow Add-on Downloading", &cv_downloading, 56}, + {IT_STRING|IT_CALL, NULL, "Select Gametype/Level...", M_GameTypeChange, 100}, + {IT_STRING|IT_CALL, NULL, "More Options...", M_ServerOptions, 130}, + {IT_WHITESTRING|IT_CALL, NULL, "Start", M_StartServer, 140}, }; enum { - mp_server_dummy = 0, // exists solely so zero-indexed in both NONET and not NONET -#ifndef NONET - mp_server_room, + mp_server_room = 0, mp_server_name, mp_server_maxpl, mp_server_waddl, -#endif mp_server_levelgt, mp_server_options, mp_server_start }; -// Separated splitscreen and normal servers. -static menuitem_t MP_SplitServerMenu[] = -{ - {IT_STRING|IT_CALL, NULL, "Select Gametype/Level...", M_GameTypeChange, 100}, - {IT_STRING|IT_CALL, NULL, "More Options...", M_ServerOptions, 130}, - {IT_WHITESTRING|IT_CALL, NULL, "Start", M_StartServer, 140}, -}; - -#ifndef NONET static menuitem_t MP_ConnectMenu[] = { {IT_STRING | IT_CALL, NULL, "Room...", M_RoomMenu, 4}, @@ -1023,17 +1023,14 @@ static menuitem_t MP_RoomMenu[] = {IT_DISABLED, NULL, "", M_ChooseRoom, 162}, }; -static menuitem_t MP_ConnectIPMenu[] = -{ - {IT_KEYHANDLER | IT_STRING, NULL, " IP Address:", M_HandleConnectIP, 0}, -}; #endif static menuitem_t MP_PlayerSetupMenu[] = { - {IT_KEYHANDLER | IT_STRING, NULL, "Your name", M_HandleSetupMultiPlayer, 0}, - {IT_KEYHANDLER | IT_STRING, NULL, "Your color", M_HandleSetupMultiPlayer, 16}, - {IT_KEYHANDLER | IT_STRING, NULL, "Your player", M_HandleSetupMultiPlayer, 96}, // Tails 01-18-2001 + {IT_KEYHANDLER, NULL, "", M_HandleSetupMultiPlayer, 0}, // name + {IT_KEYHANDLER, NULL, "", M_HandleSetupMultiPlayer, 0}, // skin + {IT_KEYHANDLER, NULL, "", M_HandleSetupMultiPlayer, 0}, // colour + {IT_KEYHANDLER, NULL, "", M_HandleSetupMultiPlayer, 0}, // default }; // ------------------------------------ @@ -1134,23 +1131,23 @@ static menuitem_t OP_ChangeControlsMenu[] = static menuitem_t OP_Joystick1Menu[] = { {IT_STRING | IT_CALL, NULL, "Select Joystick...", M_Setup1PJoystickMenu, 10}, - {IT_STRING | IT_CVAR, NULL, "Move \x1A \x1B Axis" , &cv_moveaxis , 30}, - {IT_STRING | IT_CVAR, NULL, "Move \x1C \x1D Axis" , &cv_sideaxis , 40}, - {IT_STRING | IT_CVAR, NULL, "Camera \x1A \x1B Axis" , &cv_lookaxis , 50}, - {IT_STRING | IT_CVAR, NULL, "Camera \x1C \x1D Axis" , &cv_turnaxis , 60}, - {IT_STRING | IT_CVAR, NULL, "Fire Axis" , &cv_fireaxis , 70}, - {IT_STRING | IT_CVAR, NULL, "Fire Normal Axis" , &cv_firenaxis , 80}, + {IT_STRING | IT_CVAR, NULL, "Move \x17 Axis" , &cv_moveaxis , 30}, + {IT_STRING | IT_CVAR, NULL, "Move \x18 Axis" , &cv_sideaxis , 40}, + {IT_STRING | IT_CVAR, NULL, "Camera \x17 Axis" , &cv_lookaxis , 50}, + {IT_STRING | IT_CVAR, NULL, "Camera \x18 Axis" , &cv_turnaxis , 60}, + {IT_STRING | IT_CVAR, NULL, "Fire Axis" , &cv_fireaxis , 70}, + {IT_STRING | IT_CVAR, NULL, "Fire Normal Axis" , &cv_firenaxis , 80}, }; static menuitem_t OP_Joystick2Menu[] = { {IT_STRING | IT_CALL, NULL, "Select Joystick...", M_Setup2PJoystickMenu, 10}, - {IT_STRING | IT_CVAR, NULL, "Move \x1A \x1B Axis" , &cv_moveaxis2 , 30}, - {IT_STRING | IT_CVAR, NULL, "Move \x1C \x1D Axis" , &cv_sideaxis2 , 40}, - {IT_STRING | IT_CVAR, NULL, "Camera \x1A \x1B Axis" , &cv_lookaxis2 , 50}, - {IT_STRING | IT_CVAR, NULL, "Camera \x1C \x1D Axis" , &cv_turnaxis2 , 60}, - {IT_STRING | IT_CVAR, NULL, "Fire Axis" , &cv_fireaxis2 , 70}, - {IT_STRING | IT_CVAR, NULL, "Fire Normal Axis" , &cv_firenaxis2 , 80}, + {IT_STRING | IT_CVAR, NULL, "Move \x17 Axis" , &cv_moveaxis2 , 30}, + {IT_STRING | IT_CVAR, NULL, "Move \x18 Axis" , &cv_sideaxis2 , 40}, + {IT_STRING | IT_CVAR, NULL, "Camera \x17 Axis" , &cv_lookaxis2 , 50}, + {IT_STRING | IT_CVAR, NULL, "Camera \x18 Axis" , &cv_turnaxis2 , 60}, + {IT_STRING | IT_CVAR, NULL, "Fire Axis" , &cv_fireaxis2 , 70}, + {IT_STRING | IT_CVAR, NULL, "Fire Normal Axis" , &cv_firenaxis2 , 80}, }; static menuitem_t OP_JoystickSetMenu[] = @@ -1393,7 +1390,7 @@ static menuitem_t OP_AddonsOptionsMenu[] = {IT_HEADER, NULL, "Menu", NULL, 0}, {IT_STRING|IT_CVAR, NULL, "Location", &cv_addons_option, 12}, {IT_STRING|IT_CVAR|IT_CV_STRING, NULL, "Custom Folder", &cv_addons_folder, 22}, - {IT_STRING|IT_CVAR, NULL, "Identify loaded files via", &cv_addons_md5, 50}, + {IT_STRING|IT_CVAR, NULL, "Identify add-ons via", &cv_addons_md5, 50}, {IT_STRING|IT_CVAR, NULL, "Show unsupported file types", &cv_addons_showall, 60}, {IT_HEADER, NULL, "Search", NULL, 78}, @@ -1413,7 +1410,7 @@ static menuitem_t OP_ServerOptionsMenu[] = {IT_STRING | IT_CVAR | IT_CV_STRING, NULL, "Server name", &cv_servername, 7}, {IT_STRING | IT_CVAR, NULL, "Max Players", &cv_maxplayers, 21}, - {IT_STRING | IT_CVAR, NULL, "Allow WAD Downloading", &cv_downloading, 26}, + {IT_STRING | IT_CVAR, NULL, "Allow Add-on Downloading", &cv_downloading, 26}, {IT_STRING | IT_CVAR, NULL, "Allow players to join", &cv_allownewplayer, 31}, #endif {IT_STRING | IT_CVAR, NULL, "Map progression", &cv_advancemap, 36}, @@ -1425,33 +1422,38 @@ static menuitem_t OP_ServerOptionsMenu[] = {IT_HEADER, NULL, "Items", NULL, 70}, {IT_STRING | IT_CVAR, NULL, "Item respawn delay", &cv_itemrespawntime, 76}, - {IT_STRING | IT_SUBMENU, NULL, "Random Item Box Toggles...", &OP_MonitorToggleDef, 81}, + {IT_STRING | IT_SUBMENU, NULL, "Mystery Item Monitor Toggles...", &OP_MonitorToggleDef, 81}, - {IT_HEADER, NULL, "Platform (Coop, Race, Competition)", NULL, 90}, + {IT_HEADER, NULL, "Cooperative", NULL, 90}, {IT_STRING | IT_CVAR, NULL, "Players required for exit", &cv_playersforexit, 96}, - {IT_STRING | IT_CVAR, NULL, "Level completion countdown", &cv_countdowntime, 101}, - {IT_STRING | IT_CVAR, NULL, "Item Boxes", &cv_competitionboxes, 106}, + {IT_STRING | IT_CVAR, NULL, "Starposts", &cv_coopstarposts, 101}, + {IT_STRING | IT_CVAR, NULL, "Life sharing", &cv_cooplives, 106}, - {IT_HEADER, NULL, "Ringslinger (Match, CTF, Tag, H&S)", NULL, 115}, - {IT_STRING | IT_CVAR, NULL, "Time Limit", &cv_timelimit, 121}, - {IT_STRING | IT_CVAR, NULL, "Score Limit", &cv_pointlimit, 126}, - {IT_STRING | IT_CVAR, NULL, "Overtime on Tie", &cv_overtime, 131}, - {IT_STRING | IT_CVAR, NULL, "Player respawn delay", &cv_respawntime, 136}, + {IT_HEADER, NULL, "Race, Competition", NULL, 115}, + {IT_STRING | IT_CVAR, NULL, "Level completion countdown", &cv_countdowntime, 121}, + {IT_STRING | IT_CVAR, NULL, "Item Monitors", &cv_competitionboxes, 126}, - {IT_STRING | IT_CVAR, NULL, "Item Boxes", &cv_matchboxes, 146}, - {IT_STRING | IT_CVAR, NULL, "Weapon Rings", &cv_specialrings, 151}, - {IT_STRING | IT_CVAR, NULL, "Power Stones", &cv_powerstones, 156}, + {IT_HEADER, NULL, "Ringslinger (Match, CTF, Tag, H&S)", NULL, 135}, + {IT_STRING | IT_CVAR, NULL, "Time Limit", &cv_timelimit, 141}, + {IT_STRING | IT_CVAR, NULL, "Score Limit", &cv_pointlimit, 146}, + {IT_STRING | IT_CVAR, NULL, "Overtime on Tie", &cv_overtime, 151}, + {IT_STRING | IT_CVAR, NULL, "Player respawn delay", &cv_respawntime, 156}, - {IT_STRING | IT_CVAR, NULL, "Flag respawn delay", &cv_flagtime, 166}, - {IT_STRING | IT_CVAR, NULL, "Hiding time", &cv_hidetime, 171}, + {IT_STRING | IT_CVAR, NULL, "Item Monitors", &cv_matchboxes, 166}, + {IT_STRING | IT_CVAR, NULL, "Weapon Rings", &cv_specialrings, 171}, + {IT_STRING | IT_CVAR, NULL, "Power Stones", &cv_powerstones, 176}, - {IT_STRING | IT_CVAR, NULL, "Autobalance Teams", &cv_autobalance, 181}, - {IT_STRING | IT_CVAR, NULL, "Scramble Teams on Map Change", &cv_scrambleonchange, 186}, + {IT_STRING | IT_CVAR, NULL, "Flag respawn delay", &cv_flagtime, 186}, + {IT_STRING | IT_CVAR, NULL, "Hiding time", &cv_hidetime, 191}, + + {IT_HEADER, NULL, "Teams", NULL, 200}, + {IT_STRING | IT_CVAR, NULL, "Autobalance sizes", &cv_autobalance, 206}, + {IT_STRING | IT_CVAR, NULL, "Scramble on Map Change", &cv_scrambleonchange, 211}, #ifndef NONET - {IT_HEADER, NULL, "Advanced", NULL, 195}, - {IT_STRING | IT_CVAR | IT_CV_STRING, NULL, "Master server", &cv_masterserver, 201}, - {IT_STRING | IT_CVAR, NULL, "Attempts to resynchronise", &cv_resynchattempts, 215}, + {IT_HEADER, NULL, "Advanced", NULL, 220}, + {IT_STRING | IT_CVAR | IT_CV_STRING, NULL, "Master server", &cv_masterserver, 226}, + {IT_STRING | IT_CVAR, NULL, "Attempts to resynchronise", &cv_resynchattempts, 240}, #endif }; @@ -1460,11 +1462,11 @@ static menuitem_t OP_MonitorToggleMenu[] = // Printing handled by drawing function {IT_STRING|IT_CALL, NULL, "Reset to defaults", M_ResetCvars, 15}, {IT_STRING|IT_CVAR|IT_CV_INVISSLIDER, NULL, "Recycler", &cv_recycler, 30}, - {IT_STRING|IT_CVAR|IT_CV_INVISSLIDER, NULL, "Teleporters", &cv_teleporters, 40}, + {IT_STRING|IT_CVAR|IT_CV_INVISSLIDER, NULL, "Teleport", &cv_teleporters, 40}, {IT_STRING|IT_CVAR|IT_CV_INVISSLIDER, NULL, "Super Ring", &cv_superring, 50}, {IT_STRING|IT_CVAR|IT_CV_INVISSLIDER, NULL, "Super Sneakers", &cv_supersneakers, 60}, {IT_STRING|IT_CVAR|IT_CV_INVISSLIDER, NULL, "Invincibility", &cv_invincibility, 70}, - {IT_STRING|IT_CVAR|IT_CV_INVISSLIDER, NULL, "Jump Shield", &cv_jumpshield, 80}, + {IT_STRING|IT_CVAR|IT_CV_INVISSLIDER, NULL, "Whirlwind Shield", &cv_jumpshield, 80}, {IT_STRING|IT_CVAR|IT_CV_INVISSLIDER, NULL, "Elemental Shield", &cv_watershield, 90}, {IT_STRING|IT_CVAR|IT_CV_INVISSLIDER, NULL, "Attraction Shield", &cv_ringshield, 100}, {IT_STRING|IT_CVAR|IT_CV_INVISSLIDER, NULL, "Force Shield", &cv_forceshield, 110}, @@ -1711,29 +1713,16 @@ menu_t SP_PlayerDef = }; // Multiplayer -menu_t MP_MainDef = DEFAULTMENUSTYLE("M_MULTI", MP_MainMenu, &MainDef, 60, 40); - -menu_t MP_ServerDef = -{ - "M_MULTI", - sizeof (MP_ServerMenu)/sizeof (menuitem_t), - &MP_MainDef, - MP_ServerMenu, - M_DrawServerMenu, - 27, 30 -#ifdef NONET - - 50 -#endif - , - 0, - NULL -}; menu_t MP_SplitServerDef = { "M_MULTI", sizeof (MP_SplitServerMenu)/sizeof (menuitem_t), +#ifndef NONET &MP_MainDef, +#else + &MainDef, +#endif MP_SplitServerMenu, M_DrawServerMenu, 27, 30 - 50, @@ -1742,6 +1731,31 @@ menu_t MP_SplitServerDef = }; #ifndef NONET + +menu_t MP_MainDef = +{ + "M_MULTI", + sizeof (MP_MainMenu)/sizeof (menuitem_t), + &MainDef, + MP_MainMenu, + M_DrawMPMainMenu, + 27, 40, + 0, + M_CancelConnect +}; + +menu_t MP_ServerDef = +{ + "M_MULTI", + sizeof (MP_ServerMenu)/sizeof (menuitem_t), + &MP_MainDef, + MP_ServerMenu, + M_DrawServerMenu, + 27, 30, + 0, + NULL +}; + menu_t MP_ConnectDef = { "M_MULTI", @@ -1753,17 +1767,7 @@ menu_t MP_ConnectDef = 0, M_CancelConnect }; -menu_t MP_ConnectIPDef = -{ - "M_MULTI", - sizeof (MP_ConnectIPMenu)/sizeof (menuitem_t), - &MP_MainDef, - MP_ConnectIPMenu, - M_DrawConnectIPMenu, - 27,40, - 0, - M_CancelConnect -}; + menu_t MP_RoomDef = { "M_MULTI", @@ -1781,23 +1785,23 @@ menu_t MP_PlayerSetupDef = { "M_SPLAYR", sizeof (MP_PlayerSetupMenu)/sizeof (menuitem_t), - &MP_MainDef, + &MainDef, // doesn't matter MP_PlayerSetupMenu, M_DrawSetupMultiPlayerMenu, - 27, 40, + 19, 22, 0, M_QuitMultiPlayerMenu }; // Options -menu_t OP_MainDef = DEFAULTMENUSTYLE("M_OPTTTL", OP_MainMenu, &MainDef, 60, 30); +menu_t OP_MainDef = DEFAULTMENUSTYLE("M_OPTTTL", OP_MainMenu, &MainDef, 50, 30); menu_t OP_ChangeControlsDef = CONTROLMENUSTYLE(OP_ChangeControlsMenu, &OP_MainDef); menu_t OP_P1ControlsDef = DEFAULTMENUSTYLE("M_CONTRO", OP_P1ControlsMenu, &OP_MainDef, 50, 30); menu_t OP_P2ControlsDef = DEFAULTMENUSTYLE("M_CONTRO", OP_P2ControlsMenu, &OP_MainDef, 50, 30); menu_t OP_MouseOptionsDef = DEFAULTMENUSTYLE("M_CONTRO", OP_MouseOptionsMenu, &OP_P1ControlsDef, 35, 30); menu_t OP_Mouse2OptionsDef = DEFAULTMENUSTYLE("M_CONTRO", OP_Mouse2OptionsMenu, &OP_P2ControlsDef, 35, 30); -menu_t OP_Joystick1Def = DEFAULTMENUSTYLE("M_CONTRO", OP_Joystick1Menu, &OP_P1ControlsDef, 60, 30); -menu_t OP_Joystick2Def = DEFAULTMENUSTYLE("M_CONTRO", OP_Joystick2Menu, &OP_P2ControlsDef, 60, 30); +menu_t OP_Joystick1Def = DEFAULTMENUSTYLE("M_CONTRO", OP_Joystick1Menu, &OP_P1ControlsDef, 50, 30); +menu_t OP_Joystick2Def = DEFAULTMENUSTYLE("M_CONTRO", OP_Joystick2Menu, &OP_P2ControlsDef, 50, 30); menu_t OP_JoystickSetDef = { "M_CONTRO", @@ -3000,7 +3004,7 @@ static void M_DrawThermo(INT32 x, INT32 y, consvar_t *cv) } // A smaller 'Thermo', with range given as percents (0-100) -static void M_DrawSlider(INT32 x, INT32 y, const consvar_t *cv) +static void M_DrawSlider(INT32 x, INT32 y, const consvar_t *cv, boolean ontop) { INT32 i; INT32 range; @@ -3014,6 +3018,14 @@ static void M_DrawSlider(INT32 x, INT32 y, const consvar_t *cv) for (i = 1; i < SLIDER_RANGE; i++) V_DrawScaledPatch (x+i*8, y, 0,p); + if (ontop) + { + V_DrawCharacter(x - 6 - (skullAnimCounter/5), y, + '\x1C' | V_YELLOWMAP, false); + V_DrawCharacter(x+i*8 + 8 + (skullAnimCounter/5), y, + '\x1D' | V_YELLOWMAP, false); + } + p = W_CachePatchName("M_SLIDER", PU_CACHE); V_DrawScaledPatch(x+i*8, y, 0, p); @@ -3263,7 +3275,7 @@ static void M_DrawGenericMenu(void) switch (currentMenu->menuitems[i].status & IT_CVARTYPE) { case IT_CV_SLIDER: - M_DrawSlider(x, y, cv); + M_DrawSlider(x, y, cv, (i == itemOn)); case IT_CV_NOPRINT: // color use this case IT_CV_INVISSLIDER: // monitor toggles use this break; @@ -3278,6 +3290,13 @@ static void M_DrawGenericMenu(void) default: V_DrawRightAlignedString(BASEVIDWIDTH - x, y, ((cv->flags & CV_CHEAT) && !CV_IsSetToDefault(cv) ? V_REDMAP : V_YELLOWMAP), cv->string); + if (i == itemOn) + { + V_DrawCharacter(BASEVIDWIDTH - x - 10 - V_StringWidth(cv->string, 0) - (skullAnimCounter/5), y, + '\x1C' | V_YELLOWMAP, false); + V_DrawCharacter(BASEVIDWIDTH - x + 2 + (skullAnimCounter/5), y, + '\x1D' | V_YELLOWMAP, false); + } break; } break; @@ -3372,9 +3391,9 @@ static void M_DrawGenericScrollMenu(void) } if (i) - V_DrawString(currentMenu->x - 20, currentMenu->y, V_YELLOWMAP, "\x1A"); // up arrow + V_DrawString(currentMenu->x - 20, currentMenu->y - (skullAnimCounter/5), V_YELLOWMAP, "\x1A"); // up arrow if (max != bottom) - V_DrawString(currentMenu->x - 20, currentMenu->y + 2*scrollareaheight, V_YELLOWMAP, "\x1B"); // down arrow + V_DrawString(currentMenu->x - 20, currentMenu->y + 2*scrollareaheight + (skullAnimCounter/5), V_YELLOWMAP, "\x1B"); // down arrow // draw title (or big pic) M_DrawMenuTitle(); @@ -3412,7 +3431,7 @@ static void M_DrawGenericScrollMenu(void) switch (currentMenu->menuitems[i].status & IT_CVARTYPE) { case IT_CV_SLIDER: - M_DrawSlider(x, y, cv); + M_DrawSlider(x, y, cv, (i == itemOn)); case IT_CV_NOPRINT: // color use this case IT_CV_INVISSLIDER: // monitor toggles use this break; @@ -3441,6 +3460,13 @@ static void M_DrawGenericScrollMenu(void) default: V_DrawRightAlignedString(BASEVIDWIDTH - x, y, ((cv->flags & CV_CHEAT) && !CV_IsSetToDefault(cv) ? V_REDMAP : V_YELLOWMAP), cv->string); + if (i == itemOn) + { + V_DrawCharacter(BASEVIDWIDTH - x - 10 - V_StringWidth(cv->string, 0) - (skullAnimCounter/5), y, + '\x1C' | V_YELLOWMAP, false); + V_DrawCharacter(BASEVIDWIDTH - x + 2 + (skullAnimCounter/5), y, + '\x1D' | V_YELLOWMAP, false); + } break; } break; @@ -3668,7 +3694,7 @@ static void M_DrawCenteredMenu(void) switch(currentMenu->menuitems[i].status & IT_CVARTYPE) { case IT_CV_SLIDER: - M_DrawSlider(x, y, cv); + M_DrawSlider(x, y, cv, (i == itemOn)); case IT_CV_NOPRINT: // color use this break; case IT_CV_STRING: @@ -3682,6 +3708,13 @@ static void M_DrawCenteredMenu(void) default: V_DrawString(BASEVIDWIDTH - x - V_StringWidth(cv->string, 0), y, ((cv->flags & CV_CHEAT) && !CV_IsSetToDefault(cv) ? V_REDMAP : V_YELLOWMAP), cv->string); + if (i == itemOn) + { + V_DrawCharacter(BASEVIDWIDTH - x - 10 - V_StringWidth(cv->string, 0) - (skullAnimCounter/5), y, + '\x1C' | V_YELLOWMAP, false); + V_DrawCharacter(BASEVIDWIDTH - x + 2 + (skullAnimCounter/5), y, + '\x1D' | V_YELLOWMAP, false); + } break; } break; @@ -4913,7 +4946,7 @@ static void M_DrawAddons(void) } if (i != 0) - V_DrawString(19, y+4, V_YELLOWMAP, "\x1A"); + V_DrawString(19, y+4 - (skullAnimCounter/5), V_YELLOWMAP, "\x1A"); for (; i < max; i++) { @@ -4948,7 +4981,7 @@ static void M_DrawAddons(void) } if (max != (ssize_t)sizedirmenu) - V_DrawString(19, y-12, V_YELLOWMAP, "\x1B"); + V_DrawString(19, y-12 + (skullAnimCounter/5), V_YELLOWMAP, "\x1B"); y = BASEVIDHEIGHT - currentMenu->y + offs; @@ -4980,7 +5013,7 @@ static void M_AddonExec(INT32 ch) if (ch != 'y' && ch != KEY_ENTER) return; - S_StartSound(NULL, sfx_strpst); + S_StartSound(NULL, sfx_zoom); COM_BufAddText(va("exec %s%s", menupath, dirmenu[dir_on[menudepthleft]]+DIR_STRING)); } @@ -5382,13 +5415,21 @@ static void M_HandleChecklist(INT32 choice) { case KEY_DOWNARROW: S_StartSound(NULL, sfx_menu1); - if (checklist_cangodown) + if ((check_on != MAXUNLOCKABLES) && checklist_cangodown) { for (j = check_on+1; j < MAXUNLOCKABLES; j++) { - if (!(unlockables[j].name[0] == 0 //|| unlockables[j].nochecklist - || !unlockables[j].conditionset || unlockables[j].conditionset > MAXCONDITIONSETS)) - break; + if (!unlockables[j].name[0]) + continue; + // if (unlockables[j].nochecklist) + // continue; + if (!unlockables[j].conditionset) + continue; + if (unlockables[j].conditionset > MAXCONDITIONSETS) + continue; + if (unlockables[j].conditionset == unlockables[check_on].conditionset) + continue; + break; } if (j != MAXUNLOCKABLES) check_on = j; @@ -5397,14 +5438,25 @@ static void M_HandleChecklist(INT32 choice) case KEY_UPARROW: S_StartSound(NULL, sfx_menu1); - for (j = check_on-1; j > -1; j--) + if (check_on) { - if (!(unlockables[j].name[0] == 0 //|| unlockables[j].nochecklist - || !unlockables[j].conditionset || unlockables[j].conditionset > MAXCONDITIONSETS)) + for (j = check_on-1; j > -1; j--) + { + if (!unlockables[j].name[0]) + continue; + // if (unlockables[j].nochecklist) + // continue; + if (!unlockables[j].conditionset) + continue; + if (unlockables[j].conditionset > MAXCONDITIONSETS) + continue; + if (j && unlockables[j].conditionset == unlockables[j-1].conditionset) + continue; break; + } + if (j != -1) + check_on = j; } - if (j != -1) - check_on = j; return; case KEY_ESCAPE: @@ -5430,7 +5482,7 @@ static void M_DrawChecklist(void) M_DrawMenuTitle(); if (check_on) - V_DrawString(10, y, V_YELLOWMAP, "\x1A"); + V_DrawString(10, y-(skullAnimCounter/5), V_YELLOWMAP, "\x1A"); while (i < MAXUNLOCKABLES) { @@ -5688,7 +5740,7 @@ static void M_DrawChecklist(void) finishchecklist: if ((checklist_cangodown = ((y - currentMenu->y) > (scrollareaheight*2)))) // haaaaaaacks. - V_DrawString(10, currentMenu->y+(scrollareaheight*2), V_YELLOWMAP, "\x1B"); + V_DrawString(10, currentMenu->y+(scrollareaheight*2)+(skullAnimCounter/5), V_YELLOWMAP, "\x1B"); } #define NUMHINTS 5 @@ -5759,6 +5811,13 @@ static void M_DrawSkyRoom(void) return; V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, currentMenu->y + y, V_YELLOWMAP, cv_soundtest.string); + if (i == itemOn) + { + V_DrawCharacter(BASEVIDWIDTH - currentMenu->x - 10 - V_StringWidth(cv_soundtest.string, 0) - (skullAnimCounter/5), currentMenu->y + y, + '\x1C' | V_YELLOWMAP, false); + V_DrawCharacter(BASEVIDWIDTH - currentMenu->x + 2 + (skullAnimCounter/5), currentMenu->y + y, + '\x1D' | V_YELLOWMAP, false); + } if (cv_soundtest.value) V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, currentMenu->y + y + 8, V_YELLOWMAP, S_sfx[cv_soundtest.value].name); } @@ -6719,7 +6778,7 @@ static void M_DrawStatsMaps(int location) boolean dotopname = true, dobottomarrow = (location < statsMax); if (location) - V_DrawString(10, y, V_YELLOWMAP, "\x1A"); + V_DrawString(10, y-(skullAnimCounter/5), V_YELLOWMAP, "\x1A"); while (statsMapList[++i] != -1) { @@ -6796,7 +6855,7 @@ static void M_DrawStatsMaps(int location) } bottomarrow: if (dobottomarrow) - V_DrawString(10, y-8, V_YELLOWMAP, "\x1B"); + V_DrawString(10, y-8 + (skullAnimCounter/5), V_YELLOWMAP, "\x1B"); } static void M_DrawLevelStats(void) @@ -6965,6 +7024,13 @@ void M_DrawTimeAttackMenu(void) // Should see nothing but strings V_DrawString(BASEVIDWIDTH - x - soffset - V_StringWidth(cv->string, 0), y, V_YELLOWMAP, cv->string); + if (i == itemOn) + { + V_DrawCharacter(BASEVIDWIDTH - x - soffset - 10 - V_StringWidth(cv->string, 0) - (skullAnimCounter/5), y, + '\x1C' | V_YELLOWMAP, false); + V_DrawCharacter(BASEVIDWIDTH - x - soffset + 2 + (skullAnimCounter/5), y, + '\x1D' | V_YELLOWMAP, false); + } } } @@ -7147,6 +7213,13 @@ void M_DrawNightsAttackMenu(void) // Should see nothing but strings V_DrawString(BASEVIDWIDTH - x - soffset - V_StringWidth(cv->string, 0), y, V_YELLOWMAP, cv->string); + if (i == itemOn) + { + V_DrawCharacter(BASEVIDWIDTH - x - soffset - 10 - V_StringWidth(cv->string, 0) - (skullAnimCounter/5), y, + '\x1C' | V_YELLOWMAP, false); + V_DrawCharacter(BASEVIDWIDTH - x - soffset + 2 + (skullAnimCounter/5), y, + '\x1D' | V_YELLOWMAP, false); + } } } @@ -7936,13 +8009,18 @@ static void M_DrawServerMenu(void) if (cv_nextmap.value) { +#ifndef NONET +#define imgheight MP_ServerMenu[mp_server_levelgt].alphaKey +#else +#define imgheight 100 +#endif patch_t *PictureOfLevel; lumpnum_t lumpnum; char headerstr[40]; sprintf(headerstr, "%s - %s", cv_newgametype.string, cv_nextmap.string); - M_DrawLevelPlatterHeader(currentMenu->y + MP_ServerMenu[mp_server_levelgt].alphaKey - 10 - lsheadingheight/2, (const char *)headerstr, true, false); + M_DrawLevelPlatterHeader(currentMenu->y + imgheight - 10 - lsheadingheight/2, (const char *)headerstr, true, false); // A 160x100 image of the level as entry MAPxxP lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(cv_nextmap.value))); @@ -7952,7 +8030,7 @@ static void M_DrawServerMenu(void) else PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE); - V_DrawSmallScaledPatch(319 - (currentMenu->x + (SHORT(PictureOfLevel->width)/2)), currentMenu->y + MP_ServerMenu[mp_server_levelgt].alphaKey, 0, PictureOfLevel); + V_DrawSmallScaledPatch(319 - (currentMenu->x + (SHORT(PictureOfLevel->width)/2)), currentMenu->y + imgheight, 0, PictureOfLevel); } } @@ -8017,10 +8095,10 @@ static void M_ServerOptions(INT32 choice) { OP_ServerOptionsMenu[ 1].status = IT_GRAYEDOUT; // Server name OP_ServerOptionsMenu[ 2].status = IT_GRAYEDOUT; // Max players - OP_ServerOptionsMenu[ 3].status = IT_GRAYEDOUT; // Allow WAD downloading + OP_ServerOptionsMenu[ 3].status = IT_GRAYEDOUT; // Allow add-on downloading OP_ServerOptionsMenu[ 4].status = IT_GRAYEDOUT; // Allow players to join - OP_ServerOptionsMenu[30].status = IT_GRAYEDOUT; // Master server - OP_ServerOptionsMenu[31].status = IT_GRAYEDOUT; // Attempts to resynchronise + OP_ServerOptionsMenu[34].status = IT_GRAYEDOUT; // Master server + OP_ServerOptionsMenu[35].status = IT_GRAYEDOUT; // Attempts to resynchronise } else { @@ -8028,11 +8106,10 @@ static void M_ServerOptions(INT32 choice) OP_ServerOptionsMenu[ 2].status = IT_STRING | IT_CVAR; OP_ServerOptionsMenu[ 3].status = IT_STRING | IT_CVAR; OP_ServerOptionsMenu[ 4].status = IT_STRING | IT_CVAR; - if (netgame) - OP_ServerOptionsMenu[30].status = IT_GRAYEDOUT; - else - OP_ServerOptionsMenu[30].status = IT_STRING | IT_CVAR | IT_CV_STRING; - OP_ServerOptionsMenu[31].status = IT_STRING | IT_CVAR; + OP_ServerOptionsMenu[34].status = (netgame + ? IT_GRAYEDOUT + : (IT_STRING | IT_CVAR | IT_CV_STRING)); + OP_ServerOptionsMenu[35].status = IT_STRING | IT_CVAR; } #endif @@ -8057,30 +8134,40 @@ static void M_StartServerMenu(INT32 choice) static char setupm_ip[16]; -// Connect using IP address Tails 11-19-2002 -static void M_ConnectIPMenu(INT32 choice) -{ - (void)choice; - // modified game check: no longer handled - // we don't request a restart unless the filelist differs - - M_SetupNextMenu(&MP_ConnectIPDef); -} - // Draw the funky Connect IP menu. Tails 11-19-2002 // So much work for such a little thing! -static void M_DrawConnectIPMenu(void) +static void M_DrawMPMainMenu(void) { + INT32 x = currentMenu->x; + INT32 y = currentMenu->y; + // use generic drawer for cursor, items and title M_DrawGenericMenu(); +#if MAXPLAYERS == 32 + V_DrawRightAlignedString(BASEVIDWIDTH-x, y+12, + ((itemOn == 1) ? V_YELLOWMAP : 0), "(2-32 players)"); +#else +Update the maxplayers label... +#endif + + V_DrawRightAlignedString(BASEVIDWIDTH-x, y+22, + ((itemOn == 2) ? V_YELLOWMAP : 0), "(2 players)"); + + V_DrawRightAlignedString(BASEVIDWIDTH-x, y+116, + ((itemOn == 8) ? V_YELLOWMAP : 0), "(splitscreen)"); + + y += 62; + + V_DrawFill(x+5, y+4+5, /*16*8 + 6,*/ BASEVIDWIDTH - 2*(x+5), 8+6, 159); + // draw name string - V_DrawString(128,40, V_MONOSPACE, setupm_ip); + V_DrawString(x+8,y+12, V_MONOSPACE, setupm_ip); // draw text cursor for name - if (itemOn == 0 && - skullAnimCounter < 4) //blink cursor - V_DrawCharacter(128+V_StringWidth(setupm_ip, V_MONOSPACE),40,'_',false); + if (itemOn == 5 //0 + && skullAnimCounter < 4) //blink cursor + V_DrawCharacter(x+8+V_StringWidth(setupm_ip, V_MONOSPACE),y+12,'_',false); } // Tails 11-19-2002 @@ -8101,11 +8188,21 @@ static void M_ConnectIP(INT32 choice) // Tails 11-19-2002 static void M_HandleConnectIP(INT32 choice) { - size_t l; - boolean exitmenu = false; // exit to previous menu and send name change + size_t l; + boolean exitmenu = false; // exit to previous menu and send name change switch (choice) { + case KEY_DOWNARROW: + M_NextOpt(); + S_StartSound(NULL,sfx_menu1); // Tails + break; + + case KEY_UPARROW: + M_PrevOpt(); + S_StartSound(NULL,sfx_menu1); // Tails + break; + case KEY_ENTER: S_StartSound(NULL,sfx_menu1); // Tails M_ClearMenus(true); @@ -8117,29 +8214,41 @@ static void M_HandleConnectIP(INT32 choice) break; case KEY_BACKSPACE: - if ((l = strlen(setupm_ip))!=0 && itemOn == 0) + if ((l = strlen(setupm_ip)) != 0) { S_StartSound(NULL,sfx_menu1); // Tails - setupm_ip[l-1] =0; + setupm_ip[l-1] = 0; + } + break; + + case KEY_DEL: + if (setupm_ip[0]) + { + S_StartSound(NULL,sfx_menu1); // Tails + setupm_ip[0] = 0; } break; default: l = strlen(setupm_ip); - if (l < 16-1 && (choice == 46 || (choice >= 48 && choice <= 57))) // Rudimentary number and period enforcing + if (l >= 16-1) + break; + + if (choice == 46 || (choice >= 48 && choice <= 57)) // Rudimentary number and period enforcing { S_StartSound(NULL,sfx_menu1); // Tails - setupm_ip[l] =(char)choice; - setupm_ip[l+1] =0; + setupm_ip[l] = (char)choice; + setupm_ip[l+1] = 0; } - else if (l < 16-1 && choice >= 199 && choice <= 211 && choice != 202 && choice != 206) //numpad too! + else if (choice >= 199 && choice <= 211 && choice != 202 && choice != 206) //numpad too! { XBOXSTATIC char keypad_translation[] = {'7','8','9','-','4','5','6','+','1','2','3','0','.'}; choice = keypad_translation[choice - 199]; S_StartSound(NULL,sfx_menu1); // Tails - setupm_ip[l] =(char)choice; - setupm_ip[l+1] =0; + setupm_ip[l] = (char)choice; + setupm_ip[l+1] = 0; } + break; } @@ -8158,11 +8267,9 @@ static void M_HandleConnectIP(INT32 choice) // ======================== // Tails 03-02-2002 -#define PLBOXW 8 -#define PLBOXH 9 - static UINT8 multi_tics; static UINT8 multi_frame; +static UINT8 multi_spr2; // this is set before entering the MultiPlayer setup menu, // for either player 1 or 2 @@ -8171,38 +8278,62 @@ static player_t *setupm_player; static consvar_t *setupm_cvskin; static consvar_t *setupm_cvcolor; static consvar_t *setupm_cvname; +static consvar_t *setupm_cvdefaultskin; +static consvar_t *setupm_cvdefaultcolor; +static consvar_t *setupm_cvdefaultname; static INT32 setupm_fakeskin; static INT32 setupm_fakecolor; static void M_DrawSetupMultiPlayerMenu(void) { - INT32 mx, my, flags = 0; + INT32 x, y, cursory = 0, flags = 0; spritedef_t *sprdef; spriteframe_t *sprframe; patch_t *patch; + UINT8 *colormap; - mx = MP_PlayerSetupDef.x; - my = MP_PlayerSetupDef.y; + x = MP_PlayerSetupDef.x; + y = MP_PlayerSetupDef.y; // use generic drawer for cursor, items and title - M_DrawGenericMenu(); + //M_DrawGenericMenu(); + + // draw title (or big pic) + M_DrawMenuTitle(); + + M_DrawLevelPlatterHeader(y - (lsheadingheight - 12), "Name", true, false); + if (itemOn == 0) + cursory = y; + y += 11; // draw name string - M_DrawTextBox(mx + 90, my - 8, MAXPLAYERNAME, 1); - V_DrawString(mx + 98, my, V_ALLOWLOWERCASE, setupm_name); + V_DrawFill(x, y, 282/*(MAXPLAYERNAME+1)*8+6*/, 14, 159); + V_DrawString(x + 8, y + 3, V_ALLOWLOWERCASE, setupm_name); + if (skullAnimCounter < 4 && itemOn == 0) + V_DrawCharacter(x + 8 + V_StringWidth(setupm_name, V_ALLOWLOWERCASE), y + 3, + '_' | 0x80, false); + + y += 20; + + M_DrawLevelPlatterHeader(y - (lsheadingheight - 12), "Character", true, false); + if (itemOn == 1) + cursory = y; // draw skin string - V_DrawString(mx + 90, my + 96, - ((MP_PlayerSetupMenu[2].status & IT_TYPE) == IT_SPACE ? V_TRANSLUCENT : 0)|V_YELLOWMAP|V_ALLOWLOWERCASE, + V_DrawRightAlignedString(BASEVIDWIDTH - x, y, + ((MP_PlayerSetupMenu[2].status & IT_TYPE) == IT_SPACE ? V_TRANSLUCENT : 0)|(itemOn == 1 ? V_YELLOWMAP : 0)|V_ALLOWLOWERCASE, skins[setupm_fakeskin].realname); - // draw the name of the color you have chosen - // Just so people don't go thinking that "Default" is Green. - V_DrawString(208, 72, V_YELLOWMAP|V_ALLOWLOWERCASE, Color_Names[setupm_fakecolor]); + if (itemOn == 1 && (MP_PlayerSetupMenu[2].status & IT_TYPE) != IT_SPACE) + { + V_DrawCharacter(BASEVIDWIDTH - x - 10 - V_StringWidth(skins[setupm_fakeskin].realname, V_ALLOWLOWERCASE) - (skullAnimCounter/5), y, + '\x1C' | V_YELLOWMAP, false); + V_DrawCharacter(BASEVIDWIDTH - x + 2 + (skullAnimCounter/5), y, + '\x1D' | V_YELLOWMAP, false); + } - // draw text cursor for name - if (!itemOn && skullAnimCounter < 4) // blink cursor - V_DrawCharacter(mx + 98 + V_StringWidth(setupm_name, 0), my, '_',false); + x = BASEVIDWIDTH/2; + y += 11; // anim the player in the box if (--multi_tics <= 0) @@ -8211,14 +8342,18 @@ static void M_DrawSetupMultiPlayerMenu(void) multi_tics = 4; } - // skin 0 is default player sprite - if (R_SkinAvailable(skins[setupm_fakeskin].name) != -1) - sprdef = &skins[R_SkinAvailable(skins[setupm_fakeskin].name)].sprites[SPR2_WALK]; - else - sprdef = &skins[0].sprites[SPR2_WALK]; +#define charw 74 - if (!sprdef->numframes) // No frames ?? - return; // Can't render! + // draw box around character + V_DrawFill(x-(charw/2), y, charw, 84, 159); + + sprdef = &skins[setupm_fakeskin].sprites[multi_spr2]; + + if (!setupm_fakecolor || !sprdef->numframes) // should never happen but hey, who knows + goto faildraw; + + // ok, draw player sprite for sure now + colormap = R_GetTranslationColormap(setupm_fakeskin, setupm_fakecolor, 0); if (multi_frame >= sprdef->numframes) multi_frame = 0; @@ -8228,38 +8363,96 @@ static void M_DrawSetupMultiPlayerMenu(void) if (sprframe->flip & 1) // Only for first sprite flags |= V_FLIP; // This sprite is left/right flipped! - // draw box around guy - M_DrawTextBox(mx + 90, my + 8, PLBOXW, PLBOXH); +#define chary (y+64) - // draw player sprite - if (!setupm_fakecolor) // should never happen but hey, who knows + V_DrawFixedPatch( + x<numframes) // No frames ?? + return; // Can't render! + + sprframe = &sprdef->spriteframes[0]; + patch = W_CachePatchNum(sprframe->lumppat[0], PU_CACHE); + if (sprframe->flip & 1) // Only for first sprite + flags |= V_FLIP; // This sprite is left/right flipped! + + V_DrawScaledPatch(x, chary, flags, patch); + +#undef chary + +colordraw: + x = MP_PlayerSetupDef.x; + y += 75; + + M_DrawLevelPlatterHeader(y - (lsheadingheight - 12), "Color", true, false); + if (itemOn == 2) + cursory = y; + + // draw color string + V_DrawRightAlignedString(BASEVIDWIDTH - x, y, + (itemOn == 2 ? V_YELLOWMAP : 0)|V_ALLOWLOWERCASE, + Color_Names[setupm_fakecolor]); + + if (itemOn == 2 && (MP_PlayerSetupMenu[2].status & IT_TYPE) != IT_SPACE) { - if (skins[setupm_fakeskin].flags & SF_HIRES) - { - V_DrawSciencePatch((mx+98+(PLBOXW*8/2))<= MAXSKINCOLORS) + col -= MAXSKINCOLORS-1; + x += w; } - else - V_DrawMappedPatch(mx + 98 + (PLBOXW*8/2), my + 16 + (PLBOXH*8) - 12, flags, patch, colormap); - - Z_Free(colormap); } +#undef charw +#undef indexwidth + + x = MP_PlayerSetupDef.x; + y += 20; + + V_DrawString(x, y, + ((R_SkinAvailable(setupm_cvdefaultskin->string) != setupm_fakeskin + || setupm_cvdefaultcolor->value != setupm_fakecolor + || strcmp(setupm_name, setupm_cvdefaultname->string)) + ? 0 + : V_TRANSLUCENT) + | ((itemOn == 3) ? V_YELLOWMAP : 0), + "Save as default"); + if (itemOn == 3) + cursory = y; + + V_DrawScaledPatch(x - 17, cursory, 0, + W_CachePatchName("M_CURSOR", PU_CACHE)); } // Handle 1P/2P MP Setup @@ -8282,7 +8475,7 @@ static void M_HandleSetupMultiPlayer(INT32 choice) break; case KEY_LEFTARROW: - if (itemOn == 2) //player skin + if (itemOn == 1) //player skin { S_StartSound(NULL,sfx_menu1); // Tails prev_setupm_fakeskin = setupm_fakeskin; @@ -8293,16 +8486,30 @@ static void M_HandleSetupMultiPlayer(INT32 choice) setupm_fakeskin = numskins-1; } while ((prev_setupm_fakeskin != setupm_fakeskin) && !(R_SkinUsable(-1, setupm_fakeskin))); + multi_spr2 = P_GetSkinSprite2(&skins[setupm_fakeskin], SPR2_WALK, NULL); } - else if (itemOn == 1) // player color + else if (itemOn == 2) // player color { S_StartSound(NULL,sfx_menu1); // Tails setupm_fakecolor--; } break; + case KEY_ENTER: + if (itemOn == 3 + && (R_SkinAvailable(setupm_cvdefaultskin->string) != setupm_fakeskin + || setupm_cvdefaultcolor->value != setupm_fakecolor + || strcmp(setupm_name, setupm_cvdefaultname->string))) + { + S_StartSound(NULL,sfx_strpst); + // you know what? always putting these in the buffer won't hurt anything. + COM_BufAddText (va("%s \"%s\"\n",setupm_cvdefaultskin->name,skins[setupm_fakeskin].name)); + COM_BufAddText (va("%s %d\n",setupm_cvdefaultcolor->name,setupm_fakecolor)); + COM_BufAddText (va("%s %s\n",setupm_cvdefaultname->name,setupm_name)); + break; + } case KEY_RIGHTARROW: - if (itemOn == 2) //player skin + if (itemOn == 1) //player skin { S_StartSound(NULL,sfx_menu1); // Tails prev_setupm_fakeskin = setupm_fakeskin; @@ -8313,8 +8520,9 @@ static void M_HandleSetupMultiPlayer(INT32 choice) setupm_fakeskin = 0; } while ((prev_setupm_fakeskin != setupm_fakeskin) && !(R_SkinUsable(-1, setupm_fakeskin))); + multi_spr2 = P_GetSkinSprite2(&skins[setupm_fakeskin], SPR2_WALK, NULL); } - else if (itemOn == 1) // player color + else if (itemOn == 2) // player color { S_StartSound(NULL,sfx_menu1); // Tails setupm_fakecolor++; @@ -8326,22 +8534,30 @@ static void M_HandleSetupMultiPlayer(INT32 choice) break; case KEY_BACKSPACE: - if ((l = strlen(setupm_name))!=0 && itemOn == 0) + if (itemOn == 0 && (l = strlen(setupm_name))!=0) { S_StartSound(NULL,sfx_menu1); // Tails - setupm_name[l-1] =0; + setupm_name[l-1] = 0; + } + break; + + case KEY_DEL: + if (itemOn == 0 && (l = strlen(setupm_name))!=0) + { + S_StartSound(NULL,sfx_menu1); // Tails + setupm_name[0] = 0; } break; default: - if (choice < 32 || choice > 127 || itemOn != 0) + if (itemOn != 0 || choice < 32 || choice > 127) break; + S_StartSound(NULL,sfx_menu1); // Tails l = strlen(setupm_name); if (l < MAXPLAYERNAME-1) { - S_StartSound(NULL,sfx_menu1); // Tails - setupm_name[l] =(char)choice; - setupm_name[l+1] =0; + setupm_name[l] = (char)choice; + setupm_name[l+1] = 0; } break; } @@ -8375,6 +8591,9 @@ static void M_SetupMultiPlayer(INT32 choice) setupm_cvskin = &cv_skin; setupm_cvcolor = &cv_playercolor; setupm_cvname = &cv_playername; + setupm_cvdefaultskin = &cv_defaultskin; + setupm_cvdefaultcolor = &cv_defaultplayercolor; + setupm_cvdefaultname = &cv_defaultplayername; // For whatever reason this doesn't work right if you just use ->value setupm_fakeskin = R_SkinAvailable(setupm_cvskin->string); @@ -8384,9 +8603,11 @@ static void M_SetupMultiPlayer(INT32 choice) // disable skin changes if we can't actually change skins if (!CanChangeSkin(consoleplayer)) - MP_PlayerSetupMenu[2].status = (IT_GRAYEDOUT); + MP_PlayerSetupMenu[1].status = (IT_GRAYEDOUT); else - MP_PlayerSetupMenu[2].status = (IT_KEYHANDLER|IT_STRING); + MP_PlayerSetupMenu[1].status = (IT_KEYHANDLER|IT_STRING); + + multi_spr2 = P_GetSkinSprite2(&skins[setupm_fakeskin], SPR2_WALK, NULL); MP_PlayerSetupDef.prevMenu = currentMenu; M_SetupNextMenu(&MP_PlayerSetupDef); @@ -8406,6 +8627,9 @@ static void M_SetupMultiPlayer2(INT32 choice) setupm_cvskin = &cv_skin2; setupm_cvcolor = &cv_playercolor2; setupm_cvname = &cv_playername2; + setupm_cvdefaultskin = &cv_defaultskin2; + setupm_cvdefaultcolor = &cv_defaultplayercolor2; + setupm_cvdefaultname = &cv_defaultplayername2; // For whatever reason this doesn't work right if you just use ->value setupm_fakeskin = R_SkinAvailable(setupm_cvskin->string); @@ -8415,9 +8639,11 @@ static void M_SetupMultiPlayer2(INT32 choice) // disable skin changes if we can't actually change skins if (splitscreen && !CanChangeSkin(secondarydisplayplayer)) - MP_PlayerSetupMenu[2].status = (IT_GRAYEDOUT); + MP_PlayerSetupMenu[1].status = (IT_GRAYEDOUT); else - MP_PlayerSetupMenu[2].status = (IT_KEYHANDLER | IT_STRING); + MP_PlayerSetupMenu[1].status = (IT_KEYHANDLER | IT_STRING); + + multi_spr2 = P_GetSkinSprite2(&skins[setupm_fakeskin], SPR2_WALK, NULL); MP_PlayerSetupDef.prevMenu = currentMenu; M_SetupNextMenu(&MP_PlayerSetupDef); @@ -8683,9 +8909,9 @@ static void M_DrawControl(void) "PRESS ENTER TO CHANGE, BACKSPACE TO CLEAR")); if (i) - V_DrawString(currentMenu->x - 16, y, V_YELLOWMAP, "\x1A"); // up arrow + V_DrawString(currentMenu->x - 16, y-(skullAnimCounter/5), V_YELLOWMAP, "\x1A"); // up arrow if (max != currentMenu->numitems) - V_DrawString(currentMenu->x - 16, y+(SMALLLINEHEIGHT*(controlheight-1)), V_YELLOWMAP, "\x1B"); // down arrow + V_DrawString(currentMenu->x - 16, y+(SMALLLINEHEIGHT*(controlheight-1))+(skullAnimCounter/5), V_YELLOWMAP, "\x1B"); // down arrow for (; i < max; i++) { @@ -8838,6 +9064,7 @@ void M_DrawSoundMenu(void) { const char* onstring = "ON"; const char* offstring = "OFF"; + INT32 lengthstring; M_DrawGenericMenu(); V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, @@ -8854,6 +9081,20 @@ void M_DrawSoundMenu(void) currentMenu->y+currentMenu->menuitems[4].alphaKey, (nomidimusic ? V_REDMAP : V_YELLOWMAP), ((nomidimusic || music_disabled) ? offstring : onstring)); + + if (itemOn == 0) + lengthstring = ((nosound || sound_disabled) ? 3 : 2); + else if (itemOn == 2) + lengthstring = ((nodigimusic || digital_disabled) ? 3 : 2); + else if (itemOn == 4) + lengthstring = ((nomidimusic || music_disabled) ? 3 : 2); + else + return; + + V_DrawCharacter(BASEVIDWIDTH - currentMenu->x - 10 - (lengthstring*8) - (skullAnimCounter/5), currentMenu->y+currentMenu->menuitems[itemOn].alphaKey, + '\x1C' | V_YELLOWMAP, false); + V_DrawCharacter(BASEVIDWIDTH - currentMenu->x + 2 + (skullAnimCounter/5), currentMenu->y+currentMenu->menuitems[itemOn].alphaKey, + '\x1D' | V_YELLOWMAP, false); } // Toggles sound systems in-game. @@ -9227,9 +9468,9 @@ static void M_DrawColorMenu(void) } if (i) - V_DrawString(currentMenu->x - 20, currentMenu->y, V_YELLOWMAP, "\x1A"); // up arrow + V_DrawString(currentMenu->x - 20, currentMenu->y - (skullAnimCounter/5), V_YELLOWMAP, "\x1A"); // up arrow if (max != currentMenu->numitems) - V_DrawString(currentMenu->x - 20, currentMenu->y + 2*scrollareaheight, V_YELLOWMAP, "\x1B"); // down arrow + V_DrawString(currentMenu->x - 20, currentMenu->y + 2*scrollareaheight + (skullAnimCounter/5), V_YELLOWMAP, "\x1B"); // down arrow // draw title (or big pic) M_DrawMenuTitle(); @@ -9267,7 +9508,7 @@ static void M_DrawColorMenu(void) switch (currentMenu->menuitems[i].status & IT_CVARTYPE) { case IT_CV_SLIDER: - M_DrawSlider(x, y, cv); + M_DrawSlider(x, y, cv, (i == itemOn)); case IT_CV_NOPRINT: // color use this case IT_CV_INVISSLIDER: // monitor toggles use this break; @@ -9284,6 +9525,13 @@ static void M_DrawColorMenu(void) default: V_DrawRightAlignedString(BASEVIDWIDTH - x, y, ((cv->flags & CV_CHEAT) && !CV_IsSetToDefault(cv) ? V_REDMAP : V_YELLOWMAP), cv->string); + if (i == itemOn) + { + V_DrawCharacter(BASEVIDWIDTH - x - 10 - V_StringWidth(cv->string, 0) - (skullAnimCounter/5), y, + '\x1C' | V_YELLOWMAP, false); + V_DrawCharacter(BASEVIDWIDTH - x + 2 + (skullAnimCounter/5), y, + '\x1D' | V_YELLOWMAP, false); + } break; } break; @@ -9426,7 +9674,7 @@ static void M_DrawMonitorToggles(void) continue; y = currentMenu->y + currentMenu->menuitems[i].alphaKey; - M_DrawSlider(currentMenu->x + 20, y, cv); + M_DrawSlider(currentMenu->x + 20, y, cv, (i == itemOn)); if (!cv->value) V_DrawRightAlignedString(312, y, V_OLDSPACING|((i == itemOn) ? V_YELLOWMAP : 0), "None"); diff --git a/src/p_enemy.c b/src/p_enemy.c index 7f080b43e..0cf86b1ec 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -832,6 +832,34 @@ static mobjtype_t P_DoRandomBoxChances(void) mobjtype_t spawnchance[256]; INT32 numchoices = 0, i = 0; + if (!(netgame || multiplayer)) + { + switch (P_RandomKey(10)) + { + case 0: + return MT_RING_ICON; + case 1: + return MT_SNEAKERS_ICON; + case 2: + return MT_INVULN_ICON; + case 3: + return MT_WHIRLWIND_ICON; + case 4: + return MT_ELEMENTAL_ICON; + case 5: + return MT_ATTRACT_ICON; + case 6: + return MT_FORCE_ICON; + case 7: + return MT_ARMAGEDDON_ICON; + case 8: + return MT_1UP_ICON; + case 9: + return MT_EGGMAN_ICON; + } + return MT_NULL; + } + #define QUESTIONBOXCHANCES(type, cvar) \ for (i = cvar.value; i; --i) spawnchance[numchoices++] = type QUESTIONBOXCHANCES(MT_RING_ICON, cv_superring); @@ -2826,8 +2854,8 @@ void A_BossDeath(mobj_t *mo) // make sure there is a player alive for victory for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && ((players[i].mo && players[i].mo->health > 0) - || ((netgame || multiplayer) && (players[i].lives > 0 || players[i].continues > 0)))) + if (playeringame[i] && ((players[i].mo && players[i].mo->health) + || ((netgame || multiplayer) && (players[i].lives || players[i].continues)))) break; if (i == MAXPLAYERS) @@ -3215,10 +3243,12 @@ void A_ExtraLife(mobj_t *actor) // In shooter gametypes, give the player 100 rings instead of an extra life. if (gametype != GT_COOP && gametype != GT_COMPETITION) + { P_GivePlayerRings(player, 100); + P_PlayLivesJingle(player); + } else - P_GivePlayerLives(player, 1); - P_PlayLivesJingle(player); + P_GiveCoopLives(player, 1, true); } // Function: A_GiveShield @@ -3931,12 +3961,12 @@ void A_SignPlayer(mobj_t *actor) of in the name. If you have a better idea, feel free to let me know. ~toast 2016/07/20 */ - actor->frame += Color_Opposite[Color_Opposite[skin->prefoppositecolor*2]*2+1]; + actor->frame += (15 - Color_Opposite[(Color_Opposite[(skin->prefoppositecolor - 1)*2] - 1)*2 + 1]); } - else // Set the sign to be an appropriate background color for this player's skincolor. + else if (actor->target->player->skincolor) // Set the sign to be an appropriate background color for this player's skincolor. { - actor->color = Color_Opposite[actor->target->player->skincolor*2]; - actor->frame += Color_Opposite[actor->target->player->skincolor*2+1]; + actor->color = Color_Opposite[(actor->target->player->skincolor - 1)*2]; + actor->frame += (15 - Color_Opposite[(actor->target->player->skincolor - 1)*2 + 1]); } if (skin->sprites[SPR2_SIGN].numframes) @@ -5254,7 +5284,10 @@ void A_MixUp(mobj_t *actor) } if (numplayers <= 1) // Not enough players to mix up. + { + S_StartSound(actor, sfx_lose); return; + } else if (numplayers == 2) // Special case -- simple swap { fixed_t x, y, z; @@ -5500,7 +5533,10 @@ void A_RecyclePowers(mobj_t *actor) #endif if (!multiplayer) + { + S_StartSound(actor, sfx_lose); return; + } numplayers = 0; @@ -5536,7 +5572,10 @@ void A_RecyclePowers(mobj_t *actor) } if (numplayers <= 1) + { + S_StartSound(actor, sfx_lose); return; //nobody to touch! + } //shuffle the post scramble list, whee! // hardcoded 0-1 to 1-0 for two players @@ -9016,8 +9055,8 @@ void A_ForceWin(mobj_t *actor) for (i = 0; i < MAXPLAYERS; i++) { - if (playeringame[i] && ((players[i].mo && players[i].mo->health > 0) - || ((netgame || multiplayer) && (players[i].lives > 0 || players[i].continues > 0)))) + if (playeringame[i] && ((players[i].mo && players[i].mo->health) + || ((netgame || multiplayer) && (players[i].lives || players[i].continues)))) break; } diff --git a/src/p_inter.c b/src/p_inter.c index 07165d2cc..d2101ca57 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1293,13 +1293,40 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) if (player->starpostnum >= special->health) return; // Already hit this post - // Save the player's time and position. - player->starposttime = leveltime; - player->starpostx = toucher->x>>FRACBITS; - player->starposty = toucher->y>>FRACBITS; - player->starpostz = special->z>>FRACBITS; - player->starpostangle = special->angle; - player->starpostnum = special->health; + if (cv_coopstarposts.value && gametype == GT_COOP && (netgame || multiplayer)) + { + for (i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i]) + { + if (players[i].bot) // ignore dumb, stupid tails + continue; + + players[i].starposttime = leveltime; + players[i].starpostx = player->mo->x>>FRACBITS; + players[i].starposty = player->mo->y>>FRACBITS; + players[i].starpostz = special->z>>FRACBITS; + players[i].starpostangle = special->angle; + players[i].starpostnum = special->health; + + if (cv_coopstarposts.value == 2 && (players[i].playerstate == PST_DEAD || players[i].spectator) && P_GetLives(&players[i])) + P_SpectatorJoinGame(&players[i]); //players[i].playerstate = PST_REBORN; + } + } + S_StartSound(NULL, special->info->painsound); + } + else + { + // Save the player's time and position. + player->starposttime = leveltime; + player->starpostx = toucher->x>>FRACBITS; + player->starposty = toucher->y>>FRACBITS; + player->starpostz = special->z>>FRACBITS; + player->starpostangle = special->angle; + player->starpostnum = special->health; + S_StartSound(toucher, special->info->painsound); + } + P_ClearStarPost(special->health); // Find all starposts in the level with this value. @@ -2230,14 +2257,34 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget target->flags |= MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY; P_SetThingPosition(target); - if (!target->player->bot && !G_IsSpecialStage(gamemap) + if ((target->player->lives <= 1) && (netgame || multiplayer) && (gametype == GT_COOP) && (cv_cooplives.value == 0)) + ; + else if (!target->player->bot && !target->player->spectator && !G_IsSpecialStage(gamemap) && G_GametypeUsesLives()) { target->player->lives -= 1; // Lose a life Tails 03-11-2000 if (target->player->lives <= 0) // Tails 03-14-2000 { - if (P_IsLocalPlayer(target->player)/* && target->player == &players[consoleplayer] */) + boolean gameovermus = false; + if ((netgame || multiplayer) && (gametype == GT_COOP) && (cv_cooplives.value != 1)) + { + INT32 i; + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; + + if (players[i].lives > 0) + break; + } + if (i == MAXPLAYERS) + gameovermus = true; + } + else if (P_IsLocalPlayer(target->player)) + gameovermus = true; + + if (gameovermus) { S_StopMusic(); // Stop the Music! Tails 03-14-2000 S_ChangeMusicInternal("_gover", false); // Yousa dead now, Okieday? Tails 03-14-2000 diff --git a/src/p_local.h b/src/p_local.h index a2831222a..b1bfc6456 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -148,6 +148,7 @@ void P_SwitchShield(player_t *player, UINT16 shieldtype); mobj_t *P_SpawnGhostMobj(mobj_t *mobj); void P_GivePlayerRings(player_t *player, INT32 num_rings); void P_GivePlayerLives(player_t *player, INT32 numlives); +void P_GiveCoopLives(player_t *player, INT32 numlives, boolean sound); UINT8 P_GetNextEmerald(void); void P_GiveEmerald(boolean spawnObj); #if 0 @@ -198,6 +199,9 @@ void P_PlayLivesJingle(player_t *player); #define P_PlayDeathSound(s) S_StartSound(s, sfx_altdi1 + P_RandomKey(4)); #define P_PlayVictorySound(s) S_StartSound(s, sfx_victr1 + P_RandomKey(4)); +boolean P_GetLives(player_t *player); +boolean P_SpectatorJoinGame(player_t *player); +void P_RestoreMultiMusic(player_t *player); // // P_MOBJ @@ -224,7 +228,6 @@ void P_PrecipitationEffects(void); void P_RemoveMobj(mobj_t *th); boolean P_MobjWasRemoved(mobj_t *th); void P_RemoveSavegameMobj(mobj_t *th); -UINT8 P_GetMobjSprite2(mobj_t *mobj, UINT8 spr2); boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state); boolean P_SetMobjState(mobj_t *mobj, statenum_t state); void P_RunShields(void); diff --git a/src/p_mobj.c b/src/p_mobj.c index f9d31eb31..8f9c44fdb 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -86,7 +86,7 @@ void P_AddCachedAction(mobj_t *mobj, INT32 statenum) // FUNCINLINE static ATTRINLINE void P_SetupStateAnimation(mobj_t *mobj, state_t *st) { - INT32 animlength = (mobj->skin && mobj->sprite == SPR_PLAY) + INT32 animlength = (mobj->sprite == SPR_PLAY && mobj->skin) ? (INT32)(((skin_t *)mobj->skin)->sprites[mobj->sprite2].numframes) - 1 : st->var1; @@ -185,195 +185,6 @@ static void P_CyclePlayerMobjState(mobj_t *mobj) } } -// -// P_GetMobjSprite2 -// For non-super players, tries each sprite2's immediate predecessor until it finds one with a number of frames or ends up at standing. -// For super players, does the same as above - but tries the super equivalent for each sprite2 before the non-super version. -// - -UINT8 P_GetMobjSprite2(mobj_t *mobj, UINT8 spr2) -{ - player_t *player = mobj->player; - skin_t *skin = ((skin_t *)mobj->skin); - UINT8 super = (spr2 & FF_SPR2SUPER); - - if (!skin) - return 0; - - while (!(skin->sprites[spr2].numframes) - && spr2 != SPR2_STND) - { - if (spr2 & FF_SPR2SUPER) - { - spr2 &= ~FF_SPR2SUPER; - continue; - } - - switch(spr2) - { - case SPR2_RUN: - spr2 = SPR2_WALK; - break; - case SPR2_STUN: - spr2 = SPR2_PAIN; - break; - case SPR2_DRWN: - spr2 = SPR2_DEAD; - break; - case SPR2_SPIN: - spr2 = SPR2_ROLL; - break; - case SPR2_GASP: - spr2 = SPR2_SPNG; - break; - case SPR2_JUMP: - spr2 = ((player - ? player->charflags - : skin->flags) - & SF_NOJUMPSPIN) ? SPR2_SPNG : SPR2_ROLL; - break; - case SPR2_SPNG: // spring - spr2 = SPR2_FALL; - break; - case SPR2_FALL: - spr2 = SPR2_WALK; - break; - case SPR2_RIDE: - spr2 = SPR2_FALL; - break; - - case SPR2_FLY : - spr2 = SPR2_SPNG; - break; - case SPR2_SWIM: - spr2 = SPR2_FLY ; - break; - case SPR2_TIRE: - spr2 = (player && player->charability == CA_SWIM) ? SPR2_SWIM : SPR2_FLY; - break; - - case SPR2_GLID: - spr2 = SPR2_FLY; - break; - case SPR2_CLMB: - spr2 = SPR2_ROLL; - break; - case SPR2_CLNG: - spr2 = SPR2_CLMB; - break; - - case SPR2_FLT : - spr2 = SPR2_WALK; - break; - case SPR2_FRUN: - spr2 = SPR2_RUN ; - break; - - case SPR2_DASH: - spr2 = SPR2_FRUN; - break; - - case SPR2_BNCE: - spr2 = SPR2_FALL; - break; - case SPR2_BLND: - spr2 = SPR2_ROLL; - break; - - case SPR2_TWIN: - spr2 = SPR2_ROLL; - break; - - case SPR2_MLEE: - spr2 = SPR2_TWIN; - break; - - // NiGHTS sprites. - case SPR2_NSTD: - spr2 = SPR2_STND; - super = FF_SPR2SUPER; - break; - case SPR2_NFLT: - spr2 = SPR2_FLT ; - super = FF_SPR2SUPER; - break; - case SPR2_NSTN: - spr2 = SPR2_STUN; - break; - case SPR2_NPUL: - spr2 = SPR2_NSTN; - break; - case SPR2_NATK: - spr2 = SPR2_ROLL; - super = FF_SPR2SUPER; - break; - /*case SPR2_NGT0: - spr2 = SPR2_NFLT; - break;*/ - case SPR2_NGT1: - case SPR2_NGT7: - case SPR2_DRL0: - spr2 = SPR2_NGT0; - break; - case SPR2_NGT2: - case SPR2_DRL1: - spr2 = SPR2_NGT1; - break; - case SPR2_NGT3: - case SPR2_DRL2: - spr2 = SPR2_NGT2; - break; - case SPR2_NGT4: - case SPR2_DRL3: - spr2 = SPR2_NGT3; - break; - case SPR2_NGT5: - case SPR2_DRL4: - spr2 = SPR2_NGT4; - break; - case SPR2_NGT6: - case SPR2_DRL5: - spr2 = SPR2_NGT5; - break; - case SPR2_DRL6: - spr2 = SPR2_NGT6; - break; - case SPR2_NGT8: - case SPR2_DRL7: - spr2 = SPR2_NGT7; - break; - case SPR2_NGT9: - case SPR2_DRL8: - spr2 = SPR2_NGT8; - break; - case SPR2_NGTA: - case SPR2_DRL9: - spr2 = SPR2_NGT9; - break; - case SPR2_NGTB: - case SPR2_DRLA: - spr2 = SPR2_NGTA; - break; - case SPR2_NGTC: - case SPR2_DRLB: - spr2 = SPR2_NGTB; - break; - case SPR2_DRLC: - spr2 = SPR2_NGTC; - break; - - // Dunno? Just go to standing then. - default: - spr2 = SPR2_STND; - break; - } - - spr2 |= super; - } - - return spr2; -} - // // P_SetPlayerMobjState // Returns true if the mobj is still present. @@ -574,14 +385,16 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state) { skin_t *skin = ((skin_t *)mobj->skin); UINT16 frame = (mobj->frame & FF_FRAMEMASK)+1; - UINT8 numframes; - - UINT8 spr2 = P_GetMobjSprite2(mobj, (((player->powers[pw_super]) ? FF_SPR2SUPER : 0)|st->frame) & FF_FRAMEMASK); + UINT8 numframes, spr2; if (skin) + { + spr2 = P_GetSkinSprite2(skin, (((player->powers[pw_super]) ? FF_SPR2SUPER : 0)|st->frame) & FF_FRAMEMASK, mobj->player); numframes = skin->sprites[spr2].numframes; + } else { + spr2 = 0; frame = 0; numframes = 0; } @@ -700,14 +513,16 @@ boolean P_SetMobjState(mobj_t *mobj, statenum_t state) { skin_t *skin = ((skin_t *)mobj->skin); UINT16 frame = (mobj->frame & FF_FRAMEMASK)+1; - UINT8 numframes; - - UINT8 spr2 = P_GetMobjSprite2(mobj, st->frame & FF_FRAMEMASK); + UINT8 numframes, spr2; if (skin) + { + spr2 = P_GetSkinSprite2(skin, st->frame & FF_FRAMEMASK, mobj->player); numframes = skin->sprites[spr2].numframes; + } else { + spr2 = 0; frame = 0; numframes = 0; } @@ -3225,8 +3040,17 @@ static void P_PlayerZMovement(mobj_t *mo) } } - if (mo->health && !P_CheckDeathPitCollide(mo)) + if (mo->health && !mo->player->spectator && !P_CheckDeathPitCollide(mo)) { + if ((mo->player->charability2 == CA2_SPINDASH) && !(mo->player->pflags & PF_THOKKED) && (mo->player->cmd.buttons & BT_USE) && (FixedHypot(mo->momx, mo->momy) > (5*mo->scale))) + { + mo->player->pflags |= PF_SPINNING; + P_SetPlayerMobjState(mo, S_PLAY_ROLL); + S_StartSound(mo, sfx_spin); + } + else + mo->player->pflags &= ~PF_SPINNING; + if (mo->player->pflags & PF_GLIDING) // ground gliding { mo->player->skidtime = TICRATE; @@ -3239,7 +3063,7 @@ static void P_PlayerZMovement(mobj_t *mo) S_StartSound(mo, sfx_s3k8b); mo->player->pflags |= PF_FULLSTASIS; } - else if (mo->player->pflags & PF_JUMPED || (mo->player->pflags & (PF_SPINNING|PF_USEDOWN)) != (PF_SPINNING|PF_USEDOWN) + else if (mo->player->pflags & PF_JUMPED || !(mo->player->pflags & PF_SPINNING) || mo->player->powers[pw_tailsfly] || mo->state-states == S_PLAY_FLY_TIRED) { if (mo->player->cmomx || mo->player->cmomy) @@ -3270,15 +3094,6 @@ static void P_PlayerZMovement(mobj_t *mo) } } - if ((mo->player->charability2 == CA2_SPINDASH) && !(mo->player->pflags & PF_THOKKED) && (mo->player->cmd.buttons & BT_USE) && (FixedHypot(mo->momx, mo->momy) > (5*mo->scale))) - { - mo->player->pflags |= PF_SPINNING; - P_SetPlayerMobjState(mo, S_PLAY_ROLL); - S_StartSound(mo, sfx_spin); - } - else - mo->player->pflags &= ~PF_SPINNING; - if (!(mo->player->pflags & PF_GLIDING)) mo->player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE); @@ -9261,40 +9076,44 @@ void P_SpawnPlayer(INT32 playernum) // spawn as spectator determination if (!G_GametypeHasSpectators()) { - // Special case for (NiGHTS) special stages! - // if stage has already started, force players to become spectators until the next stage - if (multiplayer && netgame && G_IsSpecialStage(gamemap) && useNightsSS && leveltime > 0) - p->spectator = true; - else - p->spectator = false; + p->spectator = p->outofcoop = + (((multiplayer || netgame) && gametype == GT_COOP) // only question status in coop + && ((leveltime > 0 + && ((G_IsSpecialStage(gamemap) && useNightsSS) // late join special stage + || (cv_coopstarposts.value == 2 && (p->jointime < 1 || p->outofcoop)))) // late join or die in new coop + || (((cv_cooplives.value == 1) || !P_GetLives(p)) && p->lives <= 0))); // game over and can't redistribute lives } - else if (netgame && p->jointime < 1) - p->spectator = true; - else if (multiplayer && !netgame) + else { - // If you're in a team game and you don't have a team assigned yet... - if (G_GametypeHasTeams() && p->ctfteam == 0) - { - changeteam_union NetPacket; - UINT16 usvalue; - NetPacket.value.l = NetPacket.value.b = 0; - - // Spawn as a spectator, - // yes even in splitscreen mode + p->outofcoop = false; + if (netgame && p->jointime < 1) p->spectator = true; - if (playernum&1) p->skincolor = skincolor_redteam; - else p->skincolor = skincolor_blueteam; + else if (multiplayer && !netgame) + { + // If you're in a team game and you don't have a team assigned yet... + if (G_GametypeHasTeams() && p->ctfteam == 0) + { + changeteam_union NetPacket; + UINT16 usvalue; + NetPacket.value.l = NetPacket.value.b = 0; - // but immediately send a team change packet. - NetPacket.packet.playernum = playernum; - NetPacket.packet.verification = true; - NetPacket.packet.newteam = !(playernum&1) + 1; + // Spawn as a spectator, + // yes even in splitscreen mode + p->spectator = true; + if (playernum&1) p->skincolor = skincolor_redteam; + else p->skincolor = skincolor_blueteam; - usvalue = SHORT(NetPacket.value.l|NetPacket.value.b); - SendNetXCmd(XD_TEAMCHANGE, &usvalue, sizeof(usvalue)); + // but immediately send a team change packet. + NetPacket.packet.playernum = playernum; + NetPacket.packet.verification = true; + NetPacket.packet.newteam = !(playernum&1) + 1; + + usvalue = SHORT(NetPacket.value.l|NetPacket.value.b); + SendNetXCmd(XD_TEAMCHANGE, &usvalue, sizeof(usvalue)); + } + else // Otherwise, never spectator. + p->spectator = false; } - else // Otherwise, never spectator. - p->spectator = false; } if (G_GametypeHasTeams()) @@ -9311,6 +9130,9 @@ void P_SpawnPlayer(INT32 playernum) p->skincolor = skincolor_blueteam; } + if ((netgame || multiplayer) && (gametype != GT_COOP || leveltime) && !p->spectator && !(maptol & TOL_NIGHTS)) + p->powers[pw_flashing] = flashingtics-1; // Babysitting deterrent + mobj = P_SpawnMobj(0, 0, 0, MT_PLAYER); (mobj->player = p)->mo = mobj; @@ -9701,9 +9523,9 @@ void P_SpawnMapThing(mapthing_t *mthing) if (gametype == GT_COMPETITION || gametype == GT_RACE) { // Set powerup boxes to user settings for competition. - if (cv_competitionboxes.value == 1) // Random + if (cv_competitionboxes.value == 1) // Mystery i = MT_MYSTERY_BOX; - else if (cv_competitionboxes.value == 2) // Teleports + else if (cv_competitionboxes.value == 2) // Teleport i = MT_MIXUP_BOX; else if (cv_competitionboxes.value == 3) // None return; // Don't spawn! @@ -9712,12 +9534,12 @@ void P_SpawnMapThing(mapthing_t *mthing) // Set powerup boxes to user settings for other netplay modes else if (gametype != GT_COOP) { - if (cv_matchboxes.value == 1) // Random + if (cv_matchboxes.value == 1) // Mystery i = MT_MYSTERY_BOX; - else if (cv_matchboxes.value == 2) // Non-Random + else if (cv_matchboxes.value == 2) // Unchanging { if (i == MT_MYSTERY_BOX) - return; // don't spawn in Non-Random + return; // don't spawn mthing->options &= ~(MTF_AMBUSH|MTF_OBJECTSPECIAL); // no random respawning! } else if (cv_matchboxes.value == 3) // Don't spawn diff --git a/src/p_setup.c b/src/p_setup.c index b6c8f75ca..fb9842399 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -199,74 +199,42 @@ void P_DeleteFlickies(INT16 i) static void P_ClearSingleMapHeaderInfo(INT16 i) { const INT16 num = (INT16)(i-1); - DEH_WriteUndoline("LEVELNAME", mapheaderinfo[num]->lvlttl, UNDO_NONE); mapheaderinfo[num]->lvlttl[0] = '\0'; - DEH_WriteUndoline("SELECTHEADING", mapheaderinfo[num]->selectheading, UNDO_NONE); mapheaderinfo[num]->selectheading[0] = '\0'; - DEH_WriteUndoline("SUBTITLE", mapheaderinfo[num]->subttl, UNDO_NONE); mapheaderinfo[num]->subttl[0] = '\0'; - DEH_WriteUndoline("ACT", va("%d", mapheaderinfo[num]->actnum), UNDO_NONE); mapheaderinfo[num]->actnum = 0; - DEH_WriteUndoline("TYPEOFLEVEL", va("%d", mapheaderinfo[num]->typeoflevel), UNDO_NONE); mapheaderinfo[num]->typeoflevel = 0; - DEH_WriteUndoline("NEXTLEVEL", va("%d", mapheaderinfo[num]->nextlevel), UNDO_NONE); mapheaderinfo[num]->nextlevel = (INT16)(i + 1); - DEH_WriteUndoline("MUSIC", mapheaderinfo[num]->musname, UNDO_NONE); snprintf(mapheaderinfo[num]->musname, 7, "%sM", G_BuildMapName(i)); mapheaderinfo[num]->musname[6] = 0; - DEH_WriteUndoline("MUSICTRACK", va("%d", mapheaderinfo[num]->mustrack), UNDO_NONE); mapheaderinfo[num]->mustrack = 0; - DEH_WriteUndoline("FORCECHARACTER", va("%d", mapheaderinfo[num]->forcecharacter), UNDO_NONE); mapheaderinfo[num]->forcecharacter[0] = '\0'; - DEH_WriteUndoline("WEATHER", va("%d", mapheaderinfo[num]->weather), UNDO_NONE); mapheaderinfo[num]->weather = 0; - DEH_WriteUndoline("SKYNUM", va("%d", mapheaderinfo[num]->skynum), UNDO_NONE); mapheaderinfo[num]->skynum = 1; - DEH_WriteUndoline("SKYBOXSCALEX", va("%d", mapheaderinfo[num]->skybox_scalex), UNDO_NONE); mapheaderinfo[num]->skybox_scalex = 16; - DEH_WriteUndoline("SKYBOXSCALEY", va("%d", mapheaderinfo[num]->skybox_scaley), UNDO_NONE); mapheaderinfo[num]->skybox_scaley = 16; - DEH_WriteUndoline("SKYBOXSCALEZ", va("%d", mapheaderinfo[num]->skybox_scalez), UNDO_NONE); mapheaderinfo[num]->skybox_scalez = 16; - DEH_WriteUndoline("INTERSCREEN", mapheaderinfo[num]->interscreen, UNDO_NONE); mapheaderinfo[num]->interscreen[0] = '#'; - DEH_WriteUndoline("RUNSOC", mapheaderinfo[num]->runsoc, UNDO_NONE); mapheaderinfo[num]->runsoc[0] = '#'; - DEH_WriteUndoline("SCRIPTNAME", mapheaderinfo[num]->scriptname, UNDO_NONE); mapheaderinfo[num]->scriptname[0] = '#'; - DEH_WriteUndoline("PRECUTSCENENUM", va("%d", mapheaderinfo[num]->precutscenenum), UNDO_NONE); mapheaderinfo[num]->precutscenenum = 0; - DEH_WriteUndoline("CUTSCENENUM", va("%d", mapheaderinfo[num]->cutscenenum), UNDO_NONE); mapheaderinfo[num]->cutscenenum = 0; - DEH_WriteUndoline("COUNTDOWN", va("%d", mapheaderinfo[num]->countdown), UNDO_NONE); mapheaderinfo[num]->countdown = 0; - DEH_WriteUndoline("PALLETE", va("%u", mapheaderinfo[num]->palette), UNDO_NONE); mapheaderinfo[num]->palette = UINT16_MAX; - DEH_WriteUndoline("NUMLAPS", va("%u", mapheaderinfo[num]->numlaps), UNDO_NONE); mapheaderinfo[num]->numlaps = NUMLAPS_DEFAULT; - DEH_WriteUndoline("UNLOCKABLE", va("%s", mapheaderinfo[num]->unlockrequired), UNDO_NONE); mapheaderinfo[num]->unlockrequired = -1; - DEH_WriteUndoline("LEVELSELECT", va("%d", mapheaderinfo[num]->levelselect), UNDO_NONE); mapheaderinfo[num]->levelselect = 0; - DEH_WriteUndoline("BONUSTYPE", va("%d", mapheaderinfo[num]->bonustype), UNDO_NONE); mapheaderinfo[num]->bonustype = 0; - DEH_WriteUndoline("LEVELFLAGS", va("%d", mapheaderinfo[num]->levelflags), UNDO_NONE); mapheaderinfo[num]->levelflags = 0; - DEH_WriteUndoline("MENUFLAGS", va("%d", mapheaderinfo[num]->menuflags), UNDO_NONE); mapheaderinfo[num]->menuflags = 0; - // Flickies. Nope, no delfile support here either #if 1 // equivalent to "FlickyList = DEMO" P_SetDemoFlickies(num); #else // equivalent to "FlickyList = NONE" P_DeleteFlickies(num); #endif - // TODO grades support for delfile (pfft yeah right) P_DeleteGrades(num); - // an even further impossibility, delfile custom opts support mapheaderinfo[num]->customopts = NULL; mapheaderinfo[num]->numCustomOptions = 0; - - DEH_WriteUndoline(va("# uload for map %d", i), NULL, UNDO_DONE); } /** Allocates a new map-header structure. @@ -2239,6 +2207,7 @@ lumpnum_t lastloadedmaplumpnum; // for comparative savegame static void P_LevelInitStuff(void) { INT32 i; + boolean canresetlives = true; leveltime = 0; @@ -2256,7 +2225,18 @@ static void P_LevelInitStuff(void) // map time limit if (mapheaderinfo[gamemap-1]->countdown) + { + tic_t maxtime = 0; countdowntimer = mapheaderinfo[gamemap-1]->countdown * TICRATE; + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; + if (players[i].starposttime > maxtime) + maxtime = players[i].starposttime; + } + countdowntimer -= maxtime; + } else countdowntimer = 0; countdowntimeup = false; @@ -2278,9 +2258,21 @@ static void P_LevelInitStuff(void) // earthquake camera memset(&quake,0,sizeof(struct quake)); + if ((netgame || multiplayer) && gametype == GT_COOP && cv_coopstarposts.value == 2) + { + for (i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i] && players[i].lives > 0) + { + canresetlives = false; + break; + } + } + } + for (i = 0; i < MAXPLAYERS; i++) { - if ((netgame || multiplayer) && (gametype == GT_COMPETITION || players[i].lives <= 0)) + if (canresetlives && (netgame || multiplayer) && playeringame[i] && (gametype == GT_COMPETITION || players[i].lives <= 0)) { // In Co-Op, replenish a user's lives if they are depleted. players[i].lives = cv_startinglives.value; @@ -2944,6 +2936,19 @@ boolean P_SetupLevel(boolean skipprecip) } } + // restore time in netgame (see also g_game.c) + if ((netgame || multiplayer) && gametype == GT_COOP && cv_coopstarposts.value == 2) + { + // is this a hack? maybe + tic_t maxstarposttime = 0; + for (i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i] && players[i].starposttime > maxstarposttime) + maxstarposttime = players[i].starposttime; + } + leveltime = maxstarposttime; + } + if (modeattacking == ATTACKING_RECORD && !demoplayback) P_LoadRecordGhosts(); else if (modeattacking == ATTACKING_NIGHTS && !demoplayback) @@ -3360,6 +3365,7 @@ boolean P_AddWadFile(const char *wadfilename, char **firstmapname) // look for skins // R_AddSkins(wadnum); // faB: wadfile index in wadfiles[] + R_PatchSkins(wadnum); // toast: PATCH PATCH // // search for maps @@ -3410,31 +3416,3 @@ boolean P_AddWadFile(const char *wadfilename, char **firstmapname) return true; } - -#ifdef DELFILE -boolean P_DelWadFile(void) -{ - sfxenum_t i; - const UINT16 wadnum = (UINT16)(numwadfiles - 1); - const lumpnum_t lumpnum = numwadfiles<<16; - //lumpinfo_t *lumpinfo = wadfiles[wadnum]->lumpinfo; - R_DelSkins(wadnum); // only used by DELFILE - R_DelSpriteDefs(wadnum); // only used by DELFILE - for (i = 0; i < NUMSFX; i++) - { - if (S_sfx[i].lumpnum != LUMPERROR && S_sfx[i].lumpnum >= lumpnum) - { - S_StopSoundByNum(i); - S_RemoveSoundFx(i); - if (S_sfx[i].lumpnum != LUMPERROR) - { - I_FreeSfx(&S_sfx[i]); - S_sfx[i].lumpnum = LUMPERROR; - } - } - } - W_UnloadWadFile(wadnum); // only used by DELFILE - R_LoadTextures(); - return false; -} -#endif diff --git a/src/p_setup.h b/src/p_setup.h index 95976d276..3443ffdb7 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -60,9 +60,6 @@ void P_ScanThings(INT16 mapnum, INT16 wadnum, INT16 lumpnum); void P_LoadThingsOnly(void); boolean P_SetupLevel(boolean skipprecip); boolean P_AddWadFile(const char *wadfilename, char **firstmapname); -#ifdef DELFILE -boolean P_DelWadFile(void); -#endif boolean P_RunSOC(const char *socfilename); void P_WriteThings(lumpnum_t lump); size_t P_PrecacheLevelFlats(void); diff --git a/src/p_tick.c b/src/p_tick.c index 5235a1a03..a79d71ef4 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -359,7 +359,7 @@ static void P_DoAutobalanceTeams(void) totalred = red + redflagcarrier; totalblue = blue + blueflagcarrier; - if ((abs(totalred - totalblue) > cv_autobalance.value)) + if ((abs(totalred - totalblue) > max(1, (totalred + totalblue) / 8))) { if (totalred > totalblue) { @@ -372,8 +372,7 @@ static void P_DoAutobalanceTeams(void) usvalue = SHORT(NetPacket.value.l|NetPacket.value.b); SendNetXCmd(XD_TEAMCHANGE, &usvalue, sizeof(usvalue)); } - - if (totalblue > totalred) + else //if (totalblue > totalred) { i = M_RandomKey(blue); NetPacket.packet.newteam = 1; @@ -651,7 +650,7 @@ void P_Ticker(boolean run) if (run) { - if (countdowntimer && --countdowntimer <= 0) + if (countdowntimer && G_PlatformGametype() && (gametype == GT_COOP || leveltime >= 4*TICRATE) && --countdowntimer <= 0) { countdowntimer = 0; countdowntimeup = true; @@ -663,6 +662,8 @@ void P_Ticker(boolean run) if (!players[i].mo) continue; + if (multiplayer || netgame) + players[i].exiting = 0; P_DamageMobj(players[i].mo, NULL, NULL, 1, DMG_INSTAKILL); } } diff --git a/src/p_user.c b/src/p_user.c index 167e1eacb..09cafa0b3 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -666,7 +666,7 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime) if (skins[player->skin].sprites[SPR2_NGT0].numframes == 0) // If you don't have a sprite for flying horizontally, use the default NiGHTS skin. { player->mo->skin = &skins[DEFAULTNIGHTSSKIN]; - player->mo->color = ((skin_t *)(player->mo->skin))->prefcolor; + player->mo->color = skins[DEFAULTNIGHTSSKIN].prefcolor; } player->nightstime = player->startedtime = nighttime*TICRATE; @@ -958,6 +958,29 @@ void P_GivePlayerLives(player_t *player, INT32 numlives) player->lives = 1; } +void P_GiveCoopLives(player_t *player, INT32 numlives, boolean sound) +{ + if (!((netgame || multiplayer) && gametype == GT_COOP)) + { + P_GivePlayerLives(player, numlives); + if (sound) + P_PlayLivesJingle(player); + } + else + { + INT32 i; + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; + + P_GivePlayerLives(&players[i], numlives); + if (sound) + P_PlayLivesJingle(&players[i]); + } + } +} + // // P_DoSuperTransformation // @@ -1130,7 +1153,9 @@ void P_PlayLivesJingle(player_t *player) if (player && !P_IsLocalPlayer(player)) return; - if (use1upSound) + if (gametype == GT_COOP && (netgame || multiplayer) && cv_cooplives.value == 0) + S_StartSound(NULL, sfx_lose); + else if (use1upSound) S_StartSound(NULL, sfx_oneup); else if (mariomode) S_StartSound(NULL, sfx_marioa); @@ -2266,7 +2291,7 @@ static void P_CheckInvincibilityTimer(player_t *player) return; if (mariomode && !player->powers[pw_super]) - player->mo->color = (UINT8)(SKINCOLOR_RED + (leveltime % (MAXSKINCOLORS - SKINCOLOR_RED))); // Passes through all saturated colours + player->mo->color = (UINT8)(SKINCOLOR_RUBY + (leveltime % (MAXSKINCOLORS - SKINCOLOR_RUBY))); // Passes through all saturated colours else if (leveltime % (TICRATE/7) == 0) { mobj_t *sparkle = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_IVSP); @@ -2323,7 +2348,7 @@ static void P_DoBubbleBreath(player_t *player) if (player->charflags & SF_MACHINE) { - if (P_RandomChance((128-(player->powers[pw_underwater]/4))*FRACUNIT/256)) + if (player->powers[pw_underwater] && P_RandomChance((128-(player->powers[pw_underwater]/4))*FRACUNIT/256)) { fixed_t r = player->mo->radius>>FRACBITS; x += (P_RandomRange(r, -r)<mo->momy /= 3; } - if (player->mo->info->attacksound && !player->spectator) - S_StartSound(player->mo, player->mo->info->attacksound); // Play the THOK sound - - P_SpawnThokMobj(player); - if (player->charability == CA_HOMINGTHOK) { P_SetTarget(&player->mo->target, P_SetTarget(&player->mo->tracer, lockon)); @@ -4357,10 +4377,16 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) { P_SetPlayerMobjState(player->mo, S_PLAY_FALL); player->pflags &= ~PF_JUMPED; + player->mo->height = P_GetPlayerHeight(player); } player->pflags &= ~PF_NOJUMPDAMAGE; } + if (player->mo->info->attacksound && !player->spectator) + S_StartSound(player->mo, player->mo->info->attacksound); // Play the THOK sound + + P_SpawnThokMobj(player); + player->pflags &= ~(PF_SPINNING|PF_STARTDASH); player->pflags |= PF_THOKKED; } @@ -4822,7 +4848,7 @@ static void P_3dMovement(player_t *player) angle_t dangle; // replaces old quadrants bits fixed_t normalspd = FixedMul(player->normalspeed, player->mo->scale); boolean analogmove = false; - boolean spin = (player->pflags & PF_SPINNING && (player->rmomx || player->rmomy) && !(player->pflags & PF_STARTDASH)); + boolean spin = ((onground = P_IsObjectOnGround(player->mo)) && player->pflags & PF_SPINNING && (player->rmomx || player->rmomy) && !(player->pflags & PF_STARTDASH)); fixed_t oldMagnitude, newMagnitude; #ifdef ESLOPE vector3_t totalthrust; @@ -4912,9 +4938,6 @@ static void P_3dMovement(player_t *player) if (player->pflags & PF_SLIDING) cmd->forwardmove = 0; - // Do not let the player control movement if not onground. - onground = P_IsObjectOnGround(player->mo); - player->aiming = cmd->aiming<forwardmove * (thrustfactor * acceleration); - // allow very small movement while in air for gameplay - if (!onground) - movepushforward >>= 2; // proper air movement - // Allow a bit of movement while spinning if (player->pflags & PF_SPINNING) { if ((mforward && cmd->forwardmove > 0) || (mbackward && cmd->forwardmove < 0) || (player->pflags & PF_STARTDASH)) movepushforward = 0; + else if (onground) + movepushforward >>= 4; else - movepushforward = FixedDiv(movepushforward, 16*FRACUNIT); + movepushforward >>= 3; } + // allow very small movement while in air for gameplay + else if (!onground) + movepushforward >>= 2; // proper air movement movepushforward = FixedMul(movepushforward, player->mo->scale); @@ -5059,21 +5080,20 @@ static void P_3dMovement(player_t *player) movepushforward = max(abs(cmd->sidemove), abs(cmd->forwardmove)) * (thrustfactor * acceleration); - // allow very small movement while in air for gameplay - if (!onground) - movepushforward >>= 2; // proper air movement - // Allow a bit of movement while spinning if (player->pflags & PF_SPINNING) { - // Stupid little movement prohibitor hack - // that REALLY shouldn't belong in analog code. if ((mforward && cmd->forwardmove > 0) || (mbackward && cmd->forwardmove < 0) || (player->pflags & PF_STARTDASH)) movepushforward = 0; + else if (onground) + movepushforward >>= 4; else - movepushforward = FixedDiv(movepushforward, 16*FRACUNIT); + movepushforward >>= 3; } + // allow very small movement while in air for gameplay + else if (!onground) + movepushforward >>= 2; // proper air movement movepushsideangle = controldirection; @@ -5091,25 +5111,26 @@ static void P_3dMovement(player_t *player) { movepushside = cmd->sidemove * (thrustfactor * acceleration); + // allow very small movement while in air for gameplay if (!onground) { - movepushside >>= 2; - + movepushside >>= 2; // proper air movement // Reduce movepushslide even more if over "max" flight speed - if (player->powers[pw_tailsfly] && player->speed > topspeed) + if ((player->pflags & PF_SPINNING) || (player->powers[pw_tailsfly] && player->speed > topspeed)) movepushside >>= 2; } - // Allow a bit of movement while spinning - if (player->pflags & PF_SPINNING) + else if (player->pflags & PF_SPINNING) { - if ((player->pflags & PF_STARTDASH)) + if (player->pflags & PF_STARTDASH) movepushside = 0; + else if (onground) + movepushside >>= 4; else - movepushside = FixedDiv(movepushside,16*FRACUNIT); + movepushside >>= 3; } - // Finally move the player now that his speed/direction has been decided. + // Finally move the player now that their speed/direction has been decided. movepushside = FixedMul(movepushside, player->mo->scale); #ifdef ESLOPE @@ -5192,16 +5213,16 @@ static void P_SpectatorMovement(player_t *player) if (!(cmd->angleturn & TICCMD_RECEIVED)) ticmiss++; - if (player->mo->z > player->mo->ceilingz - player->mo->height) - player->mo->z = player->mo->ceilingz - player->mo->height; - if (player->mo->z < player->mo->floorz) - player->mo->z = player->mo->floorz; - if (cmd->buttons & BT_JUMP) player->mo->z += FRACUNIT*16; else if (cmd->buttons & BT_USE) player->mo->z -= FRACUNIT*16; + if (player->mo->z > player->mo->ceilingz - player->mo->height) + player->mo->z = player->mo->ceilingz - player->mo->height; + if (player->mo->z < player->mo->floorz) + player->mo->z = player->mo->floorz; + // Aiming needed for SEENAMES, etc. // We may not need to fire as a spectator, but this is still handy! player->aiming = cmd->aiming<mo->state >= &states[S_PLAY_SUPER_TRANS] && player->mo->state <= &states[S_PLAY_SUPER_TRANS9]) { player->mo->momx = player->mo->momy = player->mo->momz = 0; @@ -6740,6 +6758,7 @@ static void P_MovePlayer(player_t *player) if (player->spectator) { + player->mo->eflags &= ~MFE_VERTICALFLIP; // deflip... P_SpectatorMovement(player); return; } @@ -8131,6 +8150,111 @@ void P_FindEmerald(void) return; } +// +// P_GetLives +// Get extra lives in new co-op if you're allowed to. +// + +boolean P_GetLives(player_t *player) +{ + INT32 i, maxlivesplayer = -1, livescheck = 1; + if (!(netgame || multiplayer) + || (gametype != GT_COOP) + || (cv_cooplives.value == 1)) + return true; + + if ((cv_cooplives.value == 2 || cv_cooplives.value == 0) && player->lives > 0) + return true; + + if (cv_cooplives.value == 0) // infinite lives + { + player->lives++; + return true; + } + + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; + + if (players[i].lives > livescheck) + { + maxlivesplayer = i; + livescheck = players[i].lives; + } + } + if (maxlivesplayer != -1 && &players[maxlivesplayer] != player) + { + if (cv_cooplives.value == 2 && (P_IsLocalPlayer(player) || P_IsLocalPlayer(&players[maxlivesplayer]))) + S_StartSound(NULL, sfx_jshard); // placeholder + players[maxlivesplayer].lives--; + player->lives++; + if (player->lives < 1) + player->lives = 1; + return true; + } + return (player->lives > 0); +} + +// +// P_ConsiderAllGone +// Shamelessly lifted from TD. Thanks, Sryder! +// + +static void P_ConsiderAllGone(void) +{ + INT32 i, lastdeadplayer = -1, deadtimercheck = INT32_MAX; + + if (countdown2) + return; + + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; + + if (players[i].playerstate != PST_DEAD && !players[i].spectator && players[i].mo && players[i].mo->health) + break; + + if (players[i].spectator) + { + if (lastdeadplayer == -1) + lastdeadplayer = i; + } + else if (players[i].lives > 0) + { + lastdeadplayer = i; + if (players[i].deadtimer < deadtimercheck) + deadtimercheck = players[i].deadtimer; + } + } + + if (i == MAXPLAYERS && lastdeadplayer != -1 && deadtimercheck > 2*TICRATE) // the last killed player will reset the level in G_DoReborn + { + //players[lastdeadplayer].spectator = true; + players[lastdeadplayer].outofcoop = true; + players[lastdeadplayer].playerstate = PST_REBORN; + } +} + +void P_RestoreMultiMusic(player_t *player) +{ + if (netgame) + { + if (P_IsLocalPlayer(player)) + S_ChangeMusic(mapmusname, mapmusflags, true); + } + else if (multiplayer) // local multiplayer only + { + // Restore the other player's music once we're dead for long enough + // -- that is, as long as they aren't dead too + if (player == &players[displayplayer] && players[secondarydisplayplayer].lives > 0) + P_RestoreMusic(&players[secondarydisplayplayer]); + else if (player == &players[secondarydisplayplayer] && players[displayplayer].lives > 0) + P_RestoreMusic(&players[displayplayer]); + } +} + // // P_DeathThink // Fall on your face when dying. @@ -8139,6 +8263,8 @@ void P_FindEmerald(void) static void P_DeathThink(player_t *player) { + INT32 j = MAXPLAYERS; + ticcmd_t *cmd = &player->cmd; player->deltaviewheight = 0; @@ -8154,76 +8280,100 @@ static void P_DeathThink(player_t *player) G_UseContinue(); // Even if we don't have one this handles ending the game } + if ((cv_cooplives.value != 1) + && (gametype == GT_COOP) + && (netgame || multiplayer) + && (player->lives <= 0)) + { + for (j = 0; j < MAXPLAYERS; j++) + { + if (!playeringame[j]) + continue; + + if (players[j].lives > 1) + break; + } + } + // Force respawn if idle for more than 30 seconds in shooter modes. if (player->deadtimer > 30*TICRATE && !G_PlatformGametype()) player->playerstate = PST_REBORN; - else if (player->lives > 0 && !G_IsSpecialStage(gamemap)) // Don't allow "click to respawn" in special stages! + else if ((player->lives > 0 || j != MAXPLAYERS) && !G_IsSpecialStage(gamemap)) // Don't allow "click to respawn" in special stages! { - // Respawn with jump button, force respawn time (3 second default, cheat protected) in shooter modes. - if ((cmd->buttons & BT_JUMP) && player->deadtimer > cv_respawntime.value*TICRATE - && gametype != GT_RACE && gametype != GT_COOP) - player->playerstate = PST_REBORN; + if (gametype == GT_COOP && (netgame || multiplayer) && cv_coopstarposts.value == 2) + { + P_ConsiderAllGone(); + if ((player->deadtimer > 5*TICRATE) || ((cmd->buttons & BT_JUMP) && (player->deadtimer > TICRATE))) + { + //player->spectator = true; + player->outofcoop = true; + player->playerstate = PST_REBORN; + } + } + else + { + // Respawn with jump button, force respawn time (3 second default, cheat protected) in shooter modes. + if (cmd->buttons & BT_JUMP) + { + if (gametype != GT_COOP && player->spectator) + player->playerstate = PST_REBORN; + else switch(gametype) { + case GT_COOP: + if (player->deadtimer > TICRATE) + player->playerstate = PST_REBORN; + break; + case GT_COMPETITION: + if (player->deadtimer > TICRATE) + player->playerstate = PST_REBORN; + break; + case GT_RACE: + player->playerstate = PST_REBORN; + break; + default: + if (player->deadtimer > cv_respawntime.value*TICRATE) + player->playerstate = PST_REBORN; + break; + } + } - // Instant respawn in race or if you're spectating. - if ((cmd->buttons & BT_JUMP) && (gametype == GT_RACE || player->spectator)) - player->playerstate = PST_REBORN; - - // One second respawn in coop. - if ((cmd->buttons & BT_JUMP) && player->deadtimer > TICRATE && (gametype == GT_COOP || gametype == GT_COMPETITION)) - player->playerstate = PST_REBORN; - - // Single player auto respawn - if (!(netgame || multiplayer) && player->deadtimer > 5*TICRATE) - player->playerstate = PST_REBORN; + // Single player auto respawn + if (!(netgame || multiplayer) && player->deadtimer > 5*TICRATE) + player->playerstate = PST_REBORN; + } } - else if ((netgame || multiplayer) && player->deadtimer == 8*TICRATE) + else if ((netgame || multiplayer) && player->deadtimer >= 8*TICRATE) { + + INT32 i, deadtimercheck = INT32_MAX; + // In a net/multiplayer game, and out of lives if (gametype == GT_COMPETITION) { - INT32 i; - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && !players[i].exiting && players[i].lives > 0) + { + if (!playeringame[i]) + continue; + if (!players[i].exiting && players[i].lives) break; + if (players[i].deadtimer < deadtimercheck) + deadtimercheck = players[i].deadtimer; + } - if (i == MAXPLAYERS) + if (i == MAXPLAYERS && deadtimercheck == 8*TICRATE) { // Everyone's either done with the race, or dead. if (!countdown2 || countdown2 > 1*TICRATE) countdown2 = 1*TICRATE; } } + //else if (gametype == GT_COOP) -- moved to G_DoReborn + } - // In a coop game, and out of lives - if (gametype == GT_COOP) - { - INT32 i; - - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && (players[i].exiting || players[i].lives > 0)) - break; - - if (i == MAXPLAYERS) - { - // They're dead, Jim. - //nextmapoverride = spstage_start; - nextmapoverride = gamemap; - countdown2 = 1*TICRATE; - skipstats = true; - - for (i = 0; i < MAXPLAYERS; i++) - { - if (playeringame[i]) - players[i].score = 0; - } - - //emeralds = 0; - tokenbits = 0; - tokenlist = 0; - token = 0; - } - } + if (gametype == GT_COOP && (multiplayer || netgame) && (player->lives <= 0) && (player->deadtimer >= 8*TICRATE || ((cmd->buttons & BT_JUMP) && (player->deadtimer > TICRATE)))) + { + //player->spectator = true; + player->outofcoop = true; + player->playerstate = PST_REBORN; } if (gametype == GT_RACE || gametype == GT_COMPETITION || (gametype == GT_COOP && (multiplayer || netgame))) @@ -8243,25 +8393,8 @@ static void P_DeathThink(player_t *player) } // Return to level music - if (player->lives <= 0) - { - if (netgame) - { - if (player->deadtimer == gameovertics && P_IsLocalPlayer(player)) - S_ChangeMusic(mapmusname, mapmusflags, true); - } - else if (multiplayer) // local multiplayer only - { - if (player->deadtimer != gameovertics) - ; - // Restore the other player's music once we're dead for long enough - // -- that is, as long as they aren't dead too - else if (player == &players[displayplayer] && players[secondarydisplayplayer].lives > 0) - P_RestoreMusic(&players[secondarydisplayplayer]); - else if (player == &players[secondarydisplayplayer] && players[displayplayer].lives > 0) - P_RestoreMusic(&players[displayplayer]); - } - } + if (gametype != GT_COOP && player->lives <= 0 && player->deadtimer == gameovertics) + P_RestoreMultiMusic(player); } if (!player->mo) @@ -8915,16 +9048,9 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall return (x == thiscam->x && y == thiscam->y && z == thiscam->z && angle == thiscam->aiming); } -static boolean P_SpectatorJoinGame(player_t *player) +boolean P_SpectatorJoinGame(player_t *player) { - if (!G_GametypeHasSpectators() && G_IsSpecialStage(gamemap) && useNightsSS) // Special Stage spectators should NEVER be allowed to rejoin the game - { - if (P_IsLocalPlayer(player)) - CONS_Printf(M_GetText("You cannot enter the game while a special stage is in progress.\n")); - player->powers[pw_flashing] += 2*TICRATE; //to prevent message spam. - } - - else if (!cv_allowteamchange.value) + if (gametype != GT_COOP && !cv_allowteamchange.value) { if (P_IsLocalPlayer(player)) CONS_Printf(M_GetText("Server does not allow team change.\n")); @@ -8993,7 +9119,7 @@ static boolean P_SpectatorJoinGame(player_t *player) P_RemoveMobj(player->mo); player->mo = NULL; } - player->spectator = false; + player->spectator = player->outofcoop = false; player->playerstate = PST_REBORN; if (gametype == GT_TAG) @@ -9012,7 +9138,8 @@ static boolean P_SpectatorJoinGame(player_t *player) if (P_IsLocalPlayer(player) && displayplayer != consoleplayer) displayplayer = consoleplayer; - CONS_Printf(M_GetText("%s entered the game.\n"), player_names[player-players]); + if (gametype != GT_COOP) + CONS_Printf(M_GetText("%s entered the game.\n"), player_names[player-players]); return true; // no more player->mo, cannot continue. } else @@ -9306,7 +9433,7 @@ void P_PlayerThink(player_t *player) { if (cv_playersforexit.value) // Count to be sure everyone's exited { - INT32 i; + INT32 i, total = 0, exiting = 0; for (i = 0; i < MAXPLAYERS; i++) { @@ -9315,11 +9442,12 @@ void P_PlayerThink(player_t *player) if (players[i].lives <= 0) continue; - if (!players[i].exiting || players[i].exiting > 3) - break; + total++; + if (players[i].exiting && players[i].exiting < 4) + exiting++; } - if (i == MAXPLAYERS) + if (!total || ((4*exiting)/total) >= cv_playersforexit.value) { if (server) SendNetXCmd(XD_EXITLEVEL, NULL, 0); @@ -9346,7 +9474,12 @@ void P_PlayerThink(player_t *player) if (!player->spectator) P_PlayerInSpecialSector(player); + else if ( +#else + if (player->spectator && #endif + gametype == GT_COOP && (netgame || multiplayer) && cv_coopstarposts.value == 2) + P_ConsiderAllGone(); if (player->playerstate == PST_DEAD) { @@ -9359,14 +9492,14 @@ void P_PlayerThink(player_t *player) // Make sure spectators always have a score and ring count of 0. if (player->spectator) { - player->score = 0; + if (gametype != GT_COOP) + player->score = 0; player->mo->health = 1; player->rings = 0; } - - if ((netgame || multiplayer) && player->lives <= 0) + else if ((netgame || multiplayer) && player->lives <= 0 && gametype != GT_COOP) { - // In Co-Op, replenish a user's lives if they are depleted. + // Outside of Co-Op, replenish a user's lives if they are depleted. // of course, this is just a cheap hack, meh... player->lives = cv_startinglives.value; } @@ -9392,7 +9525,7 @@ void P_PlayerThink(player_t *player) player->realtime = leveltime; } - if ((netgame || splitscreen) && player->spectator && cmd->buttons & BT_ATTACK && !player->powers[pw_flashing]) + if (player->spectator && cmd->buttons & BT_ATTACK && !player->powers[pw_flashing] && G_GametypeHasSpectators()) { if (P_SpectatorJoinGame(player)) return; // player->mo was removed. diff --git a/src/r_draw.c b/src/r_draw.c index 24062a678..4479cf02c 100644 --- a/src/r_draw.c +++ b/src/r_draw.c @@ -126,95 +126,301 @@ UINT32 nflatxshift, nflatyshift, nflatshiftup, nflatmask; #define BOSS_TT_CACHE_INDEX (MAXSKINS + 1) #define METALSONIC_TT_CACHE_INDEX (MAXSKINS + 2) #define ALLWHITE_TT_CACHE_INDEX (MAXSKINS + 3) -#define SKIN_RAMP_LENGTH 16 #define DEFAULT_STARTTRANSCOLOR 96 #define NUM_PALETTE_ENTRIES 256 static UINT8** translationtablecache[MAXSKINS + 4] = {NULL}; +const UINT8 Color_Index[MAXTRANSLATIONS-1][16] = { + // {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, // SKINCOLOR_NONE + + // Greyscale ranges + {0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x11}, // SKINCOLOR_WHITE + {0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x05, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x11, 0x12}, // SKINCOLOR_BONE + {0x02, 0x03, 0x04, 0x05, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14}, // SKINCOLOR_CLOUDY + {0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18}, // SKINCOLOR_GREY + {0x02, 0x03, 0x05, 0x07, 0x09, 0x0b, 0x0d, 0x0f, 0x11, 0x13, 0x15, 0x17, 0x19, 0x1b, 0x1d, 0x1f}, // SKINCOLOR_SILVER + {0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x16, 0x17, 0x17, 0x19, 0x19, 0x1a, 0x1a, 0x1b, 0x1c, 0x1d}, // SKINCOLOR_CARBON + {0x00, 0x05, 0x0a, 0x0f, 0x14, 0x19, 0x1a, 0x1b, 0x1c, 0x1e, 0x1e, 0x1e, 0x1f, 0x1f, 0x1f, 0x1f}, // SKINCOLOR_JET + {0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1b, 0x1b, 0x1c, 0x1d, 0x1d, 0x1e, 0x1e, 0x1f, 0x1f}, // SKINCOLOR_BLACK + + // Desaturated + {0x00, 0x00, 0x01, 0x02, 0x02, 0x03, 0x91, 0x91, 0x91, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xaf}, // SKINCOLOR_AETHER + {0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0xaa, 0xaa, 0xaa, 0xab, 0xac, 0xac, 0xad, 0xad, 0xae, 0xaf}, // SKINCOLOR_SLATE + {0xd0, 0xd0, 0xd1, 0xd1, 0xd2, 0xd2, 0xd3, 0xd3, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0x2b, 0x2c, 0x2e}, // SKINCOLOR_PINK + {0xd0, 0x30, 0xd8, 0xd9, 0xda, 0xdb, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe3, 0xe6, 0xe8, 0xe9}, // SKINCOLOR_YOGURT + {0xdf, 0xe0, 0xe1, 0xe2, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef}, // SKINCOLOR_BROWN + {0x51, 0x51, 0x54, 0x54, 0x55, 0x55, 0x56, 0x56, 0x56, 0x57, 0xf5, 0xf5, 0xf9, 0xf9, 0xed, 0xed}, // SKINCOLOR_TAN + {0x54, 0x55, 0x56, 0x56, 0xf2, 0xf3, 0xf3, 0xf4, 0xf5, 0xf6, 0xf8, 0xf9, 0xfa, 0xfb, 0xed, 0xed}, // SKINCOLOR_BEIGE + {0x58, 0x58, 0x59, 0x59, 0x5a, 0x5a, 0x5b, 0x5b, 0x5b, 0x5c, 0x5d, 0x5d, 0x5e, 0x5e, 0x5f, 0x5f}, // SKINCOLOR_MOSS + {0x90, 0x90, 0x91, 0x91, 0xaa, 0xaa, 0xab, 0xab, 0xab, 0xac, 0xad, 0xad, 0xae, 0xae, 0xaf, 0xaf}, // SKINCOLOR_AZURE + {0xc0, 0xc0, 0xc1, 0xc1, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc4, 0xc5, 0xc5, 0xc6, 0xc6, 0xc7, 0xc7}, // SKINCOLOR_LAVENDER + + // Viv's vivid colours (toast 21/07/17) + {0xb0, 0xb0, 0xc9, 0xca, 0xcc, 0x26, 0x27, 0x28, 0x29, 0x2a, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xfd}, // SKINCOLOR_RUBY + {0xd0, 0xd0, 0xd1, 0xd2, 0x20, 0x21, 0x24, 0x25, 0x26, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e}, // SKINCOLOR_SALMON + {0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x47, 0x2e, 0x2f}, // SKINCOLOR_RED + {0x27, 0x27, 0x28, 0x28, 0x29, 0x2a, 0x2b, 0x2b, 0x2c, 0x2d, 0x2e, 0x2e, 0x2e, 0x2f, 0x2f, 0x1f}, // SKINCOLOR_CRIMSON + {0x31, 0x32, 0x33, 0x36, 0x22, 0x22, 0x25, 0x25, 0x25, 0xcd, 0xcf, 0xcf, 0xc5, 0xc5, 0xc7, 0xc7}, // SKINCOLOR_FLAME + {0xd0, 0x30, 0x31, 0x31, 0x32, 0x32, 0xdc, 0xdc, 0xdc, 0xd3, 0xd4, 0xd4, 0xcc, 0xcd, 0xce, 0xcf}, // SKINCOLOR_PEACHY + {0xd8, 0xd9, 0xdb, 0xdc, 0xde, 0xdf, 0xd5, 0xd5, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0x1d, 0x1f}, // SKINCOLOR_QUAIL + {0x51, 0x52, 0x40, 0x40, 0x34, 0x36, 0xd5, 0xd5, 0xd6, 0xd7, 0xcf, 0xcf, 0xc6, 0xc6, 0xc7, 0xfe}, // SKINCOLOR_SUNSET + {0x00, 0xd8, 0xd9, 0xda, 0xdb, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e}, // SKINCOLOR_APRICOT + {0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x2c}, // SKINCOLOR_ORANGE + {0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3c, 0x3d, 0x3d, 0x3d, 0x3f, 0x2c, 0x2d, 0x47, 0x2e, 0x2f, 0x2f}, // SKINCOLOR_RUST + {0x51, 0x51, 0x54, 0x54, 0x41, 0x42, 0x43, 0x43, 0x44, 0x45, 0x46, 0x3f, 0x2d, 0x2e, 0x2f, 0x2f}, // SKINCOLOR_GOLD + {0x53, 0x40, 0x41, 0x42, 0x43, 0xe6, 0xe9, 0xe9, 0xea, 0xec, 0xec, 0xc6, 0xc6, 0xc7, 0xc7, 0xfe}, // SKINCOLOR_SANDY + {0x52, 0x53, 0x49, 0x49, 0x4a, 0x4a, 0x4b, 0x4b, 0x4b, 0x4c, 0x4d, 0x4d, 0x4e, 0x4e, 0x4f, 0xed}, // SKINCOLOR_YELLOW + {0x4b, 0x4b, 0x4c, 0x4c, 0x4d, 0x4e, 0xe7, 0xe7, 0xe9, 0xc5, 0xc5, 0xc6, 0xc6, 0xc7, 0xc7, 0xfd}, // SKINCOLOR_OLIVE + {0x50, 0x51, 0x52, 0x53, 0x48, 0xbc, 0xbd, 0xbe, 0xbe, 0xbf, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f}, // SKINCOLOR_LIME + {0x58, 0x58, 0xbc, 0xbc, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbf, 0x5e, 0x5e, 0x5f, 0x5f, 0x77, 0x77}, // SKINCOLOR_PERIDOT + {0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f}, // SKINCOLOR_GREEN + {0x65, 0x66, 0x67, 0x68, 0x69, 0x69, 0x6a, 0x6b, 0x6b, 0x6c, 0x6d, 0x6d, 0x6e, 0x6e, 0x6e, 0x6f}, // SKINCOLOR_FOREST + {0x70, 0x70, 0x71, 0x71, 0x72, 0x72, 0x73, 0x73, 0x73, 0x74, 0x75, 0x75, 0x76, 0x76, 0x77, 0x77}, // SKINCOLOR_EMERALD + {0x00, 0x00, 0x58, 0x58, 0x59, 0x62, 0x62, 0x62, 0x64, 0x67, 0x7e, 0x7e, 0x8f, 0x8f, 0x8a, 0x8a}, // SKINCOLOR_MINT + {0x01, 0x58, 0x59, 0x5a, 0x7d, 0x7d, 0x7e, 0x7e, 0x7e, 0x8f, 0x8f, 0x8a, 0x8a, 0x8a, 0xfd, 0xfd}, // SKINCOLOR_SEAFOAM + {0x78, 0x79, 0x7a, 0x7a, 0x7b, 0x7b, 0x7c, 0x7c, 0x7c, 0x7d, 0x7e, 0x7e, 0x7f, 0x7f, 0x76, 0x77}, // SKINCOLOR_AQUA + {0x78, 0x78, 0x8c, 0x8c, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8f, 0x8f, 0x8f, 0x8a, 0x8a, 0x8a, 0x8a}, // SKINCOLOR_TEAL + {0x00, 0x78, 0x78, 0x79, 0x8d, 0x87, 0x88, 0x89, 0x89, 0xae, 0xa8, 0xa8, 0xa9, 0xa9, 0xfd, 0xfd}, // SKINCOLOR_WAVE + {0x80, 0x81, 0xff, 0xff, 0x83, 0x83, 0x8d, 0x8d, 0x8d, 0x8e, 0x7e, 0x7f, 0x76, 0x76, 0x77, 0x6e}, // SKINCOLOR_CYAN + {0x80, 0x80, 0x81, 0x82, 0x83, 0x83, 0x84, 0x85, 0x85, 0x86, 0x87, 0x88, 0x89, 0x89, 0x8a, 0x8b}, // SKINCOLOR_SKY + {0x85, 0x86, 0x87, 0x88, 0x88, 0x89, 0x89, 0x89, 0x8a, 0x8a, 0xfd, 0xfd, 0xfd, 0x1f, 0x1f, 0x1f}, // SKINCOLOR_CERULEAN + {0x00, 0x00, 0x00, 0x00, 0x80, 0x81, 0x83, 0x83, 0x86, 0x87, 0x95, 0x95, 0xad, 0xad, 0xae, 0xaf}, // SKINCOLOR_ICY + {0x80, 0x83, 0x86, 0x87, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xfd, 0xfe}, // SKINCOLOR_SAPPHIRE + {0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x9a, 0x9c, 0x9d, 0x9d, 0x9e, 0x9e, 0x9e}, // SKINCOLOR_CORNFLOWER + {0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xfd, 0xfe}, // SKINCOLOR_BLUE + {0x93, 0x94, 0x95, 0x96, 0x98, 0x9a, 0x9b, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xfd, 0xfd, 0xfe, 0xfe}, // SKINCOLOR_COBALT + {0x80, 0x81, 0x83, 0x86, 0x94, 0x94, 0xa3, 0xa3, 0xa4, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa9, 0xa9}, // SKINCOLOR_VAPOR + {0x92, 0x93, 0x94, 0x94, 0xac, 0xad, 0xad, 0xad, 0xae, 0xae, 0xaf, 0xaf, 0xa9, 0xa9, 0xfd, 0xfd}, // SKINCOLOR_DUSK + {0x90, 0x90, 0xa0, 0xa0, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2, 0xa3, 0xa4, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8}, // SKINCOLOR_PASTEL + {0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa6, 0xa7, 0xa7, 0xa8, 0xa8, 0xa9, 0xa9}, // SKINCOLOR_PURPLE + {0x00, 0xd0, 0xd0, 0xc8, 0xc8, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8}, // SKINCOLOR_BUBBLEGUM + {0xb3, 0xb3, 0xb4, 0xb5, 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb8, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xbb}, // SKINCOLOR_MAGENTA + {0xb3, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xbb, 0xc7, 0xc7, 0x1d, 0x1d, 0x1e}, // SKINCOLOR_NEON + {0xd0, 0xd1, 0xd2, 0xca, 0xcc, 0xb8, 0xb9, 0xb9, 0xba, 0xa8, 0xa8, 0xa9, 0xa9, 0xfd, 0xfe, 0xfe}, // SKINCOLOR_VIOLET + {0x00, 0xd0, 0xd1, 0xd2, 0xd3, 0xc1, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc5, 0xc6, 0xc6, 0xfe, 0x1f}, // SKINCOLOR_LILAC + {0xc8, 0xd3, 0xd5, 0xd6, 0xd7, 0xce, 0xcf, 0xb9, 0xb9, 0xba, 0xba, 0xa9, 0xa9, 0xa9, 0xfd, 0xfe}, // SKINCOLOR_PLUM + {0xfc, 0xc8, 0xc8, 0xc9, 0xc9, 0xca, 0xca, 0xcb, 0xcb, 0xcc, 0xcc, 0xcd, 0xcd, 0xce, 0xce, 0xcf}, // SKINCOLOR_ROSY + + // {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, // SKINCOLOR_? + + // super + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x03}, // SKINCOLOR_SUPERSILVER1 + {0x00, 0x01, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x07}, // SKINCOLOR_SUPERSILVER2 + {0x01, 0x02, 0x02, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x07, 0x09, 0x0b}, // SKINCOLOR_SUPERSILVER3 + {0x02, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x07, 0x09, 0x0b, 0x0d, 0x0f, 0x11}, // SKINCOLOR_SUPERSILVER4 + {0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x07, 0x09, 0x0b, 0x0d, 0x0f, 0x11, 0x13}, // SKINCOLOR_SUPERSILVER5 + + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0xd0, 0xd1, 0xd1, 0xd2, 0xd2}, // SKINCOLOR_SUPERRED1 + {0x00, 0x00, 0x00, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1, 0xd1, 0xd2, 0xd2, 0xd2, 0x20, 0x20, 0x21, 0x21}, // SKINCOLOR_SUPERRED2 + {0x00, 0x00, 0xd0, 0xd0, 0xd1, 0xd1, 0xd2, 0xd2, 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23}, // SKINCOLOR_SUPERRED3 + {0x00, 0xd0, 0xd1, 0xd1, 0xd2, 0xd2, 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23, 0x24, 0x24}, // SKINCOLOR_SUPERRED4 + {0xd0, 0xd1, 0xd2, 0xd2, 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23, 0x24, 0x24, 0x25, 0x25}, // SKINCOLOR_SUPERRED5 + + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x30, 0x31, 0x32, 0x33, 0x34}, // SKINCOLOR_SUPERORANGE1 + {0x00, 0x00, 0x00, 0x00, 0xd0, 0xd0, 0x30, 0x30, 0x31, 0x31, 0x32, 0x32, 0x33, 0x33, 0x34, 0x34}, // SKINCOLOR_SUPERORANGE2 + {0x00, 0x00, 0xd0, 0xd0, 0x30, 0x30, 0x31, 0x31, 0x32, 0x32, 0x33, 0x33, 0x34, 0x34, 0x35, 0x35}, // SKINCOLOR_SUPERORANGE3 + {0x00, 0xd0, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x44, 0x45, 0x46}, // SKINCOLOR_SUPERORANGE4 + {0xd0, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x44, 0x45, 0x46, 0x47}, // SKINCOLOR_SUPERORANGE5 + + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x50, 0x51, 0x52, 0x53, 0x48}, // SKINCOLOR_SUPERGOLD1 + {0x00, 0x50, 0x51, 0x52, 0x53, 0x53, 0x48, 0x48, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x40, 0x41}, // SKINCOLOR_SUPERGOLD2 + {0x51, 0x52, 0x53, 0x53, 0x48, 0x48, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x40, 0x41, 0x42, 0x43}, // SKINCOLOR_SUPERGOLD3 + {0x53, 0x48, 0x48, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46}, // SKINCOLOR_SUPERGOLD4 + {0x48, 0x48, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47}, // SKINCOLOR_SUPERGOLD5 + + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x58, 0x58, 0xbc, 0xbc, 0xbc}, // SKINCOLOR_SUPERPERIDOT1 + {0x00, 0x58, 0x58, 0x58, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe}, // SKINCOLOR_SUPERPERIDOT2 + {0x58, 0x58, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbf, 0xbf}, // SKINCOLOR_SUPERPERIDOT3 + {0x58, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbf, 0xbf, 0x5e, 0x5e, 0x5f}, // SKINCOLOR_SUPERPERIDOT4 + {0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbf, 0xbf, 0x5e, 0x5e, 0x5f, 0x77}, // SKINCOLOR_SUPERPERIDOT5 + + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x81, 0x82, 0x83, 0x84}, // SKINCOLOR_SUPERSKY1 + {0x00, 0x80, 0x81, 0x82, 0x83, 0x83, 0x84, 0x84, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x86, 0x86}, // SKINCOLOR_SUPERSKY2 + {0x81, 0x82, 0x83, 0x83, 0x84, 0x84, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x86, 0x86, 0x87, 0x87}, // SKINCOLOR_SUPERSKY3 + {0x83, 0x84, 0x84, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x86, 0x86, 0x87, 0x87, 0x88, 0x89, 0x8a}, // SKINCOLOR_SUPERSKY4 + {0x84, 0x84, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x86, 0x86, 0x87, 0x87, 0x88, 0x89, 0x8a, 0x8b}, // SKINCOLOR_SUPERSKY5 + + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90, 0xa0, 0xa0, 0xa1, 0xa2}, // SKINCOLOR_SUPERPURPLE1 + {0x00, 0x90, 0xa0, 0xa0, 0xa1, 0xa1, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4, 0xa5, 0xa5}, // SKINCOLOR_SUPERPURPLE2 + {0xa0, 0xa0, 0xa1, 0xa1, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4, 0xa5, 0xa5, 0xa6, 0xa6}, // SKINCOLOR_SUPERPURPLE3 + {0xa1, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4, 0xa5, 0xa5, 0xa6, 0xa6, 0xa7, 0xa8, 0xa9}, // SKINCOLOR_SUPERPURPLE4 + {0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4, 0xa5, 0xa5, 0xa6, 0xa6, 0xa7, 0xa8, 0xa9, 0xfd}, // SKINCOLOR_SUPERPURPLE5 + + {0x00, 0xd0, 0xd0, 0xd0, 0x30, 0x30, 0x31, 0x32, 0x33, 0x37, 0x3a, 0x44, 0x45, 0x46, 0x47, 0x2e}, // SKINCOLOR_SUPERRUST1 + {0x30, 0x31, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x38, 0x3a, 0x44, 0x45, 0x46, 0x47, 0x47, 0x2e}, // SKINCOLOR_SUPERRUST2 + {0x31, 0x32, 0x33, 0x34, 0x36, 0x37, 0x38, 0x3a, 0x44, 0x45, 0x45, 0x46, 0x46, 0x47, 0x2e, 0x2e}, // SKINCOLOR_SUPERRUST3 + {0x48, 0x40, 0x41, 0x42, 0x43, 0x44, 0x44, 0x45, 0x45, 0x46, 0x46, 0x47, 0x47, 0x2e, 0x2e, 0x2e}, // SKINCOLOR_SUPERRUST4 + {0x41, 0x42, 0x43, 0x43, 0x44, 0x44, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xed, 0xee, 0xee, 0xef, 0xef}, // SKINCOLOR_SUPERRUST5 + + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x50, 0x51, 0x51, 0x52, 0x52}, // SKINCOLOR_SUPERTAN1 + {0x00, 0x50, 0x50, 0x51, 0x51, 0x52, 0x52, 0x52, 0x54, 0x54, 0x54, 0x54, 0x55, 0x56, 0x57, 0xf5}, // SKINCOLOR_SUPERTAN2 + {0x50, 0x51, 0x51, 0x52, 0x52, 0x52, 0x54, 0x54, 0x54, 0x54, 0x55, 0x56, 0x57, 0xf5, 0xf7, 0xf9}, // SKINCOLOR_SUPERTAN3 + {0x51, 0x52, 0x52, 0x52, 0x52, 0x54, 0x54, 0x54, 0x55, 0x56, 0x57, 0xf5, 0xf7, 0xf9, 0xfb, 0xed}, // SKINCOLOR_SUPERTAN4 + {0x52, 0x52, 0x54, 0x54, 0x54, 0x55, 0x56, 0x57, 0xf5, 0xf7, 0xf9, 0xfb, 0xed, 0xee, 0xef, 0xef} // SKINCOLOR_SUPERTAN5 +}; // See also the enum skincolors_t // TODO Callum: Can this be translated? const char *Color_Names[MAXSKINCOLORS + NUMSUPERCOLORS] = { - "None", // SKINCOLOR_NONE - "White", // SKINCOLOR_WHITE - "Silver", // SKINCOLOR_SILVER - "Grey", // SKINCOLOR_GREY - "Black", // SKINCOLOR_BLACK - "Beige", // SKINCOLOR_BEIGE - "Peach", // SKINCOLOR_PEACH - "Brown", // SKINCOLOR_BROWN - "Red", // SKINCOLOR_RED - "Crimson", // SKINCOLOR_CRIMSON - "Orange", // SKINCOLOR_ORANGE - "Rust", // SKINCOLOR_RUST - "Gold", // SKINCOLOR_GOLD - "Yellow", // SKINCOLOR_YELLOW - "Tan", // SKINCOLOR_TAN - "Moss", // SKINCOLOR_MOSS - "Peridot", // SKINCOLOR_PERIDOT - "Green", // SKINCOLOR_GREEN - "Emerald", // SKINCOLOR_EMERALD - "Aqua", // SKINCOLOR_AQUA - "Teal", // SKINCOLOR_TEAL - "Cyan", // SKINCOLOR_CYAN - "Blue", // SKINCOLOR_BLUE - "Azure", // SKINCOLOR_AZURE - "Pastel", // SKINCOLOR_PASTEL - "Purple", // SKINCOLOR_PURPLE - "Lavender", // SKINCOLOR_LAVENDER - "Magenta", // SKINCOLOR_MAGENTA - "Pink", // SKINCOLOR_PINK - "Rosy", // SKINCOLOR_ROSY + "None", // SKINCOLOR_NONE, + + // Greyscale ranges + "White", // SKINCOLOR_WHITE, + "Bone", // SKINCOLOR_BONE, + "Cloudy", // SKINCOLOR_CLOUDY, + "Grey", // SKINCOLOR_GREY, + "Silver", // SKINCOLOR_SILVER, + "Carbon", // SKINCOLOR_CARBON, + "Jet", // SKINCOLOR_JET, + "Black", // SKINCOLOR_BLACK, + + // Desaturated + "Aether", // SKINCOLOR_AETHER, + "Slate", // SKINCOLOR_SLATE, + "Pink", // SKINCOLOR_PINK, + "Yogurt", // SKINCOLOR_YOGURT, + "Brown", // SKINCOLOR_BROWN, + "Tan", // SKINCOLOR_TAN, + "Beige", // SKINCOLOR_BEIGE, + "Moss", // SKINCOLOR_MOSS, + "Azure", // SKINCOLOR_AZURE, + "Lavender", // SKINCOLOR_LAVENDER, + + // Viv's vivid colours (toast 21/07/17) + "Ruby", // SKINCOLOR_RUBY, + "Salmon", // SKINCOLOR_SALMON, + "Red", // SKINCOLOR_RED, + "Crimson", // SKINCOLOR_CRIMSON, + "Flame", // SKINCOLOR_FLAME, + "Peachy", // SKINCOLOR_PEACHY, + "Quail", // SKINCOLOR_QUAIL, + "Sunset", // SKINCOLOR_SUNSET, + "Apricot", // SKINCOLOR_APRICOT, + "Orange", // SKINCOLOR_ORANGE, + "Rust", // SKINCOLOR_RUST, + "Gold", // SKINCOLOR_GOLD, + "Sandy", // SKINCOLOR_SANDY, + "Yellow", // SKINCOLOR_YELLOW, + "Olive", // SKINCOLOR_OLIVE, + "Lime", // SKINCOLOR_LIME, + "Peridot", // SKINCOLOR_PERIDOT, + "Green", // SKINCOLOR_GREEN, + "Forest", // SKINCOLOR_FOREST, + "Emerald", // SKINCOLOR_EMERALD, + "Mint", // SKINCOLOR_MINT, + "Seafoam", // SKINCOLOR_SEAFOAM, + "Aqua", // SKINCOLOR_AQUA, + "Teal", // SKINCOLOR_TEAL, + "Wave", // SKINCOLOR_WAVE, + "Cyan", // SKINCOLOR_CYAN, + "Sky", // SKINCOLOR_SKY, + "Cerulean", // SKINCOLOR_CERULEAN, + "Icy", // SKINCOLOR_ICY, + "Sapphire", // SKINCOLOR_SAPPHIRE, + "Cornflower", // SKINCOLOR_CORNFLOWER, + "Blue", // SKINCOLOR_BLUE, + "Cobalt", // SKINCOLOR_COBALT, + "Vapor", // SKINCOLOR_VAPOR, + "Dusk", // SKINCOLOR_DUSK, + "Pastel", // SKINCOLOR_PASTEL, + "Purple", // SKINCOLOR_PURPLE, + "Bubblegum", // SKINCOLOR_BUBBLEGUM, + "Magenta", // SKINCOLOR_MAGENTA, + "Neon", // SKINCOLOR_NEON, + "Violet", // SKINCOLOR_VIOLET, + "Lilac", // SKINCOLOR_LILAC, + "Plum", // SKINCOLOR_PLUM, + "Rosy", // SKINCOLOR_ROSY, + // Super behaves by different rules (one name per 5 colours), and will be accessed exclusively via R_GetSuperColorByName instead of R_GetColorByName. - "Silver", // SKINCOLOR_SUPERSILVER1 - "Red", // SKINCOLOR_SUPERRED1 - "Orange", // SKINCOLOR_SUPERORANGE1 - "Gold", // SKINCOLOR_SUPERGOLD1 - "Peridot", // SKINCOLOR_SUPERPERIDOT1 - "Cyan", // SKINCOLOR_SUPERCYAN1 - "Purple", // SKINCOLOR_SUPERPURPLE1 - "Rust", // SKINCOLOR_SUPERRUST1 - "Tan" // SKINCOLOR_SUPERTAN1 + "Silver", // SKINCOLOR_SUPERSILVER1, + "Red", // SKINCOLOR_SUPERRED1, + "Orange", // SKINCOLOR_SUPERORANGE1, + "Gold", // SKINCOLOR_SUPERGOLD1, + "Peridot", // SKINCOLOR_SUPERPERIDOT1, + "Sky", // SKINCOLOR_SUPERSKY1, + "Purple", // SKINCOLOR_SUPERPURPLE1, + "Rust", // SKINCOLOR_SUPERRUST1, + "Tan" // SKINCOLOR_SUPERTAN1, }; /* A word of warning: If the following array is non-symmetrical, A_SignPlayer's prefoppositecolor behaviour will break. */ -const UINT8 Color_Opposite[MAXSKINCOLORS*2] = +const UINT8 Color_Opposite[(MAXSKINCOLORS - 1)*2] = { - SKINCOLOR_NONE,8, // SKINCOLOR_NONE - SKINCOLOR_BLACK,10, // SKINCOLOR_WHITE - SKINCOLOR_GREY,4, // SKINCOLOR_SILVER - SKINCOLOR_SILVER,12, // SKINCOLOR_GREY - SKINCOLOR_WHITE,8, // SKINCOLOR_BLACK - SKINCOLOR_BEIGE,8, // SKINCOLOR_BEIGE - needs new offset - SKINCOLOR_BROWN,8, // SKINCOLOR_PEACH - ditto - SKINCOLOR_PEACH,8, // SKINCOLOR_BROWN - ditto - SKINCOLOR_GREEN,5, // SKINCOLOR_RED - SKINCOLOR_CYAN,8, // SKINCOLOR_CRIMSON - ditto - SKINCOLOR_BLUE,11, // SKINCOLOR_ORANGE - SKINCOLOR_TAN,8, // SKINCOLOR_RUST - ditto - SKINCOLOR_LAVENDER,8, // SKINCOLOR_GOLD - SKINCOLOR_TEAL,8, // SKINCOLOR_YELLOW - ditto - SKINCOLOR_RUST,8, // SKINCOLOR_TAN - ditto - SKINCOLOR_MAGENTA,3, // SKINCOLOR_MOSS - SKINCOLOR_PURPLE,8, // SKINCOLOR_PERIDOT - ditto - SKINCOLOR_RED,11, // SKINCOLOR_GREEN - SKINCOLOR_PASTEL,8, // SKINCOLOR_EMERALD - ditto - SKINCOLOR_ROSY,8, // SKINCOLOR_AQUA - ditto - SKINCOLOR_YELLOW,8, // SKINCOLOR_TEAL - ditto - SKINCOLOR_CRIMSON,8, // SKINCOLOR_CYAN - ditto - SKINCOLOR_ORANGE,9, // SKINCOLOR_BLUE - SKINCOLOR_PINK,8, // SKINCOLOR_AZURE - ditto - SKINCOLOR_EMERALD,8, // SKINCOLOR_PASTEL - ditto - SKINCOLOR_PERIDOT,10, // SKINCOLOR_PURPLE - SKINCOLOR_GOLD,10, // SKINCOLOR_LAVENDER - SKINCOLOR_MOSS,8, // SKINCOLOR_MAGENTA - ditto - SKINCOLOR_AZURE,8, // SKINCOLOR_PINK - ditto - SKINCOLOR_AQUA,14 // SKINCOLOR_ROSY + // SKINCOLOR_NONE,8, // SKINCOLOR_NONE + + // Greyscale ranges + SKINCOLOR_BLACK,5, // SKINCOLOR_WHITE, + SKINCOLOR_JET,7, // SKINCOLOR_BONE, + SKINCOLOR_CARBON,7, // SKINCOLOR_CLOUDY, + SKINCOLOR_AETHER,12, // SKINCOLOR_GREY, + SKINCOLOR_SLATE,12, // SKINCOLOR_SILVER, + SKINCOLOR_CLOUDY,7, // SKINCOLOR_CARBON, + SKINCOLOR_BONE,7, // SKINCOLOR_JET, + SKINCOLOR_WHITE,7, // SKINCOLOR_BLACK, + + // Desaturated + SKINCOLOR_GREY,15, // SKINCOLOR_AETHER, + SKINCOLOR_SILVER,12, // SKINCOLOR_SLATE, + SKINCOLOR_AZURE,9, // SKINCOLOR_PINK, + SKINCOLOR_RUST,7, // SKINCOLOR_YOGURT, + SKINCOLOR_TAN,2, // SKINCOLOR_BROWN, + SKINCOLOR_BROWN,12, // SKINCOLOR_TAN, + SKINCOLOR_MOSS,5, // SKINCOLOR_BEIGE, + SKINCOLOR_BEIGE,13, // SKINCOLOR_MOSS, + SKINCOLOR_PINK,5, // SKINCOLOR_AZURE, + SKINCOLOR_GOLD,4, // SKINCOLOR_LAVENDER, + + // Viv's vivid colours (toast 21/07/17) + SKINCOLOR_EMERALD,10, // SKINCOLOR_RUBY, + SKINCOLOR_FOREST,6, // SKINCOLOR_SALMON, + SKINCOLOR_GREEN,10, // SKINCOLOR_RED, + SKINCOLOR_ICY,10, // SKINCOLOR_CRIMSON, + SKINCOLOR_PURPLE,8, // SKINCOLOR_FLAME, + SKINCOLOR_TEAL,7, // SKINCOLOR_PEACHY, + SKINCOLOR_WAVE,5, // SKINCOLOR_QUAIL, + SKINCOLOR_SAPPHIRE,5, // SKINCOLOR_SUNSET, + SKINCOLOR_CYAN,4, // SKINCOLOR_APRICOT, + SKINCOLOR_BLUE,4, // SKINCOLOR_ORANGE, + SKINCOLOR_YOGURT,8, // SKINCOLOR_RUST, + SKINCOLOR_LAVENDER,10, // SKINCOLOR_GOLD, + SKINCOLOR_SKY,8, // SKINCOLOR_SANDY, + SKINCOLOR_CORNFLOWER,8, // SKINCOLOR_YELLOW, + SKINCOLOR_DUSK,3, // SKINCOLOR_OLIVE, + SKINCOLOR_MAGENTA,9, // SKINCOLOR_LIME, + SKINCOLOR_COBALT,2, // SKINCOLOR_PERIDOT, + SKINCOLOR_RED,6, // SKINCOLOR_GREEN, + SKINCOLOR_SALMON,9, // SKINCOLOR_FOREST, + SKINCOLOR_RUBY,4, // SKINCOLOR_EMERALD, + SKINCOLOR_VIOLET,5, // SKINCOLOR_MINT, + SKINCOLOR_PLUM,6, // SKINCOLOR_SEAFOAM, + SKINCOLOR_ROSY,7, // SKINCOLOR_AQUA, + SKINCOLOR_PEACHY,7, // SKINCOLOR_TEAL, + SKINCOLOR_QUAIL,5, // SKINCOLOR_WAVE, + SKINCOLOR_APRICOT,6, // SKINCOLOR_CYAN, + SKINCOLOR_SANDY,1, // SKINCOLOR_SKY, + SKINCOLOR_NEON,4, // SKINCOLOR_CERULEAN, + SKINCOLOR_CRIMSON,0, // SKINCOLOR_ICY, + SKINCOLOR_SUNSET,5, // SKINCOLOR_SAPPHIRE, + SKINCOLOR_YELLOW,4, // SKINCOLOR_CORNFLOWER, + SKINCOLOR_ORANGE,5, // SKINCOLOR_BLUE, + SKINCOLOR_PERIDOT,5, // SKINCOLOR_COBALT, + SKINCOLOR_LILAC,4, // SKINCOLOR_VAPOR, + SKINCOLOR_OLIVE,0, // SKINCOLOR_DUSK, + SKINCOLOR_BUBBLEGUM,9, // SKINCOLOR_PASTEL, + SKINCOLOR_FLAME,7, // SKINCOLOR_PURPLE, + SKINCOLOR_PASTEL,8, // SKINCOLOR_BUBBLEGUM, + SKINCOLOR_LIME,6, // SKINCOLOR_MAGENTA, + SKINCOLOR_CERULEAN,2, // SKINCOLOR_NEON, + SKINCOLOR_MINT,6, // SKINCOLOR_VIOLET, + SKINCOLOR_VAPOR,4, // SKINCOLOR_LILAC, + SKINCOLOR_MINT,7, // SKINCOLOR_PLUM, + SKINCOLOR_AQUA,1 // SKINCOLOR_ROSY, }; CV_PossibleValue_t Color_cons_t[MAXSKINCOLORS+1]; @@ -258,40 +464,7 @@ void R_InitTranslationTables(void) */ static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, UINT8 color) { - // Table of indices into the palette of the first entries of each translated ramp - const UINT8 skinbasecolors[] = { - 0x00, // SKINCOLOR_WHITE - 0x03, // SKINCOLOR_SILVER - 0x08, // SKINCOLOR_GREY - 0x18, // SKINCOLOR_BLACK - 0xf0, // SKINCOLOR_BEIGE - 0xd8, // SKINCOLOR_PEACH - 0xe0, // SKINCOLOR_BROWN - 0x21, // SKINCOLOR_RED - 0x28, // SKINCOLOR_CRIMSON - 0x31, // SKINCOLOR_ORANGE - 0x3a, // SKINCOLOR_RUST - 0x40, // SKINCOLOR_GOLD - 0x48, // SKINCOLOR_YELLOW - 0x54, // SKINCOLOR_TAN - 0x58, // SKINCOLOR_MOSS - 0xbc, // SKINCOLOR_PERIDOT - 0x60, // SKINCOLOR_GREEN - 0x70, // SKINCOLOR_EMERALD - 0x78, // SKINCOLOR_AQUA - 0x8c, // SKINCOLOR_TEAL - 0x80, // SKINCOLOR_CYAN - 0x92, // SKINCOLOR_BLUE - 0xaa, // SKINCOLOR_AZURE - 0xa0, // SKINCOLOR_PASTEL - 0xa0, // SKINCOLOR_PURPLE - 0xc0, // SKINCOLOR_LAVENDER - 0xb3, // SKINCOLOR_MAGENTA - 0xd0, // SKINCOLOR_PINK - 0xc8, // SKINCOLOR_ROSY - }; - INT32 i; - INT32 starttranscolor; + INT32 i, starttranscolor, skinramplength; // Handle a couple of simple special cases if (skinnum == TC_BOSS || skinnum == TC_ALLWHITE || skinnum == TC_METALSONIC || color == SKINCOLOR_NONE) @@ -311,776 +484,28 @@ static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, U return; } + if (color >= MAXTRANSLATIONS) + I_Error("Invalid skin color #%hu.", (UINT16)color); + starttranscolor = (skinnum != TC_DEFAULT) ? skins[skinnum].starttranscolor : DEFAULT_STARTTRANSCOLOR; // Fill in the entries of the palette that are fixed for (i = 0; i < starttranscolor; i++) dest_colormap[i] = (UINT8)i; - for (i = (UINT8)(starttranscolor + 16); i < NUM_PALETTE_ENTRIES; i++) - dest_colormap[i] = (UINT8)i; + i = starttranscolor + 16; + if (i < NUM_PALETTE_ENTRIES) + { + for (i = (UINT8)i; i < NUM_PALETTE_ENTRIES; i++) + dest_colormap[i] = (UINT8)i; + skinramplength = 16; + } + else + skinramplength = i - NUM_PALETTE_ENTRIES; // Build the translated ramp - switch (color) - { - case SKINCOLOR_SILVER: - case SKINCOLOR_GREY: - case SKINCOLOR_BROWN: - case SKINCOLOR_GREEN: - // 16 color ramp - for (i = 0; i < SKIN_RAMP_LENGTH; i++) - dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + i); - break; - - case SKINCOLOR_WHITE: - case SKINCOLOR_CYAN: - // 12 color ramp - for (i = 0; i < SKIN_RAMP_LENGTH; i++) - dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + (12*i/SKIN_RAMP_LENGTH)); - break; - - case SKINCOLOR_BLACK: - case SKINCOLOR_MOSS: - case SKINCOLOR_EMERALD: - case SKINCOLOR_LAVENDER: - case SKINCOLOR_PINK: - // 8 color ramp - for (i = 0; i < SKIN_RAMP_LENGTH; i++) - dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + (i >> 1)); - break; - - case SKINCOLOR_BEIGE: - // 13 colors - for (i = 0; i < SKIN_RAMP_LENGTH; i++) - { - if (i == 15) - dest_colormap[starttranscolor + i] = 0xed; // Darkest - else if (i <= 6) - dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + ((i + 1) >> 1)); // Brightest - else - dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + i - 3); - } - break; - - case SKINCOLOR_PEACH: - // 11 colors - for (i = 0; i < SKIN_RAMP_LENGTH; i++) - { - if (i == 0) - dest_colormap[starttranscolor + i] = 0xD0; // Lightest 1 - else if (i == 1) - dest_colormap[starttranscolor + i] = 0x30; // Lightest 2 - else if (i <= 11) - dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + (i >> 1) - 1); - else - dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + i - 7); // Darkest - } - break; - - case SKINCOLOR_RED: - // 16 colors - for (i = 0; i < SKIN_RAMP_LENGTH; i++) - { - if (i == 13) - dest_colormap[starttranscolor + i] = 0x47; // Semidark - else if (i > 13) - dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + i - 1); // Darkest - else - dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + i); - } - break; - - case SKINCOLOR_CRIMSON: - // 9 colors - for (i = 0; i < SKIN_RAMP_LENGTH; i++) - { - if (i/2 == 6) - dest_colormap[starttranscolor + i] = 0x47; // Semidark - else if (i/2 == 7) - dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + i - 8); // Darkest - else - dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + (i >> 1)); - } - break; - - case SKINCOLOR_ORANGE: - for (i = 0; i < SKIN_RAMP_LENGTH; i++) - { - if (i == 15) - dest_colormap[starttranscolor + i] = 0x2c; // Darkest - else - dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + i); - } - break; - - case SKINCOLOR_RUST: - // 10 colors - for (i = 0; i < SKIN_RAMP_LENGTH; i++) - { - if (i <= 11) - dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + (i >> 1)); - else if (i == 12) - dest_colormap[starttranscolor + i] = 0x2c; - else if (i <= 14) - dest_colormap[starttranscolor + i] = 0x2d; - else - dest_colormap[starttranscolor + i] = 0x48; - } - break; - - case SKINCOLOR_GOLD: - // 10 colors - for (i = 0; i < SKIN_RAMP_LENGTH; i++) - { - if (i == 0) - dest_colormap[starttranscolor + i] = 0x50; // Lightest 1 - else if (i == 1) - dest_colormap[starttranscolor + i] = 0x53; // Lightest 2 - else if (i/2 == 7) - dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + i - 8); //Darkest - else - dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + (i >> 1) - 1); - } - break; - - case SKINCOLOR_YELLOW: - // 10 colors - for (i = 0; i < SKIN_RAMP_LENGTH; i++) - { - if (i == 0) - dest_colormap[starttranscolor + i] = 0x53; // Lightest - else if (i == 15) - dest_colormap[starttranscolor + i] = 0xed; // Darkest - else - dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + (i >> 1)); - } - break; - - case SKINCOLOR_TAN: - // 8 colors - for (i = 0; i < SKIN_RAMP_LENGTH; i++) - { - if (i/2 == 0) - dest_colormap[starttranscolor + i] = 0x51; // Lightest - else if (i/2 == 5) - dest_colormap[starttranscolor + i] = 0xf5; // Darkest 1 - else if (i/2 == 6) - dest_colormap[starttranscolor + i] = 0xf9; // Darkest 2 - else if (i/2 == 7) - dest_colormap[starttranscolor + i] = 0xed; // Darkest 3 - else - dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + (i >> 1) - 1); - } - break; - - case SKINCOLOR_PERIDOT: - // 8 colors - for (i = 0; i < SKIN_RAMP_LENGTH; i++) - { - if (i/2 == 0) - dest_colormap[starttranscolor + i] = 0x58; // Lightest - else if (i/2 == 7) - dest_colormap[starttranscolor + i] = 0x77; // Darkest - else if (i/2 >= 5) - dest_colormap[starttranscolor + i] = (UINT8)(0x5e + (i >> 1) - 5); // Semidark - else - dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + (i >> 1) - 1); - } - break; - - case SKINCOLOR_AQUA: - // 10 colors - for (i = 0; i < SKIN_RAMP_LENGTH; i++) - { - if (i == 0) - dest_colormap[starttranscolor + i] = 0x78; // Lightest - else if (i >= 14) - dest_colormap[starttranscolor + i] = (UINT8)(0x76 + i - 14); // Darkest - else - dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + (i >> 1) + 1); - } - break; - - case SKINCOLOR_TEAL: - // 6 colors - for (i = 0; i < SKIN_RAMP_LENGTH; i++) - { - if (i <= 1) - dest_colormap[starttranscolor + i] = 0x78; // Lightest - else if (i >= 13) - dest_colormap[starttranscolor + i] = 0x8a; // Darkest - else - dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + ((i - 1)/3)); - } - break; - - case SKINCOLOR_AZURE: - // 8 colors - for (i = 0; i < SKIN_RAMP_LENGTH; i++) - { - if (i <= 3) - dest_colormap[starttranscolor + i] = (UINT8)(0x90 + i/2); // Lightest - else - dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + (i >> 1) - 2); - } - break; - - case SKINCOLOR_BLUE: - // 16 colors - for (i = 0; i < SKIN_RAMP_LENGTH; i++) - { - if (i == 15) - dest_colormap[starttranscolor + i] = 0xfe; //Darkest 1 - else if (i == 14) - dest_colormap[starttranscolor + i] = 0xfd; //Darkest 2 - else - dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + i); - } - break; - - case SKINCOLOR_PASTEL: - // 10 colors - for (i = 0; i < SKIN_RAMP_LENGTH; i++) - { - if (i >= 12) - dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + i - 7); // Darkest - else if (i <= 1) - dest_colormap[starttranscolor + i] = 0x90; // Lightest - else - dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + (i >> 1) - 1); - } - break; - - case SKINCOLOR_PURPLE: - // 10 colors - for (i = 0; i < SKIN_RAMP_LENGTH; i++) - { - if (i <= 3) - dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + i); // Lightest - else - dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + (i >> 1) + 2); - } - break; - - case SKINCOLOR_MAGENTA: - // 9 colors - for (i = 0; i < SKIN_RAMP_LENGTH; i++) - if (i == 0) - dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1]); // Lightest - else - dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + (i >> 1) + 1); - break; - - case SKINCOLOR_ROSY: - // 9 colors - for (i = 0; i < SKIN_RAMP_LENGTH; i++) - { - if (i == 0) - dest_colormap[starttranscolor + i] = 0xfc; // Lightest - else - dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + ((i - 1) >> 1)); - } - break; - - // Super colors, from lightest to darkest! - - // Super silvers. - case SKINCOLOR_SUPERSILVER1: - for (i = 0; i < 12; i++) - dest_colormap[starttranscolor + i] = (UINT8)0; - for (; i < 14; i++) - dest_colormap[starttranscolor + i] = (UINT8)1; - for (; i < 16; i++) - dest_colormap[starttranscolor + i] = (UINT8)(i-12); - break; - - case SKINCOLOR_SUPERSILVER2: - for (i = 0; i < 3; i++) - dest_colormap[starttranscolor + i] = (UINT8)(i); - dest_colormap[starttranscolor + (i++)] = (UINT8)2; - for (; i < 8; i++) - dest_colormap[starttranscolor + i] = (UINT8)3; - for (; i < 14; i++) - dest_colormap[starttranscolor + i] = (UINT8)4; - for (; i < 16; i++) - dest_colormap[starttranscolor + i] = (UINT8)(i-9); - break; - - case SKINCOLOR_SUPERSILVER3: - dest_colormap[starttranscolor] = (UINT8)1; - for (i = 1; i < 3; i++) - dest_colormap[starttranscolor + i] = (UINT8)2; - for (; i < 6; i++) - dest_colormap[starttranscolor + i] = (UINT8)3; - for (; i < 12; i++) - dest_colormap[starttranscolor + i] = (UINT8)4; - for (; i < 16; i++) - dest_colormap[starttranscolor + i] = (UINT8)(5 + ((i-12)*2)); - break; - - case SKINCOLOR_SUPERSILVER4: - dest_colormap[starttranscolor] = (UINT8)2; - for (i = 1; i < 3; i++) - dest_colormap[starttranscolor + i] = (UINT8)3; - for (; i < 9; i++) - dest_colormap[starttranscolor + i] = (UINT8)4; - for (; i < 16; i++) - dest_colormap[starttranscolor + i] = (UINT8)(5 + ((i-9)*2)); - break; - - case SKINCOLOR_SUPERSILVER5: - for (i = 0; i < 2; i++) - dest_colormap[starttranscolor + i] = (UINT8)3; - for (; i < 8; i++) - dest_colormap[starttranscolor + i] = (UINT8)4; - for (; i < 16; i++) - dest_colormap[starttranscolor + i] = (UINT8)(5 + ((i-8)*2)); - break; - - // Super reds. - case SKINCOLOR_SUPERRED1: - for (i = 0; i < 10; i++) - dest_colormap[starttranscolor + i] = (UINT8)0; - for (; i < 16; i++) - dest_colormap[starttranscolor + i] = (UINT8)(208 + ((i-10) >> 1)); - break; - - case SKINCOLOR_SUPERRED2: - for (i = 0; i < 3; i++) - dest_colormap[starttranscolor + i] = (UINT8)0; - for (; i < 12; i++) - dest_colormap[starttranscolor + i] = (UINT8)(208 + ((i-3) / 3)); - for (; i < 16; i++) - dest_colormap[starttranscolor + i] = (UINT8)(32 + ((i-12) >> 1)); - break; - - case SKINCOLOR_SUPERRED3: - for (i = 0; i < 2; i++) - dest_colormap[starttranscolor + i] = (UINT8)0; - for (; i < 8; i++) - dest_colormap[starttranscolor + i] = (UINT8)(208 + ((i-2) >> 1)); - for (; i < 16; i++) - dest_colormap[starttranscolor + i] = (UINT8)(32 + ((i-8) >> 1)); - break; - - case SKINCOLOR_SUPERRED4: - dest_colormap[starttranscolor] = (UINT8)0; - for (i = 1; i < 6; i++) - dest_colormap[starttranscolor + i] = (UINT8)(208 + (i >> 1)); - for (; i < 16; i++) - dest_colormap[starttranscolor + i] = (UINT8)(32 + ((i-6) >> 1)); - break; - - case SKINCOLOR_SUPERRED5: - dest_colormap[starttranscolor] = (UINT8)208; - for (i = 1; i < 4; i++) - dest_colormap[starttranscolor + i] = (UINT8)(209 + (i >> 1)); - for (; i < 16; i++) - dest_colormap[starttranscolor + i] = (UINT8)(32 + ((i-4) >> 1)); - break; - - // Super oranges. - case SKINCOLOR_SUPERORANGE1: - for (i = 0; i < 10; i++) - dest_colormap[starttranscolor + i] = (UINT8)0; - dest_colormap[starttranscolor + (i++)] = (UINT8)208; - for (; i < 16; i++) - dest_colormap[starttranscolor + i] = (UINT8)(48 + (i-11)); - break; - - case SKINCOLOR_SUPERORANGE2: - for (i = 0; i < 4; i++) - dest_colormap[starttranscolor + i] = (UINT8)0; - for (; i < 6; i++) - dest_colormap[starttranscolor + i] = (UINT8)208; - for (; i < 16; i++) - dest_colormap[starttranscolor + i] = (UINT8)(48 + ((i-6) >> 1)); - break; - - case SKINCOLOR_SUPERORANGE3: - for (i = 0; i < 2; i++) - dest_colormap[starttranscolor + i] = (UINT8)0; - for (; i < 4; i++) - dest_colormap[starttranscolor + i] = (UINT8)208; - for (; i < 16; i++) - dest_colormap[starttranscolor + i] = (UINT8)(48 + ((i-4) >> 1)); - break; - - case SKINCOLOR_SUPERORANGE4: - dest_colormap[starttranscolor] = (UINT8)0; - dest_colormap[starttranscolor + 1] = (UINT8)208; - for (i = 2; i < 13; i++) - dest_colormap[starttranscolor + i] = (UINT8)(48 + (i-2)); - for (; i < 16; i++) - dest_colormap[starttranscolor + i] = (UINT8)(68 + (i-13)); - break; - - case SKINCOLOR_SUPERORANGE5: - dest_colormap[starttranscolor] = (UINT8)208; - for (i = 1; i < 12; i++) - dest_colormap[starttranscolor + i] = (UINT8)(48 + (i-1)); - for (; i < 16; i++) - dest_colormap[starttranscolor + i] = (UINT8)(68 + (i-12)); - break; - - // Super golds. - case SKINCOLOR_SUPERGOLD1: - for (i = 0; i < 10; i++) - dest_colormap[starttranscolor + i] = (UINT8)0; // True white - for (; i < 12; i++) // White-yellow fade - dest_colormap[starttranscolor + i] = (UINT8)80; - for (; i < 15; i++) // White-yellow fade - dest_colormap[starttranscolor + i] = (UINT8)(81 + (i-12)); - dest_colormap[starttranscolor + 15] = (UINT8)72; - break; - - case SKINCOLOR_SUPERGOLD2: - dest_colormap[starttranscolor] = (UINT8)(0); - for (i = 1; i < 4; i++) // White-yellow fade - dest_colormap[starttranscolor + i] = (UINT8)(80 + (i-1)); - for (; i < 6; i++) // Yellow - dest_colormap[starttranscolor + i] = (UINT8)83; - for (; i < 8; i++) // Yellow - dest_colormap[starttranscolor + i] = (UINT8)72; - for (; i < 14; i++) // Yellow - dest_colormap[starttranscolor + i] = (UINT8)73; - for (; i < 16; i++) // With a fine golden finish! :3 - dest_colormap[starttranscolor + i] = (UINT8)(64 + (i-14)); - break; - - case SKINCOLOR_SUPERGOLD3: - for (i = 0; i < 2; i++) // White-yellow fade - dest_colormap[starttranscolor + i] = (UINT8)(81 + i); - for (; i < 4; i++) - dest_colormap[starttranscolor + i] = (UINT8)83; - for (; i < 6; i++) // Yellow - dest_colormap[starttranscolor + i] = (UINT8)72; - for (; i < 12; i++) // Yellow - dest_colormap[starttranscolor + i] = (UINT8)73; - for (; i < 16; i++) // With a fine golden finish! :3 - dest_colormap[starttranscolor + i] = (UINT8)(64 + (i-12)); - break; - - case SKINCOLOR_SUPERGOLD4: // "The SSNTails" - dest_colormap[starttranscolor] = (UINT8)83; // Golden shine - for (i = 1; i < 3; i++) // Yellow - dest_colormap[starttranscolor + i] = (UINT8)(72); - for (; i < 9; i++) // Yellow - dest_colormap[starttranscolor + i] = (UINT8)(73); - for (; i < 16; i++) // With a fine golden finish! :3 - dest_colormap[starttranscolor + i] = (UINT8)(64 + (i-9)); - break; - - case SKINCOLOR_SUPERGOLD5: // Golden Delicious - for (i = 0; i < 2; i++) // Yellow - dest_colormap[starttranscolor + i] = (UINT8)(72); - for (; i < 8; i++) // Yellow - dest_colormap[starttranscolor + i] = (UINT8)(73); - for (; i < 16; i++) // With a fine golden finish! :3 - dest_colormap[starttranscolor + i] = (UINT8)(64 + (i-8)); - break; - - // Super peridots. (nyeheheheh) - case SKINCOLOR_SUPERPERIDOT1: - for (i = 0; i < 10; i++) - dest_colormap[starttranscolor + i] = (UINT8)0; - for (; i < 13; i++) - dest_colormap[starttranscolor + i] = (UINT8)88; - for (; i < 16; i++) - dest_colormap[starttranscolor + i] = (UINT8)188; - break; - - case SKINCOLOR_SUPERPERIDOT2: - dest_colormap[starttranscolor] = (UINT8)(0); - for (i = 1; i < 4; i++) - dest_colormap[starttranscolor + i] = (UINT8)88; - for (; i < 8; i++) - dest_colormap[starttranscolor + i] = (UINT8)188; - for (; i < 14; i++) - dest_colormap[starttranscolor + i] = (UINT8)189; - for (; i < 16; i++) - dest_colormap[starttranscolor + i] = (UINT8)190; - break; - - case SKINCOLOR_SUPERPERIDOT3: - for (i = 0; i < 2; i++) - dest_colormap[starttranscolor + i] = (UINT8)88; - for (; i < 6; i++) - dest_colormap[starttranscolor + i] = (UINT8)188; - for (; i < 12; i++) - dest_colormap[starttranscolor + i] = (UINT8)189; - for (; i < 16; i++) - dest_colormap[starttranscolor + i] = (UINT8)(190 + ((i-12) >> 1)); - break; - - case SKINCOLOR_SUPERPERIDOT4: - dest_colormap[starttranscolor] = (UINT8)88; - for (i = 1; i < 3; i++) - dest_colormap[starttranscolor + i] = (UINT8)188; - for (; i < 9; i++) - dest_colormap[starttranscolor + i] = (UINT8)189; - for (; i < 13; i++) - dest_colormap[starttranscolor + i] = (UINT8)(190 + ((i-9) >> 1)); - for (; i < 15; i++) - dest_colormap[starttranscolor + i] = (UINT8)94; - dest_colormap[starttranscolor + i] = (UINT8)95; - break; - - case SKINCOLOR_SUPERPERIDOT5: - for (i = 0; i < 2; i++) - dest_colormap[starttranscolor + i] = (UINT8)188; - for (; i < 8; i++) - dest_colormap[starttranscolor + i] = (UINT8)189; - for (; i < 12; i++) - dest_colormap[starttranscolor + i] = (UINT8)(190 + ((i-8) >> 1)); - for (; i < 14; i++) - dest_colormap[starttranscolor + i] = (UINT8)94; - dest_colormap[starttranscolor + (i++)] = (UINT8)95; - dest_colormap[starttranscolor + i] = (UINT8)119; - break; - - // Super cyans. - case SKINCOLOR_SUPERCYAN1: - for (i = 0; i < 10; i++) - dest_colormap[starttranscolor + i] = (UINT8)0; - for (; i < 12; i++) - dest_colormap[starttranscolor + i] = (UINT8)128; - for (; i < 16; i++) - dest_colormap[starttranscolor + i] = (UINT8)(129 + (i-12)); - break; - - case SKINCOLOR_SUPERCYAN2: - dest_colormap[starttranscolor] = (UINT8)0; - for (i = 1; i < 4; i++) - dest_colormap[starttranscolor + i] = (UINT8)(128 + (i-1)); - for (; i < 8; i++) - dest_colormap[starttranscolor + i] = (UINT8)(131 + ((i-4) >> 1)); - for (; i < 14; i++) - dest_colormap[starttranscolor + i] = (UINT8)133; - for (; i < 16; i++) - dest_colormap[starttranscolor + i] = (UINT8)134; - break; - - case SKINCOLOR_SUPERCYAN3: - for (i = 0; i < 2; i++) - dest_colormap[starttranscolor + i] = (UINT8)(129 + i); - for (; i < 6; i++) - dest_colormap[starttranscolor + i] = (UINT8)(131 + ((i-2) >> 1)); - for (; i < 12; i++) - dest_colormap[starttranscolor + i] = (UINT8)133; - for (; i < 16; i++) - dest_colormap[starttranscolor + i] = (UINT8)(134 + ((i-12) >> 1)); - break; - - case SKINCOLOR_SUPERCYAN4: - dest_colormap[starttranscolor] = (UINT8)131; - for (i = 1; i < 3; i++) - dest_colormap[starttranscolor + i] = (UINT8)132; - for (; i < 9; i++) - dest_colormap[starttranscolor + i] = (UINT8)133; - for (; i < 13; i++) - dest_colormap[starttranscolor + i] = (UINT8)(134 + ((i-9) >> 1)); - for (; i < 16; i++) - dest_colormap[starttranscolor + i] = (UINT8)(136 + (i-13)); - break; - - case SKINCOLOR_SUPERCYAN5: - for (i = 0; i < 2; i++) - dest_colormap[starttranscolor + i] = (UINT8)132; - for (; i < 8; i++) - dest_colormap[starttranscolor + i] = (UINT8)133; - for (; i < 12; i++) - dest_colormap[starttranscolor + i] = (UINT8)(134 + ((i-8) >> 1)); - for (; i < 16; i++) - dest_colormap[starttranscolor + i] = (UINT8)(136 + (i-12)); - break; - - // Super purples. - case SKINCOLOR_SUPERPURPLE1: - for (i = 0; i < 10; i++) - dest_colormap[starttranscolor + i] = (UINT8)0; - for (; i < 12; i++) - dest_colormap[starttranscolor + i] = (UINT8)144; - for (; i < 16; i++) - dest_colormap[starttranscolor + i] = (UINT8)(160 + (i-12)); - break; - - case SKINCOLOR_SUPERPURPLE2: - dest_colormap[starttranscolor] = (UINT8)0; - dest_colormap[starttranscolor + 1] = (UINT8)144; - for (i = 2; i < 4; i++) - dest_colormap[starttranscolor + i] = (UINT8)(160 + (i-2)); - for (; i < 8; i++) - dest_colormap[starttranscolor + i] = (UINT8)(162 + ((i-4) >> 1)); - for (; i < 14; i++) - dest_colormap[starttranscolor + i] = (UINT8)164; - for (; i < 16; i++) - dest_colormap[starttranscolor + i] = (UINT8)165; - break; - - case SKINCOLOR_SUPERPURPLE3: - for (i = 0; i < 2; i++) - dest_colormap[starttranscolor + i] = (UINT8)(160 + i); - for (; i < 6; i++) - dest_colormap[starttranscolor + i] = (UINT8)(162 + ((i-2) >> 1)); - for (; i < 12; i++) - dest_colormap[starttranscolor + i] = (UINT8)164; - for (; i < 16; i++) - dest_colormap[starttranscolor + i] = (UINT8)(165 + ((i-12) >> 1)); - break; - - case SKINCOLOR_SUPERPURPLE4: - dest_colormap[starttranscolor] = (UINT8)162; - for (i = 1; i < 3; i++) - dest_colormap[starttranscolor + i] = (UINT8)163; - for (; i < 9; i++) - dest_colormap[starttranscolor + i] = (UINT8)164; - for (; i < 13; i++) - dest_colormap[starttranscolor + i] = (UINT8)(165 + ((i-9) >> 1)); - for (; i < 16; i++) - dest_colormap[starttranscolor + i] = (UINT8)(167 + (i-13)); - break; - - case SKINCOLOR_SUPERPURPLE5: - for (i = 0; i < 2; i++) - dest_colormap[starttranscolor + i] = (UINT8)163; - for (; i < 8; i++) - dest_colormap[starttranscolor + i] = (UINT8)164; - for (; i < 12; i++) - dest_colormap[starttranscolor + i] = (UINT8)(165 + ((i-8) >> 1)); - for (; i < 15; i++) - dest_colormap[starttranscolor + i] = (UINT8)(167 + (i-12)); - dest_colormap[starttranscolor + i] = (UINT8)253; - break; - - // Super rusts. - case SKINCOLOR_SUPERRUST1: - for (i = 0; i < 2; i++) - dest_colormap[starttranscolor + i] = (UINT8)0; - for (; i < 5; i++) - dest_colormap[starttranscolor + i] = (UINT8)208; - for (; i < 7; i++) - dest_colormap[starttranscolor + i] = (UINT8)48; - for (; i < 10; i++) - dest_colormap[starttranscolor + i] = (UINT8)(49 + (i-7)); - for (; i < 12; i++) - dest_colormap[starttranscolor + i] = (UINT8)(55 + ((i-10)*3)); - for (; i < 16; i++) - dest_colormap[starttranscolor + i] = (UINT8)(68 + (i-11)); - break; - - case SKINCOLOR_SUPERRUST2: - for (i = 0; i < 4; i++) - dest_colormap[starttranscolor + i] = (UINT8)48; - for (; i < 9; i++) - dest_colormap[starttranscolor + i] = (UINT8)(49 + (i-4)); - for (; i < 11; i++) - dest_colormap[starttranscolor + i] = (UINT8)(56 + ((i-9)*2)); - for (; i < 15; i++) - dest_colormap[starttranscolor + i] = (UINT8)(68 + (i-11)); - dest_colormap[starttranscolor + i] = (UINT8)71; - break; - - case SKINCOLOR_SUPERRUST3: - dest_colormap[starttranscolor] = (UINT8)49; - for (i = 1; i < 3; i++) - dest_colormap[starttranscolor + i] = (UINT8)50; - for (; i < 5; i++) - dest_colormap[starttranscolor + i] = (UINT8)(51 + (i-3)); - for (; i < 8; i++) - dest_colormap[starttranscolor + i] = (UINT8)(54 + (i-5)); - dest_colormap[starttranscolor + (i++)] = (UINT8)58; - for (; i < 15; i++) - dest_colormap[starttranscolor + i] = (UINT8)(68 + ((i-7) >> 1)); - dest_colormap[starttranscolor + i] = (UINT8)46; - break; - - case SKINCOLOR_SUPERRUST4: - dest_colormap[starttranscolor] = (UINT8)83; - dest_colormap[starttranscolor + 1] = (UINT8)72; - for (i = 2; i < 6; i++) - dest_colormap[starttranscolor + i] = (UINT8)(64 + (i-2)); - for (; i < 14; i++) - dest_colormap[starttranscolor + i] = (UINT8)(68 + ((i-6) >> 1)); - for (; i < 16; i++) - dest_colormap[starttranscolor + i] = (UINT8)46; - break; - - case SKINCOLOR_SUPERRUST5: - for (i = 0; i < 3; i++) - dest_colormap[starttranscolor + i] = (UINT8)(64 + i); - for (; i < 7; i++) - dest_colormap[starttranscolor + i] = (UINT8)(67 + ((i-3) >> 1)); - for (; i < 12; i++) - dest_colormap[starttranscolor + i] = (UINT8)(233 + (i-7)); - for (; i < 16; i++) - dest_colormap[starttranscolor + i] = (UINT8)(238 + ((i-12) >> 1)); - break; - - // Super tans. - case SKINCOLOR_SUPERTAN1: - for (i = 0; i < 10; i++) - dest_colormap[starttranscolor + i] = (UINT8)0; - for (; i < 16; i++) - dest_colormap[starttranscolor + i] = (UINT8)(80 + ((i-10) >> 1)); - break; - - case SKINCOLOR_SUPERTAN2: - dest_colormap[starttranscolor] = (UINT8)0; - for (i = 1; i < 7; i++) - dest_colormap[starttranscolor + i] = (UINT8)(80 + ((i-1) >> 1)); - dest_colormap[starttranscolor + (i++)] = (UINT8)82; - for (; i < 12; i++) - dest_colormap[starttranscolor + i] = (UINT8)84; - for (; i < 15; i++) - dest_colormap[starttranscolor + i] = (UINT8)(85 + (i-12)); - dest_colormap[starttranscolor + i] = (UINT8)245; - break; - - case SKINCOLOR_SUPERTAN3: - dest_colormap[starttranscolor] = (UINT8)80; - for (i = 1; i < 5; i++) - dest_colormap[starttranscolor + i] = (UINT8)(81 + ((i-1) >> 1)); - dest_colormap[starttranscolor + (i++)] = (UINT8)82; - for (; i < 10; i++) - dest_colormap[starttranscolor + i] = (UINT8)84; - for (; i < 13; i++) - dest_colormap[starttranscolor + i] = (UINT8)(85 + (i-10)); - for (; i < 16; i++) - dest_colormap[starttranscolor + i] = (UINT8)(245 + ((i-13)*2)); - break; - - case SKINCOLOR_SUPERTAN4: - dest_colormap[starttranscolor] = (UINT8)81; - for (i = 1; i < 5; i++) - dest_colormap[starttranscolor + i] = (UINT8)82; - for (; i < 8; i++) - dest_colormap[starttranscolor + i] = (UINT8)84; - for (; i < 11; i++) - dest_colormap[starttranscolor + i] = (UINT8)(85 + (i-8)); - for (; i < 15; i++) - dest_colormap[starttranscolor + i] = (UINT8)(245 + ((i-11)*2)); - dest_colormap[starttranscolor + i] = (UINT8)237; - break; - - case SKINCOLOR_SUPERTAN5: - for (i = 0; i < 2; i++) - dest_colormap[starttranscolor + i] = (UINT8)82; - for (; i < 5; i++) - dest_colormap[starttranscolor + i] = (UINT8)84; - for (; i < 8; i++) - dest_colormap[starttranscolor + i] = (UINT8)(85 + (i-5)); - for (; i < 12; i++) - dest_colormap[starttranscolor + i] = (UINT8)(245 + (i-8)); - for (; i < 15; i++) - dest_colormap[starttranscolor + i] = (UINT8)(237 + (i-12)); - dest_colormap[starttranscolor + i] = (UINT8)239; - break; - - default: - I_Error("Invalid skin color #%hu.", (UINT16)color); - break; - } + for (i = 0; i < skinramplength; i++) + dest_colormap[starttranscolor + i] = (UINT8)Color_Index[color-1][i]; } diff --git a/src/r_things.c b/src/r_things.c index 6fd153aaf..b5227331e 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -20,6 +20,7 @@ #include "z_zone.h" #include "m_menu.h" // character select #include "m_misc.h" +#include "info.h" // spr2names #include "i_video.h" // rendermode #include "r_things.h" #include "r_plane.h" @@ -30,6 +31,7 @@ #include "d_netfil.h" // blargh. for nameonly(). #include "m_cheat.h" // objectplace #include "m_cond.h" +#include "fastcmp.h" #ifdef HWRENDER #include "hardware/hw_md2.h" #endif @@ -438,117 +440,6 @@ void R_AddSpriteDefs(UINT16 wadnum) CONS_Printf(M_GetText("%s added %d frames in %s sprites\n"), wadname, end-start, sizeu1(addsprites)); } -#ifdef DELFILE -static void R_RemoveSpriteLump(UINT16 wad, // graphics patch - UINT16 lump, - size_t lumpid, // identifier - UINT8 frame, - UINT8 rotation, - UINT8 flipped) -{ - (void)wad; /// \todo: how do I remove sprites? - (void)lump; - (void)lumpid; - (void)frame; - (void)rotation; - (void)flipped; -} - -static boolean R_DelSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 wadnum, UINT16 startlump, UINT16 endlump) -{ - UINT16 l; - UINT8 frame; - UINT8 rotation; - lumpinfo_t *lumpinfo; - - maxframe = (size_t)-1; - - // scan the lumps, - // filling in the frames for whatever is found - lumpinfo = wadfiles[wadnum]->lumpinfo; - if (endlump > wadfiles[wadnum]->numlumps) - endlump = wadfiles[wadnum]->numlumps; - - for (l = startlump; l < endlump; l++) - { - if (memcmp(lumpinfo[l].name,sprname,4)==0) - { - frame = (UINT8)(lumpinfo[l].name[4] - 'A'); - rotation = (UINT8)(lumpinfo[l].name[5] - '0'); - - // skip NULL sprites from very old dmadds pwads - if (W_LumpLengthPwad(wadnum,l)<=8) - continue; - - //---------------------------------------------------- - - R_RemoveSpriteLump(wadnum, l, numspritelumps, frame, rotation, 0); - - if (lumpinfo[l].name[6]) - { - frame = (UINT8)(lumpinfo[l].name[6] - 'A'); - rotation = (UINT8)(lumpinfo[l].name[7] - '0'); - R_RemoveSpriteLump(wadnum, l, numspritelumps, frame, rotation, 1); - } - } - } - - if (maxframe == (size_t)-1) - return false; - - spritedef->numframes = 0; - Z_Free(spritedef->spriteframes); - spritedef->spriteframes = NULL; - return true; -} - -void R_DelSpriteDefs(UINT16 wadnum) -{ - size_t i, delsprites = 0; - UINT16 start, end; - - // find the sprites section in this pwad - // we need at least the S_END - // (not really, but for speedup) - - start = W_CheckNumForNamePwad("S_START", wadnum, 0); - if (start == INT16_MAX) - start = W_CheckNumForNamePwad("SS_START", wadnum, 0); //deutex compatib. - if (start == INT16_MAX) - start = 0; //let say S_START is lump 0 - else - start++; // just after S_START - - end = W_CheckNumForNamePwad("S_END",wadnum,start); - if (end == INT16_MAX) - end = W_CheckNumForNamePwad("SS_END",wadnum,start); //deutex compatib. - if (end == INT16_MAX) - { - CONS_Debug(DBG_SETUP, "no sprites in pwad %d\n", wadnum); - return; - //I_Error("R_DelSpriteDefs: S_END, or SS_END missing for sprites " - // "in pwad %d\n",wadnum); - } - - // - // scan through lumps, for each sprite, find all the sprite frames - // - for (i = 0; i < numsprites; i++) - { - spritename = sprnames[i]; - - if (R_DelSingleSpriteDef(spritename, &sprites[i], wadnum, start, end)) - { - // if a new sprite was removed (not just replaced) - delsprites++; - CONS_Debug(DBG_SETUP, "sprite %s set in pwad %d\n", spritename, wadnum); - } - } - - CONS_Printf(M_GetText("%s sprites removed from file %s\n"), sizeu1(delsprites), wadfiles[wadnum]->filename); -} -#endif - // // GAME FUNCTIONS // @@ -2541,6 +2432,193 @@ skin_t skins[MAXSKINS+1]; CV_PossibleValue_t skin_cons_t[MAXSKINS+1]; #endif +// +// P_GetSkinSprite2 +// For non-super players, tries each sprite2's immediate predecessor until it finds one with a number of frames or ends up at standing. +// For super players, does the same as above - but tries the super equivalent for each sprite2 before the non-super version. +// + +UINT8 P_GetSkinSprite2(skin_t *skin, UINT8 spr2, player_t *player) +{ + UINT8 super = (spr2 & FF_SPR2SUPER); + + if (!skin) + return 0; + + while (!(skin->sprites[spr2].numframes) + && spr2 != SPR2_STND) + { + if (spr2 & FF_SPR2SUPER) + { + spr2 &= ~FF_SPR2SUPER; + continue; + } + + switch(spr2) + { + case SPR2_RUN: + spr2 = SPR2_WALK; + break; + case SPR2_STUN: + spr2 = SPR2_PAIN; + break; + case SPR2_DRWN: + spr2 = SPR2_DEAD; + break; + case SPR2_SPIN: + spr2 = SPR2_ROLL; + break; + case SPR2_GASP: + spr2 = SPR2_SPNG; + break; + case SPR2_JUMP: + spr2 = ((player + ? player->charflags + : skin->flags) + & SF_NOJUMPSPIN) ? SPR2_SPNG : SPR2_ROLL; + break; + case SPR2_SPNG: // spring + spr2 = SPR2_FALL; + break; + case SPR2_FALL: + spr2 = SPR2_WALK; + break; + case SPR2_RIDE: + spr2 = SPR2_FALL; + break; + + case SPR2_FLY : + spr2 = SPR2_SPNG; + break; + case SPR2_SWIM: + spr2 = SPR2_FLY ; + break; + case SPR2_TIRE: + spr2 = (player && player->charability == CA_SWIM) ? SPR2_SWIM : SPR2_FLY; + break; + + case SPR2_GLID: + spr2 = SPR2_FLY; + break; + case SPR2_CLMB: + spr2 = SPR2_ROLL; + break; + case SPR2_CLNG: + spr2 = SPR2_CLMB; + break; + + case SPR2_FLT : + spr2 = SPR2_WALK; + break; + case SPR2_FRUN: + spr2 = SPR2_RUN ; + break; + + case SPR2_DASH: + spr2 = SPR2_FRUN; + break; + + case SPR2_BNCE: + spr2 = SPR2_FALL; + break; + case SPR2_BLND: + spr2 = SPR2_ROLL; + break; + + case SPR2_TWIN: + spr2 = SPR2_ROLL; + break; + + case SPR2_MLEE: + spr2 = SPR2_TWIN; + break; + + // NiGHTS sprites. + case SPR2_NSTD: + spr2 = SPR2_STND; + super = FF_SPR2SUPER; + break; + case SPR2_NFLT: + spr2 = SPR2_FLT ; + super = FF_SPR2SUPER; + break; + case SPR2_NSTN: + spr2 = SPR2_STUN; + break; + case SPR2_NPUL: + spr2 = SPR2_NSTN; + break; + case SPR2_NATK: + spr2 = SPR2_ROLL; + super = FF_SPR2SUPER; + break; + /*case SPR2_NGT0: + spr2 = SPR2_NFLT; + break;*/ + case SPR2_NGT1: + case SPR2_NGT7: + case SPR2_DRL0: + spr2 = SPR2_NGT0; + break; + case SPR2_NGT2: + case SPR2_DRL1: + spr2 = SPR2_NGT1; + break; + case SPR2_NGT3: + case SPR2_DRL2: + spr2 = SPR2_NGT2; + break; + case SPR2_NGT4: + case SPR2_DRL3: + spr2 = SPR2_NGT3; + break; + case SPR2_NGT5: + case SPR2_DRL4: + spr2 = SPR2_NGT4; + break; + case SPR2_NGT6: + case SPR2_DRL5: + spr2 = SPR2_NGT5; + break; + case SPR2_DRL6: + spr2 = SPR2_NGT6; + break; + case SPR2_NGT8: + case SPR2_DRL7: + spr2 = SPR2_NGT7; + break; + case SPR2_NGT9: + case SPR2_DRL8: + spr2 = SPR2_NGT8; + break; + case SPR2_NGTA: + case SPR2_DRL9: + spr2 = SPR2_NGT9; + break; + case SPR2_NGTB: + case SPR2_DRLA: + spr2 = SPR2_NGTA; + break; + case SPR2_NGTC: + case SPR2_DRLB: + spr2 = SPR2_NGTB; + break; + case SPR2_DRLC: + spr2 = SPR2_NGTC; + break; + + // Dunno? Just go to standing then. + default: + spr2 = SPR2_STND; + break; + } + + spr2 |= super; + } + + return spr2; +} + static void Sk_SetDefaultValue(skin_t *skin) { INT32 i; @@ -2594,7 +2672,7 @@ static void Sk_SetDefaultValue(skin_t *skin) skin->spinitem = -1; skin->revitem = -1; - skin->highresscale = FRACUNIT>>1; + skin->highresscale = FRACUNIT; skin->availability = 0; @@ -2733,16 +2811,17 @@ void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum) if (player->mo) { + fixed_t radius = FixedMul(skin->radius, player->mo->scale); if ((player->powers[pw_carry] == CR_NIGHTSMODE) && (skin->sprites[SPR2_NGT0].numframes == 0)) // If you don't have a sprite for flying horizontally, use the default NiGHTS skin. { skin = &skins[DEFAULTNIGHTSSKIN]; - newcolor = ((skin->flags & SF_SUPER) ? skin->supercolor : skin->prefcolor); + newcolor = skin->prefcolor; // will be updated in thinker to flashing } player->mo->skin = skin; if (newcolor) player->mo->color = newcolor; P_SetScale(player->mo, player->mo->scale); - player->mo->radius = FixedMul(skin->radius, player->mo->scale); + player->mo->radius = radius; P_SetPlayerMobjState(player->mo, player->mo->state-states); // Prevent visual errors when switching between skins with differing number of frames } @@ -2787,6 +2866,189 @@ static UINT16 W_CheckForSkinMarkerInPwad(UINT16 wadid, UINT16 startlump) #define HUDNAMEWRITE(value) STRBUFCPY(skin->hudname, value) #endif +// turn _ into spaces and . into katana dot +#define SYMBOLCONVERT(name) for (value = name; *value; value++)\ + {\ + if (*value == '_') *value = ' ';\ + else if (*value == '.') *value = '\x1E';\ + } + +// +// Patch skins from a pwad, each skin preceded by 'P_SKIN' marker +// + +// Does the same is in w_wad, but check only for +// the first 6 characters (this is so we can have P_SKIN1, P_SKIN2.. +// for wad editors that don't like multiple resources of the same name) +// +static UINT16 W_CheckForPatchSkinMarkerInPwad(UINT16 wadid, UINT16 startlump) +{ + UINT16 i; + const char *P_SKIN = "P_SKIN"; + lumpinfo_t *lump_p; + + // scan forward, start at + if (startlump < wadfiles[wadid]->numlumps) + { + lump_p = wadfiles[wadid]->lumpinfo + startlump; + for (i = startlump; i < wadfiles[wadid]->numlumps; i++, lump_p++) + if (memcmp(lump_p->name,P_SKIN,6)==0) + return i; + } + return INT16_MAX; // not found +} + +static void R_LoadSkinSprites(UINT16 wadnum, UINT16 *lump, UINT16 *lastlump, skin_t *skin) +{ + UINT16 newlastlump; + UINT8 sprite2; + + *lump += 1; // start after S_SKIN + *lastlump = W_CheckNumForNamePwad("S_END",wadnum,*lump); // stop at S_END + + // old wadding practices die hard -- stop at S_SKIN (or P_SKIN) or S_START if they come before S_END. + newlastlump = W_CheckForSkinMarkerInPwad(wadnum,*lump); + if (newlastlump < *lastlump) *lastlump = newlastlump; + newlastlump = W_CheckForPatchSkinMarkerInPwad(wadnum,*lump); + if (newlastlump < *lastlump) *lastlump = newlastlump; + newlastlump = W_CheckNumForNamePwad("S_START",wadnum,*lump); + if (newlastlump < *lastlump) *lastlump = newlastlump; + + // ...and let's handle super, too + newlastlump = W_CheckNumForNamePwad("S_SUPER",wadnum,*lump); + if (newlastlump < *lastlump) + { + newlastlump++; + // load all sprite sets we are aware of... for super! + for (sprite2 = 0; sprite2 < free_spr2; sprite2++) + R_AddSingleSpriteDef((spritename = spr2names[sprite2]), &skin->sprites[FF_SPR2SUPER|sprite2], wadnum, newlastlump, *lastlump); + + newlastlump--; + *lastlump = newlastlump; // okay, make the normal sprite set loading end there + } + + // load all sprite sets we are aware of... for normal stuff. + for (sprite2 = 0; sprite2 < free_spr2; sprite2++) + R_AddSingleSpriteDef((spritename = spr2names[sprite2]), &skin->sprites[sprite2], wadnum, *lump, *lastlump); + +} + +// returns whether found appropriate property +static boolean R_ProcessPatchableFields(skin_t *skin, char *stoken, char *value) +{ + // custom translation table + if (!stricmp(stoken, "startcolor")) + skin->starttranscolor = atoi(value); + +#define FULLPROCESS(field) else if (!stricmp(stoken, #field)) skin->field = get_number(value); + // character type identification + FULLPROCESS(flags) + FULLPROCESS(ability) + FULLPROCESS(ability2) + + FULLPROCESS(thokitem) + FULLPROCESS(spinitem) + FULLPROCESS(revitem) +#undef FULLPROCESS + +#define GETFRACBITS(field) else if (!stricmp(stoken, #field)) skin->field = atoi(value)<field = atoi(value); + GETINT(thrustfactor) + GETINT(accelstart) + GETINT(acceleration) +#undef GETINT + +#define GETSKINCOLOR(field) else if (!stricmp(stoken, #field)) skin->field = R_GetColorByName(value); + GETSKINCOLOR(prefcolor) + GETSKINCOLOR(prefoppositecolor) +#undef GETSKINCOLOR + else if (!stricmp(stoken, "supercolor")) + skin->supercolor = R_GetSuperColorByName(value); + +#define GETFLOAT(field) else if (!stricmp(stoken, #field)) skin->field = FLOAT_TO_FIXED(atof(value)); + GETFLOAT(jumpfactor) + GETFLOAT(highresscale) + GETFLOAT(shieldscale) + GETFLOAT(camerascale) +#undef GETFLOAT + +#define GETFLAG(field) else if (!stricmp(stoken, #field)) { \ + strupr(value); \ + if (atoi(value) || value[0] == 'T' || value[0] == 'Y') \ + skin->flags |= (SF_##field); \ + else \ + skin->flags &= ~(SF_##field); \ +} + // parameters for individual character flags + // these are uppercase so they can be concatenated with SF_ + // 1, true, yes are all valid values + GETFLAG(SUPER) + GETFLAG(NOSUPERSPIN) + GETFLAG(NOSPINDASHDUST) + GETFLAG(HIRES) + GETFLAG(NOSKID) + GETFLAG(NOSPEEDADJUST) + GETFLAG(RUNONWATER) + GETFLAG(NOJUMPSPIN) + GETFLAG(NOJUMPDAMAGE) + GETFLAG(STOMPDAMAGE) + GETFLAG(MARIODAMAGE) + GETFLAG(MACHINE) + GETFLAG(DASHMODE) + GETFLAG(FASTEDGE) + GETFLAG(MULTIABILITY) +#undef GETFLAG + + else // let's check if it's a sound, otherwise error out + { + boolean found = false; + sfxenum_t i; + size_t stokenadjust; + + // Remove the prefix. (We need to affect an adjusting variable so that we can print error messages if it's not actually a sound.) + if ((stoken[0] == 'D' || stoken[0] == 'd') && (stoken[1] == 'S' || stoken[1] == 's')) // DS* + stokenadjust = 2; + else // sfx_* + stokenadjust = 4; + + // Remove the prefix. (We can affect this directly since we're not going to use it again.) + if ((value[0] == 'D' || value[0] == 'd') && (value[1] == 'S' || value[1] == 's')) // DS* + value += 2; + else // sfx_* + value += 4; + + // copy name of sounds that are remapped + // for this skin + for (i = 0; i < sfx_skinsoundslot0; i++) + { + if (!S_sfx[i].name) + continue; + if (S_sfx[i].skinsound != -1 + && !stricmp(S_sfx[i].name, + stoken + stokenadjust)) + { + skin->soundsid[S_sfx[i].skinsound] = + S_AddSoundFx(value, S_sfx[i].singularity, S_sfx[i].pitch, true); + found = true; + } + } + return found; + } + return true; +} + // // Find skin sprites, sounds & optional status bar face, & add them // @@ -2846,6 +3108,8 @@ void R_AddSkins(UINT16 wadnum) if (!value) I_Error("R_AddSkins: syntax error in S_SKIN lump# %d(%s) in WAD %s\n", lump, W_CheckNameForNumPwad(wadnum,lump), wadfiles[wadnum]->filename); + // Some of these can't go in R_ProcessPatchableFields because they have side effects for future lines. + // Others can't go in there because we don't want them to be patchable. if (!stricmp(stoken, "name")) { INT32 skinnum = R_SkinAvailable(value); @@ -2884,22 +3148,14 @@ void R_AddSkins(UINT16 wadnum) { HUDNAMEWRITE(skin->name); strupr(skin->hudname); - for (value = skin->hudname; *value; value++) - { - if (*value == '_') *value = ' '; // turn _ into spaces. - else if (*value == '.') *value = '\x1E'; // turn . into katana dot. - } + SYMBOLCONVERT(skin->hudname) } } else if (!stricmp(stoken, "realname")) { // Display name (eg. "Knuckles") realname = true; STRBUFCPY(skin->realname, value); - for (value = skin->realname; *value; value++) - { - if (*value == '_') *value = ' '; // turn _ into spaces. - else if (*value == '.') *value = '\x1E'; // turn . into katana dot. - } + SYMBOLCONVERT(skin->realname) if (!hudname) HUDNAMEWRITE(skin->realname); } @@ -2907,15 +3163,10 @@ void R_AddSkins(UINT16 wadnum) { // Life icon name (eg. "K.T.E") hudname = true; HUDNAMEWRITE(value); - for (value = skin->hudname; *value; value++) - { - if (*value == '_') *value = ' '; // turn _ into spaces. - else if (*value == '.') *value = '\x1E'; // turn . into katana dot. - } + SYMBOLCONVERT(skin->hudname) if (!realname) STRBUFCPY(skin->realname, skin->hudname); } - else if (!stricmp(stoken, "charsel")) { strupr(value); @@ -2934,37 +3185,6 @@ void R_AddSkins(UINT16 wadnum) strupr(value); strncpy(skin->superface, value, sizeof skin->superface); } - -#define FULLPROCESS(field) else if (!stricmp(stoken, #field)) skin->field = get_number(value); - // character type identification - FULLPROCESS(flags) - FULLPROCESS(ability) - FULLPROCESS(ability2) - - FULLPROCESS(thokitem) - FULLPROCESS(spinitem) - FULLPROCESS(revitem) -#undef FULLPROCESS - -#define GETFRACBITS(field) else if (!stricmp(stoken, #field)) skin->field = atoi(value)<field = atoi(value); - GETINT(thrustfactor) - GETINT(accelstart) - GETINT(acceleration) -#undef GETINT - else if (!stricmp(stoken, "availability")) { skin->availability = atoi(value); @@ -2973,125 +3193,16 @@ void R_AddSkins(UINT16 wadnum) if (skin->availability) STRBUFCPY(unlockables[skin->availability - 1].name, skin->realname); } + else if (!R_ProcessPatchableFields(skin, stoken, value)) + CONS_Debug(DBG_SETUP, "R_AddSkins: Unknown keyword '%s' in S_SKIN lump #%d (WAD %s)\n", stoken, lump, wadfiles[wadnum]->filename); - // custom translation table - else if (!stricmp(stoken, "startcolor")) - skin->starttranscolor = atoi(value); - -#define GETSKINCOLOR(field) else if (!stricmp(stoken, #field)) skin->field = R_GetColorByName(value); - GETSKINCOLOR(prefcolor) - GETSKINCOLOR(prefoppositecolor) -#undef GETSKINCOLOR - else if (!stricmp(stoken, "supercolor")) - skin->supercolor = R_GetSuperColorByName(value); - -#define GETFLOAT(field) else if (!stricmp(stoken, #field)) skin->field = FLOAT_TO_FIXED(atof(value)); - GETFLOAT(jumpfactor) - GETFLOAT(highresscale) - GETFLOAT(shieldscale) - GETFLOAT(camerascale) -#undef GETFLOAT - -#define GETFLAG(field) else if (!stricmp(stoken, #field)) { \ - strupr(value); \ - if (atoi(value) || value[0] == 'T' || value[0] == 'Y') \ - skin->flags |= (SF_##field); \ - else \ - skin->flags &= ~(SF_##field); \ -} - // parameters for individual character flags - // these are uppercase so they can be concatenated with SF_ - // 1, true, yes are all valid values - GETFLAG(SUPER) - GETFLAG(NOSUPERSPIN) - GETFLAG(NOSPINDASHDUST) - GETFLAG(HIRES) - GETFLAG(NOSKID) - GETFLAG(NOSPEEDADJUST) - GETFLAG(RUNONWATER) - GETFLAG(NOJUMPSPIN) - GETFLAG(NOJUMPDAMAGE) - GETFLAG(STOMPDAMAGE) - GETFLAG(MARIODAMAGE) - GETFLAG(MACHINE) - GETFLAG(DASHMODE) - GETFLAG(FASTEDGE) - GETFLAG(MULTIABILITY) -#undef GETFLAG - - else // let's check if it's a sound, otherwise error out - { - boolean found = false; - sfxenum_t i; - size_t stokenadjust; - - // Remove the prefix. (We need to affect an adjusting variable so that we can print error messages if it's not actually a sound.) - if ((stoken[0] == 'D' || stoken[0] == 'd') && (stoken[1] == 'S' || stoken[1] == 's')) // DS* - stokenadjust = 2; - else // sfx_* - stokenadjust = 4; - - // Remove the prefix. (We can affect this directly since we're not going to use it again.) - if ((value[0] == 'D' || value[0] == 'd') && (value[1] == 'S' || value[1] == 's')) // DS* - value += 2; - else // sfx_* - value += 4; - - // copy name of sounds that are remapped - // for this skin - for (i = 0; i < sfx_skinsoundslot0; i++) - { - if (!S_sfx[i].name) - continue; - if (S_sfx[i].skinsound != -1 - && !stricmp(S_sfx[i].name, - stoken + stokenadjust)) - { - skin->soundsid[S_sfx[i].skinsound] = - S_AddSoundFx(value, S_sfx[i].singularity, S_sfx[i].pitch, true); - found = true; - } - } - if (!found) - CONS_Debug(DBG_SETUP, "R_AddSkins: Unknown keyword '%s' in S_SKIN lump #%d (WAD %s)\n", stoken, lump, wadfiles[wadnum]->filename); - } next_token: stoken = strtok(NULL, "\r\n= "); } free(buf2); // Add sprites - { - UINT16 newlastlump; - UINT8 sprite2; - - lump++; // start after S_SKIN - lastlump = W_CheckNumForNamePwad("S_END",wadnum,lump); // stop at S_END - - // old wadding practices die hard -- stop at S_SKIN or S_START if they come before S_END. - newlastlump = W_CheckNumForNamePwad("S_SKIN",wadnum,lump); - if (newlastlump < lastlump) lastlump = newlastlump; - newlastlump = W_CheckNumForNamePwad("S_START",wadnum,lump); - if (newlastlump < lastlump) lastlump = newlastlump; - - // ...and let's handle super, too - newlastlump = W_CheckNumForNamePwad("S_SUPER",wadnum,lump); - if (newlastlump < lastlump) - { - newlastlump++; - // load all sprite sets we are aware of... for super! - for (sprite2 = 0; sprite2 < free_spr2; sprite2++) - R_AddSingleSpriteDef(spr2names[sprite2], &skin->sprites[FF_SPR2SUPER|sprite2], wadnum, newlastlump, lastlump); - - newlastlump--; - lastlump = newlastlump; // okay, make the normal sprite set loading end there - } - - // load all sprite sets we are aware of... for normal stuff. - for (sprite2 = 0; sprite2 < free_spr2; sprite2++) - R_AddSingleSpriteDef(spr2names[sprite2], &skin->sprites[sprite2], wadnum, lump, lastlump); - - } + R_LoadSkinSprites(wadnum, &lump, &lastlump, skin); R_FlushTranslationColormapCache(); @@ -3115,50 +3226,124 @@ next_token: return; } -#undef HUDNAMEWRITE - -#ifdef DELFILE -void R_DelSkins(UINT16 wadnum) +// +// Patch skin sprites +// +void R_PatchSkins(UINT16 wadnum) { UINT16 lump, lastlump = 0; - while ((lump = W_CheckForSkinMarkerInPwad(wadnum, lastlump)) != INT16_MAX) + char *buf; + char *buf2; + char *stoken; + char *value; + size_t size; + skin_t *skin; + boolean noskincomplain, realname, hudname; + + // + // search for all skin patch markers in pwad + // + + while ((lump = W_CheckForPatchSkinMarkerInPwad(wadnum, lastlump)) != INT16_MAX) { - if (skins[numskins].wadnum != wadnum) - break; - numskins--; - ST_UnLoadFaceGraphics(numskins); // only used by DELFILE - if (skins[numskins].sprite[0] != '\0') - { - const char *csprname = W_CheckNameForNumPwad(wadnum, lump); + INT32 skinnum = 0; - // skip to end of this skin's frames - lastlump = lump; - while (W_CheckNameForNumPwad(wadnum,lastlump) && memcmp(W_CheckNameForNumPwad(wadnum, lastlump),csprname,4)==0) - lastlump++; - // allocate (or replace) sprite frames, and set spritedef - R_DelSingleSpriteDef(csprname, &skins[numskins].spritedef, wadnum, lump, lastlump); - } - else + // advance by default + lastlump = lump + 1; + + buf = W_CacheLumpNumPwad(wadnum, lump, PU_CACHE); + size = W_LumpLengthPwad(wadnum, lump); + + // for strtok + buf2 = malloc(size+1); + if (!buf2) + I_Error("R_PatchSkins: No more free memory\n"); + M_Memcpy(buf2,buf,size); + buf2[size] = '\0'; + + skin = NULL; + noskincomplain = realname = hudname = false; + + /* + Parse. Has more phases than the parser in R_AddSkins because it needs to have the patching name first (no default skin name is acceptible for patching, unlike skin creation) + */ + + stoken = strtok(buf2, "\r\n= "); + while (stoken) { - // search in the normal sprite tables - size_t name; - boolean found = false; - const char *sprname = skins[numskins].sprite; - for (name = 0;sprnames[name][0] != '\0';name++) - if (strcmp(sprnames[name], sprname) == 0) + if ((stoken[0] == '/' && stoken[1] == '/') + || (stoken[0] == '#'))// skip comments + { + stoken = strtok(NULL, "\r\n"); // skip end of line + goto next_token; // find the real next token + } + + value = strtok(NULL, "\r\n= "); + + if (!value) + I_Error("R_PatchSkins: syntax error in P_SKIN lump# %d(%s) in WAD %s\n", lump, W_CheckNameForNumPwad(wadnum,lump), wadfiles[wadnum]->filename); + + if (!skin) // Get the name! + { + if (!stricmp(stoken, "name")) { - found = true; - skins[numskins].spritedef = sprites[name]; + strlwr(value); + skinnum = R_SkinAvailable(value); + if (skinnum != -1) + skin = &skins[skinnum]; + else + { + CONS_Debug(DBG_SETUP, "R_PatchSkins: unknown skin name in P_SKIN lump# %d(%s) in WAD %s\n", lump, W_CheckNameForNumPwad(wadnum,lump), wadfiles[wadnum]->filename); + noskincomplain = true; + } } + } + else // Get the properties! + { + // Some of these can't go in R_ProcessPatchableFields because they have side effects for future lines. + if (!stricmp(stoken, "realname")) + { // Display name (eg. "Knuckles") + realname = true; + STRBUFCPY(skin->realname, value); + SYMBOLCONVERT(skin->realname) + if (!hudname) + HUDNAMEWRITE(skin->realname); + } + else if (!stricmp(stoken, "hudname")) + { // Life icon name (eg. "K.T.E") + hudname = true; + HUDNAMEWRITE(value); + SYMBOLCONVERT(skin->hudname) + if (!realname) + STRBUFCPY(skin->realname, skin->hudname); + } + else if (!R_ProcessPatchableFields(skin, stoken, value)) + CONS_Debug(DBG_SETUP, "R_PatchSkins: Unknown keyword '%s' in P_SKIN lump #%d (WAD %s)\n", stoken, lump, wadfiles[wadnum]->filename); + } - // not found so make a new one - if (!found) - R_DelSingleSpriteDef(sprname, &skins[numskins].spritedef, wadnum, 0, INT16_MAX); + if (!skin) + break; - while (W_CheckNameForNumPwad(wadnum,lastlump) && memcmp(W_CheckNameForNumPwad(wadnum, lastlump),sprname,4)==0) - lastlump++; +next_token: + stoken = strtok(NULL, "\r\n= "); } - CONS_Printf(M_GetText("Removed skin '%s'\n"), skins[numskins].name); + free(buf2); + + if (!skin) // Didn't include a name parameter? What a waste. + { + if (!noskincomplain) + CONS_Debug(DBG_SETUP, "R_PatchSkins: no skin name given in P_SKIN lump #%d (WAD %s)\n", lump, wadfiles[wadnum]->filename); + continue; + } + + // Patch sprites + R_LoadSkinSprites(wadnum, &lump, &lastlump, skin); + + if (!skin->availability) // Safe to print... + CONS_Printf(M_GetText("Patched skin '%s'\n"), skin->name); } + return; } -#endif + +#undef HUDNAMEWRITE +#undef SYMBOLCONVERT diff --git a/src/sounds.c b/src/sounds.c index 2f5f6acf0..2c1c5f3af 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -154,7 +154,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"gravch", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Recycler"}, {"itemup", true, 255, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Sparkle"}, {"jet", false, 8, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Jet engine"}, - {"jshard", true, 167, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Got shard"}, + {"jshard", true, 167, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Life transfer"}, // placeholder repurpose; original string was "Got Shard" {"lose" , false, 127, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Failure"}, {"lvpass", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spinning signpost"}, {"mindig", false, 8, 64, -1, NULL, 0, -1, -1, LUMPERROR, "Tunnelling"}, @@ -346,7 +346,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"s3k78", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Magnet"}, {"s3k79", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Electric charge"}, {"s3k7a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Rising from lava"}, - {"s3k7b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Organic bounce"}, + {"s3k7b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Soft bounce"}, {"s3k7c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Magnet"}, {"s3k7d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"s3k7e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Eating dirt"}, diff --git a/src/st_stuff.c b/src/st_stuff.c index 8e40f138c..4515495af 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -68,6 +68,7 @@ static patch_t *sboover; static patch_t *timeover; static patch_t *stlivex; static patch_t *sboredrings; +static patch_t *sboredtime; static patch_t *getall; // Special Stage HUD static patch_t *timeup; // Special Stage HUD static patch_t *hunthoming[6]; @@ -251,6 +252,7 @@ void ST_LoadGraphics(void) sboredrings = W_CachePatchName("STTRRING", PU_HUDGFX); sboscore = W_CachePatchName("STTSCORE", PU_HUDGFX); sbotime = W_CachePatchName("STTTIME", PU_HUDGFX); // Time logo + sboredtime = W_CachePatchName("STTRTIME", PU_HUDGFX); sbocolon = W_CachePatchName("STTCOLON", PU_HUDGFX); // Colon for time sboperiod = W_CachePatchName("STTPERIO", PU_HUDGFX); // Period for time centiseconds @@ -344,15 +346,6 @@ void ST_LoadFaceGraphics(char *facestr, char *superstr, INT32 skinnum) facefreed[skinnum] = false; } -#ifdef DELFILE -void ST_UnLoadFaceGraphics(INT32 skinnum) -{ - Z_Free(faceprefix[skinnum]); - Z_Free(superprefix[skinnum]); - facefreed[skinnum] = true; -} -#endif - void ST_ReloadSkinFaceGraphics(void) { INT32 i; @@ -501,12 +494,12 @@ static INT32 SCR(INT32 r) #define ST_DrawPaddedOverlayNum(x,y,n,d) V_DrawPaddedTallNum(x, y, V_NOSCALESTART|V_HUDTRANS, n, d) #define ST_DrawOverlayPatch(x,y,p) V_DrawScaledPatch(x, y, V_NOSCALESTART|V_HUDTRANS, p) #define ST_DrawMappedOverlayPatch(x,y,p,c) V_DrawMappedScaledPatch(x, y, V_NOSCALESTART|V_HUDTRANS, p, c) -#define ST_DrawNumFromHud(h,n) V_DrawTallNum(SCX(hudinfo[h].x), SCY(hudinfo[h].y), V_NOSCALESTART|V_HUDTRANS, n) -#define ST_DrawPadNumFromHud(h,n,q) V_DrawPaddedTallNum(SCX(hudinfo[h].x), SCY(hudinfo[h].y), V_NOSCALESTART|V_HUDTRANS, n, q) -#define ST_DrawPatchFromHud(h,p) V_DrawScaledPatch(SCX(hudinfo[h].x), SCY(hudinfo[h].y), V_NOSCALESTART|V_HUDTRANS, p) -#define ST_DrawNumFromHudWS(h,n) V_DrawTallNum(SCX(hudinfo[h+!!splitscreen].x), SCY(hudinfo[h+!!splitscreen].y), V_NOSCALESTART|V_HUDTRANS, n) -#define ST_DrawPadNumFromHudWS(h,n,q) V_DrawPaddedTallNum(SCX(hudinfo[h+!!splitscreen].x), SCY(hudinfo[h+!!splitscreen].y), V_NOSCALESTART|V_HUDTRANS, n, q) -#define ST_DrawPatchFromHudWS(h,p) V_DrawScaledPatch(SCX(hudinfo[h+!!splitscreen].x), SCY(hudinfo[h+!!splitscreen].y), V_NOSCALESTART|V_HUDTRANS, p) +#define ST_DrawNumFromHud(h,n,f) V_DrawTallNum(SCX(hudinfo[h].x), SCY(hudinfo[h].y), V_NOSCALESTART|f, n) +#define ST_DrawPadNumFromHud(h,n,q,f) V_DrawPaddedTallNum(SCX(hudinfo[h].x), SCY(hudinfo[h].y), V_NOSCALESTART|f, n, q) +#define ST_DrawPatchFromHud(h,p,f) V_DrawScaledPatch(SCX(hudinfo[h].x), SCY(hudinfo[h].y), V_NOSCALESTART|f, p) +#define ST_DrawNumFromHudWS(h,n,f) V_DrawTallNum(SCX(hudinfo[h+!!splitscreen].x), SCY(hudinfo[h+!!splitscreen].y), V_NOSCALESTART|f, n) +#define ST_DrawPadNumFromHudWS(h,n,q,f) V_DrawPaddedTallNum(SCX(hudinfo[h+!!splitscreen].x), SCY(hudinfo[h+!!splitscreen].y), V_NOSCALESTART|f, n, q) +#define ST_DrawPatchFromHudWS(h,p,f) V_DrawScaledPatch(SCX(hudinfo[h+!!splitscreen].x), SCY(hudinfo[h+!!splitscreen].y), V_NOSCALESTART|f, p) // Draw a number, scaled, over the view, maybe with set translucency // Always draw the number completely since it's overlay @@ -618,16 +611,16 @@ static void ST_drawDebugInfo(void) static void ST_drawScore(void) { // SCORE: - ST_DrawPatchFromHud(HUD_SCORE, sboscore); + ST_DrawPatchFromHud(HUD_SCORE, sboscore, V_HUDTRANS); if (objectplacing) { if (op_displayflags > UINT16_MAX) ST_DrawOverlayPatch(SCX(hudinfo[HUD_SCORENUM].x-tallminus->width), SCY(hudinfo[HUD_SCORENUM].y), tallminus); else - ST_DrawNumFromHud(HUD_SCORENUM, op_displayflags); + ST_DrawNumFromHud(HUD_SCORENUM, op_displayflags, V_HUDTRANS); } else - ST_DrawNumFromHud(HUD_SCORENUM, stplyr->score); + ST_DrawNumFromHud(HUD_SCORENUM, stplyr->score,V_HUDTRANS); } static void ST_drawTime(void) @@ -635,7 +628,7 @@ static void ST_drawTime(void) INT32 seconds, minutes, tictrn, tics; // TIME: - ST_DrawPatchFromHudWS(HUD_TIME, sbotime); + ST_DrawPatchFromHudWS(HUD_TIME, ((mapheaderinfo[gamemap-1]->countdown && countdowntimer < 11*TICRATE && leveltime/5 & 1) ? sboredtime : sbotime), V_HUDTRANS); if (objectplacing) { @@ -646,24 +639,24 @@ static void ST_drawTime(void) } else { - tics = stplyr->realtime; + tics = (mapheaderinfo[gamemap-1]->countdown ? countdowntimer : stplyr->realtime); seconds = G_TicsToSeconds(tics); minutes = G_TicsToMinutes(tics, true); tictrn = G_TicsToCentiseconds(tics); } if (cv_timetic.value == 1) // Tics only -- how simple is this? - ST_DrawNumFromHudWS(HUD_SECONDS, tics); + ST_DrawNumFromHudWS(HUD_SECONDS, tics, V_HUDTRANS); else { - ST_DrawNumFromHudWS(HUD_MINUTES, minutes); // Minutes - ST_DrawPatchFromHudWS(HUD_TIMECOLON, sbocolon); // Colon - ST_DrawPadNumFromHudWS(HUD_SECONDS, seconds, 2); // Seconds + ST_DrawNumFromHudWS(HUD_MINUTES, minutes, V_HUDTRANS); // Minutes + ST_DrawPatchFromHudWS(HUD_TIMECOLON, sbocolon, V_HUDTRANS); // Colon + ST_DrawPadNumFromHudWS(HUD_SECONDS, seconds, 2, V_HUDTRANS); // Seconds if (!splitscreen && (cv_timetic.value == 2 || modeattacking)) // there's not enough room for tics in splitscreen, don't even bother trying! { - ST_DrawPatchFromHud(HUD_TIMETICCOLON, sboperiod); // Period - ST_DrawPadNumFromHud(HUD_TICS, tictrn, 2); // Tics + ST_DrawPatchFromHud(HUD_TIMETICCOLON, sboperiod, V_HUDTRANS); // Period + ST_DrawPadNumFromHud(HUD_TICS, tictrn, 2, V_HUDTRANS); // Tics } } } @@ -672,7 +665,7 @@ static inline void ST_drawRings(void) { INT32 ringnum = max(stplyr->rings, 0); - ST_DrawPatchFromHudWS(HUD_RINGS, ((stplyr->rings <= 0 && leveltime/5 & 1) ? sboredrings : sborings)); + ST_DrawPatchFromHudWS(HUD_RINGS, ((!stplyr->spectator && stplyr->rings <= 0 && leveltime/5 & 1) ? sboredrings : sborings), ((stplyr->spectator) ? V_HUDTRANSHALF : V_HUDTRANS)); if (objectplacing) ringnum = op_currentdoomednum; @@ -685,7 +678,7 @@ static inline void ST_drawRings(void) ringnum += players[i].rings; } - ST_DrawNumFromHudWS(HUD_RINGSNUM, ringnum); + ST_DrawNumFromHudWS(HUD_RINGSNUM, ringnum, ((stplyr->spectator) ? V_HUDTRANSHALF : V_HUDTRANS)); } static void ST_drawLives(void) @@ -728,9 +721,68 @@ static void ST_drawLives(void) // x V_DrawScaledPatch(hudinfo[HUD_LIVESX].x, hudinfo[HUD_LIVESX].y + (v_splitflag ? -4 : 0), V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_HUDTRANS|v_splitflag, stlivex); - // lives + + // lives number + if ((netgame || multiplayer) && gametype == GT_COOP) + { + switch (cv_cooplives.value) + { + case 0: + V_DrawCharacter(hudinfo[HUD_LIVESNUM].x - 8, hudinfo[HUD_LIVESNUM].y + (v_splitflag ? -4 : 0), '\x16' | 0x80 | V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_HUDTRANS|v_splitflag, false); + return; + case 3: + { + INT32 i, sum = 0; + boolean canrespawn = (stplyr->lives > 0); + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; + + if (players[i].lives < 1) + continue; + + if (players[i].lives > 1) + canrespawn = true; + + sum += (players[i].lives); + } + V_DrawRightAlignedString(hudinfo[HUD_LIVESNUM].x, hudinfo[HUD_LIVESNUM].y + (v_splitflag ? -4 : 0), + V_SNAPTOLEFT|V_SNAPTOBOTTOM|(canrespawn ? V_HUDTRANS : V_HUDTRANSHALF)|v_splitflag, + va("%d",sum)); + return; + } +#if 0 // render the number of lives you COULD steal + case 2: + { + INT32 i, sum = 0; + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; + + if (&players[i] == stplyr) + continue; + + if (players[i].lives < 2) + continue; + + sum += (players[i].lives - 1); + } + V_DrawString(hudinfo[HUD_LIVESNUM].x, hudinfo[HUD_LIVESNUM].y + (v_splitflag ? -4 : 0), + V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_HUDTRANSHALF|v_splitflag, va("/%d",sum)); + } + // intentional fallthrough +#endif + default: + // don't return so the SP one can be drawn below + break; + } + } + V_DrawRightAlignedString(hudinfo[HUD_LIVESNUM].x, hudinfo[HUD_LIVESNUM].y + (v_splitflag ? -4 : 0), - V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_HUDTRANS|v_splitflag, va("%d",stplyr->lives)); + V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_HUDTRANS|v_splitflag, + va("%d",stplyr->lives)); } static void ST_drawLevelTitle(void) @@ -908,15 +960,25 @@ static void ST_drawFirstPersonHUD(void) /*#define NUMLINKCOLORS 14 static skincolors_t linkColor[NUMLINKCOLORS] = {SKINCOLOR_BEIGE, SKINCOLOR_LAVENDER, SKINCOLOR_AZURE, SKINCOLOR_PEACH, SKINCOLOR_ORANGE, - SKINCOLOR_MAGENTA, SKINCOLOR_SILVER, SKINCOLOR_SUPERGOLD4, SKINCOLOR_PINK, SKINCOLOR_RED, - SKINCOLOR_BLUE, SKINCOLOR_GREEN, SKINCOLOR_CYAN, SKINCOLOR_GOLD};*/ + SKINCOLOR_MAGENTA, SKINCOLOR_SILVER, SKINCOLOR_SUPERGOLD4, SKINCOLOR_PINK, SKINCOLOR_RED, + SKINCOLOR_BLUE, SKINCOLOR_GREEN, SKINCOLOR_CYAN, SKINCOLOR_GOLD};*/ -// 2.2+: (unix time 1470866042) Emerald, Aqua, Cyan, Blue, Pastel, Purple, Magenta, Rosy, Red, Orange, Gold, Yellow, Peridot -#define NUMLINKCOLORS 13 +// 2.2 indev list: (unix time 1470866042) Emerald, Aqua, Cyan, Blue, Pastel, Purple, Magenta, Rosy, Red, Orange, Gold, Yellow, Peridot +/*#define NUMLINKCOLORS 13 static skincolors_t linkColor[NUMLINKCOLORS] = -{SKINCOLOR_EMERALD, SKINCOLOR_AQUA, SKINCOLOR_CYAN, SKINCOLOR_BLUE, SKINCOLOR_PASTEL, - SKINCOLOR_PURPLE, SKINCOLOR_MAGENTA, SKINCOLOR_ROSY, SKINCOLOR_RED, SKINCOLOR_ORANGE, - SKINCOLOR_GOLD, SKINCOLOR_YELLOW, SKINCOLOR_PERIDOT}; +{SKINCOLOR_EMERALD, SKINCOLOR_AQUA, SKINCOLOR_CYAN, SKINCOLOR_BLUE, SKINCOLOR_PASTEL, + SKINCOLOR_PURPLE, SKINCOLOR_MAGENTA, SKINCOLOR_ROSY, SKINCOLOR_RED, SKINCOLOR_ORANGE, + SKINCOLOR_GOLD, SKINCOLOR_YELLOW, SKINCOLOR_PERIDOT};*/ + +// 2.2+ list: [19:59:52] Ruby > Red > Flame > Sunset > Orange > Gold > Yellow > Lime > Green > Aqua > cyan > Sky > Blue > Pastel > Purple > Bubblegum > Magenta > Rosy > repeat +// [20:00:25] Also Icy for the link freeze text color +// [20:04:03] I would start it on lime +#define NUMLINKCOLORS 18 +static skincolors_t linkColor[NUMLINKCOLORS] = +{SKINCOLOR_LIME, SKINCOLOR_EMERALD, SKINCOLOR_AQUA, SKINCOLOR_CYAN, SKINCOLOR_SKY, + SKINCOLOR_SAPPHIRE, SKINCOLOR_PASTEL, SKINCOLOR_PURPLE, SKINCOLOR_BUBBLEGUM, SKINCOLOR_MAGENTA, + SKINCOLOR_ROSY, SKINCOLOR_RUBY, SKINCOLOR_RED, SKINCOLOR_FLAME, SKINCOLOR_SUNSET, + SKINCOLOR_ORANGE, SKINCOLOR_GOLD, SKINCOLOR_YELLOW}; static void ST_drawNightsRecords(void) { @@ -1017,8 +1079,8 @@ static void ST_drawNiGHTSHUD(void) stplyr->linkcount > minlink) { skincolors_t colornum = linkColor[((stplyr->linkcount-1) / 5) % NUMLINKCOLORS]; - if (stplyr->powers[pw_nights_linkfreeze]) - colornum = SKINCOLOR_WHITE; + if (stplyr->powers[pw_nights_linkfreeze] && (!(stplyr->powers[pw_nights_linkfreeze] & 2) || (stplyr->powers[pw_nights_linkfreeze] > flashingtics))) + colornum = SKINCOLOR_ICY; if (stplyr->linktimer < 2*TICRATE/3) { @@ -1297,7 +1359,7 @@ static void ST_drawNiGHTSHUD(void) realnightstime = lowest_time/TICRATE; } - if (stplyr->powers[pw_flashing] > TICRATE ) // was hit + if (stplyr->powers[pw_flashing] > TICRATE) // was hit { UINT16 flashingLeft = stplyr->powers[pw_flashing]-(TICRATE); if (flashingLeft < TICRATE/2) // Start fading out @@ -1639,21 +1701,21 @@ static inline void ST_drawTeamName(void) static void ST_drawSpecialStageHUD(void) { if (totalrings > 0) - ST_DrawNumFromHudWS(HUD_SS_TOTALRINGS, totalrings); + ST_DrawNumFromHudWS(HUD_SS_TOTALRINGS, totalrings, V_HUDTRANS); if (leveltime < 5*TICRATE && totalrings > 0) { - ST_DrawPatchFromHud(HUD_GETRINGS, getall); - ST_DrawNumFromHud(HUD_GETRINGSNUM, totalrings); + ST_DrawPatchFromHud(HUD_GETRINGS, getall, V_HUDTRANS); + ST_DrawNumFromHud(HUD_GETRINGSNUM, totalrings, V_HUDTRANS); } if (sstimer) { V_DrawString(hudinfo[HUD_TIMELEFT].x, STRINGY(hudinfo[HUD_TIMELEFT].y), V_HUDTRANS, M_GetText("TIME LEFT")); - ST_DrawNumFromHud(HUD_TIMELEFTNUM, sstimer/TICRATE); + ST_DrawNumFromHud(HUD_TIMELEFTNUM, sstimer/TICRATE, V_HUDTRANS); } else - ST_DrawPatchFromHud(HUD_TIMEUP, timeup); + ST_DrawPatchFromHud(HUD_TIMEUP, timeup, V_HUDTRANS); } static INT32 ST_drawEmeraldHuntIcon(mobj_t *hunt, patch_t **patches, INT32 offset) @@ -1816,7 +1878,11 @@ static void ST_overlayDrawer(void) } // GAME OVER pic - if (G_GametypeUsesLives() && stplyr->lives <= 0 && !(hu_showscores && (netgame || multiplayer))) + if ((gametype == GT_COOP) + && (netgame || multiplayer) + && (cv_cooplives.value == 0)) + ; + else if (G_GametypeUsesLives() && stplyr->lives <= 0 && !(hu_showscores && (netgame || multiplayer))) { patch_t *p; @@ -1825,7 +1891,29 @@ static void ST_overlayDrawer(void) else p = sboover; - V_DrawScaledPatch((BASEVIDWIDTH - SHORT(p->width))/2, STRINGY(BASEVIDHEIGHT/2 - (SHORT(p->height)/2)), 0, p); + if ((gametype == GT_COOP) + && (netgame || multiplayer) + && (cv_cooplives.value != 1)) + { + INT32 i; + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; + + if (&players[i] == stplyr) + continue; + + if (players[i].lives > 0) + { + p = NULL; + break; + } + } + } + + if (p) + V_DrawScaledPatch((BASEVIDWIDTH - SHORT(p->width))/2, STRINGY(BASEVIDHEIGHT/2 - (SHORT(p->height)/2)) - (splitscreen ? 4 : 0), (stplyr->spectator ? V_HUDTRANSHALF : V_HUDTRANS), p); } @@ -1910,15 +1998,49 @@ static void ST_overlayDrawer(void) ) ST_drawLevelTitle(); - if (!hu_showscores && !splitscreen && netgame && displayplayer == consoleplayer) + if (!hu_showscores && (netgame || multiplayer) && displayplayer == consoleplayer) { - if (G_GametypeUsesLives() && stplyr->lives <= 0 && countdown != 1) - V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(132), 0, M_GetText("Press F12 to watch another player.")); + if (!stplyr->spectator && stplyr->exiting && cv_playersforexit.value && gametype == GT_COOP) + { + INT32 i, total = 0, exiting = 0; + + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i] || players[i].spectator) + continue; + if (players[i].lives <= 0) + continue; + + total++; + if (players[i].exiting) + exiting++; + } + + if (cv_playersforexit.value != 4) + { + total *= cv_playersforexit.value; + if (total % 4) total += 4; // round up + total /= 4; + } + + if (exiting >= total) + ; + else + { + total -= exiting; + V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(124), 0, va(M_GetText("%d more player%s required to exit."), total, ((total == 1) ? "" : "s"))); + if (!splitscreen) + V_DrawCenteredString(BASEVIDWIDTH/2, 132, 0, M_GetText("Press F12 to watch another player.")); + } + } + else if (!splitscreen && gametype != GT_COOP && (stplyr->exiting || (G_GametypeUsesLives() && stplyr->lives <= 0 && countdown != 1))) + V_DrawCenteredString(BASEVIDWIDTH/2, 132, 0, M_GetText("Press F12 to watch another player.")); else if (gametype == GT_HIDEANDSEEK && (!stplyr->spectator && !(stplyr->pflags & PF_TAGIT)) && (leveltime > hidetime * TICRATE)) { V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(116), 0, M_GetText("You cannot move while hiding.")); - V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(132), 0, M_GetText("Press F12 to watch another player.")); + if (!splitscreen) + V_DrawCenteredString(BASEVIDWIDTH/2, 132, 0, M_GetText("Press F12 to watch another player.")); } else if (!G_PlatformGametype() && stplyr->playerstate == PST_DEAD && stplyr->lives) //Death overrides spectator text. { @@ -1928,7 +2050,7 @@ static void ST_overlayDrawer(void) else V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(132), V_HUDTRANSHALF, M_GetText("Press Jump to respawn.")); } - else if (stplyr->spectator + else if (stplyr->spectator && (gametype != GT_COOP || stplyr->playerstate == PST_LIVE) #ifdef HAVE_BLUA && LUA_HudEnabled(hud_textspectator) #endif @@ -1938,11 +2060,38 @@ static void ST_overlayDrawer(void) if (G_GametypeHasTeams()) V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(132), V_HUDTRANSHALF, M_GetText("Press Fire to be assigned to a team.")); else if (G_IsSpecialStage(gamemap) && useNightsSS) - V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(132), V_HUDTRANSHALF, M_GetText("You cannot join the game until the stage has ended.")); - else + V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(132), V_HUDTRANSHALF, M_GetText("You cannot play until the stage has ended.")); + else if (gametype == GT_COOP && stplyr->lives <= 0) + { + if (cv_cooplives.value == 1 + && (netgame || multiplayer)) + { + INT32 i; + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; + + if (&players[i] == stplyr) + continue; + + if (players[i].lives > 1) + break; + } + + if (i != MAXPLAYERS) + V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(132)-(splitscreen ? 12 : 0), V_HUDTRANSHALF, M_GetText("You'll steal a life on respawn.")); + } + } + else if (!gametype == GT_COOP) V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(132), V_HUDTRANSHALF, M_GetText("Press Fire to enter the game.")); - V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(148), V_HUDTRANSHALF, M_GetText("Press F12 to watch another player.")); - V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(164), V_HUDTRANSHALF, M_GetText("Press Jump to float and Spin to sink.")); + if (!splitscreen) + { + V_DrawCenteredString(BASEVIDWIDTH/2, 148, V_HUDTRANSHALF, M_GetText("Press F12 to watch another player.")); + V_DrawCenteredString(BASEVIDWIDTH/2, 164, V_HUDTRANSHALF, M_GetText("Press Jump to float and Spin to sink.")); + } + else + V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(136), V_HUDTRANSHALF, M_GetText("Press Jump to float and Spin to sink.")); } } diff --git a/src/st_stuff.h b/src/st_stuff.h index c11559d2b..ddb119fb8 100644 --- a/src/st_stuff.h +++ b/src/st_stuff.h @@ -44,9 +44,6 @@ void ST_LoadGraphics(void); // face load graphics, called when skin changes void ST_LoadFaceGraphics(char *facestr, char *superstr, INT32 playernum); void ST_ReloadSkinFaceGraphics(void); -#ifdef DELFILE -void ST_UnLoadFaceGraphics(INT32 skinnum); -#endif void ST_doPaletteStuff(void); diff --git a/src/w_wad.c b/src/w_wad.c index caa2bb506..cf7034958 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -735,38 +735,6 @@ UINT16 W_InitFile(const char *filename) return wadfile->numlumps; } -#ifdef DELFILE -void W_UnloadWadFile(UINT16 num) -{ - INT32 i; - wadfile_t *delwad = wadfiles[num]; - lumpcache_t *lumpcache; - if (num == 0) - return; - CONS_Printf(M_GetText("Removing WAD %s...\n"), wadfiles[num]->filename); - - DEH_UnloadDehackedWad(num); - wadfiles[num] = NULL; - lumpcache = delwad->lumpcache; - numwadfiles--; -#ifdef HWRENDER - if (rendermode != render_soft && rendermode != render_none) - HWR_FreeTextureCache(); - M_AATreeFree(delwad->hwrcache); -#endif - if (*lumpcache) - { - for (i = 0;i < delwad->numlumps;i++) - Z_ChangeTag(lumpcache[i], PU_PURGELEVEL); - } - Z_Free(lumpcache); - fclose(delwad->handle); - Z_Free(delwad->filename); - Z_Free(delwad); - CONS_Printf(M_GetText("Done unloading WAD.\n")); -} -#endif - /** Tries to load a series of files. * All files are wads unless they have an extension of ".soc" or ".lua". *