added multiple joystick support in windows.
fixed portals. again. now pushing the player out (reverting origin) if they get de-spawned. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4711 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
d710d945d0
commit
b97bc5685c
17 changed files with 391 additions and 302 deletions
|
@ -405,6 +405,7 @@ void CL_PredictUsercmd (int pnum, int entnum, player_state_t *from, player_state
|
|||
movevars.maxspeed = cl.playerview[pnum].maxspeed;
|
||||
movevars.bunnyspeedcap = cl.bunnyspeedcap;
|
||||
pmove.onladder = false;
|
||||
pmove.safeorigin_known = false;
|
||||
|
||||
VectorCopy(from->szmins, pmove.player_mins);
|
||||
VectorCopy(from->szmaxs, pmove.player_maxs);
|
||||
|
|
|
@ -120,7 +120,6 @@ static DWORD dwAxisFlags[JOY_MAX_AXES] =
|
|||
|
||||
static DWORD dwAxisMap[JOY_MAX_AXES];
|
||||
static DWORD dwControlMap[JOY_MAX_AXES];
|
||||
static PDWORD pdwRawValue[JOY_MAX_AXES];
|
||||
|
||||
// none of these cvars are saved over a session
|
||||
// this means that advanced controller configuration needs to be executed
|
||||
|
@ -147,12 +146,23 @@ static cvar_t joy_yawsensitivity = CVAR("joyyawsensitivity", "-1.0");
|
|||
static cvar_t joy_wwhack1 = CVAR("joywwhack1", "0.0");
|
||||
static cvar_t joy_wwhack2 = CVAR("joywwhack2", "0.0");
|
||||
|
||||
static qboolean joy_avail, joy_advancedinit, joy_haspov;
|
||||
static DWORD joy_oldbuttonstate, joy_oldpovstate;
|
||||
static qboolean joy_advancedinit;
|
||||
|
||||
static int joy_id;
|
||||
static DWORD joy_flags;
|
||||
static DWORD joy_numbuttons;
|
||||
#define MAX_JOYSTICKS 4
|
||||
static struct wjoy_s {
|
||||
unsigned int id; //windows id. device id is the index.
|
||||
unsigned int devid; //quake id (generally player index)
|
||||
DWORD numbuttons;
|
||||
qboolean haspov;
|
||||
DWORD povstate;
|
||||
DWORD oldpovstate;
|
||||
DWORD buttonstate;
|
||||
DWORD oldbuttonstate;
|
||||
|
||||
DWORD axis[JOY_MAX_AXES];
|
||||
} wjoy[MAX_JOYSTICKS];
|
||||
static int joy_count;
|
||||
|
||||
#ifdef AVAIL_DINPUT
|
||||
static const GUID fGUID_XAxis = {0xA36D02E0, 0xC9F3, 0x11CF, {0xBF, 0xC7, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}};
|
||||
|
@ -1318,8 +1328,7 @@ void INS_Move (float *movements, int pnum)
|
|||
if (ActiveApp && !Minimized)
|
||||
{
|
||||
INS_MouseMove (movements, pnum);
|
||||
if (pnum == 1 || cl.splitclients<2)
|
||||
INS_JoyMove (movements, pnum);
|
||||
INS_JoyMove (movements, pnum);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1530,20 +1539,50 @@ void INS_ClearStates (void)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
INS_StartupJoystick
|
||||
===============
|
||||
*/
|
||||
void INS_StartupJoystick (void)
|
||||
static void INS_StartupJoystickId(unsigned int id)
|
||||
{
|
||||
int numdevs;
|
||||
JOYCAPS jc;
|
||||
MMRESULT mmr;
|
||||
struct wjoy_s *joy;
|
||||
if (joy_count == MAX_JOYSTICKS)
|
||||
return;
|
||||
joy = &wjoy[joy_count];
|
||||
memset(joy, 0, sizeof(*joy));
|
||||
joy->id = id;
|
||||
joy->devid = 1+joy_count; //FIXME: this is a hack. make joysticks 1-based. this means mouse0 controls 1st player, joy0 controls 2nd player (controls wrap so joy1 controls 1st player too.
|
||||
|
||||
// assume no joystick
|
||||
joy_avail = false;
|
||||
// get the capabilities of the selected joystick
|
||||
// abort startup if command fails
|
||||
memset (&jc, 0, sizeof(jc));
|
||||
if ((mmr = joyGetDevCaps (joy->id, &jc, sizeof(jc))) != JOYERR_NOERROR)
|
||||
{
|
||||
Con_Printf ("joystick %03x not found -- invalid joystick capabilities (%x)\n", id, mmr);
|
||||
return;
|
||||
}
|
||||
|
||||
// save the joystick's number of buttons and POV status
|
||||
joy->numbuttons = jc.wNumButtons;
|
||||
joy->haspov = jc.wCaps & JOYCAPS_HASPOV;
|
||||
|
||||
// mark the joystick as available and advanced initialization not completed
|
||||
// this is needed as cvars are not available during initialization
|
||||
|
||||
joy_advancedinit = false;
|
||||
|
||||
joy_count++;
|
||||
}
|
||||
void INS_StartupJoystick (void)
|
||||
{
|
||||
unsigned int id, numdevs;
|
||||
MMRESULT mmr;
|
||||
|
||||
// assume no joysticks
|
||||
joy_count = 0;
|
||||
|
||||
// abort startup if user requests no joystick
|
||||
if ( COM_CheckParm ("-nojoy") )
|
||||
|
@ -1559,75 +1598,21 @@ void INS_StartupJoystick (void)
|
|||
mmr = JOYERR_UNPLUGGED;
|
||||
|
||||
// cycle through the joystick ids for the first valid one
|
||||
for (joy_id=0 ; joy_id<numdevs ; joy_id++)
|
||||
for (id=0 ; id<numdevs ; id++)
|
||||
{
|
||||
memset (&ji, 0, sizeof(ji));
|
||||
ji.dwSize = sizeof(ji);
|
||||
ji.dwFlags = JOY_RETURNCENTERED;
|
||||
|
||||
if ((mmr = joyGetPosEx (joy_id, &ji)) == JOYERR_NOERROR)
|
||||
break;
|
||||
if ((mmr = joyGetPosEx (id, &ji)) == JOYERR_NOERROR)
|
||||
{
|
||||
INS_StartupJoystickId(id);
|
||||
}
|
||||
}
|
||||
|
||||
// abort startup if we didn't find a valid joystick
|
||||
if (mmr != JOYERR_NOERROR)
|
||||
{
|
||||
// Con_Printf ("joystick not found -- no valid joysticks (%x)\n", mmr);
|
||||
return;
|
||||
}
|
||||
|
||||
// get the capabilities of the selected joystick
|
||||
// abort startup if command fails
|
||||
memset (&jc, 0, sizeof(jc));
|
||||
if ((mmr = joyGetDevCaps (joy_id, &jc, sizeof(jc))) != JOYERR_NOERROR)
|
||||
{
|
||||
Con_Printf ("joystick not found -- invalid joystick capabilities (%x)\n", mmr);
|
||||
return;
|
||||
}
|
||||
|
||||
// save the joystick's number of buttons and POV status
|
||||
joy_numbuttons = jc.wNumButtons;
|
||||
joy_haspov = jc.wCaps & JOYCAPS_HASPOV;
|
||||
|
||||
// old button and POV states default to no buttons pressed
|
||||
joy_oldbuttonstate = joy_oldpovstate = 0;
|
||||
|
||||
// mark the joystick as available and advanced initialization not completed
|
||||
// this is needed as cvars are not available during initialization
|
||||
|
||||
joy_avail = true;
|
||||
joy_advancedinit = false;
|
||||
|
||||
Con_Printf ("joystick detected\n");
|
||||
Con_Printf ("found %i joysticks\n", joy_count);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===========
|
||||
RawValuePointer
|
||||
===========
|
||||
*/
|
||||
static PDWORD RawValuePointer (int axis)
|
||||
{
|
||||
switch (axis)
|
||||
{
|
||||
case JOY_AXIS_X:
|
||||
return &ji.dwXpos;
|
||||
case JOY_AXIS_Y:
|
||||
return &ji.dwYpos;
|
||||
case JOY_AXIS_Z:
|
||||
return &ji.dwZpos;
|
||||
case JOY_AXIS_R:
|
||||
return &ji.dwRpos;
|
||||
case JOY_AXIS_U:
|
||||
return &ji.dwUpos;
|
||||
case JOY_AXIS_V:
|
||||
return &ji.dwVpos;
|
||||
}
|
||||
return 0; //compiler shut up.
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===========
|
||||
Joy_AdvancedUpdate_f
|
||||
|
@ -1646,7 +1631,6 @@ void Joy_AdvancedUpdate_f (void)
|
|||
{
|
||||
dwAxisMap[i] = AxisNada;
|
||||
dwControlMap[i] = JOY_ABSOLUTE_AXIS;
|
||||
pdwRawValue[i] = RawValuePointer(i);
|
||||
}
|
||||
|
||||
if( joy_advanced.value == 0.0)
|
||||
|
@ -1709,63 +1693,64 @@ void INS_Commands (void)
|
|||
{
|
||||
int i, key_index;
|
||||
DWORD buttonstate, povstate;
|
||||
unsigned int idx;
|
||||
struct wjoy_s *joy;
|
||||
|
||||
if (!joy_avail)
|
||||
for (idx = 0; idx < joy_count; idx++)
|
||||
{
|
||||
return;
|
||||
}
|
||||
joy = &wjoy[idx];
|
||||
|
||||
|
||||
// loop through the joystick buttons
|
||||
// key a joystick event or auxillary event for higher number buttons for each state change
|
||||
buttonstate = ji.dwButtons;
|
||||
for (i=0 ; i < joy_numbuttons ; i++)
|
||||
{
|
||||
if ( (buttonstate & (1<<i)) && !(joy_oldbuttonstate & (1<<i)) )
|
||||
// loop through the joystick buttons
|
||||
// key a joystick event or auxillary event for higher number buttons for each state change
|
||||
buttonstate = joy->buttonstate;
|
||||
for (i=0 ; i < joy->numbuttons ; i++)
|
||||
{
|
||||
key_index = (i < 4) ? K_JOY1 : K_AUX1;
|
||||
Key_Event (0, key_index + i, 0, true);
|
||||
}
|
||||
|
||||
if ( !(buttonstate & (1<<i)) && (joy_oldbuttonstate & (1<<i)) )
|
||||
{
|
||||
key_index = (i < 4) ? K_JOY1 : K_AUX1;
|
||||
Key_Event (0, key_index + i, 0, false);
|
||||
}
|
||||
}
|
||||
joy_oldbuttonstate = buttonstate;
|
||||
|
||||
if (joy_haspov)
|
||||
{
|
||||
// convert POV information into 4 bits of state information
|
||||
// this avoids any potential problems related to moving from one
|
||||
// direction to another without going through the center position
|
||||
povstate = 0;
|
||||
if(ji.dwPOV != JOY_POVCENTERED)
|
||||
{
|
||||
if (ji.dwPOV == JOY_POVFORWARD)
|
||||
povstate |= 0x01;
|
||||
if (ji.dwPOV == JOY_POVRIGHT)
|
||||
povstate |= 0x02;
|
||||
if (ji.dwPOV == JOY_POVBACKWARD)
|
||||
povstate |= 0x04;
|
||||
if (ji.dwPOV == JOY_POVLEFT)
|
||||
povstate |= 0x08;
|
||||
}
|
||||
// determine which bits have changed and key an auxillary event for each change
|
||||
for (i=0 ; i < 4 ; i++)
|
||||
{
|
||||
if ( (povstate & (1<<i)) && !(joy_oldpovstate & (1<<i)) )
|
||||
if ( (buttonstate & (1<<i)) && !(joy->oldbuttonstate & (1<<i)) )
|
||||
{
|
||||
Key_Event (0, K_AUX29 + i, 0, true);
|
||||
key_index = (i < 4) ? K_JOY1 : K_AUX1;
|
||||
Key_Event (joy->devid, key_index + i, 0, true);
|
||||
}
|
||||
|
||||
if ( !(povstate & (1<<i)) && (joy_oldpovstate & (1<<i)) )
|
||||
if ( !(buttonstate & (1<<i)) && (joy->oldbuttonstate & (1<<i)) )
|
||||
{
|
||||
Key_Event (0, K_AUX29 + i, 0, false);
|
||||
key_index = (i < 4) ? K_JOY1 : K_AUX1;
|
||||
Key_Event (joy->devid, key_index + i, 0, false);
|
||||
}
|
||||
}
|
||||
joy_oldpovstate = povstate;
|
||||
joy->oldbuttonstate = buttonstate;
|
||||
|
||||
if (joy->haspov)
|
||||
{
|
||||
// convert POV information into 4 bits of state information
|
||||
// this avoids any potential problems related to moving from one
|
||||
// direction to another without going through the center position
|
||||
povstate = 0;
|
||||
if(joy->povstate != JOY_POVCENTERED)
|
||||
{
|
||||
if (joy->povstate == JOY_POVFORWARD)
|
||||
povstate |= 0x01;
|
||||
if (joy->povstate == JOY_POVRIGHT)
|
||||
povstate |= 0x02;
|
||||
if (joy->povstate == JOY_POVBACKWARD)
|
||||
povstate |= 0x04;
|
||||
if (joy->povstate == JOY_POVLEFT)
|
||||
povstate |= 0x08;
|
||||
}
|
||||
// determine which bits have changed and key an auxillary event for each change
|
||||
for (i=0 ; i < 4 ; i++)
|
||||
{
|
||||
if ( (povstate & (1<<i)) && !(joy->oldpovstate & (1<<i)) )
|
||||
{
|
||||
Key_Event (joy->devid, K_AUX29 + i, 0, true);
|
||||
}
|
||||
|
||||
if ( !(povstate & (1<<i)) && (joy->oldpovstate & (1<<i)) )
|
||||
{
|
||||
Key_Event (joy->devid, K_AUX29 + i, 0, false);
|
||||
}
|
||||
}
|
||||
joy->oldpovstate = povstate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1775,14 +1760,13 @@ void INS_Commands (void)
|
|||
INS_ReadJoystick
|
||||
===============
|
||||
*/
|
||||
qboolean INS_ReadJoystick (void)
|
||||
qboolean INS_ReadJoystick (struct wjoy_s *joy)
|
||||
{
|
||||
|
||||
memset (&ji, 0, sizeof(ji));
|
||||
ji.dwSize = sizeof(ji);
|
||||
ji.dwFlags = joy_flags;
|
||||
|
||||
if (joyGetPosEx (joy_id, &ji) == JOYERR_NOERROR)
|
||||
if (joyGetPosEx (joy->id, &ji) == JOYERR_NOERROR)
|
||||
{
|
||||
// this is a hack -- there is a bug in the Logitech WingMan Warrior DirectInput Driver
|
||||
// rather than having 32768 be the zero point, they have the zero point at 32668
|
||||
|
@ -1791,6 +1775,14 @@ qboolean INS_ReadJoystick (void)
|
|||
{
|
||||
ji.dwUpos += 100;
|
||||
}
|
||||
joy->povstate = ji.dwPOV;
|
||||
joy->buttonstate = ji.dwButtons;
|
||||
joy->axis[JOY_AXIS_X] = ji.dwXpos;
|
||||
joy->axis[JOY_AXIS_Y] = ji.dwYpos;
|
||||
joy->axis[JOY_AXIS_Z] = ji.dwZpos;
|
||||
joy->axis[JOY_AXIS_R] = ji.dwRpos;
|
||||
joy->axis[JOY_AXIS_U] = ji.dwUpos;
|
||||
joy->axis[JOY_AXIS_V] = ji.dwVpos;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
@ -1804,34 +1796,27 @@ qboolean INS_ReadJoystick (void)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===========
|
||||
INS_JoyMove
|
||||
===========
|
||||
*/
|
||||
void INS_JoyMove (float *movements, int pnum)
|
||||
static void INS_JoyMovePtr (struct wjoy_s *joy, float *movements, int pnum)
|
||||
{
|
||||
float speed, aspeed;
|
||||
float fAxisValue, fTemp;
|
||||
int i;
|
||||
int wpnum;
|
||||
|
||||
// complete initialization if first time in
|
||||
// this is needed as cvars are not available at initialization time
|
||||
if( joy_advancedinit != true )
|
||||
{
|
||||
Joy_AdvancedUpdate_f();
|
||||
joy_advancedinit = true;
|
||||
}
|
||||
|
||||
// verify joystick is available and that the user wants to use it
|
||||
if (!joy_avail || !in_joystick.value)
|
||||
{
|
||||
/*each device will be processed when its player comes to be processed*/
|
||||
wpnum = cl.splitclients;
|
||||
if (wpnum < 1)
|
||||
wpnum = 1;
|
||||
if (cl_forcesplitclient.ival)
|
||||
wpnum = (cl_forcesplitclient.ival-1) % wpnum;
|
||||
else
|
||||
wpnum = joy->devid % wpnum;
|
||||
if (wpnum != pnum)
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// collect the joystick data, if possible
|
||||
if (INS_ReadJoystick () != true)
|
||||
if (INS_ReadJoystick (joy) != true)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -1846,7 +1831,7 @@ void INS_JoyMove (float *movements, int pnum)
|
|||
for (i = 0; i < JOY_MAX_AXES; i++)
|
||||
{
|
||||
// get the floating point zero-centered, potentially-inverted data for the current axis
|
||||
fAxisValue = (float) *pdwRawValue[i];
|
||||
fAxisValue = (float) joy->axis[i];
|
||||
// move centerpoint to zero
|
||||
fAxisValue -= 32768.0;
|
||||
|
||||
|
@ -1870,7 +1855,7 @@ void INS_JoyMove (float *movements, int pnum)
|
|||
fAxisValue /= 32768.0;
|
||||
|
||||
#ifdef CSQC_DAT
|
||||
if (CSQC_JoystickAxis(i, fAxisValue, 0))
|
||||
if (CSQC_JoystickAxis(i, fAxisValue, joy->devid))
|
||||
continue;
|
||||
#endif
|
||||
|
||||
|
@ -1983,6 +1968,32 @@ void INS_JoyMove (float *movements, int pnum)
|
|||
|
||||
CL_ClampPitch(pnum);
|
||||
}
|
||||
/*
|
||||
===========
|
||||
INS_JoyMove
|
||||
===========
|
||||
*/
|
||||
void INS_JoyMove (float *movements, int pnum)
|
||||
{
|
||||
unsigned int idx;
|
||||
|
||||
// complete initialization if first time in
|
||||
// this is needed as cvars are not available at initialization time
|
||||
if( joy_advancedinit != true )
|
||||
{
|
||||
Joy_AdvancedUpdate_f();
|
||||
joy_advancedinit = true;
|
||||
}
|
||||
|
||||
// verify joystick is available and that the user wants to use it
|
||||
if (!in_joystick.value)
|
||||
return;
|
||||
|
||||
for (idx = 0; idx < joy_count; idx++)
|
||||
{
|
||||
INS_JoyMovePtr(&wjoy[idx], movements, idx);
|
||||
}
|
||||
}
|
||||
|
||||
static qbyte scantokey[] =
|
||||
{
|
||||
|
|
|
@ -2133,6 +2133,7 @@ void Key_Event (int devid, int key, unsigned int unicode, qboolean down)
|
|||
if (key_repeats[key] > 1)
|
||||
return;
|
||||
|
||||
//first player is normally assumed anyway.
|
||||
if (devid)
|
||||
Q_snprintfz (p, sizeof(p), "p %i ", devid+1);
|
||||
else
|
||||
|
|
|
@ -2512,6 +2512,7 @@ static void QCBUILTIN PF_cs_runplayerphysics (pubprogfuncs_t *prinst, struct glo
|
|||
pmove.cmd.sidemove = csqcg.input_movevalues[1];
|
||||
pmove.cmd.upmove = csqcg.input_movevalues[2];
|
||||
pmove.cmd.buttons = *csqcg.input_buttons;
|
||||
pmove.safeorigin_known = false;
|
||||
|
||||
if (ent)
|
||||
{
|
||||
|
|
|
@ -1129,7 +1129,7 @@ qboolean rag_animate(skelobject_t *sko, doll_t *doll, float *emat)
|
|||
int i;
|
||||
for (i = 0; i < sko->numbodies; i++)
|
||||
{
|
||||
if (!doll->body[i].animate)
|
||||
if (!sko->body[i].animstrength)
|
||||
continue;
|
||||
rag_genbodymatrix(sko, &doll->body[i], emat, sko->body[i].animmatrix);
|
||||
}
|
||||
|
@ -1370,7 +1370,7 @@ void rag_doallanimations(world_t *world)
|
|||
|
||||
for (j = 0; j < sko->numbodies; j++)
|
||||
{
|
||||
if (!doll->body[j].animate)
|
||||
if (!sko->body[j].animstrength)
|
||||
continue;
|
||||
World_ODE_RagMatrixToBody(&sko->body[j].odebody, sko->body[j].animmatrix);
|
||||
}
|
||||
|
@ -1606,7 +1606,7 @@ void QCBUILTIN PF_skel_ragedit(pubprogfuncs_t *prinst, struct globalvars_s *pr_g
|
|||
}
|
||||
else if (!doll)
|
||||
{
|
||||
G_FLOAT(OFS_RETURN) = 1; //technically success.
|
||||
G_FLOAT(OFS_RETURN) = !!*ragname; //technically success.
|
||||
return;
|
||||
}
|
||||
else if (sko->numanimated)
|
||||
|
|
|
@ -3857,7 +3857,7 @@ qboolean Mod_GetTag(model_t *model, int tagnum, framestate_t *fstate, float *res
|
|||
result[10] = 1;
|
||||
while(tagnum >= 0)
|
||||
{
|
||||
for (lerp = lerps; tagnum < lerp->endbone; lerp++)
|
||||
for (lerp = lerps; tagnum < lerp->firstbone; lerp++)
|
||||
;
|
||||
//set up the per-bone transform matrix
|
||||
matrix = lerp->pose[0] + tagnum*12;
|
||||
|
|
|
@ -228,16 +228,9 @@ Netchan_Init
|
|||
*/
|
||||
void Netchan_Init (void)
|
||||
{
|
||||
static char qportstr[16];
|
||||
int port;
|
||||
|
||||
Cvar_Register (&pext_nqpredinfo, "Protocol Extensions");
|
||||
Cvar_Register (&pext_replacementdeltas, "Protocol Extensions");
|
||||
Cvar_Register (&showpackets, "Networking");
|
||||
Cvar_Register (&showdrop, "Networking");
|
||||
Cvar_Register (&qport, "Networking");
|
||||
Cvar_Register (&net_mtu, "Networking");
|
||||
Cvar_Register (&net_compress, "Networking");
|
||||
|
||||
// pick a port value that should be nice and random
|
||||
#ifdef _WIN32
|
||||
port = (time(NULL)) & 0xffff;
|
||||
|
@ -246,8 +239,16 @@ void Netchan_Init (void)
|
|||
#else
|
||||
port = ((int)(getpid()+getuid()*1000) * time(NULL)) & 0xffff;
|
||||
#endif
|
||||
Q_snprintfz(qportstr, sizeof(qportstr), "%i", port);
|
||||
qport.string = qportstr;
|
||||
|
||||
Cvar_SetValue (&qport, port);
|
||||
Cvar_Register (&pext_nqpredinfo, "Protocol Extensions");
|
||||
Cvar_Register (&pext_replacementdeltas, "Protocol Extensions");
|
||||
Cvar_Register (&showpackets, "Networking");
|
||||
Cvar_Register (&showdrop, "Networking");
|
||||
Cvar_Register (&qport, "Networking");
|
||||
Cvar_Register (&net_mtu, "Networking");
|
||||
Cvar_Register (&net_compress, "Networking");
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -84,12 +84,15 @@ void PM_ClipVelocity (vec3_t in, vec3_t normal, vec3_t out, float overbounce)
|
|||
}
|
||||
|
||||
#include "pr_common.h"
|
||||
static qboolean PM_PortalTransform(world_t *w, int portalnum, vec3_t org, vec3_t move)
|
||||
static qboolean PM_PortalTransform(world_t *w, int portalnum, vec3_t org, vec3_t move, vec3_t newang, vec3_t newvel)
|
||||
{
|
||||
vec3_t rounded;
|
||||
qboolean okay = true;
|
||||
wedict_t *portal = WEDICT_NUM(w->progs, portalnum);
|
||||
int oself = *w->g.self;
|
||||
void *pr_globals = PR_globals(w->progs, PR_CURRENT);
|
||||
int i;
|
||||
int tmp;
|
||||
|
||||
*w->g.self = EDICT_TO_PROG(w->progs, portal);
|
||||
//transform origin+velocity etc
|
||||
|
@ -103,15 +106,20 @@ static qboolean PM_PortalTransform(world_t *w, int portalnum, vec3_t org, vec3_t
|
|||
|
||||
PR_ExecuteProgram (w->progs, portal->xv->camera_transform);
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
tmp = floor(G_VECTOR(OFS_RETURN)[i]*8 + 0.5);
|
||||
rounded[i] = tmp/8.0;
|
||||
}
|
||||
//make sure the new origin is okay for the player. back out if its invalid.
|
||||
if (!PM_TestPlayerPosition(G_VECTOR(OFS_RETURN), true))
|
||||
if (!PM_TestPlayerPosition(rounded, true))
|
||||
okay = false;
|
||||
else
|
||||
{
|
||||
VectorCopy(G_VECTOR(OFS_RETURN), org);
|
||||
VectorCopy(w->g.v_forward, pmove.velocity);
|
||||
VectorCopy(rounded, org);
|
||||
VectorCopy(w->g.v_forward, newvel);
|
||||
VectorCopy(w->g.v_right, move);
|
||||
VectorCopy(w->g.v_up, pmove.gravitydir);
|
||||
// VectorCopy(w->g.v_up, pmove.gravitydir);
|
||||
|
||||
|
||||
//transform the angles too
|
||||
|
@ -119,8 +127,8 @@ static qboolean PM_PortalTransform(world_t *w, int portalnum, vec3_t org, vec3_t
|
|||
VectorCopy(pmove.angles, G_VECTOR(OFS_PARM1));
|
||||
AngleVectors(pmove.angles, w->g.v_forward, w->g.v_right, w->g.v_up);
|
||||
PR_ExecuteProgram (w->progs, portal->xv->camera_transform);
|
||||
VectorAngles(w->g.v_forward, w->g.v_up, pmove.angles);
|
||||
pmove.angles[0] *= -1;
|
||||
VectorAngles(w->g.v_forward, w->g.v_up, newang);
|
||||
newang[0] *= -1;
|
||||
}
|
||||
|
||||
*w->g.self = oself;
|
||||
|
@ -139,18 +147,32 @@ static trace_t PM_PlayerTracePortals(vec3_t start, vec3_t end, unsigned int soli
|
|||
{
|
||||
vec3_t move;
|
||||
vec3_t from;
|
||||
vec3_t newang, newvel;
|
||||
|
||||
VectorCopy(trace.endpos, from); //just in case
|
||||
VectorSubtract(end, trace.endpos, move);
|
||||
if (PM_PortalTransform(pmove.world, impact->info, from, move))
|
||||
if (PM_PortalTransform(pmove.world, impact->info, from, move, newang, newvel))
|
||||
{
|
||||
trace_t exit;
|
||||
int i, tmp;
|
||||
VectorAdd(from, move, end);
|
||||
|
||||
//if we follow the portal, then we basically need to restart from the other side.
|
||||
if (tookportal)
|
||||
*tookportal = trace.fraction;
|
||||
|
||||
return PM_PlayerTrace (from, end, MASK_PLAYERSOLID);
|
||||
exit = PM_PlayerTrace (from, end, MASK_PLAYERSOLID);
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
tmp = floor(exit.endpos[i]*8 + 0.5);
|
||||
exit.endpos[i] = tmp/8.0;
|
||||
}
|
||||
if (PM_TestPlayerPosition(exit.endpos, false))
|
||||
{
|
||||
if (tookportal)
|
||||
*tookportal = trace.fraction;
|
||||
VectorCopy(newang, pmove.angles);
|
||||
VectorCopy(newvel, pmove.velocity);
|
||||
return exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1073,15 +1095,16 @@ void PM_NudgePosition (void)
|
|||
for (i=0 ; i<3 ; i++)
|
||||
base[i] = ((int)(base[i]*8)) * 0.125;
|
||||
|
||||
if (pmove.velocity[0] || pmove.velocity[1])
|
||||
//if we're moving, allow that spot without snapping to any grid
|
||||
if (pmove.velocity[0] || pmove.velocity[1] || pmove.velocity[2])
|
||||
if (PM_TestPlayerPosition (pmove.origin, false))
|
||||
return;
|
||||
|
||||
for (z=0 ; z<=4 ; z++)
|
||||
for (z=0 ; z<sizeof(sign)/sizeof(sign[0]) ; z++)
|
||||
{
|
||||
for (x=0 ; x<=4 ; x++)
|
||||
for (x=0 ; x<sizeof(sign)/sizeof(sign[0]) ; x++)
|
||||
{
|
||||
for (y=0 ; y<=4 ; y++)
|
||||
for (y=0 ; y<sizeof(sign)/sizeof(sign[0]) ; y++)
|
||||
{
|
||||
pmove.origin[0] = base[0] + (sign[x] * 1.0/8);
|
||||
pmove.origin[1] = base[1] + (sign[y] * 1.0/8);
|
||||
|
@ -1091,7 +1114,10 @@ void PM_NudgePosition (void)
|
|||
}
|
||||
}
|
||||
}
|
||||
VectorCopy (base, pmove.origin);
|
||||
if (pmove.safeorigin_known)
|
||||
VectorCopy (pmove.safeorigin, pmove.origin);
|
||||
else
|
||||
VectorCopy (base, pmove.origin);
|
||||
// Com_DPrintf ("NudgePosition: stuck\n");
|
||||
}
|
||||
|
||||
|
@ -1267,6 +1293,7 @@ void PM_PlayerMove (float gamespeed)
|
|||
PM_ClipVelocity (pmove.velocity, groundplane.normal, pmove.velocity, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
//round to network precision
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
|
@ -1275,4 +1302,5 @@ void PM_PlayerMove (float gamespeed)
|
|||
tmp = floor(pmove.origin[i]*8 + 0.5);
|
||||
pmove.origin[i] = tmp/8.0;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
|
|
@ -56,6 +56,7 @@ typedef struct
|
|||
|
||||
// player state
|
||||
vec3_t origin;
|
||||
vec3_t safeorigin;
|
||||
vec3_t angles;
|
||||
vec3_t velocity;
|
||||
vec3_t basevelocity;
|
||||
|
@ -75,6 +76,7 @@ typedef struct
|
|||
usercmd_t cmd;
|
||||
|
||||
qboolean onladder;
|
||||
qboolean safeorigin_known;
|
||||
|
||||
// results
|
||||
int skipent;
|
||||
|
|
|
@ -358,13 +358,14 @@ PM_TestPlayerPosition
|
|||
Returns false if the given player position is not valid (in solid)
|
||||
================
|
||||
*/
|
||||
qboolean PM_TestPlayerPosition (vec3_t pos, qboolean ignoreportals)
|
||||
int PM_TestPlayerPosition (vec3_t pos, qboolean ignoreportals)
|
||||
{
|
||||
int i, j;
|
||||
physent_t *pe;
|
||||
vec3_t mins, maxs;
|
||||
hull_t *hull;
|
||||
trace_t trace;
|
||||
int csged = false;
|
||||
|
||||
for (i=0 ; i< pmove.numphysent ; i++)
|
||||
{
|
||||
|
@ -416,6 +417,7 @@ qboolean PM_TestPlayerPosition (vec3_t pos, qboolean ignoreportals)
|
|||
}
|
||||
if (trace.allsolid)
|
||||
return false;
|
||||
csged = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -431,6 +433,13 @@ qboolean PM_TestPlayerPosition (vec3_t pos, qboolean ignoreportals)
|
|||
}
|
||||
}
|
||||
|
||||
if (!csged && !ignoreportals)
|
||||
{
|
||||
//the point the player is returned to if the portal dissipates
|
||||
pmove.safeorigin_known = true;
|
||||
VectorCopy (pmove.origin, pmove.safeorigin);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -3019,6 +3019,13 @@ void QCBUILTIN PF_strftime (pubprogfuncs_t *prinst, struct globalvars_s *pr_glob
|
|||
tm = localtime(&ctime);
|
||||
else
|
||||
tm = gmtime(&ctime);
|
||||
|
||||
//msvc sucks.
|
||||
if (!strcmp(in, "%R"))
|
||||
in = "%H:%M";
|
||||
else if (!strcmp(in, "%F"))
|
||||
in = "%Y-%m-%d";
|
||||
|
||||
strftime(result, sizeof(result), in, tm);
|
||||
unicode_strtoupper(result, uresult, sizeof(uresult), VMUTF8MARKUP);
|
||||
|
||||
|
|
|
@ -167,6 +167,7 @@ struct world_s
|
|||
model_t *worldmodel;
|
||||
areanode_t areanodes[AREA_NODES];
|
||||
int numareanodes;
|
||||
areanode_t portallist;
|
||||
|
||||
double physicstime; // the last time global physics were run
|
||||
unsigned int framenum;
|
||||
|
|
|
@ -8605,6 +8605,8 @@ static void QCBUILTIN PF_runclientphys(pubprogfuncs_t *prinst, struct globalvars
|
|||
pmove.cmd.upmove = (pr_global_struct->input_movevalues)[2];
|
||||
pmove.cmd.buttons = pr_global_struct->input_buttons;
|
||||
|
||||
pmove.safeorigin_known = true;
|
||||
VectorCopy(ent->v->oldorigin, pmove.safeorigin);
|
||||
VectorCopy(ent->v->origin, pmove.origin);
|
||||
VectorCopy(ent->v->velocity, pmove.velocity);
|
||||
VectorCopy(ent->v->maxs, pmove.player_maxs);
|
||||
|
@ -8630,6 +8632,7 @@ static void QCBUILTIN PF_runclientphys(pubprogfuncs_t *prinst, struct globalvars
|
|||
}
|
||||
AddLinksToPmove(ent, sv.world.areanodes);
|
||||
// AddAllEntsToPmove();
|
||||
AddLinksToPmove_Force ( ent, &sv.world.portallist );
|
||||
|
||||
SV_PreRunCmd();
|
||||
|
||||
|
@ -8650,6 +8653,7 @@ static void QCBUILTIN PF_runclientphys(pubprogfuncs_t *prinst, struct globalvars
|
|||
else
|
||||
ent->v->teleport_time = pmove.waterjumptime;
|
||||
VectorCopy(pmove.origin, ent->v->origin);
|
||||
VectorCopy(pmove.safeorigin, ent->v->oldorigin);
|
||||
VectorCopy(pmove.velocity, ent->v->velocity);
|
||||
|
||||
|
||||
|
@ -10607,9 +10611,9 @@ void PR_DumpPlatform_f(void)
|
|||
{"VF_SCREENPSIZE", "const float", CS|MENU, "Provides a reliable way to retrieve the current physical screen size (cvars need vid_restart for them to take effect).", VF_SCREENPSIZE},
|
||||
{"VF_VIEWENTITY", "const float", CS, "Changes the RF_EXTERNALMODEL flag on entities to match the new selection, and removes entities flaged with RF_VIEWENTITY. Requires cunning use of .entnum and typically requires calling addentities(MASK_VIEWMODEL) too.", VF_VIEWENTITY},
|
||||
|
||||
{"VF_RT_DESTCOLOUR", "const float", CS|MENU, "The FrameBuffer texture index to write colour info into. 1-based. Additional arguments are: format (rgba8=1,rgba16f=2,rgba32f=3), sizexy. Written to by both 3d and 2d rendering.", VF_RT_DESTCOLOUR},
|
||||
{"VF_RT_DESTCOLOUR", "const float", CS|MENU, "The FrameBuffer texture index to write colour info into. 1-based. Additional arguments are: format (rgba8=1,rgba16f=2,rgba32f=3), sizexy. Written to by both 3d and 2d rendering. Note that any rendertargets may be destroyed on video mode changes or so.", VF_RT_DESTCOLOUR},
|
||||
{"VF_RT_SOURCECOLOUR", "const float", CS|MENU, "The FrameBuffer texture index to use with shaders that specify a $sourcecolour map.", VF_RT_SOURCECOLOUR},
|
||||
{"VF_RT_DEPTH", "const float", CS|MENU, "The FrameBuffer texture index to use as a depth buffer. Also used for shaders that specify $sourcedepth. 1-based. Additional arguments are: format (16=4,24=5,32=6), sizexy.", VF_RT_DEPTH},
|
||||
{"VF_RT_DEPTH", "const float", CS|MENU, "The FrameBuffer texture index to use as a depth buffer. Also used for shaders that specify $sourcedepth. 1-based. Additional arguments are: format (16bit=4,24bit=5,32bit=6), sizexy.", VF_RT_DEPTH},
|
||||
{"VF_RT_RIPPLE", "const float", CS|MENU, "The FrameBuffer texture index to use as a ripplemap (target for shaders with 'sort ripple'). Also used for shaders that specify $ripplemap. 1-based. Additional arguments are: format, sizexy.", VF_RT_RIPPLE},
|
||||
|
||||
{"RF_VIEWMODEL", "const float", CS, "Specifies that the entity is a view model, and that its origin is relative to the current view position. These entities are also subject to viewweapon bob.", CSQCRF_VIEWMODEL},
|
||||
|
|
|
@ -1403,6 +1403,7 @@ void SV_LogPlayer(client_t *cl, char *msg);
|
|||
|
||||
extern vec3_t pmove_mins, pmove_maxs; //abs min/max extents
|
||||
void AddLinksToPmove ( edict_t *player, areanode_t *node );
|
||||
void AddLinksToPmove_Force ( edict_t *player, areanode_t *node );
|
||||
|
||||
|
||||
#ifdef HLSERVER
|
||||
|
|
|
@ -1989,7 +1989,7 @@ void WPhys_MoveChain(world_t *w, wedict_t *ent, wedict_t *movechain, float *init
|
|||
for(i=16;i && movechain != w->edicts && !movechain->isfree;i--, movechain = PROG_TO_WEDICT(w->progs, movechain->xv->movechain))
|
||||
{
|
||||
if ((int)movechain->v->flags & FL_MOVECHAIN_ANGLE)
|
||||
VectorAdd(movechain->v->angles, moveang, movechain->v->angles);
|
||||
VectorAdd(movechain->v->angles, moveang, movechain->v->angles); //FIXME: axial only
|
||||
VectorAdd(movechain->v->origin, moveorg, movechain->v->origin);
|
||||
|
||||
if (movechain->xv->chainmoved && callfunc)
|
||||
|
|
|
@ -5488,6 +5488,71 @@ float V_CalcRoll (vec3_t angles, vec3_t velocity)
|
|||
|
||||
vec3_t pmove_mins, pmove_maxs;
|
||||
|
||||
static qboolean AddEntityToPmove(edict_t *player, edict_t *check)
|
||||
{
|
||||
physent_t *pe;
|
||||
int solid = check->v->solid;
|
||||
int q1contents;
|
||||
|
||||
if (pmove.numphysent == MAX_PHYSENTS)
|
||||
return false;
|
||||
pe = &pmove.physents[pmove.numphysent];
|
||||
pe->notouch = !((int)player->xv->dimension_solid & (int)check->xv->dimension_hit);
|
||||
if (!((int)player->xv->dimension_hit & (int)check->xv->dimension_solid))
|
||||
return true;
|
||||
if (!check->v->size[0]) //points are not meant to be solid
|
||||
return true;
|
||||
pmove.numphysent++;
|
||||
|
||||
VectorCopy (check->v->origin, pe->origin);
|
||||
pe->info = NUM_FOR_EDICT(svprogfuncs, check);
|
||||
pe->nonsolid = solid == SOLID_TRIGGER;
|
||||
pe->isportal = solid == SOLID_PORTAL;
|
||||
q1contents = (int)check->v->skin;
|
||||
if (solid == SOLID_LADDER)
|
||||
q1contents = Q1CONTENTS_LADDER; //legacy crap
|
||||
switch(q1contents)
|
||||
{
|
||||
case Q1CONTENTS_WATER:
|
||||
pe->nonsolid = true;
|
||||
pe->forcecontentsmask = FTECONTENTS_WATER;
|
||||
break;
|
||||
case Q1CONTENTS_LAVA:
|
||||
pe->nonsolid = true;
|
||||
pe->forcecontentsmask = FTECONTENTS_LAVA;
|
||||
break;
|
||||
case Q1CONTENTS_SLIME:
|
||||
pe->nonsolid = true;
|
||||
pe->forcecontentsmask = FTECONTENTS_SLIME;
|
||||
break;
|
||||
case Q1CONTENTS_SKY:
|
||||
pe->nonsolid = true;
|
||||
pe->forcecontentsmask = FTECONTENTS_SKY;
|
||||
break;
|
||||
case Q1CONTENTS_LADDER:
|
||||
pe->nonsolid = true;
|
||||
pe->forcecontentsmask = FTECONTENTS_LADDER;
|
||||
break;
|
||||
default:
|
||||
pe->forcecontentsmask = 0;
|
||||
break;
|
||||
}
|
||||
if (solid == SOLID_PORTAL || solid == SOLID_BSP)
|
||||
{
|
||||
if(progstype != PROG_H2)
|
||||
pe->angles[0]*=-1; //quake is wierd. I guess someone fixed it hexen2... or my code is buggy or something...
|
||||
pe->model = sv.models[(int)(check->v->modelindex)];
|
||||
VectorCopy (check->v->angles, pe->angles);
|
||||
}
|
||||
else
|
||||
{
|
||||
pe->model = NULL;
|
||||
VectorCopy (check->v->mins, pe->mins);
|
||||
VectorCopy (check->v->maxs, pe->maxs);
|
||||
VectorClear (pe->angles);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/*
|
||||
====================
|
||||
AddLinksToPmove
|
||||
|
@ -5502,9 +5567,6 @@ void AddLinksToPmove ( edict_t *player, areanode_t *node )
|
|||
int pl;
|
||||
int i;
|
||||
int solid;
|
||||
physent_t *pe;
|
||||
|
||||
model_t *model;
|
||||
|
||||
pl = EDICT_TO_PROG(svprogfuncs, player);
|
||||
|
||||
|
@ -5525,6 +5587,7 @@ void AddLinksToPmove ( edict_t *player, areanode_t *node )
|
|||
|| solid == SOLID_PORTAL
|
||||
|| solid == SOLID_BBOX
|
||||
|| solid == SOLID_SLIDEBOX
|
||||
|| solid == SOLID_LADDER
|
||||
//|| (solid == SOLID_PHASEH2 && progstype == PROG_H2) //logically matches hexen2, but I hate it
|
||||
)
|
||||
{
|
||||
|
@ -5536,92 +5599,8 @@ void AddLinksToPmove ( edict_t *player, areanode_t *node )
|
|||
if (i != 3)
|
||||
continue;
|
||||
|
||||
if (pmove.numphysent == MAX_PHYSENTS)
|
||||
if (!AddEntityToPmove(player, check))
|
||||
break;
|
||||
pe = &pmove.physents[pmove.numphysent];
|
||||
pe->notouch = !((int)player->xv->dimension_solid & (int)check->xv->dimension_hit);
|
||||
if (!((int)player->xv->dimension_hit & (int)check->xv->dimension_solid))
|
||||
continue;
|
||||
if (!check->v->size[0]) //points are not meant to be solid
|
||||
continue;
|
||||
pmove.numphysent++;
|
||||
|
||||
VectorCopy (check->v->origin, pe->origin);
|
||||
pe->info = NUM_FOR_EDICT(svprogfuncs, check);
|
||||
pe->nonsolid = solid == SOLID_TRIGGER;
|
||||
pe->isportal = solid == SOLID_PORTAL;
|
||||
switch((int)check->v->skin)
|
||||
{
|
||||
case Q1CONTENTS_WATER:
|
||||
pe->nonsolid = true;
|
||||
pe->forcecontentsmask = FTECONTENTS_WATER;
|
||||
break;
|
||||
case Q1CONTENTS_LAVA:
|
||||
pe->nonsolid = true;
|
||||
pe->forcecontentsmask = FTECONTENTS_LAVA;
|
||||
break;
|
||||
case Q1CONTENTS_SLIME:
|
||||
pe->nonsolid = true;
|
||||
pe->forcecontentsmask = FTECONTENTS_SLIME;
|
||||
break;
|
||||
case Q1CONTENTS_SKY:
|
||||
pe->nonsolid = true;
|
||||
pe->forcecontentsmask = FTECONTENTS_SKY;
|
||||
break;
|
||||
case Q1CONTENTS_LADDER:
|
||||
pe->nonsolid = true;
|
||||
pe->forcecontentsmask = FTECONTENTS_LADDER;
|
||||
break;
|
||||
default:
|
||||
pe->forcecontentsmask = 0;
|
||||
break;
|
||||
}
|
||||
if (solid == SOLID_PORTAL || solid == SOLID_BSP)
|
||||
{
|
||||
if(progstype != PROG_H2)
|
||||
pe->angles[0]*=-1; //quake is wierd. I guess someone fixed it hexen2... or my code is buggy or something...
|
||||
pe->model = sv.models[(int)(check->v->modelindex)];
|
||||
VectorCopy (check->v->angles, pe->angles);
|
||||
}
|
||||
else
|
||||
{
|
||||
pe->model = NULL;
|
||||
VectorCopy (check->v->mins, pe->mins);
|
||||
VectorCopy (check->v->maxs, pe->maxs);
|
||||
VectorClear (pe->angles);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (player->v->mins[2] != 24) //crouching/dead
|
||||
for (l = node->edicts.next ; l != &node->edicts ; l = next)
|
||||
{
|
||||
next = l->next;
|
||||
check = (edict_t*)EDICT_FROM_AREA(l);
|
||||
|
||||
if (check->v->owner == pl)
|
||||
continue; // player's own missile
|
||||
if (check->v->solid == SOLID_LADDER)
|
||||
{
|
||||
for (i=0 ; i<3 ; i++)
|
||||
if (check->v->absmin[i] > pmove_maxs[i]
|
||||
|| check->v->absmax[i] < pmove_mins[i])
|
||||
break;
|
||||
if (i != 3)
|
||||
continue;
|
||||
|
||||
if (!((int)player->xv->dimension_hit & (int)check->xv->dimension_solid))
|
||||
continue;
|
||||
|
||||
model = sv.models[(int)check->v->modelindex];
|
||||
if (model)
|
||||
{
|
||||
vec3_t axis[3];
|
||||
AngleVectors(check->v->angles, axis[0], axis[1], axis[2]);
|
||||
VectorNegate(axis[1], axis[1]);
|
||||
// test the point
|
||||
if (model->funcs.PointContents (model, axis, player->v->origin) == FTECONTENTS_SOLID)
|
||||
player->xv->pmove_flags = (int)player->xv->pmove_flags | PMF_LADDER; //touch that ladder!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5635,6 +5614,54 @@ void AddLinksToPmove ( edict_t *player, areanode_t *node )
|
|||
AddLinksToPmove (player, node->children[1]);
|
||||
}
|
||||
|
||||
//ignores mins/maxs.
|
||||
//portals are expected to be weird. player movement code is nasty.
|
||||
void AddLinksToPmove_Force ( edict_t *player, areanode_t *node )
|
||||
{
|
||||
link_t *l, *next;
|
||||
edict_t *check;
|
||||
int pl;
|
||||
int i;
|
||||
int solid;
|
||||
|
||||
pl = EDICT_TO_PROG(svprogfuncs, player);
|
||||
|
||||
// touch linked edicts
|
||||
for (l = node->edicts.next ; l != &node->edicts ; l = next)
|
||||
{
|
||||
next = l->next;
|
||||
check = (edict_t*)EDICT_FROM_AREA(l);
|
||||
|
||||
if (check->v->owner == pl)
|
||||
continue; // player's own missile
|
||||
if (check == player)
|
||||
continue;
|
||||
solid = check->v->solid;
|
||||
if (
|
||||
(solid == SOLID_TRIGGER && check->v->skin < 0)
|
||||
|| solid == SOLID_BSP
|
||||
|| solid == SOLID_PORTAL
|
||||
|| solid == SOLID_BBOX
|
||||
|| solid == SOLID_SLIDEBOX
|
||||
|| solid == SOLID_LADDER
|
||||
//|| (solid == SOLID_PHASEH2 && progstype == PROG_H2) //logically matches hexen2, but I hate it
|
||||
)
|
||||
{
|
||||
if (!AddEntityToPmove(player, check))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// recurse down both sides
|
||||
if (node->axis == -1)
|
||||
return;
|
||||
|
||||
if (pmove_maxs[node->axis] > node->dist)
|
||||
AddLinksToPmove_Force (player, node->children[0]);
|
||||
if (pmove_mins[node->axis] < node->dist)
|
||||
AddLinksToPmove_Force (player, node->children[1]);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
|
@ -5643,15 +5670,14 @@ AddAllEntsToPmove
|
|||
For debugging
|
||||
================
|
||||
*/
|
||||
void AddAllEntsToPmove (void)
|
||||
void AddAllEntsToPmove (edict_t *player)
|
||||
{
|
||||
int e;
|
||||
edict_t *check;
|
||||
int i;
|
||||
physent_t *pe;
|
||||
int pl;
|
||||
|
||||
pl = EDICT_TO_PROG(svprogfuncs, sv_player);
|
||||
pl = EDICT_TO_PROG(svprogfuncs, player);
|
||||
for (e=1 ; e<sv.world.num_edicts ; e++)
|
||||
{
|
||||
check = EDICT_NUM(svprogfuncs, e);
|
||||
|
@ -5663,7 +5689,7 @@ void AddAllEntsToPmove (void)
|
|||
|| check->v->solid == SOLID_BBOX
|
||||
|| check->v->solid == SOLID_SLIDEBOX)
|
||||
{
|
||||
if (check == sv_player)
|
||||
if (check == player)
|
||||
continue;
|
||||
|
||||
for (i=0 ; i<3 ; i++)
|
||||
|
@ -5672,24 +5698,8 @@ void AddAllEntsToPmove (void)
|
|||
break;
|
||||
if (i != 3)
|
||||
continue;
|
||||
pe = &pmove.physents[pmove.numphysent];
|
||||
|
||||
VectorCopy (check->v->origin, pe->origin);
|
||||
pmove.physents[pmove.numphysent].info = e;
|
||||
if (check->v->solid == SOLID_BSP)
|
||||
{
|
||||
VectorCopy (check->v->angles, pe->angles);
|
||||
pe->model = sv.models[(int)(check->v->modelindex)];
|
||||
}
|
||||
else
|
||||
{
|
||||
pe->angles[0] = pe->angles[1] = pe->angles[2] = 0;
|
||||
pe->model = NULL;
|
||||
VectorCopy (check->v->mins, pe->mins);
|
||||
VectorCopy (check->v->maxs, pe->maxs);
|
||||
}
|
||||
|
||||
if (++pmove.numphysent == MAX_PHYSENTS)
|
||||
if (!AddEntityToPmove(player, check))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -6048,9 +6058,9 @@ void SV_RunCmd (usercmd_t *ucmd, qboolean recurse)
|
|||
pmove.player_maxs[2] = sv_player->v->maxs[2];
|
||||
|
||||
VectorCopy(sv_player->xv->gravitydir, pmove.gravitydir);
|
||||
|
||||
for (i=0 ; i<3 ; i++)
|
||||
pmove.origin[i] = sv_player->v->origin[i];// + (sv_player->v->mins[i] - player_mins[i]);
|
||||
VectorCopy(sv_player->v->origin, pmove.origin);
|
||||
VectorCopy(sv_player->v->oldorigin, pmove.safeorigin);
|
||||
pmove.safeorigin_known = true;
|
||||
|
||||
VectorCopy (sv_player->v->velocity, pmove.velocity);
|
||||
VectorCopy (sv_player->v->v_angle, pmove.angles);
|
||||
|
@ -6090,8 +6100,9 @@ void SV_RunCmd (usercmd_t *ucmd, qboolean recurse)
|
|||
#if 1
|
||||
AddLinksToPmove ( sv_player, sv.world.areanodes );
|
||||
#else
|
||||
AddAllEntsToPmove ();
|
||||
AddAllEntsToPmove (sv_player);
|
||||
#endif
|
||||
AddLinksToPmove_Force ( sv_player, &sv.world.portallist );
|
||||
|
||||
if ((int)sv_player->xv->pmove_flags & PMF_LADDER)
|
||||
pmove.onladder = true;
|
||||
|
@ -6168,6 +6179,7 @@ if (sv_player->v->health > 0 && before && !after )
|
|||
else
|
||||
sv_player->v->flags = (int)sv_player->v->flags & ~FL_ONGROUND;
|
||||
|
||||
VectorCopy (pmove.safeorigin, sv_player->v->oldorigin);
|
||||
VectorCopy (pmove.origin, sv_player->v->origin);
|
||||
VectorCopy (pmove.angles, sv_player->v->v_angle);
|
||||
|
||||
|
|
|
@ -181,6 +181,10 @@ void World_ClearWorld (world_t *w)
|
|||
{
|
||||
World_InitBoxHull ();
|
||||
|
||||
memset (&w->portallist, 0, sizeof(w->portallist));
|
||||
ClearLink (&w->portallist.edicts);
|
||||
w->portallist.axis = -1;
|
||||
|
||||
memset (w->areanodes, 0, sizeof(w->areanodes));
|
||||
w->numareanodes = 0;
|
||||
if (!w->worldmodel)
|
||||
|
@ -473,17 +477,22 @@ void World_LinkEdict (world_t *w, wedict_t *ent, qboolean touch_triggers)
|
|||
}
|
||||
|
||||
// find the first node that the ent's box crosses
|
||||
node = w->areanodes;
|
||||
while (1)
|
||||
if (ent->v->solid == SOLID_PORTAL)
|
||||
node = &w->portallist;
|
||||
else
|
||||
{
|
||||
if (node->axis == -1)
|
||||
break;
|
||||
if (ent->v->absmin[node->axis] > node->dist)
|
||||
node = node->children[0];
|
||||
else if (ent->v->absmax[node->axis] < node->dist)
|
||||
node = node->children[1];
|
||||
else
|
||||
break; // crosses the node
|
||||
node = w->areanodes;
|
||||
while (1)
|
||||
{
|
||||
if (node->axis == -1)
|
||||
break;
|
||||
if (ent->v->absmin[node->axis] > node->dist)
|
||||
node = node->children[0];
|
||||
else if (ent->v->absmax[node->axis] < node->dist)
|
||||
node = node->children[1];
|
||||
else
|
||||
break; // crosses the node
|
||||
}
|
||||
}
|
||||
|
||||
// link it in
|
||||
|
@ -1966,6 +1975,7 @@ trace_t World_Move (world_t *w, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t e
|
|||
}
|
||||
else
|
||||
World_ClipToLinks (w, w->areanodes, &clip );
|
||||
World_ClipToLinks(w, &w->portallist, &clip);
|
||||
}
|
||||
|
||||
// if (clip.trace.startsolid)
|
||||
|
|
Loading…
Reference in a new issue