📄 cg_players.c
字号:
//
clientNum = cent->currentState.clientNum;
if ( clientNum >= 0 && clientNum < MAX_CLIENTS ) {
ci = &cgs.clientinfo[ clientNum ];
if ( ci->fixedtorso ) {
torsoAngles[PITCH] = 0.0f;
}
}
// --------- roll -------------
// lean towards the direction of travel
VectorCopy( cent->currentState.pos.trDelta, velocity );
speed = VectorNormalize( velocity );
if ( speed ) {
vec3_t axis[3];
float side;
speed *= 0.05f;
AnglesToAxis( legsAngles, axis );
side = speed * DotProduct( velocity, axis[1] );
legsAngles[ROLL] -= side;
side = speed * DotProduct( velocity, axis[0] );
legsAngles[PITCH] += side;
}
//
clientNum = cent->currentState.clientNum;
if ( clientNum >= 0 && clientNum < MAX_CLIENTS ) {
ci = &cgs.clientinfo[ clientNum ];
if ( ci->fixedlegs ) {
legsAngles[YAW] = torsoAngles[YAW];
legsAngles[PITCH] = 0.0f;
legsAngles[ROLL] = 0.0f;
}
}
// pain twitch
CG_AddPainTwitch( cent, torsoAngles );
// pull the angles back out of the hierarchial chain
AnglesSubtract( headAngles, torsoAngles, headAngles );
AnglesSubtract( torsoAngles, legsAngles, torsoAngles );
AnglesToAxis( legsAngles, legs );
AnglesToAxis( torsoAngles, torso );
AnglesToAxis( headAngles, head );
}
//==========================================================================
/*
===============
CG_HasteTrail
===============
*/
static void CG_HasteTrail( centity_t *cent ) {
localEntity_t *smoke;
vec3_t origin;
int anim;
if ( cent->trailTime > cg.time ) {
return;
}
anim = cent->pe.legs.animationNumber & ~ANIM_TOGGLEBIT;
if ( anim != LEGS_RUN && anim != LEGS_BACK ) {
return;
}
cent->trailTime += 100;
if ( cent->trailTime < cg.time ) {
cent->trailTime = cg.time;
}
VectorCopy( cent->lerpOrigin, origin );
origin[2] -= 16;
smoke = CG_SmokePuff( origin, vec3_origin,
8,
1, 1, 1, 1,
500,
cg.time,
0,
0,
cgs.media.hastePuffShader );
// use the optimized local entity add
smoke->leType = LE_SCALE_FADE;
}
#ifdef MISSIONPACK
/*
===============
CG_BreathPuffs
===============
*/
static void CG_BreathPuffs( centity_t *cent, refEntity_t *head) {
clientInfo_t *ci;
vec3_t up, origin;
int contents;
ci = &cgs.clientinfo[ cent->currentState.number ];
if (!cg_enableBreath.integer) {
return;
}
if ( cent->currentState.number == cg.snap->ps.clientNum && !cg.renderingThirdPerson) {
return;
}
if ( cent->currentState.eFlags & EF_DEAD ) {
return;
}
contents = trap_CM_PointContents( head->origin, 0 );
if ( contents & ( CONTENTS_WATER | CONTENTS_SLIME | CONTENTS_LAVA ) ) {
return;
}
if ( ci->breathPuffTime > cg.time ) {
return;
}
VectorSet( up, 0, 0, 8 );
VectorMA(head->origin, 8, head->axis[0], origin);
VectorMA(origin, -4, head->axis[2], origin);
CG_SmokePuff( origin, up, 16, 1, 1, 1, 0.66f, 1500, cg.time, cg.time + 400, LEF_PUFF_DONT_SCALE, cgs.media.shotgunSmokePuffShader );
ci->breathPuffTime = cg.time + 2000;
}
/*
===============
CG_DustTrail
===============
*/
static void CG_DustTrail( centity_t *cent ) {
int anim;
localEntity_t *dust;
vec3_t end, vel;
trace_t tr;
if (!cg_enableDust.integer)
return;
if ( cent->dustTrailTime > cg.time ) {
return;
}
anim = cent->pe.legs.animationNumber & ~ANIM_TOGGLEBIT;
if ( anim != LEGS_LANDB && anim != LEGS_LAND ) {
return;
}
cent->dustTrailTime += 40;
if ( cent->dustTrailTime < cg.time ) {
cent->dustTrailTime = cg.time;
}
VectorCopy(cent->currentState.pos.trBase, end);
end[2] -= 64;
CG_Trace( &tr, cent->currentState.pos.trBase, NULL, NULL, end, cent->currentState.number, MASK_PLAYERSOLID );
if ( !(tr.surfaceFlags & SURF_DUST) )
return;
VectorCopy( cent->currentState.pos.trBase, end );
end[2] -= 16;
VectorSet(vel, 0, 0, -30);
dust = CG_SmokePuff( end, vel,
24,
.8f, .8f, 0.7f, 0.33f,
500,
cg.time,
0,
0,
cgs.media.dustPuffShader );
}
#endif
/*
===============
CG_TrailItem
===============
*/
static void CG_TrailItem( centity_t *cent, qhandle_t hModel ) {
refEntity_t ent;
vec3_t angles;
vec3_t axis[3];
VectorCopy( cent->lerpAngles, angles );
angles[PITCH] = 0;
angles[ROLL] = 0;
AnglesToAxis( angles, axis );
memset( &ent, 0, sizeof( ent ) );
VectorMA( cent->lerpOrigin, -16, axis[0], ent.origin );
ent.origin[2] += 16;
angles[YAW] += 90;
AnglesToAxis( angles, ent.axis );
ent.hModel = hModel;
trap_R_AddRefEntityToScene( &ent );
}
/*
===============
CG_PlayerFlag
===============
*/
static void CG_PlayerFlag( centity_t *cent, qhandle_t hSkin, refEntity_t *torso ) {
clientInfo_t *ci;
refEntity_t pole;
refEntity_t flag;
vec3_t angles, dir;
int legsAnim, flagAnim, updateangles;
float angle, d;
// show the flag pole model
memset( &pole, 0, sizeof(pole) );
pole.hModel = cgs.media.flagPoleModel;
VectorCopy( torso->lightingOrigin, pole.lightingOrigin );
pole.shadowPlane = torso->shadowPlane;
pole.renderfx = torso->renderfx;
CG_PositionEntityOnTag( &pole, torso, torso->hModel, "tag_flag" );
trap_R_AddRefEntityToScene( &pole );
// show the flag model
memset( &flag, 0, sizeof(flag) );
flag.hModel = cgs.media.flagFlapModel;
flag.customSkin = hSkin;
VectorCopy( torso->lightingOrigin, flag.lightingOrigin );
flag.shadowPlane = torso->shadowPlane;
flag.renderfx = torso->renderfx;
VectorClear(angles);
updateangles = qfalse;
legsAnim = cent->currentState.legsAnim & ~ANIM_TOGGLEBIT;
if( legsAnim == LEGS_IDLE || legsAnim == LEGS_IDLECR ) {
flagAnim = FLAG_STAND;
} else if ( legsAnim == LEGS_WALK || legsAnim == LEGS_WALKCR ) {
flagAnim = FLAG_STAND;
updateangles = qtrue;
} else {
flagAnim = FLAG_RUN;
updateangles = qtrue;
}
if ( updateangles ) {
VectorCopy( cent->currentState.pos.trDelta, dir );
// add gravity
dir[2] += 100;
VectorNormalize( dir );
d = DotProduct(pole.axis[2], dir);
// if there is anough movement orthogonal to the flag pole
if (fabs(d) < 0.9) {
//
d = DotProduct(pole.axis[0], dir);
if (d > 1.0f) {
d = 1.0f;
}
else if (d < -1.0f) {
d = -1.0f;
}
angle = acos(d);
d = DotProduct(pole.axis[1], dir);
if (d < 0) {
angles[YAW] = 360 - angle * 180 / M_PI;
}
else {
angles[YAW] = angle * 180 / M_PI;
}
if (angles[YAW] < 0)
angles[YAW] += 360;
if (angles[YAW] > 360)
angles[YAW] -= 360;
//vectoangles( cent->currentState.pos.trDelta, tmpangles );
//angles[YAW] = tmpangles[YAW] + 45 - cent->pe.torso.yawAngle;
// change the yaw angle
CG_SwingAngles( angles[YAW], 25, 90, 0.15f, ¢->pe.flag.yawAngle, ¢->pe.flag.yawing );
}
/*
d = DotProduct(pole.axis[2], dir);
angle = Q_acos(d);
d = DotProduct(pole.axis[1], dir);
if (d < 0) {
angle = 360 - angle * 180 / M_PI;
}
else {
angle = angle * 180 / M_PI;
}
if (angle > 340 && angle < 20) {
flagAnim = FLAG_RUNUP;
}
if (angle > 160 && angle < 200) {
flagAnim = FLAG_RUNDOWN;
}
*/
}
// set the yaw angle
angles[YAW] = cent->pe.flag.yawAngle;
// lerp the flag animation frames
ci = &cgs.clientinfo[ cent->currentState.clientNum ];
CG_RunLerpFrame( ci, ¢->pe.flag, flagAnim, 1 );
flag.oldframe = cent->pe.flag.oldFrame;
flag.frame = cent->pe.flag.frame;
flag.backlerp = cent->pe.flag.backlerp;
AnglesToAxis( angles, flag.axis );
CG_PositionRotatedEntityOnTag( &flag, &pole, pole.hModel, "tag_flag" );
trap_R_AddRefEntityToScene( &flag );
}
#ifdef MISSIONPACK // bk001204
/*
===============
CG_PlayerTokens
===============
*/
static void CG_PlayerTokens( centity_t *cent, int renderfx ) {
int tokens, i, j;
float angle;
refEntity_t ent;
vec3_t dir, origin;
skulltrail_t *trail;
trail = &cg.skulltrails[cent->currentState.number];
tokens = cent->currentState.generic1;
if ( !tokens ) {
trail->numpositions = 0;
return;
}
if ( tokens > MAX_SKULLTRAIL ) {
tokens = MAX_SKULLTRAIL;
}
// add skulls if there are more than last time
for (i = 0; i < tokens - trail->numpositions; i++) {
for (j = trail->numpositions; j > 0; j--) {
VectorCopy(trail->positions[j-1], trail->positions[j]);
}
VectorCopy(cent->lerpOrigin, trail->positions[0]);
}
trail->numpositions = tokens;
// move all the skulls along the trail
VectorCopy(cent->lerpOrigin, origin);
for (i = 0; i < trail->numpositions; i++) {
VectorSubtract(trail->positions[i], origin, dir);
if (VectorNormalize(dir) > 30) {
VectorMA(origin, 30, dir, trail->positions[i]);
}
VectorCopy(trail->positions[i], origin);
}
memset( &ent, 0, sizeof( ent ) );
if( cgs.clientinfo[ cent->currentState.clientNum ].team == TEAM_BLUE ) {
ent.hModel = cgs.media.redCubeModel;
} else {
ent.hModel = cgs.media.blueCubeModel;
}
ent.renderfx = renderfx;
VectorCopy(cent->lerpOrigin, origin);
for (i = 0; i < trail->numpositions; i++) {
VectorSubtract(origin, trail->positions[i], ent.axis[0]);
ent.axis[0][2] = 0;
VectorNormalize(ent.axis[0]);
VectorSet(ent.axis[2], 0, 0, 1);
CrossProduct(ent.axis[0], ent.axis[2], ent.axis[1]);
VectorCopy(trail->positions[i], ent.origin);
angle = (((cg.time + 500 * MAX_SKULLTRAIL - 500 * i) / 16) & 255) * (M_PI * 2) / 255;
ent.origin[2] += sin(angle) * 10;
trap_R_AddRefEntityToScene( &ent );
VectorCopy(trail->positions[i], origin);
}
}
#endif
/*
===============
CG_PlayerPowerups
===============
*/
static void CG_PlayerPowerups( centity_t *cent, refEntity_t *torso ) {
int powerups;
clientInfo_t *ci;
powerups = cent->currentState.powerups;
if ( !powerups ) {
return;
}
// quad gives a dlight
if ( powerups & ( 1 << PW_QUAD ) ) {
trap_R_AddLightToScene( cent->lerpOrigin, 200 + (rand()&31), 0.2f, 0.2f, 1 );
}
// flight plays a looped sound
if ( powerups & ( 1 << PW_FLIGHT ) ) {
trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin, vec3_origin, cgs.media.flightSound );
}
ci = &cgs.clientinfo[ cent->currentState.clientNum ];
// redflag
if ( powerups & ( 1 << PW_REDFLAG ) ) {
if (ci->newAnims) {
CG_PlayerFlag( cent, cgs.media.redFlagFlapSkin, torso );
}
else {
CG_TrailItem( cent, cgs.media.redFlagModel );
}
trap_R_AddLightToScene( cent->lerpOrigin, 200 + (rand()&31), 1.0, 0.2f, 0.2f );
}
// blueflag
if ( powerups & ( 1 << PW_BLUEFLAG ) ) {
if (ci->newAnims){
CG_PlayerFlag( cent, cgs.media.blueFlagFlapSkin, torso );
}
else {
CG_TrailItem( cent, cgs.media.blueFlagModel );
}
trap_R_AddLightToScene( cent->lerpOrigin, 200 + (rand()&31), 0.2f, 0.2f, 1.0 );
}
// neutralflag
if ( powerups & ( 1 << PW_NEUTRALFLAG ) ) {
if (ci->newAnims) {
CG_PlayerFlag( cent, cgs.media.neutralFlagFlapSkin, torso );
}
else {
CG_TrailItem( cent, cgs.media.neutralFlagModel );
}
trap_R_AddLightToScene( cent->lerpOrigin, 200 + (rand()&31), 1.0, 1.0, 1.0 );
}
// haste leaves smoke trails
if ( powerups & ( 1 << PW_HASTE ) ) {
CG_HasteTrail( cent );
}
}
/*
===============
CG_PlayerFloatSprite
Float a sprite over the player's head
===============
*/
static void CG_PlayerFloatSprite( centity_t *cent, qhandle_t shader ) {
int rf;
refEntity_t ent;
if ( cent->currentState.number == cg.snap->ps.clientNum && !cg.renderingThirdPerson ) {
rf = RF_THIRD_PERSON; // only show in mirrors
} else {
rf = 0;
}
memset( &ent, 0, sizeof( ent ) );
VectorCopy( cent->lerpOrigin, ent.origin );
ent.origin[2] += 48;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -