Merge branch 'master' of c:\programming\doom-dev\zdoom

# Conflicts:
#	.gitignore
This commit is contained in:
Christoph Oelckers 2016-02-16 21:02:13 +01:00
commit 56202c49f1
84 changed files with 1246 additions and 588 deletions

3
.gitignore vendored
View file

@ -43,4 +43,5 @@
/zlib/x64/
/build_vc2013_64bit
/build_vc2015
build_cmake
/build_vc2015-32
/build_vc2015-64

View file

@ -899,11 +899,13 @@ set( NOT_COMPILED_SOURCE_FILES
g_strife/a_crusader.cpp
g_strife/a_entityboss.cpp
g_strife/a_inquisitor.cpp
g_strife/a_loremaster.cpp
g_strife/a_oracle.cpp
g_strife/a_programmer.cpp
g_strife/a_reaver.cpp
g_strife/a_rebels.cpp
g_strife/a_sentinel.cpp
g_strife/a_spectral.cpp
g_strife/a_stalker.cpp
g_strife/a_strifeitems.cpp
g_strife/a_strifeweapons.cpp

View file

@ -43,6 +43,8 @@
struct subsector_t;
class PClassAmmo;
struct FBlockNode;
struct FPortalGroupArray;
//
// NOTES: AActor
@ -530,21 +532,6 @@ enum EThingSpecialActivationType
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;
@ -569,16 +556,6 @@ struct line_t;
struct secplane_t;
struct FStrifeDialogueNode;
struct fixedvec3
{
fixed_t x, y, z;
};
struct fixedvec2
{
fixed_t x, y;
};
class DDropItem : public DObject
{
DECLARE_CLASS(DDropItem, DObject)
@ -1155,11 +1132,10 @@ private:
friend class FActorIterator;
friend bool P_IsTIDUsed(int tid);
sector_t *LinkToWorldForMapThing ();
bool FixMapthingPos();
public:
void LinkToWorld (bool buggy=false);
void LinkToWorld (sector_t *sector);
void LinkToWorld (bool spawningmapthing=false, FPortalGroupArray *groups = NULL, sector_t *sector = NULL);
void UnlinkFromWorld ();
void AdjustFloorClip ();
virtual void SetOrigin (fixed_t x, fixed_t y, fixed_t z, bool moving = false);
@ -1415,6 +1391,7 @@ inline fixedvec3 PosRelative(const fixedvec3 &pos, line_t *line, sector_t *refse
}
void PrintMiscActorInfo(AActor * query);
AActor *P_LinePickActor(AActor *t1, angle_t angle, fixed_t distance, int pitch, ActorFlags actorMask, DWORD wallMask);
#define S_FREETARGMOBJ 1

View file

@ -42,6 +42,8 @@
#include "r_renderer.h"
#include "r_sky.h"
#include "sbar.h"
#include "d_player.h"
#include "p_blockmap.h"
#include "m_cheat.h"
#include "i_system.h"
@ -58,6 +60,7 @@
// State.
#include "doomstat.h"
#include "r_state.h"
#include "r_utility.h"
// Data.
#include "gstrings.h"

View file

@ -13,6 +13,7 @@
#include "teaminfo.h"
#include "d_net.h"
#include "farchive.h"
#include "d_player.h"
IMPLEMENT_POINTY_CLASS(DBot)
DECLARE_POINTER(dest)

View file

@ -11,6 +11,7 @@
#include "doomdef.h"
#include "doomstat.h"
#include "p_local.h"
#include "p_maputl.h"
#include "b_bot.h"
#include "g_game.h"
#include "m_random.h"
@ -20,6 +21,9 @@
#include "i_system.h"
#include "s_sound.h"
#include "d_event.h"
#include "d_player.h"
#include "p_spec.h"
#include "p_checkposition.h"
static FRandom pr_botdofire ("BotDoFire");

View file

@ -59,6 +59,7 @@ Everything that is changed is marked (maybe commented) with "Added by MC"
#include "i_system.h"
#include "d_net.h"
#include "d_netinf.h"
#include "d_player.h"
static FRandom pr_botspawn ("BotSpawn");

View file

@ -18,6 +18,9 @@
#include "a_keys.h"
#include "d_event.h"
#include "p_enemy.h"
#include "d_player.h"
#include "p_spec.h"
#include "p_checkposition.h"
static FRandom pr_botopendoor ("BotOpenDoor");
static FRandom pr_bottrywalk ("BotTryWalk");

View file

@ -19,6 +19,7 @@
#include "statnums.h"
#include "d_net.h"
#include "d_event.h"
#include "d_player.h"
static FRandom pr_botmove ("BotMove");

View file

@ -81,6 +81,17 @@ union QWORD_UNION
typedef SDWORD fixed_t;
typedef DWORD dsfixed_t; // fixedpt used by span drawer
struct fixedvec3
{
fixed_t x, y, z;
};
struct fixedvec2
{
fixed_t x, y;
};
#define FIXED_MAX (signed)(0x7fffffff)
#define FIXED_MIN (signed)(0x80000000)

View file

@ -69,6 +69,8 @@
#include "v_text.h"
#include "p_lnspec.h"
#include "v_video.h"
#include "r_utility.h"
#include "r_data/r_interpolate.h"
extern FILE *Logfile;
extern bool insave;

View file

@ -60,6 +60,7 @@
#include "v_video.h"
#include "p_spec.h"
#include "hardware.h"
#include "r_utility.h"
#include "intermission/intermission.h"
EXTERN_CVAR (Int, disableautosave)

View file

@ -73,6 +73,8 @@
#include "po_man.h"
#include "autosegs.h"
#include "v_video.h"
#include "textures.h"
#include "r_utility.h"
#include "menu/menu.h"
#include "intermission/intermission.h"

View file

@ -197,6 +197,41 @@ struct PalEntry
#endif
};
class FArchive;
class PClassInventory;
class FTextureID
{
friend class FTextureManager;
friend FArchive &operator<< (FArchive &arc, FTextureID &tex);
friend FTextureID GetHUDIcon(PClassInventory *cls);
friend void R_InitSpriteDefs();
public:
FTextureID() throw() {}
bool isNull() const { return texnum == 0; }
bool isValid() const { return texnum > 0; }
bool Exists() const { return texnum >= 0; }
void SetInvalid() { texnum = -1; }
void SetNull() { texnum = 0; }
bool operator ==(const FTextureID &other) const { return texnum == other.texnum; }
bool operator !=(const FTextureID &other) const { return texnum != other.texnum; }
FTextureID operator +(int offset) throw();
int GetIndex() const { return texnum; } // Use this only if you absolutely need the index!
// The switch list needs these to sort the switches by texture index
int operator -(FTextureID other) const { return texnum - other.texnum; }
bool operator < (FTextureID other) const { return texnum < other.texnum; }
bool operator > (FTextureID other) const { return texnum > other.texnum; }
protected:
FTextureID(int num) { texnum = num; }
private:
int texnum;
};
// Screenshot buffer image data types
enum ESSType
{

View file

@ -29,6 +29,7 @@
#include "r_data/r_interpolate.h"
#include "statnums.h"
#include "farchive.h"
#include "doomstat.h"
IMPLEMENT_CLASS (DSectorEffect)

View file

@ -39,6 +39,7 @@
#include "i_system.h"
#include "doomerrors.h"
#include "farchive.h"
#include "d_player.h"
static cycle_t ThinkCycles;

View file

@ -47,6 +47,7 @@
#include "sc_man.h"
#include "g_level.h"
#include "r_renderer.h"
#include "d_player.h"
//==========================================================================
//

View file

@ -68,6 +68,7 @@
#include "r_data/colormaps.h"
#include "farchive.h"
#include "p_setup.h"
#include "p_spec.h"
static FRandom pr_script("FScript");

View file

@ -1,6 +1,7 @@
#include "actor.h"
#include "info.h"
#include "p_local.h"
#include "p_spec.h"
#include "a_sharedglobal.h"
#include "m_random.h"
#include "gi.h"
@ -15,6 +16,9 @@
#include "m_bbox.h"
#include "farchive.h"
#include "portal.h"
#include "d_player.h"
#include "p_maputl.h"
#include "g_shared/a_pickups.h"
// Include all the other Doom stuff here to reduce compile time
#include "a_arachnotron.cpp"

View file

@ -80,6 +80,9 @@
#include "m_joy.h"
#include "farchive.h"
#include "r_renderer.h"
#include "r_utility.h"
#include "a_morph.h"
#include "p_spec.h"
#include "r_data/colormaps.h"
#include <zlib.h>

View file

@ -15,6 +15,8 @@
#include "r_data/r_translate.h"
#include "doomstat.h"
#include "farchive.h"
#include "d_player.h"
#include "a_morph.h"
// Include all the other Heretic stuff here to reduce compile time
#include "a_chicken.cpp"

View file

@ -1077,12 +1077,17 @@ DEFINE_ACTION_FUNCTION(AActor, A_SkullRodStorm)
mo = Spawn<ARainPillar> (pos.x, pos.y, ONCEILINGZ, ALLOW_REPLACE);
// We used bouncecount to store the 3D floor index in A_HideInCeiling
if (!mo) return 0;
if (mo->Sector->PortalGroup != self->Sector->PortalGroup)
{
// spawning this through a portal will never work right so abort right away.
mo->Destroy();
return 0;
}
fixed_t newz;
if (self->bouncecount >= 0
&& (unsigned)self->bouncecount < self->Sector->e->XFloor.ffloors.Size())
newz = self->Sector->e->XFloor.ffloors[self->bouncecount]->bottom.plane->ZatPoint(pos.x, pos.y);// - 40 * FRACUNIT;
if (self->bouncecount >= 0 && (unsigned)self->bouncecount < self->Sector->e->XFloor.ffloors.Size())
newz = self->Sector->e->XFloor.ffloors[self->bouncecount]->bottom.plane->ZatPoint(mo);// - 40 * FRACUNIT;
else
newz = self->Sector->ceilingplane.ZatPoint(pos.x, pos.y);
newz = self->Sector->ceilingplane.ZatPoint(mo);
int moceiling = P_Find3DFloor(NULL, pos.x, pos.y, newz, false, false, newz);
if (moceiling >= 0)
mo->SetZ(newz - mo->height, false);

View file

@ -20,6 +20,10 @@
#include "farchive.h"
#include "v_palette.h"
#include "g_game.h"
#include "p_blockmap.h"
#include "r_utility.h"
#include "p_maputl.h"
#include "p_spec.h"
// Include all the Hexen stuff here to reduce compile time
#include "a_bats.cpp"

View file

@ -83,6 +83,8 @@
#include "r_data/colormaps.h"
#include "farchive.h"
#include "r_renderer.h"
#include "r_utility.h"
#include "p_spec.h"
#include "gi.h"

View file

@ -3,11 +3,14 @@
#include "a_artifacts.h"
#include "gstrings.h"
#include "p_local.h"
#include "p_spec.h"
#include "gi.h"
#include "s_sound.h"
#include "m_random.h"
#include "doomstat.h"
#include "g_game.h"
#include "d_player.h"
#include "a_morph.h"
static FRandom pr_tele ("TeleportSelf");

View file

@ -12,6 +12,8 @@
#include "g_level.h"
#include "doomstat.h"
#include "farchive.h"
#include "a_pickups.h"
#include "d_player.h"
#define MAULATORTICS (25*35)

View file

@ -20,6 +20,8 @@
#include "doomstat.h"
#include "v_palette.h"
#include "farchive.h"
#include "r_utility.h"
#include "r_data/colormaps.h"
static FRandom pr_torch ("Torch");

View file

@ -45,6 +45,7 @@
#include "colormatcher.h"
#include "v_palette.h"
#include "farchive.h"
#include "doomdata.h"
static fixed_t DecalWidth, DecalLeft, DecalRight;
static fixed_t SpreadZ;

View file

@ -4,6 +4,8 @@
#include "g_level.h"
#include "r_sky.h"
#include "p_lnspec.h"
#include "b_bot.h"
#include "p_checkposition.h"
IMPLEMENT_CLASS(AFastProjectile)

View file

@ -13,6 +13,7 @@
#include "g_level.h"
#include "farchive.h"
#include "p_enemy.h"
#include "d_player.h"
static FRandom pr_morphmonst ("MorphMonster");

View file

@ -19,6 +19,8 @@
#include "g_game.h"
#include "doomstat.h"
#include "farchive.h"
#include "d_player.h"
#include "p_spec.h"
static FRandom pr_restore ("RestorePos");

View file

@ -9,6 +9,8 @@
#include "a_sharedglobal.h"
#include "statnums.h"
#include "farchive.h"
#include "d_player.h"
#include "r_utility.h"
static FRandom pr_quake ("Quake");

View file

@ -16,6 +16,8 @@
#include "a_action.h"
#include "thingdef/thingdef.h"
#include "v_text.h"
#include "doomstat.h"
#include "doomdata.h"
#define MAX_RANDOMSPAWNERS_RECURSION 32 // Should be largely more than enough, honestly.
static FRandom pr_randomspawn("RandomSpawn");

View file

@ -40,6 +40,7 @@
#include "thingdef/thingdef.h"
#include "doomstat.h"
#include "farchive.h"
#include "a_pickups.h"
static FRandom pr_spot ("SpecialSpot");
static FRandom pr_spawnmace ("SpawnMace");

View file

@ -50,6 +50,8 @@
#include "doomstat.h"
#include "g_level.h"
#include "d_net.h"
#include "d_player.h"
#include "r_utility.h"
#include <time.h>

View file

@ -19,6 +19,7 @@
#include "d_event.h"
#include "v_font.h"
#include "farchive.h"
#include "p_spec.h"
// Include all the other Strife stuff here to reduce compile time
#include "a_acolyte.cpp"

View file

@ -35,6 +35,7 @@
*/
#include "doomstat.h"
#include "info.h"
#include "m_fixed.h"
#include "c_dispatch.h"
@ -51,6 +52,8 @@
#include "cmdlib.h"
#include "g_level.h"
#include "stats.h"
#include "thingdef.h"
#include "d_player.h"
extern void LoadActors ();
extern void InitBotStuff();

View file

@ -26,6 +26,7 @@
#include "m_bbox.h"
#include "p_local.h"
#include "p_maputl.h"
//==========================================================================
//

View file

@ -46,6 +46,8 @@
#include "d_dehacked.h"
#include "gi.h"
#include "farchive.h"
#include "r_utility.h"
#include "a_morph.h"
// [RH] Actually handle the cheat. The cheat code in st_stuff.c now just
// writes some bytes to the network data stream, and the network code

View file

@ -38,10 +38,14 @@
#include "templates.h"
#include "p_local.h"
#include "p_lnspec.h"
#include "p_maputl.h"
#include "w_wad.h"
#include "sc_man.h"
#include "g_level.h"
#include "p_terrain.h"
#include "d_player.h"
#include "r_utility.h"
#include "p_spec.h"
#include "r_data/colormaps.h"
EXTERN_CVAR(Int, vid_renderer)

View file

@ -38,6 +38,8 @@
#include "templates.h"
#include "p_local.h"
#include "p_terrain.h"
#include "p_maputl.h"
#include "p_spec.h"
//============================================================================

View file

@ -40,6 +40,7 @@
#include "templates.h"
#include "doomdef.h"
#include "p_local.h"
#include "d_player.h"
#include "p_spec.h"
#include "g_level.h"
#include "s_sound.h"
@ -79,6 +80,8 @@
#include "p_terrain.h"
#include "version.h"
#include "p_effect.h"
#include "r_utility.h"
#include "a_morph.h"
#include "g_shared/a_pickups.h"

34
src/p_blockmap.h Normal file
View file

@ -0,0 +1,34 @@
#ifndef __P_BLOCKMAP_H
#define __P_BLOCKMAP_H
#include "doomtype.h"
class AActor;
// [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
int Group; // portal group this link belongs to (can be different than the actor's own group
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, int group = -1);
void Release ();
static FBlockNode *FreeBlocks;
};
extern int* blockmaplump; // offsets in blockmap are from here
extern int* blockmap;
extern int bmapwidth;
extern int bmapheight; // in mapblocks
extern fixed_t bmaporgx;
extern fixed_t bmaporgy; // origin of block map
extern FBlockNode** blocklinks; // for thing chains
#endif

