Merge remote-tracking branch 'origin/master' into f_wipes

This commit is contained in:
Jaime Passos 2019-11-18 18:48:19 -03:00
commit 8a05afa1aa
52 changed files with 1002 additions and 414 deletions

View File

@ -90,6 +90,7 @@ SINT8 nodetoplayer[MAXNETNODES];
SINT8 nodetoplayer2[MAXNETNODES]; // say the numplayer for this node if any (splitscreen) SINT8 nodetoplayer2[MAXNETNODES]; // say the numplayer for this node if any (splitscreen)
UINT8 playerpernode[MAXNETNODES]; // used specialy for scplitscreen UINT8 playerpernode[MAXNETNODES]; // used specialy for scplitscreen
boolean nodeingame[MAXNETNODES]; // set false as nodes leave game boolean nodeingame[MAXNETNODES]; // set false as nodes leave game
tic_t servermaxping = 800; // server's max ping. Defaults to 800
static tic_t nettics[MAXNETNODES]; // what tic the client have received static tic_t nettics[MAXNETNODES]; // what tic the client have received
static tic_t supposedtics[MAXNETNODES]; // nettics prevision for smaller packet static tic_t supposedtics[MAXNETNODES]; // nettics prevision for smaller packet
static UINT8 nodewaiting[MAXNETNODES]; static UINT8 nodewaiting[MAXNETNODES];
@ -610,6 +611,11 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i)
rsp->health = LONG(players[i].mo->health); rsp->health = LONG(players[i].mo->health);
rsp->angle = (angle_t)LONG(players[i].mo->angle); rsp->angle = (angle_t)LONG(players[i].mo->angle);
#ifdef ROTSPRITE
rsp->rollangle = (angle_t)LONG(players[i].mo->rollangle);
#else
rsp->rollangle = 0;
#endif
rsp->x = LONG(players[i].mo->x); rsp->x = LONG(players[i].mo->x);
rsp->y = LONG(players[i].mo->y); rsp->y = LONG(players[i].mo->y);
rsp->z = LONG(players[i].mo->z); rsp->z = LONG(players[i].mo->z);
@ -760,6 +766,9 @@ static void resynch_read_player(resynch_pak *rsp)
//At this point, the player should have a body, whether they were respawned or not. //At this point, the player should have a body, whether they were respawned or not.
P_UnsetThingPosition(players[i].mo); P_UnsetThingPosition(players[i].mo);
players[i].mo->angle = (angle_t)LONG(rsp->angle); players[i].mo->angle = (angle_t)LONG(rsp->angle);
#ifdef ROTSPRITE
players[i].mo->rollangle = (angle_t)LONG(rsp->rollangle);
#endif
players[i].mo->eflags = (UINT16)SHORT(rsp->eflags); players[i].mo->eflags = (UINT16)SHORT(rsp->eflags);
players[i].mo->flags = LONG(rsp->flags); players[i].mo->flags = LONG(rsp->flags);
players[i].mo->flags2 = LONG(rsp->flags2); players[i].mo->flags2 = LONG(rsp->flags2);
@ -2588,9 +2597,13 @@ static void Command_Nodes(void)
if (playeringame[i]) if (playeringame[i])
{ {
CONS_Printf("%.2u: %*s", i, (int)maxlen, player_names[i]); CONS_Printf("%.2u: %*s", i, (int)maxlen, player_names[i]);
CONS_Printf(" - %.2d", playernode[i]);
if (I_GetNodeAddress && (address = I_GetNodeAddress(playernode[i])) != NULL) if (playernode[i] != UINT8_MAX)
CONS_Printf(" - %s", address); {
CONS_Printf(" - node %.2d", playernode[i]);
if (I_GetNodeAddress && (address = I_GetNodeAddress(playernode[i])) != NULL)
CONS_Printf(" - %s", address);
}
if (IsPlayerAdmin(i)) if (IsPlayerAdmin(i))
CONS_Printf(M_GetText(" (verified admin)")); CONS_Printf(M_GetText(" (verified admin)"));
@ -3221,10 +3234,10 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
{ {
const char *address; const char *address;
if (I_GetNodeAddress && (address = I_GetNodeAddress(node)) != NULL) if (I_GetNodeAddress && (address = I_GetNodeAddress(node)) != NULL)
HU_AddChatText(va("\x82*%s has joined the game (node %d) (%s)", player_names[newplayernum], node, address), false); // merge join notification + IP to avoid clogging console/chat. HU_AddChatText(va("\x82*%s has joined the game (player %d) (%s)", player_names[newplayernum], newplayernum, address), false); // merge join notification + IP to avoid clogging console/chat.
} }
else else
HU_AddChatText(va("\x82*%s has joined the game (node %d)", player_names[newplayernum], node), false); // if you don't wanna see the join address. HU_AddChatText(va("\x82*%s has joined the game (player %d)", player_names[newplayernum], newplayernum), false); // if you don't wanna see the join address.
} }
if (server && multiplayer && motd[0] != '\0') if (server && multiplayer && motd[0] != '\0')
@ -4204,10 +4217,12 @@ static void HandlePacketFromPlayer(SINT8 node)
//Update client ping table from the server. //Update client ping table from the server.
if (client) if (client)
{ {
INT32 i; UINT8 i;
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i]) if (playeringame[i])
playerpingtable[i] = (tic_t)netbuffer->u.pingtable[i]; playerpingtable[i] = (tic_t)netbuffer->u.pingtable[i];
servermaxping = (tic_t)netbuffer->u.pingtable[MAXPLAYERS];
} }
break; break;
@ -4729,6 +4744,14 @@ void TryRunTics(tic_t realtics)
} }
} }
/*
Ping Update except better:
We call this once per second and check for people's pings. If their ping happens to be too high, we increment some timer and kick them out.
If they're not lagging, decrement the timer by 1. Of course, reset all of this if they leave.
*/
static INT32 pingtimeout[MAXPLAYERS];
static inline void PingUpdate(void) static inline void PingUpdate(void)
{ {
INT32 i; INT32 i;
@ -4749,6 +4772,8 @@ static inline void PingUpdate(void)
laggers[i] = true; laggers[i] = true;
numlaggers++; numlaggers++;
} }
else
pingtimeout[i] = 0;
} }
//kick lagging players... unless everyone but the server's ping sucks. //kick lagging players... unless everyone but the server's ping sucks.
@ -4759,12 +4784,27 @@ static inline void PingUpdate(void)
{ {
if (playeringame[i] && laggers[i]) if (playeringame[i] && laggers[i])
{ {
char buf[2]; pingtimeout[i]++;
if (pingtimeout[i] > cv_pingtimeout.value)
// ok your net has been bad for too long, you deserve to die.
{
char buf[2];
buf[0] = (char)i; pingtimeout[i] = 0;
buf[1] = KICK_MSG_PING_HIGH;
SendNetXCmd(XD_KICK, &buf, 2); buf[0] = (char)i;
buf[1] = KICK_MSG_PING_HIGH;
SendNetXCmd(XD_KICK, &buf, 2);
}
} }
/*
you aren't lagging,
but you aren't free yet.
In case you'll keep spiking,
we just make the timer go back down. (Very unstable net must still get kicked).
*/
else
pingtimeout[i] = (pingtimeout[i] == 0 ? 0 : pingtimeout[i]-1);
} }
} }
} }
@ -4779,10 +4819,13 @@ static inline void PingUpdate(void)
realpingtable[i] = 0; //Reset each as we go. realpingtable[i] = 0; //Reset each as we go.
} }
// send the server's maxping as last element of our ping table. This is useful to let us know when we're about to get kicked.
netbuffer->u.pingtable[MAXPLAYERS] = cv_maxping.value;
//send out our ping packets //send out our ping packets
for (i = 0; i < MAXNETNODES; i++) for (i = 0; i < MAXNETNODES; i++)
if (nodeingame[i]) if (nodeingame[i])
HSendPacket(i, true, 0, sizeof(INT32) * MAXPLAYERS); HSendPacket(i, true, 0, sizeof(INT32) * (MAXPLAYERS+1));
pingmeasurecount = 1; //Reset count pingmeasurecount = 1; //Reset count
} }
@ -4812,7 +4855,7 @@ void NetUpdate(void)
if (server) if (server)
{ {
if (netgame && !(gametime % 255)) if (netgame && !(gametime % 35)) // update once per second.
PingUpdate(); PingUpdate();
// update node latency values so we can take an average later. // update node latency values so we can take an average later.
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)

View File

@ -255,6 +255,7 @@ typedef struct
INT32 health; INT32 health;
angle_t angle; angle_t angle;
angle_t rollangle;
fixed_t x; fixed_t x;
fixed_t y; fixed_t y;
fixed_t z; fixed_t z;
@ -423,9 +424,9 @@ typedef struct
serverrefuse_pak serverrefuse; // 65025 bytes (somehow I feel like those values are garbage...) serverrefuse_pak serverrefuse; // 65025 bytes (somehow I feel like those values are garbage...)
askinfo_pak askinfo; // 61 bytes askinfo_pak askinfo; // 61 bytes
msaskinfo_pak msaskinfo; // 22 bytes msaskinfo_pak msaskinfo; // 22 bytes
plrinfo playerinfo[MAXPLAYERS]; // 1152 bytes (I'd say 36~38) plrinfo playerinfo[MAXPLAYERS]; // 576 bytes(?)
plrconfig playerconfig[MAXPLAYERS]; // (up to) 896 bytes (welp they ARE) plrconfig playerconfig[MAXPLAYERS]; // (up to) 528 bytes(?)
UINT32 pingtable[MAXPLAYERS]; // 128 bytes UINT32 pingtable[MAXPLAYERS+1]; // 68 bytes
} u; // This is needed to pack diff packet types data together } u; // This is needed to pack diff packet types data together
} ATTRPACK doomdata_t; } ATTRPACK doomdata_t;
@ -487,6 +488,7 @@ extern tic_t jointimeout;
extern UINT16 pingmeasurecount; extern UINT16 pingmeasurecount;
extern UINT32 realpingtable[MAXPLAYERS]; extern UINT32 realpingtable[MAXPLAYERS];
extern UINT32 playerpingtable[MAXPLAYERS]; extern UINT32 playerpingtable[MAXPLAYERS];
extern tic_t servermaxping;
extern consvar_t cv_joinnextround, cv_allownewplayer, cv_maxplayers, cv_resynchattempts, cv_blamecfail, cv_maxsend, cv_noticedownload, cv_downloadspeed; extern consvar_t cv_joinnextround, cv_allownewplayer, cv_maxplayers, cv_resynchattempts, cv_blamecfail, cv_maxsend, cv_noticedownload, cv_downloadspeed;

View File

