diff --git a/src/cmdlib.h b/src/cmdlib.h index e3a9d3d081..f6f0e6ad87 100644 --- a/src/cmdlib.h +++ b/src/cmdlib.h @@ -5,6 +5,7 @@ #include "doomtype.h" +#include "doomdef.h" #include #include @@ -62,4 +63,25 @@ struct FFileList void ScanDirectory(TArray &list, const char *dirpath); + +//========================================================================== +// +// Functions to compensate for a tic being a bit short. +// Since ZDoom uses a milliseconds timer for game timing +// 35 tics are actually only 0.98 seconds. +// For real time display this needs to be adjusted +// +//========================================================================== + +inline int AdjustTics(int tics) +{ + return (tics * 98) / 100; +} + +inline int Tics2Seconds(int tics) +{ + return (tics * 98) / (100 * TICRATE); +} + + #endif diff --git a/src/g_shared/a_armor.cpp b/src/g_shared/a_armor.cpp index 6b90a6a782..a745197c2c 100644 --- a/src/g_shared/a_armor.cpp +++ b/src/g_shared/a_armor.cpp @@ -25,6 +25,11 @@ void ABasicArmor::Serialize (FArchive &arc) { Super::Serialize (arc); arc << SavePercent << BonusCount << MaxAbsorb << MaxFullAbsorb << AbsorbCount << ArmorType; + + if (SaveVersion >= 4511) + { + arc << ActualSaveAmount; + } } //=========================================================================== @@ -69,6 +74,7 @@ AInventory *ABasicArmor::CreateCopy (AActor *other) copy->Icon = Icon; copy->BonusCount = BonusCount; copy->ArmorType = ArmorType; + copy->ActualSaveAmount = ActualSaveAmount; GoAwayAndDie (); return copy; } @@ -268,6 +274,7 @@ bool ABasicArmorPickup::Use (bool pickup) armor->MaxAbsorb = MaxAbsorb; armor->MaxFullAbsorb = MaxFullAbsorb; armor->ArmorType = this->GetClass()->TypeName; + armor->ActualSaveAmount = SaveAmount; return true; } @@ -360,6 +367,7 @@ bool ABasicArmorBonus::Use (bool pickup) armor->MaxAbsorb = MaxAbsorb; armor->ArmorType = this->GetClass()->TypeName; armor->MaxFullAbsorb = MaxFullAbsorb; + armor->ActualSaveAmount = MaxSaveAmount; } armor->Amount = MIN(armor->Amount + saveAmount, MaxSaveAmount + armor->BonusCount); diff --git a/src/g_shared/a_pickups.h b/src/g_shared/a_pickups.h index 22d1e009fb..72548776a5 100644 --- a/src/g_shared/a_pickups.h +++ b/src/g_shared/a_pickups.h @@ -423,6 +423,7 @@ public: int MaxFullAbsorb; int BonusCount; FNameNoInit ArmorType; + int ActualSaveAmount; }; // BasicArmorPickup replaces the armor you have. diff --git a/src/g_shared/sbarinfo_commands.cpp b/src/g_shared/sbarinfo_commands.cpp index 629c31cb49..c9011e8512 100644 --- a/src/g_shared/sbarinfo_commands.cpp +++ b/src/g_shared/sbarinfo_commands.cpp @@ -886,8 +886,11 @@ class CommandDrawString : public SBarInfoCommand } break; case TIME: - str.Format("%02d:%02d:%02d", (level.time/TICRATE)/3600, ((level.time/TICRATE)%3600)/60, (level.time/TICRATE)%60); + { + int sec = Tics2Seconds(level.time); + str.Format("%02d:%02d:%02d", sec / 3600, (sec % 3600) / 60, sec % 60); break; + } case LOGTEXT: str = statusBar->CPlayer->LogText; break; diff --git a/src/g_shared/shared_hud.cpp b/src/g_shared/shared_hud.cpp index 3806e5f9d6..2daeff7a85 100644 --- a/src/g_shared/shared_hud.cpp +++ b/src/g_shared/shared_hud.cpp @@ -867,7 +867,7 @@ static void DrawTime() : (hud_showtime < 6 ? level.time : level.totaltime); - const int timeSeconds = timeTicks / TICRATE; + const int timeSeconds = Tics2Seconds(timeTicks); hours = timeSeconds / 3600; minutes = (timeSeconds % 3600) / 60; @@ -994,7 +994,7 @@ void DrawHUD() if (am_showtotaltime) { - seconds = level.totaltime / TICRATE; + seconds = Tics2Seconds(level.totaltime); mysnprintf(printstr, countof(printstr), "%02i:%02i:%02i", seconds/3600, (seconds%3600)/60, seconds%60); DrawHudText(SmallFont, hudcolor_ttim, printstr, hudwidth-length, bottom, FRACUNIT); bottom -= fonth; @@ -1004,14 +1004,14 @@ void DrawHUD() { if (level.clusterflags&CLUSTER_HUB) { - seconds = level.time /TICRATE; + seconds = Tics2Seconds(level.time); mysnprintf(printstr, countof(printstr), "%02i:%02i:%02i", seconds/3600, (seconds%3600)/60, seconds%60); DrawHudText(SmallFont, hudcolor_time, printstr, hudwidth-length, bottom, FRACUNIT); bottom -= fonth; } // Single level time for hubs - seconds= level.maptime /TICRATE; + seconds= Tics2Seconds(level.maptime); mysnprintf(printstr, countof(printstr), "%02i:%02i:%02i", seconds/3600, (seconds%3600)/60, seconds%60); DrawHudText(SmallFont, hudcolor_ltim, printstr, hudwidth-length, bottom, FRACUNIT); } diff --git a/src/g_shared/shared_sbar.cpp b/src/g_shared/shared_sbar.cpp index 6b2f609b7e..89921e3a2f 100644 --- a/src/g_shared/shared_sbar.cpp +++ b/src/g_shared/shared_sbar.cpp @@ -1306,8 +1306,8 @@ void DBaseStatusBar::Draw (EHudState state) } else if (automapactive) { - int y, time = level.time / TICRATE, height; - int totaltime = level.totaltime / TICRATE; + int y, time = Tics2Seconds(level.time), height; + int totaltime = Tics2Seconds(level.totaltime); EColorRange highlight = (gameinfo.gametype & GAME_DoomChex) ? CR_UNTRANSLATED : CR_YELLOW; diff --git a/src/g_strife/strife_sbar.cpp b/src/g_strife/strife_sbar.cpp index 1a355b90a8..89659e61d8 100644 --- a/src/g_strife/strife_sbar.cpp +++ b/src/g_strife/strife_sbar.cpp @@ -586,29 +586,33 @@ private: screen->DrawTexture (Images[back], left, top, DTA_CleanNoMove, true, DTA_Alpha, FRACUNIT*3/4, TAG_DONE); screen->DrawTexture (Images[bars], left, top, DTA_CleanNoMove, true, TAG_DONE); + switch (CurrentPop) { case POP_Log: + { + int seconds = Tics2Seconds(level.time); // Draw the latest log message. - mysnprintf (buff, countof(buff), "%02d:%02d:%02d", - (level.time/TICRATE)/3600, - ((level.time/TICRATE)%3600)/60, - (level.time/TICRATE)%60); + mysnprintf(buff, countof(buff), "%02d:%02d:%02d", + seconds / 3600, + (seconds % 3600) / 60, + (seconds) % 60); - screen->DrawText (SmallFont2, CR_UNTRANSLATED, left+210*xscale, top+8*yscale, buff, + screen->DrawText(SmallFont2, CR_UNTRANSLATED, left + 210 * xscale, top + 8 * yscale, buff, DTA_CleanNoMove, true, TAG_DONE); if (CPlayer->LogText != NULL) { - FBrokenLines *lines = V_BreakLines (SmallFont2, 272, CPlayer->LogText); + FBrokenLines *lines = V_BreakLines(SmallFont2, 272, CPlayer->LogText); for (i = 0; lines[i].Width >= 0; ++i) { - screen->DrawText (SmallFont2, CR_UNTRANSLATED, left+24*xscale, top+(18+i*12)*yscale, + screen->DrawText(SmallFont2, CR_UNTRANSLATED, left + 24 * xscale, top + (18 + i * 12)*yscale, lines[i].Text, DTA_CleanNoMove, true, TAG_DONE); } - V_FreeBrokenLines (lines); + V_FreeBrokenLines(lines); } break; + } case POP_Keys: // List the keys the player has. diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 1646ab7b79..e0967d4004 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -128,6 +128,7 @@ enum ARMORINFO_SAVEPERCENT, ARMORINFO_MAXABSORB, ARMORINFO_MAXFULLABSORB, + ARMORINFO_ACTUALSAVEAMOUNT, }; struct CallReturn @@ -4858,6 +4859,9 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args, const case ARMORINFO_MAXFULLABSORB: return equippedarmor->MaxFullAbsorb; + case ARMORINFO_ACTUALSAVEAMOUNT: + return equippedarmor->ActualSaveAmount; + default: return 0; } diff --git a/src/p_maputl.cpp b/src/p_maputl.cpp index 17fc97d2f3..3a4a4c6a04 100644 --- a/src/p_maputl.cpp +++ b/src/p_maputl.cpp @@ -434,8 +434,8 @@ static int R_PointOnSideSlow (fixed_t x, fixed_t y, node_t *node) // add on a 386/486, but it certainly isn't on anything newer than that. fixed_t dx; fixed_t dy; - fixed_t left; - fixed_t right; + double left; + double right; if (!node->dx) { @@ -466,8 +466,9 @@ static int R_PointOnSideSlow (fixed_t x, fixed_t y, node_t *node) return 0; } - left = FixedMul ( node->dy>>FRACBITS , dx ); - right = FixedMul ( dy , node->dx>>FRACBITS ); + // we must use doubles here because the fixed point code will produce errors due to loss of precision for extremely short linedefs. + left = (double)node->dy * (double)dx; + right = (double)dy * (double)node->dx; if (right < left) { diff --git a/src/statistics.cpp b/src/statistics.cpp index acd8440e8a..7ed6e7f8ec 100644 --- a/src/statistics.cpp +++ b/src/statistics.cpp @@ -420,7 +420,7 @@ static void StoreLevelStats() LevelData[i].killcount = level.killed_monsters; LevelData[i].totalsecrets = level.total_secrets; LevelData[i].secretcount = level.found_secrets; - LevelData[i].leveltime = level.maptime; + LevelData[i].leveltime = AdjustTics(level.maptime); // Check for living monsters. On some maps it can happen // that the counter misses some. @@ -490,7 +490,7 @@ void STAT_ChangeLevel(const char *newl) } infostring.Format("%4d/%4d, %3d/%3d, %2d", statvals[0], statvals[1], statvals[2], statvals[3], validlevels); - FSessionStatistics *es = StatisticsEntry(sl, infostring, level.totaltime); + FSessionStatistics *es = StatisticsEntry(sl, infostring, AdjustTics(level.totaltime)); for(unsigned i = 0; i < LevelData.Size(); i++) { diff --git a/src/version.h b/src/version.h index 6d24c3fe8e..af376938cf 100644 --- a/src/version.h +++ b/src/version.h @@ -76,7 +76,7 @@ const char *GetVersionString(); // Use 4500 as the base git save version, since it's higher than the // SVN revision ever got. -#define SAVEVER 4510 +#define SAVEVER 4511 #define SAVEVERSTRINGIFY2(x) #x #define SAVEVERSTRINGIFY(x) SAVEVERSTRINGIFY2(x) diff --git a/src/wi_stuff.cpp b/src/wi_stuff.cpp index e60fee3033..2ab93f0905 100644 --- a/src/wi_stuff.cpp +++ b/src/wi_stuff.cpp @@ -1460,7 +1460,7 @@ void WI_drawDeathmatchStats () // Draw game time y += height + CleanYfac; - int seconds = plrs[me].stime / TICRATE; + int seconds = Tics2Seconds(plrs[me].stime); int hours = seconds / 3600; int minutes = (seconds % 3600) / 60; seconds = seconds % 60; @@ -1817,9 +1817,9 @@ void WI_updateStats () cnt_kills[0] = plrs[me].skills; cnt_items[0] = plrs[me].sitems; cnt_secret[0] = plrs[me].ssecret; - cnt_time = plrs[me].stime / TICRATE; + cnt_time = Tics2Seconds(plrs[me].stime); cnt_par = wbs->partime / TICRATE; - cnt_total_time = wbs->totaltime / TICRATE; + cnt_total_time = Tics2Seconds(wbs->totaltime); } if (sp_state == 2) @@ -1882,19 +1882,21 @@ void WI_updateStats () cnt_total_time += 3; } - if (!gameinfo.intermissioncounter || cnt_time >= plrs[me].stime / TICRATE) - cnt_time = plrs[me].stime / TICRATE; + int sec = Tics2Seconds(plrs[me].stime); + if (!gameinfo.intermissioncounter || cnt_time >= sec) + cnt_time = sec; - if (!gameinfo.intermissioncounter || cnt_total_time >= wbs->totaltime / TICRATE) - cnt_total_time = wbs->totaltime / TICRATE; + int tsec = Tics2Seconds(wbs->totaltime); + if (!gameinfo.intermissioncounter || cnt_total_time >= tsec) + cnt_total_time = tsec; if (!gameinfo.intermissioncounter || cnt_par >= wbs->partime / TICRATE) { cnt_par = wbs->partime / TICRATE; - if (cnt_time >= plrs[me].stime / TICRATE) + if (cnt_time >= sec) { - cnt_total_time = wbs->totaltime / TICRATE; + cnt_total_time = tsec; S_Sound (CHAN_VOICE | CHAN_UI, "intermission/nextstage", 1, ATTN_NONE); sp_state++; }