From 9a96d0bff56f1969c68bb52a2f33296095bdc67d Mon Sep 17 00:00:00 2001 From: BobTheBob <32057864+BobTheBob9@users.noreply.github.com> Date: Tue, 31 Aug 2021 23:14:58 +0100 Subject: move to new mod format --- .../vscripts/gamemodes/_gamemode_arena.gnut | 185 +++++++++++++++ .../vscripts/gamemodes/_gamemode_fastball.gnut | 195 +++++++++++++++ .../gamemodes/_gamemode_fastball_intro.gnut | 201 ++++++++++++++++ .../scripts/vscripts/gamemodes/_gamemode_gg.gnut | 114 +++++++++ .../scripts/vscripts/gamemodes/_gamemode_inf.gnut | 179 ++++++++++++++ .../scripts/vscripts/gamemodes/_gamemode_kr.gnut | 126 ++++++++++ .../scripts/vscripts/gamemodes/_gamemode_sbox.gnut | 49 ++++ .../scripts/vscripts/gamemodes/_gamemode_tt.gnut | 71 ++++++ .../scripts/vscripts/gamemodes/_riff_instagib.gnut | 65 +++++ .../vscripts/gamemodes/cl_gamemode_arena.gnut | 40 ++++ .../vscripts/gamemodes/cl_gamemode_fastball.gnut | 96 ++++++++ .../scripts/vscripts/gamemodes/cl_gamemode_gg.gnut | 26 ++ .../vscripts/gamemodes/cl_gamemode_inf.gnut | 75 ++++++ .../scripts/vscripts/gamemodes/cl_gamemode_kr.gnut | 241 +++++++++++++++++++ .../scripts/vscripts/gamemodes/cl_gamemode_tt.gnut | 26 ++ .../vscripts/gamemodes/sh_arena_loadouts.gnut | 98 ++++++++ .../vscripts/gamemodes/sh_gamemode_arena.gnut | 58 +++++ .../vscripts/gamemodes/sh_gamemode_bomb.gnut | 0 .../vscripts/gamemodes/sh_gamemode_ctf_comp.gnut | 114 +++++++++ .../vscripts/gamemodes/sh_gamemode_fastball.gnut | 47 ++++ .../vscripts/gamemodes/sh_gamemode_fw_custom.nut | 73 ++++++ .../scripts/vscripts/gamemodes/sh_gamemode_gg.gnut | 165 +++++++++++++ .../vscripts/gamemodes/sh_gamemode_inf.gnut | 58 +++++ .../scripts/vscripts/gamemodes/sh_gamemode_kr.gnut | 55 +++++ .../vscripts/gamemodes/sh_gamemode_sbox.gnut | 20 ++ .../scripts/vscripts/gamemodes/sh_gamemode_tt.gnut | 36 +++ .../vscripts/gamemodes/sh_riff_floor_is_lava.nut | 262 +++++++++++++++++++++ 27 files changed, 2675 insertions(+) create mode 100644 Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_arena.gnut create mode 100644 Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_fastball.gnut create mode 100644 Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_fastball_intro.gnut create mode 100644 Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_gg.gnut create mode 100644 Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_inf.gnut create mode 100644 Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_kr.gnut create mode 100644 Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_sbox.gnut create mode 100644 Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_tt.gnut create mode 100644 Northstar.Custom/mod/scripts/vscripts/gamemodes/_riff_instagib.gnut create mode 100644 Northstar.Custom/mod/scripts/vscripts/gamemodes/cl_gamemode_arena.gnut create mode 100644 Northstar.Custom/mod/scripts/vscripts/gamemodes/cl_gamemode_fastball.gnut create mode 100644 Northstar.Custom/mod/scripts/vscripts/gamemodes/cl_gamemode_gg.gnut create mode 100644 Northstar.Custom/mod/scripts/vscripts/gamemodes/cl_gamemode_inf.gnut create mode 100644 Northstar.Custom/mod/scripts/vscripts/gamemodes/cl_gamemode_kr.gnut create mode 100644 Northstar.Custom/mod/scripts/vscripts/gamemodes/cl_gamemode_tt.gnut create mode 100644 Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_arena_loadouts.gnut create mode 100644 Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_gamemode_arena.gnut create mode 100644 Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_gamemode_bomb.gnut create mode 100644 Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_gamemode_ctf_comp.gnut create mode 100644 Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_gamemode_fastball.gnut create mode 100644 Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_gamemode_fw_custom.nut create mode 100644 Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_gamemode_gg.gnut create mode 100644 Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_gamemode_inf.gnut create mode 100644 Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_gamemode_kr.gnut create mode 100644 Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_gamemode_sbox.gnut create mode 100644 Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_gamemode_tt.gnut create mode 100644 Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_riff_floor_is_lava.nut (limited to 'Northstar.Custom/mod/scripts/vscripts/gamemodes') diff --git a/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_arena.gnut b/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_arena.gnut new file mode 100644 index 000000000..1765fd9ba --- /dev/null +++ b/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_arena.gnut @@ -0,0 +1,185 @@ +global function GameModeArena_Init + +struct { + bool inBuyPhase + + entity imcBoostStore + entity militiaBoostStore + + entity imcShield + entity militiaShield +} file + +void function GameModeArena_Init() +{ + SetSpawnpointGamemodeOverride( TEAM_DEATHMATCH ) + + SetShouldUseRoundWinningKillReplay( true ) + SetRoundBased( true ) + SetRespawnsEnabled( false ) + SetLoadoutGracePeriodEnabled( false ) // prevent modifying loadouts with grace period + Riff_ForceTitanAvailability( eTitanAvailability.Never ) + Riff_ForceBoostAvailability( eBoostAvailability.Disabled ) + Riff_ForceSetEliminationMode( eEliminationMode.Pilots ) + + ClassicMP_SetCustomIntro( GameModeArena_BuyPhaseSetup, 30.0 ) + AddCallback_EntitiesDidLoad( CreateBoostStores ) + AddCallback_OnPlayerRespawned( SetupArenaLoadoutForPlayer ) +} + +// intro / buy phase + +void function GameModeArena_BuyPhaseSetup() +{ + AddCallback_OnClientConnected( SpawnPlayerIntoArenasIntro ) + AddCallback_GameStateEnter( eGameState.Prematch, void function() { thread BuyPhase() } ) +} + +void function SpawnPlayerIntoArenasIntro( entity player ) +{ + if ( GetGameState() == eGameState.Prematch ) + RespawnAsPilot( player ) +} + +void function CreateBoostStores() +{ + array startspawns = GetEntArrayByClass_Expensive( "info_spawnpoint_human_start" ) // easier to do this than use a spawn callback imo + + vector imcAverageOrigin + float imcAverageAngle + int imcNumSpawns + + vector militiaAverageOrigin + float militiaAverageAngle + int militiaNumSpawns + + foreach ( entity startspawn in startspawns ) + { + if ( !startspawn.HasKey( "gamemode_tdm" ) || startspawn.kv.gamemode_tdm == "0" ) + continue + + if ( startspawn.GetTeam() == TEAM_IMC ) + { + imcAverageOrigin += startspawn.GetOrigin() + imcAverageAngle += startspawn.GetAngles().y + imcNumSpawns++ + } + else + { + militiaAverageOrigin += startspawn.GetOrigin() + militiaAverageAngle += startspawn.GetAngles().y + militiaNumSpawns++ + } + } + + // create imc boost store + vector finalPositionImc = < imcAverageOrigin.x / imcNumSpawns, imcAverageOrigin.y / imcNumSpawns, imcAverageOrigin.z / imcNumSpawns > + finalPositionImc += ( 200 * AnglesToForward( < 0, imcAverageAngle / imcNumSpawns, 0 > ) ) + CreateBoostStoreLocation( TEAM_IMC, finalPositionImc, < 0, 0, 0 >, true ) + + vector finalPositionMilitia = < militiaAverageOrigin.x / militiaNumSpawns, militiaAverageOrigin.y / militiaNumSpawns, militiaAverageOrigin.z / militiaNumSpawns > + finalPositionMilitia += ( 200 * AnglesToForward( < 0, militiaAverageAngle / militiaNumSpawns, 0 > ) ) + CreateBoostStoreLocation( TEAM_MILITIA, finalPositionMilitia, < 0, 0, 0 >, true ) + + // createbooststorelocation is void so have to do this + // also boost store code is just fully fucked lol, teams only get set on open so can't compare teams at this point + // sorry if someone else makes their own boost stores lol this'll just break + // if there's some way to get the invisible crates used for boost stores i will be very happy + + if ( GetBoostStores().len() != 2 ) + print( "_gamemode_arena.gnut: there are more than 2 boost stores, very bad no good" ) + + file.imcBoostStore = GetBoostStores()[0] + file.militiaBoostStore = GetBoostStores()[1] +} + +void function BuyPhase() +{ + ClassicMP_OnIntroStarted() + + foreach ( entity player in GetPlayerArray() ) + { + ScreenFadeFromBlack( player ) + RespawnAsPilot( player ) + + AddMoneyToPlayer( player, GetCashBoostForRoundCount( GetRoundsPlayed() ) ) + } + + SetJoinInProgressBonus( GetCashBoostForRoundCount( GetRoundsPlayed() ) ) + + // sort of a hack, set up a new intro here, so dropship intro only ever plays once + + //file.imcShield = CreateBubbleShieldWithSettings( TEAM_IMC, file.imcBoostStore.GetOrigin(), <0,0,0>, null, 15.0 ) + //file.militiaShield = CreateBubbleShieldWithSettings( TEAM_MILITIA, file.militiaBoostStore.GetOrigin(), <0,0,0>, null, 15.0 ) + + entity imcShield = CreateEntity( "prop_dynamic" ) + imcShield.SetValueForModelKey( $"models/fx/xo_shield.mdl" ) + imcShield.kv.solid = 0 + imcShield.kv.rendercolor = "255 255 255" // white + imcShield.kv.modelscale = 2.25 + imcShield.SetOrigin( file.imcBoostStore.GetOrigin() ) + DispatchSpawn( imcShield ) + + entity militiaShield = CreateEntity( "prop_dynamic" ) + militiaShield.SetValueForModelKey( $"models/fx/xo_shield.mdl" ) + militiaShield.kv.solid = 0 + militiaShield.kv.rendercolor = "255 255 255" // white + militiaShield.kv.modelscale = 2.25 + militiaShield.SetOrigin( file.militiaBoostStore.GetOrigin() ) + DispatchSpawn( militiaShield ) + + // current problem, there is seemingly no way of getting a shield we can resize which actually resizes the collision + // could probably just damage players that try to leave lol + + OpenBoostStores() + + thread DamageLeavingPlayers( imcShield.GetOrigin(), militiaShield.GetOrigin() ) + + wait 30.0 // intro length + + CloseBoostStores() + imcShield.Destroy() + militiaShield.Destroy() + + foreach ( entity player in GetPlayerArray() ) + if ( player.GetMainWeapons().len() != 3 ) + player.GiveWeapon( "mp_weapon_semipistol" ) + + ClassicMP_OnIntroFinished() +} + +void function DamageLeavingPlayers( vector imcOrigin, vector militiaOrigin ) +{ + while ( GetGameState() == eGameState.Prematch ) + { + wait 0.5 + foreach ( entity player in GetPlayerArray() ) + { + vector pos = imcOrigin + if ( player.GetTeam() == TEAM_MILITIA ) + pos = militiaOrigin + + if ( Distance( player.GetOrigin(), pos ) > 510.0 ) // roughly the size of the shield + player.TakeDamage( 25, svGlobal.worldspawn, svGlobal.worldspawn, {} ) + } + } +} + +void function SetupArenaLoadoutForPlayer( entity player ) +{ + PilotLoadoutDef playerLoadout = clone GetActivePilotLoadout( player ) + + if ( GetGameState() == eGameState.Prematch ) // buy phase + { + playerLoadout.primary = "" + playerLoadout.primaryMods = [] + playerLoadout.secondary = "" + playerLoadout.secondaryMods = [] + playerLoadout.weapon3 = "" + playerLoadout.weapon3Mods = [] + playerLoadout.ordnance = "" + playerLoadout.special = "" + } + + GivePilotLoadout( player, playerLoadout ) +} \ No newline at end of file diff --git a/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_fastball.gnut b/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_fastball.gnut new file mode 100644 index 000000000..b59cd2dd4 --- /dev/null +++ b/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_fastball.gnut @@ -0,0 +1,195 @@ +untyped +global function GamemodeFastball_Init + +struct { + // first panel is a, second is b, third is c + array panelSpawns +} file + +void function GamemodeFastball_Init() +{ + // used for intro + PrecacheModel( $"models/titans/buddy/titan_buddy.mdl" ) + PrecacheParticleSystem( $"P_BT_eye_SM" ) + + // used for respawn + PrecacheParticleSystem( $"P_pod_screen_lasers_OUT" ) + + SetShouldUseRoundWinningKillReplay( true ) + SetRoundBased( true ) + SetRespawnsEnabled( false ) + Riff_ForceSetEliminationMode( eEliminationMode.Pilots ) + + // implementing intro in a different file because it'll likely be big + ClassicMP_SetCustomIntro( GamemodeFastballIntroSetup, 14.5 ) // bit of a guess number + AddCallback_EntitiesDidLoad( SpawnPanelsForLevel ) + AddCallback_GameStateEnter( eGameState.Prematch, ResetPanels ) + SetTimeoutWinnerDecisionFunc( FastballDecideWinner ) + + AddCallback_OnClientConnected( FastballInitPlayer ) + AddCallback_OnPlayerKilled( FastballOnPlayerKilled ) // move this to a system in _gamestate soon!! + + // setup spawns + // first is a, second is b, third is c + + FastballAddBuddySpawnForLevel( "mp_angel_city", TEAM_IMC, < 2281.39, -3333.06, 200.031 >, < 0, 91.23, 0 > ) + FastballAddBuddySpawnForLevel( "mp_angel_city", TEAM_MILITIA, < -4139.57, 4684.4, 41.0313 >, <0, -14.326, 0 > ) + FastballAddPanelSpawnsForLevel( "mp_angel_city", [ + < 2055.94, 2040.03, 128.031 >, < 0, -180, 0 >, + < -274.757, 2255.22, 400.031 >, < 0, -176.251, 0 >, + < -3208.28, 2741.17, 128.031 >, < 0, -0.0821686, 0 > + ]) + + FastballAddBuddySpawnForLevel( "mp_thaw", TEAM_MILITIA, < 2049.29, -4085.22, -274.839 >, < 0, 89.2991, 0 > ) + FastballAddBuddySpawnForLevel( "mp_thaw", TEAM_IMC, < 834.484, 2664.28, -380.515 >, < 0.532141, -90.875, -0.542593 > ) + FastballAddPanelSpawnsForLevel( "mp_thaw", [ + < -1026.71, -1691.93, -319.969 >, < 0, 90, 0 >, + < 1836.07, -538.823, -64.1245 >, < 0, -135, 0 >, + < 2840.15, 1321.17, -63.9688 >, < 0, 0, 0 > + ]) + + FastballAddBuddySpawnForLevel( "mp_wargames", TEAM_MILITIA, < -4848.87, 682.17, -127.969 >, < 0, 0, 0 > ) + FastballAddBuddySpawnForLevel( "mp_wargames", TEAM_IMC, < 2960.78, 1229.36, -127.969 >, < 7.89891e-005, 146.505, 1.38387e-005 > ) + FastballAddPanelSpawnsForLevel( "mp_wargames", [ + < -691.961, 1888.56, 112.031 >, < 0, 90, 0 >, + < -1072.03, -508.229, -127.969 >, < 0, 180, 0 >, + < -24.291, -1403.69, -119.969 >, < 0, -90, 0 > + ]) + + FastballAddBuddySpawnForLevel( "mp_eden", TEAM_MILITIA, < -2404.4, 1738.07, 167.767 >, <0, -40.0894, 0> ) + FastballAddBuddySpawnForLevel( "mp_eden", TEAM_IMC, < 5248.01, 414.698, 77.1051 >, < 0, 180, 0 > ) + FastballAddPanelSpawnsForLevel( "mp_eden", [ + < 704.333, 1530.18, 144.031 >, < 0, 90, 0 >, + < -108.43, 272.638, 72.0313 >, < 0, -90, 0 >, + <1044.25, -1145.68, 68.0313>, < 0, 180, 0 > + ]) + + FastballAddBuddySpawnForLevel( "mp_black_water_canal", TEAM_MILITIA, < 1222.88, -5050.63, -187.763 >, < 0, 45, 0 > ) + FastballAddBuddySpawnForLevel( "mp_black_water_canal", TEAM_IMC, < -235.375, 4736.75, -255.969 >, < 0, -90, 0 > ) + FastballAddPanelSpawnsForLevel( "mp_black_water_canal", [ + < 1566.13, -731.539, -63.9688 >, < 0, -90, 0 >, + < 502.603, 1102.92, 260.031 >, < 0, 152.328, 0 >, + < 2337.37, 2099.91, -26.9688 >, < 0, 0, 0 > + ]) + + FastballAddBuddySpawnForLevel( "mp_grave", TEAM_MILITIA, < 11026.8, -5163.18, 1885.64 >, < 0, 155.05, 0 > ) + FastballAddBuddySpawnForLevel( "mp_grave", TEAM_IMC, < -1952, -3120, 1993.33 >, < 0, 0, 0 > ) + FastballAddPanelSpawnsForLevel( "mp_grave", [ + < 5204.54, -2726.54, 2376.03 >, < 0, -90, 0 >, + < 6001.58, -4126.61, 2252.03 >, < 0, -135, 0 >, + < 3595.96, -4568.04, 2376.03 >, < 0, -135, 0 > + ]) +} + +void function SpawnPanelsForLevel() +{ + int panelId + foreach ( Point panelSpawn in file.panelSpawns ) + { + entity panel = CreatePanel( panelSpawn.origin, panelSpawn.angles ) + panel.s.panelId <- panelId++ + } +} + +void function ResetPanels() +{ + foreach ( entity panel in GetAllControlPanels() ) + SetTeam( panel, TEAM_UNASSIGNED ) +} + +void function FastballInitPlayer( entity player ) +{ + foreach ( entity panel in GetAllControlPanels() ) + Remote_CallFunction_NonReplay( player, "ServerCallback_FastballUpdatePanelRui", panel.GetEncodedEHandle(), panel.s.panelId ) +} + +void function FastballAddPanelSpawnsForLevel( string level, array positionsAndOrigins ) +{ + if ( GetMapName() != level ) + return + + for ( int i = 0; i < positionsAndOrigins.len(); i += 2 ) + { + Point spawnPoint + spawnPoint.origin = positionsAndOrigins[ i ] + spawnPoint.angles = positionsAndOrigins[ i + 1 ] + + file.panelSpawns.append( spawnPoint ) + } +} + +entity function CreatePanel( vector origin, vector angles ) +{ + entity panel = CreateEntity( "prop_control_panel" ) + panel.SetValueForModelKey( $"models/communication/terminal_usable_imc_01.mdl" ) + panel.SetOrigin( origin ) + panel.SetAngles( angles ) + panel.kv.solid = SOLID_VPHYSICS + DispatchSpawn( panel ) + + panel.SetModel( $"models/communication/terminal_usable_imc_01.mdl" ) + panel.s.onPlayerFinishesUsing_func = FastballOnPanelHacked + + Highlight_SetNeutralHighlight( panel, "sp_enemy_pilot" ) + + return panel +} + +// control panel code isn't very statically typed, pain +function FastballOnPanelHacked( panel, player, success ) +{ + expect entity( panel ) + expect entity( player ) + expect bool( success ) + + if ( !success ) + return + + print( panel + " was hacked by " + player ) + PanelFlipsToPlayerTeamAndUsableByEnemies( panel, player ) + player.SetPlayerGameStat( PGS_ASSAULT_SCORE, player.GetPlayerGameStat( PGS_ASSAULT_SCORE ) + 1 ) + + foreach ( entity otherPlayer in GetPlayerArray() ) + Remote_CallFunction_NonReplay( otherPlayer, "ServerCallback_FastballPanelHacked", panel.GetEncodedEHandle(), panel.s.panelId, player.GetEncodedEHandle() ) + + // respawn dead players + foreach ( entity deadPlayer in GetPlayerArrayOfTeam( player.GetTeam() ) ) + { + if ( !IsAlive( deadPlayer ) ) + { + deadPlayer.SetOrigin( player.GetOrigin() ) + deadPlayer.RespawnPlayer( null ) + Remote_CallFunction_NonReplay( deadPlayer, "ServerCallback_FastballRespawnPlayer" ) + } + } +} + +void function FastballOnPlayerKilled( entity victim, entity attacker, var damageInfo ) +{ + if ( !victim.IsPlayer() || GetGameState() != eGameState.Playing ) + return + + if ( GetPlayerArrayOfTeam_Alive( victim.GetTeam() ).len() == 0 ) + SetWinner( GetOtherTeam( victim.GetTeam() ) ) +} + +int function FastballDecideWinner() +{ + int militiaPanels + int imcPanels + + foreach ( entity panel in GetAllControlPanels() ) + { + if ( panel.GetTeam() == TEAM_MILITIA ) + militiaPanels++ + else if ( panel.GetTeam() == TEAM_IMC ) + imcPanels++ + } + + if ( militiaPanels > imcPanels ) + return TEAM_MILITIA + else if ( imcPanels > militiaPanels ) + return TEAM_IMC + + return TEAM_UNASSIGNED +} \ No newline at end of file diff --git a/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_fastball_intro.gnut b/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_fastball_intro.gnut new file mode 100644 index 000000000..754825582 --- /dev/null +++ b/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_fastball_intro.gnut @@ -0,0 +1,201 @@ +untyped +global function GamemodeFastballIntroSetup +global function FastballAddBuddySpawnForLevel + +struct { + float introStartTime + + table< int, Point > buddySpawns + entity militiaBuddy + entity imcBuddy + + table playersHoldingJump +} file + +void function GamemodeFastballIntroSetup() +{ + RegisterSignal( "fastball_start_throw" ) + RegisterSignal( "fastball_release" ) + + AddCallback_GameStateEnter( eGameState.Prematch, OnPrematchStart ) + AddCallback_OnClientConnected( AddPlayerToFastballIntro ) +} + +void function FastballAddBuddySpawnForLevel( string level, int team, vector origin, vector angles ) +{ + if ( GetMapName() != level ) + return + + Point spawnPoint + spawnPoint.origin = origin + spawnPoint.angles = angles + + file.buddySpawns[ team ] <- spawnPoint +} + +void function OnPrematchStart() +{ + ClassicMP_OnIntroStarted() + + file.introStartTime = Time() + file.playersHoldingJump = {} // clear it + + Point militiaBuddySpawn + Point imcBuddySpawn + + // figure out positions if there's none manually specified + if ( file.buddySpawns.len() == 0 ) + { + array militiaSpawns + array imcSpawns + + foreach ( entity spawnpoint in GetEntArrayByClass_Expensive( "info_spawnpoint_titan_start" ) ) + { + // trace from top to bottom + float result = TraceHullSimple( spawnpoint.GetOrigin() + < 0, 0, 250 >, spawnpoint.GetOrigin(), < -200, -200, 0 >, < 200, 200, 400 >, null ) + + // don't need to trace much, as long as it's over 0 that means it fits + // cases where it's over 0 but less than 1 are usually caused by terrain + if ( result > 0 ) + { + if ( spawnpoint.GetTeam() == TEAM_MILITIA ) + militiaSpawns.append( spawnpoint ) + else + imcSpawns.append( spawnpoint ) + } + } + + entity milititaSpawnEnt = militiaSpawns[ RandomInt( militiaSpawns.len() ) ] + militiaBuddySpawn.origin = milititaSpawnEnt.GetOrigin() + militiaBuddySpawn.angles = milititaSpawnEnt.GetAngles() + + entity imcSpawnEnt = imcSpawns[ RandomInt( imcSpawns.len() ) ] + imcBuddySpawn.origin = imcSpawnEnt.GetOrigin() + imcBuddySpawn.angles = imcSpawnEnt.GetAngles() + } + else + { + militiaBuddySpawn = file.buddySpawns[ TEAM_MILITIA ] + imcBuddySpawn = file.buddySpawns[ TEAM_IMC ] + } + + file.militiaBuddy = CreatePropDynamic( $"models/titans/buddy/titan_buddy.mdl" ) + file.militiaBuddy.SetOrigin( militiaBuddySpawn.origin ) + file.militiaBuddy.SetAngles( militiaBuddySpawn.angles ) + thread AnimateBuddy( file.militiaBuddy ) + + file.imcBuddy = CreatePropDynamic( $"models/titans/buddy/titan_buddy.mdl" ) + file.imcBuddy.SetOrigin( imcBuddySpawn.origin ) + file.imcBuddy.SetAngles( imcBuddySpawn.angles ) + thread AnimateBuddy( file.imcBuddy ) + + foreach ( entity player in GetPlayerArray() ) + thread FastballPlayer( player ) +} + +void function AnimateBuddy( entity buddy ) +{ + print( "buddy spawn at " + buddy.GetOrigin() + " " + buddy.GetAngles() ) + + thread PlayAnim( buddy, "bt_beacon_fastball_throw_end" ) + + // play dialogue at the right time + buddy.WaitSignal( "fastball_start_throw" ) + float diagDuration = EmitSoundOnEntity( buddy, "diag_sp_spoke1_BE117_04_01_mcor_bt" ) // trust me + StartParticleEffectOnEntity( buddy, GetParticleSystemIndex( $"P_BT_eye_SM" ), FX_PATTACH_POINT_FOLLOW, buddy.LookupAttachment( "EYEGLOW" ) ) + + wait diagDuration + if ( GetGameState() != eGameState.Playing ) + ClassicMP_OnIntroFinished() + + buddy.WaitSignal( "fastball_release" ) + wait 5.0 + buddy.Destroy() +} + +void function AddPlayerToFastballIntro( entity player ) +{ + if ( GetGameState() == eGameState.Prematch ) + thread FastballPlayer( player ) +} + +void function FastballPlayer( entity player ) +{ + player.EndSignal( "OnDeath" ) + player.EndSignal( "OnDestroy" ) + + OnThreadEnd( function() : ( player ) + { + RemoveCinematicFlag( player, CE_FLAG_CLASSIC_MP_SPAWNING ) + player.ClearParent() + ClearPlayerAnimViewEntity( player ) + player.DeployWeapon() + player.PlayerCone_Disable() + }) + + FirstPersonSequenceStruct throwSequence + throwSequence.attachment = "REF" + throwSequence.useAnimatedRefAttachment = true + throwSequence.hideProxy = true + throwSequence.viewConeFunction = ViewConeFastball // this seemingly does not trigger for some reason + throwSequence.firstPersonAnim = "ptpov_beacon_fastball_throw_end" + // mp models seemingly have no 3p animation for this + throwSequence.firstPersonBlendOutTime = 0.0 + throwSequence.teleport = true + throwSequence.setInitialTime = Time() - file.introStartTime + + // get our buddy + entity buddy + if ( player.GetTeam() == TEAM_MILITIA ) + buddy = file.militiaBuddy + else + buddy = file.imcBuddy + + // respawn the player + player.SetOrigin( buddy.GetOrigin() ) + player.RespawnPlayer( null ) + player.Hide() + player.HolsterWeapon() + + // hide hud, fade screen out from black + AddCinematicFlag( player, CE_FLAG_CLASSIC_MP_SPAWNING ) + ScreenFadeFromBlack( player, 0.5, 0.5 ) + + // start fp sequence + thread FirstPersonSequence( throwSequence, player, buddy ) + + // manually do this because i can't get viewconefastball to work + player.PlayerCone_FromAnim() + player.PlayerCone_SetMinYaw( -50 ) + player.PlayerCone_SetMaxYaw( 25 ) + player.PlayerCone_SetMinPitch( -15 ) + player.PlayerCone_SetMaxPitch( 15 ) + + buddy.WaitSignal( "fastball_start_throw" ) + // lock in their final angles at this point + vector throwVel = AnglesToForward( player.EyeAngles() ) * 950 + throwVel.z = 675.0 + + // wait for it to finish + buddy.WaitSignal( "fastball_release" ) + + if ( player.IsInputCommandHeld( IN_JUMP ) ) + throwVel.z = 850.0 + + // have to correct this manually here since due to no 3p animation our position isn't set right during this sequence + player.SetOrigin( buddy.GetAttachmentOrigin( buddy.LookupAttachment( "FASTBALL_R" ) ) ) + player.Show() + player.SetVelocity( throwVel ) + + TryGameModeAnnouncement( player ) +} + +void function PlayerHoldingJumpInIntro( entity player ) +{ + file.playersHoldingJump[ player ] <- true +} + +void function PlayerNoLongerHoldingJumpInIntro( entity player ) +{ + file.playersHoldingJump[ player ] <- false +} \ No newline at end of file diff --git a/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_gg.gnut b/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_gg.gnut new file mode 100644 index 000000000..b9ee40f1f --- /dev/null +++ b/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_gg.gnut @@ -0,0 +1,114 @@ +global function GamemodeGG_Init + +void function GamemodeGG_Init() +{ + SetSpawnpointGamemodeOverride( FFA ) + + SetShouldUseRoundWinningKillReplay( true ) + Evac_SetEnabled( false ) + SetLoadoutGracePeriodEnabled( false ) // prevent modifying loadouts with grace period + SetWeaponDropsEnabled( false ) + Riff_ForceTitanAvailability( eTitanAvailability.Never ) + Riff_ForceBoostAvailability( eBoostAvailability.Disabled ) + + AddCallback_OnPlayerRespawned( OnPlayerRespawned ) + AddCallback_OnPlayerKilled( OnPlayerKilled ) + + AddCallback_GameStateEnter( eGameState.WinnerDetermined, OnWinnerDetermined ) +} + +void function OnPlayerRespawned( entity player ) +{ + UpdateLoadout( player ) + thread OnPlayerRespawned_Threaded( player ) +} + +void function OnPlayerRespawned_Threaded( entity player ) +{ + // bit of a hack, need to rework earnmeter code to have better support for completely disabling it + // rn though this just waits for earnmeter code to set the mode before we set it back + WaitFrame() + PlayerEarnMeter_SetMode( player, eEarnMeterMode.DISABLED ) +} + +void function OnPlayerKilled( entity victim, entity attacker, var damageInfo ) +{ + if ( !victim.IsPlayer() || !attacker.IsPlayer() || GetGameState() != eGameState.Playing ) + return + + if ( attacker == victim ) // suicide + { + string message = victim.GetPlayerName() + " committed suicide." + foreach ( entity player in GetPlayerArray() ) + SendHudMessage( player, message, -1, 0.4, 255, 0, 0, 0, 0, 3, 0.15 ) + + if ( GameRules_GetTeamScore( victim.GetTeam() ) != 0 ) + { + AddTeamScore( victim.GetTeam(), -1 ) // get absolutely fucking destroyed lol + victim.AddToPlayerGameStat( PGS_ASSAULT_SCORE, -1 ) + } + } + else + { + if ( DamageInfo_GetDamageSourceIdentifier( damageInfo ) != eDamageSourceId.melee_pilot_emptyhanded ) + { + AddTeamScore( attacker.GetTeam(), 1 ) + attacker.AddToPlayerGameStat( PGS_ASSAULT_SCORE, 1 ) + UpdateLoadout( attacker ) + } + + if ( DamageInfo_GetDamageSourceIdentifier( damageInfo ) == eDamageSourceId.human_execution ) + { + string message = victim.GetPlayerName() + " got executed." + foreach ( entity player in GetPlayerArray() ) + SendHudMessage( player, message, -1, 0.4, 255, 0, 0, 0, 0, 3, 0.15 ) + + if ( GameRules_GetTeamScore( victim.GetTeam() ) != 0 ) + { + AddTeamScore( victim.GetTeam(), -1 ) // get absolutely fucking destroyed lol + victim.AddToPlayerGameStat( PGS_ASSAULT_SCORE, -1 ) + } + } + } +} + +void function UpdateLoadout( entity player ) +{ + // todo: honestly, this should be reworked to use PilotLoadoutDefs instead of directly modifying weapons and shit + + int currentWeaponIndex = GameRules_GetTeamScore( player.GetTeam() ) + array weapons = GetGunGameWeapons() + + if ( currentWeaponIndex >= weapons.len() ) + currentWeaponIndex = weapons.len() - 1 + + if ( currentWeaponIndex > 18 ) // play end of game music for special weapons + PlayMusicToAll( eMusicPieceID.LEVEL_LAST_MINUTE ) // this *shouldn't* overlap if done multiple times + + GunGameWeapon weapon = weapons[ currentWeaponIndex ] + + foreach ( entity weapon in player.GetMainWeapons() ) + player.TakeWeaponNow( weapon.GetWeaponClassName() ) + + foreach ( entity weapon in player.GetOffhandWeapons() ) + player.TakeWeaponNow( weapon.GetWeaponClassName() ) + + if ( weapon.offhandSlot != -1 ) + { + // TEMP: give archer so player so player has a weapon which lets them use offhands + // need to replace this with a custom empty weapon at some point + player.GiveWeapon( "mp_weapon_rocket_launcher" ) + + player.GiveOffhandWeapon( weapon.weapon, weapon.offhandSlot, weapon.mods ) + } + else + player.GiveWeapon( weapon.weapon, weapon.mods ) + + player.GiveOffhandWeapon( "melee_pilot_emptyhanded", OFFHAND_MELEE ) +} + +void function OnWinnerDetermined() +{ + SetRespawnsEnabled( false ) + SetKillcamsEnabled( false ) +} \ No newline at end of file diff --git a/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_inf.gnut b/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_inf.gnut new file mode 100644 index 000000000..8706d53b1 --- /dev/null +++ b/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_inf.gnut @@ -0,0 +1,179 @@ +global function GamemodeInfection_Init + +struct { + bool hasHadFirstInfection = false + array playersToNotifyOfInfection +} file + +void function GamemodeInfection_Init() +{ + SetSpawnpointGamemodeOverride( FFA ) + SetLoadoutGracePeriodEnabled( false ) // prevent modifying loadouts with grace period + SetWeaponDropsEnabled( false ) + Riff_ForceTitanAvailability( eTitanAvailability.Never ) + Riff_ForceBoostAvailability( eBoostAvailability.Disabled ) + + AddCallback_OnClientConnected( InfectionInitPlayer ) + AddCallback_OnPlayerKilled( InfectionOnPlayerKilled ) + AddCallback_OnPlayerRespawned( RespawnInfected ) + AddCallback_GameStateEnter( eGameState.Playing, SelectFirstInfected ) + + SetTimeoutWinnerDecisionFunc( TimeoutCheckSurvivors ) +} + +void function InfectionInitPlayer( entity player ) +{ + if ( GetGameState() < eGameState.Playing ) + SetTeam( player, INFECTION_TEAM_SURVIVOR ) + else + InfectPlayer( player ) +} + +void function SelectFirstInfected() +{ + thread SelectFirstInfectedDelayed() +} + +void function SelectFirstInfectedDelayed() +{ + wait 10.0 + RandomFloat( 5.0 ) + + array players = GetPlayerArray() + entity infected = players[ RandomInt( players.len() ) ] + + InfectPlayer( infected ) + RespawnInfected( infected ) +} + +void function InfectionOnPlayerKilled( entity victim, entity attacker, var damageInfo ) +{ + if ( !victim.IsPlayer() || GetGameState() != eGameState.Playing ) + return + + if ( victim.GetTeam() == INFECTION_TEAM_SURVIVOR ) + InfectPlayer( victim ) + + if ( attacker.IsPlayer() ) + attacker.SetPlayerGameStat( PGS_ASSAULT_SCORE, attacker.GetPlayerGameStat( PGS_ASSAULT_SCORE ) + 1 ) +} + +void function InfectPlayer( entity player ) +{ + SetTeam( player, INFECTION_TEAM_INFECTED ) + player.SetPlayerGameStat( PGS_ASSAULT_SCORE, 0 ) // reset kills + file.playersToNotifyOfInfection.append( player ) + + // check how many survivors there are + array survivors = GetPlayerArrayOfTeam( INFECTION_TEAM_SURVIVOR ) + if ( survivors.len() == 0 ) + SetWinner( INFECTION_TEAM_INFECTED ) + else if ( survivors.len() == 1 ) + SetLastSurvivor( survivors[ 0 ] ) + + if ( !file.hasHadFirstInfection ) + { + file.hasHadFirstInfection = true + + foreach ( entity otherPlayer in GetPlayerArray() ) + if ( player != otherPlayer ) + Remote_CallFunction_NonReplay( otherPlayer, "ServerCallback_AnnounceFirstInfected", player.GetEncodedEHandle() ) + + PlayMusicToAll( eMusicPieceID.GAMEMODE_1 ) + } +} + +void function RespawnInfected( entity player ) +{ + if ( player.GetTeam() != INFECTION_TEAM_INFECTED ) + return + + // notify newly infected players of infection + if ( file.playersToNotifyOfInfection.contains( player ) ) + { + Remote_CallFunction_NonReplay( player, "ServerCallback_YouAreInfected" ) + file.playersToNotifyOfInfection.remove( file.playersToNotifyOfInfection.find( player ) ) + } + + // set camo to pond scum + player.SetSkin( 1 ) + player.SetCamo( 110 ) + + // stats for infected + StimPlayer( player, 9999.9 ) // can't do endless since we don't get the visual effect in endless + player.kv.airAcceleration = 2500 + + // scale health with num of infected, with 50 as base health + player.SetMaxHealth( ( GetPlayerArrayOfTeam( INFECTION_TEAM_SURVIVOR ).len() + 1 ) * 10 ) + + // set loadout + foreach ( entity weapon in player.GetMainWeapons() ) + player.TakeWeaponNow( weapon.GetWeaponClassName() ) + + foreach ( entity weapon in player.GetOffhandWeapons() ) + player.TakeWeaponNow( weapon.GetWeaponClassName() ) + + // TEMP: give archer so player so player has a weapon which lets them use offhands + // need to replace this with a custom empty weapon at some point + //player.GiveWeapon( "mp_weapon_rocket_launcher" ) + player.GiveWeapon( "mp_weapon_mgl" ) + player.GiveOffhandWeapon( "melee_pilot_emptyhanded", OFFHAND_MELEE ) + + thread PlayInfectedSounds( player ) +} + +void function PlayInfectedSounds( entity player ) +{ + player.EndSignal( "OnDeath" ) + player.EndSignal( "OnDestroy" ) + + float nextRandomSound + while ( true ) + { + WaitFrame() + + int meleeState = player.PlayerMelee_GetState() + if ( nextRandomSound < Time() || meleeState != 0 ) + { + string selectedSound + if ( CoinFlip() ) + selectedSound = "prowler_vocal_attack" + else + selectedSound = "prowler_vocal_attackmiss" + + bool canSeeSurvivor + foreach ( entity survivor in GetPlayerArrayOfTeam( INFECTION_TEAM_SURVIVOR ) ) + if ( TraceLineSimple( player.GetOrigin(), survivor.GetOrigin(), survivor ) == 1.0 ) + canSeeSurvivor = true + + // _int sounds are less agressive so only play them if we aren't in some sorta fight + if ( player.GetHealth() == player.GetMaxHealth() || !canSeeSurvivor || meleeState != 0 ) + selectedSound += "_int" + + EmitSoundOnEntity( player, selectedSound ) + + nextRandomSound = Time() + max( 2.5, RandomFloat( 12.0 ) ) + while ( player.PlayerMelee_GetState() != 0 ) // need to ensure this is updated + WaitFrame() + } + } +} + +void function SetLastSurvivor( entity player ) +{ + foreach ( entity otherPlayer in GetPlayerArray() ) + Remote_CallFunction_NonReplay( otherPlayer, "ServerCallback_AnnounceLastSurvivor", player.GetEncodedEHandle() ) + + Highlight_SetEnemyHighlight( player, "enemy_sonar" ) + thread CreateTitanForPlayerAndHotdrop( player, GetTitanReplacementPoint( player, false ) ) + + if ( GameTime_TimeLeftSeconds() > 45 ) + SetServerVar( "gameEndTime", Time() + 45.0 ) +} + +int function TimeoutCheckSurvivors() +{ + if ( GetPlayerArrayOfTeam( INFECTION_TEAM_SURVIVOR ).len() > 0 ) + return INFECTION_TEAM_SURVIVOR + + return INFECTION_TEAM_INFECTED +} \ No newline at end of file diff --git a/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_kr.gnut b/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_kr.gnut new file mode 100644 index 000000000..cf9d6bc57 --- /dev/null +++ b/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_kr.gnut @@ -0,0 +1,126 @@ +global function GamemodeKR_Init + +struct { + float currentHighestKillraceAmount + int currentKillraceScore + entity currentRacer + array flagSpawnPoints +} file + +void function GamemodeKR_Init() +{ + PrecacheModel( CTF_FLAG_MODEL ) + + SetSpawnpointGamemodeOverride( FFA ) + + Evac_SetEnabled( false ) + Riff_ForceTitanAvailability( eTitanAvailability.Never ) + Riff_ForceBoostAvailability( eBoostAvailability.Disabled ) + + AddSpawnCallback( "info_hardpoint", AddFlagSpawnPoint ) + + AddCallback_OnPlayerKilled( OnPlayerKilled ) + AddCallback_OnTouchHealthKit( "item_flag", StartPlayerKillrace ) + + AddCallback_GameStateEnter( eGameState.Playing, StartKillraceSpawnThink ) +} + +void function AddFlagSpawnPoint( entity hardpoint ) +{ + if ( hardpoint.HasKey( "hardpointGroup" ) && ( hardpoint.kv.hardpointGroup == "A" || hardpoint.kv.hardpointGroup == "B" || hardpoint.kv.hardpointGroup == "C" ) ) + file.flagSpawnPoints.append( hardpoint.GetOrigin() ) +} + +void function OnPlayerKilled( entity victim, entity attacker, var damageInfo ) +{ + if ( !victim.IsPlayer() || !attacker.IsPlayer() || attacker == victim ) + return + + float killRaceTime = attacker.GetPlayerNetTime( "killRaceTime" ) + 5.0 + attacker.SetPlayerNetTime( "killRaceTime", killRaceTime ) + if ( killRaceTime > file.currentHighestKillraceAmount ) + file.currentHighestKillraceAmount = killRaceTime + if ( file.currentRacer != null ) + file.currentKillraceScore++ +} + +bool function StartPlayerKillrace( entity player, entity flag ) +{ + float killRaceTime = player.GetPlayerNetTime( "killRaceTime" ) + if ( killRaceTime > 0.0 ) + { + thread PlayerKillrace( player, killRaceTime ) + return true // delete the flag entity + } + + return false // keep it alive +} + +void function PlayerKillrace( entity player, float raceTime ) +{ + file.currentKillraceScore = 0 + file.currentRacer = player + int oldMaxHealth = player.GetMaxHealth() + + player.SetMaxHealth( oldMaxHealth * 10 ) + player.SetHealth( player.GetMaxHealth() ) + + foreach ( entity weapon in player.GetMainWeapons() ) + foreach ( string mod in GetWeaponBurnMods( weapon.GetWeaponClassName() ) ) + weapon.AddMod( mod ) + + foreach ( entity otherPlayer in GetPlayerArray() ) + Remote_CallFunction_NonReplay( otherPlayer, "ServerCallback_NewKillRacer", player.GetEncodedEHandle(), Time() + raceTime ) + + float raceEnd = Time() + raceTime + while ( raceEnd > Time() && IsAlive( player ) ) + WaitFrame() + + player.SetPlayerNetTime( "killRaceTime", 0.0 ) + player.SetMaxHealth( oldMaxHealth ) + + foreach ( entity weapon in player.GetMainWeapons() ) + foreach ( string mod in GetWeaponBurnMods( weapon.GetWeaponClassName() ) ) + weapon.RemoveMod( mod ) + + foreach ( entity otherPlayer in GetPlayerArray() ) + Remote_CallFunction_NonReplay( otherPlayer, "ServerCallback_EndKillrace", player.GetEncodedEHandle(), file.currentKillraceScore ) + + if ( GameRules_GetTeamScore( player.GetTeam() ) < file.currentKillraceScore ) + { + GameRules_SetTeamScore( player.GetTeam(), file.currentKillraceScore ) + player.SetPlayerGameStat( PGS_ASSAULT_SCORE, file.currentKillraceScore ) + } + + thread KillraceSpawnThink() // go to spawn next flag +} + +void function StartKillraceSpawnThink() +{ + thread KillraceSpawnThink() +} + +void function KillraceSpawnThink() +{ + file.currentHighestKillraceAmount = 0 + file.currentRacer = null + file.currentKillraceScore = 0 + float time = Time() + while ( time + 20.0 > Time() && file.currentHighestKillraceAmount < 25 ) + WaitFrame() + + vector spawnpos = file.flagSpawnPoints[ RandomInt( file.flagSpawnPoints.len() ) ] + foreach ( entity player in GetPlayerArray() ) + Remote_CallFunction_NonReplay( player, "ServerCallback_FlagSpawnIncoming", spawnpos.x, spawnpos.y, spawnpos.z, Time() + 15 ) + + wait 15.0 + + // create a flag + entity flag = CreateEntity( "item_flag" ) + flag.SetValueForModelKey( CTF_FLAG_MODEL ) + SetTargetName( flag, "krflag" ) + DispatchSpawn( flag ) + flag.SetModel( CTF_FLAG_MODEL ) + flag.SetOrigin( spawnpos + < 0, 0, flag.GetBoundingMaxs().z / 2 > ) // get it out of the ground + flag.SetVelocity( < 0, 0, 1 > ) // make it do gravity again +} \ No newline at end of file diff --git a/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_sbox.gnut b/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_sbox.gnut new file mode 100644 index 000000000..27581aeac --- /dev/null +++ b/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_sbox.gnut @@ -0,0 +1,49 @@ +untyped +global function GamemodeSbox_Init + +struct { + array spawnpoints +} file + +void function GamemodeSbox_Init() +{ + SetConVarInt( "sv_cheats", 1 ) // cheats on by default + + // cache spawnpoints + //file.spawnpoints = GetEntArrayByClass_Expensive( "info_spawnpoint_human" ) + // todo just use a spawn callback for this rather than weird late cache in spawn + + AddCallback_OnClientConnected( SboxSpawnPlayer ) + AddDeathCallback( "player", SboxRespawnPlayer ) +} + +void function SboxSpawnPlayer( entity player ) +{ + if ( player.GetPlayerSettings() == "spectator" ) // if they haven't spawned yet + player.SetPlayerSettings( "pilot_grapple_male" ) + + if ( file.spawnpoints.len() == 0 ) // have to cache late rather than on init due to spawnpoints not existing in init + file.spawnpoints = GetEntArrayByClass_Expensive( "info_spawnpoint_human" ) + + if ( GetGameState() != eGameState.Playing ) // hacky but can't set this in init either + SetGameState( eGameState.Playing ) + + entity spawnpoint = file.spawnpoints[ RandomInt( file.spawnpoints.len() ) ] + + ScreenFadeFromBlack( player, 0.0, 0.0 ) // HACK before non-classicmp intros are ready, remove the blackscreen we get from waitingforplayers + player.RespawnPlayer( spawnpoint ) + player.GiveWeapon( "mp_weapon_toolgun" ) +} + +void function SboxRespawnPlayer( entity player, var damageInfo ) +{ + thread SboxRespawnPlayerThreaded( player ) +} + +void function SboxRespawnPlayerThreaded( entity player ) +{ + // todo: replace this with real respawn logic when that's ready + + wait 2.5 + SboxSpawnPlayer( player ) +} \ No newline at end of file diff --git a/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_tt.gnut b/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_tt.gnut new file mode 100644 index 000000000..6a53ef87b --- /dev/null +++ b/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_tt.gnut @@ -0,0 +1,71 @@ +global function GamemodeTT_Init + +struct { + entity lastPlayerDropped +} file + +void function GamemodeTT_Init() +{ + SetSpawnpointGamemodeOverride( TEAM_DEATHMATCH ) + Riff_ForceTitanAvailability( eTitanAvailability.Never ) + + AddCallback_GameStateEnter( eGameState.Playing, OnEnterPlaying ) + + AddCallback_OnPlayerKilled( OnPlayerKilled ) + AddDeathCallback( "npc_titan", OnTitanKilled ) +} + +void function OnEnterPlaying() +{ + thread DropRandomTitan() +} + +void function DropRandomTitan() +{ + array players = GetPlayerArray() + + if ( players.len() == 1 ) + file.lastPlayerDropped = null // don't wanna loop forever if only 1 player + + entity titanPlayer + do { + titanPlayer = players[ RandomInt( players.len() ) ] + } while ( titanPlayer == file.lastPlayerDropped ) + + DropTitanForPlayer( titanPlayer, 5.0 ) +} + +void function DropTitanForPlayer( entity player, float delay ) +{ + wait delay + + file.lastPlayerDropped = player + CreateTitanForPlayerAndHotdrop( player, GetTitanReplacementPoint( player, false ) ) +} + +void function AttemptToDropTitanForKill( entity victim, entity attacker, var damageInfo ) +{ + if ( !victim.IsTitan() ) + return + + if ( !attacker.IsPlayer() || victim == attacker ) + thread DropRandomTitan() + else + thread DropTitanForPlayer( attacker, 2.0 ) +} + +void function OnPlayerKilled( entity victim, entity attacker, var damageInfo ) +{ + if ( victim.IsTitan() ) + AttemptToDropTitanForKill( victim, attacker, damageInfo ) + else if ( attacker.IsTitan() ) + { + AddTeamScore( attacker.GetTeam(), 1 ) + } +} + +void function OnTitanKilled( entity victim, var damageInfo ) +{ + if ( IsPetTitan( victim ) ) + AttemptToDropTitanForKill( victim, DamageInfo_GetAttacker( damageInfo ), damageInfo ) +} \ No newline at end of file diff --git a/Northstar.Custom/mod/scripts/vscripts/gamemodes/_riff_instagib.gnut b/Northstar.Custom/mod/scripts/vscripts/gamemodes/_riff_instagib.gnut new file mode 100644 index 000000000..b3868359e --- /dev/null +++ b/Northstar.Custom/mod/scripts/vscripts/gamemodes/_riff_instagib.gnut @@ -0,0 +1,65 @@ +global function RiffInstagib_Init + +struct { + table playerWeapons + array instagibWeapons +} file + +void function RiffInstagib_Init() +{ + if ( GetCurrentPlaylistVarInt( "riff_instagib", 0 ) == 0 ) + return + + SetLoadoutGracePeriodEnabled( false ) + SetWeaponDropsEnabled( false ) + + file.instagibWeapons = [ + "mp_weapon_sniper", + "mp_weapon_wingman", + "mp_weapon_defender", + "mp_weapon_arena3", + "mp_weapon_wingman_n", + "mp_weapon_doubletake", + ] + file.instagibWeapons.randomize() + + AddCallback_OnPlayerRespawned( InstagibSetWeapons ) + AddCallback_OnPlayerKilled( InstagibCycleWeaponsForKill ) + AddCallback_OnClientDisconnected( InstagibCleanupClient ) +} + +void function InstagibSetWeapons( entity player ) +{ + if ( !( player in file.playerWeapons ) ) + file.playerWeapons[ player ] <- 0 + + player.SetMaxHealth( 1 ) + InstagibUpdateWeapons( player ) +} + +void function InstagibUpdateWeapons( entity player ) +{ + foreach( entity weapon in player.GetMainWeapons() ) + player.TakeWeaponNow( weapon.GetWeaponClassName() ) + + player.TakeWeaponNow( player.GetOffhandWeapon( OFFHAND_RIGHT ).GetWeaponClassName() ) + if ( !HasOffhandWeapon( player, "mp_weapon_grenade_sonar" ) ) + player.GiveOffhandWeapon( "mp_weapon_grenade_sonar", OFFHAND_RIGHT ) + + player.GiveWeapon( file.instagibWeapons[ file.playerWeapons[ player ] ] ) +} + +void function InstagibCycleWeaponsForKill( entity victim, entity attacker, var damageInfo ) +{ + if ( !victim.IsPlayer() || !attacker.IsPlayer() || victim == attacker ) + return + + file.playerWeapons[ attacker ] = ( file.playerWeapons[ attacker ] + 1 ) % file.instagibWeapons.len() + InstagibUpdateWeapons( attacker ) +} + +void function InstagibCleanupClient( entity player ) +{ + if ( player in file.playerWeapons ) + delete file.playerWeapons[ player ] +} \ No newline at end of file diff --git a/Northstar.Custom/mod/scripts/vscripts/gamemodes/cl_gamemode_arena.gnut b/Northstar.Custom/mod/scripts/vscripts/gamemodes/cl_gamemode_arena.gnut new file mode 100644 index 000000000..632a7efc2 --- /dev/null +++ b/Northstar.Custom/mod/scripts/vscripts/gamemodes/cl_gamemode_arena.gnut @@ -0,0 +1,40 @@ +global function ClGameModeArena_Init +global function ServerCallback_CreateMoneyParticles + +struct { + var moneyRui +} file + +void function ClGameModeArena_Init() +{ + AddCallback_OnClientScriptInit( CreateArenaUI ) + + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_INTRO, "music_mp_fd_intro_easy", TEAM_MILITIA ) + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_INTRO, "music_mp_fd_intro_easy", TEAM_IMC ) +} + +void function CreateArenaUI( entity player ) +{ + AddEventNotificationCallback( eEventNotifications.FD_BoughtItem, void function( entity e, var v ) {} ) + + var rui = CreateCockpitRui( $"ui/fd_score_splash.rpak", 500 ) + RuiTrackInt( rui, "pointValue", player, RUI_TRACK_SCRIPT_NETWORK_VAR_INT, GetNetworkedVariableIndex( "FD_money" ) ) + RuiTrackInt( rui, "pointStack", player, RUI_TRACK_SCRIPT_NETWORK_VAR_INT, GetNetworkedVariableIndex( "FD_money256" ) ) + file.moneyRui = rui +} + +void function ServerCallback_CreateMoneyParticles( int playerHandle, int amount ) +{ + // largely taken from cl_gamemode_fd + entity player = GetEntityFromEncodedEHandle( playerHandle ) + + vector randDir2D = < RandomFloatRange( -1, 1 ), 1, 0 > + randDir2D = Normalize( randDir2D ) + + var rui = RuiCreate( $"ui/at_score_popup.rpak", clGlobal.topoFullScreen, RUI_DRAW_HUD, 100 ) + RuiSetInt( rui, "scoreVal", amount ) + RuiSetGameTime( rui, "startTime", Time() ) + RuiSetFloat3( rui, "pos", player.EyePosition() ) + RuiSetFloat2( rui, "driftDir", randDir2D ) + RuiSetBool( rui, "showNormalPoints", false ) +} \ No newline at end of file diff --git a/Northstar.Custom/mod/scripts/vscripts/gamemodes/cl_gamemode_fastball.gnut b/Northstar.Custom/mod/scripts/vscripts/gamemodes/cl_gamemode_fastball.gnut new file mode 100644 index 000000000..80dc548ab --- /dev/null +++ b/Northstar.Custom/mod/scripts/vscripts/gamemodes/cl_gamemode_fastball.gnut @@ -0,0 +1,96 @@ +global function ClGamemodeFastball_Init +global function ServerCallback_FastballUpdatePanelRui +global function ServerCallback_FastballPanelHacked +global function ServerCallback_FastballRespawnPlayer + +struct { + var panelARui + var panelBRui + var panelCRui +} file + +void function ClGamemodeFastball_Init() +{ + ClGameState_RegisterGameStateAsset( $"ui/gamestate_info_lts.rpak" ) + + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_INTRO, "Music_Beacon_14_BTThrowThruFirstCrane", TEAM_MILITIA ) + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_INTRO, "Music_Beacon_14_BTThrowThruFirstCrane", TEAM_MILITIA ) + + AddCallback_OnClientScriptInit( FastballCreateRui ) +} + +void function FastballCreateRui( entity player ) +{ + file.panelARui = CreateCockpitRui( $"ui/cp_hardpoint_marker.rpak", 200 ) + file.panelBRui = CreateCockpitRui( $"ui/cp_hardpoint_marker.rpak", 200 ) + file.panelCRui = CreateCockpitRui( $"ui/cp_hardpoint_marker.rpak", 200 ) + +} + +void function ServerCallback_FastballUpdatePanelRui( int panelHandle, int id ) +{ + entity panel = GetEntityFromEncodedEHandle( panelHandle ) + var rui + if ( id == 0 ) + rui = file.panelARui + else if ( id == 1 ) + rui = file.panelBRui + else if ( id == 2 ) + rui = file.panelCRui + + RuiSetInt( rui, "hardpointId", id ) + RuiTrackFloat3( rui, "pos", panel, RUI_TRACK_OVERHEAD_FOLLOW ) + RuiSetInt( rui, "viewerTeam", GetLocalClientPlayer().GetTeam() ) + ////RuiTrackInt( rui, "cappingTeam", null, RUI_TRACK_SCRIPT_NETWORK_VAR_GLOBAL_INT, GetNetworkedVariableIndex( "panel" + id + "progress" ) ) + RuiTrackInt( rui, "hardpointTeamRelation", panel, RUI_TRACK_TEAM_RELATION_VIEWPLAYER ) + + RuiSetBool( rui, "isVisible", true ) +} + +void function ServerCallback_FastballPanelHacked( int panelHandle, int id, int capturingPlayerHandle ) +{ + ServerCallback_FastballUpdatePanelRui( panelHandle, id ) // may not be necessary, just wanna ensure this is always right + + entity panel = GetEntityFromEncodedEHandle( panelHandle ) + entity capturingPlayer = GetEntityFromEncodedEHandle( capturingPlayerHandle ) + + if ( capturingPlayer == GetLocalViewPlayer() ) + return + + string panelIdString + if ( id == 0 ) + panelIdString = "A" + if ( id == 1 ) + panelIdString = "B" + else if ( id == 2 ) + panelIdString = "C" + + AnnouncementData announcement = Announcement_Create( Localize( "#FASTBALL_PANEL_CAPTURED", capturingPlayer.GetPlayerName(), panelIdString ) ) + + if ( capturingPlayer.GetTeam() == GetLocalViewPlayer().GetTeam() ) + Announcement_SetTitleColor( announcement, < 0, 0, 1 > ) + else + Announcement_SetTitleColor( announcement, < 1, 0, 0 > ) + + Announcement_SetPurge( announcement, true ) + Announcement_SetPriority( announcement, 200 ) //Be higher priority than Titanfall ready indicator etc + Announcement_SetSoundAlias( announcement, SFX_HUD_ANNOUNCE_QUICK ) + Announcement_SetStyle( announcement, ANNOUNCEMENT_STYLE_QUICK ) + AnnouncementFromClass( GetLocalViewPlayer(), announcement ) +} + +void function ServerCallback_FastballRespawnPlayer() +{ + thread FastballRespawnPlayerEffects_Threaded() +} + +void function FastballRespawnPlayerEffects_Threaded() +{ + // sometimes this seems to get called before the player has respawned clientside, so we just wait until the client thinks they're alive + entity player = GetLocalViewPlayer() + + while ( !IsAlive( player ) ) + WaitFrame() + + StartParticleEffectOnEntity( player.GetCockpit(), GetParticleSystemIndex( $"P_pod_screen_lasers_OUT" ), FX_PATTACH_ABSORIGIN_FOLLOW, -1 ) +} \ No newline at end of file diff --git a/Northstar.Custom/mod/scripts/vscripts/gamemodes/cl_gamemode_gg.gnut b/Northstar.Custom/mod/scripts/vscripts/gamemodes/cl_gamemode_gg.gnut new file mode 100644 index 000000000..de8a34491 --- /dev/null +++ b/Northstar.Custom/mod/scripts/vscripts/gamemodes/cl_gamemode_gg.gnut @@ -0,0 +1,26 @@ +global function ClGamemodeGG_Init + +void function ClGamemodeGG_Init() +{ + // add ffa gamestate asset + ClGameState_RegisterGameStateAsset( $"ui/gamestate_info_ffa.rpak" ) + + // add music for mode, this is copied directly from the ffa/fra music registered in cl_music.gnut + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_INTRO, "music_mp_freeagents_intro", TEAM_IMC ) + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_INTRO, "music_mp_freeagents_intro", TEAM_MILITIA ) + + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_WIN, "music_mp_freeagents_outro_win", TEAM_IMC ) + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_WIN, "music_mp_freeagents_outro_win", TEAM_MILITIA ) + + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_DRAW, "music_mp_freeagents_outro_lose", TEAM_IMC ) + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_DRAW, "music_mp_freeagents_outro_lose", TEAM_MILITIA ) + + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_LOSS, "music_mp_freeagents_outro_lose", TEAM_IMC ) + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_LOSS, "music_mp_freeagents_outro_lose", TEAM_MILITIA ) + + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_THREE_MINUTE, "music_mp_freeagents_almostdone", TEAM_IMC ) + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_THREE_MINUTE, "music_mp_freeagents_almostdone", TEAM_MILITIA ) + + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_LAST_MINUTE, "music_mp_freeagents_lastminute", TEAM_IMC ) + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_LAST_MINUTE, "music_mp_freeagents_lastminute", TEAM_MILITIA ) +} \ No newline at end of file diff --git a/Northstar.Custom/mod/scripts/vscripts/gamemodes/cl_gamemode_inf.gnut b/Northstar.Custom/mod/scripts/vscripts/gamemodes/cl_gamemode_inf.gnut new file mode 100644 index 000000000..56763bd4a --- /dev/null +++ b/Northstar.Custom/mod/scripts/vscripts/gamemodes/cl_gamemode_inf.gnut @@ -0,0 +1,75 @@ +global function ClGamemodeInfection_Init +global function ServerCallback_YouAreInfected +global function ServerCallback_AnnounceFirstInfected +global function ServerCallback_AnnounceLastSurvivor + +void function ClGamemodeInfection_Init() +{ + //ClGameState_RegisterGameStateAsset( $"ui/gamestate_info_ffa.rpak" ) + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_INTRO, "music_beacon_8a_jumpingsuccess", TEAM_MILITIA ) + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_INTRO, "music_beacon_8a_jumpingsuccess", TEAM_IMC ) + RegisterLevelMusicForTeam( eMusicPieceID.GAMEMODE_1, "Music_Beacon_24_BTLob", TEAM_MILITIA ) + RegisterLevelMusicForTeam( eMusicPieceID.GAMEMODE_1, "Music_Beacon_24_BTLob", TEAM_IMC ) + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_LAST_MINUTE, "music_mp_titanwar_lastminute", TEAM_MILITIA ) + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_LAST_MINUTE, "music_mp_titanwar_lastminute", TEAM_IMC ) + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_WIN, "music_mp_freeagents_outro_lose", TEAM_MILITIA ) + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_WIN, "music_mp_freeagents_outro_lose", TEAM_IMC ) + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_DRAW, "music_mp_freeagents_outro_lose", TEAM_MILITIA ) + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_DRAW, "music_mp_freeagents_outro_lose", TEAM_IMC ) + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_LOSS, "music_mp_freeagents_outro_lose", TEAM_MILITIA ) + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_LOSS, "music_mp_freeagents_outro_lose", TEAM_IMC ) +} + +void function ServerCallback_YouAreInfected() +{ + // heavily based on mfd code + entity localPlayer = GetLocalViewPlayer() + + StartParticleEffectOnEntity( localPlayer.GetCockpit(), GetParticleSystemIndex( $"P_MFD" ), FX_PATTACH_ABSORIGIN_FOLLOW, -1 ) + EmitSoundOnEntity( localPlayer, "UI_InGame_MarkedForDeath_PlayerMarked" ) + HideEventNotification() + AnnouncementData announcement = Announcement_Create( "#INFECTION_YOU_ARE_INFECTED" ) + Announcement_SetSubText( announcement, "#INFECTION_KILL_SURVIVORS" ) + Announcement_SetTitleColor( announcement, <1,0,0> ) + Announcement_SetPurge( announcement, true ) + Announcement_SetPriority( announcement, 200 ) //Be higher priority than Titanfall ready indicator etc + Announcement_SetSoundAlias( announcement, SFX_HUD_ANNOUNCE_QUICK ) + Announcement_SetStyle( announcement, ANNOUNCEMENT_STYLE_QUICK ) + AnnouncementFromClass( localPlayer, announcement ) +} + +void function ServerCallback_AnnounceFirstInfected( int survivorEHandle ) +{ + entity player = GetEntityFromEncodedEHandle( survivorEHandle ) + + AnnouncementData announcement = Announcement_Create( Localize( "#INFECTION_FIRST_INFECTED", player.GetPlayerName() ) ) + //Announcement_SetSubText( announcement, "#INFECTION_KILL_LAST_SURVIVOR" ) + Announcement_SetTitleColor( announcement, <1,0,0> ) + Announcement_SetPurge( announcement, true ) + Announcement_SetPriority( announcement, 200 ) //Be higher priority than Titanfall ready indicator etc + Announcement_SetSoundAlias( announcement, SFX_HUD_ANNOUNCE_QUICK ) + Announcement_SetStyle( announcement, ANNOUNCEMENT_STYLE_QUICK ) + AnnouncementFromClass( GetLocalViewPlayer(), announcement ) +} + +void function ServerCallback_AnnounceLastSurvivor( int survivorEHandle ) +{ + entity player = GetEntityFromEncodedEHandle( survivorEHandle ) + + string announcementString = Localize( "#INFECTION_LAST_SURVIVOR", player.GetPlayerName() ) + string announcementSubString = "#INFECTION_KILL_LAST_SURVIVOR" + if ( player == GetLocalViewPlayer() ) + { + announcementString = "#INFECTION_YOU_ARE_LAST_SURVIVOR" + announcementSubString = "#INFECTION_SURVIVE_LAST_SURVIVOR" + } + + AnnouncementData announcement = Announcement_Create( announcementString ) + Announcement_SetSubText( announcement, announcementSubString ) + Announcement_SetTitleColor( announcement, <1,0,0> ) + Announcement_SetPurge( announcement, true ) + Announcement_SetPriority( announcement, 200 ) //Be higher priority than Titanfall ready indicator etc + Announcement_SetSoundAlias( announcement, SFX_HUD_ANNOUNCE_QUICK ) + Announcement_SetStyle( announcement, ANNOUNCEMENT_STYLE_QUICK ) + AnnouncementFromClass( GetLocalViewPlayer(), announcement ) +} \ No newline at end of file diff --git a/Northstar.Custom/mod/scripts/vscripts/gamemodes/cl_gamemode_kr.gnut b/Northstar.Custom/mod/scripts/vscripts/gamemodes/cl_gamemode_kr.gnut new file mode 100644 index 000000000..269057c79 --- /dev/null +++ b/Northstar.Custom/mod/scripts/vscripts/gamemodes/cl_gamemode_kr.gnut @@ -0,0 +1,241 @@ +global function ClGamemodeKR_Init + +global function ShowTimeGainOnKill +global function ServerCallback_FlagSpawnIncoming +global function ServerCallback_NewKillRacer +global function ServerCallback_EndKillrace + +struct { + var currentTimeRui + var currentTimeAdditionRui + var flagRui + var flagIncomingRui + var killRacerRui + + bool isCurrentlyInRace = false + float currentTimeAmount + float currentTimeLastAdditionTime + float currentTimeAdditionCombined +} file + +void function ClGamemodeKR_Init() +{ + // add ffa gamestate asset + ClGameState_RegisterGameStateAsset( $"ui/gamestate_info_ffa.rpak" ) + + // add music for mode, this is copied directly from the ffa/fra music registered in cl_music.gnut + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_INTRO, "music_mp_freeagents_intro", TEAM_IMC ) + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_INTRO, "music_mp_freeagents_intro", TEAM_MILITIA ) + + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_WIN, "music_mp_freeagents_outro_win", TEAM_IMC ) + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_WIN, "music_mp_freeagents_outro_win", TEAM_MILITIA ) + + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_DRAW, "music_mp_freeagents_outro_lose", TEAM_IMC ) + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_DRAW, "music_mp_freeagents_outro_lose", TEAM_MILITIA ) + + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_LOSS, "music_mp_freeagents_outro_lose", TEAM_IMC ) + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_LOSS, "music_mp_freeagents_outro_lose", TEAM_MILITIA ) + + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_THREE_MINUTE, "music_mp_freeagents_almostdone", TEAM_IMC ) + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_THREE_MINUTE, "music_mp_freeagents_almostdone", TEAM_MILITIA ) + + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_LAST_MINUTE, "music_mp_freeagents_lastminute", TEAM_IMC ) + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_LAST_MINUTE, "music_mp_freeagents_lastminute", TEAM_MILITIA ) + + AddCallback_OnClientScriptInit( CreateKRUI ) + AddCreateCallback( "item_flag", OnFlagCreated ) + AddDestroyCallback( "item_flag", OnFlagDestroyed ) +} + +void function CreateKRUI( entity player ) +{ + file.currentTimeRui = CreateCockpitRui( $"ui/titan_protocol_text_center.rpak", 200 ) + RuiSetInt( file.currentTimeRui, "lineNum", 1 ) + RuiSetGameTime( file.currentTimeRui, "startTime", 0.0 ) + UpdateCurrentTimeAmount() + + file.flagRui = CreateCockpitRui( $"ui/speedball_flag_marker.rpak", 200 ) + RuiSetBool( file.flagRui, "playerIsCarrying", false ) + RuiSetBool( file.flagRui, "isCarried", false ) + + file.killRacerRui = CreateCockpitRui( $"ui/mfd_target_marker.rpak", 200 ) + RuiSetBool( file.killRacerRui, "isVisible", false ) + RuiSetImage( file.killRacerRui, "markedIcon", $"rui/hud/gametype_icons/mfd/mfd_enemy" ) + RuiSetBool( file.killRacerRui, "isMarked", true ) +} + +void function OnFlagCreated( entity flag ) +{ + if ( IsValid( file.flagIncomingRui ) ) + RuiDestroy( file.flagIncomingRui ) + + RuiSetBool( file.flagRui, "isVisible", true ) + RuiTrackFloat3( file.flagRui, "pos", flag, RUI_TRACK_OVERHEAD_FOLLOW ) +} + +void function OnFlagDestroyed( entity flag ) +{ + RuiSetBool( file.flagRui, "isVisible", false ) +} + +void function ShowTimeGainOnKill( entity player, float oldVal, float newVal, bool actuallyChanged ) +{ + if ( file.isCurrentlyInRace || player != GetLocalViewPlayer() || !actuallyChanged ) + return + + if ( newVal > oldVal ) // time increase: likely given on kill + { + float amount = newVal - oldVal + + // show a combined number on the addition rui if last addition was recent enough + float additionShowAmount = amount + file.currentTimeAdditionCombined += amount + if ( Time() - file.currentTimeLastAdditionTime < 1.25 ) + amount = file.currentTimeAdditionCombined + else + { + file.currentTimeAdditionRui = CreateCockpitRui( $"ui/titan_protocol_text_center.rpak", 200 ) + RuiSetInt( file.currentTimeAdditionRui, "lineNum", 2 ) + file.currentTimeAdditionCombined = amount + } + + RuiSetString( file.currentTimeAdditionRui, "displayString", "+" + amount + "s 00ms " ) // formatted so that it lines up with other rui + RuiSetGameTime( file.currentTimeAdditionRui, "startTime", Time() ) + RuiSetGameTime( file.currentTimeAdditionRui, "endTime", Time() + 1.5 ) + + file.currentTimeLastAdditionTime = Time() + + thread UpdateFullTimeAmountAfterAdditionDone( file.currentTimeLastAdditionTime ) + } + else // time decrease either a reset or + UpdateCurrentTimeAmount() +} + +void function UpdateFullTimeAmountAfterAdditionDone( float previousAdditionTime ) +{ + wait 1.25 + + if ( previousAdditionTime == file.currentTimeLastAdditionTime ) // if not, there's been another addition since this was last updated and we'll wait for that instead + UpdateCurrentTimeAmount() +} + +void function UpdateCurrentTimeAmount( float overrideTime = -1 ) +{ + if ( overrideTime == -1 ) + file.currentTimeAmount = GetLocalViewPlayer().GetPlayerNetTime( "killRaceTime" ) + else + file.currentTimeAmount = overrideTime + + string currentTimeString + int seconds = file.currentTimeAmount.tointeger() + + string secondsString = seconds.tostring() + if ( secondsString.len() < 2 ) // pad to 2 chars + secondsString = "0" + secondsString + currentTimeString += secondsString + "s " + + string msString = ( ( file.currentTimeAmount - file.currentTimeAmount.tointeger() ) * 100 ).tostring() + if ( msString.len() < 2 ) // pad to 2 chars + msString = "0" + msString + currentTimeString += msString.slice( 0, 2 ) + "ms " + + RuiSetString( file.currentTimeRui, "displayString", currentTimeString ) + RuiSetGameTime( file.currentTimeRui, "endTime", Time() + 99999.0 ) // arbitrarily large number so this doesn't disappear +} + +void function ServerCallback_FlagSpawnIncoming( float x, float y, float z , float spawnTime ) +{ + print( "flagspawn: < " + x + ", " + y + ", " + z + " > in " + ( spawnTime - Time() ) + " seconds" ) + + AnnouncementData announcement = Announcement_Create( Localize( "#KR_FLAG_INCOMING", spawnTime.tostring() ) ) + Announcement_SetSubText( announcement, "#KR_COLLECT_FLAG" ) + Announcement_SetTitleColor( announcement, < 0, 0, 1 > ) + Announcement_SetPurge( announcement, true ) + Announcement_SetPriority( announcement, 200 ) + Announcement_SetSoundAlias( announcement, SFX_HUD_ANNOUNCE_QUICK ) + Announcement_SetStyle( announcement, ANNOUNCEMENT_STYLE_QUICK ) + AnnouncementFromClass( GetLocalViewPlayer(), announcement ) + + RuiSetFloat3( file.flagRui, "pos", < x, y, z > ) + RuiSetBool( file.flagRui, "isVisible", true ) + + file.flagIncomingRui = RuiCreate( $"ui/titanfall_timer.rpak", clGlobal.topoFullScreen, RUI_DRAW_HUD, 0 ) + RuiTrackFloat3( file.flagIncomingRui, "playerPos", GetLocalViewPlayer(), RUI_TRACK_ABSORIGIN_FOLLOW ) + RuiSetFloat3( file.flagIncomingRui, "pos", < x, y, z > + < 0, 0, 48 > ) + RuiSetGameTime( file.flagIncomingRui, "impactTime", spawnTime ) +} + +void function ServerCallback_NewKillRacer( int playerHandle, float endTime ) +{ + entity player = GetEntityFromEncodedEHandle( playerHandle ) + + string announcementMessage = Localize( "#KR_NEW_RACER", player.GetPlayerName() ) + string announcementSubMessage + if ( player == GetLocalViewPlayer() ) + { + file.isCurrentlyInRace = true + thread LerpTimeDuringRace( endTime ) + + StartParticleEffectOnEntity( player.GetCockpit(), GetParticleSystemIndex( $"P_MFD" ), FX_PATTACH_ABSORIGIN_FOLLOW, -1 ) + EmitSoundOnEntity( player, "UI_InGame_MarkedForDeath_PlayerMarked" ) + HideEventNotification() + + announcementMessage = "#KR_YOU_ARE_NEW_RACER" + announcementSubMessage = "#KR_YOU_SET_NEW_RECORD" + } + else + { + // mark the player + RuiTrackFloat3( file.killRacerRui, "pos", player, RUI_TRACK_OVERHEAD_FOLLOW ) + RuiSetBool( file.killRacerRui, "isVisible", true ) + } + + AnnouncementData announcement = Announcement_Create( announcementMessage ) + Announcement_SetSubText( announcement, announcementSubMessage ) + Announcement_SetTitleColor( announcement, < 1, 0, 0 > ) + Announcement_SetPurge( announcement, true ) + Announcement_SetPriority( announcement, 200 ) + Announcement_SetSoundAlias( announcement, SFX_HUD_ANNOUNCE_QUICK ) + Announcement_SetStyle( announcement, ANNOUNCEMENT_STYLE_QUICK ) + AnnouncementFromClass( GetLocalViewPlayer(), announcement ) +} + +void function LerpTimeDuringRace( float endTime ) +{ + while ( Time() < endTime ) + { + // manually update this here so we can get more frequent updates than what we'd get with networked vars + UpdateCurrentTimeAmount( endTime - Time() ) + WaitFrame() + } + + UpdateCurrentTimeAmount( 0.0 ) + file.isCurrentlyInRace = false +} + +void function ServerCallback_EndKillrace( int playerHandle, int score ) +{ + entity player = GetEntityFromEncodedEHandle( playerHandle ) + + vector colour = < 0, 0, 1 > + string announcementMessage = Localize( "#KR_ENEMY_KILLRACE_OVER", player.GetPlayerName() ) + string announcementSubMessage + if ( player == GetLocalViewPlayer() ) + { + StartParticleEffectOnEntity( GetLocalViewPlayer().GetCockpit(), GetParticleSystemIndex( $"P_MFD_unmark" ), FX_PATTACH_ABSORIGIN_FOLLOW, -1 ) + colour = < 1, 0, 0 > + announcementMessage = "#KR_YOUR_KILLRACE_OVER" + announcementSubMessage = Localize( "#KR_YOUR_KILLRACE_SCORE", score ) + } + + AnnouncementData announcement = Announcement_Create( announcementMessage ) + Announcement_SetSubText( announcement, announcementSubMessage ) + Announcement_SetTitleColor( announcement, colour ) + Announcement_SetPurge( announcement, true ) + Announcement_SetPriority( announcement, 200 ) + Announcement_SetSoundAlias( announcement, SFX_HUD_ANNOUNCE_QUICK ) + Announcement_SetStyle( announcement, ANNOUNCEMENT_STYLE_QUICK ) + AnnouncementFromClass( GetLocalViewPlayer(), announcement ) + + RuiSetBool( file.killRacerRui, "isVisible", false ) +} \ No newline at end of file diff --git a/Northstar.Custom/mod/scripts/vscripts/gamemodes/cl_gamemode_tt.gnut b/Northstar.Custom/mod/scripts/vscripts/gamemodes/cl_gamemode_tt.gnut new file mode 100644 index 000000000..b73ed9587 --- /dev/null +++ b/Northstar.Custom/mod/scripts/vscripts/gamemodes/cl_gamemode_tt.gnut @@ -0,0 +1,26 @@ +global function ClGamemodeTT_Init + +void function ClGamemodeTT_Init() +{ + // register gamestate asset, this is default so not necessary but doing it anyway + ClGameState_RegisterGameStateAsset( $"ui/gamestate_info_ps.rpak" ) + + // add music for mode, this is copied directly from the attrition/tdm music registered in cl_music.gnut + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_INTRO, "music_mp_pilothunt_intro_flyin", TEAM_IMC ) + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_INTRO, "music_mp_pilothunt_intro_flyin", TEAM_MILITIA ) + + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_WIN, "music_mp_pilothunt_epilogue_win", TEAM_IMC ) + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_WIN, "music_mp_pilothunt_epilogue_win", TEAM_MILITIA ) + + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_DRAW, "music_mp_pilothunt_epilogue_win", TEAM_IMC ) + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_DRAW, "music_mp_pilothunt_epilogue_win", TEAM_MILITIA ) + + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_LOSS, "music_mp_pilothunt_epilogue_lose", TEAM_IMC ) + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_LOSS, "music_mp_pilothunt_epilogue_lose", TEAM_MILITIA ) + + RegisterLevelMusicForTeam( eMusicPieceID.GAMEMODE_1, "music_mp_pilothunt_almostdone", TEAM_IMC ) + RegisterLevelMusicForTeam( eMusicPieceID.GAMEMODE_1, "music_mp_pilothunt_almostdone", TEAM_MILITIA ) + + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_LAST_MINUTE, "music_mp_pilothunt_lastminute", TEAM_IMC ) + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_LAST_MINUTE, "music_mp_pilothunt_lastminute", TEAM_MILITIA ) +} \ No newline at end of file diff --git a/Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_arena_loadouts.gnut b/Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_arena_loadouts.gnut new file mode 100644 index 000000000..ae0fa7d68 --- /dev/null +++ b/Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_arena_loadouts.gnut @@ -0,0 +1,98 @@ +// the purpose of this script is basically just to provide methods that are used in modified burnmeter and boost_store scripts to get custom items to work + +global function InitialiseArenaLoadouts +global function PopulateArenaLoadouts +global function GetArenaLoadoutForRoundCount +global function GetArenaLoadoutItemAsBurnReward +global function GetCashBoostForRoundCount + +#if SERVER + global function GivePlayerArenaLoadoutItem +#endif + +const int ABILITY_ROUND = 2 +const int CRATE_ROUND = 4 +const int TITAN_ROUND = 7 + +struct { + array tier0Weapons + array tier1Weapons + array antiTitanWeapons + + BoostStoreData droppodRespawn + BoostStoreData titanBattery + BoostStoreData titanfall +} file + +void function InitialiseArenaLoadouts() +{ + BoostStoreData g2Data = { itemRef="mp_weapon_g2", modesAllowed="arena", cost=75, ... } + file.tier0Weapons.append( g2Data ) + + BoostStoreData flatlineData = { itemRef="mp_weapon_vinson", modesAllowed="arena", cost=125, ... } + file.tier0Weapons.append( flatlineData ) + + BoostStoreData wingmanData = { itemRef="mp_weapon_wingman", modesAllowed="arena", cost=50, ... } + file.tier0Weapons.append( wingmanData ) + + BoostStoreData respawnData = { itemRef="droppodRespawn", modesAllowed="arena", cost=50, ... } + file.tier0Weapons.append( respawnData ) + + #if SERVER + SetBoostPurchaseCallback( GivePlayerArenaLoadoutItem ) + #endif +} + +array function PopulateArenaLoadouts() +{ + return GetArenaLoadoutForRoundCount( 0 ) +} + +array function GetArenaLoadoutForRoundCount( int round ) +{ + return file.tier0Weapons +} + +BurnReward function GetArenaLoadoutItemAsBurnReward( string itemRef ) +{ + BurnReward reward + reward.ref = itemRef + reward.localizedName = itemRef + + return reward +} + +bool function ArenaLoadoutItemIsWeapon( string item ) +{ + if ( item.find( "mp_weapon" ) == 0 ) + return true + + return false +} + +int function GetCashBoostForRoundCount( int round ) +{ + if ( round == 0 ) + return 150 + + if ( round < 4 ) + return 250 + + return 350 +} + +#if SERVER + void function GivePlayerArenaLoadoutItem( entity player, BoostStoreData item ) + { + if ( ArenaLoadoutItemIsWeapon( item.itemRef ) ) + { + array mods + // apply mods + //if ( item.itemRef = "mp_weapon_wingman" ) + + player.GiveWeapon( item.itemRef, mods ) + player.SetActiveWeaponByName( item.itemRef ) + return + } + } +#endif \ No newline at end of file diff --git a/Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_gamemode_arena.gnut b/Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_gamemode_arena.gnut new file mode 100644 index 000000000..b634f1d38 --- /dev/null +++ b/Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_gamemode_arena.gnut @@ -0,0 +1,58 @@ +global function Sh_GamemodeArena_Init + +global const string GAMEMODE_ARENA = "arena" + +void function Sh_GamemodeArena_Init() +{ + // create custom gamemode + AddCallback_OnCustomGamemodesInit( CreateGamemodeArena ) + AddCallback_OnRegisteringCustomNetworkVars( ArenaRegisterNetworkVars ) +} + +void function CreateGamemodeArena() +{ + GameMode_Create( GAMEMODE_ARENA ) + GameMode_SetName( GAMEMODE_ARENA, "#GAMEMODE_arena" ) + GameMode_SetDesc( GAMEMODE_ARENA, "#PL_arena_desc" ) + GameMode_SetGameModeAnnouncement( GAMEMODE_ARENA, "gnrc_modeDesc" ) + GameMode_SetDefaultTimeLimits( GAMEMODE_ARENA, 5, 0.0 ) + GameMode_AddScoreboardColumnData( GAMEMODE_ARENA, "#SCOREBOARD_PILOT_KILLS", PGS_PILOT_KILLS, 2 ) + GameMode_SetColor( GAMEMODE_ARENA, [147, 204, 57, 255] ) + + #if SERVER + GameMode_AddServerInit( GAMEMODE_ARENA, GameModeArena_Init ) + GameMode_SetPilotSpawnpointsRatingFunc( GAMEMODE_ARENA, RateSpawnpoints_Generic ) + GameMode_SetTitanSpawnpointsRatingFunc( GAMEMODE_ARENA, RateSpawnpoints_Generic ) + #elseif CLIENT + GameMode_AddClientInit( GAMEMODE_ARENA, ClGameModeArena_Init ) + #endif + #if !UI + GameMode_SetScoreCompareFunc( GAMEMODE_ARENA, CompareAssaultScore ) + #endif +} + +void function ArenaRegisterNetworkVars() +{ + if ( GAMETYPE != GAMEMODE_ARENA ) + return + + // boost store stuff + Remote_RegisterFunction( "ServerCallback_OpenBoostStore" ) + Remote_RegisterFunction( "ServerCallback_UpdateMoney" ) + Remote_RegisterFunction( "ServerCallback_UpdateTeamReserve" ) + Remote_RegisterFunction( "ServerCallback_UpdatePlayerHasBattery" ) + Remote_RegisterFunction( "ServerCallback_UpdateAmpedWeaponState" ) + Remote_RegisterFunction( "ServerCallback_BoostStoreTitanHint" ) + Remote_RegisterFunction( "ServerCallback_UpdateTurretCount" ) + + RegisterNetworkedVariable( "boostStoreOpen", SNDC_GLOBAL, SNVT_BOOL, false ) + RegisterNetworkedVariable( "FD_money", SNDC_PLAYER_GLOBAL, SNVT_UNSIGNED_INT, 0 ) + RegisterNetworkedVariable( "FD_money256", SNDC_PLAYER_GLOBAL, SNVT_UNSIGNED_INT, 0 ) + + // these are required to prevent crashes in fd code that's called from menu_boost_store + RegisterNetworkedVariable( "numSuperRodeoGrenades", SNDC_PLAYER_GLOBAL, SNVT_INT, 0 ) + RegisterNetworkedVariable( "FD_waveActive", SNDC_GLOBAL, SNVT_BOOL, false ) + + // arena-exclusive stuff + Remote_RegisterFunction( "ServerCallback_CreateMoneyParticles" ) +} \ No newline at end of file diff --git a/Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_gamemode_bomb.gnut b/Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_gamemode_bomb.gnut new file mode 100644 index 000000000..e69de29bb diff --git a/Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_gamemode_ctf_comp.gnut b/Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_gamemode_ctf_comp.gnut new file mode 100644 index 000000000..1a1ce6451 --- /dev/null +++ b/Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_gamemode_ctf_comp.gnut @@ -0,0 +1,114 @@ +global function ShGamemodeCTFComp_Init + +global const string GAMEMODE_CTF_COMP = "ctf_comp" + +void function ShGamemodeCTFComp_Init() +{ + // create custom gamemode + AddCallback_OnCustomGamemodesInit( CreateGamemodeCTFComp ) + AddCallback_OnRegisteringCustomNetworkVars( CTFCompRegisterNetworkVars ) +} + +void function CreateGamemodeCTFComp() +{ + GameMode_Create( GAMEMODE_CTF_COMP ) + GameMode_SetName( GAMEMODE_CTF_COMP, "#GAMEMODE_ctf_comp" ) + GameMode_SetGameModeAnnouncement( GAMEMODE_CTF_COMP, "ctf_modeDesc" ) + GameMode_SetDesc( GAMEMODE_CTF_COMP, "#PL_capture_the_flag_hint" ) + GameMode_SetIcon( GAMEMODE_CTF_COMP, $"ui/menu/playlist/ctf" ) + GameMode_SetSuddenDeath( GAMEMODE_CTF_COMP, true ) + GameMode_SetDefaultScoreLimits( GAMEMODE_CTF_COMP, 0, 5 ) + GameMode_SetDefaultTimeLimits( GAMEMODE_CTF_COMP, 0, 3.0 ) + GameMode_AddScoreboardColumnData( GAMEMODE_CTF_COMP, "#SCOREBOARD_CAPTURES", PGS_ASSAULT_SCORE, 2 ) + GameMode_AddScoreboardColumnData( GAMEMODE_CTF_COMP, "#SCOREBOARD_RETURNS", PGS_DEFENSE_SCORE, 2 ) + GameMode_AddScoreboardColumnData( GAMEMODE_CTF_COMP, "#SCOREBOARD_KILLS", PGS_KILLS, 2 ) + GameMode_AddScoreboardColumnData( GAMEMODE_CTF_COMP, "#SCOREBOARD_TITAN_DAMAGE", PGS_DISTANCE_SCORE, 6 ) // gotta use a weird pgs here since we're running out of them lol + GameMode_SetColor( GAMEMODE_CTF_COMP, [61, 117, 193, 255] ) + + AddPrivateMatchMode( GAMEMODE_CTF_COMP ) // add to private lobby modes + + // this gamemode is literally just normal ctf + a few extra settings + // as such we do all the inits in this file, not enough logic to be worth splitting it up + + #if SERVER + GameMode_AddServerInit( GAMEMODE_CTF_COMP, InitCTFCompSpecificSettings ) + GameMode_AddServerInit( GAMEMODE_CTF_COMP, CaptureTheFlag_Init ) + GameMode_SetPilotSpawnpointsRatingFunc( GAMEMODE_CTF_COMP, RateSpawnpoints_CTF ) + GameMode_SetTitanSpawnpointsRatingFunc( GAMEMODE_CTF_COMP, RateSpawnpoints_CTF ) + #elseif CLIENT + GameMode_AddClientInit( GAMEMODE_CTF_COMP, InitCTFCompSpecificSettings ) + GameMode_AddClientInit( GAMEMODE_CTF_COMP, ClCaptureTheFlag_Init ) + #endif + #if !UI + GameMode_SetScoreCompareFunc( GAMEMODE_CTF_COMP, CompareCTF ) + GameMode_AddSharedInit( GAMEMODE_CTF_COMP, GamemodeCtfDialogue_Init ) + GameMode_AddSharedInit( GAMEMODE_CTF_COMP, CaptureTheFlagShared_Init ) + #endif +} + +void function CTFCompRegisterNetworkVars() +{ + if ( GAMETYPE != GAMEMODE_CTF_COMP ) + return + + // copied from the vanilla ctf remote functions + RegisterNetworkedVariable( "imcFlag", SNDC_GLOBAL, SNVT_ENTITY ) + RegisterNetworkedVariable( "milFlag", SNDC_GLOBAL, SNVT_ENTITY ) + + RegisterNetworkedVariable( "imcFlagHome", SNDC_GLOBAL, SNVT_ENTITY ) + RegisterNetworkedVariable( "milFlagHome", SNDC_GLOBAL, SNVT_ENTITY ) + + RegisterNetworkedVariable( "imcFlagState", SNDC_GLOBAL, SNVT_INT, 0 ) + RegisterNetworkedVariable( "milFlagState", SNDC_GLOBAL, SNVT_INT, 0 ) + + RegisterNetworkedVariable( "flagReturnProgress", SNDC_GLOBAL, SNVT_FLOAT_RANGE_OVER_TIME, 0.0, 0.0, 1.0 ) + RegisterNetworkedVariable( "returningFlag", SNDC_PLAYER_EXCLUSIVE, SNVT_BOOL, false ) + + Remote_RegisterFunction( "ServerCallback_CTF_PlayMatchNearEndMusic" ) + Remote_RegisterFunction( "ServerCallback_CTF_StartReturnFlagProgressBar" ) + Remote_RegisterFunction( "ServerCallback_CTF_StopReturnFlagProgressBar" ) + + #if CLIENT + CLCaptureTheFlag_RegisterNetworkFunctions() + #endif +} + +void function InitCTFCompSpecificSettings() +{ + #if SERVER + SetShouldUsePickLoadoutScreen( true ) + TrackTitanDamageInPlayerGameStat( PGS_DISTANCE_SCORE ) + SetSpawnpointGamemodeOverride( CAPTURE_THE_FLAG ) + TeamTitanSelectMenu_Init() + #elseif CLIENT + ClTeamTitanSelectMenu_Init() + + // gotta register the music here because this is done hardcoded to ctf in cl_music + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_INTRO, "music_mp_ctf_intro_flyin", TEAM_IMC ) + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_INTRO, "music_mp_ctf_intro_flyin", TEAM_MILITIA ) + + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_WIN, "music_mp_ctf_epilogue_win", TEAM_IMC ) + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_WIN, "music_mp_ctf_epilogue_win", TEAM_MILITIA ) + + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_DRAW, "music_mp_ctf_halftime_losing", TEAM_IMC ) + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_DRAW, "music_mp_ctf_halftime_losing", TEAM_MILITIA ) + + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_SUDDEN_DEATH, "music_mp_ctf_draw", TEAM_IMC ) + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_SUDDEN_DEATH, "music_mp_ctf_draw", TEAM_MILITIA ) + + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_LOSS, "music_mp_ctf_epilogue_lose", TEAM_IMC ) + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_LOSS, "music_mp_ctf_epilogue_lose", TEAM_MILITIA ) + + RegisterLevelMusicForTeam( eMusicPieceID.ROUND_BASED_GAME_WON, "music_mp_ctf_halftime_winning", TEAM_IMC ) + RegisterLevelMusicForTeam( eMusicPieceID.ROUND_BASED_GAME_WON, "music_mp_ctf_halftime_winning", TEAM_MILITIA ) + + RegisterLevelMusicForTeam( eMusicPieceID.ROUND_BASED_GAME_LOST, "music_mp_ctf_halftime_losing", TEAM_IMC ) + RegisterLevelMusicForTeam( eMusicPieceID.ROUND_BASED_GAME_LOST, "music_mp_ctf_halftime_losing", TEAM_MILITIA ) + + RegisterLevelMusicForTeam( eMusicPieceID.GAMEMODE_1, "music_mp_ctf_flag_4", TEAM_IMC ) + RegisterLevelMusicForTeam( eMusicPieceID.GAMEMODE_1, "music_mp_ctf_flag_4", TEAM_MILITIA ) + + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_LAST_MINUTE, "music_mp_ctf_lastminute", TEAM_IMC ) + RegisterLevelMusicForTeam( eMusicPieceID.LEVEL_LAST_MINUTE, "music_mp_ctf_lastminute", TEAM_MILITIA ) + #endif +} \ No newline at end of file diff --git a/Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_gamemode_fastball.gnut b/Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_gamemode_fastball.gnut new file mode 100644 index 000000000..2462d5376 --- /dev/null +++ b/Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_gamemode_fastball.gnut @@ -0,0 +1,47 @@ +global function Sh_GamemodeFastball_Init + +global const string GAMEMODE_FASTBALL = "fastball" + +void function Sh_GamemodeFastball_Init() +{ + // create custom gamemode + AddCallback_OnCustomGamemodesInit( CreateGamemodeFastball ) + AddCallback_OnRegisteringCustomNetworkVars( FastballRegisterNetworkVars ) +} + +void function CreateGamemodeFastball() +{ + GameMode_Create( GAMEMODE_FASTBALL ) + GameMode_SetName( GAMEMODE_FASTBALL, "#GAMEMODE_FASTBALL" ) + GameMode_SetDesc( GAMEMODE_FASTBALL, "#PL_fastball_desc" ) + GameMode_SetGameModeAnnouncement( GAMEMODE_FASTBALL, "grnc_modeDesc" ) + GameMode_SetDefaultTimeLimits( GAMEMODE_FASTBALL, 1, 0 ) + GameMode_SetDefaultScoreLimits( GAMEMODE_FASTBALL, 5, 0 ) + GameMode_AddScoreboardColumnData( GAMEMODE_FASTBALL, "#SCOREBOARD_FASTBALL_HACKS", PGS_ASSAULT_SCORE, 2 ) + GameMode_AddScoreboardColumnData( GAMEMODE_FASTBALL, "#SCOREBOARD_PILOT_KILLS", PGS_PILOT_KILLS, 2 ) + GameMode_AddScoreboardColumnData( GAMEMODE_FASTBALL, "#SCOREBOARD_DEATHS", PGS_DEATHS, 2 ) + GameMode_SetColor( GAMEMODE_FASTBALL, [147, 204, 57, 255] ) + + AddPrivateMatchMode( GAMEMODE_FASTBALL ) // add to private lobby modes + + #if SERVER + GameMode_AddServerInit( GAMEMODE_FASTBALL, GamemodeFastball_Init ) + GameMode_SetPilotSpawnpointsRatingFunc( GAMEMODE_FASTBALL, RateSpawnpoints_Generic ) + GameMode_SetTitanSpawnpointsRatingFunc( GAMEMODE_FASTBALL, RateSpawnpoints_Generic ) + #elseif CLIENT + GameMode_AddClientInit( GAMEMODE_FASTBALL, ClGamemodeFastball_Init ) + #endif + #if !UI + GameMode_SetScoreCompareFunc( GAMEMODE_FASTBALL, CompareAssaultScore ) + #endif +} + +void function FastballRegisterNetworkVars() +{ + if ( GAMETYPE != GAMEMODE_FASTBALL ) + return + + Remote_RegisterFunction( "ServerCallback_FastballUpdatePanelRui" ) + Remote_RegisterFunction( "ServerCallback_FastballPanelHacked" ) + Remote_RegisterFunction( "ServerCallback_FastballRespawnPlayer" ) +} \ No newline at end of file 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 new file mode 100644 index 000000000..8c6e3f635 --- /dev/null +++ b/Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_gamemode_fw_custom.nut @@ -0,0 +1,73 @@ +// this script only exists to create the fw gamemode +// all client/shared gamelogic is still done in the gamemode's respective client and shared scripts +// these scripts are shipped with the game's official build so no need to recreate these +// their paths are gamemodes/cl_gamemode_fw.nut and gamemodes/sh_gamemode_fw.nut, respectively + +global function SHCreateGamemodeFW_Init + +void function SHCreateGamemodeFW_Init() +{ + AddCallback_OnCustomGamemodesInit( CreateGamemodeFW ) + AddCallback_OnRegisteringCustomNetworkVars( FWOnRegisteringNetworkVars ) +} + +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 + + GameMode_Create( FORT_WAR ) + GameMode_SetName( FORT_WAR, "#GAMEMODE_fw" ) + GameMode_SetDesc( FORT_WAR, "#PL_fw_desc" ) + GameMode_SetGameModeAnnouncement( FORT_WAR, "ffa_modeDesc" ) // fw lines are unfortunately not registered to faction dialogue + + #if SERVER + //GameMode_AddServerInit( FORT_WAR, GamemodeFW_Init ) // doesn't exist yet lol + #elseif CLIENT + GameMode_AddClientInit( FORT_WAR, CLGamemodeFW_Init ) + #endif + #if !UI + GameMode_AddSharedInit( FORT_WAR, SHGamemodeFW_Init ) + #endif +} + +void function FWOnRegisteringNetworkVars() +{ + if ( GAMETYPE != FORT_WAR ) + return + + RegisterNetworkedVariable( "turretSite1", SNDC_GLOBAL, SNVT_ENTITY ) + RegisterNetworkedVariable( "turretSite2", SNDC_GLOBAL, SNVT_ENTITY ) + RegisterNetworkedVariable( "turretSite3", SNDC_GLOBAL, SNVT_ENTITY ) + RegisterNetworkedVariable( "turretSite4", SNDC_GLOBAL, SNVT_ENTITY ) + RegisterNetworkedVariable( "turretSite5", SNDC_GLOBAL, SNVT_ENTITY ) + RegisterNetworkedVariable( "turretSite6", SNDC_GLOBAL, SNVT_ENTITY ) + RegisterNetworkedVariable( "turretSite7", SNDC_GLOBAL, SNVT_ENTITY ) + RegisterNetworkedVariable( "turretSite8", SNDC_GLOBAL, SNVT_ENTITY ) + RegisterNetworkedVariable( "turretSite9", SNDC_GLOBAL, SNVT_ENTITY ) + + RegisterNetworkedVariable( "turretStateFlags1", SNDC_GLOBAL, SNVT_INT ) + RegisterNetworkedVariable( "turretStateFlags2", SNDC_GLOBAL, SNVT_INT ) + RegisterNetworkedVariable( "turretStateFlags3", SNDC_GLOBAL, SNVT_INT ) + RegisterNetworkedVariable( "turretStateFlags4", SNDC_GLOBAL, SNVT_INT ) + RegisterNetworkedVariable( "turretStateFlags5", SNDC_GLOBAL, SNVT_INT ) + RegisterNetworkedVariable( "turretStateFlags6", SNDC_GLOBAL, SNVT_INT ) + RegisterNetworkedVariable( "turretStateFlags7", SNDC_GLOBAL, SNVT_INT ) + RegisterNetworkedVariable( "turretStateFlags8", SNDC_GLOBAL, SNVT_INT ) + RegisterNetworkedVariable( "turretStateFlags9", SNDC_GLOBAL, SNVT_INT ) + + RegisterNetworkedVariable( "imcTowerThreatLevel", SNDC_GLOBAL, SNVT_INT ) + RegisterNetworkedVariable( "milTowerThreatLevel", SNDC_GLOBAL, SNVT_INT ) + RegisterNetworkedVariable( "fwCampAlertA", SNDC_GLOBAL, SNVT_INT ) + RegisterNetworkedVariable( "fwCampStressA", SNDC_GLOBAL, SNVT_INT ) + RegisterNetworkedVariable( "fwCampAlertB", SNDC_GLOBAL, SNVT_INT ) + RegisterNetworkedVariable( "fwCampStressB", SNDC_GLOBAL, SNVT_INT ) + RegisterNetworkedVariable( "fwCampAlertC", SNDC_GLOBAL, SNVT_INT ) + RegisterNetworkedVariable( "fwCampStressC", SNDC_GLOBAL, SNVT_INT ) + + #if CLIENT + CLFortWar_RegisterNetworkFunctions() + #endif +} \ No newline at end of file diff --git a/Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_gamemode_gg.gnut b/Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_gamemode_gg.gnut new file mode 100644 index 000000000..c4021a3cc --- /dev/null +++ b/Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_gamemode_gg.gnut @@ -0,0 +1,165 @@ +global function Sh_GamemodeGG_Init +global function GetGunGameWeapons + +global const string GAMEMODE_GG = "gg" + +global struct GunGameWeapon +{ + string weapon + array mods + int offhandSlot = -1 +} + +struct { + array weapons +} file + +void function Sh_GamemodeGG_Init() +{ + // create custom gamemode + AddCallback_OnCustomGamemodesInit( CreateGamemodeGG ) +} + +void function CreateGamemodeGG() +{ + GameMode_Create( GAMEMODE_GG ) + GameMode_SetName( GAMEMODE_GG, "#GAMEMODE_GG" ) + GameMode_SetDesc( GAMEMODE_GG, "#PL_gg_desc" ) + GameMode_SetGameModeAnnouncement( GAMEMODE_GG, "ffa_modeDesc" ) + GameMode_SetDefaultTimeLimits( GAMEMODE_GG, 10, 0.0 ) + GameMode_AddScoreboardColumnData( GAMEMODE_GG, "#SCOREBOARD_SCORE", PGS_ASSAULT_SCORE, 2 ) + GameMode_AddScoreboardColumnData( GAMEMODE_GG, "#SCOREBOARD_PILOT_KILLS", PGS_PILOT_KILLS, 2 ) + GameMode_SetColor( GAMEMODE_GG, [147, 204, 57, 255] ) + + AddPrivateMatchMode( GAMEMODE_GG ) // add to private lobby modes + + // setup guns + + // smgs + // car + GunGameWeapon ggCar = { weapon = "mp_weapon_car", mods = [ "pas_run_and_gun" ], ... } + file.weapons.append( ggCar ) + + // alternator + GunGameWeapon ggAlternator = { weapon = "mp_weapon_alternator_smg", mods = [ "pas_run_and_gun" ], ... } + file.weapons.append( ggAlternator ) + + // volt + GunGameWeapon ggVolt = { weapon = "mp_weapon_hemlok_smg", ... } + file.weapons.append( ggVolt ) + + + // rifles + // hemlok + GunGameWeapon ggHemlok = { weapon = "mp_weapon_hemlok", mods = [ ], ... } + file.weapons.append( ggHemlok ) + + // flatline + GunGameWeapon ggFlatline = { weapon = "mp_weapon_vinson", mods = [ "hcog" ], ... } + file.weapons.append( ggFlatline ) + + // r201 + GunGameWeapon ggR101 = { weapon = "mp_weapon_rspn101", ... } + file.weapons.append( ggR101 ) + + + // lmgs + // devotion + GunGameWeapon ggDevotion = { weapon = "mp_weapon_esaw", ... } + file.weapons.append( ggDevotion ) + + // l-star + GunGameWeapon ggLstar = { weapon = "mp_weapon_lstar", mods = [ "pas_run_and_gun" ], ... } + if ( RandomInt( 100 ) <= 5 ) + ggLstar.mods.append( "rcee" ) // easter egg mod that changes the screen of the lstar + + file.weapons.append( ggLstar ) + + + // shotguns + // eva-8 + GunGameWeapon ggEva = { weapon = "mp_weapon_shotgun", ... } + file.weapons.append( ggEva ) + + // mastiff + GunGameWeapon ggMastiff = { weapon = "mp_weapon_mastiff", ... } + file.weapons.append( ggMastiff ) + + + // grenadiers + // softball + GunGameWeapon ggSoftball = { weapon = "mp_weapon_softball", ... } + file.weapons.append( ggSoftball ) + + // epg + GunGameWeapon ggEpg = { weapon = "mp_weapon_epg", mods = [ "jump_kit" ], ... } + file.weapons.append( ggEpg ) + + + // primary pistols + // mozambique + GunGameWeapon ggMozam = { weapon = "mp_weapon_shotgun_pistol", mods = [ "pas_run_and_gun" ], ... } + file.weapons.append( ggMozam ) + + // wingman elite + GunGameWeapon ggWme = { weapon = "mp_weapon_wingman_n", mods = [ "pas_run_and_gun", "ricochet" ], ... } + file.weapons.append( ggWme ) + + + // snipers + // double take + GunGameWeapon ggTaketake = { weapon = "mp_weapon_doubletake", ... } + file.weapons.append( ggTaketake ) + + // kraber + GunGameWeapon ggKraber = { weapon = "mp_weapon_sniper", mods = [ "pas_fast_ads", "ricochet" ], ... } + file.weapons.append( ggKraber ) + + + // secondary pistols + // re-45 + GunGameWeapon ggRe45 = { weapon = "mp_weapon_autopistol", mods = [ "pas_run_and_gun", "temp_sight" ], ... } + file.weapons.append( ggRe45 ) + + // p2016 + GunGameWeapon ggP2016 = { weapon = "mp_weapon_semipistol", mods = [ "pas_run_and_gun" ], ... } + file.weapons.append( ggP2016 ) + + // wingman + GunGameWeapon ggWingman = { weapon = "mp_weapon_wingman", mods = [ "pas_run_and_gun" ], ... } + file.weapons.append( ggWingman ) + + + // final/special weapons + // charge rifle + GunGameWeapon ggChargeRifle = { weapon = "mp_weapon_defender", ... } + file.weapons.append( ggChargeRifle ) + + // pulse blade + GunGameWeapon ggPulseBlade = { weapon = "mp_weapon_grenade_sonar", mods = [ "pas_power_cell", "amped_tacticals" ], offhandSlot = 0 } + file.weapons.append( ggPulseBlade ) + + + // set this to the number of guns + GameMode_SetDefaultScoreLimits( GAMEMODE_GG, file.weapons.len(), 0 ) + + #if SERVER + GameMode_AddServerInit( GAMEMODE_GG, GamemodeGG_Init ) + GameMode_AddServerInit( GAMEMODE_GG, GamemodeFFAShared_Init ) + GameMode_SetPilotSpawnpointsRatingFunc( GAMEMODE_GG, RateSpawnpoints_Generic ) + GameMode_SetTitanSpawnpointsRatingFunc( GAMEMODE_GG, RateSpawnpoints_Generic ) + #elseif CLIENT + GameMode_AddClientInit( GAMEMODE_GG, ClGamemodeGG_Init ) + GameMode_AddClientInit( GAMEMODE_GG, GamemodeFFAShared_Init ) + GameMode_AddClientInit( GAMEMODE_GG, ClGamemodeFFA_Init ) + #endif + #if !UI + GameMode_SetScoreCompareFunc( GAMEMODE_GG, CompareAssaultScore ) + GameMode_AddSharedInit( GAMEMODE_GG, GamemodeFFA_Dialogue_Init ) + #endif +} + +array function GetGunGameWeapons() +{ + return file.weapons +} \ No newline at end of file diff --git a/Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_gamemode_inf.gnut b/Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_gamemode_inf.gnut new file mode 100644 index 000000000..bcd863786 --- /dev/null +++ b/Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_gamemode_inf.gnut @@ -0,0 +1,58 @@ +global function Sh_GamemodeInfection_Init + +global const string GAMEMODE_INFECTION = "inf" +global const int INFECTION_TEAM_SURVIVOR = TEAM_MILITIA +global const int INFECTION_TEAM_INFECTED = TEAM_IMC + +void function Sh_GamemodeInfection_Init() +{ + // create custom gamemode + AddCallback_OnCustomGamemodesInit( CreateGamemodeInfection ) + AddCallback_OnRegisteringCustomNetworkVars( InfectionRegisterNetworkVars ) +} + +void function CreateGamemodeInfection() +{ + GameMode_Create( GAMEMODE_INFECTION ) + GameMode_SetName( GAMEMODE_INFECTION, "#GAMEMODE_inf" ) + GameMode_SetDesc( GAMEMODE_INFECTION, "#PL_inf_desc" ) + GameMode_SetGameModeAnnouncement( GAMEMODE_INFECTION, "ffa_modeDesc" ) + GameMode_SetDefaultTimeLimits( GAMEMODE_INFECTION, 5, 0.0 ) + GameMode_AddScoreboardColumnData( GAMEMODE_INFECTION, "#SCOREBOARD_KILLS", PGS_ASSAULT_SCORE, 2 ) + GameMode_SetColor( GAMEMODE_INFECTION, [147, 204, 57, 255] ) + + AddPrivateMatchMode( GAMEMODE_INFECTION ) // add to private lobby modes + + #if SERVER + GameMode_AddServerInit( GAMEMODE_INFECTION, GamemodeInfection_Init ) + GameMode_SetPilotSpawnpointsRatingFunc( GAMEMODE_INFECTION, RateSpawnpoints_Generic ) + GameMode_SetTitanSpawnpointsRatingFunc( GAMEMODE_INFECTION, RateSpawnpoints_Generic ) + #elseif CLIENT + GameMode_AddClientInit( GAMEMODE_INFECTION, ClGamemodeInfection_Init ) + #endif + #if !UI + GameMode_SetScoreCompareFunc( GAMEMODE_INFECTION, CompareAssaultScoreAndInfection ) + #endif +} + +void function InfectionRegisterNetworkVars() +{ + if ( GAMETYPE != GAMEMODE_INFECTION ) + return + + Remote_RegisterFunction( "ServerCallback_YouAreInfected" ) + Remote_RegisterFunction( "ServerCallback_AnnounceFirstInfected" ) + Remote_RegisterFunction( "ServerCallback_AnnounceLastSurvivor" ) +} + +int function CompareAssaultScoreAndInfection( entity a, entity b ) +{ + // survivors should be on top, then sort by assault score + + if ( a.GetTeam() == INFECTION_TEAM_INFECTED && b.GetTeam() == INFECTION_TEAM_SURVIVOR ) + return 1 + else if ( a.GetTeam() == INFECTION_TEAM_SURVIVOR && b.GetTeam() == INFECTION_TEAM_INFECTED ) + return -1 + + return CompareAssaultScore( a, b ) +} \ No newline at end of file diff --git a/Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_gamemode_kr.gnut b/Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_gamemode_kr.gnut new file mode 100644 index 000000000..7cd91de9d --- /dev/null +++ b/Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_gamemode_kr.gnut @@ -0,0 +1,55 @@ +global function Sh_GamemodeKR_Init + +global const string GAMEMODE_KR = "kr" + +void function Sh_GamemodeKR_Init() +{ + // create custom gamemode + AddCallback_OnCustomGamemodesInit( CreateGamemodeKR ) + AddCallback_OnRegisteringCustomNetworkVars( KRRegisterNetworkVars ) +} + +void function CreateGamemodeKR() +{ + GameMode_Create( GAMEMODE_KR ) + GameMode_SetName( GAMEMODE_KR, "#GAMEMODE_kr" ) + GameMode_SetDesc( GAMEMODE_KR, "#PL_kr_desc" ) + GameMode_SetGameModeAnnouncement( GAMEMODE_KR, "ffa_modeDesc" ) + GameMode_SetDefaultTimeLimits( GAMEMODE_KR, 10, 0.0 ) + GameMode_AddScoreboardColumnData( GAMEMODE_KR, "#SCOREBOARD_KR_RECORD", PGS_ASSAULT_SCORE, 2 ) + GameMode_AddScoreboardColumnData( GAMEMODE_KR, "#SCOREBOARD_PILOT_KILLS", PGS_PILOT_KILLS, 2 ) + GameMode_SetColor( GAMEMODE_KR, [147, 204, 57, 255] ) + + AddPrivateMatchMode( GAMEMODE_KR ) // add to private lobby modes + + #if SERVER + GameMode_AddServerInit( GAMEMODE_KR, GamemodeKR_Init ) + GameMode_AddServerInit( GAMEMODE_KR, GamemodeFFAShared_Init ) + GameMode_SetPilotSpawnpointsRatingFunc( GAMEMODE_KR, RateSpawnpoints_Generic ) + GameMode_SetTitanSpawnpointsRatingFunc( GAMEMODE_KR, RateSpawnpoints_Generic ) + #elseif CLIENT + GameMode_AddClientInit( GAMEMODE_KR, ClGamemodeKR_Init ) + GameMode_AddClientInit( GAMEMODE_KR, GamemodeFFAShared_Init ) + GameMode_AddClientInit( GAMEMODE_KR, ClGamemodeFFA_Init ) + #endif + #if !UI + GameMode_SetScoreCompareFunc( GAMEMODE_KR, CompareAssaultScore ) + GameMode_AddSharedInit( GAMEMODE_KR, GamemodeFFA_Dialogue_Init ) + #endif +} + +void function KRRegisterNetworkVars() +{ + if ( GAMETYPE != GAMEMODE_KR ) + return + + Remote_RegisterFunction( "ServerCallback_FlagSpawnIncoming" ) + Remote_RegisterFunction( "ServerCallback_NewKillRacer" ) + Remote_RegisterFunction( "ServerCallback_EndKillrace" ) + + RegisterNetworkedVariable( "killRaceTime", SNDC_PLAYER_EXCLUSIVE, SNVT_TIME, 0.0 ) + + #if CLIENT + RegisterNetworkedVariableChangeCallback_time( "killRaceTime", ShowTimeGainOnKill ) + #endif +} \ No newline at end of file diff --git a/Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_gamemode_sbox.gnut b/Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_gamemode_sbox.gnut new file mode 100644 index 000000000..893d94108 --- /dev/null +++ b/Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_gamemode_sbox.gnut @@ -0,0 +1,20 @@ +global function Sh_GamemodeSbox_Init + +global const string GAMEMODE_SBOX = "sbox" + +void function Sh_GamemodeSbox_Init() +{ + // create custom gametype + AddCallback_OnCustomGamemodesInit( CreateGamemodeSbox ) +} + +void function CreateGamemodeSbox() +{ + GameMode_Create( GAMEMODE_SBOX ) + GameMode_SetName( GAMEMODE_SBOX, "#PL_sbox" ) + GameMode_SetDesc( GAMEMODE_SBOX, "#PL_sbox_desc" ) + + #if SERVER + GameMode_AddServerInit( GAMEMODE_SBOX, GamemodeSbox_Init ) + #endif +} \ No newline at end of file diff --git a/Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_gamemode_tt.gnut b/Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_gamemode_tt.gnut new file mode 100644 index 000000000..f3fbff28f --- /dev/null +++ b/Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_gamemode_tt.gnut @@ -0,0 +1,36 @@ +global function Sh_GamemodeTT_Init + +global const string GAMEMODE_TT = "tt" + +void function Sh_GamemodeTT_Init() +{ + // create custom gamemode + AddCallback_OnCustomGamemodesInit( CreateGamemodeTT ) +} + +void function CreateGamemodeTT() +{ + GameMode_Create( GAMEMODE_TT ) + GameMode_SetName( GAMEMODE_TT, "#GAMEMODE_TT" ) + GameMode_SetDesc( GAMEMODE_TT, "#PL_tt_desc" ) + GameMode_SetGameModeAnnouncement( GAMEMODE_TT, "gnrc_modeDesc" ) + GameMode_SetDefaultScoreLimits( GAMEMODE_TT, 20, 0 ) + GameMode_SetDefaultTimeLimits( GAMEMODE_TT, 15, 0.0 ) + GameMode_AddScoreboardColumnData( GAMEMODE_TT, "#SCOREBOARD_SCORE", PGS_ASSAULT_SCORE, 2 ) + GameMode_AddScoreboardColumnData( GAMEMODE_TT, "#SCOREBOARD_TITAN_KILLS", PGS_TITAN_KILLS, 1 ) + GameMode_AddScoreboardColumnData( GAMEMODE_TT, "#SCOREBOARD_PILOT_KILLS", PGS_PILOT_KILLS, 2 ) + GameMode_SetColor( GAMEMODE_TT, [200, 40, 40, 255] ) + + AddPrivateMatchMode( GAMEMODE_TT ) // add to private lobby modes + + #if SERVER + GameMode_AddServerInit( GAMEMODE_TT, GamemodeTT_Init ) + GameMode_SetPilotSpawnpointsRatingFunc( GAMEMODE_TT, RateSpawnpoints_Generic ) + GameMode_SetTitanSpawnpointsRatingFunc( GAMEMODE_TT, RateSpawnpoints_Generic ) + #elseif CLIENT + GameMode_AddClientInit( GAMEMODE_TT, ClGamemodeTT_Init ) + #endif + #if !UI + GameMode_SetScoreCompareFunc( GAMEMODE_TT, CompareAssaultScore ) + #endif +} \ No newline at end of file diff --git a/Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_riff_floor_is_lava.nut b/Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_riff_floor_is_lava.nut new file mode 100644 index 000000000..3a8ac8e75 --- /dev/null +++ b/Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_riff_floor_is_lava.nut @@ -0,0 +1,262 @@ +untyped + +global function RiffFloorIsLavaShared_Init + +global function GetFogHeight +global function GetLethalFogTopTitan +global function GetLethalFogTop +global function GetLethalFogBottom +global function GetVisibleFogTop +global function GetVisibleFogBottom +global function GetMaxTitanSpawnFogHeight + +global function IsEntInSafeVolume +global function IsEntInLethalVolume + +struct +{ + float fogDepth = 64.0 + float maxTitanSpawnFogDepth = 170.0 + array lethalTitanVolumes + array lethalPilotVolumes + array safePilotVolumes + bool volumesDebug = false + table< string, float > lethalFogHeights +} file + +function RiffFloorIsLavaShared_Init() +{ + switch ( GetMapName() ) + { + case "mp_lagoon": + AddLethalTitanVolume( Vector( -45.656845, 3555.449463, 40.422455 ), Vector( 1209.944092, 5599.152832, 234.813217 ) ) + AddLethalTitanVolume( Vector( -5232.395020, 205.406250, 0.031250 ), Vector( -777.285400, 4075.119385, 300.634771 ) ) + AddLethalTitanVolume( Vector( -4686.448730, 4190.655273, 20.642021 ), Vector( -41.171387, 9072.019043, 200.697632 ) ) + AddLethalTitanVolume( Vector( -7586.861328, 4072.843994, 0.031254 ), Vector( -7012.854004, 4614.723145, 302.714966 ) ) + break + + case "mp_nexus": + AddLethalTitanVolume( Vector( 1567.173523, -27.374023, 209.422455 ), Vector( 2516.944092, 2585.152832, 500.813217 ) ) + AddLethalTitanVolume( Vector( -2825.766113, 5056.203125, 243.706253 ), Vector( -2255.893555, 5688.334961, 400.251160 ) ) + AddLethalTitanVolume( Vector( -5717.068359, -349.599976, 189.669785 ), Vector( -4960.125000, 758.196350, 400.268097 ) ) + AddLethalTitanVolume( Vector( -3292.942139, 1713.916626, 233.749817 ), Vector( -2322.137695, 3091.497070, 477.462799 ) ) + AddLethalTitanVolume( Vector( -878.712769, -5878.528809, 71.145332 ), Vector( 338.741943, -5014.183594, 443.146179 ) ) + AddLethalTitanVolume( Vector( -6930.957031, -1277.388550, 107.619537 ), Vector( -6574.779297, -779.338013, 685.485901 ) ) + break + + case "mp_outpost_207": + AddSafePilotVolume( Vector( 2359.524658, -631.065918, -256.714142 ), Vector( 2623.051270, -182.453323, -220.125641 ) ) + + AddLethalTitanVolume( Vector( -100.349350, 2218.763916, -330.968750 ), Vector( 2561.511230, 4030.028320, -133.065369 ) ) + AddLethalTitanVolume( Vector( -452.031647, 282.244629, -255.968750 ), Vector( 2241.971069, 1594.146851, -100.212967 ) ) + break + + case "mp_training_ground": + AddSafePilotVolume( Vector( -2618.053223, -3435.505615, 40.215054 ), Vector( -2309.167236, -3321.788330, 146.218491 ) ) + AddSafePilotVolume( Vector( -3187.767090, -2886.333496, 45.746925 ), Vector( -2865.753174, -2681.679443, 109.089279 ) ) + AddSafePilotVolume( Vector( -3717.815674, -2350.831543, 47.694588 ), Vector( -3431.980957, -2145.194092, 120.640717 ) ) + + AddLethalTitanVolume( Vector( -3439.702179, -2227.359741, -8.036909 ), Vector( 2185.765076, 2384.459412, 225.199013 ) ) + AddLethalTitanVolume( Vector( -3200.747681, -4456.148926, 0.0 ), Vector( -1261.621826, -3000.667480, 160.689011 ) ) + AddLethalTitanVolume( Vector( 1261.621826, 3000.667480, 0.0 ), Vector( 2700.747681, 4456.148926, 160.689011 ) ) + AddLethalTitanVolume( Vector( -3291.510986, 3483.724609, 4.031250 ), Vector( -2018.871826, 4463.995850, 122.675621 ) ) + AddLethalTitanVolume( Vector( 2018.871826, -3638.995850, 4.031250 ), Vector( 2241.510986, -3483.724609, 122.675621 ) ) + AddLethalTitanVolume( Vector( -2798.816528, -2302.519897, -30.285933 ), Vector( -1561.589355, -791.616699, 300.917297 ) ) + AddLethalTitanVolume( Vector( 3809.276123, 1639.001587, 11.272846 ), Vector( 4056.847412, 1862.587036, 100.205643 ) ) + AddLethalTitanVolume( Vector( -4189.979492, -3298.505127, -5.597572 ), Vector( -3398.622803, -560.027344, 147.054291 ) ) + break + + case "mp_runoff": + AddLethalPilotVolume( Vector( -621.502319, -5743.472656, 299.838928 ), Vector( -397.317047, -5578.512207, 425.437927 ) ) + break + } +} + +float function GetFogHeight() +{ + string mapName = GetMapName() + + file.lethalFogHeights = {} + file.lethalFogHeights[ "mp_angel_city" ] <- 216.0 // cp ctf mfd + file.lethalFogHeights[ "mp_lagoon" ] <- 98.0 // cp mfd + file.lethalFogHeights[ "mp_nexus" ] <- 310.0 // mfd + file.lethalFogHeights[ "mp_o2" ] <- 40.0 // mfd + file.lethalFogHeights[ "mp_outpost_207" ] <- -225.0 // mfd + file.lethalFogHeights[ "mp_training_ground" ] <- 80.0 // cp mfd + file.lethalFogHeights[ "mp_harmony_mines" ] <- 260.0 // cp ctf mfd + file.lethalFogHeights[ "mp_haven" ] <- 128.0 // mfd + + // good map, needs spawns, etc... + file.lethalFogHeights[ "mp_rise" ] <- 420.0 // mfd + file.lethalFogHeights[ "mp_runoff" ] <- 340.0 // mfd + file.lethalFogHeights[ "mp_zone_18" ] <- 460.0 // mfd + file.lethalFogHeights[ "mp_sandtrap" ] <- 64.0 + + // these don't work as well + file.lethalFogHeights[ "mp_swampland" ] <- 350.0 // mfd + file.lethalFogHeights[ "mp_backwater" ] <- 320.0 // mfd + file.lethalFogHeights[ "mp_airbase" ] <- 450.0 + file.lethalFogHeights[ "mp_boneyard" ] <- 64.0 + file.lethalFogHeights[ "mp_colony" ] <- 270.0 + file.lethalFogHeights[ "mp_corporate" ] <- -765.0 + file.lethalFogHeights[ "mp_fracture" ] <- 270.0 + file.lethalFogHeights[ "mp_overlook" ] <- 16.0 + file.lethalFogHeights[ "mp_relic" ] <- 475.0 + file.lethalFogHeights[ "mp_smugglers_cove" ] <- 400.0 + file.lethalFogHeights[ "mp_wargames" ] <- 64.0 + file.lethalFogHeights[ "mp_switchback" ] <- 840.0 + + file.lethalFogHeights[ "mp_chin_rodeo_express" ] <- 1580.0 + + // custom: titanfall 2 maps + // TODO: really need a modular system here + file.lethalFogHeights[ "mp_colony02" ] <- 270.0 // map changed name from tf1 => tf2 + file.lethalFogHeights[ "mp_glitch" ] <- 200.0 + file.lethalFogHeights[ "mp_grave" ] <- 2350.0 + file.lethalFogHeights[ "mp_homestead" ] <- 64.0 + file.lethalFogHeights[ "mp_forwardbase_kodai" ] <- 930.0 + file.lethalFogHeights[ "mp_thaw" ] <- 32.0 + file.lethalFogHeights[ "mp_black_water_canal" ] <- 32.0 + file.lethalFogHeights[ "mp_eden" ] <- 175.0 + file.lethalFogHeights[ "mp_drydock" ] <- 300.0 + file.lethalFogHeights[ "mp_crashsite3" ] <- 800.0 // crashsite is just as awful for this as it is for anything else + file.lethalFogHeights[ "mp_complex3" ] <- 630.0 + file.lethalFogHeights[ "mp_relic02" ] <- 250.0 // not great, tf1's would honestly be worse though imo + + // lf maps: overall a bit hit or miss, many likely have spawn issues + file.lethalFogHeights[ "mp_lf_stacks" ] <- -9999.0 // entirely nonworking, breaks spawns no matter what from what i can tell, could potentially use safe zones for this? + file.lethalFogHeights[ "mp_lf_deck" ] <- -9999.0 // nonworking fogcontroller so fog is invisible + file.lethalFogHeights[ "mp_lf_uma" ] <- 64.0 + file.lethalFogHeights[ "mp_lf_meadow" ] <- 64.0 + file.lethalFogHeights[ "mp_lf_traffic" ] <- 50.0 + file.lethalFogHeights[ "mp_lf_township" ] <- 64.0 + + if ( mapName in file.lethalFogHeights ) + return file.lethalFogHeights[ mapName ] + + return 64.0 +} + +float function GetLethalFogTopTitan() +{ + float fogTop = GetLethalFogTop() + + switch ( GetMapName() ) + { + case "mp_lagoon": + case "mp_nexus": + case "mp_outpost_207": + case "mp_training_ground": + case "mp_chin_rodeo_express": + return fogTop + } + + return fogTop + 256.0 +} + +float function GetLethalFogTop() +{ + return GetFogHeight() - file.fogDepth * 0.2 +} + +float function GetLethalFogBottom() +{ + return GetFogHeight() - file.fogDepth * 0.7 +} + +float function GetVisibleFogTop() +{ + return GetFogHeight() + file.fogDepth * 0.5 +} + +float function GetVisibleFogBottom() +{ + return GetFogHeight() - file.fogDepth * 0.5 +} + +float function GetMaxTitanSpawnFogHeight() +{ + return GetFogHeight() - file.maxTitanSpawnFogDepth +} + +function AddLethalTitanVolume( vector volumeMins, vector volumeMaxs ) +{ + Assert( volumeMins.x < volumeMaxs.x ) + Assert( volumeMins.y < volumeMaxs.y ) + Assert( volumeMins.z < volumeMaxs.z ) + + file.lethalTitanVolumes.append( { mins = volumeMins, maxs = volumeMaxs } ) +} + +function AddLethalPilotVolume( vector volumeMins, vector volumeMaxs ) +{ + Assert( volumeMins.x < volumeMaxs.x ) + Assert( volumeMins.y < volumeMaxs.y ) + Assert( volumeMins.z < volumeMaxs.z ) + + file.lethalPilotVolumes.append( { mins = volumeMins, maxs = volumeMaxs } ) +} + +function AddSafePilotVolume( vector volumeMins, vector volumeMaxs ) +{ + Assert( volumeMins.x < volumeMaxs.x ) + Assert( volumeMins.y < volumeMaxs.y ) + Assert( volumeMins.z < volumeMaxs.z ) + + file.safePilotVolumes.append( { mins = volumeMins, maxs = volumeMaxs } ) +} + +function IsEntInSafeVolume( entity ent ) +{ + if ( ent.IsPlayer() ) + { + foreach ( volume in file.safePilotVolumes ) + { + vector entOrg = ent.GetOrigin() + + #if SERVER + if ( file.volumesDebug ) + DebugDrawBox( Vector( 0.0, 0.0, 0.0 ), volume.mins, volume.maxs, 0, 0, 255, 1, 0.1 ) + #endif + + if ( PointIsWithinBounds( entOrg, expect vector( volume.mins ), expect vector( volume.maxs ) ) ) + return true + } + } +} + +function IsEntInLethalVolume( entity ent ) +{ + if ( ent.IsTitan() ) + { + foreach ( volume in file.lethalTitanVolumes ) + { + vector entOrg = ent.GetOrigin() + + #if SERVER + if ( file.volumesDebug ) + DebugDrawBox( Vector( 0.0, 0.0, 0.0 ), volume.mins, volume.maxs, 255, 255, 0, 1, 0.1 ) + #endif + + if ( PointIsWithinBounds( entOrg, expect vector( volume.mins ), expect vector( volume.maxs ) ) ) + return true + } + } + else if ( ent.IsPlayer() ) + { + foreach ( volume in file.lethalPilotVolumes ) + { + vector entOrg = ent.GetOrigin() + + #if SERVER + if ( file.volumesDebug ) + DebugDrawBox( Vector( 0.0, 0.0, 0.0 ), volume.mins, volume.maxs, 255, 255, 0, 1, 0.1 ) + #endif + + if ( PointIsWithinBounds( entOrg, expect vector( volume.mins ), expect vector( volume.maxs ) ) ) + return true + } + } + + return false +} -- cgit v1.2.3