aboutsummaryrefslogtreecommitdiff
path: root/Northstar.Custom/mod/scripts/vscripts/burnmeter/sh_burnmeter.gnut
diff options
context:
space:
mode:
Diffstat (limited to 'Northstar.Custom/mod/scripts/vscripts/burnmeter/sh_burnmeter.gnut')
-rw-r--r--Northstar.Custom/mod/scripts/vscripts/burnmeter/sh_burnmeter.gnut488
1 files changed, 488 insertions, 0 deletions
diff --git a/Northstar.Custom/mod/scripts/vscripts/burnmeter/sh_burnmeter.gnut b/Northstar.Custom/mod/scripts/vscripts/burnmeter/sh_burnmeter.gnut
new file mode 100644
index 000000000..3f914745d
--- /dev/null
+++ b/Northstar.Custom/mod/scripts/vscripts/burnmeter/sh_burnmeter.gnut
@@ -0,0 +1,488 @@
+global function ShBurnMeter_Init
+global function BurnReward_GetById
+global function BurnReward_GetByRef
+global function BurnReward_GetRandom
+global function GetSelectedBurnCardRef
+global function GetBoostSkin
+#if SERVER || CLIENT
+global function BurnMeterEnabled
+global function CanUseWeaponAsBurnCard
+global function TryUsingBurnCardWeapon
+global function TryUsingBurnCardWeaponInCriticalSection
+global function BurnMeterPlayer_CanUseEquipped
+global function OnWeaponAttemptOffhandSwitch_burncardweapon
+global function BurnMeterPlayer_CanUseReward
+global function BurnMeterPlayer_GetRewardOrGoal
+global function BurnReward_GetTopInventoryItemBurnCard
+global function OnWeaponPrimaryAttack_nuke_eject
+global function BurnMeter_HarvesterShieldCanUse
+#endif
+
+global function GetAllBoostTurretTypes
+
+global const BURN_METER_SMALL_POINT_VALUE = 1
+global const BURN_METER_MID_POINT_VALUE = 2
+global const BURN_METER_LARGE_POINT_VALUE = 5
+global const BURN_METER_EXTRA_LARGE_POINT_VALUE = 10
+
+global const BURN_METER_RADAR_JAMMER_PULSE_DURATION = 6.0
+global const BURN_METER_RADAR_JAMMER_EASE_OFF_TIME = 1.0
+
+global enum eBurnMeterRewardAvailableFor
+{
+ PILOT_ONLY,
+ TITAN_ONLY,
+ PILOT_AND_TITAN,
+ SPECIAL_PLAYERS_ONLY,
+}
+
+global struct BurnReward
+{
+ int id = -1
+ string ref = ""
+ string localizedName = ""
+ string description = ""
+ asset image = $""
+ float cost
+ int userType = -1
+ int skinIndex = 0
+ string weaponName = ""
+ string extraWeaponMod = ""
+ string activationText = ""
+
+ void functionref( entity ) ornull rewardAvailableCallback = null
+}
+
+global struct BurnStruct
+{
+ table< string, BurnReward > burnRewards
+ array< BurnReward > allCards //Kinda inefficient to store the same burn cards 3 times (once in burnRewards, once in foil/normal, once in allcards. Prefer speed over memory? )
+ array< BurnReward > allowedCards
+
+}
+
+global BurnStruct burn
+
+global table< string, bool functionref( entity ) > burnMeterCanUseFuncTable
+
+struct
+{
+
+ bool shouldCycleOnRelease = false
+
+} file
+
+array<string> turretBurnCards = [
+ "burnmeter_ap_turret_weapon",
+ "burnmeter_at_turret_weapon",
+ "burnmeter_ap_turret_weapon_infinite",
+ "burnmeter_at_turret_weapon_infinite",
+]
+
+void function ShBurnMeter_Init()
+{
+
+ #if SERVER || CLIENT
+ //burnMeterCanUseFuncTable[ "burnmeter_random_foil" ] <- BurnMeter_RandomFoilCanUse
+ burnMeterCanUseFuncTable[ "burnmeter_emergency_titan" ] <- BurnMeter_EmergencyTitanCanUse
+ burnMeterCanUseFuncTable[ "burnmeter_nuke_titan" ] <- BurnMeter_NukeTitanCanUse
+ // burnMeterCanUseFuncTable[ "burnmeter_harvester_shield" ] <- BurnMeter_HarvesterShieldCanUse
+ #endif
+
+
+
+ var dataTable = GetDataTable( $"datatable/burn_meter_rewards.rpak" )
+
+ for ( int row = 0; row < GetDatatableRowCount( dataTable ); row++ )
+ {
+ BurnReward burnReward
+ burnReward.id = row
+ burnReward.ref = GetDataTableString( dataTable, row, GetDataTableColumnByName( dataTable, BURN_REF_COLUMN_NAME ) )
+ burnReward.localizedName = GetDataTableString( dataTable, row, GetDataTableColumnByName( dataTable, BURN_NAME_COLUMN_NAME ) )
+ burnReward.description = GetDataTableString( dataTable, row, GetDataTableColumnByName( dataTable, BURN_DESCRIPTION_COLUMN_NAME ) )
+ burnReward.image = GetDataTableAsset( dataTable, row, GetDataTableColumnByName( dataTable, BURN_IMAGE_COLUMN_NAME ) )
+ burnReward.cost = GetDataTableFloat( dataTable, row, GetDataTableColumnByName( dataTable, BURN_COST_COLUMN_NAME ) )
+ string userType = GetDataTableString( dataTable, row, GetDataTableColumnByName( dataTable, BURN_AVAILABLE_COLUMN_NAME ) )
+ burnReward.userType = eBurnMeterRewardAvailableFor[userType]
+ burnReward.weaponName = GetDataTableString( dataTable, row, GetDataTableColumnByName( dataTable, BURN_WEAPON_COLUMN_NAME ) )
+ burnReward.extraWeaponMod = GetDataTableString( dataTable, row, GetDataTableColumnByName( dataTable, BURN_EXTRA_WEAPON_MOD_NAME ) )
+ burnReward.activationText = GetDataTableString( dataTable, row, GetDataTableColumnByName( dataTable, "activationText" ) )
+ burnReward.skinIndex = GetDataTableInt( dataTable, row, GetDataTableColumnByName( dataTable, "skinIndex" ) )
+
+ if ( IsDisabledRef( burnReward.ref ) )
+ continue
+
+#if SERVER || CLIENT
+ if ( burnReward.weaponName != "" )
+ PrecacheWeapon( burnReward.weaponName )
+ #endif
+
+ burn.burnRewards[burnReward.ref] <- burnReward
+
+ bool selectable = GetDataTableBool( dataTable, row, GetDataTableColumnByName( dataTable, "selectable" ) )
+ burn.allCards.append( burnReward )
+ if ( selectable )
+ burn.allowedCards.append( burnReward )
+ }
+
+ #if CLIENT
+ //Registering here instead of in CreateWeaponData() in _items.nut to remove dependence on HUD script with items. If more weapons other than smart pistol run into this problem, just add a column in burn_meter_rewards to specify we need to do this. ( ticks are fine because they have a damagedef associated with them )
+ RegisterWeaponDamageSourceName( "mp_weapon_smart_pistol", expect string( GetWeaponInfoFileKeyField_GlobalNotNull( "mp_weapon_smart_pistol", "shortprintname" ) ) )
+
+ RegisterConCommandTriggeredCallback( "-offhand4", CycleOnRelease )
+ #endif
+}
+
+#if SERVER || CLIENT
+bool function BurnMeterEnabled()
+{
+ return Riff_BoostAvailability() != eBoostAvailability.Disabled
+}
+#endif
+
+BurnReward function BurnReward_GetById( int id )
+{
+ return burn.allCards[ id ]
+}
+
+
+BurnReward function BurnReward_GetByRef( string ref )
+{
+ Assert( ref in burn.burnRewards )
+
+ // more hacks for arena
+ if ( !( ref in burn.burnRewards ) && GetCurrentPlaylistVarString( "boost_store_mode", "off" ) == "arena" )
+ return GetArenaLoadoutItemAsBurnReward( ref )
+
+ return burn.burnRewards[ref]
+}
+
+int function GetBoostSkin( string ref )
+{
+ BurnReward reward = BurnReward_GetByRef( ref )
+ //printt( "ref: " + ref + ", Boost skin: " + reward.skinIndex )
+ return reward.skinIndex
+}
+
+
+BurnReward function BurnReward_GetRandom()
+{
+ return burn.allowedCards.getrandom()
+}
+
+string function GetSelectedBurnCardRef( entity player )
+{
+ int burnCardID = expect int ( player.GetPersistentVar( "burnmeterSlot" ) )
+ BurnReward burnCard = burn.allCards[ burnCardID ]
+ string ref = burnCard.ref
+
+ #if SERVER
+ if ( GetItemDisplayData( ref ).hidden )
+ ClientCommand( player, "disconnect" )
+ #endif
+
+ #if SERVER || CLIENT
+
+ if ( Riff_TitanAvailability() == eTitanAvailability.Never )
+ {
+ //JFS: Batteries and Titan turrets are useless in PvP, turn them into amped weapons instead. Not an elegant solution at all. Fix next game. (Make boosts editable mid-match? )
+ if ( ref == "burnmeter_emergency_battery" || ref == "burnmeter_at_turret_weapon" )
+ ref = "burnmeter_amped_weapons"
+ }
+
+ if ( GetCurrentPlaylistVarInt( "featured_mode_all_ticks", 0 ) >= 1 )
+ {
+ if ( ref == "burnmeter_ticks" || ref == "burnmeter_random_foil" )
+ ref = "burnmeter_amped_weapons"
+ }
+ #endif
+
+ return ref
+}
+
+
+#if SERVER || CLIENT
+bool function CanUseWeaponAsBurnCard( entity weapon, entity ownerPlayer )
+{
+ Assert( weapon.HasMod( "burn_card_weapon_mod" ) )
+
+ if ( !BurnMeterPlayer_CanUseEquipped( ownerPlayer ) )
+ {
+ weapon.EmitWeaponSound( "CoOp_SentryGun_DeploymentDeniedBeep" )
+ return false
+ }
+
+ return true
+}
+
+bool function TryUsingBurnCardWeapon( entity weapon, entity ownerPlayer )
+{
+ Assert( weapon.HasMod( "burn_card_weapon_mod" ) )
+
+ if ( !CanUseWeaponAsBurnCard( weapon, ownerPlayer ) )
+ return false
+
+ #if SERVER
+ UseBurnCardWeapon( weapon, ownerPlayer )
+ #endif
+
+ return true
+}
+
+bool function TryUsingBurnCardWeaponInCriticalSection( entity weapon, entity ownerPlayer )
+{
+ Assert( weapon.HasMod( "burn_card_weapon_mod" ) )
+
+ if ( !CanUseWeaponAsBurnCard( weapon, ownerPlayer ) )
+ return false
+
+ #if SERVER
+ UseBurnCardWeaponInCriticalSection( weapon, ownerPlayer )
+ #endif
+
+ return true
+}
+
+
+
+bool function BurnMeterPlayer_CanUseReward( entity player, BurnReward burnReward )
+{
+ if ( !BurnMeterPlayer_CanUseGlobal( player ) )
+ return false
+
+ switch( burnReward.userType )
+ {
+ case eBurnMeterRewardAvailableFor.PILOT_ONLY:
+ return !player.IsTitan()
+
+ case eBurnMeterRewardAvailableFor.TITAN_ONLY:
+ return player.IsTitan()
+
+ case eBurnMeterRewardAvailableFor.PILOT_AND_TITAN:
+ return true
+
+ case eBurnMeterRewardAvailableFor.SPECIAL_PLAYERS_ONLY:
+ return BurnMeterPlayer_CanUseSpecial( player, burnReward ) //TODO: Note that for the case of reaperfall we also send the message to the client if they can't summon reaper in the validation function. Not ideal...
+ }
+
+ unreachable
+
+}
+
+
+bool function BurnMeterPlayer_CanUseEquipped( entity player )
+{
+ BurnReward burnReward = BurnReward_GetTopInventoryItemBurnCard( player )
+ return BurnMeterPlayer_CanUseReward( player, burnReward )
+}
+
+
+EarnObject function BurnMeterPlayer_GetRewardOrGoal( entity player )
+{
+ if ( PlayerEarnMeter_IsRewardEnabled( player ) ) // TODO: more robust
+ return PlayerEarnMeter_GetReward( player )
+ else
+ return PlayerEarnMeter_GetGoal( player )
+
+ unreachable
+}
+
+
+bool function BurnMeterPlayer_CanUseGlobal( entity player )
+{
+ if ( player.IsBot() )
+ return false
+
+ if ( !IsAlive( player ) )
+ return false
+
+ if ( player.IsPhaseShifted() )
+ return false
+
+ if ( player.ContextAction_IsInVehicle() ) //no rewards when in dropship
+ return false
+
+ if ( !IsBurnMeterRewardAvailableForGameState() )
+ return false
+
+ return true
+}
+
+
+bool function IsBurnMeterRewardAvailableForGameState() //Based off IsReplacementTitanAvailable
+{
+ int currentGameState = GetGameState()
+
+ switch ( currentGameState ) //need to add a new entry in here for every new game state we make
+ {
+ case eGameState.WaitingForCustomStart:
+ case eGameState.WaitingForPlayers:
+ case eGameState.PickLoadout:
+ case eGameState.Prematch:
+ case eGameState.SwitchingSides:
+ case eGameState.Postmatch:
+ return false
+
+ case eGameState.Playing:
+ case eGameState.SuddenDeath:
+ return true
+
+ case eGameState.WinnerDetermined:
+ case eGameState.Epilogue:
+ {
+ if ( IsRoundBased() )
+ {
+ // TODO: make this work on the client
+ #if SERVER
+ if ( !IsRoundBasedGameOver() )
+ return false
+
+ if ( !ShouldRunEvac() )
+ return false
+ #endif
+ }
+
+ return true
+ }
+
+ default:
+ Assert( false, "Unknown Game State: " + currentGameState )
+ return false
+ }
+
+ unreachable
+}
+
+
+bool function OnWeaponAttemptOffhandSwitch_burncardweapon( entity weapon )
+{
+ entity ownerPlayer = weapon.GetWeaponOwner()
+ Assert( ownerPlayer.IsPlayer() )
+
+ if ( ownerPlayer.IsUsingOffhandWeapon() )
+ return false
+
+ if ( weapon.HasMod( "burn_card_weapon_mod" ) )
+ {
+ bool canUse = BurnMeterPlayer_CanUseEquipped( ownerPlayer )
+
+ return canUse
+ }
+ else
+ return true
+
+ unreachable
+}
+
+BurnReward function BurnReward_GetTopInventoryItemBurnCard( entity player )
+{
+ int burnRewardID = player.GetPlayerNetInt( TOP_INVENTORY_ITEM_BURN_CARD_ID )
+ return BurnReward_GetById( burnRewardID )
+}
+
+bool function BurnMeterPlayer_CanUseSpecial( entity player, BurnReward burnReward )
+{
+ Assert( burnReward.ref in burnMeterCanUseFuncTable )
+ return burnMeterCanUseFuncTable[ burnReward.ref ]( player )
+}
+
+bool function BurnMeter_HarvesterShieldCanUse( entity player )
+{
+// entity harvester = GetGlobalNetEnt( "FD_activeHarvester" )
+ bool canUse = GetGlobalNetTime( "FD_harvesterInvulTime" ) < Time()
+ // harvester.GetShieldHealth() < harvester.GetShieldHealthMax()
+
+ if ( !canUse )
+ {
+ #if CLIENT
+ AddPlayerHint( 3.0, 0.5, $"", "#HINT_HARVESTER_BOOST_CANT_USE" )
+ #endif
+ }
+
+ return canUse
+}
+
+bool function BurnMeter_NukeTitanCanUse( entity player )
+{
+ bool canUse = BurnMeter_EmergencyTitanCanUse( player )
+
+ if ( !canUse )
+ {
+ #if CLIENT
+ AddPlayerHint( 5.0, 0.5, $"", "#HINT_NUKE_TITAN_CANT_USE" )
+ #endif
+ }
+
+ return canUse
+}
+
+bool function BurnMeter_EmergencyTitanCanUse( entity player )
+{
+ if ( IsAlive( player.GetPetTitan() ) )
+ return false
+
+ #if SERVER
+ if ( !IsReplacementTitanAvailableForGameState() )
+ return false
+
+ if ( player.isSpawning )
+ return false
+
+ return true
+ #endif
+
+ #if CLIENT
+ return true
+ #endif
+}
+
+bool function BurnMeter_SummonReaperCanUse( entity player )
+{
+ array< entity > allReapers = GetNPCArrayByClass( "npc_super_spectre" )
+
+ int playerTeam = player.GetTeam()
+
+ foreach( reaper in allReapers )
+ {
+ if ( reaper.GetTeam() == playerTeam )
+ {
+ #if SERVER
+ MessageToPlayer( player, eEventNotifications.BurnMeter_CantSummonReaper )
+ #endif
+
+ return false
+ }
+ }
+ return true
+}
+
+var function OnWeaponPrimaryAttack_nuke_eject( entity weapon, WeaponPrimaryAttackParams attackParams )
+{
+ #if CLIENT
+ entity weaponOwner = weapon.GetWeaponOwner()
+ if ( weaponOwner.IsPlayer() && IsValid( weaponOwner.GetCockpit() ) )
+ {
+ weaponOwner.ClientCommand( "TitanEject " + 3 )
+ PlayerEjects( weaponOwner, weaponOwner.GetCockpit() ) //Note that this can be run multiple times in a frame, e.g. get damaged by 4 pellets of a shotgun that brings the Titan into a doomed state with auto eject. Not ideal
+ }
+ #endif
+ return 0
+}
+
+#endif
+
+#if CLIENT
+void function CycleOnRelease( entity player )
+{
+ if ( file.shouldCycleOnRelease )
+ {
+ CycleInventory( player )
+ file.shouldCycleOnRelease = false
+ }
+}
+#endif
+
+array<string> function GetAllBoostTurretTypes()
+{
+ return turretBurnCards
+} \ No newline at end of file