From 1e2ce9a6220f6cfcb6d137bb0d7faa68644f268c Mon Sep 17 00:00:00 2001
From: Christoph Oelckers <c.oelckers@zdoom.fake>
Date: Sun, 10 Jan 2016 17:52:41 +0100
Subject: [PATCH 1/7] - some refactoring of P_AproxDistance calls into newly
 defined AActor method AproxDistance.

The main reason here is to reduce the number of instances where AActor::x and AActor::y are being referenced.
---
 src/actor.h                       | 2414 +++++++++++++++--------------
 src/b_func.cpp                    |   16 +-
 src/b_move.cpp                    |    2 +-
 src/b_think.cpp                   |   12 +-
 src/g_doom/a_lostsoul.cpp         |    2 +-
 src/g_doom/a_revenant.cpp         |    5 +-
 src/g_game.cpp                    |    3 +-
 src/g_heretic/a_ironlich.cpp      |    3 +-
 src/g_hexen/a_blastradius.cpp     |    2 +-
 src/g_hexen/a_clericholy.cpp      |    7 +-
 src/g_hexen/a_dragon.cpp          |    8 +-
 src/g_hexen/a_firedemon.cpp       |    2 +-
 src/g_hexen/a_healingradius.cpp   |    2 +-
 src/g_hexen/a_heresiarch.cpp      |    3 +-
 src/g_hexen/a_korax.cpp           |    6 +-
 src/g_raven/a_minotaur.cpp        |    6 +-
 src/g_shared/a_quake.cpp          |    5 +-
 src/g_shared/a_specialspot.cpp    |    2 +-
 src/g_strife/a_crusader.cpp       |    4 +-
 src/g_strife/a_inquisitor.cpp     |    4 +-
 src/p_enemy.cpp                   |   34 +-
 src/p_map.cpp                     |    6 +-
 src/p_mobj.cpp                    |   11 +-
 src/p_spec.cpp                    |    2 +-
 src/thingdef/thingdef_codeptr.cpp |   18 +-
 25 files changed, 1293 insertions(+), 1286 deletions(-)

diff --git a/src/actor.h b/src/actor.h
index cb0524587..0cd87ec52 100644
--- a/src/actor.h
+++ b/src/actor.h
@@ -1,1189 +1,1225 @@
-// 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"
-
-// We need the thinker_t stuff.
-#include "dthinker.h"
-
-
-// States are tied to finite states are tied to animation frames.
-#include "info.h"
-
-#include "doomdef.h"
-#include "textures/textures.h"
-#include "r_data/renderstyle.h"
-#include "s_sound.h"
-#include "memarena.h"
-#include "g_level.h"
-#include "tflags.h"
-
-struct subsector_t;
-//
-// 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?
-//
-
-// --- mobj.flags ---
-enum ActorFlag
-{
-	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
-
-	// --- dummies for unknown/unimplemented Strife flags ---
-	MF_STRIFEx8000000 = 0,		// seems related to MF_SHADOW
-};
-
-// --- mobj.flags2 ---
-enum ActorFlag2
-{
-	MF2_DONTREFLECT		= 0x00000001,	// this projectile cannot be reflected
-	MF2_WINDTHRUST		= 0x00000002,	// gets pushed around by the wind specials
-	MF2_DONTSEEKINVISIBLE=0x00000004,	// For seeker missiles: Don't home in on invisible/shadow targets
-	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_DONTTRANSLATE	= 0x00010000,	// Don't apply palette translations
-	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_THRUACTORS		= 0x00100000,	// performs no actor<->actor collision checks
-	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_ARGSDEFINED		= 0x20000000,	// Internal flag used by DECORATE to signal that the 
-										// args should not be taken from the mapthing definition
-	MF2_SEEKERMISSILE	= 0x40000000,	// is a seeker (for reflection)
-	MF2_REFLECTIVE		= 0x80000000,	// reflects missiles
-};
-
-// --- mobj.flags3 ---
-enum ActorFlag3
-{
-	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_AVOIDMELEE		= 0x00800000,	// Avoids melee attacks (same as MBF's monster_backing but must be explicitly set)
-	MF3_SCREENSEEKER    = 0x01000000,	// Fails the IsOkayToAttack test if potential target is outside player FOV
-	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 ---
-enum ActorFlag4
-{
-	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 / cannot be moved by any sector action.
-	MF4_STRIFEDAMAGE	= 0x00000100,	// Strife projectiles only do up to 4x damage, not 8x
-
-	MF4_CANUSEWALLS		= 0x00000200,	// Can activate 'use' specials
-	MF4_MISSILEMORE		= 0x00000400,	// increases the chance of a missile attack
-	MF4_MISSILEEVENMORE	= 0x00000800,	// significantly increases the chance of a missile attack
-	MF4_FORCERADIUSDMG	= 0x00001000,	// if put on an object it will override MF3_NORADIUSDMG
-	MF4_DONTFALL		= 0x00002000,	// Doesn't have NOGRAVITY disabled when dying.
-	MF4_SEESDAGGERS		= 0x00004000,	// This actor can see you striking with a dagger
-	MF4_INCOMBAT		= 0x00008000,	// Don't alert others when attacked by a dagger
-	MF4_LOOKALLAROUND	= 0x00010000,	// Monster has eyes in the back of its head
-	MF4_STANDSTILL		= 0x00020000,	// Monster should not chase targets unless attacked?
-	MF4_SPECTRAL		= 0x00040000,
-	MF4_SCROLLMOVE		= 0x00080000,	// velocity has been applied by a scroller
-	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_DONTHARMCLASS	= 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_BOSSSPAWNED		= 0x80000000,	// Spawned by a boss spawn cube
-};
-
-// --- mobj.flags5 ---
-
-enum ActorFlag5
-{
-	MF5_DONTDRAIN		= 0x00000001,	// cannot be drained health from.
-	/*					= 0x00000002,	   reserved for use by scripting branch */
-	MF5_NODROPOFF		= 0x00000004,	// cannot drop off under any circumstances.
-	MF5_NOFORWARDFALL	= 0x00000008,	// Does not make any actor fall forward by being damaged by this
-	MF5_COUNTSECRET		= 0x00000010,	// From Doom 64: actor acts like a secret
-	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
-	MF5_NOBLOODDECALS	= 0x00001000,	// Actor bleeds but doesn't spawn blood decals
-	MF5_USESPECIAL		= 0x00002000,	// Actor executes its special when being 'used'.
-	MF5_NOPAIN			= 0x00004000,	// If set the pain state won't be entered
-	MF5_ALWAYSFAST		= 0x00008000,	// always uses 'fast' attacking logic
-	MF5_NEVERFAST		= 0x00010000,	// never uses 'fast' attacking logic
-	MF5_ALWAYSRESPAWN	= 0x00020000,	// always respawns, regardless of skill setting
-	MF5_NEVERRESPAWN	= 0x00040000,	// never respawns, regardless of skill setting
-	MF5_DONTRIP			= 0x00080000,	// Ripping projectiles explode when hitting this actor
-	MF5_NOINFIGHTING	= 0x00100000,	// This actor doesn't switch target when it's hurt 
-	MF5_NOINTERACTION	= 0x00200000,	// Thing is completely excluded from any gameplay related checks
-	MF5_NOTIMEFREEZE	= 0x00400000,	// Actor is not affected by time freezer
-	MF5_PUFFGETSOWNER	= 0x00800000,	// [BB] Sets the owner of the puff to the player who fired it
-	MF5_SPECIALFIREDAMAGE=0x01000000,	// Special treatment of PhoenixFX1 turned into a flag to remove
-										// dependence of main engine code of specific actor types.
-	MF5_SUMMONEDMONSTER	= 0x02000000,	// To mark the friendly Minotaur. Hopefully to be generalized later.
-	MF5_NOVERTICALMELEERANGE=0x04000000,// Does not check vertical distance for melee range
-	MF5_BRIGHT			= 0x08000000,	// Actor is always rendered fullbright
-	MF5_CANTSEEK		= 0x10000000,	// seeker missiles cannot home in on this actor
-	MF5_INCONVERSATION	= 0x20000000,	// Actor is having a conversation
-	MF5_PAINLESS		= 0x40000000,	// Actor always inflicts painless damage.
-	MF5_MOVEWITHSECTOR	= 0x80000000,	// P_ChangeSector() will still process this actor if it has MF_NOBLOCKMAP
-};
-
-// --- mobj.flags6 ---
-enum ActorFlag6
-{
-	MF6_NOBOSSRIP		= 0x00000001,	// For rippermissiles: Don't rip through bosses.
-	MF6_THRUSPECIES		= 0x00000002,	// Actors passes through other of the same species.
-	MF6_MTHRUSPECIES	= 0x00000004,	// Missile passes through actors of its shooter's species.
-	MF6_FORCEPAIN		= 0x00000008,	// forces target into painstate (unless it has the NOPAIN flag)
-	MF6_NOFEAR			= 0x00000010,	// Not scared of frightening players
-	MF6_BUMPSPECIAL		= 0x00000020,	// Actor executes its special when being collided (as the ST flag)
-	MF6_DONTHARMSPECIES = 0x00000040,	// Don't hurt one's own species with explosions (hitscans, too?)
-	MF6_STEPMISSILE		= 0x00000080,	// Missile can "walk" up steps
-	MF6_NOTELEFRAG		= 0x00000100,	// [HW] Actor can't be telefragged
-	MF6_TOUCHY			= 0x00000200,	// From MBF: killough 11/98: dies when solids touch it
-	MF6_CANJUMP			= 0x00000400,	// From MBF: a dedicated flag instead of the BOUNCES+FLOAT+sentient combo
-	MF6_JUMPDOWN		= 0x00000800,	// From MBF: generalization of dog behavior wrt. dropoffs.
-	MF6_VULNERABLE		= 0x00001000,	// Actor can be damaged (even if not shootable).
-	MF6_ARMED			= 0x00002000,	// From MBF: Object is armed (for MF6_TOUCHY objects)
-	MF6_FALLING			= 0x00004000,	// From MBF: Object is falling (for pseudotorque simulation)
-	MF6_LINEDONE		= 0x00008000,	// From MBF: Object has already run a line effect
-	MF6_NOTRIGGER		= 0x00010000,	// actor cannot trigger any line actions
-	MF6_SHATTERING		= 0x00020000,	// marks an ice corpse for forced shattering
-	MF6_KILLED			= 0x00040000,	// Something that was killed (but not necessarily a corpse)
-	MF6_BLOCKEDBYSOLIDACTORS = 0x00080000, // Blocked by solid actors, even if not solid itself
-	MF6_ADDITIVEPOISONDAMAGE	= 0x00100000,
-	MF6_ADDITIVEPOISONDURATION	= 0x00200000,
-	MF6_NOMENU			= 0x00400000,	// Player class should not appear in the class selection menu.
-	MF6_BOSSCUBE		= 0x00800000,	// Actor spawned by A_BrainSpit, flagged for timefreeze reasons.
-	MF6_SEEINVISIBLE	= 0x01000000,	// Monsters can see invisible player.
-	MF6_DONTCORPSE		= 0x02000000,	// [RC] Don't autoset MF_CORPSE upon death and don't force Crash state change.
-	MF6_POISONALWAYS	= 0x04000000,	// Always apply poison, even when target can't take the damage.
-	MF6_DOHARMSPECIES	= 0x08000000,	// Do hurt one's own species with projectiles.
-	MF6_INTRYMOVE		= 0x10000000,	// Executing P_TryMove
-	MF6_NOTAUTOAIMED	= 0x20000000,	// Do not subject actor to player autoaim.
-	MF6_NOTONAUTOMAP	= 0x40000000,	// will not be shown on automap with the 'scanner' powerup.
-	MF6_RELATIVETOFLOOR	= 0x80000000,	// [RC] Make flying actors be affected by lifts.
-};
-
-// --- mobj.flags7 ---
-enum ActorFlag7
-{
-	MF7_NEVERTARGET		= 0x00000001,	// can not be targetted at all, even if monster friendliness is considered.
-	MF7_NOTELESTOMP		= 0x00000002,	// cannot telefrag under any circumstances (even when set by MAPINFO)
-	MF7_ALWAYSTELEFRAG	= 0x00000004,	// will unconditionally be telefragged when in the way. Overrides all other settings.
-	MF7_HANDLENODELAY	= 0x00000008,	// respect NoDelay state flag
-	MF7_WEAPONSPAWN		= 0x00000010,	// subject to DF_NO_COOP_WEAPON_SPAWN dmflag
-	MF7_HARMFRIENDS		= 0x00000020,	// is allowed to harm friendly monsters.
-	MF7_BUDDHA			= 0x00000040,	// Behaves just like the buddha cheat. 
-	MF7_FOILBUDDHA		= 0x00000080,	// Similar to FOILINVUL, foils buddha mode.
-	MF7_DONTTHRUST		= 0x00000100,	// Thrusting functions do not take, and do not give thrust (damage) to actors with this flag.
-	MF7_ALLOWPAIN		= 0x00000200,	// Invulnerable or immune (via damagefactors) actors can still react to taking damage even if they don't.
-	MF7_CAUSEPAIN		= 0x00000400,	// Damage sources with this flag can cause similar effects like ALLOWPAIN.
-	MF7_THRUREFLECT		= 0x00000800,	// Actors who are reflective cause the missiles to not slow down or change angles.
-	MF7_MIRRORREFLECT	= 0x00001000,	// Actor is turned directly 180 degrees around when reflected.
-	MF7_AIMREFLECT		= 0x00002000,	// Actor is directly reflected straight back at the one who fired the projectile.
-	MF7_HITTARGET		= 0x00004000,	// The actor the projectile dies on is set to target, provided it's targetable anyway.
-	MF7_HITMASTER		= 0x00008000,	// Same as HITTARGET, except it's master instead of target.
-	MF7_HITTRACER		= 0x00010000,	// Same as HITTARGET, but for tracer.
-	MF7_FLYCHEAT		= 0x00020000,	// must be part of the actor so that it can be tracked properly
-	MF7_NODECAL			= 0x00040000,	// [ZK] Forces puff to have no impact decal
-	MF7_FORCEDECAL		= 0x00080000,	// [ZK] Forces puff's decal to override the weapon's.
-	MF7_LAXTELEFRAGDMG	= 0x00100000,	// [MC] Telefrag damage can be reduced.
-	MF7_ICESHATTER		= 0x00200000,	// [MC] Shatters ice corpses regardless of damagetype.
-};
-
-// --- mobj.renderflags ---
-enum ActorRenderFlag
-{
-	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
-
-	RF_FORCEYBILLBOARD		= 0x10000,	// [BB] OpenGL only: draw with y axis billboard, i.e. anchored to the floor (overrides gl_billboard_mode setting)
-	RF_FORCEXYBILLBOARD		= 0x20000,	// [BB] OpenGL only: draw with xy axis billboard, i.e. unanchored (overrides gl_billboard_mode setting)
-};
-
-#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
-};
-
-enum ActorBounceFlag
-{
-	BOUNCE_Walls = 1<<0,		// bounces off of walls
-	BOUNCE_Floors = 1<<1,		// bounces off of floors
-	BOUNCE_Ceilings = 1<<2,		// bounces off of ceilings
-	BOUNCE_Actors = 1<<3,		// bounces off of some actors
-	BOUNCE_AllActors = 1<<4,	// bounces off of all actors (requires BOUNCE_Actors to be set, too)
-	BOUNCE_AutoOff = 1<<5,		// when bouncing off a sector plane, if the new Z velocity is below 3.0, disable further bouncing
-	BOUNCE_HereticType = 1<<6,	// goes into Death state when bouncing on floors or ceilings
-
-	BOUNCE_UseSeeSound = 1<<7,	// compatibility fallback. This will only be set by
-								// the compatibility handlers for the old bounce flags.
-	BOUNCE_NoWallSound = 1<<8,	// don't make noise when bouncing off a wall
-	BOUNCE_Quiet = 1<<9,		// Strife's grenades don't make a bouncing sound
-	BOUNCE_ExplodeOnWater = 1<<10,	// explodes when hitting a water surface
-	BOUNCE_CanBounceWater = 1<<11,	// can bounce on water
-	// MBF bouncing is a bit different from other modes as Killough coded many special behavioral cases
-	// for them that are not present in ZDoom, so it is necessary to identify it properly.
-	BOUNCE_MBF = 1<<12,			// This in itself is not a valid mode, but replaces MBF's MF_BOUNCE flag.
-	BOUNCE_AutoOffFloorOnly = 1<<13,		// like BOUNCE_AutoOff, but only on floors
-	BOUNCE_UseBounceState = 1<<14,	// Use Bounce[.*] states
-
-	BOUNCE_TypeMask = BOUNCE_Walls | BOUNCE_Floors | BOUNCE_Ceilings | BOUNCE_Actors | BOUNCE_AutoOff | BOUNCE_HereticType | BOUNCE_MBF,
-
-	// The three "standard" 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.
-	BOUNCE_None = 0,
-	BOUNCE_Heretic = BOUNCE_Floors | BOUNCE_Ceilings | BOUNCE_HereticType,
-	BOUNCE_Doom = BOUNCE_Walls | BOUNCE_Floors | BOUNCE_Ceilings | BOUNCE_Actors | BOUNCE_AutoOff,
-	BOUNCE_Hexen = BOUNCE_Walls | BOUNCE_Floors | BOUNCE_Ceilings | BOUNCE_Actors,
-	BOUNCE_Grenade = BOUNCE_MBF | BOUNCE_Doom,		// Bounces on walls and flats like ZDoom bounce.
-	BOUNCE_Classic = BOUNCE_MBF | BOUNCE_Floors | BOUNCE_Ceilings,	// Bounces on flats only, but 
-																	// does not die when bouncing.
-
-	// combined types
-	BOUNCE_DoomCompat = BOUNCE_Doom | BOUNCE_UseSeeSound,
-	BOUNCE_HereticCompat = BOUNCE_Heretic | BOUNCE_UseSeeSound,
-	BOUNCE_HexenCompat = BOUNCE_Hexen | BOUNCE_UseSeeSound
-
-	// The distinction between BOUNCE_Actors and BOUNCE_AllActors: A missile with
-	// BOUNCE_Actors set will bounce off of reflective and "non-sentient" actors.
-	// A missile that also has BOUNCE_AllActors set will bounce off of any actor.
-	// For compatibility reasons when BOUNCE_Actors was implied by the bounce type
-	// being "Doom" or "Hexen" and BOUNCE_AllActors was the separate
-	// MF5_BOUNCEONACTORS, you must set BOUNCE_Actors for BOUNCE_AllActors to have
-	// an effect.
-
-
-};
-
-// [TP] Flagset definitions
-typedef TFlags<ActorFlag> ActorFlags;
-typedef TFlags<ActorFlag2> ActorFlags2;
-typedef TFlags<ActorFlag3> ActorFlags3;
-typedef TFlags<ActorFlag4> ActorFlags4;
-typedef TFlags<ActorFlag5> ActorFlags5;
-typedef TFlags<ActorFlag6> ActorFlags6;
-typedef TFlags<ActorFlag7> ActorFlags7;
-typedef TFlags<ActorRenderFlag> ActorRenderFlags;
-typedef TFlags<ActorBounceFlag, WORD> ActorBounceFlags;
-DEFINE_TFLAGS_OPERATORS (ActorFlags)
-DEFINE_TFLAGS_OPERATORS (ActorFlags2)
-DEFINE_TFLAGS_OPERATORS (ActorFlags3)
-DEFINE_TFLAGS_OPERATORS (ActorFlags4)
-DEFINE_TFLAGS_OPERATORS (ActorFlags5)
-DEFINE_TFLAGS_OPERATORS (ActorFlags6)
-DEFINE_TFLAGS_OPERATORS (ActorFlags7)
-DEFINE_TFLAGS_OPERATORS (ActorRenderFlags)
-DEFINE_TFLAGS_OPERATORS (ActorBounceFlags)
-
-// Used to affect the logic for thing activation through death, USESPECIAL and BUMPSPECIAL
-// "thing" refers to what has the flag and the special, "trigger" refers to what used or bumped it
-enum EThingSpecialActivationType
-{
-	THINGSPEC_Default			= 0,		// Normal behavior: a player must be the trigger, and is the activator
-	THINGSPEC_ThingActs			= 1,		// The thing itself is the activator of the special
-	THINGSPEC_ThingTargets		= 1<<1,		// The thing changes its target to the trigger
-	THINGSPEC_TriggerTargets	= 1<<2,		// The trigger changes its target to the thing
-	THINGSPEC_MonsterTrigger	= 1<<3,		// The thing can be triggered by a monster
-	THINGSPEC_MissileTrigger	= 1<<4,		// The thing can be triggered by a projectile
-	THINGSPEC_ClearSpecial		= 1<<5,		// Clears special after successful activation
-	THINGSPEC_NoDeathSpecial	= 1<<6,		// Don't activate special on death
-	THINGSPEC_TriggerActs		= 1<<7,		// The trigger is the activator of the special
-											// (overrides LEVEL_ACTOWNSPECIAL Hexen hack)
-	THINGSPEC_Activate			= 1<<8,		// The thing is activated when triggered
-	THINGSPEC_Deactivate		= 1<<9,		// The thing is deactivated when triggered
-	THINGSPEC_Switch			= 1<<10,	// The thing is alternatively activated and deactivated when triggered
-};
-
-// [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 line_t;
-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_FastSpeed,		// Speed in fast mode
-	AMETA_RDFactor,			// Radius damage factor
-	AMETA_CameraHeight,		// Height of camera when used as such
-	AMETA_HowlSound,		// Sound being played when electrocuted or poisoned
-	AMETA_BloodType,		// Blood replacement type
-	AMETA_BloodType2,		// Bloodsplatter replacement type
-	AMETA_BloodType3,		// AxeBlood replacement type
-};
-
-struct FDropItem 
-{
-	FName Name;
-	int probability;
-	int amount;
-	FDropItem * Next;
-};
-
-class FDropItemPtrArray : public TArray<FDropItem *>
-{
-public:
-	~FDropItemPtrArray()
-	{
-		Clear();
-	}
-
-	void Clear();
-};
-
-extern FDropItemPtrArray DropItemList;
-
-void FreeDropItemChain(FDropItem *chain);
-int StoreDropItemChain(FDropItem *chain);
-
-
-
-// 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, bool SpawningMapThing = false);
-
-	inline AActor *GetDefault () const
-	{
-		return (AActor *)(RUNTIME_TYPE(this)->Defaults);
-	}
-
-	FDropItem *GetDropItems();
-
-	// Return true if the monster should use a missile attack, false for melee
-	bool SuggestMissileAttack (fixed_t dist);
-
-	// Adjusts the angle for deflection/reflection of incoming missiles
-	// Returns true if the missile should be allowed to explode anyway
-	bool AdjustReflectionAngle (AActor *thing, angle_t &angle);
-
-	// Returns true if this actor is within melee range of its target
-	bool CheckMeleeRange();
-
-	virtual void BeginPlay();			// Called immediately after the actor is created
-	virtual void PostBeginPlay();		// Called immediately before the actor's first tick
-	virtual void LevelSpawned();		// Called after BeginPlay if this actor was spawned by the world
-	virtual void HandleSpawnFlags();	// Translates SpawnFlags into in-game flags.
-
-	virtual void MarkPrecacheSounds() const;	// Marks sounds used by this actor for precaching.
-
-	virtual void Activate (AActor *activator);
-	virtual void Deactivate (AActor *activator);
-
-	virtual void Tick ();
-
-	// Called when actor dies
-	virtual void Die (AActor *source, AActor *inflictor, int dmgflags = 0);
-
-	// 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, FName damagetype);
-
-	// 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
-	// Made a metadata property so no longer virtual
-	void Howl ();
-
-	// Actor just hit the floor
-	virtual void HitFloor ();
-
-	// plays bouncing sound
-	void PlayBounceSound(bool onfloor);
-
-	// Called when an actor with MF_MISSILE and MF2_FLOORBOUNCE hits the floor
-	virtual bool FloorBounceMissile (secplane_t &plane);
-
-	// 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
-	bool IsOkayToAttack (AActor *target);
-
-	// 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);
-
-	// 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);
-
-	// Take the amount value of an item from the inventory list.
-	// If nothing is left, the item may be destroyed.
-	// Returns true if the initial item count is positive.
-	virtual bool TakeInventory (const PClass *itemclass, int amount, bool fromdecorate = false, bool notakeinfinite = false);
-
-	// 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);
-
-	// Removes all items from the inventory.
-	void ClearInventory();
-
-	// 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, bool subclass = false);
-	AInventory *FindInventory (FName type);
-	template<class T> T *FindInventory ()
-	{
-		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 ();
-
-	// 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 (AActor *other, bool changeTarget, bool resetHealth=true);
-
-	// Moves the other actor's inventory to this one
-	void ObtainInventory (AActor *other);
-
-	// Die. Now.
-	virtual bool Massacre ();
-
-	// Transforms the actor into a finely-ground paste
-	virtual bool Grind(bool items);
-
-	// Get this actor's team
-	int GetTeam();
-
-	// 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);
-
-	inline bool IsNoClip2() const;
-
-	// What species am I?
-	virtual FName GetSpecies();
-
-	fixed_t GetBobOffset(fixed_t ticfrac=0) const
-	{
-		 if (!(flags2 & MF2_FLOATBOB))
-		 {
-			 return 0;
-		 }
-		 return finesine[MulScale22(((FloatBobPhase + level.maptime) << FRACBITS) + ticfrac, FINEANGLES) & FINEMASK] * 8;
-	}
-
-	// Enter the crash state
-	void Crash();
-
-	// Return starting health adjusted by skill level
-	int SpawnHealth();
-	int GibHealth();
-
-	inline bool isMissile(bool precise=true)
-	{
-		return (flags&MF_MISSILE) || (precise && GetDefault()->flags&MF_MISSILE);
-	}
-
-	// Check for monsters that count as kill but excludes all friendlies.
-	bool CountsAsKill() const
-	{
-		return (flags & MF_COUNTKILL) && !(flags & MF_FRIENDLY);
-	}
-
-	bool intersects(AActor *other) const
-	{
-		fixed_t blockdist = radius + other->radius;
-		return ( abs(x - other->x) < blockdist && abs(y - other->y) < blockdist);
-	}
-
-	PalEntry GetBloodColor() const
-	{
-		return (PalEntry)GetClass()->Meta.GetMetaInt(AMETA_BloodColor);
-	}
-
-	// These also set CF_INTERPVIEW for players.
-	void SetPitch(int p, bool interpolate, bool forceclamp = false);
-	void SetAngle(angle_t ang, bool interpolate);
-	void SetRoll(angle_t roll, bool interpolate);
-
-	const PClass *GetBloodType(int type = 0) const
-	{
-		const PClass *bloodcls;
-		if (type == 0)
-		{
-			bloodcls = PClass::FindClass((ENamedName)GetClass()->Meta.GetMetaInt(AMETA_BloodType, NAME_Blood));
-		}
-		else if (type == 1)
-		{
-			bloodcls = PClass::FindClass((ENamedName)GetClass()->Meta.GetMetaInt(AMETA_BloodType2, NAME_BloodSplatter));
-		}
-		else if (type == 2)
-		{
-			bloodcls = PClass::FindClass((ENamedName)GetClass()->Meta.GetMetaInt(AMETA_BloodType3, NAME_AxeBlood));
-		}
-		else return NULL;
-
-		if (bloodcls != NULL)
-		{
-			bloodcls = bloodcls->GetReplacement();
-		}
-		return bloodcls;
-	}
-
-	inline void SetFriendPlayer(player_t *player);
-
-	bool IsVisibleToPlayer() const;
-
-	// Calculate amount of missile damage
-	virtual int GetMissileDamage(int mask, int add);
-
-	bool CanSeek(AActor *target) const;
-
-	fixed_t GetGravity() const;
-	bool IsSentient() const;
-	const char *GetTag(const char *def = NULL) const;
-	void SetTag(const char *def);
-
-	// Triggers SECSPAC_Exit/SECSPAC_Enter and related events if oldsec != current sector
-	void CheckSectorTransition(sector_t *oldsec);
-
-// 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
-	FRenderStyle	RenderStyle;		// Style to draw this actor with
-	ActorRenderFlags	renderflags;		// Different rendering flags
-	FTextureID		picnum;				// Draw this instead of sprite if valid
-	DWORD			effects;			// [RH] see p_effect.h
-	fixed_t			alpha;
-	DWORD			fillcolor;			// Color to draw when STYLE_Shaded
-
-// interaction info
-	fixed_t			pitch;
-	angle_t			roll;	// This was fixed_t before, which is probably wrong
-	FBlockNode		*BlockNode;			// links in blocks (if needed)
-	struct sector_t	*Sector;
-	subsector_t *		subsector;
-	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;
-	FTextureID		floorpic;			// contacted sec floorpic
-	int				floorterrain;
-	struct sector_t	*ceilingsector;
-	FTextureID		ceilingpic;			// contacted sec ceilingpic
-	fixed_t			radius, height;		// for movement checking
-	fixed_t			projectilepassheight;	// height for clipping projectile movement against this actor
-	fixed_t			velx, vely, velz;	// velocity
-	SDWORD			tics;				// state tic counter
-	FState			*state;
-	SDWORD			Damage;			// For missiles and monster railgun
-	int				projectileKickback;
-	ActorFlags		flags;
-	ActorFlags2		flags2;			// Heretic flags
-	ActorFlags3		flags3;			// [RH] Hexen/Heretic actor-dependant behavior made flaggable
-	ActorFlags4		flags4;			// [RH] Even more flags!
-	ActorFlags5		flags5;			// OMG! We need another one.
-	ActorFlags6		flags6;			// Shit! Where did all the flags go?
-	ActorFlags7		flags7;			// WHO WANTS TO BET ON 8!?
-
-	// [BB] If 0, everybody can see the actor, if > 0, only members of team (VisibleToTeam-1) can see it.
-	DWORD			VisibleToTeam;
-
-	int				special1;		// Special info
-	int				special2;		// Special info
-	int				weaponspecial;	// Special info for weapons.
-	int 			health;
-	BYTE			movedir;		// 0-7
-	SBYTE			visdir;
-	SWORD			movecount;		// when 0, select a new dir
-	SWORD			strafecount;	// for MF3_AVOIDMELEE
-	TObjPtr<AActor> target;			// thing being chased/attacked (or NULL)
-									// also the originator for missiles
-	TObjPtr<AActor>	lastenemy;		// Last known enemy -- killough 2/15/98
-	TObjPtr<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_t		*player;		// only valid if type of APlayerPawn
-	TObjPtr<AActor>	LastLookActor;	// Actor last looked for (if TIDtoHate != 0)
-	fixed_t			SpawnPoint[3]; 	// For nightmare respawn
-	WORD			SpawnAngle;
-	int				StartHealth;
-	BYTE			WeaveIndexXY;	// Separated from special2 because it's used by globally accessible functions.
-	BYTE			WeaveIndexZ;
-	int				skillrespawncount;
-	int				TIDtoHate;			// TID of things to hate (0 if none)
-	FNameNoInit		Species;		// For monster families
-	TObjPtr<AActor>	tracer;			// Thing being chased/attacked for tracers
-	TObjPtr<AActor>	master;			// Thing which spawned this one (prevents mutual attacks)
-	fixed_t			floorclip;		// value to use for floor clipping
-	int				tid;			// thing identifier
-	int				special;		// special
-	int				args[5];		// special arguments
-
-	int		accuracy, stamina;		// [RH] Strife stats -- [XA] moved here for DECORATE/ACS access.
-
-	AActor			*inext, **iprev;// Links to other mobjs in same bucket
-	TObjPtr<AActor> goal;			// Monster's goal if not chasing anything
-	int				waterlevel;		// 0=none, 1=feet, 2=waist, 3=eyes
-	BYTE			boomwaterlevel;	// splash information for non-swimmable water sectors
-	BYTE			MinMissileChance;// [RH] If a random # is > than this, then missile attack.
-	SBYTE			LastLookPlayerNumber;// Player number last looked for (if TIDtoHate == 0)
-	ActorBounceFlags	BounceFlags;	// which bouncing type?
-	DWORD			SpawnFlags;		// Increased to DWORD because of Doom 64
-	fixed_t			meleerange;		// specifies how far a melee attack reaches.
-	fixed_t			meleethreshold;	// Distance below which a monster doesn't try to shoot missiles anynore
-									// but instead tries to come closer for a melee attack.
-									// This is not the same as meleerange
-	fixed_t			maxtargetrange;	// any target farther away cannot be attacked
-	fixed_t			bouncefactor;	// Strife's grenades use 50%, Hexen's Flechettes 70.
-	fixed_t			wallbouncefactor;	// The bounce factor for walls can be different.
-	int				bouncecount;	// Strife's grenades only bounce twice before exploding
-	fixed_t			gravity;		// [GRB] Gravity factor
-	fixed_t			Friction;
-	int 			FastChaseStrafeCount;
-	fixed_t			pushfactor;
-	int				lastpush;
-	int				activationtype;	// How the thing behaves when activated with USESPECIAL or BUMPSPECIAL
-	int				lastbump;		// Last time the actor was bumped, used to control BUMPSPECIAL
-	int				Score;			// manipulated by score items, ACS or DECORATE. The engine doesn't use this itself for anything.
-	FString *		Tag;			// Strife's tag name.
-	int				DesignatedTeam;	// Allow for friendly fire cacluations to be done on non-players.
-
-	AActor			*BlockingMobj;	// Actor that blocked the last move
-	line_t			*BlockingLine;	// Line that blocked the last move
-
-	int PoisonDamage; // Damage received per tic from poison.
-	FNameNoInit PoisonDamageType; // Damage type dealt by poison.
-	int PoisonDuration; // Duration left for receiving poison damage.
-	int PoisonPeriod; // How often poison damage is applied. (Every X tics.)
-
-	int PoisonDamageReceived; // Damage received per tic from poison.
-	FNameNoInit PoisonDamageTypeReceived; // Damage type received by poison.
-	int PoisonDurationReceived; // Duration left for receiving poison damage.
-	int PoisonPeriodReceived; // How often poison damage is applied. (Every X tics.)
-	TObjPtr<AActor> Poisoner; // Last source of received poison damage.
-
-	// a linked list of sectors where this object appears
-	struct msecnode_t	*touching_sectorlist;				// phares 3/14/98
-
-	TObjPtr<AInventory>	Inventory;		// [RH] This actor's inventory
-	DWORD			InventoryID;	// A unique ID to keep track of inventory items
-
-	BYTE smokecounter;
-	BYTE FloatBobPhase;
-	BYTE FriendPlayer;				// [RH] Player # + 1 this friendly monster works for (so 0 is no player, 1 is player 0, etc)
-	DWORD Translation;
-
-	// [RH] Stuff that used to be part of an Actor Info
-	FSoundIDNoInit SeeSound;
-	FSoundIDNoInit AttackSound;
-	FSoundIDNoInit PainSound;
-	FSoundIDNoInit DeathSound;
-	FSoundIDNoInit ActiveSound;
-	FSoundIDNoInit UseSound;		// [RH] Sound to play when an actor is used.
-	FSoundIDNoInit BounceSound;
-	FSoundIDNoInit WallBounceSound;
-	FSoundIDNoInit CrushPainSound;
-
-	fixed_t Speed;
-	fixed_t FloatSpeed;
-	fixed_t MaxDropOffHeight, MaxStepHeight;
-	SDWORD Mass;
-	SWORD PainChance;
-	int PainThreshold;
-	FNameNoInit DamageType;
-	FNameNoInit DamageTypeReceived;
-	fixed_t DamageFactor;
-	fixed_t DamageMultiply;
-
-	FNameNoInit PainType;
-	FNameNoInit DeathType;
-	const PClass *TeleFogSourceType;
-	const PClass *TeleFogDestType;
-	int RipperLevel;
-	int RipLevelMin;
-	int RipLevelMax;
-
-	FState *SpawnState;
-	FState *SeeState;
-	FState *MeleeState;
-	FState *MissileState;
-
-	
-	int ConversationRoot;				// THe root of the current dialogue
-	FStrifeDialogueNode *Conversation;	// [RH] The dialogue to show when this actor is "used."
-
-	// [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;
-	angle_t PrevAngle;
-
-	// ThingIDs
-	static void ClearTIDHashes ();
-	void AddToHash ();
-	void RemoveFromHash ();
-
-private:
-	static AActor *TIDHash[128];
-	static inline int TIDHASH (int key) { return key & 127; }
-	static FSharedStringArena mStringPropertyData;
-
-	friend class FActorIterator;
-	friend bool P_IsTIDUsed(int tid);
-
-	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 nofunction=false);
-	virtual bool UpdateWaterLevel (fixed_t oldz, bool splash=true);
-	bool isFast();
-	bool isSlow();
-	void SetIdle(bool nofunction=false);
-	void ClearCounters();
-	FState *GetRaiseState();
-	void Revive();
-
-	FState *FindState (FName label) const
-	{
-		return GetClass()->ActorInfo->FindState(1, &label);
-	}
-
-	FState *FindState (FName label, FName sublabel, bool exact = false) const
-	{
-		FName names[] = { label, sublabel };
-		return GetClass()->ActorInfo->FindState(2, names, exact);
-	}
-
-	FState *FindState(int numnames, FName *names, bool exact = false) const
-	{
-		return GetClass()->ActorInfo->FindState(numnames, names, exact);
-	}
-
-	bool HasSpecialDeathStates () const;
-};
-
-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);
-	}
-};
-
-class NActorIterator : public FActorIterator
-{
-	const PClass *type;
-public:
-	NActorIterator (const PClass *cls, int id) : FActorIterator (id) { type = cls; }
-	NActorIterator (FName cls, int id) : FActorIterator (id) { type = PClass::FindClass(cls); }
-	NActorIterator (const char *cls, int id) : FActorIterator (id) { type = PClass::FindClass(cls); }
-	AActor *Next ()
-	{
-		AActor *actor;
-		if (type == NULL) return NULL;
-		do
-		{
-			actor = FActorIterator::Next ();
-		} while (actor && !actor->IsKindOf (type));
-		return actor;
-	}
-};
-
-bool P_IsTIDUsed(int tid);
-int P_FindUniqueTID(int start_tid, int limit);
-
-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);
-AActor *Spawn (FName classname, 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));
-}
-
-
-void PrintMiscActorInfo(AActor * query);
-
-#define S_FREETARGMOBJ	1
-
-#endif // __P_MOBJ_H__
+// 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"
+
+// We need the thinker_t stuff.
+#include "dthinker.h"
+
+
+// States are tied to finite states are tied to animation frames.
+#include "info.h"
+
+#include "doomdef.h"
+#include "textures/textures.h"
+#include "r_data/renderstyle.h"
+#include "s_sound.h"
+#include "memarena.h"
+#include "g_level.h"
+#include "tflags.h"
+
+struct subsector_t;
+//
+// 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?
+//
+
+// --- mobj.flags ---
+enum ActorFlag
+{
+	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
+
+	// --- dummies for unknown/unimplemented Strife flags ---
+	MF_STRIFEx8000000 = 0,		// seems related to MF_SHADOW
+};
+
+// --- mobj.flags2 ---
+enum ActorFlag2
+{
+	MF2_DONTREFLECT		= 0x00000001,	// this projectile cannot be reflected
+	MF2_WINDTHRUST		= 0x00000002,	// gets pushed around by the wind specials
+	MF2_DONTSEEKINVISIBLE=0x00000004,	// For seeker missiles: Don't home in on invisible/shadow targets
+	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_DONTTRANSLATE	= 0x00010000,	// Don't apply palette translations
+	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_THRUACTORS		= 0x00100000,	// performs no actor<->actor collision checks
+	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_ARGSDEFINED		= 0x20000000,	// Internal flag used by DECORATE to signal that the 
+										// args should not be taken from the mapthing definition
+	MF2_SEEKERMISSILE	= 0x40000000,	// is a seeker (for reflection)
+	MF2_REFLECTIVE		= 0x80000000,	// reflects missiles
+};
+
+// --- mobj.flags3 ---
+enum ActorFlag3
+{
+	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_AVOIDMELEE		= 0x00800000,	// Avoids melee attacks (same as MBF's monster_backing but must be explicitly set)
+	MF3_SCREENSEEKER    = 0x01000000,	// Fails the IsOkayToAttack test if potential target is outside player FOV
+	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 ---
+enum ActorFlag4
+{
+	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 / cannot be moved by any sector action.
+	MF4_STRIFEDAMAGE	= 0x00000100,	// Strife projectiles only do up to 4x damage, not 8x
+
+	MF4_CANUSEWALLS		= 0x00000200,	// Can activate 'use' specials
+	MF4_MISSILEMORE		= 0x00000400,	// increases the chance of a missile attack
+	MF4_MISSILEEVENMORE	= 0x00000800,	// significantly increases the chance of a missile attack
+	MF4_FORCERADIUSDMG	= 0x00001000,	// if put on an object it will override MF3_NORADIUSDMG
+	MF4_DONTFALL		= 0x00002000,	// Doesn't have NOGRAVITY disabled when dying.
+	MF4_SEESDAGGERS		= 0x00004000,	// This actor can see you striking with a dagger
+	MF4_INCOMBAT		= 0x00008000,	// Don't alert others when attacked by a dagger
+	MF4_LOOKALLAROUND	= 0x00010000,	// Monster has eyes in the back of its head
+	MF4_STANDSTILL		= 0x00020000,	// Monster should not chase targets unless attacked?
+	MF4_SPECTRAL		= 0x00040000,
+	MF4_SCROLLMOVE		= 0x00080000,	// velocity has been applied by a scroller
+	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_DONTHARMCLASS	= 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_BOSSSPAWNED		= 0x80000000,	// Spawned by a boss spawn cube
+};
+
+// --- mobj.flags5 ---
+
+enum ActorFlag5
+{
+	MF5_DONTDRAIN		= 0x00000001,	// cannot be drained health from.
+	/*					= 0x00000002,	   reserved for use by scripting branch */
+	MF5_NODROPOFF		= 0x00000004,	// cannot drop off under any circumstances.
+	MF5_NOFORWARDFALL	= 0x00000008,	// Does not make any actor fall forward by being damaged by this
+	MF5_COUNTSECRET		= 0x00000010,	// From Doom 64: actor acts like a secret
+	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
+	MF5_NOBLOODDECALS	= 0x00001000,	// Actor bleeds but doesn't spawn blood decals
+	MF5_USESPECIAL		= 0x00002000,	// Actor executes its special when being 'used'.
+	MF5_NOPAIN			= 0x00004000,	// If set the pain state won't be entered
+	MF5_ALWAYSFAST		= 0x00008000,	// always uses 'fast' attacking logic
+	MF5_NEVERFAST		= 0x00010000,	// never uses 'fast' attacking logic
+	MF5_ALWAYSRESPAWN	= 0x00020000,	// always respawns, regardless of skill setting
+	MF5_NEVERRESPAWN	= 0x00040000,	// never respawns, regardless of skill setting
+	MF5_DONTRIP			= 0x00080000,	// Ripping projectiles explode when hitting this actor
+	MF5_NOINFIGHTING	= 0x00100000,	// This actor doesn't switch target when it's hurt 
+	MF5_NOINTERACTION	= 0x00200000,	// Thing is completely excluded from any gameplay related checks
+	MF5_NOTIMEFREEZE	= 0x00400000,	// Actor is not affected by time freezer
+	MF5_PUFFGETSOWNER	= 0x00800000,	// [BB] Sets the owner of the puff to the player who fired it
+	MF5_SPECIALFIREDAMAGE=0x01000000,	// Special treatment of PhoenixFX1 turned into a flag to remove
+										// dependence of main engine code of specific actor types.
+	MF5_SUMMONEDMONSTER	= 0x02000000,	// To mark the friendly Minotaur. Hopefully to be generalized later.
+	MF5_NOVERTICALMELEERANGE=0x04000000,// Does not check vertical distance for melee range
+	MF5_BRIGHT			= 0x08000000,	// Actor is always rendered fullbright
+	MF5_CANTSEEK		= 0x10000000,	// seeker missiles cannot home in on this actor
+	MF5_INCONVERSATION	= 0x20000000,	// Actor is having a conversation
+	MF5_PAINLESS		= 0x40000000,	// Actor always inflicts painless damage.
+	MF5_MOVEWITHSECTOR	= 0x80000000,	// P_ChangeSector() will still process this actor if it has MF_NOBLOCKMAP
+};
+
+// --- mobj.flags6 ---
+enum ActorFlag6
+{
+	MF6_NOBOSSRIP		= 0x00000001,	// For rippermissiles: Don't rip through bosses.
+	MF6_THRUSPECIES		= 0x00000002,	// Actors passes through other of the same species.
+	MF6_MTHRUSPECIES	= 0x00000004,	// Missile passes through actors of its shooter's species.
+	MF6_FORCEPAIN		= 0x00000008,	// forces target into painstate (unless it has the NOPAIN flag)
+	MF6_NOFEAR			= 0x00000010,	// Not scared of frightening players
+	MF6_BUMPSPECIAL		= 0x00000020,	// Actor executes its special when being collided (as the ST flag)
+	MF6_DONTHARMSPECIES = 0x00000040,	// Don't hurt one's own species with explosions (hitscans, too?)
+	MF6_STEPMISSILE		= 0x00000080,	// Missile can "walk" up steps
+	MF6_NOTELEFRAG		= 0x00000100,	// [HW] Actor can't be telefragged
+	MF6_TOUCHY			= 0x00000200,	// From MBF: killough 11/98: dies when solids touch it
+	MF6_CANJUMP			= 0x00000400,	// From MBF: a dedicated flag instead of the BOUNCES+FLOAT+sentient combo
+	MF6_JUMPDOWN		= 0x00000800,	// From MBF: generalization of dog behavior wrt. dropoffs.
+	MF6_VULNERABLE		= 0x00001000,	// Actor can be damaged (even if not shootable).
+	MF6_ARMED			= 0x00002000,	// From MBF: Object is armed (for MF6_TOUCHY objects)
+	MF6_FALLING			= 0x00004000,	// From MBF: Object is falling (for pseudotorque simulation)
+	MF6_LINEDONE		= 0x00008000,	// From MBF: Object has already run a line effect
+	MF6_NOTRIGGER		= 0x00010000,	// actor cannot trigger any line actions
+	MF6_SHATTERING		= 0x00020000,	// marks an ice corpse for forced shattering
+	MF6_KILLED			= 0x00040000,	// Something that was killed (but not necessarily a corpse)
+	MF6_BLOCKEDBYSOLIDACTORS = 0x00080000, // Blocked by solid actors, even if not solid itself
+	MF6_ADDITIVEPOISONDAMAGE	= 0x00100000,
+	MF6_ADDITIVEPOISONDURATION	= 0x00200000,
+	MF6_NOMENU			= 0x00400000,	// Player class should not appear in the class selection menu.
+	MF6_BOSSCUBE		= 0x00800000,	// Actor spawned by A_BrainSpit, flagged for timefreeze reasons.
+	MF6_SEEINVISIBLE	= 0x01000000,	// Monsters can see invisible player.
+	MF6_DONTCORPSE		= 0x02000000,	// [RC] Don't autoset MF_CORPSE upon death and don't force Crash state change.
+	MF6_POISONALWAYS	= 0x04000000,	// Always apply poison, even when target can't take the damage.
+	MF6_DOHARMSPECIES	= 0x08000000,	// Do hurt one's own species with projectiles.
+	MF6_INTRYMOVE		= 0x10000000,	// Executing P_TryMove
+	MF6_NOTAUTOAIMED	= 0x20000000,	// Do not subject actor to player autoaim.
+	MF6_NOTONAUTOMAP	= 0x40000000,	// will not be shown on automap with the 'scanner' powerup.
+	MF6_RELATIVETOFLOOR	= 0x80000000,	// [RC] Make flying actors be affected by lifts.
+};
+
+// --- mobj.flags7 ---
+enum ActorFlag7
+{
+	MF7_NEVERTARGET		= 0x00000001,	// can not be targetted at all, even if monster friendliness is considered.
+	MF7_NOTELESTOMP		= 0x00000002,	// cannot telefrag under any circumstances (even when set by MAPINFO)
+	MF7_ALWAYSTELEFRAG	= 0x00000004,	// will unconditionally be telefragged when in the way. Overrides all other settings.
+	MF7_HANDLENODELAY	= 0x00000008,	// respect NoDelay state flag
+	MF7_WEAPONSPAWN		= 0x00000010,	// subject to DF_NO_COOP_WEAPON_SPAWN dmflag
+	MF7_HARMFRIENDS		= 0x00000020,	// is allowed to harm friendly monsters.
+	MF7_BUDDHA			= 0x00000040,	// Behaves just like the buddha cheat. 
+	MF7_FOILBUDDHA		= 0x00000080,	// Similar to FOILINVUL, foils buddha mode.
+	MF7_DONTTHRUST		= 0x00000100,	// Thrusting functions do not take, and do not give thrust (damage) to actors with this flag.
+	MF7_ALLOWPAIN		= 0x00000200,	// Invulnerable or immune (via damagefactors) actors can still react to taking damage even if they don't.
+	MF7_CAUSEPAIN		= 0x00000400,	// Damage sources with this flag can cause similar effects like ALLOWPAIN.
+	MF7_THRUREFLECT		= 0x00000800,	// Actors who are reflective cause the missiles to not slow down or change angles.
+	MF7_MIRRORREFLECT	= 0x00001000,	// Actor is turned directly 180 degrees around when reflected.
+	MF7_AIMREFLECT		= 0x00002000,	// Actor is directly reflected straight back at the one who fired the projectile.
+	MF7_HITTARGET		= 0x00004000,	// The actor the projectile dies on is set to target, provided it's targetable anyway.
+	MF7_HITMASTER		= 0x00008000,	// Same as HITTARGET, except it's master instead of target.
+	MF7_HITTRACER		= 0x00010000,	// Same as HITTARGET, but for tracer.
+	MF7_FLYCHEAT		= 0x00020000,	// must be part of the actor so that it can be tracked properly
+	MF7_NODECAL			= 0x00040000,	// [ZK] Forces puff to have no impact decal
+	MF7_FORCEDECAL		= 0x00080000,	// [ZK] Forces puff's decal to override the weapon's.
+	MF7_LAXTELEFRAGDMG	= 0x00100000,	// [MC] Telefrag damage can be reduced.
+	MF7_ICESHATTER		= 0x00200000,	// [MC] Shatters ice corpses regardless of damagetype.
+};
+
+// --- mobj.renderflags ---
+enum ActorRenderFlag
+{
+	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
+
+	RF_FORCEYBILLBOARD		= 0x10000,	// [BB] OpenGL only: draw with y axis billboard, i.e. anchored to the floor (overrides gl_billboard_mode setting)
+	RF_FORCEXYBILLBOARD		= 0x20000,	// [BB] OpenGL only: draw with xy axis billboard, i.e. unanchored (overrides gl_billboard_mode setting)
+};
+
+#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
+};
+
+enum ActorBounceFlag
+{
+	BOUNCE_Walls = 1<<0,		// bounces off of walls
+	BOUNCE_Floors = 1<<1,		// bounces off of floors
+	BOUNCE_Ceilings = 1<<2,		// bounces off of ceilings
+	BOUNCE_Actors = 1<<3,		// bounces off of some actors
+	BOUNCE_AllActors = 1<<4,	// bounces off of all actors (requires BOUNCE_Actors to be set, too)
+	BOUNCE_AutoOff = 1<<5,		// when bouncing off a sector plane, if the new Z velocity is below 3.0, disable further bouncing
+	BOUNCE_HereticType = 1<<6,	// goes into Death state when bouncing on floors or ceilings
+
+	BOUNCE_UseSeeSound = 1<<7,	// compatibility fallback. This will only be set by
+								// the compatibility handlers for the old bounce flags.
+	BOUNCE_NoWallSound = 1<<8,	// don't make noise when bouncing off a wall
+	BOUNCE_Quiet = 1<<9,		// Strife's grenades don't make a bouncing sound
+	BOUNCE_ExplodeOnWater = 1<<10,	// explodes when hitting a water surface
+	BOUNCE_CanBounceWater = 1<<11,	// can bounce on water
+	// MBF bouncing is a bit different from other modes as Killough coded many special behavioral cases
+	// for them that are not present in ZDoom, so it is necessary to identify it properly.
+	BOUNCE_MBF = 1<<12,			// This in itself is not a valid mode, but replaces MBF's MF_BOUNCE flag.
+	BOUNCE_AutoOffFloorOnly = 1<<13,		// like BOUNCE_AutoOff, but only on floors
+	BOUNCE_UseBounceState = 1<<14,	// Use Bounce[.*] states
+
+	BOUNCE_TypeMask = BOUNCE_Walls | BOUNCE_Floors | BOUNCE_Ceilings | BOUNCE_Actors | BOUNCE_AutoOff | BOUNCE_HereticType | BOUNCE_MBF,
+
+	// The three "standard" 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.
+	BOUNCE_None = 0,
+	BOUNCE_Heretic = BOUNCE_Floors | BOUNCE_Ceilings | BOUNCE_HereticType,
+	BOUNCE_Doom = BOUNCE_Walls | BOUNCE_Floors | BOUNCE_Ceilings | BOUNCE_Actors | BOUNCE_AutoOff,
+	BOUNCE_Hexen = BOUNCE_Walls | BOUNCE_Floors | BOUNCE_Ceilings | BOUNCE_Actors,
+	BOUNCE_Grenade = BOUNCE_MBF | BOUNCE_Doom,		// Bounces on walls and flats like ZDoom bounce.
+	BOUNCE_Classic = BOUNCE_MBF | BOUNCE_Floors | BOUNCE_Ceilings,	// Bounces on flats only, but 
+																	// does not die when bouncing.
+
+	// combined types
+	BOUNCE_DoomCompat = BOUNCE_Doom | BOUNCE_UseSeeSound,
+	BOUNCE_HereticCompat = BOUNCE_Heretic | BOUNCE_UseSeeSound,
+	BOUNCE_HexenCompat = BOUNCE_Hexen | BOUNCE_UseSeeSound
+
+	// The distinction between BOUNCE_Actors and BOUNCE_AllActors: A missile with
+	// BOUNCE_Actors set will bounce off of reflective and "non-sentient" actors.
+	// A missile that also has BOUNCE_AllActors set will bounce off of any actor.
+	// For compatibility reasons when BOUNCE_Actors was implied by the bounce type
+	// being "Doom" or "Hexen" and BOUNCE_AllActors was the separate
+	// MF5_BOUNCEONACTORS, you must set BOUNCE_Actors for BOUNCE_AllActors to have
+	// an effect.
+
+
+};
+
+// [TP] Flagset definitions
+typedef TFlags<ActorFlag> ActorFlags;
+typedef TFlags<ActorFlag2> ActorFlags2;
+typedef TFlags<ActorFlag3> ActorFlags3;
+typedef TFlags<ActorFlag4> ActorFlags4;
+typedef TFlags<ActorFlag5> ActorFlags5;
+typedef TFlags<ActorFlag6> ActorFlags6;
+typedef TFlags<ActorFlag7> ActorFlags7;
+typedef TFlags<ActorRenderFlag> ActorRenderFlags;
+typedef TFlags<ActorBounceFlag, WORD> ActorBounceFlags;
+DEFINE_TFLAGS_OPERATORS (ActorFlags)
+DEFINE_TFLAGS_OPERATORS (ActorFlags2)
+DEFINE_TFLAGS_OPERATORS (ActorFlags3)
+DEFINE_TFLAGS_OPERATORS (ActorFlags4)
+DEFINE_TFLAGS_OPERATORS (ActorFlags5)
+DEFINE_TFLAGS_OPERATORS (ActorFlags6)
+DEFINE_TFLAGS_OPERATORS (ActorFlags7)
+DEFINE_TFLAGS_OPERATORS (ActorRenderFlags)
+DEFINE_TFLAGS_OPERATORS (ActorBounceFlags)
+
+// Used to affect the logic for thing activation through death, USESPECIAL and BUMPSPECIAL
+// "thing" refers to what has the flag and the special, "trigger" refers to what used or bumped it
+enum EThingSpecialActivationType
+{
+	THINGSPEC_Default			= 0,		// Normal behavior: a player must be the trigger, and is the activator
+	THINGSPEC_ThingActs			= 1,		// The thing itself is the activator of the special
+	THINGSPEC_ThingTargets		= 1<<1,		// The thing changes its target to the trigger
+	THINGSPEC_TriggerTargets	= 1<<2,		// The trigger changes its target to the thing
+	THINGSPEC_MonsterTrigger	= 1<<3,		// The thing can be triggered by a monster
+	THINGSPEC_MissileTrigger	= 1<<4,		// The thing can be triggered by a projectile
+	THINGSPEC_ClearSpecial		= 1<<5,		// Clears special after successful activation
+	THINGSPEC_NoDeathSpecial	= 1<<6,		// Don't activate special on death
+	THINGSPEC_TriggerActs		= 1<<7,		// The trigger is the activator of the special
+											// (overrides LEVEL_ACTOWNSPECIAL Hexen hack)
+	THINGSPEC_Activate			= 1<<8,		// The thing is activated when triggered
+	THINGSPEC_Deactivate		= 1<<9,		// The thing is deactivated when triggered
+	THINGSPEC_Switch			= 1<<10,	// The thing is alternatively activated and deactivated when triggered
+};
+
+// [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 line_t;
+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_FastSpeed,		// Speed in fast mode
+	AMETA_RDFactor,			// Radius damage factor
+	AMETA_CameraHeight,		// Height of camera when used as such
+	AMETA_HowlSound,		// Sound being played when electrocuted or poisoned
+	AMETA_BloodType,		// Blood replacement type
+	AMETA_BloodType2,		// Bloodsplatter replacement type
+	AMETA_BloodType3,		// AxeBlood replacement type
+};
+
+struct FDropItem 
+{
+	FName Name;
+	int probability;
+	int amount;
+	FDropItem * Next;
+};
+
+class FDropItemPtrArray : public TArray<FDropItem *>
+{
+public:
+	~FDropItemPtrArray()
+	{
+		Clear();
+	}
+
+	void Clear();
+};
+
+extern FDropItemPtrArray DropItemList;
+
+void FreeDropItemChain(FDropItem *chain);
+int StoreDropItemChain(FDropItem *chain);
+fixed_t P_AproxDistance (fixed_t dx, fixed_t dy);	// since we cannot include p_local here...
+
+
+
+// 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, bool SpawningMapThing = false);
+
+	inline AActor *GetDefault () const
+	{
+		return (AActor *)(RUNTIME_TYPE(this)->Defaults);
+	}
+
+	FDropItem *GetDropItems();
+
+	// Return true if the monster should use a missile attack, false for melee
+	bool SuggestMissileAttack (fixed_t dist);
+
+	// Adjusts the angle for deflection/reflection of incoming missiles
+	// Returns true if the missile should be allowed to explode anyway
+	bool AdjustReflectionAngle (AActor *thing, angle_t &angle);
+
+	// Returns true if this actor is within melee range of its target
+	bool CheckMeleeRange();
+
+	virtual void BeginPlay();			// Called immediately after the actor is created
+	virtual void PostBeginPlay();		// Called immediately before the actor's first tick
+	virtual void LevelSpawned();		// Called after BeginPlay if this actor was spawned by the world
+	virtual void HandleSpawnFlags();	// Translates SpawnFlags into in-game flags.
+
+	virtual void MarkPrecacheSounds() const;	// Marks sounds used by this actor for precaching.
+
+	virtual void Activate (AActor *activator);
+	virtual void Deactivate (AActor *activator);
+
+	virtual void Tick ();
+
+	// Called when actor dies
+	virtual void Die (AActor *source, AActor *inflictor, int dmgflags = 0);
+
+	// 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, FName damagetype);
+
+	// 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
+	// Made a metadata property so no longer virtual
+	void Howl ();
+
+	// Actor just hit the floor
+	virtual void HitFloor ();
+
+	// plays bouncing sound
+	void PlayBounceSound(bool onfloor);
+
+	// Called when an actor with MF_MISSILE and MF2_FLOORBOUNCE hits the floor
+	virtual bool FloorBounceMissile (secplane_t &plane);
+
+	// 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
+	bool IsOkayToAttack (AActor *target);
+
+	// 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);
+
+	// 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);
+
+	// Take the amount value of an item from the inventory list.
+	// If nothing is left, the item may be destroyed.
+	// Returns true if the initial item count is positive.
+	virtual bool TakeInventory (const PClass *itemclass, int amount, bool fromdecorate = false, bool notakeinfinite = false);
+
+	// 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);
+
+	// Removes all items from the inventory.
+	void ClearInventory();
+
+	// 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, bool subclass = false);
+	AInventory *FindInventory (FName type);
+	template<class T> T *FindInventory ()
+	{
+		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 ();
+
+	// 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 (AActor *other, bool changeTarget, bool resetHealth=true);
+
+	// Moves the other actor's inventory to this one
+	void ObtainInventory (AActor *other);
+
+	// Die. Now.
+	virtual bool Massacre ();
+
+	// Transforms the actor into a finely-ground paste
+	virtual bool Grind(bool items);
+
+	// Get this actor's team
+	int GetTeam();
+
+	// 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);
+
+	inline bool IsNoClip2() const;
+
+	// What species am I?
+	virtual FName GetSpecies();
+
+	fixed_t GetBobOffset(fixed_t ticfrac=0) const
+	{
+		 if (!(flags2 & MF2_FLOATBOB))
+		 {
+			 return 0;
+		 }
+		 return finesine[MulScale22(((FloatBobPhase + level.maptime) << FRACBITS) + ticfrac, FINEANGLES) & FINEMASK] * 8;
+	}
+
+	// Enter the crash state
+	void Crash();
+
+	// Return starting health adjusted by skill level
+	int SpawnHealth();
+	int GibHealth();
+
+	inline bool isMissile(bool precise=true)
+	{
+		return (flags&MF_MISSILE) || (precise && GetDefault()->flags&MF_MISSILE);
+	}
+
+	// Check for monsters that count as kill but excludes all friendlies.
+	bool CountsAsKill() const
+	{
+		return (flags & MF_COUNTKILL) && !(flags & MF_FRIENDLY);
+	}
+
+	bool intersects(AActor *other) const
+	{
+		fixed_t blockdist = radius + other->radius;
+		return ( abs(x - other->x) < blockdist && abs(y - other->y) < blockdist);
+	}
+
+	PalEntry GetBloodColor() const
+	{
+		return (PalEntry)GetClass()->Meta.GetMetaInt(AMETA_BloodColor);
+	}
+
+	// These also set CF_INTERPVIEW for players.
+	void SetPitch(int p, bool interpolate, bool forceclamp = false);
+	void SetAngle(angle_t ang, bool interpolate);
+	void SetRoll(angle_t roll, bool interpolate);
+
+	const PClass *GetBloodType(int type = 0) const
+	{
+		const PClass *bloodcls;
+		if (type == 0)
+		{
+			bloodcls = PClass::FindClass((ENamedName)GetClass()->Meta.GetMetaInt(AMETA_BloodType, NAME_Blood));
+		}
+		else if (type == 1)
+		{
+			bloodcls = PClass::FindClass((ENamedName)GetClass()->Meta.GetMetaInt(AMETA_BloodType2, NAME_BloodSplatter));
+		}
+		else if (type == 2)
+		{
+			bloodcls = PClass::FindClass((ENamedName)GetClass()->Meta.GetMetaInt(AMETA_BloodType3, NAME_AxeBlood));
+		}
+		else return NULL;
+
+		if (bloodcls != NULL)
+		{
+			bloodcls = bloodcls->GetReplacement();
+		}
+		return bloodcls;
+	}
+
+	// 'absolute' is reserved for a linked portal implementation which needs
+	// to distinguish between portal-aware and portal-unaware distance calculation.
+	fixed_t AproxDistance(AActor *other, bool absolute = false)
+	{
+		return P_AproxDistance(x - other->x, y - other->y);
+	}
+
+	// same with 'ref' here.
+	fixed_t AproxDistance(fixed_t otherx, fixed_t othery, AActor *ref = NULL)
+	{
+		return P_AproxDistance(x - otherx, y - othery);
+	}
+
+	fixed_t AproxDistance(AActor *other, fixed_t xadd, fixed_t yadd, bool absolute = false)
+	{
+		return P_AproxDistance(x - other->x + xadd, y - other->y + yadd);
+	}
+
+	fixed_t AproxDistance3D(AActor *other, bool absolute = false)
+	{
+		return P_AproxDistance(AproxDistance(other), z - other->z);
+	}
+
+	// more precise, but slower version, being used in a few places
+	fixed_t Distance2D(AActor *other, bool absolute = false)
+	{
+		return xs_RoundToInt(FVector2(x - other->x, y - other->y).Length());
+	}
+
+	// a full 3D version of the above
+	fixed_t Distance3D(AActor *other, bool absolute = false)
+	{
+		return xs_RoundToInt(FVector3(x - other->x, y - other->y, z - other->z).Length());
+	}
+
+	inline void SetFriendPlayer(player_t *player);
+
+	bool IsVisibleToPlayer() const;
+
+	// Calculate amount of missile damage
+	virtual int GetMissileDamage(int mask, int add);
+
+	bool CanSeek(AActor *target) const;
+
+	fixed_t GetGravity() const;
+	bool IsSentient() const;
+	const char *GetTag(const char *def = NULL) const;
+	void SetTag(const char *def);
+
+	// Triggers SECSPAC_Exit/SECSPAC_Enter and related events if oldsec != current sector
+	void CheckSectorTransition(sector_t *oldsec);
+
+// 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
+	FRenderStyle	RenderStyle;		// Style to draw this actor with
+	ActorRenderFlags	renderflags;		// Different rendering flags
+	FTextureID		picnum;				// Draw this instead of sprite if valid
+	DWORD			effects;			// [RH] see p_effect.h
+	fixed_t			alpha;
+	DWORD			fillcolor;			// Color to draw when STYLE_Shaded
+
+// interaction info
+	fixed_t			pitch;
+	angle_t			roll;	// This was fixed_t before, which is probably wrong
+	FBlockNode		*BlockNode;			// links in blocks (if needed)
+	struct sector_t	*Sector;
+	subsector_t *		subsector;
+	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;
+	FTextureID		floorpic;			// contacted sec floorpic
+	int				floorterrain;
+	struct sector_t	*ceilingsector;
+	FTextureID		ceilingpic;			// contacted sec ceilingpic
+	fixed_t			radius, height;		// for movement checking
+	fixed_t			projectilepassheight;	// height for clipping projectile movement against this actor
+	fixed_t			velx, vely, velz;	// velocity
+	SDWORD			tics;				// state tic counter
+	FState			*state;
+	SDWORD			Damage;			// For missiles and monster railgun
+	int				projectileKickback;
+	ActorFlags		flags;
+	ActorFlags2		flags2;			// Heretic flags
+	ActorFlags3		flags3;			// [RH] Hexen/Heretic actor-dependant behavior made flaggable
+	ActorFlags4		flags4;			// [RH] Even more flags!
+	ActorFlags5		flags5;			// OMG! We need another one.
+	ActorFlags6		flags6;			// Shit! Where did all the flags go?
+	ActorFlags7		flags7;			// WHO WANTS TO BET ON 8!?
+
+	// [BB] If 0, everybody can see the actor, if > 0, only members of team (VisibleToTeam-1) can see it.
+	DWORD			VisibleToTeam;
+
+	int				special1;		// Special info
+	int				special2;		// Special info
+	int				weaponspecial;	// Special info for weapons.
+	int 			health;
+	BYTE			movedir;		// 0-7
+	SBYTE			visdir;
+	SWORD			movecount;		// when 0, select a new dir
+	SWORD			strafecount;	// for MF3_AVOIDMELEE
+	TObjPtr<AActor> target;			// thing being chased/attacked (or NULL)
+									// also the originator for missiles
+	TObjPtr<AActor>	lastenemy;		// Last known enemy -- killough 2/15/98
+	TObjPtr<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_t		*player;		// only valid if type of APlayerPawn
+	TObjPtr<AActor>	LastLookActor;	// Actor last looked for (if TIDtoHate != 0)
+	fixed_t			SpawnPoint[3]; 	// For nightmare respawn
+	WORD			SpawnAngle;
+	int				StartHealth;
+	BYTE			WeaveIndexXY;	// Separated from special2 because it's used by globally accessible functions.
+	BYTE			WeaveIndexZ;
+	int				skillrespawncount;
+	int				TIDtoHate;			// TID of things to hate (0 if none)
+	FNameNoInit		Species;		// For monster families
+	TObjPtr<AActor>	tracer;			// Thing being chased/attacked for tracers
+	TObjPtr<AActor>	master;			// Thing which spawned this one (prevents mutual attacks)
+	fixed_t			floorclip;		// value to use for floor clipping
+	int				tid;			// thing identifier
+	int				special;		// special
+	int				args[5];		// special arguments
+
+	int		accuracy, stamina;		// [RH] Strife stats -- [XA] moved here for DECORATE/ACS access.
+
+	AActor			*inext, **iprev;// Links to other mobjs in same bucket
+	TObjPtr<AActor> goal;			// Monster's goal if not chasing anything
+	int				waterlevel;		// 0=none, 1=feet, 2=waist, 3=eyes
+	BYTE			boomwaterlevel;	// splash information for non-swimmable water sectors
+	BYTE			MinMissileChance;// [RH] If a random # is > than this, then missile attack.
+	SBYTE			LastLookPlayerNumber;// Player number last looked for (if TIDtoHate == 0)
+	ActorBounceFlags	BounceFlags;	// which bouncing type?
+	DWORD			SpawnFlags;		// Increased to DWORD because of Doom 64
+	fixed_t			meleerange;		// specifies how far a melee attack reaches.
+	fixed_t			meleethreshold;	// Distance below which a monster doesn't try to shoot missiles anynore
+									// but instead tries to come closer for a melee attack.
+									// This is not the same as meleerange
+	fixed_t			maxtargetrange;	// any target farther away cannot be attacked
+	fixed_t			bouncefactor;	// Strife's grenades use 50%, Hexen's Flechettes 70.
+	fixed_t			wallbouncefactor;	// The bounce factor for walls can be different.
+	int				bouncecount;	// Strife's grenades only bounce twice before exploding
+	fixed_t			gravity;		// [GRB] Gravity factor
+	fixed_t			Friction;
+	int 			FastChaseStrafeCount;
+	fixed_t			pushfactor;
+	int				lastpush;
+	int				activationtype;	// How the thing behaves when activated with USESPECIAL or BUMPSPECIAL
+	int				lastbump;		// Last time the actor was bumped, used to control BUMPSPECIAL
+	int				Score;			// manipulated by score items, ACS or DECORATE. The engine doesn't use this itself for anything.
+	FString *		Tag;			// Strife's tag name.
+	int				DesignatedTeam;	// Allow for friendly fire cacluations to be done on non-players.
+
+	AActor			*BlockingMobj;	// Actor that blocked the last move
+	line_t			*BlockingLine;	// Line that blocked the last move
+
+	int PoisonDamage; // Damage received per tic from poison.
+	FNameNoInit PoisonDamageType; // Damage type dealt by poison.
+	int PoisonDuration; // Duration left for receiving poison damage.
+	int PoisonPeriod; // How often poison damage is applied. (Every X tics.)
+
+	int PoisonDamageReceived; // Damage received per tic from poison.
+	FNameNoInit PoisonDamageTypeReceived; // Damage type received by poison.
+	int PoisonDurationReceived; // Duration left for receiving poison damage.
+	int PoisonPeriodReceived; // How often poison damage is applied. (Every X tics.)
+	TObjPtr<AActor> Poisoner; // Last source of received poison damage.
+
+	// a linked list of sectors where this object appears
+	struct msecnode_t	*touching_sectorlist;				// phares 3/14/98
+
+	TObjPtr<AInventory>	Inventory;		// [RH] This actor's inventory
+	DWORD			InventoryID;	// A unique ID to keep track of inventory items
+
+	BYTE smokecounter;
+	BYTE FloatBobPhase;
+	BYTE FriendPlayer;				// [RH] Player # + 1 this friendly monster works for (so 0 is no player, 1 is player 0, etc)
+	DWORD Translation;
+
+	// [RH] Stuff that used to be part of an Actor Info
+	FSoundIDNoInit SeeSound;
+	FSoundIDNoInit AttackSound;
+	FSoundIDNoInit PainSound;
+	FSoundIDNoInit DeathSound;
+	FSoundIDNoInit ActiveSound;
+	FSoundIDNoInit UseSound;		// [RH] Sound to play when an actor is used.
+	FSoundIDNoInit BounceSound;
+	FSoundIDNoInit WallBounceSound;
+	FSoundIDNoInit CrushPainSound;
+
+	fixed_t Speed;
+	fixed_t FloatSpeed;
+	fixed_t MaxDropOffHeight, MaxStepHeight;
+	SDWORD Mass;
+	SWORD PainChance;
+	int PainThreshold;
+	FNameNoInit DamageType;
+	FNameNoInit DamageTypeReceived;
+	fixed_t DamageFactor;
+	fixed_t DamageMultiply;
+
+	FNameNoInit PainType;
+	FNameNoInit DeathType;
+	const PClass *TeleFogSourceType;
+	const PClass *TeleFogDestType;
+	int RipperLevel;
+	int RipLevelMin;
+	int RipLevelMax;
+
+	FState *SpawnState;
+	FState *SeeState;
+	FState *MeleeState;
+	FState *MissileState;
+
+	
+	int ConversationRoot;				// THe root of the current dialogue
+	FStrifeDialogueNode *Conversation;	// [RH] The dialogue to show when this actor is "used."
+
+	// [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;
+	angle_t PrevAngle;
+
+	// ThingIDs
+	static void ClearTIDHashes ();
+	void AddToHash ();
+	void RemoveFromHash ();
+
+private:
+	static AActor *TIDHash[128];
+	static inline int TIDHASH (int key) { return key & 127; }
+	static FSharedStringArena mStringPropertyData;
+
+	friend class FActorIterator;
+	friend bool P_IsTIDUsed(int tid);
+
+	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 nofunction=false);
+	virtual bool UpdateWaterLevel (fixed_t oldz, bool splash=true);
+	bool isFast();
+	bool isSlow();
+	void SetIdle(bool nofunction=false);
+	void ClearCounters();
+	FState *GetRaiseState();
+	void Revive();
+
+	FState *FindState (FName label) const
+	{
+		return GetClass()->ActorInfo->FindState(1, &label);
+	}
+
+	FState *FindState (FName label, FName sublabel, bool exact = false) const
+	{
+		FName names[] = { label, sublabel };
+		return GetClass()->ActorInfo->FindState(2, names, exact);
+	}
+
+	FState *FindState(int numnames, FName *names, bool exact = false) const
+	{
+		return GetClass()->ActorInfo->FindState(numnames, names, exact);
+	}
+
+	bool HasSpecialDeathStates () const;
+};
+
+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);
+	}
+};
+
+class NActorIterator : public FActorIterator
+{
+	const PClass *type;
+public:
+	NActorIterator (const PClass *cls, int id) : FActorIterator (id) { type = cls; }
+	NActorIterator (FName cls, int id) : FActorIterator (id) { type = PClass::FindClass(cls); }
+	NActorIterator (const char *cls, int id) : FActorIterator (id) { type = PClass::FindClass(cls); }
+	AActor *Next ()
+	{
+		AActor *actor;
+		if (type == NULL) return NULL;
+		do
+		{
+			actor = FActorIterator::Next ();
+		} while (actor && !actor->IsKindOf (type));
+		return actor;
+	}
+};
+
+bool P_IsTIDUsed(int tid);
+int P_FindUniqueTID(int start_tid, int limit);
+
+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);
+AActor *Spawn (FName classname, 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));
+}
+
+
+void PrintMiscActorInfo(AActor * query);
+
+#define S_FREETARGMOBJ	1
+
+#endif // __P_MOBJ_H__
diff --git a/src/b_func.cpp b/src/b_func.cpp
index f93625612..87b1e5416 100644
--- a/src/b_func.cpp
+++ b/src/b_func.cpp
@@ -37,7 +37,7 @@ bool DBot::Reachable (AActor *rtarget)
 
 	sector_t *last_s = player->mo->Sector;
 	fixed_t last_z = last_s->floorplane.ZatPoint (player->mo->x, player->mo->y);
-	fixed_t estimated_dist = P_AproxDistance (player->mo->x - rtarget->x, player->mo->y - rtarget->y);
+	fixed_t estimated_dist = player->mo->AproxDistance(rtarget);
 	bool reachable = true;
 
 	FPathTraverse it(player->mo->x+player->mo->velx, player->mo->y+player->mo->vely, rtarget->x, rtarget->y, PT_ADDLINES|PT_ADDTHINGS);
@@ -165,10 +165,8 @@ void DBot::Dofire (ticcmd_t *cmd)
 	//MAKEME: Decrease the rocket suicides even more.
 
 	no_fire = true;
-	//angle = R_PointToAngle2(player->mo->x, player->mo->y, player->enemy->x, player->enemy->y);
 	//Distance to enemy.
-	dist = P_AproxDistance ((player->mo->x + player->mo->velx) - (enemy->x + enemy->velx),
-		(player->mo->y + player->mo->vely) - (enemy->y + enemy->vely));
+	dist = player->mo->AproxDistance(enemy, player->mo->velx - enemy->velx, player->mo->vely - enemy->vely);
 
 	//FIRE EACH TYPE OF WEAPON DIFFERENT: Here should all the different weapons go.
 	if (player->ReadyWeapon->WeaponFlags & WIF_MELEEWEAPON)
