diff --git a/src/actor.h b/src/actor.h index 50247c0bb..d45d60a98 100644 --- a/src/actor.h +++ b/src/actor.h @@ -677,6 +677,11 @@ public: // Removes the item from the inventory list. virtual void RemoveInventory (AInventory *item); + // Take the amount value of an item from the inventory list. + // If nothing is left, the item may be destroyed. + // Returns true if the initial item count is positive. + virtual bool TakeInventory (const PClass *itemclass, int amount, bool fromdecorate = false, bool notakeinfinite = false); + // Uses an item and removes it from the inventory. virtual bool UseInventory (AInventory *item); diff --git a/src/d_main.cpp b/src/d_main.cpp index 9ddc17cd5..98be13e33 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -1981,6 +1981,9 @@ static void D_DoomInit() } FRandom::StaticClearRandom (); + + Printf ("M_LoadDefaults: Load system defaults.\n"); + M_LoadDefaults (); // load before initing other systems } //========================================================================== @@ -1989,7 +1992,7 @@ static void D_DoomInit() // //========================================================================== -static void AddAutoloadFiles(const char *autoname) +static void AddAutoloadFiles(const char *autoname) { LumpFilterIWAD.Format("%s.", autoname); // The '.' is appened to simplify parsing the string @@ -2247,8 +2250,8 @@ void D_DoomMain (void) iwad_man = new FIWadManager; iwad_man->ParseIWadInfos(basewad); - Printf ("M_LoadDefaults: Load system defaults.\n"); - M_LoadDefaults (iwad_man); // load before initing other systems + // Now that we have the IWADINFO, initialize the autoload ini sections. + GameConfig->DoAutoloadSetup(iwad_man); PClass::StaticInit (); atterm(FinalGC); @@ -2292,7 +2295,7 @@ void D_DoomMain (void) FBaseCVar::DisableCallbacks(); GameConfig->DoGameSetup (gameinfo.ConfigName); - AddAutoloadFiles(iwad_info->Autoname); + AddAutoloadFiles(iwad_info->Autoname); // Process automatically executed files FExecList *exec; diff --git a/src/g_shared/a_morph.cpp b/src/g_shared/a_morph.cpp index e3433f12e..ceffe907a 100644 --- a/src/g_shared/a_morph.cpp +++ b/src/g_shared/a_morph.cpp @@ -137,14 +137,9 @@ bool P_MorphPlayer (player_t *activator, player_t *p, const PClass *spawntype, i hxarmor->Slots[3] = 0; hxarmor->Slots[4] = spawntype->Meta.GetMetaFixed (APMETA_Hexenarmor0); } - else if (item->ItemFlags & IF_KEEPDEPLETED) - { - // Set depletable armor to 0 (this includes BasicArmor). - item->Amount = 0; - } else { - item->Destroy (); + item->DepleteOrDestroy(); } } item = next; diff --git a/src/g_shared/a_pickups.cpp b/src/g_shared/a_pickups.cpp index 5eda53ad6..038b63029 100644 --- a/src/g_shared/a_pickups.cpp +++ b/src/g_shared/a_pickups.cpp @@ -1131,6 +1131,32 @@ void AInventory::Destroy () if (SendItemDrop == this) SendItemDrop = NULL; } +//=========================================================================== +// +// AInventory :: DepleteOrDestroy +// +// If the item is depleted, just change its amount to 0, otherwise it's destroyed. +// +//=========================================================================== + +void AInventory::DepleteOrDestroy () +{ + // If it's not ammo or an internal armor, destroy it. + // Ammo needs to stick around, even when it's zero for the benefit + // of the weapons that use it and to maintain the maximum ammo + // amounts a backpack might have given. + // Armor shouldn't be removed because they only work properly when + // they are the last items in the inventory. + if (ItemFlags & IF_KEEPDEPLETED) + { + Amount = 0; + } + else + { + Destroy(); + } +} + //=========================================================================== // // AInventory :: GetBlend diff --git a/src/g_shared/a_pickups.h b/src/g_shared/a_pickups.h index df0c94b46..504a26c73 100644 --- a/src/g_shared/a_pickups.h +++ b/src/g_shared/a_pickups.h @@ -151,6 +151,7 @@ public: virtual void MarkPrecacheSounds() const; virtual void BeginPlay (); virtual void Destroy (); + virtual void DepleteOrDestroy (); virtual void Tick (); virtual bool ShouldRespawn (); virtual bool ShouldStay (); diff --git a/src/gameconfigfile.cpp b/src/gameconfigfile.cpp index 30dc2276d..3d396d98b 100644 --- a/src/gameconfigfile.cpp +++ b/src/gameconfigfile.cpp @@ -76,7 +76,7 @@ EXTERN_CVAR (Color, am_cdwallcolor) EXTERN_CVAR (Float, spc_amp) EXTERN_CVAR (Bool, wi_percents) -FGameConfigFile::FGameConfigFile (FIWadManager *iwad_man) +FGameConfigFile::FGameConfigFile () { #ifdef __APPLE__ FString user_docs, user_app_support, local_app_support; @@ -161,6 +161,27 @@ FGameConfigFile::FGameConfigFile (FIWadManager *iwad_man) SetValueForKey ("Path", "$DOOMWADDIR", true); } + // Add some self-documentation. + SetSectionNote("IWADSearch.Directories", + "# These are the directories to automatically search for IWADs.\n" + "# Each directory should be on a separate line, preceded by Path=\n"); + SetSectionNote("FileSearch.Directories", + "# These are the directories to search for wads added with the -file\n" + "# command line parameter, if they cannot be found with the path\n" + "# as-is. Layout is the same as for IWADSearch.Directories\n"); +} + +FGameConfigFile::~FGameConfigFile () +{ +} + +void FGameConfigFile::WriteCommentHeader (FILE *file) const +{ + fprintf (file, "# This file was generated by " GAMENAME " %s on %s\n", GetVersionString(), myasctime()); +} + +void FGameConfigFile::DoAutoloadSetup (FIWadManager *iwad_man) +{ // Create auto-load sections, so users know what's available. // Note that this totem pole is the reverse of the order that // they will appear in the file. @@ -220,14 +241,6 @@ FGameConfigFile::FGameConfigFile (FIWadManager *iwad_man) MoveSectionToStart("FileSearch.Directories"); MoveSectionToStart("IWADSearch.Directories"); - // Add some self-documentation. - SetSectionNote("IWADSearch.Directories", - "# These are the directories to automatically search for IWADs.\n" - "# Each directory should be on a separate line, preceded by Path=\n"); - SetSectionNote("FileSearch.Directories", - "# These are the directories to search for wads added with the -file\n" - "# command line parameter, if they cannot be found with the path\n" - "# as-is. Layout is the same as for IWADSearch.Directories\n"); SetSectionNote("Doom.AutoExec", "# Files to automatically execute when running the corresponding game.\n" "# Each file should be on its own line, preceded by Path=\n\n"); @@ -245,15 +258,6 @@ FGameConfigFile::FGameConfigFile (FIWadManager *iwad_man) "# 'doom.doom2.commercial.Autoload' only when playing doom2.wad.\n\n"); } -FGameConfigFile::~FGameConfigFile () -{ -} - -void FGameConfigFile::WriteCommentHeader (FILE *file) const -{ - fprintf (file, "# This file was generated by " GAMENAME " %s on %s\n", GetVersionString(), myasctime()); -} - void FGameConfigFile::DoGlobalSetup () { if (SetSection ("GlobalSettings.Unknown")) diff --git a/src/gameconfigfile.h b/src/gameconfigfile.h index 5862bb79e..68630f510 100644 --- a/src/gameconfigfile.h +++ b/src/gameconfigfile.h @@ -43,9 +43,10 @@ class FIWadManager; class FGameConfigFile : public FConfigFile { public: - FGameConfigFile (FIWadManager *iwad_man); + FGameConfigFile (); ~FGameConfigFile (); + void DoAutoloadSetup (FIWadManager *iwad_man); void DoGlobalSetup (); void DoGameSetup (const char *gamename); void DoKeySetup (const char *gamename); diff --git a/src/m_cheat.cpp b/src/m_cheat.cpp index f60131c8e..170c65021 100644 --- a/src/m_cheat.cpp +++ b/src/m_cheat.cpp @@ -768,11 +768,8 @@ void cht_Give (player_t *player, const char *name, int amount) type->GetReplacement()->IsDescendantOf(RUNTIME_CLASS(ADehackedPickup)))) { - // Give the weapon only if it belongs to the current game or - // is in a weapon slot. - if (type->ActorInfo->GameFilter == GAME_Any || - (type->ActorInfo->GameFilter & gameinfo.gametype) || - player->weapons.LocateWeapon(type, NULL, NULL)) + // Give the weapon only if it is in a weapon slot. + if (player->weapons.LocateWeapon(type, NULL, NULL)) { AWeapon *def = (AWeapon*)GetDefaultByType (type); if (giveall == ALL_YESYES || !(def->WeaponFlags & WIF_CHEATNOTWEAPON)) @@ -1052,24 +1049,7 @@ void cht_Take (player_t *player, const char *name, int amount) } else { - AInventory *inventory = player->mo->FindInventory (type); - - if (inventory != NULL) - { - inventory->Amount -= amount ? amount : 1; - - if (inventory->Amount <= 0) - { - if (inventory->ItemFlags & IF_KEEPDEPLETED) - { - inventory->Amount = 0; - } - else - { - inventory->Destroy (); - } - } - } + player->mo->TakeInventory(type, amount ? amount : 1); } return; } diff --git a/src/m_misc.cpp b/src/m_misc.cpp index 1369bdb52..7f4fa482d 100644 --- a/src/m_misc.cpp +++ b/src/m_misc.cpp @@ -410,9 +410,9 @@ CCMD (writeini) // M_LoadDefaults // -void M_LoadDefaults (FIWadManager *iwad_man) +void M_LoadDefaults () { - GameConfig = new FGameConfigFile(iwad_man); + GameConfig = new FGameConfigFile; GameConfig->DoGlobalSetup (); atterm (M_SaveDefaultsFinal); } diff --git a/src/m_misc.h b/src/m_misc.h index ea146c690..8b0da1050 100644 --- a/src/m_misc.h +++ b/src/m_misc.h @@ -41,7 +41,7 @@ void M_FindResponseFile (void); // Pass a NULL to get the original behavior. void M_ScreenShot (const char *filename); -void M_LoadDefaults (FIWadManager *iwad_man); +void M_LoadDefaults (); bool M_SaveDefaults (const char *filename); void M_SaveCustomKeys (FConfigFile *config, char *section, char *subsection, size_t sublen); diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 753d7728f..519e71c00 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -1131,40 +1131,6 @@ static void GiveInventory (AActor *activator, const char *type, int amount) } } -//============================================================================ -// -// DoTakeInv -// -// Takes an item from a single actor. -// -//============================================================================ - -static void DoTakeInv (AActor *actor, const PClass *info, int amount) -{ - AInventory *item = actor->FindInventory (info); - if (item != NULL) - { - item->Amount -= amount; - if (item->Amount <= 0) - { - // If it's not ammo or an internal armor, destroy it. - // Ammo needs to stick around, even when it's zero for the benefit - // of the weapons that use it and to maintain the maximum ammo - // amounts a backpack might have given. - // Armor shouldn't be removed because they only work properly when - // they are the last items in the inventory. - if (item->ItemFlags & IF_KEEPDEPLETED) - { - item->Amount = 0; - } - else - { - item->Destroy (); - } - } - } -} - //============================================================================ // // TakeInventory @@ -1199,12 +1165,12 @@ static void TakeInventory (AActor *activator, const char *type, int amount) for (int i = 0; i < MAXPLAYERS; ++i) { if (playeringame[i]) - DoTakeInv (players[i].mo, info, amount); + players[i].mo->TakeInventory(info, amount); } } else { - DoTakeInv (activator, info, amount); + activator->TakeInventory(info, amount); } } @@ -2302,8 +2268,8 @@ void FBehavior::LoadScriptsDirectory () } // [EP] Clang 3.5.0 optimizer miscompiles this function and causes random -// crashes in the program. I hope that Clang 3.5.x will fix this. -#if defined(__clang__) && __clang_major__ == 3 && __clang_minor__ >= 5 +// crashes in the program. This is fixed in 3.5.1 onwards. +#if defined(__clang__) && __clang_major__ == 3 && __clang_minor__ == 5 && __clang_patchlevel__ == 0 asm("" : "+g" (NumScripts)); #endif for (i = 0; i < NumScripts; ++i) @@ -4789,8 +4755,8 @@ static void SetActorTeleFog(AActor *activator, int tid, FString telefogsrc, FStr FActorIterator iterator(tid); AActor *actor; - const PClass * const src = telefogsrc.IsNotEmpty() ? PClass::FindClass(telefogsrc) : NULL; - const PClass * const dest = telefogdest.IsNotEmpty() ? PClass::FindClass(telefogdest) : NULL; + const PClass *src = PClass::FindClass(telefogsrc); + const PClass * dest = PClass::FindClass(telefogdest); while ((actor = iterator.Next())) { if (telefogsrc.IsNotEmpty()) diff --git a/src/p_conversation.cpp b/src/p_conversation.cpp index 4fd6f2fa6..069fca6e1 100644 --- a/src/p_conversation.cpp +++ b/src/p_conversation.cpp @@ -649,22 +649,7 @@ static void TakeStrifeItem (player_t *player, const PClass *itemtype, int amount if (itemtype == RUNTIME_CLASS(ASigil)) return; - AInventory *item = player->mo->FindInventory (itemtype); - if (item != NULL) - { - item->Amount -= amount; - if (item->Amount <= 0) - { - if (item->ItemFlags & IF_KEEPDEPLETED) - { - item->Amount = 0; - } - else - { - item->Destroy (); - } - } - } + player->mo->TakeInventory(itemtype, amount); } CUSTOM_CVAR(Float, dlg_musicvolume, 1.0f, CVAR_ARCHIVE) diff --git a/src/p_glnodes.cpp b/src/p_glnodes.cpp index 547cecace..a85dc94d9 100644 --- a/src/p_glnodes.cpp +++ b/src/p_glnodes.cpp @@ -944,13 +944,13 @@ bool P_LoadGLNodes(MapData * map) result=true; for(unsigned i=0; i<4;i++) { - if (strnicmp(f_gwa->GetLump(i+1)->Name, check[i], 8)) + if (strnicmp(f_gwa->GetLump(li+i+1)->Name, check[i], 8)) { result=false; break; } else - gwalumps[i] = f_gwa->GetLump(i+1)->NewReader(); + gwalumps[i] = f_gwa->GetLump(li+i+1)->NewReader(); } if (result) result = DoLoadGLNodes(gwalumps); } diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index 1e9dbf9b6..36f50a897 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -804,10 +804,7 @@ static int UseHealthItems(TArray &Items, int &saveHealth) saveHealth -= maxhealth; if (--Items[index]->Amount == 0) { - if (!(Items[index]->ItemFlags & IF_KEEPDEPLETED)) - { - Items[index]->Destroy (); - } + Items[index]->DepleteOrDestroy (); Items.Delete(index); break; } diff --git a/src/p_map.cpp b/src/p_map.cpp index 6370fa849..3d878c1f1 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -1034,7 +1034,7 @@ bool PIT_CheckThing(AActor *thing, FCheckPosition &tm) // Both things overlap in x or y direction bool unblocking = false; - if (tm.FromPMove || tm.thing->player != NULL) + if ((tm.FromPMove || tm.thing->player != NULL) && thing->flags&MF_SOLID) { // Both actors already overlap. To prevent them from remaining stuck allow the move if it // takes them further apart or the move does not change the position (when called from P_ChangeSector.) @@ -1042,7 +1042,9 @@ bool PIT_CheckThing(AActor *thing, FCheckPosition &tm) { unblocking = true; } - else + else if (abs(thing->x - tm.thing->x) < (thing->radius+tm.thing->radius)/2 && + abs(thing->y - tm.thing->y) < (thing->radius+tm.thing->radius)/2) + { fixed_t newdist = P_AproxDistance(thing->x - tm.x, thing->y - tm.y); fixed_t olddist = P_AproxDistance(thing->x - tm.thing->x, thing->y - tm.thing->y); diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index e2aa67764..3afc89b11 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -591,6 +591,57 @@ void AActor::RemoveInventory(AInventory *item) } } +//============================================================================ +// +// AActor :: TakeInventory +// +//============================================================================ + +bool AActor::TakeInventory(const PClass *itemclass, int amount, bool fromdecorate, bool notakeinfinite) +{ + AInventory *item = FindInventory(itemclass); + + if (item == NULL) + return false; + + if (!fromdecorate) + { + item->Amount -= amount; + if (item->Amount <= 0) + { + item->DepleteOrDestroy(); + } + // It won't be used in non-decorate context, so return false here + return false; + } + + bool result = false; + if (item->Amount > 0) + { + result = true; + } + + if (item->IsKindOf(RUNTIME_CLASS(AHexenArmor))) + return false; + + // Do not take ammo if the "no take infinite/take as ammo depletion" flag is set + // and infinite ammo is on + if (notakeinfinite && + ((dmflags & DF_INFINITE_AMMO) || (player && player->cheats & CF_INFINITEAMMO)) && + item->IsKindOf(RUNTIME_CLASS(AAmmo))) + { + // Nothing to do here, except maybe res = false;? Would it make sense? + } + else if (!amount || amount>=item->Amount) + { + item->DepleteOrDestroy(); + } + else item->Amount-=amount; + + return result; +} + + //============================================================================ // // AActor :: DestroyAllInventory @@ -658,9 +709,9 @@ bool AActor::UseInventory (AInventory *item) if (dmflags2 & DF2_INFINITE_INVENTORY) return true; - if (--item->Amount <= 0 && !(item->ItemFlags & IF_KEEPDEPLETED)) + if (--item->Amount <= 0) { - item->Destroy (); + item->DepleteOrDestroy (); } return true; } diff --git a/src/p_setup.cpp b/src/p_setup.cpp index f22979eac..fb6b34b53 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -1833,6 +1833,11 @@ void P_LoadThings2 (MapData * map) mti[i].SkillFilter = MakeSkill(mti[i].flags); mti[i].ClassFilter = (mti[i].flags & MTF_CLASS_MASK) >> MTF_CLASS_SHIFT; mti[i].flags &= ~(MTF_SKILLMASK|MTF_CLASS_MASK); + if (level.flags2 & LEVEL2_HEXENHACK) + { + mti[i].flags &= 0x7ff; // mask out Strife flags if playing an original Hexen map. + } + mti[i].gravity = FRACUNIT; mti[i].RenderStyle = STYLE_Count; mti[i].alpha = -1; diff --git a/src/p_tags.cpp b/src/p_tags.cpp index d5c03ec9d..e773b691f 100644 --- a/src/p_tags.cpp +++ b/src/p_tags.cpp @@ -314,7 +314,7 @@ int FSectorTagIterator::Next() while (start >= 0 && tagManager.allTags[start].tag != searchtag) start = tagManager.allTags[start].nexttag; if (start == -1) return -1; ret = tagManager.allTags[start].target; - start = start = tagManager.allTags[start].nexttag; + start = tagManager.allTags[start].nexttag; } return ret; } @@ -348,6 +348,6 @@ int FLineIdIterator::Next() while (start >= 0 && tagManager.allIDs[start].tag != searchtag) start = tagManager.allIDs[start].nexttag; if (start == -1) return -1; int ret = tagManager.allIDs[start].target; - start = start = tagManager.allIDs[start].nexttag; + start = tagManager.allIDs[start].nexttag; return ret; } diff --git a/src/sound/fmodsound.cpp b/src/sound/fmodsound.cpp index 73e419555..8433b301b 100644 --- a/src/sound/fmodsound.cpp +++ b/src/sound/fmodsound.cpp @@ -304,7 +304,7 @@ class FMODStreamCapsule : public SoundStream public: FMODStreamCapsule(FMOD::Sound *stream, FMODSoundRenderer *owner, const char *url) : Owner(owner), Stream(NULL), Channel(NULL), - UserData(NULL), Callback(NULL), URL(url), Reader(NULL), Ended(false) + UserData(NULL), Callback(NULL), Reader(NULL), URL(url), Ended(false) { SetStream(stream); } diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index b4c6a219a..b1da8f546 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -1783,31 +1783,7 @@ void DoTakeInventory(AActor * receiver, bool use_aaptr, DECLARE_PARAMINFO) COPY_AAPTR_NOT_NULL(receiver, receiver, setreceiver); } - bool res = false; - - AInventory * inv = receiver->FindInventory(item); - - if (inv && !inv->IsKindOf(RUNTIME_CLASS(AHexenArmor))) - { - if (inv->Amount > 0) - { - res = true; - } - // Do not take ammo if the "no take infinite/take as ammo depletion" flag is set - // and infinite ammo is on - if (flags & TIF_NOTAKEINFINITE && - ((dmflags & DF_INFINITE_AMMO) || (receiver->player->cheats & CF_INFINITEAMMO)) && - inv->IsKindOf(RUNTIME_CLASS(AAmmo))) - { - // Nothing to do here, except maybe res = false;? Would it make sense? - } - else if (!amount || amount>=inv->Amount) - { - if (inv->ItemFlags&IF_KEEPDEPLETED) inv->Amount=0; - else inv->Destroy(); - } - else inv->Amount-=amount; - } + bool res = receiver->TakeInventory(item, amount, true, (flags & TIF_NOTAKEINFINITE) != 0); ACTION_SET_RESULT(res); } diff --git a/src/thingdef/thingdef_properties.cpp b/src/thingdef/thingdef_properties.cpp index 95f1c463c..27ceeb698 100644 --- a/src/thingdef/thingdef_properties.cpp +++ b/src/thingdef/thingdef_properties.cpp @@ -1410,8 +1410,7 @@ DEFINE_PROPERTY(stamina, I, Actor) DEFINE_PROPERTY(telefogsourcetype, S, Actor) { PROP_STRING_PARM(str, 0); - if (!stricmp(str, "") || !stricmp(str, "none")) defaults->TeleFogSourceType = NULL; - else defaults->TeleFogSourceType = FindClassTentative(str,"TeleportFog"); + defaults->TeleFogSourceType = FindClassTentative(str,"Actor"); } //========================================================================== @@ -1420,8 +1419,7 @@ DEFINE_PROPERTY(telefogsourcetype, S, Actor) DEFINE_PROPERTY(telefogdesttype, S, Actor) { PROP_STRING_PARM(str, 0); - if (!stricmp(str, "") || !stricmp(str, "none")) defaults->TeleFogDestType = NULL; - else defaults->TeleFogDestType = FindClassTentative(str, "TeleportFog"); + defaults->TeleFogDestType = FindClassTentative(str, "Actor"); } //==========================================================================