diff --git a/specs/udmf_zdoom.txt b/specs/udmf_zdoom.txt index fe6897d9f..fef3fa996 100644 --- a/specs/udmf_zdoom.txt +++ b/specs/udmf_zdoom.txt @@ -183,6 +183,7 @@ Note: All <bool> fields default to false unless mentioned otherwise. // menu can display. conversation = <int> // Assigns a conversation dialogue to this thing. // Parameter is the conversation ID, 0 meaning none. + countsecret = <bool>; // Picking up this actor counts as a secret. } @@ -269,7 +270,7 @@ Changed node specifications to deprecate compression of node lump. Added 'playeruseback' line trigger flag. 1.11 07.08.2010 -Added 'soundsequnce' sector property. +Added 'soundsequence' sector property. 1.12 22.08.2010 Added 'conversation' thing property. @@ -277,6 +278,9 @@ Added 'conversation' thing property. 1.13 29.08.2010 Added 'hidden' sector property. +1.14 19.09.2010 +Added 'countsecret' actor property. + =============================================================================== EOF =============================================================================== diff --git a/src/actor.h b/src/actor.h index 2a8921b56..7de8a725e 100644 --- a/src/actor.h +++ b/src/actor.h @@ -269,7 +269,7 @@ enum MF5_FASTMELEE = 0x00000002, // has a faster melee attack when DF_FAST_MONSTERS or nightmare is on. MF5_NODROPOFF = 0x00000004, // cannot drop off under any circumstances. /* = 0x00000008, */ - /* = 0x00000010, */ + MF5_COUNTSECRET = 0x00000010, // From Doom 64: actor acts like a secret MF5_AVOIDINGDROPOFF = 0x00000020, // Used to move monsters away from dropoffs MF5_NODAMAGE = 0x00000040, // Actor can be shot and reacts to being shot but takes no damage MF5_CHASEGOAL = 0x00000080, // Walks to goal instead of target if a valid goal is set. @@ -289,7 +289,7 @@ enum MF5_NOINTERACTION = 0x00200000, // Thing is completely excluded from any gameplay related checks MF5_NOTIMEFREEZE = 0x00400000, // Actor is not affected by time freezer MF5_PUFFGETSOWNER = 0x00800000, // [BB] Sets the owner of the puff to the player who fired it - MF5_SPECIALFIREDAMAGE=0x01000000, // Special treatment of PhoenixFX1 turned into a flag to removr + MF5_SPECIALFIREDAMAGE=0x01000000, // Special treatment of PhoenixFX1 turned into a flag to remove // dependence of main engine code of specific actor types. MF5_SUMMONEDMONSTER = 0x02000000, // To mark the friendly Minotaur. Hopefully to be generalized later. MF5_NOVERTICALMELEERANGE=0x04000000,// Does not check vertical distance for melee range @@ -832,7 +832,7 @@ public: BYTE MinMissileChance;// [RH] If a random # is > than this, then missile attack. SBYTE LastLookPlayerNumber;// Player number last looked for (if TIDtoHate == 0) WORD BounceFlags; // which bouncing type? - WORD SpawnFlags; + DWORD SpawnFlags; // Increased to DWORD because of Doom 64 fixed_t meleerange; // specifies how far a melee attack reaches. fixed_t meleethreshold; // Distance below which a monster doesn't try to shoot missiles anynore // but instead tries to come closer for a melee attack. @@ -937,6 +937,7 @@ public: virtual bool UpdateWaterLevel (fixed_t oldz, bool splash=true); bool isFast(); void SetIdle(); + void ClearCounters(); FState *FindState (FName label) const { diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index 97c8296a4..225f24cab 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -2895,11 +2895,7 @@ bool ADehackedPickup::TryPickup (AActor *&toucher) if (RealPickup != NULL) { // The internally spawned item should never count towards statistics. - if (RealPickup->flags & MF_COUNTITEM) - { - RealPickup->flags &= ~MF_COUNTITEM; - level.total_items--; - } + RealPickup->ClearCounters(); if (!(flags & MF_DROPPED)) { RealPickup->flags &= ~MF_DROPPED; diff --git a/src/doomdata.h b/src/doomdata.h index 9c22b22a6..83345a671 100644 --- a/src/doomdata.h +++ b/src/doomdata.h @@ -380,6 +380,8 @@ enum EMapThingFlags MTF_STANDSTILL = 0x4000, MTF_STRIFESOMETHING = 0x8000, + MTF_SECRET = 0x080000, // Secret pickup + MTF_NOINFIGHTING = 0x100000, // BOOM and DOOM compatible versions of some of the above BTF_NOTSINGLE = 0x0010, // (TF_COOPERATIVE|TF_DEATHMATCH) diff --git a/src/g_heretic/a_dsparil.cpp b/src/g_heretic/a_dsparil.cpp index aa0bd46ed..0b25a94de 100644 --- a/src/g_heretic/a_dsparil.cpp +++ b/src/g_heretic/a_dsparil.cpp @@ -258,8 +258,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_GenWizard) mo->z -= mo->GetDefault()->height/2; if (!P_TestMobjLocation (mo)) { // Didn't fit + mo->ClearCounters(); mo->Destroy (); - level.total_monsters--; } else { // [RH] Make the new wizards inherit D'Sparil's target diff --git a/src/g_hexen/a_heresiarch.cpp b/src/g_hexen/a_heresiarch.cpp index 2107f2722..ecce5d2a8 100644 --- a/src/g_hexen/a_heresiarch.cpp +++ b/src/g_hexen/a_heresiarch.cpp @@ -859,8 +859,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpawnBishop) { if (!P_TestMobjLocation(mo)) { + mo->ClearCounters(); mo->Destroy (); - level.total_monsters--; } else if (self->target != NULL) { // [RH] Make the new bishops inherit the Heriarch's target diff --git a/src/g_shared/a_pickups.cpp b/src/g_shared/a_pickups.cpp index 30dcd482c..524daee77 100644 --- a/src/g_shared/a_pickups.cpp +++ b/src/g_shared/a_pickups.cpp @@ -924,6 +924,11 @@ void AInventory::Touch (AActor *toucher) level.found_items++; } + if (flags5 & MF5_COUNTSECRET) + { + P_GiveSecret(toucher, true, true); + } + //Added by MC: Check if item taken was the roam destination of any bot for (int i = 0; i < MAXPLAYERS; i++) { diff --git a/src/g_shared/a_secrettrigger.cpp b/src/g_shared/a_secrettrigger.cpp index d0996aab8..79f3bcd30 100644 --- a/src/g_shared/a_secrettrigger.cpp +++ b/src/g_shared/a_secrettrigger.cpp @@ -40,6 +40,8 @@ #include "d_player.h" #include "doomstat.h" #include "v_font.h" +#include "r_data.h" +#include "p_spec.h" EXTERN_CVAR(String, secretmessage) @@ -61,22 +63,7 @@ void ASecretTrigger::PostBeginPlay () void ASecretTrigger::Activate (AActor *activator) { - if (activator != NULL) - { - if (activator->CheckLocalView (consoleplayer)) - { - if (args[0] <= 1) - { - C_MidPrint (SmallFont, secretmessage); - } - if (args[0] == 0 || args[0] == 2) - { - S_Sound (activator, CHAN_AUTO, "misc/secret", 1, ATTN_NORM); - } - } - if (activator->player) activator->player->secretcount++; - } - level.found_secrets++; + P_GiveSecret(activator, args[0] <= 1, (args[0] == 0 || args[0] == 2)); Destroy (); } diff --git a/src/gameconfigfile.cpp b/src/gameconfigfile.cpp index acf2bbad1..64ddaa4b8 100644 --- a/src/gameconfigfile.cpp +++ b/src/gameconfigfile.cpp @@ -380,7 +380,7 @@ void FGameConfigFile::DoGameSetup (const char *gamename) ReadCVars (0); } - if (game != Doom && game != Strife && game != Chex) + if (game == Heretic || game == Hexen) { SetRavenDefaults (game == Hexen); } diff --git a/src/m_cheat.cpp b/src/m_cheat.cpp index 9da1b1ff5..95ddf7725 100644 --- a/src/m_cheat.cpp +++ b/src/m_cheat.cpp @@ -590,11 +590,7 @@ void GiveSpawner (player_t *player, const PClass *type, int amount) item->Amount = MIN (amount, item->MaxAmount); } } - if(item->flags & MF_COUNTITEM) // Given items shouldn't count against the map's total, - { // since they aren't added to the player's total. - level.total_items--; - item->flags &= ~MF_COUNTITEM; - } + item->ClearCounters(); if (!item->CallTryPickup (player->mo)) { item->Destroy (); diff --git a/src/namedef.h b/src/namedef.h index 9f7e5a87d..012d85afa 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -359,6 +359,7 @@ xx(Invisible) xx(Friend) xx(Strifeally) xx(Standing) +xx(Countsecret) xx(Blocking) xx(Blockmonsters) diff --git a/src/p_acs.cpp b/src/p_acs.cpp index f7a52987b..e147648e5 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -434,11 +434,7 @@ static void DoGiveInv (AActor *actor, const PClass *info, int amount) AInventory *item = static_cast<AInventory *>(Spawn (info, 0,0,0, NO_REPLACE)); // This shouldn't count for the item statistics! - if (item->flags & MF_COUNTITEM) - { - level.total_items--; - item->flags &= ~MF_COUNTITEM; - } + item->ClearCounters(); if (info->IsDescendantOf (RUNTIME_CLASS(ABasicArmorPickup))) { if (static_cast<ABasicArmorPickup*>(item)->SaveAmount != 0) @@ -2286,15 +2282,7 @@ int DLevelScript::DoSpawn (int type, fixed_t x, fixed_t y, fixed_t z, int tid, i { // If this is a monster, subtract it from the total monster // count, because it already added to it during spawning. - if (actor->CountsAsKill()) - { - level.total_monsters--; - } - // Same, for items - if (actor->flags & MF_COUNTITEM) - { - level.total_items--; - } + actor->ClearCounters(); actor->Destroy (); actor = NULL; } diff --git a/src/p_conversation.cpp b/src/p_conversation.cpp index a2c287a42..7283c4abd 100644 --- a/src/p_conversation.cpp +++ b/src/p_conversation.cpp @@ -1264,11 +1264,7 @@ static void HandleReply(player_t *player, bool isconsole, int nodenum, int reply { AInventory *item = static_cast<AInventory *>(Spawn(reply->GiveType, 0, 0, 0, NO_REPLACE)); // Items given here should not count as items! - if (item->flags & MF_COUNTITEM) - { - level.total_items--; - item->flags &= ~MF_COUNTITEM; - } + item->ClearCounters(); if (item->GetClass()->TypeName == NAME_FlameThrower) { // The flame thrower gives less ammo when given in a dialog diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 4d6cdc765..f12127a75 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -258,9 +258,18 @@ void AActor::Serialize (FArchive &arc) << args[0] << args[1] << args[2] << args[3] << args[4] << goal << waterlevel - << MinMissileChance - << SpawnFlags - << Inventory + << MinMissileChance; + if (SaveVersion >= 2826) + { + arc << SpawnFlags; + } + else + { + WORD w; + arc << w; + SpawnFlags = w; + } + arc << Inventory << InventoryID << id << FloatBobPhase @@ -728,6 +737,7 @@ AInventory *AActor::DropInventory (AInventory *item) drop->vely = vely + 5 * finesine[an]; drop->velz = velz + FRACUNIT; drop->flags &= ~MF_NOGRAVITY; // Don't float + drop->ClearCounters(); // do not count for statistics again return drop; } @@ -2458,7 +2468,7 @@ void P_NightmareRespawn (AActor *mobj) if (!P_TestMobjLocation (mo)) { //[GrafZahl] MF_COUNTKILL still needs to be checked here. - if (mo->CountsAsKill()) level.total_monsters--; + mo->ClearCounters(); mo->Destroy (); return; // no respawn } @@ -3626,6 +3636,11 @@ AActor *AActor::StaticSpawn (const PClass *type, fixed_t ix, fixed_t iy, fixed_t { level.total_items++; } + // And for secrets + if (actor->flags5 & MF5_COUNTSECRET) + { + level.total_secrets++; + } if (screen != NULL) { screen->StateChanged(actor); @@ -3695,6 +3710,11 @@ void AActor::HandleSpawnFlags () { RenderStyle = STYLE_None; } + if (SpawnFlags & MTF_SECRET) + { + //Printf("Secret %s in sector %i!\n", GetTag(), Sector->sectornum); + flags5 |= MF5_COUNTSECRET; + } } void AActor::BeginPlay () @@ -4969,11 +4989,7 @@ bool P_CheckMissileSpawn (AActor* th) if (th->BlockingMobj == NULL || !(th->flags2 & MF2_RIP) || (th->BlockingMobj->flags5 & MF5_DONTRIP)) { // If this is a monster spawned by A_CustomMissile subtract it from the counter. - if (th->CountsAsKill()) - { - th->flags&=~MF_COUNTKILL; - level.total_monsters--; - } + th->ClearCounters(); // [RH] Don't explode missiles that spawn on top of horizon lines if (th->BlockingLine != NULL && th->BlockingLine->special == Line_Horizon) { @@ -5602,6 +5618,28 @@ const char *AActor::GetTag(const char *def) const } +void AActor::ClearCounters() +{ + if (CountsAsKill()) + { + level.total_monsters--; + flags &= ~MF_COUNTKILL; + } + // Same, for items + if (flags & MF_COUNTITEM) + { + level.total_items--; + flags &= ~MF_COUNTITEM; + } + // And finally for secrets + if (flags5 & MF5_COUNTSECRET) + { + level.total_secrets--; + flags5 &= ~MF5_COUNTSECRET; + } +} + + //---------------------------------------------------------------------------- // // DropItem handling diff --git a/src/p_spec.cpp b/src/p_spec.cpp index e37df68b1..2e3f1b6e2 100644 --- a/src/p_spec.cpp +++ b/src/p_spec.cpp @@ -256,7 +256,7 @@ bool P_ActivateLine (line_t *line, AActor *mo, int side, int activationType) // end of changed code if (developer && buttonSuccess) { - Printf ("Line special %d activated\n", special); + Printf ("Line special %d activated on line %i\n", special, line - lines); } return true; } @@ -561,15 +561,33 @@ void P_PlayerInSpecialSector (player_t *player, sector_t * sector) if (sector->special & SECRET_MASK) { - player->secretcount++; - level.found_secrets++; sector->special &= ~SECRET_MASK; - if (player->mo->CheckLocalView (consoleplayer)) + P_GiveSecret(player->mo, true, true); + } +} + + +//============================================================================ +// +// P_GiveSecret +// +//============================================================================ + +void P_GiveSecret(AActor *actor, bool printmessage, bool playsound) +{ + if (actor != NULL) + { + if (actor->player != NULL) { - C_MidPrint (SmallFont, secretmessage); - S_Sound (CHAN_AUTO, "misc/secret", 1, ATTN_NORM); + actor->player->secretcount++; + } + if (actor->CheckLocalView (consoleplayer)) + { + if (printmessage) C_MidPrint (SmallFont, secretmessage); + if (playsound) S_Sound (CHAN_AUTO, "misc/secret", 1, ATTN_NORM); } } + level.found_secrets++; } //============================================================================ @@ -1923,6 +1941,15 @@ DPusher::DPusher (DPusher::EPusher type, line_t *l, int magnitude, int angle, m_Affectee = affectee; } +int DPusher::CheckForSectorMatch (EPusher type, int tag) +{ + if (m_Type == type && sectors[m_Affectee].tag == tag) + return m_Affectee; + else + return -1; +} + + ///////////////////////////// // // T_Pusher looks for all objects that are inside the radius of diff --git a/src/p_spec.h b/src/p_spec.h index ca3694c09..0171cf796 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -122,13 +122,7 @@ public: DPusher (); DPusher (EPusher type, line_t *l, int magnitude, int angle, AActor *source, int affectee); void Serialize (FArchive &arc); - int CheckForSectorMatch (EPusher type, int tag) - { - if (m_Type == type && sectors[m_Affectee].tag == tag) - return m_Affectee; - else - return -1; - } + int CheckForSectorMatch (EPusher type, int tag); void ChangeValues (int magnitude, int angle) { angle_t ang = ((angle_t)(angle<<24)) >> ANGLETOFINESHIFT; @@ -187,6 +181,8 @@ void P_PlayerOnSpecialFlat (player_t *player, int floorType); void P_SetSectorFriction (int tag, int amount, bool alterFlag); +void P_GiveSecret(AActor *actor, bool printmessage, bool playsound); + // // getSide() // Will return a side_t* diff --git a/src/p_things.cpp b/src/p_things.cpp index 6622ac0a7..aa48fe18b 100644 --- a/src/p_things.cpp +++ b/src/p_things.cpp @@ -105,15 +105,7 @@ bool P_Thing_Spawn (int tid, AActor *source, int type, angle_t angle, bool fog, { // If this is a monster, subtract it from the total monster // count, because it already added to it during spawning. - if (mobj->CountsAsKill()) - { - level.total_monsters--; - } - // Same, for items - if (mobj->flags & MF_COUNTITEM) - { - level.total_items--; - } + mobj->ClearCounters(); mobj->Destroy (); } } @@ -352,15 +344,7 @@ nolead: mobj->angle = R_PointToAngle2 (mobj->x, mobj->y, targ->x, targ->y); { // If this is a monster, subtract it from the total monster // count, because it already added to it during spawning. - if (mobj->CountsAsKill()) - { - level.total_monsters--; - } - // Same, for items - if (mobj->flags & MF_COUNTITEM) - { - level.total_items--; - } + mobj->ClearCounters(); mobj->Destroy (); } else @@ -418,8 +402,7 @@ void P_RemoveThing(AActor * actor) if (actor->player == NULL || actor != actor->player->mo) { // be friendly to the level statistics. ;) - if (actor->CountsAsKill() && actor->health > 0) level.total_monsters--; - if (actor->flags&MF_COUNTITEM) level.total_items--; + actor->ClearCounters(); actor->Destroy (); } } diff --git a/src/p_udmf.cpp b/src/p_udmf.cpp index 5f2fca941..2dd3c770e 100644 --- a/src/p_udmf.cpp +++ b/src/p_udmf.cpp @@ -599,6 +599,11 @@ public: Flag(th->flags, MTF_STANDSTILL, key); break; + case NAME_Countsecret: + CHECK_N(Zd | Zdt | Va) + Flag(th->flags, MTF_SECRET, key); + break; + default: if (!strnicmp("user_", key.GetChars(), 5)) { diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index b304e638f..1ac84d38a 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -1402,11 +1402,7 @@ static void DoGiveInventory(AActor * receiver, DECLARE_PARAMINFO) item->Amount = amount; } item->flags |= MF_DROPPED; - if (item->flags & MF_COUNTITEM) - { - item->flags&=~MF_COUNTITEM; - level.total_items--; - } + item->ClearCounters(); if (!item->CallTryPickup (receiver)) { item->Destroy (); @@ -1541,7 +1537,7 @@ static bool InitSpawnedItem(AActor *self, AActor *mo, int flags) if (!(flags&SIXF_NOCHECKPOSITION) && !P_TestMobjLocation(mo)) { // The monster is blocked so don't spawn it at all! - if (mo->CountsAsKill()) level.total_monsters--; + mo->ClearCounters(); mo->Destroy(); return false; } @@ -2925,9 +2921,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ChangeFlag) { bool kill_before, kill_after; INTBOOL item_before, item_after; + INTBOOL secret_before, secret_after; kill_before = self->CountsAsKill(); item_before = self->flags & MF_COUNTITEM; + secret_before = self->flags5 & MF5_COUNTSECRET; if (fd->structoffset == -1) { @@ -2953,6 +2951,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ChangeFlag) } kill_after = self->CountsAsKill(); item_after = self->flags & MF_COUNTITEM; + secret_after = self->flags5 & MF5_COUNTSECRET; // Was this monster previously worth a kill but no longer is? // Or vice versa? if (kill_before != kill_after) @@ -2978,6 +2977,18 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ChangeFlag) level.total_items--; } } + // and secretd + if (secret_before != secret_after) + { + if (secret_after) + { // It counts as an secret now. + level.total_secrets++; + } + else + { // It no longer counts as an secret + level.total_secrets--; + } + } } else { diff --git a/src/thingdef/thingdef_data.cpp b/src/thingdef/thingdef_data.cpp index b08e48719..05e5bc3a7 100644 --- a/src/thingdef/thingdef_data.cpp +++ b/src/thingdef/thingdef_data.cpp @@ -185,6 +185,7 @@ static FFlagDef ActorFlags[]= DEFINE_FLAG(MF5, FASTER, AActor, flags5), DEFINE_FLAG(MF5, FASTMELEE, AActor, flags5), DEFINE_FLAG(MF5, NODROPOFF, AActor, flags5), + DEFINE_FLAG(MF5, COUNTSECRET, AActor, flags5), DEFINE_FLAG(MF5, NODAMAGE, AActor, flags5), DEFINE_FLAG(MF5, BLOODSPLATTER, AActor, flags5), DEFINE_FLAG(MF5, OLDRADIUSDMG, AActor, flags5),