class Radio extends InteractiveDevice { default m_controllerTypeName = 'RadioController'; [ category = "High Pitch Noise Quick Hack Data" ] private editable inlined var m_effectAction : ScriptableDeviceAction; [ category = "High Pitch Noise Quick Hack Data" ] private editable var m_effectRef : EffectRef; [ category = "High Pitch Noise Quick Hack Data" ] private editable var m_statusEffect : TweakDBID; [ category = "Aoe Damage Quick Hack Data" ][ customEditor = "TweakDBGroupInheritance;Attacks.DeviceAttack" ] private editable var m_damageType : TweakDBID; private var m_startingStation : Int32; private var m_isInteractive : Bool; private var m_isShortGlitchActive : Bool; private var m_shortGlitchDelayID : DelayID; private var m_effectInstance : EffectInstance; private var m_targets : array< weak< ScriptedPuppet > >; private var m_vfxInstance : FxInstance; protected event OnRequestComponents( ri : EntityRequestComponentsInterface ) { EntityRequestComponentsInterface.RequestComponent( ri, 'audio', 'soundComponent', false ); EntityRequestComponentsInterface.RequestComponent( ri, 'radio_ui', 'worlduiWidgetComponent', false ); super.OnRequestComponents( ri ); } protected event OnTakeControl( ri : EntityResolveComponentsInterface ) { super.OnTakeControl( ri ); m_uiComponent = ( ( worlduiWidgetComponent )( EntityResolveComponentsInterface.GetComponent( ri, 'radio_ui' ) ) ); m_controller = ( ( RadioController )( EntityResolveComponentsInterface.GetComponent( ri, 'controller' ) ) ); } protected override function ResolveGameplayState() { super.ResolveGameplayState(); if( IsUIdirty() && m_isInsideLogicArea ) { RefreshUI(); } } protected event OnToggleON( evt : ToggleON ) { super.OnToggleON( evt ); TriggerArreaEffectDistraction( GetDefaultDistractionAreaEffectData(), evt.GetExecutor() ); } protected event OnTogglePower( evt : TogglePower ) { super.OnTogglePower( evt ); TriggerArreaEffectDistraction( GetDefaultDistractionAreaEffectData(), evt.GetExecutor() ); } protected override function RestoreDeviceState() { super.RestoreDeviceState(); } public const override function GetDevicePS() : RadioControllerPS { return GetController().GetPS(); } protected const override function GetController() : RadioController { return ( ( RadioController )( m_controller ) ); } private function PlayGivenStation() { var isMetal : Bool; var radioStation : ERadioStationList; var stationEventName : CName; radioStation = GetDevicePS().GetActiveRadioStation(); stationEventName = RadioStationDataProvider.GetStationName( radioStation ); AudioSwitch( this, 'radio_station', stationEventName, 'radio' ); isMetal = radioStation == ERadioStationList.METAL; MetalItUp( isMetal ); } private function MetalItUp( isMetal : Bool ) { if( GetDevicePS().GetDurabilityType() != EDeviceDurabilityType.INVULNERABLE ) { if( isMetal ) { GetDevicePS().SetDurabilityType( EDeviceDurabilityType.INDESTRUCTIBLE ); } else { GetDevicePS().SetDurabilityType( EDeviceDurabilityType.DESTRUCTIBLE ); } } } protected event OnNextStation( evt : NextStation ) { PlayGivenStation(); UpdateDeviceState(); RefreshUI(); TriggerArreaEffectDistraction( GetDefaultDistractionAreaEffectData(), evt.GetExecutor() ); } protected event OnPreviousStation( evt : PreviousStation ) { PlayGivenStation(); UpdateDeviceState(); RefreshUI(); TriggerArreaEffectDistraction( GetDefaultDistractionAreaEffectData(), evt.GetExecutor() ); } protected event OnQuestSetChannel( evt : QuestSetChannel ) { PlayGivenStation(); RefreshUI(); } protected event OnQuestDefaultStation( evt : QuestDefaultStation ) { PlayGivenStation(); RefreshUI(); } protected event OnSpiderbotDistraction( evt : SpiderbotDistraction ) { OrderSpiderbot(); } protected event OnSpiderbotOrderCompletedEvent( evt : SpiderbotOrderCompletedEvent ) { SendSetIsSpiderbotInteractionOrderedEvent( false ); GameInstance.GetActivityLogSystem( GetGame() ).AddLog( "SPIDERBOT HAS FINISHED ACTIVATING THE DEVICE ... " ); GetDevicePS().CauseDistraction(); } protected override function TurnOnDevice() { super.TurnOnDevice(); if( m_uiComponent ) { m_uiComponent.Toggle( true ); } PlayGivenStation(); UpdateDeviceState(); GameObjectEffectHelper.ActivateEffectAction( this, gamedataFxActionType.Start, 'radio_idle' ); RefreshUI(); } protected override function TurnOffDevice() { super.TurnOffDevice(); AudioSwitch( this, 'radio_station', 'station_none', 'radio' ); UpdateDeviceState(); GameObjectEffectHelper.ActivateEffectAction( this, gamedataFxActionType.BreakLoop, 'radio_idle' ); RefreshUI(); } protected override function CutPower() { super.CutPower(); if( m_uiComponent ) { m_uiComponent.Toggle( false ); } GameObjectEffectHelper.ActivateEffectAction( this, gamedataFxActionType.BreakLoop, 'radio_idle' ); UpdateDeviceState(); } protected override function DeactivateDevice() { super.DeactivateDevice(); if( m_uiComponent ) { m_uiComponent.Toggle( false ); } GameObjectEffectHelper.ActivateEffectAction( this, gamedataFxActionType.Kill, 'radio_idle' ); } public const override function DeterminGameplayRole() : EGameplayRole { return EGameplayRole.Distract; } protected override function StartGlitching( glitchState : EGlitchState, optional intensity : Float ) { var evt : AdvertGlitchEvent; if( intensity == 0.0 ) { intensity = 1.0; } evt = new AdvertGlitchEvent; evt.SetShouldGlitch( intensity ); QueueEvent( evt ); UpdateDeviceState(); PlaySound( this, GetDevicePS().GetGlitchSFX() ); } protected override function StopGlitching() { var evt : AdvertGlitchEvent; evt = new AdvertGlitchEvent; evt.SetShouldGlitch( 0.0 ); QueueEvent( evt ); } private function StartShortGlitch() { var evt : StopShortGlitchEvent; if( GetDevicePS().IsGlitching() ) { return; } if( !( m_isShortGlitchActive ) ) { evt = new StopShortGlitchEvent; StartGlitching( EGlitchState.DEFAULT, 1.0 ); m_shortGlitchDelayID = GameInstance.GetDelaySystem( GetGame() ).DelayEvent( this, evt, 0.25 ); m_isShortGlitchActive = true; } } protected event OnStopShortGlitch( evt : StopShortGlitchEvent ) { m_isShortGlitchActive = false; if( !( GetDevicePS().IsGlitching() ) ) { StopGlitching(); } } protected event OnQuickHackHighPitchNoise( evt : QuickHackHighPitchNoise ) { if( evt.IsStarted() ) { StartStunEffect(); } else { StopStunEffect(); } } protected event OnQuickHackAoeDamage( evt : QuickHackAoeDamage ) { PlayAoeDamageSFX(); PlayAoeDamageVFX(); ApplyElectricDamage(); Die(); } private function ApplyElectricDamage() { var attack : Attack_GameEffect; attack = RPGManager.PrepareGameEffectAttack( GetGame(), this, this, m_damageType, GetAttackPosition() ); if( attack ) { attack.StartAttack(); } } private function GetAttackPosition() : Vector4 { return GetAcousticQuerryStartPoint(); } private function StartStunEffect() { StopStunEffect(); CreateGameEffect(); PlayHighPitchNoiseSFX(); PlayHighPitchNoiseVFX(); } private function StopStunEffect() { TryTerminateEffectInstance(); RemoveStatusEffectFromTargets(); ClearTargets(); TryStopVfx(); } private function TryTerminateEffectInstance() { if( m_effectInstance ) { m_effectInstance.Terminate(); m_effectInstance = NULL; } } private function RemoveStatusEffectFromTargets() { var i : Int32; if( IsStatusEffectValid() ) { for( i = 0; i < m_targets.Size(); i += 1 ) { RemoveStatusEffect( m_targets[ i ] ); } } } private function ClearTargets() { m_targets.Clear(); } private function CreateGameEffect() { m_effectInstance = GameInstance.GetGameEffectSystem( GetGame() ).CreateEffect( m_effectRef, this ); EffectData.SetFloat( m_effectInstance.GetSharedData(), GetAllBlackboardDefs().EffectSharedData.radius, GetDevicePS().GetHighPitchNoiseRadius() ); EffectData.SetVector( m_effectInstance.GetSharedData(), GetAllBlackboardDefs().EffectSharedData.position, GetAttackPosition() ); m_effectInstance.Run(); } private function PlayHighPitchNoiseSFX() { PlaySound( this, GetDevicePS().GetHighPitchNoiseSFX() ); } private function PlayAoeDamageSFX() { PlaySound( this, GetDevicePS().GetAoeDamageSFX() ); } private function PlayHighPitchNoiseVFX() { PlayVfx( GetDevicePS().GetHighPitchNoiseVFX() ); } private function PlayAoeDamageVFX() { PlayVfx( GetDevicePS().GetAoeDamageVFX() ); } private function PlayVfx( fxResource : FxResource ) { TryStopVfx(); if( FxResource.IsValid( fxResource ) ) { m_vfxInstance = CreateFxInstance( fxResource, GetCenterWorldTransform() ); } } private function GetCenterWorldTransform() : WorldTransform { var transform : WorldTransform; var position : WorldPosition; WorldPosition.SetVector4( position, GetWorldPosition() ); WorldTransform.SetWorldPosition( transform, position ); return transform; } private function TryStopVfx() { if( m_vfxInstance ) { m_vfxInstance.Kill(); } } private function ApplyStatusEffect( target : weak< GameObject > ) { if( IsStatusEffectValid() ) { StatusEffectHelper.ApplyStatusEffect( target, m_statusEffect, GetEntityID() ); } } private function RemoveStatusEffect( target : weak< GameObject > ) { if( IsStatusEffectValid() ) { StatusEffectHelper.RemoveStatusEffect( target, m_statusEffect ); } } private function IsStatusEffectValid() : Bool { return TDBID.IsValid( m_statusEffect ); } protected event OnTargetAcquired( evt : TargetAcquiredEvent ) { TryAddToTargets( evt.target ); ApplyStatusEffect( evt.target ); } private function TryAddToTargets( target : weak< ScriptedPuppet > ) { if( target && !( m_targets.Contains( target ) ) ) { m_targets.PushBack( target ); } } protected event OnTargetLost( evt : TargetLostEvent ) { RemoveStatusEffect( evt.target ); TryRemoveFromTargets( evt.target ); } private function TryRemoveFromTargets( target : weak< ScriptedPuppet > ) { var i : Int32; if( target ) { i = m_targets.FindFirst( target ); if( i >= 0 ) { m_targets.EraseFast( i ); } } } }