diff --git a/src/game/client/tf/c_tf_projectile_energy_ball.cpp b/src/game/client/tf/c_tf_projectile_energy_ball.cpp index 56f53181abc..2af348fa1ca 100644 --- a/src/game/client/tf/c_tf_projectile_energy_ball.cpp +++ b/src/game/client/tf/c_tf_projectile_energy_ball.cpp @@ -12,6 +12,7 @@ #include "collisionutils.h" #include "util_shared.h" #include "tf_weapon_rocketlauncher.h" +#include "tf_gamerules.h" //----------------------------------------------------------------------------- IMPLEMENT_NETWORKCLASS_ALIASED( TFProjectile_EnergyBall, DT_TFProjectile_EnergyBall ) @@ -56,13 +57,44 @@ void C_TFProjectile_EnergyBall::CreateTrails( void ) } bool bDeflected = m_iCachedDeflect != GetDeflected(); + bool bUsingHalloween = false; + + // Check for Halloween spell + int iHalloweenSpell = 0; + if ( TF_IsHolidayActive( kHoliday_HalloweenOrFullMoon ) ) + { + CALL_ATTRIB_HOOK_INT_ON_OTHER( GetOriginalLauncher(), iHalloweenSpell, halloween_pumpkin_explosions ); + } if ( pEffect == NULL ) { ParticleProp()->Init( this ); - pEffect = ParticleProp()->Create( GetTrailParticleName(), PATTACH_ABSORIGIN_FOLLOW, 0 ); - if ( pEffect ) + // Handle Halloween spell particles + if ( iHalloweenSpell > 0 ) + { + const char *pszHalloweenParticle = NULL; + + // Use charged or normal Halloween particles based on shot type + if ( m_bChargedShot ) + { + pszHalloweenParticle = ( GetTeamNumber() == TF_TEAM_RED ) ? "drg_cow_rockettrail_charged_halloween" : "drg_cow_rockettrail_charged_halloween_blue"; + } + else + { + pszHalloweenParticle = ( GetTeamNumber() == TF_TEAM_RED ) ? "drg_cow_rockettrail_halloween" : "drg_cow_rockettrail_halloween_blue"; + } + + pEffect = ParticleProp()->Create( pszHalloweenParticle, PATTACH_ABSORIGIN_FOLLOW, 0 ); + bUsingHalloween = true; + } + else + { + // Use standard Cow Mangler trails + pEffect = ParticleProp()->Create( GetTrailParticleName(), PATTACH_ABSORIGIN_FOLLOW, 0 ); + } + + if ( pEffect && !bUsingHalloween ) { if ( bDeflected ) { @@ -95,4 +127,4 @@ const char *C_TFProjectile_EnergyBall::GetTrailParticleName( void ) return ( GetTeamNumber() == TF_TEAM_RED ) ? "drg_cow_rockettrail_charged" : "drg_cow_rockettrail_charged_blue"; else return ( GetTeamNumber() == TF_TEAM_RED ) ? "drg_cow_rockettrail_normal" : "drg_cow_rockettrail_normal_blue"; -} \ No newline at end of file +} diff --git a/src/game/client/tf/c_tf_projectile_rocket.cpp b/src/game/client/tf/c_tf_projectile_rocket.cpp index 3e435a629f9..3c6516ce20d 100644 --- a/src/game/client/tf/c_tf_projectile_rocket.cpp +++ b/src/game/client/tf/c_tf_projectile_rocket.cpp @@ -47,100 +47,114 @@ void C_TFProjectile_Rocket::OnDataChanged(DataUpdateType_t updateType) //----------------------------------------------------------------------------- void C_TFProjectile_Rocket::CreateTrails( void ) { - if ( IsDormant() ) - return; - - bool bUsingCustom = false; - - if ( pEffect ) - { - ParticleProp()->StopEmission( pEffect ); - pEffect = NULL; - } - - int iAttachment = LookupAttachment( "trail" ); - if ( iAttachment == INVALID_PARTICLE_ATTACHMENT ) - return; - - if ( enginetrace->GetPointContents( GetAbsOrigin() ) & MASK_WATER ) - { - ParticleProp()->Create( "rockettrail_underwater", PATTACH_POINT_FOLLOW, "trail" ); - bUsingCustom = true; - } - else if ( GetTeamNumber() == TEAM_UNASSIGNED ) - { - ParticleProp()->Create( "rockettrail_underwater", PATTACH_POINT_FOLLOW, "trail" ); - bUsingCustom = true; - } - else - { - // Halloween Spell Effect Check - int iHalloweenSpell = 0; - // if the owner is a Sentry, Check its owner - CBaseObject *pSentry = GetOwnerEntity() && GetOwnerEntity()->IsBaseObject() ? assert_cast( GetOwnerEntity() ) : NULL; - if ( TF_IsHolidayActive( kHoliday_HalloweenOrFullMoon ) ) - { - if ( pSentry ) - { - CALL_ATTRIB_HOOK_INT_ON_OTHER( pSentry->GetOwner(), iHalloweenSpell, halloween_pumpkin_explosions ); - } - else - { - CALL_ATTRIB_HOOK_INT_ON_OTHER( GetOwnerEntity(), iHalloweenSpell, halloween_pumpkin_explosions ); - } - } - - // Mini rockets from airstrike RL - if ( iHalloweenSpell > 0 ) - { - ParticleProp()->Create( "halloween_rockettrail", PATTACH_POINT_FOLLOW, iAttachment ); - bUsingCustom = true; - } - else if ( !pSentry ) - { - if ( GetLauncher() ) - { - int iMiniRocket = 0; - CALL_ATTRIB_HOOK_INT_ON_OTHER( GetLauncher(), iMiniRocket, mini_rockets ); - if ( iMiniRocket ) - { - ParticleProp()->Create( "rockettrail_airstrike", PATTACH_POINT_FOLLOW, iAttachment ); - bUsingCustom = true; - - // rockettrail_airstrike_line - CTFPlayer *pPlayer = ToTFPlayer( GetOwnerEntity() ); - if ( pPlayer && pPlayer->m_Shared.InCond( TF_COND_BLASTJUMPING ) ) - { - ParticleProp()->Create( "rockettrail_airstrike_line", PATTACH_POINT_FOLLOW, iAttachment ); - } - } - } - } - } - - if ( !bUsingCustom ) - { - if ( GetTrailParticleName() ) - { - ParticleProp()->Create( GetTrailParticleName(), PATTACH_POINT_FOLLOW, iAttachment ); - } - } - - if ( m_bCritical ) - { - switch( GetTeamNumber() ) - { - case TF_TEAM_BLUE: - pEffect = ParticleProp()->Create( "critical_rocket_blue", PATTACH_ABSORIGIN_FOLLOW ); - break; - case TF_TEAM_RED: - pEffect = ParticleProp()->Create( "critical_rocket_red", PATTACH_ABSORIGIN_FOLLOW ); - break; - default: - pEffect = ParticleProp()->Create( "eyeboss_projectile", PATTACH_ABSORIGIN_FOLLOW ); - break; - } - } + if ( IsDormant() ) + return; + + bool bUsingCustom = false; + + if ( pEffect ) + { + ParticleProp()->StopEmission( pEffect ); + pEffect = NULL; + } + + int iAttachment = LookupAttachment( "trail" ); + if ( iAttachment == INVALID_PARTICLE_ATTACHMENT ) + return; + + // Check for Halloween spell first regardless of environment + int iHalloweenSpell = 0; + // if the owner is a Sentry, Check its owner + CBaseObject *pSentry = GetOriginalLauncher() && GetOriginalLauncher()->IsBaseObject() ? assert_cast( GetOriginalLauncher() ) : NULL; + + if ( TF_IsHolidayActive( kHoliday_HalloweenOrFullMoon ) ) + { + if ( pSentry ) + { + CALL_ATTRIB_HOOK_INT_ON_OTHER( pSentry->GetOwner(), iHalloweenSpell, halloween_pumpkin_explosions ); + } + else + { + CALL_ATTRIB_HOOK_INT_ON_OTHER( GetOriginalLauncher(), iHalloweenSpell, halloween_pumpkin_explosions ); + } + } + + bool bIsUnderwater = enginetrace->GetPointContents( GetAbsOrigin() ) & MASK_WATER; + + // Handle Halloween rockets (both underwater and normal) + if ( iHalloweenSpell > 0 ) + { + if ( bIsUnderwater ) + { + // This is the new particle effect the game searches for when a Pumpkin bombs rocket is fired underwater, something that was missing entirely before. The particle in question is stored within the rockettrail.pcf file under the halloween_rockettrail_underwater name. + ParticleProp()->Create( "halloween_rockettrail_underwater", PATTACH_POINT_FOLLOW, iAttachment ); + } + else + { + // Use the existing Halloween particle + ParticleProp()->Create( "halloween_rockettrail", PATTACH_POINT_FOLLOW, iAttachment ); + } + bUsingCustom = true; + } + // Handle standard underwater rockets + else if ( bIsUnderwater ) + { + ParticleProp()->Create( "rockettrail_underwater", PATTACH_POINT_FOLLOW, "trail" ); + bUsingCustom = true; + } + else if ( GetTeamNumber() == TEAM_UNASSIGNED ) + { + ParticleProp()->Create( "rockettrail_underwater", PATTACH_POINT_FOLLOW, "trail" ); + bUsingCustom = true; + } + else + { + // Mini rockets from airstrike RL + if ( !pSentry ) + { + if ( GetOriginalLauncher() ) + { + int iMiniRocket = 0; + CALL_ATTRIB_HOOK_INT_ON_OTHER( GetOriginalLauncher(), iMiniRocket, mini_rockets ); + if ( iMiniRocket ) + { + ParticleProp()->Create( "rockettrail_airstrike", PATTACH_POINT_FOLLOW, iAttachment ); + bUsingCustom = true; + + // rockettrail_airstrike_line + CTFPlayer *pPlayer = ToTFPlayer( GetOwnerEntity() ); + if ( pPlayer && pPlayer->m_Shared.InCond( TF_COND_BLASTJUMPING ) ) + { + ParticleProp()->Create( "rockettrail_airstrike_line", PATTACH_POINT_FOLLOW, iAttachment ); + } + } + } + } + } + + if ( !bUsingCustom ) + { + if ( GetTrailParticleName() ) + { + ParticleProp()->Create( GetTrailParticleName(), PATTACH_POINT_FOLLOW, iAttachment ); + } + } + + if ( m_bCritical ) + { + switch( GetTeamNumber() ) + { + case TF_TEAM_BLUE: + pEffect = ParticleProp()->Create( "critical_rocket_blue", PATTACH_ABSORIGIN_FOLLOW ); + break; + case TF_TEAM_RED: + pEffect = ParticleProp()->Create( "critical_rocket_red", PATTACH_ABSORIGIN_FOLLOW ); + break; + default: + pEffect = ParticleProp()->Create( "eyeboss_projectile", PATTACH_ABSORIGIN_FOLLOW ); + break; + } + } } diff --git a/src/game/server/tf/tf_projectile_energy_ball.cpp b/src/game/server/tf/tf_projectile_energy_ball.cpp index fdb8d624cf9..c69483d43c3 100644 --- a/src/game/server/tf/tf_projectile_energy_ball.cpp +++ b/src/game/server/tf/tf_projectile_energy_ball.cpp @@ -135,6 +135,10 @@ void CTFProjectile_EnergyBall::Precache() PrecacheParticleSystem( "drg_cow_rockettrail_charged_blue" ); PrecacheParticleSystem( "drg_cow_rockettrail_normal" ); PrecacheParticleSystem( "drg_cow_rockettrail_normal_blue" ); + PrecacheParticleSystem( "drg_cow_rockettrail_halloween" ); + PrecacheParticleSystem( "drg_cow_rockettrail_charged_halloween" ); + PrecacheParticleSystem( "drg_cow_rockettrail_halloween_blue" ); + PrecacheParticleSystem( "drg_cow_rockettrail_charged_halloween_blue" ); PrecacheModel( ENERGY_BALL_MODEL ); @@ -341,6 +345,27 @@ void CTFProjectile_EnergyBall::Explode( trace_t *pTrace, CBaseEntity *pOther ) //----------------------------------------------------------------------------- const char *CTFProjectile_EnergyBall::GetExplosionParticleName( void ) { + // Check for Halloween spell + int iHalloweenSpell = 0; + if ( TF_IsHolidayActive( kHoliday_HalloweenOrFullMoon ) ) + { + CALL_ATTRIB_HOOK_INT_ON_OTHER( GetOriginalLauncher(), iHalloweenSpell, halloween_pumpkin_explosions ); + } + + // Use Halloween explosion particles if spell is active + if ( iHalloweenSpell > 0 ) + { + if ( m_bChargedShot ) + { + return ( GetTeamNumber() == TF_TEAM_RED ) ? "drg_cow_explosioncore_charged_halloween" : "drg_cow_explosioncore_charged_halloween_blue"; + } + else + { + return ( GetTeamNumber() == TF_TEAM_RED ) ? "drg_cow_explosioncore_normal_halloween" : "drg_cow_explosioncore_normal_halloween_blue"; + } + } + + // Standard Cow Mangler explosions if ( m_bChargedShot ) { return ( GetTeamNumber() == TF_TEAM_RED ) ? "drg_cow_explosioncore_charged" : "drg_cow_explosioncore_charged_blue"; diff --git a/src/game/shared/tf/tf_weapon_particle_cannon.cpp b/src/game/shared/tf/tf_weapon_particle_cannon.cpp index ee77a7b0a05..718af19b587 100644 --- a/src/game/shared/tf/tf_weapon_particle_cannon.cpp +++ b/src/game/shared/tf/tf_weapon_particle_cannon.cpp @@ -349,6 +349,10 @@ void CTFParticleCannon::Precache() PrecacheParticleSystem( "drg_cow_explosioncore_charged_blue" ); PrecacheParticleSystem( "drg_cow_explosioncore_normal" ); PrecacheParticleSystem( "drg_cow_explosioncore_normal_blue" ); + PrecacheParticleSystem( "drg_cow_explosioncore_charged_halloween" ); + PrecacheParticleSystem( "drg_cow_explosioncore_normal_halloween" ); + PrecacheParticleSystem( "drg_cow_explosioncore_charged_halloween_blue" ); + PrecacheParticleSystem( "drg_cow_explosioncore_normal_halloween_blue" ); PrecacheParticleSystem( "drg_cow_muzzleflash_charged" ); PrecacheParticleSystem( "drg_cow_muzzleflash_charged_blue" ); PrecacheParticleSystem( "drg_cow_muzzleflash_normal" );