void drawRiffleCam() { vec3_t muzzlePoint; // CalcMuzzlePoint { vec3_t forward, right, up; AngleVectors(eth.cg_snap->ps.viewangles, forward, right, up); VectorCopy(eth.cg_snap->ps.origin, muzzlePoint); muzzlePoint[2] += eth.cg_snap->ps.viewheight; // Default weapon muzzle offset VectorMA(muzzlePoint, 6, right, muzzlePoint); VectorMA(muzzlePoint, -4, up, muzzlePoint); SnapVector(muzzlePoint); } vec3_t forward; AngleVectors(eth.cg_snap->ps.viewangles, forward, NULL, NULL); VectorScale(forward, 2000, forward); trajectory_t riffleTrajectory; riffleTrajectory.trType = TR_GRAVITY; riffleTrajectory.trTime = eth.cg_time; VectorCopy(muzzlePoint, riffleTrajectory.trBase); 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 = 3250; int totalFly = 0; while (timeOffset < maxTime) { vec3_t nextPos; timeOffset += TIME_STEPP; totalFly += TIME_STEPP; 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; // Calculate reflect angle (forward axis) int hitTime = eth.cg_time + totalFly - TIME_STEPP + TIME_STEPP * riffleTrace.fraction; eth_BG_EvaluateTrajectoryDelta(&riffleTrajectory, hitTime, riffleTrajectory.trDelta, qfalse, 0); float dot = DotProduct(riffleTrajectory.trDelta, riffleTrace.plane.normal); VectorMA(riffleTrajectory.trDelta, -2*dot, riffleTrace.plane.normal, riffleTrajectory.trDelta); // Scale down velocity VectorScale(riffleTrajectory.trDelta, 0.35, riffleTrajectory.trDelta); // More scale down velocity on movers if ((riffleTrace.plane.normal[2] < 0.2) || (riffleTrace.entityNum != ENTITYNUM_WORLD)) VectorScale(riffleTrajectory.trDelta, 0.5, riffleTrajectory.trDelta); // Calc new max time and reset trTime maxTime -= timeOffset; timeOffset = 0; riffleTrajectory.trTime = eth.cg_time; // New base origins VectorCopy(riffleTrace.endpos, riffleTrajectory.trBase); SnapVector(riffleTrajectory.trDelta); SnapVector(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); } } }