diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 92196219d..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); @@ -4208,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; @@ -4733,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; @@ -4753,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. @@ -4763,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); } } } @@ -4783,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 } @@ -4816,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_netcmd.c b/src/d_netcmd.c index d750c81f2..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); @@ -341,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}; @@ -353,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}; @@ -514,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); @@ -577,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); @@ -3778,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 4821aff46..c2e6f980d 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -94,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; @@ -106,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 a58595c5c..2bb45969c 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, @@ -5357,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", @@ -7511,6 +7514,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", @@ -8375,6 +8381,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", @@ -8584,6 +8591,7 @@ static const char *const PLAYERFLAG_LIST[] = { /*** misc ***/ "FORCESTRAFE", // Translate turn inputs into strafe inputs "CANCARRY", // Can carry? + "FINISHED", NULL // stop loop here. }; 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/f_finale.c b/src/f_finale.c index 466d8b0f4..0f1140061 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1388,10 +1388,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 @@ -1638,7 +1641,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? @@ -1719,6 +1722,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); @@ -2148,7 +2154,6 @@ void F_StartGameEnd(void) gameaction = ga_nothing; paused = false; CON_ToggleOff(); - S_StopMusic(); S_StopSounds(); // In case menus are still up?!! diff --git a/src/g_game.c b/src/g_game.c index c16c28489..a0d8d5954 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2889,6 +2889,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) @@ -4087,7 +4112,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) @@ -5250,7 +5275,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 782b8ff5e..87232c823 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -209,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_main.c b/src/hardware/hw_main.c index f9e26733e..ea82d919b 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 90f4ceedf..afca4c773 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -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..21ce9e7f0 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 @@ -3722,9 +3723,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 +6119,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 @@ -19989,10 +19993,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 +20004,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 +20018,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..664be01e1 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, @@ -3812,6 +3813,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, @@ -4698,6 +4702,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_playerlib.c b/src/lua_playerlib.c index b1222ce67..6bda1988a 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -744,7 +744,7 @@ static int power_get(lua_State *L) UINT16 *powers = *((UINT16 **)luaL_checkudata(L, 1, META_POWERS)); powertype_t p = luaL_checkinteger(L, 2); if (p >= NUMPOWERS) - return luaL_error(L, LUA_QL("powertype_t") " cannot be %u", p); + return luaL_error(L, LUA_QL("powertype_t") " cannot be %d", (INT16)p); lua_pushinteger(L, powers[p]); 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 47ca7ccd4..04bbdba2c 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[] = @@ -7175,7 +7176,7 @@ static void M_DrawSoundTest(void) titl = va("%s - ", curplaying->title); } else - titl = "NONE - "; + titl = "None - "; i = V_LevelNameWidth(titl); @@ -7189,7 +7190,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) diff --git a/src/m_misc.c b/src/m_misc.c index 20d5f1de4..5cfb20f0f 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -23,6 +23,8 @@ #include #endif +#include + // Extended map support. #include @@ -2441,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..40c66b149 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, diff --git a/src/p_mobj.c b/src/p_mobj.c index 5d6a8a10f..47aaabc35 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); 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..5e76e0200 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 @@ -7701,9 +7734,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 +9922,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 +11443,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_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 fb0f4b2ba..f22c79eca 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 09f809ddc..a4c5246cb 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -1308,7 +1308,7 @@ void ST_drawTitleCard(void) 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) @@ -1332,7 +1332,7 @@ void ST_drawTitleCard(void) V_DrawLevelTitle(lvlttlxpos - ttlscroll, 80, V_PERPLAYER, lvlttl); if (!(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE)) - V_DrawLevelTitle(zonexpos + ttlscroll, 104, 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); lt_lasttic = lt_ticker; @@ -2236,7 +2236,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) @@ -2251,7 +2251,7 @@ static void ST_drawTextHUD(void) continue; total++; - if (players[i].exiting) + if (players[i].exiting || (players[i].pflags & PF_FINISHED)) exiting++; } diff --git a/src/v_video.c b/src/v_video.c index a9f60fff1..58244531e 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -2900,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; @@ -2935,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 @@ -2954,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; 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] = '?';