- added a ClearCounters function to AActor that handles everything necessary to un-count an item that is not supposed to be counted but has some of the COUNT* flags set.

- merged all places where secrets are credited into one common function.
- added the Doom64 COUNTSECRET actor flag.
- fixed: AInventory::CreateCopy did not clear the COUNTITEM flag.
- fixed: Dropping an item did not increase the item count but the dropped item could still have the COUNTITEM flag. Now this flag gets cleared when the item gets picked up so that dropped items don't count a second time.

SVN r2826 (trunk)
This commit is contained in:
Christoph Oelckers 2010-09-19 00:06:45 +00:00
parent 7b01f7b296
commit df138fe4f9
20 changed files with 137 additions and 100 deletions

View file

@ -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
===============================================================================

View file

@ -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
{

View file

@ -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;

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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++)
{

View file

@ -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 ();
}

View file

@ -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);
}

View file

@ -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 ();

View file

@ -359,6 +359,7 @@ xx(Invisible)
xx(Friend)
xx(Strifeally)
xx(Standing)
xx(Countsecret)
xx(Blocking)
xx(Blockmonsters)

View file

@ -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;
}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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*

View file

@ -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 ();
}
}

View file

@ -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))
{

View file

@ -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
{

View file

@ -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),