@ -180,6 +180,9 @@ void D_ProcessEvents(void)
if (M_ScreenshotResponder(ev)) if (M_ScreenshotResponder(ev))
continue; // ate the event continue; // ate the event
if (WipeStageTitle)
continue;
if (gameaction == ga_nothing && gamestate == GS_TITLESCREEN) if (gameaction == ga_nothing && gamestate == GS_TITLESCREEN)
{ {
if (cht_Responder(ev)) if (cht_Responder(ev))
@ -441,6 +444,17 @@ static void D_Display(void)
if (rendermode != render_none) if (rendermode != render_none)
{ {
F_WipeEndScreen(); F_WipeEndScreen();
// Funny.
#ifndef LEVELWIPES
if (WipeStageTitle && st_overlay)
{
lt_ticker--;
lt_lasttic = lt_ticker;
ST_preLevelTitleCardDrawer(0, false);
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, levelfadecol);
F_WipeStartScreen();
}
#endif
F_RunWipe(wipetypepost, gamestate != GS_TIMEATTACK && gamestate != GS_TITLESCREEN); F_RunWipe(wipetypepost, gamestate != GS_TIMEATTACK && gamestate != GS_TITLESCREEN);
} }
@ -742,14 +756,6 @@ void D_StartTitle(void)
// empty maptol so mario/etc sounds don't play in sound test when they shouldn't // empty maptol so mario/etc sounds don't play in sound test when they shouldn't
maptol = 0; 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; gameaction = ga_nothing;
displayplayer = consoleplayer = 0; displayplayer = consoleplayer = 0;
gametype = GT_COOP; gametype = GT_COOP;

View File

@ -87,6 +87,7 @@ static void JoinTimeout_OnChange(void);
static void CoopStarposts_OnChange(void); static void CoopStarposts_OnChange(void);
static void CoopLives_OnChange(void); static void CoopLives_OnChange(void);
static void ExitMove_OnChange(void);
static void Ringslinger_OnChange(void); static void Ringslinger_OnChange(void);
static void Gravity_OnChange(void); static void Gravity_OnChange(void);
@ -223,8 +224,8 @@ consvar_t cv_allowseenames = {"allowseenames", "Yes", CV_NETVAR, CV_YesNo, NULL,
#endif #endif
// names // names
consvar_t cv_playername = {"name", "Sonic", CV_CALL|CV_NOINIT, NULL, Name_OnChange, 0, NULL, NULL, 0, 0, NULL}; 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_CALL|CV_NOINIT, NULL, Name2_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};
// player colors // 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_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}; consvar_t cv_playercolor2 = {"color2", "Orange", CV_CALL|CV_NOINIT, Color_cons_t, Color2_OnChange, 0, NULL, NULL, 0, 0, NULL};
@ -233,8 +234,6 @@ consvar_t cv_skin = {"skin", DEFAULTSKIN, CV_CALL|CV_NOINIT, NULL, Skin_OnChange
consvar_t cv_skin2 = {"skin2", DEFAULTSKIN2, CV_CALL|CV_NOINIT, NULL, Skin2_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 // 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_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_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_defaultskin = {"defaultskin", DEFAULTSKIN, CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
@ -343,6 +342,14 @@ consvar_t cv_nettimeout = {"nettimeout", "350", CV_CALL|CV_SAVE, nettimeout_cons
static CV_PossibleValue_t jointimeout_cons_t[] = {{5*TICRATE, "MIN"}, {60*TICRATE, "MAX"}, {0, NULL}}; static CV_PossibleValue_t jointimeout_cons_t[] = {{5*TICRATE, "MIN"}, {60*TICRATE, "MAX"}, {0, NULL}};
consvar_t cv_jointimeout = {"jointimeout", "350", CV_CALL|CV_SAVE, jointimeout_cons_t, JoinTimeout_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_jointimeout = {"jointimeout", "350", CV_CALL|CV_SAVE, jointimeout_cons_t, JoinTimeout_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_maxping = {"maxping", "0", CV_SAVE, CV_Unsigned, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_maxping = {"maxping", "0", CV_SAVE, CV_Unsigned, NULL, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t pingtimeout_cons_t[] = {{8, "MIN"}, {120, "MAX"}, {0, NULL}};
consvar_t cv_pingtimeout = {"pingtimeout", "10", CV_SAVE, pingtimeout_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
// show your ping on the HUD next to framerate. Defaults to warning only (shows up if your ping is > maxping)
static CV_PossibleValue_t showping_cons_t[] = {{0, "Off"}, {1, "Always"}, {2, "Warning"}, {0, NULL}};
consvar_t cv_showping = {"showping", "Warning", CV_SAVE, showping_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
// Intermission time Tails 04-19-2002 // Intermission time Tails 04-19-2002
static CV_PossibleValue_t inttime_cons_t[] = {{0, "MIN"}, {3600, "MAX"}, {0, NULL}}; static CV_PossibleValue_t inttime_cons_t[] = {{0, "MIN"}, {3600, "MAX"}, {0, NULL}};
consvar_t cv_inttime = {"inttime", "10", 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};
@ -355,9 +362,12 @@ consvar_t cv_cooplives = {"cooplives", "Avoid Game Over", CV_NETVAR|CV_CALL|CV_C
static CV_PossibleValue_t advancemap_cons_t[] = {{0, "Off"}, {1, "Next"}, {2, "Random"}, {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}; 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, "1/4"}, {2, "Half"}, {3, "3/4"}, {4, "All"}, {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_playersforexit = {"playersforexit", "All", CV_NETVAR, playersforexit_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_exitmove = {"exitmove", "Off", CV_NETVAR|CV_CALL, CV_OnOff, ExitMove_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_runscripts = {"runscripts", "Yes", 0, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_runscripts = {"runscripts", "Yes", 0, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_pause = {"pausepermission", "Server", CV_NETVAR, pause_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_pause = {"pausepermission", "Server", CV_NETVAR, pause_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
@ -516,6 +526,7 @@ void D_RegisterServerCommands(void)
CV_RegisterVar(&cv_inttime); CV_RegisterVar(&cv_inttime);
CV_RegisterVar(&cv_advancemap); CV_RegisterVar(&cv_advancemap);
CV_RegisterVar(&cv_playersforexit); CV_RegisterVar(&cv_playersforexit);
CV_RegisterVar(&cv_exitmove);
CV_RegisterVar(&cv_timelimit); CV_RegisterVar(&cv_timelimit);
CV_RegisterVar(&cv_playbackspeed); CV_RegisterVar(&cv_playbackspeed);
CV_RegisterVar(&cv_forceskin); CV_RegisterVar(&cv_forceskin);
@ -579,6 +590,8 @@ void D_RegisterServerCommands(void)
CV_RegisterVar(&cv_skipmapcheck); CV_RegisterVar(&cv_skipmapcheck);
CV_RegisterVar(&cv_sleep); CV_RegisterVar(&cv_sleep);
CV_RegisterVar(&cv_maxping); CV_RegisterVar(&cv_maxping);
CV_RegisterVar(&cv_pingtimeout);
CV_RegisterVar(&cv_showping);
#ifdef SEENAMES #ifdef SEENAMES
CV_RegisterVar(&cv_allowseenames); CV_RegisterVar(&cv_allowseenames);
@ -670,10 +683,8 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_playercolor2); CV_RegisterVar(&cv_playercolor2);
CV_RegisterVar(&cv_skin2); CV_RegisterVar(&cv_skin2);
// saved versions of the above six // saved versions of the above six
CV_RegisterVar(&cv_defaultplayername);
CV_RegisterVar(&cv_defaultplayercolor); CV_RegisterVar(&cv_defaultplayercolor);
CV_RegisterVar(&cv_defaultskin); CV_RegisterVar(&cv_defaultskin);
CV_RegisterVar(&cv_defaultplayername2);
CV_RegisterVar(&cv_defaultplayercolor2); CV_RegisterVar(&cv_defaultplayercolor2);
CV_RegisterVar(&cv_defaultskin2); CV_RegisterVar(&cv_defaultskin2);
@ -3007,7 +3018,7 @@ static void Command_Verify_f(void)
if (COM_Argc() != 2) if (COM_Argc() != 2)
{ {
CONS_Printf(M_GetText("promote <node>: give admin privileges to a node\n")); CONS_Printf(M_GetText("promote <playernum>: give admin privileges to a player\n"));
return; return;
} }
@ -3063,7 +3074,7 @@ static void Command_RemoveAdmin_f(void)
if (COM_Argc() != 2) if (COM_Argc() != 2)
{ {
CONS_Printf(M_GetText("demote <node>: remove admin privileges from a node\n")); CONS_Printf(M_GetText("demote <playernum>: remove admin privileges from a player\n"));
return; return;
} }
@ -3782,6 +3793,17 @@ static void CoopLives_OnChange(void)
} }
} }
static void ExitMove_OnChange(void)
{
if (!(netgame || multiplayer) || gametype != GT_COOP)
return;
if (cv_exitmove.value)
CONS_Printf(M_GetText("Players can now move after completing the level.\n"));
else
CONS_Printf(M_GetText("Players can no longer move after completing the level.\n"));
}
UINT32 timelimitintics = 0; UINT32 timelimitintics = 0;
/** Deals with a timelimit change by printing the change to the console. /** Deals with a timelimit change by printing the change to the console.

View File

@ -26,10 +26,8 @@ extern consvar_t cv_playername2;
extern consvar_t cv_playercolor2; extern consvar_t cv_playercolor2;
extern consvar_t cv_skin2; extern consvar_t cv_skin2;
// saved versions of the above six // saved versions of the above six
extern consvar_t cv_defaultplayername;
extern consvar_t cv_defaultplayercolor; extern consvar_t cv_defaultplayercolor;
extern consvar_t cv_defaultskin; extern consvar_t cv_defaultskin;
extern consvar_t cv_defaultplayername2;
extern consvar_t cv_defaultplayercolor2; extern consvar_t cv_defaultplayercolor2;
extern consvar_t cv_defaultskin2; extern consvar_t cv_defaultskin2;
@ -96,7 +94,7 @@ extern consvar_t cv_recycler;
extern consvar_t cv_itemfinder; extern consvar_t cv_itemfinder;
extern consvar_t cv_inttime, cv_coopstarposts, cv_cooplives, cv_advancemap, cv_playersforexit; extern consvar_t cv_inttime, cv_coopstarposts, cv_cooplives, cv_advancemap, cv_playersforexit, cv_exitmove;
extern consvar_t cv_overtime; extern consvar_t cv_overtime;
extern consvar_t cv_startinglives; extern consvar_t cv_startinglives;
@ -108,6 +106,9 @@ extern consvar_t cv_ringslinger, cv_soundtest;
extern consvar_t cv_specialrings, cv_powerstones, cv_matchboxes, cv_competitionboxes; extern consvar_t cv_specialrings, cv_powerstones, cv_matchboxes, cv_competitionboxes;
extern consvar_t cv_maxping; extern consvar_t cv_maxping;
extern consvar_t cv_pingtimeout;
extern consvar_t cv_showping;
extern consvar_t cv_skipmapcheck; extern consvar_t cv_skipmapcheck;

View File

@ -716,7 +716,7 @@ void SV_FileSendTicker(void)
if (ram) if (ram)
M_Memcpy(p->data, &f->id.ram[transfer[i].position], size); M_Memcpy(p->data, &f->id.ram[transfer[i].position], size);
else if (fread(p->data, 1, size, transfer[i].currentfile) != size) else if (fread(p->data, 1, size, transfer[i].currentfile) != size)
I_Error("SV_FileSendTicker: can't read %s byte on %s at %d because %s", sizeu1(size), f->id.filename, transfer[i].position, strerror(ferror(transfer[i].currentfile))); I_Error("SV_FileSendTicker: can't read %s byte on %s at %d because %s", sizeu1(size), f->id.filename, transfer[i].position, M_FileError(transfer[i].currentfile));
p->position = LONG(transfer[i].position); p->position = LONG(transfer[i].position);
// Put flag so receiver knows the total size // Put flag so receiver knows the total size
if (transfer[i].position + size == f->size) if (transfer[i].position + size == f->size)
@ -794,7 +794,7 @@ void Got_Filetxpak(void)
// We can receive packet in the wrong order, anyway all os support gaped file // We can receive packet in the wrong order, anyway all os support gaped file
fseek(file->file, pos, SEEK_SET); fseek(file->file, pos, SEEK_SET);
if (fwrite(netbuffer->u.filetxpak.data,size,1,file->file) != 1) if (fwrite(netbuffer->u.filetxpak.data,size,1,file->file) != 1)
I_Error("Can't write to %s: %s\n",filename, strerror(ferror(file->file))); I_Error("Can't write to %s: %s\n",filename, M_FileError(file->file));
file->currentsize += size; file->currentsize += size;
// Finished? // Finished?

View File

@ -151,6 +151,7 @@ typedef enum
/*** misc ***/ /*** misc ***/
PF_FORCESTRAFE = 1<<28, // Turning inputs are translated into strafing inputs PF_FORCESTRAFE = 1<<28, // Turning inputs are translated into strafing inputs
PF_CANCARRY = 1<<29, // Can carry another player? PF_CANCARRY = 1<<29, // Can carry another player?
PF_FINISHED = 1<<30, // The player finished the level. NOT the same as exiting
// up to 1<<31 is free // up to 1<<31 is free
} pflags_t; } pflags_t;

View File

@ -1201,6 +1201,14 @@ static void readlevelheader(MYFILE *f, INT32 num)
word2 = tmp += 2; word2 = tmp += 2;
i = atoi(word2); // used for numerical settings i = atoi(word2); // used for numerical settings
if (fastcmp(word, "LEVELNAME"))
{
deh_strlcpy(mapheaderinfo[num-1]->lvlttl, word2,
sizeof(mapheaderinfo[num-1]->lvlttl), va("Level header %d: levelname", num));
strlcpy(mapheaderinfo[num-1]->selectheading, word2, sizeof(mapheaderinfo[num-1]->selectheading)); // not deh_ so only complains once
continue;
}
// CHEAP HACK: move this over here for lowercase subtitles // CHEAP HACK: move this over here for lowercase subtitles
if (fastcmp(word, "SUBTITLE")) if (fastcmp(word, "SUBTITLE"))
{ {
@ -1344,12 +1352,6 @@ static void readlevelheader(MYFILE *f, INT32 num)
} }
// Strings that can be truncated // Strings that can be truncated
else if (fastcmp(word, "LEVELNAME"))
{
deh_strlcpy(mapheaderinfo[num-1]->lvlttl, word2,
sizeof(mapheaderinfo[num-1]->lvlttl), va("Level header %d: levelname", num));
strlcpy(mapheaderinfo[num-1]->selectheading, word2, sizeof(mapheaderinfo[num-1]->selectheading)); // not deh_ so only complains once
}
else if (fastcmp(word, "SELECTHEADING")) else if (fastcmp(word, "SELECTHEADING"))
{ {
deh_strlcpy(mapheaderinfo[num-1]->selectheading, word2, deh_strlcpy(mapheaderinfo[num-1]->selectheading, word2,
@ -1573,6 +1575,20 @@ static void readlevelheader(MYFILE *f, INT32 num)
else else
mapheaderinfo[num-1]->levelflags &= ~LF_MIXNIGHTSCOUNTDOWN; mapheaderinfo[num-1]->levelflags &= ~LF_MIXNIGHTSCOUNTDOWN;
} }
else if (fastcmp(word, "WARNINGTITLE"))
{
if (i || word2[0] == 'T' || word2[0] == 'Y')
mapheaderinfo[num-1]->levelflags |= LF_WARNINGTITLE;
else
mapheaderinfo[num-1]->levelflags &= ~LF_WARNINGTITLE;
}
else if (fastcmp(word, "NOTITLECARD"))
{
if (i || word2[0] == 'T' || word2[0] == 'Y')
mapheaderinfo[num-1]->levelflags |= LF_NOTITLECARD;
else
mapheaderinfo[num-1]->levelflags &= ~LF_NOTITLECARD;
}
// Individual triggers for menu flags // Individual triggers for menu flags
else if (fastcmp(word, "HIDDEN")) else if (fastcmp(word, "HIDDEN"))
@ -5343,6 +5359,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_FSGNA", "S_FSGNA",
"S_FSGNB", "S_FSGNB",
"S_FSGNC", "S_FSGNC",
"S_FSGND",
// Black Eggman (Boss 7) // Black Eggman (Boss 7)
"S_BLACKEGG_STND", "S_BLACKEGG_STND",
@ -7322,13 +7339,9 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_FIREFLOWER2", "S_FIREFLOWER2",
"S_FIREFLOWER3", "S_FIREFLOWER3",
"S_FIREFLOWER4", "S_FIREFLOWER4",
"S_FIREBALL1", "S_FIREBALL",
"S_FIREBALL2", "S_FIREBALLTRAIL1",
"S_FIREBALL3", "S_FIREBALLTRAIL2",
"S_FIREBALL4",
"S_FIREBALLEXP1",
"S_FIREBALLEXP2",
"S_FIREBALLEXP3",
"S_SHELL", "S_SHELL",
"S_PUMA_START1", "S_PUMA_START1",
"S_PUMA_START2", "S_PUMA_START2",
@ -7497,6 +7510,9 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_POPHAT_SHOOT1", "S_POPHAT_SHOOT1",
"S_POPHAT_SHOOT2", "S_POPHAT_SHOOT2",
"S_POPHAT_SHOOT3", "S_POPHAT_SHOOT3",
"S_POPHAT_SHOOT4",
"S_POPSHOT",
"S_POPSHOT_TRAIL",
"S_HIVEELEMENTAL_LOOK", "S_HIVEELEMENTAL_LOOK",
"S_HIVEELEMENTAL_PREPARE1", "S_HIVEELEMENTAL_PREPARE1",
@ -8317,6 +8333,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_BLUEGOOMBA", "MT_BLUEGOOMBA",
"MT_FIREFLOWER", "MT_FIREFLOWER",
"MT_FIREBALL", "MT_FIREBALL",
"MT_FIREBALLTRAIL",
"MT_SHELL", "MT_SHELL",
"MT_PUMA", "MT_PUMA",
"MT_PUMATRAIL", "MT_PUMATRAIL",
@ -8361,6 +8378,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_PENGUINATOR", "MT_PENGUINATOR",
"MT_POPHAT", "MT_POPHAT",
"MT_POPSHOT", "MT_POPSHOT",
"MT_POPSHOT_TRAIL",
"MT_HIVEELEMENTAL", "MT_HIVEELEMENTAL",
"MT_BUMBLEBORE", "MT_BUMBLEBORE",
@ -8570,6 +8588,7 @@ static const char *const PLAYERFLAG_LIST[] = {
/*** misc ***/ /*** misc ***/
"FORCESTRAFE", // Translate turn inputs into strafe inputs "FORCESTRAFE", // Translate turn inputs into strafe inputs
"CANCARRY", // Can carry? "CANCARRY", // Can carry?
"FINISHED",
NULL // stop loop here. NULL // stop loop here.
}; };
@ -9012,6 +9031,8 @@ struct {
{"LF_NOZONE",LF_NOZONE}, {"LF_NOZONE",LF_NOZONE},
{"LF_SAVEGAME",LF_SAVEGAME}, {"LF_SAVEGAME",LF_SAVEGAME},
{"LF_MIXNIGHTSCOUNTDOWN",LF_MIXNIGHTSCOUNTDOWN}, {"LF_MIXNIGHTSCOUNTDOWN",LF_MIXNIGHTSCOUNTDOWN},
{"LF_NOTITLECARD",LF_NOTITLECARD},
{"LF_WARNINGTITLE",LF_WARNINGTITLE},
// And map flags // And map flags
{"LF2_HIDEINMENU",LF2_HIDEINMENU}, {"LF2_HIDEINMENU",LF2_HIDEINMENU},
{"LF2_HIDEINSTATS",LF2_HIDEINSTATS}, {"LF2_HIDEINSTATS",LF2_HIDEINSTATS},

View File

@ -98,6 +98,9 @@ void I_FinishUpdate (void)
if (cv_ticrate.value) if (cv_ticrate.value)
SCR_DisplayTicRate(); SCR_DisplayTicRate();
if (cv_showping.value && netgame && consoleplayer != serverplayer)
SCR_DisplayLocalPing();
//blast it to the screen //blast it to the screen
// this code sucks // this code sucks
//memcpy(dascreen,screens[0],screenwidth*screenheight); //memcpy(dascreen,screens[0],screenwidth*screenheight);

View File

@ -349,6 +349,8 @@ typedef struct
#define LF_NOZONE 16 ///< Don't include "ZONE" on level title #define LF_NOZONE 16 ///< Don't include "ZONE" on level title
#define LF_SAVEGAME 32 ///< Save the game upon loading this level #define LF_SAVEGAME 32 ///< Save the game upon loading this level
#define LF_MIXNIGHTSCOUNTDOWN 64 ///< Play sfx_timeup instead of music change for NiGHTS countdown #define LF_MIXNIGHTSCOUNTDOWN 64 ///< Play sfx_timeup instead of music change for NiGHTS countdown
#define LF_WARNINGTITLE 128 ///< WARNING! WARNING! WARNING! WARNING!
#define LF_NOTITLECARD 256 ///< Don't start the title card
#define LF2_HIDEINMENU 1 ///< Hide in the multiplayer menu #define LF2_HIDEINMENU 1 ///< Hide in the multiplayer menu
#define LF2_HIDEINSTATS 2 ///< Hide in the statistics screen #define LF2_HIDEINSTATS 2 ///< Hide in the statistics screen

View File

@ -1389,10 +1389,13 @@ void F_StartGameEvaluation(void)
// Credits option in secrets menu // Credits option in secrets menu
if (cursaveslot == -1) if (cursaveslot == -1)
{ {
S_FadeOutStopMusic(2*MUSICRATE);
F_StartGameEnd(); F_StartGameEnd();
return; return;
} }
S_FadeOutStopMusic(5*MUSICRATE);
G_SetGamestate(GS_EVALUATION); G_SetGamestate(GS_EVALUATION);
// Just in case they're open ... somehow // Just in case they're open ... somehow
@ -1639,7 +1642,7 @@ void F_StartEnding(void)
gameaction = ga_nothing; gameaction = ga_nothing;
paused = false; paused = false;
CON_ToggleOff(); CON_ToggleOff();
S_StopMusic(); // todo: placeholder S_StopMusic();
S_StopSounds(); S_StopSounds();
finalecount = -10; // what? this totally isn't a hack. why are you asking? finalecount = -10; // what? this totally isn't a hack. why are you asking?
@ -1720,6 +1723,9 @@ void F_EndingTicker(void)
return; return;
} }
if (finalecount == -8)
S_ChangeMusicInternal((goodending ? "_endg" : "_endb"), false);
if (goodending && finalecount == INFLECTIONPOINT) // time to swap some assets if (goodending && finalecount == INFLECTIONPOINT) // time to swap some assets
{ {
endegrk[0] = W_CachePatchName("ENDEGRK2", PU_LEVEL); endegrk[0] = W_CachePatchName("ENDEGRK2", PU_LEVEL);
@ -2149,7 +2155,6 @@ void F_StartGameEnd(void)
gameaction = ga_nothing; gameaction = ga_nothing;
paused = false; paused = false;
CON_ToggleOff(); CON_ToggleOff();
S_StopMusic();
S_StopSounds(); S_StopSounds();
// In case menus are still up?!! // In case menus are still up?!!
@ -2592,6 +2597,10 @@ void F_TitleScreenDrawer(void)
if (gamestate != GS_TITLESCREEN && gamestate != GS_WAITINGPLAYERS) if (gamestate != GS_TITLESCREEN && gamestate != GS_WAITINGPLAYERS)
return; return;
// Don't draw if title mode is set to Old/None and the patch isn't there
if (!ttwing && (curttmode == TTMODE_OLD || curttmode == TTMODE_NONE))
return;
// rei|miru: use title pics? // rei|miru: use title pics?
hidepics = curhidepics; hidepics = curhidepics;
if (hidepics) if (hidepics)

View File

@ -142,7 +142,7 @@ void F_MenuPresTicker(boolean run);
extern boolean WipeInAction; extern boolean WipeInAction;
extern boolean WipeInLevel; extern boolean WipeInLevel;
extern INT32 lastwipetic; extern boolean WipeStageTitle;
typedef enum typedef enum
{ {
@ -167,6 +167,11 @@ extern wipestyleflags_t wipestyleflags;
#define FADEBLUEFACTOR 10 #define FADEBLUEFACTOR 10
extern UINT8 wipecolorfill; extern UINT8 wipecolorfill;
extern INT32 lastwipetic;
// Don't know where else to place this constant
// But this file seems appropriate
#define PRELEVELTIME 24 // frames in tics
void F_WipeStartScreen(void); void F_WipeStartScreen(void);
void F_WipeEndScreen(void); void F_WipeEndScreen(void);

View File

@ -19,6 +19,7 @@
#include "r_draw.h" // transtable #include "r_draw.h" // transtable
#include "p_pspr.h" // tr_transxxx #include "p_pspr.h" // tr_transxxx
#include "p_local.h" #include "p_local.h"
#include "st_stuff.h"
#include "w_wad.h" #include "w_wad.h"
#include "z_zone.h" #include "z_zone.h"
@ -30,7 +31,6 @@
#include "m_misc.h" // movie mode #include "m_misc.h" // movie mode
#include "doomstat.h" #include "doomstat.h"
#include "st_stuff.h"
#ifdef HAVE_BLUA #ifdef HAVE_BLUA
#include "lua_hud.h" // level title #include "lua_hud.h" // level title
@ -92,6 +92,7 @@ UINT8 wipedefs[NUMWIPEDEFS] = {
boolean WipeInAction = false; boolean WipeInAction = false;
boolean WipeInLevel = false; boolean WipeInLevel = false;
boolean WipeStageTitle = false;
INT32 lastwipetic = 0; INT32 lastwipetic = 0;
wipestyle_t wipestyle = WIPESTYLE_NORMAL; wipestyle_t wipestyle = WIPESTYLE_NORMAL;
@ -193,22 +194,14 @@ static fademask_t *F_GetFadeMask(UINT8 masknum, UINT8 scrnnum) {
*/ */
void F_WipeStageTitle(void) void F_WipeStageTitle(void)
{ {
if (wipestyle == WIPESTYLE_LEVEL // draw level title
&& (!titlemapinaction) if ((WipeStageTitle && st_overlay)
&& (wipestyleflags & WSF_FADEIN) && (wipestyle == WIPESTYLE_LEVEL)
&& *mapheaderinfo[gamemap-1]->lvlttl != '\0' && !(mapheaderinfo[gamemap-1]->levelflags & LF_NOTITLECARD)
#ifdef HAVE_BLUA && *mapheaderinfo[gamemap-1]->lvlttl != '\0')
&& LUA_HudEnabled(hud_stagetitle)
#endif
)
{ {
stplyr = &players[consoleplayer]; ST_runTitleCard();
ST_drawLevelTitle(TICRATE); ST_drawWipeTitleCard();
if (splitscreen)
{
stplyr = &players[secondarydisplayplayer];
ST_drawLevelTitle(TICRATE);
}
} }
} }
@ -457,6 +450,15 @@ void F_RunWipe(UINT8 wipetype, boolean drawMenu)
#endif #endif
F_DoWipe(fmask); F_DoWipe(fmask);
// draw level title
if ((WipeStageTitle && st_overlay)
&& !(mapheaderinfo[gamemap-1]->levelflags & LF_NOTITLECARD)
&& *mapheaderinfo[gamemap-1]->lvlttl != '\0')
{
ST_runTitleCard();
ST_drawWipeTitleCard();
}
I_OsPolling(); I_OsPolling();
I_UpdateNoBlit(); I_UpdateNoBlit();
@ -468,8 +470,10 @@ void F_RunWipe(UINT8 wipetype, boolean drawMenu)
if (moviemode) if (moviemode)
M_SaveFrame(); M_SaveFrame();
} }
WipeInAction = false; WipeInAction = false;
WipeInLevel = false; WipeInLevel = false;
WipeStageTitle = false;
#endif #endif
} }
@ -497,6 +501,7 @@ void F_WipeTicker(void)
// stop // stop
WipeInAction = false; WipeInAction = false;
WipeInLevel = false; WipeInLevel = false;
WipeStageTitle = false;
return; return;
} }
@ -508,6 +513,7 @@ void F_WipeTicker(void)
#endif #endif
F_DoWipe(fmask); F_DoWipe(fmask);
#endif #endif
WipeStageTitle = false;
#endif #endif
} }

View File

@ -47,6 +47,10 @@
#include "m_cond.h" // condition sets #include "m_cond.h" // condition sets
#include "md5.h" // demo checksums #include "md5.h" // demo checksums
#ifdef HAVE_BLUA
#include "lua_hud.h"
#endif
gameaction_t gameaction; gameaction_t gameaction;
gamestate_t gamestate = GS_NULL; gamestate_t gamestate = GS_NULL;
UINT8 ultimatemode = false; UINT8 ultimatemode = false;
@ -1703,6 +1707,61 @@ void G_DoLoadLevel(boolean resetplayer)
CON_ClearHUD(); CON_ClearHUD();
} }
//
// Start the title card.
//
void G_StartTitleCard(void)
{
// The title card has been disabled for this map.
// Oh well.
if (mapheaderinfo[gamemap-1]->levelflags & LF_NOTITLECARD)
{
WipeStageTitle = false;
return;
}
// clear the hud
CON_ClearHUD();
// prepare status bar
ST_startTitleCard();
// start the title card
WipeStageTitle = (!titlemapinaction);
WipeInLevel = true;
wipestyleflags |= WSF_FADEIN;
wipestyleflags &= ~WSF_FADEOUT;
}
//
// Run the title card before fading in to the level.
//
void G_PreLevelTitleCard(tic_t ticker, boolean update)
{
tic_t starttime = I_GetTime();
tic_t endtime = starttime + (PRELEVELTIME*NEWTICRATERATIO);
tic_t nowtime = starttime;
tic_t lasttime = starttime;
while (nowtime < endtime)
{
// draw loop
while (!((nowtime = I_GetTime()) - lasttime))
I_Sleep();
lasttime = nowtime;
// Run some bullshit whatever
D_ProcessEvents();
ST_runTitleCard();
ST_preLevelTitleCardDrawer(ticker, update);
if (moviemode)
M_SaveFrame();
if (takescreenshot) // Only take screenshots after drawing.
M_DoScreenShot();
}
}
INT32 pausedelay = 0; INT32 pausedelay = 0;
boolean pausebreakkey = false; boolean pausebreakkey = false;
static INT32 camtoggledelay, camtoggledelay2 = 0; static INT32 camtoggledelay, camtoggledelay2 = 0;
@ -1992,7 +2051,7 @@ void G_Ticker(boolean run)
if (titledemo) if (titledemo)
F_TitleDemoTicker(); F_TitleDemoTicker();
P_Ticker(run); // tic the game P_Ticker(run); // tic the game
ST_Ticker(); ST_Ticker(run);
F_TextPromptTicker(); F_TextPromptTicker();
AM_Ticker(); AM_Ticker();
HU_Ticker(); HU_Ticker();
@ -2833,6 +2892,31 @@ void G_AddPlayer(INT32 playernum)
P_DoPlayerExit(p); P_DoPlayerExit(p);
} }
boolean G_EnoughPlayersFinished(void)
{
UINT8 numneeded = (G_IsSpecialStage(gamemap) ? 4 : cv_playersforexit.value);
INT32 total = 0;
INT32 exiting = 0;
INT32 i;
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i] || players[i].spectator || players[i].bot)
continue;
if (players[i].lives <= 0)
continue;
total++;
if (players[i].pflags & PF_FINISHED)
exiting++;
}
if (exiting)
return exiting * 4 / total >= numneeded;
else
return false;
}
void G_ExitLevel(void) void G_ExitLevel(void)
{ {
if (gamestate == GS_LEVEL) if (gamestate == GS_LEVEL)
@ -4031,7 +4115,7 @@ char *G_BuildMapTitle(INT32 mapnum)
len += strlen(mapheaderinfo[mapnum-1]->lvlttl); len += strlen(mapheaderinfo[mapnum-1]->lvlttl);
if (!(mapheaderinfo[mapnum-1]->levelflags & LF_NOZONE)) if (!(mapheaderinfo[mapnum-1]->levelflags & LF_NOZONE))
{ {
zonetext = M_GetText("ZONE"); zonetext = M_GetText("Zone");
len += strlen(zonetext) + 1; // ' ' + zonetext len += strlen(zonetext) + 1; // ' ' + zonetext
} }
if (actnum > 0) if (actnum > 0)
@ -5194,7 +5278,10 @@ void G_ReadMetalTic(mobj_t *metal)
{ // But wait, there's more! { // But wait, there's more!
xziptic = READUINT8(metal_p); xziptic = READUINT8(metal_p);
if (xziptic & EZT_FLIP) if (xziptic & EZT_FLIP)
{
metal->eflags ^= MFE_VERTICALFLIP; metal->eflags ^= MFE_VERTICALFLIP;
metal->flags2 ^= MF2_OBJECTFLIP;
}
if (xziptic & EZT_SCALE) if (xziptic & EZT_SCALE)
{ {
metal->destscale = READFIXED(metal_p); metal->destscale = READFIXED(metal_p);

View File

@ -140,7 +140,8 @@ void G_SpawnPlayer(INT32 playernum, boolean starpost);
void G_DeferedInitNew(boolean pultmode, const char *mapname, INT32 pickedchar, void G_DeferedInitNew(boolean pultmode, const char *mapname, INT32 pickedchar,
boolean SSSG, boolean FLS); boolean SSSG, boolean FLS);
void G_DoLoadLevel(boolean resetplayer); void G_DoLoadLevel(boolean resetplayer);
void G_StartTitleCard(void);
void G_PreLevelTitleCard(tic_t ticker, boolean update);
void G_DeferedPlayDemo(const char *demo); void G_DeferedPlayDemo(const char *demo);
// Can be called by the startup code or M_Responder, calls P_SetupLevel. // Can be called by the startup code or M_Responder, calls P_SetupLevel.
@ -208,6 +209,7 @@ boolean G_GametypeHasSpectators(void);
boolean G_RingSlingerGametype(void); boolean G_RingSlingerGametype(void);
boolean G_PlatformGametype(void); boolean G_PlatformGametype(void);
boolean G_TagGametype(void); boolean G_TagGametype(void);
boolean G_EnoughPlayersFinished(void);
void G_ExitLevel(void); void G_ExitLevel(void);
void G_NextLevel(void); void G_NextLevel(void);
void G_Continue(void); void G_Continue(void);

View File

@ -380,9 +380,9 @@ void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t
{ {
FSurfaceInfo Surf; FSurfaceInfo Surf;
Surf.FlatColor.s.red = Surf.FlatColor.s.green = Surf.FlatColor.s.blue = 0xff; Surf.FlatColor.s.red = Surf.FlatColor.s.green = Surf.FlatColor.s.blue = 0xff;
if (alphalevel == 13) Surf.FlatColor.s.alpha = softwaretranstogl_lo[cv_translucenthud.value]; if (alphalevel == 13) Surf.FlatColor.s.alpha = softwaretranstogl_lo[st_translucency];
else if (alphalevel == 14) Surf.FlatColor.s.alpha = softwaretranstogl[cv_translucenthud.value]; else if (alphalevel == 14) Surf.FlatColor.s.alpha = softwaretranstogl[st_translucency];
else if (alphalevel == 15) Surf.FlatColor.s.alpha = softwaretranstogl_hi[cv_translucenthud.value]; else if (alphalevel == 15) Surf.FlatColor.s.alpha = softwaretranstogl_hi[st_translucency];
else Surf.FlatColor.s.alpha = softwaretranstogl[10-alphalevel]; else Surf.FlatColor.s.alpha = softwaretranstogl[10-alphalevel];
flags |= PF_Modulated; flags |= PF_Modulated;
HWD.pfnDrawPolygon(&Surf, v, 4, flags); HWD.pfnDrawPolygon(&Surf, v, 4, flags);
@ -538,9 +538,9 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal
{ {
FSurfaceInfo Surf; FSurfaceInfo Surf;
Surf.FlatColor.s.red = Surf.FlatColor.s.green = Surf.FlatColor.s.blue = 0xff; Surf.FlatColor.s.red = Surf.FlatColor.s.green = Surf.FlatColor.s.blue = 0xff;
if (alphalevel == 13) Surf.FlatColor.s.alpha = softwaretranstogl_lo[cv_translucenthud.value]; if (alphalevel == 13) Surf.FlatColor.s.alpha = softwaretranstogl_lo[st_translucency];
else if (alphalevel == 14) Surf.FlatColor.s.alpha = softwaretranstogl[cv_translucenthud.value]; else if (alphalevel == 14) Surf.FlatColor.s.alpha = softwaretranstogl[st_translucency];
else if (alphalevel == 15) Surf.FlatColor.s.alpha = softwaretranstogl_hi[cv_translucenthud.value]; else if (alphalevel == 15) Surf.FlatColor.s.alpha = softwaretranstogl_hi[st_translucency];
else Surf.FlatColor.s.alpha = softwaretranstogl[10-alphalevel]; else Surf.FlatColor.s.alpha = softwaretranstogl[10-alphalevel];
flags |= PF_Modulated; flags |= PF_Modulated;
HWD.pfnDrawPolygon(&Surf, v, 4, flags); HWD.pfnDrawPolygon(&Surf, v, 4, flags);

View File

@ -4068,6 +4068,7 @@ static gr_vissprite_t *HWR_NewVisSprite(void)
return HWR_GetVisSprite(gr_visspritecount++); return HWR_GetVisSprite(gr_visspritecount++);
} }
#ifdef GLBADSHADOWS
// Finds a floor through which light does not pass. // Finds a floor through which light does not pass.
static fixed_t HWR_OpaqueFloorAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height) static fixed_t HWR_OpaqueFloorAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height)
{ {
@ -4098,6 +4099,7 @@ static fixed_t HWR_OpaqueFloorAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t hei
return floorz; return floorz;
} }
#endif //#ifdef GLBADSHADOWS
// //
// HWR_DoCulling // HWR_DoCulling
@ -4139,6 +4141,7 @@ static boolean HWR_DoCulling(line_t *cullheight, line_t *viewcullheight, float v
return false; return false;
} }
#ifdef GLBADSHADOWS
static void HWR_DrawSpriteShadow(gr_vissprite_t *spr, GLPatch_t *gpatch, float this_scale) static void HWR_DrawSpriteShadow(gr_vissprite_t *spr, GLPatch_t *gpatch, float this_scale)
{ {
FOutVector swallVerts[4]; FOutVector swallVerts[4];
@ -4311,6 +4314,7 @@ static void HWR_DrawSpriteShadow(gr_vissprite_t *spr, GLPatch_t *gpatch, float t
HWD.pfnDrawPolygon(&sSurf, swallVerts, 4, PF_Translucent|PF_Modulated|PF_Clip); HWD.pfnDrawPolygon(&sSurf, swallVerts, 4, PF_Translucent|PF_Modulated|PF_Clip);
} }
} }
#endif //#ifdef GLBADSHADOWS
// This is expecting a pointer to an array containing 4 wallVerts for a sprite // This is expecting a pointer to an array containing 4 wallVerts for a sprite
static void HWR_RotateSpritePolyToAim(gr_vissprite_t *spr, FOutVector *wallVerts) static void HWR_RotateSpritePolyToAim(gr_vissprite_t *spr, FOutVector *wallVerts)
@ -4386,6 +4390,7 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
//Hurdler: 25/04/2000: now support colormap in hardware mode //Hurdler: 25/04/2000: now support colormap in hardware mode
HWR_GetMappedPatch(gpatch, spr->colormap); HWR_GetMappedPatch(gpatch, spr->colormap);
#ifdef GLBADSHADOWS
// Draw shadow BEFORE sprite // Draw shadow BEFORE sprite
if (cv_shadow.value // Shadows enabled if (cv_shadow.value // Shadows enabled
&& (spr->mobj->flags & (MF_SCENERY|MF_SPAWNCEILING|MF_NOGRAVITY)) != (MF_SCENERY|MF_SPAWNCEILING|MF_NOGRAVITY) // Ceiling scenery have no shadow. && (spr->mobj->flags & (MF_SCENERY|MF_SPAWNCEILING|MF_NOGRAVITY)) != (MF_SCENERY|MF_SPAWNCEILING|MF_NOGRAVITY) // Ceiling scenery have no shadow.
@ -4401,6 +4406,7 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
//////////////////// ////////////////////
HWR_DrawSpriteShadow(spr, gpatch, this_scale); HWR_DrawSpriteShadow(spr, gpatch, this_scale);
} }
#endif //#ifdef GLBADSHADOWS
baseWallVerts[0].x = baseWallVerts[3].x = spr->x1; baseWallVerts[0].x = baseWallVerts[3].x = spr->x1;
baseWallVerts[2].x = baseWallVerts[1].x = spr->x2; baseWallVerts[2].x = baseWallVerts[1].x = spr->x2;
@ -4788,6 +4794,7 @@ static void HWR_DrawSprite(gr_vissprite_t *spr)
//Hurdler: 25/04/2000: now support colormap in hardware mode //Hurdler: 25/04/2000: now support colormap in hardware mode
HWR_GetMappedPatch(gpatch, spr->colormap); HWR_GetMappedPatch(gpatch, spr->colormap);
#ifdef GLBADSHADOWS
// Draw shadow BEFORE sprite // Draw shadow BEFORE sprite
if (cv_shadow.value // Shadows enabled if (cv_shadow.value // Shadows enabled
&& (spr->mobj->flags & (MF_SCENERY|MF_SPAWNCEILING|MF_NOGRAVITY)) != (MF_SCENERY|MF_SPAWNCEILING|MF_NOGRAVITY) // Ceiling scenery have no shadow. && (spr->mobj->flags & (MF_SCENERY|MF_SPAWNCEILING|MF_NOGRAVITY)) != (MF_SCENERY|MF_SPAWNCEILING|MF_NOGRAVITY) // Ceiling scenery have no shadow.
@ -4803,6 +4810,7 @@ static void HWR_DrawSprite(gr_vissprite_t *spr)
//////////////////// ////////////////////
HWR_DrawSpriteShadow(spr, gpatch, this_scale); HWR_DrawSpriteShadow(spr, gpatch, this_scale);
} }
#endif //#ifdef GLBADSHADOWS
// if it has a dispoffset, push it a little towards the camera // if it has a dispoffset, push it a little towards the camera
if (spr->dispoffset) { if (spr->dispoffset) {

View File

@ -498,24 +498,24 @@ static void DoSayCommand(SINT8 target, size_t usedargs, UINT8 flags)
if (strlen(msg) > 4 && strnicmp(msg, "/pm", 3) == 0) // used /pm if (strlen(msg) > 4 && strnicmp(msg, "/pm", 3) == 0) // used /pm
{ {
// what we're gonna do now is check if the node exists // what we're gonna do now is check if the player exists
// with that logic, characters 4 and 5 are our numbers: // with that logic, characters 4 and 5 are our numbers:
const char *newmsg; const char *newmsg;
char *nodenum = (char*) malloc(3); char *playernum = (char*) malloc(3);
INT32 spc = 1; // used if nodenum[1] is a space. INT32 spc = 1; // used if playernum[1] is a space.
strncpy(nodenum, msg+3, 3); strncpy(playernum, msg+3, 3);
// check for undesirable characters in our "number" // check for undesirable characters in our "number"
if (((nodenum[0] < '0') || (nodenum[0] > '9')) || ((nodenum[1] < '0') || (nodenum[1] > '9'))) if (((playernum[0] < '0') || (playernum[0] > '9')) || ((playernum[1] < '0') || (playernum[1] > '9')))
{ {
// check if nodenum[1] is a space // check if playernum[1] is a space
if (nodenum[1] == ' ') if (playernum[1] == ' ')
spc = 0; spc = 0;
// let it slide // let it slide
else else
{ {
HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm<node> \'.", false); HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm<playernum> \'.", false);
free(nodenum); free(playernum);
return; return;
} }
} }
@ -524,14 +524,14 @@ static void DoSayCommand(SINT8 target, size_t usedargs, UINT8 flags)
{ {
if (msg[5] != ' ') if (msg[5] != ' ')
{ {
HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm<node> \'.", false); HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm<playernum> \'.", false);
free(nodenum); free(playernum);
return; return;
} }
} }
target = atoi((const char*) nodenum); // turn that into a number target = atoi((const char*) playernum); // turn that into a number
free(nodenum); free(playernum);
//CONS_Printf("%d\n", target); //CONS_Printf("%d\n", target);
// check for target player, if it doesn't exist then we can't send the message! // check for target player, if it doesn't exist then we can't send the message!
@ -2322,13 +2322,14 @@ void HU_Erase(void)
// //
// HU_drawPing // HU_drawPing
// //
void HU_drawPing(INT32 x, INT32 y, INT32 ping, boolean notext) void HU_drawPing(INT32 x, INT32 y, UINT32 ping, boolean notext, INT32 flags)
{ {
UINT8 numbars = 1; // how many ping bars do we draw? UINT8 numbars = 1; // how many ping bars do we draw?
UINT8 barcolor = 35; // color we use for the bars (green, yellow or red) UINT8 barcolor = 35; // color we use for the bars (green, yellow or red)
SINT8 i = 0; SINT8 i = 0;
SINT8 yoffset = 6; SINT8 yoffset = 6;
INT32 dx = x+1 - (V_SmallStringWidth(va("%dms", ping), V_ALLOWLOWERCASE)/2); INT32 dx = x+1 - (V_SmallStringWidth(va("%dms", ping),
V_ALLOWLOWERCASE|flags)/2);
if (ping < 128) if (ping < 128)
{ {
@ -2342,13 +2343,13 @@ void HU_drawPing(INT32 x, INT32 y, INT32 ping, boolean notext)
} }
if (!notext || vid.width >= 640) // how sad, we're using a shit resolution. if (!notext || vid.width >= 640) // how sad, we're using a shit resolution.
V_DrawSmallString(dx, y+4, V_ALLOWLOWERCASE, va("%dms", ping)); V_DrawSmallString(dx, y+4, V_ALLOWLOWERCASE|flags, va("%dms", ping));
for (i=0; (i<3); i++) // Draw the ping bar for (i=0; (i<3); i++) // Draw the ping bar
{ {
V_DrawFill(x+2 *(i-1), y+yoffset-4, 2, 8-yoffset, 31); V_DrawFill(x+2 *(i-1), y+yoffset-4, 2, 8-yoffset, 31|flags);
if (i < numbars) if (i < numbars)
V_DrawFill(x+2 *(i-1), y+yoffset-3, 1, 8-yoffset-1, barcolor); V_DrawFill(x+2 *(i-1), y+yoffset-3, 1, 8-yoffset-1, barcolor|flags);
yoffset -= 2; yoffset -= 2;
} }
@ -2379,7 +2380,7 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I
if (!splitscreen) // don't draw it on splitscreen, if (!splitscreen) // don't draw it on splitscreen,
{ {
if (!(tab[i].num == serverplayer)) if (!(tab[i].num == serverplayer))
HU_drawPing(x+ 253, y+2, playerpingtable[tab[i].num], false); HU_drawPing(x+ 253, y, playerpingtable[tab[i].num], false, 0);
//else //else
// V_DrawSmallString(x+ 246, y+4, V_YELLOWMAP, "SERVER"); // V_DrawSmallString(x+ 246, y+4, V_YELLOWMAP, "SERVER");
} }
@ -2443,7 +2444,7 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I
V_DrawSmallScaledPatch(x-32, y-4, 0, tagico); V_DrawSmallScaledPatch(x-32, y-4, 0, tagico);
} }
if (players[tab[i].num].exiting) if (players[tab[i].num].exiting || (players[tab[i].num].pflags & PF_FINISHED))
V_DrawSmallScaledPatch(x - SHORT(exiticon->width)/2 - 1, y-3, 0, exiticon); V_DrawSmallScaledPatch(x - SHORT(exiticon->width)/2 - 1, y-3, 0, exiticon);
if (gametype == GT_RACE) if (gametype == GT_RACE)
@ -2578,7 +2579,7 @@ static void HU_Draw32TeamTabRankings(playersort_t *tab, INT32 whiteplayer)
if (!splitscreen) if (!splitscreen)
{ {
if (!(tab[i].num == serverplayer)) if (!(tab[i].num == serverplayer))
HU_drawPing(x+ 135, y+3, playerpingtable[tab[i].num], true); HU_drawPing(x+ 135, y+1, playerpingtable[tab[i].num], true, 0);
//else //else
//V_DrawSmallString(x+ 129, y+4, V_YELLOWMAP, "HOST"); //V_DrawSmallString(x+ 129, y+4, V_YELLOWMAP, "HOST");
} }
@ -2702,7 +2703,7 @@ void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer)
if (!splitscreen) if (!splitscreen)
{ {
if (!(tab[i].num == serverplayer)) if (!(tab[i].num == serverplayer))
HU_drawPing(x+ 113, y+2, playerpingtable[tab[i].num], false); HU_drawPing(x+ 113, y, playerpingtable[tab[i].num], false, 0);
//else //else
// V_DrawSmallString(x+ 94, y+4, V_YELLOWMAP, "SERVER"); // V_DrawSmallString(x+ 94, y+4, V_YELLOWMAP, "SERVER");
} }
@ -2733,7 +2734,7 @@ void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scoreline
strlcpy(name, tab[i].name, 7); strlcpy(name, tab[i].name, 7);
if (!(tab[i].num == serverplayer)) if (!(tab[i].num == serverplayer))
HU_drawPing(x+ 113, y+2, playerpingtable[tab[i].num], false); HU_drawPing(x+ 113, y, playerpingtable[tab[i].num], false, 0);
//else //else
// V_DrawSmallString(x+ 94, y+4, V_YELLOWMAP, "SERVER"); // V_DrawSmallString(x+ 94, y+4, V_YELLOWMAP, "SERVER");
@ -2747,7 +2748,7 @@ void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scoreline
else if (G_TagGametype() && players[tab[i].num].pflags & PF_TAGIT) else if (G_TagGametype() && players[tab[i].num].pflags & PF_TAGIT)
V_DrawSmallScaledPatch(x-28, y-4, 0, tagico); V_DrawSmallScaledPatch(x-28, y-4, 0, tagico);
if (players[tab[i].num].exiting) if (players[tab[i].num].exiting || (players[tab[i].num].pflags & PF_FINISHED))
V_DrawSmallScaledPatch(x - SHORT(exiticon->width)/2 - 1, y-3, 0, exiticon); V_DrawSmallScaledPatch(x - SHORT(exiticon->width)/2 - 1, y-3, 0, exiticon);
// Draw emeralds // Draw emeralds
@ -2841,7 +2842,7 @@ static void HU_Draw32TabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scor
if (!splitscreen) // don't draw it on splitscreen, if (!splitscreen) // don't draw it on splitscreen,
{ {
if (!(tab[i].num == serverplayer)) if (!(tab[i].num == serverplayer))
HU_drawPing(x+ 135, y+3, playerpingtable[tab[i].num], true); HU_drawPing(x+ 135, y+1, playerpingtable[tab[i].num], true, 0);
//else //else
// V_DrawSmallString(x+ 129, y+4, V_YELLOWMAP, "HOST"); // V_DrawSmallString(x+ 129, y+4, V_YELLOWMAP, "HOST");
} }

View File

@ -28,7 +28,7 @@
// Level title font // Level title font
#define LT_FONTSTART '!' // the first font characters #define LT_FONTSTART '!' // the first font characters
#define LT_FONTEND 'Z' // the last font characters #define LT_FONTEND 'z' // the last font characters
#define LT_FONTSIZE (LT_FONTEND - LT_FONTSTART + 1) #define LT_FONTSIZE (LT_FONTEND - LT_FONTSTART + 1)
#define CRED_FONTSTART '!' // the first font character #define CRED_FONTSTART '!' // the first font character
@ -113,7 +113,7 @@ void HU_Drawer(void);
char HU_dequeueChatChar(void); char HU_dequeueChatChar(void);
void HU_Erase(void); void HU_Erase(void);
void HU_clearChatChars(void); void HU_clearChatChars(void);
void HU_drawPing(INT32 x, INT32 y, INT32 ping, boolean notext); // Lat': Ping drawer for scoreboard. void HU_drawPing(INT32 x, INT32 y, UINT32 ping, boolean notext, INT32 flags); // Lat': Ping drawer for scoreboard.
void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, INT32 whiteplayer); void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, INT32 whiteplayer);
void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer); void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer);
void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, INT32 whiteplayer); void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, INT32 whiteplayer);

View File

@ -1487,6 +1487,7 @@ state_t states[NUMSTATES] =
{SPR_FSGN, 0|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_FSGNA {SPR_FSGN, 0|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_FSGNA
{SPR_FSGN, 1|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_FSGNB {SPR_FSGN, 1|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_FSGNB
{SPR_FSGN, 2|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_FSGNC {SPR_FSGN, 2|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_FSGNC
{SPR_FSGN, 3|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_FSGND
// Black Eggman (Boss 7) // Black Eggman (Boss 7)
{SPR_BRAK, 0, 1, {A_SetReactionTime}, 0, 0, S_BLACKEGG_STND2}, // S_BLACKEGG_STND {SPR_BRAK, 0, 1, {A_SetReactionTime}, 0, 0, S_BLACKEGG_STND2}, // S_BLACKEGG_STND
@ -3527,13 +3528,9 @@ state_t states[NUMSTATES] =
{SPR_FFWR, 3, 3, {NULL}, 0, 0, S_FIREFLOWER1}, // S_FIREFLOWER4 {SPR_FFWR, 3, 3, {NULL}, 0, 0, S_FIREFLOWER1}, // S_FIREFLOWER4
// Thrown Mario Fireball // Thrown Mario Fireball
{SPR_FBLL, FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_FIREBALL2}, // S_FIREBALL1 {SPR_FBLL, FF_FULLBRIGHT, 1, {A_SpawnObjectRelative}, 0, MT_FIREBALLTRAIL, S_FIREBALL}, // S_FIREBALL
{SPR_FBLL, FF_FULLBRIGHT|1, 3, {NULL}, 0, 0, S_FIREBALL3}, // S_FIREBALL2 {SPR_FBLL, 1|FF_FULLBRIGHT|FF_TRANS50, 1, {A_SetScale}, FRACUNIT*3/4, 0, S_FIREBALLTRAIL2}, // S_FIREBALLTRAIL1
{SPR_FBLL, FF_FULLBRIGHT|2, 3, {NULL}, 0, 0, S_FIREBALL4}, // S_FIREBALL3 {SPR_FBLL, 1|FF_FULLBRIGHT|FF_TRANS50, 8, {A_SetScale}, FRACUNIT/6, 1, S_NULL}, // S_FIREBALLTRAIL2
{SPR_FBLL, FF_FULLBRIGHT|3, 3, {NULL}, 0, 0, S_FIREBALL1}, // S_FIREBALL4
{SPR_FBLL, FF_FULLBRIGHT|4, 3, {NULL}, 0, 0, S_FIREBALLEXP2}, // S_FIREBALLEXP1
{SPR_FBLL, FF_FULLBRIGHT|5, 3, {NULL}, 0, 0, S_FIREBALLEXP3}, // S_FIREBALLEXP2
{SPR_FBLL, FF_FULLBRIGHT|6, 3, {NULL}, 0, 0, S_NULL}, // S_FIREBALLEXP3
// Turtle Shell // Turtle Shell
{SPR_SHLL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SHELL {SPR_SHLL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SHELL
@ -3722,9 +3719,12 @@ state_t states[NUMSTATES] =
{SPR_PENG, 0, 5, {A_FaceTarget}, 0, 0, S_PENGUINATOR_LOOK}, // S_PENGUINATOR_SLIDE5 {SPR_PENG, 0, 5, {A_FaceTarget}, 0, 0, S_PENGUINATOR_LOOK}, // S_PENGUINATOR_SLIDE5
{SPR_POPH, 0, 2, {A_Look}, (2048<<16)|1, 0, S_POPHAT_LOOK}, // S_POPHAT_LOOK {SPR_POPH, 0, 2, {A_Look}, (2048<<16)|1, 0, S_POPHAT_LOOK}, // S_POPHAT_LOOK
{SPR_POPH, 1, 2, {A_LobShot}, MT_POPSHOT, (70<<16)|60, S_POPHAT_SHOOT2}, // S_POPHAT_SHOOT1 {SPR_POPH, 1, 0, {A_MultiShotDist}, (MT_SPINDUST<<16)|4, 24, S_POPHAT_SHOOT2}, // S_POPHAT_SHOOT1
{SPR_POPH, 2, 1, {NULL}, 0, 0, S_POPHAT_SHOOT3}, // S_POPHAT_SHOOT2 {SPR_POPH, 1, 2, {A_LobShot}, MT_POPSHOT, (70<<16)|60, S_POPHAT_SHOOT3}, // S_POPHAT_SHOOT2
{SPR_POPH, 0, 57, {NULL}, 0, 0, S_POPHAT_LOOK}, // S_POPHAT_SHOOT3 {SPR_POPH, 2, 1, {NULL}, 0, 0, S_POPHAT_SHOOT4}, // S_POPHAT_SHOOT3
{SPR_POPH, 0, 57, {NULL}, 0, 0, S_POPHAT_LOOK}, // S_POPHAT_SHOOT4
{SPR_POPH, 3, 3, {A_SpawnObjectRelative}, 0, MT_POPSHOT_TRAIL, S_POPSHOT}, // S_POPSHOT
{SPR_NULL, 0, 2, {NULL}, 0, 0, S_SPINDUST1}, // S_POPSHOT_TRAIL
{SPR_HIVE, 0, 5, {A_Look}, 1, 1, S_HIVEELEMENTAL_LOOK}, // S_HIVEELEMENTAL_LOOK {SPR_HIVE, 0, 5, {A_Look}, 1, 1, S_HIVEELEMENTAL_LOOK}, // S_HIVEELEMENTAL_LOOK
{SPR_HIVE, 0, 14, {A_PlaySound}, sfx_s3k76, 1, S_HIVEELEMENTAL_PREPARE2}, // S_HIVEELEMENTAL_PREPARE1 {SPR_HIVE, 0, 14, {A_PlaySound}, sfx_s3k76, 1, S_HIVEELEMENTAL_PREPARE2}, // S_HIVEELEMENTAL_PREPARE1
@ -6115,11 +6115,11 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // meleestate S_NULL, // meleestate
S_NULL, // missilestate S_NULL, // missilestate
S_FSGNC, // deathstate S_FSGNC, // deathstate
S_NULL, // xdeathstate S_FSGND, // xdeathstate
sfx_None, // deathsound sfx_None, // deathsound
0, // speed 0, // speed
124*FRACUNIT, // radius 74*FRACUNIT, // radius
640*FRACUNIT, // height 320*FRACUNIT, // height
0, // display offset 0, // display offset
0, // mass 0, // mass
0, // damage 0, // damage
@ -18910,31 +18910,58 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
{ // MT_FIREBALL { // MT_FIREBALL
-1, // doomednum -1, // doomednum
S_FIREBALL1, // spawnstate S_FIREBALL, // spawnstate
1000, // spawnhealth 1000, // spawnhealth
S_FIREBALLEXP1, // seestate S_NULL, // seestate
sfx_None, // seesound sfx_None, // seesound
8, // reactiontime 8, // reactiontime
sfx_None, // attacksound sfx_None, // attacksound
S_NULL, // painstate S_NULL, // painstate
0, // painchance 0, // painchance
sfx_None, // painsound sfx_None, // painsound
S_FIREBALLEXP1, // meleestate S_NULL, // meleestate
S_FIREBALLEXP1, // missilestate S_NULL, // missilestate
S_FIREBALLEXP1, // deathstate S_NULL, // deathstate
S_FIREBALLEXP1, // xdeathstate S_NULL, // xdeathstate
sfx_mario1, // deathsound sfx_None, // deathsound
10*FRACUNIT, // speed 40*FRACUNIT, // speed
4*FRACUNIT, // radius 4*FRACUNIT, // radius
8*FRACUNIT, // height 8*FRACUNIT, // height
0, // display offset 0, // display offset
DMG_FIRE, // mass DMG_FIRE, // mass
1, // damage 1, // damage
sfx_None, // activesound sfx_None, // activesound
MF_NOBLOCKMAP|MF_FIRE|MF_MISSILE, // flags MF_FIRE|MF_BOUNCE|MF_MISSILE, // flags
S_NULL // raisestate S_NULL // raisestate
}, },
{ // MT_FIREBALLTRAIL
-1, // doomednum
S_FIREBALLTRAIL1, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
0, // speed
16*FRACUNIT, // radius
16*FRACUNIT, // height
0, // display offset
0, // mass
1, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_RUNSPAWNFUNC, // flags
S_NULL // raisestate
},
{ // MT_SHELL { // MT_SHELL
1804, // doomednum 1804, // doomednum
S_SHELL, // spawnstate S_SHELL, // spawnstate
@ -19989,10 +20016,10 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
{ // MT_POPSHOT { // MT_POPSHOT
-1, // doomednum -1, // doomednum
S_ROCKCRUMBLEI, // spawnstate S_POPSHOT, // spawnstate
1, // spawnhealth 1, // spawnhealth
S_NULL, // seestate S_NULL, // seestate
sfx_cannon, // seesound sfx_kc4c, // seesound
0, // reactiontime 0, // reactiontime
sfx_None, // attacksound sfx_None, // attacksound
S_NULL, // painstate S_NULL, // painstate
@ -20000,9 +20027,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_None, // painsound sfx_None, // painsound
S_NULL, // meleestate S_NULL, // meleestate
S_NULL, // missilestate S_NULL, // missilestate
S_XPLD1, // deathstate S_SONIC3KBOSSEXPLOSION1, // deathstate
S_NULL, // xdeathstate S_NULL, // xdeathstate
sfx_pop, // deathsound sfx_cybdth, // deathsound
0, // speed 0, // speed
16*FRACUNIT, // radius 16*FRACUNIT, // radius
32*FRACUNIT, // height 32*FRACUNIT, // height
@ -20014,6 +20041,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate S_NULL // raisestate
}, },
{ // MT_POPSHOT_TRAIL
-1, // doomednum
S_POPSHOT_TRAIL,// spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
4*FRACUNIT, // speed
4*FRACUNIT, // radius
4*FRACUNIT, // height
0, // display offset
4, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_NOCLIP, // flags
S_NULL // raisestate
},
{ // MT_HIVEELEMENTAL { // MT_HIVEELEMENTAL
127, // doomednum 127, // doomednum
S_HIVEELEMENTAL_LOOK, // spawnstate S_HIVEELEMENTAL_LOOK, // spawnstate

View File

@ -1657,6 +1657,7 @@ typedef enum state
S_FSGNA, S_FSGNA,
S_FSGNB, S_FSGNB,
S_FSGNC, S_FSGNC,
S_FSGND,
// Black Eggman (Boss 7) // Black Eggman (Boss 7)
S_BLACKEGG_STND, S_BLACKEGG_STND,
@ -3637,13 +3638,9 @@ typedef enum state
S_FIREFLOWER2, S_FIREFLOWER2,
S_FIREFLOWER3, S_FIREFLOWER3,
S_FIREFLOWER4, S_FIREFLOWER4,
S_FIREBALL1, S_FIREBALL,
S_FIREBALL2, S_FIREBALLTRAIL1,
S_FIREBALL3, S_FIREBALLTRAIL2,
S_FIREBALL4,
S_FIREBALLEXP1,
S_FIREBALLEXP2,
S_FIREBALLEXP3,
S_SHELL, S_SHELL,
S_PUMA_START1, S_PUMA_START1,
S_PUMA_START2, S_PUMA_START2,
@ -3812,6 +3809,9 @@ typedef enum state
S_POPHAT_SHOOT1, S_POPHAT_SHOOT1,
S_POPHAT_SHOOT2, S_POPHAT_SHOOT2,
S_POPHAT_SHOOT3, S_POPHAT_SHOOT3,
S_POPHAT_SHOOT4,
S_POPSHOT,
S_POPSHOT_TRAIL,
S_HIVEELEMENTAL_LOOK, S_HIVEELEMENTAL_LOOK,
S_HIVEELEMENTAL_PREPARE1, S_HIVEELEMENTAL_PREPARE1,
@ -4654,6 +4654,7 @@ typedef enum mobj_type
MT_BLUEGOOMBA, MT_BLUEGOOMBA,
MT_FIREFLOWER, MT_FIREFLOWER,
MT_FIREBALL, MT_FIREBALL,
MT_FIREBALLTRAIL,
MT_SHELL, MT_SHELL,
MT_PUMA, MT_PUMA,
MT_PUMATRAIL, MT_PUMATRAIL,
@ -4698,6 +4699,7 @@ typedef enum mobj_type
MT_PENGUINATOR, MT_PENGUINATOR,
MT_POPHAT, MT_POPHAT,
MT_POPSHOT, MT_POPSHOT,
MT_POPSHOT_TRAIL,
MT_HIVEELEMENTAL, MT_HIVEELEMENTAL,
MT_BUMBLEBORE, MT_BUMBLEBORE,

View File

@ -1165,6 +1165,17 @@ static int lib_pElementalFire(lua_State *L)
return 0; return 0;
} }
static int lib_pDoPlayerFinish(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
NOHUD
INLEVEL
if (!player)
return LUA_ErrInvalid(L, "player_t");
P_DoPlayerFinish(player);
return 0;
}
static int lib_pDoPlayerExit(lua_State *L) static int lib_pDoPlayerExit(lua_State *L)
{ {
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
@ -2674,6 +2685,13 @@ static int lib_gSetCustomExitVars(lua_State *L)
return 0; return 0;
} }
static int lib_gEnoughPlayersFinished(lua_State *L)
{
INLEVEL
lua_pushboolean(L, G_EnoughPlayersFinished());
return 1;
}
static int lib_gExitLevel(lua_State *L) static int lib_gExitLevel(lua_State *L)
{ {
int n = lua_gettop(L); // Num arguments int n = lua_gettop(L); // Num arguments
@ -2869,6 +2887,7 @@ static luaL_Reg lib[] = {
{"P_DoBubbleBounce",lib_pDoBubbleBounce}, {"P_DoBubbleBounce",lib_pDoBubbleBounce},
{"P_BlackOw",lib_pBlackOw}, {"P_BlackOw",lib_pBlackOw},
{"P_ElementalFire",lib_pElementalFire}, {"P_ElementalFire",lib_pElementalFire},
{"P_DoPlayerFinish",lib_pDoPlayerFinish},
{"P_DoPlayerExit",lib_pDoPlayerExit}, {"P_DoPlayerExit",lib_pDoPlayerExit},
{"P_InstaThrust",lib_pInstaThrust}, {"P_InstaThrust",lib_pInstaThrust},
{"P_ReturnThrustX",lib_pReturnThrustX}, {"P_ReturnThrustX",lib_pReturnThrustX},
@ -2981,6 +3000,7 @@ static luaL_Reg lib[] = {
{"G_BuildMapName",lib_gBuildMapName}, {"G_BuildMapName",lib_gBuildMapName},
{"G_DoReborn",lib_gDoReborn}, {"G_DoReborn",lib_gDoReborn},
{"G_SetCustomExitVars",lib_gSetCustomExitVars}, {"G_SetCustomExitVars",lib_gSetCustomExitVars},
{"G_EnoughPlayersFinished",lib_gEnoughPlayersFinished},
{"G_ExitLevel",lib_gExitLevel}, {"G_ExitLevel",lib_gExitLevel},
{"G_IsSpecialStage",lib_gIsSpecialStage}, {"G_IsSpecialStage",lib_gIsSpecialStage},
{"G_GametypeUsesLives",lib_gGametypeUsesLives}, {"G_GametypeUsesLives",lib_gGametypeUsesLives},

View File

@ -43,3 +43,4 @@ boolean LUA_HudEnabled(enum hud option);
void LUAh_GameHUD(player_t *stplyr); void LUAh_GameHUD(player_t *stplyr);
void LUAh_ScoresHUD(void); void LUAh_ScoresHUD(void);
void LUAh_TitleHUD(void); void LUAh_TitleHUD(void);
void LUAh_TitleCardHUD(player_t *stplyr);

View File

@ -92,12 +92,14 @@ static const char *const patch_opt[] = {
enum hudhook { enum hudhook {
hudhook_game = 0, hudhook_game = 0,
hudhook_scores, hudhook_scores,
hudhook_title hudhook_title,
hudhook_titlecard
}; };
static const char *const hudhook_opt[] = { static const char *const hudhook_opt[] = {
"game", "game",
"scores", "scores",
"title", "title",
"titlecard",
NULL}; NULL};
// alignment types for v.drawString // alignment types for v.drawString
@ -910,9 +912,17 @@ static int libd_RandomChance(lua_State *L)
return 1; return 1;
} }
// 30/10/18 Lat': Get cv_translucenthud's value for HUD rendering as a normal V_xxTRANS int // 30/10/18 Lat': Get st_translucency's value for HUD rendering as a normal V_xxTRANS int
// Could as well be thrown in global vars for ease of access but I guess it makes sense for it to be a HUD fn // Could as well be thrown in global vars for ease of access but I guess it makes sense for it to be a HUD fn
static int libd_getlocaltransflag(lua_State *L) static int libd_getlocaltransflag(lua_State *L)
{
HUDONLY
lua_pushinteger(L, (10-st_translucency)*V_10TRANS);
return 1;
}
// Get cv_translucenthud's value for HUD rendering as a normal V_xxTRANS int
static int libd_getusertransflag(lua_State *L)
{ {
HUDONLY HUDONLY
lua_pushinteger(L, (10-cv_translucenthud.value)*V_10TRANS); // A bit weird that it's called "translucenthud" yet 10 is fully opaque :V lua_pushinteger(L, (10-cv_translucenthud.value)*V_10TRANS); // A bit weird that it's called "translucenthud" yet 10 is fully opaque :V
@ -954,6 +964,7 @@ static luaL_Reg lib_draw[] = {
{"dupy", libd_dupy}, {"dupy", libd_dupy},
{"renderer", libd_renderer}, {"renderer", libd_renderer},
{"localTransFlag", libd_getlocaltransflag}, {"localTransFlag", libd_getlocaltransflag},
{"userTransFlag", libd_getusertransflag},
{NULL, NULL} {NULL, NULL}
}; };
@ -1043,6 +1054,9 @@ int LUA_HudLib(lua_State *L)
lua_newtable(L); lua_newtable(L);
lua_rawseti(L, -2, 4); // HUD[3] = title rendering functions array lua_rawseti(L, -2, 4); // HUD[3] = title rendering functions array
lua_newtable(L);
lua_rawseti(L, -2, 5); // HUD[4] = title card rendering functions array
lua_setfield(L, LUA_REGISTRYINDEX, "HUD"); lua_setfield(L, LUA_REGISTRYINDEX, "HUD");
luaL_newmetatable(L, META_HUDINFO); luaL_newmetatable(L, META_HUDINFO);
@ -1180,4 +1194,38 @@ void LUAh_TitleHUD(void)
hud_running = false; hud_running = false;
} }
void LUAh_TitleCardHUD(player_t *stplayr)
{
if (!gL || !(hudAvailable & (1<<hudhook_titlecard)))
return;
hud_running = true;
lua_pop(gL, -1);
lua_getfield(gL, LUA_REGISTRYINDEX, "HUD");
I_Assert(lua_istable(gL, -1));
lua_rawgeti(gL, -1, 5); // HUD[5] = rendering funcs
I_Assert(lua_istable(gL, -1));
lua_rawgeti(gL, -2, 1); // HUD[1] = lib_draw
I_Assert(lua_istable(gL, -1));
lua_remove(gL, -3); // pop HUD
LUA_PushUserdata(gL, stplayr, META_PLAYER);
lua_pushinteger(gL, lt_ticker);
lua_pushinteger(gL, (lt_endtime + TICRATE));
lua_pushnil(gL);
while (lua_next(gL, -6) != 0) {
lua_pushvalue(gL, -6); // graphics library (HUD[1])
lua_pushvalue(gL, -6); // stplayr
lua_pushvalue(gL, -6); // lt_ticker
lua_pushvalue(gL, -6); // lt_endtime
LUA_Call(gL, 4);
}
lua_pop(gL, -1);
hud_running = false;
}
#endif #endif

View File

@ -744,7 +744,7 @@ static int power_get(lua_State *L)
UINT16 *powers = *((UINT16 **)luaL_checkudata(L, 1, META_POWERS)); UINT16 *powers = *((UINT16 **)luaL_checkudata(L, 1, META_POWERS));
powertype_t p = luaL_checkinteger(L, 2); powertype_t p = luaL_checkinteger(L, 2);
if (p >= NUMPOWERS) if (p >= NUMPOWERS)
return luaL_error(L, LUA_QL("powertype_t") " cannot be %u", p); return luaL_error(L, LUA_QL("powertype_t") " cannot be %d", (INT16)p);
lua_pushinteger(L, powers[p]); lua_pushinteger(L, powers[p]);
return 1; return 1;
} }
@ -756,7 +756,7 @@ static int power_set(lua_State *L)
powertype_t p = luaL_checkinteger(L, 2); powertype_t p = luaL_checkinteger(L, 2);
UINT16 i = (UINT16)luaL_checkinteger(L, 3); UINT16 i = (UINT16)luaL_checkinteger(L, 3);
if (p >= NUMPOWERS) if (p >= NUMPOWERS)
return luaL_error(L, LUA_QL("powertype_t") " cannot be %u", p); return luaL_error(L, LUA_QL("powertype_t") " cannot be %d", (INT16)p);
if (hud_running) if (hud_running)
return luaL_error(L, "Do not alter player_t in HUD rendering code!"); return luaL_error(L, "Do not alter player_t in HUD rendering code!");
powers[p] = i; powers[p] = i;

View File

@ -16,6 +16,7 @@
#include "doomdef.h" #include "doomdef.h"
#include "command.h" #include "command.h"
#include "m_argv.h" #include "m_argv.h"
#include "m_misc.h"
/** \brief number of arg /** \brief number of arg
*/ */
@ -161,7 +162,7 @@ void M_FindResponseFile(void)
if (!file) if (!file)
I_Error("No more free memory for the response file"); I_Error("No more free memory for the response file");
if (fread(file, size, 1, handle) != 1) if (fread(file, size, 1, handle) != 1)
I_Error("Couldn't read response file because %s", strerror(ferror(handle))); I_Error("Couldn't read response file because %s", M_FileError(handle));
fclose(handle); fclose(handle);
// keep all the command line arguments following @responsefile // keep all the command line arguments following @responsefile

View File

@ -201,14 +201,7 @@ FUNCMATH FUNCINLINE static ATTRINLINE fixed_t FixedDiv(fixed_t a, fixed_t b)
*/ */
FUNCMATH FUNCINLINE static ATTRINLINE fixed_t FixedRem(fixed_t x, fixed_t y) FUNCMATH FUNCINLINE static ATTRINLINE fixed_t FixedRem(fixed_t x, fixed_t y)
{ {
const boolean n = x < 0; return x % y;
x = abs(x);
while (x >= y)
x -= y;
if (n)
return -x;
else
return x;
} }
/** \brief The FixedSqrt function /** \brief The FixedSqrt function

View File

@ -1224,32 +1224,33 @@ static menuitem_t OP_VideoOptionsMenu[] =
NULL, "HUD Transparency", &cv_translucenthud, 66}, NULL, "HUD Transparency", &cv_translucenthud, 66},
{IT_STRING | IT_CVAR, NULL, "Score/Time/Rings", &cv_timetic, 71}, {IT_STRING | IT_CVAR, NULL, "Score/Time/Rings", &cv_timetic, 71},
{IT_STRING | IT_CVAR, NULL, "Show Powerups", &cv_powerupdisplay, 76}, {IT_STRING | IT_CVAR, NULL, "Show Powerups", &cv_powerupdisplay, 76},
{IT_STRING | IT_CVAR, NULL, "Local ping display", &cv_showping, 81}, // shows ping next to framerate if we want to.
#ifdef SEENAMES #ifdef SEENAMES
{IT_STRING | IT_CVAR, NULL, "Show player names", &cv_seenames, 81}, {IT_STRING | IT_CVAR, NULL, "Show player names", &cv_seenames, 86},
#endif #endif
{IT_HEADER, NULL, "Console", NULL, 90}, {IT_HEADER, NULL, "Console", NULL, 95},
{IT_STRING | IT_CVAR, NULL, "Background color", &cons_backcolor, 96}, {IT_STRING | IT_CVAR, NULL, "Background color", &cons_backcolor, 101},
{IT_STRING | IT_CVAR, NULL, "Text Size", &cv_constextsize, 101}, {IT_STRING | IT_CVAR, NULL, "Text Size", &cv_constextsize, 106},
{IT_HEADER, NULL, "Chat", NULL, 110}, {IT_HEADER, NULL, "Chat", NULL, 115},
{IT_STRING | IT_CVAR, NULL, "Chat Mode", &cv_consolechat, 116}, {IT_STRING | IT_CVAR, NULL, "Chat Mode", &cv_consolechat, 121},
{IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Chat Box Width", &cv_chatwidth, 121}, {IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Chat Box Width", &cv_chatwidth, 126},
{IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Chat Box Height", &cv_chatheight, 126}, {IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Chat Box Height", &cv_chatheight, 131},
{IT_STRING | IT_CVAR, NULL, "Message Fadeout Time", &cv_chattime, 131}, {IT_STRING | IT_CVAR, NULL, "Message Fadeout Time", &cv_chattime, 136},
{IT_STRING | IT_CVAR, NULL, "Chat Notifications", &cv_chatnotifications, 136}, {IT_STRING | IT_CVAR, NULL, "Chat Notifications", &cv_chatnotifications, 141},
{IT_STRING | IT_CVAR, NULL, "Spam Protection", &cv_chatspamprotection, 141}, {IT_STRING | IT_CVAR, NULL, "Spam Protection", &cv_chatspamprotection, 146},
{IT_STRING | IT_CVAR, NULL, "Chat background tint", &cv_chatbacktint, 146}, {IT_STRING | IT_CVAR, NULL, "Chat background tint", &cv_chatbacktint, 151},
{IT_HEADER, NULL, "Level", NULL, 155}, {IT_HEADER, NULL, "Level", NULL, 160},
{IT_STRING | IT_CVAR, NULL, "Draw Distance", &cv_drawdist, 161}, {IT_STRING | IT_CVAR, NULL, "Draw Distance", &cv_drawdist, 166},
{IT_STRING | IT_CVAR, NULL, "Weather Draw Dist.", &cv_drawdist_precip, 166}, {IT_STRING | IT_CVAR, NULL, "Weather Draw Dist.", &cv_drawdist_precip, 171},
{IT_STRING | IT_CVAR, NULL, "NiGHTS Hoop Draw Dist.", &cv_drawdist_nights, 171}, {IT_STRING | IT_CVAR, NULL, "NiGHTS Hoop Draw Dist.", &cv_drawdist_nights, 176},
{IT_HEADER, NULL, "Diagnostic", NULL, 180}, {IT_HEADER, NULL, "Diagnostic", NULL, 184},
{IT_STRING | IT_CVAR, NULL, "Show FPS", &cv_ticrate, 186}, {IT_STRING | IT_CVAR, NULL, "Show FPS", &cv_ticrate, 190},
{IT_STRING | IT_CVAR, NULL, "Clear Before Redraw", &cv_homremoval, 191}, {IT_STRING | IT_CVAR, NULL, "Clear Before Redraw", &cv_homremoval, 195},
{IT_STRING | IT_CVAR, NULL, "Show \"FOCUS LOST\"", &cv_showfocuslost, 196}, {IT_STRING | IT_CVAR, NULL, "Show \"FOCUS LOST\"", &cv_showfocuslost, 200},
}; };
static menuitem_t OP_VideoModeMenu[] = static menuitem_t OP_VideoModeMenu[] =
@ -7179,7 +7180,7 @@ static void M_DrawSoundTest(void)
titl = va("%s - ", curplaying->title); titl = va("%s - ", curplaying->title);
} }
else else
titl = "NONE - "; titl = "None - ";
i = V_LevelNameWidth(titl); i = V_LevelNameWidth(titl);
@ -7193,7 +7194,7 @@ static void M_DrawSoundTest(void)
while (x > y) while (x > y)
{ {
x -= i; x -= i;
V_DrawLevelTitle(x, 24, 0, titl); V_DrawLevelTitle(x, 22, 0, titl);
} }
if (curplaying) if (curplaying)
@ -10472,7 +10473,6 @@ static consvar_t *setupm_cvcolor;
static consvar_t *setupm_cvname; static consvar_t *setupm_cvname;
static consvar_t *setupm_cvdefaultskin; static consvar_t *setupm_cvdefaultskin;
static consvar_t *setupm_cvdefaultcolor; static consvar_t *setupm_cvdefaultcolor;
static consvar_t *setupm_cvdefaultname;
static INT32 setupm_fakeskin; static INT32 setupm_fakeskin;
static INT32 setupm_fakecolor; static INT32 setupm_fakecolor;
@ -10634,8 +10634,7 @@ colordraw:
V_DrawString(x, y, V_DrawString(x, y,
((R_SkinAvailable(setupm_cvdefaultskin->string) != setupm_fakeskin ((R_SkinAvailable(setupm_cvdefaultskin->string) != setupm_fakeskin
|| setupm_cvdefaultcolor->value != setupm_fakecolor || setupm_cvdefaultcolor->value != setupm_fakecolor)
|| strcmp(setupm_name, setupm_cvdefaultname->string))
? 0 ? 0
: V_TRANSLUCENT) : V_TRANSLUCENT)
| ((itemOn == 3) ? V_YELLOWMAP : 0), | ((itemOn == 3) ? V_YELLOWMAP : 0),
@ -10690,14 +10689,12 @@ static void M_HandleSetupMultiPlayer(INT32 choice)
case KEY_ENTER: case KEY_ENTER:
if (itemOn == 3 if (itemOn == 3
&& (R_SkinAvailable(setupm_cvdefaultskin->string) != setupm_fakeskin && (R_SkinAvailable(setupm_cvdefaultskin->string) != setupm_fakeskin
|| setupm_cvdefaultcolor->value != setupm_fakecolor || setupm_cvdefaultcolor->value != setupm_fakecolor))
|| strcmp(setupm_name, setupm_cvdefaultname->string)))
{ {
S_StartSound(NULL,sfx_strpst); S_StartSound(NULL,sfx_strpst);
// you know what? always putting these in the buffer won't hurt anything. // you know what? always putting these in the buffer won't hurt anything.
COM_BufAddText (va("%s \"%s\"\n",setupm_cvdefaultskin->name,skins[setupm_fakeskin].name)); 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 %d\n",setupm_cvdefaultcolor->name,setupm_fakecolor));
COM_BufAddText (va("%s %s\n",setupm_cvdefaultname->name,setupm_name));
break; break;
} }
/* FALLTHRU */ /* FALLTHRU */
@ -10796,7 +10793,6 @@ static void M_SetupMultiPlayer(INT32 choice)
setupm_cvname = &cv_playername; setupm_cvname = &cv_playername;
setupm_cvdefaultskin = &cv_defaultskin; setupm_cvdefaultskin = &cv_defaultskin;
setupm_cvdefaultcolor = &cv_defaultplayercolor; setupm_cvdefaultcolor = &cv_defaultplayercolor;
setupm_cvdefaultname = &cv_defaultplayername;
// For whatever reason this doesn't work right if you just use ->value // For whatever reason this doesn't work right if you just use ->value
setupm_fakeskin = R_SkinAvailable(setupm_cvskin->string); setupm_fakeskin = R_SkinAvailable(setupm_cvskin->string);
@ -10838,7 +10834,6 @@ static void M_SetupMultiPlayer2(INT32 choice)
setupm_cvname = &cv_playername2; setupm_cvname = &cv_playername2;
setupm_cvdefaultskin = &cv_defaultskin2; setupm_cvdefaultskin = &cv_defaultskin2;
setupm_cvdefaultcolor = &cv_defaultplayercolor2; setupm_cvdefaultcolor = &cv_defaultplayercolor2;
setupm_cvdefaultname = &cv_defaultplayername2;
// For whatever reason this doesn't work right if you just use ->value // For whatever reason this doesn't work right if you just use ->value
setupm_fakeskin = R_SkinAvailable(setupm_cvskin->string); setupm_fakeskin = R_SkinAvailable(setupm_cvskin->string);

View File

@ -23,6 +23,8 @@
#include <unistd.h> #include <unistd.h>
#endif #endif
#include <errno.h>
// Extended map support. // Extended map support.
#include <ctype.h> #include <ctype.h>
@ -521,6 +523,12 @@ void M_FirstLoadConfig(void)
// make sure I_Quit() will write back the correct config // make sure I_Quit() will write back the correct config
// (do not write back the config if it crash before) // (do not write back the config if it crash before)
gameconfig_loaded = true; gameconfig_loaded = true;
// reset to default player stuff
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_skin2.name,cv_defaultskin2.string));
COM_BufAddText (va("%s \"%s\"\n",cv_playercolor2.name,cv_defaultplayercolor2.string));
} }
/** Saves the game configuration. /** Saves the game configuration.
@ -2435,3 +2443,13 @@ void M_SetupMemcpy(void)
M_Memcpy = cpu_cpy; M_Memcpy = cpu_cpy;
#endif #endif
} }
/** Return the appropriate message for a file error or end of file.
*/
const char *M_FileError(FILE *fp)
{
if (ferror(fp))
return strerror(errno);
else
return "end-of-file";
}

View File

@ -94,6 +94,8 @@ void strcatbf(char *s1, const char *s2, const char *s3);
void M_SetupMemcpy(void); void M_SetupMemcpy(void);
const char *M_FileError(FILE *handle);
// counting bits, for weapon ammo code, usually // counting bits, for weapon ammo code, usually
FUNCMATH UINT8 M_CountBits(UINT32 num, UINT8 size); FUNCMATH UINT8 M_CountBits(UINT32 num, UINT8 size);

View File

@ -4070,19 +4070,28 @@ bossjustdie:
mobj_t *pole = P_SpawnMobj( mobj_t *pole = P_SpawnMobj(
mo->tracer->x - P_ReturnThrustX(mo->tracer, mo->tracer->angle, speed*time), mo->tracer->x - P_ReturnThrustX(mo->tracer, mo->tracer->angle, speed*time),
mo->tracer->y - P_ReturnThrustY(mo->tracer, mo->tracer->angle, speed*time), mo->tracer->y - P_ReturnThrustY(mo->tracer, mo->tracer->angle, speed*time),
mo->tracer->floorz + 4*FRACUNIT, mo->tracer->floorz + (256+1)*FRACUNIT,
MT_FSGNB); MT_FSGNB);
P_SetTarget(&pole->tracer, P_SpawnMobj( P_SetTarget(&pole->tracer, P_SpawnMobj(
pole->x, pole->y,
pole->z - 256*FRACUNIT,
MT_FSGNB));
P_SetTarget(&pole->tracer->tracer, P_SpawnMobj(
pole->x + P_ReturnThrustX(pole, mo->tracer->angle, FRACUNIT), pole->x + P_ReturnThrustX(pole, mo->tracer->angle, FRACUNIT),
pole->y + P_ReturnThrustY(pole, mo->tracer->angle, FRACUNIT), pole->y + P_ReturnThrustY(pole, mo->tracer->angle, FRACUNIT),
pole->z + 256*FRACUNIT, pole->z + 256*FRACUNIT,
MT_FSGNA)); MT_FSGNA));
pole->angle = mo->tracer->angle; pole->tracer->flags |= MF_NOCLIPTHING;
pole->tracer->angle = pole->angle - ANGLE_90; P_SetScale(pole, (pole->destscale = 2*FRACUNIT));
P_SetScale(pole->tracer, (pole->tracer->destscale = 2*FRACUNIT));
pole->angle = pole->tracer->angle = mo->tracer->angle;
pole->tracer->tracer->angle = pole->angle - ANGLE_90;
pole->momx = P_ReturnThrustX(pole, pole->angle, speed); pole->momx = P_ReturnThrustX(pole, pole->angle, speed);
pole->momy = P_ReturnThrustY(pole, pole->angle, speed); pole->momy = P_ReturnThrustY(pole, pole->angle, speed);
pole->tracer->momx = pole->momx; pole->tracer->momx = pole->momx;
pole->tracer->momy = pole->momy; pole->tracer->momy = pole->momy;
pole->tracer->tracer->momx = pole->momx;
pole->tracer->tracer->momy = pole->momy;
} }
} }
else else
@ -5121,7 +5130,7 @@ void A_SignPlayer(mobj_t *actor)
return; return;
#endif #endif
if (actor->tracer == NULL || locvar1 < -3 || locvar1 >= numskins) if (actor->tracer == NULL || locvar1 < -3 || locvar1 >= numskins || signcolor >= MAXTRANSLATIONS)
return; return;
// if no face overlay, spawn one // if no face overlay, spawn one
@ -5148,26 +5157,9 @@ void A_SignPlayer(mobj_t *actor)
if (signcolor) if (signcolor)
; ;
else if ((actor->target->player->skincolor == skin->prefcolor) && (skin->prefoppositecolor)) // Set it as the skin's preferred oppositecolor? else if ((actor->target->player->skincolor == skin->prefcolor) && (skin->prefoppositecolor)) // Set it as the skin's preferred oppositecolor?
{
signcolor = skin->prefoppositecolor; signcolor = skin->prefoppositecolor;
/*
If you're here from the comment above Color_Opposite,
the following line is the one which is dependent on the
array being symmetrical. It gets the opposite of the
opposite of your desired colour just so it can get the
brightness frame for the End Sign. It's not a great
design choice, but it's constant time array access and
the idea that the colours should be OPPOSITES is kind
of in the name. If you have a better idea, feel free
to let me know. ~toast 2016/07/20
*/
signframe += (15 - Color_Opposite[Color_Opposite[skin->prefoppositecolor - 1][0] - 1][1]);
}
else if (actor->target->player->skincolor) // 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.
{
signcolor = Color_Opposite[actor->target->player->skincolor - 1][0]; signcolor = Color_Opposite[actor->target->player->skincolor - 1][0];
signframe += (15 - Color_Opposite[actor->target->player->skincolor - 1][1]);
}
else else
signcolor = SKINCOLOR_NONE; signcolor = SKINCOLOR_NONE;
} }
@ -5188,10 +5180,10 @@ void A_SignPlayer(mobj_t *actor)
skinnum = P_RandomKey(skincount); skinnum = P_RandomKey(skincount);
for (skincount = 0; skincount < numskins; skincount++) for (skincount = 0; skincount < numskins; skincount++)
{ {
if (skincheck(skincount))
skinnum++;
if (skincount > skinnum) if (skincount > skinnum)
break; break;
if (skincheck(skincount))
skinnum++;
} }
} }
else // otherwise, advance 1 skin else // otherwise, advance 1 skin
@ -5203,42 +5195,46 @@ void A_SignPlayer(mobj_t *actor)
skin = &skins[skinnum]; skin = &skins[skinnum];
} }
else // specific skin else // specific skin
{
skin = &skins[locvar1]; skin = &skins[locvar1];
}
facecolor = skin->prefcolor; facecolor = skin->prefcolor;
if (signcolor) if (signcolor)
; ;
else if (skin->prefoppositecolor) else if (skin->prefoppositecolor)
{
signcolor = skin->prefoppositecolor; signcolor = skin->prefoppositecolor;
} else if (facecolor)
else
{
signcolor = Color_Opposite[facecolor - 1][0]; signcolor = Color_Opposite[facecolor - 1][0];
}
signframe += (15 - Color_Opposite[Color_Opposite[signcolor - 1][0] - 1][1]);
} }
if (skin != NULL && skin->sprites[SPR2_SIGN].numframes) // player face if (skin && skin->sprites[SPR2_SIGN].numframes) // player face
{ {
ov->color = facecolor; ov->color = facecolor;
ov->skin = skin; ov->skin = skin;
P_SetMobjState(ov, actor->info->seestate); // S_PLAY_SIGN P_SetMobjState(ov, actor->info->seestate); // S_PLAY_SIGN
actor->tracer->color = signcolor;
actor->tracer->frame = signframe;
} }
else // Eggman face else // Eggman face
{ {
ov->color = SKINCOLOR_NONE; ov->color = SKINCOLOR_NONE;
P_SetMobjState(ov, actor->info->meleestate); // S_EGGMANSIGN P_SetMobjState(ov, actor->info->meleestate); // S_EGGMANSIGN
if (signcolor) if (!signcolor)
actor->tracer->color = signcolor; signcolor = SKINCOLOR_CARBON;
else
actor->tracer->color = signcolor = SKINCOLOR_CARBON;
actor->tracer->frame = signframe += (15 - Color_Opposite[Color_Opposite[signcolor - 1][0] - 1][1]);
} }
actor->tracer->color = signcolor;
/*
If you're here from the comment above Color_Opposite,
the following line is the one which is dependent on the
array being symmetrical. It gets the opposite of the
opposite of your desired colour just so it can get the
brightness frame for the End Sign. It's not a great
design choice, but it's constant time array access and
the idea that the colours should be OPPOSITES is kind
of in the name. If you have a better idea, feel free
to let me know. ~toast 2016/07/20
*/
if (signcolor && signcolor < MAXSKINCOLORS)
signframe += (15 - Color_Opposite[Color_Opposite[signcolor - 1][0] - 1][1]);
actor->tracer->frame = signframe;
} }
// Function: A_OverlayThink // Function: A_OverlayThink