@@ -219,7 +217,7 @@ void DBot::Dofire (ticcmd_t *cmd)
 		}
 		// prediction aiming
 shootmissile:
-		dist = P_AproxDistance (player->mo->x - enemy->x, player->mo->y - enemy->y);
+		dist = player->mo->AproxDistance (enemy);
 		m = dist / GetDefaultByType (player->ReadyWeapon->ProjectileType)->Speed;
 		bglobal.SetBodyAt (enemy->x + enemy->velx*m*2, enemy->y + enemy->vely*m*2, enemy->z, 1);
 		angle = R_PointToAngle2 (player->mo->x, player->mo->y, bglobal.body1->x, bglobal.body1->y);
@@ -331,8 +329,7 @@ AActor *DBot::Choose_Mate ()
 		{
 			if (P_CheckSight (player->mo, client->mo, SF_IGNOREVISIBILITY))
 			{
-				test = P_AproxDistance (client->mo->x - player->mo->x,
-										client->mo->y - player->mo->y);
+				test = client->mo->AproxDistance(player->mo);
 
 				if (test < closest_dist)
 				{
@@ -402,8 +399,7 @@ AActor *DBot::Find_enemy ()
 			if (Check_LOS (client->mo, vangle)) //Here's a strange one, when bot is standing still, the P_CheckSight within Check_LOS almost always returns false. tought it should be the same checksight as below but.. (below works) something must be fuckin wierd screded up. 
 			//if(P_CheckSight(player->mo, players[count].mo))
 			{
-				temp = P_AproxDistance (client->mo->x - player->mo->x,
-										client->mo->y - player->mo->y);
+				temp = client->mo->AproxDistance(player->mo);
 
 				//Too dark?
 				if (temp > DARK_DIST &&
@@ -505,7 +501,7 @@ angle_t DBot::FireRox (AActor *enemy, ticcmd_t *cmd)
 
 	actor = bglobal.body2;
 
-	dist = P_AproxDistance (actor->x-enemy->x, actor->y-enemy->y);
+	dist = actor->AproxDistance (enemy);
 	if (dist < SAFE_SELF_MISDIST)
 		return 0;
 	//Predict.
diff --git a/src/b_move.cpp b/src/b_move.cpp
index 4759f22d9..c608c5d03 100644
--- a/src/b_move.cpp
+++ b/src/b_move.cpp
@@ -347,7 +347,7 @@ void DBot::Pitch (AActor *target)
 	double diff;
 
 	diff = target->z - player->mo->z;
-	aim = atan (diff / (double)P_AproxDistance (player->mo->x - target->x, player->mo->y - target->y));
+	aim = atan(diff / (double)player->mo->AproxDistance(target));
 	player->mo->pitch = -(int)(aim * ANGLE_180/M_PI);
 }
 
diff --git a/src/b_think.cpp b/src/b_think.cpp
index 34baeee9c..73c5066ab 100644
--- a/src/b_think.cpp
+++ b/src/b_think.cpp
@@ -81,7 +81,7 @@ void DBot::ThinkForMove (ticcmd_t *cmd)
 	int r;
 
 	stuck = false;
-	dist = dest ? P_AproxDistance(player->mo->x-dest->x, player->mo->y-dest->y) : 0;
+	dist = dest ? player->mo->AproxDistance(dest) : 0;
 
 	if (missile &&
 		((!missile->velx || !missile->vely) || !Check_LOS(missile, SHOOTFOV*3/2)))
@@ -96,14 +96,14 @@ void DBot::ThinkForMove (ticcmd_t *cmd)
 		player->mo->pitch += 80;
 
 	//HOW TO MOVE:
-	if (missile && (P_AproxDistance(player->mo->x-missile->x, player->mo->y-missile->y)<AVOID_DIST)) //try avoid missile got from P_Mobj.c thinking part.
+	if (missile && (player->mo->AproxDistance(missile)<AVOID_DIST)) //try avoid missile got from P_Mobj.c thinking part.
 	{
 		Pitch (missile);
 		angle = R_PointToAngle2(player->mo->x, player->mo->y, missile->x, missile->y);
 		cmd->ucmd.sidemove = sleft ? -SIDERUN : SIDERUN;
 		cmd->ucmd.forwardmove = -FORWARDRUN; //Back IS best.
 
-		if ((P_AproxDistance(player->mo->x-oldx, player->mo->y-oldy)<50000)
+		if ((player->mo->AproxDistance(oldx, oldy)<50000)
 			&& t_strafe<=0)
 		{
 			t_strafe = 5;
@@ -156,7 +156,7 @@ void DBot::ThinkForMove (ticcmd_t *cmd)
 			t_fight = AFTERTICS;
 
 		if (t_strafe <= 0 &&
-			(P_AproxDistance(player->mo->x-oldx, player->mo->y-oldy)<50000
+			(player->mo->AproxDistance(oldx, oldy)<50000
 			|| ((pr_botmove()%30)==10))
 			)
 		{
@@ -168,7 +168,7 @@ void DBot::ThinkForMove (ticcmd_t *cmd)
 		angle = R_PointToAngle2(player->mo->x, player->mo->y, enemy->x, enemy->y);
 
 		if (player->ReadyWeapon == NULL ||
-			P_AproxDistance(player->mo->x-enemy->x, player->mo->y-enemy->y) >
+			player->mo->AproxDistance(enemy) >
 			player->ReadyWeapon->MoveCombatDist)
 		{
 			// If a monster, use lower speed (just for cooler apperance while strafing down doomed monster)
@@ -208,7 +208,7 @@ void DBot::ThinkForMove (ticcmd_t *cmd)
 
 		angle = R_PointToAngle2(player->mo->x, player->mo->y, mate->x, mate->y);
 
-		matedist = P_AproxDistance(player->mo->x - mate->x, player->mo->y - mate->y);
+		matedist = player->mo->AproxDistance(mate);
 		if (matedist > (FRIEND_DIST*2))
 			cmd->ucmd.forwardmove = FORWARDRUN;
 		else if (matedist > FRIEND_DIST)
diff --git a/src/g_doom/a_lostsoul.cpp b/src/g_doom/a_lostsoul.cpp
index fdc0257cb..1182292e0 100644
--- a/src/g_doom/a_lostsoul.cpp
+++ b/src/g_doom/a_lostsoul.cpp
@@ -36,7 +36,7 @@ void A_SkullAttack(AActor *self, fixed_t speed)
 	an = self->angle >> ANGLETOFINESHIFT;
 	self->velx = FixedMul (speed, finecosine[an]);
 	self->vely = FixedMul (speed, finesine[an]);
-	dist = P_AproxDistance (dest->x - self->x, dest->y - self->y);
+	dist = self->AproxDistance (dest);
 	dist = dist / speed;
 	
 	if (dist < 1)
diff --git a/src/g_doom/a_revenant.cpp b/src/g_doom/a_revenant.cpp
index 0600a59eb..90c6e0a51 100644
--- a/src/g_doom/a_revenant.cpp
+++ b/src/g_doom/a_revenant.cpp
@@ -102,10 +102,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Tracer)
 	if (!(self->flags3 & (MF3_FLOORHUGGER|MF3_CEILINGHUGGER)))
 	{
 		// change slope
-		dist = P_AproxDistance (dest->x - self->x,
-								dest->y - self->y);
-		
-		dist = dist / self->Speed;
+		dist = self->AproxDistance (dest) / self->Speed;
 
 		if (dist < 1)
 			dist = 1;
diff --git a/src/g_game.cpp b/src/g_game.cpp
index 64e746cef..b7d10251b 100644
--- a/src/g_game.cpp
+++ b/src/g_game.cpp
@@ -1479,8 +1479,7 @@ static fixed_t PlayersRangeFromSpot (FPlayerStart *spot)
 		if (!playeringame[i] || !players[i].mo || players[i].health <= 0)
 			continue;
 
-		distance = P_AproxDistance (players[i].mo->x - spot->x,
-									players[i].mo->y - spot->y);
+		distance = players[i].mo->AproxDistance (spot->x, spot->y);
 
 		if (distance < closest)
 			closest = distance;
diff --git a/src/g_heretic/a_ironlich.cpp b/src/g_heretic/a_ironlich.cpp
index dba16b622..75c05bf2b 100644
--- a/src/g_heretic/a_ironlich.cpp
+++ b/src/g_heretic/a_ironlich.cpp
@@ -91,8 +91,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_LichAttack)
 		P_TraceBleed (newdam > 0 ? newdam : damage, target, self);
 		return;
 	}
-	dist = P_AproxDistance (self->x-target->x, self->y-target->y)
-		> 8*64*FRACUNIT;
+	dist = self->AproxDistance (target) > 8*64*FRACUNIT;
 	randAttack = pr_atk ();
 	if (randAttack < atkResolve1[dist])
 	{ // Ice ball
diff --git a/src/g_hexen/a_blastradius.cpp b/src/g_hexen/a_blastradius.cpp
index a78b0b4c8..53ce08b50 100644
--- a/src/g_hexen/a_blastradius.cpp
+++ b/src/g_hexen/a_blastradius.cpp
@@ -141,7 +141,7 @@ DEFINE_ACTION_FUNCTION_PARAMS (AActor, A_Blast)
 		{	// Must be monster, player, missile, touchy or vulnerable
 			continue;
 		}
-		dist = P_AproxDistance (self->x - mo->x, self->y - mo->y);
+		dist = self->AproxDistance (mo);
 		if (dist > radius)
 		{ // Out of range
 			continue;
diff --git a/src/g_hexen/a_clericholy.cpp b/src/g_hexen/a_clericholy.cpp
index 2b469e5af..73ffeac88 100644
--- a/src/g_hexen/a_clericholy.cpp
+++ b/src/g_hexen/a_clericholy.cpp
@@ -264,12 +264,11 @@ static void CHolyTailFollow (AActor *actor, fixed_t dist)
 		{
 			an = R_PointToAngle2(actor->x, actor->y, child->x, 
 				child->y)>>ANGLETOFINESHIFT;
-			oldDistance = P_AproxDistance (child->x-actor->x, child->y-actor->y);
+			oldDistance = child->AproxDistance (actor);
 			if (P_TryMove (child, actor->x+FixedMul(dist, finecosine[an]), 
 				actor->y+FixedMul(dist, finesine[an]), true))
 			{
-				newDistance = P_AproxDistance (child->x-actor->x, 
-					child->y-actor->y)-FRACUNIT;
+				newDistance = child->AproxDistance (actor)-FRACUNIT;
 				if (oldDistance < FRACUNIT)
 				{
 					if (child->z < actor->z)
@@ -425,7 +424,7 @@ static void CHolySeekerMissile (AActor *actor, angle_t thresh, angle_t turnMax)
 				deltaZ = -15*FRACUNIT;
 			}
 		}
-		dist = P_AproxDistance (target->x-actor->x, target->y-actor->y);
+		dist = actor->AproxDistance (target);
 		dist = dist / actor->Speed;
 		if (dist < 1)
 		{
diff --git a/src/g_hexen/a_dragon.cpp b/src/g_hexen/a_dragon.cpp
index fdf2428af..5b18c0d57 100644
--- a/src/g_hexen/a_dragon.cpp
+++ b/src/g_hexen/a_dragon.cpp
@@ -59,22 +59,16 @@ static void DragonSeek (AActor *actor, angle_t thresh, angle_t turnMax)
 	angle = actor->angle>>ANGLETOFINESHIFT;
 	actor->velx = FixedMul (actor->Speed, finecosine[angle]);
 	actor->vely = FixedMul (actor->Speed, finesine[angle]);
+	dist = actor->AproxDistance (target) / actor->Speed;
 	if (actor->z+actor->height < target->z ||
 		target->z+target->height < actor->z)
 	{
-		dist = P_AproxDistance(target->x-actor->x, target->y-actor->y);
-		dist = dist/actor->Speed;
 		if (dist < 1)
 		{
 			dist = 1;
 		}
 		actor->velz = (target->z - actor->z)/dist;
 	}
-	else
-	{
-		dist = P_AproxDistance (target->x-actor->x, target->y-actor->y);
-		dist = dist/actor->Speed;
-	}
 	if (target->flags&MF_SHOOTABLE && pr_dragonseek() < 64)
 	{ // attack the destination mobj if it's attackable
 		AActor *oldTarget;
diff --git a/src/g_hexen/a_firedemon.cpp b/src/g_hexen/a_firedemon.cpp
index c588dd2ae..b1cfafc0c 100644
--- a/src/g_hexen/a_firedemon.cpp
+++ b/src/g_hexen/a_firedemon.cpp
@@ -158,7 +158,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FiredChase)
 	{
 		self->special2 = 0;
 		self->velx = self->vely = 0;
-		dist = P_AproxDistance (self->x - target->x, self->y - target->y);
+		dist = self->AproxDistance (target);
 		if (dist < FIREDEMON_ATTACK_RANGE)
 		{
 			if (pr_firedemonchase() < 30)
diff --git a/src/g_hexen/a_healingradius.cpp b/src/g_hexen/a_healingradius.cpp
index b827f666b..d1d39ddd4 100644
--- a/src/g_hexen/a_healingradius.cpp
+++ b/src/g_hexen/a_healingradius.cpp
@@ -37,7 +37,7 @@ bool AArtiHealingRadius::Use (bool pickup)
 		if (playeringame[i] &&
 			players[i].mo != NULL &&
 			players[i].mo->health > 0 &&
-			P_AproxDistance (players[i].mo->x - Owner->x, players[i].mo->y - Owner->y) <= HEAL_RADIUS_DIST)
+			players[i].mo->AproxDistance (Owner) <= HEAL_RADIUS_DIST)
 		{
 			// Q: Is it worth it to make this selectable as a player property?
 			// A: Probably not - but it sure doesn't hurt.
diff --git a/src/g_hexen/a_heresiarch.cpp b/src/g_hexen/a_heresiarch.cpp
index 9ca0a70e8..498b4e955 100644
--- a/src/g_hexen/a_heresiarch.cpp
+++ b/src/g_hexen/a_heresiarch.cpp
@@ -665,8 +665,7 @@ void A_SorcOffense2(AActor *actor)
 	if (mo)
 	{
 		mo->special2 = 35*5/2;		// 5 seconds
-		dist = P_AproxDistance(dest->x - mo->x, dest->y - mo->y);
-		dist = dist/mo->Speed;
+		dist = mo->AproxDistance(dest) / mo->Speed;
 		if(dist < 1) dist = 1;
 		mo->velz = (dest->z - mo->z) / dist;
 	}
diff --git a/src/g_hexen/a_korax.cpp b/src/g_hexen/a_korax.cpp
index 5323fb851..ca849dd97 100644
--- a/src/g_hexen/a_korax.cpp
+++ b/src/g_hexen/a_korax.cpp
@@ -388,8 +388,7 @@ void A_KSpiritSeeker (AActor *actor, angle_t thresh, angle_t turnMax)
 				deltaZ = -15*FRACUNIT;
 			}
 		}
-		dist = P_AproxDistance (target->x-actor->x, target->y-actor->y);
-		dist = dist/actor->Speed;
+		dist = actor->AproxDistance (target) / actor->Speed;
 		if (dist < 1)
 		{
 			dist = 1;
@@ -495,8 +494,7 @@ AActor *P_SpawnKoraxMissile (fixed_t x, fixed_t y, fixed_t z,
 	an >>= ANGLETOFINESHIFT;
 	th->velx = FixedMul (th->Speed, finecosine[an]);
 	th->vely = FixedMul (th->Speed, finesine[an]);
-	dist = P_AproxDistance (dest->x - x, dest->y - y);
-	dist = dist/th->Speed;
+	dist = dest->AproxDistance (x, y, source) / th->Speed;
 	if (dist < 1)
 	{
 		dist = 1;
diff --git a/src/g_raven/a_minotaur.cpp b/src/g_raven/a_minotaur.cpp
index 0f9d9cd55..c0095226e 100644
--- a/src/g_raven/a_minotaur.cpp
+++ b/src/g_raven/a_minotaur.cpp
@@ -185,7 +185,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MinotaurDecide)
 	{
 		S_Sound (self, CHAN_WEAPON, "minotaur/sight", 1, ATTN_NORM);
 	}
-	dist = P_AproxDistance (self->x-target->x, self->y-target->y);
+	dist = self->AproxDistance (target);
 	if (target->z+target->height > self->z
 		&& target->z+target->height < self->z+self->height
 		&& dist < (friendly ? 16*64*FRACUNIT : 8*64*FRACUNIT)
@@ -489,7 +489,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MinotaurLook)
 			mo = player->mo;
 			if (mo == master) continue;
 			if (mo->health <= 0) continue;
-			dist = P_AproxDistance(self->x - mo->x, self->y - mo->y);
+			dist = self->AproxDistance(mo);
 			if (dist > MINOTAUR_LOOK_DIST) continue;
 			self->target = mo;
 			break;
@@ -514,7 +514,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MinotaurLook)
 			if (!(mo->flags3 & MF3_ISMONSTER)) continue;
 			if (mo->health <= 0) continue;
 			if (!(mo->flags & MF_SHOOTABLE)) continue;
-			dist = P_AproxDistance (self->x - mo->x, self->y - mo->y);
+			dist = self->AproxDistance(mo);
 			if (dist > MINOTAUR_LOOK_DIST) continue;
 			if ((mo == master) || (mo == self)) continue;
 			if ((mo->flags5 & MF5_SUMMONEDMONSTER) && (mo->tracer == master)) continue;
diff --git a/src/g_shared/a_quake.cpp b/src/g_shared/a_quake.cpp
index 3c8d704aa..195f3ccbf 100644
--- a/src/g_shared/a_quake.cpp
+++ b/src/g_shared/a_quake.cpp
@@ -129,7 +129,7 @@ void DEarthquake::Tick ()
 				AActor *victim = players[i].mo;
 				fixed_t dist;
 
-				dist = P_AproxDistance (victim->x - m_Spot->x, victim->y - m_Spot->y);
+				dist = m_Spot->AproxDistance (victim, true);
 				// Check if in damage radius
 				if (dist < m_DamageRadius && victim->z <= victim->floorz)
 				{
@@ -242,8 +242,7 @@ int DEarthquake::StaticGetQuakeIntensities(AActor *victim, FQuakeJiggers &jigger
 	{
 		if (quake->m_Spot != NULL)
 		{
-			fixed_t dist = P_AproxDistance (victim->x - quake->m_Spot->x,
-				victim->y - quake->m_Spot->y);
+			fixed_t dist = quake->m_Spot->AproxDistance (victim, true);
 			if (dist < quake->m_TremorRadius)
 			{
 				++count;
diff --git a/src/g_shared/a_specialspot.cpp b/src/g_shared/a_specialspot.cpp
index fbfbbf550..d3994ed84 100644
--- a/src/g_shared/a_specialspot.cpp
+++ b/src/g_shared/a_specialspot.cpp
@@ -158,7 +158,7 @@ struct FSpotList
 
 		while (true)
 		{
-			distance = P_AproxDistance(Spots[i]->x - x, Spots[i]->y - y);
+			distance = Spots[i]->AproxDistance(x, y);
 
 			if ((distance >= mindist) && ((maxdist == 0) || (distance <= maxdist))) break;
 
diff --git a/src/g_strife/a_crusader.cpp b/src/g_strife/a_crusader.cpp
index 7ef0b24a1..cf5f03a23 100644
--- a/src/g_strife/a_crusader.cpp
+++ b/src/g_strife/a_crusader.cpp
@@ -11,9 +11,9 @@
 
 static bool CrusaderCheckRange (AActor *self)
 {
-	if (P_CheckSight (self, self->target) && self->reactiontime == 0)
+	if (self->reactiontime == 0 && P_CheckSight (self, self->target))
 	{
-		return P_AproxDistance (self->x - self->target->x, self->y - self->target->y) < 264*FRACUNIT;
+		return self->AproxDistance (self->target) < 264*FRACUNIT;
 	}
 	return false;
 }
diff --git a/src/g_strife/a_inquisitor.cpp b/src/g_strife/a_inquisitor.cpp
index 70ca805f8..1a0739d36 100644
--- a/src/g_strife/a_inquisitor.cpp
+++ b/src/g_strife/a_inquisitor.cpp
@@ -20,7 +20,7 @@ bool InquisitorCheckDistance (AActor *self)
 {
 	if (self->reactiontime == 0 && P_CheckSight (self, self->target))
 	{
-		return P_AproxDistance (self->x - self->target->x, self->y - self->target->y) < 264*FRACUNIT;
+		return self->AproxDistance (self->target) < 264*FRACUNIT;
 	}
 	return false;
 }
@@ -85,7 +85,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_InquisitorJump)
 	speed = self->Speed * 2/3;
 	self->velx += FixedMul (speed, finecosine[an]);
 	self->vely += FixedMul (speed, finesine[an]);
-	dist = P_AproxDistance (self->target->x - self->x, self->target->y - self->y);
+	dist = self->AproxDistance (self->target);
 	dist /= speed;
 	if (dist < 1)
 	{
diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp
index 5291101a5..489fb107d 100644
--- a/src/p_enemy.cpp
+++ b/src/p_enemy.cpp
@@ -138,7 +138,7 @@ void P_RecursiveSound (sector_t *sec, AActor *soundtarget, bool splash, int soun
 	for (actor = sec->thinglist; actor != NULL; actor = actor->snext)
 	{
 		if (actor != soundtarget && (!splash || !(actor->flags4 & MF4_NOSPLASHALERT)) &&
-			(!maxdist || (P_AproxDistance(actor->x - emitter->x, actor->y - emitter->y) <= maxdist)))
+			(!maxdist || (actor->AproxDistance(emitter) <= maxdist)))
 		{
 			actor->LastHeard = soundtarget;
 		}
@@ -231,7 +231,7 @@ bool AActor::CheckMeleeRange ()
 	if (!pl)
 		return false;
 				
-	dist = P_AproxDistance (pl->x - x, pl->y - y);
+	dist = AproxDistance (pl);
 
 	if (dist >= meleerange + pl->radius)
 		return false;
@@ -275,7 +275,7 @@ bool P_CheckMeleeRange2 (AActor *actor)
 		return false;
 	}
 	mo = actor->target;
-	dist = P_AproxDistance (mo->x-actor->x, mo->y-actor->y);
+	dist = mo->AproxDistance (actor);
 	if (dist >= MELEERANGE*2 || dist < MELEERANGE-20*FRACUNIT + mo->radius)
 	{
 		return false;
@@ -348,8 +348,7 @@ bool P_CheckMissileRange (AActor *actor)
 
 	// OPTIMIZE: get this from a global checksight
 	// [RH] What?
-	dist = P_AproxDistance (actor->x-actor->target->x,
-							actor->y-actor->target->y) - 64*FRACUNIT;
+	dist = actor->AproxDistance (actor->target) - 64*FRACUNIT;
 	
 	if (actor->MeleeState == NULL)
 		dist -= 128*FRACUNIT;	// no melee attack, so fire more
@@ -394,7 +393,7 @@ bool P_HitFriend(AActor * self)
 	if (self->flags&MF_FRIENDLY && self->target != NULL)
 	{
 		angle_t angle = R_PointToAngle2 (self->x, self->y, self->target->x, self->target->y);
-		fixed_t dist = P_AproxDistance (self->x - self->target->x, self->y - self->target->y);
+		fixed_t dist = self->AproxDistance (self->target);
 		P_AimLineAttack (self, angle, dist, &linetarget, 0, true);
 		if (linetarget != NULL && linetarget != self->target)
 		{
@@ -450,7 +449,7 @@ bool P_Move (AActor *actor)
 
 	if ((actor->flags6 & MF6_JUMPDOWN) && target &&
 			!(target->IsFriend(actor)) &&
-			P_AproxDistance(actor->x - target->x, actor->y - target->y) < FRACUNIT*144 &&
+			actor->AproxDistance(target) < FRACUNIT*144 &&
 			pr_dropoff() < 235)
 	{
 		dropoff = 2;
@@ -933,7 +932,7 @@ void P_NewChaseDir(AActor * actor)
 		if (actor->flags3 & MF3_AVOIDMELEE)
 		{
 			bool ismeleeattacker = false;
-			fixed_t dist = P_AproxDistance(actor->x-target->x, actor->y-target->y);
+			fixed_t dist = actor->AproxDistance(target);
 			if (target->player == NULL)
 			{
 				ismeleeattacker = (target->MissileState == NULL && dist < (target->meleerange + target->radius)*2);
@@ -1151,7 +1150,7 @@ bool P_IsVisible(AActor *lookee, AActor *other, INTBOOL allaround, FLookExParams
 		fov = allaround ? 0 : ANGLE_180;
 	}
 
-	fixed_t dist = P_AproxDistance (other->x - lookee->x, other->y - lookee->y);
+	fixed_t dist = lookee->AproxDistance (other);
 
 	if (maxdist && dist > maxdist)
 		return false;			// [KS] too far
@@ -1202,8 +1201,7 @@ bool P_LookForMonsters (AActor *actor)
 		{ // Not a valid monster
 			continue;
 		}
-		if (P_AproxDistance (actor->x-mo->x, actor->y-mo->y)
-			> MONS_LOOK_RANGE)
+		if (mo->AproxDistance (actor) > MONS_LOOK_RANGE)
 		{ // Out of range
 			continue;
 		}
@@ -1703,10 +1701,8 @@ bool P_LookForPlayers (AActor *actor, INTBOOL allaround, FLookExParams *params)
 			if ((player->mo->flags & MF_SHADOW && !(i_compatflags & COMPATF_INVISIBILITY)) ||
 				player->mo->flags3 & MF3_GHOST)
 			{
-				if ((P_AproxDistance (player->mo->x - actor->x,
-						player->mo->y - actor->y) > 2*MELEERANGE)
-					&& P_AproxDistance (player->mo->velx, player->mo->vely)
-					< 5*FRACUNIT)
+				if ((player->mo->AproxDistance (actor) > 2*MELEERANGE)
+					&& P_AproxDistance (player->mo->velx, player->mo->vely)	< 5*FRACUNIT)
 				{ // Player is sneaking - can't detect
 					continue;
 				}
@@ -1903,8 +1899,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_LookEx)
 				}
 				else
 				{
-					dist = P_AproxDistance (targ->x - self->x,
-											targ->y - self->y);
+					dist = self->AproxDistance (targ);
 
 					// [KS] If the target is too far away, don't respond to the sound.
 					if (maxheardist && dist > maxheardist)
@@ -1975,8 +1970,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_LookEx)
 			{
 				if (self->flags & MF_AMBUSH)
 				{
-					dist = P_AproxDistance (self->target->x - self->x,
-											self->target->y - self->y);
+					dist = self->AproxDistance (self->target);
 					if (P_CheckSight (self, self->target, SF_SEEPASTBLOCKEVERYTHING) &&
 						(!minseedist || dist > minseedist) &&
 						(!maxseedist || dist < maxseedist))
@@ -2390,7 +2384,7 @@ void A_DoChase (AActor *actor, bool fastchase, FState *meleestate, FState *missi
 			actor->FastChaseStrafeCount = 0;
 			actor->velx = 0;
 			actor->vely = 0;
-			fixed_t dist = P_AproxDistance (actor->x - actor->target->x, actor->y - actor->target->y);
+			fixed_t dist = actor->AproxDistance (actor->target);
 			if (dist < CLASS_BOSS_STRAFE_RANGE)
 			{
 				if (pr_chase() < 100)
diff --git a/src/p_map.cpp b/src/p_map.cpp
index 7aeb9d115..58b4d2c1a 100644
--- a/src/p_map.cpp
+++ b/src/p_map.cpp
@@ -1075,8 +1075,8 @@ bool PIT_CheckThing(AActor *thing, FCheckPosition &tm)
 				 abs(thing->y - tm.thing->y) < (thing->radius+tm.thing->radius))
 
 		{
-			fixed_t newdist = P_AproxDistance(thing->x - tm.x, thing->y - tm.y);
-			fixed_t olddist = P_AproxDistance(thing->x - tm.thing->x, thing->y - tm.thing->y);
+			fixed_t newdist = thing->AproxDistance(tm.x, tm.y, tm.thing);
+			fixed_t olddist = thing->AproxDistance(tm.thing);
 
 			if (newdist > olddist)
 			{
@@ -1754,7 +1754,7 @@ void P_FakeZMovement(AActor *mo)
 	{ // float down towards target if too close
 		if (!(mo->flags & MF_SKULLFLY) && !(mo->flags & MF_INFLOAT))
 		{
-			fixed_t dist = P_AproxDistance(mo->x - mo->target->x, mo->y - mo->target->y);
+			fixed_t dist = mo->AproxDistance(mo->target);
 			fixed_t delta = (mo->target->z + (mo->height >> 1)) - mo->z;
 			if (delta < 0 && dist < -(delta * 3))
 				mo->z -= mo->FloatSpeed;
diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp
index 3d0d8e072..3eeb7c71a 100644
--- a/src/p_mobj.cpp
+++ b/src/p_mobj.cpp
@@ -1669,8 +1669,7 @@ bool P_SeekerMissile (AActor *actor, angle_t thresh, angle_t turnMax, bool preci
 			if (actor->z + actor->height < target->z ||
 				target->z + target->height < actor->z)
 			{ // Need to seek vertically
-				dist = P_AproxDistance (target->x - actor->x, target->y - actor->y);
-				dist = dist / speed;
+				dist = actor->AproxDistance (target) / speed;
 				if (dist < 1)
 				{
 					dist = 1;
@@ -2380,7 +2379,7 @@ void P_ZMovement (AActor *mo, fixed_t oldfloorz)
 	{	// float down towards target if too close
 		if (!(mo->flags & (MF_SKULLFLY | MF_INFLOAT)))
 		{
-			dist = P_AproxDistance (mo->x - mo->target->x, mo->y - mo->target->y);
+			dist = mo->AproxDistance (mo->target);
 			delta = (mo->target->z + (mo->height>>1)) - mo->z;
 			if (delta < 0 && dist < -(delta*3))
 				mo->z -= mo->FloatSpeed;
@@ -3392,7 +3391,7 @@ void AActor::Tick ()
 					if (health > 0
 						&& !players[i].Bot->enemy
 						&& player ? !IsTeammate (players[i].mo) : true
-						&& P_AproxDistance (players[i].mo->x-x, players[i].mo->y-y) < MAX_MONSTER_TARGET_DIST
+						&& AproxDistance (players[i].mo) < MAX_MONSTER_TARGET_DIST
 						&& P_CheckSight (players[i].mo, this, SF_SEEPASTBLOCKEVERYTHING))
 					{ //Probably a monster, so go kill it.
 						players[i].Bot->enemy = this;
@@ -5788,7 +5787,7 @@ AActor * P_OldSpawnMissile(AActor * source, AActor * owner, AActor * dest, const
 	th->velx = FixedMul (th->Speed, finecosine[an]);
 	th->vely = FixedMul (th->Speed, finesine[an]);
 
-	dist = P_AproxDistance (dest->x - source->x, dest->y - source->y);
+	dist = source->AproxDistance (dest);
 	if (th->Speed) dist = dist / th->Speed;
 
 	if (dist < 1)
@@ -5849,7 +5848,7 @@ AActor *P_SpawnMissileZAimed (AActor *source, fixed_t z, AActor *dest, const PCl
 	{
 		an += pr_spawnmissile.Random2() << 20;
 	}
-	dist = P_AproxDistance (dest->x - source->x, dest->y - source->y);
+	dist = source->AproxDistance (dest);
 	speed = GetDefaultSpeed (type);
 	dist /= speed;
 	velz = dist != 0 ? (dest->z - source->z)/dist : speed;
diff --git a/src/p_spec.cpp b/src/p_spec.cpp
index 918d07ed2..b7bc9a7b0 100644
--- a/src/p_spec.cpp
+++ b/src/p_spec.cpp
@@ -2225,7 +2225,7 @@ void DPusher::Tick ()
 			{
 				int sx = m_X;
 				int sy = m_Y;
-				int dist = P_AproxDistance (thing->x - sx,thing->y - sy);
+				int dist = thing->AproxDistance (sx, sy);
 				int speed = (m_Magnitude - ((dist>>FRACBITS)>>1))<<(FRACBITS-PUSH_FACTOR-1);
 
 				// If speed <= 0, you're outside the effective radius. You also have
diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp
index 89299e0fa..864641b0d 100644
--- a/src/thingdef/thingdef_codeptr.cpp
+++ b/src/thingdef/thingdef_codeptr.cpp
@@ -670,7 +670,7 @@ void DoJumpIfCloser(AActor *target, DECLARE_PARAMINFO)
 	// No target - no jump
 	if (!target)
 		return;
-	if (P_AproxDistance(self->x-target->x, self->y-target->y) < dist &&
+	if (self->AproxDistance(target) < dist &&
 		(noz || 
 		((self->z > target->z && self->z - (target->z + target->height) < dist) ||
 		(self->z <= target->z && target->z - (self->z + self->height) < dist))))
@@ -3342,8 +3342,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckLOF)
 
 		if (target)
 		{
-			FVector2 xyvec(target->x - x1, target->y - y1);
-			fixed_t distance = P_AproxDistance((fixed_t)xyvec.Length(), target->z - z1);
+			fixed_t xydist = self->Distance2D(target);
+			fixed_t distance = P_AproxDistance(xydist, target->z - z1);
 
 			if (range && !(flags & CLOFF_CHECKPARTIAL))
 			{
@@ -3372,11 +3372,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckLOF)
 			}
 			else if (flags & CLOFF_AIM_VERT_NOOFFSET)
 			{
-				pitch += R_PointToAngle2 (0,0, (fixed_t)xyvec.Length(), target->z - z1 + offsetheight + target->height / 2);
+				pitch += R_PointToAngle2 (0,0, xydist, target->z - z1 + offsetheight + target->height / 2);
 			}
 			else
 			{
-				pitch += R_PointToAngle2 (0,0, (fixed_t)xyvec.Length(), target->z - z1 + target->height / 2);
+				pitch += R_PointToAngle2 (0,0, xydist, target->z - z1 + target->height / 2);
 			}
 		}
 		else if (flags & CLOFF_ALLOWNULL)
@@ -3546,8 +3546,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetInLOS)
 	// [FDARI] If actors share team, don't jump
 	if ((flags & JLOSF_ALLYNOJUMP) && self->IsFriend(target)) return;
 
-	fixed_t distance = P_AproxDistance(target->x - self->x, target->y - self->y);
-	distance = P_AproxDistance(distance, target->z - self->z);
+	fixed_t distance = self->AproxDistance3D(target);
 
 	if (dist_max && (distance > dist_max)) return;
 
@@ -3635,8 +3634,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfInTargetLOS)
 
 	if ((flags & JLOSF_DEADNOJUMP) && (target->health <= 0)) return;
 
-	fixed_t distance = P_AproxDistance(target->x - self->x, target->y - self->y);
-	distance = P_AproxDistance(distance, target->z - self->z);
+	fixed_t distance = self->AproxDistance3D(target);
 
 	if (dist_max && (distance > dist_max)) return;
 
@@ -5950,7 +5948,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckProximity)
 			continue;
 
 		//Make sure it's in range and respect the desire for Z or not.
-		if (P_AproxDistance(ref->x - mo->x, ref->y - mo->y) < distance &&
+		if (ref->AproxDistance(mo) < distance &&
 			((flags & CPXF_NOZ) ||
 			((ref->z > mo->z && ref->z - (mo->z + mo->height) < distance) ||
 			(ref->z <= mo->z && mo->z - (ref->z + ref->height) < distance))))

From 2c0f64cf9fa06834cb10522e7399b950de486e19 Mon Sep 17 00:00:00 2001
From: Christoph Oelckers <c.oelckers@zdoom.fake>
Date: Sun, 10 Jan 2016 20:46:26 +0100
Subject: [PATCH 2/7] - refactoring of R_PointToAngle2 when used to calculate
 direction between two actors.

---
 src/actor.h                        | 22 ++++++++++++++++-
 src/b_func.cpp                     | 11 ++++-----
 src/b_move.cpp                     |  2 +-
 src/b_think.cpp                    |  8 +++----
 src/fragglescript/t_func.cpp       |  4 ++--
 src/g_doom/a_doomweaps.cpp         |  8 ++-----
 src/g_doom/a_revenant.cpp          |  2 +-
 src/g_doom/a_scriptedmarine.cpp    |  5 ++--
 src/g_heretic/a_chicken.cpp        |  6 ++---
 src/g_heretic/a_hereticweaps.cpp   | 12 ++++------
 src/g_hexen/a_blastradius.cpp      |  4 ++--
 src/g_hexen/a_clericholy.cpp       |  3 +--
 src/g_hexen/a_clericstaff.cpp      |  4 ++--
 src/g_hexen/a_dragon.cpp           | 12 ++++------
 src/g_hexen/a_fighterplayer.cpp    |  2 +-
 src/g_hexen/a_firedemon.cpp        |  2 +-
 src/g_hexen/a_flies.cpp            |  2 +-
 src/g_hexen/a_hexenspecialdecs.cpp |  3 +--
 src/g_hexen/a_korax.cpp            |  2 +-
 src/g_hexen/a_magelightning.cpp    |  2 +-
 src/g_raven/a_minotaur.cpp         |  2 +-
 src/g_shared/sbar_mugshot.cpp      |  2 +-
 src/g_strife/a_strifeweapons.cpp   |  5 +---
 src/p_conversation.cpp             |  2 +-
 src/p_enemy.cpp                    | 18 +++++---------
 src/p_interaction.cpp              |  2 +-
 src/p_map.cpp                      |  6 ++---
 src/p_mobj.cpp                     | 11 ++++-----
 src/p_spec.cpp                     |  2 +-
 src/p_things.cpp                   |  3 ++-
 src/thingdef/thingdef_codeptr.cpp  | 38 ++++++++----------------------
 31 files changed, 92 insertions(+), 115 deletions(-)

diff --git a/src/actor.h b/src/actor.h
index 0cd87ec52..114dd1179 100644
--- a/src/actor.h
+++ b/src/actor.h
@@ -612,7 +612,7 @@ extern FDropItemPtrArray DropItemList;
 void FreeDropItemChain(FDropItem *chain);
 int StoreDropItemChain(FDropItem *chain);
 fixed_t P_AproxDistance (fixed_t dx, fixed_t dy);	// since we cannot include p_local here...
-
+angle_t R_PointToAngle2 (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2); // same reason here with r_defs.h
 
 
 // Map Object definition.
@@ -889,6 +889,26 @@ public:
 		return xs_RoundToInt(FVector3(x - other->x, y - other->y, z - other->z).Length());
 	}
 
+	angle_t AngleTo(AActor *other, bool absolute = false) const
+	{
+		return R_PointToAngle2(x, y, other->x, other->y);
+	}
+
+	angle_t AngleTo(AActor *other, fixed_t oxofs, fixed_t oyofs, bool absolute = false) const
+	{
+		return R_PointToAngle2(x, y, other->x + oxofs, other->y + oyofs);
+	}
+
+	fixed_t AngleTo(fixed_t otherx, fixed_t othery, AActor *ref = NULL)
+	{
+		return R_PointToAngle2(x, y, otherx, othery);
+	}
+
+	fixed_t AngleXYTo(fixed_t myx, fixed_t myy, AActor *other, bool absolute = false)
+	{
+		return R_PointToAngle2(myx, myy, other->x, other->y);
+	}
+
 	inline void SetFriendPlayer(player_t *player);
 
 	bool IsVisibleToPlayer() const;
diff --git a/src/b_func.cpp b/src/b_func.cpp
index 87b1e5416..9594d29d8 100644
--- a/src/b_func.cpp
+++ b/src/b_func.cpp
@@ -123,7 +123,7 @@ bool DBot::Check_LOS (AActor *to, angle_t vangle)
 	if (vangle == 0)
 		return false; //Looker seems to be blind.
 
-	return absangle(R_PointToAngle2 (player->mo->x, player->mo->y, to->x, to->y) - player->mo->angle) <= vangle/2;
+	return absangle(player->mo->AngleTo(to) - player->mo->angle) <= vangle/2;
 }
 
 //-------------------------------------
@@ -220,14 +220,14 @@ shootmissile:
 		dist = player->mo->AproxDistance (enemy);
 		m = dist / GetDefaultByType (player->ReadyWeapon->ProjectileType)->Speed;
 		bglobal.SetBodyAt (enemy->x + enemy->velx*m*2, enemy->y + enemy->vely*m*2, enemy->z, 1);
-		angle = R_PointToAngle2 (player->mo->x, player->mo->y, bglobal.body1->x, bglobal.body1->y);
+		angle = player->mo->AngleTo(bglobal.body1);
 		if (Check_LOS (enemy, SHOOTFOV))
 			no_fire = false;
 	}
 	else
 	{
 		//Other weapons, mostly instant hit stuff.
-		angle = R_PointToAngle2 (player->mo->x, player->mo->y, enemy->x, enemy->y);
+		angle = player->mo->AngleTo(enemy);
 		aiming_penalty = 0;
 		if (enemy->flags & MF_SHADOW)
 			aiming_penalty += (pr_botdofire()%25)+10;
@@ -263,7 +263,6 @@ shootmissile:
 		cmd->ucmd.buttons |= BT_ATTACK;
 	}
 	//Prevents bot from jerking, when firing automatic things with low skill.
-	//player->mo->angle = R_PointToAngle2(player->mo->x, player->mo->y, player->enemy->x, player->enemy->y);
 }
 
 bool FCajunMaster::IsLeader (player_t *player)
@@ -518,7 +517,7 @@ angle_t DBot::FireRox (AActor *enemy, ticcmd_t *cmd)
 		{
 			if (bglobal.FakeFire (actor, bglobal.body1, cmd) >= SAFE_SELF_MISDIST)
 			{
-				ang = R_PointToAngle2 (actor->x, actor->y, bglobal.body1->x, bglobal.body1->y);
+				ang = actor->AngleTo(bglobal.body1);
 				return ang;
 			}
 		}
@@ -528,7 +527,7 @@ angle_t DBot::FireRox (AActor *enemy, ticcmd_t *cmd)
 	{
 		if (bglobal.FakeFire (player->mo, enemy, cmd) >= SAFE_SELF_MISDIST)
 		{
-			ang = R_PointToAngle2(player->mo->x, player->mo->y, enemy->x, enemy->y);
+			ang = player->mo->AngleTo(enemy);
 			return ang;
 		}
 	}
diff --git a/src/b_move.cpp b/src/b_move.cpp
index c608c5d03..5cacd5664 100644
--- a/src/b_move.cpp
+++ b/src/b_move.cpp
@@ -35,7 +35,7 @@ void DBot::Roam (ticcmd_t *cmd)
 
 	if (Reachable(dest))
 	{ // Straight towards it.
-		angle = R_PointToAngle2(player->mo->x, player->mo->y, dest->x, dest->y);
+		angle = player->mo->AngleTo(dest);
 	}
 	else if (player->mo->movedir < 8) // turn towards movement direction if not there yet
 	{
diff --git a/src/b_think.cpp b/src/b_think.cpp
index 73c5066ab..ced5b4b4e 100644
--- a/src/b_think.cpp
+++ b/src/b_think.cpp
@@ -99,7 +99,7 @@ void DBot::ThinkForMove (ticcmd_t *cmd)
 	if (missile && (player->mo->AproxDistance(missile)<AVOID_DIST)) //try avoid missile got from P_Mobj.c thinking part.
 	{
 		Pitch (missile);
-		angle = R_PointToAngle2(player->mo->x, player->mo->y, missile->x, missile->y);
+		angle = player->mo->AngleTo(missile);
 		cmd->ucmd.sidemove = sleft ? -SIDERUN : SIDERUN;
 		cmd->ucmd.forwardmove = -FORWARDRUN; //Back IS best.
 
@@ -165,7 +165,7 @@ void DBot::ThinkForMove (ticcmd_t *cmd)
 			sleft = !sleft;
 		}
 
-		angle = R_PointToAngle2(player->mo->x, player->mo->y, enemy->x, enemy->y);
+		angle = player->mo->AngleTo(enemy);
 
 		if (player->ReadyWeapon == NULL ||
 			player->mo->AproxDistance(enemy) >
@@ -206,7 +206,7 @@ void DBot::ThinkForMove (ticcmd_t *cmd)
 			goto roam;
 		}
 
-		angle = R_PointToAngle2(player->mo->x, player->mo->y, mate->x, mate->y);
+		angle = player->mo->AngleTo(mate);
 
 		matedist = player->mo->AproxDistance(mate);
 		if (matedist > (FRIEND_DIST*2))
@@ -241,7 +241,7 @@ void DBot::ThinkForMove (ticcmd_t *cmd)
 						(pr_botmove()%100)>skill.isp) && player->ReadyWeapon != NULL && !(player->ReadyWeapon->WeaponFlags & WIF_WIMPY_WEAPON))
 						dest = enemy;//Dont let enemy kill the bot by supressive fire. So charge enemy.
 					else //hide while t_fight, but keep view at enemy.
-						angle = R_PointToAngle2(player->mo->x, player->mo->y, enemy->x, enemy->y);
+						angle = player->mo->AngleTo(enemy);
 				} //Just a monster, so kill it.
 				else
 					dest = enemy;
diff --git a/src/fragglescript/t_func.cpp b/src/fragglescript/t_func.cpp
index fdf904764..ceabc9ce5 100644
--- a/src/fragglescript/t_func.cpp
+++ b/src/fragglescript/t_func.cpp
@@ -3145,8 +3145,8 @@ void FParser::SF_MoveCamera(void)
 		}
 		
 		// set step variables based on distance and speed
-		mobjangle = R_PointToAngle2(cam->x, cam->y, target->x, target->y);
-		xydist = R_PointToDist2(target->x - cam->x, target->y - cam->y);
+		mobjangle = cam->AngleTo(target);
+		xydist = cam->Distance2D(target);
 		
 		xstep = FixedMul(finecosine[mobjangle >> ANGLETOFINESHIFT], movespeed);
 		ystep = FixedMul(finesine[mobjangle >> ANGLETOFINESHIFT], movespeed);
diff --git a/src/g_doom/a_doomweaps.cpp b/src/g_doom/a_doomweaps.cpp
index 899f1f7d5..79dd6253f 100644
--- a/src/g_doom/a_doomweaps.cpp
+++ b/src/g_doom/a_doomweaps.cpp
@@ -59,10 +59,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Punch)
 	if (linetarget)
 	{
 		S_Sound (self, CHAN_WEAPON, "*fist", 1, ATTN_NORM);
-		self->angle = R_PointToAngle2 (self->x,
-										self->y,
-										linetarget->x,
-										linetarget->y);
+		self->angle = self->AngleTo(linetarget);
 	}
 }
 
@@ -218,8 +215,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Saw)
 	// turn to face target
 	if (!(Flags & SF_NOTURN))
 	{
-			angle = R_PointToAngle2(self->x, self->y,
-			linetarget->x, linetarget->y);
+		angle = self->AngleTo(linetarget);
 		if (angle - self->angle > ANG180)
 		{
 			if (angle - self->angle < (angle_t)(-ANG90 / 20))
diff --git a/src/g_doom/a_revenant.cpp b/src/g_doom/a_revenant.cpp
index 90c6e0a51..06fdfa6aa 100644
--- a/src/g_doom/a_revenant.cpp
+++ b/src/g_doom/a_revenant.cpp
@@ -77,7 +77,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Tracer)
 		return;
 	
 	// change angle 	
-	exact = R_PointToAngle2 (self->x, self->y, dest->x,  dest->y);
+	exact = self->AngleTo(dest);
 
 	if (exact != self->angle)
 	{
diff --git a/src/g_doom/a_scriptedmarine.cpp b/src/g_doom/a_scriptedmarine.cpp
index be39b545b..6e75d80e6 100644
--- a/src/g_doom/a_scriptedmarine.cpp
+++ b/src/g_doom/a_scriptedmarine.cpp
@@ -276,7 +276,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_M_Saw)
 		S_Sound (self, CHAN_WEAPON, hitsound, 1, ATTN_NORM);
 			
 		// turn to face target
-		angle = R_PointToAngle2 (self->x, self->y, linetarget->x, linetarget->y);
+		angle = self->AngleTo(linetarget);
 		if (angle - self->angle > ANG180)
 		{
 			if (angle - self->angle < (angle_t)(-ANG90/20))
@@ -326,7 +326,8 @@ static void MarinePunch(AActor *self, int damagemul)
 	if (linetarget)
 	{
 		S_Sound (self, CHAN_WEAPON, "*fist", 1, ATTN_NORM);
-		self->angle = R_PointToAngle2 (self->x, self->y, linetarget->x, linetarget->y);
+		self->angle = self->AngleTo(linetarget);
+
 	}
 }
 
diff --git a/src/g_heretic/a_chicken.cpp b/src/g_heretic/a_chicken.cpp
index 082774a3d..f4ad4c211 100644
--- a/src/g_heretic/a_chicken.cpp
+++ b/src/g_heretic/a_chicken.cpp
@@ -178,8 +178,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BeakAttackPL1)
 	P_LineAttack (player->mo, angle, MELEERANGE, slope, damage, NAME_Melee, "BeakPuff", true, &linetarget);
 	if (linetarget)
 	{
-		player->mo->angle = R_PointToAngle2 (player->mo->x,
-			player->mo->y, linetarget->x, linetarget->y);
+		player->mo->angle = player->mo->AngleTo(linetarget);
 	}
 	P_PlayPeck (player->mo);
 	player->chickenPeck = 12;
@@ -211,8 +210,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BeakAttackPL2)
 	P_LineAttack (player->mo, angle, MELEERANGE, slope, damage, NAME_Melee, "BeakPuff", true, &linetarget);
 	if (linetarget)
 	{
-		player->mo->angle = R_PointToAngle2 (player->mo->x,
-			player->mo->y, linetarget->x, linetarget->y);
+		player->mo->angle = player->mo->AngleTo(linetarget);
 	}
 	P_PlayPeck (player->mo);
 	player->chickenPeck = 12;
diff --git a/src/g_heretic/a_hereticweaps.cpp b/src/g_heretic/a_hereticweaps.cpp
index afc4f6007..711bbd960 100644
--- a/src/g_heretic/a_hereticweaps.cpp
+++ b/src/g_heretic/a_hereticweaps.cpp
@@ -90,8 +90,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_StaffAttack)
 	{
 		//S_StartSound(player->mo, sfx_stfhit);
 		// turn to face target
-		self->angle = R_PointToAngle2 (self->x,
-			self->y, linetarget->x, linetarget->y);
+		self->angle = self->AngleTo(linetarget);
 	}
 }
 
@@ -307,8 +306,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_GauntletAttack)
 		S_Sound (self, CHAN_AUTO, "weapons/gauntletshit", 1, ATTN_NORM);
 	}
 	// turn to face target
-	angle = R_PointToAngle2 (self->x, self->y,
-		linetarget->x, linetarget->y);
+	angle = self->AngleTo(linetarget);
 	if (angle-self->angle > ANG180)
 	{
 		if ((int)(angle-self->angle) < -ANG90/20)
@@ -648,8 +646,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_DeathBallImpact)
 			}
 			else
 			{ // Seek
-				angle = R_PointToAngle2(self->x, self->y,
-					target->x, target->y);
+				self->angle = self->AngleTo(target);
 				newAngle = true;
 			}
 		}
@@ -662,8 +659,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_DeathBallImpact)
 				if (linetarget && self->target != linetarget)
 				{
 					self->tracer = linetarget;
-					angle = R_PointToAngle2 (self->x, self->y,
-						linetarget->x, linetarget->y);
+					angle = self->AngleTo(linetarget);
 					newAngle = true;
 					break;
 				}
diff --git a/src/g_hexen/a_blastradius.cpp b/src/g_hexen/a_blastradius.cpp
index 53ce08b50..c7fb17fef 100644
--- a/src/g_hexen/a_blastradius.cpp
+++ b/src/g_hexen/a_blastradius.cpp
@@ -33,13 +33,13 @@ void BlastActor (AActor *victim, fixed_t strength, fixed_t speed, AActor * Owner
 		return;
 	}
 
-	angle = R_PointToAngle2 (Owner->x, Owner->y, victim->x, victim->y);
+	angle = Owner->AngleTo(victim);
 	angle >>= ANGLETOFINESHIFT;
 	victim->velx = FixedMul (speed, finecosine[angle]);
 	victim->vely = FixedMul (speed, finesine[angle]);
 
 	// Spawn blast puff
-	ang = R_PointToAngle2 (victim->x, victim->y, Owner->x, Owner->y);
+	ang = victim->AngleTo(Owner);
 	ang >>= ANGLETOFINESHIFT;
 	x = victim->x + FixedMul (victim->radius+FRACUNIT, finecosine[ang]);
 	y = victim->y + FixedMul (victim->radius+FRACUNIT, finesine[ang]);
diff --git a/src/g_hexen/a_clericholy.cpp b/src/g_hexen/a_clericholy.cpp
index 73ffeac88..39fee109d 100644
--- a/src/g_hexen/a_clericholy.cpp
+++ b/src/g_hexen/a_clericholy.cpp
@@ -262,8 +262,7 @@ static void CHolyTailFollow (AActor *actor, fixed_t dist)
 		child = actor->tracer;
 		if (child)
 		{
-			an = R_PointToAngle2(actor->x, actor->y, child->x, 
-				child->y)>>ANGLETOFINESHIFT;
+			an = actor->AngleTo(child) >> ANGLETOFINESHIFT;
 			oldDistance = child->AproxDistance (actor);
 			if (P_TryMove (child, actor->x+FixedMul(dist, finecosine[an]), 
 				actor->y+FixedMul(dist, finesine[an]), true))
diff --git a/src/g_hexen/a_clericstaff.cpp b/src/g_hexen/a_clericstaff.cpp
index b397fc12b..eeda968fa 100644
--- a/src/g_hexen/a_clericstaff.cpp
+++ b/src/g_hexen/a_clericstaff.cpp
@@ -73,7 +73,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CStaffCheck)
 			P_LineAttack (pmo, angle, fixed_t(1.5*MELEERANGE), slope, damage, NAME_Melee, PClass::FindClass ("CStaffPuff"), false, &linetarget);
 			if (linetarget != NULL)
 			{
-				pmo->angle = R_PointToAngle2 (pmo->x, pmo->y, linetarget->x, linetarget->y);
+				pmo->angle = pmo->AngleTo(linetarget);
 				if (((linetarget->player && (!linetarget->IsTeammate (pmo) || level.teamdamage != 0))|| linetarget->flags3&MF3_ISMONSTER)
 					&& (!(linetarget->flags2&(MF2_DORMANT|MF2_INVULNERABLE))))
 				{
@@ -103,7 +103,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CStaffCheck)
 			P_LineAttack (pmo, angle, fixed_t(1.5*MELEERANGE), slope, damage, NAME_Melee, PClass::FindClass ("CStaffPuff"), false, &linetarget);
 			if (linetarget != NULL)
 			{
-				pmo->angle = R_PointToAngle2 (pmo->x, pmo->y, linetarget->x, linetarget->y);
+				pmo->angle = pmo->AngleTo(linetarget);
 				if ((linetarget->player && (!linetarget->IsTeammate (pmo) || level.teamdamage != 0)) || linetarget->flags3&MF3_ISMONSTER)
 				{
 					newLife = player->health+(damage>>4);
diff --git a/src/g_hexen/a_dragon.cpp b/src/g_hexen/a_dragon.cpp
index 5b18c0d57..d33e7b07b 100644
--- a/src/g_hexen/a_dragon.cpp
+++ b/src/g_hexen/a_dragon.cpp
@@ -73,8 +73,7 @@ static void DragonSeek (AActor *actor, angle_t thresh, angle_t turnMax)
 	{ // attack the destination mobj if it's attackable
 		AActor *oldTarget;
 
-		if (absangle(actor->angle-R_PointToAngle2(actor->x, actor->y,
-			target->x, target->y)) < ANGLE_45/2)
+		if (absangle(actor->angle - actor->AngleTo(target)) < ANGLE_45/2)
 		{
 			oldTarget = actor->target;
 			actor->target = target;
@@ -99,8 +98,7 @@ static void DragonSeek (AActor *actor, angle_t thresh, angle_t turnMax)
 		{
 			AActor *bestActor = NULL;
 			bestAngle = ANGLE_MAX;
-			angleToTarget = R_PointToAngle2(actor->x, actor->y,
-				actor->target->x, actor->target->y);
+			angleToTarget = actor->AngleTo(actor->target);
 			for (i = 0; i < 5; i++)
 			{
 				if (!target->args[i])
@@ -113,8 +111,7 @@ static void DragonSeek (AActor *actor, angle_t thresh, angle_t turnMax)
 				{
 					continue;
 				}
-				angleToSpot = R_PointToAngle2(actor->x, actor->y, 
-					mo->x, mo->y);
+				angleToSpot = actor->AngleTo(mo);
 				if (absangle(angleToSpot-angleToTarget) < bestAngle)
 				{
 					bestAngle = absangle(angleToSpot-angleToTarget);
@@ -190,8 +187,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_DragonFlight)
 			self->target = NULL;
 			return;
 		}
-		angle = R_PointToAngle2(self->x, self->y, self->target->x,
-			self->target->y);
+		angle = self->AngleTo(self->target);
 		if (absangle(self->angle-angle) < ANGLE_45/2 && self->CheckMeleeRange())
 		{
 			int damage = pr_dragonflight.HitDice (8);
diff --git a/src/g_hexen/a_fighterplayer.cpp b/src/g_hexen/a_fighterplayer.cpp
index 5df183901..82cb8bd05 100644
--- a/src/g_hexen/a_fighterplayer.cpp
+++ b/src/g_hexen/a_fighterplayer.cpp
@@ -30,7 +30,7 @@ void AdjustPlayerAngle (AActor *pmo, AActor *linetarget)
 	angle_t angle;
 	int difference;
 
-	angle = R_PointToAngle2 (pmo->x, pmo->y, linetarget->x, linetarget->y);
+	angle = pmo->AngleTo(linetarget);
 	difference = (int)angle - (int)pmo->angle;
 	if (abs(difference) > MAX_ANGLE_ADJUST)
 	{
diff --git a/src/g_hexen/a_firedemon.cpp b/src/g_hexen/a_firedemon.cpp
index b1cfafc0c..c003dc21d 100644
--- a/src/g_hexen/a_firedemon.cpp
+++ b/src/g_hexen/a_firedemon.cpp
@@ -163,7 +163,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FiredChase)
 		{
 			if (pr_firedemonchase() < 30)
 			{
-				ang = R_PointToAngle2 (self->x, self->y, target->x, target->y);
+				ang = self->AngleTo(target);
 				if (pr_firedemonchase() < 128)
 					ang += ANGLE_90;
 				else
diff --git a/src/g_hexen/a_flies.cpp b/src/g_hexen/a_flies.cpp
index 3c677d5cb..683cbebe1 100644
--- a/src/g_hexen/a_flies.cpp
+++ b/src/g_hexen/a_flies.cpp
@@ -79,7 +79,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FlyBuzz)
 		return;
 	}
 
-	angle_t ang = R_PointToAngle2(self->x, self->y, targ->x, targ->y);
+	angle_t ang = self->AngleTo(targ);
 	self->angle = ang;
 	self->args[0]++;
 	ang >>= ANGLETOFINESHIFT;
diff --git a/src/g_hexen/a_hexenspecialdecs.cpp b/src/g_hexen/a_hexenspecialdecs.cpp
index 9d0c098fe..ad10a464c 100644
--- a/src/g_hexen/a_hexenspecialdecs.cpp
+++ b/src/g_hexen/a_hexenspecialdecs.cpp
@@ -109,8 +109,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_PotteryCheck)
 		if (playeringame[i])
 		{
 			AActor *pmo = players[i].mo;
-			if (P_CheckSight (self, pmo) && (absangle(R_PointToAngle2 (pmo->x,
-				pmo->y, self->x, self->y) - pmo->angle) <= ANGLE_45))
+			if (P_CheckSight (self, pmo) && (absangle(pmo->AngleTo(self) - pmo->angle) <= ANGLE_45))
 			{ // Previous state (pottery bit waiting state)
 				self->SetState (self->state - 1);
 				return;
diff --git a/src/g_hexen/a_korax.cpp b/src/g_hexen/a_korax.cpp
index ca849dd97..a941f1a65 100644
--- a/src/g_hexen/a_korax.cpp
+++ b/src/g_hexen/a_korax.cpp
@@ -485,7 +485,7 @@ AActor *P_SpawnKoraxMissile (fixed_t x, fixed_t y, fixed_t z,
 	z -= source->floorclip;
 	th = Spawn (type, x, y, z, ALLOW_REPLACE);
 	th->target = source; // Originator
-	an = R_PointToAngle2(x, y, dest->x, dest->y);
+	an = source->AngleXYTo(x, y, dest);
 	if (dest->flags & MF_SHADOW)
 	{ // Invisible target
 		an += pr_kmissile.Random2()<<21;
diff --git a/src/g_hexen/a_magelightning.cpp b/src/g_hexen/a_magelightning.cpp
index 9953cf1d0..a13e3a274 100644
--- a/src/g_hexen/a_magelightning.cpp
+++ b/src/g_hexen/a_magelightning.cpp
@@ -190,7 +190,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_LightningClip)
 		}
 		else
 		{
-			self->angle = R_PointToAngle2(self->x, self->y, target->x, target->y);
+			self->angle = self->AngleTo(target);
 			self->velx = 0;
 			self->vely = 0;
 			P_ThrustMobj (self, self->angle, self->Speed>>1);
diff --git a/src/g_raven/a_minotaur.cpp b/src/g_raven/a_minotaur.cpp
index c0095226e..c2348a9e3 100644
--- a/src/g_raven/a_minotaur.cpp
+++ b/src/g_raven/a_minotaur.cpp
@@ -390,7 +390,7 @@ void P_MinotaurSlam (AActor *source, AActor *target)
 	fixed_t thrust;
 	int damage;
 
-	angle = R_PointToAngle2 (source->x, source->y, target->x, target->y);
+	angle = source->AngleTo(target);
 	angle >>= ANGLETOFINESHIFT;
 	thrust = 16*FRACUNIT+(pr_minotaurslam()<<10);
 	target->velx += FixedMul (thrust, finecosine[angle]);
diff --git a/src/g_shared/sbar_mugshot.cpp b/src/g_shared/sbar_mugshot.cpp
index b8f419ef0..ea1c8528e 100644
--- a/src/g_shared/sbar_mugshot.cpp
+++ b/src/g_shared/sbar_mugshot.cpp
@@ -366,7 +366,7 @@ int FMugShot::UpdateState(player_t *player, StateFlags stateflags)
 				if (player->mo != NULL)
 				{
 					// The next 12 lines are from the Doom statusbar code.
-					badguyangle = R_PointToAngle2(player->mo->x, player->mo->y, player->attacker->x, player->attacker->y);
+					badguyangle = player->mo->AngleTo(player->attacker);
 					if (badguyangle > player->mo->angle)
 					{
 						// whether right or left
diff --git a/src/g_strife/a_strifeweapons.cpp b/src/g_strife/a_strifeweapons.cpp
index a41058492..f5d4a3576 100644
--- a/src/g_strife/a_strifeweapons.cpp
+++ b/src/g_strife/a_strifeweapons.cpp
@@ -118,10 +118,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_JabDagger)
 		S_Sound (self, CHAN_WEAPON,
 			linetarget->flags & MF_NOBLOOD ? "misc/metalhit" : "misc/meathit",
 			1, ATTN_NORM);
-		self->angle = R_PointToAngle2 (self->x,
-										self->y,
-										linetarget->x,
-										linetarget->y);
+		self->angle = self->AngleTo(linetarget);
 		self->flags |= MF_JUSTATTACKED;
 		P_DaggerAlert (self, linetarget);
 	}
diff --git a/src/p_conversation.cpp b/src/p_conversation.cpp
index 85edc53ab..db5fd400c 100644
--- a/src/p_conversation.cpp
+++ b/src/p_conversation.cpp
@@ -1117,7 +1117,7 @@ void P_StartConversation (AActor *npc, AActor *pc, bool facetalker, bool saveang
 	if (facetalker)
 	{
 		A_FaceTarget (npc);
-		pc->angle = R_PointToAngle2 (pc->x, pc->y, npc->x, npc->y);
+		pc->angle = pc->AngleTo(npc);
 	}
 	if ((npc->flags & MF_FRIENDLY) || (npc->flags4 & MF4_NOHATEPLAYERS))
 	{
diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp
index 489fb107d..7b7e27b2e 100644
--- a/src/p_enemy.cpp
+++ b/src/p_enemy.cpp
@@ -392,7 +392,7 @@ bool P_HitFriend(AActor * self)
 
 	if (self->flags&MF_FRIENDLY && self->target != NULL)
 	{
-		angle_t angle = R_PointToAngle2 (self->x, self->y, self->target->x, self->target->y);
+		angle_t angle = self->AngleTo(self->target);
 		fixed_t dist = self->AproxDistance (self->target);
 		P_AimLineAttack (self, angle, dist, &linetarget, 0, true);
 		if (linetarget != NULL && linetarget != self->target)
@@ -1160,7 +1160,7 @@ bool P_IsVisible(AActor *lookee, AActor *other, INTBOOL allaround, FLookExParams
 
 	if (fov && fov < ANGLE_MAX)
 	{
-		angle_t an = R_PointToAngle2 (lookee->x, lookee->y, other->x, other->y) - lookee->angle;
+		angle_t an = lookee->AngleTo(other) - lookee->angle;
 
 		if (an > (fov / 2) && an < (ANGLE_MAX - (fov / 2)))
 		{
@@ -2389,7 +2389,7 @@ void A_DoChase (AActor *actor, bool fastchase, FState *meleestate, FState *missi
 			{
 				if (pr_chase() < 100)
 				{
-					angle_t ang = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y);
+					angle_t ang = actor->AngleTo(actor->target);
 					if (pr_chase() < 128) ang += ANGLE_90;
 					else ang -= ANGLE_90;
 					actor->velx = 13 * finecosine[ang>>ANGLETOFINESHIFT];
@@ -2743,7 +2743,7 @@ void A_Face (AActor *self, AActor *other, angle_t max_turn, angle_t max_pitch, a
 
 	self->flags &= ~MF_AMBUSH;
 
-	angle_t other_angle = R_PointToAngle2 (self->x, self->y, other->x, other->y);
+	angle_t other_angle = self->AngleTo(other);
 
 	// 0 means no limit. Also, if we turn in a single step anyways, no need to go through the algorithms.
 	// It also means that there is no need to check for going past the other.
@@ -2916,10 +2916,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MonsterRail)
 
 	self->flags &= ~MF_AMBUSH;
 		
-	self->angle = R_PointToAngle2 (self->x,
-									self->y,
-									self->target->x,
-									self->target->y);
+	self->angle = self->AngleTo(self->target);
 
 	self->pitch = P_AimLineAttack (self, self->angle, MISSILERANGE, &linetarget, ANGLE_1*60, 0, self->target);
 	if (linetarget == NULL)
@@ -2932,10 +2929,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MonsterRail)
 	}
 
 	// Let the aim trail behind the player
-	self->angle = R_PointToAngle2 (self->x,
-									self->y,
-									self->target->x - self->target->velx * 3,
-									self->target->y - self->target->vely * 3);
+	self->angle = self->AngleTo(self->target, -self->target->velx * 3, -self->target->vely * 3);
 
 	if (self->target->flags & MF_SHADOW && !(self->flags6 & MF6_SEEINVISIBLE))
 	{
diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp
index b2e27adc8..240a77378 100644
--- a/src/p_interaction.cpp
+++ b/src/p_interaction.cpp
@@ -1164,7 +1164,7 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
 			}
 			else
 			{
-				ang = R_PointToAngle2 (origin->x, origin->y, target->x, target->y);
+				ang = origin->AngleTo(target);
 			}
 
 			// Calculate this as float to avoid overflows so that the
diff --git a/src/p_map.cpp b/src/p_map.cpp
index 58b4d2c1a..3381f763f 100644
--- a/src/p_map.cpp
+++ b/src/p_map.cpp
@@ -3066,7 +3066,7 @@ bool P_BounceActor(AActor *mo, AActor *BlockingMobj, bool ontop)
 		if (!ontop)
 		{
 			fixed_t speed;
-			angle_t angle = R_PointToAngle2(BlockingMobj->x,BlockingMobj->y, mo->x, mo->y) + ANGLE_1*((pr_bounce() % 16) - 8);
+			angle_t angle = BlockingMobj->AngleTo(mo) + ANGLE_1*((pr_bounce() % 16) - 8);
 			speed = P_AproxDistance(mo->velx, mo->vely);
 			speed = FixedMul(speed, mo->wallbouncefactor); // [GZ] was 0.75, using wallbouncefactor seems more consistent
 			mo->angle = angle;
@@ -4084,7 +4084,7 @@ void P_TraceBleed(int damage, AActor *target, AActor *missile)
 		pitch = 0;
 	}
 	P_TraceBleed(damage, target->x, target->y, target->z + target->height / 2,
-		target, R_PointToAngle2(missile->x, missile->y, target->x, target->y),
+		target, missile->AngleTo(target),
 		pitch);
 }
 
@@ -4853,7 +4853,7 @@ void P_RadiusAttack(AActor *bombspot, AActor *bombsource, int bombdamage, int bo
 								{
 									velz *= 0.8f;
 								}
-								angle_t ang = R_PointToAngle2(bombspot->x, bombspot->y, thing->x, thing->y) >> ANGLETOFINESHIFT;
+								angle_t ang = bombspot->AngleTo(thing) >> ANGLETOFINESHIFT;
 								thing->velx += fixed_t(finecosine[ang] * thrust);
 								thing->vely += fixed_t(finesine[ang] * thrust);
 								if (!(flags & RADF_NODAMAGE))
diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp
index 3eeb7c71a..750cc18fb 100644
--- a/src/p_mobj.cpp
+++ b/src/p_mobj.cpp
@@ -1556,7 +1556,7 @@ int P_FaceMobj (AActor *source, AActor *target, angle_t *delta)
 	angle_t angle2;
 
 	angle1 = source->angle;
-	angle2 = R_PointToAngle2 (source->x, source->y, target->x, target->y);
+	angle2 = source->AngleTo(target);
 	if (angle2 > angle1)
 	{
 		diff = angle2 - angle1;
@@ -2019,7 +2019,7 @@ fixed_t P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly)
 					// Don't change the angle if there's THRUREFLECT on the monster.
 					if (!(BlockingMobj->flags7 & MF7_THRUREFLECT))
 					{
-						angle = R_PointToAngle2(BlockingMobj->x, BlockingMobj->y, mo->x, mo->y);
+						angle = BlockingMobj->AngleTo(mo);
 						bool dontReflect = (mo->AdjustReflectionAngle(BlockingMobj, angle));
 						// Change angle for deflection/reflection
 
@@ -3088,8 +3088,7 @@ bool AActor::IsOkayToAttack (AActor *link)
 		// to only allow the check to succeed if the enemy was in a ~84� FOV of the player
 		if (flags3 & MF3_SCREENSEEKER)
 		{
-			angle_t angle = R_PointToAngle2(Friend->x, 
-				Friend->y, link->x, link->y) - Friend->angle;
+			angle_t angle = Friend->AngleTo(link) - Friend->angle;
 			angle >>= 24;
 			if (angle>226 || angle<30)
 			{
@@ -5035,7 +5034,7 @@ AActor *P_SpawnPuff (AActor *source, const PClass *pufftype, fixed_t x, fixed_t
 		puff->target = source;
 	
 
-	if (source != NULL) puff->angle = R_PointToAngle2(x, y, source->x, source->y);
+	if (source != NULL) puff->angle = puff->AngleTo(source);
 
 	// If a puff has a crash state and an actor was not hit,
 	// it will enter the crash state. This is used by the StrifeSpark
@@ -5782,7 +5781,7 @@ AActor * P_OldSpawnMissile(AActor * source, AActor * owner, AActor * dest, const
 	P_PlaySpawnSound(th, source);
 	th->target = owner;		// record missile's originator
 
-	th->angle = an = R_PointToAngle2 (source->x, source->y, dest->x, dest->y);
+	th->angle = an = source->AngleTo(dest);
 	an >>= ANGLETOFINESHIFT;
 	th->velx = FixedMul (th->Speed, finecosine[an]);
 	th->vely = FixedMul (th->Speed, finesine[an]);
diff --git a/src/p_spec.cpp b/src/p_spec.cpp
index b7bc9a7b0..698cf4f72 100644
--- a/src/p_spec.cpp
+++ b/src/p_spec.cpp
@@ -2233,7 +2233,7 @@ void DPusher::Tick ()
 
 				if ((speed > 0) && (P_CheckSight (thing, m_Source, SF_IGNOREVISIBILITY)))
 				{
-					angle_t pushangle = R_PointToAngle2 (thing->x, thing->y, sx, sy);
+					angle_t pushangle = thing->AngleTo(sx, sy);
 					if (m_Source->GetClass()->TypeName == NAME_PointPusher)
 						pushangle += ANG180;    // away
 					pushangle >>= ANGLETOFINESHIFT;
diff --git a/src/p_things.cpp b/src/p_things.cpp
index 7e38a3c68..631f1be5e 100644
--- a/src/p_things.cpp
+++ b/src/p_things.cpp
@@ -304,7 +304,8 @@ bool P_Thing_Projectile (int tid, AActor *source, int type, const char *type_nam
 						}
 						else
 						{
-nolead:						mobj->angle = R_PointToAngle2 (mobj->x, mobj->y, targ->x, targ->y);
+nolead:
+							mobj->angle = mobj->AngleTo(targ);
 							aim.Resize (fspeed);
 							mobj->velx = fixed_t(aim[0]);
 							mobj->vely = fixed_t(aim[1]);
diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp
index 864641b0d..b6575ee19 100644
--- a/src/thingdef/thingdef_codeptr.cpp
+++ b/src/thingdef/thingdef_codeptr.cpp
@@ -1487,10 +1487,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomPunch)
 		if (!(flags & CPF_NOTURN))
 		{
 			// turn to face target
-			self->angle = R_PointToAngle2 (self->x,
-											self->y,
-											linetarget->x,
-											linetarget->y);
+			self->angle = self->AngleTo(linetarget);
 		}
 
 		if (flags & CPF_PULLIN) self->flags |= MF_JUSTATTACKED;
@@ -1614,10 +1611,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomRailgun)
 
 	if (aim)
 	{
-		self->angle = R_PointToAngle2 (self->x,
-										self->y,
-										self->target->x,
-										self->target->y);
+		self->angle = self->AngleTo(self->target);
 	}
 	self->pitch = P_AimLineAttack (self, self->angle, MISSILERANGE, &linetarget, ANGLE_1*60, 0, aim ? self->target : NULL);
 	if (linetarget == NULL && aim)
@@ -1631,9 +1625,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomRailgun)
 	// Let the aim trail behind the player
 	if (aim)
 	{
-		saved_angle = self->angle = R_PointToAngle2 (self->x, self->y,
-										self->target->x - self->target->velx * 3,
-										self->target->y - self->target->vely * 3);
+		saved_angle = self->angle = self->AngleTo(self->target, -self->target->velx * 3, -self->target->vely * 3);
 
 		if (aim == CRF_AIMDIRECT)
 		{
@@ -1642,9 +1634,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomRailgun)
 			self->x += Spawnofs_XY * finecosine[self->angle];
 			self->y += Spawnofs_XY * finesine[self->angle];
 			Spawnofs_XY = 0;
-			self->angle = R_PointToAngle2 (self->x, self->y,
-											self->target->x - self->target->velx * 3,
-											self->target->y - self->target->vely * 3);
+			self->angle = self->AngleTo(self->target,- self->target->velx * 3, -self->target->vely * 3);
 		}
 
 		if (self->target->flags & MF_SHADOW)
@@ -3357,7 +3347,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckLOF)
 				{
 					ang = self->angle;
 				}
-				else ang = R_PointToAngle2 (x1, y1, target->x, target->y);
+				else ang = self->AngleTo (target);
 				
 				angle += ang;
 				
@@ -3576,11 +3566,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetInLOS)
 
 	if (fov && (fov < ANGLE_MAX))
 	{
-		an = R_PointToAngle2 (viewport->x,
-							  viewport->y,
-							  target->x,
-							  target->y)
-			- viewport->angle;
+		an = viewport->AngleTo(target) - viewport->angle;
 
 		if (an > (fov / 2) && an < (ANGLE_MAX - (fov / 2)))
 		{
@@ -3654,11 +3640,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfInTargetLOS)
 
 	if (fov && (fov < ANGLE_MAX))
 	{
-		an = R_PointToAngle2 (target->x,
-							  target->y,
-							  self->x,
-							  self->y)
-			- target->angle;
+		an = target->AngleTo(self) - target->angle;
 
 		if (an > (fov / 2) && an < (ANGLE_MAX - (fov / 2)))
 		{
@@ -4588,7 +4570,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_WolfAttack)
 
 
 	// Target can dodge if it can see enemy
-	angle_t angle = R_PointToAngle2(self->target->x, self->target->y, self->x, self->y) - self->target->angle;
+	angle_t angle = self->target->AngleTo(self) - self->target->angle;
 	angle >>= 24;
 	bool dodge = (P_CheckSight(self->target, self) && (angle>226 || angle<30));
 
@@ -4627,7 +4609,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_WolfAttack)
 		dx = self->target->x;
 		dy = self->target->y;
 		dz = self->target->z + (self->target->height>>1);
-		angle = R_PointToAngle2(dx, dy, self->x, self->y);
+		angle = self->target->AngleTo(self);
 		
 		dx += FixedMul(self->target->radius, finecosine[angle>>ANGLETOFINESHIFT]);
 		dy += FixedMul(self->target->radius, finesine[angle>>ANGLETOFINESHIFT]);
@@ -4662,7 +4644,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_WolfAttack)
 			if (spawnblood)
 			{
 				P_SpawnBlood(dx, dy, dz, angle, newdam > 0 ? newdam : damage, self->target);
-				P_TraceBleed(newdam > 0 ? newdam : damage, self->target, R_PointToAngle2(self->x, self->y, dx, dy), 0);
+				P_TraceBleed(newdam > 0 ? newdam : damage, self->target, self->AngleTo(dx, dy, self->target), 0);
 			}
 		}
 	}

From 918a2ed56231ecd7662a6fb46baea3e559877d10 Mon Sep 17 00:00:00 2001
From: Christoph Oelckers <c.oelckers@zdoom.fake>
Date: Sun, 10 Jan 2016 22:26:08 +0100
Subject: [PATCH 3/7] -fixed: Eternity-style skyboxes must check if some portal
 copy definitions have been set for them.

---
 src/g_shared/a_skies.cpp | 55 +++++++++++++++++++++++++++++++---------
 1 file changed, 43 insertions(+), 12 deletions(-)

diff --git a/src/g_shared/a_skies.cpp b/src/g_shared/a_skies.cpp
index 54661ea14..1915a260a 100644
--- a/src/g_shared/a_skies.cpp
+++ b/src/g_shared/a_skies.cpp
@@ -37,6 +37,7 @@
 #include "p_local.h"
 #include "p_lnspec.h"
 #include "farchive.h"
+#include "r_sky.h"
 
 // arg0 = Visibility*4 for this skybox
 
@@ -87,6 +88,24 @@ void ASkyViewpoint::Destroy ()
 class ASkyCamCompat : public ASkyViewpoint
 {
 	DECLARE_CLASS (ASkyCamCompat, ASkyViewpoint)
+
+	// skyboxify all tagged sectors
+	// This involves changing their texture to the sky flat, because while
+	// EE works with any texture for its skybox portals, ZDoom doesn't.
+	void SkyboxifySector(sector_t *sector, int plane)
+	{
+		// plane: 0=floor, 1=ceiling, 2=both
+		if (plane == 1 || plane == 2)
+		{
+			sector->CeilingSkyBox = this;
+			sector->SetTexture(sector_t::ceiling, skyflatnum, false);
+		}
+		if (plane == 0 || plane == 2)
+		{
+			sector->FloorSkyBox = this;
+			sector->SetTexture(sector_t::floor, skyflatnum, false);
+		}
+	}
 public:
 	void BeginPlay ();
 };
@@ -116,23 +135,35 @@ void ASkyCamCompat::BeginPlay ()
 				// Then, change the alpha
 				alpha = refline->args[4];
 
-				// Finally, skyboxify all tagged sectors
-				// This involves changing their texture to the sky flat, because while
-				// EE works with any texture for its skybox portals, ZDoom doesn't.
 				FSectorTagIterator it(skybox_id);
 				int secnum;
 				while ((secnum = it.Next()) >= 0)
 				{
-					// plane: 0=floor, 1=ceiling, 2=both
-					if (refline->args[2] == 1 || refline->args[2] == 2)
+					SkyboxifySector(&sectors[secnum], refline->args[2]);
+				}
+				// and finally, check for portal copy linedefs
+				for (int j=0;j<numlines;j++)
+				{
+					// Check if this portal needs to be copied to other sectors
+					// This must be done here to ensure that it gets done only after the portal is set up
+					if (lines[j].special == Sector_SetPortal &&
+						lines[j].args[1] == 1 &&
+						(lines[j].args[2] == refline->args[2] || lines[j].args[2] == 3) &&
+						lines[j].args[3] == skybox_id)
 					{
-						sectors[secnum].CeilingSkyBox = this;
-						sectors[secnum].SetTexture(sector_t::ceiling, skyflatnum, false);
-					}
-					if (refline->args[2] == 0 || refline->args[2] == 2)
-					{
-						sectors[secnum].FloorSkyBox = this;
-						sectors[secnum].SetTexture(sector_t::floor, skyflatnum, false);
+						if (lines[j].args[0] == 0)
+						{
+							SkyboxifySector(lines[j].frontsector, refline->args[2]);
+						}
+						else
+						{
+							FSectorTagIterator itr(lines[j].args[0]);
+							int s;
+							while ((s = itr.Next()) >= 0)
+							{
+								SkyboxifySector(&sectors[s], refline->args[2]);
+							}
+						}
 					}
 				}
 			}

From 4f0046105dd615eb88b1eab9f97b03acb5104b1f Mon Sep 17 00:00:00 2001
From: Randy Heit <rheit@users.noreply.github.com>
Date: Sun, 10 Jan 2016 21:09:16 -0600
Subject: [PATCH 4/7] Change texture atlas display to show allocated rectangles

---
 src/win32/fb_d3d9.cpp | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/src/win32/fb_d3d9.cpp b/src/win32/fb_d3d9.cpp
index 1641df365..474183086 100644
--- a/src/win32/fb_d3d9.cpp
+++ b/src/win32/fb_d3d9.cpp
@@ -1833,8 +1833,8 @@ void D3DFB::DrawPackedTextures(int packnum)
 {
 	D3DCOLOR empty_colors[8] =
 	{
-		0xFFFF9999, 0xFF99FF99, 0xFF9999FF, 0xFFFFFF99,
-		0xFFFF99FF, 0xFF99FFFF, 0xFFFFCC99, 0xFF99CCFF
+		0x80FF0000, 0x8000FF00, 0x800000FF, 0x80FFFF00,
+		0x80FF00FF, 0x8000FFFF, 0x80FF8000, 0x800080FF
 	};
 	Atlas *pack;
 	int x = 8, y = 8;
@@ -1869,7 +1869,14 @@ void D3DFB::DrawPackedTextures(int packnum)
 		}
 
 		AddColorOnlyRect(x-1, y-1-LBOffsetI, 258, 258, D3DCOLOR_XRGB(255,255,0));
-		AddColorOnlyQuad(x, y-LBOffsetI, 256, 256, D3DCOLOR_ARGB(180,0,0,0));
+		int back = 0;
+		for (PackedTexture *box = pack->UsedList; box != NULL; box = box->Next)
+		{
+			AddColorOnlyQuad(x + box->Area.left, y + box->Area.top,
+				box->Area.right - box->Area.left, box->Area.bottom - box->Area.top, empty_colors[back]);
+			back = (back + 1) & 7;
+		}
+//		AddColorOnlyQuad(x, y-LBOffsetI, 256, 256, D3DCOLOR_ARGB(180,0,0,0));
 
 		CheckQuadBatch();
 

From 670058fa3c1afb9afababec32afad204dbb7216f Mon Sep 17 00:00:00 2001
From: Randy Heit <rheit@users.noreply.github.com>
Date: Sun, 10 Jan 2016 21:54:28 -0600
Subject: [PATCH 5/7] Switch to the bottom-left picker for the Skyline Bin
 Packer

---
 src/SkylineBinPack.cpp | 69 +++++++++++++++++++++++++++++++++++++++++-
 src/SkylineBinPack.h   |  3 ++
 2 files changed, 71 insertions(+), 1 deletion(-)

diff --git a/src/SkylineBinPack.cpp b/src/SkylineBinPack.cpp
index 33f862043..4e9de153e 100644
--- a/src/SkylineBinPack.cpp
+++ b/src/SkylineBinPack.cpp
@@ -119,7 +119,7 @@ Rect SkylineBinPack::Insert(int width, int height)
 		return newNode;
 	}
 	
-	return InsertMinWaste(width, height);
+	return InsertBottomLeft(width, height);
 }
 
 bool SkylineBinPack::RectangleFits(int skylineNodeIndex, int width, int height, int &y) const
@@ -254,6 +254,73 @@ void SkylineBinPack::MergeSkylines()
 		}
 }
 
+Rect SkylineBinPack::InsertBottomLeft(int width, int height)
+{
+	int bestHeight;
+	int bestWidth;
+	int bestIndex;
+	Rect newNode = FindPositionForNewNodeBottomLeft(width, height, bestHeight, bestWidth, bestIndex);
+
+	if (bestIndex != -1)
+	{
+		assert(disjointRects.Disjoint(newNode));
+		// Perform the actual packing.
+		AddSkylineLevel(bestIndex, newNode);
+
+		usedSurfaceArea += width * height;
+#ifdef _DEBUG
+		disjointRects.Add(newNode);
+#endif
+	}
+	else
+		memset(&newNode, 0, sizeof(Rect));
+
+	return newNode;
+}
+
+Rect SkylineBinPack::FindPositionForNewNodeBottomLeft(int width, int height, int &bestHeight, int &bestWidth, int &bestIndex) const
+{
+	bestHeight = INT_MAX;
+	bestIndex = -1;
+	// Used to break ties if there are nodes at the same level. Then pick the narrowest one.
+	bestWidth = INT_MAX;
+	Rect newNode = { 0, 0, 0, 0 };
+	for(unsigned i = 0; i < skyLine.Size(); ++i)
+	{
+		int y;
+		if (RectangleFits(i, width, height, y))
+		{
+			if (y + height < bestHeight || (y + height == bestHeight && skyLine[i].width < bestWidth))
+			{
+				bestHeight = y + height;
+				bestIndex = i;
+				bestWidth = skyLine[i].width;
+				newNode.x = skyLine[i].x;
+				newNode.y = y;
+				newNode.width = width;
+				newNode.height = height;
+				assert(disjointRects.Disjoint(newNode));
+			}
+		}
+/*		if (RectangleFits(i, height, width, y))
+		{
+			if (y + width < bestHeight || (y + width == bestHeight && skyLine[i].width < bestWidth))
+			{
+				bestHeight = y + width;
+				bestIndex = i;
+				bestWidth = skyLine[i].width;
+				newNode.x = skyLine[i].x;
+				newNode.y = y;
+				newNode.width = height;
+				newNode.height = width;
+				assert(disjointRects.Disjoint(newNode));
+			}
+		}
+*/	}
+
+	return newNode;
+}
+
 Rect SkylineBinPack::InsertMinWaste(int width, int height)
 {
 	int bestHeight;
diff --git a/src/SkylineBinPack.h b/src/SkylineBinPack.h
index f93ddd29d..937c88de6 100644
--- a/src/SkylineBinPack.h
+++ b/src/SkylineBinPack.h
@@ -72,7 +72,10 @@ private:
 	bool useWasteMap;
 	GuillotineBinPack wasteMap;
 
+	Rect InsertBottomLeft(int width, int height);
 	Rect InsertMinWaste(int width, int height);
+
+	Rect FindPositionForNewNodeBottomLeft(int width, int height, int &bestHeight, int &bestWidth, int &bestIndex) const;
 	Rect FindPositionForNewNodeMinWaste(int width, int height, int &bestHeight, int &bestWastedArea, int &bestIndex) const;
 
 	bool RectangleFits(int skylineNodeIndex, int width, int height, int &y) const;

From aaac5ac7a122d7d0cae223964b0624ae3af3c02e Mon Sep 17 00:00:00 2001
From: Randy Heit <rheit@users.noreply.github.com>
Date: Sun, 10 Jan 2016 22:01:29 -0600
Subject: [PATCH 6/7] Use not so brilliant backgrounds for allocated atlas
 backgrounds

---
 src/win32/fb_d3d9.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/win32/fb_d3d9.cpp b/src/win32/fb_d3d9.cpp
index 474183086..bfb618b51 100644
--- a/src/win32/fb_d3d9.cpp
+++ b/src/win32/fb_d3d9.cpp
@@ -1833,8 +1833,8 @@ void D3DFB::DrawPackedTextures(int packnum)
 {
 	D3DCOLOR empty_colors[8] =
 	{
-		0x80FF0000, 0x8000FF00, 0x800000FF, 0x80FFFF00,
-		0x80FF00FF, 0x8000FFFF, 0x80FF8000, 0x800080FF
+		0x50FF0000, 0x5000FF00, 0x500000FF, 0x50FFFF00,
+		0x50FF00FF, 0x5000FFFF, 0x50FF8000, 0x500080FF
 	};
 	Atlas *pack;
 	int x = 8, y = 8;

From 42e9a6a711816bb2fce51166220cb7d8bc19f063 Mon Sep 17 00:00:00 2001
From: Randy Heit <rheit@users.noreply.github.com>
Date: Sun, 10 Jan 2016 22:14:35 -0600
Subject: [PATCH 7/7] Make atlas size a macro definition and default it to
 512x512 (was 256x256)

---
 src/win32/fb_d3d9.cpp | 17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/src/win32/fb_d3d9.cpp b/src/win32/fb_d3d9.cpp
index bfb618b51..4e3a14c18 100644
--- a/src/win32/fb_d3d9.cpp
+++ b/src/win32/fb_d3d9.cpp
@@ -85,6 +85,10 @@
 // The number of quads we can batch together.
 #define MAX_QUAD_BATCH	(NUM_INDEXES / 6)
 
+// The default size for a texture atlas.
+#define DEF_ATLAS_WIDTH		512
+#define DEF_ATLAS_HEIGHT	512
+
 // TYPES -------------------------------------------------------------------
 
 IMPLEMENT_CLASS(D3DFB)
@@ -1872,8 +1876,11 @@ void D3DFB::DrawPackedTextures(int packnum)
 		int back = 0;
 		for (PackedTexture *box = pack->UsedList; box != NULL; box = box->Next)
 		{
-			AddColorOnlyQuad(x + box->Area.left, y + box->Area.top,
-				box->Area.right - box->Area.left, box->Area.bottom - box->Area.top, empty_colors[back]);
+			AddColorOnlyQuad(
+				x + box->Area.left * 256 / pack->Width,
+				y + box->Area.top * 256 / pack->Height,
+				(box->Area.right - box->Area.left) * 256 / pack->Width,
+				(box->Area.bottom - box->Area.top) * 256 / pack->Height, empty_colors[back]);
 			back = (back + 1) & 7;
 		}
 //		AddColorOnlyQuad(x, y-LBOffsetI, 256, 256, D3DCOLOR_ARGB(180,0,0,0));
@@ -1980,8 +1987,8 @@ D3DFB::PackedTexture *D3DFB::AllocPackedTexture(int w, int h, bool wrapping, D3D
 	Rect box;
 	bool padded;
 
-	// check for 254 to account for padding
-	if (w > 254 || h > 254 || wrapping)
+	// The - 2 to account for padding
+	if (w > 256 - 2 || h > 256 - 2 || wrapping)
 	{ // Create a new texture atlas.
 		pack = new Atlas(this, w, h, format);
 		pack->OneUse = true;
@@ -2006,7 +2013,7 @@ D3DFB::PackedTexture *D3DFB::AllocPackedTexture(int w, int h, bool wrapping, D3D
 		}
 		if (pack == NULL)
 		{ // Create a new texture atlas.
-			pack = new Atlas(this, 256, 256, format);
+			pack = new Atlas(this, DEF_ATLAS_WIDTH, DEF_ATLAS_HEIGHT, format);
 			box = pack->Packer.Insert(w, h);
 		}
 		padded = true;