diff --git a/assets/data0_21pure/models/weapons/instagun/instagun.cfg b/assets/data0_21pure/models/weapons/instagun/instagun.cfg index 0dcaa67e29..f7972c5ff6 100644 --- a/assets/data0_21pure/models/weapons/instagun/instagun.cfg +++ b/assets/data0_21pure/models/weapons/instagun/instagun.cfg @@ -8,7 +8,7 @@ handOffset 2.5 -0.26 -3.2 1.2 0.0 0.0 flash 150 300 yes // [time] [radius] [fade] flashColor 0.7 0.1 0.3 -barrel 700 0 // [time] [rotation speed] +barrel 700 0 0 0 // [time] [rotation speed] [initial delay] [recoil delay] 0 29 0 15 // IDLE 31 40 0 15 // ATTACK WEAK diff --git a/source/cgame/cg_ents.cpp b/source/cgame/cg_ents.cpp index 812d505da2..2cba16cb4b 100644 --- a/source/cgame/cg_ents.cpp +++ b/source/cgame/cg_ents.cpp @@ -225,7 +225,8 @@ static void CG_NewPacketEntityState( entity_state_t *state ) // if it's a player and new in PVS, remove the old power time // This is way far from being the right thing. But will make it less bad for now cg_entPModels[state->number].flash_time = cg.time; - cg_entPModels[state->number].barrel_time = cg.time; + cg_entPModels[state->number].barrel.time = cg.time; + cg_entPModels[state->number].barrel2.time = cg.time; } } else // shuffle the last state to previous @@ -634,6 +635,8 @@ static void CG_AddLinkedModel( centity_t *cent ) { if( CG_GrabTag( &tag, ¢->ent, "tag_barrel" ) ) CG_PlaceModelOnTag( &ent, ¢->ent, &tag ); + if( CG_GrabTag( &tag, ¢->ent, "tag_barrel2" ) ) + CG_PlaceModelOnTag( &ent, ¢->ent, &tag ); } else { @@ -913,11 +916,100 @@ static void CG_AddGenericEnt( centity_t *cent ) cent->ent.renderfx |= RF_MINLIGHT; // offset weapon items by their special tag - if( cent->item->type & IT_WEAPON ) - { + if( cent->item->type & IT_WEAPON ) { + orientation_t tag; + const char *weaponModelName; + char barrelPath[MAX_QPATH]; + char barrel2Path[MAX_QPATH]; + char *ext; + CG_PlaceModelOnTag( ¢->ent, ¢->ent, &cgs.weaponItemTag ); + + // Get the weapon model name from the item definition + weaponModelName = cent->item->world_model[0]; + + if( weaponModelName && weaponModelName[0] ) { + // Add barrel model if tag_barrel exists + if( CG_GrabTag( &tag, ¢->ent, "tag_barrel" ) ) { + static entity_t barrel; + struct model_s *barrelModel; + + // Construct barrel model path (e.g., "models/weapons/glauncher/glauncher.md3" -> "models/weapons/glauncher/glauncher_barrel.md3") + Q_strncpyz( barrelPath, weaponModelName, sizeof( barrelPath ) ); + ext = strstr( barrelPath, ".md3" ); + if( ext ) { + *ext = '\0'; + Q_strncatz( barrelPath, "_barrel.md3", sizeof( barrelPath ) ); + } + + // Register the barrel model + barrelModel = R_RegisterModel( barrelPath ); + + if( barrelModel ) { + memset( &barrel, 0, sizeof( entity_t ) ); + barrel.rtype = RT_MODEL; + barrel.scale = cent->ent.scale; + barrel.renderfx = cent->ent.renderfx; + barrel.shaderTime = cent->ent.shaderTime; + Vector4Copy( cent->ent.shaderRGBA, barrel.shaderRGBA ); + barrel.model = barrelModel; + barrel.customShader = NULL; + barrel.customSkin = NULL; + VectorCopy( cent->ent.origin, barrel.origin ); + VectorCopy( cent->ent.origin, barrel.origin2 ); + VectorCopy( cent->ent.lightingOrigin, barrel.lightingOrigin ); + Matrix3_Copy( cent->ent.axis, barrel.axis ); + + CG_PlaceModelOnTag( &barrel, ¢->ent, &tag ); + + if( cent->effects & EF_OUTLINE ) { + CG_AddColoredOutLineEffect( &barrel, cent->effects, cent->outlineColor[0], cent->outlineColor[1], cent->outlineColor[2], cent->outlineColor[3] ); + } + + CG_AddEntityToScene( &barrel ); + } + } + + if( CG_GrabTag( &tag, ¢->ent, "tag_barrel2" ) ) { + static entity_t barrel2; + struct model_s *barrel2Model; + + Q_strncpyz( barrel2Path, weaponModelName, sizeof( barrel2Path ) ); + ext = strstr( barrel2Path, ".md3" ); + if( ext ) { + *ext = '\0'; + Q_strncatz( barrel2Path, "_barrel2.md3", sizeof( barrel2Path ) ); + } + + barrel2Model = R_RegisterModel( barrel2Path ); + + if( barrel2Model ) { + memset( &barrel2, 0, sizeof( entity_t ) ); + barrel2.rtype = RT_MODEL; + barrel2.scale = cent->ent.scale; + barrel2.renderfx = cent->ent.renderfx; + barrel2.shaderTime = cent->ent.shaderTime; + Vector4Copy( cent->ent.shaderRGBA, barrel2.shaderRGBA ); + barrel2.model = barrel2Model; + barrel2.customShader = NULL; + barrel2.customSkin = NULL; + VectorCopy( cent->ent.origin, barrel2.origin ); + VectorCopy( cent->ent.origin, barrel2.origin2 ); + VectorCopy( cent->ent.lightingOrigin, barrel2.lightingOrigin ); + Matrix3_Copy( cent->ent.axis, barrel2.axis ); + + CG_PlaceModelOnTag( &barrel2, ¢->ent, &tag ); + + if( cent->effects & EF_OUTLINE ) { + CG_AddColoredOutLineEffect( &barrel2, cent->effects, cent->outlineColor[0], cent->outlineColor[1], cent->outlineColor[2], cent->outlineColor[3] ); + } + + CG_AddEntityToScene( &barrel2 ); + } + } + } } - } + } else { cent->ent.renderfx |= RF_NOSHADOW; diff --git a/source/cgame/cg_events.cpp b/source/cgame/cg_events.cpp index bd8d73fc03..742ef6c426 100644 --- a/source/cgame/cg_events.cpp +++ b/source/cgame/cg_events.cpp @@ -265,8 +265,10 @@ void CG_LaserBeamEffect( centity_t *cent ) } // enable continuous flash on the weapon owner - if( cg_weaponFlashes->integer ) + if( cg_weaponFlashes->integer && cg_entities[cent->current.number].current.weapon == WEAP_LASERGUN ) cg_entPModels[cent->current.number].flash_time = cg.time + CG_GetWeaponInfo( WEAP_LASERGUN )->flashTime; + else + cg_entPModels[cent->current.number].flash_time = 0; if( sound ) { @@ -379,28 +381,35 @@ static void CG_FireWeaponEvent( int entNum, int weapon, int fireMode ) if( weapon == WEAP_GUNBLADE ) // gunblade is special { - if( fireMode == FIRE_MODE_STRONG ) - { - // light flash + if( fireMode == FIRE_MODE_STRONG ) { if( cg_weaponFlashes->integer && weaponInfo->flashTime ) cg_entPModels[entNum].flash_time = cg.time + weaponInfo->flashTime; + } else { + if( weaponInfo->barrelInfo.time ) { + if( cg_entPModels[entNum].barrel.time <= cg.time ) + cg_entPModels[entNum].barrel.startTime = cg.time; + cg_entPModels[entNum].barrel.time = cg.time + weaponInfo->barrelInfo.time; + } + if( weaponInfo->barrel2Info.time ) { + if( cg_entPModels[entNum].barrel2.time <= cg.time ) + cg_entPModels[entNum].barrel2.startTime = cg.time; + cg_entPModels[entNum].barrel2.time = cg.time + weaponInfo->barrel2Info.time; + } } - else - { - // start barrel rotation or offsetting - if( weaponInfo->barrelTime ) - cg_entPModels[entNum].barrel_time = cg.time + weaponInfo->barrelTime; - } - } - else - { - // light flash + } else { if( cg_weaponFlashes->integer && weaponInfo->flashTime ) cg_entPModels[entNum].flash_time = cg.time + weaponInfo->flashTime; - // start barrel rotation or offsetting - if( weaponInfo->barrelTime ) - cg_entPModels[entNum].barrel_time = cg.time + weaponInfo->barrelTime; + if( weaponInfo->barrelInfo.time ) { + if( cg_entPModels[entNum].barrel.time <= cg.time ) + cg_entPModels[entNum].barrel.startTime = cg.time; + cg_entPModels[entNum].barrel.time = cg.time + weaponInfo->barrelInfo.time; + } + if( weaponInfo->barrel2Info.time ) { + if( cg_entPModels[entNum].barrel2.time <= cg.time ) + cg_entPModels[entNum].barrel2.startTime = cg.time; + cg_entPModels[entNum].barrel2.time = cg.time + weaponInfo->barrel2Info.time; + } } // add animation to the player model @@ -1303,6 +1312,11 @@ void CG_EntityEvent( entity_state_t *ent, int ev, int parm, bool predicted ) CG_ViewWeapon_RefreshAnimation( &cg.weapon ); } + //resets barrel and flash animations upon weapon switch, prevents random anims + memset( &cg_entPModels[ent->number].barrel, 0, sizeof( cg_barrelstate_t ) ); + memset( &cg_entPModels[ent->number].barrel2, 0, sizeof( cg_barrelstate_t ) ); + cg_entPModels[ent->number].flash_time = 0; + if( viewer ) cg.predictedWeaponSwitch = 0; diff --git a/source/cgame/cg_pmodels.cpp b/source/cgame/cg_pmodels.cpp index 2bc109e4d4..e28b69611d 100644 --- a/source/cgame/cg_pmodels.cpp +++ b/source/cgame/cg_pmodels.cpp @@ -54,7 +54,7 @@ void CG_ResetPModels( void ) for( i = 0; i < MAX_EDICTS; i++ ) { - cg_entPModels[i].flash_time = cg_entPModels[i].barrel_time = 0; + cg_entPModels[i].flash_time = cg_entPModels[i].barrel.time = cg_entPModels[i].barrel2.time = 0; memset( &cg_entPModels[i].animState, 0, sizeof( gs_pmodel_animationstate_t ) ); } memset( &cg.weapon, 0, sizeof( cg.weapon ) ); @@ -1320,5 +1320,5 @@ void CG_AddPModel( centity_t *cent ) // add weapon model if( cent->current.weapon && CG_GrabTag( &tag_weapon, ¢->ent, "tag_weapon" ) ) - CG_AddWeaponOnTag( ¢->ent, &tag_weapon, cent->current.weapon, cent->effects, &pmodel->projectionSource, pmodel->flash_time, pmodel->barrel_time ); + CG_AddWeaponOnTag( ¢->ent, &tag_weapon, cent->current.weapon, cent->effects, &pmodel->projectionSource, pmodel->flash_time, cg_entPModels[cent->current.number].barrel, cg_entPModels[cent->current.number].barrel2 ); } diff --git a/source/cgame/cg_pmodels.h b/source/cgame/cg_pmodels.h index f6b2034909..dfa9f0908a 100644 --- a/source/cgame/cg_pmodels.h +++ b/source/cgame/cg_pmodels.h @@ -35,6 +35,14 @@ extern cvar_t *cg_gunbob; extern cvar_t *cg_gun_fov; extern cvar_t *cg_handOffset; +typedef struct { + unsigned int time; + unsigned int startTime; + float speed; + unsigned int initialDelay; + unsigned int recoilDelay; +} cg_barrelstate_t; + enum { WEAPMODEL_NOANIM, @@ -75,9 +83,8 @@ typedef struct weaponinfo_s float flashRadius; vec3_t flashColor; - // barrel - unsigned int barrelTime; - float barrelSpeed; + cg_barrelstate_t barrelInfo; + cg_barrelstate_t barrel2Info; // sfx int num_fire_sounds; @@ -127,7 +134,8 @@ typedef struct orientation_t projectionSource; // for projectiles // weapon. Not sure about keeping it here unsigned int flash_time; - unsigned int barrel_time; + cg_barrelstate_t barrel; + cg_barrelstate_t barrel2; } pmodel_t; @@ -166,7 +174,7 @@ void CG_PModel_ClearEventAnimations( int entNum ); // struct weaponinfo_s *CG_CreateWeaponZeroModel( char *cgs_name ); struct weaponinfo_s *CG_RegisterWeaponModel( char *cgs_name, int weaponTag ); -void CG_AddWeaponOnTag( entity_t *ent, orientation_t *tag, int weapon, int effects, orientation_t *projectionSource, unsigned int flash_time, unsigned int barrel_time ); +void CG_AddWeaponOnTag( entity_t *ent, orientation_t *tag, int weapon, int effects, orientation_t *projectionSource, unsigned int flash_time, cg_barrelstate_t barrel, cg_barrelstate_t barrel2 ); struct weaponinfo_s *CG_GetWeaponInfo( int currentweapon ); //================================================= diff --git a/source/cgame/cg_vweap.cpp b/source/cgame/cg_vweap.cpp index 4c331c284a..2dd783d306 100644 --- a/source/cgame/cg_vweap.cpp +++ b/source/cgame/cg_vweap.cpp @@ -384,5 +384,5 @@ void CG_AddViewWeapon( cg_viewweapon_t *viewweapon ) // 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( &viewweapon->ent, &tag, viewweapon->weapon, cg.effects | EF_OUTLINE, NULL, flash_time, cg_entPModels[viewweapon->POVnum].barrel, cg_entPModels[viewweapon->POVnum].barrel2 ); } diff --git a/source/cgame/cg_wmodels.cpp b/source/cgame/cg_wmodels.cpp index 4b4d4d4ed5..5614297c23 100644 --- a/source/cgame/cg_wmodels.cpp +++ b/source/cgame/cg_wmodels.cpp @@ -39,7 +39,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. weaponinfo_t cg_pWeaponModelInfos[WEAP_TOTAL]; -static const char *wmPartSufix[] = { "", "_expansion", "_barrel", "_flash", "_hand", NULL }; +static const char *wmPartSufix[] = { "", "_expansion", "_barrel", "_barrel2", "_flash", "_hand", NULL }; /* * CG_vWeap_ParseAnimationScript @@ -67,7 +67,8 @@ static bool CG_vWeap_ParseAnimationScript( weaponinfo_t *weaponinfo, const char counter = 1; // reserve 0 for 'no animation' // set some defaults - weaponinfo->barrelSpeed = 0; + weaponinfo->barrelInfo.speed = 0; + weaponinfo->barrel2Info.speed = 0; weaponinfo->flashFade = true; if( !cg_debugWeaponModels->integer ) @@ -113,15 +114,44 @@ static bool CG_vWeap_ParseAnimationScript( weaponinfo_t *weaponinfo, const char if( debug ) CG_Printf( "%sScript: barrel:%s", S_COLOR_BLUE, S_COLOR_WHITE ); + //time + i = atoi( COM_ParseExt( &ptr, false ) ); + weaponinfo->barrelInfo.time = (unsigned int)( i > 0 ? i : 0 ); + // speed + weaponinfo->barrelInfo.speed = atof( COM_ParseExt( &ptr, false ) ); + + // initial delay + i = atoi( COM_ParseExt( &ptr, false ) ); + weaponinfo->barrelInfo.initialDelay = (unsigned int)( i > 0 ? i : 0 ); + + // recoil delay + i = atoi( COM_ParseExt( &ptr, false ) ); + weaponinfo->barrelInfo.recoilDelay = (unsigned int)( i > 0 ? i : 0 ); + + if( debug ) + CG_Printf( "%s time:%i, speed:%.2f\n", S_COLOR_BLUE, (int)weaponinfo->barrelInfo.time, weaponinfo->barrelInfo.speed, S_COLOR_WHITE ); + } + else if( !Q_stricmp( token, "barrel2" ) ) { + if( debug ) + CG_Printf( "%sScript: barrel2:%s", S_COLOR_BLUE, S_COLOR_WHITE ); + // time i = atoi( COM_ParseExt( &ptr, false ) ); - weaponinfo->barrelTime = (unsigned int)( i > 0 ? i : 0 ); + weaponinfo->barrel2Info.time = (unsigned int)( i > 0 ? i : 0 ); // speed - weaponinfo->barrelSpeed = atof( COM_ParseExt( &ptr, false ) ); + weaponinfo->barrel2Info.speed = atof( COM_ParseExt( &ptr, false ) ); + + // initial delay + i = atoi( COM_ParseExt( &ptr, false ) ); + weaponinfo->barrel2Info.initialDelay = (unsigned int)( i > 0 ? i : 0 ); + + // recoil delay + i = atoi( COM_ParseExt( &ptr, false ) ); + weaponinfo->barrel2Info.recoilDelay = (unsigned int)( i > 0 ? i : 0 ); if( debug ) - CG_Printf( "%s time:%i, speed:%.2f\n", S_COLOR_BLUE, (int)weaponinfo->barrelTime, weaponinfo->barrelSpeed, S_COLOR_WHITE ); + CG_Printf( "%s time:%i, speed:%.2f\n", S_COLOR_BLUE, (int)weaponinfo->barrel2Info.time, weaponinfo->barrel2Info.speed, S_COLOR_WHITE ); } else if( !Q_stricmp( token, "flash" ) ) { @@ -277,7 +307,8 @@ static void CG_CreateHandDefaultAnimations( weaponinfo_t *weaponinfo ) { float defaultfps = 15.0f; - weaponinfo->barrelSpeed = 0; // default + weaponinfo->barrelInfo.speed = 0; // default + weaponinfo->barrel2Info.speed = 0; // default wsw hand weaponinfo->firstframe[WEAPMODEL_STANDBY] = 0; @@ -318,7 +349,7 @@ static void CG_CreateHandDefaultAnimations( weaponinfo_t *weaponinfo ) */ static void CG_BuildProjectionOrigin( weaponinfo_t *weaponinfo ) { - orientation_t tag, tag_barrel; + orientation_t tag, tag_barrel, tag_barrel2; static entity_t ent; if( !weaponinfo ) @@ -357,9 +388,17 @@ static void CG_BuildProjectionOrigin( weaponinfo_t *weaponinfo ) tag_barrel.axis, tag.origin, tag.axis ); - return; // succesfully + return; // successfully } } + if( CG_GrabTag( &tag_barrel2, &ent, "tag_barrel2" ) && weaponinfo->model[BARREL2] ) { + // 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[BARREL2]; + CG_SetBoneposesForTemporaryEntity( &ent ); + } } // doesn't have a weapon model, or the weapon model doesn't have a tag @@ -554,7 +593,7 @@ struct weaponinfo_s *CG_GetWeaponInfo( int weapon ) * * 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 ) +void CG_AddWeaponOnTag( entity_t *ent, orientation_t *tag, int weaponid, int effects, orientation_t *projectionSource, unsigned int flash_time, cg_barrelstate_t barrel, cg_barrelstate_t barrel2 ) { entity_t weapon; weaponinfo_t *weaponInfo; @@ -632,45 +671,116 @@ void CG_AddWeaponOnTag( entity_t *ent, orientation_t *tag, int weaponid, int eff } } - // barrel - if( weaponInfo->model[BARREL] ) - { - if( CG_GrabTag( tag, &weapon, "tag_barrel" ) ) - { +// 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, ent->shaderRGBA[3] ); - 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] = anglemod( 360.0f * weaponInfo->barrelSpeed * intensity * intensity ); - - // Check for tag_recoil - if( CG_GrabTag( &barrel_recoiled, &weapon, "tag_recoil" ) ) - VectorLerp( tag->origin, intensity, barrel_recoiled.origin, tag->origin ); + vec3_t placementOrigin; + entity_t barrelEnt; + memset( &barrelEnt, 0, sizeof( barrelEnt ) ); + Vector4Set( barrelEnt.shaderRGBA, 255, 255, 255, ent->shaderRGBA[3] ); + barrelEnt.model = weaponInfo->model[BARREL]; + barrelEnt.scale = ent->scale; + barrelEnt.renderfx = ent->renderfx; + barrelEnt.frame = 0; + barrelEnt.oldframe = 0; + + VectorCopy( tag->origin, placementOrigin ); + + if( barrel.time > cg.time ) { + unsigned int elapsed = cg.time - barrel.startTime; + unsigned int timeRemaining = barrel.time - cg.time; + + if( elapsed < weaponInfo->barrelInfo.initialDelay ) { + intensity = 0.0f; + } else { + unsigned int activeElapsed = elapsed - weaponInfo->barrelInfo.initialDelay; + unsigned int activeDuration = weaponInfo->barrelInfo.time - weaponInfo->barrelInfo.initialDelay; + + intensity = (float)timeRemaining / (float)weaponInfo->barrelInfo.time; + rotangles[2] = anglemod( 360.0f * weaponInfo->barrelInfo.speed * intensity * intensity ); + + if( CG_GrabTag( &barrel_recoiled, &weapon, "tag_recoil" ) ) { + float recoilIntensity; + + if( activeElapsed < weaponInfo->barrelInfo.recoilDelay ) { + recoilIntensity = 1.0f; + } else { + unsigned int recoilElapsed = activeElapsed - weaponInfo->barrelInfo.recoilDelay; + unsigned int recoilDuration = activeDuration - weaponInfo->barrelInfo.recoilDelay; + recoilIntensity = recoilDuration > 0 ? 1.0f - (float)recoilElapsed / (float)recoilDuration : 0.0f; + } + + clamp( recoilIntensity, 0.0f, 1.0f ); + VectorLerp( tag->origin, recoilIntensity, barrel_recoiled.origin, placementOrigin ); + } + } } - AnglesToAxis( rotangles, barrel.axis ); - - // barrel requires special tagging - CG_PlaceRotatedModelOnTag( &barrel, &weapon, tag ); + VectorCopy( placementOrigin, tag->origin ); + AnglesToAxis( rotangles, barrelEnt.axis ); + CG_PlaceRotatedModelOnTag( &barrelEnt, &weapon, tag ); + CG_AddColoredOutLineEffect( &barrelEnt, effects, 0, 0, 0, ent->shaderRGBA[3] ); + if( !( effects & EF_RACEGHOST ) ) + CG_AddEntityToScene( &barrelEnt ); + CG_AddShellEffects( &barrelEnt, effects ); + } + } - CG_AddColoredOutLineEffect( &barrel, effects, 0, 0, 0, ent->shaderRGBA[3] ); + // barrel 2 Added for additional rotating detail (eg: double chaingun) + if( weaponInfo->model[BARREL2] ) { + if( CG_GrabTag( tag, &weapon, "tag_barrel2" ) ) { + orientation_t barrel_recoiled; + vec3_t rotangles = { 0, 0, 0 }; + vec3_t placementOrigin; + entity_t barrel2Ent; + memset( &barrel2Ent, 0, sizeof( barrel2Ent ) ); + Vector4Set( barrel2Ent.shaderRGBA, 255, 255, 255, ent->shaderRGBA[3] ); + barrel2Ent.model = weaponInfo->model[BARREL2]; + barrel2Ent.scale = ent->scale; + barrel2Ent.renderfx = ent->renderfx; + barrel2Ent.frame = 0; + barrel2Ent.oldframe = 0; + + VectorCopy( tag->origin, placementOrigin ); + + if( barrel2.time > cg.time ) { + unsigned int elapsed = cg.time - barrel2.startTime; + unsigned int timeRemaining = barrel2.time - cg.time; + + if( elapsed < weaponInfo->barrel2Info.initialDelay ) { + intensity = 0.0f; + } else { + unsigned int activeElapsed = elapsed - weaponInfo->barrel2Info.initialDelay; + unsigned int activeDuration = weaponInfo->barrel2Info.time - weaponInfo->barrel2Info.initialDelay; + intensity = (float)timeRemaining / (float)weaponInfo->barrel2Info.time; + rotangles[2] = anglemod( 360.0f * weaponInfo->barrel2Info.speed * intensity * intensity ); + + if( CG_GrabTag( &barrel_recoiled, &weapon, "tag_recoil2" ) ) { + float recoilIntensity; + + if( activeElapsed < weaponInfo->barrel2Info.recoilDelay ) { + recoilIntensity = 1.0f; + } else { + unsigned int recoilElapsed = activeElapsed - weaponInfo->barrel2Info.recoilDelay; + unsigned int recoilDuration = activeDuration - weaponInfo->barrel2Info.recoilDelay; + recoilIntensity = recoilDuration > 0 ? 1.0f - (float)recoilElapsed / (float)recoilDuration : 0.0f; + } + + clamp( recoilIntensity, 0.0f, 1.0f ); + VectorLerp( tag->origin, recoilIntensity, barrel_recoiled.origin, placementOrigin ); + } + } + } + VectorCopy( placementOrigin, tag->origin ); + AnglesToAxis( rotangles, barrel2Ent.axis ); + CG_PlaceRotatedModelOnTag( &barrel2Ent, &weapon, tag ); + CG_AddColoredOutLineEffect( &barrel2Ent, effects, 0, 0, 0, ent->shaderRGBA[3] ); if( !( effects & EF_RACEGHOST ) ) - CG_AddEntityToScene( &barrel ); // skelmod - - CG_AddShellEffects( &barrel, effects ); + CG_AddEntityToScene( &barrel2Ent ); + CG_AddShellEffects( &barrel2Ent, effects ); } } diff --git a/source/gameshared/gs_public.h b/source/gameshared/gs_public.h index d5b2edf1e3..83c9ec507f 100644 --- a/source/gameshared/gs_public.h +++ b/source/gameshared/gs_public.h @@ -372,6 +372,7 @@ enum WEAPON, EXPANSION, BARREL, + BARREL2, FLASH, HAND,