mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-10 14:51:40 +00:00
- Added Gez's thing activation submission.
SVN r1904 (trunk)
This commit is contained in:
parent
19ef8399a8
commit
819158a8fe
9 changed files with 131 additions and 55 deletions
|
@ -1,4 +1,5 @@
|
||||||
October 9, 2009 (Changes by Graf Zahl)
|
October 9, 2009 (Changes by Graf Zahl)
|
||||||
|
- Added Gez's thing activation submission.
|
||||||
- added a NULL pointer check to fog spawning in unmorphing code.
|
- added a NULL pointer check to fog spawning in unmorphing code.
|
||||||
- fixed: frozen corpses need to be treated as solid by z-movement code.
|
- fixed: frozen corpses need to be treated as solid by z-movement code.
|
||||||
- fixed: AAmbientSound::Serialize was adjusting its timer value for savegames
|
- fixed: AAmbientSound::Serialize was adjusting its timer value for savegames
|
||||||
|
|
25
src/actor.h
25
src/actor.h
|
@ -431,19 +431,23 @@ enum EBounceFlags
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Used to affect the logic for MF5_USESPECIAL and MF6_BUMPSPECIAL
|
// Used to affect the logic for thing activation through death, USESPECIAL and BUMPSPECIAL
|
||||||
// "thing" refers to what has the flag and the special, "trigger" refers to what used or bumped it
|
// "thing" refers to what has the flag and the special, "trigger" refers to what used or bumped it
|
||||||
enum EThingSpecialActivationType
|
enum EThingSpecialActivationType
|
||||||
{
|
{
|
||||||
THINGSPEC_Default = 0, // Normal behavior: a player must be the trigger, and is the activator
|
THINGSPEC_Default = 0, // Normal behavior: a player must be the trigger, and is the activator
|
||||||
THINGSPEC_ThingActs = 1, // The thing itself is the activator of the special
|
THINGSPEC_ThingActs = 1, // The thing itself is the activator of the special
|
||||||
THINGSPEC_ThingTargets = 2, // The thing changes its target to the trigger
|
THINGSPEC_ThingTargets = 1<<1, // The thing changes its target to the trigger
|
||||||
THINGSPEC_TriggerTargets = 4, // The trigger changes its target to the thing
|
THINGSPEC_TriggerTargets = 1<<2, // The trigger changes its target to the thing
|
||||||
THINGSPEC_MonsterTrigger = 8, // The thing can be triggered by a monster
|
THINGSPEC_MonsterTrigger = 1<<3, // The thing can be triggered by a monster
|
||||||
THINGSPEC_MissileTrigger = 16, // The thing can be triggered by a projectile
|
THINGSPEC_MissileTrigger = 1<<4, // The thing can be triggered by a projectile
|
||||||
THINGSPEC_ClearSpecial = 32, // Clears special after successful activation
|
THINGSPEC_ClearSpecial = 1<<5, // Clears special after successful activation
|
||||||
THINGSPEC_NoDeathSpecial = 64, // Don't activate special on death
|
THINGSPEC_NoDeathSpecial = 1<<6, // Don't activate special on death
|
||||||
THINGSPEC_TriggerActs = 128, // The trigger is the activator of the special (overrides LEVEL_ACTOWNSPECIAL Hexen hack)
|
THINGSPEC_TriggerActs = 1<<7, // The trigger is the activator of the special
|
||||||
|
// (overrides LEVEL_ACTOWNSPECIAL Hexen hack)
|
||||||
|
THINGSPEC_Activate = 1<<8, // The thing is activated when triggered
|
||||||
|
THINGSPEC_Deactivate = 1<<9, // The thing is deactivated when triggered
|
||||||
|
THINGSPEC_Switch = 1<<10, // The thing is alternatively activated and deactivated when triggered
|
||||||
};
|
};
|
||||||
|
|
||||||
// [RH] Like msecnode_t, but for the blockmap
|
// [RH] Like msecnode_t, but for the blockmap
|
||||||
|
@ -807,6 +811,7 @@ public:
|
||||||
fixed_t pushfactor;
|
fixed_t pushfactor;
|
||||||
int lastpush;
|
int lastpush;
|
||||||
int activationtype; // How the thing behaves when activated with USESPECIAL or BUMPSPECIAL
|
int activationtype; // How the thing behaves when activated with USESPECIAL or BUMPSPECIAL
|
||||||
|
int lastbump; // Last time the actor was bumped, used to control BUMPSPECIAL
|
||||||
int Score; // manipulated by score items, ACS or DECORATE. The engine doesn't use this itself for anything.
|
int Score; // manipulated by score items, ACS or DECORATE. The engine doesn't use this itself for anything.
|
||||||
FNameNoInit Tag; // Strife's tag name. FIXME: should be case sensitive!
|
FNameNoInit Tag; // Strife's tag name. FIXME: should be case sensitive!
|
||||||
|
|
||||||
|
|
|
@ -420,17 +420,11 @@ void AActor::Die (AActor *source, AActor *inflictor)
|
||||||
// the activator of the script.
|
// the activator of the script.
|
||||||
// New: In Hexen, the thing that died is the activator,
|
// New: In Hexen, the thing that died is the activator,
|
||||||
// so now a level flag selects who the activator gets to be.
|
// so now a level flag selects who the activator gets to be.
|
||||||
if (special && (!(flags & MF_SPECIAL) || (flags3 & MF3_ISMONSTER)) && !(activationtype & THINGSPEC_NoDeathSpecial))
|
// Everything is now moved to P_ActivateThingSpecial().
|
||||||
|
if (special && (!(flags & MF_SPECIAL) || (flags3 & MF3_ISMONSTER))
|
||||||
|
&& !(activationtype & THINGSPEC_NoDeathSpecial))
|
||||||
{
|
{
|
||||||
// Activation flags override LEVEL_ACTOWNSPECIAL if set.
|
P_ActivateThingSpecial(this, source, true);
|
||||||
AActor *activator = (activationtype & THINGSPEC_TriggerActs ? source :
|
|
||||||
(activationtype & THINGSPEC_ThingActs ? this : (level.flags & LEVEL_ACTOWNSPECIAL ? this : source)));
|
|
||||||
if (activationtype & THINGSPEC_ThingTargets)
|
|
||||||
this->target = source;
|
|
||||||
if (activationtype & THINGSPEC_TriggerTargets)
|
|
||||||
source->target = this;
|
|
||||||
LineSpecials[special] (NULL, activator, false, args[0], args[1], args[2], args[3], args[4]);
|
|
||||||
special = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CountsAsKill())
|
if (CountsAsKill())
|
||||||
|
|
|
@ -1061,6 +1061,30 @@ FUNC(LS_HealThing)
|
||||||
return it ? true : false;
|
return it ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// So that things activated/deactivated by ACS or DECORATE *and* by
|
||||||
|
// the BUMPSPECIAL or USESPECIAL flags work correctly both ways.
|
||||||
|
void DoActivateThing(AActor * thing, AActor * activator)
|
||||||
|
{
|
||||||
|
if (thing->activationtype & THINGSPEC_Activate)
|
||||||
|
{
|
||||||
|
thing->activationtype &= ~THINGSPEC_Activate; // Clear flag
|
||||||
|
if (thing->activationtype & THINGSPEC_Switch) // Set other flag if switching
|
||||||
|
thing->activationtype |= THINGSPEC_Deactivate;
|
||||||
|
}
|
||||||
|
thing->Activate (activator);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoDeactivateThing(AActor * thing, AActor * activator)
|
||||||
|
{
|
||||||
|
if (thing->activationtype & THINGSPEC_Deactivate)
|
||||||
|
{
|
||||||
|
thing->activationtype &= ~THINGSPEC_Deactivate; // Clear flag
|
||||||
|
if (thing->activationtype & THINGSPEC_Switch) // Set other flag if switching
|
||||||
|
thing->activationtype |= THINGSPEC_Activate;
|
||||||
|
}
|
||||||
|
thing->Deactivate (activator);
|
||||||
|
}
|
||||||
|
|
||||||
FUNC(LS_Thing_Activate)
|
FUNC(LS_Thing_Activate)
|
||||||
// Thing_Activate (tid)
|
// Thing_Activate (tid)
|
||||||
{
|
{
|
||||||
|
@ -1076,7 +1100,7 @@ FUNC(LS_Thing_Activate)
|
||||||
// Actor might remove itself as part of activation, so get next
|
// Actor might remove itself as part of activation, so get next
|
||||||
// one before activating it.
|
// one before activating it.
|
||||||
AActor *temp = iterator.Next ();
|
AActor *temp = iterator.Next ();
|
||||||
actor->Activate (it);
|
DoActivateThing(actor, it);
|
||||||
actor = temp;
|
actor = temp;
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
@ -1085,7 +1109,7 @@ FUNC(LS_Thing_Activate)
|
||||||
}
|
}
|
||||||
else if (it != NULL)
|
else if (it != NULL)
|
||||||
{
|
{
|
||||||
it->Activate(it);
|
DoActivateThing(it, it);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -1106,7 +1130,7 @@ FUNC(LS_Thing_Deactivate)
|
||||||
// Actor might removes itself as part of deactivation, so get next
|
// Actor might removes itself as part of deactivation, so get next
|
||||||
// one before we activate it.
|
// one before we activate it.
|
||||||
AActor *temp = iterator.Next ();
|
AActor *temp = iterator.Next ();
|
||||||
actor->Deactivate (it);
|
DoDeactivateThing(actor, it);
|
||||||
actor = temp;
|
actor = temp;
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
@ -1115,7 +1139,7 @@ FUNC(LS_Thing_Deactivate)
|
||||||
}
|
}
|
||||||
else if (it != NULL)
|
else if (it != NULL)
|
||||||
{
|
{
|
||||||
it->Deactivate(it);
|
DoDeactivateThing(it, it);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -196,5 +196,6 @@ typedef int (*lnSpecFunc)(struct line_t *line,
|
||||||
extern lnSpecFunc LineSpecials[256];
|
extern lnSpecFunc LineSpecials[256];
|
||||||
|
|
||||||
int P_FindLineSpecial (const char *string, int *min_args=NULL, int *max_args=NULL);
|
int P_FindLineSpecial (const char *string, int *min_args=NULL, int *max_args=NULL);
|
||||||
|
bool P_ActivateThingSpecial(AActor * thing, AActor * trigger, bool death=false);
|
||||||
|
|
||||||
#endif //__P_LNSPEC_H__
|
#endif //__P_LNSPEC_H__
|
||||||
|
|
100
src/p_map.cpp
100
src/p_map.cpp
|
@ -837,24 +837,13 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm)
|
||||||
|
|
||||||
// Check for MF6_BUMPSPECIAL
|
// Check for MF6_BUMPSPECIAL
|
||||||
// By default, only players can activate things by bumping into them
|
// By default, only players can activate things by bumping into them
|
||||||
if ((thing->flags6 & MF6_BUMPSPECIAL))
|
if ((thing->flags6 & MF6_BUMPSPECIAL) && ((tm.thing->player != NULL)
|
||||||
|
|| ((thing->activationtype & THINGSPEC_MonsterTrigger) && (tm.thing->flags3 & MF3_ISMONSTER))
|
||||||
|
|| ((thing->activationtype & THINGSPEC_MissileTrigger) && (tm.thing->flags & MF_MISSILE))
|
||||||
|
) && (level.maptime > thing->lastbump)) // Leave the bumper enough time to go away
|
||||||
{
|
{
|
||||||
if (((tm.thing->player != NULL)
|
if (P_ActivateThingSpecial(thing, tm.thing))
|
||||||
|| ((thing->activationtype & THINGSPEC_MonsterTrigger) && (thing->flags3 & MF3_ISMONSTER))
|
thing->lastbump = level.maptime + TICRATE;
|
||||||
|| ((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
|
||||||
|
@ -3775,18 +3764,9 @@ bool P_UseTraverse(AActor *usething, fixed_t endx, fixed_t endy, bool &foundline
|
||||||
// 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
|
// 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 (in->d.thing->activationtype & THINGSPEC_ThingTargets) in->d.thing->target = usething;
|
if (P_ActivateThingSpecial(in->d.thing, 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[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)
|
||||||
|
@ -5180,3 +5160,67 @@ static void SpawnDeepSplash (AActor *t1, const FTraceResults &trace, AActor *puf
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
// P_ActivateThingSpecial
|
||||||
|
//
|
||||||
|
// Handles the code for things activated by death, USESPECIAL or BUMPSPECIAL
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
bool P_ActivateThingSpecial(AActor * thing, AActor * trigger, bool death)
|
||||||
|
{
|
||||||
|
bool res = false;
|
||||||
|
|
||||||
|
// Target switching mechanism
|
||||||
|
if (thing->activationtype & THINGSPEC_ThingTargets) thing->target = trigger;
|
||||||
|
if (thing->activationtype & THINGSPEC_TriggerTargets) trigger->target = thing;
|
||||||
|
|
||||||
|
// State change mechanism. The thing needs to be not dead and to have at least one of the relevant flags
|
||||||
|
if (!death && (thing->activationtype & (THINGSPEC_Activate|THINGSPEC_Deactivate|THINGSPEC_Switch)))
|
||||||
|
{
|
||||||
|
// If a switchable thing does not know whether it should be activated
|
||||||
|
// or deactivated, the default is to activate it.
|
||||||
|
if ((thing->activationtype & THINGSPEC_Switch)
|
||||||
|
&& !(thing->activationtype & (THINGSPEC_Activate|THINGSPEC_Deactivate)))
|
||||||
|
{
|
||||||
|
thing->activationtype |= THINGSPEC_Activate;
|
||||||
|
}
|
||||||
|
// Can it be activated?
|
||||||
|
if (thing->activationtype & THINGSPEC_Activate)
|
||||||
|
{
|
||||||
|
thing->activationtype &= ~THINGSPEC_Activate; // Clear flag
|
||||||
|
if (thing->activationtype & THINGSPEC_Switch) // Set other flag if switching
|
||||||
|
thing->activationtype |= THINGSPEC_Deactivate;
|
||||||
|
thing->Activate(trigger);
|
||||||
|
res = true;
|
||||||
|
}
|
||||||
|
// If not, can it be deactivated?
|
||||||
|
else if (thing->activationtype & THINGSPEC_Deactivate)
|
||||||
|
{
|
||||||
|
thing->activationtype &= ~THINGSPEC_Deactivate; // Clear flag
|
||||||
|
if (thing->activationtype & THINGSPEC_Switch) // Set other flag if switching
|
||||||
|
thing->activationtype |= THINGSPEC_Activate;
|
||||||
|
thing->Deactivate(trigger);
|
||||||
|
res = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run the special, if any
|
||||||
|
if (thing->special)
|
||||||
|
{
|
||||||
|
res = !! LineSpecials[thing->special] (NULL,
|
||||||
|
// TriggerActs overrides the level flag, which only concerns thing activated by death
|
||||||
|
(((death && level.flags & LEVEL_ACTOWNSPECIAL && !(thing->activationtype & THINGSPEC_TriggerActs))
|
||||||
|
|| (thing->activationtype & THINGSPEC_ThingActs)) // Who triggers?
|
||||||
|
? thing : trigger),
|
||||||
|
false, thing->args[0], thing->args[1], thing->args[2], thing->args[3], thing->args[4]);
|
||||||
|
|
||||||
|
// Clears the special if it was run on thing's death or if flag is set.
|
||||||
|
if (death || (thing->activationtype & THINGSPEC_ClearSpecial && res)) thing->special = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the result
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
|
@ -300,6 +300,10 @@ void AActor::Serialize (FArchive &arc)
|
||||||
<< Species
|
<< Species
|
||||||
<< Score
|
<< Score
|
||||||
<< Tag;
|
<< Tag;
|
||||||
|
if (SaveVersion >= 1904)
|
||||||
|
{
|
||||||
|
arc << lastpush << lastbump;
|
||||||
|
}
|
||||||
|
|
||||||
if (SaveVersion >= 1900)
|
if (SaveVersion >= 1900)
|
||||||
{
|
{
|
||||||
|
@ -3670,7 +3674,7 @@ void AActor::Activate (AActor *activator)
|
||||||
if (flags2 & MF2_DORMANT)
|
if (flags2 & MF2_DORMANT)
|
||||||
{
|
{
|
||||||
flags2 &= ~MF2_DORMANT;
|
flags2 &= ~MF2_DORMANT;
|
||||||
FState *state = FindState("Active");
|
FState *state = FindState(NAME_Active);
|
||||||
if (state != NULL)
|
if (state != NULL)
|
||||||
{
|
{
|
||||||
SetState(state);
|
SetState(state);
|
||||||
|
@ -3690,7 +3694,7 @@ void AActor::Deactivate (AActor *activator)
|
||||||
if (!(flags2 & MF2_DORMANT))
|
if (!(flags2 & MF2_DORMANT))
|
||||||
{
|
{
|
||||||
flags2 |= MF2_DORMANT;
|
flags2 |= MF2_DORMANT;
|
||||||
FState *state = FindState("Inactive");
|
FState *state = FindState(NAME_Inactive);
|
||||||
if (state != NULL)
|
if (state != NULL)
|
||||||
{
|
{
|
||||||
SetState(state);
|
SetState(state);
|
||||||
|
|
|
@ -465,6 +465,9 @@ static int ParseThingActivation (FScanner &sc)
|
||||||
{ "THINGSPEC_ClearSpecial", THINGSPEC_ClearSpecial},
|
{ "THINGSPEC_ClearSpecial", THINGSPEC_ClearSpecial},
|
||||||
{ "THINGSPEC_NoDeathSpecial", THINGSPEC_NoDeathSpecial},
|
{ "THINGSPEC_NoDeathSpecial", THINGSPEC_NoDeathSpecial},
|
||||||
{ "THINGSPEC_TriggerActs", THINGSPEC_TriggerActs},
|
{ "THINGSPEC_TriggerActs", THINGSPEC_TriggerActs},
|
||||||
|
{ "THINGSPEC_Activate", THINGSPEC_Activate},
|
||||||
|
{ "THINGSPEC_Deactivate", THINGSPEC_Deactivate},
|
||||||
|
{ "THINGSPEC_Switch", THINGSPEC_Switch},
|
||||||
{ NULL, 0 }
|
{ NULL, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1072,7 +1072,7 @@ DEFINE_PROPERTY(projectile, 0, Actor)
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
DEFINE_PROPERTY(activation, N, Actor)
|
DEFINE_PROPERTY(activation, N, Actor)
|
||||||
{
|
{
|
||||||
// How the thing behaves when activated with MF5_USESPECIAL or MF6_BUMPSPECIAL
|
// How the thing behaves when activated by death, USESPECIAL or BUMPSPECIAL
|
||||||
PROP_INT_PARM(val, 0);
|
PROP_INT_PARM(val, 0);
|
||||||
defaults->activationtype = val;
|
defaults->activationtype = val;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue