aboutsummaryrefslogtreecommitdiff
path: root/Northstar.Custom/mod/scripts/vscripts
diff options
context:
space:
mode:
Diffstat (limited to 'Northstar.Custom/mod/scripts/vscripts')
-rw-r--r--Northstar.Custom/mod/scripts/vscripts/sh_northstar_custom_precache.gnut5
-rw-r--r--Northstar.Custom/mod/scripts/vscripts/weapons/mp_projectile_titanweapon_triple_threat.nut85
-rw-r--r--Northstar.Custom/mod/scripts/vscripts/weapons/sh_triple_threat.gnut249
3 files changed, 337 insertions, 2 deletions
diff --git a/Northstar.Custom/mod/scripts/vscripts/sh_northstar_custom_precache.gnut b/Northstar.Custom/mod/scripts/vscripts/sh_northstar_custom_precache.gnut
index d5af4cde..848a4b86 100644
--- a/Northstar.Custom/mod/scripts/vscripts/sh_northstar_custom_precache.gnut
+++ b/Northstar.Custom/mod/scripts/vscripts/sh_northstar_custom_precache.gnut
@@ -4,9 +4,10 @@ global function NorthstarCustomPrecache
void function NorthstarCustomPrecache()
{
PrecacheWeapon( "mp_weapon_peacekraber" )
+ PrecacheWeapon( "mp_titanweapon_triplethreat" )
PrecacheWeapon( "melee_pilot_kunai" )
-
+
// create kunai damage source so game won't crash when we hit smth with it
// just using the default melee one, easier than making a new one
getconsttable()[ "eDamageSourceId" ][ "melee_pilot_kunai" ] <- eDamageSourceId.melee_pilot_emptyhanded
-} \ No newline at end of file
+}
diff --git a/Northstar.Custom/mod/scripts/vscripts/weapons/mp_projectile_titanweapon_triple_threat.nut b/Northstar.Custom/mod/scripts/vscripts/weapons/mp_projectile_titanweapon_triple_threat.nut
new file mode 100644
index 00000000..afdb6961
--- /dev/null
+++ b/Northstar.Custom/mod/scripts/vscripts/weapons/mp_projectile_titanweapon_triple_threat.nut
@@ -0,0 +1,85 @@
+untyped
+
+
+global function OnProjectileCollision_titanweapon_triple_threat
+
+
+void function OnProjectileCollision_titanweapon_triple_threat( entity projectile, vector pos, vector normal, entity hitEnt, int hitbox, bool isCritical )
+{
+ if( !IsValid( hitEnt ) )
+ return
+
+ if( "impactFuse" in projectile.s && projectile.s.impactFuse == true )
+ projectile.GrenadeExplode( Vector( 0,0,0 ) )
+
+ if( hitEnt.GetClassName() == "player" && !hitEnt.IsTitan() )
+ return
+
+ if( !IsValid( projectile ) )
+ return
+
+ if( IsMagneticTarget( hitEnt ) )
+ {
+ if( hitEnt.GetTeam() != projectile.GetTeam() )
+ {
+ local normal = Vector( 0, 0, 1 )
+ if( "collisionNormal" in projectile.s )
+ normal = projectile.s.collisionNormal
+ projectile.GrenadeExplode( normal )
+ }
+ }
+ else if( "becomeProxMine" in projectile.s && projectile.s.becomeProxMine == true )
+ {
+ table collisionParams =
+ {
+ pos = pos,
+ normal = normal,
+ hitEnt = hitEnt,
+ hitbox = hitbox
+ }
+
+ PlantStickyEntity( projectile, collisionParams )
+ projectile.s.collisionNormal <- normal
+ #if SERVER
+ thread TripleThreatProximityTrigger( projectile )
+ #endif
+ }
+
+}
+
+#if SERVER
+function TripleThreatProximityTrigger( entity nade )
+{
+ //Hack, shouldn't be necessary with the IsValid check in OnProjectileCollision.
+ if( !IsValid( nade ) )
+ return
+
+ nade.EndSignal( "OnDestroy" )
+ EmitSoundOnEntity( nade, "Wpn_TripleThreat_Grenade_MineAttach" )
+
+ wait TRIPLETHREAT_MINE_FIELD_ACTIVATION_TIME
+
+ EmitSoundOnEntity( nade, "Weapon_Vortex_Gun.ExplosiveWarningBeep" )
+ local rangeCheck = PROX_MINE_RANGE
+ while( 1 )
+ {
+ local origin = nade.GetOrigin()
+ int team = nade.GetTeam()
+
+ local entityArray = GetScriptManagedEntArrayWithinCenter( level._proximityTargetArrayID, team, origin, PROX_MINE_RANGE )
+ foreach( entity ent in entityArray )
+ {
+ if ( TRIPLETHREAT_MINE_FIELD_TITAN_ONLY )
+ if ( !ent.IsTitan() )
+ continue
+
+ if ( IsAlive( ent ) )
+ {
+ nade.Signal( "ProxMineTrigger" )
+ return
+ }
+ }
+ WaitFrame()
+ }
+}
+#endif // SERVER
diff --git a/Northstar.Custom/mod/scripts/vscripts/weapons/sh_triple_threat.gnut b/Northstar.Custom/mod/scripts/vscripts/weapons/sh_triple_threat.gnut
new file mode 100644
index 00000000..eeea91d6
--- /dev/null
+++ b/Northstar.Custom/mod/scripts/vscripts/weapons/sh_triple_threat.gnut
@@ -0,0 +1,249 @@
+untyped
+
+
+global function MpTitanweaponTripleThreat_Init
+global function OnWeaponPrimaryAttack_titanweapon_triplethreat
+
+#if SERVER
+global function OnWeaponNpcPrimaryAttack_titanweapon_triplethreat
+#endif
+
+const FX_MINE_TRAIL = $"Rocket_Smoke_Large"
+const FX_MINE_LIGHT = $"tower_light_red"
+const FX_TRIPLE_IGNITION = $"wpn_grenade_TT_activate"
+const FX_TRIPLE_IGNITION_BURN = $"wpn_grenade_TT_activate"
+const BURN_MAGNETIC_FORCE = 2400
+const MIN_FUSE_TIME = 2.3
+const MAX_FUSE_TIME = 2.7
+const MIN_ROLLING_ROUNDS_FUSE_TIME = 3.2
+const MAX_ROLLING_ROUNDS_FUSE_TIME = 3.7
+
+global const TRIPLETHREAT_LAUNCH_VELOCITY = 1100.0
+global const TRIPLETHREAT_MIN_MINE_FUSE_TIME = 8.2
+global const TRIPLETHREAT_MAX_MINE_FUSE_TIME = 8.8
+global const TRIPLETHREAT_MINE_FIELD_ACTIVATION_TIME = 1.15 //After landing
+global const TRIPLETHREAT_MINE_FIELD_TITAN_ONLY = false
+global const TRIPLETHREAT_MINE_FIELD_MAX_MINES = 9
+global const TRIPLETHREAT_MINE_FIELD_LAUNCH_VELOCITY = 1100
+global const TRIPLETHREAT_NUM_SHOTS = 3
+global const PROX_MINE_RANGE = 200
+
+const TRIPLETHREAT_MAX_BOLTS = 3
+
+struct
+{
+ float[2][TRIPLETHREAT_MAX_BOLTS] boltOffsets = [
+ [0.2, 0.0],
+ [0.2, 2.0], // right
+ [0.2, -2.0], // left
+ ]
+} file
+
+
+function MpTitanweaponTripleThreat_Init()
+{
+ RegisterSignal( "ProxMineTrigger" )
+
+ PrecacheParticleSystem( FX_MINE_TRAIL )
+ PrecacheParticleSystem( FX_MINE_LIGHT )
+ PrecacheParticleSystem( FX_TRIPLE_IGNITION )
+ PrecacheParticleSystem( FX_TRIPLE_IGNITION_BURN )
+}
+
+var function OnWeaponPrimaryAttack_titanweapon_triplethreat( entity weapon, WeaponPrimaryAttackParams attackParams )
+{
+ entity owner = weapon.GetWeaponOwner()
+ float zoomFrac = owner.GetZoomFrac()
+ if ( zoomFrac < 1 && zoomFrac > 0)
+ return 0
+ weapon.EmitWeaponNpcSound( LOUD_WEAPON_AI_SOUND_RADIUS_MP, 0.2 )
+ return FireTripleThreat (weapon, attackParams, true)
+}
+
+#if SERVER
+var function OnWeaponNpcPrimaryAttack_titanweapon_triplethreat( entity weapon, WeaponPrimaryAttackParams attackParams )
+{
+ weapon.EmitWeaponNpcSound( LOUD_WEAPON_AI_SOUND_RADIUS_MP, 0.2 )
+ return FireTripleThreat (weapon, attackParams, false)
+}
+#endif
+
+function FireTripleThreat( entity weapon, WeaponPrimaryAttackParams attackParams, bool playerFired )
+{
+ entity weaponOwner = weapon.GetWeaponOwner()
+
+ bool shouldCreateProjectile = false
+ if ( IsServer() || weapon.ShouldPredictProjectiles() )
+ shouldCreateProjectile = true
+ #if CLIENT
+ if ( !playerFired )
+ shouldCreateProjectile = false
+ #endif
+
+ entity bossPlayer = weaponOwner
+ bool hasRollingRoundsMod = weapon.HasMod( "rolling_rounds" )
+
+ if ( weaponOwner.IsNPC() )
+ bossPlayer = weaponOwner.GetTitanSoul().GetBossPlayer()
+
+ bool inADS = weapon.IsWeaponInAds()
+ vector attackAngles = VectorToAngles( attackParams.dir )
+ vector baseUpVec = AnglesToUp( attackAngles )
+ vector baseRightVec = AnglesToRight( attackAngles )
+
+ if ( shouldCreateProjectile )
+ {
+ int numShots = weapon.GetProjectilesPerShot()
+ float velocity = TRIPLETHREAT_LAUNCH_VELOCITY * 1.2
+ float angleAdjustment = 1
+ if ( weapon.HasMod( "spread_increase_ttt" ) )
+ angleAdjustment = 1.5
+ else if ( weapon.HasMod( "spread_decrease_ttt" ) )
+ angleAdjustment = 0.5
+
+ for ( int i = 0; i < numShots; i++ )
+ {
+ vector upVec = baseUpVec * file.boltOffsets[i][0] * 0.05
+ vector rightVec = baseRightVec * file.boltOffsets[i][1] * angleAdjustment * 0.05
+
+ if ( inADS )
+ {
+ // Instead of swapping for horizontal spread, add it to preserve the y-axis velocity the shots normally have
+ upVec = baseUpVec * (file.boltOffsets[i][0] + file.boltOffsets[i][1] * angleAdjustment) * 0.05
+ rightVec = Vector(0, 0, 0)
+ }
+
+ vector attackVec = attackParams.dir + rightVec + upVec
+
+ if (weapon.HasMod("hydraulic_launcher"))
+ attackVec *= (1.0 + weapon.GetWeaponChargeFraction())
+
+ float fuseTime
+ if( hasRollingRoundsMod )
+ fuseTime = RandomFloatRange( MIN_ROLLING_ROUNDS_FUSE_TIME, MAX_ROLLING_ROUNDS_FUSE_TIME )
+ else
+ fuseTime = RandomFloatRange( MIN_FUSE_TIME, MAX_FUSE_TIME )
+
+ int damageType = damageTypes.explosive
+ if ( weapon.HasMod( "arc_triple_threat" ) )
+ damageType = damageType | damageTypes.electric
+
+ vector angularVelocity = Vector( RandomFloatRange( -velocity, velocity ), 100, 0 )
+
+ FireTripleThreatGrenade( weapon, attackParams.pos, attackVec, angularVelocity, playerFired, fuseTime, damageType )
+ }
+ }
+
+ return 3
+}
+
+function FireTripleThreatGrenade( entity weapon, origin, fwd, velocity, playerFired, float fuseTime, damageType = null )
+{
+ entity weaponOwner = weapon.GetWeaponOwner()
+
+ if ( damageType == null )
+ damageType = damageTypes.explosive
+
+ entity nade = weapon.FireWeaponGrenade( origin, fwd, velocity, 0, damageType, damageType, playerFired, true, true )
+ if ( nade )
+ {
+ nade.InitMagnetic( 1000.0, "Explo_MGL_MagneticAttract" )
+
+ nade.kv.CollideWithOwner = false
+
+ Grenade_Init( nade, weapon )
+ #if SERVER
+ nade.SetOwner( weaponOwner )
+ thread EnableCollision( nade )
+ thread AirPop( nade, fuseTime )
+ thread TrapExplodeOnDamage( nade, 50, 0.0, 0.1 )
+
+ if( weapon.HasMod( "mine_field" ) )
+ nade.s.becomeProxMine <- true
+
+ if( weapon.HasMod( "rolling_rounds" ) )
+ nade.s.rollingRound <- true
+
+ if( weapon.HasMod( "impact_fuse" ) )
+ nade.s.impactFuse <- true
+
+ if( weapon.HasMod( "burn_mod_titan_triple_threat" ) )
+ {
+ nade.s.hasBurnMod <- true
+ nade.InitMagnetic( BURN_MAGNETIC_FORCE, "Explo_TripleThreat_MagneticAttract" )
+ //EmitSoundOnEntity( nade, "Weapon_R1_MGL_Grenade_Emitter" )
+ }
+ #else
+ SetTeam( nade, weaponOwner.GetTeam() )
+ #endif
+
+ return nade
+ }
+}
+
+function EnableCollision( entity grenade )
+{
+ grenade.EndSignal("OnDestroy")
+
+ wait 1.0
+ grenade.kv.CollideWithOwner = true
+}
+
+function AirPop( entity grenade, float fuseTime )
+{
+ grenade.EndSignal( "OnDestroy" )
+
+ float popDelay = RandomFloatRange( 0.2, 0.3 )
+
+ string waitSignal = "Planted" // Signal triggered when mine sticks to something
+ local waitResult = WaitSignalTimeout( grenade, (fuseTime - (popDelay + 0.2)), waitSignal )
+
+ // Only enter here if the mine stuck to something
+ if ( waitResult != null && waitResult.signal == waitSignal )
+ {
+ fuseTime = RandomFloatRange( TRIPLETHREAT_MIN_MINE_FUSE_TIME, TRIPLETHREAT_MAX_MINE_FUSE_TIME )
+ waitSignal = "ProxMineTrigger"
+ waitResult = WaitSignalTimeout( grenade, (fuseTime - (popDelay + 0.2)), waitSignal )
+
+ // Mine was triggered via proximity
+ if ( waitResult != null && waitResult.signal == waitSignal )
+ EmitSoundOnEntity( grenade, "NPE_Missile_Alarm") // TEMP - Replace with a real sound
+ }
+
+ asset effect = FX_TRIPLE_IGNITION
+ if( "hasBurnMod" in grenade.s && grenade.s.hasBurnMod )
+ effect = FX_TRIPLE_IGNITION_BURN
+
+ int fxId = GetParticleSystemIndex( effect )
+ StartParticleEffectOnEntity( grenade, fxId, FX_PATTACH_ABSORIGIN_FOLLOW, -1 )
+
+ EmitSoundOnEntity( grenade, "Triple_Threat_Grenade_Charge" )
+
+ float popSpeed = RandomFloatRange( 40.0, 64.0 )
+ vector popVelocity = Vector ( 0, 0, popSpeed )
+ vector normal = Vector( 0, 0, 1 )
+ if( "becomeProxMine" in grenade.s && grenade.s.becomeProxMine == true )
+ {
+ //grenade.ClearParent()
+ if( "collisionNormal" in grenade.s )
+ {
+ normal = expect vector( grenade.s.collisionNormal )
+ popVelocity = expect vector( grenade.s.collisionNormal ) * popSpeed
+ }
+ }
+
+ vector newPosition = grenade.GetOrigin() + popVelocity
+ grenade.SetVelocity( GetVelocityForDestOverTime( grenade.GetOrigin(), newPosition, popDelay ) )
+
+ wait popDelay
+ TripleThreat_Explode( grenade )
+}
+
+function TripleThreat_Explode( entity grenade )
+{
+ vector normal = Vector( 0, 0, 1 )
+ if( "collisionNormal" in grenade.s )
+ normal = expect vector( grenade.s.collisionNormal )
+
+ grenade.GrenadeExplode( normal )
+}