// TODO: stay at least 8 units away from all walls in this leaf void Chase_UpdateForDrawing (void) { int i; vec3_t forward, up, right; vec3_t ideal, crosshair, temp; Math_AngleVectors(cl.viewangles, forward, right, up); // calc ideal camera location before checking for walls for (i=0 ; i<3 ; i++) ideal[i] = cl.viewent.origin[i] - forward[i]*chase_back.value + right[i]*chase_right.value; //+ up[i]*chase_up.value; ideal[2] = cl.viewent.origin[2] + chase_up.value; // make sure camera is not in or behind a wall TraceLine(r_refdef.vieworg, ideal, temp); if(Math_Length(temp) != 0) Math_VectorCopy(temp, ideal); // place camera Math_VectorCopy(ideal, r_refdef.vieworg); // find the spot the player is looking at Math_VectorMA(cl.viewent.origin, 4096, forward, temp); TraceLine(cl.viewent.origin, temp, crosshair); // calculate camera angles to look at the same spot Math_VectorSubtract(crosshair,r_refdef.vieworg,temp); Math_VectorAngles (temp, r_refdef.viewangles); if (r_refdef.viewangles[PITCH] == 90 || r_refdef.viewangles[PITCH] == -90) r_refdef.viewangles[YAW] = cl.viewangles[YAW]; }
void TridentHit(ServerEntity_t *ent) { vec3_t forward,temp,sndvec,vel; trace_t trace; Math_AngleVectors(ent->v.v_angle,forward,temp,temp); // [18/4/2012] A nice soft bounce ~hogsy vel[0] = vel[1] = 0; vel[2] = 0.5; sndvec[0] = ent->v.origin[0]+forward[0]*78; sndvec[1] = ent->v.origin[1]+forward[1]*78; sndvec[2] = ent->v.origin[2]+forward[2]*78; trace = Traceline(ent,ent->v.origin,sndvec,0); sndvec[0] = trace.endpos[0]-forward[0]*4; sndvec[1] = trace.endpos[1]-forward[1]*4; sndvec[2] = trace.endpos[2]-forward[2]*4; if(trace.fraction == 1.0f) return; if(trace.ent->v.bTakeDamage) { if(trace.ent->local.bBleed) Engine.Particle(sndvec,vel,10,"blood",30); Entity_Damage(trace.ent,ent,20,0); } else if(trace.ent) Engine.Particle(sndvec,vel,10,"smoke",30); }
void Area_SetMoveDirection(PLVector3D &angles, PLVector3D &direction) { if(angles == PLVector3D(0, -1, 0)) { direction = PLVector3D(0, 0, 1); } else if(angles == PLVector3D(0, -2, 0)) { direction = PLVector3D(0, 0, -1); } else { Math_AngleVectors(angles, &direction, nullptr, nullptr); } plClearVector3D(&angles); }
// [4/8/2012] Renamed to SideWinder_SpawnMissle ~hogsy void SideWinder_SpawnMissle(edict_t *ent,float fSpeed,float ox) { // [26/2/2012] Revised and fixed ~hogsy vec3_t vOrg; edict_t *eMissile = Entity_Spawn(); /* TODO: Spawn a flare at our position too ~hogsy */ eMissile->v.cClassname = "sidewindermissile"; eMissile->v.movetype = MOVETYPE_FLYMISSILE; eMissile->v.effects = EF_PARTICLE_SMOKE|EF_DIMLIGHT; eMissile->Physics.iSolid = SOLID_BBOX; eMissile->Physics.eIgnore = ent; eMissile->local.speed = SIDEWINDER_MAXSPEED; eMissile->local.eOwner = ent; eMissile->local.count = 0; // [4/8/2012] Change our speed depending on what contents we're within ~hogsy eMissile->local.speed = fSpeed; Math_VectorScale(Engine.Aim(ent),eMissile->local.speed,eMissile->v.velocity); Math_AngleVectors(ent->v.v_angle, // [4/8/2012] Set up our angle vectors ~hogsy eMissile->v.vForward, eMissile->local.vRight, eMissile->local.vUp); Math_VectorCopy(ent->v.v_angle,eMissile->v.angles); Entity_SetModel(eMissile,"models/sidewinder_missile.md2"); Math_VectorCopy(ent->v.origin,vOrg); vOrg[0] += eMissile->v.vForward[0]*8+eMissile->local.vRight[0]*ox; vOrg[1] += eMissile->v.vForward[1]*8+eMissile->local.vRight[1]*ox; vOrg[2] += eMissile->v.vForward[2]*24; Entity_SetSizeVector(eMissile,mv3Origin,mv3Origin); Entity_SetOrigin(eMissile,vOrg); // [4/8/2012] Time at which we'll be removed if nothing hit ~hogsy eMissile->local.fSpawnDelay = (float)(Server.dTime+8.0); eMissile->v.TouchFunction = SideWinder_MissileExplode; eMissile->v.dNextThink = Server.dTime+0.05; eMissile->v.think = SideWinder_Think; // [4/8/2012] Moved so we do this last! ~hogsy Engine.LinkEntity(eMissile,false); }
void R_SetupView (void) { Fog_SetupFrame (); //johnfitz // build the transformation matrix for the given view angles Math_VectorCopy(r_refdef.vieworg,r_origin); Math_AngleVectors(r_refdef.viewangles,vpn,vright,vup); // Current viewleaf r_oldviewleaf = r_viewleaf; r_viewleaf = Mod_PointInLeaf (r_origin, cl.worldmodel); V_SetContentsColor(r_viewleaf->contents); View_CalculateBlend(); //johnfitz -- calculate r_fovx and r_fovy here r_fovx = r_refdef.fov_x; r_fovy = r_refdef.fov_y; if (r_waterwarp.value) { int contents = Mod_PointInLeaf (r_origin, cl.worldmodel)->contents; if (contents == BSP_CONTENTS_WATER || contents == BSP_CONTENTS_SLIME || contents == BSP_CONTENTS_LAVA) { //variance is a percentage of width, where width = 2 * tan(fov / 2) otherwise the effect is too dramatic at high FOV and too subtle at low FOV. what a mess! r_fovx = atan(tan(pMath_DEG2RAD(r_refdef.fov_x) / 2) * (0.97 + sin(cl.time * 1.5) * 0.03)) * 2 / pMath_PI_DIV180; r_fovy = atan(tan(pMath_DEG2RAD(r_refdef.fov_y) / 2) * (1.03 - sin(cl.time * 1.5) * 0.03)) * 2 / pMath_PI_DIV180; } } //johnfitz R_SetFrustum(r_fovx, r_fovy); //johnfitz -- use r_fov* vars R_MarkSurfaces(); //johnfitz -- create texture chains from PVS R_CullSurfaces(); //johnfitz -- do after R_SetFrustum and R_MarkSurfaces R_UpdateWarpTextures(); //johnfitz -- do this before R_Clear //johnfitz -- cheat-protect some draw modes r_drawflat_cheatsafe = r_fullbright_cheatsafe = r_lightmap_cheatsafe = false; r_drawworld_cheatsafe = true; if (cl.maxclients == 1) { if (!r_drawworld.value) r_drawworld_cheatsafe = false; if (r_drawflat.value) r_drawflat_cheatsafe = true; else if (r_fullbright.value || !cl.worldmodel->lightdata) r_fullbright_cheatsafe = true; else if (r_lightmap.value) r_lightmap_cheatsafe = true; } //johnfitz }
void R_SetupGenericView(void) { Fog_SetupFrame(); // Build the transformation matrix for the given view angles Math_VectorCopy(r_refdef.vieworg, r_origin); Math_AngleVectors(r_refdef.viewangles, vpn, vright, vup); r_fovx = r_refdef.fov_x; r_fovy = r_refdef.fov_y; R_SetFrustum(r_fovx, r_fovy); Video_ClearBuffer(); }
void SV_WallFriction (edict_t *ent, trace_t *trace) { vec3_t forward, right, up; float d, i; vec3_t into, side; Math_AngleVectors(ent->v.v_angle, forward, right, up); d = Math_DotProduct (trace->plane.normal, forward); d += 0.5; if (d >= 0) return; // Cut the tangential velocity i = Math_DotProduct (trace->plane.normal, ent->v.velocity); Math_VectorScale (trace->plane.normal, i, into); Math_VectorSubtract (ent->v.velocity, into, side); ent->v.velocity[0] = side[0] * (1 + d); ent->v.velocity[1] = side[1] * (1 + d); }
void Physics_WallFriction(ServerEntity_t *eEntity, trace_t *trLine) { MathVector3f_t forward, right, up; float d, i; MathVector3f_t into, side; Math_AngleVectors(eEntity->v.v_angle, forward, right, up); d = Math_DotProduct(trLine->plane.normal, forward); d += 0.5; if (d >= 0) return; // Cut the tangential velocity. i = Math_DotProduct(trLine->plane.normal, eEntity->v.velocity); Math_VectorScale(trLine->plane.normal, i, into); Math_VectorSubtract(eEntity->v.velocity, into, side); eEntity->v.velocity[0] = side[0] * (1 + d); eEntity->v.velocity[1] = side[1] * (1 + d); }
// [18/5/2013] TODO: Merge with SV_PushMove ~hogsy static void Server_PushRotate(edict_t *pusher,float movetime) { int i,e,num_moved,slaves_moved; edict_t *check,*block,*moved_edict[MAX_EDICTS],*ground,*slave,*master; vec3_t move,a,amove,entorig,pushorig,moved_from[MAX_EDICTS],org,org2,forward,right,up; bool bMoveIt; for (i = 0; i < 3; i++) amove[i] = pusher->v.avelocity[i] * movetime; Math_VectorNegate(amove,a); Math_AngleVectors(a,forward,right,up); Math_VectorCopy(pusher->v.angles,pushorig); // move the pusher to it's final position Math_VectorAdd(pusher->v.angles,amove,pusher->v.angles); pusher->v.ltime += movetime; SV_LinkEdict (pusher, false); slaves_moved = 0; master = pusher; while(master->v.aiment) { slave = PROG_TO_EDICT(master->v.aiment); slaves_moved++; Math_VectorCopy (slave->v.angles, moved_from[MAX_EDICTS - slaves_moved]); moved_edict[MAX_EDICTS - slaves_moved] = slave; if (slave->v.movedir[PITCH]) slave->v.angles[PITCH] = master->v.angles[PITCH]; else slave->v.angles[PITCH] += slave->v.avelocity[PITCH] * movetime; if (slave->v.movedir[YAW]) slave->v.angles[YAW] = master->v.angles[YAW]; else slave->v.angles[YAW] += slave->v.avelocity[YAW] * movetime; if (slave->v.movedir[ROLL]) slave->v.angles[ROLL] = master->v.angles[ROLL]; else slave->v.angles[ROLL] += slave->v.avelocity[ROLL] * movetime; slave->v.ltime = master->v.ltime; SV_LinkEdict(slave,false); master = slave; } // see if any solid entities are inside the final position num_moved = 0; check = NEXT_EDICT(sv.edicts); for (e = 1; e < sv.num_edicts; e++, check = NEXT_EDICT(check)) { if (check->free) continue; if (check->v.movetype == MOVETYPE_PUSH || check->v.movetype == MOVETYPE_NONE || check->v.movetype == MOVETYPE_NOCLIP) continue; // if the entity is standing on the pusher, it will definitely be moved bMoveIt = false; ground = check->v.groundentity; if(check->v.flags & FL_ONGROUND) { if (ground == pusher) bMoveIt = true; else { for (i = 0; i < slaves_moved; i++) { if (ground == moved_edict[MAX_EDICTS - i - 1]) { bMoveIt = true; break; } } } } if(!bMoveIt) { 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]) { for (i = 0; i < slaves_moved; i++) { slave = moved_edict[MAX_EDICTS-i-1]; if( check->v.absmin[0] >= slave->v.absmax[0] || check->v.absmin[1] >= slave->v.absmax[1] || check->v.absmin[2] >= slave->v.absmax[2] || check->v.absmax[0] <= slave->v.absmin[0] || check->v.absmax[1] <= slave->v.absmin[1] || check->v.absmax[2] <= slave->v.absmin[2] ) continue; } if (i == slaves_moved) continue; } // See if the ent's bbox is inside the pusher's final position if(!SV_TestEntityPosition(check)) continue; } // remove the onground flag for non-players if(check->v.movetype != MOVETYPE_WALK) check->v.flags = check->v.flags & ~FL_ONGROUND; Math_VectorCopy(check->v.origin,entorig); Math_VectorCopy(check->v.origin,moved_from[num_moved]); moved_edict[num_moved] = check; num_moved++; // calculate destination position Math_VectorSubtract(check->v.origin,pusher->v.origin,org); org2[0] = Math_DotProduct(org,forward); org2[1] = -Math_DotProduct(org,right); org2[2] = Math_DotProduct(org,up); Math_VectorSubtract (org2,org,move); // try moving the contacted entity pusher->Physics.iSolid = SOLID_NOT; SV_PushEntity (check, move); //@@TODO: do we ever want to do anybody's angles? maybe just yaw??? if(check->monster.iType != 1) { #if 0 vec3_t vYaw; vYaw[YAW] = Math_AngleMod(pusher->v.angles[YAW]+check->v.angles[YAW]); Con_Printf("%i %i\n",(int)check->v.angles[YAW],(int)vYaw[YAW]); //check->v.angles[YAW] = vYaw[YAW]; //check->v.angles[YAW] = Math_AngleMod(vYaw[YAW]); #endif // move back any entities we already moved for (i = 0; i < num_moved; i++) { Math_VectorAdd(moved_edict[i]->v.angles, amove, moved_edict[i]->v.angles); moved_edict[i]->v.angles[YAW] += amove[YAW]/2.0f; SV_LinkEdict(moved_edict[i],false); } } pusher->Physics.iSolid = SOLID_BSP; // If it is still inside the pusher, block block = SV_TestEntityPosition (check); if (block) { // fail the move if (check->v.mins[0] == check->v.maxs[0]) continue; if (check->Physics.iSolid == SOLID_NOT || check->Physics.iSolid == SOLID_TRIGGER) { // corpse check->v.mins[0] = check->v.mins[1] = 0; Math_VectorCopy(check->v.mins,check->v.maxs); continue; } Math_VectorCopy(entorig,check->v.origin); SV_LinkEdict(check,true); Math_VectorCopy(pushorig,pusher->v.angles); SV_LinkEdict(pusher,false); pusher->v.ltime -= movetime; for(i = 0; i < slaves_moved; i++) { slave = moved_edict[MAX_EDICTS - i - 1]; Math_VectorCopy(moved_from[MAX_EDICTS - i - 1], slave->v.angles); SV_LinkEdict(slave,false); slave->v.ltime -= movetime; } // if the pusher has a "blocked" function, call it // otherwise, just stay in place until the obstacle is gone if (pusher->v.blocked) pusher->v.blocked(pusher,check); // move back any entities we already moved for (i = 0; i < num_moved; i++) { Math_VectorCopy (moved_from[i], moved_edict[i]->v.origin); //@@TODO:: see above // if (!((int)moved_edict[i]->v.flags & (FL_CLIENT | FL_MONSTER))) Math_VectorSubtract (moved_edict[i]->v.angles, amove, moved_edict[i]->v.angles); moved_edict[i]->v.angles[YAW] -= amove[YAW]; SV_LinkEdict(moved_edict[i],false); } return; } } }
void R_RenderView (void) { double time1 = 0, time2; if (r_norefresh.value) return; if (!cl.worldmodel) Sys_Error ("R_RenderView: NULL worldmodel"); if(r_speeds.value) { glFinish (); time1 = System_DoubleTime(); //johnfitz -- rendering statistics rs_brushpolys = rs_aliaspolys = rs_skypolys = rs_particles = rs_fogpolys = rs_megatexels = rs_dynamiclightmaps = rs_aliaspasses = rs_skypasses = rs_brushpasses = 0; } R_SetupView (); //johnfitz -- this does everything that should be done once per frame Video_ClearBuffer(); //johnfitz -- stereo rendering -- full of hacky goodness if (r_stereo.value) { float eyesep = Math_Clamp(-8.0f, r_stereo.value, 8.0f), fdepth = Math_Clamp(32.0f, r_stereodepth.value, 1024.0f); Math_AngleVectors(r_refdef.viewangles, vpn, vright, vup); // Render left eye (red) glColorMask(true,false,false,true); Math_VectorMA (r_refdef.vieworg, -0.5f * eyesep, vright, r_refdef.vieworg); frustum_skew = 0.5f*eyesep*NEARCLIP/fdepth; srand((int) (cl.time * 1000)); //sync random stuff between eyes R_RenderScene(); // Render right eye (cyan) glClear (GL_DEPTH_BUFFER_BIT); glColorMask(0, 1, 1, 1); Math_VectorMA (r_refdef.vieworg, 1.0f * eyesep, vright, r_refdef.vieworg); frustum_skew = -frustum_skew; srand((int) (cl.time * 1000)); //sync random stuff between eyes R_RenderScene(); // Restore glColorMask(true,true,true,true); Math_VectorMA (r_refdef.vieworg, -0.5f * eyesep, vright, r_refdef.vieworg); frustum_skew = 0.0f; } else R_RenderScene(); //johnfitz //johnfitz -- modified r_speeds output time2 = System_DoubleTime(); if(r_speeds.value == 2) Con_Printf( "%3i ms %4i/%4i wpoly %4i/%4i epoly %3i lmap %4i/%4i sky %1.1f mtex\n", (int)((time2-time1)*1000), rs_brushpolys, rs_brushpasses, rs_aliaspolys, rs_aliaspasses, rs_dynamiclightmaps, rs_skypolys, rs_skypasses, TexMgr_FrameUsage ()); else if(r_speeds.value) Con_Printf ("%3i ms %4i wpoly %4i epoly %3i lmap\n", (int)((time2-time1)*1000), rs_brushpolys, rs_aliaspolys, rs_dynamiclightmaps); //johnfitz }
void Sky_ProcessEntities(void) { int i,k,mark; unsigned int j; float dot; bool bRotated; ClientEntity_t *e; msurface_t *s; glpoly_t *p; MathVector3f_t vTemp, forward, right, up; if (!r_drawentities.value) return; for (i=0 ; i<cl_numvisedicts ; i++) { e = cl_visedicts[i]; if (e->model->type != MODEL_TYPE_LEVEL) continue; if(R_CullModelForEntity(e)) continue; if(e->alpha == ENTALPHA_ZERO) continue; Math_VectorSubtract (r_refdef.vieworg, e->origin, modelorg); if(e->angles[0] || e->angles[1] || e->angles[2]) { bRotated = true; Math_AngleVectors(e->angles, forward, right, up); Math_VectorCopy(modelorg,vTemp); modelorg[0] = Math_DotProduct(vTemp,forward); modelorg[1] = -Math_DotProduct(vTemp,right); modelorg[2] = Math_DotProduct(vTemp,up); } else bRotated = false; s = &e->model->surfaces[e->model->firstmodelsurface]; for (j=0 ; j<e->model->nummodelsurfaces ; j++, s++) { if (s->flags & SURF_DRAWSKY) { dot = Math_DotProduct (modelorg, s->plane->normal) - s->plane->dist; if (((s->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || (!(s->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) { //copy the polygon and translate manually, since Sky_ProcessPoly needs it to be in world space mark = Hunk_LowMark(); p = (glpoly_t*)Hunk_Alloc (sizeof(*s->polys)); //FIXME: don't allocate for each poly p->numverts = s->polys->numverts; for (k=0; k<p->numverts; k++) { if(bRotated) { p->verts[k][0] = e->origin[0] + s->polys->verts[k][0] * forward[0] - s->polys->verts[k][1] * right[0] + s->polys->verts[k][2] * up[0]; p->verts[k][1] = e->origin[1] + s->polys->verts[k][0] * forward[1] - s->polys->verts[k][1] * right[1] + s->polys->verts[k][2] * up[1]; p->verts[k][2] = e->origin[2] + s->polys->verts[k][0] * forward[2] - s->polys->verts[k][1] * right[2] + s->polys->verts[k][2] * up[2]; } else Math_VectorAdd(s->polys->verts[k], e->origin, p->verts[k]); } Sky_ProcessPoly (p); Hunk_FreeToLowMark (mark); } } } } }
void Entity_MakeVectors(ServerEntity_t *eEntity) { Math_AngleVectors(eEntity->v.v_angle, eEntity->local.vForward, eEntity->local.vRight, eEntity->local.vUp); }
void Area_ClimbTouch(ServerEntity_t *area, ServerEntity_t *other) { PLVector3D ladder_velocity, vPlayerVec; if ((other->local.ladderjump > Server.time) || (other->v.waterlevel > 1) || (other->v.flags & FL_WATERJUMP)) { return; } PLVector3D forward, right, up; Math_AngleVectors(other->v.angles, &forward, &right, &up); PLVector3D playervec = forward; playervec *= 250; if (other->v.button[2]) { playervec = other->v.velocity; } // ignore 8 units of the top edge if (other->v.origin.z + other->v.mins.z + 8 >= area->v.absmax.z) { if (!(other->v.flags & FL_ONGROUND)) { other->v.flags = other->v.flags + FL_ONGROUND; } return; } // null out gravity in PreThink other->local.laddertime = Server.time + 0.1; other->local.zerogtime = Server.time + 0.1; other->v.velocity.z = 0; if (other->v.velocity.DotProduct(right) > 25) { other->v.velocity = 0; other->v.origin.x += right.x * 0.5f; other->v.origin.y += right.y * 0.5f; other->v.origin.z += right.z * 0.5f; // printf("right "); return; } else if (other->v.velocity.DotProduct(right) < -25) { other->v.velocity = 0; other->v.origin.x -= right.x * 0.5f; other->v.origin.y -= right.y * 0.5f; other->v.origin.z -= right.z * 0.5f; // printf("left "); return; } float forwardspeed = forward.DotProduct(other->v.velocity); ladder_velocity = 0; if ((other->v.v_angle.x <= 15) && (forwardspeed > 0)) { // up (facing up/forward) //other->v.origin[0] -= area->v.movedir[0] * 0.36f; //other->v.origin[1] -= area->v.movedir[1] * 0.36f; other->v.origin.z -= area->v.movedir.z * 0.36f; ladder_velocity.z = other->v.v_angle.x * 6; // go faster when facing forward //printf("up (facing up/forward) "); if (ladder_velocity.z < 90) { ladder_velocity.z = 90; // minimum speed } } else if ((other->v.v_angle.x >= 15) && (forwardspeed < 0)) { // up (facing down) //other->v.origin[0] += area->v.movedir[0] * 0.36f; //other->v.origin[1] += area->v.movedir[1] * 0.36f; other->v.origin.z += area->v.movedir.z * 0.36f; //printf("up (facing down) "); ladder_velocity.z = other->v.v_angle.x * 4; } else if ((other->v.v_angle.x <= 15) && (forwardspeed < 0)) { // down (facing up/forward) //other->v.origin[0] += area->v.movedir[0] * 0.36f; //other->v.origin[1] += area->v.movedir[1] * 0.36f; other->v.origin.z += area->v.movedir.z * 0.36f; ladder_velocity.z = other->v.v_angle.x * -5;// go faster when facing forward //printf("down (facing up/forward) "); if (ladder_velocity.z > -80) { ladder_velocity.z = -80; // minimum speed } } else if ((other->v.v_angle.x >= 15) && (forwardspeed > 0)) { // down (facing down) other->v.origin.x -= area->v.movedir.x * 0.36f; other->v.origin.y -= area->v.movedir.y * 0.36f; other->v.origin.z -= area->v.movedir.z * 0.36f; //printf("down (facing down) "); ladder_velocity.z = other->v.v_angle.x * -4; } //printf("angle: %i; velo: %i\n", (int)other->v.v_angle[0], (int)ladder_velocity[2]); if (ladder_velocity.z > 100) { ladder_velocity.z = 100; } else if (ladder_velocity.z < -1 * 100) { ladder_velocity.z = -1 * 100; } other->v.velocity = ladder_velocity; }