void Sky_DrawFace (int axis) { glpoly_t *p; MathVector3f_t verts[4]; int i, j, start; float di,qi,dj,qj; MathVector3f_t v_up, v_right, temp, temp2; Sky_SetBoxVert(-1.0f,-1.0f,axis,verts[0]); Sky_SetBoxVert(-1.0f,1.0f,axis,verts[1]); Sky_SetBoxVert(1.0f,1.0f,axis,verts[2]); Sky_SetBoxVert(1.0f,-1.0f,axis,verts[3]); start = Hunk_LowMark (); p = (glpoly_t*)Hunk_Alloc(sizeof(glpoly_t)); Math_VectorSubtract(verts[2],verts[3], v_up); Math_VectorSubtract(verts[2],verts[1], v_right); di = Math_Max((int)r_sky_quality.value,1); qi = 1.0f/di; dj = (axis < 4) ? di*2 : di; // Subdivide vertically more than horizontally on skybox sides qj = 1.0f/dj; for (i=0; i<di; i++) { for (j=0; j<dj; j++) { if (i*qi < skymins[0][axis]/2+0.5 - qi || i*qi > skymaxs[0][axis]/2+0.5 || j*qj < skymins[1][axis]/2+0.5 - qj || j*qj > skymaxs[1][axis]/2+0.5) continue; //if (i&1 ^ j&1) continue; //checkerboard test Math_VectorScale(v_right, qi*i, temp); Math_VectorScale(v_up, qj*j, temp2); Math_VectorAdd(temp,temp2,temp); Math_VectorAdd(verts[0],temp,p->verts[0]); Math_VectorScale(v_up, qj, temp); Math_VectorAdd(p->verts[0],temp,p->verts[1]); Math_VectorScale(v_right, qi, temp); Math_VectorAdd(p->verts[1],temp,p->verts[2]); Math_VectorAdd(p->verts[0],temp,p->verts[3]); Sky_DrawFaceQuad(p); } } Hunk_FreeToLowMark(start); }
void Crossbow_Projectile(ServerEntity_t *ent) { // [11/2/2012] Revised and fixed ~hogsy MathVector3f_t mvDirection; ServerEntity_t *eArrow; eArrow = Entity_Spawn(); if(eArrow) { eArrow->local.eOwner = ent; eArrow->v.movetype = MOVETYPE_FLY; eArrow->Physics.iSolid = SOLID_BBOX; Math_MVToVector(Weapon_Aim(ent), mvDirection); Math_VectorScale(mvDirection, 2000.0f, eArrow->v.velocity); Entity_SetModel(eArrow,"models/arrow.md2"); Entity_SetSizeVector(eArrow,g_mvOrigin3f,g_mvOrigin3f); // [25/6/2012] Simplified ~hogsy Math_VectorCopy(ent->v.origin,eArrow->v.origin); eArrow->v.origin[2] += 15.0f; Math_MVToVector(Math_VectorToAngles(ent->v.velocity),ent->v.angles); eArrow->v.TouchFunction = arrow_touch; } }
// [4/7/2012] Renamed to Discus_SpawnProjectile ~hogsy void Discus_SpawnProjectile(ServerEntity_t *ent,vec3_t org) { ServerEntity_t *eDiscus; MathVector3f_t mvDirection; eDiscus = Entity_Spawn(); eDiscus->v.cClassname = "discus"; eDiscus->v.movetype = MOVETYPE_FLYBOUNCE; eDiscus->Physics.iSolid = SOLID_BBOX; eDiscus->v.effects = EF_MOTION_ROTATE; eDiscus->v.enemy = ent; // [4/8/2012] Updated to use owner instead ~hogsy eDiscus->local.eOwner = ent; eDiscus->local.hit = 0; Math_MVToVector(Weapon_Aim(ent), mvDirection); Math_VectorScale(mvDirection, 700.0f, eDiscus->v.velocity); Math_MVToVector(Math_VectorToAngles(eDiscus->v.velocity), eDiscus->v.angles); eDiscus->v.TouchFunction = Discus_ProjectileTouch; Entity_SetModel(eDiscus, "models/w_daedalus.md2"); Entity_SetSizeVector(eDiscus, g_mvOrigin3f, g_mvOrigin3f); Entity_SetOrigin(eDiscus, org); Sound(ent,CHAN_WEAPON,"weapons/discus/discusthrow.wav",255,ATTN_NORM); }
void Point_PropTouch(ServerEntity_t *eEntity, ServerEntity_t *eOther) { if(!eOther->v.iHealth) return; Math_VectorClear(eEntity->v.velocity); Math_VectorScale(eOther->v.velocity,0.25f,eEntity->v.velocity); }
// [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); }
/* TODO: - Firstly save each iteration of our water, so we can keep track of colour etc. - Recalc colour for different dynamic moving lights. */ void Warp_DrawWaterPoly(glpoly_t *p) { VideoObject_t *voWaterPoly; vec3_t vWave,vLightColour; float *v; int i; voWaterPoly = malloc(p->numverts*sizeof(VideoObject_t)); if(!voWaterPoly) { Sys_Error("Failed to allocate water poly!\n"); return; } v = p->verts[0]; for(i = 0; i < p->numverts; i++,v += VERTEXSIZE) { voWaterPoly[i].vTextureCoord[0][0] = WARPCALC(v[3],v[4]); voWaterPoly[i].vTextureCoord[0][1] = WARPCALC(v[4],v[3]); voWaterPoly[i].vColour[3] = Math_Clamp(0, r_wateralpha.value, 1.0f); Math_VectorCopy(v,vWave); // Shitty lit water, use dynamic light points in the future... { MathVector_t mvLightColour; // Use vWave position BEFORE we move it, otherwise the water will flicker. mvLightColour = Light_GetSample(vWave); Math_MVToVector(mvLightColour,vLightColour); Math_VectorScale(vLightColour,1.0f/200.0f,vLightColour); Math_VectorDivide(vLightColour,0.2f,vLightColour); } Math_VectorCopy(vLightColour,voWaterPoly[i].vColour); // [20/1/2013] Added in subtle water bobbing, based on this code http://www.quake-1.com/docs/quakesrc.org/26.html ~hogsy vWave[2] = v[2]+ 2.0f*(float)sin(v[0]*0.025f+cl.time)*(float)sin(v[2]*0.05f+cl.time)+ 2.0f*(float)sin(v[1]*0.025f+cl.time*2.0f)*(float)sin(v[2]*0.05f+cl.time); Math_VectorCopy(vWave,voWaterPoly[i].vVertex); } Video_DrawObject(voWaterPoly,VIDEO_PRIMITIVE_TRIANGLE_FAN,p->numverts); free(voWaterPoly); }
/* Toss, bounce, and fly movement. When onground, do nothing. */ void Physics_Toss(edict_t *ent) { trace_t trace; vec3_t move; float backoff; // Regular thinking if(!Server_RunThink(ent) || (ent->v.flags & FL_ONGROUND)) return; Game->Physics_CheckVelocity(ent); // Add gravity if(ent->v.movetype != MOVETYPE_FLY && ent->v.movetype != MOVETYPE_FLYMISSILE && ent->v.movetype != MOVETYPE_FLYBOUNCE) Game->Physics_SetGravity(ent); // Move angles Math_VectorMA(ent->v.angles,host_frametime,ent->v.avelocity,ent->v.angles); // Move origin Math_VectorScale(ent->v.velocity,host_frametime,move); trace = SV_PushEntity(ent, move); if(trace.fraction == 1.0f || ent->free) return; if(ent->v.movetype == MOVETYPE_FLYBOUNCE) backoff = 2.0f; else if (ent->v.movetype == MOVETYPE_BOUNCE) backoff = 1.5f; else backoff = 1.0f; ClipVelocity (ent->v.velocity, trace.plane.normal, ent->v.velocity, backoff); // Stop if on ground if(trace.plane.normal[2] > 0.7 || (ent->v.movetype != MOVETYPE_BOUNCE && ent->v.movetype != MOVETYPE_FLYBOUNCE)) if(ent->v.velocity[2] < 60.0f) { ent->v.flags = ent->v.flags | FL_ONGROUND; ent->v.groundentity = trace.ent; Math_VectorCopy(mv3Origin,ent->v.velocity); Math_VectorCopy(mv3Origin,ent->v.avelocity); } Game->Physics_CheckWaterTransition(ent); }
void C4Vizatergo_PrimaryAttack(ServerEntity_t *eOwner) { MathVector3f_t vOrigin; MathVector3f_t mvDirection; ServerEntity_t *c4ball = Entity_Spawn(); Sound(eOwner,CHAN_AUTO,"weapons/c4/c4fire.wav",255,ATTN_NORM); Sound(eOwner,CHAN_AUTO,"weapons/c4/c4cock.wav",255,ATTN_NORM); Weapon_Animate(eOwner,C4Animation_Fire1); Weapon_ViewPunch(eOwner, 7, true); eOwner->v.iPrimaryAmmo = eOwner->local.iC4Ammo -= 1; c4ball->v.cClassname = "c4ball"; c4ball->v.movetype = MOVETYPE_BOUNCE; c4ball->local.style = AMMO_C4BOMBS; // Cleaner way to tell if this can explode or not :V ~hogsy c4ball->local.iC4Ammo = 1; // [11/8/2013] Since style is used for other shit too LAWL ~hogsy c4ball->local.eOwner = eOwner; // Set the physical properties. c4ball->Physics.iSolid = SOLID_BBOX; c4ball->Physics.fMass = 0.9f; c4ball->Physics.eIgnore = eOwner; c4ball->Physics.fGravity = SERVER_GRAVITY; Math_MVToVector(Weapon_Aim(eOwner), mvDirection); Math_VectorScale(mvDirection, C4VIZATERGO_MAX_RANGE, c4ball->v.velocity); c4ball->v.velocity[pY] += 20.0f; Math_MVToVector(Math_VectorToAngles(c4ball->v.velocity),c4ball->v.angles); Math_VectorCopy(eOwner->v.origin,vOrigin); c4ball->v.TouchFunction = C4Vizatergo_C4BallTouch; c4ball->v.think = C4Vizatergo_Think; c4ball->v.dNextThink = Server.dTime + 2.5; Entity_SetModel(c4ball,"models/c4ammo.md2"); Entity_SetSizeVector(c4ball,g_mvOrigin3f,g_mvOrigin3f); Entity_SetOrigin(c4ball,vOrigin); if(eOwner->local.attackb_finished > Server.dTime) // No attack boost... eOwner->local.dAttackFinished = Server.dTime+0.6; else eOwner->local.dAttackFinished = Server.dTime+1.2; }
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); }
void Physics_AddFriction(edict_t *eEntity,vec3_t vVelocity,vec3_t vOrigin) { float *vel; float speed, newspeed, control; vec3_t start, stop; float friction; trace_t trace; vel = vVelocity; speed = sqrt(vel[0]*vel[0] +vel[1]*vel[1]); if(!speed) return; // If the leading edge is over a dropoff, increase friction start[0] = stop[0] = vOrigin[0] + vel[0]/speed*16.0f; start[1] = stop[1] = vOrigin[1] + vel[1]/speed*16.0f; start[2] = vOrigin[2] + eEntity->v.mins[2]; stop[2] = start[2] - 34; trace = SV_Move(start,mv3Origin,mv3Origin,stop,true,eEntity); if(trace.fraction == 1.0f) friction = eEntity->Physics.fFriction*sv_edgefriction.value; else friction = eEntity->Physics.fFriction; // Apply friction control = speed < cvPhysicsStopSpeed.value ? cvPhysicsStopSpeed.value : speed; newspeed = speed - host_frametime*control*friction; if(newspeed < 0) newspeed = 0; newspeed /= speed; Math_VectorScale(vel,newspeed,vel); }
winding_t *BasePolyForPlane (plane_t *p) { int i, x; vec_t max, v; vec3_t org, vright, vup; winding_t *w; // find the major axis max = -BOGUS_RANGE; x = -1; for (i=0 ; i<3; i++) { v = fabs(p->normal[i]); if (v > max) { x = i; max = v; } } if (x==-1) Error("BasePolyForPlane: no axis found"); Math_VectorCopy(vec3_origin,vup); switch (x) { case 0: case 1: vup[2] = 1; break; case 2: vup[0] = 1; break; } v = Math_DotProduct(vup,p->normal); Math_VectorMA(vup,-v,p->normal,vup); Math_VectorNormalize(vup); Math_VectorScale(p->normal,p->dist,org); Math_CrossProduct(vup,p->normal,vright); Math_VectorScale(vup,8192,vup); Math_VectorScale(vright,8192,vright); // project a really big axis aligned box onto the plane w = NewWinding (4); Math_VectorSubtract(org,vright,w->points[0]); Math_VectorAdd(w->points[0],vup,w->points[0]); Math_VectorAdd(org,vright,w->points[1]); Math_VectorAdd(w->points[1],vup,w->points[1]); Math_VectorAdd(org,vright,w->points[2]); Math_VectorSubtract(w->points[2],vup,w->points[2]); Math_VectorSubtract(org,vright,w->points[3]); Math_VectorSubtract(w->points[3],vup,w->points[3]); w->numpoints = 4; return w; }
int SV_FlyMove (edict_t *ent, float time, trace_t *steptrace) { int bumpcount, numbumps; vec3_t dir; float d; int numplanes; vec3_t planes[MAX_CLIP_PLANES]; vec3_t primal_velocity, original_velocity, new_velocity; int i, j; trace_t trace; vec3_t end; float time_left; int blocked; numbumps = 4; blocked = 0; Math_VectorCopy (ent->v.velocity, original_velocity); Math_VectorCopy (ent->v.velocity, primal_velocity); numplanes = 0; time_left = time; for (bumpcount=0 ; bumpcount<numbumps ; bumpcount++) { if (!ent->v.velocity[0] && !ent->v.velocity[1] && !ent->v.velocity[2]) break; for (i=0 ; i<3 ; i++) end[i] = ent->v.origin[i] + time_left * ent->v.velocity[i]; trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, FALSE, ent); if(trace.bAllSolid) { // Entity is trapped in another solid Math_VectorCopy(mv3Origin, ent->v.velocity); return 3; } if (trace.fraction > 0) { // Actually covered some distance Math_VectorCopy (trace.endpos, ent->v.origin); Math_VectorCopy (ent->v.velocity, original_velocity); numplanes = 0; } if (trace.fraction == 1) break; // moved the entire distance if(!trace.ent) { Sys_Error ("SV_FlyMove: !trace.ent"); return 0; } if (trace.plane.normal[2] > 0.7) { blocked |= 1; // floor if (trace.ent->Physics.iSolid == SOLID_BSP) { ent->v.flags |= FL_ONGROUND; ent->v.groundentity = trace.ent; } } if (!trace.plane.normal[2]) { blocked |= 2; // step if (steptrace) *steptrace = trace; // save for player extrafriction } // Run the impact function Physics_Impact(ent,trace.ent); if (ent->free) break; // removed by the impact function time_left -= time_left * trace.fraction; // Cliped to another plane if(numplanes >= MAX_CLIP_PLANES) { // This shouldn't really happen Math_VectorCopy(mv3Origin, ent->v.velocity); return 3; } Math_VectorCopy (trace.plane.normal, planes[numplanes]); numplanes++; // Modify original_velocity so it parallels all of the clip planes for(i = 0; i < numplanes; i++) { ClipVelocity (original_velocity, planes[i], new_velocity, 1); for (j=0 ; j<numplanes ; j++) if (j != i) { if(Math_DotProduct(new_velocity,planes[j]) < 0) break; // not ok } if (j == numplanes) break; } if (i != numplanes) Math_VectorCopy (new_velocity, ent->v.velocity); else { // Go along the crease if (numplanes != 2) { Math_VectorCopy(mv3Origin, ent->v.velocity); return 7; } Math_CrossProduct(planes[0], planes[1], dir); d = Math_DotProduct(dir, ent->v.velocity); Math_VectorScale(dir, d, ent->v.velocity); } // if original velocity is against the original velocity, stop dead // to avoid tiny occilations in sloping corners if(Math_DotProduct(ent->v.velocity,primal_velocity) <= 0) { Math_VectorCopy(mv3Origin,ent->v.velocity); return blocked; } } return blocked; }
/* Uses both primary burst and mega burst! */ void IonRifle_PrimaryAttack(edict_t *eOwner) { switch(eOwner->local.iFireMode) { case 1: Weapon_Animate(eOwner,efIonRifleBlastFire); eOwner->v.punchangle[0] -= (float)(((rand()%10)+5)); eOwner->local.ionblaster_ammo -= 5; { edict_t *eIonBall = Entity_Spawn(); if(eIonBall) { vec3_t vOrigin; eIonBall->v.cClassname = "ionball"; eIonBall->v.movetype = MOVETYPE_FLY; eIonBall->v.effects = EF_LIGHT_GREEN; eIonBall->v.TouchFunction = IonRifle_IonBallTouch; eIonBall->Model.fScale = 2.0f; eIonBall->Physics.iSolid = SOLID_BBOX; eIonBall->Physics.eIgnore = eOwner; eIonBall->local.eOwner = eOwner; eIonBall->local.style = 1; // [29/1/2014] Preserve our firemode ~hogsy Math_VectorCopy(eOwner->v.origin,vOrigin); vOrigin[2] += 25.0f; Entity_SetModel(eIonBall,"models/ionball.md2"); Entity_SetSizeVector(eIonBall,mv3Origin,mv3Origin); Entity_SetOrigin(eIonBall,vOrigin); { vec_t *vAim = Engine.Aim(eOwner); Math_VectorScale(vAim,IONRIFLE_MAX_RANGE,eIonBall->v.velocity); Math_VectorCopy(vAim,eIonBall->v.angles); } Engine.LinkEntity(eIonBall,false); } } if(eOwner->local.attackb_finished > Server.dTime) eOwner->local.dAttackFinished = Server.dTime+0.10; else eOwner->local.dAttackFinished = Server.dTime+0.5; break; default: // Simple bursts Sound(eOwner,CHAN_AUTO,"weapons/laser.wav",255,ATTN_NORM); switch(eOwner->local.iBarrelCount) { case 0: Weapon_Animate(eOwner,efIonRiflePulseFireA); break; case 1: Weapon_Animate(eOwner,efIonRiflePulseFireB); break; case 2: Weapon_Animate(eOwner,efIonRiflePulseFireC); break; case 3: Weapon_Animate(eOwner,efIonRiflePulseFireD); break; case 4: Weapon_Animate(eOwner,efIonRiflePulseFireE); } // [25/9/2013] Punch the view back ~hogsy eOwner->v.punchangle[0] -= (float)(((rand()%5)+1)/10.0f); eOwner->local.ionblaster_ammo--; // [29/1/2014] Let us cycle through each barrel on an individual basis ~hogsy eOwner->local.iBarrelCount++; if(eOwner->local.iBarrelCount >= 4) eOwner->local.iBarrelCount = 0; { edict_t *eIonBall = Entity_Spawn(); if(eIonBall) { vec3_t vOrigin; eIonBall->v.cClassname = "ionball"; eIonBall->v.movetype = MOVETYPE_FLY; eIonBall->v.effects = EF_LIGHT_GREEN; eIonBall->v.TouchFunction = IonRifle_IonBallTouch; eIonBall->Model.fScale = 0.3f; eIonBall->Physics.iSolid = SOLID_BBOX; eIonBall->Physics.eIgnore = eOwner; eIonBall->local.eOwner = eOwner; eIonBall->local.style = 0; // [29/1/2014] Preserve our firemode ~hogsy Math_VectorCopy(eOwner->v.origin,vOrigin); vOrigin[2] += 25.0f; Entity_SetModel(eIonBall,"models/ionball.md2"); Entity_SetSizeVector(eIonBall,mv3Origin,mv3Origin); Entity_SetOrigin(eIonBall,vOrigin); { vec_t *vAim = Engine.Aim(eOwner); Math_VectorScale(vAim,IONRIFLE_MAX_RANGE,eIonBall->v.velocity); Math_VectorCopy(vAim,eIonBall->v.avelocity); } Engine.LinkEntity(eIonBall,false); } } if(eOwner->local.attackb_finished > Server.dTime) eOwner->local.dAttackFinished = Server.dTime+0.5; else eOwner->local.dAttackFinished = Server.dTime+0.3; } // [17/11/2013] Update ammo counts... ~hogsy eOwner->v.iPrimaryAmmo = eOwner->local.ionblaster_ammo; }