diff --git a/.gitignore b/.gitignore index eedc31a50..df5c6663b 100644 --- a/.gitignore +++ b/.gitignore @@ -43,4 +43,5 @@ /zlib/x64/ /build_vc2013_64bit /build_vc2015 -build_cmake +/build_vc2015-32 +/build_vc2015-64 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9c2377272..a89216bf9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -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 diff --git a/src/actor.h b/src/actor.h index 1b2c93d56..0dfa981b7 100644 --- a/src/actor.h +++ b/src/actor.h @@ -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 diff --git a/src/am_map.cpp b/src/am_map.cpp index df464e59d..b0ae28a13 100644 --- a/src/am_map.cpp +++ b/src/am_map.cpp @@ -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" diff --git a/src/b_bot.cpp b/src/b_bot.cpp index aa5262929..ee954a206 100644 --- a/src/b_bot.cpp +++ b/src/b_bot.cpp @@ -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) diff --git a/src/b_func.cpp b/src/b_func.cpp index 3edc560b0..fe2e2393d 100644 --- a/src/b_func.cpp +++ b/src/b_func.cpp @@ -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"); diff --git a/src/b_game.cpp b/src/b_game.cpp index 44545f73d..b896878e7 100644 --- a/src/b_game.cpp +++ b/src/b_game.cpp @@ -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"); diff --git a/src/b_move.cpp b/src/b_move.cpp index cee409265..1fcf207ed 100644 --- a/src/b_move.cpp +++ b/src/b_move.cpp @@ -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"); diff --git a/src/b_think.cpp b/src/b_think.cpp index a2b169f56..94d8e7ea2 100644 --- a/src/b_think.cpp +++ b/src/b_think.cpp @@ -19,6 +19,7 @@ #include "statnums.h" #include "d_net.h" #include "d_event.h" +#include "d_player.h" static FRandom pr_botmove ("BotMove"); diff --git a/src/basictypes.h b/src/basictypes.h index 3aa4f4635..0ae68f39b 100644 --- a/src/basictypes.h +++ b/src/basictypes.h @@ -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) diff --git a/src/c_cmds.cpp b/src/c_cmds.cpp index 1d16af31f..ca9ddaf6e 100644 --- a/src/c_cmds.cpp +++ b/src/c_cmds.cpp @@ -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; diff --git a/src/d_net.cpp b/src/d_net.cpp index 00361053a..88b4372fb 100644 --- a/src/d_net.cpp +++ b/src/d_net.cpp @@ -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) diff --git a/src/dobjgc.cpp b/src/dobjgc.cpp index efc6d310e..d9c977670 100644 --- a/src/dobjgc.cpp +++ b/src/dobjgc.cpp @@ -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" diff --git a/src/doomtype.h b/src/doomtype.h index 92717e4c8..30fc1b65a 100644 --- a/src/doomtype.h +++ b/src/doomtype.h @@ -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 { diff --git a/src/dsectoreffect.cpp b/src/dsectoreffect.cpp index 7bc9fc400..5a2760813 100644 --- a/src/dsectoreffect.cpp +++ b/src/dsectoreffect.cpp @@ -29,6 +29,7 @@ #include "r_data/r_interpolate.h" #include "statnums.h" #include "farchive.h" +#include "doomstat.h" IMPLEMENT_CLASS (DSectorEffect) diff --git a/src/dthinker.cpp b/src/dthinker.cpp index c186bb7cc..03f103ca6 100644 --- a/src/dthinker.cpp +++ b/src/dthinker.cpp @@ -39,6 +39,7 @@ #include "i_system.h" #include "doomerrors.h" #include "farchive.h" +#include "d_player.h" static cycle_t ThinkCycles; diff --git a/src/fragglescript/t_cmd.cpp b/src/fragglescript/t_cmd.cpp index 74f366357..0e621119c 100644 --- a/src/fragglescript/t_cmd.cpp +++ b/src/fragglescript/t_cmd.cpp @@ -47,6 +47,7 @@ #include "sc_man.h" #include "g_level.h" #include "r_renderer.h" +#include "d_player.h" //========================================================================== // diff --git a/src/fragglescript/t_func.cpp b/src/fragglescript/t_func.cpp index 8be7f798d..e30c76326 100644 --- a/src/fragglescript/t_func.cpp +++ b/src/fragglescript/t_func.cpp @@ -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"); diff --git a/src/g_doom/a_doommisc.cpp b/src/g_doom/a_doommisc.cpp index 6d64bc6b6..8819270b0 100644 --- a/src/g_doom/a_doommisc.cpp +++ b/src/g_doom/a_doommisc.cpp @@ -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" diff --git a/src/g_game.cpp b/src/g_game.cpp index 865e50c23..5f30af97b 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -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 diff --git a/src/g_heretic/a_hereticmisc.cpp b/src/g_heretic/a_hereticmisc.cpp index 91499bd68..ebcb957e5 100644 --- a/src/g_heretic/a_hereticmisc.cpp +++ b/src/g_heretic/a_hereticmisc.cpp @@ -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" diff --git a/src/g_heretic/a_hereticweaps.cpp b/src/g_heretic/a_hereticweaps.cpp index 619fe7b5a..f51de13e1 100644 --- a/src/g_heretic/a_hereticweaps.cpp +++ b/src/g_heretic/a_hereticweaps.cpp @@ -1077,12 +1077,17 @@ DEFINE_ACTION_FUNCTION(AActor, A_SkullRodStorm) mo = Spawn (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); diff --git a/src/g_hexen/a_hexenmisc.cpp b/src/g_hexen/a_hexenmisc.cpp index 1141f381f..70bc3fb1e 100644 --- a/src/g_hexen/a_hexenmisc.cpp +++ b/src/g_hexen/a_hexenmisc.cpp @@ -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" diff --git a/src/g_level.cpp b/src/g_level.cpp index 55c127266..b33b528cb 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -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" diff --git a/src/g_raven/a_artitele.cpp b/src/g_raven/a_artitele.cpp index da71c31c8..7ae32b573 100644 --- a/src/g_raven/a_artitele.cpp +++ b/src/g_raven/a_artitele.cpp @@ -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"); diff --git a/src/g_raven/a_minotaur.cpp b/src/g_raven/a_minotaur.cpp index 14757c43b..038878204 100644 --- a/src/g_raven/a_minotaur.cpp +++ b/src/g_raven/a_minotaur.cpp @@ -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) diff --git a/src/g_shared/a_artifacts.cpp b/src/g_shared/a_artifacts.cpp index 992e97cef..997f68579 100644 --- a/src/g_shared/a_artifacts.cpp +++ b/src/g_shared/a_artifacts.cpp @@ -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"); diff --git a/src/g_shared/a_decals.cpp b/src/g_shared/a_decals.cpp index 64921d647..ebefcdff0 100644 --- a/src/g_shared/a_decals.cpp +++ b/src/g_shared/a_decals.cpp @@ -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; diff --git a/src/g_shared/a_fastprojectile.cpp b/src/g_shared/a_fastprojectile.cpp index 4f103be57..29a72c23c 100644 --- a/src/g_shared/a_fastprojectile.cpp +++ b/src/g_shared/a_fastprojectile.cpp @@ -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) diff --git a/src/g_shared/a_morph.cpp b/src/g_shared/a_morph.cpp index 2aa52ae4f..eb9f2e300 100644 --- a/src/g_shared/a_morph.cpp +++ b/src/g_shared/a_morph.cpp @@ -13,6 +13,7 @@ #include "g_level.h" #include "farchive.h" #include "p_enemy.h" +#include "d_player.h" static FRandom pr_morphmonst ("MorphMonster"); diff --git a/src/g_shared/a_pickups.cpp b/src/g_shared/a_pickups.cpp index 4a73212aa..32a4167bb 100644 --- a/src/g_shared/a_pickups.cpp +++ b/src/g_shared/a_pickups.cpp @@ -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"); diff --git a/src/g_shared/a_quake.cpp b/src/g_shared/a_quake.cpp index 94a375d3e..eac736f8b 100644 --- a/src/g_shared/a_quake.cpp +++ b/src/g_shared/a_quake.cpp @@ -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"); diff --git a/src/g_shared/a_randomspawner.cpp b/src/g_shared/a_randomspawner.cpp index acadbe6da..42eccacca 100644 --- a/src/g_shared/a_randomspawner.cpp +++ b/src/g_shared/a_randomspawner.cpp @@ -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"); diff --git a/src/g_shared/a_specialspot.cpp b/src/g_shared/a_specialspot.cpp index 2a97949f3..de72787a3 100644 --- a/src/g_shared/a_specialspot.cpp +++ b/src/g_shared/a_specialspot.cpp @@ -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"); diff --git a/src/g_shared/shared_hud.cpp b/src/g_shared/shared_hud.cpp index 349c1e9c5..97204cc63 100644 --- a/src/g_shared/shared_hud.cpp +++ b/src/g_shared/shared_hud.cpp @@ -50,6 +50,8 @@ #include "doomstat.h" #include "g_level.h" #include "d_net.h" +#include "d_player.h" +#include "r_utility.h" #include diff --git a/src/g_strife/a_strifestuff.cpp b/src/g_strife/a_strifestuff.cpp index fc11ba433..724deaee2 100644 --- a/src/g_strife/a_strifestuff.cpp +++ b/src/g_strife/a_strifestuff.cpp @@ -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" diff --git a/src/info.cpp b/src/info.cpp index d827cd7a0..0f3da5d78 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -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(); diff --git a/src/m_bbox.cpp b/src/m_bbox.cpp index c73f47bc4..f7827ef72 100644 --- a/src/m_bbox.cpp +++ b/src/m_bbox.cpp @@ -26,6 +26,7 @@ #include "m_bbox.h" #include "p_local.h" +#include "p_maputl.h" //========================================================================== // diff --git a/src/m_cheat.cpp b/src/m_cheat.cpp index c6bb677b5..aa539f96b 100644 --- a/src/m_cheat.cpp +++ b/src/m_cheat.cpp @@ -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 diff --git a/src/p_3dfloors.cpp b/src/p_3dfloors.cpp index c4a057e63..2938f2d52 100644 --- a/src/p_3dfloors.cpp +++ b/src/p_3dfloors.cpp @@ -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) diff --git a/src/p_3dmidtex.cpp b/src/p_3dmidtex.cpp index 5d5ba56d8..1c4ba7b7c 100644 --- a/src/p_3dmidtex.cpp +++ b/src/p_3dmidtex.cpp @@ -38,6 +38,8 @@ #include "templates.h" #include "p_local.h" #include "p_terrain.h" +#include "p_maputl.h" +#include "p_spec.h" //============================================================================ diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 070111d7b..7155c98e6 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -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" diff --git a/src/p_blockmap.h b/src/p_blockmap.h new file mode 100644 index 000000000..9cbe2e84b --- /dev/null +++ b/src/p_blockmap.h @@ -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 diff --git a/src/p_buildmap.cpp b/src/p_buildmap.cpp index 6705addd6..116c9ff6d 100644 --- a/src/p_buildmap.cpp +++ b/src/p_buildmap.cpp @@ -18,6 +18,7 @@ #include "r_data/colormaps.h" #include "gi.h" #include "portal.h" +#include "p_spec.h" // MACROS ------------------------------------------------------------------ diff --git a/src/p_ceiling.cpp b/src/p_ceiling.cpp index 24ab121c4..bd75fbee2 100644 --- a/src/p_ceiling.cpp +++ b/src/p_ceiling.cpp @@ -30,6 +30,7 @@ #include "r_state.h" #include "gi.h" #include "farchive.h" +#include "p_spec.h" //============================================================================ // diff --git a/src/p_checkposition.h b/src/p_checkposition.h new file mode 100644 index 000000000..6eee5374a --- /dev/null +++ b/src/p_checkposition.h @@ -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 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 LastRipped; + + FPortalGroupArray Groups; + int PushTime; + + FCheckPosition(bool rip=false) + { + DoRipping = rip; + PushTime = 0; + FromPMove = false; + } +}; + + +#endif diff --git a/src/p_doors.cpp b/src/p_doors.cpp index 7ed607e19..16d12be9d 100644 --- a/src/p_doors.cpp +++ b/src/p_doors.cpp @@ -36,6 +36,8 @@ #include "sc_man.h" #include "cmdlib.h" #include "farchive.h" +#include "d_player.h" +#include "p_spec.h" //============================================================================ // diff --git a/src/p_effect.cpp b/src/p_effect.cpp index c02e3a97b..ffd1f303c 100644 --- a/src/p_effect.cpp +++ b/src/p_effect.cpp @@ -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); diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index eaf729771..fed155627 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -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" diff --git a/src/p_floor.cpp b/src/p_floor.cpp index c632e8ba2..d91c05170 100644 --- a/src/p_floor.cpp +++ b/src/p_floor.cpp @@ -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 diff --git a/src/p_glnodes.cpp b/src/p_glnodes.cpp index b8e3eb5c6..ea39844e0 100644 --- a/src/p_glnodes.cpp +++ b/src/p_glnodes.cpp @@ -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 &spots, TArray &anchors); diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index dba66ca9b..98d08832e 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -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"); diff --git a/src/p_lights.cpp b/src/p_lights.cpp index 656b86112..9c5202cdf 100644 --- a/src/p_lights.cpp +++ b/src/p_lights.cpp @@ -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" diff --git a/src/p_linkedsectors.cpp b/src/p_linkedsectors.cpp index b9ef8b100..f1e199b2f 100644 --- a/src/p_linkedsectors.cpp +++ b/src/p_linkedsectors.cpp @@ -36,6 +36,7 @@ #include "templates.h" #include "p_local.h" #include "p_lnspec.h" +#include "p_spec.h" enum { diff --git a/src/p_lnspec.cpp b/src/p_lnspec.cpp index 4e83751fb..3aca74cfe 100644 --- a/src/p_lnspec.cpp +++ b/src/p_lnspec.cpp @@ -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: /* diff --git a/src/p_local.h b/src/p_local.h index 9030a0736..44a430c27 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -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 @@ -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 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 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 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__ diff --git a/src/p_map.cpp b/src/p_map.cpp index 0e3cb6617..b77d6c55a 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -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" diff --git a/src/p_maputl.cpp b/src/p_maputl.cpp index e5bb2bea2..e09c86eb4 100644 --- a/src/p_maputl.cpp +++ b/src/p_maputl.cpp @@ -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 = §or->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; +} + diff --git a/src/p_maputl.h b/src/p_maputl.h new file mode 100644 index 000000000..dbc4eaf9a --- /dev/null +++ b/src/p_maputl.h @@ -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 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 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 \ No newline at end of file diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 658fcbc69..82326c39b 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -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) diff --git a/src/p_plats.cpp b/src/p_plats.cpp index b0697fc34..83d7e101d 100644 --- a/src/p_plats.cpp +++ b/src/p_plats.cpp @@ -31,6 +31,7 @@ #include "r_state.h" #include "gi.h" #include "farchive.h" +#include "p_spec.h" static FRandom pr_doplat ("DoPlat"); diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index a5f8a2948..926df73df 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -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) diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 746e50e40..c5780e912 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -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 diff --git a/src/p_sight.cpp b/src/p_sight.cpp index b007410c8..e92380058 100644 --- a/src/p_sight.cpp +++ b/src/p_sight.cpp @@ -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" diff --git a/src/p_slopes.cpp b/src/p_slopes.cpp index 3e402f73a..bf6f1738c 100644 --- a/src/p_slopes.cpp +++ b/src/p_slopes.cpp @@ -36,6 +36,8 @@ #include "p_local.h" #include "cmdlib.h" #include "p_lnspec.h" +#include "p_maputl.h" +#include "p_spec.h" //=========================================================================== // diff --git a/src/p_spec.cpp b/src/p_spec.cpp index e66049640..fd1484c47 100644 --- a/src/p_spec.cpp +++ b/src/p_spec.cpp @@ -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 diff --git a/src/p_switch.cpp b/src/p_switch.cpp index 1ae0c43ea..0c9d37ccc 100644 --- a/src/p_switch.cpp +++ b/src/p_switch.cpp @@ -47,6 +47,8 @@ #include "tarray.h" #include "cmdlib.h" #include "farchive.h" +#include "p_maputl.h" +#include "p_spec.h" #include "gi.h" diff --git a/src/p_teleport.cpp b/src/p_teleport.cpp index a6dcbf7f3..b7f9c4fd5 100644 --- a/src/p_teleport.cpp +++ b/src/p_teleport.cpp @@ -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 diff --git a/src/p_things.cpp b/src/p_things.cpp index 14ca85aa3..1c8a4a46d 100644 --- a/src/p_things.cpp +++ b/src/p_things.cpp @@ -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; diff --git a/src/p_tick.cpp b/src/p_tick.cpp index 44fe88110..29b2cd4ad 100644 --- a/src/p_tick.cpp +++ b/src/p_tick.cpp @@ -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; diff --git a/src/p_trace.cpp b/src/p_trace.cpp index 619a61361..929f284b1 100644 --- a/src/p_trace.cpp +++ b/src/p_trace.cpp @@ -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 { diff --git a/src/p_user.cpp b/src/p_user.cpp index d5f89576b..529420347 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -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"); diff --git a/src/p_writemap.cpp b/src/p_writemap.cpp index 8f1a4edfa..c442fc0d9 100644 --- a/src/p_writemap.cpp +++ b/src/p_writemap.cpp @@ -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); diff --git a/src/po_man.cpp b/src/po_man.cpp index a0cc4487b..7cfa3cf1b 100644 --- a/src/po_man.cpp +++ b/src/po_man.cpp @@ -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 ------------------------------------------------------------------ diff --git a/src/po_man.h b/src/po_man.h index 9e81cc266..08ac465e3 100644 --- a/src/po_man.h +++ b/src/po_man.h @@ -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 \ No newline at end of file diff --git a/src/portal.cpp b/src/portal.cpp index d9156514d..a525b22f0 100644 --- a/src/portal.cpp +++ b/src/portal.cpp @@ -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 linePortals; +TArray 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 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, §ors[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 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) + diff --git a/src/portal.h b/src/portal.h index 893f3ae69..40c4a30fc 100644 --- a/src/portal.h +++ b/src/portal.h @@ -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 \ No newline at end of file diff --git a/src/r_defs.h b/src/r_defs.h index ab78f9296..920c1f3f8 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -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 diff --git a/src/r_things.cpp b/src/r_things.cpp index 1179c7291..1fb4c845b 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -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. diff --git a/src/r_utility.cpp b/src/r_utility.cpp index 540ab740a..bcba624e1 100644 --- a/src/r_utility.cpp +++ b/src/r_utility.cpp @@ -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) diff --git a/src/s_sndseq.cpp b/src/s_sndseq.cpp index cf2957885..4a5bfa25e 100644 --- a/src/s_sndseq.cpp +++ b/src/s_sndseq.cpp @@ -28,6 +28,7 @@ #include "c_dispatch.h" #include "g_level.h" #include "farchive.h" +#include "d_player.h" // MACROS ------------------------------------------------------------------ diff --git a/src/s_sound.cpp b/src/s_sound.cpp index dabed23f6..e61a0f701 100644 --- a/src/s_sound.cpp +++ b/src/s_sound.cpp @@ -51,6 +51,7 @@ #include "g_level.h" #include "po_man.h" #include "farchive.h" +#include "d_player.h" // MACROS ------------------------------------------------------------------ diff --git a/src/textures/textures.h b/src/textures/textures.h index adec69d9c..36dae7e09 100644 --- a/src/textures/textures.h +++ b/src/textures/textures.h @@ -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: diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index e4744c8b4..4b9bb77de 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -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);