diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 70159dbae..e34b476b6 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,13 @@ 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. This change also enables the implicit mapping of the old special death state names. diff --git a/src/actor.h b/src/actor.h index fcd1ffaae..b500236de 100644 --- a/src/actor.h +++ b/src/actor.h @@ -252,11 +252,11 @@ enum MF4_ACTLIKEBRIDGE = 0x00000080, // Pickups can "stand" on this actor MF4_STRIFEDAMAGE = 0x00000100, // Strife projectiles only do up to 4x damage, not 8x - MF4_LONGMELEERANGE = 0x00000200, - MF4_MISSILEMORE = 0x00000400, - MF4_MISSILEEVENMORE = 0x00000800, - MF4_SHORTMISSILERANGE=0x00001000, - MF4_DONTFALL = 0x00002000, + MF4_CANUSEWALLS = 0x00000200, // Can activate 'use' specials + MF4_MISSILEMORE = 0x00000400, // increases the chance of a missile attack + MF4_MISSILEEVENMORE = 0x00000800, // significantly increases the chance of a missile attack + // unused flag + MF4_DONTFALL = 0x00002000, // Doesn't have NOGRAVITY disabled when dying. 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_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 MinMissileChance;// [RH] If a random # is > than this, then missile attack. 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. int bouncecount; // Strife's grenades only bounce twice before exploding fixed_t gravity; // [GRB] Gravity factor diff --git a/src/g_strife/a_strifeweapons.cpp b/src/g_strife/a_strifeweapons.cpp index 10afd7cd9..36c2fa1cd 100644 --- a/src/g_strife/a_strifeweapons.cpp +++ b/src/g_strife/a_strifeweapons.cpp @@ -54,6 +54,7 @@ IMPLEMENT_ACTOR (AStrifePuff, Strife, -1, 0) PROP_SpawnState (4) PROP_CrashState (0) PROP_Flags (MF_NOBLOCKMAP|MF_NOGRAVITY) + PROP_Flags4 (MF4_ALLOWPARTICLES) PROP_Alpha (TRANSLUC25) PROP_RenderStyle (STYLE_Translucent) END_DEFAULTS @@ -89,6 +90,7 @@ IMPLEMENT_ACTOR (AStrifeSpark, Strife, -1, 0) PROP_SpawnState (0) PROP_CrashState (8) PROP_Flags (MF_NOBLOCKMAP|MF_NOGRAVITY) + PROP_Flags4 (MF4_ALLOWPARTICLES) PROP_RenderStyle (STYLE_Add) PROP_Alpha (TRANSLUC25) END_DEFAULTS diff --git a/src/infodefaults.cpp b/src/infodefaults.cpp index 439ba813b..3129c8443 100644 --- a/src/infodefaults.cpp +++ b/src/infodefaults.cpp @@ -416,6 +416,7 @@ void FActorInfo::ApplyDefaults (BYTE *defaults) if (((AActor *)defaults)->flags & MF_COUNTKILL) { ((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 if (gameinfo.gametype & GAME_Raven && ((AActor *)defaults)->flags & MF_MISSILE) diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 9c21c5934..453e851d1 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -324,10 +324,10 @@ bool AActor::SuggestMissileAttack (fixed_t dist) // Making these values customizable is not necessary and in most case more confusing than // helpful because no value here translates into anything really meaningful. - if (flags4 & MF4_SHORTMISSILERANGE && dist>14*64*FRACUNIT) - return false; // The Arch Vile's special behavior turned into a flag + if (maxtargetrange > 0 && dist > maxtargetrange) + 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 if (flags4 & MF4_MISSILEMORE) dist >>= 1; @@ -521,8 +521,8 @@ bool P_Move (AActor *actor) while (spechit.Pop (ld)) { // [RH] let monsters push lines, as well as use them - if (P_ActivateLine (ld, actor, 0, SPAC_USE) || - ((actor->flags & MF2_PUSHWALL) && P_ActivateLine (ld, actor, 0, SPAC_PUSH))) + if (((actor->flags4 & MF4_CANUSEWALLS) && P_ActivateLine (ld, actor, 0, SPAC_USE)) || + ((actor->flags2 & MF2_PUSHWALL) && P_ActivateLine (ld, actor, 0, SPAC_PUSH))) { good |= ld == BlockingLine ? 1 : 2; } diff --git a/src/p_lnspec.cpp b/src/p_lnspec.cpp index 888400021..bc4fa25d7 100644 --- a/src/p_lnspec.cpp +++ b/src/p_lnspec.cpp @@ -1415,6 +1415,34 @@ FUNC(LS_Thing_Raise) 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 iterator (arg0); + + while ( (target = iterator.Next ()) ) + { + target->momx = target->momy = target->momz = 0; + ok = true; + } + } + return ok; +} + + FUNC(LS_Thing_SetGoal) // Thing_SetGoal (tid, goal, delay, chasegoal) { @@ -1472,7 +1500,7 @@ FUNC(LS_Thing_SetTranslation) while ( (target = iterator.Next ()) ) { ok = true; - target->Translation = range; + target->Translation = range==0? target->GetDefault()->Translation : range; } return ok; @@ -2739,7 +2767,7 @@ lnSpecFunc LineSpecials[256] = LS_NOP, // Transfer_WallLight LS_Thing_Raise, LS_StartConversation, - LS_NOP, // 19 + LS_Thing_Stop, LS_Floor_LowerByValue, LS_Floor_LowerToLowest, LS_Floor_LowerToNearest, diff --git a/src/p_lnspec.h b/src/p_lnspec.h index 4d48f25d7..0def2fcf1 100644 --- a/src/p_lnspec.h +++ b/src/p_lnspec.h @@ -59,6 +59,7 @@ typedef enum { Transfer_WallLight = 16, Thing_Raise = 17, StartConversation = 18, + Thing_Stop = 19, Floor_LowerByValue = 20, Floor_LowerToLowest = 21, diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index b67389c8f..c3cb64e16 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -311,6 +311,8 @@ void AActor::Serialize (FArchive &arc) << MaxStepHeight << bouncefactor << bouncecount + << maxtargetrange + << meleethreshold << meleerange << DamageType << gravity; diff --git a/src/thingdef.cpp b/src/thingdef.cpp index 63253486e..7a507e258 100644 --- a/src/thingdef.cpp +++ b/src/thingdef.cpp @@ -90,6 +90,7 @@ TArray JumpParameters; // [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_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 { @@ -191,10 +192,9 @@ static flagdef ActorFlags[]= DEFINE_FLAG(MF4, FIXMAPTHINGPOS , AActor, flags4), DEFINE_FLAG(MF4, ACTLIKEBRIDGE, 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, MISSILEEVENMORE, AActor, flags4), - DEFINE_FLAG(MF4, SHORTMISSILERANGE, AActor, flags4), DEFINE_FLAG(MF4, DONTFALL, AActor, flags4), DEFINE_FLAG(MF4, SEESDAGGERS, 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_GRENADE, GRENADETRAIL, AActor, effects), 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[] = @@ -364,6 +371,41 @@ static flagdef *FindFlag (const PClass *type, const char *part1, const char *par 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 @@ -392,10 +434,17 @@ void A_ChangeFlag(AActor * self) 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; - else *flagp &= ~fd->flagbit; + if (expression) *flagp |= fd->flagbit; + else *flagp &= ~fd->flagbit; + } } else { @@ -2939,6 +2988,24 @@ static void ActorBurnHeight (AActor *defaults, Baggage &bag) 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->flags2|=MF2_PUSHWALL|MF2_MCROSS|MF2_PASSMOBJ; defaults->flags3|=MF3_ISMONSTER; + defaults->flags4|=MF4_CANUSEWALLS; } //========================================================================== @@ -3237,32 +3305,20 @@ static void ActorFlagSetOrReset (AActor *defaults, Baggage &bag) SC_MustGetString (); - // Fire and ice damage were once flags but now are not. - if (SC_Compare ("FIREDAMAGE")) + FString part1 = sc_String; + const char *part2 = NULL; + if (SC_CheckString (".")) { - if (mod == '+') defaults->DamageType = NAME_Fire; - else defaults->DamageType = NAME_None; + SC_MustGetString (); + part2 = sc_String; } - else if (SC_Compare ("ICEDAMAGE")) + if ( (fd = FindFlag (bag.Info->Class, part1.GetChars(), part2)) ) { - if (mod == '+') defaults->DamageType = NAME_Ice; - 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 (".")) + if (fd->structoffset == -1) // this is a deprecated flag that has been changed into a real property { - SC_MustGetString (); - part2 = sc_String; + HandleDeprecatedFlags(defaults, mod=='+', fd->flagbit); } - if ( (fd = FindFlag (bag.Info->Class, part1.GetChars(), part2)) ) + else { DWORD * flagvar = (DWORD*) ((char*)defaults + fd->structoffset); if (mod == '+') @@ -3274,16 +3330,16 @@ static void ActorFlagSetOrReset (AActor *defaults, Baggage &bag) *flagvar &= ~fd->flagbit; } } + } + else + { + if (part2 == NULL) + { + SC_ScriptError("\"%s\" is an unknown flag\n", part1.GetChars()); + } else { - if (part2 == NULL) - { - SC_ScriptError("\"%s\" is an unknown flag\n", part1.GetChars()); - } - else - { - SC_ScriptError("\"%s.%s\" is an unknown flag\n", part1.GetChars(), part2); - } + 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) }, { "maxdropoffheight", ActorMaxDropoffHeight, RUNTIME_CLASS(AActor) }, { "maxstepheight", ActorMaxStepHeight, RUNTIME_CLASS(AActor) }, + { "maxtargetrange", ActorMaxTargetRange, RUNTIME_CLASS(AActor) }, { "melee", ActorMeleeState, RUNTIME_CLASS(AActor) }, { "meleedamage", ActorMeleeDamage, RUNTIME_CLASS(AActor) }, { "meleerange", ActorMeleeRange, RUNTIME_CLASS(AActor) }, { "meleesound", ActorMeleeSound, RUNTIME_CLASS(AActor) }, + { "meleethreshold", ActorMeleeThreshold, RUNTIME_CLASS(AActor) }, { "minmissilechance", ActorMinMissileChance, RUNTIME_CLASS(AActor) }, { "missile", ActorMissileState, RUNTIME_CLASS(AActor) }, { "missileheight", ActorMissileHeight, RUNTIME_CLASS(AActor) }, diff --git a/wadsrc/decorate/doom/archvile.txt b/wadsrc/decorate/doom/archvile.txt index 997604525..96503d717 100644 --- a/wadsrc/decorate/doom/archvile.txt +++ b/wadsrc/decorate/doom/archvile.txt @@ -15,8 +15,8 @@ ACTOR Archvile 64 Speed 15 PainChance 10 Monster + MaxTargetRange 896 +QUICKTORETALIATE - +SHORTMISSILERANGE +FLOORCLIP +NOTARGET SeeSound "vile/sight" diff --git a/wadsrc/decorate/doom/revenant.txt b/wadsrc/decorate/doom/revenant.txt index 307d8e981..5f0a78691 100644 --- a/wadsrc/decorate/doom/revenant.txt +++ b/wadsrc/decorate/doom/revenant.txt @@ -14,7 +14,7 @@ ACTOR Revenant 66 Speed 10 PainChance 100 Monster - +LONGMELEERANGE + MeleeThreshold 196 +MISSILEMORE +FLOORCLIP SeeSound "skeleton/sight"