aboutsummaryrefslogtreecommitdiff
path: root/Northstar.CustomServers/mod/scripts/vscripts/_passives.gnut
diff options
context:
space:
mode:
Diffstat (limited to 'Northstar.CustomServers/mod/scripts/vscripts/_passives.gnut')
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/_passives.gnut1657
1 files changed, 1657 insertions, 0 deletions
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/_passives.gnut b/Northstar.CustomServers/mod/scripts/vscripts/_passives.gnut
new file mode 100644
index 000000000..1264686ec
--- /dev/null
+++ b/Northstar.CustomServers/mod/scripts/vscripts/_passives.gnut
@@ -0,0 +1,1657 @@
+untyped
+
+global function Passives_Init
+
+global function InitPassives
+global function GivePassive
+global function GivePassiveLifeLong
+global function GiveTitanPassiveLifeLong
+global function TakePassive
+global function TakeAllPassives
+global function ScanMinimap
+global function MinimapPlayerConnected
+global function SoulHasPassive
+global function ScanMinimapUntilDeath
+global function GivePlayerPassivesFromSoul
+global function PrintAllPassives
+
+global function IsConscript
+
+global function UpdateMinimapStatusToOtherPlayers
+global function UpdateTitanMinimapStatusToOtherPlayers
+global function UpdateAIMinimapStatusToOtherPlayers
+global function UpdateMinimapStatus // moves to minimap script eventually?
+global function ApplyTitanWeaponPassives
+global function UpdateScorchHotStreakCoreMeter
+#if MP
+global function ApplyFDUpgradeWeaponPassives
+global function ApplyFDDerviedUpgrades
+#endif
+
+const FD_HOT_STREAK_DAMAGE_MAX = 10000
+const FD_HOT_STREAK_DECAY_TIME = 30.0 //1/2 this value until it the hotstreak falls off. 1/2 the value until it goes from full to empty.
+//const FD_HOT_STREAK_CORE_MULTIPLIER_MAX = 0.5
+
+function Passives_Init()
+{
+ RegisterSignal( "EndCloakedWallHangs" )
+ RegisterSignal( "EndCloakedWallruns" )
+
+ AddSpawnCallback( "npc_spectre", MinimapNPCSpawned )
+ AddSpawnCallback( "npc_soldier", MinimapNPCSpawned )
+ AddDeathCallback( "player", PassiveDeathCallback )
+
+ AddCallback_OnTitanGetsNewTitanLoadout( ApplyTitanWeaponPassives )
+
+ #if MP
+ if ( GetCurrentPlaylistVarInt( "aegis_upgrades", 0 ) == 1 )
+ AddCallback_OnUpdateDerivedPlayerTitanLoadout( ApplyFDDerviedUpgrades ) //Half of the meta functions, the other half lives in passives.gnut This is used for class mods.
+ #endif
+
+ level.wifiLeachInterval <- 2.5
+}
+
+function InitPassives( entity player )
+{
+ player.s.removePassiveOnDeath <- {}
+}
+
+#if MP
+void function ApplyFDDerviedUpgrades( entity player, TitanLoadoutDef loadout )
+{
+ array<ItemData> fdUpgrades = GetAllItemsOfType( eItemTypes.TITAN_FD_UPGRADE )
+ array<string> upgradeRefs
+ foreach ( ItemData upgrade in fdUpgrades )
+ {
+ if ( loadout.titanClass == upgrade.parentRef && !IsSubItemLocked( player, upgrade.ref, upgrade.parentRef ) )
+ {
+ upgradeRefs.append( upgrade.ref )
+ }
+ }
+ if ( loadout.titanClass == "ronin" )
+ ApplyDerivedRoninFDUpgrades( upgradeRefs, loadout )
+ else if ( loadout.titanClass == "northstar" )
+ ApplyDerivedNorthstarFDUpgrades( upgradeRefs, loadout )
+ else if ( loadout.titanClass == "vanguard" )
+ ApplyDerivedVanguardFDUpgrades( upgradeRefs, loadout )
+ else if ( loadout.titanClass == "ion" )
+ ApplyDerivedIonFDUpgrades( upgradeRefs, loadout )
+ else if ( loadout.titanClass == "tone" )
+ ApplyDerivedToneFDUpgrades( upgradeRefs, loadout )
+ else if ( loadout.titanClass == "scorch" )
+ ApplyDerivedScorchFDUpgrades( upgradeRefs, loadout )
+ else if ( loadout.titanClass == "legion" )
+ ApplyDerivedLegionFDUpgrades( upgradeRefs, loadout )
+}
+
+void function ApplyFDUpgradeWeaponPassives( entity titan, TitanLoadoutDef loadout )
+{
+ entity player
+ if ( titan.IsPlayer() )
+ player = titan
+ else if ( IsValid( titan.mySpawnOptions_ownerPlayer ) )
+ player = expect entity( titan.mySpawnOptions_ownerPlayer )
+ else
+ player = titan.GetBossPlayer()
+
+ if ( !IsValid( player ) )
+ return
+
+ array<ItemData> fdUpgrades = GetAllItemsOfType( eItemTypes.TITAN_FD_UPGRADE )
+ array<string> upgradeRefs
+ foreach ( ItemData upgrade in fdUpgrades )
+ {
+ if ( loadout.titanClass == upgrade.parentRef && !IsSubItemLocked( player, upgrade.ref, upgrade.parentRef ) )
+ upgradeRefs.append( upgrade.ref )
+ }
+
+ if ( loadout.titanClass == "ronin" )
+ ApplyRoninFDUpgrades( upgradeRefs, titan, loadout )
+ else if ( loadout.titanClass == "northstar" )
+ ApplyNorthstarFDUpgrades( upgradeRefs, titan, loadout )
+ else if ( loadout.titanClass == "vanguard" )
+ ApplyVanguardFDUpgrades( upgradeRefs, titan, loadout )
+ else if ( loadout.titanClass == "ion" )
+ ApplyIonFDUpgrades( upgradeRefs, titan, loadout )
+ else if ( loadout.titanClass == "tone" )
+ ApplyToneFDUpgrades( upgradeRefs, titan, loadout )
+ else if ( loadout.titanClass == "scorch" )
+ ApplyScorchFDUpgrades( upgradeRefs, titan, loadout )
+ else if ( loadout.titanClass == "legion" )
+ ApplyLegionFDUpgrades( upgradeRefs, titan, loadout )
+}
+
+void function ApplyDerivedRoninFDUpgrades( array<string> upgradeRefs, TitanLoadoutDef loadout )
+{
+ foreach ( upgrade in upgradeRefs )
+ {
+ switch ( upgrade )
+ {
+ case "fd_upgrade_ronin_defense_tier_1":
+ loadout.setFileMods.append( "fd_health_upgrade" )
+ break
+ }
+ }
+}
+
+void function ApplyRoninFDUpgrades( array<string> upgradeRefs, entity titan, TitanLoadoutDef loadout )
+{
+ entity soul = titan.GetTitanSoul()
+ if ( !IsValid( soul ) ) //Ejecting
+ return
+
+ foreach ( upgrade in upgradeRefs )
+ {
+ switch ( upgrade )
+ {
+ case "fd_upgrade_ronin_utility_tier_1":
+ entity weapon = titan.GetOffhandWeapon( OFFHAND_ANTIRODEO )
+ array<string> mods = weapon.GetMods()
+ mods.append( "fd_phase_charges" )
+ weapon.SetMods( mods )
+ break
+ case "fd_upgrade_ronin_utility_tier_2":
+ entity weapon = titan.GetOffhandWeapon( OFFHAND_ANTIRODEO )
+ array<string> mods = weapon.GetMods()
+ mods.append( "fd_phase_distance" )
+ weapon.SetMods( mods )
+ break
+ case "fd_upgrade_ronin_defense_tier_2":
+ float titanShieldHealth = GetTitanSoulShieldHealth( soul )
+ soul.SetShieldHealthMax( int( titanShieldHealth * 1.5 ) )
+ break
+ case "fd_upgrade_ronin_weapon_tier_1":
+ entity weapon = titan.GetOffhandWeapon( OFFHAND_MELEE )
+ array<string> mods = weapon.GetMods()
+ mods.append( "fd_sword_upgrade" )
+ weapon.SetMods( mods )
+ break
+ case "fd_upgrade_ronin_weapon_tier_2":
+ entity weapon = titan.GetOffhandWeapon( OFFHAND_LEFT )
+ array<string> mods = weapon.GetMods()
+ mods.append( "fd_sword_block" )
+ weapon.SetMods( mods )
+ break
+ case "fd_upgrade_ronin_ultimate":
+ entity weapon = titan.GetOffhandWeapon( OFFHAND_EQUIPMENT )
+ array<string> mods = weapon.GetMods()
+ mods.append( "fd_duration" )
+ weapon.SetMods( mods )
+ break
+ }
+ }
+}
+
+void function ApplyDerivedNorthstarFDUpgrades( array<string> upgradeRefs, TitanLoadoutDef loadout )
+{
+ foreach ( upgrade in upgradeRefs )
+ {
+ switch ( upgrade )
+ {
+ case "fd_upgrade_northstar_defense_tier_1":
+ loadout.setFileMods.append( "fd_health_upgrade" )
+ break
+ }
+ }
+}
+
+void function ApplyNorthstarFDUpgrades( array<string> upgradeRefs, entity titan, TitanLoadoutDef loadout )
+{
+ entity soul = titan.GetTitanSoul()
+ if ( !IsValid( soul ) ) //Ejecting
+ return
+
+ foreach ( upgrade in upgradeRefs )
+ {
+ switch ( upgrade )
+ {
+ case "fd_upgrade_northstar_utility_tier_1":
+ entity weapon = titan.GetOffhandWeapon( OFFHAND_LEFT )
+ array<string> mods = weapon.GetMods()
+ mods.append( "fd_explosive_trap" )
+ weapon.SetMods( mods )
+ break
+ case "fd_upgrade_northstar_utility_tier_2":
+ entity weapon = titan.GetOffhandWeapon( OFFHAND_LEFT )
+ array<string> mods = weapon.GetMods()
+ mods.append( "fd_trap_charges" )
+ weapon.SetMods( mods )
+ break
+ case "fd_upgrade_northstar_defense_tier_2":
+ float titanShieldHealth = GetTitanSoulShieldHealth( soul )
+ soul.SetShieldHealthMax( int( titanShieldHealth * 1.5 ) )
+ break
+ case "fd_upgrade_northstar_weapon_tier_1":
+ entity weapon = titan.GetMainWeapons()[0]
+ array<string> mods = weapon.GetMods()
+ mods.append( "fd_upgrade_charge" )
+ weapon.SetMods( mods )
+ break
+ case "fd_upgrade_northstar_weapon_tier_2":
+ entity weapon = titan.GetMainWeapons()[0]
+ array<string> mods = weapon.GetMods()
+ mods.append( "fd_upgrade_crit" )
+ weapon.SetMods( mods )
+ break
+ case "fd_upgrade_northstar_ultimate":
+ entity weapon = titan.GetOffhandWeapon( OFFHAND_RIGHT )
+ array<string> mods = weapon.GetMods()
+ mods.append( "fd_twin_cluster" )
+ weapon.SetMods( mods )
+ break
+ }
+ }
+}
+
+void function ApplyDerivedVanguardFDUpgrades( array<string> upgradeRefs, TitanLoadoutDef loadout )
+{
+ foreach ( upgrade in upgradeRefs )
+ {
+ switch ( upgrade )
+ {
+ case "fd_upgrade_vanguard_defense_tier_1":
+ loadout.setFileMods.append( "fd_health_upgrade" )
+ break
+ }
+ }
+}
+
+void function ApplyVanguardFDUpgrades( array<string> upgradeRefs, entity titan, TitanLoadoutDef loadout )
+{
+ entity soul = titan.GetTitanSoul()
+ if ( !IsValid( soul ) ) //Ejecting
+ return
+
+ entity primaryWeapon = titan.GetMainWeapons()[0]
+ array<string> primaryMods = primaryWeapon.GetMods()
+ primaryMods.append( "fd_balance" )
+ primaryWeapon.SetMods( primaryMods )
+
+ entity ordanance = titan.GetOffhandWeapon( OFFHAND_RIGHT )
+ array<string> ordananceMods = ordanance.GetMods()
+ ordananceMods.append( "fd_balance" )
+ ordanance.SetMods( ordananceMods )
+
+ foreach ( upgrade in upgradeRefs )
+ {
+ switch ( upgrade )
+ {
+ case "fd_upgrade_vanguard_utility_tier_1":
+ entity weapon = titan.GetMainWeapons()[0]
+ array<string> mods = weapon.GetMods()
+ mods.append( "fd_vanguard_utility_1" )
+ weapon.SetMods( mods )
+ break
+ case "fd_upgrade_vanguard_utility_tier_2":
+ entity weapon = titan.GetMainWeapons()[0]
+ array<string> mods = weapon.GetMods()
+ mods.append( "fd_vanguard_utility_2" )
+ weapon.SetMods( mods )
+ break
+ case "fd_upgrade_vanguard_defense_tier_2":
+ float titanShieldHealth = GetTitanSoulShieldHealth( soul )
+ soul.SetShieldHealthMax( int( titanShieldHealth * 1.5 ) )
+ break
+ case "fd_upgrade_vanguard_weapon_tier_1":
+ entity weapon = titan.GetMainWeapons()[0]
+ array<string> mods = weapon.GetMods()
+ mods.append( "fd_vanguard_weapon_1" )
+ weapon.SetMods( mods )
+ break
+ case "fd_upgrade_vanguard_weapon_tier_2":
+ entity weapon = titan.GetMainWeapons()[0]
+ array<string> mods = weapon.GetMods()
+ mods.append( "fd_vanguard_weapon_2" )
+ weapon.SetMods( mods )
+ break
+ case "fd_upgrade_vanguard_ultimate":
+ if ( SoulHasPassive( soul, ePassives.PAS_VANGUARD_CORE1 ) ) //Has Arc Rounds, Choose Energy Transfer or Missile Racks
+ {
+ if ( RandomIntRange( 1, 100 ) <= 50 )
+ {
+ entity offhandWeapon = titan.GetOffhandWeapon( OFFHAND_RIGHT )
+ if ( IsValid( offhandWeapon ) )
+ {
+ array<string> mods = offhandWeapon.GetMods()
+ mods.append( "missile_racks" )
+ offhandWeapon.SetMods( mods )
+ }
+ }
+ else
+ {
+ entity offhandWeapon = titan.GetOffhandWeapon( OFFHAND_LEFT )
+ if ( IsValid( offhandWeapon ) )
+ {
+ array<string> mods = offhandWeapon.GetMods()
+ mods.append( "energy_transfer" )
+ offhandWeapon.SetMods( mods )
+ }
+ }
+ }
+ else if ( SoulHasPassive( soul, ePassives.PAS_VANGUARD_CORE2 ) ) //Has Missile Racks, Choose Energy Transfer or Arc Rounds
+ {
+ if ( RandomIntRange( 1, 100 ) <= 50 )
+ {
+ array<entity> weapons = GetPrimaryWeapons( titan )
+ if ( weapons.len() > 0 )
+ {
+ entity primaryWeapon = weapons[0]
+ if ( IsValid( primaryWeapon ) )
+ {
+ array<string> mods = primaryWeapon.GetMods()
+ mods.append( "arc_rounds" )
+ primaryWeapon.SetMods( mods )
+ primaryWeapon.SetWeaponPrimaryClipCount( primaryWeapon.GetWeaponPrimaryClipCountMax() )
+ }
+ }
+ }
+ else
+ {
+ entity offhandWeapon = titan.GetOffhandWeapon( OFFHAND_LEFT )
+ if ( IsValid( offhandWeapon ) )
+ {
+ array<string> mods = offhandWeapon.GetMods()
+ mods.append( "energy_transfer" )
+ offhandWeapon.SetMods( mods )
+ }
+ }
+ }
+ else if ( SoulHasPassive( soul, ePassives.PAS_VANGUARD_CORE3 ) ) //Has Energy Transfer, Choose Arc Rounds or Missile Racks
+ {
+ if ( RandomIntRange( 1, 100 ) <= 50 )
+ {
+ array<entity> weapons = GetPrimaryWeapons( titan )
+ if ( weapons.len() > 0 )
+ {
+ entity primaryWeapon = weapons[0]
+ if ( IsValid( primaryWeapon ) )
+ {
+ array<string> mods = primaryWeapon.GetMods()
+ mods.append( "arc_rounds" )
+ primaryWeapon.SetMods( mods )
+ primaryWeapon.SetWeaponPrimaryClipCount( primaryWeapon.GetWeaponPrimaryClipCountMax() )
+ }
+ }
+ }
+ else
+ {
+ entity offhandWeapon = titan.GetOffhandWeapon( OFFHAND_RIGHT )
+ if ( IsValid( offhandWeapon ) )
+ {
+ array<string> mods = offhandWeapon.GetMods()
+ mods.append( "missile_racks" )
+ offhandWeapon.SetMods( mods )
+ }
+ }
+ }
+ break
+ }
+ }
+}
+
+void function ApplyDerivedIonFDUpgrades( array<string> upgradeRefs, TitanLoadoutDef loadout )
+{
+ foreach ( upgrade in upgradeRefs )
+ {
+ switch ( upgrade )
+ {
+ case "fd_upgrade_ion_utility_tier_1":
+ loadout.setFileMods.append( "fd_energy_regen" )
+ break
+ case "fd_upgrade_ion_utility_tier_2":
+ loadout.setFileMods.append( "fd_energy_max" )
+ break
+ case "fd_upgrade_ion_defense_tier_1":
+ loadout.setFileMods.append( "fd_health_upgrade" )
+ break
+ }
+ }
+}
+
+void function ApplyIonFDUpgrades( array<string> upgradeRefs, entity titan, TitanLoadoutDef loadout )
+{
+ entity soul = titan.GetTitanSoul()
+ if ( !IsValid( soul ) ) //Ejecting
+ return
+
+ entity primaryWeapon = titan.GetMainWeapons()[0]
+ array<string> primaryMods = primaryWeapon.GetMods()
+ primaryMods.append( "fd_balance" )
+ primaryWeapon.SetMods( primaryMods )
+
+ entity ordanance = titan.GetOffhandWeapon( OFFHAND_RIGHT )
+ array<string> ordananceMods = ordanance.GetMods()
+ ordananceMods.append( "fd_balance" )
+ ordanance.SetMods( ordananceMods )
+
+ //entity utilityWeapon = titan.GetOffhandWeapon( OFFHAND_ANTIRODEO )
+ //array<string> utilityMods = utilityWeapon.GetMods()
+ //utilityMods.append( "fd_balance" )
+ //utilityWeapon.SetMods( utilityMods )
+
+ entity coreWeapon = titan.GetOffhandWeapon( OFFHAND_EQUIPMENT )
+ array<string> coreMods = coreWeapon.GetMods()
+ coreMods.append( "fd_balance" )
+ coreWeapon.SetMods( coreMods )
+
+ foreach ( upgrade in upgradeRefs )
+ {
+ switch ( upgrade )
+ {
+ case "fd_upgrade_ion_defense_tier_2":
+ float titanShieldHealth = GetTitanSoulShieldHealth( soul )
+ soul.SetShieldHealthMax( int( titanShieldHealth * 1.5 ) )
+ break
+ case "fd_upgrade_ion_weapon_tier_1":
+ entity ordanance = titan.GetOffhandWeapon( OFFHAND_RIGHT )
+ array<string> ordananceMods = ordanance.GetMods()
+ ordananceMods.append( "fd_laser_upgrade" )
+ ordanance.SetMods( ordananceMods )
+ break
+ case "fd_upgrade_ion_weapon_tier_2":
+ entity weapon = titan.GetMainWeapons()[0]
+ array<string> mods = weapon.GetMods()
+ mods.append( "fd_split_shot_cost" )
+ weapon.SetMods( mods )
+ break
+
+ case "fd_upgrade_ion_ultimate":
+ entity weapon = titan.GetOffhandWeapon( OFFHAND_EQUIPMENT )
+ array<string> mods = weapon.GetMods()
+ mods.append( "fd_laser_cannon" )
+ weapon.SetMods( mods )
+ break
+ }
+ }
+}
+
+void function ApplyDerivedToneFDUpgrades( array<string> upgradeRefs, TitanLoadoutDef loadout )
+{
+ foreach ( upgrade in upgradeRefs )
+ {
+ switch ( upgrade )
+ {
+ case "fd_upgrade_tone_defense_tier_1":
+ loadout.setFileMods.append( "fd_health_upgrade" )
+ break
+ }
+ }
+}
+
+void function ApplyToneFDUpgrades( array<string> upgradeRefs, entity titan, TitanLoadoutDef loadout )
+{
+ entity soul = titan.GetTitanSoul()
+ if ( !IsValid( soul ) ) //Ejecting
+ return
+
+ foreach ( upgrade in upgradeRefs )
+ {
+ switch ( upgrade )
+ {
+ case "fd_upgrade_tone_utility_tier_1":
+ entity weapon = titan.GetOffhandWeapon( OFFHAND_ANTIRODEO )
+ array<string> mods = weapon.GetMods()
+ mods.append( "fd_sonar_duration" )
+ weapon.SetMods( mods )
+ break
+ case "fd_upgrade_tone_utility_tier_2":
+ entity weapon = titan.GetOffhandWeapon( OFFHAND_ANTIRODEO )
+ array<string> mods = weapon.GetMods()
+ mods.append( "fd_sonar_damage_amp" )
+ weapon.SetMods( mods )
+ break
+ case "fd_upgrade_tone_defense_tier_2":
+ float titanShieldHealth = GetTitanSoulShieldHealth( soul )
+ soul.SetShieldHealthMax( int( titanShieldHealth * 1.5 ) )
+ break
+ case "fd_upgrade_tone_weapon_tier_1":
+ entity weapon = titan.GetMainWeapons()[0]
+ array<string> mods = weapon.GetMods()
+ mods.append( "fd_splasher_rounds" )
+ weapon.SetMods( mods )
+ break
+ case "fd_upgrade_tone_weapon_tier_2":
+ entity weapon = titan.GetMainWeapons()[0]
+ array<string> mods = weapon.GetMods()
+ mods.append( "fd_tone_weapon_2" )
+ weapon.SetMods( mods )
+ weapon.SetWeaponPrimaryClipCount( weapon.GetWeaponPrimaryClipCountMax() )
+ break
+ case "fd_upgrade_tone_ultimate":
+ entity weapon = titan.GetOffhandWeapon( OFFHAND_EQUIPMENT )
+ array<string> mods = weapon.GetMods()
+ mods.append( "fd_salvo_core" )
+ weapon.SetMods( mods )
+ break
+ }
+ }
+}
+
+void function ApplyDerivedScorchFDUpgrades( array<string> upgradeRefs, TitanLoadoutDef loadout )
+{
+ foreach ( upgrade in upgradeRefs )
+ {
+ switch ( upgrade )
+ {
+ case "fd_upgrade_scorch_defense_tier_1":
+ loadout.setFileMods.append( "fd_health_upgrade" )
+ break
+ }
+ }
+}
+
+void function ApplyScorchFDUpgrades( array<string> upgradeRefs, entity titan, TitanLoadoutDef loadout )
+{
+ entity soul = titan.GetTitanSoul()
+ if ( !IsValid( soul ) ) //Ejecting
+ return
+
+ foreach ( upgrade in upgradeRefs )
+ {
+ switch ( upgrade )
+ {
+ case "fd_upgrade_scorch_utility_tier_1":
+ entity weapon = titan.GetMainWeapons()[0]
+ array<string> mods = weapon.GetMods()
+ mods.append( "fd_hot_streak" )
+ weapon.SetMods( mods )
+ break
+ case "fd_upgrade_scorch_utility_tier_2":
+ entity weapon = titan.GetMainWeapons()[0]
+ array<string> mods = weapon.GetMods()
+ mods.append( "fd_fire_damage_upgrade" )
+ weapon.SetMods( mods )
+ break
+ case "fd_upgrade_scorch_defense_tier_2":
+ float titanShieldHealth = GetTitanSoulShieldHealth( soul )
+ soul.SetShieldHealthMax( int( titanShieldHealth * 1.5 ) )
+ break
+ case "fd_upgrade_scorch_weapon_tier_1":
+ entity weapon = titan.GetMainWeapons()[0]
+ array<string> mods = weapon.GetMods()
+ if ( !mods.contains( "fd_wpn_upgrade_2" ) )
+ {
+ mods.append( "fd_wpn_upgrade_1" )
+ weapon.SetMods( mods )
+ weapon.SetWeaponPrimaryClipCount( weapon.GetWeaponPrimaryClipCountMax() )
+ }
+ break
+ case "fd_upgrade_scorch_weapon_tier_2":
+ entity weapon = titan.GetMainWeapons()[0]
+ array<string> mods = weapon.GetMods()
+ mods.fastremovebyvalue( "fd_wpn_upgrade_1" )
+ mods.append( "fd_wpn_upgrade_2" )
+ weapon.SetMods( mods )
+ weapon.SetWeaponPrimaryClipCount( weapon.GetWeaponPrimaryClipCountMax() )
+ break
+ case "fd_upgrade_scorch_ultimate":
+ entity weapon = titan.GetOffhandWeapon( OFFHAND_ANTIRODEO )
+ array<string> mods = weapon.GetMods()
+ mods.append( "fd_explosive_barrel" )
+ weapon.SetMods( mods )
+ break
+ }
+ }
+}
+
+void function ApplyDerivedLegionFDUpgrades( array<string> upgradeRefs, TitanLoadoutDef loadout )
+{
+ foreach ( upgrade in upgradeRefs )
+ {
+ switch ( upgrade )
+ {
+ case "fd_upgrade_legion_defense_tier_1":
+ loadout.setFileMods.append( "fd_health_upgrade" )
+ break
+ }
+ }
+}
+
+void function ApplyLegionFDUpgrades( array<string> upgradeRefs, entity titan, TitanLoadoutDef loadout )
+{
+ entity soul = titan.GetTitanSoul()
+ if ( !IsValid( soul ) ) //Ejecting
+ return
+
+ foreach ( upgrade in upgradeRefs )
+ {
+ switch ( upgrade )
+ {
+ case "fd_upgrade_legion_utility_tier_1":
+ entity weapon = titan.GetMainWeapons()[0]
+ array<string> mods = weapon.GetMods()
+ mods.append( "fd_closerange_helper" )
+ weapon.SetMods( mods )
+ break
+ case "fd_upgrade_legion_utility_tier_2":
+ entity weapon = titan.GetMainWeapons()[0]
+ array<string> mods = weapon.GetMods()
+ mods.append( "fd_longrange_helper" )
+ weapon.SetMods( mods )
+ break
+ case "fd_upgrade_legion_defense_tier_2":
+ float titanShieldHealth = GetTitanSoulShieldHealth( soul )
+ soul.SetShieldHealthMax( int( titanShieldHealth * 1.5 ) )
+ break
+ case "fd_upgrade_legion_weapon_tier_1":
+ entity weapon = titan.GetMainWeapons()[0]
+ array<string> mods = weapon.GetMods()
+ mods.append( "fd_piercing_shots" )
+ weapon.SetMods( mods )
+ break
+ case "fd_upgrade_legion_weapon_tier_2":
+ entity weapon = titan.GetMainWeapons()[0]
+ array<string> mods = weapon.GetMods()
+ mods.append( "fd_gun_shield_redirect" )
+ weapon.SetMods( mods )
+ break
+ case "fd_upgrade_legion_ultimate":
+ entity weapon = titan.GetMainWeapons()[0]
+ array<string> mods = weapon.GetMods()
+ if ( !mods.contains( "pas_legion_weapon" ) )
+ {
+ mods.append( "pas_legion_weapon" )
+ weapon.SetMods( mods )
+ weapon.SetWeaponPrimaryClipCount( weapon.GetWeaponPrimaryClipCountMax() )
+ }
+ if ( !mods.contains( "pas_legion_spinup" ) )
+ {
+ mods.append( "pas_legion_spinup" )
+ weapon.SetMods( mods )
+ }
+ weapon = titan.GetOffhandWeapon( OFFHAND_EQUIPMENT )
+ mods = weapon.GetMods()
+ if ( !mods.contains( "pas_legion_smartcore" ) )
+ {
+ mods.append( "pas_legion_smartcore" )
+ }
+ weapon.SetMods( mods )
+ weapon = titan.GetOffhandWeapon( OFFHAND_RIGHT )
+ mods = weapon.GetMods()
+ if ( !mods.contains( "pas_legion_chargeshot" ) )
+ {
+ mods.append( "pas_legion_chargeshot" )
+ }
+ weapon.SetMods( mods )
+ weapon = titan.GetOffhandWeapon( OFFHAND_LEFT )
+ mods = weapon.GetMods()
+ mods.append( "fd_gun_shield" )
+ weapon.SetMods( mods )
+ break
+ }
+ }
+}
+#endif
+
+void function ApplyTitanWeaponPassives( entity titan, TitanLoadoutDef loadout )
+{
+ entity soul = titan.GetTitanSoul()
+ if ( !IsValid( soul ) ) //Ejecting
+ return
+
+ if ( loadout.titanClass == "ronin" && loadout.isPrime == "titan_is_prime" )
+ {
+ array<int> offhandSlots = [ OFFHAND_MELEE, OFFHAND_LEFT, OFFHAND_RIGHT ]
+
+ foreach ( slot in offhandSlots )
+ {
+ entity weapon = titan.GetOffhandWeapon( slot )
+ array<string> mods = weapon.GetMods()
+ mods.append( "modelset_prime" )
+ weapon.SetMods( mods )
+ }
+ }
+
+ foreach ( passive, value in soul.passives )
+ {
+ if ( !value )
+ continue
+
+ switch ( passive )
+ {
+ case ePassives.PAS_ION_TRIPWIRE:
+ entity weapon = titan.GetOffhandWeapon( OFFHAND_ANTIRODEO )
+ array<string> mods = weapon.GetMods()
+ mods.append( "pas_ion_tripwire" )
+ weapon.SetMods( mods )
+ break
+
+ case ePassives.PAS_ION_VORTEX:
+ entity weapon = titan.GetOffhandWeapon( OFFHAND_LEFT )
+ array<string> mods = weapon.GetMods()
+ mods.append( "pas_ion_vortex" )
+ weapon.SetMods( mods )
+ break
+
+ case ePassives.PAS_ION_LASERCANNON:
+ entity weapon = titan.GetOffhandWeapon( OFFHAND_EQUIPMENT )
+ array<string> mods = weapon.GetMods()
+ mods.append( "pas_ion_lasercannon" )
+ weapon.SetMods( mods )
+ break
+
+ case ePassives.PAS_ION_WEAPON_ADS:
+ entity weapon = titan.GetMainWeapons()[0]
+ array<string> mods = weapon.GetMods()
+ mods.append( "pas_ion_weapon_ads" )
+ weapon.SetMods( mods )
+ break
+
+ case ePassives.PAS_NORTHSTAR_WEAPON:
+ entity weapon = titan.GetMainWeapons()[0]
+ array<string> mods = weapon.GetMods()
+ mods.append( "pas_northstar_weapon" )
+ weapon.SetMods( mods )
+ break
+
+ case ePassives.PAS_NORTHSTAR_TRAP:
+ entity weapon = titan.GetOffhandWeapon( OFFHAND_LEFT )
+ array<string> mods = weapon.GetMods()
+ mods.append( "pas_northstar_trap" )
+ weapon.SetMods( mods )
+ break
+
+ case ePassives.PAS_NORTHSTAR_CLUSTER:
+ entity weapon = titan.GetOffhandWeapon( OFFHAND_RIGHT )
+ array<string> mods = weapon.GetMods()
+ mods.append( "pas_northstar_cluster" )
+ weapon.SetMods( mods )
+ break
+
+ case ePassives.PAS_NORTHSTAR_OPTICS:
+ entity weapon = titan.GetMainWeapons()[0]
+ array<string> mods = weapon.GetMods()
+ mods.append( "pas_northstar_optics" )
+ weapon.SetMods( mods )
+ break
+
+ case ePassives.PAS_SCORCH_SELFDMG:
+ soul.SetPreventCrits( true )
+ break
+
+ case ePassives.PAS_SCORCH_WEAPON:
+ entity weapon = titan.GetMainWeapons()[0]
+ array<string> mods = weapon.GetMods()
+ mods.append( "pas_scorch_weapon" )
+ weapon.SetMods( mods )
+ break
+
+ case ePassives.PAS_SCORCH_SHIELD:
+ entity weapon = titan.GetOffhandWeapon( OFFHAND_LEFT )
+ array<string> mods = weapon.GetMods()
+ mods.append( "pas_scorch_shield" )
+ weapon.SetMods( mods )
+ break
+
+ case ePassives.PAS_SCORCH_FIREWALL:
+ entity weapon = titan.GetOffhandWeapon( OFFHAND_RIGHT )
+ array<string> mods = weapon.GetMods()
+ mods.append( "pas_scorch_firewall" )
+ weapon.SetMods( mods )
+ break
+
+ case ePassives.PAS_SCORCH_FLAMECORE:
+ entity weapon = titan.GetOffhandWeapon( OFFHAND_EQUIPMENT )
+ array<string> mods = weapon.GetMods()
+ mods.append( "pas_scorch_flamecore" )
+ weapon.SetMods( mods )
+ break
+
+ case ePassives.PAS_LEGION_WEAPON:
+ entity weapon = titan.GetMainWeapons()[0]
+ array<string> mods = weapon.GetMods()
+ mods.append( "pas_legion_weapon" )
+ weapon.SetMods( mods )
+ int max = weapon.GetWeaponPrimaryClipCountMax()
+ weapon.SetWeaponPrimaryClipCount( max )
+ break
+
+ case ePassives.PAS_LEGION_SPINUP:
+ entity weapon = titan.GetMainWeapons()[0]
+ array<string> mods = weapon.GetMods()
+ mods.append( "pas_legion_spinup" )
+ weapon.SetMods( mods )
+ break
+
+ case ePassives.PAS_LEGION_SMARTCORE:
+ entity weapon = titan.GetOffhandWeapon( OFFHAND_EQUIPMENT )
+ array<string> mods = weapon.GetMods()
+ mods.append( "pas_legion_smartcore" )
+ weapon.SetMods( mods )
+ break
+
+ case ePassives.PAS_LEGION_CHARGESHOT:
+ entity weapon = titan.GetOffhandWeapon( OFFHAND_ORDNANCE )
+ array<string> mods = weapon.GetMods()
+ mods.append( "pas_legion_chargeshot" )
+ weapon.SetMods( mods )
+ break
+
+ case ePassives.PAS_TONE_WEAPON:
+ entity weapon = titan.GetMainWeapons()[0]
+ array<string> mods = weapon.GetMods()
+ mods.append( "pas_tone_weapon" )
+ weapon.SetMods( mods )
+ break
+
+ case ePassives.PAS_TONE_BURST:
+ entity weapon = titan.GetMainWeapons()[0]
+ array<string> mods = weapon.GetMods()
+ mods.append( "pas_tone_burst" )
+ weapon.SetMods( mods )
+ break
+
+ case ePassives.PAS_TONE_ROCKETS:
+ entity weapon = titan.GetOffhandWeapon( OFFHAND_RIGHT )
+ array<string> mods = weapon.GetMods()
+ mods.append( "pas_tone_rockets" )
+ weapon.SetMods( mods )
+ break
+
+ case ePassives.PAS_TONE_SONAR:
+ entity weapon = titan.GetOffhandWeapon( OFFHAND_ANTIRODEO )
+ array<string> mods = weapon.GetMods()
+ mods.append( "pas_tone_sonar" )
+ weapon.SetMods( mods )
+ break
+
+ case ePassives.PAS_RONIN_WEAPON:
+ entity weapon = titan.GetMainWeapons()[0]
+ array<string> mods = weapon.GetMods()
+ mods.append( "pas_ronin_weapon" )
+ weapon.SetMods( mods )
+ break
+
+ case ePassives.PAS_RONIN_ARCWAVE:
+ entity weapon = titan.GetOffhandWeapon( OFFHAND_RIGHT )
+ array<string> mods = weapon.GetMods()
+ mods.append( "pas_ronin_arcwave" )
+ weapon.SetMods( mods )
+ break
+
+ case ePassives.PAS_RONIN_PHASE:
+ entity weapon = titan.GetOffhandWeapon( OFFHAND_ANTIRODEO )
+ array<string> mods = weapon.GetMods()
+ mods.append( "pas_ronin_phase" )
+ weapon.SetMods( mods )
+ break
+
+ case ePassives.PAS_VANGUARD_REARM:
+ entity weapon = titan.GetOffhandWeapon( OFFHAND_ANTIRODEO )
+ array<string> mods = weapon.GetMods()
+ mods.append( "pas_vanguard_rearm" )
+ weapon.SetMods( mods )
+ break
+ }
+ }
+
+ #if MP
+ if ( GetCurrentPlaylistVarInt( "aegis_upgrades", 0 ) == 1 ) //Necessary to occur after normal weapon mods are assigned from passives.
+ ApplyFDUpgradeWeaponPassives( titan, loadout )
+ #endif
+}
+
+function GivePassive( entity player, int passive )
+{
+ if ( IsSoul( player ) )
+ {
+ entity soul = player
+ Assert( passive in level.titanPassives, "This is not a titan passive" )
+ soul.passives[ passive ] = true
+
+ entity titan = soul.GetTitan()
+ if ( IsValid( titan ) && titan.IsPlayer() )
+ GiveTitanPassiveLifeLong( titan, passive ) //This actually loops back around to GivePassive
+ return
+ }
+
+ // printt( "give passive " + GetPassiveName( passive ), passive )
+ player.GivePassive( passive )
+
+ // enter/exit functions for specific passives
+ switch ( passive )
+ {
+ case ePassives.PAS_MINIMAP_AI:
+ case ePassives.PAS_MINIMAP_ALL:
+ case ePassives.PAS_MINIMAP_PLAYERS:
+ UpdateMinimapStatus( player )
+ break
+
+ case ePassives.PAS_CONSCRIPT:
+ thread PlayerConscription( player )
+ break
+
+ case ePassives.PAS_WIFI_SPECTRE:
+ thread PlayerSpectreWifi( player )
+ break
+
+ case ePassives.PAS_FAST_SWAP:
+ player.GiveExtraWeaponMod( "pas_fast_swap" )
+ break
+
+ case ePassives.PAS_POWER_CELL:
+ player.GiveExtraWeaponMod( "pas_power_cell" )
+ break
+
+ case ePassives.PAS_WALLHANG:
+ player.GiveExtraWeaponMod( "pas_wallhang" )
+ break
+
+ case ePassives.PAS_FAST_HEALTH_REGEN:
+ player.GiveExtraWeaponMod( "pas_fast_health_regen" )
+ break
+
+ case ePassives.PAS_DEFENSIVE_CORE:
+ player.GiveExtraWeaponMod( "pas_defensive_core" )
+ break
+
+ case ePassives.PAS_RUN_AND_GUN:
+ player.GiveExtraWeaponMod( "pas_run_and_gun" )
+ break
+
+ case ePassives.PAS_ORDNANCE_PACK:
+ player.GiveExtraWeaponMod( "pas_ordnance_pack" )
+ break
+
+ case ePassives.PAS_FAST_RELOAD:
+ player.GiveExtraWeaponMod( "pas_fast_reload" )
+ break
+
+ case ePassives.PAS_ASSAULT_REACTOR:
+ player.GiveExtraWeaponMod( "mod_ordnance_core" )
+ break
+
+ case ePassives.PAS_MARATHON_CORE:
+ player.GiveExtraWeaponMod( "mod_marathon_core" )
+ break
+
+ case ePassives.PAS_CLOAKED_WALLHANG:
+ thread CloakedWallHangs( player )
+ break
+
+ case ePassives.PAS_CLOAKED_WALLRUN:
+ thread CloakedWallruns( player )
+ break
+
+ case ePassives.PAS_SMOKE_SIGHT:
+ Remote_CallFunction_Replay( player, "ServerCallback_BeginSmokeSight" )
+ break
+ }
+}
+
+string function GetPassiveName( int passive )
+{
+ Assert( passive in level.passiveEnumFromPassive, "Passive bitfield: " + passive + " does not exist" )
+
+ return expect string( level.passiveEnumFromPassive[ passive ] )
+}
+
+function TakePassive( entity player, int passive )
+{
+ if ( IsSoul( player ) )
+ {
+ entity soul = player
+ Assert( passive in level.titanPassives, "This is not a titan passive" )
+ soul.passives[ passive ] = false
+ entity titan = soul.GetTitan()
+ if ( IsValid( titan ) && titan.IsPlayer() )
+ TakePassive( titan, passive )
+ return
+ }
+
+ //printt( "take passive " + PassiveEnumFromBitfield( passive ) )
+ player.RemovePassive( passive )
+
+ // enter/exit functions for specific passives
+ switch ( passive )
+ {
+ case ePassives.PAS_MINIMAP_AI:
+ case ePassives.PAS_MINIMAP_ALL:
+ case ePassives.PAS_MINIMAP_PLAYERS:
+ UpdateMinimapStatus( player )
+ break
+
+ case ePassives.PAS_FAST_SWAP:
+ player.TakeExtraWeaponMod( "pas_fast_swap" )
+ break
+
+ case ePassives.PAS_POWER_CELL:
+ player.TakeExtraWeaponMod( "pas_power_cell" )
+ break
+
+ case ePassives.PAS_WALLHANG:
+ player.TakeExtraWeaponMod( "pas_wallhang" )
+ break
+
+ case ePassives.PAS_FAST_HEALTH_REGEN:
+ player.TakeExtraWeaponMod( "pas_fast_health_regen" )
+ break
+
+ case ePassives.PAS_DEFENSIVE_CORE:
+ player.TakeExtraWeaponMod( "pas_defensive_core" )
+ break
+
+ case ePassives.PAS_RUN_AND_GUN:
+ player.TakeExtraWeaponMod( "pas_run_and_gun" )
+ break
+
+ case ePassives.PAS_ORDNANCE_PACK:
+ player.TakeExtraWeaponMod( "pas_ordnance_pack" )
+ break
+
+ case ePassives.PAS_FAST_RELOAD:
+ player.TakeExtraWeaponMod( "pas_fast_reload" )
+ break
+
+ case ePassives.PAS_ASSAULT_REACTOR:
+ player.TakeExtraWeaponMod( "mod_ordnance_core" )
+ break
+
+ case ePassives.PAS_MARATHON_CORE:
+ player.TakeExtraWeaponMod( "mod_marathon_core" )
+ break
+
+ case ePassives.PAS_CLOAKED_WALLHANG:
+ player.Signal( "EndCloakedWallHangs" )
+ break
+
+ case ePassives.PAS_CLOAKED_WALLRUN:
+ player.Signal( "EndCloakedWallruns" )
+ break
+
+ case ePassives.PAS_SMOKE_SIGHT:
+ Remote_CallFunction_Replay( player, "ServerCallback_EndSmokeSight" )
+ break
+ }
+}
+
+void function PassiveDeathCallback( entity player, var damageInfo )
+{
+ foreach ( int passive in player.s.removePassiveOnDeath )
+ {
+ TakePassive( player, passive )
+ }
+
+ player.s.removePassiveOnDeath = {}
+}
+
+function GivePassiveLifeLong( entity player, int passive )
+{
+ //Note: Badness happens if a burn card with passive tries to give a server flag!
+ Assert( !( passive in level.titanPassives ), "This is a titan passive" )
+
+ // give the passive for one life
+ player.s.removePassiveOnDeath[ passive ] <- passive
+ GivePassive( player, passive )
+}
+
+function GiveTitanPassiveLifeLong( entity player, int passive )
+{
+ Assert( passive in level.titanPassives, "This is a titan passive" )
+
+ // give the passive for one life
+ player.s.removePassiveOnDeath[ passive ] <- passive
+ GivePassive( player, passive )
+}
+
+function TakeAllPassives( entity player )
+{
+ foreach( passiveName, passive in _PassiveFromEnum )
+ {
+ if ( player.HasPassive( passive ) )
+ TakePassive( player, passive )
+ }
+
+ player.ClearExtraWeaponMods()
+ player.s.removePassiveOnDeath = {}
+}
+
+
+function GivePlayerPassivesFromSoul( entity player, entity soul )
+{
+ Assert( player == soul.GetTitan() )
+
+ foreach( passiveName, passive in _PassiveFromEnum ) //Since this is just a bitmask, we could just add all the soul's passives directly instead of trying to break it down to its components first like we do here. However, while it is less efficent, it's also easier to debug.
+ {
+ if ( soul.passives[ passive ] )
+ GiveTitanPassiveLifeLong( player, passive )
+ }
+}
+
+table function GetRevealParms( entity player )
+{
+ table Table = {}
+
+ if ( player.HasPassive( ePassives.PAS_MINIMAP_ALL ) )
+ {
+ Table.ai <- true
+ Table.players <- true
+ Table.titans <- true
+ }
+ else
+ {
+ Table.titans <- false
+
+ if ( player.HasPassive( ePassives.PAS_MINIMAP_PLAYERS ) )
+ Table.players <- true
+ else
+ Table.players <- false
+
+ if ( player.HasPassive( ePassives.PAS_MINIMAP_AI ) )
+ Table.ai <- true
+ else
+ Table.ai <- false
+ }
+
+ return Table
+}
+
+function UpdateMinimapStatusToOtherPlayers( entity player )
+{
+ int team = player.GetTeam()
+ array players = GetPlayerArray()
+ foreach ( otherPlayer in players )
+ {
+ // teammates are on minimap by default
+ if ( team == otherPlayer.GetTeam() )
+ continue
+
+ table reveal = GetRevealParms( expect entity( otherPlayer ) )
+ if ( reveal.players )
+ {
+ player.Minimap_AlwaysShow( 0, otherPlayer )
+ }
+ }
+}
+
+function UpdateTitanMinimapStatusToOtherPlayers( entity titan )
+{
+ int team = titan.GetTeam()
+ array players = GetPlayerArray()
+ foreach ( otherPlayer in players )
+ {
+ // teammates are on minimap by default
+ if ( team == otherPlayer.GetTeam() )
+ continue
+
+ table reveal = GetRevealParms( expect entity( otherPlayer ) )
+ if ( reveal.titans )
+ {
+ titan.Minimap_AlwaysShow( 0, otherPlayer )
+ }
+ }
+}
+
+function UpdateAIMinimapStatusToOtherPlayers( entity guy )
+{
+ int team = guy.GetTeam()
+ array players = GetPlayerArray()
+ foreach ( otherPlayer in players )
+ {
+ // teammates are on minimap by default
+ if ( team == otherPlayer.GetTeam() )
+ continue
+
+ table reveal = GetRevealParms( expect entity( otherPlayer ) )
+ if ( reveal.ai )
+ {
+ guy.Minimap_AlwaysShow( 0, otherPlayer )
+ }
+ }
+}
+
+function UpdateMinimapStatus( entity player )
+{
+ int team = player.GetTeam()
+ table reveal = GetRevealParms( player )
+
+ array players = GetPlayerArray()
+ if ( reveal.players )
+ {
+ foreach ( target in players )
+ {
+ if ( team != target.GetTeam() )
+ target.Minimap_AlwaysShow( 0, player )
+ }
+ }
+ else
+ {
+ foreach ( target in players )
+ {
+ if ( team != target.GetTeam() )
+ target.Minimap_DisplayDefault( 0, player )
+ }
+ }
+
+ array<entity> titans = GetNPCArrayByClass( "npc_titan" )
+ if ( reveal.titans )
+ {
+ foreach ( target in titans )
+ {
+ if ( team != target.GetTeam() )
+ target.Minimap_AlwaysShow( 0, player )
+ }
+ }
+ else
+ {
+ foreach ( target in titans )
+ {
+ if ( team != target.GetTeam() )
+ target.Minimap_DisplayDefault( 0, player )
+ }
+ }
+
+ array<entity> ai = GetNPCArrayByClass( "npc_soldier" )
+ ai.extend( GetNPCArrayByClass( "npc_spectre" ) )
+
+ if ( reveal.ai )
+ {
+ foreach ( target in ai )
+ {
+ if ( team != target.GetTeam() )
+ target.Minimap_AlwaysShow( 0, player )
+ }
+ }
+ else
+ {
+ foreach ( target in ai )
+ {
+ if ( team != target.GetTeam() )
+ target.Minimap_DisplayDefault( 0, player )
+ }
+ }
+
+// foreach ( target in ai )
+// {
+// if ( target.GetBossPlayer() == player )
+// target.Minimap_AlwaysShow( 0, player )
+// }
+}
+
+function ScanMinimapUntilDeath( entity player )
+{
+ player.EndSignal( "OnDeath" )
+ for ( ;; )
+ {
+ thread ScanMinimap( player, true )
+ wait 10.0
+ }
+}
+
+function ScanMinimap( entity player, bool playSound, float displayTime = 3.0 )
+{
+ // already has the passive?
+ if ( PlayerHasPassive( player, ePassives.PAS_MINIMAP_ALL ) )
+ return
+
+ player.EndSignal( "OnDeath" )
+
+ int handle = player.GetEncodedEHandle()
+ Remote_CallFunction_Replay( player, "ServerCallback_MinimapPulse", handle )
+
+ OnThreadEnd(
+ function () : ( player )
+ {
+ if ( IsValid( player ) )
+ TakePassive( player, ePassives.PAS_MINIMAP_ALL )
+ }
+ )
+
+ GivePassive( player, ePassives.PAS_MINIMAP_ALL )
+ if ( playSound )
+ EmitSoundOnEntityOnlyToPlayer( player, player, "Burn_Card_Map_Hack_Radar_Pulse_V1_1P" )
+ wait displayTime
+}
+
+void function MinimapNPCSpawned( entity guy )
+{
+ // show up on minimap for player that has the passive
+
+ int team = guy.GetTeam()
+ if ( IsIMCOrMilitiaTeam( team ) == false )
+ return
+ array<entity> players = GetPlayerArrayOfEnemies( team )
+ foreach ( player in players )
+ {
+ if ( !PlayerRevealsNPCs( player ) )
+ continue
+
+ guy.Minimap_AlwaysShow( 0, player )
+ }
+}
+
+function PlayerRevealsPlayers( entity player )
+{
+ return player.HasPassive( ePassives.PAS_MINIMAP_PLAYERS ) || player.HasPassive( ePassives.PAS_MINIMAP_ALL )
+}
+
+function MinimapPlayerConnected( entity guy )
+{
+ int team = guy.GetTeam()
+ array<entity> players = GetPlayerArrayOfEnemies( team )
+ foreach ( player in players )
+ {
+ if ( !PlayerRevealsPlayers( player ) )
+ continue
+
+ guy.Minimap_AlwaysShow( 0, player )
+ }
+}
+
+function PlayerSpectreWifi( entity player )
+{
+ player.EndSignal( "OnDeath" )
+
+ for ( ;; )
+ {
+ if ( !PlayerHasPassive( player, ePassives.PAS_WIFI_SPECTRE ) )
+ return
+
+ LeechSurroundingSpectres( player.GetOrigin(), player )
+
+ wait level.wifiLeachInterval
+ }
+}
+
+const CLEAR_CONSCRIPTED_GRUNTS_ON_DEATH = false
+
+function PlayerConscription( entity player )
+{
+ player.EndSignal( "OnDestroy" )
+
+ if ( CLEAR_CONSCRIPTED_GRUNTS_ON_DEATH )
+ {
+ if ( "conscriptedGrunts" in player.s )
+ return
+
+ table conscriptedGrunts
+ if ( "conscriptedGrunts" in player.s )
+ {
+ conscriptedGrunts = expect table( player.s.conscriptedGrunts )
+ }
+ else
+ {
+ conscriptedGrunts = {}
+ player.s.conscriptedGrunts <- conscriptedGrunts
+ }
+
+ OnThreadEnd(
+ function () : ( player, conscriptedGrunts )
+ {
+ ClearConscriptedGrunts( player, conscriptedGrunts )
+ }
+ )
+ }
+
+ for ( ;; )
+ {
+ if ( !PlayerHasPassive( player, ePassives.PAS_CONSCRIPT ) )
+ return
+
+ if ( IsAlive( player ) )
+ {
+ ConscriptNearbyGrunts( player )
+ }
+ wait 1.5
+ }
+}
+
+function ConscriptNearbyGrunts( entity player )
+{
+ int team = player.GetTeam()
+ array<entity> grunts = GetNPCArrayEx( "npc_soldier", team, TEAM_ANY, player.GetOrigin(), 220 )
+
+ foreach ( grunt in grunts )
+ {
+ if ( !IsValid( grunt ) )
+ continue
+
+ if ( IsAlive( grunt.GetBossPlayer() ) )
+ continue
+
+ ConscriptGruntSquad( grunt, player, team )
+ WaitFrame()
+ }
+}
+
+function ConscriptGrunt( entity grunt, entity player, int team )
+{
+ EmitSoundOnEntity( grunt, "BurnCard_Conscription_TurnSoldier" )
+ grunt.Signal( "StopHardpointBehavior" )
+ SetTeam( grunt, team )
+ grunt.SetBossPlayer( player )
+ grunt.SetTitle( "#NPC_CONSCRIPT" )
+ grunt.ai.preventOwnerDamage = true
+
+ #if HAS_STATS
+ UpdatePlayerStat( player, "misc_stats", "gruntsConscripted", 1 )
+ #endif
+
+ if ( CLEAR_CONSCRIPTED_GRUNTS_ON_DEATH )
+ {
+ player.s.conscriptedGrunts[ grunt ] <- grunt
+ // printt( player + " Conscripted " + grunt + " to squadname " + grunt.kv.squadname )
+ }
+}
+
+function MakePlayerSquad( entity player )
+{
+ string squad = "player" + player.entindex() + "gruntSquad"
+ int index = 0
+ string squadName = squad + index
+ for ( ;; )
+ {
+ if ( GetNPCSquadSize( squadName ) == 0 )
+ return squadName
+
+ index++
+ squadName = squad + index
+ }
+}
+
+function ConscriptGruntSquad( entity grunt, entity player, int team )
+{
+ array<entity> grunts
+ string gruntSquad = expect string( grunt.Get( "squadname" ) )
+
+ if ( gruntSquad == "" )
+ grunts.append( grunt )
+ else
+ grunts = GetNPCArrayBySquad( gruntSquad )
+
+ foreach ( guy in grunts )
+ {
+ if ( IsAlive( guy.GetBossPlayer() ) )
+ continue
+ if ( guy.GetTeam() != team )
+ continue
+
+ ConscriptGrunt( guy, player, team )
+ }
+}
+
+function ClearConscriptedGrunts( entity player, table conscriptedGrunts )
+{
+ foreach ( grunt in conscriptedGrunts )
+ {
+ expect entity( grunt )
+ if ( !IsAlive( grunt ) )
+ continue
+
+ entity owner = grunt.GetBossPlayer()
+ if ( IsValid( owner ) && owner != player )
+ continue
+
+ grunt.ClearBossPlayer()
+ asset model = grunt.GetModelName()
+ int team
+ if ( model.find( "imc" ) != null )
+ {
+ team = TEAM_IMC
+ }
+ else
+ {
+ team = TEAM_MILITIA
+ }
+
+ var title = grunt.GetSettingTitle()
+ if ( title != null && title != "" )
+ {
+ grunt.SetTitle( title )
+ FixupTitle( grunt )
+ }
+
+ grunt.Signal( "StopHardpointBehavior" )
+ SetTeam( grunt, team )
+ }
+
+ delete player.s.conscriptedGrunts
+}
+
+bool function IsConscript( entity guy )
+{
+ return IsAlive( guy.GetBossPlayer() )
+}
+
+bool function SoulHasPassive( entity soul, int passive )
+{
+ return expect bool( soul.passives[ passive ] )
+}
+
+function PrintAllPassives( entity player )
+{
+ foreach( passiveName, passive in _PassiveFromEnum )
+ {
+ if ( player.HasPassive( passive ) )
+ printt( "Player " + player + " has passive: " + passiveName )
+ }
+}
+
+function CloakedWallHangs( entity player )
+{
+ player.Signal( "EndCloakedWallHangs" )
+ player.EndSignal( "EndCloakedWallHangs" )
+ player.EndSignal( "OnDeath" )
+ player.EndSignal( "OnDestroy" )
+
+ float cloakStartTime
+ float rechargeStartTime
+
+ if ( !( "wallHangCloakDuration" in player.s ) )
+ player.s.wallHangCloakDuration <- WALLHANG_CLOAK_DURATION
+
+ OnThreadEnd(
+ function() : ( player )
+ {
+ if ( !IsValid( player ) )
+ return
+
+ if ( IsCloaked( player ) )
+ DisableCloak( player, 0 )
+ }
+ )
+
+ while ( true )
+ {
+ while ( !player.IsWallHanging() )
+ {
+ rechargeStartTime = Time()
+ WaitFrame()
+ player.s.wallHangCloakDuration += Time() - rechargeStartTime
+
+ if ( player.s.wallHangCloakDuration > WALLHANG_CLOAK_DURATION )
+ player.s.wallHangCloakDuration = WALLHANG_CLOAK_DURATION
+ }
+
+ if ( !IsCloaked( player ) && player.s.wallHangCloakDuration )
+ EnableCloak( player, expect float( player.s.wallHangCloakDuration ), WALLHANG_CLOAK_TRANSITION_TIME )
+
+ while ( player.s.wallHangCloakDuration && player.IsWallHanging() )
+ {
+ cloakStartTime = Time()
+ WaitFrame()
+ player.s.wallHangCloakDuration -= Time() - cloakStartTime
+
+ if ( player.s.wallHangCloakDuration < 0 )
+ player.s.wallHangCloakDuration = 0
+ }
+
+ if ( IsCloaked( player ) )
+ DisableCloak( player, WALLHANG_CLOAK_TRANSITION_TIME )
+
+ if ( player.IsWallHanging() )
+ WaitFrame()
+ }
+}
+
+function CloakedWallruns( entity player )
+{
+ player.Signal( "EndCloakedWallruns" )
+ player.EndSignal( "EndCloakedWallruns" )
+ player.EndSignal( "OnDeath" )
+
+ float cloakStartTime
+ float rechargeStartTime
+
+ if ( !( "wallRunCloakDuration" in player.s ) )
+ player.s.wallRunCloakDuration <- WALLRUN_CLOAK_DURATION
+
+ OnThreadEnd(
+ function() : ( player )
+ {
+ if ( !IsValid( player ) )
+ return
+
+ if ( IsCloaked( player ) )
+ DisableCloak( player, 0 )
+ }
+ )
+
+ while ( true )
+ {
+ while ( !player.IsWallRunning() )
+ {
+ rechargeStartTime = Time()
+ WaitFrame()
+ player.s.wallRunCloakDuration += Time() - rechargeStartTime
+
+ if ( player.s.wallRunCloakDuration > WALLRUN_CLOAK_DURATION )
+ player.s.wallRunCloakDuration = WALLRUN_CLOAK_DURATION
+ }
+
+ if ( !IsCloaked( player ) && player.s.wallRunCloakDuration )
+ EnableCloak( player, expect float( player.s.wallRunCloakDuration ), WALLRUN_CLOAK_TRANSITION_TIME )
+
+ while ( player.s.wallRunCloakDuration && player.IsWallRunning() )
+ {
+ cloakStartTime = Time()
+ WaitFrame()
+ player.s.wallRunCloakDuration -= Time() - cloakStartTime
+
+ if ( player.s.wallRunCloakDuration < 0 )
+ player.s.wallRunCloakDuration = 0
+ }
+
+ if ( IsCloaked( player ) )
+ DisableCloak( player, WALLRUN_CLOAK_TRANSITION_TIME )
+
+ if ( player.IsWallRunning() )
+ WaitFrame()
+ }
+}
+
+//To avoid threads and callbacks, this is using any netFloat > 0.5 to mean full CoreMeter scaling.
+void function UpdateScorchHotStreakCoreMeter( entity attacker, float damage )
+{
+ if ( !attacker.IsPlayer() )
+ return
+
+ float baseValue = attacker.GetPlayerNetFloat( "coreMeterModifier" )
+ float newValue = damage / FD_HOT_STREAK_DAMAGE_MAX * 0.5
+ float combinedValue = baseValue + newValue
+ if ( baseValue + newValue >= 0.5 )
+ combinedValue = 1.0
+
+ attacker.SetPlayerNetFloat( "coreMeterModifier", combinedValue )
+ attacker.SetPlayerNetFloatOverTime( "coreMeterModifier", 0.0, FD_HOT_STREAK_DECAY_TIME )
+} \ No newline at end of file