/* * CG_BuildProjectionOrigin * store the orientation_t closer to the tag_flash we can create, * or create one using an offset we consider acceptable. * NOTE: This tag will ignore weapon models animations. You'd have to * do it in realtime to use it with animations. Or be careful on not * moving the weapon too much */ static void CG_BuildProjectionOrigin( weaponinfo_t *weaponinfo ) { orientation_t tag, tag_barrel; static entity_t ent; if( !weaponinfo ) return; if( weaponinfo->model[WEAPON] ) { // assign the model to an entity_t, so we can build boneposes memset( &ent, 0, sizeof( ent ) ); ent.rtype = RT_MODEL; ent.scale = 1.0f; ent.model = weaponinfo->model[WEAPON]; CG_SetBoneposesForTemporaryEntity( &ent ); // assigns and builds the skeleton so we can use grabtag // try getting the tag_flash from the weapon model if( CG_GrabTag( &weaponinfo->tag_projectionsource, &ent, "tag_flash" ) ) return; // succesfully // if it didn't work, try getting it from the barrel model if( CG_GrabTag( &tag_barrel, &ent, "tag_barrel" ) && weaponinfo->model[BARREL] ) { // assign the model to an entity_t, so we can build boneposes memset( &ent, 0, sizeof( ent ) ); ent.rtype = RT_MODEL; ent.scale = 1.0f; ent.model = weaponinfo->model[BARREL]; CG_SetBoneposesForTemporaryEntity( &ent ); if( CG_GrabTag( &tag, &ent, "tag_flash" ) && weaponinfo->model[BARREL] ) { VectorCopy( vec3_origin, weaponinfo->tag_projectionsource.origin ); Matrix3_Identity( weaponinfo->tag_projectionsource.axis ); CG_MoveToTag( weaponinfo->tag_projectionsource.origin, weaponinfo->tag_projectionsource.axis, tag_barrel.origin, tag_barrel.axis, tag.origin, tag.axis ); return; // succesfully } } } // doesn't have a weapon model, or the weapon model doesn't have a tag VectorSet( weaponinfo->tag_projectionsource.origin, 16, 0, 8 ); Matrix3_Identity( weaponinfo->tag_projectionsource.axis ); }
/* * CG_AddViewWeapon */ void CG_AddViewWeapon( cg_viewweapon_t *viewweapon ) { orientation_t tag; unsigned int flash_time = 0; if( !cg.view.drawWeapon || viewweapon->weapon == WEAP_NONE ) return; // update the other origins VectorCopy( viewweapon->ent.origin, viewweapon->ent.origin2 ); VectorCopy( cg_entities[viewweapon->POVnum].ent.lightingOrigin, viewweapon->ent.lightingOrigin ); CG_AddColoredOutLineEffect( &viewweapon->ent, cg.effects, 0, 0, 0, 255 ); CG_AddEntityToScene( &viewweapon->ent ); CG_AddShellEffects( &viewweapon->ent, cg.effects ); if( cg_weaponFlashes->integer == 2 ) flash_time = cg_entPModels[viewweapon->POVnum].flash_time; // add attached weapon if( CG_GrabTag( &tag, &viewweapon->ent, "tag_weapon" ) ) CG_AddWeaponOnTag( &viewweapon->ent, &tag, viewweapon->weapon, cg.effects|EF_OUTLINE, NULL, flash_time, cg_entPModels[viewweapon->POVnum].barrel_time ); }
/* * CG_AddWeaponOnTag * * Add weapon model(s) positioned at the tag */ void CG_AddWeaponOnTag( entity_t *ent, orientation_t *tag, int weaponid, int effects, orientation_t *projectionSource, unsigned int flash_time, unsigned int barrel_time ) { entity_t weapon; weaponinfo_t *weaponInfo; float intensity; //don't try without base model if( !ent->model ) return; //don't try without a tag if( !tag ) return; weaponInfo = CG_GetWeaponInfo( weaponid ); if( !weaponInfo ) return; //if( ent->renderfx & RF_WEAPONMODEL ) // effects &= ~EF_RACEGHOST; //weapon memset( &weapon, 0, sizeof( weapon ) ); Vector4Set( weapon.shaderRGBA, 255, 255, 255, 255 ); weapon.scale = ent->scale; weapon.renderfx = ent->renderfx; weapon.frame = 0; weapon.oldframe = 0; weapon.model = weaponInfo->model[WEAPON]; CG_PlaceModelOnTag( &weapon, ent, tag ); CG_AddColoredOutLineEffect( &weapon, effects, 0, 0, 0, 255 ); if( !( effects & EF_RACEGHOST ) ) CG_AddEntityToScene( &weapon ); if( !weapon.model ) return; CG_AddShellEffects( &weapon, effects ); // update projection source if( projectionSource != NULL ) { VectorCopy( vec3_origin, projectionSource->origin ); Matrix3_Copy( axis_identity, projectionSource->axis ); CG_MoveToTag( projectionSource->origin, projectionSource->axis, weapon.origin, weapon.axis, weaponInfo->tag_projectionsource.origin, weaponInfo->tag_projectionsource.axis ); } //expansion if( ( effects & EF_STRONG_WEAPON ) && weaponInfo->model[EXPANSION] ) { if( CG_GrabTag( tag, &weapon, "tag_expansion" ) ) { entity_t expansion; memset( &expansion, 0, sizeof( expansion ) ); Vector4Set( expansion.shaderRGBA, 255, 255, 255, 255 ); expansion.model = weaponInfo->model[EXPANSION]; expansion.scale = ent->scale; expansion.renderfx = ent->renderfx; expansion.frame = 0; expansion.oldframe = 0; CG_PlaceModelOnTag( &expansion, &weapon, tag ); CG_AddColoredOutLineEffect( &expansion, effects, 0, 0, 0, 255 ); if( !( effects & EF_RACEGHOST ) ) CG_AddEntityToScene( &expansion ); // skelmod CG_AddShellEffects( &expansion, effects ); } } // barrel if( weaponInfo->model[BARREL] ) { if( CG_GrabTag( tag, &weapon, "tag_barrel" ) ) { orientation_t barrel_recoiled; vec3_t rotangles = { 0, 0, 0 }; entity_t barrel; memset( &barrel, 0, sizeof( barrel ) ); Vector4Set( barrel.shaderRGBA, 255, 255, 255, 255 ); barrel.model = weaponInfo->model[BARREL]; barrel.scale = ent->scale; barrel.renderfx = ent->renderfx; barrel.frame = 0; barrel.oldframe = 0; // rotation if( barrel_time > cg.time ) { intensity = (float)( barrel_time - cg.time ) / (float)weaponInfo->barrelTime; rotangles[2] = ( 360.0f * weaponInfo->barrelSpeed * intensity * intensity ); while( rotangles[2] > 360 ) rotangles[2] -= 360; // Check for tag_recoil if( CG_GrabTag( &barrel_recoiled, &weapon, "tag_recoil" ) ) VectorLerp( tag->origin, intensity, barrel_recoiled.origin, tag->origin ); } AnglesToAxis( rotangles, barrel.axis ); // barrel requires special tagging CG_PlaceRotatedModelOnTag( &barrel, &weapon, tag ); CG_AddColoredOutLineEffect( &barrel, effects, 0, 0, 0, 255 ); if( !( effects & EF_RACEGHOST ) ) CG_AddEntityToScene( &barrel ); // skelmod CG_AddShellEffects( &barrel, effects ); } } if( flash_time < cg.time ) return; // flash if( !CG_GrabTag( tag, &weapon, "tag_flash" ) ) return; if( weaponInfo->model[FLASH] ) { entity_t flash; qbyte c; if( weaponInfo->flashFade ) { intensity = (float)( flash_time - cg.time )/(float)weaponInfo->flashTime; c = ( qbyte )( 255 * intensity ); } else { intensity = 1.0f; c = 255; } memset( &flash, 0, sizeof( flash ) ); Vector4Set( flash.shaderRGBA, c, c, c, c ); flash.model = weaponInfo->model[FLASH]; flash.scale = ent->scale; flash.renderfx = ent->renderfx | RF_NOSHADOW; flash.frame = 0; flash.oldframe = 0; CG_PlaceModelOnTag( &flash, &weapon, tag ); if( !( effects & EF_RACEGHOST ) ) CG_AddEntityToScene( &flash ); CG_AddLightToScene( flash.origin, weaponInfo->flashRadius * intensity, weaponInfo->flashColor[0], weaponInfo->flashColor[1], weaponInfo->flashColor[2] ); } }
/* * CG_CalcViewWeapon */ void CG_CalcViewWeapon( cg_viewweapon_t *viewweapon ) { orientation_t tag; weaponinfo_t *weaponInfo; vec3_t gunAngles; vec3_t gunOffset; float fallfrac, fallkick; CG_ViewWeapon_RefreshAnimation( viewweapon ); //if( cg.view.thirdperson ) // return; weaponInfo = CG_GetWeaponInfo( viewweapon->weapon ); viewweapon->ent.model = weaponInfo->model[HAND]; viewweapon->ent.renderfx = RF_MINLIGHT|RF_WEAPONMODEL|RF_FORCENOLOD|(cg_shadows->integer < 2 ? RF_NOSHADOW : 0); viewweapon->ent.scale = 1.0f; viewweapon->ent.customShader = NULL; viewweapon->ent.customSkin = NULL; viewweapon->ent.rtype = RT_MODEL; Vector4Set( viewweapon->ent.shaderRGBA, 255, 255, 255, 255 ); // calculate the entity position #if 1 VectorCopy( cg.view.origin, viewweapon->ent.origin ); #else VectorCopy( cg.predictedPlayerState.pmove.origin, viewweapon->ent.origin ); viewweapon->ent.origin[2] += cg.predictedPlayerState.viewheight; #endif // weapon config offsets VectorAdd( weaponInfo->handpositionAngles, cg.predictedPlayerState.viewangles, gunAngles ); gunOffset[FORWARD] = cg_gunz->value + weaponInfo->handpositionOrigin[FORWARD]; gunOffset[RIGHT] = cg_gunx->value + weaponInfo->handpositionOrigin[RIGHT]; gunOffset[UP] = cg_guny->value + weaponInfo->handpositionOrigin[UP]; // hand cvar offset if( cgs.demoPlaying ) { if( hand->integer == 0 ) gunOffset[RIGHT] += cg_handOffset->value; else if( hand->integer == 1 ) gunOffset[RIGHT] -= cg_handOffset->value; } else { if( cgs.clientInfo[cg.view.POVent-1].hand == 0 ) gunOffset[RIGHT] += cg_handOffset->value; else if( cgs.clientInfo[cg.view.POVent-1].hand == 1 ) gunOffset[RIGHT] -= cg_handOffset->value; } // fallkick offset if( cg.weapon.fallEff_Time > cg.time ) { fallfrac = (float)( cg.time - cg.weapon.fallEff_rebTime ) / (float)( cg.weapon.fallEff_Time - cg.weapon.fallEff_rebTime ); fallkick = sin( DEG2RAD( fallfrac*180 ) ) * ( ( cg.weapon.fallEff_Time - cg.weapon.fallEff_rebTime ) * 0.01f ); } else { cg.weapon.fallEff_Time = cg.weapon.fallEff_rebTime = 0; fallkick = fallfrac = 0; } gunOffset[UP] -= fallkick; // apply the offsets #if 1 VectorMA( viewweapon->ent.origin, gunOffset[FORWARD], &cg.view.axis[AXIS_FORWARD], viewweapon->ent.origin ); VectorMA( viewweapon->ent.origin, gunOffset[RIGHT], &cg.view.axis[AXIS_RIGHT], viewweapon->ent.origin ); VectorMA( viewweapon->ent.origin, gunOffset[UP], &cg.view.axis[AXIS_UP], viewweapon->ent.origin ); #else Matrix3_FromAngles( cg.predictedPlayerState.viewangles, offsetAxis ); VectorMA( viewweapon->ent.origin, gunOffset[FORWARD], &offsetAxis[AXIS_FORWARD], viewweapon->ent.origin ); VectorMA( viewweapon->ent.origin, gunOffset[RIGHT], &offsetAxis[AXIS_RIGHT], viewweapon->ent.origin ); VectorMA( viewweapon->ent.origin, gunOffset[UP], &offsetAxis[AXIS_UP], viewweapon->ent.origin ); #endif // add angles effects CG_ViewWeapon_AddAngleEffects( gunAngles ); // finish AnglesToAxis( gunAngles, viewweapon->ent.axis ); if( cg_gun_fov->integer && !cg.predictedPlayerState.pmove.stats[PM_STAT_ZOOMTIME] ) { float gun_fov = bound( 20, cg_gun_fov->value, 160 ); float fracWeapFOV = ( 1.0f / cg.view.fracDistFOV ) * tan( gun_fov * ( M_PI/180 ) * 0.5f ); VectorScale( &viewweapon->ent.axis[AXIS_FORWARD], fracWeapFOV, &viewweapon->ent.axis[AXIS_FORWARD] ); } // if the player doesn't want to view the weapon we still have to build the projection source if( CG_GrabTag( &tag, &viewweapon->ent, "tag_weapon" ) ) CG_ViewWeapon_UpdateProjectionSource( viewweapon->ent.origin, viewweapon->ent.axis, tag.origin, tag.axis ); else CG_ViewWeapon_UpdateProjectionSource( viewweapon->ent.origin, viewweapon->ent.axis, vec3_origin, axis_identity ); }