View file

@ -18,6 +18,7 @@
#include "r_data/colormaps.h"
#include "gi.h"
#include "portal.h"
#include "p_spec.h"
// MACROS ------------------------------------------------------------------

View file

@ -30,6 +30,7 @@
#include "r_state.h"
#include "gi.h"
#include "farchive.h"
#include "p_spec.h"
//============================================================================
//

110
src/p_checkposition.h Normal file
View file

@ -0,0 +1,110 @@
#ifndef P_CHECKPOS_H
#define P_CHECKPOS_H
//============================================================================
//
// This is a dynamic array which holds its first MAX_STATIC entries in normal
// variables to avoid constant allocations which this would otherwise
// require.
//
// When collecting touched portal groups the normal cases are either
// no portals == one group or
// two portals = two groups
//
// Anything with more can happen but far less infrequently, so this
// organization helps avoiding the overhead from heap allocations
// in the vast majority of situations.
//
//============================================================================
struct FPortalGroupArray
{
enum
{
MAX_STATIC = 2
};
FPortalGroupArray()
{
varused = 0;
}
void Clear()
{
data.Clear();
varused = 0;
}
void Add(DWORD num)
{
if (varused < MAX_STATIC) entry[varused++] = num;
else data.Push(num);
}
unsigned Size()
{
return varused + data.Size();
}
DWORD operator[](unsigned index)
{
return index < MAX_STATIC ? entry[index] : data[index - MAX_STATIC];
}
private:
DWORD entry[MAX_STATIC];
unsigned varused;
TArray<DWORD> data;
};
//============================================================================
//
// Used by P_CheckPosition and P_TryMove in place of the original
// set of global variables.
//
//============================================================================
struct FCheckPosition
{
// in
AActor *thing;
fixed_t x;
fixed_t y;
fixed_t z;
// out
sector_t *sector;
fixed_t floorz;
fixed_t ceilingz;
fixed_t dropoffz;
FTextureID floorpic;
int floorterrain;
sector_t *floorsector;
FTextureID ceilingpic;
sector_t *ceilingsector;
bool touchmidtex;
bool abovemidtex;
bool floatok;
bool FromPMove;
line_t *ceilingline;
AActor *stepthing;
// [RH] These are used by PIT_CheckThing and P_XYMovement to apply
// ripping damage once per tic instead of once per move.
bool DoRipping;
TMap<AActor*, bool> LastRipped;
FPortalGroupArray Groups;
int PushTime;
FCheckPosition(bool rip=false)
{
DoRipping = rip;
PushTime = 0;
FromPMove = false;
}
};
#endif

View file

@ -36,6 +36,8 @@
#include "sc_man.h"
#include "cmdlib.h"
#include "farchive.h"
#include "d_player.h"
#include "p_spec.h"
//============================================================================
//

View file

@ -51,6 +51,8 @@
#include "gi.h"
#include "v_palette.h"
#include "colormatcher.h"
#include "d_player.h"
#include "r_utility.h"
CVAR (Int, cl_rockettrails, 1, CVAR_ARCHIVE);
CVAR (Bool, r_rail_smartspiral, 0, CVAR_ARCHIVE);

View file

@ -31,6 +31,8 @@
#include "i_system.h"
#include "doomdef.h"
#include "p_local.h"
#include "p_maputl.h"
#include "d_player.h"
#include "m_bbox.h"
#include "p_lnspec.h"
#include "s_sound.h"
@ -44,8 +46,12 @@
#include "thingdef/thingdef.h"
#include "d_dehacked.h"
#include "g_level.h"
#include "r_utility.h"
#include "p_blockmap.h"
#include "r_data/r_translate.h"
#include "teaminfo.h"
#include "p_spec.h"
#include "p_checkposition.h"
#include "gi.h"

View file

