mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-12-12 13:42:53 +00:00
- implemented MBF's monsters_avoid_hazards feature.
Both as a map flag for MBF21 support and as an actor flag for better control.
This commit is contained in:
parent
5382e7c17b
commit
d15f450fef
8 changed files with 85 additions and 7 deletions
|
@ -1663,6 +1663,7 @@ MapFlagHandlers[] =
|
|||
{ "enableskyboxao", MITYPE_SETFLAG3, LEVEL3_SKYBOXAO, 0 },
|
||||
{ "disableskyboxao", MITYPE_CLRFLAG3, LEVEL3_SKYBOXAO, 0 },
|
||||
{ "avoidmelee", MITYPE_SETFLAG3, LEVEL3_AVOIDMELEE, 0 },
|
||||
{ "avoidhazards", MITYPE_SETFLAG3, LEVEL3_AVOID_HAZARDS, 0 },
|
||||
{ "nobotnodes", MITYPE_IGNORE, 0, 0 }, // Skulltag option: nobotnodes
|
||||
{ "compat_shorttex", MITYPE_COMPATFLAG, COMPATF_SHORTTEX, 0 },
|
||||
{ "compat_stairs", MITYPE_COMPATFLAG, COMPATF_STAIRINDEX, 0 },
|
||||
|
|
|
@ -260,6 +260,7 @@ enum ELevelFlags : unsigned int
|
|||
LEVEL3_NOSHADOWMAP = 0x00010000, // disables shadowmaps for a given level.
|
||||
LEVEL3_AVOIDMELEE = 0x00020000, // global flag needed for proper MBF support.
|
||||
LEVEL3_NOJUMPDOWN = 0x00040000, // only for MBF21. Inverse of MBF's dog_jumping flag.
|
||||
LEVEL3_AVOID_HAZARDS = 0x00080000, // another MBF thing.
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -421,6 +421,7 @@ enum ActorFlag8
|
|||
MF8_E4M6BOSS = 0x00200000, // MBF21 boss death.
|
||||
MF8_MAP07BOSS1 = 0x00400000, // MBF21 boss death.
|
||||
MF8_MAP07BOSS2 = 0x00800000, // MBF21 boss death.
|
||||
MF8_AVOIDHAZARDS = 0x01000000, // MBF AI enhancement.
|
||||
};
|
||||
|
||||
// --- mobj.renderflags ---
|
||||
|
|
|
@ -54,6 +54,9 @@ public:
|
|||
void Serialize(FSerializer &arc);
|
||||
void Tick ();
|
||||
|
||||
int getCrush() const { return m_Crush; }
|
||||
int getDirection() const { return m_Direction; }
|
||||
|
||||
protected:
|
||||
ECeiling m_Type;
|
||||
double m_BottomHeight;
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#include "g_levellocals.h"
|
||||
#include "vm.h"
|
||||
#include "actorinlines.h"
|
||||
#include "a_ceiling.h"
|
||||
|
||||
#include "gi.h"
|
||||
|
||||
|
@ -67,6 +68,7 @@ static FRandom pr_look3 ("IGotHooky");
|
|||
static FRandom pr_slook ("SlooK");
|
||||
static FRandom pr_dropoff ("Dropoff");
|
||||
static FRandom pr_defect ("Defect");
|
||||
static FRandom pr_avoidcrush("AvoidCrush");
|
||||
|
||||
static FRandom pr_skiptarget("SkipTarget");
|
||||
static FRandom pr_enemystrafe("EnemyStrafe");
|
||||
|
@ -414,13 +416,41 @@ int P_HitFriend(AActor * self)
|
|||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* P_IsUnderDamage
|
||||
*
|
||||
* killough 9/9/98:
|
||||
*
|
||||
* Returns nonzero if the object is under damage based on
|
||||
* their current position. Returns 1 if the damage is moderate,
|
||||
* -1 if it is serious. Used for AI.
|
||||
*/
|
||||
|
||||
static int P_IsUnderDamage(AActor* actor)
|
||||
{
|
||||
msecnode_t* seclist;
|
||||
int dir = 0;
|
||||
for (seclist = actor->touching_sectorlist; seclist; seclist = seclist->m_tnext)
|
||||
{
|
||||
DSectorEffect* e = seclist->m_sector->ceilingdata;
|
||||
if (e && e->IsKindOf(RUNTIME_CLASS(DCeiling)))
|
||||
{
|
||||
auto cl = (DCeiling*)e;
|
||||
if (cl->getCrush() > 0) // unlike MBF we need to consider non-crushing ceiling movers here.
|
||||
dir |= cl->getDirection();
|
||||
}
|
||||
// Q: consider crushing 3D floors too?
|
||||
}
|
||||
return dir;
|
||||
}
|
||||
|
||||
//
|
||||
// P_Move
|
||||
// Move in the current direction,
|
||||
// returns false if the move is blocked.
|
||||
//
|
||||
|
||||
int P_Move (AActor *actor)
|
||||
static int P_Move (AActor *actor)
|
||||
{
|
||||
|
||||
double tryx, tryy, deltax, deltay, origx, origy;
|
||||
|
@ -653,6 +683,47 @@ int P_Move (AActor *actor)
|
|||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// P_SmartMove
|
||||
//
|
||||
// killough 9/12/98: Same as P_Move, except smarter
|
||||
//
|
||||
|
||||
int P_SmartMove(AActor* actor)
|
||||
{
|
||||
AActor* target = actor->target;
|
||||
int on_lift = false, dropoff = false, under_damage;
|
||||
bool monster_avoid_hazards = (actor->Level->flags3 & LEVEL3_AVOID_HAZARDS) || (actor->flags8 & MF8_AVOIDHAZARDS);
|
||||
|
||||
#if 0
|
||||
/* killough 9/12/98: Stay on a lift if target is on one */
|
||||
on_lift = !comp[comp_staylift]
|
||||
&& target && target->health > 0
|
||||
&& target->subsector->sector->tag == actor->subsector->sector->tag &&
|
||||
P_IsOnLift(actor);
|
||||
#endif
|
||||
|
||||
under_damage = monster_avoid_hazards && P_IsUnderDamage(actor) != 0;//e6y
|
||||
|
||||
if (!P_Move(actor))
|
||||
return false;
|
||||
|
||||
// killough 9/9/98: avoid crushing ceilings or other damaging areas
|
||||
if (
|
||||
#if 0
|
||||
(on_lift && P_Random(pr_stayonlift) < 230 && // Stay on lift
|
||||
!P_IsOnLift(actor))
|
||||
||
|
||||
#endif
|
||||
(monster_avoid_hazards && !under_damage && //e6y // Get away from damage
|
||||
(under_damage = P_IsUnderDamage(actor)) &&
|
||||
(under_damage < 0 || pr_avoidcrush() < 200))
|
||||
)
|
||||
actor->movedir = DI_NODIR; // avoid the area (most of the time anyway)
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// TryWalk
|
||||
|
@ -669,7 +740,7 @@ int P_Move (AActor *actor)
|
|||
|
||||
bool P_TryWalk (AActor *actor)
|
||||
{
|
||||
if (!P_Move (actor))
|
||||
if (!P_SmartMove (actor))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -2123,7 +2194,7 @@ void A_Wander(AActor *self, int flags)
|
|||
}
|
||||
}
|
||||
|
||||
if ((--self->movecount < 0 && !(flags & CHF_NORANDOMTURN)) || (!P_Move(self) && !(flags & CHF_STOPIFBLOCKED)))
|
||||
if ((--self->movecount < 0 && !(flags & CHF_NORANDOMTURN)) || (!P_SmartMove(self) && !(flags & CHF_STOPIFBLOCKED)))
|
||||
{
|
||||
P_RandomChaseDir(self);
|
||||
self->movecount += 5;
|
||||
|
@ -2525,7 +2596,7 @@ void A_DoChase (AActor *actor, bool fastchase, FState *meleestate, FState *missi
|
|||
FTextureID oldFloor = actor->floorpic;
|
||||
|
||||
// chase towards player
|
||||
if ((--actor->movecount < 0 && !(flags & CHF_NORANDOMTURN)) || (!P_Move(actor) && !(flags & CHF_STOPIFBLOCKED)))
|
||||
if ((--actor->movecount < 0 && !(flags & CHF_NORANDOMTURN)) || (!P_SmartMove(actor) && !(flags & CHF_STOPIFBLOCKED)))
|
||||
{
|
||||
P_NewChaseDir(actor);
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ int P_HitFriend (AActor *self);
|
|||
void P_NoiseAlert (AActor *emmiter, AActor *target, bool splash=false, double maxdist=0);
|
||||
|
||||
bool P_CheckMeleeRange2 (AActor *actor);
|
||||
int P_Move (AActor *actor);
|
||||
int P_SmartMove (AActor *actor);
|
||||
bool P_TryWalk (AActor *actor);
|
||||
void P_NewChaseDir (AActor *actor);
|
||||
void P_RandomChaseDir(AActor *actor);;
|
||||
|
|
|
@ -336,6 +336,7 @@ static FFlagDef ActorFlagDefs[]=
|
|||
DEFINE_FLAG(MF8, E4M6BOSS, AActor, flags8),
|
||||
DEFINE_FLAG(MF8, MAP07BOSS1, AActor, flags8),
|
||||
DEFINE_FLAG(MF8, MAP07BOSS2, AActor, flags8),
|
||||
DEFINE_FLAG(MF8, AVOIDHAZARDS, AActor, flags8),
|
||||
|
||||
// Effect flags
|
||||
DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects),
|
||||
|
|
|
@ -1443,10 +1443,10 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, HitFriend, P_HitFriend)
|
|||
ACTION_RETURN_BOOL(P_HitFriend(self));
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_NATIVE(AActor, MonsterMove, P_Move)
|
||||
DEFINE_ACTION_FUNCTION_NATIVE(AActor, MonsterMove, P_SmartMove)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
ACTION_RETURN_BOOL(P_Move(self));
|
||||
ACTION_RETURN_BOOL(P_SmartMove(self));
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_NATIVE(AActor, NewChaseDir, P_NewChaseDir)
|
||||
|
|
Loading…
Reference in a new issue