View File

@ -2741,7 +2741,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
case MT_EGGTRAP: case MT_EGGTRAP:
// Time for birdies! Yaaaaaaaay! // Time for birdies! Yaaaaaaaay!
target->fuse = TICRATE*2; target->fuse = TICRATE;
break; break;
case MT_MINECART: case MT_MINECART:
@ -3002,6 +3002,10 @@ static inline void P_NiGHTSDamage(mobj_t *target, mobj_t *source)
P_SetPlayerMobjState(target, S_PLAY_NIGHTS_STUN); P_SetPlayerMobjState(target, S_PLAY_NIGHTS_STUN);
S_StartSound(target, sfx_nghurt); S_StartSound(target, sfx_nghurt);
#ifdef ROTSPRITE
player->mo->rollangle = 0;
#endif
if (oldnightstime > 10*TICRATE if (oldnightstime > 10*TICRATE
&& player->nightstime < 10*TICRATE) && player->nightstime < 10*TICRATE)
{ {

View File

@ -172,6 +172,7 @@ void P_ElementalFire(player_t *player, boolean cropcircle);
void P_DoPityCheck(player_t *player); void P_DoPityCheck(player_t *player);
void P_PlayerThink(player_t *player); void P_PlayerThink(player_t *player);
void P_PlayerAfterThink(player_t *player); void P_PlayerAfterThink(player_t *player);
void P_DoPlayerFinish(player_t *player);
void P_DoPlayerExit(player_t *player); void P_DoPlayerExit(player_t *player);
void P_NightserizePlayer(player_t *player, INT32 ptime); void P_NightserizePlayer(player_t *player, INT32 ptime);

View File

@ -592,6 +592,9 @@ static void P_DoTailsCarry(player_t *sonic, player_t *tails)
if (!(tails->pflags & PF_CANCARRY)) if (!(tails->pflags & PF_CANCARRY))
return; return;
if (sonic->pflags & PF_FINISHED)
return;
if (tails->bot == 1) if (tails->bot == 1)
return; return;
@ -661,31 +664,32 @@ static void P_SlapStick(mobj_t *fang, mobj_t *pole)
momx2 = fang->momx/dist; momx2 = fang->momx/dist;
momy2 = fang->momy/dist; momy2 = fang->momy/dist;
pole->tracer->momx = momx1 + (dist-1)*momx2; pole->tracer->tracer->momx = momx1 + (dist-1)*momx2;
pole->tracer->momy = momy1 + (dist-1)*momy2; pole->tracer->tracer->momy = momy1 + (dist-1)*momy2;
fang->momx = (dist-1)*momx1 + momx2; fang->momx = (dist-1)*momx1 + momx2;
fang->momy = (dist-1)*momy1 + momy2; fang->momy = (dist-1)*momy1 + momy2;
#undef dist #undef dist
P_SetMobjState(pole, pole->info->deathstate); P_SetObjectMomZ(pole->tracer->tracer, 6*FRACUNIT, false);
pole->tracer->tracer->flags &= ~(MF_NOGRAVITY|MF_NOCLIP);
P_SetObjectMomZ(pole->tracer, 6*FRACUNIT, false); pole->tracer->tracer->movedir = ANGLE_67h;
pole->tracer->flags &= ~(MF_NOGRAVITY|MF_NOCLIP); if ((R_PointToAngle(fang->x - pole->tracer->tracer->x, fang->y - pole->tracer->tracer->y) - pole->angle) > ANGLE_180)
pole->tracer->movedir = ANGLE_67h; pole->tracer->tracer->movedir = InvAngle(pole->tracer->movedir);
if ((R_PointToAngle(fang->x - pole->tracer->x, fang->y - pole->tracer->y) - pole->angle) > ANGLE_180)
pole->tracer->movedir = InvAngle(pole->tracer->movedir);
P_SetObjectMomZ(fang, 14*FRACUNIT, false); P_SetObjectMomZ(fang, 14*FRACUNIT, false);
fang->flags |= MF_NOGRAVITY|MF_NOCLIP; fang->flags |= MF_NOGRAVITY|MF_NOCLIP;
P_SetMobjState(fang, fang->info->xdeathstate); P_SetMobjState(fang, fang->info->xdeathstate);
pole->tracer->tics = pole->tics = fang->tics; pole->tracer->tracer->tics = pole->tracer->tics = pole->tics = fang->tics;
var1 = var2 = 0; var1 = var2 = 0;
A_Scream(pole->tracer); A_Scream(pole->tracer->tracer);
S_StartSound(fang, sfx_altdi1); S_StartSound(fang, sfx_altdi1);
P_SetTarget(&pole->tracer->tracer, NULL);
P_SetMobjState(pole->tracer, pole->info->xdeathstate);
P_SetTarget(&pole->tracer, NULL); P_SetTarget(&pole->tracer, NULL);
P_SetMobjState(pole, pole->info->deathstate);
} }
static void P_PlayerBarrelCollide(mobj_t *toucher, mobj_t *barrel) static void P_PlayerBarrelCollide(mobj_t *toucher, mobj_t *barrel)
@ -1089,7 +1093,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
return true; // overhead return true; // overhead
if (thing->z + thing->height < tmthing->z) if (thing->z + thing->height < tmthing->z)
return true; // underneath return true; // underneath
if (!thing->tracer) if (!thing->tracer || !thing->tracer->tracer)
return true; return true;
P_SlapStick(tmthing, thing); P_SlapStick(tmthing, thing);
// no return value was used in the original prototype script at this point, // no return value was used in the original prototype script at this point,
@ -1301,6 +1305,11 @@ static boolean PIT_CheckThing(mobj_t *thing)
return false; return false;
} }
// Fireball touched an enemy
// Don't bounce though, just despawn right there
if ((tmthing->type == MT_FIREBALL) && (thing->flags & MF_ENEMY))
P_KillMobj(tmthing, NULL, NULL, 0);
// damage / explode // damage / explode
if (tmthing->flags & MF_ENEMY) // An actual ENEMY! (Like the deton, for example) if (tmthing->flags & MF_ENEMY) // An actual ENEMY! (Like the deton, for example)
P_DamageMobj(thing, tmthing, tmthing, 1, 0); P_DamageMobj(thing, tmthing, tmthing, 1, 0);

View File

@ -246,6 +246,7 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state)
{ {
case S_PLAY_STND: case S_PLAY_STND:
case S_PLAY_WAIT: case S_PLAY_WAIT:
case S_PLAY_NIGHTS_STAND:
player->panim = PA_IDLE; player->panim = PA_IDLE;
break; break;
case S_PLAY_EDGE: case S_PLAY_EDGE:
@ -254,6 +255,7 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state)
case S_PLAY_WALK: case S_PLAY_WALK:
case S_PLAY_SKID: case S_PLAY_SKID:
case S_PLAY_FLOAT: case S_PLAY_FLOAT:
case S_PLAY_NIGHTS_FLOAT:
player->panim = PA_WALK; player->panim = PA_WALK;
break; break;
case S_PLAY_RUN: case S_PLAY_RUN:
@ -269,6 +271,7 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state)
break; break;
case S_PLAY_ROLL: case S_PLAY_ROLL:
//case S_PLAY_SPINDASH: -- everyone can ROLL thanks to zoom tubes... //case S_PLAY_SPINDASH: -- everyone can ROLL thanks to zoom tubes...
case S_PLAY_NIGHTS_ATTACK:
player->panim = PA_ROLL; player->panim = PA_ROLL;
break; break;
case S_PLAY_JUMP: case S_PLAY_JUMP:
@ -8227,7 +8230,7 @@ void P_MobjThinker(mobj_t *mobj)
mobj->flags2 ^= MF2_DONTDRAW; mobj->flags2 ^= MF2_DONTDRAW;
break; break;
case MT_EGGTRAP: // Egg Capsule animal release case MT_EGGTRAP: // Egg Capsule animal release
if (mobj->fuse > 0 && mobj->fuse < 2*TICRATE-(TICRATE/7)) if (mobj->fuse > 0)// && mobj->fuse < TICRATE-(TICRATE/7))
{ {
INT32 i; INT32 i;
fixed_t x,y,z; fixed_t x,y,z;
@ -8236,9 +8239,9 @@ void P_MobjThinker(mobj_t *mobj)
mobj_t *flicky; mobj_t *flicky;
z = mobj->subsector->sector->floorheight + FRACUNIT + (P_RandomKey(64)<<FRACBITS); z = mobj->subsector->sector->floorheight + FRACUNIT + (P_RandomKey(64)<<FRACBITS);
for (i = 0; i < 2; i++) for (i = 0; i < 3; i++)
{ {
const angle_t fa = (P_RandomByte()*FINEANGLES/16) & FINEMASK; const angle_t fa = P_RandomKey(FINEANGLES) & FINEMASK;
ns = 64 * FRACUNIT; ns = 64 * FRACUNIT;
x = mobj->x + FixedMul(FINESINE(fa),ns); x = mobj->x + FixedMul(FINESINE(fa),ns);
y = mobj->y + FixedMul(FINECOSINE(fa),ns); y = mobj->y + FixedMul(FINECOSINE(fa),ns);
@ -8690,6 +8693,13 @@ void P_MobjThinker(mobj_t *mobj)
case MT_KOOPA: case MT_KOOPA:
P_KoopaThinker(mobj); P_KoopaThinker(mobj);
break; break;
case MT_FIREBALL:
if (P_AproxDistance(mobj->momx, mobj->momy) <= 16*FRACUNIT) // Once fireballs lose enough speed, kill them
{
P_KillMobj(mobj, NULL, NULL, 0);
return;
}
break;
case MT_REDRING: case MT_REDRING:
if (((mobj->z < mobj->floorz) || (mobj->z + mobj->height > mobj->ceilingz)) if (((mobj->z < mobj->floorz) || (mobj->z + mobj->height > mobj->ceilingz))
&& mobj->flags & MF_MISSILE) && mobj->flags & MF_MISSILE)

View File

@ -3244,47 +3244,22 @@ boolean P_SetupLevel(boolean skipprecip)
#endif #endif
} }
// Stage title! // No render mode, stop here.
wipestyleflags |= WSF_FADEIN; if (rendermode == render_none)
wipestyleflags &= ~WSF_FADEOUT; return true;
WipeInLevel = true;
if (rendermode != render_none
&& (!titlemapinaction)
&& ranspecialwipe != 2
&& *mapheaderinfo[gamemap-1]->lvlttl != '\0'
#ifdef HAVE_BLUA
&& LUA_HudEnabled(hud_stagetitle)
#endif
)
{
tic_t starttime = I_GetTime();
tic_t endtime = starttime + (10*NEWTICRATERATIO);
tic_t nowtime = starttime;
tic_t lasttime = starttime;
while (nowtime < endtime)
{
// draw loop
while (!((nowtime = I_GetTime()) - lasttime))
I_Sleep();
lasttime = nowtime;
F_WipeColorFill(levelfadecol); // Title card!
stplyr = &players[consoleplayer]; G_StartTitleCard();
ST_drawLevelTitle(nowtime - starttime);
if (splitscreen)
{
stplyr = &players[secondarydisplayplayer];
ST_drawLevelTitle(nowtime - starttime);
}
I_OsPolling(); // Can the title card actually run, though?
I_UpdateNoBlit(); if (!WipeStageTitle)
I_FinishUpdate(); // page flip or blit buffer return true;
if (ranspecialwipe == 2)
return true;
if (moviemode) // make sure we save frames for the white hold too // If so...
M_SaveFrame(); if ((!(mapheaderinfo[gamemap-1]->levelflags & LF_NOTITLECARD)) && (*mapheaderinfo[gamemap-1]->lvlttl != '\0'))
} G_PreLevelTitleCard(lt_ticker, true);
}
return true; return true;
} }

