1 // Emacs style mode select -*- C++ -*-
2 //-----------------------------------------------------------------------------
3 //
4 // $Id:$
5 //
6 // Copyright (C) 1993-1996 by id Software, Inc.
7 //
8 // This source is available for distribution and/or modification
9 // only under the terms of the DOOM Source Code License as
10 // published by id Software. All rights reserved.
11 //
12 // The source is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
15 // for more details.
16 //
17 // DESCRIPTION:
18 // Map Objects, MObj, definition and handling.
19 //
20 //-----------------------------------------------------------------------------
21
22
23 #ifndef __P_MOBJ_H__
24 #define __P_MOBJ_H__
25
26 // Basics.
27 #include "tables.h"
28
29 // We need the thinker_t stuff.
30 #include "dthinker.h"
31
32
33 // States are tied to finite states are tied to animation frames.
34 #include "info.h"
35
36 #include "doomdef.h"
37 #include "textures/textures.h"
38 #include "r_data/renderstyle.h"
39 #include "s_sound.h"
40 #include "memarena.h"
41 #include "g_level.h"
42 #include "tflags.h"
43
44 struct subsector_t;
45 //
46 // NOTES: AActor
47 //
48 // Actors are used to tell the refresh where to draw an image,
49 // tell the world simulation when objects are contacted,
50 // and tell the sound driver how to position a sound.
51 //
52 // The refresh uses the next and prev links to follow
53 // lists of things in sectors as they are being drawn.
54 // The sprite, frame, and angle elements determine which patch_t
55 // is used to draw the sprite if it is visible.
56 // The sprite and frame values are almost always set
57 // from state_t structures.
58 // The statescr.exe utility generates the states.h and states.c
59 // files that contain the sprite/frame numbers from the
60 // statescr.txt source file.
61 // The xyz origin point represents a point at the bottom middle
62 // of the sprite (between the feet of a biped).
63 // This is the default origin position for patch_ts grabbed
64 // with lumpy.exe.
65 // A walking creature will have its z equal to the floor
66 // it is standing on.
67 //
68 // The sound code uses the x,y, and sometimes z fields
69 // to do stereo positioning of any sound emitted by the actor.
70 //
71 // The play simulation uses the blocklinks, x,y,z, radius, height
72 // to determine when AActors are touching each other,
73 // touching lines in the map, or hit by trace lines (gunshots,
74 // lines of sight, etc).
75 // The AActor->flags element has various bit flags
76 // used by the simulation.
77 //
78 // Every actor is linked into a single sector
79 // based on its origin coordinates.
80 // The subsector_t is found with R_PointInSubsector(x,y),
81 // and the sector_t can be found with subsector->sector.
82 // The sector links are only used by the rendering code,
83 // the play simulation does not care about them at all.
84 //
85 // Any actor that needs to be acted upon by something else
86 // in the play world (block movement, be shot, etc) will also
87 // need to be linked into the blockmap.
88 // If the thing has the MF_NOBLOCK flag set, it will not use
89 // the block links. It can still interact with other things,
90 // but only as the instigator (missiles will run into other
91 // things, but nothing can run into a missile).
92 // Each block in the grid is 128*128 units, and knows about
93 // every line_t that it contains a piece of, and every
94 // interactable actor that has its origin contained.
95 //
96 // A valid actor is an actor that has the proper subsector_t
97 // filled in for its xy coordinates and is linked into the
98 // sector from which the subsector was made, or has the
99 // MF_NOSECTOR flag set (the subsector_t needs to be valid
100 // even if MF_NOSECTOR is set), and is linked into a blockmap
101 // block or has the MF_NOBLOCKMAP flag set.
102 // Links should only be modified by the P_[Un]SetThingPosition()
103 // functions.
104 // Do not change the MF_NO* flags while a thing is valid.
105 //
106 // Any questions?
107 //
108
109 // --- mobj.flags ---
110 enum ActorFlag
111 {
112 MF_SPECIAL = 0x00000001, // call P_SpecialThing when touched
113 MF_SOLID = 0x00000002,
114 MF_SHOOTABLE = 0x00000004,
115 MF_NOSECTOR = 0x00000008, // don't use the sector links
116 // (invisible but touchable)
117 MF_NOBLOCKMAP = 0x00000010, // don't use the blocklinks
118 // (inert but displayable)
119 MF_AMBUSH = 0x00000020, // not activated by sound; deaf monster
120 MF_JUSTHIT = 0x00000040, // try to attack right back
121 MF_JUSTATTACKED = 0x00000080, // take at least one step before attacking
122 MF_SPAWNCEILING = 0x00000100, // hang from ceiling instead of floor
123 MF_NOGRAVITY = 0x00000200, // don't apply gravity every tic
124
125 // movement flags
126 MF_DROPOFF = 0x00000400, // allow jumps from high places
127 MF_PICKUP = 0x00000800, // for players to pick up items
128 MF_NOCLIP = 0x00001000, // player cheat
129 MF_INCHASE = 0x00002000, // [RH] used by A_Chase and A_Look to avoid recursion
130 MF_FLOAT = 0x00004000, // allow moves to any height, no gravity
131 MF_TELEPORT = 0x00008000, // don't cross lines or look at heights
132 MF_MISSILE = 0x00010000, // don't hit same species, explode on block
133
134 MF_DROPPED = 0x00020000, // dropped by a demon, not level spawned
135 MF_SHADOW = 0x00040000, // actor is hard for monsters to see
136 MF_NOBLOOD = 0x00080000, // don't bleed when shot (use puff)
137 MF_CORPSE = 0x00100000, // don't stop moving halfway off a step
138 MF_INFLOAT = 0x00200000, // floating to a height for a move, don't
139 // auto float to target's height
140 MF_INBOUNCE = 0x00200000, // used by Heretic bouncing missiles
141
142 MF_COUNTKILL = 0x00400000, // count towards intermission kill total
143 MF_COUNTITEM = 0x00800000, // count towards intermission item total
144
145 MF_SKULLFLY = 0x01000000, // skull in flight
146 MF_NOTDMATCH = 0x02000000, // don't spawn in death match (key cards)
147
148 MF_SPAWNSOUNDSOURCE = 0x04000000, // Plays missile's see sound at spawning object.
149 MF_FRIENDLY = 0x08000000, // [RH] Friendly monsters for Strife (and MBF)
150 MF_UNMORPHED = 0x10000000, // [RH] Actor is the unmorphed version of something else
151 MF_NOLIFTDROP = 0x20000000, // [RH] Used with MF_NOGRAVITY to avoid dropping with lifts
152 MF_STEALTH = 0x40000000, // [RH] Andy Baker's stealth monsters
153 MF_ICECORPSE = 0x80000000, // a frozen corpse (for blasting) [RH] was 0x800000
154
155 // --- dummies for unknown/unimplemented Strife flags ---
156 MF_STRIFEx8000000 = 0, // seems related to MF_SHADOW
157 };
158
159 // --- mobj.flags2 ---
160 enum ActorFlag2
161 {
162 MF2_DONTREFLECT = 0x00000001, // this projectile cannot be reflected
163 MF2_WINDTHRUST = 0x00000002, // gets pushed around by the wind specials
164 MF2_DONTSEEKINVISIBLE=0x00000004, // For seeker missiles: Don't home in on invisible/shadow targets
165 MF2_BLASTED = 0x00000008, // actor will temporarily take damage from impact
166 MF2_FLY = 0x00000010, // fly mode is active
167 MF2_FLOORCLIP = 0x00000020, // if feet are allowed to be clipped
168 MF2_SPAWNFLOAT = 0x00000040, // spawn random float z
169 MF2_NOTELEPORT = 0x00000080, // does not teleport
170 MF2_RIP = 0x00000100, // missile rips through solid targets
171 MF2_PUSHABLE = 0x00000200, // can be pushed by other moving actors
172 MF2_SLIDE = 0x00000400, // slides against walls
173 MF2_ONMOBJ = 0x00000800, // actor is resting on top of another actor
174 MF2_PASSMOBJ = 0x00001000, // Enable z block checking. If on,
175 // this flag will allow the actor to
176 // pass over/under other actors.
177 MF2_CANNOTPUSH = 0x00002000, // cannot push other pushable mobjs
178 MF2_THRUGHOST = 0x00004000, // missile will pass through ghosts [RH] was 8
179 MF2_BOSS = 0x00008000, // mobj is a major boss
180
181 MF2_DONTTRANSLATE = 0x00010000, // Don't apply palette translations
182 MF2_NODMGTHRUST = 0x00020000, // does not thrust target when damaging
183 MF2_TELESTOMP = 0x00040000, // mobj can stomp another
184 MF2_FLOATBOB = 0x00080000, // use float bobbing z movement
185 MF2_THRUACTORS = 0x00100000, // performs no actor<->actor collision checks
186 MF2_IMPACT = 0x00200000, // an MF_MISSILE mobj can activate SPAC_IMPACT
187 MF2_PUSHWALL = 0x00400000, // mobj can push walls
188 MF2_MCROSS = 0x00800000, // can activate monster cross lines
189 MF2_PCROSS = 0x01000000, // can activate projectile cross lines
190 MF2_CANTLEAVEFLOORPIC=0x02000000, // stay within a certain floor type
191 MF2_NONSHOOTABLE = 0x04000000, // mobj is totally non-shootable,
192 // but still considered solid
193 MF2_INVULNERABLE = 0x08000000, // mobj is invulnerable
194 MF2_DORMANT = 0x10000000, // thing is dormant
195 MF2_ARGSDEFINED = 0x20000000, // Internal flag used by DECORATE to signal that the
196 // args should not be taken from the mapthing definition
197 MF2_SEEKERMISSILE = 0x40000000, // is a seeker (for reflection)
198 MF2_REFLECTIVE = 0x80000000, // reflects missiles
199 };
200
201 // --- mobj.flags3 ---
202 enum ActorFlag3
203 {
204 MF3_FLOORHUGGER = 0x00000001, // Missile stays on floor
205 MF3_CEILINGHUGGER = 0x00000002, // Missile stays on ceiling
206 MF3_NORADIUSDMG = 0x00000004, // Actor does not take radius damage
207 MF3_GHOST = 0x00000008, // Actor is a ghost
208 MF3_ALWAYSPUFF = 0x00000010, // Puff always appears, even when hit nothing
209 MF3_SPECIALFLOORCLIP= 0x00000020, // Actor uses floorclip for special effect (e.g. Wraith)
210 MF3_DONTSPLASH = 0x00000040, // Thing doesn't make a splash
211 MF3_NOSIGHTCHECK = 0x00000080, // Go after first acceptable target without checking sight
212 MF3_DONTOVERLAP = 0x00000100, // Don't pass over/under other things with this bit set
213 MF3_DONTMORPH = 0x00000200, // Immune to arti_egg
214 MF3_DONTSQUASH = 0x00000400, // Death ball can't squash this actor
215 MF3_EXPLOCOUNT = 0x00000800, // Don't explode until special2 counts to special1
216 MF3_FULLVOLACTIVE = 0x00001000, // Active sound is played at full volume
217 MF3_ISMONSTER = 0x00002000, // Actor is a monster
218 MF3_SKYEXPLODE = 0x00004000, // Explode missile when hitting sky
219 MF3_STAYMORPHED = 0x00008000, // Monster cannot unmorph
220 MF3_DONTBLAST = 0x00010000, // Actor cannot be pushed by blasting
221 MF3_CANBLAST = 0x00020000, // Actor is not a monster but can be blasted
222 MF3_NOTARGET = 0x00040000, // This actor not targetted when it hurts something else
223 MF3_DONTGIB = 0x00080000, // Don't gib this corpse
224 MF3_NOBLOCKMONST = 0x00100000, // Can cross ML_BLOCKMONSTERS lines
225 MF3_CRASHED = 0x00200000, // Actor entered its crash state
226 MF3_FULLVOLDEATH = 0x00400000, // DeathSound is played full volume (for missiles)
227 MF3_AVOIDMELEE = 0x00800000, // Avoids melee attacks (same as MBF's monster_backing but must be explicitly set)
228 MF3_SCREENSEEKER = 0x01000000, // Fails the IsOkayToAttack test if potential target is outside player FOV
229 MF3_FOILINVUL = 0x02000000, // Actor can hurt MF2_INVULNERABLE things
230 MF3_NOTELEOTHER = 0x04000000, // Monster is unaffected by teleport other artifact
231 MF3_BLOODLESSIMPACT = 0x08000000, // Projectile does not leave blood
232 MF3_NOEXPLODEFLOOR = 0x10000000, // Missile stops at floor instead of exploding
233 MF3_WARNBOT = 0x20000000, // Missile warns bot
234 MF3_PUFFONACTORS = 0x40000000, // Puff appears even when hit bleeding actors
235 MF3_HUNTPLAYERS = 0x80000000, // Used with TIDtoHate, means to hate players too
236 };
237
238 // --- mobj.flags4 ---
239 enum ActorFlag4
240 {
241 MF4_NOHATEPLAYERS = 0x00000001, // Ignore player attacks
242 MF4_QUICKTORETALIATE= 0x00000002, // Always switch targets when hurt
243 MF4_NOICEDEATH = 0x00000004, // Actor never enters an ice death, not even the generic one
244 MF4_BOSSDEATH = 0x00000008, // A_FreezeDeathChunks calls A_BossDeath
245 MF4_RANDOMIZE = 0x00000010, // Missile has random initial tic count
246 MF4_NOSKIN = 0x00000020, // Player cannot use skins
247 MF4_FIXMAPTHINGPOS = 0x00000040, // Fix this actor's position when spawned as a map thing
248 MF4_ACTLIKEBRIDGE = 0x00000080, // Pickups can "stand" on this actor / cannot be moved by any sector action.
249 MF4_STRIFEDAMAGE = 0x00000100, // Strife projectiles only do up to 4x damage, not 8x
250
251 MF4_CANUSEWALLS = 0x00000200, // Can activate 'use' specials
252 MF4_MISSILEMORE = 0x00000400, // increases the chance of a missile attack
253 MF4_MISSILEEVENMORE = 0x00000800, // significantly increases the chance of a missile attack
254 MF4_FORCERADIUSDMG = 0x00001000, // if put on an object it will override MF3_NORADIUSDMG
255 MF4_DONTFALL = 0x00002000, // Doesn't have NOGRAVITY disabled when dying.
256 MF4_SEESDAGGERS = 0x00004000, // This actor can see you striking with a dagger
257 MF4_INCOMBAT = 0x00008000, // Don't alert others when attacked by a dagger
258 MF4_LOOKALLAROUND = 0x00010000, // Monster has eyes in the back of its head
259 MF4_STANDSTILL = 0x00020000, // Monster should not chase targets unless attacked?
260 MF4_SPECTRAL = 0x00040000,
261 MF4_SCROLLMOVE = 0x00080000, // velocity has been applied by a scroller
262 MF4_NOSPLASHALERT = 0x00100000, // Splashes don't alert this monster
263 MF4_SYNCHRONIZED = 0x00200000, // For actors spawned at load-time only: Do not randomize tics
264 MF4_NOTARGETSWITCH = 0x00400000, // monster never switches target until current one is dead
265 MF4_VFRICTION = 0x00800000, // Internal flag used by A_PainAttack to push a monster down
266 MF4_DONTHARMCLASS = 0x01000000, // Don't hurt one's own kind with explosions (hitscans, too?)
267 MF4_SHIELDREFLECT = 0x02000000,
268 MF4_DEFLECT = 0x04000000, // different projectile reflection styles
269 MF4_ALLOWPARTICLES = 0x08000000, // this puff type can be replaced by particles
270 MF4_NOEXTREMEDEATH = 0x10000000, // this projectile or weapon never gibs its victim
271 MF4_EXTREMEDEATH = 0x20000000, // this projectile or weapon always gibs its victim
272 MF4_FRIGHTENED = 0x40000000, // Monster runs away from player
273 MF4_BOSSSPAWNED = 0x80000000, // Spawned by a boss spawn cube
274 };
275
276 // --- mobj.flags5 ---
277
278 enum ActorFlag5
279 {
280 MF5_DONTDRAIN = 0x00000001, // cannot be drained health from.
281 /* = 0x00000002, reserved for use by scripting branch */
282 MF5_NODROPOFF = 0x00000004, // cannot drop off under any circumstances.
283 MF5_NOFORWARDFALL = 0x00000008, // Does not make any actor fall forward by being damaged by this
284 MF5_COUNTSECRET = 0x00000010, // From Doom 64: actor acts like a secret
285 MF5_AVOIDINGDROPOFF = 0x00000020, // Used to move monsters away from dropoffs
286 MF5_NODAMAGE = 0x00000040, // Actor can be shot and reacts to being shot but takes no damage
287 MF5_CHASEGOAL = 0x00000080, // Walks to goal instead of target if a valid goal is set.
288 MF5_BLOODSPLATTER = 0x00000100, // Blood splatter like in Raven's games.
289 MF5_OLDRADIUSDMG = 0x00000200, // Use old radius damage code (for barrels and boss brain)
290 MF5_DEHEXPLOSION = 0x00000400, // Use the DEHACKED explosion options when this projectile explodes
291 MF5_PIERCEARMOR = 0x00000800, // Armor doesn't protect against damage from this actor
292 MF5_NOBLOODDECALS = 0x00001000, // Actor bleeds but doesn't spawn blood decals
293 MF5_USESPECIAL = 0x00002000, // Actor executes its special when being 'used'.
294 MF5_NOPAIN = 0x00004000, // If set the pain state won't be entered
295 MF5_ALWAYSFAST = 0x00008000, // always uses 'fast' attacking logic
296 MF5_NEVERFAST = 0x00010000, // never uses 'fast' attacking logic
297 MF5_ALWAYSRESPAWN = 0x00020000, // always respawns, regardless of skill setting
298 MF5_NEVERRESPAWN = 0x00040000, // never respawns, regardless of skill setting
299 MF5_DONTRIP = 0x00080000, // Ripping projectiles explode when hitting this actor
300 MF5_NOINFIGHTING = 0x00100000, // This actor doesn't switch target when it's hurt
301 MF5_NOINTERACTION = 0x00200000, // Thing is completely excluded from any gameplay related checks
302 MF5_NOTIMEFREEZE = 0x00400000, // Actor is not affected by time freezer
303 MF5_PUFFGETSOWNER = 0x00800000, // [BB] Sets the owner of the puff to the player who fired it
304 MF5_SPECIALFIREDAMAGE=0x01000000, // Special treatment of PhoenixFX1 turned into a flag to remove
305 // dependence of main engine code of specific actor types.
306 MF5_SUMMONEDMONSTER = 0x02000000, // To mark the friendly Minotaur. Hopefully to be generalized later.
307 MF5_NOVERTICALMELEERANGE=0x04000000,// Does not check vertical distance for melee range
308 MF5_BRIGHT = 0x08000000, // Actor is always rendered fullbright
309 MF5_CANTSEEK = 0x10000000, // seeker missiles cannot home in on this actor
310 MF5_INCONVERSATION = 0x20000000, // Actor is having a conversation
311 MF5_PAINLESS = 0x40000000, // Actor always inflicts painless damage.
312 MF5_MOVEWITHSECTOR = 0x80000000, // P_ChangeSector() will still process this actor if it has MF_NOBLOCKMAP
313 };
314
315 // --- mobj.flags6 ---
316 enum ActorFlag6
317 {
318 MF6_NOBOSSRIP = 0x00000001, // For rippermissiles: Don't rip through bosses.
319 MF6_THRUSPECIES = 0x00000002, // Actors passes through other of the same species.
320 MF6_MTHRUSPECIES = 0x00000004, // Missile passes through actors of its shooter's species.
321 MF6_FORCEPAIN = 0x00000008, // forces target into painstate (unless it has the NOPAIN flag)
322 MF6_NOFEAR = 0x00000010, // Not scared of frightening players
323 MF6_BUMPSPECIAL = 0x00000020, // Actor executes its special when being collided (as the ST flag)
324 MF6_DONTHARMSPECIES = 0x00000040, // Don't hurt one's own species with explosions (hitscans, too?)
325 MF6_STEPMISSILE = 0x00000080, // Missile can "walk" up steps
326 MF6_NOTELEFRAG = 0x00000100, // [HW] Actor can't be telefragged
327 MF6_TOUCHY = 0x00000200, // From MBF: killough 11/98: dies when solids touch it
328 MF6_CANJUMP = 0x00000400, // From MBF: a dedicated flag instead of the BOUNCES+FLOAT+sentient combo
329 MF6_JUMPDOWN = 0x00000800, // From MBF: generalization of dog behavior wrt. dropoffs.
330 MF6_VULNERABLE = 0x00001000, // Actor can be damaged (even if not shootable).
331 MF6_ARMED = 0x00002000, // From MBF: Object is armed (for MF6_TOUCHY objects)
332 MF6_FALLING = 0x00004000, // From MBF: Object is falling (for pseudotorque simulation)
333 MF6_LINEDONE = 0x00008000, // From MBF: Object has already run a line effect
334 MF6_NOTRIGGER = 0x00010000, // actor cannot trigger any line actions
335 MF6_SHATTERING = 0x00020000, // marks an ice corpse for forced shattering
336 MF6_KILLED = 0x00040000, // Something that was killed (but not necessarily a corpse)
337 MF6_BLOCKEDBYSOLIDACTORS = 0x00080000, // Blocked by solid actors, even if not solid itself
338 MF6_ADDITIVEPOISONDAMAGE = 0x00100000,
339 MF6_ADDITIVEPOISONDURATION = 0x00200000,
340 MF6_NOMENU = 0x00400000, // Player class should not appear in the class selection menu.
341 MF6_BOSSCUBE = 0x00800000, // Actor spawned by A_BrainSpit, flagged for timefreeze reasons.
342 MF6_SEEINVISIBLE = 0x01000000, // Monsters can see invisible player.
343 MF6_DONTCORPSE = 0x02000000, // [RC] Don't autoset MF_CORPSE upon death and don't force Crash state change.
344 MF6_POISONALWAYS = 0x04000000, // Always apply poison, even when target can't take the damage.
345 MF6_DOHARMSPECIES = 0x08000000, // Do hurt one's own species with projectiles.
346 MF6_INTRYMOVE = 0x10000000, // Executing P_TryMove
347 MF6_NOTAUTOAIMED = 0x20000000, // Do not subject actor to player autoaim.
348 MF6_NOTONAUTOMAP = 0x40000000, // will not be shown on automap with the 'scanner' powerup.
349 MF6_RELATIVETOFLOOR = 0x80000000, // [RC] Make flying actors be affected by lifts.
350 };
351
352 // --- mobj.flags7 ---
353 enum ActorFlag7
354 {
355 MF7_NEVERTARGET = 0x00000001, // can not be targetted at all, even if monster friendliness is considered.
356 MF7_NOTELESTOMP = 0x00000002, // cannot telefrag under any circumstances (even when set by MAPINFO)
357 MF7_ALWAYSTELEFRAG = 0x00000004, // will unconditionally be telefragged when in the way. Overrides all other settings.
358 MF7_HANDLENODELAY = 0x00000008, // respect NoDelay state flag
359 MF7_WEAPONSPAWN = 0x00000010, // subject to DF_NO_COOP_WEAPON_SPAWN dmflag
360 MF7_HARMFRIENDS = 0x00000020, // is allowed to harm friendly monsters.
361 MF7_BUDDHA = 0x00000040, // Behaves just like the buddha cheat.
362 MF7_FOILBUDDHA = 0x00000080, // Similar to FOILINVUL, foils buddha mode.
363 MF7_DONTTHRUST = 0x00000100, // Thrusting functions do not take, and do not give thrust (damage) to actors with this flag.
364 MF7_ALLOWPAIN = 0x00000200, // Invulnerable or immune (via damagefactors) actors can still react to taking damage even if they don't.
365 MF7_CAUSEPAIN = 0x00000400, // Damage sources with this flag can cause similar effects like ALLOWPAIN.
366 MF7_THRUREFLECT = 0x00000800, // Actors who are reflective cause the missiles to not slow down or change angles.
367 MF7_MIRRORREFLECT = 0x00001000, // Actor is turned directly 180 degrees around when reflected.
368 MF7_AIMREFLECT = 0x00002000, // Actor is directly reflected straight back at the one who fired the projectile.
369 MF7_HITTARGET = 0x00004000, // The actor the projectile dies on is set to target, provided it's targetable anyway.
370 MF7_HITMASTER = 0x00008000, // Same as HITTARGET, except it's master instead of target.
371 MF7_HITTRACER = 0x00010000, // Same as HITTARGET, but for tracer.
372 MF7_FLYCHEAT = 0x00020000, // must be part of the actor so that it can be tracked properly
373 MF7_NODECAL = 0x00040000, // [ZK] Forces puff to have no impact decal
374 MF7_FORCEDECAL = 0x00080000, // [ZK] Forces puff's decal to override the weapon's.
375 MF7_LAXTELEFRAGDMG = 0x00100000, // [MC] Telefrag damage can be reduced.
376 MF7_ICESHATTER = 0x00200000, // [MC] Shatters ice corpses regardless of damagetype.
377 };
378
379 // --- mobj.renderflags ---
380 enum ActorRenderFlag
381 {
382 RF_XFLIP = 0x0001, // Flip sprite horizontally
383 RF_YFLIP = 0x0002, // Flip sprite vertically
384 RF_ONESIDED = 0x0004, // Wall/floor sprite is visible from front only
385 RF_FULLBRIGHT = 0x0010, // Sprite is drawn at full brightness
386
387 RF_RELMASK = 0x0300, // ---Relative z-coord for bound actors (these obey texture pegging)
388 RF_RELABSOLUTE = 0x0000, // Actor z is absolute
389 RF_RELUPPER = 0x0100, // Actor z is relative to upper part of wall
390 RF_RELLOWER = 0x0200, // Actor z is relative to lower part of wall
391 RF_RELMID = 0x0300, // Actor z is relative to middle part of wall
392
393 RF_CLIPMASK = 0x0c00, // ---Clipping for bound actors
394 RF_CLIPFULL = 0x0000, // Clip sprite to full height of wall
395 RF_CLIPUPPER = 0x0400, // Clip sprite to upper part of wall
396 RF_CLIPMID = 0x0800, // Clip sprite to mid part of wall
397 RF_CLIPLOWER = 0x0c00, // Clip sprite to lower part of wall
398
399 RF_DECALMASK = RF_RELMASK|RF_CLIPMASK,
400
401 RF_SPRITETYPEMASK = 0x7000, // ---Different sprite types, not all implemented
402 RF_FACESPRITE = 0x0000, // Face sprite
403 RF_WALLSPRITE = 0x1000, // Wall sprite
404 RF_FLOORSPRITE = 0x2000, // Floor sprite
405 RF_VOXELSPRITE = 0x3000, // Voxel object
406 RF_INVISIBLE = 0x8000, // Don't bother drawing this actor
407
408 RF_FORCEYBILLBOARD = 0x10000, // [BB] OpenGL only: draw with y axis billboard, i.e. anchored to the floor (overrides gl_billboard_mode setting)
409 RF_FORCEXYBILLBOARD = 0x20000, // [BB] OpenGL only: draw with xy axis billboard, i.e. unanchored (overrides gl_billboard_mode setting)
410 };
411
412 #define TRANSLUC25 (FRACUNIT/4)
413 #define TRANSLUC33 (FRACUNIT/3)
414 #define TRANSLUC50 (FRACUNIT/2)
415 #define TRANSLUC66 ((FRACUNIT*2)/3)
416 #define TRANSLUC75 ((FRACUNIT*3)/4)
417
418 // <wingdi.h> also #defines OPAQUE
419 #ifndef OPAQUE
420 #define OPAQUE (FRACUNIT)
421 #endif
422
423 // This translucency value produces the closest match to Heretic's TINTTAB.
424 // ~40% of the value of the overlaid image shows through.
425 #define HR_SHADOW (0x6800)
426
427 // Hexen's TINTTAB is the same as Heretic's, just reversed.
428 #define HX_SHADOW (0x9800)
429 #define HX_ALTSHADOW (0x6800)
430
431 // This could easily be a bool but then it'd be much harder to find later. ;)
432 enum replace_t
433 {
434 NO_REPLACE = 0,
435 ALLOW_REPLACE = 1
436 };
437
438 enum ActorBounceFlag
439 {
440 BOUNCE_Walls = 1<<0, // bounces off of walls
441 BOUNCE_Floors = 1<<1, // bounces off of floors
442 BOUNCE_Ceilings = 1<<2, // bounces off of ceilings
443 BOUNCE_Actors = 1<<3, // bounces off of some actors
444 BOUNCE_AllActors = 1<<4, // bounces off of all actors (requires BOUNCE_Actors to be set, too)
445 BOUNCE_AutoOff = 1<<5, // when bouncing off a sector plane, if the new Z velocity is below 3.0, disable further bouncing
446 BOUNCE_HereticType = 1<<6, // goes into Death state when bouncing on floors or ceilings
447
448 BOUNCE_UseSeeSound = 1<<7, // compatibility fallback. This will only be set by
449 // the compatibility handlers for the old bounce flags.
450 BOUNCE_NoWallSound = 1<<8, // don't make noise when bouncing off a wall
451 BOUNCE_Quiet = 1<<9, // Strife's grenades don't make a bouncing sound
452 BOUNCE_ExplodeOnWater = 1<<10, // explodes when hitting a water surface
453 BOUNCE_CanBounceWater = 1<<11, // can bounce on water
454 // MBF bouncing is a bit different from other modes as Killough coded many special behavioral cases
455 // for them that are not present in ZDoom, so it is necessary to identify it properly.
456 BOUNCE_MBF = 1<<12, // This in itself is not a valid mode, but replaces MBF's MF_BOUNCE flag.
457 BOUNCE_AutoOffFloorOnly = 1<<13, // like BOUNCE_AutoOff, but only on floors
458 BOUNCE_UseBounceState = 1<<14, // Use Bounce[.*] states
459
460 BOUNCE_TypeMask = BOUNCE_Walls | BOUNCE_Floors | BOUNCE_Ceilings | BOUNCE_Actors | BOUNCE_AutoOff | BOUNCE_HereticType | BOUNCE_MBF,
461
462 // The three "standard" types of bounciness are:
463 // HERETIC - Missile will only bounce off the floor once and then enter
464 // its death state. It does not bounce off walls at all.
465 // HEXEN - Missile bounces off of walls and floors indefinitely.
466 // DOOM - Like Hexen, but the bounce turns off if its vertical velocity
467 // is too low.
468 BOUNCE_None = 0,
469 BOUNCE_Heretic = BOUNCE_Floors | BOUNCE_Ceilings | BOUNCE_HereticType,
470 BOUNCE_Doom = BOUNCE_Walls | BOUNCE_Floors | BOUNCE_Ceilings | BOUNCE_Actors | BOUNCE_AutoOff,
471 BOUNCE_Hexen = BOUNCE_Walls | BOUNCE_Floors | BOUNCE_Ceilings | BOUNCE_Actors,
472 BOUNCE_Grenade = BOUNCE_MBF | BOUNCE_Doom, // Bounces on walls and flats like ZDoom bounce.
473 BOUNCE_Classic = BOUNCE_MBF | BOUNCE_Floors | BOUNCE_Ceilings, // Bounces on flats only, but
474 // does not die when bouncing.
475
476 // combined types
477 BOUNCE_DoomCompat = BOUNCE_Doom | BOUNCE_UseSeeSound,
478 BOUNCE_HereticCompat = BOUNCE_Heretic | BOUNCE_UseSeeSound,
479 BOUNCE_HexenCompat = BOUNCE_Hexen | BOUNCE_UseSeeSound
480
481 // The distinction between BOUNCE_Actors and BOUNCE_AllActors: A missile with
482 // BOUNCE_Actors set will bounce off of reflective and "non-sentient" actors.
483 // A missile that also has BOUNCE_AllActors set will bounce off of any actor.
484 // For compatibility reasons when BOUNCE_Actors was implied by the bounce type
485 // being "Doom" or "Hexen" and BOUNCE_AllActors was the separate
486 // MF5_BOUNCEONACTORS, you must set BOUNCE_Actors for BOUNCE_AllActors to have
487 // an effect.
488
489
490 };
491
492 // [TP] Flagset definitions
493 typedef TFlags<ActorFlag> ActorFlags;
494 typedef TFlags<ActorFlag2> ActorFlags2;
495 typedef TFlags<ActorFlag3> ActorFlags3;
496 typedef TFlags<ActorFlag4> ActorFlags4;
497 typedef TFlags<ActorFlag5> ActorFlags5;
498 typedef TFlags<ActorFlag6> ActorFlags6;
499 typedef TFlags<ActorFlag7> ActorFlags7;
500 typedef TFlags<ActorRenderFlag> ActorRenderFlags;
501 typedef TFlags<ActorBounceFlag, WORD> ActorBounceFlags;
502 DEFINE_TFLAGS_OPERATORS (ActorFlags)
503 DEFINE_TFLAGS_OPERATORS (ActorFlags2)
504 DEFINE_TFLAGS_OPERATORS (ActorFlags3)
505 DEFINE_TFLAGS_OPERATORS (ActorFlags4)
506 DEFINE_TFLAGS_OPERATORS (ActorFlags5)
507 DEFINE_TFLAGS_OPERATORS (ActorFlags6)
508 DEFINE_TFLAGS_OPERATORS (ActorFlags7)
509 DEFINE_TFLAGS_OPERATORS (ActorRenderFlags)
510 DEFINE_TFLAGS_OPERATORS (ActorBounceFlags)
511
512 // Used to affect the logic for thing activation through death, USESPECIAL and BUMPSPECIAL
513 // "thing" refers to what has the flag and the special, "trigger" refers to what used or bumped it
514 enum EThingSpecialActivationType
515 {
516 THINGSPEC_Default = 0, // Normal behavior: a player must be the trigger, and is the activator
517 THINGSPEC_ThingActs = 1, // The thing itself is the activator of the special
518 THINGSPEC_ThingTargets = 1<<1, // The thing changes its target to the trigger
519 THINGSPEC_TriggerTargets = 1<<2, // The trigger changes its target to the thing
520 THINGSPEC_MonsterTrigger = 1<<3, // The thing can be triggered by a monster
521 THINGSPEC_MissileTrigger = 1<<4, // The thing can be triggered by a projectile
522 THINGSPEC_ClearSpecial = 1<<5, // Clears special after successful activation
523 THINGSPEC_NoDeathSpecial = 1<<6, // Don't activate special on death
524 THINGSPEC_TriggerActs = 1<<7, // The trigger is the activator of the special
525 // (overrides LEVEL_ACTOWNSPECIAL Hexen hack)
526 THINGSPEC_Activate = 1<<8, // The thing is activated when triggered
527 THINGSPEC_Deactivate = 1<<9, // The thing is deactivated when triggered
528 THINGSPEC_Switch = 1<<10, // The thing is alternatively activated and deactivated when triggered
529 };
530
531 // [RH] Like msecnode_t, but for the blockmap
532 struct FBlockNode
533 {
534 AActor *Me; // actor this node references
535 int BlockIndex; // index into blocklinks for the block this node is in
536 FBlockNode **PrevActor; // previous actor in this block
537 FBlockNode *NextActor; // next actor in this block
538 FBlockNode **PrevBlock; // previous block this actor is in
539 FBlockNode *NextBlock; // next block this actor is in
540
541 static FBlockNode *Create (AActor *who, int x, int y);
542 void Release ();
543
544 static FBlockNode *FreeBlocks;
545 };
546
547 class FDecalBase;
548 class AInventory;
549
GetDefaultByName(const char * name)550 inline AActor *GetDefaultByName (const char *name)
551 {
552 return (AActor *)(PClass::FindClass(name)->Defaults);
553 }
554
GetDefaultByType(const PClass * type)555 inline AActor *GetDefaultByType (const PClass *type)
556 {
557 return (AActor *)(type->Defaults);
558 }
559
560 template<class T>
GetDefault()561 inline T *GetDefault ()
562 {
563 return (T *)(RUNTIME_CLASS(T)->Defaults);
564 }
565
566 struct line_t;
567 struct secplane_t;
568 struct FStrifeDialogueNode;
569
570 enum
571 {
572 AMETA_BASE = 0x12000,
573
574 AMETA_Obituary, // string (player was killed by this actor)
575 AMETA_HitObituary, // string (player was killed by this actor in melee)
576 AMETA_DeathHeight, // fixed (height on normal death)
577 AMETA_BurnHeight, // fixed (height on burning death)
578 AMETA_StrifeName, // string (for named Strife objects)
579 AMETA_BloodColor, // colorized blood
580 AMETA_GibHealth, // negative health below which this monster dies an extreme death
581 AMETA_WoundHealth, // health needed to enter wound state
582 AMETA_FastSpeed, // Speed in fast mode
583 AMETA_RDFactor, // Radius damage factor
584 AMETA_CameraHeight, // Height of camera when used as such
585 AMETA_HowlSound, // Sound being played when electrocuted or poisoned
586 AMETA_BloodType, // Blood replacement type
587 AMETA_BloodType2, // Bloodsplatter replacement type
588 AMETA_BloodType3, // AxeBlood replacement type
589 };
590
591 struct fixedvec3
592 {
593 fixed_t x, y, z;
594 };
595
596 struct fixedvec2
597 {
598 fixed_t x, y;
599 };
600
601 struct FDropItem
602 {
603 FName Name;
604 int probability;
605 int amount;
606 FDropItem * Next;
607 };
608
609 class FDropItemPtrArray : public TArray<FDropItem *>
610 {
611 public:
~FDropItemPtrArray()612 ~FDropItemPtrArray()
613 {
614 Clear();
615 }
616
617 void Clear();
618 };
619
620 extern FDropItemPtrArray DropItemList;
621
622 void FreeDropItemChain(FDropItem *chain);
623 int StoreDropItemChain(FDropItem *chain);
624 fixed_t P_AproxDistance (fixed_t dx, fixed_t dy); // since we cannot include p_local here...
625 angle_t R_PointToAngle2 (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2); // same reason here with r_defs.h
626
627
628 // Map Object definition.
629 class AActor : public DThinker
630 {
631 DECLARE_CLASS (AActor, DThinker)
632 HAS_OBJECT_POINTERS
633 public:
634 AActor () throw();
635 AActor (const AActor &other) throw();
636 AActor &operator= (const AActor &other);
637 void Destroy ();
638 ~AActor ();
639
640 void Serialize (FArchive &arc);
641
642 static AActor *StaticSpawn (const PClass *type, fixed_t x, fixed_t y, fixed_t z, replace_t allowreplacement, bool SpawningMapThing = false);
643
GetDefault()644 inline AActor *GetDefault () const
645 {
646 return (AActor *)(RUNTIME_TYPE(this)->Defaults);
647 }
648
649 FDropItem *GetDropItems();
650
651 // Return true if the monster should use a missile attack, false for melee
652 bool SuggestMissileAttack (fixed_t dist);
653
654 // Adjusts the angle for deflection/reflection of incoming missiles
655 // Returns true if the missile should be allowed to explode anyway
656 bool AdjustReflectionAngle (AActor *thing, angle_t &angle);
657
658 // Returns true if this actor is within melee range of its target
659 bool CheckMeleeRange();
660
661 virtual void BeginPlay(); // Called immediately after the actor is created
662 virtual void PostBeginPlay(); // Called immediately before the actor's first tick
663 virtual void LevelSpawned(); // Called after BeginPlay if this actor was spawned by the world
664 virtual void HandleSpawnFlags(); // Translates SpawnFlags into in-game flags.
665
666 virtual void MarkPrecacheSounds() const; // Marks sounds used by this actor for precaching.
667
668 virtual void Activate (AActor *activator);
669 virtual void Deactivate (AActor *activator);
670
671 virtual void Tick ();
672
673 // Called when actor dies
674 virtual void Die (AActor *source, AActor *inflictor, int dmgflags = 0);
675
676 // Perform some special damage action. Returns the amount of damage to do.
677 // Returning -1 signals the damage routine to exit immediately
678 virtual int DoSpecialDamage (AActor *target, int damage, FName damagetype);
679
680 // Like DoSpecialDamage, but called on the actor receiving the damage.
681 virtual int TakeSpecialDamage (AActor *inflictor, AActor *source, int damage, FName damagetype);
682
683 // Centaurs and ettins squeal when electrocuted, poisoned, or "holy"-ed
684 // Made a metadata property so no longer virtual
685 void Howl ();
686
687 // Actor just hit the floor
688 virtual void HitFloor ();
689
690 // plays bouncing sound
691 void PlayBounceSound(bool onfloor);
692
693 // Called when an actor with MF_MISSILE and MF2_FLOORBOUNCE hits the floor
694 virtual bool FloorBounceMissile (secplane_t &plane);
695
696 // Called when an actor is to be reflected by a disc of repulsion.
697 // Returns true to continue normal blast processing.
698 virtual bool SpecialBlastHandling (AActor *source, fixed_t strength);
699
700 // Called by RoughBlockCheck
701 bool IsOkayToAttack (AActor *target);
702
703 // Plays the actor's ActiveSound if its voice isn't already making noise.
704 void PlayActiveSound ();
705
706 // Actor had MF_SKULLFLY set and rammed into something
707 // Returns false to stop moving and true to keep moving
708 virtual bool Slam (AActor *victim);
709
710 // Called by PIT_CheckThing() and needed for some Hexen things.
711 // Returns -1 for normal behavior, 0 to return false, and 1 to return true.
712 // I'm not sure I like it this way, but it will do for now.
713 virtual int SpecialMissileHit (AActor *victim);
714
715 // Returns true if it's okay to switch target to "other" after being attacked by it.
716 virtual bool OkayToSwitchTarget (AActor *other);
717
718 // Something just touched this actor.
719 virtual void Touch (AActor *toucher);
720
721 // Adds the item to this actor's inventory and sets its Owner.
722 virtual void AddInventory (AInventory *item);
723
724 // Removes the item from the inventory list.
725 virtual void RemoveInventory (AInventory *item);
726
727 // Take the amount value of an item from the inventory list.
728 // If nothing is left, the item may be destroyed.
729 // Returns true if the initial item count is positive.
730 virtual bool TakeInventory (const PClass *itemclass, int amount, bool fromdecorate = false, bool notakeinfinite = false);
731
732 // Uses an item and removes it from the inventory.
733 virtual bool UseInventory (AInventory *item);
734
735 // Tosses an item out of the inventory.
736 virtual AInventory *DropInventory (AInventory *item);
737
738 // Removes all items from the inventory.
739 void ClearInventory();
740
741 // Returns true if this view is considered "local" for the player.
742 bool CheckLocalView (int playernum) const;
743
744 // Finds the first item of a particular type.
745 AInventory *FindInventory (const PClass *type, bool subclass = false);
746 AInventory *FindInventory (FName type);
FindInventory()747 template<class T> T *FindInventory ()
748 {
749 return static_cast<T *> (FindInventory (RUNTIME_CLASS(T)));
750 }
751
752 // Adds one item of a particular type. Returns NULL if it could not be added.
753 AInventory *GiveInventoryType (const PClass *type);
754
755 // Returns the first item held with IF_INVBAR set.
756 AInventory *FirstInv ();
757
758 // Tries to give the actor some ammo.
759 bool GiveAmmo (const PClass *type, int amount);
760
761 // Destroys all the inventory the actor is holding.
762 void DestroyAllInventory ();
763
764 // Set the alphacolor field properly
765 void SetShade (DWORD rgb);
766 void SetShade (int r, int g, int b);
767
768 // Plays a conversation animation
769 void ConversationAnimation (int animnum);
770
771 // Make this actor hate the same things as another actor
772 void CopyFriendliness (AActor *other, bool changeTarget, bool resetHealth=true);
773
774 // Moves the other actor's inventory to this one
775 void ObtainInventory (AActor *other);
776
777 // Die. Now.
778 virtual bool Massacre ();
779
780 // Transforms the actor into a finely-ground paste
781 virtual bool Grind(bool items);
782
783 // Get this actor's team
784 int GetTeam();
785
786 // Is the other actor on my team?
787 bool IsTeammate (AActor *other);
788
789 // Is the other actor my friend?
790 bool IsFriend (AActor *other);
791
792 // Do I hate the other actor?
793 bool IsHostile (AActor *other);
794
795 inline bool IsNoClip2() const;
796
797 // What species am I?
798 virtual FName GetSpecies();
799
800 fixed_t GetBobOffset(fixed_t ticfrac=0) const
801 {
802 if (!(flags2 & MF2_FLOATBOB))
803 {
804 return 0;
805 }
806 return finesine[MulScale22(((FloatBobPhase + level.maptime) << FRACBITS) + ticfrac, FINEANGLES) & FINEMASK] * 8;
807 }
808
809 // Enter the crash state
810 void Crash();
811
812 // Return starting health adjusted by skill level
813 int SpawnHealth();
814 int GibHealth();
815
816 inline bool isMissile(bool precise=true)
817 {
818 return (flags&MF_MISSILE) || (precise && GetDefault()->flags&MF_MISSILE);
819 }
820
821 // Check for monsters that count as kill but excludes all friendlies.
CountsAsKill()822 bool CountsAsKill() const
823 {
824 return (flags & MF_COUNTKILL) && !(flags & MF_FRIENDLY);
825 }
826
GetBloodColor()827 PalEntry GetBloodColor() const
828 {
829 return (PalEntry)GetClass()->Meta.GetMetaInt(AMETA_BloodColor);
830 }
831
832 // These also set CF_INTERPVIEW for players.
833 void SetPitch(int p, bool interpolate, bool forceclamp = false);
834 void SetAngle(angle_t ang, bool interpolate);
835 void SetRoll(angle_t roll, bool interpolate);
836
837 const PClass *GetBloodType(int type = 0) const
838 {
839 const PClass *bloodcls;
840 if (type == 0)
841 {
842 bloodcls = PClass::FindClass((ENamedName)GetClass()->Meta.GetMetaInt(AMETA_BloodType, NAME_Blood));
843 }
844 else if (type == 1)
845 {
846 bloodcls = PClass::FindClass((ENamedName)GetClass()->Meta.GetMetaInt(AMETA_BloodType2, NAME_BloodSplatter));
847 }
848 else if (type == 2)
849 {
850 bloodcls = PClass::FindClass((ENamedName)GetClass()->Meta.GetMetaInt(AMETA_BloodType3, NAME_AxeBlood));
851 }
852 else return NULL;
853
854 if (bloodcls != NULL)
855 {
856 bloodcls = bloodcls->GetReplacement();
857 }
858 return bloodcls;
859 }
860
intersects(AActor * other)861 bool intersects(AActor *other) const
862 {
863 fixed_t blockdist = radius + other->radius;
864 return ( abs(X() - other->X()) < blockdist && abs(Y() - other->Y()) < blockdist);
865 }
866
867 // 'absolute' is reserved for a linked portal implementation which needs
868 // to distinguish between portal-aware and portal-unaware distance calculation.
869 fixed_t AproxDistance(AActor *other, bool absolute = false)
870 {
871 return P_AproxDistance(X() - other->X(), Y() - other->Y());
872 }
873
874 // same with 'ref' here.
875 fixed_t AproxDistance(fixed_t otherx, fixed_t othery, AActor *ref = NULL)
876 {
877 return P_AproxDistance(X() - otherx, Y() - othery);
878 }
879
880 fixed_t AproxDistance(AActor *other, fixed_t xadd, fixed_t yadd, bool absolute = false)
881 {
882 return P_AproxDistance(X() - other->X() + xadd, Y() - other->Y() + yadd);
883 }
884
885 fixed_t AproxDistance3D(AActor *other, bool absolute = false)
886 {
887 return P_AproxDistance(AproxDistance(other), Z() - other->Z());
888 }
889
890 // more precise, but slower version, being used in a few places
891 fixed_t Distance2D(AActor *other, bool absolute = false)
892 {
893 return xs_RoundToInt(FVector2(X() - other->X(), Y() - other->Y()).Length());
894 }
895
896 // a full 3D version of the above
897 fixed_t Distance3D(AActor *other, bool absolute = false)
898 {
899 return xs_RoundToInt(FVector3(X() - other->X(), Y() - other->Y(), Z() - other->Z()).Length());
900 }
901
902 angle_t AngleTo(AActor *other, bool absolute = false) const
903 {
904 return R_PointToAngle2(X(), Y(), other->X(), other->Y());
905 }
906
907 angle_t AngleTo(AActor *other, fixed_t oxofs, fixed_t oyofs, bool absolute = false) const
908 {
909 return R_PointToAngle2(X(), Y(), other->X() + oxofs, other->Y() + oyofs);
910 }
911
912 fixed_t AngleTo(fixed_t otherx, fixed_t othery, AActor *ref = NULL)
913 {
914 return R_PointToAngle2(X(), Y(), otherx, othery);
915 }
916
917 fixed_t AngleXYTo(fixed_t myx, fixed_t myy, AActor *other, bool absolute = false)
918 {
919 return R_PointToAngle2(myx, myy, other->X(), other->Y());
920 }
921
Vec2To(AActor * other)922 fixedvec2 Vec2To(AActor *other) const
923 {
924 fixedvec2 ret = { other->X() - X(), other->Y() - Y() };
925 return ret;
926 }
927
Vec3To(AActor * other)928 fixedvec3 Vec3To(AActor *other) const
929 {
930 fixedvec3 ret = { other->X() - X(), other->Y() - Y(), other->Z() - Z() };
931 return ret;
932 }
933
934 fixedvec2 Vec2Offset(fixed_t dx, fixed_t dy, bool absolute = false) const
935 {
936 fixedvec2 ret = { X() + dx, Y() + dy };
937 return ret;
938 }
939
940
941 fixedvec2 Vec2Angle(fixed_t length, angle_t angle, bool absolute = false) const
942 {
943 fixedvec2 ret = { X() + FixedMul(length, finecosine[angle >> ANGLETOFINESHIFT]),
944 Y() + FixedMul(length, finesine[angle >> ANGLETOFINESHIFT]) };
945 return ret;
946 }
947
948 fixedvec3 Vec3Offset(fixed_t dx, fixed_t dy, fixed_t dz, bool absolute = false) const
949 {
950 fixedvec3 ret = { X() + dx, Y() + dy, Z() + dz };
951 return ret;
952 }
953
954 fixedvec3 Vec3Angle(fixed_t length, angle_t angle, fixed_t dz, bool absolute = false) const
955 {
956 fixedvec3 ret = { X() + FixedMul(length, finecosine[angle >> ANGLETOFINESHIFT]),
957 Y() + FixedMul(length, finesine[angle >> ANGLETOFINESHIFT]), Z() + dz };
958 return ret;
959 }
960
Move(fixed_t dx,fixed_t dy,fixed_t dz)961 void Move(fixed_t dx, fixed_t dy, fixed_t dz)
962 {
963 SetOrigin(X() + dx, Y() + dy, Z() + dz, true);
964 }
965
SetOrigin(const fixedvec3 & npos,bool moving)966 void SetOrigin(const fixedvec3 & npos, bool moving)
967 {
968 SetOrigin(npos.x, npos.y, npos.z, moving);
969 }
970
971 inline void SetFriendPlayer(player_t *player);
972
973 bool IsVisibleToPlayer() const;
974
975 // Calculate amount of missile damage
976 virtual int GetMissileDamage(int mask, int add);
977
978 bool CanSeek(AActor *target) const;
979
980 fixed_t GetGravity() const;
981 bool IsSentient() const;
982 const char *GetTag(const char *def = NULL) const;
983 void SetTag(const char *def);
984
985 // Triggers SECSPAC_Exit/SECSPAC_Enter and related events if oldsec != current sector
986 void CheckSectorTransition(sector_t *oldsec);
987
988 // info for drawing
989 // NOTE: The first member variable *must* be snext.
990 AActor *snext, **sprev; // links in sector (if needed)
991 fixedvec3 __pos; // double underscores so that it won't get used by accident. Access to this should be exclusively through the designated access functions.
992
993 angle_t angle;
994 WORD sprite; // used to find patch_t and flip value
995 BYTE frame; // sprite frame to draw
996 fixed_t scaleX, scaleY; // Scaling values; FRACUNIT is normal size
997 FRenderStyle RenderStyle; // Style to draw this actor with
998 ActorRenderFlags renderflags; // Different rendering flags
999 FTextureID picnum; // Draw this instead of sprite if valid
1000 DWORD effects; // [RH] see p_effect.h
1001 fixed_t alpha;
1002 DWORD fillcolor; // Color to draw when STYLE_Shaded
1003
1004 // interaction info
1005 fixed_t pitch;
1006 angle_t roll; // This was fixed_t before, which is probably wrong
1007 FBlockNode *BlockNode; // links in blocks (if needed)
1008 struct sector_t *Sector;
1009 subsector_t * subsector;
1010 fixed_t floorz, ceilingz; // closest together of contacted secs
1011 fixed_t dropoffz; // killough 11/98: the lowest floor over all contacted Sectors.
1012
1013 struct sector_t *floorsector;
1014 FTextureID floorpic; // contacted sec floorpic
1015 int floorterrain;
1016 struct sector_t *ceilingsector;
1017 FTextureID ceilingpic; // contacted sec ceilingpic
1018 fixed_t radius, height; // for movement checking
1019 fixed_t projectilepassheight; // height for clipping projectile movement against this actor
1020 fixed_t velx, vely, velz; // velocity
1021 SDWORD tics; // state tic counter
1022 FState *state;
1023 SDWORD Damage; // For missiles and monster railgun
1024 int projectileKickback;
1025 ActorFlags flags;
1026 ActorFlags2 flags2; // Heretic flags
1027 ActorFlags3 flags3; // [RH] Hexen/Heretic actor-dependant behavior made flaggable
1028 ActorFlags4 flags4; // [RH] Even more flags!
1029 ActorFlags5 flags5; // OMG! We need another one.
1030 ActorFlags6 flags6; // Shit! Where did all the flags go?
1031 ActorFlags7 flags7; // WHO WANTS TO BET ON 8!?
1032
1033 // [BB] If 0, everybody can see the actor, if > 0, only members of team (VisibleToTeam-1) can see it.
1034 DWORD VisibleToTeam;
1035
1036 int special1; // Special info
1037 int special2; // Special info
1038 int weaponspecial; // Special info for weapons.
1039 int health;
1040 BYTE movedir; // 0-7
1041 SBYTE visdir;
1042 SWORD movecount; // when 0, select a new dir
1043 SWORD strafecount; // for MF3_AVOIDMELEE
1044 TObjPtr<AActor> target; // thing being chased/attacked (or NULL)
1045 // also the originator for missiles
1046 TObjPtr<AActor> lastenemy; // Last known enemy -- killough 2/15/98
1047 TObjPtr<AActor> LastHeard; // [RH] Last actor this one heard
1048 SDWORD reactiontime; // if non 0, don't attack yet; used by
1049 // player to freeze a bit after teleporting
1050 SDWORD threshold; // if > 0, the target will be chased
1051 // no matter what (even if shot)
1052 player_t *player; // only valid if type of APlayerPawn
1053 TObjPtr<AActor> LastLookActor; // Actor last looked for (if TIDtoHate != 0)
1054 fixed_t SpawnPoint[3]; // For nightmare respawn
1055 WORD SpawnAngle;
1056 int StartHealth;
1057 BYTE WeaveIndexXY; // Separated from special2 because it's used by globally accessible functions.
1058 BYTE WeaveIndexZ;
1059 int skillrespawncount;
1060 int TIDtoHate; // TID of things to hate (0 if none)
1061 FNameNoInit Species; // For monster families
1062 TObjPtr<AActor> tracer; // Thing being chased/attacked for tracers
1063 TObjPtr<AActor> master; // Thing which spawned this one (prevents mutual attacks)
1064 fixed_t floorclip; // value to use for floor clipping
1065 int tid; // thing identifier
1066 int special; // special
1067 int args[5]; // special arguments
1068
1069 int accuracy, stamina; // [RH] Strife stats -- [XA] moved here for DECORATE/ACS access.
1070
1071 AActor *inext, **iprev;// Links to other mobjs in same bucket
1072 TObjPtr<AActor> goal; // Monster's goal if not chasing anything
1073 int waterlevel; // 0=none, 1=feet, 2=waist, 3=eyes
1074 BYTE boomwaterlevel; // splash information for non-swimmable water sectors
1075 BYTE MinMissileChance;// [RH] If a random # is > than this, then missile attack.
1076 SBYTE LastLookPlayerNumber;// Player number last looked for (if TIDtoHate == 0)
1077 ActorBounceFlags BounceFlags; // which bouncing type?
1078 DWORD SpawnFlags; // Increased to DWORD because of Doom 64
1079 fixed_t meleerange; // specifies how far a melee attack reaches.
1080 fixed_t meleethreshold; // Distance below which a monster doesn't try to shoot missiles anynore
1081 // but instead tries to come closer for a melee attack.
1082 // This is not the same as meleerange
1083 fixed_t maxtargetrange; // any target farther away cannot be attacked
1084 fixed_t bouncefactor; // Strife's grenades use 50%, Hexen's Flechettes 70.
1085 fixed_t wallbouncefactor; // The bounce factor for walls can be different.
1086 int bouncecount; // Strife's grenades only bounce twice before exploding
1087 fixed_t gravity; // [GRB] Gravity factor
1088 fixed_t Friction;
1089 int FastChaseStrafeCount;
1090 fixed_t pushfactor;
1091 int lastpush;
1092 int activationtype; // How the thing behaves when activated with USESPECIAL or BUMPSPECIAL
1093 int lastbump; // Last time the actor was bumped, used to control BUMPSPECIAL
1094 int Score; // manipulated by score items, ACS or DECORATE. The engine doesn't use this itself for anything.
1095 FString * Tag; // Strife's tag name.
1096 int DesignatedTeam; // Allow for friendly fire cacluations to be done on non-players.
1097
1098 AActor *BlockingMobj; // Actor that blocked the last move
1099 line_t *BlockingLine; // Line that blocked the last move
1100
1101 int PoisonDamage; // Damage received per tic from poison.
1102 FNameNoInit PoisonDamageType; // Damage type dealt by poison.
1103 int PoisonDuration; // Duration left for receiving poison damage.
1104 int PoisonPeriod; // How often poison damage is applied. (Every X tics.)
1105
1106 int PoisonDamageReceived; // Damage received per tic from poison.
1107 FNameNoInit PoisonDamageTypeReceived; // Damage type received by poison.
1108 int PoisonDurationReceived; // Duration left for receiving poison damage.
1109 int PoisonPeriodReceived; // How often poison damage is applied. (Every X tics.)
1110 TObjPtr<AActor> Poisoner; // Last source of received poison damage.
1111
1112 // a linked list of sectors where this object appears
1113 struct msecnode_t *touching_sectorlist; // phares 3/14/98
1114
1115 TObjPtr<AInventory> Inventory; // [RH] This actor's inventory
1116 DWORD InventoryID; // A unique ID to keep track of inventory items
1117
1118 BYTE smokecounter;
1119 BYTE FloatBobPhase;
1120 BYTE FriendPlayer; // [RH] Player # + 1 this friendly monster works for (so 0 is no player, 1 is player 0, etc)
1121 DWORD Translation;
1122
1123 // [RH] Stuff that used to be part of an Actor Info
1124 FSoundIDNoInit SeeSound;
1125 FSoundIDNoInit AttackSound;
1126 FSoundIDNoInit PainSound;
1127 FSoundIDNoInit DeathSound;
1128 FSoundIDNoInit ActiveSound;
1129 FSoundIDNoInit UseSound; // [RH] Sound to play when an actor is used.
1130 FSoundIDNoInit BounceSound;
1131 FSoundIDNoInit WallBounceSound;
1132 FSoundIDNoInit CrushPainSound;
1133
1134 fixed_t Speed;
1135 fixed_t FloatSpeed;
1136 fixed_t MaxDropOffHeight, MaxStepHeight;
1137 SDWORD Mass;
1138 SWORD PainChance;
1139 int PainThreshold;
1140 FNameNoInit DamageType;
1141 FNameNoInit DamageTypeReceived;
1142 fixed_t DamageFactor;
1143 fixed_t DamageMultiply;
1144
1145 FNameNoInit PainType;
1146 FNameNoInit DeathType;
1147 const PClass *TeleFogSourceType;
1148 const PClass *TeleFogDestType;
1149 int RipperLevel;
1150 int RipLevelMin;
1151 int RipLevelMax;
1152
1153 FState *SpawnState;
1154 FState *SeeState;
1155 FState *MeleeState;
1156 FState *MissileState;
1157
1158
1159 int ConversationRoot; // THe root of the current dialogue
1160 FStrifeDialogueNode *Conversation; // [RH] The dialogue to show when this actor is "used."
1161
1162 // [RH] Decal(s) this weapon/projectile generates on impact.
1163 FDecalBase *DecalGenerator;
1164
1165 // [RH] Used to interpolate the view to get >35 FPS
1166 fixed_t PrevX, PrevY, PrevZ;
1167 angle_t PrevAngle;
1168
1169 // ThingIDs
1170 static void ClearTIDHashes ();
1171 void AddToHash ();
1172 void RemoveFromHash ();
1173
1174 private:
1175 static AActor *TIDHash[128];
TIDHASH(int key)1176 static inline int TIDHASH (int key) { return key & 127; }
1177 static FSharedStringArena mStringPropertyData;
1178
1179 friend class FActorIterator;
1180 friend bool P_IsTIDUsed(int tid);
1181
1182 sector_t *LinkToWorldForMapThing ();
1183
1184 public:
1185 void LinkToWorld (bool buggy=false);
1186 void LinkToWorld (sector_t *sector);
1187 void UnlinkFromWorld ();
1188 void AdjustFloorClip ();
1189 void SetOrigin (fixed_t x, fixed_t y, fixed_t z, bool moving = false);
1190 bool InStateSequence(FState * newstate, FState * basestate);
1191 int GetTics(FState * newstate);
1192 bool SetState (FState *newstate, bool nofunction=false);
1193 virtual bool UpdateWaterLevel (fixed_t oldz, bool splash=true);
1194 bool isFast();
1195 bool isSlow();
1196 void SetIdle(bool nofunction=false);
1197 void ClearCounters();
1198 FState *GetRaiseState();
1199 void Revive();
1200
FindState(FName label)1201 FState *FindState (FName label) const
1202 {
1203 return GetClass()->ActorInfo->FindState(1, &label);
1204 }
1205
1206 FState *FindState (FName label, FName sublabel, bool exact = false) const
1207 {
1208 FName names[] = { label, sublabel };
1209 return GetClass()->ActorInfo->FindState(2, names, exact);
1210 }
1211
1212 FState *FindState(int numnames, FName *names, bool exact = false) const
1213 {
1214 return GetClass()->ActorInfo->FindState(numnames, names, exact);
1215 }
1216
1217 bool HasSpecialDeathStates () const;
1218
X()1219 fixed_t X() const
1220 {
1221 return __pos.x;
1222 }
Y()1223 fixed_t Y() const
1224 {
1225 return __pos.y;
1226 }
Z()1227 fixed_t Z() const
1228 {
1229 return __pos.z;
1230 }
Pos()1231 fixedvec3 Pos() const
1232 {
1233 fixedvec3 ret = { X(), Y(), Z() };
1234 return ret;
1235 }
PosRelative(AActor * other)1236 fixedvec3 PosRelative(AActor *other) const
1237 {
1238 fixedvec3 ret = { X(), Y(), Z() };
1239 return ret;
1240 }
PosRelative(sector_t * sec)1241 fixedvec3 PosRelative(sector_t *sec) const
1242 {
1243 fixedvec3 ret = { X(), Y(), Z() };
1244 return ret;
1245 }
PosRelative(line_t * line)1246 fixedvec3 PosRelative(line_t *line) const
1247 {
1248 fixedvec3 ret = { X(), Y(), Z() };
1249 return ret;
1250 }
SoundX()1251 fixed_t SoundX() const
1252 {
1253 return X();
1254 }
SoundY()1255 fixed_t SoundY() const
1256 {
1257 return Y();
1258 }
SoundZ()1259 fixed_t SoundZ() const
1260 {
1261 return Z();
1262 }
InterpolatedPosition(fixed_t ticFrac)1263 fixedvec3 InterpolatedPosition(fixed_t ticFrac) const
1264 {
1265 fixedvec3 ret;
1266
1267 ret.x = PrevX + FixedMul (ticFrac, X() - PrevX);
1268 ret.y = PrevY + FixedMul (ticFrac, Y() - PrevY);
1269 ret.z = PrevZ + FixedMul (ticFrac, Z() - PrevZ);
1270 return ret;
1271 }
PosPlusZ(fixed_t zadd)1272 fixedvec3 PosPlusZ(fixed_t zadd) const
1273 {
1274 fixedvec3 ret = { X(), Y(), Z() + zadd };
1275 return ret;
1276 }
Top()1277 fixed_t Top() const
1278 {
1279 return Z() + height;
1280 }
1281 void SetZ(fixed_t newz, bool moving = true)
1282 {
1283 __pos.z = newz;
1284 }
1285 void AddZ(fixed_t newz, bool moving = true)
1286 {
1287 __pos.z += newz;
1288 }
1289
1290 // These are not for general use as they do not link the actor into the world!
SetXY(fixed_t xx,fixed_t yy)1291 void SetXY(fixed_t xx, fixed_t yy)
1292 {
1293 __pos.x = xx;
1294 __pos.y = yy;
1295 }
SetXYZ(fixed_t xx,fixed_t yy,fixed_t zz)1296 void SetXYZ(fixed_t xx, fixed_t yy, fixed_t zz)
1297 {
1298 __pos.x = xx;
1299 __pos.y = yy;
1300 __pos.z = zz;
1301 }
SetXY(const fixedvec2 & npos)1302 void SetXY(const fixedvec2 &npos)
1303 {
1304 __pos.x = npos.x;
1305 __pos.y = npos.y;
1306 }
SetXYZ(const fixedvec3 & npos)1307 void SetXYZ(const fixedvec3 &npos)
1308 {
1309 __pos.x = npos.x;
1310 __pos.y = npos.y;
1311 __pos.z = npos.z;
1312 }
SetMovement(fixed_t x,fixed_t y,fixed_t z)1313 void SetMovement(fixed_t x, fixed_t y, fixed_t z)
1314 {
1315 // not yet implemented
1316 }
1317
1318 };
1319
1320 class FActorIterator
1321 {
1322 public:
FActorIterator(int i)1323 FActorIterator (int i) : base (NULL), id (i)
1324 {
1325 }
FActorIterator(int i,AActor * start)1326 FActorIterator (int i, AActor *start) : base (start), id (i)
1327 {
1328 }
Next()1329 AActor *Next ()
1330 {
1331 if (id == 0)
1332 return NULL;
1333 if (!base)
1334 base = AActor::TIDHash[id & 127];
1335 else
1336 base = base->inext;
1337
1338 while (base && base->tid != id)
1339 base = base->inext;
1340
1341 return base;
1342 }
1343 private:
1344 AActor *base;
1345 int id;
1346 };
1347
1348 template<class T>
1349 class TActorIterator : public FActorIterator
1350 {
1351 public:
TActorIterator(int id)1352 TActorIterator (int id) : FActorIterator (id) {}
Next()1353 T *Next ()
1354 {
1355 AActor *actor;
1356 do
1357 {
1358 actor = FActorIterator::Next ();
1359 } while (actor && !actor->IsKindOf (RUNTIME_CLASS(T)));
1360 return static_cast<T *>(actor);
1361 }
1362 };
1363
1364 class NActorIterator : public FActorIterator
1365 {
1366 const PClass *type;
1367 public:
NActorIterator(const PClass * cls,int id)1368 NActorIterator (const PClass *cls, int id) : FActorIterator (id) { type = cls; }
NActorIterator(FName cls,int id)1369 NActorIterator (FName cls, int id) : FActorIterator (id) { type = PClass::FindClass(cls); }
NActorIterator(const char * cls,int id)1370 NActorIterator (const char *cls, int id) : FActorIterator (id) { type = PClass::FindClass(cls); }
Next()1371 AActor *Next ()
1372 {
1373 AActor *actor;
1374 if (type == NULL) return NULL;
1375 do
1376 {
1377 actor = FActorIterator::Next ();
1378 } while (actor && !actor->IsKindOf (type));
1379 return actor;
1380 }
1381 };
1382
1383 bool P_IsTIDUsed(int tid);
1384 int P_FindUniqueTID(int start_tid, int limit);
1385
Spawn(const PClass * type,fixed_t x,fixed_t y,fixed_t z,replace_t allowreplacement)1386 inline AActor *Spawn (const PClass *type, fixed_t x, fixed_t y, fixed_t z, replace_t allowreplacement)
1387 {
1388 return AActor::StaticSpawn (type, x, y, z, allowreplacement);
1389 }
1390
Spawn(const PClass * type,const fixedvec3 & pos,replace_t allowreplacement)1391 inline AActor *Spawn (const PClass *type, const fixedvec3 &pos, replace_t allowreplacement)
1392 {
1393 return AActor::StaticSpawn (type, pos.x, pos.y, pos.z, allowreplacement);
1394 }
1395
1396 AActor *Spawn (const char *type, fixed_t x, fixed_t y, fixed_t z, replace_t allowreplacement);
1397 AActor *Spawn (FName classname, fixed_t x, fixed_t y, fixed_t z, replace_t allowreplacement);
1398
Spawn(const char * type,const fixedvec3 & pos,replace_t allowreplacement)1399 inline AActor *Spawn (const char *type, const fixedvec3 &pos, replace_t allowreplacement)
1400 {
1401 return Spawn (type, pos.x, pos.y, pos.z, allowreplacement);
1402 }
1403
Spawn(FName classname,const fixedvec3 & pos,replace_t allowreplacement)1404 inline AActor *Spawn (FName classname, const fixedvec3 &pos, replace_t allowreplacement)
1405 {
1406 return Spawn (classname, pos.x, pos.y, pos.z, allowreplacement);
1407 }
1408
1409
1410 template<class T>
Spawn(fixed_t x,fixed_t y,fixed_t z,replace_t allowreplacement)1411 inline T *Spawn (fixed_t x, fixed_t y, fixed_t z, replace_t allowreplacement)
1412 {
1413 return static_cast<T *>(AActor::StaticSpawn (RUNTIME_CLASS(T), x, y, z, allowreplacement));
1414 }
1415
1416 template<class T>
Spawn(const fixedvec3 & pos,replace_t allowreplacement)1417 inline T *Spawn (const fixedvec3 &pos, replace_t allowreplacement)
1418 {
1419 return static_cast<T *>(AActor::StaticSpawn (RUNTIME_CLASS(T), pos.x, pos.y, pos.z, allowreplacement));
1420 }
1421
Vec2Angle(fixed_t length,angle_t angle)1422 inline fixedvec2 Vec2Angle(fixed_t length, angle_t angle)
1423 {
1424 fixedvec2 ret = { FixedMul(length, finecosine[angle >> ANGLETOFINESHIFT]),
1425 FixedMul(length, finesine[angle >> ANGLETOFINESHIFT]) };
1426 return ret;
1427 }
1428
1429 inline fixedvec3 PosRelative(const fixedvec3 &pos, line_t *line, sector_t *refsec = NULL)
1430 {
1431 return pos;
1432 }
1433
1434 void PrintMiscActorInfo(AActor * query);
1435
1436 #define S_FREETARGMOBJ 1
1437
1438 #endif // __P_MOBJ_H__
1439