- added a CANUSEWALLS flag which allows a monster to activate 'use' specials

like doors. This flag is on by default for any monster which was the
  previous behavior.
- Optimized the DECORATE flag parser so it can more efficiently handle
  the deprecated flags. As a side effect of this optimization the deprecated
  flags became usable in A_ChangeFlag again.
- Changed LONGMELEERANGE flag into a MeleeThreshold property.
- Changed SHORTMISSILERANGE flag into a MaxTargetRange property.
- Added Thing_Stop action special.


SVN r517 (trunk)
This commit is contained in:
Christoph Oelckers 2007-04-22 21:01:35 +00:00
parent 8c7d4fb393
commit 9deec29b34
11 changed files with 154 additions and 49 deletions

View file

@ -1,4 +1,13 @@
April 22, 2007 (Changes by Graf Zahl) April 22, 2007 (Changes by Graf Zahl)
- added a CANUSEWALLS flag which allows a monster to activate 'use' specials
like doors. This flag is on by default for any monster which was the
previous behavior.
- Optimized the DECORATE flag parser so it can more efficiently handle
the deprecated flags. As a side effect of this optimization the deprecated
flags became usable in A_ChangeFlag again.
- Changed LONGMELEERANGE flag into a MeleeThreshold property.
- Changed SHORTMISSILERANGE flag into a MaxTargetRange property.
- Added Thing_Stop action special.
- Changed ACS's SetActorState so that it isn't limited to only one sublabel. - Changed ACS's SetActorState so that it isn't limited to only one sublabel.
This change also enables the implicit mapping of the old special death This change also enables the implicit mapping of the old special death
state names. state names.

View file

@ -252,11 +252,11 @@ enum
MF4_ACTLIKEBRIDGE = 0x00000080, // Pickups can "stand" on this actor MF4_ACTLIKEBRIDGE = 0x00000080, // Pickups can "stand" on this actor
MF4_STRIFEDAMAGE = 0x00000100, // Strife projectiles only do up to 4x damage, not 8x MF4_STRIFEDAMAGE = 0x00000100, // Strife projectiles only do up to 4x damage, not 8x
MF4_LONGMELEERANGE = 0x00000200, MF4_CANUSEWALLS = 0x00000200, // Can activate 'use' specials
MF4_MISSILEMORE = 0x00000400, MF4_MISSILEMORE = 0x00000400, // increases the chance of a missile attack
MF4_MISSILEEVENMORE = 0x00000800, MF4_MISSILEEVENMORE = 0x00000800, // significantly increases the chance of a missile attack
MF4_SHORTMISSILERANGE=0x00001000, // unused flag
MF4_DONTFALL = 0x00002000, MF4_DONTFALL = 0x00002000, // Doesn't have NOGRAVITY disabled when dying.
MF4_SEESDAGGERS = 0x00004000, // This actor can see you striking with a dagger MF4_SEESDAGGERS = 0x00004000, // This actor can see you striking with a dagger
MF4_INCOMBAT = 0x00008000, // Don't alert others when attacked by a dagger MF4_INCOMBAT = 0x00008000, // Don't alert others when attacked by a dagger
MF4_LOOKALLAROUND = 0x00010000, // Monster has eyes in the back of its head MF4_LOOKALLAROUND = 0x00010000, // Monster has eyes in the back of its head
@ -680,7 +680,11 @@ public:
BYTE boomwaterlevel; // splash information for non-swimmable water sectors BYTE boomwaterlevel; // splash information for non-swimmable water sectors
BYTE MinMissileChance;// [RH] If a random # is > than this, then missile attack. BYTE MinMissileChance;// [RH] If a random # is > than this, then missile attack.
WORD SpawnFlags; WORD SpawnFlags;
fixed_t meleerange; 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.
// This is not the same as meleerange
fixed_t maxtargetrange; // any target farther away cannot be attacked
fixed_t bouncefactor; // Strife's grenades use 50%, Hexen's Flechettes 70. fixed_t bouncefactor; // Strife's grenades use 50%, Hexen's Flechettes 70.
int bouncecount; // Strife's grenades only bounce twice before exploding int bouncecount; // Strife's grenades only bounce twice before exploding
fixed_t gravity; // [GRB] Gravity factor fixed_t gravity; // [GRB] Gravity factor

View file

@ -54,6 +54,7 @@ IMPLEMENT_ACTOR (AStrifePuff, Strife, -1, 0)
PROP_SpawnState (4) PROP_SpawnState (4)
PROP_CrashState (0) PROP_CrashState (0)
PROP_Flags (MF_NOBLOCKMAP|MF_NOGRAVITY) PROP_Flags (MF_NOBLOCKMAP|MF_NOGRAVITY)
PROP_Flags4 (MF4_ALLOWPARTICLES)
PROP_Alpha (TRANSLUC25) PROP_Alpha (TRANSLUC25)
PROP_RenderStyle (STYLE_Translucent) PROP_RenderStyle (STYLE_Translucent)
END_DEFAULTS END_DEFAULTS
@ -89,6 +90,7 @@ IMPLEMENT_ACTOR (AStrifeSpark, Strife, -1, 0)
PROP_SpawnState (0) PROP_SpawnState (0)
PROP_CrashState (8) PROP_CrashState (8)
PROP_Flags (MF_NOBLOCKMAP|MF_NOGRAVITY) PROP_Flags (MF_NOBLOCKMAP|MF_NOGRAVITY)
PROP_Flags4 (MF4_ALLOWPARTICLES)
PROP_RenderStyle (STYLE_Add) PROP_RenderStyle (STYLE_Add)
PROP_Alpha (TRANSLUC25) PROP_Alpha (TRANSLUC25)
END_DEFAULTS END_DEFAULTS

View file

@ -416,6 +416,7 @@ void FActorInfo::ApplyDefaults (BYTE *defaults)
if (((AActor *)defaults)->flags & MF_COUNTKILL) if (((AActor *)defaults)->flags & MF_COUNTKILL)
{ {
((AActor *)defaults)->flags3 |= MF3_ISMONSTER; ((AActor *)defaults)->flags3 |= MF3_ISMONSTER;
((AActor *)defaults)->flags4 |= MF4_CANUSEWALLS; // I won't bother changing all internal monster definitions so let's set this here.
} }
// Any default projectile in Raven's games produces blood splatter // Any default projectile in Raven's games produces blood splatter
if (gameinfo.gametype & GAME_Raven && ((AActor *)defaults)->flags & MF_MISSILE) if (gameinfo.gametype & GAME_Raven && ((AActor *)defaults)->flags & MF_MISSILE)

View file

