From 15b3b65fc4e88fe98ba12b4d7603e396fba91fb3 Mon Sep 17 00:00:00 2001 From: Jack <66967891+ASpoonPlaysGames@users.noreply.github.com> Date: Sat, 7 Oct 2023 11:40:31 +0100 Subject: [PATCH 01/25] Display origin auth failure in a dialog (#648) Currently, we don't do anything with origin auth failure, meaning the next request just fails, and we get not particularly relevant error messages (player not found, invalid masterserver token) --- .github/nativefuncs.json | 6 ++ Northstar.Client/mod.json | 7 +++ .../northstar_client_localisation_english.txt | 5 ++ .../vscripts/cl_northstar_client_init.nut | 7 +++ .../mod/scripts/vscripts/ui/atlas_auth.nut | 56 +++++++++++++++++++ 5 files changed, 81 insertions(+) create mode 100644 Northstar.Client/mod/scripts/vscripts/ui/atlas_auth.nut diff --git a/.github/nativefuncs.json b/.github/nativefuncs.json index 6f46095fd..13a7edd3d 100644 --- a/.github/nativefuncs.json +++ b/.github/nativefuncs.json @@ -729,6 +729,12 @@ "helpText":"", "returnTypeString":"void", "argTypes":"struct presence" + }, + { + "name":"NSGetMasterServerAuthResult", + "helpText":"", + "returnTypeString":"MasterServerAuthResult", + "argTypes":"" } ] } \ No newline at end of file diff --git a/Northstar.Client/mod.json b/Northstar.Client/mod.json index 7d695a4b7..f7c7c9b5b 100644 --- a/Northstar.Client/mod.json +++ b/Northstar.Client/mod.json @@ -128,6 +128,13 @@ { "Path": "ui/ui_mouse_capture.nut", "RunOn": "UI" + }, + { + "Path": "ui/atlas_auth.nut", + "RunOn": "UI", + "UICallback": { + "After": "AtlasAuthDialog" + } } ], "Localisation": [ diff --git a/Northstar.Client/mod/resource/northstar_client_localisation_english.txt b/Northstar.Client/mod/resource/northstar_client_localisation_english.txt index 8c7bab3a7..49e9ee43d 100644 --- a/Northstar.Client/mod/resource/northstar_client_localisation_english.txt +++ b/Northstar.Client/mod/resource/northstar_client_localisation_english.txt @@ -322,6 +322,11 @@ Press Yes if you agree to this. This choice can be changed in the mods menu at a "INVALID_MASTERSERVER_TOKEN" "Invalid or expired masterserver token" "JSON_PARSE_ERROR" "Error parsing json response" "UNSUPPORTED_VERSION" "The version you are using is no longer supported" + + "AUTHENTICATION_FAILED_HEADER" "Authentication Failed" + "AUTHENTICATION_FAILED_BODY" "Failed to authenticate with Atlas!" + "AUTHENTICATION_FAILED_ERROR_CODE" "Error code: ^DB6F2C00%s1^" + "AUTHENTICATION_FAILED_HELP" "Help" // Mod Settings "MOD_SETTINGS" "Mod Settings" diff --git a/Northstar.Client/mod/scripts/vscripts/cl_northstar_client_init.nut b/Northstar.Client/mod/scripts/vscripts/cl_northstar_client_init.nut index 2a2ed3dbe..a844478a2 100644 --- a/Northstar.Client/mod/scripts/vscripts/cl_northstar_client_init.nut +++ b/Northstar.Client/mod/scripts/vscripts/cl_northstar_client_init.nut @@ -41,3 +41,10 @@ global struct ServerInfo string region array< RequiredModInfo > requiredMods } + +global struct MasterServerAuthResult +{ + bool success + string errorCode + string errorMessage +} diff --git a/Northstar.Client/mod/scripts/vscripts/ui/atlas_auth.nut b/Northstar.Client/mod/scripts/vscripts/ui/atlas_auth.nut new file mode 100644 index 000000000..89b7f7196 --- /dev/null +++ b/Northstar.Client/mod/scripts/vscripts/ui/atlas_auth.nut @@ -0,0 +1,56 @@ +global function AtlasAuthDialog + +void function AtlasAuthDialog() +{ + thread AtlasAuthDialog_Threaded() +} + +void function AtlasAuthDialog_Threaded() +{ + // wait at least 1 frame so that the main menu can be loaded first + WaitFrame() + + while ( !NSIsMasterServerAuthenticated() || GetConVarBool( "ns_auth_allow_insecure" ) ) + WaitFrame() + + if ( GetConVarBool( "ns_auth_allow_insecure" ) ) + return + + MasterServerAuthResult res = NSGetMasterServerAuthResult() + + // do nothing on successful authentication + if ( res.success ) + return + + EmitUISound( "blackmarket_purchase_fail" ) + + DialogData dialogData + dialogData.image = $"ui/menu/common/dialog_error" + dialogData.header = Localize( "#AUTHENTICATION_FAILED_HEADER" ) + + // if we got a special error message from Atlas, display it + if ( res.errorMessage != "" ) + dialogData.message = res.errorMessage + else + dialogData.message = Localize( "#AUTHENTICATION_FAILED_BODY" ) + + if ( res.errorCode != "" ) + dialogData.message += format( "\n\n%s", Localize( "#AUTHENTICATION_FAILED_ERROR_CODE", res.errorCode ) ) + + string link = "https://r2northstar.gitbook.io/r2northstar-wiki/installing-northstar/troubleshooting" + // link to generic troubleshooting page if we don't have an error code from Atlas + if ( res.errorCode != "" ) + link = format( "%s#%s", link, res.errorCode ) + + CloseAllDialogs() + AddDialogButton( dialogData, "#OK" ) + AddDialogButton( dialogData, Localize( "#AUTHENTICATION_FAILED_HELP" ), void function() : ( dialogData, link ) + { + // todo: get MS to redirect, so i can use an MS link or something? + LaunchExternalWebBrowser( link, WEBBROWSER_FLAG_FORCEEXTERNAL ) + // keep the dialog open + OpenDialog( dialogData ) + } ) + + OpenDialog( dialogData ) +} From 0ee1f3daea0cd1c2badfb7c373fe9d0b14917501 Mon Sep 17 00:00:00 2001 From: Harmony Weblate <96563367+harmony-weblate@users.noreply.github.com> Date: Sun, 8 Oct 2023 16:19:51 +0200 Subject: [PATCH 02/25] Translations update from Weblate (#739) Translated using Weblate (Russian) Currently translated at 95.1% (277 of 291 strings) Translation: Northstar/Northstar Client Localisation Translate-URL: https://translate.harmony.tf/projects/northstar/client/ru/ Co-authored-by: WofWca --- .../mod/resource/northstar_client_localisation_russian.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Northstar.Client/mod/resource/northstar_client_localisation_russian.txt b/Northstar.Client/mod/resource/northstar_client_localisation_russian.txt index 514e4fd13..f7c6bc6e2 100644 --- a/Northstar.Client/mod/resource/northstar_client_localisation_russian.txt +++ b/Northstar.Client/mod/resource/northstar_client_localisation_russian.txt @@ -341,5 +341,9 @@ "PROGRESSION_TOGGLE_ENABLED_BODY" "Все титаны, оружие, фракции, раскраски, и т.п. станут разблокированы.\n\nЭту настройку всегда можно изменить в лобби сетевой игры." "PROGRESSION_TOGGLE_DISABLED_BODY" "Будут доступны только разблокированные или купленные вами титаны, оружие, фракции, раскраски, и т.п.\n\nЭту настройку всегда можно изменить в лобби сетевой игры.\n\n^CC000000Внимание: недоступные предметы в экипировке будут заменены на доступные!" "PROGRESSION_ANNOUNCEMENT_BODY" "^CCCC0000Прогресс!^\n\nВ Northstar теперь работает оригинальная система прогресса разблокировок. Титанов, оружие, фракции, раскраски, и т.п. теперь можно разблокировать через получение новых уровней и прохождение испытаний.\n\nПрогресс можно включить с помощью кнопки внизу меню лобби.\n\nЭту настройку всегда можно изменить." + "AUTHENTICATION_FAILED_BODY" "Не удалось войти в Atlas!" + "AUTHENTICATION_FAILED_ERROR_CODE" "Код ошибки: ^DB6F2C00%s1^" + "AUTHENTICATION_FAILED_HELP" "Справка" + "AUTHENTICATION_FAILED_HEADER" "Ошибка аутентификации" } } From 89c0d98ed62ec32861045852dbbfd295b0859761 Mon Sep 17 00:00:00 2001 From: Jack <66967891+ASpoonPlaysGames@users.noreply.github.com> Date: Mon, 9 Oct 2023 00:44:02 +0100 Subject: [PATCH 03/25] Fix localisation string for toggling progression on controller (#717) Fix the controller button for toggling progression not showing up. --- .../mod/resource/northstar_client_localisation_english.txt | 2 +- .../mod/resource/northstar_client_localisation_french.txt | 2 +- .../mod/resource/northstar_client_localisation_russian.txt | 2 +- .../mod/resource/northstar_client_localisation_spanish.txt | 2 +- .../mod/resource/northstar_client_localisation_tchinese.txt | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Northstar.Client/mod/resource/northstar_client_localisation_english.txt b/Northstar.Client/mod/resource/northstar_client_localisation_english.txt index 49e9ee43d..c7b25a706 100644 --- a/Northstar.Client/mod/resource/northstar_client_localisation_english.txt +++ b/Northstar.Client/mod/resource/northstar_client_localisation_english.txt @@ -351,7 +351,7 @@ Press Yes if you agree to this. This choice can be changed in the mods menu at a // Toggleable progression "TOGGLE_PROGRESSION" "Toggle Progression" - "Y_BUTTON_TOGGLE_PROGRESSION" "%[Y_BUTTON]% Toggle Progression" + "Y_BUTTON_TOGGLE_PROGRESSION" "%[Y_BUTTON|]% Toggle Progression" "PROGRESSION_TOGGLE_ENABLED_HEADER" "Disable Progression?" "PROGRESSION_TOGGLE_ENABLED_BODY" "Titans, Weapons, Factions, Skins, etc. will all be unlocked and usable at any time.\n\nThis can be changed at any time in the multiplayer lobby." diff --git a/Northstar.Client/mod/resource/northstar_client_localisation_french.txt b/Northstar.Client/mod/resource/northstar_client_localisation_french.txt index 45abcfc5d..377f69179 100644 --- a/Northstar.Client/mod/resource/northstar_client_localisation_french.txt +++ b/Northstar.Client/mod/resource/northstar_client_localisation_french.txt @@ -351,7 +351,7 @@ Choisissez Oui si vous êtes d'accord. Ce choix peut être modifié à tout inst "PROGRESSION_TOGGLE_DISABLED_BODY" "Les Titans, Armes, Factions, Skins et autres seront débloqués par la monté en niveau ou par leur achats en mérites.\n\nPeut être changé à n'importe que moment dans le salon multijoueurs.\n\n^CC000000Warning : Si vous équiper des objets que vous n'avez pas encore débloqués, ils seront déséquipés !" "PROGRESSION_ENABLED_BODY" "^CCCC0000La progression a été activée.^\n\nLes Titans, Armes, Factions, Skins et autres seront débloqués par la monté en niveau ou par leur achats en mérites.\n\nPeut être changé à n'importe que moment dans le salon multijoueurs." "TOGGLE_PROGRESSION" "Activer la progression" - "Y_BUTTON_TOGGLE_PROGRESSION" "%[Y_BUTTON]% Activer la progression" + "Y_BUTTON_TOGGLE_PROGRESSION" "%[Y_BUTTON|]% Activer la progression" "PROGRESSION_ANNOUNCEMENT_BODY" "^CCCC0000Le système de progression peut être activé !^\n\nNorthstar supporte désormais le système de progression du jeu original, vous permettant de choisir si vous souhaitez débloquer les armes, skins, titans etc. en gagnant des niveaux et en complétant des défis.\n\nVous pouvez activer la progression en utilisant le bouton en bas de l'écran d'accueil.\n\nCeci peut être changé à tout moment." } } diff --git a/Northstar.Client/mod/resource/northstar_client_localisation_russian.txt b/Northstar.Client/mod/resource/northstar_client_localisation_russian.txt index f7c6bc6e2..cf410ff29 100644 --- a/Northstar.Client/mod/resource/northstar_client_localisation_russian.txt +++ b/Northstar.Client/mod/resource/northstar_client_localisation_russian.txt @@ -330,7 +330,7 @@ "sns_reset_pulse_blade_cooldown_on_pulse_blade_kill" "Сброс перезарядки пульс. клинка при убийстве им" "gg_assist_reward" "Множитель награды за помощь в убийстве" "TOGGLE_PROGRESSION" "Вкл/выкл прогресс" - "Y_BUTTON_TOGGLE_PROGRESSION" "%[Y_BUTTON]% Вкл/выкл прогресс" + "Y_BUTTON_TOGGLE_PROGRESSION" "%[Y_BUTTON|]% Вкл/выкл прогресс" "PROGRESSION_TOGGLE_DISABLED_HEADER" "Включить прогресс?" "PROGRESSION_ENABLED_HEADER" "Прогресс включён!" "PROGRESSION_ENABLED_BODY" "^CCCC0000Прогресс включён.^\n\nНедоступных титанов, оружие, фракции, раскраски, и т.п. теперь нужно разблокировать, или купить за Заслуги.\n\nЭту настройку всегда можно изменить в лобби сетевой игры." diff --git a/Northstar.Client/mod/resource/northstar_client_localisation_spanish.txt b/Northstar.Client/mod/resource/northstar_client_localisation_spanish.txt index 43ee412f7..3d9ae4c6c 100644 --- a/Northstar.Client/mod/resource/northstar_client_localisation_spanish.txt +++ b/Northstar.Client/mod/resource/northstar_client_localisation_spanish.txt @@ -342,7 +342,7 @@ Presiona Sí al estar de acuerdo. Esta opcion se puede cambiar en el menú de mo "PROGRESSION_ENABLED_HEADER" "¡Progreso habilitado!" "PROGRESSION_DISABLED_HEADER" "¡Progreso deshabilitado!" "TOGGLE_PROGRESSION" "Cambiar modo de progresión" - "Y_BUTTON_TOGGLE_PROGRESSION" "%[Y_BUTTON]% Cambiar modo de progresión" + "Y_BUTTON_TOGGLE_PROGRESSION" "%[Y_BUTTON|]% Cambiar modo de progresión" "PROGRESSION_TOGGLE_DISABLED_BODY" "Titanes, Armas, Facciones, Aspectos y otros serán desbloqueados sólo al subir de nivel, o a través de Logros.\n\nÉsta opción puede ser cambiada cuando quieras en la sala de espera.\n\n^CC000000Advertencia: ¡Cualquier equipamiento o utensilio será reiniciado si no lo tienes desbloqueado!" "MOD_SETTINGS_SERVER" "Servidor" "MOD_SETTINGS_RESET_ALL" "Reiniciar completamente" diff --git a/Northstar.Client/mod/resource/northstar_client_localisation_tchinese.txt b/Northstar.Client/mod/resource/northstar_client_localisation_tchinese.txt index 003ca28a4..500f8a969 100644 --- a/Northstar.Client/mod/resource/northstar_client_localisation_tchinese.txt +++ b/Northstar.Client/mod/resource/northstar_client_localisation_tchinese.txt @@ -350,7 +350,7 @@ "PROGRESSION_TOGGLE_DISABLED_BODY" "泰坦,武器, 陣營,皮膚以及其他一切需要解鎖的物品將通過升級或是使用點數購買來進行解鎖。.\n\n您可以隨時在多人大廳中更改此項。\n\n^CC000000警告:如果您已經裝備了尚未解鎖的物品,它們將會被重置!" "PROGRESSION_TOGGLE_ENABLED_BODY" "泰坦,武器,陣營,皮膚及所有其他一切需要解鎖的物品都將隨時可以進行解鎖並使用。\n\n您可以隨時在多人大廳中更改此項。" "TOGGLE_PROGRESSION" "遊戲進度" - "Y_BUTTON_TOGGLE_PROGRESSION" "%[Y_BUTTON]% 遊戲進度" + "Y_BUTTON_TOGGLE_PROGRESSION" "%[Y_BUTTON|]% 遊戲進度" "PROGRESSION_TOGGLE_ENABLED_HEADER" "停用個人進度?" "PROGRESSION_DISABLED_HEADER" "個人進度已關閉!" "PROGRESSION_DISABLED_BODY" "^CCCC0000個人進度已停用^\n\n泰坦,武器,陣營,皮膚及所有其他一切需要解鎖的物品將隨時可以進行解鎖並使用。\n\n您可以隨時在多人大廳中更改此項。" From 612e6a116990afe15212af917aa8443030d5c3d4 Mon Sep 17 00:00:00 2001 From: Jack <66967891+ASpoonPlaysGames@users.noreply.github.com> Date: Mon, 9 Oct 2023 00:45:46 +0100 Subject: [PATCH 04/25] Fix titan-only boosts for modes like LTS (#678) Revert back to the original check by Respawn --- .../mod/scripts/vscripts/burnmeter/sh_burnmeter.gnut | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Northstar.Custom/mod/scripts/vscripts/burnmeter/sh_burnmeter.gnut b/Northstar.Custom/mod/scripts/vscripts/burnmeter/sh_burnmeter.gnut index ac9ffab37..37d4356f0 100644 --- a/Northstar.Custom/mod/scripts/vscripts/burnmeter/sh_burnmeter.gnut +++ b/Northstar.Custom/mod/scripts/vscripts/burnmeter/sh_burnmeter.gnut @@ -188,7 +188,7 @@ BurnReward function BurnReward_GetRandom() string ref = burn.allowedCards.getrandom().ref #if SERVER || CLIENT - if ( !EarnMeterMP_IsTitanEarnGametype() ) + if ( Riff_TitanAvailability() == eTitanAvailability.Never ) ref = BurnMeter_GetNoTitansReplacement( ref ) if ( GetCurrentPlaylistVarInt( "featured_mode_all_ticks", 0 ) >= 1 ) @@ -211,7 +211,7 @@ string function GetSelectedBurnCardRef( entity player ) #endif #if SERVER || CLIENT - if ( !EarnMeterMP_IsTitanEarnGametype() ) + if ( Riff_TitanAvailability() == eTitanAvailability.Never ) ref = BurnMeter_GetNoTitansReplacement( ref ) if ( GetCurrentPlaylistVarInt( "featured_mode_all_ticks", 0 ) >= 1 ) From 9eede6047a18d9936b2d98c1499cc90bd8d091d7 Mon Sep 17 00:00:00 2001 From: William Miller Date: Mon, 9 Oct 2023 21:35:11 -0300 Subject: [PATCH 05/25] Implement `_grunt_chatter_mp.gnut` (#687) Code is adapted from `_grunt_chatter.gnut` which is used in the campaign. File implementation is a vanilla behavior restoration of Grunts being able to chatter about when other grunts nearby are killed, or when an enemy Titan is killed. --- .../conversation/_grunt_chatter_mp.gnut | 195 +++++++++++++++++- 1 file changed, 194 insertions(+), 1 deletion(-) diff --git a/Northstar.CustomServers/mod/scripts/vscripts/conversation/_grunt_chatter_mp.gnut b/Northstar.CustomServers/mod/scripts/vscripts/conversation/_grunt_chatter_mp.gnut index 1a70c2896..4eb423fdb 100644 --- a/Northstar.CustomServers/mod/scripts/vscripts/conversation/_grunt_chatter_mp.gnut +++ b/Northstar.CustomServers/mod/scripts/vscripts/conversation/_grunt_chatter_mp.gnut @@ -1,11 +1,33 @@ global function GruntChatter_MP_Init global function PlayGruntChatterMPLine +const float CHATTER_FRIENDLY_GRUNT_DOWN_DIST_MAX = 1100.0 +const float CHATTER_SQUAD_DEPLETED_FRIENDLY_NEARBY_DIST = 650.0 // if any other friendly grunt is within this dist, squad deplete chatter won't play +const float CHATTER_ENEMY_TITAN_DOWN_DIST_MAX = 1500.0 +const float CHATTER_NEARBY_GRUNT_TRACEFRAC_MIN = 0.95 // for when we need "LOS" trace + void function GruntChatter_MP_Init() { - //ShGruntChatter_MP_Init() + Assert( IsMultiplayer(), "MP Grunt chatter is restricted to Multiplayer only." ) + + AddCallback_OnPlayerKilled( GruntChatter_OnPlayerOrNPCKilled ) + AddCallback_OnNPCKilled( GruntChatter_OnPlayerOrNPCKilled ) } + + + +/*===================================================================================================================================================== + _____ _ _____ _ _ _ __ __ _ _ _ _ + / ____| | | / ____|| | | | | | | \/ | | || | (_) | | + | | __ _ __ _ _ _ __ | |_ | | | |__ __ _ | |_ | |_ ___ _ __ | \ / | _ _ | || |_ _ _ __ | | __ _ _ _ ___ _ __ + | | |_ || '__|| | | || '_ \ | __| | | | '_ \ / _` || __|| __|/ _ \| '__| | |\/| || | | || || __|| || '_ \ | | / _` || | | | / _ \| '__| + | |__| || | | |_| || | | || |_ | |____ | | | || (_| || |_ | |_| __/| | | | | || |_| || || |_ | || |_) || || (_| || |_| || __/| | + \_____||_| \__,_||_| |_| \__| \_____||_| |_| \__,_| \__| \__|\___||_| |_| |_| \__,_||_| \__||_|| .__/ |_| \__,_| \__, | \___||_| + | | __/ | + |_| |___/ +/*===================================================================================================================================================*/ + void function PlayGruntChatterMPLine( entity grunt, string conversationType ) { #if !GRUNT_CHATTER_MP_ENABLED @@ -15,4 +37,175 @@ void function PlayGruntChatterMPLine( entity grunt, string conversationType ) foreach ( entity player in GetPlayerArray() ) if ( ShouldPlayGruntChatterMPLine( conversationType, player, grunt ) ) Remote_CallFunction_Replay( player, "ServerCallback_PlayGruntChatterMP", GetConversationIndex( conversationType ), grunt.GetEncodedEHandle() ) +} + +void function GruntChatter_OnPlayerOrNPCKilled( entity deadGuy, entity attacker, var damageInfo ) +{ + if ( !IsValid( deadGuy ) || !IsValid( attacker ) ) + return + + if( IsGrunt( attacker ) && IsPilot( deadGuy ) ) + PlayGruntChatterMPLine( attacker, "bc_killenemypilot" ) + else + GruntChatter_TryEnemyTitanDown( deadGuy ) + + if ( IsGrunt( deadGuy ) ) + { + GruntChatter_TryFriendlyDown( deadGuy ) + GruntChatter_TrySquadDepleted( deadGuy ) + } +} + +void function GruntChatter_TryFriendlyDown( entity deadGuy ) +{ + entity closestGrunt = GruntChatter_FindClosestFriendlyHumanGrunt_LOS( deadGuy.GetOrigin(), deadGuy.GetTeam(), CHATTER_FRIENDLY_GRUNT_DOWN_DIST_MAX ) + if ( !closestGrunt ) + return + + if ( !GruntChatter_CanGruntChatterNow( closestGrunt ) ) + return + + PlayGruntChatterMPLine( closestGrunt, "bc_allygruntdown" ) +} + +void function GruntChatter_TrySquadDepleted( entity deadGuy ) +{ + string deadGuySquadName = expect string( deadGuy.kv.squadname ) + if ( deadGuySquadName == "" ) + return + + array squad = GetNPCArrayBySquad( deadGuySquadName ) + entity lastSquadMember + if ( squad.len() == 1 ) + lastSquadMember = squad[0] + + if ( !GruntChatter_CanGruntChatterNow( lastSquadMember ) ) + return + + if ( lastSquadMember.GetNPCState() == "idle" ) + return + + // if another grunt from another squad is nearby, don't chatter about being alone + array nearbyGrunts = GetNearbyFriendlyGrunts( lastSquadMember.GetOrigin(), lastSquadMember.GetTeam(), CHATTER_SQUAD_DEPLETED_FRIENDLY_NEARBY_DIST ) + nearbyGrunts.fastremovebyvalue( lastSquadMember ) + if ( nearbyGrunts.len() ) + return + + PlayGruntChatterMPLine( lastSquadMember, "bc_squaddeplete" ) +} + +void function GruntChatter_TryEnemyTitanDown( entity deadGuy ) +{ + if ( deadGuy.IsTitan() ) + { + entity closestGrunt = GruntChatter_FindClosestEnemyHumanGrunt_LOS( deadGuy.GetOrigin(), deadGuy.GetTeam(), CHATTER_ENEMY_TITAN_DOWN_DIST_MAX ) + if ( !closestGrunt ) + return + + PlayGruntChatterMPLine( closestGrunt, "bc_enemytitandown" ) + } +} + +entity function GruntChatter_FindClosestEnemyHumanGrunt_LOS( vector searchOrigin, int enemyTeam, float searchDist ) +{ + array humanGrunts = GetNearbyEnemyHumanGrunts( searchOrigin, enemyTeam, searchDist ) + return GruntChatter_GetClosestGrunt_LOS( humanGrunts, searchOrigin ) +} + +entity function GruntChatter_FindClosestFriendlyHumanGrunt_LOS( vector searchOrigin, int friendlyTeam, float searchDist ) +{ + array humanGrunts = GetNearbyFriendlyHumanGrunts( searchOrigin, friendlyTeam, searchDist ) + return GruntChatter_GetClosestGrunt_LOS( humanGrunts, searchOrigin ) +} + +entity function GruntChatter_GetClosestGrunt_LOS( array nearbyGrunts, vector searchOrigin ) +{ + entity closestGrunt = null + float closestDist = 10000 + + foreach ( grunt in nearbyGrunts ) + { + vector gruntOrigin = grunt.GetOrigin() + + // CanSee doesn't return true if the target is dead + if ( !GruntChatter_CanGruntTraceToLocation( grunt, searchOrigin ) ) + continue + + if ( !closestGrunt ) + { + closestGrunt = grunt + continue + } + + float distFromSearchOrigin = Distance( grunt.GetOrigin(), searchOrigin ) + + if ( closestDist > distFromSearchOrigin ) + continue + + closestGrunt = grunt + closestDist = distFromSearchOrigin + } + + return closestGrunt +} + +bool function GruntChatter_CanGruntTraceToLocation( entity grunt, vector traceEnd ) +{ + float traceFrac = TraceLineSimple( grunt.GetOrigin(), traceEnd, grunt ) + return traceFrac > CHATTER_NEARBY_GRUNT_TRACEFRAC_MIN +} + +array function GetNearbyFriendlyHumanGrunts( vector searchOrigin, int friendlyTeam, float ornull searchRange = null ) +{ + array nearbyGrunts = GetNearbyFriendlyGrunts( searchOrigin, friendlyTeam, searchRange ) + array humanGrunts = [] + foreach ( grunt in nearbyGrunts ) + { + if ( grunt.IsMechanical() ) + continue + + humanGrunts.append( grunt ) + } + + return humanGrunts +} + +array function GetNearbyEnemyHumanGrunts( vector searchOrigin, int enemyTeam, float ornull searchRange = null ) +{ + array nearbyGrunts = GetNearbyEnemyGrunts( searchOrigin, enemyTeam, searchRange ) + array humanGrunts = [] + foreach ( grunt in nearbyGrunts ) + { + if ( grunt.IsMechanical() ) + continue + + humanGrunts.append( grunt ) + } + + return humanGrunts +} + +bool function GruntChatter_CanGruntChatterNow( entity grunt ) +{ + if ( !IsAlive( grunt ) ) + return false + + if ( !GruntChatter_IsGruntTypeEligibleForChatter( grunt ) ) + return false + + if ( grunt.ContextAction_IsMeleeExecution() ) + return false + + string squadname = expect string( grunt.kv.squadname ) + // we only care about this because the grunt conversation system wants it + return squadname != "" +} + +bool function GruntChatter_IsGruntTypeEligibleForChatter( entity grunt ) +{ + if ( !IsGrunt( grunt ) ) + return false + + // mechanical grunts don't chatter + return !grunt.IsMechanical() } \ No newline at end of file From 70c599a345bf5be16ae76d98de2943ee388e6d07 Mon Sep 17 00:00:00 2001 From: GeckoEidechse <40122905+GeckoEidechse@users.noreply.github.com> Date: Tue, 10 Oct 2023 15:04:47 +0200 Subject: [PATCH 06/25] Use string convar flags (#740) Uses string names for convars (been supported since refactor but not yet used) rather than magic numbers Co-authored-by: BobTheBob <32057864+BobTheBob9@users.noreply.github.com> --- Northstar.Client/mod.json | 4 ++-- Northstar.CustomServers/mod.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Northstar.Client/mod.json b/Northstar.Client/mod.json index f7c7c9b5b..a22f49fdf 100644 --- a/Northstar.Client/mod.json +++ b/Northstar.Client/mod.json @@ -36,12 +36,12 @@ { "Name": "modlist_show_convars", "DefaultValue": "0", - "Flags": 16777216 + "Flags": "ARCHIVE_PLAYERPROFILE" }, { "Name": "modlist_reverse", "DefaultValue": "0", - "Flags": 16777216 + "Flags": "ARCHIVE_PLAYERPROFILE" } ], "Scripts": [ diff --git a/Northstar.CustomServers/mod.json b/Northstar.CustomServers/mod.json index e6f2c4b7a..de3fcd0d1 100644 --- a/Northstar.CustomServers/mod.json +++ b/Northstar.CustomServers/mod.json @@ -20,7 +20,7 @@ { "Name": "ns_allow_spectators", "DefaultValue": "0", - "Flags": 8192 + "Flags": "REPLICATED" }, { "Name": "ns_private_match_last_mode", From add7305318b6fc1fe74389c60c352a19bddd7748 Mon Sep 17 00:00:00 2001 From: BobTheBob <32057864+BobTheBob9@users.noreply.github.com> Date: Tue, 10 Oct 2023 16:41:48 +0100 Subject: [PATCH 07/25] Remove unnecessary convars (#530) Removes some convars we don't need at all --- .../mod/scripts/vscripts/ui/menu_lobby.nut | 45 +++++-------------- .../scripts/vscripts/ui/menu_mode_select.nut | 18 +++----- .../vscripts/ui/menu_private_match.nut | 19 +------- .../mod/scripts/vscripts/ui/openinvites.nut | 5 ++- .../scripts/vscripts/ui/panel_mainmenu.nut | 2 - Northstar.CustomServers/mod.json | 9 ---- .../scripts/vscripts/sh_northstar_utils.gnut | 6 --- 7 files changed, 22 insertions(+), 82 deletions(-) diff --git a/Northstar.Client/mod/scripts/vscripts/ui/menu_lobby.nut b/Northstar.Client/mod/scripts/vscripts/ui/menu_lobby.nut index e4cc56874..23dae99d5 100644 --- a/Northstar.Client/mod/scripts/vscripts/ui/menu_lobby.nut +++ b/Northstar.Client/mod/scripts/vscripts/ui/menu_lobby.nut @@ -288,44 +288,21 @@ void function SetupComboButtonTest( var menu ) int buttonIndex = 0 file.playHeader = AddComboButtonHeader( comboStruct, headerIndex, "#MENU_HEADER_PLAY" ) - bool isModded = IsNorthstarServer() - - - // this will be the server browser - if ( isModded ) - { - file.findGameButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#MENU_TITLE_SERVER_BROWSER" ) - file.lobbyButtons.append( file.findGameButton ) - Hud_SetLocked( file.findGameButton, true ) - Hud_AddEventHandler( file.findGameButton, UIE_CLICK, OpenServerBrowser ) - } - else - { - file.findGameButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#MENU_TITLE_FIND_GAME" ) - file.lobbyButtons.append( file.findGameButton ) - Hud_AddEventHandler( file.findGameButton, UIE_CLICK, BigPlayButton1_Activate ) - } + // server browser + file.findGameButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#MENU_TITLE_SERVER_BROWSER" ) + file.lobbyButtons.append( file.findGameButton ) + Hud_SetLocked( file.findGameButton, true ) + Hud_AddEventHandler( file.findGameButton, UIE_CLICK, OpenServerBrowser ) - // this is used for launching private matches now - if ( isModded ) - { - file.inviteRoomButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#PRIVATE_MATCH" ) - Hud_AddEventHandler( file.inviteRoomButton, UIE_CLICK, StartPrivateMatch ) - } - else - { - file.inviteRoomButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#MENU_TITLE_INVITE_ROOM" ) - Hud_AddEventHandler( file.inviteRoomButton, UIE_CLICK, DoRoomInviteIfAllowed ) - } + // private match + file.inviteRoomButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#PRIVATE_MATCH" ) + Hud_AddEventHandler( file.inviteRoomButton, UIE_CLICK, StartPrivateMatch ) file.inviteFriendsButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#MENU_TITLE_INVITE_FRIENDS" ) Hud_AddEventHandler( file.inviteFriendsButton, UIE_CLICK, InviteFriendsIfAllowed ) - - if ( isModded ) - { - Hud_SetEnabled( file.inviteFriendsButton, false ) - Hud_SetVisible( file.inviteFriendsButton, false ) - } + + Hud_SetEnabled( file.inviteFriendsButton, false ) + Hud_SetVisible( file.inviteFriendsButton, false ) // file.toggleMenuModeButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#MENU_LOBBY_SWITCH_FD" ) // Hud_AddEventHandler( file.toggleMenuModeButton, UIE_CLICK, ToggleLobbyMode ) diff --git a/Northstar.Client/mod/scripts/vscripts/ui/menu_mode_select.nut b/Northstar.Client/mod/scripts/vscripts/ui/menu_mode_select.nut index 52a99b6fe..605af3832 100644 --- a/Northstar.Client/mod/scripts/vscripts/ui/menu_mode_select.nut +++ b/Northstar.Client/mod/scripts/vscripts/ui/menu_mode_select.nut @@ -18,8 +18,8 @@ void function InitModesMenu() AddMenuFooterOption( menu, BUTTON_A, "#A_BUTTON_SELECT" ) AddMenuFooterOption( menu, BUTTON_B, "#B_BUTTON_BACK", "#BACK" ) - AddMenuFooterOption( menu, BUTTON_SHOULDER_LEFT, "#PRIVATE_MATCH_PAGE_PREV", "#PRIVATE_MATCH_PAGE_PREV", CycleModesBack, IsNorthstarServer ) - AddMenuFooterOption( menu, BUTTON_SHOULDER_RIGHT, "#PRIVATE_MATCH_PAGE_NEXT", "#PRIVATE_MATCH_PAGE_NEXT", CycleModesForward, IsNorthstarServer ) + AddMenuFooterOption( menu, BUTTON_SHOULDER_LEFT, "#PRIVATE_MATCH_PAGE_PREV", "#PRIVATE_MATCH_PAGE_PREV", CycleModesBack ) + AddMenuFooterOption( menu, BUTTON_SHOULDER_RIGHT, "#PRIVATE_MATCH_PAGE_NEXT", "#PRIVATE_MATCH_PAGE_NEXT", CycleModesForward ) } void function OnOpenModesMenu() @@ -56,13 +56,7 @@ void function UpdateVisibleModes() if ( !ModeSettings_RequiresAI( modesArray[ modeIndex ] ) || modesArray[ modeIndex ] == "aitdm" || modesArray[ modeIndex ] == "at" ) Hud_SetLocked( buttons[ i ], false ) else - Hud_SetLocked( buttons[ i ], true ) - - if ( !PrivateMatch_IsValidMapModeCombo( PrivateMatch_GetSelectedMap(), modesArray[ modeIndex ] ) && !IsNorthstarServer() ) - { - Hud_SetLocked( buttons[ i ], true ) - SetButtonRuiText( buttons[ i ], Localize( "#PRIVATE_MATCH_UNAVAILABLE", Localize( GetGameModeDisplayName( modesArray[ modeIndex ] ) ) ) ) - } + Hud_SetLocked( buttons[ i ], true ) } } @@ -90,9 +84,7 @@ void function ModeButton_GetFocus( var button ) string mapName = PrivateMatch_GetSelectedMap() bool mapSupportsMode = PrivateMatch_IsValidMapModeCombo( mapName, modeName ) - if ( !mapSupportsMode && !IsNorthstarServer() ) - Hud_SetText( nextModeDesc, Localize( "#PRIVATE_MATCH_MODE_NO_MAP_SUPPORT", Localize( GetGameModeDisplayName( modeName ) ), Localize( GetMapDisplayName( mapName ) ) ) ) - else if ( IsFDMode( modeName ) ) // HACK! + if ( IsFDMode( modeName ) ) // HACK! Hud_SetText( nextModeDesc, Localize( "#FD_PLAYERS_DESC", Localize( GetGameModeDisplayHint( modeName ) ) ) ) else Hud_SetText( nextModeDesc, GetGameModeDisplayHint( modeName ) ) @@ -114,7 +106,7 @@ void function ModeButton_Click( var button ) // on modded servers set us to the first map for that mode automatically // need this for coliseum mainly which is literally impossible to select without this - if ( IsNorthstarServer() && !PrivateMatch_IsValidMapModeCombo( PrivateMatch_GetSelectedMap(), modesArray[ modeID ] ) ) + if ( !PrivateMatch_IsValidMapModeCombo( PrivateMatch_GetSelectedMap(), modesArray[ modeID ] ) ) ClientCommand( "SetCustomMap " + GetPrivateMatchMapsForMode( modeName )[ 0 ] ) // set it diff --git a/Northstar.Client/mod/scripts/vscripts/ui/menu_private_match.nut b/Northstar.Client/mod/scripts/vscripts/ui/menu_private_match.nut index d7c7442f4..e3c1f268e 100644 --- a/Northstar.Client/mod/scripts/vscripts/ui/menu_private_match.nut +++ b/Northstar.Client/mod/scripts/vscripts/ui/menu_private_match.nut @@ -247,10 +247,7 @@ void function OnSelectMatchSettings_Activate( var button ) if ( Hud_IsLocked( button ) ) return - if ( !IsNorthstarServer() ) - AdvanceMenu( GetMenu( "MatchSettingsMenu" ) ) - else - AdvanceMenu( GetMenu( "CustomMatchSettingsCategoryMenu" ) ) + AdvanceMenu( GetMenu( "CustomMatchSettingsCategoryMenu" ) ) } void function SetupComboButtons( var menu, var navUpButton, var navDownButton ) @@ -274,13 +271,6 @@ void function SetupComboButtons( var menu, var navUpButton, var navDownButton ) file.matchSettingsButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#MENU_TITLE_MATCH_SETTINGS" ) Hud_AddEventHandler( file.matchSettingsButton, UIE_CLICK, OnSelectMatchSettings_Activate ) - if ( !IsNorthstarServer() ) - { - var friendsButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#MENU_TITLE_INVITE_FRIENDS" ) - file.inviteFriendsButton = friendsButton - Hud_AddEventHandler( friendsButton, UIE_CLICK, InviteFriendsIfAllowed ) - } - headerIndex++ buttonIndex = 0 file.customizeHeader = AddComboButtonHeader( comboStruct, headerIndex, "#MENU_HEADER_LOADOUTS" ) @@ -575,17 +565,12 @@ function UpdatePrivateMatchButtons() Hud_SetLocked( file.selectMapButton, true ) Hud_SetLocked( file.selectModeButton, true ) Hud_SetLocked( file.matchSettingsButton, true ) - - if ( !IsNorthstarServer() ) - Hud_SetLocked( file.inviteFriendsButton, true ) } else { RHud_SetText( file.startMatchButton, "#START_MATCH" ) Hud_SetLocked( file.selectMapButton, false ) Hud_SetLocked( file.selectModeButton, false ) - if ( !IsNorthstarServer() ) - Hud_SetLocked( file.inviteFriendsButton, false ) string modeName = PrivateMatch_GetSelectedMode() bool settingsLocked = IsFDMode( modeName ) @@ -648,7 +633,7 @@ function UpdateLobby() { float varOrigVal = float( GetCurrentPlaylistGamemodeByIndexVar( gamemodeIdx, varName, false ) ) float varOverrideVal = float( GetCurrentPlaylistGamemodeByIndexVar( gamemodeIdx, varName, true ) ) - if ( varOrigVal == varOverrideVal && !IsNorthstarServer() ) // stuff seems to break outside of northstar servers since we dont always use private_match playlist + if ( varOrigVal == varOverrideVal ) // stuff seems to break outside of northstar servers since we dont always use private_match playlist continue string label = Localize( MatchSettings_PlaylistVarLabels[varName] ) + ": " diff --git a/Northstar.Client/mod/scripts/vscripts/ui/openinvites.nut b/Northstar.Client/mod/scripts/vscripts/ui/openinvites.nut index 4b3d0f55e..f91231b6b 100644 --- a/Northstar.Client/mod/scripts/vscripts/ui/openinvites.nut +++ b/Northstar.Client/mod/scripts/vscripts/ui/openinvites.nut @@ -202,7 +202,10 @@ void function UpdateOpenInvite_Thread() void function UICodeCallback_OpenInviteUpdated() { - if ( file.openInviteVisible || IsNorthstarServer() ) + // don't support on northstar + return + + if ( file.openInviteVisible ) return int currentPartySize = GetPartySize() diff --git a/Northstar.Client/mod/scripts/vscripts/ui/panel_mainmenu.nut b/Northstar.Client/mod/scripts/vscripts/ui/panel_mainmenu.nut index eef19b5ee..c97c8cdce 100644 --- a/Northstar.Client/mod/scripts/vscripts/ui/panel_mainmenu.nut +++ b/Northstar.Client/mod/scripts/vscripts/ui/panel_mainmenu.nut @@ -531,7 +531,6 @@ void function OnPlayFDButton_Activate( var button ) // repurposed for launching { if ( !Hud_IsLocked( button ) ) { - SetConVarBool( "ns_is_modded_server", true ) SetConVarString( "communities_hostname", "" ) // disable communities due to crash exploits that are still possible through it NSTryAuthWithLocalServer() thread TryAuthWithLocalServer() @@ -601,7 +600,6 @@ void function OnPlayMPButton_Activate( var button ) { Lobby_SetAutoFDOpen( false ) // Lobby_SetFDMode( false ) - SetConVarBool( "ns_is_modded_server", false ) thread file.mpButtonActivateFunc() } } diff --git a/Northstar.CustomServers/mod.json b/Northstar.CustomServers/mod.json index de3fcd0d1..fa51f4d41 100644 --- a/Northstar.CustomServers/mod.json +++ b/Northstar.CustomServers/mod.json @@ -4,15 +4,6 @@ "Version": "1.19.0", "LoadPriority": 0, "ConVars": [ - { - "Name": "ns_lobby_type", - "DefaultValue": "0" - }, - { - "Name": "ns_is_modded_server", - "DefaultValue": "1", - "Flags": 8192 - }, { "Name": "ns_should_return_to_lobby", "DefaultValue": "1" diff --git a/Northstar.CustomServers/mod/scripts/vscripts/sh_northstar_utils.gnut b/Northstar.CustomServers/mod/scripts/vscripts/sh_northstar_utils.gnut index b26e48ca0..f8597744f 100644 --- a/Northstar.CustomServers/mod/scripts/vscripts/sh_northstar_utils.gnut +++ b/Northstar.CustomServers/mod/scripts/vscripts/sh_northstar_utils.gnut @@ -1,11 +1,5 @@ globalize_all_functions -// whether the server is a modded, northstar server -bool function IsNorthstarServer() -{ - return GetConVarBool( "ns_is_modded_server" ) -} - // whether the game should return to the lobby on GameRules_EndMatch() bool function ShouldReturnToLobby() { From 3714f23edde5a48aa29560dc74fc5a59ce2ca85a Mon Sep 17 00:00:00 2001 From: Jack <66967891+ASpoonPlaysGames@users.noreply.github.com> Date: Wed, 11 Oct 2023 21:57:00 +0100 Subject: [PATCH 08/25] Fix `StringReplace` looping forever when replacing character when replacing same character as match (#736) Find the next replacement starting from the end of the last one, instead of from the start of the string --- .../mod/scripts/vscripts/sh_utility_all.gnut | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Northstar.CustomServers/mod/scripts/vscripts/sh_utility_all.gnut b/Northstar.CustomServers/mod/scripts/vscripts/sh_utility_all.gnut index a2de99136..9e7629858 100644 --- a/Northstar.CustomServers/mod/scripts/vscripts/sh_utility_all.gnut +++ b/Northstar.CustomServers/mod/scripts/vscripts/sh_utility_all.gnut @@ -362,7 +362,7 @@ string function StringReplace( string baseString, string searchString, string re source = part1 + replaceString + part2 loopedOnce = true - findResult = source.find( searchString ) + findResult = source.find( searchString, findResult + replaceString.len() ) } return baseString From bdb2fa3ca291101dc861d19e8979077bf8fdf57a Mon Sep 17 00:00:00 2001 From: William Miller Date: Wed, 11 Oct 2023 18:00:11 -0300 Subject: [PATCH 09/25] Unlock paid items with progression enabled (#726) When turning on progression now, items that should be purchased from the store will remain unlocked. These items contain among others the prime versions of the various Titans. Some mods make explicit use of prime Titans to switch to alternate loadouts (Brute, Archon, ...) Some players would like to opt into progression but decide against it due to losing access to prime Titans As such we should keep them unlocked, even when progression is enabled as they cannot be obtained through progression alone anyway. --- .../mod/scripts/vscripts/_items.nut | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Northstar.CustomServers/mod/scripts/vscripts/_items.nut b/Northstar.CustomServers/mod/scripts/vscripts/_items.nut index 5878da134..a5c3e2709 100644 --- a/Northstar.CustomServers/mod/scripts/vscripts/_items.nut +++ b/Northstar.CustomServers/mod/scripts/vscripts/_items.nut @@ -5700,6 +5700,12 @@ bool function IsSubItemLocked( entity player, string ref, string parentRef ) { if ( DevEverythingUnlocked( player ) ) return false + + if ( IsItemPurchasableEntitlement( ref, parentRef ) ) + return false + + if ( GetItemType( ref ) == eItemTypes.PRIME_TITAN || GetSubitemType( parentRef, ref ) == eItemTypes.PRIME_TITAN ) + return false if ( IsItemInEntitlementUnlock( ref, parentRef ) ) { @@ -5819,6 +5825,12 @@ bool function IsItemLocked( entity player, string ref ) { if ( DevEverythingUnlocked( player ) ) return false + + if ( IsItemPurchasableEntitlement( ref ) ) + return false + + if ( GetItemType( ref ) == eItemTypes.PRIME_TITAN ) + return false if ( IsItemInEntitlementUnlock( ref ) ) { From 7893a11faa5a9f3d13b241b1269b169ae8c519d3 Mon Sep 17 00:00:00 2001 From: Respawn Date: Thu, 12 Oct 2023 02:22:29 +0200 Subject: [PATCH 10/25] Add menu_edit_pilot_loadouts.nut from englishclient_frontend --- .../vscripts/ui/menu_edit_pilot_loadouts.nut | 165 ++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 Northstar.Client/mod/scripts/vscripts/ui/menu_edit_pilot_loadouts.nut diff --git a/Northstar.Client/mod/scripts/vscripts/ui/menu_edit_pilot_loadouts.nut b/Northstar.Client/mod/scripts/vscripts/ui/menu_edit_pilot_loadouts.nut new file mode 100644 index 000000000..e785b067f --- /dev/null +++ b/Northstar.Client/mod/scripts/vscripts/ui/menu_edit_pilot_loadouts.nut @@ -0,0 +1,165 @@ +untyped + +global function InitEditPilotLoadoutsMenu + +struct +{ + var menu + var loadoutPanel + var[NUM_PERSISTENT_PILOT_LOADOUTS] loadoutHeaders + var[NUM_PERSISTENT_PILOT_LOADOUTS] activateButtons + bool enteringEdit = false + var unlockReq +} file + +void function InitEditPilotLoadoutsMenu() +{ + file.menu = GetMenu( "EditPilotLoadoutsMenu" ) + var menu = file.menu + + AddMenuEventHandler( menu, eUIEvent.MENU_OPEN, OnPilotLoadoutsMenu_Open ) + AddMenuEventHandler( menu, eUIEvent.MENU_CLOSE, OnPilotLoadoutsMenu_Close ) + AddMenuEventHandler( menu, eUIEvent.MENU_INPUT_MODE_CHANGED, OnPilotLoadoutsMenu_InputModeChanged ) + + for ( int i = 0; i < NUM_PERSISTENT_PILOT_LOADOUTS; i++ ) + { + var activateButton = Hud_GetChild( menu, "Button" + i ) + activateButton.s.rowIndex <- i + Hud_SetVisible( activateButton, true ) + Hud_AddEventHandler( activateButton, UIE_CLICK, OnLoadoutButton_Activate ) + Hud_AddEventHandler( activateButton, UIE_GET_FOCUS, OnLoadoutButton_Focused ) + Hud_AddEventHandler( activateButton, UIE_LOSE_FOCUS, OnLoadoutButton_LostFocus ) + file.activateButtons[i] = activateButton + } + + Hud_SetFocused( file.activateButtons[0] ) + + file.loadoutPanel = Hud_GetChild( menu, "PilotLoadoutDisplay" ) + file.unlockReq = Hud_GetChild( menu, "UnlockReq" ) + + AddMenuFooterOption( menu, BUTTON_A, "#A_BUTTON_SELECT" ) + AddMenuFooterOption( menu, BUTTON_B, "#B_BUTTON_BACK", "#BACK" ) +} + +void function OnPilotLoadoutsMenu_Open() +{ + entity player = GetUIPlayer() + if ( player == null ) + return + + RunMenuClientFunction( "ClearEditingPilotLoadoutIndex" ) + + int loadoutIndex = uiGlobal.pilotSpawnLoadoutIndex + UpdatePilotLoadoutButtons( loadoutIndex, file.activateButtons ) + UpdatePilotLoadoutPanel( file.loadoutPanel, GetCachedPilotLoadout( loadoutIndex ) ) + UI_SetPresentationType( ePresentationType.PILOT ) + + RefreshCreditsAvailable() +} + +void function OnPilotLoadoutsMenu_Close() +{ + entity player = GetUIPlayer() + if ( player == null ) + return + + foreach ( i, button in file.activateButtons ) + { + string pilotLoadoutRef = "pilot_loadout_" + ( i + 1 ) + if ( !IsItemNew( player, pilotLoadoutRef ) ) + continue + + ClearNewStatus( button, pilotLoadoutRef ) + } +} + +void function OnPilotLoadoutsMenu_InputModeChanged() +{ + UpdatePilotLoadoutPanelBinds( file.loadoutPanel ) +} + +void function OnLoadoutButton_Focused( var button ) +{ + int index = expect int( button.s.rowIndex ) + + UpdatePilotLoadout( index ) + + string pilotLoadoutRef = "pilot_loadout_" + ( index + 1 ) + string unlockReq = GetItemUnlockReqText( pilotLoadoutRef ) + RHud_SetText( file.unlockReq, unlockReq ) +} + +void function UpdatePilotLoadout( int loadoutIndex ) +{ + PilotLoadoutDef loadout = GetCachedPilotLoadout( loadoutIndex ) + + UpdatePilotLoadoutPanel( file.loadoutPanel, loadout ) + RunMenuClientFunction( "UpdatePilotModel", loadoutIndex ) +} + +void function OnLoadoutButton_Activate( var button ) +{ + if ( !IsFullyConnected() ) + return + + if ( Hud_IsLocked( button ) ) + { + int index = expect int ( button.s.rowIndex ) + string pilotLoadoutRef = "pilot_loadout_" + ( index + 1 ) + + array buttons + foreach ( button in file.activateButtons ) + { + buttons.append( button ) + } + + OpenBuyItemDialog( buttons, button, GetItemName( pilotLoadoutRef ), pilotLoadoutRef ) + return + } + + int loadoutIndex = expect int ( button.s.rowIndex ) + SetEditLoadout( "pilot", loadoutIndex ) + + if ( EDIT_LOADOUT_SELECTS ) + { + bool indexChanged = loadoutIndex != uiGlobal.pilotSpawnLoadoutIndex + + if ( indexChanged ) + { + EmitUISound( "Menu_LoadOut_Pilot_Select" ) + + if ( !IsLobby() ) + uiGlobal.updatePilotSpawnLoadout = true + } + + uiGlobal.pilotSpawnLoadoutIndex = loadoutIndex + ClientCommand( "RequestPilotLoadout " + loadoutIndex ) + } + + if ( PRE_RELEASE_DEMO && loadoutIndex < 3 ) + { + UpdatePilotLoadoutButtons( loadoutIndex, file.activateButtons ) + return + } + + RunMenuClientFunction( "SetEditingPilotLoadoutIndex", loadoutIndex ) + AdvanceMenu( GetMenu( "EditPilotLoadoutMenu" ) ) +} + +void function OnLoadoutButton_LostFocus( var button ) +{ + entity player = GetUIPlayer() + if ( !IsValid( player ) ) + return + + int loadoutIndex = expect int ( button.s.rowIndex ) + string pilotLoadoutRef = "pilot_loadout_" + ( loadoutIndex + 1 ) + ClearNewStatus( button, pilotLoadoutRef ) + + if ( IsItemLocked( player, pilotLoadoutRef ) ) + return + + PilotLoadoutDef loadout = GetCachedPilotLoadout( loadoutIndex ) + if ( (RefHasAnyNewSubitem( player, loadout.primary ) || RefHasAnyNewSubitem( player, loadout.secondary ) || RefHasAnyNewSubitem( player, loadout.weapon3 )) ) + Hud_SetNew( button, true ) +} From c2716db187ce1e896031ac75e097f96754dc92cf Mon Sep 17 00:00:00 2001 From: Respawn Date: Thu, 12 Oct 2023 02:23:02 +0200 Subject: [PATCH 11/25] Add menu_pilot_loadouts_shared.nut from englishclient_frontend --- .../ui/menu_pilot_loadouts_shared.nut | 284 ++++++++++++++++++ 1 file changed, 284 insertions(+) create mode 100644 Northstar.Client/mod/scripts/vscripts/ui/menu_pilot_loadouts_shared.nut diff --git a/Northstar.Client/mod/scripts/vscripts/ui/menu_pilot_loadouts_shared.nut b/Northstar.Client/mod/scripts/vscripts/ui/menu_pilot_loadouts_shared.nut new file mode 100644 index 000000000..122403a38 --- /dev/null +++ b/Northstar.Client/mod/scripts/vscripts/ui/menu_pilot_loadouts_shared.nut @@ -0,0 +1,284 @@ + +global function UpdatePilotLoadoutPanel +global function UpdatePilotLoadoutPanelBinds +global function UpdatePilotLoadoutButtons +global function UpdatePilotItemButton + +void function UpdatePilotLoadoutButtons( int selectedIndex, var[NUM_PERSISTENT_PILOT_LOADOUTS] buttons, bool focusSelected = true ) +{ + entity player = GetUIPlayer() + if ( player == null ) + return + + int numLoadouts = GetAllCachedPilotLoadouts().len() + + // HACK: num_pilot_loadouts is just used to disable certain loadouts for FNF + int numLoadoutsForPlaylist = GetCurrentPlaylistVarInt( "num_pilot_loadouts", 0 ) + if ( numLoadoutsForPlaylist > 0 ) + numLoadouts = numLoadoutsForPlaylist + + foreach ( index, button in buttons ) + { + PilotLoadoutDef loadout = GetCachedPilotLoadout( index ) + RHud_SetText( button, GetPilotLoadoutName( loadout ) ) + Hud_SetPanelAlpha( button, 0 ) + + bool isSelected = ( index == selectedIndex ) ? true : false + Hud_SetSelected( button, isSelected ) + + string pilotLoadoutRef = "pilot_loadout_" + ( index + 1 ) + Hud_SetLocked( button, IsItemLocked( player, pilotLoadoutRef ) ) + + bool shouldShowNew = ButtonShouldShowNew( eItemTypes.FEATURE, pilotLoadoutRef ) + if ( !shouldShowNew && (RefHasAnyNewSubitem( player, loadout.primary ) || RefHasAnyNewSubitem( player, loadout.secondary ) || RefHasAnyNewSubitem( player, loadout.weapon3 )) ) + shouldShowNew = true + + if ( IsItemLocked( player, pilotLoadoutRef ) ) + shouldShowNew = false + + Hud_SetNew( button, shouldShowNew ) + + RefreshButtonCost( button, pilotLoadoutRef ) + } + + if ( focusSelected ) + Hud_SetFocused( buttons[ selectedIndex ] ) +} + +void function UpdatePilotLoadoutPanel( var loadoutPanel, PilotLoadoutDef loadout ) +{ + SetLabelRuiText( Hud_GetChild( loadoutPanel, "TacticalName" ), Localize( GetItemName( loadout.special ) ) ) + SetLabelRuiText( Hud_GetChild( loadoutPanel, "PrimaryName" ), Localize( GetItemName( loadout.primary ) ) ) + SetLabelRuiText( Hud_GetChild( loadoutPanel, "SecondaryName" ), Localize( GetItemName( loadout.secondary ) ) ) + SetLabelRuiText( Hud_GetChild( loadoutPanel, "Weapon3Name" ), Localize( GetItemName( loadout.weapon3 ) ) ) + SetLabelRuiText( Hud_GetChild( loadoutPanel, "OrdnanceName" ), Localize( GetItemName( loadout.ordnance ) ) ) + SetLabelRuiText( Hud_GetChild( loadoutPanel, "Kit1Name" ), Localize( GetItemName( loadout.passive1 ) ) ) + SetLabelRuiText( Hud_GetChild( loadoutPanel, "Kit2Name" ), Localize( GetItemName( loadout.passive2 ) ) ) + SetLabelRuiText( Hud_GetChild( loadoutPanel, "ExecutionName" ), Localize( GetItemName( loadout.execution ) ) ) + + UpdatePilotLoadoutPanelBinds( loadoutPanel ) + + var menu = Hud_GetParent( loadoutPanel ) + array buttons = GetElementsByClassname( menu, "PilotLoadoutPanelButtonClass" ) + + /*if ( button ) + { + // TEMP disabled since Hud_GetChild( menu, "ButtonTooltip" ) will fail + //if ( HandleLockedMenuItem( menu, button ) ) + // return + }*/ + bool isEdit + if ( Hud_GetHudName( loadoutPanel ) == "PilotLoadoutButtons" ) // Edit menu + isEdit = true + else // Select menu + isEdit = false + + foreach ( button in buttons ) + UpdatePilotItemButton( button, loadout, isEdit ) + + var renameEditBox = Hud_GetChild( loadoutPanel, "RenameEditBox" ) + + asset pilotAppearanceImage = loadout.camoIndex > 0 ? CamoSkin_GetImage( CamoSkins_GetByIndex( loadout.camoIndex ) ) : $"rui/menu/common/appearance_button_swatch" + + asset primaryAppearanceImage + if ( loadout.primarySkinIndex == 0 ) // default skin + primaryAppearanceImage = $"rui/menu/common/appearance_button_swatch" + else if ( loadout.primarySkinIndex == 1 ) // camo + primaryAppearanceImage = CamoSkin_GetImage( CamoSkins_GetByIndex( loadout.primaryCamoIndex ) ) + else // warpaint skin + primaryAppearanceImage = GetItemImage( GetSkinRefFromWeaponRefAndPersistenceValue( loadout.primary, loadout.primarySkinIndex ) ) + + asset secondaryAppearanceImage + if ( loadout.secondarySkinIndex == 0 ) // default skin + secondaryAppearanceImage = $"rui/menu/common/appearance_button_swatch" + else if ( loadout.secondarySkinIndex == 1 ) // camo + secondaryAppearanceImage = CamoSkin_GetImage( CamoSkins_GetByIndex( loadout.secondaryCamoIndex ) ) + else // warpaint skin + secondaryAppearanceImage = GetItemImage( GetSkinRefFromWeaponRefAndPersistenceValue( loadout.secondary, loadout.secondarySkinIndex ) ) + + asset weapon3AppearanceImage + if ( loadout.weapon3SkinIndex == 0 ) // default skin + weapon3AppearanceImage = $"rui/menu/common/appearance_button_swatch" + else if ( loadout.weapon3SkinIndex == 1 ) // camo + weapon3AppearanceImage = CamoSkin_GetImage( CamoSkins_GetByIndex( loadout.weapon3CamoIndex ) ) + else // warpaint skin + weapon3AppearanceImage = GetItemImage( GetSkinRefFromWeaponRefAndPersistenceValue( loadout.weapon3, loadout.weapon3SkinIndex ) ) + + RuiSetImage( Hud_GetRui( Hud_GetChild( loadoutPanel, "ButtonPilotCamo" ) ), "camoImage", pilotAppearanceImage ) + RuiSetImage( Hud_GetRui( Hud_GetChild( loadoutPanel, "ButtonPrimarySkin" ) ), "camoImage", primaryAppearanceImage ) + RuiSetImage( Hud_GetRui( Hud_GetChild( loadoutPanel, "ButtonSecondarySkin" ) ), "camoImage", secondaryAppearanceImage ) + RuiSetImage( Hud_GetRui( Hud_GetChild( loadoutPanel, "ButtonWeapon3Skin" ) ), "camoImage", weapon3AppearanceImage ) + + array nonItemElements + nonItemElements.append( Hud_GetChild( loadoutPanel, "ButtonPilotCamo" ) ) + nonItemElements.append( Hud_GetChild( loadoutPanel, "ButtonGender" ) ) + nonItemElements.append( Hud_GetChild( loadoutPanel, "ButtonPrimarySkin" ) ) + nonItemElements.append( Hud_GetChild( loadoutPanel, "ButtonSecondarySkin" ) ) + nonItemElements.append( Hud_GetChild( loadoutPanel, "ButtonWeapon3Skin" ) ) + nonItemElements.append( renameEditBox ) + + foreach ( elem in nonItemElements ) + { + if ( isEdit ) + Hud_Show( elem ) + else + Hud_Hide( elem ) + } + Hud_SetEnabled( renameEditBox, isEdit ) +} + +void function UpdatePilotItemButton( var button, PilotLoadoutDef loadout, bool isEdit ) +{ + string propertyName = Hud_GetScriptID( button ) + string itemRef = GetPilotLoadoutValue( loadout, propertyName ) + int itemType = GetItemTypeFromPilotLoadoutProperty( propertyName ) + asset image + + ItemDisplayData parentItem + + if ( itemType == eItemTypes.PILOT_PRIMARY_ATTACHMENT || itemType == eItemTypes.PILOT_PRIMARY_MOD || itemType == eItemTypes.PILOT_SECONDARY_MOD || itemType == eItemTypes.PILOT_WEAPON_MOD3 ) + { + string parentProperty = GetParentLoadoutProperty( "pilot", propertyName ) + Assert( parentProperty == "primary" || parentProperty == "secondary" || parentProperty == "weapon3" ) + + if ( parentProperty == "primary" ) + parentItem = GetItemDisplayData( loadout.primary ) + else if ( parentProperty == "secondary" ) + parentItem = GetItemDisplayData( loadout.secondary ) + else + parentItem = GetItemDisplayData( loadout.weapon3 ) + + bool isHiddenAttachment = false + + if ( itemType == eItemTypes.PILOT_PRIMARY_ATTACHMENT ) + { + // Disable attachment option for "special" primary weapons + if ( "menuCategory" in parentItem.i && ( expect int( parentItem.i.menuCategory ) == ePrimaryWeaponCategory.SPECIAL || expect int( parentItem.i.menuCategory ) == ePrimaryWeaponCategory.HANDGUN ) ) + { + isHiddenAttachment = true + + Hud_SetWidth( button, 0 ) + Hud_SetPos( button, 0, 0 ) // Clear sibling offset + } + else + { + int defaultButtonWidth = int( ContentScaledX( 72 ) ) + int defaultOffsetX = int( ContentScaledX( 6 ) ) + + Hud_SetWidth( button, defaultButtonWidth ) + Hud_SetPos( button, defaultOffsetX, 0 ) + } + } + + if ( !isHiddenAttachment ) + image = GetImage( itemType, parentItem.ref, itemRef ) + } + else + { + image = GetImage( itemType, itemRef ) + } + + if ( itemType == eItemTypes.PILOT_PRIMARY || itemType == eItemTypes.PILOT_SECONDARY ) + { + //if ( isEdit ) + //{ + // RuiSetString( Hud_GetRui( button ), "subText", "" ) + // RuiSetFloat( Hud_GetRui( button ), "numSegments", 0 ) + // RuiSetFloat( Hud_GetRui( button ), "filledSegments", 0 ) + //} + //else + { + int currentXP = WeaponGetXP( GetLocalClientPlayer(), itemRef ) + int numPips = WeaponGetNumPipsForXP( itemRef, currentXP ) + int filledPips = WeaponGetFilledPipsForXP( itemRef, currentXP ) + RuiSetString( Hud_GetRui( button ), "subText", WeaponGetDisplayGenAndLevelForXP( itemRef, currentXP ) ) + RuiSetFloat( Hud_GetRui( button ), "numSegments", float( numPips ) ) + RuiSetFloat( Hud_GetRui( button ), "filledSegments", float( filledPips ) ) + } + } + + var rui = Hud_GetRui( button ) + + if ( image == $"" ) + { + RuiSetBool( rui, "isVisible", false ) + Hud_SetEnabled( button, false ) + } + else + { + RuiSetBool( rui, "isVisible", true ) + RuiSetImage( rui, "buttonImage", image ) + + Hud_SetEnabled( button, true ) + } + + bool isLocked = false + bool shouldShowNew = false + + // For unlock and subitem checks below, treat weapon3 as secondary + if ( propertyName == "weapon3Mod1" ) + propertyName = "secondaryMod1" + else if ( propertyName == "weapon3Mod2" ) + propertyName = "secondaryMod2" + else if ( propertyName == "weapon3Mod3" ) + propertyName = "secondaryMod3" + + string propertyRef = propertyName.tolower() + + if ( !IsSubItemType( itemType ) ) + { + if ( IsUnlockValid( propertyRef ) && IsItemLocked( GetUIPlayer(), propertyRef ) ) + { + RefreshButtonCost( button, propertyRef ) + isLocked = true + } + shouldShowNew = ButtonShouldShowNew( itemType, itemRef ) + } + else + { + if ( IsUnlockValid( propertyRef, parentItem.ref ) && IsSubItemLocked( GetUIPlayer(), propertyRef, parentItem.ref ) ) + { + RefreshButtonCost( button, propertyRef ) + isLocked = true + } + shouldShowNew = ButtonShouldShowNew( itemType, itemRef, parentItem.ref ) + } + + Hud_SetLocked( button, isLocked ) + + if ( !shouldShowNew && IsUnlockValid( propertyRef, parentItem.ref ) ) + shouldShowNew = ButtonShouldShowNew( GetSubitemType( parentItem.ref, propertyRef ), propertyRef, parentItem.ref ) + Hud_SetNew( button, shouldShowNew ) + +#if HAS_THREAT_SCOPE_SLOT_LOCK + if ( propertyName == "primaryMod2" ) + { + string attatchmentRef = GetPilotLoadoutValue( loadout, "primaryAttachment" ) + if ( attatchmentRef == "threat_scope" ) + { + Hud_SetLocked( button, true ) + RefreshButtonCost( button, propertyRef, "", 0, 0 ) + Hud_SetNew( button, false ) + } + } +#endif +} + +void function UpdatePilotLoadoutPanelBinds( var loadoutPanel ) +{ + if ( IsControllerModeActive() ) + { + //SetLabelRuiText( Hud_GetChild( loadoutPanel, "PrimaryBind" ), "%weaponCycle%" ) + //SetLabelRuiText( Hud_GetChild( loadoutPanel, "SecondaryBind" ), "%weaponCycle%" ) + SetLabelRuiText( Hud_GetChild( loadoutPanel, "Weapon3Bind" ), Localize( "#WEAPON3_HOLD_HINT" ) ) + } + else + { + //SetLabelRuiText( Hud_GetChild( loadoutPanel, "PrimaryBind" ), "%weaponSelectPrimary0%" ) + //SetLabelRuiText( Hud_GetChild( loadoutPanel, "SecondaryBind" ), "%weaponSelectPrimary1%" ) + SetLabelRuiText( Hud_GetChild( loadoutPanel, "Weapon3Bind" ), Localize( "#WEAPON3_PRESS_HINT" ) ) + } + + //SetLabelRuiText( Hud_GetChild( loadoutPanel, "TacticalBind" ), Localize( "%offhand1%" ) ) + //SetLabelRuiText( Hud_GetChild( loadoutPanel, "OrdnanceBind" ), Localize( "%offhand0%" ) ) +} From 407c5ce39c3124658a869c387e4308e6b72e4c23 Mon Sep 17 00:00:00 2001 From: Jack <66967891+ASpoonPlaysGames@users.noreply.github.com> Date: Thu, 12 Oct 2023 01:29:31 +0100 Subject: [PATCH 12/25] Fix INVALID_REF errors caused by mods (#657) `INVALID_REF` errors were being caused by trying to get the item image for weapon skins. If a mod (e.g. moreskins) added new skins, the client equipped one, and then the mod is disabled, the client now has bad persistence. This is mostly handled fine by the game, except for weapon skins. This PR prevents the crash, and resets the bad persistence to default. --- .../vscripts/ui/menu_edit_pilot_loadouts.nut | 5 +++++ .../ui/menu_pilot_loadouts_shared.nut | 22 ++++++++++++++++--- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/Northstar.Client/mod/scripts/vscripts/ui/menu_edit_pilot_loadouts.nut b/Northstar.Client/mod/scripts/vscripts/ui/menu_edit_pilot_loadouts.nut index e785b067f..89479a76c 100644 --- a/Northstar.Client/mod/scripts/vscripts/ui/menu_edit_pilot_loadouts.nut +++ b/Northstar.Client/mod/scripts/vscripts/ui/menu_edit_pilot_loadouts.nut @@ -82,6 +82,11 @@ void function OnLoadoutButton_Focused( var button ) { int index = expect int( button.s.rowIndex ) + // update the editingLoadoutIndex on focus so that it always matches + // with the pilot loadout panel + uiGlobal.editingLoadoutIndex = index + uiGlobal.editingLoadoutType = "pilot" + UpdatePilotLoadout( index ) string pilotLoadoutRef = "pilot_loadout_" + ( index + 1 ) diff --git a/Northstar.Client/mod/scripts/vscripts/ui/menu_pilot_loadouts_shared.nut b/Northstar.Client/mod/scripts/vscripts/ui/menu_pilot_loadouts_shared.nut index 122403a38..f0139e04e 100644 --- a/Northstar.Client/mod/scripts/vscripts/ui/menu_pilot_loadouts_shared.nut +++ b/Northstar.Client/mod/scripts/vscripts/ui/menu_pilot_loadouts_shared.nut @@ -86,7 +86,7 @@ void function UpdatePilotLoadoutPanel( var loadoutPanel, PilotLoadoutDef loadout else if ( loadout.primarySkinIndex == 1 ) // camo primaryAppearanceImage = CamoSkin_GetImage( CamoSkins_GetByIndex( loadout.primaryCamoIndex ) ) else // warpaint skin - primaryAppearanceImage = GetItemImage( GetSkinRefFromWeaponRefAndPersistenceValue( loadout.primary, loadout.primarySkinIndex ) ) + primaryAppearanceImage = GetItemImageFromWeaponRefAndPersistenceValue( loadout.primary, loadout.primarySkinIndex, "primarySkinIndex" ) asset secondaryAppearanceImage if ( loadout.secondarySkinIndex == 0 ) // default skin @@ -94,7 +94,7 @@ void function UpdatePilotLoadoutPanel( var loadoutPanel, PilotLoadoutDef loadout else if ( loadout.secondarySkinIndex == 1 ) // camo secondaryAppearanceImage = CamoSkin_GetImage( CamoSkins_GetByIndex( loadout.secondaryCamoIndex ) ) else // warpaint skin - secondaryAppearanceImage = GetItemImage( GetSkinRefFromWeaponRefAndPersistenceValue( loadout.secondary, loadout.secondarySkinIndex ) ) + secondaryAppearanceImage = GetItemImageFromWeaponRefAndPersistenceValue( loadout.secondary, loadout.secondarySkinIndex, "secondarySkinIndex" ) asset weapon3AppearanceImage if ( loadout.weapon3SkinIndex == 0 ) // default skin @@ -102,7 +102,7 @@ void function UpdatePilotLoadoutPanel( var loadoutPanel, PilotLoadoutDef loadout else if ( loadout.weapon3SkinIndex == 1 ) // camo weapon3AppearanceImage = CamoSkin_GetImage( CamoSkins_GetByIndex( loadout.weapon3CamoIndex ) ) else // warpaint skin - weapon3AppearanceImage = GetItemImage( GetSkinRefFromWeaponRefAndPersistenceValue( loadout.weapon3, loadout.weapon3SkinIndex ) ) + weapon3AppearanceImage = GetItemImageFromWeaponRefAndPersistenceValue( loadout.weapon3, loadout.weapon3SkinIndex, "weapon3SkinIndex" ) RuiSetImage( Hud_GetRui( Hud_GetChild( loadoutPanel, "ButtonPilotCamo" ) ), "camoImage", pilotAppearanceImage ) RuiSetImage( Hud_GetRui( Hud_GetChild( loadoutPanel, "ButtonPrimarySkin" ) ), "camoImage", primaryAppearanceImage ) @@ -282,3 +282,19 @@ void function UpdatePilotLoadoutPanelBinds( var loadoutPanel ) //SetLabelRuiText( Hud_GetChild( loadoutPanel, "TacticalBind" ), Localize( "%offhand1%" ) ) //SetLabelRuiText( Hud_GetChild( loadoutPanel, "OrdnanceBind" ), Localize( "%offhand0%" ) ) } + +asset function GetItemImageFromWeaponRefAndPersistenceValue(string weaponRef, int persistenceValue, string loadoutProperty) +{ + string skinRef = GetSkinRefFromWeaponRefAndPersistenceValue( weaponRef, persistenceValue ) + if (!IsRefValid(skinRef)) + { + if (uiGlobal.editingLoadoutIndex != -1) + { + printt( "Resetting invalid " + loadoutProperty + " for weapon " + weaponRef ) + SetCachedLoadoutValue(GetUIPlayer(), "pilot", uiGlobal.editingLoadoutIndex, loadoutProperty, "0") + } + return $"rui/menu/common/appearance_button_swatch" + } + + return GetItemImage( skinRef ) +} From 2bb9216939a8bfd9fcd300893cb0626890a18a44 Mon Sep 17 00:00:00 2001 From: William Miller Date: Thu, 12 Oct 2023 18:54:27 -0300 Subject: [PATCH 13/25] Expose extra optional arg in `UpdatePlayerStat` function (#742) Exposes the previously hidden string argument in the `UpdatePlayerStat` function, that is needed to track some things more easily when hooking stats. --- Northstar.CustomServers/mod/scripts/vscripts/mp/_stats.nut | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/_stats.nut b/Northstar.CustomServers/mod/scripts/vscripts/mp/_stats.nut index 010184ff1..208e6da12 100644 --- a/Northstar.CustomServers/mod/scripts/vscripts/mp/_stats.nut +++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/_stats.nut @@ -136,12 +136,12 @@ float function PlayerStat_GetCurrentFloat( entity player, string statCategory, s return 0 } -void function UpdatePlayerStat( entity player, string statCategory, string subStat, int count = 1 ) +void function UpdatePlayerStat( entity player, string statCategory, string subStat, int count = 1, string statAlias = "" ) { if ( !IsValid( player ) ) return - Stats_IncrementStat( player, statCategory, subStat, "", count.tofloat() ) + Stats_IncrementStat( player, statCategory, subStat, statAlias, count.tofloat() ) } void function IncrementPlayerDidPilotExecutionWhileCloaked( entity player ) From a7d40aac072c6725548c2ba6d6a9ab649191594f Mon Sep 17 00:00:00 2001 From: Jack <66967891+ASpoonPlaysGames@users.noreply.github.com> Date: Sat, 14 Oct 2023 21:41:01 +0100 Subject: [PATCH 14/25] Add workflow for adding PRs and Issues to the project board (#696) Automatically adds all opened issues and pull requests to the project board. --- .github/workflows/add-to-project.yml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 .github/workflows/add-to-project.yml diff --git a/.github/workflows/add-to-project.yml b/.github/workflows/add-to-project.yml new file mode 100644 index 000000000..3a1d1c9a5 --- /dev/null +++ b/.github/workflows/add-to-project.yml @@ -0,0 +1,19 @@ +name: add-to-project + +on: + issues: + types: + - opened + pull_request: + types: + - opened + +jobs: + add-to-project: + name: Add to project + runs-on: ubuntu-latest + steps: + - uses: actions/add-to-project@v0.5.0 + with: + project-url: "https://github.com/orgs/R2Northstar/projects/3" + github-token: "${{ secrets.ADD_TO_PROJECT_PAT }}" From 8dfc1b9a0749c35c9f53745400718188cf6fe6f6 Mon Sep 17 00:00:00 2001 From: GeckoEidechse Date: Sun, 15 Oct 2023 02:18:18 +0200 Subject: [PATCH 15/25] Only run `add-to-project` action on issues PRs from forks are triggered from that fork which means that they don't have access to the necessary token --- .github/workflows/add-to-project.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/add-to-project.yml b/.github/workflows/add-to-project.yml index 3a1d1c9a5..556672e9f 100644 --- a/.github/workflows/add-to-project.yml +++ b/.github/workflows/add-to-project.yml @@ -4,9 +4,6 @@ on: issues: types: - opened - pull_request: - types: - - opened jobs: add-to-project: From 6df399f251bbaf8b43629ba023061eea67a37656 Mon Sep 17 00:00:00 2001 From: Jack <66967891+ASpoonPlaysGames@users.noreply.github.com> Date: Mon, 16 Oct 2023 13:53:02 +0100 Subject: [PATCH 16/25] Make dropships immune to Titan step damage (#737) Currently dropships take damage from titans stepping on them, this prevents that Co-authored-by: William Miller --- .../mod/scripts/vscripts/mp/_base_gametype_mp.gnut | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/_base_gametype_mp.gnut b/Northstar.CustomServers/mod/scripts/vscripts/mp/_base_gametype_mp.gnut index bab7eaede..c11ca36f8 100644 --- a/Northstar.CustomServers/mod/scripts/vscripts/mp/_base_gametype_mp.gnut +++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/_base_gametype_mp.gnut @@ -628,6 +628,10 @@ void function SetRecalculateRespawnAsTitanStartPointCallback( entity functionref bool function ShouldEntTakeDamage_SPMP( entity ent, var damageInfo ) { + // dropships are immune to being crushed + if ( ( IsDropship( ent ) || IsEvacDropship( ent ) ) && IsTitanCrushDamage( damageInfo ) ) + return false + return true } From 327e40edf85e9ad12b85256382123049d55fd07f Mon Sep 17 00:00:00 2001 From: Jack <66967891+ASpoonPlaysGames@users.noreply.github.com> Date: Tue, 17 Oct 2023 14:27:37 +0100 Subject: [PATCH 17/25] Award titan assist stats based on titan soul damage history (#746) Titans stores damage history in their Soul component, not the NPC itself, probably due to how game handles pilot/auto-titan interaction with the Titan entities. This means that we weren't awarding assist stats properly for titan assists --- Northstar.CustomServers/mod/scripts/vscripts/mp/_stats.nut | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/_stats.nut b/Northstar.CustomServers/mod/scripts/vscripts/mp/_stats.nut index 208e6da12..dbfcea61b 100644 --- a/Northstar.CustomServers/mod/scripts/vscripts/mp/_stats.nut +++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/_stats.nut @@ -571,9 +571,11 @@ void function HandleKillStats( entity victim, entity attacker, var damageInfo ) // assistsTotal ( weapon_kill_stats ) // note: eww table alreadyAssisted - foreach( DamageHistoryStruct attackerInfo in victim.e.recentDamageHistory ) + // titans store their recentDamageHistory in the soul + entity assistVictim = ( victim.IsTitan() && IsValid( victim.GetTitanSoul() ) ) ? victim.GetTitanSoul() : victim + foreach( DamageHistoryStruct attackerInfo in assistVictim.e.recentDamageHistory ) { - if ( !IsValid( attackerInfo.attacker ) || !attackerInfo.attacker.IsPlayer() || attackerInfo.attacker == victim ) + if ( !IsValid( attackerInfo.attacker ) || !attackerInfo.attacker.IsPlayer() || attackerInfo.attacker == assistVictim ) continue bool exists = attackerInfo.attacker.GetEncodedEHandle() in alreadyAssisted ? true : false From bc4e4263e714f9b1eff58f2c39bb714a3564b2e6 Mon Sep 17 00:00:00 2001 From: GalacticMoblin <100473309+GalacticMoblin@users.noreply.github.com> Date: Tue, 17 Oct 2023 14:36:46 +0100 Subject: [PATCH 18/25] Fix a crash related to Arc Cannon (#681) Fixes an issue where dying while the Arc Cannon beam is hurting someone would cause an error. Co-authored-by: Dinorush <62536724+Dinorush@users.noreply.github.com> --- .../scripts/vscripts/weapons/_arc_cannon.nut | 62 +++++++------------ 1 file changed, 22 insertions(+), 40 deletions(-) diff --git a/Northstar.Custom/mod/scripts/vscripts/weapons/_arc_cannon.nut b/Northstar.Custom/mod/scripts/vscripts/weapons/_arc_cannon.nut index 011389670..defb1a56f 100644 --- a/Northstar.Custom/mod/scripts/vscripts/weapons/_arc_cannon.nut +++ b/Northstar.Custom/mod/scripts/vscripts/weapons/_arc_cannon.nut @@ -536,12 +536,6 @@ function ZapTarget( zapInfo, target, beamStartPos, beamEndPos, chainNum = 1 ) thread CreateArcCannonBeam( zapInfo.weapon, target, beamStartPos, beamEndPos, zapInfo.player, ARC_CANNON_BEAM_LIFETIME, zapInfo.radius, boltWidth, 5, true, firstBeam ) #if SERVER - local isMissile = ( target.GetClassName() == "rpg_missile" ) - if ( !isMissile ) - wait ARC_CANNON_FORK_DELAY - else - wait 0.05 - local deathPackage = damageTypes.arcCannon float damageAmount @@ -569,40 +563,20 @@ function ZapTarget( zapInfo, target, beamStartPos, beamEndPos, chainNum = 1 ) bool hasFastPacitor = false bool noArcing = false - if ( IsValid( zapInfo.weapon ) ) - { - entity weap = expect entity( zapInfo.weapon ) - hasFastPacitor = weap.GetWeaponInfoFileKeyField( "push_apart" ) != null && weap.GetWeaponInfoFileKeyField( "push_apart" ) == 1 - noArcing = weap.GetWeaponInfoFileKeyField( "no_arcing" ) != null && weap.GetWeaponInfoFileKeyField( "no_arcing" ) == 1 - } + entity weapon = expect entity( zapInfo.weapon ) + hasFastPacitor = weapon.GetWeaponInfoFileKeyField( "push_apart" ) != null && weapon.GetWeaponInfoFileKeyField( "push_apart" ) == 1 + noArcing = weapon.GetWeaponInfoFileKeyField( "no_arcing" ) != null && weapon.GetWeaponInfoFileKeyField( "no_arcing" ) == 1 + float critScale = weapon.GetWeaponSettingFloat( eWeaponVar.critical_hit_damage_scale ) if ( target.GetArmorType() == ARMOR_TYPE_HEAVY ) { - if ( IsValid( zapInfo.weapon ) ) - { - entity weapon = expect entity( zapInfo.weapon ) - damageMin = weapon.GetWeaponSettingInt( damageFarValueTitanArmor ) - damageMax = weapon.GetWeaponSettingInt( damageNearValueTitanArmor ) - } - else - { - damageMin = 100 - damageMax = zapInfo.player.IsNPC() ? 1200 : 800 - } + damageMin = weapon.GetWeaponSettingInt( damageFarValueTitanArmor ) + damageMax = weapon.GetWeaponSettingInt( damageNearValueTitanArmor ) } else { - if ( IsValid( zapInfo.weapon ) ) - { - entity weapon = expect entity( zapInfo.weapon ) - damageMin = weapon.GetWeaponSettingInt( damageFarValue ) - damageMax = weapon.GetWeaponSettingInt( damageNearValue ) - } - else - { - damageMin = 120 - damageMax = zapInfo.player.IsNPC() ? 140 : 275 - } + damageMin = weapon.GetWeaponSettingInt( damageFarValue ) + damageMax = weapon.GetWeaponSettingInt( damageNearValue ) if ( target.IsNPC() ) { @@ -612,11 +586,10 @@ function ZapTarget( zapInfo, target, beamStartPos, beamEndPos, chainNum = 1 ) } - local chargeRatio = GetArcCannonChargeFraction( zapInfo.weapon ) - if ( IsValid( zapInfo.weapon ) && !zapInfo.weapon.GetWeaponSettingBool( eWeaponVar.charge_require_input ) ) + local chargeRatio = GetArcCannonChargeFraction( weapon ) + if ( !weapon.GetWeaponSettingBool( eWeaponVar.charge_require_input ) ) { // use distance for damage if the weapon auto-fires - entity weapon = expect entity( zapInfo.weapon ) float nearDist = weapon.GetWeaponSettingFloat( damageNearDistance ) float farDist = weapon.GetWeaponSettingFloat( damageFarDistance ) @@ -629,10 +602,19 @@ function ZapTarget( zapInfo, target, beamStartPos, beamEndPos, chainNum = 1 ) damageAmount = GraphCapped( zapInfo.chargeFrac, 0, chargeRatio, damageMin, damageMax ) } local damageFalloff = ARC_CANNON_DAMAGE_FALLOFF_SCALER - if ( IsValid( zapInfo.weapon ) && zapInfo.weapon.HasMod( "splitter" ) ) + if ( weapon.HasMod( "splitter" ) ) damageFalloff = SPLITTER_DAMAGE_FALLOFF_SCALER damageAmount *= pow( damageFalloff, chainNum - 1 ) + local isMissile = ( target.GetClassName() == "rpg_missile" ) + if ( !isMissile ) + wait ARC_CANNON_FORK_DELAY + else + wait 0.05 + + if ( !IsValid( target ) || !IsValid( zapInfo.player ) ) + return + local dmgSourceID = zapInfo.dmgSourceID // Update Later - This shouldn't be done here, this is not where we determine if damage actually happened to the target @@ -660,13 +642,13 @@ function ZapTarget( zapInfo, target, beamStartPos, beamEndPos, chainNum = 1 ) // Do 3rd person effect on the body asset effect string tag - target.TakeDamage( damageAmount, zapInfo.player, zapInfo.player, { origin = beamEndPos, force = Vector(0,0,0), scriptType = deathPackage, weapon = zapInfo.weapon, damageSourceId = dmgSourceID,criticalHitScale = zapInfo.weapon.GetWeaponSettingFloat( eWeaponVar.critical_hit_damage_scale ) } ) + target.TakeDamage( damageAmount, zapInfo.player, zapInfo.player, { origin = beamEndPos, force = Vector(0,0,0), scriptType = deathPackage, weapon = zapInfo.weapon, damageSourceId = dmgSourceID,criticalHitScale = critScale } ) //vector dir = Normalize( beamEndPos - beamStartPos ) //vector velocity = dir * 600 //PushPlayerAway( target, velocity ) //PushPlayerAway( expect entity( zapInfo.player ), -velocity ) - if ( IsValid( zapInfo.weapon ) && hasFastPacitor ) + if ( IsValid( weapon ) && hasFastPacitor ) { if ( IsAlive( target ) && IsAlive( expect entity( zapInfo.player ) ) && target.IsTitan() ) { From aa79ad4b924d838904169b4e251c27c5f09557db Mon Sep 17 00:00:00 2001 From: William Miller Date: Tue, 17 Oct 2023 21:41:01 -0300 Subject: [PATCH 19/25] Fix Titan Assist not tracking properly (#744) Titan Assist medals aren't given to players who assisted damage when someone kills a titan, that is due the fact that Titans stores damage history in their Soul component, not the NPC itself. --- .../mod/scripts/vscripts/mp/_score.nut | 25 +++++++++++-------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/_score.nut b/Northstar.CustomServers/mod/scripts/vscripts/mp/_score.nut index 0b55e9ffd..df7577aa0 100644 --- a/Northstar.CustomServers/mod/scripts/vscripts/mp/_score.nut +++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/_score.nut @@ -202,18 +202,23 @@ void function ScoreEvent_TitanKilled( entity victim, entity attacker, var damage AddPlayerScore( attacker, "KillTitan" ) } - table alreadyAssisted - foreach( DamageHistoryStruct attackerInfo in victim.e.recentDamageHistory ) + entity soul = victim.GetTitanSoul() + if ( IsValid( soul ) ) { - if ( !IsValid( attackerInfo.attacker ) || !attackerInfo.attacker.IsPlayer() || attackerInfo.attacker == victim ) - continue - - bool exists = attackerInfo.attacker.GetEncodedEHandle() in alreadyAssisted ? true : false - if( attackerInfo.attacker != attacker && !exists ) + table alreadyAssisted + + foreach( DamageHistoryStruct attackerInfo in soul.e.recentDamageHistory ) { - alreadyAssisted[attackerInfo.attacker.GetEncodedEHandle()] <- true - AddPlayerScore(attackerInfo.attacker, "TitanAssist" ) - Remote_CallFunction_NonReplay( attackerInfo.attacker, "ServerCallback_SetAssistInformation", attackerInfo.damageSourceId, attacker.GetEncodedEHandle(), victim.GetEncodedEHandle(), attackerInfo.time ) + if ( !IsValid( attackerInfo.attacker ) || !attackerInfo.attacker.IsPlayer() || attackerInfo.attacker == soul ) + continue + + bool exists = attackerInfo.attacker.GetEncodedEHandle() in alreadyAssisted ? true : false + if( attackerInfo.attacker != attacker && !exists ) + { + alreadyAssisted[attackerInfo.attacker.GetEncodedEHandle()] <- true + AddPlayerScore(attackerInfo.attacker, "TitanAssist" ) + Remote_CallFunction_NonReplay( attackerInfo.attacker, "ServerCallback_SetAssistInformation", attackerInfo.damageSourceId, attacker.GetEncodedEHandle(), soul.GetEncodedEHandle(), attackerInfo.time ) + } } } From d84d875347b54e87dfada23f516f89cf507be610 Mon Sep 17 00:00:00 2001 From: Jack <66967891+ASpoonPlaysGames@users.noreply.github.com> Date: Wed, 18 Oct 2023 19:34:47 +0100 Subject: [PATCH 20/25] Stop logging invalid map/mode exception in progression (#750) Some game modes like Gun Game or Infection are not considered valid yet, causing the warning message to be spammed in the logs. Necessary work should be done to add the modes to the list of valid modes. Until we will just comment out the print statement in order to prevent log spam. Co-authored-by: GeckoEidechse <40122905+GeckoEidechse@users.noreply.github.com> --- Northstar.CustomServers/mod/scripts/vscripts/mp/_stats.nut | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/_stats.nut b/Northstar.CustomServers/mod/scripts/vscripts/mp/_stats.nut index dbfcea61b..63841f7ac 100644 --- a/Northstar.CustomServers/mod/scripts/vscripts/mp/_stats.nut +++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/_stats.nut @@ -264,7 +264,7 @@ void function Stats_IncrementStat( entity player, string statCategory, string st // persistence string, we can't save the persistence so we have to just return if ( str != saveVar ) { - printt( ex ) + //printt( ex, str, GetMapName(), mode ) // Commented out due to spamming logs on invalid modes (e.g. Gun Game, Infection, ...) return } } From 640d3915c1a2c76ce4ff6d0c2cf7868c6d2e4f4f Mon Sep 17 00:00:00 2001 From: Jack <66967891+ASpoonPlaysGames@users.noreply.github.com> Date: Sat, 21 Oct 2023 17:39:21 +0100 Subject: [PATCH 21/25] Make add to project workflow work on PRs (#753) Fix the add to project workflow so that it works on PRs from forks, securely by running it in the context of the target. --- .github/workflows/add-to-project.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/add-to-project.yml b/.github/workflows/add-to-project.yml index 556672e9f..773a52b8b 100644 --- a/.github/workflows/add-to-project.yml +++ b/.github/workflows/add-to-project.yml @@ -4,6 +4,9 @@ on: issues: types: - opened + pull_request_target: + types: + - opened jobs: add-to-project: From 82f87121da416de0f6feab1fe2aa775c9c5b3088 Mon Sep 17 00:00:00 2001 From: Jack <66967891+ASpoonPlaysGames@users.noreply.github.com> Date: Sat, 28 Oct 2023 20:22:41 +0100 Subject: [PATCH 22/25] Change gun game score limit setting (#735) Gun game was never set up to properly use the playlistvars for setting guns, and relied on playlistvaroverrides to set the score limit, this caused the change to persist to other modes --- Northstar.Custom/keyvalues/playlists_v2.txt | 2 -- .../mod/scripts/vscripts/gamemodes/_gamemode_gg.gnut | 8 -------- 2 files changed, 10 deletions(-) diff --git a/Northstar.Custom/keyvalues/playlists_v2.txt b/Northstar.Custom/keyvalues/playlists_v2.txt index 21934b319..c22e2174d 100644 --- a/Northstar.Custom/keyvalues/playlists_v2.txt +++ b/Northstar.Custom/keyvalues/playlists_v2.txt @@ -47,8 +47,6 @@ playlists max_teams 12 classic_mp 1 - scorelimit 21 // temp until we have a way of dynamically setting non-default scorelimit in code - gamemode_score_hint #GAMEMODE_SCORE_HINT_FFA gamemode_bullet_001 #GAMEMODE_BULLET_FFA_001 gamemode_bullet_002 #GAMEMODE_BULLET_FFA_002 diff --git a/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_gg.gnut b/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_gg.gnut index 8f34541bf..ad46b42e2 100644 --- a/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_gg.gnut +++ b/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_gg.gnut @@ -18,14 +18,6 @@ void function GamemodeGG_Init() AddCallback_GameStateEnter( eGameState.WinnerDetermined, OnWinnerDetermined ) AddCallback_GGEarnMeterFull( OnGGEarnMeterFilled ) - - // set scorelimit if it's wrong, sort of a jank way to do it but best i've got rn - try - { - if ( GetCurrentPlaylistVarInt( "scorelimit", GetGunGameWeapons().len() ) != GetGunGameWeapons().len() ) - SetPlaylistVarOverride( "scorelimit", GetGunGameWeapons().len().tostring() ) - } - catch ( ex ) {} } void function OnPlayerDisconnected(entity player) From faff062f6cbdac84803ced8a7c6e69dd7731af57 Mon Sep 17 00:00:00 2001 From: Jack <66967891+ASpoonPlaysGames@users.noreply.github.com> Date: Fri, 3 Nov 2023 16:10:40 +0000 Subject: [PATCH 23/25] Don't mark items as new if progression is disabled (#752) Also doesn't show the challenge completion notifications in game as a nice side effect --- Northstar.CustomServers/mod/scripts/vscripts/_items.nut | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Northstar.CustomServers/mod/scripts/vscripts/_items.nut b/Northstar.CustomServers/mod/scripts/vscripts/_items.nut index a5c3e2709..a23a68b0c 100644 --- a/Northstar.CustomServers/mod/scripts/vscripts/_items.nut +++ b/Northstar.CustomServers/mod/scripts/vscripts/_items.nut @@ -10231,6 +10231,10 @@ void function StatUnlock_Unlocked( entity player, string itemRef, string parentR if ( IsItemNew( player, itemRef, parentRef ) ) return + // early out if the player has progression disabled + if ( !ProgressionEnabledForPlayer( player ) ) + return + int refGuid = file.itemRefToGuid[itemRef] int parentRefGuid = parentRef == "" ? 0 : file.itemRefToGuid[parentRef] From dfeaba7208deff89de67f32271c0d5c5a44746f1 Mon Sep 17 00:00:00 2001 From: William Miller Date: Fri, 3 Nov 2023 13:15:42 -0300 Subject: [PATCH 24/25] Fix wrong Item Type for Titan Camos (#728) Small fix which the wrong item type was being addressed to check for Titan Camos, allowing players to use any camo without fallback to default if they didn't own that item previously when enabling progression. --- .../mod/scripts/vscripts/sh_progression.nut | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Northstar.CustomServers/mod/scripts/vscripts/sh_progression.nut b/Northstar.CustomServers/mod/scripts/vscripts/sh_progression.nut index ceb5e837c..496e8b42d 100644 --- a/Northstar.CustomServers/mod/scripts/vscripts/sh_progression.nut +++ b/Northstar.CustomServers/mod/scripts/vscripts/sh_progression.nut @@ -268,7 +268,7 @@ void function ValidateEquippedItems( entity player ) // camoIndex if ( loadout.skinIndex == TITAN_SKIN_INDEX_CAMO ) { - array camoSkins = GetAllItemsOfType( eItemTypes.CAMO_SKIN ) + array camoSkins = GetAllItemsOfType( eItemTypes.CAMO_SKIN_TITAN ) if ( loadout.camoIndex >= camoSkins.len() || loadout.camoIndex < 0 ) { printt( " - INVALID TITAN CAMO/SKIN, RESETTING" ) @@ -363,7 +363,7 @@ void function ValidateEquippedItems( entity player ) // primeCamoIndex if ( loadout.primeSkinIndex == TITAN_SKIN_INDEX_CAMO ) { - array camoSkins = GetAllItemsOfType( eItemTypes.CAMO_SKIN ) + array camoSkins = GetAllItemsOfType( eItemTypes.CAMO_SKIN_TITAN ) if ( loadout.primeCamoIndex >= camoSkins.len() || loadout.primeCamoIndex < 0 ) { printt( " - INVALID TITAN CAMO/SKIN, RESETTING" ) From 54fae18d727aa84fb6eb45de4f9479aba3361158 Mon Sep 17 00:00:00 2001 From: William Miller Date: Fri, 3 Nov 2023 13:17:34 -0300 Subject: [PATCH 25/25] Fix wrong attacker receiving progression stat updates (#755) Fixes wrong attacker receiving stat updates --- Northstar.CustomServers/mod/scripts/vscripts/mp/_stats.nut | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/_stats.nut b/Northstar.CustomServers/mod/scripts/vscripts/mp/_stats.nut index 63841f7ac..bd64e4caa 100644 --- a/Northstar.CustomServers/mod/scripts/vscripts/mp/_stats.nut +++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/_stats.nut @@ -587,7 +587,7 @@ void function HandleKillStats( entity victim, entity attacker, var damageInfo ) string source = DamageSourceIDToString( attackerInfo.damageSourceId ) if ( IsValidStatItemString( source ) ) - Stats_IncrementStat( attacker, "weapon_kill_stats", "assistsTotal", source, 1.0 ) + Stats_IncrementStat( attackerInfo.attacker, "weapon_kill_stats", "assistsTotal", source, 1.0 ) } }