📄 cg_weapons.c
字号:
==========================
CG_NailTrail
==========================
*/
static void CG_PlasmaTrail( centity_t *cent, const weaponInfo_t *wi ) {
localEntity_t *le;
refEntity_t *re;
entityState_t *es;
vec3_t velocity, xvelocity, origin;
vec3_t offset, xoffset;
vec3_t v[3];
int t, startTime, step;
float waterScale = 1.0f;
if ( cg_noProjectileTrail.integer || cg_oldPlasma.integer ) {
return;
}
step = 50;
es = ¢->currentState;
startTime = cent->trailTime;
t = step * ( (startTime + step) / step );
BG_EvaluateTrajectory( &es->pos, cg.time, origin );
le = CG_AllocLocalEntity();
re = &le->refEntity;
velocity[0] = 60 - 120 * crandom();
velocity[1] = 40 - 80 * crandom();
velocity[2] = 100 - 200 * crandom();
le->leType = LE_MOVE_SCALE_FADE;
le->leFlags = LEF_TUMBLE;
le->leBounceSoundType = LEBS_NONE;
le->leMarkType = LEMT_NONE;
le->startTime = cg.time;
le->endTime = le->startTime + 600;
le->pos.trType = TR_GRAVITY;
le->pos.trTime = cg.time;
AnglesToAxis( cent->lerpAngles, v );
offset[0] = 2;
offset[1] = 2;
offset[2] = 2;
xoffset[0] = offset[0] * v[0][0] + offset[1] * v[1][0] + offset[2] * v[2][0];
xoffset[1] = offset[0] * v[0][1] + offset[1] * v[1][1] + offset[2] * v[2][1];
xoffset[2] = offset[0] * v[0][2] + offset[1] * v[1][2] + offset[2] * v[2][2];
VectorAdd( origin, xoffset, re->origin );
VectorCopy( re->origin, le->pos.trBase );
if ( CG_PointContents( re->origin, -1 ) & CONTENTS_WATER ) {
waterScale = 0.10f;
}
xvelocity[0] = velocity[0] * v[0][0] + velocity[1] * v[1][0] + velocity[2] * v[2][0];
xvelocity[1] = velocity[0] * v[0][1] + velocity[1] * v[1][1] + velocity[2] * v[2][1];
xvelocity[2] = velocity[0] * v[0][2] + velocity[1] * v[1][2] + velocity[2] * v[2][2];
VectorScale( xvelocity, waterScale, le->pos.trDelta );
AxisCopy( axisDefault, re->axis );
re->shaderTime = cg.time / 1000.0f;
re->reType = RT_SPRITE;
re->radius = 0.25f;
re->customShader = cgs.media.railRingsShader;
le->bounceFactor = 0.3f;
re->shaderRGBA[0] = wi->flashDlightColor[0] * 63;
re->shaderRGBA[1] = wi->flashDlightColor[1] * 63;
re->shaderRGBA[2] = wi->flashDlightColor[2] * 63;
re->shaderRGBA[3] = 63;
le->color[0] = wi->flashDlightColor[0] * 0.2;
le->color[1] = wi->flashDlightColor[1] * 0.2;
le->color[2] = wi->flashDlightColor[2] * 0.2;
le->color[3] = 0.25f;
le->angles.trType = TR_LINEAR;
le->angles.trTime = cg.time;
le->angles.trBase[0] = rand()&31;
le->angles.trBase[1] = rand()&31;
le->angles.trBase[2] = rand()&31;
le->angles.trDelta[0] = 1;
le->angles.trDelta[1] = 0.5;
le->angles.trDelta[2] = 0;
}
/*
==========================
CG_GrappleTrail
==========================
*/
void CG_GrappleTrail( centity_t *ent, const weaponInfo_t *wi ) {
vec3_t origin;
entityState_t *es;
vec3_t forward, up;
refEntity_t beam;
es = &ent->currentState;
BG_EvaluateTrajectory( &es->pos, cg.time, origin );
ent->trailTime = cg.time;
memset( &beam, 0, sizeof( beam ) );
//FIXME adjust for muzzle position
VectorCopy ( cg_entities[ ent->currentState.otherEntityNum ].lerpOrigin, beam.origin );
beam.origin[2] += 26;
AngleVectors( cg_entities[ ent->currentState.otherEntityNum ].lerpAngles, forward, NULL, up );
VectorMA( beam.origin, -6, up, beam.origin );
VectorCopy( origin, beam.oldorigin );
if (Distance( beam.origin, beam.oldorigin ) < 64 )
return; // Don't draw if close
beam.reType = RT_LIGHTNING;
beam.customShader = cgs.media.lightningShader;
AxisClear( beam.axis );
beam.shaderRGBA[0] = 0xff;
beam.shaderRGBA[1] = 0xff;
beam.shaderRGBA[2] = 0xff;
beam.shaderRGBA[3] = 0xff;
trap_R_AddRefEntityToScene( &beam );
}
/*
==========================
CG_GrenadeTrail
==========================
*/
static void CG_GrenadeTrail( centity_t *ent, const weaponInfo_t *wi ) {
CG_RocketTrail( ent, wi );
}
/*
=================
CG_RegisterWeapon
The server says this item is used on this level
=================
*/
void CG_RegisterWeapon( int weaponNum ) {
weaponInfo_t *weaponInfo;
gitem_t *item, *ammo;
char path[MAX_QPATH];
vec3_t mins, maxs;
int i;
weaponInfo = &cg_weapons[weaponNum];
if ( weaponNum == 0 ) {
return;
}
if ( weaponInfo->registered ) {
return;
}
memset( weaponInfo, 0, sizeof( *weaponInfo ) );
weaponInfo->registered = qtrue;
for ( item = bg_itemlist + 1 ; item->classname ; item++ ) {
if ( item->giType == IT_WEAPON && item->giTag == weaponNum ) {
weaponInfo->item = item;
break;
}
}
if ( !item->classname ) {
CG_Error( "Couldn't find weapon %i", weaponNum );
}
CG_RegisterItemVisuals( item - bg_itemlist );
// load cmodel before model so filecache works
weaponInfo->weaponModel = trap_R_RegisterModel( item->world_model[0] );
// calc midpoint for rotation
trap_R_ModelBounds( weaponInfo->weaponModel, mins, maxs );
for ( i = 0 ; i < 3 ; i++ ) {
weaponInfo->weaponMidpoint[i] = mins[i] + 0.5 * ( maxs[i] - mins[i] );
}
weaponInfo->weaponIcon = trap_R_RegisterShader( item->icon );
weaponInfo->ammoIcon = trap_R_RegisterShader( item->icon );
for ( ammo = bg_itemlist + 1 ; ammo->classname ; ammo++ ) {
if ( ammo->giType == IT_AMMO && ammo->giTag == weaponNum ) {
break;
}
}
if ( ammo->classname && ammo->world_model[0] ) {
weaponInfo->ammoModel = trap_R_RegisterModel( ammo->world_model[0] );
}
strcpy( path, item->world_model[0] );
COM_StripExtension( path, path );
strcat( path, "_flash.md3" );
weaponInfo->flashModel = trap_R_RegisterModel( path );
strcpy( path, item->world_model[0] );
COM_StripExtension( path, path );
strcat( path, "_barrel.md3" );
weaponInfo->barrelModel = trap_R_RegisterModel( path );
strcpy( path, item->world_model[0] );
COM_StripExtension( path, path );
strcat( path, "_hand.md3" );
weaponInfo->handsModel = trap_R_RegisterModel( path );
if ( !weaponInfo->handsModel ) {
weaponInfo->handsModel = trap_R_RegisterModel( "models/weapons2/shotgun/shotgun_hand.md3" );
}
weaponInfo->loopFireSound = qfalse;
switch ( weaponNum ) {
case WP_GAUNTLET:
MAKERGB( weaponInfo->flashDlightColor, 0.6f, 0.6f, 1.0f );
weaponInfo->firingSound = trap_S_RegisterSound( "sound/weapons/melee/fstrun.wav", qfalse );
weaponInfo->flashSound[0] = trap_S_RegisterSound( "sound/weapons/melee/fstatck.wav", qfalse );
break;
case WP_LIGHTNING:
MAKERGB( weaponInfo->flashDlightColor, 0.6f, 0.6f, 1.0f );
weaponInfo->readySound = trap_S_RegisterSound( "sound/weapons/melee/fsthum.wav", qfalse );
weaponInfo->firingSound = trap_S_RegisterSound( "sound/weapons/lightning/lg_hum.wav", qfalse );
weaponInfo->flashSound[0] = trap_S_RegisterSound( "sound/weapons/lightning/lg_fire.wav", qfalse );
cgs.media.lightningShader = trap_R_RegisterShader( "lightningBoltNew");
cgs.media.lightningExplosionModel = trap_R_RegisterModel( "models/weaphits/crackle.md3" );
cgs.media.sfx_lghit1 = trap_S_RegisterSound( "sound/weapons/lightning/lg_hit.wav", qfalse );
cgs.media.sfx_lghit2 = trap_S_RegisterSound( "sound/weapons/lightning/lg_hit2.wav", qfalse );
cgs.media.sfx_lghit3 = trap_S_RegisterSound( "sound/weapons/lightning/lg_hit3.wav", qfalse );
break;
case WP_GRAPPLING_HOOK:
MAKERGB( weaponInfo->flashDlightColor, 0.6f, 0.6f, 1.0f );
weaponInfo->missileModel = trap_R_RegisterModel( "models/ammo/rocket/rocket.md3" );
weaponInfo->missileTrailFunc = CG_GrappleTrail;
weaponInfo->missileDlight = 200;
weaponInfo->wiTrailTime = 2000;
weaponInfo->trailRadius = 64;
MAKERGB( weaponInfo->missileDlightColor, 1, 0.75f, 0 );
weaponInfo->readySound = trap_S_RegisterSound( "sound/weapons/melee/fsthum.wav", qfalse );
weaponInfo->firingSound = trap_S_RegisterSound( "sound/weapons/melee/fstrun.wav", qfalse );
break;
#ifdef MISSIONPACK
case WP_CHAINGUN:
weaponInfo->firingSound = trap_S_RegisterSound( "sound/weapons/vulcan/wvulfire.wav", qfalse );
weaponInfo->loopFireSound = qtrue;
MAKERGB( weaponInfo->flashDlightColor, 1, 1, 0 );
weaponInfo->flashSound[0] = trap_S_RegisterSound( "sound/weapons/vulcan/vulcanf1b.wav", qfalse );
weaponInfo->flashSound[1] = trap_S_RegisterSound( "sound/weapons/vulcan/vulcanf2b.wav", qfalse );
weaponInfo->flashSound[2] = trap_S_RegisterSound( "sound/weapons/vulcan/vulcanf3b.wav", qfalse );
weaponInfo->flashSound[3] = trap_S_RegisterSound( "sound/weapons/vulcan/vulcanf4b.wav", qfalse );
weaponInfo->ejectBrassFunc = CG_MachineGunEjectBrass;
cgs.media.bulletExplosionShader = trap_R_RegisterShader( "bulletExplosion" );
break;
#endif
case WP_MACHINEGUN:
MAKERGB( weaponInfo->flashDlightColor, 1, 1, 0 );
weaponInfo->flashSound[0] = trap_S_RegisterSound( "sound/weapons/machinegun/machgf1b.wav", qfalse );
weaponInfo->flashSound[1] = trap_S_RegisterSound( "sound/weapons/machinegun/machgf2b.wav", qfalse );
weaponInfo->flashSound[2] = trap_S_RegisterSound( "sound/weapons/machinegun/machgf3b.wav", qfalse );
weaponInfo->flashSound[3] = trap_S_RegisterSound( "sound/weapons/machinegun/machgf4b.wav", qfalse );
weaponInfo->ejectBrassFunc = CG_MachineGunEjectBrass;
cgs.media.bulletExplosionShader = trap_R_RegisterShader( "bulletExplosion" );
break;
case WP_SHOTGUN:
MAKERGB( weaponInfo->flashDlightColor, 1, 1, 0 );
weaponInfo->flashSound[0] = trap_S_RegisterSound( "sound/weapons/shotgun/sshotf1b.wav", qfalse );
weaponInfo->ejectBrassFunc = CG_ShotgunEjectBrass;
break;
case WP_ROCKET_LAUNCHER:
weaponInfo->missileModel = trap_R_RegisterModel( "models/ammo/rocket/rocket.md3" );
weaponInfo->missileSound = trap_S_RegisterSound( "sound/weapons/rocket/rockfly.wav", qfalse );
weaponInfo->missileTrailFunc = CG_RocketTrail;
weaponInfo->missileDlight = 200;
weaponInfo->wiTrailTime = 2000;
weaponInfo->trailRadius = 64;
MAKERGB( weaponInfo->missileDlightColor, 1, 0.75f, 0 );
MAKERGB( weaponInfo->flashDlightColor, 1, 0.75f, 0 );
weaponInfo->flashSound[0] = trap_S_RegisterSound( "sound/weapons/rocket/rocklf1a.wav", qfalse );
cgs.media.rocketExplosionShader = trap_R_RegisterShader( "rocketExplosion" );
break;
#ifdef MISSIONPACK
case WP_PROX_LAUNCHER:
weaponInfo->missileModel = trap_R_RegisterModel( "models/weaphits/proxmine.md3" );
weaponInfo->missileTrailFunc = CG_GrenadeTrail;
weaponInfo->wiTrailTime = 700;
weaponInfo->trailRadius = 32;
MAKERGB( weaponInfo->flashDlightColor, 1, 0.70f, 0 );
weaponInfo->flashSound[0] = trap_S_RegisterSound( "sound/weapons/proxmine/wstbfire.wav", qfalse );
cgs.media.grenadeExplosionShader = trap_R_RegisterShader( "grenadeExplosion" );
break;
#endif
case WP_GRENADE_LAUNCHER:
weaponInfo->missileModel = trap_R_RegisterModel( "models/ammo/grenade1.md3" );
weaponInfo->missileTrailFunc = CG_GrenadeTrail;
weaponInfo->wiTrailTime = 700;
weaponInfo->trailRadius = 32;
MAKERGB( weaponInfo->flashDlightColor, 1, 0.70f, 0 );
weaponInfo->flashSound[0] = trap_S_RegisterSound( "sound/weapons/grenade/grenlf1a.wav", qfalse );
cgs.media.grenadeExplosionShader = trap_R_RegisterShader( "grenadeExplosion" );
break;
#ifdef MISSIONPACK
case WP_NAILGUN:
weaponInfo->ejectBrassFunc = CG_NailgunEjectBrass;
weaponInfo->missileTrailFunc = CG_NailTrail;
// weaponInfo->missileSound = trap_S_RegisterSound( "sound/weapons/nailgun/wnalflit.wav", qfalse );
weaponInfo->trailRadius = 16;
weaponInfo->wiTrailTime = 250;
weaponInfo->missileModel = trap_R_RegisterModel( "models/weaphits/nail.md3" );
MAKERGB( weaponInfo->flashDlightColor, 1, 0.75f, 0 );
weaponInfo->flashSound[0] = trap_S_RegisterSound( "sound/weapons/nailgun/wnalfire.wav", qfalse );
break;
#endif
case WP_PLASMAGUN:
// weaponInfo->missileModel = cgs.media.invulnerabilityPowerupModel;
weaponInfo->missileTrailFunc = CG_PlasmaTrail;
weaponInfo->missileSound = trap_S_RegisterSound( "sound/weapons/plasma/lasfly.wav", qfalse );
MAKERGB( weaponInfo->flashDlightColor, 0.6f, 0.6f, 1.0f );
weaponInfo->flashSound[0] = trap_S_RegisterSound( "sound/weapons/plasma/hyprbf1a.wav", qfalse );
cgs.media.plasmaExplosionShader = trap_R_RegisterShader( "plasmaExplosion" );
cgs.media.railRingsShader = trap_R_RegisterShader( "railDisc" );
break;
case WP_RAILGUN:
weaponInfo->readySound = trap_S_RegisterSound( "sound/weapons/railgun/rg_hum.wav", qfalse );
MAKERGB( weaponInfo->flashDlightColor, 1, 0.5f, 0 );
weaponInfo->flashSound[0] = trap_S_RegisterSound( "sound/weapons/railgun/railgf1a.wav", qfalse );
cgs.media.railExplosionShader = trap_R_RegisterShader( "railExplosion" );
cgs.media.railRingsShader = trap_R_RegisterShader( "railDisc" );
cgs.media.railCoreShader = trap_R_RegisterShader( "railCore" );
break;
case WP_BFG:
weaponInfo->readySound = trap_S_RegisterSound( "sound/weapons/bfg/bfg_hum.wav", qfalse );
MAKERGB( weaponInfo->flashDlightColor, 1, 0.7f, 1 );
weaponInfo->flashSound[0] = trap_S_RegisterSound( "sound/weapons/bfg/bfg_fire.wav", qfalse );
cgs.media.bfgExplosionShader = trap_R_RegisterShader( "bfgExplosion" );
weaponInfo->missileModel = trap_R_RegisterModel( "models/weaphits/bfg.md3" );
weaponInfo->missileSound = trap_S_RegisterSound( "sound/weapons/rocket/rockfly.wav", qfalse );
break;
default:
MAKERGB( weaponInfo->flashDlightColor, 1, 1, 1 );
weaponInfo->flashSound[0] = trap_S_RegisterSound( "sound/weapons/rocket/rocklf1a.wav", qfalse );
break;
}
}
/*
=================
CG_RegisterItemVisuals
The server says this item is used on this level
=================
*/
void CG_RegisterItemVisuals( int itemNum ) {
itemInfo_t *itemInfo;
gitem_t *item;
if ( itemNum < 0 || itemNum >= bg_numItems ) {
CG_Error( "CG_RegisterItemVisuals: itemNum %d out of range [0-%d]", itemNum, bg_numItems-1 );
}
itemInfo = &cg_items[ itemNum ];
if ( itemInfo->registered ) {
return;
}
item = &bg_itemlist[ itemNum ];
memset( itemInfo, 0, sizeof( &itemInfo ) );
itemInfo->registered = qtrue;
itemInfo->models[0] = trap_R_RegisterModel( item->world_model[0] );
itemInfo->icon = trap_R_RegisterShader( item->icon );
if ( item->giType == IT_WEAPON ) {
CG_RegisterWeapon( item->giTag );
}
//
// powerups have an accompanying ring or sphere
//
if ( item->giType == IT_POWERUP || item->giType == IT_HEALTH ||
item->giType == IT_ARMOR || item->giType == IT_HOLDABLE ) {
if ( item->world_model[1] ) {
itemInfo->models[1] = trap_R_RegisterModel( item->world_model[1] );
}
}
}
/*
========================================================================================
VIEW WEAPON
========================================================================================
*/
/*
=================
CG_MapTorsoToWeaponFrame
=================
*/
static int CG_MapTorsoToWeaponFrame( clientInfo_t *ci, int frame ) {
// change weapon
if ( frame >= ci->animations[TORSO_DROP].firstFrame
&& frame < ci->animations[TORSO_DROP].firstFrame + 9 ) {
return frame - ci->animations[TORSO_DROP].firstFrame + 6;
}
// stand attack
if ( frame >= ci->animations[TORSO_ATTACK].firstFrame
&& frame < ci->animations[TORSO_ATTACK].firstFrame + 6 ) {
return 1 + frame - ci->animations[TORSO_ATTACK].firstFrame;
}
// stand attack 2
if ( frame >= ci->animations[TORSO_ATTACK2].firstFrame
&& frame < ci->animations[TORSO_ATTACK2].firstFrame + 6 ) {
return 1 + frame - ci->animations[TORSO_ATTACK2].firstFrame;
}
return 0;
}
/*
==============
CG_CalculateWeaponPosition
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -