mirror of
https://github.com/ZDoom/qzdoom-gpl.git
synced 2024-12-02 08:22:25 +00:00
62ea83a35a
This is mostly a straight refactoring of the existing code to work independently of specific member variables in the involved classes, using a bit of template magic to avoid redundancy and moving the work code into subfunctions. It still needs some testing to see if it a) helps fix the crash issues and b) doesn't break anything-
446 lines
14 KiB
C++
446 lines
14 KiB
C++
// Emacs style mode select -*- C++ -*-
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// $Id:$
|
|
//
|
|
// Copyright (C) 1993-1996 by id Software, Inc.
|
|
//
|
|
// This source is available for distribution and/or modification
|
|
// only under the terms of the DOOM Source Code License as
|
|
// published by id Software. All rights reserved.
|
|
//
|
|
// The source is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
|
// for more details.
|
|
//
|
|
// DESCRIPTION:
|
|
// Play functions, animation, global header.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
#ifndef __P_LOCAL__
|
|
#define __P_LOCAL__
|
|
|
|
#include <float.h>
|
|
#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 <stdlib.h>
|
|
|
|
#define STEEPSLOPE (46342/65536.) // [RH] Minimum floorplane.c value for walking
|
|
|
|
#define BONUSADD 6
|
|
|
|
// 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);
|
|
|
|
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);
|
|
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_t> spechit;
|
|
extern TArray<spechit_t> 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 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 = 2,
|
|
LAF_NOIMPACTDECAL = 4,
|
|
LAF_NOINTERACT = 8,
|
|
LAF_TARGETISSOURCE = 16,
|
|
};
|
|
|
|
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);
|
|
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);
|
|
|
|
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<class nodetype, class linktype>
|
|
nodetype *P_AddSecnode(linktype *s, AActor *thing, nodetype *nextnode, nodetype *&sec_thinglist);
|
|
|
|
template<class nodetype, class linktype>
|
|
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_SETUP
|
|
//
|
|
extern BYTE* rejectmatrix; // for fast sight rejection
|
|
|
|
|
|
|
|
//
|
|
// 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,
|
|
};
|
|
|
|
|
|
//
|
|
// P_SPEC
|
|
//
|
|
bool P_AlignFlat (int linenum, int side, int fc);
|
|
|
|
#endif // __P_LOCAL__
|