//----------------------------------------------------------------------------- // // Copyright 1993-1996 id Software // Copyright 1994-1996 Raven Software // Copyright 1998-1998 Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman // Copyright 1999-2016 Randy Heit // Copyright 2002-2016 Christoph Oelckers // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see http://www.gnu.org/licenses/ // //----------------------------------------------------------------------------- // // DESCRIPTION: // Play functions, animation, global header. // //----------------------------------------------------------------------------- #ifndef __P_LOCAL__ #define __P_LOCAL__ #include #include "doomtype.h" #include "vectors.h" #include "dobject.h" const double NO_VALUE = FLT_MAX; class player_t; class AActor; struct FPlayerStart; class PClassActor; class APlayerPawn; struct line_t; struct sector_t; struct msecnode_t; struct portnode_t; struct secplane_t; struct FCheckPosition; struct FTranslatedLineTarget; struct FLinePortal; #include #define STEEPSLOPE (46342/65536.) // [RH] Minimum floorplane.c value for walking // Inspired by Maes extern int bmapnegx; extern int bmapnegy; //#define GRAVITY FRACUNIT #define MAXMOVE (30.) #define TALKRANGE (128.) #define USERANGE (64.) #define DEFMELEERANGE (64.) #define SAWRANGE (64.+(1./65536.)) // use meleerange + 1 so the puff doesn't skip the flash (i.e. plays all states) #define MISSILERANGE (32*64.) #define PLAYERMISSILERANGE (8192.) // [RH] New MISSILERANGE for players // follow a player exlusively for 3 seconds // No longer used. // #define BASETHRESHOLD 100 // // P_PSPR // void P_SetupPsprites (player_t* curplayer, bool startweaponup); void P_DropWeapon (player_t* player); // // P_USER // void P_FallingDamage (AActor *ent); void P_PlayerThink (player_t *player); void P_PredictPlayer (player_t *player); void P_UnPredictPlayer (); void P_PredictionLerpReset(); // // P_MOBJ // #define SPF_TEMPPLAYER 1 // spawning a short-lived dummy player #define SPF_WEAPONFULLYUP 2 // spawn with weapon already raised APlayerPawn *P_SpawnPlayer (FPlayerStart *mthing, int playernum, int flags=0); int P_FaceMobj (AActor *source, AActor *target, DAngle *delta); bool P_SeekerMissile (AActor *actor, double thresh, double turnMax, bool precise = false, bool usecurspeed=false); enum EPuffFlags { PF_HITTHING = 1, PF_MELEERANGE = 2, PF_TEMPORARY = 4, PF_HITTHINGBLEED = 8, PF_NORANDOMZ = 16 }; AActor *P_SpawnPuff(AActor *source, PClassActor *pufftype, const DVector3 &pos, DAngle hitdir, DAngle particledir, int updown, int flags = 0, AActor *vict = NULL); void P_SpawnBlood (const DVector3 &pos, DAngle angle, int damage, AActor *originator); void P_BloodSplatter (const DVector3 &pos, AActor *originator, DAngle hitangle); void P_BloodSplatter2 (const DVector3 &pos, AActor *originator, DAngle hitangle); void P_RipperBlood (AActor *mo, AActor *bleeder); int P_GetThingFloorType (AActor *thing); void P_ExplodeMissile (AActor *missile, line_t *explodeline, AActor *target, bool onsky = false); AActor *P_OldSpawnMissile(AActor *source, AActor *owner, AActor *dest, PClassActor *type); AActor *P_SpawnMissile (AActor* source, AActor* dest, PClassActor *type, AActor* owner = NULL); AActor *P_SpawnMissileZ(AActor* source, double z, AActor* dest, PClassActor *type); AActor *P_SpawnMissileXYZ(DVector3 pos, AActor *source, AActor *dest, PClassActor *type, bool checkspawn = true, AActor *owner = NULL); AActor *P_SpawnMissileAngle(AActor *source, PClassActor *type, DAngle angle, double vz); AActor *P_SpawnMissileAngleZ(AActor *source, double z, PClassActor *type, DAngle angle, double vz); AActor *P_SpawnMissileAngleZSpeed(AActor *source, double z, PClassActor *type, DAngle angle, double vz, double speed, AActor *owner = NULL, bool checkspawn = true); AActor *P_SpawnMissileZAimed(AActor *source, double z, AActor *dest, PClassActor *type); AActor *P_SpawnPlayerMissile (AActor* source, PClassActor *type); AActor *P_SpawnPlayerMissile (AActor *source, PClassActor *type, DAngle angle); AActor *P_SpawnPlayerMissile (AActor *source, double x, double y, double z, PClassActor *type, DAngle angle, FTranslatedLineTarget *pLineTarget = NULL, AActor **MissileActor = NULL, bool nofreeaim = false, bool noautoaim = false, int aimflags = 0); void P_CheckFakeFloorTriggers(AActor *mo, double oldz, bool oldz_has_viewheight = false); AActor *P_SpawnSubMissile (AActor *source, PClassActor *type, AActor *target); // Strife uses it // // [RH] P_THINGS // extern FClassMap SpawnableThings; extern FClassMap StrifeTypes; bool P_Thing_Spawn (int tid, AActor *source, int type, DAngle angle, bool fog, int newtid); bool P_Thing_Projectile (int tid, AActor *source, int type, const char * type_name, DAngle angle, double speed, double vspeed, int dest, AActor *forcedest, int gravity, int newtid, bool leadTarget); bool P_MoveThing(AActor *source, const DVector3 &pos, bool fog); bool P_Thing_Move (int tid, AActor *source, int mapspot, bool fog); int P_Thing_Damage (int tid, AActor *whofor0, int amount, FName type); void P_Thing_SetVelocity(AActor *actor, const DVector3 &vec, bool add, bool setbob); void P_RemoveThing(AActor * actor); bool P_Thing_Raise(AActor *thing, AActor *raiser, int nocheck = false); bool P_Thing_CanRaise(AActor *thing); PClassActor *P_GetSpawnableType(int spawnnum); void InitSpawnablesFromMapinfo(); int P_Thing_CheckInputNum(player_t *p, int inputnum); int P_Thing_Warp(AActor *caller, AActor *reference, double xofs, double yofs, double zofs, DAngle angle, int flags, double heightoffset, double radiusoffset, DAngle pitch); int P_Thing_CheckProximity(AActor *self, PClass *classname, double distance, int count, int flags, int ptr, bool counting = false); enum { // These are the original inputs sent by the player. INPUT_OLDBUTTONS, INPUT_BUTTONS, INPUT_PITCH, INPUT_YAW, INPUT_ROLL, INPUT_FORWARDMOVE, INPUT_SIDEMOVE, INPUT_UPMOVE, // These are the inputs, as modified by P_PlayerThink(). // Most of the time, these will match the original inputs, but // they can be different if a player is frozen or using a // chainsaw. MODINPUT_OLDBUTTONS, MODINPUT_BUTTONS, MODINPUT_PITCH, MODINPUT_YAW, MODINPUT_ROLL, MODINPUT_FORWARDMOVE, MODINPUT_SIDEMOVE, MODINPUT_UPMOVE }; enum CPXF { CPXF_ANCESTOR = 1 << 0, CPXF_LESSOREQUAL = 1 << 1, CPXF_NOZ = 1 << 2, CPXF_COUNTDEAD = 1 << 3, CPXF_DEADONLY = 1 << 4, CPXF_EXACT = 1 << 5, CPXF_SETTARGET = 1 << 6, CPXF_SETMASTER = 1 << 7, CPXF_SETTRACER = 1 << 8, CPXF_FARTHEST = 1 << 9, CPXF_CLOSEST = 1 << 10, CPXF_SETONPTR = 1 << 11, CPXF_CHECKSIGHT = 1 << 12, }; enum WARPF { WARPF_ABSOLUTEOFFSET = 0x1, WARPF_ABSOLUTEANGLE = 0x2, WARPF_USECALLERANGLE = 0x4, WARPF_NOCHECKPOSITION = 0x8, WARPF_INTERPOLATE = 0x10, WARPF_WARPINTERPOLATION = 0x20, WARPF_COPYINTERPOLATION = 0x40, WARPF_STOP = 0x80, WARPF_TOFLOOR = 0x100, WARPF_TESTONLY = 0x200, WARPF_ABSOLUTEPOSITION = 0x400, WARPF_BOB = 0x800, WARPF_MOVEPTR = 0x1000, WARPF_USEPTR = 0x2000, WARPF_USETID = 0x2000, WARPF_COPYVELOCITY = 0x4000, WARPF_COPYPITCH = 0x8000, }; enum PCM { PCM_DROPOFF = 1, PCM_NOACTORS = 1 << 1, PCM_NOLINES = 1 << 2, }; 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, bool frontonly = false); // // P_MAP // struct spechit_t { line_t *line; DVector2 Oldrefpos; DVector2 Refpos; }; extern TArray spechit; extern TArray portalhit; bool P_TestMobjLocation (AActor *mobj); bool P_TestMobjZ (AActor *mobj, bool quick=true, AActor **pOnmobj = NULL); bool P_CheckPosition(AActor *thing, const DVector2 &pos, bool actorsonly = false); bool P_CheckPosition(AActor *thing, const DVector2 &pos, FCheckPosition &tm, bool actorsonly = false); AActor *P_CheckOnmobj (AActor *thing); void P_FakeZMovement (AActor *mo); bool P_TryMove(AActor* thing, const DVector2 &pos, int dropoff, const secplane_t * onfloor, FCheckPosition &tm, bool missileCheck = false); bool P_TryMove(AActor* thing, const DVector2 &pos, int dropoff, const secplane_t * onfloor = NULL, bool missilecheck = false); bool P_CheckMove(AActor *thing, const DVector2 &pos, int flags = 0); void P_ApplyTorque(AActor *mo); bool P_TeleportMove(AActor* thing, const DVector3 &pos, bool telefrag, bool modifyactor = true); // [RH] Added z and telefrag parameters void P_PlayerStartStomp (AActor *actor, bool mononly=false); // [RH] Stomp on things for a newly spawned player void P_SlideMove (AActor* mo, const DVector2 &pos, int numsteps); bool P_BounceWall (AActor *mo); bool P_BounceActor (AActor *mo, AActor *BlockingMobj, bool ontop); bool P_CheckSight (AActor *t1, AActor *t2, int flags=0); enum ESightFlags { SF_IGNOREVISIBILITY=1, SF_SEEPASTSHOOTABLELINES=2, SF_SEEPASTBLOCKEVERYTHING=4, SF_IGNOREWATERBOUNDARY=8 }; void P_ResetSightCounters (bool full); bool P_TalkFacing (AActor *player); void P_UseLines (player_t* player); bool P_UsePuzzleItem (AActor *actor, int itemType); enum { FFCF_ONLYSPAWNPOS = 1, FFCF_SAMESECTOR = 2, FFCF_ONLY3DFLOORS = 4, // includes 3D midtexes FFCF_3DRESTRICT = 8, // ignore 3D midtexes and floors whose floorz are above thing's z FFCF_NOPORTALS = 16, // ignore portals (considers them impassable.) FFCF_NOFLOOR = 32, FFCF_NOCEILING = 64, FFCF_RESTRICTEDPORTAL = 128, // current values in the iterator's return are through a restricted portal type (i.e. some features are blocked.) FFCF_NODROPOFF = 256, // Caller does not need a dropoff (saves some time when checking portals) }; void P_FindFloorCeiling (AActor *actor, int flags=0); bool P_ChangeSector (sector_t* sector, int crunch, double amt, int floorOrCeil, bool isreset, bool instant = false); DAngle P_AimLineAttack(AActor *t1, DAngle angle, double distance, FTranslatedLineTarget *pLineTarget = NULL, DAngle vrange = 0., int flags = 0, AActor *target = NULL, AActor *friender = NULL); enum // P_AimLineAttack flags { ALF_FORCENOSMART = 1, ALF_CHECK3D = 2, ALF_CHECKNONSHOOTABLE = 4, ALF_CHECKCONVERSATION = 8, ALF_NOFRIENDS = 16, ALF_PORTALRESTRICT = 32, // only work through portals with a global offset (to be used for stuff that cannot remember the calculated FTranslatedLineTarget info) }; enum // P_LineAttack flags { LAF_ISMELEEATTACK = 1, LAF_NORANDOMPUFFZ = 1 << 1, LAF_NOIMPACTDECAL = 1 << 2, LAF_NOINTERACT = 1 << 3, LAF_TARGETISSOURCE= 1 << 4, LAF_OVERRIDEZ = 1 << 5, LAF_ABSOFFSET = 1 << 6, LAF_ABSPOSITION = 1 << 7, }; AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, DAngle pitch, int damage, FName damageType, PClassActor *pufftype, int flags = 0, FTranslatedLineTarget *victim = NULL, int *actualdamage = NULL, double sz = 0.0, double offsetforward = 0.0, double offsetside = 0.0); AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, DAngle pitch, int damage, FName damageType, FName pufftype, int flags = 0, FTranslatedLineTarget *victim = NULL, int *actualdamage = NULL, double sz = 0.0, double offsetforward = 0.0, double offsetside = 0.0); enum // P_LineTrace flags { TRF_ABSPOSITION = 1, TRF_ABSOFFSET = 2, TRF_THRUSPECIES = 4, TRF_THRUACTORS = 8, TRF_THRUBLOCK = 16, TRF_THRUHITSCAN = 32, TRF_NOSKY = 64, TRF_ALLACTORS = 128, TRF_SOLIDACTORS = 256, TRF_BLOCKUSE = 512, TRF_BLOCKSELF = 1024, }; void P_TraceBleed(int damage, const DVector3 &pos, AActor *target, DAngle angle, DAngle pitch); void P_TraceBleed(int damage, AActor *target, DAngle angle, DAngle pitch); void P_TraceBleed (int damage, AActor *target, AActor *missile); // missile version void P_TraceBleed(int damage, FTranslatedLineTarget *t, AActor *puff); // hitscan version void P_TraceBleed (int damage, AActor *target); // random direction version bool P_HitFloor (AActor *thing); bool P_HitWater (AActor *thing, sector_t *sec, const DVector3 &pos, bool checkabove = false, bool alert = true, bool force = false); void P_CheckSplash(AActor *self, double distance); struct FRailParams { AActor *source = nullptr; int damage = 0; double offset_xy = 0; double offset_z = 0; int color1 = 0, color2 = 0; double maxdiff = 0; int flags = 0; PClassActor *puff = nullptr; DAngle angleoffset = 0.; DAngle pitchoffset = 0.; double distance = 8192; int duration = 0; double sparsity = 1.0; double drift = 1.0; PClassActor *spawnclass = nullptr; int SpiralOffset = 270; int limit = 0; }; // [RH] Shoot a railgun void P_RailAttack(FRailParams *params); enum // P_RailAttack / A_RailAttack / A_CustomRailgun / P_DrawRailTrail flags { RAF_SILENT = 1, RAF_NOPIERCE = 2, RAF_EXPLICITANGLE = 4, RAF_FULLBRIGHT = 8, RAF_CENTERZ = 16, RAF_NORANDOMPUFFZ = 32, }; bool P_CheckMissileSpawn(AActor *missile, double maxdist); void P_PlaySpawnSound(AActor *missile, AActor *spawner); // [RH] Position the chasecam void P_AimCamera (AActor *t1, DVector3 &, DAngle &, sector_t *&sec, bool &unlinked); // [RH] Means of death enum { RADF_HURTSOURCE = 1, RADF_NOIMPACTDAMAGE = 2, RADF_SOURCEISSPOT = 4, RADF_NODAMAGE = 8, RADF_THRUSTZ = 16, }; int P_RadiusAttack (AActor *spot, AActor *source, int damage, int distance, FName damageType, int flags, int fulldamagedistance=0); void P_DelSeclist(msecnode_t *, msecnode_t *sector_t::*seclisthead); void P_DelSeclist(portnode_t *, portnode_t *FLinePortal::*seclisthead); template nodetype *P_AddSecnode(linktype *s, AActor *thing, nodetype *nextnode, nodetype *&sec_thinglist); template nodetype* P_DelSecnode(nodetype *, nodetype *linktype::*head); msecnode_t *P_CreateSecNodeList(AActor *thing, double radius, msecnode_t *sector_list, msecnode_t *sector_t::*seclisthead); double P_GetMoveFactor(const AActor *mo, double *frictionp); // phares 3/6/98 double P_GetFriction(const AActor *mo, double *frictionfactor); // [RH] const secplane_t * P_CheckSlopeWalk(AActor *actor, DVector2 &move); // // P_INTER // void P_TouchSpecialThing (AActor *special, AActor *toucher); int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, FName mod, int flags=0, DAngle angle = 0.); void P_PoisonMobj (AActor *target, AActor *inflictor, AActor *source, int damage, int duration, int period, FName type); bool P_GiveBody (AActor *actor, int num, int max=0); bool P_PoisonPlayer (player_t *player, AActor *poisoner, AActor *source, int poison); void P_PoisonDamage (player_t *player, AActor *source, int damage, bool playPainSound); enum EDmgFlags { DMG_NO_ARMOR = 1, DMG_INFLICTOR_IS_PUFF = 2, DMG_THRUSTLESS = 4, DMG_FORCED = 8, DMG_NO_FACTOR = 16, DMG_PLAYERATTACK = 32, DMG_FOILINVUL = 64, DMG_FOILBUDDHA = 128, DMG_NO_PROTECT = 256, DMG_USEANGLE = 512, DMG_NO_PAIN = 1024, DMG_EXPLOSION = 2048, }; // // P_SPEC // bool P_AlignFlat (int linenum, int side, int fc); enum ETexReplaceFlags { NOT_BOTTOM = 1, NOT_MIDDLE = 2, NOT_TOP = 4, NOT_FLOOR = 8, NOT_CEILING = 16 }; void P_ReplaceTextures(const char *fromname, const char *toname, int flags); #endif // __P_LOCAL__