Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix transferring active Stim ability to Titan and endless stim effects #864

Merged
merged 14 commits into from
Nov 27, 2024
Merged
189 changes: 189 additions & 0 deletions Northstar.Custom/mod/scripts/vscripts/weapons/sh_stim.gnut
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@

global function StimShared_Init
global function StimPlayer
global function EndlessStimBegin
global function EndlessStimEnd


global int COCKPIT_STIM_FX
global int PILOT_STIM_HLD_FX

global const float STIM_EFFECT_SEVERITY = 0.4 // assuming 'movement_speedboost_extraScale' is 2.0

void function StimShared_Init()
{
COCKPIT_STIM_FX = PrecacheParticleSystem( $"P_heal" )
PILOT_STIM_HLD_FX = PrecacheParticleSystem( $"P_pilot_stim_hld" )

#if CLIENT
StatusEffect_RegisterEnabledCallback( eStatusEffect.stim_visual_effect, StimVisualsEnabled )
StatusEffect_RegisterDisabledCallback( eStatusEffect.stim_visual_effect, StimVisualsDisabled )
#endif

RegisterSignal( "EndStim" )
RegisterSignal( "StopEndlessStim" )
}

void function EndlessStimBegin( entity player, float effectSeverity )
{
StimPlayer_Internal( player, USE_TIME_INFINITE, effectSeverity )
}
void function EndlessStimEnd( entity player )
{
player.Signal( "StopEndlessStim" )
}

void function StimPlayer( entity player, float duration, float severity = STIM_EFFECT_SEVERITY )
{
StimPlayer_Internal( player, duration, severity )
}

void function StimPlayer_Internal( entity player, float duration, float effectSeverity )
{
// Handles for tracking endless status effects
int endlessStatusEffectHandle_SpeedBoost = 0
int endlessStatusEffectHandle_StimVFX = 0
if ( duration == USE_TIME_INFINITE )
{
endlessStatusEffectHandle_SpeedBoost = StatusEffect_AddEndless( player, eStatusEffect.speed_boost, effectSeverity )
endlessStatusEffectHandle_StimVFX = StatusEffect_AddEndless( player, eStatusEffect.stim_visual_effect, 1.0 )
}
else
{
StatusEffect_AddTimed( player, eStatusEffect.speed_boost, effectSeverity, duration + 0.5, 0.25 ) // sound is slightly off
StatusEffect_AddTimed( player, eStatusEffect.stim_visual_effect, 1.0, duration, duration )
}

#if SERVER
thread StimThink( player, duration, endlessStatusEffectHandle_SpeedBoost, endlessStatusEffectHandle_StimVFX )
#else // CLIENT
entity cockpit = player.GetCockpit()
if ( !IsValid( cockpit ) )
return

HealthHUD_ClearFX( player )
#endif
}

#if SERVER
void function StimThink( entity player, float duration, int endlessStatusEffectHandle_SpeedBoost, int endlessStatusEffectHandle_StimVFX )
{
player.EndSignal( "OnDeath" )
player.EndSignal( "OnChangedPlayerClass" )
player.EndSignal( "player_embarks_titan" ) // Prevent transferring active Stim ability to Titan.

if ( endlessStatusEffectHandle_SpeedBoost != 0 || endlessStatusEffectHandle_StimVFX != 0 )
{
player.EndSignal( "StopEndlessStim" )
// TF|2 stim loop sounds don't actually loop, use TF|1 loop sound.
// BUG: It still stops playing sometimes for whatever reason ( Too many sounds? )
EmitSoundOnEntity( player, "Pilot_Stimpack_Loop" )
}
else
{
EmitSoundOnEntityOnlyToPlayer( player, player, "pilot_stimpack_loop_1P" )
EmitSoundOnEntityExceptToPlayer( player, player, "pilot_stimpack_loop_3P" )
}

int attachmentIndex = player.LookupAttachment( "CHESTFOCUS" )

entity stimFX = StartParticleEffectOnEntity_ReturnEntity( player, PILOT_STIM_HLD_FX, FX_PATTACH_POINT_FOLLOW, attachmentIndex )
stimFX.SetOwner( player )
stimFX.kv.VisibilityFlags = (ENTITY_VISIBLE_TO_FRIENDLY | ENTITY_VISIBLE_TO_ENEMY) // not owner only

//thread StimSlowmoAim( player, duration )

OnThreadEnd(
function() : ( player, stimFX, endlessStatusEffectHandle_SpeedBoost, endlessStatusEffectHandle_StimVFX )
{
if ( !IsValid( player ) )
return

if ( IsValid( stimFX ) )
EffectStop( stimFX )

if ( endlessStatusEffectHandle_SpeedBoost != 0 || endlessStatusEffectHandle_StimVFX != 0 )
{
StopSoundOnEntity( player, "Pilot_Stimpack_Loop" )
}
else
{
StopSoundOnEntity( player, "pilot_stimpack_loop_1P" )
StopSoundOnEntity( player, "pilot_stimpack_loop_3P" )
}

if ( endlessStatusEffectHandle_SpeedBoost != 0 )
StatusEffect_Stop( player, endlessStatusEffectHandle_SpeedBoost )

if ( endlessStatusEffectHandle_StimVFX != 0 )
StatusEffect_Stop( player, endlessStatusEffectHandle_StimVFX )

player.Signal( "EndStim" )
}
)

if ( duration == USE_TIME_INFINITE )
WaitForever()

wait duration - 2.0

EmitSoundOnEntityOnlyToPlayer( player, player, "pilot_stimpack_deactivate_1P" )
EmitSoundOnEntityExceptToPlayer( player, player, "pilot_stimpack_deactivate_3P" )

wait 2.0
}

#else // CLIENT
void function StimVisualsEnabled( entity ent, int statusEffect, bool actuallyChanged )
{
if ( ent != GetLocalViewPlayer() )
return

entity player = ent

entity cockpit = player.GetCockpit()
if ( !IsValid( cockpit ) )
return

int fxHandle = StartParticleEffectOnEntity( cockpit, COCKPIT_STIM_FX, FX_PATTACH_ABSORIGIN_FOLLOW, -1 )
thread StimScreenFXThink( player, fxHandle, cockpit )
}

void function StimVisualsDisabled( entity ent, int statusEffect, bool actuallyChanged )
{
if ( ent != GetLocalViewPlayer() )
return

ent.Signal( "EndStim" )
}

void function StimScreenFXThink( entity player, int fxHandle, entity cockpit )
{
player.EndSignal( "EndStim" )
player.EndSignal( "OnDeath" )
cockpit.EndSignal( "OnDestroy" )

OnThreadEnd(
function() : ( fxHandle )
{
if ( !EffectDoesExist( fxHandle ) )
return

EffectStop( fxHandle, false, true )
}
)

for ( ;; )
{
float velocityX = Length( player.GetVelocity() )

if ( !EffectDoesExist( fxHandle ) )
break

velocityX = GraphCapped( velocityX, 0.0, 360, 5, 200 )
EffectSetControlPointVector( fxHandle, 1, Vector( velocityX, 999, 0 ) )
WaitFrame()
}
}

#endif
Loading