Moved modified HL SDK to trunk
This commit is contained in:
322
hlsdk/pm_shared/pm_debug.c
Normal file
322
hlsdk/pm_shared/pm_debug.c
Normal file
@ -0,0 +1,322 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
|
||||
#include "mathlib.h"
|
||||
#include "const.h"
|
||||
#include "usercmd.h"
|
||||
#include "pm_defs.h"
|
||||
#include "pm_shared.h"
|
||||
#include "pm_movevars.h"
|
||||
#include "pm_debug.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4244)
|
||||
#pragma warning(disable : 4305)
|
||||
#endif
|
||||
|
||||
extern playermove_t *pmove;
|
||||
|
||||
// Expand debugging BBOX particle hulls by this many units.
|
||||
#define BOX_GAP 0.0f
|
||||
|
||||
static int PM_boxpnt[6][4] =
|
||||
{
|
||||
{ 0, 4, 6, 2 }, // +X
|
||||
{ 0, 1, 5, 4 }, // +Y
|
||||
{ 0, 2, 3, 1 }, // +Z
|
||||
{ 7, 5, 1, 3 }, // -X
|
||||
{ 7, 3, 2, 6 }, // -Y
|
||||
{ 7, 6, 4, 5 }, // -Z
|
||||
};
|
||||
|
||||
void PM_ShowClipBox( void )
|
||||
{
|
||||
#if defined( _DEBUG )
|
||||
vec3_t org;
|
||||
vec3_t offset = { 0, 0, 0 };
|
||||
|
||||
if ( !pmove->runfuncs )
|
||||
return;
|
||||
|
||||
// More debugging, draw the particle bbox for player and for the entity we are looking directly at.
|
||||
// aslo prints entity info to the console overlay.
|
||||
//if ( !pmove->server )
|
||||
// return;
|
||||
|
||||
// Draw entity in center of view
|
||||
// Also draws the normal to the clip plane that intersects our movement ray. Leaves a particle
|
||||
// trail at the intersection point.
|
||||
PM_ViewEntity();
|
||||
|
||||
VectorCopy( pmove->origin, org );
|
||||
|
||||
if ( pmove->server )
|
||||
{
|
||||
VectorAdd( org, offset, org );
|
||||
}
|
||||
else
|
||||
{
|
||||
VectorSubtract( org, offset, org );
|
||||
}
|
||||
|
||||
// Show our BBOX in particles.
|
||||
PM_DrawBBox( pmove->player_mins[pmove->usehull], pmove->player_maxs[pmove->usehull], org, pmove->server ? 132 : 0, 0.1 );
|
||||
|
||||
PM_ParticleLine( org, org, pmove->server ? 132 : 0, 0.1, 5.0 );
|
||||
/*
|
||||
{
|
||||
int i;
|
||||
for ( i = 0; i < pmove->numphysent; i++ )
|
||||
{
|
||||
if ( pmove->physents[ i ].info >= 1 && pmove->physents[ i ].info <= 4 )
|
||||
{
|
||||
PM_DrawBBox( pmove->player_mins[pmove->usehull], pmove->player_maxs[pmove->usehull], pmove->physents[i].origin, 132, 0.1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
PM_ParticleLine(vec3_t start, vec3_t end, int color, float life)
|
||||
|
||||
================
|
||||
*/
|
||||
void PM_ParticleLine(vec3_t start, vec3_t end, int pcolor, float life, float vert)
|
||||
{
|
||||
float linestep = 2.0f;
|
||||
float curdist;
|
||||
float len;
|
||||
vec3_t curpos;
|
||||
vec3_t diff;
|
||||
int i;
|
||||
// Determine distance;
|
||||
|
||||
VectorSubtract(end, start, diff);
|
||||
|
||||
len = VectorNormalize(diff);
|
||||
|
||||
curdist = 0;
|
||||
while (curdist <= len)
|
||||
{
|
||||
for (i = 0; i < 3; i++)
|
||||
curpos[i] = start[i] + curdist * diff[i];
|
||||
|
||||
pmove->PM_Particle( curpos, pcolor, life, 0, vert);
|
||||
curdist += linestep;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
PM_DrawRectangle(vec3_t tl, vec3_t br)
|
||||
|
||||
================
|
||||
*/
|
||||
void PM_DrawRectangle(vec3_t tl, vec3_t bl, vec3_t tr, vec3_t br, int pcolor, float life)
|
||||
{
|
||||
PM_ParticleLine(tl, bl, pcolor, life, 0);
|
||||
PM_ParticleLine(bl, br, pcolor, life, 0);
|
||||
PM_ParticleLine(br, tr, pcolor, life, 0);
|
||||
PM_ParticleLine(tr, tl, pcolor, life, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
PM_DrawPhysEntBBox(int num)
|
||||
|
||||
================
|
||||
*/
|
||||
void PM_DrawPhysEntBBox(int num, int pcolor, float life)
|
||||
{
|
||||
physent_t *pe;
|
||||
vec3_t org;
|
||||
int j;
|
||||
vec3_t tmp;
|
||||
vec3_t p[8];
|
||||
float gap = BOX_GAP;
|
||||
vec3_t modelmins, modelmaxs;
|
||||
|
||||
if (num >= pmove->numphysent ||
|
||||
num <= 0)
|
||||
return;
|
||||
|
||||
pe = &pmove->physents[num];
|
||||
|
||||
if (pe->model)
|
||||
{
|
||||
VectorCopy(pe->origin, org);
|
||||
|
||||
pmove->PM_GetModelBounds( pe->model, modelmins, modelmaxs );
|
||||
for (j = 0; j < 8; j++)
|
||||
{
|
||||
tmp[0] = (j & 1) ? modelmins[0] - gap : modelmaxs[0] + gap;
|
||||
tmp[1] = (j & 2) ? modelmins[1] - gap : modelmaxs[1] + gap;
|
||||
tmp[2] = (j & 4) ? modelmins[2] - gap : modelmaxs[2] + gap;
|
||||
|
||||
VectorCopy(tmp, p[j]);
|
||||
}
|
||||
|
||||
// If the bbox should be rotated, do that
|
||||
if (pe->angles[0] || pe->angles[1] || pe->angles[2])
|
||||
{
|
||||
vec3_t forward, right, up;
|
||||
|
||||
AngleVectorsTranspose(pe->angles, forward, right, up);
|
||||
for (j = 0; j < 8; j++)
|
||||
{
|
||||
VectorCopy(p[j], tmp);
|
||||
p[j][0] = DotProduct ( tmp, forward );
|
||||
p[j][1] = DotProduct ( tmp, right );
|
||||
p[j][2] = DotProduct ( tmp, up );
|
||||
}
|
||||
}
|
||||
|
||||
// Offset by entity origin, if any.
|
||||
for (j = 0; j < 8; j++)
|
||||
VectorAdd(p[j], org, p[j]);
|
||||
|
||||
for (j = 0; j < 6; j++)
|
||||
{
|
||||
PM_DrawRectangle(
|
||||
p[PM_boxpnt[j][1]],
|
||||
p[PM_boxpnt[j][0]],
|
||||
p[PM_boxpnt[j][2]],
|
||||
p[PM_boxpnt[j][3]],
|
||||
pcolor, life);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (j = 0; j < 8; j++)
|
||||
{
|
||||
tmp[0] = (j & 1) ? pe->mins[0] : pe->maxs[0];
|
||||
tmp[1] = (j & 2) ? pe->mins[1] : pe->maxs[1];
|
||||
tmp[2] = (j & 4) ? pe->mins[2] : pe->maxs[2];
|
||||
|
||||
VectorAdd(tmp, pe->origin, tmp);
|
||||
VectorCopy(tmp, p[j]);
|
||||
}
|
||||
|
||||
for (j = 0; j < 6; j++)
|
||||
{
|
||||
PM_DrawRectangle(
|
||||
p[PM_boxpnt[j][1]],
|
||||
p[PM_boxpnt[j][0]],
|
||||
p[PM_boxpnt[j][2]],
|
||||
p[PM_boxpnt[j][3]],
|
||||
pcolor, life);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
PM_DrawBBox(vec3_t mins, vec3_t maxs, vec3_t origin, int pcolor, float life)
|
||||
|
||||
================
|
||||
*/
|
||||
void PM_DrawBBox(vec3_t mins, vec3_t maxs, vec3_t origin, int pcolor, float life)
|
||||
{
|
||||
int j;
|
||||
|
||||
vec3_t tmp;
|
||||
vec3_t p[8];
|
||||
float gap = BOX_GAP;
|
||||
|
||||
for (j = 0; j < 8; j++)
|
||||
{
|
||||
tmp[0] = (j & 1) ? mins[0] - gap : maxs[0] + gap;
|
||||
tmp[1] = (j & 2) ? mins[1] - gap : maxs[1] + gap ;
|
||||
tmp[2] = (j & 4) ? mins[2] - gap : maxs[2] + gap ;
|
||||
|
||||
VectorAdd(tmp, origin, tmp);
|
||||
VectorCopy(tmp, p[j]);
|
||||
}
|
||||
|
||||
for (j = 0; j < 6; j++)
|
||||
{
|
||||
PM_DrawRectangle(
|
||||
p[PM_boxpnt[j][1]],
|
||||
p[PM_boxpnt[j][0]],
|
||||
p[PM_boxpnt[j][2]],
|
||||
p[PM_boxpnt[j][3]],
|
||||
pcolor, life);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifndef DEDICATED
|
||||
|
||||
/*
|
||||
================
|
||||
PM_ViewEntity
|
||||
|
||||
Shows a particle trail from player to entity in crosshair.
|
||||
Shows particles at that entities bbox
|
||||
|
||||
Tries to shoot a ray out by about 128 units.
|
||||
================
|
||||
*/
|
||||
void PM_ViewEntity( void )
|
||||
{
|
||||
vec3_t forward, right, up;
|
||||
float raydist = 256.0f;
|
||||
vec3_t origin;
|
||||
vec3_t end;
|
||||
int i;
|
||||
pmtrace_t trace;
|
||||
int pcolor = 77;
|
||||
float fup;
|
||||
|
||||
#if 0
|
||||
if ( !pm_showclip.value )
|
||||
return;
|
||||
#endif
|
||||
|
||||
AngleVectors (pmove->angles, forward, right, up); // Determine movement angles
|
||||
|
||||
VectorCopy( pmove->origin, origin);
|
||||
|
||||
fup = 0.5*( pmove->player_mins[pmove->usehull][2] + pmove->player_maxs[pmove->usehull][2] );
|
||||
fup += pmove->view_ofs[2];
|
||||
fup -= 4;
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
end[i] = origin[i] + raydist * forward[i];
|
||||
}
|
||||
|
||||
trace = pmove->PM_PlayerTrace( origin, end, PM_STUDIO_BOX, -1 );
|
||||
|
||||
if (trace.ent > 0) // Not the world
|
||||
{
|
||||
pcolor = 111;
|
||||
}
|
||||
|
||||
// Draw the hull or bbox.
|
||||
if (trace.ent > 0)
|
||||
{
|
||||
PM_DrawPhysEntBBox(trace.ent, pcolor, 0.3f);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
28
hlsdk/pm_shared/pm_debug.h
Normal file
28
hlsdk/pm_shared/pm_debug.h
Normal file
@ -0,0 +1,28 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
#ifndef PM_DEBUG_H
|
||||
#define PM_DEBUG_H
|
||||
#ifdef _WIN32
|
||||
#ifndef __MINGW32__
|
||||
#pragma once
|
||||
#endif /* not __MINGW32__ */
|
||||
#endif
|
||||
|
||||
void PM_ViewEntity( void );
|
||||
void PM_DrawBBox(vec3_t mins, vec3_t maxs, vec3_t origin, int pcolor, float life);
|
||||
void PM_ParticleLine(vec3_t start, vec3_t end, int pcolor, float life, float vert);
|
||||
void PM_ShowClipBox( void );
|
||||
|
||||
#endif // PMOVEDBG_H
|
266
hlsdk/pm_shared/pm_defs.h
Normal file
266
hlsdk/pm_shared/pm_defs.h
Normal file
@ -0,0 +1,266 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
// pm_defs.h
|
||||
#if !defined( PM_DEFSH )
|
||||
#define PM_DEFSH
|
||||
#ifdef _WIN32
|
||||
#ifndef __MINGW32__
|
||||
#pragma once
|
||||
#endif /* not __MINGW32__ */
|
||||
#endif
|
||||
|
||||
#define MAX_PHYSENTS 600 // Must have room for all entities in the world.
|
||||
#define MAX_MOVEENTS 64
|
||||
#define MAX_CLIP_PLANES 5
|
||||
|
||||
#define PM_NORMAL 0x00000000
|
||||
#define PM_STUDIO_IGNORE 0x00000001 // Skip studio models
|
||||
#define PM_STUDIO_BOX 0x00000002 // Use boxes for non-complex studio models (even in traceline)
|
||||
#define PM_GLASS_IGNORE 0x00000004 // Ignore entities with non-normal rendermode
|
||||
#define PM_WORLD_ONLY 0x00000008 // Only trace against the world
|
||||
|
||||
// Values for flags parameter of PM_TraceLine
|
||||
#define PM_TRACELINE_PHYSENTSONLY 0
|
||||
#define PM_TRACELINE_ANYVISIBLE 1
|
||||
|
||||
#if defined _MSC_VER && _MSC_VER >= 1400
|
||||
#ifndef _CRT_SECURE_NO_DEPRECATE
|
||||
#define _CRT_SECURE_NO_DEPRECATE
|
||||
#endif
|
||||
|
||||
#pragma warning(disable: 4996) // deprecated functions
|
||||
#endif
|
||||
|
||||
#include "pm_info.h"
|
||||
|
||||
// PM_PlayerTrace results.
|
||||
#include "pmtrace.h"
|
||||
|
||||
#if !defined ( USERCMD_H )
|
||||
#include "usercmd.h"
|
||||
#endif
|
||||
|
||||
// physent_t
|
||||
typedef struct physent_s
|
||||
{
|
||||
char name[32]; // Name of model, or "player" or "world".
|
||||
int player;
|
||||
vec3_t origin; // Model's origin in world coordinates.
|
||||
struct model_s *model; // only for bsp models
|
||||
struct model_s *studiomodel; // SOLID_BBOX, but studio clip intersections.
|
||||
vec3_t mins, maxs; // only for non-bsp models
|
||||
int info; // For client or server to use to identify (index into edicts or cl_entities)
|
||||
vec3_t angles; // rotated entities need this info for hull testing to work.
|
||||
|
||||
int solid; // Triggers and func_door type WATER brushes are SOLID_NOT
|
||||
int skin; // BSP Contents for such things like fun_door water brushes.
|
||||
int rendermode; // So we can ignore glass
|
||||
|
||||
// Complex collision detection.
|
||||
float frame;
|
||||
int sequence;
|
||||
byte controller[4];
|
||||
byte blending[2];
|
||||
|
||||
int movetype;
|
||||
int takedamage;
|
||||
int blooddecal;
|
||||
int team;
|
||||
int classnumber;
|
||||
|
||||
// For mods
|
||||
int iuser1;
|
||||
int iuser2;
|
||||
int iuser3;
|
||||
int iuser4;
|
||||
float fuser1;
|
||||
float fuser2;
|
||||
float fuser3;
|
||||
float fuser4;
|
||||
vec3_t vuser1;
|
||||
vec3_t vuser2;
|
||||
vec3_t vuser3;
|
||||
vec3_t vuser4;
|
||||
} physent_t;
|
||||
|
||||
#ifndef _DCLIPNODE_DEFINED_
|
||||
#define _DCLIPNODE_DEFINED_
|
||||
typedef struct
|
||||
{
|
||||
int planenum;
|
||||
short children[2]; // negative numbers are contents
|
||||
} dclipnode_t;
|
||||
#endif
|
||||
|
||||
#ifndef _MPLANE_DEFINED_
|
||||
#define _MPLANE_DEFINED_
|
||||
typedef struct mplane_s
|
||||
{
|
||||
vec3_t normal; // surface normal
|
||||
float dist; // closest appoach to origin
|
||||
byte type; // for texture axis selection and fast side tests
|
||||
byte signbits; // signx + signy<<1 + signz<<1
|
||||
byte pad[2];
|
||||
} mplane_t;
|
||||
#endif
|
||||
|
||||
#ifndef _HULL_DEFINED_
|
||||
#define _HULL_DEFINED_
|
||||
typedef struct hull_s
|
||||
{
|
||||
dclipnode_t *clipnodes;
|
||||
mplane_t *planes;
|
||||
int firstclipnode;
|
||||
int lastclipnode;
|
||||
vec3_t clip_mins;
|
||||
vec3_t clip_maxs;
|
||||
} hull_t;
|
||||
#endif
|
||||
|
||||
typedef struct playermove_s
|
||||
{
|
||||
int player_index; // So we don't try to run the PM_CheckStuck nudging too quickly.
|
||||
qboolean server; // For debugging, are we running physics code on server side?
|
||||
|
||||
qboolean multiplayer; // 1 == multiplayer server
|
||||
float time; // realtime on host, for reckoning duck timing
|
||||
float frametime; // Duration of this frame
|
||||
|
||||
vec3_t forward, right, up; // Vectors for angles
|
||||
// player state
|
||||
vec3_t origin; // Movement origin.
|
||||
vec3_t angles; // Movement view angles.
|
||||
vec3_t oldangles; // Angles before movement view angles were looked at.
|
||||
vec3_t velocity; // Current movement direction.
|
||||
vec3_t movedir; // For waterjumping, a forced forward velocity so we can fly over lip of ledge.
|
||||
vec3_t basevelocity; // Velocity of the conveyor we are standing, e.g.
|
||||
|
||||
// For ducking/dead
|
||||
vec3_t view_ofs; // Our eye position.
|
||||
float flDuckTime; // Time we started duck
|
||||
qboolean bInDuck; // In process of ducking or ducked already?
|
||||
|
||||
// For walking/falling
|
||||
int flTimeStepSound; // Next time we can play a step sound
|
||||
int iStepLeft;
|
||||
|
||||
float flFallVelocity;
|
||||
vec3_t punchangle;
|
||||
|
||||
float flSwimTime;
|
||||
|
||||
float flNextPrimaryAttack;
|
||||
|
||||
int effects; // MUZZLE FLASH, e.g.
|
||||
|
||||
int flags; // FL_ONGROUND, FL_DUCKING, etc.
|
||||
int usehull; // 0 = regular player hull, 1 = ducked player hull, 2 = point hull
|
||||
float gravity; // Our current gravity and friction.
|
||||
float friction;
|
||||
int oldbuttons; // Buttons last usercmd
|
||||
float waterjumptime; // Amount of time left in jumping out of water cycle.
|
||||
qboolean dead; // Are we a dead player?
|
||||
int deadflag;
|
||||
int spectator; // Should we use spectator physics model?
|
||||
int movetype; // Our movement type, NOCLIP, WALK, FLY
|
||||
|
||||
int onground;
|
||||
int waterlevel;
|
||||
int watertype;
|
||||
int oldwaterlevel;
|
||||
|
||||
char sztexturename[256];
|
||||
char chtexturetype;
|
||||
|
||||
float maxspeed;
|
||||
float clientmaxspeed; // Player specific maxspeed
|
||||
|
||||
// For mods
|
||||
int iuser1;
|
||||
int iuser2;
|
||||
int iuser3;
|
||||
int iuser4;
|
||||
float fuser1;
|
||||
float fuser2;
|
||||
float fuser3;
|
||||
float fuser4;
|
||||
vec3_t vuser1;
|
||||
vec3_t vuser2;
|
||||
vec3_t vuser3;
|
||||
vec3_t vuser4;
|
||||
// world state
|
||||
// Number of entities to clip against.
|
||||
int numphysent;
|
||||
physent_t physents[MAX_PHYSENTS];
|
||||
// Number of momvement entities (ladders)
|
||||
int nummoveent;
|
||||
// just a list of ladders
|
||||
physent_t moveents[MAX_MOVEENTS];
|
||||
|
||||
// All things being rendered, for tracing against things you don't actually collide with
|
||||
int numvisent;
|
||||
physent_t visents[ MAX_PHYSENTS ];
|
||||
|
||||
// input to run through physics.
|
||||
usercmd_t cmd;
|
||||
|
||||
// Trace results for objects we collided with.
|
||||
int numtouch;
|
||||
pmtrace_t touchindex[MAX_PHYSENTS];
|
||||
|
||||
char physinfo[ MAX_PHYSINFO_STRING ]; // Physics info string
|
||||
|
||||
struct movevars_s *movevars;
|
||||
vec3_t player_mins[ 4 ];
|
||||
vec3_t player_maxs[ 4 ];
|
||||
|
||||
// Common functions
|
||||
const char *(*PM_Info_ValueForKey) ( const char *s, const char *key );
|
||||
void (*PM_Particle)( float *origin, int color, float life, int zpos, int zvel);
|
||||
int (*PM_TestPlayerPosition) (float *pos, pmtrace_t *ptrace );
|
||||
void (*Con_NPrintf)( int idx, char *fmt, ... );
|
||||
void (*Con_DPrintf)( char *fmt, ... );
|
||||
void (*Con_Printf)( char *fmt, ... );
|
||||
double (*Sys_FloatTime)( void );
|
||||
void (*PM_StuckTouch)( int hitent, pmtrace_t *ptraceresult );
|
||||
int (*PM_PointContents) (float *p, int *truecontents /*filled in if this is non-null*/ );
|
||||
int (*PM_TruePointContents) (float *p);
|
||||
int (*PM_HullPointContents) ( struct hull_s *hull, int num, float *p);
|
||||
pmtrace_t (*PM_PlayerTrace) (float *start, float *end, int traceFlags, int ignore_pe );
|
||||
struct pmtrace_s *(*PM_TraceLine)( float *start, float *end, int flags, int usehulll, int ignore_pe );
|
||||
long (*RandomLong)( long lLow, long lHigh );
|
||||
float (*RandomFloat)( float flLow, float flHigh );
|
||||
int (*PM_GetModelType)( struct model_s *mod );
|
||||
void (*PM_GetModelBounds)( struct model_s *mod, float *mins, float *maxs );
|
||||
void *(*PM_HullForBsp)( physent_t *pe, float *offset );
|
||||
float (*PM_TraceModel)( physent_t *pEnt, float *start, float *end, trace_t *trace );
|
||||
int (*COM_FileSize)(char *filename);
|
||||
byte *(*COM_LoadFile) (char *path, int usehunk, int *pLength);
|
||||
void (*COM_FreeFile) ( void *buffer );
|
||||
char *(*memfgets)( byte *pMemFile, int fileSize, int *pFilePos, char *pBuffer, int bufferSize );
|
||||
|
||||
// Functions
|
||||
// Run functions for this frame?
|
||||
qboolean runfuncs;
|
||||
void (*PM_PlaySound) ( int channel, const char *sample, float volume, float attenuation, int fFlags, int pitch );
|
||||
const char *(*PM_TraceTexture) ( int ground, float *vstart, float *vend );
|
||||
void (*PM_PlaybackEventFull) ( int flags, int clientindex, unsigned short eventindex, float delay, float *origin, float *angles, float fparam1, float fparam2, int iparam1, int iparam2, int bparam1, int bparam2 );
|
||||
|
||||
pmtrace_t (*PM_PlayerTraceEx) (float *start, float *end, int traceFlags, int (*pfnIgnore)( physent_t *pe ) );
|
||||
int (*PM_TestPlayerPositionEx) (float *pos, pmtrace_t *ptrace, int (*pfnIgnore)( physent_t *pe ) );
|
||||
struct pmtrace_s *(*PM_TraceLineEx)( float *start, float *end, int flags, int usehulll, int (*pfnIgnore)( physent_t *pe ) );
|
||||
} playermove_t;
|
||||
|
||||
#endif
|
26
hlsdk/pm_shared/pm_info.h
Normal file
26
hlsdk/pm_shared/pm_info.h
Normal file
@ -0,0 +1,26 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
// Physics info string definition
|
||||
#if !defined( PM_INFOH )
|
||||
#define PM_INFOH
|
||||
#ifdef _WIN32
|
||||
#ifndef __MINGW32__
|
||||
#pragma once
|
||||
#endif /* not __MINGW32__ */
|
||||
#endif
|
||||
|
||||
#define MAX_PHYSINFO_STRING 256
|
||||
|
||||
#endif // PM_INFOH
|
37
hlsdk/pm_shared/pm_materials.h
Normal file
37
hlsdk/pm_shared/pm_materials.h
Normal file
@ -0,0 +1,37 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
#if !defined( PM_MATERIALSH )
|
||||
#define PM_MATERIALSH
|
||||
#ifdef _WIN32
|
||||
#ifndef __MINGW32__
|
||||
#pragma once
|
||||
#endif /* not __MINGW32__ */
|
||||
#endif
|
||||
|
||||
#define CBTEXTURENAMEMAX 13 // only load first n chars of name
|
||||
|
||||
#define CHAR_TEX_CONCRETE 'C' // texture types
|
||||
#define CHAR_TEX_METAL 'M'
|
||||
#define CHAR_TEX_DIRT 'D'
|
||||
#define CHAR_TEX_VENT 'V'
|
||||
#define CHAR_TEX_GRATE 'G'
|
||||
#define CHAR_TEX_TILE 'T'
|
||||
#define CHAR_TEX_SLOSH 'S'
|
||||
#define CHAR_TEX_WOOD 'W'
|
||||
#define CHAR_TEX_COMPUTER 'P'
|
||||
#define CHAR_TEX_GLASS 'Y'
|
||||
#define CHAR_TEX_FLESH 'F'
|
||||
|
||||
#endif // !PM_MATERIALSH
|
424
hlsdk/pm_shared/pm_math.c
Normal file
424
hlsdk/pm_shared/pm_math.c
Normal file
@ -0,0 +1,424 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
// pm_math.c -- math primitives
|
||||
|
||||
#include "mathlib.h"
|
||||
#include "const.h"
|
||||
#include <math.h>
|
||||
|
||||
// up / down
|
||||
#define PITCH 0
|
||||
// left / right
|
||||
#define YAW 1
|
||||
// fall over
|
||||
#define ROLL 2
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4244)
|
||||
#endif
|
||||
|
||||
vec3_t vec3_origin = {0,0,0};
|
||||
int nanmask = 255<<23;
|
||||
|
||||
float anglemod(float a)
|
||||
{
|
||||
a = (360.0/65536) * ((int)(a*(65536/360.0)) & 65535);
|
||||
return a;
|
||||
}
|
||||
|
||||
void AngleVectors (const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up)
|
||||
{
|
||||
float angle;
|
||||
float sr, sp, sy, cr, cp, cy;
|
||||
|
||||
angle = angles[YAW] * (M_PI*2 / 360);
|
||||
sy = sin(angle);
|
||||
cy = cos(angle);
|
||||
angle = angles[PITCH] * (M_PI*2 / 360);
|
||||
sp = sin(angle);
|
||||
cp = cos(angle);
|
||||
angle = angles[ROLL] * (M_PI*2 / 360);
|
||||
sr = sin(angle);
|
||||
cr = cos(angle);
|
||||
|
||||
if (forward)
|
||||
{
|
||||
forward[0] = cp*cy;
|
||||
forward[1] = cp*sy;
|
||||
forward[2] = -sp;
|
||||
}
|
||||
if (right)
|
||||
{
|
||||
right[0] = (-1*sr*sp*cy+-1*cr*-sy);
|
||||
right[1] = (-1*sr*sp*sy+-1*cr*cy);
|
||||
right[2] = -1*sr*cp;
|
||||
}
|
||||
if (up)
|
||||
{
|
||||
up[0] = (cr*sp*cy+-sr*-sy);
|
||||
up[1] = (cr*sp*sy+-sr*cy);
|
||||
up[2] = cr*cp;
|
||||
}
|
||||
}
|
||||
|
||||
void AngleVectorsTranspose (const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up)
|
||||
{
|
||||
float angle;
|
||||
float sr, sp, sy, cr, cp, cy;
|
||||
|
||||
angle = angles[YAW] * (M_PI*2 / 360);
|
||||
sy = sin(angle);
|
||||
cy = cos(angle);
|
||||
angle = angles[PITCH] * (M_PI*2 / 360);
|
||||
sp = sin(angle);
|
||||
cp = cos(angle);
|
||||
angle = angles[ROLL] * (M_PI*2 / 360);
|
||||
sr = sin(angle);
|
||||
cr = cos(angle);
|
||||
|
||||
if (forward)
|
||||
{
|
||||
forward[0] = cp*cy;
|
||||
forward[1] = (sr*sp*cy+cr*-sy);
|
||||
forward[2] = (cr*sp*cy+-sr*-sy);
|
||||
}
|
||||
if (right)
|
||||
{
|
||||
right[0] = cp*sy;
|
||||
right[1] = (sr*sp*sy+cr*cy);
|
||||
right[2] = (cr*sp*sy+-sr*cy);
|
||||
}
|
||||
if (up)
|
||||
{
|
||||
up[0] = -sp;
|
||||
up[1] = sr*cp;
|
||||
up[2] = cr*cp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void AngleMatrix (const vec3_t angles, float (*matrix)[4] )
|
||||
{
|
||||
float angle;
|
||||
float sr, sp, sy, cr, cp, cy;
|
||||
|
||||
angle = angles[YAW] * (M_PI*2 / 360);
|
||||
sy = sin(angle);
|
||||
cy = cos(angle);
|
||||
angle = angles[PITCH] * (M_PI*2 / 360);
|
||||
sp = sin(angle);
|
||||
cp = cos(angle);
|
||||
angle = angles[ROLL] * (M_PI*2 / 360);
|
||||
sr = sin(angle);
|
||||
cr = cos(angle);
|
||||
|
||||
// matrix = (YAW * PITCH) * ROLL
|
||||
matrix[0][0] = cp*cy;
|
||||
matrix[1][0] = cp*sy;
|
||||
matrix[2][0] = -sp;
|
||||
matrix[0][1] = sr*sp*cy+cr*-sy;
|
||||
matrix[1][1] = sr*sp*sy+cr*cy;
|
||||
matrix[2][1] = sr*cp;
|
||||
matrix[0][2] = (cr*sp*cy+-sr*-sy);
|
||||
matrix[1][2] = (cr*sp*sy+-sr*cy);
|
||||
matrix[2][2] = cr*cp;
|
||||
matrix[0][3] = 0.0;
|
||||
matrix[1][3] = 0.0;
|
||||
matrix[2][3] = 0.0;
|
||||
}
|
||||
|
||||
void AngleIMatrix (const vec3_t angles, float matrix[3][4] )
|
||||
{
|
||||
float angle;
|
||||
float sr, sp, sy, cr, cp, cy;
|
||||
|
||||
angle = angles[YAW] * (M_PI*2 / 360);
|
||||
sy = sin(angle);
|
||||
cy = cos(angle);
|
||||
angle = angles[PITCH] * (M_PI*2 / 360);
|
||||
sp = sin(angle);
|
||||
cp = cos(angle);
|
||||
angle = angles[ROLL] * (M_PI*2 / 360);
|
||||
sr = sin(angle);
|
||||
cr = cos(angle);
|
||||
|
||||
// matrix = (YAW * PITCH) * ROLL
|
||||
matrix[0][0] = cp*cy;
|
||||
matrix[0][1] = cp*sy;
|
||||
matrix[0][2] = -sp;
|
||||
matrix[1][0] = sr*sp*cy+cr*-sy;
|
||||
matrix[1][1] = sr*sp*sy+cr*cy;
|
||||
matrix[1][2] = sr*cp;
|
||||
matrix[2][0] = (cr*sp*cy+-sr*-sy);
|
||||
matrix[2][1] = (cr*sp*sy+-sr*cy);
|
||||
matrix[2][2] = cr*cp;
|
||||
matrix[0][3] = 0.0;
|
||||
matrix[1][3] = 0.0;
|
||||
matrix[2][3] = 0.0;
|
||||
}
|
||||
|
||||
void NormalizeAngles( float *angles )
|
||||
{
|
||||
int i;
|
||||
// Normalize angles
|
||||
for ( i = 0; i < 3; i++ )
|
||||
{
|
||||
if ( angles[i] > 180.0 )
|
||||
{
|
||||
angles[i] -= 360.0;
|
||||
}
|
||||
else if ( angles[i] < -180.0 )
|
||||
{
|
||||
angles[i] += 360.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
InterpolateAngles
|
||||
|
||||
Interpolate Euler angles.
|
||||
FIXME: Use Quaternions to avoid discontinuities
|
||||
Frac is 0.0 to 1.0 ( i.e., should probably be clamped, but doesn't have to be )
|
||||
===================
|
||||
*/
|
||||
void InterpolateAngles( float *start, float *end, float *output, float frac )
|
||||
{
|
||||
int i;
|
||||
float ang1, ang2;
|
||||
float d;
|
||||
|
||||
NormalizeAngles( start );
|
||||
NormalizeAngles( end );
|
||||
|
||||
for ( i = 0 ; i < 3 ; i++ )
|
||||
{
|
||||
ang1 = start[i];
|
||||
ang2 = end[i];
|
||||
|
||||
d = ang2 - ang1;
|
||||
if ( d > 180 )
|
||||
{
|
||||
d -= 360;
|
||||
}
|
||||
else if ( d < -180 )
|
||||
{
|
||||
d += 360;
|
||||
}
|
||||
|
||||
output[i] = ang1 + d * frac;
|
||||
}
|
||||
|
||||
NormalizeAngles( output );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===================
|
||||
AngleBetweenVectors
|
||||
|
||||
===================
|
||||
*/
|
||||
float AngleBetweenVectors( const vec3_t v1, const vec3_t v2 )
|
||||
{
|
||||
float angle;
|
||||
float l1 = Length( v1 );
|
||||
float l2 = Length( v2 );
|
||||
|
||||
if ( !l1 || !l2 )
|
||||
return 0.0f;
|
||||
|
||||
angle = acos( DotProduct( v1, v2 ) ) / (l1*l2);
|
||||
angle = ( angle * 180.0f ) / M_PI;
|
||||
|
||||
return angle;
|
||||
}
|
||||
|
||||
|
||||
void VectorTransform (const vec3_t in1, float in2[3][4], vec3_t out)
|
||||
{
|
||||
out[0] = DotProduct(in1, in2[0]) + in2[0][3];
|
||||
out[1] = DotProduct(in1, in2[1]) + in2[1][3];
|
||||
out[2] = DotProduct(in1, in2[2]) + in2[2][3];
|
||||
}
|
||||
|
||||
|
||||
int VectorCompare (const vec3_t v1, const vec3_t v2)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0 ; i<3 ; i++)
|
||||
if (v1[i] != v2[i])
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void VectorMA (const vec3_t veca, float scale, const vec3_t vecb, vec3_t vecc)
|
||||
{
|
||||
vecc[0] = veca[0] + scale*vecb[0];
|
||||
vecc[1] = veca[1] + scale*vecb[1];
|
||||
vecc[2] = veca[2] + scale*vecb[2];
|
||||
}
|
||||
|
||||
|
||||
vec_t _DotProduct (vec3_t v1, vec3_t v2)
|
||||
{
|
||||
return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
|
||||
}
|
||||
|
||||
void _VectorSubtract (vec3_t veca, vec3_t vecb, vec3_t out)
|
||||
{
|
||||
out[0] = veca[0]-vecb[0];
|
||||
out[1] = veca[1]-vecb[1];
|
||||
out[2] = veca[2]-vecb[2];
|
||||
}
|
||||
|
||||
void _VectorAdd (vec3_t veca, vec3_t vecb, vec3_t out)
|
||||
{
|
||||
out[0] = veca[0]+vecb[0];
|
||||
out[1] = veca[1]+vecb[1];
|
||||
out[2] = veca[2]+vecb[2];
|
||||
}
|
||||
|
||||
void _VectorCopy (vec3_t in, vec3_t out)
|
||||
{
|
||||
out[0] = in[0];
|
||||
out[1] = in[1];
|
||||
out[2] = in[2];
|
||||
}
|
||||
|
||||
void CrossProduct (const vec3_t v1, const vec3_t v2, vec3_t cross)
|
||||
{
|
||||
cross[0] = v1[1]*v2[2] - v1[2]*v2[1];
|
||||
cross[1] = v1[2]*v2[0] - v1[0]*v2[2];
|
||||
cross[2] = v1[0]*v2[1] - v1[1]*v2[0];
|
||||
}
|
||||
|
||||
double sqrt(double x);
|
||||
|
||||
float Length(const vec3_t v)
|
||||
{
|
||||
int i;
|
||||
float length = 0.0f;
|
||||
|
||||
for (i=0 ; i< 3 ; i++)
|
||||
length += v[i]*v[i];
|
||||
length = sqrt (length); // FIXME
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
float Distance(const vec3_t v1, const vec3_t v2)
|
||||
{
|
||||
vec3_t d;
|
||||
VectorSubtract(v2,v1,d);
|
||||
return Length(d);
|
||||
}
|
||||
|
||||
float VectorNormalize (vec3_t v)
|
||||
{
|
||||
float length, ilength;
|
||||
|
||||
length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
|
||||
length = sqrt (length); // FIXME
|
||||
|
||||
if (length)
|
||||
{
|
||||
ilength = 1/length;
|
||||
v[0] *= ilength;
|
||||
v[1] *= ilength;
|
||||
v[2] *= ilength;
|
||||
}
|
||||
|
||||
return length;
|
||||
|
||||
}
|
||||
|
||||
void VectorInverse (vec3_t v)
|
||||
{
|
||||
v[0] = -v[0];
|
||||
v[1] = -v[1];
|
||||
v[2] = -v[2];
|
||||
}
|
||||
|
||||
void VectorScale (const vec3_t in, vec_t scale, vec3_t out)
|
||||
{
|
||||
out[0] = in[0]*scale;
|
||||
out[1] = in[1]*scale;
|
||||
out[2] = in[2]*scale;
|
||||
}
|
||||
|
||||
|
||||
int Q_log2(int val)
|
||||
{
|
||||
int answer=0;
|
||||
while (val>>=1)
|
||||
answer++;
|
||||
return answer;
|
||||
}
|
||||
|
||||
void VectorMatrix( vec3_t forward, vec3_t right, vec3_t up)
|
||||
{
|
||||
vec3_t tmp;
|
||||
|
||||
if (forward[0] == 0 && forward[1] == 0)
|
||||
{
|
||||
right[0] = 1;
|
||||
right[1] = 0;
|
||||
right[2] = 0;
|
||||
up[0] = -forward[2];
|
||||
up[1] = 0;
|
||||
up[2] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
tmp[0] = 0; tmp[1] = 0; tmp[2] = 1.0;
|
||||
CrossProduct( forward, tmp, right );
|
||||
VectorNormalize( right );
|
||||
CrossProduct( right, forward, up );
|
||||
VectorNormalize( up );
|
||||
}
|
||||
|
||||
|
||||
void VectorAngles( const vec3_t forward, vec3_t angles )
|
||||
{
|
||||
float tmp, yaw, pitch;
|
||||
|
||||
if (forward[1] == 0 && forward[0] == 0)
|
||||
{
|
||||
yaw = 0;
|
||||
if (forward[2] > 0)
|
||||
pitch = 90;
|
||||
else
|
||||
pitch = 270;
|
||||
}
|
||||
else
|
||||
{
|
||||
yaw = (atan2(forward[1], forward[0]) * 180 / M_PI);
|
||||
if (yaw < 0)
|
||||
yaw += 360;
|
||||
|
||||
tmp = sqrt (forward[0]*forward[0] + forward[1]*forward[1]);
|
||||
pitch = (atan2(forward[2], tmp) * 180 / M_PI);
|
||||
if (pitch < 0)
|
||||
pitch += 360;
|
||||
}
|
||||
|
||||
angles[0] = pitch;
|
||||
angles[1] = yaw;
|
||||
angles[2] = 0;
|
||||
}
|
47
hlsdk/pm_shared/pm_movevars.h
Normal file
47
hlsdk/pm_shared/pm_movevars.h
Normal file
@ -0,0 +1,47 @@
|
||||
//========= Copyright <20> 1996-2002, Valve LLC, All rights reserved. ============
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================
|
||||
|
||||
// pm_movevars.h
|
||||
#if !defined( PM_MOVEVARSH )
|
||||
#define PM_MOVEVARSH
|
||||
|
||||
// movevars_t // Physics variables.
|
||||
typedef struct movevars_s movevars_t;
|
||||
|
||||
struct movevars_s
|
||||
{
|
||||
float gravity; // Gravity for map
|
||||
float stopspeed; // Deceleration when not moving
|
||||
float maxspeed; // Max allowed speed
|
||||
float spectatormaxspeed;
|
||||
float accelerate; // Acceleration factor
|
||||
float airaccelerate; // Same for when in open air
|
||||
float wateraccelerate; // Same for when in water
|
||||
float friction;
|
||||
float edgefriction; // Extra friction near dropofs
|
||||
float waterfriction; // Less in water
|
||||
float entgravity; // 1.0
|
||||
float bounce; // Wall bounce value. 1.0
|
||||
float stepsize; // sv_stepsize;
|
||||
float maxvelocity; // maximum server velocity.
|
||||
float zmax; // Max z-buffer range (for GL)
|
||||
float waveHeight; // Water wave height (for GL)
|
||||
qboolean footsteps; // Play footstep sounds
|
||||
char skyName[32]; // Name of the sky map
|
||||
float rollangle;
|
||||
float rollspeed;
|
||||
float skycolor_r; // Sky color
|
||||
float skycolor_g; //
|
||||
float skycolor_b; //
|
||||
float skyvec_x; // Sky vector
|
||||
float skyvec_y; //
|
||||
float skyvec_z; //
|
||||
};
|
||||
|
||||
extern movevars_t movevars;
|
||||
|
||||
#endif
|
3308
hlsdk/pm_shared/pm_shared.c
Normal file
3308
hlsdk/pm_shared/pm_shared.c
Normal file
File diff suppressed because it is too large
Load Diff
40
hlsdk/pm_shared/pm_shared.h
Normal file
40
hlsdk/pm_shared/pm_shared.h
Normal file
@ -0,0 +1,40 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
|
||||
//
|
||||
// pm_shared.h
|
||||
//
|
||||
#if !defined( PM_SHAREDH )
|
||||
#define PM_SHAREDH
|
||||
#ifdef _WIN32
|
||||
#ifndef __MINGW32__
|
||||
#pragma once
|
||||
#endif /* not __MINGW32__ */
|
||||
#endif
|
||||
|
||||
void PM_Init( struct playermove_s *ppmove );
|
||||
void PM_Move ( struct playermove_s *ppmove, int server );
|
||||
char PM_FindTextureType( char *name );
|
||||
|
||||
// Spectator Movement modes (stored in pev->iuser1, so the physics code can get at them)
|
||||
#define OBS_NONE 0
|
||||
#define OBS_CHASE_LOCKED 1
|
||||
#define OBS_CHASE_FREE 2
|
||||
#define OBS_ROAMING 3
|
||||
#define OBS_IN_EYE 4
|
||||
#define OBS_MAP_FREE 5
|
||||
#define OBS_MAP_CHASE 6
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user