diff --git a/docs/rh-log.txt b/docs/rh-log.txt index f4a9c1212..1f8051527 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,9 +1,26 @@ +February 5, 2009 (Changes by Graf Zahl) +- fixed: The compatibility parser applied the last map's settings to all + maps in the compatibility list. +- Added compatibility settings for a few more levels in some classic WADs. +- Added spechit overflow workaround for Strain MAP07. This is highly map + specific because the original behavior cannot be restored. +- Added a check for Doom's IWAD levels that forces COMPAT_SHORTTEX for them. + MD5 cannot be used well here because there's many different IWADs with + slightly different levels. This is only done for Doom format levels to + ensure that custom IWADs for ZDoom are not affected. +- fixed: level.flags2 was not reset at level start. +- Fixed: Morph powerups can change the actor picking up the item so + AInventory::CallTryPickup must be able to return the new actor. +- Fixed: ACS's GiveInventory may not assume that a PlayerPawn is still + attached to the player data after an item has been given. +- Added a missing NULL pointer check to DBaseStatusBar::Blendview. + February 4, 2009 - Added a compatibility lump because I think it's a shame that Void doesn't work properly on new ZDooms after all the collaboration I had with Cyb on that map. (Works with other maps, too.) -February 5, 2009 (Changes by Graf Zahl) +February 4, 2009 (Changes by Graf Zahl) - Made improvements so that the FOptionalMapinfoData class is easier to use. February 3, 2009 diff --git a/src/compatibility.cpp b/src/compatibility.cpp index a2cf321f8..68e60b88c 100644 --- a/src/compatibility.cpp +++ b/src/compatibility.cpp @@ -45,6 +45,8 @@ #include "doomdef.h" #include "doomstat.h" #include "c_dispatch.h" +#include "gi.h" +#include "g_level.h" // MACROS ------------------------------------------------------------------ @@ -75,6 +77,7 @@ static FCompatOption Options[] = { { "setslopeoverflow", 0, BCOMPATF_SETSLOPEOVERFLOW }, { "resetplayerspeed", 0, BCOMPATF_RESETPLAYERSPEED }, + { "spechitoverflow", 0, BCOMPATF_SPECHITOVERFLOW }, // list copied from g_mapinfo.cpp { "shorttex", COMPATF_SHORTTEX, 0 }, @@ -169,6 +172,7 @@ void ParseCompatibility() { BCompatMap[md5array[j]] = flags; } + md5array.Clear(); } } @@ -183,20 +187,42 @@ void CheckCompatibility(MapData *map) FMD5Holder md5; FCompatValues *flags; - map->GetChecksum(md5.Bytes); - flags = BCompatMap.CheckKey(md5); - if (flags != NULL) + // When playing Doom IWAD levels force COMPAT_SHORTTEX. + if (Wads.GetLumpFile(map->lumpnum) == 1 && gameinfo.gametype == GAME_Doom && !(level.flags & LEVEL_HEXENFORMAT)) { - ii_compatflags = flags->CompatFlags; - ib_compatflags = flags->BCompatFlags; + ii_compatflags = COMPATF_SHORTTEX; + ib_compatflags = 0; } else { - ii_compatflags = 0; - ib_compatflags = 0; + map->GetChecksum(md5.Bytes); + + flags = BCompatMap.CheckKey(md5); + + if (developer) + { + Printf("MD5 = "); + for (size_t j = 0; j < sizeof(md5.Bytes); ++j) + { + Printf("%02X", md5.Bytes[j]); + } + if (flags != NULL) Printf(", cflags = %08x, bflags = %08x\n", flags->CompatFlags, flags->BCompatFlags); + else Printf("\n"); + } + + if (flags != NULL) + { + ii_compatflags = flags->CompatFlags; + ib_compatflags = flags->BCompatFlags; + } + else + { + ii_compatflags = 0; + ib_compatflags = 0; + } } // Reset i_compatflags - compatflags = compatflags; + compatflags.Callback(); } //========================================================================== diff --git a/src/doomdef.h b/src/doomdef.h index 4346a6d56..718724cc1 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -288,6 +288,7 @@ enum { BCOMPATF_SETSLOPEOVERFLOW = 1 << 0, // SetSlope things can overflow BCOMPATF_RESETPLAYERSPEED = 1 << 1, // Set player speed to 1.0 when changing maps + BCOMPATF_SPECHITOVERFLOW = 1 << 2, // Emulate spechit overflow (e.g. Strain MAP07) }; // phares 3/20/98: diff --git a/src/g_level.cpp b/src/g_level.cpp index 825ec621c..a2859ad75 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -1216,6 +1216,7 @@ void G_InitLevelLocals () level.aircontrol = (fixed_t)(sv_aircontrol * 65536.f); level.teamdamage = teamdamage; level.flags = 0; + level.flags2 = 0; info = FindLevelInfo (level.mapname); diff --git a/src/g_shared/a_pickups.cpp b/src/g_shared/a_pickups.cpp index e466d1cd0..a9689f4af 100644 --- a/src/g_shared/a_pickups.cpp +++ b/src/g_shared/a_pickups.cpp @@ -876,9 +876,9 @@ void AInventory::Touch (AActor *toucher) toucher = toucher->player->mo; } - // This is the only situation when a pickup flash should ever play. - if (!CallTryPickup (toucher)) return; + if (!CallTryPickup (toucher, &toucher)) return; + // This is the only situation when a pickup flash should ever play. if (PickupFlash != NULL && !ShouldStay()) { Spawn(PickupFlash, x, y, z, ALLOW_REPLACE); @@ -1258,10 +1258,13 @@ bool AInventory::TryPickup (AActor *&toucher) // //=========================================================================== -bool AInventory::CallTryPickup (AActor *toucher) +bool AInventory::CallTryPickup (AActor *toucher, AActor **toucher_return) { bool res = TryPickup(toucher); + // Morph items can change the toucher so we need an option to return this info. + if (toucher_return != NULL) *toucher_return = toucher; + if (!res && (ItemFlags & IF_ALWAYSPICKUP) && !ShouldStay()) { res = true; diff --git a/src/g_shared/a_pickups.h b/src/g_shared/a_pickups.h index d5d9465fb..fc56e3047 100644 --- a/src/g_shared/a_pickups.h +++ b/src/g_shared/a_pickups.h @@ -117,7 +117,7 @@ public: virtual bool ShouldRespawn (); virtual bool ShouldStay (); virtual void Hide (); - bool CallTryPickup (AActor *toucher); + bool CallTryPickup (AActor *toucher, AActor **toucher_return = NULL); virtual void DoPickupSpecial (AActor *toucher); virtual bool SpecialDropAction (AActor *dropper); virtual bool DrawPowerup (int x, int y); diff --git a/src/g_shared/shared_sbar.cpp b/src/g_shared/shared_sbar.cpp index 644e25085..ac1d31686 100644 --- a/src/g_shared/shared_sbar.cpp +++ b/src/g_shared/shared_sbar.cpp @@ -1502,7 +1502,7 @@ void DBaseStatusBar::BlendView (float blend[4]) if (screen->Accel2D || (CPlayer->camera != NULL && menuactive == MENU_Off && ConsoleState == c_up)) { - player_t *player = (CPlayer->camera->player != NULL) ? CPlayer->camera->player : CPlayer; + player_t *player = (CPlayer->camera != NULL && CPlayer->camera->player != NULL) ? CPlayer->camera->player : CPlayer; AddBlend (player->BlendR, player->BlendG, player->BlendB, player->BlendA, blend); } diff --git a/src/m_bbox.h b/src/m_bbox.h index bfc9bd7d7..7c7221688 100644 --- a/src/m_bbox.h +++ b/src/m_bbox.h @@ -65,6 +65,8 @@ public: int BoxOnLineSide (const line_t *ld) const; + void Set(int index, fixed_t value) {m_Box[index] = value;} + protected: fixed_t m_Box[4]; }; diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 2c192e91e..612190a39 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -451,7 +451,7 @@ static void DoGiveInv (AActor *actor, const PClass *info, int amount) } // If the item was a weapon, don't bring it up automatically // unless the player was not already using a weapon. - if (savedPendingWeap != NULL && hadweap) + if (savedPendingWeap != NULL && hadweap && actor->player != NULL) { actor->player->PendingWeapon = savedPendingWeap; } diff --git a/src/p_setup.cpp b/src/p_setup.cpp index aeef9bbb8..5465fec1c 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -3423,6 +3423,16 @@ void P_SetupLevel (char *lumpname, int position) P_LoadThings (map); else P_LoadThings2 (map); // [RH] Load Hexen-style things + + if (ib_compatflags & BCOMPATF_SPECHITOVERFLOW) + { + // restoring the original behavior doesn't work so we have to patch the levels in other ways. + // Fortunately the only known level depending on this bug is Strain's MAP07 and that's easy to fix. + if (numlines == 1022) + { + lines[1021].flags &= ~ML_BLOCKING; + } + } } else { diff --git a/src/p_user.cpp b/src/p_user.cpp index d1ef70fc9..8ff455b79 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -978,6 +978,8 @@ void APlayerPawn::ThrowPoisonBag () void APlayerPawn::GiveDefaultInventory () { + if (player == NULL) return; + // [GRB] Give inventory specified in DECORATE player->health = GetDefault ()->health; @@ -1033,13 +1035,20 @@ void APlayerPawn::GiveDefaultInventory () static_cast(item)->AmmoGive1 = static_cast(item)->AmmoGive2 = 0; } - if (!item->CallTryPickup(this)) + AActor *check; + if (!item->CallTryPickup(this, &check)) { + if (check != this) + { + // Player was morphed. This is illegal at game start. + // This problem is only detectable when it's too late to do something about it... + I_Error("Cannot give morph items when starting a game"); + } item->Destroy (); item = NULL; } } - if (item != NULL && item->IsKindOf (RUNTIME_CLASS (AWeapon)) && + if (item != NULL && item->IsKindOf (RUNTIME_CLASS (AWeapon)) && static_cast(item)->CheckAmmo(AWeapon::EitherFire, false)) { player->ReadyWeapon = player->PendingWeapon = static_cast (item); diff --git a/wadsrc/static/compatibility.txt b/wadsrc/static/compatibility.txt index f1afb6cbd..0601f7370 100644 --- a/wadsrc/static/compatibility.txt +++ b/wadsrc/static/compatibility.txt @@ -29,4 +29,34 @@ A80E7EE40E0D0C76A6FBD242BE29FE27 // map15 // What's really sad is that I got a separate bug report for this map // years ago, but nobody made mention of this problem back then. trace + useblocking +} + +// mostly cosmetic (except AV MAP07 and MM2 MAP25) +0EECBF37B328C9CAAF20DED4949A4157 // Sudtic e2m6 +4ACE0644883BDA0CBA254FA02C9ACF83 // Teutic e3m4 +9F2BE080A33F775294BD78822456924E // Nukemine e1m4 +CD31793D3A4B00231B124C0C23649644 // Strain map02 +19094AEB53D12EFC8E0568424F659F11 // Strain map31 +60733BDD1AA3F4B2262ADC79B2E1B5AB // Memento Mori map29 +F84AB4557464A383E93F37CD3A82AC48 // MM2 map03 +1497894956B3C8EBE8A240B7FDD99C6A // MM2 map25 +941E4CB56EE4184E0B1ED43486AB0BBF // AV map07 +{ + shorttex +} + +2FE901F659A16E58D7BCD7C30021C238 // AV map15 +{ + trace +} + +9D50EBE17CEC78938C7A668DB0768611 // Strain map07: Make the exit accessible +{ + spechitoverflow +} + +96368EB950E33AF62EA6423434E3CEF7 // Hacx map17: There's some switches behind shootable covers in this level +{ + useblocking }