This commit is contained in:
FrozenDragon 2025-12-17 15:28:30 +08:00 committed by GitHub
commit 0ff1e8f5ca
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 166 additions and 91 deletions

View File

@ -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";
}
}

View File

@ -47,100 +47,114 @@ void C_TFProjectile_Rocket::OnDataChanged(DataUpdateType_t updateType)
//-----------------------------------------------------------------------------
void C_TFProjectile_Rocket::CreateTrails( void )
{
if ( IsDormant() )
return;
if ( IsDormant() )
return;
bool bUsingCustom = false;
bool bUsingCustom = false;
if ( pEffect )
{
ParticleProp()->StopEmission( pEffect );
pEffect = NULL;
}
if ( pEffect )
{
ParticleProp()->StopEmission( pEffect );
pEffect = NULL;
}
int iAttachment = LookupAttachment( "trail" );
if ( iAttachment == INVALID_PARTICLE_ATTACHMENT )
return;
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<CBaseObject*>( 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;
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<CBaseObject*>( 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 );
}
}
// 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 );
}
}
}
}
}
// 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;
if ( !bUsingCustom )
{
if ( GetTrailParticleName() )
{
ParticleProp()->Create( GetTrailParticleName(), PATTACH_POINT_FOLLOW, iAttachment );
}
}
// 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 ( 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;
}
}
}

View File

@ -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";

View File

@ -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" );