// Get the sighted location // void GetSightedLocation (edict_t * self, char *buf) { vec3_t start, forward, right, end, up, offset; int xo, yo, zo; trace_t tr; AngleVectors (self->client->v_angle, forward, right, up); VectorSet (offset, 24, 8, self->viewheight); P_ProjectSource (self->client, self->s.origin, offset, forward, right, start); VectorMA (start, 8192, forward, end); PRETRACE (); tr = gi.trace (start, NULL, NULL, end, self, CONTENTS_SOLID | CONTENTS_MONSTER | CONTENTS_DEADMONSTER); POSTTRACE (); xo = tr.endpos[0]; yo = tr.endpos[1]; zo = tr.endpos[2]; GetLocation (xo, yo, zo, 10, buf); }
qboolean loc_CanSee(edict_t * targ, edict_t * inflictor) { trace_t trace; vec3_t targpoints[8]; int i; vec3_t viewpoint; // bmodels need special checking because their origin is 0,0,0 if (targ->movetype == MOVETYPE_PUSH) return false; // bmodels not supported loc_buildboxpoints(targpoints, targ->s.origin, targ->mins, targ->maxs); VectorCopy(inflictor->s.origin, viewpoint); viewpoint[2] += inflictor->viewheight; for (i = 0; i < 8; i++) { PRETRACE(); trace = gi.trace(viewpoint, vec3_origin, vec3_origin, targpoints[i], inflictor, MASK_SOLID); POSTTRACE(); if (trace.fraction == 1.0) return true; } return false; }
//updated void LaserLinkThink (edict_t *laser) { edict_t *node = NULL; vec3_t start; vec3_t end; trace_t tr; if (!laser->enemy) { node = FindEdictByClassnumAndMass("LaserTrailLink", laser->classnum-1, laser->mass); if (node) laser->enemy = node; else laser->enemy = laser; } VectorCopy (laser->s.origin, start); VectorMA (start, 0, laser->movedir, end); PRETRACE(); tr = gi.trace (start, NULL, NULL, laser->enemy->s.origin, NULL /*ignore*/ , /*MASK_SOLID);//*/ MASK_PLAYERSOLID); POSTTRACE(); //HERE FOR TRAIL FLASHES if (tr.ent->client) { tr.ent->client->resp.intblend = laser->s.skinnum; tr.ent->client->resp.trailtouch = laser->mass; } VectorCopy (tr.endpos, laser->s.old_origin); laser->nextthink = level.time + FRAMETIME; }
edict_t *GetIDView(edict_t *ent) { vec3_t forward, dir; trace_t tr; edict_t *who, *best; float bd = 0.9, d; int i; if ((ent->client->chase_mode) && (ent->client->chase_target)) return ent->client->chase_target; AngleVectors(ent->client->v_angle, forward, NULL, NULL); VectorScale(forward, 8192, forward); VectorAdd(ent->s.origin, forward, forward); PRETRACE(); tr = gi.trace(ent->s.origin, NULL, NULL, forward, ent, MASK_PLAYERSOLID); POSTTRACE(); AngleVectors(ent->client->v_angle, forward, NULL, NULL); best = NULL; for (i = 1; i <= maxclients->value; i++) { who = g_edicts + i; if (!who->inuse) continue; //check for player VectorSubtract(who->s.origin, ent->s.origin, dir); VectorNormalize(dir); d = DotProduct(forward, dir); if (d > bd && loc_CanSee(ent, who))// && { //FIREBLADE bd = d; best = who; } //check for puppet if (ent->client->puppet) { VectorSubtract(ent->client->puppet->s.origin, ent->s.origin, dir); VectorNormalize(dir); d = DotProduct(forward, dir); if (d > bd && loc_CanSee(ent, ent->client->puppet)) { //FIREBLADE bd = d; best = ent->client->puppet; } } } if ((best != NULL) && (bd > 0.90)) return best; else return NULL; }
// DetermineViewedTeammate: determine the current player you're viewing (only looks for live teammates) // Modified from SetIDView (which was used from Zoid's CTF) edict_t *DetermineViewedTeammate (edict_t * ent) { vec3_t forward, dir; trace_t tr; edict_t *who, *best; //FIREBLADE, suggested by hal[9k] 3/11/1999 float bd = 0.9f; //FIREBLADE float d; int i; AngleVectors (ent->client->v_angle, forward, NULL, NULL); VectorScale (forward, 8192, forward); VectorAdd (ent->s.origin, forward, forward); PRETRACE (); tr = gi.trace (ent->s.origin, NULL, NULL, forward, ent, MASK_SOLID); POSTTRACE (); if (tr.fraction < 1 && tr.ent && tr.ent->client) { return NULL; } AngleVectors (ent->client->v_angle, forward, NULL, NULL); best = NULL; for (i = 1; i <= maxclients->value; i++) { who = g_edicts + i; if (!who->inuse) continue; VectorSubtract (who->s.origin, ent->s.origin, dir); VectorNormalize (dir); d = DotProduct (forward, dir); if (d > bd && loc_CanSee (ent, who) && who->solid != SOLID_NOT && who->deadflag != DEAD_DEAD && OnSameTeam (who, ent)) { bd = d; best = who; } } if (bd > 0.90) { return best; } return NULL; }
/* ============ SV_PushEntity Does not change the entities velocity at all ============ */ trace_t SV_PushEntity (edict_t * ent, vec3_t push) { trace_t trace; vec3_t start; vec3_t end; int mask; VectorCopy (ent->s.origin, start); VectorAdd (start, push, end); retry: if (ent->clipmask) mask = ent->clipmask; else mask = MASK_SOLID; PRETRACE (); trace = gi.trace (start, ent->mins, ent->maxs, end, ent, mask); POSTTRACE (); VectorCopy (trace.endpos, ent->s.origin); gi.linkentity (ent); if (trace.fraction != 1.0) { SV_Impact (ent, &trace); // if the pushed entity went away and the pusher is still there if (!trace.ent->inuse && ent->inuse) { // move the pusher back and try again VectorCopy (start, ent->s.origin); gi.linkentity (ent); goto retry; } } if (ent->inuse) G_TouchTriggers (ent); return trace; }
/* ============ SV_TestEntityPosition ============ */ edict_t * SV_TestEntityPosition (edict_t * ent) { trace_t trace; int mask; if (ent->clipmask) mask = ent->clipmask; else mask = MASK_SOLID; PRETRACE (); trace = gi.trace (ent->s.origin, ent->mins, ent->maxs, ent->s.origin, ent, mask); POSTTRACE (); if (trace.startsolid) return g_edicts; return NULL; }
void LaserSightThink(edict_t * self) { vec3_t start, end, endp, offset; vec3_t forward, right, up, angles; trace_t tr; int height = 0; // zucc compensate for weapon ride up VectorAdd(self->owner->client->v_angle, self->owner->client->kick_angles, angles); AngleVectors(angles, forward, right, up); if (self->owner->lasersight != self) { self->think = G_FreeEdict; } if (self->owner->client->pers.firing_style == ACTION_FIRING_CLASSIC) height = 8; VectorSet(offset, 24, 8, self->owner->viewheight - height); P_ProjectSource(self->owner->client, self->owner->s.origin, offset, forward, right, start); VectorMA(start, 8192, forward, end); PRETRACE(); tr = gi.trace(start, NULL, NULL, end, self->owner, CONTENTS_SOLID | CONTENTS_MONSTER | CONTENTS_DEADMONSTER); POSTTRACE(); if (tr.fraction != 1) { VectorMA(tr.endpos, -4, forward, endp); VectorCopy(endp, tr.endpos); } vectoangles(tr.plane.normal, self->s.angles); VectorCopy(tr.endpos, self->s.origin); gi.linkentity(self); self->nextthink = level.time + 0.1; }
void UpdateChaseCam( edict_t * ent ) { vec3_t o, ownerv, goal; edict_t *targ; vec3_t forward, right, angles; trace_t trace; int i; gclient_t *client; short oldStats[MAX_STATS]; if (ChaseTargetGone( ent )) return; client = ent->client; targ = client->resp.last_chase_target = client->chase_target; memcpy(oldStats, client->ps.stats, sizeof(oldStats)); if (client->chase_mode == 1) { VectorCopy( targ->s.origin, ownerv ); ownerv[2] += targ->viewheight; VectorCopy(client->resp.cmd_angles, angles); for (i = 0; i < 3; i++) angles[i] += SHORT2ANGLE(client->ps.pmove.delta_angles[i]); AngleVectors( angles, forward, right, NULL ); VectorNormalize( forward ); VectorMA( ownerv, -150, forward, o ); // jump animation lifts if (!targ->groundentity) o[2] += 16; PRETRACE(); trace = gi.trace( ownerv, vec3_origin, vec3_origin, o, targ, MASK_SOLID ); VectorCopy( trace.endpos, goal ); VectorMA( goal, 2, forward, goal ); // pad for floors and ceilings VectorCopy( goal, o ); o[2] += 6; trace = gi.trace( goal, vec3_origin, vec3_origin, o, targ, MASK_SOLID ); if (trace.fraction < 1) { VectorCopy( trace.endpos, goal ); goal[2] -= 6; } VectorCopy( goal, o ); o[2] -= 6; trace = gi.trace( goal, vec3_origin, vec3_origin, o, targ, MASK_SOLID ); POSTTRACE(); if (trace.fraction < 1) { VectorCopy( trace.endpos, goal ); goal[2] += 6; } if (targ->deadflag) client->ps.pmove.pm_type = PM_DEAD; else client->ps.pmove.pm_type = PM_FREEZE; VectorCopy(goal, ent->s.origin); VectorScale(goal, 8, client->ps.pmove.origin); for (i = 0; i < 3; i++) { client->ps.pmove.delta_angles[i] = ANGLE2SHORT(angles[i] - client->resp.cmd_angles[i]); } VectorCopy(angles, client->ps.viewangles); VectorCopy(angles, client->v_angle); client->clientNum = ent - g_edicts - 1; client->ps.gunindex = client->ps.gunframe = 0; client->desired_fov = 90; client->ps.fov = 90; ent->viewheight = 0; memcpy(client->ps.stats, targ->client->ps.stats, sizeof(client->ps.stats)); client->ps.stats[STAT_SNIPER_ICON] = 0; // only show sniper lens when in chase mode 2 if( client->ps.stats[STAT_HELPICON] != level.pic_health ) // Keep bandaging icon. client->ps.stats[STAT_HELPICON] = 0; // No weapon icon in 3rd person chase. } else // chase_mode == 2 { VectorCopy( targ->client->v_angle, angles ); if (!(game.serverfeatures & GMF_CLIENTNUM)) { VectorCopy( targ->s.origin, ownerv ); ownerv[2] += targ->viewheight; AngleVectors( angles, forward, right, NULL ); VectorNormalize( forward ); VectorMA( ownerv, 11, forward, o ); VectorCopy(o, ent->s.origin); VectorScale(o, 8, client->ps.pmove.origin); if (targ->deadflag) { client->ps.viewangles[ROLL] = 40; client->ps.viewangles[PITCH] = -15; client->ps.viewangles[YAW] = targ->client->killer_yaw; client->ps.pmove.pm_type = PM_DEAD; } else { VectorCopy(targ->client->ps.kick_angles, client->ps.kick_angles); for (i = 0; i < 3; i++) { ent->client->ps.pmove.delta_angles[i] = ANGLE2SHORT(angles[i] - client->resp.cmd_angles[i]); } VectorCopy(angles, client->ps.viewangles); VectorCopy(angles, client->v_angle); client->ps.pmove.pm_type = PM_FREEZE; } ent->viewheight = 0; memcpy(client->ps.stats, targ->client->ps.stats, sizeof(client->ps.stats)); } else { i = client->ps.pmove.pm_flags & PMF_JUMP_HELD; client->ps = targ->client->ps; VectorCopy(client->ps.viewangles, ent->s.angles); VectorCopy(client->ps.viewangles, client->v_angle); VectorScale(client->ps.pmove.origin, 0.125f, ent->s.origin); ent->viewheight = targ->viewheight; client->ps.pmove.pm_flags &= ~PMF_JUMP_HELD; client->ps.pmove.pm_flags |= i; client->ps.pmove.pm_type = PM_FREEZE; } ent->client->clientNum = targ - g_edicts - 1; ent->client->ps.fov = targ->client->ps.fov; ent->client->desired_fov = targ->client->ps.fov; // Keep bandaging icon from stats, but weapon icon is based on observer's hand and fov. if( client->ps.stats[STAT_HELPICON] == level.pic_health ) ; else if( (client->pers.hand == CENTER_HANDED || client->ps.fov > 91) && targ->client->weapon ) client->ps.stats[STAT_HELPICON] = level.pic_items[targ->client->weapon->typeNum]; else client->ps.stats[STAT_HELPICON] = 0; } //protect these for (i = STAT_TEAM_HEADER; i <= STAT_TEAM2_SCORE; i++) { client->ps.stats[i] = oldStats[i]; } client->ps.stats[STAT_TEAM3_PIC] = oldStats[STAT_TEAM3_PIC]; client->ps.stats[STAT_TEAM3_SCORE] = oldStats[STAT_TEAM3_SCORE]; client->ps.stats[STAT_LAYOUTS] = oldStats[STAT_LAYOUTS]; client->ps.stats[STAT_ID_VIEW] = oldStats[STAT_ID_VIEW]; client->ps.stats[STAT_FRAGS] = oldStats[STAT_FRAGS]; client->ps.pmove.pm_flags |= PMF_NO_PREDICTION; gi.linkentity( ent ); }
/* ============ CanDamage Returns true if the inflictor can directly damage the target. Used for explosions and melee attacks. ============ */ qboolean CanDamage (edict_t * targ, edict_t * inflictor) { vec3_t dest; trace_t trace; // bmodels need special checking because their origin is 0,0,0 //GLASS FX if ((targ->movetype == MOVETYPE_PUSH) || ((targ->movetype == MOVETYPE_FLYMISSILE) && (0 == Q_stricmp ("func_explosive", targ->classname)))) //GLASS FX { VectorAdd (targ->absmin, targ->absmax, dest); VectorScale (dest, 0.5, dest); PRETRACE (); trace = gi.trace (inflictor->s.origin, vec3_origin, vec3_origin, dest, inflictor, MASK_SOLID); POSTTRACE (); if (trace.fraction == 1.0) return true; if (trace.ent == targ) return true; return false; } PRETRACE (); trace = gi.trace (inflictor->s.origin, vec3_origin, vec3_origin, targ->s.origin, inflictor, MASK_SOLID); POSTTRACE (); if (trace.fraction == 1.0) return true; VectorCopy (targ->s.origin, dest); dest[0] += 15.0; dest[1] += 15.0; PRETRACE (); trace = gi.trace (inflictor->s.origin, vec3_origin, vec3_origin, dest, inflictor, MASK_SOLID); POSTTRACE (); if (trace.fraction == 1.0) return true; VectorCopy (targ->s.origin, dest); dest[0] += 15.0; dest[1] -= 15.0; PRETRACE (); trace = gi.trace (inflictor->s.origin, vec3_origin, vec3_origin, dest, inflictor, MASK_SOLID); POSTTRACE (); if (trace.fraction == 1.0) return true; VectorCopy (targ->s.origin, dest); dest[0] -= 15.0; dest[1] += 15.0; PRETRACE (); trace = gi.trace (inflictor->s.origin, vec3_origin, vec3_origin, dest, inflictor, MASK_SOLID); POSTTRACE (); if (trace.fraction == 1.0) return true; VectorCopy (targ->s.origin, dest); dest[0] -= 15.0; dest[1] -= 15.0; PRETRACE (); trace = gi.trace (inflictor->s.origin, vec3_origin, vec3_origin, dest, inflictor, MASK_SOLID); POSTTRACE (); if (trace.fraction == 1.0) return true; return false; }
// originally from Zoid's CTF void SetIDView(edict_t * ent) { vec3_t forward, dir; trace_t tr; edict_t *who, *best; //FIREBLADE, suggested by hal[9k] 3/11/1999 float bd = 0.9f; float d; int i; ent->client->ps.stats[STAT_ID_VIEW] = 0; //FIREBLADE if (ent->solid != SOLID_NOT && !teamplay->value) { if (!((int) (dmflags->value) & (DF_MODELTEAMS | DF_SKINTEAMS))) return; // won't ever work in non-teams so don't run the code... } if (ent->client->chase_mode) { if (ent->client->chase_target && ent->client->chase_target->inuse) { ent->client->ps.stats[STAT_ID_VIEW] = CS_PLAYERSKINS + (ent->client->chase_target - g_edicts - 1); } return; } //FIREBLADE if (ent->client->resp.id == 1) return; AngleVectors(ent->client->v_angle, forward, NULL, NULL); VectorScale(forward, 8192, forward); VectorAdd(ent->s.origin, forward, forward); PRETRACE(); tr = gi.trace(ent->s.origin, NULL, NULL, forward, ent, MASK_SOLID); POSTTRACE(); if (tr.fraction < 1 && tr.ent && tr.ent->client) { ent->client->ps.stats[STAT_ID_VIEW] = CS_PLAYERSKINS + (ent - g_edicts - 1); return; } AngleVectors(ent->client->v_angle, forward, NULL, NULL); best = NULL; for (i = 1; i <= maxclients->value; i++) { who = g_edicts + i; if (!who->inuse) continue; VectorSubtract(who->s.origin, ent->s.origin, dir); VectorNormalize(dir); d = DotProduct(forward, dir); if (d > bd && loc_CanSee(ent, who) && //FIREBLADE (who->solid != SOLID_NOT || who->deadflag == DEAD_DEAD) && (ent->solid == SOLID_NOT || OnSameTeam(ent, who))) { //FIREBLADE bd = d; best = who; } } if (best != NULL && bd > 0.90) { ent->client->ps.stats[STAT_ID_VIEW] = CS_PLAYERSKINS + (best - g_edicts - 1); } }
void UpdateChaseCam(edict_t *ent) { vec3_t o, ownerv, goal; edict_t *targ; vec3_t forward, right; trace_t trace; int i; vec3_t angles; if (ChaseTargetGone(ent)) return; targ = ent->client->resp.last_chase_target = ent->client->chase_target; if (ent->client->chase_mode == 1) { ent->client->desired_fov = 90; ent->client->ps.fov = 90; if (ent->client->resp.cmd_angles[PITCH] > 89) ent->client->resp.cmd_angles[PITCH] = 89; if (ent->client->resp.cmd_angles[PITCH] < -89) ent->client->resp.cmd_angles[PITCH] = -89; VectorCopy(targ->s.origin, ownerv); ownerv[2] += targ->viewheight; VectorCopy(ent->client->ps.viewangles, angles); AngleVectors (angles, forward, right, NULL); VectorNormalize(forward); VectorMA(ownerv, -150, forward, o); // not sure if this should be left in... -FB // if (o[2] < targ->s.origin[2] + 20) // o[2] = targ->s.origin[2] + 20; // jump animation lifts if (!targ->groundentity) o[2] += 16; PRETRACE(); trace = gi.trace(ownerv, vec3_origin, vec3_origin, o, targ, MASK_SOLID); POSTTRACE(); VectorCopy(trace.endpos, goal); VectorMA(goal, 2, forward, goal); // pad for floors and ceilings VectorCopy(goal, o); o[2] += 6; PRETRACE(); trace = gi.trace(goal, vec3_origin, vec3_origin, o, targ, MASK_SOLID); POSTTRACE(); if (trace.fraction < 1) { VectorCopy(trace.endpos, goal); goal[2] -= 6; } VectorCopy(goal, o); o[2] -= 6; PRETRACE(); trace = gi.trace(goal, vec3_origin, vec3_origin, o, targ, MASK_SOLID); POSTTRACE(); if (trace.fraction < 1) { VectorCopy(trace.endpos, goal); goal[2] += 6; } if (targ->deadflag) ent->client->ps.pmove.pm_type = PM_DEAD; else ent->client->ps.pmove.pm_type = PM_FREEZE; VectorCopy(goal, ent->s.origin); for (i=0 ; i<3 ; i++) ent->client->ps.pmove.delta_angles[i] = ANGLE2SHORT(ent->client->v_angle[i] - ent->client->resp.cmd_angles[i]); VectorCopy(ent->client->resp.cmd_angles, ent->client->ps.viewangles); } else // chase_mode == 2 { VectorCopy(targ->s.origin, ownerv); VectorCopy(targ->client->v_angle, angles); AngleVectors (angles, forward, right, NULL); VectorNormalize(forward); VectorMA(ownerv, 16, forward, o); o[2] += targ->viewheight; VectorCopy(o, ent->s.origin); ent->client->ps.fov = targ->client->ps.fov; ent->client->desired_fov = targ->client->ps.fov; for (i=0 ; i<3 ; i++) ent->client->ps.pmove.delta_angles[i] = ANGLE2SHORT(targ->client->v_angle[i] - ent->client->resp.cmd_angles[i]); if (targ->deadflag) { ent->client->ps.viewangles[ROLL] = 40; ent->client->ps.viewangles[PITCH] = -15; ent->client->ps.viewangles[YAW] = targ->client->killer_yaw; } else { VectorAdd(targ->client->v_angle, targ->client->ps.kick_angles, angles); VectorCopy(angles, ent->client->ps.viewangles); VectorCopy(angles, ent->client->v_angle); } } ent->viewheight = 0; ent->client->ps.pmove.pm_flags |= PMF_NO_PREDICTION; gi.linkentity(ent); }
int KickDoor( trace_t *tr_old, edict_t *ent, vec3_t forward ) { trace_t tr; vec3_t d_forward, right, end; float d; if ( !Q_strcasecmp( tr_old->ent->classname, "func_door_rotating" ) ) { // Make that the door is closed tr = *tr_old; #if 1 if ( (!(tr.ent->spawnflags & DOOR_START_OPEN) && !(tr.ent->moveinfo.state == STATE_TOP)) || ( (tr.ent->spawnflags & DOOR_START_OPEN) && !(tr.ent->moveinfo.state == STATE_BOTTOM)) ) #else if ( (!(tr.ent->spawnflags & DOOR_START_OPEN) && ((tr.ent->moveinfo.state == STATE_BOTTOM) || (tr.ent->moveinfo.state == STATE_DOWN))) || ((tr.ent->spawnflags & DOOR_START_OPEN) && ((tr.ent->moveinfo.state == STATE_TOP) || (tr.ent->moveinfo.state == STATE_UP))) ) #endif { //gi.dprintf( "Kicking a closed door\n" ); // Find out if we are on the "outside" #if 0 gi.WriteByte (svc_temp_entity); gi.WriteByte (TE_RAILTRAIL); gi.WritePosition (tr.ent->s.origin); gi.WritePosition (tr.endpos); gi.multicast (tr.ent->s.origin, MULTICAST_PHS); #endif VectorSubtract( tr.endpos, tr.ent->s.origin, d_forward ); forward[2] = 0; d_forward[2] = 0; VectorNormalize( forward ); VectorNormalize( d_forward ); VectorSet( right, 0, 90, 0 ); VectorRotate( d_forward, right, d_forward ); d = DotProduct( forward, d_forward ); if ( tr.ent->spawnflags & DOOR_REVERSE ) d = -d; // d = sin( acos( d ) ); if ( d > 0.0 ) { // gi.dprintf( "we think we are on the outside\n" ); //if ( tr.ent->spawnflags & DOOR_REVERSE ) // gi.dprintf( "but DOOR_REVERSE is set\n" ); // Only use the door if it's not already opening if ( (!( tr.ent->spawnflags & DOOR_START_OPEN ) && !( tr.ent->moveinfo.state == STATE_UP )) || ((tr.ent->spawnflags & DOOR_START_OPEN ) && (tr.ent->moveinfo.state == STATE_DOWN) ) ) door_use( tr.ent, ent, ent ); // Find out if someone else is on the other side VectorMA( tr.endpos, 25, forward, end ); PRETRACE(); tr = gi.trace (tr.endpos, NULL, NULL, end, tr.ent, MASK_SHOT); POSTTRACE(); if (!((tr.surface) && (tr.surface->flags & SURF_SKY))) { if (tr.fraction < 1.0) { if (tr.ent->client) { //gi.dprintf(DEVELOPER_MSG_GAME, "we found a client on the other side\n"); *tr_old = tr; return( 1 ); } } } } } } return( 0 ); }
int SV_FlyMove (edict_t * ent, float time, int mask) { edict_t *hit; 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; VectorCopy (ent->velocity, original_velocity); VectorCopy (ent->velocity, primal_velocity); numplanes = 0; time_left = time; ent->groundentity = NULL; for (bumpcount = 0; bumpcount < numbumps; bumpcount++) { for (i = 0; i < 3; i++) end[i] = ent->s.origin[i] + time_left * ent->velocity[i]; PRETRACE (); trace = gi.trace (ent->s.origin, ent->mins, ent->maxs, end, ent, mask); POSTTRACE (); if (trace.allsolid) { // entity is trapped in another solid VectorCopy (vec3_origin, ent->velocity); return 3; } if (trace.fraction > 0) { // actually covered some distance VectorCopy (trace.endpos, ent->s.origin); VectorCopy (ent->velocity, original_velocity); numplanes = 0; } if (trace.fraction == 1) break; // moved the entire distance hit = trace.ent; if (trace.plane.normal[2] > 0.7) { blocked |= 1; // floor if (hit->solid == SOLID_BSP) { ent->groundentity = hit; ent->groundentity_linkcount = hit->linkcount; } } if (!trace.plane.normal[2]) { blocked |= 2; // step } // // run the impact function // SV_Impact (ent, &trace); if (!ent->inuse) 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 VectorCopy (vec3_origin, ent->velocity); return 3; } 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++) // The following VectorCompare was added in 3.20, adding it. -FB if ((j != i) && !VectorCompare (planes[i], planes[j])) { if (DotProduct (new_velocity, planes[j]) < 0) break; // not ok } if (j == numplanes) break; } if (i != numplanes) { // go along this plane VectorCopy (new_velocity, ent->velocity); } else { // go along the crease if (numplanes != 2) { // gi.dprintf ("clip velocity, numplanes == %i\n",numplanes); VectorCopy (vec3_origin, ent->velocity); return 7; } CrossProduct (planes[0], planes[1], dir); d = DotProduct (dir, ent->velocity); VectorScale (dir, d, ent->velocity); } // // if original velocity is against the original velocity, stop dead // to avoid tiny occilations in sloping corners // if (DotProduct (ent->velocity, primal_velocity) <= 0) { VectorCopy (vec3_origin, ent->velocity); return blocked; } } return blocked; }
/* 8===============> FL_think Moving the flashlight <===============8 */ void FL_think (edict_t * self) { vec3_t start, end, endp, offset; vec3_t forward, right, up; vec3_t angles; trace_t tr; int height = 0; /*vec3_t start,end,endp,offset; vec3_t forward,right,up; trace_t tr; */ //AngleVectors (self->owner->client->v_angle, forward, right, up); VectorAdd (self->owner->client->v_angle, self->owner->client->kick_angles, angles); AngleVectors ( /*self->owner->client->v_angle */ angles, forward, right, up); /* VectorSet(offset,24 , 6, self->owner->viewheight-7); G_ProjectSource (self->owner->s.origin, offset, forward, right, start); VectorMA(start,8192,forward,end); tr = gi.trace (start,NULL,NULL, end,self->owner,CONTENTS_SOLID|CONTENTS_MONSTER|CONTENTS_DEADMONSTER); if (tr.fraction != 1) { VectorMA(tr.endpos,-4,forward,endp); VectorCopy(endp,tr.endpos); } if ((tr.ent->svflags & SVF_MONSTER) || (tr.ent->client)) { if ((tr.ent->takedamage) && (tr.ent != self->owner)) { self->s.skinnum = 1; } } else self->s.skinnum = 0; vectoangles(tr.plane.normal,self->s.angles); VectorCopy(tr.endpos,self->s.origin); gi.linkentity (self); self->nextthink = level.framenum + FRAMEDIV; */ if (self->owner->client->pers.firing_style == ACTION_FIRING_CLASSIC) height = 8; VectorSet (offset, 24, 8, self->owner->viewheight - height); P_ProjectSource (self->owner->client, self->owner->s.origin, offset, forward, right, start); VectorMA (start, 8192, forward, end); PRETRACE (); tr = gi.trace (start, NULL, NULL, end, self->owner, CONTENTS_SOLID | CONTENTS_MONSTER | CONTENTS_DEADMONSTER); POSTTRACE (); if (tr.fraction != 1) { VectorMA (tr.endpos, -4, forward, endp); VectorCopy (endp, tr.endpos); } vectoangles (tr.plane.normal, self->s.angles); VectorCopy (tr.endpos, self->s.origin); gi.linkentity (self); self->nextthink = level.framenum + FRAMEDIV; }
void target_laser_think (edict_t *self) { edict_t *ignore; vec3_t start; vec3_t end; trace_t tr; vec3_t point; vec3_t last_movedir; int count; if (self->spawnflags & 0x80000000) count = 8; else count = 4; if (self->enemy) { VectorCopy (self->movedir, last_movedir); VectorMA (self->enemy->absmin, 0.5, self->enemy->size, point); VectorSubtract (point, self->s.origin, self->movedir); VectorNormalize (self->movedir); if (!VectorCompare(self->movedir, last_movedir)) self->spawnflags |= 0x80000000; } ignore = self; VectorCopy (self->s.origin, start); VectorMA (start, 2048, self->movedir, end); while(1) { PRETRACE(); tr = gi.trace (start, NULL, NULL, end, ignore, CONTENTS_SOLID|CONTENTS_MONSTER|CONTENTS_DEADMONSTER); POSTTRACE(); if (!tr.ent) break; // hurt it if we can if ((tr.ent->takedamage) && !(tr.ent->flags & FL_IMMUNE_LASER)) T_Damage (tr.ent, self, self->activator, self->movedir, tr.endpos, vec3_origin, self->dmg, 1, DAMAGE_ENERGY, MOD_TARGET_LASER); // if we hit something that's not a monster or player or is immune to lasers, we're done if (!(tr.ent->svflags & SVF_MONSTER) && (!tr.ent->client)) { if (self->spawnflags & 0x80000000) { self->spawnflags &= ~0x80000000; gi.WriteByte (svc_temp_entity); gi.WriteByte (TE_LASER_SPARKS); gi.WriteByte (count); gi.WritePosition (tr.endpos); gi.WriteDir (tr.plane.normal); gi.WriteByte (self->s.skinnum); gi.multicast (tr.endpos, MULTICAST_PVS); } break; } ignore = tr.ent; VectorCopy (tr.endpos, start); } VectorCopy (tr.endpos, self->s.old_origin); self->nextthink = level.time + FRAMETIME; }