gzdoom-gles/src/actor.h

830 lines
31 KiB
C++

// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// $Id:$
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This source is available for distribution and/or modification
// only under the terms of the DOOM Source Code License as
// published by id Software. All rights reserved.
//
// The source is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
// for more details.
//
// DESCRIPTION:
// Map Objects, MObj, definition and handling.
//
//-----------------------------------------------------------------------------
#ifndef __P_MOBJ_H__
#define __P_MOBJ_H__
// Basics.
#include "tables.h"
#include "m_fixed.h"
// We need the thinker_t stuff.
#include "dthinker.h"
// We need the WAD data structure for Map things,
// from the THINGS lump.
#include "doomdata.h"
// States are tied to finite states are
// tied to animation frames.
// Needs precompiled tables/data structures.
#include "info.h"
#include "doomdef.h"
//
// NOTES: AActor
//
// Actors are used to tell the refresh where to draw an image,
// tell the world simulation when objects are contacted,
// and tell the sound driver how to position a sound.
//
// The refresh uses the next and prev links to follow
// lists of things in sectors as they are being drawn.
// The sprite, frame, and angle elements determine which patch_t
// is used to draw the sprite if it is visible.
// The sprite and frame values are almost always set
// from state_t structures.
// The statescr.exe utility generates the states.h and states.c
// files that contain the sprite/frame numbers from the
// statescr.txt source file.
// The xyz origin point represents a point at the bottom middle
// of the sprite (between the feet of a biped).
// This is the default origin position for patch_ts grabbed
// with lumpy.exe.
// A walking creature will have its z equal to the floor
// it is standing on.
//
// The sound code uses the x,y, and sometimes z fields
// to do stereo positioning of any sound emitted by the actor.
//
// The play simulation uses the blocklinks, x,y,z, radius, height
// to determine when AActors are touching each other,
// touching lines in the map, or hit by trace lines (gunshots,
// lines of sight, etc).
// The AActor->flags element has various bit flags
// used by the simulation.
//
// Every actor is linked into a single sector
// based on its origin coordinates.
// The subsector_t is found with R_PointInSubsector(x,y),
// and the sector_t can be found with subsector->sector.
// The sector links are only used by the rendering code,
// the play simulation does not care about them at all.
//
// Any actor that needs to be acted upon by something else
// in the play world (block movement, be shot, etc) will also
// need to be linked into the blockmap.
// If the thing has the MF_NOBLOCK flag set, it will not use
// the block links. It can still interact with other things,
// but only as the instigator (missiles will run into other
// things, but nothing can run into a missile).
// Each block in the grid is 128*128 units, and knows about
// every line_t that it contains a piece of, and every
// interactable actor that has its origin contained.
//
// A valid actor is an actor that has the proper subsector_t
// filled in for its xy coordinates and is linked into the
// sector from which the subsector was made, or has the
// MF_NOSECTOR flag set (the subsector_t needs to be valid
// even if MF_NOSECTOR is set), and is linked into a blockmap
// block or has the MF_NOBLOCKMAP flag set.
// Links should only be modified by the P_[Un]SetThingPosition()
// functions.
// Do not change the MF_NO* flags while a thing is valid.
//
// Any questions?
//
enum
{
// --- mobj.flags ---
MF_SPECIAL = 0x00000001, // call P_SpecialThing when touched
MF_SOLID = 0x00000002,
MF_SHOOTABLE = 0x00000004,
MF_NOSECTOR = 0x00000008, // don't use the sector links
// (invisible but touchable)
MF_NOBLOCKMAP = 0x00000010, // don't use the blocklinks
// (inert but displayable)
MF_AMBUSH = 0x00000020, // not activated by sound; deaf monster
MF_JUSTHIT = 0x00000040, // try to attack right back
MF_JUSTATTACKED = 0x00000080, // take at least one step before attacking
MF_SPAWNCEILING = 0x00000100, // hang from ceiling instead of floor
MF_NOGRAVITY = 0x00000200, // don't apply gravity every tic
// movement flags
MF_DROPOFF = 0x00000400, // allow jumps from high places
MF_PICKUP = 0x00000800, // for players to pick up items
MF_NOCLIP = 0x00001000, // player cheat
MF_INCHASE = 0x00002000, // [RH] used by A_Chase and A_Look to avoid recursion
MF_FLOAT = 0x00004000, // allow moves to any height, no gravity
MF_TELEPORT = 0x00008000, // don't cross lines or look at heights
MF_MISSILE = 0x00010000, // don't hit same species, explode on block
MF_DROPPED = 0x00020000, // dropped by a demon, not level spawned
MF_SHADOW = 0x00040000, // actor is hard for monsters to see
MF_NOBLOOD = 0x00080000, // don't bleed when shot (use puff)
MF_CORPSE = 0x00100000, // don't stop moving halfway off a step
MF_INFLOAT = 0x00200000, // floating to a height for a move, don't
// auto float to target's height
MF_INBOUNCE = 0x00200000, // used by Heretic bouncing missiles
MF_COUNTKILL = 0x00400000, // count towards intermission kill total
MF_COUNTITEM = 0x00800000, // count towards intermission item total
MF_SKULLFLY = 0x01000000, // skull in flight
MF_NOTDMATCH = 0x02000000, // don't spawn in death match (key cards)
MF_SPAWNSOUNDSOURCE = 0x04000000, // Plays missile's see sound at spawning object.
MF_FRIENDLY = 0x08000000, // [RH] Friendly monsters for Strife (and MBF)
MF_UNMORPHED = 0x10000000, // [RH] Actor is the unmorphed version of something else
MF_NOLIFTDROP = 0x20000000, // [RH] Used with MF_NOGRAVITY to avoid dropping with lifts
MF_STEALTH = 0x40000000, // [RH] Andy Baker's stealth monsters
MF_ICECORPSE = 0x80000000, // a frozen corpse (for blasting) [RH] was 0x800000
// --- mobj.flags2 ---
MF2_LOGRAV = 0x00000001, // alternate gravity setting
MF2_WINDTHRUST = 0x00000002, // gets pushed around by the wind specials
MF2_BOUNCE1 = 0x00000004,
MF2_BLASTED = 0x00000008, // actor will temporarily take damage from impact
MF2_FLY = 0x00000010, // fly mode is active
MF2_FLOORCLIP = 0x00000020, // if feet are allowed to be clipped
MF2_SPAWNFLOAT = 0x00000040, // spawn random float z
MF2_NOTELEPORT = 0x00000080, // does not teleport
MF2_RIP = 0x00000100, // missile rips through solid targets
MF2_PUSHABLE = 0x00000200, // can be pushed by other moving actors
MF2_SLIDE = 0x00000400, // slides against walls
MF2_ONMOBJ = 0x00000800, // actor is resting on top of another actor
MF2_PASSMOBJ = 0x00001000, // Enable z block checking. If on,
// this flag will allow the actor to
// pass over/under other actors.
MF2_CANNOTPUSH = 0x00002000, // cannot push other pushable mobjs
MF2_THRUGHOST = 0x00004000, // missile will pass through ghosts [RH] was 8
MF2_BOSS = 0x00008000, // mobj is a major boss
MF2_NODMGTHRUST = 0x00020000, // does not thrust target when damaging
MF2_TELESTOMP = 0x00040000, // mobj can stomp another
MF2_FLOATBOB = 0x00080000, // use float bobbing z movement
MF2_BOUNCE2 = 0x00100000,
MF2_IMPACT = 0x00200000, // an MF_MISSILE mobj can activate SPAC_IMPACT
MF2_PUSHWALL = 0x00400000, // mobj can push walls
MF2_MCROSS = 0x00800000, // can activate monster cross lines
MF2_PCROSS = 0x01000000, // can activate projectile cross lines
MF2_CANTLEAVEFLOORPIC=0x02000000, // stay within a certain floor type
MF2_NONSHOOTABLE = 0x04000000, // mobj is totally non-shootable,
// but still considered solid
MF2_INVULNERABLE = 0x08000000, // mobj is invulnerable
MF2_DORMANT = 0x10000000, // thing is dormant
MF2_SEEKERMISSILE = 0x40000000, // is a seeker (for reflection)
MF2_REFLECTIVE = 0x80000000, // reflects missiles
// The three types of bounciness are:
// HERETIC - Missile will only bounce off the floor once and then enter
// its death state. It does not bounce off walls at all.
// HEXEN - Missile bounces off of walls and floors indefinitely.
// DOOM - Like Hexen, but the bounce turns off if its vertical velocity
// is too low.
MF2_BOUNCETYPE = MF2_BOUNCE1|MF2_BOUNCE2,
MF2_NOBOUNCE = 0,
MF2_HERETICBOUNCE = MF2_BOUNCE1,
MF2_HEXENBOUNCE = MF2_BOUNCE2,
MF2_DOOMBOUNCE = MF2_BOUNCE1|MF2_BOUNCE2,
// --- mobj.flags3 ---
MF3_FLOORHUGGER = 0x00000001, // Missile stays on floor
MF3_CEILINGHUGGER = 0x00000002, // Missile stays on ceiling
MF3_NORADIUSDMG = 0x00000004, // Actor does not take radius damage
MF3_GHOST = 0x00000008, // Actor is a ghost
MF3_ALWAYSPUFF = 0x00000010, // Puff always appears, even when hit nothing
MF3_SPECIALFLOORCLIP= 0x00000020, // Actor uses floorclip for special effect (e.g. Wraith)
MF3_DONTSPLASH = 0x00000040, // Thing doesn't make a splash
MF3_NOSIGHTCHECK = 0x00000080, // Go after first acceptable target without checking sight
MF3_DONTOVERLAP = 0x00000100, // Don't pass over/under other things with this bit set
MF3_DONTMORPH = 0x00000200, // Immune to arti_egg
MF3_DONTSQUASH = 0x00000400, // Death ball can't squash this actor
MF3_EXPLOCOUNT = 0x00000800, // Don't explode until special2 counts to special1
MF3_FULLVOLACTIVE = 0x00001000, // Active sound is played at full volume
MF3_ISMONSTER = 0x00002000, // Actor is a monster
MF3_SKYEXPLODE = 0x00004000, // Explode missile when hitting sky
MF3_STAYMORPHED = 0x00008000, // Monster cannot unmorph
MF3_DONTBLAST = 0x00010000, // Actor cannot be pushed by blasting
MF3_CANBLAST = 0x00020000, // Actor is not a monster but can be blasted
MF3_NOTARGET = 0x00040000, // This actor not targetted when it hurts something else
MF3_DONTGIB = 0x00080000, // Don't gib this corpse
MF3_NOBLOCKMONST = 0x00100000, // Can cross ML_BLOCKMONSTERS lines
MF3_CRASHED = 0x00200000, // Actor entered its crash state
MF3_FULLVOLDEATH = 0x00400000, // DeathSound is played full volume (for missiles)
MF3_CANBOUNCEWATER = 0x00800000, // Missile can bounce on water
MF3_NOWALLBOUNCESND = 0x01000000, // Don't make noise when bouncing off a wall
MF3_FOILINVUL = 0x02000000, // Actor can hurt MF2_INVULNERABLE things
MF3_NOTELEOTHER = 0x04000000, // Monster is unaffected by teleport other artifact
MF3_BLOODLESSIMPACT = 0x08000000, // Projectile does not leave blood
MF3_NOEXPLODEFLOOR = 0x10000000, // Missile stops at floor instead of exploding
MF3_WARNBOT = 0x20000000, // Missile warns bot
MF3_PUFFONACTORS = 0x40000000, // Puff appears even when hit bleeding actors
MF3_HUNTPLAYERS = 0x80000000, // Used with TIDtoHate, means to hate players too
// --- mobj.flags4 ---
MF4_NOHATEPLAYERS = 0x00000001, // Ignore player attacks
MF4_QUICKTORETALIATE= 0x00000002, // Always switch targets when hurt
MF4_NOICEDEATH = 0x00000004, // Actor never enters an ice death, not even the generic one
MF4_BOSSDEATH = 0x00000008, // A_FreezeDeathChunks calls A_BossDeath
MF4_RANDOMIZE = 0x00000010, // Missile has random initial tic count
MF4_NOSKIN = 0x00000020, // Player cannot use skins
MF4_FIXMAPTHINGPOS = 0x00000040, // Fix this actor's position when spawned as a map thing
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_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
MF4_STANDSTILL = 0x00020000, // Monster should not chase targets unless attacked?
MF4_SPECTRAL = 0x00040000,
MF4_FIRERESIST = 0x00080000, // Actor takes half damage from fire
MF4_NOSPLASHALERT = 0x00100000, // Splashes don't alert this monster
MF4_SYNCHRONIZED = 0x00200000, // For actors spawned at load-time only: Do not randomize tics
MF4_NOTARGETSWITCH = 0x00400000, // monster never switches target until current one is dead
MF4_VFRICTION = 0x00800000, // Internal flag used by A_PainAttack to push a monster down
MF4_DONTHURTSPECIES = 0x01000000, // Don't hurt one's own kind with explosions (hitscans, too?)
MF4_SHIELDREFLECT = 0x02000000,
MF4_DEFLECT = 0x04000000, // different projectile reflection styles
MF4_ALLOWPARTICLES = 0x08000000, // this puff type can be replaced by particles
MF4_NOEXTREMEDEATH = 0x10000000, // this projectile or weapon never gibs its victim
MF4_EXTREMEDEATH = 0x20000000, // this projectile or weapon always gibs its victim
MF4_FRIGHTENED = 0x40000000, // Monster runs away from player
MF4_NOBOUNCESOUND = 0x80000000, // Strife's grenades don't make a bouncing sound.
MF5_FASTER = 0x00000001, // moves faster when DF_FAST_MONSTERS or nightmare is on.
MF5_FASTMELEE = 0x00000002, // has a faster melee attack when DF_FAST_MONSTERS or nightmare is on.
MF5_NODROPOFF = 0x00000004, // cannot drop off under any circumstances.
MF5_BOUNCEONACTORS = 0x00000008, // bouncing missile doesn't explode when it hits an actor
MF5_EXPLODEONWATER = 0x00000010, // bouncing missile explodes when hitting a water surface
MF5_AVOIDINGDROPOFF = 0x00000020, // Used to move monsters away from dropoffs
MF5_NODAMAGE = 0x00000040, // Actor can be shot and reacts to being shot but takes no damage
MF5_CHASEGOAL = 0x00000080, // Walks to goal instead of target if a valid goal is set.
MF5_BLOODSPLATTER = 0x00000100, // Blood splatter like in Raven's games.
MF5_OLDRADIUSDMG = 0x00000200, // Use old radius damage code (for barrels and boss brain)
MF5_DEHEXPLOSION = 0x00000400, // Use the DEHACKED explosion options when this projectile explodes
MF5_PIERCEARMOR = 0x00000800, // Armor doesn't protect against damage from this actor
// --- mobj.renderflags ---
RF_XFLIP = 0x0001, // Flip sprite horizontally
RF_YFLIP = 0x0002, // Flip sprite vertically
RF_ONESIDED = 0x0004, // Wall/floor sprite is visible from front only
RF_FULLBRIGHT = 0x0010, // Sprite is drawn at full brightness
RF_RELMASK = 0x0300, // ---Relative z-coord for bound actors (these obey texture pegging)
RF_RELABSOLUTE = 0x0000, // Actor z is absolute
RF_RELUPPER = 0x0100, // Actor z is relative to upper part of wall
RF_RELLOWER = 0x0200, // Actor z is relative to lower part of wall
RF_RELMID = 0x0300, // Actor z is relative to middle part of wall
RF_CLIPMASK = 0x0c00, // ---Clipping for bound actors
RF_CLIPFULL = 0x0000, // Clip sprite to full height of wall
RF_CLIPUPPER = 0x0400, // Clip sprite to upper part of wall
RF_CLIPMID = 0x0800, // Clip sprite to mid part of wall
RF_CLIPLOWER = 0x0c00, // Clip sprite to lower part of wall
RF_DECALMASK = RF_RELMASK|RF_CLIPMASK,
RF_SPRITETYPEMASK = 0x7000, // ---Different sprite types, not all implemented
RF_FACESPRITE = 0x0000, // Face sprite
RF_WALLSPRITE = 0x1000, // Wall sprite
RF_FLOORSPRITE = 0x2000, // Floor sprite
RF_VOXELSPRITE = 0x3000, // Voxel object
RF_INVISIBLE = 0x8000, // Don't bother drawing this actor
// --- dummies for unknown/unimplemented Strife flags ---
MF_STRIFEx8000000 = 0, // seems related to MF_SHADOW
};
enum ERenderStyle
{
STYLE_None, // Do not draw
STYLE_Normal, // Normal; just copy the image to the screen
STYLE_Fuzzy, // Draw silhouette using "fuzz" effect
STYLE_SoulTrans, // Draw translucent with amount in r_transsouls
STYLE_OptFuzzy, // Draw as fuzzy or translucent, based on user preference
STYLE_Stencil, // Fill image interior with alphacolor
// The following styles can affect visibility in P_CheckSight()
STYLE_Translucent=64, // Draw translucent
STYLE_Add, // Draw additive
STYLE_Shaded, // Treat patch data as alpha values for alphacolor
STYLE_TranslucentStencil,
STYLE_Count
};
#define TRANSLUC25 (FRACUNIT/4)
#define TRANSLUC33 (FRACUNIT/3)
#define TRANSLUC50 (FRACUNIT/2)
#define TRANSLUC66 ((FRACUNIT*2)/3)
#define TRANSLUC75 ((FRACUNIT*3)/4)
// <wingdi.h> also #defines OPAQUE
#ifndef OPAQUE
#define OPAQUE (FRACUNIT)
#endif
// This translucency value produces the closest match to Heretic's TINTTAB.
// ~40% of the value of the overlaid image shows through.
#define HR_SHADOW (0x6800)
// Hexen's TINTTAB is the same as Heretic's, just reversed.
#define HX_SHADOW (0x9800)
#define HX_ALTSHADOW (0x6800)
// This could easily be a bool but then it'd be much harder to find later. ;)
enum replace_t
{
NO_REPLACE = 0,
ALLOW_REPLACE = 1
};
// [RH] Like msecnode_t, but for the blockmap
struct FBlockNode
{
AActor *Me; // actor this node references
int BlockIndex; // index into blocklinks for the block this node is in
FBlockNode **PrevActor; // previous actor in this block
FBlockNode *NextActor; // next actor in this block
FBlockNode **PrevBlock; // previous block this actor is in
FBlockNode *NextBlock; // next block this actor is in
static FBlockNode *Create (AActor *who, int x, int y);
void Release ();
static FBlockNode *FreeBlocks;
};
class FDecalBase;
class AInventory;
inline AActor *GetDefaultByName (const char *name)
{
return (AActor *)(PClass::FindClass(name)->Defaults);
}
inline AActor *GetDefaultByType (const PClass *type)
{
return (AActor *)(type->Defaults);
}
template<class T>
inline T *GetDefault ()
{
return (T *)(RUNTIME_CLASS(T)->Defaults);
}
struct secplane_t;
struct FStrifeDialogueNode;
enum
{
AMETA_BASE = 0x12000,
AMETA_Obituary, // string (player was killed by this actor)
AMETA_HitObituary, // string (player was killed by this actor in melee)
AMETA_DeathHeight, // fixed (height on normal death)
AMETA_BurnHeight, // fixed (height on burning death)
AMETA_StrifeName, // string (for named Strife objects)
AMETA_BloodColor, // colorized blood
AMETA_GibHealth, // negative health below which this monster dies an extreme death
AMETA_WoundHealth, // health needed to enter wound state
AMETA_PoisonDamage, // Amount of poison damage
AMETA_FastSpeed, // Speed in fast mode
AMETA_RDFactor, // Radius damage factor
AMETA_CameraHeight, // Height of camera when used as such
};
// Map Object definition.
class AActor : public DThinker
{
DECLARE_CLASS (AActor, DThinker)
HAS_OBJECT_POINTERS
public:
AActor () throw();
AActor (const AActor &other) throw();
AActor &operator= (const AActor &other);
void Destroy ();
~AActor ();
void Serialize (FArchive &arc);
static AActor *StaticSpawn (const PClass *type, fixed_t x, fixed_t y, fixed_t z, replace_t allowreplacement);
inline AActor *GetDefault () const
{
return (AActor *)(RUNTIME_TYPE(this)->Defaults);
}
// BeginPlay: Called just after the actor is created
virtual void BeginPlay ();
// LevelSpawned: Called after BeginPlay if this actor was spawned by the world
virtual void LevelSpawned ();
// Translates SpawnFlags into in-game flags.
virtual void HandleSpawnFlags ();
virtual void Activate (AActor *activator);
virtual void Deactivate (AActor *activator);
virtual void Tick ();
// Smallest yaw interval for a mapthing to be spawned with
virtual angle_t AngleIncrements ();
// Return true if the monster should use a missile attack, false for melee
virtual bool SuggestMissileAttack (fixed_t dist);
// Called when actor dies
virtual void Die (AActor *source, AActor *inflictor);
// Called by A_Explode just before exploding the actor
virtual void PreExplode ();
// Called by A_Explode to find out how much damage to do
virtual void GetExplodeParms (int &damage, int &dist, bool &hurtSource);
// Perform some special damage action. Returns the amount of damage to do.
// Returning -1 signals the damage routine to exit immediately
virtual int DoSpecialDamage (AActor *target, int damage);
// Like DoSpecialDamage, but called on the actor receiving the damage.
virtual int TakeSpecialDamage (AActor *inflictor, AActor *source, int damage, FName damagetype);
// Centaurs and ettins squeal when electrocuted, poisoned, or "holy"-ed
virtual void Howl ();
// Called by A_NoBlocking in case the actor wants to drop some presents
virtual void NoBlockingSet ();
// Called by A_SinkMobj
virtual fixed_t GetSinkSpeed ();
// Called by A_RaiseMobj
virtual fixed_t GetRaiseSpeed ();
// Actor just hit the floor
virtual void HitFloor ();
// Called when an actor with MF_MISSILE and MF2_FLOORBOUNCE hits the floor
virtual bool FloorBounceMissile (secplane_t &plane);
// Adjusts the angle for deflection/reflection of incoming missiles
// Returns true if the missile should be allowed to explode anyway
virtual bool AdjustReflectionAngle (AActor *thing, angle_t &angle);
// Called when an actor is to be reflected by a disc of repulsion.
// Returns true to continue normal blast processing.
virtual bool SpecialBlastHandling (AActor *source, fixed_t strength);
// Called by RoughBlockCheck
virtual bool IsOkayToAttack (AActor *target);
virtual void ChangeSpecial (int special, int data1, int data2,
int data3, int data4, int data5);
// Plays the actor's ActiveSound if its voice isn't already making noise.
void PlayActiveSound ();
// Actor had MF_SKULLFLY set and rammed into something
// Returns false to stop moving and true to keep moving
virtual bool Slam (AActor *victim);
// Called by PIT_CheckThing() and needed for some Hexen things.
// Returns -1 for normal behavior, 0 to return false, and 1 to return true.
// I'm not sure I like it this way, but it will do for now.
virtual int SpecialMissileHit (AActor *victim);
// Returns true if it's okay to switch target to "other" after being attacked by it.
virtual bool OkayToSwitchTarget (AActor *other);
// Returns true if this actor is within melee range of its target
virtual bool CheckMeleeRange ();
// Something just touched this actor.
virtual void Touch (AActor *toucher);
// Adds the item to this actor's inventory and sets its Owner.
virtual void AddInventory (AInventory *item);
// Removes the item from the inventory list.
virtual void RemoveInventory (AInventory *item);
// Uses an item and removes it from the inventory.
virtual bool UseInventory (AInventory *item);
// Tosses an item out of the inventory.
virtual AInventory *DropInventory (AInventory *item);
// Returns true if this view is considered "local" for the player.
bool CheckLocalView (int playernum) const;
// Finds the first item of a particular type.
AInventory *FindInventory (const PClass *type) const;
template<class T> T *FindInventory () const
{
return static_cast<T *> (FindInventory (RUNTIME_CLASS(T)));
}
// Adds one item of a particular type. Returns NULL if it could not be added.
AInventory *GiveInventoryType (const PClass *type);
// Returns the first item held with IF_INVBAR set.
AInventory *FirstInv () const;
// Tries to give the actor some ammo.
bool GiveAmmo (const PClass *type, int amount);
// Destroys all the inventory the actor is holding.
void DestroyAllInventory ();
// Set the alphacolor field properly
void SetShade (DWORD rgb);
void SetShade (int r, int g, int b);
// Plays a conversation animation
void ConversationAnimation (int animnum);
// Make this actor hate the same things as another actor
void CopyFriendliness (const AActor *other, bool changeTarget);
// Moves the other actor's inventory to this one
void ObtainInventory (AActor *other);
// Die. Now.
virtual bool Massacre ();
// Is the other actor on my team?
bool IsTeammate (AActor *other);
// Is the other actor my friend?
bool IsFriend (AActor *other);
// Do I hate the other actor?
bool IsHostile (AActor *other);
// What species am I?
virtual const PClass *GetSpecies();
// Check for monsters that count as kill but excludes all friendlies.
bool CountsAsKill() const
{
return (flags & MF_COUNTKILL) && !(flags & MF_FRIENDLY);
}
// Calculate amount of missile damage
virtual int GetMissileDamage(int mask, int add);
// info for drawing
// NOTE: The first member variable *must* be x.
fixed_t x,y,z;
AActor *snext, **sprev; // links in sector (if needed)
angle_t angle;
WORD sprite; // used to find patch_t and flip value
BYTE frame; // sprite frame to draw
fixed_t scaleX, scaleY; // Scaling values; FRACUNIT is normal size
BYTE RenderStyle; // Style to draw this actor with
DWORD renderflags; // Different rendering flags
WORD picnum; // Draw this instead of sprite if != 0xffff
SWORD TIDtoHate; // TID of things to hate (0 if none)
DWORD effects; // [RH] see p_effect.h
fixed_t alpha;
DWORD alphacolor; // Color to draw when STYLE_Shaded
// interaction info
fixed_t pitch, roll;
FBlockNode *BlockNode; // links in blocks (if needed)
struct sector_t *Sector;
fixed_t floorz, ceilingz; // closest together of contacted secs
fixed_t dropoffz; // killough 11/98: the lowest floor over all contacted Sectors.
struct sector_t *floorsector;
SDWORD floorpic; // contacted sec floorpic
struct sector_t *ceilingsector;
SDWORD ceilingpic; // contacted sec ceilingpic
fixed_t radius, height; // for movement checking
fixed_t momx, momy, momz; // momentums
SDWORD tics; // state tic counter
FState *state;
SDWORD Damage; // For missiles and monster railgun
DWORD flags;
DWORD flags2; // Heretic flags
DWORD flags3; // [RH] Hexen/Heretic actor-dependant behavior made flaggable
DWORD flags4; // [RH] Even more flags!
DWORD flags5; // OMG! We need another one.
int special1; // Special info
int special2; // Special info
int health;
BYTE movedir; // 0-7
SBYTE visdir;
SWORD movecount; // when 0, select a new dir
AActor *target; // thing being chased/attacked (or NULL)
// also the originator for missiles
AActor *lastenemy; // Last known enemy -- killogh 2/15/98
AActor *LastHeard; // [RH] Last actor this one heard
SDWORD reactiontime; // if non 0, don't attack yet; used by
// player to freeze a bit after teleporting
SDWORD threshold; // if > 0, the target will be chased
// no matter what (even if shot)
player_s *player; // only valid if type of APlayerPawn
union
{
AActor *Actor; // Actor last looked for (if TIDtoHate != 0)
SDWORD PlayerNumber; // Player number last looked for
} LastLook;
WORD SpawnPoint[3]; // For nightmare respawn
WORD SpawnAngle;
AActor *tracer; // Thing being chased/attacked for tracers
AActor *master; // Thing which spawned this one (prevents mutual attacks)
fixed_t floorclip; // value to use for floor clipping
SWORD tid; // thing identifier
BYTE special; // special
int args[5]; // special arguments
AActor *inext, **iprev;// Links to other mobjs in same bucket
AActor *goal; // Monster's goal if not chasing anything
BYTE waterlevel; // 0=none, 1=feet, 2=waist, 3=eyes
BYTE MinMissileChance;// [RH] If a random # is > than this, then missile attack.
WORD SpawnFlags;
fixed_t meleerange;
fixed_t bouncefactor; // Strife's grenades use 50%, Hexen's Flechettes 70.
int bouncecount; // Strife's grenades only bounce twice before exploding
// a linked list of sectors where this object appears
struct msecnode_s *touching_sectorlist; // phares 3/14/98
AInventory *Inventory; // [RH] This actor's inventory
DWORD InventoryID; // A unique ID to keep track of inventory items
//Added by MC:
SDWORD id; // Player ID (for items, # in list.)
BYTE FloatBobPhase;
BYTE FriendPlayer; // [RH] Player # + 1 this friendly monster works for (so 0 is no player, 1 is player 0, etc)
WORD Translation;
// [RH] Stuff that used to be part of an Actor Info
WORD SeeSound;
WORD AttackSound;
WORD PainSound;
WORD DeathSound;
WORD ActiveSound;
WORD UseSound; // [RH] Sound to play when an actor is used.
fixed_t Speed;
fixed_t FloatSpeed;
fixed_t MaxDropOffHeight, MaxStepHeight;
SDWORD Mass;
SWORD PainChance;
FNameNoInit DamageType;
FState *SpawnState;
FState *SeeState;
FState *MeleeState;
FState *MissileState;
// [RH] The dialogue to show when this actor is "used."
FStrifeDialogueNode *Conversation;
// [RH] Decal(s) this weapon/projectile generates on impact.
FDecalBase *DecalGenerator;
// [RH] Used to interpolate the view to get >35 FPS
fixed_t PrevX, PrevY, PrevZ;
// ThingIDs
static void ClearTIDHashes ();
void AddToHash ();
void RemoveFromHash ();
private:
static AActor *TIDHash[128];
static inline int TIDHASH (int key) { return key & 127; }
friend class FActorIterator;
sector_t *LinkToWorldForMapThing ();
public:
void LinkToWorld (bool buggy=false);
void LinkToWorld (sector_t *sector);
void UnlinkFromWorld ();
void AdjustFloorClip ();
void SetOrigin (fixed_t x, fixed_t y, fixed_t z);
bool InStateSequence(FState * newstate, FState * basestate);
int GetTics(FState * newstate);
bool SetState (FState *newstate);
bool SetStateNF (FState *newstate);
bool UpdateWaterLevel (fixed_t oldz);
FState *FindState (FName label) const;
FState *FindState (int numnames, int first, ...) const;
FState *FindState (int numnames, va_list arglist) const;
bool HasSpecialDeathStates () const;
static FState States[];
enum { S_NULL = 2, S_GENERICFREEZEDEATH = 3 };
};
class FActorIterator
{
public:
FActorIterator (int i) : base (NULL), id (i)
{
}
FActorIterator (int i, AActor *start) : base (start), id (i)
{
}
AActor *Next ()
{
if (id == 0)
return NULL;
if (!base)
base = AActor::TIDHash[id & 127];
else
base = base->inext;
while (base && base->tid != id)
base = base->inext;
return base;
}
private:
AActor *base;
int id;
};
template<class T>
class TActorIterator : public FActorIterator
{
public:
TActorIterator (int id) : FActorIterator (id) {}
T *Next ()
{
AActor *actor;
do
{
actor = FActorIterator::Next ();
} while (actor && !actor->IsKindOf (RUNTIME_CLASS(T)));
return static_cast<T *>(actor);
}
};
inline AActor *Spawn (const PClass *type, fixed_t x, fixed_t y, fixed_t z, replace_t allowreplacement)
{
return AActor::StaticSpawn (type, x, y, z, allowreplacement);
}
AActor *Spawn (const char *type, fixed_t x, fixed_t y, fixed_t z, replace_t allowreplacement);
template<class T>
inline T *Spawn (fixed_t x, fixed_t y, fixed_t z, replace_t allowreplacement)
{
return static_cast<T *>(AActor::StaticSpawn (RUNTIME_CLASS(T), x, y, z, allowreplacement));
}
#define S_FREETARGMOBJ 1
struct FSoundIndex
{
int Index;
};
struct FSoundIndexWord
{
WORD Index;
};
FArchive &operator<< (FArchive &arc, FSoundIndex &snd);
FArchive &operator<< (FArchive &arc, FSoundIndexWord &snd);
#define AR_SOUND(id) (*(FSoundIndex *)&(id))
#define AR_SOUNDW(id) (*(FSoundIndexWord *)&(id))
#endif // __P_MOBJ_H__