@ -324,10 +324,10 @@ bool AActor::SuggestMissileAttack (fixed_t dist)
// Making these values customizable is not necessary and in most case more confusing than // Making these values customizable is not necessary and in most case more confusing than
// helpful because no value here translates into anything really meaningful. // helpful because no value here translates into anything really meaningful.
if (flags4 & MF4_SHORTMISSILERANGE && dist>14*64*FRACUNIT) if (maxtargetrange > 0 && dist > maxtargetrange)
return false; // The Arch Vile's special behavior turned into a flag return false; // The Arch Vile's special behavior turned into a property
if (flags4 & MF4_LONGMELEERANGE && dist < 196*FRACUNIT) if (dist < meleethreshold)
return false; // From the Revenant: close enough for fist attack return false; // From the Revenant: close enough for fist attack
if (flags4 & MF4_MISSILEMORE) dist >>= 1; if (flags4 & MF4_MISSILEMORE) dist >>= 1;
@ -521,8 +521,8 @@ bool P_Move (AActor *actor)
while (spechit.Pop (ld)) while (spechit.Pop (ld))
{ {
// [RH] let monsters push lines, as well as use them // [RH] let monsters push lines, as well as use them
if (P_ActivateLine (ld, actor, 0, SPAC_USE) || if (((actor->flags4 & MF4_CANUSEWALLS) && P_ActivateLine (ld, actor, 0, SPAC_USE)) ||
((actor->flags & MF2_PUSHWALL) && P_ActivateLine (ld, actor, 0, SPAC_PUSH))) ((actor->flags2 & MF2_PUSHWALL) && P_ActivateLine (ld, actor, 0, SPAC_PUSH)))
{ {
good |= ld == BlockingLine ? 1 : 2; good |= ld == BlockingLine ? 1 : 2;
} }

View file

@ -1415,6 +1415,34 @@ FUNC(LS_Thing_Raise)
return ok; return ok;
} }
FUNC(LS_Thing_Stop)
// Thing_Stop(tid)
{
AActor * target;
bool ok = false;
if (arg0==0)
{
if (it != NULL)
{
it->momx = it->momy = it->momz = 0;
ok = true;
}
}
else
{
TActorIterator<AActor> iterator (arg0);
while ( (target = iterator.Next ()) )
{
target->momx = target->momy = target->momz = 0;
ok = true;
}
}
return ok;
}
FUNC(LS_Thing_SetGoal) FUNC(LS_Thing_SetGoal)
// Thing_SetGoal (tid, goal, delay, chasegoal) // Thing_SetGoal (tid, goal, delay, chasegoal)
{ {
@ -1472,7 +1500,7 @@ FUNC(LS_Thing_SetTranslation)
while ( (target = iterator.Next ()) ) while ( (target = iterator.Next ()) )
{ {
ok = true; ok = true;
target->Translation = range; target->Translation = range==0? target->GetDefault()->Translation : range;
} }
return ok; return ok;
@ -2739,7 +2767,7 @@ lnSpecFunc LineSpecials[256] =
LS_NOP, // Transfer_WallLight LS_NOP, // Transfer_WallLight
LS_Thing_Raise, LS_Thing_Raise,
LS_StartConversation, LS_StartConversation,
LS_NOP, // 19 LS_Thing_Stop,
LS_Floor_LowerByValue, LS_Floor_LowerByValue,
LS_Floor_LowerToLowest, LS_Floor_LowerToLowest,
LS_Floor_LowerToNearest, LS_Floor_LowerToNearest,

View file

@ -59,6 +59,7 @@ typedef enum {
Transfer_WallLight = 16, Transfer_WallLight = 16,
Thing_Raise = 17, Thing_Raise = 17,
StartConversation = 18, StartConversation = 18,
Thing_Stop = 19,
Floor_LowerByValue = 20, Floor_LowerByValue = 20,
Floor_LowerToLowest = 21, Floor_LowerToLowest = 21,

View file

@ -311,6 +311,8 @@ void AActor::Serialize (FArchive &arc)
<< MaxStepHeight << MaxStepHeight
<< bouncefactor << bouncefactor
<< bouncecount << bouncecount
<< maxtargetrange
<< meleethreshold
<< meleerange << meleerange
<< DamageType << DamageType
<< gravity; << gravity;

View file

@ -90,6 +90,7 @@ TArray<FName> JumpParameters;
// [RH] Keep GCC quiet by not using offsetof on Actor types. // [RH] Keep GCC quiet by not using offsetof on Actor types.
#define DEFINE_FLAG(prefix, name, type, variable) { prefix##_##name, #name, (int)(size_t)&((type*)1)->variable - 1 } #define DEFINE_FLAG(prefix, name, type, variable) { prefix##_##name, #name, (int)(size_t)&((type*)1)->variable - 1 }
#define DEFINE_FLAG2(symbol, name, type, variable) { symbol, #name, (int)(size_t)&((type*)1)->variable - 1 } #define DEFINE_FLAG2(symbol, name, type, variable) { symbol, #name, (int)(size_t)&((type*)1)->variable - 1 }
#define DEFINE_DEPRECATED_FLAG(name, type, index) { index, #name, -1 }
struct flagdef struct flagdef
{ {
@ -191,10 +192,9 @@ static flagdef ActorFlags[]=
DEFINE_FLAG(MF4, FIXMAPTHINGPOS , AActor, flags4), DEFINE_FLAG(MF4, FIXMAPTHINGPOS , AActor, flags4),
DEFINE_FLAG(MF4, ACTLIKEBRIDGE, AActor, flags4), DEFINE_FLAG(MF4, ACTLIKEBRIDGE, AActor, flags4),
DEFINE_FLAG(MF4, STRIFEDAMAGE, AActor, flags4), DEFINE_FLAG(MF4, STRIFEDAMAGE, AActor, flags4),
DEFINE_FLAG(MF4, LONGMELEERANGE, AActor, flags4), DEFINE_FLAG(MF4, CANUSEWALLS, AActor, flags4),
DEFINE_FLAG(MF4, MISSILEMORE, AActor, flags4), DEFINE_FLAG(MF4, MISSILEMORE, AActor, flags4),
DEFINE_FLAG(MF4, MISSILEEVENMORE, AActor, flags4), DEFINE_FLAG(MF4, MISSILEEVENMORE, AActor, flags4),
DEFINE_FLAG(MF4, SHORTMISSILERANGE, AActor, flags4),
DEFINE_FLAG(MF4, DONTFALL, AActor, flags4), DEFINE_FLAG(MF4, DONTFALL, AActor, flags4),
DEFINE_FLAG(MF4, SEESDAGGERS, AActor, flags4), DEFINE_FLAG(MF4, SEESDAGGERS, AActor, flags4),
DEFINE_FLAG(MF4, INCOMBAT, AActor, flags4), DEFINE_FLAG(MF4, INCOMBAT, AActor, flags4),
@ -233,6 +233,13 @@ static flagdef ActorFlags[]=
DEFINE_FLAG2(FX_ROCKET, ROCKETTRAIL, AActor, effects), DEFINE_FLAG2(FX_ROCKET, ROCKETTRAIL, AActor, effects),
DEFINE_FLAG2(FX_GRENADE, GRENADETRAIL, AActor, effects), DEFINE_FLAG2(FX_GRENADE, GRENADETRAIL, AActor, effects),
DEFINE_FLAG(RF, INVISIBLE, AActor, renderflags), DEFINE_FLAG(RF, INVISIBLE, AActor, renderflags),
// Deprecated flags. Handling must be performed in HandleDeprecatedFlags
DEFINE_DEPRECATED_FLAG(FIREDAMAGE, AActor, 0),
DEFINE_DEPRECATED_FLAG(ICEDAMAGE, AActor, 1),
DEFINE_DEPRECATED_FLAG(LOWGRAVITY, AActor, 2),
DEFINE_DEPRECATED_FLAG(SHORTMISSILERANGE, AActor, 3),
DEFINE_DEPRECATED_FLAG(LONGMELEERANGE, AActor, 4),
}; };
static flagdef InventoryFlags[] = static flagdef InventoryFlags[] =
@ -364,6 +371,41 @@ static flagdef *FindFlag (const PClass *type, const char *part1, const char *par
return NULL; return NULL;
} }
//===========================================================================
//
// HandleDeprecatedFlags
//
// Handles the deprecated flags and sets the respective properties
// to appropriate values. This is solely intended for backwards
// compatibility so mixing this with code that is aware of the real
// properties is not recommended
//
//===========================================================================
static void HandleDeprecatedFlags(AActor *defaults, bool set, int index)
{
switch (index)
{
case 0: // FIREDAMAGE
defaults->DamageType = set? NAME_Fire : NAME_None;
break;
case 1: // ICEDAMAGE
defaults->DamageType = set? NAME_Ice : NAME_None;
break;
case 2: // LOWGRAVITY
defaults->gravity = set? FRACUNIT/8 : FRACUNIT;
break;
case 3: // SHORTMISSILERANGE
defaults->maxtargetrange = set? 896*FRACUNIT : 0;
break;
case 4: // LONGMELEERANGE
defaults->meleethreshold = set? 196*FRACUNIT : 0;
break;
default:
break; // silence GCC
}
}
//=========================================================================== //===========================================================================
// //
// A_ChangeFlag // A_ChangeFlag
@ -392,10 +434,17 @@ void A_ChangeFlag(AActor * self)
if (fd != NULL) if (fd != NULL)
{ {
int * flagp = (int*) (((char*)self) + fd->structoffset); if (fd->structoffset == -1)
{
HandleDeprecatedFlags(self, !!expression, fd->flagbit);
}
else
{
int * flagp = (int*) (((char*)self) + fd->structoffset);
if (expression) *flagp |= fd->flagbit; if (expression) *flagp |= fd->flagbit;
else *flagp &= ~fd->flagbit; else *flagp &= ~fd->flagbit;
}
} }
else else
{ {
@ -2939,6 +2988,24 @@ static void ActorBurnHeight (AActor *defaults, Baggage &bag)
bag.Info->Class->Meta.SetMetaFixed (AMETA_BurnHeight, h <= 0 ? -1 : h); bag.Info->Class->Meta.SetMetaFixed (AMETA_BurnHeight, h <= 0 ? -1 : h);
} }
//==========================================================================
//
//==========================================================================
static void ActorMaxTargetRange (AActor *defaults, Baggage &bag)
{
SC_MustGetFloat();
defaults->maxtargetrange = fixed_t(sc_Float*FRACUNIT);
}
//==========================================================================
//
//==========================================================================
static void ActorMeleeThreshold (AActor *defaults, Baggage &bag)
{
SC_MustGetFloat();
defaults->meleethreshold = fixed_t(sc_Float*FRACUNIT);
}
//========================================================================== //==========================================================================
// //
//========================================================================== //==========================================================================
@ -3214,6 +3281,7 @@ static void ActorMonster (AActor *defaults, Baggage &bag)
defaults->flags|=MF_SHOOTABLE|MF_COUNTKILL|MF_SOLID; defaults->flags|=MF_SHOOTABLE|MF_COUNTKILL|MF_SOLID;
defaults->flags2|=MF2_PUSHWALL|MF2_MCROSS|MF2_PASSMOBJ; defaults->flags2|=MF2_PUSHWALL|MF2_MCROSS|MF2_PASSMOBJ;
defaults->flags3|=MF3_ISMONSTER; defaults->flags3|=MF3_ISMONSTER;
defaults->flags4|=MF4_CANUSEWALLS;
} }
//========================================================================== //==========================================================================
@ -3237,32 +3305,20 @@ static void ActorFlagSetOrReset (AActor *defaults, Baggage &bag)
SC_MustGetString (); SC_MustGetString ();
// Fire and ice damage were once flags but now are not. FString part1 = sc_String;
if (SC_Compare ("FIREDAMAGE")) const char *part2 = NULL;
if (SC_CheckString ("."))
{ {
if (mod == '+') defaults->DamageType = NAME_Fire; SC_MustGetString ();
else defaults->DamageType = NAME_None; part2 = sc_String;
} }
else if (SC_Compare ("ICEDAMAGE")) if ( (fd = FindFlag (bag.Info->Class, part1.GetChars(), part2)) )
{ {
if (mod == '+') defaults->DamageType = NAME_Ice; if (fd->structoffset == -1) // this is a deprecated flag that has been changed into a real property
else defaults->DamageType = NAME_None;
}
else if (SC_Compare ("LOWGRAVITY"))
{
if (mod == '+') defaults->gravity = FRACUNIT/8;
else defaults->gravity = FRACUNIT;
}
else
{
FString part1 = sc_String;
const char *part2 = NULL;
if (SC_CheckString ("."))
{ {
SC_MustGetString (); HandleDeprecatedFlags(defaults, mod=='+', fd->flagbit);
part2 = sc_String;
} }
if ( (fd = FindFlag (bag.Info->Class, part1.GetChars(), part2)) ) else
{ {
DWORD * flagvar = (DWORD*) ((char*)defaults + fd->structoffset); DWORD * flagvar = (DWORD*) ((char*)defaults + fd->structoffset);
if (mod == '+') if (mod == '+')
@ -3274,16 +3330,16 @@ static void ActorFlagSetOrReset (AActor *defaults, Baggage &bag)
*flagvar &= ~fd->flagbit; *flagvar &= ~fd->flagbit;
} }
} }
}
else
{
if (part2 == NULL)
{
SC_ScriptError("\"%s\" is an unknown flag\n", part1.GetChars());
}
else else
{ {
if (part2 == NULL) SC_ScriptError("\"%s.%s\" is an unknown flag\n", part1.GetChars(), part2);
{
SC_ScriptError("\"%s\" is an unknown flag\n", part1.GetChars());
}
else
{
SC_ScriptError("\"%s.%s\" is an unknown flag\n", part1.GetChars(), part2);
}
} }
} }
} }
@ -4105,10 +4161,12 @@ static const ActorProps props[] =
{ "mass", ActorMass, RUNTIME_CLASS(AActor) }, { "mass", ActorMass, RUNTIME_CLASS(AActor) },
{ "maxdropoffheight", ActorMaxDropoffHeight, RUNTIME_CLASS(AActor) }, { "maxdropoffheight", ActorMaxDropoffHeight, RUNTIME_CLASS(AActor) },
{ "maxstepheight", ActorMaxStepHeight, RUNTIME_CLASS(AActor) }, { "maxstepheight", ActorMaxStepHeight, RUNTIME_CLASS(AActor) },
{ "maxtargetrange", ActorMaxTargetRange, RUNTIME_CLASS(AActor) },
{ "melee", ActorMeleeState, RUNTIME_CLASS(AActor) }, { "melee", ActorMeleeState, RUNTIME_CLASS(AActor) },
{ "meleedamage", ActorMeleeDamage, RUNTIME_CLASS(AActor) }, { "meleedamage", ActorMeleeDamage, RUNTIME_CLASS(AActor) },
{ "meleerange", ActorMeleeRange, RUNTIME_CLASS(AActor) }, { "meleerange", ActorMeleeRange, RUNTIME_CLASS(AActor) },
{ "meleesound", ActorMeleeSound, RUNTIME_CLASS(AActor) }, { "meleesound", ActorMeleeSound, RUNTIME_CLASS(AActor) },
{ "meleethreshold", ActorMeleeThreshold, RUNTIME_CLASS(AActor) },
{ "minmissilechance", ActorMinMissileChance, RUNTIME_CLASS(AActor) }, { "minmissilechance", ActorMinMissileChance, RUNTIME_CLASS(AActor) },
{ "missile", ActorMissileState, RUNTIME_CLASS(AActor) }, { "missile", ActorMissileState, RUNTIME_CLASS(AActor) },
{ "missileheight", ActorMissileHeight, RUNTIME_CLASS(AActor) }, { "missileheight", ActorMissileHeight, RUNTIME_CLASS(AActor) },

View file

@ -15,8 +15,8 @@ ACTOR Archvile 64
Speed 15 Speed 15
PainChance 10 PainChance 10
Monster Monster
MaxTargetRange 896
+QUICKTORETALIATE +QUICKTORETALIATE
+SHORTMISSILERANGE
+FLOORCLIP +FLOORCLIP
+NOTARGET +NOTARGET
SeeSound "vile/sight" SeeSound "vile/sight"

View file

@ -14,7 +14,7 @@ ACTOR Revenant 66
Speed 10 Speed 10
PainChance 100 PainChance 100
Monster Monster
+LONGMELEERANGE MeleeThreshold 196
+MISSILEMORE +MISSILEMORE
+FLOORCLIP +FLOORCLIP
SeeSound "skeleton/sight" SeeSound "skeleton/sight"