@ -31,6 +31,7 @@
#include "tables.h"
#include "farchive.h"
#include "p_3dmidtex.h"
#include "p_spec.h"
#include "r_data/r_interpolate.h"
//==========================================================================
@ -411,8 +412,8 @@ bool EV_DoFloor (DFloor::EFloor floortype, line_t *line, int tag,
case DFloor::floorLowerByTexture:
floor->m_Direction = -1;
newheight = sec->floorplane.ZatPoint (0, 0) - sec->FindShortestTextureAround ();
floor->m_FloorDestDist = sec->floorplane.PointToDist (0, 0, newheight);
newheight = sec->floorplane.ZatPoint (sec->soundorg[0], sec->soundorg[1]) - sec->FindShortestTextureAround ();
floor->m_FloorDestDist = sec->floorplane.PointToDist (sec->soundorg[0], sec->soundorg[1], newheight);
break;
case DFloor::floorLowerToCeiling:
@ -428,14 +429,14 @@ bool EV_DoFloor (DFloor::EFloor floortype, line_t *line, int tag,
// since the code is identical to what was here. (Oddly
// enough, BOOM preserved the code here even though it
// also had this function.)
newheight = sec->floorplane.ZatPoint (0, 0) + sec->FindShortestTextureAround ();
floor->m_FloorDestDist = sec->floorplane.PointToDist (0, 0, newheight);
newheight = sec->floorplane.ZatPoint (sec->soundorg[0], sec->soundorg[1]) + sec->FindShortestTextureAround ();
floor->m_FloorDestDist = sec->floorplane.PointToDist (sec->soundorg[0], sec->soundorg[1], newheight);
break;
case DFloor::floorRaiseAndChange:
floor->m_Direction = 1;
newheight = sec->floorplane.ZatPoint (0, 0) + height;
floor->m_FloorDestDist = sec->floorplane.PointToDist (0, 0, newheight);
newheight = sec->floorplane.ZatPoint (sec->soundorg[0], sec->soundorg[1]) + height;
floor->m_FloorDestDist = sec->floorplane.PointToDist (sec->soundorg[0], sec->soundorg[1], newheight);
if (line != NULL)
{
FTextureID oldpic = sec->GetTexture(sector_t::floor);
@ -618,8 +619,8 @@ bool EV_BuildStairs (int tag, DFloor::EStair type, line_t *line,
floor->m_Hexencrush = false;
floor->m_Speed = speed;
height = sec->floorplane.ZatPoint (0, 0) + stairstep;
floor->m_FloorDestDist = sec->floorplane.PointToDist (0, 0, height);
height = sec->floorplane.ZatPoint (sec->soundorg[0], sec->soundorg[1]) + stairstep;
floor->m_FloorDestDist = sec->floorplane.PointToDist (sec->soundorg[0], sec->soundorg[1], height);
texture = sec->GetTexture(sector_t::floor);
osecnum = secnum; //jff 3/4/98 preserve loop index

View file

@ -65,6 +65,8 @@
#include "version.h"
#include "md5.h"
#include "m_misc.h"
#include "r_utility.h"
#include "cmdlib.h"
void P_GetPolySpots (MapData * lump, TArray<FNodeBuilder::FPolyStart> &spots, TArray<FNodeBuilder::FPolyStart> &anchors);

View file

@ -58,6 +58,7 @@
#include "g_level.h"
#include "d_net.h"
#include "d_netinf.h"
#include "a_morph.h"
static FRandom pr_obituary ("Obituary");
static FRandom pr_botrespawn ("BotRespawn");

View file

@ -27,8 +27,10 @@
#include "doomdef.h"
#include "p_local.h"
#include "p_spec.h"
#include "p_lnspec.h"
#include "doomstat.h"
// State.
#include "r_state.h"

View file

@ -36,6 +36,7 @@
#include "templates.h"
#include "p_local.h"
#include "p_lnspec.h"
#include "p_spec.h"
enum
{

View file

@ -58,8 +58,12 @@
#include "d_event.h"
#include "gstrings.h"
#include "portal.h"
#include "po_man.h"
#include "d_player.h"
#include "r_utility.h"
#include "r_data/colormaps.h"
#include "fragglescript/t_fs.h"
#include "p_spec.h"
// Remaps EE sector change types to Generic_Floor values. According to the Eternity Wiki:
/*

View file

@ -24,13 +24,19 @@
#define __P_LOCAL__
#include "doomtype.h"
#include "doomdef.h"
#include "tables.h"
#include "r_state.h"
#include "r_utility.h"
#include "d_player.h"
#include "a_morph.h"
class player_t;
class AActor;
struct FPlayerStart;
class PClassActor;
struct fixedvec3;
class APlayerPawn;
struct line_t;
struct sector_t;
struct msecnode_t;
struct secplane_t;
struct FCheckPosition;
#include <stdlib.h>
@ -119,7 +125,7 @@ void P_PredictionLerpReset();
#define SPF_TEMPPLAYER 1 // spawning a short-lived dummy player
#define SPF_WEAPONFULLYUP 2 // spawn with weapon already raised
APlayerPawn *P_SpawnPlayer (struct FPlayerStart *mthing, int playernum, int flags=0);
APlayerPawn *P_SpawnPlayer (FPlayerStart *mthing, int playernum, int flags=0);
void P_ThrustMobj (AActor *mo, angle_t angle, fixed_t move);
int P_FaceMobj (AActor *source, AActor *target, angle_t *delta);
@ -221,200 +227,6 @@ enum WARPF
//
// P_MAPUTL
//
struct divline_t
{
fixed_t x;
fixed_t y;
fixed_t dx;
fixed_t dy;
};
struct intercept_t
{
fixed_t frac; // along trace line
bool isaline;
bool done;
union {
AActor *thing;
line_t *line;
} d;
};
typedef bool (*traverser_t) (intercept_t *in);
fixed_t P_AproxDistance (fixed_t dx, fixed_t dy);
//==========================================================================
//
// P_PointOnLineSide
//
// Returns 0 (front/on) or 1 (back)
// [RH] inlined, stripped down, and made more precise
//
//==========================================================================
inline int P_PointOnLineSide (fixed_t x, fixed_t y, const line_t *line)
{
extern int P_VanillaPointOnLineSide(fixed_t x, fixed_t y, const line_t* line);
return i_compatflags2 & COMPATF2_POINTONLINE
? P_VanillaPointOnLineSide(x, y, line)
: DMulScale32 (y-line->v1->y, line->dx, line->v1->x-x, line->dy) > 0;
}
inline int P_PointOnLineSidePrecise (fixed_t x, fixed_t y, const line_t *line)
{
return DMulScale32 (y-line->v1->y, line->dx, line->v1->x-x, line->dy) > 0;
}
//==========================================================================
//
// P_PointOnDivlineSide
//
// Same as P_PointOnLineSide except it uses divlines
// [RH] inlined, stripped down, and made more precise
//
//==========================================================================
inline int P_PointOnDivlineSide (fixed_t x, fixed_t y, const divline_t *line)
{
extern int P_VanillaPointOnDivlineSide(fixed_t x, fixed_t y, const divline_t* line);
return (i_compatflags2 & COMPATF2_POINTONLINE)
? P_VanillaPointOnDivlineSide(x, y, line)
: (DMulScale32 (y-line->y, line->dx, line->x-x, line->dy) > 0);
}
inline int P_PointOnDivlineSidePrecise (fixed_t x, fixed_t y, const divline_t *line)
{
return DMulScale32 (y-line->y, line->dx, line->x-x, line->dy) > 0;
}
//==========================================================================
//
// P_MakeDivline
//
//==========================================================================
inline void P_MakeDivline (const line_t *li, divline_t *dl)
{
dl->x = li->v1->x;
dl->y = li->v1->y;
dl->dx = li->dx;
dl->dy = li->dy;
}
fixed_t P_InterceptVector (const divline_t *v2, const divline_t *v1);
struct FLineOpening
{
fixed_t top;
fixed_t bottom;
fixed_t range;
fixed_t lowfloor;
sector_t *bottomsec;
sector_t *topsec;
FTextureID ceilingpic;
FTextureID floorpic;
int floorterrain;
bool touchmidtex;
bool abovemidtex;
};
void P_LineOpening (FLineOpening &open, AActor *thing, const line_t *linedef, fixed_t x, fixed_t y, fixed_t refx=FIXED_MIN, fixed_t refy=0, int flags=0);
class FBoundingBox;
struct polyblock_t;
class FBlockLinesIterator
{
int minx, maxx;
int miny, maxy;
int curx, cury;
polyblock_t *polyLink;
int polyIndex;
int *list;
void StartBlock(int x, int y);
public:
FBlockLinesIterator(int minx, int miny, int maxx, int maxy, bool keepvalidcount = false);
FBlockLinesIterator(const FBoundingBox &box);
line_t *Next();
void Reset() { StartBlock(minx, miny); }
};
class FBlockThingsIterator
{
int minx, maxx;
int miny, maxy;
int curx, cury;
FBlockNode *block;
int Buckets[32];
struct HashEntry
{
AActor *Actor;
int Next;
};
HashEntry FixedHash[10];
int NumFixedHash;
TArray<HashEntry> DynHash;
HashEntry *GetHashEntry(int i) { return i < (int)countof(FixedHash) ? &FixedHash[i] : &DynHash[i - countof(FixedHash)]; }
void StartBlock(int x, int y);
void SwitchBlock(int x, int y);
void ClearHash();
// The following is only for use in the path traverser
// and therefore declared private.
FBlockThingsIterator();
friend class FPathTraverse;
public:
FBlockThingsIterator(int minx, int miny, int maxx, int maxy);
FBlockThingsIterator(const FBoundingBox &box);
AActor *Next(bool centeronly = false);
void Reset() { StartBlock(minx, miny); }
};
class FPathTraverse
{
static TArray<intercept_t> intercepts;
divline_t trace;
unsigned int intercept_index;
unsigned int intercept_count;
unsigned int count;
void AddLineIntercepts(int bx, int by);
void AddThingIntercepts(int bx, int by, FBlockThingsIterator &it, bool compatible);
public:
intercept_t *Next();
FPathTraverse(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, int flags);
~FPathTraverse();
const divline_t &Trace() const { return trace; }
};
#define PT_ADDLINES 1
#define PT_ADDTHINGS 2
#define PT_COMPATIBLE 4
#define PT_DELTA 8 // x2,y2 is passed as a delta, not as an endpoint
AActor *P_BlockmapSearch (AActor *mo, int distance, AActor *(*check)(AActor*, int, void *), void *params = NULL);
AActor *P_RoughMonsterSearch (AActor *mo, int distance, bool onlyseekable=false);
@ -423,45 +235,6 @@ AActor *P_RoughMonsterSearch (AActor *mo, int distance, bool onlyseekable=false)
// P_MAP
//
struct FCheckPosition
{
// in
AActor *thing;
fixed_t x;
fixed_t y;
fixed_t z;
// out
sector_t *sector;
fixed_t floorz;
fixed_t ceilingz;
fixed_t dropoffz;
FTextureID floorpic;
int floorterrain;
sector_t *floorsector;
FTextureID ceilingpic;
sector_t *ceilingsector;
bool touchmidtex;
bool abovemidtex;
bool floatok;
bool FromPMove;
line_t *ceilingline;
AActor *stepthing;
// [RH] These are used by PIT_CheckThing and P_XYMovement to apply
// ripping damage once per tic instead of once per move.
bool DoRipping;
TMap<AActor*, bool> LastRipped;
int PushTime;
FCheckPosition(bool rip=false)
{
DoRipping = rip;
PushTime = 0;
FromPMove = false;
}
};
// If "floatok" true, move would be ok
// if within "tmfloorz - tmceilingz".
@ -539,7 +312,6 @@ enum // P_LineAttack flags
AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, int pitch, int damage, FName damageType, PClassActor *pufftype, int flags = 0, AActor **victim = NULL, int *actualdamage = NULL);
AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, int pitch, int damage, FName damageType, FName pufftype, int flags = 0, AActor **victim = NULL, int *actualdamage = NULL);
AActor *P_LinePickActor (AActor *t1, angle_t angle, fixed_t distance, int pitch, ActorFlags actorMask, DWORD wallMask);
void P_TraceBleed (int damage, fixed_t x, fixed_t y, fixed_t z, AActor *target, angle_t angle, int pitch);
void P_TraceBleed (int damage, AActor *target, angle_t angle, int pitch);
void P_TraceBleed (int damage, AActor *target, AActor *missile); // missile version
@ -587,31 +359,10 @@ bool Check_Sides(AActor *, int, int); // phares
// [RH]
const secplane_t * P_CheckSlopeWalk (AActor *actor, fixed_t &xmove, fixed_t &ymove);
//----------------------------------------------------------------------------------
//
// Added so that in the source there's a clear distinction between
// game engine and renderer specific calls.
// (For ZDoom itself this doesn't make any difference here but for GZDoom it does.)
//
//----------------------------------------------------------------------------------
subsector_t *P_PointInSubsector (fixed_t x, fixed_t y);
inline sector_t *P_PointInSector(fixed_t x, fixed_t y)
{
return P_PointInSubsector(x,y)->sector;
}
//
// P_SETUP
//
extern BYTE* rejectmatrix; // for fast sight rejection
extern int* blockmaplump; // offsets in blockmap are from here
extern int* blockmap;
extern int bmapwidth;
extern int bmapheight; // in mapblocks
extern fixed_t bmaporgx;
extern fixed_t bmaporgy; // origin of block map
extern FBlockNode** blocklinks; // for thing chains
@ -639,46 +390,9 @@ enum EDmgFlags
};
// ===== PO_MAN =====
typedef enum
{
PODOOR_NONE,
PODOOR_SLIDE,
PODOOR_SWING,
} podoortype_t;
bool EV_RotatePoly (line_t *line, int polyNum, int speed, int byteAngle, int direction, bool overRide);
bool EV_MovePoly (line_t *line, int polyNum, int speed, angle_t angle, fixed_t dist, bool overRide);
bool EV_MovePolyTo (line_t *line, int polyNum, int speed, fixed_t x, fixed_t y, bool overRide);
bool EV_OpenPolyDoor (line_t *line, int polyNum, int speed, angle_t angle, int delay, int distance, podoortype_t type);
bool EV_StopPoly (int polyNum);
// [RH] Data structure for P_SpawnMapThing() to keep track
// of polyobject-related things.
struct polyspawns_t
{
polyspawns_t *next;
fixed_t x;
fixed_t y;
short angle;
short type;
};
extern int po_NumPolyobjs;
extern polyspawns_t *polyspawns; // [RH] list of polyobject things to spawn
void PO_Init ();
bool PO_Busy (int polyobj);
FPolyObj *PO_GetPolyobj(int polyNum);
//
// P_SPEC
//
#include "p_spec.h"
bool P_AlignFlat (int linenum, int side, int fc);
#endif // __P_LOCAL__

View file

@ -34,10 +34,15 @@
#include "doomdef.h"
#include "p_local.h"
#include "p_spec.h"
#include "d_player.h"
#include "p_maputl.h"
#include "p_lnspec.h"
#include "p_effect.h"
#include "p_terrain.h"
#include "p_trace.h"
#include "p_checkposition.h"
#include "r_utility.h"
#include "s_sound.h"
#include "decallib.h"

View file

@ -32,9 +32,13 @@
#include "m_bbox.h"
#include "doomdef.h"
#include "doomdata.h"
#include "doomstat.h"
#include "p_local.h"
#include "p_maputl.h"
#include "p_3dmidtex.h"
#include "p_blockmap.h"
#include "r_utility.h"
// State.
#include "r_state.h"
@ -42,6 +46,8 @@
#include "po_man.h"
static AActor *RoughBlockCheck (AActor *mo, int index, void *);
static int R_PointOnSideSlow(fixed_t x, fixed_t y, node_t *node);
sector_t *P_PointInSectorBuggy(fixed_t x, fixed_t y);
//==========================================================================
@ -311,39 +317,118 @@ void AActor::UnlinkFromWorld ()
}
//==========================================================================
//
// If the thing is exactly on a line, move it into the sector
// slightly in order to resolve clipping issues in the renderer.
//
//==========================================================================
bool AActor::FixMapthingPos()
{
sector_t *secstart = P_PointInSectorBuggy(X(), Y());
int blockx = GetSafeBlockX(X() - bmaporgx);
int blocky = GetSafeBlockY(Y() - bmaporgy);
bool success = false;
if ((unsigned int)blockx < (unsigned int)bmapwidth &&
(unsigned int)blocky < (unsigned int)bmapheight)
{
int *list;
for (list = blockmaplump + blockmap[blocky*bmapwidth + blockx] + 1; *list != -1; ++list)
{
line_t *ldef = &lines[*list];
if (ldef->frontsector == ldef->backsector)
{ // Skip two-sided lines inside a single sector
continue;
}
if (ldef->backsector != NULL)
{
if (ldef->frontsector->floorplane == ldef->backsector->floorplane &&
ldef->frontsector->ceilingplane == ldef->backsector->ceilingplane)
{ // Skip two-sided lines without any height difference on either side
continue;
}
}
// Not inside the line's bounding box
if (X() + radius <= ldef->bbox[BOXLEFT]
|| X() - radius >= ldef->bbox[BOXRIGHT]
|| Y() + radius <= ldef->bbox[BOXBOTTOM]
|| Y() - radius >= ldef->bbox[BOXTOP])
continue;
// Get the exact distance to the line
divline_t dll, dlv;
fixed_t linelen = (fixed_t)sqrt((double)ldef->dx*ldef->dx + (double)ldef->dy*ldef->dy);
P_MakeDivline(ldef, &dll);
dlv.x = X();
dlv.y = Y();
dlv.dx = FixedDiv(dll.dy, linelen);
dlv.dy = -FixedDiv(dll.dx, linelen);
fixed_t distance = abs(P_InterceptVector(&dlv, &dll));
if (distance < radius)
{
DPrintf("%s at (%d,%d) lies on %s line %td, distance = %f\n",
this->GetClass()->TypeName.GetChars(), X() >> FRACBITS, Y() >> FRACBITS,
ldef->dx == 0 ? "vertical" : ldef->dy == 0 ? "horizontal" : "diagonal",
ldef - lines, FIXED2DBL(distance));
angle_t finean = R_PointToAngle2(0, 0, ldef->dx, ldef->dy);
if (ldef->backsector != NULL && ldef->backsector == secstart)
{
finean += ANGLE_90;
}
else
{
finean -= ANGLE_90;
}
finean >>= ANGLETOFINESHIFT;
// Get the distance we have to move the object away from the wall
distance = radius - distance;
SetXY(X() + FixedMul(distance, finecosine[finean]), Y() + FixedMul(distance, finesine[finean]));
success = true;
}
}
}
return success;
}
//==========================================================================
//
// P_SetThingPosition
// Links a thing into both a block and a subsector based on it's x y.
// Links a thing into both a block and a subsector based on its x y.
// Sets thing->sector properly
//
//==========================================================================
void AActor::LinkToWorld (bool buggy)
void AActor::LinkToWorld (bool spawningmapthing, FPortalGroupArray *groups, sector_t *sector)
{
// link into subsector
sector_t *sec;
if (!buggy || numgamenodes == 0)
if (spawningmapthing && (flags4 & MF4_FIXMAPTHINGPOS) && sector == NULL)
{
sec = P_PointInSector (X(), Y());
}
else
{
sec = LinkToWorldForMapThing ();
if (FixMapthingPos()) spawningmapthing = false;
}
LinkToWorld (sec);
}
void AActor::LinkToWorld (sector_t *sec)
{
if (sec == NULL)
if (sector == NULL)
{
LinkToWorld ();
return;
if (!spawningmapthing || numgamenodes == 0)
{
sector = P_PointInSector(X(), Y());
}
else
{
sector = P_PointInSectorBuggy(X(), Y());
}
}
Sector = sec;
Sector = sector;
subsector = R_PointInSubsector(X(), Y()); // this is from the rendering nodes, not the gameplay nodes!
if ( !(flags & MF_NOSECTOR) )
@ -352,7 +437,7 @@ void AActor::LinkToWorld (sector_t *sec)
// killough 8/11/98: simpler scheme using pointer-to-pointer prev
// pointers, allows head nodes to be treated like everything else
AActor **link = &sec->thinglist;
AActor **link = &sector->thinglist;
AActor *next = *link;
if ((snext = next))
next->sprev = &snext;
@ -401,7 +486,7 @@ void AActor::LinkToWorld (sector_t *sec)
for (int x = x1; x <= x2; ++x)
{
FBlockNode **link = &blocklinks[y*bmapwidth + x];
FBlockNode *node = FBlockNode::Create (this, x, y);
FBlockNode *node = FBlockNode::Create (this, x, y, this->Sector->PortalGroup);
// Link in to block
if ((node->NextActor = *link) != NULL)
@ -422,168 +507,6 @@ void AActor::LinkToWorld (sector_t *sec)
}
}
//==========================================================================
//
// [RH] LinkToWorldForMapThing
//
// Emulate buggy PointOnLineSide and fix actors that lie on
// lines to compensate for some IWAD maps.
//
//==========================================================================
static int R_PointOnSideSlow (fixed_t x, fixed_t y, node_t *node)
{
// [RH] This might have been faster than two multiplies and an
// add on a 386/486, but it certainly isn't on anything newer than that.
fixed_t dx;
fixed_t dy;
double left;
double right;
if (!node->dx)
{
if (x <= node->x)
return node->dy > 0;
return node->dy < 0;
}
if (!node->dy)
{
if (y <= node->y)
return node->dx < 0;
return node->dx > 0;
}
dx = (x - node->x);
dy = (y - node->y);
// Try to quickly decide by looking at sign bits.
if ( (node->dy ^ node->dx ^ dx ^ dy)&0x80000000 )
{
if ( (node->dy ^ dx) & 0x80000000 )
{
// (left is negative)
return 1;
}
return 0;
}
// we must use doubles here because the fixed point code will produce errors due to loss of precision for extremely short linedefs.
left = (double)node->dy * (double)dx;
right = (double)dy * (double)node->dx;
if (right < left)
{
// front side
return 0;
}
// back side
return 1;
}
sector_t *AActor::LinkToWorldForMapThing ()
{
node_t *node = gamenodes + numgamenodes - 1;
do
{
// Use original buggy point-on-side test when spawning
// things at level load so that the map spots in the
// emerald key room of Hexen MAP01 are spawned on the
// window ledge instead of the blocking floor in front
// of it. Why do I consider it buggy? Because a point
// that lies directly on a line should always be
// considered as "in front" of the line. The orientation
// of the line should be irrelevant.
node = (node_t *)node->children[R_PointOnSideSlow (X(), Y(), node)];
}
while (!((size_t)node & 1));
subsector_t *ssec = (subsector_t *)((BYTE *)node - 1);
if (flags4 & MF4_FIXMAPTHINGPOS)
{
// If the thing is exactly on a line, move it into the subsector
// slightly in order to resolve clipping issues in the renderer.
// This check needs to use the blockmap, because an actor on a
// one-sided line might go into a subsector behind the line, so
// the line would not be included as one of its subsector's segs.
int blockx = GetSafeBlockX(X() - bmaporgx);
int blocky = GetSafeBlockY(Y() - bmaporgy);
if ((unsigned int)blockx < (unsigned int)bmapwidth &&
(unsigned int)blocky < (unsigned int)bmapheight)
{
int *list;
for (list = blockmaplump + blockmap[blocky*bmapwidth + blockx] + 1; *list != -1; ++list)
{
line_t *ldef = &lines[*list];
if (ldef->frontsector == ldef->backsector)
{ // Skip two-sided lines inside a single sector
continue;
}
if (ldef->backsector != NULL)
{
if (ldef->frontsector->floorplane == ldef->backsector->floorplane &&
ldef->frontsector->ceilingplane == ldef->backsector->ceilingplane)
{ // Skip two-sided lines without any height difference on either side
continue;
}
}
// Not inside the line's bounding box
if (X() + radius <= ldef->bbox[BOXLEFT]
|| X() - radius >= ldef->bbox[BOXRIGHT]
|| Y() + radius <= ldef->bbox[BOXBOTTOM]
|| Y() - radius >= ldef->bbox[BOXTOP] )
continue;
// Get the exact distance to the line
divline_t dll, dlv;
fixed_t linelen = (fixed_t)sqrt((double)ldef->dx*ldef->dx + (double)ldef->dy*ldef->dy);
P_MakeDivline (ldef, &dll);
dlv.x = X();
dlv.y = Y();
dlv.dx = FixedDiv(dll.dy, linelen);
dlv.dy = -FixedDiv(dll.dx, linelen);
fixed_t distance = abs(P_InterceptVector(&dlv, &dll));
if (distance < radius)
{
DPrintf ("%s at (%d,%d) lies on %s line %td, distance = %f\n",
this->GetClass()->TypeName.GetChars(), X()>>FRACBITS, Y()>>FRACBITS,
ldef->dx == 0? "vertical" : ldef->dy == 0? "horizontal" : "diagonal",
ldef-lines, FIXED2DBL(distance));
angle_t finean = R_PointToAngle2 (0, 0, ldef->dx, ldef->dy);
if (ldef->backsector != NULL && ldef->backsector == ssec->sector)
{
finean += ANGLE_90;
}
else
{
finean -= ANGLE_90;
}
finean >>= ANGLETOFINESHIFT;
// Get the distance we have to move the object away from the wall
distance = radius - distance;
SetXY(X() + FixedMul(distance, finecosine[finean]), Y() + FixedMul(distance, finesine[finean]));
return P_PointInSector (X(), Y());
}
}
}
}
return ssec->sector;
}
void AActor::SetOrigin (fixed_t ix, fixed_t iy, fixed_t iz, bool moving)
{
UnlinkFromWorld ();
@ -597,7 +520,7 @@ void AActor::SetOrigin (fixed_t ix, fixed_t iy, fixed_t iz, bool moving)
FBlockNode *FBlockNode::FreeBlocks = NULL;
FBlockNode *FBlockNode::Create (AActor *who, int x, int y)
FBlockNode *FBlockNode::Create (AActor *who, int x, int y, int group)
{
FBlockNode *block;
@ -1524,6 +1447,67 @@ static AActor *RoughBlockCheck (AActor *mo, int index, void *param)
return NULL;
}
//==========================================================================
//
// [RH] LinkToWorldForMapThing
//
// Emulate buggy PointOnLineSide and fix actors that lie on
// lines to compensate for some IWAD maps.
//
//==========================================================================
static int R_PointOnSideSlow(fixed_t x, fixed_t y, node_t *node)
{
// [RH] This might have been faster than two multiplies and an
// add on a 386/486, but it certainly isn't on anything newer than that.
fixed_t dx;
fixed_t dy;
double left;
double right;
if (!node->dx)
{
if (x <= node->x)
return node->dy > 0;
return node->dy < 0;
}
if (!node->dy)
{
if (y <= node->y)
return node->dx < 0;
return node->dx > 0;
}
dx = (x - node->x);
dy = (y - node->y);
// Try to quickly decide by looking at sign bits.
if ((node->dy ^ node->dx ^ dx ^ dy) & 0x80000000)
{
if ((node->dy ^ dx) & 0x80000000)
{
// (left is negative)
return 1;
}
return 0;
}
// we must use doubles here because the fixed point code will produce errors due to loss of precision for extremely short linedefs.
left = (double)node->dy * (double)dx;
right = (double)dy * (double)node->dx;
if (right < left)
{
// front side
return 0;
}
// back side
return 1;
}
//===========================================================================
//
// P_VanillaPointOnLineSide
@ -1612,3 +1596,24 @@ int P_VanillaPointOnDivlineSide(fixed_t x, fixed_t y, const divline_t* line)
return 1; // back side
}
sector_t *P_PointInSectorBuggy(fixed_t x, fixed_t y)
{
node_t *node = gamenodes + numgamenodes - 1;
do
{
// Use original buggy point-on-side test when spawning
// things at level load so that the map spots in the
// emerald key room of Hexen MAP01 are spawned on the
// window ledge instead of the blocking floor in front
// of it. Why do I consider it buggy? Because a point
// that lies directly on a line should always be
// considered as "in front" of the line. The orientation
// of the line should be irrelevant.
node = (node_t *)node->children[R_PointOnSideSlow(x, y, node)];
} while (!((size_t)node & 1));
subsector_t *ssec = (subsector_t *)((BYTE *)node - 1);
return ssec->sector;
}

208
src/p_maputl.h Normal file
View file

@ -0,0 +1,208 @@
#ifndef __P_MAPUTL_H
#define __P_MAPUTL_H
#include "r_defs.h"
#include "doomstat.h"
extern int validcount;
struct divline_t
{
fixed_t x;
fixed_t y;
fixed_t dx;
fixed_t dy;
};
struct intercept_t
{
fixed_t frac; // along trace line
bool isaline;
bool done;
union {
AActor *thing;
line_t *line;
} d;
};
//==========================================================================
//
// P_PointOnLineSide
//
// Returns 0 (front/on) or 1 (back)
// [RH] inlined, stripped down, and made more precise
//
//==========================================================================
inline int P_PointOnLineSide (fixed_t x, fixed_t y, const line_t *line)
{
extern int P_VanillaPointOnLineSide(fixed_t x, fixed_t y, const line_t* line);
return i_compatflags2 & COMPATF2_POINTONLINE
? P_VanillaPointOnLineSide(x, y, line)
: DMulScale32 (y-line->v1->y, line->dx, line->v1->x-x, line->dy) > 0;
}
inline int P_PointOnLineSidePrecise (fixed_t x, fixed_t y, const line_t *line)
{
return DMulScale32 (y-line->v1->y, line->dx, line->v1->x-x, line->dy) > 0;
}
//==========================================================================
//
// P_PointOnDivlineSide
//
// Same as P_PointOnLineSide except it uses divlines
// [RH] inlined, stripped down, and made more precise
//
//==========================================================================
inline int P_PointOnDivlineSide (fixed_t x, fixed_t y, const divline_t *line)
{
extern int P_VanillaPointOnDivlineSide(fixed_t x, fixed_t y, const divline_t* line);
return (i_compatflags2 & COMPATF2_POINTONLINE)
? P_VanillaPointOnDivlineSide(x, y, line)
: (DMulScale32 (y-line->y, line->dx, line->x-x, line->dy) > 0);
}
inline int P_PointOnDivlineSidePrecise (fixed_t x, fixed_t y, const divline_t *line)
{
return DMulScale32 (y-line->y, line->dx, line->x-x, line->dy) > 0;
}
//==========================================================================
//
// P_MakeDivline
//
//==========================================================================
inline void P_MakeDivline (const line_t *li, divline_t *dl)
{
dl->x = li->v1->x;
dl->y = li->v1->y;
dl->dx = li->dx;
dl->dy = li->dy;
}
struct FLineOpening
{
fixed_t top;
fixed_t bottom;
fixed_t range;
fixed_t lowfloor;
sector_t *bottomsec;
sector_t *topsec;
FTextureID ceilingpic;
FTextureID floorpic;
int floorterrain;
bool touchmidtex;
bool abovemidtex;
};
void P_LineOpening (FLineOpening &open, AActor *thing, const line_t *linedef, fixed_t x, fixed_t y, fixed_t refx=FIXED_MIN, fixed_t refy=0, int flags=0);
class FBoundingBox;
struct polyblock_t;
class FBlockLinesIterator
{
int minx, maxx;
int miny, maxy;
int curx, cury;
polyblock_t *polyLink;
int polyIndex;
int *list;
void StartBlock(int x, int y);
public:
FBlockLinesIterator(int minx, int miny, int maxx, int maxy, bool keepvalidcount = false);
FBlockLinesIterator(const FBoundingBox &box);
line_t *Next();
void Reset() { StartBlock(minx, miny); }
};
class FBlockThingsIterator
{
int minx, maxx;
int miny, maxy;
int curx, cury;
FBlockNode *block;
int Buckets[32];
struct HashEntry
{
AActor *Actor;
int Next;
};
HashEntry FixedHash[10];
int NumFixedHash;
TArray<HashEntry> DynHash;
HashEntry *GetHashEntry(int i) { return i < (int)countof(FixedHash) ? &FixedHash[i] : &DynHash[i - countof(FixedHash)]; }
void StartBlock(int x, int y);
void SwitchBlock(int x, int y);
void ClearHash();
// The following is only for use in the path traverser
// and therefore declared private.
FBlockThingsIterator();
friend class FPathTraverse;
public:
FBlockThingsIterator(int minx, int miny, int maxx, int maxy);
FBlockThingsIterator(const FBoundingBox &box);
AActor *Next(bool centeronly = false);
void Reset() { StartBlock(minx, miny); }
};
class FPathTraverse
{
static TArray<intercept_t> intercepts;
divline_t trace;
unsigned int intercept_index;
unsigned int intercept_count;
unsigned int count;
void AddLineIntercepts(int bx, int by);
void AddThingIntercepts(int bx, int by, FBlockThingsIterator &it, bool compatible);
public:
intercept_t *Next();
FPathTraverse(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, int flags);
~FPathTraverse();
const divline_t &Trace() const { return trace; }
};
//
// P_MAPUTL
//
typedef bool(*traverser_t) (intercept_t *in);
fixed_t P_AproxDistance (fixed_t dx, fixed_t dy);
fixed_t P_InterceptVector (const divline_t *v2, const divline_t *v1);
#define PT_ADDLINES 1
#define PT_ADDTHINGS 2
#define PT_COMPATIBLE 4
#define PT_DELTA 8 // x2,y2 is passed as a delta, not as an endpoint
#endif

View file

@ -29,6 +29,7 @@
#include "m_random.h"
#include "doomdef.h"
#include "p_local.h"
#include "p_maputl.h"
#include "p_lnspec.h"
#include "p_effect.h"
#include "p_terrain.h"
@ -66,6 +67,9 @@
#include "farchive.h"
#include "r_data/colormaps.h"
#include "r_renderer.h"
#include "po_man.h"
#include "p_spec.h"
#include "p_checkposition.h"
// MACROS ------------------------------------------------------------------
@ -452,7 +456,7 @@ void AActor::Serialize (FArchive &arc)
if (arc.IsLoading ())
{
touching_sectorlist = NULL;
LinkToWorld (Sector);
LinkToWorld (false, NULL, Sector);
AddToHash ();
SetShade (fillcolor);
if (player)

View file

@ -31,6 +31,7 @@
#include "r_state.h"
#include "gi.h"
#include "farchive.h"
#include "p_spec.h"
static FRandom pr_doplat ("DoPlat");

View file

@ -34,8 +34,10 @@
#include "i_system.h"
#include "p_local.h"
#include "p_spec.h"
// State.
#include "d_player.h"
#include "dobject.h"
#include "doomstat.h"
#include "r_state.h"
@ -532,6 +534,7 @@ void P_SerializeWorld (FArchive &arc)
{
linePortals.Clear();
}
P_CollectLinkedPortals();
}
void extsector_t::Serialize(FArchive &arc)

View file

@ -29,6 +29,7 @@
#endif
#include "templates.h"
#include "d_player.h"
#include "m_argv.h"
#include "m_swap.h"
#include "m_bbox.h"
@ -69,6 +70,9 @@
#include "r_renderer.h"
#include "r_data/colormaps.h"
#include "portal.h"
#include "p_blockmap.h"
#include "r_utility.h"
#include "p_spec.h"
#ifndef NO_EDATA
#include "edata.h"
#endif

View file

@ -14,11 +14,16 @@
#include "doomdef.h"
#include "i_system.h"
#include "p_local.h"
#include "p_maputl.h"
#include "p_blockmap.h"
#include "m_random.h"
#include "m_bbox.h"
#include "p_lnspec.h"
#include "g_level.h"
#include "po_man.h"
#include "r_utility.h"
#include "b_bot.h"
#include "p_spec.h"
// State.
#include "r_state.h"

View file

@ -36,6 +36,8 @@
#include "p_local.h"
#include "cmdlib.h"
#include "p_lnspec.h"
#include "p_maputl.h"
#include "p_spec.h"
//===========================================================================
//

View file

@ -46,6 +46,8 @@
#include "w_wad.h"
#include "p_local.h"
#include "p_spec.h"
#include "p_blockmap.h"
#include "p_lnspec.h"
#include "p_terrain.h"
#include "p_acs.h"
@ -64,7 +66,10 @@
#include "a_keys.h"
#include "c_dispatch.h"
#include "r_sky.h"
#include "d_player.h"
#include "portal.h"
#include "p_maputl.h"
#include "p_blockmap.h"
#ifndef NO_EDATA
#include "edata.h"
#endif

View file

@ -47,6 +47,8 @@
#include "tarray.h"
#include "cmdlib.h"
#include "farchive.h"
#include "p_maputl.h"
#include "p_spec.h"
#include "gi.h"

View file

@ -34,6 +34,10 @@
#include "m_random.h"
#include "i_system.h"
#include "doomstat.h"
#include "d_player.h"
#include "p_maputl.h"
#include "r_utility.h"
#include "p_spec.h"
#define FUDGEFACTOR 10

View file

@ -47,6 +47,9 @@
#include "g_level.h"
#include "v_text.h"
#include "i_system.h"
#include "d_player.h"
#include "r_utility.h"
#include "p_spec.h"
// Set of spawnable things for the Thing_Spawn and Thing_Projectile specials.
FClassMap SpawnableThings;

View file

@ -31,7 +31,10 @@
#include "sbar.h"
#include "r_data/r_interpolate.h"
#include "i_sound.h"
#include "d_player.h"
#include "g_level.h"
#include "r_utility.h"
#include "p_spec.h"
extern gamestate_t wipegamestate;

View file

@ -37,6 +37,9 @@
#include "i_system.h"
#include "r_sky.h"
#include "doomstat.h"
#include "p_maputl.h"
#include "r_defs.h"
#include "p_spec.h"
struct FTraceInfo
{

View file

@ -54,6 +54,11 @@
#include "gstrings.h"
#include "farchive.h"
#include "r_renderer.h"
#include "d_player.h"
#include "r_utility.h"
#include "p_blockmap.h"
#include "a_morph.h"
#include "p_spec.h"
static FRandom pr_skullpop ("SkullPop");

View file

@ -5,6 +5,8 @@
#include "r_defs.h"
#include "m_swap.h"
#include "doomstat.h"
#include "d_player.h"
#include "p_spec.h"
static int WriteTHINGS (FILE *file);
static int WriteLINEDEFS (FILE *file);

View file

@ -29,6 +29,9 @@
#include "p_setup.h"
#include "vectors.h"
#include "farchive.h"
#include "p_blockmap.h"
#include "p_maputl.h"
#include "r_utility.h"
// MACROS ------------------------------------------------------------------

View file

@ -107,4 +107,40 @@ FArchive &operator<< (FArchive &arc, FPolyObj *&poly);
FArchive &operator<< (FArchive &arc, const FPolyObj *&poly);
// ===== PO_MAN =====
typedef enum
{
PODOOR_NONE,
PODOOR_SLIDE,
PODOOR_SWING,
} podoortype_t;
bool EV_RotatePoly (line_t *line, int polyNum, int speed, int byteAngle, int direction, bool overRide);
bool EV_MovePoly (line_t *line, int polyNum, int speed, angle_t angle, fixed_t dist, bool overRide);
bool EV_MovePolyTo (line_t *line, int polyNum, int speed, fixed_t x, fixed_t y, bool overRide);
bool EV_OpenPolyDoor (line_t *line, int polyNum, int speed, angle_t angle, int delay, int distance, podoortype_t type);
bool EV_StopPoly (int polyNum);
// [RH] Data structure for P_SpawnMapThing() to keep track
// of polyobject-related things.
struct polyspawns_t
{
polyspawns_t *next;
fixed_t x;
fixed_t y;
short angle;
short type;
};
extern int po_NumPolyobjs;
extern polyspawns_t *polyspawns; // [RH] list of polyobject things to spawn
void PO_Init ();
bool PO_Busy (int polyobj);
FPolyObj *PO_GetPolyobj(int polyNum);
#endif

View file

@ -1,3 +1,42 @@
/*
** portals.cpp
** Everything that has to do with portals (both of the line and sector variety)
**
**---------------------------------------------------------------------------
** Copyright 2016 ZZYZX
** Copyright 2016 Christoph Oelckers
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
** There is no code here that is directly taken from Eternity
** although some similarities may be inevitable because it has to
** implement the same concepts.
*/
#include "portal.h"
#include "p_local.h"
#include "p_lnspec.h"
@ -11,6 +50,9 @@
#include "a_sharedglobal.h"
#include "i_system.h"
#include "c_dispatch.h"
#include "p_maputl.h"
#include "p_spec.h"
#include "p_checkposition.h"
// simulation recurions maximum
CVAR(Int, sv_portal_recursions, 4, CVAR_ARCHIVE|CVAR_SERVERINFO)
@ -18,7 +60,47 @@ CVAR(Int, sv_portal_recursions, 4, CVAR_ARCHIVE|CVAR_SERVERINFO)
FDisplacementTable Displacements;
TArray<FLinePortal> linePortals;
TArray<FLinePortal*> linkedPortals; // only the linked portals, this is used to speed up looking for them in P_CollectConnectedGroups.
//============================================================================
//
// This is used to mark processed portals for some collection functions.
//
//============================================================================
struct FPortalBits
{
TArray<DWORD> data;
void setSize(int num)
{
data.Resize((num + 31) / 32);
clear();
}
void clear()
{
memset(&data[0], 0, data.Size()*sizeof(DWORD));
}
void setBit(int group)
{
data[group >> 5] |= (1 << (group & 31));
}
int getBit(int group)
{
return data[group >> 5] & (1 << (group & 31));
}
};
//============================================================================
//
// Save a line portal for savegames.
//
//============================================================================
FArchive &operator<< (FArchive &arc, FLinePortal &port)
{
@ -34,6 +116,12 @@ FArchive &operator<< (FArchive &arc, FLinePortal &port)
}
//============================================================================
//
// finds the destination for a line portal for spawning
//
//============================================================================
static line_t *FindDestination(line_t *src, int tag)
{
if (tag)
@ -52,6 +140,12 @@ static line_t *FindDestination(line_t *src, int tag)
return NULL;
}
//============================================================================
//
// Spawns a single line portal
//
//============================================================================
void P_SpawnLinePortal(line_t* line)
{
// portal destination is special argument #0
@ -132,6 +226,12 @@ void P_SpawnLinePortal(line_t* line)
}
}
//============================================================================
//
// Update a line portal's state after all have been spawned
//
//============================================================================
void P_UpdatePortal(FLinePortal *port)
{
if (port->mDestination == NULL)
@ -168,6 +268,32 @@ void P_UpdatePortal(FLinePortal *port)
}
}
//============================================================================
//
// Collect a separate list of linked portals so that these can be
// processed faster without the simpler types interfering.
//
//============================================================================
void P_CollectLinkedPortals()
{
linkedPortals.Clear();
for (unsigned i = 0; i < linePortals.Size(); i++)
{
FLinePortal * port = &linePortals[i];
if (port->mType == PORTT_LINKED)
{
linkedPortals.Push(port);
}
}
}
//============================================================================
//
// Post-process all line portals
//
//============================================================================
void P_FinalizePortals()
{
for (unsigned i = 0; i < linePortals.Size(); i++)
@ -175,8 +301,15 @@ void P_FinalizePortals()
FLinePortal * port = &linePortals[i];
P_UpdatePortal(port);
}
P_CollectLinkedPortals();
}
//============================================================================
//
// Change the destination of a portal
//
//============================================================================
static bool ChangePortalLine(line_t *line, int destid)
{
if (line->portalindex >= linePortals.Size()) return false;
@ -207,6 +340,12 @@ static bool ChangePortalLine(line_t *line, int destid)
}
//============================================================================
//
// Change the destination of a group of portals
//
//============================================================================
bool P_ChangePortal(line_t *ln, int thisid, int destid)
{
int lineno;
@ -221,7 +360,13 @@ bool P_ChangePortal(line_t *ln, int thisid, int destid)
return res;
}
//============================================================================
//
// Calculate the intersection between two lines.
// [ZZ] lots of floats here to avoid overflowing a lot
//
//============================================================================
bool P_IntersectLines(fixed_t o1x, fixed_t o1y, fixed_t p1x, fixed_t p1y,
fixed_t o2x, fixed_t o2y, fixed_t p2x, fixed_t p2y,
fixed_t& rx, fixed_t& ry)
@ -261,9 +406,15 @@ inline int P_PointOnLineSideExplicit (fixed_t x, fixed_t y, fixed_t x1, fixed_t
return DMulScale32 (y-y1, x2-x1, x1-x, y2-y1) > 0;
}
//============================================================================
//
// check if this line is between portal and the viewer. clip away if it is.
// (this may need some fixing)
//
//============================================================================
bool P_ClipLineToPortal(line_t* line, line_t* portal, fixed_t viewx, fixed_t viewy, bool partial, bool samebehind)
{
// check if this line is between portal and the viewer. clip away if it is.
bool behind1 = !!P_PointOnLineSidePrecise(line->v1->x, line->v1->y, portal);
bool behind2 = !!P_PointOnLineSidePrecise(line->v2->x, line->v2->y, portal);
@ -289,6 +440,12 @@ bool P_ClipLineToPortal(line_t* line, line_t* portal, fixed_t viewx, fixed_t vie
return false;
}
//============================================================================
//
// Translates a coordinate by a portal's displacement
//
//============================================================================
void P_TranslatePortalXY(line_t* src, line_t* dst, fixed_t& x, fixed_t& y)
{
if (!src || !dst)
@ -325,6 +482,12 @@ void P_TranslatePortalXY(line_t* src, line_t* dst, fixed_t& x, fixed_t& y)
y = ty;
}
//============================================================================
//
// Translates a velocity vector by a portal's displacement
//
//============================================================================
void P_TranslatePortalVXVY(line_t* src, line_t* dst, fixed_t& vx, fixed_t& vy)
{
angle_t angle =
@ -343,6 +506,12 @@ void P_TranslatePortalVXVY(line_t* src, line_t* dst, fixed_t& vx, fixed_t& vy)
vy = FixedMul(orig_vely, c) + FixedMul(orig_velx, s);
}
//============================================================================
//
// Translates an angle by a portal's displacement
//
//============================================================================
void P_TranslatePortalAngle(line_t* src, line_t* dst, angle_t& angle)
{
if (!src || !dst)
@ -359,6 +528,12 @@ void P_TranslatePortalAngle(line_t* src, line_t* dst, angle_t& angle)
angle += xangle;
}
//============================================================================
//
// Translates a z-coordinate by a portal's displacement
//
//============================================================================
void P_TranslatePortalZ(line_t* src, line_t* dst, fixed_t& z)
{
// args[2] = 0 - no adjustment
@ -380,7 +555,12 @@ void P_TranslatePortalZ(line_t* src, line_t* dst, fixed_t& z)
}
}
//============================================================================
//
// calculate shortest distance from a point (x,y) to a linedef
//
//============================================================================
fixed_t P_PointLineDistance(line_t* line, fixed_t x, fixed_t y)
{
angle_t angle = R_PointToAngle2(0, 0, line->dx, line->dy);
@ -406,7 +586,12 @@ void P_NormalizeVXVY(fixed_t& vx, fixed_t& vy)
vy = FLOAT2FIXED(_vy/len);
}
//============================================================================
//
// portal tracer code
//
//============================================================================
PortalTracer::PortalTracer(fixed_t startx, fixed_t starty, fixed_t endx, fixed_t endy)
{
this->startx = startx;
@ -521,8 +706,6 @@ bool PortalTracer::TraceStep()
return (oDepth != depth); // if a portal has been found, return false
}
//============================================================================
//
// CollectSectors
@ -566,6 +749,9 @@ static bool CollectSectors(int groupid, sector_t *origin)
// Adds the displacement for one portal to the displacement array
// (one version for sector to sector plane, one for line to line portals)
//
// Note: Despite the similarities to Eternity's equivalent this is
// original code!
//
//============================================================================
static void AddDisplacementForPortal(AStackPoint *portal)
@ -779,14 +965,13 @@ void P_CreateLinkedPortals()
ASkyViewpoint *box = sectors[i].SkyBoxes[j];
if (box != NULL)
{
if (box->special1 == SKYBOX_LINKEDPORTAL && box->Sector->PortalGroup == 0)
if (box->special1 == SKYBOX_LINKEDPORTAL && sectors[i].PortalGroup == 0)
{
CollectSectors(box->Sector->PortalGroup, box->Sector);
box = box->Mate;
if (box->special1 == SKYBOX_LINKEDPORTAL && box->Sector->PortalGroup == 0)
{
CollectSectors(box->Sector->PortalGroup, box->Sector);
}
// Note: the linked actor will be on the other side of the portal.
// To get this side's group we will have to look at the mate object.
CollectSectors(box->Mate->Sector->PortalGroup, &sectors[i]);
// We cannot process the backlink here because all we can access is the anchor object
// If necessary that will have to be done for the other side's portal.
}
}
}
@ -812,10 +997,32 @@ void P_CreateLinkedPortals()
if (dispxy.isSet && dispyx.isSet &&
(dispxy.x != -dispyx.x || dispxy.y != -dispyx.y))
{
Printf("Link offset mismatch between groups %d and %d\n", x, y); // need to find some sectors to report.
int sec1 = -1, sec2 = -1;
for (int i = 0; i < numsectors && (sec1 == -1 || sec2 == -1); i++)
{
if (sec1 == -1 && sectors[i].PortalGroup == x) sec1 = i;
if (sec2 == -1 && sectors[i].PortalGroup == y) sec2 = i;
}
Printf("Link offset mismatch between sectors %d and %d\n", sec1, sec2);
bogus = true;
}
// todo: Find sectors that have no group but belong to a portal.
// mark everything that connects to a one-sided line
for (int i = 0; i < numlines; i++)
{
if (lines[i].backsector == NULL && lines[i].frontsector->PortalGroup == 0)
{
CollectSectors(-1, lines[i].frontsector);
}
}
// and now print a message for everything that still wasn't processed.
for (int i = 0; i < numsectors; i++)
{
if (sectors[i].PortalGroup == 0)
{
Printf("Unable to assign sector %d to any group. Possibly self-referencing\n", i);
}
else if (sectors[i].PortalGroup == -1) sectors[i].PortalGroup = 0;
}
}
}
bogus |= ConnectGroups();
@ -839,6 +1046,106 @@ void P_CreateLinkedPortals()
//BuildBlockmap();
}
//============================================================================
//
// Collect all portal groups this actor would occupy at the given position
// This is used to determine which parts of the map need to be checked.
//
//============================================================================
bool P_CollectConnectedGroups(AActor *actor, fixed_t newx, fixed_t newy, FPortalGroupArray &out)
{
// Keep this temporary work stuff static. This function can never be called recursively
// and this would have to be reallocated for each call otherwise.
static FPortalBits processMask;
static TArray<FLinePortal*> foundPortals;
bool retval = false;
if (linkedPortals.Size() == 0)
{
// If there are no portals, all sectors are in group 0.
out.Add(0);
return false;
}
processMask.setSize(linkedPortals.Size());
processMask.clear();
foundPortals.Clear();
int thisgroup = actor->Sector->PortalGroup;
processMask.setBit(thisgroup);
out.Add(thisgroup);
for (unsigned i = 0; i < linkedPortals.Size(); i++)
{
line_t *ld = linkedPortals[i]->mOrigin;
int othergroup = ld->frontsector->PortalGroup;
FDisplacement &disp = Displacements(thisgroup, othergroup);
if (!disp.isSet) continue; // no connection.
FBoundingBox box(newx + disp.x, newy + disp.y, actor->radius);
if (box.Right() <= ld->bbox[BOXLEFT]
|| box.Left() >= ld->bbox[BOXRIGHT]
|| box.Top() <= ld->bbox[BOXBOTTOM]
|| box.Bottom() >= ld->bbox[BOXTOP])
continue; // not touched
if (box.BoxOnLineSide(linkedPortals[i]->mOrigin) != -1) continue; // not touched
foundPortals.Push(linkedPortals[i]);
}
bool foundone = true;
while (foundone)
{
foundone = false;
for (int i = foundPortals.Size() - 1; i >= 0; i--)
{
if (processMask.getBit(foundPortals[i]->mOrigin->frontsector->PortalGroup) &&
!processMask.getBit(foundPortals[i]->mDestination->frontsector->PortalGroup))
{
processMask.setBit(foundPortals[i]->mDestination->frontsector->PortalGroup);
out.Add(foundPortals[i]->mDestination->frontsector->PortalGroup);
foundone = true;
retval = true;
foundPortals.Delete(i);
}
}
}
sector_t *sec = P_PointInSector(newx, newy);
sector_t *wsec = sec;
while (!wsec->PortalBlocksMovement(sector_t::ceiling) && actor->Top() > wsec->SkyBoxes[sector_t::ceiling]->threshold)
{
sector_t *othersec = wsec->SkyBoxes[sector_t::ceiling]->Sector;
FDisplacement &disp = Displacements(actor->Sector->PortalGroup, othersec->PortalGroup);
fixed_t dx = newx + disp.x;
fixed_t dy = newx + disp.y;
processMask.setBit(othersec->PortalGroup);
out.Add(othersec->PortalGroup);
wsec = P_PointInSector(dx, dy); // get upper sector at the exact spot we want to check and repeat
retval = true;
}
wsec = sec;
while (!wsec->PortalBlocksMovement(sector_t::floor) && actor->Z() < wsec->SkyBoxes[sector_t::floor]->threshold)
{
sector_t *othersec = wsec->SkyBoxes[sector_t::ceiling]->Sector;
FDisplacement &disp = Displacements(actor->Sector->PortalGroup, othersec->PortalGroup);
fixed_t dx = newx + disp.x;
fixed_t dy = newx + disp.y;
processMask.setBit(othersec->PortalGroup);
out.Add(othersec->PortalGroup);
wsec = P_PointInSector(dx, dy); // get lower sector at the exact spot we want to check and repeat
retval = true;
}
return retval;
}
//============================================================================
//
// print the group link table to the console
//
//============================================================================
CCMD(dumplinktable)
{
for (int x = 1; x < Displacements.size; x++)
@ -854,3 +1161,4 @@ CCMD(dumplinktable)

View file

@ -7,6 +7,26 @@
#include "actor.h"
#include "p_local.h"
#include "m_bbox.h"
#include "a_sharedglobal.h"
struct FPortalGroupArray;
//============================================================================
//
// This table holds the offsets for the different parts of a map
// that are connected by portals.
// The idea here is basically the same as implemented in Eternity Engine:
//
// - each portal creates two sector groups in the map
// which are offset by the displacement of the portal anchors
//
// - for two or multiple groups the displacement is calculated by
// adding the displacements between intermediate groups which
// have to be traversed to connect the two
//
// - any sector not connected to any portal is assigned to group 0
// Group 0 has no displacement to any other group in the level.
//
//============================================================================
struct FDisplacement
{
@ -33,6 +53,14 @@ struct FDisplacementTable
}
};
extern FDisplacementTable Displacements;
//============================================================================
//
// Flags and types for linedef portals
//
//============================================================================
enum
{
PORTF_VISIBLE = 1,
@ -60,6 +88,20 @@ enum
PORG_CEILING,
};
enum
{
PCOLL_NOTLINKED = 1,
PCOLL_LINKED = 2
};
//============================================================================
//
// All information about a line-to-line portal (all types)
// There is no structure for sector plane portals because for historic
// reasons those use actors to connect.
//
//============================================================================
struct FLinePortal
{
line_t *mOrigin;
@ -78,6 +120,12 @@ void P_SpawnLinePortal(line_t* line);
void P_FinalizePortals();
bool P_ChangePortal(line_t *ln, int thisid, int destid);
void P_CreateLinkedPortals();
bool P_CollectConnectedGroups(AActor *actor, fixed_t newx, fixed_t newy, FPortalGroupArray &out);
void P_CollectLinkedPortals();
inline int P_NumPortalGroups()
{
return Displacements.size;
}
/* code ported from prototype */
@ -88,9 +136,14 @@ void P_TranslatePortalAngle(line_t* src, line_t* dst, angle_t& angle);
void P_TranslatePortalZ(line_t* src, line_t* dst, fixed_t& z);
void P_NormalizeVXVY(fixed_t& vx, fixed_t& vy);
//============================================================================
//
// basically, this is a teleporting tracer function,
// which can be used by itself (to calculate portal-aware offsets, say, for projectiles)
// or to teleport normal tracers (like hitscan, railgun, autoaim tracers)
//
//============================================================================
class PortalTracer
{
public:
@ -122,6 +175,12 @@ public:
/* new code */
fixed_t P_PointLineDistance(line_t* line, fixed_t x, fixed_t y);
//============================================================================
//
// some wrappers around the portal data.
//
//============================================================================
// returns true if the portal is crossable by actors
inline bool line_t::isLinePortal() const
@ -145,4 +204,22 @@ inline int line_t::getPortalAlignment() const
return portalindex >= linePortals.Size() ? 0 : linePortals[portalindex].mAlign;
}
inline bool sector_t::PortalBlocksView(int plane)
{
if (SkyBoxes[plane] == NULL || SkyBoxes[plane]->special1 != SKYBOX_LINKEDPORTAL) return true;
return !!(planes[plane].Flags & (PLANEF_NORENDER | PLANEF_DISABLED | PLANEF_OBSTRUCTED));
}
inline bool sector_t::PortalBlocksMovement(int plane)
{
if (SkyBoxes[plane] == NULL || SkyBoxes[plane]->special1 != SKYBOX_LINKEDPORTAL) return true;
return !!(planes[plane].Flags & (PLANEF_NOPASS | PLANEF_DISABLED | PLANEF_OBSTRUCTED));
}
inline bool sector_t::PortalBlocksSound(int plane)
{
if (SkyBoxes[plane] == NULL || SkyBoxes[plane]->special1 != SKYBOX_LINKEDPORTAL) return true;
return !!(planes[plane].Flags & (PLANEF_BLOCKSOUND | PLANEF_DISABLED | PLANEF_OBSTRUCTED));
}
#endif

View file

@ -792,21 +792,9 @@ struct sector_t
Flags &= ~SECF_SPECIALFLAGS;
}
inline bool PortalBlocksView(int plane)
{
return !!(planes[plane].Flags & (PLANEF_NORENDER | PLANEF_DISABLED | PLANEF_OBSTRUCTED));
}
inline bool PortalBlocksMovement(int plane)
{
return !!(planes[plane].Flags & (PLANEF_NOPASS | PLANEF_DISABLED | PLANEF_OBSTRUCTED));
}
inline bool PortalBlocksSound(int plane)
{
return !!(planes[plane].Flags & (PLANEF_BLOCKSOUND | PLANEF_DISABLED | PLANEF_OBSTRUCTED));
}
bool PortalBlocksView(int plane);
bool PortalBlocksMovement(int plane);
bool PortalBlocksSound(int plane);
int GetTerrain(int pos) const;
@ -1277,4 +1265,17 @@ struct visstyle_t
};
//----------------------------------------------------------------------------------
//
// The playsim can use different nodes than the renderer so this is
// not the same as R_PointInSubsector
//
//----------------------------------------------------------------------------------
subsector_t *P_PointInSubsector(fixed_t x, fixed_t y);
inline sector_t *P_PointInSector(fixed_t x, fixed_t y)
{
return P_PointInSubsector(x, y)->sector;
}
#endif

View file

@ -63,6 +63,7 @@
#include "r_data/colormaps.h"
#include "r_data/voxels.h"
#include "p_local.h"
#include "p_maputl.h"
// [RH] A c-buffer. Used for keeping track of offscreen voxel spans.

View file

@ -55,6 +55,8 @@
#include "r_renderer.h"
#include "r_data/colormaps.h"
#include "farchive.h"
#include "r_utility.h"
#include "d_player.h"
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
@ -878,16 +880,22 @@ void R_SetupFrame (AActor *actor)
interpolator.DoInterpolations (r_TicFrac);
// Keep the view within the sector's floor and ceiling
fixed_t theZ = viewsector->ceilingplane.ZatPoint (viewx, viewy) - 4*FRACUNIT;
if (viewz > theZ)
if (viewsector->PortalBlocksMovement(sector_t::ceiling))
{
viewz = theZ;
fixed_t theZ = viewsector->ceilingplane.ZatPoint(viewx, viewy) - 4 * FRACUNIT;
if (viewz > theZ)
{
viewz = theZ;
}
}
theZ = viewsector->floorplane.ZatPoint (viewx, viewy) + 4*FRACUNIT;
if (viewz < theZ)
if (viewsector->PortalBlocksMovement(sector_t::floor))
{
viewz = theZ;
fixed_t theZ = viewsector->floorplane.ZatPoint(viewx, viewy) + 4 * FRACUNIT;
if (viewz < theZ)
{
viewz = theZ;
}
}
if (!paused)

