2006-02-24 04:48:15 +00:00
|
|
|
/*
|
|
|
|
** Decorations that do special things
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "actor.h"
|
|
|
|
#include "info.h"
|
|
|
|
#include "a_action.h"
|
|
|
|
#include "p_enemy.h"
|
|
|
|
#include "m_random.h"
|
|
|
|
#include "s_sound.h"
|
|
|
|
#include "p_local.h"
|
|
|
|
#include "p_lnspec.h"
|
- Fixed: ActorFlagSetOrReset() wasn't receiving the + or - character from
ParseActorProperties().
- Fixed: The decorate FindFlag() function returned flags from ActorFlags
instead of the passed flags set.
- Fixed: The CHT_CHAINSAW, CHT_POWER, CHT_HEALTH, and CHT_RESSURECT needed
NULL player->mo checks.
- Fixed: The "give all" command didn't give the backpack in Doom, and it
must give the backpack before giving ammo.
- Fixed: P_SetPsprite() must not call the action function if the player is
not attached to an actor. This can happen, for instance, if the level is
destroyed while the player is holding a powered-up Phoenix Rod. As part
of its EndPowerup() function, it sets the psprite to the regular version,
but the player actor has already been destroyed.
- Fixed: FinishThingdef() needs to check for valid names, because weapons
could have inherited valid pointers from their superclass.
- Fixed: fuglyname didn't work.
- Fixed: Redefining $ambient sounds leaked memory.
- Added Jim's crashcatcher.c fix for better shell support.
- VC7.1 seems to have no trouble distinguishing between passing a (const
TypeInfo *) reference to operator<< and the generic, templated (object *)
version, so a few places that can benefit from it now use it. I believe
VC6 had problems with this, which is why I didn't do it all along. The
function's implementation was also moved out of dobject.cpp and into
farchive.cpp.
- Fixed: UnpackPixels() unpacked all chunks in a byte, which is wrong for the
last byte in a row if the image width is not an even multiple of the number
pixels per byte.
- Fixed: P_TranslateLineDef() should only clear monster activation for secret
useable lines, not crossable lines.
- Fixed: Some leftover P_IsHostile() calls still needed to be rewritten.
- Fixed: AWeaponHolder::Serialize() wrote the class type in all circumstances.
SVN r20 (trunk)
2006-03-14 06:11:39 +00:00
|
|
|
#include "a_hexenglobal.h"
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
static FRandom pr_pottery ("PotteryExplode");
|
|
|
|
static FRandom pr_bit ("PotteryChooseBit");
|
|
|
|
static FRandom pr_drip ("CorpseBloodDrip");
|
|
|
|
static FRandom pr_foo ("CorpseExplode");
|
|
|
|
static FRandom pr_leaf ("LeafSpawn");
|
|
|
|
static FRandom pr_leafthrust ("LeafThrust");
|
|
|
|
static FRandom pr_leafcheck ("LeafCheck");
|
|
|
|
static FRandom pr_shroom ("PoisonShroom");
|
|
|
|
static FRandom pr_soaexplode ("SoAExplode");
|
|
|
|
|
|
|
|
// Pottery1 ------------------------------------------------------------------
|
|
|
|
|
|
|
|
void A_PotteryExplode (AActor *);
|
|
|
|
void A_PotteryChooseBit (AActor *);
|
|
|
|
void A_PotteryCheck (AActor *);
|
|
|
|
|
|
|
|
class APottery1 : public AActor
|
|
|
|
{
|
2008-08-08 15:18:23 +00:00
|
|
|
DECLARE_CLASS (APottery1, AActor)
|
2006-02-24 04:48:15 +00:00
|
|
|
public:
|
|
|
|
void HitFloor ();
|
|
|
|
};
|
|
|
|
|
2008-08-08 15:18:23 +00:00
|
|
|
IMPLEMENT_CLASS (APottery1)
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
void APottery1::HitFloor ()
|
|
|
|
{
|
|
|
|
Super::HitFloor ();
|
2006-10-31 14:53:21 +00:00
|
|
|
P_DamageMobj (this, NULL, NULL, 25, NAME_None);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
//
|
|
|
|
// A_PotteryExplode
|
|
|
|
//
|
|
|
|
//============================================================================
|
|
|
|
|
|
|
|
void A_PotteryExplode (AActor *actor)
|
|
|
|
{
|
|
|
|
AActor *mo = NULL;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for(i = (pr_pottery()&3)+3; i; i--)
|
|
|
|
{
|
2008-08-08 15:18:23 +00:00
|
|
|
mo = Spawn ("PotteryBit", actor->x, actor->y, actor->z, ALLOW_REPLACE);
|
2006-02-24 04:48:15 +00:00
|
|
|
mo->SetState (mo->SpawnState + (pr_pottery()%5));
|
|
|
|
if (mo)
|
|
|
|
{
|
|
|
|
mo->momz = ((pr_pottery()&7)+5)*(3*FRACUNIT/4);
|
|
|
|
mo->momx = (pr_pottery.Random2())<<(FRACBITS-6);
|
|
|
|
mo->momy = (pr_pottery.Random2())<<(FRACBITS-6);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
S_Sound (mo, CHAN_BODY, "PotteryExplode", 1, ATTN_NORM);
|
2006-04-16 13:29:50 +00:00
|
|
|
if (actor->args[0]>=0 && actor->args[0]<=255 && SpawnableThings[actor->args[0]])
|
2006-02-24 04:48:15 +00:00
|
|
|
{ // Spawn an item
|
2007-11-08 09:22:06 +00:00
|
|
|
if (!((level.flags & LEVEL_NOMONSTERS) || (dmflags & DF_NO_MONSTERS))
|
2006-02-24 04:48:15 +00:00
|
|
|
|| !(GetDefaultByType (SpawnableThings[actor->args[0]])->flags3 & MF3_ISMONSTER))
|
|
|
|
{ // Only spawn monsters if not -nomonsters
|
|
|
|
Spawn (SpawnableThings[actor->args[0]],
|
2006-07-16 09:10:45 +00:00
|
|
|
actor->x, actor->y, actor->z, ALLOW_REPLACE);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
//
|
|
|
|
// A_PotteryChooseBit
|
|
|
|
//
|
|
|
|
//============================================================================
|
|
|
|
|
|
|
|
void A_PotteryChooseBit (AActor *actor)
|
|
|
|
{
|
2006-10-31 14:53:21 +00:00
|
|
|
actor->SetState (actor->FindState(NAME_Death) + 1 + 2*(pr_bit()%5));
|
2006-02-24 04:48:15 +00:00
|
|
|
actor->tics = 256+(pr_bit()<<1);
|
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
//
|
|
|
|
// A_PotteryCheck
|
|
|
|
//
|
|
|
|
//============================================================================
|
|
|
|
|
|
|
|
void A_PotteryCheck (AActor *actor)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for(i = 0; i < MAXPLAYERS; i++)
|
|
|
|
{
|
|
|
|
if (playeringame[i])
|
|
|
|
{
|
|
|
|
AActor *pmo = players[i].mo;
|
|
|
|
if (P_CheckSight (actor, pmo) && (abs (R_PointToAngle2 (pmo->x,
|
|
|
|
pmo->y, actor->x, actor->y) - pmo->angle) <= ANGLE_45))
|
|
|
|
{ // Previous state (pottery bit waiting state)
|
|
|
|
actor->SetState (actor->state - 1);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Lynched corpse (no heart) ------------------------------------------------
|
|
|
|
|
|
|
|
void A_CorpseBloodDrip (AActor *);
|
|
|
|
|
|
|
|
class AZCorpseLynchedNoHeart : public AActor
|
|
|
|
{
|
2008-08-08 15:18:23 +00:00
|
|
|
DECLARE_CLASS (AZCorpseLynchedNoHeart, AActor)
|
2006-02-24 04:48:15 +00:00
|
|
|
public:
|
|
|
|
void PostBeginPlay ();
|
|
|
|
};
|
|
|
|
|
2008-08-08 15:18:23 +00:00
|
|
|
IMPLEMENT_CLASS (AZCorpseLynchedNoHeart)
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
void AZCorpseLynchedNoHeart::PostBeginPlay ()
|
|
|
|
{
|
|
|
|
Super::PostBeginPlay ();
|
2008-08-08 15:18:23 +00:00
|
|
|
Spawn ("BloodPool", x, y, ONFLOORZ, ALLOW_REPLACE);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
//
|
|
|
|
// A_CorpseBloodDrip
|
|
|
|
//
|
|
|
|
//============================================================================
|
|
|
|
|
|
|
|
void A_CorpseBloodDrip (AActor *actor)
|
|
|
|
{
|
|
|
|
if (pr_drip() <= 128)
|
|
|
|
{
|
2008-08-08 15:18:23 +00:00
|
|
|
Spawn ("CorpseBloodDrip", actor->x, actor->y, actor->z + actor->height/2, ALLOW_REPLACE);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
//
|
|
|
|
// A_CorpseExplode
|
|
|
|
//
|
|
|
|
//============================================================================
|
|
|
|
|
|
|
|
void A_CorpseExplode (AActor *actor)
|
|
|
|
{
|
|
|
|
AActor *mo;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = (pr_foo()&3)+3; i; i--)
|
|
|
|
{
|
2008-08-08 15:18:23 +00:00
|
|
|
mo = Spawn ("CorpseBit", actor->x, actor->y, actor->z, ALLOW_REPLACE);
|
2006-02-24 04:48:15 +00:00
|
|
|
mo->SetState (mo->SpawnState + (pr_foo()%3));
|
|
|
|
if (mo)
|
|
|
|
{
|
|
|
|
mo->momz = ((pr_foo()&7)+5)*(3*FRACUNIT/4);
|
|
|
|
mo->momx = pr_foo.Random2()<<(FRACBITS-6);
|
|
|
|
mo->momy = pr_foo.Random2()<<(FRACBITS-6);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Spawn a skull
|
2008-08-08 15:18:23 +00:00
|
|
|
mo = Spawn ("CorpseBit", actor->x, actor->y, actor->z, ALLOW_REPLACE);
|
2006-02-24 04:48:15 +00:00
|
|
|
mo->SetState (mo->SpawnState + 3);
|
|
|
|
if (mo)
|
|
|
|
{
|
|
|
|
mo->momz = ((pr_foo()&7)+5)*(3*FRACUNIT/4);
|
|
|
|
mo->momx = pr_foo.Random2()<<(FRACBITS-6);
|
|
|
|
mo->momy = pr_foo.Random2()<<(FRACBITS-6);
|
|
|
|
}
|
2008-06-15 02:25:09 +00:00
|
|
|
S_Sound (actor, CHAN_BODY, actor->DeathSound, 1, ATTN_IDLE);
|
2006-02-24 04:48:15 +00:00
|
|
|
actor->Destroy ();
|
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
//
|
|
|
|
// A_LeafSpawn
|
|
|
|
//
|
|
|
|
//============================================================================
|
|
|
|
|
|
|
|
void A_LeafSpawn (AActor *actor)
|
|
|
|
{
|
|
|
|
AActor *mo;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = (pr_leaf()&3)+1; i; i--)
|
|
|
|
{
|
2008-08-08 15:18:23 +00:00
|
|
|
mo = Spawn (pr_leaf()&1 ? PClass::FindClass ("Leaf1") : PClass::FindClass ("Leaf2"),
|
2006-02-24 04:48:15 +00:00
|
|
|
actor->x + (pr_leaf.Random2()<<14),
|
|
|
|
actor->y + (pr_leaf.Random2()<<14),
|
2006-07-16 09:10:45 +00:00
|
|
|
actor->z + (pr_leaf()<<14), ALLOW_REPLACE);
|
2006-02-24 04:48:15 +00:00
|
|
|
if (mo)
|
|
|
|
{
|
|
|
|
P_ThrustMobj (mo, actor->angle, (pr_leaf()<<9)+3*FRACUNIT);
|
|
|
|
mo->target = actor;
|
|
|
|
mo->special1 = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
//
|
|
|
|
// A_LeafThrust
|
|
|
|
//
|
|
|
|
//============================================================================
|
|
|
|
|
|
|
|
void A_LeafThrust (AActor *actor)
|
|
|
|
{
|
|
|
|
if (pr_leafthrust() <= 96)
|
|
|
|
{
|
|
|
|
actor->momz += (pr_leafthrust()<<9)+FRACUNIT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
//
|
|
|
|
// A_LeafCheck
|
|
|
|
//
|
|
|
|
//============================================================================
|
|
|
|
|
|
|
|
void A_LeafCheck (AActor *actor)
|
|
|
|
{
|
|
|
|
actor->special1++;
|
|
|
|
if (actor->special1 >= 20)
|
|
|
|
{
|
|
|
|
actor->SetState (NULL);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
angle_t ang = actor->target ? actor->target->angle : actor->angle;
|
|
|
|
if (pr_leafcheck() > 64)
|
|
|
|
{
|
|
|
|
if (!actor->momx && !actor->momy)
|
|
|
|
{
|
|
|
|
P_ThrustMobj (actor, ang, (pr_leafcheck()<<9)+FRACUNIT);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
actor->SetState (actor->SpawnState + 7);
|
|
|
|
actor->momz = (pr_leafcheck()<<9)+FRACUNIT;
|
|
|
|
P_ThrustMobj (actor, ang, (pr_leafcheck()<<9)+2*FRACUNIT);
|
|
|
|
actor->flags |= MF_MISSILE;
|
|
|
|
}
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
//
|
|
|
|
// A_PoisonShroom
|
|
|
|
//
|
|
|
|
//===========================================================================
|
|
|
|
|
|
|
|
void A_PoisonShroom (AActor *actor)
|
|
|
|
{
|
|
|
|
actor->tics = 128+(pr_shroom()<<1);
|
|
|
|
}
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
//
|
|
|
|
// A_SoAExplode - Suit of Armor Explode
|
|
|
|
//
|
|
|
|
//===========================================================================
|
|
|
|
|
|
|
|
void A_SoAExplode (AActor *actor)
|
|
|
|
{
|
|
|
|
AActor *mo;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < 10; i++)
|
|
|
|
{
|
2008-08-08 15:18:23 +00:00
|
|
|
mo = Spawn ("ZArmorChunk", actor->x+((pr_soaexplode()-128)<<12),
|
2006-02-24 04:48:15 +00:00
|
|
|
actor->y+((pr_soaexplode()-128)<<12),
|
2006-07-16 09:10:45 +00:00
|
|
|
actor->z+(pr_soaexplode()*actor->height/256), ALLOW_REPLACE);
|
2006-02-24 04:48:15 +00:00
|
|
|
mo->SetState (mo->SpawnState + i);
|
|
|
|
if (mo)
|
|
|
|
{
|
|
|
|
mo->momz = ((pr_soaexplode()&7)+5)*FRACUNIT;
|
|
|
|
mo->momx = pr_soaexplode.Random2()<<(FRACBITS-6);
|
|
|
|
mo->momy = pr_soaexplode.Random2()<<(FRACBITS-6);
|
|
|
|
}
|
|
|
|
}
|
2006-04-16 13:29:50 +00:00
|
|
|
if (actor->args[0]>=0 && actor->args[0]<=255 && SpawnableThings[actor->args[0]])
|
2006-02-24 04:48:15 +00:00
|
|
|
{ // Spawn an item
|
2007-11-08 09:22:06 +00:00
|
|
|
if (!((level.flags & LEVEL_NOMONSTERS) || (dmflags & DF_NO_MONSTERS))
|
2006-02-24 04:48:15 +00:00
|
|
|
|| !(GetDefaultByType (SpawnableThings[actor->args[0]])->flags3 & MF3_ISMONSTER))
|
|
|
|
{ // Only spawn monsters if not -nomonsters
|
|
|
|
Spawn (SpawnableThings[actor->args[0]],
|
2006-07-16 09:10:45 +00:00
|
|
|
actor->x, actor->y, actor->z, ALLOW_REPLACE);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
}
|
2008-06-15 02:25:09 +00:00
|
|
|
S_Sound (actor, CHAN_BODY, actor->DeathSound, 1, ATTN_NORM);
|
2006-02-24 04:48:15 +00:00
|
|
|
actor->Destroy ();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Bell ---------------------------------------------------------------------
|
|
|
|
|
|
|
|
void A_BellReset1 (AActor *);
|
|
|
|
void A_BellReset2 (AActor *);
|
|
|
|
|
|
|
|
class AZBell : public AActor
|
|
|
|
{
|
2008-08-08 15:18:23 +00:00
|
|
|
DECLARE_CLASS (AZBell, AActor)
|
2006-02-24 04:48:15 +00:00
|
|
|
public:
|
|
|
|
void Activate (AActor *activator);
|
|
|
|
};
|
|
|
|
|
2008-08-08 15:18:23 +00:00
|
|
|
IMPLEMENT_CLASS (AZBell)
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
void AZBell::Activate (AActor *activator)
|
|
|
|
{
|
|
|
|
if (health > 0)
|
|
|
|
{
|
2006-10-31 14:53:21 +00:00
|
|
|
P_DamageMobj (this, activator, activator, 10, NAME_Melee); // 'ring' the bell
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
//
|
|
|
|
// A_BellReset1
|
|
|
|
//
|
|
|
|
//===========================================================================
|
|
|
|
|
|
|
|
void A_BellReset1 (AActor *actor)
|
|
|
|
{
|
|
|
|
actor->flags |= MF_NOGRAVITY;
|
|
|
|
actor->height <<= 2;
|
|
|
|
if (actor->special)
|
|
|
|
{ // Initiate death action
|
|
|
|
LineSpecials[actor->special] (NULL, NULL, false, actor->args[0],
|
|
|
|
actor->args[1], actor->args[2], actor->args[3], actor->args[4]);
|
|
|
|
actor->special = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
//
|
|
|
|
// A_BellReset2
|
|
|
|
//
|
|
|
|
//===========================================================================
|
|
|
|
|
|
|
|
void A_BellReset2 (AActor *actor)
|
|
|
|
{
|
|
|
|
actor->flags |= MF_SHOOTABLE;
|
|
|
|
actor->flags &= ~MF_CORPSE;
|
|
|
|
actor->health = 5;
|
|
|
|
}
|
|
|
|
|