portal tweaks. prediction code can now use portals, but cannot actually predict them yet, for a couple of reasons.
gravitydir on monsters should now be workable (qc needs to be careful with ideal_yaw, which is now relative to the gravitydir rather than the xy plane). fix an issue where shaders were not loaded after gamedir switches. added 6dof command (and player movetype). git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4689 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
49a04eacae
commit
ed54ed2dcf
29 changed files with 811 additions and 307 deletions
|
@ -39,6 +39,7 @@ cvar_t cl_queueimpulses = CVAR("cl_queueimpulses", "0");
|
|||
cvar_t cl_smartjump = CVAR("cl_smartjump", "1");
|
||||
cvar_t cl_run = CVARD("cl_run", "0", "Enables autorun, inverting the state of the +speed key.");
|
||||
cvar_t cl_fastaccel = CVARD("cl_fastaccel", "1", "Begin moving at full speed instantly, instead of waiting a frame or so.");
|
||||
extern cvar_t cl_rollspeed;
|
||||
|
||||
cvar_t cl_prydoncursor = CVAR("cl_prydoncursor", ""); //for dp protocol
|
||||
cvar_t cl_instantrotate = CVARF("cl_instantrotate", "1", CVAR_SEMICHEAT);
|
||||
|
@ -143,7 +144,7 @@ kbutton_t in_mlook, in_klook;
|
|||
kbutton_t in_left, in_right, in_forward, in_back;
|
||||
kbutton_t in_lookup, in_lookdown, in_moveleft, in_moveright;
|
||||
kbutton_t in_strafe, in_speed, in_use, in_jump, in_attack;
|
||||
kbutton_t in_up, in_down;
|
||||
kbutton_t in_rollleft, in_rollright, in_up, in_down;
|
||||
|
||||
kbutton_t in_button3, in_button4, in_button5, in_button6, in_button7, in_button8;
|
||||
|
||||
|
@ -252,6 +253,10 @@ void IN_MoveleftDown(void) {KeyDown(&in_moveleft);}
|
|||
void IN_MoveleftUp(void) {KeyUp(&in_moveleft);}
|
||||
void IN_MoverightDown(void) {KeyDown(&in_moveright);}
|
||||
void IN_MoverightUp(void) {KeyUp(&in_moveright);}
|
||||
void IN_RollLeftDown(void) {KeyDown(&in_rollleft);}
|
||||
void IN_RollLeftUp(void) {KeyUp(&in_rollleft);}
|
||||
void IN_RollRightDown(void) {KeyDown(&in_rollright);}
|
||||
void IN_RollRightUp(void) {KeyUp(&in_rollright);}
|
||||
|
||||
void IN_SpeedDown(void) {KeyDown(&in_speed);}
|
||||
void IN_SpeedUp(void) {KeyUp(&in_speed);}
|
||||
|
@ -546,6 +551,10 @@ void CL_AdjustAngles (int pnum, double frametime)
|
|||
cl.playerview[pnum].viewanglechange[PITCH] -= speed*quant * CL_KeyState (&in_forward, pnum, false);
|
||||
cl.playerview[pnum].viewanglechange[PITCH] += speed*quant * CL_KeyState (&in_back, pnum, false);
|
||||
}
|
||||
|
||||
quant = cl_rollspeed.ival;
|
||||
cl.playerview[pnum].viewanglechange[ROLL] -= speed*quant * CL_KeyState (&in_rollleft, pnum, false);
|
||||
cl.playerview[pnum].viewanglechange[ROLL] += speed*quant * CL_KeyState (&in_rollright, pnum, false);
|
||||
|
||||
up = CL_KeyState (&in_lookup, pnum, false);
|
||||
down = CL_KeyState(&in_lookdown, pnum, false);
|
||||
|
@ -604,15 +613,15 @@ void CL_ClampPitch (int pnum)
|
|||
float roll;
|
||||
static float oldtime;
|
||||
float timestep = realtime - oldtime;
|
||||
playerview_t *pv = &cl.playerview[pnum];
|
||||
oldtime = realtime;
|
||||
|
||||
if (cl.intermission)
|
||||
{
|
||||
memset(cl.playerview[pnum].viewanglechange, 0, sizeof(cl.playerview[pnum].viewanglechange));
|
||||
memset(pv->viewanglechange, 0, sizeof(pv->viewanglechange));
|
||||
return;
|
||||
}
|
||||
#if 0
|
||||
if (cl.pmovetype[pnum] == PM_WALLWALK)
|
||||
if (pv->pmovetype == PM_6DOF)
|
||||
{
|
||||
vec3_t impact;
|
||||
vec3_t norm;
|
||||
|
@ -620,16 +629,20 @@ void CL_ClampPitch (int pnum)
|
|||
vec3_t cross;
|
||||
vec3_t view[4];
|
||||
float dot;
|
||||
AngleVectors(cl.viewangles[pnum], view[0], view[1], view[2]);
|
||||
AngleVectors(pv->viewangles, view[0], view[1], view[2]);
|
||||
Matrix4x4_RM_FromVectors(mat, view[0], view[1], view[2], vec3_origin);
|
||||
|
||||
Matrix4_Multiply(Matrix4x4_CM_NewRotation(-cl.viewanglechange[pnum][PITCH], 0, 1, 0), mat, mat2);
|
||||
Matrix4_Multiply(Matrix4x4_CM_NewRotation(cl.viewanglechange[pnum][YAW], 0, 0, 1), mat2, mat);
|
||||
|
||||
Matrix4_Multiply(Matrix4x4_CM_NewRotation(-pv->viewanglechange[PITCH], 0, 1, 0), mat, mat2);
|
||||
Matrix4_Multiply(Matrix4x4_CM_NewRotation(pv->viewanglechange[YAW], 0, 0, 1), mat2, mat);
|
||||
#if 1
|
||||
//roll angles
|
||||
Matrix4_Multiply(Matrix4x4_CM_NewRotation(pv->viewanglechange[ROLL], 1, 0, 0), mat, mat2);
|
||||
#else
|
||||
//auto-roll
|
||||
Matrix3x4_RM_ToVectors(mat, view[0], view[1], view[2], view[3]);
|
||||
|
||||
VectorMA(cl.simorg[pnum], -48, view[2], view[3]);
|
||||
if (!TraceLineN(cl.simorg[pnum], view[3], impact, norm))
|
||||
VectorMA(pv->simorg, -48, view[2], view[3]);
|
||||
if (!TraceLineN(pv->simorg, view[3], impact, norm))
|
||||
{
|
||||
norm[0] = 0;
|
||||
norm[1] = 0;
|
||||
|
@ -641,17 +654,16 @@ void CL_ClampPitch (int pnum)
|
|||
dot = DotProduct(view[0], cross);
|
||||
roll = timestep * 360 * -(dot);
|
||||
Matrix4_Multiply(Matrix4x4_CM_NewRotation(roll, 1, 0, 0), mat, mat2);
|
||||
|
||||
#endif
|
||||
Matrix3x4_RM_ToVectors(mat2, view[0], view[1], view[2], view[3]);
|
||||
VectorAngles(view[0], view[2], cl.viewangles[pnum]);
|
||||
cl.viewangles[pnum][PITCH]=360 - cl.viewangles[pnum][PITCH];
|
||||
VectorClear(cl.viewanglechange[pnum]);
|
||||
VectorAngles(view[0], view[2], pv->viewangles);
|
||||
pv->viewangles[PITCH]=360 - pv->viewangles[PITCH];
|
||||
VectorClear(pv->viewanglechange);
|
||||
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#if 1
|
||||
if ((cl.playerview[pnum].gravitydir[2] != -1 || cl.playerview[pnum].viewangles[2]))
|
||||
if ((pv->gravitydir[2] != -1 || pv->viewangles[2]))
|
||||
{
|
||||
float surfm[16], invsurfm[16];
|
||||
float viewm[16];
|
||||
|
@ -661,17 +673,17 @@ void CL_ClampPitch (int pnum)
|
|||
void PerpendicularVector( vec3_t dst, const vec3_t src );
|
||||
|
||||
/*calc current view matrix relative to the surface*/
|
||||
AngleVectors(cl.playerview[pnum].viewangles, view[0], view[1], view[2]);
|
||||
AngleVectors(pv->viewangles, view[0], view[1], view[2]);
|
||||
VectorNegate(view[1], view[1]);
|
||||
|
||||
/*calculate the surface axis with up from the pmove code and right/forwards relative to the player's directions*/
|
||||
if (!cl.playerview[pnum].gravitydir[0] && !cl.playerview[pnum].gravitydir[1] && !cl.playerview[pnum].gravitydir[2])
|
||||
if (!pv->gravitydir[0] && !pv->gravitydir[1] && !pv->gravitydir[2])
|
||||
{
|
||||
VectorSet(surf[2], 0, 0, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
VectorNegate(cl.playerview[pnum].gravitydir, surf[2]);
|
||||
VectorNegate(pv->gravitydir, surf[2]);
|
||||
}
|
||||
VectorNormalize(surf[2]);
|
||||
PerpendicularVector(surf[1], surf[2]);
|
||||
|
@ -691,8 +703,8 @@ void CL_ClampPitch (int pnum)
|
|||
vang[PITCH] *= -1;
|
||||
|
||||
/*edit it*/
|
||||
vang[PITCH] += cl.playerview[pnum].viewanglechange[PITCH];
|
||||
vang[YAW] += cl.playerview[pnum].viewanglechange[YAW];
|
||||
vang[PITCH] += pv->viewanglechange[PITCH];
|
||||
vang[YAW] += pv->viewanglechange[YAW];
|
||||
if (vang[PITCH] <= -180)
|
||||
vang[PITCH] += 360;
|
||||
if (vang[PITCH] > 180)
|
||||
|
@ -705,7 +717,7 @@ void CL_ClampPitch (int pnum)
|
|||
/*keep the player looking relative to their ground (smoothlyish)*/
|
||||
if (!vang[ROLL])
|
||||
{
|
||||
if (!cl.playerview[pnum].viewanglechange[PITCH] && !cl.playerview[pnum].viewanglechange[YAW] && !cl.playerview[pnum].viewanglechange[ROLL])
|
||||
if (!pv->viewanglechange[PITCH] && !pv->viewanglechange[YAW] && !pv->viewanglechange[ROLL])
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
@ -723,7 +735,7 @@ void CL_ClampPitch (int pnum)
|
|||
vang[ROLL] += host_frametime*180;
|
||||
}
|
||||
}
|
||||
VectorClear(cl.playerview[pnum].viewanglechange);
|
||||
VectorClear(pv->viewanglechange);
|
||||
/*clamp pitch*/
|
||||
if (vang[PITCH] > cl.maxpitch)
|
||||
vang[PITCH] = cl.maxpitch;
|
||||
|
@ -741,19 +753,19 @@ void CL_ClampPitch (int pnum)
|
|||
VectorAngles(view[0], view[2], cl.playerview[pnum].viewangles);
|
||||
cl.playerview[pnum].viewangles[PITCH] *= -1;
|
||||
|
||||
if (cl.playerview[pnum].viewangles[ROLL] >= 360)
|
||||
cl.playerview[pnum].viewangles[ROLL] -= 360;
|
||||
if (cl.playerview[pnum].viewangles[ROLL] < 0)
|
||||
cl.playerview[pnum].viewangles[ROLL] += 360;
|
||||
if (cl.playerview[pnum].viewangles[PITCH] < -180)
|
||||
cl.playerview[pnum].viewangles[PITCH] += 360;
|
||||
if (pv->viewangles[ROLL] >= 360)
|
||||
pv->viewangles[ROLL] -= 360;
|
||||
if (pv->viewangles[ROLL] < 0)
|
||||
pv->viewangles[ROLL] += 360;
|
||||
if (pv->viewangles[PITCH] < -180)
|
||||
pv->viewangles[PITCH] += 360;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
cl.playerview[pnum].viewangles[PITCH] += cl.playerview[pnum].viewanglechange[PITCH];
|
||||
cl.playerview[pnum].viewangles[YAW] += cl.playerview[pnum].viewanglechange[YAW];
|
||||
cl.playerview[pnum].viewangles[ROLL] += cl.playerview[pnum].viewanglechange[ROLL];
|
||||
VectorClear(cl.playerview[pnum].viewanglechange);
|
||||
pv->viewangles[PITCH] += pv->viewanglechange[PITCH];
|
||||
pv->viewangles[YAW] += pv->viewanglechange[YAW];
|
||||
pv->viewangles[ROLL] += pv->viewanglechange[ROLL];
|
||||
VectorClear(pv->viewanglechange);
|
||||
|
||||
#ifdef Q2CLIENT
|
||||
if (cls.protocol == CP_QUAKE2)
|
||||
|
@ -763,15 +775,15 @@ void CL_ClampPitch (int pnum)
|
|||
if (pitch > 180)
|
||||
pitch -= 360;
|
||||
|
||||
if (cl.playerview[pnum].viewangles[PITCH] + pitch < -360)
|
||||
cl.playerview[pnum].viewangles[PITCH] += 360; // wrapped
|
||||
if (cl.playerview[pnum].viewangles[PITCH] + pitch > 360)
|
||||
cl.playerview[pnum].viewangles[PITCH] -= 360; // wrapped
|
||||
if (pv->viewangles[PITCH] + pitch < -360)
|
||||
pv->viewangles[PITCH] += 360; // wrapped
|
||||
if (pv->viewangles[PITCH] + pitch > 360)
|
||||
pv->viewangles[PITCH] -= 360; // wrapped
|
||||
|
||||
if (cl.playerview[pnum].viewangles[PITCH] + pitch > cl.maxpitch)
|
||||
cl.playerview[pnum].viewangles[PITCH] = cl.maxpitch - pitch;
|
||||
if (cl.playerview[pnum].viewangles[PITCH] + pitch < cl.minpitch)
|
||||
cl.playerview[pnum].viewangles[PITCH] = cl.minpitch - pitch;
|
||||
if (pv->viewangles[PITCH] + pitch > cl.maxpitch)
|
||||
pv->viewangles[PITCH] = cl.maxpitch - pitch;
|
||||
if (pv->viewangles[PITCH] + pitch < cl.minpitch)
|
||||
pv->viewangles[PITCH] = cl.minpitch - pitch;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
@ -783,21 +795,21 @@ void CL_ClampPitch (int pnum)
|
|||
else
|
||||
#endif
|
||||
{
|
||||
if (cl.playerview[pnum].viewangles[PITCH] > cl.maxpitch)
|
||||
cl.playerview[pnum].viewangles[PITCH] = cl.maxpitch;
|
||||
if (cl.playerview[pnum].viewangles[PITCH] < cl.minpitch)
|
||||
cl.playerview[pnum].viewangles[PITCH] = cl.minpitch;
|
||||
if (pv->viewangles[PITCH] > cl.maxpitch)
|
||||
pv->viewangles[PITCH] = cl.maxpitch;
|
||||
if (pv->viewangles[PITCH] < cl.minpitch)
|
||||
pv->viewangles[PITCH] = cl.minpitch;
|
||||
}
|
||||
|
||||
// if (cl.viewangles[pnum][ROLL] > 50)
|
||||
// cl.viewangles[pnum][ROLL] = 50;
|
||||
// if (cl.viewangles[pnum][ROLL] < -50)
|
||||
// cl.viewangles[pnum][ROLL] = -50;
|
||||
roll = timestep*cl.playerview[pnum].viewangles[ROLL]*30;
|
||||
if ((cl.playerview[pnum].viewangles[ROLL]-roll < 0) != (cl.playerview[pnum].viewangles[ROLL]<0))
|
||||
cl.playerview[pnum].viewangles[ROLL] = 0;
|
||||
roll = timestep*pv->viewangles[ROLL]*30;
|
||||
if ((pv->viewangles[ROLL]-roll < 0) != (pv->viewangles[ROLL]<0))
|
||||
pv->viewangles[ROLL] = 0;
|
||||
else
|
||||
cl.playerview[pnum].viewangles[ROLL] -= timestep*cl.playerview[pnum].viewangles[ROLL]*3;
|
||||
pv->viewangles[ROLL] -= timestep*pv->viewangles[ROLL]*3;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1977,6 +1989,10 @@ void CL_InitInput (void)
|
|||
Cmd_AddCommand ("-moveleft", IN_MoveleftUp);
|
||||
Cmd_AddCommand ("+moveright", IN_MoverightDown);
|
||||
Cmd_AddCommand ("-moveright", IN_MoverightUp);
|
||||
Cmd_AddCommand ("+rollleft", IN_RollLeftDown);
|
||||
Cmd_AddCommand ("-rollleft", IN_RollLeftUp);
|
||||
Cmd_AddCommand ("+rollright", IN_RollRightDown);
|
||||
Cmd_AddCommand ("-rollright", IN_RollRightUp);
|
||||
Cmd_AddCommand ("+speed", IN_SpeedDown);
|
||||
Cmd_AddCommand ("-speed", IN_SpeedUp);
|
||||
Cmd_AddCommand ("+attack", IN_AttackDown);
|
||||
|
|
|
@ -1809,6 +1809,8 @@ void CL_CheckServerInfo(void)
|
|||
movevars.stepheight = *s?Q_atof(s):PM_DEFAULTSTEPHEIGHT;
|
||||
s = Info_ValueForKey(cl.serverinfo, "pm_watersinkspeed");
|
||||
movevars.watersinkspeed = *s?Q_atof(s):60;
|
||||
s = Info_ValueForKey(cl.serverinfo, "pm_flyfriction");
|
||||
movevars.flyfriction = *s?Q_atof(s):4;
|
||||
|
||||
// Initialize cl.maxpitch & cl.minpitch
|
||||
if (cls.protocol == CP_QUAKEWORLD || cls.protocol == CP_NETQUAKE)
|
||||
|
@ -3655,9 +3657,11 @@ void CL_Init (void)
|
|||
Cmd_AddCommand ("god", NULL); //cheats
|
||||
Cmd_AddCommand ("give", NULL);
|
||||
Cmd_AddCommand ("noclip", NULL);
|
||||
Cmd_AddCommand ("notarget", NULL);
|
||||
Cmd_AddCommand ("6dof", NULL);
|
||||
Cmd_AddCommand ("spiderpig", NULL);
|
||||
Cmd_AddCommand ("fly", NULL);
|
||||
Cmd_AddCommand ("setpos", NULL);
|
||||
Cmd_AddCommand ("notarget", NULL);
|
||||
|
||||
Cmd_AddCommand ("topten", NULL);
|
||||
|
||||
|
|
|
@ -6088,6 +6088,7 @@ void CLQW_ParseServerMessage (void)
|
|||
|
||||
case svc_cdtrack:
|
||||
{
|
||||
//quakeworld got a crippled svc_cdtrack.
|
||||
unsigned int firsttrack;
|
||||
firsttrack = MSG_ReadByte ();
|
||||
Media_NumberedTrack (firsttrack, firsttrack);
|
||||
|
|
|
@ -720,6 +720,9 @@ static void CL_EntStateToPlayerState(player_state_t *plstate, entity_state_t *st
|
|||
case MOVETYPE_WALLWALK:
|
||||
pmtype = PM_WALLWALK;
|
||||
break;
|
||||
case MOVETYPE_6DOF:
|
||||
pmtype = PM_6DOF;
|
||||
break;
|
||||
default:
|
||||
pmtype = PM_NORMAL;
|
||||
break;
|
||||
|
|
|
@ -445,7 +445,10 @@ void CD_f (void)
|
|||
|
||||
if (Q_strcasecmp(command, "loop") == 0)
|
||||
{
|
||||
Media_BackgroundTrack(Cmd_Argv(2), NULL);
|
||||
if (Cmd_Argc() < 4)
|
||||
Media_BackgroundTrack(Cmd_Argv(2), NULL);
|
||||
else
|
||||
Media_BackgroundTrack(Cmd_Argv(2), Cmd_Argv(3));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -3622,6 +3622,7 @@ static int PScript_RunParticleEffectState (vec3_t org, vec3_t dir, float count,
|
|||
part_type_t *ptype = &part_type[typenum];
|
||||
int i, j, k, l, spawnspc;
|
||||
float m, pcount, orgadd, veladd;
|
||||
vec3_t axis[3]={{1,0,0},{0,1,0},{0,0,-1}};
|
||||
particle_t *p;
|
||||
beamseg_t *b, *bfirst;
|
||||
vec3_t ofsvec, arsvec; // offsetspread vec, areaspread vec
|
||||
|
@ -3889,6 +3890,17 @@ static int PScript_RunParticleEffectState (vec3_t org, vec3_t dir, float count,
|
|||
break;
|
||||
}
|
||||
|
||||
if (dir)
|
||||
{
|
||||
void PerpendicularVector( vec3_t dst, const vec3_t src );
|
||||
VectorCopy(dir, axis[2]);
|
||||
VectorNormalize(axis[2]);
|
||||
PerpendicularVector(axis[0], axis[2]);
|
||||
VectorNormalize(axis[0]);
|
||||
CrossProduct(axis[2], axis[0], axis[1]);
|
||||
VectorNormalize(axis[1]);
|
||||
}
|
||||
|
||||
// time limit (for completeness)
|
||||
if (ptype->spawntime && ts)
|
||||
{
|
||||
|
@ -4112,30 +4124,43 @@ static int PScript_RunParticleEffectState (vec3_t org, vec3_t dir, float count,
|
|||
}
|
||||
break;
|
||||
default: // SM_BALL, SM_CIRCLE
|
||||
ofsvec[0] = hrandom();
|
||||
ofsvec[1] = hrandom();
|
||||
if (ptype->areaspreadvert)
|
||||
ofsvec[2] = hrandom();
|
||||
else
|
||||
ofsvec[2] = 0;
|
||||
{
|
||||
ofsvec[0] = hrandom();
|
||||
ofsvec[1] = hrandom();
|
||||
if (ptype->areaspreadvert)
|
||||
ofsvec[2] = hrandom();
|
||||
else
|
||||
ofsvec[2] = 0;
|
||||
|
||||
VectorNormalize(ofsvec);
|
||||
if (ptype->spawnmode != SM_CIRCLE)
|
||||
VectorScale(ofsvec, frandom(), ofsvec);
|
||||
VectorNormalize(ofsvec);
|
||||
if (ptype->spawnmode != SM_CIRCLE)
|
||||
VectorScale(ofsvec, frandom(), ofsvec);
|
||||
|
||||
arsvec[0] = ofsvec[0]*ptype->areaspread;
|
||||
arsvec[1] = ofsvec[1]*ptype->areaspread;
|
||||
arsvec[2] = ofsvec[2]*ptype->areaspreadvert;
|
||||
arsvec[0] = ofsvec[0]*ptype->areaspread;
|
||||
arsvec[1] = ofsvec[1]*ptype->areaspread;
|
||||
arsvec[2] = ofsvec[2]*ptype->areaspreadvert;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
p->org[0] = org[0] + arsvec[0];
|
||||
p->org[1] = org[1] + arsvec[1];
|
||||
p->org[2] = org[2] + arsvec[2];
|
||||
|
||||
// apply arsvec+ofsvec
|
||||
orgadd = ptype->orgadd + frandom()*ptype->randomorgadd;
|
||||
veladd = ptype->veladd + frandom()*ptype->randomveladd;
|
||||
#if 1
|
||||
if (dir)
|
||||
veladd *= VectorLength(dir);
|
||||
VectorMA(p->vel, ofsvec[0]*ptype->spawnvel, axis[0], p->vel);
|
||||
VectorMA(p->vel, ofsvec[1]*ptype->spawnvel, axis[1], p->vel);
|
||||
VectorMA(p->vel, veladd+ofsvec[2]*ptype->spawnvelvert, axis[2], p->vel);
|
||||
|
||||
VectorCopy(org, p->org);
|
||||
VectorMA(p->org, arsvec[0], axis[0], p->org);
|
||||
VectorMA(p->org, arsvec[1], axis[1], p->org);
|
||||
VectorMA(p->org, orgadd+arsvec[2], axis[2], p->org);
|
||||
#else
|
||||
p->org[0] = org[0] + arsvec[0];
|
||||
p->org[1] = org[1] + arsvec[1];
|
||||
p->org[2] = org[2] + arsvec[2];
|
||||
if (dir)
|
||||
{
|
||||
p->vel[0] += dir[0]*veladd+ofsvec[0]*ptype->spawnvel;
|
||||
|
@ -4154,7 +4179,7 @@ static int PScript_RunParticleEffectState (vec3_t org, vec3_t dir, float count,
|
|||
|
||||
p->org[2] -= orgadd;
|
||||
}
|
||||
|
||||
#endif
|
||||
VectorAdd(p->org, ptype->orgbias, p->org);
|
||||
|
||||
p->die = particletime + ptype->die - p->die;
|
||||
|
|
|
@ -3592,16 +3592,6 @@ static void QCBUILTIN PF_rotatevectorsbytag (pubprogfuncs_t *prinst, struct glob
|
|||
|
||||
|
||||
|
||||
//fixme merge with ssqc
|
||||
static void QCBUILTIN PF_cs_checkbottom (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
csqcedict_t *ent;
|
||||
|
||||
ent = (csqcedict_t*)G_EDICT(prinst, OFS_PARM0);
|
||||
|
||||
G_FLOAT(OFS_RETURN) = World_CheckBottom (&csqc_world, (wedict_t*)ent);
|
||||
}
|
||||
|
||||
static void QCBUILTIN PF_cs_break (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
Con_Printf ("break statement\n");
|
||||
|
@ -3613,14 +3603,16 @@ static void QCBUILTIN PF_cs_break (pubprogfuncs_t *prinst, struct globalvars_s *
|
|||
//fixme merge with ssqc
|
||||
static void QCBUILTIN PF_cs_walkmove (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
csqcedict_t *ent;
|
||||
wedict_t *ent;
|
||||
float yaw, dist;
|
||||
vec3_t move;
|
||||
// dfunction_t *oldf;
|
||||
int oldself;
|
||||
qboolean settrace;
|
||||
vec3_t axis[3];
|
||||
float s;
|
||||
|
||||
ent = (csqcedict_t*)PROG_TO_EDICT(prinst, *csqcg.self);
|
||||
ent = PROG_TO_WEDICT(prinst, *csqcg.self);
|
||||
yaw = G_FLOAT(OFS_PARM0);
|
||||
dist = G_FLOAT(OFS_PARM1);
|
||||
if (prinst->callargc >= 3 && G_FLOAT(OFS_PARM2))
|
||||
|
@ -3634,16 +3626,19 @@ static void QCBUILTIN PF_cs_walkmove (pubprogfuncs_t *prinst, struct globalvars_
|
|||
return;
|
||||
}
|
||||
|
||||
World_GetEntGravityAxis(ent, axis);
|
||||
|
||||
yaw = yaw*M_PI*2 / 360;
|
||||
|
||||
move[0] = cos(yaw)*dist;
|
||||
move[1] = sin(yaw)*dist;
|
||||
move[2] = 0;
|
||||
s = cos(yaw)*dist;
|
||||
VectorScale(axis[0], s, move);
|
||||
s = sin(yaw)*dist;
|
||||
VectorMA(move, s, axis[1], move);
|
||||
|
||||
// save program state, because CS_movestep may call other progs
|
||||
oldself = *csqcg.self;
|
||||
|
||||
G_FLOAT(OFS_RETURN) = World_movestep(&csqc_world, (wedict_t*)ent, move, true, false, settrace?cs_settracevars:NULL, pr_globals);
|
||||
G_FLOAT(OFS_RETURN) = World_movestep(&csqc_world, (wedict_t*)ent, move, axis, true, false, settrace?cs_settracevars:NULL, pr_globals);
|
||||
|
||||
// restore program state
|
||||
*csqcg.self = oldself;
|
||||
|
@ -4386,7 +4381,7 @@ static struct {
|
|||
{"ceil", PF_ceil, 38}, // #38 float(float f) ceil (QUAKE)
|
||||
// {"?", PF_Fixme, 39}, // #39
|
||||
//40
|
||||
{"checkbottom", PF_cs_checkbottom, 40}, // #40 float(entity e) checkbottom (QUAKE)
|
||||
{"checkbottom", PF_checkbottom, 40}, // #40 float(entity e) checkbottom (QUAKE)
|
||||
{"pointcontents", PF_cs_pointcontents, 41}, // #41 float(vector org) pointcontents (QUAKE)
|
||||
// {"?", PF_Fixme, 42}, // #42
|
||||
{"fabs", PF_fabs, 43}, // #43 float(float f) fabs (QUAKE)
|
||||
|
|
|
@ -509,14 +509,14 @@ void QCBUILTIN PF_CL_precache_pic (pubprogfuncs_t *prinst, struct globalvars_s *
|
|||
pic = R2D_SafePicFromWad(str);
|
||||
else
|
||||
{
|
||||
if (cls.state
|
||||
pic = R2D_SafeCachePic(str);
|
||||
|
||||
if ((!pic || (pic->flags & SHADER_NOIMAGE)) && cls.state
|
||||
#ifndef CLIENTONLY
|
||||
&& !sv.active
|
||||
#endif
|
||||
)
|
||||
&& strchr(str, '.')) //only try to download it if it looks as though it contains a path.
|
||||
CL_CheckOrEnqueDownloadFile(str, str, 0);
|
||||
|
||||
pic = R2D_SafeCachePic(str);
|
||||
}
|
||||
|
||||
if (pic)
|
||||
|
|
|
@ -2889,6 +2889,13 @@ void FS_ReloadPackFilesFlags(unsigned int reloadflags)
|
|||
Z_Free(oldpaths);
|
||||
oldpaths = next;
|
||||
}
|
||||
|
||||
|
||||
#ifndef SERVERONLY
|
||||
Shader_NeedReload(true);
|
||||
#endif
|
||||
// Mod_ClearAll();
|
||||
// Cache_Flush();
|
||||
}
|
||||
|
||||
void FS_UnloadPackFiles(void)
|
||||
|
|
|
@ -995,8 +995,22 @@ static qboolean FSZIP_ReadCentralEntry(zipfile_t *zip, qbyte *data, struct zipce
|
|||
entry->flags |= ZFL_CORRUPT;
|
||||
else if (entry->cmethod == 0)
|
||||
entry->flags |= ZFL_STORED;
|
||||
//1: shrink
|
||||
//2-5: reduce
|
||||
//6: implode
|
||||
//7: tokenize
|
||||
else if (entry->cmethod == 8)
|
||||
entry->flags |= ZFL_DEFLATED;
|
||||
//8: deflate64 - patented. sometimes written by microsoft's crap. only minor improvements.
|
||||
//10: implode
|
||||
//12: bzip2
|
||||
// else if (entry->cmethod == 12)
|
||||
// entry->flags |= ZFL_BZIP2;
|
||||
// else if (entry->cmethod == 14)
|
||||
// entry->flags |= ZFL_LZMA;
|
||||
//19: lz77
|
||||
//97: wavpack
|
||||
//98: ppmd
|
||||
else
|
||||
entry->flags |= ZFL_CORRUPT; //unsupported compression method.
|
||||
return true;
|
||||
|
|
|
@ -34,8 +34,6 @@ void PM_Init (void)
|
|||
|
||||
#define MIN_STEP_NORMAL 0.7 // roughly 45 degrees
|
||||
|
||||
#define pm_flyfriction 4
|
||||
|
||||
#define STOP_EPSILON 0.1
|
||||
#define BLOCKED_FLOOR 1
|
||||
#define BLOCKED_STEP 2
|
||||
|
@ -118,7 +116,6 @@ static qboolean PM_PortalTransform(world_t *w, int portalnum, vec3_t org, vec3_t
|
|||
|
||||
//transform the angles too
|
||||
VectorCopy(org, G_VECTOR(OFS_PARM0));
|
||||
pmove.angles[0] *= -1;
|
||||
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);
|
||||
|
@ -130,6 +127,36 @@ static qboolean PM_PortalTransform(world_t *w, int portalnum, vec3_t org, vec3_t
|
|||
return okay;
|
||||
}
|
||||
|
||||
static trace_t PM_PlayerTracePortals(vec3_t start, vec3_t end, unsigned int solidmask, float *tookportal)
|
||||
{
|
||||
trace_t trace = PM_PlayerTrace (start, end, MASK_PLAYERSOLID);
|
||||
if (tookportal)
|
||||
*tookportal = 0;
|
||||
if (trace.entnum >= 0 && pmove.world)
|
||||
{
|
||||
physent_t *impact = &pmove.physents[trace.entnum];
|
||||
if (impact->isportal)
|
||||
{
|
||||
vec3_t move;
|
||||
vec3_t from;
|
||||
|
||||
VectorCopy(trace.endpos, from); //just in case
|
||||
VectorSubtract(end, trace.endpos, move);
|
||||
if (PM_PortalTransform(pmove.world, impact->info, from, move))
|
||||
{
|
||||
VectorAdd(from, move, end);
|
||||
|
||||
//if we follow the portal, then we basically need to restart from the other side.
|
||||
if (tookportal)
|
||||
*tookportal = trace.fraction;
|
||||
|
||||
trace = PM_PlayerTrace (from, end, MASK_PLAYERSOLID);
|
||||
}
|
||||
}
|
||||
}
|
||||
return trace;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
PM_SlideMove
|
||||
|
@ -152,6 +179,7 @@ int PM_SlideMove (void)
|
|||
vec3_t end;
|
||||
float time_left;
|
||||
int blocked;
|
||||
float tookportal;
|
||||
|
||||
numbumps = 4;
|
||||
|
||||
|
@ -169,31 +197,14 @@ int PM_SlideMove (void)
|
|||
for (i=0 ; i<3 ; i++)
|
||||
end[i] = pmove.origin[i] + time_left * pmove.velocity[i];
|
||||
|
||||
trace = PM_PlayerTrace (pmove.origin, end, MASK_PLAYERSOLID);
|
||||
|
||||
if (trace.entnum >= 0 && pmove.world)
|
||||
trace = PM_PlayerTracePortals (pmove.origin, end, MASK_PLAYERSOLID, &tookportal);
|
||||
if (tookportal)
|
||||
{
|
||||
physent_t *impact = &pmove.physents[trace.entnum];
|
||||
if (impact->isportal)
|
||||
{
|
||||
vec3_t move;
|
||||
vec3_t from;
|
||||
|
||||
VectorCopy(trace.endpos, from); //just in case
|
||||
VectorSubtract(end, trace.endpos, move);
|
||||
if (PM_PortalTransform(pmove.world, impact->info, from, move))
|
||||
{
|
||||
VectorAdd(from, move, end);
|
||||
|
||||
//if we follow the portal, then we basically need to restart from the other side.
|
||||
time_left -= time_left * trace.fraction;
|
||||
VectorCopy (pmove.velocity, primal_velocity);
|
||||
VectorCopy (pmove.velocity, original_velocity);
|
||||
numplanes = 0;
|
||||
|
||||
trace = PM_PlayerTrace (from, end, MASK_PLAYERSOLID);
|
||||
}
|
||||
}
|
||||
//made progress, but hit a portal
|
||||
time_left -= time_left * tookportal;
|
||||
VectorCopy (pmove.velocity, primal_velocity);
|
||||
VectorCopy (pmove.velocity, original_velocity);
|
||||
numplanes = 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -344,6 +355,7 @@ int PM_StepSlideMove (qboolean in_air)
|
|||
|
||||
// adjust stepsize, otherwise it would be possible to walk up a
|
||||
// a step higher than STEPSIZE
|
||||
//FIXME gravitydir, portals
|
||||
stepsize = movevars.stepheight - (org[2] - trace.endpos[2]);
|
||||
}
|
||||
else
|
||||
|
@ -357,12 +369,13 @@ int PM_StepSlideMove (qboolean in_air)
|
|||
|
||||
// move up a stair height
|
||||
VectorMA (pmove.origin, -stepsize, pmove.gravitydir, dest);
|
||||
trace = PM_PlayerTrace (pmove.origin, dest, MASK_PLAYERSOLID);
|
||||
trace = PM_PlayerTracePortals (pmove.origin, dest, MASK_PLAYERSOLID, NULL);
|
||||
if (!trace.startsolid && !trace.allsolid)
|
||||
{
|
||||
VectorCopy (trace.endpos, pmove.origin);
|
||||
}
|
||||
|
||||
//FIXME gravitydir
|
||||
if (in_air && originalvel[2] < 0)
|
||||
VectorMA(pmove.velocity, -DotProduct(pmove.velocity, pmove.gravitydir), pmove.gravitydir, pmove.velocity); //z=0
|
||||
|
||||
|
@ -370,7 +383,7 @@ int PM_StepSlideMove (qboolean in_air)
|
|||
|
||||
// press down the stepheight
|
||||
VectorMA (pmove.origin, stepsize, pmove.gravitydir, dest);
|
||||
trace = PM_PlayerTrace (pmove.origin, dest, MASK_PLAYERSOLID);
|
||||
trace = PM_PlayerTracePortals (pmove.origin, dest, MASK_PLAYERSOLID, NULL);
|
||||
if (trace.fraction != 1 && -DotProduct(pmove.gravitydir, trace.plane.normal) < MIN_STEP_NORMAL)
|
||||
goto usedown;
|
||||
if (!trace.startsolid && !trace.allsolid)
|
||||
|
@ -441,7 +454,7 @@ void PM_Friction (void)
|
|||
//fixme: gravitydir fix needed
|
||||
pmove.velocity[0] = 0;
|
||||
pmove.velocity[1] = 0;
|
||||
if (pmove.pm_type == PM_FLY)
|
||||
if (pmove.pm_type == PM_FLY || pmove.pm_type == PM_6DOF)
|
||||
pmove.velocity[2] = 0;
|
||||
return;
|
||||
}
|
||||
|
@ -449,9 +462,9 @@ void PM_Friction (void)
|
|||
if (pmove.waterlevel >= 2)
|
||||
// apply water friction, even if in fly mode
|
||||
drop = speed*movevars.waterfriction*pmove.waterlevel*frametime;
|
||||
else if (pmove.pm_type == PM_FLY) {
|
||||
else if (pmove.pm_type == PM_FLY || pmove.pm_type == PM_6DOF) {
|
||||
// apply flymode friction
|
||||
drop = speed * pm_flyfriction * frametime;
|
||||
drop = speed * movevars.flyfriction * frametime;
|
||||
}
|
||||
else if (pmove.onground) {
|
||||
// apply ground friction
|
||||
|
@ -460,6 +473,7 @@ void PM_Friction (void)
|
|||
// if the leading edge is over a dropoff, increase friction
|
||||
start[0] = stop[0] = pmove.origin[0] + pmove.velocity[0]/speed*16;
|
||||
start[1] = stop[1] = pmove.origin[1] + pmove.velocity[1]/speed*16;
|
||||
//FIXME: gravitydir.
|
||||
start[2] = pmove.origin[2] + pmove.player_mins[2];
|
||||
stop[2] = start[2] - 34;
|
||||
trace = PM_PlayerTrace (start, stop, MASK_PLAYERSOLID);
|
||||
|
@ -619,10 +633,18 @@ void PM_FlyMove (void)
|
|||
float wishspeed;
|
||||
vec3_t wishdir;
|
||||
|
||||
for (i=0 ; i<3 ; i++)
|
||||
wishvel[i] = forward[i]*pmove.cmd.forwardmove + right[i]*pmove.cmd.sidemove;
|
||||
if (pmove.pm_type == PM_6DOF)
|
||||
{
|
||||
for (i=0 ; i<3 ; i++)
|
||||
wishvel[i] = forward[i]*pmove.cmd.forwardmove + right[i]*pmove.cmd.sidemove + up[i]*pmove.cmd.upmove;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i=0 ; i<3 ; i++)
|
||||
wishvel[i] = forward[i]*pmove.cmd.forwardmove + right[i]*pmove.cmd.sidemove;
|
||||
|
||||
VectorMA(wishvel, -pmove.cmd.upmove, pmove.gravitydir, wishvel);
|
||||
VectorMA(wishvel, -pmove.cmd.upmove, pmove.gravitydir, wishvel);
|
||||
}
|
||||
|
||||
VectorCopy (wishvel, wishdir);
|
||||
wishspeed = VectorNormalize(wishdir);
|
||||
|
@ -815,7 +837,7 @@ void PM_CategorizePosition (void)
|
|||
}
|
||||
else
|
||||
{
|
||||
trace = PM_PlayerTrace (pmove.origin, point, MASK_PLAYERSOLID);
|
||||
trace = PM_PlayerTracePortals (pmove.origin, point, MASK_PLAYERSOLID, NULL);
|
||||
if (trace.fraction == 1 || -DotProduct(pmove.gravitydir, trace.plane.normal) < MIN_STEP_NORMAL)
|
||||
pmove.onground = false;
|
||||
else
|
||||
|
@ -837,6 +859,7 @@ void PM_CategorizePosition (void)
|
|||
pmove.waterlevel = 0;
|
||||
pmove.watertype = FTECONTENTS_EMPTY;
|
||||
|
||||
//FIXME: gravitydir
|
||||
point[2] = pmove.origin[2] + pmove.player_mins[2] + 1;
|
||||
cont = PM_PointContents (point);
|
||||
|
||||
|
@ -1220,7 +1243,7 @@ void PM_PlayerMove (float gamespeed)
|
|||
|
||||
if (pmove.waterlevel >= 2)
|
||||
PM_WaterMove ();
|
||||
else if (pmove.pm_type == PM_FLY)
|
||||
else if (pmove.pm_type == PM_FLY || pmove.pm_type == PM_6DOF)
|
||||
PM_FlyMove ();
|
||||
else if (pmove.onladder)
|
||||
PM_LadderMove ();
|
||||
|
|
|
@ -29,7 +29,8 @@ typedef enum {
|
|||
PM_FLY, // fly, bump into walls
|
||||
PM_NONE, // can't move
|
||||
PM_FREEZE, // can't move or look around (TODO)
|
||||
PM_WALLWALK // sticks to walls. on ground while near one
|
||||
PM_WALLWALK, // sticks to walls. on ground while near one
|
||||
PM_6DOF // spaceship mode
|
||||
} pmtype_t;
|
||||
|
||||
#define PMF_JUMP_HELD 1
|
||||
|
@ -99,6 +100,7 @@ typedef struct {
|
|||
float wateraccelerate;
|
||||
float friction;
|
||||
float waterfriction;
|
||||
float flyfriction;
|
||||
float entgravity;
|
||||
float bunnyspeedcap;
|
||||
float watersinkspeed;
|
||||
|
|
|
@ -259,6 +259,76 @@ static qboolean PM_TransformedHullCheck (model_t *model, vec3_t start, vec3_t en
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
//a portal is flush with a world surface behind it.
|
||||
//this causes problems. namely that we can't pass through the portal plane if the bsp behind it prevents out origin from getting through.
|
||||
//so if the trace was clipped and ended infront of the portal, continue the trace to the edges of the portal cutout instead.
|
||||
void PM_PortalCSG(physent_t *portal, float trminz, float trmaxz, vec3_t start, vec3_t end, trace_t *trace)
|
||||
{
|
||||
vec4_t planes[6]; //far, near, right, left, up, down
|
||||
int plane;
|
||||
vec3_t worldpos;
|
||||
float portalradius = 128;
|
||||
//only run this code if we impacted on the portal's parent.
|
||||
if (trace->fraction == 1 && !trace->startsolid)
|
||||
return;
|
||||
if (!portalradius)
|
||||
return;
|
||||
|
||||
if (trace->startsolid)
|
||||
VectorCopy(start, worldpos); //make sure we use a sane valid position.
|
||||
else
|
||||
VectorCopy(trace->endpos, worldpos);
|
||||
|
||||
//determine the csg area. normals should be facing in
|
||||
AngleVectors(portal->angles, planes[1], planes[3], planes[5]);
|
||||
VectorNegate(planes[1], planes[0]);
|
||||
VectorNegate(planes[3], planes[2]);
|
||||
VectorNegate(planes[5], planes[4]);
|
||||
|
||||
trminz = fabs(trminz);
|
||||
portalradius/=2;
|
||||
planes[0][3] = DotProduct(portal->origin, planes[0]) - (trminz+fabs(trmaxz)+16);
|
||||
planes[1][3] = DotProduct(portal->origin, planes[1]) - (64.0/32); //an epsilon beyond the portal
|
||||
planes[2][3] = DotProduct(portal->origin, planes[2]) - portalradius+trminz;
|
||||
planes[3][3] = DotProduct(portal->origin, planes[3]) - portalradius+trminz;
|
||||
planes[4][3] = DotProduct(portal->origin, planes[4]) - portalradius+trminz;
|
||||
planes[5][3] = DotProduct(portal->origin, planes[5]) - portalradius+trminz;
|
||||
|
||||
//if we're actually inside the csg region
|
||||
for (plane = 0; plane < 6; plane++)
|
||||
{
|
||||
float d = DotProduct(worldpos, planes[plane]);
|
||||
if (d - planes[plane][3] >= 0)
|
||||
continue; //endpos is inside
|
||||
else
|
||||
return; //end is already outside
|
||||
}
|
||||
//yup, we're inside, the trace shouldn't end where it actually did
|
||||
trace->fraction = 1;
|
||||
trace->startsolid = trace->allsolid = false;
|
||||
VectorInterpolate(start, 1, end, trace->endpos);
|
||||
for (plane = 0; plane < 6; plane++)
|
||||
{
|
||||
float ds = DotProduct(start, planes[plane]) - planes[plane][3];
|
||||
float de = DotProduct(end, planes[plane]) - planes[plane][3];
|
||||
float frac;
|
||||
if (ds >= 0 && de < 0)
|
||||
{
|
||||
frac = (ds-(1.0/32)) / (ds - de);
|
||||
if (frac < trace->fraction)
|
||||
{
|
||||
if (frac < 0)
|
||||
frac = 0;
|
||||
trace->fraction = frac;
|
||||
VectorInterpolate(start, frac, end, trace->endpos);
|
||||
VectorCopy(planes[plane], trace->plane.normal);
|
||||
trace->plane.dist = planes[plane][3];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
PM_TestPlayerPosition
|
||||
|
@ -268,12 +338,14 @@ Returns false if the given player position is not valid (in solid)
|
|||
*/
|
||||
qboolean PM_TestPlayerPosition (vec3_t pos)
|
||||
{
|
||||
int i;
|
||||
int i, j;
|
||||
physent_t *pe;
|
||||
vec3_t mins, maxs;
|
||||
hull_t *hull;
|
||||
trace_t trace;
|
||||
|
||||
trace.allsolid = false;
|
||||
|
||||
for (i=0 ; i< pmove.numphysent ; i++)
|
||||
{
|
||||
pe = &pmove.physents[i];
|
||||
|
@ -293,7 +365,16 @@ qboolean PM_TestPlayerPosition (vec3_t pos)
|
|||
if (!PM_TransformedHullCheck (pe->model, pos, pos, pmove.player_mins, pmove.player_maxs, &trace, pe->origin, pe->angles))
|
||||
continue;
|
||||
if (trace.allsolid)
|
||||
return false; //solid
|
||||
{
|
||||
for (j = i+1; j < pmove.numphysent && trace.allsolid; j++)
|
||||
{
|
||||
pe = &pmove.physents[j];
|
||||
if (pe->isportal)
|
||||
PM_PortalCSG(pe, pmove.player_mins[2], pmove.player_maxs[2], pos, pos, &trace);
|
||||
}
|
||||
if (trace.allsolid)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -318,7 +399,7 @@ PM_PlayerTrace
|
|||
trace_t PM_PlayerTrace (vec3_t start, vec3_t end, unsigned int solidmask)
|
||||
{
|
||||
trace_t trace, total;
|
||||
int i;
|
||||
int i, j;
|
||||
physent_t *pe;
|
||||
|
||||
// fill in a default trace
|
||||
|
@ -352,6 +433,9 @@ trace_t PM_PlayerTrace (vec3_t start, vec3_t end, unsigned int solidmask)
|
|||
}
|
||||
else if (pe->isportal)
|
||||
{
|
||||
//make sure we don't hit the world if we're inside the portal
|
||||
PM_PortalCSG(pe, pmove.player_mins[2], pmove.player_maxs[2], start, end, &total);
|
||||
|
||||
// trace a line through the apropriate clipping hull
|
||||
if (!PM_TransformedHullCheck (pe->model, start, end, vec3_origin, vec3_origin, &trace, pe->origin, pe->angles))
|
||||
continue;
|
||||
|
@ -361,6 +445,17 @@ trace_t PM_PlayerTrace (vec3_t start, vec3_t end, unsigned int solidmask)
|
|||
// trace a line through the apropriate clipping hull
|
||||
if (!PM_TransformedHullCheck (pe->model, start, end, pmove.player_mins, pmove.player_maxs, &trace, pe->origin, pe->angles))
|
||||
continue;
|
||||
|
||||
if (trace.allsolid)
|
||||
{
|
||||
for (j = i+1; j < pmove.numphysent && trace.allsolid; j++)
|
||||
{
|
||||
pe = &pmove.physents[j];
|
||||
if (pe->isportal)
|
||||
PM_PortalCSG(pe, pmove.player_mins[2], pmove.player_maxs[2], start, end, &trace);
|
||||
}
|
||||
pe = &pmove.physents[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (trace.allsolid)
|
||||
|
@ -370,11 +465,7 @@ trace_t PM_PlayerTrace (vec3_t start, vec3_t end, unsigned int solidmask)
|
|||
continue;
|
||||
|
||||
if (trace.startsolid)
|
||||
{
|
||||
// if (!pmove.physents[i].model) //caught inside annother model
|
||||
// continue; //don't count this.
|
||||
trace.fraction = 0;
|
||||
}
|
||||
|
||||
// did we clip the move?
|
||||
if (trace.fraction < total.fraction)
|
||||
|
|
|
@ -4092,6 +4092,27 @@ void QCBUILTIN PF_droptofloor (pubprogfuncs_t *prinst, struct globalvars_s *pr_g
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
PF_checkbottom
|
||||
=============
|
||||
*/
|
||||
void QCBUILTIN PF_checkbottom (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
world_t *world = prinst->parms->user;
|
||||
wedict_t *ent;
|
||||
vec3_t gravup;
|
||||
|
||||
ent = G_WEDICT(prinst, OFS_PARM0);
|
||||
|
||||
if (ent->xv->gravitydir[0] || ent->xv->gravitydir[1] || ent->xv->gravitydir[2])
|
||||
VectorNegate(ent->xv->gravitydir, gravup);
|
||||
else
|
||||
VectorSet(gravup, 0, 0, 1);
|
||||
|
||||
G_FLOAT(OFS_RETURN) = World_CheckBottom (world, ent, gravup);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Vector functions
|
||||
|
||||
|
@ -4118,12 +4139,16 @@ This was a major timewaster in progs, so it was converted to C
|
|||
FIXME: add gravitydir support
|
||||
==============
|
||||
*/
|
||||
float World_changeyaw (wedict_t *ent);
|
||||
void QCBUILTIN PF_changeyaw (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
edict_t *ent;
|
||||
float ideal, current, move, speed;
|
||||
wedict_t *ent;
|
||||
// float ideal, current, move, speed;
|
||||
|
||||
ent = PROG_TO_EDICT(prinst, pr_global_struct->self);
|
||||
ent = PROG_TO_WEDICT(prinst, pr_global_struct->self);
|
||||
|
||||
World_changeyaw(ent);
|
||||
/*
|
||||
current = anglemod( ent->v->angles[1] );
|
||||
ideal = ent->v->ideal_yaw;
|
||||
speed = ent->v->yaw_speed;
|
||||
|
@ -4153,6 +4178,7 @@ void QCBUILTIN PF_changeyaw (pubprogfuncs_t *prinst, struct globalvars_s *pr_glo
|
|||
}
|
||||
|
||||
ent->v->angles[1] = anglemod (current + move);
|
||||
*/
|
||||
}
|
||||
|
||||
//void() changepitch = #63;
|
||||
|
@ -4194,20 +4220,33 @@ void QCBUILTIN PF_changepitch (pubprogfuncs_t *prinst, struct globalvars_s *pr_g
|
|||
ent->v->angles[1] = anglemod (current + move);
|
||||
}
|
||||
|
||||
//float vectoyaw(vector)
|
||||
//FIXME: support gravitydir
|
||||
//float vectoyaw(vector, optional entity reference)
|
||||
void QCBUILTIN PF_vectoyaw (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
float *value1;
|
||||
float x, y;
|
||||
float yaw;
|
||||
|
||||
value1 = G_VECTOR(OFS_PARM0);
|
||||
|
||||
if (value1[1] == 0 && value1[0] == 0)
|
||||
if (prinst->callargc >= 2)
|
||||
{
|
||||
vec3_t axis[3];
|
||||
World_GetEntGravityAxis(G_WEDICT(prinst, OFS_PARM1), axis);
|
||||
x = DotProduct(value1, axis[0]);
|
||||
y = DotProduct(value1, axis[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
x = value1[0];
|
||||
y = value1[1];
|
||||
}
|
||||
|
||||
if (y == 0 && x == 0)
|
||||
yaw = 0;
|
||||
else
|
||||
{
|
||||
yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI);
|
||||
yaw = (int) (atan2(y, x) * 180 / M_PI);
|
||||
if (yaw < 0)
|
||||
yaw += 360;
|
||||
}
|
||||
|
|
|
@ -125,6 +125,7 @@ void QCBUILTIN PF_dupstring(pubprogfuncs_t *prinst, struct globalvars_s *pr_glob
|
|||
void QCBUILTIN PF_forgetstring(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
|
||||
void QCBUILTIN PF_Spawn (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
|
||||
void QCBUILTIN PF_droptofloor (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
|
||||
void QCBUILTIN PF_checkbottom (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
|
||||
void QCBUILTIN PF_min (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
|
||||
void QCBUILTIN PF_max (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
|
||||
void QCBUILTIN PF_registercvar (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
|
||||
|
@ -481,6 +482,7 @@ pbool QDECL ED_CanFree (edict_t *ed);
|
|||
#define MOVETYPE_FOLLOW 12 // track movement of aiment
|
||||
#define MOVETYPE_H2PUSHPULL 13 // pushable/pullable object
|
||||
#define MOVETYPE_H2SWIM 14 // should keep the object in water
|
||||
#define MOVETYPE_6DOF 30 // flightsim mode
|
||||
#define MOVETYPE_WALLWALK 31 // walks up walls and along ceilings
|
||||
#define MOVETYPE_PHYSICS 32
|
||||
|
||||
|
|
|
@ -798,6 +798,48 @@ void Q1BSP_LoadBrushes(model_t *model)
|
|||
model->engineflags |= MDLF_HASBRUSHES;
|
||||
}
|
||||
|
||||
hull_t *Q1BSP_ChooseHull(model_t *model, int forcehullnum, vec3_t mins, vec3_t maxs, vec3_t offset)
|
||||
{
|
||||
hull_t *hull;
|
||||
vec3_t size;
|
||||
VectorSubtract (maxs, mins, size);
|
||||
if (forcehullnum >= 1 && forcehullnum <= MAX_MAP_HULLSM && model->hulls[forcehullnum-1].available)
|
||||
hull = &model->hulls[forcehullnum-1];
|
||||
else
|
||||
{
|
||||
if (model->hulls[5].available)
|
||||
{ //choose based on hexen2 sizes.
|
||||
|
||||
if (size[0] < 3) // Point
|
||||
hull = &model->hulls[0];
|
||||
else if (size[0] <= 8.1 && model->hulls[4].available)
|
||||
hull = &model->hulls[4]; //Pentacles
|
||||
else if (size[0] <= 32.1 && size[2] <= 28.1) // Half Player
|
||||
hull = &model->hulls[3];
|
||||
else if (size[0] <= 32.1) // Full Player
|
||||
hull = &model->hulls[1];
|
||||
else // Golumn
|
||||
hull = &model->hulls[5];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (size[0] < 3 || !model->hulls[1].available)
|
||||
hull = &model->hulls[0];
|
||||
else if (size[0] <= 32.1)
|
||||
{
|
||||
if (size[2] < 54.1 && model->hulls[3].available)
|
||||
hull = &model->hulls[3]; // 32x32x36 (half-life's crouch)
|
||||
else
|
||||
hull = &model->hulls[1];
|
||||
}
|
||||
else
|
||||
hull = &model->hulls[2];
|
||||
}
|
||||
}
|
||||
|
||||
VectorSubtract (hull->clip_mins, mins, offset);
|
||||
return hull;
|
||||
}
|
||||
qboolean Q1BSP_Trace(model_t *model, int forcehullnum, int frame, vec3_t axis[3], vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, unsigned int hitcontentsmask, trace_t *trace)
|
||||
{
|
||||
hull_t *hull;
|
||||
|
@ -805,7 +847,6 @@ qboolean Q1BSP_Trace(model_t *model, int forcehullnum, int frame, vec3_t axis[3]
|
|||
vec3_t start_l, end_l;
|
||||
vec3_t offset;
|
||||
|
||||
VectorSubtract (maxs, mins, size);
|
||||
if ((model->engineflags & MDLF_HASBRUSHES))// && (size[0] || size[1] || size[2]))
|
||||
{
|
||||
struct traceinfo_s traceinfo;
|
||||
|
@ -846,42 +887,7 @@ qboolean Q1BSP_Trace(model_t *model, int forcehullnum, int frame, vec3_t axis[3]
|
|||
trace->fraction = 1;
|
||||
trace->allsolid = true;
|
||||
|
||||
if (forcehullnum >= 1 && forcehullnum <= MAX_MAP_HULLSM && model->hulls[forcehullnum-1].available)
|
||||
hull = &model->hulls[forcehullnum-1];
|
||||
else
|
||||
{
|
||||
if (model->hulls[5].available)
|
||||
{ //choose based on hexen2 sizes.
|
||||
|
||||
if (size[0] < 3) // Point
|
||||
hull = &model->hulls[0];
|
||||
else if (size[0] <= 8.1 && model->hulls[4].available)
|
||||
hull = &model->hulls[4]; //Pentacles
|
||||
else if (size[0] <= 32.1 && size[2] <= 28.1) // Half Player
|
||||
hull = &model->hulls[3];
|
||||
else if (size[0] <= 32.1) // Full Player
|
||||
hull = &model->hulls[1];
|
||||
else // Golumn
|
||||
hull = &model->hulls[5];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (size[0] < 3 || !model->hulls[1].available)
|
||||
hull = &model->hulls[0];
|
||||
else if (size[0] <= 32.1)
|
||||
{
|
||||
if (size[2] < 54.1 && model->hulls[3].available)
|
||||
hull = &model->hulls[3]; // 32x32x36 (half-life's crouch)
|
||||
else
|
||||
hull = &model->hulls[1];
|
||||
}
|
||||
else
|
||||
hull = &model->hulls[2];
|
||||
}
|
||||
}
|
||||
|
||||
// calculate an offset value to center the origin
|
||||
VectorSubtract (hull->clip_mins, mins, offset);
|
||||
hull = Q1BSP_ChooseHull(model, forcehullnum, mins, maxs, offset);
|
||||
|
||||
// offset[0] = 0;
|
||||
// offset[1] = 0;
|
||||
|
|
|
@ -281,9 +281,10 @@ void Q2BSP_FindTouchedLeafs(model_t *mod, struct pvscache_s *ent, float *mins, f
|
|||
|
||||
|
||||
/*sv_move.c*/
|
||||
qboolean World_CheckBottom (world_t *world, wedict_t *ent);
|
||||
qboolean World_movestep (world_t *world, wedict_t *ent, vec3_t move, qboolean relink, qboolean noenemy, void (*set_move_trace)(trace_t *trace, struct globalvars_s *pr_globals), struct globalvars_s *set_trace_globs);
|
||||
qboolean World_CheckBottom (world_t *world, wedict_t *ent, vec3_t up);
|
||||
qboolean World_movestep (world_t *world, wedict_t *ent, vec3_t move, vec3_t axis[3], qboolean relink, qboolean noenemy, void (*set_move_trace)(trace_t *trace, struct globalvars_s *pr_globals), struct globalvars_s *set_trace_globs);
|
||||
qboolean World_MoveToGoal (world_t *world, wedict_t *ent, float dist);
|
||||
qboolean World_GetEntGravityAxis(wedict_t *ent, vec3_t axis[3]);
|
||||
|
||||
void WPhys_Init(void);
|
||||
void World_Physics_Frame(world_t *w);
|
||||
|
|
|
@ -2820,6 +2820,7 @@ void Shader_FlushCache(void)
|
|||
for (i = 0; i < HASH_SIZE; i++)
|
||||
{
|
||||
cache = shader_hash[i];
|
||||
shader_hash[i] = NULL;
|
||||
|
||||
for (; cache; cache = cache_next)
|
||||
{
|
||||
|
@ -4962,6 +4963,8 @@ void Shader_DoReload(void)
|
|||
|
||||
if (shader_rescan_needed && ruleset_allow_shaders.ival)
|
||||
{
|
||||
Shader_FlushCache();
|
||||
|
||||
COM_EnumerateFiles("materials/*.mtr", Shader_InitCallback, NULL);
|
||||
COM_EnumerateFiles("shaders/*.shader", Shader_InitCallback, NULL);
|
||||
COM_EnumerateFiles("scripts/*.shader", Shader_InitCallback, NULL);
|
||||
|
|
|
@ -369,8 +369,11 @@ pbool PDECL SV_BadField(pubprogfuncs_t *inst, edict_t *foo, const char *keyname,
|
|||
{
|
||||
/*hexen2 midi - just mute it, we don't support it*/
|
||||
if (!stricmp(keyname, "MIDI"))
|
||||
{
|
||||
Q_strncpyz(sv.h2miditrack, value, sizeof(sv.h2miditrack));
|
||||
return true;
|
||||
/*hexen2 does cd tracks slightly differently too*/
|
||||
}
|
||||
/*hexen2 does cd tracks slightly differently too, so there's consistancy for you*/
|
||||
if (!stricmp(keyname, "CD"))
|
||||
{
|
||||
sv.h2cdtrack = atoi(value);
|
||||
|
@ -3915,14 +3918,16 @@ float(float yaw, float dist) walkmove
|
|||
*/
|
||||
static void QCBUILTIN PF_walkmove (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
edict_t *ent;
|
||||
wedict_t *ent;
|
||||
float yaw, dist;
|
||||
vec3_t move;
|
||||
// dfunction_t *oldf;
|
||||
int oldself;
|
||||
qboolean settrace;
|
||||
vec3_t axis[3];
|
||||
float s;
|
||||
|
||||
ent = PROG_TO_EDICT(prinst, pr_global_struct->self);
|
||||
ent = PROG_TO_WEDICT(prinst, pr_global_struct->self);
|
||||
yaw = G_FLOAT(OFS_PARM0);
|
||||
dist = G_FLOAT(OFS_PARM1);
|
||||
if (svprogfuncs->callargc >= 3 && G_FLOAT(OFS_PARM2))
|
||||
|
@ -3937,10 +3942,12 @@ static void QCBUILTIN PF_walkmove (pubprogfuncs_t *prinst, struct globalvars_s *
|
|||
}
|
||||
|
||||
yaw = yaw*M_PI*2 / 360;
|
||||
World_GetEntGravityAxis(ent, axis);
|
||||
|
||||
move[0] = cos(yaw)*dist;
|
||||
move[1] = sin(yaw)*dist;
|
||||
move[2] = 0;
|
||||
s = cos(yaw)*dist;
|
||||
VectorScale(axis[0], s, move);
|
||||
s = sin(yaw)*dist;
|
||||
VectorMA(move, s, axis[1], move);
|
||||
|
||||
// save program state, because SV_movestep may call other progs
|
||||
// oldf = pr_xfunction;
|
||||
|
@ -3952,7 +3959,7 @@ static void QCBUILTIN PF_walkmove (pubprogfuncs_t *prinst, struct globalvars_s *
|
|||
// }
|
||||
// else if (!SV_TestEntityPosition(ent))
|
||||
// {
|
||||
G_FLOAT(OFS_RETURN) = World_movestep(&sv.world, (wedict_t*)ent, move, true, false, settrace?set_trace_globals:NULL, pr_globals);
|
||||
G_FLOAT(OFS_RETURN) = World_movestep(&sv.world, (wedict_t*)ent, move, axis, true, false, settrace?set_trace_globals:NULL, pr_globals);
|
||||
// if (SV_TestEntityPosition(ent))
|
||||
// Con_Printf("Entity became stuck\n");
|
||||
// }
|
||||
|
@ -4097,20 +4104,6 @@ static void QCBUILTIN PF_lightstylestatic (pubprogfuncs_t *prinst, struct global
|
|||
PF_applylightstyle(style, val, col);
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
PF_checkbottom
|
||||
=============
|
||||
*/
|
||||
static void QCBUILTIN PF_checkbottom (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
edict_t *ent;
|
||||
|
||||
ent = G_EDICT(prinst, OFS_PARM0);
|
||||
|
||||
G_FLOAT(OFS_RETURN) = World_CheckBottom (&sv.world, (wedict_t*)ent);
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
PF_pointcontents
|
||||
|
@ -6869,7 +6862,7 @@ static void QCBUILTIN PF_h2movestep (pubprogfuncs_t *prinst, struct globalvars_s
|
|||
// save program state, because SV_movestep may call other progs
|
||||
oldself = pr_global_struct->self;
|
||||
|
||||
G_INT(OFS_RETURN) = World_movestep (&sv.world, (wedict_t*)ent, v, false, true, set_trace?set_trace_globals:NULL, pr_globals);
|
||||
G_INT(OFS_RETURN) = World_movestep (&sv.world, (wedict_t*)ent, v, NULL, false, true, set_trace?set_trace_globals:NULL, pr_globals);
|
||||
|
||||
// restore program state
|
||||
pr_global_struct->self = oldself;
|
||||
|
@ -8402,33 +8395,6 @@ static void QCBUILTIN PF_setcolors (pubprogfuncs_t *prinst, struct globalvars_s
|
|||
SV_ExtractFromUserinfo (client, true);
|
||||
}
|
||||
|
||||
|
||||
static client_t *DirectSplit(client_t *cl, int svc, int svclen)
|
||||
{
|
||||
if (cl->controller)
|
||||
{ //this is a slave client.
|
||||
//find the right number and send.
|
||||
client_t *sp;
|
||||
int pnum = 0;
|
||||
for (sp = cl->controller; sp; sp = sp->controlled)
|
||||
{
|
||||
if (sp == cl)
|
||||
break;
|
||||
pnum++;
|
||||
}
|
||||
sp = cl->controller;
|
||||
|
||||
ClientReliableWrite_Begin (sp, svcfte_choosesplitclient, 2+svclen);
|
||||
ClientReliableWrite_Byte (sp, pnum);
|
||||
ClientReliableWrite_Byte (sp, svc);
|
||||
return sp;
|
||||
}
|
||||
else
|
||||
{
|
||||
ClientReliableWrite_Begin (cl, svc, svclen);
|
||||
return cl;
|
||||
}
|
||||
}
|
||||
static void ParamNegateFix ( float * xx, float * yy, int Zone )
|
||||
{
|
||||
float x,y;
|
||||
|
@ -8466,7 +8432,7 @@ static void QCBUILTIN PF_ShowPic(pubprogfuncs_t *prinst, struct globalvars_s *pr
|
|||
if (!(svs.clients[entnum].fteprotocolextensions & PEXT_SHOWPIC))
|
||||
return; //need an extension for this. duh.
|
||||
|
||||
cl = DirectSplit(&svs.clients[entnum], svcfte_showpic, 8 + strlen(slot)+strlen(picname));
|
||||
cl = ClientReliableWrite_BeginSplit(&svs.clients[entnum], svcfte_showpic, 8 + strlen(slot)+strlen(picname));
|
||||
ClientReliableWrite_Byte(cl, zone);
|
||||
ClientReliableWrite_String(cl, slot);
|
||||
ClientReliableWrite_String(cl, picname);
|
||||
|
@ -8499,7 +8465,7 @@ static void QCBUILTIN PF_HidePic(pubprogfuncs_t *prinst, struct globalvars_s *pr
|
|||
if (!(svs.clients[entnum].fteprotocolextensions & PEXT_SHOWPIC))
|
||||
return; //need an extension for this. duh.
|
||||
|
||||
cl = DirectSplit(&svs.clients[entnum], svcfte_hidepic, 2 + strlen(slot));
|
||||
cl = ClientReliableWrite_BeginSplit(&svs.clients[entnum], svcfte_hidepic, 2 + strlen(slot));
|
||||
ClientReliableWrite_String(cl, slot);
|
||||
}
|
||||
else
|
||||
|
@ -8534,7 +8500,7 @@ static void QCBUILTIN PF_MovePic(pubprogfuncs_t *prinst, struct globalvars_s *pr
|
|||
if (!(svs.clients[entnum].fteprotocolextensions & PEXT_SHOWPIC))
|
||||
return; //need an extension for this. duh.
|
||||
|
||||
cl = DirectSplit(&svs.clients[entnum], svcfte_movepic, 6 + strlen(slot));
|
||||
cl = ClientReliableWrite_BeginSplit(&svs.clients[entnum], svcfte_movepic, 6 + strlen(slot));
|
||||
ClientReliableWrite_String(cl, slot);
|
||||
ClientReliableWrite_Byte(cl, zone);
|
||||
ClientReliableWrite_Short(cl, x);
|
||||
|
@ -8567,7 +8533,7 @@ static void QCBUILTIN PF_ChangePic(pubprogfuncs_t *prinst, struct globalvars_s *
|
|||
if (!(svs.clients[entnum].fteprotocolextensions & PEXT_SHOWPIC))
|
||||
return; //need an extension for this. duh.
|
||||
|
||||
cl = DirectSplit(&svs.clients[entnum], svcfte_updatepic, 3 + strlen(slot)+strlen(newpic));
|
||||
cl = ClientReliableWrite_BeginSplit(&svs.clients[entnum], svcfte_updatepic, 3 + strlen(slot)+strlen(newpic));
|
||||
ClientReliableWrite_String(cl, slot);
|
||||
ClientReliableWrite_String(cl, newpic);
|
||||
}
|
||||
|
@ -9000,7 +8966,7 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
|
|||
{"error", PF_error, 10, 10, 10, 0, D("void(string e)", "Ends the game with an easily readable error message.")},
|
||||
{"objerror", PF_objerror, 11, 11, 11, 0, D("void(string e)", "Displays a non-fatal easily readable error message concerning the self entity, including a field dump. self will be removed!")},
|
||||
{"vlen", PF_vlen, 12, 12, 12, 0, D("float(vector v)", "Returns the square root of the dotproduct of a vector with itself. Or in other words the length of a distance vector, in quake units.")},
|
||||
{"vectoyaw", PF_vectoyaw, 13, 13, 13, 0, D("float(vector v)", "Given a direction vector, returns the yaw (_y) angle in which that direction vector points.")},
|
||||
{"vectoyaw", PF_vectoyaw, 13, 13, 13, 0, D("float(vector v, optional entity reference)", "Given a direction vector, returns the yaw angle in which that direction vector points. If an entity is passed, the yaw angle will be relative to that entity's gravity direction.")},
|
||||
{"spawn", PF_Spawn, 14, 14, 14, 0, D("entity()", "Adds a brand new entity into the world! Hurrah, you're now a parent!")},
|
||||
{"remove", PF_Remove, 15, 15, 15, 0, D("void(entity e)", "Destroys the given entity and clears some limited fields (including model, modelindex, solid, classname). Any references to the entity following the call are an error. After two seconds, the entity will be reused, in the interim you can unfortunatly still read its fields to see if the reference is no longer valid.")},
|
||||
{"traceline", PF_svtraceline, 16, 16, 16, 0, D("void(vector v1, vector v2, float flags, entity ent)", "Traces an infinitely thin line through the world from v1 towards v2.\nWill not collide with ent, ent.owner, or any entity who's owner field refers to ent.\nThere are no side effects beyond the trace_* globals being written.\nflags&MOVE_NOMONSTERS will not impact on non-bsp entities.\nflags&MOVE_MISSILE will impact with increased size.\nflags&MOVE_HITMODEL will impact upon model meshes, instead of their bounding boxes.\nflags&MOVE_TRIGGERS will also stop on triggers\nflags&MOVE_EVERYTHING will stop if it hits anything, even non-solid entities.\nflags&MOVE_LAGGED will backdate entity positions for the purposes of this builtin according to the indicated player ent's latency, to provide lag compensation.")},
|
||||
|
|
|
@ -1011,6 +1011,7 @@ static int bi_lua_walkmove(lua_State *L)
|
|||
float yaw, dist;
|
||||
vec3_t move;
|
||||
int oldself;
|
||||
vec3_t axis;
|
||||
|
||||
ent = PROG_TO_WEDICT(prinst, *world->g.self);
|
||||
yaw = lua.tonumberx(L, 1, NULL);
|
||||
|
@ -1022,16 +1023,17 @@ static int bi_lua_walkmove(lua_State *L)
|
|||
return 1;
|
||||
}
|
||||
|
||||
World_GetEntGravityAxis(ent, axis);
|
||||
|
||||
yaw = yaw*M_PI*2 / 360;
|
||||
|
||||
move[0] = cos(yaw)*dist;
|
||||
move[1] = sin(yaw)*dist;
|
||||
move[2] = 0;
|
||||
VectorScale(axis[0], cos(yaw)*dist, move);
|
||||
VectorMA(move, sin(yaw)*dist, axis[1], move);
|
||||
|
||||
// save program state, because World_movestep may call other progs
|
||||
oldself = *world->g.self;
|
||||
|
||||
lua.pushboolean(L, World_movestep(world, ent, move, true, false, NULL, NULL));
|
||||
lua.pushboolean(L, World_movestep(world, ent, move, axis, true, false, NULL, NULL));
|
||||
|
||||
// restore program state
|
||||
*world->g.self = oldself;
|
||||
|
|
|
@ -734,17 +734,20 @@ static qintptr_t syscallhandle (void *offset, quintptr_t mask, qintptr_t fn, con
|
|||
|
||||
case G_WALKMOVE:
|
||||
{
|
||||
edict_t *ed = EDICT_NUM(svprogfuncs, arg[0]);
|
||||
wedict_t *ed = WEDICT_NUM(svprogfuncs, arg[0]);
|
||||
float yaw = VM_FLOAT(arg[1]);
|
||||
float dist = VM_FLOAT(arg[2]);
|
||||
vec3_t move;
|
||||
vec3_t axis[3];
|
||||
|
||||
World_GetEntGravityAxis(ed, axis);
|
||||
|
||||
yaw = yaw*M_PI*2 / 360;
|
||||
move[0] = cos(yaw)*dist;
|
||||
move[1] = sin(yaw)*dist;
|
||||
move[2] = 0;
|
||||
|
||||
return World_movestep(&sv.world, (wedict_t*)ed, move, true, false, NULL, NULL);
|
||||
return World_movestep(&sv.world, (wedict_t*)ed, move, axis, true, false, NULL, NULL);
|
||||
}
|
||||
|
||||
case G_DROPTOFLOOR:
|
||||
|
@ -780,7 +783,10 @@ static qintptr_t syscallhandle (void *offset, quintptr_t mask, qintptr_t fn, con
|
|||
break;
|
||||
|
||||
case G_CHECKBOTTOM:
|
||||
return World_CheckBottom(&sv.world, (wedict_t*)EDICT_NUM(svprogfuncs, VM_LONG(arg[0])));
|
||||
{
|
||||
vec3_t up = {0,0,1};
|
||||
return World_CheckBottom(&sv.world, (wedict_t*)EDICT_NUM(svprogfuncs, VM_LONG(arg[0])), up);
|
||||
}
|
||||
|
||||
case G_POINTCONTENTS:
|
||||
{
|
||||
|
|
|
@ -141,6 +141,7 @@ typedef struct
|
|||
qbyte lightstylecolours[MAX_LIGHTSTYLES];
|
||||
};
|
||||
} strings;
|
||||
char h2miditrack[MAX_QPATH];
|
||||
qbyte h2cdtrack;
|
||||
|
||||
int allocated_client_slots; //number of slots available. (used mostly to stop single player saved games cacking up)
|
||||
|
@ -1190,6 +1191,7 @@ void SV_CSQC_DropAll(client_t *client);
|
|||
void ClientReliableCheckBlock(client_t *cl, int maxsize);
|
||||
void ClientReliable_FinishWrite(client_t *cl);
|
||||
void ClientReliableWrite_Begin(client_t *cl, int c, int maxsize);
|
||||
client_t *ClientReliableWrite_BeginSplit(client_t *cl, int svc, int svclen);
|
||||
void ClientReliableWrite_Angle(client_t *cl, float f);
|
||||
void ClientReliableWrite_Angle16(client_t *cl, float f);
|
||||
void ClientReliableWrite_Byte(client_t *cl, int c);
|
||||
|
|
|
@ -5168,6 +5168,7 @@ void SV_InitLocal (void)
|
|||
extern cvar_t pm_walljump;
|
||||
extern cvar_t pm_slidyslopes;
|
||||
extern cvar_t pm_watersinkspeed;
|
||||
extern cvar_t pm_flyfriction;
|
||||
|
||||
SV_InitOperatorCommands ();
|
||||
SV_UserInit ();
|
||||
|
@ -5221,6 +5222,7 @@ void SV_InitLocal (void)
|
|||
|
||||
Cvar_Register (&pm_bunnyspeedcap, cvargroup_serverphysics);
|
||||
Cvar_Register (&pm_watersinkspeed, cvargroup_serverphysics);
|
||||
Cvar_Register (&pm_flyfriction, cvargroup_serverphysics);
|
||||
Cvar_Register (&pm_ktjump, cvargroup_serverphysics);
|
||||
Cvar_Register (&pm_slidefix, cvargroup_serverphysics);
|
||||
Cvar_Register (&pm_slidyslopes, cvargroup_serverphysics);
|
||||
|
|
|
@ -23,7 +23,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#include "pr_common.h"
|
||||
|
||||
#if defined(CSQC_DAT) || !defined(CLIENTONLY)
|
||||
|
||||
/*
|
||||
=============
|
||||
SV_CheckBottom
|
||||
|
@ -35,26 +34,59 @@ is not a staircase.
|
|||
*/
|
||||
int c_yes, c_no;
|
||||
|
||||
qboolean World_CheckBottom (world_t *world, wedict_t *ent)
|
||||
hull_t *Q1BSP_ChooseHull(model_t *model, int hullnum, vec3_t mins, vec3_t maxs, vec3_t offset);
|
||||
|
||||
//this function is axial. major axis determines ground. if it switches slightly, a new axis may become the ground...
|
||||
qboolean World_CheckBottom (world_t *world, wedict_t *ent, vec3_t up)
|
||||
{
|
||||
int savedhull;
|
||||
vec3_t mins, maxs, start, stop;
|
||||
trace_t trace;
|
||||
int x, y;
|
||||
float mid, bottom;
|
||||
float mid;
|
||||
|
||||
int a0,a1,a2; //logical x, y, z
|
||||
int sign;
|
||||
|
||||
mins[0] = fabs(up[0]);
|
||||
mins[1] = fabs(up[1]);
|
||||
mins[2] = fabs(up[2]);
|
||||
if (mins[2] > mins[0] && mins[2] > mins[1])
|
||||
{
|
||||
a0 = 0;
|
||||
a1 = 1;
|
||||
a2 = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
a2 = mins[1] > mins[0];
|
||||
a0 = 1 - a2;
|
||||
a1 = 2;
|
||||
}
|
||||
sign = (up[a2]>0)?1:-1;
|
||||
|
||||
VectorAdd (ent->v->origin, ent->v->mins, mins);
|
||||
VectorAdd (ent->v->origin, ent->v->maxs, maxs);
|
||||
if (world->worldmodel->fromgame == fg_quake)
|
||||
{
|
||||
//quake's hulls are weird. sizes are defined as from mins to mins+hullsize. the actual maxs is ignored other than for its size.
|
||||
hull_t *hull;
|
||||
hull = Q1BSP_ChooseHull(world->worldmodel, ent->xv->hull, ent->v->mins, ent->v->maxs, start);
|
||||
VectorAdd (mins, start, mins);
|
||||
VectorSubtract (mins, hull->clip_mins, maxs);
|
||||
VectorAdd (maxs, hull->clip_maxs, maxs);
|
||||
}
|
||||
else
|
||||
VectorAdd (ent->v->origin, ent->v->maxs, maxs);
|
||||
|
||||
// if all of the points under the corners are solid world, don't bother
|
||||
// with the tougher checks
|
||||
// the corners must be within 16 of the midpoint
|
||||
start[2] = mins[2] - 1;
|
||||
start[a2] = (sign<0)?maxs[a2]:mins[a2] - sign;
|
||||
for (x=0 ; x<=1 ; x++)
|
||||
for (y=0 ; y<=1 ; y++)
|
||||
{
|
||||
start[0] = x ? maxs[0] : mins[0];
|
||||
start[1] = y ? maxs[1] : mins[1];
|
||||
start[a0] = x ? maxs[a0] : mins[a0];
|
||||
start[a1] = y ? maxs[a1] : mins[a1];
|
||||
if (!(World_PointContents (world, start) & FTECONTENTS_SOLID))
|
||||
goto realcheck;
|
||||
}
|
||||
|
@ -67,12 +99,12 @@ realcheck:
|
|||
//
|
||||
// check it for real...
|
||||
//
|
||||
start[2] = mins[2];
|
||||
start[a2] = (sign<0)?maxs[a2]:mins[a2];
|
||||
|
||||
// the midpoint must be within 16 of the bottom
|
||||
start[0] = stop[0] = (mins[0] + maxs[0])*0.5;
|
||||
start[1] = stop[1] = (mins[1] + maxs[1])*0.5;
|
||||
stop[2] = start[2] - 2*movevars.stepheight;
|
||||
start[a0] = stop[a0] = (mins[a0] + maxs[a0])*0.5;
|
||||
start[a1] = stop[a1] = (mins[a1] + maxs[a1])*0.5;
|
||||
stop[a2] = start[a2] - 2*movevars.stepheight*sign;
|
||||
savedhull = ent->xv->hull;
|
||||
ent->xv->hull = 0; //stop the hull from breaking tracelines
|
||||
trace = World_Move (world, start, vec3_origin, vec3_origin, stop, true, ent);
|
||||
|
@ -82,20 +114,20 @@ realcheck:
|
|||
ent->xv->hull = savedhull;
|
||||
return false;
|
||||
}
|
||||
mid = bottom = trace.endpos[2];
|
||||
mid = trace.endpos[2];
|
||||
|
||||
mid = (mid-start[a2]-(movevars.stepheight*sign)) / (stop[a2]-start[a2]);
|
||||
|
||||
// the corners must be within 16 of the midpoint
|
||||
for (x=0 ; x<=1 ; x++)
|
||||
for (y=0 ; y<=1 ; y++)
|
||||
{
|
||||
start[0] = stop[0] = x ? maxs[0] : mins[0];
|
||||
start[1] = stop[1] = y ? maxs[1] : mins[1];
|
||||
start[a0] = stop[a0] = x ? maxs[a0] : mins[a0];
|
||||
start[a1] = stop[a1] = y ? maxs[a1] : mins[a1];
|
||||
|
||||
trace = World_Move (world, start, vec3_origin, vec3_origin, stop, true, ent);
|
||||
|
||||
if (trace.fraction != 1.0 && trace.endpos[2] > bottom)
|
||||
bottom = trace.endpos[2];
|
||||
if (trace.fraction == 1.0 || mid - trace.endpos[2] > movevars.stepheight)
|
||||
if (trace.fraction == 1.0 || trace.fraction > mid)//mid - trace.endpos[2] > movevars.stepheight)
|
||||
{
|
||||
ent->xv->hull = savedhull;
|
||||
return false;
|
||||
|
@ -117,7 +149,7 @@ possible, no move is done, false is returned, and
|
|||
pr_global_struct->trace_normal is set to the normal of the blocking wall
|
||||
=============
|
||||
*/
|
||||
qboolean World_movestep (world_t *world, wedict_t *ent, vec3_t move, qboolean relink, qboolean noenemy, void (*set_move_trace)(trace_t *trace, struct globalvars_s *pr_globals), struct globalvars_s *set_trace_globs)
|
||||
qboolean World_movestep (world_t *world, wedict_t *ent, vec3_t move, vec3_t axis[3], qboolean relink, qboolean noenemy, void (*set_move_trace)(trace_t *trace, struct globalvars_s *pr_globals), struct globalvars_s *set_trace_globs)
|
||||
{
|
||||
float dz;
|
||||
vec3_t oldorg, neworg, end;
|
||||
|
@ -125,6 +157,14 @@ qboolean World_movestep (world_t *world, wedict_t *ent, vec3_t move, qboolean re
|
|||
int i;
|
||||
wedict_t *enemy = world->edicts;
|
||||
int eflags = ent->v->flags;
|
||||
vec3_t eaxis[3];
|
||||
|
||||
if (!axis)
|
||||
{
|
||||
//fixme?
|
||||
World_GetEntGravityAxis(ent, eaxis);
|
||||
axis = eaxis;
|
||||
}
|
||||
|
||||
#ifndef CLIENTONLY
|
||||
if (progstype != PROG_H2 || world != &sv.world)
|
||||
|
@ -147,13 +187,14 @@ qboolean World_movestep (world_t *world, wedict_t *ent, vec3_t move, qboolean re
|
|||
enemy = (wedict_t*)PROG_TO_EDICT(world->progs, ent->v->enemy);
|
||||
if (i == 0 && enemy->entnum)
|
||||
{
|
||||
dz = ent->v->origin[2] - ((wedict_t*)PROG_TO_EDICT(world->progs, ent->v->enemy))->v->origin[2];
|
||||
VectorSubtract(ent->v->origin, ((wedict_t*)PROG_TO_EDICT(world->progs, ent->v->enemy))->v->origin, end);
|
||||
dz = DotProduct(end, axis[2]);
|
||||
if (eflags & FLH2_HUNTFACE) /*get the ent's origin_z to match its victims face*/
|
||||
dz += ((wedict_t*)PROG_TO_EDICT(world->progs, ent->v->enemy))->v->view_ofs[2];
|
||||
if (dz > 40)
|
||||
neworg[2] -= 8;
|
||||
VectorMA(neworg, -8, axis[2], neworg);
|
||||
if (dz < 30)
|
||||
neworg[2] += 8;
|
||||
VectorMA(neworg, 8, axis[2], neworg);
|
||||
}
|
||||
}
|
||||
trace = World_Move (world, ent->v->origin, ent->v->mins, ent->v->maxs, neworg, false, ent);
|
||||
|
@ -179,9 +220,8 @@ qboolean World_movestep (world_t *world, wedict_t *ent, vec3_t move, qboolean re
|
|||
}
|
||||
|
||||
// push down from a step height above the wished position
|
||||
neworg[2] += movevars.stepheight;
|
||||
VectorCopy (neworg, end);
|
||||
end[2] -= movevars.stepheight*2;
|
||||
VectorMA(neworg, movevars.stepheight, axis[2], neworg);
|
||||
VectorMA(neworg, movevars.stepheight*-2, axis[2], end);
|
||||
|
||||
trace = World_Move (world, neworg, ent->v->mins, ent->v->maxs, end, false, ent);
|
||||
if (set_move_trace)
|
||||
|
@ -192,7 +232,8 @@ qboolean World_movestep (world_t *world, wedict_t *ent, vec3_t move, qboolean re
|
|||
|
||||
if (trace.startsolid)
|
||||
{
|
||||
neworg[2] -= movevars.stepheight;
|
||||
//move up by an extra step, if needed
|
||||
VectorMA(neworg, -movevars.stepheight, axis[2], neworg);
|
||||
trace = World_Move (world, neworg, ent->v->mins, ent->v->maxs, end, false, ent);
|
||||
if (set_move_trace)
|
||||
set_move_trace(&trace, set_trace_globs);
|
||||
|
@ -218,7 +259,7 @@ qboolean World_movestep (world_t *world, wedict_t *ent, vec3_t move, qboolean re
|
|||
// check point traces down for dangling corners
|
||||
VectorCopy (trace.endpos, ent->v->origin);
|
||||
|
||||
if (!World_CheckBottom (world, ent))
|
||||
if (!World_CheckBottom (world, ent, axis[2]))
|
||||
{
|
||||
if ( (int)ent->v->flags & FL_PARTIALGROUND )
|
||||
{ // entity had floor mostly pulled out from underneath it
|
||||
|
@ -247,6 +288,28 @@ qboolean World_movestep (world_t *world, wedict_t *ent, vec3_t move, qboolean re
|
|||
|
||||
//============================================================================
|
||||
|
||||
qboolean World_GetEntGravityAxis(wedict_t *ent, vec3_t axis[3])
|
||||
{
|
||||
if (ent->xv->gravitydir[0] || ent->xv->gravitydir[1] || ent->xv->gravitydir[2])
|
||||
{
|
||||
void PerpendicularVector( vec3_t dst, const vec3_t src );
|
||||
VectorNegate(ent->xv->gravitydir, axis[2]);
|
||||
VectorNormalize(axis[2]);
|
||||
PerpendicularVector(axis[0], axis[2]);
|
||||
VectorNormalize(axis[0]);
|
||||
CrossProduct(axis[2], axis[0], axis[1]);
|
||||
VectorNormalize(axis[1]);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
VectorSet(axis[0], 1, 0, 0);
|
||||
VectorSet(axis[1], 0, 1, 0);
|
||||
VectorSet(axis[2], 0, 0, 1);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
PF_changeyaw
|
||||
|
@ -254,9 +317,80 @@ PF_changeyaw
|
|||
This was a major timewaster in progs, so it was converted to C
|
||||
==============
|
||||
*/
|
||||
void World_changeyaw (wedict_t *ent)
|
||||
float World_changeyaw (wedict_t *ent)
|
||||
{
|
||||
float ideal, current, move, speed;
|
||||
vec3_t surf[3];
|
||||
if (World_GetEntGravityAxis(ent, surf))
|
||||
{
|
||||
//complex matrix stuff
|
||||
float mat[16];
|
||||
float surfm[16], invsurfm[16];
|
||||
float viewm[16];
|
||||
vec3_t view[4];
|
||||
vec3_t vang;
|
||||
|
||||
/*calc current view matrix relative to the surface*/
|
||||
ent->v->angles[PITCH] *= -1;
|
||||
AngleVectors(ent->v->angles, view[0], view[1], view[2]);
|
||||
VectorNegate(view[1], view[1]);
|
||||
|
||||
World_GetEntGravityAxis(ent, surf);
|
||||
|
||||
Matrix4x4_RM_FromVectors(surfm, surf[0], surf[1], surf[2], vec3_origin);
|
||||
Matrix3x4_InvertTo4x4_Simple(surfm, invsurfm);
|
||||
|
||||
/*calc current view matrix relative to the surface*/
|
||||
Matrix4x4_RM_FromVectors(viewm, view[0], view[1], view[2], vec3_origin);
|
||||
Matrix4_Multiply(viewm, invsurfm, mat);
|
||||
/*convert that back to angles*/
|
||||
Matrix3x4_RM_ToVectors(mat, view[0], view[1], view[2], view[3]);
|
||||
VectorAngles(view[0], view[2], vang);
|
||||
|
||||
/*edit it*/
|
||||
|
||||
ideal = ent->v->ideal_yaw;
|
||||
speed = ent->v->yaw_speed;
|
||||
move = ideal - anglemod(vang[YAW]);
|
||||
if (move > 180)
|
||||
move -= 360;
|
||||
else if (move < -180)
|
||||
move += 360;
|
||||
if (move > 0)
|
||||
{
|
||||
if (move > speed)
|
||||
move = speed;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (move < -speed)
|
||||
move = -speed;
|
||||
}
|
||||
vang[YAW] = anglemod(vang[YAW] + move);
|
||||
|
||||
/*clamp pitch, kill roll. monsters don't pitch/roll.*/
|
||||
vang[PITCH] = 0;
|
||||
vang[ROLL] = 0;
|
||||
|
||||
move = ideal - vang[YAW];
|
||||
|
||||
/*turn those angles back to a matrix*/
|
||||
AngleVectors(vang, view[0], view[1], view[2]);
|
||||
VectorNegate(view[1], view[1]);
|
||||
Matrix4x4_RM_FromVectors(mat, view[0], view[1], view[2], vec3_origin);
|
||||
/*rotate back into world space*/
|
||||
Matrix4_Multiply(mat, surfm, viewm);
|
||||
/*and figure out the final result*/
|
||||
Matrix3x4_RM_ToVectors(viewm, view[0], view[1], view[2], view[3]);
|
||||
VectorAngles(view[0], view[2], ent->v->angles);
|
||||
|
||||
//make sure everything is sane
|
||||
ent->v->angles[PITCH] = anglemod(ent->v->angles[PITCH]);
|
||||
ent->v->angles[YAW] = anglemod(ent->v->angles[YAW]);
|
||||
ent->v->angles[ROLL] = anglemod(ent->v->angles[ROLL]);
|
||||
return move;
|
||||
}
|
||||
|
||||
|
||||
//FIXME: gravitydir. reorient the angles to change the yaw with respect to the current ground surface.
|
||||
|
||||
|
@ -265,7 +399,7 @@ void World_changeyaw (wedict_t *ent)
|
|||
speed = ent->v->yaw_speed;
|
||||
|
||||
if (current == ideal)
|
||||
return;
|
||||
return 0;
|
||||
move = ideal - current;
|
||||
if (ideal > current)
|
||||
{
|
||||
|
@ -289,6 +423,8 @@ void World_changeyaw (wedict_t *ent)
|
|||
}
|
||||
|
||||
ent->v->angles[1] = anglemod (current + move);
|
||||
|
||||
return ideal - ent->v->angles[1];
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -300,29 +436,31 @@ facing it.
|
|||
|
||||
======================
|
||||
*/
|
||||
qboolean World_StepDirection (world_t *world, wedict_t *ent, float yaw, float dist)
|
||||
qboolean World_StepDirection (world_t *world, wedict_t *ent, float yaw, float dist, vec3_t axis[3])
|
||||
{
|
||||
vec3_t move, oldorigin;
|
||||
float delta;
|
||||
float delta, s;
|
||||
|
||||
ent->v->ideal_yaw = yaw;
|
||||
|
||||
World_changeyaw(ent);
|
||||
delta = World_changeyaw(ent);
|
||||
|
||||
yaw = yaw*M_PI*2 / 360;
|
||||
//FIXME: gravitydir
|
||||
move[0] = cos(yaw)*dist;
|
||||
move[1] = sin(yaw)*dist;
|
||||
move[2] = 0;
|
||||
|
||||
s = cos(yaw)*dist;
|
||||
VectorScale(axis[0], s, move);
|
||||
s = sin(yaw)*dist;
|
||||
VectorMA(move, s, axis[1], move);
|
||||
|
||||
//FIXME: Hexen2: ent flags & FL_SET_TRACE
|
||||
|
||||
VectorCopy (ent->v->origin, oldorigin);
|
||||
if (World_movestep (world, ent, move, false, false, NULL, NULL))
|
||||
if (World_movestep (world, ent, move, axis, false, false, NULL, NULL))
|
||||
{
|
||||
delta = ent->v->angles[YAW] - ent->v->ideal_yaw;
|
||||
delta = anglemod(delta);
|
||||
if (delta > 45 && delta < 315)
|
||||
{ // not turned far enough, so don't take the step
|
||||
{ // not turned far enough, so don't take the step
|
||||
//FIXME: surely this is noticably inefficient?
|
||||
VectorCopy (oldorigin, ent->v->origin);
|
||||
}
|
||||
World_LinkEdict (world, ent, true);
|
||||
|
@ -356,7 +494,7 @@ SV_NewChaseDir
|
|||
*/
|
||||
#define DI_NODIR -1
|
||||
|
||||
void World_NewChaseDir (world_t *world, wedict_t *actor, wedict_t *enemy, float dist)
|
||||
void World_NewChaseDir (world_t *world, wedict_t *actor, wedict_t *enemy, float dist, vec3_t axis[3])
|
||||
{
|
||||
float deltax,deltay;
|
||||
float d[3];
|
||||
|
@ -365,8 +503,9 @@ void World_NewChaseDir (world_t *world, wedict_t *actor, wedict_t *enemy, float
|
|||
olddir = anglemod( (int)(actor->v->ideal_yaw/45)*45 );
|
||||
turnaround = anglemod(olddir - 180);
|
||||
|
||||
deltax = enemy->v->origin[0] - actor->v->origin[0];
|
||||
deltay = enemy->v->origin[1] - actor->v->origin[1];
|
||||
VectorSubtract(enemy->v->origin, actor->v->origin, d);
|
||||
deltax = DotProduct(d, axis[0]);
|
||||
deltay = DotProduct(d, axis[1]);
|
||||
if (deltax>10)
|
||||
d[1]= 0;
|
||||
else if (deltax<-10)
|
||||
|
@ -388,7 +527,7 @@ void World_NewChaseDir (world_t *world, wedict_t *actor, wedict_t *enemy, float
|
|||
else
|
||||
tdir = d[2] == 90 ? 135 : 215;
|
||||
|
||||
if (tdir != turnaround && World_StepDirection(world, actor, tdir, dist))
|
||||
if (tdir != turnaround && World_StepDirection(world, actor, tdir, dist, axis))
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -401,32 +540,32 @@ void World_NewChaseDir (world_t *world, wedict_t *actor, wedict_t *enemy, float
|
|||
}
|
||||
|
||||
if (d[1]!=DI_NODIR && d[1]!=turnaround
|
||||
&& World_StepDirection(world, actor, d[1], dist))
|
||||
&& World_StepDirection(world, actor, d[1], dist, axis))
|
||||
return;
|
||||
|
||||
if (d[2]!=DI_NODIR && d[2]!=turnaround
|
||||
&& World_StepDirection(world, actor, d[2], dist))
|
||||
&& World_StepDirection(world, actor, d[2], dist, axis))
|
||||
return;
|
||||
|
||||
/* there is no direct path to the player, so pick another direction */
|
||||
|
||||
if (olddir!=DI_NODIR && World_StepDirection(world, actor, olddir, dist))
|
||||
if (olddir!=DI_NODIR && World_StepDirection(world, actor, olddir, dist, axis))
|
||||
return;
|
||||
|
||||
if (rand()&1) /*randomly determine direction of search*/
|
||||
{
|
||||
for (tdir=0 ; tdir<=315 ; tdir += 45)
|
||||
if (tdir!=turnaround && World_StepDirection(world, actor, tdir, dist) )
|
||||
if (tdir!=turnaround && World_StepDirection(world, actor, tdir, dist, axis) )
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (tdir=315 ; tdir >=0 ; tdir -= 45)
|
||||
if (tdir!=turnaround && World_StepDirection(world, actor, tdir, dist) )
|
||||
if (tdir!=turnaround && World_StepDirection(world, actor, tdir, dist, axis) )
|
||||
return;
|
||||
}
|
||||
|
||||
if (turnaround != DI_NODIR && World_StepDirection(world, actor, turnaround, dist) )
|
||||
if (turnaround != DI_NODIR && World_StepDirection(world, actor, turnaround, dist, axis) )
|
||||
return;
|
||||
|
||||
actor->v->ideal_yaw = olddir; // can't move
|
||||
|
@ -434,7 +573,7 @@ void World_NewChaseDir (world_t *world, wedict_t *actor, wedict_t *enemy, float
|
|||
// if a bridge was pulled out from underneath a monster, it may not have
|
||||
// a valid standing position at all
|
||||
|
||||
if (!World_CheckBottom (world, actor))
|
||||
if (!World_CheckBottom (world, actor, axis[2]))
|
||||
World_FixCheckBottom (actor);
|
||||
|
||||
}
|
||||
|
@ -468,6 +607,7 @@ SV_MoveToGoal
|
|||
qboolean World_MoveToGoal (world_t *world, wedict_t *ent, float dist)
|
||||
{
|
||||
wedict_t *goal;
|
||||
vec3_t axis[3];
|
||||
|
||||
ent = (wedict_t*)PROG_TO_EDICT(world->progs, *world->g.self);
|
||||
goal = (wedict_t*)PROG_TO_EDICT(world->progs, ent->v->goalentity);
|
||||
|
@ -481,11 +621,14 @@ qboolean World_MoveToGoal (world_t *world, wedict_t *ent, float dist)
|
|||
if ( PROG_TO_EDICT(world->progs, ent->v->enemy) != (edict_t*)world->edicts && World_CloseEnough (ent, goal, dist) )
|
||||
return true;
|
||||
|
||||
|
||||
World_GetEntGravityAxis(ent, axis);
|
||||
|
||||
// bump around...
|
||||
if ( (rand()&3)==1 ||
|
||||
!World_StepDirection (world, ent, ent->v->ideal_yaw, dist))
|
||||
!World_StepDirection (world, ent, ent->v->ideal_yaw, dist, axis))
|
||||
{
|
||||
World_NewChaseDir (world, ent, goal, dist);
|
||||
World_NewChaseDir (world, ent, goal, dist, axis);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -70,6 +70,33 @@ void ClientReliableWrite_Begin(client_t *cl, int c, int maxsize)
|
|||
ClientReliableWrite_Byte(cl, c);
|
||||
}
|
||||
|
||||
client_t *ClientReliableWrite_BeginSplit(client_t *cl, int svc, int svclen)
|
||||
{
|
||||
if (cl->controller)
|
||||
{ //this is a slave client.
|
||||
//find the right number and send.
|
||||
client_t *sp;
|
||||
int pnum = 0;
|
||||
for (sp = cl->controller; sp; sp = sp->controlled)
|
||||
{
|
||||
if (sp == cl)
|
||||
break;
|
||||
pnum++;
|
||||
}
|
||||
sp = cl->controller;
|
||||
|
||||
ClientReliableWrite_Begin (sp, svcfte_choosesplitclient, 2+svclen);
|
||||
ClientReliableWrite_Byte (sp, pnum);
|
||||
ClientReliableWrite_Byte (sp, svc);
|
||||
return sp;
|
||||
}
|
||||
else
|
||||
{
|
||||
ClientReliableWrite_Begin (cl, svc, svclen);
|
||||
return cl;
|
||||
}
|
||||
}
|
||||
|
||||
void ClientReliable_FinishWrite(client_t *cl)
|
||||
{
|
||||
if (cl->num_backbuf)
|
||||
|
|
|
@ -63,6 +63,7 @@ cvar_t sv_stepheight = CVARAFD("pm_stepheight", "", "sv_stepheight", CVAR_SERV
|
|||
cvar_t pm_ktjump = CVARF("pm_ktjump", "", CVAR_SERVERINFO);
|
||||
cvar_t pm_bunnyspeedcap = CVARFD("pm_bunnyspeedcap", "", CVAR_SERVERINFO, "0 or 1, ish. If the player is traveling faster than this speed while turning, their velocity will be gracefully reduced to match their current maxspeed. You can still rocket-jump to gain high velocity, but turning will reduce your speed back to the max. This can be used to disable bunny hopping.");
|
||||
cvar_t pm_watersinkspeed = CVARFD("pm_watersinkspeed", "", CVAR_SERVERINFO, "This is the speed that players will sink at while inactive in water. Empty means 60.");
|
||||
cvar_t pm_flyfriction = CVARFD("pm_flyfriction", "", CVAR_SERVERINFO, "Amount of friction that applies in fly or 6dof mode. Empty means 4.");
|
||||
cvar_t pm_slidefix = CVARF("pm_slidefix", "", CVAR_SERVERINFO);
|
||||
cvar_t pm_slidyslopes = CVARF("pm_slidyslopes", "", CVAR_SERVERINFO);
|
||||
cvar_t pm_airstep = CVARF("pm_airstep", "", CVAR_SERVERINFO);
|
||||
|
@ -281,13 +282,17 @@ static void WPhys_PortalTransform(world_t *w, wedict_t *ent, wedict_t *portal, v
|
|||
VectorCopy(w->g.v_right, move);
|
||||
// VectorCopy(w->g.v_up, ent->xv->gravitydir);
|
||||
|
||||
//monsters get their gravitydir set if it isn't already, to ensure that they still work (angle issues).
|
||||
if ((int)ent->v->flags & FL_MONSTER)
|
||||
if (!ent->xv->gravitydir[0] && !ent->xv->gravitydir[1] && !ent->xv->gravitydir[2])
|
||||
ent->xv->gravitydir[2] = -1;
|
||||
|
||||
|
||||
//transform the angles too
|
||||
VectorCopy(org, G_VECTOR(OFS_PARM0));
|
||||
if (ent->entnum <= svs.allocated_client_slots)
|
||||
{
|
||||
VectorCopy(ent->v->v_angle, ent->v->angles);
|
||||
ent->v->fixangle = true;
|
||||
}
|
||||
else
|
||||
ent->v->angles[0] *= -1;
|
||||
|
@ -295,8 +300,36 @@ static void WPhys_PortalTransform(world_t *w, wedict_t *ent, wedict_t *portal, v
|
|||
AngleVectors(ent->v->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, ent->v->angles);
|
||||
if (ent->entnum <= svs.allocated_client_slots)
|
||||
if (ent->entnum > 0 && ent->entnum <= svs.allocated_client_slots)
|
||||
{
|
||||
client_t *cl = &svs.clients[ent->entnum-1];
|
||||
int i;
|
||||
vec3_t delta;
|
||||
ent->v->angles[0] *= -1;
|
||||
if (!cl->lockangles && (cl->fteprotocolextensions2 & PEXT2_SETANGLEDELTA))
|
||||
{
|
||||
cl = ClientReliableWrite_BeginSplit(cl, svcfte_setangledelta, 7);
|
||||
|
||||
VectorSubtract(ent->v->angles, ent->v->v_angle, delta);
|
||||
delta[2] = anglemod(delta[2]);
|
||||
if (delta[2] > 90 && delta[2] < 270)
|
||||
{
|
||||
delta[2] -= 180;
|
||||
delta[1] -= 180;
|
||||
delta[0] -= -180;
|
||||
}
|
||||
for (i=0 ; i < 3 ; i++)
|
||||
ClientReliableWrite_Angle16 (cl, delta[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
cl = ClientReliableWrite_BeginSplit (cl, svc_setangle, 7);
|
||||
for (i=0 ; i < 3 ; i++)
|
||||
ClientReliableWrite_Angle (cl, ent->v->angles[i]);
|
||||
}
|
||||
VectorCopy(ent->v->angles, ent->v->v_angle);
|
||||
ent->v->angles[0] *= -1;
|
||||
}
|
||||
|
||||
/*
|
||||
avelocity is horribly dependant upon eular angles. trying to treat it as a matrix is folly.
|
||||
|
@ -2491,5 +2524,6 @@ void SV_SetMoveVars(void)
|
|||
movevars.entgravity = 1.0;
|
||||
movevars.stepheight = *sv_stepheight.string?sv_stepheight.value:PM_DEFAULTSTEPHEIGHT;
|
||||
movevars.watersinkspeed = *pm_watersinkspeed.string?pm_watersinkspeed.value:60;
|
||||
movevars.flyfriction = *pm_flyfriction.string?pm_flyfriction.value:60;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1307,7 +1307,7 @@ void SV_WriteClientdataToMessage (client_t *client, sizebuf_t *msg)
|
|||
if (client->chokecount)
|
||||
{
|
||||
MSG_WriteByte (msg, svc_chokecount);
|
||||
MSG_WriteByte (msg, client->chokecount);
|
||||
MSG_WriteByte (msg, bound(0, client->chokecount, 255));
|
||||
client->chokecount = 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -90,6 +90,7 @@ extern cvar_t pm_slidyslopes;
|
|||
extern cvar_t pm_airstep;
|
||||
extern cvar_t pm_walljump;
|
||||
extern cvar_t pm_watersinkspeed;
|
||||
extern cvar_t pm_flyfriction;
|
||||
cvar_t sv_pushplayers = SCVAR("sv_pushplayers", "0");
|
||||
|
||||
//yes, realip cvars need to be fully initialised or realip will be disabled
|
||||
|
@ -938,6 +939,9 @@ void SV_SendClientPrespawnInfo(client_t *client)
|
|||
ClientReliableWrite_Byte (client, track);
|
||||
if (ISNQCLIENT(client))
|
||||
ClientReliableWrite_Byte (client, track);
|
||||
|
||||
if (!track && *sv.h2miditrack)
|
||||
SV_StuffcmdToClient(client, va("cd loop \"%s\"\n"));
|
||||
}
|
||||
else if (client->prespawn_idx == 2)
|
||||
{
|
||||
|
@ -4140,6 +4144,34 @@ void Cmd_Give_f (void)
|
|||
}
|
||||
}
|
||||
|
||||
void Cmd_Spiderpig_f(void)
|
||||
{
|
||||
if (!SV_MayCheat())
|
||||
{
|
||||
SV_TPrintToClient(host_client, PRINT_HIGH, "Cheats are not allowed on this server\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!svprogfuncs)
|
||||
return;
|
||||
|
||||
SV_LogPlayer(host_client, "spiderpig cheat");
|
||||
if (sv_player->v->movetype != MOVETYPE_WALLWALK)
|
||||
{
|
||||
sv_player->v->movetype = MOVETYPE_WALLWALK;
|
||||
sv_player->v->solid = SOLID_TRIGGER;
|
||||
SV_ClientTPrintf (host_client, PRINT_HIGH, "Spider-Pig, Spider-Pig, does whatever a Spider-Pig does...\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
sv_player->v->movetype = MOVETYPE_WALK;
|
||||
if (sv_player->v->health > 0)
|
||||
sv_player->v->solid = SOLID_SLIDEBOX;
|
||||
else
|
||||
sv_player->v->solid = SOLID_NOT;
|
||||
SV_ClientTPrintf (host_client, PRINT_HIGH, "Spider-Pig, Spider-Pig!\n");
|
||||
}
|
||||
}
|
||||
void Cmd_Noclip_f (void)
|
||||
{
|
||||
if (!SV_MayCheat())
|
||||
|
@ -4169,6 +4201,34 @@ void Cmd_Noclip_f (void)
|
|||
}
|
||||
}
|
||||
|
||||
void Cmd_6dof_f (void)
|
||||
{
|
||||
if (!SV_MayCheat())
|
||||
{
|
||||
SV_TPrintToClient(host_client, PRINT_HIGH, "Cheats are not allowed on this server\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!svprogfuncs)
|
||||
return;
|
||||
|
||||
SV_LogPlayer(host_client, "6dof cheat");
|
||||
if (sv_player->v->movetype != MOVETYPE_6DOF)
|
||||
{
|
||||
sv_player->v->movetype = MOVETYPE_6DOF;
|
||||
SV_ClientTPrintf (host_client, PRINT_HIGH, "6dof mode ON\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
sv_player->v->movetype = MOVETYPE_WALK;
|
||||
if (sv_player->v->health > 0)
|
||||
sv_player->v->solid = SOLID_SLIDEBOX;
|
||||
else
|
||||
sv_player->v->solid = SOLID_NOT;
|
||||
SV_ClientTPrintf (host_client, PRINT_HIGH, "6dof mode OFF\n");
|
||||
}
|
||||
}
|
||||
|
||||
void Cmd_Fly_f (void)
|
||||
{
|
||||
if (!SV_MayCheat())
|
||||
|
@ -5066,6 +5126,8 @@ ucmd_t ucmds[] =
|
|||
{"god", Cmd_God_f},
|
||||
{"give", Cmd_Give_f},
|
||||
{"noclip", Cmd_Noclip_f},
|
||||
{"spiderpig", Cmd_Spiderpig_f},
|
||||
{"6dof", Cmd_6dof_f},
|
||||
{"fly", Cmd_Fly_f},
|
||||
{"notarget", Cmd_Notarget_f},
|
||||
{"setpos", Cmd_SetPos_f},
|
||||
|
@ -5635,6 +5697,9 @@ int SV_PMTypeForClient (client_t *cl)
|
|||
|
||||
case MOVETYPE_WALLWALK:
|
||||
return PM_WALLWALK;
|
||||
|
||||
case MOVETYPE_6DOF:
|
||||
return PM_6DOF;
|
||||
|
||||
case MOVETYPE_FLY:
|
||||
return PM_FLY;
|
||||
|
@ -5785,6 +5850,7 @@ void SV_RunCmd (usercmd_t *ucmd, qboolean recurse)
|
|||
movevars.walljump = (pm_walljump.value);
|
||||
movevars.slidyslopes = (pm_slidyslopes.value!=0);
|
||||
movevars.watersinkspeed = *pm_watersinkspeed.string?pm_watersinkspeed.value:60;
|
||||
movevars.flyfriction = *pm_flyfriction.string?pm_flyfriction.value:4;
|
||||
|
||||
for (i=0 ; i<3 ; i++)
|
||||
{
|
||||
|
@ -5977,6 +6043,7 @@ void SV_RunCmd (usercmd_t *ucmd, qboolean recurse)
|
|||
movevars.walljump = (pm_walljump.value);
|
||||
movevars.slidyslopes = (pm_slidyslopes.value!=0);
|
||||
movevars.watersinkspeed = *pm_watersinkspeed.string?pm_watersinkspeed.value:60;
|
||||
movevars.flyfriction = *pm_flyfriction.string?pm_flyfriction.value:4;
|
||||
|
||||
if (sv_player->xv->hasted)
|
||||
movevars.maxspeed*=sv_player->xv->hasted;
|
||||
|
@ -6015,6 +6082,19 @@ if (sv_player->v->health > 0 && before && !after )
|
|||
#endif
|
||||
pmove.world = NULL;
|
||||
|
||||
{
|
||||
vec3_t delta;
|
||||
VectorSubtract (pmove.angles, sv_player->v->v_angle, delta);
|
||||
|
||||
if (delta[0] || delta[1] || delta[2])
|
||||
{
|
||||
client_t *cl = ClientReliableWrite_BeginSplit(host_client, svcfte_setangledelta, 7);
|
||||
for (i=0 ; i < 3 ; i++)
|
||||
ClientReliableWrite_Angle16 (cl, delta[i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
host_client->jump_held = pmove.jump_held;
|
||||
if (progstype != PROG_QW) //this is just annoying.
|
||||
{
|
||||
|
@ -6049,7 +6129,7 @@ if (sv_player->v->health > 0 && before && !after )
|
|||
VectorCopy (pmove.origin, sv_player->v->origin);
|
||||
VectorCopy (pmove.angles, sv_player->v->v_angle);
|
||||
|
||||
VectorCopy (pmove.gravitydir, sv_player->xv->gravitydir);
|
||||
// VectorCopy (pmove.gravitydir, sv_player->xv->gravitydir);
|
||||
if (pmove.gravitydir[0] || pmove.gravitydir[1] || (pmove.gravitydir[2] && pmove.gravitydir[2] != -1))
|
||||
{
|
||||
if (!sv_player->v->fixangle)
|
||||
|
|
|
@ -1043,7 +1043,7 @@ static trace_t World_ClipMoveToEntity (world_t *w, wedict_t *ent, vec3_t eorg, v
|
|||
//solid_portal cares only about origins and as such has no mins/max
|
||||
TransformedTrace(model, 0, ent->v->frame, start, end, vec3_origin, vec3_origin, &trace, eorg, ent->v->angles, hitcontentsmask);
|
||||
if (trace.startsolid) //portals should not block traces. this prevents infinite looping
|
||||
trace.startsolid = trace.allsolid = false;
|
||||
trace.startsolid = false;
|
||||
hitmodel = false;
|
||||
}
|
||||
else if (ent->v->solid != SOLID_BSP)
|
||||
|
@ -1368,7 +1368,7 @@ void WorldQ2_ClipMoveToEntities (world_t *w, moveclip_t *clip )
|
|||
//a portal is flush with a world surface behind it.
|
||||
//this causes problems. namely that we can't pass through the portal plane if the bsp behind it prevents out origin from getting through.
|
||||
//so if the trace was clipped and ended infront of the portal, continue the trace to the edges of the portal cutout instead.
|
||||
void World_PortalCSG(wedict_t *portal, float trminz, float trmaxz, vec3_t start, vec3_t end, trace_t *trace)
|
||||
void World_PortalCSG(wedict_t *portal, float *trmin, float *trmax, vec3_t start, vec3_t end, trace_t *trace)
|
||||
{
|
||||
vec4_t planes[6]; //far, near, right, left, up, down
|
||||
int plane;
|
||||
|
@ -1391,19 +1391,26 @@ void World_PortalCSG(wedict_t *portal, float trminz, float trmaxz, vec3_t start,
|
|||
VectorNegate(planes[3], planes[2]);
|
||||
VectorNegate(planes[5], planes[4]);
|
||||
|
||||
trminz = fabs(trminz);
|
||||
portalradius/=2;
|
||||
planes[0][3] = DotProduct(portal->v->origin, planes[0]) - trminz-16;
|
||||
planes[0][3] = DotProduct(portal->v->origin, planes[0]) - (1.0/32);
|
||||
planes[1][3] = DotProduct(portal->v->origin, planes[1]) - (1.0/32); //an epsilon beyond the portal
|
||||
planes[2][3] = DotProduct(portal->v->origin, planes[2]) - portalradius+trminz;
|
||||
planes[3][3] = DotProduct(portal->v->origin, planes[3]) - portalradius+trminz;
|
||||
planes[4][3] = DotProduct(portal->v->origin, planes[4]) - portalradius+trminz;
|
||||
planes[5][3] = DotProduct(portal->v->origin, planes[5]) - portalradius+trminz;
|
||||
planes[2][3] = DotProduct(portal->v->origin, planes[2]) - portalradius;
|
||||
planes[3][3] = DotProduct(portal->v->origin, planes[3]) - portalradius;
|
||||
planes[4][3] = DotProduct(portal->v->origin, planes[4]) - portalradius;
|
||||
planes[5][3] = DotProduct(portal->v->origin, planes[5]) - portalradius;
|
||||
|
||||
//if we're actually inside the csg region
|
||||
for (plane = 0; plane < 6; plane++)
|
||||
{
|
||||
vec3_t nearest;
|
||||
float d = DotProduct(worldpos, planes[plane]);
|
||||
int k;
|
||||
for (k = 0; k < 3; k++)
|
||||
nearest[k] = (planes[plane][k]>=0)?trmax[k]:trmin[k];
|
||||
if (!plane) //front plane gets further away with side
|
||||
planes[plane][3] -= DotProduct(nearest, planes[plane]);
|
||||
else if (plane>1) //side planes get nearer with size
|
||||
planes[plane][3] += DotProduct(nearest, planes[plane]);
|
||||
if (d - planes[plane][3] >= 0)
|
||||
continue; //endpos is inside
|
||||
else
|
||||
|
@ -1418,7 +1425,7 @@ void World_PortalCSG(wedict_t *portal, float trminz, float trmaxz, vec3_t start,
|
|||
float ds = DotProduct(start, planes[plane]) - planes[plane][3];
|
||||
float de = DotProduct(end, planes[plane]) - planes[plane][3];
|
||||
float frac;
|
||||
if (ds > 0 && de < 0)
|
||||
if (ds >= 0 && de < 0)
|
||||
{
|
||||
frac = (ds-(1.0/32)) / (ds - de);
|
||||
if (frac < trace->fraction)
|
||||
|
@ -1504,7 +1511,7 @@ static void World_ClipToEverything (world_t *w, moveclip_t *clip)
|
|||
if (touch->v->solid == SOLID_PORTAL)
|
||||
{
|
||||
//make sure we don't hit the world if we're inside the portal
|
||||
World_PortalCSG(touch, clip->mins[2], clip->maxs[2], clip->start, clip->end, &clip->trace);
|
||||
World_PortalCSG(touch, clip->mins, clip->maxs, clip->start, clip->end, &clip->trace);
|
||||
}
|
||||
|
||||
if ((int)touch->v->flags & FL_MONSTER)
|
||||
|
@ -1611,7 +1618,7 @@ static void World_ClipToLinks (world_t *w, areanode_t *node, moveclip_t *clip)
|
|||
if (touch->v->solid == SOLID_PORTAL)
|
||||
{
|
||||
//make sure we don't hit the world if we're inside the portal
|
||||
World_PortalCSG(touch, clip->mins[2], clip->maxs[2], clip->start, clip->end, &clip->trace);
|
||||
World_PortalCSG(touch, clip->mins, clip->maxs, clip->start, clip->end, &clip->trace);
|
||||
}
|
||||
|
||||
if ((int)touch->v->flags & FL_MONSTER)
|
||||
|
|
Loading…
Reference in a new issue