mirror of
https://github.com/nzp-team/fteqw.git
synced 2024-11-10 14:42:13 +00:00
Rotating BSP fixes, hexen2 fixes, and a few extra bugs...
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@2134 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
43872108b9
commit
b5b74f2529
21 changed files with 203 additions and 69 deletions
|
@ -1742,7 +1742,8 @@ void CL_LinkPacketEntities (void)
|
|||
}
|
||||
|
||||
VectorCopy(angles, ent->angles);
|
||||
angles[0]*=-1;
|
||||
if (model && model->type == mod_alias)
|
||||
angles[0]*=-1; //carmack screwed up when he added alias models - they pitch the wrong way.
|
||||
AngleVectors(angles, ent->axis[0], ent->axis[1], ent->axis[2]);
|
||||
VectorInverse(ent->axis[1]);
|
||||
|
||||
|
|
|
@ -544,6 +544,9 @@ void PF_CL_drawgetimagesize (progfuncs_t *prinst, struct globalvars_s *pr_global
|
|||
|
||||
float *ret = G_VECTOR(OFS_RETURN);
|
||||
|
||||
if (!p)
|
||||
p = Draw_SafeCachePic(va("%s.tga", picname));
|
||||
|
||||
if (p)
|
||||
{
|
||||
ret[0] = p->width;
|
||||
|
|
|
@ -686,7 +686,7 @@ cvar_t *Cvar_SetCore (cvar_t *var, const char *value, qboolean force)
|
|||
}
|
||||
#endif
|
||||
|
||||
latch = var->string;
|
||||
latch = var->string;//save off the old value (so cvar_set(var, var->string) works)
|
||||
|
||||
var->string = (char*)Z_Malloc (Q_strlen(value)+1);
|
||||
Q_strcpy (var->string, value);
|
||||
|
@ -920,13 +920,19 @@ void Cvar_RegisterVariable (cvar_t *variable)
|
|||
cvar_t *Cvar_Get(const char *name, const char *defaultvalue, int flags, const char *group)
|
||||
{
|
||||
cvar_t *var;
|
||||
int old;
|
||||
var = Cvar_FindVar(name);
|
||||
|
||||
if (var)
|
||||
{
|
||||
//allow this to change all < cvar_latch values.
|
||||
//this allows q2 dlls to apply different flags to a cvar without destroying our important ones (like cheat).
|
||||
old = var->flags;
|
||||
var->flags = (var->flags & ~(CVAR_NOSET)) | (flags & (CVAR_NOSET|CVAR_SERVERINFO|CVAR_USERINFO|CVAR_ARCHIVE));
|
||||
if (old != var->flags)
|
||||
{
|
||||
Cvar_Set(var, var->string);
|
||||
}
|
||||
return var;
|
||||
}
|
||||
|
||||
|
|
|
@ -1765,24 +1765,26 @@ vfsfile_t *FS_OpenTCP(char *name)
|
|||
{
|
||||
tcpfile_t *newf;
|
||||
int sock;
|
||||
netadr_t adr;
|
||||
if (!NET_StringToAdr(name, &adr))
|
||||
netadr_t adr = {0};
|
||||
if (NET_StringToAdr(name, &adr))
|
||||
{
|
||||
sock = TCP_OpenStream(adr);
|
||||
if (sock == INVALID_SOCKET)
|
||||
return NULL;
|
||||
|
||||
newf = Z_Malloc(sizeof(*newf));
|
||||
newf->sock = sock;
|
||||
newf->funcs.Close = VFSTCP_Close;
|
||||
newf->funcs.Flush = NULL;
|
||||
newf->funcs.GetLen = VFSTCP_GetLen;
|
||||
newf->funcs.ReadBytes = VFSTCP_ReadBytes;
|
||||
newf->funcs.Seek = VFSTCP_Seek;
|
||||
newf->funcs.Tell = VFSTCP_Tell;
|
||||
newf->funcs.WriteBytes = VFSTCP_WriteBytes;
|
||||
newf->funcs.seekingisabadplan = true;
|
||||
|
||||
return &newf->funcs;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
|
||||
sock = TCP_OpenStream(adr);
|
||||
if (sock == INVALID_SOCKET)
|
||||
return NULL;
|
||||
|
||||
newf = Z_Malloc(sizeof(*newf));
|
||||
newf->sock = sock;
|
||||
newf->funcs.Close = VFSTCP_Close;
|
||||
newf->funcs.Flush = NULL;
|
||||
newf->funcs.GetLen = VFSTCP_GetLen;
|
||||
newf->funcs.ReadBytes = VFSTCP_ReadBytes;
|
||||
newf->funcs.Seek = VFSTCP_Seek;
|
||||
newf->funcs.Tell = VFSTCP_Tell;
|
||||
newf->funcs.WriteBytes = VFSTCP_WriteBytes;
|
||||
newf->funcs.seekingisabadplan = true;
|
||||
|
||||
return &newf->funcs;
|
||||
}
|
||||
|
|
|
@ -199,9 +199,9 @@ qboolean PM_TransformedHullCheck (model_t *model, vec3_t start, vec3_t end, trac
|
|||
|
||||
if (trace->fraction != 1.0)
|
||||
{
|
||||
a[0] = angles[0];
|
||||
a[1] = angles[1];
|
||||
a[2] = angles[2];
|
||||
a[0] = -angles[0];
|
||||
a[1] = -angles[1];
|
||||
a[2] = -angles[2];
|
||||
AngleVectors (a, forward, right, up);
|
||||
|
||||
VectorCopy (trace->plane.normal, temp);
|
||||
|
|
|
@ -3064,6 +3064,8 @@ SOURCE=..\gl\gl_bloom.c
|
|||
|
||||
!ELSEIF "$(CFG)" == "ftequake - Win32 Debug Dedicated Server"
|
||||
|
||||
# PROP Exclude_From_Build 1
|
||||
|
||||
!ELSEIF "$(CFG)" == "ftequake - Win32 Release Dedicated Server"
|
||||
|
||||
# PROP Exclude_From_Build 1
|
||||
|
|
|
@ -2194,7 +2194,7 @@ qboolean GLMod_LoadClipnodes (lump_t *l)
|
|||
hull->planes = loadmodel->planes;
|
||||
hull->clip_mins[0] = -48;
|
||||
hull->clip_mins[1] = -48;
|
||||
hull->clip_mins[2] = -50;
|
||||
hull->clip_mins[2] = -50 - 24;
|
||||
hull->clip_maxs[0] = 48;
|
||||
hull->clip_maxs[1] = 48;
|
||||
hull->clip_maxs[2] = 50;
|
||||
|
|
|
@ -1731,12 +1731,25 @@ void PPL_BaseBModelTextures(entity_t *e)
|
|||
currentmodel = model = e->model;
|
||||
s = model->surfaces+model->firstmodelsurface;
|
||||
|
||||
GL_TexEnv(GL_MODULATE);
|
||||
if (currententity->drawflags & DRF_TRANSLUCENT)
|
||||
currententity->shaderRGBAf[3]=0.5;
|
||||
if ((currententity->drawflags & MLS_ABSLIGHT) == MLS_ABSLIGHT)
|
||||
{
|
||||
currententity->shaderRGBAf[0] =
|
||||
currententity->shaderRGBAf[1] =
|
||||
currententity->shaderRGBAf[2] = currententity->abslight/255.0f;
|
||||
}
|
||||
|
||||
if (currententity->shaderRGBAf[3]<1)
|
||||
{
|
||||
GL_TexEnv(GL_MODULATE);
|
||||
qglEnable(GL_BLEND);
|
||||
}
|
||||
else
|
||||
{
|
||||
GL_TexEnv(GL_REPLACE);
|
||||
qglDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
qglColor4fv(currententity->shaderRGBAf);
|
||||
|
||||
|
|
|
@ -711,6 +711,13 @@ float *GLRecursiveLightPoint3C (mnode_t *node, vec3_t start, vec3_t end)
|
|||
float scale;
|
||||
int maps;
|
||||
|
||||
if (!cl.worldmodel->lightdata)
|
||||
{
|
||||
l[0]=255;l[1]=255;l[2]=255;
|
||||
l[3]=0;l[4]=1;l[5]=1;
|
||||
return l;
|
||||
}
|
||||
|
||||
if (cl.worldmodel->fromgame == fg_quake2)
|
||||
{
|
||||
if (node->contents != -1)
|
||||
|
|
|
@ -259,6 +259,18 @@ void GLR_AddStain(vec3_t org, float red, float green, float blue, float radius)
|
|||
parms[1] = org[0] - pe->origin[0];
|
||||
parms[2] = org[1] - pe->origin[1];
|
||||
parms[3] = org[2] - pe->origin[2];
|
||||
|
||||
if (pe->angles[0] || pe->angles[1] || pe->angles[2])
|
||||
{
|
||||
vec3_t f, r, u, temp;
|
||||
AngleVectors(pe->angles, f, r, u);
|
||||
VectorCopy((parms+1), temp);
|
||||
parms[1] = DotProduct(temp, f);
|
||||
parms[2] = -DotProduct(temp, r);
|
||||
parms[3] = DotProduct(temp, u);
|
||||
}
|
||||
|
||||
|
||||
pe->model->funcs.StainNode(pe->model->nodes+pe->model->hulls[0].firstclipnode, parms);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2674,9 +2674,13 @@ QCC_def_t *QCC_PR_ParseFunctionCall (QCC_def_t *func) //warning, the func could
|
|||
e = QCC_PR_Statement(pr_opcodes+OP_CONV_FTOI, e, NULL, NULL);
|
||||
else if (p->type == ev_float && e->type->type == ev_integer) //convert float -> int... is this a constant?
|
||||
e = QCC_PR_Statement(pr_opcodes+OP_CONV_ITOF, e, NULL, NULL);
|
||||
else if (p->type == ev_function && e->type->type == ev_integer && e->constant && !((int*)qcc_pr_globals)[e->ofs])
|
||||
{ //you're allowed to use int 0 to pass a null function pointer
|
||||
//this is basically because __NULL__ is defined as ~0 (int 0)
|
||||
}
|
||||
else if (p->type != ev_variant) //can cast to variant whatever happens
|
||||
{
|
||||
if (flag_laxcasts)
|
||||
if (flag_laxcasts || (p->type == ev_function && e->type->type == ev_function))
|
||||
{
|
||||
QCC_PR_ParseWarning(WARN_LAXCAST, "type mismatch on parm %i - (%s should be %s)", arg+1, TypeName(e->type), TypeName(p));
|
||||
QCC_PR_ParsePrintDef(WARN_LAXCAST, func);
|
||||
|
|
|
@ -162,18 +162,34 @@ void QCC_FindBestInclude(char *newfile, char *currentfile, char *rootpath)
|
|||
{
|
||||
char fullname[10248];
|
||||
char *stripfrom;
|
||||
int doubledots;
|
||||
|
||||
char *end = fullname;
|
||||
|
||||
if (!*newfile)
|
||||
return;
|
||||
|
||||
doubledots = 0;
|
||||
while(!strncmp(newfile, "../", 3) || !strncmp(newfile, "..\\", 3))
|
||||
{
|
||||
newfile+=3;
|
||||
doubledots++;
|
||||
}
|
||||
|
||||
currentfile += strlen(rootpath); //could this be bad?
|
||||
|
||||
for(stripfrom = currentfile+strlen(currentfile)-1; stripfrom>currentfile; stripfrom--)
|
||||
{
|
||||
if (*stripfrom == '/' || *stripfrom == '\\')
|
||||
break;
|
||||
{
|
||||
if (doubledots>0)
|
||||
doubledots--;
|
||||
else
|
||||
{
|
||||
stripfrom++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
strcpy(end, rootpath); end = end+strlen(end);
|
||||
if (*fullname && end[-1] != '/')
|
||||
|
|
|
@ -114,6 +114,7 @@ func_t pr_SV_ShouldPause;
|
|||
|
||||
func_t SV_PlayerPhysicsQC; //DP's DP_SV_PLAYERPHYSICS extension
|
||||
func_t EndFrameQC;
|
||||
func_t pr_ClassChangeWeapon;
|
||||
|
||||
qboolean pr_items2;
|
||||
|
||||
|
@ -540,6 +541,7 @@ void PR_LoadGlabalStruct(void)
|
|||
|
||||
pr_SV_PausedTic = PR_FindFunction(svprogfuncs, "SV_PausedTic", PR_ANY);
|
||||
pr_SV_ShouldPause = PR_FindFunction(svprogfuncs, "SV_ShouldPause", PR_ANY);
|
||||
pr_ClassChangeWeapon = PR_FindFunction(svprogfuncs, "ClassChangeWeapon", PR_ANY);
|
||||
|
||||
if (pr_no_playerphysics.value)
|
||||
SV_PlayerPhysicsQC = 0;
|
||||
|
@ -1262,7 +1264,7 @@ void Q_InitProgs(void)
|
|||
if (f)
|
||||
{
|
||||
pr_globals = PR_globals(svprogfuncs, PR_CURRENT);
|
||||
G_INT(OFS_PARM0) = (int)PR_SetString(svprogfuncs, as);
|
||||
G_INT(OFS_PARM0) = (int)PR_SetString(svprogfuncs, sv_addon[i2].string);
|
||||
PR_ExecuteProgram (svprogfuncs, f);
|
||||
}
|
||||
else
|
||||
|
@ -1328,7 +1330,7 @@ qboolean PR_ShouldTogglePause(client_t *initiator, qboolean newpaused)
|
|||
globalvars_t *pr_globals;
|
||||
|
||||
if (!svprogfuncs || !pr_SV_ShouldPause)
|
||||
return false;
|
||||
return true;
|
||||
|
||||
pr_globals = PR_globals(svprogfuncs, PR_CURRENT);
|
||||
|
||||
|
@ -7478,6 +7480,32 @@ void PF_advanceweaponframe (progfuncs_t *prinst, struct globalvars_s *pr_globals
|
|||
G_FLOAT(OFS_RETURN) = state;
|
||||
}
|
||||
|
||||
void PR_SetPlayerClass(client_t *cl, int classnum, qboolean fromqc)
|
||||
{
|
||||
char temp[16];
|
||||
if (classnum < 1)
|
||||
return; //reject it (it would crash the (standard hexen2) mod)
|
||||
if (classnum > 5)
|
||||
return;
|
||||
if (cl->playerclass != classnum)
|
||||
{
|
||||
cl->edict->v->playerclass = classnum;
|
||||
cl->playerclass = classnum;
|
||||
|
||||
sprintf(temp,"%i",(int)classnum);
|
||||
Info_SetValueForKey (cl->userinfo, "cl_playerclass", temp, sizeof(cl->userinfo));
|
||||
|
||||
if (!fromqc)
|
||||
{
|
||||
cl->sendinfo = true;
|
||||
if (cl->state == cs_spawned && pr_ClassChangeWeapon)
|
||||
{
|
||||
pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, cl->edict);
|
||||
PR_ExecuteProgram (svprogfuncs, pr_ClassChangeWeapon);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PF_setclass (progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
|
|
|
@ -129,7 +129,7 @@ typedef enum {
|
|||
// ClientCommand and ServerCommand parameter access
|
||||
|
||||
G_ARGV, // ( int n, char *buffer, int bufferLength );
|
||||
|
||||
//10
|
||||
G_FS_FOPEN_FILE, // ( const char *qpath, fileHandle_t *file, fsMode_t mode );
|
||||
G_FS_READ, // ( void *buffer, int len, fileHandle_t f );
|
||||
G_FS_WRITE, // ( const void *buffer, int len, fileHandle_t f );
|
||||
|
@ -162,7 +162,7 @@ typedef enum {
|
|||
// All confgstrings are cleared at each level start.
|
||||
|
||||
G_GET_CONFIGSTRING, // ( int num, char *buffer, int bufferSize );
|
||||
|
||||
//20
|
||||
G_GET_USERINFO, // ( int num, char *buffer, int bufferSize );
|
||||
// userinfo strings are maintained by the server system, so they
|
||||
// are persistant across level loads, while all other game visible
|
||||
|
@ -189,7 +189,7 @@ typedef enum {
|
|||
G_ADJUST_AREA_PORTAL_STATE, // ( gentity_t *ent, qboolean open );
|
||||
|
||||
G_AREAS_CONNECTED, // ( int area1, int area2 );
|
||||
|
||||
//30
|
||||
G_LINKENTITY, // ( gentity_t *ent );
|
||||
// an entity will never be sent to a client or used for collision
|
||||
// if it is not passed to linkentity. If the size, position, or
|
||||
|
@ -219,6 +219,7 @@ typedef enum {
|
|||
|
||||
G_FS_GETFILELIST,
|
||||
G_DEBUG_POLYGON_CREATE,
|
||||
//40
|
||||
G_DEBUG_POLYGON_DELETE,
|
||||
G_REAL_TIME,
|
||||
G_SNAPVECTOR,
|
||||
|
|
|
@ -119,7 +119,10 @@ void Chat_GetTag(char *filename, float tag, char **text, char **condition, char
|
|||
}
|
||||
}
|
||||
}
|
||||
Sys_Error("Tag %f not found in file %s", tag, host_client->chat.filename);
|
||||
*text = va("Chat Tag %f not found in file %s", tag, host_client->chat.filename);
|
||||
*condition = "";
|
||||
*options = "";
|
||||
return;
|
||||
}
|
||||
|
||||
chatvar_t *SV_ChatFindVariable(char *name)
|
||||
|
|
|
@ -2546,8 +2546,6 @@ void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignore
|
|||
state->modelindex = SV_ModelIndex(modname);
|
||||
}
|
||||
}
|
||||
if (/*progstype == PROG_H2 &&*/ ent->v->solid == SOLID_BSP)
|
||||
state->angles[0]*=-1;
|
||||
|
||||
if (state->effects & EF_FULLBRIGHT)
|
||||
{
|
||||
|
|
|
@ -1022,6 +1022,7 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
|
|||
|
||||
if (progstype == PROG_H2)
|
||||
{
|
||||
cvar_t *cv;
|
||||
if (coop.value)
|
||||
{
|
||||
eval = PR_FindGlobal(svprogfuncs, "coop", 0);
|
||||
|
@ -1032,11 +1033,13 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
|
|||
eval = PR_FindGlobal(svprogfuncs, "deathmatch", 0);
|
||||
if (eval) eval->_float = deathmatch.value;
|
||||
}
|
||||
cv = Cvar_Get("randomclass", "0", CVAR_LATCH, "Hexen2");
|
||||
eval = PR_FindGlobal(svprogfuncs, "randomclass", 0);
|
||||
if (eval) eval->_float = Cvar_Get("randomclass", "1", CVAR_LATCH, "Hexen2 rules")->value;
|
||||
if (eval && cv) eval->_float = cv->value;
|
||||
|
||||
cv = Cvar_Get("cl_playerclass", "1", CVAR_USERINFO|CVAR_ARCHIVE, "Hexen2");
|
||||
eval = PR_FindGlobal(svprogfuncs, "cl_playerclass", 0);
|
||||
if (eval) eval->_float = 1;
|
||||
if (eval && cv) eval->_float = cv->value;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1078,6 +1081,8 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
|
|||
spawnflagmask |= SPAWNFLAG_NOT_H2HARD;
|
||||
else
|
||||
spawnflagmask |= SPAWNFLAG_NOT_H2MEDIUM;
|
||||
|
||||
//don't filter based on player class. we're lame and don't have any real concept of player classes.
|
||||
}
|
||||
else if (!deathmatch.value) //decide if we are to inhibit single player game ents instead
|
||||
{
|
||||
|
|
|
@ -3721,6 +3721,12 @@ void SV_ExtractFromUserinfo (client_t *cl)
|
|||
else
|
||||
cl->drate = 0; //0 disables the downloading check
|
||||
|
||||
val = Info_ValueForKey (cl->userinfo, "cl_playerclass");
|
||||
if (val)
|
||||
{
|
||||
PR_SetPlayerClass(cl, atoi(val), false);
|
||||
}
|
||||
|
||||
// msg command
|
||||
val = Info_ValueForKey (cl->userinfo, "msg");
|
||||
if (strlen(val))
|
||||
|
|
|
@ -72,7 +72,10 @@ realcheck:
|
|||
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*pm_stepheight;
|
||||
savedhull = ent->v->hull;
|
||||
ent->v->hull = 0;
|
||||
trace = SV_Move (start, vec3_origin, vec3_origin, stop, true, ent);
|
||||
ent->v->hull = savedhull;
|
||||
|
||||
if (trace.fraction == 1.0)
|
||||
return false;
|
||||
|
|
|
@ -114,13 +114,13 @@ void DestFlush(qboolean compleate)
|
|||
break;
|
||||
|
||||
case DEST_STREAM:
|
||||
if (d->cacheused)
|
||||
if (d->cacheused && !d->error)
|
||||
{
|
||||
len = send(d->socket, d->cache, d->cacheused, 0);
|
||||
if (len == 0) //client died
|
||||
d->error = true;
|
||||
else if (len > 0) //error of some kind
|
||||
{
|
||||
else if (len > 0) //we put some data through
|
||||
{ //move up the buffer
|
||||
d->cacheused -= len;
|
||||
memmove(d->cache, d->cache+len, d->cacheused);
|
||||
}
|
||||
|
|
|
@ -389,26 +389,42 @@ void SV_LinkEdict (edict_t *ent, qboolean touch_triggers)
|
|||
if (ent->v->solid == SOLID_BSP &&
|
||||
(ent->v->angles[0] || ent->v->angles[1] || ent->v->angles[2]) )
|
||||
{ // expand for rotation
|
||||
|
||||
#if 1
|
||||
int i;
|
||||
float v;
|
||||
float max, min;
|
||||
//q2 method
|
||||
max = 0;
|
||||
for (i=0 ; i<3 ; i++)
|
||||
{
|
||||
v =fabs( ent->v->mins[i]);
|
||||
if (v > max)
|
||||
max = v;
|
||||
v =fabs( ent->v->maxs[i]);
|
||||
if (v > max)
|
||||
max = v;
|
||||
}
|
||||
for (i=0 ; i<3 ; i++)
|
||||
{
|
||||
ent->v->absmin[i] = ent->v->origin[i] - max;
|
||||
ent->v->absmax[i] = ent->v->origin[i] + max;
|
||||
}
|
||||
#else
|
||||
|
||||
int i;
|
||||
|
||||
vec3_t f, r, u;
|
||||
vec3_t mn, mx;
|
||||
|
||||
|
||||
//we need to link to the correct leaves
|
||||
|
||||
if (progstype == PROG_H2)
|
||||
{
|
||||
ent->v->angles[0]*=-1;
|
||||
AngleVectors(ent->v->angles, f,r,u);
|
||||
ent->v->angles[0]*=-1;
|
||||
}
|
||||
else
|
||||
AngleVectors(ent->v->angles, f,r,u);
|
||||
AngleVectors(ent->v->angles, f,r,u);
|
||||
|
||||
mn[0] = DotProduct(ent->v->mins, f);
|
||||
mn[1] = -DotProduct(ent->v->mins, r);
|
||||
mn[2] = DotProduct(ent->v->mins, u);
|
||||
|
||||
|
||||
mx[0] = DotProduct(ent->v->maxs, f);
|
||||
mx[1] = -DotProduct(ent->v->maxs, r);
|
||||
mx[2] = DotProduct(ent->v->maxs, u);
|
||||
|
@ -425,6 +441,7 @@ void SV_LinkEdict (edict_t *ent, qboolean touch_triggers)
|
|||
ent->v->absmax[i] = ent->v->origin[i]+mn[i]+0.1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -959,22 +976,29 @@ qboolean TransformedTrace (struct model_s *model, int hulloverride, int frame, v
|
|||
if (rotated)
|
||||
{
|
||||
// FIXME: figure out how to do this with existing angles
|
||||
// VectorNegate (angles, a);
|
||||
a[0] = -angles[0];
|
||||
a[1] = -angles[1];
|
||||
a[2] = -angles[2];
|
||||
AngleVectors (a, forward, right, up);
|
||||
|
||||
VectorCopy (trace->plane.normal, temp);
|
||||
trace->plane.normal[0] = DotProduct (temp, forward);
|
||||
trace->plane.normal[1] = -DotProduct (temp, right);
|
||||
trace->plane.normal[2] = DotProduct (temp, up);
|
||||
if (trace->fraction != 1)
|
||||
{
|
||||
VectorNegate (angles, a);
|
||||
AngleVectors (a, forward, right, up);
|
||||
|
||||
trace->endpos[0] = start[0] + trace->fraction * (end[0] - start[0]);
|
||||
trace->endpos[1] = start[1] + trace->fraction * (end[1] - start[1]);
|
||||
trace->endpos[2] = start[2] + trace->fraction * (end[2] - start[2]);
|
||||
VectorCopy (trace->plane.normal, temp);
|
||||
trace->plane.normal[0] = DotProduct (temp, forward);
|
||||
trace->plane.normal[1] = -DotProduct (temp, right);
|
||||
trace->plane.normal[2] = DotProduct (temp, up);
|
||||
|
||||
|
||||
trace->endpos[0] = start[0] + trace->fraction * (end[0] - start[0]);
|
||||
trace->endpos[1] = start[1] + trace->fraction * (end[1] - start[1]);
|
||||
trace->endpos[2] = start[2] + trace->fraction * (end[2] - start[2]);
|
||||
}
|
||||
else
|
||||
{
|
||||
VectorCopy (end, trace->endpos);
|
||||
}
|
||||
}
|
||||
VectorAdd (trace->endpos, origin, trace->endpos);
|
||||
else
|
||||
VectorAdd (trace->endpos, origin, trace->endpos);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1115,15 +1139,15 @@ trace_t SV_ClipMoveToEntity (edict_t *ent, vec3_t start, vec3_t mins, vec3_t max
|
|||
}
|
||||
|
||||
// trace a line through the apropriate clipping hull
|
||||
if (progstype == PROG_H2 && ent->v->solid == SOLID_BSP)
|
||||
if (ent->v->solid != SOLID_BSP)
|
||||
{
|
||||
ent->v->angles[0]*=-1;
|
||||
TransformedTrace(model, 0, ent->v->frame, start, end, mins, maxs, &trace, ent->v->origin, ent->v->angles);
|
||||
ent->v->angles[0]*=-1; //carmack made bsp models rotate wrongly.
|
||||
TransformedTrace(model, hullnum, ent->v->frame, start, end, mins, maxs, &trace, ent->v->origin, ent->v->angles);
|
||||
ent->v->angles[0]*=-1;
|
||||
}
|
||||
else
|
||||
{
|
||||
TransformedTrace(model, 0, ent->v->frame, start, end, mins, maxs, &trace, ent->v->origin, ent->v->angles);
|
||||
TransformedTrace(model, hullnum, ent->v->frame, start, end, mins, maxs, &trace, ent->v->origin, ent->v->angles);
|
||||
}
|
||||
|
||||
// fix trace up by the offset
|
||||
|
@ -1146,7 +1170,7 @@ trace_t SV_ClipMoveToEntity (edict_t *ent, vec3_t start, vec3_t mins, vec3_t max
|
|||
if (model && model->funcs.Trace)
|
||||
{
|
||||
//do the second trace
|
||||
TransformedTrace(model, 0, ent->v->frame, start, end, mins, maxs, &trace, ent->v->origin, ent->v->angles);
|
||||
TransformedTrace(model, hullnum, ent->v->frame, start, end, mins, maxs, &trace, ent->v->origin, ent->v->angles);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue