void drawRiffleCam() { vec3_t angles, forward, viewpos; trajectory_t riffleTrajectory; riffleTrajectory.trType = TR_GRAVITY; riffleTrajectory.trTime = eth.cg_time; VectorCopy(eth.cg_refdef.vieworg, riffleTrajectory.trBase); VectorCopy(riffleTrajectory.trBase, viewpos); VectorCopy(eth.cg_snap->ps.viewangles, angles); AngleVectors(angles, forward, NULL,NULL); viewpos[2] += eth.cg_snap->ps.viewheight; VectorMA(viewpos, 32, forward, viewpos); VectorScale(forward, 2000, forward); VectorCopy(forward, riffleTrajectory.trDelta); SnapVector(riffleTrajectory.trDelta); // Calculate riffle impact int timeOffset = 0; trace_t riffleTrace; vec3_t riffleImpact; VectorCopy(riffleTrajectory.trBase, riffleImpact); #define TIME_STEPP 50 int maxTime = 4000; // int usedelta = 0; int totalFly = 0; while (timeOffset < maxTime) { vec3_t nextPos; timeOffset += TIME_STEPP; totalFly += TIME_STEPP; // trace with std delta until hit smtg // when hit calc delta every step // if (usedelta > 0) // eth_BG_EvaluateTrajectoryDelta(&riffleTrajectory, eth.cg_time+timeOffset, riffleTrajectory.trDelta, qfalse, 0); eth.BG_EvaluateTrajectory(&riffleTrajectory, eth.cg_time + timeOffset, nextPos, qfalse, 0); eth.CG_Trace(&riffleTrace, riffleImpact, 0, 0, nextPos, eth.cg_snap->ps.clientNum, MASK_MISSILESHOT); // check for hit if (riffleTrace.startsolid || riffleTrace.fraction != 1) { // When a nade flies for over 750ms and hits something, it'll explode if (totalFly > 750) break; int hitTime = eth.cg_time + totalFly - TIME_STEPP + TIME_STEPP * riffleTrace.fraction; eth_BG_EvaluateTrajectoryDelta(&riffleTrajectory, hitTime, riffleTrajectory.trDelta, qfalse, 0); // calculate reflect angle (forward axis) float dot = DotProduct(riffleTrajectory.trDelta, riffleTrace.plane.normal); VectorMA(riffleTrajectory.trDelta, -2*dot, riffleTrace.plane.normal, riffleTrajectory.trDelta); // VectorMA(riffleTrajectory.trDelta, 0.85f, vec3_origin, riffleTrajectory.trDelta); // FIXME: inaccurate /* if (usedelta > 0) VectorScale(riffleTrajectory.trDelta, 0.2f, riffleTrajectory.trDelta); else VectorScale(riffleTrajectory.trDelta, 0.5f, riffleTrajectory.trDelta); usedelta = 1; */ VectorScale(riffleTrajectory.trDelta, 0.35, riffleTrajectory.trDelta); // calc new max time and reset trTime maxTime = maxTime - timeOffset; timeOffset = 0; riffleTrajectory.trTime = eth.cg_time; // new base origins VectorCopy(riffleTrace.endpos, riffleTrajectory.trBase); } else { VectorCopy(nextPos, riffleImpact); #define POINT_SIZE 2 int x, y; if (worldToScreen(nextPos, &x, &y)) { if (isVisible(nextPos)) drawFillRect(x - (POINT_SIZE / 2), y - (POINT_SIZE / 2), POINT_SIZE, POINT_SIZE, colorYellow); else drawFillRect(x - (POINT_SIZE / 2), y - (POINT_SIZE / 2), POINT_SIZE, POINT_SIZE, colorRed); } } } // Set the view refdef_t camRefDef = eth.cg_refdef; // fov camRefDef.fov_x = 90; camRefDef.fov_y = 90; // origin VectorCopy(riffleImpact, camRefDef.vieworg); camRefDef.vieworg[ROLL] += 500.0f; // Up the cam // angle vec3_t camAngle; VectorCopy(eth.cg_refdefViewAngles, camAngle); camAngle[PITCH] = 90; // Look down AnglesToAxis(camAngle, camRefDef.viewaxis); // Draw the rifflecam drawSpyCam(10, 10, 250, 250, &camRefDef, eth.enemyMortarShader, eth.friendMortarShader, qtrue); // Draw impact time char str[128]; sprintf(str, "^2%.1f ^3s", (float)totalFly / 1000.0f); drawText(10 + (250 - sizeTextWidth(0.19f, str, ð.fontVariable)) / 2, 10 + 250 - 15, 0.19f, str, colorWhite, qfalse, qtrue, ð.fontVariable); }