diff --git a/src/d_clisrv.c b/src/d_clisrv.c index a92619a34..aca37df1d 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -90,6 +90,7 @@ SINT8 nodetoplayer[MAXNETNODES]; SINT8 nodetoplayer2[MAXNETNODES]; // say the numplayer for this node if any (splitscreen) UINT8 playerpernode[MAXNETNODES]; // used specialy for scplitscreen 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 supposedtics[MAXNETNODES]; // nettics prevision for smaller packet 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->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->y = LONG(players[i].mo->y); 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. P_UnsetThingPosition(players[i].mo); 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->flags = LONG(rsp->flags); players[i].mo->flags2 = LONG(rsp->flags2); @@ -2588,9 +2597,13 @@ static void Command_Nodes(void) if (playeringame[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) - CONS_Printf(" - %s", address); + + if (playernode[i] != UINT8_MAX) + { + CONS_Printf(" - node %.2d", playernode[i]); + if (I_GetNodeAddress && (address = I_GetNodeAddress(playernode[i])) != NULL) + CONS_Printf(" - %s", address); + } if (IsPlayerAdmin(i)) CONS_Printf(M_GetText(" (verified admin)")); @@ -3221,10 +3234,10 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum) { const char *address; 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 - 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') @@ -4204,10 +4217,12 @@ static void HandlePacketFromPlayer(SINT8 node) //Update client ping table from the server. if (client) { - INT32 i; + UINT8 i; for (i = 0; i < MAXPLAYERS; i++) if (playeringame[i]) playerpingtable[i] = (tic_t)netbuffer->u.pingtable[i]; + + servermaxping = (tic_t)netbuffer->u.pingtable[MAXPLAYERS]; } 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) { INT32 i; @@ -4749,6 +4772,8 @@ static inline void PingUpdate(void) laggers[i] = true; numlaggers++; } + else + pingtimeout[i] = 0; } //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]) { - 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; - buf[1] = KICK_MSG_PING_HIGH; - SendNetXCmd(XD_KICK, &buf, 2); + pingtimeout[i] = 0; + + 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. } + // 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 for (i = 0; i < MAXNETNODES; i++) if (nodeingame[i]) - HSendPacket(i, true, 0, sizeof(INT32) * MAXPLAYERS); + HSendPacket(i, true, 0, sizeof(INT32) * (MAXPLAYERS+1)); pingmeasurecount = 1; //Reset count } @@ -4812,7 +4855,7 @@ void NetUpdate(void) if (server) { - if (netgame && !(gametime % 255)) + if (netgame && !(gametime % 35)) // update once per second. PingUpdate(); // update node latency values so we can take an average later. for (i = 0; i < MAXPLAYERS; i++) diff --git a/src/d_clisrv.h b/src/d_clisrv.h index d7c210895..7313c7355 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -255,6 +255,7 @@ typedef struct INT32 health; angle_t angle; + angle_t rollangle; fixed_t x; fixed_t y; fixed_t z; @@ -423,9 +424,9 @@ typedef struct serverrefuse_pak serverrefuse; // 65025 bytes (somehow I feel like those values are garbage...) askinfo_pak askinfo; // 61 bytes msaskinfo_pak msaskinfo; // 22 bytes - plrinfo playerinfo[MAXPLAYERS]; // 1152 bytes (I'd say 36~38) - plrconfig playerconfig[MAXPLAYERS]; // (up to) 896 bytes (welp they ARE) - UINT32 pingtable[MAXPLAYERS]; // 128 bytes + plrinfo playerinfo[MAXPLAYERS]; // 576 bytes(?) + plrconfig playerconfig[MAXPLAYERS]; // (up to) 528 bytes(?) + UINT32 pingtable[MAXPLAYERS+1]; // 68 bytes } u; // This is needed to pack diff packet types data together } ATTRPACK doomdata_t; @@ -487,6 +488,7 @@ extern tic_t jointimeout; extern UINT16 pingmeasurecount; extern UINT32 realpingtable[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; diff --git a/src/d_main.c b/src/d_main.c index 011e38e2a..e48b26ba8 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -180,6 +180,9 @@ void D_ProcessEvents(void) if (M_ScreenshotResponder(ev)) continue; // ate the event + if (WipeStageTitle) + continue; + if (gameaction == ga_nothing && gamestate == GS_TITLESCREEN) { if (cht_Responder(ev)) @@ -441,6 +444,17 @@ static void D_Display(void) if (rendermode != render_none) { 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); } @@ -742,14 +756,6 @@ void D_StartTitle(void) // empty maptol so mario/etc sounds don't play in sound test when they shouldn't maptol = 0; - // reset to default player stuff - COM_BufAddText (va("%s \"%s\"\n",cv_playername.name,cv_defaultplayername.string)); - COM_BufAddText (va("%s \"%s\"\n",cv_skin.name,cv_defaultskin.string)); - COM_BufAddText (va("%s \"%s\"\n",cv_playercolor.name,cv_defaultplayercolor.string)); - COM_BufAddText (va("%s \"%s\"\n",cv_playername2.name,cv_defaultplayername2.string)); - COM_BufAddText (va("%s \"%s\"\n",cv_skin2.name,cv_defaultskin2.string)); - COM_BufAddText (va("%s \"%s\"\n",cv_playercolor2.name,cv_defaultplayercolor2.string)); - gameaction = ga_nothing; displayplayer = consoleplayer = 0; gametype = GT_COOP; diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 14746265f..4de166e41 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -87,6 +87,7 @@ static void JoinTimeout_OnChange(void); static void CoopStarposts_OnChange(void); static void CoopLives_OnChange(void); +static void ExitMove_OnChange(void); static void Ringslinger_OnChange(void); static void Gravity_OnChange(void); @@ -223,8 +224,8 @@ consvar_t cv_allowseenames = {"allowseenames", "Yes", CV_NETVAR, CV_YesNo, NULL, #endif // names -consvar_t cv_playername = {"name", "Sonic", CV_CALL|CV_NOINIT, NULL, Name_OnChange, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_playername2 = {"name2", "Tails", CV_CALL|CV_NOINIT, NULL, Name2_OnChange, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_playername = {"name", "Sonic", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Name_OnChange, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_playername2 = {"name2", "Tails", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Name2_OnChange, 0, NULL, NULL, 0, 0, NULL}; // player colors consvar_t cv_playercolor = {"color", "Blue", CV_CALL|CV_NOINIT, Color_cons_t, Color_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_playercolor2 = {"color2", "Orange", CV_CALL|CV_NOINIT, Color_cons_t, Color2_OnChange, 0, NULL, NULL, 0, 0, NULL}; @@ -233,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}; // saved versions of the above six -consvar_t cv_defaultplayername = {"defaultname", "Sonic", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_defaultplayername2 = {"defaultname2", "Tails", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_defaultplayercolor = {"defaultcolor", "Blue", CV_SAVE, Color_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_defaultplayercolor2 = {"defaultcolor2", "Orange", CV_SAVE, Color_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_defaultskin = {"defaultskin", DEFAULTSKIN, CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -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}}; 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}; + +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 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}; @@ -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}}; 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}}; 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_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_advancemap); CV_RegisterVar(&cv_playersforexit); + CV_RegisterVar(&cv_exitmove); CV_RegisterVar(&cv_timelimit); CV_RegisterVar(&cv_playbackspeed); CV_RegisterVar(&cv_forceskin); @@ -579,6 +590,8 @@ void D_RegisterServerCommands(void) CV_RegisterVar(&cv_skipmapcheck); CV_RegisterVar(&cv_sleep); CV_RegisterVar(&cv_maxping); + CV_RegisterVar(&cv_pingtimeout); + CV_RegisterVar(&cv_showping); #ifdef SEENAMES CV_RegisterVar(&cv_allowseenames); @@ -670,10 +683,8 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_playercolor2); CV_RegisterVar(&cv_skin2); // saved versions of the above six - CV_RegisterVar(&cv_defaultplayername); CV_RegisterVar(&cv_defaultplayercolor); CV_RegisterVar(&cv_defaultskin); - CV_RegisterVar(&cv_defaultplayername2); CV_RegisterVar(&cv_defaultplayercolor2); CV_RegisterVar(&cv_defaultskin2); @@ -3007,7 +3018,7 @@ static void Command_Verify_f(void) if (COM_Argc() != 2) { - CONS_Printf(M_GetText("promote : give admin privileges to a node\n")); + CONS_Printf(M_GetText("promote : give admin privileges to a player\n")); return; } @@ -3063,7 +3074,7 @@ static void Command_RemoveAdmin_f(void) if (COM_Argc() != 2) { - CONS_Printf(M_GetText("demote : remove admin privileges from a node\n")); + CONS_Printf(M_GetText("demote : remove admin privileges from a player\n")); 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; /** Deals with a timelimit change by printing the change to the console. diff --git a/src/d_netcmd.h b/src/d_netcmd.h index 0b538890e..c2e6f980d 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -26,10 +26,8 @@ extern consvar_t cv_playername2; extern consvar_t cv_playercolor2; extern consvar_t cv_skin2; // saved versions of the above six -extern consvar_t cv_defaultplayername; extern consvar_t cv_defaultplayercolor; extern consvar_t cv_defaultskin; -extern consvar_t cv_defaultplayername2; extern consvar_t cv_defaultplayercolor2; extern consvar_t cv_defaultskin2; @@ -96,7 +94,7 @@ extern consvar_t cv_recycler; 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_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_maxping; +extern consvar_t cv_pingtimeout; +extern consvar_t cv_showping; + extern consvar_t cv_skipmapcheck; diff --git a/src/d_netfil.c b/src/d_netfil.c index 5e7f59310..bd7089609 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -716,7 +716,7 @@ void SV_FileSendTicker(void) if (ram) M_Memcpy(p->data, &f->id.ram[transfer[i].position], 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); // Put flag so receiver knows the total 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 fseek(file->file, pos, SEEK_SET); 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; // Finished? diff --git a/src/d_player.h b/src/d_player.h index d3f84d0e6..6d0c5f5d1 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -151,6 +151,7 @@ typedef enum /*** misc ***/ PF_FORCESTRAFE = 1<<28, // Turning inputs are translated into strafing inputs 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 } pflags_t; diff --git a/src/dehacked.c b/src/dehacked.c index fff9dbee8..be897b952 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -1201,6 +1201,14 @@ static void readlevelheader(MYFILE *f, INT32 num) word2 = tmp += 2; 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 if (fastcmp(word, "SUBTITLE")) { @@ -1344,12 +1352,6 @@ static void readlevelheader(MYFILE *f, INT32 num) } // 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")) { deh_strlcpy(mapheaderinfo[num-1]->selectheading, word2, @@ -1573,6 +1575,20 @@ static void readlevelheader(MYFILE *f, INT32 num) else 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 else if (fastcmp(word, "HIDDEN")) @@ -5343,6 +5359,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_FSGNA", "S_FSGNB", "S_FSGNC", + "S_FSGND", // Black Eggman (Boss 7) "S_BLACKEGG_STND", @@ -7322,13 +7339,9 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_FIREFLOWER2", "S_FIREFLOWER3", "S_FIREFLOWER4", - "S_FIREBALL1", - "S_FIREBALL2", - "S_FIREBALL3", - "S_FIREBALL4", - "S_FIREBALLEXP1", - "S_FIREBALLEXP2", - "S_FIREBALLEXP3", + "S_FIREBALL", + "S_FIREBALLTRAIL1", + "S_FIREBALLTRAIL2", "S_SHELL", "S_PUMA_START1", "S_PUMA_START2", @@ -7497,6 +7510,9 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_POPHAT_SHOOT1", "S_POPHAT_SHOOT2", "S_POPHAT_SHOOT3", + "S_POPHAT_SHOOT4", + "S_POPSHOT", + "S_POPSHOT_TRAIL", "S_HIVEELEMENTAL_LOOK", "S_HIVEELEMENTAL_PREPARE1", @@ -8317,6 +8333,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_BLUEGOOMBA", "MT_FIREFLOWER", "MT_FIREBALL", + "MT_FIREBALLTRAIL", "MT_SHELL", "MT_PUMA", "MT_PUMATRAIL", @@ -8361,6 +8378,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_PENGUINATOR", "MT_POPHAT", "MT_POPSHOT", + "MT_POPSHOT_TRAIL", "MT_HIVEELEMENTAL", "MT_BUMBLEBORE", @@ -8570,6 +8588,7 @@ static const char *const PLAYERFLAG_LIST[] = { /*** misc ***/ "FORCESTRAFE", // Translate turn inputs into strafe inputs "CANCARRY", // Can carry? + "FINISHED", NULL // stop loop here. }; @@ -9012,6 +9031,8 @@ struct { {"LF_NOZONE",LF_NOZONE}, {"LF_SAVEGAME",LF_SAVEGAME}, {"LF_MIXNIGHTSCOUNTDOWN",LF_MIXNIGHTSCOUNTDOWN}, + {"LF_NOTITLECARD",LF_NOTITLECARD}, + {"LF_WARNINGTITLE",LF_WARNINGTITLE}, // And map flags {"LF2_HIDEINMENU",LF2_HIDEINMENU}, {"LF2_HIDEINSTATS",LF2_HIDEINSTATS}, diff --git a/src/djgppdos/i_video.c b/src/djgppdos/i_video.c index 6a7641174..56570b7bf 100644 --- a/src/djgppdos/i_video.c +++ b/src/djgppdos/i_video.c @@ -98,6 +98,9 @@ void I_FinishUpdate (void) if (cv_ticrate.value) SCR_DisplayTicRate(); + if (cv_showping.value && netgame && consoleplayer != serverplayer) + SCR_DisplayLocalPing(); + //blast it to the screen // this code sucks //memcpy(dascreen,screens[0],screenwidth*screenheight); diff --git a/src/doomstat.h b/src/doomstat.h index 7d06f03e2..84939a8db 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -349,6 +349,8 @@ typedef struct #define LF_NOZONE 16 ///< Don't include "ZONE" on level title #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_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_HIDEINSTATS 2 ///< Hide in the statistics screen diff --git a/src/f_finale.c b/src/f_finale.c index b39a4444f..e3809ea25 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1389,10 +1389,13 @@ void F_StartGameEvaluation(void) // Credits option in secrets menu if (cursaveslot == -1) { + S_FadeOutStopMusic(2*MUSICRATE); F_StartGameEnd(); return; } + S_FadeOutStopMusic(5*MUSICRATE); + G_SetGamestate(GS_EVALUATION); // Just in case they're open ... somehow @@ -1639,7 +1642,7 @@ void F_StartEnding(void) gameaction = ga_nothing; paused = false; CON_ToggleOff(); - S_StopMusic(); // todo: placeholder + S_StopMusic(); S_StopSounds(); finalecount = -10; // what? this totally isn't a hack. why are you asking? @@ -1720,6 +1723,9 @@ void F_EndingTicker(void) return; } + if (finalecount == -8) + S_ChangeMusicInternal((goodending ? "_endg" : "_endb"), false); + if (goodending && finalecount == INFLECTIONPOINT) // time to swap some assets { endegrk[0] = W_CachePatchName("ENDEGRK2", PU_LEVEL); @@ -2149,7 +2155,6 @@ void F_StartGameEnd(void) gameaction = ga_nothing; paused = false; CON_ToggleOff(); - S_StopMusic(); S_StopSounds(); // In case menus are still up?!! @@ -2592,6 +2597,10 @@ void F_TitleScreenDrawer(void) if (gamestate != GS_TITLESCREEN && gamestate != GS_WAITINGPLAYERS) 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? hidepics = curhidepics; if (hidepics) diff --git a/src/f_finale.h b/src/f_finale.h index d28ed0b01..82a7e1408 100644 --- a/src/f_finale.h +++ b/src/f_finale.h @@ -142,7 +142,7 @@ void F_MenuPresTicker(boolean run); extern boolean WipeInAction; extern boolean WipeInLevel; -extern INT32 lastwipetic; +extern boolean WipeStageTitle; typedef enum { @@ -167,6 +167,11 @@ extern wipestyleflags_t wipestyleflags; #define FADEBLUEFACTOR 10 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_WipeEndScreen(void); diff --git a/src/f_wipe.c b/src/f_wipe.c index 8e767932f..ad0e89c13 100644 --- a/src/f_wipe.c +++ b/src/f_wipe.c @@ -19,6 +19,7 @@ #include "r_draw.h" // transtable #include "p_pspr.h" // tr_transxxx #include "p_local.h" +#include "st_stuff.h" #include "w_wad.h" #include "z_zone.h" @@ -30,7 +31,6 @@ #include "m_misc.h" // movie mode #include "doomstat.h" -#include "st_stuff.h" #ifdef HAVE_BLUA #include "lua_hud.h" // level title @@ -92,6 +92,7 @@ UINT8 wipedefs[NUMWIPEDEFS] = { boolean WipeInAction = false; boolean WipeInLevel = false; +boolean WipeStageTitle = false; INT32 lastwipetic = 0; wipestyle_t wipestyle = WIPESTYLE_NORMAL; @@ -193,22 +194,14 @@ static fademask_t *F_GetFadeMask(UINT8 masknum, UINT8 scrnnum) { */ void F_WipeStageTitle(void) { - if (wipestyle == WIPESTYLE_LEVEL - && (!titlemapinaction) - && (wipestyleflags & WSF_FADEIN) - && *mapheaderinfo[gamemap-1]->lvlttl != '\0' -#ifdef HAVE_BLUA - && LUA_HudEnabled(hud_stagetitle) -#endif - ) + // draw level title + if ((WipeStageTitle && st_overlay) + && (wipestyle == WIPESTYLE_LEVEL) + && !(mapheaderinfo[gamemap-1]->levelflags & LF_NOTITLECARD) + && *mapheaderinfo[gamemap-1]->lvlttl != '\0') { - stplyr = &players[consoleplayer]; - ST_drawLevelTitle(TICRATE); - if (splitscreen) - { - stplyr = &players[secondarydisplayplayer]; - ST_drawLevelTitle(TICRATE); - } + ST_runTitleCard(); + ST_drawWipeTitleCard(); } } @@ -457,6 +450,15 @@ void F_RunWipe(UINT8 wipetype, boolean drawMenu) #endif 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_UpdateNoBlit(); @@ -468,8 +470,10 @@ void F_RunWipe(UINT8 wipetype, boolean drawMenu) if (moviemode) M_SaveFrame(); } + WipeInAction = false; WipeInLevel = false; + WipeStageTitle = false; #endif } @@ -497,6 +501,7 @@ void F_WipeTicker(void) // stop WipeInAction = false; WipeInLevel = false; + WipeStageTitle = false; return; } @@ -508,6 +513,7 @@ void F_WipeTicker(void) #endif F_DoWipe(fmask); #endif + WipeStageTitle = false; #endif } diff --git a/src/g_game.c b/src/g_game.c index 63caaa15c..5e1645901 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -47,6 +47,10 @@ #include "m_cond.h" // condition sets #include "md5.h" // demo checksums +#ifdef HAVE_BLUA +#include "lua_hud.h" +#endif + gameaction_t gameaction; gamestate_t gamestate = GS_NULL; UINT8 ultimatemode = false; @@ -1703,6 +1707,61 @@ void G_DoLoadLevel(boolean resetplayer) 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; boolean pausebreakkey = false; static INT32 camtoggledelay, camtoggledelay2 = 0; @@ -1992,7 +2051,7 @@ void G_Ticker(boolean run) if (titledemo) F_TitleDemoTicker(); P_Ticker(run); // tic the game - ST_Ticker(); + ST_Ticker(run); F_TextPromptTicker(); AM_Ticker(); HU_Ticker(); @@ -2833,6 +2892,31 @@ void G_AddPlayer(INT32 playernum) 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) { if (gamestate == GS_LEVEL) @@ -4031,7 +4115,7 @@ char *G_BuildMapTitle(INT32 mapnum) len += strlen(mapheaderinfo[mapnum-1]->lvlttl); if (!(mapheaderinfo[mapnum-1]->levelflags & LF_NOZONE)) { - zonetext = M_GetText("ZONE"); + zonetext = M_GetText("Zone"); len += strlen(zonetext) + 1; // ' ' + zonetext } if (actnum > 0) @@ -5194,7 +5278,10 @@ void G_ReadMetalTic(mobj_t *metal) { // But wait, there's more! xziptic = READUINT8(metal_p); if (xziptic & EZT_FLIP) + { metal->eflags ^= MFE_VERTICALFLIP; + metal->flags2 ^= MF2_OBJECTFLIP; + } if (xziptic & EZT_SCALE) { metal->destscale = READFIXED(metal_p); diff --git a/src/g_game.h b/src/g_game.h index 2489ff097..87232c823 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -140,7 +140,8 @@ void G_SpawnPlayer(INT32 playernum, boolean starpost); void G_DeferedInitNew(boolean pultmode, const char *mapname, INT32 pickedchar, boolean SSSG, boolean FLS); void G_DoLoadLevel(boolean resetplayer); - +void G_StartTitleCard(void); +void G_PreLevelTitleCard(tic_t ticker, boolean update); void G_DeferedPlayDemo(const char *demo); // 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_PlatformGametype(void); boolean G_TagGametype(void); +boolean G_EnoughPlayersFinished(void); void G_ExitLevel(void); void G_NextLevel(void); void G_Continue(void); diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index e493dafac..4519e1280 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -380,9 +380,9 @@ void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t { FSurfaceInfo Surf; 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]; - else if (alphalevel == 14) Surf.FlatColor.s.alpha = softwaretranstogl[cv_translucenthud.value]; - else if (alphalevel == 15) Surf.FlatColor.s.alpha = softwaretranstogl_hi[cv_translucenthud.value]; + if (alphalevel == 13) Surf.FlatColor.s.alpha = softwaretranstogl_lo[st_translucency]; + else if (alphalevel == 14) Surf.FlatColor.s.alpha = softwaretranstogl[st_translucency]; + else if (alphalevel == 15) Surf.FlatColor.s.alpha = softwaretranstogl_hi[st_translucency]; else Surf.FlatColor.s.alpha = softwaretranstogl[10-alphalevel]; flags |= PF_Modulated; 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; 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]; - else if (alphalevel == 14) Surf.FlatColor.s.alpha = softwaretranstogl[cv_translucenthud.value]; - else if (alphalevel == 15) Surf.FlatColor.s.alpha = softwaretranstogl_hi[cv_translucenthud.value]; + if (alphalevel == 13) Surf.FlatColor.s.alpha = softwaretranstogl_lo[st_translucency]; + else if (alphalevel == 14) Surf.FlatColor.s.alpha = softwaretranstogl[st_translucency]; + else if (alphalevel == 15) Surf.FlatColor.s.alpha = softwaretranstogl_hi[st_translucency]; else Surf.FlatColor.s.alpha = softwaretranstogl[10-alphalevel]; flags |= PF_Modulated; HWD.pfnDrawPolygon(&Surf, v, 4, flags); diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 52bdbcf5a..263344ebe 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -4068,6 +4068,7 @@ static gr_vissprite_t *HWR_NewVisSprite(void) return HWR_GetVisSprite(gr_visspritecount++); } +#ifdef GLBADSHADOWS // 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) { @@ -4098,6 +4099,7 @@ static fixed_t HWR_OpaqueFloorAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t hei return floorz; } +#endif //#ifdef GLBADSHADOWS // // HWR_DoCulling @@ -4139,6 +4141,7 @@ static boolean HWR_DoCulling(line_t *cullheight, line_t *viewcullheight, float v return false; } +#ifdef GLBADSHADOWS static void HWR_DrawSpriteShadow(gr_vissprite_t *spr, GLPatch_t *gpatch, float this_scale) { 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); } } +#endif //#ifdef GLBADSHADOWS // This is expecting a pointer to an array containing 4 wallVerts for a sprite 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 HWR_GetMappedPatch(gpatch, spr->colormap); +#ifdef GLBADSHADOWS // Draw shadow BEFORE sprite 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. @@ -4401,6 +4406,7 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) //////////////////// HWR_DrawSpriteShadow(spr, gpatch, this_scale); } +#endif //#ifdef GLBADSHADOWS baseWallVerts[0].x = baseWallVerts[3].x = spr->x1; 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 HWR_GetMappedPatch(gpatch, spr->colormap); +#ifdef GLBADSHADOWS // Draw shadow BEFORE sprite 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. @@ -4803,6 +4810,7 @@ static void HWR_DrawSprite(gr_vissprite_t *spr) //////////////////// HWR_DrawSpriteShadow(spr, gpatch, this_scale); } +#endif //#ifdef GLBADSHADOWS // if it has a dispoffset, push it a little towards the camera if (spr->dispoffset) { diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 428656bf2..afca4c773 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -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 { - // 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: const char *newmsg; - char *nodenum = (char*) malloc(3); - INT32 spc = 1; // used if nodenum[1] is a space. + char *playernum = (char*) malloc(3); + 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" - 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 - if (nodenum[1] == ' ') + // check if playernum[1] is a space + if (playernum[1] == ' ') spc = 0; // let it slide else { - HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm \'.", false); - free(nodenum); + HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm \'.", false); + free(playernum); return; } } @@ -524,14 +524,14 @@ static void DoSayCommand(SINT8 target, size_t usedargs, UINT8 flags) { if (msg[5] != ' ') { - HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm \'.", false); - free(nodenum); + HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm \'.", false); + free(playernum); return; } } - target = atoi((const char*) nodenum); // turn that into a number - free(nodenum); + target = atoi((const char*) playernum); // turn that into a number + free(playernum); //CONS_Printf("%d\n", target); // 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 // -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 barcolor = 35; // color we use for the bars (green, yellow or red) SINT8 i = 0; 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) { @@ -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. - 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 { - 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) - 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; } @@ -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 (!(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 // 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); } - 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); if (gametype == GT_RACE) @@ -2578,7 +2579,7 @@ static void HU_Draw32TeamTabRankings(playersort_t *tab, INT32 whiteplayer) if (!splitscreen) { 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 //V_DrawSmallString(x+ 129, y+4, V_YELLOWMAP, "HOST"); } @@ -2702,7 +2703,7 @@ void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer) if (!splitscreen) { 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 // 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); 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 // 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) 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); // 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 (!(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 // V_DrawSmallString(x+ 129, y+4, V_YELLOWMAP, "HOST"); } diff --git a/src/hu_stuff.h b/src/hu_stuff.h index 55b61d4b7..47419d29a 100644 --- a/src/hu_stuff.h +++ b/src/hu_stuff.h @@ -28,7 +28,7 @@ // Level title font #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 CRED_FONTSTART '!' // the first font character @@ -113,7 +113,7 @@ void HU_Drawer(void); char HU_dequeueChatChar(void); void HU_Erase(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_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer); void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, INT32 whiteplayer); diff --git a/src/info.c b/src/info.c index ed29fe2bf..b88d02932 100644 --- a/src/info.c +++ b/src/info.c @@ -1487,6 +1487,7 @@ state_t states[NUMSTATES] = {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, 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) {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 // Thrown Mario Fireball - {SPR_FBLL, FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_FIREBALL2}, // S_FIREBALL1 - {SPR_FBLL, FF_FULLBRIGHT|1, 3, {NULL}, 0, 0, S_FIREBALL3}, // S_FIREBALL2 - {SPR_FBLL, FF_FULLBRIGHT|2, 3, {NULL}, 0, 0, S_FIREBALL4}, // S_FIREBALL3 - {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 + {SPR_FBLL, FF_FULLBRIGHT, 1, {A_SpawnObjectRelative}, 0, MT_FIREBALLTRAIL, S_FIREBALL}, // S_FIREBALL + {SPR_FBLL, 1|FF_FULLBRIGHT|FF_TRANS50, 1, {A_SetScale}, FRACUNIT*3/4, 0, S_FIREBALLTRAIL2}, // S_FIREBALLTRAIL1 + {SPR_FBLL, 1|FF_FULLBRIGHT|FF_TRANS50, 8, {A_SetScale}, FRACUNIT/6, 1, S_NULL}, // S_FIREBALLTRAIL2 // Turtle 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_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, 2, 1, {NULL}, 0, 0, S_POPHAT_SHOOT3}, // S_POPHAT_SHOOT2 - {SPR_POPH, 0, 57, {NULL}, 0, 0, S_POPHAT_LOOK}, // S_POPHAT_SHOOT3 + {SPR_POPH, 1, 0, {A_MultiShotDist}, (MT_SPINDUST<<16)|4, 24, S_POPHAT_SHOOT2}, // S_POPHAT_SHOOT1 + {SPR_POPH, 1, 2, {A_LobShot}, MT_POPSHOT, (70<<16)|60, S_POPHAT_SHOOT3}, // S_POPHAT_SHOOT2 + {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, 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, // missilestate S_FSGNC, // deathstate - S_NULL, // xdeathstate + S_FSGND, // xdeathstate sfx_None, // deathsound 0, // speed - 124*FRACUNIT, // radius - 640*FRACUNIT, // height + 74*FRACUNIT, // radius + 320*FRACUNIT, // height 0, // display offset 0, // mass 0, // damage @@ -18910,31 +18910,58 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = { // MT_FIREBALL -1, // doomednum - S_FIREBALL1, // spawnstate + S_FIREBALL, // spawnstate 1000, // spawnhealth - S_FIREBALLEXP1, // seestate + S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound - S_FIREBALLEXP1, // meleestate - S_FIREBALLEXP1, // missilestate - S_FIREBALLEXP1, // deathstate - S_FIREBALLEXP1, // xdeathstate - sfx_mario1, // deathsound - 10*FRACUNIT, // speed + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 40*FRACUNIT, // speed 4*FRACUNIT, // radius 8*FRACUNIT, // height 0, // display offset DMG_FIRE, // mass 1, // damage sfx_None, // activesound - MF_NOBLOCKMAP|MF_FIRE|MF_MISSILE, // flags + MF_FIRE|MF_BOUNCE|MF_MISSILE, // flags 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 1804, // doomednum S_SHELL, // spawnstate @@ -19989,10 +20016,10 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = { // MT_POPSHOT -1, // doomednum - S_ROCKCRUMBLEI, // spawnstate + S_POPSHOT, // spawnstate 1, // spawnhealth S_NULL, // seestate - sfx_cannon, // seesound + sfx_kc4c, // seesound 0, // reactiontime sfx_None, // attacksound S_NULL, // painstate @@ -20000,9 +20027,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate - S_XPLD1, // deathstate + S_SONIC3KBOSSEXPLOSION1, // deathstate S_NULL, // xdeathstate - sfx_pop, // deathsound + sfx_cybdth, // deathsound 0, // speed 16*FRACUNIT, // radius 32*FRACUNIT, // height @@ -20014,6 +20041,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 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 127, // doomednum S_HIVEELEMENTAL_LOOK, // spawnstate diff --git a/src/info.h b/src/info.h index bbb6a21fc..fd9c45a1a 100644 --- a/src/info.h +++ b/src/info.h @@ -1657,6 +1657,7 @@ typedef enum state S_FSGNA, S_FSGNB, S_FSGNC, + S_FSGND, // Black Eggman (Boss 7) S_BLACKEGG_STND, @@ -3637,13 +3638,9 @@ typedef enum state S_FIREFLOWER2, S_FIREFLOWER3, S_FIREFLOWER4, - S_FIREBALL1, - S_FIREBALL2, - S_FIREBALL3, - S_FIREBALL4, - S_FIREBALLEXP1, - S_FIREBALLEXP2, - S_FIREBALLEXP3, + S_FIREBALL, + S_FIREBALLTRAIL1, + S_FIREBALLTRAIL2, S_SHELL, S_PUMA_START1, S_PUMA_START2, @@ -3812,6 +3809,9 @@ typedef enum state S_POPHAT_SHOOT1, S_POPHAT_SHOOT2, S_POPHAT_SHOOT3, + S_POPHAT_SHOOT4, + S_POPSHOT, + S_POPSHOT_TRAIL, S_HIVEELEMENTAL_LOOK, S_HIVEELEMENTAL_PREPARE1, @@ -4654,6 +4654,7 @@ typedef enum mobj_type MT_BLUEGOOMBA, MT_FIREFLOWER, MT_FIREBALL, + MT_FIREBALLTRAIL, MT_SHELL, MT_PUMA, MT_PUMATRAIL, @@ -4698,6 +4699,7 @@ typedef enum mobj_type MT_PENGUINATOR, MT_POPHAT, MT_POPSHOT, + MT_POPSHOT_TRAIL, MT_HIVEELEMENTAL, MT_BUMBLEBORE, diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 2e14b3f26..03f1aff18 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -1165,6 +1165,17 @@ static int lib_pElementalFire(lua_State *L) 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) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); @@ -2674,6 +2685,13 @@ static int lib_gSetCustomExitVars(lua_State *L) return 0; } +static int lib_gEnoughPlayersFinished(lua_State *L) +{ + INLEVEL + lua_pushboolean(L, G_EnoughPlayersFinished()); + return 1; +} + static int lib_gExitLevel(lua_State *L) { int n = lua_gettop(L); // Num arguments @@ -2869,6 +2887,7 @@ static luaL_Reg lib[] = { {"P_DoBubbleBounce",lib_pDoBubbleBounce}, {"P_BlackOw",lib_pBlackOw}, {"P_ElementalFire",lib_pElementalFire}, + {"P_DoPlayerFinish",lib_pDoPlayerFinish}, {"P_DoPlayerExit",lib_pDoPlayerExit}, {"P_InstaThrust",lib_pInstaThrust}, {"P_ReturnThrustX",lib_pReturnThrustX}, @@ -2981,6 +3000,7 @@ static luaL_Reg lib[] = { {"G_BuildMapName",lib_gBuildMapName}, {"G_DoReborn",lib_gDoReborn}, {"G_SetCustomExitVars",lib_gSetCustomExitVars}, + {"G_EnoughPlayersFinished",lib_gEnoughPlayersFinished}, {"G_ExitLevel",lib_gExitLevel}, {"G_IsSpecialStage",lib_gIsSpecialStage}, {"G_GametypeUsesLives",lib_gGametypeUsesLives}, diff --git a/src/lua_hud.h b/src/lua_hud.h index 7f928f7c4..d1adef7dc 100644 --- a/src/lua_hud.h +++ b/src/lua_hud.h @@ -43,3 +43,4 @@ boolean LUA_HudEnabled(enum hud option); void LUAh_GameHUD(player_t *stplyr); void LUAh_ScoresHUD(void); void LUAh_TitleHUD(void); +void LUAh_TitleCardHUD(player_t *stplyr); diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index 62be61283..9b12dd3c0 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -92,12 +92,14 @@ static const char *const patch_opt[] = { enum hudhook { hudhook_game = 0, hudhook_scores, - hudhook_title + hudhook_title, + hudhook_titlecard }; static const char *const hudhook_opt[] = { "game", "scores", "title", + "titlecard", NULL}; // alignment types for v.drawString @@ -910,9 +912,17 @@ static int libd_RandomChance(lua_State *L) 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 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 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}, {"renderer", libd_renderer}, {"localTransFlag", libd_getlocaltransflag}, + {"userTransFlag", libd_getusertransflag}, {NULL, NULL} }; @@ -1043,6 +1054,9 @@ int LUA_HudLib(lua_State *L) lua_newtable(L); 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"); luaL_newmetatable(L, META_HUDINFO); @@ -1180,4 +1194,38 @@ void LUAh_TitleHUD(void) hud_running = false; } +void LUAh_TitleCardHUD(player_t *stplayr) +{ + if (!gL || !(hudAvailable & (1<= 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]); return 1; } @@ -756,7 +756,7 @@ static int power_set(lua_State *L) powertype_t p = luaL_checkinteger(L, 2); UINT16 i = (UINT16)luaL_checkinteger(L, 3); 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) return luaL_error(L, "Do not alter player_t in HUD rendering code!"); powers[p] = i; diff --git a/src/m_argv.c b/src/m_argv.c index 117ec7833..bb43ad57c 100644 --- a/src/m_argv.c +++ b/src/m_argv.c @@ -16,6 +16,7 @@ #include "doomdef.h" #include "command.h" #include "m_argv.h" +#include "m_misc.h" /** \brief number of arg */ @@ -161,7 +162,7 @@ void M_FindResponseFile(void) if (!file) I_Error("No more free memory for the response file"); 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); // keep all the command line arguments following @responsefile diff --git a/src/m_fixed.h b/src/m_fixed.h index 370633c1f..08bc95884 100644 --- a/src/m_fixed.h +++ b/src/m_fixed.h @@ -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) { - const boolean n = x < 0; - x = abs(x); - while (x >= y) - x -= y; - if (n) - return -x; - else - return x; + return x % y; } /** \brief The FixedSqrt function diff --git a/src/m_menu.c b/src/m_menu.c index 28799a9c3..7a5aa8ae6 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1224,32 +1224,33 @@ static menuitem_t OP_VideoOptionsMenu[] = NULL, "HUD Transparency", &cv_translucenthud, 66}, {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, "Local ping display", &cv_showping, 81}, // shows ping next to framerate if we want to. #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 - {IT_HEADER, NULL, "Console", NULL, 90}, - {IT_STRING | IT_CVAR, NULL, "Background color", &cons_backcolor, 96}, - {IT_STRING | IT_CVAR, NULL, "Text Size", &cv_constextsize, 101}, + {IT_HEADER, NULL, "Console", NULL, 95}, + {IT_STRING | IT_CVAR, NULL, "Background color", &cons_backcolor, 101}, + {IT_STRING | IT_CVAR, NULL, "Text Size", &cv_constextsize, 106}, - {IT_HEADER, NULL, "Chat", NULL, 110}, - {IT_STRING | IT_CVAR, NULL, "Chat Mode", &cv_consolechat, 116}, - {IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Chat Box Width", &cv_chatwidth, 121}, - {IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Chat Box Height", &cv_chatheight, 126}, - {IT_STRING | IT_CVAR, NULL, "Message Fadeout Time", &cv_chattime, 131}, - {IT_STRING | IT_CVAR, NULL, "Chat Notifications", &cv_chatnotifications, 136}, - {IT_STRING | IT_CVAR, NULL, "Spam Protection", &cv_chatspamprotection, 141}, - {IT_STRING | IT_CVAR, NULL, "Chat background tint", &cv_chatbacktint, 146}, + {IT_HEADER, NULL, "Chat", NULL, 115}, + {IT_STRING | IT_CVAR, NULL, "Chat Mode", &cv_consolechat, 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, 131}, + {IT_STRING | IT_CVAR, NULL, "Message Fadeout Time", &cv_chattime, 136}, + {IT_STRING | IT_CVAR, NULL, "Chat Notifications", &cv_chatnotifications, 141}, + {IT_STRING | IT_CVAR, NULL, "Spam Protection", &cv_chatspamprotection, 146}, + {IT_STRING | IT_CVAR, NULL, "Chat background tint", &cv_chatbacktint, 151}, - {IT_HEADER, NULL, "Level", NULL, 155}, - {IT_STRING | IT_CVAR, NULL, "Draw Distance", &cv_drawdist, 161}, - {IT_STRING | IT_CVAR, NULL, "Weather Draw Dist.", &cv_drawdist_precip, 166}, - {IT_STRING | IT_CVAR, NULL, "NiGHTS Hoop Draw Dist.", &cv_drawdist_nights, 171}, + {IT_HEADER, NULL, "Level", NULL, 160}, + {IT_STRING | IT_CVAR, NULL, "Draw Distance", &cv_drawdist, 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, 176}, - {IT_HEADER, NULL, "Diagnostic", NULL, 180}, - {IT_STRING | IT_CVAR, NULL, "Show FPS", &cv_ticrate, 186}, - {IT_STRING | IT_CVAR, NULL, "Clear Before Redraw", &cv_homremoval, 191}, - {IT_STRING | IT_CVAR, NULL, "Show \"FOCUS LOST\"", &cv_showfocuslost, 196}, + {IT_HEADER, NULL, "Diagnostic", NULL, 184}, + {IT_STRING | IT_CVAR, NULL, "Show FPS", &cv_ticrate, 190}, + {IT_STRING | IT_CVAR, NULL, "Clear Before Redraw", &cv_homremoval, 195}, + {IT_STRING | IT_CVAR, NULL, "Show \"FOCUS LOST\"", &cv_showfocuslost, 200}, }; static menuitem_t OP_VideoModeMenu[] = @@ -7179,7 +7180,7 @@ static void M_DrawSoundTest(void) titl = va("%s - ", curplaying->title); } else - titl = "NONE - "; + titl = "None - "; i = V_LevelNameWidth(titl); @@ -7193,7 +7194,7 @@ static void M_DrawSoundTest(void) while (x > y) { x -= i; - V_DrawLevelTitle(x, 24, 0, titl); + V_DrawLevelTitle(x, 22, 0, titl); } if (curplaying) @@ -10472,7 +10473,6 @@ static consvar_t *setupm_cvcolor; static consvar_t *setupm_cvname; static consvar_t *setupm_cvdefaultskin; static consvar_t *setupm_cvdefaultcolor; -static consvar_t *setupm_cvdefaultname; static INT32 setupm_fakeskin; static INT32 setupm_fakecolor; @@ -10634,8 +10634,7 @@ colordraw: V_DrawString(x, y, ((R_SkinAvailable(setupm_cvdefaultskin->string) != setupm_fakeskin - || setupm_cvdefaultcolor->value != setupm_fakecolor - || strcmp(setupm_name, setupm_cvdefaultname->string)) + || setupm_cvdefaultcolor->value != setupm_fakecolor) ? 0 : V_TRANSLUCENT) | ((itemOn == 3) ? V_YELLOWMAP : 0), @@ -10690,14 +10689,12 @@ static void M_HandleSetupMultiPlayer(INT32 choice) case KEY_ENTER: if (itemOn == 3 && (R_SkinAvailable(setupm_cvdefaultskin->string) != setupm_fakeskin - || setupm_cvdefaultcolor->value != setupm_fakecolor - || strcmp(setupm_name, setupm_cvdefaultname->string))) + || setupm_cvdefaultcolor->value != setupm_fakecolor)) { S_StartSound(NULL,sfx_strpst); // you know what? always putting these in the buffer won't hurt anything. COM_BufAddText (va("%s \"%s\"\n",setupm_cvdefaultskin->name,skins[setupm_fakeskin].name)); COM_BufAddText (va("%s %d\n",setupm_cvdefaultcolor->name,setupm_fakecolor)); - COM_BufAddText (va("%s %s\n",setupm_cvdefaultname->name,setupm_name)); break; } /* FALLTHRU */ @@ -10796,7 +10793,6 @@ static void M_SetupMultiPlayer(INT32 choice) setupm_cvname = &cv_playername; setupm_cvdefaultskin = &cv_defaultskin; setupm_cvdefaultcolor = &cv_defaultplayercolor; - setupm_cvdefaultname = &cv_defaultplayername; // For whatever reason this doesn't work right if you just use ->value setupm_fakeskin = R_SkinAvailable(setupm_cvskin->string); @@ -10838,7 +10834,6 @@ static void M_SetupMultiPlayer2(INT32 choice) setupm_cvname = &cv_playername2; setupm_cvdefaultskin = &cv_defaultskin2; setupm_cvdefaultcolor = &cv_defaultplayercolor2; - setupm_cvdefaultname = &cv_defaultplayername2; // For whatever reason this doesn't work right if you just use ->value setupm_fakeskin = R_SkinAvailable(setupm_cvskin->string); diff --git a/src/m_misc.c b/src/m_misc.c index f7d5cf961..5cfb20f0f 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -23,6 +23,8 @@ #include #endif +#include + // Extended map support. #include @@ -521,6 +523,12 @@ void M_FirstLoadConfig(void) // make sure I_Quit() will write back the correct config // (do not write back the config if it crash before) 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. @@ -2435,3 +2443,13 @@ void M_SetupMemcpy(void) M_Memcpy = cpu_cpy; #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"; +} diff --git a/src/m_misc.h b/src/m_misc.h index 7038e3e48..c37865ff3 100644 --- a/src/m_misc.h +++ b/src/m_misc.h @@ -94,6 +94,8 @@ void strcatbf(char *s1, const char *s2, const char *s3); void M_SetupMemcpy(void); +const char *M_FileError(FILE *handle); + // counting bits, for weapon ammo code, usually FUNCMATH UINT8 M_CountBits(UINT32 num, UINT8 size); diff --git a/src/p_enemy.c b/src/p_enemy.c index eedbecaa7..7aba64e42 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -4070,19 +4070,28 @@ bossjustdie: mobj_t *pole = P_SpawnMobj( 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->floorz + 4*FRACUNIT, + mo->tracer->floorz + (256+1)*FRACUNIT, MT_FSGNB); 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->y + P_ReturnThrustY(pole, mo->tracer->angle, FRACUNIT), pole->z + 256*FRACUNIT, MT_FSGNA)); - pole->angle = mo->tracer->angle; - pole->tracer->angle = pole->angle - ANGLE_90; + pole->tracer->flags |= MF_NOCLIPTHING; + 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->momy = P_ReturnThrustY(pole, pole->angle, speed); pole->tracer->momx = pole->momx; pole->tracer->momy = pole->momy; + pole->tracer->tracer->momx = pole->momx; + pole->tracer->tracer->momy = pole->momy; } } else @@ -5121,7 +5130,7 @@ void A_SignPlayer(mobj_t *actor) return; #endif - if (actor->tracer == NULL || locvar1 < -3 || locvar1 >= numskins) + if (actor->tracer == NULL || locvar1 < -3 || locvar1 >= numskins || signcolor >= MAXTRANSLATIONS) return; // if no face overlay, spawn one @@ -5148,26 +5157,9 @@ void A_SignPlayer(mobj_t *actor) if (signcolor) ; else if ((actor->target->player->skincolor == skin->prefcolor) && (skin->prefoppositecolor)) // Set it as the skin's preferred oppositecolor? - { 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. - { signcolor = Color_Opposite[actor->target->player->skincolor - 1][0]; - signframe += (15 - Color_Opposite[actor->target->player->skincolor - 1][1]); - } else signcolor = SKINCOLOR_NONE; } @@ -5188,10 +5180,10 @@ void A_SignPlayer(mobj_t *actor) skinnum = P_RandomKey(skincount); for (skincount = 0; skincount < numskins; skincount++) { - if (skincheck(skincount)) - skinnum++; if (skincount > skinnum) break; + if (skincheck(skincount)) + skinnum++; } } else // otherwise, advance 1 skin @@ -5203,42 +5195,46 @@ void A_SignPlayer(mobj_t *actor) skin = &skins[skinnum]; } else // specific skin - { skin = &skins[locvar1]; - } facecolor = skin->prefcolor; if (signcolor) ; else if (skin->prefoppositecolor) - { signcolor = skin->prefoppositecolor; - } - else - { + else if (facecolor) 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->skin = skin; P_SetMobjState(ov, actor->info->seestate); // S_PLAY_SIGN - actor->tracer->color = signcolor; - actor->tracer->frame = signframe; } else // Eggman face { ov->color = SKINCOLOR_NONE; P_SetMobjState(ov, actor->info->meleestate); // S_EGGMANSIGN - if (signcolor) - actor->tracer->color = signcolor; - else - actor->tracer->color = signcolor = SKINCOLOR_CARBON; - actor->tracer->frame = signframe += (15 - Color_Opposite[Color_Opposite[signcolor - 1][0] - 1][1]); + if (!signcolor) + signcolor = SKINCOLOR_CARBON; } + + 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 diff --git a/src/p_inter.c b/src/p_inter.c index b0a401b10..cc7d702f3 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2741,7 +2741,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget case MT_EGGTRAP: // Time for birdies! Yaaaaaaaay! - target->fuse = TICRATE*2; + target->fuse = TICRATE; break; 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); S_StartSound(target, sfx_nghurt); +#ifdef ROTSPRITE + player->mo->rollangle = 0; +#endif + if (oldnightstime > 10*TICRATE && player->nightstime < 10*TICRATE) { diff --git a/src/p_local.h b/src/p_local.h index 17a1c32d2..b718c43f1 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -172,6 +172,7 @@ void P_ElementalFire(player_t *player, boolean cropcircle); void P_DoPityCheck(player_t *player); void P_PlayerThink(player_t *player); void P_PlayerAfterThink(player_t *player); +void P_DoPlayerFinish(player_t *player); void P_DoPlayerExit(player_t *player); void P_NightserizePlayer(player_t *player, INT32 ptime); diff --git a/src/p_map.c b/src/p_map.c index bb56a50b1..4055f7082 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -592,6 +592,9 @@ static void P_DoTailsCarry(player_t *sonic, player_t *tails) if (!(tails->pflags & PF_CANCARRY)) return; + if (sonic->pflags & PF_FINISHED) + return; + if (tails->bot == 1) return; @@ -661,31 +664,32 @@ static void P_SlapStick(mobj_t *fang, mobj_t *pole) momx2 = fang->momx/dist; momy2 = fang->momy/dist; - pole->tracer->momx = momx1 + (dist-1)*momx2; - pole->tracer->momy = momy1 + (dist-1)*momy2; + pole->tracer->tracer->momx = momx1 + (dist-1)*momx2; + pole->tracer->tracer->momy = momy1 + (dist-1)*momy2; fang->momx = (dist-1)*momx1 + momx2; fang->momy = (dist-1)*momy1 + momy2; #undef dist - P_SetMobjState(pole, pole->info->deathstate); - - P_SetObjectMomZ(pole->tracer, 6*FRACUNIT, false); - pole->tracer->flags &= ~(MF_NOGRAVITY|MF_NOCLIP); - pole->tracer->movedir = ANGLE_67h; - 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(pole->tracer->tracer, 6*FRACUNIT, false); + pole->tracer->tracer->flags &= ~(MF_NOGRAVITY|MF_NOCLIP); + pole->tracer->tracer->movedir = ANGLE_67h; + if ((R_PointToAngle(fang->x - pole->tracer->tracer->x, fang->y - pole->tracer->tracer->y) - pole->angle) > ANGLE_180) + pole->tracer->tracer->movedir = InvAngle(pole->tracer->movedir); P_SetObjectMomZ(fang, 14*FRACUNIT, false); fang->flags |= MF_NOGRAVITY|MF_NOCLIP; 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; - A_Scream(pole->tracer); + A_Scream(pole->tracer->tracer); S_StartSound(fang, sfx_altdi1); + P_SetTarget(&pole->tracer->tracer, NULL); + P_SetMobjState(pole->tracer, pole->info->xdeathstate); P_SetTarget(&pole->tracer, NULL); + P_SetMobjState(pole, pole->info->deathstate); } static void P_PlayerBarrelCollide(mobj_t *toucher, mobj_t *barrel) @@ -1089,7 +1093,7 @@ static boolean PIT_CheckThing(mobj_t *thing) return true; // overhead if (thing->z + thing->height < tmthing->z) return true; // underneath - if (!thing->tracer) + if (!thing->tracer || !thing->tracer->tracer) return true; P_SlapStick(tmthing, thing); // 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; } + // 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 if (tmthing->flags & MF_ENEMY) // An actual ENEMY! (Like the deton, for example) P_DamageMobj(thing, tmthing, tmthing, 1, 0); diff --git a/src/p_mobj.c b/src/p_mobj.c index 5d6a8a10f..d6ec977c2 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -246,6 +246,7 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state) { case S_PLAY_STND: case S_PLAY_WAIT: + case S_PLAY_NIGHTS_STAND: player->panim = PA_IDLE; break; case S_PLAY_EDGE: @@ -254,6 +255,7 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state) case S_PLAY_WALK: case S_PLAY_SKID: case S_PLAY_FLOAT: + case S_PLAY_NIGHTS_FLOAT: player->panim = PA_WALK; break; case S_PLAY_RUN: @@ -269,6 +271,7 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state) break; case S_PLAY_ROLL: //case S_PLAY_SPINDASH: -- everyone can ROLL thanks to zoom tubes... + case S_PLAY_NIGHTS_ATTACK: player->panim = PA_ROLL; break; case S_PLAY_JUMP: @@ -8227,7 +8230,7 @@ void P_MobjThinker(mobj_t *mobj) mobj->flags2 ^= MF2_DONTDRAW; break; 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; fixed_t x,y,z; @@ -8236,9 +8239,9 @@ void P_MobjThinker(mobj_t *mobj) mobj_t *flicky; z = mobj->subsector->sector->floorheight + FRACUNIT + (P_RandomKey(64)<x + FixedMul(FINESINE(fa),ns); y = mobj->y + FixedMul(FINECOSINE(fa),ns); @@ -8690,6 +8693,13 @@ void P_MobjThinker(mobj_t *mobj) case MT_KOOPA: P_KoopaThinker(mobj); 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: if (((mobj->z < mobj->floorz) || (mobj->z + mobj->height > mobj->ceilingz)) && mobj->flags & MF_MISSILE) diff --git a/src/p_setup.c b/src/p_setup.c index 60e507e86..bc0829670 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3244,47 +3244,22 @@ boolean P_SetupLevel(boolean skipprecip) #endif } - // Stage title! - wipestyleflags |= WSF_FADEIN; - wipestyleflags &= ~WSF_FADEOUT; - 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; + // No render mode, stop here. + if (rendermode == render_none) + return true; - F_WipeColorFill(levelfadecol); - stplyr = &players[consoleplayer]; - ST_drawLevelTitle(nowtime - starttime); - if (splitscreen) - { - stplyr = &players[secondarydisplayplayer]; - ST_drawLevelTitle(nowtime - starttime); - } + // Title card! + G_StartTitleCard(); - I_OsPolling(); - I_UpdateNoBlit(); - I_FinishUpdate(); // page flip or blit buffer + // Can the title card actually run, though? + if (!WipeStageTitle) + return true; + if (ranspecialwipe == 2) + return true; - if (moviemode) // make sure we save frames for the white hold too - M_SaveFrame(); - } - } + // If so... + if ((!(mapheaderinfo[gamemap-1]->levelflags & LF_NOTITLECARD)) && (*mapheaderinfo[gamemap-1]->lvlttl != '\0')) + G_PreLevelTitleCard(lt_ticker, true); return true; } diff --git a/src/p_spec.c b/src/p_spec.c index 355f5e728..f1a697399 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -4675,7 +4675,7 @@ DoneSection2: { INT32 lineindex; - P_DoPlayerExit(player); + P_DoPlayerFinish(player); P_SetupSignExit(player); // important: use sector->tag on next line instead of player->mo->subsector->tag diff --git a/src/p_user.c b/src/p_user.c index 3c481e7e2..ddb333d6d 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -636,6 +636,10 @@ static void P_DeNightserizePlayer(player_t *player) player->marebonuslap = 0; player->flyangle = 0; player->anotherflyangle = 0; +#ifdef ROTSPRITE + player->mo->rollangle = 0; +#endif + P_SetTarget(&player->mo->target, 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->flyangle = 0; player->anotherflyangle = 0; +#ifdef ROTSPRITE + player->mo->rollangle = 0; +#endif player->powers[pw_shield] = SH_NONE; 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 } +/** 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 // @@ -2158,12 +2189,14 @@ void P_DoPlayerExit(player_t *player) player->pflags |= P_GetJumpFlags(player); 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_spacetime] = 0; 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 @@ -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))) 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; mo = P_SpawnPlayerMissile(player->mo, MT_FIREBALL, 0); P_InstaThrust(mo, player->mo->angle, ((mo->info->speed>>FRACBITS)*player->mo->scale) + player->speed); S_StartSound(player->mo, sfx_mario7); + P_SetWeaponDelay(player, TICRATE); // Short delay between fireballs so you can't spam them everywhere return; } @@ -7701,9 +7735,9 @@ void P_ElementalFire(player_t *player, boolean cropcircle) I_Assert(!P_MobjWasRemoved(player->mo)); 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 - ground = player->mo->floorz; + ground = player->mo->floorz + 1; 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); - if (mo->eflags & MFE_VERTICALFLIP) - z = mo->z + mo->height - pviewheight - camheight + distz; + if (sign) + { + if (mo->eflags & MFE_VERTICALFLIP) + z = sign->ceilingz - pviewheight - camheight; + else + z = sign->floorz + pviewheight + camheight; + } 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 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 P_MobjCheckWater(player->mo); diff --git a/src/r_main.c b/src/r_main.c index 3ed509af5..5e758e52a 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -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_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}; +#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}; +#endif //#ifdef GLBADSHADOWS 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_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_chasecam2); +#if defined(FLOORSPLATS) || defined(GLBADSHADOWS) CV_RegisterVar(&cv_shadow); +#endif //#if defined(FLOORSPLATS) || defined(GLBADSHADOWS) +#ifdef GLBADSHADOWS CV_RegisterVar(&cv_shadowoffs); +#endif //#ifdef GLBADSHADOWS CV_RegisterVar(&cv_skybox); CV_RegisterVar(&cv_cam_dist); diff --git a/src/r_main.h b/src/r_main.h index 2c9b5cc3d..ae74ee067 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -76,7 +76,12 @@ extern consvar_t cv_showhud, cv_translucenthud; extern consvar_t cv_homremoval; extern consvar_t cv_chasecam, cv_chasecam2; 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_drawdist, cv_drawdist_nights, cv_drawdist_precip; extern consvar_t cv_skybox; diff --git a/src/r_patch.c b/src/r_patch.c index 9b65a54be..639f682fd 100644 --- a/src/r_patch.c +++ b/src/r_patch.c @@ -1066,16 +1066,15 @@ void R_ParseSPRTINFOLump(UINT16 wadNum, UINT16 lumpNum) sprinfoToken = M_GetToken(sprinfoText); while (sprinfoToken != NULL) { - if (!stricmp(sprinfoToken, "SPRITE") || !stricmp(sprinfoToken, "SPRITE2")) - { - Z_Free(sprinfoToken); - R_ParseSpriteInfo(!stricmp(sprinfoToken, "SPRITE2")); - } + if (!stricmp(sprinfoToken, "SPRITE")) + R_ParseSpriteInfo(false); + else if (!stricmp(sprinfoToken, "SPRITE2")) + R_ParseSpriteInfo(true); else I_Error("Error parsing SPRTINFO lump: Unknown keyword \"%s\"", sprinfoToken); + Z_Free(sprinfoToken); sprinfoToken = M_GetToken(NULL); } - Z_Free(sprinfoToken); Z_Free((void *)sprinfoText); } diff --git a/src/r_things.c b/src/r_things.c index ae3c47db4..c89d87bf4 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1196,20 +1196,20 @@ static void R_ProjectSprite(mobj_t *thing) #ifdef ROTSPRITE sprinfo = NULL; #endif - } - 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) + if (rot >= sprdef->numframes) { - thing->state->sprite = thing->sprite; - thing->state->frame = thing->frame; + CONS_Alert(CONS_ERROR, M_GetText("R_ProjectSprite: invalid sprite frame %s/%s for %s\n"), + 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; } } diff --git a/src/screen.c b/src/screen.c index f1d91de66..a1f6b7f55 100644 --- a/src/screen.c +++ b/src/screen.c @@ -428,6 +428,17 @@ void SCR_DisplayTicRate(void) 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) { UINT8 i; diff --git a/src/screen.h b/src/screen.h index 79f21e8e4..6f03612c4 100644 --- a/src/screen.h +++ b/src/screen.h @@ -167,5 +167,6 @@ FUNCMATH boolean SCR_IsAspectCorrect(INT32 width, INT32 height); // move out to main code for consistency void SCR_DisplayTicRate(void); void SCR_ClosedCaptions(void); +void SCR_DisplayLocalPing(void); #undef DNWH #endif //__SCREEN_H__ diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 578c705eb..5f162b00d 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -1180,6 +1180,9 @@ void I_FinishUpdate(void) { if (cv_ticrate.value) SCR_DisplayTicRate(); + + if (cv_showping.value && netgame && consoleplayer != serverplayer) + SCR_DisplayLocalPing(); } if (rendermode == render_soft && screens[0]) diff --git a/src/sounds.c b/src/sounds.c index b067903b1..ba2402eb9 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -779,7 +779,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"kc49", 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, ""}, - {"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"}, {"kc4e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"kc4f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, diff --git a/src/st_stuff.c b/src/st_stuff.c index 3fbee27e4..2b1b8e3ca 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -23,6 +23,7 @@ #include "v_video.h" #include "z_zone.h" #include "hu_stuff.h" +#include "console.h" #include "s_sound.h" #include "i_system.h" #include "m_menu.h" @@ -186,14 +187,18 @@ boolean ST_SameTeam(player_t *a, player_t *b) static boolean st_stopped = true; -void ST_Ticker(void) +void ST_Ticker(boolean run) { if (st_stopped) return; + + if (run) + ST_runTitleCard(); } // 0 is default, any others are special palettes. INT32 st_palette = 0; +INT32 st_translucency = 0; void ST_doPaletteStuff(void) { @@ -818,7 +823,7 @@ static void ST_drawLivesArea(void) face = superprefix[stplyr->skin]; V_DrawSmallMappedPatch(hudinfo[HUD_LIVES].x, hudinfo[HUD_LIVES].y, 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; 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!!"); } -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 *subttl = mapheaderinfo[gamemap-1]->subttl; INT32 actnum = mapheaderinfo[gamemap-1]->actnum; - INT32 lvlttly, zoney, lvlttlxpos, ttlnumxpos, zonexpos; + INT32 lvlttlxpos, ttlnumxpos, zonexpos; 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; +#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)); @@ -1177,72 +1310,73 @@ void ST_drawLevelTitle(tic_t titletime) lvlttlxpos -= V_LevelActNumWidth(actnum); ttlnumxpos = lvlttlxpos + V_LevelNameWidth(lvlttl); - zonexpos = ttlnumxpos - V_LevelNameWidth(M_GetText("ZONE")); + zonexpos = ttlnumxpos - V_LevelNameWidth(M_GetText("Zone")); ttlnumxpos++; if (lvlttlxpos < 0) lvlttlxpos = 0; -#if 0 // toaster's experiment. srb2&toast.exe one day, maybe? Requires stuff below to be converted to fixed point. -#define MIDTTLY 79 -#define MIDZONEY 105 -#define MIDDIFF 4 - - if (titletime < 10) + if (!splitscreen || (splitscreen && stplyr == &players[displayplayer])) { - fixed_t z = ((titletime - 3)<height, V_SNAPTOTOP|V_SNAPTOLEFT, zigzag); + V_DrawScaledPatch(FixedInt(lt_zigzag), (zigzag->height-zzticker) % zigzag->height, V_SNAPTOTOP|V_SNAPTOLEFT, zigzag); + 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)<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) - V_DrawCenteredString(subttlxpos, lvlttly+48, V_PERPLAYER|V_ALLOWLOWERCASE, subttl); + lt_lasttic = lt_ticker; + +#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) @@ -2106,7 +2240,7 @@ static void ST_drawTextHUD(void) 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); if (numneeded) @@ -2121,7 +2255,7 @@ static void ST_drawTextHUD(void) continue; total++; - if (players[i].exiting) + if (players[i].exiting || (players[i].pflags & PF_FINISHED)) exiting++; } @@ -2394,12 +2528,25 @@ static void ST_doItemFinderIconsAndSound(void) S_StartSound(NULL, sfx_emfind); } +// // Draw the status bar overlay, customisable: the user chooses which // kind of information to overlay // 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 ((maptol & TOL_NIGHTS || G_IsSpecialStage(gamemap)) && @@ -2550,12 +2697,8 @@ static void ST_overlayDrawer(void) #endif // draw level title Tails - if (*mapheaderinfo[gamemap-1]->lvlttl != '\0' && !(hu_showscores && (netgame || multiplayer)) -#ifdef HAVE_BLUA - && LUA_HudEnabled(hud_stagetitle) -#endif - ) - ST_drawLevelTitle(timeinmap+70); + if (stagetitle && (!WipeInAction) && (!WipeStageTitle)) + ST_drawTitleCard(); if (!hu_showscores && (netgame || multiplayer) #ifdef HAVE_BLUA @@ -2631,6 +2774,8 @@ void ST_Drawer(void) } } + st_translucency = cv_translucenthud.value; + if (st_overlay) { // No deadview! diff --git a/src/st_stuff.h b/src/st_stuff.h index aaf01ca15..33ffa957a 100644 --- a/src/st_stuff.h +++ b/src/st_stuff.h @@ -24,7 +24,7 @@ // // Called by main loop. -void ST_Ticker(void); +void ST_Ticker(boolean run); // Called by main loop. void ST_Drawer(void); @@ -47,8 +47,16 @@ void ST_ReloadSkinFaceGraphics(void); void ST_doPaletteStuff(void); -// level title draw -void ST_drawLevelTitle(tic_t titletime); +// title card +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 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 INT32 st_palette; // 0 is default, any others are special palettes. +extern INT32 st_translucency; extern lumpnum_t st_borderpatchnum; // patches, also used in intermission diff --git a/src/v_video.c b/src/v_video.c index 44e80c9f5..58244531e 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -18,6 +18,7 @@ #include "p_local.h" // stplyr #include "g_game.h" // players #include "v_video.h" +#include "st_stuff.h" #include "hu_stuff.h" #include "r_draw.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 == 13) - alphalevel = hudminusalpha[cv_translucenthud.value]; + alphalevel = hudminusalpha[st_translucency]; else if (alphalevel == 14) - alphalevel = 10 - cv_translucenthud.value; + alphalevel = 10 - st_translucency; else if (alphalevel == 15) - alphalevel = hudplusalpha[cv_translucenthud.value]; + alphalevel = hudplusalpha[st_translucency]; if (alphalevel >= 10) 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 == 13) - alphalevel = hudminusalpha[cv_translucenthud.value]; + alphalevel = hudminusalpha[st_translucency]; else if (alphalevel == 14) - alphalevel = 10 - cv_translucenthud.value; + alphalevel = 10 - st_translucency; else if (alphalevel == 15) - alphalevel = hudplusalpha[cv_translucenthud.value]; + alphalevel = hudplusalpha[st_translucency]; if (alphalevel >= 10) 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 == 13) - alphalevel = hudminusalpha[cv_translucenthud.value]; + alphalevel = hudminusalpha[st_translucency]; else if (alphalevel == 14) - alphalevel = 10 - cv_translucenthud.value; + alphalevel = 10 - st_translucency; else if (alphalevel == 15) - alphalevel = hudplusalpha[cv_translucenthud.value]; + alphalevel = hudplusalpha[st_translucency]; if (alphalevel >= 10) return; // invis @@ -2899,7 +2900,7 @@ void V_DrawLevelTitle(INT32 x, INT32 y, INT32 option, const char *string) continue; } - c = toupper(*ch) - LT_FONTSTART; + c = *ch - LT_FONTSTART; if (c < 0 || c >= LT_FONTSIZE || !lt_font[c]) { cx += 16*dupx; @@ -2934,7 +2935,7 @@ INT32 V_LevelNameWidth(const char *string) { if (string[i] & 0x80) continue; - c = toupper(string[i]) - LT_FONTSTART; + c = string[i] - LT_FONTSTART; if (c < 0 || c >= LT_FONTSIZE || !lt_font[c]) w += 16; else @@ -2953,7 +2954,7 @@ INT32 V_LevelNameHeight(const char *string) 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]) continue; @@ -2964,7 +2965,7 @@ INT32 V_LevelNameHeight(const char *string) return w; } -// For ST_drawLevelTitle +// For ST_drawTitleCard // Returns the width of the act num patch INT32 V_LevelActNumWidth(INT32 num) { diff --git a/src/w_wad.c b/src/w_wad.c index c3f38e737..0cd2175ec 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -383,7 +383,7 @@ static lumpinfo_t* ResGetLumpsWad (FILE* handle, UINT16* nlmp, const char* filen // read the 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; } @@ -406,7 +406,7 @@ static lumpinfo_t* ResGetLumpsWad (FILE* handle, UINT16* nlmp, const char* filen if (fseek(handle, header.infotableofs, SEEK_SET) == -1 || 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); return NULL; } @@ -427,7 +427,7 @@ static lumpinfo_t* ResGetLumpsWad (FILE* handle, UINT16* nlmp, const char* filen handle) < sizeof realsize) { I_Error("corrupt compressed file: %s; maybe %s", /// \todo Avoid the bailout? - filename, strerror(ferror(handle))); + filename, M_FileError(handle)); } realsize = LONG(realsize); if (realsize != 0) @@ -565,7 +565,7 @@ static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp) fseek(handle, -4, SEEK_CUR); 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; } 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)) { - 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); free(zentries); return NULL; @@ -602,7 +602,7 @@ static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp) fullname = malloc(zentry->namelen + 1); 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); free(zentries); free(fullname); diff --git a/src/win32/win_vid.c b/src/win32/win_vid.c index 11c7a6744..39a60cd93 100644 --- a/src/win32/win_vid.c +++ b/src/win32/win_vid.c @@ -371,6 +371,9 @@ void I_FinishUpdate(void) if (cv_ticrate.value) SCR_DisplayTicRate(); + if (cv_showping.value && netgame && consoleplayer != serverplayer) + SCR_DisplayLocalPing(); + // if (bDIBMode) { diff --git a/src/y_inter.c b/src/y_inter.c index 21e4bc56e..48d08a02e 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -399,10 +399,13 @@ void Y_IntermissionDrawer(void) // draw the "got through act" lines and act number 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) - V_DrawLevelActNum(244, 57, 0, data.coop.actnum); + if (data.coop.actnum) + V_DrawLevelActNum(244, 42+h, 0, data.coop.actnum); + } bonusy = 150; // Total @@ -485,10 +488,10 @@ void Y_IntermissionDrawer(void) if (drawsection == 1) { - const char *ringtext = "\x82" "50 RINGS, NO SHIELD"; - const char *tut1text = "\x82" "PRESS " "\x80" "SPIN"; - const char *tut2text = "\x82" "MID-" "\x80" "JUMP"; - ttheight = 16; + const char *ringtext = "\x82" "50 rings, no shield"; + const char *tut1text = "\x82" "press " "\x80" "spin"; + const char *tut2text = "\x82" "mid-" "\x80" "jump"; + ttheight = 8; V_DrawLevelTitle(data.spec.passedx1 + xoffset1, ttheight, 0, data.spec.passed1); ttheight += V_LevelNameHeight(data.spec.passed3) + 2; V_DrawLevelTitle(data.spec.passedx3 + xoffset2, ttheight, 0, data.spec.passed3); @@ -497,9 +500,9 @@ void Y_IntermissionDrawer(void) ttheight = 108; 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; + 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); } else @@ -1384,21 +1387,21 @@ void Y_StartIntermission(void) // too long so just show "YOU GOT THROUGH THE ACT" if (strlen(skins[players[consoleplayer].skin].realname) > 13) { - strcpy(data.coop.passed1, "YOU GOT"); - strcpy(data.coop.passed2, (mapheaderinfo[gamemap-1]->actnum) ? "THROUGH ACT" : "THROUGH THE ACT"); + strcpy(data.coop.passed1, "you got"); + 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" else if (strlen(skins[players[consoleplayer].skin].realname) > 8) { 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 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); - 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 @@ -1498,7 +1501,7 @@ void Y_StartIntermission(void) // set up the "got through act" message according to skin name if (stagefailed) { - strcpy(data.spec.passed2, "SPECIAL STAGE"); + strcpy(data.spec.passed2, "Special Stage"); data.spec.passed1[0] = '\0'; } else if (ALL7EMERALDS(emeralds)) @@ -1507,13 +1510,13 @@ void Y_StartIntermission(void) sizeof data.spec.passed1, "%s", skins[players[consoleplayer].skin].realname); 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) { - strcpy(data.spec.passed3, "CAN NOW BECOME"); + strcpy(data.spec.passed3, "can now become"); snprintf(data.spec.passed4, - sizeof data.spec.passed4, "SUPER %s", + sizeof data.spec.passed4, "Super %s", skins[players[consoleplayer].skin].realname); 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) { snprintf(data.spec.passed1, - sizeof data.spec.passed1, "%s GOT", + sizeof data.spec.passed1, "%s got", skins[players[consoleplayer].skin].realname); data.spec.passed1[sizeof data.spec.passed1 - 1] = '\0'; } else - strcpy(data.spec.passed1, "YOU GOT"); - strcpy(data.spec.passed2, "A CHAOS EMERALD"); + strcpy(data.spec.passed1, "You got"); + strcpy(data.spec.passed2, "a Chaos Emerald"); if (P_GetNextEmerald() > 6) { data.spec.passed2[15] = '?';