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.maxspeed = cl.playerview[pnum].maxspeed;
|
||||||
movevars.bunnyspeedcap = cl.bunnyspeedcap;
|
movevars.bunnyspeedcap = cl.bunnyspeedcap;
|
||||||
pmove.onladder = false;
|
pmove.onladder = false;
|
||||||
|
pmove.safeorigin_known = false;
|
||||||
|
|
||||||
VectorCopy(from->szmins, pmove.player_mins);
|
VectorCopy(from->szmins, pmove.player_mins);
|
||||||
VectorCopy(from->szmaxs, pmove.player_maxs);
|
VectorCopy(from->szmaxs, pmove.player_maxs);
|
||||||
|
|
|
@ -120,7 +120,6 @@ static DWORD dwAxisFlags[JOY_MAX_AXES] =
|
||||||
|
|
||||||
static DWORD dwAxisMap[JOY_MAX_AXES];
|
static DWORD dwAxisMap[JOY_MAX_AXES];
|
||||||
static DWORD dwControlMap[JOY_MAX_AXES];
|
static DWORD dwControlMap[JOY_MAX_AXES];
|
||||||
static PDWORD pdwRawValue[JOY_MAX_AXES];
|
|
||||||
|
|
||||||
// none of these cvars are saved over a session
|
// none of these cvars are saved over a session
|
||||||
// this means that advanced controller configuration needs to be executed
|
// 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_wwhack1 = CVAR("joywwhack1", "0.0");
|
||||||
static cvar_t joy_wwhack2 = CVAR("joywwhack2", "0.0");
|
static cvar_t joy_wwhack2 = CVAR("joywwhack2", "0.0");
|
||||||
|
|
||||||
static qboolean joy_avail, joy_advancedinit, joy_haspov;
|
static qboolean joy_advancedinit;
|
||||||
static DWORD joy_oldbuttonstate, joy_oldpovstate;
|
|
||||||
|
|
||||||
static int joy_id;
|
|
||||||
static DWORD joy_flags;
|
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
|
#ifdef AVAIL_DINPUT
|
||||||
static const GUID fGUID_XAxis = {0xA36D02E0, 0xC9F3, 0x11CF, {0xBF, 0xC7, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}};
|
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)
|
if (ActiveApp && !Minimized)
|
||||||
{
|
{
|
||||||
INS_MouseMove (movements, pnum);
|
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
|
INS_StartupJoystick
|
||||||
===============
|
===============
|
||||||
*/
|
*/
|
||||||
void INS_StartupJoystick (void)
|
static void INS_StartupJoystickId(unsigned int id)
|
||||||
{
|
{
|
||||||
int numdevs;
|
|
||||||
JOYCAPS jc;
|
JOYCAPS jc;
|
||||||
MMRESULT mmr;
|
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
|
// get the capabilities of the selected joystick
|
||||||
joy_avail = false;
|
// 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
|
// abort startup if user requests no joystick
|
||||||
if ( COM_CheckParm ("-nojoy") )
|
if ( COM_CheckParm ("-nojoy") )
|
||||||
|
@ -1559,75 +1598,21 @@ void INS_StartupJoystick (void)
|
||||||
mmr = JOYERR_UNPLUGGED;
|
mmr = JOYERR_UNPLUGGED;
|
||||||
|
|
||||||
// cycle through the joystick ids for the first valid one
|
// 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));
|
memset (&ji, 0, sizeof(ji));
|
||||||
ji.dwSize = sizeof(ji);
|
ji.dwSize = sizeof(ji);
|
||||||
ji.dwFlags = JOY_RETURNCENTERED;
|
ji.dwFlags = JOY_RETURNCENTERED;
|
||||||
|
|
||||||
if ((mmr = joyGetPosEx (joy_id, &ji)) == JOYERR_NOERROR)
|
if ((mmr = joyGetPosEx (id, &ji)) == JOYERR_NOERROR)
|
||||||
break;
|
{
|
||||||
|
INS_StartupJoystickId(id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// abort startup if we didn't find a valid joystick
|
Con_Printf ("found %i joysticks\n", joy_count);
|
||||||
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");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
===========
|
|
||||||
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
|
Joy_AdvancedUpdate_f
|
||||||
|
@ -1646,7 +1631,6 @@ void Joy_AdvancedUpdate_f (void)
|
||||||
{
|
{
|
||||||
dwAxisMap[i] = AxisNada;
|
dwAxisMap[i] = AxisNada;
|
||||||
dwControlMap[i] = JOY_ABSOLUTE_AXIS;
|
dwControlMap[i] = JOY_ABSOLUTE_AXIS;
|
||||||
pdwRawValue[i] = RawValuePointer(i);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( joy_advanced.value == 0.0)
|
if( joy_advanced.value == 0.0)
|
||||||
|
@ -1709,63 +1693,64 @@ void INS_Commands (void)
|
||||||
{
|
{
|
||||||
int i, key_index;
|
int i, key_index;
|
||||||
DWORD buttonstate, povstate;
|
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
|
||||||
// loop through the joystick buttons
|
// key a joystick event or auxillary event for higher number buttons for each state change
|
||||||
// key a joystick event or auxillary event for higher number buttons for each state change
|
buttonstate = joy->buttonstate;
|
||||||
buttonstate = ji.dwButtons;
|
for (i=0 ; i < joy->numbuttons ; i++)
|
||||||
for (i=0 ; i < joy_numbuttons ; i++)
|
|
||||||
{
|
|
||||||
if ( (buttonstate & (1<<i)) && !(joy_oldbuttonstate & (1<<i)) )
|
|
||||||
{
|
{
|
||||||
key_index = (i < 4) ? K_JOY1 : K_AUX1;
|
if ( (buttonstate & (1<<i)) && !(joy->oldbuttonstate & (1<<i)) )
|
||||||
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)) )
|
|
||||||
{
|
{
|
||||||
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
|
INS_ReadJoystick
|
||||||
===============
|
===============
|
||||||
*/
|
*/
|
||||||
qboolean INS_ReadJoystick (void)
|
qboolean INS_ReadJoystick (struct wjoy_s *joy)
|
||||||
{
|
{
|
||||||
|
|
||||||
memset (&ji, 0, sizeof(ji));
|
memset (&ji, 0, sizeof(ji));
|
||||||
ji.dwSize = sizeof(ji);
|
ji.dwSize = sizeof(ji);
|
||||||
ji.dwFlags = joy_flags;
|
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
|
// 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
|
// 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;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1804,34 +1796,27 @@ qboolean INS_ReadJoystick (void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void INS_JoyMovePtr (struct wjoy_s *joy, float *movements, int pnum)
|
||||||
/*
|
|
||||||
===========
|
|
||||||
INS_JoyMove
|
|
||||||
===========
|
|
||||||
*/
|
|
||||||
void INS_JoyMove (float *movements, int pnum)
|
|
||||||
{
|
{
|
||||||
float speed, aspeed;
|
float speed, aspeed;
|
||||||
float fAxisValue, fTemp;
|
float fAxisValue, fTemp;
|
||||||
int i;
|
int i;
|
||||||
|
int wpnum;
|
||||||
|
|
||||||
// complete initialization if first time in
|
/*each device will be processed when its player comes to be processed*/
|
||||||
// this is needed as cvars are not available at initialization time
|
wpnum = cl.splitclients;
|
||||||
if( joy_advancedinit != true )
|
if (wpnum < 1)
|
||||||
{
|
wpnum = 1;
|
||||||
Joy_AdvancedUpdate_f();
|
if (cl_forcesplitclient.ival)
|
||||||
joy_advancedinit = true;
|
wpnum = (cl_forcesplitclient.ival-1) % wpnum;
|
||||||
}
|
else
|
||||||
|
wpnum = joy->devid % wpnum;
|
||||||
// verify joystick is available and that the user wants to use it
|
if (wpnum != pnum)
|
||||||
if (!joy_avail || !in_joystick.value)
|
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
// collect the joystick data, if possible
|
// collect the joystick data, if possible
|
||||||
if (INS_ReadJoystick () != true)
|
if (INS_ReadJoystick (joy) != true)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1846,7 +1831,7 @@ void INS_JoyMove (float *movements, int pnum)
|
||||||
for (i = 0; i < JOY_MAX_AXES; i++)
|
for (i = 0; i < JOY_MAX_AXES; i++)
|
||||||
{
|
{
|
||||||
// get the floating point zero-centered, potentially-inverted data for the current axis
|
// 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
|
// move centerpoint to zero
|
||||||
fAxisValue -= 32768.0;
|
fAxisValue -= 32768.0;
|
||||||
|
|
||||||
|
@ -1870,7 +1855,7 @@ void INS_JoyMove (float *movements, int pnum)
|
||||||
fAxisValue /= 32768.0;
|
fAxisValue /= 32768.0;
|
||||||
|
|
||||||
#ifdef CSQC_DAT
|
#ifdef CSQC_DAT
|
||||||
if (CSQC_JoystickAxis(i, fAxisValue, 0))
|
if (CSQC_JoystickAxis(i, fAxisValue, joy->devid))
|
||||||
continue;
|
continue;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1983,6 +1968,32 @@ void INS_JoyMove (float *movements, int pnum)
|
||||||
|
|
||||||
CL_ClampPitch(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[] =
|
static qbyte scantokey[] =
|
||||||
{
|
{
|
||||||
|
|
|
@ -2133,6 +2133,7 @@ void Key_Event (int devid, int key, unsigned int unicode, qboolean down)
|
||||||
if (key_repeats[key] > 1)
|
if (key_repeats[key] > 1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
//first player is normally assumed anyway.
|
||||||
if (devid)
|
if (devid)
|
||||||
Q_snprintfz (p, sizeof(p), "p %i ", devid+1);
|
Q_snprintfz (p, sizeof(p), "p %i ", devid+1);
|
||||||
else
|
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.sidemove = csqcg.input_movevalues[1];
|
||||||
pmove.cmd.upmove = csqcg.input_movevalues[2];
|
pmove.cmd.upmove = csqcg.input_movevalues[2];
|
||||||
pmove.cmd.buttons = *csqcg.input_buttons;
|
pmove.cmd.buttons = *csqcg.input_buttons;
|
||||||
|
pmove.safeorigin_known = false;
|
||||||
|
|
||||||
if (ent)
|
if (ent)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1129,7 +1129,7 @@ qboolean rag_animate(skelobject_t *sko, doll_t *doll, float *emat)
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < sko->numbodies; i++)
|
for (i = 0; i < sko->numbodies; i++)
|
||||||
{
|
{
|
||||||
if (!doll->body[i].animate)
|
if (!sko->body[i].animstrength)
|
||||||
continue;
|
continue;
|
||||||
rag_genbodymatrix(sko, &doll->body[i], emat, sko->body[i].animmatrix);
|
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++)
|
for (j = 0; j < sko->numbodies; j++)
|
||||||
{
|
{
|
||||||
if (!doll->body[j].animate)
|
if (!sko->body[j].animstrength)
|
||||||
continue;
|
continue;
|
||||||
World_ODE_RagMatrixToBody(&sko->body[j].odebody, sko->body[j].animmatrix);
|
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)
|
else if (!doll)
|
||||||
{
|
{
|
||||||
G_FLOAT(OFS_RETURN) = 1; //technically success.
|
G_FLOAT(OFS_RETURN) = !!*ragname; //technically success.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (sko->numanimated)
|
else if (sko->numanimated)
|
||||||
|
|
|
@ -3857,7 +3857,7 @@ qboolean Mod_GetTag(model_t *model, int tagnum, framestate_t *fstate, float *res
|
||||||
result[10] = 1;
|
result[10] = 1;
|
||||||
while(tagnum >= 0)
|
while(tagnum >= 0)
|
||||||
{
|
{
|
||||||
for (lerp = lerps; tagnum < lerp->endbone; lerp++)
|
for (lerp = lerps; tagnum < lerp->firstbone; lerp++)
|
||||||
;
|
;
|
||||||
//set up the per-bone transform matrix
|
//set up the per-bone transform matrix
|
||||||
matrix = lerp->pose[0] + tagnum*12;
|
matrix = lerp->pose[0] + tagnum*12;
|
||||||
|
|
|
@ -228,16 +228,9 @@ Netchan_Init
|
||||||
*/
|
*/
|
||||||
void Netchan_Init (void)
|
void Netchan_Init (void)
|
||||||
{
|
{
|
||||||
|
static char qportstr[16];
|
||||||
int port;
|
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
|
// pick a port value that should be nice and random
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
port = (time(NULL)) & 0xffff;
|
port = (time(NULL)) & 0xffff;
|
||||||
|
@ -246,8 +239,16 @@ void Netchan_Init (void)
|
||||||
#else
|
#else
|
||||||
port = ((int)(getpid()+getuid()*1000) * time(NULL)) & 0xffff;
|
port = ((int)(getpid()+getuid()*1000) * time(NULL)) & 0xffff;
|
||||||
#endif
|
#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"
|
#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;
|
qboolean okay = true;
|
||||||
wedict_t *portal = WEDICT_NUM(w->progs, portalnum);
|
wedict_t *portal = WEDICT_NUM(w->progs, portalnum);
|
||||||
int oself = *w->g.self;
|
int oself = *w->g.self;
|
||||||
void *pr_globals = PR_globals(w->progs, PR_CURRENT);
|
void *pr_globals = PR_globals(w->progs, PR_CURRENT);
|
||||||
|
int i;
|
||||||
|
int tmp;
|
||||||
|
|
||||||
*w->g.self = EDICT_TO_PROG(w->progs, portal);
|
*w->g.self = EDICT_TO_PROG(w->progs, portal);
|
||||||
//transform origin+velocity etc
|
//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);
|
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.
|
//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;
|
okay = false;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
VectorCopy(G_VECTOR(OFS_RETURN), org);
|
VectorCopy(rounded, org);
|
||||||
VectorCopy(w->g.v_forward, pmove.velocity);
|
VectorCopy(w->g.v_forward, newvel);
|
||||||
VectorCopy(w->g.v_right, move);
|
VectorCopy(w->g.v_right, move);
|
||||||
VectorCopy(w->g.v_up, pmove.gravitydir);
|
// VectorCopy(w->g.v_up, pmove.gravitydir);
|
||||||
|
|
||||||
|
|
||||||
//transform the angles too
|
//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));
|
VectorCopy(pmove.angles, G_VECTOR(OFS_PARM1));
|
||||||
AngleVectors(pmove.angles, w->g.v_forward, w->g.v_right, w->g.v_up);
|
AngleVectors(pmove.angles, w->g.v_forward, w->g.v_right, w->g.v_up);
|
||||||
PR_ExecuteProgram (w->progs, portal->xv->camera_transform);
|
PR_ExecuteProgram (w->progs, portal->xv->camera_transform);
|
||||||
VectorAngles(w->g.v_forward, w->g.v_up, pmove.angles);
|
VectorAngles(w->g.v_forward, w->g.v_up, newang);
|
||||||
pmove.angles[0] *= -1;
|
newang[0] *= -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
*w->g.self = oself;
|
*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 move;
|
||||||
vec3_t from;
|
vec3_t from;
|
||||||
|
vec3_t newang, newvel;
|
||||||
|
|
||||||
VectorCopy(trace.endpos, from); //just in case
|
VectorCopy(trace.endpos, from); //just in case
|
||||||
VectorSubtract(end, trace.endpos, move);
|
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);
|
VectorAdd(from, move, end);
|
||||||
|
|
||||||
//if we follow the portal, then we basically need to restart from the other side.
|
//if we follow the portal, then we basically need to restart from the other side.
|
||||||
if (tookportal)
|
exit = PM_PlayerTrace (from, end, MASK_PLAYERSOLID);
|
||||||
*tookportal = trace.fraction;
|
|
||||||
|
for (i = 0; i < 3; i++)
|
||||||
return PM_PlayerTrace (from, end, MASK_PLAYERSOLID);
|
{
|
||||||
|
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++)
|
for (i=0 ; i<3 ; i++)
|
||||||
base[i] = ((int)(base[i]*8)) * 0.125;
|
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))
|
if (PM_TestPlayerPosition (pmove.origin, false))
|
||||||
return;
|
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[0] = base[0] + (sign[x] * 1.0/8);
|
||||||
pmove.origin[1] = base[1] + (sign[y] * 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");
|
// Com_DPrintf ("NudgePosition: stuck\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1267,6 +1293,7 @@ void PM_PlayerMove (float gamespeed)
|
||||||
PM_ClipVelocity (pmove.velocity, groundplane.normal, pmove.velocity, 1);
|
PM_ClipVelocity (pmove.velocity, groundplane.normal, pmove.velocity, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
//round to network precision
|
//round to network precision
|
||||||
for (i = 0; i < 3; i++)
|
for (i = 0; i < 3; i++)
|
||||||
{
|
{
|
||||||
|
@ -1275,4 +1302,5 @@ void PM_PlayerMove (float gamespeed)
|
||||||
tmp = floor(pmove.origin[i]*8 + 0.5);
|
tmp = floor(pmove.origin[i]*8 + 0.5);
|
||||||
pmove.origin[i] = tmp/8.0;
|
pmove.origin[i] = tmp/8.0;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,6 +56,7 @@ typedef struct
|
||||||
|
|
||||||
// player state
|
// player state
|
||||||
vec3_t origin;
|
vec3_t origin;
|
||||||
|
vec3_t safeorigin;
|
||||||
vec3_t angles;
|
vec3_t angles;
|
||||||
vec3_t velocity;
|
vec3_t velocity;
|
||||||
vec3_t basevelocity;
|
vec3_t basevelocity;
|
||||||
|
@ -75,6 +76,7 @@ typedef struct
|
||||||
usercmd_t cmd;
|
usercmd_t cmd;
|
||||||
|
|
||||||
qboolean onladder;
|
qboolean onladder;
|
||||||
|
qboolean safeorigin_known;
|
||||||
|
|
||||||
// results
|
// results
|
||||||
int skipent;
|
int skipent;
|
||||||
|
|
|
@ -358,13 +358,14 @@ PM_TestPlayerPosition
|
||||||
Returns false if the given player position is not valid (in solid)
|
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;
|
int i, j;
|
||||||
physent_t *pe;
|
physent_t *pe;
|
||||||
vec3_t mins, maxs;
|
vec3_t mins, maxs;
|
||||||
hull_t *hull;
|
hull_t *hull;
|
||||||
trace_t trace;
|
trace_t trace;
|
||||||
|
int csged = false;
|
||||||
|
|
||||||
for (i=0 ; i< pmove.numphysent ; i++)
|
for (i=0 ; i< pmove.numphysent ; i++)
|
||||||
{
|
{
|
||||||
|
@ -416,6 +417,7 @@ qboolean PM_TestPlayerPosition (vec3_t pos, qboolean ignoreportals)
|
||||||
}
|
}
|
||||||
if (trace.allsolid)
|
if (trace.allsolid)
|
||||||
return false;
|
return false;
|
||||||
|
csged = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3019,6 +3019,13 @@ void QCBUILTIN PF_strftime (pubprogfuncs_t *prinst, struct globalvars_s *pr_glob
|
||||||
tm = localtime(&ctime);
|
tm = localtime(&ctime);
|
||||||
else
|
else
|
||||||
tm = gmtime(&ctime);
|
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);
|
strftime(result, sizeof(result), in, tm);
|
||||||
unicode_strtoupper(result, uresult, sizeof(uresult), VMUTF8MARKUP);
|
unicode_strtoupper(result, uresult, sizeof(uresult), VMUTF8MARKUP);
|
||||||
|
|
||||||
|
|
|
@ -167,6 +167,7 @@ struct world_s
|
||||||
model_t *worldmodel;
|
model_t *worldmodel;
|
||||||
areanode_t areanodes[AREA_NODES];
|
areanode_t areanodes[AREA_NODES];
|
||||||
int numareanodes;
|
int numareanodes;
|
||||||
|
areanode_t portallist;
|
||||||
|
|
||||||
double physicstime; // the last time global physics were run
|
double physicstime; // the last time global physics were run
|
||||||
unsigned int framenum;
|
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.upmove = (pr_global_struct->input_movevalues)[2];
|
||||||
pmove.cmd.buttons = pr_global_struct->input_buttons;
|
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->origin, pmove.origin);
|
||||||
VectorCopy(ent->v->velocity, pmove.velocity);
|
VectorCopy(ent->v->velocity, pmove.velocity);
|
||||||
VectorCopy(ent->v->maxs, pmove.player_maxs);
|
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);
|
AddLinksToPmove(ent, sv.world.areanodes);
|
||||||
// AddAllEntsToPmove();
|
// AddAllEntsToPmove();
|
||||||
|
AddLinksToPmove_Force ( ent, &sv.world.portallist );
|
||||||
|
|
||||||
SV_PreRunCmd();
|
SV_PreRunCmd();
|
||||||
|
|
||||||
|
@ -8650,6 +8653,7 @@ static void QCBUILTIN PF_runclientphys(pubprogfuncs_t *prinst, struct globalvars
|
||||||
else
|
else
|
||||||
ent->v->teleport_time = pmove.waterjumptime;
|
ent->v->teleport_time = pmove.waterjumptime;
|
||||||
VectorCopy(pmove.origin, ent->v->origin);
|
VectorCopy(pmove.origin, ent->v->origin);
|
||||||
|
VectorCopy(pmove.safeorigin, ent->v->oldorigin);
|
||||||
VectorCopy(pmove.velocity, ent->v->velocity);
|
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_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_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_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},
|
{"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},
|
{"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
|
extern vec3_t pmove_mins, pmove_maxs; //abs min/max extents
|
||||||
void AddLinksToPmove ( edict_t *player, areanode_t *node );
|
void AddLinksToPmove ( edict_t *player, areanode_t *node );
|
||||||
|
void AddLinksToPmove_Force ( edict_t *player, areanode_t *node );
|
||||||
|
|
||||||
|
|
||||||
#ifdef HLSERVER
|
#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))
|
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)
|
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);
|
VectorAdd(movechain->v->origin, moveorg, movechain->v->origin);
|
||||||
|
|
||||||
if (movechain->xv->chainmoved && callfunc)
|
if (movechain->xv->chainmoved && callfunc)
|
||||||
|
|
|
@ -5488,6 +5488,71 @@ float V_CalcRoll (vec3_t angles, vec3_t velocity)
|
||||||
|
|
||||||
vec3_t pmove_mins, pmove_maxs;
|
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
|
AddLinksToPmove
|
||||||
|
@ -5502,9 +5567,6 @@ void AddLinksToPmove ( edict_t *player, areanode_t *node )
|
||||||
int pl;
|
int pl;
|
||||||
int i;
|
int i;
|
||||||
int solid;
|
int solid;
|
||||||
physent_t *pe;
|
|
||||||
|
|
||||||
model_t *model;
|
|
||||||
|
|
||||||
pl = EDICT_TO_PROG(svprogfuncs, player);
|
pl = EDICT_TO_PROG(svprogfuncs, player);
|
||||||
|
|
||||||
|
@ -5525,6 +5587,7 @@ void AddLinksToPmove ( edict_t *player, areanode_t *node )
|
||||||
|| solid == SOLID_PORTAL
|
|| solid == SOLID_PORTAL
|
||||||
|| solid == SOLID_BBOX
|
|| solid == SOLID_BBOX
|
||||||
|| solid == SOLID_SLIDEBOX
|
|| solid == SOLID_SLIDEBOX
|
||||||
|
|| solid == SOLID_LADDER
|
||||||
//|| (solid == SOLID_PHASEH2 && progstype == PROG_H2) //logically matches hexen2, but I hate it
|
//|| (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)
|
if (i != 3)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (pmove.numphysent == MAX_PHYSENTS)
|
if (!AddEntityToPmove(player, check))
|
||||||
break;
|
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]);
|
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
|
For debugging
|
||||||
================
|
================
|
||||||
*/
|
*/
|
||||||
void AddAllEntsToPmove (void)
|
void AddAllEntsToPmove (edict_t *player)
|
||||||
{
|
{
|
||||||
int e;
|
int e;
|
||||||
edict_t *check;
|
edict_t *check;
|
||||||
int i;
|
int i;
|
||||||
physent_t *pe;
|
|
||||||
int pl;
|
int pl;
|
||||||
|
|
||||||
pl = EDICT_TO_PROG(svprogfuncs, sv_player);
|
pl = EDICT_TO_PROG(svprogfuncs, player);
|
||||||
for (e=1 ; e<sv.world.num_edicts ; e++)
|
for (e=1 ; e<sv.world.num_edicts ; e++)
|
||||||
{
|
{
|
||||||
check = EDICT_NUM(svprogfuncs, e);
|
check = EDICT_NUM(svprogfuncs, e);
|
||||||
|
@ -5663,7 +5689,7 @@ void AddAllEntsToPmove (void)
|
||||||
|| check->v->solid == SOLID_BBOX
|
|| check->v->solid == SOLID_BBOX
|
||||||
|| check->v->solid == SOLID_SLIDEBOX)
|
|| check->v->solid == SOLID_SLIDEBOX)
|
||||||
{
|
{
|
||||||
if (check == sv_player)
|
if (check == player)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (i=0 ; i<3 ; i++)
|
for (i=0 ; i<3 ; i++)
|
||||||
|
@ -5672,24 +5698,8 @@ void AddAllEntsToPmove (void)
|
||||||
break;
|
break;
|
||||||
if (i != 3)
|
if (i != 3)
|
||||||
continue;
|
continue;
|
||||||
pe = &pmove.physents[pmove.numphysent];
|
|
||||||
|
|
||||||
VectorCopy (check->v->origin, pe->origin);
|
if (!AddEntityToPmove(player, check))
|
||||||
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)
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6048,9 +6058,9 @@ void SV_RunCmd (usercmd_t *ucmd, qboolean recurse)
|
||||||
pmove.player_maxs[2] = sv_player->v->maxs[2];
|
pmove.player_maxs[2] = sv_player->v->maxs[2];
|
||||||
|
|
||||||
VectorCopy(sv_player->xv->gravitydir, pmove.gravitydir);
|
VectorCopy(sv_player->xv->gravitydir, pmove.gravitydir);
|
||||||
|
VectorCopy(sv_player->v->origin, pmove.origin);
|
||||||
for (i=0 ; i<3 ; i++)
|
VectorCopy(sv_player->v->oldorigin, pmove.safeorigin);
|
||||||
pmove.origin[i] = sv_player->v->origin[i];// + (sv_player->v->mins[i] - player_mins[i]);
|
pmove.safeorigin_known = true;
|
||||||
|
|
||||||
VectorCopy (sv_player->v->velocity, pmove.velocity);
|
VectorCopy (sv_player->v->velocity, pmove.velocity);
|
||||||
VectorCopy (sv_player->v->v_angle, pmove.angles);
|
VectorCopy (sv_player->v->v_angle, pmove.angles);
|
||||||
|
@ -6090,8 +6100,9 @@ void SV_RunCmd (usercmd_t *ucmd, qboolean recurse)
|
||||||
#if 1
|
#if 1
|
||||||
AddLinksToPmove ( sv_player, sv.world.areanodes );
|
AddLinksToPmove ( sv_player, sv.world.areanodes );
|
||||||
#else
|
#else
|
||||||
AddAllEntsToPmove ();
|
AddAllEntsToPmove (sv_player);
|
||||||
#endif
|
#endif
|
||||||
|
AddLinksToPmove_Force ( sv_player, &sv.world.portallist );
|
||||||
|
|
||||||
if ((int)sv_player->xv->pmove_flags & PMF_LADDER)
|
if ((int)sv_player->xv->pmove_flags & PMF_LADDER)
|
||||||
pmove.onladder = true;
|
pmove.onladder = true;
|
||||||
|
@ -6168,6 +6179,7 @@ if (sv_player->v->health > 0 && before && !after )
|
||||||
else
|
else
|
||||||
sv_player->v->flags = (int)sv_player->v->flags & ~FL_ONGROUND;
|
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.origin, sv_player->v->origin);
|
||||||
VectorCopy (pmove.angles, sv_player->v->v_angle);
|
VectorCopy (pmove.angles, sv_player->v->v_angle);
|
||||||
|
|
||||||
|
|
|
@ -181,6 +181,10 @@ void World_ClearWorld (world_t *w)
|
||||||
{
|
{
|
||||||
World_InitBoxHull ();
|
World_InitBoxHull ();
|
||||||
|
|
||||||
|
memset (&w->portallist, 0, sizeof(w->portallist));
|
||||||
|
ClearLink (&w->portallist.edicts);
|
||||||
|
w->portallist.axis = -1;
|
||||||
|
|
||||||
memset (w->areanodes, 0, sizeof(w->areanodes));
|
memset (w->areanodes, 0, sizeof(w->areanodes));
|
||||||
w->numareanodes = 0;
|
w->numareanodes = 0;
|
||||||
if (!w->worldmodel)
|
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
|
// find the first node that the ent's box crosses
|
||||||
node = w->areanodes;
|
if (ent->v->solid == SOLID_PORTAL)
|
||||||
while (1)
|
node = &w->portallist;
|
||||||
|
else
|
||||||
{
|
{
|
||||||
if (node->axis == -1)
|
node = w->areanodes;
|
||||||
break;
|
while (1)
|
||||||
if (ent->v->absmin[node->axis] > node->dist)
|
{
|
||||||
node = node->children[0];
|
if (node->axis == -1)
|
||||||
else if (ent->v->absmax[node->axis] < node->dist)
|
break;
|
||||||
node = node->children[1];
|
if (ent->v->absmin[node->axis] > node->dist)
|
||||||
else
|
node = node->children[0];
|
||||||
break; // crosses the node
|
else if (ent->v->absmax[node->axis] < node->dist)
|
||||||
|
node = node->children[1];
|
||||||
|
else
|
||||||
|
break; // crosses the node
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// link it in
|
// 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
|
else
|
||||||
World_ClipToLinks (w, w->areanodes, &clip );
|
World_ClipToLinks (w, w->areanodes, &clip );
|
||||||
|
World_ClipToLinks(w, &w->portallist, &clip);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (clip.trace.startsolid)
|
// if (clip.trace.startsolid)
|
||||||
|
|
Loading…
Reference in a new issue