View File

@ -4675,7 +4675,7 @@ DoneSection2:
{ {
INT32 lineindex; INT32 lineindex;
P_DoPlayerExit(player); P_DoPlayerFinish(player);
P_SetupSignExit(player); P_SetupSignExit(player);
// important: use sector->tag on next line instead of player->mo->subsector->tag // important: use sector->tag on next line instead of player->mo->subsector->tag

View File

@ -636,6 +636,10 @@ static void P_DeNightserizePlayer(player_t *player)
player->marebonuslap = 0; player->marebonuslap = 0;
player->flyangle = 0; player->flyangle = 0;
player->anotherflyangle = 0; player->anotherflyangle = 0;
#ifdef ROTSPRITE
player->mo->rollangle = 0;
#endif
P_SetTarget(&player->mo->target, NULL); P_SetTarget(&player->mo->target, NULL);
P_SetTarget(&player->axis1, P_SetTarget(&player->axis2, NULL)); P_SetTarget(&player->axis1, P_SetTarget(&player->axis2, NULL));
@ -762,6 +766,9 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime)
player->secondjump = 0; player->secondjump = 0;
player->flyangle = 0; player->flyangle = 0;
player->anotherflyangle = 0; player->anotherflyangle = 0;
#ifdef ROTSPRITE
player->mo->rollangle = 0;
#endif
player->powers[pw_shield] = SH_NONE; player->powers[pw_shield] = SH_NONE;
player->powers[pw_super] = 0; player->powers[pw_super] = 0;
@ -2124,6 +2131,30 @@ void P_SpawnSpinMobj(player_t *player, mobjtype_t type)
P_SetTarget(&mobj->target, player->mo); // the one thing P_SpawnGhostMobj doesn't do P_SetTarget(&mobj->target, player->mo); // the one thing P_SpawnGhostMobj doesn't do
} }
/** Called when \p player finishes the level.
*
* Only use for cases where the player should be able to move
* while waiting for others to finish. Otherwise, use P_DoPlayerExit().
*
* In single player or if ::cv_exitmove is disabled, this will also cause
* P_PlayerThink() to call P_DoPlayerExit(), so you do not need to
* make a special cases for those.
*
* \param player The player who finished the level.
* \sa P_DoPlayerExit
*
*/
void P_DoPlayerFinish(player_t *player)
{
if (player->pflags & PF_FINISHED)
return;
player->pflags |= PF_FINISHED;
if (netgame)
CONS_Printf(M_GetText("%s has completed the level.\n"), player_names[player-players]);
}
// //
// P_DoPlayerExit // P_DoPlayerExit
// //
@ -2158,12 +2189,14 @@ void P_DoPlayerExit(player_t *player)
player->pflags |= P_GetJumpFlags(player); player->pflags |= P_GetJumpFlags(player);
P_SetPlayerMobjState(player->mo, S_PLAY_JUMP); P_SetPlayerMobjState(player->mo, S_PLAY_JUMP);
} }
else if (player->pflags & PF_STARTDASH)
{
player->pflags &= ~PF_STARTDASH;
P_SetPlayerMobjState(player->mo, S_PLAY_STND);
}
player->powers[pw_underwater] = 0; player->powers[pw_underwater] = 0;
player->powers[pw_spacetime] = 0; player->powers[pw_spacetime] = 0;
P_RestoreMusic(player); P_RestoreMusic(player);
if (playeringame[player-players] && netgame && !circuitmap)
CONS_Printf(M_GetText("%s has completed the level.\n"), player_names[player-players]);
} }
#define SPACESPECIAL 12 #define SPACESPECIAL 12
@ -3993,12 +4026,13 @@ static void P_DoFiring(player_t *player, ticcmd_t *cmd)
if (player->pflags & PF_ATTACKDOWN || player->climbing || (G_TagGametype() && !(player->pflags & PF_TAGIT))) if (player->pflags & PF_ATTACKDOWN || player->climbing || (G_TagGametype() && !(player->pflags & PF_TAGIT)))
return; return;
if ((player->powers[pw_shield] & SH_STACK) == SH_FIREFLOWER) if (((player->powers[pw_shield] & SH_STACK) == SH_FIREFLOWER) && !(player->weapondelay))
{ {
player->pflags |= PF_ATTACKDOWN; player->pflags |= PF_ATTACKDOWN;
mo = P_SpawnPlayerMissile(player->mo, MT_FIREBALL, 0); mo = P_SpawnPlayerMissile(player->mo, MT_FIREBALL, 0);
P_InstaThrust(mo, player->mo->angle, ((mo->info->speed>>FRACBITS)*player->mo->scale) + player->speed); P_InstaThrust(mo, player->mo->angle, ((mo->info->speed>>FRACBITS)*player->mo->scale) + player->speed);
S_StartSound(player->mo, sfx_mario7); S_StartSound(player->mo, sfx_mario7);
P_SetWeaponDelay(player, TICRATE); // Short delay between fireballs so you can't spam them everywhere
return; return;
} }
@ -7701,9 +7735,9 @@ void P_ElementalFire(player_t *player, boolean cropcircle)
I_Assert(!P_MobjWasRemoved(player->mo)); I_Assert(!P_MobjWasRemoved(player->mo));
if (player->mo->eflags & MFE_VERTICALFLIP) if (player->mo->eflags & MFE_VERTICALFLIP)
ground = player->mo->ceilingz - FixedMul(mobjinfo[MT_SPINFIRE].height, player->mo->scale); ground = player->mo->ceilingz - FixedMul(mobjinfo[MT_SPINFIRE].height - 1, player->mo->scale);
else else
ground = player->mo->floorz; ground = player->mo->floorz + 1;
if (cropcircle) if (cropcircle)
{ {
@ -9889,10 +9923,20 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
pviewheight = FixedMul(41*player->height/48, mo->scale); pviewheight = FixedMul(41*player->height/48, mo->scale);
if (mo->eflags & MFE_VERTICALFLIP) if (sign)
z = mo->z + mo->height - pviewheight - camheight + distz; {
if (mo->eflags & MFE_VERTICALFLIP)
z = sign->ceilingz - pviewheight - camheight;
else
z = sign->floorz + pviewheight + camheight;
}
else else
z = mo->z + pviewheight + camheight + distz; {
if (mo->eflags & MFE_VERTICALFLIP)
z = mo->z + mo->height - pviewheight - camheight + distz;
else
z = mo->z + pviewheight + camheight + distz;
}
// move camera down to move under lower ceilings // move camera down to move under lower ceilings
newsubsec = R_IsPointInSubsector(((mo->x>>FRACBITS) + (thiscam->x>>FRACBITS))<<(FRACBITS-1), ((mo->y>>FRACBITS) + (thiscam->y>>FRACBITS))<<(FRACBITS-1)); newsubsec = R_IsPointInSubsector(((mo->x>>FRACBITS) + (thiscam->x>>FRACBITS))<<(FRACBITS-1), ((mo->y>>FRACBITS) + (thiscam->y>>FRACBITS))<<(FRACBITS-1));
@ -11400,6 +11444,14 @@ void P_PlayerThink(player_t *player)
} }
} }
if (player->pflags & PF_FINISHED)
{
if (cv_exitmove.value && !G_EnoughPlayersFinished())
player->exiting = 0;
else
P_DoPlayerExit(player);
}
// check water content, set stuff in mobj // check water content, set stuff in mobj
P_MobjCheckWater(player->mo); P_MobjCheckWater(player->mo);

