cvar_t sv_maxvelocity = {"sv_maxvelocity","2000"};
cvar_t sv_nostep = {"sv_nostep","0"};
-static vec3_t vec_origin = {0.0, 0.0, 0.0};
-
#define MOVE_EPSILON 0.01
void SV_Physics_Toss (edict_t *ent);
float thinktime;
thinktime = ent->v.nextthink;
- if (thinktime <= 0 || thinktime > sv.time + host_frametime)
+ if (thinktime <= 0 || thinktime > sv.time + sv.frametime)
return true;
if (thinktime < sv.time)
pr_global_struct->time = thinktime;
pr_global_struct->self = EDICT_TO_PROG(ent);
pr_global_struct->other = EDICT_TO_PROG(sv.edicts);
- PR_ExecuteProgram (ent->v.think);
+ PR_ExecuteProgram (ent->v.think, "NULL think function");
return !ent->free;
}
{
pr_global_struct->self = EDICT_TO_PROG(e1);
pr_global_struct->other = EDICT_TO_PROG(e2);
- PR_ExecuteProgram (e1->v.touch);
+ PR_ExecuteProgram (e1->v.touch, "");
}
if (e2->v.touch && e2->v.solid != SOLID_NOT)
{
pr_global_struct->self = EDICT_TO_PROG(e2);
pr_global_struct->other = EDICT_TO_PROG(e1);
- PR_ExecuteProgram (e2->v.touch);
+ PR_ExecuteProgram (e2->v.touch, "");
}
pr_global_struct->self = old_self;
If steptrace is not NULL, the trace of any vertical wall hit will be stored
============
*/
-#define MAX_CLIP_PLANES 5
+// LordHavoc: increased from 5 to 20, to partially fix angled corner sticking
+// (example - start.bsp hall to e1m4, leading to the pool there are two
+// angled corners, which you could get stuck on, now they are just a one
+// frame hiccup)
+#define MAX_CLIP_PLANES 20
int SV_FlyMove (edict_t *ent, float time, trace_t *steptrace)
{
int bumpcount, numbumps;
if (trace.allsolid)
{ // entity is trapped in another solid
- VectorCopy (vec3_origin, ent->v.velocity);
+ VectorClear(ent->v.velocity);
return 3;
}
break; // moved the entire distance
if (!trace.ent)
- Sys_Error ("SV_FlyMove: !trace.ent");
+ Host_Error ("SV_FlyMove: !trace.ent");
if (trace.plane.normal[2] > 0.7)
{
// cliped to another plane
if (numplanes >= MAX_CLIP_PLANES)
{ // this shouldn't really happen
- VectorCopy (vec3_origin, ent->v.velocity);
+ VectorClear(ent->v.velocity);
return 3;
}
if (numplanes != 2)
{
// Con_Printf ("clip velocity, numplanes == %i\n",numplanes);
- VectorCopy (vec3_origin, ent->v.velocity);
+ VectorClear(ent->v.velocity);
return 7;
}
CrossProduct (planes[0], planes[1], dir);
//
if (DotProduct (ent->v.velocity, primal_velocity) <= 0)
{
- VectorCopy (vec3_origin, ent->v.velocity);
+ VectorClear(ent->v.velocity);
return blocked;
}
}
eval_t *val;
val = GETEDICTFIELDVALUE(ent, eval_gravity);
- if (val && val->_float)
+ if (val!=0 && val->_float)
ent_gravity = val->_float;
else
ent_gravity = 1.0;
- ent->v.velocity[2] -= ent_gravity * sv_gravity.value * host_frametime;
+ ent->v.velocity[2] -= ent_gravity * sv_gravity.value * sv.frametime;
}
void SV_PushMove (edict_t *pusher, float movetime)
{
int i, e;
- edict_t *check, *block;
+ edict_t *check;
vec3_t mins, maxs, move;
vec3_t entorig, pushorig;
int num_moved;
vec3_t moved_from[MAX_EDICTS];
float savesolid;
+ switch ((int) pusher->v.solid)
+ {
+ // LordHavoc: valid pusher types
+ case SOLID_BSP:
+ case SOLID_BBOX:
+ case SOLID_SLIDEBOX:
+ case SOLID_CORPSE: // LordHavoc: this would be weird...
+ break;
+ // LordHavoc: no collisions
+ case SOLID_NOT:
+ case SOLID_TRIGGER:
+ VectorMA (pusher->v.origin, movetime, pusher->v.velocity, pusher->v.origin);
+ pusher->v.ltime += movetime;
+ SV_LinkEdict (pusher, false);
+ return;
+ default:
+ Host_Error("SV_PushMove: unrecognized solid type %f\n", pusher->v.solid);
+ }
if (!pusher->v.velocity[0] && !pusher->v.velocity[1] && !pusher->v.velocity[2])
{
pusher->v.ltime += movetime;
pusher->v.solid = savesolid; // was SOLID_BSP
// if it is still inside the pusher, block
- if (block = SV_TestEntityPosition (check))
+ if (SV_TestEntityPosition (check))
{ // fail the move
if (check->v.mins[0] == check->v.maxs[0])
continue;
SV_LinkEdict (pusher, false);
pusher->v.ltime -= movetime;
- // if the pusher has a "blocked" function, call it
- // otherwise, just stay in place until the obstacle is gone
+ // if the pusher has a "blocked" function, call it, otherwise just stay in place until the obstacle is gone
if (pusher->v.blocked)
{
pr_global_struct->self = EDICT_TO_PROG(pusher);
pr_global_struct->other = EDICT_TO_PROG(check);
- PR_ExecuteProgram (pusher->v.blocked);
+ PR_ExecuteProgram (pusher->v.blocked, "");
}
// move back any entities we already moved
+ num_moved--; // LordHavoc: pop off check, because it was already restored
for (i=0 ; i<num_moved ; i++)
{
VectorCopy (moved_from[i], moved_edict[i]->v.origin);
void SV_PushRotate (edict_t *pusher, float movetime)
{
int i, e;
- edict_t *check, *block;
+ edict_t *check;
vec3_t move, a, amove;
- vec3_t entorig, pushorig;
+ vec3_t entorigin, entangles, pushorigin, pushangles;
int num_moved;
edict_t *moved_edict[MAX_EDICTS];
vec3_t moved_from[MAX_EDICTS];
+ vec3_t angled_from[MAX_EDICTS];
vec3_t org, org2;
vec3_t forward, right, up;
float savesolid;
+ switch ((int) pusher->v.solid)
+ {
+ // LordHavoc: valid pusher types
+ case SOLID_BSP:
+ case SOLID_BBOX:
+ case SOLID_SLIDEBOX:
+ case SOLID_CORPSE: // LordHavoc: this would be weird...
+ break;
+ // LordHavoc: no collisions
+ case SOLID_NOT:
+ case SOLID_TRIGGER:
+ VectorMA (pusher->v.angles, movetime, pusher->v.avelocity, pusher->v.angles);
+ pusher->v.ltime += movetime;
+ SV_LinkEdict (pusher, false);
+ return;
+ default:
+ Host_Error("SV_PushRotate: unrecognized solid type %f\n", pusher->v.solid);
+ }
if (!pusher->v.avelocity[0] && !pusher->v.avelocity[1] && !pusher->v.avelocity[2])
{
pusher->v.ltime += movetime;
for (i=0 ; i<3 ; i++)
amove[i] = pusher->v.avelocity[i] * movetime;
- VectorSubtract (vec3_origin, amove, a);
+ VectorNegate (amove, a);
AngleVectors (a, forward, right, up);
- VectorCopy (pusher->v.angles, pushorig);
+ VectorCopy (pusher->v.origin, pushorigin);
+ VectorCopy (pusher->v.angles, pushangles);
// move the pusher to it's final position
if (check->free)
continue;
if (check->v.movetype == MOVETYPE_PUSH
- || check->v.movetype == MOVETYPE_NONE
- || check->v.movetype == MOVETYPE_FOLLOW
- || check->v.movetype == MOVETYPE_NOCLIP)
+ || check->v.movetype == MOVETYPE_NONE
+ || check->v.movetype == MOVETYPE_FOLLOW
+ || check->v.movetype == MOVETYPE_NOCLIP)
continue;
// if the entity is standing on the pusher, it will definately be moved
- if ( ! ( ((int)check->v.flags & FL_ONGROUND)
- && PROG_TO_EDICT(check->v.groundentity) == pusher) )
+ if (!(((int)check->v.flags & FL_ONGROUND) && PROG_TO_EDICT(check->v.groundentity) == pusher))
{
- if ( check->v.absmin[0] >= pusher->v.absmax[0]
- || check->v.absmin[1] >= pusher->v.absmax[1]
- || check->v.absmin[2] >= pusher->v.absmax[2]
- || check->v.absmax[0] <= pusher->v.absmin[0]
- || check->v.absmax[1] <= pusher->v.absmin[1]
- || check->v.absmax[2] <= pusher->v.absmin[2] )
+ if (check->v.absmin[0] >= pusher->v.absmax[0]
+ || check->v.absmin[1] >= pusher->v.absmax[1]
+ || check->v.absmin[2] >= pusher->v.absmax[2]
+ || check->v.absmax[0] <= pusher->v.absmin[0]
+ || check->v.absmax[1] <= pusher->v.absmin[1]
+ || check->v.absmax[2] <= pusher->v.absmin[2])
continue;
// see if the ent's bbox is inside the pusher's final position
if (check->v.movetype != MOVETYPE_WALK)
check->v.flags = (int)check->v.flags & ~FL_ONGROUND;
- VectorCopy (check->v.origin, entorig);
+ VectorCopy (check->v.origin, entorigin);
VectorCopy (check->v.origin, moved_from[num_moved]);
+ VectorCopy (check->v.angles, entangles);
+ VectorCopy (check->v.angles, angled_from[num_moved]);
moved_edict[num_moved] = check;
num_moved++;
SV_PushEntity (check, move);
pusher->v.solid = savesolid; // LordHavoc: restore to correct solid type
+ VectorAdd (check->v.angles, amove, check->v.angles);
+
// if it is still inside the pusher, block
- block = SV_TestEntityPosition (check);
- if (block)
+ if (SV_TestEntityPosition (check))
{ // fail the move
if (check->v.mins[0] == check->v.maxs[0])
continue;
continue;
}
- VectorCopy (entorig, check->v.origin);
+ VectorCopy (entorigin, check->v.origin);
+ VectorCopy (entangles, check->v.angles);
SV_LinkEdict (check, true);
- VectorCopy (pushorig, pusher->v.angles);
+ VectorCopy (pushorigin, pusher->v.origin);
+ VectorCopy (pushangles, pusher->v.angles);
SV_LinkEdict (pusher, false);
pusher->v.ltime -= movetime;
- // if the pusher has a "blocked" function, call it
- // otherwise, just stay in place until the obstacle is gone
+ // if the pusher has a "blocked" function, call it, otherwise just stay in place until the obstacle is gone
if (pusher->v.blocked)
{
pr_global_struct->self = EDICT_TO_PROG(pusher);
pr_global_struct->other = EDICT_TO_PROG(check);
- PR_ExecuteProgram (pusher->v.blocked);
+ PR_ExecuteProgram (pusher->v.blocked, "");
}
// move back any entities we already moved
+ num_moved--; // LordHavoc: pop off check, because it was already restored
for (i=0 ; i<num_moved ; i++)
{
VectorCopy (moved_from[i], moved_edict[i]->v.origin);
- VectorSubtract (moved_edict[i]->v.angles, amove, moved_edict[i]->v.angles);
+ VectorCopy (angled_from[i], moved_edict[i]->v.angles);
SV_LinkEdict (moved_edict[i], false);
}
return;
}
- else
- {
- VectorAdd (check->v.angles, amove, check->v.angles);
- }
}
-
-
}
-//#endif
/*
================
oldltime = ent->v.ltime;
thinktime = ent->v.nextthink;
- if (thinktime < ent->v.ltime + host_frametime)
+ if (thinktime < ent->v.ltime + sv.frametime)
{
movetime = thinktime - ent->v.ltime;
if (movetime < 0)
movetime = 0;
}
else
- movetime = host_frametime;
+ movetime = sv.frametime;
if (movetime)
{
pr_global_struct->time = sv.time;
pr_global_struct->self = EDICT_TO_PROG(ent);
pr_global_struct->other = EDICT_TO_PROG(sv.edicts);
- PR_ExecuteProgram (ent->v.think);
+ PR_ExecuteProgram (ent->v.think, "NULL think function");
if (ent->free)
return;
}
*/
void SV_WallFriction (edict_t *ent, trace_t *trace)
{
- vec3_t forward, right, up;
+ vec3_t forward;
float d, i;
vec3_t into, side;
- AngleVectors (ent->v.v_angle, forward, right, up);
+ AngleVectors (ent->v.v_angle, forward, NULL, NULL);
d = DotProduct (trace->plane.normal, forward);
d += 0.5;
trace_t steptrace;
VectorCopy (ent->v.origin, oldorg);
- VectorCopy (vec3_origin, dir);
+ VectorClear (dir);
for (i=0 ; i<8 ; i++)
{
VectorCopy (oldorg, ent->v.origin);
}
- VectorCopy (vec3_origin, ent->v.velocity);
+ VectorClear (ent->v.velocity);
return 7; // still not moving
}
VectorCopy (ent->v.origin, oldorg);
VectorCopy (ent->v.velocity, oldvel);
- clip = SV_FlyMove (ent, host_frametime, &steptrace);
+ clip = SV_FlyMove (ent, sv.frametime, &steptrace);
if ( !(clip & 2) )
return; // move didn't block on a step
//
VectorCopy (oldorg, ent->v.origin); // back to start pos
- VectorCopy (vec3_origin, upmove);
- VectorCopy (vec3_origin, downmove);
+ VectorClear (upmove);
+ VectorClear (downmove);
upmove[2] = STEPSIZE;
- downmove[2] = -STEPSIZE + oldvel[2]*host_frametime;
+ downmove[2] = -STEPSIZE + oldvel[2]*sv.frametime;
// move up
SV_PushEntity (ent, upmove); // FIXME: don't link?
ent->v.velocity[0] = oldvel[0];
ent->v. velocity[1] = oldvel[1];
ent->v. velocity[2] = 0;
- clip = SV_FlyMove (ent, host_frametime, &steptrace);
+ clip = SV_FlyMove (ent, sv.frametime, &steptrace);
// check for stuckness, possibly due to the limited precision of floats
// in the clipping hulls
//
pr_global_struct->time = sv.time;
pr_global_struct->self = EDICT_TO_PROG(ent);
- PR_ExecuteProgram (pr_global_struct->PlayerPreThink);
+ PR_ExecuteProgram (pr_global_struct->PlayerPreThink, "QC function PlayerPreThink is missing");
//
// do a move
case MOVETYPE_FLY:
if (!SV_RunThink (ent))
return;
- SV_FlyMove (ent, host_frametime, NULL);
+ SV_CheckWater (ent);
+ SV_FlyMove (ent, sv.frametime, NULL);
break;
case MOVETYPE_NOCLIP:
if (!SV_RunThink (ent))
return;
- VectorMA (ent->v.origin, host_frametime, ent->v.velocity, ent->v.origin);
+ SV_CheckWater (ent);
+ VectorMA (ent->v.origin, sv.frametime, ent->v.velocity, ent->v.origin);
break;
default:
- Sys_Error ("SV_Physics_client: bad movetype %i", (int)ent->v.movetype);
+ Host_Error ("SV_Physics_client: bad movetype %i", (int)ent->v.movetype);
}
//
pr_global_struct->time = sv.time;
pr_global_struct->self = EDICT_TO_PROG(ent);
- PR_ExecuteProgram (pr_global_struct->PlayerPostThink);
+ PR_ExecuteProgram (pr_global_struct->PlayerPostThink, "QC function PlayerPostThink is missing");
}
//============================================================================
*/
void SV_Physics_Follow (edict_t *ent)
{
- vec3_t vf, vu, vr, angles;
+ vec3_t vf, vr, vu, angles, v;
edict_t *e;
// regular thinking
- SV_RunThink (ent);
+ if (!SV_RunThink (ent))
+ return;
// LordHavoc: implemented rotation on MOVETYPE_FOLLOW objects
e = PROG_TO_EDICT(ent->v.aiment);
- angles[0] = -e->v.angles[0];
- angles[1] = e->v.angles[1];
- angles[2] = e->v.angles[2];
- AngleVectors (angles, vf, vr, vu);
- VectorMA (e->v.origin, ent->v.view_ofs[0], vf, ent->v.origin);
- VectorMA (ent->v.origin, ent->v.view_ofs[1], vr, ent->v.origin);
- VectorMA (ent->v.origin, ent->v.view_ofs[2], vu, ent->v.origin);
+ if (e->v.angles[0] == ent->v.punchangle[0] && e->v.angles[1] == ent->v.punchangle[1] && e->v.angles[2] == ent->v.punchangle[2])
+ {
+ // quick case for no rotation
+ VectorAdd(e->v.origin, ent->v.view_ofs, ent->v.origin);
+ }
+ else
+ {
+ angles[0] = -ent->v.punchangle[0];
+ angles[1] = ent->v.punchangle[1];
+ angles[2] = ent->v.punchangle[2];
+ AngleVectors (angles, vf, vr, vu);
+ v[0] = ent->v.view_ofs[0] * vf[0] + ent->v.view_ofs[1] * vr[0] + ent->v.view_ofs[2] * vu[0];
+ v[1] = ent->v.view_ofs[0] * vf[1] + ent->v.view_ofs[1] * vr[1] + ent->v.view_ofs[2] * vu[1];
+ v[2] = ent->v.view_ofs[0] * vf[2] + ent->v.view_ofs[1] * vr[2] + ent->v.view_ofs[2] * vu[2];
+ angles[0] = -e->v.angles[0];
+ angles[1] = e->v.angles[1];
+ angles[2] = e->v.angles[2];
+ AngleVectors (angles, vf, vr, vu);
+ ent->v.origin[0] = v[0] * vf[0] + v[1] * vf[1] + v[2] * vf[2] + e->v.origin[0];
+ ent->v.origin[1] = v[0] * vr[0] + v[1] * vr[1] + v[2] * vr[2] + e->v.origin[1];
+ ent->v.origin[2] = v[0] * vu[0] + v[1] * vu[1] + v[2] * vu[2] + e->v.origin[2];
+ /*
+ ent->v.origin[0] = ent->v.view_ofs[0] * vf[0] + ent->v.view_ofs[0] * vf[1] + ent->v.view_ofs[0] * vf[2] + e->v.origin[0];
+ ent->v.origin[1] = ent->v.view_ofs[1] * vr[0] + ent->v.view_ofs[1] * vr[1] + ent->v.view_ofs[1] * vr[2] + e->v.origin[1];
+ ent->v.origin[2] = ent->v.view_ofs[2] * vu[0] + ent->v.view_ofs[2] * vu[1] + ent->v.view_ofs[2] * vu[2] + e->v.origin[2];
+ */
+ }
VectorAdd (e->v.angles, ent->v.v_angle, ent->v.angles);
// VectorAdd (PROG_TO_EDICT(ent->v.aiment)->v.origin, ent->v.v_angle, ent->v.origin);
SV_LinkEdict (ent, true);
if (!SV_RunThink (ent))
return;
- VectorMA (ent->v.angles, host_frametime, ent->v.avelocity, ent->v.angles);
- VectorMA (ent->v.origin, host_frametime, ent->v.velocity, ent->v.origin);
+ VectorMA (ent->v.angles, sv.frametime, ent->v.avelocity, ent->v.angles);
+ VectorMA (ent->v.origin, sv.frametime, ent->v.velocity, ent->v.origin);
SV_LinkEdict (ent, false);
}
SV_AddGravity (ent);
// move angles
- VectorMA (ent->v.angles, host_frametime, ent->v.avelocity, ent->v.angles);
+ VectorMA (ent->v.angles, sv.frametime, ent->v.avelocity, ent->v.angles);
// move origin
- VectorScale (ent->v.velocity, host_frametime, move);
+ VectorScale (ent->v.velocity, sv.frametime, move);
trace = SV_PushEntity (ent, move);
if (trace.fraction == 1)
return;
{
ent->v.flags = (int)ent->v.flags | FL_ONGROUND;
ent->v.groundentity = EDICT_TO_PROG(trace.ent);
- VectorCopy (vec3_origin, ent->v.velocity);
- VectorCopy (vec3_origin, ent->v.avelocity);
+ VectorClear (ent->v.velocity);
+ VectorClear (ent->v.avelocity);
}
}
SV_AddGravity (ent);
SV_CheckVelocity (ent);
- SV_FlyMove (ent, host_frametime, NULL);
+ SV_FlyMove (ent, sv.frametime, NULL);
SV_LinkEdict (ent, true);
if ( (int)ent->v.flags & FL_ONGROUND ) // just hit ground
pr_global_struct->self = EDICT_TO_PROG(sv.edicts);
pr_global_struct->other = EDICT_TO_PROG(sv.edicts);
pr_global_struct->time = sv.time;
- PR_ExecuteProgram (pr_global_struct->StartFrame);
+ PR_ExecuteProgram (pr_global_struct->StartFrame, "QC function StartFrame is missing");
//SV_CheckAllEnts ();
continue;
if (pr_global_struct->force_retouch)
- {
SV_LinkEdict (ent, true); // force retouch even for stationary
- }
if (i > 0 && i <= svs.maxclients)
+ {
SV_Physics_Client (ent, i);
- else if (ent->v.movetype == MOVETYPE_PUSH)
+ continue;
+ }
+
+ switch ((int) ent->v.movetype)
+ {
+ case MOVETYPE_PUSH:
SV_Physics_Pusher (ent);
- else if (ent->v.movetype == MOVETYPE_NONE)
+ break;
+ case MOVETYPE_NONE:
SV_Physics_None (ent);
- else if (ent->v.movetype == MOVETYPE_FOLLOW)
+ break;
+ case MOVETYPE_FOLLOW:
SV_Physics_Follow (ent);
- else if (ent->v.movetype == MOVETYPE_NOCLIP)
+ break;
+ case MOVETYPE_NOCLIP:
SV_Physics_Noclip (ent);
- else if (ent->v.movetype == MOVETYPE_STEP)
+ break;
+ case MOVETYPE_STEP:
SV_Physics_Step (ent);
+ break;
// LordHavoc: added support for MOVETYPE_WALK on normal entities! :)
- else if (ent->v.movetype == MOVETYPE_WALK)
- {
+ case MOVETYPE_WALK:
if (SV_RunThink (ent))
{
if (!SV_CheckWater (ent) && ! ((int)ent->v.flags & FL_WATERJUMP) )
SV_CheckStuck (ent);
SV_WalkMove (ent);
}
- }
- else if (ent->v.movetype == MOVETYPE_TOSS
- || ent->v.movetype == MOVETYPE_BOUNCE
- || ent->v.movetype == MOVETYPE_BOUNCEMISSILE
- || ent->v.movetype == MOVETYPE_FLY
- || ent->v.movetype == MOVETYPE_FLYMISSILE)
+ break;
+ case MOVETYPE_TOSS:
+ case MOVETYPE_BOUNCE:
+ case MOVETYPE_BOUNCEMISSILE:
+ case MOVETYPE_FLY:
+ case MOVETYPE_FLYMISSILE:
SV_Physics_Toss (ent);
- else
- Sys_Error ("SV_Physics: bad movetype %i", (int)ent->v.movetype);
+ break;
+ default:
+ Host_Error ("SV_Physics: bad movetype %i", (int)ent->v.movetype);
+ break;
+ }
}
if (pr_global_struct->force_retouch)
pr_global_struct->self = EDICT_TO_PROG(sv.edicts);
pr_global_struct->other = EDICT_TO_PROG(sv.edicts);
pr_global_struct->time = sv.time;
- PR_ExecuteProgram ((func_t)(EndFrameQC - pr_functions));
+ PR_ExecuteProgram ((func_t)(EndFrameQC - pr_functions), "");
}
- sv.time += host_frametime;
+ sv.time += sv.frametime;
}
trace_t trace;
vec3_t move;
vec3_t end;
- double save_frametime;
-
- save_frametime = host_frametime;
- host_frametime = 0.05;
memcpy(&tempent, ent, sizeof(edict_t));
tent = &tempent;
{
SV_CheckVelocity (tent);
SV_AddGravity (tent);
- VectorMA (tent->v.angles, host_frametime, tent->v.avelocity, tent->v.angles);
- VectorScale (tent->v.velocity, host_frametime, move);
+ VectorMA (tent->v.angles, 0.05, tent->v.avelocity, tent->v.angles);
+ VectorScale (tent->v.velocity, 0.05, move);
VectorAdd (tent->v.origin, move, end);
trace = SV_Move (tent->v.origin, tent->v.mins, tent->v.maxs, end, MOVE_NORMAL, tent);
VectorCopy (trace.endpos, tent->v.origin);
if (trace.ent != ignore)
break;
}
- host_frametime = save_frametime;
+ trace.fraction = 0; // not relevant
return trace;
}