View file

@ -28,6 +28,7 @@
#include "c_dispatch.h"
#include "g_level.h"
#include "farchive.h"
#include "d_player.h"
// MACROS ------------------------------------------------------------------

View file

@ -51,6 +51,7 @@
#include "g_level.h"
#include "po_man.h"
#include "farchive.h"
#include "d_player.h"
// MACROS ------------------------------------------------------------------

View file

@ -37,36 +37,6 @@ class FTerrainTypeArray;
class FGLTexture;
class FMaterial;
class FTextureID
{
friend class FTextureManager;
friend FArchive &operator<< (FArchive &arc, FTextureID &tex);
friend FTextureID GetHUDIcon(PClassInventory *cls);
friend void R_InitSpriteDefs ();
public:
FTextureID() throw() {}
bool isNull() const { return texnum == 0; }
bool isValid() const { return texnum > 0; }
bool Exists() const { return texnum >= 0; }
void SetInvalid() { texnum = -1; }
void SetNull() { texnum = 0; }
bool operator ==(const FTextureID &other) const { return texnum == other.texnum; }
bool operator !=(const FTextureID &other) const { return texnum != other.texnum; }
FTextureID operator +(int offset) throw();
int GetIndex() const { return texnum; } // Use this only if you absolutely need the index!
// The switch list needs these to sort the switches by texture index
int operator -(FTextureID other) const { return texnum - other.texnum; }
bool operator < (FTextureID other) const { return texnum < other.texnum; }
bool operator > (FTextureID other) const { return texnum > other.texnum; }
protected:
FTextureID(int num) { texnum = num; }
private:
int texnum;
};
class FNullTextureID : public FTextureID
{
public:

View file

@ -73,6 +73,9 @@
#include "p_trace.h"
#include "p_setup.h"
#include "gstrings.h"
#include "d_player.h"
#include "p_maputl.h"
#include "p_spec.h"
AActor *SingleActorFromTID(int tid, AActor *defactor);