mirror of
https://github.com/ZDoom/gzdoom.git
synced 2025-01-31 05:40:44 +00:00
- added RandomSpawner update from Gez's experimental build.
- added thing activation types for BUMPSPECIAL and USESPECIAL. Also added a new ClearSpecial flag to the activation type. - added MBF's code for dogs jumping down, controlled by the MF6_JUMPDOWN flag. SVN r1835 (trunk)
This commit is contained in:
parent
f2a122e076
commit
5910d90a19
9 changed files with 224 additions and 83 deletions
|
@ -1,4 +1,9 @@
|
||||||
September 15, 2009 (Changes by Graf Zahl)
|
September 15, 2009 (Changes by Graf Zahl)
|
||||||
|
- added RandomSpawner update from Gez's experimental build.
|
||||||
|
- added thing activation types for BUMPSPECIAL and USESPECIAL. Also added
|
||||||
|
a new ClearSpecial flag to the activation type.
|
||||||
|
- added MBF's code for dogs jumping down, controlled by the MF6_JUMPDOWN
|
||||||
|
flag.
|
||||||
- fixed: pr_bounce was declared statically in o_mobj.cpp and redeclared externally
|
- fixed: pr_bounce was declared statically in o_mobj.cpp and redeclared externally
|
||||||
in p_map.cpp resulting in a CRC conflict.
|
in p_map.cpp resulting in a CRC conflict.
|
||||||
- fixed: The Dehacked flags parser fix from May 31 (r1624) was undone by
|
- fixed: The Dehacked flags parser fix from May 31 (r1624) was undone by
|
||||||
|
|
|
@ -441,6 +441,7 @@ enum EThingSpecialActivationType
|
||||||
THINGSPEC_TriggerTargets = 4, // The trigger changes its target to the thing
|
THINGSPEC_TriggerTargets = 4, // The trigger changes its target to the thing
|
||||||
THINGSPEC_MonsterTrigger = 8, // The thing can be triggered by a monster
|
THINGSPEC_MonsterTrigger = 8, // The thing can be triggered by a monster
|
||||||
THINGSPEC_MissileTrigger = 16, // The thing can be triggered by a projectile
|
THINGSPEC_MissileTrigger = 16, // The thing can be triggered by a projectile
|
||||||
|
THINGSPEC_ClearSpecial = 32, // Clears special after successful activation
|
||||||
};
|
};
|
||||||
|
|
||||||
// [RH] Like msecnode_t, but for the blockmap
|
// [RH] Like msecnode_t, but for the blockmap
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
/*
|
/*
|
||||||
** a_randomspawner.cpp
|
** a_randomspawner.cpp
|
||||||
** A thing that randomly spawns one item in a list of many, before disappearing.
|
** A thing that randomly spawns one item in a list of many, before disappearing.
|
||||||
|
** bouncecount is used to keep track of recursions (so as to prevent infinite loops).
|
||||||
|
** Species is used to store the index of the spawned actor's name.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "actor.h"
|
#include "actor.h"
|
||||||
|
@ -21,14 +23,16 @@ class ARandomSpawner : public AActor
|
||||||
{
|
{
|
||||||
DECLARE_CLASS (ARandomSpawner, AActor)
|
DECLARE_CLASS (ARandomSpawner, AActor)
|
||||||
|
|
||||||
void PostBeginPlay()
|
// To handle "RandomSpawning" missiles, the code has to be split in two parts.
|
||||||
|
// If the following code is not done in BeginPlay, missiles will use the
|
||||||
|
// random spawner's velocity (0...) instead of their own.
|
||||||
|
void BeginPlay()
|
||||||
{
|
{
|
||||||
AActor *newmobj = NULL;
|
|
||||||
FDropItem *di; // di will be our drop item list iterator
|
FDropItem *di; // di will be our drop item list iterator
|
||||||
FDropItem *drop; // while drop stays as the reference point.
|
FDropItem *drop; // while drop stays as the reference point.
|
||||||
int n=0;
|
int n=0;
|
||||||
|
|
||||||
Super::PostBeginPlay();
|
Super::BeginPlay();
|
||||||
drop = di = GetDropItems();
|
drop = di = GetDropItems();
|
||||||
if (di != NULL)
|
if (di != NULL)
|
||||||
{
|
{
|
||||||
|
@ -46,7 +50,7 @@ class ARandomSpawner : public AActor
|
||||||
// Take a random number...
|
// Take a random number...
|
||||||
n = pr_randomspawn(n);
|
n = pr_randomspawn(n);
|
||||||
// And iterate in the array up to the random number chosen.
|
// And iterate in the array up to the random number chosen.
|
||||||
while (n > 0)
|
while (n > -1)
|
||||||
{
|
{
|
||||||
if (di->Name != NAME_None)
|
if (di->Name != NAME_None)
|
||||||
{
|
{
|
||||||
|
@ -55,64 +59,109 @@ class ARandomSpawner : public AActor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// So now we can spawn the dropped item.
|
// So now we can spawn the dropped item.
|
||||||
if (special1 >= MAX_RANDOMSPAWNERS_RECURSION) // Prevents infinite recursions
|
if (bouncecount >= MAX_RANDOMSPAWNERS_RECURSION) // Prevents infinite recursions
|
||||||
|
{
|
||||||
Spawn("Unknown", x, y, z, NO_REPLACE); // Show that there's a problem.
|
Spawn("Unknown", x, y, z, NO_REPLACE); // Show that there's a problem.
|
||||||
|
Destroy(); return;
|
||||||
|
}
|
||||||
else if (pr_randomspawn() <= di->probability) // prob 255 = always spawn, prob 0 = never spawn.
|
else if (pr_randomspawn() <= di->probability) // prob 255 = always spawn, prob 0 = never spawn.
|
||||||
{
|
{
|
||||||
newmobj = Spawn(di->Name, x, y, z, ALLOW_REPLACE);
|
// Handle replacement here so as to get the proper speed and flags for missiles
|
||||||
// copy everything relevant
|
const PClass * cls; PClass * rep;
|
||||||
newmobj->SpawnAngle = newmobj->angle = angle;
|
cls = PClass::FindClass(di->Name);
|
||||||
newmobj->special = special;
|
if (cls) rep = cls->ActorInfo->GetReplacement()->Class;
|
||||||
newmobj->args[0] = args[0];
|
if (rep) cls = rep;
|
||||||
newmobj->args[1] = args[1];
|
if (cls)
|
||||||
newmobj->args[2] = args[2];
|
|
||||||
newmobj->args[3] = args[3];
|
|
||||||
newmobj->args[4] = args[4];
|
|
||||||
newmobj->SpawnFlags = SpawnFlags;
|
|
||||||
newmobj->HandleSpawnFlags();
|
|
||||||
newmobj->tid = tid;
|
|
||||||
newmobj->AddToHash();
|
|
||||||
newmobj->velx = velx;
|
|
||||||
newmobj->vely = vely;
|
|
||||||
newmobj->velz = velz;
|
|
||||||
newmobj->master = master; // For things such as DamageMaster/DamageChildren, transfer mastery.
|
|
||||||
newmobj->target = target;
|
|
||||||
newmobj->tracer = tracer;
|
|
||||||
newmobj->CopyFriendliness(this, false);
|
|
||||||
if (!(flags & MF_DROPPED)) newmobj->flags &= ~MF_DROPPED;
|
|
||||||
|
|
||||||
// Handle special altitude flags
|
|
||||||
if (newmobj->flags & MF_SPAWNCEILING)
|
|
||||||
{
|
{
|
||||||
newmobj->z = newmobj->ceilingz - newmobj->height;
|
Species = cls->TypeName;
|
||||||
|
AActor * defmobj = GetDefaultByType(cls);
|
||||||
|
this->Speed = defmobj->Speed;
|
||||||
|
this->flags |= (defmobj->flags & MF_MISSILE);
|
||||||
|
this->flags2 |= (defmobj->flags2 & MF2_SEEKERMISSILE);
|
||||||
|
this->flags4 |= (defmobj->flags4 & MF4_SPECTRAL);
|
||||||
}
|
}
|
||||||
else if (newmobj->flags2 & MF2_SPAWNFLOAT)
|
else Species = NAME_None;
|
||||||
{
|
|
||||||
fixed_t space = newmobj->ceilingz - newmobj->height - newmobj->floorz;
|
|
||||||
if (space > 48*FRACUNIT)
|
|
||||||
{
|
|
||||||
space -= 40*FRACUNIT;
|
|
||||||
newmobj->z = MulScale8 (space, pr_randomspawn()) + newmobj->floorz + 40*FRACUNIT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Special1 is used to count how many recursions we're in.
|
|
||||||
if (newmobj->IsKindOf(PClass::FindClass("RandomSpawner")))
|
|
||||||
newmobj->special1 = ++special1;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((newmobj != NULL) && ((newmobj->flags4 & MF4_BOSSDEATH) || (newmobj->flags2 & MF2_BOSS)))
|
}
|
||||||
this->target = newmobj; // If the spawned actor has either of those flags, it's a boss.
|
|
||||||
|
// The second half of random spawning. Now that the spawner is initialized, the
|
||||||
|
// real actor can be created. If the following code were in BeginPlay instead,
|
||||||
|
// missiles would not have yet obtained certain information that is absolutely
|
||||||
|
// necessary to them -- such as their source and destination.
|
||||||
|
void PostBeginPlay()
|
||||||
|
{
|
||||||
|
AActor * newmobj = NULL;
|
||||||
|
bool boss = false;
|
||||||
|
if (Species == NAME_None) { Destroy(); return; }
|
||||||
|
const PClass * cls = PClass::FindClass(Species);
|
||||||
|
if (this->flags & MF_MISSILE && target && target->target) // Attempting to spawn a missile.
|
||||||
|
{
|
||||||
|
if ((tracer == NULL) && (flags2 & MF2_SEEKERMISSILE)) tracer = target->target;
|
||||||
|
newmobj = P_SpawnMissileXYZ(x, y, z, target, target->target, cls, false);
|
||||||
|
}
|
||||||
|
else newmobj = Spawn(cls, x, y, z, NO_REPLACE);
|
||||||
|
if (newmobj != NULL)
|
||||||
|
{
|
||||||
|
// copy everything relevant
|
||||||
|
newmobj->SpawnAngle = newmobj->angle = angle;
|
||||||
|
newmobj->special = special;
|
||||||
|
newmobj->args[0] = args[0];
|
||||||
|
newmobj->args[1] = args[1];
|
||||||
|
newmobj->args[2] = args[2];
|
||||||
|
newmobj->args[3] = args[3];
|
||||||
|
newmobj->args[4] = args[4];
|
||||||
|
newmobj->SpawnFlags = SpawnFlags;
|
||||||
|
newmobj->HandleSpawnFlags();
|
||||||
|
newmobj->tid = tid;
|
||||||
|
newmobj->AddToHash();
|
||||||
|
newmobj->velx = velx;
|
||||||
|
newmobj->vely = vely;
|
||||||
|
newmobj->velz = velz;
|
||||||
|
newmobj->master = master; // For things such as DamageMaster/DamageChildren, transfer mastery.
|
||||||
|
newmobj->target = target;
|
||||||
|
newmobj->tracer = tracer;
|
||||||
|
newmobj->CopyFriendliness(this, false);
|
||||||
|
// This handles things such as projectiles with the MF4_SPECTRAL flag that have
|
||||||
|
// a health set to -2 after spawning, for internal reasons.
|
||||||
|
if (health != SpawnHealth()) newmobj->health = health;
|
||||||
|
if (!(flags & MF_DROPPED)) newmobj->flags &= ~MF_DROPPED;
|
||||||
|
// Handle special altitude flags
|
||||||
|
if (newmobj->flags & MF_SPAWNCEILING)
|
||||||
|
{
|
||||||
|
newmobj->z = newmobj->ceilingz - newmobj->height;
|
||||||
|
}
|
||||||
|
else if (newmobj->flags2 & MF2_SPAWNFLOAT)
|
||||||
|
{
|
||||||
|
fixed_t space = newmobj->ceilingz - newmobj->height - newmobj->floorz;
|
||||||
|
if (space > 48*FRACUNIT)
|
||||||
|
{
|
||||||
|
space -= 40*FRACUNIT;
|
||||||
|
newmobj->z = MulScale8 (space, pr_randomspawn()) + newmobj->floorz + 40*FRACUNIT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (newmobj->flags & MF_MISSILE)
|
||||||
|
P_CheckMissileSpawn(newmobj);
|
||||||
|
// Bouncecount is used to count how many recursions we're in.
|
||||||
|
if (newmobj->IsKindOf(PClass::FindClass("RandomSpawner")))
|
||||||
|
newmobj->bouncecount = ++bouncecount;
|
||||||
|
// If the spawned actor has either of those flags, it's a boss.
|
||||||
|
if ((newmobj->flags4 & MF4_BOSSDEATH) || (newmobj->flags2 & MF2_BOSS))
|
||||||
|
boss = true;
|
||||||
|
// If a replaced actor has either of those same flags, it's also a boss.
|
||||||
|
AActor * rep = GetDefaultByType(GetClass()->ActorInfo->GetReplacee()->Class);
|
||||||
|
if (rep && (rep->flags4 & MF4_BOSSDEATH) || (rep->flags2 & MF2_BOSS))
|
||||||
|
boss = true;
|
||||||
|
}
|
||||||
|
if (boss) this->tracer = newmobj;
|
||||||
else Destroy(); // "else" because a boss-replacing spawner must wait until it can call A_BossDeath.
|
else Destroy(); // "else" because a boss-replacing spawner must wait until it can call A_BossDeath.
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tick() // This function is needed for handling boss replacers
|
void Tick() // This function is needed for handling boss replacers
|
||||||
{
|
{
|
||||||
Super::Tick();
|
Super::Tick();
|
||||||
if (target == NULL || target->health <= 0)
|
if (tracer == NULL || tracer->health <= 0)
|
||||||
{
|
{
|
||||||
health = 0;
|
|
||||||
CALL_ACTION(A_BossDeath, this);
|
CALL_ACTION(A_BossDeath, this);
|
||||||
Destroy();
|
Destroy();
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,6 +61,7 @@ static FRandom pr_dropitem ("DropItem");
|
||||||
static FRandom pr_look2 ("LookyLooky");
|
static FRandom pr_look2 ("LookyLooky");
|
||||||
static FRandom pr_look3 ("IGotHooky");
|
static FRandom pr_look3 ("IGotHooky");
|
||||||
static FRandom pr_slook ("SlooK");
|
static FRandom pr_slook ("SlooK");
|
||||||
|
static FRandom pr_dropoff ("Dropoff");
|
||||||
|
|
||||||
static FRandom pr_skiptarget("SkipTarget");
|
static FRandom pr_skiptarget("SkipTarget");
|
||||||
|
|
||||||
|
@ -380,6 +381,7 @@ bool P_Move (AActor *actor)
|
||||||
int speed = actor->Speed;
|
int speed = actor->Speed;
|
||||||
int movefactor = ORIG_FRICTION_FACTOR;
|
int movefactor = ORIG_FRICTION_FACTOR;
|
||||||
int friction = ORIG_FRICTION;
|
int friction = ORIG_FRICTION;
|
||||||
|
int dropoff = 0;
|
||||||
|
|
||||||
if (actor->flags2 & MF2_BLASTED)
|
if (actor->flags2 & MF2_BLASTED)
|
||||||
{
|
{
|
||||||
|
@ -410,23 +412,18 @@ bool P_Move (AActor *actor)
|
||||||
if ((unsigned)actor->movedir >= 8)
|
if ((unsigned)actor->movedir >= 8)
|
||||||
I_Error ("Weird actor->movedir!");
|
I_Error ("Weird actor->movedir!");
|
||||||
|
|
||||||
speed = actor->Speed;
|
|
||||||
|
|
||||||
#if 0 // todo
|
|
||||||
|
|
||||||
// killough 10/98: allow dogs to drop off of taller ledges sometimes.
|
// killough 10/98: allow dogs to drop off of taller ledges sometimes.
|
||||||
// dropoff==1 means always allow it, dropoff==2 means only up to 128 high,
|
// dropoff==1 means always allow it, dropoff==2 means only up to 128 high,
|
||||||
// and only if the target is immediately on the other side of the line.
|
// and only if the target is immediately on the other side of the line.
|
||||||
|
AActor *target = actor->target;
|
||||||
|
|
||||||
if (actor->flags6 & MF6_JUMPDOWN && target &&
|
if ((actor->flags6 & MF6_JUMPDOWN) && target &&
|
||||||
!(target->IsFriend(actor)) &&
|
!(target->IsFriend(actor)) &&
|
||||||
P_AproxDistance(actor->x - target->x,
|
P_AproxDistance(actor->x - target->x, actor->y - target->y) < FRACUNIT*144 &&
|
||||||
actor->y - target->y) < FRACUNIT*144 &&
|
pr_dropoff() < 235)
|
||||||
P_Random(pr_dropoff) < 235)
|
|
||||||
{
|
{
|
||||||
dropoff = 2;
|
dropoff = 2;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
// [RH] I'm not so sure this is such a good idea
|
// [RH] I'm not so sure this is such a good idea
|
||||||
// [GZ] That's why it's compat-optioned.
|
// [GZ] That's why it's compat-optioned.
|
||||||
|
@ -479,12 +476,12 @@ bool P_Move (AActor *actor)
|
||||||
try_ok = true;
|
try_ok = true;
|
||||||
for(int i=1; i < steps; i++)
|
for(int i=1; i < steps; i++)
|
||||||
{
|
{
|
||||||
try_ok = P_TryMove(actor, origx + Scale(deltax, i, steps), origy + Scale(deltay, i, steps), false, false, tm);
|
try_ok = P_TryMove(actor, origx + Scale(deltax, i, steps), origy + Scale(deltay, i, steps), dropoff, false, tm);
|
||||||
if (!try_ok) break;
|
if (!try_ok) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// killough 3/15/98: don't jump over dropoffs:
|
// killough 3/15/98: don't jump over dropoffs:
|
||||||
if (try_ok) try_ok = P_TryMove (actor, tryx, tryy, false, false, tm);
|
if (try_ok) try_ok = P_TryMove (actor, tryx, tryy, dropoff, false, tm);
|
||||||
|
|
||||||
// [GrafZahl] Interpolating monster movement as it is done here just looks bad
|
// [GrafZahl] Interpolating monster movement as it is done here just looks bad
|
||||||
// so make it switchable!
|
// so make it switchable!
|
||||||
|
|
|
@ -377,8 +377,8 @@ bool P_CheckPosition (AActor *thing, fixed_t x, fixed_t y, FCheckPosition &tm);
|
||||||
bool P_CheckPosition (AActor *thing, fixed_t x, fixed_t y);
|
bool P_CheckPosition (AActor *thing, fixed_t x, fixed_t y);
|
||||||
AActor *P_CheckOnmobj (AActor *thing);
|
AActor *P_CheckOnmobj (AActor *thing);
|
||||||
void P_FakeZMovement (AActor *mo);
|
void P_FakeZMovement (AActor *mo);
|
||||||
bool P_TryMove (AActor* thing, fixed_t x, fixed_t y, bool dropoff, const secplane_t * onfloor, FCheckPosition &tm);
|
bool P_TryMove (AActor* thing, fixed_t x, fixed_t y, int dropoff, const secplane_t * onfloor, FCheckPosition &tm);
|
||||||
bool P_TryMove (AActor* thing, fixed_t x, fixed_t y, bool dropoff, const secplane_t * onfloor = NULL);
|
bool P_TryMove (AActor* thing, fixed_t x, fixed_t y, int dropoff, const secplane_t * onfloor = NULL);
|
||||||
bool P_CheckMove(AActor *thing, fixed_t x, fixed_t y);
|
bool P_CheckMove(AActor *thing, fixed_t x, fixed_t y);
|
||||||
void P_ApplyTorque(AActor *mo);
|
void P_ApplyTorque(AActor *mo);
|
||||||
bool P_TeleportMove (AActor* thing, fixed_t x, fixed_t y, fixed_t z, bool telefrag); // [RH] Added z and telefrag parameters
|
bool P_TeleportMove (AActor* thing, fixed_t x, fixed_t y, fixed_t z, bool telefrag); // [RH] Added z and telefrag parameters
|
||||||
|
|
|
@ -834,6 +834,29 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm)
|
||||||
P_DamageMobj (thing, NULL, NULL, thing->health, NAME_None, DMG_FORCED); // kill object
|
P_DamageMobj (thing, NULL, NULL, thing->health, NAME_None, DMG_FORCED); // kill object
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check for MF6_BUMPSPECIAL
|
||||||
|
// By default, only players can activate things by bumping into them
|
||||||
|
if ((thing->flags6 & MF6_BUMPSPECIAL))
|
||||||
|
{
|
||||||
|
if (((tm.thing->player != NULL)
|
||||||
|
|| ((thing->activationtype & THINGSPEC_MonsterTrigger) && (thing->flags3 & MF3_ISMONSTER))
|
||||||
|
|| ((thing->activationtype & THINGSPEC_MissileTrigger) && (thing->flags & MF_MISSILE))
|
||||||
|
))
|
||||||
|
{ // Target switching mechanism
|
||||||
|
if (thing->activationtype & THINGSPEC_ThingTargets) thing->target = tm.thing;
|
||||||
|
if (thing->activationtype & THINGSPEC_TriggerTargets) tm.thing->target = thing;
|
||||||
|
// Run the special
|
||||||
|
|
||||||
|
int res = LineSpecials[thing->special] (NULL,
|
||||||
|
((thing->activationtype & THINGSPEC_ThingActs) ? thing : tm.thing), // Who triggers?
|
||||||
|
false, thing->args[0], thing->args[1], thing->args[2], thing->args[3], thing->args[4]);
|
||||||
|
|
||||||
|
if (thing->activationtype & THINGSPEC_ClearSpecial && res) thing->special = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Check for skulls slamming into things
|
// Check for skulls slamming into things
|
||||||
if (tm.thing->flags & MF_SKULLFLY)
|
if (tm.thing->flags & MF_SKULLFLY)
|
||||||
{
|
{
|
||||||
|
@ -860,13 +883,6 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Check for players touching a thing with MF6_BUMPSPECIAL
|
|
||||||
// A blind recreation of what the Skulltag code is probably like.
|
|
||||||
if (tm.thing->player && (thing->flags6 & MF6_BUMPSPECIAL) && thing->special)
|
|
||||||
{
|
|
||||||
LineSpecials[thing->special] (NULL, tm.thing, false, thing->args[0],
|
|
||||||
thing->args[1], thing->args[2], thing->args[3], thing->args[4]);
|
|
||||||
}
|
|
||||||
// Check for missile or non-solid MBF bouncer
|
// Check for missile or non-solid MBF bouncer
|
||||||
if (tm.thing->flags & MF_MISSILE || ((tm.thing->BounceFlags & BOUNCE_MBF) && !(tm.thing->flags & MF_SOLID)))
|
if (tm.thing->flags & MF_MISSILE || ((tm.thing->BounceFlags & BOUNCE_MBF) && !(tm.thing->flags & MF_SOLID)))
|
||||||
{
|
{
|
||||||
|
@ -1537,7 +1553,7 @@ static void CheckForPushSpecial (line_t *line, int side, AActor *mobj)
|
||||||
// crossing special lines unless MF_TELEPORT is set.
|
// crossing special lines unless MF_TELEPORT is set.
|
||||||
//
|
//
|
||||||
bool P_TryMove (AActor *thing, fixed_t x, fixed_t y,
|
bool P_TryMove (AActor *thing, fixed_t x, fixed_t y,
|
||||||
bool dropoff, // killough 3/15/98: allow dropoff as option
|
int dropoff, // killough 3/15/98: allow dropoff as option
|
||||||
const secplane_t *onfloor, // [RH] Let P_TryMove keep the thing on the floor
|
const secplane_t *onfloor, // [RH] Let P_TryMove keep the thing on the floor
|
||||||
FCheckPosition &tm)
|
FCheckPosition &tm)
|
||||||
{
|
{
|
||||||
|
@ -1667,6 +1683,13 @@ bool P_TryMove (AActor *thing, fixed_t x, fixed_t y,
|
||||||
dropoff = false;
|
dropoff = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dropoff==2 && // large jump down (e.g. dogs)
|
||||||
|
(tm.floorz-tm.dropoffz > 128*FRACUNIT || thing->target == NULL || thing->target->z >tm.dropoffz))
|
||||||
|
{
|
||||||
|
dropoff = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// killough 3/15/98: Allow certain objects to drop off
|
// killough 3/15/98: Allow certain objects to drop off
|
||||||
if ((!dropoff && !(thing->flags & (MF_DROPOFF|MF_FLOAT|MF_MISSILE))) || (thing->flags5&MF5_NODROPOFF))
|
if ((!dropoff && !(thing->flags & (MF_DROPOFF|MF_FLOAT|MF_MISSILE))) || (thing->flags5&MF5_NODROPOFF))
|
||||||
{
|
{
|
||||||
|
@ -1894,7 +1917,7 @@ pushline:
|
||||||
}
|
}
|
||||||
|
|
||||||
bool P_TryMove (AActor *thing, fixed_t x, fixed_t y,
|
bool P_TryMove (AActor *thing, fixed_t x, fixed_t y,
|
||||||
bool dropoff, // killough 3/15/98: allow dropoff as option
|
int dropoff, // killough 3/15/98: allow dropoff as option
|
||||||
const secplane_t *onfloor) // [RH] Let P_TryMove keep the thing on the floor
|
const secplane_t *onfloor) // [RH] Let P_TryMove keep the thing on the floor
|
||||||
{
|
{
|
||||||
FCheckPosition tm;
|
FCheckPosition tm;
|
||||||
|
@ -3745,12 +3768,20 @@ bool P_UseTraverse(AActor *usething, fixed_t endx, fixed_t endy, bool &foundline
|
||||||
// Check thing
|
// Check thing
|
||||||
|
|
||||||
// Check for puzzle item use or USESPECIAL flag
|
// Check for puzzle item use or USESPECIAL flag
|
||||||
|
// Extended to use the same activationtype mechanism as BUMPSPECIAL does
|
||||||
if (in->d.thing->flags5 & MF5_USESPECIAL || in->d.thing->special == UsePuzzleItem)
|
if (in->d.thing->flags5 & MF5_USESPECIAL || in->d.thing->special == UsePuzzleItem)
|
||||||
{
|
{ // Target switching mechanism
|
||||||
if (LineSpecials[in->d.thing->special] (NULL, usething, false,
|
if (in->d.thing->activationtype & THINGSPEC_ThingTargets) in->d.thing->target = usething;
|
||||||
|
if (in->d.thing->activationtype & THINGSPEC_TriggerTargets) usething->target = in->d.thing;
|
||||||
|
// Run the special
|
||||||
|
if (LineSpecials[in->d.thing->special] (NULL, // Who triggers?
|
||||||
|
((in->d.thing->activationtype & THINGSPEC_ThingActs) ? in->d.thing : usething), false,
|
||||||
in->d.thing->args[0], in->d.thing->args[1], in->d.thing->args[2],
|
in->d.thing->args[0], in->d.thing->args[1], in->d.thing->args[2],
|
||||||
in->d.thing->args[3], in->d.thing->args[4]))
|
in->d.thing->args[3], in->d.thing->args[4]))
|
||||||
|
{
|
||||||
|
if (in->d.thing->activationtype & THINGSPEC_ClearSpecial) in->d.thing->special = 0;
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Dead things can't talk.
|
// Dead things can't talk.
|
||||||
if (in->d.thing->health <= 0)
|
if (in->d.thing->health <= 0)
|
||||||
|
|
|
@ -395,18 +395,14 @@ void HandleActorFlag(FScanner &sc, Baggage &bag, const char *part1, const char *
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
static int ParseMorphStyle (FScanner &sc)
|
struct FParseValue
|
||||||
{
|
{
|
||||||
static const char * morphstyles[]={
|
const char *Name;
|
||||||
"MRF_ADDSTAMINA", "MRF_FULLHEALTH", "MRF_UNDOBYTOMEOFPOWER", "MRF_UNDOBYCHAOSDEVICE",
|
int Flag;
|
||||||
"MRF_FAILNOTELEFRAG", "MRF_FAILNOLAUGH", "MRF_WHENINVULNERABLE", "MRF_LOSEACTUALWEAPON",
|
};
|
||||||
"MRF_NEWTIDBEHAVIOUR", "MRF_UNDOBYDEATH", "MRF_UNDOBYDEATHFORCED", "MRF_UNDOBYDEATHSAVES", NULL};
|
|
||||||
|
|
||||||
static const int morphstyle_values[]={
|
|
||||||
MORPH_ADDSTAMINA, MORPH_FULLHEALTH, MORPH_UNDOBYTOMEOFPOWER, MORPH_UNDOBYCHAOSDEVICE,
|
|
||||||
MORPH_FAILNOTELEFRAG, MORPH_FAILNOLAUGH, MORPH_WHENINVULNERABLE, MORPH_LOSEACTUALWEAPON,
|
|
||||||
MORPH_NEWTIDBEHAVIOUR, MORPH_UNDOBYDEATH, MORPH_UNDOBYDEATHFORCED, MORPH_UNDOBYDEATHSAVES};
|
|
||||||
|
|
||||||
|
int ParseFlagExpressionString(FScanner &sc, const FParseValue *vals)
|
||||||
|
{
|
||||||
// May be given flags by number...
|
// May be given flags by number...
|
||||||
if (sc.CheckNumber())
|
if (sc.CheckNumber())
|
||||||
{
|
{
|
||||||
|
@ -422,7 +418,7 @@ static int ParseMorphStyle (FScanner &sc)
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
sc.MustGetString();
|
sc.MustGetString();
|
||||||
style |= morphstyle_values[sc.MustMatchString(morphstyles)];
|
style |= vals[sc.MustMatchString(&vals->Name, sizeof (*vals))].Flag;
|
||||||
}
|
}
|
||||||
while (sc.CheckString("|"));
|
while (sc.CheckString("|"));
|
||||||
if (gotparen)
|
if (gotparen)
|
||||||
|
@ -433,6 +429,46 @@ static int ParseMorphStyle (FScanner &sc)
|
||||||
return style;
|
return style;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int ParseMorphStyle (FScanner &sc)
|
||||||
|
{
|
||||||
|
static const FParseValue morphstyles[]={
|
||||||
|
{ "MRF_ADDSTAMINA", MORPH_ADDSTAMINA},
|
||||||
|
{ "MRF_FULLHEALTH", MORPH_FULLHEALTH},
|
||||||
|
{ "MRF_UNDOBYTOMEOFPOWER", MORPH_UNDOBYTOMEOFPOWER},
|
||||||
|
{ "MRF_UNDOBYCHAOSDEVICE", MORPH_UNDOBYCHAOSDEVICE},
|
||||||
|
{ "MRF_FAILNOTELEFRAG", MORPH_FAILNOTELEFRAG},
|
||||||
|
{ "MRF_FAILNOLAUGH", MORPH_FAILNOLAUGH},
|
||||||
|
{ "MRF_WHENINVULNERABLE", MORPH_WHENINVULNERABLE},
|
||||||
|
{ "MRF_LOSEACTUALWEAPON", MORPH_LOSEACTUALWEAPON},
|
||||||
|
{ "MRF_NEWTIDBEHAVIOUR", MORPH_NEWTIDBEHAVIOUR},
|
||||||
|
{ "MRF_UNDOBYDEATH", MORPH_UNDOBYDEATH},
|
||||||
|
{ "MRF_UNDOBYDEATHFORCED", MORPH_UNDOBYDEATHFORCED},
|
||||||
|
{ "MRF_UNDOBYDEATHSAVES", MORPH_UNDOBYDEATHSAVES},
|
||||||
|
{ NULL, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
return ParseFlagExpressionString(sc, morphstyles);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ParseThingActivation (FScanner &sc)
|
||||||
|
{
|
||||||
|
static const FParseValue activationstyles[]={
|
||||||
|
|
||||||
|
{ "THINGSPEC_Default", THINGSPEC_Default},
|
||||||
|
{ "THINGSPEC_ThingActs", THINGSPEC_ThingActs},
|
||||||
|
{ "THINGSPEC_ThingTargets", THINGSPEC_ThingTargets},
|
||||||
|
{ "THINGSPEC_TriggerTargets", THINGSPEC_TriggerTargets},
|
||||||
|
{ "THINGSPEC_MonsterTrigger", THINGSPEC_MonsterTrigger},
|
||||||
|
{ "THINGSPEC_MissileTrigger", THINGSPEC_MissileTrigger},
|
||||||
|
{ "THINGSPEC_ClearSpecial", THINGSPEC_ClearSpecial},
|
||||||
|
{ NULL, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
return ParseFlagExpressionString(sc, activationstyles);
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// For getting a state address from the parent
|
// For getting a state address from the parent
|
||||||
|
|
|
@ -1057,6 +1057,16 @@ DEFINE_PROPERTY(projectile, 0, Actor)
|
||||||
if (gameinfo.gametype&GAME_Raven) defaults->flags5|=MF5_BLOODSPLATTER;
|
if (gameinfo.gametype&GAME_Raven) defaults->flags5|=MF5_BLOODSPLATTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
DEFINE_PROPERTY(activation, N, Actor)
|
||||||
|
{
|
||||||
|
// How the thing behaves when activated with MF5_USESPECIAL or MF6_BUMPSPECIAL
|
||||||
|
PROP_INT_PARM(val, 0);
|
||||||
|
defaults->activationtype = val;
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// Special inventory properties
|
// Special inventory properties
|
||||||
|
|
|
@ -61,6 +61,18 @@ const int MRF_UNDOBYDEATHSAVES = 2048;
|
||||||
const int RGF_SILENT = 1;
|
const int RGF_SILENT = 1;
|
||||||
const int RGF_NOPIERCING = 2;
|
const int RGF_NOPIERCING = 2;
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
THINGSPEC_Default = 0,
|
||||||
|
THINGSPEC_ThingActs = 1,
|
||||||
|
THINGSPEC_ThingTargets = 2,
|
||||||
|
THINGSPEC_TriggerTargets = 4,
|
||||||
|
THINGSPEC_MonsterTrigger = 8,
|
||||||
|
THINGSPEC_MissileTrigger = 16,
|
||||||
|
THINGSPEC_ClearSpecial = 32,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// constants for A_PlaySound
|
// constants for A_PlaySound
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue