diff options
Diffstat (limited to 'Northstar.CustomServers/scripts/vscripts/_bubble_shield.gnut')
-rw-r--r-- | Northstar.CustomServers/scripts/vscripts/_bubble_shield.gnut | 524 |
1 files changed, 0 insertions, 524 deletions
diff --git a/Northstar.CustomServers/scripts/vscripts/_bubble_shield.gnut b/Northstar.CustomServers/scripts/vscripts/_bubble_shield.gnut deleted file mode 100644 index 30758bec..00000000 --- a/Northstar.CustomServers/scripts/vscripts/_bubble_shield.gnut +++ /dev/null @@ -1,524 +0,0 @@ -global function BubbleShield_Init - -global function CreateBubbleShield -global function IsTitanWithinBubbleShield -global function TitanHasBubbleShieldWeapon -global function LetTitanPlayerShootThroughBubbleShield -global function CreateGenericBubbleShield -global function CreateParentedBubbleShield - -global function WaitUntilTitanStandsOrDies -global function DestroyBubbleShield -global function CreateBubbleShieldWithSettings - -const float SHIELD_TITAN_DAMAGE_FLOOR = 250.0 -const float SHIELD_TITAN_DAMAGE_CEILING = 16000 //Some arbitrarily large number really -const float SHIELD_PILOT_DAMAGE_FLOOR = 30.0 -const float SHIELD_PILOT_DAMAGE_CEILING = 60.0 -const float SHIELD_NPC_DAMAGE_FLOOR = 30.0 - -const float SHIELD_FADE_ARBITRARY_DELAY = 3.0 -const float SHIELD_FADE_ENDCAP_DELAY = 1.0 - -const float SHIELD_DISTANCE_TO_DESTROY = 40 - -struct BubbleShieldDamageStruct -{ - float damageFloor - float damageCeiling - array<float> quadraticPolynomialCoefficients //Should actually be float[3], but because float[ 3 ] and array<float> are different types and this needs to be fed into EvaluatePolynomial make it an array<float> instead -} - -struct -{ - BubbleShieldDamageStruct titanDamageStruct - BubbleShieldDamageStruct pilotDamageStruct - BubbleShieldDamageStruct aiDamageStruct - -}file - - -void function BubbleShield_Init() -{ - RegisterSignal( "TitanBrokeBubbleShield" ) - RegisterSignal( "NewBubbleShield" ) - RegisterSignal( "StopBubbleShieldDamage" ) - - InitBubbleShieldDamageStructValues( file.titanDamageStruct, SHIELD_TITAN_DAMAGE_FLOOR, SHIELD_TITAN_DAMAGE_CEILING, [ 12.0, 5.0, 2.0 ] ) - InitBubbleShieldDamageStructValues( file.pilotDamageStruct, SHIELD_PILOT_DAMAGE_FLOOR, SHIELD_PILOT_DAMAGE_CEILING, [ 2.0, 1.0, 1.0 ] ) - InitBubbleShieldDamageStructValues( file.aiDamageStruct, SHIELD_PILOT_DAMAGE_FLOOR, SHIELD_PILOT_DAMAGE_CEILING, [ 2.0, 1.0, 1.0 ] ) -} - -void function InitBubbleShieldDamageStructValues( BubbleShieldDamageStruct damageStruct, float damageFloor, float damageCeiling, array<float> quadPolynomialCoeffs ) -{ - damageStruct.damageFloor = damageFloor - damageStruct.damageCeiling = damageCeiling - damageStruct.quadraticPolynomialCoefficients = quadPolynomialCoeffs -} - -void function CreateBubbleShield( entity titan, vector origin, vector angles ) -{ - if ( !IsAlive( titan ) ) - return - - titan.Signal( "ClearDisableTitanfall" ) - - entity soul = titan.GetTitanSoul() - entity player = soul.GetBossPlayer() - - if ( !IsValid( player ) ) - return - - if ( !svGlobal.bubbleShieldEnabled ) - return - - player.EndSignal( "OnDestroy" ) - - float embarkTime = GetBubbleShieldDuration( player ) - float bubTime = embarkTime + SHIELD_FADE_ARBITRARY_DELAY + SHIELD_FADE_ENDCAP_DELAY - - soul.Signal( "NewBubbleShield" ) - entity bubbleShield = CreateBubbleShieldWithSettings( titan.GetTeam(), origin, angles, player, bubTime ) - bubbleShield.SetBossPlayer( player ) // so code knows AI should try to shoot at titan inside shield - soul.soul.bubbleShield = bubbleShield - - player.SetTitanBubbleShieldTime( Time() + GetBubbleShieldDuration( player ) ) //This sets the time to display "Titan Shielded" on the HUD - - AI_CreateDangerousArea_Static( bubbleShield, null, TITAN_BUBBLE_SHIELD_INVULNERABILITY_RANGE, titan.GetTeam(), true, true, origin ) - - //titan.SetNPCPriorityOverride( 1 ) - - OnThreadEnd( - function () : ( titan, soul, player, bubbleShield ) - { - if ( IsValid( player ) ) - player.SetTitanBubbleShieldTime( 0 ) //This sets the time to display "Titan Shielded" on the HUD - - CleanupTitanBubbleShieldVars( titan, soul, bubbleShield ) - - } - ) - - waitthread WaitUntilShieldFades( player, titan, bubbleShield, bubTime + 4.0 ) -} - -void function MonitorTitanMovement( entity soul, entity bubbleShield ) -{ - entity titan = soul.GetTitan() - soul.EndSignal( "OnDestroy" ) - soul.EndSignal( "OnTitanDeath" ) - bubbleShield.EndSignal( "OnDestroy" ) - titan.EndSignal( "OnDestroy" ) - - vector startPos = titan.GetOrigin() - float endTime = Time() + SHIELD_FADE_ARBITRARY_DELAY - while( endTime >= Time() ) - { - if ( Distance( titan.GetOrigin(), startPos ) > SHIELD_DISTANCE_TO_DESTROY ) - break - - wait 0.1 - } - - soul.Signal( "TitanBrokeBubbleShield" ) -} - -void function CreateGenericBubbleShield( entity titan, vector origin, vector angles, float duration = 9999.0 ) -{ - if ( !IsAlive( titan ) ) - return - - entity soul = titan.GetTitanSoul() - soul.Signal( "NewBubbleShield" ) - entity bubbleShield = CreateBubbleShieldWithSettings( titan.GetTeam(), origin, angles, titan, 9999 ) - soul.soul.bubbleShield = bubbleShield - - titan.SetNPCPriorityOverride( 10 ) - - OnThreadEnd( - function () : ( titan, soul, bubbleShield ) - { - CleanupTitanBubbleShieldVars( titan, soul, bubbleShield ) - } - ) - - waitthread WaitUntilShieldFades( null, titan, bubbleShield, duration ) -} - -void function CreateParentedBubbleShield( entity titan, vector origin, vector angles, float duration = 9999.0 ) -{ - if ( !IsAlive( titan ) ) - return - - entity soul = titan.GetTitanSoul() - soul.Signal( "NewBubbleShield" ) - entity bubbleShield = CreateBubbleShieldWithSettings( titan.GetTeam(), origin, angles, titan, 9999 ) - soul.soul.bubbleShield = bubbleShield - - titan.SetNPCPriorityOverride( 10 ) - - OnThreadEnd( - function () : ( titan, soul, bubbleShield ) - { - CleanupTitanBubbleShieldVars( titan, soul, bubbleShield ) - } - ) - - soul.EndSignal( "OnTitanDeath" ) - soul.EndSignal( "OnDestroy" ) - - soul.soul.bubbleShield.SetParent( titan, "ORIGIN" ) - table bubleshieldDotS = expect table( soul.soul.bubbleShield.s ) - entity friendlyColoredFX = expect entity (bubleshieldDotS.friendlyColoredFX ) - entity enemyColoredFX = expect entity (bubleshieldDotS.enemyColoredFX ) - friendlyColoredFX.SetParent( soul.soul.bubbleShield ) - enemyColoredFX.SetParent( soul.soul.bubbleShield ) - - wait duration -} - -void function CleanupTitanBubbleShieldVars( entity titan, entity soul, entity bubbleShield ) -{ - DestroyBubbleShield( bubbleShield ) - - if ( IsValid( soul ) ){ - soul.soul.bubbleShield = null - } - - if ( IsAlive( titan ) ) - titan.ClearNPCPriorityOverride() -} - -void function DestroyBubbleShield( entity bubbleShield ) -{ - if ( IsValid( bubbleShield ) ) - { - ClearChildren( bubbleShield ) - bubbleShield.Destroy() - } -} - -entity function CreateBubbleShieldWithSettings( int team, vector origin, vector angles, entity owner = null, float duration = 9999 ) -{ - entity bubbleShield = CreateEntity( "prop_dynamic" ) - bubbleShield.SetValueForModelKey( $"models/fx/xo_shield.mdl" ) - bubbleShield.kv.solid = SOLID_VPHYSICS - bubbleShield.kv.rendercolor = "81 130 151" - bubbleShield.kv.contents = (int(bubbleShield.kv.contents) | CONTENTS_NOGRAPPLE) - bubbleShield.SetOrigin( origin ) - bubbleShield.SetAngles( angles ) - // Blocks bullets, projectiles but not players and not AI - bubbleShield.kv.CollisionGroup = TRACE_COLLISION_GROUP_BLOCK_WEAPONS - bubbleShield.SetBlocksRadiusDamage( true ) - DispatchSpawn( bubbleShield ) - bubbleShield.Hide() - - SetTeam( bubbleShield, team ) - array<entity> bubbleShieldFXs - - vector coloredFXOrigin = origin + Vector( 0, 0, 25 ) - table bubbleShieldDotS = expect table( bubbleShield.s ) - if ( team == TEAM_UNASSIGNED ) - { - entity neutralColoredFX = StartParticleEffectInWorld_ReturnEntity( BUBBLE_SHIELD_FX_PARTICLE_SYSTEM_INDEX, coloredFXOrigin, <0, 0, 0> ) - SetTeam( neutralColoredFX, team ) - bubbleShieldDotS.neutralColoredFX <- neutralColoredFX - bubbleShieldFXs.append( neutralColoredFX ) - } - else - { - //Create friendly and enemy colored particle systems - entity friendlyColoredFX = StartParticleEffectInWorld_ReturnEntity( BUBBLE_SHIELD_FX_PARTICLE_SYSTEM_INDEX, coloredFXOrigin, <0, 0, 0> ) - SetTeam( friendlyColoredFX, team ) - friendlyColoredFX.kv.VisibilityFlags = ENTITY_VISIBLE_TO_FRIENDLY - EffectSetControlPointVector( friendlyColoredFX, 1, FRIENDLY_COLOR_FX ) - - entity enemyColoredFX = StartParticleEffectInWorld_ReturnEntity( BUBBLE_SHIELD_FX_PARTICLE_SYSTEM_INDEX, coloredFXOrigin, <0, 0, 0> ) - SetTeam( enemyColoredFX, team ) - enemyColoredFX.kv.VisibilityFlags = ENTITY_VISIBLE_TO_ENEMY - EffectSetControlPointVector( enemyColoredFX, 1, ENEMY_COLOR_FX ) - - bubbleShieldDotS.friendlyColoredFX <- friendlyColoredFX - bubbleShieldDotS.enemyColoredFX <- enemyColoredFX - bubbleShieldFXs.append( friendlyColoredFX ) - bubbleShieldFXs.append( enemyColoredFX ) - } - - #if MP - DisableTitanfallForLifetimeOfEntityNearOrigin( bubbleShield, origin, TITANHOTDROP_DISABLE_ENEMY_TITANFALL_RADIUS ) - #endif - - EmitSoundOnEntity( bubbleShield, "BubbleShield_Sustain_Loop" ) - - thread CleanupBubbleShield( bubbleShield, bubbleShieldFXs, duration ) - thread BubbleShieldDamageEnemies( bubbleShield, owner ) - - return bubbleShield -} - -void function CleanupBubbleShield( entity bubbleShield, array<entity> bubbleShieldFXs, float fadeTime ) -{ - bubbleShield.EndSignal( "OnDestroy" ) - - OnThreadEnd( - function () : ( bubbleShield, bubbleShieldFXs ) - { - if ( IsValid_ThisFrame( bubbleShield ) ) - { - StopSoundOnEntity( bubbleShield, "BubbleShield_Sustain_Loop" ) - EmitSoundOnEntity( bubbleShield, "BubbleShield_End" ) - DestroyBubbleShield( bubbleShield ) - } - - foreach ( fx in bubbleShieldFXs ) - { - if ( IsValid_ThisFrame( fx ) ) - { - EffectStop( fx ) - } - } - } - ) - - wait fadeTime -} - -void function WaitUntilShieldFades( entity player, entity titan, entity bubbleShield, float failTime ) -{ - bubbleShield.EndSignal( "OnDestroy" ) - entity soul = titan.GetTitanSoul() - soul.EndSignal( "OnDestroy" ) - soul.EndSignal( "OnTitanDeath" ) - soul.EndSignal( "NewBubbleShield" ) - - soul.EndSignal( "TitanBrokeBubbleShield" ) - - if ( player != null ) - waitthread WaitUntilPlayerTitanStandsOrDies( player, titan, failTime ) - else - waitthread WaitUntilTitanStandsOrDies( titan, failTime ) - - // have to add this since OnTitanDeath is somewhat unreliable, especially in the middle of titan transfer - if ( !IsAlive( soul.GetTitan() ) ) - return - - thread MonitorTitanMovement( soul, bubbleShield ) - wait SHIELD_FADE_ARBITRARY_DELAY -} - -void function WaitUntilPlayerTitanStandsOrDies( entity player, entity titan, float failTime ) -{ - waitthread WaitUntilTitanStandsOrDies( titan, failTime ) - - if ( !IsAlive( player ) ) - return - - if ( IsPlayerEmbarking( player ) && player.Anim_IsActive() ) - WaittillAnimDone( player ) -} - -void function WaitUntilTitanStandsOrDies( entity titan, float timeout = -1.0 ) -{ - titan.EndSignal( "OnDeath" ) - titan.EndSignal( "ChangedTitanMode" ) - float endTime = Time() + timeout - - for ( ;; ) - { - if ( titan.GetTitanSoul().GetStance() == STANCE_STAND ) - return - - if ( Time() > endTime && timeout != -1 ) - break - - wait 0.2 - } -} - -void function BubbleShieldDamageEnemies( entity bubbleShield, entity bubbleShieldPlayer ) -{ - bubbleShield.EndSignal( "OnDestroy" ) - if ( IsValid( bubbleShieldPlayer ) ) - bubbleShieldPlayer.EndSignal( "OnDestroy" ) - - bubbleShield.EndSignal( "StopBubbleShieldDamage" ) - - entity trigger = CreateEntity( "trigger_cylinder" ) - trigger.SetRadius( TITAN_BUBBLE_SHIELD_INVULNERABILITY_RANGE ) - trigger.SetAboveHeight( TITAN_BUBBLE_SHIELD_CYLINDER_TRIGGER_HEIGHT ) //Still not quite a sphere, will see if close enough - trigger.SetBelowHeight( 0 ) - trigger.SetOrigin( bubbleShield.GetOrigin() ) - trigger.SetParent( bubbleShield ) - DispatchSpawn( trigger ) - - trigger.SearchForNewTouchingEntity() //JFS: trigger.GetTouchingEntities() will not return entities already in the trigger unless this is called. See bug 202843 - - /*DebugDrawCylinder( trigger.GetOrigin(), <270,0,0>, TITAN_BUBBLE_SHIELD_INVULNERABILITY_RANGE, TITAN_BUBBLE_SHIELD_CYLINDER_TRIGGER_HEIGHT, 255, 255, 255, true, 20.0 ) - DebugDrawSphere( bubbleShield.GetOrigin(), TITAN_BUBBLE_SHIELD_INVULNERABILITY_RANGE, 255, 0, 0, true, 20 )*/ - OnThreadEnd( - function() : ( trigger ) - { - trigger.Destroy() - } - ) - - float refreshLowerBound = 0.5 - float refreshUpperBound = 0.8 - - table<entity, int> soulTable = {} - table<entity, int> npcTable = {} - table<entity, int> pilotTable = {} - - table<entity, int> countTable - - while ( true ) - { - array<entity> touchingEnts = trigger.GetTouchingEntities() - - foreach( touchingEnt in touchingEnts ) - { - if ( touchingEnt.IsTitan() ) - countTable = soulTable - else if( touchingEnt.IsPlayer() ) - countTable = pilotTable - else - countTable = npcTable - - DamageEntWithinBubbleShield( bubbleShield, bubbleShieldPlayer, touchingEnt, countTable ) - } - - wait RandomFloatRange( refreshLowerBound, refreshUpperBound ) - } -} - -void function LetTitanPlayerShootThroughBubbleShield( entity titanPlayer ) -{ - Assert( titanPlayer.IsTitan() ) - - entity soul = titanPlayer.GetTitanSoul() - entity bubbleShield = soul.soul.bubbleShield - - if ( !IsValid( bubbleShield ) ) - return - - bubbleShield.SetOwner( titanPlayer ) //After this, player is able to fire out from shield. WATCH OUT FOR POTENTIAL COLLISION BUGS! - - thread MonitorLastFireTime( titanPlayer ) - thread StopPlayerShootThroughBubbleShield( titanPlayer, bubbleShield ) -} - -void function StopPlayerShootThroughBubbleShield( entity player, entity bubbleShield ) -{ - player.EndSignal( "OnDeath" ) - player.WaitSignal( "OnChangedPlayerClass" ) //Kill this thread once player gets out of the Titan - - if ( !IsValid( bubbleShield ) ) - return - - bubbleShield.SetOwner( null ) -} - -void function MonitorLastFireTime( entity player ) -{ - player.EndSignal( "OnDestroy" ) - player.EndSignal( "OnChangedPlayerClass" ) //Kill this thread once player gets out of the Titan - - player.WaitSignal( "OnPrimaryAttack" ) //Sent when player fires his weapon - //printt( "Player fired weapon! in MonitorLastFireTime" ) - - entity soul = player.GetTitanSoul() - - if ( !IsValid( soul ) ) - return - - soul.Signal( "TitanBrokeBubbleShield" ) //WaitUntilShieldFades will end when this signal is sent -} - -void function DamageEntWithinBubbleShield( entity bubbleShield, entity bubbleShieldPlayer, entity touchingEnt, table<entity, int> countTable, ) -{ - int ownerTeam = IsValid( bubbleShieldPlayer ) ? bubbleShieldPlayer.GetTeam() : bubbleShield.GetTeam() - if ( !BubbleShieldShouldDamage( bubbleShield, ownerTeam, touchingEnt ) ) - return - - entity entInCountTable = null - - if ( touchingEnt.IsTitan() ) - { - entity soul = touchingEnt.GetTitanSoul() - if ( !IsValid( soul ) ) - return - - entInCountTable = soul - } - else - { - entInCountTable = touchingEnt - } - - if ( IsValid( entInCountTable ) && !( entInCountTable in countTable ) ) - countTable[ entInCountTable ] <- 0 - - int timesTouched = ++countTable[ entInCountTable ] - - BubbleShieldDamageStruct damageStruct - - if ( touchingEnt.IsTitan() ) - damageStruct = file.titanDamageStruct - else if ( touchingEnt.IsPlayer() ) - damageStruct = file.pilotDamageStruct - else - damageStruct = file.aiDamageStruct - - float damageAmount = damageStruct.damageFloor + EvaluatePolynomial( float ( countTable[ entInCountTable ] ), damageStruct.quadraticPolynomialCoefficients ) - - //printt( "Damage amount: " + damageAmount + ", touchingEnt: " + touchingEnt ) - - touchingEnt.TakeDamage( damageAmount, bubbleShieldPlayer, bubbleShield, { origin = bubbleShield.GetOrigin(), damageSourceId=eDamageSourceId.bubble_shield } ) - StatusEffect_AddTimed( touchingEnt, eStatusEffect.emp, 0.1, 1.0, 0.2 ) - - EmitSoundOnEntity( bubbleShield, "titan_energyshield_damage" ) -} - -bool function BubbleShieldShouldDamage( entity bubbleShield, int ownerTeam, entity ent ) -{ - if ( !IsAlive( ent ) ) - return false - - if ( ownerTeam == ent.GetTeam() ) - return false - - /*if ( ent.IsTitan() && IsTitanWithinBubbleShield( ent ) ) - return false*/ - - if ( ! ( ent instanceof CBaseCombatCharacter ) ) //Projectiles etc won't get damaged - return false - - float distSqr = DistanceSqr( bubbleShield.GetOrigin(), ent.GetOrigin() ) - - return distSqr <= TITAN_BUBBLE_SHIELD_INVULNERABILITY_RANGE_SQUARED -} - -bool function IsTitanWithinBubbleShield( entity titan ) -{ - if ( !IsAlive( titan ) ) - return false - - entity soul = titan.GetTitanSoul() - - if ( !IsValid( soul ) ) //Bug 152438. Defensive coding, but there's a small window after embarking where the npc Titan doesn't have a soul anymore but can be damaged - return false - - if ( !IsValid( soul.soul.bubbleShield ) ) - return false - - return DistanceSqr( soul.soul.bubbleShield.GetOrigin(), titan.GetOrigin() ) < TITAN_BUBBLE_SHIELD_INVULNERABILITY_RANGE * TITAN_BUBBLE_SHIELD_INVULNERABILITY_RANGE -} - -bool function TitanHasBubbleShieldWeapon( entity titan ) -{ - entity weapon = titan.GetActiveWeapon() - if ( IsValid( weapon ) && IsValid( weapon.w.bubbleShield ) ) - return true - - return false -} |