From 67611e7fad615b33db8c4751b3e61ff44a630071 Mon Sep 17 00:00:00 2001 From: Connie Price Date: Tue, 28 Dec 2021 18:26:54 +0000 Subject: Fixed the game erroring when disembarking from a titan and the player has a weapon missing "menu_category" equipped (like titan weapons). --- .../mod/scripts/vscripts/mp/_titan_transfer.nut | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'Northstar.CustomServers') diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/_titan_transfer.nut b/Northstar.CustomServers/mod/scripts/vscripts/mp/_titan_transfer.nut index 7b126cd0..c84e6aba 100644 --- a/Northstar.CustomServers/mod/scripts/vscripts/mp/_titan_transfer.nut +++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/_titan_transfer.nut @@ -178,7 +178,12 @@ void function GiveWeaponsFromStoredArray( entity player, array sto UpdateProScreen( player, weapon ) } - string weaponCategory = GetWeaponInfoFileKeyField_GlobalString( weapon.GetWeaponClassName(), "menu_category" ) + string weaponCategory = "" + if ( IsWeaponKeyFieldDefined(weapon.GetWeaponClassName(), "menu_category") ) + { + weaponCategory = GetWeaponInfoFileKeyField_GlobalString( weapon.GetWeaponClassName(), "menu_category" ) + } + if ( weaponCategory == "at" || weaponCategory == "special" ) // refill AT/grenadier ammo stockpile { int defaultTotal = weapon.GetWeaponSettingInt( eWeaponVar.ammo_default_total ) -- cgit v1.2.3 From d579444d87117c9262142a3a6ef553a51d3a7735 Mon Sep 17 00:00:00 2001 From: x3Karma Date: Wed, 29 Dec 2021 12:35:57 +0800 Subject: Stop Pilots vs Pilots from scoring during the epilogue --- .../mod/scripts/vscripts/gamemodes/_gamemode_ps.nut | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Northstar.CustomServers') diff --git a/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_ps.nut b/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_ps.nut index 4e62e8c5..7e3e5ea2 100644 --- a/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_ps.nut +++ b/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_ps.nut @@ -10,6 +10,6 @@ void function GamemodePs_Init() void function GiveScoreForPlayerKill( entity victim, entity attacker, var damageInfo ) { - if ( victim != attacker && victim.IsPlayer() && attacker.IsPlayer() ) + if ( victim != attacker && victim.IsPlayer() && attacker.IsPlayer() && GetGameState() != eGameState.Epilogue ) AddTeamScore( attacker.GetTeam(), 1 ) -} \ No newline at end of file +} -- cgit v1.2.3 From 425336bbb830a2699e3b9b4eb11d71690bb26aac Mon Sep 17 00:00:00 2001 From: x3Karma Date: Wed, 29 Dec 2021 12:37:06 +0800 Subject: Stop Skirmish from scoring during the epilogue --- .../mod/scripts/vscripts/gamemodes/_gamemode_tdm.nut | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Northstar.CustomServers') diff --git a/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_tdm.nut b/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_tdm.nut index 5dd8a403..fd5cbb14 100644 --- a/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_tdm.nut +++ b/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_tdm.nut @@ -9,7 +9,7 @@ void function GamemodeTdm_Init() void function GiveScoreForPlayerKill( entity victim, entity attacker, var damageInfo ) { - if ( victim != attacker && victim.IsPlayer() && attacker.IsPlayer() ) + if ( victim != attacker && victim.IsPlayer() && attacker.IsPlayer() && GetGameState() != eGameState.Epilogue ) AddTeamScore( attacker.GetTeam(), 1 ) } @@ -17,4 +17,4 @@ void function RateSpawnpoints_Directional( int checkclass, array spawnpo { // temp RateSpawnpoints_Generic( checkclass, spawnpoints, team, player ) -} \ No newline at end of file +} -- cgit v1.2.3 From 4210b5684c11538db59df1cd4a77e99423df4f4d Mon Sep 17 00:00:00 2001 From: x3Karma Date: Wed, 29 Dec 2021 12:38:15 +0800 Subject: Stop Titan Brawl from scoring during the epilogue if tits turned on lol --- .../mod/scripts/vscripts/gamemodes/_gamemode_ttdm.nut | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Northstar.CustomServers') diff --git a/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_ttdm.nut b/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_ttdm.nut index 9e5d95ba..82b673d2 100644 --- a/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_ttdm.nut +++ b/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_ttdm.nut @@ -69,8 +69,8 @@ void function PlayerWatchesTTDMIntroIntermissionCam( entity player ) void function AddTeamScoreForPlayerKilled( entity victim, entity attacker, var damageInfo ) { - if ( victim == attacker || !victim.IsPlayer() || !attacker.IsPlayer() ) + if ( victim == attacker || !victim.IsPlayer() || !attacker.IsPlayer() || GetGameState() != eGameState.Playing ) return AddTeamScore( GetOtherTeam( victim.GetTeam() ), 1 ) -} \ No newline at end of file +} -- cgit v1.2.3 From 7ed259a9a76dc2e90cc1934f688c949cc7e9edcc Mon Sep 17 00:00:00 2001 From: x3Karma Date: Thu, 30 Dec 2021 02:06:19 +0800 Subject: reset flags properly --- .../mod/scripts/vscripts/gamemodes/_gamemode_speedball.nut | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'Northstar.CustomServers') diff --git a/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_speedball.nut b/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_speedball.nut index cef0af6b..bba70358 100644 --- a/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_speedball.nut +++ b/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_speedball.nut @@ -25,6 +25,7 @@ void function GamemodeSpeedball_Init() AddCallback_OnTouchHealthKit( "item_flag", OnFlagCollected ) AddCallback_OnPlayerKilled( OnPlayerKilled ) SetTimeoutWinnerDecisionFunc( TimeoutCheckFlagHolder ) + AddCallback_OnRoundEndCleanup ( ResetFlag ) ClassicMP_SetCustomIntro( ClassicMP_DefaultNoIntro_Setup, ClassicMP_DefaultNoIntro_GetLength() ) ClassicMP_ForceDisableEpilogue( true ) @@ -127,4 +128,4 @@ int function TimeoutCheckFlagHolder() return TEAM_UNASSIGNED return file.flagCarrier.GetTeam() -} \ No newline at end of file +} -- cgit v1.2.3 From a109a2d376f61fb92bf9bedffe67713316bcdfae Mon Sep 17 00:00:00 2001 From: Soup-64 <43444191+Soup-64@users.noreply.github.com> Date: Wed, 29 Dec 2021 19:39:06 -0500 Subject: Fix missing respawn grace during EvacEpilogue and Postmatch gamestate Adds in a helper function on top of setting respawn behaviour for adding a grace period before disabling the respawn to fix #30. This also disables respawns during the Postmatch game state, and grace length is controlled by the GAME_EPILOGUE_PLAYER_RESPAWN_LEEWAY constant. --- .../mod/scripts/vscripts/evac/_evac.gnut | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'Northstar.CustomServers') diff --git a/Northstar.CustomServers/mod/scripts/vscripts/evac/_evac.gnut b/Northstar.CustomServers/mod/scripts/vscripts/evac/_evac.gnut index a4f23b85..b861ed9f 100644 --- a/Northstar.CustomServers/mod/scripts/vscripts/evac/_evac.gnut +++ b/Northstar.CustomServers/mod/scripts/vscripts/evac/_evac.gnut @@ -103,11 +103,20 @@ void function EvacEpilogue() if ( canRunEvac ) { - SetRespawnsEnabled( false ) + thread SetRespawnAndWait( false ) thread Evac( GetOtherTeam( winner ), EVAC_INITIAL_WAIT, EVAC_ARRIVAL_TIME, EVAC_WAIT_TIME, EvacEpiloguePlayerCanBoard, EvacEpilogueShouldLeaveEarly, EvacEpilogueCompleted ) } else - thread EvacEpilogueCompleted( null ) // this is hacky but like, this also shouldn't really be hit in normal gameplay + { + thread SetRespawnAndWait( false ) //prevent respawns during the fade to black, should only be an issue if the match is a draw + thread EvacEpilogueCompleted( null ) //this is hacky but like, this also shouldn't really be hit in normal gameplay + } +} + +void function SetRespawnAndWait(bool mode) +{ + wait GAME_EPILOGUE_PLAYER_RESPAWN_LEEWAY + SetRespawnsEnabled( mode ) } bool function EvacEpiloguePlayerCanBoard( entity dropship, entity player ) @@ -386,4 +395,4 @@ void function EvacDropshipKilled( entity dropship, var damageInfo ) player.Die( DamageInfo_GetAttacker( damageInfo ), DamageInfo_GetWeapon( damageInfo ), { damageSourceId = eDamageSourceId.evac_dropship_explosion, scriptType = DF_GIB } ) } } -} \ No newline at end of file +} -- cgit v1.2.3 From 38b3a6efddbe19af38b4d75406f4794d3f8b2c7f Mon Sep 17 00:00:00 2001 From: BobTheBob <32057864+BobTheBob9@users.noreply.github.com> Date: Thu, 30 Dec 2021 02:12:52 +0000 Subject: speedball and dropship crash fixes --- Northstar.Client/mod/scripts/vscripts/ui/panel_mainmenu.nut | 4 ++-- .../mod/scripts/vscripts/gamemodes/sh_gamemode_fw_custom.nut | 2 -- .../mod/scripts/vscripts/gamemodes/_gamemode_speedball.nut | 4 +++- .../mod/scripts/vscripts/mp/_classic_mp_dropship_intro.gnut | 3 ++- 4 files changed, 7 insertions(+), 6 deletions(-) (limited to 'Northstar.CustomServers') diff --git a/Northstar.Client/mod/scripts/vscripts/ui/panel_mainmenu.nut b/Northstar.Client/mod/scripts/vscripts/ui/panel_mainmenu.nut index 25097c6f..ecb34d47 100644 --- a/Northstar.Client/mod/scripts/vscripts/ui/panel_mainmenu.nut +++ b/Northstar.Client/mod/scripts/vscripts/ui/panel_mainmenu.nut @@ -502,9 +502,9 @@ void function TryUnlockNorthstarButton() // unlock "Launch Northstar" button until you're authed with masterserver, are allowing insecure auth, or 7.5 seconds have passed float time = Time() - while ( Time() < time + 7.5 || GetConVarInt( "ns_has_agreed_to_send_token" ) != NS_AGREED_TO_SEND_TOKEN ) + while ( GetConVarInt( "ns_has_agreed_to_send_token" ) != NS_AGREED_TO_SEND_TOKEN ) { - if ( NSIsMasterServerAuthenticated() || GetConVarBool( "ns_auth_allow_insecure" ) ) + if ( ( NSIsMasterServerAuthenticated() && IsStryderAllowingMP() ) || GetConVarBool( "ns_auth_allow_insecure" ) ) break WaitFrame() diff --git a/Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_gamemode_fw_custom.nut b/Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_gamemode_fw_custom.nut index 8c6e3f63..ca238d5d 100644 --- a/Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_gamemode_fw_custom.nut +++ b/Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_gamemode_fw_custom.nut @@ -13,8 +13,6 @@ void function SHCreateGamemodeFW_Init() void function CreateGamemodeFW() { - //entity e = CreateEntity("npc_turret_mega"); SetAISettingsWrapper( e, "npc_turret_mega_fortwar" ); e.SetOrigin(GetPlayerArray()[0].GetOrigin()); SetTeam(e,3); DispatchSpawn(e) - // we have to manually add the client/shared scripts to scripts.rson atm so we need to prevent compile errors when they aren't included // best way to do this is to just ignore this whole block for now and wait until we don't have to add them manually diff --git a/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_speedball.nut b/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_speedball.nut index cef0af6b..22c660d8 100644 --- a/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_speedball.nut +++ b/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_speedball.nut @@ -103,7 +103,9 @@ void function DropFlag() file.flag.ClearParent() file.flag.SetAngles( < 0, 0, 0 > ) SetGlobalNetEnt( "flagCarrier", file.flag ) - EmitSoundOnEntityOnlyToPlayer( file.flagCarrier, file.flagCarrier, "UI_CTF_1P_FlagDrop" ) + + if ( IsValid( file.flagCarrier ) ) + EmitSoundOnEntityOnlyToPlayer( file.flagCarrier, file.flagCarrier, "UI_CTF_1P_FlagDrop" ) foreach ( entity player in GetPlayerArray() ) MessageToPlayer( player, eEventNotifications.SPEEDBALL_FlagDropped, file.flagCarrier ) diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/_classic_mp_dropship_intro.gnut b/Northstar.CustomServers/mod/scripts/vscripts/mp/_classic_mp_dropship_intro.gnut index 78dec3d1..d3b4cd7e 100644 --- a/Northstar.CustomServers/mod/scripts/vscripts/mp/_classic_mp_dropship_intro.gnut +++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/_classic_mp_dropship_intro.gnut @@ -125,6 +125,8 @@ void function EndIntroWhenFinished() void function SpawnPlayerIntoDropship( entity player ) { + player.EndSignal( "OnDestroy" ) + if ( IsAlive( player ) ) player.Die() // kill them so we don't have any issues respawning them later @@ -148,7 +150,6 @@ void function SpawnPlayerIntoDropship( entity player ) WaitFrame() player.EndSignal( "OnDeath" ) - player.EndSignal( "OnDestroy" ) // find the player's dropship and seat array teamDropships -- cgit v1.2.3 From d90fccb4cef95c2809cabab8454c22121c91efef Mon Sep 17 00:00:00 2001 From: Barichello Date: Wed, 29 Dec 2021 23:37:07 -0300 Subject: Fix #17 --- .../mod/scripts/vscripts/mp/_classic_mp_dropship_intro.gnut | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'Northstar.CustomServers') diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/_classic_mp_dropship_intro.gnut b/Northstar.CustomServers/mod/scripts/vscripts/mp/_classic_mp_dropship_intro.gnut index d3b4cd7e..8e624c14 100644 --- a/Northstar.CustomServers/mod/scripts/vscripts/mp/_classic_mp_dropship_intro.gnut +++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/_classic_mp_dropship_intro.gnut @@ -180,6 +180,7 @@ void function SpawnPlayerIntoDropship( entity player ) // respawn player and holster their weapons so they aren't out player.RespawnPlayer( null ) + HolsterAndDisableWeapons(player) player.DisableWeaponViewModel() // hide hud and fade screen out from black @@ -187,7 +188,7 @@ void function SpawnPlayerIntoDropship( entity player ) ScreenFadeFromBlack( player, 0.5, 0.5 ) // faction leaders are done clientside, spawn them here Remote_CallFunction_NonReplay( player, "ServerCallback_SpawnFactionCommanderInDropship", playerDropship.dropship.GetEncodedEHandle(), file.introStartTime ) - + // do firstperson sequence FirstPersonSequenceStruct idleSequence idleSequence.firstPersonAnim = DROPSHIP_IDLE_ANIMS_POV[ playerDropshipIndex ] @@ -229,6 +230,7 @@ void function PlayerJumpsFromDropship( entity player ) // show weapon viewmodel and hud and let them move again player.MovementEnable() player.EnableWeaponViewModel() + DeployAndEnableWeapons(player) RemoveCinematicFlag( player, CE_FLAG_CLASSIC_MP_SPAWNING ) } }) -- cgit v1.2.3 From a0923c46ade1d30a9fb0949f9468255b9dd91c50 Mon Sep 17 00:00:00 2001 From: x3Karma Date: Thu, 30 Dec 2021 14:22:31 +0800 Subject: fixes map hack issues --- .../mod/scripts/vscripts/burnmeter/_burnmeter.gnut | 874 +++++++++++---------- 1 file changed, 440 insertions(+), 434 deletions(-) (limited to 'Northstar.CustomServers') diff --git a/Northstar.CustomServers/mod/scripts/vscripts/burnmeter/_burnmeter.gnut b/Northstar.CustomServers/mod/scripts/vscripts/burnmeter/_burnmeter.gnut index 3151a0f2..3eb6bda6 100644 --- a/Northstar.CustomServers/mod/scripts/vscripts/burnmeter/_burnmeter.gnut +++ b/Northstar.CustomServers/mod/scripts/vscripts/burnmeter/_burnmeter.gnut @@ -1,435 +1,441 @@ -untyped - -global function BurnMeter_Init -global function ForceSetGlobalBurncardOverride -global function GetSelectedBurncardRefFromWeaponOrPlayer -global function RunBurnCardUseFunc -global function UseBurnCardWeapon -global function UseBurnCardWeaponInCriticalSection -global function BurnMeter_GiveRewardDirect -global function GetBurnCardWeaponSkin -global function InitBurnMeterPersistentData - -const float PHASE_REWIND_LENGTH = 2.0 -// taken from wraith portal in apex, assuming it's the same as tf2's -const float PHASE_REWIND_PATH_SNAPSHOT_INTERVAL = 0.1 -const int PHASE_REWIND_MAX_SNAPSHOTS = int( PHASE_REWIND_LENGTH / PHASE_REWIND_PATH_SNAPSHOT_INTERVAL ) - -const float AMPED_WEAPONS_LENGTH = 30.0 - -const int MAPHACK_PULSE_COUNT = 4 -const float MAPHACK_PULSE_DELAY = 2.0 - -struct { - string forcedGlobalBurncardOverride = "" -} file - -void function BurnMeter_Init() -{ - // turret precaches - // do we have to cache these on client? release builds sure don't - PrecacheModel( Dev_GetAISettingAssetByKeyField_Global( "npc_turret_sentry_burn_card_ap", "DefaultModelName" ) ) - PrecacheModel( Dev_GetAISettingAssetByKeyField_Global( "npc_turret_sentry_burn_card_at", "DefaultModelName" ) ) - - // setup burncard use funcs - BurnReward_GetByRef( "burnmeter_amped_weapons" ).rewardAvailableCallback = PlayerUsesAmpedWeaponsBurncard - BurnReward_GetByRef( "burnmeter_smart_pistol" ).rewardAvailableCallback = PlayerUsesSmartPistolBurncard - BurnReward_GetByRef( "burnmeter_emergency_battery" ).rewardAvailableCallback = PlayerUsesBatteryBurncard - BurnReward_GetByRef( "burnmeter_radar_jammer" ).rewardAvailableCallback = PlayerUsesRadarJammerBurncard - BurnReward_GetByRef( "burnmeter_maphack" ).rewardAvailableCallback = PlayerUsesMaphackBurncard - BurnReward_GetByRef( "burnmeter_phase_rewind" ).rewardAvailableCallback = PlayerUsesPhaseRewindBurncard - - // these ones aren't so important, they're either for fd ( unsupported rn ) or unused - //BurnReward_GetByRef( "burnmeter_harvester_shield" ).rewardAvailableCallback = - BurnReward_GetByRef( "burnmeter_rodeo_grenade" ).rewardAvailableCallback = PlayerUsesRodeoGrenadeBurncard - BurnReward_GetByRef( "burnmeter_nuke_titan" ).rewardAvailableCallback = PlayerUsesNukeTitanBurncard // unused in vanilla, fun though - - // setup player callbacks - AddCallback_GameStateEnter( eGameState.Playing, InitBurncardsForIntroPlayers ) - AddCallback_OnClientConnected( InitBurncardsForLateJoiner ) - - AddCallback_OnPlayerRespawned( StartPhaseRewindLifetime ) - AddCallback_OnTitanBecomesPilot( RemoveAmpedWeaponsForTitanPilot ) - - // necessary signals - RegisterSignal( "StopAmpedWeapons" ) -} - -void function ForceSetGlobalBurncardOverride( string ref ) -{ - file.forcedGlobalBurncardOverride = ref -} - -string function GetSelectedBurncardRefFromWeaponOrPlayer( entity weapon, entity player ) -{ - // determine the burncard we're using - // in actual gameplay, this will always be the player's selected burncard - // however, if we want to manually give burncards and such, we want to make sure they'll still work - // so some extra work goes into this - - string ref = GetSelectedBurnCardRef( player ) - - if ( file.forcedGlobalBurncardOverride.len() > 0 ) - ref = file.forcedGlobalBurncardOverride - - if ( IsValid( weapon ) ) - { - // determine via weapon mods, this assumes weapon mod names are the same as burn refs, which works in practice but is a bit weird - // this does crash with the burnmeter_doublexp mod, but who cares, it doesn't get hit normally - if ( weapon.GetWeaponClassName() == "mp_ability_burncardweapon" ) - { - foreach ( string mod in weapon.GetMods() ) - if ( mod.find( "burnmeter_" ) == 0 ) - return mod - } - // determine via weapon name in the case of stuff like holopilot etc - else - { - // unfortunately, we have to hardcode this, we don't have a way of getting refs directly from weapons other than the burncard weapon - // this should be modular at some point, wish we could just iterate over burncards and find ones with the current weapon, but this isn't possible - switch ( weapon.GetWeaponClassName() ) - { - case "mp_ability_holopilot_nova": - return "burnmeter_holopilot_nova" - - case "mp_weapon_arc_trap": - return "burnmeter_arc_trap" - - case "mp_weapon_frag_drone": - return "burnmeter_ticks" - - case "mp_weapon_hard_cover": - return "burnmeter_hard_cover" - - case "mp_ability_turretweapon": - // turret has 2 burncards, antititan and antipilot - if( weapon.HasMod( "burnmeter_at_turret_weapon" ) || weapon.HasMod( "burnmeter_at_turret_weapon_inf" ) ) - return "burnmeter_at_turret_weapon" - else - return "burnmeter_ap_turret_weapon" - - // note: cloak and stim both have burn_card_weapon_mod mods, but they aren't used and don't call burncard code at all, likely for tf1 infinite stim/cloak burncards? - - default: - print( "tried to use unknown burncard weapon " + weapon.GetWeaponClassName() ) - return "burnmeter_amped_weapons" - } - } - } - - return ref -} - -void function InitPlayerBurncards( entity player ) -{ - string ref = GetSelectedBurncardRefFromWeaponOrPlayer( null, player ) - BurnReward reward = BurnReward_GetByRef( ref ) - player.SetPlayerNetInt( TOP_INVENTORY_ITEM_BURN_CARD_ID, reward.id ) - - if ( IsAlive( player ) ) - thread PhaseRewindLifetime( player ) -} - -void function InitBurncardsForIntroPlayers() -{ - // gotta do this, since sh_burnmeter uses this netint - foreach ( entity player in GetPlayerArray() ) - InitPlayerBurncards( player ) -} - -void function InitBurncardsForLateJoiner( entity player ) -{ - // gotta do this, since sh_burnmeter uses this netint - if ( GetGameState() > eGameState.Prematch ) - InitPlayerBurncards( player ) -} - -void function StartPhaseRewindLifetime( entity player ) -{ - thread PhaseRewindLifetime( player ) -} - -void function PhaseRewindLifetime( entity player ) -{ - player.EndSignal( "OnDestroy" ) - player.EndSignal( "OnDeath" ) - - OnThreadEnd( function() : ( player ) - { - player.p.burnCardPhaseRewindStruct.phaseRetreatSavedPositions.clear() - }) - - while ( true ) - { - PhaseRewindData rewindData - rewindData.origin = player.GetOrigin() - rewindData.angles = player.GetAngles() - rewindData.velocity = player.GetVelocity() - rewindData.wasInContextAction = player.ContextAction_IsActive() - rewindData.wasCrouched = player.IsCrouched() - - if ( player.p.burnCardPhaseRewindStruct.phaseRetreatSavedPositions.len() >= PHASE_REWIND_MAX_SNAPSHOTS ) - { - // shift all snapshots left - for ( int i = 0; i < PHASE_REWIND_MAX_SNAPSHOTS - 1; i++ ) - player.p.burnCardPhaseRewindStruct.phaseRetreatSavedPositions[ i ] = player.p.burnCardPhaseRewindStruct.phaseRetreatSavedPositions[ i + 1 ] - - player.p.burnCardPhaseRewindStruct.phaseRetreatSavedPositions[ PHASE_REWIND_MAX_SNAPSHOTS - 1 ] = rewindData - } - else - player.p.burnCardPhaseRewindStruct.phaseRetreatSavedPositions.append( rewindData ) - - wait PHASE_REWIND_PATH_SNAPSHOT_INTERVAL - } -} - -void function RunBurnCardUseFunc( entity player, string itemRef ) -{ - void functionref( entity ) ornull func = BurnReward_GetByRef( itemRef ).rewardAvailableCallback - if ( func != null ) - ( expect void functionref( entity ) ( func ) )( player ) -} - -void function UseBurnCardWeapon( entity weapon, entity player ) -{ - string ref = GetSelectedBurncardRefFromWeaponOrPlayer( weapon, player ) - - Remote_CallFunction_Replay( player, "ServerCallback_RewardUsed", BurnReward_GetByRef( ref ).id ) - RunBurnCardUseFunc( player, ref ) - - // dont remove in RunBurnCardUseFunc because it can be called in non-burn_card_weapon_mod contexts - // TODO: currently not sure how burncards can be stacked ( max clipcount for all burncards is 1, so can't just set that ) - // if this gets figured out, add a conditional check here to prevent removes if they've got burncards left - if ( PlayerEarnMeter_IsRewardAvailable( player ) ) - PlayerEarnMeter_SetRewardUsed( player ) - - player.TakeWeapon( BurnReward_GetByRef( ref ).weaponName ) -} - -void function UseBurnCardWeaponInCriticalSection( entity weapon, entity ownerPlayer ) -{ - // ignoring critical section stuff, assuming it was necessary in tf1 where burncards were part of inventory, but not here - UseBurnCardWeapon( weapon, ownerPlayer ) -} - -void function BurnMeter_GiveRewardDirect( entity player, string itemRef ) -{ - -} - -int function GetBurnCardWeaponSkin( entity weapon ) -{ - return GetBoostSkin( GetSelectedBurncardRefFromWeaponOrPlayer( weapon, weapon.GetOwner() ) ) -} - -// stub -void function InitBurnMeterPersistentData( entity player ) -{} - - -// burncard use funcs - -void function PlayerUsesAmpedWeaponsBurncard( entity player ) -{ - thread PlayerUsesAmpedWeaponsBurncardThreaded( player ) -} - -void function PlayerUsesAmpedWeaponsBurncardThreaded( entity player ) -{ - array weapons = player.GetMainWeapons() - //weapons.extend( player.GetOffhandWeapons() ) // idk? unsure of vanilla behaviour here - foreach ( entity weapon in weapons ) - { - weapon.RemoveMod( "silencer" ) // both this and the burnmod will override firing fx, if a second one overrides this we crash - foreach ( string mod in GetWeaponBurnMods( weapon.GetWeaponClassName() ) ) - { - // catch incompatibilities just in case - try - { - weapon.AddMod( mod ) - } - catch( ex ) - { - weapons.removebyvalue( weapon ) - } - } - - // needed to display amped weapon time left - weapon.SetScriptFlags0( weapon.GetScriptFlags0() | WEAPONFLAG_AMPED ) - weapon.SetScriptTime0( Time() + AMPED_WEAPONS_LENGTH ) - } - - wait AMPED_WEAPONS_LENGTH - - // note: weapons may have been destroyed or picked up by other people by this point, so need to verify this - foreach ( entity weapon in weapons ) - { - if ( !IsValid( weapon ) ) - continue - - foreach ( string mod in GetWeaponBurnMods( weapon.GetWeaponClassName() ) ) - weapon.RemoveMod( mod ) - - weapon.SetScriptFlags0( weapon.GetScriptFlags0() & ~WEAPONFLAG_AMPED ) - } -} - -void function RemoveAmpedWeaponsForTitanPilot( entity player, entity titan ) -{ - foreach ( entity weapon in player.GetMainWeapons() ) - foreach ( string mod in GetWeaponBurnMods( weapon.GetWeaponClassName() ) ) - weapon.RemoveMod( mod ) -} - -void function PlayerUsesSmartPistolBurncard( entity player ) -{ - // take secondary weapon - array sidearms = player.GetMainWeapons() - if ( sidearms.len() > 1 ) - player.TakeWeaponNow( sidearms[ 1 ].GetWeaponClassName() ) // take secondary weapon - - player.GiveWeapon( "mp_weapon_smart_pistol" ) - player.SetActiveWeaponByName( "mp_weapon_smart_pistol" ) - - // do we need to track the player losing smart pistol, then give their old weapon back? idk not implementing for now, check later -} - -void function PlayerUsesBatteryBurncard( entity player ) -{ - Rodeo_GiveBatteryToPlayer( player ) -} - -void function PlayerUsesRadarJammerBurncard( entity player ) -{ - foreach ( entity otherPlayer in GetPlayerArray() ) - { - MessageToPlayer( otherPlayer, eEventNotifications.BurnMeter_RadarJammerUsed, player ) - - if ( otherPlayer.GetTeam() != player.GetTeam() ) - StatusEffect_AddTimed( otherPlayer, eStatusEffect.minimap_jammed, 1.0, RADAR_JAM_TIME, RADAR_JAM_TIME ) - } -} - -void function PlayerUsesMaphackBurncard( entity player ) -{ - thread PlayerUsesMaphackBurncardThreaded( player ) -} - -void function PlayerUsesMaphackBurncardThreaded( entity player ) -{ - player.EndSignal( "OnDestroy" ) - player.EndSignal( "OnDeath" ) - - // todo: potentially look into ScanMinimap in _passives for doing this better? boost is pretty likely based off it pretty heavily - for ( int i = 0; i < MAPHACK_PULSE_COUNT; i++ ) - { - EmitSoundOnEntityOnlyToPlayer( player, player, "Burn_Card_Map_Hack_Radar_Pulse_V1_1P" ) - - foreach ( entity otherPlayer in GetPlayerArray() ) - { - Remote_CallFunction_Replay( otherPlayer, "ServerCallback_SonarPulseFromPosition", player.GetOrigin().x, player.GetOrigin().y, player.GetOrigin().z, SONAR_GRENADE_RADIUS ) - - if ( otherPlayer.GetTeam() != player.GetTeam() ) - { - StatusEffect_AddTimed( player, eStatusEffect.maphack_detected, 1.0, MAPHACK_PULSE_DELAY / 2, 0.0 ) - SonarStart( otherPlayer, player.GetOrigin(), player.GetTeam(), player ) - } - } - - wait MAPHACK_PULSE_DELAY - } -} - -void function PlayerUsesPhaseRewindBurncard( entity player ) -{ - thread PlayerUsesPhaseRewindBurncardThreaded( player ) -} - -void function PlayerUsesPhaseRewindBurncardThreaded( entity player ) -{ - player.EndSignal( "OnDestroy" ) - player.EndSignal( "OnDeath" ) - - entity mover = CreateScriptMover( player.GetOrigin(), player.GetAngles() ) - player.SetParent( mover, "REF" ) - - OnThreadEnd( function() : ( player, mover ) - { - CancelPhaseShift( player ) - player.DeployWeapon() - player.SetPredictionEnabled( true ) - player.ClearParent() - ViewConeFree( player ) - mover.Destroy() - }) - - array positions = clone player.p.burnCardPhaseRewindStruct.phaseRetreatSavedPositions - - ViewConeZero( player ) - player.HolsterWeapon() - player.SetPredictionEnabled( false ) - PhaseShift( player, 0.0, positions.len() * PHASE_REWIND_PATH_SNAPSHOT_INTERVAL * 1.5 ) - - for ( int i = positions.len() - 1; i > -1; i-- ) - { - mover.NonPhysicsMoveTo( positions[ i ].origin, PHASE_REWIND_PATH_SNAPSHOT_INTERVAL, 0, 0 ) - mover.NonPhysicsRotateTo( positions[ i ].angles, PHASE_REWIND_PATH_SNAPSHOT_INTERVAL, 0, 0 ) - wait PHASE_REWIND_PATH_SNAPSHOT_INTERVAL - } - - // this isn't vanilla but it's cool lol, should prolly remove it tho - player.SetVelocity( -positions[ positions.len() - 1 ].velocity ) -} - -void function PlayerUsesNukeTitanBurncard( entity player ) -{ - thread PlayerUsesNukeBurncardThreaded( player ) -} - -void function PlayerUsesNukeBurncardThreaded( entity player ) -{ - // if this is given manually ( i.e. not the equipped burnreward in inventory ), this will run at bad times - // so do this check here, yes, this will cause people to lose their cards and get nothing, but better than free titan regens - if ( !BurnMeterPlayer_CanUseReward( player, BurnReward_GetByRef( "burnmeter_nuke_titan" ) ) ) - return - - float ownedFrac = PlayerEarnMeter_GetOwnedFrac( player ) - - // use player's titan loadout, but with warpfall so faster and no dome - TitanLoadoutDef titanLoadout = GetTitanLoadoutForPlayer( player ) - titanLoadout.passive3 = "pas_warpfall" - - thread CreateTitanForPlayerAndHotdrop( player, GetTitanReplacementPoint( player, false ) ) - - entity titan = player.GetPetTitan() - SetTeam( titan, TEAM_UNASSIGNED ) // make it so you can kill yourself lol - DoomTitan( titan ) - NPC_SetNuclearPayload( titan ) - // this should get run after the vanilla set_usable's event, so titan is never embarkable - // embarking a titan in this state WILL kill the server so uhh, pretty bad - AddAnimEvent( titan, "set_usable", void function( entity titan ) { titan.UnsetUsable() } ) - - titan.WaitSignal( "TitanHotDropComplete" ) - AutoTitan_SelfDestruct( titan ) - - while ( PlayerEarnMeter_GetMode( player ) == eEarnMeterMode.PET ) - WaitFrame() - - // restore original earnmeter values, no way to set earned that's exposed unfortunately - PlayerEarnMeter_SetOwnedFrac( player, ownedFrac ) -} - -void function PlayerUsesRodeoGrenadeBurncard( entity player ) -{ - player.SetPlayerNetInt( "numSuperRodeoGrenades", player.GetPlayerNetInt( "numSuperRodeoGrenades" ) + 1 ) -} - -// unused burncard that's mentioned in a few areas and has a validiation function in sh_burnmeter ( BurnMeter_SummonReaperCanUse ), thought it'd be neat to add it -void function PlayerUsesReaperfallBurncard( entity player ) -{ - Point spawnpoint = GetTitanReplacementPoint( player, false ) - entity reaper = CreateSuperSpectre( player.GetTeam(), spawnpoint.origin, spawnpoint.angles ) - DispatchSpawn( reaper ) - - thread SuperSpectre_WarpFall( reaper ) +untyped + +global function BurnMeter_Init +global function ForceSetGlobalBurncardOverride +global function GetSelectedBurncardRefFromWeaponOrPlayer +global function RunBurnCardUseFunc +global function UseBurnCardWeapon +global function UseBurnCardWeaponInCriticalSection +global function BurnMeter_GiveRewardDirect +global function GetBurnCardWeaponSkin +global function InitBurnMeterPersistentData + +const float PHASE_REWIND_LENGTH = 2.0 +// taken from wraith portal in apex, assuming it's the same as tf2's +const float PHASE_REWIND_PATH_SNAPSHOT_INTERVAL = 0.1 +const int PHASE_REWIND_MAX_SNAPSHOTS = int( PHASE_REWIND_LENGTH / PHASE_REWIND_PATH_SNAPSHOT_INTERVAL ) + +const float AMPED_WEAPONS_LENGTH = 30.0 + +const int MAPHACK_PULSE_COUNT = 4 +const float MAPHACK_PULSE_DELAY = 2.0 + +struct { + string forcedGlobalBurncardOverride = "" +} file + +void function BurnMeter_Init() +{ + // turret precaches + // do we have to cache these on client? release builds sure don't + PrecacheModel( Dev_GetAISettingAssetByKeyField_Global( "npc_turret_sentry_burn_card_ap", "DefaultModelName" ) ) + PrecacheModel( Dev_GetAISettingAssetByKeyField_Global( "npc_turret_sentry_burn_card_at", "DefaultModelName" ) ) + + // setup burncard use funcs + BurnReward_GetByRef( "burnmeter_amped_weapons" ).rewardAvailableCallback = PlayerUsesAmpedWeaponsBurncard + BurnReward_GetByRef( "burnmeter_smart_pistol" ).rewardAvailableCallback = PlayerUsesSmartPistolBurncard + BurnReward_GetByRef( "burnmeter_emergency_battery" ).rewardAvailableCallback = PlayerUsesBatteryBurncard + BurnReward_GetByRef( "burnmeter_radar_jammer" ).rewardAvailableCallback = PlayerUsesRadarJammerBurncard + BurnReward_GetByRef( "burnmeter_maphack" ).rewardAvailableCallback = PlayerUsesMaphackBurncard + BurnReward_GetByRef( "burnmeter_phase_rewind" ).rewardAvailableCallback = PlayerUsesPhaseRewindBurncard + + // these ones aren't so important, they're either for fd ( unsupported rn ) or unused + //BurnReward_GetByRef( "burnmeter_harvester_shield" ).rewardAvailableCallback = + BurnReward_GetByRef( "burnmeter_rodeo_grenade" ).rewardAvailableCallback = PlayerUsesRodeoGrenadeBurncard + BurnReward_GetByRef( "burnmeter_nuke_titan" ).rewardAvailableCallback = PlayerUsesNukeTitanBurncard // unused in vanilla, fun though + + // setup player callbacks + AddCallback_GameStateEnter( eGameState.Playing, InitBurncardsForIntroPlayers ) + AddCallback_OnClientConnected( InitBurncardsForLateJoiner ) + + AddCallback_OnPlayerRespawned( StartPhaseRewindLifetime ) + AddCallback_OnTitanBecomesPilot( RemoveAmpedWeaponsForTitanPilot ) + + // necessary signals + RegisterSignal( "StopAmpedWeapons" ) +} + +void function ForceSetGlobalBurncardOverride( string ref ) +{ + file.forcedGlobalBurncardOverride = ref +} + +string function GetSelectedBurncardRefFromWeaponOrPlayer( entity weapon, entity player ) +{ + // determine the burncard we're using + // in actual gameplay, this will always be the player's selected burncard + // however, if we want to manually give burncards and such, we want to make sure they'll still work + // so some extra work goes into this + + string ref = GetSelectedBurnCardRef( player ) + + if ( file.forcedGlobalBurncardOverride.len() > 0 ) + ref = file.forcedGlobalBurncardOverride + + if ( IsValid( weapon ) ) + { + // determine via weapon mods, this assumes weapon mod names are the same as burn refs, which works in practice but is a bit weird + // this does crash with the burnmeter_doublexp mod, but who cares, it doesn't get hit normally + if ( weapon.GetWeaponClassName() == "mp_ability_burncardweapon" ) + { + foreach ( string mod in weapon.GetMods() ) + if ( mod.find( "burnmeter_" ) == 0 ) + return mod + } + // determine via weapon name in the case of stuff like holopilot etc + else + { + // unfortunately, we have to hardcode this, we don't have a way of getting refs directly from weapons other than the burncard weapon + // this should be modular at some point, wish we could just iterate over burncards and find ones with the current weapon, but this isn't possible + switch ( weapon.GetWeaponClassName() ) + { + case "mp_ability_holopilot_nova": + return "burnmeter_holopilot_nova" + + case "mp_weapon_arc_trap": + return "burnmeter_arc_trap" + + case "mp_weapon_frag_drone": + return "burnmeter_ticks" + + case "mp_weapon_hard_cover": + return "burnmeter_hard_cover" + + case "mp_ability_turretweapon": + // turret has 2 burncards, antititan and antipilot + if( weapon.HasMod( "burnmeter_at_turret_weapon" ) || weapon.HasMod( "burnmeter_at_turret_weapon_inf" ) ) + return "burnmeter_at_turret_weapon" + else + return "burnmeter_ap_turret_weapon" + + // note: cloak and stim both have burn_card_weapon_mod mods, but they aren't used and don't call burncard code at all, likely for tf1 infinite stim/cloak burncards? + + default: + print( "tried to use unknown burncard weapon " + weapon.GetWeaponClassName() ) + return "burnmeter_amped_weapons" + } + } + } + + return ref +} + +void function InitPlayerBurncards( entity player ) +{ + string ref = GetSelectedBurncardRefFromWeaponOrPlayer( null, player ) + BurnReward reward = BurnReward_GetByRef( ref ) + player.SetPlayerNetInt( TOP_INVENTORY_ITEM_BURN_CARD_ID, reward.id ) + + if ( IsAlive( player ) ) + thread PhaseRewindLifetime( player ) +} + +void function InitBurncardsForIntroPlayers() +{ + // gotta do this, since sh_burnmeter uses this netint + foreach ( entity player in GetPlayerArray() ) + InitPlayerBurncards( player ) +} + +void function InitBurncardsForLateJoiner( entity player ) +{ + // gotta do this, since sh_burnmeter uses this netint + if ( GetGameState() > eGameState.Prematch ) + InitPlayerBurncards( player ) +} + +void function StartPhaseRewindLifetime( entity player ) +{ + thread PhaseRewindLifetime( player ) +} + +void function PhaseRewindLifetime( entity player ) +{ + player.EndSignal( "OnDestroy" ) + player.EndSignal( "OnDeath" ) + + OnThreadEnd( function() : ( player ) + { + player.p.burnCardPhaseRewindStruct.phaseRetreatSavedPositions.clear() + }) + + while ( true ) + { + PhaseRewindData rewindData + rewindData.origin = player.GetOrigin() + rewindData.angles = player.GetAngles() + rewindData.velocity = player.GetVelocity() + rewindData.wasInContextAction = player.ContextAction_IsActive() + rewindData.wasCrouched = player.IsCrouched() + + if ( player.p.burnCardPhaseRewindStruct.phaseRetreatSavedPositions.len() >= PHASE_REWIND_MAX_SNAPSHOTS ) + { + // shift all snapshots left + for ( int i = 0; i < PHASE_REWIND_MAX_SNAPSHOTS - 1; i++ ) + player.p.burnCardPhaseRewindStruct.phaseRetreatSavedPositions[ i ] = player.p.burnCardPhaseRewindStruct.phaseRetreatSavedPositions[ i + 1 ] + + player.p.burnCardPhaseRewindStruct.phaseRetreatSavedPositions[ PHASE_REWIND_MAX_SNAPSHOTS - 1 ] = rewindData + } + else + player.p.burnCardPhaseRewindStruct.phaseRetreatSavedPositions.append( rewindData ) + + wait PHASE_REWIND_PATH_SNAPSHOT_INTERVAL + } +} + +void function RunBurnCardUseFunc( entity player, string itemRef ) +{ + void functionref( entity ) ornull func = BurnReward_GetByRef( itemRef ).rewardAvailableCallback + if ( func != null ) + ( expect void functionref( entity ) ( func ) )( player ) +} + +void function UseBurnCardWeapon( entity weapon, entity player ) +{ + string ref = GetSelectedBurncardRefFromWeaponOrPlayer( weapon, player ) + + Remote_CallFunction_Replay( player, "ServerCallback_RewardUsed", BurnReward_GetByRef( ref ).id ) + RunBurnCardUseFunc( player, ref ) + + // dont remove in RunBurnCardUseFunc because it can be called in non-burn_card_weapon_mod contexts + // TODO: currently not sure how burncards can be stacked ( max clipcount for all burncards is 1, so can't just set that ) + // if this gets figured out, add a conditional check here to prevent removes if they've got burncards left + if ( PlayerEarnMeter_IsRewardAvailable( player ) ) + PlayerEarnMeter_SetRewardUsed( player ) + + player.TakeWeapon( BurnReward_GetByRef( ref ).weaponName ) +} + +void function UseBurnCardWeaponInCriticalSection( entity weapon, entity ownerPlayer ) +{ + // ignoring critical section stuff, assuming it was necessary in tf1 where burncards were part of inventory, but not here + UseBurnCardWeapon( weapon, ownerPlayer ) +} + +void function BurnMeter_GiveRewardDirect( entity player, string itemRef ) +{ + +} + +int function GetBurnCardWeaponSkin( entity weapon ) +{ + return GetBoostSkin( GetSelectedBurncardRefFromWeaponOrPlayer( weapon, weapon.GetOwner() ) ) +} + +// stub +void function InitBurnMeterPersistentData( entity player ) +{} + + +// burncard use funcs + +void function PlayerUsesAmpedWeaponsBurncard( entity player ) +{ + thread PlayerUsesAmpedWeaponsBurncardThreaded( player ) +} + +void function PlayerUsesAmpedWeaponsBurncardThreaded( entity player ) +{ + array weapons = player.GetMainWeapons() + //weapons.extend( player.GetOffhandWeapons() ) // idk? unsure of vanilla behaviour here + foreach ( entity weapon in weapons ) + { + weapon.RemoveMod( "silencer" ) // both this and the burnmod will override firing fx, if a second one overrides this we crash + foreach ( string mod in GetWeaponBurnMods( weapon.GetWeaponClassName() ) ) + { + // catch incompatibilities just in case + try + { + weapon.AddMod( mod ) + } + catch( ex ) + { + weapons.removebyvalue( weapon ) + } + } + + // needed to display amped weapon time left + weapon.SetScriptFlags0( weapon.GetScriptFlags0() | WEAPONFLAG_AMPED ) + weapon.SetScriptTime0( Time() + AMPED_WEAPONS_LENGTH ) + } + + wait AMPED_WEAPONS_LENGTH + + // note: weapons may have been destroyed or picked up by other people by this point, so need to verify this + foreach ( entity weapon in weapons ) + { + if ( !IsValid( weapon ) ) + continue + + foreach ( string mod in GetWeaponBurnMods( weapon.GetWeaponClassName() ) ) + weapon.RemoveMod( mod ) + + weapon.SetScriptFlags0( weapon.GetScriptFlags0() & ~WEAPONFLAG_AMPED ) + } +} + +void function RemoveAmpedWeaponsForTitanPilot( entity player, entity titan ) +{ + foreach ( entity weapon in player.GetMainWeapons() ) + foreach ( string mod in GetWeaponBurnMods( weapon.GetWeaponClassName() ) ) + weapon.RemoveMod( mod ) +} + +void function PlayerUsesSmartPistolBurncard( entity player ) +{ + // take secondary weapon + array sidearms = player.GetMainWeapons() + if ( sidearms.len() > 1 ) + player.TakeWeaponNow( sidearms[ 1 ].GetWeaponClassName() ) // take secondary weapon + + player.GiveWeapon( "mp_weapon_smart_pistol" ) + player.SetActiveWeaponByName( "mp_weapon_smart_pistol" ) + + // do we need to track the player losing smart pistol, then give their old weapon back? idk not implementing for now, check later +} + +void function PlayerUsesBatteryBurncard( entity player ) +{ + Rodeo_GiveBatteryToPlayer( player ) +} + +void function PlayerUsesRadarJammerBurncard( entity player ) +{ + foreach ( entity otherPlayer in GetPlayerArray() ) + { + MessageToPlayer( otherPlayer, eEventNotifications.BurnMeter_RadarJammerUsed, player ) + + if ( otherPlayer.GetTeam() != player.GetTeam() ) + StatusEffect_AddTimed( otherPlayer, eStatusEffect.minimap_jammed, 1.0, RADAR_JAM_TIME, RADAR_JAM_TIME ) + } +} + +void function PlayerUsesMaphackBurncard( entity player ) +{ + thread PlayerUsesMaphackBurncardThreaded( player ) +} + +void function PlayerUsesMaphackBurncardThreaded( entity player ) +{ + player.EndSignal( "OnDestroy" ) + player.EndSignal( "OnDeath" ) + + // todo: potentially look into ScanMinimap in _passives for doing this better? boost is pretty likely based off it pretty heavily + for ( int i = 0; i < MAPHACK_PULSE_COUNT; i++ ) + { + EmitSoundOnEntityOnlyToPlayer( player, player, "Burn_Card_Map_Hack_Radar_Pulse_V1_1P" ) + array aliveplayers = GetPlayerArray() + foreach ( entity otherPlayer in GetPlayerArray() ) + { + Remote_CallFunction_Replay( otherPlayer, "ServerCallback_SonarPulseFromPosition", player.GetOrigin().x, player.GetOrigin().y, player.GetOrigin().z, SONAR_GRENADE_RADIUS ) + + if ( otherPlayer.GetTeam() != player.GetTeam() && aliveplayers.find(otherPlayer) != -1 && aliveplayers.find(player) != -1 ) + { + StatusEffect_AddTimed( otherPlayer, eStatusEffect.maphack_detected, 1.0, MAPHACK_PULSE_DELAY / 2, 0.0 ) + SonarStart( otherPlayer, player.GetOrigin(), player.GetTeam(), player ) + IncrementSonarPerTeam( player.GetTeam() ) + } + } + wait MAPHACK_PULSE_DELAY + foreach ( entity otherPlayer in GetPlayerArray() ) { + if ( otherPlayer.GetTeam() != player.GetTeam() && aliveplayers.find(otherPlayer) != -1 && aliveplayers.find(player) != -1 ) { + SonarEnd (otherPlayer, player.GetTeam() ) + DecrementSonarPerTeam( player.GetTeam() ) + } + } + } +} + +void function PlayerUsesPhaseRewindBurncard( entity player ) +{ + thread PlayerUsesPhaseRewindBurncardThreaded( player ) +} + +void function PlayerUsesPhaseRewindBurncardThreaded( entity player ) +{ + player.EndSignal( "OnDestroy" ) + player.EndSignal( "OnDeath" ) + + entity mover = CreateScriptMover( player.GetOrigin(), player.GetAngles() ) + player.SetParent( mover, "REF" ) + + OnThreadEnd( function() : ( player, mover ) + { + CancelPhaseShift( player ) + player.DeployWeapon() + player.SetPredictionEnabled( true ) + player.ClearParent() + ViewConeFree( player ) + mover.Destroy() + }) + + array positions = clone player.p.burnCardPhaseRewindStruct.phaseRetreatSavedPositions + + ViewConeZero( player ) + player.HolsterWeapon() + player.SetPredictionEnabled( false ) + PhaseShift( player, 0.0, positions.len() * PHASE_REWIND_PATH_SNAPSHOT_INTERVAL * 1.5 ) + + for ( int i = positions.len() - 1; i > -1; i-- ) + { + mover.NonPhysicsMoveTo( positions[ i ].origin, PHASE_REWIND_PATH_SNAPSHOT_INTERVAL, 0, 0 ) + mover.NonPhysicsRotateTo( positions[ i ].angles, PHASE_REWIND_PATH_SNAPSHOT_INTERVAL, 0, 0 ) + wait PHASE_REWIND_PATH_SNAPSHOT_INTERVAL + } + + // this isn't vanilla but it's cool lol, should prolly remove it tho + player.SetVelocity( -positions[ positions.len() - 1 ].velocity ) +} + +void function PlayerUsesNukeTitanBurncard( entity player ) +{ + thread PlayerUsesNukeBurncardThreaded( player ) +} + +void function PlayerUsesNukeBurncardThreaded( entity player ) +{ + // if this is given manually ( i.e. not the equipped burnreward in inventory ), this will run at bad times + // so do this check here, yes, this will cause people to lose their cards and get nothing, but better than free titan regens + if ( !BurnMeterPlayer_CanUseReward( player, BurnReward_GetByRef( "burnmeter_nuke_titan" ) ) ) + return + + float ownedFrac = PlayerEarnMeter_GetOwnedFrac( player ) + + // use player's titan loadout, but with warpfall so faster and no dome + TitanLoadoutDef titanLoadout = GetTitanLoadoutForPlayer( player ) + titanLoadout.passive3 = "pas_warpfall" + + thread CreateTitanForPlayerAndHotdrop( player, GetTitanReplacementPoint( player, false ) ) + + entity titan = player.GetPetTitan() + SetTeam( titan, TEAM_UNASSIGNED ) // make it so you can kill yourself lol + DoomTitan( titan ) + NPC_SetNuclearPayload( titan ) + // this should get run after the vanilla set_usable's event, so titan is never embarkable + // embarking a titan in this state WILL kill the server so uhh, pretty bad + AddAnimEvent( titan, "set_usable", void function( entity titan ) { titan.UnsetUsable() } ) + + titan.WaitSignal( "TitanHotDropComplete" ) + AutoTitan_SelfDestruct( titan ) + + while ( PlayerEarnMeter_GetMode( player ) == eEarnMeterMode.PET ) + WaitFrame() + + // restore original earnmeter values, no way to set earned that's exposed unfortunately + PlayerEarnMeter_SetOwnedFrac( player, ownedFrac ) +} + +void function PlayerUsesRodeoGrenadeBurncard( entity player ) +{ + player.SetPlayerNetInt( "numSuperRodeoGrenades", player.GetPlayerNetInt( "numSuperRodeoGrenades" ) + 1 ) +} + +// unused burncard that's mentioned in a few areas and has a validiation function in sh_burnmeter ( BurnMeter_SummonReaperCanUse ), thought it'd be neat to add it +void function PlayerUsesReaperfallBurncard( entity player ) +{ + Point spawnpoint = GetTitanReplacementPoint( player, false ) + entity reaper = CreateSuperSpectre( player.GetTeam(), spawnpoint.origin, spawnpoint.angles ) + DispatchSpawn( reaper ) + + thread SuperSpectre_WarpFall( reaper ) } \ No newline at end of file -- cgit v1.2.3 From 33b94edca707e71084b2742ad9f57265f39aac88 Mon Sep 17 00:00:00 2001 From: x3Karma Date: Thu, 30 Dec 2021 14:23:27 +0800 Subject: adds time out check for all of these --- .../vscripts/gamemodes/_gamemode_ps.nut.bak | 15 ++ .../scripts/vscripts/gamemodes/_gamemode_tdm.nut | 51 ++++--- .../scripts/vscripts/gamemodes/_gamemode_ttdm.nut | 163 +++++++++++---------- 3 files changed, 133 insertions(+), 96 deletions(-) create mode 100644 Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_ps.nut.bak (limited to 'Northstar.CustomServers') diff --git a/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_ps.nut.bak b/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_ps.nut.bak new file mode 100644 index 00000000..8092a790 --- /dev/null +++ b/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_ps.nut.bak @@ -0,0 +1,15 @@ +global function GamemodePs_Init + +void function GamemodePs_Init() +{ + Riff_ForceTitanAvailability( eTitanAvailability.Never ) + + AddCallback_OnPlayerKilled( GiveScoreForPlayerKill ) + ScoreEvent_SetupEarnMeterValuesForMixedModes() +} + +void function GiveScoreForPlayerKill( entity victim, entity attacker, var damageInfo ) +{ + if ( victim != attacker && victim.IsPlayer() && attacker.IsPlayer() && GetGameState() == eGameState.Epilogue) + AddTeamScore( attacker.GetTeam(), 1 ) +} \ No newline at end of file diff --git a/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_tdm.nut b/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_tdm.nut index fd5cbb14..ba180790 100644 --- a/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_tdm.nut +++ b/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_tdm.nut @@ -1,20 +1,31 @@ -global function GamemodeTdm_Init -global function RateSpawnpoints_Directional - -void function GamemodeTdm_Init() -{ - AddCallback_OnPlayerKilled( GiveScoreForPlayerKill ) - ScoreEvent_SetupEarnMeterValuesForMixedModes() -} - -void function GiveScoreForPlayerKill( entity victim, entity attacker, var damageInfo ) -{ - if ( victim != attacker && victim.IsPlayer() && attacker.IsPlayer() && GetGameState() != eGameState.Epilogue ) - AddTeamScore( attacker.GetTeam(), 1 ) -} - -void function RateSpawnpoints_Directional( int checkclass, array spawnpoints, int team, entity player ) -{ - // temp - RateSpawnpoints_Generic( checkclass, spawnpoints, team, player ) -} +global function GamemodeTdm_Init +global function RateSpawnpoints_Directional + +void function GamemodeTdm_Init() +{ + AddCallback_OnPlayerKilled( GiveScoreForPlayerKill ) + ScoreEvent_SetupEarnMeterValuesForMixedModes() + SetTimeoutWinnerDecisionFunc( CheckScoreForDraw ) +} + +void function GiveScoreForPlayerKill( entity victim, entity attacker, var damageInfo ) +{ + if ( victim != attacker && victim.IsPlayer() && attacker.IsPlayer() || GetGameState() != eGameState.Playing ) + AddTeamScore( attacker.GetTeam(), 1 ) +} + +void function RateSpawnpoints_Directional( int checkclass, array spawnpoints, int team, entity player ) +{ + // temp + RateSpawnpoints_Generic( checkclass, spawnpoints, team, player ) +} + +int function CheckScoreForDraw() +{ + if (GameRules_GetTeamScore(TEAM_IMC) > GameRules_GetTeamScore(TEAM_MILITIA)) + return TEAM_IMC + else if (GameRules_GetTeamScore(TEAM_MILITIA) > GameRules_GetTeamScore(TEAM_IMC)) + return TEAM_MILITIA + + return TEAM_UNASSIGNED +} \ No newline at end of file diff --git a/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_ttdm.nut b/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_ttdm.nut index 82b673d2..c72fcb0d 100644 --- a/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_ttdm.nut +++ b/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_ttdm.nut @@ -1,76 +1,87 @@ -global function GamemodeTTDM_Init - -const float TTDMIntroLength = 15.0 - -void function GamemodeTTDM_Init() -{ - Riff_ForceSetSpawnAsTitan( eSpawnAsTitan.Always ) - Riff_ForceTitanExitEnabled( eTitanExitEnabled.Never ) - TrackTitanDamageInPlayerGameStat( PGS_ASSAULT_SCORE ) - ScoreEvent_SetupEarnMeterValuesForMixedModes() - SetLoadoutGracePeriodEnabled( false ) - - ClassicMP_SetCustomIntro( TTDMIntroSetup, TTDMIntroLength ) - ClassicMP_ForceDisableEpilogue( true ) - - AddCallback_OnPlayerKilled( AddTeamScoreForPlayerKilled ) // dont have to track autotitan kills since you cant leave your titan in this mode - - // probably needs scoreevent earnmeter values -} - -void function TTDMIntroSetup() -{ - // this should show intermission cam for 15 sec in prematch, before spawning players as titans - AddCallback_GameStateEnter( eGameState.Prematch, TTDMIntroStart ) - AddCallback_OnClientConnected( TTDMIntroShowIntermissionCam ) -} - -void function TTDMIntroStart() -{ - thread TTDMIntroStartThreaded() -} - -void function TTDMIntroStartThreaded() -{ - ClassicMP_OnIntroStarted() - - foreach ( entity player in GetPlayerArray() ) - TTDMIntroShowIntermissionCam( player ) - - wait TTDMIntroLength - - ClassicMP_OnIntroFinished() -} - -void function TTDMIntroShowIntermissionCam( entity player ) -{ - if ( GetGameState() != eGameState.Prematch ) - return - - thread PlayerWatchesTTDMIntroIntermissionCam( player ) -} - -void function PlayerWatchesTTDMIntroIntermissionCam( entity player ) -{ - ScreenFadeFromBlack( player ) - - entity intermissionCam = GetEntArrayByClass_Expensive( "info_intermission" )[ 0 ] - - // the angle set here seems sorta inconsistent as to whether it actually works or just stays at 0 for some reason - player.SetObserverModeStaticPosition( intermissionCam.GetOrigin() ) - player.SetObserverModeStaticAngles( intermissionCam.GetAngles() ) - player.StartObserverMode( OBS_MODE_STATIC_LOCKED ) - - wait TTDMIntroLength - - RespawnAsTitan( player, false ) - TryGameModeAnnouncement( player ) -} - -void function AddTeamScoreForPlayerKilled( entity victim, entity attacker, var damageInfo ) -{ - if ( victim == attacker || !victim.IsPlayer() || !attacker.IsPlayer() || GetGameState() != eGameState.Playing ) - return - - AddTeamScore( GetOtherTeam( victim.GetTeam() ), 1 ) -} +global function GamemodeTTDM_Init + +const float TTDMIntroLength = 15.0 + +void function GamemodeTTDM_Init() +{ + Riff_ForceSetSpawnAsTitan( eSpawnAsTitan.Always ) + Riff_ForceTitanExitEnabled( eTitanExitEnabled.Never ) + TrackTitanDamageInPlayerGameStat( PGS_ASSAULT_SCORE ) + ScoreEvent_SetupEarnMeterValuesForMixedModes() + SetLoadoutGracePeriodEnabled( false ) + + ClassicMP_SetCustomIntro( TTDMIntroSetup, TTDMIntroLength ) + ClassicMP_ForceDisableEpilogue( true ) + SetTimeoutWinnerDecisionFunc( CheckScoreForDraw ) + + AddCallback_OnPlayerKilled( AddTeamScoreForPlayerKilled ) // dont have to track autotitan kills since you cant leave your titan in this mode + + // probably needs scoreevent earnmeter values +} + +void function TTDMIntroSetup() +{ + // this should show intermission cam for 15 sec in prematch, before spawning players as titans + AddCallback_GameStateEnter( eGameState.Prematch, TTDMIntroStart ) + AddCallback_OnClientConnected( TTDMIntroShowIntermissionCam ) +} + +void function TTDMIntroStart() +{ + thread TTDMIntroStartThreaded() +} + +void function TTDMIntroStartThreaded() +{ + ClassicMP_OnIntroStarted() + + foreach ( entity player in GetPlayerArray() ) + TTDMIntroShowIntermissionCam( player ) + + wait TTDMIntroLength + + ClassicMP_OnIntroFinished() +} + +void function TTDMIntroShowIntermissionCam( entity player ) +{ + if ( GetGameState() != eGameState.Prematch ) + return + + thread PlayerWatchesTTDMIntroIntermissionCam( player ) +} + +void function PlayerWatchesTTDMIntroIntermissionCam( entity player ) +{ + ScreenFadeFromBlack( player ) + + entity intermissionCam = GetEntArrayByClass_Expensive( "info_intermission" )[ 0 ] + + // the angle set here seems sorta inconsistent as to whether it actually works or just stays at 0 for some reason + player.SetObserverModeStaticPosition( intermissionCam.GetOrigin() ) + player.SetObserverModeStaticAngles( intermissionCam.GetAngles() ) + player.StartObserverMode( OBS_MODE_STATIC_LOCKED ) + + wait TTDMIntroLength + + RespawnAsTitan( player, false ) + TryGameModeAnnouncement( player ) +} + +void function AddTeamScoreForPlayerKilled( entity victim, entity attacker, var damageInfo ) +{ + if ( victim == attacker || !victim.IsPlayer() || !attacker.IsPlayer() || GetGameState() != eGameState.Playing ) + return + + AddTeamScore( GetOtherTeam( victim.GetTeam() ), 1 ) +} + +int function CheckScoreForDraw() +{ + if (GameRules_GetTeamScore(TEAM_IMC) > GameRules_GetTeamScore(TEAM_MILITIA)) + return TEAM_IMC + else if (GameRules_GetTeamScore(TEAM_MILITIA) > GameRules_GetTeamScore(TEAM_IMC)) + return TEAM_MILITIA + + return TEAM_UNASSIGNED +} \ No newline at end of file -- cgit v1.2.3 From f98b68820d29c8bf3aad041dec269ea83f33da5f Mon Sep 17 00:00:00 2001 From: x3Karma Date: Thu, 30 Dec 2021 14:26:36 +0800 Subject: wrong file fuck me this is a backup --- .../mod/scripts/vscripts/gamemodes/_gamemode_ps.nut.bak | 15 --------------- 1 file changed, 15 deletions(-) delete mode 100644 Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_ps.nut.bak (limited to 'Northstar.CustomServers') diff --git a/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_ps.nut.bak b/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_ps.nut.bak deleted file mode 100644 index 8092a790..00000000 --- a/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_ps.nut.bak +++ /dev/null @@ -1,15 +0,0 @@ -global function GamemodePs_Init - -void function GamemodePs_Init() -{ - Riff_ForceTitanAvailability( eTitanAvailability.Never ) - - AddCallback_OnPlayerKilled( GiveScoreForPlayerKill ) - ScoreEvent_SetupEarnMeterValuesForMixedModes() -} - -void function GiveScoreForPlayerKill( entity victim, entity attacker, var damageInfo ) -{ - if ( victim != attacker && victim.IsPlayer() && attacker.IsPlayer() && GetGameState() == eGameState.Epilogue) - AddTeamScore( attacker.GetTeam(), 1 ) -} \ No newline at end of file -- cgit v1.2.3 From 269dda4ad2bf2ecf774f6a1f704b338d357811da Mon Sep 17 00:00:00 2001 From: x3Karma Date: Thu, 30 Dec 2021 14:27:17 +0800 Subject: adds timeout checker to PvP --- .../scripts/vscripts/gamemodes/_gamemode_ps.nut | 42 ++++++++++++++-------- 1 file changed, 27 insertions(+), 15 deletions(-) (limited to 'Northstar.CustomServers') diff --git a/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_ps.nut b/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_ps.nut index 7e3e5ea2..7eec7c89 100644 --- a/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_ps.nut +++ b/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_ps.nut @@ -1,15 +1,27 @@ -global function GamemodePs_Init - -void function GamemodePs_Init() -{ - Riff_ForceTitanAvailability( eTitanAvailability.Never ) - - AddCallback_OnPlayerKilled( GiveScoreForPlayerKill ) - ScoreEvent_SetupEarnMeterValuesForMixedModes() -} - -void function GiveScoreForPlayerKill( entity victim, entity attacker, var damageInfo ) -{ - if ( victim != attacker && victim.IsPlayer() && attacker.IsPlayer() && GetGameState() != eGameState.Epilogue ) - AddTeamScore( attacker.GetTeam(), 1 ) -} +global function GamemodePs_Init + +void function GamemodePs_Init() +{ + Riff_ForceTitanAvailability( eTitanAvailability.Never ) + + AddCallback_OnPlayerKilled( GiveScoreForPlayerKill ) + ScoreEvent_SetupEarnMeterValuesForMixedModes() + SetTimeoutWinnerDecisionFunc( CheckScoreForDraw ) + +} + +void function GiveScoreForPlayerKill( entity victim, entity attacker, var damageInfo ) +{ + if ( victim != attacker && victim.IsPlayer() && attacker.IsPlayer() || GetGameState() != eGameState.Playing ) + AddTeamScore( attacker.GetTeam(), 1 ) +} + +int function CheckScoreForDraw() +{ + if (GameRules_GetTeamScore(TEAM_IMC) > GameRules_GetTeamScore(TEAM_MILITIA)) + return TEAM_IMC + else if (GameRules_GetTeamScore(TEAM_MILITIA) > GameRules_GetTeamScore(TEAM_IMC)) + return TEAM_MILITIA + + return TEAM_UNASSIGNED +} \ No newline at end of file -- cgit v1.2.3