View File

@ -123,8 +123,12 @@ consvar_t cv_chasecam2 = {"chasecam2", "On", CV_CALL, CV_OnOff, ChaseCam2_OnChan
consvar_t cv_flipcam = {"flipcam", "No", CV_SAVE|CV_CALL|CV_NOINIT, CV_YesNo, FlipCam_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_flipcam = {"flipcam", "No", CV_SAVE|CV_CALL|CV_NOINIT, CV_YesNo, FlipCam_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_flipcam2 = {"flipcam2", "No", CV_SAVE|CV_CALL|CV_NOINIT, CV_YesNo, FlipCam2_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_flipcam2 = {"flipcam2", "No", CV_SAVE|CV_CALL|CV_NOINIT, CV_YesNo, FlipCam2_OnChange, 0, NULL, NULL, 0, 0, NULL};
#if defined(FLOORSPLATS) || defined(GLBADSHADOWS)
consvar_t cv_shadow = {"shadow", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_shadow = {"shadow", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
#endif //#if defined(FLOORSPLATS) || defined(GLBADSHADOWS)
#ifdef GLBADSHADOWS
consvar_t cv_shadowoffs = {"offsetshadows", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_shadowoffs = {"offsetshadows", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
#endif //#ifdef GLBADSHADOWS
consvar_t cv_skybox = {"skybox", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_skybox = {"skybox", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_allowmlook = {"allowmlook", "Yes", CV_NETVAR, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_allowmlook = {"allowmlook", "Yes", CV_NETVAR, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_showhud = {"showhud", "Yes", CV_CALL, CV_YesNo, R_SetViewSize, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_showhud = {"showhud", "Yes", CV_CALL, CV_YesNo, R_SetViewSize, 0, NULL, NULL, 0, 0, NULL};
@ -1172,8 +1176,12 @@ void R_RegisterEngineStuff(void)
CV_RegisterVar(&cv_chasecam); CV_RegisterVar(&cv_chasecam);
CV_RegisterVar(&cv_chasecam2); CV_RegisterVar(&cv_chasecam2);
#if defined(FLOORSPLATS) || defined(GLBADSHADOWS)
CV_RegisterVar(&cv_shadow); CV_RegisterVar(&cv_shadow);
#endif //#if defined(FLOORSPLATS) || defined(GLBADSHADOWS)
#ifdef GLBADSHADOWS
CV_RegisterVar(&cv_shadowoffs); CV_RegisterVar(&cv_shadowoffs);
#endif //#ifdef GLBADSHADOWS
CV_RegisterVar(&cv_skybox); CV_RegisterVar(&cv_skybox);
CV_RegisterVar(&cv_cam_dist); CV_RegisterVar(&cv_cam_dist);

View File

@ -76,7 +76,12 @@ extern consvar_t cv_showhud, cv_translucenthud;
extern consvar_t cv_homremoval; extern consvar_t cv_homremoval;
extern consvar_t cv_chasecam, cv_chasecam2; extern consvar_t cv_chasecam, cv_chasecam2;
extern consvar_t cv_flipcam, cv_flipcam2; extern consvar_t cv_flipcam, cv_flipcam2;
extern consvar_t cv_shadow, cv_shadowoffs; #if defined(FLOORSPLATS) || defined(GLBADSHADOWS)
extern consvar_t cv_shadow;
#endif
#ifdef GLBADSHADOWS
extern conscar_t cv_shadowoffs;
#endif //#ifdef GLBADSHADOWS
extern consvar_t cv_translucency; extern consvar_t cv_translucency;
extern consvar_t cv_drawdist, cv_drawdist_nights, cv_drawdist_precip; extern consvar_t cv_drawdist, cv_drawdist_nights, cv_drawdist_precip;
extern consvar_t cv_skybox; extern consvar_t cv_skybox;

View File

@ -1066,16 +1066,15 @@ void R_ParseSPRTINFOLump(UINT16 wadNum, UINT16 lumpNum)
sprinfoToken = M_GetToken(sprinfoText); sprinfoToken = M_GetToken(sprinfoText);
while (sprinfoToken != NULL) while (sprinfoToken != NULL)
{ {
if (!stricmp(sprinfoToken, "SPRITE") || !stricmp(sprinfoToken, "SPRITE2")) if (!stricmp(sprinfoToken, "SPRITE"))
{ R_ParseSpriteInfo(false);
Z_Free(sprinfoToken); else if (!stricmp(sprinfoToken, "SPRITE2"))
R_ParseSpriteInfo(!stricmp(sprinfoToken, "SPRITE2")); R_ParseSpriteInfo(true);
}
else else
I_Error("Error parsing SPRTINFO lump: Unknown keyword \"%s\"", sprinfoToken); I_Error("Error parsing SPRTINFO lump: Unknown keyword \"%s\"", sprinfoToken);
Z_Free(sprinfoToken);
sprinfoToken = M_GetToken(NULL); sprinfoToken = M_GetToken(NULL);
} }
Z_Free(sprinfoToken);
Z_Free((void *)sprinfoText); Z_Free((void *)sprinfoText);
} }

View File

@ -1196,20 +1196,20 @@ static void R_ProjectSprite(mobj_t *thing)
#ifdef ROTSPRITE #ifdef ROTSPRITE
sprinfo = NULL; sprinfo = NULL;
#endif #endif
}
if (rot >= sprdef->numframes) if (rot >= sprdef->numframes)
{
CONS_Alert(CONS_ERROR, M_GetText("R_ProjectSprite: invalid sprite frame %s/%s for %s\n"),
sizeu1(rot), sizeu2(sprdef->numframes), sprnames[thing->sprite]);
thing->sprite = states[S_UNKNOWN].sprite;
thing->frame = states[S_UNKNOWN].frame;
sprdef = &sprites[thing->sprite];
rot = thing->frame&FF_FRAMEMASK;
if (!thing->skin)
{ {
thing->state->sprite = thing->sprite; CONS_Alert(CONS_ERROR, M_GetText("R_ProjectSprite: invalid sprite frame %s/%s for %s\n"),
thing->state->frame = thing->frame; sizeu1(rot), sizeu2(sprdef->numframes), sprnames[thing->sprite]);
if (thing->sprite == thing->state->sprite && thing->frame == thing->state->frame)
{
thing->state->sprite = states[S_UNKNOWN].sprite;
thing->state->frame = states[S_UNKNOWN].frame;
}
thing->sprite = states[S_UNKNOWN].sprite;
thing->frame = states[S_UNKNOWN].frame;
sprdef = &sprites[thing->sprite];
rot = thing->frame&FF_FRAMEMASK;
} }
} }

View File

@ -428,6 +428,17 @@ void SCR_DisplayTicRate(void)
lasttic = ontic; lasttic = ontic;
} }
void SCR_DisplayLocalPing(void)
{
UINT32 ping = playerpingtable[consoleplayer]; // consoleplayer's ping is everyone's ping in a splitnetgame :P
if (cv_showping.value == 1 || (cv_showping.value == 2 && servermaxping && ping > servermaxping)) // only show 2 (warning) if our ping is at a bad level
{
INT32 dispy = cv_ticrate.value ? 180 : 189;
HU_drawPing(307, dispy, ping, true, V_SNAPTORIGHT | V_SNAPTOBOTTOM);
}
}
void SCR_ClosedCaptions(void) void SCR_ClosedCaptions(void)
{ {
UINT8 i; UINT8 i;

View File

@ -167,5 +167,6 @@ FUNCMATH boolean SCR_IsAspectCorrect(INT32 width, INT32 height);
// move out to main code for consistency // move out to main code for consistency
void SCR_DisplayTicRate(void); void SCR_DisplayTicRate(void);
void SCR_ClosedCaptions(void); void SCR_ClosedCaptions(void);
void SCR_DisplayLocalPing(void);
#undef DNWH #undef DNWH
#endif //__SCREEN_H__ #endif //__SCREEN_H__

View File

@ -1180,6 +1180,9 @@ void I_FinishUpdate(void)
{ {
if (cv_ticrate.value) if (cv_ticrate.value)
SCR_DisplayTicRate(); SCR_DisplayTicRate();
if (cv_showping.value && netgame && consoleplayer != serverplayer)
SCR_DisplayLocalPing();
} }
if (rendermode == render_soft && screens[0]) if (rendermode == render_soft && screens[0])

View File

@ -779,7 +779,7 @@ sfxinfo_t S_sfx[NUMSFX] =
{"kc49", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"kc49", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"kc4a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"kc4a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"kc4b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"kc4b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"kc4c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"kc4c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Pop-shot"},
{"kc4d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Power up"}, {"kc4d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Power up"},
{"kc4e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"kc4e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"kc4f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"kc4f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},

View File

@ -23,6 +23,7 @@
#include "v_video.h" #include "v_video.h"
#include "z_zone.h" #include "z_zone.h"
#include "hu_stuff.h" #include "hu_stuff.h"
#include "console.h"
#include "s_sound.h" #include "s_sound.h"
#include "i_system.h" #include "i_system.h"
#include "m_menu.h" #include "m_menu.h"
@ -186,14 +187,18 @@ boolean ST_SameTeam(player_t *a, player_t *b)
static boolean st_stopped = true; static boolean st_stopped = true;
void ST_Ticker(void) void ST_Ticker(boolean run)
{ {
if (st_stopped) if (st_stopped)
return; return;
if (run)
ST_runTitleCard();
} }
// 0 is default, any others are special palettes. // 0 is default, any others are special palettes.
INT32 st_palette = 0; INT32 st_palette = 0;
INT32 st_translucency = 0;
void ST_doPaletteStuff(void) void ST_doPaletteStuff(void)
{ {
@ -818,7 +823,7 @@ static void ST_drawLivesArea(void)
face = superprefix[stplyr->skin]; face = superprefix[stplyr->skin];
V_DrawSmallMappedPatch(hudinfo[HUD_LIVES].x, hudinfo[HUD_LIVES].y, V_DrawSmallMappedPatch(hudinfo[HUD_LIVES].x, hudinfo[HUD_LIVES].y,
hudinfo[HUD_LIVES].f|V_PERPLAYER|V_HUDTRANS, face, colormap); hudinfo[HUD_LIVES].f|V_PERPLAYER|V_HUDTRANS, face, colormap);
if (cv_translucenthud.value == 10 && stplyr->powers[pw_super] == 1 && stplyr->mo->tracer) if (st_translucency == 10 && stplyr->powers[pw_super] == 1 && stplyr->mo->tracer)
{ {
INT32 v_supertrans = (stplyr->mo->tracer->frame & FF_TRANSMASK) >> FF_TRANSSHIFT; INT32 v_supertrans = (stplyr->mo->tracer->frame & FF_TRANSMASK) >> FF_TRANSSHIFT;
if (v_supertrans < 10) if (v_supertrans < 10)
@ -1160,16 +1165,144 @@ static void ST_drawInput(void)
V_DrawThinString(x, y, hudinfo[HUD_LIVES].f|((leveltime & 4) ? V_YELLOWMAP : V_REDMAP), "BAD DEMO!!"); V_DrawThinString(x, y, hudinfo[HUD_LIVES].f|((leveltime & 4) ? V_YELLOWMAP : V_REDMAP), "BAD DEMO!!");
} }
void ST_drawLevelTitle(tic_t titletime) static patch_t *lt_patches[3];
static INT32 lt_scroll = 0;
static INT32 lt_mom = 0;
static INT32 lt_zigzag = 0;
tic_t lt_ticker = 0, lt_lasttic = 0;
tic_t lt_exitticker = 0, lt_endtime = 0;
//
// Load the graphics for the title card.
//
static void ST_cacheLevelTitle(void)
{
if (!(mapheaderinfo[gamemap-1]->levelflags & LF_WARNINGTITLE))
{
lt_patches[0] = (patch_t *)W_CachePatchName("LTACTBLU", PU_HUDGFX);
lt_patches[1] = (patch_t *)W_CachePatchName("LTZIGZAG", PU_HUDGFX);
lt_patches[2] = (patch_t *)W_CachePatchName("LTZZTEXT", PU_HUDGFX);
}
else // boss map
{
lt_patches[0] = (patch_t *)W_CachePatchName("LTACTRED", PU_HUDGFX);
lt_patches[1] = (patch_t *)W_CachePatchName("LTZIGRED", PU_HUDGFX);
lt_patches[2] = (patch_t *)W_CachePatchName("LTZZWARN", PU_HUDGFX);
}
}
//
// Start the title card.
//
void ST_startTitleCard(void)
{
// cache every HUD patch used
ST_cacheLevelTitle();
// initialize HUD variables
lt_ticker = lt_exitticker = lt_lasttic = 0;
lt_endtime = 2*TICRATE;
lt_scroll = BASEVIDWIDTH * FRACUNIT;
lt_zigzag = -((lt_patches[1])->width * FRACUNIT);
lt_mom = 0;
}
//
// What happens before drawing the title card.
// Which is just setting the HUD translucency.
//
void ST_preDrawTitleCard(void)
{
if (lt_ticker >= (lt_endtime + TICRATE))
return;
if (!lt_exitticker)
st_translucency = 0;
else
st_translucency = max(0, min((INT32)lt_exitticker-4, cv_translucenthud.value));
}
//
// Run the title card.
// Called from ST_Ticker.
//
void ST_runTitleCard(void)
{
if (lt_ticker >= (lt_endtime + TICRATE))
return;
if (!(paused || P_AutoPause()))
{
// tick
lt_ticker++;
if (lt_ticker >= lt_endtime)
lt_exitticker++;
// scroll to screen (level title)
if (!lt_exitticker)
{
if (abs(lt_scroll) > FRACUNIT)
lt_scroll -= (lt_scroll>>2);
else
lt_scroll = 0;
}
// scroll away from screen (level title)
else
{
lt_mom -= FRACUNIT*6;
lt_scroll += lt_mom;
}
// scroll to screen (zigzag)
if (!lt_exitticker)
{
if (abs(lt_zigzag) > FRACUNIT)
lt_zigzag -= (lt_zigzag>>2);
else
lt_zigzag = 0;
}
// scroll away from screen (zigzag)
else
lt_zigzag += lt_mom;
}
}
//
// Draw the title card itself.
//
void ST_drawTitleCard(void)
{ {
char *lvlttl = mapheaderinfo[gamemap-1]->lvlttl; char *lvlttl = mapheaderinfo[gamemap-1]->lvlttl;
char *subttl = mapheaderinfo[gamemap-1]->subttl; char *subttl = mapheaderinfo[gamemap-1]->subttl;
INT32 actnum = mapheaderinfo[gamemap-1]->actnum; INT32 actnum = mapheaderinfo[gamemap-1]->actnum;
INT32 lvlttly, zoney, lvlttlxpos, ttlnumxpos, zonexpos; INT32 lvlttlxpos, ttlnumxpos, zonexpos;
INT32 subttlxpos = BASEVIDWIDTH/2; INT32 subttlxpos = BASEVIDWIDTH/2;
INT32 ttlscroll = FixedInt(lt_scroll);
INT32 zzticker;
patch_t *actpat, *zigzag, *zztext;
if (!(titletime > 2 && titletime-3 < 110)) #ifdef HAVE_BLUA
if (!LUA_HudEnabled(hud_stagetitle))
goto luahook;
#endif
if (lt_ticker >= (lt_endtime + TICRATE))
#ifdef HAVE_BLUA
goto luahook;
#else
return; return;
#endif
#ifndef LEVELWIPES
if ((lt_ticker-lt_lasttic) > 1)
lt_ticker = lt_lasttic+1;
#endif
ST_cacheLevelTitle();
actpat = lt_patches[0];
zigzag = lt_patches[1];
zztext = lt_patches[2];
lvlttlxpos = ((BASEVIDWIDTH/2) - (V_LevelNameWidth(lvlttl)/2)); lvlttlxpos = ((BASEVIDWIDTH/2) - (V_LevelNameWidth(lvlttl)/2));
@ -1177,72 +1310,73 @@ void ST_drawLevelTitle(tic_t titletime)
lvlttlxpos -= V_LevelActNumWidth(actnum); lvlttlxpos -= V_LevelActNumWidth(actnum);
ttlnumxpos = lvlttlxpos + V_LevelNameWidth(lvlttl); ttlnumxpos = lvlttlxpos + V_LevelNameWidth(lvlttl);
zonexpos = ttlnumxpos - V_LevelNameWidth(M_GetText("ZONE")); zonexpos = ttlnumxpos - V_LevelNameWidth(M_GetText("Zone"));
ttlnumxpos++; ttlnumxpos++;
if (lvlttlxpos < 0) if (lvlttlxpos < 0)
lvlttlxpos = 0; lvlttlxpos = 0;
#if 0 // toaster's experiment. srb2&toast.exe one day, maybe? Requires stuff below to be converted to fixed point. if (!splitscreen || (splitscreen && stplyr == &players[displayplayer]))
#define MIDTTLY 79
#define MIDZONEY 105
#define MIDDIFF 4
if (titletime < 10)
{ {
fixed_t z = ((titletime - 3)<<FRACBITS)/7; zzticker = lt_ticker;
INT32 ttlh = V_LevelNameHeight(lvlttl); V_DrawScaledPatch(FixedInt(lt_zigzag), (-zzticker) % zigzag->height, V_SNAPTOTOP|V_SNAPTOLEFT, zigzag);
zoney = (200<<FRACBITS) - ((200 - (MIDZONEY + MIDDIFF))*z); V_DrawScaledPatch(FixedInt(lt_zigzag), (zigzag->height-zzticker) % zigzag->height, V_SNAPTOTOP|V_SNAPTOLEFT, zigzag);
lvlttly = ((MIDTTLY + ttlh - MIDDIFF)*z) - (ttlh<<FRACBITS); V_DrawScaledPatch(FixedInt(lt_zigzag), (-zigzag->height+zzticker) % zztext->height, V_SNAPTOTOP|V_SNAPTOLEFT, zztext);
V_DrawScaledPatch(FixedInt(lt_zigzag), (zzticker) % zztext->height, V_SNAPTOTOP|V_SNAPTOLEFT, zztext);
} }
else if (titletime < 105)
{
fixed_t z = (((titletime - 10)*MIDDIFF)<<(FRACBITS+1))/95;
zoney = ((MIDZONEY + MIDDIFF)<<FRACBITS) - z;
lvlttly = ((MIDTTLY - MIDDIFF)<<FRACBITS) + z;
}
else
{
fixed_t z = ((titletime - 105)<<FRACBITS)/7;
INT32 zoneh = V_LevelNameHeight(M_GetText("ZONE"));
zoney = (MIDZONEY + zoneh - MIDDIFF)*(FRACUNIT - z) - (zoneh<<FRACBITS);
lvlttly = ((MIDTTLY + MIDDIFF)<<FRACBITS) + ((200 - (MIDTTLY + MIDDIFF))*z);
}
#undef MIDTTLY
#undef MIDZONEY
#undef MIDDIFF
#else
// There's no consistent algorithm that can accurately define the old positions
// so I just ended up resorting to a single switch statement to define them
switch (titletime-3)
{
case 0: zoney = 200; lvlttly = 0; break;
case 1: zoney = 188; lvlttly = 12; break;
case 2: zoney = 176; lvlttly = 24; break;
case 3: zoney = 164; lvlttly = 36; break;
case 4: zoney = 152; lvlttly = 48; break;
case 5: zoney = 140; lvlttly = 60; break;
case 6: zoney = 128; lvlttly = 72; break;
case 105: zoney = 80; lvlttly = 104; break;
case 106: zoney = 56; lvlttly = 128; break;
case 107: zoney = 32; lvlttly = 152; break;
case 108: zoney = 8; lvlttly = 176; break;
case 109: zoney = 0; lvlttly = 200; break;
default: zoney = 104; lvlttly = 80; break;
}
#endif
if (actnum) if (actnum)
V_DrawLevelActNum(ttlnumxpos, zoney, V_PERPLAYER, actnum); {
if (!splitscreen)
V_DrawLevelTitle(lvlttlxpos, lvlttly, V_PERPLAYER, lvlttl); V_DrawScaledPatch(ttlnumxpos + ttlscroll, 104 - ttlscroll, 0, actpat);
V_DrawLevelActNum(ttlnumxpos + ttlscroll, 104, V_PERPLAYER, actnum);
}
V_DrawLevelTitle(lvlttlxpos - ttlscroll, 80, V_PERPLAYER, lvlttl);
if (!(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE)) if (!(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE))
V_DrawLevelTitle(zonexpos, zoney, V_PERPLAYER, M_GetText("ZONE")); V_DrawLevelTitle(zonexpos + ttlscroll, 104, V_PERPLAYER, M_GetText("Zone"));
V_DrawCenteredString(subttlxpos - ttlnumxpos, 128, V_PERPLAYER|V_ALLOWLOWERCASE, subttl);
if (lvlttly+48 < 200) lt_lasttic = lt_ticker;
V_DrawCenteredString(subttlxpos, lvlttly+48, V_PERPLAYER|V_ALLOWLOWERCASE, subttl);
#ifdef HAVE_BLUA
luahook:
LUAh_TitleCardHUD(stplyr);
#endif
}
//
// Drawer for G_PreLevelTitleCard.
//
void ST_preLevelTitleCardDrawer(tic_t ticker, boolean update)
{
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, levelfadecol);
#ifndef LEVELWIPES
if (ticker < PRELEVELTIME-1)
#endif
ST_drawWipeTitleCard();
I_OsPolling();
I_UpdateNoBlit();
if (update)
I_FinishUpdate(); // page flip or blit buffer
}
//
// Draw the title card while on a wipe.
// Also used in G_PreLevelTitleCard.
//
void ST_drawWipeTitleCard(void)
{
stplyr = &players[consoleplayer];
ST_preDrawTitleCard();
ST_drawTitleCard();
if (splitscreen)
{
stplyr = &players[secondarydisplayplayer];
ST_preDrawTitleCard();
ST_drawTitleCard();
}
} }
static void ST_drawPowerupHUD(void) static void ST_drawPowerupHUD(void)
@ -2106,7 +2240,7 @@ static void ST_drawTextHUD(void)
textHUDdraw(M_GetText("\x82""FIRE:""\x80 Enter game")) textHUDdraw(M_GetText("\x82""FIRE:""\x80 Enter game"))
} }
if (gametype == GT_COOP && (!stplyr->spectator || (!(maptol & TOL_NIGHTS) && G_IsSpecialStage(gamemap))) && stplyr->exiting) if (gametype == GT_COOP && (!stplyr->spectator || (!(maptol & TOL_NIGHTS) && G_IsSpecialStage(gamemap))) && (stplyr->exiting || (stplyr->pflags & PF_FINISHED)))
{ {
UINT8 numneeded = (G_IsSpecialStage(gamemap) ? 4 : cv_playersforexit.value); UINT8 numneeded = (G_IsSpecialStage(gamemap) ? 4 : cv_playersforexit.value);
if (numneeded) if (numneeded)
@ -2121,7 +2255,7 @@ static void ST_drawTextHUD(void)
continue; continue;
total++; total++;
if (players[i].exiting) if (players[i].exiting || (players[i].pflags & PF_FINISHED))
exiting++; exiting++;
} }
@ -2394,12 +2528,25 @@ static void ST_doItemFinderIconsAndSound(void)
S_StartSound(NULL, sfx_emfind); S_StartSound(NULL, sfx_emfind);
} }
//
// Draw the status bar overlay, customisable: the user chooses which // Draw the status bar overlay, customisable: the user chooses which
// kind of information to overlay // kind of information to overlay
// //
static void ST_overlayDrawer(void) static void ST_overlayDrawer(void)
{ {
//hu_showscores = auto hide score/time/rings when tab rankings are shown // Decide whether to draw the stage title or not
boolean stagetitle = false;
// Check for a valid level title
// If the HUD is enabled
// And, if Lua is running, if the HUD library has the stage title enabled
if (!(mapheaderinfo[gamemap-1]->levelflags & LF_NOTITLECARD) && *mapheaderinfo[gamemap-1]->lvlttl != '\0' && !(hu_showscores && (netgame || multiplayer)))
{
stagetitle = true;
ST_preDrawTitleCard();
}
// hu_showscores = auto hide score/time/rings when tab rankings are shown
if (!(hu_showscores && (netgame || multiplayer))) if (!(hu_showscores && (netgame || multiplayer)))
{ {
if ((maptol & TOL_NIGHTS || G_IsSpecialStage(gamemap)) && if ((maptol & TOL_NIGHTS || G_IsSpecialStage(gamemap)) &&
@ -2550,12 +2697,8 @@ static void ST_overlayDrawer(void)
#endif #endif
// draw level title Tails // draw level title Tails
if (*mapheaderinfo[gamemap-1]->lvlttl != '\0' && !(hu_showscores && (netgame || multiplayer)) if (stagetitle && (!WipeInAction) && (!WipeStageTitle))
#ifdef HAVE_BLUA ST_drawTitleCard();
&& LUA_HudEnabled(hud_stagetitle)
#endif
)
ST_drawLevelTitle(timeinmap+70);
if (!hu_showscores && (netgame || multiplayer) if (!hu_showscores && (netgame || multiplayer)
#ifdef HAVE_BLUA #ifdef HAVE_BLUA
@ -2631,6 +2774,8 @@ void ST_Drawer(void)
} }
} }
st_translucency = cv_translucenthud.value;
if (st_overlay) if (st_overlay)
{ {
// No deadview! // No deadview!

View File

@ -24,7 +24,7 @@
// //
// Called by main loop. // Called by main loop.
void ST_Ticker(void); void ST_Ticker(boolean run);
// Called by main loop. // Called by main loop.
void ST_Drawer(void); void ST_Drawer(void);
@ -47,8 +47,16 @@ void ST_ReloadSkinFaceGraphics(void);
void ST_doPaletteStuff(void); void ST_doPaletteStuff(void);
// level title draw // title card
void ST_drawLevelTitle(tic_t titletime); void ST_startTitleCard(void);
void ST_runTitleCard(void);
void ST_drawTitleCard(void);
void ST_preDrawTitleCard(void);
void ST_preLevelTitleCardDrawer(tic_t ticker, boolean update);
void ST_drawWipeTitleCard(void);
extern tic_t lt_ticker, lt_lasttic;
extern tic_t lt_exitticker, lt_endtime;
// return if player a is in the same team as player b // return if player a is in the same team as player b
boolean ST_SameTeam(player_t *a, player_t *b); boolean ST_SameTeam(player_t *a, player_t *b);
@ -59,6 +67,7 @@ boolean ST_SameTeam(player_t *a, player_t *b);
extern boolean st_overlay; // sb overlay on or off when fullscreen extern boolean st_overlay; // sb overlay on or off when fullscreen
extern INT32 st_palette; // 0 is default, any others are special palettes. extern INT32 st_palette; // 0 is default, any others are special palettes.
extern INT32 st_translucency;
extern lumpnum_t st_borderpatchnum; extern lumpnum_t st_borderpatchnum;
// patches, also used in intermission // patches, also used in intermission

View File

@ -18,6 +18,7 @@
#include "p_local.h" // stplyr #include "p_local.h" // stplyr
#include "g_game.h" // players #include "g_game.h" // players
#include "v_video.h" #include "v_video.h"
#include "st_stuff.h"
#include "hu_stuff.h" #include "hu_stuff.h"
#include "r_draw.h" #include "r_draw.h"
#include "console.h" #include "console.h"
@ -574,11 +575,11 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca
if ((alphalevel = ((scrn & V_ALPHAMASK) >> V_ALPHASHIFT))) if ((alphalevel = ((scrn & V_ALPHAMASK) >> V_ALPHASHIFT)))
{ {
if (alphalevel == 13) if (alphalevel == 13)
alphalevel = hudminusalpha[cv_translucenthud.value]; alphalevel = hudminusalpha[st_translucency];
else if (alphalevel == 14) else if (alphalevel == 14)
alphalevel = 10 - cv_translucenthud.value; alphalevel = 10 - st_translucency;
else if (alphalevel == 15) else if (alphalevel == 15)
alphalevel = hudplusalpha[cv_translucenthud.value]; alphalevel = hudplusalpha[st_translucency];
if (alphalevel >= 10) if (alphalevel >= 10)
return; // invis return; // invis
@ -874,11 +875,11 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_
if ((alphalevel = ((scrn & V_ALPHAMASK) >> V_ALPHASHIFT))) if ((alphalevel = ((scrn & V_ALPHAMASK) >> V_ALPHASHIFT)))
{ {
if (alphalevel == 13) if (alphalevel == 13)
alphalevel = hudminusalpha[cv_translucenthud.value]; alphalevel = hudminusalpha[st_translucency];
else if (alphalevel == 14) else if (alphalevel == 14)
alphalevel = 10 - cv_translucenthud.value; alphalevel = 10 - st_translucency;
else if (alphalevel == 15) else if (alphalevel == 15)
alphalevel = hudplusalpha[cv_translucenthud.value]; alphalevel = hudplusalpha[st_translucency];
if (alphalevel >= 10) if (alphalevel >= 10)
return; // invis return; // invis
@ -1393,11 +1394,11 @@ void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c)
if ((alphalevel = ((c & V_ALPHAMASK) >> V_ALPHASHIFT))) if ((alphalevel = ((c & V_ALPHAMASK) >> V_ALPHASHIFT)))
{ {
if (alphalevel == 13) if (alphalevel == 13)
alphalevel = hudminusalpha[cv_translucenthud.value]; alphalevel = hudminusalpha[st_translucency];
else if (alphalevel == 14) else if (alphalevel == 14)
alphalevel = 10 - cv_translucenthud.value; alphalevel = 10 - st_translucency;
else if (alphalevel == 15) else if (alphalevel == 15)
alphalevel = hudplusalpha[cv_translucenthud.value]; alphalevel = hudplusalpha[st_translucency];
if (alphalevel >= 10) if (alphalevel >= 10)
return; // invis return; // invis
@ -2899,7 +2900,7 @@ void V_DrawLevelTitle(INT32 x, INT32 y, INT32 option, const char *string)
continue; continue;
} }
c = toupper(*ch) - LT_FONTSTART; c = *ch - LT_FONTSTART;
if (c < 0 || c >= LT_FONTSIZE || !lt_font[c]) if (c < 0 || c >= LT_FONTSIZE || !lt_font[c])
{ {
cx += 16*dupx; cx += 16*dupx;
@ -2934,7 +2935,7 @@ INT32 V_LevelNameWidth(const char *string)
{ {
if (string[i] & 0x80) if (string[i] & 0x80)
continue; continue;
c = toupper(string[i]) - LT_FONTSTART; c = string[i] - LT_FONTSTART;
if (c < 0 || c >= LT_FONTSIZE || !lt_font[c]) if (c < 0 || c >= LT_FONTSIZE || !lt_font[c])
w += 16; w += 16;
else else
@ -2953,7 +2954,7 @@ INT32 V_LevelNameHeight(const char *string)
for (i = 0; i < strlen(string); i++) for (i = 0; i < strlen(string); i++)
{ {
c = toupper(string[i]) - LT_FONTSTART; c = string[i] - LT_FONTSTART;
if (c < 0 || c >= LT_FONTSIZE || !lt_font[c]) if (c < 0 || c >= LT_FONTSIZE || !lt_font[c])
continue; continue;
@ -2964,7 +2965,7 @@ INT32 V_LevelNameHeight(const char *string)
return w; return w;
} }
// For ST_drawLevelTitle // For ST_drawTitleCard
// Returns the width of the act num patch // Returns the width of the act num patch
INT32 V_LevelActNumWidth(INT32 num) INT32 V_LevelActNumWidth(INT32 num)
{ {

View File

@ -383,7 +383,7 @@ static lumpinfo_t* ResGetLumpsWad (FILE* handle, UINT16* nlmp, const char* filen
// read the header // read the header
if (fread(&header, 1, sizeof header, handle) < sizeof header) if (fread(&header, 1, sizeof header, handle) < sizeof header)
{ {
CONS_Alert(CONS_ERROR, M_GetText("Can't read wad header because %s\n"), strerror(ferror(handle))); CONS_Alert(CONS_ERROR, M_GetText("Can't read wad header because %s\n"), M_FileError(handle));
return NULL; return NULL;
} }
@ -406,7 +406,7 @@ static lumpinfo_t* ResGetLumpsWad (FILE* handle, UINT16* nlmp, const char* filen
if (fseek(handle, header.infotableofs, SEEK_SET) == -1 if (fseek(handle, header.infotableofs, SEEK_SET) == -1
|| fread(fileinfo, 1, i, handle) < i) || fread(fileinfo, 1, i, handle) < i)
{ {
CONS_Alert(CONS_ERROR, M_GetText("Corrupt wadfile directory (%s)\n"), strerror(ferror(handle))); CONS_Alert(CONS_ERROR, M_GetText("Corrupt wadfile directory (%s)\n"), M_FileError(handle));
free(fileinfov); free(fileinfov);
return NULL; return NULL;
} }
@ -427,7 +427,7 @@ static lumpinfo_t* ResGetLumpsWad (FILE* handle, UINT16* nlmp, const char* filen
handle) < sizeof realsize) handle) < sizeof realsize)
{ {
I_Error("corrupt compressed file: %s; maybe %s", /// \todo Avoid the bailout? I_Error("corrupt compressed file: %s; maybe %s", /// \todo Avoid the bailout?
filename, strerror(ferror(handle))); filename, M_FileError(handle));
} }
realsize = LONG(realsize); realsize = LONG(realsize);
if (realsize != 0) if (realsize != 0)
@ -565,7 +565,7 @@ static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp)
fseek(handle, -4, SEEK_CUR); fseek(handle, -4, SEEK_CUR);
if (fread(&zend, 1, sizeof zend, handle) < sizeof zend) if (fread(&zend, 1, sizeof zend, handle) < sizeof zend)
{ {
CONS_Alert(CONS_ERROR, "Corrupt central directory (%s)\n", strerror(ferror(handle))); CONS_Alert(CONS_ERROR, "Corrupt central directory (%s)\n", M_FileError(handle));
return NULL; return NULL;
} }
numlumps = zend.entries; numlumps = zend.entries;
@ -582,7 +582,7 @@ static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp)
if (fread(zentry, 1, sizeof(zentry_t), handle) < sizeof(zentry_t)) if (fread(zentry, 1, sizeof(zentry_t), handle) < sizeof(zentry_t))
{ {
CONS_Alert(CONS_ERROR, "Failed to read central directory (%s)\n", strerror(ferror(handle))); CONS_Alert(CONS_ERROR, "Failed to read central directory (%s)\n", M_FileError(handle));
Z_Free(lumpinfo); Z_Free(lumpinfo);
free(zentries); free(zentries);
return NULL; return NULL;
@ -602,7 +602,7 @@ static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp)
fullname = malloc(zentry->namelen + 1); fullname = malloc(zentry->namelen + 1);
if (fgets(fullname, zentry->namelen + 1, handle) != fullname) if (fgets(fullname, zentry->namelen + 1, handle) != fullname)
{ {
CONS_Alert(CONS_ERROR, "Unable to read lumpname (%s)\n", strerror(ferror(handle))); CONS_Alert(CONS_ERROR, "Unable to read lumpname (%s)\n", M_FileError(handle));
Z_Free(lumpinfo); Z_Free(lumpinfo);
free(zentries); free(zentries);
free(fullname); free(fullname);

View File

@ -371,6 +371,9 @@ void I_FinishUpdate(void)
if (cv_ticrate.value) if (cv_ticrate.value)
SCR_DisplayTicRate(); SCR_DisplayTicRate();
if (cv_showping.value && netgame && consoleplayer != serverplayer)
SCR_DisplayLocalPing();
// //
if (bDIBMode) if (bDIBMode)
{ {

View File

@ -399,10 +399,13 @@ void Y_IntermissionDrawer(void)
// draw the "got through act" lines and act number // draw the "got through act" lines and act number
V_DrawLevelTitle(data.coop.passedx1, 49, 0, data.coop.passed1); V_DrawLevelTitle(data.coop.passedx1, 49, 0, data.coop.passed1);
V_DrawLevelTitle(data.coop.passedx2, 49+V_LevelNameHeight(data.coop.passed2)+2, 0, data.coop.passed2); {
INT32 h = V_LevelNameHeight(data.coop.passed2);
V_DrawLevelTitle(data.coop.passedx2, 49+h+2, 0, data.coop.passed2);
if (data.coop.actnum) if (data.coop.actnum)
V_DrawLevelActNum(244, 57, 0, data.coop.actnum); V_DrawLevelActNum(244, 42+h, 0, data.coop.actnum);
}
bonusy = 150; bonusy = 150;
// Total // Total
@ -485,10 +488,10 @@ void Y_IntermissionDrawer(void)
if (drawsection == 1) if (drawsection == 1)
{ {
const char *ringtext = "\x82" "50 RINGS, NO SHIELD"; const char *ringtext = "\x82" "50 rings, no shield";
const char *tut1text = "\x82" "PRESS " "\x80" "SPIN"; const char *tut1text = "\x82" "press " "\x80" "spin";
const char *tut2text = "\x82" "MID-" "\x80" "JUMP"; const char *tut2text = "\x82" "mid-" "\x80" "jump";
ttheight = 16; ttheight = 8;
V_DrawLevelTitle(data.spec.passedx1 + xoffset1, ttheight, 0, data.spec.passed1); V_DrawLevelTitle(data.spec.passedx1 + xoffset1, ttheight, 0, data.spec.passed1);
ttheight += V_LevelNameHeight(data.spec.passed3) + 2; ttheight += V_LevelNameHeight(data.spec.passed3) + 2;
V_DrawLevelTitle(data.spec.passedx3 + xoffset2, ttheight, 0, data.spec.passed3); V_DrawLevelTitle(data.spec.passedx3 + xoffset2, ttheight, 0, data.spec.passed3);
@ -497,9 +500,9 @@ void Y_IntermissionDrawer(void)
ttheight = 108; ttheight = 108;
V_DrawLevelTitle(BASEVIDWIDTH/2 + xoffset4 - (V_LevelNameWidth(ringtext)/2), ttheight, 0, ringtext); V_DrawLevelTitle(BASEVIDWIDTH/2 + xoffset4 - (V_LevelNameWidth(ringtext)/2), ttheight, 0, ringtext);
ttheight += V_LevelNameHeight(ringtext) + 2;
V_DrawLevelTitle(BASEVIDWIDTH/2 + xoffset5 - (V_LevelNameWidth(tut1text)/2), ttheight, 0, tut1text);
ttheight += V_LevelNameHeight(tut1text) + 2; ttheight += V_LevelNameHeight(tut1text) + 2;
V_DrawLevelTitle(BASEVIDWIDTH/2 + xoffset5 - (V_LevelNameWidth(tut1text)/2), ttheight, 0, tut1text);
ttheight += V_LevelNameHeight(tut2text) + 2;
V_DrawLevelTitle(BASEVIDWIDTH/2 + xoffset6 - (V_LevelNameWidth(tut2text)/2), ttheight, 0, tut2text); V_DrawLevelTitle(BASEVIDWIDTH/2 + xoffset6 - (V_LevelNameWidth(tut2text)/2), ttheight, 0, tut2text);
} }
else else
@ -1384,21 +1387,21 @@ void Y_StartIntermission(void)
// too long so just show "YOU GOT THROUGH THE ACT" // too long so just show "YOU GOT THROUGH THE ACT"
if (strlen(skins[players[consoleplayer].skin].realname) > 13) if (strlen(skins[players[consoleplayer].skin].realname) > 13)
{ {
strcpy(data.coop.passed1, "YOU GOT"); strcpy(data.coop.passed1, "you got");
strcpy(data.coop.passed2, (mapheaderinfo[gamemap-1]->actnum) ? "THROUGH ACT" : "THROUGH THE ACT"); strcpy(data.coop.passed2, (mapheaderinfo[gamemap-1]->actnum) ? "through act" : "through the act");
} }
// long enough that "X GOT" won't fit so use "X PASSED THE ACT" // long enough that "X GOT" won't fit so use "X PASSED THE ACT"
else if (strlen(skins[players[consoleplayer].skin].realname) > 8) else if (strlen(skins[players[consoleplayer].skin].realname) > 8)
{ {
strcpy(data.coop.passed1, skins[players[consoleplayer].skin].realname); strcpy(data.coop.passed1, skins[players[consoleplayer].skin].realname);
strcpy(data.coop.passed2, (mapheaderinfo[gamemap-1]->actnum) ? "PASSED ACT" : "PASSED THE ACT"); strcpy(data.coop.passed2, (mapheaderinfo[gamemap-1]->actnum) ? "passed act" : "passed the act");
} }
// length is okay for normal use // length is okay for normal use
else else
{ {
snprintf(data.coop.passed1, sizeof data.coop.passed1, "%s GOT", snprintf(data.coop.passed1, sizeof data.coop.passed1, "%s got",
skins[players[consoleplayer].skin].realname); skins[players[consoleplayer].skin].realname);
strcpy(data.coop.passed2, (mapheaderinfo[gamemap-1]->actnum) ? "THROUGH ACT" : "THROUGH THE ACT"); strcpy(data.coop.passed2, (mapheaderinfo[gamemap-1]->actnum) ? "through act" : "through the act");
} }
// set X positions // set X positions
@ -1498,7 +1501,7 @@ void Y_StartIntermission(void)
// set up the "got through act" message according to skin name // set up the "got through act" message according to skin name
if (stagefailed) if (stagefailed)
{ {
strcpy(data.spec.passed2, "SPECIAL STAGE"); strcpy(data.spec.passed2, "Special Stage");
data.spec.passed1[0] = '\0'; data.spec.passed1[0] = '\0';
} }
else if (ALL7EMERALDS(emeralds)) else if (ALL7EMERALDS(emeralds))
@ -1507,13 +1510,13 @@ void Y_StartIntermission(void)
sizeof data.spec.passed1, "%s", sizeof data.spec.passed1, "%s",
skins[players[consoleplayer].skin].realname); skins[players[consoleplayer].skin].realname);
data.spec.passed1[sizeof data.spec.passed1 - 1] = '\0'; data.spec.passed1[sizeof data.spec.passed1 - 1] = '\0';
strcpy(data.spec.passed2, "GOT THEM ALL!"); strcpy(data.spec.passed2, "got them all!");
if (players[consoleplayer].charflags & SF_SUPER) if (players[consoleplayer].charflags & SF_SUPER)
{ {
strcpy(data.spec.passed3, "CAN NOW BECOME"); strcpy(data.spec.passed3, "can now become");
snprintf(data.spec.passed4, snprintf(data.spec.passed4,
sizeof data.spec.passed4, "SUPER %s", sizeof data.spec.passed4, "Super %s",
skins[players[consoleplayer].skin].realname); skins[players[consoleplayer].skin].realname);
data.spec.passed4[sizeof data.spec.passed4 - 1] = '\0'; data.spec.passed4[sizeof data.spec.passed4 - 1] = '\0';
} }
@ -1523,13 +1526,13 @@ void Y_StartIntermission(void)
if (strlen(skins[players[consoleplayer].skin].realname) <= SKINNAMESIZE-5) if (strlen(skins[players[consoleplayer].skin].realname) <= SKINNAMESIZE-5)
{ {
snprintf(data.spec.passed1, snprintf(data.spec.passed1,
sizeof data.spec.passed1, "%s GOT", sizeof data.spec.passed1, "%s got",
skins[players[consoleplayer].skin].realname); skins[players[consoleplayer].skin].realname);
data.spec.passed1[sizeof data.spec.passed1 - 1] = '\0'; data.spec.passed1[sizeof data.spec.passed1 - 1] = '\0';
} }
else else
strcpy(data.spec.passed1, "YOU GOT"); strcpy(data.spec.passed1, "You got");
strcpy(data.spec.passed2, "A CHAOS EMERALD"); strcpy(data.spec.passed2, "a Chaos Emerald");
if (P_GetNextEmerald() > 6) if (P_GetNextEmerald() > 6)
{ {
data.spec.passed2[15] = '?'; data.spec.passed2[15] = '?';